diff --git a/README.md b/README.md index 3bbd38b3b..0eb8bb2e5 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ [![Packaging status](https://repology.org/badge/tiny-repos/unbound.svg)](https://repology.org/project/unbound/versions) [![Fuzzing Status](https://oss-fuzz-build-logs.storage.googleapis.com/badges/unbound.svg)](https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:unbound) [![Documentation Status](https://readthedocs.org/projects/unbound/badge/?version=latest)](https://unbound.readthedocs.io/en/latest/?badge=latest) -[![Mastodon Follow](https://img.shields.io/mastodon/follow/109262826617293067?domain=https%3A%2F%2Ffosstodon.org&style=social)](https://fosstodon.org/@nlnetlabs) +[![Mastodon Follow](https://img.shields.io/mastodon/follow/114692612288811644?domain=social.nlnetlabs.nl&style=social)](https://social.nlnetlabs.nl/@nlnetlabs) Unbound is a validating, recursive, caching DNS resolver. It is designed to be fast and lean and incorporates modern features based on open standards. If you diff --git a/acx_nlnetlabs.m4 b/acx_nlnetlabs.m4 index 6a01dc5a4..c8195f5e1 100644 --- a/acx_nlnetlabs.m4 +++ b/acx_nlnetlabs.m4 @@ -2,7 +2,10 @@ # Copyright 2009, Wouter Wijngaards, NLnet Labs. # BSD licensed. # -# Version 48 +# Version 50 +# 2025-09-29 add ac_cv_func_malloc_0_nonnull as a cache value for the malloc(0) +# check by ACX_FUNC_MALLOC. +# 2025-09-29 add ACX_CHECK_NONSTRING_ATTRIBUTE, AHX_CONFIG_NONSTRING_ATTRIBUTE. # 2024-01-16 fix to add -l:libssp.a to -lcrypto link check. # and check for getaddrinfo with only header. # 2024-01-15 fix to add crypt32 to -lcrypto link check when checking for gdi32. @@ -71,6 +74,7 @@ # ACX_DEPFLAG - find cc dependency flags. # ACX_DETERMINE_EXT_FLAGS_UNBOUND - find out which flags enable BSD and POSIX. # ACX_CHECK_FORMAT_ATTRIBUTE - find cc printf format syntax. +# ACX_CHECK_NONSTRING_ATTRIBUTE - find cc nonstring attribute syntax. # ACX_CHECK_UNUSED_ATTRIBUTE - find cc variable unused syntax. # ACX_CHECK_FLTO - see if cc supports -flto and use it if so. # ACX_LIBTOOL_C_ONLY - create libtool for C only, improved. @@ -92,6 +96,7 @@ # ACX_FUNC_IOCTLSOCKET - find ioctlsocket, portably. # ACX_FUNC_MALLOC - check malloc, define replacement . # AHX_CONFIG_FORMAT_ATTRIBUTE - config.h text for format. +# AHX_CONFIG_NONSTRING_ATTRIBUTE - config.h text for nonstring. # AHX_CONFIG_UNUSED_ATTRIBUTE - config.h text for unused. # AHX_CONFIG_FSEEKO - define fseeko, ftello fallback. # AHX_CONFIG_RAND_MAX - define RAND_MAX if needed. @@ -490,7 +495,7 @@ AC_DEFUN([AHX_CONFIG_FORMAT_ATTRIBUTE], ]) dnl Check how to mark function arguments as unused. -dnl result in HAVE_ATTR_UNUSED. +dnl result in HAVE_ATTR_UNUSED. dnl Make sure you include AHX_CONFIG_UNUSED_ATTRIBUTE also. AC_DEFUN([ACX_CHECK_UNUSED_ATTRIBUTE], [AC_REQUIRE([AC_PROG_CC]) @@ -525,6 +530,45 @@ if test $ac_cv_c_unused_attribute = yes; then fi ])dnl +dnl Check how to mark function arguments as nonstring. +dnl result in HAVE_ATTR_NONSTRING. +dnl Make sure you include AHX_CONFIG_NONSTRING_ATTRIBUTE also. +AC_DEFUN([ACX_CHECK_NONSTRING_ATTRIBUTE], +[AC_REQUIRE([AC_PROG_CC]) +AC_MSG_CHECKING(whether the C compiler (${CC-cc}) accepts the "nonstring" attribute) +AC_CACHE_VAL(ac_cv_c_nonstring_attribute, +[ac_cv_c_nonstring_attribute=no +AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include +struct test { + char __attribute__((nonstring)) s[1]; +}; +]], [[ + struct test t = { "1" }; + (void) t; +]])],[ac_cv_c_nonstring_attribute="yes"],[ac_cv_c_nonstring_attribute="no"]) +]) + +dnl Setup ATTR_NONSTRING config.h parts. +dnl make sure you call ACX_CHECK_NONSTRING_ATTRIBUTE also. +AC_DEFUN([AHX_CONFIG_NONSTRING_ATTRIBUTE], +[ +#if defined(DOXYGEN) +# define ATTR_NONSTRING(x) x +#elif defined(__cplusplus) +# define ATTR_NONSTRING(x) __attribute__((nonstring)) x +#elif defined(HAVE_ATTR_NONSTRING) +# define ATTR_NONSTRING(x) __attribute__((nonstring)) x +#else /* !HAVE_ATTR_NONSTRING */ +# define ATTR_NONSTRING(x) x +#endif /* !HAVE_ATTR_NONSTRING */ +]) + +AC_MSG_RESULT($ac_cv_c_nonstring_attribute) +if test $ac_cv_c_nonstring_attribute = yes; then + AC_DEFINE(HAVE_ATTR_NONSTRING, 1, [Whether the C compiler accepts the "nonstring" attribute]) +fi +])dnl + dnl Pre-fun for ACX_LIBTOOL_C_ONLY AC_DEFUN([ACX_LIBTOOL_C_PRE], [ # skip these tests, we do not need them. @@ -1190,8 +1234,9 @@ dnl detect malloc and provide malloc compat prototype. dnl $1: unique name for compat code AC_DEFUN([ACX_FUNC_MALLOC], [ - AC_MSG_CHECKING([for GNU libc compatible malloc]) - AC_RUN_IFELSE([AC_LANG_PROGRAM( + AC_CACHE_CHECK([for GNU libc compatible malloc],[ac_cv_func_malloc_0_nonnull], + [ + AC_RUN_IFELSE([AC_LANG_PROGRAM( [[#if defined STDC_HEADERS || defined HAVE_STDLIB_H #include #else @@ -1199,14 +1244,16 @@ char *malloc (); #endif ]], [ if(malloc(0) != 0) return 1;]) ], - [AC_MSG_RESULT([no]) - AC_LIBOBJ(malloc) - AC_DEFINE_UNQUOTED([malloc], [rpl_malloc_$1], [Define if replacement function should be used.])] , - [AC_MSG_RESULT([yes]) - AC_DEFINE([HAVE_MALLOC], 1, [If have GNU libc compatible malloc])], - [AC_MSG_RESULT([no (crosscompile)]) - AC_LIBOBJ(malloc) - AC_DEFINE_UNQUOTED([malloc], [rpl_malloc_$1], [Define if replacement function should be used.])] ) + [ac_cv_func_malloc_0_nonnull=no], + [ac_cv_func_malloc_0_nonnull=yes], + [ac_cv_func_malloc_0_nonnull="no (crosscompile)"]) + ]) + AS_IF([test "$ac_cv_func_malloc_0_nonnull" = yes], + [AC_DEFINE([HAVE_MALLOC], 1, [If have GNU libc compatible malloc])], + [ + AC_LIBOBJ(malloc) + AC_DEFINE_UNQUOTED([malloc], [rpl_malloc_$1], [Define if replacement function should be used.]) + ]) ]) dnl Define fallback for fseeko and ftello if needed. diff --git a/cachedb/cachedb.c b/cachedb/cachedb.c index bdb1754e4..b45c0a3ea 100644 --- a/cachedb/cachedb.c +++ b/cachedb/cachedb.c @@ -401,12 +401,9 @@ prep_data(struct module_qstate* qstate, struct sldns_buffer* buf) FLAGS_GET_RCODE(qstate->return_msg->rep->flags) != LDNS_RCODE_YXDOMAIN) return 0; - /* We don't store the reply if its TTL is 0 unless serve-expired is - * enabled. Such a reply won't be reusable and simply be a waste for - * the backend. It's also compatible with the default behavior of - * dns_cache_store_msg(). */ - if(qstate->return_msg->rep->ttl == 0 && - !qstate->env->cfg->serve_expired) + /* We don't store the reply if its TTL is 0. This is probably coming + * from upstream and it is not meant to be stored. */ + if(qstate->return_msg->rep->ttl == 0) return 0; /* The EDE is added to the out-list so it is encoded in the cached message */ @@ -460,7 +457,7 @@ good_expiry_and_qinfo(struct module_qstate* qstate, struct sldns_buffer* buf) * - serve_expired needs to be set * - if SERVE_EXPIRED_TTL is set make sure that the record is not older * than that. */ - if((time_t)expiry < *qstate->env->now && + if(TTL_IS_EXPIRED((time_t)expiry, *qstate->env->now) && (!qstate->env->cfg->serve_expired || (SERVE_EXPIRED_TTL && *qstate->env->now - (time_t)expiry > SERVE_EXPIRED_TTL))) @@ -472,7 +469,8 @@ good_expiry_and_qinfo(struct module_qstate* qstate, struct sldns_buffer* buf) /* Adjust the TTL of the given RRset by 'subtract'. If 'subtract' is * negative, set the TTL to 0. */ static void -packed_rrset_ttl_subtract(struct packed_rrset_data* data, time_t subtract) +packed_rrset_ttl_subtract(struct packed_rrset_data* data, time_t subtract, + time_t timestamp) { size_t i; size_t total = data->count + data->rrsig_count; @@ -484,13 +482,13 @@ packed_rrset_ttl_subtract(struct packed_rrset_data* data, time_t subtract) data->rr_ttl[i] -= subtract; else data->rr_ttl[i] = 0; } - data->ttl_add = (subtract < data->ttl_add) ? (data->ttl_add - subtract) : 0; + data->ttl_add = timestamp; } /* Adjust the TTL of a DNS message and its RRs by 'adjust'. If 'adjust' is * negative, set the TTLs to 0. */ static void -adjust_msg_ttl(struct dns_msg* msg, time_t adjust) +adjust_msg_ttl(struct dns_msg* msg, time_t adjust, time_t timestamp) { size_t i; if(adjust >= 0 && msg->rep->ttl > adjust) @@ -502,13 +500,13 @@ adjust_msg_ttl(struct dns_msg* msg, time_t adjust) for(i=0; irep->rrset_count; i++) { packed_rrset_ttl_subtract((struct packed_rrset_data*)msg-> - rep->rrsets[i]->entry.data, adjust); + rep->rrsets[i]->entry.data, adjust, timestamp); } } /* Set the TTL of the given RRset to fixed value. */ static void -packed_rrset_ttl_set(struct packed_rrset_data* data, time_t ttl) +packed_rrset_ttl_set(struct packed_rrset_data* data, time_t ttl, time_t timestamp) { size_t i; size_t total = data->count + data->rrsig_count; @@ -516,12 +514,12 @@ packed_rrset_ttl_set(struct packed_rrset_data* data, time_t ttl) for(i=0; irr_ttl[i] = ttl; } - data->ttl_add = 0; + data->ttl_add = timestamp; } /* Set the TTL of a DNS message and its RRs by to a fixed value. */ static void -set_msg_ttl(struct dns_msg* msg, time_t ttl) +set_msg_ttl(struct dns_msg* msg, time_t ttl, time_t timestamp) { size_t i; msg->rep->ttl = ttl; @@ -530,14 +528,14 @@ set_msg_ttl(struct dns_msg* msg, time_t ttl) for(i=0; irep->rrset_count; i++) { packed_rrset_ttl_set((struct packed_rrset_data*)msg-> - rep->rrsets[i]->entry.data, ttl); + rep->rrsets[i]->entry.data, ttl, timestamp); } } /** convert dns message in buffer to return_msg */ static int parse_data(struct module_qstate* qstate, struct sldns_buffer* buf, - int* msg_expired) + int* msg_expired, time_t* msg_timestamp, time_t* msg_expiry) { struct msg_parse* prs; struct edns_data edns; @@ -554,6 +552,9 @@ parse_data(struct module_qstate* qstate, struct sldns_buffer* buf, ×tamp, sizeof(timestamp)); expiry = be64toh(expiry); timestamp = be64toh(timestamp); + log_assert(timestamp <= expiry); + *msg_expiry = (time_t)expiry; + *msg_timestamp = (time_t)timestamp; /* parse DNS packet */ regional_free_all(qstate->env->scratch); @@ -605,11 +606,9 @@ parse_data(struct module_qstate* qstate, struct sldns_buffer* buf, return 1; /* message from the future (clock skew?) */ } adjust = *qstate->env->now - (time_t)timestamp; - if(qstate->return_msg->rep->ttl < adjust) { + if(TTL_IS_EXPIRED((time_t)expiry, *qstate->env->now)) { verbose(VERB_ALGO, "cachedb msg expired"); *msg_expired = 1; - /* If serve-expired is enabled, we still use an expired message - * setting the TTL to 0. */ if(!qstate->env->cfg->serve_expired || (FLAGS_GET_RCODE(qstate->return_msg->rep->flags) != LDNS_RCODE_NOERROR && @@ -618,23 +617,21 @@ parse_data(struct module_qstate* qstate, struct sldns_buffer* buf, FLAGS_GET_RCODE(qstate->return_msg->rep->flags) != LDNS_RCODE_YXDOMAIN)) return 0; /* message expired */ - else - adjust = -1; + /* If serve-expired is enabled, we still use an expired message. + * Set the TTL to 0 now and it will be handled specially later + * when we need to store it internally. */ + adjust = -1; } + adjust_msg_ttl(qstate->return_msg, adjust, timestamp); verbose(VERB_ALGO, "cachedb msg adjusted down by %d", (int)adjust); - adjust_msg_ttl(qstate->return_msg, adjust); if(qstate->env->cfg->aggressive_nsec) { limit_nsec_ttl(qstate->return_msg); } /* Similar to the unbound worker, if serve-expired is enabled and * the msg would be considered to be expired, mark the state so a - * refetch will be scheduled. The comparison between 'expiry' and - * 'now' should be redundant given how these values were calculated, - * but we check it just in case as does good_expiry_and_qinfo(). */ - if(qstate->env->cfg->serve_expired && - !qstate->env->cfg->serve_expired_client_timeout && - (adjust == -1 || (time_t)expiry < *qstate->env->now)) { + * refetch will be scheduled. */ + if(*msg_expired && !qstate->env->cfg->serve_expired_client_timeout) { qstate->need_refetch = 1; } @@ -647,7 +644,7 @@ parse_data(struct module_qstate* qstate, struct sldns_buffer* buf, */ static int cachedb_extcache_lookup(struct module_qstate* qstate, struct cachedb_env* ie, - int* msg_expired) + int* msg_expired, time_t* msg_timestamp, time_t* msg_expiry) { char key[(CACHEDB_HASHSIZE/8)*2+1]; calc_hash(&qstate->qinfo, qstate->env, key, sizeof(key)); @@ -664,7 +661,8 @@ cachedb_extcache_lookup(struct module_qstate* qstate, struct cachedb_env* ie, } /* parse dns message into return_msg */ - if( !parse_data(qstate, qstate->env->scratch_buffer, msg_expired) ) { + if( !parse_data(qstate, qstate->env->scratch_buffer, msg_expired, + msg_timestamp, msg_expiry) ) { return 0; } return 1; @@ -736,20 +734,24 @@ cachedb_intcache_lookup(struct module_qstate* qstate, struct cachedb_env* cde) * Store query into the internal cache of unbound. */ static void -cachedb_intcache_store(struct module_qstate* qstate, int msg_expired) +cachedb_intcache_store(struct module_qstate* qstate, int msg_expired, + time_t msg_timestamp, time_t msg_expiry) { uint32_t store_flags = qstate->query_flags; int serve_expired = qstate->env->cfg->serve_expired; - - if(qstate->env->cfg->serve_expired) - store_flags |= DNSCACHE_STORE_ZEROTTL; if(!qstate->return_msg) return; if(serve_expired && msg_expired) { - /* Set TTLs to a value such that value + *env->now is - * going to be now-3 seconds. Making it expired - * in the cache. */ - set_msg_ttl(qstate->return_msg, (time_t)-3); + time_t original_ttl = msg_expiry - msg_timestamp; + store_flags |= DNSCACHE_STORE_EXPIRED_MSG_CACHEDB; + /* Pass the original TTL of the expired message and signal with + * the DNSCACHE_STORE_EXPIRED_MSG_CACHEDB flag that + * dns_cache_store_msg() needs to set absolute expired TTLs + * based on the original message TTL. + * Results as expired message in the cache */ + set_msg_ttl(qstate->return_msg, original_ttl, 0); + verbose(VERB_ALGO, "cachedb expired msg set to be expired now " + "(original ttl: %d)", (int)original_ttl); /* The expired entry does not get checked by the validator * and we need a validation value for it. */ if(qstate->env->cfg->cachedb_check_when_serve_expired) @@ -767,12 +769,14 @@ cachedb_intcache_store(struct module_qstate* qstate, int msg_expired) * of cache. */ return; } - /* set TTLs to zero again */ - adjust_msg_ttl(qstate->return_msg, -1); /* Send serve expired responses based on the cachedb * returned message, that was just stored in the cache. * It can then continue to work on this query. */ mesh_respond_serve_expired(qstate->mesh_info); + /* set TTLs as expired for this return_msg in case it is used + * later on */ + set_msg_ttl(qstate->return_msg, + EXPIRED_REPLY_TTL_CALC(msg_expiry, msg_timestamp), 0); } } @@ -790,6 +794,7 @@ cachedb_handle_query(struct module_qstate* qstate, struct cachedb_env* ie, int id) { int msg_expired = 0; + time_t msg_timestamp, msg_expiry; qstate->is_cachedb_answer = 0; /* check if we are enabled, and skip if so */ if(!ie->enabled) { @@ -824,13 +829,15 @@ cachedb_handle_query(struct module_qstate* qstate, } /* ask backend cache to see if we have data */ - if(cachedb_extcache_lookup(qstate, ie, &msg_expired)) { + if(cachedb_extcache_lookup(qstate, ie, &msg_expired, &msg_timestamp, + &msg_expiry)) { if(verbosity >= VERB_ALGO) log_dns_msg(ie->backend->name, &qstate->return_msg->qinfo, qstate->return_msg->rep); /* store this result in internal cache */ - cachedb_intcache_store(qstate, msg_expired); + cachedb_intcache_store(qstate, + msg_expired, msg_timestamp, msg_expiry); /* In case we have expired data but there is a client timer for expired * answers, pass execution to next module in order to try updating the * data first. @@ -850,6 +857,8 @@ cachedb_handle_query(struct module_qstate* qstate, qstate->ext_state[id] = module_wait_module; return; } + /* No 0TTL answers escaping from external cache. */ + log_assert(qstate->return_msg->rep->ttl > 0); qstate->is_cachedb_answer = 1; /* we are done with the query */ qstate->ext_state[id] = module_finished; diff --git a/config.h.in b/config.h.in index 1646c3863..b2c1bc9fd 100644 --- a/config.h.in +++ b/config.h.in @@ -66,6 +66,9 @@ /* Whether the C compiler accepts the "format" attribute */ #undef HAVE_ATTR_FORMAT +/* Whether the C compiler accepts the "nonstring" attribute */ +#undef HAVE_ATTR_NONSTRING + /* Whether the C compiler accepts the "noreturn" attribute */ #undef HAVE_ATTR_NORETURN @@ -1390,6 +1393,17 @@ #endif /* !HAVE_ATTR_UNUSED */ +#if defined(DOXYGEN) +# define ATTR_NONSTRING(x) x +#elif defined(__cplusplus) +# define ATTR_NONSTRING(x) __attribute__((nonstring)) x +#elif defined(HAVE_ATTR_NONSTRING) +# define ATTR_NONSTRING(x) __attribute__((nonstring)) x +#else /* !HAVE_ATTR_NONSTRING */ +# define ATTR_NONSTRING(x) x +#endif /* !HAVE_ATTR_NONSTRING */ + + #ifndef HAVE_FSEEKO #define fseeko fseek #define ftello ftell diff --git a/configure b/configure index f89aae181..b696e356e 100755 --- a/configure +++ b/configure @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.71 for unbound 1.24.0. +# Generated by GNU Autoconf 2.71 for unbound 1.24.1. # # Report bugs to . # @@ -622,8 +622,8 @@ MAKEFLAGS= # Identity of this package. PACKAGE_NAME='unbound' PACKAGE_TARNAME='unbound' -PACKAGE_VERSION='1.24.0' -PACKAGE_STRING='unbound 1.24.0' +PACKAGE_VERSION='1.24.1' +PACKAGE_STRING='unbound 1.24.1' PACKAGE_BUGREPORT='unbound-bugs@nlnetlabs.nl or https://github.com/NLnetLabs/unbound/issues' PACKAGE_URL='' @@ -1513,7 +1513,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.24.0 to adapt to many kinds of systems. +\`configure' configures unbound 1.24.1 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1579,7 +1579,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of unbound 1.24.0:";; + short | recursive ) echo "Configuration of unbound 1.24.1:";; esac cat <<\_ACEOF @@ -1832,7 +1832,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -unbound configure 1.24.0 +unbound configure 1.24.1 generated by GNU Autoconf 2.71 Copyright (C) 2021 Free Software Foundation, Inc. @@ -2489,7 +2489,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.24.0, which was +It was created by unbound $as_me 1.24.1, which was generated by GNU Autoconf 2.71. Invocation command line was $ $0$ac_configure_args_raw @@ -3253,11 +3253,11 @@ UNBOUND_VERSION_MAJOR=1 UNBOUND_VERSION_MINOR=24 -UNBOUND_VERSION_MICRO=0 +UNBOUND_VERSION_MICRO=1 LIBUNBOUND_CURRENT=9 -LIBUNBOUND_REVISION=33 +LIBUNBOUND_REVISION=34 LIBUNBOUND_AGE=1 # 1.0.0 had 0:12:0 # 1.0.1 had 0:13:0 @@ -3358,6 +3358,7 @@ LIBUNBOUND_AGE=1 # 1.23.0 had 9:31:1 # 1.23.1 had 9:32:1 # 1.24.0 had 9:33:1 +# 1.24.1 had 9:34:1 # Current -- the number of the binary API that we're implementing # Revision -- which iteration of the implementation of the binary @@ -6947,6 +6948,53 @@ printf "%s\n" "#define HAVE_ATTR_UNUSED 1" >>confdefs.h fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the C compiler (${CC-cc}) accepts the \"nonstring\" attribute" >&5 +printf %s "checking whether the C compiler (${CC-cc}) accepts the \"nonstring\" attribute... " >&6; } +if test ${ac_cv_c_nonstring_attribute+y} +then : + printf %s "(cached) " >&6 +else $as_nop + ac_cv_c_nonstring_attribute=no +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +struct test { + char __attribute__((nonstring)) s[1]; +}; + +int +main (void) +{ + + struct test t = { "1" }; + (void) t; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO" +then : + ac_cv_c_nonstring_attribute="yes" +else $as_nop + ac_cv_c_nonstring_attribute="no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext + +fi + + + + +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_nonstring_attribute" >&5 +printf "%s\n" "$ac_cv_c_nonstring_attribute" >&6; } +if test $ac_cv_c_nonstring_attribute = yes; then + +printf "%s\n" "#define HAVE_ATTR_NONSTRING 1" >>confdefs.h + +fi + + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the C compiler (${CC-cc}) accepts the \"weak\" attribute" >&5 @@ -17972,7 +18020,9 @@ if test x_$enable_alloc_nonregional = x_yes; then printf "%s\n" "#define UNBOUND_ALLOC_NONREGIONAL 1" >>confdefs.h fi -if test x_$enable_alloc_checks = x_yes; then +if test x_$enable_alloc_checks = x_yes +then : + printf "%s\n" "#define UNBOUND_ALLOC_STATS 1" >>confdefs.h @@ -17980,28 +18030,29 @@ printf "%s\n" "#define UNBOUND_ALLOC_STATS 1" >>confdefs.h ASYNCLOOK_ALLOCCHECK_EXTRA_OBJ="alloc.lo" -else - if test x_$enable_alloc_lite = x_yes; then + +else $as_nop + + if test x_$enable_alloc_lite = x_yes +then : + printf "%s\n" "#define UNBOUND_ALLOC_LITE 1" >>confdefs.h - else + +else $as_nop + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for GNU libc compatible malloc" >&5 printf %s "checking for GNU libc compatible malloc... " >&6; } - if test "$cross_compiling" = yes +if test ${ac_cv_func_malloc_0_nonnull+y} then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no (crosscompile)" >&5 -printf "%s\n" "no (crosscompile)" >&6; } - case " $LIBOBJS " in - *" malloc.$ac_objext "* ) ;; - *) LIBOBJS="$LIBOBJS malloc.$ac_objext" - ;; -esac - - -printf "%s\n" "#define malloc rpl_malloc_unbound" >>confdefs.h + printf %s "(cached) " >&6 +else $as_nop + if test "$cross_compiling" = yes +then : + ac_cv_func_malloc_0_nonnull="no (crosscompile)" else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -18022,9 +18073,26 @@ main (void) _ACEOF if ac_fn_c_try_run "$LINENO" then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } - case " $LIBOBJS " in + ac_cv_func_malloc_0_nonnull=no +else $as_nop + ac_cv_func_malloc_0_nonnull=yes +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + + +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_malloc_0_nonnull" >&5 +printf "%s\n" "$ac_cv_func_malloc_0_nonnull" >&6; } + if test "$ac_cv_func_malloc_0_nonnull" = yes +then : + +printf "%s\n" "#define HAVE_MALLOC 1" >>confdefs.h + +else $as_nop + + case " $LIBOBJS " in *" malloc.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS malloc.$ac_objext" ;; @@ -18033,19 +18101,12 @@ esac printf "%s\n" "#define malloc rpl_malloc_unbound" >>confdefs.h -else $as_nop - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; } - -printf "%s\n" "#define HAVE_MALLOC 1" >>confdefs.h fi -rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ - conftest.$ac_objext conftest.beam conftest.$ac_ext + + fi - - fi fi # check windows threads (we use them, not pthreads, on windows). @@ -25309,7 +25370,7 @@ printf "%s\n" "#define MAXSYSLOGMSGLEN 10240" >>confdefs.h -version=1.24.0 +version=1.24.1 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for build time" >&5 printf %s "checking for build time... " >&6; } @@ -25839,7 +25900,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.24.0, which was +This file was extended by unbound $as_me 1.24.1, which was generated by GNU Autoconf 2.71. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -25907,7 +25968,7 @@ ac_cs_config_escaped=`printf "%s\n" "$ac_cs_config" | sed "s/^ //; s/'/'\\\\\\\\ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config='$ac_cs_config_escaped' ac_cs_version="\\ -unbound config.status 1.24.0 +unbound config.status 1.24.1 configured by $0, generated by GNU Autoconf 2.71, with options \\"\$ac_cs_config\\" diff --git a/configure.ac b/configure.ac index b7cca7977..ad7ec3e35 100644 --- a/configure.ac +++ b/configure.ac @@ -12,14 +12,14 @@ sinclude(dnscrypt/dnscrypt.m4) # must be numbers. ac_defun because of later processing m4_define([VERSION_MAJOR],[1]) m4_define([VERSION_MINOR],[24]) -m4_define([VERSION_MICRO],[0]) +m4_define([VERSION_MICRO],[1]) 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=33 +LIBUNBOUND_REVISION=34 LIBUNBOUND_AGE=1 # 1.0.0 had 0:12:0 # 1.0.1 had 0:13:0 @@ -120,6 +120,7 @@ LIBUNBOUND_AGE=1 # 1.23.0 had 9:31:1 # 1.23.1 had 9:32:1 # 1.24.0 had 9:33:1 +# 1.24.1 had 9:34:1 # Current -- the number of the binary API that we're implementing # Revision -- which iteration of the implementation of the binary @@ -328,6 +329,7 @@ fi AC_C_INLINE ACX_CHECK_FORMAT_ATTRIBUTE ACX_CHECK_UNUSED_ATTRIBUTE +ACX_CHECK_NONSTRING_ATTRIBUTE AC_DEFUN([CHECK_WEAK_ATTRIBUTE], [AC_REQUIRE([AC_PROG_CC]) @@ -633,19 +635,19 @@ AC_ARG_ENABLE(alloc-nonregional, AS_HELP_STRING([--enable-alloc-nonregional],[ e if test x_$enable_alloc_nonregional = x_yes; then AC_DEFINE(UNBOUND_ALLOC_NONREGIONAL, 1, [use malloc not regions, for debug use]) fi -if test x_$enable_alloc_checks = x_yes; then +AS_IF([test x_$enable_alloc_checks = x_yes],[ AC_DEFINE(UNBOUND_ALLOC_STATS, 1, [use statistics for allocs and frees, for debug use]) SLDNS_ALLOCCHECK_EXTRA_OBJ="alloc.lo log.lo" AC_SUBST(SLDNS_ALLOCCHECK_EXTRA_OBJ) ASYNCLOOK_ALLOCCHECK_EXTRA_OBJ="alloc.lo" AC_SUBST(ASYNCLOOK_ALLOCCHECK_EXTRA_OBJ) -else - if test x_$enable_alloc_lite = x_yes; then +],[ + AS_IF([test x_$enable_alloc_lite = x_yes],[ AC_DEFINE(UNBOUND_ALLOC_LITE, 1, [use to enable lightweight alloc assertions, for debug use]) - else + ],[ ACX_FUNC_MALLOC([unbound]) - fi -fi + ]) +]) # check windows threads (we use them, not pthreads, on windows). if test "$on_mingw" = "yes"; then @@ -2291,6 +2293,7 @@ dnl includes AHX_CONFIG_FORMAT_ATTRIBUTE AHX_CONFIG_UNUSED_ATTRIBUTE +AHX_CONFIG_NONSTRING_ATTRIBUTE AHX_CONFIG_FSEEKO AHX_CONFIG_MAXHOSTNAMELEN #if !defined(HAVE_SNPRINTF) || defined(SNPRINTF_RET_BROKEN) diff --git a/contrib/unbound.service.in b/contrib/unbound.service.in index cc8d0ed2d..b05e2c959 100644 --- a/contrib/unbound.service.in +++ b/contrib/unbound.service.in @@ -59,7 +59,7 @@ ExecReload=+/bin/kill -HUP $MAINPID ExecStart=@UNBOUND_SBIN_DIR@/unbound -d -p NotifyAccess=main Type=notify -CapabilityBoundingSet=CAP_NET_BIND_SERVICE CAP_SETGID CAP_SETUID CAP_SYS_CHROOT CAP_SYS_RESOURCE CAP_NET_RAW +CapabilityBoundingSet=CAP_NET_BIND_SERVICE CAP_SETGID CAP_SETUID CAP_SYS_CHROOT CAP_SYS_RESOURCE CAP_NET_ADMIN MemoryDenyWriteExecute=true NoNewPrivileges=true PrivateDevices=true diff --git a/contrib/unbound_portable.service.in b/contrib/unbound_portable.service.in index 22cd44638..d03197d55 100644 --- a/contrib/unbound_portable.service.in +++ b/contrib/unbound_portable.service.in @@ -26,7 +26,7 @@ ExecReload=+/bin/kill -HUP $MAINPID ExecStart=@UNBOUND_SBIN_DIR@/unbound -d -p NotifyAccess=main Type=notify -CapabilityBoundingSet=CAP_NET_BIND_SERVICE CAP_SETGID CAP_SETUID CAP_SYS_CHROOT CAP_SYS_RESOURCE CAP_NET_RAW +CapabilityBoundingSet=CAP_NET_BIND_SERVICE CAP_SETGID CAP_SETUID CAP_SYS_CHROOT CAP_SYS_RESOURCE CAP_NET_ADMIN MemoryDenyWriteExecute=true NoNewPrivileges=true PrivateDevices=true diff --git a/daemon/remote.c b/daemon/remote.c index d94c9f7fd..527c91a57 100644 --- a/daemon/remote.c +++ b/daemon/remote.c @@ -154,7 +154,7 @@ remote_setup_ctx(struct daemon_remote* rc, struct config_file* cfg) log_crypto_err("could not SSL_CTX_new"); return 0; } - if(!listen_sslctx_setup(rc->ctx)) { + if(!listen_sslctx_setup(rc->ctx, cfg->tls_use_system_policy_versions)) { return 0; } @@ -5895,6 +5895,7 @@ fr_atomic_copy_cfg(struct config_file* oldcfg, struct config_file* cfg, COPY_VAR_ptr(tls_ciphers); COPY_VAR_ptr(tls_ciphersuites); COPY_VAR_int(tls_use_sni); + COPY_VAR_int(tls_use_system_policy_versions); COPY_VAR_int(https_port); COPY_VAR_ptr(http_endpoint); COPY_VAR_uint32_t(http_max_streams); diff --git a/daemon/unbound.c b/daemon/unbound.c index 164d0fb89..688804743 100644 --- a/daemon/unbound.c +++ b/daemon/unbound.c @@ -473,7 +473,7 @@ setup_listen_sslctx(void** ctx, int is_dot, int is_doh, struct config_file* cfg) cfg->tls_ciphers, cfg->tls_ciphersuites, (cfg->tls_session_ticket_keys.first && cfg->tls_session_ticket_keys.first->str[0] != 0), - is_dot, is_doh))) { + is_dot, is_doh, cfg->tls_use_system_policy_versions))) { fatal_exit("could not set up listen SSL_CTX"); } } diff --git a/daemon/worker.c b/daemon/worker.c index 5088a63c7..33c7899f9 100644 --- a/daemon/worker.c +++ b/daemon/worker.c @@ -747,7 +747,7 @@ answer_from_cache(struct worker* worker, struct query_info* qinfo, *partial_repp = NULL; /* avoid accidental further pass */ /* Check TTL */ - if(rep->ttl < timenow) { + if(TTL_IS_EXPIRED(rep->ttl, timenow)) { /* Check if we need to serve expired now */ if(worker->env.cfg->serve_expired && /* if serve-expired-client-timeout is set, serve @@ -1967,11 +1967,11 @@ lookup_cache: if((worker->env.cfg->prefetch && rep->prefetch_ttl <= *worker->env.now) || (worker->env.cfg->serve_expired && - rep->ttl < *worker->env.now && + TTL_IS_EXPIRED(rep->ttl, *worker->env.now) && !(*worker->env.now < rep->serve_expired_norec_ttl))) { - time_t leeway = rep->ttl - *worker->env.now; - if(rep->ttl < *worker->env.now) - leeway = 0; + time_t leeway = + TTL_IS_EXPIRED(rep->ttl, *worker->env.now) + ? 0 : rep->ttl - *worker->env.now; lock_rw_unlock(&e->lock); reply_and_prefetch(worker, lookup_qinfo, diff --git a/dns64/dns64.c b/dns64/dns64.c index fbdbd87b9..0de1ac422 100644 --- a/dns64/dns64.c +++ b/dns64/dns64.c @@ -496,8 +496,8 @@ handle_ipv6_ptr(struct module_qstate* qstate, int id) /* Create the new sub-query. */ fptr_ok(fptr_whitelist_modenv_attach_sub(qstate->env->attach_sub)); - if(!(*qstate->env->attach_sub)(qstate, &qinfo, qstate->query_flags, 0, 0, - &subq)) + if(!(*qstate->env->attach_sub)(qstate, &qinfo, qstate->client_info, + qstate->query_flags, 0, 0, &subq)) return module_error; if (subq) { subq->curmod = id; @@ -522,8 +522,8 @@ generate_type_A_query(struct module_qstate* qstate, int id) /* Start the sub-query. */ fptr_ok(fptr_whitelist_modenv_attach_sub(qstate->env->attach_sub)); - if(!(*qstate->env->attach_sub)(qstate, &qinfo, qstate->query_flags, 0, - 0, &subq)) + if(!(*qstate->env->attach_sub)(qstate, &qinfo, qstate->client_info, + qstate->query_flags, 0, 0, &subq)) { verbose(VERB_ALGO, "dns64: sub-query creation failed"); return module_error; diff --git a/dnstap/unbound-dnstap-socket.c b/dnstap/unbound-dnstap-socket.c index a01627de9..c0d344cbb 100644 --- a/dnstap/unbound-dnstap-socket.c +++ b/dnstap/unbound-dnstap-socket.c @@ -347,7 +347,7 @@ static struct tap_socket* tap_socket_new_tlsaccept(char* ip, s->ev_cb = ev_cb; s->data = data; s->sslctx = listen_sslctx_create(server_key, server_cert, verifypem, - NULL, NULL, 0, 0, 0); + NULL, NULL, 0, 0, 0, 0); if(!s->sslctx) { log_err("could not create ssl context"); free(s->ip); diff --git a/doc/Changelog b/doc/Changelog index b5e8be997..67f54b02e 100644 --- a/doc/Changelog +++ b/doc/Changelog @@ -1,3 +1,73 @@ +30 September 2025: Wouter + - Fix for #1344: Fix that respip and dns64 can be enabled at the + same time, the client info is copied for attach_sub and add_sub + calls. That makes respip work on dns64 synthesized answers, and + also makes RPZ work with DNS64. The order for the modules is + module-config: "respip dns64 validator iterator". + +29 September 2025: Wouter + - Rebuild configure script from its sources. + - Fix modstack_call_init to use the original string when it has + changed, to call modstack_config with. And skip the changed name + in the string correctly. Thanks to Jan Komissar. + - Neaten up the change in acx_nlnetlabs.m4 to version 49. + - Fix fr_atomic_copy_cfg. + - Rebuild configure script from its sources. + - Fix #1353: auth-zone can not use empty label for $ORIGIN when + http download. + - Fix #1344: module conf 'respip dns64 validator cachedb iterator' + is not known to work. + +29 September 2025: Yorgos + - Merge #1349: Fix #1346: [FR] Please allow back TLS 1.2. + - Merge #1351: ac_cv_func_malloc_0_nonnull for malloc(0) check. + +26 September 2025: Yorgos + - Test for nonstring attribute in configure and add + nonstring attribute annotations. + +24 September 2025: Yorgos + - Avoid calling mesh_detect_cycle_found() when there is no mesh state + to begin with. + +23 September 2025: Yorgos + - Merge #1352 from Petr Vaganov: pythonmod: fix HANDLE_LEAK on + pythonmod_init. + - For #1352, align with the current Python<3 code. + - Merge #1350 from Maryse47: unbound.service.in: allow CAP_NET_ADMIN. + - For #1350, same CAP_NET_ADMIN change for unbound_portable.service.in + as well. + +19 September 2025: Wouter + - Fix to remove configure~ from release tarballs. + +19 September 2025: Yorgos + - Update README.man with clearer text. + - Merge #1337: 0 TTL cached replies and some TTL behavior changes. + - TTL change: Cached records that reach TTL 0 are expired. + - TTL change: TTL 0 upstream answers are no longer cached by + cachedb, as they should. + - TTL change: 'serve-expired-reply-ttl' is now capped by the original + TTL value of the record to try and make some sense when replying + with expired records. + - TTL change: TTL decoding was updated to adhere to RFC8767 section 4 + where a 'set high-order bit' means the value is positive instead of + 0. + - unbound.conf manpage: explicitly mention RFC6891. + +18 September 2025: Wouter + - Tag for 1.24.0 release. Includes the fixes below after rc1. + The repository continues with version 1.24.1. + +17 September 2025: Yorgos + - Too many quotes for the EDE message debug printout. + +15 September 2025: Yorgos + - Small debug output improvement when attaching an EDE. + +15 September 2025: Wouter + - Fix to print warning for when so-sndbuf setsockopt is not granted. + 11 September 2025: Wouter - version set to 1.24.0 for release. - tag for 1.24.0rc1. diff --git a/doc/README.man b/doc/README.man index 8e7897f47..dae1bc94c 100644 --- a/doc/README.man +++ b/doc/README.man @@ -6,11 +6,16 @@ and makes it easier to maintain and contribute to the documentation. The templated man pages (*.in) are still part of the code repository as to not alter current procedures that could be in place by users/packagers. +These man pages (*.in) are still the ones being used when +configuring/installing Unbound. +Packagers/users do not have to generate any man pages themselves, this is done +by the core developers during development and upon releasing new versions. + The templated man pages (*.in) are generated by Sphinx (used for the online documentation). The online documentation has its own repository at https://github.com/NLnetLabs/unbound-manual. -In the README.md there (branch test-auto for now), there are further simple -instructions on how to generate the templated man pages there and update them -in this repository. +In that README.md (https://github.com/NLnetLabs/unbound-manual/README.md) +there are further simple instructions on how to generate the templated man +pages there and update them in this repository. diff --git a/doc/example.conf.in b/doc/example.conf.in index cb8a24e38..4701ecb68 100644 --- a/doc/example.conf.in +++ b/doc/example.conf.in @@ -752,6 +752,7 @@ server: # serve-expired-ttl-reset: no # # TTL value to use when replying with expired data. + # Capped by the original TTL of the record. # serve-expired-reply-ttl: 30 # # Time in milliseconds before replying to the client with expired data. @@ -931,21 +932,26 @@ server: # https-port: 443 # quic-port: 853 + # Also serve tls on these port numbers (eg. 443, ...), by listing + # tls-additional-port: portno for each of the port numbers. + # cipher setting for TLSv1.2 # tls-ciphers: "DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256" # cipher setting for TLSv1.3 # tls-ciphersuites: "TLS_AES_128_GCM_SHA256:TLS_AES_128_CCM_8_SHA256:TLS_AES_128_CCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256" - # Pad responses to padded queries received over TLS - # pad-responses: yes - - # Padded responses will be padded to the closest multiple of this size. - # pad-responses-block-size: 468 - # Use the SNI extension for TLS connections. Default is yes. # Changing the value requires a reload. # tls-use-sni: yes + # Allow general-purpose version-flexible TLS server configuration that + # may be further restricted by the system's policy. + # Use only if you want to support legacy TLS client connections. + # Default is no and Unbound will only use the latest available TLS + # version. + # Changing the value requires a reload. + # tls-use-system-policy-versions: no + # Add the secret file for TLS Session Ticket. # Secret file must be 80 bytes of random data. # First key use to encrypt and decrypt TLS session tickets. @@ -966,15 +972,18 @@ server: # and on other systems, the default openssl certificates # tls-system-cert: no + # Pad responses to padded queries received over TLS + # pad-responses: yes + + # Padded responses will be padded to the closest multiple of this size. + # pad-responses-block-size: 468 + # Pad queries over TLS upstreams # pad-queries: yes # Padded queries will be padded to the closest multiple of this size. # pad-queries-block-size: 128 - # Also serve tls on these port numbers (eg. 443, ...), by listing - # tls-additional-port: portno for each of the port numbers. - # HTTP endpoint to provide DNS-over-HTTPS service on. # http-endpoint: "/dns-query" diff --git a/doc/unbound.conf.5.in b/doc/unbound.conf.5.in index 172eb26c5..08a926bd5 100644 --- a/doc/unbound.conf.5.in +++ b/doc/unbound.conf.5.in @@ -1218,6 +1218,47 @@ Default: \(dq\(dq .UNINDENT .INDENT 0.0 .TP +.B tls\-use\-sni: \fI\fP +Enable or disable sending the SNI extension on TLS connections. +.sp +\fBNOTE:\fP +.INDENT 7.0 +.INDENT 3.5 +Changing the value requires a reload. +.UNINDENT +.UNINDENT +.sp +Default: yes +.UNINDENT +.INDENT 0.0 +.TP +.B tls\-use\-system\-policy\-versions: \fI\fP +Enable or disable general\-puspose version\-flexible TLS server configuration +when serving TLS. +This will allow the whole list of available TLS versions provided by the +crypto library, which may have been further restricted by the system\(aqs +crypto policy. +.sp +By default Unbound only uses the latest available TLS version. +.sp +\fBCAUTION:\fP +.INDENT 7.0 +.INDENT 3.5 +Use only if you want to support legacy TLS client connections. +.UNINDENT +.UNINDENT +.sp +\fBNOTE:\fP +.INDENT 7.0 +.INDENT 3.5 +Changing the value requires a reload. +.UNINDENT +.UNINDENT +.sp +Default: no +.UNINDENT +.INDENT 0.0 +.TP .B pad\-responses: \fI\fP If enabled, TLS serviced queries that contained an EDNS Padding option will cause responses padded to the closest multiple of the size specified in @@ -1251,20 +1292,6 @@ Default: 128 .UNINDENT .INDENT 0.0 .TP -.B tls\-use\-sni: \fI\fP -Enable or disable sending the SNI extension on TLS connections. -.sp -\fBNOTE:\fP -.INDENT 7.0 -.INDENT 3.5 -Changing the value requires a reload. -.UNINDENT -.UNINDENT -.sp -Default: yes -.UNINDENT -.INDENT 0.0 -.TP .B https\-port: \fI\fP The port number on which to provide DNS\-over\-HTTPS service. Only interfaces configured with that port number as @number get the HTTPS @@ -1969,7 +1996,7 @@ Default: \(dq3 2 1 0 0\(dq .B harden\-short\-bufsize: \fI\fP Very small EDNS buffer sizes from queries are ignored. .sp -Default: yes (as described in the standard) +Default: yes (per \fI\%RFC 6891\fP) .UNINDENT .INDENT 0.0 .TP @@ -2600,6 +2627,12 @@ If \fI\%serve\-expired\-client\-timeout\fP is also used then it is RECOMMENDED to use 30 as the value (\fI\%RFC 8767\fP). .sp +This value is capped by the original TTL of the record. +This means that records with higher original TTL than this value will use +this value for expired replies. +Records with lower original TTL than this value will use their original TTL +for expired replies. +.sp Default: 30 .UNINDENT .INDENT 0.0 diff --git a/doc/unbound.conf.rst b/doc/unbound.conf.rst index 0494a9d49..3c2b1781e 100644 --- a/doc/unbound.conf.rst +++ b/doc/unbound.conf.rst @@ -1103,6 +1103,30 @@ These options are part of the **server:** clause. Default: "" +@@UAHL@unbound.conf@tls-use-sni@@: ** + Enable or disable sending the SNI extension on TLS connections. + + .. note:: Changing the value requires a reload. + + Default: yes + + +@@UAHL@unbound.conf@tls-use-system-policy-versions@@: ** + Enable or disable general-puspose version-flexible TLS server configuration + when serving TLS. + This will allow the whole list of available TLS versions provided by the + crypto library, which may have been further restricted by the system's + crypto policy. + + By default Unbound only uses the latest available TLS version. + + .. caution:: Use only if you want to support legacy TLS client connections. + + .. note:: Changing the value requires a reload. + + Default: no + + @@UAHL@unbound.conf@pad-responses@@: ** If enabled, TLS serviced queries that contained an EDNS Padding option will cause responses padded to the closest multiple of the size specified in @@ -1132,14 +1156,6 @@ These options are part of the **server:** clause. Default: 128 -@@UAHL@unbound.conf@tls-use-sni@@: ** - Enable or disable sending the SNI extension on TLS connections. - - .. note:: Changing the value requires a reload. - - Default: yes - - @@UAHL@unbound.conf@https-port@@: ** The port number on which to provide DNS-over-HTTPS service. Only interfaces configured with that port number as @number get the HTTPS @@ -1744,7 +1760,7 @@ These options are part of the **server:** clause. @@UAHL@unbound.conf@harden-short-bufsize@@: ** Very small EDNS buffer sizes from queries are ignored. - Default: yes (as described in the standard) + Default: yes (per :rfc:`6891`) @@UAHL@unbound.conf@harden-large-queries@@: ** @@ -2306,6 +2322,12 @@ These options are part of the **server:** clause. :ref:`serve-expired-client-timeout` is also used then it is RECOMMENDED to use 30 as the value (:rfc:`8767`). + This value is capped by the original TTL of the record. + This means that records with higher original TTL than this value will use + this value for expired replies. + Records with lower original TTL than this value will use their original TTL + for expired replies. + Default: 30 diff --git a/edns-subnet/subnetmod.c b/edns-subnet/subnetmod.c index 88310a785..a2a3f1846 100644 --- a/edns-subnet/subnetmod.c +++ b/edns-subnet/subnetmod.c @@ -567,8 +567,8 @@ generate_sub_request(struct module_qstate *qstate, int id, struct subnet_qstate* } fptr_ok(fptr_whitelist_modenv_attach_sub(qstate->env->attach_sub)); - if(!(*qstate->env->attach_sub)(qstate, &qinf, qflags, prime, valrec, - &subq)) { + if(!(*qstate->env->attach_sub)(qstate, &qinf, qstate->client_info, + qflags, prime, valrec, &subq)) { return 0; } if(subq) { diff --git a/ipsecmod/ipsecmod.c b/ipsecmod/ipsecmod.c index 1c9e6e6a5..ce38b55cf 100644 --- a/ipsecmod/ipsecmod.c +++ b/ipsecmod/ipsecmod.c @@ -163,7 +163,7 @@ generate_request(struct module_qstate* qstate, int id, uint8_t* name, } fptr_ok(fptr_whitelist_modenv_attach_sub(qstate->env->attach_sub)); - if(!(*qstate->env->attach_sub)(qstate, &ask, + if(!(*qstate->env->attach_sub)(qstate, &ask, NULL, (uint16_t)(BIT_RD|flags), 0, 0, &newq)){ log_err("Could not generate request: out of memory"); return 0; diff --git a/iterator/iterator.c b/iterator/iterator.c index 71e64655f..071dd0827 100644 --- a/iterator/iterator.c +++ b/iterator/iterator.c @@ -829,7 +829,7 @@ generate_sub_request(uint8_t* qname, size_t qnamelen, uint16_t qtype, struct mesh_state* sub = NULL; fptr_ok(fptr_whitelist_modenv_add_sub( qstate->env->add_sub)); - if(!(*qstate->env->add_sub)(qstate, &qinf, + if(!(*qstate->env->add_sub)(qstate, &qinf, NULL, qflags, prime, valrec, &subq, &sub)){ return 0; } @@ -838,8 +838,8 @@ generate_sub_request(uint8_t* qname, size_t qnamelen, uint16_t qtype, /* attach subquery, lookup existing or make a new one */ fptr_ok(fptr_whitelist_modenv_attach_sub( qstate->env->attach_sub)); - if(!(*qstate->env->attach_sub)(qstate, &qinf, qflags, prime, - valrec, &subq)) { + if(!(*qstate->env->attach_sub)(qstate, &qinf, NULL, qflags, + prime, valrec, &subq)) { return 0; } } diff --git a/makedist.sh b/makedist.sh index b6b593431..008e2ce4c 100755 --- a/makedist.sh +++ b/makedist.sh @@ -440,6 +440,7 @@ if [ "$DOWIN" = "yes" ]; then autoheader -f || error_cleanup "Autoheader failed." rm -r autom4te* || echo "ignored" rm -f config.h.in~ || echo "ignore absence of config.h.in~ file." + rm -f configure~ || echo "ignore absence of configure~ file." fi if test "`uname`" = "Linux"; then @@ -621,6 +622,7 @@ autoreconf -f || error_cleanup "Autoconf failed." rm -r autom4te* || error_cleanup "Failed to remove autoconf cache directory." rm -f config.h.in~ || echo "ignore absence of config.h.in~ file." +rm -f configure~ || echo "ignore absence of configure~ file." info "Building lexer and parser." echo "#include \"config.h\"" > util/configlexer.c || error_cleanup "Failed to create configlexer" @@ -666,6 +668,7 @@ if [ "$RECONFIGURE" = "yes" ]; then autoreconf -f || error_cleanup "Autoconf failed." rm -r autom4te* || error_cleanup "Failed to remove autoconf cache directory." rm -f config.h.in~ || echo "ignore absence of config.h.in~ file." + rm -f configure~ || echo "ignore absence of configure~ file." fi replace_all doc/README diff --git a/pythonmod/interface.i b/pythonmod/interface.i index 2040fb9e8..7ac868df5 100644 --- a/pythonmod/interface.i +++ b/pythonmod/interface.i @@ -732,8 +732,8 @@ struct module_env { char* tls_auth_name, struct module_qstate* q, int* was_ratelimited); void (*detach_subs)(struct module_qstate* qstate); int (*attach_sub)(struct module_qstate* qstate, - struct query_info* qinfo, uint16_t qflags, int prime, - int valrec, struct module_qstate** newq); + struct query_info* qinfo, struct respip_client_info* cinfo, + uint16_t qflags, int prime, int valrec, struct module_qstate** newq); void (*kill_sub)(struct module_qstate* newq); int (*detect_cycle)(struct module_qstate* qstate, struct query_info* qinfo, uint16_t flags, int prime, diff --git a/pythonmod/pythonmod.c b/pythonmod/pythonmod.c index e231ad079..7cd9a7543 100644 --- a/pythonmod/pythonmod.c +++ b/pythonmod/pythonmod.c @@ -454,7 +454,7 @@ int pythonmod_init(struct module_env* env, int id) if(PyDict_SetItemString(pe->data, "script", fname) < 0) { log_err("pythonmod: could not add item to dictionary"); Py_XDECREF(fname); - goto python_init_fail; + goto fail_close_file; } Py_XDECREF(fname); Py_XINCREF(pe->data); /* reference will be stolen below */ @@ -462,7 +462,7 @@ int pythonmod_init(struct module_env* env, int id) log_err("pythonmod: could not add mod_env object"); Py_XDECREF(pe->data); /* 2 times, here and on python_init_fail; */ /* on failure the reference is not stolen */ - goto python_init_fail; + goto fail_close_file; } if (PyRun_SimpleFile(script_py, pe->fname) < 0) { @@ -493,31 +493,15 @@ int pythonmod_init(struct module_env* env, int id) flen = (size_t)ftell(script_py); fstr = malloc(flen+1); if(!fstr) { - log_err("malloc failure to print parse error"); - -/* close the file */ -#if PY_MAJOR_VERSION < 3 - Py_XDECREF(PyFileObject); -#else - fclose(script_py); -#endif - - goto python_init_fail; + log_err("malloc failure to print parse error"); + goto fail_close_file; } fseek(script_py, 0, SEEK_SET); if(fread(fstr, flen, 1, script_py) < 1) { - log_err("file read failed to print parse error: %s: %s", + log_err("file read failed to print parse error: %s: %s", pe->fname, strerror(errno)); - free(fstr); - -/* close the file */ -#if PY_MAJOR_VERSION < 3 - Py_XDECREF(PyFileObject); -#else - fclose(script_py); -#endif - - goto python_init_fail; + free(fstr); + goto fail_close_file; } fstr[flen] = 0; /* we compile the string, but do not run it, to stop side-effects */ @@ -527,21 +511,13 @@ int pythonmod_init(struct module_env* env, int id) #endif log_py_err(); - -/* close the file */ -#if PY_MAJOR_VERSION < 3 - Py_XDECREF(PyFileObject); -#else - fclose(script_py); -#endif - #if PY_MAJOR_VERSION <= 2 || (PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION < 9) /* no cleanup needed for python before 3.9 */ #else /* cleanup for python 3.9 and newer */ free(fstr); #endif - goto python_init_fail; + goto fail_close_file; } /* close the file */ @@ -602,6 +578,13 @@ int pythonmod_init(struct module_env* env, int id) PyGILState_Release(gil); return 1; +fail_close_file: +#if PY_MAJOR_VERSION < 3 + Py_XDECREF(PyFileObject); +#else + fclose(script_py); +#endif + python_init_fail: Py_XDECREF(pe->module); Py_XDECREF(pe->dict); diff --git a/respip/respip.c b/respip/respip.c index 353a0fd78..f39ce5805 100644 --- a/respip/respip.c +++ b/respip/respip.c @@ -1074,7 +1074,8 @@ generate_cname_request(struct module_qstate* qstate, subqi.qtype = qstate->qinfo.qtype; subqi.qclass = qstate->qinfo.qclass; fptr_ok(fptr_whitelist_modenv_attach_sub(qstate->env->attach_sub)); - return (*qstate->env->attach_sub)(qstate, &subqi, BIT_RD, 0, 0, &subq); + return (*qstate->env->attach_sub)(qstate, &subqi, + qstate->client_info, BIT_RD, 0, 0, &subq); } void @@ -1233,7 +1234,8 @@ respip_inform_super(struct module_qstate* qstate, int id, struct respip_qstate* rq = (struct respip_qstate*)super->minfo[id]; struct reply_info* new_rep = NULL; - rq->state = RESPIP_SUBQUERY_FINISHED; + if(rq) + rq->state = RESPIP_SUBQUERY_FINISHED; /* respip subquery should have always been created with a valid reply * in super. */ diff --git a/services/authzone.c b/services/authzone.c index 27e50731b..ebe4fc670 100644 --- a/services/authzone.c +++ b/services/authzone.c @@ -172,7 +172,7 @@ get_rrset_ttl(struct ub_packed_rrset_key* k) /** Copy rrset into region from domain-datanode and packet rrset */ static struct ub_packed_rrset_key* auth_packed_rrset_copy_region(struct auth_zone* z, struct auth_data* node, - struct auth_rrset* rrset, struct regional* region, time_t adjust) + struct auth_rrset* rrset, struct regional* region) { struct ub_packed_rrset_key key; memset(&key, 0, sizeof(key)); @@ -183,7 +183,7 @@ auth_packed_rrset_copy_region(struct auth_zone* z, struct auth_data* node, key.rk.type = htons(rrset->type); key.rk.rrset_class = htons(z->dclass); key.entry.hash = rrset_key_hash(&key.rk); - return packed_rrset_copy_region(&key, region, adjust); + return packed_rrset_copy_region(&key, region, 0); } /** fix up msg->rep TTL and prefetch ttl */ @@ -237,7 +237,7 @@ msg_add_rrset_an(struct auth_zone* z, struct regional* region, return 0; /* copy it */ if(!(msg->rep->rrsets[msg->rep->rrset_count] = - auth_packed_rrset_copy_region(z, node, rrset, region, 0))) + auth_packed_rrset_copy_region(z, node, rrset, region))) return 0; msg->rep->rrset_count++; msg->rep->an_numrrsets++; @@ -261,7 +261,7 @@ msg_add_rrset_ns(struct auth_zone* z, struct regional* region, return 0; /* copy it */ if(!(msg->rep->rrsets[msg->rep->rrset_count] = - auth_packed_rrset_copy_region(z, node, rrset, region, 0))) + auth_packed_rrset_copy_region(z, node, rrset, region))) return 0; msg->rep->rrset_count++; msg->rep->ns_numrrsets++; @@ -284,7 +284,7 @@ msg_add_rrset_ar(struct auth_zone* z, struct regional* region, return 0; /* copy it */ if(!(msg->rep->rrsets[msg->rep->rrset_count] = - auth_packed_rrset_copy_region(z, node, rrset, region, 0))) + auth_packed_rrset_copy_region(z, node, rrset, region))) return 0; msg->rep->rrset_count++; msg->rep->ar_numrrsets++; @@ -4651,6 +4651,23 @@ http_parse_ttl(sldns_buffer* buf, struct sldns_file_parse_state* pstate) return 0; } +/** remove newlines from collated line */ +static void +chunkline_newline_removal(sldns_buffer* buf) +{ + size_t i, end=sldns_buffer_limit(buf); + for(i=0; iref[i].id != rep->ref[i].key->id) ck = NULL; else ck = packed_rrset_copy_region( - rep->ref[i].key, region, now); + rep->ref[i].key, region, + ((ntohs(rep->ref[i].key->rk.type)== + LDNS_RR_TYPE_NS && !pside)?qstarttime:now)); lock_rw_unlock(&rep->ref[i].key->entry.lock); if(ck) { /* use cached copy if memory allows */ qrep->rrsets[i] = ck; + ttl = ((struct packed_rrset_data*) + ck->entry.data)->ttl; + if(ttl < qrep->ttl) { + qrep->ttl = ttl; + qrep->prefetch_ttl = PREFETCH_TTL_CALC(qrep->ttl); + qrep->serve_expired_ttl = qrep->ttl + SERVE_EXPIRED_TTL; + } } } /* no break: also copy key item */ @@ -169,10 +178,12 @@ 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); + if((flags & DNSCACHE_STORE_EXPIRED_MSG_CACHEDB)) { + reply_info_absolute_ttls(rep, *env->now, *env->now - ttl); + } else reply_info_set_ttls(rep, *env->now); store_rrsets(env, rep, *env->now, leeway, pside, qrep, region, qstarttime); - if(ttl == 0 && !(flags & DNSCACHE_STORE_ZEROTTL)) { + if(ttl == 0) { /* we do not store the message, but we did store the RRs, * which could be useful for delegation information */ verbose(VERB_ALGO, "TTL 0: dropped msg from cache"); @@ -272,8 +283,10 @@ addr_to_additional(struct ub_packed_rrset_key* rrset, struct regional* region, { if((msg->rep->rrsets[msg->rep->rrset_count] = packed_rrset_copy_region(rrset, region, now))) { + struct packed_rrset_data* d = rrset->entry.data; msg->rep->ar_numrrsets++; msg->rep->rrset_count++; + UPDATE_TTL_FROM_RRSET(msg->rep->ttl, d->ttl); } } @@ -456,8 +469,10 @@ find_add_ds(struct module_env* env, struct regional* region, /* add it to auth section. This is the second rrset. */ if((msg->rep->rrsets[msg->rep->rrset_count] = packed_rrset_copy_region(rrset, region, now))) { + struct packed_rrset_data* d = rrset->entry.data; msg->rep->ns_numrrsets++; msg->rep->rrset_count++; + UPDATE_TTL_FROM_RRSET(msg->rep->ttl, d->ttl); } lock_rw_unlock(&rrset->entry.lock); } @@ -487,6 +502,8 @@ dns_msg_create(uint8_t* qname, size_t qnamelen, uint16_t qtype, return NULL; /* integer overflow protection */ msg->rep->flags = BIT_QR; /* with QR, no AA */ msg->rep->qdcount = 1; + msg->rep->ttl = MAX_TTL; /* will be updated (brought down) while we add + * rrsets to the message */ msg->rep->reason_bogus = LDNS_EDE_NONE; msg->rep->rrsets = (struct ub_packed_rrset_key**) regional_alloc(region, @@ -497,24 +514,28 @@ dns_msg_create(uint8_t* qname, size_t qnamelen, uint16_t qtype, } int -dns_msg_authadd(struct dns_msg* msg, struct regional* region, +dns_msg_authadd(struct dns_msg* msg, struct regional* region, struct ub_packed_rrset_key* rrset, time_t now) { - if(!(msg->rep->rrsets[msg->rep->rrset_count++] = + struct packed_rrset_data* d = rrset->entry.data; + if(!(msg->rep->rrsets[msg->rep->rrset_count++] = packed_rrset_copy_region(rrset, region, now))) return 0; msg->rep->ns_numrrsets++; + UPDATE_TTL_FROM_RRSET(msg->rep->ttl, d->ttl); return 1; } int -dns_msg_ansadd(struct dns_msg* msg, struct regional* region, +dns_msg_ansadd(struct dns_msg* msg, struct regional* region, struct ub_packed_rrset_key* rrset, time_t now) { - if(!(msg->rep->rrsets[msg->rep->rrset_count++] = + struct packed_rrset_data* d = rrset->entry.data; + if(!(msg->rep->rrsets[msg->rep->rrset_count++] = packed_rrset_copy_region(rrset, region, now))) return 0; msg->rep->an_numrrsets++; + UPDATE_TTL_FROM_RRSET(msg->rep->ttl, d->ttl); return 1; } @@ -585,6 +606,7 @@ gen_dns_msg(struct regional* region, struct query_info* q, size_t num) sizeof(struct reply_info) - sizeof(struct rrset_ref)); if(!msg->rep) return NULL; + msg->rep->ttl = MAX_TTL; msg->rep->reason_bogus = LDNS_EDE_NONE; msg->rep->reason_bogus_str = NULL; if(num > RR_COUNT_MAX) @@ -606,13 +628,13 @@ tomsg(struct module_env* env, struct query_info* q, struct reply_info* r, size_t i; int is_expired = 0; time_t now_control = now; - if(now > r->ttl) { + if(TTL_IS_EXPIRED(r->ttl, now)) { /* Check if we are allowed to serve expired */ if(!allow_expired || !reply_info_can_answer_expired(r, now)) return NULL; - /* Change the current time so we can pass the below TTL checks when - * serving expired data. */ - now_control = r->ttl - env->cfg->serve_expired_reply_ttl; + /* Change the current time so we can pass the below TTL checks + * when serving expired data. */ + now_control = 0; is_expired = 1; } @@ -620,15 +642,6 @@ tomsg(struct module_env* env, struct query_info* q, struct reply_info* r, if(!msg) return NULL; msg->rep->flags = r->flags; msg->rep->qdcount = r->qdcount; - msg->rep->ttl = is_expired - ?SERVE_EXPIRED_REPLY_TTL - :r->ttl - now; - if(r->prefetch_ttl > now) - msg->rep->prefetch_ttl = r->prefetch_ttl - now; - else - msg->rep->prefetch_ttl = PREFETCH_TTL_CALC(msg->rep->ttl); - msg->rep->serve_expired_ttl = msg->rep->ttl + SERVE_EXPIRED_TTL; - msg->rep->serve_expired_norec_ttl = 0; msg->rep->security = r->security; msg->rep->an_numrrsets = r->an_numrrsets; msg->rep->ns_numrrsets = r->ns_numrrsets; @@ -656,13 +669,30 @@ tomsg(struct module_env* env, struct query_info* q, struct reply_info* r, return NULL; } for(i=0; irep->rrset_count; i++) { + struct packed_rrset_data* d; msg->rep->rrsets[i] = packed_rrset_copy_region(r->rrsets[i], region, now); if(!msg->rep->rrsets[i]) { rrset_array_unlock(r->ref, r->rrset_count); return NULL; } + d = msg->rep->rrsets[i]->entry.data; + UPDATE_TTL_FROM_RRSET(msg->rep->ttl, d->ttl); } + if(msg->rep->rrset_count < 1) { + msg->rep->ttl = is_expired + ?SERVE_EXPIRED_REPLY_TTL + :r->ttl - now; + if(r->prefetch_ttl > now) + msg->rep->prefetch_ttl = r->prefetch_ttl - now; + else + msg->rep->prefetch_ttl = PREFETCH_TTL_CALC(msg->rep->ttl); + } else { + /* msg->rep->ttl has been updated through the RRSets above */ + msg->rep->prefetch_ttl = PREFETCH_TTL_CALC(msg->rep->ttl); + } + msg->rep->serve_expired_ttl = msg->rep->ttl + SERVE_EXPIRED_TTL; + msg->rep->serve_expired_norec_ttl = 0; if(env) rrset_array_unlock_touch(env->rrset_cache, scratch, r->ref, r->rrset_count); @@ -701,7 +731,7 @@ rrset_msg(struct ub_packed_rrset_key* rrset, struct regional* region, struct dns_msg* msg; struct packed_rrset_data* d = (struct packed_rrset_data*) rrset->entry.data; - if(now > d->ttl) + if(TTL_IS_EXPIRED(d->ttl, now)) return NULL; msg = gen_dns_msg(region, q, 1); /* only the CNAME (or other) RRset */ if(!msg) @@ -736,7 +766,7 @@ synth_dname_msg(struct ub_packed_rrset_key* rrset, struct regional* region, rrset->entry.data; uint8_t* newname, *dtarg = NULL; size_t newlen, dtarglen; - if(now > d->ttl) + if(TTL_IS_EXPIRED(d->ttl, now)) return NULL; /* only allow validated (with DNSSEC) DNAMEs used from cache * for insecure DNAMEs, query again. */ @@ -844,6 +874,8 @@ fill_any(struct module_env* env, /* set NOTIMPL for RFC 8482 */ msg->rep->flags |= LDNS_RCODE_NOTIMPL; msg->rep->security = sec_status_indeterminate; + msg->rep->ttl = 1; /* empty NOTIMPL response will never be + * updated with rrsets, set TTL to 1 */ return msg; } @@ -1069,7 +1101,7 @@ dns_cache_store(struct module_env* env, struct query_info* msgqinf, msgqinf->qclass, flags, 0, 1); if(e) { struct reply_info* cached = e->entry.data; - if(cached->ttl < *env->now + if(TTL_IS_EXPIRED(cached->ttl, *env->now) && reply_info_could_use_expired(cached, *env->now) /* If we are validating make sure only * validating modules can update such messages. diff --git a/services/cache/dns.h b/services/cache/dns.h index 8aa6b44bc..41d42e60d 100644 --- a/services/cache/dns.h +++ b/services/cache/dns.h @@ -53,7 +53,7 @@ struct delegpt; * Must be an unsigned 32-bit value larger than 0xffff */ /** Allow caching a DNS message with a zero TTL. */ -#define DNSCACHE_STORE_ZEROTTL 0x100000 +#define DNSCACHE_STORE_EXPIRED_MSG_CACHEDB 0x100000 /** * Region allocated message reply diff --git a/services/cache/rrset.c b/services/cache/rrset.c index 6d5c24f80..200e3c701 100644 --- a/services/cache/rrset.c +++ b/services/cache/rrset.c @@ -131,7 +131,7 @@ need_to_update_rrset(void* nd, void* cd, time_t timenow, int equal, int ns) struct packed_rrset_data* newd = (struct packed_rrset_data*)nd; struct packed_rrset_data* cached = (struct packed_rrset_data*)cd; /* o if new data is expired, cached data is better */ - if( newd->ttl < timenow && timenow <= cached->ttl) + if( TTL_IS_EXPIRED(newd->ttl, timenow) && !TTL_IS_EXPIRED(cached->ttl, timenow)) return 0; /* o store if rrset has been validated * everything better than bogus data @@ -146,13 +146,13 @@ need_to_update_rrset(void* nd, void* cd, time_t timenow, int equal, int ns) if( newd->trust > cached->trust ) { /* if the cached rrset is bogus, and new is equal, * do not update the TTL - let it expire. */ - if(equal && cached->ttl >= timenow && + if(equal && !TTL_IS_EXPIRED(cached->ttl, timenow) && cached->security == sec_status_bogus) return 0; return 1; } /* o item in cache has expired */ - if( cached->ttl < timenow ) + if( TTL_IS_EXPIRED(cached->ttl, timenow) ) return 1; /* o same trust, but different in data - insert it */ if( newd->trust == cached->trust && !equal ) { @@ -300,7 +300,7 @@ rrset_cache_lookup(struct rrset_cache* r, uint8_t* qname, size_t qnamelen, /* check TTL */ struct packed_rrset_data* data = (struct packed_rrset_data*)e->data; - if(timenow > data->ttl) { + if(TTL_IS_EXPIRED(data->ttl, timenow)) { lock_rw_unlock(&e->lock); return NULL; } @@ -310,17 +310,18 @@ rrset_cache_lookup(struct rrset_cache* r, uint8_t* qname, size_t qnamelen, return NULL; } -int +int rrset_array_lock(struct rrset_ref* ref, size_t count, time_t timenow) { size_t i; + struct packed_rrset_data* d; for(i=0; i0 && ref[i].key == ref[i-1].key) continue; /* only lock items once */ lock_rw_rdlock(&ref[i].key->entry.lock); - if(ref[i].id != ref[i].key->id || timenow > - ((struct packed_rrset_data*)(ref[i].key->entry.data)) - ->ttl) { + d = ref[i].key->entry.data; + if(ref[i].id != ref[i].key->id || + TTL_IS_EXPIRED(d->ttl, timenow)) { /* failure! rollback our readlocks */ rrset_array_unlock(ref, i+1); return 0; @@ -511,7 +512,7 @@ rrset_cache_expired_above(struct rrset_cache* r, uint8_t** qname, size_t* *qnamelen, searchtype, qclass, 0, 0, 0))) { struct packed_rrset_data* data = (struct packed_rrset_data*)rrset->entry.data; - if(now > data->ttl) { + if(TTL_IS_EXPIRED(data->ttl, now)) { /* it is expired, this is not wanted */ lock_rw_unlock(&rrset->entry.lock); log_nametypeclass(VERB_ALGO, "this rrset is expired", *qname, searchtype, qclass); diff --git a/services/listen_dnsport.c b/services/listen_dnsport.c index b7d3d747c..f7fcca194 100644 --- a/services/listen_dnsport.c +++ b/services/listen_dnsport.c @@ -450,7 +450,7 @@ create_udp_sock(int family, int socktype, struct sockaddr* addr, * /proc/sys/net/core/wmem_max or sysctl net.core.wmem_max */ if(setsockopt(s, SOL_SOCKET, SO_SNDBUFFORCE, (void*)&snd, (socklen_t)sizeof(snd)) < 0) { - if(errno != EPERM) { + if(errno != EPERM && errno != ENOBUFS) { log_err("setsockopt(..., SO_SNDBUFFORCE, " "...) failed: %s", sock_strerror(errno)); sock_close(s); @@ -458,15 +458,23 @@ create_udp_sock(int family, int socktype, struct sockaddr* addr, *inuse = 0; return -1; } + if(errno != EPERM) { + verbose(VERB_ALGO, "setsockopt(..., SO_SNDBUFFORCE, " + "...) was not granted: %s", sock_strerror(errno)); + } # endif /* SO_SNDBUFFORCE */ if(setsockopt(s, SOL_SOCKET, SO_SNDBUF, (void*)&snd, (socklen_t)sizeof(snd)) < 0) { - log_err("setsockopt(..., SO_SNDBUF, " - "...) failed: %s", sock_strerror(errno)); - sock_close(s); - *noproto = 0; - *inuse = 0; - return -1; + if(errno != ENOSYS && errno != ENOBUFS) { + log_err("setsockopt(..., SO_SNDBUF, " + "...) failed: %s", sock_strerror(errno)); + sock_close(s); + *noproto = 0; + *inuse = 0; + return -1; + } + log_warn("setsockopt(..., SO_SNDBUF, " + "...) was not granted: %s", sock_strerror(errno)); } /* check if we got the right thing or if system * reduced to some system max. Warn if so */ diff --git a/services/mesh.c b/services/mesh.c index 3212a6abf..40e68b70f 100644 --- a/services/mesh.c +++ b/services/mesh.c @@ -348,7 +348,7 @@ mesh_serve_expired_lookup(struct module_qstate* qstate, key = (struct msgreply_entry*)e->key; data = (struct reply_info*)e->data; - if(data->ttl < timenow) *is_expired = 1; + if(TTL_IS_EXPIRED(data->ttl, timenow)) *is_expired = 1; msg = tomsg(qstate->env, &key->key, data, qstate->region, timenow, qstate->env->cfg->serve_expired, qstate->env->scratch); if(!msg) @@ -1152,8 +1152,7 @@ mesh_detect_cycle_found(struct module_qstate* qstate, struct mesh_state* dep_m) { struct mesh_state* cyc_m = qstate->mesh_info; size_t counter = 0; - if(!dep_m) - return 0; + log_assert(dep_m); if(dep_m == cyc_m || find_in_subsub(dep_m, cyc_m, &counter)) { if(counter > MESH_MAX_SUBSUB) return 2; @@ -1190,24 +1189,19 @@ void mesh_detach_subs(struct module_qstate* qstate) } int mesh_add_sub(struct module_qstate* qstate, struct query_info* qinfo, - uint16_t qflags, int prime, int valrec, struct module_qstate** newq, - struct mesh_state** sub) + struct respip_client_info* cinfo, uint16_t qflags, int prime, + int valrec, struct module_qstate** newq, struct mesh_state** sub) { /* find it, if not, create it */ struct mesh_area* mesh = qstate->env->mesh; - *sub = mesh_area_find(mesh, NULL, qinfo, qflags, - prime, valrec); - if(mesh_detect_cycle_found(qstate, *sub)) { - verbose(VERB_ALGO, "attach failed, cycle detected"); - return 0; - } + *sub = mesh_area_find(mesh, cinfo, qinfo, qflags, prime, valrec); if(!*sub) { #ifdef UNBOUND_DEBUG struct rbnode_type* n; #endif /* create a new one */ - *sub = mesh_state_create(qstate->env, qinfo, NULL, qflags, prime, - valrec); + *sub = mesh_state_create(qstate->env, qinfo, cinfo, qflags, + prime, valrec); if(!*sub) { log_err("mesh_attach_sub: out of memory"); return 0; @@ -1230,18 +1224,25 @@ int mesh_add_sub(struct module_qstate* qstate, struct query_info* qinfo, rbtree_insert(&mesh->run, &(*sub)->run_node); log_assert(n != NULL); *newq = &(*sub)->s; - } else + } else { *newq = NULL; + if(mesh_detect_cycle_found(qstate, *sub)) { + verbose(VERB_ALGO, "attach failed, cycle detected"); + return 0; + } + } return 1; } int mesh_attach_sub(struct module_qstate* qstate, struct query_info* qinfo, - uint16_t qflags, int prime, int valrec, struct module_qstate** newq) + struct respip_client_info* cinfo, uint16_t qflags, int prime, + int valrec, struct module_qstate** newq) { struct mesh_area* mesh = qstate->env->mesh; struct mesh_state* sub = NULL; int was_detached; - if(!mesh_add_sub(qstate, qinfo, qflags, prime, valrec, newq, &sub)) + if(!mesh_add_sub(qstate, qinfo, cinfo, qflags, prime, valrec, newq, + &sub)) return 0; was_detached = (sub->super_set.count == 0); if(!mesh_state_attachment(qstate->mesh_info, sub)) @@ -1684,7 +1685,7 @@ static void dns_error_reporting(struct module_qstate* qstate, log_query_info(VERB_ALGO, "DNS Error Reporting: generating report " "query for", &qinfo); - if(mesh_add_sub(qstate, &qinfo, BIT_RD, 0, 0, &newq, &sub)) { + if(mesh_add_sub(qstate, &qinfo, NULL, BIT_RD, 0, 0, &newq, &sub)) { qstate->env->mesh->num_dns_error_reports++; } return; @@ -2297,7 +2298,7 @@ mesh_detect_cycle(struct module_qstate* qstate, struct query_info* qinfo, struct mesh_area* mesh = qstate->env->mesh; struct mesh_state* dep_m = NULL; dep_m = mesh_area_find(mesh, NULL, qinfo, flags, prime, valrec); - return mesh_detect_cycle_found(qstate, dep_m); + return dep_m?mesh_detect_cycle_found(qstate, dep_m):0; } void mesh_list_insert(struct mesh_state* m, struct mesh_state** fp, diff --git a/services/mesh.h b/services/mesh.h index f19f423a8..53a05b443 100644 --- a/services/mesh.h +++ b/services/mesh.h @@ -399,6 +399,8 @@ void mesh_detach_subs(struct module_qstate* qstate); * @param qstate: the state to find mesh state, and that wants to receive * the results from the new subquery. * @param qinfo: what to query for (copied). + * @param cinfo: if non-NULL client specific info that may affect IP-based + * actions that apply to the query result. It is copied. * @param qflags: what flags to use (RD / CD flag or not). * @param prime: if it is a (stub) priming query. * @param valrec: if it is a validation recursion query (lookup of key, DS). @@ -407,7 +409,8 @@ void mesh_detach_subs(struct module_qstate* qstate); * @return: false on error, true if success (and init may be needed). */ int mesh_attach_sub(struct module_qstate* qstate, struct query_info* qinfo, - uint16_t qflags, int prime, int valrec, struct module_qstate** newq); + struct respip_client_info* cinfo, uint16_t qflags, int prime, + int valrec, struct module_qstate** newq); /** * Add detached query. @@ -426,6 +429,8 @@ int mesh_attach_sub(struct module_qstate* qstate, struct query_info* qinfo, * @param qstate: the state to find mesh state, and that wants to receive * the results from the new subquery. * @param qinfo: what to query for (copied). + * @param cinfo: if non-NULL client specific info that may affect IP-based + * actions that apply to the query result. It is copied. * @param qflags: what flags to use (RD / CD flag or not). * @param prime: if it is a (stub) priming query. * @param valrec: if it is a validation recursion query (lookup of key, DS). @@ -435,8 +440,8 @@ int mesh_attach_sub(struct module_qstate* qstate, struct query_info* qinfo, * @return: false on error, true if success (and init may be needed). */ int mesh_add_sub(struct module_qstate* qstate, struct query_info* qinfo, - uint16_t qflags, int prime, int valrec, struct module_qstate** newq, - struct mesh_state** sub); + struct respip_client_info* cinfo, uint16_t qflags, int prime, + int valrec, struct module_qstate** newq, struct mesh_state** sub); /** * Query state is done, send messages to reply entries. diff --git a/services/modstack.c b/services/modstack.c index 2bc79c4ad..f5913dc38 100644 --- a/services/modstack.c +++ b/services/modstack.c @@ -262,6 +262,7 @@ int modstack_call_init(struct module_stack* stack, const char* module_conf, struct module_env* env) { + const char* orig_module_conf = module_conf; int i, changed = 0; env->need_to_validate = 0; /* set by module init below */ for(i=0; inum; i++) { @@ -276,11 +277,13 @@ modstack_call_init(struct module_stack* stack, const char* module_conf, changed = 1; } } - module_conf += strlen(stack->mod[i]->name); + /* Skip this module name in module_conf. */ + while(*module_conf && !isspace((unsigned char)*module_conf)) + module_conf++; } if(changed) { modstack_free(stack); - if(!modstack_config(stack, module_conf)) { + if(!modstack_config(stack, orig_module_conf)) { return 0; } } diff --git a/smallapp/unbound-checkconf.c b/smallapp/unbound-checkconf.c index 66f53bd4d..fd3f8ff9a 100644 --- a/smallapp/unbound-checkconf.c +++ b/smallapp/unbound-checkconf.c @@ -784,7 +784,6 @@ morechecks(struct config_file* cfg) /* check that the modules listed in module_conf exist */ check_modules_exist(cfg->module_conf); - /* Respip is known to *not* work with dns64. */ if(strcmp(cfg->module_conf, "iterator") != 0 && strcmp(cfg->module_conf, "validator iterator") != 0 && strcmp(cfg->module_conf, "dns64 validator iterator") != 0 @@ -870,6 +869,7 @@ morechecks(struct config_file* cfg) && strcmp(cfg->module_conf, "respip cachedb iterator") != 0 && strcmp(cfg->module_conf, "dns64 validator cachedb iterator") != 0 && strcmp(cfg->module_conf, "dns64 cachedb iterator") != 0 + && strcmp(cfg->module_conf, "respip dns64 validator cachedb iterator") != 0 #endif #if defined(WITH_PYTHONMODULE) && defined(USE_CACHEDB) && strcmp(cfg->module_conf, "python dns64 cachedb iterator") != 0 diff --git a/testdata/auth_https_origin.tdir/127.0.0.1/example.com.zone b/testdata/auth_https_origin.tdir/127.0.0.1/example.com.zone new file mode 100644 index 000000000..e5ef82f14 --- /dev/null +++ b/testdata/auth_https_origin.tdir/127.0.0.1/example.com.zone @@ -0,0 +1,5 @@ +$ORIGIN . +$TTL 7200 +example.com. IN SOA ns.example.com. hostmaster.example.com. 1 3600 900 86400 3600 +example.com. IN NS ns.example.net. +www.example.com. IN A 1.2.3.4 diff --git a/testdata/auth_https_origin.tdir/auth_https_origin.conf b/testdata/auth_https_origin.tdir/auth_https_origin.conf new file mode 100644 index 000000000..bfe013e44 --- /dev/null +++ b/testdata/auth_https_origin.tdir/auth_https_origin.conf @@ -0,0 +1,17 @@ +server: + verbosity: 7 + # num-threads: 1 + interface: 127.0.0.1 + port: @PORT@ + use-syslog: no + directory: "" + pidfile: "unbound.pid" + chroot: "" + username: "" + do-not-query-localhost: no +auth-zone: + name: "example.com" + for-upstream: yes + for-downstream: yes + url: "https://127.0.0.1:@TOPORT@/example.com.zone" + diff --git a/testdata/auth_https_origin.tdir/auth_https_origin.dsc b/testdata/auth_https_origin.tdir/auth_https_origin.dsc new file mode 100644 index 000000000..9727fc6d1 --- /dev/null +++ b/testdata/auth_https_origin.tdir/auth_https_origin.dsc @@ -0,0 +1,16 @@ +BaseName: auth_https_origin +Version: 1.0 +Description: Perform https for authority zone with $ORIGIN +CreationDate: Mon 29 September 14:35:40 CEST 2025 +Maintainer: dr. W.C.A. Wijngaards +Category: +Component: +CmdDepends: +Depends: +Help: +Pre: auth_https_origin.pre +Post: auth_https_origin.post +Test: auth_https_origin.test +AuxFiles: +Passed: +Failure: diff --git a/testdata/auth_https_origin.tdir/auth_https_origin.post b/testdata/auth_https_origin.tdir/auth_https_origin.post new file mode 100644 index 000000000..f642d5401 --- /dev/null +++ b/testdata/auth_https_origin.tdir/auth_https_origin.post @@ -0,0 +1,11 @@ +# #-- auth_https_origin.post --# +# source the master var file when it's there +[ -f ../.tpkg.var.master ] && source ../.tpkg.var.master +# source the test var file when it's there +[ -f .tpkg.var.test ] && source .tpkg.var.test +# +# do your teardown here +PRE="../.." +. ../common.sh +kill_pid $UNBOUND_PID +kill_pid $PETAL_PID diff --git a/testdata/auth_https_origin.tdir/auth_https_origin.pre b/testdata/auth_https_origin.tdir/auth_https_origin.pre new file mode 100644 index 000000000..ec838c571 --- /dev/null +++ b/testdata/auth_https_origin.tdir/auth_https_origin.pre @@ -0,0 +1,34 @@ +# #-- auth_https_origin.pre--# +# source the master var file when it's there +[ -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 + +PRE="../.." +. ../common.sh +get_random_port 2 +UNBOUND_PORT=$RND_PORT +PETAL_PORT=$(($RND_PORT + 1)) +echo "UNBOUND_PORT=$UNBOUND_PORT" >> .tpkg.var.test +echo "PETAL_PORT=$PETAL_PORT" >> .tpkg.var.test + +get_make +(cd $PRE; $MAKE petal) + +# start https daemon +$PRE/petal -v -a "127.0.0.1" -p $PETAL_PORT >petal.log 2>&1 & +PETAL_PID=$! +echo "PETAL_PID=$PETAL_PID" >> .tpkg.var.test +cat .tpkg.var.test +wait_petal_up petal.log + +# make config file +sed -e 's/@PORT\@/'$UNBOUND_PORT'/' -e 's/@TOPORT\@/'$PETAL_PORT'/' < auth_https_origin.conf > ub.conf +# start unbound in the background +$PRE/unbound -d -c ub.conf >unbound.log 2>&1 & +UNBOUND_PID=$! +echo "UNBOUND_PID=$UNBOUND_PID" >> .tpkg.var.test + +cat .tpkg.var.test +wait_unbound_up unbound.log + diff --git a/testdata/auth_https_origin.tdir/auth_https_origin.test b/testdata/auth_https_origin.tdir/auth_https_origin.test new file mode 100644 index 000000000..ac6eda9bb --- /dev/null +++ b/testdata/auth_https_origin.tdir/auth_https_origin.test @@ -0,0 +1,63 @@ +# #-- auth_https_origin.test --# +# source the master var file when it's there +[ -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 + +PRE="../.." +. ../common.sh +# do the test +echo "> dig www.example.com." +dig @127.0.0.1 -p $UNBOUND_PORT www.example.com. | tee outfile +if grep SERVFAIL outfile; then + echo "> try again" + dig @127.0.0.1 -p $UNBOUND_PORT www.example.com. | tee outfile +fi +if grep SERVFAIL outfile; then + echo "> try again" + sleep 1 + dig @127.0.0.1 -p $UNBOUND_PORT www.example.com. | tee outfile +fi +if grep SERVFAIL outfile; then + echo "> try again" + sleep 1 + dig @127.0.0.1 -p $UNBOUND_PORT www.example.com. | tee outfile +fi +if grep SERVFAIL outfile; then + echo "> try again" + sleep 1 + dig @127.0.0.1 -p $UNBOUND_PORT www.example.com. | tee outfile +fi +if grep SERVFAIL outfile; then + echo "> try again" + sleep 10 + dig @127.0.0.1 -p $UNBOUND_PORT www.example.com. | tee outfile +fi +if grep SERVFAIL outfile; then + echo "> try again" + sleep 10 + dig @127.0.0.1 -p $UNBOUND_PORT www.example.com. | tee outfile +fi +echo "> cat logfiles" +cat petal.log +cat unbound.log +echo "> check answer" +if grep "1.2.3.4" outfile; then + echo "OK" +else + echo "Not OK" + exit 1 +fi + +# Test that notify is allowed from the webserver address +get_ldns_notify +echo "> ldns-notify -z example.com" +$LDNS_NOTIFY -p $UNBOUND_PORT -z example.com 127.0.0.1 | tee outfile +if grep "rcode: REFUSED" outfile; then + echo "Not OK" + exit 1 +else + echo "OK" +fi + +exit 0 diff --git a/testdata/auth_https_origin.tdir/petal.key b/testdata/auth_https_origin.tdir/petal.key new file mode 100644 index 000000000..6614e498f --- /dev/null +++ b/testdata/auth_https_origin.tdir/petal.key @@ -0,0 +1,21 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIDfQIBAAKBwQC1xQ/Kca6zszZbcCtdOTIH2Uy2gOy/DfabMUU7TmNPm0dVE0NJ +RuN+Rm304SonpwghfP2/ULZNnuDgpG03/32yI7k/VzG6iA4hiF7tT/KAAWC/+2l1 +QCsawCV2bSrFK0VhcZr7ALqXd8vkDaQ867K029ypjOQtAJ85qdO3mERy7TGtdUcu +O6hLeVet419YeQ2F8cfNxn63d7bOzNGLPW5xwaCd3UcgD+Ib0k4xfFvbinvPQUeU +J/i4YDWexFYSL+ECAwEAAQKBwCLXXQl+9O+5AEhSnd1Go1Jh0pSA7eBJOuXQcebG +Rb7ykp+6C4G2NtDziwwPRNdI6wQQQ0sym18RfyVQHydGr78/nbiIbB3HCn5e92Mh +mefzW6ow9Kvm2txLzGKA1lvoyRbNm81jnG/eygi3u7Nqd5PNv+4dHj2RkTlmxOeh +qnDMVP5md8uZPv6lYNnrnIzvLCR5vnPNdVwn89AqzI85IcDZdy0R9ZX4NBbsDgAU +6ig6uXuRXvSGiyJ/OUXSrnogaQJhAOjvkHUhVZQkPOxO90TNH4j0GdKKtbSWxIdz +lKfuJeBAEqs0TL+C6vbS81Xw3W1alyDdUBk3rJMOBqW6Ryq5HNL+j5H+Jfsh7fvc +Yle+5wHGci0P9zCFZCrY8It7n9XFIwJhAMfEi6oJa2G8waPJ1bQhxka82Tf9pnKM +XCn/1BBOFjVIx5F842cpA+zp5a62GENTGYPQTTRBB/2/ZwnW5aIkrlg54AtmbqBZ +Oh+2kJdJQD/tfoVmc5soUE2ScTHadK5RKwJhAN4w9kjkXS+MSZjX0kIMsBIBVkhh +C+aREjJqa9ir7/Ey7RvmLXdYuCxtGLRXp7/R8+rjcK49Tx6O+IRJZe042mfhbq3C +EhS1Tr86f4xXix9EXlDhs9bSxrOgcAN9Dv/opQJhAK7eBcPaav0rVfYh/8emqQHS +3fJ9Pu6WnzbEksWTFS2ff9KDGCx9YspIFJ5TF/oXDAaumGZdZrlgirm6O1kr8tGY +F97i04PZl1+bWAaWQH+1TUNI43m2WFUPE7coG2tb8QJgcddDg9VlXliZqgcETZfJ +kJmYETxrcSn3ao6v116N8yxhEgUgjkmsCTiFgx36iDVnXwK6PIt+sIu8MC7eYNa3 +berrv/M21K0LRn20IWRxvUobG070weHCAgkko7fTWgr2 +-----END RSA PRIVATE KEY----- diff --git a/testdata/auth_https_origin.tdir/petal.pem b/testdata/auth_https_origin.tdir/petal.pem new file mode 100644 index 000000000..19c8b895b --- /dev/null +++ b/testdata/auth_https_origin.tdir/petal.pem @@ -0,0 +1,14 @@ +-----BEGIN CERTIFICATE----- +MIICFzCCAUACCQDO660L5y5LGDANBgkqhkiG9w0BAQUFADAQMQ4wDAYDVQQDEwVw +ZXRhbDAeFw0xMDA5MzAxMzQzMDFaFw0zMDA2MTcxMzQzMDFaMBAxDjAMBgNVBAMT +BXBldGFsMIHfMA0GCSqGSIb3DQEBAQUAA4HNADCByQKBwQC1xQ/Kca6zszZbcCtd +OTIH2Uy2gOy/DfabMUU7TmNPm0dVE0NJRuN+Rm304SonpwghfP2/ULZNnuDgpG03 +/32yI7k/VzG6iA4hiF7tT/KAAWC/+2l1QCsawCV2bSrFK0VhcZr7ALqXd8vkDaQ8 +67K029ypjOQtAJ85qdO3mERy7TGtdUcuO6hLeVet419YeQ2F8cfNxn63d7bOzNGL +PW5xwaCd3UcgD+Ib0k4xfFvbinvPQUeUJ/i4YDWexFYSL+ECAwEAATANBgkqhkiG +9w0BAQUFAAOBwQBBkX9KDP2RXbg+xPmdJ4P6CwvA5x1LZwC++ydVx4NlvT0pWicD +ZUnXjcWAJlkeOuUBAqFG7WHTrXpUUAjmdqFVq2yFjteUYBdrFz0RDB2jM9feeKYO +mTgxdZyT9a6humxCxt5VfgT02axLjm/2AqCyFPMbf4PASoJDln01AEuZLZ8Xl2gV +bYHMnHTGoD1Hu6FNEzRgkMC6XT8X3YjHvzQhpc/qL5wEfEsinQGdX4twsuWbf8xd +q7miNnkO8vd0maw= +-----END CERTIFICATE----- diff --git a/testdata/cachedb_expired.crpl b/testdata/cachedb_expired.crpl index d3bf06fe1..697e88e26 100644 --- a/testdata/cachedb_expired.crpl +++ b/testdata/cachedb_expired.crpl @@ -5,7 +5,10 @@ server: minimal-responses: no serve-expired: yes serve-expired-client-timeout: 0 + serve-expired-reply-ttl: 123 module-config: "cachedb iterator" + ede: yes + ede-serve-expired: yes cachedb: backend: "testframe" @@ -82,7 +85,7 @@ REPLY QR AA NOERROR SECTION QUESTION www.example.com. IN A SECTION ANSWER -www.example.com. 10 IN A 1.2.3.4 +www.example.com. 200 IN A 1.2.3.4 ENTRY_END ENTRY_BEGIN @@ -91,7 +94,8 @@ REPLY QR AA NOERROR SECTION QUESTION www2.example.com. IN A SECTION ANSWER -www2.example.com. 10 IN A 1.2.3.5 +; TTL lower than serve-expired-reply-ttl on purpose +www2.example.com. 100 IN A 1.2.3.5 ENTRY_END RANGE_END @@ -111,7 +115,7 @@ REPLY QR RD RA NOERROR SECTION QUESTION www.example.com. IN A SECTION ANSWER -www.example.com. 10 IN A 1.2.3.4 +www.example.com. 200 IN A 1.2.3.4 ENTRY_END ; Get another query in cache to make it expired. @@ -130,46 +134,46 @@ REPLY QR RD RA NOERROR SECTION QUESTION www2.example.com. IN A SECTION ANSWER -www2.example.com. 10 IN A 1.2.3.5 +www2.example.com. 100 IN A 1.2.3.5 ENTRY_END ; it is now expired -STEP 40 TIME_PASSES ELAPSE 20 +STEP 40 TIME_PASSES ELAPSE 200 ; cache is expired, and cachedb is expired. STEP 50 QUERY ENTRY_BEGIN -REPLY RD +REPLY RD DO SECTION QUESTION www2.example.com. IN A ENTRY_END STEP 60 CHECK_ANSWER ENTRY_BEGIN -MATCH all ttl -REPLY QR RD RA NOERROR +MATCH all ttl ede=3 +REPLY QR RD RA DO NOERROR SECTION QUESTION www2.example.com. IN A SECTION ANSWER -www2.example.com. 30 IN A 1.2.3.5 +www2.example.com. 100 IN A 1.2.3.5 ENTRY_END ; cache is expired, cachedb has no answer STEP 70 QUERY ENTRY_BEGIN -REPLY RD +REPLY RD DO SECTION QUESTION www.example.com. IN A ENTRY_END STEP 80 CHECK_ANSWER ENTRY_BEGIN -MATCH all ttl -REPLY QR RD RA NOERROR +MATCH all ttl ede=3 +REPLY QR RD RA DO NOERROR SECTION QUESTION www.example.com. IN A SECTION ANSWER -www.example.com. 30 IN A 1.2.3.4 +www.example.com. 123 IN A 1.2.3.4 ENTRY_END STEP 90 TRAFFIC @@ -189,7 +193,7 @@ REPLY QR RD RA NOERROR SECTION QUESTION www.example.com. IN A SECTION ANSWER -www.example.com. 10 IN A 1.2.3.4 +www.example.com. 200 IN A 1.2.3.4 ENTRY_END ; flush the entry from cache @@ -210,30 +214,30 @@ REPLY QR RD RA NOERROR SECTION QUESTION www.example.com. IN A SECTION ANSWER -www.example.com. 10 IN A 1.2.3.4 +www.example.com. 200 IN A 1.2.3.4 ENTRY_END ; it is now expired -STEP 150 TIME_PASSES ELAPSE 20 +STEP 150 TIME_PASSES ELAPSE 200 ; flush the entry from cache STEP 160 FLUSH_MESSAGE www.example.com. IN A ; cache has no answer, cachedb is expired STEP 170 QUERY ENTRY_BEGIN -REPLY RD +REPLY RD DO SECTION QUESTION www.example.com. IN A ENTRY_END STEP 180 CHECK_ANSWER ENTRY_BEGIN -MATCH all ttl -REPLY QR RD RA NOERROR +MATCH all ttl ede=3 +REPLY QR RD RA DO NOERROR SECTION QUESTION www.example.com. IN A SECTION ANSWER -www.example.com. 30 IN A 1.2.3.4 +www.example.com. 123 IN A 1.2.3.4 ENTRY_END STEP 190 TRAFFIC @@ -254,7 +258,7 @@ REPLY QR RD RA NOERROR SECTION QUESTION www.example.com. IN A SECTION ANSWER -www.example.com. 10 IN A 1.2.3.4 +www.example.com. 200 IN A 1.2.3.4 ENTRY_END ; expire the entry in cache @@ -275,30 +279,30 @@ REPLY QR RD RA NOERROR SECTION QUESTION www.example.com. IN A SECTION ANSWER -www.example.com. 10 IN A 1.2.3.4 +www.example.com. 200 IN A 1.2.3.4 ENTRY_END ; it is now expired -STEP 250 TIME_PASSES ELAPSE 20 +STEP 250 TIME_PASSES ELAPSE 200 ; expire the entry in cache STEP 260 EXPIRE_MESSAGE www.example.com. IN A ; cache is expired, cachedb is expired STEP 270 QUERY ENTRY_BEGIN -REPLY RD +REPLY RD DO SECTION QUESTION www.example.com. IN A ENTRY_END STEP 280 CHECK_ANSWER ENTRY_BEGIN -MATCH all ttl -REPLY QR RD RA NOERROR +MATCH all ttl ede=3 +REPLY QR RD RA DO NOERROR SECTION QUESTION www.example.com. IN A SECTION ANSWER -www.example.com. 30 IN A 1.2.3.4 +www.example.com. 123 IN A 1.2.3.4 ENTRY_END STEP 290 TRAFFIC @@ -319,7 +323,7 @@ REPLY QR RD RA NOERROR SECTION QUESTION www.example.com. IN A SECTION ANSWER -www.example.com. 10 IN A 1.2.3.4 +www.example.com. 200 IN A 1.2.3.4 ENTRY_END SCENARIO_END diff --git a/testdata/cachedb_expired_client_timeout.crpl b/testdata/cachedb_expired_client_timeout.crpl index 78ddf4d8f..16d8cc30d 100644 --- a/testdata/cachedb_expired_client_timeout.crpl +++ b/testdata/cachedb_expired_client_timeout.crpl @@ -4,12 +4,14 @@ server: qname-minimisation: no minimal-responses: no serve-expired: yes - serve-expired-reply-ttl: 30 + serve-expired-reply-ttl: 123 ; at least one second, so we can time skip past the timer in the ; testbound script steps, but also reply within the time. serve-expired-client-timeout: 1200 module-config: "cachedb iterator" discard-timeout: 3000 + ede: yes + ede-serve-expired: yes cachedb: backend: "testframe" @@ -86,7 +88,7 @@ REPLY QR AA NOERROR SECTION QUESTION www.example.com. IN A SECTION ANSWER -www.example.com. 10 IN A 1.2.3.4 +www.example.com. 200 IN A 1.2.3.4 ENTRY_END ENTRY_BEGIN @@ -95,7 +97,8 @@ REPLY QR AA NOERROR SECTION QUESTION www2.example.com. IN A SECTION ANSWER -www2.example.com. 10 IN A 1.2.3.5 +; TTL lower than serve-expired-reply-ttl on purpose +www2.example.com. 100 IN A 1.2.3.5 ENTRY_END RANGE_END @@ -108,7 +111,7 @@ REPLY QR AA NOERROR SECTION QUESTION www.example.com. IN A SECTION ANSWER -www.example.com. 10 IN A 1.2.3.6 +www.example.com. 200 IN A 1.2.3.6 ENTRY_END ENTRY_BEGIN @@ -117,7 +120,8 @@ REPLY QR AA NOERROR SECTION QUESTION www2.example.com. IN A SECTION ANSWER -www2.example.com. 10 IN A 1.2.3.7 +; TTL lower than serve-expired-reply-ttl on purpose +www2.example.com. 100 IN A 1.2.3.7 ENTRY_END RANGE_END @@ -132,7 +136,7 @@ REPLY QR AA NOERROR SECTION QUESTION www.example.com. IN A SECTION ANSWER -www.example.com. 10 IN A 1.2.3.8 +www.example.com. 200 IN A 1.2.3.8 ENTRY_END ENTRY_BEGIN @@ -141,7 +145,8 @@ REPLY QR AA NOERROR SECTION QUESTION www2.example.com. IN A SECTION ANSWER -www2.example.com. 10 IN A 1.2.3.9 +; TTL lower than serve-expired-reply-ttl on purpose +www2.example.com. 100 IN A 1.2.3.9 ENTRY_END RANGE_END @@ -156,7 +161,7 @@ REPLY QR AA NOERROR SECTION QUESTION www.example.com. IN A SECTION ANSWER -www.example.com. 10 IN A 1.2.3.10 +www.example.com. 200 IN A 1.2.3.10 ENTRY_END ENTRY_BEGIN @@ -165,7 +170,7 @@ REPLY QR AA NOERROR SECTION QUESTION www2.example.com. IN A SECTION ANSWER -www2.example.com. 10 IN A 1.2.3.11 +www2.example.com. 100 IN A 1.2.3.11 ENTRY_END RANGE_END @@ -188,7 +193,7 @@ REPLY QR RD RA NOERROR SECTION QUESTION www.example.com. IN A SECTION ANSWER -www.example.com. 10 IN A 1.2.3.4 +www.example.com. 200 IN A 1.2.3.4 ENTRY_END ; Get another query in cache. @@ -207,7 +212,7 @@ REPLY QR RD RA NOERROR SECTION QUESTION www2.example.com. IN A SECTION ANSWER -www2.example.com. 10 IN A 1.2.3.5 +www2.example.com. 100 IN A 1.2.3.5 ENTRY_END ; www.example.com and www2.example.com are in cache, www2 in cachedb. @@ -217,7 +222,7 @@ STEP 40 FLUSH_MESSAGE www2.example.com. IN A ; response from cachedb for www2. ; make 2 seconds pass to decrement the TTL on the response, -; the upstream TTL would be 10, cachedb 8. +; the upstream TTL would be 200, cachedb 198. STEP 48 TIME_PASSES ELAPSE 2 STEP 50 QUERY @@ -234,11 +239,11 @@ REPLY QR RD RA NOERROR SECTION QUESTION www2.example.com. IN A SECTION ANSWER -www2.example.com. 8 IN A 1.2.3.5 +www2.example.com. 98 IN A 1.2.3.5 ENTRY_END ; make both cache and cachedb expired -STEP 70 TIME_PASSES ELAPSE 20 +STEP 70 TIME_PASSES ELAPSE 200 ; www and www2 expired in cache, www2 expired in cachedb. ; the query should now try to resolve and complete within the @@ -258,11 +263,11 @@ REPLY QR RD RA NOERROR SECTION QUESTION www2.example.com. IN A SECTION ANSWER -www2.example.com. 10 IN A 1.2.3.7 +www2.example.com. 100 IN A 1.2.3.7 ENTRY_END ; expire the data again -STEP 100 TIME_PASSES ELAPSE 20 +STEP 100 TIME_PASSES ELAPSE 200 ; the query should now try to resolve, but the upstream is not ; responsive for several testbound steps. When the timer expires, @@ -271,7 +276,7 @@ STEP 100 TIME_PASSES ELAPSE 20 ; www2 expired in cache and www2 expired in cachedb. STEP 110 QUERY ENTRY_BEGIN -REPLY RD +REPLY RD DO SECTION QUESTION www2.example.com. IN A ENTRY_END @@ -281,26 +286,26 @@ STEP 112 TIME_PASSES ELAPSE 2 STEP 120 CHECK_ANSWER ENTRY_BEGIN -MATCH all ttl -REPLY QR RD RA NOERROR +MATCH all ttl ede=3 +REPLY QR RD RA DO NOERROR SECTION QUESTION www2.example.com. IN A SECTION ANSWER -www2.example.com. 30 IN A 1.2.3.7 +www2.example.com. 100 IN A 1.2.3.7 ENTRY_END ; make traffic flow to resolve the query, server responds. STEP 130 TRAFFIC ; expire the data again -STEP 140 TIME_PASSES ELAPSE 20 +STEP 140 TIME_PASSES ELAPSE 200 ; The client query tries to resolve, but gets no immediate answer, ; so the expired data is used. But the expired data is in cache and ; the query is not in cachedb. STEP 150 QUERY ENTRY_BEGIN -REPLY RD +REPLY RD DO SECTION QUESTION www.example.com. IN A ENTRY_END @@ -310,12 +315,12 @@ STEP 152 TIME_PASSES ELAPSE 2 STEP 160 CHECK_ANSWER ENTRY_BEGIN -MATCH all ttl -REPLY QR RD RA NOERROR +MATCH all ttl ede=3 +REPLY QR RD RA DO NOERROR SECTION QUESTION www.example.com. IN A SECTION ANSWER -www.example.com. 30 IN A 1.2.3.4 +www.example.com. 123 IN A 1.2.3.4 ENTRY_END ; make traffic flow to resolve the query, server responds. @@ -337,7 +342,7 @@ REPLY QR RD RA NOERROR SECTION QUESTION www2.example.com. IN A SECTION ANSWER -www2.example.com. 10 IN A 1.2.3.11 +www2.example.com. 100 IN A 1.2.3.11 ENTRY_END SCENARIO_END diff --git a/testdata/cachedb_expired_reply_ttl.crpl b/testdata/cachedb_expired_reply_ttl.crpl index 03fd01add..b8adbe738 100644 --- a/testdata/cachedb_expired_reply_ttl.crpl +++ b/testdata/cachedb_expired_reply_ttl.crpl @@ -5,8 +5,10 @@ server: minimal-responses: no serve-expired: yes serve-expired-client-timeout: 0 - serve-expired-reply-ttl: 30 + serve-expired-reply-ttl: 123 module-config: "cachedb iterator" + ede: yes + ede-serve-expired: yes cachedb: backend: "testframe" @@ -83,7 +85,7 @@ REPLY QR AA NOERROR SECTION QUESTION www.example.com. IN A SECTION ANSWER -www.example.com. 10 IN A 1.2.3.4 +www.example.com. 200 IN A 1.2.3.4 ENTRY_END ENTRY_BEGIN @@ -92,7 +94,8 @@ REPLY QR AA NOERROR SECTION QUESTION www2.example.com. IN A SECTION ANSWER -www2.example.com. 10 IN A 1.2.3.5 +; TTL lower than serve-expired-reply-ttl on purpose +www2.example.com. 100 IN A 1.2.3.5 ENTRY_END RANGE_END @@ -115,7 +118,7 @@ REPLY QR RD RA NOERROR SECTION QUESTION www.example.com. IN A SECTION ANSWER -www.example.com. 10 IN A 1.2.3.4 +www.example.com. 200 IN A 1.2.3.4 ENTRY_END ; Get another query in cache to make it expired. @@ -134,28 +137,28 @@ REPLY QR RD RA NOERROR SECTION QUESTION www2.example.com. IN A SECTION ANSWER -www2.example.com. 10 IN A 1.2.3.5 +www2.example.com. 100 IN A 1.2.3.5 ENTRY_END ; it is now expired -STEP 40 TIME_PASSES ELAPSE 20 +STEP 40 TIME_PASSES ELAPSE 200 ; cache is expired, and cachedb is expired. STEP 50 QUERY ENTRY_BEGIN -REPLY RD +REPLY RD DO SECTION QUESTION www2.example.com. IN A ENTRY_END STEP 60 CHECK_ANSWER ENTRY_BEGIN -MATCH all ttl -REPLY QR RD RA NOERROR +MATCH all ttl ede=3 +REPLY QR RD RA DO NOERROR SECTION QUESTION www2.example.com. IN A SECTION ANSWER -www2.example.com. 30 IN A 1.2.3.5 +www2.example.com. 100 IN A 1.2.3.5 ENTRY_END ; got an answer from upstream @@ -173,25 +176,25 @@ REPLY QR RD RA NOERROR SECTION QUESTION www2.example.com. IN A SECTION ANSWER -www2.example.com. 10 IN A 1.2.3.5 +www2.example.com. 100 IN A 1.2.3.5 ENTRY_END ; cache is expired, cachedb has no answer STEP 70 QUERY ENTRY_BEGIN -REPLY RD +REPLY RD DO SECTION QUESTION www.example.com. IN A ENTRY_END STEP 80 CHECK_ANSWER ENTRY_BEGIN -MATCH all ttl -REPLY QR RD RA NOERROR +MATCH all ttl ede=3 +REPLY QR RD RA DO NOERROR SECTION QUESTION www.example.com. IN A SECTION ANSWER -www.example.com. 30 IN A 1.2.3.4 +www.example.com. 123 IN A 1.2.3.4 ENTRY_END STEP 90 TRAFFIC @@ -211,29 +214,29 @@ REPLY QR RD RA NOERROR SECTION QUESTION www.example.com. IN A SECTION ANSWER -www.example.com. 10 IN A 1.2.3.4 +www.example.com. 200 IN A 1.2.3.4 ENTRY_END ; make both cache and cachedb expired. -STEP 120 TIME_PASSES ELAPSE 20 +STEP 120 TIME_PASSES ELAPSE 200 STEP 130 FLUSH_MESSAGE www.example.com. IN A ; cache has no entry and cachedb is expired. STEP 140 QUERY ENTRY_BEGIN -REPLY RD +REPLY RD DO SECTION QUESTION www.example.com. IN A ENTRY_END STEP 150 CHECK_ANSWER ENTRY_BEGIN -MATCH all ttl -REPLY QR RD RA NOERROR +MATCH all ttl ede=3 +REPLY QR RD RA DO NOERROR SECTION QUESTION www.example.com. IN A SECTION ANSWER -www.example.com. 30 IN A 1.2.3.4 +www.example.com. 123 IN A 1.2.3.4 ENTRY_END ; the name is resolved @@ -254,7 +257,7 @@ REPLY QR RD RA NOERROR SECTION QUESTION www.example.com. IN A SECTION ANSWER -www.example.com. 10 IN A 1.2.3.4 +www.example.com. 200 IN A 1.2.3.4 ENTRY_END SCENARIO_END diff --git a/testdata/cachedb_subnet_change.crpl b/testdata/cachedb_subnet_change.crpl index 73584305c..87903132c 100644 --- a/testdata/cachedb_subnet_change.crpl +++ b/testdata/cachedb_subnet_change.crpl @@ -4,7 +4,7 @@ server: qname-minimisation: no minimal-responses: no serve-expired: yes - serve-expired-reply-ttl: 30 + serve-expired-reply-ttl: 123 ; disable the serve expired client timeout. serve-expired-client-timeout: 0 @@ -14,6 +14,8 @@ server: ; store for edns subnet content for modules to the right of it. ; this keeps subnet content out of cachedb as global content. module-config: "subnetcache cachedb iterator" + ede: yes + ede-serve-expired: yes cachedb: backend: "testframe" @@ -105,7 +107,7 @@ REPLY QR AA NOERROR SECTION QUESTION www.example.com. IN A SECTION ANSWER -www.example.com. 10 IN CNAME www.initial.com. +www.example.com. 200 IN CNAME www.initial.com. ENTRY_END RANGE_END @@ -118,7 +120,7 @@ REPLY QR AA NOERROR SECTION QUESTION www.example.com. IN A SECTION ANSWER -www.example.com. 10 IN CNAME example.foo.com. +www.example.com. 200 IN CNAME example.foo.com. ENTRY_END RANGE_END @@ -131,7 +133,7 @@ REPLY QR AA NOERROR SECTION QUESTION www.initial.com. IN A SECTION ANSWER -www.initial.com. 10 IN A 1.2.3.4 +www.initial.com. 200 IN A 1.2.3.4 ENTRY_END RANGE_END @@ -144,7 +146,7 @@ REPLY QR AA NOERROR SECTION QUESTION example.foo.com. IN A SECTION ANSWER -example.foo.com. 10 IN A 1.2.3.5 +example.foo.com. 200 IN A 1.2.3.5 SECTION ADDITIONAL HEX_EDNSDATA_BEGIN ; client is 127.0.0.1 @@ -166,7 +168,7 @@ REPLY QR AA NOERROR SECTION QUESTION www.example.com. IN A SECTION ANSWER -www.example.com. 10 IN CNAME example.foo.com. +www.example.com. 200 IN CNAME example.foo.com. ENTRY_END RANGE_END @@ -179,7 +181,7 @@ REPLY QR AA NOERROR SECTION QUESTION example.foo.com. IN A SECTION ANSWER -example.foo.com. 10 IN A 1.2.3.6 +example.foo.com. 200 IN A 1.2.3.6 SECTION ADDITIONAL HEX_EDNSDATA_BEGIN ; client is 127.0.0.1 @@ -211,19 +213,19 @@ REPLY QR RD RA NOERROR SECTION QUESTION www.example.com. IN A SECTION ANSWER -www.example.com. 10 IN CNAME www.initial.com. -www.initial.com. 10 IN A 1.2.3.4 +www.example.com. 200 IN CNAME www.initial.com. +www.initial.com. 200 IN A 1.2.3.4 ENTRY_END ; now valid in cache and valid in cachedb, without subnet. -STEP 30 TIME_PASSES ELAPSE 20 +STEP 30 TIME_PASSES ELAPSE 200 ; now the cache and cachedb have an expired entry. ; the upstream is updated to CNAME to a subnet zone A record. STEP 40 QUERY ADDRESS 127.0.0.1 ENTRY_BEGIN -REPLY RD +REPLY RD DO SECTION QUESTION www.example.com. IN A ENTRY_END @@ -231,13 +233,13 @@ ENTRY_END ; the expired answer, while the ECS answer is looked up. STEP 50 CHECK_ANSWER ENTRY_BEGIN -MATCH all ttl -REPLY QR RD RA NOERROR +MATCH all ttl ede=3 +REPLY QR RD RA DO NOERROR SECTION QUESTION www.example.com. IN A SECTION ANSWER -www.example.com. 30 IN CNAME www.initial.com. -www.initial.com. 30 IN A 1.2.3.4 +www.example.com. 123 IN CNAME www.initial.com. +www.initial.com. 123 IN A 1.2.3.4 ENTRY_END ; check that subnet has the query in cache. @@ -256,12 +258,12 @@ REPLY QR RD RA NOERROR SECTION QUESTION www.example.com. IN A SECTION ANSWER -www.example.com. 8 IN CNAME example.foo.com. -example.foo.com. 8 IN A 1.2.3.5 +www.example.com. 198 IN CNAME example.foo.com. +example.foo.com. 198 IN A 1.2.3.5 ENTRY_END ; everything is expired, cache, subnetcache and cachedb. -STEP 80 TIME_PASSES ELAPSE 20 +STEP 80 TIME_PASSES ELAPSE 200 STEP 90 QUERY ADDRESS 127.0.0.1 ENTRY_BEGIN @@ -277,8 +279,8 @@ REPLY QR RD RA NOERROR SECTION QUESTION www.example.com. IN A SECTION ANSWER -www.example.com. 10 IN CNAME example.foo.com. -example.foo.com. 10 IN A 1.2.3.6 +www.example.com. 200 IN CNAME example.foo.com. +example.foo.com. 200 IN A 1.2.3.6 ENTRY_END ; see the entry now in cache, from the subnetcache. @@ -297,8 +299,8 @@ REPLY QR RD RA NOERROR SECTION QUESTION www.example.com. IN A SECTION ANSWER -www.example.com. 8 IN CNAME example.foo.com. -example.foo.com. 8 IN A 1.2.3.6 +www.example.com. 198 IN CNAME example.foo.com. +example.foo.com. 198 IN A 1.2.3.6 ENTRY_END SCENARIO_END diff --git a/testdata/cachedb_val_expired.crpl b/testdata/cachedb_val_expired.crpl index 741445ce8..aa98b5fe6 100644 --- a/testdata/cachedb_val_expired.crpl +++ b/testdata/cachedb_val_expired.crpl @@ -5,8 +5,11 @@ server: minimal-responses: yes serve-expired: yes serve-expired-client-timeout: 0 + serve-expired-reply-ttl: 123 ;module-config: "subnetcache validator cachedb iterator" module-config: "validator cachedb iterator" + ede: yes + ede-serve-expired: yes cachedb: backend: "testframe" @@ -83,7 +86,7 @@ REPLY QR AA NOERROR SECTION QUESTION www.example.com. IN A SECTION ANSWER -www.example.com. 10 IN A 1.2.3.4 +www.example.com. 200 IN A 1.2.3.4 ENTRY_END ENTRY_BEGIN @@ -92,7 +95,8 @@ REPLY QR AA NOERROR SECTION QUESTION www2.example.com. IN A SECTION ANSWER -www2.example.com. 10 IN A 1.2.3.5 +; TTL lower than serve-expired-reply-ttl on purpose +www2.example.com. 100 IN A 1.2.3.5 ENTRY_END RANGE_END @@ -112,7 +116,7 @@ REPLY QR RD RA NOERROR SECTION QUESTION www.example.com. IN A SECTION ANSWER -www.example.com. 10 IN A 1.2.3.4 +www.example.com. 200 IN A 1.2.3.4 ENTRY_END ; Get another query in cache to make it expired. @@ -131,48 +135,48 @@ REPLY QR RD RA NOERROR SECTION QUESTION www2.example.com. IN A SECTION ANSWER -www2.example.com. 10 IN A 1.2.3.5 +www2.example.com. 100 IN A 1.2.3.5 ENTRY_END ; it is now expired -STEP 40 TIME_PASSES ELAPSE 20 +STEP 40 TIME_PASSES ELAPSE 200 ; cache is expired, and cachedb is expired. ; The expired reply, from cachedb, needs a validation status, ; because the validator module set that validation is needed. STEP 50 QUERY ENTRY_BEGIN -REPLY RD +REPLY RD DO SECTION QUESTION www2.example.com. IN A ENTRY_END STEP 60 CHECK_ANSWER ENTRY_BEGIN -MATCH all ttl -REPLY QR RD RA NOERROR +MATCH all ttl ede=3 +REPLY QR RD RA DO NOERROR SECTION QUESTION www2.example.com. IN A SECTION ANSWER -www2.example.com. 30 IN A 1.2.3.5 +www2.example.com. 100 IN A 1.2.3.5 ENTRY_END ; cache is expired, cachedb has no answer STEP 70 QUERY ENTRY_BEGIN -REPLY RD +REPLY RD DO SECTION QUESTION www.example.com. IN A ENTRY_END STEP 80 CHECK_ANSWER ENTRY_BEGIN -MATCH all ttl -REPLY QR RD RA NOERROR +MATCH all ttl ede=3 +REPLY QR RD RA DO NOERROR SECTION QUESTION www.example.com. IN A SECTION ANSWER -www.example.com. 30 IN A 1.2.3.4 +www.example.com. 123 IN A 1.2.3.4 ENTRY_END STEP 90 TRAFFIC @@ -192,7 +196,7 @@ REPLY QR RD RA NOERROR SECTION QUESTION www.example.com. IN A SECTION ANSWER -www.example.com. 10 IN A 1.2.3.4 +www.example.com. 200 IN A 1.2.3.4 ENTRY_END ; flush the entry from cache @@ -213,30 +217,30 @@ REPLY QR RD RA NOERROR SECTION QUESTION www.example.com. IN A SECTION ANSWER -www.example.com. 10 IN A 1.2.3.4 +www.example.com. 200 IN A 1.2.3.4 ENTRY_END ; it is now expired -STEP 150 TIME_PASSES ELAPSE 20 +STEP 150 TIME_PASSES ELAPSE 200 ; flush the entry from cache STEP 160 FLUSH_MESSAGE www.example.com. IN A ; cache has no answer, cachedb is expired STEP 170 QUERY ENTRY_BEGIN -REPLY RD +REPLY RD DO SECTION QUESTION www.example.com. IN A ENTRY_END STEP 180 CHECK_ANSWER ENTRY_BEGIN -MATCH all ttl -REPLY QR RD RA NOERROR +MATCH all ttl ede=3 +REPLY QR RD RA DO NOERROR SECTION QUESTION www.example.com. IN A SECTION ANSWER -www.example.com. 30 IN A 1.2.3.4 +www.example.com. 123 IN A 1.2.3.4 ENTRY_END STEP 190 TRAFFIC @@ -257,7 +261,7 @@ REPLY QR RD RA NOERROR SECTION QUESTION www.example.com. IN A SECTION ANSWER -www.example.com. 10 IN A 1.2.3.4 +www.example.com. 200 IN A 1.2.3.4 ENTRY_END ; expire the entry in cache @@ -278,30 +282,30 @@ REPLY QR RD RA NOERROR SECTION QUESTION www.example.com. IN A SECTION ANSWER -www.example.com. 10 IN A 1.2.3.4 +www.example.com. 200 IN A 1.2.3.4 ENTRY_END ; it is now expired -STEP 250 TIME_PASSES ELAPSE 20 +STEP 250 TIME_PASSES ELAPSE 200 ; expire the entry in cache STEP 260 EXPIRE_MESSAGE www.example.com. IN A ; cache is expired, cachedb is expired STEP 270 QUERY ENTRY_BEGIN -REPLY RD +REPLY RD DO SECTION QUESTION www.example.com. IN A ENTRY_END STEP 280 CHECK_ANSWER ENTRY_BEGIN -MATCH all ttl -REPLY QR RD RA NOERROR +MATCH all ttl ede=3 +REPLY QR RD RA DO NOERROR SECTION QUESTION www.example.com. IN A SECTION ANSWER -www.example.com. 30 IN A 1.2.3.4 +www.example.com. 123 IN A 1.2.3.4 ENTRY_END STEP 290 TRAFFIC @@ -322,7 +326,7 @@ REPLY QR RD RA NOERROR SECTION QUESTION www.example.com. IN A SECTION ANSWER -www.example.com. 10 IN A 1.2.3.4 +www.example.com. 200 IN A 1.2.3.4 ENTRY_END SCENARIO_END diff --git a/testdata/fwd_0ttlservfail.rpl b/testdata/fwd_0ttlservfail.rpl index d50d386d4..635ee6db6 100644 --- a/testdata/fwd_0ttlservfail.rpl +++ b/testdata/fwd_0ttlservfail.rpl @@ -46,25 +46,10 @@ www.example.com. IN A SECTION ANSWER ENTRY_END -; enough to pass by the TTL of the servfail answer in cache +; enough to expire the servfail answer in cache STEP 50 TIME_PASSES ELAPSE 5 -; this query triggers a prefetch -STEP 210 QUERY -ENTRY_BEGIN -REPLY RD -SECTION QUESTION -www.example.com. IN A -ENTRY_END - -STEP 220 CHECK_ANSWER -ENTRY_BEGIN -MATCH all -REPLY QR RD RA SERVFAIL -SECTION QUESTION -www.example.com. IN A -SECTION ANSWER -ENTRY_END +; Expired SERVFAILS are no longer served from Unbound ; this query gets the 0ttl answer STEP 230 QUERY @@ -76,7 +61,7 @@ ENTRY_END STEP 240 CHECK_ANSWER ENTRY_BEGIN -MATCH all +MATCH all ttl REPLY QR RD RA NOERROR SECTION QUESTION www.example.com. IN A diff --git a/testdata/respip_dns64_lookup.rpl b/testdata/respip_dns64_lookup.rpl new file mode 100644 index 000000000..df6e56121 --- /dev/null +++ b/testdata/respip_dns64_lookup.rpl @@ -0,0 +1,522 @@ +; config options +server: + target-fetch-policy: "0 0 0 0 0" + qname-minimisation: no + minimal-responses: yes + ; respip is before dns64 in the module list. + module-config: "respip dns64 validator iterator" + dns64-prefix: 64:ff9b::0/96 + response-ip: 10.20.30.42/32 always_refuse + response-ip: 10.20.30.43/32 redirect + response-ip-data: 10.20.30.43/32 "A 4.5.6.3" + response-ip: 5.6.7.9/32 redirect + response-ip-data: 5.6.7.9/32 "A 4.5.6.7" + response-ip: 5.6.7.10/32 always_nxdomain + response-ip: 64:ff9b::506:70B/128 redirect + response-ip-data: 64:ff9b::506:70B/128 "AAAA 2001:db8::4" + +rpz: + name: "rpz.example.com." + rpz-log: yes + zonefile: +TEMPFILE_NAME rpz.example.com +TEMPFILE_CONTENTS rpz.example.com +$ORIGIN example.com. +rpz 3600 IN SOA ns1.rpz.example.com. hostmaster.rpz.example.com. ( + 1379078166 28800 7200 604800 7200 ) + 3600 IN NS ns1.rpz.example.com. + 3600 IN NS ns2.rpz.example.com. +$ORIGIN rpz.example.com. +32.44.30.20.10.rpz-ip CNAME . +32.12.7.6.5.rpz-ip CNAME . +32.13.7.6.5.rpz-ip A 4.5.6.13 +32.14.7.6.5.rpz-ip CNAME alias.example.com. +TEMPFILE_END + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test respip and dns64 lookup. + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 1000 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. 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. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 1000 + 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. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. 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 + +; ns.example.com. +RANGE_BEGIN 0 1000 + 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 +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www2.example.com. IN A +SECTION ANSWER +www2.example.com. IN A 10.20.30.42 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www3.example.com. IN A +SECTION ANSWER +www3.example.com. IN A 10.20.30.43 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www4.example.com. IN A +SECTION ANSWER +www4.example.com. IN A 10.20.30.44 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ip4.example.com. IN AAAA +SECTION ANSWER +; NO AAAA present +SECTION AUTHORITY +example.com. IN SOA a. b. 1 2 3 4 5 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ip4.example.com. IN A +SECTION ANSWER +ip4.example.com. IN A 5.6.7.8 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ip4-2.example.com. IN AAAA +SECTION ANSWER +; NO AAAA present +SECTION AUTHORITY +example.com. IN SOA a. b. 1 2 3 4 5 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ip4-2.example.com. IN A +SECTION ANSWER +ip4-2.example.com. IN A 5.6.7.9 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ip4-3.example.com. IN AAAA +SECTION ANSWER +; NO AAAA present +SECTION AUTHORITY +example.com. IN SOA a. b. 1 2 3 4 5 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ip4-3.example.com. IN A +SECTION ANSWER +ip4-3.example.com. IN A 5.6.7.10 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ip4-4.example.com. IN AAAA +SECTION ANSWER +; NO AAAA present +SECTION AUTHORITY +example.com. IN SOA a. b. 1 2 3 4 5 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ip4-4.example.com. IN A +SECTION ANSWER +ip4-4.example.com. IN A 5.6.7.11 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ip4-5.example.com. IN AAAA +SECTION ANSWER +; NO AAAA present +SECTION AUTHORITY +example.com. IN SOA a. b. 1 2 3 4 5 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ip4-5.example.com. IN A +SECTION ANSWER +ip4-5.example.com. IN A 5.6.7.12 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ip4-6.example.com. IN AAAA +SECTION ANSWER +; NO AAAA present +SECTION AUTHORITY +example.com. IN SOA a. b. 1 2 3 4 5 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ip4-6.example.com. IN A +SECTION ANSWER +ip4-6.example.com. IN A 5.6.7.13 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ip4-7.example.com. IN AAAA +SECTION ANSWER +; NO AAAA present +SECTION AUTHORITY +example.com. IN SOA a. b. 1 2 3 4 5 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ip4-7.example.com. IN A +SECTION ANSWER +ip4-7.example.com. IN A 5.6.7.14 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +alias.example.com. IN A +SECTION ANSWER +alias.example.com. IN A 4.5.6.14 +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +; The query is unaltered. +STEP 10 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 +ENTRY_END + +STEP 20 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www2.example.com. IN A +ENTRY_END + +; The query is altered by respip, A query refused. +STEP 30 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA REFUSED +SECTION QUESTION +www2.example.com. IN A +SECTION ANSWER +ENTRY_END + +STEP 40 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www3.example.com. IN A +ENTRY_END + +; The query is altered by respip, with redirect. +STEP 50 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +www3.example.com. IN A +SECTION ANSWER +www3.example.com. IN A 4.5.6.3 +ENTRY_END + +STEP 60 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +ip4.example.com. IN AAAA +ENTRY_END + +; synthesize from A record 5.6.7.8 with DNS64. +STEP 70 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +ip4.example.com. IN AAAA +SECTION ANSWER +ip4.example.com. IN AAAA 64:ff9b::506:708 +ENTRY_END + +STEP 80 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +ip4-2.example.com. IN AAAA +ENTRY_END + +; The dns64 subquery is altered by respip, with redirect. +; and the respip result is dns64 synthesized. +STEP 90 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +ip4-2.example.com. IN AAAA +SECTION ANSWER +ip4-2.example.com. IN AAAA 64:ff9b::405:607 +ENTRY_END + +STEP 100 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +ip4-3.example.com. IN AAAA +ENTRY_END + +; The dns64 subquery is altered by respip, with nxdomain. +; and the respip result is dns64 synthesized. +STEP 110 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +ip4-3.example.com. IN AAAA +SECTION ANSWER +SECTION AUTHORITY +example.com. IN SOA a. b. 1 2 3 4 5 +ENTRY_END + +STEP 120 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +ip4-4.example.com. IN AAAA +ENTRY_END + +; The dns64 subquery is synthesized, respip operates on the +; synthesized AAAA result, and makes a redirect. +STEP 130 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +ip4-4.example.com. IN AAAA +SECTION ANSWER +ip4-4.example.com. IN AAAA 2001:db8::4 +ENTRY_END + +STEP 140 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www4.example.com. IN A +ENTRY_END + +; The query is blocked by rpz. +STEP 150 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NXDOMAIN +SECTION QUESTION +www4.example.com. IN A +SECTION ANSWER +ENTRY_END + +STEP 160 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +ip4-5.example.com. IN AAAA +ENTRY_END + +; The dns64 subquery is blocked by RPZ. +STEP 170 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +ip4-5.example.com. IN AAAA +SECTION ANSWER +SECTION AUTHORITY +example.com. IN SOA a. b. 1 2 3 4 5 +ENTRY_END + +STEP 180 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +ip4-6.example.com. IN AAAA +ENTRY_END + +; The dns64 subquery is redirected by RPZ. +STEP 190 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +ip4-6.example.com. IN AAAA +SECTION ANSWER +ip4-6.example.com. AAAA 64:ff9b::405:60d +ENTRY_END + +STEP 200 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +ip4-7.example.com. IN AAAA +ENTRY_END + +; The dns64 subquery is a CNAME by RPZ. +; that CNAME resolves to an A record, dns64 synthesizes that A record. +STEP 210 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +ip4-7.example.com. IN AAAA +SECTION ANSWER +ip4-7.example.com. CNAME alias.example.com. +alias.example.com. AAAA 64:ff9b::405:60e +ENTRY_END + +SCENARIO_END diff --git a/testdata/rrset_use_cached.rpl b/testdata/rrset_use_cached.rpl index 8420ae02a..7af5c85d2 100644 --- a/testdata/rrset_use_cached.rpl +++ b/testdata/rrset_use_cached.rpl @@ -5,8 +5,11 @@ server: # We do not want only serve-expired because fetches from that # apply a generous PREFETCH_LEEWAY. serve-expired-client-timeout: 1000 + serve-expired-reply-ttl: 123 # So that we can only have to give one SERVFAIL answer. outbound-msg-retry: 0 + ede: yes + ede-serve-expired: yes forward-zone: name: "." forward-addr: 216.0.0.1 CONFIG_END @@ -35,11 +38,11 @@ ENTRY_BEGIN SECTION QUESTION www.example.com. IN A SECTION ANSWER - www.example.com. 5 IN A 10.20.30.40 + www.example.com. 205 IN A 10.20.30.40 SECTION AUTHORITY - example.com. 10 IN NS ns.example.com. + example.com. 210 IN NS ns.example.com. SECTION ADDITIONAL - ns.example.com. 10 IN A 10.20.30.50 + ns.example.com. 210 IN A 10.20.30.50 ENTRY_END STEP 4 CHECK_ANSWER ENTRY_BEGIN @@ -48,15 +51,15 @@ ENTRY_BEGIN SECTION QUESTION www.example.com. IN A SECTION ANSWER - www.example.com. 5 IN A 10.20.30.40 + www.example.com. 205 IN A 10.20.30.40 SECTION AUTHORITY - example.com. 10 IN NS ns.example.com. + example.com. 210 IN NS ns.example.com. SECTION ADDITIONAL - ns.example.com. 10 IN A 10.20.30.50 + ns.example.com. 210 IN A 10.20.30.50 ENTRY_END ; Wait for the A RRSET to expire. -STEP 5 TIME_PASSES ELAPSE 6 +STEP 5 TIME_PASSES ELAPSE 205 STEP 6 QUERY ENTRY_BEGIN @@ -80,14 +83,14 @@ ENTRY_BEGIN SECTION QUESTION www.example.com. IN A SECTION ANSWER - www.example.com. 5 IN A 10.20.30.40 + www.example.com. 205 IN A 10.20.30.40 SECTION AUTHORITY - example.com. 10 IN NS ns.example.com. + example.com. 210 IN NS ns.example.com. SECTION ADDITIONAL - ns.example.com. 10 IN A 10.20.30.50 + ns.example.com. 210 IN A 10.20.30.50 ENTRY_END ; The cached NS related RRSETs will not be overwritten by the fresh answer. -; The message should have a TTL of 4 instead of 5 from above. +; The message should have a TTL of 5 instead of 205 from above. STEP 9 CHECK_ANSWER ENTRY_BEGIN MATCH all ttl @@ -95,11 +98,11 @@ ENTRY_BEGIN SECTION QUESTION www.example.com. IN A SECTION ANSWER - www.example.com. 5 IN A 10.20.30.40 + www.example.com. 205 IN A 10.20.30.40 SECTION AUTHORITY - example.com. 4 IN NS ns.example.com. + example.com. 5 IN NS ns.example.com. SECTION ADDITIONAL - ns.example.com. 4 IN A 10.20.30.50 + ns.example.com. 5 IN A 10.20.30.50 ENTRY_END ; Wait for the NS RRSETs to expire. @@ -107,7 +110,7 @@ STEP 10 TIME_PASSES ELAPSE 5 STEP 11 QUERY ENTRY_BEGIN - REPLY RD + REPLY RD DO SECTION QUESTION www.example.com. IN A ENTRY_END @@ -129,23 +132,23 @@ ENTRY_BEGIN ENTRY_END ; The SERVFAIL will trigger the serve-expired-client-timeout logic to try and ; replace the SERVFAIL with a possible cached (expired) answer. -; The A RRSET would be at 0TTL left (not expired) but the message should have -; been updated to use a TTL of 4 so expired by now. +; The A RRSET would be at 200 left but the message should have +; been updated to use a TTL of 5 so expired by now. ; If the message TTL was not updated (bug), this message would be treated as ; non-expired and the now expired NS related RRSETs would fail sanity checks ; for non-expired messages. The result would be SERVFAIL here. STEP 14 CHECK_ANSWER ENTRY_BEGIN - MATCH all ttl - REPLY QR RD RA + MATCH all ttl ede=3 + REPLY QR RD RA DO SECTION QUESTION www.example.com. IN A SECTION ANSWER - www.example.com. 0 IN A 10.20.30.40 + www.example.com. 200 IN A 10.20.30.40 SECTION AUTHORITY - example.com. 30 IN NS ns.example.com. + example.com. 123 IN NS ns.example.com. SECTION ADDITIONAL - ns.example.com. 30 IN A 10.20.30.50 + ns.example.com. 123 IN A 10.20.30.50 ENTRY_END SCENARIO_END diff --git a/testdata/serve_expired.rpl b/testdata/serve_expired.rpl index 990a562c7..4aa65e167 100644 --- a/testdata/serve_expired.rpl +++ b/testdata/serve_expired.rpl @@ -5,6 +5,7 @@ server: minimal-responses: no serve-expired: yes serve-expired-client-timeout: 0 + serve-expired-reply-ttl: 123 access-control: 127.0.0.1/32 allow_snoop ede: yes ede-serve-expired: yes @@ -44,7 +45,7 @@ RANGE_BEGIN 0 100 SECTION QUESTION example.com. IN A SECTION ANSWER - example.com. 10 IN A 5.6.7.8 + example.com. 200 IN A 5.6.7.8 SECTION AUTHORITY example.com. IN NS ns.example.com. SECTION ADDITIONAL @@ -68,15 +69,15 @@ ENTRY_BEGIN SECTION QUESTION example.com. IN A SECTION ANSWER - example.com. 10 IN A 5.6.7.8 + example.com. 200 IN A 5.6.7.8 SECTION AUTHORITY example.com. IN NS ns.example.com. SECTION ADDITIONAL ns.example.com. IN A 1.2.3.4 ENTRY_END -; Wait for the TTL to expire -STEP 11 TIME_PASSES ELAPSE 3601 +; Wait for the TTL to expire (for all RRSets; default 3600) +STEP 11 TIME_PASSES ELAPSE 3600 ; Query again without RD bit STEP 30 QUERY @@ -94,11 +95,11 @@ ENTRY_BEGIN SECTION QUESTION example.com. IN A SECTION ANSWER - example.com. 30 IN A 5.6.7.8 + example.com. 123 IN A 5.6.7.8 SECTION AUTHORITY - example.com. 30 IN NS ns.example.com. + example.com. 123 IN NS ns.example.com. SECTION ADDITIONAL - ns.example.com. 30 IN A 1.2.3.4 + ns.example.com. 123 IN A 1.2.3.4 ENTRY_END ; Query with RD bit (the record should have been prefetched) @@ -116,7 +117,7 @@ ENTRY_BEGIN SECTION QUESTION example.com. IN A SECTION ANSWER - example.com. 10 IN A 5.6.7.8 + example.com. 200 IN A 5.6.7.8 SECTION AUTHORITY example.com. IN NS ns.example.com. SECTION ADDITIONAL diff --git a/testdata/serve_expired_0ttl_nodata.rpl b/testdata/serve_expired_0ttl_nodata.rpl index 8ca461be2..a53df437a 100644 --- a/testdata/serve_expired_0ttl_nodata.rpl +++ b/testdata/serve_expired_0ttl_nodata.rpl @@ -5,6 +5,7 @@ server: minimal-responses: no serve-expired: yes serve-expired-client-timeout: 0 + serve-expired-reply-ttl: 123 ede: yes ede-serve-expired: yes @@ -48,9 +49,9 @@ RANGE_BEGIN 30 100 SECTION QUESTION example.com. IN NS SECTION ANSWER - example.com. 10 IN NS ns.example.com. + example.com. 200 IN NS ns.example.com. SECTION ADDITIONAL - ns.example.com. 10 IN A 1.2.3.4 + ns.example.com. 200 IN A 1.2.3.4 ENTRY_END ENTRY_BEGIN @@ -62,9 +63,9 @@ RANGE_BEGIN 30 100 SECTION ANSWER 0ttl.example.com. 0 IN A 5.6.7.8 SECTION AUTHORITY - example.com. 10 IN NS ns.example.com. + example.com. 200 IN NS ns.example.com. SECTION ADDITIONAL - ns.example.com. 10 IN A 1.2.3.4 + ns.example.com. 200 IN A 1.2.3.4 ENTRY_END RANGE_END @@ -106,13 +107,13 @@ ENTRY_BEGIN example.com IN SOA ns.example.com dns.example.com 1 7200 3600 2419200 10 ENTRY_END -; Wait for the NXDOMAIN to expire -STEP 31 TIME_PASSES ELAPSE 32 +; Wait for the NODATA to expire +STEP 31 TIME_PASSES ELAPSE 10 ; Query again STEP 40 QUERY ENTRY_BEGIN - REPLY RD + REPLY RD DO SECTION QUESTION 0ttl.example.com. IN A ENTRY_END @@ -120,8 +121,8 @@ ENTRY_END ; Check that we get the cached NODATA STEP 50 CHECK_ANSWER ENTRY_BEGIN - MATCH all - REPLY QR RD RA NOERROR + MATCH all ede=3 + REPLY QR RD RA DO NOERROR SECTION QUESTION 0ttl.example.com. IN A SECTION AUTHORITY @@ -146,9 +147,9 @@ ENTRY_BEGIN SECTION ANSWER 0ttl.example.com. 0 IN A 5.6.7.8 SECTION AUTHORITY - example.com. 10 IN NS ns.example.com. + example.com. 200 IN NS ns.example.com. SECTION ADDITIONAL - ns.example.com. 10 IN A 1.2.3.4 + ns.example.com. 200 IN A 1.2.3.4 ENTRY_END SCENARIO_END diff --git a/testdata/serve_expired_0ttl_nxdomain.rpl b/testdata/serve_expired_0ttl_nxdomain.rpl index 7cf26aedd..7dd27b8d5 100644 --- a/testdata/serve_expired_0ttl_nxdomain.rpl +++ b/testdata/serve_expired_0ttl_nxdomain.rpl @@ -107,7 +107,7 @@ ENTRY_BEGIN ENTRY_END ; Wait for the NXDOMAIN to expire -STEP 31 TIME_PASSES ELAPSE 32 +STEP 31 TIME_PASSES ELAPSE 10 ; Query again STEP 40 QUERY @@ -117,7 +117,7 @@ ENTRY_BEGIN 0ttl.example.com. IN A ENTRY_END -; Check that we get the cached NXDOMAIN +; Check that we get the newly cached NXDOMAIN STEP 50 CHECK_ANSWER ENTRY_BEGIN MATCH all diff --git a/testdata/serve_expired_0ttl_servfail.rpl b/testdata/serve_expired_0ttl_servfail.rpl index e9d4c4884..9e5a17a09 100644 --- a/testdata/serve_expired_0ttl_servfail.rpl +++ b/testdata/serve_expired_0ttl_servfail.rpl @@ -101,7 +101,7 @@ ENTRY_BEGIN ENTRY_END ; Wait for the SERVFAIL to expire -STEP 31 TIME_PASSES ELAPSE 32 +STEP 31 TIME_PASSES ELAPSE 10 ; Query again STEP 40 QUERY diff --git a/testdata/serve_expired_client_timeout.rpl b/testdata/serve_expired_client_timeout.rpl index 5560aa05a..c44543692 100644 --- a/testdata/serve_expired_client_timeout.rpl +++ b/testdata/serve_expired_client_timeout.rpl @@ -48,7 +48,7 @@ RANGE_BEGIN 0 20 SECTION QUESTION example.com. IN A SECTION ANSWER - example.com. 10 IN A 5.6.7.8 + example.com. 200 IN A 5.6.7.8 SECTION AUTHORITY example.com. IN NS ns.example.com. SECTION ADDITIONAL @@ -72,7 +72,7 @@ ENTRY_BEGIN SECTION QUESTION example.com. IN A SECTION ANSWER - example.com. 10 IN A 5.6.7.8 + example.com. 200 IN A 5.6.7.8 SECTION AUTHORITY example.com. IN NS ns.example.com. SECTION ADDITIONAL diff --git a/testdata/serve_expired_client_timeout_no_prefetch.rpl b/testdata/serve_expired_client_timeout_no_prefetch.rpl deleted file mode 100644 index aed397d9e..000000000 --- a/testdata/serve_expired_client_timeout_no_prefetch.rpl +++ /dev/null @@ -1,110 +0,0 @@ -; config options -server: - module-config: "validator iterator" - qname-minimisation: "no" - minimal-responses: no - serve-expired: yes - serve-expired-client-timeout: 1 - serve-expired-reply-ttl: 123 - ede: yes - ede-serve-expired: yes - -stub-zone: - name: "example.com" - stub-addr: 1.2.3.4 -CONFIG_END - -SCENARIO_BEGIN Test that no prefetch is triggered for 0TTL records with serve-expired and client-timeout enabled -; Scenario overview: -; - query for example.com. IN A -; - check that we get an answer for example.com. IN A with the correct TTL -; - query again right at the 0TTL cached entry -; - check that we get the cached answer with no prefetching triggered - -; 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 -RANGE_END - -; ns.example.com. -RANGE_BEGIN 0 10 - ADDRESS 1.2.3.4 - ; response to A query - ENTRY_BEGIN - MATCH opcode qtype qname - ADJUST copy_id - REPLY QR NOERROR - SECTION QUESTION - example.com. IN A - SECTION ANSWER - example.com. 10 IN A 5.6.7.8 - SECTION AUTHORITY - example.com. IN NS ns.example.com. - SECTION ADDITIONAL - ns.example.com. IN A 1.2.3.4 - ENTRY_END -RANGE_END - -; Query with RD flag -STEP 0 QUERY -ENTRY_BEGIN - REPLY RD - SECTION QUESTION - example.com. IN A -ENTRY_END - -; Check that we got the correct answer (should be cached) -STEP 1 CHECK_ANSWER -ENTRY_BEGIN - MATCH all ttl - REPLY QR RD RA NOERROR - SECTION QUESTION - example.com. IN A - SECTION ANSWER - example.com. 10 IN A 5.6.7.8 - SECTION AUTHORITY - example.com. IN NS ns.example.com. - SECTION ADDITIONAL - ns.example.com. IN A 1.2.3.4 -ENTRY_END - -; Wait for the TTL to expire and produce a 0 TTL cached record. -STEP 10 TIME_PASSES ELAPSE 10 - -; Query again -STEP 20 QUERY -ENTRY_BEGIN - REPLY RD DO - SECTION QUESTION - example.com. IN A -ENTRY_END - -; This should come from the cache with no prefetch triggered (earlier bug). -STEP 21 CHECK_ANSWER -ENTRY_BEGIN - MATCH all ttl - REPLY QR RD RA DO NOERROR - SECTION QUESTION - example.com. IN A - SECTION ANSWER - example.com. 0 IN A 5.6.7.8 - SECTION AUTHORITY - example.com. 3590 IN NS ns.example.com. - SECTION ADDITIONAL - ns.example.com. 3590 IN A 1.2.3.4 -ENTRY_END - -; If a prefetch triggers the test will fail with 'messages pending'. - -SCENARIO_END diff --git a/testdata/serve_expired_client_timeout_servfail.rpl b/testdata/serve_expired_client_timeout_servfail.rpl index 3c5b35e17..46fe032fb 100644 --- a/testdata/serve_expired_client_timeout_servfail.rpl +++ b/testdata/serve_expired_client_timeout_servfail.rpl @@ -40,9 +40,9 @@ RANGE_BEGIN 0 20 SECTION QUESTION example.com. IN NS SECTION ANSWER - example.com. 10 IN NS ns.example.com. + example.com. 200 IN NS ns.example.com. SECTION ADDITIONAL - ns.example.com. 10 IN A 1.2.3.4 + ns.example.com. 200 IN A 1.2.3.4 ENTRY_END ENTRY_BEGIN @@ -52,11 +52,11 @@ RANGE_BEGIN 0 20 SECTION QUESTION example.com. IN A SECTION ANSWER - example.com. 10 IN A 5.6.7.8 + example.com. 200 IN A 5.6.7.8 SECTION AUTHORITY - example.com. 10 IN NS ns.example.com. + example.com. 200 IN NS ns.example.com. SECTION ADDITIONAL - ns.example.com. 10 IN A 1.2.3.4 + ns.example.com. 200 IN A 1.2.3.4 ENTRY_END RANGE_END @@ -84,11 +84,11 @@ RANGE_BEGIN 50 100 SECTION QUESTION example.com. IN A SECTION ANSWER - example.com. 10 IN A 5.6.7.8 + example.com. 200 IN A 5.6.7.8 SECTION AUTHORITY - example.com. 10 IN NS ns.example.com. + example.com. 200 IN NS ns.example.com. SECTION ADDITIONAL - ns.example.com. 10 IN A 1.2.3.4 + ns.example.com. 200 IN A 1.2.3.4 ENTRY_END RANGE_END @@ -108,15 +108,15 @@ ENTRY_BEGIN SECTION QUESTION example.com. IN A SECTION ANSWER - example.com. 10 IN A 5.6.7.8 + example.com. 200 IN A 5.6.7.8 SECTION AUTHORITY - example.com. 10 IN NS ns.example.com. + example.com. 200 IN NS ns.example.com. SECTION ADDITIONAL - ns.example.com. 10 IN A 1.2.3.4 + ns.example.com. 200 IN A 1.2.3.4 ENTRY_END ; Wait for the TTL to expire -STEP 11 TIME_PASSES ELAPSE 11 +STEP 11 TIME_PASSES ELAPSE 200 ; Query again STEP 30 QUERY @@ -209,11 +209,11 @@ ENTRY_BEGIN SECTION QUESTION example.com. IN A SECTION ANSWER - example.com. 10 IN A 5.6.7.8 + example.com. 200 IN A 5.6.7.8 SECTION AUTHORITY - example.com. 10 IN NS ns.example.com. + example.com. 200 IN NS ns.example.com. SECTION ADDITIONAL - ns.example.com. 10 IN A 1.2.3.4 + ns.example.com. 200 IN A 1.2.3.4 ENTRY_END SCENARIO_END diff --git a/testdata/serve_expired_reply_ttl.rpl b/testdata/serve_expired_reply_ttl.rpl index e76976bde..c7859e00e 100644 --- a/testdata/serve_expired_reply_ttl.rpl +++ b/testdata/serve_expired_reply_ttl.rpl @@ -18,8 +18,11 @@ SCENARIO_BEGIN Test serve-expired with reply-ttl ; Scenario overview: ; - query for example.com. IN A ; - check that we get an answer for example.com. IN A with the correct TTL +; - query for shorterttl.example.com. IN A +; - check that we get an answer for shorterttl.example.com. IN A with the correct TTL ; - query again right after the TTL expired -; - check that we get the expired cached answer with the configured TTL +; - check that we get the expired cached answer for example.com. with the configured TTL +; - check that we get the expired cached answer for shorterttl.example.com. with its own original TTL since it is shorter than the configured one ; ns.example.com. RANGE_BEGIN 0 100 @@ -43,7 +46,21 @@ RANGE_BEGIN 0 100 SECTION QUESTION example.com. IN A SECTION ANSWER - example.com. 10 IN A 5.6.7.8 + example.com. 200 IN A 5.6.7.8 + 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 + shorterttl.example.com. IN A + SECTION ANSWER + shorterttl.example.com. 121 IN A 5.6.7.8 SECTION AUTHORITY example.com. IN NS ns.example.com. SECTION ADDITIONAL @@ -67,15 +84,37 @@ ENTRY_BEGIN SECTION QUESTION example.com. IN A SECTION ANSWER - example.com. 10 IN A 5.6.7.8 + example.com. 200 IN A 5.6.7.8 SECTION AUTHORITY example.com. IN NS ns.example.com. SECTION ADDITIONAL ns.example.com. IN A 1.2.3.4 ENTRY_END -; Wait for the TTL to expire -STEP 11 TIME_PASSES ELAPSE 3601 +STEP 11 QUERY +ENTRY_BEGIN + REPLY RD + SECTION QUESTION + shorterttl.example.com. IN A +ENTRY_END + + +STEP 12 CHECK_ANSWER +ENTRY_BEGIN + MATCH all ttl + REPLY QR RD RA NOERROR + SECTION QUESTION + shorterttl.example.com. IN A + SECTION ANSWER + shorterttl.example.com. 121 IN A 5.6.7.8 + SECTION AUTHORITY + example.com. IN NS ns.example.com. + SECTION ADDITIONAL + ns.example.com. IN A 1.2.3.4 +ENTRY_END + +; Wait for the TTL to expire (for all rrsets; default 3600) +STEP 20 TIME_PASSES ELAPSE 3600 ; Query again STEP 30 QUERY @@ -100,7 +139,31 @@ ENTRY_BEGIN ns.example.com. 123 A 1.2.3.4 ENTRY_END +; Query again for shorter ttl +STEP 50 QUERY +ENTRY_BEGIN + REPLY RD DO + SECTION QUESTION + shorterttl.example.com. IN A +ENTRY_END + +; Check that we got a stale answer +; Note: auth, additional rrsets are already updated from previous recursion. +STEP 60 CHECK_ANSWER +ENTRY_BEGIN + MATCH all ttl ede=3 + REPLY QR RD RA DO NOERROR + SECTION QUESTION + shorterttl.example.com. IN A + SECTION ANSWER + shorterttl.example.com. 121 A 5.6.7.8 + SECTION AUTHORITY + example.com. 3600 NS ns.example.com. + SECTION ADDITIONAL + ns.example.com. 3600 A 1.2.3.4 +ENTRY_END + ; Give time for the pending query to get answered -STEP 41 TRAFFIC +STEP 61 TRAFFIC SCENARIO_END diff --git a/testdata/serve_expired_ttl_client_timeout.rpl b/testdata/serve_expired_ttl_client_timeout.rpl index 169d070ea..d1aef32af 100644 --- a/testdata/serve_expired_ttl_client_timeout.rpl +++ b/testdata/serve_expired_ttl_client_timeout.rpl @@ -78,7 +78,7 @@ ENTRY_BEGIN ENTRY_END ; Wait for the TTL to expire + serve-expired-ttl -STEP 11 TIME_PASSES ELAPSE 3611 +STEP 11 TIME_PASSES ELAPSE 3610 ; Query again STEP 30 QUERY diff --git a/testdata/serve_expired_ttl_reset.rpl b/testdata/serve_expired_ttl_reset.rpl index 9f215c96b..f732fddcf 100644 --- a/testdata/serve_expired_ttl_reset.rpl +++ b/testdata/serve_expired_ttl_reset.rpl @@ -36,7 +36,7 @@ REPLY QR AA NOERROR SECTION QUESTION www.example.com. IN A SECTION ANSWER -www.example.com. 10 IN A 0.0.0.0 +www.example.com. 200 IN A 0.0.0.0 ENTRY_END STEP 3 CHECK_ANSWER @@ -46,11 +46,11 @@ REPLY QR RA RD NOERROR SECTION QUESTION www.example.com. IN A SECTION ANSWER -www.example.com. 10 IN A 0.0.0.0 +www.example.com. 200 IN A 0.0.0.0 ENTRY_END ; Expire the record (+ serve-expired-ttl) -STEP 4 TIME_PASSES ELAPSE 12 +STEP 4 TIME_PASSES ELAPSE 201 STEP 5 QUERY ENTRY_BEGIN diff --git a/testdata/serve_expired_zerottl.rpl b/testdata/serve_expired_zerottl.rpl index 1411cb8e7..50a50bb3b 100644 --- a/testdata/serve_expired_zerottl.rpl +++ b/testdata/serve_expired_zerottl.rpl @@ -65,11 +65,11 @@ RANGE_BEGIN 11 100 SECTION QUESTION example.com. IN A SECTION ANSWER - example.com. 10 IN A 5.6.7.8 + example.com. 200 IN A 5.6.7.8 SECTION AUTHORITY - example.com. 10 IN NS ns.example.com. + example.com. 200 IN NS ns.example.com. SECTION ADDITIONAL - ns.example.com. 10 IN A 1.2.3.4 + ns.example.com. 200 IN A 1.2.3.4 ENTRY_END RANGE_END @@ -118,15 +118,15 @@ ENTRY_BEGIN SECTION QUESTION example.com. IN A SECTION ANSWER - example.com. 10 IN A 5.6.7.8 + example.com. 200 IN A 5.6.7.8 SECTION AUTHORITY - example.com. 10 IN NS ns.example.com. + example.com. 200 IN NS ns.example.com. SECTION ADDITIONAL - ns.example.com. 10 IN A 1.2.3.4 + ns.example.com. 200 IN A 1.2.3.4 ENTRY_END ; Wait for the TTL to expire -STEP 30 TIME_PASSES ELAPSE 11 +STEP 30 TIME_PASSES ELAPSE 200 ; Query with RD flag STEP 40 QUERY diff --git a/testdata/subnet_global_prefetch_always_forward.crpl b/testdata/subnet_global_prefetch_always_forward.crpl index 775474cbc..f2c8bdb60 100644 --- a/testdata/subnet_global_prefetch_always_forward.crpl +++ b/testdata/subnet_global_prefetch_always_forward.crpl @@ -7,12 +7,15 @@ server: target-fetch-policy: "0 0 0 0 0" serve-expired: yes serve-expired-client-timeout: 0 + serve-expired-reply-ttl: 123 client-subnet-always-forward: yes module-config: "subnetcache iterator" verbosity: 3 access-control: 127.0.0.1 allow_snoop qname-minimisation: no minimal-responses: no + ede: yes + ede-serve-expired: yes stub-zone: name: "." @@ -100,7 +103,7 @@ RANGE_BEGIN 0 100 SECTION QUESTION www.example.com. IN A SECTION ANSWER - www.example.com. 10 IN A 10.20.30.40 + www.example.com. 200 IN A 10.20.30.40 SECTION AUTHORITY example.com. IN NS ns.example.com. SECTION ADDITIONAL @@ -131,11 +134,11 @@ ns.example.com. IN A 1.2.3.4 ENTRY_END ; Wait for the TTL to expire -STEP 3 TIME_PASSES ELAPSE 20 +STEP 3 TIME_PASSES ELAPSE 200 STEP 11 QUERY ENTRY_BEGIN -REPLY RD +REPLY RD DO SECTION QUESTION www.example.com. IN A ENTRY_END @@ -143,16 +146,16 @@ ENTRY_END ; This record came from the global cache and a prefetch was triggered STEP 12 CHECK_ANSWER ENTRY_BEGIN -MATCH all ttl -REPLY QR RD RA NOERROR +MATCH all ttl ede=3 +REPLY QR RD RA DO NOERROR SECTION QUESTION www.example.com. IN A SECTION ANSWER -www.example.com. 30 IN A 10.20.30.40 +www.example.com. 123 IN A 10.20.30.40 SECTION AUTHORITY -example.com. 3580 IN NS ns.example.com. +example.com. 3400 IN NS ns.example.com. SECTION ADDITIONAL -ns.example.com. 3580 IN A 1.2.3.4 +ns.example.com. 3400 IN A 1.2.3.4 ENTRY_END STEP 13 CHECK_OUT_QUERY diff --git a/testdata/subnet_global_prefetch_expired.crpl b/testdata/subnet_global_prefetch_expired.crpl index 374bf3e69..a347550ba 100644 --- a/testdata/subnet_global_prefetch_expired.crpl +++ b/testdata/subnet_global_prefetch_expired.crpl @@ -16,7 +16,11 @@ server: serve-expired: yes serve-expired-client-timeout: 0 serve-expired-ttl: 1 - prefetch: yes + serve-expired-client-timeout: 0 + serve-expired-reply-ttl: 123 + #prefetch: yes #not needed, expired answers also trigger refetch + ede: yes + ede-serve-expired: yes stub-zone: name: "." @@ -113,7 +117,7 @@ RANGE_BEGIN 0 10 SECTION QUESTION www.example.com. IN A SECTION ANSWER - www.example.com. 10 IN A 10.20.30.40 + www.example.com. 200 IN A 10.20.30.40 SECTION AUTHORITY example.com. IN NS ns.example.com. SECTION ADDITIONAL @@ -147,7 +151,7 @@ RANGE_BEGIN 11 100 SECTION QUESTION www.example.com. IN A SECTION ANSWER - www.example.com. 10 IN A 10.20.30.40 + www.example.com. 200 IN A 10.20.30.40 SECTION AUTHORITY example.com. IN NS ns.example.com. SECTION ADDITIONAL @@ -178,7 +182,7 @@ REPLY QR RD RA NOERROR SECTION QUESTION www.example.com. IN A SECTION ANSWER -www.example.com. IN A 10.20.30.40 +www.example.com. 200 IN A 10.20.30.40 SECTION AUTHORITY example.com. IN NS ns.example.com. SECTION ADDITIONAL @@ -186,11 +190,11 @@ ns.example.com. IN A 1.2.3.4 ENTRY_END ; Try to trigger a prefetch with expired data -STEP 3 TIME_PASSES ELAPSE 11 +STEP 3 TIME_PASSES ELAPSE 200 STEP 11 QUERY ENTRY_BEGIN -REPLY RD +REPLY RD DO SECTION QUESTION www.example.com. IN A ENTRY_END @@ -198,19 +202,18 @@ ENTRY_END ; This expired record came from the global cache and a prefetch is triggered. STEP 12 CHECK_ANSWER ENTRY_BEGIN -MATCH all ttl -REPLY QR RD RA NOERROR +MATCH all ttl ede=3 +REPLY QR RD RA DO NOERROR SECTION QUESTION www.example.com. IN A SECTION ANSWER -www.example.com. 30 IN A 10.20.30.40 +www.example.com. 123 IN A 10.20.30.40 SECTION AUTHORITY -example.com. 3589 IN NS ns.example.com. +example.com. 3400 IN NS ns.example.com. SECTION ADDITIONAL -ns.example.com. 3589 IN A 1.2.3.4 +ns.example.com. 3400 IN A 1.2.3.4 ENTRY_END -;STEP 13 TRAFFIC ; Allow enough time to pass so that the expired record from the global cache ; cannot be used anymore. STEP 14 TIME_PASSES ELAPSE 1 @@ -232,7 +235,7 @@ REPLY QR RD RA NOERROR SECTION QUESTION www.example.com. IN A SECTION ANSWER -www.example.com. 9 IN A 10.20.30.40 +www.example.com. 199 IN A 10.20.30.40 SECTION AUTHORITY example.com. 3599 IN NS ns.example.com. SECTION ADDITIONAL diff --git a/testdata/ttl_zero_cacherep.rpl b/testdata/ttl_zero_cacherep.rpl new file mode 100644 index 000000000..fe6f9dcc7 --- /dev/null +++ b/testdata/ttl_zero_cacherep.rpl @@ -0,0 +1,269 @@ +; config options +server: + target-fetch-policy: "0 0 0 0 0" + prefetch: no + serve-expired: no + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test TTL for the last zero second of cached messages. + +; 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 +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. 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 A +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +a.gtld-servers.net. IN A +SECTION ANSWER +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +K.ROOT-SERVERS.NET. IN A +SECTION ANSWER +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +a.gtld-servers.net. IN AAAA +SECTION AUTHORITY +. 86400 IN SOA . . 20070304 28800 7200 604800 86400 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +K.ROOT-SERVERS.NET. IN AAAA +SECTION AUTHORITY +. 86400 IN SOA . . 20070304 28800 7200 604800 86400 +ENTRY_END + +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 300 + 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. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. 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 A +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.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 +www.example.com. IN A +SECTION ANSWER +www.example.com. 10 IN A 1.2.3.4 +ENTRY_END +RANGE_END + +; ns.example.com +RANGE_BEGIN 100 300 + ADDRESS 1.2.3.4 + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA REFUSED +SECTION QUESTION +example.com. IN NS +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA REFUSED +SECTION QUESTION +ns.example.com. IN A +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA REFUSED +SECTION QUESTION +ns.example.com. IN AAAA +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR REFUSED +SECTION QUESTION +www.example.com. IN A +ENTRY_END +RANGE_END + +STEP 1 TIME_PASSES ELAPSE 10 + +STEP 10 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +STEP 20 CHECK_ANSWER +ENTRY_BEGIN +MATCH all ttl +REPLY QR RD RA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. 10 IN A 1.2.3.4 +ENTRY_END + +STEP 30 TIME_PASSES ELAPSE 5 + +STEP 40 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +STEP 50 CHECK_ANSWER +ENTRY_BEGIN +MATCH all ttl +REPLY QR RD RA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. 5 IN A 1.2.3.4 +ENTRY_END + +STEP 60 TIME_PASSES ELAPSE 3 + +STEP 70 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +STEP 80 CHECK_ANSWER +ENTRY_BEGIN +MATCH all ttl +REPLY QR RD RA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. 2 IN A 1.2.3.4 +ENTRY_END + +STEP 90 TIME_PASSES ELAPSE 1 + +STEP 100 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +STEP 110 CHECK_ANSWER +ENTRY_BEGIN +MATCH all ttl +REPLY QR RD RA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. 1 IN A 1.2.3.4 +ENTRY_END + +STEP 120 TIME_PASSES ELAPSE 1 + +STEP 130 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +STEP 140 CHECK_ANSWER +ENTRY_BEGIN +MATCH all ttl +REPLY QR RD RA SERVFAIL +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +ENTRY_END + +SCENARIO_END diff --git a/util/config_file.c b/util/config_file.c index a862c6a65..7becb8f05 100644 --- a/util/config_file.c +++ b/util/config_file.c @@ -129,6 +129,7 @@ config_create(void) cfg->tls_cert_bundle = NULL; cfg->tls_win_cert = 0; cfg->tls_use_sni = 1; + cfg->tls_use_system_policy_versions = 0; cfg->https_port = UNBOUND_DNS_OVER_HTTPS_PORT; if(!(cfg->http_endpoint = strdup("/dns-query"))) goto error_exit; cfg->http_max_streams = 100; @@ -629,6 +630,7 @@ int config_set_option(struct config_file* cfg, const char* opt, else S_STR("tls-ciphers:", tls_ciphers) else S_STR("tls-ciphersuites:", tls_ciphersuites) else S_YNO("tls-use-sni:", tls_use_sni) + else S_YNO("tls-use-system-policy-versions:", tls_use_system_policy_versions) else S_NUMBER_NONZERO("https-port:", https_port) else S_STR("http-endpoint:", http_endpoint) else S_NUMBER_NONZERO("http-max-streams:", http_max_streams) @@ -1180,6 +1182,7 @@ config_get_option(struct config_file* cfg, const char* opt, else O_STR(opt, "tls-ciphers", tls_ciphers) else O_STR(opt, "tls-ciphersuites", tls_ciphersuites) else O_YNO(opt, "tls-use-sni", tls_use_sni) + else O_YNO(opt, "tls-use-system-policy-versions", tls_use_system_policy_versions) else O_DEC(opt, "https-port", https_port) else O_STR(opt, "http-endpoint", http_endpoint) else O_UNS(opt, "http-max-streams", http_max_streams) diff --git a/util/config_file.h b/util/config_file.h index f512cde54..08e598501 100644 --- a/util/config_file.h +++ b/util/config_file.h @@ -149,6 +149,8 @@ struct config_file { char* tls_ciphersuites; /** if SNI is to be used */ int tls_use_sni; + /** if all TLS versions can be used; based on system policy (if any) */ + int tls_use_system_policy_versions; /** port on which to provide DNS over HTTPS service */ int https_port; diff --git a/util/configlexer.lex b/util/configlexer.lex index 9ddc5c1bc..e058f11b5 100644 --- a/util/configlexer.lex +++ b/util/configlexer.lex @@ -262,6 +262,7 @@ tls-session-ticket-keys{COLON} { YDVAR(1, VAR_TLS_SESSION_TICKET_KEYS) } tls-ciphers{COLON} { YDVAR(1, VAR_TLS_CIPHERS) } tls-ciphersuites{COLON} { YDVAR(1, VAR_TLS_CIPHERSUITES) } tls-use-sni{COLON} { YDVAR(1, VAR_TLS_USE_SNI) } +tls-use-system-policy-versions{COLON} { YDVAR(1, VAR_TLS_USE_SYSTEM_POLICY_VERSIONS) } https-port{COLON} { YDVAR(1, VAR_HTTPS_PORT) } http-endpoint{COLON} { YDVAR(1, VAR_HTTP_ENDPOINT) } http-max-streams{COLON} { YDVAR(1, VAR_HTTP_MAX_STREAMS) } diff --git a/util/configparser.y b/util/configparser.y index 2075ab836..ba5df616c 100644 --- a/util/configparser.y +++ b/util/configparser.y @@ -202,6 +202,7 @@ extern struct config_parser_state* cfg_parser; %token VAR_DISCARD_TIMEOUT VAR_WAIT_LIMIT VAR_WAIT_LIMIT_COOKIE %token VAR_WAIT_LIMIT_NETBLOCK VAR_WAIT_LIMIT_COOKIE_NETBLOCK %token VAR_STREAM_WAIT_SIZE VAR_TLS_CIPHERS VAR_TLS_CIPHERSUITES VAR_TLS_USE_SNI +%token VAR_TLS_USE_SYSTEM_POLICY_VERSIONS %token VAR_IPSET VAR_IPSET_NAME_V4 VAR_IPSET_NAME_V6 %token VAR_TLS_SESSION_TICKET_KEYS VAR_RPZ VAR_TAGS VAR_RPZ_ACTION_OVERRIDE %token VAR_RPZ_CNAME_OVERRIDE VAR_RPZ_LOG VAR_RPZ_LOG_NAME @@ -350,6 +351,7 @@ content_server: server_num_threads | server_verbosity | server_port | server_tls_ciphersuites | server_tls_session_ticket_keys | server_answer_cookie | server_cookie_secret | server_ip_ratelimit_cookie | server_tls_use_sni | server_edns_client_string | + server_tls_use_system_policy_versions | server_edns_client_string_opcode | server_nsid | server_zonemd_permissive_mode | server_max_reuse_tcp_queries | server_tcp_reuse_timeout | server_tcp_auth_query_timeout | @@ -1160,6 +1162,15 @@ server_tls_use_sni: VAR_TLS_USE_SNI STRING_ARG free($2); } ; +server_tls_use_system_policy_versions: VAR_TLS_USE_SYSTEM_POLICY_VERSIONS STRING_ARG + { + OUTYY(("P(server_tls_use_system_policy_versions:%s)\n", $2)); + if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) + yyerror("expected yes or no."); + else cfg_parser->cfg->tls_use_system_policy_versions = (strcmp($2, "yes")==0); + free($2); + } + ; server_https_port: VAR_HTTPS_PORT STRING_ARG { OUTYY(("P(server_https_port:%s)\n", $2)); diff --git a/util/data/msgencode.c b/util/data/msgencode.c index 84aa3b9e7..019da7253 100644 --- a/util/data/msgencode.c +++ b/util/data/msgencode.c @@ -496,10 +496,18 @@ packed_rrset_encode(struct ub_packed_rrset_key* key, sldns_buffer* pkt, return r; sldns_buffer_write(pkt, &key->rk.type, 2); sldns_buffer_write(pkt, &key->rk.rrset_class, 2); - if(data->rr_ttl[j] < adjust) + if(key->rk.flags & PACKED_RRSET_UPSTREAM_0TTL) { + sldns_buffer_write_u32(pkt, 0); + } else if(adjust == 0) { + sldns_buffer_write_u32(pkt, data->rr_ttl[j]); + } else if(TTL_IS_EXPIRED(data->rr_ttl[j], adjust)) { sldns_buffer_write_u32(pkt, - SERVE_EXPIRED?SERVE_EXPIRED_REPLY_TTL:0); - else sldns_buffer_write_u32(pkt, data->rr_ttl[j]-adjust); + EXPIRED_REPLY_TTL_CALC( + data->rr_ttl[j], data->ttl_add)); + } else { + sldns_buffer_write_u32(pkt, + data->rr_ttl[j] - adjust); + } if(c) { if((r=compress_rdata(pkt, data->rr_data[j], data->rr_len[j], region, tree, c, @@ -533,10 +541,18 @@ packed_rrset_encode(struct ub_packed_rrset_key* key, sldns_buffer* pkt, } sldns_buffer_write_u16(pkt, LDNS_RR_TYPE_RRSIG); sldns_buffer_write(pkt, &key->rk.rrset_class, 2); - if(data->rr_ttl[i] < adjust) + if(key->rk.flags & PACKED_RRSET_UPSTREAM_0TTL) { + sldns_buffer_write_u32(pkt, 0); + } else if(adjust == 0) { + sldns_buffer_write_u32(pkt, data->rr_ttl[i]); + } else if(TTL_IS_EXPIRED(data->rr_ttl[i], adjust)) { sldns_buffer_write_u32(pkt, - SERVE_EXPIRED?SERVE_EXPIRED_REPLY_TTL:0); - else sldns_buffer_write_u32(pkt, data->rr_ttl[i]-adjust); + EXPIRED_REPLY_TTL_CALC( + data->rr_ttl[i], data->ttl_add)); + } else { + sldns_buffer_write_u32(pkt, + data->rr_ttl[i] - adjust); + } /* rrsig rdata cannot be compressed, perform 100+ byte * memcopy. */ sldns_buffer_write(pkt, data->rr_data[i], @@ -993,10 +1009,10 @@ attach_edns_record(sldns_buffer* pkt, struct edns_data* edns) attach_edns_record_max_msg_sz(pkt, edns, edns->udp_size); } -int -reply_info_answer_encode(struct query_info* qinf, struct reply_info* rep, +int +reply_info_answer_encode(struct query_info* qinf, struct reply_info* rep, uint16_t id, uint16_t qflags, sldns_buffer* pkt, time_t timenow, - int cached, struct regional* region, uint16_t udpsize, + int cached, struct regional* region, uint16_t udpsize, struct edns_data* edns, int dnssec, int secure) { uint16_t flags; diff --git a/util/data/msgencode.h b/util/data/msgencode.h index 08fcb59b8..0363a90bf 100644 --- a/util/data/msgencode.h +++ b/util/data/msgencode.h @@ -66,9 +66,9 @@ struct edns_data; * @param secure: if 1, the AD bit is set in the reply. * @return: 0 on error (server failure). */ -int reply_info_answer_encode(struct query_info* qinf, struct reply_info* rep, +int reply_info_answer_encode(struct query_info* qinf, struct reply_info* rep, uint16_t id, uint16_t qflags, struct sldns_buffer* dest, time_t timenow, - int cached, struct regional* region, uint16_t udpsize, + int cached, struct regional* region, uint16_t udpsize, struct edns_data* edns, int dnssec, int secure); /** diff --git a/util/data/msgparse.c b/util/data/msgparse.c index 438d0e5b0..ca1ead05d 100644 --- a/util/data/msgparse.c +++ b/util/data/msgparse.c @@ -1383,3 +1383,13 @@ msgparse_rrset_remove_rr(const char* str, sldns_buffer* pkt, struct rrset_parse* * the rr->next works fine to continue. */ return rrset->rr_count == 0; } + +#ifdef UNBOUND_DEBUG +time_t debug_expired_reply_ttl_calc(time_t ttl, time_t ttl_add) { + /* Check that we are serving expired when this is called */ + /* ttl (absolute) should be later than ttl_add */ + log_assert(SERVE_EXPIRED && ttl_add <= ttl); + return (SERVE_EXPIRED_REPLY_TTL < (ttl) - (ttl_add) ? + SERVE_EXPIRED_REPLY_TTL : (ttl) - (ttl_add)); +} +#endif diff --git a/util/data/msgparse.h b/util/data/msgparse.h index 7de4e394f..373de677d 100644 --- a/util/data/msgparse.h +++ b/util/data/msgparse.h @@ -98,6 +98,31 @@ extern time_t SERVE_EXPIRED_REPLY_TTL; /** If we serve the original TTL or decrementing TTLs */ extern int SERVE_ORIGINAL_TTL; +/** calculate the prefetch TTL as 90% of original. Calculation + * without numerical overflow (uin32_t) */ +#define PREFETCH_TTL_CALC(ttl) ((ttl) - (ttl)/10) + +/* caclulate the TTL used for expired answers to somewhat make sense wrt the + * original TTL; don't reply with higher TTL than the original */ +#ifdef UNBOUND_DEBUG +time_t debug_expired_reply_ttl_calc(time_t ttl, time_t ttl_add); +#define EXPIRED_REPLY_TTL_CALC(ttl, ttl_add) \ + debug_expired_reply_ttl_calc(ttl, ttl_add) +#else +#define EXPIRED_REPLY_TTL_CALC(ttl, ttl_add) \ + (SERVE_EXPIRED_REPLY_TTL < (ttl) - (ttl_add) ? \ + SERVE_EXPIRED_REPLY_TTL : (ttl) - (ttl_add)) +#endif + +/** Update the reply_info TTL from an RRSet's TTL, essentially keeping the TTL + * sane with all the (progressively added) rrsets to the message */ +#define UPDATE_TTL_FROM_RRSET(ttl, rrsetttl) \ + ((ttl) = ((ttl) < (rrsetttl)) ? (ttl) : (rrsetttl)) + +/** Check if TTL is expired. 0 TTL is considered expired. + * Used mainly to identify parts of the code that do this comparison. */ +#define TTL_IS_EXPIRED(ttl, now) ((ttl) <= (now)) + /** * Data stored in scratch pad memory during parsing. * Stores the data that will enter into the msgreply and packet result. diff --git a/util/data/msgreply.c b/util/data/msgreply.c index 6b65e1eb1..dc82a7dec 100644 --- a/util/data/msgreply.c +++ b/util/data/msgreply.c @@ -178,9 +178,9 @@ reply_info_alloc_rrset_keys(struct reply_info* rep, struct alloc_cache* alloc, int reply_info_can_answer_expired(struct reply_info* rep, time_t timenow) { - log_assert(rep->ttl < timenow); + log_assert(TTL_IS_EXPIRED(rep->ttl, timenow)); /* Really expired */ - if(SERVE_EXPIRED_TTL && rep->serve_expired_ttl < timenow) return 0; + if(SERVE_EXPIRED_TTL && TTL_IS_EXPIRED(rep->serve_expired_ttl, timenow)) return 0; /* Ignore expired failure answers */ if(FLAGS_GET_RCODE(rep->flags) != LDNS_RCODE_NOERROR && FLAGS_GET_RCODE(rep->flags) != LDNS_RCODE_NXDOMAIN && @@ -188,12 +188,13 @@ reply_info_can_answer_expired(struct reply_info* rep, time_t timenow) return 1; } -int reply_info_could_use_expired(struct reply_info* rep, time_t timenow) +int +reply_info_could_use_expired(struct reply_info* rep, time_t timenow) { - log_assert(rep->ttl < timenow); + log_assert(TTL_IS_EXPIRED(rep->ttl, timenow)); /* Really expired */ - if(SERVE_EXPIRED_TTL && rep->serve_expired_ttl < timenow && - !SERVE_EXPIRED_TTL_RESET) return 0; + if(SERVE_EXPIRED_TTL && TTL_IS_EXPIRED(rep->serve_expired_ttl, timenow) + && !SERVE_EXPIRED_TTL_RESET) return 0; /* Ignore expired failure answers */ if(FLAGS_GET_RCODE(rep->flags) != LDNS_RCODE_NOERROR && FLAGS_GET_RCODE(rep->flags) != LDNS_RCODE_NXDOMAIN && @@ -229,7 +230,7 @@ make_new_reply_info(const struct reply_info* rep, struct regional* region, } /** find the minimumttl in the rdata of SOA record */ -static time_t +static uint32_t soa_find_minttl(struct rr_parse* rr) { uint16_t rlen = sldns_read_uint16(rr->ttl_data+4); @@ -237,7 +238,7 @@ soa_find_minttl(struct rr_parse* rr) return 0; /* rdata too small for SOA (dname, dname, 5*32bit) */ /* minimum TTL is the last 32bit value in the rdata of the record */ /* at position ttl_data + 4(ttl) + 2(rdatalen) + rdatalen - 4(timeval)*/ - return (time_t)sldns_read_uint32(rr->ttl_data+6+rlen-4); + return sldns_read_uint32(rr->ttl_data+6+rlen-4); } /** do the rdata copy */ @@ -247,37 +248,40 @@ rdata_copy(sldns_buffer* pkt, struct packed_rrset_data* data, uint8_t* to, sldns_pkt_section section) { uint16_t pkt_len; + uint32_t ttl; const sldns_rr_descriptor* desc; - *rr_ttl = sldns_read_uint32(rr->ttl_data); + ttl = sldns_read_uint32(rr->ttl_data); /* RFC 2181 Section 8. if msb of ttl is set treat as if zero. */ - if((*rr_ttl & 0x80000000U)) - *rr_ttl = 0; + /* RFC 8767 Section 4. values with high-order bit as positive, not 0. ++ * As such, it will be capped by MAX_TTL below. */ if(type == LDNS_RR_TYPE_SOA && section == LDNS_SECTION_AUTHORITY) { /* negative response. see if TTL of SOA record larger than the * minimum-ttl in the rdata of the SOA record */ - if(*rr_ttl > soa_find_minttl(rr)) *rr_ttl = soa_find_minttl(rr); + if(ttl > soa_find_minttl(rr)) ttl = soa_find_minttl(rr); if(!SERVE_ORIGINAL_TTL) { /* If MIN_NEG_TTL is configured skip setting MIN_TTL */ - if(MIN_NEG_TTL <= 0 && *rr_ttl < MIN_TTL) { - *rr_ttl = MIN_TTL; + if(MIN_NEG_TTL <= 0 && ttl < MIN_TTL) { + ttl = MIN_TTL; } - if(*rr_ttl > MAX_TTL) *rr_ttl = MAX_TTL; + if(ttl > MAX_TTL) ttl = MAX_TTL; } /* MAX_NEG_TTL overrides the min and max ttl of everything * else; it is for a more specific record */ - if(*rr_ttl > MAX_NEG_TTL) *rr_ttl = MAX_NEG_TTL; + if(ttl > MAX_NEG_TTL) ttl = MAX_NEG_TTL; /* MIN_NEG_TTL overrides the min and max ttl of everything * else if configured; it is for a more specific record */ - if(MIN_NEG_TTL > 0 && *rr_ttl < MIN_NEG_TTL) { - *rr_ttl = MIN_NEG_TTL; + if(MIN_NEG_TTL > 0 && ttl < MIN_NEG_TTL) { + ttl = MIN_NEG_TTL; } } else if(!SERVE_ORIGINAL_TTL) { - if(*rr_ttl < MIN_TTL) *rr_ttl = MIN_TTL; - if(*rr_ttl > MAX_TTL) *rr_ttl = MAX_TTL; + if(ttl < MIN_TTL) ttl = MIN_TTL; + if(ttl > MAX_TTL) ttl = MAX_TTL; } - if(*rr_ttl < data->ttl) - data->ttl = *rr_ttl; + if(ttl < data->ttl) + data->ttl = ttl; + /* We have concluded the TTL checks */ + *rr_ttl = (time_t)ttl; if(rr->outside_packet) { /* uncompressed already, only needs copy */ @@ -481,6 +485,7 @@ parse_copy_decompress_rrset(sldns_buffer* pkt, struct msg_parse* msg, pk->entry.key = (void*)pk; pk->entry.hash = pset->hash; data->trust = get_rrset_trust(msg, pset); + pk->rk.flags |= (data->ttl == 0) ? PACKED_RRSET_UPSTREAM_0TTL : 0; return 1; } @@ -617,6 +622,29 @@ reply_info_set_ttls(struct reply_info* rep, time_t timenow) } } +void +reply_info_absolute_ttls(struct reply_info* rep, time_t ttl, time_t ttl_add) +{ + size_t i, j; + rep->ttl = ttl; + rep->prefetch_ttl = PREFETCH_TTL_CALC(ttl); + rep->serve_expired_ttl = ttl + SERVE_EXPIRED_TTL; + /* Don't set rep->serve_expired_norec_ttl; this should only be set + * on cached records when encountering an error */ + log_assert(rep->serve_expired_norec_ttl == 0); + for(i=0; irrset_count; i++) { + struct packed_rrset_data* data = (struct packed_rrset_data*) + rep->ref[i].key->entry.data; + if(i>0 && rep->ref[i].key == rep->ref[i-1].key) + continue; + data->ttl = ttl; + for(j=0; jcount + data->rrsig_count; j++) { + data->rr_ttl[j] = ttl; + } + data->ttl_add = ttl_add; + } +} + void reply_info_parsedelete(struct reply_info* rep, struct alloc_cache* alloc) { @@ -1129,7 +1157,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?txt:"\"\"")); + verbose(VERB_ALGO, "attached EDE code: %d with message: '%s'", code, (txt?txt:"")); *prevp = opt; return 1; } diff --git a/util/data/msgreply.h b/util/data/msgreply.h index b65abd922..87eebb2b9 100644 --- a/util/data/msgreply.h +++ b/util/data/msgreply.h @@ -60,10 +60,6 @@ struct local_rrset; struct dns_msg; enum comm_point_type; -/** calculate the prefetch TTL as 90% of original. Calculation - * without numerical overflow (uin32_t) */ -#define PREFETCH_TTL_CALC(ttl) ((ttl) - (ttl)/10) - /** * Structure to store query information that makes answers to queries * different. @@ -340,6 +336,15 @@ void reply_info_sortref(struct reply_info* rep); */ void reply_info_set_ttls(struct reply_info* rep, time_t timenow); +/** + * Set TTLs inside the replyinfo to the given absolute values. + * @param rep: reply info. rrsets must be filled in. + * Also refs must be filled in. + * @param ttl: absolute ttl value to be set. + * @param ttl_add: the current time to be used verbatim for ttl_add in the rrsets. + */ +void reply_info_absolute_ttls(struct reply_info* rep, time_t ttl, time_t ttl_add); + /** * Delete reply_info and packed_rrsets (while they are not yet added to the * hashtables.). Returns rrsets to the alloc cache. @@ -572,7 +577,7 @@ void log_query_info(enum verbosity_value v, const char* str, struct query_info* qinf); /** - * Append edns option to edns option list + * Append edns option to edns option list. * @param list: the edns option list to append the edns option to. * @param code: the edns option's code. * @param len: the edns option's length. @@ -584,20 +589,23 @@ int edns_opt_list_append(struct edns_option** list, uint16_t code, size_t len, uint8_t* data, struct regional* region); /** - * Append edns EDE option to edns options list + * Append edns EDE option to edns options list. + * We need ATTR_NONSTRING because we are trimming the trailing \0 of static + * string (TXT) when assigning to ede.text; it silences compiler nonstring + * warnings. * @param LIST: the edns option list to append the edns option to. * @param REGION: region to allocate the new edns option. * @param CODE: the EDE code. - * @param TXT: Additional text for the option + * @param TXT: Additional text for the option. */ #define EDNS_OPT_LIST_APPEND_EDE(LIST, REGION, CODE, TXT) \ do { \ struct { \ uint16_t code; \ - char text[sizeof(TXT) - 1]; \ + char ATTR_NONSTRING(text[sizeof(TXT) - 1]) ; \ } ede = { htons(CODE), TXT }; \ verbose(VERB_ALGO, "attached EDE code: %d with" \ - " message: %s", CODE, TXT); \ + " message: '%s'", CODE, TXT); \ edns_opt_list_append((LIST), LDNS_EDNS_EDE, \ sizeof(uint16_t) + sizeof(TXT) - 1, \ (void *)&ede, (REGION)); \ diff --git a/util/data/packed_rrset.c b/util/data/packed_rrset.c index d18486cc5..89ece3c03 100644 --- a/util/data/packed_rrset.c +++ b/util/data/packed_rrset.c @@ -336,10 +336,9 @@ packed_rrset_copy_region(struct ub_packed_rrset_key* key, struct ub_packed_rrset_key* ck = regional_alloc(region, sizeof(struct ub_packed_rrset_key)); struct packed_rrset_data* d; - struct packed_rrset_data* data = (struct packed_rrset_data*) - key->entry.data; + struct packed_rrset_data* data = key->entry.data; size_t dsize, i; - time_t adjust = 0; + time_t now_control; if(!ck) return NULL; ck->id = key->id; @@ -352,22 +351,31 @@ packed_rrset_copy_region(struct ub_packed_rrset_key* key, if(!ck->rk.dname) return NULL; dsize = packed_rrset_sizeof(data); - d = (struct packed_rrset_data*)regional_alloc_init(region, data, dsize); + d = regional_alloc_init(region, data, dsize); if(!d) return NULL; ck->entry.data = d; packed_rrset_ptr_fixup(d); - /* make TTLs relative - once per rrset */ - adjust = SERVE_ORIGINAL_TTL ? data->ttl_add : now; - for(i=0; icount + d->rrsig_count; i++) { - if(d->rr_ttl[i] < adjust) - d->rr_ttl[i] = SERVE_EXPIRED?SERVE_EXPIRED_REPLY_TTL:0; - else d->rr_ttl[i] -= adjust; + /* make TTLs relative - once per rr */ + if(now > 0) { + /* NS RRSets may be here with ttl_add higher than now because + * of the novel ghost attack mitigation i.e., using the + * qstarttime for NS RRSets. In that case make sure that the + * returned TTL is not higher than the original one. */ + log_assert(d->ttl_add <= now || + (ntohs(key->rk.type) == LDNS_RR_TYPE_NS)); + now_control = SERVE_ORIGINAL_TTL ? data->ttl_add + : (d->ttl_add > now ? d->ttl_add : now ); + for(i=0; icount + d->rrsig_count; i++) { + if(TTL_IS_EXPIRED(d->rr_ttl[i], now_control)) { + d->rr_ttl[i] = EXPIRED_REPLY_TTL_CALC(d->rr_ttl[i], data->ttl_add); + } else d->rr_ttl[i] -= now_control; + } + if(TTL_IS_EXPIRED(d->ttl, now_control)) { + d->ttl = EXPIRED_REPLY_TTL_CALC(d->ttl, data->ttl_add); + } else d->ttl -= now_control; + d->ttl_add = 0; /* TTLs have been made relative */ } - if(d->ttl < adjust) - d->ttl = SERVE_EXPIRED?SERVE_EXPIRED_REPLY_TTL:0; - else d->ttl -= adjust; - d->ttl_add = 0; /* TTLs have been made relative */ return ck; } diff --git a/util/data/packed_rrset.h b/util/data/packed_rrset.h index 776e8d092..4e0911ccf 100644 --- a/util/data/packed_rrset.h +++ b/util/data/packed_rrset.h @@ -70,6 +70,8 @@ typedef uint64_t rrset_id_type; #define PACKED_RRSET_RPZ 0x8 /** this rrset is A/AAAA and is an unverified glue record */ #define PACKED_RRSET_UNVERIFIED_GLUE 0x10 +/** this rrset has a 0TTL from upstream */ +#define PACKED_RRSET_UPSTREAM_0TTL 0x20 /** number of rrs and rrsets for integer overflow protection. More than * this is not really possible (64K packet has much less RRs and RRsets) in @@ -99,6 +101,7 @@ struct packed_rrset_key { * o PACKED_RRSET_FIXEDTTL (not supposed to be cached) * o PACKED_RRSET_RPZ * o PACKED_RRSET_UNVERIFIED_GLUE + * o PACKED_RRSET_UPSTREAM_0TTL (not supposed to be cached) */ uint32_t flags; /** the rrset type in network format */ diff --git a/util/fptr_wlist.c b/util/fptr_wlist.c index 464ab0138..101f7ca57 100644 --- a/util/fptr_wlist.c +++ b/util/fptr_wlist.c @@ -382,7 +382,8 @@ fptr_whitelist_modenv_detach_subs(void (*fptr)( int fptr_whitelist_modenv_attach_sub(int (*fptr)( struct module_qstate* qstate, struct query_info* qinfo, - uint16_t qflags, int prime, int valrec, struct module_qstate** newq)) + struct respip_client_info* cinfo, uint16_t qflags, int prime, + int valrec, struct module_qstate** newq)) { if(fptr == &mesh_attach_sub) return 1; return 0; @@ -391,8 +392,8 @@ fptr_whitelist_modenv_attach_sub(int (*fptr)( int fptr_whitelist_modenv_add_sub(int (*fptr)( struct module_qstate* qstate, struct query_info* qinfo, - uint16_t qflags, int prime, int valrec, struct module_qstate** newq, - struct mesh_state** sub)) + struct respip_client_info* cinfo, uint16_t qflags, int prime, + int valrec, struct module_qstate** newq, struct mesh_state** sub)) { if(fptr == &mesh_add_sub) return 1; return 0; diff --git a/util/fptr_wlist.h b/util/fptr_wlist.h index fb2475cce..a1a75625d 100644 --- a/util/fptr_wlist.h +++ b/util/fptr_wlist.h @@ -233,7 +233,8 @@ int fptr_whitelist_modenv_detach_subs(void (*fptr)( */ int fptr_whitelist_modenv_attach_sub(int (*fptr)( struct module_qstate* qstate, struct query_info* qinfo, - uint16_t qflags, int prime, int valrec, struct module_qstate** newq)); + struct respip_client_info* cinfo, uint16_t qflags, int prime, + int valrec, struct module_qstate** newq)); /** * Check function pointer whitelist for module_env add_sub callback values. @@ -242,8 +243,9 @@ int fptr_whitelist_modenv_attach_sub(int (*fptr)( * @return false if not in whitelist. */ int fptr_whitelist_modenv_add_sub(int (*fptr)(struct module_qstate* qstate, - struct query_info* qinfo, uint16_t qflags, int prime, int valrec, - struct module_qstate** newq, struct mesh_state** sub)); + struct query_info* qinfo, struct respip_client_info* cinfo, + uint16_t qflags, int prime, int valrec, struct module_qstate** newq, + struct mesh_state** sub)); /** * Check function pointer whitelist for module_env kill_sub callback values. * diff --git a/util/module.h b/util/module.h index aa7508ac2..e3a1693d4 100644 --- a/util/module.h +++ b/util/module.h @@ -412,6 +412,8 @@ struct module_env { * @param qstate: the state to find mesh state, and that wants to * receive the results from the new subquery. * @param qinfo: what to query for (copied). + * @param cinfo: if non-NULL client specific info that may affect + * IP-based actions that apply to the query result. * @param qflags: what flags to use (RD, CD flag or not). * @param prime: if it is a (stub) priming query. * @param valrec: validation lookup recursion, does not need validation @@ -420,8 +422,9 @@ struct module_env { * @return: false on error, true if success (and init may be needed). */ int (*attach_sub)(struct module_qstate* qstate, - struct query_info* qinfo, uint16_t qflags, int prime, - int valrec, struct module_qstate** newq); + struct query_info* qinfo, struct respip_client_info* cinfo, + uint16_t qflags, int prime, int valrec, + struct module_qstate** newq); /** * Add detached query. @@ -441,6 +444,8 @@ struct module_env { * @param qstate: the state to find mesh state, and that wants to receive * the results from the new subquery. * @param qinfo: what to query for (copied). + * @param cinfo: if non-NULL client specific info that may affect + * IP-based actions that apply to the query result. * @param qflags: what flags to use (RD / CD flag or not). * @param prime: if it is a (stub) priming query. * @param valrec: if it is a validation recursion query (lookup of key, DS). @@ -450,9 +455,9 @@ struct module_env { * @return: false on error, true if success (and init may be needed). */ int (*add_sub)(struct module_qstate* qstate, - struct query_info* qinfo, uint16_t qflags, int prime, - int valrec, struct module_qstate** newq, - struct mesh_state** sub); + struct query_info* qinfo, struct respip_client_info* cinfo, + uint16_t qflags, int prime, int valrec, + struct module_qstate** newq, struct mesh_state** sub); /** * Kill newly attached sub. If attach_sub returns newq for diff --git a/util/net_help.c b/util/net_help.c index 6ce0d9131..426ace934 100644 --- a/util/net_help.c +++ b/util/net_help.c @@ -1226,7 +1226,7 @@ setup_ticket_keys_cb(void* sslctx) #endif /* HAVE_SSL */ int -listen_sslctx_setup(void* ctxt) +listen_sslctx_setup(void* ctxt, int use_system_versions) { #ifdef HAVE_SSL SSL_CTX* ctx = (SSL_CTX*)ctxt; @@ -1238,35 +1238,37 @@ listen_sslctx_setup(void* ctxt) return 0; } #endif - if((SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv3) & SSL_OP_NO_SSLv3) - != SSL_OP_NO_SSLv3){ - log_crypto_err("could not set SSL_OP_NO_SSLv3"); - return 0; - } + if(!use_system_versions) { + if((SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv3) & SSL_OP_NO_SSLv3) + != SSL_OP_NO_SSLv3){ + log_crypto_err("could not set SSL_OP_NO_SSLv3"); + return 0; + } #if defined(SSL_OP_NO_TLSv1) && defined(SSL_OP_NO_TLSv1_1) - /* if we have tls 1.1 disable 1.0 */ - if((SSL_CTX_set_options(ctx, SSL_OP_NO_TLSv1) & SSL_OP_NO_TLSv1) - != SSL_OP_NO_TLSv1){ - log_crypto_err("could not set SSL_OP_NO_TLSv1"); - return 0; - } + /* if we have tls 1.1 disable 1.0 */ + if((SSL_CTX_set_options(ctx, SSL_OP_NO_TLSv1) & SSL_OP_NO_TLSv1) + != SSL_OP_NO_TLSv1){ + log_crypto_err("could not set SSL_OP_NO_TLSv1"); + return 0; + } #endif #if defined(SSL_OP_NO_TLSv1_1) && defined(SSL_OP_NO_TLSv1_2) - /* if we have tls 1.2 disable 1.1 */ - if((SSL_CTX_set_options(ctx, SSL_OP_NO_TLSv1_1) & SSL_OP_NO_TLSv1_1) - != SSL_OP_NO_TLSv1_1){ - log_crypto_err("could not set SSL_OP_NO_TLSv1_1"); - return 0; - } + /* if we have tls 1.2 disable 1.1 */ + if((SSL_CTX_set_options(ctx, SSL_OP_NO_TLSv1_1) & SSL_OP_NO_TLSv1_1) + != SSL_OP_NO_TLSv1_1){ + log_crypto_err("could not set SSL_OP_NO_TLSv1_1"); + return 0; + } #endif #if defined(SSL_OP_NO_TLSv1_2) && defined(SSL_OP_NO_TLSv1_3) - /* if we have tls 1.3 disable 1.2 */ - if((SSL_CTX_set_options(ctx, SSL_OP_NO_TLSv1_2) & SSL_OP_NO_TLSv1_2) - != SSL_OP_NO_TLSv1_2){ - log_crypto_err("could not set SSL_OP_NO_TLSv1_2"); - return 0; - } + /* if we have tls 1.3 disable 1.2 */ + if((SSL_CTX_set_options(ctx, SSL_OP_NO_TLSv1_2) & SSL_OP_NO_TLSv1_2) + != SSL_OP_NO_TLSv1_2){ + log_crypto_err("could not set SSL_OP_NO_TLSv1_2"); + return 0; + } #endif + } #if defined(SSL_OP_NO_RENEGOTIATION) /* disable client renegotiation */ if((SSL_CTX_set_options(ctx, SSL_OP_NO_RENEGOTIATION) & @@ -1341,7 +1343,7 @@ listen_sslctx_setup_2(void* ctxt) void* listen_sslctx_create(const char* key, const char* pem, const char* verifypem, const char* tls_ciphers, const char* tls_ciphersuites, int set_ticket_keys_cb, - int is_dot, int is_doh) + int is_dot, int is_doh, int use_system_versions) { #ifdef HAVE_SSL SSL_CTX* ctx = SSL_CTX_new(SSLv23_server_method()); @@ -1359,7 +1361,7 @@ void* listen_sslctx_create(const char* key, const char* pem, SSL_CTX_free(ctx); return NULL; } - if(!listen_sslctx_setup(ctx)) { + if(!listen_sslctx_setup(ctx, use_system_versions)) { SSL_CTX_free(ctx); return NULL; } diff --git a/util/net_help.h b/util/net_help.h index 278e370a2..7b8a20642 100644 --- a/util/net_help.h +++ b/util/net_help.h @@ -478,9 +478,11 @@ void log_cert(unsigned level, const char* str, void* cert); /** * Set SSL_OP_NOxxx options on SSL context to disable bad crypto * @param ctxt: SSL_CTX* + * @param use_system_versions: rely on the system policy (if any) for allowed + * TLS versions * @return false on failure. */ -int listen_sslctx_setup(void* ctxt); +int listen_sslctx_setup(void* ctxt, int use_system_versions); /** * Further setup of listening SSL context, after keys loaded. @@ -499,12 +501,14 @@ void listen_sslctx_setup_2(void* ctxt); * to be set. * @param is_dot: if the TLS connection is for DoT to set the appropriate ALPN. * @param is_doh: if the TLS connection is for DoH to set the appropriate ALPN. + * @param use_system_versions: rely on the system policy (if any) for allowed + * TLS versions * return SSL_CTX* or NULL on failure (logged). */ void* listen_sslctx_create(const char* key, const char* pem, const char* verifypem, const char* tls_ciphers, const char* tls_ciphersuites, int set_ticket_keys_cb, - int is_dot, int is_doh); + int is_dot, int is_doh, int use_system_versions); /** * create SSL connect context diff --git a/validator/val_neg.c b/validator/val_neg.c index bc3a83aeb..7817d56fc 100644 --- a/validator/val_neg.c +++ b/validator/val_neg.c @@ -1066,11 +1066,7 @@ grab_nsec(struct rrset_cache* rrset_cache, uint8_t* qname, size_t qname_len, qname, qname_len, qtype, qclass, flags, now, 0); struct packed_rrset_data* d; if(!k) return NULL; - d = (struct packed_rrset_data*)k->entry.data; - if(d->ttl < now) { - lock_rw_unlock(&k->entry.lock); - return NULL; - } + d = k->entry.data; /* only secure or unchecked records that have signatures. */ if( ! ( d->security == sec_status_secure || (d->security == sec_status_unchecked && diff --git a/validator/val_utils.c b/validator/val_utils.c index 549264d76..1a5f19673 100644 --- a/validator/val_utils.c +++ b/validator/val_utils.c @@ -1310,6 +1310,7 @@ val_find_DS(struct module_env* env, uint8_t* nm, size_t nmlen, uint16_t c, /* DS rrset exists. Return it to the validator immediately*/ struct ub_packed_rrset_key* copy = packed_rrset_copy_region( rrset, region, *env->now); + struct packed_rrset_data* d = copy->entry.data; lock_rw_unlock(&rrset->entry.lock); if(!copy) return NULL; @@ -1319,6 +1320,7 @@ val_find_DS(struct module_env* env, uint8_t* nm, size_t nmlen, uint16_t c, msg->rep->rrsets[0] = copy; msg->rep->rrset_count++; msg->rep->an_numrrsets++; + UPDATE_TTL_FROM_RRSET(msg->rep->ttl, d->ttl); return msg; } /* lookup in rrset and negative cache for NSEC/NSEC3 */ diff --git a/validator/validator.c b/validator/validator.c index 5817fc808..c129df920 100644 --- a/validator/validator.c +++ b/validator/validator.c @@ -496,7 +496,7 @@ generate_request(struct module_qstate* qstate, int id, uint8_t* name, struct mesh_state* sub = NULL; fptr_ok(fptr_whitelist_modenv_add_sub( qstate->env->add_sub)); - if(!(*qstate->env->add_sub)(qstate, &ask, + if(!(*qstate->env->add_sub)(qstate, &ask, NULL, (uint16_t)(BIT_RD|flags), 0, valrec, newq, &sub)){ log_err("Could not generate request: out of memory"); return 0; @@ -505,7 +505,7 @@ generate_request(struct module_qstate* qstate, int id, uint8_t* name, else { fptr_ok(fptr_whitelist_modenv_attach_sub( qstate->env->attach_sub)); - if(!(*qstate->env->attach_sub)(qstate, &ask, + if(!(*qstate->env->attach_sub)(qstate, &ask, NULL, (uint16_t)(BIT_RD|flags), 0, valrec, newq)){ log_err("Could not generate request: out of memory"); return 0; diff --git a/winrc/win_svc.c b/winrc/win_svc.c index 429b045dc..6fca0c7d5 100644 --- a/winrc/win_svc.c +++ b/winrc/win_svc.c @@ -369,7 +369,7 @@ service_init(int r, struct daemon** d, struct config_file** c) cfg->tls_ciphers, cfg->tls_ciphersuites, (cfg->tls_session_ticket_keys.first && cfg->tls_session_ticket_keys.first->str[0] != 0), - 1, 0))) { + 1, 0, cfg->tls_use_system_policy_versions))) { fatal_exit("could not set up listen SSL_CTX"); } #ifdef HAVE_NGHTTP2_NGHTTP2_H @@ -379,7 +379,7 @@ service_init(int r, struct daemon** d, struct config_file** c) cfg->tls_ciphers, cfg->tls_ciphersuites, (cfg->tls_session_ticket_keys.first && cfg->tls_session_ticket_keys.first->str[0] != 0), - 0, 1))) { + 0, 1, cfg->tls_use_system_policy_versions))) { fatal_exit("could not set up listen doh SSL_CTX"); } }