} except-from {
"example";
};
+ qname-minimization disabled; // Regression test for GL #4652
};
trust-anchors { };
$DIG $DIGOPTS @10.53.0.1 tsig. >dig.out.test$n.1 || ret=1
grep "status: NOERROR" dig.out.test$n.1 >/dev/null || ret=1
rndc_dumpdb ns1
+ # prime cache with NS response for QNAME minimisation
grep "$pat" ns1/named_dump.db.test$n >/dev/null || ret=1
+ $DIG $DIGOPTS @10.53.0.1 NS nocookie.tsig >dig.out.test$n.2 || ret=1
+ grep "status: NOERROR" dig.out.test$n.2 >/dev/null || ret=1
# check the disabled server response
nextpart ns1/named.run >/dev/null
- $DIG $DIGOPTS @10.53.0.1 nocookie.tsig >dig.out.test$n.2 || ret=1
- grep "status: NOERROR" dig.out.test$n.2 >/dev/null || ret=1
- grep 'A.10\.53\.0\.9' dig.out.test$n.2 >/dev/null || ret=1
- grep 'A.10\.53\.0\.10' dig.out.test$n.2 >/dev/null || ret=1
+ $DIG $DIGOPTS @10.53.0.1 nocookie.tsig >dig.out.test$n.3 || ret=1
+ grep "status: NOERROR" dig.out.test$n.3 >/dev/null || ret=1
+ grep 'A.10\.53\.0\.9' dig.out.test$n.3 >/dev/null || ret=1
+ grep 'A.10\.53\.0\.10' dig.out.test$n.3 >/dev/null || ret=1
nextpart ns1/named.run >named.run.test$n
count=$(grep -c ') [0-9][0-9]* NOERROR 0' named.run.test$n)
test $count -eq 2 || ret=1
+ count=$(grep -c '^; COOKIE: ................................' named.run.test$n)
+ test $count -eq 1 || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=$((status + ret))
fi
ret=0
dig_with_opts normalthenrrsig.secure.example. @10.53.0.4 a >/dev/null || ret=1
ans=$(dig_with_opts +short normalthenrrsig.secure.example. @10.53.0.4 rrsig) || ret=1
-expect=$(dig_with_opts +short normalthenrrsig.secure.example. @10.53.0.3 rrsig | grep '^A') || ret=1
+expect=$(dig_with_opts +short normalthenrrsig.secure.example. @10.53.0.3 rrsig | grep '^\(A\|NSEC\)') || ret=1
test "$ans" = "$expect" || ret=1
# also check that RA is set
dig_with_opts normalthenrrsig.secure.example. @10.53.0.4 rrsig >dig.out.ns4.test$n || ret=1
echo_i "checking EDE code 1 for bad alg mnemonic ($n)"
ret=0
dig_with_opts @10.53.0.4 badalg.secure.example >dig.out.ns4.test$n || ret=1
-grep "; EDE: 1 (Unsupported DNSKEY Algorithm): (ECDSAP256SHA256 badalg.secure.example/A)" dig.out.ns4.test$n >/dev/null || ret=1
+grep "; EDE: 1 (Unsupported DNSKEY Algorithm): (ECDSAP256SHA256 badalg.secure.example/NSEC)" dig.out.ns4.test$n >/dev/null || ret=1
grep "flags:.*ad.*QUERY" dig.out.ns4.test$n >/dev/null && ret=1
n=$((n + 1))
test "$ret" -eq 0 || echo_i "failed"
grep "NOERROR" dig.out.ns3.test$n.1 >/dev/null || ret=1
grep "flags:.* ad" dig.out.ns3.test$n.1 >/dev/null || ret=1
# Sanity check: the authoritative server should have been queried.
-nextpart ns2/named.run | grep "query 'foo.initially-unavailable/A/IN'" >/dev/null || ret=1
+nextpart ns2/named.run | grep "query 'foo.initially-unavailable/NS/IN'" >/dev/null || ret=1
# Reconfigure ns2 so that the zone can be mirrored on ns3.
sed '/^zone "initially-unavailable" {$/,/^};$/ {
s/10.53.0.254/10.53.0.3/
grep "NOERROR" dig.out.ns3.test$n.2 >/dev/null || ret=1
grep "flags:.* ad" dig.out.ns3.test$n.2 >/dev/null || ret=1
# Ensure the authoritative server was not queried.
-nextpart ns2/named.run | grep "query 'foo.initially-unavailable/A/IN'" >/dev/null && ret=1
+nextpart ns2/named.run | grep "query 'foo.initially-unavailable/NS/IN'" >/dev/null && ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=$((status + ret))
grep "NOERROR" dig.out.ns3.test$n >/dev/null || ret=1
grep "flags:.* ad" dig.out.ns3.test$n >/dev/null || ret=1
# Sanity check: the authoritative server should have been queried.
-nextpart ns2/named.run | grep "query 'foo.initially-unavailable/A/IN'" >/dev/null || ret=1
+nextpart ns2/named.run | grep "query 'foo.initially-unavailable/NS/IN'" >/dev/null || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=$((status + ret))
r.answer.append(dns.rrset.from_text(lqname, 1, IN, TXT, "hooray"))
elif rrtype == NS:
# NS a.b.
+ # This is only returned if a query for b.stale/NS has been made
r.answer.append(dns.rrset.from_text(lqname, 1, IN, NS, "ns.a.b.stale."))
r.additional.append(
- dns.rrset.from_text("ns.a.b.stale.", 1, IN, A, "10.53.0.3")
+ dns.rrset.from_text("ns.a.b.stale.", 1, IN, A, "10.53.0.4")
)
elif rrtype == SOA:
# SOA a.b.
r.flags |= dns.flags.AA
if rrtype == A:
r.answer.append(
- dns.rrset.from_text("ns.a.b.stale.", 1, IN, A, "10.53.0.3")
+ dns.rrset.from_text("ns.a.b.stale.", 1, IN, A, "10.53.0.4")
)
else:
# NODATA.
ADDR ns2.good.
ADDR ns3.good.
ADDR ns3.good.
+NS a.bit.longer.ns.name.good.
NS bit.longer.ns.name.good.
NS boing.good.
NS good.
NS longer.ns.name.good.
NS name.good.
NS ns.name.good.
+NS ns3.good.
NS zoop.boing.good.
__EOF
cat <<__EOF | diff ans3/query.log - >/dev/null || ret=1
ADDR ns2.good.
ADDR ns3.good.
ADDR ns3.good.
+NS a.bit.longer.ns.name.good.
NS bit.longer.ns.name.good.
NS boing.good.
NS longer.ns.name.good.
NS name.good.
NS ns.name.good.
+NS ns3.good.
NS zoop.boing.good.
__EOF
cat <<__EOF | diff ans3/query.log - >/dev/null || ret=1
ADDR ns3.bad.
NS boing.bad.
NS name.bad.
+NS ns3.bad.
__EOF
cat <<__EOF | diff ans3/query.log - >/dev/null || ret=1
ADDR icky.icky.icky.ptang.zoop.boing.bad.
NS boing.ugly.
NS name.ugly.
NS name.ugly.
+NS ns3.ugly.
__EOF
echo "ADDR icky.icky.icky.ptang.zoop.boing.ugly." | diff ans3/query.log - >/dev/null || ret=1
echo "ADDR icky.icky.icky.ptang.zoop.boing.ugly." | diff ans4/query.log - >/dev/null || ret=1
ADDR ns2.slow.
ADDR ns3.slow.
ADDR ns3.slow.
+NS a.bit.longer.ns.name.slow.
NS bit.longer.ns.name.slow.
NS boing.slow.
NS longer.ns.name.slow.
NS name.slow.
NS ns.name.slow.
+NS ns3.slow.
NS slow.
NS zoop.boing.slow.
__EOF
NS 0.0.0.0.8.f.4.0.1.0.0.2.ip6.arpa.
NS 0.0.0.0.0.0.8.f.4.0.1.0.0.2.ip6.arpa.
NS 0.0.0.0.0.0.0.0.8.f.4.0.1.0.0.2.ip6.arpa.
+NS 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.
PTR 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.
__EOF
for ans in ans2 ans3 ans4; do mv -f $ans/query.log query-$ans-$n.log 2>/dev/null || true; done
ADDR ns2.good.
ADDR ns3.good.
ADDR ns3.good.
+NS a.bit.longer.ns.name.good.
NS bit.longer.ns.name.good.
NS boing.good.
NS good.
NS longer.ns.name.good.
NS name.good.
NS ns.name.good.
+NS ns3.good.
NS zoop.boing.good.
__EOF
cat <<__EOF | diff ans3/query.log - >/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.a.b.stale.
ADDR ns.b.stale.
ADDR ns2.stale.
NS b.stale.
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.a.b.stale.
ADDR ns.b.stale.
+NS a.b.stale.
NS b.stale.
TXT a.b.stale.
__EOF
sleep 1
sort ans2/query.log >ans2/query.log.sorted
cat <<__EOF | diff ans2/query.log.sorted - >/dev/null || ret=1
+ADDR ns.a.b.stale.
ADDR ns.b.stale.
ADDR ns2.stale.
NS b.stale.
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.a.b.stale.
ADDR ns.b.stale.
+NS a.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
sleep 1
sort ans2/query.log >ans2/query.log.sorted
cat <<__EOF | diff ans2/query.log.sorted - >/dev/null || ret=1
+ADDR ns.a.b.stale.
ADDR ns.b.stale.
ADDR ns2.stale.
NS b.stale.
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.a.b.stale.
ADDR ns.b.stale.
+NS a.b.stale.
NS b.stale.
TXT a.b.stale.
__EOF
sleep 1
sort ans2/query.log >ans2/query.log.sorted
cat <<__EOF | diff ans2/query.log.sorted - >/dev/null || ret=1
+ADDR ns.a.b.stale.
ADDR ns.b.stale.
ADDR ns2.stale.
NS b.stale.
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.a.b.stale.
ADDR ns.b.stale.
+NS a.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
grep "status: SERVFAIL" dig.ns5.out.${n} >/dev/null || ret=1
check_namedrun() {
nextpartpeek ns5/named.run >nextpart.out.${n}
- grep 'resolving tcpalso.no-questions/A for [^:]*: empty question section, accepting it anyway as TC=1' nextpart.out.${n} >/dev/null || return 1
- grep '(tcpalso.no-questions/A): connecting via TCP' nextpart.out.${n} >/dev/null || return 1
- grep 'resolving tcpalso.no-questions/A for [^:]*: empty question section$' nextpart.out.${n} >/dev/null || return 1
- grep '(tcpalso.no-questions/A): nextitem' nextpart.out.${n} >/dev/null || return 1
+ grep 'resolving tcpalso.no-questions/NS for [^:]*: empty question section, accepting it anyway as TC=1' nextpart.out.${n} >/dev/null || return 1
+ grep '(tcpalso.no-questions/NS): connecting via TCP' nextpart.out.${n} >/dev/null || return 1
+ grep 'resolving tcpalso.no-questions/NS for [^:]*: empty question section$' nextpart.out.${n} >/dev/null || return 1
+ grep '(tcpalso.no-questions/NS): nextitem' nextpart.out.${n} >/dev/null || return 1
return 0
}
retry_quiet 12 check_namedrun || ret=1
expected_rcode=dns.rcode.NOERROR,
)
assert res_allowed_any.answer == [
- dns.rrset.from_text("allowed.", 300, "IN", "NS", "ns1.allowed."),
dns.rrset.from_text("allowed.", 300, "IN", "A", "10.53.0.2"),
+ dns.rrset.from_text("allowed.", 300, "IN", "NS", "ns1.allowed."),
]
# The comparison above doesn't compare the TTL values, and we want to
# make sure that the "passthru" rpz doesn't cap the TTL with max-policy-ttl.
# stale for somewhere between 3500-3599 seconds.
echo_i "check rndc dump stale data.example ($n)"
rndc_dumpdb ns1 || ret=1
-awk '/; stale since [0-9]*/ { x=$0; getline; print x, $0}' ns1/named_dump.db.test$n \
+# add in inherited owner names
+awk '$1 ~ /^[0-9][0-9]*$/ { $0 = last " " $0 } $1 != ";" { last = $1 } { print }' ns1/named_dump.db.test$n >named_dump.db.test$n
+awk '/; stale since [0-9]*/ { x=$0; getline; print x, $0}' named_dump.db.test$n \
| grep "; stale since [0-9]* data\.example.*3[56]...*TXT.*A text record with a 2 second ttl" >/dev/null 2>&1 || ret=1
# Also make sure the not expired data does not have a stale comment.
-awk '/; authanswer/ { x=$0; getline; print x, $0}' ns1/named_dump.db.test$n \
+awk '/; authanswer/ { x=$0; getline; print x, $0}' named_dump.db.test$n \
| grep "; authanswer longttl\.example.*[56]...*TXT.*A text record with a 600 second ttl" >/dev/null 2>&1 || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=$((status + ret))
# Check that expired records are dumped.
echo_i "check rndc dump expired data.example ($n)"
ret=0
-awk '/; expired/ { x=$0; getline; print x, $0}' ns5/named_dump.db.test$n \
- | grep "; expired (awaiting cleanup) data\.example\..*A text record with a 2 second ttl" >/dev/null 2>&1 || ret=1
-awk '/; expired/ { x=$0; getline; print x, $0}' ns5/named_dump.db.test$n \
- | grep "; expired (awaiting cleanup) nodata\.example\." >/dev/null 2>&1 || ret=1
-awk '/; expired/ { x=$0; getline; print x, $0}' ns5/named_dump.db.test$n \
- | grep "; expired (awaiting cleanup) nxdomain\.example\." >/dev/null 2>&1 || ret=1
-awk '/; expired/ { x=$0; getline; print x, $0}' ns5/named_dump.db.test$n \
- | grep "; expired (awaiting cleanup) othertype\.example\." >/dev/null 2>&1 || ret=1
+# add in inherited owner names
+awk '$1 ~ /^[0-9][0-9]*$/ { $0 = last " " $0 } $1 != ";" { last = $1 } { print }' ns5/named_dump.db.test$n >named_dump.db.test$n
+# extract expired records
+awk '/; expired/ { x=$0; getline; print x, $0}' named_dump.db.test$n >expired.test$n
+grep "; expired (awaiting cleanup) data\.example\..*A text record with a 2 second ttl" expired.test$n >/dev/null 2>&1 || ret=1
+grep "; expired (awaiting cleanup) nodata\.example\." expired.test$n >/dev/null 2>&1 || ret=1
+grep "; expired (awaiting cleanup) nxdomain\.example\." expired.test$n >/dev/null 2>&1 || ret=1
# Also make sure the not expired data does not have an expired comment.
-awk '/; authanswer/ { x=$0; getline; print x, $0}' ns5/named_dump.db.test$n \
+awk '/; authanswer/ { x=$0; getline; print x, $0}' named_dump.db.test$n \
| grep "; authanswer longttl\.example.*A text record with a 600 second ttl" >/dev/null 2>&1 || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=$((status + ret))
pytestmark = pytest.mark.extra_artifacts(
[
"dig.out.*",
+ "expired.test*",
+ "named_dump.db.test*",
"rndc.out.*",
"ans*/ans.run",
"ns*/named.stats*",
check_status NOERROR dig.out.ns${ns}.test$n || ret=1
if [ ${synth} = yes ]; then
check_synth_cname b.wild-cname.example. dig.out.ns${ns}.test$n || ret=1
- nextpart ns1/named.run | grep b.wild-cname.example/A >/dev/null && ret=1
+ nextpart ns1/named.run | grep b.wild-cname.example/NS >/dev/null && ret=1
else
check_nosynth_cname b.wild-cname.example. dig.out.ns${ns}.test$n || ret=1
- nextpart ns1/named.run | grep b.wild-cname.example/A >/dev/null || ret=1
+ nextpart ns1/named.run | grep b.wild-cname.example/NS >/dev/null || ret=1
fi
grep "ns1.example.*.IN.A" dig.out.ns${ns}.test$n >/dev/null || ret=1
digcomp wildcname.out dig.out.ns${ns}.test$n || ret=1
check_nosynth_aaaa b.wild-2-nsec-afterdata.example. dig.out.a.ns${ns}.test$n || ret=1
#
nextpart ns1/named.run >/dev/null
+ sleep 1
dig_with_opts b.wild-2-nsec-afterdata.example. @10.53.0.${ns} TLSA >dig.out.ns${ns}.test$n || ret=1
check_ad_flag $ad dig.out.ns${ns}.test$n || ret=1
check_status NOERROR dig.out.ns${ns}.test$n || ret=1
check_ad_flag no dig.out.ns${ns}.test$n || ret=1
check_status NOERROR dig.out.ns${ns}.test$n || ret=1
check_nosynth_cname b.wild-cname.insecure.example dig.out.ns${ns}.test$n || ret=1
- nextpart ns1/named.run | grep b.wild-cname.insecure.example/A >/dev/null || ret=1
+ nextpart ns1/named.run | grep b.wild-cname.insecure.example/NS >/dev/null || ret=1
grep "ns1.insecure.example.*.IN.A" dig.out.ns${ns}.test$n >/dev/null || ret=1
digcomp insecure.wildcname.out dig.out.ns${ns}.test$n || ret=1
n=$((n + 1))
dns_rdatatype_t qmintype;
dns_fetch_t *qminfetch;
dns_rdataset_t qminrrset;
+ dns_rdataset_t qminsigrrset;
dns_fixedname_t qmindcfname;
dns_name_t *qmindcname;
dns_fixedname_t fwdfname;
static void
resume_qmin(void *arg);
+static void
+clone_results(fetchctx_t *fctx);
+
static isc_result_t
get_attached_fctx(dns_resolver_t *res, isc_loop_t *loop, const dns_name_t *name,
dns_rdatatype_t type, const dns_name_t *domain,
&fctx->nameservers, NULL, NULL, 0,
options | DNS_FETCHOPT_QMINFETCH, 0, fctx->qc,
fctx->gqc, fctx->loop, resume_qmin, fctx, &fctx->edectx,
- &fctx->qminrrset, NULL, &fctx->qminfetch);
+ &fctx->qminrrset, &fctx->qminsigrrset,
+ &fctx->qminfetch);
if (result != ISC_R_SUCCESS) {
fetchctx_unref(fctx);
goto done;
unsigned int findoptions = 0;
dns_name_t *fname = NULL, *dcname = NULL;
dns_fixedname_t ffixed, dcfixed;
+ dns_rdataset_t rdataset;
+ dns_rdataset_t sigrdataset;
+ dns_db_t *db = NULL;
+ dns_dbnode_t *node = NULL;
+ bool fixup_result = false;
REQUIRE(VALID_FCTX(fctx));
fname = dns_fixedname_initname(&ffixed);
dcname = dns_fixedname_initname(&dcfixed);
+ dns_rdataset_init(&rdataset);
+ dns_rdataset_init(&sigrdataset);
+
if (resp->node != NULL) {
+ dns_db_attachnode(resp->db, resp->node, &node);
dns_db_detachnode(resp->db, &resp->node);
}
if (resp->db != NULL) {
+ dns_db_attach(resp->db, &db);
dns_db_detach(&resp->db);
}
if (dns_rdataset_isassociated(resp->rdataset)) {
+ dns_rdataset_clone(resp->rdataset, &rdataset);
dns_rdataset_disassociate(resp->rdataset);
}
+ if (dns_rdataset_isassociated(resp->sigrdataset)) {
+ dns_rdataset_clone(resp->sigrdataset, &sigrdataset);
+ dns_rdataset_disassociate(resp->sigrdataset);
+ }
+ dns_name_copy(resp->foundname, fname);
result = resp->result;
goto cleanup;
}
+ if (result == DNS_R_NXDOMAIN &&
+ fctx->qmin_labels == dns_name_countlabels(fctx->name))
+ {
+ LOCK(&fctx->lock);
+ resp = ISC_LIST_HEAD(fctx->resps);
+ if (resp != NULL) {
+ if (dns_rdataset_isassociated(&rdataset)) {
+ dns_rdataset_clone(&rdataset,
+ resp->rdataset);
+ }
+ if (dns_rdataset_isassociated(&sigrdataset) &&
+ resp->sigrdataset != NULL)
+ {
+ dns_rdataset_clone(&sigrdataset,
+ resp->sigrdataset);
+ }
+ if (db != NULL) {
+ dns_db_attach(db, &resp->db);
+ }
+ if (node != NULL) {
+ dns_db_attachnode(db, node,
+ &resp->node);
+ }
+ dns_name_copy(fname, resp->foundname);
+ clone_results(fctx);
+ UNLOCK(&fctx->lock);
+ goto cleanup;
+ }
+ UNLOCK(&fctx->lock);
+ }
+
/* ...or disable minimization in relaxed mode */
fctx->qmin_labels = DNS_NAME_MAXLABELS;
{
fctx->force_qmin_warning = true;
}
+
+ /*
+ * We have got a CNAME or DNAME respone to the NS query
+ * so we are done in almost all cases.
+ */
+ if ((result == DNS_R_CNAME || result == DNS_R_DNAME) &&
+ fctx->qmin_labels == dns_name_countlabels(fctx->name) &&
+ fctx->type != dns_rdatatype_key &&
+ fctx->type != dns_rdatatype_nsec &&
+ fctx->type != dns_rdatatype_any &&
+ fctx->type != dns_rdatatype_sig &&
+ fctx->type != dns_rdatatype_rrsig)
+ {
+ LOCK(&fctx->lock);
+ resp = ISC_LIST_HEAD(fctx->resps);
+ if (resp != NULL) {
+ if (dns_rdataset_isassociated(&rdataset)) {
+ dns_rdataset_clone(&rdataset,
+ resp->rdataset);
+ }
+ if (dns_rdataset_isassociated(&sigrdataset) &&
+ resp->sigrdataset != NULL)
+ {
+ dns_rdataset_clone(&sigrdataset,
+ resp->sigrdataset);
+ }
+ if (db != NULL) {
+ dns_db_attach(db, &resp->db);
+ }
+ if (node != NULL) {
+ dns_db_attachnode(db, node,
+ &resp->node);
+ }
+ dns_name_copy(fname, resp->foundname);
+ if (result == DNS_R_CNAME &&
+ dns_rdataset_isassociated(&rdataset) &&
+ fctx->type == dns_rdatatype_cname)
+ {
+ fixup_result = true;
+ }
+ clone_results(fctx);
+ UNLOCK(&fctx->lock);
+ goto cleanup;
+ }
+ UNLOCK(&fctx->lock);
+ }
+
/*
* Any other result will *not* cause a failure in strict
* mode, or cause minimization to be disabled in relaxed
fctx_try(fctx, true);
cleanup:
+ if (node != NULL) {
+ dns_db_detachnode(db, &node);
+ }
+ if (db != NULL) {
+ dns_db_detach(&db);
+ }
+ if (dns_rdataset_isassociated(&rdataset)) {
+ dns_rdataset_disassociate(&rdataset);
+ }
+ if (dns_rdataset_isassociated(&sigrdataset)) {
+ dns_rdataset_disassociate(&sigrdataset);
+ }
if (result != ISC_R_SUCCESS) {
/* An error occurred, tear down whole fctx */
- fctx_done_unref(fctx, result);
+ fctx_done_unref(fctx, fixup_result ? ISC_R_SUCCESS : result);
}
fetchctx_detach(&fctx);
}
dns_rdataset_init(&fctx->nameservers);
dns_rdataset_init(&fctx->qminrrset);
+ dns_rdataset_init(&fctx->qminsigrrset);
dns_rdataset_init(&fctx->nsrrset);
fctx->start = isc_time_now();
} else if (fctx->qmin_labels < 35) {
fctx->qmin_labels = 35;
} else {
- fctx->qmin_labels = nlabels;
+ fctx->qmin_labels = nlabels + 1;
}
} else if (fctx->qmin_labels > DNS_QMIN_MAXLABELS) {
fctx->qmin_labels = DNS_NAME_MAXLABELS;
}
- if (fctx->qmin_labels < nlabels) {
+ if (fctx->qmin_labels <= nlabels) {
dns_rdataset_t rdataset;
dns_fixedname_t fixed;
dns_name_t *fname = dns_fixedname_initname(&fixed);
break;
}
break;
- } while (fctx->qmin_labels < nlabels);
+ } while (fctx->qmin_labels <= nlabels);
}
- if (fctx->qmin_labels < nlabels) {
+ /*
+ * DS lookups come from the parent zone so we don't need to do a
+ * NS lookup at the QNAME. If the QTYPE is NS we are not leaking
+ * the type if we just do the final NS lookup.
+ */
+ if (fctx->qmin_labels < nlabels ||
+ (fctx->type != dns_rdatatype_ns && fctx->type != dns_rdatatype_ds &&
+ fctx->qmin_labels == nlabels))
+ {
dns_name_copy(&name, fctx->qminname);
fctx->qmintype = dns_rdatatype_ns;
fctx->minimized = true;