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