[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