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 %u (#%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 %u (%ld, %ld) %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 %u %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: }