[klibc] [PATCH] Only peek and discard packets from specified device.

Ulrich Dangel uli at spamt.net
Sun Mar 27 17:30:22 PDT 2011


This patch fixes a bug on systems with multiple connected network devices.
As packet_peek uses all devices to receive data instead of a specific
device. As the return value was never reset it was possible that packets
from other devices were returned by packet_peek. As the the ifindex did
not match any ifindex of the specified devices the packet was never
removed and packets for the correct device were never processed.

This patch enhance packet_peek and packet_discard to only work on packages
for the specified device instead of all packets.
---
 usr/kinit/ipconfig/bootp_proto.c |    2 +-
 usr/kinit/ipconfig/dhcp_proto.c  |    2 +-
 usr/kinit/ipconfig/main.c        |   16 ++++++----------
 usr/kinit/ipconfig/packet.c      |   16 +++++++++-------
 usr/kinit/ipconfig/packet.h      |    6 +++---
 5 files changed, 20 insertions(+), 22 deletions(-)

diff --git a/usr/kinit/ipconfig/bootp_proto.c b/usr/kinit/ipconfig/bootp_proto.c
index baf9d3e..f2cc90c 100644
--- a/usr/kinit/ipconfig/bootp_proto.c
+++ b/usr/kinit/ipconfig/bootp_proto.c
@@ -169,7 +169,7 @@ int bootp_recv_reply(struct netdev *dev)
 	};
 	int ret;
 
-	ret = packet_recv(iov, 3);
+	ret = packet_recv(dev, iov, 3);
 	if (ret <= 0)
 		return ret;
 
diff --git a/usr/kinit/ipconfig/dhcp_proto.c b/usr/kinit/ipconfig/dhcp_proto.c
index fc0494d..993db52 100644
--- a/usr/kinit/ipconfig/dhcp_proto.c
+++ b/usr/kinit/ipconfig/dhcp_proto.c
@@ -147,7 +147,7 @@ static int dhcp_recv(struct netdev *dev)
 	};
 	int ret;
 
-	ret = packet_recv(iov, 3);
+	ret = packet_recv(dev, iov, 3);
 	if (ret <= 0)
 		return ret;
 
diff --git a/usr/kinit/ipconfig/main.c b/usr/kinit/ipconfig/main.c
index d501bec..1e48083 100644
--- a/usr/kinit/ipconfig/main.c
+++ b/usr/kinit/ipconfig/main.c
@@ -304,23 +304,19 @@ struct netdev *ifaces;
  */
 static int do_pkt_recv(int pkt_fd, time_t now)
 {
-	int ifindex, ret;
+	int ret = 0;
 	struct state *s;
 
-	ret = packet_peek(&ifindex);
-	if (ret == 0)
-		return ret;
-
 	for (s = slist; s; s = s->next) {
-		if (s->dev->ifindex == ifindex) {
+		ret = packet_peek(s->dev);
+		if (ret) {
 			ret = process_receive_event(s, now);
+			if (ret == 0) {
+				packet_discard(s->dev);
+			}
 			break;
 		}
 	}
-
-	if (ret == 0)
-		packet_discard();
-
 	return ret;
 }
 
diff --git a/usr/kinit/ipconfig/packet.c b/usr/kinit/ipconfig/packet.c
index 84267b7..993a2fa 100644
--- a/usr/kinit/ipconfig/packet.c
+++ b/usr/kinit/ipconfig/packet.c
@@ -167,17 +167,18 @@ int packet_send(struct netdev *dev, struct iovec *iov, int iov_len)
 }
 
 /*
- * Fetches a bootp packet, but doesn't remove it.
+ * Fetches a bootp packet from specified device, but doesn't remove it.
  * Returns:
  *  0 = Error
  * >0 = A packet of size "ret" is available for interface ifindex
  */
-int packet_peek(int *ifindex)
+int packet_peek(struct netdev *dev)
 {
 	struct sockaddr_ll sll;
 	struct iphdr iph;
 	int ret, sllen = sizeof(struct sockaddr_ll);
 
+	sll.sll_ifindex = dev->ifindex;
 	/*
 	 * Peek at the IP header.
 	 */
@@ -192,21 +193,22 @@ int packet_peek(int *ifindex)
 	if (iph.ihl < 5 || iph.version != IPVERSION)
 		goto discard_pkt;
 
-	*ifindex = sll.sll_ifindex;
 
 	return ret;
 
 discard_pkt:
-	packet_discard();
+	packet_discard(dev);
 	return 0;
 }
 
-void packet_discard(void)
+void packet_discard(struct netdev *dev)
 {
 	struct iphdr iph;
 	struct sockaddr_ll sll;
 	socklen_t sllen = sizeof(sll);
 
+	sll.sll_ifindex = dev->ifindex;
+
 	recvfrom(pkt_fd, &iph, sizeof(iph), 0,
 		 (struct sockaddr *)&sll, &sllen);
 }
@@ -219,7 +221,7 @@ void packet_discard(void)
 *   0 = Discarded packet (non-DHCP/BOOTP traffic)
  * >0 = Size of packet
  */
-int packet_recv(struct iovec *iov, int iov_len)
+int packet_recv(struct netdev* dev, struct iovec *iov, int iov_len)
 {
 	struct iphdr *ip, iph;
 	struct udphdr *udp;
@@ -293,6 +295,6 @@ free_pkt:
 
 discard_pkt:
 	dprintf("discarded\n");
-	packet_discard();
+	packet_discard(dev);
 	return 0;
 }
diff --git a/usr/kinit/ipconfig/packet.h b/usr/kinit/ipconfig/packet.h
index 627d282..524f393 100644
--- a/usr/kinit/ipconfig/packet.h
+++ b/usr/kinit/ipconfig/packet.h
@@ -6,8 +6,8 @@ struct iovec;
 int packet_open(void);
 void packet_close(void);
 int packet_send(struct netdev *dev, struct iovec *iov, int iov_len);
-int packet_peek(int *ifindex);
-void packet_discard(void);
-int packet_recv(struct iovec *iov, int iov_len);
+int packet_peek(struct netdev *dev);
+void packet_discard(struct netdev *dev);
+int packet_recv(struct netdev *dev, struct iovec *iov, int iov_len);
 
 #endif /* IPCONFIG_PACKET_H */
-- 
1.7.1



More information about the klibc mailing list