major work on multiple network code (Kirk Smith, ks@ef.purdue.edu)
authorJim Bloom <bloom@ucbvax.Berkeley.EDU>
Sat, 12 Apr 1986 09:17:00 +0000 (01:17 -0800)
committerJim Bloom <bloom@ucbvax.Berkeley.EDU>
Sat, 12 Apr 1986 09:17:00 +0000 (01:17 -0800)
SCCS-vsn: usr.sbin/timed/timed/acksend.c 2.3
SCCS-vsn: usr.sbin/timed/timed/candidate.c 2.2
SCCS-vsn: usr.sbin/timed/timed/globals.h 2.2
SCCS-vsn: usr.sbin/timed/timed/master.c 2.3
SCCS-vsn: usr.sbin/timed/timed/readmsg.c 2.2
SCCS-vsn: usr.sbin/timed/timed/slave.c 2.4
SCCS-vsn: usr.sbin/timed/timed/timed.c 2.4

usr/src/usr.sbin/timed/timed/acksend.c
usr/src/usr.sbin/timed/timed/candidate.c
usr/src/usr.sbin/timed/timed/globals.h
usr/src/usr.sbin/timed/timed/master.c
usr/src/usr.sbin/timed/timed/readmsg.c
usr/src/usr.sbin/timed/timed/slave.c
usr/src/usr.sbin/timed/timed/timed.c

index 80580af..49ae456 100644 (file)
@@ -5,7 +5,7 @@
  */
 
 #ifndef lint
  */
 
 #ifndef lint
-static char sccsid[] = "@(#)acksend.c  2.2 (Berkeley) %G%";
+static char sccsid[] = "@(#)acksend.c  2.3 (Berkeley) %G%";
 #endif not lint
 
 #include "globals.h"
 #endif not lint
 
 #include "globals.h"
@@ -50,7 +50,7 @@ struct netinfo *net;
                        fprintf(fd, "broadcast: ");
                else
                        fprintf(fd, "%s: ", name);
                        fprintf(fd, "broadcast: ");
                else
                        fprintf(fd, "%s: ", name);
-               print(message);
+               print(message, addr);
        }
        bytenetorder(message);
        do {
        }
        bytenetorder(message);
        do {
index 94d51bc..0514bae 100644 (file)
@@ -5,7 +5,7 @@
  */
 
 #ifndef lint
  */
 
 #ifndef lint
-static char sccsid[] = "@(#)candidate.c        2.1 (Berkeley) %G%";
+static char sccsid[] = "@(#)candidate.c        2.2 (Berkeley) %G%";
 #endif not lint
 
 #include "globals.h"
 #endif not lint
 
 #include "globals.h"
@@ -108,7 +108,7 @@ struct netinfo *net;
                        default:
                                if (trace) {
                                        fprintf(fd, "candidate: ");
                        default:
                                if (trace) {
                                        fprintf(fd, "candidate: ");
-                                       print(resp);
+                                       print(resp, &from);
                                }
                                break;
                        }
                                }
                                break;
                        }
index 6f4c701..6d0b8b7 100644 (file)
@@ -4,7 +4,7 @@
  * specifies the terms and conditions for redistribution.
  */
 
  * specifies the terms and conditions for redistribution.
  */
 
-/*     @(#)globals.h   2.1     (Berkeley)      %G%     */
+/*     @(#)globals.h   2.2     (Berkeley)      %G%     */
 
 #include <sys/param.h>
 #include <stdio.h>
 
 #include <sys/param.h>
 #include <stdio.h>
@@ -64,6 +64,7 @@ extern int status;
 extern int trace;
 extern int sock;
 extern struct sockaddr_in from;
 extern int trace;
 extern int sock;
 extern struct sockaddr_in from;
+extern struct netinfo *fromnet, *slavenet;
 extern FILE *fd;
 extern char hostname[];
 extern char tracefile[];
 extern FILE *fd;
 extern char hostname[];
 extern char tracefile[];
@@ -71,5 +72,9 @@ extern struct host hp[];
 extern int backoff;
 extern long delay1, delay2;
 extern int slvcount;
 extern int backoff;
 extern long delay1, delay2;
 extern int slvcount;
+extern int nslavenets;         /* Number of nets were I could be a slave */
+extern int nmasternets;                /* Number of nets were I could be a master */
+extern int nignorednets;       /* Number of ignored nets */
+extern int nnets;              /* Number of nets I am connected to */
 
 char *strcpy(), *malloc();
 
 char *strcpy(), *malloc();
index 13ec7f7..42696ae 100644 (file)
@@ -5,7 +5,7 @@
  */
 
 #ifndef lint
  */
 
 #ifndef lint
-static char sccsid[] = "@(#)master.c   2.2 (Berkeley) %G%";
+static char sccsid[] = "@(#)master.c   2.3 (Berkeley) %G%";
 #endif not lint
 
 #include "globals.h"
 #endif not lint
 
 #include "globals.h"
@@ -39,7 +39,6 @@ master()
        struct timeval wait;
        struct timeval time;
        struct timezone tzone;
        struct timeval wait;
        struct timeval time;
        struct timezone tzone;
-       struct timeval mytime;
        struct tsp *msg, to;
        struct sockaddr_in saveaddr;
        int findhost();
        struct tsp *msg, to;
        struct sockaddr_in saveaddr;
        int findhost();
@@ -79,36 +78,10 @@ loop:
                switch (msg->tsp_type) {
 
                case TSP_MASTERREQ:
                switch (msg->tsp_type) {
 
                case TSP_MASTERREQ:
-                       ind = addmach(msg->tsp_name, &from);
-                       if (trace)
-                               prthp();
-                       if (hp[ind].seq !=  msg->tsp_seq) {
-                               hp[ind].seq = msg->tsp_seq;
-                               to.tsp_type = TSP_SETTIME;
-                               (void)strcpy(to.tsp_name, hostname);
-                               /*
-                                * give the upcoming slave the time
-                                * to check its input queue before
-                                * setting the time
-                                */
-                               sleep(1);
-                               to.tsp_time.tv_usec = 0;
-                               (void) gettimeofday(&mytime,
-                                   (struct timezone *)0);
-                               to.tsp_time.tv_sec = mytime.tv_sec;
-                               answer = acksend(&to, &hp[ind].addr,
-                                   hp[ind].name, TSP_ACK,
-                                   (struct netinfo *)NULL);
-                               if (answer == NULL) {
-                                       syslog(LOG_ERR,
-                                           "ERROR ON SETTIME machine: %s",
-                                           hp[ind].name);
-                                       slvcount--;
-                               }
-                       }
                        break;
                case TSP_SLAVEUP:
                        break;
                case TSP_SLAVEUP:
-                       (void) addmach(msg->tsp_name, &from);
+                       ind = addmach(msg->tsp_name, &from);
+                       newslave(ind, msg->tsp_seq);
                        break;
                case TSP_DATE:
                        saveaddr = from;
                        break;
                case TSP_DATE:
                        saveaddr = from;
@@ -207,17 +180,12 @@ loop:
 
                        (void)strcpy(to.tsp_name, hostname);
 
 
                        (void)strcpy(to.tsp_name, hostname);
 
-                       for (ntp = nettab; ntp != NULL; ntp = ntp->next) {
-                               if ((ntp->mask & from.sin_addr.s_addr) ==
-                                   ntp->net)
-                                       break;
-                       }
-                       if (ntp == NULL)
+                       if (fromnet == NULL)
                                break;
                        for(;;) {
                                to.tsp_type = TSP_RESOLVE;
                                break;
                        for(;;) {
                                to.tsp_type = TSP_RESOLVE;
-                               answer = acksend(&to, &ntp->dest_addr,
-                                   (char *)ANYADDR, TSP_MASTERACK, ntp);
+                               answer = acksend(&to, &fromnet->dest_addr,
+                                   (char *)ANYADDR, TSP_MASTERACK, fromnet);
                                if (answer == NULL)
                                        break;
                                to.tsp_type = TSP_QUIT;
                                if (answer == NULL)
                                        break;
                                to.tsp_type = TSP_QUIT;
@@ -230,7 +198,7 @@ loop:
                                        (void) addmach(answer->tsp_name, &from);
                                }
                        }
                                        (void) addmach(answer->tsp_name, &from);
                                }
                        }
-                       masterup(ntp);
+                       masterup(fromnet);
                        pollingtime = 0;
                        break;
                case TSP_RESOLVE:
                        pollingtime = 0;
                        break;
                case TSP_RESOLVE:
@@ -251,7 +219,7 @@ loop:
                default:
                        if (trace) {
                                fprintf(fd, "garbage: ");
                default:
                        if (trace) {
                                fprintf(fd, "garbage: ");
-                               print(msg);
+                               print(msg, &from);
                        }
                        break;
                }
                        }
                        break;
                }
@@ -335,7 +303,7 @@ long mydelta;
 #endif
                for(i=1; i<slvcount; i++) {
                        if (hp[i].delta == HOSTDOWN) {
 #endif
                for(i=1; i<slvcount; i++) {
                        if (hp[i].delta == HOSTDOWN) {
-                               free((char *)hp[i].name);
+                               rmmach(i);
                                hp[i] = hp[--slvcount];
 #ifdef MEASURE
                                header = ON;
                                hp[i] = hp[--slvcount];
 #ifdef MEASURE
                                header = ON;
@@ -450,9 +418,8 @@ rmmach(ind)
 {
        if (trace)
                fprintf(fd, "rmmach: %s\n", hp[ind].name);
 {
        if (trace)
                fprintf(fd, "rmmach: %s\n", hp[ind].name);
-       if (slvcount-ind-1 > 0)
-               bcopy(&hp[ind+1], &hp[ind], (slvcount-ind-1)*sizeof(hp[ind]));
-       slvcount--;
+       free(hp[ind].name);
+       hp[ind] = hp[--slvcount];
 }
 
 prthp()
 }
 
 prthp()
@@ -470,6 +437,7 @@ struct netinfo *net;
 {
        struct timeval wait;
        struct tsp to, *msg, *readmsg();
 {
        struct timeval wait;
        struct tsp to, *msg, *readmsg();
+       int ind;
 
        to.tsp_type = TSP_MASTERUP;
        to.tsp_vers = TSPVERSION;
 
        to.tsp_type = TSP_MASTERUP;
        to.tsp_vers = TSPVERSION;
@@ -486,8 +454,42 @@ struct netinfo *net;
                wait.tv_usec = 0;
                msg = readmsg(TSP_SLAVEUP, (char *)ANYADDR, &wait, net);
                if (msg != NULL) {
                wait.tv_usec = 0;
                msg = readmsg(TSP_SLAVEUP, (char *)ANYADDR, &wait, net);
                if (msg != NULL) {
-                       (void) addmach(msg->tsp_name, &from);
+                       ind = addmach(msg->tsp_name, &from);
                } else
                        break;
        }
 }
                } else
                        break;
        }
 }
+
+newslave(ind, seq)
+{
+       struct tsp to;
+       struct tsp *answer, *acksend();
+       struct timeval mytime;
+
+       if (trace)
+               prthp();
+       if (seq == 0 || hp[ind].seq !=  seq) {
+               hp[ind].seq = seq;
+               to.tsp_type = TSP_SETTIME;
+               (void)strcpy(to.tsp_name, hostname);
+               /*
+                * give the upcoming slave the time
+                * to check its input queue before
+                * setting the time
+                */
+               sleep(1);
+               to.tsp_time.tv_usec = 0;
+               (void) gettimeofday(&mytime,
+                   (struct timezone *)0);
+               to.tsp_time.tv_sec = mytime.tv_sec;
+               answer = acksend(&to, &hp[ind].addr,
+                   hp[ind].name, TSP_ACK,
+                   (struct netinfo *)NULL);
+               if (answer == NULL) {
+                       syslog(LOG_ERR,
+                           "ERROR ON SETTIME machine: %s",
+                           hp[ind].name);
+                       rmmach(ind);
+               }
+       }
+}
index 7700916..3b84701 100644 (file)
@@ -5,7 +5,7 @@
  */
 
 #ifndef lint
  */
 
 #ifndef lint
-static char sccsid[] = "@(#)readmsg.c  2.1 (Berkeley) %G%";
+static char sccsid[] = "@(#)readmsg.c  2.2 (Berkeley) %G%";
 #endif not lint
 
 #include "globals.h"
 #endif not lint
 
 #include "globals.h"
@@ -39,6 +39,7 @@ static struct tsplist {
        struct tsplist *p;
 } msgslist;
 struct sockaddr_in from;
        struct tsplist *p;
 } msgslist;
 struct sockaddr_in from;
+struct netinfo *fromnet;
 
 /*
  * `readmsg' returns message `type' sent by `machfrom' if it finds it 
 
 /*
  * `readmsg' returns message `type' sent by `machfrom' if it finds it 
@@ -74,7 +75,7 @@ struct netinfo *netfrom;
                fprintf(fd, "msgqueue:\n");
                while (ptr != NULL) {
                        fprintf(fd, "\t");
                fprintf(fd, "msgqueue:\n");
                while (ptr != NULL) {
                        fprintf(fd, "\t");
-                       print(&ptr->info);
+                       print(&ptr->info, &ptr->addr);
                        ptr = ptr->p;
                }
        }
                        ptr = ptr->p;
                }
        }
@@ -164,7 +165,7 @@ struct netinfo *netfrom;
                                        msgin.tsp_type == TSP_TRACEOFF)) {
                                if (trace) {
                                        fprintf(fd, "readmsg: discarded: ");
                                        msgin.tsp_type == TSP_TRACEOFF)) {
                                if (trace) {
                                        fprintf(fd, "readmsg: discarded: ");
-                                       print(&msgin);
+                                       print(&msgin, &from);
                                }
                                (void)gettimeofday(&rtime,(struct timezone *)0);
                                if (ISTOUTOFF(rtime, rtout))
                                }
                                (void)gettimeofday(&rtime,(struct timezone *)0);
                                if (ISTOUTOFF(rtime, rtout))
@@ -184,12 +185,11 @@ struct netinfo *netfrom;
                                    ntp->net) {
                                        if (ntp->status == MASTER)
                                                masterack();
                                    ntp->net) {
                                        if (ntp->status == MASTER)
                                                masterack();
-                                       else 
+                                       else
                                                slaveack();
                                        break;
                                }
                        }
                                                slaveack();
                                        break;
                                }
                        }
-
                        if (LOOKAT(msgin, type, machfrom, netfrom, from)) {
                                ret = &msgin;
                                break;
                        if (LOOKAT(msgin, type, machfrom, netfrom, from)) {
                                ret = &msgin;
                                break;
@@ -213,7 +213,15 @@ out:
        if (ret != NULL) {
                if (trace) {
                        fprintf(fd, "readmsg: ");
        if (ret != NULL) {
                if (trace) {
                        fprintf(fd, "readmsg: ");
-                       print(ret);
+                       print(ret, &from);
+               }
+               fromnet = NULL;
+               for (ntp = nettab; ntp != NULL; ntp = ntp->next) {
+                       if ((ntp->mask & from.sin_addr.s_addr) ==
+                           ntp->net) {
+                               fromnet = ntp;
+                               break;
+                       }
                }
        }
        return(ret);
                }
        }
        return(ret);
@@ -245,7 +253,7 @@ slaveack()
                (void)strcpy(resp.tsp_name, hostname);
                if (trace) {
                        fprintf(fd, "Slaveack: ");
                (void)strcpy(resp.tsp_name, hostname);
                if (trace) {
                        fprintf(fd, "Slaveack: ");
-                       print(&resp);
+                       print(&resp, &from);
                }
                bytenetorder(&resp);     /* this is not really necessary here */
                if (sendto(sock, (char *)&resp, sizeof(struct tsp), 0, 
                }
                bytenetorder(&resp);     /* this is not really necessary here */
                if (sendto(sock, (char *)&resp, sizeof(struct tsp), 0, 
@@ -286,7 +294,7 @@ masterack()
                bytenetorder(&resp);
                if (trace) {
                        fprintf(fd, "Masterack: ");
                bytenetorder(&resp);
                if (trace) {
                        fprintf(fd, "Masterack: ");
-                       print(&resp);
+                       print(&resp, &from);
                }
                if (sendto(sock, (char *)&resp, sizeof(struct tsp), 0, 
                                                &from, length) < 0) {
                }
                if (sendto(sock, (char *)&resp, sizeof(struct tsp), 0, 
                                                &from, length) < 0) {
@@ -300,7 +308,7 @@ masterack()
                bytenetorder(&resp);
                if (trace) {
                        fprintf(fd, "Masterack: ");
                bytenetorder(&resp);
                if (trace) {
                        fprintf(fd, "Masterack: ");
-                       print(&resp);
+                       print(&resp, &from);
                }
                if (sendto(sock, (char *)&resp, sizeof(struct tsp), 0, 
                                                &from, length) < 0) {
                }
                if (sendto(sock, (char *)&resp, sizeof(struct tsp), 0, 
                                                &from, length) < 0) {
@@ -313,7 +321,7 @@ masterack()
                bytenetorder(&resp);
                if (trace) {
                        fprintf(fd, "Masterack: ");
                bytenetorder(&resp);
                if (trace) {
                        fprintf(fd, "Masterack: ");
-                       print(&resp);
+                       print(&resp, &from);
                }
                if (sendto(sock, (char *)&resp, sizeof(struct tsp), 0, 
                                                &from, length) < 0) {
                }
                if (sendto(sock, (char *)&resp, sizeof(struct tsp), 0, 
                                                &from, length) < 0) {
@@ -329,14 +337,16 @@ masterack()
 /*
  * Print a TSP message 
  */
 /*
  * Print a TSP message 
  */
-print(msg)
+print(msg, addr)
 struct tsp *msg;
 struct tsp *msg;
+struct sockaddr_in *addr;
 {
 {
-       fprintf(fd, "%s %d %d (%d, %d) %s\n",
+       fprintf(fd, "%s %d %d (%d, %d) %s %s\n",
                tsptype[msg->tsp_type],
                msg->tsp_vers,
                msg->tsp_seq,
                msg->tsp_time.tv_sec, 
                msg->tsp_time.tv_usec, 
                tsptype[msg->tsp_type],
                msg->tsp_vers,
                msg->tsp_seq,
                msg->tsp_time.tv_sec, 
                msg->tsp_time.tv_usec, 
-               msg->tsp_name);
+               msg->tsp_name,
+               inet_ntoa(addr->sin_addr));
 }
 }
index f9dd2c8..8aec503 100644 (file)
@@ -5,7 +5,7 @@
  */
 
 #ifndef lint
  */
 
 #ifndef lint
-static char sccsid[] = "@(#)slave.c    2.3 (Berkeley) %G%";
+static char sccsid[] = "@(#)slave.c    2.4 (Berkeley) %G%";
 #endif not lint
 
 #include "globals.h"
 #endif not lint
 
 #include "globals.h"
@@ -18,7 +18,7 @@ slave()
 {
        int length;
        int senddateack;
 {
        int length;
        int senddateack;
-       long electiontime, refusetime;
+       long electiontime, refusetime, looktime;
        u_short seq;
        char candidate[MAXHOSTNAMELEN];
        struct tsp *msg, to, *readmsg();
        u_short seq;
        char candidate[MAXHOSTNAMELEN];
        struct tsp *msg, to, *readmsg();
@@ -34,9 +34,22 @@ slave()
        struct sockaddr_in server;
        register struct netinfo *ntp;
        int ind;
        struct sockaddr_in server;
        register struct netinfo *ntp;
        int ind;
+       struct tsp resp;
+       extern int Mflag;
 #ifdef MEASURE
        extern FILE *fp;
 #endif
 #ifdef MEASURE
        extern FILE *fp;
 #endif
+       if (slavenet) {
+               resp.tsp_type = TSP_SLAVEUP;
+               resp.tsp_vers = TSPVERSION;
+               (void)strcpy(resp.tsp_name, hostname);
+               bytenetorder(&resp);
+               if (sendto(sock, (char *)&resp, sizeof(struct tsp), 0,
+                   &slavenet->dest_addr, sizeof(struct sockaddr_in)) < 0) {
+                       syslog(LOG_ERR, "sendto: %m");
+                       exit(1);
+               }
+       }
 
        if (status & MASTER) {
 #ifdef MEASURE
 
        if (status & MASTER) {
 #ifdef MEASURE
@@ -63,6 +76,10 @@ slave()
 
        (void)gettimeofday(&time, (struct timezone *)0);
        electiontime = time.tv_sec + delay2;
 
        (void)gettimeofday(&time, (struct timezone *)0);
        electiontime = time.tv_sec + delay2;
+       if (Mflag && nignorednets > 0)
+               looktime = time.tv_sec + delay2;
+       else
+               looktime = 0;
 
 loop:
        length = sizeof(struct sockaddr_in);
 
 loop:
        length = sizeof(struct sockaddr_in);
@@ -72,13 +89,64 @@ loop:
                        fprintf(fd, "election timer expired\n");
                longjmp(jmpenv, 1);
        }
                        fprintf(fd, "election timer expired\n");
                longjmp(jmpenv, 1);
        }
+       if (looktime && time.tv_sec > looktime) {
+               if (trace) 
+                       fprintf(fd, "Looking for nets to master\n");
+               
+               for (ntp = nettab; ntp != NULL; ntp = ntp->next) {
+                       if (ntp->status == IGNORE) {
+                               lookformaster(ntp);
+                               if (ntp->status == MASTER)
+                                       masterup(ntp);
+                               else
+                                       ntp->status = IGNORE;
+                       }
+               }
+               setstatus();
+               
+               if (nignorednets > 0) {
+                       (void)gettimeofday(&time, (struct timezone *)0);
+                       looktime = time.tv_sec + delay2;
+               }
+       }
        wait.tv_sec = electiontime - time.tv_sec + 10;
        wait.tv_usec = 0;
        msg = readmsg(TSP_ANY, (char *)ANYADDR, &wait, (struct netinfo *)NULL);
        if (msg != NULL) {
        wait.tv_sec = electiontime - time.tv_sec + 10;
        wait.tv_usec = 0;
        msg = readmsg(TSP_ANY, (char *)ANYADDR, &wait, (struct netinfo *)NULL);
        if (msg != NULL) {
+               switch (msg->tsp_type) {
+               case TSP_DATE:
+#ifdef TESTING
+               case TSP_TEST:
+#endif
+               case TSP_MSITE:
+               case TSP_TRACEOFF:
+               case TSP_TRACEON:
+                       break;
+               case TSP_MASTERUP:
+                       if (fromnet == NULL) {
+                               if (trace) {
+                                       fprintf(fd, "slave ignored: ");
+                                       print(msg, &from);
+                               }
+                               goto loop;
+                       }
+                       break;
+               default:
+                       if (fromnet == NULL || fromnet->status == IGNORE) {
+                               if (trace) {
+                                       fprintf(fd, "slave ignored: ");
+                                       print(msg, &from);
+                               }
+                               goto loop;
+                       }
+                       break;
+               }
+
                switch (msg->tsp_type) {
 
                case TSP_ADJTIME:
                switch (msg->tsp_type) {
 
                case TSP_ADJTIME:
+                       if (fromnet->status != SLAVE)
+                               break;
                        (void)gettimeofday(&time, (struct timezone *)0);
                        electiontime = time.tv_sec + delay2;
                        if (seq != msg->tsp_seq) {
                        (void)gettimeofday(&time, (struct timezone *)0);
                        electiontime = time.tv_sec + delay2;
                        if (seq != msg->tsp_seq) {
@@ -92,6 +160,8 @@ loop:
                        }
                        break;
                case TSP_SETTIME:
                        }
                        break;
                case TSP_SETTIME:
+                       if (fromnet->status != SLAVE)
+                               break;
                        if (seq == msg->tsp_seq)
                                break;
 
                        if (seq == msg->tsp_seq)
                                break;
 
@@ -121,6 +191,10 @@ loop:
                        }
                        break;
                case TSP_MASTERUP:
                        }
                        break;
                case TSP_MASTERUP:
+                       if (slavenet && fromnet != slavenet)
+                               break;
+                       makeslave(fromnet);
+                       setstatus();
                        msg->tsp_type = TSP_SLAVEUP;
                        msg->tsp_vers = TSPVERSION;
                        (void)strcpy(msg->tsp_name, hostname);
                        msg->tsp_type = TSP_SLAVEUP;
                        msg->tsp_vers = TSPVERSION;
                        (void)strcpy(msg->tsp_name, hostname);
@@ -139,45 +213,10 @@ loop:
                        refusetime = 0;
                        break;
                case TSP_MASTERREQ:
                        refusetime = 0;
                        break;
                case TSP_MASTERREQ:
-                       for (ntp = nettab; ntp != NULL; ntp = ntp->next) {
-                               if ((ntp->mask & from.sin_addr.s_addr) ==
-                                   ntp->net) {
-                                       if (ntp->status == MASTER)
-                                               break;
-                               }
-                       }
-                       if (!(status & MASTER) || ntp == NULL) {
-                               (void)gettimeofday(&time, (struct timezone *)0);
-                               electiontime = time.tv_sec + delay2;
+                       if (fromnet->status != SLAVE)
                                break;
                                break;
-                       }
-                       ind = addmach(msg->tsp_name, &from);
-                       if (trace)
-                               prthp();
-                       if (hp[ind].seq !=  msg->tsp_seq) {
-                               hp[ind].seq = msg->tsp_seq;
-                               to.tsp_type = TSP_SETTIME;
-                               (void)strcpy(to.tsp_name, hostname);
-                               /*
-                                * give the upcoming slave the time
-                                * to check its input queue before
-                                * setting the time
-                                */
-                               sleep(1);
-                               to.tsp_time.tv_usec = 0;
-                               (void) gettimeofday(&mytime,
-                                   (struct timezone *)0);
-                               to.tsp_time.tv_sec = mytime.tv_sec;
-                               answer = acksend(&to, &hp[ind].addr,
-                                   hp[ind].name, TSP_ACK,
-                                   (struct netinfo *)NULL);
-                               if (answer == NULL) {
-                                       syslog(LOG_ERR,
-                                           "ERROR ON SETTIME machine: %s",
-                                           hp[ind].name);
-                                       slvcount--;
-                               }
-                       }
+                       (void)gettimeofday(&time, (struct timezone *)0);
+                       electiontime = time.tv_sec + delay2;
                        break;
                case TSP_DATE:
                        saveaddr = from;
                        break;
                case TSP_DATE:
                        saveaddr = from;
@@ -189,6 +228,8 @@ loop:
                                if (ntp->status == SLAVE)
                                        break;
                        }
                                if (ntp->status == SLAVE)
                                        break;
                        }
+                       if (ntp == NULL)
+                               break;
                        answer = acksend(msg, &ntp->dest_addr, (char *)ANYADDR,
                            TSP_DATEACK, ntp);
                        if (answer != NULL) {
                        answer = acksend(msg, &ntp->dest_addr, (char *)ANYADDR,
                            TSP_DATEACK, ntp);
                        if (answer != NULL) {
@@ -206,16 +247,7 @@ loop:
                        break;
                case TSP_DATEREQ:
                        saveaddr = from;
                        break;
                case TSP_DATEREQ:
                        saveaddr = from;
-                       if (status != SUBMASTER)
-                               break;
-                       for (ntp = nettab; ntp != NULL; ntp = ntp->next) {
-                               if ((ntp->mask & from.sin_addr.s_addr) ==
-                                   ntp->net) {
-                                       if (ntp->status == MASTER)
-                                               break;
-                               }
-                       }
-                       if (ntp == NULL)
+                       if (status != SUBMASTER || fromnet->status != MASTER)
                                break;
                        for (ntp = nettab; ntp != NULL; ntp = ntp->next) {
                                if (ntp->status == SLAVE)
                                break;
                        for (ntp = nettab; ntp != NULL; ntp = ntp->next) {
                                if (ntp->status == SLAVE)
@@ -257,48 +289,83 @@ loop:
                        trace = OFF;
                        break;
                case TSP_SLAVEUP:
                        trace = OFF;
                        break;
                case TSP_SLAVEUP:
-                       if (!(status & MASTER))
-                               break;
-                       for (ntp = nettab; ntp != NULL; ntp = ntp->next) {
-                               if ((ntp->mask & from.sin_addr.s_addr) ==
-                                   ntp->net) {
-                                       if (ntp->status == MASTER)
-                                               addmach(msg->tsp_name, &from);
-                                       break;
-                               }
+                       if ((status & MASTER) && fromnet->status == MASTER) {
+                               ind = addmach(msg->tsp_name, &from);
+                               newslave(ind, msg->tsp_seq);
                        }
                        break;
                case TSP_ELECTION:
                        }
                        break;
                case TSP_ELECTION:
-                       (void)gettimeofday(&time, (struct timezone *)0);
-                       electiontime = time.tv_sec + delay2;
-                       seq = 0;            /* reset sequence number */
-                       if (time.tv_sec < refusetime)
-                               msg->tsp_type = TSP_REFUSE;
-                       else {
-                               msg->tsp_type = TSP_ACCEPT;
-                               refusetime = time.tv_sec + 30;
+                       if (fromnet->status == SLAVE) {
+                               (void)gettimeofday(&time, (struct timezone *)0);
+                               electiontime = time.tv_sec + delay2;
+                               seq = 0;            /* reset sequence number */
+                               if (time.tv_sec < refusetime)
+                                       msg->tsp_type = TSP_REFUSE;
+                               else {
+                                       msg->tsp_type = TSP_ACCEPT;
+                                       refusetime = time.tv_sec + 30;
+                               }
+                               (void)strcpy(candidate, msg->tsp_name);
+                               (void)strcpy(msg->tsp_name, hostname);
+                               answerdelay();
+                               server = from;
+                               answer = acksend(msg, &server, candidate, TSP_ACK,
+                                   (struct netinfo *)NULL);
+                               if (answer == NULL) {
+                                       syslog(LOG_ERR, "problem in election\n");
+                               }
                        }
                        }
-                       (void)strcpy(candidate, msg->tsp_name);
-                       (void)strcpy(msg->tsp_name, hostname);
-                       answerdelay();
-                       server = from;
-                       answer = acksend(msg, &server, candidate, TSP_ACK,
-                           (struct netinfo *)NULL);
-                       if (answer == NULL) {
-                               syslog(LOG_ERR, "problem in election\n");
+                       else {  /* fromnet->status == MASTER */
+                               to.tsp_type = TSP_QUIT;
+                               (void)strcpy(to.tsp_name, hostname);
+                               server = from;
+                               answer = acksend(&to, &server, msg->tsp_name,
+                                   TSP_ACK, (struct netinfo *)NULL);
+                               if (answer == NULL) {
+                                       syslog(LOG_ERR, "election error");
+                               } else {
+                                       (void) addmach(msg->tsp_name, &from);
+                               }
                        }
                        break;
                        }
                        break;
+                case TSP_CONFLICT:
+                       if (fromnet->status != MASTER)
+                               break;
+                        /*
+                         * After a network partition, there can be
+                         * more than one master: the first slave to
+                         * come up will notify here the situation.
+                         */
+                        (void)strcpy(to.tsp_name, hostname);
+
+                        if (fromnet == NULL)
+                                break;
+                        for(;;) {
+                                to.tsp_type = TSP_RESOLVE;
+                                answer = acksend(&to, &fromnet->dest_addr,
+                                    (char *)ANYADDR, TSP_MASTERACK, fromnet);
+                                if (answer == NULL)
+                                        break;
+                                to.tsp_type = TSP_QUIT;
+                                server = from;
+                                msg = acksend(&to, &server, answer->tsp_name,
+                                    TSP_MASTERACK, (struct netinfo *)NULL);
+                                if (msg == NULL) {
+                                        syslog(LOG_ERR, "error on sending QUIT");
+                                } else {
+                                        (void) addmach(answer->tsp_name, &from);                                }
+                        }
+                        masterup(fromnet);
+                        break;
                case TSP_MSITE:
                case TSP_MSITE:
+                       if (!slavenet)
+                               break;
                        msaveaddr = from;
                        msg->tsp_type = TSP_MSITEREQ;
                        msg->tsp_vers = TSPVERSION;
                        (void)strcpy(msg->tsp_name, hostname);
                        msaveaddr = from;
                        msg->tsp_type = TSP_MSITEREQ;
                        msg->tsp_vers = TSPVERSION;
                        (void)strcpy(msg->tsp_name, hostname);
-                       for (ntp = nettab; ntp != NULL; ntp = ntp->next) {
-                               if (ntp->status == SLAVE)
-                                       break;
-                       }
-                       answer = acksend(msg, &ntp->dest_addr, (char *)ANYADDR,
-                           TSP_ACK, ntp);
+                       answer = acksend(msg, &slavenet->dest_addr,
+                                        (char *)ANYADDR, TSP_ACK, slavenet);
                        if (answer != NULL) {
                                msg->tsp_type = TSP_ACK;
                                length = sizeof(struct sockaddr_in);
                        if (answer != NULL) {
                                msg->tsp_type = TSP_ACK;
                                length = sizeof(struct sockaddr_in);
@@ -314,6 +381,15 @@ loop:
                case TSP_ACCEPT:
                case TSP_REFUSE:
                        break;
                case TSP_ACCEPT:
                case TSP_REFUSE:
                        break;
+               case TSP_RESOLVE:
+                       break;
+               case TSP_QUIT:
+                       /* become slave */
+#ifdef MEASURE
+                       (void)fclose(fp);
+#endif
+                       longjmp(jmpenv, 2);
+                       break;
 #ifdef TESTING
                case TSP_TEST:
                        electiontime = 0;
 #ifdef TESTING
                case TSP_TEST:
                        electiontime = 0;
@@ -324,13 +400,13 @@ loop:
                                break;
                        if (trace) {
                                fprintf(fd, "garbage: ");
                                break;
                        if (trace) {
                                fprintf(fd, "garbage: ");
-                               print(msg);
+                               print(msg, &from);
                        }
                        break;
                default:
                        if (trace) {
                                fprintf(fd, "garbage: ");
                        }
                        break;
                default:
                        if (trace) {
                                fprintf(fd, "garbage: ");
-                               print(msg);
+                               print(msg, &from);
                        }
                        break;
                }
                        }
                        break;
                }
index 39b0181..9c50b4f 100644 (file)
@@ -11,7 +11,7 @@ char copyright[] =
 #endif not lint
 
 #ifndef lint
 #endif not lint
 
 #ifndef lint
-static char sccsid[] = "@(#)timed.c    2.3 (Berkeley) %G%";
+static char sccsid[] = "@(#)timed.c    2.4 (Berkeley) %G%";
 #endif not lint
 
 #include "globals.h"
 #endif not lint
 
 #include "globals.h"
@@ -38,6 +38,13 @@ char tracefile[] = "/usr/adm/timed.log";
 FILE *fd;
 jmp_buf jmpenv;
 struct netinfo *nettab = NULL;
 FILE *fd;
 jmp_buf jmpenv;
 struct netinfo *nettab = NULL;
+int nslavenets;                /* Number of networks were I could be a slave */
+int nmasternets;       /* Number of networks were I could be a master */
+int nignorednets;      /* Number of ignored networks */
+int nnets;             /* Number of networks I am connected to */
+struct netinfo *slavenet;
+struct netinfo *firstslavenet();
+int Mflag;
 
 /*
  * The timedaemons synchronize the clocks of hosts in a local area network.
 
 /*
  * The timedaemons synchronize the clocks of hosts in a local area network.
@@ -60,15 +67,12 @@ char **argv;
        int on;
        int ret;
        long seed;
        int on;
        int ret;
        long seed;
-       int Mflag;
        int nflag;
        int nflag;
-       char mastername[MAXHOSTNAMELEN];
        char *netname;
        struct timeval time;
        struct servent *srvp;
        struct netent *getnetent();
        struct netent *localnet;
        char *netname;
        struct timeval time;
        struct servent *srvp;
        struct netent *getnetent();
        struct netent *localnet;
-       struct sockaddr_in masteraddr;
        struct tsp resp, conflict, *answer, *readmsg(), *acksend();
        long casual();
        char *date();
        struct tsp resp, conflict, *answer, *readmsg(), *acksend();
        long casual();
        char *date();
@@ -79,10 +83,11 @@ char **argv;
        struct ifreq ifreq, *ifr;
        register struct netinfo *ntp;
        struct netinfo *ntip;
        struct ifreq ifreq, *ifr;
        register struct netinfo *ntp;
        struct netinfo *ntip;
+       struct netinfo *savefromnet;
        struct sockaddr_in server;
        u_short port;
        int havemaster = 0;
        struct sockaddr_in server;
        u_short port;
        int havemaster = 0;
-       
+
 #ifdef lint
        ntip = NULL;
 #endif
 #ifdef lint
        ntip = NULL;
 #endif
@@ -285,97 +290,12 @@ char **argv;
                exit(1);
        }
 
                exit(1);
        }
 
-       for(ntp = nettab; ntp != NULL; ntp = ntp->next) {
-               /* look for master */
-               resp.tsp_type = TSP_MASTERREQ;
-               (void)strcpy(resp.tsp_name, hostname);
-               answer = acksend(&resp, &ntp->dest_addr, (char *)ANYADDR, 
-                   TSP_MASTERACK, ntp);
-               if (answer == NULL) {
-                       /*
-                        * Various conditions can cause conflict: race between
-                        * two just started timedaemons when no master is
-                        * present, or timedaemon started during an election.
-                        * Conservative approach is taken: give up and became a
-                        * slave postponing election of a master until first
-                        * timer expires.
-                        */
-                       time.tv_sec = time.tv_usec = 0;
-                       answer = readmsg(TSP_MASTERREQ, (char *)ANYADDR,
-                           &time, ntp);
-                       if (answer != NULL) {
-                               if (!havemaster) {
-                                       ntp->status = SLAVE;
-                                       status |= SLAVE;
-                                       havemaster++;
-                               } else
-                                       ntp->status = IGNORE;
-                               continue;
-                       }
-       
-                       time.tv_sec = time.tv_usec = 0;
-                       answer = readmsg(TSP_MASTERUP, (char *)ANYADDR,
-                           &time, ntp);
-                       if (answer != NULL) {
-                               if (!havemaster) {
-                                       ntp->status = SLAVE;
-                                       status |= SLAVE;
-                                       havemaster++;
-                               } else
-                                       ntp->status = IGNORE;
-                               continue;
-                       }
-       
-                       time.tv_sec = time.tv_usec = 0;
-                       answer = readmsg(TSP_ELECTION, (char *)ANYADDR,
-                           &time, ntp);
-                       if (answer != NULL) {
-                               if (!havemaster) {
-                                       ntp->status = SLAVE;
-                                       status |= SLAVE;
-                                       havemaster++;
-                               } else
-                                       ntp->status = IGNORE;
-                               continue;
-                       }
-                       ntp->status = MASTER;
-                       status |= MASTER;
-               } else {
-                       if (!havemaster) {
-                               ntp->status = SLAVE;
-                               status |= SLAVE;
-                               havemaster++;
-                       } else
-                               ntp->status = IGNORE;
-                       (void)strcpy(mastername, answer->tsp_name);
-                       masteraddr = from;
-
-                       /*
-                        * If network has been partitioned, there might be other
-                        * masters; tell the one we have just acknowledged that 
-                        * it has to gain control over the others. 
-                        */
-                       time.tv_sec = 0;
-                       time.tv_usec = 300000;
-                       answer = readmsg(TSP_MASTERACK, (char *)ANYADDR, &time,
-                           ntp);
-                       /*
-                        * checking also not to send CONFLICT to ack'ed master
-                        * due to duplicated MASTERACKs
-                        */
-                       if (answer != NULL && 
-                           strcmp(answer->tsp_name, mastername) != 0) {
-                               conflict.tsp_type = TSP_CONFLICT;
-                               (void)strcpy(conflict.tsp_name, hostname);
-                               if (acksend(&conflict, &masteraddr, mastername,
-                                   TSP_ACK, (struct netinfo *)NULL) == NULL) {
-                                       syslog(LOG_ERR, 
-                                           "error on sending TSP_CONFLICT");
-                                       exit(1);
-                               }
-                       }
-               }
-       }
+       for (ntp = nettab; ntp != NULL; ntp = ntp->next)
+               lookformaster(ntp);
+       setstatus();
+       /*
+        * Take care of some basic initialization.
+        */
        /* us. delay to be used in response to broadcast */
        delay1 = casual((long)10000, 200000);   
 
        /* us. delay to be used in response to broadcast */
        delay1 = casual((long)10000, 200000);   
 
@@ -396,42 +316,40 @@ char **argv;
                 * correct.c 
                 */
                slvcount = 1;
                 * correct.c 
                 */
                slvcount = 1;
-
                ret = setjmp(jmpenv);
                ret = setjmp(jmpenv);
+
                switch (ret) {
 
                case 0: 
                switch (ret) {
 
                case 0: 
+                       makeslave(firstslavenet());
+                       setstatus();
                        break;
                case 1: 
                        break;
                case 1: 
-                       /* from slave */
-                       for (ntp = nettab; ntp != NULL; ntp = ntp->next) {
-                               if (ntp->status == SLAVE)
-                                       break;
-                       }
-                       ntp->status = election(ntp);
-                       status = 0;
-                       for (ntp = nettab; ntp != NULL; ntp = ntp->next) {
-                               status |= ntp->status;
-                       }
-                       status &= ~IGNORE;
+                       /* Just lost our master */
+                       setstatus();
+                       slavenet->status = election(slavenet);
+                       checkignorednets();
+                       setstatus();
+                       if (slavenet->status == MASTER)
+                               makeslave(firstslavenet());
+                       else
+                               makeslave(slavenet);
+                       setstatus();
                        break;
                case 2:
                        break;
                case 2:
-                       /* from master */
-                       havemaster = 0;
-                       for (ntp = nettab; ntp != NULL; ntp = ntp->next) {
-                               if ((from.sin_addr.s_addr & ntp->mask) ==
-                                   ntp->net) {
-                                       ntp->status = SLAVE;
-                                       rmnetmachs(ntp);
-                                       break;
-                               }
-                       }
-                       status = 0;
-                       for (ntp = nettab; ntp != NULL; ntp = ntp->next) {
-                               status |= ntp->status;
-                       }
-                       status &= ~IGNORE;
+                       /* Just been told to quit */
+                       fromnet->status = SLAVE;
+                       setstatus();
+                       savefromnet = fromnet;
+                       rmnetmachs(fromnet);
+                       checkignorednets();
+                       if (slavenet)
+                               makeslave(slavenet);
+                       else
+                               makeslave(savefromnet);
+                       setstatus();
                        break;
                        break;
+                       
                default:
                        /* this should not happen */
                        syslog(LOG_ERR, "Attempt to enter invalid state");
                default:
                        /* this should not happen */
                        syslog(LOG_ERR, "Attempt to enter invalid state");
@@ -445,31 +363,180 @@ char **argv;
        } else {
                /* if Mflag is not set timedaemon is forced to act as a slave */
                status = SLAVE;
        } else {
                /* if Mflag is not set timedaemon is forced to act as a slave */
                status = SLAVE;
-               ntip = NULL;
-               for(ntp = nettab; ntp != NULL; ntp = ntp->next) {
-                       if (ntp->status & (SLAVE|MASTER)) {
-                               if (ntip == NULL) {
-                                       ntip = ntp;
-                                       ntp->status = SLAVE;
-                               } else {
-                                       ntp->status = IGNORE;
-                               }
-                       }
-               }
+               makeslave(firstslavenet());
                if (setjmp(jmpenv)) {
                if (setjmp(jmpenv)) {
-                       resp.tsp_type = TSP_SLAVEUP;
-                       resp.tsp_vers = TSPVERSION;
-                       (void)strcpy(resp.tsp_name, hostname);
-                       bytenetorder(&resp);
-                       if (sendto(sock, (char *)&resp, sizeof(struct tsp), 0,
-                           &ntip->dest_addr, sizeof(struct sockaddr_in)) < 0) {
-                               syslog(LOG_ERR, "sendto: %m");
+                       setstatus();
+                       checkignorednets();
+                       makeslave(firstslavenet());
+               }
+               for (ntp = nettab; ntp != NULL; ntp = ntp->next)
+                       if (ntp->status == MASTER)
+                               ntp->status = IGNORE;
+               setstatus();
+               slave();
+       }
+}
+
+/*
+ * Try to become master over ignored nets..
+ */
+checkignorednets()
+{
+       register struct netinfo *ntp;
+       for (ntp = nettab; ntp != NULL; ntp = ntp->next)
+               if (ntp->status == IGNORE)
+                       lookformaster(ntp);
+}
+
+lookformaster(ntp)
+       register struct netinfo *ntp;
+{
+       struct tsp resp, conflict, *answer, *readmsg(), *acksend();
+       struct timeval time;
+       char mastername[MAXHOSTNAMELEN];
+       struct sockaddr_in masteraddr;
+
+       ntp->status = SLAVE;
+       /* look for master */
+       resp.tsp_type = TSP_MASTERREQ;
+       (void)strcpy(resp.tsp_name, hostname);
+       answer = acksend(&resp, &ntp->dest_addr, (char *)ANYADDR, 
+           TSP_MASTERACK, ntp);
+       if (answer == NULL) {
+               /*
+                * Various conditions can cause conflict: race between
+                * two just started timedaemons when no master is
+                * present, or timedaemon started during an election.
+                * Conservative approach is taken: give up and became a
+                * slave postponing election of a master until first
+                * timer expires.
+                */
+               time.tv_sec = time.tv_usec = 0;
+               answer = readmsg(TSP_MASTERREQ, (char *)ANYADDR,
+                   &time, ntp);
+               if (answer != NULL) {
+                       ntp->status = SLAVE;
+                       return;
+               }
+
+               time.tv_sec = time.tv_usec = 0;
+               answer = readmsg(TSP_MASTERUP, (char *)ANYADDR,
+                   &time, ntp);
+               if (answer != NULL) {
+                       ntp->status = SLAVE;
+                       return;
+               }
+
+               time.tv_sec = time.tv_usec = 0;
+               answer = readmsg(TSP_ELECTION, (char *)ANYADDR,
+                   &time, ntp);
+               if (answer != NULL) {
+                       ntp->status = SLAVE;
+                       return;
+               }
+               ntp->status = MASTER;
+       } else {
+               (void)strcpy(mastername, answer->tsp_name);
+               masteraddr = from;
+
+               /*
+                * If network has been partitioned, there might be other
+                * masters; tell the one we have just acknowledged that 
+                * it has to gain control over the others. 
+                */
+               time.tv_sec = 0;
+               time.tv_usec = 300000;
+               answer = readmsg(TSP_MASTERACK, (char *)ANYADDR, &time,
+                   ntp);
+               /*
+                * checking also not to send CONFLICT to ack'ed master
+                * due to duplicated MASTERACKs
+                */
+               if (answer != NULL && 
+                   strcmp(answer->tsp_name, mastername) != 0) {
+                       conflict.tsp_type = TSP_CONFLICT;
+                       (void)strcpy(conflict.tsp_name, hostname);
+                       if (acksend(&conflict, &masteraddr, mastername,
+                           TSP_ACK, (struct netinfo *)NULL) == NULL) {
+                               syslog(LOG_ERR, 
+                                   "error on sending TSP_CONFLICT");
                                exit(1);
                        }
                }
                                exit(1);
                        }
                }
-               slave();
        }
 }
        }
 }
+/*
+ * based on the current network configuration, set the status, and count
+ * networks;
+ */
+setstatus()
+{
+       register struct netinfo *ntp;
+
+       status = 0;
+       nmasternets = nslavenets = nnets = nignorednets = 0;
+       if (trace)
+               fprintf(fd, "Net status:\n");
+       for (ntp = nettab; ntp != NULL; ntp = ntp->next) {
+               switch (ntp->status) {
+                 case MASTER:
+                       nmasternets++;
+                       break;
+                 case SLAVE:
+                       nslavenets++;
+                       break;
+                 case IGNORE:
+                       nignorednets++;
+                       break;
+               }
+               if (trace) {
+                       fprintf(fd, "\t%-16s", inet_ntoa(ntp->net));
+                       switch (ntp->status) {
+                         case MASTER:
+                               fprintf(fd, "MASTER\n");
+                               break;
+                         case SLAVE:
+                               fprintf(fd, "SLAVE\n");
+                               break;
+                         case IGNORE:
+                               fprintf(fd, "IGNORE\n");
+                               break;
+                         default:
+                               fprintf(fd, "invalid state %d\n");
+                               break;
+                       }
+               }
+               nnets++;
+               status |= ntp->status;
+       }
+       status &= ~IGNORE;
+       if (trace)
+               fprintf(fd,
+                     "\tnets = %d, masters = %d, slaves = %d, ignored = %d\n",
+                     nnets, nmasternets, nslavenets, nignorednets);
+}
+
+makeslave(net)
+       struct netinfo *net;
+{
+       register struct netinfo *ntp;
+
+       for (ntp = nettab; ntp != NULL; ntp = ntp->next)
+               if (ntp->status == SLAVE && ntp != net)
+                       ntp->status = IGNORE;
+       slavenet = net;
+}
+       
+struct netinfo *
+firstslavenet()
+{
+       register struct netinfo *ntp;
+
+       for (ntp = nettab; ntp != NULL; ntp = ntp->next)
+               if (ntp->status == SLAVE)
+                       return (ntp);
+       return ((struct netinfo *)0);
+}
 
 /* 
  * `casual' returns a random number in the range [inf, sup]
 
 /* 
  * `casual' returns a random number in the range [inf, sup]