[ipv6] Add a dedicated function for prefix matching
authorMatthew Iselin <matthew@theiselins.net>
Wed, 8 Jun 2011 03:30:25 +0000 (13:30 +1000)
committerMarty Connor <mdc@etherboot.org>
Thu, 21 Jul 2011 01:57:24 +0000 (21:57 -0400)
Signed-off-by: Matthew Iselin <matthew@theiselins.net>
Signed-off-by: Marty Connor <mdc@etherboot.org>
src/include/gpxe/ip6.h
src/net/ipv6.c

index 6204b03..5fc0d02 100644 (file)
@@ -74,6 +74,8 @@ extern int inet6_aton ( const char *cp, struct in6_addr *inp );
 
 void ipv6_generate_eui64 ( uint8_t *out, uint8_t *ll );
 
 
 void ipv6_generate_eui64 ( uint8_t *out, uint8_t *ll );
 
+int ipv6_match_prefix ( struct in6_addr *p1, struct in6_addr *p2, size_t len );
+
 extern int add_ipv6_address ( struct net_device *netdev,
                              struct in6_addr prefix, int prefix_len,
                              struct in6_addr address,
 extern int add_ipv6_address ( struct net_device *netdev,
                              struct in6_addr prefix, int prefix_len,
                              struct in6_addr address,
index 9d63ce8..6e6fe3f 100644 (file)
@@ -65,6 +65,46 @@ void ipv6_generate_eui64 ( uint8_t *out, uint8_t *ll ) {
        out[0] |= 0x2;
 }
 
        out[0] |= 0x2;
 }
 
+/**
+ * Verifies that a prefix matches another one.
+ *
+ * @v p1               first prefix
+ * @v p2               second prefix
+ * @v len              prefix length in bits to compare
+ * @ret int            0 if a match, nonzero otherwise
+ */
+int ipv6_match_prefix ( struct in6_addr *p1, struct in6_addr *p2, size_t len ) {
+       uint8_t ip1, ip2;
+       size_t offset, bits;
+       int rc = 0;
+
+       /* Check for a prefix match on the route. */
+       if ( ! memcmp ( p1, p2, len / 8 ) ) {
+               rc = 0;
+
+               /* Handle extra bits in the prefix. */
+               if ( ( len % 8 ) ||
+                    ( len < 8 ) ) {
+                       DBG ( "ipv6: prefix is not aligned to a byte.\n" );
+
+                       /* Compare the remaining bits. */
+                       offset = len / 8;
+                       bits = len % 8;
+
+                       ip1 = p1->in6_u.u6_addr8[offset];
+                       ip2 = p2->in6_u.u6_addr8[offset];
+                       if ( ! ( ( ip1 & (0xFF >> (8 - bits)) ) &
+                            ( ip2 ) ) ) {
+                               rc = 1;
+                       }
+               }
+       } else {
+               rc = 1;
+       }
+
+       return rc;
+}
+
 /**
  * Add IPv6 minirouting table entry
  *
 /**
  * Add IPv6 minirouting table entry
  *
@@ -214,9 +254,9 @@ static int ipv6_tx ( struct io_buffer *iobuf,
        struct sockaddr_in6 *dest = ( struct sockaddr_in6* ) st_dest;
        struct in6_addr next_hop, gateway = ip6_none;
        struct ipv6_miniroute *miniroute;
        struct sockaddr_in6 *dest = ( struct sockaddr_in6* ) st_dest;
        struct in6_addr next_hop, gateway = ip6_none;
        struct ipv6_miniroute *miniroute;
-       uint8_t ll_dest_buf[MAX_LL_ADDR_LEN], ip1, ip2;
+       uint8_t ll_dest_buf[MAX_LL_ADDR_LEN];
        const uint8_t *ll_dest = ll_dest_buf;
        const uint8_t *ll_dest = ll_dest_buf;
-       int rc, multicast, linklocal, bits, offset;
+       int rc, multicast, linklocal;
        
        /* Check for multicast transmission. */
        multicast = dest->sin6_addr.in6_u.u6_addr8[0] == 0xFF;
        
        /* Check for multicast transmission. */
        multicast = dest->sin6_addr.in6_u.u6_addr8[0] == 0xFF;
@@ -265,28 +305,7 @@ static int ipv6_tx ( struct io_buffer *iobuf,
                }
                
                /* Check for a prefix match on the route. */
                }
                
                /* Check for a prefix match on the route. */
-               if ( ! memcmp ( &next_hop, &miniroute->prefix, miniroute->prefix_len / 8 ) ) {
-                       rc = 0;
-                       
-                       /* Handle extra bits in the prefix. */
-                       if ( ( miniroute->prefix_len % 8 ) ||
-                            ( miniroute->prefix_len < 8 ) ) {
-                               DBG ( "ipv6: prefix is not aligned to a byte.\n" );
-                       
-                               /* Compare the remaining bits. */
-                               offset = miniroute->prefix_len / 8;
-                               bits = miniroute->prefix_len % 8;
-                               
-                               ip1 = next_hop.in6_u.u6_addr8[offset];
-                               ip2 = miniroute->prefix.in6_u.u6_addr8[offset];
-                               if ( ! ( ( ip1 & (0xFF >> (8 - bits)) ) &
-                                    ( ip2 ) ) ) {
-                                       rc = 1;
-                               }
-                       }
-               } else {
-                       rc = 1;
-               }
+               rc = ipv6_match_prefix ( &next_hop, &miniroute->prefix, miniroute->prefix_len );
                
                /* Matched? */
                if( rc == 0 ) {
                
                /* Matched? */
                if( rc == 0 ) {