From: Ondřej Surý Date: Sat, 21 Mar 2026 16:26:30 +0000 (+0100) Subject: Remove AF_UNSPEC and has_prefix from radix tree X-Git-Url: http://git.ipfire.org/gitweb/?a=commitdiff_plain;h=fc36519d59381fc7baf3d3f026372260e59c4622;p=thirdparty%2Fbind9.git Remove AF_UNSPEC and has_prefix from radix tree 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. --- diff --git a/lib/dns/acl.c b/lib/dns/acl.c index a42f9fde431..03c5bb5212b 100644 --- a/lib/dns/acl.c +++ b/lib/dns/acl.c @@ -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; } diff --git a/lib/dns/iptable.c b/lib/dns/iptable.c index 9c00664bff1..6c807add065 100644 --- a/lib/dns/iptable.c +++ b/lib/dns/iptable.c @@ -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); } /* diff --git a/lib/isc/include/isc/radix.h b/lib/isc/include/isc/radix.h index c3eb53f02aa..d738a9efe62 100644 --- a/lib/isc/include/isc/radix.h +++ b/lib/isc/include/isc/radix.h @@ -21,32 +21,26 @@ #include 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) { \ diff --git a/lib/isc/radix.c b/lib/isc/radix.c index 83bfc913a89..8df0bcd6ae0 100644 --- a/lib/isc/radix.c +++ b/lib/isc/radix.c @@ -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; }