]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
inet6: Set default ND timers before a RA arrives after preservation
authorRoy Marples <roy@marples.name>
Wed, 29 Apr 2020 15:33:57 +0000 (16:33 +0100)
committerRoy Marples <roy@marples.name>
Wed, 29 Apr 2020 15:33:57 +0000 (16:33 +0100)
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.

src/ipv6nd.c

index 18f6c0a58dcedeeecf4fb17b7c51988f64b5420c..777190419f87a32c75db435b87bb163e1fc23110 100644 (file)
@@ -638,7 +638,6 @@ ipv6nd_applyra(struct interface *ifp)
 {
        struct ra *rap;
        struct rs_state *state = RS_STATE(ifp);
-
        struct ra defra = {
                .iface = ifp,
                .hoplimit = IPV6_DEFHLIM ,
@@ -647,12 +646,12 @@ ipv6nd_applyra(struct interface *ifp)
        };
 
        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 @@ ipv6nd_handlera(struct dhcpcd_ctx *ctx,
                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))