|
|
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.