diff --git a/bin/tests/system/qmin/tests.sh b/bin/tests/system/qmin/tests.sh index d104161f40..6cf8d2b9d0 100755 --- a/bin/tests/system/qmin/tests.sh +++ b/bin/tests/system/qmin/tests.sh @@ -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 diff --git a/lib/dns/qpcache.c b/lib/dns/qpcache.c index cccf522694..ab8f22add2 100644 --- a/lib/dns/qpcache.c +++ b/lib/dns/qpcache.c @@ -2087,45 +2087,35 @@ qpcache_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 { @@ -2135,12 +2125,14 @@ qpcache_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; }