static char *RCSid
= "$Header: /f/osi/others/ntp/RCS/ntp_sock.c,v 7.1 91/02/22 09:33:53 mrose Interim $";
* Ntp UDP specific code (mainly) based on the 3.4 ntp but heavily modified.
* Revision 7.1 91/02/22 09:33:53 mrose
* Revision 7.0 90/12/10 17:21:33 mrose
* *** empty log message ***
* Revision 1.2 90/08/14 10:13:58 jpo
* Revision 1.1 89/06/15 20:36:59 jpo
advise(LLOG_DEBUG
, NULLCP
, "ifconfig test");
create_sockets(htons(43242));
for (i
= 0; i
< nintf
; i
++) {
printf("%d: %s fd %d addr %s mask %x ",
i
, addrs
[i
].name
, addrs
[i
].fd
,
ntohl(addrs
[i
].mask
.sin_addr
.s_addr
));
if (getsockopt(addrs
[0].fd
, SOL_SOCKET
, SO_BROADCAST
,
printf("BCAST opt %d", val
);
if (getsockopt(addrs
[0].fd
, SOL_SOCKET
, SO_RCVBUF
,
printf("sockbuf size = %d ", val
);
for (i
=0; i
< nintf
; i
++) {
fprintf(stderr
, "Read fd %d.. ", addrs
[i
].fd
);
cc
= read(addrs
[i
].fd
, foo
, 10);
fprintf(stderr
, " returns %d ", cc
);
* If we can't determine the interface configuration, just listen with one
* socket at the INADDR_ANY address.
ap
->addr
.ad_inet
.sin
.sin_family
= AF_INET
;
ap
->addr
.ad_inet
.sin
.sin_port
= 0;
ap
->addr
.ad_inet
.sin_addr
.s_addr
= INADDR_ANY
;
ap
->addr
.ad_inet
.sin_mask
.s_addr
= htonl(~0);
ap
->flags
= (INTF_VALID
|INTF_STATIC
);
if ((ap
->fd
= socket(AF_INET
, SOCK_DGRAM
, 0)) < 0)
adios ("failed", "socket()");
if (fcntl(ap
->fd
, F_SETFL
, FNDELAY
) < 0)
adios ("failed", "fcntl(FNDELAY)");
ap
->addr
.ad_inet
.sin_family
= AF_INET
;
ap
->addr
.ad_inet
.sin_port
= port
;
ap
->flags
= (INTF_VALID
|INTF_STATIC
);
if (bind(ap
->fd
, (struct sockaddr
*)&addrs
[0].addr
.ad_inet
,
sizeof(ap
->addr
.ad_inet
)) < 0)
* Grab interface configuration, and create a socket for each interface
struct ifreq ifreq
, *ifr
;
* create pseudo-interface with wildcard address
ap
-> addr
.inet_ad
.sin_family
= AF_INET
;
ap
-> addr
.inet_ad
.sin_port
= 0;
ap
-> addr
.inet_ad
.sin_addr
.s_addr
= INADDR_ANY
;
ap
-> flags
= (INTF_VALID
|INTF_STATIC
);
ap
-> mask
.sin_addr
.s_addr
= htonl(~0);
if ((vs
= socket(AF_INET
, SOCK_DGRAM
, 0)) < 0)
adios("failed", "socket(AF_INET, SOCK_DGRAM)");
ifc
.ifc_len
= sizeof(buf
);
if (ioctl(vs
, SIOCGIFCONF
, (char *)&ifc
) < 0)
adios ("failed", "get interface configuration");
n
= ifc
.ifc_len
/sizeof(struct ifreq
);
for (ifr
= ifc
.ifc_req
; n
> 0; n
--, ifr
++) {
if (ifr
->ifr_addr
.sa_family
!= AF_INET
)
if (ioctl(vs
, SIOCGIFFLAGS
, (char *)&ifreq
) < 0) {
advise(LLOG_EXCEPTIONS
, "failed",
if ((ifreq
.ifr_flags
& IFF_UP
) == 0)
ap
-> if_flags
= ifreq
.ifr_flags
;
if (ioctl(vs
, SIOCGIFADDR
, (char *)&ifreq
) < 0) {
advise (LLOG_EXCEPTIONS
, "failed",
ap
-> name
= strdup (ifreq
.ifr_name
);
ap
-> addr
.inet_ad
= *(struct sockaddr_in
*)&ifreq
.ifr_addr
;
ap
-> addr
.type
= AF_INET
;
if (ap
-> if_flags
& IFF_BROADCAST
) {
if (ioctl(vs
, SIOCGIFBRDADDR
, (char *)&ifreq
) < 0)
adios("failed", "SIOCGIFBRDADDR ");
*(struct sockaddr_in
*)&ifreq
.ifr_broadaddr
;
*(struct sockaddr_in
*)&ifreq
.ifr_addr
;
#endif /* SIOCGIFBRDADDR */
if (ioctl(vs
, SIOCGIFNETMASK
, (char *)&ifreq
) < 0)
adios ("failed", "SIOCGIFNETMASK ");
ap
-> mask
= *(struct sockaddr_in
*)&ifreq
.ifr_addr
;
#endif /* SIOCGIFNETMASK */
* look for an already existing source interface address. If
* the machine has multiple point to point interfaces, then
* the local address may appear more than once.
for (i
=0; i
< nintf
; i
++) {
addr_compare (&addrs
[i
].addr
, &ap
-> addr
)) {
advise (LLOG_EXCEPTIONS
, NULLCP
,
"dup interface address %s on %s\n",
ap
-> flags
= (INTF_VALID
|INTF_STATIC
);
for (i
= 0; i
< nintf
; i
++) {
if ((addrs
[i
].flags
& INTF_VALID
) == 0)
/* create a datagram (UDP) socket */
if ((addrs
[i
].fd
= socket(AF_INET
, SOCK_DGRAM
, 0)) < 0)
adios ("failed", "socket()");
/* set SO_REUSEADDR since we will be binding the same port
number on each interface */
if (setsockopt(addrs
[i
].fd
, SOL_SOCKET
, SO_REUSEADDR
,
(char *)&on
, sizeof(on
)))
advise(LLOG_EXCEPTIONS
, "failed",
"setsockopt SO_REUSEADDR");
* set non-blocking I/O on the descriptor
if (fcntl(addrs
[i
].fd
, F_SETFL
, FNDELAY
) < 0)
adios ("failed", "fcntl(FNDELAY) fails");
* finally, bind the local address address.
addrs
[i
].addr
.inet_ad
.sin_family
= AF_INET
;
addrs
[i
].addr
.inet_ad
.sin_port
= port
;
(struct sockaddr
*)&addrs
[i
].addr
.inet_ad
,
sizeof(addrs
[i
].addr
.inet_ad
)) < 0)
adios ("failed", "bind on %s", paddr(&addrs
[i
].addr
));
* Turn off the SO_REUSEADDR socket option. It apparently
* causes heartburn on systems with multicast IP installed.
* On normal systems it only gets looked at when the address
* is being bound anyway..
if (setsockopt(addrs
[i
].fd
, SOL_SOCKET
, SO_REUSEADDR
,
(char *)&off
, sizeof(off
)))
adios ("failed", "setsockopt SO_REUSEADDR off");
/* if this interface can support broadcast, set SO_BROADCAST */
if (addrs
[i
].if_flags
& IFF_BROADCAST
) {
if (setsockopt(addrs
[i
].fd
, SOL_SOCKET
, SO_BROADCAST
,
(char *)&on
, sizeof(on
)))
adios ("failed", "setsockopt(SO_BROADCAST)");
#endif /* SO_BROADCAST */
struct Naddr
*peer
= &peers
;
struct ntpdata
*pkt
= &pkts
;
dstlen
= sizeof(struct sockaddr_in
);
if ((cc
= recvfrom(ap
-> fd
, (char *) pkt
,
(struct sockaddr
*) &peer
->inet_ad
, &dstlen
)) < 0) {
if (errno
!= EWOULDBLOCK
) {
advise (LLOG_EXCEPTIONS
, "failed", "recvfrom");
printf("Runt packet from %s\n",
if (pkt
-> stratum
== INFO_QUERY
||
pkt
-> stratum
== INFO_REPLY
) {
query_mode (peer
, pkt
, ap
);
dump_pkt(peer
, pkt
, (struct ntp_peer
*)NULL
);
switch (PKT2VERS (pkt
-> status
)) {
receive (peer
, pkt
, tvp
, ap
- addrs
);
send_inet (ap
, pkt
, size
, peer
)
if (ap
-> addr
.type
!= AF_INET
) {
advise (LLOG_EXCEPTIONS
, NULLCP
,
"Bad address type in sent_inet");
if (sendto(ap
-> fd
, (char *) pkt
, size
,
0, (struct sockaddr
*)&peer
->inet_ad
,
sizeof(peer
->inet_ad
)) < 0) {
advise (LLOG_EXCEPTIONS
, "failed", "sendto: %s",
/* number of clocks per packet */
((PKTBUF_SIZE - sizeof(struct ntpinfo))/(sizeof(struct clockinfo)))
extern struct list peer_list
;
extern struct sysdata sys
;
char packet
[PKTBUF_SIZE
];
register struct ntpinfo
*nip
= (struct ntpinfo
*) packet
;
register struct ntp_peer
*peer
;
if (ntp
->stratum
!= INFO_QUERY
)
nip
->version
= NTPDC_VERSION
;
nip
->npkts
= peer_list
.members
/N_NTP_PKTS
;
if (peer_list
.members
% N_NTP_PKTS
)
nip
->peers
= peer_list
.members
;
cip
= (struct clockinfo
*)&nip
[1];
for (peer
= peer_list
.head
; peer
!= NULL
; peer
= peer
->next
) {
if (peer
->src
.type
== AF_INET
) {
cip
->my_address
= htonl(0);
addrs
[peer
->sock
].addr
.inet_ad
.sin_addr
.s_addr
;
cip
->port
= peer
->src
.inet_ad
.sin_port
; /* already in network order */
cip
->net_address
= peer
->src
.inet_ad
.sin_addr
.s_addr
;
sin
= inet_makeaddr (126,1);
cip
-> net_address
= sin
.s_addr
;
cip
-> port
= htons(10123);
sin
= inet_makeaddr (126, 1);
cip
-> my_address
= sin
.s_addr
;
cip
->flags
= htons(peer
->flags
);
cip
->flags
|= htons(PEER_FL_SELECTED
);
cip
->pkt_sent
= htonl(peer
->pkt_sent
);
cip
->pkt_rcvd
= htonl(peer
->pkt_rcvd
);
cip
->pkt_dropped
= htonl(peer
->pkt_dropped
);
cip
->timer
= htonl(peer
->timer
);
cip
->stratum
= peer
->stratum
;
cip
->ppoll
= peer
->ppoll
;
cip
->precision
= (int) peer
->precision
;
cip
->hpoll
= peer
->hpoll
;
cip
->reach
= htons(peer
->reach
& NTP_WINDOW_SHIFT_MASK
);
cip
->estdisp
= htonl((long) (peer
->estdisp
* 1000.0));
cip
->estdelay
= htonl((long) (peer
->estdelay
* 1000.0));
cip
->estoffset
= htonl((long) (peer
->estoffset
* 1000.0));
switch (peer
->refid
.rid_type
) {
cip
->refid
= peer
->refid
.rid_inet
; /* XXX */
cip
->reftime
.int_part
= htonl(peer
->reftime
.int_part
);
cip
->reftime
.fraction
= htonl(peer
->reftime
.fraction
);
cip
->info_filter
.index
= htons(peer
->filter
.samples
);
for (i
= 0; i
< PEER_SHIFT
; i
++) {
cip
->info_filter
.offset
[i
] =
htonl((long)(peer
->filter
.offset
[i
] * 1000.0));
cip
->info_filter
.delay
[i
] =
htonl((long)(peer
->filter
.delay
[i
] * 1000.0));
if (nip
->count
++ >= N_NTP_PKTS
- 1) {
(void) send_inet (ap
, (char *)packet
,
cip
= (struct clockinfo
*)&nip
[1];
(void) send_inet (ap
, (char *)packet
,