diff -up ntp-4.2.6p1/ntpd/ntp_io.c.bcast ntp-4.2.6p1/ntpd/ntp_io.c --- ntp-4.2.6p1/ntpd/ntp_io.c.bcast 2009-12-09 08:36:37.000000000 +0100 +++ ntp-4.2.6p1/ntpd/ntp_io.c 2010-03-05 14:49:25.000000000 +0100 @@ -151,6 +151,8 @@ int ninterfaces; /* Total number of in int disable_dynamic_updates; /* scan interfaces once only */ +static int pktinfo_status = 0; /* is IP_PKTINFO on wildipv4 iface enabled? */ + #ifdef REFCLOCK /* * Refclock stuff. We keep a chain of structures with data concerning @@ -1937,6 +1939,17 @@ set_reuseaddr( #endif /* ! SO_EXCLUSIVEADDRUSE */ } +static void +set_pktinfo(int flag) +{ + if (wildipv4 == NULL) + return; + if (setsockopt(wildipv4->fd, SOL_IP, IP_PKTINFO, &flag, sizeof (flag))) { + msyslog(LOG_ERR, "set_pktinfo: setsockopt(IP_PKTINFO, %s) failed: %m", flag ? "on" : "off"); + } else + pktinfo_status = flag; +} + /* * This is just a wrapper around an internal function so we can * make other changes as necessary later on @@ -2374,6 +2387,7 @@ io_setbclient(void) } } set_reuseaddr(0); + set_pktinfo(1); if (nif > 0) DPRINTF(1, ("io_setbclient: Opened broadcast clients\n")); else if (!nif) @@ -2405,6 +2419,7 @@ io_unsetbclient(void) socket_broadcast_disable(interf, &interf->sin); } + set_pktinfo(0); } /* @@ -3130,7 +3145,8 @@ read_network_packet( #ifdef HAVE_TIMESTAMP struct msghdr msghdr; struct iovec iovec; - char control[TIMESTAMP_CTLMSGBUF_SIZE]; + char control[sizeof (struct cmsghdr) * 2 + sizeof (struct timeval) + + sizeof (struct in_pktinfo) + 32]; #endif /* @@ -3141,7 +3157,7 @@ read_network_packet( */ rb = get_free_recv_buffer(); - if (NULL == rb || itf->ignore_packets) { + if (NULL == rb || (itf->ignore_packets && !(pktinfo_status && itf == wildipv4))) { char buf[RX_BUFF_SIZE]; sockaddr_u from; @@ -3201,6 +3217,27 @@ read_network_packet( return (buflen); } + if (pktinfo_status && itf->ignore_packets && itf == wildipv4) { + /* check for broadcast on 255.255.255.255, exception allowed on wildipv4 */ + struct cmsghdr *cmsg; + struct in_pktinfo *pktinfo = NULL; + + if ((cmsg = CMSG_FIRSTHDR(&msghdr))) + do { + if (cmsg->cmsg_level == SOL_IP && cmsg->cmsg_type == IP_PKTINFO) + pktinfo = (struct in_pktinfo *) CMSG_DATA(cmsg); + } while ((cmsg = CMSG_NXTHDR(&msghdr, cmsg))); + if (pktinfo && pktinfo->ipi_addr.s_addr == INADDR_BROADCAST) { + DPRINTF(4, ("INADDR_BROADCAST\n")); + } else { + DPRINTF(4, ("%s on (%lu) fd=%d from %s\n", "ignore", + free_recvbuffs(), fd, stoa(&rb->recv_srcadr))); + packets_ignored++; + freerecvbuf(rb); + return (buflen); + } + } + DPRINTF(3, ("read_network_packet: fd=%d length %d from %s\n", fd, buflen, stoa(&rb->recv_srcadr)));