# Data for the "cname + other data / 2" test: same RRs in opposite order
$packet->push("answer", new Net::DNS::RR("cname2.example.com 300 A 1.2.3.4"));
$packet->push("answer", new Net::DNS::RR("cname2.example.com 300 CNAME cname2.example.com"));
+ } elsif ($qname =~ /redirect\.com/) {
+ $packet->push("authority", new Net::DNS::RR("redirect.com 300 NS ns.redirect.com"));
+ $packet->push("additional", new Net::DNS::RR("ns.redirect.com 300 A 10.53.0.6"));
+ } elsif ($qname =~ /\.tld1/) {
+ $packet->push("authority", new Net::DNS::RR("tld1 300 NS ns.tld1"));
+ $packet->push("additional", new Net::DNS::RR("ns.tld1 300 A 10.53.0.6"));
+ } elsif ($qname =~ /\.tld2/) {
+ $packet->push("authority", new Net::DNS::RR("tld2 300 NS ns.tld2"));
+ $packet->push("additional", new Net::DNS::RR("ns.tld2 300 A 10.53.0.7"));
} elsif ($qname eq "org" && $qtype eq "NS") {
$packet->header->aa(1);
$packet->push("answer", new Net::DNS::RR("org 300 NS a.root-servers.nil."));
use Net::DNS;
use Net::DNS::Packet;
+# Ignore SIGPIPE so we won't fail if peer closes a TCP socket early
+local $SIG{PIPE} = 'IGNORE';
+
+# Flush logged output after every line
+local $| = 1;
+
my $localport = int($ENV{'PORT'});
if (!$localport) { $localport = 5300; }
-my $sock = IO::Socket::INET->new(LocalAddr => "10.53.0.3",
- LocalPort => $localport, Proto => "udp") or die "$!";
+my $server_addr = "10.53.0.3";
+
+my $udpsock = IO::Socket::INET->new(LocalAddr => "$server_addr",
+ LocalPort => $localport, Proto => "udp", Reuse => 1) or die "$!";
+my $tcpsock = IO::Socket::INET->new(LocalAddr => "$server_addr",
+ LocalPort => $localport, Proto => "tcp", Listen => 5, Reuse => 1) 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: $!";
$SIG{INT} = \&rmpid;
$SIG{TERM} = \&rmpid;
-for (;;) {
- $sock->recv($buf, 512);
-
- print "**** request from " , $sock->peerhost, " port ", $sock->peerport, "\n";
-
+sub handleQuery {
+ my $buf = shift;
my $packet;
if ($Net::DNS::VERSION > 0.68) {
$packet->header->aa(0);
$packet->push("authority", new Net::DNS::RR("lame.example.org 300 NS ns.lame.example.org"));
$packet->push("additional", new Net::DNS::RR("ns.lame.example.org 300 A 10.53.0.3"));
+ } elsif ($qname eq "large-referral.example.net") {
+ for (my $i = 1; $i < 1000; $i++) {
+ $packet->push("authority", new Net::DNS::RR("large-referral.example.net 300 NS ns" . $i . ".fake.redirect.com"));
+ }
+ # No glue records
+ } elsif ($qname eq "foo.bar.sub.tld1") {
+ $packet->push("answer", new Net::DNS::RR("$qname 300 TXT baz"));
} elsif ($qname eq "cname.sub.example.org") {
$packet->push("answer",
new Net::DNS::RR($qname .
$packet->push("answer", new Net::DNS::RR("www.example.com 300 A 1.2.3.4"));
}
- $sock->send($packet->data);
-
print "RESPONSE:\n";
$packet->print;
- print "\n";
+
+ return $packet->data;
+}
+
+# Main
+my $rin;
+my $rout;
+for (;;) {
+ $rin = '';
+ vec($rin, fileno($tcpsock), 1) = 1;
+ vec($rin, fileno($udpsock), 1) = 1;
+
+ select($rout = $rin, undef, undef, undef);
+
+ if (vec($rout, fileno($udpsock), 1)) {
+ printf "UDP request\n";
+ my $buf;
+ $udpsock->recv($buf, 512);
+ my $result = handleQuery($buf);
+ my $num_chars = $udpsock->send($result);
+ print " Sent $num_chars bytes via UDP\n";
+ } elsif (vec($rout, fileno($tcpsock), 1)) {
+ my $conn = $tcpsock->accept;
+ my $buf;
+ for (;;) {
+ my $lenbuf;
+ my $n = $conn->sysread($lenbuf, 2);
+ last unless $n == 2;
+ my $len = unpack("n", $lenbuf);
+ $n = $conn->sysread($buf, $len);
+ last unless $n == $len;
+ print "TCP request\n";
+ my $result = handleQuery($buf);
+ $len = length($result);
+ $conn->syswrite(pack("n", $len), 2);
+ $n = $conn->syswrite($result, $len);
+ print " Sent: $n chars via TCP\n";
+ }
+ $conn->close;
+ }
}
attach-cache "globalcache";
};
+server 10.53.0.3 {
+ tcp-only yes;
+};
+
server 10.42.23.3/32 {
notify-source 10.42.22.1;
query-source address 10.42.22.1 port 0;
file "root.hint";
};
};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.1 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
allow-update { any; };
};
+zone "redirect.com" {
+ type primary;
+ file "redirect.com.db";
+};
+
+zone "tld1" {
+ type primary;
+ file "tld1.db";
+};
+
zone "no-edns-version.tld" {
type primary;
file "no-edns-version.tld.db";
--- /dev/null
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 600
+@ IN SOA ns hostmaster 1 1800 900 604800 600
+@ IN NS ns
+ns IN A 10.53.0.6
+
+; 10.53.1.* are non-responsive IP addresses
+$GENERATE 1-100 ns$.fake IN A 10.53.1.$
+$GENERATE 101-200 ns$.fake IN A 10.53.1.${-100}
+$GENERATE 201-300 ns$.fake IN A 10.53.1.${-200}
+$GENERATE 301-400 ns$.fake IN A 10.53.1.${-300}
+$GENERATE 401-500 ns$.fake IN A 10.53.1.${-400}
+$GENERATE 501-600 ns$.fake IN A 10.53.1.${-500}
+$GENERATE 601-700 ns$.fake IN A 10.53.1.${-600}
+$GENERATE 701-800 ns$.fake IN A 10.53.1.${-700}
+$GENERATE 801-900 ns$.fake IN A 10.53.1.${-800}
+$GENERATE 901-1000 ns$.fake IN A 10.53.1.${-900}
--- /dev/null
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 600
+@ IN SOA ns hostmaster 1 1800 900 604800 600
+@ IN NS ns
+ns IN A 10.53.0.6
+
+$GENERATE 1-21 sub IN NS sub-ns$.tld2.
type primary;
file "all-cnames.db";
};
+
+zone "tld2" {
+ type primary;
+ file "tld2.db";
+};
+
+zone "sub.tld1" {
+ type primary;
+ file "sub.tld1.db";
+};
type primary;
file "all-cnames.db";
};
+
+zone "tld2" {
+ type primary;
+ file "tld2.db";
+};
+
+zone "sub.tld1" {
+ type primary;
+ file "sub.tld1.db";
+};
--- /dev/null
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 600
+@ IN SOA ns hostmaster 1 1800 900 604800 600
+
+$GENERATE 1-21 @ IN NS sub-ns$.tld2.
+
+$GENERATE 1-21 bar IN NS bar-sub-ns$.tld2.
--- /dev/null
+; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+;
+; SPDX-License-Identifier: MPL-2.0
+;
+; This Source Code Form is subject to the terms of the Mozilla Public
+; License, v. 2.0. If a copy of the MPL was not distributed with this
+; file, you can obtain one at https://mozilla.org/MPL/2.0/.
+;
+; See the COPYRIGHT file distributed with this work for additional
+; information regarding copyright ownership.
+
+$TTL 600
+@ IN SOA ns hostmaster 1 1800 900 604800 600
+@ IN NS ns
+ns IN A 10.53.0.7
+
+$GENERATE 1-21 sub-ns$ IN A 10.53.0.7
+$GENERATE 1-21 bar-sub-ns$ IN A 10.53.0.3
if [ $ret != 0 ]; then echo_i "failed"; fi
status=$((status + ret))
+n=$((n+1))
+echo_i "check handling of large referrals to unresponsive name servers ($n)"
+ret=0
+dig_with_opts +timeout=15 large-referral.example.net @10.53.0.1 a > dig.out.ns1.test${n} || ret=1
+grep "status: SERVFAIL" dig.out.ns1.test${n} > /dev/null || ret=1
+# Check the total number of findname() calls triggered by a single query
+# for large-referral.example.net/A.
+findname_call_count="$(grep -c "large-referral\.example\.net.*FINDNAME" ns1/named.run)"
+if [ "${findname_call_count}" -gt 1000 ]; then
+ echo_i "failed: ${findname_call_count} (> 1000) findname() calls detected for large-referral.example.net"
+ ret=1
+fi
+# Check whether the limit of NS RRs processed for any delegation
+# encountered was not exceeded.
+if grep -Eq "dns_adb_createfind: started (A|AAAA) fetch for name ns21.fake.redirect.com" ns1/named.run; then
+ echo_i "failed: unexpected address fetch(es) were triggered for ns21.fake.redirect.com"
+ ret=1
+fi
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n+1))
+echo_i "checking query resolution for a domain with a valid glueless delegation chain ($n)"
+ret=0
+rndccmd 10.53.0.1 flush || ret=1
+dig_with_opts foo.bar.sub.tld1 @10.53.0.1 TXT > dig.out.ns1.test${n} || ret=1
+grep "status: NOERROR" dig.out.ns1.test${n} > /dev/null || ret=1
+grep "IN.*TXT.*baz" dig.out.ns1.test${n} > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
echo_i "exit status: $status"
[ $status -eq 0 ] || exit 1