]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
4336. [bug] Don't emit records with zero ttl unless the records
authorMark Andrews <marka@isc.org>
Mon, 21 Mar 2016 02:22:21 +0000 (13:22 +1100)
committerMark Andrews <marka@isc.org>
Mon, 21 Mar 2016 03:34:30 +0000 (14:34 +1100)
                        were learnt with a zero ttl. [RT #41687]

(cherry picked from commit 0993cd5f2227c1aa6a8554f4a9a847efabbcfcb8)

CHANGES
bin/tests/system/resolver/ns6/example.net.db.in
bin/tests/system/resolver/ns7/named1.conf
bin/tests/system/resolver/ns7/named2.conf
bin/tests/system/resolver/tests.sh
lib/dns/rbtdb.c
lib/dns/zone.c

diff --git a/CHANGES b/CHANGES
index 1a200a8c901b61fb2cfa436016a6b687ba73db2d..613ba4a3712bd9950acf5db1e32f3827cdb6b8ad 100644 (file)
--- 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
index 103cab4c887b5df5efa7af2db88b202fd9eacc77..cb01dbbbd21b80d37d082fa92a51c8a0ff123a0e 100644 (file)
@@ -20,3 +20,6 @@ $TTL 600
 @      IN MX   0 mail
 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
index a2dc8173584dd8800d521eff19e2aae2b5884216..370a0ae361ba1f7c70e23455c16611343a2683f1 100644 (file)
@@ -29,6 +29,10 @@ options {
        recursion yes;
        empty-zones-enable yes;
        disable-empty-zone 20.172.in-addr.arpa;
+       /*
+        * I: check zero ttl not returned
+        */
+       querylog yes;
 };
 
 key rndc_key {
index 8ed95b712a8fc03b0e7bd8e001e26c204dec2729..d7ff23380acf944814df1643c2ba9979f8fb6160 100644 (file)
@@ -29,6 +29,10 @@ options {
        recursion yes;
        empty-zones-enable yes;
        disable-empty-zone 20.172.in-addr.arpa;
+       /*
+        * I: check zero ttl not returned
+        */
+       querylog yes;
 };
 
 key rndc_key {
index 4c1571f85e60352c815a6d3f51cb0537da7d855b..cc38a71db98cf378cc698c33858a59cf4afd5c2f 100755 (executable)
@@ -396,7 +396,6 @@ grep "status: NOERROR" dig.ns7.out.${n} > /dev/null || ret=1
 grep "ANSWER: 1" dig.ns7.out.${n} > /dev/null || ret=1
 if [ $ret != 0 ]; then echo "I:failed"; ret=1; fi
 status=`expr $status + $ret`
-#HERE >>>
 
 n=`expr $n + 1`
 echo "I:check that '-t aaaa' in .digrc does not have unexpected side effects ($n)"
@@ -517,5 +516,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
index d919e0b2ed323536e42fc08225f10951fc156c92..187dd0c1dc7b721d6c6dc140e828135301044724 100644 (file)
@@ -401,6 +401,9 @@ typedef ISC_LIST(dns_rbtnode_t)         rbtnodelist_t;
 #define RDATASET_ATTR_STATCOUNT         0x0040
 #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;
@@ -441,6 +444,12 @@ struct acachectl {
        (((header)->attributes & RDATASET_ATTR_OPTOUT) != 0)
 #define NEGATIVE(header) \
        (((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. */
 
@@ -4303,7 +4312,8 @@ 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) {
+               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
@@ -4311,7 +4321,7 @@ cache_zonecut_callback(dns_rbtnode_t *node, dns_name_t *name, void *arg) {
                         * the node as dirty, so it will get cleaned
                         * up later.
                         */
-                       if ((header->rdh_ttl <  search->now - RBTDB_VIRTUAL) &&
+                       if ((header->rdh_ttl < search->now - RBTDB_VIRTUAL) &&
                            (locktype == isc_rwlocktype_write ||
                             NODE_TRYUPGRADE(lock) == ISC_R_SUCCESS)) {
                                /*
@@ -4427,7 +4437,8 @@ 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) {
+                       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
@@ -4435,7 +4446,7 @@ find_deepest_zonecut(rbtdb_search_t *search, dns_rbtnode_t *node,
                                 * the node as dirty, so it will get cleaned
                                 * up later.
                                 */
-                               if ((header->rdh_ttl <  search->now -
+                               if ((header->rdh_ttl < search->now -
                                                    RBTDB_VIRTUAL) &&
                                    (locktype == isc_rwlocktype_write ||
                                     NODE_TRYUPGRADE(lock) == ISC_R_SUCCESS)) {
@@ -4604,7 +4615,8 @@ find_coveringnsec(rbtdb_search_t *search, dns_dbnode_t **nodep,
                     header != NULL;
                     header = header_next) {
                        header_next = header->next;
-                       if (header->rdh_ttl <  now) {
+                       if (header->rdh_ttl < now ||
+                           (header->rdh_ttl == now && !ZEROTTL(header))) {
                                /*
                                 * This rdataset is stale.  If no one else is
                                 * using the node, we can clean it up right
@@ -4612,7 +4624,7 @@ find_coveringnsec(rbtdb_search_t *search, dns_dbnode_t **nodep,
                                 * node as dirty, so it will get cleaned up
                                 * later.
                                 */
-                               if ((header->rdh_ttl <  now - RBTDB_VIRTUAL) &&
+                               if ((header->rdh_ttl < now - RBTDB_VIRTUAL) &&
                                    (locktype == isc_rwlocktype_write ||
                                     NODE_TRYUPGRADE(lock) == ISC_R_SUCCESS)) {
                                        /*
@@ -5011,14 +5023,15 @@ 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) {
+               if (header->rdh_ttl < now ||
+                   (header->rdh_ttl == 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 it as stale, and the node as dirty, so it will
                         * get cleaned up later.
                         */
-                       if ((header->rdh_ttl <  now - RBTDB_VIRTUAL) &&
+                       if ((header->rdh_ttl < now - RBTDB_VIRTUAL) &&
                            (locktype == isc_rwlocktype_write ||
                             NODE_TRYUPGRADE(lock) == ISC_R_SUCCESS)) {
                                /*
@@ -5318,7 +5331,8 @@ 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) {
+               if (header->rdh_ttl < now ||
+                   (header->rdh_ttl == now && !ZEROTTL(header))) {
                        /*
                         * This rdataset is stale.  If no one else is using the
                         * node, we can clean it up right now, otherwise we
@@ -5807,7 +5821,8 @@ 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) {
+               if (header->rdh_ttl < now ||
+                   (header->rdh_ttl == now && !ZEROTTL(header))) {
                        if ((header->rdh_ttl < now - RBTDB_VIRTUAL) &&
                            (locktype == isc_rwlocktype_write ||
                             NODE_TRYUPGRADE(lock) == ISC_R_SUCCESS)) {
@@ -6644,6 +6659,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++;
index 73f1a6a14f9f97094254e7fcab3fb61cc2e13d6c..af77ce5f8e60d3290c49e82e0c8aabdd70487108 100644 (file)
@@ -3410,7 +3410,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];