]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
QNAME miminimization should create a separate fetch context for each fetch -
authorWitold Kręcicki <wpk@isc.org>
Wed, 13 Jun 2018 07:29:40 +0000 (09:29 +0200)
committerWitold Kręcicki <wpk@isc.org>
Tue, 23 Oct 2018 12:15:04 +0000 (12:15 +0000)
this makes the cache more efficient and eliminates duplicates queries.

26 files changed:
bin/tests/optional/db_test.c
bin/tests/system/dyndb/driver/db.c
bin/tests/system/qmin/ans2/ans.py
bin/tests/system/qmin/ans3/ans.py
bin/tests/system/qmin/ans4/ans.py
bin/tests/system/qmin/ns1/root.db
bin/tests/system/qmin/tests.sh
bin/tests/system/rpz/ns2/named.conf.in
bin/tests/system/rpz/ns3/named.conf.in
bin/tests/system/rpz/ns4/named.conf.in
bin/tests/system/rpz/ns5/named.conf.in
bin/tests/system/rpz/ns6/named.conf.in
bin/tests/system/rpz/ns7/named.conf.in
lib/dns/adb.c
lib/dns/db.c
lib/dns/ecdb.c
lib/dns/gen.c
lib/dns/include/dns/db.h
lib/dns/include/dns/view.h
lib/dns/rbtdb.c
lib/dns/resolver.c
lib/dns/sdb.c
lib/dns/sdlz.c
lib/dns/validator.c
lib/dns/view.c
lib/ns/query.c

index 92ec7472bec8a19224bb5eb951534cd7a8a6a922..29d341a9c2871c2f66742537c77ec72f0dcde697 100644 (file)
@@ -771,7 +771,7 @@ main(int argc, char *argv[]) {
                        if (noexact_zonecut)
                                zcoptions |= DNS_DBFIND_NOEXACT;
                        result = dns_db_findzonecut(db, &name, zcoptions,
-                                                   0, &node, fname,
+                                                   0, &node, fname, NULL,
                                                    &rdataset, &sigrdataset);
                } else {
                        result = dns_db_find(db, &name, version, type,
index fd0f998b74a5f9f93bb20c485e85cbb286cf9daf..a793a69f04e6c88924f1ce1fd94a88e3de824a98 100644 (file)
@@ -220,14 +220,15 @@ find(dns_db_t *db, const dns_name_t *name, dns_dbversion_t *version,
 static isc_result_t
 findzonecut(dns_db_t *db, const dns_name_t *name, unsigned int options,
            isc_stdtime_t now, dns_dbnode_t **nodep, dns_name_t *foundname,
-           dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset)
+           dns_name_t *dcname, dns_rdataset_t *rdataset,
+           dns_rdataset_t *sigrdataset)
 {
        sampledb_t *sampledb = (sampledb_t *) db;
 
        REQUIRE(VALID_SAMPLEDB(sampledb));
 
        return (dns_db_findzonecut(sampledb->rbtdb, name, options,
-                                  now, nodep, foundname, rdataset,
+                                  now, nodep, foundname, dcname, rdataset,
                                   sigrdataset));
 }
 
index bb6a696737cc78d565d6bc98c8cb0ae0706147ed..17a2ba4874e169b035855f917814e4877281e2a2 100755 (executable)
@@ -19,7 +19,7 @@ from datetime import datetime, timedelta
 import time
 import functools
 
-import dns, dns.message, dns.query
+import dns, dns.message, dns.query, dns.flags
 from dns.rdatatype import *
 from dns.rdataclass import *
 from dns.rcode import *
@@ -44,6 +44,8 @@ def logquery(type, qname):
 #
 # For bad. it works the same as for good., but returns NXDOMAIN to non-empty terminals
 #
+# For ugly. it works the same as for good., but returns garbage to non-empty terminals
+#
 # For 1.0.0.2.ip6.arpa it serves
 # 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. IN PTR nee.com.
 # 1.0.0.2.ip6.arpa. IN NS ns2.good
@@ -61,6 +63,7 @@ def create_response(msg):
     if typename == "A" or typename == "AAAA":
         typename = "ADDR"
     bad = False
+    ugly = False
     slow = False
 
     # log this query
@@ -76,9 +79,11 @@ def create_response(msg):
         if lqname == "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." and rrtype == PTR:
             # Direct query - give direct answer
             r.answer.append(dns.rrset.from_text("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."))
+            r.flags |= dns.flags.AA
         elif lqname == "1.0.0.2.ip6.arpa." and rrtype == NS:
             # NS query at the apex
             r.answer.append(dns.rrset.from_text("1.0.0.2.ip6.arpa.", 1, IN, NS, "ns2.good."))
+            r.flags |= dns.flags.AA
         elif "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.".endswith(lqname):
             # NODATA answer
             r.authority.append(dns.rrset.from_text("1.0.0.2.ip6.arpa.", 1, IN, SOA, "ns2.good. hostmaster.arpa. 2018050100 1 1 1 1"))
@@ -91,6 +96,7 @@ def create_response(msg):
         if lqname == "ip6.arpa." and rrtype == NS:
             # NS query at the apex
             r.answer.append(dns.rrset.from_text("ip6.arpa.", 1, IN, NS, "ns2.good."))
+            r.flags |= dns.flags.AA
         elif "1.0.0.2.ip6.arpa.".endswith(lqname):
             # NODATA answer
             r.authority.append(dns.rrset.from_text("ip6.arpa.", 1, IN, SOA, "ns2.good. hostmaster.arpa. 2018050100 1 1 1 1"))
@@ -103,6 +109,10 @@ def create_response(msg):
         bad = True
         suffix = "bad."
         lqname = lqname[:-4]
+    elif lqname.endswith("ugly."):
+        ugly = True
+        suffix = "ugly."
+        lqname = lqname[:-5]
     elif lqname.endswith("good."):
         suffix = "good."
         lqname = lqname[:-5]
@@ -114,25 +124,33 @@ def create_response(msg):
         r.set_rcode(REFUSED)
         return r
 
-    # Good/bad differs only in how we treat non-empty terminals
+    # Good/bad/ugly differs only in how we treat non-empty terminals
     if lqname.endswith("zoop.boing."):
         r.authority.append(dns.rrset.from_text("zoop.boing." + suffix, 1, IN, NS, "ns3." + suffix))
     elif lqname == "many.labels.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z." and rrtype == A:
         r.answer.append(dns.rrset.from_text(lqname + suffix, 1, IN, A, "192.0.2.2"))
+        r.flags |= dns.flags.AA
     elif lqname == "" and rrtype == NS:
         r.answer.append(dns.rrset.from_text(suffix, 1, IN, NS, "ns2." + suffix))
+        r.flags |= dns.flags.AA
     elif lqname == "ns2." and rrtype == A:
         r.answer.append(dns.rrset.from_text("ns2."+suffix, 1, IN, A, "10.53.0.2"))
+        r.flags |= dns.flags.AA
     elif lqname == "ns2." and rrtype == AAAA:
         r.answer.append(dns.rrset.from_text("ns2."+suffix, 1, IN, AAAA, "fd92:7065:b8e:ffff::2"))
+        r.flags |= dns.flags.AA
     elif lqname == "ns3." and rrtype == A:
         r.answer.append(dns.rrset.from_text("ns3."+suffix, 1, IN, A, "10.53.0.3"))
+        r.flags |= dns.flags.AA
     elif lqname == "ns3." and rrtype == AAAA:
         r.answer.append(dns.rrset.from_text("ns3."+suffix, 1, IN, AAAA, "fd92:7065:b8e:ffff::3"))
+        r.flags |= dns.flags.AA
     elif lqname == "a.bit.longer.ns.name." and rrtype == A:
         r.answer.append(dns.rrset.from_text("a.bit.longer.ns.name."+suffix, 1, IN, A, "10.53.0.4"))
+        r.flags |= dns.flags.AA
     elif lqname == "a.bit.longer.ns.name." and rrtype == AAAA:
         r.answer.append(dns.rrset.from_text("a.bit.longer.ns.name."+suffix, 1, IN, AAAA, "fd92:7065:b8e:ffff::4"))
+        r.flags |= dns.flags.AA
     else:
         r.authority.append(dns.rrset.from_text(suffix, 1, IN, SOA, "ns2." + suffix + " hostmaster.arpa. 2018050100 1 1 1 1"))
         if bad or not \
@@ -140,6 +158,8 @@ def create_response(msg):
              "many.labels.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z.".endswith(lqname) or \
              "a.bit.longer.ns.name.".endswith(lqname)):
             r.set_rcode(NXDOMAIN)
+        if ugly:
+            r.set_rcode(FORMERR)
     if slow:
         time.sleep(0.2)
     return r
index e3943328109e0a56fdce142ff56c5be443f362fe..51d9ae2e7e6926c5811ad2e7b9e193e05066f813 100755 (executable)
@@ -19,7 +19,7 @@ from datetime import datetime, timedelta
 import time
 import functools
 
-import dns, dns.message, dns.query
+import dns, dns.message, dns.query, dns.flags
 from dns.rdatatype import *
 from dns.rdataclass import *
 from dns.rcode import *
@@ -41,6 +41,8 @@ def logquery(type, qname):
 # For slow. it works the same as for good., but each response is delayed by 400 miliseconds
 #
 # For bad. it works the same as for good., but returns NXDOMAIN to non-empty terminals
+#
+# For ugly. it works the same as for good., but returns garbage to non-empty terminals
 ############################################################################
 def create_response(msg):
     m = dns.message.from_wire(msg)
@@ -54,6 +56,7 @@ def create_response(msg):
     if typename == "A" or typename == "AAAA":
         typename = "ADDR"
     bad = False
+    ugly = False
     slow = False
 
     # log this query
@@ -68,6 +71,10 @@ def create_response(msg):
         bad = True
         suffix = "bad."
         lqname = lqname[:-4]
+    elif lqname.endswith("ugly."):
+        ugly = True
+        suffix = "ugly."
+        lqname = lqname[:-5]
     elif lqname.endswith("good."):
         suffix = "good."
         lqname = lqname[:-5]
@@ -82,12 +89,15 @@ def create_response(msg):
     # Good/bad differs only in how we treat non-empty terminals
     if lqname == "zoop.boing." and rrtype == NS:
         r.answer.append(dns.rrset.from_text(lqname + suffix, 1, IN, NS, "ns3."+suffix))
+        r.flags |= dns.flags.AA
     elif lqname.endswith("icky.ptang.zoop.boing."):
         r.authority.append(dns.rrset.from_text("icky.ptang.zoop.boing." + suffix, 1, IN, NS, "a.bit.longer.ns.name." + suffix))
     elif "icky.ptang.zoop.boing.".endswith(lqname):
         r.authority.append(dns.rrset.from_text("zoop.boing." + suffix, 1, IN, SOA, "ns3." + suffix + " hostmaster.arpa. 2018050100 1 1 1 1"))
         if bad:
             r.set_rcode(NXDOMAIN)
+        if ugly:
+            r.set_rcode(FORMERR)
     elif "zoop.boing.".endswith(lqname):
         r.authority.append(dns.rrset.from_text("zoop.boing." + suffix, 1, IN, SOA, "ns3." + suffix + " hostmaster.arpa. 2018050100 1 1 1 1"))
         r.set_rcode(NXDOMAIN)
index c48fc55a34bdff03b4fc925cb38ab55f53dfca06..1bbf017a9ef2158b6f8c7909b08153529ddd7606 100755 (executable)
@@ -19,7 +19,7 @@ from datetime import datetime, timedelta
 import time
 import functools
 
-import dns, dns.message, dns.query
+import dns, dns.message, dns.query, dns.flags
 from dns.rdatatype import *
 from dns.rdataclass import *
 from dns.rcode import *
@@ -42,6 +42,8 @@ def logquery(type, qname):
 # For slow. it works the same as for good., but each response is delayed by 400 miliseconds
 #
 # For bad. it works the same as for good., but returns NXDOMAIN to non-empty terminals
+#
+# For ugly. it works the same as for good., but returns garbage to non-empty terminals
 ############################################################################
 def create_response(msg):
     m = dns.message.from_wire(msg)
@@ -56,6 +58,7 @@ def create_response(msg):
         typename = "ADDR"
     bad = False
     slow = False
+    ugly = False
 
     # log this query
     with open("query.log", "a") as f:
@@ -69,6 +72,10 @@ def create_response(msg):
         bad = True
         suffix = "bad."
         lqname = lqname[:-4]
+    elif lqname.endswith("ugly."):
+        ugly = True
+        suffix = "ugly."
+        lqname = lqname[:-5]
     elif lqname.endswith("good."):
         suffix = "good."
         lqname = lqname[:-5]
@@ -83,14 +90,19 @@ def create_response(msg):
     # Good/bad differs only in how we treat non-empty terminals
     if lqname == "icky.icky.icky.ptang.zoop.boing." and rrtype == A:
         r.answer.append(dns.rrset.from_text(lqname + suffix, 1, IN, A, "192.0.2.1"))
+        r.flags |= dns.flags.AA
     elif lqname == "more.icky.icky.icky.ptang.zoop.boing." and rrtype == A:
         r.answer.append(dns.rrset.from_text(lqname + suffix, 1, IN, A, "192.0.2.2"))
+        r.flags |= dns.flags.AA
     elif lqname == "icky.ptang.zoop.boing." and rrtype == NS:
         r.answer.append(dns.rrset.from_text(lqname + suffix, 1, IN, NS, "a.bit.longer.ns.name."+suffix))
+        r.flags |= dns.flags.AA
     elif lqname.endswith("icky.ptang.zoop.boing."):
         r.authority.append(dns.rrset.from_text("icky.ptang.zoop.boing." + suffix, 1, IN, SOA, "ns2." + suffix + " hostmaster.arpa. 2018050100 1 1 1 1"))
         if bad or not "more.icky.icky.icky.ptang.zoop.boing.".endswith(lqname):
             r.set_rcode(NXDOMAIN)
+        if ugly:
+            r.set_rcode(FORMERR)
     else:
         r.set_rcode(REFUSED)
 
index 83f157f8f0436cc4fc4c38ee1182324e3faac790..294111df4dfdcbc1628343b5f3aa1f8bd3a3f70b 100644 (file)
@@ -28,5 +28,5 @@ ns2.bad.              A       10.53.0.2
 slow                   NS      ns2.slow.
 ns2.slow.              A       10.53.0.2
 
-horrible.              NS      ns2.horrible.
-ns2.horrible.          A       10.53.0.2
+ugly.                  NS      ns2.ugly.
+ns2.ugly.              A       10.53.0.2
index a485ec6f415bb0bbe1aecd83470b830967ef858a..9c669d4358e2dfefd0b852c0f3ffa650795e6151 100755 (executable)
@@ -85,6 +85,29 @@ for ans in ans2 ans3 ans4; do mv -f $ans/query.log query-$ans-$n.log 2>/dev/null
 if [ $ret != 0 ]; then echo_i "failed"; fi
 status=`expr $status + $ret`
 
+n=`expr $n + 1`
+echo_i "query for .ugly is not minimized when qname-minimization is off ($n)"
+ret=0
+$CLEANQL
+$RNDCCMD 10.53.0.5 flush
+$DIG $DIGOPTS icky.icky.icky.ptang.zoop.boing.ugly. @10.53.0.5 > dig.out.test$n
+sleep 5
+grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
+grep "icky.icky.icky.ptang.zoop.boing.ugly. 1  IN A    192.0.2.1" dig.out.test$n > /dev/null || ret=1
+sleep 1
+cat << __EOF | diff ans2/query.log - > /dev/null || ret=1
+ADDR icky.icky.icky.ptang.zoop.boing.ugly.
+ADDR ns3.ugly.
+ADDR ns3.ugly.
+ADDR a.bit.longer.ns.name.ugly.
+ADDR a.bit.longer.ns.name.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
+for ans in ans2 ans3 ans4; do mv -f $ans/query.log query-$ans-$n.log 2>/dev/null || true; done
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+
 n=`expr $n + 1`
 echo_i "query for .good is properly minimized when qname-minimization is on ($n)"
 ret=0
@@ -94,31 +117,22 @@ $DIG $DIGOPTS icky.icky.icky.ptang.zoop.boing.good. @10.53.0.6 > dig.out.test$n
 grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
 grep "icky.icky.icky.ptang.zoop.boing.good. 1  IN A    192.0.2.1" dig.out.test$n > /dev/null || ret=1
 sleep 1
-# Duplicated NS queries are there because we're not creating
-# a separate fetch when doing qname minimization - so two
-# queries running for the same name but different RRTYPE
-# (A and AAAA in this case) will create separate queries
-# for NSes on the way. Those will be cached though, so it
-# should not be a problem
 cat << __EOF | diff ans2/query.log - > /dev/null || ret=1
+NS good.
 NS boing.good.
 NS zoop.boing.good.
 ADDR ns3.good.
 ADDR ns3.good.
-NS name.good.
-NS name.good.
-NS ns.name.good.
-NS ns.name.good.
-NS longer.ns.name.good.
-NS longer.ns.name.good.
 ADDR a.bit.longer.ns.name.good.
 ADDR a.bit.longer.ns.name.good.
 __EOF
 cat << __EOF | diff ans3/query.log - > /dev/null || ret=1
+NS zoop.boing.good.
 NS ptang.zoop.boing.good.
 NS icky.ptang.zoop.boing.good.
 __EOF
 cat << __EOF | diff ans4/query.log - > /dev/null || ret=1
+NS icky.ptang.zoop.boing.good.
 NS icky.icky.ptang.zoop.boing.good.
 ADDR icky.icky.icky.ptang.zoop.boing.good.
 __EOF
@@ -134,7 +148,10 @@ $RNDCCMD 10.53.0.6 flush
 $DIG $DIGOPTS icky.icky.icky.ptang.zoop.boing.bad. @10.53.0.6 > dig.out.test$n
 grep "status: NXDOMAIN" dig.out.test$n > /dev/null || ret=1
 sleep 1
-echo "NS boing.bad." | diff ans2/query.log - > /dev/null || ret=1
+cat << __EOF | diff ans2/query.log - > /dev/null || ret=1
+NS bad.
+NS boing.bad.
+__EOF
 for ans in ans2 ans3 ans4; do mv -f $ans/query.log query-$ans-$n.log 2>/dev/null || true; done
 if [ $ret != 0 ]; then echo_i "failed"; fi
 status=`expr $status + $ret`
@@ -149,12 +166,11 @@ grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
 grep "icky.icky.icky.ptang.zoop.boing.bad. 1 IN A      192.0.2.1" dig.out.test$n > /dev/null || ret=1
 sleep 1
 cat << __EOF | diff ans2/query.log - > /dev/null || ret=1
+NS bad.
 NS boing.bad.
 ADDR icky.icky.icky.ptang.zoop.boing.bad.
 ADDR ns3.bad.
 ADDR ns3.bad.
-NS name.bad.
-NS name.bad.
 ADDR a.bit.longer.ns.name.bad.
 ADDR a.bit.longer.ns.name.bad.
 __EOF
@@ -164,6 +180,52 @@ for ans in ans2 ans3 ans4; do mv -f $ans/query.log query-$ans-$n.log 2>/dev/null
 if [ $ret != 0 ]; then echo_i "failed"; fi
 status=`expr $status + $ret`
 
+n=`expr $n + 1`
+echo_i "query for .ugly fails when qname-minimization is in strict mode ($n)"
+ret=0
+$CLEANQL
+$RNDCCMD 10.53.0.6 flush
+$DIG $DIGOPTS icky.icky.icky.ptang.zoop.boing.ugly. @10.53.0.6 > dig.out.test$n
+grep "status: SERVFAIL" dig.out.test$n > /dev/null || ret=1
+sleep 1
+cat << __EOF | diff ans2/query.log - > /dev/null || ret=1
+NS ugly.
+NS boing.ugly.
+NS boing.ugly.
+NS boing.ugly.
+__EOF
+for ans in ans2 ans3 ans4; do mv -f $ans/query.log query-$ans-$n.log 2>/dev/null || true; done
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+$RNDCCMD 10.53.0.6 flush
+
+n=`expr $n + 1`
+echo_i "query for .ugly succeds when qname-minimization is in relaxed mode ($n)"
+ret=0
+$CLEANQL
+$RNDCCMD 10.53.0.7 flush
+$DIG $DIGOPTS icky.icky.icky.ptang.zoop.boing.ugly. @10.53.0.7 > dig.out.test$n
+grep "status: NOERROR" dig.out.test$n > /dev/null || (ret=1; echo "A")
+grep "icky.icky.icky.ptang.zoop.boing.ugly. 1  IN A    192.0.2.1" dig.out.test$n > /dev/null || (ret=1; echo "X")
+sleep 1
+cat << __EOF | diff ans2/query.log - > /dev/null || (ret=1; echo "Y")
+NS ugly.
+NS boing.ugly.
+NS boing.ugly.
+NS boing.ugly.
+ADDR icky.icky.icky.ptang.zoop.boing.ugly.
+ADDR ns3.ugly.
+ADDR ns3.ugly.
+ADDR a.bit.longer.ns.name.ugly.
+ADDR a.bit.longer.ns.name.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
+for ans in ans2 ans3 ans4; do mv -f $ans/query.log query-$ans-$n.log 2>/dev/null || true; done
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=`expr $status + $ret`
+$RNDCCMD 10.53.0.7 flush
+
 n=`expr $n + 1`
 echo_i "query for .slow is properly minimized when qname-minimization is on ($n)"
 ret=0
@@ -174,24 +236,22 @@ sleep 5
 grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
 grep "icky.icky.icky.ptang.zoop.boing.slow. 1  IN A    192.0.2.1" dig.out.test$n > /dev/null || ret=1
 cat << __EOF | diff ans2/query.log - > /dev/null || ret=1
+NS slow.
 NS boing.slow.
 NS zoop.boing.slow.
 ADDR ns3.slow.
 ADDR ns3.slow.
-NS name.slow.
-NS name.slow.
-NS ns.name.slow.
-NS ns.name.slow.
-NS longer.ns.name.slow.
-NS longer.ns.name.slow.
+NS icky.ptang.zoop.boing.slow.
 ADDR a.bit.longer.ns.name.slow.
 ADDR a.bit.longer.ns.name.slow.
 __EOF
 cat << __EOF | diff ans3/query.log - > /dev/null || ret=1
+NS zoop.boing.slow.
 NS ptang.zoop.boing.slow.
 NS icky.ptang.zoop.boing.slow.
 __EOF
 cat << __EOF | diff ans4/query.log - > /dev/null || ret=1
+NS icky.ptang.zoop.boing.slow.
 NS icky.icky.ptang.zoop.boing.slow.
 ADDR icky.icky.icky.ptang.zoop.boing.slow.
 __EOF
@@ -220,25 +280,6 @@ for ans in ans2 ans3 ans4; do mv -f $ans/query.log query-$ans-$n.log 2>/dev/null
 if [ $ret != 0 ]; then echo_i "failed"; fi
 status=`expr $status + $ret`
 
-n=`expr $n + 1`
-echo_i "query for multiple label name skips after 3rd no-delegation response ($n)"
-ret=0
-$CLEANQL
-$RNDCCMD 10.53.0.6 flush
-$DIG $DIGOPTS many.labels.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z.good. @10.53.0.6 > dig.out.test$n
-grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
-grep "many.labels.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z.good. 1  IN A 192.0.2.2" dig.out.test$n > /dev/null || ret=1
-sleep 1
-# We skipped after third no-delegation.
-cat << __EOF | diff ans2/query.log - > /dev/null || ret=1
-NS z.good.
-NS y.z.good.
-NS x.y.z.good.
-ADDR many.labels.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z.good.
-__EOF
-if [ $ret != 0 ]; then echo_i "failed"; fi
-status=`expr $status + $ret`
-
 n=`expr $n + 1`
 echo_i "query for multiple label name skips after 7th label ($n)"
 ret=0
@@ -249,25 +290,22 @@ grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
 grep "more.icky.icky.icky.ptang.zoop.boing.good. 1 IN  A 192.0.2.2" dig.out.test$n > /dev/null || ret=1
 sleep 1
 cat << __EOF | diff ans2/query.log - > /dev/null || ret=1
+NS good.
 NS boing.good.
 NS zoop.boing.good.
 ADDR ns3.good.
 ADDR ns3.good.
-NS name.good.
-NS name.good.
-NS ns.name.good.
-NS ns.name.good.
-NS longer.ns.name.good.
-NS longer.ns.name.good.
 ADDR a.bit.longer.ns.name.good.
 ADDR a.bit.longer.ns.name.good.
 __EOF
 cat << __EOF | diff ans3/query.log - > /dev/null || ret=1
+NS zoop.boing.good.
 NS ptang.zoop.boing.good.
 NS icky.ptang.zoop.boing.good.
 __EOF
-# There's no NS icky.icky.ptang.zoop.boing.good. query - we skipped it.
+# There's no NS icky.icky.icky.ptang.zoop.boing.good. query - we skipped it.
 cat << __EOF | diff ans4/query.log - > /dev/null || ret=1
+NS icky.ptang.zoop.boing.good.
 NS icky.icky.ptang.zoop.boing.good.
 ADDR more.icky.icky.icky.ptang.zoop.boing.good.
 __EOF
index 12a24630710157209afe54160c2d1ff813259f52..15226401e9bc7d25ed9d262c027ef3e3ab54ff27 100644 (file)
@@ -21,7 +21,6 @@ options {
        notify no;
        minimal-responses no;
        recursion yes;
-       qname-minimization disabled;
        dnssec-validation yes;
 };
 
index 63b0aed6bbef99c85047ddb515c6cecf9360abe7..851a055bc9d2e6125cbb56b9bbcbc14c07569c30 100644 (file)
@@ -27,7 +27,6 @@ options {
        notify yes;
        minimal-responses no;
        recursion yes;
-       qname-minimization disabled;
        dnssec-validation yes;
 
        response-policy {
index c875b10784e049b06c1053543a375712eeff355e..04d6d188fd0367ab0b574b471542bbbf689597c5 100644 (file)
@@ -21,7 +21,6 @@ options {
        notify no;
        minimal-responses no;
        recursion yes;
-       qname-minimization disabled;
        dnssec-validation yes;
 };
 
index 76c9761cdc512d296ac6b4d9e48fc1169901ba87..00d072529392de3ad21476e4ca55e122a938b117 100644 (file)
@@ -29,7 +29,6 @@ options {
        notify yes;
        minimal-responses no;
        recursion yes;
-       qname-minimization disabled;
        dnssec-validation yes;
 
        # turn rpz on or off
index db0c43abc0cafe1e07c7d8ae8e349efa13fdd884..1cf738399b59ee33e975c09205fa828d413926fa 100644 (file)
@@ -23,7 +23,6 @@ options {
        forwarders { 10.53.0.3; };
        minimal-responses no;
        recursion yes;
-       qname-minimization disabled;
        dnssec-validation yes;
 
        response-policy {
index 192fe054f59da0d5291b44ef1f9f5db96e6435b2..842f709923ddc72850b03941948fd90b8f148948 100644 (file)
@@ -21,7 +21,6 @@ options {
        listen-on-v6 { none; };
        minimal-responses no;
        recursion yes;
-       qname-minimization disabled;
        dnssec-validation yes;
 
        response-policy {
index ae8c887340f3100d1f25ba4a5dabfedfee50db14..1572732bcd914247d79f2423bf53afac099212f2 100644 (file)
@@ -4024,7 +4024,7 @@ fetch_name(dns_adbname_t *adbname, bool start_at_zone,
                   adbname);
                name = dns_fixedname_initname(&fixed);
                result = dns_view_findzonecut(adb->view, &adbname->name, name,
-                                             0, 0, true, false,
+                                             NULL, 0, 0, true, false,
                                              &rdataset, NULL);
                if (result != ISC_R_SUCCESS && result != DNS_R_HINT)
                        goto cleanup;
@@ -4032,14 +4032,6 @@ fetch_name(dns_adbname_t *adbname, bool start_at_zone,
                options |= DNS_FETCHOPT_UNSHARED;
        }
 
-       if (adb->view->qminimization) {
-               options |= DNS_FETCHOPT_QMINIMIZE;
-               options |= DNS_FETCHOPT_QMIN_SKIP_IP6A;
-               if (adb->view->qmin_strict) {
-                       options |= DNS_FETCHOPT_QMIN_STRICT;
-               }
-       }
-
        fetch = new_adbfetch(adb);
        if (fetch == NULL) {
                result = ISC_R_NOMEMORY;
@@ -4047,6 +4039,14 @@ fetch_name(dns_adbname_t *adbname, bool start_at_zone,
        }
        fetch->depth = depth;
 
+       /*
+        * We're not minimizing this query, as nothing user-related should
+        * be leaked here.
+        * However, if we'd ever want to change it we'd have to modify
+        * createfetch to find deepest cached name when we're providing
+        * domain and nameservers.
+        */
+
        result = dns_resolver_createfetch(adb->view->resolver, &adbname->name,
                                          type, name, nameservers, NULL,
                                          NULL, 0, options, depth, qc,
index cb3b2e6eec0ff2b0f3bb9f1ccc86c13aa88a2c21..6f55aa3f0fe793b98e632623a87b7281f465b915 100644 (file)
@@ -559,10 +559,13 @@ isc_result_t
 dns_db_findzonecut(dns_db_t *db, const dns_name_t *name,
                   unsigned int options, isc_stdtime_t now,
                   dns_dbnode_t **nodep, dns_name_t *foundname,
-                  dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset)
+                  dns_name_t *dcname, dns_rdataset_t *rdataset,
+                  dns_rdataset_t *sigrdataset)
 {
        /*
         * Find the deepest known zonecut which encloses 'name' in 'db'.
+        * foundname is the zonecut, dcname is the deepest name we have
+        * in database that is part of queried name.
         */
 
        REQUIRE(DNS_DB_VALID(db));
@@ -574,7 +577,8 @@ dns_db_findzonecut(dns_db_t *db, const dns_name_t *name,
                 ! dns_rdataset_isassociated(sigrdataset)));
 
        return ((db->methods->findzonecut)(db, name, options, now, nodep,
-                                          foundname, rdataset, sigrdataset));
+                                          foundname, dcname,
+                                          rdataset, sigrdataset));
 }
 
 void
index 45a5d1b46515f06893dff11cd745143954f8cec6..465b96c3c9b27f656e831f940cda8bd191f56e30 100644 (file)
@@ -311,7 +311,8 @@ static isc_result_t
 findzonecut(dns_db_t *db, const dns_name_t *name,
            unsigned int options, isc_stdtime_t now,
            dns_dbnode_t **nodep, dns_name_t *foundname,
-           dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset)
+           dns_name_t *dcname, dns_rdataset_t *rdataset,
+           dns_rdataset_t *sigrdataset)
 {
        dns_ecdb_t *ecdb = (dns_ecdb_t *)db;
 
@@ -322,6 +323,7 @@ findzonecut(dns_db_t *db, const dns_name_t *name,
        UNUSED(now);
        UNUSED(nodep);
        UNUSED(foundname);
+       UNUSED(dcname);
        UNUSED(rdataset);
        UNUSED(sigrdataset);
 
index 42535cdfb0f9ddeac321b5c1f0ef889a032d121a..1492aa67bd7c496f225d7d8e5bc8a273a9e10a79 100644 (file)
@@ -147,7 +147,7 @@ static struct tt {
        int type;
        char classname[TYPECLASSBUF];
        char typename[TYPECLASSBUF];
-       char dirname[DIRNAMESIZE];      /* XXX Should be max path length */
+       char dirname[DIRNAMESIZE-30];   /* XXX Should be max path length */
 } *types;
 
 static struct ttnam {
index cb6c034342c30e7bb5c15a5a7eeae919735541b3..b7b28c4ed75880d3000e6a08216c7a97ee1525f2 100644 (file)
@@ -103,6 +103,7 @@ typedef struct dns_dbmethods {
                                       unsigned int options, isc_stdtime_t now,
                                       dns_dbnode_t **nodep,
                                       dns_name_t *foundname,
+                                      dns_name_t *dcname,
                                       dns_rdataset_t *rdataset,
                                       dns_rdataset_t *sigrdataset);
        void            (*attachnode)(dns_db_t *db,
@@ -936,7 +937,8 @@ isc_result_t
 dns_db_findzonecut(dns_db_t *db, const dns_name_t *name,
                   unsigned int options, isc_stdtime_t now,
                   dns_dbnode_t **nodep, dns_name_t *foundname,
-                  dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset);
+                  dns_name_t *dcname, dns_rdataset_t *rdataset,
+                  dns_rdataset_t *sigrdataset);
 /*%<
  * Find the deepest known zonecut which encloses 'name' in 'db'.
  *
@@ -955,6 +957,8 @@ dns_db_findzonecut(dns_db_t *db, const dns_name_t *name,
  *
  * \li 'foundname' is a valid name with a dedicated buffer.
  *
+ * \li 'dcname' is a valid name with a dedicated buffer.
+ *
  * \li 'rdataset' is NULL, or is a valid unassociated rdataset.
  *
  * Ensures, on a non-error completion:
@@ -964,6 +968,9 @@ dns_db_findzonecut(dns_db_t *db, const dns_name_t *name,
  * \li If foundname != NULL, then it contains the full name of the
  *     found node.
  *
+ * \li If dcname != NULL, then it contains the deepest cached name
+ *      that exists in the database.
+ *
  * \li If rdataset != NULL and type != dns_rdatatype_any, then
  *     rdataset is bound to the found rdataset.
  *
index e7a70f27ba619b2270974c9081d93faf6c2a8911..c8c7f25536c7119037afc4abf57419898240cf8c 100644 (file)
@@ -704,7 +704,7 @@ dns_view_simplefind(dns_view_t *view, const dns_name_t *name,
 
 isc_result_t
 dns_view_findzonecut(dns_view_t *view, const dns_name_t *name,
-                    dns_name_t *fname, isc_stdtime_t now,
+                    dns_name_t *fname, dns_name_t *dcname, isc_stdtime_t now,
                     unsigned int options,
                     bool use_hints, bool use_cache,
                     dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset);
@@ -730,6 +730,8 @@ dns_view_findzonecut(dns_view_t *view, const dns_name_t *name,
  *\li  If the DNS_DBFIND_NOEXACT option is set, then the zonecut returned
  *     (if any) will be the deepest known ancestor of 'name'.
  *
+ *\li  If dcname is not NULL the deepest cached name is copied to it.
+ *
  * Requires:
  *
  *\li  'view' is a valid, frozen view.
index 92d8d0ec727b69c220bf58126de6406436367fa6..b2da8abddf5614b28cd3e53151b6b893c7b9202f 100644 (file)
@@ -4307,7 +4307,7 @@ zone_find(dns_db_t *db, const dns_name_t *name, dns_dbversion_t *version,
 static isc_result_t
 zone_findzonecut(dns_db_t *db, const dns_name_t *name, unsigned int options,
                 isc_stdtime_t now, dns_dbnode_t **nodep,
-                dns_name_t *foundname,
+                dns_name_t *foundname, dns_name_t *dcname,
                 dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset)
 {
        UNUSED(db);
@@ -4316,6 +4316,7 @@ zone_findzonecut(dns_db_t *db, const dns_name_t *name, unsigned int options,
        UNUSED(now);
        UNUSED(nodep);
        UNUSED(foundname);
+       UNUSED(dcname);
        UNUSED(rdataset);
        UNUSED(sigrdataset);
 
@@ -5034,7 +5035,7 @@ cache_find(dns_db_t *db, const dns_name_t *name, dns_dbversion_t *version,
 static isc_result_t
 cache_findzonecut(dns_db_t *db, const dns_name_t *name, unsigned int options,
                  isc_stdtime_t now, dns_dbnode_t **nodep,
-                 dns_name_t *foundname,
+                 dns_name_t *foundname, dns_name_t *dcname,
                  dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset)
 {
        dns_rbtnode_t *node = NULL;
@@ -5045,6 +5046,7 @@ cache_findzonecut(dns_db_t *db, const dns_name_t *name, unsigned int options,
        rdatasetheader_t *found, *foundsig;
        unsigned int rbtoptions = DNS_RBTFIND_EMPTYDATA;
        isc_rwlocktype_t locktype;
+       bool dcnull = (dcname == NULL);
 
        search.rbtdb = (dns_rbtdb_t *)db;
 
@@ -5064,6 +5066,10 @@ cache_findzonecut(dns_db_t *db, const dns_name_t *name, unsigned int options,
        dns_rbtnodechain_init(&search.chain, search.rbtdb->common.mctx);
        search.now = now;
 
+       if (dcnull) {
+               dcname = foundname;
+       }
+
        if ((options & DNS_DBFIND_NOEXACT) != 0)
                rbtoptions |= DNS_RBTFIND_NOEXACT;
 
@@ -5072,17 +5078,18 @@ cache_findzonecut(dns_db_t *db, const dns_name_t *name, unsigned int options,
        /*
         * Search down from the root of the tree.
         */
-       result = dns_rbt_findnode(search.rbtdb->tree, name, foundname, &node,
+       result = dns_rbt_findnode(search.rbtdb->tree, name, dcname, &node,
                                  &search.chain, rbtoptions, NULL, &search);
 
        if (result == DNS_R_PARTIALMATCH) {
-       find_ns:
                result = find_deepest_zonecut(&search, node, nodep, foundname,
                                              rdataset, sigrdataset);
                goto tree_exit;
-       } else if (result != ISC_R_SUCCESS)
+       } else if (result != ISC_R_SUCCESS) {
                goto tree_exit;
-
+       } else if (!dcnull) {
+               dns_name_copy(dcname, foundname, NULL);
+       }
        /*
         * We now go looking for an NS rdataset at the node.
         */
@@ -5129,7 +5136,9 @@ cache_findzonecut(dns_db_t *db, const dns_name_t *name, unsigned int options,
                 * No NS records here.
                 */
                NODE_UNLOCK(lock, locktype);
-               goto find_ns;
+               result = find_deepest_zonecut(&search, node, nodep, foundname,
+                                             rdataset, sigrdataset);
+               goto tree_exit;
        }
 
        if (nodep != NULL) {
index b4aa0946305cf1e4c0963f66df5969b1d0dc7839..a19e5680ba8c4eaa38a4db941482c1221d4f9fca 100644 (file)
@@ -261,8 +261,8 @@ struct fetchctx {
        /*% Not locked. */
        unsigned int                    magic;
        dns_resolver_t *                res;
-       dns_name_t                      fullname;
-       dns_rdatatype_t                 fulltype;
+       dns_name_t                      name;
+       dns_rdatatype_t                 type;
        unsigned int                    options;
        unsigned int                    bucketnum;
        unsigned int                    dbucketnum;
@@ -311,10 +311,12 @@ struct fetchctx {
        isc_counter_t *                 qc;
        bool                    minimized;
        unsigned int                    qmin_labels;
-       unsigned int                    qmin_steps;
-       bool                    ip6arpaskip;
-       dns_name_t                      name;
-       dns_rdatatype_t                 type;
+       bool                            ip6arpaskip;
+       dns_name_t                      qminname;
+       dns_rdatatype_t                 qmintype;
+       dns_fetch_t *                   qminfetch;
+       dns_rdataset_t                  qminrrset;
+       dns_name_t                      qmindcname;
 
        /*%
         * The number of events we're waiting for.
@@ -558,6 +560,12 @@ struct dns_resolver {
 #define NXDOMAIN(r) (((r)->attributes & DNS_RDATASETATTR_NXDOMAIN) != 0)
 #define NEGATIVE(r) (((r)->attributes & DNS_RDATASETATTR_NEGATIVE) != 0)
 
+#define NXDOMAIN_RESULT(r)      ((r) == DNS_R_NXDOMAIN || \
+                                 (r) == DNS_R_NCACHENXDOMAIN)
+#define NXRRSET_RESULT(r)       ((r) == DNS_R_NCACHENXRRSET || \
+                                 (r) == DNS_R_NXRRSET || \
+                                 (r) == DNS_R_HINTNXRRSET)
+
 #ifdef ENABLE_AFL
 bool dns_fuzzing_resolver = false;
 void dns_resolver_setfuzzing() {
@@ -597,6 +605,7 @@ static inline isc_result_t findnoqname(fetchctx_t *fctx, dns_name_t *name,
                                       dns_name_t **noqname);
 static void fctx_increference(fetchctx_t *fctx);
 static bool fctx_decreference(fetchctx_t *fctx);
+static void resume_qmin(isc_task_t *task, isc_event_t *event);
 
 /*%
  * The structure and functions defined below implement the resolver
@@ -766,12 +775,6 @@ rctx_referral(respctx_t *rctx);
 static isc_result_t
 rctx_answer_none(respctx_t *rctx);
 
-static void
-rctx_follow_referral(respctx_t *rctx);
-
-static isc_result_t
-rctx_answer_minimized(respctx_t *rctx);
-
 static void
 rctx_nextserver(respctx_t *rctx, dns_adbaddrinfo_t *addrinfo,
                isc_result_t result);
@@ -3339,6 +3342,7 @@ findname(fetchctx_t *fctx, const dns_name_t *name, in_port_t port,
                                    options, now, NULL,
                                    res->view->dstport,
                                    fctx->depth + 1, fctx->qc, &find);
+
        if (result != ISC_R_SUCCESS) {
                if (result == DNS_R_ALIAS) {
                        char namebuf[DNS_NAME_FORMATSIZE];
@@ -3930,6 +3934,7 @@ fctx_try(fetchctx_t *fctx, bool retrying, bool badcache) {
        isc_result_t result;
        dns_adbaddrinfo_t *addrinfo = NULL;
        dns_resolver_t *res;
+       isc_task_t *task;
        unsigned int bucketnum;
        bool bucket_empty;
 
@@ -3938,6 +3943,7 @@ fctx_try(fetchctx_t *fctx, bool retrying, bool badcache) {
        REQUIRE(!ADDRWAIT(fctx));
 
        res = fctx->res;
+       bucketnum = fctx->bucketnum;
 
        /* We've already exceeded maximum query count */
        if (isc_counter_used(fctx->qc) > res->maxqueries) {
@@ -3951,6 +3957,26 @@ fctx_try(fetchctx_t *fctx, bool retrying, bool badcache) {
                return;
        }
 
+       /*
+        * We're minimizing and we're not yet at the final NS -
+        * we need to launch a query for NS for 'upper' domain
+        */
+       if (fctx->minimized == true) {
+               unsigned int options = fctx->options;
+               options &= ~DNS_FETCHOPT_QMINIMIZE;
+               fctx_increference(fctx);
+               task = res->buckets[bucketnum].task;
+               result = dns_resolver_createfetch(fctx->res, &fctx->qminname,
+                                                 fctx->qmintype, NULL,
+                                                 NULL, NULL, NULL, 0,
+                                                 options, 0, fctx->qc,
+                                                 task, resume_qmin, fctx,
+                                                 &fctx->qminrrset, NULL,
+                                                 &fctx->qminfetch);
+               return;
+       }
+
+
        addrinfo = fctx_nextaddress(fctx);
 
        /* Try to find an address that isn't over quota */
@@ -4005,7 +4031,6 @@ fctx_try(fetchctx_t *fctx, bool retrying, bool badcache) {
                }
        }
 
-       bucketnum = fctx->bucketnum;
        fctx_increference(fctx);
        result = fctx_query(fctx, addrinfo, fctx->options);
        if (result != ISC_R_SUCCESS) {
@@ -4019,6 +4044,118 @@ fctx_try(fetchctx_t *fctx, bool retrying, bool badcache) {
                inc_stats(res, dns_resstatscounter_retry);
 }
 
+static void
+resume_qmin(isc_task_t *task, isc_event_t *event) {
+       dns_fetchevent_t *fevent;
+       dns_resolver_t *res;
+       fetchctx_t *fctx;
+       isc_result_t result;
+       bool bucket_empty;
+       bool locked = false;
+       unsigned int bucketnum;
+       unsigned int findoptions = 0;
+       dns_name_t *fname, *dcname;
+       dns_fixedname_t ffixed, dcfixed;
+       fname = dns_fixedname_initname(&ffixed);
+       dcname = dns_fixedname_initname(&dcfixed);
+
+       REQUIRE(event->ev_type == DNS_EVENT_FETCHDONE);
+       fevent = (dns_fetchevent_t *)event;
+       fctx = event->ev_arg;
+       REQUIRE(VALID_FCTX(fctx));
+       res = fctx->res;
+
+       UNUSED(task);
+       FCTXTRACE("resume_qmin");
+
+       if (fevent->node != NULL)
+               dns_db_detachnode(fevent->db, &fevent->node);
+       if (fevent->db != NULL)
+               dns_db_detach(&fevent->db);
+
+       bucketnum = fctx->bucketnum;
+
+       if (dns_rdataset_isassociated(fevent->rdataset)) {
+               dns_rdataset_disassociate(fevent->rdataset);
+       }
+       result = fevent->result;
+       fevent = NULL;
+       isc_event_free(&event);
+
+       dns_resolver_destroyfetch(&fctx->qminfetch);
+
+       /*
+        * Note: fevent->rdataset must be disassociated and
+        * isc_event_free(&event) be called before resuming
+        * processing of the 'fctx' to prevent use-after-free.
+        * 'fevent' is set to NULL so as to not have a dangling
+        * pointer.
+        */
+       if (result == ISC_R_CANCELED) {
+               fctx_done(fctx, result, __LINE__);
+               goto cleanup;
+       } else if (NXDOMAIN_RESULT(result) || result == DNS_R_FORMERR ||
+                  result == DNS_R_REMOTEFORMERR)
+       {
+               if ((fctx->options & DNS_FETCHOPT_QMIN_STRICT) == 0) {
+                       isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
+                                     DNS_LOGMODULE_RESOLVER, ISC_LOG_INFO,
+                                     "disabling qname minimization for '%s' "
+                                     "due to nxdomain", fctx->info);
+                       fctx->qmin_labels = DNS_MAX_LABELS + 1;
+               } else {
+                       fctx_done(fctx, result, __LINE__);
+                       goto cleanup;
+               }
+       }
+
+
+       if (dns_rdataset_isassociated(&fctx->nameservers)) {
+               dns_rdataset_disassociate(&fctx->nameservers);
+       }
+
+       if (dns_rdatatype_atparent(fctx->type)) {
+               findoptions |= DNS_DBFIND_NOEXACT;
+       }
+       result = dns_view_findzonecut(res->view, &fctx->name, fname,
+                                     dcname, fctx->now, findoptions,
+                                     true, true, &fctx->nameservers, NULL);
+
+       if (result != ISC_R_SUCCESS) {
+               fctx_done(fctx, result, __LINE__);
+               return;
+       }
+       fcount_decr(fctx);
+       dns_name_free(&fctx->domain, fctx->mctx);
+       dns_name_init(&fctx->domain, NULL);
+       result = dns_name_dup(fname, fctx->mctx, &fctx->domain);
+       if (result != ISC_R_SUCCESS) {
+               fctx_done(fctx, result, __LINE__);
+               return;
+       }
+       dns_name_free(&fctx->qmindcname, fctx->mctx);
+       dns_name_init(&fctx->qmindcname, NULL);
+       result = dns_name_dup(dcname, fctx->mctx, &fctx->qmindcname);
+       if (result != ISC_R_SUCCESS) {
+               fctx_done(fctx, result, __LINE__);
+               return;
+       }
+       fctx->ns_ttl = fctx->nameservers.ttl;
+       fctx->ns_ttl_ok = true;
+       fctx_minimize_qname(fctx);
+       fctx_try(fctx, true, false);
+
+ cleanup:
+       INSIST(event == NULL);
+       INSIST(fevent == NULL);
+       if (!locked)
+               LOCK(&res->buckets[bucketnum].lock);
+       bucket_empty = fctx_decreference(fctx);
+       UNLOCK(&res->buckets[bucketnum].lock);
+       if (bucket_empty)
+               empty_bucket(res);
+}
+
 static bool
 fctx_unlink(fetchctx_t *fctx) {
        dns_resolver_t *res;
@@ -4119,8 +4256,9 @@ fctx_destroy(fetchctx_t *fctx) {
                dns_name_free(&fctx->domain, fctx->mctx);
        if (dns_rdataset_isassociated(&fctx->nameservers))
                dns_rdataset_disassociate(&fctx->nameservers);
-       dns_name_free(&fctx->fullname, fctx->mctx);
        dns_name_free(&fctx->name, fctx->mctx);
+       dns_name_free(&fctx->qminname, fctx->mctx);
+       dns_name_free(&fctx->qmindcname, fctx->mctx);
        dns_db_detach(&fctx->cache);
        dns_adb_detach(&fctx->adb);
        isc_mem_free(fctx->mctx, fctx->info);
@@ -4402,7 +4540,7 @@ fctx_join(fetchctx_t *fctx, isc_task_t *task, const isc_sockaddr_t *client,
                return (ISC_R_NOMEMORY);
        }
        event->result = DNS_R_SERVFAIL;
-       event->qtype = fctx->fulltype;
+       event->qtype = fctx->type;
        event->db = NULL;
        event->node = NULL;
        event->rdataset = rdataset;
@@ -4453,7 +4591,6 @@ fctx_create(dns_resolver_t *res, const dns_name_t *name, dns_rdatatype_t type,
        isc_result_t result;
        isc_result_t iresult;
        isc_interval_t interval;
-       dns_fixedname_t fixed;
        unsigned int findoptions = 0;
        char buf[DNS_NAME_FORMATSIZE + DNS_RDATATYPE_FORMATSIZE];
        char typebuf[DNS_RDATATYPE_FORMATSIZE];
@@ -4498,15 +4635,15 @@ fctx_create(dns_resolver_t *res, const dns_name_t *name, dns_rdatatype_t type,
        result = dns_name_dup(name, mctx, &fctx->name);
        if (result != ISC_R_SUCCESS)
                goto cleanup_info;
-       dns_name_init(&fctx->fullname, NULL);
-       result = dns_name_dup(name, mctx, &fctx->fullname);
+       dns_name_init(&fctx->qminname, NULL);
+       result = dns_name_dup(name, mctx, &fctx->qminname);
        if (result != ISC_R_SUCCESS)
-               goto cleanup_name;
+               goto cleanup_qminname;
        dns_name_init(&fctx->domain, NULL);
        dns_rdataset_init(&fctx->nameservers);
 
-       fctx->fulltype = type;
        fctx->type = type;
+       fctx->qmintype = type;
        fctx->options = options;
        /*
         * Note!  We do not attach to the task.  We are relying on the
@@ -4524,7 +4661,9 @@ fctx_create(dns_resolver_t *res, const dns_name_t *name, dns_rdatatype_t type,
        fctx->minimized = false;
        fctx->ip6arpaskip = false;
        fctx->qmin_labels = 1;
-       fctx->qmin_steps = 0;
+       fctx->qminfetch = NULL;
+       dns_rdataset_init(&fctx->qminrrset);
+       dns_name_init(&fctx->qmindcname, NULL);
        isc_stdtime_get(&fctx->now);
        ISC_LIST_INIT(fctx->queries);
        ISC_LIST_INIT(fctx->finds);
@@ -4576,6 +4715,7 @@ fctx_create(dns_resolver_t *res, const dns_name_t *name, dns_rdatatype_t type,
 
        if (domain == NULL) {
                dns_forwarders_t *forwarders = NULL;
+               dns_fixedname_t fixed;
                unsigned int labels;
                const dns_name_t *fwdname = name;
                dns_name_t suffix;
@@ -4602,6 +4742,9 @@ fctx_create(dns_resolver_t *res, const dns_name_t *name, dns_rdatatype_t type,
                        fctx->fwdpolicy = forwarders->fwdpolicy;
 
                if (fctx->fwdpolicy != dns_fwdpolicy_only) {
+                       dns_fixedname_t dcfixed;
+                       dns_name_t *dcname;
+                       dcname = dns_fixedname_initname(&dcfixed);
                        /*
                         * The caller didn't supply a query domain and
                         * nameservers, and we're not in forward-only mode,
@@ -4610,17 +4753,22 @@ fctx_create(dns_resolver_t *res, const dns_name_t *name, dns_rdatatype_t type,
                        if (dns_rdatatype_atparent(fctx->type))
                                findoptions |= DNS_DBFIND_NOEXACT;
                        result = dns_view_findzonecut(res->view, name, fname,
-                                                     0, findoptions, true,
-                                                     true,
+                                                     dcname, fctx->now,
+                                                     findoptions, true, true,
                                                      &fctx->nameservers,
                                                      NULL);
-                       if (result != ISC_R_SUCCESS)
+                       if (result != ISC_R_SUCCESS) {
                                goto cleanup_nameservers;
+                       }
 
                        result = dns_name_dup(fname, mctx, &fctx->domain);
-                       if (result != ISC_R_SUCCESS)
+                       if (result != ISC_R_SUCCESS) {
                                goto cleanup_nameservers;
-
+                       }
+                       result = dns_name_dup(dcname, mctx, &fctx->qmindcname);
+                       if (result != ISC_R_SUCCESS) {
+                               goto cleanup_domain;
+                       }
                        fctx->ns_ttl = fctx->nameservers.ttl;
                        fctx->ns_ttl_ok = true;
                } else {
@@ -4628,13 +4776,27 @@ fctx_create(dns_resolver_t *res, const dns_name_t *name, dns_rdatatype_t type,
                         * We're in forward-only mode.  Set the query domain.
                         */
                        result = dns_name_dup(fname, mctx, &fctx->domain);
-                       if (result != ISC_R_SUCCESS)
-                               goto cleanup_fullname;
+                       if (result != ISC_R_SUCCESS) {
+                               goto cleanup_name;
+                       }
+                       result = dns_name_dup(fname, mctx, &fctx->qmindcname);
+                       if (result != ISC_R_SUCCESS) {
+                               goto cleanup_domain;
+                       }
+                       /*
+                        * Disable query minimization
+                        */
+                       options &= ~DNS_FETCHOPT_QMINIMIZE;
                }
        } else {
                result = dns_name_dup(domain, mctx, &fctx->domain);
-               if (result != ISC_R_SUCCESS)
-                       goto cleanup_fullname;
+               if (result != ISC_R_SUCCESS) {
+                       goto cleanup_name;
+               }
+               result = dns_name_dup(domain, mctx, &fctx->qmindcname);
+               if (result != ISC_R_SUCCESS) {
+                       goto cleanup_domain;
+               }
                dns_rdataset_clone(nameservers, &fctx->nameservers);
                fctx->ns_ttl = fctx->nameservers.ttl;
                fctx->ns_ttl_ok = true;
@@ -4754,17 +4916,19 @@ fctx_create(dns_resolver_t *res, const dns_name_t *name, dns_rdatatype_t type,
  cleanup_domain:
        if (dns_name_countlabels(&fctx->domain) > 0)
                dns_name_free(&fctx->domain, mctx);
+       if (dns_name_countlabels(&fctx->qmindcname) > 0)
+               dns_name_free(&fctx->qmindcname, mctx);
 
  cleanup_nameservers:
        if (dns_rdataset_isassociated(&fctx->nameservers))
                dns_rdataset_disassociate(&fctx->nameservers);
 
- cleanup_fullname:
-       dns_name_free(&fctx->fullname, mctx);
-
  cleanup_name:
        dns_name_free(&fctx->name, mctx);
 
+ cleanup_qminname:
+       dns_name_free(&fctx->qminname, mctx);
+
  cleanup_info:
        isc_mem_free(mctx, fctx->info);
 
@@ -6469,10 +6633,13 @@ check_related(void *arg, const dns_name_t *addname, dns_rdatatype_t type) {
 #ifndef CHECK_FOR_GLUE_IN_ANSWER
 #define CHECK_FOR_GLUE_IN_ANSWER 0
 #endif
+
+#if CHECK_FOR_GLUE_IN_ANSWER
 static isc_result_t
 check_answer(void *arg, const dns_name_t *addname, dns_rdatatype_t type) {
        return (check_section(arg, addname, type, DNS_SECTION_ANSWER));
 }
+#endif
 
 static bool
 is_answeraddress_allowed(dns_view_t *view, dns_name_t *name,
@@ -7768,12 +7935,7 @@ rctx_answer(respctx_t *rctx) {
        fetchctx_t *fctx = rctx->fctx;
        resquery_t *query = rctx->query;
 
-       if (fctx->minimized) {
-                       result = rctx_answer_minimized(rctx);
-                       if (result != ISC_R_SUCCESS) {
-                               FCTXTRACE3("rctx_answer_minimized", result);
-                       }
-       } else if ((fctx->rmessage->flags & DNS_MESSAGEFLAG_AA) != 0 ||
+       if ((fctx->rmessage->flags & DNS_MESSAGEFLAG_AA) != 0 ||
            ISFORWARDER(query->addrinfo))
        {
                result = rctx_answer_positive(rctx);
@@ -8478,19 +8640,6 @@ rctx_answer_none(respctx_t *rctx) {
                } else {
                        log_formerr(fctx, "invalid response");
                }
-               /*
-                * If we're minimizing in relaxed mode, retry with full name,
-                * just to be safe. The error will be logged.
-                */
-               if (fctx->minimized &&
-                   (fctx->options & DNS_FETCHOPT_QMIN_STRICT) == 0) {
-                       isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
-                                     DNS_LOGMODULE_RESOLVER, ISC_LOG_INFO,
-                                     "disabling qname minimization for '%s' "
-                                     "due to formerr", fctx->info);
-                       fctx->qmin_labels = DNS_MAX_LABELS + 1;
-                       return (rctx_answer_minimized(rctx));
-               }
                return (DNS_R_FORMERR);
        }
 
@@ -8512,21 +8661,6 @@ rctx_answer_none(respctx_t *rctx) {
                return (rctx->result);
        }
 
-       /*
-        * If we're doing qname minimization this is an empty non-terminal, add
-        * the next label to query and restart it.
-        */
-       if (fctx->minimized && fctx->rmessage->rcode == dns_rcode_noerror) {
-               return (rctx_answer_minimized(rctx));
-       }
-       /*
-        * Workaround for broken servers in relaxed mode - if we hit an
-        * NXDOMAIN we go straight to the full query.
-        */
-       if (fctx->minimized && !(fctx->options & DNS_FETCHOPT_QMIN_STRICT)) {
-               fctx->qmin_labels = DNS_MAX_LABELS + 1;
-               return (rctx_answer_minimized(rctx));
-       }
        /*
         * Since we're not doing a referral, we don't want to cache any
         * NS RRs we may have found.
@@ -8894,10 +9028,6 @@ rctx_referral(respctx_t *rctx) {
                                                  check_answer, fctx);
        }
 #endif
-       if (fctx->minimized) {
-               (void)dns_rdataset_additionaldata(rctx->ns_rdataset,
-                                                 check_answer, fctx);
-       }
        fctx->attributes &= ~FCTX_ATTR_GLUING;
 
        /*
@@ -8943,39 +9073,6 @@ rctx_referral(respctx_t *rctx) {
        log_ns_ttl(fctx, "DELEGATION");
        rctx->result = DNS_R_DELEGATION;
 
-       rctx_follow_referral(rctx);
-       if (rctx->fctx->minimized) {
-               /*
-                * Reset the value
-                */
-               fctx->qmin_labels = 1;
-               fctx_minimize_qname(rctx->fctx);
-       }
-       return (ISC_R_COMPLETE);
-}
-
-/*
- * rctx_answer_minimized():
- * Handles a positive response to a qname-minimized query.
- */
-static isc_result_t
-rctx_answer_minimized(respctx_t *rctx) {
-       fetchctx_t *fctx = rctx->fctx;
-
-       FCTXTRACE("rctx_answer_minimized");
-       if (dns_rdataset_isassociated(&fctx->nameservers)) {
-               dns_rdataset_disassociate(&fctx->nameservers);
-       }
-       rctx->result = DNS_R_DELEGATION;
-       rctx_follow_referral(rctx);
-       fctx->qmin_labels++;
-       fctx_minimize_qname(rctx->fctx);
-
-       return (ISC_R_SUCCESS);
-}
-
-static void
-rctx_follow_referral(respctx_t *rctx) {
        /*
         * Reinitialize 'rctx' to prepare for following the delegation:
         * set the get_nameservers and next_server flags appropriately and
@@ -8992,6 +9089,8 @@ rctx_follow_referral(respctx_t *rctx) {
        rctx->fctx->neterr = 0;
        rctx->fctx->badresp = 0;
        rctx->fctx->adberr = 0;
+
+       return (ISC_R_COMPLETE);
 }
 
 /*
@@ -9058,11 +9157,12 @@ rctx_nextserver(respctx_t *rctx, dns_adbaddrinfo_t *addrinfo,
        }
 
        if (rctx->get_nameservers) {
-               dns_fixedname_t foundname;
-               dns_name_t *name, *fname;
+               dns_fixedname_t foundname, founddc;
+               dns_name_t *name, *fname, *dcname;
                unsigned int findoptions = 0;
 
                fname = dns_fixedname_initname(&foundname);
+               dcname = dns_fixedname_initname(&founddc);
 
                if (result != ISC_R_SUCCESS) {
                        fctx_done(fctx, DNS_R_SERVFAIL, __LINE__);
@@ -9075,11 +9175,9 @@ rctx_nextserver(respctx_t *rctx, dns_adbaddrinfo_t *addrinfo,
                } else {
                        name = &fctx->domain;
                }
-               result = dns_view_findzonecut(fctx->res->view,
-                                             name, fname,
-                                             fctx->now, findoptions,
-                                             true, true,
-                                             &fctx->nameservers,
+               result = dns_view_findzonecut(fctx->res->view, name, fname,
+                                             dcname, fctx->now, findoptions,
+                                             true, true, &fctx->nameservers,
                                              NULL);
                if (result != ISC_R_SUCCESS) {
                        FCTXTRACE("couldn't find a zonecut");
@@ -9096,6 +9194,7 @@ rctx_nextserver(respctx_t *rctx, dns_adbaddrinfo_t *addrinfo,
                }
 
                fcount_decr(fctx);
+
                dns_name_free(&fctx->domain, fctx->mctx);
                dns_name_init(&fctx->domain, NULL);
                result = dns_name_dup(fname, fctx->mctx, &fctx->domain);
@@ -9103,6 +9202,14 @@ rctx_nextserver(respctx_t *rctx, dns_adbaddrinfo_t *addrinfo,
                        fctx_done(fctx, DNS_R_SERVFAIL, __LINE__);
                        return;
                }
+               dns_name_free(&fctx->qmindcname, fctx->mctx);
+               dns_name_init(&fctx->qmindcname, NULL);
+               result = dns_name_dup(dcname, fctx->mctx, &fctx->qmindcname);
+               if (result != ISC_R_SUCCESS) {
+                       fctx_done(fctx, DNS_R_SERVFAIL, __LINE__);
+                       return;
+               }
+
                result = fcount_incr(fctx, true);
                if (result != ISC_R_SUCCESS) {
                        fctx_done(fctx, DNS_R_SERVFAIL, __LINE__);
@@ -9367,20 +9474,8 @@ rctx_badserver(respctx_t *rctx, isc_result_t result) {
                return (ISC_R_SUCCESS);
        }
 
-       /*
-        * If we're minimizing in relaxed mode try to disable minimization.
-        */
-       if (fctx->minimized &&
-           (fctx->options & DNS_FETCHOPT_QMIN_STRICT) == 0)
-       {
-               isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,
-                             DNS_LOGMODULE_RESOLVER, ISC_LOG_INFO,
-                             "disabling qname minimization for '%s'"
-                             " due to bad server", fctx->info);
-               fctx->qmin_labels = DNS_MAX_LABELS + 1;
-               result = rctx_answer_minimized(rctx);
-       } else if ((fctx->rmessage->rcode == dns_rcode_formerr) &&
-                  (rctx->retryopts & DNS_FETCHOPT_NOEDNS0) == 0)
+       if ((fctx->rmessage->rcode == dns_rcode_formerr) &&
+           (rctx->retryopts & DNS_FETCHOPT_NOEDNS0) == 0)
        {
                /*
                 * It's very likely they don't like EDNS0.
@@ -10189,9 +10284,9 @@ fctx_match(fetchctx_t *fctx, const dns_name_t *name, dns_rdatatype_t type,
            ISC_LIST_EMPTY(fctx->events))
                return (false);
 
-       if (fctx->fulltype != type || fctx->options != options)
+       if (fctx->type != type || fctx->options != options)
                return (false);
-       return (dns_name_equal(&fctx->fullname, name));
+       return (dns_name_equal(&fctx->name, name));
 }
 
 static inline void
@@ -10217,16 +10312,17 @@ log_fetch(const dns_name_t *name, dns_rdatatype_t type) {
 
 void
 fctx_minimize_qname(fetchctx_t *fctx) {
-       /*
-        * XXXWPK TODO we should update info to show that this query
-        * is minimized
-        */
        unsigned int dlabels, nlabels;
 
-       dlabels = dns_name_countlabels(&fctx->domain);
-       nlabels = dns_name_countlabels(&fctx->fullname);
-       dns_name_free(&fctx->name, fctx->mctx);
-       dns_name_init(&fctx->name, NULL);
+       dlabels = dns_name_countlabels(&fctx->qmindcname);
+       nlabels = dns_name_countlabels(&fctx->name);
+       dns_name_free(&fctx->qminname, fctx->mctx);
+       dns_name_init(&fctx->qminname, NULL);
+       if (dlabels > fctx->qmin_labels) {
+               fctx->qmin_labels = dlabels+1;
+       } else {
+               fctx->qmin_labels++;
+       }
        if (fctx->ip6arpaskip) {
                /*
                 * For ip6.arpa we want to skip some of the labels, with
@@ -10235,43 +10331,39 @@ fctx_minimize_qname(fetchctx_t *fctx) {
                 *    7    11   15   17   19      35
                 * We fix fctx->qmin_labels to point to the nearest boundary
                 */
-               if (dlabels + fctx->qmin_labels < 7) {
-                       fctx->qmin_labels = 7 - dlabels;
-               } else if (dlabels + fctx->qmin_labels < 11) {
-                       fctx->qmin_labels = 11 - dlabels;
-               } else if (dlabels + fctx->qmin_labels < 15) {
-                       fctx->qmin_labels = 15 - dlabels;
-               } else if (dlabels + fctx->qmin_labels < 17) {
-                       fctx->qmin_labels = 17 - dlabels;
-               } else if (dlabels + fctx->qmin_labels < 19) {
-                       fctx->qmin_labels = 19 - dlabels;
-               } else if (dlabels + fctx->qmin_labels > 19) {
-                       fctx->qmin_labels = 35 - dlabels;
-               }
-       } else if (dlabels + fctx->qmin_labels > DNS_QMIN_MAXLABELS) {
-                       fctx->qmin_labels = DNS_MAX_LABELS + 1;
-       } else if (fctx->qmin_labels > DNS_QMIN_MAX_NO_DELEGATION) {
-                       fctx->qmin_labels = DNS_MAX_LABELS + 1;
+               if (fctx->qmin_labels < 7) {
+                       fctx->qmin_labels = 7;
+               } else if (fctx->qmin_labels < 11) {
+                       fctx->qmin_labels = 11;
+               } else if (fctx->qmin_labels < 15) {
+                       fctx->qmin_labels = 15;
+               } else if (fctx->qmin_labels < 17) {
+                       fctx->qmin_labels = 17;
+               } else if (fctx->qmin_labels < 19) {
+                       fctx->qmin_labels = 19;
+               } else if (fctx->qmin_labels > 19) {
+                       fctx->qmin_labels = 35;
+               }
+       } else if (fctx->qmin_labels > DNS_QMIN_MAXLABELS) {
+               fctx->qmin_labels = DNS_MAX_LABELS + 1;
        }
-       if (dlabels + fctx->qmin_labels < nlabels) {
+       if (fctx->qmin_labels < nlabels) {
                /*
-                * We want to query for
-                * [qmin_labels from fctx->fullname] + fctx->domain
+                * We want to query for qmin_labels from fctx->name
                 */
                dns_fixedname_t fname;
                dns_fixedname_init(&fname);
-               dns_name_split(&fctx->fullname,
-                              dlabels + fctx->qmin_labels,
+               dns_name_split(&fctx->name,
+                              fctx->qmin_labels,
                               NULL, dns_fixedname_name(&fname));
                dns_name_dup(dns_fixedname_name(&fname), fctx->mctx,
-                            &fctx->name);
-               fctx->type = dns_rdatatype_ns;
+                            &fctx->qminname);
+               fctx->qmintype = dns_rdatatype_ns;
                fctx->minimized = true;
-               fctx->qmin_steps++;
        } else {
                /* Minimization is done, we'll ask for whole qname */
-               fctx->type = fctx->fulltype;
-               dns_name_dup(&fctx->fullname, fctx->mctx, &fctx->name);
+               fctx->qmintype = fctx->type;
+               dns_name_dup(&fctx->name, fctx->mctx, &fctx->qminname);
                fctx->minimized = false;
        }
 }
@@ -10540,8 +10632,7 @@ dns_resolver_logfetch(dns_fetch_t *fetch, isc_log_t *lctx,
                              "%06" PRIu64 ": %s/%s "
                              "[domain:%s,referral:%u,restart:%u,qrysent:%u,"
                              "timeout:%u,lame:%u,quota:%u,neterr:%u,"
-                             "badresp:%u,adberr:%u,findfail:%u,valfail:%u,"
-                             "qminsteps:%u]",
+                             "badresp:%u,adberr:%u,findfail:%u,valfail:%u]",
                              __FILE__, fctx->exitline, fctx->info,
                              fctx->duration / US_PER_SEC,
                              fctx->duration % US_PER_SEC,
@@ -10551,8 +10642,7 @@ dns_resolver_logfetch(dns_fetch_t *fetch, isc_log_t *lctx,
                              fctx->querysent, fctx->timeouts,
                              fctx->lamecount, fctx->quotacount,
                              fctx->neterr, fctx->badresp, fctx->adberr,
-                             fctx->findfail, fctx->valfail,
-                             fctx->qmin_steps);
+                             fctx->findfail, fctx->valfail);
                fctx->logged = true;
        }
 
index 1a20f36b6f6de4ff1310de0af67e1421667ad9c0..f70c17f4bc39ffc5bdb0ee98aa221a5666e20d9f 100644 (file)
@@ -986,7 +986,8 @@ findext(dns_db_t *db, const dns_name_t *name, dns_dbversion_t *version,
 static isc_result_t
 findzonecut(dns_db_t *db, const dns_name_t *name, unsigned int options,
            isc_stdtime_t now, dns_dbnode_t **nodep, dns_name_t *foundname,
-           dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset)
+           dns_name_t *dcname, dns_rdataset_t *rdataset,
+           dns_rdataset_t *sigrdataset)
 {
        UNUSED(db);
        UNUSED(name);
@@ -994,6 +995,7 @@ findzonecut(dns_db_t *db, const dns_name_t *name, unsigned int options,
        UNUSED(now);
        UNUSED(nodep);
        UNUSED(foundname);
+       UNUSED(dcname);
        UNUSED(rdataset);
        UNUSED(sigrdataset);
 
index 979cbf52d7212bd357f965566f4edcb48fd2da45..8bb66e8f1b54718a9e8cbbf229e7192b3eaca50a 100644 (file)
@@ -715,7 +715,8 @@ findnode(dns_db_t *db, const dns_name_t *name, bool create,
 static isc_result_t
 findzonecut(dns_db_t *db, const dns_name_t *name, unsigned int options,
            isc_stdtime_t now, dns_dbnode_t **nodep, dns_name_t *foundname,
-           dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset)
+           dns_name_t *dcname, dns_rdataset_t *rdataset,
+           dns_rdataset_t *sigrdataset)
 {
        UNUSED(db);
        UNUSED(name);
@@ -723,6 +724,7 @@ findzonecut(dns_db_t *db, const dns_name_t *name, unsigned int options,
        UNUSED(now);
        UNUSED(nodep);
        UNUSED(foundname);
+       UNUSED(dcname);
        UNUSED(rdataset);
        UNUSED(sigrdataset);
 
index 45d94bff815627ee3a5c74dac6179e77801bad8f..9894059143f4ae694be47cc9906c067ab4e09b0c 100644 (file)
@@ -3400,7 +3400,7 @@ proveunsecure(dns_validator_t *val, bool have_ds, bool resume)
                         */
                        if (result == DNS_R_NXRRSET &&
                            !dns_rdataset_isassociated(&val->frdataset) &&
-                       dns_view_findzonecut(val->view, tname, found,
+                       dns_view_findzonecut(val->view, tname, found, NULL,
                                             0, 0, false, false,
                                             NULL, NULL) == ISC_R_SUCCESS &&
                            dns_name_equal(tname, found)) {
index 53e04b67614438a934a0a94748a5c5bc49450839..2ac81bdcca8ea7077b372c9e0d3f4aa9f585ee17 100644 (file)
@@ -1254,7 +1254,7 @@ dns_view_simplefind(dns_view_t *view, const dns_name_t *name,
 
 isc_result_t
 dns_view_findzonecut(dns_view_t *view, const dns_name_t *name,
-                    dns_name_t *fname, isc_stdtime_t now,
+                    dns_name_t *fname, dns_name_t *dcname, isc_stdtime_t now,
                     unsigned int options, bool use_hints,
                     bool use_cache, dns_rdataset_t *rdataset,
                     dns_rdataset_t *sigrdataset)
@@ -1357,7 +1357,8 @@ dns_view_findzonecut(dns_view_t *view, const dns_name_t *name,
                }
        } else {
                result = dns_db_findzonecut(db, name, options, now, NULL,
-                                           fname, rdataset, sigrdataset);
+                                           fname, dcname, rdataset,
+                                           sigrdataset);
                if (result == ISC_R_SUCCESS) {
                        if (zfname != NULL &&
                            (!dns_name_issubdomain(fname, zfname) ||
@@ -1401,6 +1402,11 @@ dns_view_findzonecut(dns_view_t *view, const dns_name_t *name,
                result = dns_name_copy(zfname, fname, NULL);
                if (result != ISC_R_SUCCESS)
                        goto cleanup;
+               if (dcname != NULL) {
+                       result = dns_name_copy(zfname, dcname, NULL);
+                       if (result != ISC_R_SUCCESS)
+                               goto cleanup;
+               }
                dns_rdataset_clone(&zrdataset, rdataset);
                if (sigrdataset != NULL &&
                    dns_rdataset_isassociated(&zrdataset))
@@ -1420,6 +1426,8 @@ dns_view_findzonecut(dns_view_t *view, const dns_name_t *name,
                        if (dns_rdataset_isassociated(rdataset))
                                dns_rdataset_disassociate(rdataset);
                        result = ISC_R_NOTFOUND;
+               } else if (dcname != NULL) {
+                       dns_name_copy(fname, dcname, NULL);
                }
        }
 
index a1fc0d3a94723279d0f2737cf59866badeee0e65..fd423659f401a9b08895dcc7d14d214a3ab1b6cd 100644 (file)
@@ -10113,7 +10113,7 @@ query_addbestns(query_ctx_t *qctx) {
        } else {
                result = dns_db_findzonecut(db, client->query.qname,
                                            client->query.dboptions,
-                                           client->now, &node, fname,
+                                           client->now, &node, fname, NULL,
                                            rdataset, sigrdataset);
                if (result == ISC_R_SUCCESS) {
                        if (zfname != NULL &&