Browse Source

[ipv6] Perform SLAAC only during autoconfiguration

We currently perform IPv6 stateless address autoconfiguration (SLAAC)
in response to any router advertisement with the relevant flags set.
This can result in the local IPv6 source address changing midway
through a TCP connection, since our connections bind only to a local
port number and do not store a local network address.

In addition, this behaviour for SLAAC is inconsistent with that for
DHCPv4 and stateful DHCPv6, both of which will be performed only as a
result of an explicit autoconfiguration action (e.g. via the default
autoboot sequence, or the "ifconf" command).

Fix by ignoring router advertisements arriving outside the context of
an ongoing autoconfiguration attempt.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 8 years ago
parent
commit
c53a209a42
1 changed files with 14 additions and 8 deletions
  1. 14
    8
      src/net/ndp.c

+ 14
- 8
src/net/ndp.c View File

38
  *
38
  *
39
  */
39
  */
40
 
40
 
41
+static struct ipv6conf * ipv6conf_demux ( struct net_device *netdev );
41
 static int
42
 static int
42
 ipv6conf_rx_router_advertisement ( struct net_device *netdev,
43
 ipv6conf_rx_router_advertisement ( struct net_device *netdev,
43
 				   struct ndp_router_advertisement_header *radv,
44
 				   struct ndp_router_advertisement_header *radv,
341
 	struct ndp_prefix_information_option *prefix_opt = &option->prefix;
342
 	struct ndp_prefix_information_option *prefix_opt = &option->prefix;
342
 	struct in6_addr *router = &sin6_src->sin6_addr;
343
 	struct in6_addr *router = &sin6_src->sin6_addr;
343
 	struct in6_addr address;
344
 	struct in6_addr address;
345
+	struct ipv6conf *ipv6conf;
344
 	int prefix_len;
346
 	int prefix_len;
345
 	int rc;
347
 	int rc;
346
 
348
 
350
 		       "short at %zd bytes\n", netdev->name, len );
352
 		       "short at %zd bytes\n", netdev->name, len );
351
 		return -EINVAL;
353
 		return -EINVAL;
352
 	}
354
 	}
355
+
356
+	/* Identify IPv6 configurator, if any */
357
+	ipv6conf = ipv6conf_demux ( netdev );
353
 	DBGC ( netdev, "NDP %s found %sdefault router %s ",
358
 	DBGC ( netdev, "NDP %s found %sdefault router %s ",
354
 	       netdev->name, ( radv->lifetime ? "" : "non-" ),
359
 	       netdev->name, ( radv->lifetime ? "" : "non-" ),
355
 	       inet6_ntoa ( &sin6_src->sin6_addr ) );
360
 	       inet6_ntoa ( &sin6_src->sin6_addr ) );
356
-	DBGC ( netdev, "for %s-link %sautonomous prefix %s/%d\n",
361
+	DBGC ( netdev, "for %s-link %sautonomous prefix %s/%d%s\n",
357
 	       ( ( prefix_opt->flags & NDP_PREFIX_ON_LINK ) ? "on" : "off" ),
362
 	       ( ( prefix_opt->flags & NDP_PREFIX_ON_LINK ) ? "on" : "off" ),
358
 	       ( ( prefix_opt->flags & NDP_PREFIX_AUTONOMOUS ) ? "" : "non-" ),
363
 	       ( ( prefix_opt->flags & NDP_PREFIX_AUTONOMOUS ) ? "" : "non-" ),
359
 	       inet6_ntoa ( &prefix_opt->prefix ),
364
 	       inet6_ntoa ( &prefix_opt->prefix ),
360
-	       prefix_opt->prefix_len );
365
+	       prefix_opt->prefix_len, ( ipv6conf ? "" : " (ignored)" ) );
366
+
367
+	/* Do nothing unless IPv6 autoconfiguration is in progress */
368
+	if ( ! ipv6conf )
369
+		return 0;
361
 
370
 
362
 	/* Ignore off-link prefixes */
371
 	/* Ignore off-link prefixes */
363
 	if ( ! ( prefix_opt->flags & NDP_PREFIX_ON_LINK ) )
372
 	if ( ! ( prefix_opt->flags & NDP_PREFIX_ON_LINK ) )
915
 
924
 
916
 	/* Identify IPv6 configurator, if any */
925
 	/* Identify IPv6 configurator, if any */
917
 	ipv6conf = ipv6conf_demux ( netdev );
926
 	ipv6conf = ipv6conf_demux ( netdev );
918
-	if ( ! ipv6conf ) {
919
-		/* Not an error; router advertisements are processed
920
-		 * as a background activity even when no explicit
921
-		 * autoconfiguration is taking place.
922
-		 */
927
+
928
+	/* Do nothing unless IPv6 autoconfiguration is in progress */
929
+	if ( ! ipv6conf )
923
 		return 0;
930
 		return 0;
924
-	}
925
 
931
 
926
 	/* If this is not the first solicited router advertisement, ignore it */
932
 	/* If this is not the first solicited router advertisement, ignore it */
927
 	if ( ! timer_running ( &ipv6conf->timer ) )
933
 	if ( ! timer_running ( &ipv6conf->timer ) )

Loading…
Cancel
Save