[ipv6] Handle unaligned prefixes in router advertisements
authorMatthew Iselin <matthew@theiselins.net>
Wed, 8 Jun 2011 03:30:54 +0000 (13:30 +1000)
committerMarty Connor <mdc@etherboot.org>
Thu, 21 Jul 2011 02:06:15 +0000 (22:06 -0400)
Signed-off-by: Matthew Iselin <matthew@theiselins.net>
Signed-off-by: Marty Connor <mdc@etherboot.org>
src/net/ndp.c

index 6f98b3b..6cd2813 100644 (file)
@@ -177,8 +177,8 @@ int ndp_process_radvert ( struct io_buffer *iobuf, struct sockaddr_tcpip *st_src
                        prefix_len = opt->prefix_len;
 
                        if ( prefix_len % 8 ) {
                        prefix_len = opt->prefix_len;
 
                        if ( prefix_len % 8 ) {
-                               /* FIXME: non-aligned prefixes unhandled */
-                               DBG ( "ndp: prefix length is unaligned, connectivity may suffer.\n" );
+                               /* Copy one extra prefix byte. */
+                               prefix_len += 8;
                        }
 
                        if ( prefix_len > 64 ) {
                        }
 
                        if ( prefix_len > 64 ) {
@@ -186,6 +186,9 @@ int ndp_process_radvert ( struct io_buffer *iobuf, struct sockaddr_tcpip *st_src
                                DBG ( "ndp: prefix length is quite long, connectivity may suffer.\n" );
                        }
 
                                DBG ( "ndp: prefix length is quite long, connectivity may suffer.\n" );
                        }
 
+                       /* Copy the prefix first and then add the EUI-64 */
+                       memcpy( &host_addr.s6_addr, opt->prefix, prefix_len / 8 );
+
                        /* Create an IPv6 address for this station based on the prefix. */
                        ll_size = netdev->ll_protocol->ll_addr_len;
                        if ( ll_size < 6 ) {
                        /* Create an IPv6 address for this station based on the prefix. */
                        ll_size = netdev->ll_protocol->ll_addr_len;
                        if ( ll_size < 6 ) {
@@ -194,8 +197,6 @@ int ndp_process_radvert ( struct io_buffer *iobuf, struct sockaddr_tcpip *st_src
                                ipv6_generate_eui64 ( host_addr.s6_addr + 8, netdev->ll_addr );
                        }
 
                                ipv6_generate_eui64 ( host_addr.s6_addr + 8, netdev->ll_addr );
                        }
 
-                       memcpy( &host_addr.s6_addr, opt->prefix, prefix_len / 8 );
-
                        rc = 0;
                        }
                        break;
                        rc = 0;
                        }
                        break;