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

##### Functions

    addmach           X
    findhost          X
    logwtmp           X
    master            X
    masterup          X
    newslave          X
    prthp             X
    rmmach            X
    rmnetmachs        X
    spreadtime        X
    synch             X

##### Variables

    header            X
    wtmp              X
    wtmpfile          X

##### Macros

    MAXLINES          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[] = "@(#)master.c	2.14 (Berkeley) 6/5/86";
       9: #endif not lint
      10:
      11: #include "globals.h"
      12: #include <protocols/timed.h>
      13: #include <sys/file.h>
      14: #include <setjmp.h>
      15: #include <utmp.h>
      16:
      17: extern int machup;
      18: extern long measure_delta;
      19: extern jmp_buf jmpenv;
      20:
      21: extern u_short sequence;
      22:
      23: #ifdef MEASURE
      24: int header;
      25: FILE *fp = NULL;
      26: #endif
      27:
      28: /*
      29:  * The main function of `master' is to periodically compute the differences
      30:  * (deltas) between its clock and the clocks of the slaves, to compute the
      31:  * network average delta, and to send to the slaves the differences between
      32:  * their individual deltas and the network delta.
      33:  * While waiting, it receives messages from the slaves (i.e. requests for
      34:  * master's name, remote requests to set the network time, ...), and
      35:  * takes the appropriate action.
      36:  */
      37:
      38: master()
      39: {
      40:     int ind;
      41:     long pollingtime;
      42:     struct timeval wait;
      43:     struct timeval time;
      44:     struct timeval otime;
      45:     struct timezone tzone;
      46:     struct tsp *msg, to;
      47:     struct sockaddr_in saveaddr;
      48:     int findhost();
      49:     char *date();
      50:     struct tsp *readmsg();
      51:     struct tsp *answer, *acksend();
      52:     char olddate[32];
      53:     struct sockaddr_in server;
      54:     register struct netinfo *ntp;
      55:
      56: #ifdef MEASURE
      57:     if (fp == NULL) {
      58:         fp = fopen("/usr/adm/timed.masterlog", "w");
      59:         setlinebuf(fp);
      60:     }
      61: #endif
      62:
      63:     syslog(LOG_INFO, "This machine is master");
      64:     if (trace)
      65:         fprintf(fd, "THIS MACHINE IS MASTER\n");
      66:
      67:     for (ntp = nettab; ntp != NULL; ntp = ntp->next)
      68:         if (ntp->status == MASTER)
      69:             masterup(ntp);
      70:     pollingtime = 0;
      71:
      72: loop:
      73:     (void)gettimeofday(&time, (struct timezone *)0);
      74:     if (time.tv_sec >= pollingtime) {
      75:         pollingtime = time.tv_sec + SAMPLEINTVL;
      76:         synch(0L);
      77:
      78:         for (ntp = nettab; ntp != NULL; ntp = ntp->next) {
      79:             to.tsp_type = TSP_LOOP;
      80:             to.tsp_vers = TSPVERSION;
      81:             to.tsp_seq = sequence++;
      82:             to.tsp_hopcnt = 10;
      83:             (void)strcpy(to.tsp_name, hostname);
      84:             bytenetorder(&to);
      85:             if (sendto(sock, (char *)&to, sizeof(struct tsp), 0,
      86:                 &ntp->dest_addr, sizeof(struct sockaddr_in)) < 0) {
      87:                 syslog(LOG_ERR, "sendto: %m");
      88:                 exit(1);
      89:             }
      90:         }
      91:     }
      92:
      93:     wait.tv_sec = pollingtime - time.tv_sec;
      94:     wait.tv_usec = 0;
      95:     msg = readmsg(TSP_ANY, (char *)ANYADDR, &wait, (struct netinfo *)NULL);
      96:     if (msg != NULL) {
      97:         switch (msg->tsp_type) {
      98:
      99:         case TSP_MASTERREQ:
     100:             break;
     101:         case TSP_SLAVEUP:
     102:             ind = addmach(msg->tsp_name, &from);
     103:             newslave(ind, msg->tsp_seq);
     104:             break;
     105:         case TSP_SETDATE:
     106:             saveaddr = from;
     107:             /*
     108: 			 * the following line is necessary due to syslog
     109: 			 * calling ctime() which clobbers the static buffer
     110: 			 */
     111:             (void)strcpy(olddate, date());
     112:             (void)gettimeofday(&time, &tzone);
     113:             otime = time;
     114:             time.tv_sec = msg->tsp_time.tv_sec;
     115:             time.tv_usec = msg->tsp_time.tv_usec;
     116:             (void)settimeofday(&time, &tzone);
     117:             syslog(LOG_NOTICE, "date changed from: %s", olddate);
     118:             logwtmp(otime, time);
     119:             msg->tsp_type = TSP_DATEACK;
     120:             msg->tsp_vers = TSPVERSION;
     121:             (void)strcpy(msg->tsp_name, hostname);
     122:             bytenetorder(msg);
     123:             if (sendto(sock, (char *)msg, sizeof(struct tsp), 0,
     124:                 &saveaddr, sizeof(struct sockaddr_in)) < 0) {
     125:                 syslog(LOG_ERR, "sendto: %m");
     126:                 exit(1);
     127:             }
     128:             spreadtime();
     129:             pollingtime = 0;
     130:             break;
     131:         case TSP_SETDATEREQ:
     132:             ind = findhost(msg->tsp_name);
     133:             if (ind < 0) {
     134:                 syslog(LOG_WARNING,
     135:                 "DATEREQ from uncontrolled machine");
     136:                 break;
     137:             }
     138:             if (hp[ind].seq !=  msg->tsp_seq) {
     139:                 hp[ind].seq = msg->tsp_seq;
     140:                 /*
     141: 				 * the following line is necessary due to syslog
     142: 				 * calling ctime() which clobbers the static buffer
     143: 				 */
     144:                 (void)strcpy(olddate, date());
     145:                 (void)gettimeofday(&time, &tzone);
     146:                 otime = time;
     147:                 time.tv_sec = msg->tsp_time.tv_sec;
     148:                 time.tv_usec = msg->tsp_time.tv_usec;
     149:                 (void)settimeofday(&time, &tzone);
     150:                 syslog(LOG_NOTICE,
     151:                     "date changed by %s from: %s",
     152:                     msg->tsp_name, olddate);
     153:                 logwtmp(otime, time);
     154:                 spreadtime();
     155:                 pollingtime = 0;
     156:             }
     157:             break;
     158:         case TSP_MSITE:
     159:         case TSP_MSITEREQ:
     160:             break;
     161:         case TSP_TRACEON:
     162:             if (!(trace)) {
     163:                 fd = fopen(tracefile, "w");
     164:                 setlinebuf(fd);
     165:                 fprintf(fd, "Tracing started on: %s\n\n",
     166:                             date());
     167:             }
     168:             trace = ON;
     169:             break;
     170:         case TSP_TRACEOFF:
     171:             if (trace) {
     172:                 fprintf(fd, "Tracing ended on: %s\n", date());
     173:                 (void)fclose(fd);
     174:             }
     175: #ifdef GPROF
     176:             moncontrol(0);
     177:             _mcleanup();
     178:             moncontrol(1);
     179: #endif
     180:             trace = OFF;
     181:             break;
     182:         case TSP_ELECTION:
     183:             to.tsp_type = TSP_QUIT;
     184:             (void)strcpy(to.tsp_name, hostname);
     185:             server = from;
     186:             answer = acksend(&to, &server, msg->tsp_name, TSP_ACK,
     187:                 (struct netinfo *)NULL);
     188:             if (answer == NULL) {
     189:                 syslog(LOG_ERR, "election error");
     190:             } else {
     191:                 (void) addmach(msg->tsp_name, &from);
     192:             }
     193:             pollingtime = 0;
     194:             break;
     195:         case TSP_CONFLICT:
     196:             /*
     197: 			 * After a network partition, there can be
     198: 			 * more than one master: the first slave to
     199: 			 * come up will notify here the situation.
     200: 			 */
     201:
     202:             (void)strcpy(to.tsp_name, hostname);
     203:
     204:             if (fromnet == NULL)
     205:                 break;
     206:             for(;;) {
     207:                 to.tsp_type = TSP_RESOLVE;
     208:                 answer = acksend(&to, &fromnet->dest_addr,
     209:                     (char *)ANYADDR, TSP_MASTERACK, fromnet);
     210:                 if (answer == NULL)
     211:                     break;
     212:                 to.tsp_type = TSP_QUIT;
     213:                 server = from;
     214:                 msg = acksend(&to, &server, answer->tsp_name,
     215:                     TSP_ACK, (struct netinfo *)NULL);
     216:                 if (msg == NULL) {
     217:                     syslog(LOG_ERR, "error on sending QUIT");
     218:                 } else {
     219:                     (void) addmach(answer->tsp_name, &from);
     220:                 }
     221:             }
     222:             masterup(fromnet);
     223:             pollingtime = 0;
     224:             break;
     225:         case TSP_RESOLVE:
     226:             /*
     227: 			 * do not want to call synch() while waiting
     228: 			 * to be killed!
     229: 			 */
     230:             (void)gettimeofday(&time, (struct timezone *)0);
     231:             pollingtime = time.tv_sec + SAMPLEINTVL;
     232:             break;
     233:         case TSP_QUIT:
     234:             /* become slave */
     235: #ifdef MEASURE
     236:             if (fp != NULL) {
     237:                 (void)fclose(fp);
     238:                 fp = NULL;
     239:             }
     240: #endif
     241:             longjmp(jmpenv, 2);
     242:             break;
     243:         case TSP_LOOP:
     244:             /*
     245: 			 * We should not have received this from a net
     246: 			 * we are master on.  There must be two masters
     247: 			 * in this case.
     248: 			 */
     249:             to.tsp_type = TSP_QUIT;
     250:             (void)strcpy(to.tsp_name, hostname);
     251:             server = from;
     252:             answer = acksend(&to, &server, msg->tsp_name, TSP_ACK,
     253:                 (struct netinfo *)NULL);
     254:             if (answer == NULL) {
     255:                 syslog(LOG_WARNING,
     256:                     "loop breakage: no reply to QUIT");
     257:             } else {
     258:                 (void)addmach(msg->tsp_name, &from);
     259:             }
     260:         default:
     261:             if (trace) {
     262:                 fprintf(fd, "garbage: ");
     263:                 print(msg, &from);
     264:             }
     265:             break;
     266:         }
     267:     }
     268:     goto loop;
     269: }
     270:
     271: /*
     272:  * `synch' synchronizes all the slaves by calling measure,
     273:  * networkdelta and correct
     274:  */
     275:
     276: synch(mydelta)
     277: long mydelta;
     278: {
     279:     int i;
     280:     int measure_status;
     281:     long netdelta;
     282:     struct timeval tack;
     283: #ifdef MEASURE
     284: #define MAXLINES    8
     285:     static int lines = 1;
     286:     struct timeval start, end;
     287: #endif
     288:     int measure();
     289:     int correct();
     290:     long networkdelta();
     291:     char *date();
     292:
     293:     if (slvcount > 1) {
     294: #ifdef MEASURE
     295:         (void)gettimeofday(&start, (struct timezone *)0);
     296:         if (header == ON || --lines == 0) {
     297:             fprintf(fp, "%s\n", date());
     298:             for (i=0; i<slvcount; i++)
     299:                 fprintf(fp, "%.7s\t", hp[i].name);
     300:             fprintf(fp, "\n");
     301:             lines = MAXLINES;
     302:             header = OFF;
     303:         }
     304: #endif
     305:         machup = 1;
     306:         hp[0].delta = 0;
     307:         for(i=1; i<slvcount; i++) {
     308:             tack.tv_sec = 0;
     309:             tack.tv_usec = 500000;
     310:             if ((measure_status = measure(&tack, &hp[i].addr)) <0) {
     311:                 syslog(LOG_ERR, "measure: %m");
     312:                 exit(1);
     313:             }
     314:             hp[i].delta = measure_delta;
     315:             if (measure_status == GOOD)
     316:                 machup++;
     317:         }
     318:         if (status & SLAVE) {
     319:             /* called by a submaster */
     320:             if (trace)
     321:                 fprintf(fd, "submaster correct: %ld ms.\n",
     322:                     mydelta);
     323:             correct(mydelta);
     324:         } else {
     325:             if (machup > 1) {
     326:                 netdelta = networkdelta();
     327:                 if (trace)
     328:                     fprintf(fd,
     329:                         "master correct: %ld ms.\n",
     330:                         mydelta);
     331:                 correct(netdelta);
     332:             }
     333:         }
     334: #ifdef MEASURE
     335:         gettimeofday(&end, 0);
     336:         end.tv_sec -= start.tv_sec;
     337:         end.tv_usec -= start.tv_usec;
     338:         if (end.tv_usec < 0) {
     339:             end.tv_sec -= 1;
     340:             end.tv_usec += 1000000;
     341:         }
     342:         fprintf(fp, "%D ms.\n", (end.tv_sec*1000+end.tv_usec/1000));
     343: #endif
     344:         for(i=1; i<slvcount; i++) {
     345:             if (hp[i].delta == HOSTDOWN) {
     346:                 rmmach(i);
     347: #ifdef MEASURE
     348:                 header = ON;
     349: #endif
     350:             }
     351:         }
     352:     } else {
     353:         if (status & SLAVE) {
     354:             correct(mydelta);
     355:         }
     356:     }
     357: }
     358:
     359: /*
     360:  * 'spreadtime' sends the time to each slave after the master
     361:  * has received the command to set the network time
     362:  */
     363:
     364: spreadtime()
     365: {
     366:     int i;
     367:     struct tsp to;
     368:     struct tsp *answer, *acksend();
     369:
     370:     for(i=1; i<slvcount; i++) {
     371:         to.tsp_type = TSP_SETTIME;
     372:         (void)strcpy(to.tsp_name, hostname);
     373:         (void)gettimeofday(&to.tsp_time, (struct timezone *)0);
     374:         answer = acksend(&to, &hp[i].addr, hp[i].name, TSP_ACK,
     375:             (struct netinfo *)NULL);
     376:         if (answer == NULL) {
     377:             syslog(LOG_WARNING,
     378:                 "no reply to SETTIME from: %s", hp[i].name);
     379:         }
     380:     }
     381: }
     382:
     383: findhost(name)
     384: char *name;
     385: {
     386:     int i;
     387:     int ind;
     388:
     389:     ind = -1;
     390:     for (i=1; i<slvcount; i++) {
     391:         if (strcmp(name, hp[i].name) == 0) {
     392:             ind = i;
     393:             break;
     394:         }
     395:     }
     396:     return(ind);
     397: }
     398:
     399: /*
     400:  * 'addmach' adds a host to the list of controlled machines
     401:  * if not already there
     402:  */
     403:
     404: addmach(name, addr)
     405: char *name;
     406: struct sockaddr_in *addr;
     407: {
     408:     int ret;
     409:     int findhost();
     410:
     411:     ret = findhost(name);
     412:     if (ret < 0) {
     413:         hp[slvcount].addr = *addr;
     414:         hp[slvcount].name = (char *)malloc(MAXHOSTNAMELEN);
     415:         (void)strcpy(hp[slvcount].name, name);
     416:         hp[slvcount].seq = 0;
     417:         ret = slvcount;
     418:         if (slvcount < NHOSTS)
     419:             slvcount++;
     420:         else {
     421:             syslog(LOG_ERR, "no more slots in host table");
     422:         }
     423:     } else {
     424:         /* need to clear sequence number anyhow */
     425:         hp[ret].seq = 0;
     426:     }
     427: #ifdef MEASURE
     428:     header = ON;
     429: #endif
     430:     return(ret);
     431: }
     432:
     433: /*
     434:  * Remove all the machines from the host table that exist on the given
     435:  * network.  This is called when a master transitions to a slave on a
     436:  * given network.
     437:  */
     438:
     439: rmnetmachs(ntp)
     440:     register struct netinfo *ntp;
     441: {
     442:     int i;
     443:
     444:     if (trace)
     445:         prthp();
     446:     for (i = 1; i < slvcount; i++)
     447:         if ((hp[i].addr.sin_addr.s_addr & ntp->mask) == ntp->net)
     448:             rmmach(i--);
     449:     if (trace)
     450:         prthp();
     451: }
     452:
     453: /*
     454:  * remove the machine with the given index in the host table.
     455:  */
     456: rmmach(ind)
     457:     int ind;
     458: {
     459:     if (trace)
     460:         fprintf(fd, "rmmach: %s\n", hp[ind].name);
     461:     free(hp[ind].name);
     462:     hp[ind] = hp[--slvcount];
     463: }
     464:
     465: prthp()
     466: {
     467:     int i;
     468:
     469:     fprintf(fd, "host table:");
     470:     for (i=1; i<slvcount; i++)
     471:         fprintf(fd, " %s", hp[i].name);
     472:     fprintf(fd, "\n");
     473: }
     474:
     475: masterup(net)
     476: struct netinfo *net;
     477: {
     478:     struct timeval wait;
     479:     struct tsp to, *msg, *readmsg();
     480:
     481:     to.tsp_type = TSP_MASTERUP;
     482:     to.tsp_vers = TSPVERSION;
     483:     (void)strcpy(to.tsp_name, hostname);
     484:     bytenetorder(&to);
     485:     if (sendto(sock, (char *)&to, sizeof(struct tsp), 0, &net->dest_addr,
     486:         sizeof(struct sockaddr_in)) < 0) {
     487:         syslog(LOG_ERR, "sendto: %m");
     488:         exit(1);
     489:     }
     490:
     491:     for (;;) {
     492:         wait.tv_sec = 1;
     493:         wait.tv_usec = 0;
     494:         msg = readmsg(TSP_SLAVEUP, (char *)ANYADDR, &wait, net);
     495:         if (msg != NULL) {
     496:             (void) addmach(msg->tsp_name, &from);
     497:         } else
     498:             break;
     499:     }
     500: }
     501:
     502: newslave(ind, seq)
     503: u_short seq;
     504: {
     505:     struct tsp to;
     506:     struct tsp *answer, *acksend();
     507:
     508:     if (trace)
     509:         prthp();
     510:     if (seq == 0 || hp[ind].seq !=  seq) {
     511:         hp[ind].seq = seq;
     512:         to.tsp_type = TSP_SETTIME;
     513:         (void)strcpy(to.tsp_name, hostname);
     514:         /*
     515: 		 * give the upcoming slave the time
     516: 		 * to check its input queue before
     517: 		 * setting the time
     518: 		 */
     519:         sleep(1);
     520:         (void) gettimeofday(&to.tsp_time,
     521:             (struct timezone *)0);
     522:         answer = acksend(&to, &hp[ind].addr,
     523:             hp[ind].name, TSP_ACK,
     524:             (struct netinfo *)NULL);
     525:         if (answer == NULL) {
     526:             syslog(LOG_WARNING,
     527:                 "no reply to initial SETTIME from: %s",
     528:                 hp[ind].name);
     529:             rmmach(ind);
     530:         }
     531:     }
     532: }
     533:
     534: char *wtmpfile = "/usr/adm/wtmp";
     535: struct utmp wtmp[2] = {
     536:     { "|", "", "", 0 },
     537:     { "{", "", "", 0 }
     538: };
     539:
     540: logwtmp(otime, ntime)
     541: struct timeval otime, ntime;
     542: {
     543:     int f;
     544:
     545:     wtmp[0].ut_time = otime.tv_sec + (otime.tv_usec + 500000) / 1000000;
     546:     wtmp[1].ut_time = ntime.tv_sec + (ntime.tv_usec + 500000) / 1000000;
     547:     if (wtmp[0].ut_time == wtmp[1].ut_time)
     548:         return;
     549:     if ((f = open(wtmpfile, O_WRONLY|O_APPEND)) >= 0) {
     550:         (void) write(f, (char *)wtmp, sizeof(wtmp));
     551:         (void) close(f);
     552:     }
     553: }

#### Defined functions

addmach defined in line 404; used 12 times

- in line 102, 191, 219, 258, 496
- in /usr/src/usr.sbin/timed/candidate.c line 59, 96-101(2)
- in /usr/src/usr.sbin/timed/slave.c line 339, 373, 403, 520

findhost defined in line 383; used 5 times

- in line 48, 132, 409-411(2)
- in /usr/src/usr.sbin/timed/slave.c line 292

logwtmp defined in line 540; used 3 times

- in line 118, 153
- in /usr/src/usr.sbin/timed/slave.c line 210

master defined in line 38; used 1 times

- in /usr/src/usr.sbin/timed/timed.c line 389

masterup defined in line 475; used 5 times

- in line 69, 222
- in /usr/src/usr.sbin/timed/slave.c line 70, 110, 406

newslave defined in line 502; used 2 times

- in line 103
- in /usr/src/usr.sbin/timed/slave.c line 340

prthp defined in line 465; used 3 times

- in line 445-450(2), 509

rmmach defined in line 456; used 3 times

- in line 346, 448, 529

rmnetmachs defined in line 439; used 1 times

- in /usr/src/usr.sbin/timed/timed.c line 372

spreadtime defined in line 364; used 3 times

- in line 128, 154
- in /usr/src/usr.sbin/timed/slave.c line 212

synch defined in line 276; used 2 times

- in line 76
- in /usr/src/usr.sbin/timed/slave.c line 189

#### Defined variables

header defined in line 24; used 4 times

- in line 296, 302, 348, 428

sccsid defined in line 8; never used
wtmp defined in line 535; used 6 times

- in line 545-550(6)

wtmpfile defined in line 534; used 1 times

- in line 549

#### Defined macros

MAXLINES defined in line 284; used 1 times

- in line 301

Last modified: 1988-12-25 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 2497 |