Commit 8b5de970 authored by Mark Andrews's avatar Mark Andrews
Browse files

1448. [bug] Handle empty wildcards labels.

developer: marka
reviewer: explorer
parent 80b782f3
1448. [bug] Handle empty wildcards labels.
1447. [bug] We were casting (unsigned int) to and from (void *).
rdataset->private4 is now rdataset->privateuint4
to reflect a type change.
......
......@@ -15,7 +15,7 @@
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: query.c,v 1.242 2003/01/31 12:07:56 marka Exp $ */
/* $Id: query.c,v 1.243 2003/02/27 00:19:03 marka Exp $ */
#include <config.h>
......@@ -1899,7 +1899,7 @@ query_addwildcardproof(ns_client_t *client, dns_db_t *db,
*/
if (result == ISC_R_SUCCESS && ispositive)
break;
if (result == DNS_R_NXDOMAIN) {
if (result == DNS_R_NXDOMAIN || result == DNS_R_EMPTYNAME) {
if (!ispositive &&
dns_name_issubdomain(name, fname))
done = ISC_TRUE;
......@@ -2269,6 +2269,7 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
dns_rdata_cname_t cname;
dns_rdata_dname_t dname;
unsigned int options;
isc_boolean_t empty_wild;
CTRACE("query_find");
......@@ -2292,6 +2293,7 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
version = NULL;
zone = NULL;
need_wildcardproof = ISC_FALSE;
empty_wild = ISC_FALSE;
options = 0;
if (event != NULL) {
......@@ -2745,6 +2747,9 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
&rdataset, &sigrdataset);
}
goto cleanup;
case DNS_R_EMPTYWILD:
empty_wild = ISC_TRUE;
/* FALLTHROUGH */
case DNS_R_NXDOMAIN:
INSIST(is_zone);
if (dns_rdataset_isassociated(rdataset)) {
......@@ -2792,7 +2797,10 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
/*
* Set message rcode.
*/
client->message->rcode = dns_rcode_nxdomain;
if (empty_wild)
client->message->rcode = dns_rcode_noerror;
else
client->message->rcode = dns_rcode_nxdomain;
goto cleanup;
case DNS_R_NCACHENXDOMAIN:
case DNS_R_NCACHENXRRSET:
......
......@@ -15,7 +15,7 @@
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: result.h,v 1.96 2003/01/18 03:18:31 marka Exp $ */
/* $Id: result.h,v 1.97 2003/02/27 00:19:04 marka Exp $ */
#ifndef DNS_RESULT_H
#define DNS_RESULT_H 1
......@@ -134,8 +134,9 @@
#define DNS_R_UNEXPECTEDOPCODE (ISC_RESULTCLASS_DNS + 90)
#define DNS_R_CHASEDSSERVERS (ISC_RESULTCLASS_DNS + 91)
#define DNS_R_EMPTYNAME (ISC_RESULTCLASS_DNS + 92)
#define DNS_R_EMPTYWILD (ISC_RESULTCLASS_DNS + 93)
#define DNS_R_NRESULTS 93 /* Number of results */
#define DNS_R_NRESULTS 94 /* Number of results */
/*
* DNS wire format rcodes.
......
......@@ -15,7 +15,7 @@
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: rbtdb.c,v 1.185 2003/02/26 23:52:29 marka Exp $ */
/* $Id: rbtdb.c,v 1.186 2003/02/27 00:19:03 marka Exp $ */
/*
* Principal Author: Bob Halley
......@@ -1086,6 +1086,34 @@ add_wildcard_magic(dns_rbtdb_t *rbtdb, dns_name_t *name) {
return (ISC_R_SUCCESS);
}
static isc_result_t
add_empty_wildcards(dns_rbtdb_t *rbtdb, dns_name_t *name) {
isc_result_t result;
dns_name_t foundname;
dns_offsets_t offsets;
unsigned int n, l, i;
dns_name_init(&foundname, offsets);
n = dns_name_countlabels(name);
l = dns_name_countlabels(&rbtdb->common.origin);
i = l + 1;
while (i < n) {
dns_rbtnode_t *node = NULL; /* dummy */
dns_name_getlabelsequence(name, n - i, i, &foundname);
if (dns_name_iswildcard(&foundname)) {
result = add_wildcard_magic(rbtdb, &foundname);
if (result != ISC_R_SUCCESS)
return (result);
result = dns_rbt_addnode(rbtdb->tree, &foundname,
&node);
if (result != ISC_R_SUCCESS && result != ISC_R_EXISTS)
return (result);
}
i++;
}
return (ISC_R_SUCCESS);
}
static isc_result_t
findnode(dns_db_t *db, dns_name_t *name, isc_boolean_t create,
dns_dbnode_t **nodep)
......@@ -1126,6 +1154,8 @@ findnode(dns_db_t *db, dns_name_t *name, isc_boolean_t create,
node->locknum = dns_name_hash(&nodename, ISC_TRUE) %
rbtdb->node_lock_count;
#endif
add_empty_wildcards(rbtdb, name);
if (dns_name_iswildcard(name)) {
result = add_wildcard_magic(rbtdb, name);
if (result != ISC_R_SUCCESS) {
......@@ -1436,6 +1466,56 @@ valid_glue(rbtdb_search_t *search, dns_name_t *name, rbtdb_rdatatype_t type,
return (valid);
}
static inline isc_boolean_t
activeempty(rbtdb_search_t *search, dns_rbtnodechain_t *chain,
dns_name_t *name)
{
dns_fixedname_t fnext;
dns_fixedname_t forigin;
dns_name_t *next;
dns_name_t *origin;
dns_name_t prefix;
dns_rbtdb_t *rbtdb;
dns_rbtnode_t *node;
isc_result_t result;
isc_boolean_t answer = ISC_FALSE;
rdatasetheader_t *header;
rbtdb = search->rbtdb;
dns_name_init(&prefix, NULL);
dns_fixedname_init(&fnext);
next = dns_fixedname_name(&fnext);
dns_fixedname_init(&forigin);
origin = dns_fixedname_name(&forigin);
result = dns_rbtnodechain_next(chain, NULL, NULL);
while (result == ISC_R_SUCCESS || result == DNS_R_NEWORIGIN) {
node = NULL;
result = dns_rbtnodechain_current(chain, &prefix,
origin, &node);
if (result != ISC_R_SUCCESS)
break;
LOCK(&(rbtdb->node_locks[node->locknum].lock));
for (header = node->data;
header != NULL;
header = header->next) {
if (header->serial <= search->serial &&
!IGNORE(header) && EXISTS(header))
break;
}
UNLOCK(&(rbtdb->node_locks[node->locknum].lock));
if (header != NULL)
break;
result = dns_rbtnodechain_next(chain, NULL, NULL);
}
if (result == ISC_R_SUCCESS)
result = dns_name_concatenate(&prefix, origin, next, NULL);
if (result == ISC_R_SUCCESS && dns_name_issubdomain(next, name))
answer = ISC_TRUE;
return (answer);
}
static inline isc_boolean_t
activeemtpynode(rbtdb_search_t *search, dns_name_t *qname, dns_name_t *wname) {
dns_fixedname_t fnext;
......@@ -1452,6 +1532,7 @@ activeemtpynode(rbtdb_search_t *search, dns_name_t *qname, dns_name_t *wname) {
dns_rbtnodechain_t chain;
isc_boolean_t check_next = ISC_TRUE;
isc_boolean_t check_prev = ISC_TRUE;
isc_boolean_t answer = ISC_FALSE;
isc_result_t result;
rdatasetheader_t *header;
unsigned int n;
......@@ -1533,15 +1614,17 @@ activeemtpynode(rbtdb_search_t *search, dns_name_t *qname, dns_name_t *wname) {
do {
if ((check_prev && dns_name_issubdomain(prev, &rname)) ||
(check_next && dns_name_issubdomain(next, &rname)))
return (ISC_TRUE);
(check_next && dns_name_issubdomain(next, &rname))) {
answer = ISC_TRUE;
break;
}
/*
* Remove the left hand label.
*/
n = dns_name_countlabels(&rname);
dns_name_getlabelsequence(&rname, 1, n - 1, &rname);
} while (!dns_name_equal(&rname, &tname));
return (ISC_FALSE);
return (answer);
}
static inline isc_result_t
......@@ -1557,6 +1640,7 @@ find_wildcard(rbtdb_search_t *search, dns_rbtnode_t **nodep,
dns_fixedname_t fwname;
dns_rbtdb_t *rbtdb;
isc_boolean_t done, wild, active;
dns_rbtnodechain_t wchain;
/*
* Caller must be holding the tree lock and MUST NOT be holding
......@@ -1630,8 +1714,9 @@ find_wildcard(rbtdb_search_t *search, dns_rbtnode_t **nodep,
break;
wnode = NULL;
dns_rbtnodechain_init(&wchain, NULL);
result = dns_rbt_findnode(rbtdb->tree, wname,
NULL, &wnode, NULL,
NULL, &wnode, &wchain,
DNS_RBTFIND_EMPTYDATA,
NULL, NULL);
if (result == ISC_R_SUCCESS) {
......@@ -1649,7 +1734,8 @@ find_wildcard(rbtdb_search_t *search, dns_rbtnode_t **nodep,
break;
}
UNLOCK(&(rbtdb->node_locks[wnode->locknum].lock));
if (header != NULL) {
if (header != NULL ||
activeempty(search, &wchain, wname)) {
if (activeemtpynode(search, qname, wname))
return (ISC_R_NOTFOUND);
/*
......@@ -1846,9 +1932,6 @@ zone_find(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version,
rdatasetheader_t *header, *header_next, *found, *nxtheader;
rdatasetheader_t *foundsig, *cnamesig, *nxtsig;
rbtdb_rdatatype_t sigtype;
dns_fixedname_t fnext;
dns_fixedname_t forigin;
dns_name_t nname, *next, *origin;
isc_boolean_t active;
dns_rbtnodechain_t chain;
......@@ -1925,45 +2008,9 @@ zone_find(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version,
goto tree_exit;
}
/*
* Find if this is a active empty node (next active node is
* subdomain if 'name'). This is a simpler test than is
* required for activeemptynode() where name is not as
* constained.
*/
active = ISC_FALSE;
dns_fixedname_init(&fnext);
next = dns_fixedname_name(&fnext);
dns_fixedname_init(&forigin);
origin = dns_fixedname_name(&forigin);
dns_name_init(&nname, NULL);
chain = search.chain;
result = dns_rbtnodechain_next(&chain, NULL, NULL);
while (result == ISC_R_SUCCESS || result == DNS_R_NEWORIGIN) {
node = NULL;
result = dns_rbtnodechain_current(&chain, &nname,
origin, &node);
if (result != ISC_R_SUCCESS)
break;
LOCK(&(search.rbtdb->node_locks[node->locknum].lock));
for (header = node->data;
header != NULL;
header = header->next) {
if (header->serial <= search.serial &&
!IGNORE(header) && EXISTS(header))
break;
}
UNLOCK(&(search.rbtdb->node_locks[node->locknum].lock));
if (header != NULL) {
result = dns_name_concatenate(&nname, origin,
next, NULL);
if (result == ISC_R_SUCCESS &&
dns_name_issubdomain(next, name))
active = ISC_TRUE;
break;
}
result = dns_rbtnodechain_next(&chain, NULL, NULL);
}
active = activeempty(&search, &chain, name);
/*
* If we're here, then the name does not exist, is not
* beneath a zonecut, and there's no matching wildcard.
......@@ -2162,14 +2209,11 @@ zone_find(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version,
* active rdatasets in the desired version. That means that
* this node doesn't exist in the desired version, and that
* we really have a partial match.
*
* If the node is the result of a wildcard match, then
* it must be active in the desired version, and hence
* empty_node should never be true. We INSIST upon it.
*/
INSIST(!wild);
UNLOCK(&(search.rbtdb->node_locks[node->locknum].lock));
goto partial_match;
if (!wild) {
UNLOCK(&(search.rbtdb->node_locks[node->locknum].lock));
goto partial_match;
}
}
/*
......@@ -2198,8 +2242,18 @@ zone_find(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version,
* The zone is secure but there's no NXT,
* or the NXT has no signature!
*/
result = DNS_R_BADDB;
goto node_exit;
if (!wild) {
result = DNS_R_BADDB;
goto node_exit;
}
UNLOCK(&(search.rbtdb->node_locks[node->locknum].lock));
result = find_closest_nxt(&search, nodep, foundname,
rdataset, sigrdataset,
search.rbtdb->secure);
if (result == ISC_R_SUCCESS)
result = DNS_R_EMPTYWILD;
goto tree_exit;
}
if ((search.options & DNS_DBFIND_FORCENXT) != 0 &&
nxtheader == NULL)
......@@ -4138,6 +4192,8 @@ loading_addrdataset(void *arg, dns_name_t *name, dns_rdataset_t *rdataset) {
!IS_CACHE(rbtdb) && !dns_name_equal(name, &rbtdb->common.origin))
return (DNS_R_NOTZONETOP);
add_empty_wildcards(rbtdb, name);
if (dns_name_iswildcard(name)) {
/*
* NS record owners cannot legally be wild cards.
......
......@@ -15,7 +15,7 @@
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: result.c,v 1.106 2003/01/18 03:18:30 marka Exp $ */
/* $Id: result.c,v 1.107 2003/02/27 00:19:03 marka Exp $ */
#include <config.h>
......@@ -140,7 +140,8 @@ static const char *text[DNS_R_NRESULTS] = {
"unexpected OPCODE", /* 90 DNS_R_UNEXPECTEDOPCODE */
"chase DS servers", /* 91 DNS_R_CHASEDSSERVERS */
"empty name" /* 92 DNS_R_EMPTYNAME */
"empty name", /* 92 DNS_R_EMPTYNAME */
"empty wild" /* 93 DNS_R_EMPTYWILD */
};
static const char *rcode_text[DNS_R_NRCODERESULTS] = {
......
......@@ -15,7 +15,7 @@
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: validator.c,v 1.111 2003/01/18 03:18:30 marka Exp $ */
/* $Id: validator.c,v 1.112 2003/02/27 00:19:04 marka Exp $ */
#include <config.h>
......@@ -441,7 +441,7 @@ nxtprovesnonexistence(dns_validator_t *val, dns_name_t *nxtname,
isc_boolean_t isnxdomain;
isc_result_t result;
dns_namereln_t relation;
unsigned int labels, bits;
unsigned int olabels, nlabels, labels, bits;
INSIST(DNS_MESSAGE_VALID(val->event->message));
......@@ -459,7 +459,8 @@ nxtprovesnonexistence(dns_validator_t *val, dns_name_t *nxtname,
dns_rdataset_current(nxtset, &rdata);
validator_log(val, ISC_LOG_DEBUG(3), "looking for relevant nxt");
order = dns_name_compare(val->event->name, nxtname);
relation = dns_name_fullcompare(val->event->name, nxtname,
&order, &olabels, &bits);
if (order == 0) {
/*
* The names are the same. Look for the type present bit.
......@@ -495,16 +496,39 @@ nxtprovesnonexistence(dns_validator_t *val, dns_name_t *nxtname,
RUNTIME_CHECK(result == ISC_R_SUCCESS);
relation = dns_name_fullcompare(&nxt.next,
val->event->name,
&order, &labels, &bits);
dns_rdata_freestruct(&nxt);
if (order <= 0 || relation != dns_namereln_subdomain) {
&order, &nlabels,
&bits);
if (order > 0 && relation == dns_namereln_subdomain) {
dns_rdata_freestruct(&nxt);
validator_log(val, ISC_LOG_DEBUG(3),
"missing NXT record at name");
return (ISC_FALSE);
"nxt proves empty node, ok");
return (ISC_TRUE);
}
/*
* Look for empty wildcard matches.
*/
labels = dns_name_countlabels(&nxt.next);
if (nlabels >= olabels && nlabels + 1 < labels) {
dns_name_t wild;
dns_name_init(&wild, NULL);
dns_name_getlabelsequence(&nxt.next,
labels - 1 - nlabels,
nlabels + 1,
&wild);
if (dns_name_iswildcard(&wild)) {
dns_rdata_freestruct(&nxt);
validator_log(val, ISC_LOG_DEBUG(3),
"nxt proves empty wildcard, ok");
return (ISC_TRUE);
}
}
/*
* We are not a empty name.
*/
dns_rdata_freestruct(&nxt);
validator_log(val, ISC_LOG_DEBUG(3),
"nxt proves empty node, ok");
return (ISC_TRUE);
"missing NXT record at name");
return (ISC_FALSE);
}
if (dns_name_issubdomain(val->event->name, nxtname) &&
dns_nxt_typepresent(&rdata, dns_rdatatype_ns) &&
......@@ -524,7 +548,7 @@ nxtprovesnonexistence(dns_validator_t *val, dns_name_t *nxtname,
return (ISC_FALSE);
dns_rdata_reset(&rdata);
relation = dns_name_fullcompare(&nxt.next, val->event->name,
&order, &labels, &bits);
&order, &nlabels, &bits);
if (order <= 0) {
/*
* The NXT next name is less than the nonexistent
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment