Annotation of 43BSD/etc/timed/slave.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.