dhcpcd-discuss

Re: ICMPv6 RA with router lifetime 0

Roy Marples

Thu Mar 06 20:05:08 2014

Hi Maarten

On 06/03/2014 14:04, Maarten de Vries wrote:
Thanks for the quick reply and patch.

I like to provide a prompt service :)

With the patch, stateless autoconfiguration seems to work with the
router lifetime set to 0. But when I just ran the unpatched dhcpcd,
stateless autoconfiguration also seemed to work, even though the
dhcpcd log says "no IPv6 Routers available". The patched version does
log "Router Advertisement from fe80::x:x:x:x" and stateless
autoconfiguration also works, so it is an improvement. Address and
prefix information from the RA seem to be processed as they should.

With the patch, DNS options from the RA are now properly processed
with a router lifetime of 0. This didn't work in the unpatched
version. Note that these DNS options do have their own lifetime
fields. I don't know if dhcpcd uses these?

However, what still doesn't seem to work is DHCPv6 when the router
lifetime field is 0. With the lifetime set to 60 I got this:
dhcpcd[23593]: enp4s0: confirming prior DHCPv6 lease
dhcpcd[23593]: enp4s0: REPLY6 received from fe80::x:x:x:x
 dhcpcd[23593]: enp4s0: adding address fd13:0:0:1::/128

With router lifetime set to 0, no messages regarding DHCPv6 are
logged. I tested with Managed and Other Configuration flag of the RA
on, and with only the Other Configuration flag on.

OK good.
This final patch should be fine for you then.
You'll need to revert the prior patch.
Test and let me know!

Thanks

Roy
Index: ipv6.c
==================================================================
--- ipv6.c
+++ ipv6.c
@@ -940,18 +940,19 @@
 	TAILQ_FOREACH(rap, ctx->ra_routers, next) {
 		if (rap->expired != expired)
 			continue;
 		if (rap->iface->options->options & DHCPCD_IPV6RA_OWN) {
 			TAILQ_FOREACH(addr, &rap->addrs, next) {
-				if ((addr->flags & IPV6_AF_ONLINK) == 0)
+				if (addr->prefix_vltime == 0 ||
+				    (addr->flags & IPV6_AF_ONLINK) == 0)
 					continue;
 				rt = make_prefix(rap->iface, rap, addr);
 				if (rt)
 					TAILQ_INSERT_TAIL(dnr, rt, next);
 			}
 		}
-		if (rap->iface->options->options &
+		if (rap->lifetime && rap->iface->options->options &
 		    (DHCPCD_IPV6RA_OWN | DHCPCD_IPV6RA_OWN_DEFAULT))
 		{
 			rt = make_router(rap);
 			if (rt)
 				TAILQ_INSERT_TAIL(dnr, rt, next);

Index: ipv6nd.c
==================================================================
--- ipv6nd.c
+++ ipv6nd.c
@@ -586,11 +586,11 @@
 				}
 				if (rapap == ap)
 					found = 1;
 			}
 
-			if (wascompleted && found && rap->lifetime) {
+			if (wascompleted && found) {
 				syslog(LOG_DEBUG,
 				    "%s: Router Advertisement DAD completed",
 				    rap->iface->name);
 				if (ipv6nd_scriptrun(rap))
 					return;
@@ -662,15 +662,10 @@
 		    sizeof(rap->from.s6_addr)) == 0)
 			break;
 	}
 
 	nd_ra = (struct nd_router_advert *)icp;
-	/* Don't bother doing anything if we don't know about a router
-	 * expiring */
-	if ((rap == NULL || rap->lifetime == 0)
-	    && nd_ra->nd_ra_router_lifetime == 0)
-		return;
 
 	/* We don't want to spam the log with the fact we got an RA every
 	 * 30 seconds or so, so only spam the log if it's different. */
 	if (rap == NULL || (rap->data_len != len ||
 	     memcmp(rap->data, (unsigned char *)icp, rap->data_len) != 0))
@@ -978,16 +973,12 @@
 		script_runreason(ifp, "TEST");
 		goto handle_flag;
 	}
 	ipv6_addaddrs(&rap->addrs);
 	ipv6_buildroutes(ifp->ctx);
-
-	/* We will get run by the expire function */
-	if (rap->lifetime) {
-		if (ipv6nd_scriptrun(rap))
-			return;
-	}
+	if (ipv6nd_scriptrun(rap))
+		return;
 
 	eloop_timeout_delete(ifp->ctx->eloop, NULL, ifp);
 	eloop_timeout_delete(ifp->ctx->eloop, NULL, rap); /* reachable timer */
 
 	/* If we're owning the RA then we need to try and ensure the
@@ -1000,19 +991,17 @@
 			ipv6nd_proberouter(rap);
 	}
 
 handle_flag:
 	if (rap->flags & ND_RA_FLAG_MANAGED) {
-		if (rap->lifetime && new_data &&
-		    dhcp6_start(ifp, DH6S_INIT) == -1)
+		if (new_data && dhcp6_start(ifp, DH6S_INIT) == -1)
 			syslog(LOG_ERR, "dhcp6_start: %s: %m", ifp->name);
 	} else if (rap->flags & ND_RA_FLAG_OTHER) {
-		if (rap->lifetime && new_data &&
-		    dhcp6_start(ifp, DH6S_INFORM) == -1)
+		if (new_data && dhcp6_start(ifp, DH6S_INFORM) == -1)
 			syslog(LOG_ERR, "dhcp6_start: %s: %m", ifp->name);
 	} else {
-		if (rap->lifetime && new_data)
+		if (new_data)
 			syslog(LOG_DEBUG, "%s: No DHCPv6 instruction in RA",
 			    ifp->name);
 		if (ifp->ctx->options & DHCPCD_TEST) {
 			eloop_exit(ifp->ctx->eloop, EXIT_SUCCESS);
 			return;
@@ -1178,27 +1167,30 @@
 	timerclear(&next);
 
 	TAILQ_FOREACH_SAFE(rap, ifp->ctx->ipv6->ra_routers, next, ran) {
 		if (rap->iface != ifp)
 			continue;
-		lt.tv_sec = rap->lifetime;
-		lt.tv_usec = 0;
-		timeradd(&rap->received, &lt, &expire);
-		if (rap->lifetime == 0 || timercmp(&now, &expire, >)) {
-			valid = 0;
-			if (!rap->expired) {
-				syslog(LOG_WARNING,
-				    "%s: %s: router expired",
-				    ifp->name, rap->sfrom);
-				rap->expired = expired = 1;
-				ipv6nd_cancelproberouter(rap);
+		valid = 0;
+		if (rap->lifetime) {
+			lt.tv_sec = rap->lifetime;
+			lt.tv_usec = 0;
+			timeradd(&rap->received, &lt, &expire);
+			if (rap->lifetime == 0 || timercmp(&now, &expire, >)) {
+				if (!rap->expired) {
+					syslog(LOG_WARNING,
+					    "%s: %s: router expired",
+					    ifp->name, rap->sfrom);
+					rap->expired = expired = 1;
+					ipv6nd_cancelproberouter(rap);
+				}
+			} else {
+				valid = 1;
+				timersub(&expire, &now, &lt);
+				if (!timerisset(&next) ||
+				    timercmp(&next, &lt, >))
+					next = lt;
 			}
-		} else {
-			valid = 1;
-			timersub(&expire, &now, &lt);
-			if (!timerisset(&next) || timercmp(&next, &lt, >))
-				next = lt;
 		}
 
 		/* Addresses are expired in ipv6_addaddrs
 		 * so that DHCPv6 addresses can be removed also. */
 		TAILQ_FOREACH_SAFE(rao, &rap->options, next, raon) {


Follow-Ups:
Re: ICMPv6 RA with router lifetime 0Maarten de Vries
References:
ICMPv6 RA with router lifetime 0Maarten de Vries
Re: ICMPv6 RA with router lifetime 0Roy Marples
Re: ICMPv6 RA with router lifetime 0Maarten de Vries
Archive administrator: postmaster@marples.name