summaryrefslogtreecommitdiffstats
path: root/src/ipv6nd.c
diff options
context:
space:
mode:
authorRoy Marples <roy@marples.name>2019-08-30 11:06:20 +0100
committerRoy Marples <roy@marples.name>2019-08-30 11:06:20 +0100
commit2c340935edbe3a6e9b1ff50ff7f9f23414986180 (patch)
tree57a57bf549309a1a1c4a2044a00aad5db6a61252 /src/ipv6nd.c
parent9dff4f78f2ac04d207953982cb649ac927eb4f07 (diff)
downloaddhcpcd-2c340935edbe3a6e9b1ff50ff7f9f23414986180.tar.xz
inet6: Stop reacting to kernel neighbour messages about a router
It's unreliable and very corner case. See the comment for the ipv6nd_neighbour() function.
Diffstat (limited to 'src/ipv6nd.c')
-rw-r--r--src/ipv6nd.c21
1 files changed, 15 insertions, 6 deletions
diff --git a/src/ipv6nd.c b/src/ipv6nd.c
index cb9e1086..35401b75 100644
--- a/src/ipv6nd.c
+++ b/src/ipv6nd.c
@@ -554,8 +554,21 @@ ipv6nd_startexpire(struct interface *ifp)
ipv6nd_expire, ifp);
}
+/*
+ * Neighbour reachability.
+ *
+ * RFC 4681 6.2.5 says when a node is no longer a router it MUST
+ * send a RA with a zero lifetime.
+ * All OS's I know of set the NA router flag if they are a router
+ * or not and disregard that they are actively advertising or
+ * shutting down. If the interface is disabled, it cant't send a NA at all.
+ *
+ * As such we CANNOT rely on the NA Router flag and MUST use
+ * unreachability or receive a RA with a lifetime of zero to remove
+ * the node as a default router.
+ */
void
-ipv6nd_neighbour(struct dhcpcd_ctx *ctx, struct in6_addr *addr, int flags)
+ipv6nd_neighbour(struct dhcpcd_ctx *ctx, struct in6_addr *addr, bool reachable)
{
struct ra *rap, *rapr;
@@ -570,11 +583,7 @@ ipv6nd_neighbour(struct dhcpcd_ctx *ctx, struct in6_addr *addr, int flags)
if (rap == NULL || rap->expired)
return;
- if (!(flags & IPV6ND_ROUTER) && rap->lifetime != 0) {
- loginfox("%s: %s is no longer a router",
- rap->iface->name, rap->sfrom);
- rap->lifetime = 0;
- } else if (flags & IPV6ND_REACHABLE) {
+ if (reachable) {
if (rap->isreachable)
return;
loginfox("%s: %s is reachable again",