aboutsummaryrefslogtreecommitdiff
path: root/contrib
diff options
context:
space:
mode:
authorCy Schubert <cy@FreeBSD.org>2022-08-06 01:44:40 +0000
committerCy Schubert <cy@FreeBSD.org>2022-08-09 13:29:14 +0000
commited7eaf6b8dce3765542d0695a5ff8fa8148978c2 (patch)
tree93819dc39cd779d3cc5617bd3b157ccf69c34e57 /contrib
parentfd03b246b75376c32f307ec1ebf609f5f50a37f6 (diff)
downloadsrc-ed7eaf6b8dce3765542d0695a5ff8fa8148978c2.tar.gz
src-ed7eaf6b8dce3765542d0695a5ff8fa8148978c2.zip
unbound: Vendor import 1.16.2
Security update to unbound. PR: 265645 Security: CVE-2022-30698, CVE-2022-30699 Security: bc43a578-14ec-11ed-856e-d4c9ef517024 Merge commit '9b76d32f2310b735dbeb896cbf2776cad61f23e8' into main (cherry picked from commit 790c6b245151d6d5a26b84e5f34fee61453e2e60)
Diffstat (limited to 'contrib')
-rw-r--r--contrib/unbound/SECURITY.md31
-rw-r--r--contrib/unbound/cachedb/cachedb.c2
-rwxr-xr-xcontrib/unbound/configure25
-rw-r--r--contrib/unbound/configure.ac5
-rw-r--r--contrib/unbound/daemon/cachedump.c5
-rw-r--r--contrib/unbound/daemon/worker.c2
-rw-r--r--contrib/unbound/dns64/dns64.c4
-rw-r--r--contrib/unbound/doc/Changelog30
-rw-r--r--contrib/unbound/doc/README2
-rw-r--r--contrib/unbound/doc/example.conf.in8
-rw-r--r--contrib/unbound/doc/libunbound.3.in4
-rw-r--r--contrib/unbound/doc/unbound-anchor.8.in2
-rw-r--r--contrib/unbound/doc/unbound-checkconf.8.in2
-rw-r--r--contrib/unbound/doc/unbound-control.8.in2
-rw-r--r--contrib/unbound/doc/unbound-host.1.in2
-rw-r--r--contrib/unbound/doc/unbound.8.in4
-rw-r--r--contrib/unbound/doc/unbound.conf.5.in15
-rw-r--r--contrib/unbound/ipsecmod/ipsecmod.c2
-rw-r--r--contrib/unbound/iterator/iter_utils.c6
-rw-r--r--contrib/unbound/iterator/iter_utils.h3
-rw-r--r--contrib/unbound/iterator/iterator.c23
-rw-r--r--contrib/unbound/iterator/iterator.h12
-rw-r--r--contrib/unbound/services/authzone.c1
-rw-r--r--contrib/unbound/services/cache/dns.c111
-rw-r--r--contrib/unbound/services/cache/dns.h18
-rw-r--r--contrib/unbound/services/cache/infra.c6
-rw-r--r--contrib/unbound/services/listen_dnsport.c17
-rw-r--r--contrib/unbound/services/mesh.c1
-rw-r--r--contrib/unbound/sldns/rrdef.c4
-rw-r--r--contrib/unbound/sldns/wire2str.c2
-rw-r--r--contrib/unbound/testdata/iter_ghost_sub.rpl309
-rw-r--r--contrib/unbound/testdata/iter_ghost_timewindow.rpl391
-rw-r--r--contrib/unbound/util/config_file.c15
-rw-r--r--contrib/unbound/util/config_file.h4
-rw-r--r--contrib/unbound/util/configlexer.lex1
-rw-r--r--contrib/unbound/util/configparser.y13
-rw-r--r--contrib/unbound/util/data/msgreply.c2
-rw-r--r--contrib/unbound/util/iana_ports.inc1
-rw-r--r--contrib/unbound/util/module.h6
-rw-r--r--contrib/unbound/util/rtt.c3
-rw-r--r--contrib/unbound/util/rtt.h2
-rw-r--r--contrib/unbound/validator/val_utils.c1
-rw-r--r--contrib/unbound/validator/validator.c7
43 files changed, 1015 insertions, 91 deletions
diff --git a/contrib/unbound/SECURITY.md b/contrib/unbound/SECURITY.md
new file mode 100644
index 000000000000..5770ccd79918
--- /dev/null
+++ b/contrib/unbound/SECURITY.md
@@ -0,0 +1,31 @@
+# Security Policy
+
+## Supported Versions
+
+NLnet Labs adheres to the straightforward, semantic versioning scheme that is
+commonly used in the software industry.
+
+Support is provided in respect of the latest release, i.e. releases with the
+highest minor and patch version level. We do not backport security fixes to
+older (minor) versions. In the event a new major version is released (e.g. from
+3.2.18 to 4.0.0), support will also be provided on the latest minor version of
+the previous major version (3.2.18) for a period of one year from the release of
+the new major version (4.0.0).
+
+In the event that, during this period, a new patch or minor version of the
+previous major version is released, then support on these versions will only be
+provided for the remainder of the one-year-period.
+
+You can find detailed information on our software support policy here:
+
+https://www.nlnetlabs.nl/support/software-support-policy/
+
+## Reporting a Vulnerability
+
+We take security very seriously. If you have discovered a security vulnerability
+in one of our projects and you would like to report it to us, you can send an
+encrypted message to our Security Entry Point.
+
+Details are described here:
+
+https://www.nlnetlabs.nl/security-report/
diff --git a/contrib/unbound/cachedb/cachedb.c b/contrib/unbound/cachedb/cachedb.c
index 725bc6ce8b38..b07743d85259 100644
--- a/contrib/unbound/cachedb/cachedb.c
+++ b/contrib/unbound/cachedb/cachedb.c
@@ -662,7 +662,7 @@ cachedb_intcache_store(struct module_qstate* qstate)
return;
(void)dns_cache_store(qstate->env, &qstate->qinfo,
qstate->return_msg->rep, 0, qstate->prefetch_leeway, 0,
- qstate->region, store_flags);
+ qstate->region, store_flags, qstate->qstarttime);
}
/**
diff --git a/contrib/unbound/configure b/contrib/unbound/configure
index 0029d5b42782..cc44a57502af 100755
--- a/contrib/unbound/configure
+++ b/contrib/unbound/configure
@@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for unbound 1.16.1.
+# Generated by GNU Autoconf 2.69 for unbound 1.16.2.
#
# Report bugs to <unbound-bugs@nlnetlabs.nl or https://github.com/NLnetLabs/unbound/issues>.
#
@@ -591,8 +591,8 @@ MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='unbound'
PACKAGE_TARNAME='unbound'
-PACKAGE_VERSION='1.16.1'
-PACKAGE_STRING='unbound 1.16.1'
+PACKAGE_VERSION='1.16.2'
+PACKAGE_STRING='unbound 1.16.2'
PACKAGE_BUGREPORT='unbound-bugs@nlnetlabs.nl or https://github.com/NLnetLabs/unbound/issues'
PACKAGE_URL=''
@@ -1477,7 +1477,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
-\`configure' configures unbound 1.16.1 to adapt to many kinds of systems.
+\`configure' configures unbound 1.16.2 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1543,7 +1543,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
- short | recursive ) echo "Configuration of unbound 1.16.1:";;
+ short | recursive ) echo "Configuration of unbound 1.16.2:";;
esac
cat <<\_ACEOF
@@ -1785,7 +1785,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
-unbound configure 1.16.1
+unbound configure 1.16.2
generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc.
@@ -2494,7 +2494,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
-It was created by unbound $as_me 1.16.1, which was
+It was created by unbound $as_me 1.16.2, which was
generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@
@@ -2846,11 +2846,11 @@ UNBOUND_VERSION_MAJOR=1
UNBOUND_VERSION_MINOR=16
-UNBOUND_VERSION_MICRO=1
+UNBOUND_VERSION_MICRO=2
LIBUNBOUND_CURRENT=9
-LIBUNBOUND_REVISION=17
+LIBUNBOUND_REVISION=18
LIBUNBOUND_AGE=1
# 1.0.0 had 0:12:0
# 1.0.1 had 0:13:0
@@ -2935,6 +2935,7 @@ LIBUNBOUND_AGE=1
# 1.15.0 had 9:15:1
# 1.16.0 had 9:16:1
# 1.16.1 had 9:17:1
+# 1.16.2 had 9:18:1
# Current -- the number of the binary API that we're implementing
# Revision -- which iteration of the implementation of the binary
@@ -22013,7 +22014,7 @@ _ACEOF
-version=1.16.1
+version=1.16.2
date=`date +'%b %e, %Y'`
@@ -22532,7 +22533,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
-This file was extended by unbound $as_me 1.16.1, which was
+This file was extended by unbound $as_me 1.16.2, which was
generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -22598,7 +22599,7 @@ _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\
-unbound config.status 1.16.1
+unbound config.status 1.16.2
configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\"
diff --git a/contrib/unbound/configure.ac b/contrib/unbound/configure.ac
index e41c811ae826..224501b3afbe 100644
--- a/contrib/unbound/configure.ac
+++ b/contrib/unbound/configure.ac
@@ -11,14 +11,14 @@ sinclude(dnscrypt/dnscrypt.m4)
# must be numbers. ac_defun because of later processing
m4_define([VERSION_MAJOR],[1])
m4_define([VERSION_MINOR],[16])
-m4_define([VERSION_MICRO],[1])
+m4_define([VERSION_MICRO],[2])
AC_INIT([unbound],m4_defn([VERSION_MAJOR]).m4_defn([VERSION_MINOR]).m4_defn([VERSION_MICRO]),[unbound-bugs@nlnetlabs.nl or https://github.com/NLnetLabs/unbound/issues],[unbound])
AC_SUBST(UNBOUND_VERSION_MAJOR, [VERSION_MAJOR])
AC_SUBST(UNBOUND_VERSION_MINOR, [VERSION_MINOR])
AC_SUBST(UNBOUND_VERSION_MICRO, [VERSION_MICRO])
LIBUNBOUND_CURRENT=9
-LIBUNBOUND_REVISION=17
+LIBUNBOUND_REVISION=18
LIBUNBOUND_AGE=1
# 1.0.0 had 0:12:0
# 1.0.1 had 0:13:0
@@ -103,6 +103,7 @@ LIBUNBOUND_AGE=1
# 1.15.0 had 9:15:1
# 1.16.0 had 9:16:1
# 1.16.1 had 9:17:1
+# 1.16.2 had 9:18:1
# Current -- the number of the binary API that we're implementing
# Revision -- which iteration of the implementation of the binary
diff --git a/contrib/unbound/daemon/cachedump.c b/contrib/unbound/daemon/cachedump.c
index b929f909bab2..baf8008ea80f 100644
--- a/contrib/unbound/daemon/cachedump.c
+++ b/contrib/unbound/daemon/cachedump.c
@@ -679,7 +679,8 @@ load_msg(RES* ssl, sldns_buffer* buf, struct worker* worker)
if(!go_on)
return 1; /* skip this one, not all references satisfied */
- if(!dns_cache_store(&worker->env, &qinf, &rep, 0, 0, 0, NULL, flags)) {
+ if(!dns_cache_store(&worker->env, &qinf, &rep, 0, 0, 0, NULL, flags,
+ *worker->env.now)) {
log_warn("error out of memory");
return 0;
}
@@ -850,7 +851,7 @@ int print_deleg_lookup(RES* ssl, struct worker* worker, uint8_t* nm,
while(1) {
dp = dns_cache_find_delegation(&worker->env, nm, nmlen,
qinfo.qtype, qinfo.qclass, region, &msg,
- *worker->env.now);
+ *worker->env.now, 0, NULL, 0);
if(!dp) {
return ssl_printf(ssl, "no delegation from "
"cache; goes to configured roots\n");
diff --git a/contrib/unbound/daemon/worker.c b/contrib/unbound/daemon/worker.c
index 27626ce938ca..010c4dc0a281 100644
--- a/contrib/unbound/daemon/worker.c
+++ b/contrib/unbound/daemon/worker.c
@@ -459,7 +459,7 @@ answer_norec_from_cache(struct worker* worker, struct query_info* qinfo,
dp = dns_cache_find_delegation(&worker->env, qinfo->qname,
qinfo->qname_len, qinfo->qtype, qinfo->qclass,
- worker->scratchpad, &msg, timenow);
+ worker->scratchpad, &msg, timenow, 0, NULL, 0);
if(!dp) { /* no delegation, need to reprime */
return 0;
}
diff --git a/contrib/unbound/dns64/dns64.c b/contrib/unbound/dns64/dns64.c
index d01b436e1d6c..4b98b609e2d3 100644
--- a/contrib/unbound/dns64/dns64.c
+++ b/contrib/unbound/dns64/dns64.c
@@ -652,7 +652,7 @@ handle_event_moddone(struct module_qstate* qstate, int id)
if ( (!iq || !iq->started_no_cache_store) &&
qstate->return_msg && qstate->return_msg->rep &&
!dns_cache_store(qstate->env, &qstate->qinfo, qstate->return_msg->rep,
- 0, 0, 0, NULL, qstate->query_flags))
+ 0, 0, 0, NULL, qstate->query_flags, qstate->qstarttime))
log_err("out of memory");
/* do nothing */
@@ -991,7 +991,7 @@ dns64_inform_super(struct module_qstate* qstate, int id,
/* Store the generated response in cache. */
if ( (!super_dq || !super_dq->started_no_cache_store) &&
!dns_cache_store(super->env, &super->qinfo, super->return_msg->rep,
- 0, 0, 0, NULL, super->query_flags))
+ 0, 0, 0, NULL, super->query_flags, qstate->qstarttime))
log_err("out of memory");
}
diff --git a/contrib/unbound/doc/Changelog b/contrib/unbound/doc/Changelog
index d3573190e7e2..13f0f11749e0 100644
--- a/contrib/unbound/doc/Changelog
+++ b/contrib/unbound/doc/Changelog
@@ -1,3 +1,30 @@
+1 August 2022: Wouter
+ - Fix the novel ghost domain issues CVE-2022-30698 and CVE-2022-30699.
+ - Tests for ghost domain fixes.
+
+19 July 2022: George
+ - Update documentation for 'outbound-msg-retry:'.
+
+19 July 2022: Wouter
+ - Merge #718: Introduce infra-cache-max-rtt option to config max
+ retransmit timeout.
+
+15 July 2022: Wouter
+ - Merge PR 714: Avoid treat normal hosts as unresponsive servers.
+ And fixup the lock code.
+ - iana portlist update.
+
+12 July 2022: George
+ - For windows crosscompile, fix setting the IPV6_MTU socket option
+ equivalent (IPV6_USER_MTU); allows cross compiling with latest
+ cross-compiler versions.
+
+12 July 2022: Wouter
+ - Fix dname count in sldns parse type descriptor for SVCB and HTTPS.
+
+11 July 2022: Wouter
+ - Fix verbose EDE error printout.
+
4 July 2022: George
- Fix bug introduced in 'improve val_sigcrypt.c::algo_needs_missing for
one loop pass'.
@@ -5,7 +32,8 @@
outbound tcp sockets.
4 July 2022: Wouter
- - Tag for 1.16.1rc1 release.
+ - Tag for 1.16.1rc1 release. This became 1.16.1 on 11 July 2022.
+ The code repo continues with version 1.16.2 under development.
3 July 2022: George
- Merge PR #671 from Petr Menšík: Disable ED25519 and ED448 in FIPS
diff --git a/contrib/unbound/doc/README b/contrib/unbound/doc/README
index 13992ac7f9ec..a6377d85c71e 100644
--- a/contrib/unbound/doc/README
+++ b/contrib/unbound/doc/README
@@ -1,4 +1,4 @@
-README for Unbound 1.16.1
+README for Unbound 1.16.2
Copyright 2007 NLnet Labs
http://unbound.net
diff --git a/contrib/unbound/doc/example.conf.in b/contrib/unbound/doc/example.conf.in
index b01d2c58dbfe..087e6364297f 100644
--- a/contrib/unbound/doc/example.conf.in
+++ b/contrib/unbound/doc/example.conf.in
@@ -1,7 +1,7 @@
#
# Example configuration file.
#
-# See unbound.conf(5) man page, version 1.16.1.
+# See unbound.conf(5) man page, version 1.16.2.
#
# this is a comment.
@@ -168,7 +168,8 @@ server:
# perform connect for UDP sockets to mitigate ICMP side channel.
# udp-connect: yes
- # The number of retries when a non-positive response is received.
+ # The number of retries, per upstream nameserver in a delegation, when
+ # a throwaway response (also timeouts) is received.
# outbound-msg-retry: 5
# msec for waiting for an unknown server to reply. Increase if you
@@ -202,6 +203,9 @@ server:
# minimum wait time for responses, increase if uplink is long. In msec.
# infra-cache-min-rtt: 50
+ # maximum wait time for responses. In msec.
+ # infra-cache-max-rtt: 120000
+
# enable to make server probe down hosts more frequently.
# infra-keep-probing: no
diff --git a/contrib/unbound/doc/libunbound.3.in b/contrib/unbound/doc/libunbound.3.in
index 8049e3ae29d3..543e628fd22a 100644
--- a/contrib/unbound/doc/libunbound.3.in
+++ b/contrib/unbound/doc/libunbound.3.in
@@ -1,4 +1,4 @@
-.TH "libunbound" "3" "Jul 11, 2022" "NLnet Labs" "unbound 1.16.1"
+.TH "libunbound" "3" "Aug 1, 2022" "NLnet Labs" "unbound 1.16.2"
.\"
.\" libunbound.3 -- unbound library functions manual
.\"
@@ -44,7 +44,7 @@
.B ub_ctx_zone_remove,
.B ub_ctx_data_add,
.B ub_ctx_data_remove
-\- Unbound DNS validating resolver 1.16.1 functions.
+\- Unbound DNS validating resolver 1.16.2 functions.
.SH "SYNOPSIS"
.B #include <unbound.h>
.LP
diff --git a/contrib/unbound/doc/unbound-anchor.8.in b/contrib/unbound/doc/unbound-anchor.8.in
index 85b71fd30b8e..7fc316855320 100644
--- a/contrib/unbound/doc/unbound-anchor.8.in
+++ b/contrib/unbound/doc/unbound-anchor.8.in
@@ -1,4 +1,4 @@
-.TH "unbound-anchor" "8" "Jul 11, 2022" "NLnet Labs" "unbound 1.16.1"
+.TH "unbound-anchor" "8" "Aug 1, 2022" "NLnet Labs" "unbound 1.16.2"
.\"
.\" unbound-anchor.8 -- unbound anchor maintenance utility manual
.\"
diff --git a/contrib/unbound/doc/unbound-checkconf.8.in b/contrib/unbound/doc/unbound-checkconf.8.in
index 8133feeaa364..628f841b36f4 100644
--- a/contrib/unbound/doc/unbound-checkconf.8.in
+++ b/contrib/unbound/doc/unbound-checkconf.8.in
@@ -1,4 +1,4 @@
-.TH "unbound-checkconf" "8" "Jul 11, 2022" "NLnet Labs" "unbound 1.16.1"
+.TH "unbound-checkconf" "8" "Aug 1, 2022" "NLnet Labs" "unbound 1.16.2"
.\"
.\" unbound-checkconf.8 -- unbound configuration checker manual
.\"
diff --git a/contrib/unbound/doc/unbound-control.8.in b/contrib/unbound/doc/unbound-control.8.in
index 128101e2f887..d18a407cb5eb 100644
--- a/contrib/unbound/doc/unbound-control.8.in
+++ b/contrib/unbound/doc/unbound-control.8.in
@@ -1,4 +1,4 @@
-.TH "unbound-control" "8" "Jul 11, 2022" "NLnet Labs" "unbound 1.16.1"
+.TH "unbound-control" "8" "Aug 1, 2022" "NLnet Labs" "unbound 1.16.2"
.\"
.\" unbound-control.8 -- unbound remote control manual
.\"
diff --git a/contrib/unbound/doc/unbound-host.1.in b/contrib/unbound/doc/unbound-host.1.in
index fb73e625df47..d3b701fb9e48 100644
--- a/contrib/unbound/doc/unbound-host.1.in
+++ b/contrib/unbound/doc/unbound-host.1.in
@@ -1,4 +1,4 @@
-.TH "unbound\-host" "1" "Jul 11, 2022" "NLnet Labs" "unbound 1.16.1"
+.TH "unbound\-host" "1" "Aug 1, 2022" "NLnet Labs" "unbound 1.16.2"
.\"
.\" unbound-host.1 -- unbound DNS lookup utility
.\"
diff --git a/contrib/unbound/doc/unbound.8.in b/contrib/unbound/doc/unbound.8.in
index bc768c6a151b..73b9e4b7a8d0 100644
--- a/contrib/unbound/doc/unbound.8.in
+++ b/contrib/unbound/doc/unbound.8.in
@@ -1,4 +1,4 @@
-.TH "unbound" "8" "Jul 11, 2022" "NLnet Labs" "unbound 1.16.1"
+.TH "unbound" "8" "Aug 1, 2022" "NLnet Labs" "unbound 1.16.2"
.\"
.\" unbound.8 -- unbound manual
.\"
@@ -9,7 +9,7 @@
.\"
.SH "NAME"
.B unbound
-\- Unbound DNS validating resolver 1.16.1.
+\- Unbound DNS validating resolver 1.16.2.
.SH "SYNOPSIS"
.B unbound
.RB [ \-h ]
diff --git a/contrib/unbound/doc/unbound.conf.5.in b/contrib/unbound/doc/unbound.conf.5.in
index 1157a2d1975f..47250e4f88f0 100644
--- a/contrib/unbound/doc/unbound.conf.5.in
+++ b/contrib/unbound/doc/unbound.conf.5.in
@@ -1,4 +1,4 @@
-.TH "unbound.conf" "5" "Jul 11, 2022" "NLnet Labs" "unbound 1.16.1"
+.TH "unbound.conf" "5" "Aug 1, 2022" "NLnet Labs" "unbound 1.16.2"
.\"
.\" unbound.conf.5 -- unbound.conf manual
.\"
@@ -395,6 +395,10 @@ Lower limit for dynamic retransmit timeout calculation in infrastructure
cache. Default is 50 milliseconds. Increase this value if using forwarders
needing more time to do recursive name resolution.
.TP
+.B infra\-cache\-max\-rtt: \fI<msec>
+Upper limit for dynamic retransmit timeout calculation in infrastructure
+cache. Default is 2 minutes.
+.TP
.B infra\-keep\-probing: \fI<yes or no>
If enabled the server keeps probing hosts that are down, in the one probe
at a time regime. Default is no. Hosts that are down, eg. they did
@@ -1758,9 +1762,12 @@ set ip\-ratelimit to a suspicious rate to aggressively limit unusually high
traffic. Default is off.
.TP 5
.B outbound\-msg\-retry: \fI<number>
-The number of retries Unbound will do in case of a non positive response is
-received. If a forward nameserver is used, this is the number of retries per
-forward nameserver in case of throwaway response.
+The number of retries, per upstream nameserver in a delegation, that Unbound
+will attempt in case a throwaway response is received.
+No response (timeout) contributes to the retry counter.
+If a forward/stub zone is used, this is the number of retries per nameserver in
+the zone.
+Default is 5.
.TP 5
.B fast\-server\-permil: \fI<number>
Specify how many times out of 1000 to pick from the set of fastest servers.
diff --git a/contrib/unbound/ipsecmod/ipsecmod.c b/contrib/unbound/ipsecmod/ipsecmod.c
index 577f7112e194..19549d4eefe0 100644
--- a/contrib/unbound/ipsecmod/ipsecmod.c
+++ b/contrib/unbound/ipsecmod/ipsecmod.c
@@ -456,7 +456,7 @@ ipsecmod_handle_query(struct module_qstate* qstate,
/* Store A/AAAA in cache. */
if(!dns_cache_store(qstate->env, &qstate->qinfo,
qstate->return_msg->rep, 0, qstate->prefetch_leeway,
- 0, qstate->region, qstate->query_flags)) {
+ 0, qstate->region, qstate->query_flags, qstate->qstarttime)) {
log_err("ipsecmod: out of memory caching record");
}
qstate->ext_state[id] = module_finished;
diff --git a/contrib/unbound/iterator/iter_utils.c b/contrib/unbound/iterator/iter_utils.c
index 6d159157a995..3e13e595c63d 100644
--- a/contrib/unbound/iterator/iter_utils.c
+++ b/contrib/unbound/iterator/iter_utils.c
@@ -70,8 +70,6 @@
/** time when nameserver glue is said to be 'recent' */
#define SUSPICION_RECENT_EXPIRY 86400
-/** penalty to validation failed blacklisted IPs */
-#define BLACKLIST_PENALTY (USEFUL_SERVER_TOP_TIMEOUT*4)
/** fillup fetch policy array */
static void
@@ -661,10 +659,10 @@ dns_copy_msg(struct dns_msg* from, struct regional* region)
void
iter_dns_store(struct module_env* env, struct query_info* msgqinf,
struct reply_info* msgrep, int is_referral, time_t leeway, int pside,
- struct regional* region, uint16_t flags)
+ struct regional* region, uint16_t flags, time_t qstarttime)
{
if(!dns_cache_store(env, msgqinf, msgrep, is_referral, leeway,
- pside, region, flags))
+ pside, region, flags, qstarttime))
log_err("out of memory: cannot store data in cache");
}
diff --git a/contrib/unbound/iterator/iter_utils.h b/contrib/unbound/iterator/iter_utils.h
index c0e5181573f5..8583fde58a44 100644
--- a/contrib/unbound/iterator/iter_utils.h
+++ b/contrib/unbound/iterator/iter_utils.h
@@ -132,6 +132,7 @@ struct dns_msg* dns_copy_msg(struct dns_msg* from, struct regional* regional);
* can be prefetch-updates.
* @param region: to copy modified (cache is better) rrs back to.
* @param flags: with BIT_CD for dns64 AAAA translated queries.
+ * @param qstarttime: time of query start.
* return void, because we are not interested in alloc errors,
* the iterator and validator can operate on the results in their
* scratch space (the qstate.region) and are not dependent on the cache.
@@ -140,7 +141,7 @@ struct dns_msg* dns_copy_msg(struct dns_msg* from, struct regional* regional);
*/
void iter_dns_store(struct module_env* env, struct query_info* qinf,
struct reply_info* rep, int is_referral, time_t leeway, int pside,
- struct regional* region, uint16_t flags);
+ struct regional* region, uint16_t flags, time_t qstarttime);
/**
* Select randomly with n/m probability.
diff --git a/contrib/unbound/iterator/iterator.c b/contrib/unbound/iterator/iterator.c
index 727631d6cf8e..25e5cfee4645 100644
--- a/contrib/unbound/iterator/iterator.c
+++ b/contrib/unbound/iterator/iterator.c
@@ -71,6 +71,10 @@
/* in msec */
int UNKNOWN_SERVER_NICENESS = 376;
+/* in msec */
+int USEFUL_SERVER_TOP_TIMEOUT = 120000;
+/* Equals USEFUL_SERVER_TOP_TIMEOUT*4 */
+int BLACKLIST_PENALTY = (120000*4);
static void target_count_increase_nx(struct iter_qstate* iq, int num);
@@ -371,7 +375,7 @@ error_response_cache(struct module_qstate* qstate, int id, int rcode)
err.security = sec_status_indeterminate;
verbose(VERB_ALGO, "store error response in message cache");
iter_dns_store(qstate->env, &qstate->qinfo, &err, 0, 0, 0, NULL,
- qstate->query_flags);
+ qstate->query_flags, qstate->qstarttime);
}
return error_response(qstate, id, rcode);
}
@@ -1485,7 +1489,8 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
iq->dp = dns_cache_find_delegation(qstate->env, delname,
delnamelen, iq->qchase.qtype, iq->qchase.qclass,
qstate->region, &iq->deleg_msg,
- *qstate->env->now+qstate->prefetch_leeway);
+ *qstate->env->now+qstate->prefetch_leeway, 1,
+ dpname, dpnamelen);
else iq->dp = NULL;
/* If the cache has returned nothing, then we have a
@@ -1777,7 +1782,8 @@ generate_parentside_target_query(struct module_qstate* qstate,
subiq->dp = dns_cache_find_delegation(qstate->env,
name, namelen, qtype, qclass, subq->region,
&subiq->deleg_msg,
- *qstate->env->now+subq->prefetch_leeway);
+ *qstate->env->now+subq->prefetch_leeway,
+ 1, NULL, 0);
/* if no dp, then it's from root, refetch unneeded */
if(subiq->dp) {
subiq->dnssec_expected = iter_indicates_dnssec(
@@ -2943,7 +2949,8 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
iq->qchase.qtype != iq->response->qinfo.qtype,
qstate->prefetch_leeway,
iq->dp&&iq->dp->has_parent_side_NS,
- qstate->region, qstate->query_flags);
+ qstate->region, qstate->query_flags,
+ qstate->qstarttime);
/* close down outstanding requests to be discarded */
outbound_list_clear(&iq->outlist);
iq->num_current_queries = 0;
@@ -3032,7 +3039,8 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
/* Store the referral under the current query */
/* no prefetch-leeway, since its not the answer */
iter_dns_store(qstate->env, &iq->response->qinfo,
- iq->response->rep, 1, 0, 0, NULL, 0);
+ iq->response->rep, 1, 0, 0, NULL, 0,
+ qstate->qstarttime);
if(iq->store_parent_NS)
iter_store_parentside_NS(qstate->env,
iq->response->rep);
@@ -3146,7 +3154,7 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
iter_dns_store(qstate->env, &iq->response->qinfo,
iq->response->rep, 1, qstate->prefetch_leeway,
iq->dp&&iq->dp->has_parent_side_NS, NULL,
- qstate->query_flags);
+ qstate->query_flags, qstate->qstarttime);
/* set the current request's qname to the new value. */
iq->qchase.qname = sname;
iq->qchase.qname_len = snamelen;
@@ -3752,7 +3760,8 @@ processFinished(struct module_qstate* qstate, struct iter_qstate* iq,
iter_dns_store(qstate->env, &qstate->qinfo,
iq->response->rep, 0, qstate->prefetch_leeway,
iq->dp&&iq->dp->has_parent_side_NS,
- qstate->region, qstate->query_flags);
+ qstate->region, qstate->query_flags,
+ qstate->qstarttime);
}
}
qstate->return_rcode = LDNS_RCODE_NOERROR;
diff --git a/contrib/unbound/iterator/iterator.h b/contrib/unbound/iterator/iterator.h
index 62f4768ea01d..b71b7fe9945f 100644
--- a/contrib/unbound/iterator/iterator.h
+++ b/contrib/unbound/iterator/iterator.h
@@ -94,15 +94,17 @@ struct rbtree_type;
extern int UNKNOWN_SERVER_NICENESS;
/** maximum timeout before a host is deemed unsuitable, in msec.
* After host_ttl this will be timed out and the host will be tried again.
- * Equals RTT_MAX_TIMEOUT
- */
-#define USEFUL_SERVER_TOP_TIMEOUT 120000
+ * Equals RTT_MAX_TIMEOUT, and thus when RTT_MAX_TIMEOUT is overwritten by
+ * config infra_cache_max_rtt, it will be overwritten as well. */
+extern int USEFUL_SERVER_TOP_TIMEOUT;
+/** penalty to validation failed blacklisted IPs
+ * Equals USEFUL_SERVER_TOP_TIMEOUT*4, and thus when RTT_MAX_TIMEOUT is
+ * overwritten by config infra_cache_max_rtt, it will be overwritten as well. */
+extern int BLACKLIST_PENALTY;
/** RTT band, within this amount from the best, servers are chosen randomly.
* Chosen so that the UNKNOWN_SERVER_NICENESS falls within the band of a
* fast server, this causes server exploration as a side benefit. msec. */
#define RTT_BAND 400
-/** Start value for blacklisting a host, 2*USEFUL_SERVER_TOP_TIMEOUT in sec */
-#define INFRA_BACKOFF_INITIAL 240
/**
* Global state for the iterator.
diff --git a/contrib/unbound/services/authzone.c b/contrib/unbound/services/authzone.c
index fee90d5697ac..137c45b726b5 100644
--- a/contrib/unbound/services/authzone.c
+++ b/contrib/unbound/services/authzone.c
@@ -8189,7 +8189,6 @@ auth_zone_verify_zonemd_key_with_ds(struct auth_zone* z,
keystorage->rk.type = htons(LDNS_RR_TYPE_DNSKEY);
keystorage->rk.rrset_class = htons(z->dclass);
auth_zone_log(z->name, VERB_QUERY, "zonemd: verify zone DNSKEY with DS");
- // @TODO add EDE here? we currently just pass NULL
sec = val_verify_DNSKEY_with_DS(env, ve, keystorage, ds, sigalg,
why_bogus, NULL, NULL);
regional_free_all(env->scratch);
diff --git a/contrib/unbound/services/cache/dns.c b/contrib/unbound/services/cache/dns.c
index f6c11451c93a..6bca8d85fadb 100644
--- a/contrib/unbound/services/cache/dns.c
+++ b/contrib/unbound/services/cache/dns.c
@@ -68,11 +68,16 @@
* in a prefetch situation to be updated (without becoming sticky).
* @param qrep: update rrsets here if cache is better
* @param region: for qrep allocs.
+ * @param qstarttime: time when delegations were looked up, this is perhaps
+ * earlier than the time in now. The time is used to determine if RRsets
+ * of type NS have expired, so that they can only be updated using
+ * lookups of delegation points that did not use them, since they had
+ * expired then.
*/
static void
store_rrsets(struct module_env* env, struct reply_info* rep, time_t now,
time_t leeway, int pside, struct reply_info* qrep,
- struct regional* region)
+ struct regional* region, time_t qstarttime)
{
size_t i;
/* see if rrset already exists in cache, if not insert it. */
@@ -81,8 +86,8 @@ store_rrsets(struct module_env* env, struct reply_info* rep, time_t now,
rep->ref[i].id = rep->rrsets[i]->id;
/* update ref if it was in the cache */
switch(rrset_cache_update(env->rrset_cache, &rep->ref[i],
- env->alloc, now + ((ntohs(rep->ref[i].key->rk.type)==
- LDNS_RR_TYPE_NS && !pside)?0:leeway))) {
+ env->alloc, ((ntohs(rep->ref[i].key->rk.type)==
+ LDNS_RR_TYPE_NS && !pside)?qstarttime:now + leeway))) {
case 0: /* ref unchanged, item inserted */
break;
case 2: /* ref updated, cache is superior */
@@ -155,7 +160,8 @@ msg_del_servfail(struct module_env* env, struct query_info* qinfo,
void
dns_cache_store_msg(struct module_env* env, struct query_info* qinfo,
hashvalue_type hash, struct reply_info* rep, time_t leeway, int pside,
- struct reply_info* qrep, uint32_t flags, struct regional* region)
+ struct reply_info* qrep, uint32_t flags, struct regional* region,
+ time_t qstarttime)
{
struct msgreply_entry* e;
time_t ttl = rep->ttl;
@@ -170,7 +176,8 @@ dns_cache_store_msg(struct module_env* env, struct query_info* qinfo,
/* there was a reply_info_sortref(rep) here but it seems to be
* unnecessary, because the cache gets locked per rrset. */
reply_info_set_ttls(rep, *env->now);
- store_rrsets(env, rep, *env->now, leeway, pside, qrep, region);
+ store_rrsets(env, rep, *env->now, leeway, pside, qrep, region,
+ qstarttime);
if(ttl == 0 && !(flags & DNSCACHE_STORE_ZEROTTL)) {
/* we do not store the message, but we did store the RRs,
* which could be useful for delegation information */
@@ -194,10 +201,51 @@ dns_cache_store_msg(struct module_env* env, struct query_info* qinfo,
slabhash_insert(env->msg_cache, hash, &e->entry, rep, env->alloc);
}
+/** see if an rrset is expired above the qname, return upper qname. */
+static int
+rrset_expired_above(struct module_env* env, uint8_t** qname, size_t* qnamelen,
+ uint16_t searchtype, uint16_t qclass, time_t now, uint8_t* expiretop,
+ size_t expiretoplen)
+{
+ struct ub_packed_rrset_key *rrset;
+ uint8_t lablen;
+
+ while(*qnamelen > 0) {
+ /* look one label higher */
+ lablen = **qname;
+ *qname += lablen + 1;
+ *qnamelen -= lablen + 1;
+ if(*qnamelen <= 0)
+ break;
+
+ /* looks up with a time of 0, to see expired entries */
+ if((rrset = rrset_cache_lookup(env->rrset_cache, *qname,
+ *qnamelen, searchtype, qclass, 0, 0, 0))) {
+ struct packed_rrset_data* data =
+ (struct packed_rrset_data*)rrset->entry.data;
+ if(now > data->ttl) {
+ /* it is expired, this is not wanted */
+ lock_rw_unlock(&rrset->entry.lock);
+ log_nametypeclass(VERB_ALGO, "this rrset is expired", *qname, searchtype, qclass);
+ return 1;
+ }
+ /* it is not expired, continue looking */
+ lock_rw_unlock(&rrset->entry.lock);
+ }
+
+ /* do not look above the expiretop. */
+ if(expiretop && *qnamelen == expiretoplen &&
+ query_dname_compare(*qname, expiretop)==0)
+ break;
+ }
+ return 0;
+}
+
/** find closest NS or DNAME and returns the rrset (locked) */
static struct ub_packed_rrset_key*
find_closest_of_type(struct module_env* env, uint8_t* qname, size_t qnamelen,
- uint16_t qclass, time_t now, uint16_t searchtype, int stripfront)
+ uint16_t qclass, time_t now, uint16_t searchtype, int stripfront,
+ int noexpiredabove, uint8_t* expiretop, size_t expiretoplen)
{
struct ub_packed_rrset_key *rrset;
uint8_t lablen;
@@ -212,8 +260,40 @@ find_closest_of_type(struct module_env* env, uint8_t* qname, size_t qnamelen,
/* snip off front part of qname until the type is found */
while(qnamelen > 0) {
if((rrset = rrset_cache_lookup(env->rrset_cache, qname,
- qnamelen, searchtype, qclass, 0, now, 0)))
- return rrset;
+ qnamelen, searchtype, qclass, 0, now, 0))) {
+ uint8_t* origqname = qname;
+ size_t origqnamelen = qnamelen;
+ if(!noexpiredabove)
+ return rrset;
+ /* if expiretop set, do not look above it, but
+ * qname is equal, so the just found result is also
+ * the nonexpired above part. */
+ if(expiretop && qnamelen == expiretoplen &&
+ query_dname_compare(qname, expiretop)==0)
+ return rrset;
+ /* check for expiry, but we have to let go of the rrset
+ * for the lock ordering */
+ lock_rw_unlock(&rrset->entry.lock);
+ /* the expired_above function always takes off one
+ * label (if qnamelen>0) and returns the final qname
+ * where it searched, so we can continue from there
+ * turning the O N*N search into O N. */
+ if(!rrset_expired_above(env, &qname, &qnamelen,
+ searchtype, qclass, now, expiretop,
+ expiretoplen)) {
+ /* we want to return rrset, but it may be
+ * gone from cache, if so, just loop like
+ * it was not in the cache in the first place.
+ */
+ if((rrset = rrset_cache_lookup(env->
+ rrset_cache, origqname, origqnamelen,
+ searchtype, qclass, 0, now, 0))) {
+ return rrset;
+ }
+ }
+ log_nametypeclass(VERB_ALGO, "ignoring rrset because expired rrsets exist above it", origqname, searchtype, qclass);
+ continue;
+ }
/* snip off front label */
lablen = *qname;
@@ -462,7 +542,8 @@ dns_msg_ansadd(struct dns_msg* msg, struct regional* region,
struct delegpt*
dns_cache_find_delegation(struct module_env* env, uint8_t* qname,
size_t qnamelen, uint16_t qtype, uint16_t qclass,
- struct regional* region, struct dns_msg** msg, time_t now)
+ struct regional* region, struct dns_msg** msg, time_t now,
+ int noexpiredabove, uint8_t* expiretop, size_t expiretoplen)
{
/* try to find closest NS rrset */
struct ub_packed_rrset_key* nskey;
@@ -470,7 +551,7 @@ dns_cache_find_delegation(struct module_env* env, uint8_t* qname,
struct delegpt* dp;
nskey = find_closest_of_type(env, qname, qnamelen, qclass, now,
- LDNS_RR_TYPE_NS, 0);
+ LDNS_RR_TYPE_NS, 0, noexpiredabove, expiretop, expiretoplen);
if(!nskey) /* hope the caller has hints to prime or something */
return NULL;
nsdata = (struct packed_rrset_data*)nskey->entry.data;
@@ -840,7 +921,7 @@ dns_cache_lookup(struct module_env* env,
* consistent with the DNAME */
if(!no_partial &&
(rrset=find_closest_of_type(env, qname, qnamelen, qclass, now,
- LDNS_RR_TYPE_DNAME, 1))) {
+ LDNS_RR_TYPE_DNAME, 1, 0, NULL, 0))) {
/* synthesize a DNAME+CNAME message based on this */
enum sec_status sec_status = sec_status_unchecked;
struct dns_msg* msg = synth_dname_msg(rrset, region, now, &k,
@@ -973,7 +1054,7 @@ dns_cache_lookup(struct module_env* env,
int
dns_cache_store(struct module_env* env, struct query_info* msgqinf,
struct reply_info* msgrep, int is_referral, time_t leeway, int pside,
- struct regional* region, uint32_t flags)
+ struct regional* region, uint32_t flags, time_t qstarttime)
{
struct reply_info* rep = NULL;
/* alloc, malloc properly (not in region, like msg is) */
@@ -996,9 +1077,9 @@ dns_cache_store(struct module_env* env, struct query_info* msgqinf,
/*ignore ret: it was in the cache, ref updated */
/* no leeway for typeNS */
(void)rrset_cache_update(env->rrset_cache, &ref,
- env->alloc, *env->now +
+ env->alloc,
((ntohs(ref.key->rk.type)==LDNS_RR_TYPE_NS
- && !pside) ? 0:leeway));
+ && !pside) ? qstarttime:*env->now + leeway));
}
free(rep);
return 1;
@@ -1020,7 +1101,7 @@ dns_cache_store(struct module_env* env, struct query_info* msgqinf,
rep->flags &= ~(BIT_AA | BIT_CD);
h = query_info_hash(&qinf, (uint16_t)flags);
dns_cache_store_msg(env, &qinf, h, rep, leeway, pside, msgrep,
- flags, region);
+ flags, region, qstarttime);
/* qname is used inside query_info_entrysetup, and set to
* NULL. If it has not been used, free it. free(0) is safe. */
free(qinf.qname);
diff --git a/contrib/unbound/services/cache/dns.h b/contrib/unbound/services/cache/dns.h
index bece83702960..147f992cbc74 100644
--- a/contrib/unbound/services/cache/dns.h
+++ b/contrib/unbound/services/cache/dns.h
@@ -88,11 +88,13 @@ struct dns_msg {
* @param flags: flags with BIT_CD for AAAA queries in dns64 translation.
* The higher 16 bits are used internally to customize the cache policy.
* (See DNSCACHE_STORE_xxx flags).
+ * @param qstarttime: time when the query was started, and thus when the
+ * delegations were looked up.
* @return 0 on alloc error (out of memory).
*/
int dns_cache_store(struct module_env* env, struct query_info* qinf,
struct reply_info* rep, int is_referral, time_t leeway, int pside,
- struct regional* region, uint32_t flags);
+ struct regional* region, uint32_t flags, time_t qstarttime);
/**
* Store message in the cache. Stores in message cache and rrset cache.
@@ -112,11 +114,14 @@ int dns_cache_store(struct module_env* env, struct query_info* qinf,
* can be updated to full TTL even in prefetch situations.
* @param qrep: message that can be altered with better rrs from cache.
* @param flags: customization flags for the cache policy.
+ * @param qstarttime: time when the query was started, and thus when the
+ * delegations were looked up.
* @param region: to allocate into for qmsg.
*/
void dns_cache_store_msg(struct module_env* env, struct query_info* qinfo,
hashvalue_type hash, struct reply_info* rep, time_t leeway, int pside,
- struct reply_info* qrep, uint32_t flags, struct regional* region);
+ struct reply_info* qrep, uint32_t flags, struct regional* region,
+ time_t qstarttime);
/**
* Find a delegation from the cache.
@@ -129,11 +134,18 @@ void dns_cache_store_msg(struct module_env* env, struct query_info* qinfo,
* @param msg: if not NULL, delegation message is returned here, synthesized
* from the cache.
* @param timenow: the time now, for checking if TTL on cache entries is OK.
+ * @param noexpiredabove: if set, no expired NS rrsets above the one found
+ * are tolerated. It only returns delegations where the delegations above
+ * it are valid.
+ * @param expiretop: if not NULL, name where check for expiry ends for
+ * noexpiredabove.
+ * @param expiretoplen: length of expiretop dname.
* @return new delegation or NULL on error or if not found in cache.
*/
struct delegpt* dns_cache_find_delegation(struct module_env* env,
uint8_t* qname, size_t qnamelen, uint16_t qtype, uint16_t qclass,
- struct regional* region, struct dns_msg** msg, time_t timenow);
+ struct regional* region, struct dns_msg** msg, time_t timenow,
+ int noexpiredabove, uint8_t* expiretop, size_t expiretoplen);
/**
* generate dns_msg from cached message
diff --git a/contrib/unbound/services/cache/infra.c b/contrib/unbound/services/cache/infra.c
index 252e1e288b35..0461c815b86b 100644
--- a/contrib/unbound/services/cache/infra.c
+++ b/contrib/unbound/services/cache/infra.c
@@ -721,13 +721,13 @@ infra_get_lame_rtt(struct infra_cache* infra,
else *rtt = USEFUL_SERVER_TOP_TIMEOUT-1000;
}
}
+ /* expired entry */
if(timenow > host->ttl) {
- /* expired entry */
+
/* see if this can be a re-probe of an unresponsive server */
/* minus 1000 because that is outside of the RTTBAND, so
* blacklisted servers stay blacklisted if this is chosen */
- if(host->rtt.rto >= USEFUL_SERVER_TOP_TIMEOUT ||
- infra->infra_keep_probing) {
+ if(host->rtt.rto >= USEFUL_SERVER_TOP_TIMEOUT) {
lock_rw_unlock(&e->lock);
*rtt = USEFUL_SERVER_TOP_TIMEOUT-1000;
*lame = 0;
diff --git a/contrib/unbound/services/listen_dnsport.c b/contrib/unbound/services/listen_dnsport.c
index 03153bd64778..1c7c177a007e 100644
--- a/contrib/unbound/services/listen_dnsport.c
+++ b/contrib/unbound/services/listen_dnsport.c
@@ -490,6 +490,7 @@ create_udp_sock(int family, int socktype, struct sockaddr* addr,
return -1;
}
# elif defined(IPV6_MTU)
+# ifndef USE_WINSOCK
/*
* On Linux, to send no larger than 1280, the PMTUD is
* disabled by default for datagrams anyway, so we set
@@ -497,13 +498,27 @@ create_udp_sock(int family, int socktype, struct sockaddr* addr,
*/
if (setsockopt(s, IPPROTO_IPV6, IPV6_MTU,
(void*)&mtu, (socklen_t)sizeof(mtu)) < 0) {
- log_err("setsockopt(..., IPV6_MTU, ...) failed: %s",
+ log_err("setsockopt(..., IPV6_MTU, ...) failed: %s",
sock_strerror(errno));
sock_close(s);
*noproto = 0;
*inuse = 0;
return -1;
}
+# elif defined(IPV6_USER_MTU)
+ /* As later versions of the mingw crosscompiler define
+ * IPV6_MTU, do the same for windows but use IPV6_USER_MTU
+ * instead which is writable; IPV6_MTU is readonly there. */
+ if (setsockopt(s, IPPROTO_IPV6, IPV6_USER_MTU,
+ (void*)&mtu, (socklen_t)sizeof(mtu)) < 0) {
+ log_err("setsockopt(..., IPV6_USER_MTU, ...) failed: %s",
+ wsa_strerror(WSAGetLastError()));
+ sock_close(s);
+ *noproto = 0;
+ *inuse = 0;
+ return -1;
+ }
+# endif /* USE_WINSOCK */
# endif /* IPv6 MTU */
# if defined(IPV6_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT)
# if defined(IP_PMTUDISC_OMIT)
diff --git a/contrib/unbound/services/mesh.c b/contrib/unbound/services/mesh.c
index c40eb50dc55c..30bcf7cda155 100644
--- a/contrib/unbound/services/mesh.c
+++ b/contrib/unbound/services/mesh.c
@@ -954,6 +954,7 @@ mesh_state_create(struct module_env* env, struct query_info* qinfo,
mstate->s.no_cache_store = 0;
mstate->s.need_refetch = 0;
mstate->s.was_ratelimited = 0;
+ mstate->s.qstarttime = *env->now;
/* init modules */
for(i=0; i<env->mesh->mods.num; i++) {
diff --git a/contrib/unbound/sldns/rrdef.c b/contrib/unbound/sldns/rrdef.c
index fe5c8e104a88..322eff096c03 100644
--- a/contrib/unbound/sldns/rrdef.c
+++ b/contrib/unbound/sldns/rrdef.c
@@ -381,9 +381,9 @@ static sldns_rr_descriptor rdata_field_descriptors[] = {
/* 63 */
{LDNS_RR_TYPE_ZONEMD, "ZONEMD", 4, 4, type_zonemd_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
/* 64 */
- {LDNS_RR_TYPE_SVCB, "SVCB", 2, 2, type_svcb_wireformat, LDNS_RDF_TYPE_SVCPARAM, LDNS_RR_NO_COMPRESS, 0 },
+ {LDNS_RR_TYPE_SVCB, "SVCB", 2, 2, type_svcb_wireformat, LDNS_RDF_TYPE_SVCPARAM, LDNS_RR_NO_COMPRESS, 1 },
/* 65 */
- {LDNS_RR_TYPE_HTTPS, "HTTPS", 2, 2, type_svcb_wireformat, LDNS_RDF_TYPE_SVCPARAM, LDNS_RR_NO_COMPRESS, 0 },
+ {LDNS_RR_TYPE_HTTPS, "HTTPS", 2, 2, type_svcb_wireformat, LDNS_RDF_TYPE_SVCPARAM, LDNS_RR_NO_COMPRESS, 1 },
{(enum sldns_enum_rr_type)0, "TYPE66", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
{(enum sldns_enum_rr_type)0, "TYPE67", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
{(enum sldns_enum_rr_type)0, "TYPE68", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
diff --git a/contrib/unbound/sldns/wire2str.c b/contrib/unbound/sldns/wire2str.c
index d6fb289650b2..74d1b62dfe8d 100644
--- a/contrib/unbound/sldns/wire2str.c
+++ b/contrib/unbound/sldns/wire2str.c
@@ -1071,7 +1071,7 @@ static int sldns_wire2str_svcparam_mandatory2str(char** s,
assert(data_len > 0);
if (data_len % sizeof(uint16_t))
- return -1; // wireformat error, data_len must be multiple of shorts
+ return -1; /* wireformat error, data_len must be multiple of shorts */
w += sldns_str_print(s, slen, "=");
w += sldns_print_svcparamkey(s, slen, sldns_read_uint16(data));
data += 2;
diff --git a/contrib/unbound/testdata/iter_ghost_sub.rpl b/contrib/unbound/testdata/iter_ghost_sub.rpl
new file mode 100644
index 000000000000..ccd6b29842e4
--- /dev/null
+++ b/contrib/unbound/testdata/iter_ghost_sub.rpl
@@ -0,0 +1,309 @@
+; config options
+server:
+ target-fetch-policy: "0 0 0 0 0"
+ qname-minimisation: "no"
+ minimal-responses: no
+
+stub-zone:
+ name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN Test ghost subdomain of another subdomain.
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. 86400 IN NS
+SECTION ANSWER
+. 86400 IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. 86400 IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION AUTHORITY
+com. 86400 IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. 86400 IN A 192.5.6.30
+ENTRY_END
+
+RANGE_END
+
+; a.gtld-servers.net.
+; this is the one where example.com is delegated.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. 86400 IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. 86400 IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net.
+; this is the one where example.com is no longer delegated.
+RANGE_BEGIN 100 200
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. 86400 IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. 86400 IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NXDOMAIN
+SECTION QUESTION
+example.com. IN NS
+SECTION AUTHORITY
+com. 86400 IN SOA a. b. 1 2 3 4 5
+ENTRY_END
+RANGE_END
+
+; ns.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.4
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.com. IN A
+SECTION ANSWER
+ns.example.com. IN A 1.2.3.4
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.com. IN AAAA
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com IN A 1.2.3.4
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+s.example.com. IN A
+SECTION ANSWER
+s.example.com. IN A 1.2.3.4
+SECTION AUTHORITY
+s.example.com. IN NS s.example.com.
+SECTION ADDITIONAL
+s.example.com IN A 1.2.3.4
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+s.s.example.com. IN A
+SECTION ANSWER
+s.s.example.com. IN A 1.2.3.4
+SECTION AUTHORITY
+s.s.example.com. IN NS s.s.example.com.
+SECTION ADDITIONAL
+s.s.example.com IN A 1.2.3.4
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+; get the delegation in cache
+STEP 20 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com IN A 1.2.3.4
+ENTRY_END
+
+; time passes
+STEP 25 TIME_PASSES ELAPSE 1800
+
+; get another delegation in cache
+STEP 30 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+s.example.com. IN A
+ENTRY_END
+
+STEP 40 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+s.example.com. IN A
+SECTION ANSWER
+s.example.com. IN A 1.2.3.4
+SECTION AUTHORITY
+s.example.com. IN NS s.example.com.
+ENTRY_END
+
+; time passes, 1800 + 1000 = 2800 of 3600 TTL on NS of s.example.com. and
+; example.com.
+STEP 45 TIME_PASSES ELAPSE 1000
+
+; get another delegation in cache
+STEP 50 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+s.s.example.com. IN A
+ENTRY_END
+
+STEP 60 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+s.s.example.com. IN A
+SECTION ANSWER
+s.s.example.com. IN A 1.2.3.4
+SECTION AUTHORITY
+s.s.example.com. IN NS s.s.example.com.
+ENTRY_END
+
+
+; time passes, 1800 + 2000 = 3800 of 3600 TTL on NS of s.example.com. and
+; example.com.
+STEP 75 TIME_PASSES ELAPSE 1000
+
+; domain no longer delegated
+; is the domain still up?
+
+STEP 100 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.s.example.com. IN A
+ENTRY_END
+
+STEP 110 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NXDOMAIN
+SECTION QUESTION
+www.s.example.com. IN A
+SECTION AUTHORITY
+com. 86400 IN SOA a. b. 1 2 3 4 5
+ENTRY_END
+
+STEP 120 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.s.s.example.com. IN A
+ENTRY_END
+
+STEP 130 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NXDOMAIN
+SECTION QUESTION
+www.s.s.example.com. IN A
+SECTION AUTHORITY
+com. 86400 IN SOA a. b. 1 2 3 4 5
+ENTRY_END
+
+STEP 140 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+STEP 150 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NXDOMAIN
+SECTION QUESTION
+www.example.com. IN A
+SECTION AUTHORITY
+com. 86400 IN SOA a. b. 1 2 3 4 5
+ENTRY_END
+
+SCENARIO_END
diff --git a/contrib/unbound/testdata/iter_ghost_timewindow.rpl b/contrib/unbound/testdata/iter_ghost_timewindow.rpl
new file mode 100644
index 000000000000..566be82a9cf8
--- /dev/null
+++ b/contrib/unbound/testdata/iter_ghost_timewindow.rpl
@@ -0,0 +1,391 @@
+; config options
+server:
+ target-fetch-policy: "0 0 0 0 0"
+ qname-minimisation: "no"
+ minimal-responses: no
+
+stub-zone:
+ name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN Test ghost subdomain with extension reply in timewindow.
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+. 86400 IN NS
+SECTION ANSWER
+. 86400 IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. 86400 IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION AUTHORITY
+com. 86400 IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. 86400 IN A 192.5.6.30
+ENTRY_END
+
+RANGE_END
+
+; a.gtld-servers.net.
+; this is the one where example.com is delegated.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. 86400 IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. 86400 IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example2.com. IN NS
+SECTION AUTHORITY
+example2.com. 3610 IN NS ns.example2.com.
+SECTION ADDITIONAL
+ns.example2.com. 3610 IN A 1.2.3.5
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net.
+; this is the one where example.com is no longer delegated.
+RANGE_BEGIN 100 300
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. 86400 IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. 86400 IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NXDOMAIN
+SECTION QUESTION
+example.com. IN NS
+SECTION AUTHORITY
+com. 86400 IN SOA a. b. 1 2 3 4 5
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NXDOMAIN
+SECTION QUESTION
+example2.com. IN NS
+SECTION AUTHORITY
+com. 86400 IN SOA a. b. 1 2 3 4 5
+ENTRY_END
+RANGE_END
+
+; ns.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.4
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+ns.example.com. IN A
+SECTION ANSWER
+ns.example.com. IN A 1.2.3.4
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+ns.example.com. IN AAAA
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com IN A 1.2.3.4
+ENTRY_END
+RANGE_END
+
+; ns.example2.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.5
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+example2.com. IN NS
+SECTION ANSWER
+example2.com. 3610 IN NS ns.example2.com.
+SECTION ADDITIONAL
+ns.example2.com. 3610 IN A 1.2.3.5
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+ns.example2.com. IN A
+SECTION ANSWER
+ns.example2.com. 3610 IN A 1.2.3.5
+SECTION AUTHORITY
+example2.com. 3610 IN NS ns.example2.com.
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+ns.example2.com. IN AAAA
+SECTION AUTHORITY
+example2.com. 3610 IN NS ns.example2.com.
+SECTION ADDITIONAL
+ns.example2.com. 3610 IN A 1.2.3.5
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+www.example2.com. IN A
+SECTION ANSWER
+www.example2.com. 3610 IN A 10.20.30.40
+SECTION AUTHORITY
+example2.com. 3610 IN NS ns.example2.com.
+SECTION ADDITIONAL
+ns.example2.com 3610 IN A 1.2.3.5
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+; get the delegation in cache
+STEP 20 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com IN A 1.2.3.4
+ENTRY_END
+
+; get example2 in cache too to check other response type
+STEP 30 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.example2.com. IN A
+ENTRY_END
+
+STEP 40 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+www.example2.com. IN A
+SECTION ANSWER
+www.example2.com. IN A 10.20.30.40
+SECTION AUTHORITY
+example2.com. IN NS ns.example2.com.
+SECTION ADDITIONAL
+ns.example2.com IN A 1.2.3.5
+ENTRY_END
+
+; time passes
+STEP 95 TIME_PASSES ELAPSE 3595
+
+STEP 100 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+ns.example.com. IN A
+ENTRY_END
+
+; ns.example.com RANGE does not answer, only until step 100,
+; so we provide an answer, but first, let time pass beyond the TTL.
+; it is going to time 3605, just passed the 3600 expire TTL, but the
+; query started at 3595 before the TTL expired.
+STEP 110 TIME_PASSES ELAPSE 10
+
+; provide the answer to the query sent.
+STEP 120 CHECK_OUT_QUERY
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+ns.example.com. IN A
+SECTION ANSWER
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com IN A 1.2.3.4
+ENTRY_END
+
+STEP 130 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+ns.example.com. IN A
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+
+; check if the domain is still live.
+STEP 140 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www2.example.com. IN A
+ENTRY_END
+
+STEP 150 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NXDOMAIN
+SECTION QUESTION
+www2.example.com. IN A
+SECTION AUTHORITY
+com. 86400 IN SOA a. b. 1 2 3 4 5
+ENTRY_END
+
+; example2 is valid with TTL of 3610, it is time 3605
+STEP 160 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+ns.example2.com. IN A
+ENTRY_END
+
+; move to time 3615
+STEP 170 TIME_PASSES ELAPSE 10
+
+STEP 180 CHECK_OUT_QUERY
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+ns.example2.com. IN A
+SECTION ANSWER
+ns.example2.com. IN A 1.2.3.5
+SECTION AUTHORITY
+example2.com. IN NS ns.example2.com.
+SECTION ADDITIONAL
+ns.example2.com. IN A 1.2.3.5
+ENTRY_END
+
+STEP 190 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+ns.example2.com. IN A
+SECTION ANSWER
+ns.example2.com IN A 1.2.3.5
+SECTION AUTHORITY
+example2.com. IN NS ns.example2.com.
+SECTION ADDITIONAL
+ENTRY_END
+
+; check if the domain is still live.
+STEP 200 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www2.example2.com. IN A
+ENTRY_END
+
+STEP 210 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NXDOMAIN
+SECTION QUESTION
+www2.example2.com. IN A
+SECTION AUTHORITY
+com. 86400 IN SOA a. b. 1 2 3 4 5
+ENTRY_END
+
+SCENARIO_END
diff --git a/contrib/unbound/util/config_file.c b/contrib/unbound/util/config_file.c
index 363af3c2c5a9..976cb976f48e 100644
--- a/contrib/unbound/util/config_file.c
+++ b/contrib/unbound/util/config_file.c
@@ -173,6 +173,7 @@ config_create(void)
cfg->infra_cache_slabs = 4;
cfg->infra_cache_numhosts = 10000;
cfg->infra_cache_min_rtt = 50;
+ cfg->infra_cache_max_rtt = 120000;
cfg->infra_keep_probing = 0;
cfg->delay_close = 0;
cfg->udp_connect = 1;
@@ -595,8 +596,14 @@ int config_set_option(struct config_file* cfg, const char* opt,
else if(strcmp(opt, "cache-min-ttl:") == 0)
{ IS_NUMBER_OR_ZERO; cfg->min_ttl = atoi(val); MIN_TTL=(time_t)cfg->min_ttl;}
else if(strcmp(opt, "infra-cache-min-rtt:") == 0) {
- IS_NUMBER_OR_ZERO; cfg->infra_cache_min_rtt = atoi(val);
- RTT_MIN_TIMEOUT=cfg->infra_cache_min_rtt;
+ IS_NUMBER_OR_ZERO; cfg->infra_cache_min_rtt = atoi(val);
+ RTT_MIN_TIMEOUT=cfg->infra_cache_min_rtt;
+ }
+ else if(strcmp(opt, "infra-cache-max-rtt:") == 0) {
+ IS_NUMBER_OR_ZERO; cfg->infra_cache_max_rtt = atoi(val);
+ RTT_MAX_TIMEOUT=cfg->infra_cache_max_rtt;
+ USEFUL_SERVER_TOP_TIMEOUT = RTT_MAX_TIMEOUT;
+ BLACKLIST_PENALTY = USEFUL_SERVER_TOP_TIMEOUT*4;
}
else S_YNO("infra-keep-probing:", infra_keep_probing)
else S_NUMBER_OR_ZERO("infra-host-ttl:", host_ttl)
@@ -1026,6 +1033,7 @@ config_get_option(struct config_file* cfg, const char* opt,
else O_DEC(opt, "infra-host-ttl", host_ttl)
else O_DEC(opt, "infra-cache-slabs", infra_cache_slabs)
else O_DEC(opt, "infra-cache-min-rtt", infra_cache_min_rtt)
+ else O_UNS(opt, "infra-cache-max-rtt", infra_cache_max_rtt)
else O_YNO(opt, "infra-keep-probing", infra_keep_probing)
else O_MEM(opt, "infra-cache-numhosts", infra_cache_numhosts)
else O_UNS(opt, "delay-close", delay_close)
@@ -2222,11 +2230,14 @@ config_apply(struct config_file* config)
SERVE_ORIGINAL_TTL = config->serve_original_ttl;
MAX_NEG_TTL = (time_t)config->max_negative_ttl;
RTT_MIN_TIMEOUT = config->infra_cache_min_rtt;
+ RTT_MAX_TIMEOUT = config->infra_cache_max_rtt;
EDNS_ADVERTISED_SIZE = (uint16_t)config->edns_buffer_size;
MINIMAL_RESPONSES = config->minimal_responses;
RRSET_ROUNDROBIN = config->rrset_roundrobin;
LOG_TAG_QUERYREPLY = config->log_tag_queryreply;
UNKNOWN_SERVER_NICENESS = config->unknown_server_time_limit;
+ USEFUL_SERVER_TOP_TIMEOUT = RTT_MAX_TIMEOUT;
+ BLACKLIST_PENALTY = USEFUL_SERVER_TOP_TIMEOUT*4;
log_set_time_asc(config->log_time_ascii);
autr_permit_small_holddown = config->permit_small_holddown;
stream_wait_max = config->stream_wait_size;
diff --git a/contrib/unbound/util/config_file.h b/contrib/unbound/util/config_file.h
index 0b457e3476b9..ed372522dfae 100644
--- a/contrib/unbound/util/config_file.h
+++ b/contrib/unbound/util/config_file.h
@@ -186,8 +186,10 @@ struct config_file {
size_t infra_cache_slabs;
/** max number of hosts in the infra cache */
size_t infra_cache_numhosts;
- /** min value for infra cache rtt */
+ /** min value for infra cache rtt (min retransmit timeout) */
int infra_cache_min_rtt;
+ /** max value for infra cache rtt (max retransmit timeout) */
+ int infra_cache_max_rtt;
/** keep probing hosts that are down */
int infra_keep_probing;
/** delay close of udp-timeouted ports, if 0 no delayclose. in msec */
diff --git a/contrib/unbound/util/configlexer.lex b/contrib/unbound/util/configlexer.lex
index 96e542fd1fd2..7f7704b337ba 100644
--- a/contrib/unbound/util/configlexer.lex
+++ b/contrib/unbound/util/configlexer.lex
@@ -303,6 +303,7 @@ infra-cache-slabs{COLON} { YDVAR(1, VAR_INFRA_CACHE_SLABS) }
infra-cache-numhosts{COLON} { YDVAR(1, VAR_INFRA_CACHE_NUMHOSTS) }
infra-cache-lame-size{COLON} { YDVAR(1, VAR_INFRA_CACHE_LAME_SIZE) }
infra-cache-min-rtt{COLON} { YDVAR(1, VAR_INFRA_CACHE_MIN_RTT) }
+infra-cache-max-rtt{COLON} { YDVAR(1, VAR_INFRA_CACHE_MAX_RTT) }
infra-keep-probing{COLON} { YDVAR(1, VAR_INFRA_KEEP_PROBING) }
num-queries-per-thread{COLON} { YDVAR(1, VAR_NUM_QUERIES_PER_THREAD) }
jostle-timeout{COLON} { YDVAR(1, VAR_JOSTLE_TIMEOUT) }
diff --git a/contrib/unbound/util/configparser.y b/contrib/unbound/util/configparser.y
index c003f3358390..c23534019e5e 100644
--- a/contrib/unbound/util/configparser.y
+++ b/contrib/unbound/util/configparser.y
@@ -120,7 +120,7 @@ extern struct config_parser_state* cfg_parser;
%token VAR_STUB_FIRST VAR_MINIMAL_RESPONSES VAR_RRSET_ROUNDROBIN
%token VAR_MAX_UDP_SIZE VAR_DELAY_CLOSE VAR_UDP_CONNECT
%token VAR_UNBLOCK_LAN_ZONES VAR_INSECURE_LAN_ZONES
-%token VAR_INFRA_CACHE_MIN_RTT VAR_INFRA_KEEP_PROBING
+%token VAR_INFRA_CACHE_MIN_RTT VAR_INFRA_CACHE_MAX_RTT VAR_INFRA_KEEP_PROBING
%token VAR_DNS64_PREFIX VAR_DNS64_SYNTHALL VAR_DNS64_IGNORE_AAAA
%token VAR_DNSTAP VAR_DNSTAP_ENABLE VAR_DNSTAP_SOCKET_PATH VAR_DNSTAP_IP
%token VAR_DNSTAP_TLS VAR_DNSTAP_TLS_SERVER_NAME VAR_DNSTAP_TLS_CERT_BUNDLE
@@ -267,7 +267,7 @@ content_server: server_num_threads | server_verbosity | server_port |
server_so_reuseport | server_delay_close | server_udp_connect |
server_unblock_lan_zones | server_insecure_lan_zones |
server_dns64_prefix | server_dns64_synthall | server_dns64_ignore_aaaa |
- server_infra_cache_min_rtt | server_harden_algo_downgrade |
+ server_infra_cache_min_rtt | server_infra_cache_max_rtt | server_harden_algo_downgrade |
server_ip_transparent | server_ip_ratelimit | server_ratelimit |
server_ip_dscp | server_infra_keep_probing |
server_ip_ratelimit_slabs | server_ratelimit_slabs |
@@ -1659,6 +1659,15 @@ server_infra_cache_min_rtt: VAR_INFRA_CACHE_MIN_RTT STRING_ARG
free($2);
}
;
+server_infra_cache_max_rtt: VAR_INFRA_CACHE_MAX_RTT STRING_ARG
+ {
+ OUTYY(("P(server_infra_cache_max_rtt:%s)\n", $2));
+ if(atoi($2) == 0 && strcmp($2, "0") != 0)
+ yyerror("number expected");
+ else cfg_parser->cfg->infra_cache_max_rtt = atoi($2);
+ free($2);
+ }
+ ;
server_infra_keep_probing: VAR_INFRA_KEEP_PROBING STRING_ARG
{
OUTYY(("P(server_infra_keep_probing:%s)\n", $2));
diff --git a/contrib/unbound/util/data/msgreply.c b/contrib/unbound/util/data/msgreply.c
index e3ee607b1540..1e6ee97040cf 100644
--- a/contrib/unbound/util/data/msgreply.c
+++ b/contrib/unbound/util/data/msgreply.c
@@ -1015,7 +1015,7 @@ int edns_opt_list_append_ede(struct edns_option** list, struct regional* region,
prevp = list;
while(*prevp != NULL)
prevp = &((*prevp)->next);
- verbose(VERB_ALGO, "attached EDE code: %d with message: %s", code, txt);
+ verbose(VERB_ALGO, "attached EDE code: %d with message: %s", code, (txt?txt:"\"\""));
*prevp = opt;
return 1;
}
diff --git a/contrib/unbound/util/iana_ports.inc b/contrib/unbound/util/iana_ports.inc
index ae2986c822e5..80a8144d385b 100644
--- a/contrib/unbound/util/iana_ports.inc
+++ b/contrib/unbound/util/iana_ports.inc
@@ -3976,6 +3976,7 @@
4789,
4790,
4791,
+4792,
4800,
4801,
4802,
diff --git a/contrib/unbound/util/module.h b/contrib/unbound/util/module.h
index 33068a71ce6e..013c65b02dcf 100644
--- a/contrib/unbound/util/module.h
+++ b/contrib/unbound/util/module.h
@@ -665,6 +665,12 @@ struct module_qstate {
int need_refetch;
/** whether the query (or a subquery) was ratelimited */
int was_ratelimited;
+ /** time when query was started. This is when the qstate is created.
+ * This is used so that type NS data cannot be overwritten by them
+ * expiring while the lookup is in progress, using data fetched from
+ * those servers. By comparing expiry time with qstarttime for type NS.
+ */
+ time_t qstarttime;
/**
* Attributes of clients that share the qstate that may affect IP-based
diff --git a/contrib/unbound/util/rtt.c b/contrib/unbound/util/rtt.c
index f51576fb57fa..b64206ecad18 100644
--- a/contrib/unbound/util/rtt.c
+++ b/contrib/unbound/util/rtt.c
@@ -45,6 +45,9 @@
/* overwritten by config: infra_cache_min_rtt: */
int RTT_MIN_TIMEOUT = 50;
+/* overwritten by config: infra_cache_max_rtt: */
+int RTT_MAX_TIMEOUT = 120000;
+
/** calculate RTO from rtt information */
static int
calc_rto(const struct rtt_info* rtt)
diff --git a/contrib/unbound/util/rtt.h b/contrib/unbound/util/rtt.h
index 07e65ee1d3d1..63ed8eadb9df 100644
--- a/contrib/unbound/util/rtt.h
+++ b/contrib/unbound/util/rtt.h
@@ -58,7 +58,7 @@ struct rtt_info {
/** min retransmit timeout value, in milliseconds */
extern int RTT_MIN_TIMEOUT;
/** max retransmit timeout value, in milliseconds */
-#define RTT_MAX_TIMEOUT 120000
+extern int RTT_MAX_TIMEOUT;
/**
* Initialize RTT estimators.
diff --git a/contrib/unbound/validator/val_utils.c b/contrib/unbound/validator/val_utils.c
index 18c963d863f1..e2319ee2399d 100644
--- a/contrib/unbound/validator/val_utils.c
+++ b/contrib/unbound/validator/val_utils.c
@@ -489,7 +489,6 @@ int val_favorite_ds_algo(struct ub_packed_rrset_key* ds_rrset)
return digest_algo;
}
-// @TODO change the use of this function to _ede function in authzone.c:8111
enum sec_status
val_verify_DNSKEY_with_DS(struct module_env* env, struct val_env* ve,
struct ub_packed_rrset_key* dnskey_rrset,
diff --git a/contrib/unbound/validator/validator.c b/contrib/unbound/validator/validator.c
index 75f3220cf3d9..1723afefe353 100644
--- a/contrib/unbound/validator/validator.c
+++ b/contrib/unbound/validator/validator.c
@@ -2202,7 +2202,7 @@ processFinished(struct module_qstate* qstate, struct val_qstate* vq,
if(!qstate->no_cache_store) {
if(!dns_cache_store(qstate->env, &vq->orig_msg->qinfo,
vq->orig_msg->rep, 0, qstate->prefetch_leeway, 0, NULL,
- qstate->query_flags)) {
+ qstate->query_flags, qstate->qstarttime)) {
log_err("out of memory caching validator results");
}
}
@@ -2211,7 +2211,7 @@ processFinished(struct module_qstate* qstate, struct val_qstate* vq,
/* and this does not get prefetched, so no leeway */
if(!dns_cache_store(qstate->env, &vq->orig_msg->qinfo,
vq->orig_msg->rep, 1, 0, 0, NULL,
- qstate->query_flags)) {
+ qstate->query_flags, qstate->qstarttime)) {
log_err("out of memory caching validator results");
}
}
@@ -2493,7 +2493,8 @@ ds_response_to_ke(struct module_qstate* qstate, struct val_qstate* vq,
/* If they aren't usable, then we treat it like
* there was no DS. */
- // @TODO add EDE Unsupported DS Digest Type
+ /* TODO add EDE Unsupported DS Digest Type; this needs
+ * EDE to be added on non SERVFAIL answers. */
*ke = key_entry_create_null(qstate->region,
qinfo->qname, qinfo->qname_len, qinfo->qclass,