Blame SOURCES/ntp-4.2.6p3-bcast.patch

6e16f6
diff -up ntp-4.2.6p3/ntpd/ntp_io.c.bcast ntp-4.2.6p3/ntpd/ntp_io.c
6e16f6
--- ntp-4.2.6p3/ntpd/ntp_io.c.bcast	2010-12-25 10:40:36.000000000 +0100
6e16f6
+++ ntp-4.2.6p3/ntpd/ntp_io.c	2011-01-05 17:46:13.820049150 +0100
6e16f6
@@ -151,6 +151,8 @@ int ninterfaces;			/* Total number of in
6e16f6
 
6e16f6
 int disable_dynamic_updates;		/* scan interfaces once only */
6e16f6
 
6e16f6
+static int pktinfo_status = 0;		/* is IP_PKTINFO on wildipv4 iface enabled? */
6e16f6
+
6e16f6
 #ifdef REFCLOCK
6e16f6
 /*
6e16f6
  * Refclock stuff.	We keep a chain of structures with data concerning
6e16f6
@@ -2254,6 +2256,17 @@ set_reuseaddr(
6e16f6
 #endif /* ! SO_EXCLUSIVEADDRUSE */
6e16f6
 }
6e16f6
 
6e16f6
+static void
6e16f6
+set_pktinfo(int flag)
6e16f6
+{
6e16f6
+	if (wildipv4 == NULL)
6e16f6
+		return;
6e16f6
+	if (setsockopt(wildipv4->fd, SOL_IP, IP_PKTINFO, &flag, sizeof (flag))) {
6e16f6
+		msyslog(LOG_ERR, "set_pktinfo: setsockopt(IP_PKTINFO, %s) failed: %m", flag ? "on" : "off");
6e16f6
+	} else
6e16f6
+		pktinfo_status = flag;
6e16f6
+}
6e16f6
+
6e16f6
 /*
6e16f6
  * This is just a wrapper around an internal function so we can
6e16f6
  * make other changes as necessary later on
6e16f6
@@ -2659,6 +2672,7 @@ io_setbclient(void)
6e16f6
 		}
6e16f6
 	}
6e16f6
 	set_reuseaddr(0);
6e16f6
+	set_pktinfo(1);
6e16f6
 	if (nif > 0)
6e16f6
 		DPRINTF(1, ("io_setbclient: Opened broadcast clients\n"));
6e16f6
 	else if (!nif)
6e16f6
@@ -2685,6 +2699,7 @@ io_unsetbclient(void)
6e16f6
 			continue;
6e16f6
 		socket_broadcast_disable(ep, &ep->sin);
6e16f6
 	}
6e16f6
+	set_pktinfo(0);
6e16f6
 }
6e16f6
 
6e16f6
 /*
6e16f6
@@ -3392,7 +3407,8 @@ read_network_packet(
6e16f6
 #ifdef HAVE_TIMESTAMP
6e16f6
 	struct msghdr msghdr;
6e16f6
 	struct iovec iovec;
6e16f6
-	char control[TIMESTAMP_CTLMSGBUF_SIZE];
6e16f6
+	char control[sizeof (struct cmsghdr) * 2 + sizeof (struct timeval) +
6e16f6
+		sizeof (struct in_pktinfo) + 32];
6e16f6
 #endif
6e16f6
 
6e16f6
 	/*
6e16f6
@@ -3403,7 +3419,7 @@ read_network_packet(
6e16f6
 	 */
6e16f6
 
6e16f6
 	rb = get_free_recv_buffer();
6e16f6
-	if (NULL == rb || itf->ignore_packets) {
6e16f6
+	if (NULL == rb || (itf->ignore_packets && !(pktinfo_status && itf == wildipv4))) {
6e16f6
 		char buf[RX_BUFF_SIZE];
6e16f6
 		sockaddr_u from;
6e16f6
 
6e16f6
@@ -3463,6 +3479,27 @@ read_network_packet(
6e16f6
 		return (buflen);
6e16f6
 	}
6e16f6
 
6e16f6
+	if (pktinfo_status && itf->ignore_packets && itf == wildipv4) {
6e16f6
+		/* check for broadcast on 255.255.255.255, exception allowed on wildipv4 */
6e16f6
+		struct cmsghdr *cmsg;
6e16f6
+		struct in_pktinfo *pktinfo = NULL;
6e16f6
+
6e16f6
+		if ((cmsg = CMSG_FIRSTHDR(&msghdr)))
6e16f6
+			do {
6e16f6
+				if (cmsg->cmsg_level == SOL_IP && cmsg->cmsg_type == IP_PKTINFO)
6e16f6
+					pktinfo = (struct in_pktinfo *) CMSG_DATA(cmsg);
6e16f6
+			} while ((cmsg = CMSG_NXTHDR(&msghdr, cmsg)));
6e16f6
+		if (pktinfo && pktinfo->ipi_addr.s_addr == INADDR_BROADCAST) {
6e16f6
+			DPRINTF(4, ("INADDR_BROADCAST\n"));
6e16f6
+		} else {
6e16f6
+			DPRINTF(4, ("%s on (%lu) fd=%d from %s\n", "ignore",
6e16f6
+				free_recvbuffs(), fd, stoa(&rb->recv_srcadr)));
6e16f6
+			packets_ignored++;
6e16f6
+			freerecvbuf(rb);
6e16f6
+			return (buflen);
6e16f6
+		}
6e16f6
+	}
6e16f6
+
6e16f6
 	DPRINTF(3, ("read_network_packet: fd=%d length %d from %s\n",
6e16f6
 		    fd, buflen, stoa(&rb->recv_srcadr)));
6e16f6