From: Roy Marples Date: Tue, 23 Jun 2026 01:17:10 +0000 (+0100) Subject: DHCPv6: When deprecating addresses, restart on prefix deletions X-Git-Url: http://git.ipfire.org/index.cgi?a=commitdiff_plain;ds=sidebyside;p=thirdparty%2Fdhcpcd.git DHCPv6: When deprecating addresses, restart on prefix deletions As that might invalidate the next address to iterate on. Reported-by: CuB3y0nd --- diff --git a/src/dhcp6.c b/src/dhcp6.c index 460040bd..02464eb3 100644 --- a/src/dhcp6.c +++ b/src/dhcp6.c @@ -2561,12 +2561,13 @@ dhcp6_findia(struct interface *ifp, struct dhcp6_message *m, size_t l, } #ifndef SMALL -static void +static bool dhcp6_deprecatedele(struct ipv6_addr *ia) { struct ipv6_addr *da, *dan, *dda; struct timespec now; struct dhcp6_state *state; + bool freed = false; timespecclear(&now); TAILQ_FOREACH_SAFE(da, &ia->pd_pfxs, pd_next, dan) { @@ -2595,11 +2596,14 @@ dhcp6_deprecatedele(struct ipv6_addr *ia) if (IN6_ARE_ADDR_EQUAL(&dda->addr, &da->addr)) break; } - if (dda != NULL) { + if (dda != ia && dda != NULL) { TAILQ_REMOVE(&state->addrs, dda, next); ipv6_freeaddr(dda); + freed = true; } } + + return freed; } #endif @@ -2607,7 +2611,11 @@ static void dhcp6_deprecateaddrs(struct ipv6_addrhead *addrs) { struct ipv6_addr *ia, *ian; +#ifndef SMALL + bool again; +#endif +again: TAILQ_FOREACH_SAFE(ia, addrs, next, ian) { if (ia->flags & IPV6_AF_EXTENDED) ; @@ -2629,7 +2637,9 @@ dhcp6_deprecateaddrs(struct ipv6_addrhead *addrs) /* If we delegated from this prefix, deprecate or remove * the delegations. */ if (ia->flags & IPV6_AF_PFXDELEGATION) - dhcp6_deprecatedele(ia); + again = dhcp6_deprecatedele(ia); + else + again = false; #endif if (ia->flags & IPV6_AF_REQUEST) { @@ -2642,6 +2652,11 @@ dhcp6_deprecateaddrs(struct ipv6_addrhead *addrs) if (!(ia->flags & IPV6_AF_EXTENDED)) ipv6_deleteaddr(ia); ipv6_freeaddr(ia); +#ifndef SMALL + /* Deletion may invalidate the next pointer so restart */ + if (again) + goto again; +#endif } }