|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1983 Regents of the University of California. ! 3: * All rights reserved. The Berkeley software License Agreement ! 4: * specifies the terms and conditions for redistribution. ! 5: */ ! 6: ! 7: #ifndef lint ! 8: static char sccsid[] = "@(#)readmsg.c 2.9 (Berkeley) 6/5/86"; ! 9: #endif not lint ! 10: ! 11: #include "globals.h" ! 12: #include <protocols/timed.h> ! 13: ! 14: extern char *tsptype[]; ! 15: ! 16: /* ! 17: * LOOKAT checks if the message is of the requested type and comes from ! 18: * the right machine, returning 1 in case of affirmative answer ! 19: */ ! 20: ! 21: #define LOOKAT(msg, mtype, mfrom, netp, froms) \ ! 22: (((((mtype) == TSP_ANY) || ((mtype) == (msg).tsp_type)) && \ ! 23: (((mfrom) == NULL) || (strcmp((mfrom), (msg).tsp_name) == 0)) && \ ! 24: (((netp) == NULL) || \ ! 25: (((netp)->mask & (froms).sin_addr.s_addr) == (netp)->net))) \ ! 26: ? 1 : 0) ! 27: ! 28: #define MORETIME(rtime, rtout) \ ! 29: (((rtime).tv_sec > (rtout).tv_sec || \ ! 30: ((rtime).tv_sec == (rtout).tv_sec && \ ! 31: (rtime).tv_usec >= (rtout).tv_usec)) \ ! 32: ? 0 : 1) ! 33: ! 34: struct timeval rtime, rwait, rtout; ! 35: struct tsp msgin; ! 36: static struct tsplist { ! 37: struct tsp info; ! 38: struct sockaddr_in addr; ! 39: struct tsplist *p; ! 40: } msgslist; ! 41: struct sockaddr_in from; ! 42: struct netinfo *fromnet; ! 43: ! 44: /* ! 45: * `readmsg' returns message `type' sent by `machfrom' if it finds it ! 46: * either in the receive queue, or in a linked list of previously received ! 47: * messages that it maintains. ! 48: * Otherwise it waits to see if the appropriate message arrives within ! 49: * `intvl' seconds. If not, it returns NULL. ! 50: */ ! 51: ! 52: struct tsp * ! 53: readmsg(type, machfrom, intvl, netfrom) ! 54: ! 55: int type; ! 56: char *machfrom; ! 57: struct timeval *intvl; ! 58: struct netinfo *netfrom; ! 59: { ! 60: int length; ! 61: fd_set ready; ! 62: static struct tsplist *head = &msgslist; ! 63: static struct tsplist *tail = &msgslist; ! 64: struct tsplist *prev; ! 65: register struct netinfo *ntp; ! 66: register struct tsplist *ptr; ! 67: ! 68: if (trace) { ! 69: fprintf(fd, "looking for %s from %s\n", ! 70: tsptype[type], machfrom == NULL ? "ANY" : machfrom); ! 71: ptr = head->p; ! 72: fprintf(fd, "msgqueue:\n"); ! 73: while (ptr != NULL) { ! 74: fprintf(fd, "\t"); ! 75: print(&ptr->info, &ptr->addr); ! 76: ptr = ptr->p; ! 77: } ! 78: } ! 79: ! 80: ptr = head->p; ! 81: prev = head; ! 82: ! 83: /* ! 84: * Look for the requested message scanning through the ! 85: * linked list. If found, return it and free the space ! 86: */ ! 87: ! 88: while (ptr != NULL) { ! 89: if (LOOKAT(ptr->info, type, machfrom, netfrom, ptr->addr)) { ! 90: msgin = ptr->info; ! 91: from = ptr->addr; ! 92: prev->p = ptr->p; ! 93: if (ptr == tail) ! 94: tail = prev; ! 95: free((char *)ptr); ! 96: fromnet = NULL; ! 97: if (netfrom == NULL) ! 98: for (ntp = nettab; ntp != NULL; ntp = ntp->next) { ! 99: if ((ntp->mask & from.sin_addr.s_addr) == ! 100: ntp->net) { ! 101: fromnet = ntp; ! 102: break; ! 103: } ! 104: } ! 105: else ! 106: fromnet = netfrom; ! 107: if (trace) { ! 108: fprintf(fd, "readmsg: "); ! 109: print(&msgin, &from); ! 110: } ! 111: return(&msgin); ! 112: } else { ! 113: prev = ptr; ! 114: ptr = ptr->p; ! 115: } ! 116: } ! 117: ! 118: /* ! 119: * If the message was not in the linked list, it may still be ! 120: * coming from the network. Set the timer and wait ! 121: * on a select to read the next incoming message: if it is the ! 122: * right one, return it, otherwise insert it in the linked list. ! 123: */ ! 124: ! 125: (void)gettimeofday(&rtime, (struct timezone *)0); ! 126: rtout.tv_sec = rtime.tv_sec + intvl->tv_sec; ! 127: rtout.tv_usec = rtime.tv_usec + intvl->tv_usec; ! 128: if (rtout.tv_usec > 1000000) { ! 129: rtout.tv_usec -= 1000000; ! 130: rtout.tv_sec++; ! 131: } ! 132: ! 133: FD_ZERO(&ready); ! 134: for (; MORETIME(rtime, rtout); ! 135: (void)gettimeofday(&rtime, (struct timezone *)0)) { ! 136: rwait.tv_sec = rtout.tv_sec - rtime.tv_sec; ! 137: rwait.tv_usec = rtout.tv_usec - rtime.tv_usec; ! 138: if (rwait.tv_usec < 0) { ! 139: rwait.tv_usec += 1000000; ! 140: rwait.tv_sec--; ! 141: } ! 142: if (rwait.tv_sec < 0) ! 143: rwait.tv_sec = rwait.tv_usec = 0; ! 144: ! 145: if (trace) { ! 146: fprintf(fd, "readmsg: wait: (%d %d)\n", ! 147: rwait.tv_sec, rwait.tv_usec); ! 148: } ! 149: FD_SET(sock, &ready); ! 150: if (select(FD_SETSIZE, &ready, (fd_set *)0, (fd_set *)0, ! 151: &rwait)) { ! 152: length = sizeof(struct sockaddr_in); ! 153: if (recvfrom(sock, (char *)&msgin, sizeof(struct tsp), ! 154: 0, &from, &length) < 0) { ! 155: syslog(LOG_ERR, "receiving datagram packet: %m"); ! 156: exit(1); ! 157: } ! 158: ! 159: bytehostorder(&msgin); ! 160: ! 161: if (msgin.tsp_vers > TSPVERSION) { ! 162: if (trace) { ! 163: fprintf(fd, "readmsg: version mismatch\n"); ! 164: /* should do a dump of the packet, but... */ ! 165: } ! 166: continue; ! 167: } ! 168: ! 169: fromnet = NULL; ! 170: for (ntp = nettab; ntp != NULL; ntp = ntp->next) ! 171: if ((ntp->mask & from.sin_addr.s_addr) == ! 172: ntp->net) { ! 173: fromnet = ntp; ! 174: break; ! 175: } ! 176: ! 177: /* ! 178: * drop packets from nets we are ignoring permanently ! 179: */ ! 180: if (fromnet == NULL) { ! 181: /* ! 182: * The following messages may originate on ! 183: * this host with an ignored network address ! 184: */ ! 185: if (msgin.tsp_type != TSP_TRACEON && ! 186: msgin.tsp_type != TSP_SETDATE && ! 187: msgin.tsp_type != TSP_MSITE && ! 188: #ifdef TESTING ! 189: msgin.tsp_type != TSP_TEST && ! 190: #endif ! 191: msgin.tsp_type != TSP_TRACEOFF) { ! 192: if (trace) { ! 193: fprintf(fd, "readmsg: discarded: "); ! 194: print(&msgin, &from); ! 195: } ! 196: continue; ! 197: } ! 198: } ! 199: ! 200: /* ! 201: * Throw away messages coming from this machine, unless ! 202: * they are of some particular type. ! 203: * This gets rid of broadcast messages and reduces ! 204: * master processing time. ! 205: */ ! 206: if ( !(strcmp(msgin.tsp_name, hostname) != 0 || ! 207: msgin.tsp_type == TSP_SETDATE || ! 208: #ifdef TESTING ! 209: msgin.tsp_type == TSP_TEST || ! 210: #endif ! 211: msgin.tsp_type == TSP_MSITE || ! 212: (msgin.tsp_type == TSP_LOOP && ! 213: msgin.tsp_hopcnt != 10) || ! 214: msgin.tsp_type == TSP_TRACEON || ! 215: msgin.tsp_type == TSP_TRACEOFF)) { ! 216: if (trace) { ! 217: fprintf(fd, "readmsg: discarded: "); ! 218: print(&msgin, &from); ! 219: } ! 220: continue; ! 221: } ! 222: ! 223: /* ! 224: * Send acknowledgements here; this is faster and avoids ! 225: * deadlocks that would occur if acks were sent from a ! 226: * higher level routine. Different acknowledgements are ! 227: * necessary, depending on status. ! 228: */ ! 229: if (fromnet->status == MASTER) ! 230: masterack(); ! 231: else if (fromnet->status == SLAVE) ! 232: slaveack(); ! 233: else ! 234: ignoreack(); ! 235: ! 236: if (LOOKAT(msgin, type, machfrom, netfrom, from)) { ! 237: if (trace) { ! 238: fprintf(fd, "readmsg: "); ! 239: print(&msgin, &from); ! 240: } ! 241: return(&msgin); ! 242: } else { ! 243: tail->p = (struct tsplist *) ! 244: malloc(sizeof(struct tsplist)); ! 245: tail = tail->p; ! 246: tail->p = NULL; ! 247: tail->info = msgin; ! 248: tail->addr = from; ! 249: } ! 250: } else { ! 251: break; ! 252: } ! 253: } ! 254: return((struct tsp *)NULL); ! 255: } ! 256: ! 257: /* ! 258: * `slaveack' sends the necessary acknowledgements: ! 259: * only the type ACK is to be sent by a slave ! 260: */ ! 261: ! 262: slaveack() ! 263: { ! 264: int length; ! 265: struct tsp resp; ! 266: ! 267: length = sizeof(struct sockaddr_in); ! 268: switch(msgin.tsp_type) { ! 269: ! 270: case TSP_ADJTIME: ! 271: case TSP_SETTIME: ! 272: case TSP_ACCEPT: ! 273: case TSP_REFUSE: ! 274: case TSP_TRACEON: ! 275: case TSP_TRACEOFF: ! 276: case TSP_QUIT: ! 277: resp = msgin; ! 278: resp.tsp_type = TSP_ACK; ! 279: resp.tsp_vers = TSPVERSION; ! 280: (void)strcpy(resp.tsp_name, hostname); ! 281: if (trace) { ! 282: fprintf(fd, "Slaveack: "); ! 283: print(&resp, &from); ! 284: } ! 285: bytenetorder(&resp); /* this is not really necessary here */ ! 286: if (sendto(sock, (char *)&resp, sizeof(struct tsp), 0, ! 287: &from, length) < 0) { ! 288: syslog(LOG_ERR, "sendto: %m"); ! 289: exit(1); ! 290: } ! 291: break; ! 292: default: ! 293: break; ! 294: } ! 295: } ! 296: ! 297: /* ! 298: * Certain packets may arrive from this machine on ignored networks. ! 299: * These packets should be acknowledged. ! 300: */ ! 301: ! 302: ignoreack() ! 303: { ! 304: int length; ! 305: struct tsp resp; ! 306: ! 307: length = sizeof(struct sockaddr_in); ! 308: switch(msgin.tsp_type) { ! 309: ! 310: case TSP_TRACEON: ! 311: case TSP_TRACEOFF: ! 312: resp = msgin; ! 313: resp.tsp_type = TSP_ACK; ! 314: resp.tsp_vers = TSPVERSION; ! 315: (void)strcpy(resp.tsp_name, hostname); ! 316: if (trace) { ! 317: fprintf(fd, "Ignoreack: "); ! 318: print(&resp, &from); ! 319: } ! 320: bytenetorder(&resp); /* this is not really necessary here */ ! 321: if (sendto(sock, (char *)&resp, sizeof(struct tsp), 0, ! 322: &from, length) < 0) { ! 323: syslog(LOG_ERR, "sendto: %m"); ! 324: exit(1); ! 325: } ! 326: break; ! 327: default: ! 328: break; ! 329: } ! 330: } ! 331: ! 332: /* ! 333: * `masterack' sends the necessary acknowledgments ! 334: * to the messages received by a master ! 335: */ ! 336: ! 337: masterack() ! 338: { ! 339: int length; ! 340: struct tsp resp; ! 341: ! 342: length = sizeof(struct sockaddr_in); ! 343: ! 344: resp = msgin; ! 345: resp.tsp_vers = TSPVERSION; ! 346: (void)strcpy(resp.tsp_name, hostname); ! 347: ! 348: switch(msgin.tsp_type) { ! 349: ! 350: case TSP_QUIT: ! 351: case TSP_TRACEON: ! 352: case TSP_TRACEOFF: ! 353: case TSP_MSITE: ! 354: case TSP_MSITEREQ: ! 355: resp.tsp_type = TSP_ACK; ! 356: bytenetorder(&resp); ! 357: if (trace) { ! 358: fprintf(fd, "Masterack: "); ! 359: print(&resp, &from); ! 360: } ! 361: if (sendto(sock, (char *)&resp, sizeof(struct tsp), 0, ! 362: &from, length) < 0) { ! 363: syslog(LOG_ERR, "sendto: %m"); ! 364: exit(1); ! 365: } ! 366: break; ! 367: case TSP_RESOLVE: ! 368: case TSP_MASTERREQ: ! 369: resp.tsp_type = TSP_MASTERACK; ! 370: bytenetorder(&resp); ! 371: if (trace) { ! 372: fprintf(fd, "Masterack: "); ! 373: print(&resp, &from); ! 374: } ! 375: if (sendto(sock, (char *)&resp, sizeof(struct tsp), 0, ! 376: &from, length) < 0) { ! 377: syslog(LOG_ERR, "sendto: %m"); ! 378: exit(1); ! 379: } ! 380: break; ! 381: case TSP_SETDATEREQ: ! 382: resp.tsp_type = TSP_DATEACK; ! 383: bytenetorder(&resp); ! 384: if (trace) { ! 385: fprintf(fd, "Masterack: "); ! 386: print(&resp, &from); ! 387: } ! 388: if (sendto(sock, (char *)&resp, sizeof(struct tsp), 0, ! 389: &from, length) < 0) { ! 390: syslog(LOG_ERR, "sendto: %m"); ! 391: exit(1); ! 392: } ! 393: break; ! 394: default: ! 395: break; ! 396: } ! 397: } ! 398: ! 399: /* ! 400: * Print a TSP message ! 401: */ ! 402: print(msg, addr) ! 403: struct tsp *msg; ! 404: struct sockaddr_in *addr; ! 405: { ! 406: switch (msg->tsp_type) { ! 407: ! 408: case TSP_LOOP: ! 409: fprintf(fd, "%s %d %d (#%d) %s %s\n", ! 410: tsptype[msg->tsp_type], ! 411: msg->tsp_vers, ! 412: msg->tsp_seq, ! 413: msg->tsp_hopcnt, ! 414: msg->tsp_name, ! 415: inet_ntoa(addr->sin_addr)); ! 416: break; ! 417: ! 418: case TSP_SETTIME: ! 419: case TSP_ADJTIME: ! 420: case TSP_SETDATE: ! 421: case TSP_SETDATEREQ: ! 422: fprintf(fd, "%s %d %d (%d, %d) %s %s\n", ! 423: tsptype[msg->tsp_type], ! 424: msg->tsp_vers, ! 425: msg->tsp_seq, ! 426: msg->tsp_time.tv_sec, ! 427: msg->tsp_time.tv_usec, ! 428: msg->tsp_name, ! 429: inet_ntoa(addr->sin_addr)); ! 430: break; ! 431: ! 432: default: ! 433: fprintf(fd, "%s %d %d %s %s\n", ! 434: tsptype[msg->tsp_type], ! 435: msg->tsp_vers, ! 436: msg->tsp_seq, ! 437: msg->tsp_name, ! 438: inet_ntoa(addr->sin_addr)); ! 439: break; ! 440: } ! 441: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.