|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1985 Regents of the University of California. ! 3: * All rights reserved. ! 4: * ! 5: * Redistribution and use in source and binary forms are permitted ! 6: * provided that the above copyright notice and this paragraph are ! 7: * duplicated in all such forms and that any documentation, ! 8: * advertising materials, and other materials related to such ! 9: * distribution and use acknowledge that the software was developed ! 10: * by the University of California, Berkeley. The name of the ! 11: * University may not be used to endorse or promote products derived ! 12: * from this software without specific prior written permission. ! 13: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR ! 14: * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED ! 15: * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. ! 16: */ ! 17: ! 18: #ifndef lint ! 19: static char sccsid[] = "@(#)slave.c 2.18 (Berkeley) 6/18/88"; ! 20: #endif /* not lint */ ! 21: ! 22: #include "globals.h" ! 23: #include <protocols/timed.h> ! 24: #include <setjmp.h> ! 25: ! 26: extern jmp_buf jmpenv; ! 27: ! 28: extern u_short sequence; ! 29: ! 30: slave() ! 31: { ! 32: int length; ! 33: int senddateack; ! 34: long electiontime, refusetime, looktime; ! 35: u_short seq; ! 36: char candidate[MAXHOSTNAMELEN]; ! 37: struct tsp *msg, to, *readmsg(); ! 38: struct sockaddr_in saveaddr, msaveaddr; ! 39: struct timeval wait; ! 40: struct timeval time, otime; ! 41: struct tsp *answer, *acksend(); ! 42: int timeout(); ! 43: char *date(); ! 44: long casual(); ! 45: int bytenetorder(); ! 46: char olddate[32]; ! 47: struct sockaddr_in server; ! 48: register struct netinfo *ntp; ! 49: int ind; ! 50: struct tsp resp; ! 51: extern int Mflag; ! 52: extern int justquit; ! 53: #ifdef MEASURE ! 54: extern FILE *fp; ! 55: #endif ! 56: if (slavenet) { ! 57: resp.tsp_type = TSP_SLAVEUP; ! 58: resp.tsp_vers = TSPVERSION; ! 59: (void)strcpy(resp.tsp_name, hostname); ! 60: bytenetorder(&resp); ! 61: if (sendto(sock, (char *)&resp, sizeof(struct tsp), 0, ! 62: &slavenet->dest_addr, sizeof(struct sockaddr_in)) < 0) { ! 63: syslog(LOG_ERR, "sendto: %m"); ! 64: exit(1); ! 65: } ! 66: } ! 67: ! 68: if (status & MASTER) { ! 69: #ifdef MEASURE ! 70: if (fp == NULL) { ! 71: fp = fopen("/usr/adm/timed.masterlog", "w"); ! 72: setlinebuf(fp); ! 73: } ! 74: #endif ! 75: syslog(LOG_INFO, "THIS MACHINE IS A SUBMASTER"); ! 76: if (trace) { ! 77: fprintf(fd, "THIS MACHINE IS A SUBMASTER\n"); ! 78: } ! 79: for (ntp = nettab; ntp != NULL; ntp = ntp->next) ! 80: if (ntp->status == MASTER) ! 81: masterup(ntp); ! 82: ! 83: } else { ! 84: syslog(LOG_INFO, "THIS MACHINE IS A SLAVE"); ! 85: if (trace) { ! 86: fprintf(fd, "THIS MACHINE IS A SLAVE\n"); ! 87: } ! 88: } ! 89: ! 90: seq = 0; ! 91: senddateack = OFF; ! 92: refusetime = 0; ! 93: ! 94: (void)gettimeofday(&time, (struct timezone *)0); ! 95: electiontime = time.tv_sec + delay2; ! 96: if (Mflag) ! 97: if (justquit) ! 98: looktime = time.tv_sec + delay2; ! 99: else ! 100: looktime = 1; ! 101: else ! 102: looktime = 0; ! 103: ! 104: loop: ! 105: length = sizeof(struct sockaddr_in); ! 106: (void)gettimeofday(&time, (struct timezone *)0); ! 107: if (time.tv_sec > electiontime) { ! 108: if (trace) ! 109: fprintf(fd, "election timer expired\n"); ! 110: longjmp(jmpenv, 1); ! 111: } ! 112: if (looktime && time.tv_sec > looktime) { ! 113: if (trace) ! 114: fprintf(fd, "Looking for nets to master and loops\n"); ! 115: ! 116: if (nignorednets > 0) { ! 117: for (ntp = nettab; ntp != NULL; ntp = ntp->next) { ! 118: if (ntp->status == IGNORE) { ! 119: lookformaster(ntp); ! 120: if (ntp->status == MASTER) ! 121: masterup(ntp); ! 122: else ! 123: ntp->status = IGNORE; ! 124: } ! 125: } ! 126: setstatus(); ! 127: #ifdef MEASURE ! 128: /* ! 129: * Check to see if we just became master ! 130: * (file not open) ! 131: */ ! 132: if (fp == NULL) { ! 133: fp = fopen("/usr/adm/timed.masterlog", "w"); ! 134: setlinebuf(fp); ! 135: } ! 136: #endif ! 137: } ! 138: ! 139: for (ntp = nettab; ntp != NULL; ntp = ntp->next) { ! 140: if (ntp->status == MASTER) { ! 141: to.tsp_type = TSP_LOOP; ! 142: to.tsp_vers = TSPVERSION; ! 143: to.tsp_seq = sequence++; ! 144: to.tsp_hopcnt = 10; ! 145: (void)strcpy(to.tsp_name, hostname); ! 146: bytenetorder(&to); ! 147: if (sendto(sock, (char *)&to, sizeof(struct tsp), 0, ! 148: &ntp->dest_addr, sizeof(struct sockaddr_in)) < 0) { ! 149: syslog(LOG_ERR, "sendto: %m"); ! 150: exit(1); ! 151: } ! 152: } ! 153: } ! 154: (void)gettimeofday(&time, (struct timezone *)0); ! 155: looktime = time.tv_sec + delay2; ! 156: } ! 157: wait.tv_sec = electiontime - time.tv_sec + 10; ! 158: wait.tv_usec = 0; ! 159: msg = readmsg(TSP_ANY, (char *)ANYADDR, &wait, (struct netinfo *)NULL); ! 160: if (msg != NULL) { ! 161: switch (msg->tsp_type) { ! 162: case TSP_SETDATE: ! 163: #ifdef TESTING ! 164: case TSP_TEST: ! 165: #endif ! 166: case TSP_MSITE: ! 167: case TSP_TRACEOFF: ! 168: case TSP_TRACEON: ! 169: break; ! 170: case TSP_MASTERUP: ! 171: if (fromnet == NULL) { ! 172: if (trace) { ! 173: fprintf(fd, "slave ignored: "); ! 174: print(msg, &from); ! 175: } ! 176: goto loop; ! 177: } ! 178: break; ! 179: default: ! 180: if (fromnet == NULL || fromnet->status == IGNORE) { ! 181: if (trace) { ! 182: fprintf(fd, "slave ignored: "); ! 183: print(msg, &from); ! 184: } ! 185: goto loop; ! 186: } ! 187: break; ! 188: } ! 189: ! 190: switch (msg->tsp_type) { ! 191: ! 192: case TSP_ADJTIME: ! 193: if (fromnet->status != SLAVE) ! 194: break; ! 195: (void)gettimeofday(&time, (struct timezone *)0); ! 196: electiontime = time.tv_sec + delay2; ! 197: if (seq != msg->tsp_seq) { ! 198: seq = msg->tsp_seq; ! 199: if ((status & SUBMASTER) == SUBMASTER) { ! 200: synch((msg->tsp_time.tv_sec * 1000) + ! 201: (msg->tsp_time.tv_usec / 1000)); ! 202: } else { ! 203: adjclock(&(msg->tsp_time)); ! 204: } ! 205: } ! 206: break; ! 207: case TSP_SETTIME: ! 208: if (fromnet->status != SLAVE) ! 209: break; ! 210: if (seq == msg->tsp_seq) ! 211: break; ! 212: ! 213: seq = msg->tsp_seq; ! 214: ! 215: (void)strcpy(olddate, date()); ! 216: (void)gettimeofday(&otime, (struct timezone *)0); ! 217: (void)settimeofday(&msg->tsp_time, ! 218: (struct timezone *)0); ! 219: syslog(LOG_NOTICE, "date changed by %s from: %s", ! 220: msg->tsp_name, olddate); ! 221: logwtmp(otime, msg->tsp_time); ! 222: if ((status & SUBMASTER) == SUBMASTER) ! 223: spreadtime(); ! 224: (void)gettimeofday(&time, (struct timezone *)0); ! 225: electiontime = time.tv_sec + delay2; ! 226: ! 227: if (senddateack == ON) { ! 228: senddateack = OFF; ! 229: msg->tsp_type = TSP_DATEACK; ! 230: (void)strcpy(msg->tsp_name, hostname); ! 231: bytenetorder(msg); ! 232: length = sizeof(struct sockaddr_in); ! 233: if (sendto(sock, (char *)msg, ! 234: sizeof(struct tsp), 0, ! 235: &saveaddr, length) < 0) { ! 236: syslog(LOG_ERR, "sendto: %m"); ! 237: exit(1); ! 238: } ! 239: } ! 240: break; ! 241: case TSP_MASTERUP: ! 242: if (slavenet && fromnet != slavenet) ! 243: break; ! 244: makeslave(fromnet); ! 245: setstatus(); ! 246: msg->tsp_type = TSP_SLAVEUP; ! 247: msg->tsp_vers = TSPVERSION; ! 248: (void)strcpy(msg->tsp_name, hostname); ! 249: bytenetorder(msg); ! 250: answerdelay(); ! 251: length = sizeof(struct sockaddr_in); ! 252: if (sendto(sock, (char *)msg, sizeof(struct tsp), 0, ! 253: &from, length) < 0) { ! 254: syslog(LOG_ERR, "sendto: %m"); ! 255: exit(1); ! 256: } ! 257: backoff = 1; ! 258: delay2 = casual((long)MINTOUT, (long)MAXTOUT); ! 259: (void)gettimeofday(&time, (struct timezone *)0); ! 260: electiontime = time.tv_sec + delay2; ! 261: refusetime = 0; ! 262: break; ! 263: case TSP_MASTERREQ: ! 264: if (fromnet->status != SLAVE) ! 265: break; ! 266: (void)gettimeofday(&time, (struct timezone *)0); ! 267: electiontime = time.tv_sec + delay2; ! 268: break; ! 269: case TSP_SETDATE: ! 270: saveaddr = from; ! 271: msg->tsp_type = TSP_SETDATEREQ; ! 272: msg->tsp_vers = TSPVERSION; ! 273: (void)strcpy(msg->tsp_name, hostname); ! 274: for (ntp = nettab; ntp != NULL; ntp = ntp->next) { ! 275: if (ntp->status == SLAVE) ! 276: break; ! 277: } ! 278: if (ntp == NULL) ! 279: break; ! 280: answer = acksend(msg, &ntp->dest_addr, (char *)ANYADDR, ! 281: TSP_DATEACK, ntp); ! 282: if (answer != NULL) { ! 283: msg->tsp_type = TSP_ACK; ! 284: bytenetorder(msg); ! 285: length = sizeof(struct sockaddr_in); ! 286: if (sendto(sock, (char *)msg, ! 287: sizeof(struct tsp), 0, &saveaddr, ! 288: length) < 0) { ! 289: syslog(LOG_ERR, "sendto: %m"); ! 290: exit(1); ! 291: } ! 292: senddateack = ON; ! 293: } ! 294: break; ! 295: case TSP_SETDATEREQ: ! 296: saveaddr = from; ! 297: if (status != SUBMASTER || fromnet->status != MASTER) ! 298: break; ! 299: for (ntp = nettab; ntp != NULL; ntp = ntp->next) { ! 300: if (ntp->status == SLAVE) ! 301: break; ! 302: } ! 303: ind = findhost(msg->tsp_name); ! 304: if (ind < 0) { ! 305: syslog(LOG_WARNING, ! 306: "DATEREQ from uncontrolled machine"); ! 307: break; ! 308: } ! 309: syslog(LOG_DEBUG, ! 310: "forwarding date change request for %s", ! 311: msg->tsp_name); ! 312: (void)strcpy(msg->tsp_name, hostname); ! 313: answer = acksend(msg, &ntp->dest_addr, (char *)ANYADDR, ! 314: TSP_DATEACK, ntp); ! 315: if (answer != NULL) { ! 316: msg->tsp_type = TSP_DATEACK; ! 317: bytenetorder(msg); ! 318: length = sizeof(struct sockaddr_in); ! 319: if (sendto(sock, (char *)msg, ! 320: sizeof(struct tsp), 0, &saveaddr, ! 321: length) < 0) { ! 322: syslog(LOG_ERR, "sendto: %m"); ! 323: exit(1); ! 324: } ! 325: } ! 326: break; ! 327: case TSP_TRACEON: ! 328: if (!(trace)) { ! 329: fd = fopen(tracefile, "w"); ! 330: setlinebuf(fd); ! 331: fprintf(fd, "Tracing started on: %s\n\n", ! 332: date()); ! 333: } ! 334: trace = ON; ! 335: break; ! 336: case TSP_TRACEOFF: ! 337: if (trace) { ! 338: fprintf(fd, "Tracing ended on: %s\n", date()); ! 339: (void)fclose(fd); ! 340: } ! 341: #ifdef GPROF ! 342: moncontrol(0); ! 343: _mcleanup(); ! 344: moncontrol(1); ! 345: #endif ! 346: trace = OFF; ! 347: break; ! 348: case TSP_SLAVEUP: ! 349: if ((status & MASTER) && fromnet->status == MASTER) { ! 350: ind = addmach(msg->tsp_name, &from); ! 351: newslave(ind, msg->tsp_seq); ! 352: } ! 353: break; ! 354: case TSP_ELECTION: ! 355: if (fromnet->status == SLAVE) { ! 356: (void)gettimeofday(&time, (struct timezone *)0); ! 357: electiontime = time.tv_sec + delay2; ! 358: seq = 0; /* reset sequence number */ ! 359: if (time.tv_sec < refusetime) ! 360: msg->tsp_type = TSP_REFUSE; ! 361: else { ! 362: msg->tsp_type = TSP_ACCEPT; ! 363: refusetime = time.tv_sec + 30; ! 364: } ! 365: (void)strcpy(candidate, msg->tsp_name); ! 366: (void)strcpy(msg->tsp_name, hostname); ! 367: answerdelay(); ! 368: server = from; ! 369: answer = acksend(msg, &server, candidate, TSP_ACK, ! 370: (struct netinfo *)NULL); ! 371: if (answer == NULL) ! 372: syslog(LOG_WARNING, ! 373: "no answer from master candidate\n"); ! 374: } else { /* fromnet->status == MASTER */ ! 375: to.tsp_type = TSP_QUIT; ! 376: (void)strcpy(to.tsp_name, hostname); ! 377: server = from; ! 378: answer = acksend(&to, &server, msg->tsp_name, ! 379: TSP_ACK, (struct netinfo *)NULL); ! 380: if (answer == NULL) { ! 381: syslog(LOG_WARNING, ! 382: "election error: no reply to QUIT"); ! 383: } else { ! 384: (void) addmach(msg->tsp_name, &from); ! 385: } ! 386: } ! 387: break; ! 388: case TSP_CONFLICT: ! 389: if (fromnet->status != MASTER) ! 390: break; ! 391: /* ! 392: * After a network partition, there can be ! 393: * more than one master: the first slave to ! 394: * come up will notify here the situation. ! 395: */ ! 396: (void)strcpy(to.tsp_name, hostname); ! 397: ! 398: if (fromnet == NULL) ! 399: break; ! 400: for(;;) { ! 401: to.tsp_type = TSP_RESOLVE; ! 402: answer = acksend(&to, &fromnet->dest_addr, ! 403: (char *)ANYADDR, TSP_MASTERACK, fromnet); ! 404: if (answer == NULL) ! 405: break; ! 406: to.tsp_type = TSP_QUIT; ! 407: server = from; ! 408: msg = acksend(&to, &server, answer->tsp_name, ! 409: TSP_ACK, (struct netinfo *)NULL); ! 410: if (msg == NULL) { ! 411: syslog(LOG_WARNING, ! 412: "conflict error: no reply to QUIT"); ! 413: } else { ! 414: (void) addmach(answer->tsp_name, &from); ! 415: } ! 416: } ! 417: masterup(fromnet); ! 418: break; ! 419: case TSP_MSITE: ! 420: if (!slavenet) ! 421: break; ! 422: msaveaddr = from; ! 423: msg->tsp_type = TSP_MSITEREQ; ! 424: msg->tsp_vers = TSPVERSION; ! 425: (void)strcpy(msg->tsp_name, hostname); ! 426: answer = acksend(msg, &slavenet->dest_addr, ! 427: (char *)ANYADDR, TSP_ACK, slavenet); ! 428: if (answer != NULL) { ! 429: msg->tsp_type = TSP_ACK; ! 430: length = sizeof(struct sockaddr_in); ! 431: bytenetorder(msg); ! 432: if (sendto(sock, (char *)msg, ! 433: sizeof(struct tsp), 0, ! 434: &msaveaddr, length) < 0) { ! 435: syslog(LOG_ERR, "sendto: %m"); ! 436: exit(1); ! 437: } ! 438: } ! 439: break; ! 440: case TSP_ACCEPT: ! 441: case TSP_REFUSE: ! 442: break; ! 443: case TSP_RESOLVE: ! 444: break; ! 445: case TSP_QUIT: ! 446: /* become slave */ ! 447: #ifdef MEASURE ! 448: if (fp != NULL) { ! 449: (void)fclose(fp); ! 450: fp = NULL; ! 451: } ! 452: #endif ! 453: longjmp(jmpenv, 2); ! 454: break; ! 455: #ifdef TESTING ! 456: case TSP_TEST: ! 457: electiontime = 0; ! 458: break; ! 459: #endif ! 460: case TSP_MSITEREQ: ! 461: if (status & MASTER) ! 462: break; ! 463: if (trace) { ! 464: fprintf(fd, "garbage: "); ! 465: print(msg, &from); ! 466: } ! 467: break; ! 468: ! 469: case TSP_LOOP: ! 470: /* looking for loops of masters */ ! 471: if ( !(status & MASTER)) ! 472: break; ! 473: if (fromnet->status == SLAVE) { ! 474: if ( !strcmp(msg->tsp_name, hostname)) { ! 475: for(;;) { ! 476: to.tsp_type = TSP_RESOLVE; ! 477: answer = acksend(&to, &fromnet->dest_addr, ! 478: (char *)ANYADDR, TSP_MASTERACK, ! 479: fromnet); ! 480: if (answer == NULL) ! 481: break; ! 482: to.tsp_type = TSP_QUIT; ! 483: (void)strcpy(to.tsp_name, hostname); ! 484: server = from; ! 485: answer = acksend(&to, &server, ! 486: answer->tsp_name, TSP_ACK, ! 487: (struct netinfo *)NULL); ! 488: if (answer == NULL) { ! 489: syslog(LOG_ERR, "loop kill error"); ! 490: } else { ! 491: electiontime = 0; ! 492: } ! 493: } ! 494: } else { ! 495: if (msg->tsp_hopcnt-- <= 0) ! 496: break; ! 497: bytenetorder(msg); ! 498: ntp = nettab; ! 499: for (; ntp != NULL; ntp = ntp->next) ! 500: if (ntp->status == MASTER) ! 501: if (sendto(sock, (char *)msg, ! 502: sizeof(struct tsp), 0, ! 503: &ntp->dest_addr, length) < 0) { ! 504: syslog(LOG_ERR, "sendto: %m"); ! 505: exit(1); ! 506: } ! 507: } ! 508: } else { ! 509: /* ! 510: * We should not have received this from a net ! 511: * we are master on. There must be two masters ! 512: * in this case. ! 513: */ ! 514: if (fromnet->my_addr.s_addr == from.sin_addr.s_addr) ! 515: break; ! 516: for (;;) { ! 517: to.tsp_type = TSP_RESOLVE; ! 518: answer = acksend(&to, &fromnet->dest_addr, ! 519: (char *)ANYADDR, TSP_MASTERACK, ! 520: fromnet); ! 521: if (answer == NULL) ! 522: break; ! 523: to.tsp_type = TSP_QUIT; ! 524: (void)strcpy(to.tsp_name, hostname); ! 525: server = from; ! 526: answer = acksend(&to, &server, answer->tsp_name, ! 527: TSP_ACK, (struct netinfo *)NULL); ! 528: if (answer == NULL) { ! 529: syslog(LOG_ERR, "loop kill error2"); ! 530: } else { ! 531: (void)addmach(msg->tsp_name, &from); ! 532: } ! 533: } ! 534: } ! 535: break; ! 536: default: ! 537: if (trace) { ! 538: fprintf(fd, "garbage: "); ! 539: print(msg, &from); ! 540: } ! 541: break; ! 542: } ! 543: } ! 544: goto loop; ! 545: } ! 546: ! 547: /* ! 548: * Used before answering a broadcast message to avoid network ! 549: * contention and likely collisions. ! 550: */ ! 551: answerdelay() ! 552: { ! 553: struct timeval timeout; ! 554: ! 555: timeout.tv_sec = 0; ! 556: timeout.tv_usec = delay1; ! 557: ! 558: (void)select(0, (fd_set *)NULL, (fd_set *)NULL, (fd_set *)NULL, ! 559: &timeout); ! 560: return; ! 561: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.