From 4a61eae6514bfde56f8801ef66f27a8d462bd164 Mon Sep 17 00:00:00 2001 From: Mark Andrews Date: Mon, 29 Jun 2015 15:48:41 +1000 Subject: [PATCH] 4147. [bug] Filter-aaaa / filter-aaaa-on-v4 / filter-aaaa-on-v6 was returning referrals rather than nodata responses when the AAAA records were filtered. [RT #39843] --- CHANGES | 4 ++++ bin/tests/system/filter-aaaa/tests.sh | 19 +++++++++++++++++++ lib/dns/message.c | 21 +++++++++++++++++---- 3 files changed, 40 insertions(+), 4 deletions(-) diff --git a/CHANGES b/CHANGES index 38ae0d8f3b..46d8df4d30 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,7 @@ +4147. [bug] Filter-aaaa / filter-aaaa-on-v4 / filter-aaaa-on-v6 + was returning referrals rather than nodata responses + when the AAAA records were filtered. [RT #39843] + 4146. [bug] Address reference leak that could prevent a clean shutdown. [RT #37125] diff --git a/bin/tests/system/filter-aaaa/tests.sh b/bin/tests/system/filter-aaaa/tests.sh index 3a7443c994..6486981840 100644 --- a/bin/tests/system/filter-aaaa/tests.sh +++ b/bin/tests/system/filter-aaaa/tests.sh @@ -55,6 +55,7 @@ n=`expr $n + 1` echo "I:checking that AAAA is returned when only AAAA record exists, signed ($n)" ret=0 $DIG $DIGOPTS aaaa aaaa-only.signed -b 10.53.0.1 @10.53.0.1 > dig.out.ns1.test$n || ret=1 +grep "AUTHORITY: 1," dig.out.ns1.test$n > /dev/null || ret=1 grep ::2 dig.out.ns1.test$n > /dev/null || ret=1 if [ $ret != 0 ]; then echo "I:failed"; fi status=`expr $status + $ret` @@ -63,6 +64,7 @@ n=`expr $n + 1` echo "I:checking that AAAA is returned when only AAAA record exists, unsigned ($n)" ret=0 $DIG $DIGOPTS aaaa aaaa-only.unsigned -b 10.53.0.1 @10.53.0.1 > dig.out.ns1.test$n || ret=1 +grep "AUTHORITY: 1," dig.out.ns1.test$n > /dev/null || ret=1 grep ::5 dig.out.ns1.test$n > /dev/null || ret=1 if [ $ret != 0 ]; then echo "I:failed"; fi status=`expr $status + $ret` @@ -72,6 +74,7 @@ echo "I:checking that NODATA/NOERROR is returned when both AAAA and A records ex ret=0 $DIG $DIGOPTS aaaa dual.signed -b 10.53.0.1 @10.53.0.1 > dig.out.ns1.test$n || ret=1 grep "ANSWER: 0" dig.out.ns1.test$n > /dev/null || ret=1 +grep "AUTHORITY: 0" dig.out.ns1.test$n > /dev/null || ret=1 grep "status: NOERROR" dig.out.ns1.test$n > /dev/null || ret=1 if [ $ret != 0 ]; then echo "I:failed"; fi status=`expr $status + $ret` @@ -81,6 +84,7 @@ echo "I:checking that NODATA/NOERROR is returned when both AAAA and A records ex ret=0 $DIG $DIGOPTS aaaa dual.unsigned -b 10.53.0.1 @10.53.0.1 > dig.out.ns1.test$n || ret=1 grep "ANSWER: 0" dig.out.ns1.test$n > /dev/null || ret=1 +grep "AUTHORITY: 0" dig.out.ns1.test$n > /dev/null || ret=1 grep "status: NOERROR" dig.out.ns1.test$n > /dev/null || ret=1 if [ $ret != 0 ]; then echo "I:failed"; fi status=`expr $status + $ret` @@ -89,6 +93,7 @@ n=`expr $n + 1` echo "I:checking that AAAA is returned when both AAAA and A records exist, signed and DO set ($n)" ret=0 $DIG $DIGOPTS aaaa dual.signed +dnssec -b 10.53.0.1 @10.53.0.1 > dig.out.ns1.test$n || ret=1 +grep "AUTHORITY: 2," dig.out.ns1.test$n > /dev/null || ret=1 grep ::3 dig.out.ns1.test$n > /dev/null || ret=1 if [ $ret != 0 ]; then echo "I:failed"; fi status=`expr $status + $ret` @@ -98,6 +103,7 @@ echo "I:checking that NODATA/NOERROR is returned when both AAAA and A records ex ret=0 $DIG $DIGOPTS aaaa dual.unsigned -b 10.53.0.1 @10.53.0.1 > dig.out.ns1.test$n || ret=1 grep "ANSWER: 0" dig.out.ns1.test$n > /dev/null || ret=1 +grep "AUTHORITY: 0," dig.out.ns1.test$n > /dev/null || ret=1 grep "status: NOERROR" dig.out.ns1.test$n > /dev/null || ret=1 if [ $ret != 0 ]; then echo "I:failed"; fi status=`expr $status + $ret` @@ -107,6 +113,7 @@ echo "I:checking that AAAA is returned when both AAAA and A records exist and qu ret=0 $DIG $DIGOPTS aaaa dual.unsigned -b 10.53.0.2 @10.53.0.1 > dig.out.ns1.test$n || ret=1 grep "status: NOERROR" dig.out.ns1.test$n > /dev/null || ret=1 +grep "AUTHORITY: 1," dig.out.ns1.test$n > /dev/null || ret=1 grep ::6 dig.out.ns1.test$n > /dev/null || ret=1 if [ $ret != 0 ]; then echo "I:failed"; fi status=`expr $status + $ret` @@ -116,6 +123,7 @@ echo "I:checking that A and not AAAA is returned when both AAAA and A records ex ret=0 $DIG $DIGOPTS any dual.signed -b 10.53.0.1 @10.53.0.1 > dig.out.ns1.test$n || ret=1 grep "status: NOERROR" dig.out.ns1.test$n > /dev/null || ret=1 +grep "AUTHORITY: 0," dig.out.ns1.test$n > /dev/null || ret=1 grep "1.0.0.3" dig.out.ns1.test$n > /dev/null || ret=1 grep "::3" dig.out.ns1.test$n > /dev/null && ret=1 if [ $ret != 0 ]; then echo "I:failed"; fi @@ -126,6 +134,7 @@ echo "I:checking that A and not AAAA is returned when both AAAA and A records ex ret=0 $DIG $DIGOPTS any dual.unsigned -b 10.53.0.1 @10.53.0.1 > dig.out.ns1.test$n || ret=1 grep "status: NOERROR" dig.out.ns1.test$n > /dev/null || ret=1 +grep "AUTHORITY: 0," dig.out.ns1.test$n > /dev/null || ret=1 grep "1.0.0.6" dig.out.ns1.test$n > /dev/null || ret=1 grep "::6" dig.out.ns1.test$n > /dev/null && ret=1 if [ $ret != 0 ]; then echo "I:failed"; fi @@ -136,6 +145,7 @@ echo "I:checking that both A and AAAA are returned when both AAAA and A records ret=0 $DIG $DIGOPTS any dual.signed +dnssec -b 10.53.0.1 @10.53.0.1 > dig.out.ns1.test$n || ret=1 grep "status: NOERROR" dig.out.ns1.test$n > /dev/null || ret=1 +grep "AUTHORITY: 2," dig.out.ns1.test$n > /dev/null || ret=1 grep ::3 dig.out.ns1.test$n > /dev/null || ret=1 grep "1.0.0.3" dig.out.ns1.test$n > /dev/null || ret=1 if [ $ret != 0 ]; then echo "I:failed"; fi @@ -146,6 +156,7 @@ echo "I:checking that A and not AAAA is returned when both AAAA and A records ex ret=0 $DIG $DIGOPTS any dual.unsigned +dnssec -b 10.53.0.1 @10.53.0.1 > dig.out.ns1.test$n || ret=1 grep "status: NOERROR" dig.out.ns1.test$n > /dev/null || ret=1 +grep "AUTHORITY: 0," dig.out.ns1.test$n > /dev/null || ret=1 grep "1.0.0.6" dig.out.ns1.test$n > /dev/null || ret=1 grep "::6" dig.out.ns1.test$n > /dev/null && ret=1 if [ $ret != 0 ]; then echo "I:failed"; fi @@ -156,6 +167,7 @@ echo "I:checking that both A and AAAA are returned when both AAAA and A records ret=0 $DIG $DIGOPTS any dual.unsigned -b 10.53.0.2 @10.53.0.1 > dig.out.ns1.test$n || ret=1 grep "status: NOERROR" dig.out.ns1.test$n > /dev/null || ret=1 +grep "AUTHORITY: 1," dig.out.ns1.test$n > /dev/null || ret=1 grep 1.0.0.6 dig.out.ns1.test$n > /dev/null || ret=1 grep ::6 dig.out.ns1.test$n > /dev/null || ret=1 if [ $ret != 0 ]; then echo "I:failed"; fi @@ -168,6 +180,7 @@ then ret=0 $DIG $DIGOPTS aaaa dual.unsigned -b fd92:7065:b8e:ffff::1 @fd92:7065:b8e:ffff::1 > dig.out.ns1.test$n || ret=1 grep 2001:db8::6 dig.out.ns1.test$n > /dev/null || ret=1 +grep "AUTHORITY: 1," dig.out.ns1.test$n > /dev/null || ret=1 if [ $ret != 0 ]; then echo "I:failed"; fi status=`expr $status + $ret` else @@ -179,6 +192,7 @@ echo "I:checking that AAAA is omitted from additional section, qtype=NS ($n)" ret=0 $DIG $DIGOPTS +add ns unsigned -b 10.53.0.1 @10.53.0.1 > dig.out.ns1.test$n || ret=1 grep AAAA dig.out.ns1.test$n > /dev/null 2>&1 && ret=1 +grep "ANSWER: 1," dig.out.ns1.test$n > /dev/null || ret=1 grep "ADDITIONAL: 2" dig.out.ns1.test$n > /dev/null 2>&1 || ret=1 if [ $ret != 0 ]; then echo "I:failed"; fi status=`expr $status + $ret` @@ -196,6 +210,7 @@ echo "I:checking that AAAA is included in additional section, qtype=MX, signed ( ret=0 $DIG $DIGOPTS +add +dnssec mx signed -b 10.53.0.1 @10.53.0.1 > dig.out.ns1.test$n || ret=1 grep "^mx.signed.*AAAA" dig.out.ns1.test$n > /dev/null 2>&1 || ret=1 +grep "AUTHORITY: 2," dig.out.ns1.test$n > /dev/null || ret=1 if [ $ret != 0 ]; then echo "I:failed"; fi status=`expr $status + $ret` @@ -206,6 +221,7 @@ then ret=0 $DIG $DIGOPTS +add +dnssec mx unsigned -b fd92:7065:b8e:ffff::1 @fd92:7065:b8e:ffff::1 > dig.out.ns1.test$n || ret=1 grep "^mx.unsigned.*AAAA" dig.out.ns1.test$n > /dev/null 2>&1 || ret=1 +grep "AUTHORITY: 1," dig.out.ns1.test$n > /dev/null || ret=1 if [ $ret != 0 ]; then echo "I:failed"; fi status=`expr $status + $ret` else @@ -222,6 +238,7 @@ n=`expr $n + 1` echo "I:checking that AAAA is returned when only AAAA record exists, signed with break-dnssec ($n)" ret=0 $DIG $DIGOPTS aaaa aaaa-only.signed -b 10.53.0.4 @10.53.0.4 > dig.out.ns4.test$n || ret=1 +grep "AUTHORITY: 1," dig.out.ns4.test$n > /dev/null || ret=1 grep ::2 dig.out.ns4.test$n > /dev/null || ret=1 if [ $ret != 0 ]; then echo "I:failed"; fi status=`expr $status + $ret` @@ -230,6 +247,7 @@ n=`expr $n + 1` echo "I:checking that AAAA is returned when only AAAA record exists, unsigned with break-dnssec ($n)" ret=0 $DIG $DIGOPTS aaaa aaaa-only.unsigned -b 10.53.0.4 @10.53.0.4 > dig.out.ns4.test$n || ret=1 +grep "AUTHORITY: 1," dig.out.ns4.test$n > /dev/null || ret=1 grep ::5 dig.out.ns4.test$n > /dev/null || ret=1 if [ $ret != 0 ]; then echo "I:failed"; fi status=`expr $status + $ret` @@ -239,6 +257,7 @@ echo "I:checking that NODATA/NOERROR is returned when both AAAA and A records ex ret=0 $DIG $DIGOPTS aaaa dual.signed -b 10.53.0.4 @10.53.0.4 > dig.out.ns4.test$n || ret=1 grep "ANSWER: 0" dig.out.ns4.test$n > /dev/null || ret=1 +grep "AUTHORITY: 0," dig.out.ns4.test$n > /dev/null || ret=1 grep "status: NOERROR" dig.out.ns4.test$n > /dev/null || ret=1 if [ $ret != 0 ]; then echo "I:failed"; fi status=`expr $status + $ret` diff --git a/lib/dns/message.c b/lib/dns/message.c index 6ff8d75828..5a09059075 100644 --- a/lib/dns/message.c +++ b/lib/dns/message.c @@ -1836,9 +1836,19 @@ wrong_priority(dns_rdataset_t *rds, int pass, dns_rdatatype_t preferred_glue) { * Decide whether to not answer with an AAAA record and its RRSIG */ static inline isc_boolean_t -norender_rdataset(const dns_rdataset_t *rdataset, unsigned int options) +norender_rdataset(const dns_rdataset_t *rdataset, unsigned int options, + dns_section_t sectionid) { + if (sectionid == DNS_SECTION_QUESTION) + return (ISC_FALSE); + switch (rdataset->type) { + case dns_rdatatype_ns: + if ((options & DNS_MESSAGERENDER_FILTER_AAAA) == 0 || + sectionid != DNS_SECTION_AUTHORITY) + return (ISC_FALSE); + break; + case dns_rdatatype_aaaa: if ((options & DNS_MESSAGERENDER_FILTER_AAAA) == 0) return (ISC_FALSE); @@ -1846,7 +1856,11 @@ norender_rdataset(const dns_rdataset_t *rdataset, unsigned int options) case dns_rdatatype_rrsig: if ((options & DNS_MESSAGERENDER_FILTER_AAAA) == 0 || - rdataset->covers != dns_rdatatype_aaaa) + (rdataset->covers != dns_rdatatype_ns && + rdataset->covers != dns_rdatatype_aaaa)) + return (ISC_FALSE); + if ((rdataset->covers == dns_rdatatype_ns) && + (sectionid != DNS_SECTION_AUTHORITY)) return (ISC_FALSE); break; @@ -1994,8 +2008,7 @@ dns_message_rendersection(dns_message_t *msg, dns_section_t sectionid, * not doing DNSSEC or are breaking DNSSEC. * Say so in the AD bit if we break DNSSEC. */ - if (norender_rdataset(rdataset, options) && - sectionid != DNS_SECTION_QUESTION) { + if (norender_rdataset(rdataset, options, sectionid)) { if (sectionid == DNS_SECTION_ANSWER || sectionid == DNS_SECTION_AUTHORITY) msg->flags &= ~DNS_MESSAGEFLAG_AD;