mirror of
https://github.com/isc-projects/bind9.git
synced 2026-06-08 21:32:11 -04:00
1416. [bug] Empty node should return NOERROR NODATA, not NXDOMAIN.
[RT #4715] developer: marka reviewer: explorer
This commit is contained in:
parent
e8426953c1
commit
421e4cf66e
10 changed files with 119 additions and 29 deletions
3
CHANGES
3
CHANGES
|
|
@ -1,3 +1,6 @@
|
|||
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");
|
||||
|
|
|
|||
Loading…
Reference in a new issue