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: }

Defined functions

ignoreack defined in line 302; used 1 times
masterack defined in line 337; used 1 times
slaveack defined in line 262; used 1 times

Defined variables

from defined in line 41; used 69 times
fromnet defined in line 42; used 45 times
msgin defined in line 35; used 31 times
msgslist defined in line 40; used 2 times
rtime defined in line 34; used 11 times
rtout defined in line 34; used 12 times
rwait defined in line 34; used 11 times
sccsid defined in line 8; never used

Defined struct's

tsplist defined in line 36; used 14 times

Defined macros

LOOKAT defined in line 21; used 2 times
MORETIME defined in line 28; used 1 times
Last modified: 1988-12-25
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 4573
Valid CSS Valid XHTML 1.0 Strict