diff --git a/CHANGES b/CHANGES index 0d50bf85e4..3647265892 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,6 @@ +4336. [bug] Don't emit records with zero ttl unless the records + were learnt with a zero ttl. [RT #41687] + 4335. [bug] zone->view could be detached too early. [RT #41942] 4333. [maint] L.ROOT-SERVERS.NET is now 199.7.83.42 and diff --git a/bin/tests/system/resolver/ns6/example.net.db.in b/bin/tests/system/resolver/ns6/example.net.db.in index c45de7fe9e..aac7483b0c 100644 --- a/bin/tests/system/resolver/ns6/example.net.db.in +++ b/bin/tests/system/resolver/ns6/example.net.db.in @@ -21,3 +21,5 @@ $TTL 600 ns IN A 10.53.0.6 mail IN A 10.53.0.6 fetch 10 IN TXT A short ttl +non-zero 10 IN TXT A short ttl +zero 0 IN TXT A zero ttl diff --git a/bin/tests/system/resolver/ns7/named1.conf b/bin/tests/system/resolver/ns7/named1.conf index 974b57cbf8..1955aa509b 100644 --- a/bin/tests/system/resolver/ns7/named1.conf +++ b/bin/tests/system/resolver/ns7/named1.conf @@ -29,6 +29,10 @@ options { recursion yes; empty-zones-enable yes; disable-empty-zone 20.172.in-addr.arpa; + /* + * I: check prefetch disabled + * I: check zero ttl not returned + */ prefetch 0; }; diff --git a/bin/tests/system/resolver/ns7/named2.conf b/bin/tests/system/resolver/ns7/named2.conf index ab6bed3715..a433a4741c 100644 --- a/bin/tests/system/resolver/ns7/named2.conf +++ b/bin/tests/system/resolver/ns7/named2.conf @@ -29,6 +29,10 @@ options { recursion yes; empty-zones-enable yes; disable-empty-zone 20.172.in-addr.arpa; + /* + * I: check prefetch disabled + * I: check zero ttl not returned + */ prefetch 0; }; diff --git a/bin/tests/system/resolver/tests.sh b/bin/tests/system/resolver/tests.sh index bd7540cb9f..91fd7a23af 100755 --- a/bin/tests/system/resolver/tests.sh +++ b/bin/tests/system/resolver/tests.sh @@ -435,24 +435,24 @@ n=`expr $n + 1` echo "I:check prefetch disabled (${n})" ret=0 $DIG @10.53.0.7 -p 5300 fetch.example.net txt > dig.out.1.${n} || ret=1 -ttl1=`awk '/"A" "short" "ttl"/ { print $2 - 1 }' dig.out.1.${n}` +ttl1=`awk '/"A" "short" "ttl"/ { print $2 - 2 }' dig.out.1.${n}` # sleep so we are in expire range sleep ${ttl1:-0} -# look for zero ttl, allow for one miss at getting zero ttl +# look for ttl = 1, allow for one miss at getting zero ttl zerotonine="0 1 2 3 4 5 6 7 8 9" for i in $zerotonine $zerotonine $zerotonine $zerotonine do $DIG @10.53.0.7 -p 5300 fetch.example.net txt > dig.out.2.${n} || ret=1 ttl2=`awk '/"A" "short" "ttl"/ { print $2 }' dig.out.2.${n}` - test ${ttl2:-1} -eq 0 && break + test ${ttl2:-2} -eq 1 && break $PERL -e 'select(undef, undef, undef, 0.05);' done -test ${ttl2:-1} -eq 0 || ret=1 +test ${ttl2:-2} -eq 1 || ret=1 # delay so that any prefetched record will have a lower ttl than expected sleep 3 # check that prefetch has not occured $DIG @10.53.0.7 -p 5300 fetch.example.net txt > dig.out.3.${n} || ret=1 -ttl=`awk '/"A" "short" "ttl"/ { print $2 - 1 }' dig.out.3.${n}` +ttl=`awk '/"A" "short" "ttl"/ { print $2 - 2 }' dig.out.3.${n}` test ${ttl:-0} -eq ${ttl1:-1} || ret=1 if [ $ret != 0 ]; then echo "I:failed"; fi status=`expr $status + $ret` @@ -629,5 +629,37 @@ grep "status: NXDOMAIN" dig.out.ns5.test${n} > /dev/null || ret=1 if [ $ret != 0 ]; then echo "I:failed"; fi status=`expr $status + $ret` +n=`expr $n + 1` +echo "I:check zero ttl not returned for learnt non zero ttl records (${n})" +ret=0 +# use prefetch disabled server +$DIG @10.53.0.7 -p 5300 non-zero.example.net txt > dig.out.1.${n} || ret=1 +ttl1=`awk '/"A" "short" "ttl"/ { print $2 - 2 }' dig.out.1.${n}` +# sleep so we are in expire range +sleep ${ttl1:-0} +# look for ttl = 1, allow for one miss at getting zero ttl +zerotonine="0 1 2 3 4 5 6 7 8 9" +zerotonine="$zerotonine $zerotonine $zerotonine" +for i in $zerotonine $zerotonine $zerotonine $zerotonine +do + $DIG @10.53.0.7 -p 5300 non-zero.example.net txt > dig.out.2.${n} || ret=1 + ttl2=`awk '/"A" "short" "ttl"/ { print $2 }' dig.out.2.${n}` + test ${ttl2:-1} -eq 0 && break + test ${ttl2:-1} -ge ${ttl1:-0} && break + $PERL -e 'select(undef, undef, undef, 0.05);' +done +test ${ttl2:-1} -eq 0 && ret=1 +test ${ttl2:-1} -ge ${ttl1:-0} || break +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +n=`expr $n + 1` +echo "I:check zero ttl is returned for learnt zero ttl records (${n})" +ret=0 +$DIG @10.53.0.7 -p 5300 zero.example.net txt > dig.out.1.${n} || ret=1 +ttl=`awk '/"A" "zero" "ttl"/ { print $2 }' dig.out.1.${n}` +test ${ttl:-1} -eq 0 || ret=1 +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` echo "I:exit status: $status" exit $status diff --git a/lib/dns/rbtdb.c b/lib/dns/rbtdb.c index d37b1148a1..aeca609d64 100644 --- a/lib/dns/rbtdb.c +++ b/lib/dns/rbtdb.c @@ -467,6 +467,8 @@ typedef ISC_LIST(dns_rbtnode_t) rbtnodelist_t; #define RDATASET_ATTR_OPTOUT 0x0080 #define RDATASET_ATTR_NEGATIVE 0x0100 #define RDATASET_ATTR_PREFETCH 0x0200 +#define RDATASET_ATTR_CASESET 0x0400 +#define RDATASET_ATTR_ZEROTTL 0x0800 typedef struct acache_cbarg { dns_rdatasetadditional_t type; @@ -511,6 +513,10 @@ struct acachectl { (((header)->attributes & RDATASET_ATTR_NEGATIVE) != 0) #define PREFETCH(header) \ (((header)->attributes & RDATASET_ATTR_PREFETCH) != 0) +#define CASESET(header) \ + (((header)->attributes & RDATASET_ATTR_CASESET) != 0) +#define ZEROTTL(header) \ + (((header)->attributes & RDATASET_ATTR_ZEROTTL) != 0) #define DEFAULT_NODE_LOCK_COUNT 7 /*%< Should be prime. */ @@ -4503,7 +4509,8 @@ check_stale_rdataset(dns_rbtnode_t *node, rdatasetheader_t *header, UNUSED(lock); #endif - if (header->rdh_ttl < search->now) { + if (header->rdh_ttl < search->now || + (header->rdh_ttl == search->now && !ZEROTTL(header))) { /* * This rdataset is stale. If no one else is using the * node, we can clean it up right now, otherwise we mark @@ -6544,6 +6551,8 @@ addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, newheader->type = RBTDB_RDATATYPE_VALUE(rdataset->type, rdataset->covers); newheader->attributes = 0; + if (rdataset->ttl == 0U) + newheader->attributes |= RDATASET_ATTR_ZEROTTL; newheader->noqname = NULL; newheader->closest = NULL; newheader->count = init_count++; diff --git a/lib/dns/zone.c b/lib/dns/zone.c index d1d27e25ad..d6ac084a69 100644 --- a/lib/dns/zone.c +++ b/lib/dns/zone.c @@ -3638,7 +3638,8 @@ compute_tag(dns_name_t *name, dns_rdata_dnskey_t *dnskey, isc_mem_t *mctx, */ static void trust_key(dns_zone_t *zone, dns_name_t *keyname, - dns_rdata_dnskey_t *dnskey, isc_mem_t *mctx) { + dns_rdata_dnskey_t *dnskey, isc_mem_t *mctx) +{ isc_result_t result; dns_rdata_t rdata = DNS_RDATA_INIT; unsigned char data[4096];