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