slave.c revision 30830
159191Skris/*- 255714Skris * Copyright (c) 1985, 1993 355714Skris * The Regents of the University of California. All rights reserved. 455714Skris * 555714Skris * Redistribution and use in source and binary forms, with or without 655714Skris * modification, are permitted provided that the following conditions 755714Skris * are met: 8280297Sjkim * 1. Redistributions of source code must retain the above copyright 955714Skris * notice, this list of conditions and the following disclaimer. 1055714Skris * 2. Redistributions in binary form must reproduce the above copyright 1155714Skris * notice, this list of conditions and the following disclaimer in the 1255714Skris * documentation and/or other materials provided with the distribution. 1355714Skris * 3. All advertising materials mentioning features or use of this software 1455714Skris * must display the following acknowledgement: 15280297Sjkim * This product includes software developed by the University of 1655714Skris * California, Berkeley and its contributors. 1755714Skris * 4. Neither the name of the University nor the names of its contributors 1855714Skris * may be used to endorse or promote products derived from this software 1955714Skris * without specific prior written permission. 2055714Skris * 2155714Skris * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22280297Sjkim * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2355714Skris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2455714Skris * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2555714Skris * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2655714Skris * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2755714Skris * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2855714Skris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2955714Skris * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3055714Skris * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3155714Skris * SUCH DAMAGE. 3255714Skris */ 3355714Skris 3455714Skris#ifndef lint 3555714Skris#if 0 3655714Skrisstatic char sccsid[] = "@(#)slave.c 8.1 (Berkeley) 6/6/93"; 37280297Sjkim#endif 3855714Skrisstatic const char rcsid[] = 3955714Skris "$Id: slave.c,v 1.3 1997/10/22 06:19:48 charnier Exp $"; 40280297Sjkim#endif /* not lint */ 4155714Skris 4255714Skris#include "globals.h" 4355714Skris#include <setjmp.h> 4455714Skris#include "pathnames.h" 4555714Skris 4655714Skrisextern jmp_buf jmpenv; 4755714Skrisextern int Mflag; 4855714Skrisextern int justquit; 4955714Skris 5055714Skrisextern u_short sequence; 5155714Skris 52280297Sjkimstatic char master_name[MAXHOSTNAMELEN+1]; 5355714Skrisstatic struct netinfo *old_slavenet; 5455714Skrisstatic int old_status; 5555714Skris 5655714Skrisstatic void schgdate __P((struct tsp *, char *)); 5755714Skrisstatic void setmaster __P((struct tsp *)); 5855714Skrisstatic void answerdelay __P((void)); 5955714Skris 60280297Sjkim#ifdef sgi 61194206Ssimonextern void logwtmp __P((struct timeval *, struct timeval *)); 6255714Skris#else 63280297Sjkimextern void logwtmp __P((char *, char *, char *)); 64194206Ssimon#endif /* sgi */ 6555714Skris 66280297Sjkimint 67325335Sjkimslave() 68325335Sjkim{ 69325335Sjkim int tries; 70325335Sjkim long electiontime, refusetime, looktime, looptime, adjtime; 71325335Sjkim u_short seq; 72325335Sjkim long fastelection; 73325335Sjkim#define FASTTOUT 3 7455714Skris struct in_addr cadr; 75325335Sjkim struct timeval otime; 76325335Sjkim struct sockaddr_in taddr; 77325335Sjkim char tname[MAXHOSTNAMELEN]; 78325335Sjkim struct tsp *msg, to; 79325335Sjkim struct timeval ntime, wait; 80325335Sjkim struct tsp *answer; 81325335Sjkim int timeout(); 82325335Sjkim char olddate[32]; 83325335Sjkim char newdate[32]; 84325335Sjkim struct netinfo *ntp; 85325335Sjkim struct hosttbl *htp; 86325335Sjkim 87325335Sjkim 88325335Sjkim old_slavenet = 0; 89325335Sjkim seq = 0; 90325335Sjkim refusetime = 0; 91325335Sjkim adjtime = 0; 92325335Sjkim 93325335Sjkim (void)gettimeofday(&ntime, 0); 94325335Sjkim electiontime = ntime.tv_sec + delay2; 95325335Sjkim fastelection = ntime.tv_sec + FASTTOUT; 96325335Sjkim if (justquit) 97325335Sjkim looktime = electiontime; 98325335Sjkim else 99325335Sjkim looktime = fastelection; 100325335Sjkim looptime = fastelection; 101325335Sjkim 102325335Sjkim if (slavenet) 103325335Sjkim xmit(TSP_SLAVEUP, 0, &slavenet->dest_addr); 104325335Sjkim if (status & MASTER) { 105325335Sjkim for (ntp = nettab; ntp != NULL; ntp = ntp->next) { 106325335Sjkim if (ntp->status == MASTER) 107325335Sjkim masterup(ntp); 108325335Sjkim } 109325335Sjkim } 110325335Sjkim 111325335Sjkimloop: 112325335Sjkim get_goodgroup(0); 113325335Sjkim (void)gettimeofday(&ntime, (struct timezone *)0); 114325335Sjkim if (ntime.tv_sec > electiontime) { 115325335Sjkim if (trace) 116325335Sjkim fprintf(fd, "election timer expired\n"); 117325335Sjkim longjmp(jmpenv, 1); 118325335Sjkim } 119325335Sjkim 120325335Sjkim if (ntime.tv_sec >= looktime) { 121325335Sjkim if (trace) 122325335Sjkim fprintf(fd, "Looking for nets to master\n"); 123325335Sjkim 124325335Sjkim if (Mflag && nignorednets > 0) { 125325335Sjkim for (ntp = nettab; ntp != NULL; ntp = ntp->next) { 126325335Sjkim if (ntp->status == IGNORE 127325335Sjkim || ntp->status == NOMASTER) { 128325335Sjkim lookformaster(ntp); 129325335Sjkim if (ntp->status == MASTER) { 130325335Sjkim masterup(ntp); 131325335Sjkim } else if (ntp->status == MASTER) { 132325335Sjkim ntp->status = NOMASTER; 133325335Sjkim } 134325335Sjkim } 135325335Sjkim if (ntp->status == MASTER 136325335Sjkim && --ntp->quit_count < 0) 137325335Sjkim ntp->quit_count = 0; 138325335Sjkim } 139325335Sjkim makeslave(slavenet); /* prune extras */ 140325335Sjkim setstatus(); 141325335Sjkim } 142325335Sjkim (void)gettimeofday(&ntime, 0); 143325335Sjkim looktime = ntime.tv_sec + delay2; 144325335Sjkim } 145325335Sjkim if (ntime.tv_sec >= looptime) { 146325335Sjkim if (trace) 147325335Sjkim fprintf(fd, "Looking for loops\n"); 148325335Sjkim for (ntp = nettab; ntp != NULL; ntp = ntp->next) { 149325335Sjkim if (ntp->status == MASTER) { 150325335Sjkim to.tsp_type = TSP_LOOP; 151325335Sjkim to.tsp_vers = TSPVERSION; 152325335Sjkim to.tsp_seq = sequence++; 153325335Sjkim to.tsp_hopcnt = MAX_HOPCNT; 154325335Sjkim (void)strcpy(to.tsp_name, hostname); 155325335Sjkim bytenetorder(&to); 156325335Sjkim if (sendto(sock, (char *)&to, sizeof(struct tsp), 0, 157325335Sjkim (struct sockaddr*)&ntp->dest_addr, 158325335Sjkim sizeof(ntp->dest_addr)) < 0) { 159325335Sjkim trace_sendto_err(ntp->dest_addr.sin_addr); 160325335Sjkim } 161325335Sjkim } 162325335Sjkim } 163325335Sjkim (void)gettimeofday(&ntime, 0); 164325335Sjkim looptime = ntime.tv_sec + delay2; 165325335Sjkim } 166325335Sjkim 167325335Sjkim wait.tv_sec = min(electiontime,min(looktime,looptime)) - ntime.tv_sec; 168325335Sjkim if (wait.tv_sec < 0) 169325335Sjkim wait.tv_sec = 0; 170325335Sjkim wait.tv_sec += FASTTOUT; 171325335Sjkim wait.tv_usec = 0; 172325335Sjkim msg = readmsg(TSP_ANY, ANYADDR, &wait, 0); 173325335Sjkim 174325335Sjkim if (msg != NULL) { 175325335Sjkim /* 176325335Sjkim * filter stuff not for us 177325335Sjkim */ 178325335Sjkim switch (msg->tsp_type) { 179325335Sjkim case TSP_SETDATE: 180325335Sjkim case TSP_TRACEOFF: 181325335Sjkim case TSP_TRACEON: 182325335Sjkim /* 183325335Sjkim * XXX check to see they are from ourself 184325335Sjkim */ 185325335Sjkim break; 186325335Sjkim 187325335Sjkim case TSP_TEST: 188325335Sjkim case TSP_MSITE: 189325335Sjkim break; 190325335Sjkim 191325335Sjkim case TSP_MASTERUP: 192325335Sjkim if (!fromnet) { 193325335Sjkim if (trace) { 194325335Sjkim fprintf(fd, "slave ignored: "); 195325335Sjkim print(msg, &from); 196325335Sjkim } 197325335Sjkim goto loop; 198325335Sjkim } 199325335Sjkim break; 200325335Sjkim 201325335Sjkim default: 202325335Sjkim if (!fromnet 203325335Sjkim || fromnet->status == IGNORE 204325335Sjkim || fromnet->status == NOMASTER) { 205325335Sjkim if (trace) { 206325335Sjkim fprintf(fd, "slave ignored: "); 207325335Sjkim print(msg, &from); 208325335Sjkim } 209325335Sjkim goto loop; 210325335Sjkim } 211325335Sjkim break; 212325335Sjkim } 213325335Sjkim 214325335Sjkim 215325335Sjkim /* 216325335Sjkim * now process the message 217325335Sjkim */ 218325335Sjkim switch (msg->tsp_type) { 219325335Sjkim 220325335Sjkim case TSP_ADJTIME: 221325335Sjkim if (fromnet != slavenet) 222325335Sjkim break; 223325335Sjkim if (!good_host_name(msg->tsp_name)) { 224325335Sjkim syslog(LOG_NOTICE, 225325335Sjkim "attempted time adjustment by %s", 226325335Sjkim msg->tsp_name); 227325335Sjkim suppress(&from, msg->tsp_name, fromnet); 228325335Sjkim break; 229325335Sjkim } 230325335Sjkim /* 231325335Sjkim * Speed up loop detection in case we have a loop. 232325335Sjkim * Otherwise the clocks can race until the loop 233325335Sjkim * is found. 234325335Sjkim */ 235325335Sjkim (void)gettimeofday(&otime, 0); 236325335Sjkim if (adjtime < otime.tv_sec) 237325335Sjkim looptime -= (looptime-otime.tv_sec)/2 + 1; 238325335Sjkim 239325335Sjkim setmaster(msg); 240325335Sjkim if (seq != msg->tsp_seq) { 241325335Sjkim seq = msg->tsp_seq; 242325335Sjkim synch(tvtomsround(msg->tsp_time)); 243325335Sjkim } 244325335Sjkim (void)gettimeofday(&ntime, 0); 245325335Sjkim electiontime = ntime.tv_sec + delay2; 246325335Sjkim fastelection = ntime.tv_sec + FASTTOUT; 247325335Sjkim adjtime = ntime.tv_sec + SAMPLEINTVL*2; 248325335Sjkim break; 249325335Sjkim 250325335Sjkim case TSP_SETTIME: 251325335Sjkim if (fromnet != slavenet) 252325335Sjkim break; 253325335Sjkim if (seq == msg->tsp_seq) 254325335Sjkim break; 255325335Sjkim seq = msg->tsp_seq; 256325335Sjkim 257325335Sjkim /* adjust time for residence on the queue */ 258325335Sjkim (void)gettimeofday(&otime, 0); 259325335Sjkim adj_msg_time(msg,&otime); 260325335Sjkim#ifdef sgi 261325335Sjkim (void)cftime(newdate, "%D %T", &msg->tsp_time.tv_sec); 262325335Sjkim (void)cftime(olddate, "%D %T", &otime.tv_sec); 263325335Sjkim#else 264325335Sjkim /* 265325335Sjkim * the following line is necessary due to syslog 266325335Sjkim * calling ctime() which clobbers the static buffer 267325335Sjkim */ 268325335Sjkim (void)strcpy(olddate, date()); 269325335Sjkim (void)strcpy(newdate, ctime(&msg->tsp_time.tv_sec)); 270325335Sjkim#endif /* sgi */ 271325335Sjkim 272325335Sjkim if (!good_host_name(msg->tsp_name)) { 273325335Sjkim syslog(LOG_NOTICE, 274325335Sjkim "attempted time setting by untrusted %s to %s", 275325335Sjkim msg->tsp_name, newdate); 276325335Sjkim suppress(&from, msg->tsp_name, fromnet); 277325335Sjkim break; 278325335Sjkim } 279325335Sjkim 280325335Sjkim setmaster(msg); 281325335Sjkim timevalsub(&ntime, &msg->tsp_time, &otime); 282325335Sjkim if (ntime.tv_sec < MAXADJ && ntime.tv_sec > -MAXADJ) { 283325335Sjkim /* 284325335Sjkim * do not change the clock if we can adjust it 285325335Sjkim */ 286325335Sjkim synch(tvtomsround(ntime)); 287325335Sjkim } else { 288325335Sjkim#ifdef sgi 289325335Sjkim if (0 > settimeofday(&msg->tsp_time, 0)) { 290325335Sjkim syslog(LOG_ERR,"settimeofdate(): %m"); 291325335Sjkim break; 292325335Sjkim } 293325335Sjkim logwtmp(&otime, &msg->tsp_time); 294325335Sjkim#else 295325335Sjkim logwtmp("|", "date", ""); 296325335Sjkim (void)settimeofday(&msg->tsp_time, 0); 297325335Sjkim logwtmp("{", "date", ""); 298325335Sjkim#endif /* sgi */ 299325335Sjkim syslog(LOG_NOTICE, 300325335Sjkim "date changed by %s from %s", 301325335Sjkim msg->tsp_name, olddate); 302325335Sjkim if (status & MASTER) 303325335Sjkim spreadtime(); 304325335Sjkim } 305325335Sjkim (void)gettimeofday(&ntime, 0); 306325335Sjkim electiontime = ntime.tv_sec + delay2; 307325335Sjkim fastelection = ntime.tv_sec + FASTTOUT; 308325335Sjkim 309325335Sjkim/* This patches a bad protocol bug. Imagine a system with several networks, 310325335Sjkim * where there are a pair of redundant gateways between a pair of networks, 311325335Sjkim * each running timed. Assume that we start with a third machine mastering 312325335Sjkim * one of the networks, and one of the gateways mastering the other. 313325335Sjkim * Imagine that the third machine goes away and the non-master gateway 314325335Sjkim * decides to replace it. If things are timed just 'right,' we will have 315325335Sjkim * each gateway mastering one network for a little while. If a SETTIME 316325335Sjkim * message gets into the network at that time, perhaps from the newly 317325335Sjkim * masterful gateway as it was taking control, the SETTIME will loop 318325335Sjkim * forever. Each time a gateway receives it on its slave side, it will 319325335Sjkim * call spreadtime to forward it on its mastered network. We are now in 320325335Sjkim * a permanent loop, since the SETTIME msgs will keep any clock 321325335Sjkim * in the network from advancing. Normally, the 'LOOP' stuff will detect 322325335Sjkim * and correct the situation. However, with the clocks stopped, the 323325335Sjkim * 'looptime' timer cannot expire. While they are in this state, the 324325335Sjkim * masters will try to saturate the network with SETTIME packets. 32555714Skris */ 326280297Sjkim looptime = ntime.tv_sec + (looptime-otime.tv_sec)/2-1; 327 break; 328 329 case TSP_MASTERUP: 330 if (slavenet && fromnet != slavenet) 331 break; 332 if (!good_host_name(msg->tsp_name)) { 333 suppress(&from, msg->tsp_name, fromnet); 334 if (electiontime > fastelection) 335 electiontime = fastelection; 336 break; 337 } 338 makeslave(fromnet); 339 setmaster(msg); 340 setstatus(); 341 answerdelay(); 342 xmit(TSP_SLAVEUP, 0, &from); 343 (void)gettimeofday(&ntime, 0); 344 electiontime = ntime.tv_sec + delay2; 345 fastelection = ntime.tv_sec + FASTTOUT; 346 refusetime = 0; 347 break; 348 349 case TSP_MASTERREQ: 350 if (fromnet->status != SLAVE) 351 break; 352 (void)gettimeofday(&ntime, 0); 353 electiontime = ntime.tv_sec + delay2; 354 break; 355 356 case TSP_SETDATE: 357#ifdef sgi 358 (void)cftime(newdate, "%D %T", &msg->tsp_time.tv_sec); 359#else 360 (void)strcpy(newdate, ctime(&msg->tsp_time.tv_sec)); 361#endif /* sgi */ 362 schgdate(msg, newdate); 363 break; 364 365 case TSP_SETDATEREQ: 366 if (fromnet->status != MASTER) 367 break; 368#ifdef sgi 369 (void)cftime(newdate, "%D %T", &msg->tsp_time.tv_sec); 370#else 371 (void)strcpy(newdate, ctime(&msg->tsp_time.tv_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 */ 631static void 632setmaster(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 */ 661static void 662schgdate(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 */ 701static void 702answerdelay() 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} 717