Commit 7195921147 for bind
commit 7195921147a9a07183c015d8a4c740363ef89bcc
Author: OndÅ™ej Surý <ondrej@isc.org>
Date: Thu Aug 13 15:13:49 2026 +0200
Honor minimal-any over TCP
TCP transport does not change the semantics of the minimal-any option.
Apply response minimization regardless of transport and retain coverage
for both enabled and disabled configurations.
diff --git a/bin/tests/system/additional/ns1/named2.conf.j2 b/bin/tests/system/additional/ns1/named2.conf.j2
index 06a6d045e1..520d6e60cb 100644
--- a/bin/tests/system/additional/ns1/named2.conf.j2
+++ b/bin/tests/system/additional/ns1/named2.conf.j2
@@ -3,6 +3,7 @@ options {
recursion no;
dnssec-validation no;
notify no;
+ minimal-any no;
minimal-responses no;
};
diff --git a/bin/tests/system/additional/tests.sh b/bin/tests/system/additional/tests.sh
index e434474ab1..aa199ebd7a 100644
--- a/bin/tests/system/additional/tests.sh
+++ b/bin/tests/system/additional/tests.sh
@@ -303,7 +303,7 @@ n=$((n + 1))
echo_i "testing with 'minimal-any yes;' over TCP ($n)"
ret=0
$DIG $DIGOPTS -t ANY +tcp www.rt.example @10.53.0.1 >dig.out.$n || ret=1
-grep "ANSWER: 3, AUTHORITY: 0, ADDITIONAL: 1" dig.out.$n >/dev/null || ret=1
+grep "ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1" dig.out.$n >/dev/null || ret=1
if [ $ret -eq 1 ]; then
echo_i "failed"
status=$((status + 1))
diff --git a/bin/tests/system/filters/common.py b/bin/tests/system/filters/common.py
index cade025568..0e94d65d69 100644
--- a/bin/tests/system/filters/common.py
+++ b/bin/tests/system/filters/common.py
@@ -52,27 +52,6 @@ def check_filtertype_only(dest, source, qname, ftype, expected, adflag):
), f"expected A {expected} in ANSWER: {res}"
-def check_any(dest, source, qname, expected4, expected6, do):
- qname = dns.name.from_text(qname)
- msg = isctest.query.create(qname, "any", dnssec=do)
- res = isctest.query.tcp(msg, dest, source=source)
- isctest.check.noerror(res)
- a_record = res.get_rrset(res.answer, qname, rdataclass.IN, rdatatype.A)
- if expected4:
- assert (
- a_record and a_record[0].address == expected4
- ), f"expected A {expected4} in ANSWER: {res}"
- else:
- assert not a_record
- aaaa_record = res.get_rrset(res.answer, qname, rdataclass.IN, rdatatype.AAAA)
- if expected6:
- assert (
- aaaa_record and aaaa_record[0].address == expected6
- ), f"expected AAAA {expected6} in ANSWER: {res}"
- else:
- assert not aaaa_record
-
-
def check_nodata(dest, source, qname, qtype, do, adflag):
msg = isctest.query.create(qname, qtype, dnssec=do)
res = isctest.query.tcp(msg, dest, source=source)
@@ -155,43 +134,6 @@ def check_filter(addr, altaddr, ftype, break_dnssec, recursive):
expected = "1.0.0.6" if ftype == "a" else "2001:db8::6"
check_filtertype_only(addr, altaddr, "dual.unsigned", ftype, expected, False)
- isctest.log.debug(
- f"check that A/AAAA (and not {qtype}) is returned if both AAAA and A exist, signed, qtype=ANY, DO=0"
- )
- expected4 = "1.0.0.3" if ftype == "aaaa" else None
- expected6 = "2001:db8::3" if ftype == "a" else None
- check_any(addr, addr, "dual.signed", expected4, expected6, False)
-
- isctest.log.debug(
- "check that both A and AAAA are returned if both AAAA and A exist, signed, qtype=ANY, DO=1, unless break-dnssec is enabled"
- )
- if break_dnssec:
- if ftype == "a":
- expected4 = None
- else:
- expected6 = None
- check_any(addr, addr, "dual.signed", expected4, expected6, True)
- else:
- check_any(addr, addr, "dual.signed", "1.0.0.3", "2001:db8::3", True)
-
- expected4 = "1.0.0.6" if ftype == "aaaa" else None
- expected6 = "2001:db8::6" if ftype == "a" else None
-
- isctest.log.debug(
- f"check that A/AAAA (and not {qtype}) is returned if both AAAA and A exist, unsigned, qtype=ANY, DO=0"
- )
- check_any(addr, addr, "dual.unsigned", expected4, expected6, False)
-
- isctest.log.debug(
- f"check that A/AAAA (and not {qtype}) is returned if both AAAA and A exist, unsigned, qtype=ANY, DO=1"
- )
- check_any(addr, addr, "dual.unsigned", expected4, expected6, True)
-
- isctest.log.debug(
- "check that both A and AAAA are returned if both AAAA and A exist, signed, qtype=ANY, query source does not match ACL"
- )
- check_any(addr, altaddr, "dual.unsigned", "1.0.0.6", "2001:db8::6", True)
-
isctest.log.debug(
f"check that {qtype} is omitted from additional section, qtype=NS, unsigned"
)
diff --git a/bin/tests/system/host/tests.sh b/bin/tests/system/host/tests.sh
index 4bc3bf93d9..7312679d5a 100644
--- a/bin/tests/system/host/tests.sh
+++ b/bin/tests/system/host/tests.sh
@@ -117,9 +117,8 @@ ret=0
$HOST -p ${PORT} -t ANY example.net 10.53.0.1 2>host.err${n} >host.out${n} || ret=1
lines=$(grep -c 'Address:.10\.53\.0\.1#'"${PORT}" host.out${n})
test $lines -eq 1 || ret=1
-lines=$(grep -c 'example.net has SOA record ns1.example.net. hostmaster.example.net. 1397051952 5 5 1814400 3600' host.out${n})
-test $lines -eq 1 || ret=1
-lines=$(grep -c 'example.net name server ns1.example.net.' host.out${n})
+# the answer is minimized to a single RRset (SOA or NS)
+lines=$(grep -c -e 'example.net has SOA record ns1.example.net. hostmaster.example.net. 1397051952 5 5 1814400 3600' -e 'example.net name server ns1.example.net.' host.out${n})
test $lines -eq 1 || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=$((status + ret))
diff --git a/bin/tests/system/nslookup/tests.sh b/bin/tests/system/nslookup/tests.sh
index 85dc1d72f0..ffae5f83bb 100644
--- a/bin/tests/system/nslookup/tests.sh
+++ b/bin/tests/system/nslookup/tests.sh
@@ -130,11 +130,8 @@ ret=0
$NSLOOKUP -port=${PORT} -type=ANY example.net 10.53.0.1 2>nslookup.err${n} >nslookup.out${n} || ret=1
lines=$(grep -c 'Address:.10\.53\.0\.1#'"${PORT}" nslookup.out${n})
test $lines -eq 1 || ret=1
-lines=$(grep -c 'origin = ns1\.example\.net' nslookup.out${n})
-test $lines -eq 1 || ret=1
-lines=$(grep -c 'mail addr = hostmaster\.example\.net' nslookup.out${n})
-test $lines -eq 1 || ret=1
-lines=$(grep -c 'nameserver = ns1\.example\.net.' nslookup.out${n})
+# the answer is minimized to a single RRset (SOA or NS)
+lines=$(grep -c -e 'origin = ns1\.example\.net' -e 'nameserver = ns1\.example\.net.' nslookup.out${n})
test $lines -eq 1 || ret=1
if [ $ret != 0 ]; then echo_i "failed"; fi
status=$((status + ret))
diff --git a/bin/tests/system/nsupdate/tests.sh b/bin/tests/system/nsupdate/tests.sh
index f42ddcbc10..8bacefc941 100755
--- a/bin/tests/system/nsupdate/tests.sh
+++ b/bin/tests/system/nsupdate/tests.sh
@@ -1243,10 +1243,12 @@ $DIG $DIGOPTS +tcp +noadd +nosea +nostat +noquest +nocomm +nocmd dnskey.test. \
$NSUPDATE update.in.$n
$DIG $DIGOPTS +tcp +noadd +nosea +nostat +noquest +nocomm +nocmd dnskey.test. \
- @10.53.0.3 any >dig.out.ns3.$n || ret=1
+ @10.53.0.3 dnskey >dig.out.ns3.$n || ret=1
+$DIG $DIGOPTS +tcp +noadd +nosea +nostat +noquest +nocomm +nocmd dnskey.test. \
+ @10.53.0.3 type65534 >dig.out.ns3.65534.$n || ret=1
grep "600.*DNSKEY" dig.out.ns3.$n >/dev/null || ret=1
-grep TYPE65534 dig.out.ns3.$n >/dev/null && ret=1
+grep TYPE65534 dig.out.ns3.65534.$n >/dev/null && ret=1
if test $ret -ne 0; then
echo_i "failed"
status=1
@@ -2173,16 +2175,19 @@ send
END
$DIG $DIGOPTS @10.53.0.6 \
+tcp +noadd +nosea +nostat +noquest +nocomm +nocmd \
- ANY -x 10.53.0.5 >dig.out.ns6.test$n || ret=1
+ A -x 10.53.0.5 >dig.out.ns6.a.test$n || ret=1
+$DIG $DIGOPTS @10.53.0.6 \
+ +tcp +noadd +nosea +nostat +noquest +nocomm +nocmd \
+ AAAA -x 10.53.0.5 >dig.out.ns6.aaaa.test$n || ret=1
nextpart ns6/named.run >nextpart.out.test$n
grep "attempt to add more records than permitted by policy" nextpart.out.test$n >/dev/null || ret=1
# the policy is 'grant * tcp-self . PTR(1) ANY(2) A;' so all the A
# records should have been added as there is no limit and the first 2
# of the AAAA records added as they match ANY(2).
-c1=$(awk '$4 == "A" { print }' dig.out.ns6.test$n | wc -l)
-c2=$(awk '$4 == "AAAA" { print }' dig.out.ns6.test$n | wc -l)
+c1=$(awk '$4 == "A" { print }' dig.out.ns6.a.test$n | wc -l)
+c2=$(awk '$4 == "AAAA" { print }' dig.out.ns6.aaaa.test$n | wc -l)
test "$c1" -eq 3 -a "$c2" -eq 2 || ret=1
-grep "::ffff:1.2.3.2" dig.out.ns6.test$n >/dev/null && ret=1
+grep "::ffff:1.2.3.2" dig.out.ns6.aaaa.test$n >/dev/null && ret=1
if test $ret -ne 0; then
echo_i "failed"
status=1
@@ -2644,10 +2649,12 @@ EOF
update add _xxx.self-srv-no-type.example.com 3600 IN TXT a txt record
send
EOF
- $DIG $DIGOPTS +tcp @10.53.0.7 _xxx.self-srv-no-type.example.com ANY >dig.out.ns7.test$n || ret=1
- grep "status: NOERROR" dig.out.ns7.test$n >/dev/null || ret=1
- grep '_xxx.self-srv-no-type.example.com.*SRV.*0 0 0 machine.example.com' dig.out.ns7.test$n >/dev/null || ret=1
- grep '_xxx.self-srv-no-type.example.com.*TXT.*"a" "txt" "record"' dig.out.ns7.test$n >/dev/null || ret=1
+ $DIG $DIGOPTS +tcp @10.53.0.7 _xxx.self-srv-no-type.example.com SRV >dig.out.ns7.srv.test$n || ret=1
+ grep "status: NOERROR" dig.out.ns7.srv.test$n >/dev/null || ret=1
+ grep '_xxx.self-srv-no-type.example.com.*SRV.*0 0 0 machine.example.com' dig.out.ns7.srv.test$n >/dev/null || ret=1
+ $DIG $DIGOPTS +tcp @10.53.0.7 _xxx.self-srv-no-type.example.com TXT >dig.out.ns7.txt.test$n || ret=1
+ grep "status: NOERROR" dig.out.ns7.txt.test$n >/dev/null || ret=1
+ grep '_xxx.self-srv-no-type.example.com.*TXT.*"a" "txt" "record"' dig.out.ns7.txt.test$n >/dev/null || ret=1
[ $ret = 0 ] || {
echo_i "failed"
status=1
diff --git a/bin/tests/system/redirect/tests.sh b/bin/tests/system/redirect/tests.sh
index 007b6f73de..e7d65a19b1 100644
--- a/bin/tests/system/redirect/tests.sh
+++ b/bin/tests/system/redirect/tests.sh
@@ -77,8 +77,8 @@ echo_i "checking ANY zone redirect works for nonexist ($n)"
ret=0
$DIG $DIGOPTS nonexist. @10.53.0.2 -b 10.53.0.2 any >dig.out.ns2.test$n || ret=1
grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1
-grep "100.100.100.1" dig.out.ns2.test$n >/dev/null || ret=1
-grep "2001:ffff:ffff::6464:6401" dig.out.ns2.test$n >/dev/null || ret=1
+# the answer is minimized to a single RRset
+grep -e "100.100.100.1" -e "2001:ffff:ffff::6464:6401" dig.out.ns2.test$n >/dev/null || ret=1
n=$((n + 1))
if [ $ret != 0 ]; then echo_i "failed"; fi
status=$((status + ret))
@@ -133,8 +133,8 @@ echo_i "checking ANY zone redirect works for signed nonexist, DO=0 ($n)"
ret=0
$DIG $DIGOPTS nonexist.signed. @10.53.0.2 -b 10.53.0.2 any >dig.out.ns2.test$n || ret=1
grep "status: NOERROR" dig.out.ns2.test$n >/dev/null || ret=1
-grep "100.100.100.1" dig.out.ns2.test$n >/dev/null || ret=1
-grep "2001:ffff:ffff::6464:6401" dig.out.ns2.test$n >/dev/null || ret=1
+# the answer is minimized to a single RRset
+grep -e "100.100.100.1" -e "2001:ffff:ffff::6464:6401" dig.out.ns2.test$n >/dev/null || ret=1
n=$((n + 1))
if [ $ret != 0 ]; then echo_i "failed"; fi
status=$((status + ret))
@@ -220,8 +220,8 @@ echo_i "checking ANY zone redirect works for nonexist authoritative ($n)"
ret=0
$DIG $DIGOPTS nonexist. @10.53.0.1 -b 10.53.0.1 any >dig.out.ns1.test$n || ret=1
grep "status: NOERROR" dig.out.ns1.test$n >/dev/null || ret=1
-grep "100.100.100.2" dig.out.ns1.test$n >/dev/null || ret=1
-grep "2001:ffff:ffff::6464:6402" dig.out.ns1.test$n >/dev/null || ret=1
+# the answer is minimized to a single RRset
+grep -e "100.100.100.2" -e "2001:ffff:ffff::6464:6402" dig.out.ns1.test$n >/dev/null || ret=1
n=$((n + 1))
if [ $ret != 0 ]; then echo_i "failed"; fi
status=$((status + ret))
@@ -276,8 +276,8 @@ echo_i "checking ANY zone redirect works for signed nonexist, DO=0 authoritative
ret=0
$DIG $DIGOPTS nonexist.signed. @10.53.0.1 -b 10.53.0.1 any >dig.out.ns1.test$n || ret=1
grep "status: NOERROR" dig.out.ns1.test$n >/dev/null || ret=1
-grep "100.100.100.2" dig.out.ns1.test$n >/dev/null || ret=1
-grep "2001:ffff:ffff::6464:6402" dig.out.ns1.test$n >/dev/null || ret=1
+# the answer is minimized to a single RRset
+grep -e "100.100.100.2" -e "2001:ffff:ffff::6464:6402" dig.out.ns1.test$n >/dev/null || ret=1
n=$((n + 1))
if [ $ret != 0 ]; then echo_i "failed"; fi
status=$((status + ret))
@@ -409,8 +409,8 @@ echo_i "checking ANY nxdomain-redirect works for nonexist ($n)"
ret=0
$DIG $DIGOPTS nonexist. @10.53.0.4 -b 10.53.0.2 any >dig.out.ns4.test$n || ret=1
grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1
-grep "100.100.100.1" dig.out.ns4.test$n >/dev/null || ret=1
-grep "2001:ffff:ffff::6464:6401" dig.out.ns4.test$n >/dev/null || ret=1
+# the answer is minimized to a single RRset
+grep -e "100.100.100.1" -e "2001:ffff:ffff::6464:6401" dig.out.ns4.test$n >/dev/null || ret=1
n=$((n + 1))
if [ $ret != 0 ]; then echo_i "failed"; fi
status=$((status + ret))
@@ -437,8 +437,8 @@ echo_i "checking ANY nxdomain-redirect works for signed nonexist, DO=0 ($n)"
ret=0
$DIG $DIGOPTS nonexist.signed. @10.53.0.4 -b 10.53.0.2 any >dig.out.ns4.test$n || ret=1
grep "status: NOERROR" dig.out.ns4.test$n >/dev/null || ret=1
-grep "100.100.100.1" dig.out.ns4.test$n >/dev/null || ret=1
-grep "2001:ffff:ffff::6464:6401" dig.out.ns4.test$n >/dev/null || ret=1
+# the answer is minimized to a single RRset
+grep -e "100.100.100.1" -e "2001:ffff:ffff::6464:6401" dig.out.ns4.test$n >/dev/null || ret=1
n=$((n + 1))
if [ $ret != 0 ]; then echo_i "failed"; fi
status=$((status + ret))
diff --git a/bin/tests/system/views/tests.sh b/bin/tests/system/views/tests.sh
index 90e4e10d04..f8d19281b1 100644
--- a/bin/tests/system/views/tests.sh
+++ b/bin/tests/system/views/tests.sh
@@ -29,10 +29,10 @@ RNDCCMD="$RNDC -c ../_common/rndc.conf -p ${CONTROLPORT} -s"
status=0
echo_i "fetching a.example from ns2's initial configuration"
-dig_with_opts a.example. @10.53.0.2 any >dig.out.ns2.1 || status=1
+dig_with_opts a.example. @10.53.0.2 a >dig.out.ns2.1 || status=1
echo_i "fetching a.example from ns3's initial configuration"
-dig_with_opts a.example. @10.53.0.3 any >dig.out.ns3.1 || status=1
+dig_with_opts a.example. @10.53.0.3 a >dig.out.ns3.1 || status=1
echo_i "copying in new configurations for ns2 and ns3"
rm -f ns2/named.conf ns3/named.conf ns2/example.db
@@ -58,13 +58,13 @@ if [ $ret != 0 ]; then echo_i "failed"; fi
status=$((status + ret))
echo_i "fetching a.example from ns2's 10.53.0.4, source address 10.53.0.4"
-dig_with_opts -b 10.53.0.4 a.example. @10.53.0.4 any >dig.out.ns4.2 || status=1
+dig_with_opts -b 10.53.0.4 a.example. @10.53.0.4 a >dig.out.ns4.2 || status=1
echo_i "fetching a.example from ns2's 10.53.0.2, source address 10.53.0.2"
-dig_with_opts -b 10.53.0.2 a.example. @10.53.0.2 any >dig.out.ns2.2 || status=1
+dig_with_opts -b 10.53.0.2 a.example. @10.53.0.2 a >dig.out.ns2.2 || status=1
echo_i "fetching a.example from ns3's 10.53.0.3, source address defaulted"
-dig_with_opts @10.53.0.3 a.example. any >dig.out.ns3.2 || status=1
+dig_with_opts @10.53.0.3 a.example. a >dig.out.ns3.2 || status=1
echo_i "comparing ns3's initial a.example to one from reconfigured 10.53.0.2"
digcomp dig.out.ns3.1 dig.out.ns2.2 || status=1
diff --git a/doc/arm/reference.rst b/doc/arm/reference.rst
index 43c8c66553..f0d19b4db5 100644
--- a/doc/arm/reference.rst
+++ b/doc/arm/reference.rst
@@ -2072,11 +2072,11 @@ Boolean Options
.. namedconf:statement:: minimal-any
:tags: query
- :short: Controls whether the server replies with only one of the RRsets for a query name, when generating a positive response to a query of type ANY over UDP.
+ :short: Controls whether the server replies with only one of the RRsets for a query name, when generating a positive response to a query of type ANY.
If set to ``yes``, the server replies with only one of
the RRsets for the query name, and its covering RRSIGs if any,
- when generating a positive response to a query of type ANY over UDP,
+ when generating a positive response to a query of type ANY,
instead of replying with all known RRsets for the name. Similarly, a
query for type RRSIG is answered with the RRSIG records covering
only one type. This can reduce the impact of some kinds of attack
diff --git a/lib/ns/query.c b/lib/ns/query.c
index f897cb6d18..9d48e43478 100644
--- a/lib/ns/query.c
+++ b/lib/ns/query.c
@@ -7428,7 +7428,6 @@ query_respond_any(query_ctx_t *qctx) {
dns_rdataset_disassociate(qctx->rdataset);
hidden = true;
} else if (qctx->view->minimal_any &&
- !qctx->client->inner.tcp &&
!qctx->client->inner.wantdnssec &&
qctx->qtype == dns_rdatatype_any &&
(dns_rdatatype_issig(qctx->rdataset->type)))
@@ -7437,7 +7436,6 @@ query_respond_any(query_ctx_t *qctx) {
"minimal-any skip signature");
dns_rdataset_disassociate(qctx->rdataset);
} else if (qctx->view->minimal_any &&
- !qctx->client->inner.tcp &&
onetype != dns_rdatatype_none &&
qctx->rdataset->type != onetype &&
qctx->rdataset->covers != onetype)
@@ -11452,9 +11450,7 @@ ns_query_start(ns_client_t *client, isc_nmhandle_t *handle) {
/*
* Maybe turn on minimal responses for ANY queries.
*/
- if (qtype == dns_rdatatype_any && client->inner.view->minimal_any &&
- !client->inner.tcp)
- {
+ if (qtype == dns_rdatatype_any && client->inner.view->minimal_any) {
client->query.noauthority = true;
client->query.noadditional = true;
}