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 \
$(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
## 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
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
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 "
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);
#! /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
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."
set_cc_for_build
cat <<-EOF > "$dummy.c"
+ #if defined(__ANDROID__)
+ LIBC=android
+ #else
#include <features.h>
#if defined(__UCLIBC__)
LIBC=uclibc
LIBC=dietlibc
#elif defined(__GLIBC__)
LIBC=gnu
+ #elif defined(__LLVM_LIBC__)
+ LIBC=llvm
#else
#include <stdarg.h>
/* First heuristic to detect musl libc. */
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"
fi
;;
*:FreeBSD:*:*)
- UNAME_PROCESSOR=`/usr/bin/uname -p`
+ UNAME_PROCESSOR=`uname -p`
case $UNAME_PROCESSOR in
amd64)
UNAME_PROCESSOR=x86_64 ;;
*:Unleashed:*:*)
GUESS=$UNAME_MACHINE-unknown-unleashed$UNAME_RELEASE
;;
+ *:Ironclad:*:*)
+ GUESS=$UNAME_MACHINE-unknown-ironclad
+ ;;
esac
# Do we have a guess based on uname results?
#! /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
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."
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] \
| 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 \
| moxie \
| mt \
| msp430 \
+ | nanomips* \
| nds32 | nds32le | nds32be \
| nfp \
| nios | nios2 | nios2eb | nios2el \
| ubicom32 \
| v70 | v850 | v850e | v850e1 | v850es | v850e2 | v850e2v3 \
| vax \
+ | vc4 \
| visium \
| w65 \
| wasm32 | wasm64 \
# 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
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.
;;
# 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
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-*)
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
os=sunos4.1.1
;;
pru-*)
- os=elf
+ os=
+ obj=elf
;;
*-be)
os=beos
os=uxpv
;;
*-rom68k)
- os=coff
+ os=
+ obj=coff
;;
*-*bug)
- os=coff
+ os=
+ obj=coff
;;
*-apple)
os=macos
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*)
# 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.
| 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* \
| 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
;;
;;
esac
-echo "$cpu-$vendor-${kernel:+$kernel-}$os"
+echo "$cpu-$vendor${kernel:+-$kernel}${os:+-$os}${obj:+-$obj}"
exit
# Local variables:
#! /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>.
#
# 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=''
# 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]...
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
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.
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 $@
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
# 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
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
$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
$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. */
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. */
{ $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. */
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
-version=1.18.0
+version=1.19.2
date=`date +'%b %e, %Y'`
# 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
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\\"
# 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
# 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
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
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
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"
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)
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.])
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 {
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 {
}
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;
}
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;
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;
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++;
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;
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 {
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;
#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"
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))
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))
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,
worker->env.cfg->stat_interval);
worker_restart_timer(worker);
}
+ pp_init(&sldns_write_uint16, &sldns_write_uint32);
return 1;
}
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. */
* 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 */
}
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;
}
+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.
- 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
-README for Unbound 1.18.0
+README for Unbound 1.19.2
Copyright 2007 NLnet Labs
http://unbound.net
#
# 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.
# 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
# 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)
# 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.
-.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
.\"
.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
-.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
.\"
-.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
.\"
-.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
.\"
-.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
.\"
-.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
.\"
.\"
.SH "NAME"
.B unbound
-\- Unbound DNS validating resolver 1.18.0.
+\- Unbound DNS validating resolver 1.19.2.
.SH "SYNOPSIS"
.B unbound
.RB [ \-h ]
-.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
.\"
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
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
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.
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,
* 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);
}
}
/* 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 */
}
/* 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
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. */
(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;
}
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 &&
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;
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;
#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"
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;
/* 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;
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
* @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;
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)) {
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,
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;
}
}
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;
/* 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(
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--;
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
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;
/* 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;
/* 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;
* 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.
*/
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;
#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"
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) {
hints_delete(w->env->hints);
w->env->hints = NULL;
}
+#endif
if(!w->is_bg || w->is_bg_thread) {
lock_basic_unlock(&ctx->cfglock);
}
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;
}
struct auth_rrset** rrset)
{
struct auth_data* n = node;
+ struct auth_rrset* lookrrset;
*ce = NULL;
*rrset = NULL;
if(!node_exact) {
/* 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)) {
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)
}
} 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");
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) ||
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
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;
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.
result = rbtree_first(&outnet->tcp_reuse);
}
+ /* not found, return null */
if(!result || result == RBTREE_NULL)
return NULL;
(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
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 */
{ 6, "DHU" },
{ 7, "N3U" },
{ 8, "edns-client-subnet" },
+ { 10, "COOKIE" },
{ 11, "edns-tcp-keepalive"},
{ 12, "Padding" },
{ 15, "EDE"},
};
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" },
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)
{
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);
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 */
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.
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 */
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;
#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;
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
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; }
{ 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
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)
#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)
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
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 */
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;
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 */
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) }
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) }
%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
%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 ;
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
{
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));
| ;
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
{
#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)
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));
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 {
#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"
}
}
+/** 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;
+}
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 */
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;
default_ident = id;
}
-void log_ident_revert_to_default()
+void log_ident_revert_to_default(void)
{
ident = default_ident;
}
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];
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;
*/
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.
#endif /* HAVE_SSL */
}
+#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
*/
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
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. */
}
/* 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;
}
/* 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;
}
/* 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:
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];
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)
} 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);
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", "",
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;
}
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,
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;
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);
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) {
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) {
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", "",
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;
}
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,
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",
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;
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);
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;
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);
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,
c->event_added = 1;
return c;
}
+#endif
static struct comm_point*
comm_point_create_tcp_handler(struct comm_base *base,
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;
+}
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 */
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;
}