NXDOMAIN NXT support
This commit is contained in:
@@ -887,22 +887,45 @@ query_find(ns_client_t *client) {
|
||||
goto cleanup;
|
||||
}
|
||||
INSIST(is_zone);
|
||||
/*
|
||||
* Set message rcode.
|
||||
*/
|
||||
client->message->rcode = dns_rcode_nxdomain;
|
||||
if (dns_rdataset_isassociated(rdataset)) {
|
||||
/*
|
||||
* If we've got a NXT record, we need to save the
|
||||
* name now because we're going call query_addsoa()
|
||||
* below, and it needs to use the name buffer.
|
||||
*/
|
||||
query_keepname(client, fname, dbuf);
|
||||
/*
|
||||
* We don't want the cleanup code to try to release
|
||||
* fname if we fail below, so we set it to NULL.
|
||||
*/
|
||||
tname = fname;
|
||||
fname = NULL;
|
||||
} else {
|
||||
/*
|
||||
* We're not going to use fname, and need to release
|
||||
* our hold on the name buffer so query_addsoa()
|
||||
* may use it.
|
||||
*/
|
||||
query_releasename(client, &fname);
|
||||
}
|
||||
/*
|
||||
* Add SOA.
|
||||
*/
|
||||
query_releasename(client, &fname);
|
||||
result = query_addsoa(client, db);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
QUERY_ERROR(result);
|
||||
goto cleanup;
|
||||
}
|
||||
/*
|
||||
* XXXRTH Add NXT chain here.
|
||||
* Add NXT record if we found one.
|
||||
*/
|
||||
if (dns_rdataset_isassociated(rdataset))
|
||||
query_addrrset(client, &tname, &rdataset, NULL,
|
||||
DNS_SECTION_AUTHORITY);
|
||||
/*
|
||||
* Set message rcode.
|
||||
*/
|
||||
client->message->rcode = dns_rcode_nxdomain;
|
||||
goto cleanup;
|
||||
case DNS_R_NOTFOUND:
|
||||
QUERY_ERROR(DNS_R_NOTIMP);
|
||||
|
||||
133
lib/dns/rbtdb.c
133
lib/dns/rbtdb.c
@@ -1353,6 +1353,118 @@ find_wildcard(rbtdb_search_t *search, dns_rbtnode_t **nodep) {
|
||||
return (result);
|
||||
}
|
||||
|
||||
static inline isc_result_t
|
||||
find_closest_nxt(rbtdb_search_t *search, dns_dbnode_t **nodep,
|
||||
dns_name_t *foundname, dns_rdataset_t *rdataset)
|
||||
{
|
||||
dns_rbtnode_t *node;
|
||||
rdatasetheader_t *header, *header_next;
|
||||
isc_boolean_t empty_node;
|
||||
isc_result_t result;
|
||||
dns_fixedname_t fname, forigin;
|
||||
dns_name_t *name, *origin;
|
||||
|
||||
do {
|
||||
node = NULL;
|
||||
dns_fixedname_init(&fname);
|
||||
name = dns_fixedname_name(&fname);
|
||||
dns_fixedname_init(&forigin);
|
||||
origin = dns_fixedname_name(&forigin);
|
||||
result = dns_rbtnodechain_current(&search->chain, name,
|
||||
origin, &node);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
return (result);
|
||||
LOCK(&(search->rbtdb->node_locks[node->locknum].lock));
|
||||
empty_node = ISC_TRUE;
|
||||
for (header = node->data;
|
||||
header != NULL;
|
||||
header = header_next) {
|
||||
header_next = header->next;
|
||||
/*
|
||||
* Look for an active, extant rdataset with a
|
||||
* NXT record.
|
||||
*/
|
||||
do {
|
||||
if (header->serial <= search->serial &&
|
||||
!IGNORE(header)) {
|
||||
/*
|
||||
* Is this a "this rdataset doesn't
|
||||
* exist" record?
|
||||
*/
|
||||
if ((header->attributes &
|
||||
RDATASET_ATTR_NONEXISTENT) != 0)
|
||||
header = NULL;
|
||||
break;
|
||||
} else
|
||||
header = header->down;
|
||||
} while (header != NULL);
|
||||
if (header != NULL) {
|
||||
/*
|
||||
* We now know that there is at least one
|
||||
* active rdataset at this node.
|
||||
*/
|
||||
empty_node = ISC_FALSE;
|
||||
if (header->type == dns_rdatatype_nxt)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!empty_node) {
|
||||
if (header != NULL) {
|
||||
/*
|
||||
* We've found the right NXT record.
|
||||
*
|
||||
* XXXRTH Well, not necessarily. If
|
||||
* someone adds an NS rdataset causing a
|
||||
* tree to be obscured, we might be looking
|
||||
* at a NXT record in the obscured part of
|
||||
* the tree. To avoid this, we must either
|
||||
* erase all the NXT records (causing lots
|
||||
* of IXFR work), or we must somehow determine
|
||||
* that we're looking at one. For now, we
|
||||
* do nothing.
|
||||
*/
|
||||
result = dns_name_concatenate(name,
|
||||
origin,
|
||||
foundname, NULL);
|
||||
if (result == ISC_R_SUCCESS) {
|
||||
if (nodep != NULL) {
|
||||
new_reference(search->rbtdb,
|
||||
node);
|
||||
*nodep = node;
|
||||
}
|
||||
bind_rdataset(search->rbtdb, node,
|
||||
header, search->now,
|
||||
rdataset);
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* We found an active node without a NXT
|
||||
* record. This shouldn't happen.
|
||||
*/
|
||||
result = DNS_R_BADDB;
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* This node isn't active. We've got to keep
|
||||
* looking.
|
||||
*/
|
||||
result = dns_rbtnodechain_prev(&search->chain, NULL,
|
||||
NULL);
|
||||
}
|
||||
UNLOCK(&(search->rbtdb->node_locks[node->locknum].lock));
|
||||
} while (empty_node && result == ISC_R_SUCCESS);
|
||||
|
||||
/*
|
||||
* If the result is DNS_R_NOMORE, then we got to the beginning of
|
||||
* the database and didn't find a NXT record. This shouldn't
|
||||
* happen.
|
||||
*/
|
||||
if (result == DNS_R_NOMORE)
|
||||
result = DNS_R_BADDB;
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
||||
static dns_result_t
|
||||
zone_find(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version,
|
||||
dns_rdatatype_t type, unsigned int options, isc_stdtime_t now,
|
||||
@@ -1363,7 +1475,6 @@ zone_find(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version,
|
||||
dns_result_t result;
|
||||
rbtdb_search_t search;
|
||||
isc_boolean_t cname_ok = ISC_TRUE;
|
||||
isc_boolean_t must_succeed = ISC_FALSE;
|
||||
isc_boolean_t close_version = ISC_FALSE;
|
||||
isc_boolean_t maybe_zonecut = ISC_FALSE;
|
||||
isc_boolean_t at_zonecut = ISC_FALSE;
|
||||
@@ -1449,11 +1560,13 @@ zone_find(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version,
|
||||
* If we're here, then the name does not exist, is not
|
||||
* beneath a zonecut, and there's no matching wildcard.
|
||||
*/
|
||||
result = DNS_R_NXDOMAIN;
|
||||
if (search.rbtdb->secure)
|
||||
result = DNS_R_NOTIMPLEMENTED; /* XXXDNSSEC */
|
||||
if (nodep != NULL)
|
||||
*nodep = NULL;
|
||||
if (search.rbtdb->secure) {
|
||||
result = find_closest_nxt(&search, nodep, foundname,
|
||||
rdataset);
|
||||
if (result == ISC_R_SUCCESS)
|
||||
result = DNS_R_NXDOMAIN;
|
||||
} else
|
||||
result = DNS_R_NXDOMAIN;
|
||||
goto tree_exit;
|
||||
} else if (result != DNS_R_SUCCESS)
|
||||
goto tree_exit;
|
||||
@@ -1602,13 +1715,7 @@ zone_find(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version,
|
||||
* If we didn't find what we were looking for...
|
||||
*/
|
||||
if (found == NULL) {
|
||||
if (must_succeed) {
|
||||
/*
|
||||
* We were looking for a type which must be in the
|
||||
* database, but isn't for some reason.
|
||||
*/
|
||||
result = DNS_R_BADDB;
|
||||
} else if (search.zonecut != NULL) {
|
||||
if (search.zonecut != NULL) {
|
||||
/*
|
||||
* We were trying to find glue at a node beneath a
|
||||
* zone cut, but didn't, so we return the delegation.
|
||||
|
||||
Reference in New Issue
Block a user