File:  [DragonFly] / src / usr.sbin / timed / timed / slave.c
Revision 1.3: download - view: text, annotated - select for diffs
Mon Nov 3 19:31:43 2003 UTC (10 years, 10 months ago) by eirikn
Branches: MAIN
CVS tags: HEAD
Remove __P macros from src/usr.bin and src/usr.sbin.

Reviewed by: David Rhodus <drhodus@catpa.com> and
             Matthew Dillon <dillon@apollo.backplane.com>

    1: /*-
    2:  * Copyright (c) 1985, 1993
    3:  *	The Regents of the University of California.  All rights reserved.
    4:  *
    5:  * Redistribution and use in source and binary forms, with or without
    6:  * modification, are permitted provided that the following conditions
    7:  * are met:
    8:  * 1. Redistributions of source code must retain the above copyright
    9:  *    notice, this list of conditions and the following disclaimer.
   10:  * 2. Redistributions in binary form must reproduce the above copyright
   11:  *    notice, this list of conditions and the following disclaimer in the
   12:  *    documentation and/or other materials provided with the distribution.
   13:  * 3. All advertising materials mentioning features or use of this software
   14:  *    must display the following acknowledgement:
   15:  *	This product includes software developed by the University of
   16:  *	California, Berkeley and its contributors.
   17:  * 4. Neither the name of the University nor the names of its contributors
   18:  *    may be used to endorse or promote products derived from this software
   19:  *    without specific prior written permission.
   20:  *
   21:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   22:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   23:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   24:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   25:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   26:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   27:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   28:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   29:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   30:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   31:  * SUCH DAMAGE.
   32:  *
   33:  * @(#)slave.c	8.1 (Berkeley) 6/6/93
   34:  * $FreeBSD: src/usr.sbin/timed/timed/slave.c,v 1.7 1999/08/28 01:20:18 peter Exp $
   35:  * $DragonFly: src/usr.sbin/timed/timed/slave.c,v 1.3 2003/11/03 19:31:43 eirikn Exp $
   36:  */
   37: 
   38: #include "globals.h"
   39: #include <setjmp.h>
   40: #include "pathnames.h"
   41: 
   42: extern jmp_buf jmpenv;
   43: extern int Mflag;
   44: extern int justquit;
   45: 
   46: extern u_short sequence;
   47: 
   48: static char master_name[MAXHOSTNAMELEN];
   49: static struct netinfo *old_slavenet;
   50: static int old_status;
   51: 
   52: static void schgdate(struct tsp *, char *);
   53: static void setmaster(struct tsp *);
   54: static void answerdelay(void);
   55: 
   56: #ifdef sgi
   57: extern void logwtmp(struct timeval *, struct timeval *);
   58: #else
   59: extern void logwtmp(char *, char *, char *);
   60: #endif /* sgi */
   61: 
   62: int
   63: slave()
   64: {
   65: 	int tries;
   66: 	long electiontime, refusetime, looktime, looptime, adjtime;
   67: 	u_short seq;
   68: 	long fastelection;
   69: #define FASTTOUT 3
   70: 	struct in_addr cadr;
   71: 	struct timeval otime;
   72: 	struct sockaddr_in taddr;
   73: 	char tname[MAXHOSTNAMELEN];
   74: 	struct tsp *msg, to;
   75: 	struct timeval ntime, wait;
   76: 	time_t tsp_time_sec;
   77: 	struct tsp *answer;
   78: 	int timeout();
   79: 	char olddate[32];
   80: 	char newdate[32];
   81: 	struct netinfo *ntp;
   82: 	struct hosttbl *htp;
   83: 
   84: 
   85: 	old_slavenet = 0;
   86: 	seq = 0;
   87: 	refusetime = 0;
   88: 	adjtime = 0;
   89: 
   90: 	(void)gettimeofday(&ntime, 0);
   91: 	electiontime = ntime.tv_sec + delay2;
   92: 	fastelection = ntime.tv_sec + FASTTOUT;
   93: 	if (justquit)
   94: 		looktime = electiontime;
   95: 	else
   96: 		looktime = fastelection;
   97: 	looptime = fastelection;
   98: 
   99: 	if (slavenet)
  100: 		xmit(TSP_SLAVEUP, 0, &slavenet->dest_addr);
  101: 	if (status & MASTER) {
  102: 		for (ntp = nettab; ntp != NULL; ntp = ntp->next) {
  103: 			if (ntp->status == MASTER)
  104: 				masterup(ntp);
  105: 		}
  106: 	}
  107: 
  108: loop:
  109: 	get_goodgroup(0);
  110: 	(void)gettimeofday(&ntime, (struct timezone *)0);
  111: 	if (ntime.tv_sec > electiontime) {
  112: 		if (trace)
  113: 			fprintf(fd, "election timer expired\n");
  114: 		longjmp(jmpenv, 1);
  115: 	}
  116: 
  117: 	if (ntime.tv_sec >= looktime) {
  118: 		if (trace)
  119: 			fprintf(fd, "Looking for nets to master\n");
  120: 
  121: 		if (Mflag && nignorednets > 0) {
  122: 			for (ntp = nettab; ntp != NULL; ntp = ntp->next) {
  123: 				if (ntp->status == IGNORE
  124: 				    || ntp->status == NOMASTER) {
  125: 					lookformaster(ntp);
  126: 					if (ntp->status == MASTER) {
  127: 						masterup(ntp);
  128: 					} else if (ntp->status == MASTER) {
  129: 						ntp->status = NOMASTER;
  130: 					}
  131: 				}
  132: 				if (ntp->status == MASTER
  133: 				    && --ntp->quit_count < 0)
  134: 					ntp->quit_count = 0;
  135: 			}
  136: 			makeslave(slavenet);	/* prune extras */
  137: 			setstatus();
  138: 		}
  139: 		(void)gettimeofday(&ntime, 0);
  140: 		looktime = ntime.tv_sec + delay2;
  141: 	}
  142: 	if (ntime.tv_sec >= looptime) {
  143: 		if (trace)
  144: 			fprintf(fd, "Looking for loops\n");
  145: 		for (ntp = nettab; ntp != NULL; ntp = ntp->next) {
  146: 		    if (ntp->status == MASTER) {
  147: 			to.tsp_type = TSP_LOOP;
  148: 			to.tsp_vers = TSPVERSION;
  149: 			to.tsp_seq = sequence++;
  150: 			to.tsp_hopcnt = MAX_HOPCNT;
  151: 			(void)strcpy(to.tsp_name, hostname);
  152: 			bytenetorder(&to);
  153: 			if (sendto(sock, (char *)&to, sizeof(struct tsp), 0,
  154: 				   (struct sockaddr*)&ntp->dest_addr,
  155: 				   sizeof(ntp->dest_addr)) < 0) {
  156: 				trace_sendto_err(ntp->dest_addr.sin_addr);
  157: 			}
  158: 		    }
  159: 		}
  160: 		(void)gettimeofday(&ntime, 0);
  161: 		looptime = ntime.tv_sec + delay2;
  162: 	}
  163: 
  164: 	wait.tv_sec = min(electiontime,min(looktime,looptime)) - ntime.tv_sec;
  165: 	if (wait.tv_sec < 0)
  166: 		wait.tv_sec = 0;
  167: 	wait.tv_sec += FASTTOUT;
  168: 	wait.tv_usec = 0;
  169: 	msg = readmsg(TSP_ANY, ANYADDR, &wait, 0);
  170: 
  171: 	if (msg != NULL) {
  172: 		/*
  173: 		 * filter stuff not for us
  174: 		 */
  175: 		switch (msg->tsp_type) {
  176: 		case TSP_SETDATE:
  177: 		case TSP_TRACEOFF:
  178: 		case TSP_TRACEON:
  179: 			/*
  180: 			 * XXX check to see they are from ourself
  181: 			 */
  182: 			break;
  183: 
  184: 		case TSP_TEST:
  185: 		case TSP_MSITE:
  186: 			break;
  187: 
  188: 		case TSP_MASTERUP:
  189: 			if (!fromnet) {
  190: 				if (trace) {
  191: 					fprintf(fd, "slave ignored: ");
  192: 					print(msg, &from);
  193: 				}
  194: 				goto loop;
  195: 			}
  196: 			break;
  197: 
  198: 		default:
  199: 			if (!fromnet
  200: 			    || fromnet->status == IGNORE
  201: 			    || fromnet->status == NOMASTER) {
  202: 				if (trace) {
  203: 					fprintf(fd, "slave ignored: ");
  204: 					print(msg, &from);
  205: 				}
  206: 				goto loop;
  207: 			}
  208: 			break;
  209: 		}
  210: 
  211: 
  212: 		/*
  213: 		 * now process the message
  214: 		 */
  215: 		switch (msg->tsp_type) {
  216: 
  217: 		case TSP_ADJTIME:
  218: 			if (fromnet != slavenet)
  219: 				break;
  220: 			if (!good_host_name(msg->tsp_name)) {
  221: 				syslog(LOG_NOTICE,
  222: 				   "attempted time adjustment by %s",
  223: 				       msg->tsp_name);
  224: 				suppress(&from, msg->tsp_name, fromnet);
  225: 				break;
  226: 			}
  227: 			/*
  228: 			 * Speed up loop detection in case we have a loop.
  229: 			 * Otherwise the clocks can race until the loop
  230: 			 * is found.
  231: 			 */
  232: 			(void)gettimeofday(&otime, 0);
  233: 			if (adjtime < otime.tv_sec)
  234: 				looptime -= (looptime-otime.tv_sec)/2 + 1;
  235: 
  236: 			setmaster(msg);
  237: 			if (seq != msg->tsp_seq) {
  238: 				seq = msg->tsp_seq;
  239: 				synch(tvtomsround(msg->tsp_time));
  240: 			}
  241: 			(void)gettimeofday(&ntime, 0);
  242: 			electiontime = ntime.tv_sec + delay2;
  243: 			fastelection = ntime.tv_sec + FASTTOUT;
  244: 			adjtime = ntime.tv_sec + SAMPLEINTVL*2;
  245: 			break;
  246: 
  247: 		case TSP_SETTIME:
  248: 			if (fromnet != slavenet)
  249: 				break;
  250: 			if (seq == msg->tsp_seq)
  251: 				break;
  252: 			seq = msg->tsp_seq;
  253: 
  254: 			/* adjust time for residence on the queue */
  255: 			(void)gettimeofday(&otime, 0);
  256: 			adj_msg_time(msg,&otime);
  257: #ifdef sgi
  258: 			(void)cftime(newdate, "%D %T", &msg->tsp_time.tv_sec);
  259: 			(void)cftime(olddate, "%D %T", &otime.tv_sec);
  260: #else
  261: 			/*
  262: 			 * the following line is necessary due to syslog
  263: 			 * calling ctime() which clobbers the static buffer
  264: 			 */
  265: 			(void)strcpy(olddate, date());
  266: 			tsp_time_sec = msg->tsp_time.tv_sec;
  267: 			(void)strcpy(newdate, ctime(&tsp_time_sec));
  268: #endif /* sgi */
  269: 
  270: 			if (!good_host_name(msg->tsp_name)) {
  271: 				syslog(LOG_NOTICE,
  272: 			    "attempted time setting by untrusted %s to %s",
  273: 				       msg->tsp_name, newdate);
  274: 				suppress(&from, msg->tsp_name, fromnet);
  275: 				break;
  276: 			}
  277: 
  278: 			setmaster(msg);
  279: 			timevalsub(&ntime, &msg->tsp_time, &otime);
  280: 			if (ntime.tv_sec < MAXADJ && ntime.tv_sec > -MAXADJ) {
  281: 				/*
  282: 				 * do not change the clock if we can adjust it
  283: 				 */
  284: 				synch(tvtomsround(ntime));
  285: 			} else {
  286: #ifdef sgi
  287: 				if (0 > settimeofday(&msg->tsp_time, 0)) {
  288: 					syslog(LOG_ERR,"settimeofdate(): %m");
  289: 					break;
  290: 				}
  291: 				logwtmp(&otime, &msg->tsp_time);
  292: #else
  293: 				logwtmp("|", "date", "");
  294: 				(void)settimeofday(&msg->tsp_time, 0);
  295: 				logwtmp("{", "date", "");
  296: #endif /* sgi */
  297: 				syslog(LOG_NOTICE,
  298: 				       "date changed by %s from %s",
  299: 					msg->tsp_name, olddate);
  300: 				if (status & MASTER)
  301: 					spreadtime();
  302: 			}
  303: 			(void)gettimeofday(&ntime, 0);
  304: 			electiontime = ntime.tv_sec + delay2;
  305: 			fastelection = ntime.tv_sec + FASTTOUT;
  306: 
  307: /* This patches a bad protocol bug.  Imagine a system with several networks,
  308:  * where there are a pair of redundant gateways between a pair of networks,
  309:  * each running timed.  Assume that we start with a third machine mastering
  310:  * one of the networks, and one of the gateways mastering the other.
  311:  * Imagine that the third machine goes away and the non-master gateway
  312:  * decides to replace it.  If things are timed just 'right,' we will have
  313:  * each gateway mastering one network for a little while.  If a SETTIME
  314:  * message gets into the network at that time, perhaps from the newly
  315:  * masterful gateway as it was taking control, the SETTIME will loop
  316:  * forever.  Each time a gateway receives it on its slave side, it will
  317:  * call spreadtime to forward it on its mastered network.  We are now in
  318:  * a permanent loop, since the SETTIME msgs will keep any clock
  319:  * in the network from advancing.  Normally, the 'LOOP' stuff will detect
  320:  * and correct the situation.  However, with the clocks stopped, the
  321:  * 'looptime' timer cannot expire.  While they are in this state, the
  322:  * masters will try to saturate the network with SETTIME packets.
  323:  */
  324: 			looptime = ntime.tv_sec + (looptime-otime.tv_sec)/2-1;
  325: 			break;
  326: 
  327: 		case TSP_MASTERUP:
  328: 			if (slavenet && fromnet != slavenet)
  329: 				break;
  330: 			if (!good_host_name(msg->tsp_name)) {
  331: 				suppress(&from, msg->tsp_name, fromnet);
  332: 				if (electiontime > fastelection)
  333: 					electiontime = fastelection;
  334: 				break;
  335: 			}
  336: 			makeslave(fromnet);
  337: 			setmaster(msg);
  338: 			setstatus();
  339: 			answerdelay();
  340: 			xmit(TSP_SLAVEUP, 0, &from);
  341: 			(void)gettimeofday(&ntime, 0);
  342: 			electiontime = ntime.tv_sec + delay2;
  343: 			fastelection = ntime.tv_sec + FASTTOUT;
  344: 			refusetime = 0;
  345: 			break;
  346: 
  347: 		case TSP_MASTERREQ:
  348: 			if (fromnet->status != SLAVE)
  349: 				break;
  350: 			(void)gettimeofday(&ntime, 0);
  351: 			electiontime = ntime.tv_sec + delay2;
  352: 			break;
  353: 
  354: 		case TSP_SETDATE:
  355: #ifdef sgi
  356: 			(void)cftime(newdate, "%D %T", &msg->tsp_time.tv_sec);
  357: #else
  358: 			tsp_time_sec = msg->tsp_time.tv_sec;
  359: 			(void)strcpy(newdate, ctime(&tsp_time_sec));
  360: #endif /* sgi */
  361: 			schgdate(msg, newdate);
  362: 			break;
  363: 
  364: 		case TSP_SETDATEREQ:
  365: 			if (fromnet->status != MASTER)
  366: 				break;
  367: #ifdef sgi
  368: 			(void)cftime(newdate, "%D %T", &msg->tsp_time.tv_sec);
  369: #else
  370: 			tsp_time_sec = msg->tsp_time.tv_sec;
  371: 			(void)strcpy(newdate, ctime(&tsp_time_sec));
  372: #endif /* sgi */
  373: 			htp = findhost(msg->tsp_name);
  374: 			if (0 == htp) {
  375: 				syslog(LOG_WARNING,
  376: 				       "DATEREQ from uncontrolled machine");
  377: 				break;
  378: 			}
  379: 			if (!htp->good) {
  380: 				syslog(LOG_WARNING,
  381: 				"attempted date change by untrusted %s to %s",
  382: 				       htp->name, newdate);
  383: 				spreadtime();
  384: 				break;
  385: 			}
  386: 			schgdate(msg, newdate);
  387: 			break;
  388: 
  389: 		case TSP_TRACEON:
  390: 			traceon();
  391: 			break;
  392: 
  393: 		case TSP_TRACEOFF:
  394: 			traceoff("Tracing ended at %s\n");
  395: 			break;
  396: 
  397: 		case TSP_SLAVEUP:
  398: 			newslave(msg);
  399: 			break;
  400: 
  401: 		case TSP_ELECTION:
  402: 			if (fromnet->status == SLAVE) {
  403: 				(void)gettimeofday(&ntime, 0);
  404: 				electiontime = ntime.tv_sec + delay2;
  405: 				fastelection = ntime.tv_sec + FASTTOUT;
  406: 				seq = 0;
  407: 				if (!good_host_name(msg->tsp_name)) {
  408: 					syslog(LOG_NOTICE,
  409: 					       "suppress election of %s",
  410: 					       msg->tsp_name);
  411: 					to.tsp_type = TSP_QUIT;
  412: 					electiontime = fastelection;
  413: 				} else if (cadr.s_addr != from.sin_addr.s_addr
  414: 					   && ntime.tv_sec < refusetime) {
  415: /* if the candidate has to repeat itself, the old code would refuse it
  416:  * the second time.  That would prevent elections.
  417:  */
  418: 					to.tsp_type = TSP_REFUSE;
  419: 				} else {
  420: 					cadr.s_addr = from.sin_addr.s_addr;
  421: 					to.tsp_type = TSP_ACCEPT;
  422: 					refusetime = ntime.tv_sec + 30;
  423: 				}
  424: 				taddr = from;
  425: 				(void)strcpy(tname, msg->tsp_name);
  426: 				(void)strcpy(to.tsp_name, hostname);
  427: 				answerdelay();
  428: 				if (!acksend(&to, &taddr, tname,
  429: 					     TSP_ACK, 0, 0))
  430: 					syslog(LOG_WARNING,
  431: 					     "no answer from candidate %s\n",
  432: 					       tname);
  433: 
  434: 			} else {	/* fromnet->status == MASTER */
  435: 				htp = addmach(msg->tsp_name, &from,fromnet);
  436: 				to.tsp_type = TSP_QUIT;
  437: 				(void)strcpy(to.tsp_name, hostname);
  438: 				if (!acksend(&to, &htp->addr, htp->name,
  439: 					     TSP_ACK, 0, htp->noanswer)) {
  440: 					syslog(LOG_ERR,
  441: 					  "no reply from %s to ELECTION-QUIT",
  442: 					       htp->name);
  443: 					(void)remmach(htp);
  444: 				}
  445: 			}
  446: 			break;
  447: 
  448: 		case TSP_CONFLICT:
  449: 			if (fromnet->status != MASTER)
  450: 				break;
  451: 			/*
  452: 			 * After a network partition, there can be
  453: 			 * more than one master: the first slave to
  454: 			 * come up will notify here the situation.
  455: 			 */
  456: 			(void)strcpy(to.tsp_name, hostname);
  457: 
  458: 			/* The other master often gets into the same state,
  459: 			 * with boring results.
  460: 			 */
  461: 			ntp = fromnet;	/* (acksend() can leave fromnet=0 */
  462: 			for (tries = 0; tries < 3; tries++) {
  463: 				to.tsp_type = TSP_RESOLVE;
  464: 				answer = acksend(&to, &ntp->dest_addr,
  465: 						 ANYADDR, TSP_MASTERACK,
  466: 						 ntp, 0);
  467: 				if (answer == NULL)
  468: 					break;
  469: 				htp = addmach(answer->tsp_name,&from,ntp);
  470: 				to.tsp_type = TSP_QUIT;
  471: 				answer = acksend(&to, &htp->addr, htp->name,
  472: 						 TSP_ACK, 0, htp->noanswer);
  473: 				if (!answer) {
  474: 					syslog(LOG_WARNING,
  475: 				  "conflict error: no reply from %s to QUIT",
  476: 						htp->name);
  477: 					(void)remmach(htp);
  478: 				}
  479: 			}
  480: 			masterup(ntp);
  481: 			break;
  482: 
  483: 		case TSP_MSITE:
  484: 			if (!slavenet)
  485: 				break;
  486: 			taddr = from;
  487: 			to.tsp_type = TSP_MSITEREQ;
  488: 			to.tsp_vers = TSPVERSION;
  489: 			to.tsp_seq = 0;
  490: 			(void)strcpy(to.tsp_name, hostname);
  491: 			answer = acksend(&to, &slavenet->dest_addr,
  492: 					 ANYADDR, TSP_ACK,
  493: 					 slavenet, 0);
  494: 			if (answer != NULL
  495: 			    && good_host_name(answer->tsp_name)) {
  496: 				setmaster(answer);
  497: 				to.tsp_type = TSP_ACK;
  498: 				(void)strcpy(to.tsp_name, answer->tsp_name);
  499: 				bytenetorder(&to);
  500: 				if (sendto(sock, (char *)&to,
  501: 					   sizeof(struct tsp), 0,
  502: 					   (struct sockaddr*)&taddr,
  503: 					   sizeof(taddr)) < 0) {
  504: 					trace_sendto_err(taddr.sin_addr);
  505: 				}
  506: 			}
  507: 			break;
  508: 
  509: 		case TSP_MSITEREQ:
  510: 			break;
  511: 
  512: 		case TSP_ACCEPT:
  513: 		case TSP_REFUSE:
  514: 		case TSP_RESOLVE:
  515: 			break;
  516: 
  517: 		case TSP_QUIT:
  518: 			doquit(msg);		/* become a slave */
  519: 			break;
  520: 
  521: 		case TSP_TEST:
  522: 			electiontime = 0;
  523: 			break;
  524: 
  525: 		case TSP_LOOP:
  526: 			/* looking for loops of masters */
  527: 			if (!(status & MASTER))
  528: 				break;
  529: 			if (fromnet->status == SLAVE) {
  530: 			    if (!strcmp(msg->tsp_name, hostname)) {
  531: 				/*
  532: 				 * Someone forwarded our message back to
  533: 				 * us.  There must be a loop.  Tell the
  534: 				 * master of this network to quit.
  535: 				 *
  536: 				 * The other master often gets into
  537: 				 * the same state, with boring results.
  538: 				 */
  539: 				ntp = fromnet;
  540: 				for (tries = 0; tries < 3; tries++) {
  541: 				    to.tsp_type = TSP_RESOLVE;
  542: 				    answer = acksend(&to, &ntp->dest_addr,
  543: 						     ANYADDR, TSP_MASTERACK,
  544: 						     ntp,0);
  545: 				    if (answer == NULL)
  546: 					break;
  547: 				    taddr = from;
  548: 				    (void)strcpy(tname, answer->tsp_name);
  549: 				    to.tsp_type = TSP_QUIT;
  550: 				    (void)strcpy(to.tsp_name, hostname);
  551: 				    if (!acksend(&to, &taddr, tname,
  552: 						 TSP_ACK, 0, 1)) {
  553: 					syslog(LOG_ERR,
  554: 					"no reply from %s to slave LOOP-QUIT",
  555: 						 tname);
  556: 				    } else {
  557: 					electiontime = 0;
  558: 				    }
  559: 				}
  560: 				(void)gettimeofday(&ntime, 0);
  561: 				looptime = ntime.tv_sec + FASTTOUT;
  562: 			    } else {
  563: 				if (msg->tsp_hopcnt-- < 1)
  564: 				    break;
  565: 				bytenetorder(msg);
  566: 				for (ntp = nettab; ntp != 0; ntp = ntp->next) {
  567: 				    if (ntp->status == MASTER
  568: 					&& 0 > sendto(sock, (char *)msg,
  569: 						      sizeof(struct tsp), 0,
  570: 					      (struct sockaddr*)&ntp->dest_addr,
  571: 						      sizeof(ntp->dest_addr)))
  572: 				    trace_sendto_err(ntp->dest_addr.sin_addr);
  573: 				}
  574: 			    }
  575: 			} else {	/* fromnet->status == MASTER */
  576: 			    /*
  577: 			     * We should not have received this from a net
  578: 			     * we are master on.  There must be two masters,
  579: 			     * unless the packet was really from us.
  580: 			     */
  581: 			    if (from.sin_addr.s_addr
  582: 				== fromnet->my_addr.s_addr) {
  583: 				if (trace)
  584: 				    fprintf(fd,"discarding forwarded LOOP\n");
  585: 				break;
  586: 			    }
  587: 
  588: 			    /*
  589: 			     * The other master often gets into the same
  590: 			     * state, with boring results.
  591: 			     */
  592: 			    ntp = fromnet;
  593: 			    for (tries = 0; tries < 3; tries++) {
  594: 				to.tsp_type = TSP_RESOLVE;
  595: 				answer = acksend(&to, &ntp->dest_addr,
  596: 						 ANYADDR, TSP_MASTERACK,
  597: 						ntp,0);
  598: 				if (!answer)
  599: 					break;
  600: 				htp = addmach(answer->tsp_name,
  601: 					      &from,ntp);
  602: 				to.tsp_type = TSP_QUIT;
  603: 				(void)strcpy(to.tsp_name, hostname);
  604: 				if (!acksend(&to,&htp->addr,htp->name,
  605: 					     TSP_ACK, 0, htp->noanswer)) {
  606: 					syslog(LOG_ERR,
  607: 				    "no reply from %s to master LOOP-QUIT",
  608: 					       htp->name);
  609: 					(void)remmach(htp);
  610: 				}
  611: 			    }
  612: 			    (void)gettimeofday(&ntime, 0);
  613: 			    looptime = ntime.tv_sec + FASTTOUT;
  614: 			}
  615: 			break;
  616: 		default:
  617: 			if (trace) {
  618: 				fprintf(fd, "garbage message: ");
  619: 				print(msg, &from);
  620: 			}
  621: 			break;
  622: 		}
  623: 	}
  624: 	goto loop;
  625: }
  626: 
  627: 
  628: /*
  629:  * tell the world who our master is
  630:  */
  631: static void
  632: setmaster(msg)
  633: 	struct tsp *msg;
  634: {
  635: 	if (slavenet
  636: 	    && (slavenet != old_slavenet
  637: 		|| strcmp(msg->tsp_name, master_name)
  638: 		|| old_status != status)) {
  639: 		(void)strcpy(master_name, msg->tsp_name);
  640: 		old_slavenet = slavenet;
  641: 		old_status = status;
  642: 
  643: 		if (status & MASTER) {
  644: 			syslog(LOG_NOTICE, "submaster to %s", master_name);
  645: 			if (trace)
  646: 				fprintf(fd, "submaster to %s\n", master_name);
  647: 
  648: 		} else {
  649: 			syslog(LOG_NOTICE, "slave to %s", master_name);
  650: 			if (trace)
  651: 				fprintf(fd, "slave to %s\n", master_name);
  652: 		}
  653: 	}
  654: }
  655: 
  656: 
  657: 
  658: /*
  659:  * handle date change request on a slave
  660:  */
  661: static void
  662: schgdate(msg, newdate)
  663: 	struct tsp *msg;
  664: 	char *newdate;
  665: {
  666: 	struct tsp to;
  667: 	u_short seq;
  668: 	struct sockaddr_in taddr;
  669: 	struct timeval otime;
  670: 
  671: 	if (!slavenet)
  672: 		return;			/* no where to forward */
  673: 
  674: 	taddr = from;
  675: 	seq = msg->tsp_seq;
  676: 
  677: 	syslog(LOG_INFO,
  678: 	       "forwarding date change by %s to %s",
  679: 	       msg->tsp_name, newdate);
  680: 
  681: 	/* adjust time for residence on the queue */
  682: 	(void)gettimeofday(&otime, 0);
  683: 	adj_msg_time(msg, &otime);
  684: 
  685: 	to.tsp_type = TSP_SETDATEREQ;
  686: 	to.tsp_time = msg->tsp_time;
  687: 	(void)strcpy(to.tsp_name, hostname);
  688: 	if (!acksend(&to, &slavenet->dest_addr,
  689: 		     ANYADDR, TSP_DATEACK,
  690: 		     slavenet, 0))
  691: 		return;			/* no answer */
  692: 
  693: 	xmit(TSP_DATEACK, seq, &taddr);
  694: }
  695: 
  696: 
  697: /*
  698:  * Used before answering a broadcast message to avoid network
  699:  * contention and likely collisions.
  700:  */
  701: static void
  702: answerdelay()
  703: {
  704: #ifdef sgi
  705: 	sginap(delay1);
  706: #else
  707: 	struct timeval timeout;
  708: 
  709: 	timeout.tv_sec = 0;
  710: 	timeout.tv_usec = delay1;
  711: 
  712: 	(void)select(0, (fd_set *)NULL, (fd_set *)NULL, (fd_set *)NULL,
  713: 	    &timeout);
  714: 	return;
  715: #endif /* sgi */
  716: }