|
|
1.1 root 1: /*
2: * Copyright (c) 1983 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[] = "@(#)readmsg.c 2.9 (Berkeley) 6/5/86";
9: #endif not lint
10:
11: #include "globals.h"
12: #include <protocols/timed.h>
13:
14: extern char *tsptype[];
15:
16: /*
17: * LOOKAT checks if the message is of the requested type and comes from
18: * the right machine, returning 1 in case of affirmative answer
19: */
20:
21: #define LOOKAT(msg, mtype, mfrom, netp, froms) \
22: (((((mtype) == TSP_ANY) || ((mtype) == (msg).tsp_type)) && \
23: (((mfrom) == NULL) || (strcmp((mfrom), (msg).tsp_name) == 0)) && \
24: (((netp) == NULL) || \
25: (((netp)->mask & (froms).sin_addr.s_addr) == (netp)->net))) \
26: ? 1 : 0)
27:
28: #define MORETIME(rtime, rtout) \
29: (((rtime).tv_sec > (rtout).tv_sec || \
30: ((rtime).tv_sec == (rtout).tv_sec && \
31: (rtime).tv_usec >= (rtout).tv_usec)) \
32: ? 0 : 1)
33:
34: struct timeval rtime, rwait, rtout;
35: struct tsp msgin;
36: static struct tsplist {
37: struct tsp info;
38: struct sockaddr_in addr;
39: struct tsplist *p;
40: } msgslist;
41: struct sockaddr_in from;
42: struct netinfo *fromnet;
43:
44: /*
45: * `readmsg' returns message `type' sent by `machfrom' if it finds it
46: * either in the receive queue, or in a linked list of previously received
47: * messages that it maintains.
48: * Otherwise it waits to see if the appropriate message arrives within
49: * `intvl' seconds. If not, it returns NULL.
50: */
51:
52: struct tsp *
53: readmsg(type, machfrom, intvl, netfrom)
54:
55: int type;
56: char *machfrom;
57: struct timeval *intvl;
58: struct netinfo *netfrom;
59: {
60: int length;
61: fd_set ready;
62: static struct tsplist *head = &msgslist;
63: static struct tsplist *tail = &msgslist;
64: struct tsplist *prev;
65: register struct netinfo *ntp;
66: register struct tsplist *ptr;
67:
68: if (trace) {
69: fprintf(fd, "looking for %s from %s\n",
70: tsptype[type], machfrom == NULL ? "ANY" : machfrom);
71: ptr = head->p;
72: fprintf(fd, "msgqueue:\n");
73: while (ptr != NULL) {
74: fprintf(fd, "\t");
75: print(&ptr->info, &ptr->addr);
76: ptr = ptr->p;
77: }
78: }
79:
80: ptr = head->p;
81: prev = head;
82:
83: /*
84: * Look for the requested message scanning through the
85: * linked list. If found, return it and free the space
86: */
87:
88: while (ptr != NULL) {
89: if (LOOKAT(ptr->info, type, machfrom, netfrom, ptr->addr)) {
90: msgin = ptr->info;
91: from = ptr->addr;
92: prev->p = ptr->p;
93: if (ptr == tail)
94: tail = prev;
95: free((char *)ptr);
96: fromnet = NULL;
97: if (netfrom == NULL)
98: for (ntp = nettab; ntp != NULL; ntp = ntp->next) {
99: if ((ntp->mask & from.sin_addr.s_addr) ==
100: ntp->net) {
101: fromnet = ntp;
102: break;
103: }
104: }
105: else
106: fromnet = netfrom;
107: if (trace) {
108: fprintf(fd, "readmsg: ");
109: print(&msgin, &from);
110: }
111: return(&msgin);
112: } else {
113: prev = ptr;
114: ptr = ptr->p;
115: }
116: }
117:
118: /*
119: * If the message was not in the linked list, it may still be
120: * coming from the network. Set the timer and wait
121: * on a select to read the next incoming message: if it is the
122: * right one, return it, otherwise insert it in the linked list.
123: */
124:
125: (void)gettimeofday(&rtime, (struct timezone *)0);
126: rtout.tv_sec = rtime.tv_sec + intvl->tv_sec;
127: rtout.tv_usec = rtime.tv_usec + intvl->tv_usec;
128: if (rtout.tv_usec > 1000000) {
129: rtout.tv_usec -= 1000000;
130: rtout.tv_sec++;
131: }
132:
133: FD_ZERO(&ready);
134: for (; MORETIME(rtime, rtout);
135: (void)gettimeofday(&rtime, (struct timezone *)0)) {
136: rwait.tv_sec = rtout.tv_sec - rtime.tv_sec;
137: rwait.tv_usec = rtout.tv_usec - rtime.tv_usec;
138: if (rwait.tv_usec < 0) {
139: rwait.tv_usec += 1000000;
140: rwait.tv_sec--;
141: }
142: if (rwait.tv_sec < 0)
143: rwait.tv_sec = rwait.tv_usec = 0;
144:
145: if (trace) {
146: fprintf(fd, "readmsg: wait: (%d %d)\n",
147: rwait.tv_sec, rwait.tv_usec);
148: }
149: FD_SET(sock, &ready);
150: if (select(FD_SETSIZE, &ready, (fd_set *)0, (fd_set *)0,
151: &rwait)) {
152: length = sizeof(struct sockaddr_in);
153: if (recvfrom(sock, (char *)&msgin, sizeof(struct tsp),
154: 0, &from, &length) < 0) {
155: syslog(LOG_ERR, "receiving datagram packet: %m");
156: exit(1);
157: }
158:
159: bytehostorder(&msgin);
160:
161: if (msgin.tsp_vers > TSPVERSION) {
162: if (trace) {
163: fprintf(fd, "readmsg: version mismatch\n");
164: /* should do a dump of the packet, but... */
165: }
166: continue;
167: }
168:
169: fromnet = NULL;
170: for (ntp = nettab; ntp != NULL; ntp = ntp->next)
171: if ((ntp->mask & from.sin_addr.s_addr) ==
172: ntp->net) {
173: fromnet = ntp;
174: break;
175: }
176:
177: /*
178: * drop packets from nets we are ignoring permanently
179: */
180: if (fromnet == NULL) {
181: /*
182: * The following messages may originate on
183: * this host with an ignored network address
184: */
185: if (msgin.tsp_type != TSP_TRACEON &&
186: msgin.tsp_type != TSP_SETDATE &&
187: msgin.tsp_type != TSP_MSITE &&
188: #ifdef TESTING
189: msgin.tsp_type != TSP_TEST &&
190: #endif
191: msgin.tsp_type != TSP_TRACEOFF) {
192: if (trace) {
193: fprintf(fd, "readmsg: discarded: ");
194: print(&msgin, &from);
195: }
196: continue;
197: }
198: }
199:
200: /*
201: * Throw away messages coming from this machine, unless
202: * they are of some particular type.
203: * This gets rid of broadcast messages and reduces
204: * master processing time.
205: */
206: if ( !(strcmp(msgin.tsp_name, hostname) != 0 ||
207: msgin.tsp_type == TSP_SETDATE ||
208: #ifdef TESTING
209: msgin.tsp_type == TSP_TEST ||
210: #endif
211: msgin.tsp_type == TSP_MSITE ||
212: (msgin.tsp_type == TSP_LOOP &&
213: msgin.tsp_hopcnt != 10) ||
214: msgin.tsp_type == TSP_TRACEON ||
215: msgin.tsp_type == TSP_TRACEOFF)) {
216: if (trace) {
217: fprintf(fd, "readmsg: discarded: ");
218: print(&msgin, &from);
219: }
220: continue;
221: }
222:
223: /*
224: * Send acknowledgements here; this is faster and avoids
225: * deadlocks that would occur if acks were sent from a
226: * higher level routine. Different acknowledgements are
227: * necessary, depending on status.
228: */
229: if (fromnet->status == MASTER)
230: masterack();
231: else if (fromnet->status == SLAVE)
232: slaveack();
233: else
234: ignoreack();
235:
236: if (LOOKAT(msgin, type, machfrom, netfrom, from)) {
237: if (trace) {
238: fprintf(fd, "readmsg: ");
239: print(&msgin, &from);
240: }
241: return(&msgin);
242: } else {
243: tail->p = (struct tsplist *)
244: malloc(sizeof(struct tsplist));
245: tail = tail->p;
246: tail->p = NULL;
247: tail->info = msgin;
248: tail->addr = from;
249: }
250: } else {
251: break;
252: }
253: }
254: return((struct tsp *)NULL);
255: }
256:
257: /*
258: * `slaveack' sends the necessary acknowledgements:
259: * only the type ACK is to be sent by a slave
260: */
261:
262: slaveack()
263: {
264: int length;
265: struct tsp resp;
266:
267: length = sizeof(struct sockaddr_in);
268: switch(msgin.tsp_type) {
269:
270: case TSP_ADJTIME:
271: case TSP_SETTIME:
272: case TSP_ACCEPT:
273: case TSP_REFUSE:
274: case TSP_TRACEON:
275: case TSP_TRACEOFF:
276: case TSP_QUIT:
277: resp = msgin;
278: resp.tsp_type = TSP_ACK;
279: resp.tsp_vers = TSPVERSION;
280: (void)strcpy(resp.tsp_name, hostname);
281: if (trace) {
282: fprintf(fd, "Slaveack: ");
283: print(&resp, &from);
284: }
285: bytenetorder(&resp); /* this is not really necessary here */
286: if (sendto(sock, (char *)&resp, sizeof(struct tsp), 0,
287: &from, length) < 0) {
288: syslog(LOG_ERR, "sendto: %m");
289: exit(1);
290: }
291: break;
292: default:
293: break;
294: }
295: }
296:
297: /*
298: * Certain packets may arrive from this machine on ignored networks.
299: * These packets should be acknowledged.
300: */
301:
302: ignoreack()
303: {
304: int length;
305: struct tsp resp;
306:
307: length = sizeof(struct sockaddr_in);
308: switch(msgin.tsp_type) {
309:
310: case TSP_TRACEON:
311: case TSP_TRACEOFF:
312: resp = msgin;
313: resp.tsp_type = TSP_ACK;
314: resp.tsp_vers = TSPVERSION;
315: (void)strcpy(resp.tsp_name, hostname);
316: if (trace) {
317: fprintf(fd, "Ignoreack: ");
318: print(&resp, &from);
319: }
320: bytenetorder(&resp); /* this is not really necessary here */
321: if (sendto(sock, (char *)&resp, sizeof(struct tsp), 0,
322: &from, length) < 0) {
323: syslog(LOG_ERR, "sendto: %m");
324: exit(1);
325: }
326: break;
327: default:
328: break;
329: }
330: }
331:
332: /*
333: * `masterack' sends the necessary acknowledgments
334: * to the messages received by a master
335: */
336:
337: masterack()
338: {
339: int length;
340: struct tsp resp;
341:
342: length = sizeof(struct sockaddr_in);
343:
344: resp = msgin;
345: resp.tsp_vers = TSPVERSION;
346: (void)strcpy(resp.tsp_name, hostname);
347:
348: switch(msgin.tsp_type) {
349:
350: case TSP_QUIT:
351: case TSP_TRACEON:
352: case TSP_TRACEOFF:
353: case TSP_MSITE:
354: case TSP_MSITEREQ:
355: resp.tsp_type = TSP_ACK;
356: bytenetorder(&resp);
357: if (trace) {
358: fprintf(fd, "Masterack: ");
359: print(&resp, &from);
360: }
361: if (sendto(sock, (char *)&resp, sizeof(struct tsp), 0,
362: &from, length) < 0) {
363: syslog(LOG_ERR, "sendto: %m");
364: exit(1);
365: }
366: break;
367: case TSP_RESOLVE:
368: case TSP_MASTERREQ:
369: resp.tsp_type = TSP_MASTERACK;
370: bytenetorder(&resp);
371: if (trace) {
372: fprintf(fd, "Masterack: ");
373: print(&resp, &from);
374: }
375: if (sendto(sock, (char *)&resp, sizeof(struct tsp), 0,
376: &from, length) < 0) {
377: syslog(LOG_ERR, "sendto: %m");
378: exit(1);
379: }
380: break;
381: case TSP_SETDATEREQ:
382: resp.tsp_type = TSP_DATEACK;
383: bytenetorder(&resp);
384: if (trace) {
385: fprintf(fd, "Masterack: ");
386: print(&resp, &from);
387: }
388: if (sendto(sock, (char *)&resp, sizeof(struct tsp), 0,
389: &from, length) < 0) {
390: syslog(LOG_ERR, "sendto: %m");
391: exit(1);
392: }
393: break;
394: default:
395: break;
396: }
397: }
398:
399: /*
400: * Print a TSP message
401: */
402: print(msg, addr)
403: struct tsp *msg;
404: struct sockaddr_in *addr;
405: {
406: switch (msg->tsp_type) {
407:
408: case TSP_LOOP:
409: fprintf(fd, "%s %d %d (#%d) %s %s\n",
410: tsptype[msg->tsp_type],
411: msg->tsp_vers,
412: msg->tsp_seq,
413: msg->tsp_hopcnt,
414: msg->tsp_name,
415: inet_ntoa(addr->sin_addr));
416: break;
417:
418: case TSP_SETTIME:
419: case TSP_ADJTIME:
420: case TSP_SETDATE:
421: case TSP_SETDATEREQ:
422: fprintf(fd, "%s %d %d (%d, %d) %s %s\n",
423: tsptype[msg->tsp_type],
424: msg->tsp_vers,
425: msg->tsp_seq,
426: msg->tsp_time.tv_sec,
427: msg->tsp_time.tv_usec,
428: msg->tsp_name,
429: inet_ntoa(addr->sin_addr));
430: break;
431:
432: default:
433: fprintf(fd, "%s %d %d %s %s\n",
434: tsptype[msg->tsp_type],
435: msg->tsp_vers,
436: msg->tsp_seq,
437: msg->tsp_name,
438: inet_ntoa(addr->sin_addr));
439: break;
440: }
441: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.