]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[ipv6] Ignore SLAAC on prefixes with an incompatible prefix length
authorMichael Brown <mcb30@ipxe.org>
Tue, 13 Sep 2022 12:25:19 +0000 (13:25 +0100)
committerMichael Brown <mcb30@ipxe.org>
Tue, 13 Sep 2022 12:25:19 +0000 (13:25 +0100)
Experience suggests that routers are often misconfigured to advertise
SLAAC even on prefixes that do not have a SLAAC-compatible prefix
length.  iPXE will currently treat this as an error, resulting in the
prefix being ignored completely.

Handle this misconfiguration by ignoring the autonomous address flag
when the prefix length is unsuitable for SLAAC.

Reported-by: Malte Janduda <mail@janduda.net>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
src/net/ndp.c

index 75e5316483fa5b57ceb3e43a2d8bd28a119dd44d..c8e8ebad3c112e7dc6f2b482886584f6f40eb6e8 100644 (file)
@@ -789,29 +789,43 @@ static int ndp_prefix_fetch_ip6 ( struct settings *settings, void *data,
                container_of ( ndpset->settings.parent, struct net_device,
                               settings.settings );
        struct ndp_prefix_information_option *prefix = prefset->prefix;
-       struct in6_addr ip6;
+       struct in6_addr *ip6 = &prefix->prefix;
+       struct in6_addr slaac;
        int prefix_len;
+       int rc;
 
        /* Skip dead prefixes */
        if ( ! prefix->valid )
                return -ENOENT;
 
        /* Construct IPv6 address via SLAAC, if applicable */
-       memcpy ( &ip6, &prefix->prefix, sizeof ( ip6 ) );
        if ( prefix->flags & NDP_PREFIX_AUTONOMOUS ) {
-               prefix_len = ipv6_eui64 ( &ip6, netdev );
-               if ( prefix_len < 0 )
-                       return prefix_len;
-               if ( prefix_len != prefix->prefix_len )
-                       return -EINVAL;
+               memcpy ( &slaac, ip6, sizeof ( slaac ) );
+               prefix_len = ipv6_eui64 ( &slaac, netdev );
+               if ( prefix_len == prefix->prefix_len ) {
+                       /* Correctly configured prefix: use SLAAC address */
+                       ip6 = &slaac;
+               } else if ( prefix_len < 0 ) {
+                       /* Link layer does not support SLAAC */
+                       rc = prefix_len;
+                       DBGC ( netdev, "NDP %s does not support SLAAC: %s\n",
+                              netdev->name, strerror ( rc ) );
+               } else {
+                       /* Prefix length incorrect: assume a badly
+                        * configured router and ignore SLAAC address.
+                        */
+                       DBGC ( netdev, "NDP %s ignoring misconfigured SLAAC "
+                              "on prefix %s/%d\n", netdev->name,
+                              inet6_ntoa ( ip6 ), prefix->prefix_len );
+               }
        }
 
        /* Fill in IPv6 address */
-       if ( len > sizeof ( ip6 ) )
-               len = sizeof ( ip6 );
-       memcpy ( data, &ip6, len );
+       if ( len > sizeof ( *ip6 ) )
+               len = sizeof ( *ip6 );
+       memcpy ( data, ip6, len );
 
-       return sizeof ( ip6 );
+       return sizeof ( *ip6 );
 }
 
 /**