--- /dev/null
+ns1 simulates a root server
+
+ns2 is an auth server (over example.) which is also a resolver.
+
+ns3 is an auth server on `sub.example.`.
+
+The point of the test is to show that because ns2 knows the IP address of the
+NS delegating sub.example., there won't be any queries to resolve
+ns.sub.example.
+
+In order to prove it, ns2 also does a DNSTAP dump of its outgoing queries and
+checks there is no NS queries to ns3 (but only an AAAA query).
--- /dev/null
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.1;
+ notify-source 10.53.0.1;
+ transfer-source 10.53.0.1;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify yes;
+ dnssec-validation no;
+};
+
+zone "." {
+ type primary;
+ file "root.db";
+};
--- /dev/null
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300
+. IN SOA a.root.servers.nil. a.root.servers.nil. (
+ 2000042100 ; serial
+ 600 ; refresh
+ 600 ; retry
+ 1200 ; expire
+ 600 ; minimum
+ )
+. NS a.root-servers.nil.
+a.root-servers.nil. A 10.53.0.1
+
+example. NS ns.example.
+ns.example. A 10.53.0.2
--- /dev/null
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300
+@ IN SOA example. example. (
+ 2000042100 ; serial
+ 600 ; refresh
+ 600 ; retry
+ 1200 ; expire
+ 600 ; minimum
+ )
+@ NS ns.example.
+ns.example. A 10.53.0.2
+
+sub.example. NS ns.sub.example.
+ns.sub.example. A 10.53.0.3
--- /dev/null
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.2;
+ notify-source 10.53.0.2;
+ transfer-source 10.53.0.2;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { none; };
+ recursion yes;
+ notify yes;
+ dnssec-validation no;
+ dnstap { resolver query; };
+ dnstap-output file "dnstap.out";
+};
+
+zone "." {
+ type primary;
+ file "example.db";
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
--- /dev/null
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+options {
+ query-source address 10.53.0.3;
+ notify-source 10.53.0.3;
+ transfer-source 10.53.0.3;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.3; };
+ listen-on-v6 { none; };
+ recursion no;
+ notify yes;
+ dnssec-validation no;
+};
+
+zone "." {
+ type primary;
+ file "sub.example.db";
+};
--- /dev/null
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 300
+@ IN SOA sub.example. sub.example. (
+ 2000042100 ; serial
+ 600 ; refresh
+ 600 ; retry
+ 1200 ; expire
+ 600 ; minimum
+ )
+@ NS ns.sub.example.
+ns.sub.example. A 10.53.0.3
+
+aaaa.sub.example. AAAA ac::dc
--- /dev/null
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, you can obtain one at https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+import os
+
+import isctest
+import isctest.mark
+
+pytestmark = [isctest.mark.with_dnstap]
+
+
+def line_to_query(line):
+ # dnstap-read output line example
+ # 05-Feb-2026 11:00:57.853 RQ 10.53.0.6:38507 -> 10.53.0.3:22047 TCP 56b fooXXX.example./IN/NS
+ _, _, _, _, _, _, _, _, query = line.split(" ", 9)
+ return query
+
+
+def extract_dnstap(ns):
+ ns.rndc("dnstap -roll 1")
+ path = os.path.join(ns.identifier, "dnstap.out.0")
+ dnstapread = isctest.run.cmd(
+ [isctest.vars.ALL["DNSTAPREAD"], path],
+ )
+
+ lines = dnstapread.out.splitlines()
+ return list(map(line_to_query, lines))
+
+
+def test_auth_res_deleg(ns2):
+ msg = isctest.query.create("aaaa.sub.example.", "AAAA")
+ res = isctest.query.udp(msg, ns2.ip)
+ isctest.check.noerror(res)
+ assert len(res.answer[0]) == 1
+ res.answer[0].ttl = 300
+ assert str(res.answer[0]) == "aaaa.sub.example. 300 IN AAAA ac::dc"
+
+ queries = extract_dnstap(ns2)
+ assert len(queries) == 1
+ assert queries[0] == "aaaa.sub.example/IN/AAAA"
if (result != ISC_R_SUCCESS) {
result = DNS_R_NXDOMAIN;
} else {
- dns_delegset_fromrdataset(rdataset, delegsetp);
+ /*
+ * The rdataset came either from a local zone or a hint. Either
+ * way, we only considering the NS rdataset here, so if there
+ * are glues, they'll be ignored. This is okay: the delegation
+ * type will be DNS_DELEGSET_NS_NAMES, so ADB will do a NS name
+ * lookup but immediately find the results locally (because this
+ * came from a local zone or hint). So the resolution will be
+ * the same, and this avoid adding extra code here to extract
+ * A/AAAA rdataset if any.
+ */
+ dns_delegset_fromnsrdataset(rdataset, delegsetp);
}
dns_rdataset_cleanup(rdataset);
qctx->client->inner.now, 0, true,
true, &delegset);
if (tresult != ISC_R_SUCCESS) {
- dns_delegset_fromrdataset(qctx->rdataset, &delegset);
+ dns_delegset_fromnsrdataset(qctx->rdataset, &delegset);
fname = qctx->fname;
}