summaryrefslogtreecommitdiffstats
path: root/bin/tests/system/forward
diff options
context:
space:
mode:
Diffstat (limited to 'bin/tests/system/forward')
-rw-r--r--bin/tests/system/forward/ans11/ans.py272
-rw-r--r--bin/tests/system/forward/ans6/ans.pl562
-rw-r--r--bin/tests/system/forward/clean.sh26
-rw-r--r--bin/tests/system/forward/ns1/diditwork.net.db22
-rw-r--r--bin/tests/system/forward/ns1/example.db23
-rw-r--r--bin/tests/system/forward/ns1/named.conf.in87
-rw-r--r--bin/tests/system/forward/ns1/net.example.lll15
-rw-r--r--bin/tests/system/forward/ns1/root.db.in36
-rw-r--r--bin/tests/system/forward/ns1/sign.sh34
-rw-r--r--bin/tests/system/forward/ns1/sld.tld.db22
-rw-r--r--bin/tests/system/forward/ns1/spoofed.net.db22
-rw-r--r--bin/tests/system/forward/ns1/sub.local.net.db22
-rw-r--r--bin/tests/system/forward/ns10/fakenet.zone17
-rw-r--r--bin/tests/system/forward/ns10/fakenet2.zone15
-rw-r--r--bin/tests/system/forward/ns10/fakesublocalnet.zone15
-rw-r--r--bin/tests/system/forward/ns10/fakesublocaltld.zone15
-rw-r--r--bin/tests/system/forward/ns10/named.conf.in54
-rw-r--r--bin/tests/system/forward/ns10/net.example.lll15
-rw-r--r--bin/tests/system/forward/ns10/spoofednet.zone16
-rw-r--r--bin/tests/system/forward/ns2/example.db23
-rw-r--r--bin/tests/system/forward/ns2/named.conf.in72
-rw-r--r--bin/tests/system/forward/ns2/root.db30
-rw-r--r--bin/tests/system/forward/ns2/tld.db29
-rw-r--r--bin/tests/system/forward/ns3/named1.conf.in66
-rw-r--r--bin/tests/system/forward/ns3/named2.conf.in43
-rw-r--r--bin/tests/system/forward/ns3/root.db30
-rw-r--r--bin/tests/system/forward/ns3/root2.db21
-rw-r--r--bin/tests/system/forward/ns4/malicious.db24
-rw-r--r--bin/tests/system/forward/ns4/named.conf.in69
-rw-r--r--bin/tests/system/forward/ns4/root.db30
-rw-r--r--bin/tests/system/forward/ns4/sibling.tld.db22
-rw-r--r--bin/tests/system/forward/ns5/named.conf.in36
-rw-r--r--bin/tests/system/forward/ns5/rebind.db24
-rw-r--r--bin/tests/system/forward/ns5/root.db30
-rw-r--r--bin/tests/system/forward/ns7/named.conf.in30
-rw-r--r--bin/tests/system/forward/ns7/root.db30
-rw-r--r--bin/tests/system/forward/ns8/named.conf.in35
-rw-r--r--bin/tests/system/forward/ns8/root.db13
-rw-r--r--bin/tests/system/forward/ns8/sub.local.tld.db15
-rw-r--r--bin/tests/system/forward/ns9/local.net.db16
-rw-r--r--bin/tests/system/forward/ns9/local.tld.db15
-rw-r--r--bin/tests/system/forward/ns9/named1.conf.in67
-rw-r--r--bin/tests/system/forward/ns9/named2.conf.in70
-rw-r--r--bin/tests/system/forward/ns9/named3.conf.in50
-rw-r--r--bin/tests/system/forward/ns9/named4.conf.in47
-rw-r--r--bin/tests/system/forward/ns9/root.db13
-rw-r--r--bin/tests/system/forward/rfc1918-inherited.conf17
-rw-r--r--bin/tests/system/forward/rfc1918-notinherited.conf18
-rw-r--r--bin/tests/system/forward/setup.sh30
-rw-r--r--bin/tests/system/forward/tests.sh406
-rw-r--r--bin/tests/system/forward/tests_sh_forward.py14
-rw-r--r--bin/tests/system/forward/ula-inherited.conf17
-rw-r--r--bin/tests/system/forward/ula-notinherited.conf18
53 files changed, 2760 insertions, 0 deletions
diff --git a/bin/tests/system/forward/ans11/ans.py b/bin/tests/system/forward/ans11/ans.py
new file mode 100644
index 0000000..00b5895
--- /dev/null
+++ b/bin/tests/system/forward/ans11/ans.py
@@ -0,0 +1,272 @@
+# 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.
+
+from __future__ import print_function
+import os
+import sys
+import signal
+import socket
+import select
+import struct
+from datetime import datetime, timedelta
+import time
+import functools
+
+import dns, dns.message, dns.query, dns.flags
+from dns.rdatatype import *
+from dns.rdataclass import *
+from dns.rcode import *
+from dns.name import *
+
+
+# Log query to file
+def logquery(type, qname):
+ with open("qlog", "a") as f:
+ f.write("%s %s\n", type, qname)
+
+
+# Create a UDP listener
+def udp_listen(ip, port, is_ipv6=False):
+ try:
+ udp = socket.socket(
+ socket.AF_INET6 if is_ipv6 else socket.AF_INET, socket.SOCK_DGRAM
+ )
+ try:
+ udp.bind((ip, port))
+ except:
+ udp.close()
+ udp = None
+ except:
+ udp = None
+
+ if udp is None and not is_ipv6:
+ raise socket.error("Can not create an IPv4 UDP listener")
+
+ return udp
+
+
+# Create a TCP listener
+def tcp_listen(ip, port, is_ipv6=False):
+ try:
+ tcp = socket.socket(
+ socket.AF_INET6 if is_ipv6 else socket.AF_INET, socket.SOCK_STREAM
+ )
+ try:
+ tcp.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
+ tcp.bind((ip, port))
+ tcp.listen(100)
+ except:
+ tcp.close()
+ tcp = None
+ except:
+ tcp = None
+
+ if tcp is None and not is_ipv6:
+ raise socket.error("Can not create an IPv4 TCP listener")
+
+ return tcp
+
+
+############################################################################
+# Control channel - send "1" or "0" to enable or disable the "silent" mode.
+############################################################################
+silent = False
+
+
+def ctrl_channel(msg):
+ global silent
+
+ msg = msg.splitlines().pop(0)
+ print("Received control message: %s" % msg)
+
+ if len(msg) != 1:
+ return
+
+ if silent:
+ if msg == b"0":
+ silent = False
+ print("Silent mode was disabled")
+ else:
+ if msg == b"1":
+ silent = True
+ print("Silent mode was enabled")
+
+
+############################################################################
+# Respond to a DNS query.
+############################################################################
+def create_response(msg):
+ m = dns.message.from_wire(msg)
+ qname = m.question[0].name.to_text()
+ rrtype = m.question[0].rdtype
+ typename = dns.rdatatype.to_text(rrtype)
+
+ with open("query.log", "a") as f:
+ f.write("%s %s\n" % (typename, qname))
+ print("%s %s" % (typename, qname), end=" ")
+
+ r = dns.message.make_response(m)
+ r.set_rcode(NOERROR)
+ if rrtype == A:
+ tld = qname.split(".")[-2] + "."
+ ns = "local." + tld
+ r.answer.append(dns.rrset.from_text(qname, 300, IN, A, "10.53.0.11"))
+ r.answer.append(dns.rrset.from_text(tld, 300, IN, NS, "local." + tld))
+ r.additional.append(dns.rrset.from_text(ns, 300, IN, A, "10.53.0.11"))
+ elif rrtype == NS:
+ r.answer.append(dns.rrset.from_text(qname, 300, IN, NS, "."))
+ elif rrtype == SOA:
+ r.answer.append(dns.rrset.from_text(qname, 300, IN, SOA, ". . 0 0 0 0 0"))
+ else:
+ r.authority.append(dns.rrset.from_text(qname, 300, IN, SOA, ". . 0 0 0 0 0"))
+ r.flags |= dns.flags.AA
+ return r
+
+
+def sigterm(signum, frame):
+ print("Shutting down now...")
+ os.remove("ans.pid")
+ running = False
+ sys.exit(0)
+
+
+############################################################################
+# Main
+#
+# Set up responder and control channel, open the pid file, and start
+# the main loop, listening for queries on the query channel or commands
+# on the control channel and acting on them.
+############################################################################
+ip4 = "10.53.0.11"
+ip6 = "fd92:7065:b8e:ffff::11"
+
+try:
+ port = int(os.environ["PORT"])
+except:
+ port = 5300
+
+try:
+ ctrlport = int(os.environ["EXTRAPORT1"])
+except:
+ ctrlport = 5300
+
+ctrl4_tcp = tcp_listen(ip4, ctrlport)
+query4_udp = udp_listen(ip4, port)
+query6_udp = udp_listen(ip6, port, is_ipv6=True)
+query4_tcp = tcp_listen(ip4, port)
+query6_tcp = tcp_listen(ip6, port, is_ipv6=True)
+
+havev6 = query6_udp is not None and query6_tcp is not None
+
+signal.signal(signal.SIGTERM, sigterm)
+
+f = open("ans.pid", "w")
+pid = os.getpid()
+print(pid, file=f)
+f.close()
+
+running = True
+
+print("Listening on %s port %d" % (ip4, ctrlport))
+print("Listening on %s port %d" % (ip4, port))
+if havev6:
+ print("Listening on %s port %d" % (ip6, port))
+
+print("Ctrl-c to quit")
+
+if havev6:
+ input = [ctrl4_tcp, query4_udp, query6_udp, query4_tcp, query6_tcp]
+else:
+ input = [ctrl4_tcp, query4_udp, query4_tcp]
+
+hung_conns = []
+
+while running:
+ try:
+ inputready, outputready, exceptready = select.select(input, [], [])
+ except select.error as e:
+ break
+ except socket.error as e:
+ break
+ except KeyboardInterrupt:
+ break
+
+ for s in inputready:
+ if s == ctrl4_tcp:
+ print("Control channel connected")
+ conn = None
+ try:
+ # Handle control channel input
+ conn, addr = s.accept()
+ msg = conn.recv(1)
+ if msg:
+ ctrl_channel(msg)
+ conn.close()
+ except s.timeout:
+ pass
+ if conn:
+ conn.close()
+ elif s == query4_tcp or s == query6_tcp:
+ print(
+ "TCP query received on %s" % (ip4 if s == query4_tcp else ip6), end=" "
+ )
+ conn = None
+ try:
+ # Handle incoming queries
+ conn, addr = s.accept()
+ if not silent:
+ # get TCP message length
+ msg = conn.recv(2)
+ if len(msg) != 2:
+ print("NO RESPONSE (can not read the message length)")
+ conn.close()
+ continue
+ length = struct.unpack(">H", msg[:2])[0]
+ msg = conn.recv(length)
+ if len(msg) != length:
+ print("NO RESPONSE (can not read the message)")
+ conn.close()
+ continue
+ rsp = create_response(msg)
+ if rsp:
+ print(dns.rcode.to_text(rsp.rcode()))
+ wire = rsp.to_wire()
+ conn.send(struct.pack(">H", len(wire)))
+ conn.send(wire)
+ else:
+ print("NO RESPONSE (can not create a response)")
+ else:
+ # Do not respond and hang the connection.
+ print("NO RESPONSE (silent mode)")
+ hung_conns.append(conn)
+ continue
+ except socket.error as e:
+ print("NO RESPONSE (error: %s)" % str(e))
+ if conn:
+ conn.close()
+ elif s == query4_udp or s == query6_udp:
+ print(
+ "UDP query received on %s" % (ip4 if s == query4_udp else ip6), end=" "
+ )
+ # Handle incoming queries
+ msg = s.recvfrom(65535)
+ if not silent:
+ rsp = create_response(msg[0])
+ if rsp:
+ print(dns.rcode.to_text(rsp.rcode()))
+ s.sendto(rsp.to_wire(), msg[1])
+ else:
+ print("NO RESPONSE (can not create a response)")
+ else:
+ # Do not respond.
+ print("NO RESPONSE (silent mode)")
+ if not running:
+ break
diff --git a/bin/tests/system/forward/ans6/ans.pl b/bin/tests/system/forward/ans6/ans.pl
new file mode 100644
index 0000000..6102e4a
--- /dev/null
+++ b/bin/tests/system/forward/ans6/ans.pl
@@ -0,0 +1,562 @@
+#!/usr/bin/perl
+
+# 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.
+
+#
+# This is the name server from hell. It provides canned
+# responses based on pattern matching the queries, and
+# can be reprogrammed on-the-fly over a TCP connection.
+#
+# The server listens for queries on port 5300 (or PORT).
+#
+# The server listens for control connections on port 5301 (or EXTRAPORT1).
+#
+# A control connection is a TCP stream of lines like
+#
+# /pattern/
+# name ttl type rdata
+# name ttl type rdata
+# ...
+# /pattern/
+# name ttl type rdata
+# name ttl type rdata
+# ...
+#
+# There can be any number of patterns, each associated
+# with any number of response RRs. Each pattern is a
+# Perl regular expression. If an empty pattern ("//") is
+# received, the server will ignore all incoming queries (TCP
+# connections will still be accepted, but both UDP queries
+# and TCP queries will not be responded to). If a non-empty
+# pattern is then received over the same control connection,
+# default behavior is restored.
+#
+# Each incoming query is converted into a string of the form
+# "qname qtype" (the printable query domain name, space,
+# printable query type) and matched against each pattern.
+#
+# The first pattern matching the query is selected, and
+# the RR following the pattern line are sent in the
+# answer section of the response.
+#
+# Each new control connection causes the current set of
+# patterns and responses to be cleared before adding new
+# ones.
+#
+# The server handles UDP and TCP queries. Zone transfer
+# responses work, but must fit in a single 64 k message.
+#
+# Now you can add TSIG, just specify key/key data with:
+#
+# /pattern <key> <key_data>/
+# name ttl type rdata
+# name ttl type rdata
+#
+# Note that this data will still be sent with any request for
+# pattern, only this data will be signed. Currently, this is only
+# done for TCP.
+#
+# /pattern bad-id <key> <key_data>/
+# /pattern bad-id/
+#
+# will add 50 to the message id of the response.
+
+
+use IO::File;
+use IO::Socket;
+use Data::Dumper;
+use Net::DNS;
+use Net::DNS::Packet;
+use strict;
+
+# 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;
+
+# We default to listening on 10.53.0.2 for historical reasons
+# XXX: we should also be able to specify IPv6
+my $server_addr = "10.53.0.6";
+if (@ARGV > 0) {
+ $server_addr = @ARGV[0];
+}
+
+my $mainport = int($ENV{'PORT'});
+if (!$mainport) { $mainport = 5300; }
+my $ctrlport = int($ENV{'EXTRAPORT1'});
+if (!$ctrlport) { $ctrlport = 5301; }
+
+print "listening on $server_addr:$mainport,$ctrlport.\n";
+print "Using Net::DNS $Net::DNS::VERSION\n";
+
+# XXX: we should also be able to set the port numbers to listen on.
+my $ctlsock = IO::Socket::INET->new(LocalAddr => "$server_addr",
+ LocalPort => $ctrlport, Proto => "tcp", Listen => 5, Reuse => 1) or die "$!";
+
+my $udpsock = IO::Socket::INET->new(LocalAddr => "$server_addr",
+ LocalPort => $mainport, Proto => "udp", Reuse => 1) or die "$!";
+
+my $tcpsock = IO::Socket::INET->new(LocalAddr => "$server_addr",
+ LocalPort => $mainport, 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: $!";
+$pidf->close or die "cannot close pid file: $!";;
+sub rmpid { unlink "ans.pid"; exit 1; };
+
+$SIG{INT} = \&rmpid;
+$SIG{TERM} = \&rmpid;
+
+#my @answers = ();
+my @rules;
+my $udphandler;
+my $tcphandler;
+
+sub handleUDP {
+ my ($buf) = @_;
+ my $request;
+
+ if ($Net::DNS::VERSION > 0.68) {
+ $request = new Net::DNS::Packet(\$buf, 0);
+ $@ and die $@;
+ } else {
+ my $err;
+ ($request, $err) = new Net::DNS::Packet(\$buf, 0);
+ $err and die $err;
+ }
+
+ my @questions = $request->question;
+ my $qname = $questions[0]->qname;
+ my $qtype = $questions[0]->qtype;
+ my $qclass = $questions[0]->qclass;
+ my $id = $request->header->id;
+
+ my $packet = new Net::DNS::Packet($qname, $qtype, $qclass);
+ $packet->header->qr(1);
+ $packet->header->aa(1);
+ $packet->header->id($id);
+
+ # get the existing signature if any, and clear the additional section
+ my $prev_tsig;
+ while (my $rr = $request->pop("additional")) {
+ $prev_tsig = $rr if ($rr->type eq "TSIG");
+ }
+
+ my $r;
+ my $answers = 0;
+ my $match;
+ my $key_name;
+ my $key_data;
+ foreach $r (@rules) {
+ my $pattern = $r->{pattern};
+ ($match, $key_name, $key_data) = split(/ /,$pattern);
+ print "[handleUDP] $match, $key_name, $key_data\n";
+ $match =~ tr/\// /;
+ if ("$qname $qtype" =~ /$match/) {
+ my $a;
+ foreach $a (@{$r->{answer}}) {
+ my $resp;
+ $resp = new Net::DNS::RR("$qname $a");
+ $packet->push("answer", $resp);
+ ++$answers;
+ }
+ last;
+ }
+ }
+ if ($answers eq 0) {
+ my $soa;
+ $soa = new Net::DNS::RR("$qname 300 IN SOA . . 0 0 0 0 0");
+ $packet->push("authority", $soa)
+ }
+ if (defined($key_name) && defined($key_data)) {
+ my $tsig;
+ # Sign the packet
+ print " Signing the response with " .
+ "$key_name/$key_data\n";
+
+ if ($Net::DNS::VERSION < 0.69) {
+ $tsig = Net::DNS::RR->new(
+ "$key_name TSIG $key_data");
+ } else {
+ $tsig = Net::DNS::RR->new(
+ name => $key_name,
+ type => 'TSIG',
+ key => $key_data);
+ }
+
+ # These kluges are necessary because Net::DNS
+ # doesn't know how to sign responses. We
+ # clear compnames so that the TSIG key and
+ # algorithm name won't be compressed, and
+ # add one to arcount because the signing
+ # function will attempt to decrement it,
+ # which is incorrect in a response. Finally
+ # we set request_mac to the previous digest.
+ $packet->{"compnames"} = {}
+ if ($Net::DNS::VERSION < 0.70);
+ $packet->{"header"}{"arcount"} += 1
+ if ($Net::DNS::VERSION < 0.70);
+ if (defined($prev_tsig)) {
+ if ($Net::DNS::VERSION < 0.73) {
+ my $rmac = pack('n H*',
+ length($prev_tsig->mac)/2,
+ $prev_tsig->mac);
+ $tsig->{"request_mac"} =
+ unpack("H*", $rmac);
+ } else {
+ $tsig->request_mac(
+ $prev_tsig->mac);
+ }
+ }
+
+ $packet->sign_tsig($tsig);
+ }
+ #$packet->print;
+
+ return $packet->data;
+}
+
+# namelen:
+# given a stream of data, reads a DNS-formatted name and returns its
+# total length, thus making it possible to skip past it.
+sub namelen {
+ my ($data) = @_;
+ my $len = 0;
+ my $label_len = 0;
+ do {
+ $label_len = unpack("c", $data);
+ $data = substr($data, $label_len + 1);
+ $len += $label_len + 1;
+ } while ($label_len != 0);
+ return ($len);
+}
+
+# packetlen:
+# given a stream of data, reads a DNS wire-format packet and returns
+# its total length, making it possible to skip past it.
+sub packetlen {
+ my ($data) = @_;
+ my $q;
+ my $rr;
+ my $header;
+ my $offset;
+
+ #
+ # decode/encode were introduced in Net::DNS 0.68
+ # parse is no longer a method and calling it here makes perl croak.
+ #
+ my $decode = 0;
+ $decode = 1 if ($Net::DNS::VERSION >= 0.68);
+
+ if ($decode) {
+ ($header, $offset) = Net::DNS::Header->decode(\$data);
+ } else {
+ ($header, $offset) = Net::DNS::Header->parse(\$data);
+ }
+
+ for (1 .. $header->qdcount) {
+ if ($decode) {
+ ($q, $offset) =
+ Net::DNS::Question->decode(\$data, $offset);
+ } else {
+ ($q, $offset) =
+ Net::DNS::Question->parse(\$data, $offset);
+ }
+ }
+ for (1 .. $header->ancount) {
+ if ($decode) {
+ ($q, $offset) = Net::DNS::RR->decode(\$data, $offset);
+ } else {
+ ($q, $offset) = Net::DNS::RR->parse(\$data, $offset);
+ }
+ }
+ for (1 .. $header->nscount) {
+ if ($decode) {
+ ($q, $offset) = Net::DNS::RR->decode(\$data, $offset);
+ } else {
+ ($q, $offset) = Net::DNS::RR->parse(\$data, $offset);
+ }
+ }
+ for (1 .. $header->arcount) {
+ if ($decode) {
+ ($q, $offset) = Net::DNS::RR->decode(\$data, $offset);
+ } else {
+ ($q, $offset) = Net::DNS::RR->parse(\$data, $offset);
+ }
+ }
+ return $offset;
+}
+
+# sign_tcp_continuation:
+# This is a hack to correct the problem that Net::DNS has no idea how
+# to sign multiple-message TCP responses. Several data that are included
+# in the digest when signing a query or the first message of a response are
+# omitted when signing subsequent messages in a TCP stream.
+#
+# Net::DNS::Packet->sign_tsig() has the ability to use a custom signing
+# function (specified by calling Packet->sign_func()). We use this
+# function as the signing function for TCP continuations, and it removes
+# the unwanted data from the digest before calling the default sign_hmac
+# function.
+sub sign_tcp_continuation {
+ my ($key, $data) = @_;
+
+ # copy out first two bytes: size of the previous MAC
+ my $rmacsize = unpack("n", $data);
+ $data = substr($data, 2);
+
+ # copy out previous MAC
+ my $rmac = substr($data, 0, $rmacsize);
+ $data = substr($data, $rmacsize);
+
+ # try parsing out the packet information
+ my $plen = packetlen($data);
+ my $pdata = substr($data, 0, $plen);
+ $data = substr($data, $plen);
+
+ # remove the keyname, ttl, class, and algorithm name
+ $data = substr($data, namelen($data));
+ $data = substr($data, 6);
+ $data = substr($data, namelen($data));
+
+ # preserve the TSIG data
+ my $tdata = substr($data, 0, 8);
+
+ # prepare a new digest and sign with it
+ $data = pack("n", $rmacsize) . $rmac . $pdata . $tdata;
+ return Net::DNS::RR::TSIG::sign_hmac($key, $data);
+}
+
+sub handleTCP {
+ my ($buf) = @_;
+ my $request;
+
+ if ($Net::DNS::VERSION > 0.68) {
+ $request = new Net::DNS::Packet(\$buf, 0);
+ $@ and die $@;
+ } else {
+ my $err;
+ ($request, $err) = new Net::DNS::Packet(\$buf, 0);
+ $err and die $err;
+ }
+
+ my @questions = $request->question;
+ my $qname = $questions[0]->qname;
+ my $qtype = $questions[0]->qtype;
+ my $qclass = $questions[0]->qclass;
+ my $id = $request->header->id;
+
+ my $opaque;
+
+ my $packet = new Net::DNS::Packet($qname, $qtype, $qclass);
+ $packet->header->qr(1);
+ $packet->header->aa(1);
+ $packet->header->id($id);
+
+ # get the existing signature if any, and clear the additional section
+ my $prev_tsig;
+ my $signer;
+ my $continuation = 0;
+ if ($Net::DNS::VERSION < 0.81) {
+ while (my $rr = $request->pop("additional")) {
+ if ($rr->type eq "TSIG") {
+ $prev_tsig = $rr;
+ }
+ }
+ }
+
+ my @results = ();
+ my $count_these = 0;
+
+ my $r;
+ my $answers = 0;
+ my $match;
+ my $key_name;
+ my $key_data;
+ my $tname;
+ foreach $r (@rules) {
+ my $pattern = $r->{pattern};
+ my($match, $key_name, $key_data, $tname) = split(/ /,$pattern);
+ print "[handleTCP] $match, $key_name, $key_data, $tname \n";
+ $match =~ tr/\// /;
+ if ("$qname $qtype" =~ /$match/) {
+ $count_these++;
+ my $a;
+ foreach $a (@{$r->{answer}}) {
+ my $resp;
+ $resp = new Net::DNS::RR("$qname $a");
+ $packet->push("answer", $resp);
+ ++$answers;
+ }
+ last;
+ }
+ }
+ if ($answers eq 0) {
+ my $soa;
+ $soa = new Net::DNS::RR("$qname 300 SOA . . 0 0 0 0 0");
+ $packet->push("authority", $soa)
+ }
+ if (defined($key_name) && $key_name eq "bad-id") {
+ $packet->header->id(($id+50)%0xffff);
+ $key_name = $key_data;
+ ($key_data, $tname) = split(/ /,$tname)
+ }
+ if (defined($key_name) && defined($key_data)) {
+ my $tsig;
+ # sign the packet
+ print " Signing the data with " .
+ "$key_name/$key_data\n";
+
+ if ($Net::DNS::VERSION < 0.69) {
+ $tsig = Net::DNS::RR->new(
+ "$key_name TSIG $key_data");
+ } elsif ($Net::DNS::VERSION >= 0.81 &&
+ $continuation) {
+ } elsif ($Net::DNS::VERSION >= 0.75 &&
+ $continuation) {
+ $tsig = $prev_tsig;
+ } else {
+ $tsig = Net::DNS::RR->new(
+ name => $key_name,
+ type => 'TSIG',
+ key => $key_data);
+ }
+
+ # These kluges are necessary because Net::DNS
+ # doesn't know how to sign responses. We
+ # clear compnames so that the TSIG key and
+ # algorithm name won't be compressed, and
+ # add one to arcount because the signing
+ # function will attempt to decrement it,
+ # which is incorrect in a response. Finally
+ # we set request_mac to the previous digest.
+ $packet->{"compnames"} = {}
+ if ($Net::DNS::VERSION < 0.70);
+ $packet->{"header"}{"arcount"} += 1
+ if ($Net::DNS::VERSION < 0.70);
+ if (defined($prev_tsig)) {
+ if ($Net::DNS::VERSION < 0.73) {
+ my $rmac = pack('n H*',
+ length($prev_tsig->mac)/2,
+ $prev_tsig->mac);
+ $tsig->{"request_mac"} =
+ unpack("H*", $rmac);
+ } elsif ($Net::DNS::VERSION < 0.81) {
+ $tsig->request_mac(
+ $prev_tsig->mac);
+ }
+ }
+
+ $tsig->sign_func($signer) if defined($signer);
+ $tsig->continuation($continuation) if
+ ($Net::DNS::VERSION >= 0.71 &&
+ $Net::DNS::VERSION <= 0.74 );
+ if ($Net::DNS::VERSION < 0.81) {
+ $packet->sign_tsig($tsig);
+ } elsif ($continuation) {
+ $opaque = $packet->sign_tsig($opaque);
+ } else {
+ $opaque = $packet->sign_tsig($request);
+ }
+ $signer = \&sign_tcp_continuation
+ if ($Net::DNS::VERSION < 0.70);
+ $continuation = 1;
+
+ my $copy =
+ Net::DNS::Packet->new(\($packet->data));
+ $prev_tsig = $copy->pop("additional");
+ }
+
+ #$packet->print;
+ push(@results,$packet->data);
+ if ($tname eq "") {
+ $tname = $qname;
+ }
+ $packet = new Net::DNS::Packet($tname, $qtype, $qclass);
+ $packet->header->qr(1);
+ $packet->header->aa(1);
+ $packet->header->id($id);
+ print " A total of $count_these patterns matched\n";
+ return \@results;
+}
+
+# Main
+my $rin;
+my $rout;
+for (;;) {
+ $rin = '';
+ vec($rin, fileno($ctlsock), 1) = 1;
+ vec($rin, fileno($tcpsock), 1) = 1;
+ vec($rin, fileno($udpsock), 1) = 1;
+
+ select($rout = $rin, undef, undef, undef);
+
+ if (vec($rout, fileno($ctlsock), 1)) {
+ warn "ctl conn";
+ my $conn = $ctlsock->accept;
+ my $rule = ();
+ @rules = ();
+ while (my $line = $conn->getline) {
+ chomp $line;
+ if ($line =~ m!^/(.*)/$!) {
+ if (length($1) == 0) {
+ $udphandler = sub { return; };
+ $tcphandler = sub { return; };
+ } else {
+ $udphandler = \&handleUDP;
+ $tcphandler = \&handleTCP;
+ $rule = { pattern => $1, answer => [] };
+ push(@rules, $rule);
+ }
+ } else {
+ push(@{$rule->{answer}}, $line);
+ }
+ }
+ $conn->close;
+ #print Dumper(@rules);
+ #print "+=+=+ $rules[0]->{'pattern'}\n";
+ #print "+=+=+ $rules[0]->{'answer'}->[0]->{'rname'}\n";
+ #print "+=+=+ $rules[0]->{'answer'}->[0]\n";
+ } elsif (vec($rout, fileno($udpsock), 1)) {
+ printf "UDP request\n";
+ my $buf;
+ $udpsock->recv($buf, 512);
+ my $result = &$udphandler($buf);
+ if (defined($result)) {
+ 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 = &$tcphandler($buf);
+ if (defined($result)) {
+ foreach my $response (@$result) {
+ $len = length($response);
+ $n = $conn->syswrite(pack("n", $len), 2);
+ $n = $conn->syswrite($response, $len);
+ print " Sent: $n chars via TCP\n";
+ }
+ }
+ }
+ $conn->close;
+ }
+}
diff --git a/bin/tests/system/forward/clean.sh b/bin/tests/system/forward/clean.sh
new file mode 100644
index 0000000..6d76bb0
--- /dev/null
+++ b/bin/tests/system/forward/clean.sh
@@ -0,0 +1,26 @@
+#!/bin/sh
+
+# 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.
+
+#
+# Clean up after forward tests.
+#
+rm -f ./dig.out.*
+rm -f ./*/named.conf
+rm -f ./*/named.memstats
+rm -f ./*/named.run ./*/named.run.prev ./*/ans.run
+rm -f ./*/named_dump.db
+rm -f ./ns*/named.lock
+rm -f ./ns*/managed-keys.bind*
+rm -f ./ns1/root.db ./ns1/root.db.signed
+rm -f ./ns*/trusted.conf
+rm -f ./ns1/K* ./ns1/dsset-*
diff --git a/bin/tests/system/forward/ns1/diditwork.net.db b/bin/tests/system/forward/ns1/diditwork.net.db
new file mode 100644
index 0000000..fd9a46e
--- /dev/null
+++ b/bin/tests/system/forward/ns1/diditwork.net.db
@@ -0,0 +1,22 @@
+; 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 300 ; 5 minutes
+@ IN SOA ns root (
+ 2000082401 ; serial
+ 1800 ; refresh (30 minutes)
+ 1800 ; retry (30 minutes)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ TXT "recursed"
+ns A 10.53.0.1
diff --git a/bin/tests/system/forward/ns1/example.db b/bin/tests/system/forward/ns1/example.db
new file mode 100644
index 0000000..aac1bef
--- /dev/null
+++ b/bin/tests/system/forward/ns1/example.db
@@ -0,0 +1,23 @@
+; 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 300 ; 5 minutes
+@ IN SOA ns root (
+ 2000082401 ; serial
+ 1800 ; refresh (30 minutes)
+ 1800 ; retry (30 minutes)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.1
+
+txt TXT "recursed"
diff --git a/bin/tests/system/forward/ns1/named.conf.in b/bin/tests/system/forward/ns1/named.conf.in
new file mode 100644
index 0000000..f871fd6
--- /dev/null
+++ b/bin/tests/system/forward/ns1/named.conf.in
@@ -0,0 +1,87 @@
+/*
+ * 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.
+ */
+
+options {
+ query-source address 10.53.0.1;
+ query-source-v6 address fd92:7065:b8e:ffff::1;
+ notify-source 10.53.0.1;
+ notify-source-v6 fd92:7065:b8e:ffff::1;
+ transfer-source 10.53.0.1;
+ transfer-source-v6 fd92:7065:b8e:ffff::1;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.1; };
+ listen-on-v6 { fd92:7065:b8e:ffff::1; };
+ recursion no;
+ dnssec-validation no;
+};
+
+zone "." {
+ type primary;
+ file "root.db.signed";
+};
+
+zone "example1." {
+ type primary;
+ file "example.db";
+};
+
+zone "example2." {
+ type primary;
+ file "example.db";
+};
+
+zone "example3." {
+ type primary;
+ file "example.db";
+};
+
+zone "example4." {
+ type primary;
+ file "example.db";
+};
+
+zone "example5." {
+ type primary;
+ file "example.db";
+};
+
+zone "sld.tld" {
+ type primary;
+ file "sld.tld.db";
+};
+
+/* A forward zone without forwarders. */
+zone "example6" {
+ type forward;
+};
+
+zone "diditwork.net" {
+ type primary;
+ file "diditwork.net.db";
+};
+
+zone "spoofed.net" {
+ type primary;
+ file "spoofed.net.db";
+};
+
+zone "sub.local.net" {
+ type primary;
+ file "sub.local.net.db";
+};
+
+zone "net.example.lll" {
+ type master;
+ file "net.example.lll";
+};
diff --git a/bin/tests/system/forward/ns1/net.example.lll b/bin/tests/system/forward/ns1/net.example.lll
new file mode 100644
index 0000000..ba0804f
--- /dev/null
+++ b/bin/tests/system/forward/ns1/net.example.lll
@@ -0,0 +1,15 @@
+; 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 86400
+net.example.lll. SOA . . 0 0 0 0 0
+net.example.lll. NS attackSecureDomain.net.
+didItWork.net.example.lll. TXT "if you can see this record the attack worked"
diff --git a/bin/tests/system/forward/ns1/root.db.in b/bin/tests/system/forward/ns1/root.db.in
new file mode 100644
index 0000000..95ffac3
--- /dev/null
+++ b/bin/tests/system/forward/ns1/root.db.in
@@ -0,0 +1,36 @@
+; 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 300
+. IN SOA gson.nominum.com. a.root.servers.nil. (
+ 2000042100 ; serial
+ 600 ; refresh
+ 600 ; retry
+ 1200 ; expire
+ 600 ; minimum
+ )
+. NS a.root-servers.nil.
+a.root-servers.nil. A 10.53.0.1
+
+example1 NS ns.example1
+ns.example1 A 10.53.0.1
+
+example2 NS ns.example2
+ns.example2 A 10.53.0.1
+
+example3 NS ns.example3
+ns.example3 A 10.53.0.1
+
+example7 NS ns.example7
+ns.example7 A 10.53.0.2
+
+tld NS ns.tld
+ns.tld A 10.53.0.2
diff --git a/bin/tests/system/forward/ns1/sign.sh b/bin/tests/system/forward/ns1/sign.sh
new file mode 100644
index 0000000..0888c5f
--- /dev/null
+++ b/bin/tests/system/forward/ns1/sign.sh
@@ -0,0 +1,34 @@
+#!/bin/sh -e
+
+# 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.
+
+# shellcheck source=conf.sh
+. ../../conf.sh
+
+set -e
+
+zone=.
+infile=root.db.in
+zonefile=root.db
+
+echo_i "ns1/sign.sh"
+
+ksk=$("$KEYGEN" -q -fk -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone")
+zsk=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone")
+
+cat "$infile" "$ksk.key" "$zsk.key" > "$zonefile"
+
+"$SIGNER" -P -g -o "$zone" "$zonefile" > /dev/null 2>&1
+
+# Configure the resolving server with a static key.
+keyfile_to_static_ds "$ksk" > trusted.conf
+cp trusted.conf ../ns3/trusted.conf
diff --git a/bin/tests/system/forward/ns1/sld.tld.db b/bin/tests/system/forward/ns1/sld.tld.db
new file mode 100644
index 0000000..f0d4b05
--- /dev/null
+++ b/bin/tests/system/forward/ns1/sld.tld.db
@@ -0,0 +1,22 @@
+; 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 300 ; 5 minutes
+@ IN SOA ns root (
+ 2000082401 ; serial
+ 1800 ; refresh (30 minutes)
+ 1800 ; retry (30 minutes)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.1
+xxx TXT "foo"
diff --git a/bin/tests/system/forward/ns1/spoofed.net.db b/bin/tests/system/forward/ns1/spoofed.net.db
new file mode 100644
index 0000000..eedc46f
--- /dev/null
+++ b/bin/tests/system/forward/ns1/spoofed.net.db
@@ -0,0 +1,22 @@
+; 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 300 ; 5 minutes
+@ IN SOA ns root (
+ 2000082401 ; serial
+ 1800 ; refresh (30 minutes)
+ 1800 ; retry (30 minutes)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.1
+sub TXT "recursed"
diff --git a/bin/tests/system/forward/ns1/sub.local.net.db b/bin/tests/system/forward/ns1/sub.local.net.db
new file mode 100644
index 0000000..fd9a46e
--- /dev/null
+++ b/bin/tests/system/forward/ns1/sub.local.net.db
@@ -0,0 +1,22 @@
+; 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 300 ; 5 minutes
+@ IN SOA ns root (
+ 2000082401 ; serial
+ 1800 ; refresh (30 minutes)
+ 1800 ; retry (30 minutes)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ TXT "recursed"
+ns A 10.53.0.1
diff --git a/bin/tests/system/forward/ns10/fakenet.zone b/bin/tests/system/forward/ns10/fakenet.zone
new file mode 100644
index 0000000..b655a32
--- /dev/null
+++ b/bin/tests/system/forward/ns10/fakenet.zone
@@ -0,0 +1,17 @@
+; 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 86400
+net. SOA . . 0 0 0 0 0
+net. NS attackSecureDomain.net.
+attackSecureDomain.net. A 10.53.0.10
+didItWork.net. TXT "if you can see this record the attack worked"
+ns.spoofed.net. A 10.53.0.10
diff --git a/bin/tests/system/forward/ns10/fakenet2.zone b/bin/tests/system/forward/ns10/fakenet2.zone
new file mode 100644
index 0000000..cd1e6e9
--- /dev/null
+++ b/bin/tests/system/forward/ns10/fakenet2.zone
@@ -0,0 +1,15 @@
+; 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 86400
+net2. SOA . . 0 0 0 0 0
+net2. NS attackSecureDomain.net.
+net2. DNAME net.example.lll.
diff --git a/bin/tests/system/forward/ns10/fakesublocalnet.zone b/bin/tests/system/forward/ns10/fakesublocalnet.zone
new file mode 100644
index 0000000..160b533
--- /dev/null
+++ b/bin/tests/system/forward/ns10/fakesublocalnet.zone
@@ -0,0 +1,15 @@
+; 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 86400
+sub.local.net. SOA . . 0 0 0 0 0
+sub.local.net. NS ns.spoofed.net.
+sub.local.net. TXT "if you see this attacker overrode local delegation"
diff --git a/bin/tests/system/forward/ns10/fakesublocaltld.zone b/bin/tests/system/forward/ns10/fakesublocaltld.zone
new file mode 100644
index 0000000..f78cbc7
--- /dev/null
+++ b/bin/tests/system/forward/ns10/fakesublocaltld.zone
@@ -0,0 +1,15 @@
+; 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.
+
+sub.local.tld. 3600 IN SOA . . 0 0 0 0 0
+sub.local.tld. 3600 IN NS ns.sub.local.tld.
+sub.local.tld. 3600 IN TXT bad
+ns.sub.local.tld. 3600 IN A 10.53.0.8
diff --git a/bin/tests/system/forward/ns10/named.conf.in b/bin/tests/system/forward/ns10/named.conf.in
new file mode 100644
index 0000000..8148d9e
--- /dev/null
+++ b/bin/tests/system/forward/ns10/named.conf.in
@@ -0,0 +1,54 @@
+/*
+ * 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.
+ */
+
+options {
+ query-source address 10.53.0.10;
+ notify-source 10.53.0.10;
+ transfer-source 10.53.0.10;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.10; };
+ listen-on-v6 { none; };
+ minimal-responses no;
+ dnssec-validation no;
+};
+
+zone "net." {
+ type master;
+ file "fakenet.zone";
+};
+
+zone "spoofed.net." {
+ type master;
+ file "spoofednet.zone";
+};
+
+zone "sub.local.net." {
+ type master;
+ file "fakesublocalnet.zone";
+};
+
+zone "net2" {
+ type master;
+ file "fakenet2.zone";
+};
+
+zone "net.example.lll" {
+ type master;
+ file "net.example.lll";
+};
+
+zone "sub.local.tld." {
+ type master;
+ file "fakesublocaltld.zone";
+};
diff --git a/bin/tests/system/forward/ns10/net.example.lll b/bin/tests/system/forward/ns10/net.example.lll
new file mode 100644
index 0000000..ba0804f
--- /dev/null
+++ b/bin/tests/system/forward/ns10/net.example.lll
@@ -0,0 +1,15 @@
+; 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 86400
+net.example.lll. SOA . . 0 0 0 0 0
+net.example.lll. NS attackSecureDomain.net.
+didItWork.net.example.lll. TXT "if you can see this record the attack worked"
diff --git a/bin/tests/system/forward/ns10/spoofednet.zone b/bin/tests/system/forward/ns10/spoofednet.zone
new file mode 100644
index 0000000..fb70a43
--- /dev/null
+++ b/bin/tests/system/forward/ns10/spoofednet.zone
@@ -0,0 +1,16 @@
+; 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 86400
+spoofed.net. SOA . . 0 0 0 0 0
+spoofed.net. NS ns.spoofed.net.
+ns.spoofed.net. A 10.53.0.10
+spoofed.net. TXT "this record is clearly spoofed"
diff --git a/bin/tests/system/forward/ns2/example.db b/bin/tests/system/forward/ns2/example.db
new file mode 100644
index 0000000..df3e52c
--- /dev/null
+++ b/bin/tests/system/forward/ns2/example.db
@@ -0,0 +1,23 @@
+; 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 300 ; 5 minutes
+@ IN SOA ns root (
+ 2000082401 ; serial
+ 1800 ; refresh (30 minutes)
+ 1800 ; retry (30 minutes)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.1
+
+txt TXT "forwarded"
diff --git a/bin/tests/system/forward/ns2/named.conf.in b/bin/tests/system/forward/ns2/named.conf.in
new file mode 100644
index 0000000..f9a081a
--- /dev/null
+++ b/bin/tests/system/forward/ns2/named.conf.in
@@ -0,0 +1,72 @@
+/*
+ * 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.
+ */
+
+options {
+ query-source address 10.53.0.2;
+ query-source-v6 address fd92:7065:b8e:ffff::2;
+ notify-source 10.53.0.2;
+ notify-source-v6 fd92:7065:b8e:ffff::2;
+ transfer-source 10.53.0.2;
+ transfer-source-v6 fd92:7065:b8e:ffff::2;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.2; };
+ listen-on-v6 { fd92:7065:b8e:ffff::2; };
+ recursion no;
+ dnssec-validation no;
+};
+
+zone "." {
+ type hint;
+ file "root.db";
+};
+
+zone "example1." {
+ type primary;
+ file "example.db";
+};
+
+zone "example2." {
+ type primary;
+ file "example.db";
+};
+
+zone "example3." {
+ type primary;
+ file "example.db";
+};
+
+zone "example4." {
+ type primary;
+ file "example.db";
+};
+
+zone "example7." {
+ type primary;
+ file "example.db";
+};
+
+zone "grafted." {
+ type primary;
+ file "example.db";
+};
+
+zone "1.0.10.in-addr.arpa." {
+ type primary;
+ file "example.db";
+};
+
+zone "tld" {
+ type primary;
+ file "tld.db";
+};
diff --git a/bin/tests/system/forward/ns2/root.db b/bin/tests/system/forward/ns2/root.db
new file mode 100644
index 0000000..7108723
--- /dev/null
+++ b/bin/tests/system/forward/ns2/root.db
@@ -0,0 +1,30 @@
+; 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 300
+. IN SOA gson.nominum.com. a.root.servers.nil. (
+ 2000042100 ; serial
+ 600 ; refresh
+ 600 ; retry
+ 1200 ; expire
+ 600 ; minimum
+ )
+. NS a.root-servers.nil.
+a.root-servers.nil. A 10.53.0.1
+
+example1 NS ns.example1
+ns.example1 A 10.53.0.1
+
+example2 NS ns.example2
+ns.example2 A 10.53.0.1
+
+example3 NS ns.example3
+ns.example3 A 10.53.0.1
diff --git a/bin/tests/system/forward/ns2/tld.db b/bin/tests/system/forward/ns2/tld.db
new file mode 100644
index 0000000..965f2a4
--- /dev/null
+++ b/bin/tests/system/forward/ns2/tld.db
@@ -0,0 +1,29 @@
+; 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 300 ; 5 minutes
+@ IN SOA ns root (
+ 2000082401 ; serial
+ 1800 ; refresh (30 minutes)
+ 1800 ; retry (30 minutes)
+ 1814400 ; expire (3 weeks)
+ 3600 ; minimum (1 hour)
+ )
+ NS ns
+ns A 10.53.0.2
+sld NS ns.sld
+ns.sld A 10.53.0.1
+local NS ns.local
+ns.local A 10.53.0.9
+sibling NS ns.sibling
+ns.sibling A 10.53.0.4
+sibling NS ns.sub.local
+ns.sub.local A 10.53.0.10
diff --git a/bin/tests/system/forward/ns3/named1.conf.in b/bin/tests/system/forward/ns3/named1.conf.in
new file mode 100644
index 0000000..ffc0718
--- /dev/null
+++ b/bin/tests/system/forward/ns3/named1.conf.in
@@ -0,0 +1,66 @@
+/*
+ * 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.
+ */
+
+options {
+ query-source address 10.53.0.3;
+ query-source-v6 address fd92:7065:b8e:ffff::3;
+ notify-source 10.53.0.3;
+ notify-source-v6 fd92:7065:b8e:ffff::3;
+ transfer-source 10.53.0.3;
+ transfer-source-v6 fd92:7065:b8e:ffff::3;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.3; };
+ listen-on-v6 { fd92:7065:b8e:ffff::3; };
+ forwarders { fd92:7065:b8e:ffff::2; };
+ forward first;
+ dnssec-validation yes;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "." {
+ type hint;
+ file "root.db";
+};
+
+zone "example1." {
+ type forward;
+ forward first;
+ forwarders { 10.53.0.2; };
+};
+
+zone "example2." {
+ type forward;
+ forward first;
+ forwarders { };
+};
+
+zone "example3." {
+ type forward;
+ forward only;
+ forwarders { };
+};
+
+zone "example7." {
+ type forward;
+ forward first;
+ forwarders { 10.53.0.6; };
+};
diff --git a/bin/tests/system/forward/ns3/named2.conf.in b/bin/tests/system/forward/ns3/named2.conf.in
new file mode 100644
index 0000000..986a60e
--- /dev/null
+++ b/bin/tests/system/forward/ns3/named2.conf.in
@@ -0,0 +1,43 @@
+/*
+ * 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.
+ */
+
+options {
+ query-source address 10.53.0.3;
+ query-source-v6 address fd92:7065:b8e:ffff::3;
+ notify-source 10.53.0.3;
+ notify-source-v6 fd92:7065:b8e:ffff::3;
+ transfer-source 10.53.0.3;
+ transfer-source-v6 fd92:7065:b8e:ffff::3;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.3; };
+ listen-on-v6 { fd92:7065:b8e:ffff::3; };
+ forwarders { 10.53.0.6; };
+ dnssec-validation yes;
+};
+
+include "trusted.conf";
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.3 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+zone "." {
+ type hint;
+ file "root.db";
+};
diff --git a/bin/tests/system/forward/ns3/root.db b/bin/tests/system/forward/ns3/root.db
new file mode 100644
index 0000000..7108723
--- /dev/null
+++ b/bin/tests/system/forward/ns3/root.db
@@ -0,0 +1,30 @@
+; 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 300
+. IN SOA gson.nominum.com. a.root.servers.nil. (
+ 2000042100 ; serial
+ 600 ; refresh
+ 600 ; retry
+ 1200 ; expire
+ 600 ; minimum
+ )
+. NS a.root-servers.nil.
+a.root-servers.nil. A 10.53.0.1
+
+example1 NS ns.example1
+ns.example1 A 10.53.0.1
+
+example2 NS ns.example2
+ns.example2 A 10.53.0.1
+
+example3 NS ns.example3
+ns.example3 A 10.53.0.1
diff --git a/bin/tests/system/forward/ns3/root2.db b/bin/tests/system/forward/ns3/root2.db
new file mode 100644
index 0000000..40586f0
--- /dev/null
+++ b/bin/tests/system/forward/ns3/root2.db
@@ -0,0 +1,21 @@
+; 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 300
+. IN SOA gson.nominum.com. a.root.servers.nil. (
+ 2000042100 ; serial
+ 600 ; refresh
+ 600 ; retry
+ 1200 ; expire
+ 600 ; minimum
+ )
+. NS a.root-servers.nil.
+a.root-servers.nil. A 10.53.0.11
diff --git a/bin/tests/system/forward/ns4/malicious.db b/bin/tests/system/forward/ns4/malicious.db
new file mode 100644
index 0000000..e4859c1
--- /dev/null
+++ b/bin/tests/system/forward/ns4/malicious.db
@@ -0,0 +1,24 @@
+; 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 86400
+@ IN SOA malicious. admin.malicious. (
+ 1 ; Serial
+ 604800 ; Refresh
+ 86400 ; Retry
+ 2419200 ; Expire
+ 86400 ) ; Negative Cache TTL
+
+@ IN NS ns
+
+ns IN A 10.53.0.4
+
+target IN CNAME subdomain.rebind.
diff --git a/bin/tests/system/forward/ns4/named.conf.in b/bin/tests/system/forward/ns4/named.conf.in
new file mode 100644
index 0000000..c97823d
--- /dev/null
+++ b/bin/tests/system/forward/ns4/named.conf.in
@@ -0,0 +1,69 @@
+/*
+ * 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.
+ */
+
+options {
+ query-source address 10.53.0.4;
+ notify-source 10.53.0.4;
+ transfer-source 10.53.0.4;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.4; };
+ listen-on-v6 { none; };
+ recursion yes;
+ dnssec-validation yes;
+ minimal-responses yes;
+};
+
+zone "." {
+ type hint;
+ file "root.db";
+};
+
+zone "example1." {
+ type forward;
+ forward first;
+ forwarders { 10.53.0.2; };
+};
+
+zone "example3." {
+ type forward;
+ forwarders { 10.53.0.2; };
+};
+
+zone "example5." {
+ type forward;
+ forward only;
+ forwarders { 10.53.0.2; };
+};
+
+zone "1.0.10.in-addr.arpa" {
+ type forward;
+ forward only;
+ forwarders { 10.53.0.2; };
+};
+
+zone "grafted" {
+ type forward;
+ forward only;
+ forwarders { 10.53.0.2; };
+};
+
+zone "malicious." {
+ type primary;
+ file "malicious.db";
+};
+
+zone "sibling.tld" {
+ type primary;
+ file "sibling.tld.db";
+};
diff --git a/bin/tests/system/forward/ns4/root.db b/bin/tests/system/forward/ns4/root.db
new file mode 100644
index 0000000..7108723
--- /dev/null
+++ b/bin/tests/system/forward/ns4/root.db
@@ -0,0 +1,30 @@
+; 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 300
+. IN SOA gson.nominum.com. a.root.servers.nil. (
+ 2000042100 ; serial
+ 600 ; refresh
+ 600 ; retry
+ 1200 ; expire
+ 600 ; minimum
+ )
+. NS a.root-servers.nil.
+a.root-servers.nil. A 10.53.0.1
+
+example1 NS ns.example1
+ns.example1 A 10.53.0.1
+
+example2 NS ns.example2
+ns.example2 A 10.53.0.1
+
+example3 NS ns.example3
+ns.example3 A 10.53.0.1
diff --git a/bin/tests/system/forward/ns4/sibling.tld.db b/bin/tests/system/forward/ns4/sibling.tld.db
new file mode 100644
index 0000000..fe080ae
--- /dev/null
+++ b/bin/tests/system/forward/ns4/sibling.tld.db
@@ -0,0 +1,22 @@
+; 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 86400
+@ IN SOA malicious. admin.malicious. (
+ 1 ; Serial
+ 604800 ; Refresh
+ 86400 ; Retry
+ 2419200 ; Expire
+ 86400 ) ; Negative Cache TTL
+
+@ IN NS ns
+
+ns IN A 10.53.0.4
diff --git a/bin/tests/system/forward/ns5/named.conf.in b/bin/tests/system/forward/ns5/named.conf.in
new file mode 100644
index 0000000..024f49b
--- /dev/null
+++ b/bin/tests/system/forward/ns5/named.conf.in
@@ -0,0 +1,36 @@
+/*
+ * 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.
+ */
+
+options {
+ query-source address 10.53.0.5;
+ notify-source 10.53.0.5;
+ transfer-source 10.53.0.5;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.5; };
+ listen-on-v6 { none; };
+ forward only;
+ forwarders { 10.53.0.4; };
+ deny-answer-aliases { "rebind"; };
+ dnssec-validation yes;
+};
+
+zone "." {
+ type hint;
+ file "root.db";
+};
+
+zone "rebind" {
+ type primary;
+ file "rebind.db";
+};
diff --git a/bin/tests/system/forward/ns5/rebind.db b/bin/tests/system/forward/ns5/rebind.db
new file mode 100644
index 0000000..aed6c2e
--- /dev/null
+++ b/bin/tests/system/forward/ns5/rebind.db
@@ -0,0 +1,24 @@
+; 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 86400
+@ IN SOA rebind. admin.rebind. (
+ 1 ; Serial
+ 604800 ; Refresh
+ 86400 ; Retry
+ 2419200 ; Expire
+ 86400 ) ; Negative Cache TTL
+
+@ IN NS ns
+
+ns IN A 10.53.0.5
+
+subdomain IN A 10.53.0.1
diff --git a/bin/tests/system/forward/ns5/root.db b/bin/tests/system/forward/ns5/root.db
new file mode 100644
index 0000000..7108723
--- /dev/null
+++ b/bin/tests/system/forward/ns5/root.db
@@ -0,0 +1,30 @@
+; 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 300
+. IN SOA gson.nominum.com. a.root.servers.nil. (
+ 2000042100 ; serial
+ 600 ; refresh
+ 600 ; retry
+ 1200 ; expire
+ 600 ; minimum
+ )
+. NS a.root-servers.nil.
+a.root-servers.nil. A 10.53.0.1
+
+example1 NS ns.example1
+ns.example1 A 10.53.0.1
+
+example2 NS ns.example2
+ns.example2 A 10.53.0.1
+
+example3 NS ns.example3
+ns.example3 A 10.53.0.1
diff --git a/bin/tests/system/forward/ns7/named.conf.in b/bin/tests/system/forward/ns7/named.conf.in
new file mode 100644
index 0000000..302bb55
--- /dev/null
+++ b/bin/tests/system/forward/ns7/named.conf.in
@@ -0,0 +1,30 @@
+/*
+ * 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.
+ */
+
+options {
+ query-source address 10.53.0.7;
+ notify-source 10.53.0.7;
+ transfer-source 10.53.0.7;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.7; };
+ listen-on-v6 { none; };
+ forwarders { 10.53.0.4; };
+ forward first;
+ dnssec-validation yes;
+};
+
+zone "." {
+ type hint;
+ file "root.db";
+};
diff --git a/bin/tests/system/forward/ns7/root.db b/bin/tests/system/forward/ns7/root.db
new file mode 100644
index 0000000..7108723
--- /dev/null
+++ b/bin/tests/system/forward/ns7/root.db
@@ -0,0 +1,30 @@
+; 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 300
+. IN SOA gson.nominum.com. a.root.servers.nil. (
+ 2000042100 ; serial
+ 600 ; refresh
+ 600 ; retry
+ 1200 ; expire
+ 600 ; minimum
+ )
+. NS a.root-servers.nil.
+a.root-servers.nil. A 10.53.0.1
+
+example1 NS ns.example1
+ns.example1 A 10.53.0.1
+
+example2 NS ns.example2
+ns.example2 A 10.53.0.1
+
+example3 NS ns.example3
+ns.example3 A 10.53.0.1
diff --git a/bin/tests/system/forward/ns8/named.conf.in b/bin/tests/system/forward/ns8/named.conf.in
new file mode 100644
index 0000000..2de656f
--- /dev/null
+++ b/bin/tests/system/forward/ns8/named.conf.in
@@ -0,0 +1,35 @@
+/*
+ * 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.
+ */
+
+options {
+ query-source address 10.53.0.8;
+ notify-source 10.53.0.8;
+ transfer-source 10.53.0.8;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.8; };
+ listen-on-v6 { none; };
+ forwarders { 10.53.0.2; }; // returns referrals
+ forward first;
+ dnssec-validation yes;
+};
+
+zone "." {
+ type hint;
+ file "root.db";
+};
+
+zone "sub.local.tld" {
+ type primary;
+ file "sub.local.tld.db";
+};
diff --git a/bin/tests/system/forward/ns8/root.db b/bin/tests/system/forward/ns8/root.db
new file mode 100644
index 0000000..2cbdff5
--- /dev/null
+++ b/bin/tests/system/forward/ns8/root.db
@@ -0,0 +1,13 @@
+; 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.
+
+. NS a.root-servers.nil.
+a.root-servers.nil. A 10.53.0.1
diff --git a/bin/tests/system/forward/ns8/sub.local.tld.db b/bin/tests/system/forward/ns8/sub.local.tld.db
new file mode 100644
index 0000000..f2234c7
--- /dev/null
+++ b/bin/tests/system/forward/ns8/sub.local.tld.db
@@ -0,0 +1,15 @@
+; 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.
+
+sub.local.tld. 3600 IN SOA . . 0 0 0 0 0
+sub.local.tld. 3600 IN NS ns.sub.local.tld.
+sub.local.tld. 3600 IN TXT good
+ns.sub.local.tld. 3600 IN A 10.53.0.8
diff --git a/bin/tests/system/forward/ns9/local.net.db b/bin/tests/system/forward/ns9/local.net.db
new file mode 100644
index 0000000..af0d2a5
--- /dev/null
+++ b/bin/tests/system/forward/ns9/local.net.db
@@ -0,0 +1,16 @@
+; 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.
+
+local.net. 3600 IN SOA . . 0 0 0 0 0
+local.net. 3600 IN NS localhost.
+ns.local.net. 3600 IN A 10.53.0.9
+txt.local.net. 3600 IN TXT "something in the local auth zone"
+sub.local.net. 3600 IN NS ns.spoofed.net. ; attacker will try to override this
diff --git a/bin/tests/system/forward/ns9/local.tld.db b/bin/tests/system/forward/ns9/local.tld.db
new file mode 100644
index 0000000..876a913
--- /dev/null
+++ b/bin/tests/system/forward/ns9/local.tld.db
@@ -0,0 +1,15 @@
+; 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.
+
+local.tld. 3600 IN SOA . . 0 0 0 0 0
+local.tld. 3600 IN NS localhost.
+sub.local.tld. 3600 IN NS ns.sub.local.tld.
+ns.sub.local.tld. 3600 IN A 10.53.0.8
diff --git a/bin/tests/system/forward/ns9/named1.conf.in b/bin/tests/system/forward/ns9/named1.conf.in
new file mode 100644
index 0000000..54fed8f
--- /dev/null
+++ b/bin/tests/system/forward/ns9/named1.conf.in
@@ -0,0 +1,67 @@
+/*
+ * 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.
+ */
+
+options {
+ query-source address 10.53.0.9;
+ notify-source 10.53.0.9;
+ transfer-source 10.53.0.9;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.9; };
+ listen-on-v6 { none; };
+ dnssec-validation no;
+ edns-udp-size 1232;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.9 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+server 10.53.0.10 {
+ edns no;
+};
+
+server 10.53.0.11 {
+ edns no;
+};
+
+zone "." {
+ type hint;
+ file "root.db";
+};
+
+zone "attacksecuredomain.net." {
+ type forward;
+ forwarders { 10.53.0.10; };
+};
+
+zone "attacksecuredomain.net2." {
+ type forward;
+ forwarders { 10.53.0.10; };
+};
+
+zone "attacksecuredomain.net3." {
+ type forward;
+ forwarders { 10.53.0.11; };
+};
+
+zone "local.net." {
+ type primary;
+ file "local.net.db";
+ forwarders {};
+};
diff --git a/bin/tests/system/forward/ns9/named2.conf.in b/bin/tests/system/forward/ns9/named2.conf.in
new file mode 100644
index 0000000..34f7eea
--- /dev/null
+++ b/bin/tests/system/forward/ns9/named2.conf.in
@@ -0,0 +1,70 @@
+/*
+ * 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.
+ */
+
+options {
+ query-source address 10.53.0.9;
+ notify-source 10.53.0.9;
+ transfer-source 10.53.0.9;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.9; };
+ listen-on-v6 { none; };
+ dnssec-validation no;
+ edns-udp-size 1232;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.9 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+server 10.53.0.10 {
+ edns no;
+};
+
+server 10.53.0.11 {
+ edns no;
+};
+
+zone "." {
+ type hint;
+ file "root.db";
+};
+
+zone "attacksecuredomain.net." {
+ type forward;
+ forward only;
+ forwarders { 10.53.0.10; };
+};
+
+zone "attacksecuredomain.net2." {
+ type forward;
+ forward only;
+ forwarders { 10.53.0.10; };
+};
+
+zone "attacksecuredomain.net3." {
+ type forward;
+ forward only;
+ forwarders { 10.53.0.11; };
+};
+
+zone "local.net." {
+ type primary;
+ file "local.net.db";
+ forwarders {};
+};
diff --git a/bin/tests/system/forward/ns9/named3.conf.in b/bin/tests/system/forward/ns9/named3.conf.in
new file mode 100644
index 0000000..c07281f
--- /dev/null
+++ b/bin/tests/system/forward/ns9/named3.conf.in
@@ -0,0 +1,50 @@
+/*
+ * 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.
+ */
+
+options {
+ query-source address 10.53.0.9;
+ notify-source 10.53.0.9;
+ transfer-source 10.53.0.9;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.9; };
+ listen-on-v6 { none; };
+ dnssec-validation no;
+ edns-udp-size 1232;
+ forward only;
+ forwarders { 10.53.0.10; };
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.9 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+server 10.53.0.10 {
+ edns no;
+};
+
+zone "." {
+ type hint;
+ file "root.db";
+};
+
+zone "local.net." {
+ type primary;
+ file "local.net.db";
+ forwarders {};
+};
diff --git a/bin/tests/system/forward/ns9/named4.conf.in b/bin/tests/system/forward/ns9/named4.conf.in
new file mode 100644
index 0000000..c06b361
--- /dev/null
+++ b/bin/tests/system/forward/ns9/named4.conf.in
@@ -0,0 +1,47 @@
+/*
+ * 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.
+ */
+
+options {
+ query-source address 10.53.0.9;
+ notify-source 10.53.0.9;
+ transfer-source 10.53.0.9;
+ port @PORT@;
+ pid-file "named.pid";
+ listen-on { 10.53.0.9; };
+ listen-on-v6 { none; };
+ dnssec-validation no;
+ edns-udp-size 1232;
+};
+
+key rndc_key {
+ secret "1234abcd8765";
+ algorithm @DEFAULT_HMAC@;
+};
+
+controls {
+ inet 10.53.0.9 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
+};
+
+server 10.53.0.10 {
+ edns no;
+};
+
+zone "." {
+ type hint;
+ file "root.db";
+};
+
+zone "local.tld." {
+ type primary;
+ file "local.tld.db";
+};
diff --git a/bin/tests/system/forward/ns9/root.db b/bin/tests/system/forward/ns9/root.db
new file mode 100644
index 0000000..2cbdff5
--- /dev/null
+++ b/bin/tests/system/forward/ns9/root.db
@@ -0,0 +1,13 @@
+; 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.
+
+. NS a.root-servers.nil.
+a.root-servers.nil. A 10.53.0.1
diff --git a/bin/tests/system/forward/rfc1918-inherited.conf b/bin/tests/system/forward/rfc1918-inherited.conf
new file mode 100644
index 0000000..66569dc
--- /dev/null
+++ b/bin/tests/system/forward/rfc1918-inherited.conf
@@ -0,0 +1,17 @@
+/*
+ * 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.
+ */
+
+zone 10.in-addr.arpa {
+ type forward;
+ forwarders { 1.2.3.4; };
+};
diff --git a/bin/tests/system/forward/rfc1918-notinherited.conf b/bin/tests/system/forward/rfc1918-notinherited.conf
new file mode 100644
index 0000000..d6d5c2d
--- /dev/null
+++ b/bin/tests/system/forward/rfc1918-notinherited.conf
@@ -0,0 +1,18 @@
+/*
+ * 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.
+ */
+
+zone 10.in-addr.arpa {
+ type forward;
+ forward first;
+ forwarders { 1.2.3.4; };
+};
diff --git a/bin/tests/system/forward/setup.sh b/bin/tests/system/forward/setup.sh
new file mode 100644
index 0000000..09624ca
--- /dev/null
+++ b/bin/tests/system/forward/setup.sh
@@ -0,0 +1,30 @@
+#!/bin/sh
+
+# 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.
+
+. ../conf.sh
+
+$SHELL clean.sh
+copy_setports ns1/named.conf.in ns1/named.conf
+copy_setports ns2/named.conf.in ns2/named.conf
+copy_setports ns3/named1.conf.in ns3/named.conf
+copy_setports ns4/named.conf.in ns4/named.conf
+copy_setports ns5/named.conf.in ns5/named.conf
+copy_setports ns7/named.conf.in ns7/named.conf
+copy_setports ns8/named.conf.in ns8/named.conf
+copy_setports ns9/named1.conf.in ns9/named.conf
+copy_setports ns10/named.conf.in ns10/named.conf
+
+(
+ cd ns1
+ $SHELL sign.sh
+)
diff --git a/bin/tests/system/forward/tests.sh b/bin/tests/system/forward/tests.sh
new file mode 100644
index 0000000..4037f22
--- /dev/null
+++ b/bin/tests/system/forward/tests.sh
@@ -0,0 +1,406 @@
+#!/bin/sh
+
+# 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.
+
+set -e
+
+#shellcheck source=conf.sh
+. ../conf.sh
+
+dig_with_opts() (
+ "$DIG" -p "$PORT" "$@"
+)
+
+sendcmd() (
+ send "$1" "$EXTRAPORT1"
+)
+
+rndccmd() {
+ "$RNDC" -c ../common/rndc.conf -p "$CONTROLPORT" -s "$@"
+}
+
+root=10.53.0.1
+hidden=10.53.0.2
+f1=10.53.0.3
+f2=10.53.0.4
+
+status=0
+n=0
+
+n=$((n+1))
+echo_i "checking that a forward zone overrides global forwarders ($n)"
+ret=0
+dig_with_opts +noadd +noauth txt.example1. txt @$hidden > dig.out.$n.hidden || ret=1
+dig_with_opts +noadd +noauth txt.example1. txt @$f1 > dig.out.$n.f1 || ret=1
+digcomp dig.out.$n.hidden dig.out.$n.f1 || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking that a forward first zone no forwarders recurses ($n)"
+ret=0
+dig_with_opts +noadd +noauth txt.example2. txt @$root > dig.out.$n.root || ret=1
+dig_with_opts +noadd +noauth txt.example2. txt @$f1 > dig.out.$n.f1 || ret=1
+digcomp dig.out.$n.root dig.out.$n.f1 || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking that a forward only zone no forwarders fails ($n)"
+ret=0
+dig_with_opts +noadd +noauth txt.example2. txt @$root > dig.out.$n.root || ret=1
+dig_with_opts +noadd +noauth txt.example2. txt @$f1 > dig.out.$n.f1 || ret=1
+digcomp dig.out.$n.root dig.out.$n.f1 || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking that global forwarders work ($n)"
+ret=0
+dig_with_opts +noadd +noauth txt.example4. txt @$hidden > dig.out.$n.hidden || ret=1
+dig_with_opts +noadd +noauth txt.example4. txt @$f1 > dig.out.$n.f1 || ret=1
+digcomp dig.out.$n.hidden dig.out.$n.f1 || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking that a forward zone works ($n)"
+ret=0
+dig_with_opts +noadd +noauth txt.example1. txt @$hidden > dig.out.$n.hidden || ret=1
+dig_with_opts +noadd +noauth txt.example1. txt @$f2 > dig.out.$n.f2 || ret=1
+digcomp dig.out.$n.hidden dig.out.$n.f2 || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking that forwarding doesn't spontaneously happen ($n)"
+ret=0
+dig_with_opts +noadd +noauth txt.example2. txt @$root > dig.out.$n.root || ret=1
+dig_with_opts +noadd +noauth txt.example2. txt @$f2 > dig.out.$n.f2 || ret=1
+digcomp dig.out.$n.root dig.out.$n.f2 || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking that a forward zone with no specified policy works ($n)"
+ret=0
+dig_with_opts +noadd +noauth txt.example3. txt @$hidden > dig.out.$n.hidden || ret=1
+dig_with_opts +noadd +noauth txt.example3. txt @$f2 > dig.out.$n.f2 || ret=1
+digcomp dig.out.$n.hidden dig.out.$n.f2 || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking that a forward only doesn't recurse ($n)"
+ret=0
+dig_with_opts txt.example5. txt @$f2 > dig.out.$n.f2 || ret=1
+grep "SERVFAIL" dig.out.$n.f2 > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking for negative caching of forwarder response ($n)"
+# prime the cache, shutdown the forwarder then check that we can
+# get the answer from the cache. restart forwarder.
+ret=0
+dig_with_opts nonexist. txt @10.53.0.5 > dig.out.$n.f2 || ret=1
+grep "status: NXDOMAIN" dig.out.$n.f2 > /dev/null || ret=1
+stop_server ns4 || ret=1
+dig_with_opts nonexist. txt @10.53.0.5 > dig.out.$n.f2 || ret=1
+grep "status: NXDOMAIN" dig.out.$n.f2 > /dev/null || ret=1
+start_server --restart --noclean --port "${PORT}" ns4 || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+check_override() (
+ dig_with_opts 1.0.10.in-addr.arpa TXT @10.53.0.4 > dig.out.$n.f2 &&
+ grep "status: NOERROR" dig.out.$n.f2 > /dev/null &&
+ dig_with_opts 2.0.10.in-addr.arpa TXT @10.53.0.4 > dig.out.$n.f2 &&
+ grep "status: NXDOMAIN" dig.out.$n.f2 > /dev/null
+)
+
+n=$((n+1))
+echo_i "checking that forward only zone overrides empty zone ($n)"
+ret=0
+# retry loop in case the server restart above causes transient failure
+retry_quiet 10 check_override || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking that DS lookups for grafting forward zones are isolated ($n)"
+ret=0
+dig_with_opts grafted A @10.53.0.4 > dig.out.$n.q1 || ret=1
+dig_with_opts grafted DS @10.53.0.4 > dig.out.$n.q2 || ret=1
+dig_with_opts grafted A @10.53.0.4 > dig.out.$n.q3 || ret=1
+dig_with_opts grafted AAAA @10.53.0.4 > dig.out.$n.q4 || ret=1
+grep "status: NOERROR" dig.out.$n.q1 > /dev/null || ret=1
+grep "status: NXDOMAIN" dig.out.$n.q2 > /dev/null || ret=1
+grep "status: NOERROR" dig.out.$n.q3 > /dev/null || ret=1
+grep "status: NOERROR" dig.out.$n.q4 > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking that rfc1918 inherited 'forward first;' zones are warned about ($n)"
+ret=0
+$CHECKCONF rfc1918-inherited.conf | grep "forward first;" >/dev/null || ret=1
+$CHECKCONF rfc1918-notinherited.conf | grep "forward first;" >/dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking that ULA inherited 'forward first;' zones are warned about ($n)"
+ret=0
+$CHECKCONF ula-inherited.conf | grep "forward first;" >/dev/null || ret=1
+$CHECKCONF ula-notinherited.conf | grep "forward first;" >/dev/null && ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+count_sent() (
+ logfile="$1"
+ start_pattern="$2"
+ pattern="$3"
+ nextpartpeek "$logfile" | sed -n "/$start_pattern/,/^\$/p" | grep -c "$pattern"
+)
+
+check_sent() (
+ expected="$1"
+ shift
+ count=$(count_sent "$@")
+ [ "$expected" = "$count" ]
+)
+
+wait_for_log() (
+ nextpartpeek "$1" | grep "$2" >/dev/null
+
+)
+
+n=$((n+1))
+echo_i "checking that a forwarder timeout prevents it from being reused in the same fetch context ($n)"
+ret=0
+# Make ans6 receive queries without responding to them.
+echo "//" | sendcmd 10.53.0.6
+# Query for a record in a zone which is forwarded to a non-responding forwarder
+# and is delegated from the root to check whether the forwarder will be retried
+# when a delegation is encountered after falling back to full recursive
+# resolution.
+nextpart ns3/named.run >/dev/null
+dig_with_opts txt.example7. txt @$f1 > dig.out.$n.f1 || ret=1
+# The forwarder for the "example7" zone should only be queried once.
+start_pattern="sending packet to 10\.53\.0\.6"
+retry_quiet 5 wait_for_log ns3/named.run "$start_pattern"
+check_sent 1 ns3/named.run "$start_pattern" ";txt\.example7\.[[:space:]]*IN[[:space:]]*TXT$" || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking that priming queries are not forwarded ($n)"
+ret=0
+nextpart ns7/named.run >/dev/null
+dig_with_opts +noadd +noauth txt.example1. txt @10.53.0.7 > dig.out.$n.f7 || ret=1
+received_pattern="received packet from 10\.53\.0\.1"
+start_pattern="sending packet to 10\.53\.0\.1"
+retry_quiet 5 wait_for_log ns7/named.run "$received_pattern" || ret=1
+check_sent 1 ns7/named.run "$start_pattern" ";\.[[:space:]]*IN[[:space:]]*NS$" || ret=1
+sent=$(grep -c "10.53.0.7#.* (.): query '\./NS/IN' approved" ns4/named.run || true)
+[ "$sent" -eq 0 ] || ret=1
+sent=$(grep -c "10.53.0.7#.* (.): query '\./NS/IN' approved" ns1/named.run || true)
+[ "$sent" -eq 1 ] || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking recovery from forwarding to a non-recursive server ($n)"
+ret=0
+dig_with_opts xxx.sld.tld txt @10.53.0.8 > dig.out.$n.f8 || ret=1
+grep "status: NOERROR" dig.out.$n.f8 > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking that rebinding protection works in forward only mode ($n)"
+ret=0
+# 10.53.0.5 will forward target.malicious. query to 10.53.0.4
+# which in turn will return a CNAME for subdomain.rebind.
+# to honor the option deny-answer-aliases { "rebind"; };
+# ns5 should return a SERVFAIL to avoid potential rebinding attacks
+dig_with_opts +noadd +noauth @10.53.0.5 target.malicious. > dig.out.$n || ret=1
+grep "status: SERVFAIL" dig.out.$n > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+# Prepare ans6 for the chasing DS tests.
+sendcmd 10.53.0.6 << EOF
+/ns1.sld.tld/A/
+300 A 10.53.0.2
+/sld.tld/NS/
+300 NS ns1.sld.tld.
+/sld.tld/
+EOF
+
+n=$((n+1))
+echo_i "checking switch from forwarding to normal resolution while chasing DS ($n)"
+ret=0
+copy_setports ns3/named2.conf.in ns3/named.conf
+rndccmd 10.53.0.3 reconfig 2>&1 | sed 's/^/ns3 /' | cat_i
+sleep 1
+nextpart ns3/named.run >/dev/null
+dig_with_opts @$f1 xxx.yyy.sld.tld ds > dig.out.$n.f1 || ret=1
+grep "status: SERVFAIL" dig.out.$n.f1 > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+# See [GL #3129].
+# Enable silent mode for ans11.
+echo "1" | sendcmd 10.53.0.11
+n=$((n+1))
+echo_i "checking the handling of hung DS fetch while chasing DS ($n)"
+ret=0
+copy_setports ns3/named2.conf.in ns3/tmp
+sed 's/root.db/root2.db/' ns3/tmp > ns3/named.conf
+rm -f ns3/tmp
+rndccmd 10.53.0.3 reconfig 2>&1 | sed 's/^/ns3 /' | cat_i
+rndccmd 10.53.0.3 flush 2>&1 | sed 's/^/ns3 /' | cat_i
+sleep 1
+nextpart ns3/named.run >/dev/null
+dig_with_opts @$f1 xxx.yyy.sld.tld ds > dig.out.$n.f1 || ret=1
+grep "status: SERVFAIL" dig.out.$n.f1 > /dev/null || ret=1
+# Disable silent mode for ans11.
+echo "0" | sendcmd 10.53.0.11
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+#
+# Check various spoofed response scenarios. The same tests will be
+# run twice, with "forward first" and "forward only" configurations.
+#
+run_spooftests () {
+ n=$((n+1))
+ echo_i "checking spoofed response scenario 1 - out of bailiwick NS ($n)"
+ ret=0
+ # prime
+ dig_with_opts @10.53.0.9 attackSecureDomain.net > dig.out.$n.prime || ret=1
+ # check 'net' is not poisoned.
+ dig_with_opts @10.53.0.9 diditwork.net. TXT > dig.out.$n.net || ret=1
+ grep '^diditwork\.net\..*TXT.*"recursed"' dig.out.$n.net > /dev/null || ret=1
+ # check 'sub.local.net' is not poisoned.
+ dig_with_opts @10.53.0.9 sub.local.net TXT > dig.out.$n.sub || ret=1
+ grep '^sub\.local\.net\..*TXT.*"recursed"' dig.out.$n.sub > /dev/null || ret=1
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ n=$((n+1))
+ echo_i "checking spoofed response scenario 2 - inject DNAME/net2. ($n)"
+ ret=0
+ # prime
+ dig_with_opts @10.53.0.9 attackSecureDomain.net2 > dig.out.$n.prime || ret=1
+ # check that net2/DNAME is not cached
+ dig_with_opts @10.53.0.9 net2. DNAME > dig.out.$n.net2 || ret=1
+ grep "ANSWER: 0," dig.out.$n.net2 > /dev/null || ret=1
+ grep "status: NXDOMAIN" dig.out.$n.net2 > /dev/null || ret=1
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ n=$((n+1))
+ echo_i "checking spoofed response scenario 3 - extra answer ($n)"
+ ret=0
+ # prime
+ dig_with_opts @10.53.0.9 attackSecureDomain.net3 > dig.out.$n.prime || ret=1
+ # check extra net3 records are not cached
+ rndccmd 10.53.0.9 dumpdb -cache 2>&1 | sed 's/^/ns9 /' | cat_i
+ for try in 1 2 3 4 5; do
+ lines=$(grep "net3" ns9/named_dump.db | wc -l)
+ if [ ${lines} -eq 0 ]; then
+ sleep 1
+ continue
+ fi
+ [ ${lines} -eq 1 ] || ret=1
+ grep -q '^attackSecureDomain.net3' ns9/named_dump.db || ret=1
+ grep -q '^local.net3' ns9/named_dump.db && ret=1
+ done
+ if [ $ret != 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+}
+
+echo_i "checking spoofed response scenarios with forward first zones"
+run_spooftests
+
+copy_setports ns9/named2.conf.in ns9/named.conf
+rndccmd 10.53.0.9 reconfig 2>&1 | sed 's/^/ns3 /' | cat_i
+rndccmd 10.53.0.9 flush 2>&1 | sed 's/^/ns3 /' | cat_i
+sleep 1
+
+echo_i "rechecking spoofed response scenarios with forward only zones"
+run_spooftests
+
+#
+# This scenario expects the spoofed response to succeed. The tests are
+# similar to the ones above, but not identical.
+#
+echo_i "rechecking spoofed response scenarios with 'forward only' set globally"
+copy_setports ns9/named3.conf.in ns9/named.conf
+rndccmd 10.53.0.9 reconfig 2>&1 | sed 's/^/ns3 /' | cat_i
+rndccmd 10.53.0.9 flush 2>&1 | sed 's/^/ns3 /' | cat_i
+sleep 1
+
+n=$((n+1))
+echo_i "checking spoofed response scenario 1 - out of bailiwick NS ($n)"
+ret=0
+# prime
+dig_with_opts @10.53.0.9 attackSecureDomain.net > dig.out.$n.prime || ret=1
+# check 'net' is poisoned.
+dig_with_opts @10.53.0.9 diditwork.net. TXT > dig.out.$n.net || ret=1
+grep '^didItWork\.net\..*TXT.*"if you can see this record the attack worked"' dig.out.$n.net > /dev/null || ret=1
+# check 'sub.local.net' is poisoned.
+dig_with_opts @10.53.0.9 sub.local.net TXT > dig.out.$n.sub || ret=1
+grep '^sub\.local\.net\..*TXT.*"if you see this attacker overrode local delegation"' dig.out.$n.sub > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+n=$((n+1))
+echo_i "checking spoofed response scenario 2 - inject DNAME/net2. ($n)"
+ret=0
+# prime
+dig_with_opts @10.53.0.9 attackSecureDomain.net2 > dig.out.$n.prime || ret=1
+# check that net2/DNAME is cached
+dig_with_opts @10.53.0.9 net2. DNAME > dig.out.$n.net2 || ret=1
+grep "ANSWER: 1," dig.out.$n.net2 > /dev/null || ret=1
+grep "net2\..*IN.DNAME.net\.example\.lll\." dig.out.$n.net2 > /dev/null || ret=1
+if [ $ret != 0 ]; then echo_i "failed"; fi
+status=$((status+ret))
+
+#
+# This test doesn't use any forwarder clauses but is here because it
+# is similar to forwarders, as the set of servers that can populate
+# the namespace is defined by the zone content.
+#
+echo_i "rechecking spoofed response scenarios glue below local zone"
+copy_setports ns9/named4.conf.in ns9/named.conf
+rndccmd 10.53.0.9 reconfig 2>&1 | sed 's/^/ns3 /' | cat_i
+rndccmd 10.53.0.9 flush 2>&1 | sed 's/^/ns3 /' | cat_i
+sleep 1
+
+n=$((n+1))
+echo_i "checking sibling glue below zone ($n)"
+ret=0
+# prime
+dig_with_opts @10.53.0.9 sibling.tld > dig.out.$n.prime || ret=1
+# check for glue A record for sub.local.tld is not used
+dig_with_opts @10.53.0.9 sub.local.tld TXT > dig.out.$n.sub || ret=1
+grep "ANSWER: 1," dig.out.$n.sub > /dev/null || ret=1
+grep 'sub\.local\.tld\..*IN.TXT."good"$' dig.out.$n.sub > /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
diff --git a/bin/tests/system/forward/tests_sh_forward.py b/bin/tests/system/forward/tests_sh_forward.py
new file mode 100644
index 0000000..4380a49
--- /dev/null
+++ b/bin/tests/system/forward/tests_sh_forward.py
@@ -0,0 +1,14 @@
+# 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.
+
+
+def test_forward(run_tests_sh):
+ run_tests_sh()
diff --git a/bin/tests/system/forward/ula-inherited.conf b/bin/tests/system/forward/ula-inherited.conf
new file mode 100644
index 0000000..1fb94b1
--- /dev/null
+++ b/bin/tests/system/forward/ula-inherited.conf
@@ -0,0 +1,17 @@
+/*
+ * 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.
+ */
+
+zone d.f.ip6.arpa {
+ type forward;
+ forwarders { 1.2.3.4; };
+};
diff --git a/bin/tests/system/forward/ula-notinherited.conf b/bin/tests/system/forward/ula-notinherited.conf
new file mode 100644
index 0000000..300001a
--- /dev/null
+++ b/bin/tests/system/forward/ula-notinherited.conf
@@ -0,0 +1,18 @@
+/*
+ * 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.
+ */
+
+zone d.f.ip6.arpa {
+ type forward;
+ forward first;
+ forwarders { 1.2.3.4; };
+};