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 . # @@ -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 .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 +Upper limit for dynamic retransmit timeout calculation in infrastructure +cache. Default is 2 minutes. +.TP .B infra\-keep\-probing: \fI 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 -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 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; imesh->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,