]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Remove AF_UNSPEC and has_prefix from radix tree
authorOndřej Surý <ondrej@sury.org>
Sat, 21 Mar 2026 16:26:30 +0000 (17:26 +0100)
committerOndřej Surý <ondrej@sury.org>
Wed, 1 Jul 2026 04:06:10 +0000 (06:06 +0200)
Instead of treating AF_UNSPEC as a special "any" prefix that sets
both IPv4 and IPv6 data slots, insert two separate entries (one
per address family). Both land on the same 0/0 node via the
existing dual-family data[] mechanism.

This eliminates AF_UNSPEC handling from isc_radix_insert (4 branch
blocks removed), removes the has_prefix bool from isc_radix_node_t
(using family==0 for glue nodes instead), and simplifies the
NETADDR_TO_PREFIX_T macro.

lib/dns/acl.c
lib/dns/iptable.c
lib/isc/include/isc/radix.h
lib/isc/radix.c

index a42f9fde431e55e3f7db3ddbbf7913c040b3ffbc..03c5bb5212bb8c77baa37683a16ac632773e08e1 100644 (file)
@@ -103,12 +103,12 @@ dns_acl_isanyornone(dns_acl_t *acl, bool pos) {
        /* Should never happen but let's be safe */
        if (acl == NULL || acl->iptable == NULL ||
            acl->iptable->radix == NULL || acl->iptable->radix->head == NULL ||
-           !acl->iptable->radix->head->has_prefix)
+           acl->iptable->radix->head->prefix.family == 0)
        {
                return false;
        }
 
-       if (acl->length != 0 || dns_acl_node_count(acl) != 1) {
+       if (acl->length != 0 || dns_acl_node_count(acl) != 2) {
                return false;
        }
 
index 9c00664bff1f0d51523fa74da121624613a33499..6c807add0653339d16fed7038343dfde28101bbc 100644 (file)
@@ -43,44 +43,51 @@ static bool dns_iptable_pos = true;
 /*
  * Add an IP prefix to an existing IP table
  */
+static isc_result_t
+iptable_addentry(dns_iptable_t *tab, isc_prefix_t *pfx, bool pos) {
+       isc_radix_node_t *node = NULL;
+       isc_result_t result;
+
+       result = isc_radix_insert(tab->radix, &node, NULL, pfx);
+       if (result != ISC_R_SUCCESS) {
+               return result;
+       }
+
+       /* If a node already contains data, don't overwrite it */
+       int fam = ISC_RADIX_FAMILY(pfx);
+       if (node->data[fam] == NULL) {
+               node->data[fam] = pos ? &dns_iptable_pos : &dns_iptable_neg;
+       }
+
+       return ISC_R_SUCCESS;
+}
+
 isc_result_t
 dns_iptable_addprefix(dns_iptable_t *tab, const isc_netaddr_t *addr,
                      uint16_t bitlen, bool pos) {
        isc_result_t result;
-       isc_prefix_t pfx;
-       isc_radix_node_t *node = NULL;
-       int i;
 
        INSIST(DNS_IPTABLE_VALID(tab));
        INSIST(tab->radix != NULL);
 
-       NETADDR_TO_PREFIX_T(addr, pfx, bitlen);
-
-       result = isc_radix_insert(tab->radix, &node, NULL, &pfx);
-       if (result != ISC_R_SUCCESS) {
-               return result;
-       }
+       if (addr == NULL) {
+               /*
+                * "any" or "none": insert both IPv4 and IPv6 wildcard
+                * entries so they match all addresses.
+                */
+               isc_prefix_t pfx4 = { .family = AF_INET, .bitlen = 0 };
+               isc_prefix_t pfx6 = { .family = AF_INET6, .bitlen = 0 };
 
-       /* If a node already contains data, don't overwrite it */
-       if (pfx.family == AF_UNSPEC) {
-               /* "any" or "none" */
-               INSIST(pfx.bitlen == 0);
-               for (i = 0; i < RADIX_FAMILIES; i++) {
-                       if (node->data[i] == NULL) {
-                               node->data[i] = pos ? &dns_iptable_pos
-                                                   : &dns_iptable_neg;
-                       }
-               }
-       } else {
-               /* any other prefix */
-               int fam = ISC_RADIX_FAMILY(&pfx);
-               if (node->data[fam] == NULL) {
-                       node->data[fam] = pos ? &dns_iptable_pos
-                                             : &dns_iptable_neg;
+               result = iptable_addentry(tab, &pfx4, pos);
+               if (result != ISC_R_SUCCESS) {
+                       return result;
                }
+               return iptable_addentry(tab, &pfx6, pos);
        }
 
-       return ISC_R_SUCCESS;
+       isc_prefix_t pfx;
+       NETADDR_TO_PREFIX_T(addr, pfx, bitlen);
+       return iptable_addentry(tab, &pfx, pos);
 }
 
 /*
index c3eb53f02aa21b4cd3b2459204c85998c35ec520..d738a9efe629b6e8e39a0866716719dc156c6d8b 100644 (file)
 #include <isc/types.h>
 
 typedef struct isc_prefix {
-       unsigned int family; /* AF_INET | AF_INET6, or AF_UNSPEC for
-                             * "any" */
-       unsigned int bitlen; /* 0 for "any" */
+       unsigned int family; /* AF_INET | AF_INET6 (0 means no prefix) */
+       unsigned int bitlen; /* prefix length in bits */
        union {
                struct in_addr  sin;
                struct in6_addr sin6;
        } add;
 } isc_prefix_t;
 
-#define NETADDR_TO_PREFIX_T(na, pt, bits)                                \
-       do {                                                             \
-               const void *p = na;                                      \
-               memset(&(pt), 0, sizeof(pt));                            \
-               if (p != NULL) {                                         \
-                       (pt).family = (na)->family;                      \
-                       (pt).bitlen = (bits);                            \
-                       if ((pt).family == AF_INET6) {                   \
-                               memmove(&(pt).add.sin6, &(na)->type.in6, \
-                                       ((bits) + 7) / 8);               \
-                       } else                                           \
-                               memmove(&(pt).add.sin, &(na)->type.in,   \
-                                       ((bits) + 7) / 8);               \
-               } else {                                                 \
-                       (pt).family = AF_UNSPEC;                         \
-                       (pt).bitlen = 0;                                 \
-               }                                                        \
+#define NETADDR_TO_PREFIX_T(na, pt, bits)                        \
+       do {                                                     \
+               memset(&(pt), 0, sizeof(pt));                    \
+               (pt).family = (na)->family;                      \
+               (pt).bitlen = (bits);                            \
+               if ((pt).family == AF_INET6) {                   \
+                       memmove(&(pt).add.sin6, &(na)->type.in6, \
+                               ((bits) + 7) / 8);               \
+               } else {                                         \
+                       memmove(&(pt).add.sin, &(na)->type.in,   \
+                               ((bits) + 7) / 8);               \
+               }                                                \
        } while (0)
 
 typedef void (*isc_radix_destroyfunc_t)(void *);
@@ -85,12 +79,11 @@ typedef struct isc_radix_node {
        struct isc_radix_node *parent; /* may be used */
        void                  *data[RADIX_FAMILIES]; /* pointers to IPv4
                                                      * and IPV6 data */
-       isc_prefix_t           prefix;               /* inline prefix data */
-       uint32_t               bit;   /* bit length of the prefix */
-       int node_num[RADIX_FAMILIES]; /* which node this was in
-                                      * the tree, or -1 for
-                                      * glue nodes */
-       bool has_prefix;
+       isc_prefix_t           prefix;               /* inline prefix data;
+                                                     * family==0 for glue */
+       uint32_t bit;                                /* bit position */
+       int      node_num[RADIX_FAMILIES];           /* insertion order,
+                                                     * or -1 for glue */
 } isc_radix_node_t;
 
 #define RADIX_TREE_MAGIC    ISC_MAGIC('R', 'd', 'x', 'T')
@@ -189,7 +182,7 @@ isc_radix_process(isc_radix_tree_t *radix, isc_radix_processfunc_t func);
                isc_radix_node_t **Xsp = Xstack;              \
                isc_radix_node_t  *Xrn = (Xhead);             \
                while ((Xnode = Xrn)) {                       \
-                       if (Xnode->has_prefix)
+                       if (Xnode->prefix.family != 0)
 
 #define RADIX_WALK_END                       \
        if (Xrn->l) {                        \
index 83bfc913a8941a4f28fbc2e56d6ff33b0b2b3a60..8df0bcd6ae06245d720917fdaf535ab998c9bfa8 100644 (file)
@@ -55,7 +55,6 @@ _new_node(isc_mem_t *mctx, isc_prefix_t *prefix, uint32_t bit) {
        };
        if (prefix != NULL) {
                node->prefix = *prefix;
-               node->has_prefix = true;
        }
        return node;
 }
@@ -92,7 +91,7 @@ _clear_radix(isc_radix_tree_t *radix, isc_radix_destroyfunc_t func) {
                        isc_radix_node_t *l = Xrn->l;
                        isc_radix_node_t *r = Xrn->r;
 
-                       if (Xrn->has_prefix) {
+                       if (Xrn->prefix.family != 0) {
                                if (func != NULL) {
                                        func(Xrn->data);
                                }
@@ -167,7 +166,7 @@ isc_radix_search(isc_radix_tree_t *radix, isc_radix_node_t **target,
        bitlen = prefix->bitlen;
 
        while (node != NULL && node->bit < bitlen) {
-               if (node->has_prefix) {
+               if (node->prefix.family != 0) {
                        stack[cnt++] = node;
                }
 
@@ -179,7 +178,7 @@ isc_radix_search(isc_radix_tree_t *radix, isc_radix_node_t **target,
                }
        }
 
-       if (node != NULL && node->has_prefix) {
+       if (node != NULL && node->prefix.family != 0) {
                stack[cnt++] = node;
        }
 
@@ -217,12 +216,13 @@ isc_radix_insert(isc_radix_tree_t *radix, isc_radix_node_t **target,
                 isc_radix_node_t *source, isc_prefix_t *prefix) {
        isc_radix_node_t *node, *new_node, *parent, *glue = NULL;
        u_char *addr, *test_addr;
-       uint32_t bitlen, fam, check_bit, differ_bit;
+       uint32_t bitlen, check_bit, differ_bit;
        uint32_t i, j, r;
 
        REQUIRE(radix != NULL);
        REQUIRE(target != NULL && *target == NULL);
-       REQUIRE(prefix != NULL || (source != NULL && source->has_prefix));
+       REQUIRE(prefix != NULL ||
+               (source != NULL && source->prefix.family != 0));
        RUNTIME_CHECK(prefix == NULL || prefix->bitlen <= radix->maxbits);
 
        if (prefix == NULL) {
@@ -232,7 +232,6 @@ isc_radix_insert(isc_radix_tree_t *radix, isc_radix_node_t **target,
        INSIST(prefix != NULL);
 
        bitlen = prefix->bitlen;
-       fam = prefix->family;
 
        if (radix->head == NULL) {
                node = _new_node(radix->mctx, prefix, bitlen);
@@ -255,14 +254,7 @@ isc_radix_insert(isc_radix_tree_t *radix, isc_radix_node_t **target,
                        }
                } else {
                        int next = ++radix->num_added_node;
-                       if (fam == AF_UNSPEC) {
-                               /* "any" or "none" */
-                               for (i = 0; i < RADIX_FAMILIES; i++) {
-                                       node->node_num[i] = next;
-                               }
-                       } else {
-                               node->node_num[ISC_RADIX_FAMILY(prefix)] = next;
-                       }
+                       node->node_num[ISC_RADIX_FAMILY(prefix)] = next;
                }
                radix->head = node;
                radix->num_active_node++;
@@ -273,7 +265,7 @@ isc_radix_insert(isc_radix_tree_t *radix, isc_radix_node_t **target,
        addr = isc_prefix_touchar(prefix);
        node = radix->head;
 
-       while (node->bit < bitlen || !node->has_prefix) {
+       while (node->bit < bitlen || node->prefix.family == 0) {
                if (node->bit < radix->maxbits &&
                    BIT_TEST(addr[node->bit >> 3], 0x80 >> (node->bit & 0x07)))
                {
@@ -291,7 +283,7 @@ isc_radix_insert(isc_radix_tree_t *radix, isc_radix_node_t **target,
                INSIST(node != NULL);
        }
 
-       INSIST(node->has_prefix);
+       INSIST(node->prefix.family != 0);
 
        test_addr = isc_prefix_touchar(&node->prefix);
        /* Find the first bit different. */
@@ -325,7 +317,7 @@ isc_radix_insert(isc_radix_tree_t *radix, isc_radix_node_t **target,
        }
 
        if (differ_bit == bitlen && node->bit == bitlen) {
-               if (node->has_prefix) {
+               if (node->prefix.family != 0) {
                        /* Set node_num only if it hasn't been set before */
                        if (source != NULL) {
                                /* Merging nodes */
@@ -340,30 +332,16 @@ isc_radix_insert(isc_radix_tree_t *radix, isc_radix_node_t **target,
                                        }
                                }
                        } else {
-                               if (fam == AF_UNSPEC) {
-                                       /* "any" or "none" */
-                                       int next = radix->num_added_node + 1;
-                                       for (i = 0; i < RADIX_FAMILIES; i++) {
-                                               if (node->node_num[i] == -1) {
-                                                       node->node_num[i] =
-                                                               next;
-                                                       radix->num_added_node =
-                                                               next;
-                                               }
-                                       }
-                               } else {
-                                       int foff = ISC_RADIX_FAMILY(prefix);
-                                       if (node->node_num[foff] == -1) {
-                                               node->node_num[foff] =
-                                                       ++radix->num_added_node;
-                                       }
+                               int foff = ISC_RADIX_FAMILY(prefix);
+                               if (node->node_num[foff] == -1) {
+                                       node->node_num[foff] =
+                                               ++radix->num_added_node;
                                }
                        }
                        *target = node;
                        return ISC_R_SUCCESS;
                } else {
                        node->prefix = *prefix;
-                       node->has_prefix = true;
                }
                INSIST(node->data[RADIX_V4] == NULL &&
                       node->node_num[RADIX_V4] == -1 &&
@@ -381,14 +359,7 @@ isc_radix_insert(isc_radix_tree_t *radix, isc_radix_node_t **target,
                        }
                } else {
                        int next = ++radix->num_added_node;
-                       if (fam == AF_UNSPEC) {
-                               /* "any" or "none" */
-                               for (i = 0; i < RADIX_FAMILIES; i++) {
-                                       node->node_num[i] = next;
-                               }
-                       } else {
-                               node->node_num[ISC_RADIX_FAMILY(prefix)] = next;
-                       }
+                       node->node_num[ISC_RADIX_FAMILY(prefix)] = next;
                }
                *target = node;
                return ISC_R_SUCCESS;
@@ -412,14 +383,7 @@ isc_radix_insert(isc_radix_tree_t *radix, isc_radix_node_t **target,
                }
        } else {
                int next = ++radix->num_added_node;
-               if (fam == AF_UNSPEC) {
-                       /* "any" or "none" */
-                       for (i = 0; i < RADIX_FAMILIES; i++) {
-                               new_node->node_num[i] = next;
-                       }
-               } else {
-                       new_node->node_num[ISC_RADIX_FAMILY(prefix)] = next;
-               }
+               new_node->node_num[ISC_RADIX_FAMILY(prefix)] = next;
        }
 
        if (node->bit == differ_bit) {
@@ -500,7 +464,7 @@ isc_radix_remove(isc_radix_tree_t *radix, isc_radix_node_t *node) {
                 * This might be a placeholder node -- have to check and
                 * make sure there is a prefix associated with it!
                 */
-               node->has_prefix = false;
+               memset(&node->prefix, 0, sizeof(node->prefix));
                memset(node->data, 0, sizeof(node->data));
                return;
        }
@@ -528,7 +492,7 @@ isc_radix_remove(isc_radix_tree_t *radix, isc_radix_node_t *node) {
                isc_mem_put(radix->mctx, node, sizeof(*node));
                radix->num_active_node--;
 
-               if (parent->has_prefix) {
+               if (parent->prefix.family != 0) {
                        return;
                }