# 2.11BSD#431 - /usr/src/usr.sbin/timed/slave.c

##### Functions

    answerdelay       X
    slave             X

       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

- in line 239, 356

slave defined in line 19; used 2 times

- in /usr/src/usr.sbin/timed/timed.c line 391, 404

#### 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: 2380 |