1: /*
   2:  * Copyright (c) 1985 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[] = "@(#)slave.c	2.16 (Berkeley) 6/5/86";
   9: #endif not lint
  10: 
  11: #include "globals.h"
  12: #include <protocols/timed.h>
  13: #include <setjmp.h>
  14: 
  15: extern jmp_buf jmpenv;
  16: 
  17: extern u_short sequence;
  18: 
  19: slave()
  20: {
  21:     int length;
  22:     int senddateack;
  23:     long electiontime, refusetime, looktime;
  24:     u_short seq;
  25:     char candidate[MAXHOSTNAMELEN];
  26:     struct tsp *msg, to, *readmsg();
  27:     struct sockaddr_in saveaddr, msaveaddr;
  28:     struct timeval wait;
  29:     struct timeval time, otime;
  30:     struct tsp *answer, *acksend();
  31:     int timeout();
  32:     char *date();
  33:     long casual();
  34:     int bytenetorder();
  35:     char olddate[32];
  36:     struct sockaddr_in server;
  37:     register struct netinfo *ntp;
  38:     int ind;
  39:     struct tsp resp;
  40:     extern int Mflag;
  41:     extern int justquit;
  42: #ifdef MEASURE
  43:     extern FILE *fp;
  44: #endif
  45:     if (slavenet) {
  46:         resp.tsp_type = TSP_SLAVEUP;
  47:         resp.tsp_vers = TSPVERSION;
  48:         (void)strcpy(resp.tsp_name, hostname);
  49:         bytenetorder(&resp);
  50:         if (sendto(sock, (char *)&resp, sizeof(struct tsp), 0,
  51:             &slavenet->dest_addr, sizeof(struct sockaddr_in)) < 0) {
  52:             syslog(LOG_ERR, "sendto: %m");
  53:             exit(1);
  54:         }
  55:     }
  56: 
  57:     if (status & MASTER) {
  58: #ifdef MEASURE
  59:         if (fp == NULL) {
  60:             fp = fopen("/usr/adm/timed.masterlog", "w");
  61:             setlinebuf(fp);
  62:         }
  63: #endif
  64:         syslog(LOG_INFO, "THIS MACHINE IS A SUBMASTER");
  65:         if (trace) {
  66:             fprintf(fd, "THIS MACHINE IS A SUBMASTER\n");
  67:         }
  68:         for (ntp = nettab; ntp != NULL; ntp = ntp->next)
  69:             if (ntp->status == MASTER)
  70:                 masterup(ntp);
  71: 
  72:     } else {
  73:         syslog(LOG_INFO, "THIS MACHINE IS A SLAVE");
  74:         if (trace) {
  75:             fprintf(fd, "THIS MACHINE IS A SLAVE\n");
  76:         }
  77:     }
  78: 
  79:     seq = 0;
  80:     senddateack = OFF;
  81:     refusetime = 0;
  82: 
  83:     (void)gettimeofday(&time, (struct timezone *)0);
  84:     electiontime = time.tv_sec + delay2;
  85:     if (Mflag)
  86:         if (justquit)
  87:             looktime = time.tv_sec + delay2;
  88:         else
  89:             looktime = 1;
  90:     else
  91:         looktime = 0;
  92: 
  93: loop:
  94:     length = sizeof(struct sockaddr_in);
  95:     (void)gettimeofday(&time, (struct timezone *)0);
  96:     if (time.tv_sec > electiontime) {
  97:         if (trace)
  98:             fprintf(fd, "election timer expired\n");
  99:         longjmp(jmpenv, 1);
 100:     }
 101:     if (looktime && time.tv_sec > looktime) {
 102:         if (trace)
 103:             fprintf(fd, "Looking for nets to master and loops\n");
 104: 
 105:         if (nignorednets > 0) {
 106:             for (ntp = nettab; ntp != NULL; ntp = ntp->next) {
 107:                 if (ntp->status == IGNORE) {
 108:                     lookformaster(ntp);
 109:                     if (ntp->status == MASTER)
 110:                         masterup(ntp);
 111:                     else
 112:                         ntp->status = IGNORE;
 113:                 }
 114:             }
 115:             setstatus();
 116: #ifdef MEASURE
 117:             /*
 118: 			 * Check to see if we just became master
 119: 			 * (file not open)
 120: 			 */
 121:             if (fp == NULL) {
 122:                 fp = fopen("/usr/adm/timed.masterlog", "w");
 123:                 setlinebuf(fp);
 124:             }
 125: #endif
 126:         }
 127: 
 128:         for (ntp = nettab; ntp != NULL; ntp = ntp->next) {
 129:             if (ntp->status == MASTER) {
 130:             to.tsp_type = TSP_LOOP;
 131:             to.tsp_vers = TSPVERSION;
 132:             to.tsp_seq = sequence++;
 133:             to.tsp_hopcnt = 10;
 134:             (void)strcpy(to.tsp_name, hostname);
 135:             bytenetorder(&to);
 136:             if (sendto(sock, (char *)&to, sizeof(struct tsp), 0,
 137:                 &ntp->dest_addr, sizeof(struct sockaddr_in)) < 0) {
 138:                 syslog(LOG_ERR, "sendto: %m");
 139:                 exit(1);
 140:             }
 141:             }
 142:         }
 143:         (void)gettimeofday(&time, (struct timezone *)0);
 144:         looktime = time.tv_sec + delay2;
 145:     }
 146:     wait.tv_sec = electiontime - time.tv_sec + 10;
 147:     wait.tv_usec = 0;
 148:     msg = readmsg(TSP_ANY, (char *)ANYADDR, &wait, (struct netinfo *)NULL);
 149:     if (msg != NULL) {
 150:         switch (msg->tsp_type) {
 151:         case TSP_SETDATE:
 152: #ifdef TESTING
 153:         case TSP_TEST:
 154: #endif
 155:         case TSP_MSITE:
 156:         case TSP_TRACEOFF:
 157:         case TSP_TRACEON:
 158:             break;
 159:         case TSP_MASTERUP:
 160:             if (fromnet == NULL) {
 161:                 if (trace) {
 162:                     fprintf(fd, "slave ignored: ");
 163:                     print(msg, &from);
 164:                 }
 165:                 goto loop;
 166:             }
 167:             break;
 168:         default:
 169:             if (fromnet == NULL || fromnet->status == IGNORE) {
 170:                 if (trace) {
 171:                     fprintf(fd, "slave ignored: ");
 172:                     print(msg, &from);
 173:                 }
 174:                 goto loop;
 175:             }
 176:             break;
 177:         }
 178: 
 179:         switch (msg->tsp_type) {
 180: 
 181:         case TSP_ADJTIME:
 182:             if (fromnet->status != SLAVE)
 183:                 break;
 184:             (void)gettimeofday(&time, (struct timezone *)0);
 185:             electiontime = time.tv_sec + delay2;
 186:             if (seq != msg->tsp_seq) {
 187:                 seq = msg->tsp_seq;
 188:                 if ((status & SUBMASTER) == SUBMASTER) {
 189:                     synch((msg->tsp_time.tv_sec * 1000) +
 190:                         (msg->tsp_time.tv_usec / 1000));
 191:                 } else {
 192:                     adjclock(&(msg->tsp_time));
 193:                 }
 194:             }
 195:             break;
 196:         case TSP_SETTIME:
 197:             if (fromnet->status != SLAVE)
 198:                 break;
 199:             if (seq == msg->tsp_seq)
 200:                 break;
 201: 
 202:             seq = msg->tsp_seq;
 203: 
 204:             (void)strcpy(olddate, date());
 205:             (void)gettimeofday(&otime, (struct timezone *)0);
 206:             (void)settimeofday(&msg->tsp_time,
 207:                 (struct timezone *)0);
 208:             syslog(LOG_NOTICE, "date changed by %s from: %s",
 209:                 msg->tsp_name, olddate);
 210:             logwtmp(otime, msg->tsp_time);
 211:             if ((status & SUBMASTER) == SUBMASTER)
 212:                 spreadtime();
 213:             (void)gettimeofday(&time, (struct timezone *)0);
 214:             electiontime = time.tv_sec + delay2;
 215: 
 216:             if (senddateack == ON) {
 217:                 senddateack = OFF;
 218:                 msg->tsp_type = TSP_DATEACK;
 219:                 (void)strcpy(msg->tsp_name, hostname);
 220:                 bytenetorder(msg);
 221:                 length = sizeof(struct sockaddr_in);
 222:                 if (sendto(sock, (char *)msg,
 223:                         sizeof(struct tsp), 0,
 224:                         &saveaddr, length) < 0) {
 225:                     syslog(LOG_ERR, "sendto: %m");
 226:                     exit(1);
 227:                 }
 228:             }
 229:             break;
 230:         case TSP_MASTERUP:
 231:             if (slavenet && fromnet != slavenet)
 232:                 break;
 233:             makeslave(fromnet);
 234:             setstatus();
 235:             msg->tsp_type = TSP_SLAVEUP;
 236:             msg->tsp_vers = TSPVERSION;
 237:             (void)strcpy(msg->tsp_name, hostname);
 238:             bytenetorder(msg);
 239:             answerdelay();
 240:             length = sizeof(struct sockaddr_in);
 241:             if (sendto(sock, (char *)msg, sizeof(struct tsp), 0,
 242:                         &from, length) < 0) {
 243:                 syslog(LOG_ERR, "sendto: %m");
 244:                 exit(1);
 245:             }
 246:             backoff = 1;
 247:             delay2 = casual((long)MINTOUT, (long)MAXTOUT);
 248:             (void)gettimeofday(&time, (struct timezone *)0);
 249:             electiontime = time.tv_sec + delay2;
 250:             refusetime = 0;
 251:             break;
 252:         case TSP_MASTERREQ:
 253:             if (fromnet->status != SLAVE)
 254:                 break;
 255:             (void)gettimeofday(&time, (struct timezone *)0);
 256:             electiontime = time.tv_sec + delay2;
 257:             break;
 258:         case TSP_SETDATE:
 259:             saveaddr = from;
 260:             msg->tsp_type = TSP_SETDATEREQ;
 261:             msg->tsp_vers = TSPVERSION;
 262:             (void)strcpy(msg->tsp_name, hostname);
 263:             for (ntp = nettab; ntp != NULL; ntp = ntp->next) {
 264:                 if (ntp->status == SLAVE)
 265:                     break;
 266:             }
 267:             if (ntp == NULL)
 268:                 break;
 269:             answer = acksend(msg, &ntp->dest_addr, (char *)ANYADDR,
 270:                 TSP_DATEACK, ntp);
 271:             if (answer != NULL) {
 272:                 msg->tsp_type = TSP_ACK;
 273:                 bytenetorder(msg);
 274:                 length = sizeof(struct sockaddr_in);
 275:                 if (sendto(sock, (char *)msg,
 276:                     sizeof(struct tsp), 0, &saveaddr,
 277:                     length) < 0) {
 278:                     syslog(LOG_ERR, "sendto: %m");
 279:                     exit(1);
 280:                 }
 281:                 senddateack = ON;
 282:             }
 283:             break;
 284:         case TSP_SETDATEREQ:
 285:             saveaddr = from;
 286:             if (status != SUBMASTER || fromnet->status != MASTER)
 287:                 break;
 288:             for (ntp = nettab; ntp != NULL; ntp = ntp->next) {
 289:                 if (ntp->status == SLAVE)
 290:                     break;
 291:             }
 292:             ind = findhost(msg->tsp_name);
 293:             if (ind < 0) {
 294:                 syslog(LOG_WARNING,
 295:                 "DATEREQ from uncontrolled machine");
 296:                 break;
 297:             }
 298:             syslog(LOG_DEBUG,
 299:                 "forwarding date change request for %s",
 300:                 msg->tsp_name);
 301:             (void)strcpy(msg->tsp_name, hostname);
 302:             answer = acksend(msg, &ntp->dest_addr, (char *)ANYADDR,
 303:                 TSP_DATEACK, ntp);
 304:             if (answer != NULL) {
 305:                 msg->tsp_type = TSP_DATEACK;
 306:                 bytenetorder(msg);
 307:                 length = sizeof(struct sockaddr_in);
 308:                 if (sendto(sock, (char *)msg,
 309:                     sizeof(struct tsp), 0, &saveaddr,
 310:                     length) < 0) {
 311:                     syslog(LOG_ERR, "sendto: %m");
 312:                     exit(1);
 313:                 }
 314:             }
 315:             break;
 316:         case TSP_TRACEON:
 317:             if (!(trace)) {
 318:                 fd = fopen(tracefile, "w");
 319:                 setlinebuf(fd);
 320:                 fprintf(fd, "Tracing started on: %s\n\n",
 321:                                 date());
 322:             }
 323:             trace = ON;
 324:             break;
 325:         case TSP_TRACEOFF:
 326:             if (trace) {
 327:                 fprintf(fd, "Tracing ended on: %s\n", date());
 328:                 (void)fclose(fd);
 329:             }
 330: #ifdef GPROF
 331:             moncontrol(0);
 332:             _mcleanup();
 333:             moncontrol(1);
 334: #endif
 335:             trace = OFF;
 336:             break;
 337:         case TSP_SLAVEUP:
 338:             if ((status & MASTER) && fromnet->status == MASTER) {
 339:                 ind = addmach(msg->tsp_name, &from);
 340:                 newslave(ind, msg->tsp_seq);
 341:             }
 342:             break;
 343:         case TSP_ELECTION:
 344:             if (fromnet->status == SLAVE) {
 345:                 (void)gettimeofday(&time, (struct timezone *)0);
 346:                 electiontime = time.tv_sec + delay2;
 347:                 seq = 0;            /* reset sequence number */
 348:                 if (time.tv_sec < refusetime)
 349:                     msg->tsp_type = TSP_REFUSE;
 350:                 else {
 351:                     msg->tsp_type = TSP_ACCEPT;
 352:                     refusetime = time.tv_sec + 30;
 353:                 }
 354:                 (void)strcpy(candidate, msg->tsp_name);
 355:                 (void)strcpy(msg->tsp_name, hostname);
 356:                 answerdelay();
 357:                 server = from;
 358:                 answer = acksend(msg, &server, candidate, TSP_ACK,
 359:                     (struct netinfo *)NULL);
 360:                 if (answer == NULL)
 361:                     syslog(LOG_WARNING,
 362:                        "no answer from master candidate\n");
 363:             } else {    /* fromnet->status == MASTER */
 364:                 to.tsp_type = TSP_QUIT;
 365:                 (void)strcpy(to.tsp_name, hostname);
 366:                 server = from;
 367:                 answer = acksend(&to, &server, msg->tsp_name,
 368:                     TSP_ACK, (struct netinfo *)NULL);
 369:                 if (answer == NULL) {
 370:                     syslog(LOG_WARNING,
 371:                         "election error: no reply to QUIT");
 372:                 } else {
 373:                     (void) addmach(msg->tsp_name, &from);
 374:                 }
 375:             }
 376:             break;
 377:                 case TSP_CONFLICT:
 378:             if (fromnet->status != MASTER)
 379:                 break;
 380:                         /*
 381:                          * After a network partition, there can be
 382:                          * more than one master: the first slave to
 383:                          * come up will notify here the situation.
 384:                          */
 385:                         (void)strcpy(to.tsp_name, hostname);
 386: 
 387:                         if (fromnet == NULL)
 388:                                 break;
 389:                         for(;;) {
 390:                                 to.tsp_type = TSP_RESOLVE;
 391:                                 answer = acksend(&to, &fromnet->dest_addr,
 392:                                     (char *)ANYADDR, TSP_MASTERACK, fromnet);
 393:                                 if (answer == NULL)
 394:                                         break;
 395:                                 to.tsp_type = TSP_QUIT;
 396:                                 server = from;
 397:                                 msg = acksend(&to, &server, answer->tsp_name,
 398:                                     TSP_ACK, (struct netinfo *)NULL);
 399:                                 if (msg == NULL) {
 400:                                         syslog(LOG_WARNING,
 401:                         "conflict error: no reply to QUIT");
 402:                 } else {
 403:                                         (void) addmach(answer->tsp_name, &from);
 404:                 }
 405:                         }
 406:                         masterup(fromnet);
 407:                         break;
 408:         case TSP_MSITE:
 409:             if (!slavenet)
 410:                 break;
 411:             msaveaddr = from;
 412:             msg->tsp_type = TSP_MSITEREQ;
 413:             msg->tsp_vers = TSPVERSION;
 414:             (void)strcpy(msg->tsp_name, hostname);
 415:             answer = acksend(msg, &slavenet->dest_addr,
 416:                      (char *)ANYADDR, TSP_ACK, slavenet);
 417:             if (answer != NULL) {
 418:                 msg->tsp_type = TSP_ACK;
 419:                 length = sizeof(struct sockaddr_in);
 420:                 bytenetorder(msg);
 421:                 if (sendto(sock, (char *)msg,
 422:                         sizeof(struct tsp), 0,
 423:                         &msaveaddr, length) < 0) {
 424:                     syslog(LOG_ERR, "sendto: %m");
 425:                     exit(1);
 426:                 }
 427:             }
 428:             break;
 429:         case TSP_ACCEPT:
 430:         case TSP_REFUSE:
 431:             break;
 432:         case TSP_RESOLVE:
 433:             break;
 434:         case TSP_QUIT:
 435:             /* become slave */
 436: #ifdef MEASURE
 437:             if (fp != NULL) {
 438:                 (void)fclose(fp);
 439:                 fp = NULL;
 440:             }
 441: #endif
 442:             longjmp(jmpenv, 2);
 443:             break;
 444: #ifdef TESTING
 445:         case TSP_TEST:
 446:             electiontime = 0;
 447:             break;
 448: #endif
 449:         case TSP_MSITEREQ:
 450:             if (status & MASTER)
 451:                 break;
 452:             if (trace) {
 453:                 fprintf(fd, "garbage: ");
 454:                 print(msg, &from);
 455:             }
 456:             break;
 457: 
 458:         case TSP_LOOP:
 459:             /* looking for loops of masters */
 460:             if ( !(status & MASTER))
 461:                 break;
 462:             if (fromnet->status == SLAVE) {
 463:                 if ( !strcmp(msg->tsp_name, hostname)) {
 464:                   for(;;) {
 465:                     to.tsp_type = TSP_RESOLVE;
 466:                     answer = acksend(&to, &fromnet->dest_addr,
 467:                     (char *)ANYADDR, TSP_MASTERACK,
 468:                     fromnet);
 469:                     if (answer == NULL)
 470:                         break;
 471:                     to.tsp_type = TSP_QUIT;
 472:                     (void)strcpy(to.tsp_name, hostname);
 473:                     server = from;
 474:                     answer = acksend(&to, &server,
 475:                     answer->tsp_name, TSP_ACK,
 476:                     (struct netinfo *)NULL);
 477:                     if (answer == NULL) {
 478:                     syslog(LOG_ERR, "loop kill error");
 479:                     } else {
 480:                     electiontime = 0;
 481:                     }
 482:                   }
 483:                 } else {
 484:                 if (msg->tsp_hopcnt-- <= 0)
 485:                     break;
 486:                 bytenetorder(msg);
 487:                 ntp = nettab;
 488:                 for (; ntp != NULL; ntp = ntp->next)
 489:                     if (ntp->status == MASTER)
 490:                     if (sendto(sock, (char *)msg,
 491:                         sizeof(struct tsp), 0,
 492:                         &ntp->dest_addr, length) < 0) {
 493:                         syslog(LOG_ERR, "sendto: %m");
 494:                         exit(1);
 495:                     }
 496:                 }
 497:             } else {
 498:                 /*
 499: 			     * We should not have received this from a net
 500: 			     * we are master on.  There must be two masters
 501: 			     * in this case.
 502: 			     */
 503:                 if (fromnet->my_addr.s_addr == from.sin_addr.s_addr)
 504:                 break;
 505:                 for (;;) {
 506:                 to.tsp_type = TSP_RESOLVE;
 507:                 answer = acksend(&to, &fromnet->dest_addr,
 508:                     (char *)ANYADDR, TSP_MASTERACK,
 509:                     fromnet);
 510:                 if (answer == NULL)
 511:                     break;
 512:                 to.tsp_type = TSP_QUIT;
 513:                 (void)strcpy(to.tsp_name, hostname);
 514:                 server = from;
 515:                 answer = acksend(&to, &server, answer->tsp_name,
 516:                     TSP_ACK, (struct netinfo *)NULL);
 517:                 if (answer == NULL) {
 518:                     syslog(LOG_ERR, "loop kill error2");
 519:                 } else {
 520:                     (void)addmach(msg->tsp_name, &from);
 521:                 }
 522:                 }
 523:             }
 524:             break;
 525:         default:
 526:             if (trace) {
 527:                 fprintf(fd, "garbage: ");
 528:                 print(msg, &from);
 529:             }
 530:             break;
 531:         }
 532:     }
 533:     goto loop;
 534: }
 535: 
 536: /*
 537:  * Used before answering a broadcast message to avoid network
 538:  * contention and likely collisions.
 539:  */
 540: answerdelay()
 541: {
 542:     struct timeval timeout;
 543: 
 544:     timeout.tv_sec = 0;
 545:     timeout.tv_usec = delay1;
 546: 
 547:     (void)select(0, (fd_set *)NULL, (fd_set *)NULL, (fd_set *)NULL,
 548:         &timeout);
 549:     return;
 550: }

Defined functions

answerdelay defined in line 540; used 2 times
slave defined in line 19; used 2 times

Defined variables

sccsid defined in line 8; never used
Last modified: 1987-08-30
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 5178
Valid CSS Valid XHTML 1.0 Strict