0b10309e4d
MAXHOSTNAMELEN chars, like everywhere else in the system, so that strcpy()s and printf()s won't fail.
717 lines
18 KiB
C
717 lines
18 KiB
C
/*-
|
|
* Copyright (c) 1985, 1993
|
|
* The Regents of the University of California. All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
* 3. All advertising materials mentioning features or use of this software
|
|
* must display the following acknowledgement:
|
|
* This product includes software developed by the University of
|
|
* California, Berkeley and its contributors.
|
|
* 4. 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 BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
* SUCH DAMAGE.
|
|
*/
|
|
|
|
#ifndef lint
|
|
#if 0
|
|
static char sccsid[] = "@(#)slave.c 8.1 (Berkeley) 6/6/93";
|
|
#endif
|
|
static const char rcsid[] =
|
|
"$Id: slave.c,v 1.4 1997/10/29 07:32:29 charnier Exp $";
|
|
#endif /* not lint */
|
|
|
|
#include "globals.h"
|
|
#include <setjmp.h>
|
|
#include "pathnames.h"
|
|
|
|
extern jmp_buf jmpenv;
|
|
extern int Mflag;
|
|
extern int justquit;
|
|
|
|
extern u_short sequence;
|
|
|
|
static char master_name[MAXHOSTNAMELEN];
|
|
static struct netinfo *old_slavenet;
|
|
static int old_status;
|
|
|
|
static void schgdate __P((struct tsp *, char *));
|
|
static void setmaster __P((struct tsp *));
|
|
static void answerdelay __P((void));
|
|
|
|
#ifdef sgi
|
|
extern void logwtmp __P((struct timeval *, struct timeval *));
|
|
#else
|
|
extern void logwtmp __P((char *, char *, char *));
|
|
#endif /* sgi */
|
|
|
|
int
|
|
slave()
|
|
{
|
|
int tries;
|
|
long electiontime, refusetime, looktime, looptime, adjtime;
|
|
u_short seq;
|
|
long fastelection;
|
|
#define FASTTOUT 3
|
|
struct in_addr cadr;
|
|
struct timeval otime;
|
|
struct sockaddr_in taddr;
|
|
char tname[MAXHOSTNAMELEN];
|
|
struct tsp *msg, to;
|
|
struct timeval ntime, wait;
|
|
struct tsp *answer;
|
|
int timeout();
|
|
char olddate[32];
|
|
char newdate[32];
|
|
struct netinfo *ntp;
|
|
struct hosttbl *htp;
|
|
|
|
|
|
old_slavenet = 0;
|
|
seq = 0;
|
|
refusetime = 0;
|
|
adjtime = 0;
|
|
|
|
(void)gettimeofday(&ntime, 0);
|
|
electiontime = ntime.tv_sec + delay2;
|
|
fastelection = ntime.tv_sec + FASTTOUT;
|
|
if (justquit)
|
|
looktime = electiontime;
|
|
else
|
|
looktime = fastelection;
|
|
looptime = fastelection;
|
|
|
|
if (slavenet)
|
|
xmit(TSP_SLAVEUP, 0, &slavenet->dest_addr);
|
|
if (status & MASTER) {
|
|
for (ntp = nettab; ntp != NULL; ntp = ntp->next) {
|
|
if (ntp->status == MASTER)
|
|
masterup(ntp);
|
|
}
|
|
}
|
|
|
|
loop:
|
|
get_goodgroup(0);
|
|
(void)gettimeofday(&ntime, (struct timezone *)0);
|
|
if (ntime.tv_sec > electiontime) {
|
|
if (trace)
|
|
fprintf(fd, "election timer expired\n");
|
|
longjmp(jmpenv, 1);
|
|
}
|
|
|
|
if (ntime.tv_sec >= looktime) {
|
|
if (trace)
|
|
fprintf(fd, "Looking for nets to master\n");
|
|
|
|
if (Mflag && nignorednets > 0) {
|
|
for (ntp = nettab; ntp != NULL; ntp = ntp->next) {
|
|
if (ntp->status == IGNORE
|
|
|| ntp->status == NOMASTER) {
|
|
lookformaster(ntp);
|
|
if (ntp->status == MASTER) {
|
|
masterup(ntp);
|
|
} else if (ntp->status == MASTER) {
|
|
ntp->status = NOMASTER;
|
|
}
|
|
}
|
|
if (ntp->status == MASTER
|
|
&& --ntp->quit_count < 0)
|
|
ntp->quit_count = 0;
|
|
}
|
|
makeslave(slavenet); /* prune extras */
|
|
setstatus();
|
|
}
|
|
(void)gettimeofday(&ntime, 0);
|
|
looktime = ntime.tv_sec + delay2;
|
|
}
|
|
if (ntime.tv_sec >= looptime) {
|
|
if (trace)
|
|
fprintf(fd, "Looking for loops\n");
|
|
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 = MAX_HOPCNT;
|
|
(void)strcpy(to.tsp_name, hostname);
|
|
bytenetorder(&to);
|
|
if (sendto(sock, (char *)&to, sizeof(struct tsp), 0,
|
|
(struct sockaddr*)&ntp->dest_addr,
|
|
sizeof(ntp->dest_addr)) < 0) {
|
|
trace_sendto_err(ntp->dest_addr.sin_addr);
|
|
}
|
|
}
|
|
}
|
|
(void)gettimeofday(&ntime, 0);
|
|
looptime = ntime.tv_sec + delay2;
|
|
}
|
|
|
|
wait.tv_sec = min(electiontime,min(looktime,looptime)) - ntime.tv_sec;
|
|
if (wait.tv_sec < 0)
|
|
wait.tv_sec = 0;
|
|
wait.tv_sec += FASTTOUT;
|
|
wait.tv_usec = 0;
|
|
msg = readmsg(TSP_ANY, ANYADDR, &wait, 0);
|
|
|
|
if (msg != NULL) {
|
|
/*
|
|
* filter stuff not for us
|
|
*/
|
|
switch (msg->tsp_type) {
|
|
case TSP_SETDATE:
|
|
case TSP_TRACEOFF:
|
|
case TSP_TRACEON:
|
|
/*
|
|
* XXX check to see they are from ourself
|
|
*/
|
|
break;
|
|
|
|
case TSP_TEST:
|
|
case TSP_MSITE:
|
|
break;
|
|
|
|
case TSP_MASTERUP:
|
|
if (!fromnet) {
|
|
if (trace) {
|
|
fprintf(fd, "slave ignored: ");
|
|
print(msg, &from);
|
|
}
|
|
goto loop;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
if (!fromnet
|
|
|| fromnet->status == IGNORE
|
|
|| fromnet->status == NOMASTER) {
|
|
if (trace) {
|
|
fprintf(fd, "slave ignored: ");
|
|
print(msg, &from);
|
|
}
|
|
goto loop;
|
|
}
|
|
break;
|
|
}
|
|
|
|
|
|
/*
|
|
* now process the message
|
|
*/
|
|
switch (msg->tsp_type) {
|
|
|
|
case TSP_ADJTIME:
|
|
if (fromnet != slavenet)
|
|
break;
|
|
if (!good_host_name(msg->tsp_name)) {
|
|
syslog(LOG_NOTICE,
|
|
"attempted time adjustment by %s",
|
|
msg->tsp_name);
|
|
suppress(&from, msg->tsp_name, fromnet);
|
|
break;
|
|
}
|
|
/*
|
|
* Speed up loop detection in case we have a loop.
|
|
* Otherwise the clocks can race until the loop
|
|
* is found.
|
|
*/
|
|
(void)gettimeofday(&otime, 0);
|
|
if (adjtime < otime.tv_sec)
|
|
looptime -= (looptime-otime.tv_sec)/2 + 1;
|
|
|
|
setmaster(msg);
|
|
if (seq != msg->tsp_seq) {
|
|
seq = msg->tsp_seq;
|
|
synch(tvtomsround(msg->tsp_time));
|
|
}
|
|
(void)gettimeofday(&ntime, 0);
|
|
electiontime = ntime.tv_sec + delay2;
|
|
fastelection = ntime.tv_sec + FASTTOUT;
|
|
adjtime = ntime.tv_sec + SAMPLEINTVL*2;
|
|
break;
|
|
|
|
case TSP_SETTIME:
|
|
if (fromnet != slavenet)
|
|
break;
|
|
if (seq == msg->tsp_seq)
|
|
break;
|
|
seq = msg->tsp_seq;
|
|
|
|
/* adjust time for residence on the queue */
|
|
(void)gettimeofday(&otime, 0);
|
|
adj_msg_time(msg,&otime);
|
|
#ifdef sgi
|
|
(void)cftime(newdate, "%D %T", &msg->tsp_time.tv_sec);
|
|
(void)cftime(olddate, "%D %T", &otime.tv_sec);
|
|
#else
|
|
/*
|
|
* the following line is necessary due to syslog
|
|
* calling ctime() which clobbers the static buffer
|
|
*/
|
|
(void)strcpy(olddate, date());
|
|
(void)strcpy(newdate, ctime(&msg->tsp_time.tv_sec));
|
|
#endif /* sgi */
|
|
|
|
if (!good_host_name(msg->tsp_name)) {
|
|
syslog(LOG_NOTICE,
|
|
"attempted time setting by untrusted %s to %s",
|
|
msg->tsp_name, newdate);
|
|
suppress(&from, msg->tsp_name, fromnet);
|
|
break;
|
|
}
|
|
|
|
setmaster(msg);
|
|
timevalsub(&ntime, &msg->tsp_time, &otime);
|
|
if (ntime.tv_sec < MAXADJ && ntime.tv_sec > -MAXADJ) {
|
|
/*
|
|
* do not change the clock if we can adjust it
|
|
*/
|
|
synch(tvtomsround(ntime));
|
|
} else {
|
|
#ifdef sgi
|
|
if (0 > settimeofday(&msg->tsp_time, 0)) {
|
|
syslog(LOG_ERR,"settimeofdate(): %m");
|
|
break;
|
|
}
|
|
logwtmp(&otime, &msg->tsp_time);
|
|
#else
|
|
logwtmp("|", "date", "");
|
|
(void)settimeofday(&msg->tsp_time, 0);
|
|
logwtmp("{", "date", "");
|
|
#endif /* sgi */
|
|
syslog(LOG_NOTICE,
|
|
"date changed by %s from %s",
|
|
msg->tsp_name, olddate);
|
|
if (status & MASTER)
|
|
spreadtime();
|
|
}
|
|
(void)gettimeofday(&ntime, 0);
|
|
electiontime = ntime.tv_sec + delay2;
|
|
fastelection = ntime.tv_sec + FASTTOUT;
|
|
|
|
/* This patches a bad protocol bug. Imagine a system with several networks,
|
|
* where there are a pair of redundant gateways between a pair of networks,
|
|
* each running timed. Assume that we start with a third machine mastering
|
|
* one of the networks, and one of the gateways mastering the other.
|
|
* Imagine that the third machine goes away and the non-master gateway
|
|
* decides to replace it. If things are timed just 'right,' we will have
|
|
* each gateway mastering one network for a little while. If a SETTIME
|
|
* message gets into the network at that time, perhaps from the newly
|
|
* masterful gateway as it was taking control, the SETTIME will loop
|
|
* forever. Each time a gateway receives it on its slave side, it will
|
|
* call spreadtime to forward it on its mastered network. We are now in
|
|
* a permanent loop, since the SETTIME msgs will keep any clock
|
|
* in the network from advancing. Normally, the 'LOOP' stuff will detect
|
|
* and correct the situation. However, with the clocks stopped, the
|
|
* 'looptime' timer cannot expire. While they are in this state, the
|
|
* masters will try to saturate the network with SETTIME packets.
|
|
*/
|
|
looptime = ntime.tv_sec + (looptime-otime.tv_sec)/2-1;
|
|
break;
|
|
|
|
case TSP_MASTERUP:
|
|
if (slavenet && fromnet != slavenet)
|
|
break;
|
|
if (!good_host_name(msg->tsp_name)) {
|
|
suppress(&from, msg->tsp_name, fromnet);
|
|
if (electiontime > fastelection)
|
|
electiontime = fastelection;
|
|
break;
|
|
}
|
|
makeslave(fromnet);
|
|
setmaster(msg);
|
|
setstatus();
|
|
answerdelay();
|
|
xmit(TSP_SLAVEUP, 0, &from);
|
|
(void)gettimeofday(&ntime, 0);
|
|
electiontime = ntime.tv_sec + delay2;
|
|
fastelection = ntime.tv_sec + FASTTOUT;
|
|
refusetime = 0;
|
|
break;
|
|
|
|
case TSP_MASTERREQ:
|
|
if (fromnet->status != SLAVE)
|
|
break;
|
|
(void)gettimeofday(&ntime, 0);
|
|
electiontime = ntime.tv_sec + delay2;
|
|
break;
|
|
|
|
case TSP_SETDATE:
|
|
#ifdef sgi
|
|
(void)cftime(newdate, "%D %T", &msg->tsp_time.tv_sec);
|
|
#else
|
|
(void)strcpy(newdate, ctime(&msg->tsp_time.tv_sec));
|
|
#endif /* sgi */
|
|
schgdate(msg, newdate);
|
|
break;
|
|
|
|
case TSP_SETDATEREQ:
|
|
if (fromnet->status != MASTER)
|
|
break;
|
|
#ifdef sgi
|
|
(void)cftime(newdate, "%D %T", &msg->tsp_time.tv_sec);
|
|
#else
|
|
(void)strcpy(newdate, ctime(&msg->tsp_time.tv_sec));
|
|
#endif /* sgi */
|
|
htp = findhost(msg->tsp_name);
|
|
if (0 == htp) {
|
|
syslog(LOG_WARNING,
|
|
"DATEREQ from uncontrolled machine");
|
|
break;
|
|
}
|
|
if (!htp->good) {
|
|
syslog(LOG_WARNING,
|
|
"attempted date change by untrusted %s to %s",
|
|
htp->name, newdate);
|
|
spreadtime();
|
|
break;
|
|
}
|
|
schgdate(msg, newdate);
|
|
break;
|
|
|
|
case TSP_TRACEON:
|
|
traceon();
|
|
break;
|
|
|
|
case TSP_TRACEOFF:
|
|
traceoff("Tracing ended at %s\n");
|
|
break;
|
|
|
|
case TSP_SLAVEUP:
|
|
newslave(msg);
|
|
break;
|
|
|
|
case TSP_ELECTION:
|
|
if (fromnet->status == SLAVE) {
|
|
(void)gettimeofday(&ntime, 0);
|
|
electiontime = ntime.tv_sec + delay2;
|
|
fastelection = ntime.tv_sec + FASTTOUT;
|
|
seq = 0;
|
|
if (!good_host_name(msg->tsp_name)) {
|
|
syslog(LOG_NOTICE,
|
|
"suppress election of %s",
|
|
msg->tsp_name);
|
|
to.tsp_type = TSP_QUIT;
|
|
electiontime = fastelection;
|
|
} else if (cadr.s_addr != from.sin_addr.s_addr
|
|
&& ntime.tv_sec < refusetime) {
|
|
/* if the candidate has to repeat itself, the old code would refuse it
|
|
* the second time. That would prevent elections.
|
|
*/
|
|
to.tsp_type = TSP_REFUSE;
|
|
} else {
|
|
cadr.s_addr = from.sin_addr.s_addr;
|
|
to.tsp_type = TSP_ACCEPT;
|
|
refusetime = ntime.tv_sec + 30;
|
|
}
|
|
taddr = from;
|
|
(void)strcpy(tname, msg->tsp_name);
|
|
(void)strcpy(to.tsp_name, hostname);
|
|
answerdelay();
|
|
if (!acksend(&to, &taddr, tname,
|
|
TSP_ACK, 0, 0))
|
|
syslog(LOG_WARNING,
|
|
"no answer from candidate %s\n",
|
|
tname);
|
|
|
|
} else { /* fromnet->status == MASTER */
|
|
htp = addmach(msg->tsp_name, &from,fromnet);
|
|
to.tsp_type = TSP_QUIT;
|
|
(void)strcpy(to.tsp_name, hostname);
|
|
if (!acksend(&to, &htp->addr, htp->name,
|
|
TSP_ACK, 0, htp->noanswer)) {
|
|
syslog(LOG_ERR,
|
|
"no reply from %s to ELECTION-QUIT",
|
|
htp->name);
|
|
(void)remmach(htp);
|
|
}
|
|
}
|
|
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);
|
|
|
|
/* The other master often gets into the same state,
|
|
* with boring results.
|
|
*/
|
|
ntp = fromnet; /* (acksend() can leave fromnet=0 */
|
|
for (tries = 0; tries < 3; tries++) {
|
|
to.tsp_type = TSP_RESOLVE;
|
|
answer = acksend(&to, &ntp->dest_addr,
|
|
ANYADDR, TSP_MASTERACK,
|
|
ntp, 0);
|
|
if (answer == NULL)
|
|
break;
|
|
htp = addmach(answer->tsp_name,&from,ntp);
|
|
to.tsp_type = TSP_QUIT;
|
|
answer = acksend(&to, &htp->addr, htp->name,
|
|
TSP_ACK, 0, htp->noanswer);
|
|
if (!answer) {
|
|
syslog(LOG_WARNING,
|
|
"conflict error: no reply from %s to QUIT",
|
|
htp->name);
|
|
(void)remmach(htp);
|
|
}
|
|
}
|
|
masterup(ntp);
|
|
break;
|
|
|
|
case TSP_MSITE:
|
|
if (!slavenet)
|
|
break;
|
|
taddr = from;
|
|
to.tsp_type = TSP_MSITEREQ;
|
|
to.tsp_vers = TSPVERSION;
|
|
to.tsp_seq = 0;
|
|
(void)strcpy(to.tsp_name, hostname);
|
|
answer = acksend(&to, &slavenet->dest_addr,
|
|
ANYADDR, TSP_ACK,
|
|
slavenet, 0);
|
|
if (answer != NULL
|
|
&& good_host_name(answer->tsp_name)) {
|
|
setmaster(answer);
|
|
to.tsp_type = TSP_ACK;
|
|
(void)strcpy(to.tsp_name, answer->tsp_name);
|
|
bytenetorder(&to);
|
|
if (sendto(sock, (char *)&to,
|
|
sizeof(struct tsp), 0,
|
|
(struct sockaddr*)&taddr,
|
|
sizeof(taddr)) < 0) {
|
|
trace_sendto_err(taddr.sin_addr);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case TSP_MSITEREQ:
|
|
break;
|
|
|
|
case TSP_ACCEPT:
|
|
case TSP_REFUSE:
|
|
case TSP_RESOLVE:
|
|
break;
|
|
|
|
case TSP_QUIT:
|
|
doquit(msg); /* become a slave */
|
|
break;
|
|
|
|
case TSP_TEST:
|
|
electiontime = 0;
|
|
break;
|
|
|
|
case TSP_LOOP:
|
|
/* looking for loops of masters */
|
|
if (!(status & MASTER))
|
|
break;
|
|
if (fromnet->status == SLAVE) {
|
|
if (!strcmp(msg->tsp_name, hostname)) {
|
|
/*
|
|
* Someone forwarded our message back to
|
|
* us. There must be a loop. Tell the
|
|
* master of this network to quit.
|
|
*
|
|
* The other master often gets into
|
|
* the same state, with boring results.
|
|
*/
|
|
ntp = fromnet;
|
|
for (tries = 0; tries < 3; tries++) {
|
|
to.tsp_type = TSP_RESOLVE;
|
|
answer = acksend(&to, &ntp->dest_addr,
|
|
ANYADDR, TSP_MASTERACK,
|
|
ntp,0);
|
|
if (answer == NULL)
|
|
break;
|
|
taddr = from;
|
|
(void)strcpy(tname, answer->tsp_name);
|
|
to.tsp_type = TSP_QUIT;
|
|
(void)strcpy(to.tsp_name, hostname);
|
|
if (!acksend(&to, &taddr, tname,
|
|
TSP_ACK, 0, 1)) {
|
|
syslog(LOG_ERR,
|
|
"no reply from %s to slave LOOP-QUIT",
|
|
tname);
|
|
} else {
|
|
electiontime = 0;
|
|
}
|
|
}
|
|
(void)gettimeofday(&ntime, 0);
|
|
looptime = ntime.tv_sec + FASTTOUT;
|
|
} else {
|
|
if (msg->tsp_hopcnt-- < 1)
|
|
break;
|
|
bytenetorder(msg);
|
|
for (ntp = nettab; ntp != 0; ntp = ntp->next) {
|
|
if (ntp->status == MASTER
|
|
&& 0 > sendto(sock, (char *)msg,
|
|
sizeof(struct tsp), 0,
|
|
(struct sockaddr*)&ntp->dest_addr,
|
|
sizeof(ntp->dest_addr)))
|
|
trace_sendto_err(ntp->dest_addr.sin_addr);
|
|
}
|
|
}
|
|
} else { /* fromnet->status == MASTER */
|
|
/*
|
|
* We should not have received this from a net
|
|
* we are master on. There must be two masters,
|
|
* unless the packet was really from us.
|
|
*/
|
|
if (from.sin_addr.s_addr
|
|
== fromnet->my_addr.s_addr) {
|
|
if (trace)
|
|
fprintf(fd,"discarding forwarded LOOP\n");
|
|
break;
|
|
}
|
|
|
|
/*
|
|
* The other master often gets into the same
|
|
* state, with boring results.
|
|
*/
|
|
ntp = fromnet;
|
|
for (tries = 0; tries < 3; tries++) {
|
|
to.tsp_type = TSP_RESOLVE;
|
|
answer = acksend(&to, &ntp->dest_addr,
|
|
ANYADDR, TSP_MASTERACK,
|
|
ntp,0);
|
|
if (!answer)
|
|
break;
|
|
htp = addmach(answer->tsp_name,
|
|
&from,ntp);
|
|
to.tsp_type = TSP_QUIT;
|
|
(void)strcpy(to.tsp_name, hostname);
|
|
if (!acksend(&to,&htp->addr,htp->name,
|
|
TSP_ACK, 0, htp->noanswer)) {
|
|
syslog(LOG_ERR,
|
|
"no reply from %s to master LOOP-QUIT",
|
|
htp->name);
|
|
(void)remmach(htp);
|
|
}
|
|
}
|
|
(void)gettimeofday(&ntime, 0);
|
|
looptime = ntime.tv_sec + FASTTOUT;
|
|
}
|
|
break;
|
|
default:
|
|
if (trace) {
|
|
fprintf(fd, "garbage message: ");
|
|
print(msg, &from);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
goto loop;
|
|
}
|
|
|
|
|
|
/*
|
|
* tell the world who our master is
|
|
*/
|
|
static void
|
|
setmaster(msg)
|
|
struct tsp *msg;
|
|
{
|
|
if (slavenet
|
|
&& (slavenet != old_slavenet
|
|
|| strcmp(msg->tsp_name, master_name)
|
|
|| old_status != status)) {
|
|
(void)strcpy(master_name, msg->tsp_name);
|
|
old_slavenet = slavenet;
|
|
old_status = status;
|
|
|
|
if (status & MASTER) {
|
|
syslog(LOG_NOTICE, "submaster to %s", master_name);
|
|
if (trace)
|
|
fprintf(fd, "submaster to %s\n", master_name);
|
|
|
|
} else {
|
|
syslog(LOG_NOTICE, "slave to %s", master_name);
|
|
if (trace)
|
|
fprintf(fd, "slave to %s\n", master_name);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
* handle date change request on a slave
|
|
*/
|
|
static void
|
|
schgdate(msg, newdate)
|
|
struct tsp *msg;
|
|
char *newdate;
|
|
{
|
|
struct tsp to;
|
|
u_short seq;
|
|
struct sockaddr_in taddr;
|
|
struct timeval otime;
|
|
|
|
if (!slavenet)
|
|
return; /* no where to forward */
|
|
|
|
taddr = from;
|
|
seq = msg->tsp_seq;
|
|
|
|
syslog(LOG_INFO,
|
|
"forwarding date change by %s to %s",
|
|
msg->tsp_name, newdate);
|
|
|
|
/* adjust time for residence on the queue */
|
|
(void)gettimeofday(&otime, 0);
|
|
adj_msg_time(msg, &otime);
|
|
|
|
to.tsp_type = TSP_SETDATEREQ;
|
|
to.tsp_time = msg->tsp_time;
|
|
(void)strcpy(to.tsp_name, hostname);
|
|
if (!acksend(&to, &slavenet->dest_addr,
|
|
ANYADDR, TSP_DATEACK,
|
|
slavenet, 0))
|
|
return; /* no answer */
|
|
|
|
xmit(TSP_DATEACK, seq, &taddr);
|
|
}
|
|
|
|
|
|
/*
|
|
* Used before answering a broadcast message to avoid network
|
|
* contention and likely collisions.
|
|
*/
|
|
static void
|
|
answerdelay()
|
|
{
|
|
#ifdef sgi
|
|
sginap(delay1);
|
|
#else
|
|
struct timeval timeout;
|
|
|
|
timeout.tv_sec = 0;
|
|
timeout.tv_usec = delay1;
|
|
|
|
(void)select(0, (fd_set *)NULL, (fd_set *)NULL, (fd_set *)NULL,
|
|
&timeout);
|
|
return;
|
|
#endif /* sgi */
|
|
}
|