From: Mark Andrews Date: Wed, 22 Jun 2016 05:26:38 +0000 (+1000) Subject: 4387. [bug] Change 4336 was not complete leading to SERVFAIL X-Git-Tag: v9.9.9-P2~16 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=5cb9080313650f8588662f07780f7af3dfb0f0fc;p=thirdparty%2Fbind9.git 4387. [bug] Change 4336 was not complete leading to SERVFAIL being return as NS records expired. [RT #42683] (cherry picked from commit b56bd9b59f590ade778ac6621fb5bede4001d8ae) (cherry picked from commit aa630523173f5d0267d97e8e9e5016f65ce006db) --- diff --git a/CHANGES b/CHANGES index bcc57205377..359b496dd08 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,6 @@ +4387. [bug] Change 4336 was not complete leading to SERVFAIL + being return as NS records expired. [RT #42683] + --- 9.9.9-P1 released --- 4366. [bug] Address race condition when updating rbtnode bit diff --git a/bin/tests/system/zero/ns1/root.db b/bin/tests/system/zero/ns1/root.db index 69aca86fb85..c07a41751c0 100644 --- a/bin/tests/system/zero/ns1/root.db +++ b/bin/tests/system/zero/ns1/root.db @@ -22,3 +22,5 @@ example. NS ns2.example. ns2.example. A 10.53.0.2 example. NS ns4.example. ns4.example. A 10.53.0.4 +tld. NS ns2.tld. +ns2.tld. A 10.53.0.2 diff --git a/bin/tests/system/zero/ns2/named.conf b/bin/tests/system/zero/ns2/named.conf index 86673b21887..c1d2e6a6471 100644 --- a/bin/tests/system/zero/ns2/named.conf +++ b/bin/tests/system/zero/ns2/named.conf @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2013, 2016 Internet Systems Consortium, Inc. ("ISC") * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -35,3 +35,7 @@ zone "example" { file "example.db"; }; +zone "tld" { + type master; + file "tld.db"; +}; diff --git a/bin/tests/system/zero/ns2/tld.db b/bin/tests/system/zero/ns2/tld.db new file mode 100644 index 00000000000..f5e987ea8a4 --- /dev/null +++ b/bin/tests/system/zero/ns2/tld.db @@ -0,0 +1,23 @@ +; Copyright (C) 2016 Internet Systems Consortium, Inc. ("ISC") +; +; Permission to use, copy, modify, and/or distribute this software for any +; purpose with or without fee is hereby granted, provided that the above +; copyright notice and this permission notice appear in all copies. +; +; THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH +; REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +; AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, +; INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +; LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE +; OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +; PERFORMANCE OF THIS SOFTWARE. + +$TTL 1 +@ 300 SOA ns2.tld. hostmaster.ns2.tld. 0 1 1 1 1 +@ 300 NS ns2.tld. +ns2 300 A 10.53.0.2 +; +; The TTL of these delegation records needs to 1. +; +one 1 NS ns4.one.tld. +ns4.one 1 A 10.53.0.4 diff --git a/bin/tests/system/zero/ns4/named.conf b/bin/tests/system/zero/ns4/named.conf index bceeb231175..3cf95a59b25 100644 --- a/bin/tests/system/zero/ns4/named.conf +++ b/bin/tests/system/zero/ns4/named.conf @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2013, 2016 Internet Systems Consortium, Inc. ("ISC") * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -36,3 +36,7 @@ zone "example" { file "example.bk"; }; +zone "one.tld" { + type master; + file "one.tld.db"; +}; diff --git a/bin/tests/system/zero/ns4/one.tld.db b/bin/tests/system/zero/ns4/one.tld.db new file mode 100644 index 00000000000..94423094e13 --- /dev/null +++ b/bin/tests/system/zero/ns4/one.tld.db @@ -0,0 +1,20 @@ +; Copyright (C) 2016 Internet Systems Consortium, Inc. ("ISC") +; +; Permission to use, copy, modify, and/or distribute this software for any +; purpose with or without fee is hereby granted, provided that the above +; copyright notice and this permission notice appear in all copies. +; +; THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH +; REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +; AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, +; INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +; LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE +; OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +; PERFORMANCE OF THIS SOFTWARE. + +$TTL 1 +; The TTL of all these records needs to be 1. +@ 1 SOA ns4.one.tld. hostmaster.ns4.tld. 0 1 1 1 1 +@ 1 NS ns4.one.tld. +ns4 1 A 10.53.0.4 +www 1 A 10.53.0.4 diff --git a/bin/tests/system/zero/tests.sh b/bin/tests/system/zero/tests.sh index 15c2906a928..703bd43fb28 100644 --- a/bin/tests/system/zero/tests.sh +++ b/bin/tests/system/zero/tests.sh @@ -16,7 +16,10 @@ SYSTEMTESTTOP=.. . $SYSTEMTESTTOP/conf.sh status=0 -echo "I:check lookups against zero TTL records" +n=0 + +n=`expr $n + 1` +echo "I:check lookups against TTL=0 records ($n)" i=0 passes=10 $DIG -p 5300 @10.53.0.2 axfr example | @@ -24,22 +27,49 @@ awk '$2 == "0" { print "-q", $1, $4; print "-q", "zzz"$1, $4;}' > query.list while [ $i -lt $passes ] do ret=0 - $DIG -p 5300 @10.53.0.3 -f query.list > dig.out$i.1 & - $DIG -p 5300 @10.53.0.3 -f query.list > dig.out$i.2 & - $DIG -p 5300 @10.53.0.3 -f query.list > dig.out$i.3 & - $DIG -p 5300 @10.53.0.3 -f query.list > dig.out$i.4 & - $DIG -p 5300 @10.53.0.3 -f query.list > dig.out$i.5 & - $DIG -p 5300 @10.53.0.3 -f query.list > dig.out$i.6 & + $DIG -p 5300 @10.53.0.3 -f query.list > dig.out$i.1.test$n & + $DIG -p 5300 @10.53.0.3 -f query.list > dig.out$i.2.test$n & + $DIG -p 5300 @10.53.0.3 -f query.list > dig.out$i.3.test$n & + $DIG -p 5300 @10.53.0.3 -f query.list > dig.out$i.4.test$n & + $DIG -p 5300 @10.53.0.3 -f query.list > dig.out$i.5.test$n & + $DIG -p 5300 @10.53.0.3 -f query.list > dig.out$i.6.test$n & wait - grep "status: SERVFAIL" dig.out$i.1 && ret=1 - grep "status: SERVFAIL" dig.out$i.2 && ret=1 - grep "status: SERVFAIL" dig.out$i.3 && ret=1 - grep "status: SERVFAIL" dig.out$i.5 && ret=1 - grep "status: SERVFAIL" dig.out$i.6 && ret=1 - grep "status: SERVFAIL" dig.out$i.6 && ret=1 + grep "status: SERVFAIL" dig.out$i.1.test$n && ret=1 + grep "status: SERVFAIL" dig.out$i.2.test$n && ret=1 + grep "status: SERVFAIL" dig.out$i.3.test$n && ret=1 + grep "status: SERVFAIL" dig.out$i.4.test$n && ret=1 + grep "status: SERVFAIL" dig.out$i.5.test$n && ret=1 + grep "status: SERVFAIL" dig.out$i.6.test$n && ret=1 + [ $ret = 1 ] && break + i=`expr $i + 1` + echo "I: successfully completed pass $i of $passes" +done +if [ $ret != 0 ]; then echo "I:failed"; fi +status=`expr $status + $ret` + +n=`expr $n + 1` +echo "I:check lookups against TTL=1 records ($n)" +i=0 +passes=10 +while [ $i -lt $passes ] +do + ret=0 + $DIG -p 5300 @10.53.0.3 www.one.tld > dig.out$i.1.test$n + $DIG -p 5300 @10.53.0.3 www.one.tld > dig.out$i.2.test$n + $DIG -p 5300 @10.53.0.3 www.one.tld > dig.out$i.3.test$n + $DIG -p 5300 @10.53.0.3 www.one.tld > dig.out$i.4.test$n + $DIG -p 5300 @10.53.0.3 www.one.tld > dig.out$i.5.test$n + $DIG -p 5300 @10.53.0.3 www.one.tld > dig.out$i.6.test$n + grep "status: SERVFAIL" dig.out$i.1.test$n && ret=1 + grep "status: SERVFAIL" dig.out$i.2.test$n && ret=1 + grep "status: SERVFAIL" dig.out$i.3.test$n && ret=1 + grep "status: SERVFAIL" dig.out$i.4.test$n && ret=1 + grep "status: SERVFAIL" dig.out$i.5.test$n && ret=1 + grep "status: SERVFAIL" dig.out$i.6.test$n && ret=1 [ $ret = 1 ] && break i=`expr $i + 1` echo "I: successfully completed pass $i of $passes" + $PERL -e 'select(undef, undef, undef, 0.3);' done if [ $ret != 0 ]; then echo "I:failed"; fi status=`expr $status + $ret` diff --git a/lib/dns/rbtdb.c b/lib/dns/rbtdb.c index 80713da20dd..1912c8478d2 100644 --- a/lib/dns/rbtdb.c +++ b/lib/dns/rbtdb.c @@ -451,6 +451,10 @@ struct acachectl { #define ZEROTTL(header) \ (((header)->attributes & RDATASET_ATTR_ZEROTTL) != 0) +#define ACTIVE(header, now) \ + (((header)->rdh_ttl > (now)) || \ + ((header)->rdh_ttl == (now) && ZEROTTL(header))) + #define DEFAULT_NODE_LOCK_COUNT 7 /*%< Should be prime. */ /*% @@ -4334,8 +4338,7 @@ cache_zonecut_callback(dns_rbtnode_t *node, dns_name_t *name, void *arg) { header_prev = NULL; for (header = node->data; header != NULL; header = header_next) { header_next = header->next; - if (header->rdh_ttl < search->now || - (header->rdh_ttl == search->now && !ZEROTTL(header))) { + if (!ACTIVE(header, search->now)) { /* * This rdataset is stale. If no one else is * using the node, we can clean it up right @@ -4459,8 +4462,7 @@ find_deepest_zonecut(rbtdb_search_t *search, dns_rbtnode_t *node, header != NULL; header = header_next) { header_next = header->next; - if (header->rdh_ttl < search->now || - (header->rdh_ttl == search->now && !ZEROTTL(header))) { + if (!ACTIVE(header, search->now)) { /* * This rdataset is stale. If no one else is * using the node, we can clean it up right @@ -4637,8 +4639,7 @@ find_coveringnsec(rbtdb_search_t *search, dns_dbnode_t **nodep, header != NULL; header = header_next) { header_next = header->next; - if (header->rdh_ttl < now || - (header->rdh_ttl == now && !ZEROTTL(header))) { + if (!ACTIVE(header, now)) { /* * This rdataset is stale. If no one else is * using the node, we can clean it up right @@ -5045,8 +5046,7 @@ cache_find(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version, header_prev = NULL; for (header = node->data; header != NULL; header = header_next) { header_next = header->next; - if (header->rdh_ttl < now || - (header->rdh_ttl == now && !ZEROTTL(header))) { + if (!ACTIVE(header, now)) { /* * This rdataset is stale. If no one else is using the * node, we can clean it up right now, otherwise we @@ -5353,8 +5353,7 @@ cache_findzonecut(dns_db_t *db, dns_name_t *name, unsigned int options, header_prev = NULL; for (header = node->data; header != NULL; header = header_next) { header_next = header->next; - if (header->rdh_ttl < now || - (header->rdh_ttl == now && !ZEROTTL(header))) { + if (!ACTIVE(header, now)) { /* * This rdataset is stale. If no one else is using the * node, we can clean it up right now, otherwise we @@ -5843,8 +5842,7 @@ cache_findrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, for (header = rbtnode->data; header != NULL; header = header_next) { header_next = header->next; - if (header->rdh_ttl < now || - (header->rdh_ttl == now && !ZEROTTL(header))) { + if (!ACTIVE(header, now)) { if ((header->rdh_ttl < now - RBTDB_VIRTUAL) && (locktype == isc_rwlocktype_write || NODE_TRYUPGRADE(lock) == ISC_R_SUCCESS)) { @@ -6169,7 +6167,7 @@ add32(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode, rbtdb_version_t *rbtversion, } } if (topheader != NULL && EXISTS(topheader) && - topheader->rdh_ttl >= now) { + ACTIVE(topheader, now)) { /* * Found one. */ @@ -6235,7 +6233,7 @@ add32(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode, rbtdb_version_t *rbtversion, * has no effect, provided that the cache data isn't stale. */ if (rbtversion == NULL && trust < header->trust && - (header->rdh_ttl >= now || header_nx)) { + (ACTIVE(header, now) || header_nx)) { free_rdataset(rbtdb, rbtdb->common.mctx, newheader); if (addedrdataset != NULL) bind_rdataset(rbtdb, rbtnode, header, now, @@ -6305,7 +6303,7 @@ add32(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode, rbtdb_version_t *rbtversion, * Don't lower trust of existing record if the * update is forced. */ - if (IS_CACHE(rbtdb) && header->rdh_ttl >= now && + if (IS_CACHE(rbtdb) && ACTIVE(header, now) && header->type == dns_rdatatype_ns && !header_nx && !newheader_nx && header->trust >= newheader->trust && @@ -6341,7 +6339,7 @@ add32(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode, rbtdb_version_t *rbtversion, * to be no more than the current NS RRset's TTL. This * ensures the delegations that are withdrawn are honoured. */ - if (IS_CACHE(rbtdb) && header->rdh_ttl >= now && + if (IS_CACHE(rbtdb) && ACTIVE(header, now) && header->type == dns_rdatatype_ns && !header_nx && !newheader_nx && header->trust <= newheader->trust) { @@ -6349,7 +6347,7 @@ add32(dns_rbtdb_t *rbtdb, dns_rbtnode_t *rbtnode, rbtdb_version_t *rbtversion, newheader->rdh_ttl = header->rdh_ttl; } } - if (IS_CACHE(rbtdb) && header->rdh_ttl >= now && + if (IS_CACHE(rbtdb) && ACTIVE(header, now) && (header->type == dns_rdatatype_a || header->type == dns_rdatatype_aaaa || header->type == dns_rdatatype_ds ||