]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[ipv4] Discard unwanted unicast packets
authorMichael Brown <mcb30@ipxe.org>
Fri, 15 Jul 2011 17:58:44 +0000 (18:58 +0100)
committerMichael Brown <mcb30@ipxe.org>
Fri, 15 Jul 2011 17:58:44 +0000 (18:58 +0100)
Explicitly discard any unicast packets for addresses that we do not
control, to avoid unexpected behaviour when operating in promiscuous
mode (which is now the default, thanks to FCoE).

Signed-off-by: Michael Brown <mcb30@ipxe.org>
src/net/ipv4.c

index 01eca09d81ee0f16784fc6239a3c40ceb07da7ea..aee3bc355b2acc90179b22e8b6d7ccf4b43c04e7 100644 (file)
@@ -378,6 +378,42 @@ static int ipv4_tx ( struct io_buffer *iobuf,
        return rc;
 }
 
+/**
+ * Check if network device has any IPv4 address
+ *
+ * @v netdev           Network device
+ * @ret has_any_addr   Network device has any IPv4 address
+ */
+static int ipv4_has_any_addr ( struct net_device *netdev ) {
+       struct ipv4_miniroute *miniroute;
+
+       list_for_each_entry ( miniroute, &ipv4_miniroutes, list ) {
+               if ( miniroute->netdev == netdev )
+                       return 1;
+       }
+       return 0;
+}
+
+/**
+ * Check if network device has a specific IPv4 address
+ *
+ * @v netdev           Network device
+ * @v addr             IPv4 address
+ * @ret has_addr       Network device has this IPv4 address
+ */
+static int ipv4_has_addr ( struct net_device *netdev, struct in_addr addr ) {
+       struct ipv4_miniroute *miniroute;
+
+       list_for_each_entry ( miniroute, &ipv4_miniroutes, list ) {
+               if ( ( miniroute->netdev == netdev ) &&
+                    ( miniroute->address.s_addr == addr.s_addr ) ) {
+                       /* Found matching address */
+                       return 1;
+               }
+       }
+       return 0;
+}
+
 /**
  * Process incoming packets
  *
@@ -392,10 +428,10 @@ static int ipv4_tx ( struct io_buffer *iobuf,
  * and sends it to the transport layer.
  */
 static int ipv4_rx ( struct io_buffer *iobuf,
-                    struct net_device *netdev __unused,
+                    struct net_device *netdev,
                     const void *ll_dest __unused,
                     const void *ll_source __unused,
-                    unsigned int flags __unused ) {
+                    unsigned int flags ) {
        struct iphdr *iphdr = iobuf->data;
        size_t hdrlen;
        size_t len;
@@ -451,6 +487,15 @@ static int ipv4_rx ( struct io_buffer *iobuf,
              inet_ntoa ( iphdr->src ), ntohs ( iphdr->len ), iphdr->protocol,
              ntohs ( iphdr->ident ), ntohs ( iphdr->chksum ) );
 
+       /* Discard unicast packets not destined for us */
+       if ( ( ! ( flags & LL_MULTICAST ) ) &&
+            ipv4_has_any_addr ( netdev ) &&
+            ( ! ipv4_has_addr ( netdev, iphdr->dest ) ) ) {
+               DBG ( "IPv4 discarding non-local unicast packet for %s\n",
+                     inet_ntoa ( iphdr->dest ) );
+               goto err;
+       }
+
        /* Truncate packet to correct length, calculate pseudo-header
         * checksum and then strip off the IPv4 header.
         */
@@ -499,15 +544,10 @@ static int ipv4_rx ( struct io_buffer *iobuf,
  */
 static int ipv4_arp_check ( struct net_device *netdev, const void *net_addr ) {
        const struct in_addr *address = net_addr;
-       struct ipv4_miniroute *miniroute;
 
-       list_for_each_entry ( miniroute, &ipv4_miniroutes, list ) {
-               if ( ( miniroute->netdev == netdev ) &&
-                    ( miniroute->address.s_addr == address->s_addr ) ) {
-                       /* Found matching address */
-                       return 0;
-               }
-       }
+       if ( ipv4_has_addr ( netdev, *address ) )
+               return 0;
+
        return -ENOENT;
 }