[ipv6] check for a valid destination address in ipv6_rx master
authorMatthew Iselin <matthew@theiselins.net>
Mon, 25 Jul 2011 00:40:02 +0000 (10:40 +1000)
committerMatthew Iselin <matthew@theiselins.net>
Mon, 25 Jul 2011 10:57:26 +0000 (20:57 +1000)
Previously, gPXE would happily process any IPv6 packet transmitted to it,
even if it was not targeted to the gPXE station. This caused issues
with ICMPv6 echo requests in particular, but also wasted processing time on
other traffic on the network.

Now, the destination address is verified before too much processing is done.

src/net/icmpv6.c
src/net/ipv6.c

index d154c03..24f2ec5 100644 (file)
@@ -194,15 +194,6 @@ int icmp6_rx ( struct io_buffer *iobuf, struct sockaddr_tcpip *st_src,
                rc = 0;
                goto done;
        }
-       
-       /* Verify that we should even begin to process this packet.
-        * It must be either unicast, and targeted to us, or multicast. */
-       if ( icmp6_net_protocol->check ( netdev, &dest->sin6_addr ) &&
-            ( ! ( dest->sin6_addr.in6_u.u6_addr8[0] == 0xFF ) ) ) {
-               DBG ( "ICMPv6 packet is not targeted to us.\n" );
-               rc = -EINVAL;
-               goto done;
-       }
 
        /* Verify checksum */
        csum = tcpip_continue_chksum ( pshdr_csum, icmp6hdr, len );
index 58cb155..6bea135 100644 (file)
@@ -35,9 +35,7 @@ struct net_protocol ipv6_protocol;
 
 char * inet6_ntoa ( struct in6_addr in6 );
 
-static int ipv6_process_nxt_hdr ( struct io_buffer *iobuf, uint8_t nxt_hdr,
-               struct sockaddr_tcpip *src, struct sockaddr_tcpip *dest,
-               struct net_device *netdev, uint16_t phcsm );
+static int ipv6_check ( struct net_device *netdev, const void *net_addr );
 
 /* Unspecified IP6 address */
 static struct in6_addr ip6_none = {
@@ -701,6 +699,23 @@ static int ipv6_rx ( struct io_buffer *iobuf,
                goto drop;
        }
 
+       /* Construct socket address */
+       memset ( &src, 0, sizeof ( src ) );
+       src.sin6.sin_family = AF_INET6;
+       src.sin6.sin6_addr = ip6hdr->src;
+       memset ( &dest, 0, sizeof ( dest ) );
+       dest.sin6.sin_family = AF_INET6;
+       dest.sin6.sin6_addr = ip6hdr->dest;
+       
+       /* Check destination - always allow multicast. */
+       if ( dest.sin6.sin6_addr.s6_addr[0] != 0xFF ) {
+               if ( ipv6_check ( netdev, &dest.sin6.sin6_addr ) ) {
+                       DBG ( "IP6: packet not for us\n" );
+                       rc = -EINVAL;
+                       goto drop;
+               }
+       }
+
        /* Print IP6 header for debugging */
        ipv6_dump ( ip6hdr );
 
@@ -721,14 +736,6 @@ static int ipv6_rx ( struct io_buffer *iobuf,
 
        /* Ignore the traffic class and flow control values */
 
-       /* Construct socket address */
-       memset ( &src, 0, sizeof ( src ) );
-       src.sin6.sin_family = AF_INET6;
-       src.sin6.sin6_addr = ip6hdr->src;
-       memset ( &dest, 0, sizeof ( dest ) );
-       dest.sin6.sin_family = AF_INET6;
-       dest.sin6.sin6_addr = ip6hdr->dest;
-
        /* Calculate the psuedo-header checksum before the IP6 header is
         * stripped away. */
        phcsm = ipv6_tx_csum ( iobuf, TCPIP_EMPTY_CSUM );