From: Danny Mayer Date: Sat, 2 Jun 2007 22:30:39 +0000 (-0400) Subject: Bug #629 Allow certain broadcast packets to be received on the wildcard socket X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=fab2885d0dfdc1c60f98da8d1d4331cd3dc876ff;p=thirdparty%2Fntp.git Bug #629 Allow certain broadcast packets to be received on the wildcard socket bk: 4661ef8fMY9mjHkM08KokcrZv7HqQg --- diff --git a/include/ntp_io.h b/include/ntp_io.h index 983c6c7dce..cff1b701f6 100644 --- a/include/ntp_io.h +++ b/include/ntp_io.h @@ -30,6 +30,7 @@ # include "win32_io.h" #endif +#include /* * Define FNDELAY and FASYNC using O_NONBLOCK and O_ASYNC if we need * to (and can). This is here initially for QNX, but may help for @@ -47,4 +48,6 @@ # endif #endif +isc_boolean_t get_broadcastclient_flag(void); /* Get the status of client broadcast */ + #endif diff --git a/include/ntp_request.h b/include/ntp_request.h index eb13fadb8f..fe0a119901 100644 --- a/include/ntp_request.h +++ b/include/ntp_request.h @@ -6,6 +6,7 @@ #define _NTP_REQUEST_H #include "ntp_types.h" +#include "recvbuff.h" /* * A mode 7 packet is used exchanging data between an NTP server @@ -923,4 +924,10 @@ struct info_dns_assoc { associd_t associd; /* association ID */ char hostname[NTP_MAXHOSTNAME]; /* hostname */ }; + +/* + * function declarations + */ +int get_packet_mode(struct recvbuf *rbufp); /* Return packet mode */ + #endif /* NTP_REQUEST_H */ diff --git a/ntpd/ntp_io.c b/ntpd/ntp_io.c index c2b266df60..44fb53f5c8 100644 --- a/ntpd/ntp_io.c +++ b/ntpd/ntp_io.c @@ -133,6 +133,7 @@ struct interface *any_interface; /* default ipv4 interface */ struct interface *any6_interface; /* default ipv6 interface */ struct interface *loopback_interface; /* loopback ipv4 interface */ +isc_boolean_t broadcast_client_enabled = ISC_FALSE; /* is broadcast client enabled */ int ninterfaces; /* Total number of interfaces */ volatile int disable_dynamic_updates; /* when set to != 0 dynamic updates won't happen */ @@ -758,7 +759,7 @@ add_interface(struct interface *interface) } /* - * remove interface from known interface list and clean up + * remove interface from knoen interface list and clean up * associated resources */ static void @@ -1548,6 +1549,7 @@ socket_broadcast_enable(struct interface *iface, SOCKET fd, struct sockaddr_stor #endif } iface->flags |= INT_BCASTOPEN; + broadcast_client_enabled = ISC_TRUE; return ISC_TRUE; #else return ISC_FALSE; @@ -1575,6 +1577,7 @@ socket_broadcast_disable(struct interface *iface, struct sockaddr_storage *maddr } } iface->flags &= ~INT_BCASTOPEN; + broadcast_client_enabled = ISC_FALSE; return ISC_TRUE; #else return ISC_FALSE; @@ -1582,6 +1585,15 @@ socket_broadcast_disable(struct interface *iface, struct sockaddr_storage *maddr } #endif /* OPEN_BCAST_SOCKET */ + +/* + * return the broadcast client flag value + */ +isc_boolean_t +get_broadcastclient_flag(void) +{ + return (broadcast_client_enabled); +} /* * Check to see if the address is a multicast address */ @@ -2833,6 +2845,7 @@ read_network_packet(SOCKET fd, struct interface *itf, l_fp ts) { GETSOCKNAME_SOCKLEN_TYPE fromlen; int buflen; + isc_boolean_t ignore_this; register struct recvbuf *rb; #ifdef HAVE_TIMESTAMP struct msghdr msghdr; @@ -2849,7 +2862,19 @@ read_network_packet(SOCKET fd, struct interface *itf, l_fp ts) rb = get_free_recv_buffer(); - if (rb == NULL || itf->ignore_packets == ISC_TRUE) + /* For broadcast packet received on the IPv4 wildcard socket + * we carve out an exception but only if the client has requested + * to receive wildcard sockets + */ + ignore_this = itf->ignore_packets; + if (ignore_this == ISC_TRUE && itf->family == AF_INET && + itf->flags == (INT_BROADCAST | INT_WILDCARD) && + get_packet_mode(rb) == MODE_BROADCAST && + get_broadcastclient_flag() == ISC_TRUE + ) + ignore_this = ISC_FALSE; + + if (rb == NULL || ignore_this == ISC_TRUE) { char buf[RX_BUFF_SIZE]; struct sockaddr_storage from; diff --git a/ntpd/ntp_request.c b/ntpd/ntp_request.c index d9a486c629..f1cd4bfc69 100644 --- a/ntpd/ntp_request.c +++ b/ntpd/ntp_request.c @@ -400,6 +400,15 @@ flush_pkt(void) +/* + * Given a buffer, return the packet mode + */ +int +get_packet_mode(struct recvbuf *rbufp) +{ + struct req_pkt *inpkt = (struct req_pkt *)&rbufp->recv_pkt; + return (INFO_MODE(inpkt->rm_vn_mode)); +} /* * process_private - process private mode (7) packets */ diff --git a/ports/winnt/ntpd/ntp_iocompletionport.c b/ports/winnt/ntpd/ntp_iocompletionport.c index 39ae4f15ae..026d5044f9 100644 --- a/ports/winnt/ntpd/ntp_iocompletionport.c +++ b/ports/winnt/ntpd/ntp_iocompletionport.c @@ -16,6 +16,8 @@ #include "ntp_refclock.h" #include "ntp_iocompletionport.h" #include "transmitbuff.h" +#include "ntp_request.h" +#include "ntp_io.h" /* * Request types @@ -456,8 +458,12 @@ OnSocketRecv(DWORD i, IoCompletionInfo *lpo, DWORD Bytes, int errstatus) { struct recvbuf *buff = NULL; recvbuf_t *newbuff; + isc_boolean_t ignore_this; + l_fp arrival_time; struct interface * inter = (struct interface *) i; + get_systime(&arrival_time); + /* Convert the overlapped pointer back to a recvbuf pointer. */ @@ -501,11 +507,23 @@ OnSocketRecv(DWORD i, IoCompletionInfo *lpo, DWORD Bytes, int errstatus) } else { + /* For broadcast packet received on the IPv4 wildcard socket + * we carve out an exception but only if the client has requested + * to receive wildcard sockets + */ + ignore_this = inter->ignore_packets; + if (ignore_this == ISC_TRUE && inter->family == AF_INET && + inter->flags == (INT_BROADCAST | INT_WILDCARD) && + get_packet_mode(buff) == MODE_BROADCAST && + get_broadcastclient_flag() == ISC_TRUE + ) + ignore_this = ISC_FALSE; + /* * If we keep it add some info to the structure */ - if (Bytes > 0 && inter->ignore_packets == ISC_FALSE) { - get_systime(&buff->recv_time); + if (Bytes > 0 && ignore_this == ISC_FALSE) { + memcpy(&buff->recv_time, &arrival_time, sizeof(arrival_time)); buff->recv_length = (int) Bytes; buff->receiver = receive; buff->dstadr = inter;