Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > e8c0b673ea1b7e162bcac8e349d03cea > files > 9

ntp-4.2.2p1-15.el5_7.1.src.rpm

--- ntp-4.2.2p1/ntpd/ntp_io.c.bcast	2007-05-11 13:41:48.000000000 +0200
+++ ntp-4.2.2p1/ntpd/ntp_io.c	2007-05-11 13:45:26.000000000 +0200
@@ -114,6 +114,8 @@
 int wildipv4 = -1;			/* Index into inter_list for IPv4 wildcard */
 int wildipv6 = -1;			/* Index into inter_list for IPv6 wildcard */
 
+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
@@ -880,6 +882,18 @@
 	}
 }
 
+static void
+set_pktinfo(int flag)
+{
+	if (wildipv4 < 0)
+		return;
+	if (setsockopt(inter_list[wildipv4].fd, SOL_IP, IP_PKTINFO, &flag, sizeof (flag))) {
+		if (debug > 1)
+			printf("setsockopt(IP_PKTINFO) failed: %s\n", strerror(errno));
+	} else
+		pktinfo_status = flag;
+}
+
 /*
  * This is just a wrapper around an internal function so we can
  * make other changes as necessary later on
@@ -1307,6 +1321,7 @@
 #else
 	netsyslog(LOG_ERR, "io_setbclient: Broadcast Client disabled by build");
 #endif
+	set_pktinfo(1);
 }
 
 /*
@@ -1326,6 +1341,7 @@
 		lstatus = socket_broadcast_disable(&inter_list[i], i, &inter_list[i].sin);
 	}
 #endif
+	set_pktinfo(0);
 }
 
 void
@@ -2236,7 +2252,58 @@
 
 	rb = get_free_recv_buffer();
 
-	if (rb == NULL || itf->ignore_packets == ISC_TRUE)
+	if (pktinfo_status && itf->ifindex == wildipv4 && rb != NULL
+			&& itf->ignore_packets == ISC_TRUE) {
+		struct msghdr msg;
+		struct iovec iov;
+		struct cmsghdr *cmsg;
+		struct in_pktinfo *pktinfo = NULL;
+		char control[sizeof (struct cmsghdr) + sizeof (struct in_pktinfo) + 8];
+
+#ifdef DEBUG
+		if (debug > 3) {
+			printf("checking for broadcast on 255.255.255.255\n");
+		}
+#endif
+		iov.iov_base = (void *) &rb->recv_space;
+		iov.iov_len = sizeof (rb->recv_space);
+		msg.msg_name = (void *) &rb->recv_srcadr;
+		msg.msg_namelen = sizeof (rb->recv_srcadr);
+		msg.msg_iov = &iov;
+		msg.msg_iovlen = 1;
+		msg.msg_control = (void *) &control;
+		msg.msg_controllen = sizeof (control);
+		msg.msg_flags = 0;
+		rb->recv_length = recvmsg(fd, &msg, 0);
+
+		if (rb->recv_length <= 0)
+			goto packet_read;
+
+		if ((cmsg = CMSG_FIRSTHDR(&msg)))
+			do {
+				if (cmsg->cmsg_level == SOL_IP && cmsg->cmsg_type == IP_PKTINFO) {
+					pktinfo = (struct in_pktinfo *) CMSG_DATA(cmsg);
+				}
+			} while ((cmsg = CMSG_NXTHDR(&msg, cmsg)));
+
+		if (pktinfo && pktinfo->ipi_addr.s_addr == INADDR_BROADCAST) {
+#ifdef DEBUG
+			if (debug > 3) {
+				printf("INADDR_BROADCAST\n");
+			}
+#endif
+			goto packet_read;
+		}
+#ifdef DEBUG
+		if (debug > 3)
+			printf("%s on (%lu) fd=%d from %s\n", "ignore",
+					free_recvbuffs(), fd, stoa(&rb->recv_srcadr));
+#endif
+		packets_ignored++;
+		freerecvbuf(rb);
+		return (rb->recv_length);
+	}
+	else if (rb == NULL || itf->ignore_packets == ISC_TRUE)
 	{
 		char buf[RX_BUFF_SIZE];
 		struct sockaddr_storage from;
@@ -2266,6 +2333,7 @@
 			   sizeof(rb->recv_space), 0,
 			   (struct sockaddr *)&rb->recv_srcadr,
 			   &fromlen);
+packet_read:
 	if (rb->recv_length == 0|| (rb->recv_length == -1 && 
 	    (errno==EWOULDBLOCK
 #ifdef EAGAIN