]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
DHCP6: Rework delegation deprecation
authorRoy Marples <roy@marples.name>
Tue, 17 Dec 2019 22:16:26 +0000 (22:16 +0000)
committerRoy Marples <roy@marples.name>
Tue, 17 Dec 2019 22:16:26 +0000 (22:16 +0000)
Split ipv6_addaddrs out so ipv6_doaddr can operate on a single address.
Call this when deprecating delegated addresses to avoid calling
ipv6_addaddrs.

This allows a more simple ipv6_addaddrs that doesn't need to test
which address collection we are deleting from and removes DHCPv6
specific code from the generic IPv6 module.

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

index b3f16b911a6ef856756e66978f76f1634e954607..ed5fe8d698c2c8f35fb1a0a63e59e5d75ef77f2a 100644 (file)
@@ -2351,11 +2351,53 @@ dhcp6_findia(struct interface *ifp, struct dhcp6_message *m, size_t l,
        return i;
 }
 
+#ifndef SMALL
+static void
+dhcp6_deprecatedele(struct ipv6_addr *ia)
+{
+       struct ipv6_addr *da, *dan, *dda;
+       struct timespec now;
+       struct dhcp6_state *state;
+
+       timespecclear(&now);
+       TAILQ_FOREACH_SAFE(da, &ia->pd_pfxs, pd_next, dan) {
+               if (ia->prefix_vltime == 0) {
+                       if (da->prefix_vltime != 0)
+                               da->prefix_vltime = 0;
+                       else
+                               continue;
+               } else if (da->prefix_pltime != 0)
+                       da->prefix_pltime = 0;
+               else
+                       continue;
+
+               if (ipv6_doaddr(da, &now) != -1)
+                       continue;
+
+               /* Delegation deleted, forget it. */
+               TAILQ_REMOVE(&ia->pd_pfxs, da, pd_next);
+
+               /* Delete it from the interface. */
+               state = D6_STATE(da->iface);
+               TAILQ_FOREACH(dda, &state->addrs, next) {
+                       if (IN6_ARE_ADDR_EQUAL(&dda->addr, &da->addr))
+                               break;
+               }
+               if (dda != NULL) {
+                       TAILQ_REMOVE(&state->addrs, dda, next);
+                       ipv6_freeaddr(dda);
+               }
+       }
+}
+#endif
+
 static void
 dhcp6_deprecateaddrs(struct ipv6_addrhead *addrs)
 {
        struct ipv6_addr *ia, *ian;
+       struct timespec now;
 
+       timespecclear(&now);
        TAILQ_FOREACH_SAFE(ia, addrs, next, ian) {
                if (ia->flags & IPV6_AF_EXTENDED)
                        ;
@@ -2373,24 +2415,8 @@ dhcp6_deprecateaddrs(struct ipv6_addrhead *addrs)
 #ifndef SMALL
                /* If we delegated from this prefix, deprecate or remove
                 * the delegations. */
-               if (ia->flags & IPV6_AF_DELEGATEDPFX) {
-                       struct ipv6_addr *da;
-                       bool touched = false;
-
-                       TAILQ_FOREACH(da, &ia->pd_pfxs, pd_next) {
-                               if (ia->prefix_vltime == 0) {
-                                       if (da->prefix_vltime != 0) {
-                                               da->prefix_vltime = 0;
-                                               touched = true;
-                                       }
-                               } else if (da->prefix_pltime != 0) {
-                                       da->prefix_pltime = 0;
-                                       touched = true;
-                               }
-                       }
-                       if (touched)
-                               ipv6_addaddrs(&ia->pd_pfxs);
-               }
+               if (ia->flags & IPV6_AF_DELEGATEDPFX)
+                       dhcp6_deprecatedele(ia);
 #endif
 
                if (ia->flags & IPV6_AF_REQUEST) {
index d3dfe064a7335145973fc44f554de3226c2fdf66..347cb30329cd7d16bbd705b36b15db0698c37b23 100644 (file)
@@ -898,52 +898,54 @@ ipv6_findaddr(struct dhcpcd_ctx *ctx, const struct in6_addr *addr, unsigned int
 #endif
 }
 
+int
+ipv6_doaddr(struct ipv6_addr *ia, struct timespec *now)
+{
+
+       /* A delegated prefix is not an address. */
+       if (ia->flags & IPV6_AF_DELEGATEDPFX)
+               return 0;
+
+       if (ia->prefix_vltime == 0) {
+               if (ia->flags & IPV6_AF_ADDED)
+                       ipv6_deleteaddr(ia);
+               eloop_q_timeout_delete(ia->iface->ctx->eloop,
+                   0, NULL, ia);
+               if (ia->flags & IPV6_AF_REQUEST) {
+                       ia->flags &= ~IPV6_AF_ADDED;
+                       return 0;
+               }
+               return -1;
+       }
+
+       if (ia->flags & IPV6_AF_STALE ||
+           IN6_IS_ADDR_UNSPECIFIED(&ia->addr))
+               return 0;
+
+       if (!timespecisset(now))
+               clock_gettime(CLOCK_MONOTONIC, now);
+       ipv6_addaddr(ia, now);
+       return ia->flags & IPV6_AF_NEW ? 1 : 0;
+}
+
 ssize_t
-ipv6_addaddrs(struct ipv6_addrhead *addrs)
+ipv6_addaddrs(struct ipv6_addrhead *iaddrs)
 {
-       struct ipv6_addr *ap, *apn;
-       ssize_t i;
        struct timespec now;
+       struct ipv6_addr *ia, *ian;
+       ssize_t i, r;
 
        i = 0;
        timespecclear(&now);
-       TAILQ_FOREACH_SAFE(ap, addrs, next, apn) {
-               /* A delegated prefix is not an address. */
-               if (ap->flags & IPV6_AF_DELEGATEDPFX)
-                       continue;
-               if (ap->prefix_vltime == 0) {
-                       if (ap->flags & IPV6_AF_ADDED) {
-                               ipv6_deleteaddr(ap);
-                               i++;
-                       }
-                       eloop_q_timeout_delete(ap->iface->ctx->eloop,
-                           0, NULL, ap);
-                       if (ap->flags & IPV6_AF_REQUEST) {
-                               ap->flags &= ~IPV6_AF_ADDED;
-                       } else {
-#ifndef SMALL
-                               if (ap->delegating_prefix != NULL &&
-                                   addrs == &ap->delegating_prefix->pd_pfxs) {
-                                       TAILQ_REMOVE(addrs, ap, pd_next);
-                                       ap->delegating_prefix = NULL;
-                               } else
-#endif
-                               {
-                                       TAILQ_REMOVE(addrs, ap, next);
-                                       ipv6_freeaddr(ap);
-                               }
-                       }
-               } else if (!(ap->flags & IPV6_AF_STALE) &&
-                   !IN6_IS_ADDR_UNSPECIFIED(&ap->addr))
-               {
-                       if (ap->flags & IPV6_AF_NEW)
-                               i++;
-                       if (!timespecisset(&now))
-                               clock_gettime(CLOCK_MONOTONIC, &now);
-                       ipv6_addaddr(ap, &now);
+       TAILQ_FOREACH_SAFE(ia, iaddrs, next, ian) {
+               r = ipv6_doaddr(ia, &now);
+               if (r != 0)
+                       i++;
+               if (r == -1) {
+                       TAILQ_REMOVE(iaddrs, ia, next);
+                       ipv6_freeaddr(ia);
                }
        }
-
        return i;
 }
 
index cc3e8a676e99628d468238105fd626a08dc10bfc..49c367655d7385cadc2b9a4d111a22e388ba20b2 100644 (file)
@@ -247,6 +247,7 @@ void ipv6_checkaddrflags(void *);
 void ipv6_markaddrsstale(struct interface *, unsigned int);
 void ipv6_deletestaleaddrs(struct interface *);
 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,