/* 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;
}
/*
* 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);
}
/*
#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 *);
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')
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) { \
};
if (prefix != NULL) {
node->prefix = *prefix;
- node->has_prefix = true;
}
return node;
}
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);
}
bitlen = prefix->bitlen;
while (node != NULL && node->bit < bitlen) {
- if (node->has_prefix) {
+ if (node->prefix.family != 0) {
stack[cnt++] = node;
}
}
}
- if (node != NULL && node->has_prefix) {
+ if (node != NULL && node->prefix.family != 0) {
stack[cnt++] = node;
}
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) {
INSIST(prefix != NULL);
bitlen = prefix->bitlen;
- fam = prefix->family;
if (radix->head == NULL) {
node = _new_node(radix->mctx, prefix, bitlen);
}
} 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++;
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)))
{
INSIST(node != NULL);
}
- INSIST(node->has_prefix);
+ INSIST(node->prefix.family != 0);
test_addr = isc_prefix_touchar(&node->prefix);
/* Find the first bit different. */
}
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 */
}
}
} 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 &&
}
} 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;
}
} 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) {
* 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;
}
isc_mem_put(radix->mctx, node, sizeof(*node));
radix->num_active_node--;
- if (parent->has_prefix) {
+ if (parent->prefix.family != 0) {
return;
}