slave.c revision 1553
125184Sjkh/*- 2113674Smtm * Copyright (c) 1985, 1993 3113674Smtm * The Regents of the University of California. All rights reserved. 4113674Smtm * 5113674Smtm * Redistribution and use in source and binary forms, with or without 6113674Smtm * modification, are permitted provided that the following conditions 7113674Smtm * are met: 8113674Smtm * 1. Redistributions of source code must retain the above copyright 9113674Smtm * notice, this list of conditions and the following disclaimer. 10113674Smtm * 2. Redistributions in binary form must reproduce the above copyright 11113674Smtm * notice, this list of conditions and the following disclaimer in the 12113674Smtm * documentation and/or other materials provided with the distribution. 13113674Smtm * 3. All advertising materials mentioning features or use of this software 14113674Smtm * must display the following acknowledgement: 15113674Smtm * This product includes software developed by the University of 16113674Smtm * California, Berkeley and its contributors. 17113674Smtm * 4. Neither the name of the University nor the names of its contributors 18113674Smtm * may be used to endorse or promote products derived from this software 19113674Smtm * without specific prior written permission. 20113674Smtm * 21113674Smtm * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22113674Smtm * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23113674Smtm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24113674Smtm * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2550472Speter * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2666830Sobrien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2725184Sjkh * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28113674Smtm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29113674Smtm * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30113674Smtm * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31113674Smtm * SUCH DAMAGE. 3225184Sjkh */ 33178356Ssam 34197147Shrs#ifndef lint 35197147Shrsstatic char sccsid[] = "@(#)slave.c 8.1 (Berkeley) 6/6/93"; 36178356Ssam#endif /* not lint */ 37178356Ssam 38178356Ssam#ifdef sgi 39178356Ssam#ident "$Revision: 1.20 $" 40178356Ssam#endif 41178356Ssam 42178356Ssam#include "globals.h" 43178356Ssam#include <setjmp.h> 44178356Ssam#include "pathnames.h" 45178356Ssam 46178356Ssamextern jmp_buf jmpenv; 47222515Sbzextern int Mflag; 48222515Sbzextern int justquit; 49222515Sbz 50197139Shrsextern u_short sequence; 51178356Ssam 52178356Ssamstatic char master_name[MAXHOSTNAMELEN+1]; 53178356Ssamstatic struct netinfo *old_slavenet; 54178356Ssamstatic int old_status; 55197139Shrs 56197147Shrsstatic void schgdate __P((struct tsp *, char *)); 57197147Shrsstatic void setmaster __P((struct tsp *)); 58178356Ssamstatic void answerdelay __P((void)); 59178356Ssam 60178356Ssam#ifdef sgi 61178356Ssamextern void logwtmp __P((struct timeval *, struct timeval *)); 62178356Ssam#else 63178356Ssamextern void logwtmp __P((char *, char *, char *)); 64178356Ssam#endif /* sgi */ 65197139Shrs 66178356Ssamint 67222515Sbzslave() 68222515Sbz{ 69222515Sbz int tries; 70178356Ssam long electiontime, refusetime, looktime, looptime, adjtime; 71178356Ssam u_short seq; 72197139Shrs long fastelection; 73178356Ssam#define FASTTOUT 3 74178356Ssam struct in_addr cadr; 75178356Ssam struct timeval otime; 76178356Ssam struct sockaddr_in taddr; 77113674Smtm char tname[MAXHOSTNAMELEN]; 78113674Smtm struct tsp *msg, to; 79113674Smtm struct timeval ntime, wait; 80113674Smtm struct tsp *answer; 81147088Sbrooks int timeout(); 82147088Sbrooks char olddate[32]; 83113674Smtm char newdate[32]; 84113674Smtm struct netinfo *ntp; 85113674Smtm struct hosttbl *htp; 86197139Shrs 87147088Sbrooks 88147088Sbrooks old_slavenet = 0; 89222515Sbz seq = 0; 90222515Sbz refusetime = 0; 91222515Sbz adjtime = 0; 92222515Sbz 93222515Sbz (void)gettimeofday(&ntime, 0); 94197139Shrs electiontime = ntime.tv_sec + delay2; 95147088Sbrooks fastelection = ntime.tv_sec + FASTTOUT; 96113674Smtm if (justquit) 97223506Spluknet looktime = electiontime; 98147088Sbrooks else 99113674Smtm looktime = fastelection; 100147088Sbrooks looptime = fastelection; 101197139Shrs 102197139Shrs if (slavenet) 103222733Shrs xmit(TSP_SLAVEUP, 0, &slavenet->dest_addr); 104222733Shrs if (status & MASTER) { 105222746Shrs for (ntp = nettab; ntp != NULL; ntp = ntp->next) { 106222733Shrs if (ntp->status == MASTER) 107212574Shrs masterup(ntp); 108197139Shrs } 109222733Shrs } 110222733Shrs 111222733Shrsloop: 112222733Shrs get_goodgroup(0); 113222733Shrs (void)gettimeofday(&ntime, (struct timezone *)0); 114222733Shrs if (ntime.tv_sec > electiontime) { 115222733Shrs if (trace) 116225521Shrs fprintf(fd, "election timer expired\n"); 117225521Shrs longjmp(jmpenv, 1); 118225521Shrs } 119225521Shrs 120225521Shrs if (ntime.tv_sec >= looktime) { 121225521Shrs if (trace) 122212574Shrs fprintf(fd, "Looking for nets to master\n"); 123212574Shrs 124197526Shrs if (Mflag && nignorednets > 0) { 125212574Shrs for (ntp = nettab; ntp != NULL; ntp = ntp->next) { 126212574Shrs if (ntp->status == IGNORE 127212574Shrs || ntp->status == NOMASTER) { 128212574Shrs lookformaster(ntp); 129225522Shrs if (ntp->status == MASTER) { 130225522Shrs masterup(ntp); 131225522Shrs } else if (ntp->status == MASTER) { 132225522Shrs ntp->status = NOMASTER; 133225522Shrs } 134225522Shrs } 135225522Shrs if (ntp->status == MASTER 136225522Shrs && --ntp->quit_count < 0) 137212574Shrs ntp->quit_count = 0; 138225522Shrs } 139212574Shrs makeslave(slavenet); /* prune extras */ 140212574Shrs setstatus(); 141212574Shrs } 142212574Shrs (void)gettimeofday(&ntime, 0); 143212574Shrs looktime = ntime.tv_sec + delay2; 144212574Shrs } 145212574Shrs if (ntime.tv_sec >= looptime) { 146212574Shrs if (trace) 147212574Shrs fprintf(fd, "Looking for loops\n"); 148225522Shrs for (ntp = nettab; ntp != NULL; ntp = ntp->next) { 149212574Shrs if (ntp->status == MASTER) { 150212574Shrs to.tsp_type = TSP_LOOP; 151197139Shrs to.tsp_vers = TSPVERSION; 152197139Shrs to.tsp_seq = sequence++; 153197139Shrs to.tsp_hopcnt = MAX_HOPCNT; 154197139Shrs (void)strcpy(to.tsp_name, hostname); 155197139Shrs bytenetorder(&to); 156197139Shrs if (sendto(sock, (char *)&to, sizeof(struct tsp), 0, 157147088Sbrooks (struct sockaddr*)&ntp->dest_addr, 158147682Sbrooks sizeof(ntp->dest_addr)) < 0) { 159147088Sbrooks trace_sendto_err(ntp->dest_addr.sin_addr); 160147088Sbrooks } 161147088Sbrooks } 162147088Sbrooks } 163149726Sbrooks (void)gettimeofday(&ntime, 0); 164149726Sbrooks looptime = ntime.tv_sec + delay2; 165149726Sbrooks } 166157706Sbrooks 167157706Sbrooks wait.tv_sec = min(electiontime,min(looktime,looptime)) - ntime.tv_sec; 168157706Sbrooks if (wait.tv_sec < 0) 169147088Sbrooks wait.tv_sec = 0; 170147088Sbrooks wait.tv_sec += FASTTOUT; 171147088Sbrooks wait.tv_usec = 0; 172147121Sbrooks msg = readmsg(TSP_ANY, ANYADDR, &wait, 0); 173113674Smtm 17425184Sjkh if (msg != NULL) { 175116029Smtm /* 176161386Sbrooks * filter stuff not for us 177161386Sbrooks */ 178116029Smtm switch (msg->tsp_type) { 179116029Smtm case TSP_SETDATE: 180116029Smtm case TSP_TRACEOFF: 181197139Shrs case TSP_TRACEON: 182147121Sbrooks /* 183116029Smtm * XXX check to see they are from ourself 184147088Sbrooks */ 185147682Sbrooks break; 186147121Sbrooks 187147088Sbrooks case TSP_TEST: 188147088Sbrooks case TSP_MSITE: 189147088Sbrooks break; 190147088Sbrooks 191147088Sbrooks case TSP_MASTERUP: 192147088Sbrooks if (!fromnet) { 193147088Sbrooks if (trace) { 194161386Sbrooks fprintf(fd, "slave ignored: "); 195161386Sbrooks print(msg, &from); 196161386Sbrooks } 197161386Sbrooks goto loop; 198157706Sbrooks } 199147121Sbrooks break; 200116029Smtm 201116029Smtm default: 202157706Sbrooks if (!fromnet 203197147Shrs || fromnet->status == IGNORE 204197147Shrs || fromnet->status == NOMASTER) { 205197147Shrs if (trace) { 206197147Shrs fprintf(fd, "slave ignored: "); 207197147Shrs print(msg, &from); 208157706Sbrooks } 209157706Sbrooks goto loop; 210212578Shrs } 211197139Shrs break; 212157706Sbrooks } 213157706Sbrooks 214157706Sbrooks 215157706Sbrooks /* 216157706Sbrooks * now process the message 217157706Sbrooks */ 218157736Sbrooks switch (msg->tsp_type) { 219157706Sbrooks 220157706Sbrooks case TSP_ADJTIME: 221157706Sbrooks if (fromnet != slavenet) 222157706Sbrooks break; 223157706Sbrooks if (!good_host_name(msg->tsp_name)) { 224157706Sbrooks syslog(LOG_NOTICE, 225157706Sbrooks "attempted time adjustment by %s", 226168033Sache msg->tsp_name); 227157706Sbrooks suppress(&from, msg->tsp_name, fromnet); 228157706Sbrooks break; 229197139Shrs } 230147088Sbrooks /* 231147088Sbrooks * Speed up loop detection in case we have a loop. 232147088Sbrooks * Otherwise the clocks can race until the loop 233147088Sbrooks * is found. 234147088Sbrooks */ 235212574Shrs (void)gettimeofday(&otime, 0); 236147088Sbrooks if (adjtime < otime.tv_sec) 237197139Shrs looptime -= (looptime-otime.tv_sec)/2 + 1; 238197139Shrs 239147088Sbrooks setmaster(msg); 240147088Sbrooks if (seq != msg->tsp_seq) { 241147088Sbrooks seq = msg->tsp_seq; 242147088Sbrooks synch(tvtomsround(msg->tsp_time)); 243212574Shrs } 244147088Sbrooks (void)gettimeofday(&ntime, 0); 245147088Sbrooks electiontime = ntime.tv_sec + delay2; 246197139Shrs fastelection = ntime.tv_sec + FASTTOUT; 247147088Sbrooks adjtime = ntime.tv_sec + SAMPLEINTVL*2; 248147088Sbrooks break; 249147088Sbrooks 250147088Sbrooks case TSP_SETTIME: 251197139Shrs if (fromnet != slavenet) 252197139Shrs break; 253147088Sbrooks if (seq == msg->tsp_seq) 254147088Sbrooks break; 255147088Sbrooks seq = msg->tsp_seq; 256147088Sbrooks 257147088Sbrooks /* adjust time for residence on the queue */ 258147088Sbrooks (void)gettimeofday(&otime, 0); 259147088Sbrooks adj_msg_time(msg,&otime); 260157706Sbrooks#ifdef sgi 261157706Sbrooks (void)cftime(newdate, "%D %T", &msg->tsp_time.tv_sec); 262157706Sbrooks (void)cftime(olddate, "%D %T", &otime.tv_sec); 263157706Sbrooks#else 264157706Sbrooks /* 265147088Sbrooks * the following line is necessary due to syslog 266147088Sbrooks * calling ctime() which clobbers the static buffer 267147088Sbrooks */ 268147088Sbrooks (void)strcpy(olddate, date()); 269147088Sbrooks (void)strcpy(newdate, ctime(&msg->tsp_time.tv_sec)); 270147088Sbrooks#endif /* sgi */ 271147088Sbrooks 272147088Sbrooks if (!good_host_name(msg->tsp_name)) { 273147088Sbrooks syslog(LOG_NOTICE, 274149401Sbrooks "attempted time setting by untrusted %s to %s", 275149401Sbrooks msg->tsp_name, newdate); 276149401Sbrooks suppress(&from, msg->tsp_name, fromnet); 277149401Sbrooks break; 278149401Sbrooks } 279197139Shrs 280149401Sbrooks setmaster(msg); 281197139Shrs timevalsub(&ntime, &msg->tsp_time, &otime); 282149401Sbrooks if (ntime.tv_sec < MAXADJ && ntime.tv_sec > -MAXADJ) { 283149401Sbrooks /* 284149401Sbrooks * do not change the clock if we can adjust it 285149401Sbrooks */ 286149401Sbrooks synch(tvtomsround(ntime)); 287149401Sbrooks } else { 288149401Sbrooks#ifdef sgi 289197139Shrs if (0 > settimeofday(&msg->tsp_time, 0)) { 290149401Sbrooks syslog(LOG_ERR,"settimeofdate(): %m"); 291149401Sbrooks break; 292149401Sbrooks } 293147088Sbrooks logwtmp(&otime, &msg->tsp_time); 294147088Sbrooks#else 295147088Sbrooks logwtmp("|", "date", ""); 296147088Sbrooks (void)settimeofday(&msg->tsp_time, 0); 297197139Shrs logwtmp("}", "date", ""); 298147088Sbrooks#endif /* sgi */ 299197139Shrs syslog(LOG_NOTICE, 300147088Sbrooks "date changed by %s from %s", 301147088Sbrooks msg->tsp_name, olddate); 302147088Sbrooks if (status & MASTER) 303147088Sbrooks spreadtime(); 304147088Sbrooks } 305157706Sbrooks (void)gettimeofday(&ntime, 0); 306157706Sbrooks electiontime = ntime.tv_sec + delay2; 307157706Sbrooks fastelection = ntime.tv_sec + FASTTOUT; 308157706Sbrooks 309157706Sbrooks/* This patches a bad protocol bug. Imagine a system with several networks, 310157706Sbrooks * where there are a pair of redundant gateways between a pair of networks, 311147088Sbrooks * each running timed. Assume that we start with a third machine mastering 312147088Sbrooks * one of the networks, and one of the gateways mastering the other. 313197139Shrs * Imagine that the third machine goes away and the non-master gateway 314147088Sbrooks * decides to replace it. If things are timed just 'right,' we will have 315147088Sbrooks * each gateway mastering one network for a little while. If a SETTIME 316147088Sbrooks * message gets into the network at that time, perhaps from the newly 317157706Sbrooks * masterful gateway as it was taking control, the SETTIME will loop 318157706Sbrooks * forever. Each time a gateway receives it on its slave side, it will 319157706Sbrooks * call spreadtime to forward it on its mastered network. We are now in 320157706Sbrooks * a permanent loop, since the SETTIME msgs will keep any clock 321157706Sbrooks * in the network from advancing. Normally, the 'LOOP' stuff will detect 322197139Shrs * and correct the situation. However, with the clocks stopped, the 323157706Sbrooks * 'looptime' timer cannot expire. While they are in this state, the 324197139Shrs * masters will try to saturate the network with SETTIME packets. 325157706Sbrooks */ 326157706Sbrooks looptime = ntime.tv_sec + (looptime-otime.tv_sec)/2-1; 327157706Sbrooks break; 328157706Sbrooks 329157706Sbrooks case TSP_MASTERUP: 330157706Sbrooks if (slavenet && fromnet != slavenet) 331157706Sbrooks break; 332157706Sbrooks if (!good_host_name(msg->tsp_name)) { 333157706Sbrooks suppress(&from, msg->tsp_name, fromnet); 334157706Sbrooks if (electiontime > fastelection) 335197139Shrs electiontime = fastelection; 336197139Shrs break; 337157706Sbrooks } 338157706Sbrooks makeslave(fromnet); 339147088Sbrooks setmaster(msg); 340147088Sbrooks setstatus(); 341147088Sbrooks answerdelay(); 342147088Sbrooks xmit(TSP_SLAVEUP, 0, &from); 343197139Shrs (void)gettimeofday(&ntime, 0); 344147088Sbrooks electiontime = ntime.tv_sec + delay2; 345197139Shrs fastelection = ntime.tv_sec + FASTTOUT; 346147088Sbrooks refusetime = 0; 347147088Sbrooks break; 348147088Sbrooks 349147088Sbrooks case TSP_MASTERREQ: 350147088Sbrooks if (fromnet->status != SLAVE) 351147088Sbrooks break; 352147088Sbrooks (void)gettimeofday(&ntime, 0); 353197139Shrs electiontime = ntime.tv_sec + delay2; 354147088Sbrooks break; 355147088Sbrooks 356147088Sbrooks case TSP_SETDATE: 357197139Shrs#ifdef sgi 358197139Shrs (void)cftime(newdate, "%D %T", &msg->tsp_time.tv_sec); 359197139Shrs#else 360197139Shrs (void)strcpy(newdate, ctime(&msg->tsp_time.tv_sec)); 361197139Shrs#endif /* sgi */ 362197139Shrs schgdate(msg, newdate); 363197139Shrs break; 364197139Shrs 365197139Shrs case TSP_SETDATEREQ: 366222996Shrs if (fromnet->status != MASTER) 367222996Shrs break; 368197139Shrs#ifdef sgi 369197697Shrs (void)cftime(newdate, "%D %T", &msg->tsp_time.tv_sec); 370197697Shrs#else 371197697Shrs (void)strcpy(newdate, ctime(&msg->tsp_time.tv_sec)); 372197697Shrs#endif /* sgi */ 373197697Shrs htp = findhost(msg->tsp_name); 374197697Shrs if (0 == htp) { 375197697Shrs syslog(LOG_WARNING, 376197697Shrs "DATEREQ from uncontrolled machine"); 377197697Shrs break; 378197697Shrs } 379197139Shrs if (!htp->good) { 380197139Shrs syslog(LOG_WARNING, 381197139Shrs "attempted date change by untrusted %s to %s", 382197139Shrs htp->name, newdate); 383197139Shrs spreadtime(); 384197139Shrs break; 385212574Shrs } 386212574Shrs schgdate(msg, newdate); 387212574Shrs break; 388212574Shrs 389212574Shrs case TSP_TRACEON: 390212574Shrs traceon(); 391212574Shrs break; 392212574Shrs 393212574Shrs case TSP_TRACEOFF: 394212574Shrs traceoff("Tracing ended at %s\n"); 395212574Shrs break; 396212574Shrs 397212574Shrs case TSP_SLAVEUP: 398212577Shrs newslave(msg); 399212574Shrs break; 400212574Shrs 401212574Shrs case TSP_ELECTION: 402212574Shrs if (fromnet->status == SLAVE) { 403212574Shrs (void)gettimeofday(&ntime, 0); 404212574Shrs electiontime = ntime.tv_sec + delay2; 405212574Shrs fastelection = ntime.tv_sec + FASTTOUT; 406212574Shrs seq = 0; 407212574Shrs if (!good_host_name(msg->tsp_name)) { 408212574Shrs syslog(LOG_NOTICE, 409212574Shrs "suppress election of %s", 410212574Shrs msg->tsp_name); 411212574Shrs to.tsp_type = TSP_QUIT; 412162490Sbrooks electiontime = fastelection; 413162490Sbrooks } else if (cadr.s_addr != from.sin_addr.s_addr 414162490Sbrooks && ntime.tv_sec < refusetime) { 415162490Sbrooks/* if the candidate has to repeat itself, the old code would refuse it 416162490Sbrooks * the second time. That would prevent elections. 417212574Shrs */ 418212574Shrs to.tsp_type = TSP_REFUSE; 419212574Shrs } else { 420197139Shrs cadr.s_addr = from.sin_addr.s_addr; 421162490Sbrooks to.tsp_type = TSP_ACCEPT; 422162490Sbrooks refusetime = ntime.tv_sec + 30; 423197139Shrs } 424197139Shrs taddr = from; 425212574Shrs (void)strcpy(tname, msg->tsp_name); 426197139Shrs (void)strcpy(to.tsp_name, hostname); 427197139Shrs answerdelay(); 428197139Shrs if (!acksend(&to, &taddr, tname, 429197139Shrs TSP_ACK, 0, 0)) 430197139Shrs syslog(LOG_WARNING, 431212574Shrs "no answer from candidate %s\n", 432212575Shrs tname); 433212575Shrs 434212575Shrs } else { /* fromnet->status == MASTER */ 435212575Shrs htp = addmach(msg->tsp_name, &from,fromnet); 436212575Shrs to.tsp_type = TSP_QUIT; 437212575Shrs (void)strcpy(to.tsp_name, hostname); 438197139Shrs if (!acksend(&to, &htp->addr, htp->name, 439212575Shrs TSP_ACK, 0, htp->noanswer)) { 440212575Shrs syslog(LOG_ERR, 441212575Shrs "no reply from %s to ELECTION-QUIT", 442212574Shrs htp->name); 443212574Shrs (void)remmach(htp); 444212575Shrs } 445212575Shrs } 446197139Shrs break; 447162490Sbrooks 448162490Sbrooks case TSP_CONFLICT: 449162490Sbrooks if (fromnet->status != MASTER) 450197139Shrs break; 451197139Shrs /* 452197139Shrs * After a network partition, there can be 453197139Shrs * more than one master: the first slave to 454197139Shrs * come up will notify here the situation. 455197139Shrs */ 456197139Shrs (void)strcpy(to.tsp_name, hostname); 457197139Shrs 458212577Shrs /* The other master often gets into the same state, 459212577Shrs * with boring results. 460212577Shrs */ 461212577Shrs ntp = fromnet; /* (acksend() can leave fromnet=0 */ 462212577Shrs for (tries = 0; tries < 3; tries++) { 463212577Shrs to.tsp_type = TSP_RESOLVE; 464197139Shrs answer = acksend(&to, &ntp->dest_addr, 465212577Shrs ANYADDR, TSP_MASTERACK, 466212577Shrs ntp, 0); 467212574Shrs if (answer == NULL) 468212574Shrs break; 469212574Shrs htp = addmach(answer->tsp_name,&from,ntp); 470212577Shrs to.tsp_type = TSP_QUIT; 471212577Shrs answer = acksend(&to, &htp->addr, htp->name, 472212577Shrs TSP_ACK, 0, htp->noanswer); 473197139Shrs if (!answer) { 474197139Shrs syslog(LOG_WARNING, 475197139Shrs "conflict error: no reply from %s to QUIT", 476197526Shrs htp->name); 477197526Shrs (void)remmach(htp); 478197526Shrs } 479197526Shrs } 480212574Shrs masterup(ntp); 481212574Shrs break; 482212577Shrs 483197526Shrs case TSP_MSITE: 484212577Shrs if (!slavenet) 485197526Shrs break; 486197526Shrs taddr = from; 487212574Shrs to.tsp_type = TSP_MSITEREQ; 488212574Shrs to.tsp_vers = TSPVERSION; 489212574Shrs to.tsp_seq = 0; 490212574Shrs (void)strcpy(to.tsp_name, hostname); 491212574Shrs answer = acksend(&to, &slavenet->dest_addr, 492212574Shrs ANYADDR, TSP_ACK, 493212574Shrs slavenet, 0); 494212574Shrs if (answer != NULL 495212574Shrs && good_host_name(answer->tsp_name)) { 496212574Shrs setmaster(answer); 497212574Shrs to.tsp_type = TSP_ACK; 498212574Shrs (void)strcpy(to.tsp_name, answer->tsp_name); 499212574Shrs bytenetorder(&to); 500212574Shrs if (sendto(sock, (char *)&to, 501212574Shrs sizeof(struct tsp), 0, 502212574Shrs (struct sockaddr*)&taddr, sizeof(taddr)) < 0) { 503212574Shrs trace_sendto_err(taddr.sin_addr); 504212574Shrs } 505212574Shrs } 506197139Shrs break; 507197139Shrs 508197139Shrs case TSP_MSITEREQ: 509161386Sbrooks break; 510161386Sbrooks 511161386Sbrooks case TSP_ACCEPT: 512161386Sbrooks case TSP_REFUSE: 513197139Shrs case TSP_RESOLVE: 514169889Sthompsa break; 515161386Sbrooks 516161386Sbrooks case TSP_QUIT: 517152441Sbrooks doquit(msg); /* become a slave */ 518212578Shrs break; 519152441Sbrooks 520152441Sbrooks case TSP_TEST: 521197139Shrs electiontime = 0; 522152441Sbrooks break; 523197139Shrs 524197139Shrs case TSP_LOOP: 525222515Sbz /* looking for loops of masters */ 526222515Sbz if (!(status & MASTER)) 527222515Sbz break; 528222515Sbz if (fromnet->status == SLAVE) { 529222515Sbz if (!strcmp(msg->tsp_name, hostname)) { 530222515Sbz /* 531222515Sbz * Someone forwarded our message back to 532197139Shrs * us. There must be a loop. Tell the 533197139Shrs * master of this network to quit. 534197139Shrs * 535197139Shrs * The other master often gets into 536152441Sbrooks * the same state, with boring results. 537152441Sbrooks */ 538197139Shrs ntp = fromnet; 539197139Shrs for (tries = 0; tries < 3; tries++) { 540197139Shrs to.tsp_type = TSP_RESOLVE; 541197139Shrs answer = acksend(&to, &ntp->dest_addr, 542197139Shrs ANYADDR, TSP_MASTERACK, 543197139Shrs ntp,0); 544197139Shrs if (answer == NULL) 545197139Shrs break; 546197139Shrs taddr = from; 547197139Shrs (void)strcpy(tname, answer->tsp_name); 548197139Shrs to.tsp_type = TSP_QUIT; 549197139Shrs (void)strcpy(to.tsp_name, hostname); 550197139Shrs if (!acksend(&to, &taddr, tname, 551197139Shrs TSP_ACK, 0, 1)) { 552197139Shrs syslog(LOG_ERR, 553197139Shrs "no reply from %s to slave LOOP-QUIT", 554197139Shrs tname); 555197139Shrs } else { 556197139Shrs electiontime = 0; 557197139Shrs } 558197139Shrs } 559197139Shrs (void)gettimeofday(&ntime, 0); 560197139Shrs looptime = ntime.tv_sec + FASTTOUT; 561152441Sbrooks } else { 562197147Shrs if (msg->tsp_hopcnt-- < 1) 563152441Sbrooks break; 564152441Sbrooks bytenetorder(msg); 565197139Shrs for (ntp = nettab; ntp != 0; ntp = ntp->next) { 566152441Sbrooks if (ntp->status == MASTER 567161386Sbrooks && 0 > sendto(sock, (char *)msg, 568161386Sbrooks sizeof(struct tsp), 0, 569161386Sbrooks (struct sockaddr*)&ntp->dest_addr, 570161386Sbrooks sizeof(ntp->dest_addr))) 571161386Sbrooks trace_sendto_err(ntp->dest_addr.sin_addr); 572161386Sbrooks } 573161386Sbrooks } 574161386Sbrooks } else { /* fromnet->status == MASTER */ 575161386Sbrooks /* 576161386Sbrooks * We should not have received this from a net 577161386Sbrooks * we are master on. There must be two masters, 578161386Sbrooks * unless the packet was really from us. 579161386Sbrooks */ 580161386Sbrooks if (from.sin_addr.s_addr 581161386Sbrooks == fromnet->my_addr.s_addr) { 582161386Sbrooks if (trace) 583161386Sbrooks fprintf(fd,"discarding forwarded LOOP\n"); 584161386Sbrooks break; 585161386Sbrooks } 586161386Sbrooks 587197139Shrs /* 588161386Sbrooks * The other master often gets into the same 589161386Sbrooks * state, with boring results. 590161386Sbrooks */ 591152441Sbrooks ntp = fromnet; 592152441Sbrooks for (tries = 0; tries < 3; tries++) { 593197139Shrs to.tsp_type = TSP_RESOLVE; 594197139Shrs answer = acksend(&to, &ntp->dest_addr, 595197139Shrs ANYADDR, TSP_MASTERACK, 596197139Shrs ntp,0); 597197139Shrs if (!answer) 598197139Shrs break; 599197139Shrs htp = addmach(answer->tsp_name, 600197139Shrs &from,ntp); 601197139Shrs to.tsp_type = TSP_QUIT; 602197139Shrs (void)strcpy(to.tsp_name, hostname); 603197139Shrs if (!acksend(&to,&htp->addr,htp->name, 604197139Shrs TSP_ACK, 0, htp->noanswer)) { 605197139Shrs syslog(LOG_ERR, 606197139Shrs "no reply from %s to master LOOP-QUIT", 607197139Shrs htp->name); 608197139Shrs (void)remmach(htp); 609197139Shrs } 610197139Shrs } 611197139Shrs (void)gettimeofday(&ntime, 0); 612197139Shrs looptime = ntime.tv_sec + FASTTOUT; 613197139Shrs } 614197139Shrs break; 615197139Shrs default: 616197139Shrs if (trace) { 617197139Shrs fprintf(fd, "garbage message: "); 618197139Shrs print(msg, &from); 619197139Shrs } 620197139Shrs break; 621197139Shrs } 622197139Shrs } 623197139Shrs goto loop; 624197139Shrs} 625197139Shrs 626197139Shrs 627197139Shrs/* 628197139Shrs * tell the world who our master is 629152441Sbrooks */ 630197147Shrsstatic void 631197147Shrssetmaster(msg) 632152441Sbrooks struct tsp *msg; 633197147Shrs{ 634197139Shrs if (slavenet 635212578Shrs && (slavenet != old_slavenet 636152441Sbrooks || strcmp(msg->tsp_name, master_name) 637152441Sbrooks || old_status != status)) { 638152441Sbrooks (void)strcpy(master_name, msg->tsp_name); 639212578Shrs old_slavenet = slavenet; 640152441Sbrooks old_status = status; 641157706Sbrooks 642212578Shrs if (status & MASTER) { 643152441Sbrooks syslog(LOG_NOTICE, "submaster to %s", master_name); 644152441Sbrooks if (trace) 645152441Sbrooks fprintf(fd, "submaster to %s\n", master_name); 646152441Sbrooks 647152441Sbrooks } else { 648152441Sbrooks syslog(LOG_NOTICE, "slave to %s", master_name); 649152441Sbrooks if (trace) 650152441Sbrooks fprintf(fd, "slave to %s\n", master_name); 651152441Sbrooks } 652152441Sbrooks } 653152441Sbrooks} 654152441Sbrooks 655212578Shrs 656152441Sbrooks 657152441Sbrooks/* 658152441Sbrooks * handle date change request on a slave 659152441Sbrooks */ 660152441Sbrooksstatic void 661152441Sbrooksschgdate(msg, newdate) 662152441Sbrooks struct tsp *msg; 663152441Sbrooks char *newdate; 664152441Sbrooks{ 665152441Sbrooks struct tsp to; 666152441Sbrooks u_short seq; 667152441Sbrooks struct sockaddr_in taddr; 668197139Shrs struct timeval otime; 669152441Sbrooks 670152441Sbrooks if (!slavenet) 671152441Sbrooks return; /* no where to forward */ 672197139Shrs 673113674Smtm taddr = from; 674113674Smtm seq = msg->tsp_seq; 675113674Smtm 676113674Smtm syslog(LOG_INFO, 677113674Smtm "forwarding date change by %s to %s", 678113674Smtm msg->tsp_name, newdate); 679197139Shrs 680113674Smtm /* adjust time for residence on the queue */ 681197139Shrs (void)gettimeofday(&otime, 0); 682197139Shrs adj_msg_time(msg, &otime); 683197139Shrs 684197139Shrs to.tsp_type = TSP_SETDATEREQ; 685197139Shrs to.tsp_time = msg->tsp_time; 686197139Shrs (void)strcpy(to.tsp_name, hostname); 687197139Shrs if (!acksend(&to, &slavenet->dest_addr, 688197139Shrs ANYADDR, TSP_DATEACK, 689197139Shrs slavenet, 0)) 690197139Shrs return; /* no answer */ 691197139Shrs 692197139Shrs xmit(TSP_DATEACK, seq, &taddr); 693197139Shrs} 694197139Shrs 695197139Shrs 696197139Shrs/* 697197139Shrs * Used before answering a broadcast message to avoid network 698197139Shrs * contention and likely collisions. 699197139Shrs */ 700197139Shrsstatic void 701197139Shrsanswerdelay() 702197139Shrs{ 703113674Smtm#ifdef sgi 704113674Smtm sginap(delay1); 705157706Sbrooks#else 706197139Shrs struct timeval timeout; 707197139Shrs 708197139Shrs timeout.tv_sec = 0; 709197139Shrs timeout.tv_usec = delay1; 710197139Shrs 711197139Shrs (void)select(0, (fd_set *)NULL, (fd_set *)NULL, (fd_set *)NULL, 712197139Shrs &timeout); 713197139Shrs return; 714197147Shrs#endif /* sgi */ 715197139Shrs} 716197139Shrs