From 02412bfe731d0cb229eb22f0ca4e8fbaed601cbe Mon Sep 17 00:00:00 2001 From: Mark Andrews Date: Fri, 27 May 2016 09:59:46 +1000 Subject: [PATCH] 4377. [bug] Don't reuse zero TTL responses beyond the current client set (excludes ANY/SIG/RRSIG queries). [RT #42142] (cherry picked from commit aabcb1fde0ca255ff30f0a5c10cbd39f798cc5b7) REDIRECT macro is 9.11.0+ --- bin/named/query.c | 31 +++++++++++++++ bin/tests/system/zero/ans5/ans.pl | 81 +++++++++++++++++++++++++++++++++++++++ bin/tests/system/zero/ns1/root.db | 2 + bin/tests/system/zero/tests.sh | 13 +++++++ 4 files changed, 127 insertions(+) create mode 100644 bin/tests/system/zero/ans5/ans.pl diff --git a/bin/named/query.c b/bin/named/query.c index 2c44e9ff53..3b402f1d01 100644 --- a/bin/named/query.c +++ b/bin/named/query.c @@ -6816,6 +6816,37 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype) goto cleanup; case DNS_R_CNAME: + /* + * If we have a zero ttl from the cache refetch it. + */ + if (!is_zone && event == NULL && rdataset->ttl == 0 && + RECURSIONOK(client)) + { + if (dns_rdataset_isassociated(rdataset)) + dns_rdataset_disassociate(rdataset); + if (sigrdataset != NULL && + dns_rdataset_isassociated(sigrdataset)) + dns_rdataset_disassociate(sigrdataset); + if (node != NULL) + dns_db_detachnode(db, &node); + + result = query_recurse(client, qtype, + client->query.qname, + NULL, NULL, resuming); + if (result == ISC_R_SUCCESS) { + client->query.attributes |= + NS_QUERYATTR_RECURSING; + if (dns64) + client->query.attributes |= + NS_QUERYATTR_DNS64; + if (dns64_exclude) + client->query.attributes |= + NS_QUERYATTR_DNS64EXCLUDE; + } else + RECURSE_ERROR(result); + goto cleanup; + } + /* * Keep a copy of the rdataset. We have to do this because * query_addrrset may clear 'rdataset' (to prevent the diff --git a/bin/tests/system/zero/ans5/ans.pl b/bin/tests/system/zero/ans5/ans.pl new file mode 100644 index 0000000000..9dfa18e444 --- /dev/null +++ b/bin/tests/system/zero/ans5/ans.pl @@ -0,0 +1,81 @@ +#!/usr/bin/perl -w +# +# Copyright (C) 2015 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. + +# +# Don't respond if the "norespond" file exists; otherwise respond to +# any A or AAAA query. +# + +use IO::File; +use IO::Socket; +use Net::DNS; +use Net::DNS::Packet; + +my $sock = IO::Socket::INET->new(LocalAddr => "10.53.0.5", + LocalPort => 5300, Proto => "udp") or die "$!"; + +my $pidf = new IO::File "ans.pid", "w" or die "cannot open pid file: $!"; +print $pidf "$$\n" or die "cannot write pid file: $!"; +$pidf->close or die "cannot close pid file: $!"; +sub rmpid { unlink "ans.pid"; exit 1; }; + +$SIG{INT} = \&rmpid; +$SIG{TERM} = \&rmpid; + +my $octet = 0; + +for (;;) { + $sock->recv($buf, 512); + + print "**** request from " , $sock->peerhost, " port ", $sock->peerport, "\n"; + + my $packet; + + if ($Net::DNS::VERSION > 0.68) { + $packet = new Net::DNS::Packet(\$buf, 0); + $@ and die $@; + } else { + my $err; + ($packet, $err) = new Net::DNS::Packet(\$buf, 0); + $err and die $err; + } + + print "REQUEST:\n"; + $packet->print; + + $packet->header->qr(1); + + my @questions = $packet->question; + my $qname = $questions[0]->qname; + my $qtype = $questions[0]->qtype; + + $packet->header->aa(1); + if ($qtype eq "A") { + $packet->push("answer", + new Net::DNS::RR($qname . + " 0 A 192.0.2." . $octet)); + $octet = $octet + 1; + } elsif ($qtype eq "AAAA") { + $packet->push("answer", + new Net::DNS::RR($qname . + " 300 AAAA 2001:db8:beef::1")); + } + + $sock->send($packet->data); + print "RESPONSE:\n"; + $packet->print; + print "\n"; +} diff --git a/bin/tests/system/zero/ns1/root.db b/bin/tests/system/zero/ns1/root.db index 69aca86fb8..beb97cb693 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 +increment. NS incrementns. +incrementns A 10.53.0.5 diff --git a/bin/tests/system/zero/tests.sh b/bin/tests/system/zero/tests.sh index 15c2906a92..bbb78f0fd8 100644 --- a/bin/tests/system/zero/tests.sh +++ b/bin/tests/system/zero/tests.sh @@ -44,5 +44,18 @@ done if [ $ret != 0 ]; then echo "I:failed"; fi status=`expr $status + $ret` +echo "I:check repeated recursive lookups of non recurring zero ttl responses get new values" +count=`( +dig +short -p 5300 @10.53.0.3 foo.increment +dig +short -p 5300 @10.53.0.3 foo.increment +dig +short -p 5300 @10.53.0.3 foo.increment +dig +short -p 5300 @10.53.0.3 foo.increment +dig +short -p 5300 @10.53.0.3 foo.increment +dig +short -p 5300 @10.53.0.3 foo.increment +dig +short -p 5300 @10.53.0.3 foo.increment +) | sort -u | wc -l ` +if [ $count -ne 7 ] ; then echo "I:failed (count=$count)"; ret=1; fi +status=`expr $status + $ret` + echo "I:exit status: $status" exit $status -- 2.14.4