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