summaryrefslogtreecommitdiffstats
path: root/src/ipv6nd.c
diff options
context:
space:
mode:
authorRoy Marples <roy@marples.name>2020-04-29 16:33:57 +0100
committerRoy Marples <roy@marples.name>2020-04-29 16:33:57 +0100
commit787d42df9d4cbddc1acd771fd86833f0cbce0ede (patch)
treebd83e1176fa11bac8f777b92f559b21cb9f8c910 /src/ipv6nd.c
parentb38ba89bea76ef8166db19f6b0e3e967c46b9203 (diff)
downloaddhcpcd-787d42df9d4cbddc1acd771fd86833f0cbce0ede.tar.xz
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.
Diffstat (limited to 'src/ipv6nd.c')
-rw-r--r--src/ipv6nd.c20
1 files changed, 17 insertions, 3 deletions
diff --git a/src/ipv6nd.c b/src/ipv6nd.c
index 18f6c0a5..77719041 100644
--- a/src/ipv6nd.c
+++ b/src/ipv6nd.c
@@ -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))