+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.
* 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>
}
}
goto cleanup;
+ case DNS_R_EMPTYNAME:
+ result = DNS_R_NXRRSET;
+ /* FALLTHROUGH */
case DNS_R_NXRRSET:
INSIST(is_zone);
if (dns_rdataset_isassociated(rdataset)) {
* 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
* 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
* 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
#define DNS_RDATASETATTR_FIXEDORDER 0x0400
#define DNS_RDATASETATTR_RANDOMIZE 0x0800
#define DNS_RDATASETATTR_CHASE 0x1000 /* Used by resolver. */
+#define DNS_RDATASETATTR_NXDOMAIN 0x2000
/*
* _OMITDNSSEC:
* 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
#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.
* 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>
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));
* 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
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 {
#define RDATASET_ATTR_STALE 0x0002
#define RDATASET_ATTR_IGNORE 0x0004
#define RDATASET_ATTR_RETAIN 0x0008
+#define RDATASET_ATTR_NXDOMAIN 0x0010
/*
* XXX
(((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. */
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);
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;
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.
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;
* 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.
/*
* We found a negative cache entry.
*/
- if (found->type == RBTDB_RDATATYPE_NXDOMAIN)
+ if (NXDOMAIN(found))
result = DNS_R_NCACHENXDOMAIN;
else
result = DNS_R_NCACHENXRRSET;
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)
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)
/*
* We found a negative cache entry.
*/
- if (found->type == RBTDB_RDATATYPE_NXDOMAIN)
+ if (NXDOMAIN(found))
result = DNS_R_NCACHENXDOMAIN;
else
result = DNS_R_NCACHENXRRSET;
for (topheader = rbtnode->data;
topheader != NULL;
topheader = topheader->next) {
- if (topheader->type ==
- RBTDB_RDATATYPE_NXDOMAIN)
+ if (NXDOMAIN(topheader))
break;
}
if (topheader != NULL && EXISTS(topheader) &&
} else {
newheader->serial = 1;
newheader->trust = rdataset->trust;
+ if ((rdataset->attributes & DNS_RDATASETATTR_NXDOMAIN) != 0)
+ newheader->attributes |= RDATASET_ATTR_NXDOMAIN;
}
/*
* 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>
#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);
* a negative cache entry, so we
* must set eresult appropriately.
*/
- if (ardataset->covers ==
- dns_rdatatype_any)
+ if (NXDOMAIN(ardataset))
eresult =
DNS_R_NCACHENXDOMAIN;
else
* 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;
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;
* 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>
"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] = {
* 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>
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));
* 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) &&
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
}
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");