Compare commits

...

1 Commits

Author SHA1 Message Date
Evan Hunt
471671b012 refactor wildcard matching
make wildcard matching code a little easier to understand,
before porting it to qpdb
2023-11-06 17:06:12 +01:00

View File

@@ -312,27 +312,33 @@ setup_delegation(rbtdb_search_t *search, dns_dbnode_t **nodep,
return (DNS_R_DELEGATION);
}
typedef enum { FORWARD, BACK } direction_t;
/*
* Step backwards or forwards through the database until we find a
* node with data in it for the desired version. If 'next' is not NULL,
* and we found a predecessor or successor, save the name we found in it.
*
* If 'current' is NULL, we return true if we found a predecessor or
* successor. If it's not NULL, we check whether the found name is a
* subdomain of it, and return true if so.
*/
static bool
activeempty(rbtdb_search_t *search, dns_rbtnodechain_t *chain,
const dns_name_t *name) {
dns_fixedname_t fnext;
step(rbtdb_search_t *search, dns_rbtnodechain_t *chain, direction_t dir,
dns_name_t *nextname) {
dns_fixedname_t forigin;
dns_name_t *next = NULL;
dns_name_t *origin = NULL;
dns_name_t prefix;
dns_rbtdb_t *rbtdb = NULL;
dns_rbtnode_t *node = NULL;
isc_result_t result;
bool answer = false;
isc_result_t result = ISC_R_SUCCESS;
dns_slabheader_t *header = NULL;
rbtdb = search->rbtdb;
dns_name_init(&prefix, NULL);
next = dns_fixedname_initname(&fnext);
origin = dns_fixedname_initname(&forigin);
result = dns_rbtnodechain_next(chain, NULL, NULL);
while (result == ISC_R_SUCCESS || result == DNS_R_NEWORIGIN) {
isc_rwlocktype_t nlocktype = isc_rwlocktype_none;
node = NULL;
@@ -356,115 +362,76 @@ activeempty(rbtdb_search_t *search, dns_rbtnodechain_t *chain,
if (header != NULL) {
break;
}
result = dns_rbtnodechain_next(chain, NULL, NULL);
if (dir == FORWARD) {
result = dns_rbtnodechain_next(chain, NULL, NULL);
} else {
result = dns_rbtnodechain_prev(chain, NULL, NULL);
}
};
if (result == ISC_R_SUCCESS) {
result = dns_name_concatenate(&prefix, origin, nextname, NULL);
}
if (result == ISC_R_SUCCESS) {
result = dns_name_concatenate(&prefix, origin, next, NULL);
return (true);
}
if (result == ISC_R_SUCCESS && dns_name_issubdomain(next, name)) {
answer = true;
}
return (answer);
return (false);
}
static bool
activeemptynode(rbtdb_search_t *search, const dns_name_t *qname,
dns_name_t *wname) {
activeempty(rbtdb_search_t *search, dns_rbtnodechain_t *chain,
const dns_name_t *current) {
dns_fixedname_t fnext;
dns_name_t *next = dns_fixedname_initname(&fnext);
return (step(search, chain, FORWARD, next) &&
dns_name_issubdomain(next, current));
}
static bool
wildcard_blocked(rbtdb_search_t *search, const dns_name_t *qname,
dns_name_t *wname) {
isc_result_t result;
dns_fixedname_t fnext;
dns_fixedname_t forigin;
dns_fixedname_t fprev;
dns_name_t *next = NULL;
dns_name_t *origin = NULL;
dns_name_t *prev = NULL;
dns_name_t *next = NULL, *prev = NULL;
dns_name_t name;
dns_name_t rname;
dns_name_t tname;
dns_rbtdb_t *rbtdb = NULL;
dns_rbtnode_t *node = NULL;
dns_rbtnodechain_t chain;
bool check_next = true;
bool check_prev = true;
bool answer = false;
isc_result_t result;
dns_slabheader_t *header = NULL;
bool check_next = false;
bool check_prev = false;
unsigned int n;
rbtdb = search->rbtdb;
dns_name_init(&name, NULL);
dns_name_init(&tname, NULL);
dns_name_init(&rname, NULL);
next = dns_fixedname_initname(&fnext);
prev = dns_fixedname_initname(&fprev);
origin = dns_fixedname_initname(&forigin);
/*
* Find if qname is at or below a empty node.
* Use our own copy of the chain.
* The qname seems to have matched a wildcard, but we
* need to find out if there's an empty nonterminal node
* between the wildcard level and the qname.
*
* search->chain should now be pointing at the predecessor
* of the searched-for name. We are using a local copy of the
* chain so as not to change the state of search->chain.
* step() will walk backward until we find a predecessor with
* data.
*/
chain = search->chain;
do {
isc_rwlocktype_t nlocktype = isc_rwlocktype_none;
node = NULL;
result = dns_rbtnodechain_current(&chain, &name, origin, &node);
if (result != ISC_R_SUCCESS) {
break;
}
NODE_RDLOCK(&(rbtdb->node_locks[node->locknum].lock),
&nlocktype);
for (header = node->data; header != NULL; header = header->next)
{
if (header->serial <= search->serial &&
!IGNORE(header) && EXISTS(header))
{
break;
}
}
NODE_UNLOCK(&(rbtdb->node_locks[node->locknum].lock),
&nlocktype);
if (header != NULL) {
break;
}
result = dns_rbtnodechain_prev(&chain, NULL, NULL);
} while (result == ISC_R_SUCCESS || result == DNS_R_NEWORIGIN);
check_prev = step(search, &chain, BACK, prev);
/* Now reset the chain and look for a successor with data. */
chain = search->chain;
result = dns_rbtnodechain_next(&chain, NULL, NULL);
if (result == ISC_R_SUCCESS) {
result = dns_name_concatenate(&name, origin, prev, NULL);
}
if (result != ISC_R_SUCCESS) {
check_prev = false;
check_next = step(search, &chain, FORWARD, next);
}
result = dns_rbtnodechain_next(&chain, NULL, NULL);
while (result == ISC_R_SUCCESS || result == DNS_R_NEWORIGIN) {
isc_rwlocktype_t nlocktype = isc_rwlocktype_none;
node = NULL;
result = dns_rbtnodechain_current(&chain, &name, origin, &node);
if (result != ISC_R_SUCCESS) {
break;
}
NODE_RDLOCK(&(rbtdb->node_locks[node->locknum].lock),
&nlocktype);
for (header = node->data; header != NULL; header = header->next)
{
if (header->serial <= search->serial &&
!IGNORE(header) && EXISTS(header))
{
break;
}
}
NODE_UNLOCK(&(rbtdb->node_locks[node->locknum].lock),
&nlocktype);
if (header != NULL) {
break;
}
result = dns_rbtnodechain_next(&chain, NULL, NULL);
}
if (result == ISC_R_SUCCESS) {
result = dns_name_concatenate(&name, origin, next, NULL);
}
if (result != ISC_R_SUCCESS) {
check_next = false;
if (!check_prev && !check_next) {
/* No predecessor or successor was found at all? */
return (false);
}
dns_name_clone(qname, &rname);
@@ -479,16 +446,17 @@ activeemptynode(rbtdb_search_t *search, const dns_name_t *qname,
if ((check_prev && dns_name_issubdomain(prev, &rname)) ||
(check_next && dns_name_issubdomain(next, &rname)))
{
answer = true;
break;
return (true);
}
/*
* Remove the left hand label.
* Remove the leftmost label from the qname and check again.
*/
n = dns_name_countlabels(&rname);
dns_name_getlabelsequence(&rname, 1, n - 1, &rname);
} while (!dns_name_equal(&rname, &tname));
return (answer);
return (false);
}
static isc_result_t
@@ -607,8 +575,8 @@ find_wildcard(rbtdb_search_t *search, dns_rbtnode_t **nodep,
if (header != NULL ||
activeempty(search, &wchain, wname))
{
if (activeemptynode(search, qname,
wname))
if (wildcard_blocked(search, qname,
wname))
{
return (ISC_R_NOTFOUND);
}