diff options
Diffstat (limited to 'usr.sbin/unbound')
52 files changed, 1345 insertions, 663 deletions
diff --git a/usr.sbin/unbound/Makefile.in b/usr.sbin/unbound/Makefile.in index fef4c5283ec..1c4f5fe8581 100644 --- a/usr.sbin/unbound/Makefile.in +++ b/usr.sbin/unbound/Makefile.in @@ -739,7 +739,7 @@ msgencode.lo msgencode.o: $(srcdir)/util/data/msgencode.c config.h $(srcdir)/uti msgparse.lo msgparse.o: $(srcdir)/util/data/msgparse.c config.h $(srcdir)/util/data/msgparse.h \ $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/sldns/pkthdr.h \ $(srcdir)/sldns/rrdef.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h \ - $(srcdir)/util/data/dname.h $(srcdir)/util/storage/lookup3.h $(srcdir)/util/regional.h $(srcdir)/sldns/sbuffer.h \ + $(srcdir)/util/data/dname.h $(srcdir)/util/storage/lookup3.h $(srcdir)/util/regional.h $(srcdir)/util/net_help.h $(srcdir)/sldns/sbuffer.h \ $(srcdir)/sldns/parseutil.h $(srcdir)/sldns/wire2str.h msgreply.lo msgreply.o: $(srcdir)/util/data/msgreply.c config.h $(srcdir)/util/data/msgreply.h \ $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/data/packed_rrset.h \ @@ -794,7 +794,7 @@ iter_priv.lo iter_priv.o: $(srcdir)/iterator/iter_priv.c config.h $(srcdir)/iter $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/net_help.h \ $(srcdir)/util/storage/dnstree.h $(srcdir)/sldns/str2wire.h $(srcdir)/sldns/sbuffer.h iter_resptype.lo iter_resptype.o: $(srcdir)/iterator/iter_resptype.c config.h \ - $(srcdir)/iterator/iter_resptype.h $(srcdir)/iterator/iter_delegpt.h $(srcdir)/util/log.h \ + $(srcdir)/iterator/iter_resptype.h $(srcdir)/iterator/iter_delegpt.h $(srcdir)/iterator/iterator.h $(srcdir)/util/log.h \ $(srcdir)/services/cache/dns.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h \ $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/net_help.h \ $(srcdir)/util/data/dname.h $(srcdir)/sldns/rrdef.h $(srcdir)/sldns/pkthdr.h diff --git a/usr.sbin/unbound/README.md b/usr.sbin/unbound/README.md index c220da03045..3bbd38b3b78 100644 --- a/usr.sbin/unbound/README.md +++ b/usr.sbin/unbound/README.md @@ -17,7 +17,9 @@ You can learn more about Unbound by reading our ## Compiling Make sure you have the C toolchain, OpenSSL and its include files, and libexpat -installed. Unbound can be compiled and installed using: +installed. +If building from the repository source you also need flex and bison installed. +Unbound can be compiled and installed using: ``` ./configure && make && make install @@ -27,7 +29,7 @@ You can use libevent if you want. libevent is useful when using many (10000) outgoing ports. By default max 256 ports are opened at the same time and the builtin alternative is equally capable and a little faster. -Use the `--with-libevent=dir` configure option to compile Unbound with libevent +Use the `--with-libevent` configure option to compile Unbound with libevent support. ## Unbound configuration diff --git a/usr.sbin/unbound/cachedb/cachedb.c b/usr.sbin/unbound/cachedb/cachedb.c index 30645268ca2..b912be8ed54 100644 --- a/usr.sbin/unbound/cachedb/cachedb.c +++ b/usr.sbin/unbound/cachedb/cachedb.c @@ -265,11 +265,11 @@ cachedb_init(struct module_env* env, int id) return 0; } cachedb_env->enabled = 1; - if(env->cfg->serve_expired_reply_ttl) + if(env->cfg->serve_expired && env->cfg->serve_expired_reply_ttl) log_warn( "cachedb: serve-expired-reply-ttl is set but not working for data " - "originating from the external cache; 0 TLL is used for those."); - if(env->cfg->serve_expired_client_timeout) + "originating from the external cache; 0 TTL is used for those."); + if(env->cfg->serve_expired && env->cfg->serve_expired_client_timeout) log_warn( "cachedb: serve-expired-client-timeout is set but not working for " "data originating from the external cache; expired data are used " @@ -815,6 +815,11 @@ cachedb_handle_response(struct module_qstate* qstate, qstate->ext_state[id] = module_finished; return; } + if(qstate->env->cfg->cachedb_no_store) { + /* do not store the item in the external cache */ + qstate->ext_state[id] = module_finished; + return; + } /* store the item into the backend cache */ cachedb_extcache_store(qstate, ie); diff --git a/usr.sbin/unbound/config.guess b/usr.sbin/unbound/config.guess index b187213930f..f6d217a49f8 100644 --- a/usr.sbin/unbound/config.guess +++ b/usr.sbin/unbound/config.guess @@ -1,10 +1,10 @@ #! /bin/sh # Attempt to guess a canonical system name. -# Copyright 1992-2023 Free Software Foundation, Inc. +# Copyright 1992-2024 Free Software Foundation, Inc. # shellcheck disable=SC2006,SC2268 # see below for rationale -timestamp='2023-07-20' +timestamp='2024-01-01' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by @@ -60,7 +60,7 @@ version="\ GNU config.guess ($timestamp) Originally written by Per Bothner. -Copyright 1992-2023 Free Software Foundation, Inc. +Copyright 1992-2024 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." @@ -155,6 +155,9 @@ Linux|GNU|GNU/*) set_cc_for_build cat <<-EOF > "$dummy.c" + #if defined(__ANDROID__) + LIBC=android + #else #include <features.h> #if defined(__UCLIBC__) LIBC=uclibc @@ -162,6 +165,8 @@ Linux|GNU|GNU/*) LIBC=dietlibc #elif defined(__GLIBC__) LIBC=gnu + #elif defined(__LLVM_LIBC__) + LIBC=llvm #else #include <stdarg.h> /* First heuristic to detect musl libc. */ @@ -169,6 +174,7 @@ Linux|GNU|GNU/*) LIBC=musl #endif #endif + #endif EOF cc_set_libc=`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^LIBC' | sed 's, ,,g'` eval "$cc_set_libc" @@ -904,7 +910,7 @@ EOF fi ;; *:FreeBSD:*:*) - UNAME_PROCESSOR=`/usr/bin/uname -p` + UNAME_PROCESSOR=`uname -p` case $UNAME_PROCESSOR in amd64) UNAME_PROCESSOR=x86_64 ;; @@ -1589,6 +1595,9 @@ EOF *:Unleashed:*:*) GUESS=$UNAME_MACHINE-unknown-unleashed$UNAME_RELEASE ;; + *:Ironclad:*:*) + GUESS=$UNAME_MACHINE-unknown-ironclad + ;; esac # Do we have a guess based on uname results? diff --git a/usr.sbin/unbound/config.sub b/usr.sbin/unbound/config.sub index 6ae25027537..2c6a07ab3c3 100644 --- a/usr.sbin/unbound/config.sub +++ b/usr.sbin/unbound/config.sub @@ -1,10 +1,10 @@ #! /bin/sh # Configuration validation subroutine script. -# Copyright 1992-2023 Free Software Foundation, Inc. +# Copyright 1992-2024 Free Software Foundation, Inc. # shellcheck disable=SC2006,SC2268 # see below for rationale -timestamp='2023-07-31' +timestamp='2024-01-01' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by @@ -76,7 +76,7 @@ Report bugs and patches to <config-patches@gnu.org>." version="\ GNU config.sub ($timestamp) -Copyright 1992-2023 Free Software Foundation, Inc. +Copyright 1992-2024 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." @@ -1181,7 +1181,7 @@ case $cpu-$vendor in case $cpu in 1750a | 580 \ | a29k \ - | aarch64 | aarch64_be \ + | aarch64 | aarch64_be | aarch64c | arm64ec \ | abacus \ | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] \ | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] \ @@ -1200,6 +1200,7 @@ case $cpu-$vendor in | d10v | d30v | dlx | dsp16xx \ | e2k | elxsi | epiphany \ | f30[01] | f700 | fido | fr30 | frv | ft32 | fx80 \ + | javascript \ | h8300 | h8500 \ | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ | hexagon \ @@ -1221,6 +1222,7 @@ case $cpu-$vendor in | moxie \ | mt \ | msp430 \ + | nanomips* \ | nds32 | nds32le | nds32be \ | nfp \ | nios | nios2 | nios2eb | nios2el \ @@ -1252,6 +1254,7 @@ case $cpu-$vendor in | ubicom32 \ | v70 | v850 | v850e | v850e1 | v850es | v850e2 | v850e2v3 \ | vax \ + | vc4 \ | visium \ | w65 \ | wasm32 | wasm64 \ @@ -1284,11 +1287,12 @@ esac # Decode manufacturer-specific aliases for certain operating systems. -if test x$basic_os != x +if test x"$basic_os" != x then # First recognize some ad-hoc cases, or perhaps split kernel-os, or else just # set os. +obj= case $basic_os in gnu/linux*) kernel=linux @@ -1488,10 +1492,16 @@ case $os in os=eabi ;; *) - os=elf + os= + obj=elf ;; esac ;; + aout* | coff* | elf* | pe*) + # These are machine code file formats, not OSes + obj=$os + os= + ;; *) # No normalization, but not necessarily accepted, that comes below. ;; @@ -1510,12 +1520,15 @@ else # system, and we'll never get to this point. kernel= +obj= case $cpu-$vendor in score-*) - os=elf + os= + obj=elf ;; spu-*) - os=elf + os= + obj=elf ;; *-acorn) os=riscix1.2 @@ -1525,28 +1538,35 @@ case $cpu-$vendor in os=gnu ;; arm*-semi) - os=aout + os= + obj=aout ;; c4x-* | tic4x-*) - os=coff + os= + obj=coff ;; c8051-*) - os=elf + os= + obj=elf ;; clipper-intergraph) os=clix ;; hexagon-*) - os=elf + os= + obj=elf ;; tic54x-*) - os=coff + os= + obj=coff ;; tic55x-*) - os=coff + os= + obj=coff ;; tic6x-*) - os=coff + os= + obj=coff ;; # This must come before the *-dec entry. pdp10-*) @@ -1568,19 +1588,24 @@ case $cpu-$vendor in os=sunos3 ;; m68*-cisco) - os=aout + os= + obj=aout ;; mep-*) - os=elf + os= + obj=elf ;; mips*-cisco) - os=elf + os= + obj=elf ;; - mips*-*) - os=elf + mips*-*|nanomips*-*) + os= + obj=elf ;; or32-*) - os=coff + os= + obj=coff ;; *-tti) # must be before sparc entry or we get the wrong os. os=sysv3 @@ -1589,7 +1614,8 @@ case $cpu-$vendor in os=sunos4.1.1 ;; pru-*) - os=elf + os= + obj=elf ;; *-be) os=beos @@ -1670,10 +1696,12 @@ case $cpu-$vendor in os=uxpv ;; *-rom68k) - os=coff + os= + obj=coff ;; *-*bug) - os=coff + os= + obj=coff ;; *-apple) os=macos @@ -1691,10 +1719,11 @@ esac fi -# Now, validate our (potentially fixed-up) OS. +# Now, validate our (potentially fixed-up) individual pieces (OS, OBJ). + case $os in # Sometimes we do "kernel-libc", so those need to count as OSes. - musl* | newlib* | relibc* | uclibc*) + llvm* | musl* | newlib* | relibc* | uclibc*) ;; # Likewise for "kernel-abi" eabi* | gnueabi*) @@ -1702,6 +1731,9 @@ case $os in # VxWorks passes extra cpu info in the 4th filed. simlinux | simwindows | spe) ;; + # See `case $cpu-$os` validation below + ghcjs) + ;; # Now accept the basic system types. # The portable systems comes first. # Each alternative MUST end in a * to match a version number. @@ -1719,11 +1751,11 @@ case $os in | mirbsd* | netbsd* | dicos* | openedition* | ose* \ | bitrig* | openbsd* | secbsd* | solidbsd* | libertybsd* | os108* \ | ekkobsd* | freebsd* | riscix* | lynxos* | os400* \ - | bosx* | nextstep* | cxux* | aout* | elf* | oabi* \ - | ptx* | coff* | ecoff* | winnt* | domain* | vsta* \ + | bosx* | nextstep* | cxux* | oabi* \ + | ptx* | ecoff* | winnt* | domain* | vsta* \ | udi* | lites* | ieee* | go32* | aux* | hcos* \ | chorusrdb* | cegcc* | glidix* | serenity* \ - | cygwin* | msys* | pe* | moss* | proelf* | rtems* \ + | cygwin* | msys* | moss* | proelf* | rtems* \ | midipix* | mingw32* | mingw64* | mint* \ | uxpv* | beos* | mpeix* | udk* | moxiebox* \ | interix* | uwin* | mks* | rhapsody* | darwin* \ @@ -1736,71 +1768,115 @@ case $os in | onefs* | tirtos* | phoenix* | fuchsia* | redox* | bme* \ | midnightbsd* | amdhsa* | unleashed* | emscripten* | wasi* \ | nsk* | powerunix* | genode* | zvmoe* | qnx* | emx* | zephyr* \ - | fiwix* | mlibc* | cos* | mbr* ) + | fiwix* | mlibc* | cos* | mbr* | ironclad* ) ;; # This one is extra strict with allowed versions sco3.2v2 | sco3.2v[4-9]* | sco5v6*) # Don't forget version if it is 3.2v4 or newer. ;; + # This refers to builds using the UEFI calling convention + # (which depends on the architecture) and PE file format. + # Note that this is both a different calling convention and + # different file format than that of GNU-EFI + # (x86_64-w64-mingw32). + uefi) + ;; none) ;; kernel* | msvc* ) # Restricted further below ;; + '') + if test x"$obj" = x + then + echo "Invalid configuration '$1': Blank OS only allowed with explicit machine code file format" 1>&2 + fi + ;; *) echo "Invalid configuration '$1': OS '$os' not recognized" 1>&2 exit 1 ;; esac +case $obj in + aout* | coff* | elf* | pe*) + ;; + '') + # empty is fine + ;; + *) + echo "Invalid configuration '$1': Machine code format '$obj' not recognized" 1>&2 + exit 1 + ;; +esac + +# Here we handle the constraint that a (synthetic) cpu and os are +# valid only in combination with each other and nowhere else. +case $cpu-$os in + # The "javascript-unknown-ghcjs" triple is used by GHC; we + # accept it here in order to tolerate that, but reject any + # variations. + javascript-ghcjs) + ;; + javascript-* | *-ghcjs) + echo "Invalid configuration '$1': cpu '$cpu' is not valid with os '$os$obj'" 1>&2 + exit 1 + ;; +esac + # As a final step for OS-related things, validate the OS-kernel combination # (given a valid OS), if there is a kernel. -case $kernel-$os in - linux-gnu* | linux-dietlibc* | linux-android* | linux-newlib* \ - | linux-musl* | linux-relibc* | linux-uclibc* | linux-mlibc* ) +case $kernel-$os-$obj in + linux-gnu*- | linux-android*- | linux-dietlibc*- | linux-llvm*- \ + | linux-mlibc*- | linux-musl*- | linux-newlib*- \ + | linux-relibc*- | linux-uclibc*- ) ;; - uclinux-uclibc* ) + uclinux-uclibc*- ) ;; - managarm-mlibc* | managarm-kernel* ) + managarm-mlibc*- | managarm-kernel*- ) ;; - windows*-gnu* | windows*-msvc*) + windows*-msvc*-) ;; - -dietlibc* | -newlib* | -musl* | -relibc* | -uclibc* | -mlibc* ) + -dietlibc*- | -llvm*- | -mlibc*- | -musl*- | -newlib*- | -relibc*- \ + | -uclibc*- ) # These are just libc implementations, not actual OSes, and thus # require a kernel. echo "Invalid configuration '$1': libc '$os' needs explicit kernel." 1>&2 exit 1 ;; - -kernel* ) + -kernel*- ) echo "Invalid configuration '$1': '$os' needs explicit kernel." 1>&2 exit 1 ;; - *-kernel* ) + *-kernel*- ) echo "Invalid configuration '$1': '$kernel' does not support '$os'." 1>&2 exit 1 ;; - *-msvc* ) + *-msvc*- ) echo "Invalid configuration '$1': '$os' needs 'windows'." 1>&2 exit 1 ;; - kfreebsd*-gnu* | kopensolaris*-gnu*) + kfreebsd*-gnu*- | kopensolaris*-gnu*-) ;; - vxworks-simlinux | vxworks-simwindows | vxworks-spe) + vxworks-simlinux- | vxworks-simwindows- | vxworks-spe-) ;; - nto-qnx*) + nto-qnx*-) ;; - os2-emx) + os2-emx-) ;; - *-eabi* | *-gnueabi*) + *-eabi*- | *-gnueabi*-) ;; - none-coff* | none-elf*) + none--*) # None (no kernel, i.e. freestanding / bare metal), - # can be paired with an output format "OS" + # can be paired with an machine code file format ;; - -*) + -*-) # Blank kernel with real OS is always fine. ;; - *-*) + --*) + # Blank kernel and OS with real machine code file format is always fine. + ;; + *-*-*) echo "Invalid configuration '$1': Kernel '$kernel' not known to work with OS '$os'." 1>&2 exit 1 ;; @@ -1884,7 +1960,7 @@ case $vendor in ;; esac -echo "$cpu-$vendor-${kernel:+$kernel-}$os" +echo "$cpu-$vendor${kernel:+-$kernel}${os:+-$os}${obj:+-$obj}" exit # Local variables: diff --git a/usr.sbin/unbound/configure b/usr.sbin/unbound/configure index b3d4ee34d4a..ffb845d7b6a 100644 --- a/usr.sbin/unbound/configure +++ b/usr.sbin/unbound/configure @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.69 for unbound 1.18.0. +# Generated by GNU Autoconf 2.69 for unbound 1.19.2. # # Report bugs to <unbound-bugs@nlnetlabs.nl or https://github.com/NLnetLabs/unbound/issues>. # @@ -591,8 +591,8 @@ MAKEFLAGS= # Identity of this package. PACKAGE_NAME='unbound' PACKAGE_TARNAME='unbound' -PACKAGE_VERSION='1.18.0' -PACKAGE_STRING='unbound 1.18.0' +PACKAGE_VERSION='1.19.2' +PACKAGE_STRING='unbound 1.19.2' PACKAGE_BUGREPORT='unbound-bugs@nlnetlabs.nl or https://github.com/NLnetLabs/unbound/issues' PACKAGE_URL='' @@ -1477,7 +1477,7 @@ if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures unbound 1.18.0 to adapt to many kinds of systems. +\`configure' configures unbound 1.19.2 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1543,7 +1543,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of unbound 1.18.0:";; + short | recursive ) echo "Configuration of unbound 1.19.2:";; esac cat <<\_ACEOF @@ -1785,7 +1785,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -unbound configure 1.18.0 +unbound configure 1.19.2 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. @@ -2494,7 +2494,7 @@ cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by unbound $as_me 1.18.0, which was +It was created by unbound $as_me 1.19.2, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ @@ -2844,13 +2844,13 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu UNBOUND_VERSION_MAJOR=1 -UNBOUND_VERSION_MINOR=18 +UNBOUND_VERSION_MINOR=19 -UNBOUND_VERSION_MICRO=0 +UNBOUND_VERSION_MICRO=2 LIBUNBOUND_CURRENT=9 -LIBUNBOUND_REVISION=22 +LIBUNBOUND_REVISION=25 LIBUNBOUND_AGE=1 # 1.0.0 had 0:12:0 # 1.0.1 had 0:13:0 @@ -2940,6 +2940,9 @@ LIBUNBOUND_AGE=1 # 1.17.0 had 9:20:1 # 1.17.1 had 9:21:1 # 1.18.0 had 9:22:1 +# 1.19.0 had 9:23:1 +# 1.19.1 had 9:24:1 +# 1.19.2 had 9:25:1 # Current -- the number of the binary API that we're implementing # Revision -- which iteration of the implementation of the binary @@ -4604,450 +4607,186 @@ fi default_cflags=yes fi -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu -if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. -set dummy ${ac_tool_prefix}gcc; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_CC+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$CC"; then - ac_cv_prog_CC="$CC" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_CC="${ac_tool_prefix}gcc" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -CC=$ac_cv_prog_CC -if test -n "$CC"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 -$as_echo "$CC" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - -fi -if test -z "$ac_cv_prog_CC"; then - ac_ct_CC=$CC - # Extract the first word of "gcc", so it can be a program name with args. -set dummy gcc; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_ac_ct_CC+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$ac_ct_CC"; then - ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_ac_ct_CC="gcc" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -ac_ct_CC=$ac_cv_prog_ac_ct_CC -if test -n "$ac_ct_CC"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 -$as_echo "$ac_ct_CC" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - if test "x$ac_ct_CC" = x; then - CC="" - else - case $cross_compiling:$ac_tool_warned in -yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} -ac_tool_warned=yes ;; -esac - CC=$ac_ct_CC - fi -else - CC="$ac_cv_prog_CC" -fi - -if test -z "$CC"; then - if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. -set dummy ${ac_tool_prefix}cc; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_CC+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$CC"; then - ac_cv_prog_CC="$CC" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_CC="${ac_tool_prefix}cc" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -CC=$ac_cv_prog_CC -if test -n "$CC"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 -$as_echo "$CC" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - - fi -fi -if test -z "$CC"; then - # Extract the first word of "cc", so it can be a program name with args. -set dummy cc; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_CC+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$CC"; then - ac_cv_prog_CC="$CC" # Let the user override the test. -else - ac_prog_rejected=no -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then - ac_prog_rejected=yes - continue - fi - ac_cv_prog_CC="cc" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -if test $ac_prog_rejected = yes; then - # We found a bogon in the path, so make sure we never use it. - set dummy $ac_cv_prog_CC - shift - if test $# != 0; then - # We chose a different compiler from the bogus one. - # However, it has the same basename, so the bogon will be chosen - # first if we set CC to just the basename; use the full file name. - shift - ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" - fi -fi -fi -fi -CC=$ac_cv_prog_CC -if test -n "$CC"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 -$as_echo "$CC" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - -fi -if test -z "$CC"; then - if test -n "$ac_tool_prefix"; then - for ac_prog in cl.exe - do - # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. -set dummy $ac_tool_prefix$ac_prog; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_CC+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$CC"; then - ac_cv_prog_CC="$CC" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_CC="$ac_tool_prefix$ac_prog" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -CC=$ac_cv_prog_CC -if test -n "$CC"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 -$as_echo "$CC" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - - test -n "$CC" && break - done -fi -if test -z "$CC"; then - ac_ct_CC=$CC - for ac_prog in cl.exe -do - # Extract the first word of "$ac_prog", so it can be a program name with args. -set dummy $ac_prog; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_ac_ct_CC+:} false; then : + case $ac_cv_prog_cc_stdc in #( + no) : + ac_cv_prog_cc_c99=no; ac_cv_prog_cc_c89=no ;; #( + *) : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C99" >&5 +$as_echo_n "checking for $CC option to accept ISO C99... " >&6; } +if ${ac_cv_prog_cc_c99+:} false; then : $as_echo_n "(cached) " >&6 else - if test -n "$ac_ct_CC"; then - ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_ac_ct_CC="$ac_prog" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS + ac_cv_prog_cc_c99=no +ac_save_CC=$CC +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <stdarg.h> +#include <stdbool.h> +#include <stdlib.h> +#include <wchar.h> +#include <stdio.h> -fi -fi -ac_ct_CC=$ac_cv_prog_ac_ct_CC -if test -n "$ac_ct_CC"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 -$as_echo "$ac_ct_CC" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi +// Check varargs macros. These examples are taken from C99 6.10.3.5. +#define debug(...) fprintf (stderr, __VA_ARGS__) +#define showlist(...) puts (#__VA_ARGS__) +#define report(test,...) ((test) ? puts (#test) : printf (__VA_ARGS__)) +static void +test_varargs_macros (void) +{ + int x = 1234; + int y = 5678; + debug ("Flag"); + debug ("X = %d\n", x); + showlist (The first, second, and third items.); + report (x>y, "x is %d but y is %d", x, y); +} +// Check long long types. +#define BIG64 18446744073709551615ull +#define BIG32 4294967295ul +#define BIG_OK (BIG64 / BIG32 == 4294967297ull && BIG64 % BIG32 == 0) +#if !BIG_OK + your preprocessor is broken; +#endif +#if BIG_OK +#else + your preprocessor is broken; +#endif +static long long int bignum = -9223372036854775807LL; +static unsigned long long int ubignum = BIG64; - test -n "$ac_ct_CC" && break -done +struct incomplete_array +{ + int datasize; + double data[]; +}; - if test "x$ac_ct_CC" = x; then - CC="" - else - case $cross_compiling:$ac_tool_warned in -yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} -ac_tool_warned=yes ;; -esac - CC=$ac_ct_CC - fi -fi +struct named_init { + int number; + const wchar_t *name; + double average; +}; -fi +typedef const char *ccp; +static inline int +test_restrict (ccp restrict text) +{ + // See if C++-style comments work. + // Iterate through items via the restricted pointer. + // Also check for declarations in for loops. + for (unsigned int i = 0; *(text+i) != '\0'; ++i) + continue; + return 0; +} -test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error $? "no acceptable C compiler found in \$PATH -See \`config.log' for more details" "$LINENO" 5; } +// Check varargs and va_copy. +static void +test_varargs (const char *format, ...) +{ + va_list args; + va_start (args, format); + va_list args_copy; + va_copy (args_copy, args); -# Provide some information about the compiler. -$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 -set X $ac_compile -ac_compiler=$2 -for ac_option in --version -v -V -qversion; do - { { ac_try="$ac_compiler $ac_option >&5" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_compiler $ac_option >&5") 2>conftest.err - ac_status=$? - if test -s conftest.err; then - sed '10a\ -... rest of stderr output deleted ... - 10q' conftest.err >conftest.er1 - cat conftest.er1 >&5 - fi - rm -f conftest.er1 conftest.err - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } -done + const char *str; + int number; + float fnumber; -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 -$as_echo_n "checking whether we are using the GNU C compiler... " >&6; } -if ${ac_cv_c_compiler_gnu+:} false; then : - $as_echo_n "(cached) " >&6 -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ + while (*format) + { + switch (*format++) + { + case 's': // string + str = va_arg (args_copy, const char *); + break; + case 'd': // int + number = va_arg (args_copy, int); + break; + case 'f': // float + fnumber = va_arg (args_copy, double); + break; + default: + break; + } + } + va_end (args_copy); + va_end (args); +} int main () { -#ifndef __GNUC__ - choke me -#endif - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - ac_compiler_gnu=yes -else - ac_compiler_gnu=no -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -ac_cv_c_compiler_gnu=$ac_compiler_gnu + // Check bool. + _Bool success = false; -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 -$as_echo "$ac_cv_c_compiler_gnu" >&6; } -if test $ac_compiler_gnu = yes; then - GCC=yes -else - GCC= -fi -ac_test_CFLAGS=${CFLAGS+set} -ac_save_CFLAGS=$CFLAGS -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 -$as_echo_n "checking whether $CC accepts -g... " >&6; } -if ${ac_cv_prog_cc_g+:} false; then : - $as_echo_n "(cached) " >&6 -else - ac_save_c_werror_flag=$ac_c_werror_flag - ac_c_werror_flag=yes - ac_cv_prog_cc_g=no - CFLAGS="-g" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ + // Check restrict. + if (test_restrict ("String literal") == 0) + success = true; + char *restrict newvar = "Another string"; -int -main () -{ + // Check varargs. + test_varargs ("s, d' f .", "string", 65, 34.234); + test_varargs_macros (); - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - ac_cv_prog_cc_g=yes -else - CFLAGS="" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ + // Check flexible array members. + struct incomplete_array *ia = + malloc (sizeof (struct incomplete_array) + (sizeof (double) * 10)); + ia->datasize = 10; + for (int i = 0; i < ia->datasize; ++i) + ia->data[i] = i * 1.234; -int -main () -{ + // Check named initializers. + struct named_init ni = { + .number = 34, + .name = L"Test wide string", + .average = 543.34343, + }; - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : + ni.number = 58; -else - ac_c_werror_flag=$ac_save_c_werror_flag - CFLAGS="-g" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ + int dynamic_array[ni.number]; + dynamic_array[ni.number - 1] = 543; -int -main () -{ + // work around unused variable warnings + return (!success || bignum == 0LL || ubignum == 0uLL || newvar[0] == 'x' + || dynamic_array[ni.number - 1] != 543); ; return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - ac_cv_prog_cc_g=yes -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +for ac_arg in '' -std=gnu99 -std=c99 -c99 -AC99 -D_STDC_C99= -qlanglvl=extc99 +do + CC="$ac_save_CC $ac_arg" + if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_c99=$ac_arg fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - ac_c_werror_flag=$ac_save_c_werror_flag +rm -f core conftest.err conftest.$ac_objext + test "x$ac_cv_prog_cc_c99" != "xno" && break +done +rm -f conftest.$ac_ext +CC=$ac_save_CC + fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 -$as_echo "$ac_cv_prog_cc_g" >&6; } -if test "$ac_test_CFLAGS" = set; then - CFLAGS=$ac_save_CFLAGS -elif test $ac_cv_prog_cc_g = yes; then - if test "$GCC" = yes; then - CFLAGS="-g -O2" - else - CFLAGS="-g" - fi +# AC_CACHE_VAL +case "x$ac_cv_prog_cc_c99" in + x) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 +$as_echo "none needed" >&6; } ;; + xno) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 +$as_echo "unsupported" >&6; } ;; + *) + CC="$CC $ac_cv_prog_cc_c99" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c99" >&5 +$as_echo "$ac_cv_prog_cc_c99" >&6; } ;; +esac +if test "x$ac_cv_prog_cc_c99" != xno; then : + ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c99 else - if test "$GCC" = yes; then - CFLAGS="-O2" - else - CFLAGS= - fi -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 $as_echo_n "checking for $CC option to accept ISO C89... " >&6; } if ${ac_cv_prog_cc_c89+:} false; then : $as_echo_n "(cached) " >&6 @@ -5134,14 +4873,31 @@ $as_echo "unsupported" >&6; } ;; $as_echo "$ac_cv_prog_cc_c89" >&6; } ;; esac if test "x$ac_cv_prog_cc_c89" != xno; then : + ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c89 +else + ac_cv_prog_cc_stdc=no +fi fi + ;; +esac + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO Standard C" >&5 +$as_echo_n "checking for $CC option to accept ISO Standard C... " >&6; } + if ${ac_cv_prog_cc_stdc+:} false; then : + $as_echo_n "(cached) " >&6 +fi -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu + case $ac_cv_prog_cc_stdc in #( + no) : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 +$as_echo "unsupported" >&6; } ;; #( + '') : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 +$as_echo "none needed" >&6; } ;; #( + *) : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_stdc" >&5 +$as_echo "$ac_cv_prog_cc_stdc" >&6; } ;; +esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking $CC dependency flag" >&5 @@ -16247,10 +16003,7 @@ _ACEOF $as_echo_n "checking whether strptime works... " >&6; } if test c${cross_compiling} = cno; then if test "$cross_compiling" = yes; then : - { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error $? "cannot run test program while cross compiling -See \`config.log' for more details" "$LINENO" 5; } + eval "ac_cv_c_strptime_works=maybe" else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -19039,10 +18792,7 @@ if test -n "$ssldir"; then CFLAGS="$CFLAGS -Wl,-rpath,$ssldir_lib" fi if test "$cross_compiling" = yes; then : - { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error $? "cannot run test program while cross compiling -See \`config.log' for more details" "$LINENO" 5; } + eval "ac_cv_c_gost_works=maybe" else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -20916,10 +20666,8 @@ if test "x$ac_cv_func_snprintf" = xyes; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for correct snprintf return value" >&5 $as_echo_n "checking for correct snprintf return value... " >&6; } if test "$cross_compiling" = yes; then : - { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error $? "cannot run test program while cross compiling -See \`config.log' for more details" "$LINENO" 5; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: maybe" >&5 +$as_echo "maybe" >&6; } else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -21594,7 +21342,7 @@ if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" else - as_fn_error $? "The protobuf-c library was not found. Please install protobuf-c!" "$LINENO" 5 + as_fn_error $? "The protobuf-c library was not found. Please install the development libraries for protobuf-c!" "$LINENO" 5 fi @@ -22148,7 +21896,7 @@ _ACEOF -version=1.18.0 +version=1.19.2 date=`date +'%b %e, %Y'` @@ -22667,7 +22415,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.18.0, which was +This file was extended by unbound $as_me 1.19.2, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -22733,7 +22481,7 @@ _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -unbound config.status 1.18.0 +unbound config.status 1.19.2 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" diff --git a/usr.sbin/unbound/configure.ac b/usr.sbin/unbound/configure.ac index f6bf9104884..b41d7eeafc8 100644 --- a/usr.sbin/unbound/configure.ac +++ b/usr.sbin/unbound/configure.ac @@ -10,15 +10,15 @@ sinclude(dnscrypt/dnscrypt.m4) # must be numbers. ac_defun because of later processing m4_define([VERSION_MAJOR],[1]) -m4_define([VERSION_MINOR],[18]) -m4_define([VERSION_MICRO],[0]) +m4_define([VERSION_MINOR],[19]) +m4_define([VERSION_MICRO],[2]) AC_INIT([unbound],m4_defn([VERSION_MAJOR]).m4_defn([VERSION_MINOR]).m4_defn([VERSION_MICRO]),[unbound-bugs@nlnetlabs.nl or https://github.com/NLnetLabs/unbound/issues],[unbound]) AC_SUBST(UNBOUND_VERSION_MAJOR, [VERSION_MAJOR]) AC_SUBST(UNBOUND_VERSION_MINOR, [VERSION_MINOR]) AC_SUBST(UNBOUND_VERSION_MICRO, [VERSION_MICRO]) LIBUNBOUND_CURRENT=9 -LIBUNBOUND_REVISION=22 +LIBUNBOUND_REVISION=25 LIBUNBOUND_AGE=1 # 1.0.0 had 0:12:0 # 1.0.1 had 0:13:0 @@ -108,6 +108,9 @@ LIBUNBOUND_AGE=1 # 1.17.0 had 9:20:1 # 1.17.1 had 9:21:1 # 1.18.0 had 9:22:1 +# 1.19.0 had 9:23:1 +# 1.19.1 had 9:24:1 +# 1.19.2 had 9:25:1 # Current -- the number of the binary API that we're implementing # Revision -- which iteration of the implementation of the binary @@ -279,7 +282,7 @@ ACX_CHECK_COMPILER_FLAG(g, [CFLAGS="$CFLAGS -g"]) ACX_CHECK_COMPILER_FLAG(O2, [CFLAGS="$CFLAGS -O2"]) default_cflags=yes fi -AC_PROG_CC +m4_version_prereq([2.70], [AC_PROG_CC], [AC_PROG_CC_STDC]) ACX_DEPFLAG ACX_DETERMINE_EXT_FLAGS_UNBOUND @@ -525,7 +528,8 @@ res = strptime("2010-07-15T00:00:00+00:00", "%t%Y%t-%t%m%t-%t%d%tT%t%H%t:%t%M%t: if (!res) return 2; res = strptime("20070207111842", "%Y%m%d%H%M%S", &tm); if (!res) return 1; return 0; } -]])] , [eval "ac_cv_c_strptime_works=yes"], [eval "ac_cv_c_strptime_works=no"]) +]])] , [eval "ac_cv_c_strptime_works=yes"], [eval "ac_cv_c_strptime_works=no"], +[eval "ac_cv_c_strptime_works=maybe"]) else eval "ac_cv_c_strptime_works=maybe" fi @@ -1137,7 +1141,8 @@ int main(void) { return 6; return 0; } -]])] , [eval "ac_cv_c_gost_works=yes"], [eval "ac_cv_c_gost_works=no"]) +]])] , [eval "ac_cv_c_gost_works=yes"], [eval "ac_cv_c_gost_works=no"], +[eval "ac_cv_c_gost_works=maybe"]) CFLAGS="$BAKCFLAGS" else eval "ac_cv_c_gost_works=maybe" @@ -1714,7 +1719,7 @@ int main(void) { return !(snprintf(NULL, 0, "test") == 4); } AC_MSG_RESULT(no) AC_DEFINE([SNPRINTF_RET_BROKEN], [], [define if (v)snprintf does not return length needed, (but length used)]) AC_LIBOBJ(snprintf) - ]) + ], [AC_MSG_RESULT(maybe)]) fi fi AC_REPLACE_FUNCS(strlcat) @@ -1944,7 +1949,7 @@ case "$enable_explicit_port_randomisation" in esac if echo "$host" | $GREP -i -e linux >/dev/null; then - AC_ARG_ENABLE(linux-ip-local-port-range, AC_HELP_STRING([--enable-linux-ip-local-port-range], [Define this to enable use of /proc/sys/net/ipv4/ip_local_port_range as a default outgoing port range. This is only for the libunbound on Linux and does not affect unbound resolving daemon itself. This may severely limit the number of available outgoing ports and thus decrease randomness. Define this only when the target system restricts (e.g. some of SELinux enabled distributions) the use of non-ephemeral ports.])) + AC_ARG_ENABLE(linux-ip-local-port-range, AS_HELP_STRING([--enable-linux-ip-local-port-range], [Define this to enable use of /proc/sys/net/ipv4/ip_local_port_range as a default outgoing port range. This is only for the libunbound on Linux and does not affect unbound resolving daemon itself. This may severely limit the number of available outgoing ports and thus decrease randomness. Define this only when the target system restricts (e.g. some of SELinux enabled distributions) the use of non-ephemeral ports.])) case "$enable_linux_ip_local_port_range" in yes) AC_DEFINE([USE_LINUX_IP_LOCAL_PORT_RANGE], [1], [Define this to enable use of /proc/sys/net/ipv4/ip_local_port_range as a default outgoing port range. This is only for the libunbound on Linux and does not affect unbound resolving daemon itself. This may severely limit the number of available outgoing ports and thus decrease randomness. Define this only when the target system restricts (e.g. some of SELinux enabled distributions) the use of non-ephemeral ports.]) diff --git a/usr.sbin/unbound/daemon/remote.c b/usr.sbin/unbound/daemon/remote.c index 4990fc8e919..3eb711ce642 100644 --- a/usr.sbin/unbound/daemon/remote.c +++ b/usr.sbin/unbound/daemon/remote.c @@ -523,12 +523,13 @@ ssl_print_text(RES* res, const char* text) if(res->ssl) { ERR_clear_error(); if((r=SSL_write(res->ssl, text, (int)strlen(text))) <= 0) { - if(SSL_get_error(res->ssl, r) == SSL_ERROR_ZERO_RETURN) { + int r2; + if((r2=SSL_get_error(res->ssl, r)) == SSL_ERROR_ZERO_RETURN) { verbose(VERB_QUERY, "warning, in SSL_write, peer " "closed connection"); return 0; } - log_crypto_err("could not SSL_write"); + log_crypto_err_io("could not SSL_write", r2); return 0; } } else { @@ -579,11 +580,12 @@ ssl_read_line(RES* res, char* buf, size_t max) if(res->ssl) { ERR_clear_error(); if((r=SSL_read(res->ssl, buf+len, 1)) <= 0) { - if(SSL_get_error(res->ssl, r) == SSL_ERROR_ZERO_RETURN) { + int r2; + if((r2=SSL_get_error(res->ssl, r)) == SSL_ERROR_ZERO_RETURN) { buf[len] = 0; return 1; } - log_crypto_err("could not SSL_read"); + log_crypto_err_io("could not SSL_read", r2); return 0; } } else { @@ -596,7 +598,7 @@ ssl_read_line(RES* res, char* buf, size_t max) } if(errno == EINTR || errno == EAGAIN) continue; - log_err("could not recv: %s", + if(rr < 0) log_err("could not recv: %s", sock_strerror(errno)); return 0; } @@ -1223,8 +1225,8 @@ do_zones_add(RES* ssl, struct local_zones* zones) char buf[2048]; int num = 0; while(ssl_read_line(ssl, buf, sizeof(buf))) { - if(buf[0] == 0x04 && buf[1] == 0) - break; /* end of transmission */ + if(buf[0] == 0 || (buf[0] == 0x04 && buf[1] == 0)) + break; /* zero byte line or end of transmission */ if(!perform_zone_add(ssl, zones, buf)) { if(!ssl_printf(ssl, "error for input line: %s\n", buf)) return; @@ -1272,8 +1274,8 @@ do_zones_remove(RES* ssl, struct local_zones* zones) char buf[2048]; int num = 0; while(ssl_read_line(ssl, buf, sizeof(buf))) { - if(buf[0] == 0x04 && buf[1] == 0) - break; /* end of transmission */ + if(buf[0] == 0 || (buf[0] == 0x04 && buf[1] == 0)) + break; /* zero byte line or end of transmission */ if(!perform_zone_remove(ssl, zones, buf)) { if(!ssl_printf(ssl, "error for input line: %s\n", buf)) return; @@ -1336,8 +1338,8 @@ do_datas_add(RES* ssl, struct local_zones* zones) char buf[2048]; int num = 0, line = 0; while(ssl_read_line(ssl, buf, sizeof(buf))) { - if(buf[0] == 0x04 && buf[1] == 0) - break; /* end of transmission */ + if(buf[0] == 0 || (buf[0] == 0x04 && buf[1] == 0)) + break; /* zero byte line or end of transmission */ line++; if(perform_data_add(ssl, zones, buf, line)) num++; @@ -1376,8 +1378,8 @@ do_datas_remove(RES* ssl, struct local_zones* zones) char buf[2048]; int num = 0; while(ssl_read_line(ssl, buf, sizeof(buf))) { - if(buf[0] == 0x04 && buf[1] == 0) - break; /* end of transmission */ + if(buf[0] == 0 || (buf[0] == 0x04 && buf[1] == 0)) + break; /* zero byte line or end of transmission */ if(!perform_data_remove(ssl, zones, buf)) { if(!ssl_printf(ssl, "error for input line: %s\n", buf)) return; @@ -3222,9 +3224,10 @@ handle_req(struct daemon_remote* rc, struct rc_state* s, RES* res) if(res->ssl) { ERR_clear_error(); if((r=SSL_read(res->ssl, magic, (int)sizeof(magic)-1)) <= 0) { - if(SSL_get_error(res->ssl, r) == SSL_ERROR_ZERO_RETURN) + int r2; + if((r2=SSL_get_error(res->ssl, r)) == SSL_ERROR_ZERO_RETURN) return; - log_crypto_err("could not SSL_read"); + log_crypto_err_io("could not SSL_read", r2); return; } } else { @@ -3291,7 +3294,7 @@ remote_handshake_later(struct daemon_remote* rc, struct rc_state* s, log_err("remote control connection closed prematurely"); log_addr(VERB_OPS, "failed connection from", &s->c->repinfo.remote_addr, s->c->repinfo.remote_addrlen); - log_crypto_err("remote control failed ssl"); + log_crypto_err_io("remote control failed ssl", r2); clean_point(rc, s); } return 0; diff --git a/usr.sbin/unbound/daemon/worker.c b/usr.sbin/unbound/daemon/worker.c index 8c6fa3b9af3..8ae05eb67e6 100644 --- a/usr.sbin/unbound/daemon/worker.c +++ b/usr.sbin/unbound/daemon/worker.c @@ -66,6 +66,7 @@ #include "util/data/msgencode.h" #include "util/data/dname.h" #include "util/fptr_wlist.h" +#include "util/proxy_protocol.h" #include "util/tube.h" #include "util/edns.h" #include "util/timeval_func.h" @@ -542,6 +543,8 @@ answer_norec_from_cache(struct worker* worker, struct query_info* qinfo, edns->udp_size = EDNS_ADVERTISED_SIZE; edns->ext_rcode = 0; edns->bits &= EDNS_DO; + if(worker->env.cfg->disable_edns_do && (edns->bits & EDNS_DO)) + edns->edns_present = 0; if(!inplace_cb_reply_cache_call(&worker->env, qinfo, NULL, msg->rep, (int)(flags&LDNS_RCODE_MASK), edns, repinfo, worker->scratchpad, worker->env.now_tv)) @@ -702,6 +705,8 @@ answer_from_cache(struct worker* worker, struct query_info* qinfo, edns->udp_size = EDNS_ADVERTISED_SIZE; edns->ext_rcode = 0; edns->bits &= EDNS_DO; + if(worker->env.cfg->disable_edns_do && (edns->bits & EDNS_DO)) + edns->edns_present = 0; if(!inplace_cb_reply_servfail_call(&worker->env, qinfo, NULL, rep, LDNS_RCODE_SERVFAIL, edns, repinfo, worker->scratchpad, worker->env.now_tv)) @@ -742,6 +747,8 @@ answer_from_cache(struct worker* worker, struct query_info* qinfo, edns->udp_size = EDNS_ADVERTISED_SIZE; edns->ext_rcode = 0; edns->bits &= EDNS_DO; + if(worker->env.cfg->disable_edns_do && (edns->bits & EDNS_DO)) + edns->edns_present = 0; *alias_rrset = NULL; /* avoid confusion if caller set it to non-NULL */ if((worker->daemon->use_response_ip || worker->daemon->use_rpz) && !partial_rep && !apply_respip_action(worker, qinfo, cinfo, rep, @@ -2317,6 +2324,7 @@ worker_init(struct worker* worker, struct config_file *cfg, worker->env.cfg->stat_interval); worker_restart_timer(worker); } + pp_init(&sldns_write_uint16, &sldns_write_uint32); return 1; } diff --git a/usr.sbin/unbound/dns64/dns64.c b/usr.sbin/unbound/dns64/dns64.c index 1e31f51e831..83fb027790e 100644 --- a/usr.sbin/unbound/dns64/dns64.c +++ b/usr.sbin/unbound/dns64/dns64.c @@ -573,28 +573,29 @@ static enum module_ext_state handle_event_pass(struct module_qstate* qstate, int id) { struct dns64_qstate* iq = (struct dns64_qstate*)qstate->minfo[id]; - if (iq && iq->state == DNS64_NEW_QUERY - && qstate->qinfo.qtype == LDNS_RR_TYPE_PTR - && qstate->qinfo.qname_len == 74 - && !strcmp((char*)&qstate->qinfo.qname[64], "\03ip6\04arpa")) - /* Handle PTR queries for IPv6 addresses. */ - return handle_ipv6_ptr(qstate, id); - - if (qstate->env->cfg->dns64_synthall && - iq && iq->state == DNS64_NEW_QUERY - && qstate->qinfo.qtype == LDNS_RR_TYPE_AAAA) - return generate_type_A_query(qstate, id); + int synth_all_cfg = qstate->env->cfg->dns64_synthall; + int synth_qname = 0; + + if(iq && iq->state == DNS64_NEW_QUERY + && qstate->qinfo.qtype == LDNS_RR_TYPE_PTR + && qstate->qinfo.qname_len == 74 + && !strcmp((char*)&qstate->qinfo.qname[64], "\03ip6\04arpa")) { + /* Handle PTR queries for IPv6 addresses. */ + return handle_ipv6_ptr(qstate, id); + } - if(dns64_always_synth_for_qname(qstate, id) && - iq && iq->state == DNS64_NEW_QUERY - && !(qstate->query_flags & BIT_CD) - && qstate->qinfo.qtype == LDNS_RR_TYPE_AAAA) { - verbose(VERB_ALGO, "dns64: ignore-aaaa and synthesize anyway"); + if(iq && iq->state == DNS64_NEW_QUERY && + qstate->qinfo.qtype == LDNS_RR_TYPE_AAAA && + (synth_all_cfg || + (synth_qname=(dns64_always_synth_for_qname(qstate, id) + && !(qstate->query_flags & BIT_CD))))) { + if(synth_qname) + verbose(VERB_ALGO, "dns64: ignore-aaaa and synthesize anyway"); return generate_type_A_query(qstate, id); } /* We are finished when our sub-query is finished. */ - if (iq && iq->state == DNS64_SUBQUERY_FINISHED) + if(iq && iq->state == DNS64_SUBQUERY_FINISHED) return module_finished; /* Otherwise, pass request to next module. */ @@ -627,32 +628,37 @@ handle_event_moddone(struct module_qstate* qstate, int id) * synthesize in (sec 5.1.2 of RFC6147). * - A successful AAAA query with an answer. */ - if((!iq || iq->state != DNS64_INTERNAL_QUERY) - && qstate->qinfo.qtype == LDNS_RR_TYPE_AAAA - && !(qstate->query_flags & BIT_CD) - && !(qstate->return_msg && - qstate->return_msg->rep && - reply_find_answer_rrset(&qstate->qinfo, - qstate->return_msg->rep))) - /* not internal, type AAAA, not CD, and no answer RRset, - * So, this is a AAAA noerror/nodata answer */ - return generate_type_A_query(qstate, id); - if((!iq || iq->state != DNS64_INTERNAL_QUERY) - && qstate->qinfo.qtype == LDNS_RR_TYPE_AAAA - && !(qstate->query_flags & BIT_CD) - && dns64_always_synth_for_qname(qstate, id)) { - /* if it is not internal, AAAA, not CD and listed domain, - * generate from A record and ignore AAAA */ - verbose(VERB_ALGO, "dns64: ignore-aaaa and synthesize anyway"); + /* When an AAAA query completes check if we want to perform DNS64 + * synthesis. We skip queries with DNSSEC enabled (!CD) and + * ones generated by us to retrive the A/PTR record to use for + * synth. */ + int could_synth = + qstate->qinfo.qtype == LDNS_RR_TYPE_AAAA && + (!iq || iq->state != DNS64_INTERNAL_QUERY) && + !(qstate->query_flags & BIT_CD); + int has_data = /* whether query returned non-empty rrset */ + qstate->return_msg && + qstate->return_msg->rep && + reply_find_answer_rrset(&qstate->qinfo, qstate->return_msg->rep); + int synth_qname = 0; + + if(could_synth && + (!has_data || + (synth_qname=dns64_always_synth_for_qname(qstate, id)))) { + if(synth_qname) + verbose(VERB_ALGO, "dns64: ignore-aaaa and synthesize anyway"); return generate_type_A_query(qstate, id); } /* Store the response in cache. */ - if ( (!iq || !iq->started_no_cache_store) && - qstate->return_msg && qstate->return_msg->rep && - !dns_cache_store(qstate->env, &qstate->qinfo, qstate->return_msg->rep, - 0, 0, 0, NULL, qstate->query_flags, qstate->qstarttime)) + if( (!iq || !iq->started_no_cache_store) && + qstate->return_msg && + qstate->return_msg->rep && + !dns_cache_store( + qstate->env, &qstate->qinfo, qstate->return_msg->rep, + 0, 0, 0, NULL, + qstate->query_flags, qstate->qstarttime)) log_err("out of memory"); /* do nothing */ @@ -969,10 +975,19 @@ dns64_inform_super(struct module_qstate* qstate, int id, } super_dq->state = DNS64_SUBQUERY_FINISHED; - /* If there is no successful answer, we're done. */ - if (qstate->return_rcode != LDNS_RCODE_NOERROR - || !qstate->return_msg - || !qstate->return_msg->rep) { + /* If there is no successful answer, we're done. + * Guarantee that we have at least a NOERROR reply further on. */ + if(qstate->return_rcode != LDNS_RCODE_NOERROR + || !qstate->return_msg + || !qstate->return_msg->rep) { + return; + } + + /* When no A record is found for synthesis fall back to AAAA again. */ + if(qstate->qinfo.qtype == LDNS_RR_TYPE_A && + !reply_find_answer_rrset(&qstate->qinfo, + qstate->return_msg->rep)) { + super_dq->state = DNS64_INTERNAL_QUERY; return; } diff --git a/usr.sbin/unbound/doc/Changelog b/usr.sbin/unbound/doc/Changelog index be48561d8f4..05112e898a3 100644 --- a/usr.sbin/unbound/doc/Changelog +++ b/usr.sbin/unbound/doc/Changelog @@ -1,13 +1,158 @@ +2 November 2023: Wouter + - Set version number to 1.19.0. + - Tag for 1.19.0rc1 release. + +1 November 2023: George + - Mention flex and bison in README.md when building from repository + source. + +1 November 2023: Wouter + - Fix SSL compile failure for definition in log_crypto_err_io_code_arg. + - Fix SSL compile failure for other missing definitions in + log_crypto_err_io_code_arg. + - Fix compilation without openssl, remove unused function warning. + +31 October 2023: George + - Fix #941: dnscrypt doesn't work after upgrade to 1.18 with + suggestion by dukeartem to also fix the udp_ancil with dnscrypt. + +30 October 2023: George + - Merge #930 from Stuart Henderson: add void to + log_ident_revert_to_default declaration. + +30 October 2023: Wouter + - autoconf. + +24 October 2023: George + - Clearer configure text for missing protobuf-c development libraries. + +20 October 2023: Wouter + - Merge #951: Cachedb no store. The cachedb-no-store: yes option is + used to stop cachedb from writing messages to the backend storage. + It reads messages when data is available from the backend. The + default is no. + +19 October 2023: Wouter + - Fix to print detailed errors when an SSL IO routine fails via + SSL_get_error. + +18 October 2023: George + - Mailing list patches from Daniel Gröber for DNS64 fallback to plain + AAAA when no A record exists for synthesis, and minor DNS64 code + refactoring for better readability. + - Fixes for the DNS64 patches. + - Update the dns64_lookup.rpl test for the DNS64 fallback patch. + - Merge #955 from buevsan: fix ipset wrong behavior. + - Update testdata/ipset.tdir test for ipset fix. + +17 October 2023: Wouter + - Fix #954: Inconsistent RPZ handling for A record returned along with + CNAME. + +16 October 2023: George + - Expose the script filename in the Python module environment 'mod_env' + instead of the config_file structure which includes the linked list + of scripts in a multi Python module setup; fixes #79. + - Expose the configured listening and outgoing interfaces, if any, as + a list of strings in the Python 'config_file' class instead of the + current Swig object proxy; fixes #79. + - For multi Python module setups, clean previously parsed module + functions in __main__'s dictionary, if any, so that only current + module functions are registered. + +13 October 2023: George + - Better fix for infinite loop when reading multiple lines of input on + a broken remote control socket, by treating a zero byte line the + same as transmission end. Addesses #947 and #948. + +12 October 2023: Wouter + - Merge #944: Disable EDNS DO. + Disable the EDNS DO flag in upstream requests. This can be helpful + for devices that cannot handle DNSSEC information. But it should not + be enabled otherwise, because that would stop DNSSEC validation. The + DNSSEC validation would not work for Unbound itself, and also not + for downstream users. Default is no. The option + is disable-edns-do: no + +11 October 2023: George + - Fix #850: [FR] Ability to use specific database in Redis, with new + redis-logical-db configuration option. + +11 October 2023: Wouter + - Fix #949: "could not create control compt". + - Fix that cachedb does not warn when serve-expired is disabled about + use of serve-expired-reply-ttl and serve-expired-client-timeout. + - Fix for #949: Fix pythonmod/ubmodule-tst.py for Python 3.x. + +10 October 2023: George + - Fix infinite loop when reading multiple lines of input on a broken + remote control socket. Addesses #947 and #948. + +9 October 2023: Wouter + - Fix edns subnet so that queries with a source prefix of zero cause + the recursor send no edns subnet option to the upstream. + - Fix that printout of EDNS options shows the EDNS cookie option by + name. + +4 October 2023: Wouter + - Fix #946: Forwarder returns servfail on upstream response noerror no + data. + +3 October 2023: George + - Merge #881: Generalise the proxy protocol code. + +2 October 2023: George + - Fix misplaced comment. + +22 September 2023: Wouter + - Fix #942: 1.18.0 libunbound DNS regression when built without + OpenSSL. + +18 September 2023: Wouter + - Fix rpz tcp-only action with rpz triggers nsdname and nsip. + +15 September 2023: Wouter + - Merge #936: Check for c99 with autoconf versions prior to 2.70. + - Fix to remove two c99 notations. + +14 September 2023: Wouter + - Fix authority zone answers for obscured DNAMEs and delegations. + 8 September 2023: Wouter - Fix send of udp retries when ENOBUFS is returned. It stops looping and also waits for the condition to go away. Reported by Florian Obser. +7 September 2023: Wouter + - Fix to scrub resource records of type A and AAAA that have an + inappropriate size. They are removed from responses. + - Fix to move msgparse_rrset_remove_rr code to util/msgparse.c. + - Fix to add EDE text when RRs have been removed due to length. + - Fix to set ede match in unit test for rr length removal. + - Fix to print EDE text in readable form in output logs. + +6 September 2023: Wouter + - Merge #931: Prevent warnings from -Wmissing-prototypes. + +31 August 2023: Wouter + - Fix autoconf 2.69 warnings in configure. + - Fix #927: unbound 1.18.0 make test error. Fix make test without SHA1. + +30 August 2023: Wouter + - Fix for WKS call to getservbyname that creates allocation on exit + in unit test by testing numbers first and testing from the services + list later. + +28 August 2023: Wouter + - Fix for version generation race condition that ignored changes. + 25 August 2023: Wouter - Fix compile error on NetBSD in util/netevent.h. 23 August 2023: Wouter - - Tag for 1.18.0rc1 release. + - Tag for 1.18.0rc1 release. This became the 1.18.0 release on + 30 aug 2023, with the fix from 25 aug, fix compile on NetBSD + included. The repository continues with version 1.18.1. 22 August 2023: Wouter - Set version number to 1.18.0. @@ -4754,7 +4899,7 @@ - Fix that with openssl 1.1 control-use-cert: no uses less cpu, by using no encryption over the unix socket. -22 Novenber 2016: Ralph +22 November 2016: Ralph - Make access-control-tag-data RDATA absolute. This makes the RDATA origin consistent between local-data and access-control-tag-data. - Fix NSEC ENT wildcard check. Matching wildcard does not have to be a diff --git a/usr.sbin/unbound/doc/README b/usr.sbin/unbound/doc/README index 8bc8765d464..ea0cf091ffa 100644 --- a/usr.sbin/unbound/doc/README +++ b/usr.sbin/unbound/doc/README @@ -1,4 +1,4 @@ -README for Unbound 1.18.0 +README for Unbound 1.19.2 Copyright 2007 NLnet Labs http://unbound.net diff --git a/usr.sbin/unbound/doc/example.conf.in b/usr.sbin/unbound/doc/example.conf.in index b7195360c5b..2bf460b8d6f 100644 --- a/usr.sbin/unbound/doc/example.conf.in +++ b/usr.sbin/unbound/doc/example.conf.in @@ -1,7 +1,7 @@ # # Example configuration file. # -# See unbound.conf(5) man page, version 1.18.0. +# See unbound.conf(5) man page, version 1.19.2. # # this is a comment. @@ -683,6 +683,11 @@ server: # that set CD but cannot validate themselves. # ignore-cd-flag: no + # Disable the DO flag in outgoing requests. It is helpful for upstream + # devices that cannot handle DNSSEC information. But do not enable it + # otherwise, because it would stop DNSSEC validation. + # disable-edns-do: no + # Serve expired responses from cache, with serve-expired-reply-ttl in # the response, and then attempt to fetch the data afresh. # serve-expired: no @@ -1221,6 +1226,8 @@ remote-control: # backend: "testframe" # # secret seed string to calculate hashed keys # secret-seed: "default" +# # if the backend should be read from, but not written to. +# cachedb-no-store: no # # # For "redis" backend: # # (to enable, use --with-libhiredis to configure before compiling) @@ -1236,6 +1243,8 @@ remote-control: # redis-timeout: 100 # # set timeout on redis records based on DNS response TTL # redis-expire-records: no +# # redis logical database to use, 0 is the default database. +# redis-logical-db: 0 # IPSet # Add specify domain into set via ipset. diff --git a/usr.sbin/unbound/doc/libunbound.3.in b/usr.sbin/unbound/doc/libunbound.3.in index 429ac93407f..7478ad891cd 100644 --- a/usr.sbin/unbound/doc/libunbound.3.in +++ b/usr.sbin/unbound/doc/libunbound.3.in @@ -1,4 +1,4 @@ -.TH "libunbound" "3" "Aug 30, 2023" "NLnet Labs" "unbound 1.18.0" +.TH "libunbound" "3" "Mar 7, 2024" "NLnet Labs" "unbound 1.19.2" .\" .\" libunbound.3 -- unbound library functions manual .\" @@ -44,7 +44,7 @@ .B ub_ctx_zone_remove, .B ub_ctx_data_add, .B ub_ctx_data_remove -\- Unbound DNS validating resolver 1.18.0 functions. +\- Unbound DNS validating resolver 1.19.2 functions. .SH "SYNOPSIS" .B #include <unbound.h> .LP diff --git a/usr.sbin/unbound/doc/unbound-anchor.8.in b/usr.sbin/unbound/doc/unbound-anchor.8.in index 4e862fc89c7..978208e9fde 100644 --- a/usr.sbin/unbound/doc/unbound-anchor.8.in +++ b/usr.sbin/unbound/doc/unbound-anchor.8.in @@ -1,4 +1,4 @@ -.TH "unbound-anchor" "8" "Aug 30, 2023" "NLnet Labs" "unbound 1.18.0" +.TH "unbound-anchor" "8" "Mar 7, 2024" "NLnet Labs" "unbound 1.19.2" .\" .\" unbound-anchor.8 -- unbound anchor maintenance utility manual .\" diff --git a/usr.sbin/unbound/doc/unbound-checkconf.8.in b/usr.sbin/unbound/doc/unbound-checkconf.8.in index 6a2c2cc94ee..2d7f583871c 100644 --- a/usr.sbin/unbound/doc/unbound-checkconf.8.in +++ b/usr.sbin/unbound/doc/unbound-checkconf.8.in @@ -1,4 +1,4 @@ -.TH "unbound-checkconf" "8" "Aug 30, 2023" "NLnet Labs" "unbound 1.18.0" +.TH "unbound-checkconf" "8" "Mar 7, 2024" "NLnet Labs" "unbound 1.19.2" .\" .\" unbound-checkconf.8 -- unbound configuration checker manual .\" diff --git a/usr.sbin/unbound/doc/unbound-control.8.in b/usr.sbin/unbound/doc/unbound-control.8.in index db4eb72308a..5588d2231e2 100644 --- a/usr.sbin/unbound/doc/unbound-control.8.in +++ b/usr.sbin/unbound/doc/unbound-control.8.in @@ -1,4 +1,4 @@ -.TH "unbound-control" "8" "Aug 30, 2023" "NLnet Labs" "unbound 1.18.0" +.TH "unbound-control" "8" "Mar 7, 2024" "NLnet Labs" "unbound 1.19.2" .\" .\" unbound-control.8 -- unbound remote control manual .\" diff --git a/usr.sbin/unbound/doc/unbound-host.1.in b/usr.sbin/unbound/doc/unbound-host.1.in index e4fe718ab07..2bb881d18f6 100644 --- a/usr.sbin/unbound/doc/unbound-host.1.in +++ b/usr.sbin/unbound/doc/unbound-host.1.in @@ -1,4 +1,4 @@ -.TH "unbound\-host" "1" "Aug 30, 2023" "NLnet Labs" "unbound 1.18.0" +.TH "unbound\-host" "1" "Mar 7, 2024" "NLnet Labs" "unbound 1.19.2" .\" .\" unbound-host.1 -- unbound DNS lookup utility .\" diff --git a/usr.sbin/unbound/doc/unbound.8.in b/usr.sbin/unbound/doc/unbound.8.in index 7b955a92e54..c9babdb579e 100644 --- a/usr.sbin/unbound/doc/unbound.8.in +++ b/usr.sbin/unbound/doc/unbound.8.in @@ -1,4 +1,4 @@ -.TH "unbound" "8" "Aug 30, 2023" "NLnet Labs" "unbound 1.18.0" +.TH "unbound" "8" "Mar 7, 2024" "NLnet Labs" "unbound 1.19.2" .\" .\" unbound.8 -- unbound manual .\" @@ -9,7 +9,7 @@ .\" .SH "NAME" .B unbound -\- Unbound DNS validating resolver 1.18.0. +\- Unbound DNS validating resolver 1.19.2. .SH "SYNOPSIS" .B unbound .RB [ \-h ] diff --git a/usr.sbin/unbound/doc/unbound.conf.5.in b/usr.sbin/unbound/doc/unbound.conf.5.in index 07ee839065d..a1bb1a4a561 100644 --- a/usr.sbin/unbound/doc/unbound.conf.5.in +++ b/usr.sbin/unbound/doc/unbound.conf.5.in @@ -1,4 +1,4 @@ -.TH "unbound.conf" "5" "Aug 30, 2023" "NLnet Labs" "unbound 1.18.0" +.TH "unbound.conf" "5" "Mar 7, 2024" "NLnet Labs" "unbound 1.19.2" .\" .\" unbound.conf.5 -- unbound.conf manual .\" @@ -1257,6 +1257,20 @@ servers that set the CD flag but cannot validate DNSSEC themselves are the clients, and then Unbound provides them with DNSSEC protection. The default value is "no". .TP +.B disable\-edns\-do: \fI<yes or no> +Disable the EDNS DO flag in upstream requests. +It breaks DNSSEC validation for Unbound's clients. +This results in the upstream name servers to not include DNSSEC records in +their replies and could be helpful for devices that cannot handle DNSSEC +information. +When the option is enabled, clients that set the DO flag receive no EDNS +record in the response to indicate the lack of support to them. +If this option is enabled but Unbound is already configured for DNSSEC +validation (i.e., the validator module is enabled; default) this option is +implicitly turned off with a warning as to not break DNSSEC validation in +Unbound. +Default is no. +.TP .B serve\-expired: \fI<yes or no> If enabled, Unbound attempts to serve old responses from cache with a TTL of \fBserve\-expired\-reply\-ttl\fR in the response without waiting for the @@ -2622,6 +2636,11 @@ operationally. If the backend database is shared by multiple Unbound instances, all instances must use the same secret seed. This option defaults to "default". +.TP +.B cachedb-no-store: \fI<yes or no>\fR +If the backend should be read from, but not written to. This makes this +instance not store dns messages in the backend. But if data is available it +is retrieved. The default is no. .P The following .B cachedb @@ -2662,6 +2681,17 @@ Unbound is configured with \fBserve-expired\fR and \fBserve-expired-ttl\fR is 0, this option is internally reverted to "no". Redis SETEX support is required for this option (Redis >= 2.0.0). This option defaults to no. +.TP +.B redis-logical-db: \fI<logical database index> +The logical database in Redis to use. +These are databases in the same Redis instance sharing the same configuration +and persisted in the same RDB/AOF file. +If unsure about using this option, Redis documentation +(https://redis.io/commands/select/) suggests not to use a single Redis instance +for multiple unrelated applications. +The default database in Redis is 0 while other logical databases need to be +explicitly SELECT'ed upon connecting. +This option defaults to 0. .SS DNSTAP Logging Options DNSTAP support, when compiled in by using \fB\-\-enable\-dnstap\fR, is enabled in the \fBdnstap:\fR section. diff --git a/usr.sbin/unbound/edns-subnet/subnetmod.c b/usr.sbin/unbound/edns-subnet/subnetmod.c index 13fd669b5d5..cefde84e5f4 100644 --- a/usr.sbin/unbound/edns-subnet/subnetmod.c +++ b/usr.sbin/unbound/edns-subnet/subnetmod.c @@ -156,6 +156,7 @@ int ecs_whitelist_check(struct query_info* qinfo, qstate->no_cache_store = 0; } + sq->subnet_sent_no_subnet = 0; if(sq->ecs_server_out.subnet_validdata && ((sq->subnet_downstream && qstate->env->cfg->client_subnet_always_forward) || ecs_is_whitelisted(sn_env->whitelist, @@ -166,6 +167,14 @@ int ecs_whitelist_check(struct query_info* qinfo, * set. */ if(!edns_opt_list_find(qstate->edns_opts_back_out, qstate->env->cfg->client_subnet_opcode)) { + /* if the client is not wanting an EDNS subnet option, + * omit it and store that we omitted it but actually + * are doing EDNS subnet to the server. */ + if(sq->ecs_server_out.subnet_source_mask == 0) { + sq->subnet_sent_no_subnet = 1; + sq->subnet_sent = 0; + return 1; + } subnet_ecs_opt_list_append(&sq->ecs_server_out, &qstate->edns_opts_back_out, qstate, region); } @@ -515,7 +524,7 @@ eval_response(struct module_qstate *qstate, int id, struct subnet_qstate *sq) } /* We have not asked for subnet data */ - if (!sq->subnet_sent) { + if (!sq->subnet_sent && !sq->subnet_sent_no_subnet) { if (s_in->subnet_validdata) verbose(VERB_QUERY, "subnetcache: received spurious data"); if (sq->subnet_downstream) /* Copy back to client */ @@ -524,7 +533,7 @@ eval_response(struct module_qstate *qstate, int id, struct subnet_qstate *sq) } /* subnet sent but nothing came back */ - if (!s_in->subnet_validdata) { + if (!s_in->subnet_validdata && !sq->subnet_sent_no_subnet) { /* The authority indicated no support for edns subnet. As a * consequence the answer ended up in the regular cache. It * is still useful to put it in the edns subnet cache for @@ -540,6 +549,18 @@ eval_response(struct module_qstate *qstate, int id, struct subnet_qstate *sq) return module_finished; } + /* Purposefully there was no sent subnet, and there is consequently + * no subnet in the answer. If there was, use the subnet in the answer + * anyway. But if there is not, treat it as a prefix 0 answer. */ + if(sq->subnet_sent_no_subnet && !s_in->subnet_validdata) { + /* Fill in 0.0.0.0/0 scope 0, or ::0/0 scope 0, for caching. */ + s_in->subnet_addr_fam = s_out->subnet_addr_fam; + s_in->subnet_source_mask = 0; + s_in->subnet_scope_mask = 0; + memset(s_in->subnet_addr, 0, INET6_SIZE); + s_in->subnet_validdata = 1; + } + /* Being here means we have asked for and got a subnet specific * answer. Also, the answer from the authority is not yet cached * anywhere. */ @@ -556,6 +577,7 @@ eval_response(struct module_qstate *qstate, int id, struct subnet_qstate *sq) (void)edns_opt_list_remove(&qstate->edns_opts_back_out, qstate->env->cfg->client_subnet_opcode); sq->subnet_sent = 0; + sq->subnet_sent_no_subnet = 0; return module_restart_next; } @@ -676,6 +698,7 @@ ecs_query_response(struct module_qstate* qstate, struct dns_msg* response, edns_opt_list_remove(&qstate->edns_opts_back_out, qstate->env->cfg->client_subnet_opcode); sq->subnet_sent = 0; + sq->subnet_sent_no_subnet = 0; memset(&sq->ecs_server_out, 0, sizeof(sq->ecs_server_out)); } else if (!sq->track_max_scope && FLAGS_GET_RCODE(response->rep->flags) == LDNS_RCODE_NOERROR && @@ -737,6 +760,9 @@ ecs_edns_back_parsed(struct module_qstate* qstate, int id, sq->ecs_server_in.subnet_scope_mask > sq->max_scope)) sq->max_scope = sq->ecs_server_in.subnet_scope_mask; + } else if(sq->subnet_sent_no_subnet) { + /* The answer can be stored as scope 0, not in global cache. */ + qstate->no_cache_store = 1; } return 1; diff --git a/usr.sbin/unbound/edns-subnet/subnetmod.h b/usr.sbin/unbound/edns-subnet/subnetmod.h index f0bcaad33e1..1ff8a23ecdb 100644 --- a/usr.sbin/unbound/edns-subnet/subnetmod.h +++ b/usr.sbin/unbound/edns-subnet/subnetmod.h @@ -85,6 +85,13 @@ struct subnet_qstate { struct ecs_data ecs_server_out; int subnet_downstream; int subnet_sent; + /** + * If there was no subnet sent because the client used source prefix + * length 0 for omitting the information. Then the answer is cached + * like subnet was a /0 scope. Like the subnet_sent flag, but when + * the EDNS subnet option is omitted because the client asked. + */ + int subnet_sent_no_subnet; /** keep track of longest received scope, set after receiving CNAME for * incoming QNAME. */ int track_max_scope; diff --git a/usr.sbin/unbound/iterator/iter_resptype.c b/usr.sbin/unbound/iterator/iter_resptype.c index e85595b843d..38e186e7904 100644 --- a/usr.sbin/unbound/iterator/iter_resptype.c +++ b/usr.sbin/unbound/iterator/iter_resptype.c @@ -42,6 +42,7 @@ #include "config.h" #include "iterator/iter_resptype.h" #include "iterator/iter_delegpt.h" +#include "iterator/iterator.h" #include "services/cache/dns.h" #include "util/net_help.h" #include "util/data/dname.h" @@ -105,7 +106,8 @@ response_type_from_cache(struct dns_msg* msg, enum response_type response_type_from_server(int rdset, - struct dns_msg* msg, struct query_info* request, struct delegpt* dp) + struct dns_msg* msg, struct query_info* request, struct delegpt* dp, + int* empty_nodata_found) { uint8_t* origzone = (uint8_t*)"\000"; /* the default */ struct ub_packed_rrset_key* s; @@ -284,13 +286,22 @@ response_type_from_server(int rdset, /* If we've gotten this far, this is NOERROR/NODATA (which could * be an entirely empty message) */ - /* but ignore entirely empty messages, noerror/nodata has a soa - * negative ttl value in the authority section, this makes it try - * again at another authority. And turns it from a 5 second empty - * message into a 5 second servfail response. */ + /* For entirely empty messages, try again, at first, then accept + * it it happens more. A regular noerror/nodata response has a soa + * negative ttl value in the authority section. This makes it try + * again at another authority. And decides between storing a 5 second + * empty message or a 5 second servfail response. */ if(msg->rep->an_numrrsets == 0 && msg->rep->ns_numrrsets == 0 && - msg->rep->ar_numrrsets == 0) - return RESPONSE_TYPE_THROWAWAY; + msg->rep->ar_numrrsets == 0) { + if(empty_nodata_found) { + /* detect as throwaway at first, but accept later. */ + (*empty_nodata_found)++; + if(*empty_nodata_found < EMPTY_NODATA_RETRY_COUNT) + return RESPONSE_TYPE_THROWAWAY; + return RESPONSE_TYPE_ANSWER; + } + return RESPONSE_TYPE_ANSWER; + } /* check if recursive answer; saying it has empty cache */ if( (msg->rep->flags&BIT_RA) && !(msg->rep->flags&BIT_AA) && !rdset) return RESPONSE_TYPE_REC_LAME; diff --git a/usr.sbin/unbound/iterator/iter_scrub.c b/usr.sbin/unbound/iterator/iter_scrub.c index d1fedcd0f90..5f2e3033722 100644 --- a/usr.sbin/unbound/iterator/iter_scrub.c +++ b/usr.sbin/unbound/iterator/iter_scrub.c @@ -716,6 +716,56 @@ static int sanitize_nsec_is_overreach(sldns_buffer* pkt, return 0; } +/** Remove individual RRs, if the length is wrong. Returns true if the RRset + * has been removed. */ +static int +scrub_sanitize_rr_length(sldns_buffer* pkt, struct msg_parse* msg, + struct rrset_parse* prev, struct rrset_parse** rrset, int* added_ede, + struct module_qstate* qstate) +{ + struct rr_parse* rr, *rr_prev = NULL; + for(rr = (*rrset)->rr_first; rr; rr = rr->next) { + + /* Sanity check for length of records + * An A record should be 6 bytes only + * (2 bytes for length and 4 for IPv4 addr)*/ + if((*rrset)->type == LDNS_RR_TYPE_A && rr->size != 6 ) { + if(!*added_ede) { + *added_ede = 1; + errinf_ede(qstate, "sanitize: records of inappropriate length have been removed.", + LDNS_EDE_OTHER); + } + if(msgparse_rrset_remove_rr("sanitize: removing type A RR of inappropriate length:", + pkt, *rrset, rr_prev, rr, NULL, 0)) { + remove_rrset("sanitize: removing type A RRset of inappropriate length:", + pkt, msg, prev, rrset); + return 1; + } + continue; + } + + /* Sanity check for length of records + * An AAAA record should be 18 bytes only + * (2 bytes for length and 16 for IPv6 addr)*/ + if((*rrset)->type == LDNS_RR_TYPE_AAAA && rr->size != 18 ) { + if(!*added_ede) { + *added_ede = 1; + errinf_ede(qstate, "sanitize: records of inappropriate length have been removed.", + LDNS_EDE_OTHER); + } + if(msgparse_rrset_remove_rr("sanitize: removing type AAAA RR of inappropriate length:", + pkt, *rrset, rr_prev, rr, NULL, 0)) { + remove_rrset("sanitize: removing type AAAA RRset of inappropriate length:", + pkt, msg, prev, rrset); + return 1; + } + continue; + } + rr_prev = rr; + } + return 0; +} + /** * Given a response event, remove suspect RRsets from the response. * "Suspect" rrsets are potentially poison. Note that this routine expects @@ -728,15 +778,17 @@ static int sanitize_nsec_is_overreach(sldns_buffer* pkt, * @param zonename: name of server zone. * @param env: module environment with config and cache. * @param ie: iterator environment with private address data. + * @param qstate: for setting errinf for EDE error messages. * @return 0 on error. */ static int scrub_sanitize(sldns_buffer* pkt, struct msg_parse* msg, struct query_info* qinfo, uint8_t* zonename, struct module_env* env, - struct iter_env* ie) + struct iter_env* ie, struct module_qstate* qstate) { int del_addi = 0; /* if additional-holding rrsets are deleted, we do not trust the normalized additional-A-AAAA any more */ + int added_rrlen_ede = 0; struct rrset_parse* rrset, *prev; prev = NULL; rrset = msg->rrset_first; @@ -781,6 +833,14 @@ scrub_sanitize(sldns_buffer* pkt, struct msg_parse* msg, rrset = msg->rrset_first; while(rrset) { + /* Sanity check for length of records */ + if(rrset->type == LDNS_RR_TYPE_A || + rrset->type == LDNS_RR_TYPE_AAAA) { + if(scrub_sanitize_rr_length(pkt, msg, prev, &rrset, + &added_rrlen_ede, qstate)) + continue; + } + /* remove private addresses */ if( (rrset->type == LDNS_RR_TYPE_A || rrset->type == LDNS_RR_TYPE_AAAA)) { @@ -854,7 +914,8 @@ scrub_sanitize(sldns_buffer* pkt, struct msg_parse* msg, int scrub_message(sldns_buffer* pkt, struct msg_parse* msg, struct query_info* qinfo, uint8_t* zonename, struct regional* region, - struct module_env* env, struct iter_env* ie) + struct module_env* env, struct module_qstate* qstate, + struct iter_env* ie) { /* basic sanity checks */ log_nametypeclass(VERB_ALGO, "scrub for", zonename, LDNS_RR_TYPE_NS, @@ -886,7 +947,7 @@ scrub_message(sldns_buffer* pkt, struct msg_parse* msg, if(!scrub_normalize(pkt, msg, qinfo, region, env)) return 0; /* delete all out-of-zone information */ - if(!scrub_sanitize(pkt, msg, qinfo, zonename, env, ie)) + if(!scrub_sanitize(pkt, msg, qinfo, zonename, env, ie, qstate)) return 0; return 1; } diff --git a/usr.sbin/unbound/iterator/iterator.c b/usr.sbin/unbound/iterator/iterator.c index 1548dfcaee6..6ff811a27d0 100644 --- a/usr.sbin/unbound/iterator/iterator.c +++ b/usr.sbin/unbound/iterator/iterator.c @@ -1449,6 +1449,39 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq, } iq->qchase.qname = sname; iq->qchase.qname_len = slen; + if(qstate->env->auth_zones) { + /* apply rpz qname triggers after cname */ + struct dns_msg* forged_response = + rpz_callback_from_iterator_cname(qstate, iq); + while(forged_response && reply_find_rrset_section_an( + forged_response->rep, iq->qchase.qname, + iq->qchase.qname_len, LDNS_RR_TYPE_CNAME, + iq->qchase.qclass)) { + /* another cname to follow */ + if(!handle_cname_response(qstate, iq, forged_response, + &sname, &slen)) { + errinf(qstate, "malloc failure, CNAME info"); + return error_response(qstate, id, LDNS_RCODE_SERVFAIL); + } + iq->qchase.qname = sname; + iq->qchase.qname_len = slen; + forged_response = + rpz_callback_from_iterator_cname(qstate, iq); + } + if(forged_response != NULL) { + qstate->ext_state[id] = module_finished; + qstate->return_rcode = LDNS_RCODE_NOERROR; + qstate->return_msg = forged_response; + iq->response = forged_response; + next_state(iq, FINISHED_STATE); + if(!iter_prepend(iq, qstate->return_msg, qstate->region)) { + log_err("rpz: after cached cname, prepend rrsets: out of memory"); + return error_response(qstate, id, LDNS_RCODE_SERVFAIL); + } + qstate->return_msg->qinfo = qstate->qinfo; + return 0; + } + } /* This *is* a query restart, even if it is a cheap * one. */ iq->dp = NULL; @@ -2875,7 +2908,8 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq, /* unset CD if to forwarder(RD set) and not dnssec retry * (blacklist nonempty) and no trust-anchors are configured * above the qname or on the first attempt when dnssec is on */ - EDNS_DO| ((iq->chase_to_rd||(iq->chase_flags&BIT_RD)!=0)&& + (qstate->env->cfg->disable_edns_do?0:EDNS_DO)| + ((iq->chase_to_rd||(iq->chase_flags&BIT_RD)!=0)&& !qstate->blacklist&&(!iter_qname_indicates_dnssec(qstate->env, &iq->qinfo_out)||target->attempts==1)?0:BIT_CD), iq->dnssec_expected, iq->caps_fallback || is_caps_whitelisted( @@ -2940,7 +2974,7 @@ static int processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq, struct iter_env* ie, int id) { - int dnsseclame = 0, origtypecname = 0; + int dnsseclame = 0, origtypecname = 0, orig_empty_nodata_found; enum response_type type; iq->num_current_queries--; @@ -2960,12 +2994,25 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq, return next_state(iq, QUERYTARGETS_STATE); } iq->timeout_count = 0; + orig_empty_nodata_found = iq->empty_nodata_found; type = response_type_from_server( (int)((iq->chase_flags&BIT_RD) || iq->chase_to_rd), - iq->response, &iq->qinfo_out, iq->dp); + iq->response, &iq->qinfo_out, iq->dp, &iq->empty_nodata_found); iq->chase_to_rd = 0; /* remove TC flag, if this is erroneously set by TCP upstream */ iq->response->rep->flags &= ~BIT_TC; + if(orig_empty_nodata_found != iq->empty_nodata_found && + iq->empty_nodata_found < EMPTY_NODATA_RETRY_COUNT) { + /* try to search at another server */ + if(qstate->reply) { + struct delegpt_addr* a = delegpt_find_addr( + iq->dp, &qstate->reply->remote_addr, + qstate->reply->remote_addrlen); + /* make selection disprefer it */ + if(a) a->lame = 1; + } + return next_state(iq, QUERYTARGETS_STATE); + } if(type == RESPONSE_TYPE_REFERRAL && (iq->chase_flags&BIT_RD) && !iq->auth_zone_response) { /* When forwarding (RD bit is set), we handle referrals @@ -3501,7 +3548,7 @@ processPrimeResponse(struct module_qstate* qstate, int id) iq->response->rep->flags &= ~(BIT_RD|BIT_RA); /* ignore rec-lame */ type = response_type_from_server( (int)((iq->chase_flags&BIT_RD) || iq->chase_to_rd), - iq->response, &iq->qchase, iq->dp); + iq->response, &iq->qchase, iq->dp, NULL); if(type == RESPONSE_TYPE_ANSWER) { qstate->return_rcode = LDNS_RCODE_NOERROR; qstate->return_msg = iq->response; @@ -3874,6 +3921,23 @@ processFinished(struct module_qstate* qstate, struct iter_qstate* iq, /* explicitly set the EDE string to NULL */ iq->response->rep->reason_bogus_str = NULL; + if((qstate->env->cfg->val_log_level >= 2 || + qstate->env->cfg->log_servfail) && qstate->errinf && + !qstate->env->cfg->val_log_squelch) { + char* err_str = errinf_to_str_misc(qstate); + if(err_str) { + size_t err_str_len = strlen(err_str); + verbose(VERB_ALGO, "iterator EDE: %s", err_str); + /* allocate space and store the error + * string */ + iq->response->rep->reason_bogus_str = regional_alloc( + qstate->region, + sizeof(char) * (err_str_len+1)); + memcpy(iq->response->rep->reason_bogus_str, + err_str, err_str_len+1); + } + free(err_str); + } /* we have finished processing this query */ qstate->ext_state[id] = module_finished; @@ -4098,7 +4162,7 @@ process_response(struct module_qstate* qstate, struct iter_qstate* iq, /* normalize and sanitize: easy to delete items from linked lists */ if(!scrub_message(pkt, prs, &iq->qinfo_out, iq->dp->name, - qstate->env->scratch, qstate->env, ie)) { + qstate->env->scratch, qstate->env, qstate, ie)) { /* if 0x20 enabled, start fallback, but we have no message */ if(event == module_event_capsfail && !iq->caps_fallback) { iq->caps_fallback = 1; diff --git a/usr.sbin/unbound/iterator/iterator.h b/usr.sbin/unbound/iterator/iterator.h index fad7f03e63d..e253f3f7e2b 100644 --- a/usr.sbin/unbound/iterator/iterator.h +++ b/usr.sbin/unbound/iterator/iterator.h @@ -101,6 +101,8 @@ extern int BLACKLIST_PENALTY; * Chosen so that the UNKNOWN_SERVER_NICENESS falls within the band of a * fast server, this causes server exploration as a side benefit. msec. */ #define RTT_BAND 400 +/** Number of retries for empty nodata packets before it is accepted. */ +#define EMPTY_NODATA_RETRY_COUNT 2 /** * Global state for the iterator. @@ -415,6 +417,11 @@ struct iter_qstate { */ int refetch_glue; + /** + * This flag detects that a completely empty nodata was received, + * already so that it is accepted later. */ + int empty_nodata_found; + /** list of pending queries to authoritative servers. */ struct outbound_list outlist; diff --git a/usr.sbin/unbound/libunbound/libworker.c b/usr.sbin/unbound/libunbound/libworker.c index 104244937bf..0e1c4039376 100644 --- a/usr.sbin/unbound/libunbound/libworker.c +++ b/usr.sbin/unbound/libunbound/libworker.c @@ -62,6 +62,7 @@ #include "util/random.h" #include "util/config_file.h" #include "util/netevent.h" +#include "util/proxy_protocol.h" #include "util/storage/lookup3.h" #include "util/storage/slabhash.h" #include "util/net_help.h" @@ -168,6 +169,7 @@ libworker_setup(struct ub_ctx* ctx, int is_bg, struct ub_event_base* eb) hints_delete(w->env->hints); w->env->hints = NULL; } +#ifdef HAVE_SSL w->sslctx = connect_sslctx_create(NULL, NULL, cfg->tls_cert_bundle, cfg->tls_win_cert); if(!w->sslctx) { @@ -175,6 +177,7 @@ libworker_setup(struct ub_ctx* ctx, int is_bg, struct ub_event_base* eb) hints_delete(w->env->hints); w->env->hints = NULL; } +#endif if(!w->is_bg || w->is_bg_thread) { lock_basic_unlock(&ctx->cfglock); } @@ -263,6 +266,7 @@ libworker_setup(struct ub_ctx* ctx, int is_bg, struct ub_event_base* eb) w->env->kill_sub = &mesh_state_delete; w->env->detect_cycle = &mesh_detect_cycle; comm_base_timept(w->base, &w->env->now, &w->env->now_tv); + pp_init(&sldns_write_uint16, &sldns_write_uint32); return w; } diff --git a/usr.sbin/unbound/services/authzone.c b/usr.sbin/unbound/services/authzone.c index 849a5d29f3b..9d02cfbffe4 100644 --- a/usr.sbin/unbound/services/authzone.c +++ b/usr.sbin/unbound/services/authzone.c @@ -2475,6 +2475,7 @@ az_find_ce(struct auth_zone* z, struct query_info* qinfo, struct auth_rrset** rrset) { struct auth_data* n = node; + struct auth_rrset* lookrrset; *ce = NULL; *rrset = NULL; if(!node_exact) { @@ -2497,21 +2498,23 @@ az_find_ce(struct auth_zone* z, struct query_info* qinfo, /* see if the current candidate has issues */ /* not zone apex and has type NS */ if(n->namelen != z->namelen && - (*rrset=az_domain_rrset(n, LDNS_RR_TYPE_NS)) && + (lookrrset=az_domain_rrset(n, LDNS_RR_TYPE_NS)) && /* delegate here, but DS at exact the dp has notype */ (qinfo->qtype != LDNS_RR_TYPE_DS || n->namelen != qinfo->qname_len)) { /* referral */ /* this is ce and the lowernode is nonexisting */ *ce = n; - return 0; + *rrset = lookrrset; + node_exact = 0; } /* not equal to qname and has type DNAME */ if(n->namelen != qinfo->qname_len && - (*rrset=az_domain_rrset(n, LDNS_RR_TYPE_DNAME))) { + (lookrrset=az_domain_rrset(n, LDNS_RR_TYPE_DNAME))) { /* this is ce and the lowernode is nonexisting */ *ce = n; - return 0; + *rrset = lookrrset; + node_exact = 0; } if(*ce == NULL && !domain_has_only_nsec3(n)) { diff --git a/usr.sbin/unbound/services/listen_dnsport.c b/usr.sbin/unbound/services/listen_dnsport.c index 60f9b41e5f6..753550978a0 100644 --- a/usr.sbin/unbound/services/listen_dnsport.c +++ b/usr.sbin/unbound/services/listen_dnsport.c @@ -1327,7 +1327,9 @@ ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp, log_warn("socket timestamping is not available"); } if(!port_insert(list, s, is_dnscrypt - ?listen_type_udp_dnscrypt:listen_type_udp, + ?listen_type_udp_dnscrypt : + (sock_queue_timeout ? + listen_type_udpancil:listen_type_udp), is_pp2, ub_sock)) { sock_close(s); if(ub_sock->addr) @@ -1498,9 +1500,13 @@ listen_create(struct comm_base* base, struct listen_port* ports, } } else if(ports->ftype == listen_type_udpancil || ports->ftype == listen_type_udpancil_dnscrypt) { +#if defined(AF_INET6) && defined(IPV6_PKTINFO) && defined(HAVE_RECVMSG) cp = comm_point_create_udp_ancil(base, ports->fd, front->udp_buff, ports->pp2_enabled, cb, cb_arg, ports->socket); +#else + log_warn("This system does not support UDP ancilliary data."); +#endif } if(!cp) { log_err("can't create commpoint"); diff --git a/usr.sbin/unbound/services/mesh.c b/usr.sbin/unbound/services/mesh.c index 52d14a2d1f5..509bee36a2c 100644 --- a/usr.sbin/unbound/services/mesh.c +++ b/usr.sbin/unbound/services/mesh.c @@ -1197,6 +1197,8 @@ mesh_do_callback(struct mesh_state* m, int rcode, struct reply_info* rep, r->edns.udp_size = EDNS_ADVERTISED_SIZE; r->edns.ext_rcode = 0; r->edns.bits &= EDNS_DO; + if(m->s.env->cfg->disable_edns_do && (r->edns.bits&EDNS_DO)) + r->edns.edns_present = 0; if(!inplace_cb_reply_call(m->s.env, &m->s.qinfo, &m->s, rep, LDNS_RCODE_NOERROR, &r->edns, NULL, m->s.region, start_time) || @@ -1224,11 +1226,12 @@ static inline int mesh_is_rpz_respip_tcponly_action(struct mesh_state const* m) { struct respip_action_info const* respip_info = m->s.respip_action_info; - return respip_info == NULL + return (respip_info == NULL ? 0 : (respip_info->rpz_used && !respip_info->rpz_disabled - && respip_info->action == respip_truncate); + && respip_info->action == respip_truncate)) + || m->s.tcp_required; } static inline int @@ -1371,6 +1374,8 @@ mesh_send_reply(struct mesh_state* m, int rcode, struct reply_info* rep, r->edns.udp_size = EDNS_ADVERTISED_SIZE; r->edns.ext_rcode = 0; r->edns.bits &= EDNS_DO; + if(m->s.env->cfg->disable_edns_do && (r->edns.bits&EDNS_DO)) + r->edns.edns_present = 0; m->s.qinfo.qname = r->qname; m->s.qinfo.local_alias = r->local_alias; diff --git a/usr.sbin/unbound/services/outside_network.c b/usr.sbin/unbound/services/outside_network.c index 2a219cbc6e9..12923f07d78 100644 --- a/usr.sbin/unbound/services/outside_network.c +++ b/usr.sbin/unbound/services/outside_network.c @@ -550,7 +550,6 @@ reuse_tcp_find(struct outside_network* outnet, struct sockaddr_storage* addr, log_assert(&key_p.reuse != (struct reuse_tcp*)result); log_assert(&key_p != ((struct reuse_tcp*)result)->pending); } - /* not found, return null */ /* It is possible that we search for something before the first element * in the tree. Replace a null pointer with the first element. @@ -560,6 +559,7 @@ reuse_tcp_find(struct outside_network* outnet, struct sockaddr_storage* addr, result = rbtree_first(&outnet->tcp_reuse); } + /* not found, return null */ if(!result || result == RBTREE_NULL) return NULL; diff --git a/usr.sbin/unbound/sldns/str2wire.c b/usr.sbin/unbound/sldns/str2wire.c index 45e24761374..fdd40e0f223 100644 --- a/usr.sbin/unbound/sldns/str2wire.c +++ b/usr.sbin/unbound/sldns/str2wire.c @@ -2459,12 +2459,13 @@ int sldns_str2wire_wks_buf(const char* str, uint8_t* rd, size_t* len) (void)strlcpy(proto_str, token, sizeof(proto_str)); } else { int serv_port; - struct servent *serv = getservbyname(token, proto_str); - if(serv) serv_port=(int)ntohs((uint16_t)serv->s_port); + if(atoi(token) != 0) serv_port=atoi(token); + else if(strcmp(token, "0") == 0) serv_port=0; else if(strcasecmp(token, "domain")==0) serv_port=53; else { - serv_port = atoi(token); - if(serv_port == 0 && strcmp(token, "0") != 0) { + struct servent *serv = getservbyname(token, proto_str); + if(serv) serv_port=(int)ntohs((uint16_t)serv->s_port); + else { #ifdef HAVE_ENDSERVENT endservent(); #endif @@ -2474,16 +2475,16 @@ int sldns_str2wire_wks_buf(const char* str, uint8_t* rd, size_t* len) return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX, sldns_buffer_position(&strbuf)); } - if(serv_port < 0 || serv_port > 65535) { + } + if(serv_port < 0 || serv_port > 65535) { #ifdef HAVE_ENDSERVENT - endservent(); + endservent(); #endif #ifdef HAVE_ENDPROTOENT - endprotoent(); + endprotoent(); #endif - return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX, - sldns_buffer_position(&strbuf)); - } + return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX, + sldns_buffer_position(&strbuf)); } if(rd_len < 1+serv_port/8+1) { /* bitmap is larger, init new bytes at 0 */ diff --git a/usr.sbin/unbound/sldns/wire2str.c b/usr.sbin/unbound/sldns/wire2str.c index e6278ff560d..2b5dc0513f8 100644 --- a/usr.sbin/unbound/sldns/wire2str.c +++ b/usr.sbin/unbound/sldns/wire2str.c @@ -192,6 +192,7 @@ static sldns_lookup_table sldns_edns_options_data[] = { { 6, "DHU" }, { 7, "N3U" }, { 8, "edns-client-subnet" }, + { 10, "COOKIE" }, { 11, "edns-tcp-keepalive"}, { 12, "Padding" }, { 15, "EDE"}, @@ -199,6 +200,38 @@ static sldns_lookup_table sldns_edns_options_data[] = { }; sldns_lookup_table* sldns_edns_options = sldns_edns_options_data; +/* From RFC8914 5.2 Table 3, the "Extended DNS Error Codes" registry. */ +static sldns_lookup_table sldns_edns_ede_codes_data[] = { + { LDNS_EDE_NONE, "None" }, + { LDNS_EDE_OTHER, "Other Error" }, + { LDNS_EDE_UNSUPPORTED_DNSKEY_ALG, "Unsupported DNSKEY Algorithm" }, + { LDNS_EDE_UNSUPPORTED_DS_DIGEST, "Unsupported DS Digest Type" }, + { LDNS_EDE_STALE_ANSWER, "Stale Answer" }, + { LDNS_EDE_FORGED_ANSWER, "Forged Answer" }, + { LDNS_EDE_DNSSEC_INDETERMINATE, "DNSSEC Indeterminate" }, + { LDNS_EDE_DNSSEC_BOGUS, "DNSSEC Bogus" }, + { LDNS_EDE_SIGNATURE_EXPIRED, "Signature Expired" }, + { LDNS_EDE_SIGNATURE_NOT_YET_VALID, "Signature Not Yet Valid" }, + { LDNS_EDE_DNSKEY_MISSING, "DNSKEY Missing" }, + { LDNS_EDE_RRSIGS_MISSING, "RRSIGs Missing" }, + { LDNS_EDE_NO_ZONE_KEY_BIT_SET, "No Zone Key Bit Set" }, + { LDNS_EDE_NSEC_MISSING, "NSEC Missing" }, + { LDNS_EDE_CACHED_ERROR, "Cached Error" }, + { LDNS_EDE_NOT_READY, "Not Ready" }, + { LDNS_EDE_BLOCKED, "Blocked" }, + { LDNS_EDE_CENSORED, "Censored" }, + { LDNS_EDE_FILTERED, "Filtered" }, + { LDNS_EDE_PROHIBITED, "Prohibited" }, + { LDNS_EDE_STALE_NXDOMAIN_ANSWER, "Stale NXDOMAIN Answer" }, + { LDNS_EDE_NOT_AUTHORITATIVE, "Not Authoritative" }, + { LDNS_EDE_NOT_SUPPORTED, "Not Supported" }, + { LDNS_EDE_NO_REACHABLE_AUTHORITY, "No Reachable Authority" }, + { LDNS_EDE_NETWORK_ERROR, "Network Error" }, + { LDNS_EDE_INVALID_DATA, "Invalid Data" }, + { 0, NULL} +}; +sldns_lookup_table* sldns_edns_ede_codes = sldns_edns_ede_codes_data; + static sldns_lookup_table sldns_tsig_errors_data[] = { { LDNS_TSIG_ERROR_NOERROR, "NOERROR" }, { LDNS_RCODE_FORMERR, "FORMERR" }, @@ -2234,6 +2267,52 @@ static int sldns_wire2str_edns_keepalive_print(char** s, size_t* sl, return w; } +int sldns_wire2str_edns_ede_print(char** s, size_t* sl, + uint8_t* data, size_t len) +{ + uint16_t ede_code; + int w = 0; + sldns_lookup_table *lt; + size_t i; + int printable; + + if(len < 2) { + w += sldns_str_print(s, sl, "malformed ede "); + w += print_hex_buf(s, sl, data, len); + return w; + } + + ede_code = sldns_read_uint16(data); + lt = sldns_lookup_by_id(sldns_edns_ede_codes, (int)ede_code); + if(lt && lt->name) + w += sldns_str_print(s, sl, "%s", lt->name); + else w += sldns_str_print(s, sl, "%d", (int)ede_code); + + if(len == 2) + return w; + + w += sldns_str_print(s, sl, " "); + + /* If it looks like text, show it as text. */ + printable=1; + for(i=2; i<len; i++) { + if(isprint((unsigned char)data[i]) || data[i] == '\t') + continue; + printable = 0; + break; + } + if(printable) { + w += sldns_str_print(s, sl, "\""); + for(i=2; i<len; i++) { + w += str_char_print(s, sl, data[i]); + } + w += sldns_str_print(s, sl, "\""); + } else { + w += print_hex_buf(s, sl, data+2, len-2); + } + return w; +} + int sldns_wire2str_edns_option_print(char** s, size_t* sl, uint16_t option_code, uint8_t* optdata, size_t optlen) { @@ -2268,6 +2347,9 @@ int sldns_wire2str_edns_option_print(char** s, size_t* sl, case LDNS_EDNS_PADDING: w += print_hex_buf(s, sl, optdata, optlen); break; + case LDNS_EDNS_EDE: + w += sldns_wire2str_edns_ede_print(s, sl, optdata, optlen); + break; default: /* unknown option code */ w += print_hex_buf(s, sl, optdata, optlen); diff --git a/usr.sbin/unbound/sldns/wire2str.h b/usr.sbin/unbound/sldns/wire2str.h index 548c66300d9..a7c58b85a5f 100644 --- a/usr.sbin/unbound/sldns/wire2str.h +++ b/usr.sbin/unbound/sldns/wire2str.h @@ -36,6 +36,8 @@ extern struct sldns_struct_lookup_table* sldns_opcodes; extern struct sldns_struct_lookup_table* sldns_edns_flags; /** EDNS option codes */ extern struct sldns_struct_lookup_table* sldns_edns_options; +/** EDNS EDE codes */ +extern struct sldns_struct_lookup_table* sldns_edns_ede_codes; /** error string from wireparse */ extern struct sldns_struct_lookup_table* sldns_wireparse_errors; /** tsig errors are the rcodes with extra (higher) values */ @@ -1021,6 +1023,17 @@ int sldns_wire2str_edns_subnet_print(char** str, size_t* str_len, uint8_t* option_data, size_t option_len); /** + * Print EDNS EDE option data to string. User buffers, moves string pointers. + * @param str: string buffer. + * @param str_len: length of string buffer. + * @param option_data: buffer with EDNS option code data. + * @param option_len: length of the data for this option. + * @return number of characters (except null) needed to print. + */ +int sldns_wire2str_edns_ede_print(char** str, size_t* str_len, + uint8_t* option_data, size_t option_len); + +/** * Print an EDNS option as OPT: VALUE. User buffers, moves string pointers. * @param str: string buffer. * @param str_len: length of string buffer. diff --git a/usr.sbin/unbound/smallapp/unbound-checkconf.c b/usr.sbin/unbound/smallapp/unbound-checkconf.c index 99692a6255a..b359da354bb 100644 --- a/usr.sbin/unbound/smallapp/unbound-checkconf.c +++ b/usr.sbin/unbound/smallapp/unbound-checkconf.c @@ -707,6 +707,23 @@ morechecks(struct config_file* cfg) cfg->auto_trust_anchor_file_list, cfg->chrootdir, cfg); check_chroot_filelist_wild("trusted-keys-file", cfg->trusted_keys_file_list, cfg->chrootdir, cfg); + if(cfg->disable_edns_do && strstr(cfg->module_conf, "validator") + && (cfg->trust_anchor_file_list + || cfg->trust_anchor_list + || cfg->auto_trust_anchor_file_list + || cfg->trusted_keys_file_list)) { + char* key = NULL; + if(cfg->auto_trust_anchor_file_list) + key = cfg->auto_trust_anchor_file_list->str; + if(!key && cfg->trust_anchor_file_list) + key = cfg->trust_anchor_file_list->str; + if(!key && cfg->trust_anchor_list) + key = cfg->trust_anchor_list->str; + if(!key && cfg->trusted_keys_file_list) + key = cfg->trusted_keys_file_list->str; + if(!key) key = ""; + fatal_exit("disable-edns-do does not allow DNSSEC to work, but the validator module uses a trust anchor %s, turn off disable-edns-do or disable validation", key); + } #ifdef USE_IPSECMOD if(cfg->ipsecmod_enabled && strstr(cfg->module_conf, "ipsecmod")) { /* only check hook if enabled */ diff --git a/usr.sbin/unbound/util/config_file.c b/usr.sbin/unbound/util/config_file.c index b7aed66dc19..8d1fd552191 100644 --- a/usr.sbin/unbound/util/config_file.c +++ b/usr.sbin/unbound/util/config_file.c @@ -271,6 +271,7 @@ config_create(void) cfg->val_permissive_mode = 0; cfg->aggressive_nsec = 1; cfg->ignore_cd = 0; + cfg->disable_edns_do = 0; cfg->serve_expired = 0; cfg->serve_expired_ttl = 0; cfg->serve_expired_ttl_reset = 0; @@ -381,6 +382,7 @@ config_create(void) #ifdef USE_CACHEDB if(!(cfg->cachedb_backend = strdup("testframe"))) goto error_exit; if(!(cfg->cachedb_secret = strdup("default"))) goto error_exit; + cfg->cachedb_no_store = 0; #ifdef USE_REDIS if(!(cfg->redis_server_host = strdup("127.0.0.1"))) goto error_exit; cfg->redis_server_path = NULL; @@ -388,6 +390,7 @@ config_create(void) cfg->redis_timeout = 100; cfg->redis_server_port = 6379; cfg->redis_expire_records = 0; + cfg->redis_logical_db = 0; #endif /* USE_REDIS */ #endif /* USE_CACHEDB */ #ifdef USE_IPSET @@ -690,6 +693,7 @@ int config_set_option(struct config_file* cfg, const char* opt, else S_YNO("val-permissive-mode:", val_permissive_mode) else S_YNO("aggressive-nsec:", aggressive_nsec) else S_YNO("ignore-cd-flag:", ignore_cd) + else S_YNO("disable-edns-do:", disable_edns_do) else if(strcmp(opt, "serve-expired:") == 0) { IS_YES_OR_NO; cfg->serve_expired = (strcmp(val, "yes") == 0); SERVE_EXPIRED = cfg->serve_expired; } @@ -819,6 +823,9 @@ int config_set_option(struct config_file* cfg, const char* opt, { IS_NUMBER_OR_ZERO; cfg->ipsecmod_max_ttl = atoi(val); } else S_YNO("ipsecmod-strict:", ipsecmod_strict) #endif +#ifdef USE_CACHEDB + else S_YNO("cachedb-no-store:", cachedb_no_store) +#endif /* USE_CACHEDB */ else if(strcmp(opt, "define-tag:") ==0) { return config_add_tag(cfg, val); /* val_sig_skew_min, max and val_max_restart are copied into val_env @@ -1149,6 +1156,7 @@ config_get_option(struct config_file* cfg, const char* opt, else O_YNO(opt, "val-permissive-mode", val_permissive_mode) else O_YNO(opt, "aggressive-nsec", aggressive_nsec) else O_YNO(opt, "ignore-cd-flag", ignore_cd) + else O_YNO(opt, "disable-edns-do", disable_edns_do) else O_YNO(opt, "serve-expired", serve_expired) else O_DEC(opt, "serve-expired-ttl", serve_expired_ttl) else O_YNO(opt, "serve-expired-ttl-reset", serve_expired_ttl_reset) @@ -1306,6 +1314,7 @@ config_get_option(struct config_file* cfg, const char* opt, #ifdef USE_CACHEDB else O_STR(opt, "backend", cachedb_backend) else O_STR(opt, "secret-seed", cachedb_secret) + else O_YNO(opt, "cachedb-no-store", cachedb_no_store) #ifdef USE_REDIS else O_STR(opt, "redis-server-host", redis_server_host) else O_DEC(opt, "redis-server-port", redis_server_port) @@ -1313,6 +1322,7 @@ config_get_option(struct config_file* cfg, const char* opt, else O_STR(opt, "redis-server-password", redis_server_password) else O_DEC(opt, "redis-timeout", redis_timeout) else O_YNO(opt, "redis-expire-records", redis_expire_records) + else O_DEC(opt, "redis-logical-db", redis_logical_db) #endif /* USE_REDIS */ #endif /* USE_CACHEDB */ #ifdef USE_IPSET diff --git a/usr.sbin/unbound/util/config_file.h b/usr.sbin/unbound/util/config_file.h index 452f3c6a78f..ad22b8330e3 100644 --- a/usr.sbin/unbound/util/config_file.h +++ b/usr.sbin/unbound/util/config_file.h @@ -409,6 +409,8 @@ struct config_file { int aggressive_nsec; /** ignore the CD flag in incoming queries and refuse them bogus data */ int ignore_cd; + /** disable EDNS DO flag in outgoing requests */ + int disable_edns_do; /** serve expired entries and prefetch them */ int serve_expired; /** serve expired entries until TTL after expiration */ @@ -699,6 +701,8 @@ struct config_file { char* cachedb_backend; /** secret seed for hash key calculation */ char* cachedb_secret; + /** cachedb that does not store, but only reads from database, if on */ + int cachedb_no_store; #ifdef USE_REDIS /** redis server's IP address or host name */ char* redis_server_host; @@ -712,6 +716,8 @@ struct config_file { int redis_timeout; /** set timeout on redis records based on DNS response ttl */ int redis_expire_records; + /** set the redis logical database upon connection */ + int redis_logical_db; #endif #endif /** Downstream DNS Cookies */ diff --git a/usr.sbin/unbound/util/configlexer.lex b/usr.sbin/unbound/util/configlexer.lex index 3fcdfa62e03..fdc267434c7 100644 --- a/usr.sbin/unbound/util/configlexer.lex +++ b/usr.sbin/unbound/util/configlexer.lex @@ -403,6 +403,7 @@ val-clean-additional{COLON} { YDVAR(1, VAR_VAL_CLEAN_ADDITIONAL) } val-permissive-mode{COLON} { YDVAR(1, VAR_VAL_PERMISSIVE_MODE) } aggressive-nsec{COLON} { YDVAR(1, VAR_AGGRESSIVE_NSEC) } ignore-cd-flag{COLON} { YDVAR(1, VAR_IGNORE_CD_FLAG) } +disable-edns-do{COLON} { YDVAR(1, VAR_DISABLE_EDNS_DO) } serve-expired{COLON} { YDVAR(1, VAR_SERVE_EXPIRED) } serve-expired-ttl{COLON} { YDVAR(1, VAR_SERVE_EXPIRED_TTL) } serve-expired-ttl-reset{COLON} { YDVAR(1, VAR_SERVE_EXPIRED_TTL_RESET) } @@ -557,12 +558,14 @@ ipsecmod-strict{COLON} { YDVAR(1, VAR_IPSECMOD_STRICT) } cachedb{COLON} { YDVAR(0, VAR_CACHEDB) } backend{COLON} { YDVAR(1, VAR_CACHEDB_BACKEND) } secret-seed{COLON} { YDVAR(1, VAR_CACHEDB_SECRETSEED) } +cachedb-no-store{COLON} { YDVAR(1, VAR_CACHEDB_NO_STORE) } redis-server-host{COLON} { YDVAR(1, VAR_CACHEDB_REDISHOST) } redis-server-port{COLON} { YDVAR(1, VAR_CACHEDB_REDISPORT) } redis-server-path{COLON} { YDVAR(1, VAR_CACHEDB_REDISPATH) } redis-server-password{COLON} { YDVAR(1, VAR_CACHEDB_REDISPASSWORD) } redis-timeout{COLON} { YDVAR(1, VAR_CACHEDB_REDISTIMEOUT) } redis-expire-records{COLON} { YDVAR(1, VAR_CACHEDB_REDISEXPIRERECORDS) } +redis-logical-db{COLON} { YDVAR(1, VAR_CACHEDB_REDISLOGICALDB) } ipset{COLON} { YDVAR(0, VAR_IPSET) } name-v4{COLON} { YDVAR(1, VAR_IPSET_NAME_V4) } name-v6{COLON} { YDVAR(1, VAR_IPSET_NAME_V6) } diff --git a/usr.sbin/unbound/util/configparser.y b/usr.sbin/unbound/util/configparser.y index d8f25a67ebb..da5d6608f1d 100644 --- a/usr.sbin/unbound/util/configparser.y +++ b/usr.sbin/unbound/util/configparser.y @@ -179,6 +179,7 @@ extern struct config_parser_state* cfg_parser; %token VAR_CACHEDB VAR_CACHEDB_BACKEND VAR_CACHEDB_SECRETSEED %token VAR_CACHEDB_REDISHOST VAR_CACHEDB_REDISPORT VAR_CACHEDB_REDISTIMEOUT %token VAR_CACHEDB_REDISEXPIRERECORDS VAR_CACHEDB_REDISPATH VAR_CACHEDB_REDISPASSWORD +%token VAR_CACHEDB_REDISLOGICALDB %token VAR_UDP_UPSTREAM_WITHOUT_DOWNSTREAM VAR_FOR_UPSTREAM %token VAR_AUTH_ZONE VAR_ZONEFILE VAR_MASTER VAR_URL VAR_FOR_DOWNSTREAM %token VAR_FALLBACK_ENABLED VAR_TLS_ADDITIONAL_PORT VAR_LOW_RTT VAR_LOW_RTT_PERMIL @@ -198,7 +199,7 @@ extern struct config_parser_state* cfg_parser; %token VAR_INTERFACE_ACTION VAR_INTERFACE_VIEW VAR_INTERFACE_TAG %token VAR_INTERFACE_TAG_ACTION VAR_INTERFACE_TAG_DATA %token VAR_PROXY_PROTOCOL_PORT VAR_STATISTICS_INHIBIT_ZERO -%token VAR_HARDEN_UNKNOWN_ADDITIONAL +%token VAR_HARDEN_UNKNOWN_ADDITIONAL VAR_DISABLE_EDNS_DO VAR_CACHEDB_NO_STORE %% toplevelvars: /* empty */ | toplevelvars toplevelvar ; @@ -332,7 +333,7 @@ content_server: server_num_threads | server_verbosity | server_port | server_tcp_reuse_timeout | server_tcp_auth_query_timeout | server_interface_automatic_ports | server_ede | server_proxy_protocol_port | server_statistics_inhibit_zero | - server_harden_unknown_additional + server_harden_unknown_additional | server_disable_edns_do ; stubstart: VAR_STUB_ZONE { @@ -2060,6 +2061,15 @@ server_ignore_cd_flag: VAR_IGNORE_CD_FLAG STRING_ARG free($2); } ; +server_disable_edns_do: VAR_DISABLE_EDNS_DO STRING_ARG + { + OUTYY(("P(server_disable_edns_do:%s)\n", $2)); + if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) + yyerror("expected yes or no."); + else cfg_parser->cfg->disable_edns_do = (strcmp($2, "yes")==0); + free($2); + } + ; server_serve_expired: VAR_SERVE_EXPIRED STRING_ARG { OUTYY(("P(server_serve_expired:%s)\n", $2)); @@ -3701,7 +3711,8 @@ contents_cachedb: contents_cachedb content_cachedb | ; content_cachedb: cachedb_backend_name | cachedb_secret_seed | redis_server_host | redis_server_port | redis_timeout | - redis_expire_records | redis_server_path | redis_server_password + redis_expire_records | redis_server_path | redis_server_password | + cachedb_no_store | redis_logical_db ; cachedb_backend_name: VAR_CACHEDB_BACKEND STRING_ARG { @@ -3727,6 +3738,19 @@ cachedb_secret_seed: VAR_CACHEDB_SECRETSEED STRING_ARG #endif } ; +cachedb_no_store: VAR_CACHEDB_NO_STORE STRING_ARG + { + #ifdef USE_CACHEDB + OUTYY(("P(cachedb_no_store:%s)\n", $2)); + if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) + yyerror("expected yes or no."); + else cfg_parser->cfg->cachedb_no_store = (strcmp($2, "yes")==0); + #else + OUTYY(("P(Compiled without cachedb, ignoring)\n")); + #endif + free($2); + } + ; redis_server_host: VAR_CACHEDB_REDISHOST STRING_ARG { #if defined(USE_CACHEDB) && defined(USE_REDIS) @@ -3804,6 +3828,21 @@ redis_expire_records: VAR_CACHEDB_REDISEXPIRERECORDS STRING_ARG free($2); } ; +redis_logical_db: VAR_CACHEDB_REDISLOGICALDB STRING_ARG + { + #if defined(USE_CACHEDB) && defined(USE_REDIS) + int db; + OUTYY(("P(redis_logical_db:%s)\n", $2)); + db = atoi($2); + if((db == 0 && strcmp($2, "0") != 0) || db < 0) + yyerror("valid redis logical database index expected"); + else cfg_parser->cfg->redis_logical_db = db; + #else + OUTYY(("P(Compiled without cachedb or redis, ignoring)\n")); + #endif + free($2); + } + ; server_tcp_connection_limit: VAR_TCP_CONNECTION_LIMIT STRING_ARG STRING_ARG { OUTYY(("P(server_tcp_connection_limit:%s %s)\n", $2, $3)); diff --git a/usr.sbin/unbound/util/data/msgencode.c b/usr.sbin/unbound/util/data/msgencode.c index 93423f985bd..898ff8412a4 100644 --- a/usr.sbin/unbound/util/data/msgencode.c +++ b/usr.sbin/unbound/util/data/msgencode.c @@ -1015,8 +1015,10 @@ reply_info_answer_encode(struct query_info* qinf, struct reply_info* rep, ede_size = calc_ede_option_size(edns, &ede_txt_size); if(sldns_buffer_capacity(pkt) < udpsize) udpsize = sldns_buffer_capacity(pkt); + if(!edns || !edns->edns_present) { + attach_edns = 0; /* EDEs are optional, try to fit anything else before them */ - if(udpsize < LDNS_HEADER_SIZE + edns_field_size - ede_size) { + } else if(udpsize < LDNS_HEADER_SIZE + edns_field_size - ede_size) { /* packet too small to contain edns, omit it. */ attach_edns = 0; } else { diff --git a/usr.sbin/unbound/util/data/msgparse.c b/usr.sbin/unbound/util/data/msgparse.c index b5414c6d0a5..d06b7bb25e6 100644 --- a/usr.sbin/unbound/util/data/msgparse.c +++ b/usr.sbin/unbound/util/data/msgparse.c @@ -47,6 +47,7 @@ #include "util/regional.h" #include "util/rfc_1982.h" #include "util/edns.h" +#include "util/net_help.h" #include "sldns/rrdef.h" #include "sldns/sbuffer.h" #include "sldns/parseutil.h" @@ -1306,3 +1307,27 @@ log_edns_opt_list(enum verbosity_value level, const char* info_str, } } +/** remove RR from msgparse RRset, return true if rrset is entirely bad */ +int +msgparse_rrset_remove_rr(const char* str, sldns_buffer* pkt, struct rrset_parse* rrset, + struct rr_parse* prev, struct rr_parse* rr, struct sockaddr_storage* addr, socklen_t addrlen) +{ + if(verbosity >= VERB_QUERY && rrset->dname_len <= LDNS_MAX_DOMAINLEN && str) { + uint8_t buf[LDNS_MAX_DOMAINLEN+1]; + dname_pkt_copy(pkt, buf, rrset->dname); + if(addr) + log_name_addr(VERB_QUERY, str, buf, addr, addrlen); + else log_nametypeclass(VERB_QUERY, str, buf, + rrset->type, ntohs(rrset->rrset_class)); + } + if(prev) + prev->next = rr->next; + else rrset->rr_first = rr->next; + if(rrset->rr_last == rr) + rrset->rr_last = prev; + rrset->rr_count --; + rrset->size -= rr->size; + /* rr struct still exists, but is unlinked, so that in the for loop + * the rr->next works fine to continue. */ + return rrset->rr_count == 0; +} diff --git a/usr.sbin/unbound/util/data/msgparse.h b/usr.sbin/unbound/util/data/msgparse.h index b7dc235d677..8e5c94a28cb 100644 --- a/usr.sbin/unbound/util/data/msgparse.h +++ b/usr.sbin/unbound/util/data/msgparse.h @@ -371,4 +371,22 @@ void msgparse_bucket_remove(struct msg_parse* msg, struct rrset_parse* rrset); void log_edns_opt_list(enum verbosity_value level, const char* info_str, struct edns_option* list); +/** + * Remove RR from msgparse RRset. + * @param str: this string is used for logging if verbose. If NULL, there is + * no logging of the remove. + * @param pkt: packet in buffer that is removed from. Used to log the name + * of the item removed. + * @param rrset: RRset that the RR is removed from. + * @param prev: previous RR in list, or NULL. + * @param rr: RR that is removed. + * @param addr: address used for logging, if verbose, or NULL then it is not + * used. + * @param addrlen: length of addr, if that is not NULL. + * @return true if rrset is entirely bad, it would then need to be removed. + */ +int msgparse_rrset_remove_rr(const char* str, struct sldns_buffer* pkt, + struct rrset_parse* rrset, struct rr_parse* prev, struct rr_parse* rr, + struct sockaddr_storage* addr, socklen_t addrlen); + #endif /* UTIL_DATA_MSGPARSE_H */ diff --git a/usr.sbin/unbound/util/fptr_wlist.c b/usr.sbin/unbound/util/fptr_wlist.c index 11cce1a2a04..a792a342954 100644 --- a/usr.sbin/unbound/util/fptr_wlist.c +++ b/usr.sbin/unbound/util/fptr_wlist.c @@ -169,7 +169,9 @@ int fptr_whitelist_event(void (*fptr)(int, short, void *)) { if(fptr == &comm_point_udp_callback) return 1; +#if defined(AF_INET6) && defined(IPV6_PKTINFO) && defined(HAVE_RECVMSG) else if(fptr == &comm_point_udp_ancil_callback) return 1; +#endif else if(fptr == &comm_point_tcp_accept_callback) return 1; else if(fptr == &comm_point_tcp_handle_callback) return 1; else if(fptr == &comm_timer_callback) return 1; diff --git a/usr.sbin/unbound/util/log.c b/usr.sbin/unbound/util/log.c index dfbb2334994..a15ee920c0f 100644 --- a/usr.sbin/unbound/util/log.c +++ b/usr.sbin/unbound/util/log.c @@ -187,7 +187,7 @@ void log_ident_set_default(const char* id) default_ident = id; } -void log_ident_revert_to_default() +void log_ident_revert_to_default(void) { ident = default_ident; } diff --git a/usr.sbin/unbound/util/module.c b/usr.sbin/unbound/util/module.c index 773dab853d2..62e5de4a05b 100644 --- a/usr.sbin/unbound/util/module.c +++ b/usr.sbin/unbound/util/module.c @@ -194,6 +194,24 @@ char* errinf_to_str_servfail(struct module_qstate* qstate) return p; } +char* errinf_to_str_misc(struct module_qstate* qstate) +{ + char buf[20480]; + char* p = buf; + size_t left = sizeof(buf); + struct errinf_strlist* s; + if(!qstate->errinf) + snprintf(p, left, "misc failure"); + else for(s=qstate->errinf; s; s=s->next) { + snprintf(p, left, "%s%s", (s==qstate->errinf?"":" "), s->str); + left -= strlen(p); p += strlen(p); + } + p = strdup(buf); + if(!p) + log_err("malloc failure in errinf_to_str"); + return p; +} + void errinf_rrset(struct module_qstate* qstate, struct ub_packed_rrset_key *rr) { char buf[1024]; diff --git a/usr.sbin/unbound/util/module.h b/usr.sbin/unbound/util/module.h index 5b6fcc93cf1..8a9da3f931a 100644 --- a/usr.sbin/unbound/util/module.h +++ b/usr.sbin/unbound/util/module.h @@ -691,6 +691,8 @@ struct module_qstate { struct respip_action_info* respip_action_info; /** if the query is rpz passthru, no further rpz processing for it */ int rpz_passthru; + /* Flag tcp required. */ + int tcp_required; /** whether the reply should be dropped */ int is_drop; @@ -843,6 +845,14 @@ sldns_ede_code errinf_to_reason_bogus(struct module_qstate* qstate); char* errinf_to_str_servfail(struct module_qstate* qstate); /** + * Create error info in string. For misc failures that are not servfail. + * @param qstate: query state. + * @return string or NULL on malloc failure (already logged). + * This string is malloced and has to be freed by caller. + */ +char* errinf_to_str_misc(struct module_qstate* qstate); + +/** * Initialize the edns known options by allocating the required space. * @param env: the module environment. * @return false on failure (no memory). diff --git a/usr.sbin/unbound/util/net_help.c b/usr.sbin/unbound/util/net_help.c index dec46da20e2..8970247926d 100644 --- a/usr.sbin/unbound/util/net_help.c +++ b/usr.sbin/unbound/util/net_help.c @@ -953,6 +953,111 @@ void log_crypto_err_code(const char* str, unsigned long err) } #ifdef HAVE_SSL +/** Print crypt erro with SSL_get_error want code and err_get_error code */ +static void log_crypto_err_io_code_arg(const char* str, int r, + unsigned long err, int err_present) +{ + int print_errno = 0, print_crypto_err = 0; + const char* inf = NULL; + + switch(r) { + case SSL_ERROR_NONE: + inf = "no error"; + break; + case SSL_ERROR_ZERO_RETURN: + inf = "channel closed"; + break; + case SSL_ERROR_WANT_READ: + inf = "want read"; + break; + case SSL_ERROR_WANT_WRITE: + inf = "want write"; + break; + case SSL_ERROR_WANT_CONNECT: + inf = "want connect"; + break; + case SSL_ERROR_WANT_ACCEPT: + inf = "want accept"; + break; + case SSL_ERROR_WANT_X509_LOOKUP: + inf = "want X509 lookup"; + break; +#ifdef SSL_ERROR_WANT_ASYNC + case SSL_ERROR_WANT_ASYNC: + inf = "want async"; + break; +#endif +#ifdef SSL_ERROR_WANT_ASYNC_JOB + case SSL_ERROR_WANT_ASYNC_JOB: + inf = "want async job"; + break; +#endif +#ifdef SSL_ERROR_WANT_CLIENT_HELLO_CB + case SSL_ERROR_WANT_CLIENT_HELLO_CB: + inf = "want client hello cb"; + break; +#endif + case SSL_ERROR_SYSCALL: + print_errno = 1; + inf = "syscall"; + break; + case SSL_ERROR_SSL: + print_crypto_err = 1; + inf = "SSL, usually protocol, error"; + break; + default: + inf = "unknown SSL_get_error result code"; + print_errno = 1; + print_crypto_err = 1; + } + if(print_crypto_err) { + if(print_errno) { + char buf[1024]; + snprintf(buf, sizeof(buf), "%s with errno %s", + str, strerror(errno)); + if(err_present) + log_crypto_err_code(buf, err); + else log_crypto_err(buf); + } else { + if(err_present) + log_crypto_err_code(str, err); + else log_crypto_err(str); + } + } else { + if(print_errno) { + if(errno == 0) + log_err("str: syscall error with errno %s", + strerror(errno)); + else log_err("str: %s", strerror(errno)); + } else { + log_err("str: %s", inf); + } + } +} +#endif /* HAVE_SSL */ + +void log_crypto_err_io(const char* str, int r) +{ +#ifdef HAVE_SSL + log_crypto_err_io_code_arg(str, r, 0, 0); +#else + (void)str; + (void)r; +#endif /* HAVE_SSL */ +} + +void log_crypto_err_io_code(const char* str, int r, unsigned long err) +{ +#ifdef HAVE_SSL + log_crypto_err_io_code_arg(str, r, err, 1); +#else + (void)str; + (void)r; + (void)err; +#endif /* HAVE_SSL */ +} + +#ifdef HAVE_SSL /** log certificate details */ void log_cert(unsigned level, const char* str, void* cert) diff --git a/usr.sbin/unbound/util/net_help.h b/usr.sbin/unbound/util/net_help.h index a9de910d546..edaea42353d 100644 --- a/usr.sbin/unbound/util/net_help.h +++ b/usr.sbin/unbound/util/net_help.h @@ -430,6 +430,24 @@ void log_crypto_err(const char* str); void log_crypto_err_code(const char* str, unsigned long err); /** + * Log an error from libcrypto that came from SSL_write and so on, with + * a value from SSL_get_error, calls log_err. If that fails it logs with + * log_crypto_err. + * @param str: what failed + * @param r: output of SSL_get_error on the I/O operation result. + */ +void log_crypto_err_io(const char* str, int r); + +/** + * Log an error from libcrypt that came from an I/O routine with the + * errcode from ERR_get_error. Calls log_err() and log_crypto_err_code. + * @param str: what failed + * @param r: output of SSL_get_error on the I/O operation result. + * @param err: error code from ERR_get_error + */ +void log_crypto_err_io_code(const char* str, int r, unsigned long err); + +/** * Log certificate details verbosity, string, of X509 cert * @param level: verbosity level * @param str: string to prefix on output diff --git a/usr.sbin/unbound/util/netevent.c b/usr.sbin/unbound/util/netevent.c index b9395a8998b..141e48d48b3 100644 --- a/usr.sbin/unbound/util/netevent.c +++ b/usr.sbin/unbound/util/netevent.c @@ -892,15 +892,18 @@ static int udp_recv_needs_log(int err) static int consume_pp2_header(struct sldns_buffer* buf, struct comm_reply* rep, int stream) { size_t size; - struct pp2_header *header = pp2_read_header(buf); - if(header == NULL) return 0; + struct pp2_header *header; + int err = pp2_read_header(sldns_buffer_begin(buf), + sldns_buffer_remaining(buf)); + if(err) return 0; + header = (struct pp2_header*)sldns_buffer_begin(buf); size = PP2_HEADER_SIZE + ntohs(header->len); if((header->ver_cmd & 0xF) == PP2_CMD_LOCAL) { /* A connection from the proxy itself. * No need to do anything with addresses. */ goto done; } - if(header->fam_prot == 0x00) { + if(header->fam_prot == PP2_UNSPEC_UNSPEC) { /* Unspecified family and protocol. This could be used for * health checks by proxies. * No need to do anything with addresses. */ @@ -908,8 +911,8 @@ static int consume_pp2_header(struct sldns_buffer* buf, struct comm_reply* rep, } /* Read the proxied address */ switch(header->fam_prot) { - case 0x11: /* AF_INET|STREAM */ - case 0x12: /* AF_INET|DGRAM */ + case PP2_INET_STREAM: + case PP2_INET_DGRAM: { struct sockaddr_in* addr = (struct sockaddr_in*)&rep->client_addr; @@ -920,8 +923,8 @@ static int consume_pp2_header(struct sldns_buffer* buf, struct comm_reply* rep, } /* Ignore the destination address; it should be us. */ break; - case 0x21: /* AF_INET6|STREAM */ - case 0x22: /* AF_INET6|DGRAM */ + case PP2_INET6_STREAM: + case PP2_INET6_DGRAM: { struct sockaddr_in6* addr = (struct sockaddr_in6*)&rep->client_addr; @@ -934,6 +937,10 @@ static int consume_pp2_header(struct sldns_buffer* buf, struct comm_reply* rep, } /* Ignore the destination address; it should be us. */ break; + default: + log_err("proxy_protocol: unsupported family and " + "protocol 0x%x", (int)header->fam_prot); + return 0; } rep->is_proxied = 1; done: @@ -948,10 +955,10 @@ done: return 1; } +#if defined(AF_INET6) && defined(IPV6_PKTINFO) && defined(HAVE_RECVMSG) void comm_point_udp_ancil_callback(int fd, short event, void* arg) { -#if defined(AF_INET6) && defined(IPV6_PKTINFO) && defined(HAVE_RECVMSG) struct comm_reply rep; struct msghdr msg; struct iovec iov[1]; @@ -1063,21 +1070,21 @@ comm_point_udp_ancil_callback(int fd, short event, void* arg) fptr_ok(fptr_whitelist_comm_point(rep.c->callback)); if((*rep.c->callback)(rep.c, rep.c->cb_arg, NETEVENT_NOERROR, &rep)) { /* send back immediate reply */ - (void)comm_point_send_udp_msg_if(rep.c, rep.c->buffer, + struct sldns_buffer *buffer; +#ifdef USE_DNSCRYPT + buffer = rep.c->dnscrypt_buffer; +#else + buffer = rep.c->buffer; +#endif + (void)comm_point_send_udp_msg_if(rep.c, buffer, (struct sockaddr*)&rep.remote_addr, rep.remote_addrlen, &rep); } if(!rep.c || rep.c->fd == -1) /* commpoint closed */ break; } -#else - (void)fd; - (void)event; - (void)arg; - fatal_exit("recvmsg: No support for IPV6_PKTINFO; IP_PKTINFO or IP_RECVDSTADDR. " - "Please disable interface-automatic"); -#endif /* AF_INET6 && IPV6_PKTINFO && HAVE_RECVMSG */ } +#endif /* AF_INET6 && IPV6_PKTINFO && HAVE_RECVMSG */ void comm_point_udp_callback(int fd, short event, void* arg) @@ -1665,7 +1672,8 @@ ssl_handshake(struct comm_point* c) } else { unsigned long err = ERR_get_error(); if(!squelch_err_ssl_handshake(err)) { - log_crypto_err_code("ssl handshake failed", err); + log_crypto_err_io_code("ssl handshake failed", + want, err); log_addr(VERB_OPS, "ssl handshake failed", &c->repinfo.remote_addr, c->repinfo.remote_addrlen); @@ -1815,23 +1823,30 @@ ssl_handle_read(struct comm_point* c) strerror(errno)); return 0; } - log_crypto_err("could not SSL_read"); + log_crypto_err_io("could not SSL_read", + want); return 0; } c->tcp_byte_count += r; + sldns_buffer_skip(c->buffer, r); if(c->tcp_byte_count != current_read_size) return 1; c->pp2_header_state = pp2_header_init; } } if(c->pp2_header_state == pp2_header_init) { - header = pp2_read_header(c->buffer); - if(!header) { + int err; + err = pp2_read_header( + sldns_buffer_begin(c->buffer), + sldns_buffer_limit(c->buffer)); + if(err) { log_err("proxy_protocol: could not parse " - "PROXYv2 header"); + "PROXYv2 header (%s)", + pp_lookup_error(err)); return 0; } + header = (struct pp2_header*)sldns_buffer_begin(c->buffer); want_read_size = ntohs(header->len); - if(sldns_buffer_remaining(c->buffer) < + if(sldns_buffer_limit(c->buffer) < PP2_HEADER_SIZE + want_read_size) { log_err_addr("proxy_protocol: not enough " "buffer size to read PROXYv2 header", "", @@ -1876,10 +1891,12 @@ ssl_handle_read(struct comm_point* c) strerror(errno)); return 0; } - log_crypto_err("could not SSL_read"); + log_crypto_err_io("could not SSL_read", + want); return 0; } c->tcp_byte_count += r; + sldns_buffer_skip(c->buffer, r); if(c->tcp_byte_count != current_read_size) return 1; c->pp2_header_state = pp2_header_done; } @@ -1890,6 +1907,7 @@ ssl_handle_read(struct comm_point* c) c->repinfo.remote_addrlen); return 0; } + sldns_buffer_flip(c->buffer); if(!consume_pp2_header(c->buffer, &c->repinfo, 1)) { log_err_addr("proxy_protocol: could not consume " "PROXYv2 header", "", &c->repinfo.remote_addr, @@ -1934,7 +1952,7 @@ ssl_handle_read(struct comm_point* c) strerror(errno)); return 0; } - log_crypto_err("could not SSL_read"); + log_crypto_err_io("could not SSL_read", want); return 0; } c->tcp_byte_count += r; @@ -1984,7 +2002,7 @@ ssl_handle_read(struct comm_point* c) strerror(errno)); return 0; } - log_crypto_err("could not SSL_read"); + log_crypto_err_io("could not SSL_read", want); return 0; } sldns_buffer_skip(c->buffer, (ssize_t)r); @@ -2075,7 +2093,7 @@ ssl_handle_write(struct comm_point* c) strerror(errno)); return 0; } - log_crypto_err("could not SSL_write"); + log_crypto_err_io("could not SSL_write", want); return 0; } if(c->tcp_write_and_read) { @@ -2127,7 +2145,7 @@ ssl_handle_write(struct comm_point* c) strerror(errno)); return 0; } - log_crypto_err("could not SSL_write"); + log_crypto_err_io("could not SSL_write", want); return 0; } if(c->tcp_write_and_read) { @@ -2211,19 +2229,25 @@ comm_point_tcp_handle_read(int fd, struct comm_point* c, int short_ok) goto recv_error_initial; } c->tcp_byte_count += r; + sldns_buffer_skip(c->buffer, r); if(c->tcp_byte_count != current_read_size) return 1; c->pp2_header_state = pp2_header_init; } } if(c->pp2_header_state == pp2_header_init) { - header = pp2_read_header(c->buffer); - if(!header) { + int err; + err = pp2_read_header( + sldns_buffer_begin(c->buffer), + sldns_buffer_limit(c->buffer)); + if(err) { log_err("proxy_protocol: could not parse " - "PROXYv2 header"); + "PROXYv2 header (%s)", + pp_lookup_error(err)); return 0; } + header = (struct pp2_header*)sldns_buffer_begin(c->buffer); want_read_size = ntohs(header->len); - if(sldns_buffer_remaining(c->buffer) < + if(sldns_buffer_limit(c->buffer) < PP2_HEADER_SIZE + want_read_size) { log_err_addr("proxy_protocol: not enough " "buffer size to read PROXYv2 header", "", @@ -2250,6 +2274,7 @@ comm_point_tcp_handle_read(int fd, struct comm_point* c, int short_ok) goto recv_error; } c->tcp_byte_count += r; + sldns_buffer_skip(c->buffer, r); if(c->tcp_byte_count != current_read_size) return 1; c->pp2_header_state = pp2_header_done; } @@ -2260,6 +2285,7 @@ comm_point_tcp_handle_read(int fd, struct comm_point* c, int short_ok) c->repinfo.remote_addrlen); return 0; } + sldns_buffer_flip(c->buffer); if(!consume_pp2_header(c->buffer, &c->repinfo, 1)) { log_err_addr("proxy_protocol: could not consume " "PROXYv2 header", "", &c->repinfo.remote_addr, @@ -2913,7 +2939,7 @@ ssl_http_read_more(struct comm_point* c) strerror(errno)); return 0; } - log_crypto_err("could not SSL_read"); + log_crypto_err_io("could not SSL_read", want); return 0; } verbose(VERB_ALGO, "ssl http read more skip to %d + %d", @@ -3364,7 +3390,7 @@ ssize_t http2_recv_cb(nghttp2_session* ATTR_UNUSED(session), uint8_t* buf, strerror(errno)); return NGHTTP2_ERR_CALLBACK_FAILURE; } - log_crypto_err("could not SSL_read"); + log_crypto_err_io("could not SSL_read", want); return NGHTTP2_ERR_CALLBACK_FAILURE; } return r; @@ -3619,7 +3645,7 @@ ssl_http_write_more(struct comm_point* c) strerror(errno)); return 0; } - log_crypto_err("could not SSL_write"); + log_crypto_err_io("could not SSL_write", want); return 0; } sldns_buffer_skip(c->buffer, (ssize_t)r); @@ -3692,7 +3718,7 @@ ssize_t http2_send_cb(nghttp2_session* ATTR_UNUSED(session), const uint8_t* buf, strerror(errno)); return NGHTTP2_ERR_CALLBACK_FAILURE; } - log_crypto_err("could not SSL_write"); + log_crypto_err_io("could not SSL_write", want); return NGHTTP2_ERR_CALLBACK_FAILURE; } return r; @@ -3958,11 +3984,7 @@ comm_point_create_udp(struct comm_base *base, int fd, sldns_buffer* buffer, evbits = UB_EV_READ | UB_EV_PERSIST; /* ub_event stuff */ c->ev->ev = ub_event_new(base->eb->base, c->fd, evbits, -#ifdef USE_WINSOCK comm_point_udp_callback, c); -#else - comm_point_udp_ancil_callback, c); -#endif if(c->ev->ev == NULL) { log_err("could not baseset udp event"); comm_point_delete(c); @@ -3977,6 +3999,7 @@ comm_point_create_udp(struct comm_base *base, int fd, sldns_buffer* buffer, return c; } +#if defined(AF_INET6) && defined(IPV6_PKTINFO) && defined(HAVE_RECVMSG) struct comm_point* comm_point_create_udp_ancil(struct comm_base *base, int fd, sldns_buffer* buffer, int pp2_enabled, @@ -4039,6 +4062,7 @@ comm_point_create_udp_ancil(struct comm_base *base, int fd, c->event_added = 1; return c; } +#endif static struct comm_point* comm_point_create_tcp_handler(struct comm_base *base, diff --git a/usr.sbin/unbound/validator/val_anchor.c b/usr.sbin/unbound/validator/val_anchor.c index b1a54e1f019..8466a8923eb 100644 --- a/usr.sbin/unbound/validator/val_anchor.c +++ b/usr.sbin/unbound/validator/val_anchor.c @@ -1322,3 +1322,24 @@ anchor_has_keytag(struct val_anchors* anchors, uint8_t* name, int namelabs, free(taglist); return 0; } + +struct trust_anchor* +anchors_find_any_noninsecure(struct val_anchors* anchors) +{ + struct trust_anchor* ta, *next; + lock_basic_lock(&anchors->lock); + ta=(struct trust_anchor*)rbtree_first(anchors->tree); + while((rbnode_type*)ta != RBTREE_NULL) { + next = (struct trust_anchor*)rbtree_next(&ta->node); + lock_basic_lock(&ta->lock); + if(ta->numDS != 0 || ta->numDNSKEY != 0) { + /* not an insecurepoint */ + lock_basic_unlock(&anchors->lock); + return ta; + } + lock_basic_unlock(&ta->lock); + ta = next; + } + lock_basic_unlock(&anchors->lock); + return NULL; +} diff --git a/usr.sbin/unbound/validator/val_anchor.h b/usr.sbin/unbound/validator/val_anchor.h index 1597a7d62fb..02e7e17b521 100644 --- a/usr.sbin/unbound/validator/val_anchor.h +++ b/usr.sbin/unbound/validator/val_anchor.h @@ -240,4 +240,12 @@ size_t anchor_list_keytags(struct trust_anchor* ta, uint16_t* list, size_t num); int anchor_has_keytag(struct val_anchors* anchors, uint8_t* name, int namelabs, size_t namelen, uint16_t dclass, uint16_t keytag); +/** + * Find an anchor that is not an insecure point, if any, or there are no + * DNSSEC verification anchors if none. + * @param anchors: anchor storage + * @return trust anchor or NULL. It is locked. + */ +struct trust_anchor* anchors_find_any_noninsecure(struct val_anchors* anchors); + #endif /* VALIDATOR_VAL_ANCHOR_H */ diff --git a/usr.sbin/unbound/validator/validator.c b/usr.sbin/unbound/validator/validator.c index 4dca35bbac7..26d33a37ff3 100644 --- a/usr.sbin/unbound/validator/validator.c +++ b/usr.sbin/unbound/validator/validator.c @@ -205,6 +205,17 @@ val_init(struct module_env* env, int id) log_err("validator: could not apply configuration settings."); return 0; } + if(env->cfg->disable_edns_do) { + struct trust_anchor* anchor = anchors_find_any_noninsecure( + env->anchors); + if(anchor) { + char b[LDNS_MAX_DOMAINLEN+2]; + dname_str(anchor->name, b); + log_warn("validator: disable-edns-do is enabled, but there is a trust anchor for '%s'. Since DNSSEC could not work, the disable-edns-do setting is turned off. Continuing without it.", b); + lock_basic_unlock(&anchor->lock); + env->cfg->disable_edns_do = 0; + } + } return 1; } |