summaryrefslogtreecommitdiffstats
path: root/src/ipv6.c
diff options
context:
space:
mode:
authorRoy Marples <roy@marples.name>2018-03-19 15:39:05 +0000
committerRoy Marples <roy@marples.name>2018-03-19 15:39:05 +0000
commit1437db1d25f09c5235ed792bd278ee3f0f17dd65 (patch)
treedecb2c14336f00dff8f505e394e099ec8a2c40ba /src/ipv6.c
parent81edfe77f1ab8c5e9d5761fda73506d2a28710fb (diff)
downloaddhcpcd-1437db1d25f09c5235ed792bd278ee3f0f17dd65.tar.xz
link: detect buffer overflow / desync and relearn interface state
It's possible for the internal kernel buffer that reports network events to overflow. On Linux and NetBSD* this is handled by ENOBUFS being returned by recv(2). On OpenBSD there is a special route(4) message RTM_DESYNC. All other OS's don't seem to report this error, so dhcpcd cannot detect it. * I will commit a patch to NetBSD soon for this and will request a pullup to NetBSD-8.
Diffstat (limited to 'src/ipv6.c')
-rw-r--r--src/ipv6.c26
1 files changed, 24 insertions, 2 deletions
diff --git a/src/ipv6.c b/src/ipv6.c
index 615aed22..282d40e5 100644
--- a/src/ipv6.c
+++ b/src/ipv6.c
@@ -1134,6 +1134,7 @@ ipv6_handleifa(struct dhcpcd_ctx *ctx,
TAILQ_INSERT_TAIL(&state->addrs, ia, next);
}
ia->addr_flags = addrflags;
+ ia->flags &= ~IPV6_AF_STALE;
#ifdef IPV6_MANAGETEMPADDR
if (ia->addr_flags & IN6_IFF_TEMPORARY)
ia->flags |= IPV6_AF_TEMPORARY;
@@ -1973,18 +1974,39 @@ again:
}
void
-ipv6_settempstale(struct interface *ifp)
+ipv6_markaddrsstale(struct interface *ifp, unsigned int flags)
{
struct ipv6_state *state;
struct ipv6_addr *ia;
state = IPV6_STATE(ifp);
+ if (state == NULL)
+ return;
+
TAILQ_FOREACH(ia, &state->addrs, next) {
- if (ia->flags & IPV6_AF_TEMPORARY)
+ if (flags == 0 || ia->flags & flags)
ia->flags |= IPV6_AF_STALE;
}
}
+void
+ipv6_deletestaleaddrs(struct interface *ifp)
+{
+ struct ipv6_state *state;
+ struct ipv6_addr *ia, *ia1;
+
+ state = IPV6_STATE(ifp);
+ if (state == NULL)
+ return;
+
+ TAILQ_FOREACH_SAFE(ia, &state->addrs, next, ia1) {
+ if (ia->flags & IPV6_AF_STALE)
+ ipv6_handleifa(ifp->ctx, RTM_DELADDR,
+ ifp->ctx->ifaces, ifp->name,
+ &ia->addr, ia->prefix_len, 0, 0);
+ }
+}
+
struct ipv6_addr *
ipv6_settemptime(struct ipv6_addr *ia, int flags)
{