* Copyright (c) 1983 Regents of the University of California.
* All rights reserved. The Berkeley software License Agreement
* specifies the terms and conditions for redistribution.
static char sccsid
[] = "@(#)readmsg.c 2.4 (Berkeley) %G%";
#include <protocols/timed.h>
* LOOKAT checks if the message is of the requested type and comes from
* the right machine, returning 1 in case of affirmative answer
#define LOOKAT(msg, mtype, mfrom, netp, froms) \
(((((mtype) == TSP_ANY) || ((mtype) == (msg).tsp_type)) && \
(((mfrom) == NULL) || (strcmp((mfrom), (msg).tsp_name) == 0)) && \
(((netp)->mask & (froms).sin_addr.s_addr) == (netp)->net))) \
#define ISTOUTOFF(rtime, rtout) \
(((rtime).tv_sec > (rtout).tv_sec || \
((rtime).tv_sec == (rtout).tv_sec && \
(rtime).tv_usec >= (rtout).tv_usec)) \
struct timeval rtime
, rwait
, rtout
;
* `readmsg' returns message `type' sent by `machfrom' if it finds it
* either in the receive queue, or in a linked list of previously received
* messages that it maintains.
* Otherwise it waits to see if the appropriate message arrives within
* `intvl' seconds. If not, it returns NULL.
readmsg(type
, machfrom
, intvl
, netfrom
)
static struct tsplist
*head
= &msgslist
;
static struct tsplist
*tail
= &msgslist
;
int bytenetorder(), bytehostorder();
register struct netinfo
*ntp
;
register struct tsplist
*ptr
;
fprintf(fd
, "looking for %s from %s\n",
tsptype
[type
], machfrom
);
fprintf(fd
, "msgqueue:\n");
print(&ptr
->info
, &ptr
->addr
);
* Look for the requested message scanning through the
* linked list. If found, return it and free the space
if (LOOKAT(ptr
->info
, type
, machfrom
, netfrom
, ptr
->addr
)) {
ret
= (struct tsp
*)malloc(sizeof(struct tsp
));
* If the message was not in the linked list, it may still be
* coming from the network. Set the timer and wait
* on a select to read the next incoming message: if it is the
* right one, return it, otherwise insert it in the linked list.
(void)gettimeofday(&rtime
, (struct timezone
*)0);
rtout
.tv_sec
= rtime
.tv_sec
+ intvl
->tv_sec
;
rtout
.tv_usec
= rtime
.tv_usec
+ intvl
->tv_usec
;
if (rtout
.tv_usec
> 1000000) {
rtout
.tv_usec
-= 1000000;
rwait
.tv_sec
= rtout
.tv_sec
- rtime
.tv_sec
;
rwait
.tv_usec
= rtout
.tv_usec
- rtime
.tv_usec
;
rwait
.tv_usec
+= 1000000;
rwait
.tv_sec
= rwait
.tv_usec
= 0;
fprintf(fd
, "readmsg: wait: (%d %d)\n",
rwait
.tv_sec
, rwait
.tv_usec
);
if (select(FD_SETSIZE
, &ready
, (fd_set
*)0, (fd_set
*)0,
length
= sizeof(struct sockaddr_in
);
if (recvfrom(sock
, (char *)&msgin
, sizeof(struct tsp
),
0, &from
, &length
) < 0) {
syslog(LOG_ERR
, "receiving datagram packet: %m");
* Throw away messages coming from this machine, unless
* they are of some particular type.
* This gets rid of broadcast messages and reduces
* master processing time.
if ( !(strcmp(msgin
.tsp_name
, hostname
) != 0 ||
msgin
.tsp_type
== TSP_SETDATE
||
msgin
.tsp_type
== TSP_TEST
||
msgin
.tsp_type
== TSP_MSITE
||
(msgin
.tsp_type
== TSP_LOOP
&&
msgin
.tsp_hopcnt
!= 10) ||
msgin
.tsp_type
== TSP_TRACEON
||
msgin
.tsp_type
== TSP_TRACEOFF
)) {
fprintf(fd
, "readmsg: discarded: ");
(void)gettimeofday(&rtime
,(struct timezone
*)0);
if (ISTOUTOFF(rtime
, rtout
))
* Send acknowledgements here; this is faster and avoids
* deadlocks that would occur if acks were sent from a
* higher level routine. Different acknowledgements are
* necessary, depending on status.
for (ntp
= nettab
; ntp
!= NULL
; ntp
= ntp
->next
) {
if ((ntp
->mask
& from
.sin_addr
.s_addr
) ==
if (ntp
->status
== MASTER
)
if (LOOKAT(msgin
, type
, machfrom
, netfrom
, from
)) {
tail
->p
= (struct tsplist
*)
malloc(sizeof(struct tsplist
));
(void)gettimeofday(&rtime
, (struct timezone
*)0);
if (ISTOUTOFF(rtime
, rtout
))
fprintf(fd
, "readmsg: ");
for (ntp
= nettab
; ntp
!= NULL
; ntp
= ntp
->next
) {
if ((ntp
->mask
& from
.sin_addr
.s_addr
) ==
* `slaveack' sends the necessary acknowledgements:
* only the type ACK is to be sent by a slave
length
= sizeof(struct sockaddr_in
);
resp
.tsp_vers
= TSPVERSION
;
(void)strcpy(resp
.tsp_name
, hostname
);
fprintf(fd
, "Slaveack: ");
bytenetorder(&resp
); /* this is not really necessary here */
if (sendto(sock
, (char *)&resp
, sizeof(struct tsp
), 0,
syslog(LOG_ERR
, "sendto: %m");
* `masterack' sends the necessary acknowledgments
* to the messages received by a master
length
= sizeof(struct sockaddr_in
);
resp
.tsp_vers
= TSPVERSION
;
(void)strcpy(resp
.tsp_name
, hostname
);
fprintf(fd
, "Masterack: ");
if (sendto(sock
, (char *)&resp
, sizeof(struct tsp
), 0,
syslog(LOG_ERR
, "sendto: %m");
resp
.tsp_type
= TSP_MASTERACK
;
fprintf(fd
, "Masterack: ");
if (sendto(sock
, (char *)&resp
, sizeof(struct tsp
), 0,
syslog(LOG_ERR
, "sendto: %m");
resp
.tsp_type
= TSP_DATEACK
;
fprintf(fd
, "Masterack: ");
if (sendto(sock
, (char *)&resp
, sizeof(struct tsp
), 0,
syslog(LOG_ERR
, "sendto: %m");
struct sockaddr_in
*addr
;
if (msg
->tsp_type
== TSP_LOOP
) {
fprintf(fd
, "%s %d %d (#%d) %s %s\n",
inet_ntoa(addr
->sin_addr
));
fprintf(fd
, "%s %d %d (%d, %d) %s %s\n",
inet_ntoa(addr
->sin_addr
));