changeset 5181:6788ac9191a7 draft

inet6: Set default ND timers before a RA arrives after preservation Other OS will just remove the RA's on carrier down and thus set default values, but not so on NetBSD. As such as need to set default values just before settings any values from the incoming RA. This allows us to change networks sensibly.
author Roy Marples <roy@marples.name>
date Wed, 29 Apr 2020 16:33:57 +0100
parents 0e4f56cb4c03
children 72d627ef016e
files src/ipv6nd.c
diffstat 1 files changed, 17 insertions(+), 3 deletions(-) [+]
line wrap: on
line diff
--- a/src/ipv6nd.c	Wed Apr 29 15:06:04 2020 +0000
+++ b/src/ipv6nd.c	Wed Apr 29 16:33:57 2020 +0100
@@ -638,7 +638,6 @@
 {
 	struct ra *rap;
 	struct rs_state *state = RS_STATE(ifp);
-
 	struct ra defra = {
 		.iface = ifp,
 		.hoplimit = IPV6_DEFHLIM ,
@@ -647,12 +646,12 @@
 	};
 
 	TAILQ_FOREACH(rap, ifp->ctx->ra_routers, next) {
-		if (rap->iface == ifp && !rap->expired)
+		if (rap->iface == ifp)
 			break;
 	}
 
 	/* If we have no Router Advertisement, then set default values. */
-	if (rap == NULL)
+	if (rap == NULL || rap->expired || rap->willexpire)
 		rap = &defra;
 
 	state->retrans = rap->retrans;
@@ -1131,6 +1130,21 @@
 		return;
 	}
 
+#ifdef NOCARRIER_PRESERVE_IP
+	/*
+	 * Because we preserve RA's and expire them quickly after
+	 * carrier up, it's important to reset the kernels notion of
+	 * reachable timers back to default values before applying
+	 * new RA values.
+	 */
+	TAILQ_FOREACH(rap, ctx->ra_routers, next) {
+		if (ifp == rap->iface)
+			break;
+	}
+	if (rap != NULL && rap->willexpire)
+		ipv6nd_applyra(ifp);
+#endif
+
 	TAILQ_FOREACH(rap, ctx->ra_routers, next) {
 		if (ifp == rap->iface &&
 		    IN6_ARE_ADDR_EQUAL(&rap->from, &from->sin6_addr))