diff --git a/CHANGES b/CHANGES
index c085f85a3f..2aca18860c 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,9 @@
+5284. [func] Added +unexpected command line option to dig.
+ By default, dig won't accept a reply from a source
+ other than the one to which it sent the query.
+ Invoking dig with +unexpected argument will allow it
+ to process replies from unexpected sources.
+
5283. [bug] When a response-policy zone expires, ensure that
its policies are removed from the RPZ summary
database. [GL #1146]
diff --git a/bin/dig/dig.c b/bin/dig/dig.c
index 51b52b6ba6..d4dca378e6 100644
--- a/bin/dig/dig.c
+++ b/bin/dig/dig.c
@@ -235,6 +235,8 @@ help(void) {
" +tries=### (Set number of UDP attempts) [3]\n"
" +[no]ttlid (Control display of ttls in records)\n"
" +[no]ttlunits (Display TTLs in human-readable units)\n"
+" +[no]unexpected (Print replies from unexpected sources\n"
+" default=off)\n"
" +[no]unknownformat (Print RDATA in RFC 3597 \"unknown\" "
"format)\n"
" +[no]vc (TCP mode (+[no]tcp))\n"
@@ -1667,8 +1669,25 @@ plus_option(char *option, bool is_batchfile,
}
break;
case 'u':
- FULLCHECK("unknownformat");
- lookup->print_unknown_format = state;
+ switch (cmd[1]) {
+ case 'n':
+ switch (cmd[2]) {
+ case 'e':
+ FULLCHECK("unexpected");
+ lookup->accept_reply_unexpected_src = state;
+ break;
+ case 'k':
+ FULLCHECK("unknownformat");
+ lookup->print_unknown_format = state;
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ default:
+ goto invalid_option;
+ }
+
break;
case 'v':
FULLCHECK("vc");
diff --git a/bin/dig/dig.docbook b/bin/dig/dig.docbook
index 86125c6040..7658128f6c 100644
--- a/bin/dig/dig.docbook
+++ b/bin/dig/dig.docbook
@@ -1269,6 +1269,17 @@
+
+
+
+
+ Accept [do not accept] answers from unexpected sources. By
+ default, dig won't accept a reply from a
+ source other than the one to which it sent the query.
+
+
+
+
diff --git a/bin/dig/dighost.c b/bin/dig/dighost.c
index 619bc0f9db..06169db44d 100644
--- a/bin/dig/dighost.c
+++ b/bin/dig/dighost.c
@@ -621,6 +621,7 @@ make_empty_lookup(void) {
looknew->ttlunits = false;
looknew->expandaaaa = false;
looknew->qr = false;
+ looknew->accept_reply_unexpected_src = false;
#ifdef HAVE_LIBIDN2
looknew->idnin = isatty(1)?(getenv("IDN_DISABLE") == NULL):false;
looknew->idnout = looknew->idnin;
@@ -766,6 +767,8 @@ clone_lookup(dig_lookup_t *lookold, bool servers) {
looknew->ttlunits = lookold->ttlunits;
looknew->expandaaaa = lookold->expandaaaa;
looknew->qr = lookold->qr;
+ looknew->accept_reply_unexpected_src =
+ lookold->accept_reply_unexpected_src;
looknew->idnin = lookold->idnin;
looknew->idnout = lookold->idnout;
looknew->udpsize = lookold->udpsize;
@@ -3602,7 +3605,9 @@ recv_done(isc_task_t *task, isc_event_t *event) {
sizeof(buf2));
printf(";; reply from unexpected source: %s,"
" expected %s\n", buf1, buf2);
- match = false;
+ if (!l->accept_reply_unexpected_src) {
+ match = false;
+ }
}
}
diff --git a/bin/dig/include/dig/dig.h b/bin/dig/include/dig/dig.h
index 35f1f30c8f..563cd9d4ed 100644
--- a/bin/dig/include/dig/dig.h
+++ b/bin/dig/include/dig/dig.h
@@ -141,7 +141,9 @@ struct dig_lookup {
idnin,
idnout,
expandaaaa,
- qr;
+ qr,
+ accept_reply_unexpected_src; /*% print replies from unexpected
+ sources. */
char textname[MXNAME]; /*% Name we're going to be looking up */
char cmdline[MXNAME];
dns_rdatatype_t rdtype;
diff --git a/bin/tests/system/digdelv/ans6/ans.pl b/bin/tests/system/digdelv/ans6/ans.pl
new file mode 100755
index 0000000000..793f796cf2
--- /dev/null
+++ b/bin/tests/system/digdelv/ans6/ans.pl
@@ -0,0 +1,82 @@
+#!/usr/bin/perl -w
+#
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# 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 http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+use IO::File;
+use IO::Socket;
+use Net::DNS;
+use Net::DNS::Packet;
+
+my $localport = int($ENV{'PORT'});
+if (!$localport) { $localport = 5300; }
+
+my $sock = IO::Socket::INET->new(LocalAddr => "10.53.0.6",
+ LocalPort => $localport, Proto => "udp") or die "$!";
+
+my $pidf = new IO::File "ans.pid", "w" or die "cannot open pid file: $!";
+print $pidf "$$\n" or die "cannot write pid file: $!";
+$pidf->close or die "cannot close pid file: $!";
+sub rmpid { unlink "ans.pid"; exit 1; };
+
+$SIG{INT} = \&rmpid;
+$SIG{TERM} = \&rmpid;
+
+for (;;) {
+ $sock->recv($buf, 512);
+
+ print "**** request from " , $sock->peerhost, " port ", $sock->peerport, "\n";
+
+ my $packet;
+
+ if ($Net::DNS::VERSION > 0.68) {
+ $packet = new Net::DNS::Packet(\$buf, 0);
+ $@ and die $@;
+ } else {
+ my $err;
+ ($packet, $err) = new Net::DNS::Packet(\$buf, 0);
+ $err and die $err;
+ }
+
+ print "REQUEST:\n";
+ $packet->print;
+
+ $packet->header->qr(1);
+
+ my @questions = $packet->question;
+ my $qname = $questions[0]->qname;
+ my $qtype = $questions[0]->qtype;
+
+ my $donotrespond = 0;
+
+ $packet->header->aa(1);
+ if ($qtype eq "A") {
+ $packet->push("answer",
+ new Net::DNS::RR($qname . " 300 A 10.53.0.5"));
+ } else {
+ $donotrespond = 1;
+ }
+
+ if ($donotrespond == 0) {
+ my $sendsock =
+ IO::Socket::INET->new(LocalAddr => "10.53.1.2",
+ PeerAddr => $sock->peerhost,
+ PeerPort => $sock->peerport,
+ Proto => "udp") or die "$!";
+ print "**** response from ", $sendsock->sockhost, " to " ,
+ $sendsock->peerhost, " port ", $sendsock->peerport, "\n";
+ $sendsock->send($packet->data);
+ $sendsock->close;
+ print "RESPONSE:\n";
+ $packet->print;
+ print "\n";
+ } else {
+ print "DROP:\n";
+ }
+}
diff --git a/bin/tests/system/digdelv/tests.sh b/bin/tests/system/digdelv/tests.sh
index f87ece2598..d67a50cd86 100644
--- a/bin/tests/system/digdelv/tests.sh
+++ b/bin/tests/system/digdelv/tests.sh
@@ -68,6 +68,7 @@ if [ -n "$PYTHON" ] ; then
fi
if [ -x "$DIG" ] ; then
+
n=$((n+1))
echo_i "checking dig short form works ($n)"
ret=0
@@ -723,6 +724,7 @@ if [ -x "$DIG" ] ; then
status=$((status+ret))
n=$((n+1))
+
echo_i "check that dig +short +expandaaaa works ($n)"
ret=0
dig_with_opts @10.53.0.3 +short +expandaaaa AAAA ns2.example > dig.out.test$n 2>&1 || ret=1
@@ -744,6 +746,33 @@ if [ -x "$DIG" ] ; then
if [ $ret -ne 0 ]; then echo_i "failed"; fi
status=$((status+ret))
fi
+
+ echo_i "check that dig +unexpected works ($n)"
+ ret=0
+ dig_with_opts @10.53.0.6 +unexpected a a.example > dig.out.test$n || ret=1
+ grep 'reply from unexpected source' dig.out.test$n > /dev/null || ret=1
+ grep 'status: NOERROR' dig.out.test$n > /dev/null || ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ n=$((n+1))
+ echo_i "check that dig +nounexpected works ($n)"
+ ret=0
+ dig_with_opts @10.53.0.6 +nounexpected +tries=1 +time=2 a a.example > dig.out.test$n && ret=1
+ grep 'reply from unexpected source' dig.out.test$n > /dev/null || ret=1
+ grep "status: NOERROR" < dig.out.test$n > /dev/null && ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
+ n=$((n+1))
+ echo_i "check that dig default for +[no]unexpected (+nounexpected) works ($n)"
+ ret=0
+ dig_with_opts @10.53.0.6 +tries=1 +time=2 a a.example > dig.out.test$n && ret=1
+ grep 'reply from unexpected source' dig.out.test$n > /dev/null || ret=1
+ grep "status: NOERROR" < dig.out.test$n > /dev/null && ret=1
+ if [ $ret -ne 0 ]; then echo_i "failed"; fi
+ status=$((status+ret))
+
else
echo_i "$DIG is needed, so skipping these dig tests"
fi
diff --git a/doc/arm/notes.xml b/doc/arm/notes.xml
index 62e8a4e2a3..5796058a60 100644
--- a/doc/arm/notes.xml
+++ b/doc/arm/notes.xml
@@ -113,6 +113,15 @@
New Features
+
+
+ Added a new command line option to dig:
+ +[no]unexpected. By default, dig
+ won't accept a reply from a source other than the one to which
+ it sent the query. Add the +unexpected argument
+ to enable it to process replies from unexpected sources.
+
+
The GeoIP2 API from MaxMind is now supported. Geolocation support
diff --git a/util/copyrights b/util/copyrights
index fd2e88db74..9516634102 100644
--- a/util/copyrights
+++ b/util/copyrights
@@ -497,6 +497,7 @@
./bin/tests/system/digcomp.pl PERL 2000,2001,2004,2007,2012,2013,2016,2018,2019
./bin/tests/system/digdelv/ans4/startme X 2017,2018,2019
./bin/tests/system/digdelv/ans5/ans.pl PERL 2019
+./bin/tests/system/digdelv/ans6/ans.pl PERL 2019
./bin/tests/system/digdelv/clean.sh SH 2015,2016,2018,2019
./bin/tests/system/digdelv/ns2/sign.sh SH 2018,2019
./bin/tests/system/digdelv/prereq.sh SH 2018,2019