[ipv6] Check for a valid destination address in ipv6_rx
authorMatthew Iselin <matthew@theiselins.net>
Mon, 25 Jul 2011 00:40:02 +0000 (10:40 +1000)
committerMarty Connor <mdc@etherboot.org>
Tue, 26 Jul 2011 01:39:05 +0000 (21:39 -0400)
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.

Signed-off-by: Matthew Iselin <matthew@theiselins.net>
Signed-off-by: Marty Connor <mdc@etherboot.org>
src/net/ipv6.c

index 58cb155..1c01cb2 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 );