diff options
| author | Roy Marples <roy@marples.name> | 2018-03-19 15:39:05 +0000 |
|---|---|---|
| committer | Roy Marples <roy@marples.name> | 2018-03-19 15:39:05 +0000 |
| commit | 1437db1d25f09c5235ed792bd278ee3f0f17dd65 (patch) | |
| tree | decb2c14336f00dff8f505e394e099ec8a2c40ba /src/ipv6.c | |
| parent | 81edfe77f1ab8c5e9d5761fda73506d2a28710fb (diff) | |
| download | dhcpcd-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.c | 26 |
1 files changed, 24 insertions, 2 deletions
@@ -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) { |
