changeset 4183:115cbfa711e2 draft

DHCPv6: confirm lease on carrier up On some platforms which preserve state when carrier goes down, such as NetBSD-8, the state does not enter the CONFIRM state. Add more logic to dhcp6_start so that we can better control this from the various call points.
author Roy Marples <roy@marples.name>
date Tue, 14 Nov 2017 16:41:59 +0000
parents 4d1dbe479752
children 548f1baa118d
files src/dhcp6.c src/dhcpcd.c src/ipv6nd.c
diffstat 3 files changed, 52 insertions(+), 48 deletions(-) [+]
line wrap: on
line diff
--- a/src/dhcp6.c	Tue Nov 14 15:37:23 2017 +0000
+++ b/src/dhcp6.c	Tue Nov 14 16:41:59 2017 +0000
@@ -3673,28 +3673,47 @@
 	struct dhcp6_state *state;
 
 	state = D6_STATE(ifp);
-	if (state) {
-		if (state->state == DH6S_INFORMED &&
-		    init_state == DH6S_INFORM)
-		{
-			dhcp6_startinform(ifp);
-			return 0;
+	if (state != NULL) {
+		switch (init_state) {
+		case DH6S_INIT:
+			/* This should only happen on OS's where we keep state
+			 * on carrier down, such as NetBSD-8. */
+			goto gogogo;
+		case DH6S_INFORM:
+			if (state->state == DH6S_INFORMED)
+				dhcp6_startinform(ifp);
+			break;
+		case DH6S_REQUEST:
+			if (ifp->options->options & DHCPCD_DHCP6 &&
+			    (state->state == DH6S_INFORM ||
+			     state->state == DH6S_INFORMED ||
+			     state->state == DH6S_DELEGATED))
+			{
+				/* Change from stateless to stateful */
+				init_state = DH6S_INIT;
+				goto gogogo;
+			}
+			break;
+		case DH6S_CONFIRM:
+			/* This should only happen on OS's where we keep state
+			 * on carrier down, such as NetBSD-8. */
+			init_state = DH6S_INIT;
+			goto gogogo;
+		default:
+			/* Not possible, but sushes some compiler warnings. */
+			break;
 		}
-		if (init_state == DH6S_INIT &&
-		    ifp->options->options & DHCPCD_DHCP6 &&
-		    (state->state == DH6S_INFORM ||
-		    state->state == DH6S_INFORMED ||
-		    state->state == DH6S_DELEGATED))
-		{
-			/* Change from stateless to stateful */
-			goto gogogo;
+		return 0;
+	} else {
+		switch (init_state) {
+		case DH6S_CONFIRM:
+			/* No DHCPv6 config, no existing state
+			 * so nothing to do. */
+			return 0;
+		default:
+			init_state = DH6S_INIT;
+			break;
 		}
-		/* We're already running DHCP6 */
-		/* XXX: What if the managed flag vanishes from all RA? */
-#ifndef SMALL
-		dhcp6_activateinterfaces(ifp);
-#endif
-		return 0;
 	}
 
 	if (!(ifp->options->options & DHCPCD_DHCP6))
--- a/src/dhcpcd.c	Tue Nov 14 15:37:23 2017 +0000
+++ b/src/dhcpcd.c	Tue Nov 14 16:41:59 2017 +0000
@@ -871,37 +871,22 @@
 				ipv6nd_startrs(ifp);
 		}
 
-		if (ifo->options & DHCPCD_DHCP6)
+
+		if (ifo->options & DHCPCD_DHCP6) {
 			dhcp6_find_delegates(ifp);
 
-		if ((!(ifo->options & DHCPCD_IPV6RS) ||
-		    ifo->options & (DHCPCD_IA_FORCED | DHCPCD_INFORM6)) &&
-		    ifp->active == IF_ACTIVE_USER)
-		{
-			ssize_t nolease;
+			if (ifp->active == IF_ACTIVE_USER) {
+				enum DH6S d6_state;
 
-			if (ifo->options & DHCPCD_IA_FORCED)
-				nolease = dhcp6_start(ifp, DH6S_INIT);
-			else if (ifo->options & DHCPCD_INFORM6)
-				nolease = dhcp6_start(ifp, DH6S_INFORM);
-			else {
-				nolease = 0;
-				/* Enabling the below doesn't really make
-				 * sense as there is currently no standard
-				 * to push routes via DHCPv6.
-				 * (There is an expired working draft,
-				 * maybe abandoned?)
-				 * You can also get it to work by forcing
-				 * an IA as shown above. */
-#if 0
-				/* With no RS or delegates we might
-				 * as well try and solicit a DHCPv6 address */
-				if (nolease == 0)
-					nolease = dhcp6_start(ifp, DH6S_INIT);
-#endif
+				if (ifo->options & DHCPCD_IA_FORCED)
+					d6_state = DH6S_INIT;
+				else if (ifo->options & DHCPCD_INFORM6)
+					d6_state = DH6S_INFORM;
+				else
+					d6_state = DH6S_CONFIRM;
+				if (dhcp6_start(ifp, d6_state) == -1)
+					logerr("%s: dhcp6_start", ifp->name);
 			}
-			if (nolease == -1)
-			        logerr("%s: dhcp6_start", ifp->name);
 		}
 	}
 
--- a/src/ipv6nd.c	Tue Nov 14 15:37:23 2017 +0000
+++ b/src/ipv6nd.c	Tue Nov 14 16:41:59 2017 +0000
@@ -1095,7 +1095,7 @@
 #define LOG_DHCP6	logdebug
 #endif
 	if (rap->flags & ND_RA_FLAG_MANAGED) {
-		if (new_data && dhcp6_start(ifp, DH6S_INIT) == -1)
+		if (new_data && dhcp6_start(ifp, DH6S_REQUEST) == -1)
 			LOG_DHCP6("dhcp6_start: %s", ifp->name);
 	} else if (rap->flags & ND_RA_FLAG_OTHER) {
 		if (new_data && dhcp6_start(ifp, DH6S_INFORM) == -1)