From: Roy Marples Date: Wed, 26 Jun 2024 08:36:35 +0000 (+0100) Subject: DHCP6: Don't remove delegated prefix addresses on start or fail X-Git-Tag: v10.0.9~16 X-Git-Url: http://git.ipfire.org/gitweb/gitweb.cgi?a=commitdiff_plain;h=4908d931fc8208fb58fa26b3e921d1dab575e060;p=thirdparty%2Fdhcpcd.git DHCP6: Don't remove delegated prefix addresses on start or fail In the event where an interface is first delegated and then started, we don't want the reading of a lease file to remove the delegated prefixes or addresses. Neither do we want any DHCP6 failure to remove the delegated addresses. As such, we also can't test the actual DHCP6 state when building routes. Instead, just change the test for a delegated prefix or not so we can still prefer non delegated routes. While here, fix reject routes being restored for privsep. Fixes #333. --- diff --git a/src/dhcp6.c b/src/dhcp6.c index 0f1ba25f..50154b9a 100644 --- a/src/dhcp6.c +++ b/src/dhcp6.c @@ -1187,14 +1187,14 @@ dhcp6_get_op(uint16_t type) } static void -dhcp6_freedrop_addrs(struct interface *ifp, int drop, +dhcp6_freedrop_addrs(struct interface *ifp, int drop, unsigned int notflags, const struct interface *ifd) { struct dhcp6_state *state; state = D6_STATE(ifp); if (state) { - ipv6_freedrop_addrs(&state->addrs, drop, ifd); + ipv6_freedrop_addrs(&state->addrs, drop, notflags, ifd); if (drop) rt_build(ifp->ctx, AF_INET6); } @@ -1208,7 +1208,7 @@ static void dhcp6_delete_delegates(struct interface *ifp) if (ifp->ctx->ifaces) { TAILQ_FOREACH(ifp0, ifp->ctx->ifaces, next) { if (ifp0 != ifp) - dhcp6_freedrop_addrs(ifp0, 1, ifp); + dhcp6_freedrop_addrs(ifp0, 1, 0, ifp); } } } @@ -1779,7 +1779,7 @@ dhcp6_fail(struct interface *ifp) dhcp6_leaseextend(ifp); dhcp6_bind(ifp, NULL, NULL); } else { - dhcp6_freedrop_addrs(ifp, 1, NULL); + dhcp6_freedrop_addrs(ifp, 1, IPV6_AF_ANYDELEGATED, NULL); #ifndef SMALL dhcp6_delete_delegates(ifp); #endif @@ -2732,7 +2732,7 @@ out: return bytes; ex: - dhcp6_freedrop_addrs(ifp, 0, NULL); + dhcp6_freedrop_addrs(ifp, 0, IPV6_AF_ANYDELEGATED, NULL); dhcp_unlink(ifp->ctx, state->leasefile); free(state->new); state->new = NULL; @@ -3082,7 +3082,6 @@ dhcp6_find_delegates(struct interface *ifp) if (k) { loginfox("%s: adding delegated prefixes", ifp->name); state = D6_STATE(ifp); - state->state = DH6S_DELEGATED; ipv6_addaddrs(&state->addrs); rt_build(ifp->ctx, AF_INET6); dhcp6_script_try_run(ifp, 1); @@ -4153,7 +4152,7 @@ dhcp6_freedrop(struct interface *ifp, int drop, const char *reason) } #endif - dhcp6_freedrop_addrs(ifp, drop, NULL); + dhcp6_freedrop_addrs(ifp, drop, 0, NULL); free(state->old); state->old = state->new; state->old_len = state->new_len; diff --git a/src/ipv6.c b/src/ipv6.c index c08f0ee5..b6136c08 100644 --- a/src/ipv6.c +++ b/src/ipv6.c @@ -615,9 +615,8 @@ ipv6_deletedaddr(struct ipv6_addr *ia) #ifdef PRIVSEP if (!(ia->iface->ctx->options & DHCPCD_MANAGER)) ps_inet_closedhcp6(ia); -#elif defined(SMALL) - UNUSED(ia); -#else +#endif +#ifndef SMALL /* NOREJECT is set if we delegated exactly the prefix to another * address. * This can only be one address, so just clear the flag. @@ -625,8 +624,10 @@ ipv6_deletedaddr(struct ipv6_addr *ia) if (ia->delegating_prefix != NULL) ia->delegating_prefix->flags &= ~IPV6_AF_NOREJECT; #endif -#else - UNUSED(ia); +#endif + +#if !defined(DHCP6) || (!defined(PRIVSEP) && defined(SMALL)) + UNUSED(ia) #endif } @@ -1040,7 +1041,7 @@ ipv6_freeaddr(struct ipv6_addr *ia) void ipv6_freedrop_addrs(struct ipv6_addrhead *addrs, int drop, - const struct interface *ifd) + unsigned int notflags, const struct interface *ifd) { struct ipv6_addr *ap, *apn, *apf; struct timespec now; @@ -1050,6 +1051,8 @@ ipv6_freedrop_addrs(struct ipv6_addrhead *addrs, int drop, #endif timespecclear(&now); TAILQ_FOREACH_SAFE(ap, addrs, next, apn) { + if (ap->flags & notflags) + continue; #ifndef SMALL if (ifd != NULL && (ap->delegating_prefix == NULL || @@ -1862,7 +1865,7 @@ ipv6_freedrop(struct interface *ifp, int drop) free(cb); } - ipv6_freedrop_addrs(&state->addrs, drop ? 2 : 0, NULL); + ipv6_freedrop_addrs(&state->addrs, drop ? 2 : 0, 0, NULL); if (drop) { if (ifp->ctx->ra_routers != NULL) rt_build(ifp->ctx, AF_INET6); diff --git a/src/ipv6.h b/src/ipv6.h index a895e247..7096d381 100644 --- a/src/ipv6.h +++ b/src/ipv6.h @@ -217,8 +217,8 @@ struct ipv6_addr { #define IPV6_AF_ADDED (1U << 3) #define IPV6_AF_AUTOCONF (1U << 4) #define IPV6_AF_DADCOMPLETED (1U << 5) -#define IPV6_AF_DELEGATED (1U << 6) -#define IPV6_AF_DELEGATEDPFX (1U << 7) +#define IPV6_AF_DELEGATED (1U << 6) // Delegated from prefix +#define IPV6_AF_DELEGATEDPFX (1U << 7) // Delegated prefix #define IPV6_AF_NOREJECT (1U << 8) #define IPV6_AF_REQUEST (1U << 9) #define IPV6_AF_STATIC (1U << 10) @@ -231,6 +231,8 @@ struct ipv6_addr { #define IPV6_AF_TEMPORARY (1U << 16) #endif +#define IPV6_AF_ANYDELEGATED (IPV6_AF_DELEGATED | IPV6_AF_DELEGATEDPFX) + struct ll_callback { TAILQ_ENTRY(ll_callback) next; void (*callback)(void *); @@ -270,7 +272,7 @@ int ipv6_addaddr(struct ipv6_addr *, const struct timespec *); int ipv6_doaddr(struct ipv6_addr *, struct timespec *); ssize_t ipv6_addaddrs(struct ipv6_addrhead *addrs); void ipv6_deleteaddr(struct ipv6_addr *); -void ipv6_freedrop_addrs(struct ipv6_addrhead *, int, +void ipv6_freedrop_addrs(struct ipv6_addrhead *, int, unsigned int, const struct interface *); void ipv6_handleifa(struct dhcpcd_ctx *ctx, int, struct if_head *, const char *, const struct in6_addr *, uint8_t, int, pid_t); diff --git a/src/ipv6nd.c b/src/ipv6nd.c index 06d19cff..20ac28cf 100644 --- a/src/ipv6nd.c +++ b/src/ipv6nd.c @@ -842,7 +842,7 @@ ipv6nd_removefreedrop_ra(struct ra *rap, int remove_ra, int drop_ra) eloop_timeout_delete(rap->iface->ctx->eloop, NULL, rap); if (remove_ra) TAILQ_REMOVE(rap->iface->ctx->ra_routers, rap, next); - ipv6_freedrop_addrs(&rap->addrs, drop_ra, NULL); + ipv6_freedrop_addrs(&rap->addrs, drop_ra, 0, NULL); routeinfohead_free(&rap->rinfos); free(rap->data); free(rap);