Skip to content

Commit

Permalink
DHCP6: Don't remove delegated prefix addresses on start or fail
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
rsmarples committed Jun 26, 2024
1 parent 8bc7607 commit 4908d93
Show file tree
Hide file tree
Showing 4 changed files with 22 additions and 18 deletions.
13 changes: 6 additions & 7 deletions src/dhcp6.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand All @@ -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);
}
}
}
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -2732,7 +2732,7 @@ dhcp6_readlease(struct interface *ifp, int validate)
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;
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand Down
17 changes: 10 additions & 7 deletions src/ipv6.c
Original file line number Diff line number Diff line change
Expand Up @@ -615,18 +615,19 @@ 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.
* This should ensure the reject route will be restored. */
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
}

Expand Down Expand Up @@ -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;
Expand All @@ -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 ||
Expand Down Expand Up @@ -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);
Expand Down
8 changes: 5 additions & 3 deletions src/ipv6.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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 *);
Expand Down Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion src/ipv6nd.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down

0 comments on commit 4908d93

Please sign in to comment.