BSD 4_3_Reno release
[unix-history] / usr / src / usr.sbin / timed / timed / slave.c
index eef0cb7..1ed85b4 100644 (file)
@@ -1,19 +1,35 @@
 /*
 /*
- * Copyright (c) 1983 Regents of the University of California.
- * All rights reserved.  The Berkeley software License Agreement
- * specifies the terms and conditions for redistribution.
+ * Copyright (c) 1985 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted provided
+ * that: (1) source distributions retain this entire copyright notice and
+ * comment, and (2) distributions including binaries display the following
+ * acknowledgement:  ``This product includes software developed by the
+ * University of California, Berkeley and its contributors'' in the
+ * documentation or other materials provided with the distribution and in
+ * all advertising materials mentioning features or use of this software.
+ * Neither the name of the University nor the names of its contributors may
+ * be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  */
 
 #ifndef lint
  */
 
 #ifndef lint
-static char sccsid[] = "@(#)slave.c    2.5 (Berkeley) %G%";
-#endif not lint
+static char sccsid[] = "@(#)slave.c    2.21 (Berkeley) 6/1/90";
+#endif /* not lint */
 
 #include "globals.h"
 #include <protocols/timed.h>
 #include <setjmp.h>
 
 #include "globals.h"
 #include <protocols/timed.h>
 #include <setjmp.h>
+#include "pathnames.h"
 
 extern jmp_buf jmpenv;
 
 
 extern jmp_buf jmpenv;
 
+extern u_short sequence;
+
 slave()
 {
        int length;
 slave()
 {
        int length;
@@ -23,8 +39,7 @@ slave()
        char candidate[MAXHOSTNAMELEN];
        struct tsp *msg, to, *readmsg();
        struct sockaddr_in saveaddr, msaveaddr;
        char candidate[MAXHOSTNAMELEN];
        struct tsp *msg, to, *readmsg();
        struct sockaddr_in saveaddr, msaveaddr;
-       struct timeval wait;
-       struct timeval time, mytime;
+       struct timeval time, wait;
        struct tsp *answer, *acksend();
        int timeout();
        char *date();
        struct tsp *answer, *acksend();
        int timeout();
        char *date();
@@ -36,8 +51,8 @@ slave()
        int ind;
        struct tsp resp;
        extern int Mflag;
        int ind;
        struct tsp resp;
        extern int Mflag;
+       extern int justquit;
 #ifdef MEASURE
 #ifdef MEASURE
-       int tempstat;
        extern FILE *fp;
 #endif
        if (slavenet) {
        extern FILE *fp;
 #endif
        if (slavenet) {
@@ -54,18 +69,21 @@ slave()
 
        if (status & MASTER) {
 #ifdef MEASURE
 
        if (status & MASTER) {
 #ifdef MEASURE
-               fp = fopen("/usr/adm/timed.masterlog", "w");
-               setlinebuf(fp);
+               if (fp == NULL) {
+                       fp = fopen(_PATH_MASTERLOG, "w");
+                       setlinebuf(fp);
+               }
 #endif
 #endif
-               syslog(LOG_NOTICE, "THIS MACHINE IS A SUBMASTER");
+               syslog(LOG_INFO, "THIS MACHINE IS A SUBMASTER");
                if (trace) {
                        fprintf(fd, "THIS MACHINE IS A SUBMASTER\n");
                }
                for (ntp = nettab; ntp != NULL; ntp = ntp->next)
                        if (ntp->status == MASTER)
                                masterup(ntp);
                if (trace) {
                        fprintf(fd, "THIS MACHINE IS A SUBMASTER\n");
                }
                for (ntp = nettab; ntp != NULL; ntp = ntp->next)
                        if (ntp->status == MASTER)
                                masterup(ntp);
+
        } else {
        } else {
-               syslog(LOG_NOTICE, "THIS MACHINE IS A SLAVE");
+               syslog(LOG_INFO, "THIS MACHINE IS A SLAVE");
                if (trace) {
                        fprintf(fd, "THIS MACHINE IS A SLAVE\n");
                }
                if (trace) {
                        fprintf(fd, "THIS MACHINE IS A SLAVE\n");
                }
@@ -77,8 +95,11 @@ 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;
+       if (Mflag)
+               if (justquit)
+                       looktime = time.tv_sec + delay2;
+               else 
+                       looktime = 1;
        else
                looktime = 0;
 
        else
                looktime = 0;
 
@@ -92,43 +113,55 @@ loop:
        }
        if (looktime && time.tv_sec > looktime) {
                if (trace) 
        }
        if (looktime && time.tv_sec > looktime) {
                if (trace) 
-                       fprintf(fd, "Looking for nets to master\n");
+                       fprintf(fd, "Looking for nets to master and loops\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;
+               if (nignorednets > 0) {
+                       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();
 #ifdef MEASURE
 #ifdef MEASURE
-               tempstat = status;
+                       /*
+                        * Check to see if we just became master
+                        * (file not open)
+                        */
+                       if (fp == NULL) {
+                               fp = fopen(_PATH_MASTERLOG, "w");
+                               setlinebuf(fp);
+                       }
 #endif
 #endif
-               setstatus();
-#ifdef MEASURE
-               /*
-                * Check to see if we just became master
-                */
-               if ((status & MASTER) && !(tempstat & MASTER)) {
-                       fp = fopen("/usr/adm/timed.masterlog", "w");
-                       setlinebuf(fp);
                }
                }
-#endif
-               
-               if (nignorednets > 0) {
-                       (void)gettimeofday(&time, (struct timezone *)0);
-                       looktime = time.tv_sec + delay2;
-               } else
-                       looktime = 0;
+
+               for (ntp = nettab; ntp != NULL; ntp = ntp->next) {
+                   if (ntp->status == MASTER) {
+                       to.tsp_type = TSP_LOOP;
+                       to.tsp_vers = TSPVERSION;
+                       to.tsp_seq = sequence++;
+                       to.tsp_hopcnt = 10;
+                       (void)strcpy(to.tsp_name, hostname);
+                       bytenetorder(&to);
+                       if (sendto(sock, (char *)&to, sizeof(struct tsp), 0,
+                           &ntp->dest_addr, sizeof(struct sockaddr_in)) < 0) {
+                               syslog(LOG_ERR, "sendto: %m");
+                               exit(1);
+                       }
+                   }
+               }
+               (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) {
                switch (msg->tsp_type) {
        }
        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:
+               case TSP_SETDATE:
 #ifdef TESTING
                case TSP_TEST:
 #endif
 #ifdef TESTING
                case TSP_TEST:
 #endif
@@ -182,12 +215,15 @@ loop:
                        seq = msg->tsp_seq;
 
                        (void)strcpy(olddate, date());
                        seq = msg->tsp_seq;
 
                        (void)strcpy(olddate, date());
+                       logwtmp("|", "date", "");
                        (void)settimeofday(&msg->tsp_time,
                                (struct timezone *)0);
                        (void)settimeofday(&msg->tsp_time,
                                (struct timezone *)0);
+                       logwtmp("{", "date", "");
                        syslog(LOG_NOTICE, "date changed by %s from: %s",
                                msg->tsp_name, olddate);
                        if ((status & SUBMASTER) == SUBMASTER)
                                spreadtime();
                        syslog(LOG_NOTICE, "date changed by %s from: %s",
                                msg->tsp_name, olddate);
                        if ((status & SUBMASTER) == SUBMASTER)
                                spreadtime();
+                       (void)gettimeofday(&time, (struct timezone *)0);
                        electiontime = time.tv_sec + delay2;
 
                        if (senddateack == ON) {
                        electiontime = time.tv_sec + delay2;
 
                        if (senddateack == ON) {
@@ -232,10 +268,9 @@ loop:
                        (void)gettimeofday(&time, (struct timezone *)0);
                        electiontime = time.tv_sec + delay2;
                        break;
                        (void)gettimeofday(&time, (struct timezone *)0);
                        electiontime = time.tv_sec + delay2;
                        break;
-               case TSP_DATE:
+               case TSP_SETDATE:
                        saveaddr = from;
                        saveaddr = from;
-                       msg->tsp_time.tv_usec = 0;
-                       msg->tsp_type = TSP_DATEREQ;
+                       msg->tsp_type = TSP_SETDATEREQ;
                        msg->tsp_vers = TSPVERSION;
                        (void)strcpy(msg->tsp_name, hostname);
                        for (ntp = nettab; ntp != NULL; ntp = ntp->next) {
                        msg->tsp_vers = TSPVERSION;
                        (void)strcpy(msg->tsp_name, hostname);
                        for (ntp = nettab; ntp != NULL; ntp = ntp->next) {
@@ -259,7 +294,7 @@ loop:
                                senddateack = ON;
                        }
                        break;
                                senddateack = ON;
                        }
                        break;
-               case TSP_DATEREQ:
+               case TSP_SETDATEREQ:
                        saveaddr = from;
                        if (status != SUBMASTER || fromnet->status != MASTER)
                                break;
                        saveaddr = from;
                        if (status != SUBMASTER || fromnet->status != MASTER)
                                break;
@@ -267,6 +302,16 @@ loop:
                                if (ntp->status == SLAVE)
                                        break;
                        }
                                if (ntp->status == SLAVE)
                                        break;
                        }
+                       ind = findhost(msg->tsp_name);
+                       if (ind < 0) {
+                           syslog(LOG_WARNING,
+                               "DATEREQ from uncontrolled machine");
+                           break;
+                       }
+                       syslog(LOG_DEBUG,
+                           "forwarding date change request for %s",
+                           msg->tsp_name);
+                       (void)strcpy(msg->tsp_name, hostname);
                        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) {
@@ -325,18 +370,18 @@ loop:
                                server = from;
                                answer = acksend(msg, &server, candidate, TSP_ACK,
                                    (struct netinfo *)NULL);
                                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 */
+                               if (answer == NULL)
+                                       syslog(LOG_WARNING,
+                                          "no answer from master candidate\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) {
                                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");
+                                       syslog(LOG_WARNING,
+                                           "election error: no reply to QUIT");
                                } else {
                                        (void) addmach(msg->tsp_name, &from);
                                }
                                } else {
                                        (void) addmach(msg->tsp_name, &from);
                                }
@@ -363,11 +408,13 @@ loop:
                                 to.tsp_type = TSP_QUIT;
                                 server = from;
                                 msg = acksend(&to, &server, answer->tsp_name,
                                 to.tsp_type = TSP_QUIT;
                                 server = from;
                                 msg = acksend(&to, &server, answer->tsp_name,
-                                    TSP_MASTERACK, (struct netinfo *)NULL);
+                                    TSP_ACK, (struct netinfo *)NULL);
                                 if (msg == NULL) {
                                 if (msg == NULL) {
-                                        syslog(LOG_ERR, "error on sending QUIT");
-                                } else {
-                                        (void) addmach(answer->tsp_name, &from);                                }
+                                        syslog(LOG_WARNING,
+                                           "conflict error: no reply to QUIT");
+                               } else {
+                                        (void) addmach(answer->tsp_name, &from);
+                               }
                         }
                         masterup(fromnet);
                         break;
                         }
                         masterup(fromnet);
                         break;
@@ -400,7 +447,10 @@ loop:
                case TSP_QUIT:
                        /* become slave */
 #ifdef MEASURE
                case TSP_QUIT:
                        /* become slave */
 #ifdef MEASURE
-                       (void)fclose(fp);
+                       if (fp != NULL) {
+                               (void)fclose(fp);
+                               fp = NULL;
+                       }
 #endif
                        longjmp(jmpenv, 2);
                        break;
 #endif
                        longjmp(jmpenv, 2);
                        break;
@@ -417,6 +467,74 @@ loop:
                                print(msg, &from);
                        }
                        break;
                                print(msg, &from);
                        }
                        break;
+
+               case TSP_LOOP:
+                       /* looking for loops of masters */
+                       if ( !(status & MASTER))
+                               break;
+                       if (fromnet->status == SLAVE) {
+                           if ( !strcmp(msg->tsp_name, hostname)) {
+                                 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;
+                                   (void)strcpy(to.tsp_name, hostname);
+                                   server = from;
+                                   answer = acksend(&to, &server,
+                                       answer->tsp_name, TSP_ACK,
+                                       (struct netinfo *)NULL);
+                                   if (answer == NULL) {
+                                       syslog(LOG_ERR, "loop kill error");
+                                   } else {
+                                       electiontime = 0;
+                                   }
+                                 }
+                           } else {
+                               if (msg->tsp_hopcnt-- <= 0)
+                                   break;
+                               bytenetorder(msg);
+                               ntp = nettab;
+                               for (; ntp != NULL; ntp = ntp->next)
+                                   if (ntp->status == MASTER)
+                                       if (sendto(sock, (char *)msg, 
+                                           sizeof(struct tsp), 0,
+                                           &ntp->dest_addr, length) < 0) {
+                                               syslog(LOG_ERR, "sendto: %m");
+                                               exit(1);
+                                       }
+                           }
+                       } else {
+                           /*
+                            * We should not have received this from a net
+                            * we are master on.  There must be two masters
+                            * in this case.
+                            */
+                           if (fromnet->my_addr.s_addr == from.sin_addr.s_addr)
+                               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;
+                               (void)strcpy(to.tsp_name, hostname);
+                               server = from;
+                               answer = acksend(&to, &server, answer->tsp_name,
+                                   TSP_ACK, (struct netinfo *)NULL);
+                               if (answer == NULL) {
+                                       syslog(LOG_ERR, "loop kill error2");
+                               } else {
+                                       (void)addmach(msg->tsp_name, &from);
+                               }
+                           }
+                       }
+                       break;
                default:
                        if (trace) {
                                fprintf(fd, "garbage: ");
                default:
                        if (trace) {
                                fprintf(fd, "garbage: ");