Commit 421e4cf6 authored by Mark Andrews's avatar Mark Andrews
Browse files

1416. [bug] Empty node should return NOERROR NODATA, not NXDOMAIN.

                        [RT #4715]
developer: marka
reviewer: explorer
parent e8426953
1416. [bug] Empty node should return NOERROR NODATA, not NXDOMAIN.
[RT #4715]
1415. [func] DS TTL now derived from NS ttl. NXT TTL now derived
from SOA MINIMUM.
......
......@@ -15,7 +15,7 @@
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: query.c,v 1.239 2003/01/14 00:28:49 marka Exp $ */
/* $Id: query.c,v 1.240 2003/01/18 03:18:30 marka Exp $ */
#include <config.h>
......@@ -2687,6 +2687,9 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
}
}
goto cleanup;
case DNS_R_EMPTYNAME:
result = DNS_R_NXRRSET;
/* FALLTHROUGH */
case DNS_R_NXRRSET:
INSIST(is_zone);
if (dns_rdataset_isassociated(rdataset)) {
......
......@@ -15,7 +15,7 @@
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: db.h,v 1.70 2002/08/06 01:50:28 marka Exp $ */
/* $Id: db.h,v 1.71 2003/01/18 03:18:31 marka Exp $ */
#ifndef DNS_DB_H
#define DNS_DB_H 1
......@@ -767,6 +767,9 @@ dns_db_find(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version,
* name, and 'rdataset' contains
* the negative caching proof.
*
* DNS_R_EMPTYNAME The name exists but there is
* no data at the name.
*
* Error results:
*
* ISC_R_NOMEMORY
......
......@@ -15,7 +15,7 @@
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: rdataset.h,v 1.45 2002/02/20 03:34:37 marka Exp $ */
/* $Id: rdataset.h,v 1.46 2003/01/18 03:18:31 marka Exp $ */
#ifndef DNS_RDATASET_H
#define DNS_RDATASET_H 1
......@@ -129,6 +129,7 @@ struct dns_rdataset {
#define DNS_RDATASETATTR_FIXEDORDER 0x0400
#define DNS_RDATASETATTR_RANDOMIZE 0x0800
#define DNS_RDATASETATTR_CHASE 0x1000 /* Used by resolver. */
#define DNS_RDATASETATTR_NXDOMAIN 0x2000
/*
* _OMITDNSSEC:
......
......@@ -15,7 +15,7 @@
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: result.h,v 1.95 2003/01/14 00:28:50 marka Exp $ */
/* $Id: result.h,v 1.96 2003/01/18 03:18:31 marka Exp $ */
#ifndef DNS_RESULT_H
#define DNS_RESULT_H 1
......@@ -133,8 +133,9 @@
#define DNS_R_UNEXPECTEDRCODE (ISC_RESULTCLASS_DNS + 89)
#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_NRESULTS 92 /* Number of results */
#define DNS_R_NRESULTS 93 /* Number of results */
/*
* DNS wire format rcodes.
......
......@@ -15,7 +15,7 @@
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: ncache.c,v 1.30 2002/07/19 03:29:15 marka Exp $ */
/* $Id: ncache.c,v 1.31 2003/01/18 03:18:30 marka Exp $ */
#include <config.h>
......@@ -247,6 +247,8 @@ dns_ncache_add(dns_message_t *message, dns_db_t *cache, dns_dbnode_t *node,
RUNTIME_CHECK(dns_rdatalist_tordataset(&ncrdatalist, &ncrdataset)
== ISC_R_SUCCESS);
ncrdataset.trust = trust;
if (message->rcode == dns_rcode_nxdomain)
ncrdataset.attributes |= DNS_RDATASETATTR_NXDOMAIN;
return (dns_db_addrdataset(cache, node, NULL, now, &ncrdataset,
0, addedrdataset));
......
......@@ -15,7 +15,7 @@
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: rbtdb.c,v 1.183 2003/01/14 00:38:07 marka Exp $ */
/* $Id: rbtdb.c,v 1.184 2003/01/18 03:18:30 marka Exp $ */
/*
* Principal Author: Bob Halley
......@@ -91,7 +91,7 @@ typedef isc_uint32_t rbtdb_rdatatype_t;
RBTDB_RDATATYPE_VALUE(dns_rdatatype_sig, dns_rdatatype_cname)
#define RBTDB_RDATATYPE_SIGDNAME \
RBTDB_RDATATYPE_VALUE(dns_rdatatype_sig, dns_rdatatype_dname)
#define RBTDB_RDATATYPE_NXDOMAIN \
#define RBTDB_RDATATYPE_NCACHEANY \
RBTDB_RDATATYPE_VALUE(0, dns_rdatatype_any)
typedef struct rdatasetheader {
......@@ -128,6 +128,7 @@ typedef struct rdatasetheader {
#define RDATASET_ATTR_STALE 0x0002
#define RDATASET_ATTR_IGNORE 0x0004
#define RDATASET_ATTR_RETAIN 0x0008
#define RDATASET_ATTR_NXDOMAIN 0x0010
/*
* XXX
......@@ -147,6 +148,8 @@ typedef struct rdatasetheader {
(((header)->attributes & RDATASET_ATTR_IGNORE) != 0)
#define RETAIN(header) \
(((header)->attributes & RDATASET_ATTR_RETAIN) != 0)
#define NXDOMAIN(header) \
(((header)->attributes & RDATASET_ATTR_NXDOMAIN) != 0)
#define DEFAULT_NODE_LOCK_COUNT 7 /* Should be prime. */
......@@ -1307,6 +1310,8 @@ bind_rdataset(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node,
rdataset->covers = RBTDB_RDATATYPE_EXT(header->type);
rdataset->ttl = header->ttl - now;
rdataset->trust = header->trust;
if (NXDOMAIN(header))
rdataset->attributes |= DNS_RDATASETATTR_NXDOMAIN;
rdataset->private1 = rbtdb;
rdataset->private2 = node;
raw = (unsigned char *)header + sizeof(*header);
......@@ -1841,6 +1846,12 @@ 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;
search.rbtdb = (dns_rbtdb_t *)db;
......@@ -1914,6 +1925,45 @@ 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);
}
/*
* If we're here, then the name does not exist, is not
* beneath a zonecut, and there's no matching wildcard.
......@@ -1925,9 +1975,10 @@ zone_find(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version,
rdataset, sigrdataset,
search.rbtdb->secure);
if (result == ISC_R_SUCCESS)
result = DNS_R_NXDOMAIN;
result = active ? DNS_R_EMPTYNAME :
DNS_R_NXDOMAIN;
} else
result = DNS_R_NXDOMAIN;
result = active ? DNS_R_EMPTYNAME : DNS_R_NXDOMAIN;
goto tree_exit;
} else if (result != ISC_R_SUCCESS)
goto tree_exit;
......@@ -2668,7 +2719,7 @@ cache_find(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version,
* target type. Remember it.
*/
foundsig = header;
} else if (header->type == RBTDB_RDATATYPE_NXDOMAIN ||
} else if (header->type == RBTDB_RDATATYPE_NCACHEANY ||
header->type == nxtype) {
/*
* We've found a negative cache entry.
......@@ -2756,7 +2807,7 @@ cache_find(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version,
/*
* We found a negative cache entry.
*/
if (found->type == RBTDB_RDATATYPE_NXDOMAIN)
if (NXDOMAIN(found))
result = DNS_R_NCACHENXDOMAIN;
else
result = DNS_R_NCACHENXRRSET;
......@@ -2776,7 +2827,8 @@ cache_find(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version,
result = ISC_R_SUCCESS;
}
if (type != dns_rdatatype_any || result == DNS_R_NCACHENXDOMAIN) {
if (type != dns_rdatatype_any || result == DNS_R_NCACHENXDOMAIN ||
result == DNS_R_NCACHENXRRSET) {
bind_rdataset(search.rbtdb, node, found, search.now,
rdataset);
if (foundsig != NULL)
......@@ -3298,7 +3350,7 @@ cache_findrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
0) {
if (header->type == matchtype)
found = header;
else if (header->type == RBTDB_RDATATYPE_NXDOMAIN ||
else if (header->type == RBTDB_RDATATYPE_NCACHEANY ||
header->type == nxtype)
found = header;
else if (header->type == sigmatchtype)
......@@ -3321,7 +3373,7 @@ cache_findrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
/*
* We found a negative cache entry.
*/
if (found->type == RBTDB_RDATATYPE_NXDOMAIN)
if (NXDOMAIN(found))
result = DNS_R_NCACHENXDOMAIN;
else
result = DNS_R_NCACHENXRRSET;
......@@ -3549,8 +3601,7 @@ add(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode, rbtdb_version_t *rbtversion,
for (topheader = rbtnode->data;
topheader != NULL;
topheader = topheader->next) {
if (topheader->type ==
RBTDB_RDATATYPE_NXDOMAIN)
if (NXDOMAIN(topheader))
break;
}
if (topheader != NULL && EXISTS(topheader) &&
......@@ -3857,6 +3908,8 @@ addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
} else {
newheader->serial = 1;
newheader->trust = rdataset->trust;
if ((rdataset->attributes & DNS_RDATASETATTR_NXDOMAIN) != 0)
newheader->attributes |= RDATASET_ATTR_NXDOMAIN;
}
/*
......
......@@ -15,7 +15,7 @@
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: resolver.c,v 1.259 2003/01/16 03:59:25 marka Exp $ */
/* $Id: resolver.c,v 1.260 2003/01/18 03:18:30 marka Exp $ */
#include <config.h>
......@@ -309,6 +309,8 @@ struct dns_resolver {
#define ISFORWARDER(a) (((a)->flags & \
FCTX_ADDRINFO_FORWARDER) != 0)
#define NXDOMAIN(r) (((r)->attributes & DNS_RDATASETATTR_NXDOMAIN) != 0)
static void destroy(dns_resolver_t *res);
static void empty_bucket(dns_resolver_t *res);
static isc_result_t resquery_send(resquery_t *query);
......@@ -3337,8 +3339,7 @@ cache_name(fetchctx_t *fctx, dns_name_t *name, isc_stdtime_t now) {
* a negative cache entry, so we
* must set eresult appropriately.
*/
if (ardataset->covers ==
dns_rdatatype_any)
if (NXDOMAIN(ardataset))
eresult =
DNS_R_NCACHENXDOMAIN;
else
......@@ -3445,7 +3446,7 @@ ncache_adderesult(dns_message_t *message, dns_db_t *cache, dns_dbnode_t *node,
* The cache data is also a negative cache
* entry.
*/
if (ardataset->covers == dns_rdatatype_any)
if (NXDOMAIN(ardataset))
*eresultp = DNS_R_NCACHENXDOMAIN;
else
*eresultp = DNS_R_NCACHENXRRSET;
......@@ -3464,7 +3465,7 @@ ncache_adderesult(dns_message_t *message, dns_db_t *cache, dns_dbnode_t *node,
result = ISC_R_SUCCESS;
}
} else if (result == ISC_R_SUCCESS) {
if (covers == dns_rdatatype_any)
if (NXDOMAIN(ardataset))
*eresultp = DNS_R_NCACHENXDOMAIN;
else
*eresultp = DNS_R_NCACHENXRRSET;
......
......@@ -15,7 +15,7 @@
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: result.c,v 1.105 2003/01/14 00:28:49 marka Exp $ */
/* $Id: result.c,v 1.106 2003/01/18 03:18:30 marka Exp $ */
#include <config.h>
......@@ -139,7 +139,8 @@ static const char *text[DNS_R_NRESULTS] = {
"unexpected RCODE", /* 89 DNS_R_UNEXPECTEDRCODE */
"unexpected OPCODE", /* 90 DNS_R_UNEXPECTEDOPCODE */
"chase DS servers" /* 91 DNS_R_CHASEDSSERVERS */
"chase DS servers", /* 91 DNS_R_CHASEDSSERVERS */
"empty name" /* 92 DNS_R_EMPTYNAME */
};
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.110 2002/07/22 03:00:49 marka Exp $ */
/* $Id: validator.c,v 1.111 2003/01/18 03:18:30 marka Exp $ */
#include <config.h>
......@@ -440,6 +440,8 @@ nxtprovesnonexistence(dns_validator_t *val, dns_name_t *nxtname,
dns_rdata_t rdata = DNS_RDATA_INIT;
isc_boolean_t isnxdomain;
isc_result_t result;
dns_namereln_t relation;
unsigned int labels, bits;
INSIST(DNS_MESSAGE_VALID(val->event->message));
......@@ -486,9 +488,23 @@ nxtprovesnonexistence(dns_validator_t *val, dns_name_t *nxtname,
* The NXT owner name is less than the nonexistent name.
*/
if (!isnxdomain) {
/*
* Is this a empty node?
*/
result = dns_rdata_tostruct(&rdata, &nxt, NULL);
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) {
validator_log(val, ISC_LOG_DEBUG(3),
"missing NXT record at name");
return (ISC_FALSE);
}
validator_log(val, ISC_LOG_DEBUG(3),
"missing NXT record at name");
return (ISC_FALSE);
"nxt proves empty node, ok");
return (ISC_TRUE);
}
if (dns_name_issubdomain(val->event->name, nxtname) &&
dns_nxt_typepresent(&rdata, dns_rdatatype_ns) &&
......@@ -507,8 +523,9 @@ nxtprovesnonexistence(dns_validator_t *val, dns_name_t *nxtname,
if (result != ISC_R_SUCCESS)
return (ISC_FALSE);
dns_rdata_reset(&rdata);
order = dns_name_compare(val->event->name, &nxt.next);
if (order >= 0) {
relation = dns_name_fullcompare(&nxt.next, val->event->name,
&order, &labels, &bits);
if (order <= 0) {
/*
* The NXT next name is less than the nonexistent
* name. This is only ok if the next name is the zone
......@@ -522,6 +539,11 @@ nxtprovesnonexistence(dns_validator_t *val, dns_name_t *nxtname,
}
validator_log(val, ISC_LOG_DEBUG(3),
"nxt points to zone apex, ok");
} else if (relation == dns_namereln_subdomain) {
validator_log(val, ISC_LOG_DEBUG(3),
"nxt proves empty node, bad");
dns_rdata_freestruct(&nxt);
return (ISC_FALSE);
}
dns_rdata_freestruct(&nxt);
validator_log(val, ISC_LOG_DEBUG(3), "nxt range ok");
......
Supports Markdown
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