mirror of
https://github.com/isc-projects/bind9.git
synced 2026-06-10 08:39:59 -04:00
[9.20] fix: dev: Fix the cache findzonecut() implementation
The search for the deepest known zone cut in the cache could improperly reject a node if it contained any stale data, regardless of whether it was the NS RRset that was stale. Closes #5155 Backport of MR !10047 Merge branch 'backport-5155-fix-findzonecut-9.20' into 'bind-9.20' See merge request isc-projects/bind9!10050
This commit is contained in:
commit
619f163e68
3 changed files with 53 additions and 61 deletions
|
|
@ -333,7 +333,7 @@ $DIG $DIGOPTS -x 2001:4f8::1 @10.53.0.6 >dig.out.test$n || ret=1
|
|||
grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1
|
||||
grep "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.f.4.0.1.0.0.2.ip6.arpa. 1 IN PTR nee.com." dig.out.test$n >/dev/null || ret=1
|
||||
sleep 1
|
||||
grep -v ADDR ans2/query.log >ans2/query.log.trimmed
|
||||
grep -F "ip6.arpa." ans2/query.log >ans2/query.log.trimmed
|
||||
cat <<__EOF | diff ans2/query.log.trimmed - >/dev/null || ret=1
|
||||
NS 1.0.0.2.ip6.arpa.
|
||||
NS 8.f.4.0.1.0.0.2.ip6.arpa.
|
||||
|
|
@ -512,18 +512,22 @@ n=$((n + 1))
|
|||
echo_i "query for .stale is properly minimized when qname-minimization is in strict mode (stale cache) ($n)"
|
||||
ret=0
|
||||
$CLEANQL
|
||||
$RNDCCMD 10.53.0.6 flush
|
||||
$DIG $DIGOPTS @10.53.0.6 txt a.b.stale. >dig.out.test$n || ret=1
|
||||
grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1
|
||||
grep "a\.b\.stale\..*1.*IN.*TXT.*hooray" dig.out.test$n >/dev/null || ret=1
|
||||
sleep 1
|
||||
sort ans2/query.log >ans2/query.log.sorted
|
||||
cat <<__EOF | diff ans2/query.log.sorted - >/dev/null || ret=1
|
||||
ADDR ns.b.stale.
|
||||
ADDR ns2.stale.
|
||||
NS b.stale.
|
||||
NS stale.
|
||||
__EOF
|
||||
test -f ans3/query.log && ret=1
|
||||
sort ans4/query.log >ans4/query.log.sorted
|
||||
cat <<__EOF | diff ans4/query.log.sorted - >/dev/null || ret=1
|
||||
ADDR ns.b.stale.
|
||||
NS b.stale.
|
||||
TXT a.b.stale.
|
||||
__EOF
|
||||
|
|
@ -535,17 +539,21 @@ n=$((n + 1))
|
|||
echo_i "query for .stale is properly minimized when qname-minimization is in relaxed mode (stale cache) ($n)"
|
||||
ret=0
|
||||
$CLEANQL
|
||||
$RNDCCMD 10.53.0.7 flush
|
||||
$DIG $DIGOPTS @10.53.0.7 txt a.b.stale. >dig.out.test$n || ret=1
|
||||
grep "status: NOERROR" dig.out.test$n >/dev/null || ret=1
|
||||
grep "a\.b\.stale\..*1.*IN.*TXT.*hooray" dig.out.test$n >/dev/null || ret=1
|
||||
sleep 1
|
||||
sort ans2/query.log >ans2/query.log.sorted
|
||||
cat <<__EOF | diff ans2/query.log.sorted - >/dev/null || ret=1
|
||||
ADDR ns.b.stale.
|
||||
ADDR ns2.stale.
|
||||
NS b.stale.
|
||||
__EOF
|
||||
test -f ans3/query.log && ret=1
|
||||
sort ans4/query.log >ans4/query.log.sorted
|
||||
cat <<__EOF | diff ans4/query.log.sorted - >/dev/null || ret=1
|
||||
ADDR ns.b.stale.
|
||||
TXT a.b.stale.
|
||||
__EOF
|
||||
for ans in ans2 ans3 ans4; do mv -f $ans/query.log query-$ans-$n.log 2>/dev/null || true; done
|
||||
|
|
|
|||
|
|
@ -2086,45 +2086,35 @@ findzonecut(dns_db_t *db, const dns_name_t *name, unsigned int options,
|
|||
|
||||
for (header = node->data; header != NULL; header = header_next) {
|
||||
header_next = header->next;
|
||||
bool ns = (header->type == dns_rdatatype_ns ||
|
||||
header->type == DNS_SIGTYPE(dns_rdatatype_ns));
|
||||
if (check_stale_header(node, header, &nlocktype, nlock, &search,
|
||||
&header_prev))
|
||||
{
|
||||
/*
|
||||
* The function dns_qp_lookup found us a matching
|
||||
* node for 'name' and stored the result in 'dcname'.
|
||||
* This is the deepest known zonecut in our database.
|
||||
* However, this node may be stale and if serve-stale
|
||||
* is not enabled (in other words 'stale-answer-enable'
|
||||
* is set to no), this node may not be used as a
|
||||
* zonecut we know about. If so, find the deepest
|
||||
* zonecut from this node up and return that instead.
|
||||
*/
|
||||
NODE_UNLOCK(nlock, &nlocktype);
|
||||
result = find_deepest_zonecut(
|
||||
&search, node, nodep, foundname, rdataset,
|
||||
sigrdataset DNS__DB_FLARG_PASS);
|
||||
dns_name_copy(foundname, dcname);
|
||||
goto tree_exit;
|
||||
} else if (EXISTS(header) && !ANCIENT(header)) {
|
||||
/*
|
||||
* If we found a type we were looking for, remember
|
||||
* it.
|
||||
*/
|
||||
if (header->type == dns_rdatatype_ns) {
|
||||
if (ns) {
|
||||
/*
|
||||
* Remember a NS rdataset even if we're
|
||||
* not specifically looking for it, because
|
||||
* we might need it later.
|
||||
* We found a cached NS, but was either
|
||||
* ancient or it was stale and serve-stale
|
||||
* is disabled, so this node can't be used
|
||||
* as a zone cut we know about. Instead we
|
||||
* bail out and call find_deepest_zonecut()
|
||||
* below.
|
||||
*/
|
||||
break;
|
||||
}
|
||||
} else if (EXISTS(header) && !ANCIENT(header)) {
|
||||
if (header->type == dns_rdatatype_ns) {
|
||||
found = header;
|
||||
if (foundsig != NULL) {
|
||||
break;
|
||||
}
|
||||
} else if (header->type ==
|
||||
DNS_SIGTYPE(dns_rdatatype_ns))
|
||||
{
|
||||
/*
|
||||
* If we need the NS rdataset, we'll also
|
||||
* need its signature.
|
||||
*/
|
||||
foundsig = header;
|
||||
if (found != NULL) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
header_prev = header;
|
||||
} else {
|
||||
|
|
@ -2134,12 +2124,14 @@ findzonecut(dns_db_t *db, const dns_name_t *name, unsigned int options,
|
|||
|
||||
if (found == NULL) {
|
||||
/*
|
||||
* No NS records here.
|
||||
* No active NS records found. Call find_deepest_zonecut()
|
||||
* to look for them in nodes above this one.
|
||||
*/
|
||||
NODE_UNLOCK(nlock, &nlocktype);
|
||||
result = find_deepest_zonecut(&search, node, nodep, foundname,
|
||||
rdataset,
|
||||
sigrdataset DNS__DB_FLARG_PASS);
|
||||
dns_name_copy(foundname, dcname);
|
||||
goto tree_exit;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1251,45 +1251,35 @@ cache_findzonecut(dns_db_t *db, const dns_name_t *name, unsigned int options,
|
|||
|
||||
for (header = node->data; header != NULL; header = header_next) {
|
||||
header_next = header->next;
|
||||
bool ns = (header->type == dns_rdatatype_ns ||
|
||||
header->type == DNS_SIGTYPE(dns_rdatatype_ns));
|
||||
if (check_stale_header(node, header, &nlocktype, lock, &search,
|
||||
&header_prev))
|
||||
{
|
||||
/*
|
||||
* The function dns_rbt_findnode found us the a matching
|
||||
* node for 'name' and stored the result in 'dcname'.
|
||||
* This is the deepest known zonecut in our database.
|
||||
* However, this node may be stale and if serve-stale
|
||||
* is not enabled (in other words 'stale-answer-enable'
|
||||
* is set to no), this node may not be used as a
|
||||
* zonecut we know about. If so, find the deepest
|
||||
* zonecut from this node up and return that instead.
|
||||
*/
|
||||
NODE_UNLOCK(lock, &nlocktype);
|
||||
result = find_deepest_zonecut(
|
||||
&search, node, nodep, foundname, rdataset,
|
||||
sigrdataset DNS__DB_FLARG_PASS);
|
||||
dns_name_copy(foundname, dcname);
|
||||
goto tree_exit;
|
||||
} else if (EXISTS(header) && !ANCIENT(header)) {
|
||||
/*
|
||||
* If we found a type we were looking for, remember
|
||||
* it.
|
||||
*/
|
||||
if (header->type == dns_rdatatype_ns) {
|
||||
if (ns) {
|
||||
/*
|
||||
* Remember a NS rdataset even if we're
|
||||
* not specifically looking for it, because
|
||||
* we might need it later.
|
||||
* We found a cached NS, but was either
|
||||
* ancient or it was stale and serve-stale
|
||||
* is disabled, so this node can't be used
|
||||
* as a zone cut we know about. Instead we
|
||||
* bail out and call find_deepest_zonecut()
|
||||
* below.
|
||||
*/
|
||||
break;
|
||||
}
|
||||
} else if (EXISTS(header) && !ANCIENT(header)) {
|
||||
if (header->type == dns_rdatatype_ns) {
|
||||
found = header;
|
||||
if (foundsig != NULL) {
|
||||
break;
|
||||
}
|
||||
} else if (header->type ==
|
||||
DNS_SIGTYPE(dns_rdatatype_ns))
|
||||
{
|
||||
/*
|
||||
* If we need the NS rdataset, we'll also
|
||||
* need its signature.
|
||||
*/
|
||||
foundsig = header;
|
||||
if (found != NULL) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
header_prev = header;
|
||||
} else {
|
||||
|
|
@ -1299,12 +1289,14 @@ cache_findzonecut(dns_db_t *db, const dns_name_t *name, unsigned int options,
|
|||
|
||||
if (found == NULL) {
|
||||
/*
|
||||
* No NS records here.
|
||||
* No active NS records found. Call find_deepest_zonecut()
|
||||
* to look for them in nodes above this one.
|
||||
*/
|
||||
NODE_UNLOCK(lock, &nlocktype);
|
||||
result = find_deepest_zonecut(&search, node, nodep, foundname,
|
||||
rdataset,
|
||||
sigrdataset DNS__DB_FLARG_PASS);
|
||||
dns_name_copy(foundname, dcname);
|
||||
goto tree_exit;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue