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: }