Fix miscellanious size_t related compiler warnings.
[dragonfly.git] / usr.sbin / timed / timed / readmsg.c
CommitLineData
984263bc
MD
1/*-
2 * Copyright (c) 1985, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
1de703da
MD
32 *
33 * @(#)readmsg.c 8.1 (Berkeley) 6/6/93
34 * $FreeBSD: src/usr.sbin/timed/timed/readmsg.c,v 1.5.2.3 2001/08/31 08:02:05 kris Exp $
37c7aa4c 35 * $DragonFly: src/usr.sbin/timed/timed/readmsg.c,v 1.6 2004/09/05 02:20:15 dillon Exp $
984263bc
MD
36 */
37
984263bc
MD
38#include "globals.h"
39
40extern char *tsptype[];
41
42/*
43 * LOOKAT checks if the message is of the requested type and comes from
44 * the right machine, returning 1 in case of affirmative answer
45 */
46#define LOOKAT(msg, mtype, mfrom, netp, froms) \
47 (((mtype) == TSP_ANY || (mtype) == (msg).tsp_type) && \
48 ((mfrom) == 0 || !strcmp((mfrom), (msg).tsp_name)) && \
49 ((netp) == 0 || \
50 ((netp)->mask & (froms).sin_addr.s_addr) == (netp)->net.s_addr))
51
52struct timeval rtime, rwait, rtout;
53struct tsp msgin;
54static struct tsplist {
55 struct tsp info;
56 struct timeval when;
57 struct sockaddr_in addr;
58 struct tsplist *p;
59} msgslist;
60struct sockaddr_in from;
61struct netinfo *fromnet;
62struct timeval from_when;
63
64/*
65 * `readmsg' returns message `type' sent by `machfrom' if it finds it
66 * either in the receive queue, or in a linked list of previously received
67 * messages that it maintains.
68 * Otherwise it waits to see if the appropriate message arrives within
69 * `intvl' seconds. If not, it returns NULL.
70 */
71
72struct tsp *
320b887a
EN
73readmsg(int type, char *machfrom, struct timeval *intvl,
74 struct netinfo *netfrom)
984263bc
MD
75{
76 int length;
77 fd_set ready;
78 static struct tsplist *head = &msgslist;
79 static struct tsplist *tail = &msgslist;
80 static int msgcnt = 0;
81 struct tsplist *prev;
320b887a
EN
82 struct netinfo *ntp;
83 struct tsplist *ptr;
984263bc
MD
84 ssize_t n;
85
86 if (trace) {
87 fprintf(fd, "readmsg: looking for %s from %s, %s\n",
88 tsptype[type], machfrom == NULL ? "ANY" : machfrom,
89 netfrom == NULL ? "ANYNET" : inet_ntoa(netfrom->net));
90 if (head->p != 0) {
91 length = 1;
92 for (ptr = head->p; ptr != 0; ptr = ptr->p) {
93 /* do not repeat the hundreds of messages */
94 if (++length > 3) {
95 if (ptr == tail) {
96 fprintf(fd,"\t ...%d skipped\n",
97 length);
98 } else {
99 continue;
100 }
101 }
102 fprintf(fd, length > 1 ? "\t" : "queue:\t");
103 print(&ptr->info, &ptr->addr);
104 }
105 }
106 }
107
108 ptr = head->p;
109 prev = head;
110
111 /*
112 * Look for the requested message scanning through the
113 * linked list. If found, return it and free the space
114 */
115
116 while (ptr != NULL) {
117 if (LOOKAT(ptr->info, type, machfrom, netfrom, ptr->addr)) {
118again:
119 msgin = ptr->info;
120 from = ptr->addr;
121 from_when = ptr->when;
122 prev->p = ptr->p;
123 if (ptr == tail)
124 tail = prev;
125 free((char *)ptr);
126 fromnet = NULL;
127 if (netfrom == NULL)
128 for (ntp = nettab; ntp != NULL; ntp = ntp->next) {
129 if ((ntp->mask & from.sin_addr.s_addr) ==
130 ntp->net.s_addr) {
131 fromnet = ntp;
132 break;
133 }
134 }
135 else
136 fromnet = netfrom;
137 if (trace) {
138 fprintf(fd, "readmsg: found ");
139 print(&msgin, &from);
140 }
141
142/* The protocol can get far behind. When it does, it gets
143 * hopelessly confused. So delete duplicate messages.
144 */
145 for (ptr = prev; (ptr = ptr->p) != NULL; prev = ptr) {
146 if (ptr->addr.sin_addr.s_addr
147 == from.sin_addr.s_addr
148 && ptr->info.tsp_type == msgin.tsp_type) {
149 if (trace)
150 fprintf(fd, "\tdup ");
151 goto again;
152 }
153 }
154 msgcnt--;
155 return(&msgin);
156 } else {
157 prev = ptr;
158 ptr = ptr->p;
159 }
160 }
161
162 /*
163 * If the message was not in the linked list, it may still be
164 * coming from the network. Set the timer and wait
165 * on a select to read the next incoming message: if it is the
166 * right one, return it, otherwise insert it in the linked list.
167 */
168
37c7aa4c 169 gettimeofday(&rtout, 0);
984263bc
MD
170 timevaladd(&rtout, intvl);
171 FD_ZERO(&ready);
172 for (;;) {
37c7aa4c 173 gettimeofday(&rtime, 0);
984263bc
MD
174 timevalsub(&rwait, &rtout, &rtime);
175 if (rwait.tv_sec < 0)
176 rwait.tv_sec = rwait.tv_usec = 0;
177 else if (rwait.tv_sec == 0
178 && rwait.tv_usec < 1000000/CLK_TCK)
179 rwait.tv_usec = 1000000/CLK_TCK;
180
181 if (trace) {
182 fprintf(fd, "readmsg: wait %ld.%6ld at %s\n",
183 rwait.tv_sec, rwait.tv_usec, date());
184 /* Notice a full disk, as we flush trace info.
185 * It is better to flush periodically than at
186 * every line because the tracing consists of bursts
187 * of many lines. Without care, tracing slows
188 * down the code enough to break the protocol.
189 */
190 if (rwait.tv_sec != 0
191 && EOF == fflush(fd))
192 traceoff("Tracing ended for cause at %s\n");
193 }
194
195 FD_SET(sock, &ready);
60233e58 196 if (!select(sock+1, &ready, NULL, NULL, &rwait)) {
984263bc
MD
197 if (rwait.tv_sec == 0 && rwait.tv_usec == 0)
198 return(0);
199 continue;
200 }
201 length = sizeof(from);
202 if ((n = recvfrom(sock, (char *)&msgin, sizeof(struct tsp), 0,
203 (struct sockaddr*)&from, &length)) < 0) {
204 syslog(LOG_ERR, "recvfrom: %m");
205 exit(1);
206 }
207 /*
208 * The 4.3BSD protocol spec had a 32-byte tsp_name field, and
209 * this is still OS-dependent. Demand that the packet is at
210 * least long enough to hold a 4.3BSD packet.
211 */
212 if (n < (ssize_t)(sizeof(struct tsp) - MAXHOSTNAMELEN + 32)) {
213 syslog(LOG_NOTICE,
424e8382 214 "short packet (%zd/%zu bytes) from %s",
984263bc
MD
215 n, sizeof(struct tsp) - MAXHOSTNAMELEN + 32,
216 inet_ntoa(from.sin_addr));
217 continue;
218 }
60233e58 219 gettimeofday(&from_when, NULL);
984263bc
MD
220 bytehostorder(&msgin);
221
222 if (msgin.tsp_vers > TSPVERSION) {
223 if (trace) {
224 fprintf(fd,"readmsg: version mismatch\n");
225 /* should do a dump of the packet */
226 }
227 continue;
228 }
229
230 if (memchr(msgin.tsp_name,
231 '\0', sizeof msgin.tsp_name) == NULL) {
232 syslog(LOG_NOTICE, "hostname field not NUL terminated "
233 "in packet from %s", inet_ntoa(from.sin_addr));
234 continue;
235 }
236
237 fromnet = NULL;
238 for (ntp = nettab; ntp != NULL; ntp = ntp->next)
239 if ((ntp->mask & from.sin_addr.s_addr) ==
240 ntp->net.s_addr) {
241 fromnet = ntp;
242 break;
243 }
244
245 /*
246 * drop packets from nets we are ignoring permanently
247 */
248 if (fromnet == NULL) {
249 /*
250 * The following messages may originate on
251 * this host with an ignored network address
252 */
253 if (msgin.tsp_type != TSP_TRACEON &&
254 msgin.tsp_type != TSP_SETDATE &&
255 msgin.tsp_type != TSP_MSITE &&
256 msgin.tsp_type != TSP_TEST &&
257 msgin.tsp_type != TSP_TRACEOFF) {
258 if (trace) {
259 fprintf(fd,"readmsg: discard null net ");
260 print(&msgin, &from);
261 }
262 continue;
263 }
264 }
265
266 /*
267 * Throw away messages coming from this machine,
268 * unless they are of some particular type.
269 * This gets rid of broadcast messages and reduces
270 * master processing time.
271 */
272 if (!strcmp(msgin.tsp_name, hostname)
273 && msgin.tsp_type != TSP_SETDATE
274 && msgin.tsp_type != TSP_TEST
275 && msgin.tsp_type != TSP_MSITE
276 && msgin.tsp_type != TSP_TRACEON
277 && msgin.tsp_type != TSP_TRACEOFF
278 && msgin.tsp_type != TSP_LOOP) {
279 if (trace) {
280 fprintf(fd, "readmsg: discard own ");
281 print(&msgin, &from);
282 }
283 continue;
284 }
285
286 /*
287 * Send acknowledgements here; this is faster and
288 * avoids deadlocks that would occur if acks were
289 * sent from a higher level routine. Different
290 * acknowledgements are necessary, depending on
291 * status.
292 */
293 if (fromnet == NULL) /* do not de-reference 0 */
294 ignoreack();
295 else if (fromnet->status == MASTER)
296 masterack();
297 else if (fromnet->status == SLAVE)
298 slaveack();
299 else
300 ignoreack();
301
302 if (LOOKAT(msgin, type, machfrom, netfrom, from)) {
303 if (trace) {
304 fprintf(fd, "readmsg: ");
305 print(&msgin, &from);
306 }
307 return(&msgin);
308 } else if (++msgcnt > NHOSTS*3) {
309
310/* The protocol gets hopelessly confused if it gets too far
311* behind. However, it seems able to recover from all cases of lost
312* packets. Therefore, if we are swamped, throw everything away.
313*/
314 if (trace)
315 fprintf(fd,
316 "readmsg: discarding %d msgs\n",
317 msgcnt);
318 msgcnt = 0;
319 while ((ptr=head->p) != NULL) {
320 head->p = ptr->p;
321 free((char *)ptr);
322 }
323 tail = head;
324 } else {
325 tail->p = (struct tsplist *)
326 malloc(sizeof(struct tsplist));
327 tail = tail->p;
328 tail->p = NULL;
329 tail->info = msgin;
330 tail->addr = from;
331 /* timestamp msgs so SETTIMEs are correct */
332 tail->when = from_when;
333 }
334 }
335}
336
337/*
338 * Send the necessary acknowledgements:
339 * only the type ACK is to be sent by a slave
340 */
341void
320b887a 342slaveack(void)
984263bc 343{
320b887a 344
984263bc
MD
345 switch(msgin.tsp_type) {
346
347 case TSP_ADJTIME:
348 case TSP_SETTIME:
349 case TSP_ACCEPT:
350 case TSP_REFUSE:
351 case TSP_TRACEON:
352 case TSP_TRACEOFF:
353 case TSP_QUIT:
354 if (trace) {
355 fprintf(fd, "Slaveack: ");
356 print(&msgin, &from);
357 }
358 xmit(TSP_ACK,msgin.tsp_seq, &from);
359 break;
360
361 default:
362 if (trace) {
363 fprintf(fd, "Slaveack: no ack: ");
364 print(&msgin, &from);
365 }
366 break;
367 }
368}
369
370/*
371 * Certain packets may arrive from this machine on ignored networks.
372 * These packets should be acknowledged.
373 */
374void
320b887a 375ignoreack(void)
984263bc 376{
320b887a 377
984263bc
MD
378 switch(msgin.tsp_type) {
379
380 case TSP_TRACEON:
381 case TSP_TRACEOFF:
382 case TSP_QUIT:
383 if (trace) {
384 fprintf(fd, "Ignoreack: ");
385 print(&msgin, &from);
386 }
387 xmit(TSP_ACK,msgin.tsp_seq, &from);
388 break;
389
390 default:
391 if (trace) {
392 fprintf(fd, "Ignoreack: no ack: ");
393 print(&msgin, &from);
394 }
395 break;
396 }
397}
398
399/*
400 * `masterack' sends the necessary acknowledgments
401 * to the messages received by a master
402 */
403void
320b887a 404masterack(void)
984263bc
MD
405{
406 struct tsp resp;
407
408 resp = msgin;
409 resp.tsp_vers = TSPVERSION;
372138d3 410 strlcpy(resp.tsp_name, hostname, sizeof(resp.tsp_name));
984263bc
MD
411
412 switch(msgin.tsp_type) {
413
414 case TSP_QUIT:
415 case TSP_TRACEON:
416 case TSP_TRACEOFF:
417 case TSP_MSITEREQ:
418 if (trace) {
419 fprintf(fd, "Masterack: ");
420 print(&msgin, &from);
421 }
422 xmit(TSP_ACK,msgin.tsp_seq, &from);
423 break;
424
425 case TSP_RESOLVE:
426 case TSP_MASTERREQ:
427 if (trace) {
428 fprintf(fd, "Masterack: ");
429 print(&msgin, &from);
430 }
431 xmit(TSP_MASTERACK,msgin.tsp_seq, &from);
432 break;
433
434 default:
435 if (trace) {
436 fprintf(fd,"Masterack: no ack: ");
437 print(&msgin, &from);
438 }
439 break;
440 }
441}
442
443/*
444 * Print a TSP message
445 */
446void
320b887a 447print(struct tsp *msg, struct sockaddr_in *addr)
984263bc
MD
448{
449 char tm[26];
450 time_t tsp_time_sec;
451
452 if (msg->tsp_type >= TSPTYPENUMBER) {
453 fprintf(fd, "bad type (%u) on packet from %s\n",
454 msg->tsp_type, inet_ntoa(addr->sin_addr));
455 return;
456 }
457
458 switch (msg->tsp_type) {
459
460 case TSP_LOOP:
461 fprintf(fd, "%s %d %-6u #%d %-15s %s\n",
462 tsptype[msg->tsp_type],
463 msg->tsp_vers,
464 msg->tsp_seq,
465 msg->tsp_hopcnt,
466 inet_ntoa(addr->sin_addr),
467 msg->tsp_name);
468 break;
469
470 case TSP_SETTIME:
471 case TSP_SETDATE:
472 case TSP_SETDATEREQ:
984263bc 473 tsp_time_sec = msg->tsp_time.tv_sec;
372138d3 474 strlcpy(tm, ctime(&tsp_time_sec)+3+1, sizeof(tm));
984263bc
MD
475 fprintf(fd, "%s %d %-6u %s %-15s %s\n",
476 tsptype[msg->tsp_type],
477 msg->tsp_vers,
478 msg->tsp_seq,
479 tm,
480 inet_ntoa(addr->sin_addr),
481 msg->tsp_name);
482 break;
483
484 case TSP_ADJTIME:
485 fprintf(fd, "%s %d %-6u (%ld,%ld) %-15s %s\n",
486 tsptype[msg->tsp_type],
487 msg->tsp_vers,
488 msg->tsp_seq,
489 msg->tsp_time.tv_sec,
490 msg->tsp_time.tv_usec,
491 inet_ntoa(addr->sin_addr),
492 msg->tsp_name);
493 break;
494
495 default:
496 fprintf(fd, "%s %d %-6u %-15s %s\n",
497 tsptype[msg->tsp_type],
498 msg->tsp_vers,
499 msg->tsp_seq,
500 inet_ntoa(addr->sin_addr),
501 msg->tsp_name);
502 break;
503 }
504}