]>
git.saurik.com Git - apple/network_cmds.git/blob - timed.tproj/timed.tproj/readmsg.c
ac25ec8d3fe589c6aef8b3e33e9abf2920ae42d9
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
23 * @APPLE_LICENSE_HEADER_END@
26 * Copyright (c) 1985, 1993
27 * The Regents of the University of California. All rights reserved.
29 * Redistribution and use in source and binary forms, with or without
30 * modification, are permitted provided that the following conditions
32 * 1. Redistributions of source code must retain the above copyright
33 * notice, this list of conditions and the following disclaimer.
34 * 2. Redistributions in binary form must reproduce the above copyright
35 * notice, this list of conditions and the following disclaimer in the
36 * documentation and/or other materials provided with the distribution.
37 * 3. All advertising materials mentioning features or use of this software
38 * must display the following acknowledgement:
39 * This product includes software developed by the University of
40 * California, Berkeley and its contributors.
41 * 4. Neither the name of the University nor the names of its contributors
42 * may be used to endorse or promote products derived from this software
43 * without specific prior written permission.
45 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
46 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
47 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
48 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
49 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
50 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
51 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
52 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
53 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
54 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
59 static char sccsid
[] = "@(#)readmsg.c 8.1 (Berkeley) 6/6/93";
63 #ident "$Revision: 1.2 $"
68 extern char *tsptype
[];
71 * LOOKAT checks if the message is of the requested type and comes from
72 * the right machine, returning 1 in case of affirmative answer
74 #define LOOKAT(msg, mtype, mfrom, netp, froms) \
75 (((mtype) == TSP_ANY || (mtype) == (msg).tsp_type) && \
76 ((mfrom) == 0 || !strcmp((mfrom), (msg).tsp_name)) && \
78 ((netp)->mask & (froms).sin_addr.s_addr) == (netp)->net.s_addr))
80 struct timeval rtime
, rwait
, rtout
;
82 static struct tsplist
{
85 struct sockaddr_in addr
;
88 struct sockaddr_in from
;
89 struct netinfo
*fromnet
;
90 struct timeval from_when
;
93 * `readmsg' returns message `type' sent by `machfrom' if it finds it
94 * either in the receive queue, or in a linked list of previously received
95 * messages that it maintains.
96 * Otherwise it waits to see if the appropriate message arrives within
97 * `intvl' seconds. If not, it returns NULL.
101 readmsg(type
, machfrom
, intvl
, netfrom
)
104 struct timeval
*intvl
;
105 struct netinfo
*netfrom
;
109 static struct tsplist
*head
= &msgslist
;
110 static struct tsplist
*tail
= &msgslist
;
111 static int msgcnt
= 0;
112 struct tsplist
*prev
;
113 register struct netinfo
*ntp
;
114 register struct tsplist
*ptr
;
118 fprintf(fd
, "readmsg: looking for %s from %s, %s\n",
119 tsptype
[type
], machfrom
== NULL
? "ANY" : machfrom
,
120 netfrom
== NULL
? "ANYNET" : inet_ntoa(netfrom
->net
));
123 for (ptr
= head
->p
; ptr
!= 0; ptr
= ptr
->p
) {
124 /* do not repeat the hundreds of messages */
127 fprintf(fd
,"\t ...%d skipped\n",
133 fprintf(fd
, length
> 1 ? "\t" : "queue:\t");
134 print(&ptr
->info
, &ptr
->addr
);
143 * Look for the requested message scanning through the
144 * linked list. If found, return it and free the space
147 while (ptr
!= NULL
) {
148 if (LOOKAT(ptr
->info
, type
, machfrom
, netfrom
, ptr
->addr
)) {
152 from_when
= ptr
->when
;
159 for (ntp
= nettab
; ntp
!= NULL
; ntp
= ntp
->next
) {
160 if ((ntp
->mask
& from
.sin_addr
.s_addr
) ==
169 fprintf(fd
, "readmsg: found ");
170 print(&msgin
, &from
);
173 /* The protocol can get far behind. When it does, it gets
174 * hopelessly confused. So delete duplicate messages.
176 for (ptr
= prev
; (ptr
= ptr
->p
) != NULL
; prev
= ptr
) {
177 if (ptr
->addr
.sin_addr
.s_addr
178 == from
.sin_addr
.s_addr
179 && ptr
->info
.tsp_type
== msgin
.tsp_type
) {
181 fprintf(fd
, "\tdup ");
194 * If the message was not in the linked list, it may still be
195 * coming from the network. Set the timer and wait
196 * on a select to read the next incoming message: if it is the
197 * right one, return it, otherwise insert it in the linked list.
200 (void)gettimeofday(&rtout
, 0);
201 timevaladd(&rtout
, intvl
);
204 (void)gettimeofday(&rtime
, 0);
205 timevalsub(&rwait
, &rtout
, &rtime
);
206 if (rwait
.tv_sec
< 0)
207 rwait
.tv_sec
= rwait
.tv_usec
= 0;
208 else if (rwait
.tv_sec
== 0
209 && rwait
.tv_usec
< 1000000/CLK_TCK
)
210 rwait
.tv_usec
= 1000000/CLK_TCK
;
213 fprintf(fd
, "readmsg: wait %ld.%6ld at %s\n",
214 rwait
.tv_sec
, rwait
.tv_usec
, date());
215 /* Notice a full disk, as we flush trace info.
216 * It is better to flush periodically than at
217 * every line because the tracing consists of bursts
218 * of many lines. Without care, tracing slows
219 * down the code enough to break the protocol.
221 if (rwait
.tv_sec
!= 0
222 && EOF
== fflush(fd
))
223 traceoff("Tracing ended for cause at %s\n");
226 FD_SET(sock
, &ready
);
227 if (!select(sock
+1, &ready
, (fd_set
*)0, (fd_set
*)0,
229 if (rwait
.tv_sec
== 0 && rwait
.tv_usec
== 0)
233 length
= sizeof(from
);
234 if ((n
= recvfrom(sock
, (char *)&msgin
, sizeof(struct tsp
), 0,
235 (struct sockaddr
*)&from
, &length
)) < 0) {
236 syslog(LOG_ERR
, "recvfrom: %m");
239 if (n
< (ssize_t
)sizeof(struct tsp
)) {
241 "short packet (%u/%u bytes) from %s",
242 n
, sizeof(struct tsp
),
243 inet_ntoa(from
.sin_addr
));
246 (void)gettimeofday(&from_when
, (struct timezone
*)0);
247 bytehostorder(&msgin
);
249 if (msgin
.tsp_vers
> TSPVERSION
) {
251 fprintf(fd
,"readmsg: version mismatch\n");
252 /* should do a dump of the packet */
257 if (memchr(msgin
.tsp_name
,
258 '\0', sizeof msgin
.tsp_name
) == NULL
) {
259 syslog(LOG_NOTICE
, "hostname field not NUL terminated "
260 "in packet from %s", inet_ntoa(from
.sin_addr
));
265 for (ntp
= nettab
; ntp
!= NULL
; ntp
= ntp
->next
)
266 if ((ntp
->mask
& from
.sin_addr
.s_addr
) ==
273 * drop packets from nets we are ignoring permanently
275 if (fromnet
== NULL
) {
277 * The following messages may originate on
278 * this host with an ignored network address
280 if (msgin
.tsp_type
!= TSP_TRACEON
&&
281 msgin
.tsp_type
!= TSP_SETDATE
&&
282 msgin
.tsp_type
!= TSP_MSITE
&&
283 msgin
.tsp_type
!= TSP_TEST
&&
284 msgin
.tsp_type
!= TSP_TRACEOFF
) {
286 fprintf(fd
,"readmsg: discard null net ");
287 print(&msgin
, &from
);
294 * Throw away messages coming from this machine,
295 * unless they are of some particular type.
296 * This gets rid of broadcast messages and reduces
297 * master processing time.
299 if (!strcmp(msgin
.tsp_name
, hostname
)
300 && msgin
.tsp_type
!= TSP_SETDATE
301 && msgin
.tsp_type
!= TSP_TEST
302 && msgin
.tsp_type
!= TSP_MSITE
303 && msgin
.tsp_type
!= TSP_TRACEON
304 && msgin
.tsp_type
!= TSP_TRACEOFF
305 && msgin
.tsp_type
!= TSP_LOOP
) {
307 fprintf(fd
, "readmsg: discard own ");
308 print(&msgin
, &from
);
314 * Send acknowledgements here; this is faster and
315 * avoids deadlocks that would occur if acks were
316 * sent from a higher level routine. Different
317 * acknowledgements are necessary, depending on
320 if (fromnet
== NULL
) /* do not de-reference 0 */
322 else if (fromnet
->status
== MASTER
)
324 else if (fromnet
->status
== SLAVE
)
329 if (LOOKAT(msgin
, type
, machfrom
, netfrom
, from
)) {
331 fprintf(fd
, "readmsg: ");
332 print(&msgin
, &from
);
335 } else if (++msgcnt
> NHOSTS
*3) {
337 /* The protocol gets hopelessly confused if it gets too far
338 * behind. However, it seems able to recover from all cases of lost
339 * packets. Therefore, if we are swamped, throw everything away.
343 "readmsg: discarding %d msgs\n",
346 while ((ptr
=head
->p
) != NULL
) {
352 tail
->p
= (struct tsplist
*)
353 malloc(sizeof(struct tsplist
));
358 /* timestamp msgs so SETTIMEs are correct */
359 tail
->when
= from_when
;
365 * Send the necessary acknowledgements:
366 * only the type ACK is to be sent by a slave
371 switch(msgin
.tsp_type
) {
381 fprintf(fd
, "Slaveack: ");
382 print(&msgin
, &from
);
384 xmit(TSP_ACK
,msgin
.tsp_seq
, &from
);
389 fprintf(fd
, "Slaveack: no ack: ");
390 print(&msgin
, &from
);
397 * Certain packets may arrive from this machine on ignored networks.
398 * These packets should be acknowledged.
403 switch(msgin
.tsp_type
) {
409 fprintf(fd
, "Ignoreack: ");
410 print(&msgin
, &from
);
412 xmit(TSP_ACK
,msgin
.tsp_seq
, &from
);
417 fprintf(fd
, "Ignoreack: no ack: ");
418 print(&msgin
, &from
);
425 * `masterack' sends the necessary acknowledgments
426 * to the messages received by a master
434 resp
.tsp_vers
= TSPVERSION
;
435 (void)strcpy(resp
.tsp_name
, hostname
);
437 switch(msgin
.tsp_type
) {
444 fprintf(fd
, "Masterack: ");
445 print(&msgin
, &from
);
447 xmit(TSP_ACK
,msgin
.tsp_seq
, &from
);
453 fprintf(fd
, "Masterack: ");
454 print(&msgin
, &from
);
456 xmit(TSP_MASTERACK
,msgin
.tsp_seq
, &from
);
461 fprintf(fd
,"Masterack: no ack: ");
462 print(&msgin
, &from
);
469 * Print a TSP message
474 struct sockaddr_in
*addr
;
478 if (msg
->tsp_type
>= TSPTYPENUMBER
) {
479 fprintf(fd
, "bad type (%u) on packet from %s\n",
480 msg
->tsp_type
, inet_ntoa(addr
->sin_addr
));
484 switch (msg
->tsp_type
) {
487 fprintf(fd
, "%s %d %-6u #%d %-15s %s\n",
488 tsptype
[msg
->tsp_type
],
492 inet_ntoa(addr
->sin_addr
),
500 (void)cftime(tm
, "%D %T", &msg
->tsp_time
.tv_sec
);
502 strncpy(tm
, ctime(&msg
->tsp_time
.tv_sec
)+3+1, sizeof(tm
));
503 tm
[15] = '\0'; /* ugh */
505 fprintf(fd
, "%s %d %-6u %s %-15s %s\n",
506 tsptype
[msg
->tsp_type
],
510 inet_ntoa(addr
->sin_addr
),
515 fprintf(fd
, "%s %d %-6u (%ld,%ld) %-15s %s\n",
516 tsptype
[msg
->tsp_type
],
519 msg
->tsp_time
.tv_sec
,
520 msg
->tsp_time
.tv_usec
,
521 inet_ntoa(addr
->sin_addr
),
526 fprintf(fd
, "%s %d %-6u %-15s %s\n",
527 tsptype
[msg
->tsp_type
],
530 inet_ntoa(addr
->sin_addr
),