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