tech-net archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: pppoe, dhcpcd v6 and renew



On 14/11/2017 05:06, Roy Marples wrote:
dhcpcd did try and start the interface, but didn't actually do anything.
Can you try the attached patch please?
I've only compile tested it and won't be able to actually try it for a while.

So that patch caused a few other problems.
This one is more invasive but fixes a whole raft of issues related to not removing addresses on carrier down, which is exclusive to NetBSD-8.

Let me know how it works!

Roy
diff --git a/src/dhcp6.c b/src/dhcp6.c
index 2910274a..7e85a455 100644
--- a/src/dhcp6.c
+++ b/src/dhcp6.c
@@ -3673,28 +3673,47 @@ dhcp6_start(struct interface *ifp, enum DH6S init_state)
 	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 (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 */
+	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;
 		}
-		/* We're already running DHCP6 */
-		/* XXX: What if the managed flag vanishes from all RA? */
-#ifndef SMALL
-		dhcp6_activateinterfaces(ifp);
-#endif
 		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;
+		}
 	}
 
 	if (!(ifp->options->options & DHCPCD_DHCP6))
diff --git a/src/dhcpcd.c b/src/dhcpcd.c
index 8b3ac1b5..e677e4c6 100644
--- a/src/dhcpcd.c
+++ b/src/dhcpcd.c
@@ -871,37 +871,22 @@ dhcpcd_startinterface(void *arg)
 				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 (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 (ifp->active == IF_ACTIVE_USER) {
+				enum DH6S d6_state;
+
+				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);
 		}
 	}
 
diff --git a/src/if-bsd.c b/src/if-bsd.c
index 5dcdc71b..b5bb667d 100644
--- a/src/if-bsd.c
+++ b/src/if-bsd.c
@@ -1164,6 +1164,12 @@ if_ifa(struct dhcpcd_ctx *ctx, const struct ifa_msghdr *ifam)
 		}
 #endif
 
+#ifdef __KAME__
+		if (IN6_IS_ADDR_LINKLOCAL(&addr6))
+			/* Remove the scope from the address */
+			addr6.s6_addr[2] = addr6.s6_addr[3] = '\0';
+#endif
+
 		ipv6_handleifa(ctx, ifam->ifam_type, NULL,
 		    ifp->name, &addr6, ipv6_prefixlen(&mask6), addrflags);
 		break;
diff --git a/src/ipv6nd.c b/src/ipv6nd.c
index a35381f7..a4bae15b 100644
--- a/src/ipv6nd.c
+++ b/src/ipv6nd.c
@@ -336,6 +336,8 @@ ipv6nd_expire(struct interface *ifp, uint32_t seconds)
 {
 	struct ra *rap;
 	struct timespec now;
+	uint32_t vltime = seconds;
+	uint32_t pltime = seconds / 2;
 
 	if (ifp->ctx->ra_routers == NULL)
 		return;
@@ -347,13 +349,18 @@ ipv6nd_expire(struct interface *ifp, uint32_t seconds)
 			rap->acquired = now;
 			rap->expired = seconds ? 0 : 1;
 			if (seconds) {
-				struct ipv6_addr *ap;
+				struct ipv6_addr *ia;
 
 				rap->lifetime = seconds;
-				TAILQ_FOREACH(ap, &rap->addrs, next) {
-					if (ap->prefix_vltime) {
-						ap->prefix_vltime = seconds;
-						ap->prefix_pltime = seconds / 2;
+				TAILQ_FOREACH(ia, &rap->addrs, next) {
+					if (ia->prefix_pltime > pltime ||
+					    ia->prefix_vltime > vltime)
+					{
+						ia->acquired = now;
+						if (ia->prefix_pltime != 0)
+							ia->prefix_pltime =
+							    pltime;
+						ia->prefix_vltime = vltime;
 					}
 				}
 				ipv6_addaddrs(&rap->addrs);
@@ -1088,7 +1095,7 @@ handle_flag:
 #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)


Home | Main Index | Thread Index | Old Index