]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
DHCP6: Don't remove delegated prefix addresses on start or fail
authorRoy Marples <roy@marples.name>
Wed, 26 Jun 2024 08:36:35 +0000 (09:36 +0100)
committerRoy Marples <roy@marples.name>
Wed, 26 Jun 2024 08:36:35 +0000 (09:36 +0100)
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.

src/dhcp6.c
src/ipv6.c
src/ipv6.h
src/ipv6nd.c

index 0f1ba25f1285f052a8c60eea0fca999ed77b991c..50154b9a7c15dd28e2c1b4ca7a89befa359322ac 100644 (file)
@@ -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;
index c08f0ee5edb6e73e63deaf83f64864db7d19cbbe..b6136c088d3684dde82161120a1aa5f088d18f41 100644 (file)
@@ -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);
index a895e24713251b33bcaedfb219dd95fab09c8d3a..7096d3816deb0150682a72028fa0c97b0cde9306 100644 (file)
@@ -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);
index 06d19cff11d8bf468232e516d0e419e843147452..20ac28cfb6b7bf262edc4124acdcc7f70081d674 100644 (file)
@@ -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);