diff --git a/Makefile.in b/Makefile.in index c262250ca..b8d2a96b2 100644 --- a/Makefile.in +++ b/Makefile.in @@ -509,10 +509,15 @@ util/configlexer.c: $(srcdir)/util/configlexer.lex util/configparser.h fi @if test ! -f $@; then echo "No $@ : need flex and bison to compile from source repository"; exit 1; fi -util/configparser.c util/configparser.h: $(srcdir)/util/configparser.y +# Builds both util/configparser.c and util/configparser.h. +# To avoid double-building we split one target out. +util/configparser.c: $(srcdir)/util/configparser.y @-if test ! -d util; then $(INSTALL) -d util; fi $(YACC) -d -o util/configparser.c $(srcdir)/util/configparser.y +util/configparser.h: util/configparser.c + touch $@ + clean: rm -f *.o *.d *.lo *~ tags rm -f unbound$(EXEEXT) unbound-checkconf$(EXEEXT) unbound-host$(EXEEXT) unbound-control$(EXEEXT) unbound-anchor$(EXEEXT) unbound-control-setup libunbound.la unbound.h diff --git a/cachedb/cachedb.c b/cachedb/cachedb.c index 0329f8458..eca3b7cb7 100644 --- a/cachedb/cachedb.c +++ b/cachedb/cachedb.c @@ -755,7 +755,8 @@ cachedb_intcache_store(struct module_qstate* qstate, int msg_expired) } (void)dns_cache_store(qstate->env, &qstate->qinfo, qstate->return_msg->rep, 0, qstate->prefetch_leeway, 0, - qstate->region, store_flags, qstate->qstarttime); + qstate->region, store_flags, qstate->qstarttime, + qstate->is_valrec); if(serve_expired && msg_expired) { if(qstate->env->cfg->serve_expired_client_timeout) { /* No expired response from the query state, the diff --git a/cachedb/redis.c b/cachedb/redis.c index 68c033535..248a3d7b4 100644 --- a/cachedb/redis.c +++ b/cachedb/redis.c @@ -61,6 +61,7 @@ struct redis_moddata { struct timeval command_timeout; /* timeout for commands */ struct timeval connect_timeout; /* timeout for connect */ int logical_db; /* the redis logical database to use */ + int setex_available; /* if the SETEX command is supported */ }; static redisReply* redis_command(struct module_env*, struct cachedb_env*, @@ -102,7 +103,7 @@ redis_connect(const struct redis_moddata* moddata) goto fail; } if(redisSetTimeout(ctx, moddata->command_timeout) != REDIS_OK) { - log_err("failed to set redis timeout"); + log_err("failed to set redis timeout, %s", ctx->errstr); goto fail; } if(moddata->server_password && moddata->server_password[0]!=0) { @@ -182,13 +183,16 @@ redis_init(struct module_env* env, struct cachedb_env* cachedb_env) for(i = 0; i < moddata->numctxs; i++) { redisContext* ctx = redis_connect(moddata); if(!ctx) { - log_err("redis_init: failed to init redis"); - goto fail; + log_err("redis_init: failed to init redis " + "(for thread %d)", i); + /* And continue, the context can be established + * later, just like after a disconnect. */ } moddata->ctxs[i] = ctx; } cachedb_env->backend_data = moddata; - if(env->cfg->redis_expire_records) { + if(env->cfg->redis_expire_records && + moddata->ctxs[env->alloc->thread_num] != NULL) { redisReply* rep = NULL; int redis_reply_type = 0; /** check if setex command is supported */ @@ -196,10 +200,7 @@ redis_init(struct module_env* env, struct cachedb_env* cachedb_env) "SETEX __UNBOUND_REDIS_CHECK__ 1 none", NULL, 0); if(!rep) { /** init failed, no response from redis server*/ - log_err("redis_init: failed to init redis, the " - "redis-expire-records option requires the SETEX command " - "(redis >= 2.0.0)"); - goto fail; + goto setex_fail; } redis_reply_type = rep->type; freeReplyObject(rep); @@ -208,14 +209,17 @@ redis_init(struct module_env* env, struct cachedb_env* cachedb_env) break; default: /** init failed, setex command not supported */ - log_err("redis_init: failed to init redis, the " - "redis-expire-records option requires the SETEX command " - "(redis >= 2.0.0)"); - goto fail; + goto setex_fail; } + moddata->setex_available = 1; } return 1; +setex_fail: + log_err("redis_init: failure during redis_init, the " + "redis-expire-records option requires the SETEX command " + "(redis >= 2.0.0)"); + return 1; fail: moddata_clean(&moddata); return 0; @@ -346,7 +350,10 @@ redis_store(struct module_env* env, struct cachedb_env* cachedb_env, { redisReply* rep; int n; - int set_ttl = (env->cfg->redis_expire_records && + struct redis_moddata* moddata = (struct redis_moddata*) + cachedb_env->backend_data; + int set_ttl = (moddata->setex_available && + env->cfg->redis_expire_records && (!env->cfg->serve_expired || env->cfg->serve_expired_ttl > 0)); /* Supported commands: * - "SET " + key + " %b" diff --git a/daemon/cachedump.c b/daemon/cachedump.c index c4f55d8c9..a04b24e56 100644 --- a/daemon/cachedump.c +++ b/daemon/cachedump.c @@ -692,7 +692,7 @@ load_msg(RES* ssl, sldns_buffer* buf, struct worker* worker) return 1; /* skip this one, not all references satisfied */ if(!dns_cache_store(&worker->env, &qinf, &rep, 0, 0, 0, NULL, flags, - *worker->env.now)) { + *worker->env.now, 1)) { log_warn("error out of memory"); return 0; } diff --git a/daemon/remote.c b/daemon/remote.c index 8877cd194..4d7cff4db 100644 --- a/daemon/remote.c +++ b/daemon/remote.c @@ -707,6 +707,10 @@ print_stats(RES* ssl, const char* nm, struct ub_stats_info* s) (unsigned long)s->svr.num_queries_cookie_client)) return 0; if(!ssl_printf(ssl, "%s.num.queries_cookie_invalid"SQ"%lu\n", nm, (unsigned long)s->svr.num_queries_cookie_invalid)) return 0; + if(!ssl_printf(ssl, "%s.num.queries_discard_timeout"SQ"%lu\n", nm, + (unsigned long)s->svr.num_queries_discard_timeout)) return 0; + if(!ssl_printf(ssl, "%s.num.queries_wait_limit"SQ"%lu\n", nm, + (unsigned long)s->svr.num_queries_wait_limit)) return 0; if(!ssl_printf(ssl, "%s.num.cachehits"SQ"%lu\n", nm, (unsigned long)(s->svr.num_queries - s->svr.num_queries_missed_cache))) return 0; diff --git a/daemon/stats.c b/daemon/stats.c index 0e17300a1..3f2d848b3 100644 --- a/daemon/stats.c +++ b/daemon/stats.c @@ -281,6 +281,10 @@ server_stats_compile(struct worker* worker, struct ub_stats_info* s, int reset) s->svr.rpz_action[i] += (long long)worker->env.mesh->rpz_action[i]; timehist_export(worker->env.mesh->histogram, s->svr.hist, NUM_BUCKETS_HIST); + s->svr.num_queries_discard_timeout += + (long long)worker->env.mesh->num_queries_discard_timeout; + s->svr.num_queries_wait_limit += + (long long)worker->env.mesh->num_queries_wait_limit; /* values from outside network */ s->svr.unwanted_replies = (long long)worker->back->unwanted_replies; s->svr.qtcp_outgoing = (long long)worker->back->num_tcp_outgoing; @@ -325,20 +329,8 @@ server_stats_compile(struct worker* worker, struct ub_stats_info* s, int reset) s->svr.num_query_dnscrypt_replay = 0; #endif /* USE_DNSCRYPT */ if(worker->env.auth_zones) { - if(reset && !worker->env.cfg->stat_cumulative) { - lock_rw_wrlock(&worker->env.auth_zones->lock); - } else { - lock_rw_rdlock(&worker->env.auth_zones->lock); - } - s->svr.num_query_authzone_up = (long long)worker->env. - auth_zones->num_query_up; - s->svr.num_query_authzone_down = (long long)worker->env. - auth_zones->num_query_down; - if(reset && !worker->env.cfg->stat_cumulative) { - worker->env.auth_zones->num_query_up = 0; - worker->env.auth_zones->num_query_down = 0; - } - lock_rw_unlock(&worker->env.auth_zones->lock); + s->svr.num_query_authzone_up += (long long)worker->env.mesh->num_query_authzone_up; + s->svr.num_query_authzone_down += (long long)worker->env.mesh->num_query_authzone_down; } s->svr.mem_stream_wait = (long long)tcp_req_info_get_stream_buffer_size(); @@ -451,9 +443,14 @@ void server_stats_add(struct ub_stats_info* total, struct ub_stats_info* a) total->svr.num_queries_cookie_valid += a->svr.num_queries_cookie_valid; total->svr.num_queries_cookie_client += a->svr.num_queries_cookie_client; total->svr.num_queries_cookie_invalid += a->svr.num_queries_cookie_invalid; + total->svr.num_queries_discard_timeout += + a->svr.num_queries_discard_timeout; + total->svr.num_queries_wait_limit += a->svr.num_queries_wait_limit; total->svr.num_queries_missed_cache += a->svr.num_queries_missed_cache; total->svr.num_queries_prefetch += a->svr.num_queries_prefetch; total->svr.num_queries_timed_out += a->svr.num_queries_timed_out; + total->svr.num_query_authzone_up += a->svr.num_query_authzone_up; + total->svr.num_query_authzone_down += a->svr.num_query_authzone_down; if (total->svr.max_query_time_us < a->svr.max_query_time_us) total->svr.max_query_time_us = a->svr.max_query_time_us; total->svr.sum_query_list_size += a->svr.sum_query_list_size; diff --git a/dns64/dns64.c b/dns64/dns64.c index 0db174ba9..f028cd28a 100644 --- a/dns64/dns64.c +++ b/dns64/dns64.c @@ -658,7 +658,8 @@ handle_event_moddone(struct module_qstate* qstate, int id) !dns_cache_store( qstate->env, &qstate->qinfo, qstate->return_msg->rep, 0, qstate->prefetch_leeway, 0, NULL, - qstate->query_flags, qstate->qstarttime)) + qstate->query_flags, qstate->qstarttime, + qstate->is_valrec)) log_err("out of memory"); /* do nothing */ @@ -1008,7 +1009,8 @@ 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, super->prefetch_leeway, 0, NULL, super->query_flags, qstate->qstarttime)) + 0, super->prefetch_leeway, 0, NULL, super->query_flags, + qstate->qstarttime, qstate->is_valrec)) log_err("out of memory"); } diff --git a/doc/Changelog b/doc/Changelog index adc76c08d..47f321caf 100644 --- a/doc/Changelog +++ b/doc/Changelog @@ -1,3 +1,60 @@ +22 November 2024: Yorgos + - Fix #1175: serve-expired does not adhere to secure-by-default + principle. The default value of serve-expired-client-timeout + is set to 1800 as suggested by RFC8767. + - For #1175, update serve-expired tests. + +20 November 2024: Yorgos + - Fix comparison to help static analyzer. + +19 November 2024: Yorgos + - Merge #1169 from Sergey Kacheev, fix: lock-free counters for + auth_zone up/down queries. + +15 November 2024: Wouter + - Fix #1183: the data being used is released in method + nsec3_hash_test_entry. + - Fix for #1183: release nsec3 hashes per test file. + +8 November 2024: Yorgos + - More descriptive text for 'harden-algo-downgrade'. + - Complete fix for max-global-quota to 200. + +6 November 2024: Yorgos + - Increase the default of max-global-quota to 200 from 128 after + operational feedback. Still keeping the possible amplification + factor (CAMP related issues) in the hundreds. + +5 November 2024: Wouter + - Fix for the serve expired DNSSEC information fix, it would not allow + current delegation information be updated in cache. The fix allows + current delegation and validation recursion information to be + updated, but as a consequence no longer has certain expired + information around for later dnssec valid expired responses. + - Fix to log redis timeout error string on failure. + +5 November 2024: Yorgos + - Fix SETEX check during Redis (re)initialization. + +4 November 2024: Wouter + - Fix redis that during a reload it does not fail if the redis + server does not connect or does not respond. It still logs the + errors and if the server is up checks expiration features. + - Merge #1167: Makefile.in: fix occasional parallel build failures + around bison rule. + +1 November 2024: Yorgos + - Merge #1159: Stats for discard-timeout and wait-limit. + - Add test case for #1159. + - Some clean up for stat_values.test. + - Merge #1170 from Melroy van den Berg, Fix chroot manpage + description. + - Merge #1157 from Liang Zhu, Fix heap corruption when calling + ub_ctx_delete in Windows. + +25 October 2024: Yorgos + - Fix #1163: Typos in unbound.conf documentation. + 17 October 2024: Wouter - Tag for 1.22.0 release. This did not contain the 1154 fix from 16 oct. The code repository continues with diff --git a/doc/example.conf.in b/doc/example.conf.in index 06e2b4ba8..e0ee39ad4 100644 --- a/doc/example.conf.in +++ b/doc/example.conf.in @@ -194,7 +194,7 @@ server: # iter-scrub-cname: 11 # Limit on upstream queries for an incoming query and its recursion. - # max-global-quota: 128 + # max-global-quota: 200 # msec for waiting for an unknown server to reply. Increase if you # are behind a slow satellite link, to eg. 1128. @@ -556,8 +556,9 @@ server: # harden-referral-path: no # Harden against algorithm downgrade when multiple algorithms are - # advertised in the DS record. If no, allows the weakest algorithm - # to validate the zone. + # advertised in the DS record. If no, allows any algorithm + # to validate the zone which is the standard behavior for validators. + # Check the manpage for detailed information. # harden-algo-downgrade: no # Harden against unknown records in the authority section and the @@ -730,7 +731,8 @@ server: # disable-edns-do: no # Serve expired responses from cache, with serve-expired-reply-ttl in - # the response, and then attempt to fetch the data afresh. + # the response. By default it first tries to refresh an expired answer. + # Can be configured with serve-expired-client-timeout. # serve-expired: no # # Limit serving of expired responses to configured seconds after @@ -748,10 +750,9 @@ server: # # Time in milliseconds before replying to the client with expired data. # This essentially enables the serve-stale behavior as specified in - # RFC 8767 that first tries to resolve before - # immediately responding with expired data. 0 disables this behavior. - # A recommended value is 1800. - # serve-expired-client-timeout: 0 + # RFC 8767 that first tries to resolve before immediately responding + # with expired data. 0 disables this behavior. + # serve-expired-client-timeout: 1800 # Return the original TTL as received from the upstream name server rather # than the decrementing TTL as stored in the cache. Enabling this feature diff --git a/doc/unbound-control.8.in b/doc/unbound-control.8.in index 6470d544c..467374d33 100644 --- a/doc/unbound-control.8.in +++ b/doc/unbound-control.8.in @@ -422,6 +422,12 @@ number of queries with a client part only DNS Cookie by thread .I threadX.num.queries_cookie_invalid number of queries with an invalid DNS Cookie by thread .TP +.I threadX.num.queries_discard_timeout +number of queries removed due to discard-timeout by thread +.TP +.I threadX.num.queries_wait_limit +number of queries removed due to wait-limit by thread +.TP .I threadX.num.cachehits number of queries that were successfully answered using a cache lookup .TP @@ -511,6 +517,12 @@ summed over threads. .I total.num.queries_cookie_invalid summed over threads. .TP +.I total.num.queries_discard_timeout +summed over threads. +.TP +.I total.num.queries_wait_limit +summed over threads. +.TP .I total.num.cachehits summed over threads. .TP diff --git a/doc/unbound.conf.5.in b/doc/unbound.conf.5.in index da494087c..cf6f14915 100644 --- a/doc/unbound.conf.5.in +++ b/doc/unbound.conf.5.in @@ -902,9 +902,8 @@ outside of the chroot directory. Additionally, Unbound may need to access /dev/urandom (for entropy) from inside the chroot. .IP -If given a chroot is done to the given directory. By default chroot is -enabled and the default is "@UNBOUND_CHROOT_DIR@". If you give "" no -chroot is performed. +If given a chroot is done to the given directory. The chroot is by default +set to "@UNBOUND_CHROOT_DIR@". If you give "" no chroot is performed. .TP .B username: \fI If given, after binding the port the user privileges are dropped. Default is @@ -1056,11 +1055,11 @@ closer to that of BIND 9, while setting "\-1 \-1 \-1 \-1 \-1" gives behaviour rumoured to be closer to that of BIND 8. .TP .B harden\-short\-bufsize: \fI -Very small EDNS buffer sizes from queries are ignored. Default is on, as +Very small EDNS buffer sizes from queries are ignored. Default is yes, as described in the standard. .TP .B harden\-large\-queries: \fI -Very large queries are ignored. Default is off, since it is legal protocol +Very large queries are ignored. Default is no, since it is legal protocol wise to send these, and could be necessary for operation if TSIG or EDNS payload is very large. .TP @@ -1107,10 +1106,23 @@ to increase the max depth that is checked to. .TP .B harden\-algo\-downgrade: \fI Harden against algorithm downgrade when multiple algorithms are -advertised in the DS record. If no, allows the weakest algorithm to -validate the zone. Default is no. Zone signers must produce zones -that allow this feature to work, but sometimes they do not, and turning -this option off avoids that validation failure. +advertised in the DS record. +This works by first choosing only the strongest DS digest type as per RFC 4509 +(Unbound treats the highest algorithm as the strongest) and then +expecting signatures from all the advertised signing algorithms from the chosen +DS(es) to be present. +If no, allows any algorithm to validate the zone. +Default is no. +RFC 6840 mandates that zone signers must produce zones signed with all +advertised algorithms, but sometimes they do not. +RFC 6840 also clarifies that this requirement is not for validators and +validators should accept any single valid path. +It should thus be explicitly noted that this option violates RFC 6840 for +DNSSEC validation and should only be used to perform a signature +completeness test to support troubleshooting. +Using this option may break DNSSEC resolution with non-RFC6840-conforming +signers and/or in multi-signer configurations that don't send all the +advertised signatures. .TP .B harden\-unknown\-additional: \fI Harden against unknown records in the authority section and additional @@ -1131,7 +1143,7 @@ queries. For domains that do not support 0x20 and also fail with fallback because they keep sending different answers, like some load balancers. Can be given multiple times, for different domains. .TP -.B caps\-whitelist: \fI +.B caps\-whitelist: \fI Alternate syntax for \fBcaps\-exempt\fR. .TP .B qname\-minimisation: \fI @@ -1390,9 +1402,10 @@ Default is no. .TP .B serve\-expired: \fI If enabled, Unbound attempts to serve old responses from cache with a -TTL of \fBserve\-expired\-reply\-ttl\fR in the response without waiting for the -actual resolution to finish. The actual resolution answer ends up in the cache -later on. Default is "no". +TTL of \fBserve\-expired\-reply\-ttl\fR in the response. +By default the expired answer will be used after a resolution attempt errored +out or is taking more than serve\-expired\-client\-timeout to resolve. +Default is "no". .TP .B serve\-expired\-ttl: \fI Limit serving of expired responses to configured seconds after expiration. 0 @@ -1412,12 +1425,14 @@ TTL value to use when replying with expired data. If use 30 as the value (RFC 8767). The default is 30. .TP .B serve\-expired\-client\-timeout: \fI -Time in milliseconds before replying to the client with expired data. This -essentially enables the serve-stale behavior as specified in +Time in milliseconds before replying to the client with expired data. +This essentially enables the serve-stale behavior as specified in RFC 8767 that first tries to resolve before immediately -responding with expired data. A recommended value per -RFC 8767 is 1800. Setting this to 0 will disable this -behavior. Default is 0. +responding with expired data. +Setting this to 0 will disable this behavior and instead serve the expired +record immediately from the cache before attempting to refresh it via +resolution. +Default is 1800. .TP .B serve\-original\-ttl: \fI If enabled, Unbound will always return the original TTL as received from @@ -1998,7 +2013,7 @@ Default is 11. Limit on the number of upstream queries sent out for an incoming query and its subqueries from recursion. It is not reset during the resolution. When it is exceeded the query is failed and the lookup process stops. -Default is 128. +Default is 200. .TP 5 .B fast\-server\-permil: \fI Specify how many times out of 1000 to pick from the set of fastest servers. @@ -2715,7 +2730,7 @@ Allow the ipsecmod functionality for the domain so that the module logic will be executed. Can be given multiple times, for different domains. If the option is not specified, all domains are treated as being allowed (default). .TP -.B ipsecmod\-whitelist: \fI +.B ipsecmod\-whitelist: \fI Alternate syntax for \fBipsecmod\-allow\fR. .SS "Cache DB Module Options" .LP diff --git a/ipsecmod/ipsecmod.c b/ipsecmod/ipsecmod.c index 76f9b1965..1c9e6e6a5 100644 --- a/ipsecmod/ipsecmod.c +++ b/ipsecmod/ipsecmod.c @@ -456,7 +456,8 @@ 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, qstate->qstarttime)) { + 0, qstate->region, qstate->query_flags, qstate->qstarttime, + qstate->is_valrec)) { log_err("ipsecmod: out of memory caching record"); } qstate->ext_state[id] = module_finished; diff --git a/iterator/iter_utils.c b/iterator/iter_utils.c index cacba420e..5198e9ef2 100644 --- a/iterator/iter_utils.c +++ b/iterator/iter_utils.c @@ -693,10 +693,11 @@ 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, time_t qstarttime) + struct regional* region, uint16_t flags, time_t qstarttime, + int is_valrec) { if(!dns_cache_store(env, msgqinf, msgrep, is_referral, leeway, - pside, region, flags, qstarttime)) + pside, region, flags, qstarttime, is_valrec)) log_err("out of memory: cannot store data in cache"); } @@ -1606,3 +1607,12 @@ limit_nsec_ttl(struct dns_msg* msg) } } } + +void +iter_make_minimal(struct reply_info* rep) +{ + size_t rem = rep->ns_numrrsets + rep->ar_numrrsets; + rep->ns_numrrsets = 0; + rep->ar_numrrsets = 0; + rep->rrset_count -= rem; +} diff --git a/iterator/iter_utils.h b/iterator/iter_utils.h index 0361e4377..30b3dbe5f 100644 --- a/iterator/iter_utils.h +++ b/iterator/iter_utils.h @@ -142,6 +142,7 @@ struct dns_msg* dns_copy_msg(struct dns_msg* from, struct regional* regional); * @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. + * @param is_valrec: if the query is validation recursion and does not get * 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. @@ -150,7 +151,8 @@ 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, time_t qstarttime); + struct regional* region, uint16_t flags, time_t qstarttime, + int is_valrec); /** * Select randomly with n/m probability. @@ -435,4 +437,11 @@ void iterator_set_ip46_support(struct module_stack* mods, */ void limit_nsec_ttl(struct dns_msg* msg); +/** + * Make the response minimal. Removed authority and additional section, + * that works when there is an answer in the answer section. + * @param rep: reply to modify. + */ +void iter_make_minimal(struct reply_info* rep); + #endif /* ITERATOR_ITER_UTILS_H */ diff --git a/iterator/iterator.c b/iterator/iterator.c index 59e4b36ce..fdba52ddb 100644 --- a/iterator/iterator.c +++ b/iterator/iterator.c @@ -71,7 +71,7 @@ #include "sldns/sbuffer.h" /* number of packets */ -int MAX_GLOBAL_QUOTA = 128; +int MAX_GLOBAL_QUOTA = 200; /* in msec */ int UNKNOWN_SERVER_NICENESS = 376; /* in msec */ @@ -368,7 +368,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->qstarttime); + qstate->query_flags, qstate->qstarttime, qstate->is_valrec); return error_response(qstate, id, rcode); } @@ -2741,9 +2741,7 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq, if((iq->chase_flags&BIT_RD) && !(iq->response->rep->flags&BIT_AA)) { verbose(VERB_ALGO, "forwarder, ignoring referral from auth zone"); } else { - lock_rw_wrlock(&qstate->env->auth_zones->lock); - qstate->env->auth_zones->num_query_up++; - lock_rw_unlock(&qstate->env->auth_zones->lock); + qstate->env->mesh->num_query_authzone_up++; iq->num_current_queries++; iq->chase_to_rd = 0; iq->dnssec_lame_query = 0; @@ -3296,6 +3294,16 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq, iq->num_target_queries = 0; return processDSNSFind(qstate, iq, id); } + if(iq->qchase.qtype == LDNS_RR_TYPE_DNSKEY && SERVE_EXPIRED + && qstate->is_valrec && + reply_find_answer_rrset(&iq->qchase, iq->response->rep) != NULL) { + /* clean out the authority section, if any, so it + * does not overwrite dnssec valid data in the + * validation recursion lookup. */ + verbose(VERB_ALGO, "make DNSKEY minimal for serve " + "expired"); + iter_make_minimal(iq->response->rep); + } if(!qstate->no_cache_store) iter_dns_store(qstate->env, &iq->response->qinfo, iq->response->rep, @@ -3303,7 +3311,7 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq, qstate->prefetch_leeway, iq->dp&&iq->dp->has_parent_side_NS, qstate->region, qstate->query_flags, - qstate->qstarttime); + qstate->qstarttime, qstate->is_valrec); /* close down outstanding requests to be discarded */ outbound_list_clear(&iq->outlist); iq->num_current_queries = 0; @@ -3397,7 +3405,7 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq, /* no prefetch-leeway, since its not the answer */ iter_dns_store(qstate->env, &iq->response->qinfo, iq->response->rep, 1, 0, 0, NULL, 0, - qstate->qstarttime); + qstate->qstarttime, qstate->is_valrec); if(iq->store_parent_NS) iter_store_parentside_NS(qstate->env, iq->response->rep); @@ -3527,7 +3535,8 @@ 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->qstarttime); + qstate->query_flags, qstate->qstarttime, + qstate->is_valrec); /* set the current request's qname to the new value. */ iq->qchase.qname = sname; iq->qchase.qname_len = snamelen; @@ -4154,7 +4163,7 @@ processFinished(struct module_qstate* qstate, struct iter_qstate* iq, iq->response->rep, 0, qstate->prefetch_leeway, iq->dp&&iq->dp->has_parent_side_NS, qstate->region, qstate->query_flags, - qstate->qstarttime); + qstate->qstarttime, qstate->is_valrec); } } qstate->return_rcode = LDNS_RCODE_NOERROR; diff --git a/libunbound/unbound.h b/libunbound/unbound.h index ef2c5c067..8a1625b9f 100644 --- a/libunbound/unbound.h +++ b/libunbound/unbound.h @@ -849,6 +849,10 @@ struct ub_server_stats { long long mem_quic; /** number of queries over (DNS over) QUIC */ long long qquic; + /** number of queries removed due to discard-timeout */ + long long num_queries_discard_timeout; + /** number of queries removed due to wait-limit */ + long long num_queries_wait_limit; }; /** diff --git a/pythonmod/pythonmod_utils.c b/pythonmod/pythonmod_utils.c index aebe4d2bb..fc9921aa1 100644 --- a/pythonmod/pythonmod_utils.c +++ b/pythonmod/pythonmod_utils.c @@ -73,7 +73,7 @@ int storeQueryInCache(struct module_qstate* qstate, struct query_info* qinfo, return dns_cache_store(qstate->env, qinfo, msgrep, is_referral, qstate->prefetch_leeway, 0, NULL, qstate->query_flags, - qstate->qstarttime); + qstate->qstarttime, qstate->is_valrec); } /* Invalidate the message associated with query_info stored in message cache */ diff --git a/services/authzone.c b/services/authzone.c index 6f6c55d43..8019c491f 100644 --- a/services/authzone.c +++ b/services/authzone.c @@ -3610,9 +3610,7 @@ int auth_zones_answer(struct auth_zones* az, struct module_env* env, return 0; } lock_rw_unlock(&z->lock); - lock_rw_wrlock(&az->lock); - az->num_query_down++; - lock_rw_unlock(&az->lock); + env->mesh->num_query_authzone_down++; auth_error_encode(qinfo, env, edns, repinfo, buf, temp, LDNS_RCODE_SERVFAIL); return 1; @@ -3625,9 +3623,7 @@ int auth_zones_answer(struct auth_zones* az, struct module_env* env, /* fallback to regular answering (recursive) */ return 0; } - lock_rw_wrlock(&az->lock); - az->num_query_down++; - lock_rw_unlock(&az->lock); + env->mesh->num_query_authzone_down++; /* encode answer */ if(!r) diff --git a/services/authzone.h b/services/authzone.h index 07614ed82..3994a4ead 100644 --- a/services/authzone.h +++ b/services/authzone.h @@ -78,10 +78,6 @@ struct auth_zones { rbtree_type xtree; /** do we have downstream enabled */ int have_downstream; - /** number of queries upstream */ - size_t num_query_up; - /** number of queries downstream */ - size_t num_query_down; /** first auth zone containing rpz item in linked list */ struct auth_zone* rpz_first; /** rw lock for rpz linked list, needed when iterating or editing linked diff --git a/services/cache/dns.c b/services/cache/dns.c index 7ab63bacf..d9536c0e7 100644 --- a/services/cache/dns.c +++ b/services/cache/dns.c @@ -1057,7 +1057,8 @@ 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, time_t qstarttime) + struct regional* region, uint32_t flags, time_t qstarttime, + int is_valrec) { struct reply_info* rep = NULL; if(SERVE_EXPIRED) { @@ -1079,7 +1080,8 @@ dns_cache_store(struct module_env* env, struct query_info* msgqinf, * one and let the validator manage caching. */ && cached->security != sec_status_bogus && (env->need_to_validate && - msgrep->security == sec_status_unchecked)) { + msgrep->security == sec_status_unchecked) + && !is_valrec) { verbose(VERB_ALGO, "a validated expired entry " "could be overwritten, skip caching " "the new message at this stage"); diff --git a/services/cache/dns.h b/services/cache/dns.h index 1dd537d2b..8aa6b44bc 100644 --- a/services/cache/dns.h +++ b/services/cache/dns.h @@ -90,11 +90,14 @@ struct dns_msg { * (See DNSCACHE_STORE_xxx flags). * @param qstarttime: time when the query was started, and thus when the * delegations were looked up. + * @param is_valrec: if the query is validation recursion and does not get + * dnssec validation itself. * @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, time_t qstarttime); + struct regional* region, uint32_t flags, time_t qstarttime, + int is_valrec); /** * Store message in the cache. Stores in message cache and rrset cache. diff --git a/services/mesh.c b/services/mesh.c index d512ab3d3..5b9a02ae4 100644 --- a/services/mesh.c +++ b/services/mesh.c @@ -214,6 +214,8 @@ mesh_create(struct module_stack* stack, struct module_env* env) mesh->stats_dropped = 0; mesh->ans_expired = 0; mesh->ans_cachedb = 0; + mesh->num_queries_discard_timeout = 0; + mesh->num_queries_wait_limit = 0; mesh->max_reply_states = env->cfg->num_queries_per_thread; mesh->max_forever_states = (mesh->max_reply_states+1)/2; #ifndef S_SPLINT_S @@ -424,7 +426,7 @@ void mesh_new_client(struct mesh_area* mesh, struct query_info* qinfo, verbose(VERB_ALGO, "Too many queries waiting from the IP. " "dropping incoming query."); comm_point_drop_reply(rep); - mesh->stats_dropped++; + mesh->num_queries_wait_limit++; return; } if(!unique) @@ -1540,7 +1542,7 @@ void mesh_query_done(struct mesh_state* mstate) http2_stream_remove_mesh_state(r->h2_stream); comm_point_drop_reply(&r->query_reply); mstate->reply_list = reply_list; - mstate->s.env->mesh->stats_dropped++; + mstate->s.env->mesh->num_queries_discard_timeout++; continue; } @@ -2029,6 +2031,8 @@ mesh_stats_clear(struct mesh_area* mesh) { if(!mesh) return; + mesh->num_query_authzone_up = 0; + mesh->num_query_authzone_down = 0; mesh->replies_sent = 0; mesh->replies_sum_wait.tv_sec = 0; mesh->replies_sum_wait.tv_usec = 0; @@ -2042,6 +2046,8 @@ mesh_stats_clear(struct mesh_area* mesh) memset(&mesh->ans_rcode[0], 0, sizeof(size_t)*UB_STATS_RCODE_NUM); memset(&mesh->rpz_action[0], 0, sizeof(size_t)*UB_STATS_RPZ_ACTION_NUM); mesh->ans_nodata = 0; + mesh->num_queries_discard_timeout = 0; + mesh->num_queries_wait_limit = 0; } size_t @@ -2270,7 +2276,7 @@ mesh_serve_expired_callback(void* arg) http2_stream_remove_mesh_state(r->h2_stream); comm_point_drop_reply(&r->query_reply); mstate->reply_list = reply_list; - mstate->s.env->mesh->stats_dropped++; + mstate->s.env->mesh->num_queries_discard_timeout++; continue; } diff --git a/services/mesh.h b/services/mesh.h index 26ececbe6..0906ed9cf 100644 --- a/services/mesh.h +++ b/services/mesh.h @@ -90,6 +90,11 @@ struct mesh_area { /** rbtree of all current queries (mesh_state.node)*/ rbtree_type all; + /** number of queries for unbound's auth_zones, upstream query */ + size_t num_query_authzone_up; + /** number of queries for unbound's auth_zones, downstream answers */ + size_t num_query_authzone_down; + /** count of the total number of mesh_reply entries */ size_t num_reply_addrs; /** count of the number of mesh_states that have mesh_replies @@ -132,6 +137,10 @@ struct mesh_area { size_t ans_nodata; /** (extended stats) type of applied RPZ action */ size_t rpz_action[UB_STATS_RPZ_ACTION_NUM]; + /** stats, number of queries removed due to discard-timeout */ + size_t num_queries_discard_timeout; + /** stats, number of queries removed due to wait-limit */ + size_t num_queries_wait_limit; /** backup of query if other operations recurse and need the * network buffers */ diff --git a/smallapp/unbound-control.c b/smallapp/unbound-control.c index b8479e9ab..f274b9dbf 100644 --- a/smallapp/unbound-control.c +++ b/smallapp/unbound-control.c @@ -222,6 +222,9 @@ static void pr_stats(const char* nm, struct ub_stats_info* s) s->svr.num_queries_cookie_client); PR_UL_NM("num.queries_cookie_invalid", s->svr.num_queries_cookie_invalid); + PR_UL_NM("num.queries_discard_timeout", + s->svr.num_queries_discard_timeout); + PR_UL_NM("num.queries_wait_limit", s->svr.num_queries_wait_limit); PR_UL_NM("num.cachehits", s->svr.num_queries - s->svr.num_queries_missed_cache); PR_UL_NM("num.cachemiss", s->svr.num_queries_missed_cache); diff --git a/testcode/unitverify.c b/testcode/unitverify.c index 275435c73..81c8b13c6 100644 --- a/testcode/unitverify.c +++ b/testcode/unitverify.c @@ -425,7 +425,7 @@ nsec3_hash_test_entry(struct entry* e, rbtree_type* ct, { struct query_info qinfo; struct reply_info* rep = NULL; - struct ub_packed_rrset_key* answer, *nsec3; + struct ub_packed_rrset_key* answer, *nsec3, *nsec3_region; struct nsec3_cached_hash* hash = NULL; int ret; uint8_t* qname; @@ -443,7 +443,11 @@ nsec3_hash_test_entry(struct entry* e, rbtree_type* ct, /* check test is OK */ unit_assert(nsec3 && answer && qname); - ret = nsec3_hash_name(ct, region, buf, nsec3, 0, qname, + /* Copy the nsec3 to the region, so it can stay referenced by the + * ct tree entry. The region is freed when the file is done. */ + nsec3_region = packed_rrset_copy_region(nsec3, region, 0); + + ret = nsec3_hash_name(ct, region, buf, nsec3_region, 0, qname, qinfo.qname_len, &hash); if(ret < 1) { printf("Bad nsec3_hash_name retcode %d\n", ret); diff --git a/testdata/cachedb_expired.crpl b/testdata/cachedb_expired.crpl index 9f9ff677c..d3bf06fe1 100644 --- a/testdata/cachedb_expired.crpl +++ b/testdata/cachedb_expired.crpl @@ -4,6 +4,7 @@ server: qname-minimisation: no minimal-responses: no serve-expired: yes + serve-expired-client-timeout: 0 module-config: "cachedb iterator" cachedb: diff --git a/testdata/cachedb_expired_reply_ttl.crpl b/testdata/cachedb_expired_reply_ttl.crpl index b5f340505..03fd01add 100644 --- a/testdata/cachedb_expired_reply_ttl.crpl +++ b/testdata/cachedb_expired_reply_ttl.crpl @@ -4,6 +4,7 @@ server: qname-minimisation: no minimal-responses: no serve-expired: yes + serve-expired-client-timeout: 0 serve-expired-reply-ttl: 30 module-config: "cachedb iterator" diff --git a/testdata/cachedb_servfail_cname.crpl b/testdata/cachedb_servfail_cname.crpl index 221f00d4d..99b3d51f9 100644 --- a/testdata/cachedb_servfail_cname.crpl +++ b/testdata/cachedb_servfail_cname.crpl @@ -3,7 +3,7 @@ server: target-fetch-policy: "0 0 0 0 0" qname-minimisation: no minimal-responses: no - ;serve-expired: yes + serve-expired: no module-config: "cachedb iterator" cachedb: diff --git a/testdata/cachedb_val_expired.crpl b/testdata/cachedb_val_expired.crpl index 4a51e8272..741445ce8 100644 --- a/testdata/cachedb_val_expired.crpl +++ b/testdata/cachedb_val_expired.crpl @@ -4,6 +4,7 @@ server: qname-minimisation: no minimal-responses: yes serve-expired: yes + serve-expired-client-timeout: 0 ;module-config: "subnetcache validator cachedb iterator" module-config: "validator cachedb iterator" diff --git a/testdata/dnstap.tdir/dnstap.conf b/testdata/dnstap.tdir/dnstap.conf index fc382ccfd..b5497bfeb 100644 --- a/testdata/dnstap.tdir/dnstap.conf +++ b/testdata/dnstap.tdir/dnstap.conf @@ -12,8 +12,9 @@ server: do-not-query-localhost: no local-zone: "example.net." redirect local-data: "example.net. IN A 10.20.30.41" - serve-expired: yes - serve-expired-reply-ttl: 30 + serve-expired: yes + serve-expired-client-timeout: 0 + serve-expired-reply-ttl: 30 remote-control: control-enable: yes control-interface: 127.0.0.1 diff --git a/testdata/fwd_0ttlservfail.rpl b/testdata/fwd_0ttlservfail.rpl index ed912c73b..d50d386d4 100644 --- a/testdata/fwd_0ttlservfail.rpl +++ b/testdata/fwd_0ttlservfail.rpl @@ -2,6 +2,7 @@ ; config options go here. server: serve-expired: yes + serve-expired-client-timeout: 0 prefetch: yes forward-zone: name: "." forward-addr: 216.0.0.1 CONFIG_END diff --git a/testdata/serve_expired.rpl b/testdata/serve_expired.rpl index 3f61019fa..990a562c7 100644 --- a/testdata/serve_expired.rpl +++ b/testdata/serve_expired.rpl @@ -4,6 +4,7 @@ server: qname-minimisation: "no" minimal-responses: no serve-expired: yes + serve-expired-client-timeout: 0 access-control: 127.0.0.1/32 allow_snoop ede: yes ede-serve-expired: yes diff --git a/testdata/serve_expired_0ttl_nodata.rpl b/testdata/serve_expired_0ttl_nodata.rpl index 7f1b5a565..032706f23 100644 --- a/testdata/serve_expired_0ttl_nodata.rpl +++ b/testdata/serve_expired_0ttl_nodata.rpl @@ -4,6 +4,7 @@ server: qname-minimisation: "no" minimal-responses: no serve-expired: yes + serve-expired-client-timeout: 0 log-servfail: yes ede: yes ede-serve-expired: yes diff --git a/testdata/serve_expired_0ttl_nxdomain.rpl b/testdata/serve_expired_0ttl_nxdomain.rpl index 4adb4b839..146752658 100644 --- a/testdata/serve_expired_0ttl_nxdomain.rpl +++ b/testdata/serve_expired_0ttl_nxdomain.rpl @@ -4,6 +4,7 @@ server: qname-minimisation: "no" minimal-responses: no serve-expired: yes + serve-expired-client-timeout: 0 log-servfail: yes ede: yes ede-serve-expired: yes diff --git a/testdata/serve_expired_0ttl_servfail.rpl b/testdata/serve_expired_0ttl_servfail.rpl index 6833af17b..a3bf826fe 100644 --- a/testdata/serve_expired_0ttl_servfail.rpl +++ b/testdata/serve_expired_0ttl_servfail.rpl @@ -4,6 +4,7 @@ server: qname-minimisation: "no" minimal-responses: no serve-expired: yes + serve-expired-client-timeout: 0 log-servfail: yes ede: yes ede-serve-expired: yes diff --git a/testdata/serve_expired_cached_servfail.rpl b/testdata/serve_expired_cached_servfail.rpl index edec74479..3fd7dd274 100644 --- a/testdata/serve_expired_cached_servfail.rpl +++ b/testdata/serve_expired_cached_servfail.rpl @@ -4,6 +4,7 @@ server: qname-minimisation: "no" minimal-responses: no serve-expired: yes + serve-expired-client-timeout: 0 serve-expired-reply-ttl: 123 log-servfail: yes ede: yes diff --git a/testdata/serve_expired_cached_servfail_refresh.rpl b/testdata/serve_expired_cached_servfail_refresh.rpl index 4d14dd948..6ad73efa4 100644 --- a/testdata/serve_expired_cached_servfail_refresh.rpl +++ b/testdata/serve_expired_cached_servfail_refresh.rpl @@ -4,6 +4,7 @@ server: qname-minimisation: "no" minimal-responses: no serve-expired: yes + serve-expired-client-timeout: 0 serve-expired-reply-ttl: 123 log-servfail: yes ede: yes diff --git a/testdata/serve_expired_client_timeout_val_bogus.rpl b/testdata/serve_expired_client_timeout_val_bogus.rpl index f4937a16c..4334168cd 100644 --- a/testdata/serve_expired_client_timeout_val_bogus.rpl +++ b/testdata/serve_expired_client_timeout_val_bogus.rpl @@ -38,6 +38,15 @@ SCENARIO_BEGIN Test serve-expired with client-timeout and bogus answer ; - query one last time ; - check that we get the immediate valid cache response; upstream does not have an answer at this moment +; The example.com NS and ns.example.com A record are commented out. +; This to make the test succeed. It then keeps the dnssec valid lookup. +; Otherwise, the relookup of the referral would overwrite the example.com NS +; the serve expired response would no longer be valid. But this record must +; be cached, for keeping the current delegation information. +; Also the DNSKEY lookup authority and additional are cleaned to stop overwrite +; of the NS and A record. This is more likely to keep the serve expired +; information intact. + ;; ;; K.ROOT-SERVERS.NET. ;; @@ -150,12 +159,12 @@ RANGE_BEGIN 0 10 www.example.com. IN A SECTION ANSWER www.example.com. IN A 10.20.30.40 - ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCQMyTjn7WWwpwAR1LlVeLpRgZGuQIUCcJDEkwAuzytTDRlYK7nIMwH1CM= ;{id = 2854} + ;ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCQMyTjn7WWwpwAR1LlVeLpRgZGuQIUCcJDEkwAuzytTDRlYK7nIMwH1CM= ;{id = 2854} SECTION AUTHORITY - example.com. IN NS ns.example.com. - example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} + ;example.com. IN NS ns.example.com. + ;example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} SECTION ADDITIONAL - ns.example.com. IN A 1.2.3.4 + ;ns.example.com. IN A 1.2.3.4 www.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFC99iE9K5y2WNgI0gFvBWaTi9wm6AhUAoUqOpDtG5Zct+Qr9F3mSdnbc6V4= ;{id = 2854} ENTRY_END RANGE_END @@ -174,12 +183,12 @@ RANGE_BEGIN 20 30 www.example.com. IN A SECTION ANSWER www.example.com. IN A 10.20.30.40 - ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCQMyTjn7WWwpwAR1LlVeLpRgZGuQIUCcJDEkwAuzytTDRlYK7nIMwH1CM= ;{id = 2854} + ;ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCQMyTjn7WWwpwAR1LlVeLpRgZGuQIUCcJDEkwAuzytTDRlYK7nIMwH1CM= ;{id = 2854} SECTION AUTHORITY - example.com. IN NS ns.example.com. - example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} + ;example.com. IN NS ns.example.com. + ;example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} SECTION ADDITIONAL - ns.example.com. IN A 1.2.3.4 + ;ns.example.com. IN A 1.2.3.4 ;; (valid signature) ;; www.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFC99iE9K5y2WNgI0gFvBWaTi9wm6AhUAoUqOpDtG5Zct+Qr9F3mSdnbc6V4= ;{id = 2854} ;; (bogus signature) @@ -201,12 +210,12 @@ RANGE_BEGIN 40 60 www.example.com. IN A SECTION ANSWER www.example.com. IN A 10.20.30.40 - ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCQMyTjn7WWwpwAR1LlVeLpRgZGuQIUCcJDEkwAuzytTDRlYK7nIMwH1CM= ;{id = 2854} + ;ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCQMyTjn7WWwpwAR1LlVeLpRgZGuQIUCcJDEkwAuzytTDRlYK7nIMwH1CM= ;{id = 2854} SECTION AUTHORITY - example.com. IN NS ns.example.com. - example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} + ;example.com. IN NS ns.example.com. + ;example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} SECTION ADDITIONAL - ns.example.com. IN A 1.2.3.4 + ;ns.example.com. IN A 1.2.3.4 www.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFC99iE9K5y2WNgI0gFvBWaTi9wm6AhUAoUqOpDtG5Zct+Qr9F3mSdnbc6V4= ;{id = 2854} ENTRY_END RANGE_END @@ -229,11 +238,11 @@ SECTION ANSWER www.example.com. IN A 10.20.30.40 www.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFC99iE9K5y2WNgI0gFvBWaTi9wm6AhUAoUqOpDtG5Zct+Qr9F3mSdnbc6V4= ;{id = 2854} SECTION AUTHORITY -example.com. IN NS ns.example.com. -example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +;example.com. IN NS ns.example.com. +;example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} SECTION ADDITIONAL -ns.example.com. IN A 1.2.3.4 -ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCQMyTjn7WWwpwAR1LlVeLpRgZGuQIUCcJDEkwAuzytTDRlYK7nIMwH1CM= ;{id = 2854} +;ns.example.com. IN A 1.2.3.4 +;ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCQMyTjn7WWwpwAR1LlVeLpRgZGuQIUCcJDEkwAuzytTDRlYK7nIMwH1CM= ;{id = 2854} ENTRY_END STEP 11 TIME_PASSES ELAPSE 3601 @@ -256,11 +265,11 @@ SECTION ANSWER www.example.com. 123 IN A 10.20.30.40 www.example.com. 123 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFC99iE9K5y2WNgI0gFvBWaTi9wm6AhUAoUqOpDtG5Zct+Qr9F3mSdnbc6V4= ;{id = 2854} SECTION AUTHORITY -example.com. 123 IN NS ns.example.com. -example.com. 123 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +;example.com. 123 IN NS ns.example.com. +;example.com. 123 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} SECTION ADDITIONAL -ns.example.com. 123 IN A 1.2.3.4 -ns.example.com. 123 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCQMyTjn7WWwpwAR1LlVeLpRgZGuQIUCcJDEkwAuzytTDRlYK7nIMwH1CM= ;{id = 2854} +;ns.example.com. 123 IN A 1.2.3.4 +;ns.example.com. 123 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCQMyTjn7WWwpwAR1LlVeLpRgZGuQIUCcJDEkwAuzytTDRlYK7nIMwH1CM= ;{id = 2854} ENTRY_END STEP 40 QUERY @@ -281,11 +290,11 @@ SECTION ANSWER www.example.com. 123 IN A 10.20.30.40 www.example.com. 123 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFC99iE9K5y2WNgI0gFvBWaTi9wm6AhUAoUqOpDtG5Zct+Qr9F3mSdnbc6V4= ;{id = 2854} SECTION AUTHORITY -example.com. 123 IN NS ns.example.com. -example.com. 123 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +;example.com. 123 IN NS ns.example.com. +;example.com. 123 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} SECTION ADDITIONAL -ns.example.com. 123 IN A 1.2.3.4 -ns.example.com. 123 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCQMyTjn7WWwpwAR1LlVeLpRgZGuQIUCcJDEkwAuzytTDRlYK7nIMwH1CM= ;{id = 2854} +;ns.example.com. 123 IN A 1.2.3.4 +;ns.example.com. 123 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCQMyTjn7WWwpwAR1LlVeLpRgZGuQIUCcJDEkwAuzytTDRlYK7nIMwH1CM= ;{id = 2854} ENTRY_END ; upstream query is resolved before this query comes in @@ -307,11 +316,11 @@ SECTION ANSWER www.example.com. IN A 10.20.30.40 www.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFC99iE9K5y2WNgI0gFvBWaTi9wm6AhUAoUqOpDtG5Zct+Qr9F3mSdnbc6V4= ;{id = 2854} SECTION AUTHORITY -example.com. IN NS ns.example.com. -example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +;example.com. IN NS ns.example.com. +;example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} SECTION ADDITIONAL -ns.example.com. IN A 1.2.3.4 -ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCQMyTjn7WWwpwAR1LlVeLpRgZGuQIUCcJDEkwAuzytTDRlYK7nIMwH1CM= ;{id = 2854} +;ns.example.com. IN A 1.2.3.4 +;ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCQMyTjn7WWwpwAR1LlVeLpRgZGuQIUCcJDEkwAuzytTDRlYK7nIMwH1CM= ;{id = 2854} ENTRY_END SCENARIO_END diff --git a/testdata/serve_expired_reply_ttl.rpl b/testdata/serve_expired_reply_ttl.rpl index 124fb874d..e76976bde 100644 --- a/testdata/serve_expired_reply_ttl.rpl +++ b/testdata/serve_expired_reply_ttl.rpl @@ -5,6 +5,7 @@ server: minimal-responses: no serve-expired: yes serve-expired-reply-ttl: 123 + serve-expired-client-timeout: 0 ede: yes ede-serve-expired: yes diff --git a/testdata/serve_expired_ttl.rpl b/testdata/serve_expired_ttl.rpl index df4ecb89d..66acbdcf1 100644 --- a/testdata/serve_expired_ttl.rpl +++ b/testdata/serve_expired_ttl.rpl @@ -4,6 +4,7 @@ server: qname-minimisation: "no" minimal-responses: no serve-expired: yes + serve-expired-client-timeout: 0 serve-expired-ttl: 10 stub-zone: diff --git a/testdata/serve_expired_ttl_reset.rpl b/testdata/serve_expired_ttl_reset.rpl index 521d5a0f0..faedb1cfc 100644 --- a/testdata/serve_expired_ttl_reset.rpl +++ b/testdata/serve_expired_ttl_reset.rpl @@ -4,6 +4,7 @@ server: serve-expired-ttl: 1 serve-expired-ttl-reset: yes serve-expired-reply-ttl: 123 + serve-expired-client-timeout: 0 ede: yes ede-serve-expired: yes forward-zone: name: "." forward-addr: 216.0.0.1 diff --git a/testdata/serve_expired_val_bogus.rpl b/testdata/serve_expired_val_bogus.rpl index 35365beef..6c28aa9a6 100644 --- a/testdata/serve_expired_val_bogus.rpl +++ b/testdata/serve_expired_val_bogus.rpl @@ -10,6 +10,7 @@ server: minimal-responses: no serve-expired: yes + serve-expired-client-timeout: 0 serve-expired-reply-ttl: 123 ede: yes ede-serve-expired: yes @@ -37,6 +38,15 @@ SCENARIO_BEGIN Test serve-expired with client-timeout and bogus answer ; - query one last time ; - check that we get an immediate valid cache response +; The example.com NS and ns.example.com A record are commented out. +; This to make the test succeed. It then keeps the dnssec valid lookup. +; Otherwise, the relookup of the referral would overwrite the example.com NS +; the serve expired response would no longer be valid. But this record must +; be cached, for keeping the current delegation information. +; Also the DNSKEY lookup authority and additional are cleaned to stop overwrite +; of the NS and A record. This is more likely to keep the serve expired +; information intact. + ;; ;; K.ROOT-SERVERS.NET. ;; @@ -149,12 +159,12 @@ RANGE_BEGIN 0 10 www.example.com. IN A SECTION ANSWER www.example.com. IN A 10.20.30.40 - ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCQMyTjn7WWwpwAR1LlVeLpRgZGuQIUCcJDEkwAuzytTDRlYK7nIMwH1CM= ;{id = 2854} + ;ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCQMyTjn7WWwpwAR1LlVeLpRgZGuQIUCcJDEkwAuzytTDRlYK7nIMwH1CM= ;{id = 2854} SECTION AUTHORITY - example.com. IN NS ns.example.com. - example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} + ;example.com. IN NS ns.example.com. + ;example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} SECTION ADDITIONAL - ns.example.com. IN A 1.2.3.4 + ;ns.example.com. IN A 1.2.3.4 www.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFC99iE9K5y2WNgI0gFvBWaTi9wm6AhUAoUqOpDtG5Zct+Qr9F3mSdnbc6V4= ;{id = 2854} ENTRY_END RANGE_END @@ -173,12 +183,12 @@ RANGE_BEGIN 20 40 www.example.com. IN A SECTION ANSWER www.example.com. IN A 10.20.30.40 - ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCQMyTjn7WWwpwAR1LlVeLpRgZGuQIUCcJDEkwAuzytTDRlYK7nIMwH1CM= ;{id = 2854} + ;ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCQMyTjn7WWwpwAR1LlVeLpRgZGuQIUCcJDEkwAuzytTDRlYK7nIMwH1CM= ;{id = 2854} SECTION AUTHORITY - example.com. IN NS ns.example.com. - example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} + ;example.com. IN NS ns.example.com. + ;example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} SECTION ADDITIONAL - ns.example.com. IN A 1.2.3.4 + ;ns.example.com. IN A 1.2.3.4 ;; (valid signature) ;; www.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFC99iE9K5y2WNgI0gFvBWaTi9wm6AhUAoUqOpDtG5Zct+Qr9F3mSdnbc6V4= ;{id = 2854} ;; (bogus signature) @@ -200,12 +210,12 @@ RANGE_BEGIN 50 100 www.example.com. IN A SECTION ANSWER www.example.com. IN A 10.20.30.40 - ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCQMyTjn7WWwpwAR1LlVeLpRgZGuQIUCcJDEkwAuzytTDRlYK7nIMwH1CM= ;{id = 2854} + ;ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCQMyTjn7WWwpwAR1LlVeLpRgZGuQIUCcJDEkwAuzytTDRlYK7nIMwH1CM= ;{id = 2854} SECTION AUTHORITY - example.com. IN NS ns.example.com. - example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} + ;example.com. IN NS ns.example.com. + ;example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} SECTION ADDITIONAL - ns.example.com. IN A 1.2.3.4 + ;ns.example.com. IN A 1.2.3.4 www.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFC99iE9K5y2WNgI0gFvBWaTi9wm6AhUAoUqOpDtG5Zct+Qr9F3mSdnbc6V4= ;{id = 2854} ENTRY_END RANGE_END @@ -229,11 +239,11 @@ SECTION ANSWER www.example.com. IN A 10.20.30.40 www.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFC99iE9K5y2WNgI0gFvBWaTi9wm6AhUAoUqOpDtG5Zct+Qr9F3mSdnbc6V4= ;{id = 2854} SECTION AUTHORITY -example.com. IN NS ns.example.com. -example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +;example.com. IN NS ns.example.com. +;example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} SECTION ADDITIONAL -ns.example.com. IN A 1.2.3.4 -ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCQMyTjn7WWwpwAR1LlVeLpRgZGuQIUCcJDEkwAuzytTDRlYK7nIMwH1CM= ;{id = 2854} +;ns.example.com. IN A 1.2.3.4 +;ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCQMyTjn7WWwpwAR1LlVeLpRgZGuQIUCcJDEkwAuzytTDRlYK7nIMwH1CM= ;{id = 2854} ENTRY_END STEP 11 TIME_PASSES ELAPSE 3601 @@ -256,11 +266,11 @@ SECTION ANSWER www.example.com. 123 IN A 10.20.30.40 www.example.com. 123 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFC99iE9K5y2WNgI0gFvBWaTi9wm6AhUAoUqOpDtG5Zct+Qr9F3mSdnbc6V4= ;{id = 2854} SECTION AUTHORITY -example.com. 123 IN NS ns.example.com. -example.com. 123 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +;example.com. 123 IN NS ns.example.com. +;example.com. 123 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} SECTION ADDITIONAL -ns.example.com. 123 IN A 1.2.3.4 -ns.example.com. 123 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCQMyTjn7WWwpwAR1LlVeLpRgZGuQIUCcJDEkwAuzytTDRlYK7nIMwH1CM= ;{id = 2854} +;ns.example.com. 123 IN A 1.2.3.4 +;ns.example.com. 123 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCQMyTjn7WWwpwAR1LlVeLpRgZGuQIUCcJDEkwAuzytTDRlYK7nIMwH1CM= ;{id = 2854} ENTRY_END STEP 40 QUERY @@ -281,11 +291,11 @@ SECTION ANSWER www.example.com. 123 IN A 10.20.30.40 www.example.com. 123 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFC99iE9K5y2WNgI0gFvBWaTi9wm6AhUAoUqOpDtG5Zct+Qr9F3mSdnbc6V4= ;{id = 2854} SECTION AUTHORITY -example.com. 123 IN NS ns.example.com. -example.com. 123 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +;example.com. 123 IN NS ns.example.com. +;example.com. 123 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} SECTION ADDITIONAL -ns.example.com. 123 IN A 1.2.3.4 -ns.example.com. 123 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCQMyTjn7WWwpwAR1LlVeLpRgZGuQIUCcJDEkwAuzytTDRlYK7nIMwH1CM= ;{id = 2854} +;ns.example.com. 123 IN A 1.2.3.4 +;ns.example.com. 123 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCQMyTjn7WWwpwAR1LlVeLpRgZGuQIUCcJDEkwAuzytTDRlYK7nIMwH1CM= ;{id = 2854} ENTRY_END STEP 60 QUERY @@ -306,11 +316,11 @@ SECTION ANSWER www.example.com. IN A 10.20.30.40 www.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFC99iE9K5y2WNgI0gFvBWaTi9wm6AhUAoUqOpDtG5Zct+Qr9F3mSdnbc6V4= ;{id = 2854} SECTION AUTHORITY -example.com. IN NS ns.example.com. -example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} +;example.com. IN NS ns.example.com. +;example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854} SECTION ADDITIONAL -ns.example.com. IN A 1.2.3.4 -ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCQMyTjn7WWwpwAR1LlVeLpRgZGuQIUCcJDEkwAuzytTDRlYK7nIMwH1CM= ;{id = 2854} +;ns.example.com. IN A 1.2.3.4 +;ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCQMyTjn7WWwpwAR1LlVeLpRgZGuQIUCcJDEkwAuzytTDRlYK7nIMwH1CM= ;{id = 2854} ENTRY_END SCENARIO_END diff --git a/testdata/serve_expired_zerottl.rpl b/testdata/serve_expired_zerottl.rpl index 0239b4a19..1411cb8e7 100644 --- a/testdata/serve_expired_zerottl.rpl +++ b/testdata/serve_expired_zerottl.rpl @@ -4,6 +4,7 @@ server: qname-minimisation: "no" minimal-responses: no serve-expired: yes + serve-expired-client-timeout: 0 serve-expired-reply-ttl: 123 ede: yes ede-serve-expired: yes diff --git a/testdata/serve_original_ttl.rpl b/testdata/serve_original_ttl.rpl index 24d01b6fe..30503c285 100644 --- a/testdata/serve_original_ttl.rpl +++ b/testdata/serve_original_ttl.rpl @@ -8,6 +8,7 @@ server: cache-max-ttl: 1000 cache-min-ttl: 20 serve-expired: yes + serve-expired-client-timeout: 0 serve-expired-reply-ttl: 123 ede: yes ede-serve-expired: yes diff --git a/testdata/stat_values.tdir/stat_values.conf b/testdata/stat_values.tdir/stat_values.conf index dc4553920..d1adff58c 100644 --- a/testdata/stat_values.tdir/stat_values.conf +++ b/testdata/stat_values.tdir/stat_values.conf @@ -14,6 +14,7 @@ server: outbound-msg-retry: 0 root-key-sentinel: no trust-anchor-signaling: no + serve-expired-client-timeout: 0 local-zone: local.zone static local-data: "www.local.zone A 192.0.2.1" @@ -26,9 +27,9 @@ remote-control: server-cert-file: "unbound_server.pem" control-key-file: "unbound_control.key" control-cert-file: "unbound_control.pem" -forward-zone: - name: "." - forward-addr: "127.0.0.1@@TOPORT@" -forward-zone: +stub-zone: + name: "example.com." + stub-addr: "127.0.0.1@@TOPORT@" +stub-zone: name: "expired." - forward-addr: "127.0.0.1@@EXPIREDPORT@" + stub-addr: "127.0.0.1@@EXPIREDPORT@" diff --git a/testdata/stat_values.tdir/stat_values.pre b/testdata/stat_values.tdir/stat_values.pre index 7b6eefdfa..81f94d8d1 100644 --- a/testdata/stat_values.tdir/stat_values.pre +++ b/testdata/stat_values.tdir/stat_values.pre @@ -38,6 +38,7 @@ echo "FWD_EXPIRED_PID=$FWD_EXPIRED_PID" >> .tpkg.var.test sed -e 's/@PORT\@/'$UNBOUND_PORT'/' -e 's/@TOPORT\@/'$FWD_PORT'/' -e 's/@EXPIREDPORT\@/'$FWD_EXPIRED_PORT'/' -e 's/@CONTROL_PORT\@/'$CONTROL_PORT'/' < stat_values.conf > ub.conf sed -e 's/@PORT\@/'$UNBOUND_PORT'/' -e 's/@TOPORT\@/'$FWD_PORT'/' -e 's/@EXPIREDPORT\@/'$FWD_EXPIRED_PORT'/' -e 's/@CONTROL_PORT\@/'$CONTROL_PORT'/' < stat_values_cachedb.conf > ub_cachedb.conf sed -e 's/@PORT\@/'$UNBOUND_PORT'/' -e 's/@CONTROL_PORT\@/'$CONTROL_PORT'/' < stat_values_downstream_cookies.conf > ub_downstream_cookies.conf +sed -e 's/@PORT\@/'$UNBOUND_PORT'/' -e 's/@TOPORT\@/'$FWD_PORT'/' -e 's/@CONTROL_PORT\@/'$CONTROL_PORT'/' < stat_values_discard_wait_limit.conf > ub_discard_wait_limit.conf # start unbound in the background $PRE/unbound -d -c ub.conf >unbound.log 2>&1 & UNBOUND_PID=$! diff --git a/testdata/stat_values.tdir/stat_values.test b/testdata/stat_values.tdir/stat_values.test index 814ecd116..456d27cb8 100644 --- a/testdata/stat_values.tdir/stat_values.test +++ b/testdata/stat_values.tdir/stat_values.test @@ -3,7 +3,6 @@ [ -f ../.tpkg.var.master ] && source ../.tpkg.var.master # use .tpkg.var.test for in test variable passing [ -f .tpkg.var.test ] && source .tpkg.var.test -# We need kill_pid for the serve-expired-client-timeout test . ../common.sh PRE="../.." @@ -154,6 +153,19 @@ set_ub_option () { fi } +# Convenient function to kill current Unbound and bring up one with an alternate configuration. +bring_up_alternate_configuration () { + conf_file=$1 + kill_pid $UNBOUND_PID # kill current Unbound + echo "" + cat unbound.log + echo "" + $PRE/unbound -d -c $conf_file >unbound.log 2>&1 & + UNBOUND_PID=$! + echo "UNBOUND_PID=$UNBOUND_PID" >> .tpkg.var.test + wait_unbound_up unbound.log +} + # Convenient function to exit the test. end () { echo "> cat logfiles" @@ -180,8 +192,8 @@ else end 1 fi -echo -echo "[ Check initial stats based on first query. ]" + +teststep "Check initial stats based on first query." check_stats "\ total.num.queries=1 total.num.cachemiss=1 @@ -198,16 +210,15 @@ rrset.cache.count=1 infra.cache.count=1 num.answer.rcode.NOERROR=1" -echo -echo "[ Check stat reset. ]" + +teststep "Check stat reset." check_stats "\ msg.cache.count=1 rrset.cache.count=1 infra.cache.count=1" -echo -echo "[ Enable serve-expired and check. ]" +teststep "Enable serve-expired and check." set_ub_option serve-expired yes sleep 2 # make sure the TTL has expired. echo "> dig 1ttl.example.com." @@ -236,8 +247,7 @@ rrset.cache.count=1 infra.cache.count=1" -echo -echo "[ Enable serve-expired-client-timeout and check. ]" +teststep "Enable serve-expired-client-timeout and check." set_ub_option serve-expired-client-timeout 1 echo "> dig servfail.expired." dig @127.0.0.1 -p $UNBOUND_PORT servfail.expired. | tee outfile @@ -295,8 +305,7 @@ infra.cache.count=2" set_ub_option serve-expired no -echo -echo "[ Check REFUSED; try without RD flag. ]" +teststep "Check REFUSED; try without RD flag." echo "> dig somethingelse.example.com." dig @127.0.0.1 -p $UNBOUND_PORT +nordflag somethingelse.example.com. | tee outfile echo "> check answer" @@ -319,8 +328,7 @@ rrset.cache.count=2 infra.cache.count=2" -echo -echo "[ Check the AD flag. ]" +teststep "Check the AD flag." echo "> dig www.example.com." dig @127.0.0.1 -p $UNBOUND_PORT +noadflag www.example.com. | tee outfile echo "> check answer" @@ -345,8 +353,8 @@ msg.cache.count=3 rrset.cache.count=3 infra.cache.count=2" -echo -echo "[ Check local zone. ]" + +teststep "Check local zone." echo "> dig www.local.zone." dig @127.0.0.1 -p $UNBOUND_PORT www.local.zone. | tee outfile echo "> check answer" @@ -370,8 +378,7 @@ rrset.cache.count=3 infra.cache.count=2" -echo -echo "[ Check NXDOMAIN (with local data). ]" +teststep "Check NXDOMAIN (with local data)." echo "> dig mail.local.zone." dig @127.0.0.1 -p $UNBOUND_PORT mail.local.zone. | tee outfile echo "> check answer" @@ -395,8 +402,7 @@ rrset.cache.count=3 infra.cache.count=2" -echo -echo "[ Check CHAOS. ]" +teststep "Check CHAOS." echo "> dig id.server. ch txt" dig @127.0.0.1 -p $UNBOUND_PORT id.server. ch txt | tee outfile echo "> check answer" @@ -420,18 +426,50 @@ rrset.cache.count=3 infra.cache.count=2" +### +# +# Bring the discard-timeout, wait-limit configured Unbound up +# +bring_up_alternate_configuration ub_discard_wait_limit.conf +# +### + + +teststep "Check discard-timeout and wait-limit" +echo "> dig www.slow" +dig @127.0.0.1 -p $UNBOUND_PORT +retry=2 +timeout=1 www.slow. | tee outfile +echo "> check answer" +if grep "no servers could be reached" outfile; then + echo "OK" +else + end 1 +fi +check_stats "\ +infra.cache.count=1 +msg.cache.count=1 +num.query.class.IN=3 +num.query.edns.present=3 +num.query.flags.AD=3 +num.query.flags.RD=3 +num.query.opcode.QUERY=3 +num.query.type.A=3 +num.query.udpout=1 +total.num.cachemiss=3 +total.num.queries=3 +total.num.queries_discard_timeout=2 +total.num.queries_wait_limit=1" + + +### +# # Bring the downstream DNS Cookies configured Unbound up -kill_pid $UNBOUND_PID # kill current Unbound -echo "" -cat unbound.log -echo "" -$PRE/unbound -d -c ub_downstream_cookies.conf >unbound.log 2>&1 & -UNBOUND_PID=$! -echo "UNBOUND_PID=$UNBOUND_PID" >> .tpkg.var.test -wait_unbound_up unbound.log - -echo -echo "[ Get a DNS Cookie. ]" +# +bring_up_alternate_configuration ub_downstream_cookies.conf +# +### + + +teststep "Get a DNS Cookie." echo "> dig www.local.zone +tcp $nocookie +ednsopt=10:0102030405060708" dig @127.0.0.1 -p $UNBOUND_PORT +tcp $nocookie +ednsopt=10:0102030405060708 +retry=0 +time=1 www.local.zone. | tee outfile echo "> check answer" @@ -456,8 +494,8 @@ num.query.edns.present=1 num.query.tcp=1 num.answer.rcode.NOERROR=1" -echo -echo "[ Present the valid DNS Cookie. ]" + +teststep "Present the valid DNS Cookie." echo "> dig www.local.zone $nocookie +ednsopt=10:valid_cookie" dig @127.0.0.1 -p $UNBOUND_PORT $nocookie +ednsopt=10:$valid_cookie +retry=0 +time=1 www.local.zone. | tee outfile echo "> check answer" @@ -478,8 +516,8 @@ num.query.flags.AD=1 num.query.edns.present=1 num.answer.rcode.NOERROR=1" -echo -echo "[ Present an invalid DNS Cookie. ]" + +teststep "Present an invalid DNS Cookie." echo "> dig www.local.zone $nocookie +ednsopt=10:invalid_cookie" dig @127.0.0.1 -p $UNBOUND_PORT $nocookie +ednsopt=10:$invalid_cookie +retry=0 +time=1 www.local.zone. | tee outfile echo "> check answer" @@ -497,8 +535,8 @@ total.num.queries_cookie_invalid=1 total.num.cachehits=1 num.answer.rcode.YXRRSET=1" -echo -echo "[ Present no DNS Cookie. ]" + +teststep "Present no DNS Cookie." echo "> dig www.local.zone +ignore" dig @127.0.0.1 -p $UNBOUND_PORT +ignore $nocookie +retry=0 +time=1 www.local.zone. | tee outfile echo "> check answer" @@ -516,18 +554,17 @@ num.answer.rcode.REFUSED=1" if test x$USE_CACHEDB = "x1"; then + +### +# # Bring the cachedb configured Unbound up -kill_pid $UNBOUND_PID # kill current Unbound -echo "" -cat unbound.log -echo "" -$PRE/unbound -d -c ub_cachedb.conf >unbound.log 2>&1 & -UNBOUND_PID=$! -echo "UNBOUND_PID=$UNBOUND_PID" >> .tpkg.var.test -wait_unbound_up unbound.log - -echo -echo "[ Check cachedb cache miss. ]" +# +bring_up_alternate_configuration ub_cachedb.conf +# +### + + +teststep "Check cachedb cache miss." echo "> dig www.example.com." dig @127.0.0.1 +ednsopt=65534 -p $UNBOUND_PORT www.example.com. | tee outfile echo "> check answer" @@ -554,8 +591,8 @@ rrset.cache.count=1 infra.cache.count=1 num.answer.rcode.NOERROR=1" -echo -echo "[ Check cachedb cache hit. ]" + +teststep "Check cachedb cache hit." echo "> dig www.example.com." dig @127.0.0.1 +ednsopt=65534 -p $UNBOUND_PORT www.example.com. | tee outfile echo "> check answer" @@ -582,8 +619,8 @@ rrset.cache.count=1 infra.cache.count=1 num.answer.rcode.NOERROR=1" -echo -echo "[ Check cachedb cache hit with stat reset ]" + +teststep "Check cachedb cache hit with stat reset." echo "> dig www.example.com." dig @127.0.0.1 +ednsopt=65534 -p $UNBOUND_PORT www.example.com. | tee outfile echo "> check answer" diff --git a/testdata/stat_values.tdir/stat_values.testns b/testdata/stat_values.tdir/stat_values.testns index 12df8a939..906c49f2b 100644 --- a/testdata/stat_values.tdir/stat_values.testns +++ b/testdata/stat_values.tdir/stat_values.testns @@ -31,3 +31,15 @@ SECTION QUESTION SECTION ANSWER 0ttl 0 IN A 0.0.0.1 ENTRY_END + +$ORIGIN slow. + +ENTRY_BEGIN +MATCH opcode qtype qname +REPLY QR AA NOERROR +ADJUST copy_id sleep=2 +SECTION QUESTION +www. IN A +SECTION ANSWER +www. 0 IN A 10.20.30.40 +ENTRY_END diff --git a/testdata/stat_values.tdir/stat_values_cachedb.conf b/testdata/stat_values.tdir/stat_values_cachedb.conf index b5e9b0e02..b7b375b36 100644 --- a/testdata/stat_values.tdir/stat_values_cachedb.conf +++ b/testdata/stat_values.tdir/stat_values_cachedb.conf @@ -1,7 +1,6 @@ server: verbosity: 5 module-config: "cachedb iterator" - serve-expired: yes num-threads: 1 interface: 127.0.0.1 port: @PORT@ @@ -17,8 +16,6 @@ server: root-key-sentinel: no trust-anchor-signaling: no - local-zone: local.zone static - local-data: "www.local.zone A 192.0.2.1" remote-control: control-enable: yes control-interface: 127.0.0.1 @@ -28,9 +25,6 @@ remote-control: server-cert-file: "unbound_server.pem" control-key-file: "unbound_control.key" control-cert-file: "unbound_control.pem" -forward-zone: - name: "." - forward-addr: "127.0.0.1@@TOPORT@" -forward-zone: - name: "expired." - forward-addr: "127.0.0.1@@EXPIREDPORT@" +stub-zone: + name: "example.com." + stub-addr: "127.0.0.1@@TOPORT@" diff --git a/testdata/stat_values.tdir/stat_values_discard_wait_limit.conf b/testdata/stat_values.tdir/stat_values_discard_wait_limit.conf new file mode 100644 index 000000000..9e350382d --- /dev/null +++ b/testdata/stat_values.tdir/stat_values_discard_wait_limit.conf @@ -0,0 +1,34 @@ +server: + verbosity: 5 + num-threads: 1 + interface: 127.0.0.1 + module-config: "validator iterator" + port: @PORT@ + use-syslog: no + directory: "" + pidfile: "unbound.pid" + chroot: "" + username: "" + do-not-query-localhost: no + extended-statistics: yes + identity: "stat_values" + outbound-msg-retry: 0 + root-key-sentinel: no + trust-anchor-signaling: no + + discard-timeout: 800 + wait-limit: 1 + infra-cache-min-rtt: 3000 # This is for the discard-timeout test + +remote-control: + control-enable: yes + control-interface: 127.0.0.1 + # control-interface: ::1 + control-port: @CONTROL_PORT@ + server-key-file: "unbound_server.key" + server-cert-file: "unbound_server.pem" + control-key-file: "unbound_control.key" + control-cert-file: "unbound_control.pem" +stub-zone: + name: "slow." + stub-addr: "127.0.0.1@@TOPORT@" diff --git a/testdata/subnet_cached_servfail.crpl b/testdata/subnet_cached_servfail.crpl index 9c746d579..f1a66159c 100644 --- a/testdata/subnet_cached_servfail.crpl +++ b/testdata/subnet_cached_servfail.crpl @@ -12,6 +12,7 @@ server: qname-minimisation: no minimal-responses: no serve-expired: yes + serve-expired-client-timeout: 0 prefetch: yes stub-zone: diff --git a/testdata/subnet_global_prefetch_always_forward.crpl b/testdata/subnet_global_prefetch_always_forward.crpl index ccfe5dfd6..775474cbc 100644 --- a/testdata/subnet_global_prefetch_always_forward.crpl +++ b/testdata/subnet_global_prefetch_always_forward.crpl @@ -6,6 +6,7 @@ server: trust-anchor-signaling: no target-fetch-policy: "0 0 0 0 0" serve-expired: yes + serve-expired-client-timeout: 0 client-subnet-always-forward: yes module-config: "subnetcache iterator" verbosity: 3 diff --git a/testdata/subnet_global_prefetch_expired.crpl b/testdata/subnet_global_prefetch_expired.crpl index de1b78055..374bf3e69 100644 --- a/testdata/subnet_global_prefetch_expired.crpl +++ b/testdata/subnet_global_prefetch_expired.crpl @@ -14,6 +14,7 @@ server: qname-minimisation: no minimal-responses: no serve-expired: yes + serve-expired-client-timeout: 0 serve-expired-ttl: 1 prefetch: yes diff --git a/util/config_file.c b/util/config_file.c index aca0039d4..c1c55c529 100644 --- a/util/config_file.c +++ b/util/config_file.c @@ -283,7 +283,7 @@ config_create(void) cfg->serve_expired_ttl = 0; cfg->serve_expired_ttl_reset = 0; cfg->serve_expired_reply_ttl = 30; - cfg->serve_expired_client_timeout = 0; + cfg->serve_expired_client_timeout = 1800; cfg->ede_serve_expired = 0; cfg->serve_original_ttl = 0; cfg->zonemd_permissive_mode = 0; @@ -416,7 +416,7 @@ config_create(void) cfg->ede = 0; cfg->iter_scrub_ns = 20; cfg->iter_scrub_cname = 11; - cfg->max_global_quota = 128; + cfg->max_global_quota = 200; return cfg; error_exit: config_delete(cfg); diff --git a/util/netevent.c b/util/netevent.c index b36f00f1a..9181d3e4a 100644 --- a/util/netevent.c +++ b/util/netevent.c @@ -2845,6 +2845,7 @@ static int doq_lookup_conn_stream(struct comm_reply* repinfo, struct comm_point* c, struct doq_conn** conn, struct doq_stream** stream) { + log_assert(c->doq_socket); if(c->doq_socket->current_conn) { *conn = c->doq_socket->current_conn; } else { @@ -6747,7 +6748,7 @@ comm_point_drop_reply(struct comm_reply* repinfo) reclaim_http_handler(repinfo->c); return; #ifdef HAVE_NGTCP2 - } else if(repinfo->c->type == comm_doq) { + } else if(repinfo->c->doq_socket) { doq_socket_drop_reply(repinfo); return; #endif diff --git a/util/tube.c b/util/tube.c index 7d98b93c3..96187e134 100644 --- a/util/tube.c +++ b/util/tube.c @@ -584,7 +584,10 @@ void tube_close_write(struct tube* ATTR_UNUSED(tube)) void tube_remove_bg_listen(struct tube* tube) { verbose(VERB_ALGO, "tube remove_bg_listen"); - ub_winsock_unregister_wsaevent(tube->ev_listen); + if (tube->ev_listen != NULL) { + ub_winsock_unregister_wsaevent(tube->ev_listen); + tube->ev_listen = NULL; + } } void tube_remove_bg_write(struct tube* tube) diff --git a/validator/validator.c b/validator/validator.c index 857510b65..1a51dc270 100644 --- a/validator/validator.c +++ b/validator/validator.c @@ -2563,7 +2563,7 @@ processFinished(struct module_qstate* qstate, struct val_qstate* vq, if(!dns_cache_store(qstate->env, &vq->orig_msg->qinfo, vq->orig_msg->rep, 0, qstate->prefetch_leeway, 0, qstate->region, qstate->query_flags, - qstate->qstarttime)) { + qstate->qstarttime, qstate->is_valrec)) { log_err("out of memory caching validator results"); } } @@ -2572,7 +2572,8 @@ 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, qstate->region, - qstate->query_flags, qstate->qstarttime)) { + qstate->query_flags, qstate->qstarttime, + qstate->is_valrec)) { log_err("out of memory caching validator results"); } }