changeset 4231:0dcc72ad719c draft

ipv6nd: drop DHCPv6 when RA fully expires Fixes an error where RA addresses would expire but the DHCPv6 lease still persisted.
author Roy Marples <roy@marples.name>
date Fri, 02 Mar 2018 15:00:07 +0000
parents bdf512764978
children 8b92c1844860
files src/dhcp6.c src/ipv6nd.c
diffstat 2 files changed, 19 insertions(+), 10 deletions(-) [+]
line wrap: on
line diff
--- a/src/dhcp6.c	Fri Mar 02 13:58:52 2018 +0000
+++ b/src/dhcp6.c	Fri Mar 02 15:00:07 2018 +0000
@@ -3860,9 +3860,14 @@
 {
 
 #ifndef SMALL
-	if (dhcp6_hasprefixdelegation(ifp) == 0)
+	if (dhcp6_hasprefixdelegation(ifp))
+		return;
 #endif
-		dhcp6_drop(ifp, "EXPIRE6");
+	if (D6_CSTATE(ifp) == NULL)
+		return;
+
+	loginfox("%s: dropping DHCPv6 due to no valid routers", ifp->name);
+	dhcp6_drop(ifp, "EXPIRE6");
 }
 
 void
--- a/src/ipv6nd.c	Fri Mar 02 13:58:52 2018 +0000
+++ b/src/ipv6nd.c	Fri Mar 02 15:00:07 2018 +0000
@@ -1313,7 +1313,7 @@
 	struct interface *ifp;
 	struct ra *rap, *ran;
 	struct timespec now, lt, expire, next;
-	uint8_t expired, valid, validone;
+	uint8_t expired, anyvalid, valid, validone;
 	struct ipv6_addr *ia;
 
 	ifp = arg;
@@ -1321,11 +1321,11 @@
 	expired = 0;
 	timespecclear(&next);
 
-	validone = 0;
+	anyvalid = 0;
 	TAILQ_FOREACH_SAFE(rap, ifp->ctx->ra_routers, next, ran) {
 		if (rap->iface != ifp)
 			continue;
-		valid = 0;
+		valid = validone = 0;
 		if (rap->lifetime) {
 			lt.tv_sec = (time_t)rap->lifetime;
 			lt.tv_nsec = 0;
@@ -1351,9 +1351,12 @@
 		 * the kernel can expire, so we need to handle it ourself.
 		 * Also, some OS don't support address lifetimes (Solaris). */
 		TAILQ_FOREACH(ia, &rap->addrs, next) {
-			if (ia->prefix_vltime == ND6_INFINITE_LIFETIME ||
-			    ia->prefix_vltime == 0)
+			if (ia->prefix_vltime == 0)
 				continue;
+			if (ia->prefix_vltime == ND6_INFINITE_LIFETIME) {
+				validone = 1;
+				continue;
+			}
 			lt.tv_sec = (time_t)ia->prefix_vltime;
 			lt.tv_nsec = 0;
 			timespecadd(&ia->acquired, &lt, &expire);
@@ -1375,6 +1378,7 @@
 				if (!timespecisset(&next) ||
 				    timespeccmp(&next, &lt, >))
 					next = lt;
+				validone = 1;
 			}
 		}
 
@@ -1385,10 +1389,10 @@
 
 		/* No valid lifetimes are left on the RA, so we might
 		 * as well punt it. */
-		if (!valid && TAILQ_FIRST(&rap->addrs) == NULL)
+		if (!valid && !validone)
 			ipv6nd_free_ra(rap);
 		else
-			validone = 1;
+			anyvalid = 1;
 	}
 
 	if (timespecisset(&next))
@@ -1400,7 +1404,7 @@
 	}
 
 	/* No valid routers? Kill any DHCPv6. */
-	if (!validone)
+	if (!anyvalid)
 		dhcp6_dropnondelegates(ifp);
 }