diff options
author | Brad Smith <brad@cvs.openbsd.org> | 2014-11-20 00:00:39 +0000 |
---|---|---|
committer | Brad Smith <brad@cvs.openbsd.org> | 2014-11-20 00:00:39 +0000 |
commit | 07c6cec57079d8ed326998c1b910ac76461dffc3 (patch) | |
tree | a9cdd7792ba1e19759ee607268be81f82fa4eda6 /usr.sbin | |
parent | 0527c7828f578c661937a9e2df91d279f942d669 (diff) |
update to Unbound 1.5.0, ok sthen@
Diffstat (limited to 'usr.sbin')
69 files changed, 3589 insertions, 635 deletions
diff --git a/usr.sbin/unbound/aclocal.m4 b/usr.sbin/unbound/aclocal.m4 index 4e52c652062..a50a63068e2 100644 --- a/usr.sbin/unbound/aclocal.m4 +++ b/usr.sbin/unbound/aclocal.m4 @@ -1,6 +1,6 @@ -# generated automatically by aclocal 1.12.2 -*- Autoconf -*- +# generated automatically by aclocal 1.13.4 -*- Autoconf -*- -# Copyright (C) 1996-2012 Free Software Foundation, Inc. +# Copyright (C) 1996-2013 Free Software Foundation, Inc. # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -11,6 +11,7 @@ # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. +m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])]) # libtool.m4 - Configure libtool for the host system. -*-Autoconf-*- # # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, @@ -1317,7 +1318,7 @@ ia64-*-hpux*) rm -rf conftest* ;; -x86_64-*kfreebsd*-gnu|x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*| \ +x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \ s390*-*linux*|s390*-*tpf*|sparc*-*linux*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext @@ -1331,7 +1332,10 @@ s390*-*linux*|s390*-*tpf*|sparc*-*linux*) x86_64-*linux*) LD="${LD-ld} -m elf_i386" ;; - ppc64-*linux*|powerpc64-*linux*) + powerpc64le-*linux*) + LD="${LD-ld} -m elf32lppclinux" + ;; + powerpc64-*linux*) LD="${LD-ld} -m elf32ppclinux" ;; s390x-*linux*) @@ -1350,7 +1354,10 @@ s390*-*linux*|s390*-*tpf*|sparc*-*linux*) x86_64-*linux*) LD="${LD-ld} -m elf_x86_64" ;; - ppc*-*linux*|powerpc*-*linux*) + powerpcle-*linux*) + LD="${LD-ld} -m elf64lppc" + ;; + powerpc-*linux*) LD="${LD-ld} -m elf64ppc" ;; s390*-*linux*|s390*-*tpf*) diff --git a/usr.sbin/unbound/acx_python.m4 b/usr.sbin/unbound/acx_python.m4 index 99ffa254a8e..254ff209628 100644 --- a/usr.sbin/unbound/acx_python.m4 +++ b/usr.sbin/unbound/acx_python.m4 @@ -14,58 +14,11 @@ AC_DEFUN([AC_PYTHON_DEVEL],[ fi if test -z "$PYTHON_VERSION"; then - PYTHON_VERSION=`$PYTHON -c "import sys, string; \ - print string.split(sys.version)[[0]]"` + PYTHON_VERSION=`$PYTHON -c "import sys; \ + print(sys.version.split()[[0]])"` fi # - # Check for a version of Python >= 2.1.0 - # - AC_MSG_CHECKING([for a version of Python >= '2.1.0']) - ac_supports_python_ver=`$PYTHON -c "import sys, string; \ - ver = string.split(sys.version)[[0]]; \ - print ver >= '2.1.0'"` - if test "$ac_supports_python_ver" != "True"; then - if test -z "$PYTHON_NOVERSIONCHECK"; then - AC_MSG_RESULT([no]) - AC_MSG_FAILURE([ -This version of the AC@&t@_PYTHON_DEVEL macro -doesn't work properly with versions of Python before -2.1.0. You may need to re-run configure, setting the -variables PYTHON_CPPFLAGS, PYTHON_LDFLAGS, PYTHON_SITE_PKG, -PYTHON_EXTRA_LIBS and PYTHON_EXTRA_LDFLAGS by hand. -Moreover, to disable this check, set PYTHON_NOVERSIONCHECK -to something else than an empty string. -]) - else - AC_MSG_RESULT([skip at user request]) - fi - else - AC_MSG_RESULT([yes]) - fi - - # - # if the macro parameter ``version'' is set, honour it - # - if test -n "$1"; then - AC_MSG_CHECKING([for a version of Python $1]) - ac_supports_python_ver=`$PYTHON -c "import sys, string; \ - ver = string.split(sys.version)[[0]]; \ - print ver $1"` - if test "$ac_supports_python_ver" = "True"; then - AC_MSG_RESULT([yes]) - else - AC_MSG_RESULT([no]) - AC_MSG_ERROR([this package requires Python $1. -If you have it installed, but it isn't the default Python -interpreter in your system path, please pass the PYTHON_VERSION -variable to configure. See ``configure --help'' for reference. -]) - PYTHON_VERSION="" - fi - fi - - # # Check if you have distutils, else fail # AC_MSG_CHECKING([for the distutils Python package]) @@ -86,7 +39,7 @@ $ac_distutils_result]) AC_MSG_CHECKING([for Python include path]) if test -z "$PYTHON_CPPFLAGS"; then python_path=`$PYTHON -c "import distutils.sysconfig; \ - print distutils.sysconfig.get_python_inc();"` + print(distutils.sysconfig.get_python_inc());"` if test -n "${python_path}"; then python_path="-I$python_path" fi @@ -100,25 +53,8 @@ $ac_distutils_result]) # AC_MSG_CHECKING([for Python library path]) if test -z "$PYTHON_LDFLAGS"; then - # (makes two attempts to ensure we've got a version number - # from the interpreter) - py_version=`$PYTHON -c "from distutils.sysconfig import *; \ - from string import join; \ - print join(get_config_vars('VERSION'))"` - if test "$py_version" = "[None]"; then - if test -n "$PYTHON_VERSION"; then - py_version=$PYTHON_VERSION - else - py_version=`$PYTHON -c "import sys; \ - print sys.version[[:3]]"` - fi - fi - PYTHON_LDFLAGS=`$PYTHON -c "from distutils.sysconfig import *; \ - from string import join; \ - print '-L' + get_python_lib(0,1), \ - '-L' + os.path.dirname(get_python_lib(0,1)), \ - '-lpython';"`$py_version + print(get_config_var('BLDLIBRARY'));"` fi AC_MSG_RESULT([$PYTHON_LDFLAGS]) AC_SUBST([PYTHON_LDFLAGS]) @@ -129,36 +65,12 @@ $ac_distutils_result]) AC_MSG_CHECKING([for Python site-packages path]) if test -z "$PYTHON_SITE_PKG"; then PYTHON_SITE_PKG=`$PYTHON -c "import distutils.sysconfig; \ - print distutils.sysconfig.get_python_lib(1,0);"` + print(distutils.sysconfig.get_python_lib(1,0));"` fi AC_MSG_RESULT([$PYTHON_SITE_PKG]) AC_SUBST([PYTHON_SITE_PKG]) # - # libraries which must be linked in when embedding - # - AC_MSG_CHECKING(python extra libraries) - if test -z "$PYTHON_EXTRA_LIBS"; then - PYTHON_EXTRA_LIBS=`$PYTHON -c "import distutils.sysconfig; \ - conf = distutils.sysconfig.get_config_var; \ - print conf('LOCALMODLIBS'), conf('LIBS')"` - fi - AC_MSG_RESULT([$PYTHON_EXTRA_LIBS]) - AC_SUBST(PYTHON_EXTRA_LIBS) - - # - # linking flags needed when embedding - # - AC_MSG_CHECKING(python extra linking flags) - if test -z "$PYTHON_EXTRA_LDFLAGS"; then - PYTHON_EXTRA_LDFLAGS=`$PYTHON -c "import distutils.sysconfig; \ - conf = distutils.sysconfig.get_config_var; \ - print conf('LINKFORSHARED')"` - fi - AC_MSG_RESULT([$PYTHON_EXTRA_LDFLAGS]) - AC_SUBST(PYTHON_EXTRA_LDFLAGS) - - # # final check to see if everything compiles alright # AC_MSG_CHECKING([consistency of all components of python development environment]) diff --git a/usr.sbin/unbound/config.guess b/usr.sbin/unbound/config.guess index c0adba94b2f..b79252d6b10 100755..100644 --- a/usr.sbin/unbound/config.guess +++ b/usr.sbin/unbound/config.guess @@ -1,14 +1,12 @@ #! /bin/sh # Attempt to guess a canonical system name. -# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, -# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, -# 2011, 2012 Free Software Foundation, Inc. +# Copyright 1992-2013 Free Software Foundation, Inc. -timestamp='2012-06-10' +timestamp='2013-06-10' # 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 -# the Free Software Foundation; either version 2 of the License, or +# the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, but @@ -22,19 +20,17 @@ timestamp='2012-06-10' # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that program. - - -# Originally written by Per Bothner. Please send patches (context -# diff format) to <config-patches@gnu.org> and include a ChangeLog -# entry. +# the same distribution terms that you use for the rest of that +# program. This Exception is an additional permission under section 7 +# of the GNU General Public License, version 3 ("GPLv3"). # -# This script attempts to guess a canonical system name similar to -# config.sub. If it succeeds, it prints the system name on stdout, and -# exits with 0. Otherwise, it exits with 1. +# Originally written by Per Bothner. # # You can get the latest version of this script from: # http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD +# +# Please send patches with a ChangeLog entry to config-patches@gnu.org. + me=`echo "$0" | sed -e 's,.*/,,'` @@ -54,9 +50,7 @@ version="\ GNU config.guess ($timestamp) Originally written by Per Bothner. -Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, -2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 -Free Software Foundation, Inc. +Copyright 1992-2013 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." @@ -138,6 +132,27 @@ UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown +case "${UNAME_SYSTEM}" in +Linux|GNU|GNU/*) + # If the system lacks a compiler, then just pick glibc. + # We could probably try harder. + LIBC=gnu + + eval $set_cc_for_build + cat <<-EOF > $dummy.c + #include <features.h> + #if defined(__UCLIBC__) + LIBC=uclibc + #elif defined(__dietlibc__) + LIBC=dietlibc + #else + LIBC=gnu + #endif + EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC'` + ;; +esac + # Note: order is significant - the case branches are not exclusive. case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in @@ -200,6 +215,10 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. echo "${machine}-${os}${release}" exit ;; + *:Bitrig:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'` + echo ${UNAME_MACHINE_ARCH}-unknown-bitrig${UNAME_RELEASE} + exit ;; *:OpenBSD:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} @@ -302,7 +321,7 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) echo arm-acorn-riscix${UNAME_RELEASE} exit ;; - arm:riscos:*:*|arm:RISCOS:*:*) + arm*:riscos:*:*|arm*:RISCOS:*:*) echo arm-unknown-riscos exit ;; SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) @@ -801,6 +820,9 @@ EOF i*:CYGWIN*:*) echo ${UNAME_MACHINE}-pc-cygwin exit ;; + *:MINGW64*:*) + echo ${UNAME_MACHINE}-pc-mingw64 + exit ;; *:MINGW*:*) echo ${UNAME_MACHINE}-pc-mingw32 exit ;; @@ -852,21 +874,21 @@ EOF exit ;; *:GNU:*:*) # the GNU system - echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` + echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-${LIBC}`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` exit ;; *:GNU/*:*:*) # other systems with GNU libc and userland - echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu + echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-${LIBC} exit ;; i*86:Minix:*:*) echo ${UNAME_MACHINE}-pc-minix exit ;; aarch64:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; aarch64_be:Linux:*:*) UNAME_MACHINE=aarch64_be - echo ${UNAME_MACHINE}-unknown-linux-gnu + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; alpha:Linux:*:*) case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in @@ -879,59 +901,54 @@ EOF EV68*) UNAME_MACHINE=alphaev68 ;; esac objdump --private-headers /bin/sh | grep -q ld.so.1 - if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi - echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} + if test "$?" = 0 ; then LIBC="gnulibc1" ; fi + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; + arc:Linux:*:* | arceb:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; arm*:Linux:*:*) eval $set_cc_for_build if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ARM_EABI__ then - echo ${UNAME_MACHINE}-unknown-linux-gnu + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} else if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ARM_PCS_VFP then - echo ${UNAME_MACHINE}-unknown-linux-gnueabi + echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabi else - echo ${UNAME_MACHINE}-unknown-linux-gnueabihf + echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabihf fi fi exit ;; avr32*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; cris:Linux:*:*) - echo ${UNAME_MACHINE}-axis-linux-gnu + echo ${UNAME_MACHINE}-axis-linux-${LIBC} exit ;; crisv32:Linux:*:*) - echo ${UNAME_MACHINE}-axis-linux-gnu + echo ${UNAME_MACHINE}-axis-linux-${LIBC} exit ;; frv:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; hexagon:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; i*86:Linux:*:*) - LIBC=gnu - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c - #ifdef __dietlibc__ - LIBC=dietlibc - #endif -EOF - eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC'` - echo "${UNAME_MACHINE}-pc-linux-${LIBC}" + echo ${UNAME_MACHINE}-pc-linux-${LIBC} exit ;; ia64:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; m32r*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; m68*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; mips:Linux:*:* | mips64:Linux:*:*) eval $set_cc_for_build @@ -950,54 +967,63 @@ EOF #endif EOF eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'` - test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; } + test x"${CPU}" != x && { echo "${CPU}-unknown-linux-${LIBC}"; exit; } ;; + or1k:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; or32:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; padre:Linux:*:*) - echo sparc-unknown-linux-gnu + echo sparc-unknown-linux-${LIBC} exit ;; parisc64:Linux:*:* | hppa64:Linux:*:*) - echo hppa64-unknown-linux-gnu + echo hppa64-unknown-linux-${LIBC} exit ;; parisc:Linux:*:* | hppa:Linux:*:*) # Look for CPU level case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in - PA7*) echo hppa1.1-unknown-linux-gnu ;; - PA8*) echo hppa2.0-unknown-linux-gnu ;; - *) echo hppa-unknown-linux-gnu ;; + PA7*) echo hppa1.1-unknown-linux-${LIBC} ;; + PA8*) echo hppa2.0-unknown-linux-${LIBC} ;; + *) echo hppa-unknown-linux-${LIBC} ;; esac exit ;; ppc64:Linux:*:*) - echo powerpc64-unknown-linux-gnu + echo powerpc64-unknown-linux-${LIBC} exit ;; ppc:Linux:*:*) - echo powerpc-unknown-linux-gnu + echo powerpc-unknown-linux-${LIBC} + exit ;; + ppc64le:Linux:*:*) + echo powerpc64le-unknown-linux-${LIBC} + exit ;; + ppcle:Linux:*:*) + echo powerpcle-unknown-linux-${LIBC} exit ;; s390:Linux:*:* | s390x:Linux:*:*) - echo ${UNAME_MACHINE}-ibm-linux + echo ${UNAME_MACHINE}-ibm-linux-${LIBC} exit ;; sh64*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; sh*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; sparc:Linux:*:* | sparc64:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; tile*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; vax:Linux:*:*) - echo ${UNAME_MACHINE}-dec-linux-gnu + echo ${UNAME_MACHINE}-dec-linux-${LIBC} exit ;; x86_64:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; xtensa*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; i*86:DYNIX/ptx:4*:*) # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. @@ -1201,6 +1227,9 @@ EOF BePC:Haiku:*:*) # Haiku running on Intel PC compatible. echo i586-pc-haiku exit ;; + x86_64:Haiku:*:*) + echo x86_64-unknown-haiku + exit ;; SX-4:SUPER-UX:*:*) echo sx4-nec-superux${UNAME_RELEASE} exit ;; @@ -1227,19 +1256,21 @@ EOF exit ;; *:Darwin:*:*) UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown - case $UNAME_PROCESSOR in - i386) - eval $set_cc_for_build - if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then - if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ - (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ - grep IS_64BIT_ARCH >/dev/null - then - UNAME_PROCESSOR="x86_64" - fi - fi ;; - unknown) UNAME_PROCESSOR=powerpc ;; - esac + eval $set_cc_for_build + if test "$UNAME_PROCESSOR" = unknown ; then + UNAME_PROCESSOR=powerpc + fi + if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then + if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + case $UNAME_PROCESSOR in + i386) UNAME_PROCESSOR=x86_64 ;; + powerpc) UNAME_PROCESSOR=powerpc64 ;; + esac + fi + fi echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} exit ;; *:procnto*:*:* | *:QNX:[0123456789]*:*) @@ -1330,9 +1361,6 @@ EOF exit ;; esac -#echo '(No uname command or uname output not recognized.)' 1>&2 -#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2 - eval $set_cc_for_build cat >$dummy.c <<EOF #ifdef _SEQUENT_ diff --git a/usr.sbin/unbound/config.h.in b/usr.sbin/unbound/config.h.in index ffab98c1d64..5f8f8a992de 100644 --- a/usr.sbin/unbound/config.h.in +++ b/usr.sbin/unbound/config.h.in @@ -1,20 +1,17 @@ /* config.h.in. Generated from configure.ac by autoheader. */ +/* define if a library can reference the 'main' symbol */ +#undef CAN_REFERENCE_MAIN + /* Directory to chroot to */ #undef CHROOT_DIR +/* Do sha512 definitions in config.h */ +#undef COMPAT_SHA512 + /* Pathname to the Unbound configuration file */ #undef CONFIGFILE -/* configure flags */ -#undef CONFIGURE_BUILD_WITH - -/* configure date */ -#undef CONFIGURE_DATE - -/* configure target system */ -#undef CONFIGURE_TARGET - /* Define this if on macOSX10.4-darwin8 and setreuid and setregid do not work */ #undef DARWIN_BROKEN_SETREUID @@ -22,6 +19,9 @@ /* Whether daemon is deprecated */ #undef DEPRECATED_DAEMON +/* default dnstap socket path */ +#undef DNSTAP_SOCKET_PATH + /* Define if you want to use debug lock checking (slow). */ #undef ENABLE_LOCK_CHECKS @@ -30,6 +30,12 @@ internal symbols */ #undef EXPORT_ALL_SYMBOLS +/* Define to 1 if you have the `arc4random' function. */ +#undef HAVE_ARC4RANDOM + +/* Define to 1 if you have the `arc4random_uniform' function. */ +#undef HAVE_ARC4RANDOM_UNIFORM + /* Define to 1 if you have the <arpa/inet.h> header file. */ #undef HAVE_ARPA_INET_H @@ -51,6 +57,14 @@ /* Define to 1 if you have the `daemon' function. */ #undef HAVE_DAEMON +/* Define to 1 if you have the declaration of `arc4random', and to 0 if you + don't. */ +#undef HAVE_DECL_ARC4RANDOM + +/* Define to 1 if you have the declaration of `arc4random_uniform', and to 0 + if you don't. */ +#undef HAVE_DECL_ARC4RANDOM_UNIFORM + /* Define to 1 if you have the declaration of `NID_secp384r1', and to 0 if you don't. */ #undef HAVE_DECL_NID_SECP384R1 @@ -67,9 +81,20 @@ `SSL_COMP_get_compression_methods', and to 0 if you don't. */ #undef HAVE_DECL_SSL_COMP_GET_COMPRESSION_METHODS +/* Define to 1 if you have the declaration of `strlcat', and to 0 if you + don't. */ +#undef HAVE_DECL_STRLCAT + +/* Define to 1 if you have the declaration of `strlcpy', and to 0 if you + don't. */ +#undef HAVE_DECL_STRLCPY + /* Define to 1 if you have the <dlfcn.h> header file. */ #undef HAVE_DLFCN_H +/* Define to 1 if you have the <endian.h> header file. */ +#undef HAVE_ENDIAN_H + /* Define to 1 if you have the `endprotoent' function. */ #undef HAVE_ENDPROTOENT @@ -124,6 +149,9 @@ /* Whether getaddrinfo is available */ #undef HAVE_GETADDRINFO +/* Define to 1 if you have the `getentropy' function. */ +#undef HAVE_GETENTROPY + /* Define to 1 if you have the <getopt.h> header file. */ #undef HAVE_GETOPT_H @@ -172,6 +200,9 @@ /* Define to 1 if you have the `kill' function. */ #undef HAVE_KILL +/* Define if we have LibreSSL */ +#undef HAVE_LIBRESSL + /* Define to 1 if you have the `localtime_r' function. */ #undef HAVE_LOCALTIME_R @@ -265,6 +296,9 @@ /* Define to 1 if you have the `setusercontext' function. */ #undef HAVE_SETUSERCONTEXT +/* Define to 1 if you have the `SHA512_Update' function. */ +#undef HAVE_SHA512_UPDATE + /* Define to 1 if you have the `sigprocmask' function. */ #undef HAVE_SIGPROCMASK @@ -331,12 +365,18 @@ /* Define to 1 if you have the <sys/resource.h> header file. */ #undef HAVE_SYS_RESOURCE_H +/* Define to 1 if you have the <sys/sha2.h> header file. */ +#undef HAVE_SYS_SHA2_H + /* Define to 1 if you have the <sys/socket.h> header file. */ #undef HAVE_SYS_SOCKET_H /* Define to 1 if you have the <sys/stat.h> header file. */ #undef HAVE_SYS_STAT_H +/* Define to 1 if you have the <sys/sysctl.h> header file. */ +#undef HAVE_SYS_SYSCTL_H + /* Define to 1 if you have the <sys/types.h> header file. */ #undef HAVE_SYS_TYPES_H @@ -502,6 +542,9 @@ /* define this to enable debug checks. */ #undef UNBOUND_DEBUG +/* Define to 1 to enable dnstap support */ +#undef USE_DNSTAP + /* Define this to enable ECDSA support. */ #undef USE_ECDSA @@ -888,6 +931,50 @@ struct tm; char *strptime(const char *s, const char *format, struct tm *tm); #endif +#ifdef HAVE_LIBRESSL +# if !HAVE_DECL_STRLCPY +size_t strlcpy(char *dst, const char *src, size_t siz); +# endif +# if !HAVE_DECL_STRLCAT +size_t strlcat(char *dst, const char *src, size_t siz); +# endif +# if !HAVE_DECL_ARC4RANDOM && defined(HAVE_ARC4RANDOM) +uint32_t arc4random(void); +# endif +# if !HAVE_DECL_ARC4RANDOM_UNIFORM && defined(HAVE_ARC4RANDOM_UNIFORM) +uint32_t arc4random_uniform(uint32_t upper_bound); +# endif +#endif /* HAVE_LIBRESSL */ +#ifndef HAVE_ARC4RANDOM +void explicit_bzero(void* buf, size_t len); +int getentropy(void* buf, size_t len); +uint32_t arc4random(void); +void arc4random_buf(void* buf, size_t n); +void _ARC4_LOCK(void); +void _ARC4_UNLOCK(void); +#endif +#ifndef HAVE_ARC4RANDOM_UNIFORM +uint32_t arc4random_uniform(uint32_t upper_bound); +#endif +#ifdef COMPAT_SHA512 +#ifndef SHA512_DIGEST_LENGTH +#define SHA512_BLOCK_LENGTH 128 +#define SHA512_DIGEST_LENGTH 64 +#define SHA512_DIGEST_STRING_LENGTH (SHA512_DIGEST_LENGTH * 2 + 1) +typedef struct _SHA512_CTX { + uint64_t state[8]; + uint64_t bitcount[2]; + uint8_t buffer[SHA512_BLOCK_LENGTH]; +} SHA512_CTX; +#endif /* SHA512_DIGEST_LENGTH */ +void SHA512_Init(SHA512_CTX*); +void SHA512_Update(SHA512_CTX*, void*, size_t); +void SHA512_Final(uint8_t[SHA512_DIGEST_LENGTH], SHA512_CTX*); +unsigned char *SHA512(void* data, unsigned int data_len, unsigned char *digest); +#endif /* COMPAT_SHA512 */ + + + #if defined(HAVE_EVENT_H) && !defined(HAVE_EVENT_BASE_ONCE) && !(defined(HAVE_EV_LOOP) || defined(HAVE_EV_DEFAULT_LOOP)) && (defined(HAVE_PTHREAD) || defined(HAVE_SOLARIS_THREADS)) /* using version of libevent that is not threadsafe. */ # define LIBEVENT_SIGNAL_PROBLEM 1 diff --git a/usr.sbin/unbound/config.sub b/usr.sbin/unbound/config.sub index 6205f8423d6..d2a96130330 100755..100644 --- a/usr.sbin/unbound/config.sub +++ b/usr.sbin/unbound/config.sub @@ -1,24 +1,18 @@ #! /bin/sh # Configuration validation subroutine script. -# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, -# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, -# 2011, 2012 Free Software Foundation, Inc. +# Copyright 1992-2013 Free Software Foundation, Inc. -timestamp='2012-04-18' +timestamp='2013-08-10' -# This file is (in principle) common to ALL GNU software. -# The presence of a machine in this file suggests that SOME GNU software -# can handle that machine. It does not imply ALL GNU software can. -# -# 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 -# the Free Software Foundation; either version 2 of the License, or +# 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 +# the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. # -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, see <http://www.gnu.org/licenses/>. @@ -26,11 +20,12 @@ timestamp='2012-04-18' # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that program. +# the same distribution terms that you use for the rest of that +# program. This Exception is an additional permission under section 7 +# of the GNU General Public License, version 3 ("GPLv3"). -# Please send patches to <config-patches@gnu.org>. Submit a context -# diff and a properly formatted GNU ChangeLog entry. +# Please send patches with a ChangeLog entry to config-patches@gnu.org. # # Configuration subroutine to validate and canonicalize a configuration type. # Supply the specified configuration type as an argument. @@ -73,9 +68,7 @@ Report bugs and patches to <config-patches@gnu.org>." version="\ GNU config.sub ($timestamp) -Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, -2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 -Free Software Foundation, Inc. +Copyright 1992-2013 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." @@ -123,7 +116,7 @@ esac maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` case $maybe_os in nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \ - linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ + linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ knetbsd*-gnu* | netbsd*-gnu* | \ kopensolaris*-gnu* | \ storm-chaos* | os2-emx* | rtmk-nova*) @@ -156,7 +149,7 @@ case $os in -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ - -apple | -axis | -knuth | -cray | -microblaze) + -apple | -axis | -knuth | -cray | -microblaze*) os= basic_machine=$1 ;; @@ -259,10 +252,12 @@ case $basic_machine in | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ | am33_2.0 \ - | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \ - | be32 | be64 \ + | arc | arceb \ + | arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \ + | avr | avr32 \ + | be32 | be64 \ | bfin \ - | c4x | clipper \ + | c4x | c8051 | clipper \ | d10v | d30v | dlx | dsp16xx \ | epiphany \ | fido | fr30 | frv \ @@ -273,7 +268,7 @@ case $basic_machine in | le32 | le64 \ | lm32 \ | m32c | m32r | m32rle | m68000 | m68k | m88k \ - | maxq | mb | microblaze | mcore | mep | metag \ + | maxq | mb | microblaze | microblazeel | mcore | mep | metag \ | mips | mipsbe | mipseb | mipsel | mipsle \ | mips16 \ | mips64 | mips64el \ @@ -291,16 +286,17 @@ case $basic_machine in | mipsisa64r2 | mipsisa64r2el \ | mipsisa64sb1 | mipsisa64sb1el \ | mipsisa64sr71k | mipsisa64sr71kel \ + | mipsr5900 | mipsr5900el \ | mipstx39 | mipstx39el \ | mn10200 | mn10300 \ | moxie \ | mt \ | msp430 \ | nds32 | nds32le | nds32be \ - | nios | nios2 \ + | nios | nios2 | nios2eb | nios2el \ | ns16k | ns32k \ | open8 \ - | or32 \ + | or1k | or32 \ | pdp10 | pdp11 | pj | pjl \ | powerpc | powerpc64 | powerpc64le | powerpcle \ | pyramid \ @@ -370,13 +366,13 @@ case $basic_machine in | aarch64-* | aarch64_be-* \ | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ - | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ + | alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \ | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ | avr-* | avr32-* \ | be32-* | be64-* \ | bfin-* | bs2000-* \ | c[123]* | c30-* | [cjt]90-* | c4x-* \ - | clipper-* | craynv-* | cydra-* \ + | c8051-* | clipper-* | craynv-* | cydra-* \ | d10v-* | d30v-* | dlx-* \ | elxsi-* \ | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ @@ -389,7 +385,8 @@ case $basic_machine in | lm32-* \ | m32c-* | m32r-* | m32rle-* \ | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ - | m88110-* | m88k-* | maxq-* | mcore-* | metag-* | microblaze-* \ + | m88110-* | m88k-* | maxq-* | mcore-* | metag-* \ + | microblaze-* | microblazeel-* \ | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ | mips16-* \ | mips64-* | mips64el-* \ @@ -407,12 +404,13 @@ case $basic_machine in | mipsisa64r2-* | mipsisa64r2el-* \ | mipsisa64sb1-* | mipsisa64sb1el-* \ | mipsisa64sr71k-* | mipsisa64sr71kel-* \ + | mipsr5900-* | mipsr5900el-* \ | mipstx39-* | mipstx39el-* \ | mmix-* \ | mt-* \ | msp430-* \ | nds32-* | nds32le-* | nds32be-* \ - | nios-* | nios2-* \ + | nios-* | nios2-* | nios2eb-* | nios2el-* \ | none-* | np1-* | ns16k-* | ns32k-* \ | open8-* \ | orion-* \ @@ -788,11 +786,15 @@ case $basic_machine in basic_machine=ns32k-utek os=-sysv ;; - microblaze) + microblaze*) basic_machine=microblaze-xilinx ;; + mingw64) + basic_machine=x86_64-pc + os=-mingw64 + ;; mingw32) - basic_machine=i386-pc + basic_machine=i686-pc os=-mingw32 ;; mingw32ce) @@ -828,7 +830,7 @@ case $basic_machine in basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` ;; msys) - basic_machine=i386-pc + basic_machine=i686-pc os=-msys ;; mvs) @@ -1004,7 +1006,7 @@ case $basic_machine in ;; ppc64) basic_machine=powerpc64-unknown ;; - ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` + ppc64-* | ppc64p7-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppc64le | powerpc64little | ppc64-le | powerpc64-little) basic_machine=powerpc64le-unknown @@ -1019,7 +1021,11 @@ case $basic_machine in basic_machine=i586-unknown os=-pw32 ;; - rdos) + rdos | rdos64) + basic_machine=x86_64-pc + os=-rdos + ;; + rdos32) basic_machine=i386-pc os=-rdos ;; @@ -1346,21 +1352,21 @@ case $os in -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\ | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \ - | -sym* | -kopensolaris* \ + | -sym* | -kopensolaris* | -plan9* \ | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ | -aos* | -aros* \ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ - | -openbsd* | -solidbsd* \ + | -bitrig* | -openbsd* | -solidbsd* \ | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ | -chorusos* | -chorusrdb* | -cegcc* \ | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ - | -mingw32* | -linux-gnu* | -linux-android* \ - | -linux-newlib* | -linux-uclibc* \ + | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \ + | -linux-newlib* | -linux-musl* | -linux-uclibc* \ | -uxpv* | -beos* | -mpeix* | -udk* \ | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ @@ -1492,9 +1498,6 @@ case $os in -aros*) os=-aros ;; - -kaos*) - os=-kaos - ;; -zvmoe) os=-zvmoe ;; @@ -1543,6 +1546,9 @@ case $basic_machine in c4x-* | tic4x-*) os=-coff ;; + c8051-*) + os=-elf + ;; hexagon-*) os=-elf ;; @@ -1586,6 +1592,9 @@ case $basic_machine in mips*-*) os=-elf ;; + or1k-*) + os=-elf + ;; or32-*) os=-coff ;; diff --git a/usr.sbin/unbound/daemon/daemon.c b/usr.sbin/unbound/daemon/daemon.c index aed22c2db7f..f693a0285a2 100644 --- a/usr.sbin/unbound/daemon/daemon.c +++ b/usr.sbin/unbound/daemon/daemon.c @@ -109,8 +109,9 @@ int ub_c_lex_destroy(void); static RETSIGTYPE record_sigh(int sig) { #ifdef LIBEVENT_SIGNAL_PROBLEM - verbose(VERB_OPS, "quit on signal, no cleanup and statistics, " - "because installed libevent version is not threadsafe"); + /* cannot log, verbose here because locks may be held */ + /* quit on signal, no cleanup and statistics, + because installed libevent version is not threadsafe */ exit(0); #endif switch(sig) @@ -135,7 +136,8 @@ static RETSIGTYPE record_sigh(int sig) break; #endif default: - log_err("ignoring signal %d", sig); + /* ignoring signal */ + break; } } @@ -256,8 +258,8 @@ daemon_open_shared_ports(struct daemon* daemon) log_assert(daemon); if(daemon->cfg->port != daemon->listening_port) { size_t i; - int reuseport = 0; struct listen_port* p0; + daemon->reuseport = 0; /* free and close old ports */ if(daemon->ports != NULL) { for(i=0; i<daemon->num_ports; i++) @@ -266,17 +268,17 @@ daemon_open_shared_ports(struct daemon* daemon) daemon->ports = NULL; } /* see if we want to reuseport */ -#if defined(__linux__) && defined(SO_REUSEPORT) +#ifdef SO_REUSEPORT if(daemon->cfg->so_reuseport && daemon->cfg->num_threads > 0) - reuseport = 1; + daemon->reuseport = 1; #endif /* try to use reuseport */ - p0 = listening_ports_open(daemon->cfg, &reuseport); + p0 = listening_ports_open(daemon->cfg, &daemon->reuseport); if(!p0) { listening_ports_free(p0); return 0; } - if(reuseport) { + if(daemon->reuseport) { /* reuseport was successful, allocate for it */ daemon->num_ports = (size_t)daemon->cfg->num_threads; } else { @@ -290,12 +292,13 @@ daemon_open_shared_ports(struct daemon* daemon) return 0; } daemon->ports[0] = p0; - if(reuseport) { + if(daemon->reuseport) { /* continue to use reuseport */ for(i=1; i<daemon->num_ports; i++) { if(!(daemon->ports[i]= listening_ports_open(daemon->cfg, - &reuseport)) || !reuseport ) { + &daemon->reuseport)) + || !daemon->reuseport ) { for(i=0; i<daemon->num_ports; i++) listening_ports_free(daemon->ports[i]); free(daemon->ports); @@ -398,6 +401,17 @@ daemon_create_workers(struct daemon* daemon) daemon->num = (daemon->cfg->num_threads?daemon->cfg->num_threads:1); daemon->workers = (struct worker**)calloc((size_t)daemon->num, sizeof(struct worker*)); + if(daemon->cfg->dnstap) { +#ifdef USE_DNSTAP + daemon->dtenv = dt_create(daemon->cfg->dnstap_socket_path, + (unsigned int)daemon->num); + if (!daemon->dtenv) + fatal_exit("dt_create failed"); + dt_apply_cfg(daemon->dtenv, daemon->cfg); +#else + fatal_exit("dnstap enabled in config but not built with dnstap support"); +#endif + } for(i=0; i<daemon->num; i++) { if(!(daemon->workers[i] = worker_create(daemon, i, shufport+numport*i/daemon->num, @@ -448,7 +462,7 @@ thread_start(void* arg) tube_close_write(worker->cmd); close_other_pipes(worker->daemon, worker->thread_num); #endif -#if defined(__linux__) && defined(SO_REUSEPORT) +#ifdef SO_REUSEPORT if(worker->daemon->cfg->so_reuseport) port_num = worker->thread_num; else @@ -582,6 +596,9 @@ daemon_cleanup(struct daemon* daemon) free(daemon->workers); daemon->workers = NULL; daemon->num = 0; +#ifdef USE_DNSTAP + dt_delete(daemon->dtenv); +#endif daemon->cfg = NULL; } diff --git a/usr.sbin/unbound/daemon/daemon.h b/usr.sbin/unbound/daemon/daemon.h index 855b0d34408..86ddab1df73 100644 --- a/usr.sbin/unbound/daemon/daemon.h +++ b/usr.sbin/unbound/daemon/daemon.h @@ -59,6 +59,11 @@ struct local_zones; struct ub_randstate; struct daemon_remote; +#include "dnstap/dnstap_config.h" +#ifdef USE_DNSTAP +struct dt_env; +#endif + /** * Structure holding worker list. * Holds globally visible information. @@ -77,6 +82,8 @@ struct daemon { struct listen_port** ports; /** size of ports array */ size_t num_ports; + /** reuseport is enabled if true */ + int reuseport; /** port number for remote that has ports opened. */ int rc_port; /** listening ports for remote control */ @@ -107,6 +114,10 @@ struct daemon { struct timeval time_last_stat; /** time when daemon started */ struct timeval time_boot; +#ifdef USE_DNSTAP + /** the dnstap environment master value, copied and changed by threads*/ + struct dt_env* dtenv; +#endif }; /** diff --git a/usr.sbin/unbound/daemon/stats.c b/usr.sbin/unbound/daemon/stats.c index 57ad1ef6bcd..d3f41de037b 100644 --- a/usr.sbin/unbound/daemon/stats.c +++ b/usr.sbin/unbound/daemon/stats.c @@ -56,6 +56,9 @@ #include "util/net_help.h" #include "validator/validator.h" #include "ldns/sbuffer.h" +#include "services/cache/rrset.h" +#include "services/cache/infra.h" +#include "validator/val_kcache.h" /** add timers and the values do not overflow or become negative */ static void @@ -158,10 +161,19 @@ server_stats_compile(struct worker* worker, struct stats_info* s, int reset) NUM_BUCKETS_HIST); /* values from outside network */ s->svr.unwanted_replies = worker->back->unwanted_replies; + s->svr.qtcp_outgoing = worker->back->num_tcp_outgoing; /* get and reset validator rrset bogus number */ s->svr.rrset_bogus = get_rrset_bogus(worker); + /* get cache sizes */ + s->svr.msg_cache_count = count_slabhash_entries(worker->env.msg_cache); + s->svr.rrset_cache_count = count_slabhash_entries(&worker->env.rrset_cache->table); + s->svr.infra_cache_count = count_slabhash_entries(worker->env.infra_cache->hosts); + if(worker->env.key_cache) + s->svr.key_cache_count = count_slabhash_entries(worker->env.key_cache->slab); + else s->svr.key_cache_count = 0; + if(reset && !worker->env.cfg->stat_cumulative) { worker_stats_clear(worker); } @@ -217,6 +229,7 @@ void server_stats_add(struct stats_info* total, struct stats_info* a) total->svr.qtype_big += a->svr.qtype_big; total->svr.qclass_big += a->svr.qclass_big; total->svr.qtcp += a->svr.qtcp; + total->svr.qtcp_outgoing += a->svr.qtcp_outgoing; total->svr.qipv6 += a->svr.qipv6; total->svr.qbit_QR += a->svr.qbit_QR; total->svr.qbit_AA += a->svr.qbit_AA; diff --git a/usr.sbin/unbound/daemon/stats.h b/usr.sbin/unbound/daemon/stats.h index 7c315513f36..5ea00a0da5b 100644 --- a/usr.sbin/unbound/daemon/stats.h +++ b/usr.sbin/unbound/daemon/stats.h @@ -91,6 +91,8 @@ struct server_stats { size_t qopcode[STATS_OPCODE_NUM]; /** number of queries over TCP */ size_t qtcp; + /** number of outgoing queries over TCP */ + size_t qtcp_outgoing; /** number of queries over IPv6 */ size_t qipv6; /** number of queries with QR bit */ @@ -133,6 +135,15 @@ struct server_stats { * if all histograms are same size (is so by default) then * adding up works well. */ size_t hist[NUM_BUCKETS_HIST]; + + /** number of message cache entries */ + size_t msg_cache_count; + /** number of rrset cache entries */ + size_t rrset_cache_count; + /** number of infra cache entries */ + size_t infra_cache_count; + /** number of key cache entries */ + size_t key_cache_count; }; /** diff --git a/usr.sbin/unbound/dns64/dns64.c b/usr.sbin/unbound/dns64/dns64.c new file mode 100644 index 00000000000..963e727fed7 --- /dev/null +++ b/usr.sbin/unbound/dns64/dns64.c @@ -0,0 +1,865 @@ +/* + * dns64/dns64.c - DNS64 module + * + * Copyright (c) 2009, Viagénie. All rights reserved. + * + * This software is open source. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of Viagénie nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * This file contains a module that performs DNS64 query processing. + */ + +#include "config.h" +#include "dns64/dns64.h" +#include "services/cache/dns.h" +#include "services/cache/rrset.h" +#include "util/config_file.h" +#include "util/data/msgreply.h" +#include "util/fptr_wlist.h" +#include "util/net_help.h" +#include "util/regional.h" + +/****************************************************************************** + * * + * STATIC CONSTANTS * + * * + ******************************************************************************/ + +/** + * This is the default DNS64 prefix that is used whent he dns64 module is listed + * in module-config but when the dns64-prefix variable is not present. + */ +static const char DEFAULT_DNS64_PREFIX[] = "64:ff9b::/96"; + +/** + * Maximum length of a domain name in a PTR query in the .in-addr.arpa tree. + */ +#define MAX_PTR_QNAME_IPV4 30 + +/** + * Per-query module-specific state. This is usually a dynamically-allocated + * structure, but in our case we only need to store one variable describing the + * state the query is in. So we repurpose the minfo pointer by storing an + * integer in there. + */ +enum dns64_qstate { + DNS64_INTERNAL_QUERY, /**< Internally-generated query, no DNS64 + processing. */ + DNS64_NEW_QUERY, /**< Query for which we're the first module in + line. */ + DNS64_SUBQUERY_FINISHED /**< Query for which we generated a sub-query, and + for which this sub-query is finished. */ +}; + + +/****************************************************************************** + * * + * STRUCTURES * + * * + ******************************************************************************/ + +/** + * This structure contains module configuration information. One instance of + * this structure exists per instance of the module. Normally there is only one + * instance of the module. + */ +struct dns64_env { + /** + * DNS64 prefix address. We're using a full sockaddr instead of just an + * in6_addr because we can reuse Unbound's generic string parsing functions. + * It will always contain a sockaddr_in6, and only the sin6_addr member will + * ever be used. + */ + struct sockaddr_storage prefix_addr; + + /** + * This is always sizeof(sockaddr_in6). + */ + socklen_t prefix_addrlen; + + /** + * This is the CIDR length of the prefix. It needs to be between 0 and 96. + */ + int prefix_net; +}; + + +/****************************************************************************** + * * + * UTILITY FUNCTIONS * + * * + ******************************************************************************/ + +/** + * Generic macro for swapping two variables. + * + * \param t Type of the variables. (e.g. int) + * \param a First variable. + * \param b Second variable. + * + * \warning Do not attempt something foolish such as swap(int,a++,b++)! + */ +#define swap(t,a,b) do {t x = a; a = b; b = x;} while(0) + +/** + * Reverses a string. + * + * \param begin Points to the first character of the string. + * \param end Points one past the last character of the string. + */ +static void +reverse(char* begin, char* end) +{ + while ( begin < --end ) { + swap(char, *begin, *end); + ++begin; + } +} + +/** + * Convert an unsigned integer to a string. The point of this function is that + * of being faster than sprintf(). + * + * \param n The number to be converted. + * \param s The result will be written here. Must be large enough, be careful! + * + * \return The number of characters written. + */ +static int +uitoa(unsigned n, char* s) +{ + char* ss = s; + do { + *ss++ = '0' + n % 10; + } while (n /= 10); + reverse(s, ss); + return ss - s; +} + +/** + * Extract an IPv4 address embedded in the IPv6 address \a ipv6 at offset \a + * offset (in bits). Note that bits are not necessarily aligned on bytes so we + * need to be careful. + * + * \param ipv6 IPv6 address represented as a 128-bit array in big-endian + * order. + * \param offset Index of the MSB of the IPv4 address embedded in the IPv6 + * address. + */ +static uint32_t +extract_ipv4(const uint8_t ipv6[16], const int offset) +{ + uint32_t ipv4 = (uint32_t)ipv6[offset/8+0] << (24 + (offset%8)) + | (uint32_t)ipv6[offset/8+1] << (16 + (offset%8)) + | (uint32_t)ipv6[offset/8+2] << ( 8 + (offset%8)) + | (uint32_t)ipv6[offset/8+3] << ( 0 + (offset%8)); + if (offset/8+4 < 16) + ipv4 |= (uint32_t)ipv6[offset/8+4] >> (8 - offset%8); + return ipv4; +} + +/** + * Builds the PTR query name corresponding to an IPv4 address. For example, + * given the number 3,464,175,361, this will build the string + * "\03206\03123\0231\011\07in-addr\04arpa". + * + * \param ipv4 IPv4 address represented as an unsigned 32-bit number. + * \param ptr The result will be written here. Must be large enough, be + * careful! + * + * \return The number of characters written. + */ +static size_t +ipv4_to_ptr(uint32_t ipv4, char ptr[MAX_PTR_QNAME_IPV4]) +{ + static const char IPV4_PTR_SUFFIX[] = "\07in-addr\04arpa"; + int i; + char* c = ptr; + + for (i = 0; i < 4; ++i) { + *c = uitoa((unsigned int)(ipv4 % 256), c + 1); + c += *c + 1; + ipv4 /= 256; + } + + memmove(c, IPV4_PTR_SUFFIX, sizeof(IPV4_PTR_SUFFIX)); + + return c + sizeof(IPV4_PTR_SUFFIX) - ptr; +} + +/** + * Converts an IPv6-related domain name string from a PTR query into an IPv6 + * address represented as a 128-bit array. + * + * \param ptr The domain name. (e.g. "\011[...]\010\012\016\012\03ip6\04arpa") + * \param ipv6 The result will be written here, in network byte order. + * + * \return 1 on success, 0 on failure. + */ +static int +ptr_to_ipv6(const char* ptr, uint8_t ipv6[16]) +{ + int i; + + for (i = 0; i < 64; i++) { + int x; + + if (ptr[i++] != 1) + return 0; + + if (ptr[i] >= '0' && ptr[i] <= '9') { + x = ptr[i] - '0'; + } else if (ptr[i] >= 'a' && ptr[i] <= 'f') { + x = ptr[i] - 'a' + 10; + } else if (ptr[i] >= 'A' && ptr[i] <= 'F') { + x = ptr[i] - 'A' + 10; + } else { + return 0; + } + + ipv6[15-i/4] |= x << (2 * ((i-1) % 4)); + } + + return 1; +} + +/** + * Synthesize an IPv6 address based on an IPv4 address and the DNS64 prefix. + * + * \param prefix_addr DNS64 prefix address. + * \param prefix_net CIDR length of the DNS64 prefix. Must be between 0 and 96. + * \param a IPv4 address. + * \param aaaa IPv6 address. The result will be written here. + */ +static void +synthesize_aaaa(const uint8_t prefix_addr[16], int prefix_net, + const uint8_t a[4], uint8_t aaaa[16]) +{ + memcpy(aaaa, prefix_addr, 16); + aaaa[prefix_net/8+0] |= a[0] >> (0+prefix_net%8); + aaaa[prefix_net/8+1] |= a[0] << (8-prefix_net%8); + aaaa[prefix_net/8+1] |= a[1] >> (0+prefix_net%8); + aaaa[prefix_net/8+2] |= a[1] << (8-prefix_net%8); + aaaa[prefix_net/8+2] |= a[2] >> (0+prefix_net%8); + aaaa[prefix_net/8+3] |= a[2] << (8-prefix_net%8); + aaaa[prefix_net/8+3] |= a[3] >> (0+prefix_net%8); + if (prefix_net/8+4 < 16) /* <-- my beautiful symmetry is destroyed! */ + aaaa[prefix_net/8+4] |= a[3] << (8-prefix_net%8); +} + + +/****************************************************************************** + * * + * DNS64 MODULE FUNCTIONS * + * * + ******************************************************************************/ + +/** + * This function applies the configuration found in the parsed configuration + * file \a cfg to this instance of the dns64 module. Currently only the DNS64 + * prefix (a.k.a. Pref64) is configurable. + * + * \param dns64_env Module-specific global parameters. + * \param cfg Parsed configuration file. + */ +static int +dns64_apply_cfg(struct dns64_env* dns64_env, struct config_file* cfg) +{ + verbose(VERB_ALGO, "dns64-prefix: %s", cfg->dns64_prefix); + if (!netblockstrtoaddr(cfg->dns64_prefix ? cfg->dns64_prefix : + DEFAULT_DNS64_PREFIX, 0, &dns64_env->prefix_addr, + &dns64_env->prefix_addrlen, &dns64_env->prefix_net)) { + log_err("cannot parse dns64-prefix netblock: %s", cfg->dns64_prefix); + return 0; + } + if (!addr_is_ip6(&dns64_env->prefix_addr, dns64_env->prefix_addrlen)) { + log_err("dns64_prefix is not IPv6: %s", cfg->dns64_prefix); + return 0; + } + if (dns64_env->prefix_net < 0 || dns64_env->prefix_net > 96) { + log_err("dns64-prefix length it not between 0 and 96: %s", + cfg->dns64_prefix); + return 0; + } + return 1; +} + +/** + * Initializes this instance of the dns64 module. + * + * \param env Global state of all module instances. + * \param id This instance's ID number. + */ +int +dns64_init(struct module_env* env, int id) +{ + struct dns64_env* dns64_env = + (struct dns64_env*)calloc(1, sizeof(struct dns64_env)); + if (!dns64_env) { + log_err("malloc failure"); + return 0; + } + env->modinfo[id] = (void*)dns64_env; + if (!dns64_apply_cfg(dns64_env, env->cfg)) { + log_err("dns64: could not apply configuration settings."); + return 0; + } + return 1; +} + +/** + * Deinitializes this instance of the dns64 module. + * + * \param env Global state of all module instances. + * \param id This instance's ID number. + */ +void +dns64_deinit(struct module_env* env, int id) +{ + if (!env) + return; + free(env->modinfo[id]); + env->modinfo[id] = NULL; +} + +/** + * Handle PTR queries for IPv6 addresses. If the address belongs to the DNS64 + * prefix, we must do a PTR query for the corresponding IPv4 address instead. + * + * \param qstate Query state structure. + * \param id This module instance's ID number. + * + * \return The new state of the query. + */ +static enum module_ext_state +handle_ipv6_ptr(struct module_qstate* qstate, int id) +{ + struct dns64_env* dns64_env = (struct dns64_env*)qstate->env->modinfo[id]; + struct module_qstate* subq = NULL; + struct query_info qinfo; + struct sockaddr_in6 sin6; + + /* Convert the PTR query string to an IPv6 address. */ + memset(&sin6, 0, sizeof(sin6)); + sin6.sin6_family = AF_INET6; + if (!ptr_to_ipv6((char*)qstate->qinfo.qname, sin6.sin6_addr.s6_addr)) + return module_wait_module; /* Let other module handle this. */ + + /* + * If this IPv6 address is not part of our DNS64 prefix, then we don't need + * to do anything. Let another module handle the query. + */ + if (addr_in_common((struct sockaddr_storage*)&sin6, 128, + &dns64_env->prefix_addr, dns64_env->prefix_net, + (socklen_t)sizeof(sin6)) != dns64_env->prefix_net) + return module_wait_module; + + verbose(VERB_ALGO, "dns64: rewrite PTR record"); + + /* + * Create a new PTR query info for the domain name corresponding to the IPv4 + * address corresponding to the IPv6 address corresponding to the original + * PTR query domain name. + */ + qinfo = qstate->qinfo; + if (!(qinfo.qname = regional_alloc(qstate->region, MAX_PTR_QNAME_IPV4))) + return module_error; + qinfo.qname_len = ipv4_to_ptr(extract_ipv4(sin6.sin6_addr.s6_addr, + dns64_env->prefix_net), (char*)qinfo.qname); + + /* Create the new sub-query. */ + fptr_ok(fptr_whitelist_modenv_attach_sub(qstate->env->attach_sub)); + if(!(*qstate->env->attach_sub)(qstate, &qinfo, qstate->query_flags, 0, + &subq)) + return module_error; + if (subq) { + subq->curmod = id; + subq->ext_state[id] = module_state_initial; + subq->minfo[id] = NULL; + } + + return module_wait_subquery; +} + +/** allocate (special) rrset keys, return 0 on error */ +static int +repinfo_alloc_rrset_keys(struct reply_info* rep, + struct regional* region) +{ + size_t i; + for(i=0; i<rep->rrset_count; i++) { + if(region) { + rep->rrsets[i] = (struct ub_packed_rrset_key*) + regional_alloc(region, + sizeof(struct ub_packed_rrset_key)); + if(rep->rrsets[i]) { + memset(rep->rrsets[i], 0, + sizeof(struct ub_packed_rrset_key)); + rep->rrsets[i]->entry.key = rep->rrsets[i]; + } + } + else return 0;/* rep->rrsets[i] = alloc_special_obtain(alloc);*/ + if(!rep->rrsets[i]) + return 0; + rep->rrsets[i]->entry.data = NULL; + } + return 1; +} + +static enum module_ext_state +generate_type_A_query(struct module_qstate* qstate, int id) +{ + struct module_qstate* subq = NULL; + struct query_info qinfo; + + verbose(VERB_ALGO, "dns64: query A record"); + + /* Create a new query info. */ + qinfo = qstate->qinfo; + qinfo.qtype = LDNS_RR_TYPE_A; + + /* Start the sub-query. */ + fptr_ok(fptr_whitelist_modenv_attach_sub(qstate->env->attach_sub)); + if(!(*qstate->env->attach_sub)(qstate, &qinfo, qstate->query_flags, 0, + &subq)) + { + verbose(VERB_ALGO, "dns64: sub-query creation failed"); + return module_error; + } + if (subq) { + subq->curmod = id; + subq->ext_state[id] = module_state_initial; + subq->minfo[id] = NULL; + } + + return module_wait_subquery; +} + +/** + * Handles the "pass" event for a query. This event is received when a new query + * is received by this module. The query may have been generated internally by + * another module, in which case we don't want to do any special processing + * (this is an interesting discussion topic), or it may be brand new, e.g. + * received over a socket, in which case we do want to apply DNS64 processing. + * + * \param qstate A structure representing the state of the query that has just + * received the "pass" event. + * \param id This module's instance ID. + * + * \return The new state of the query. + */ +static enum module_ext_state +handle_event_pass(struct module_qstate* qstate, int id) +{ + if ((uintptr_t)qstate->minfo[id] == 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 && + (uintptr_t)qstate->minfo[id] == DNS64_NEW_QUERY + && qstate->qinfo.qtype == LDNS_RR_TYPE_AAAA) + return generate_type_A_query(qstate, id); + + /* We are finished when our sub-query is finished. */ + if ((uintptr_t)qstate->minfo[id] == DNS64_SUBQUERY_FINISHED) + return module_finished; + + /* Otherwise, pass request to next module. */ + verbose(VERB_ALGO, "dns64: pass to next module"); + return module_wait_module; +} + +/** + * Handles the "done" event for a query. We need to analyze the response and + * maybe issue a new sub-query for the A record. + * + * \param qstate A structure representing the state of the query that has just + * received the "pass" event. + * \param id This module's instance ID. + * + * \return The new state of the query. + */ +static enum module_ext_state +handle_event_moddone(struct module_qstate* qstate, int id) +{ + /* + * In many cases we have nothing special to do. From most to least common: + * + * - An internal query. + * - A query for a record type other than AAAA. + * - An AAAA query for which an error was returned. + * - A successful AAAA query with an answer. + */ + if ( (enum dns64_qstate)qstate->minfo[id] == DNS64_INTERNAL_QUERY + || qstate->qinfo.qtype != LDNS_RR_TYPE_AAAA + || qstate->return_rcode != LDNS_RCODE_NOERROR + || (qstate->return_msg && + qstate->return_msg->rep && + reply_find_answer_rrset(&qstate->qinfo, + qstate->return_msg->rep))) + return module_finished; + + /* So, this is a AAAA noerror/nodata answer */ + return generate_type_A_query(qstate, id); +} + +/** + * This is the module's main() function. It gets called each time a query + * receives an event which we may need to handle. We respond by updating the + * state of the query. + * + * \param qstate Structure containing the state of the query. + * \param event Event that has just been received. + * \param id This module's instance ID. + * \param outbound State of a DNS query on an authoritative server. We never do + * our own queries ourselves (other modules do it for us), so + * this is unused. + */ +void +dns64_operate(struct module_qstate* qstate, enum module_ev event, int id, + struct outbound_entry* outbound) +{ + (void)outbound; + verbose(VERB_QUERY, "dns64[module %d] operate: extstate:%s event:%s", + id, strextstate(qstate->ext_state[id]), + strmodulevent(event)); + log_query_info(VERB_QUERY, "dns64 operate: query", &qstate->qinfo); + + switch(event) { + case module_event_new: + /* Tag this query as being new and fall through. */ + qstate->minfo[id] = (void*)DNS64_NEW_QUERY; + case module_event_pass: + qstate->ext_state[id] = handle_event_pass(qstate, id); + break; + case module_event_moddone: + qstate->ext_state[id] = handle_event_moddone(qstate, id); + break; + default: + qstate->ext_state[id] = module_finished; + break; + } +} + +static void +dns64_synth_aaaa_data(const struct ub_packed_rrset_key* fk, + const struct packed_rrset_data* fd, + struct ub_packed_rrset_key *dk, + struct packed_rrset_data **dd_out, struct regional *region, + struct dns64_env* dns64_env ) +{ + struct packed_rrset_data *dd; + size_t i; + /* + * Create synthesized AAAA RR set data. We need to allocated extra memory + * for the RRs themselves. Each RR has a length, TTL, pointer to wireformat + * data, 2 bytes of data length, and 16 bytes of IPv6 address. + */ + if (!(dd = *dd_out = regional_alloc(region, + sizeof(struct packed_rrset_data) + + fd->count * (sizeof(size_t) + sizeof(time_t) + + sizeof(uint8_t*) + 2 + 16)))) { + log_err("out of memory"); + return; + } + + /* Copy attributes from A RR set. */ + dd->ttl = fd->ttl; + dd->count = fd->count; + dd->rrsig_count = 0; + dd->trust = fd->trust; + dd->security = fd->security; + + /* + * Synthesize AAAA records. Adjust pointers in structure. + */ + dd->rr_len = + (size_t*)((uint8_t*)dd + sizeof(struct packed_rrset_data)); + dd->rr_data = (uint8_t**)&dd->rr_len[dd->count]; + dd->rr_ttl = (time_t*)&dd->rr_data[dd->count]; + for(i = 0; i < fd->count; ++i) { + if (fd->rr_len[i] != 6 || fd->rr_data[i][0] != 0 + || fd->rr_data[i][1] != 4) + return; + dd->rr_len[i] = 18; + dd->rr_data[i] = + (uint8_t*)&dd->rr_ttl[dd->count] + 18*i; + dd->rr_data[i][0] = 0; + dd->rr_data[i][1] = 16; + synthesize_aaaa( + ((struct sockaddr_in6*)&dns64_env->prefix_addr)->sin6_addr.s6_addr, + dns64_env->prefix_net, &fd->rr_data[i][2], + &dd->rr_data[i][2] ); + dd->rr_ttl[i] = fd->rr_ttl[i]; + } + + /* + * Create synthesized AAAA RR set key. This is mostly just bookkeeping, + * nothing interesting here. + */ + if(!dk) { + log_err("no key"); + return; + } + + dk->rk.dname = (uint8_t*)regional_alloc_init(region, + fk->rk.dname, fk->rk.dname_len); + + if(!dk->rk.dname) { + log_err("out of memory"); + return; + } + + dk->rk.type = htons(LDNS_RR_TYPE_AAAA); + memset(&dk->entry, 0, sizeof(dk->entry)); + dk->entry.key = dk; + dk->entry.hash = rrset_key_hash(&dk->rk); + dk->entry.data = dd; + +} + +/** + * Synthesize an AAAA RR set from an A sub-query's answer and add it to the + * original empty response. + * + * \param id This module's instance ID. + * \param super Original AAAA query. + * \param qstate A query. + */ +static void +dns64_adjust_a(int id, struct module_qstate* super, struct module_qstate* qstate) +{ + struct dns64_env* dns64_env = (struct dns64_env*)super->env->modinfo[id]; + struct reply_info *rep, *cp; + size_t i, s; + struct packed_rrset_data* fd, *dd; + struct ub_packed_rrset_key* fk, *dk; + + verbose(VERB_ALGO, "converting A answers to AAAA answers"); + + log_assert(super->region); + log_assert(qstate->return_msg); + log_assert(qstate->return_msg->rep); + + /* If dns64-synthall is enabled, return_msg is not initialized */ + if(!super->return_msg) { + super->return_msg = (struct dns_msg*)regional_alloc( + super->region, sizeof(struct dns_msg)); + if(!super->return_msg) + return; + memset(super->return_msg, 0, sizeof(*super->return_msg)); + super->return_msg->qinfo = super->qinfo; + } + + rep = qstate->return_msg->rep; + + /* + * Build the actual reply. + */ + cp = construct_reply_info_base(super->region, rep->flags, rep->qdcount, + rep->ttl, rep->prefetch_ttl, rep->an_numrrsets, rep->ns_numrrsets, + rep->ar_numrrsets, rep->rrset_count, rep->security); + if(!cp) + return; + + /* allocate ub_key structures special or not */ + if(!repinfo_alloc_rrset_keys(cp, super->region)) { + return; + } + + /* copy everything and replace A by AAAA */ + for(i=0; i<cp->rrset_count; i++) { + fk = rep->rrsets[i]; + dk = cp->rrsets[i]; + fd = (struct packed_rrset_data*)fk->entry.data; + dk->rk = fk->rk; + dk->id = fk->id; + + if(i<rep->an_numrrsets && fk->rk.type == htons(LDNS_RR_TYPE_A)) { + /* also sets dk->entry.hash */ + dns64_synth_aaaa_data(fk, fd, dk, &dd, super->region, dns64_env); + /* Delete negative AAAA record from cache stored by + * the iterator module */ + rrset_cache_remove(super->env->rrset_cache, dk->rk.dname, + dk->rk.dname_len, LDNS_RR_TYPE_AAAA, + LDNS_RR_CLASS_IN, 0); + } else { + dk->entry.hash = fk->entry.hash; + dk->rk.dname = (uint8_t*)regional_alloc_init(super->region, + fk->rk.dname, fk->rk.dname_len); + + if(!dk->rk.dname) + return; + + s = packed_rrset_sizeof(fd); + dd = (struct packed_rrset_data*)regional_alloc_init( + super->region, fd, s); + + if(!dd) + return; + } + + packed_rrset_ptr_fixup(dd); + dk->entry.data = (void*)dd; + } + + /* Commit changes. */ + super->return_msg->rep = cp; +} + +/** + * Generate a response for the original IPv6 PTR query based on an IPv4 PTR + * sub-query's response. + * + * \param qstate IPv4 PTR sub-query. + * \param super Original IPv6 PTR query. + */ +static void +dns64_adjust_ptr(struct module_qstate* qstate, struct module_qstate* super) +{ + struct ub_packed_rrset_key* answer; + + verbose(VERB_ALGO, "adjusting PTR reply"); + + /* Copy the sub-query's reply to the parent. */ + if (!(super->return_msg = (struct dns_msg*)regional_alloc(super->region, + sizeof(struct dns_msg)))) + return; + super->return_msg->qinfo = super->qinfo; + super->return_msg->rep = reply_info_copy(qstate->return_msg->rep, NULL, + super->region); + + /* + * Adjust the domain name of the answer RR set so that it matches the + * initial query's domain name. + */ + answer = reply_find_answer_rrset(&qstate->qinfo, super->return_msg->rep); + log_assert(answer); + answer->rk.dname = super->qinfo.qname; + answer->rk.dname_len = super->qinfo.qname_len; +} + +/** + * This function is called when a sub-query finishes to inform the parent query. + * + * We issue two kinds of sub-queries: PTR and A. + * + * \param qstate State of the sub-query. + * \param id This module's instance ID. + * \param super State of the super-query. + */ +void +dns64_inform_super(struct module_qstate* qstate, int id, + struct module_qstate* super) +{ + log_query_info(VERB_ALGO, "dns64: inform_super, sub is", + &qstate->qinfo); + log_query_info(VERB_ALGO, "super is", &super->qinfo); + + /* + * Signal that the sub-query is finished, no matter whether we are + * successful or not. This lets the state machine terminate. + */ + super->minfo[id] = (void*)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 + || !reply_find_answer_rrset(&qstate->qinfo, + qstate->return_msg->rep)) + return; + + /* Generate a response suitable for the original query. */ + if (qstate->qinfo.qtype == LDNS_RR_TYPE_A) { + dns64_adjust_a(id, super, qstate); + } else { + log_assert(qstate->qinfo.qtype == LDNS_RR_TYPE_PTR); + dns64_adjust_ptr(qstate, super); + } + + /* Store the generated response in cache. */ + if (!dns_cache_store(super->env, &super->qinfo, super->return_msg->rep, + 0, 0, 0, NULL)) + log_err("out of memory"); +} + +/** + * Clear module-specific data from query state. Since we do not allocate memory, + * it's just a matter of setting a pointer to NULL. + * + * \param qstate Query state. + * \param id This module's instance ID. + */ +void +dns64_clear(struct module_qstate* qstate, int id) +{ + qstate->minfo[id] = NULL; +} + +/** + * Returns the amount of global memory that this module uses, not including + * per-query data. + * + * \param env Module environment. + * \param id This module's instance ID. + */ +size_t +dns64_get_mem(struct module_env* env, int id) +{ + struct dns64_env* dns64_env = (struct dns64_env*)env->modinfo[id]; + if (!dns64_env) + return 0; + return sizeof(*dns64_env); +} + +/** + * The dns64 function block. + */ +static struct module_func_block dns64_block = { + "dns64", + &dns64_init, &dns64_deinit, &dns64_operate, &dns64_inform_super, + &dns64_clear, &dns64_get_mem +}; + +/** + * Function for returning the above function block. + */ +struct module_func_block * +dns64_get_funcblock() +{ + return &dns64_block; +} diff --git a/usr.sbin/unbound/dns64/dns64.h b/usr.sbin/unbound/dns64/dns64.h new file mode 100644 index 00000000000..2f0c01a228c --- /dev/null +++ b/usr.sbin/unbound/dns64/dns64.h @@ -0,0 +1,71 @@ +/* + * dns64/dns64.h - DNS64 module + * + * Copyright (c) 2009, Viagénie. All rights reserved. + * + * This software is open source. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the NLNET LABS nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * This file contains a module that performs DNS64 query processing. + */ + +#ifndef DNS64_DNS64_H +#define DNS64_DNS64_H +#include "util/module.h" + +/** + * Get the dns64 function block. + * @return: function block with function pointers to dns64 methods. + */ +struct module_func_block *dns64_get_funcblock(void); + +/** dns64 init */ +int dns64_init(struct module_env* env, int id); + +/** dns64 deinit */ +void dns64_deinit(struct module_env* env, int id); + +/** dns64 operate on a query */ +void dns64_operate(struct module_qstate* qstate, enum module_ev event, int id, + struct outbound_entry* outbound); + +void dns64_inform_super(struct module_qstate* qstate, int id, + struct module_qstate* super); + +/** dns64 cleanup query state */ +void dns64_clear(struct module_qstate* qstate, int id); + +/** dns64 alloc size routine */ +size_t dns64_get_mem(struct module_env* env, int id); + +#endif /* DNS64_DNS64_H */ diff --git a/usr.sbin/unbound/dnstap/dnstap.c b/usr.sbin/unbound/dnstap/dnstap.c new file mode 100644 index 00000000000..b2dc053bdbf --- /dev/null +++ b/usr.sbin/unbound/dnstap/dnstap.c @@ -0,0 +1,510 @@ +/* dnstap support for Unbound */ + +/* + * Copyright (c) 2013-2014, Farsight Security, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "dnstap/dnstap_config.h" + +#ifdef USE_DNSTAP + +#include "config.h" +#include <string.h> +#include <sys/time.h> +#include "ldns/sbuffer.h" +#include "util/config_file.h" +#include "util/net_help.h" +#include "util/netevent.h" +#include "util/log.h" + +#include <fstrm.h> +#include <protobuf-c/protobuf-c.h> + +#include "dnstap/dnstap.h" +#include "dnstap/dnstap.pb-c.h" + +#define DNSTAP_CONTENT_TYPE "protobuf:dnstap.Dnstap" +#define DNSTAP_INITIAL_BUF_SIZE 256 + +struct dt_msg { + void *buf; + size_t len_buf; + Dnstap__Dnstap d; + Dnstap__Message m; +}; + +static int +dt_pack(const Dnstap__Dnstap *d, void **buf, size_t *sz) +{ + ProtobufCBufferSimple sbuf; + + memset(&sbuf, 0, sizeof(sbuf)); + sbuf.base.append = protobuf_c_buffer_simple_append; + sbuf.len = 0; + sbuf.alloced = DNSTAP_INITIAL_BUF_SIZE; + sbuf.data = malloc(sbuf.alloced); + if (sbuf.data == NULL) + return 0; + sbuf.must_free_data = 1; + + *sz = dnstap__dnstap__pack_to_buffer(d, (ProtobufCBuffer *) &sbuf); + if (sbuf.data == NULL) + return 0; + *buf = sbuf.data; + + return 1; +} + +static void +dt_send(const struct dt_env *env, void *buf, size_t len_buf) +{ + fstrm_res res; + if (!buf) + return; + res = fstrm_iothr_submit(env->iothr, env->ioq, buf, len_buf, + fstrm_free_wrapper, NULL); + if (res != fstrm_res_success) + free(buf); +} + +static void +dt_msg_init(const struct dt_env *env, + struct dt_msg *dm, + Dnstap__Message__Type mtype) +{ + memset(dm, 0, sizeof(*dm)); + dm->d.base.descriptor = &dnstap__dnstap__descriptor; + dm->m.base.descriptor = &dnstap__message__descriptor; + dm->d.type = DNSTAP__DNSTAP__TYPE__MESSAGE; + dm->d.message = &dm->m; + dm->m.type = mtype; + if (env->identity != NULL) { + dm->d.identity.data = (uint8_t *) env->identity; + dm->d.identity.len = (size_t) env->len_identity; + dm->d.has_identity = 1; + } + if (env->version != NULL) { + dm->d.version.data = (uint8_t *) env->version; + dm->d.version.len = (size_t) env->len_version; + dm->d.has_version = 1; + } +} + +struct dt_env * +dt_create(const char *socket_path, unsigned num_workers) +{ + fstrm_res res; + struct dt_env *env; + struct fstrm_iothr_options *fopt; + struct fstrm_unix_writer_options *fuwopt; + struct fstrm_writer *fw; + struct fstrm_writer_options *fwopt; + + verbose(VERB_OPS, "opening dnstap socket %s", socket_path); + log_assert(socket_path != NULL); + log_assert(num_workers > 0); + + env = (struct dt_env *) calloc(1, sizeof(struct dt_env)); + if (!env) + return NULL; + + fwopt = fstrm_writer_options_init(); + res = fstrm_writer_options_add_content_type(fwopt, + DNSTAP_CONTENT_TYPE, sizeof(DNSTAP_CONTENT_TYPE) - 1); + log_assert(res == fstrm_res_success); + + fuwopt = fstrm_unix_writer_options_init(); + fstrm_unix_writer_options_set_socket_path(fuwopt, socket_path); + + fw = fstrm_unix_writer_init(fuwopt, fwopt); + log_assert(fw != NULL); + + fopt = fstrm_iothr_options_init(); + fstrm_iothr_options_set_num_input_queues(fopt, num_workers); + env->iothr = fstrm_iothr_init(fopt, &fw); + if (env->iothr == NULL) { + verbose(VERB_DETAIL, "dt_create: fstrm_iothr_init() failed"); + fstrm_writer_destroy(&fw); + free(env); + env = NULL; + } + fstrm_iothr_options_destroy(&fopt); + fstrm_unix_writer_options_destroy(&fuwopt); + fstrm_writer_options_destroy(&fwopt); + + return env; +} + +static void +dt_apply_identity(struct dt_env *env, struct config_file *cfg) +{ + char buf[MAXHOSTNAMELEN+1]; + if (!cfg->dnstap_send_identity) + return; + free(env->identity); + if (cfg->dnstap_identity == NULL || cfg->dnstap_identity[0] == 0) { + if (gethostname(buf, MAXHOSTNAMELEN) == 0) { + buf[MAXHOSTNAMELEN] = 0; + env->identity = strdup(buf); + } else { + fatal_exit("dt_apply_identity: gethostname() failed"); + } + } else { + env->identity = strdup(cfg->dnstap_identity); + } + if (env->identity == NULL) + fatal_exit("dt_apply_identity: strdup() failed"); + env->len_identity = (unsigned int)strlen(env->identity); + verbose(VERB_OPS, "dnstap identity field set to \"%s\"", + env->identity); +} + +static void +dt_apply_version(struct dt_env *env, struct config_file *cfg) +{ + if (!cfg->dnstap_send_version) + return; + free(env->version); + if (cfg->dnstap_version == NULL || cfg->dnstap_version[0] == 0) + env->version = strdup(PACKAGE_STRING); + else + env->version = strdup(cfg->dnstap_version); + if (env->version == NULL) + fatal_exit("dt_apply_version: strdup() failed"); + env->len_version = (unsigned int)strlen(env->version); + verbose(VERB_OPS, "dnstap version field set to \"%s\"", + env->version); +} + +void +dt_apply_cfg(struct dt_env *env, struct config_file *cfg) +{ + if (!cfg->dnstap) + return; + + dt_apply_identity(env, cfg); + dt_apply_version(env, cfg); + if ((env->log_resolver_query_messages = (unsigned int) + cfg->dnstap_log_resolver_query_messages)) + { + verbose(VERB_OPS, "dnstap Message/RESOLVER_QUERY enabled"); + } + if ((env->log_resolver_response_messages = (unsigned int) + cfg->dnstap_log_resolver_response_messages)) + { + verbose(VERB_OPS, "dnstap Message/RESOLVER_RESPONSE enabled"); + } + if ((env->log_client_query_messages = (unsigned int) + cfg->dnstap_log_client_query_messages)) + { + verbose(VERB_OPS, "dnstap Message/CLIENT_QUERY enabled"); + } + if ((env->log_client_response_messages = (unsigned int) + cfg->dnstap_log_client_response_messages)) + { + verbose(VERB_OPS, "dnstap Message/CLIENT_RESPONSE enabled"); + } + if ((env->log_forwarder_query_messages = (unsigned int) + cfg->dnstap_log_forwarder_query_messages)) + { + verbose(VERB_OPS, "dnstap Message/FORWARDER_QUERY enabled"); + } + if ((env->log_forwarder_response_messages = (unsigned int) + cfg->dnstap_log_forwarder_response_messages)) + { + verbose(VERB_OPS, "dnstap Message/FORWARDER_RESPONSE enabled"); + } +} + +int +dt_init(struct dt_env *env) +{ + env->ioq = fstrm_iothr_get_input_queue(env->iothr); + if (env->ioq == NULL) + return 0; + return 1; +} + +void +dt_delete(struct dt_env *env) +{ + if (!env) + return; + verbose(VERB_OPS, "closing dnstap socket"); + fstrm_iothr_destroy(&env->iothr); + free(env->identity); + free(env->version); + free(env); +} + +static void +dt_fill_timeval(const struct timeval *tv, + uint64_t *time_sec, protobuf_c_boolean *has_time_sec, + uint32_t *time_nsec, protobuf_c_boolean *has_time_nsec) +{ +#ifndef S_SPLINT_S + *time_sec = tv->tv_sec; + *time_nsec = tv->tv_usec * 1000; +#endif + *has_time_sec = 1; + *has_time_nsec = 1; +} + +static void +dt_fill_buffer(sldns_buffer *b, ProtobufCBinaryData *p, protobuf_c_boolean *has) +{ + log_assert(b != NULL); + p->len = sldns_buffer_limit(b); + p->data = sldns_buffer_begin(b); + *has = 1; +} + +static void +dt_msg_fill_net(struct dt_msg *dm, + struct sockaddr_storage *ss, + enum comm_point_type cptype, + ProtobufCBinaryData *addr, protobuf_c_boolean *has_addr, + uint32_t *port, protobuf_c_boolean *has_port) +{ + log_assert(ss->ss_family == AF_INET6 || ss->ss_family == AF_INET); + if (ss->ss_family == AF_INET6) { + struct sockaddr_in6 *s = (struct sockaddr_in6 *) ss; + + /* socket_family */ + dm->m.socket_family = DNSTAP__SOCKET_FAMILY__INET6; + dm->m.has_socket_family = 1; + + /* addr: query_address or response_address */ + addr->data = s->sin6_addr.s6_addr; + addr->len = 16; /* IPv6 */ + *has_addr = 1; + + /* port: query_port or response_port */ + *port = ntohs(s->sin6_port); + *has_port = 1; + } else if (ss->ss_family == AF_INET) { + struct sockaddr_in *s = (struct sockaddr_in *) ss; + + /* socket_family */ + dm->m.socket_family = DNSTAP__SOCKET_FAMILY__INET; + dm->m.has_socket_family = 1; + + /* addr: query_address or response_address */ + addr->data = (uint8_t *) &s->sin_addr.s_addr; + addr->len = 4; /* IPv4 */ + *has_addr = 1; + + /* port: query_port or response_port */ + *port = ntohs(s->sin_port); + *has_port = 1; + } + + log_assert(cptype == comm_udp || cptype == comm_tcp); + if (cptype == comm_udp) { + /* socket_protocol */ + dm->m.socket_protocol = DNSTAP__SOCKET_PROTOCOL__UDP; + dm->m.has_socket_protocol = 1; + } else if (cptype == comm_tcp) { + /* socket_protocol */ + dm->m.socket_protocol = DNSTAP__SOCKET_PROTOCOL__TCP; + dm->m.has_socket_protocol = 1; + } +} + +void +dt_msg_send_client_query(struct dt_env *env, + struct sockaddr_storage *qsock, + enum comm_point_type cptype, + sldns_buffer *qmsg) +{ + struct dt_msg dm; + struct timeval qtime; + + gettimeofday(&qtime, NULL); + + /* type */ + dt_msg_init(env, &dm, DNSTAP__MESSAGE__TYPE__CLIENT_QUERY); + + /* query_time */ + dt_fill_timeval(&qtime, + &dm.m.query_time_sec, &dm.m.has_query_time_sec, + &dm.m.query_time_nsec, &dm.m.has_query_time_nsec); + + /* query_message */ + dt_fill_buffer(qmsg, &dm.m.query_message, &dm.m.has_query_message); + + /* socket_family, socket_protocol, query_address, query_port */ + log_assert(cptype == comm_udp || cptype == comm_tcp); + dt_msg_fill_net(&dm, qsock, cptype, + &dm.m.query_address, &dm.m.has_query_address, + &dm.m.query_port, &dm.m.has_query_port); + + if (dt_pack(&dm.d, &dm.buf, &dm.len_buf)) + dt_send(env, dm.buf, dm.len_buf); +} + +void +dt_msg_send_client_response(struct dt_env *env, + struct sockaddr_storage *qsock, + enum comm_point_type cptype, + sldns_buffer *rmsg) +{ + struct dt_msg dm; + struct timeval rtime; + + gettimeofday(&rtime, NULL); + + /* type */ + dt_msg_init(env, &dm, DNSTAP__MESSAGE__TYPE__CLIENT_RESPONSE); + + /* response_time */ + dt_fill_timeval(&rtime, + &dm.m.response_time_sec, &dm.m.has_response_time_sec, + &dm.m.response_time_nsec, &dm.m.has_response_time_nsec); + + /* response_message */ + dt_fill_buffer(rmsg, &dm.m.response_message, &dm.m.has_response_message); + + /* socket_family, socket_protocol, query_address, query_port */ + log_assert(cptype == comm_udp || cptype == comm_tcp); + dt_msg_fill_net(&dm, qsock, cptype, + &dm.m.query_address, &dm.m.has_query_address, + &dm.m.query_port, &dm.m.has_query_port); + + if (dt_pack(&dm.d, &dm.buf, &dm.len_buf)) + dt_send(env, dm.buf, dm.len_buf); +} + +void +dt_msg_send_outside_query(struct dt_env *env, + struct sockaddr_storage *rsock, + enum comm_point_type cptype, + uint8_t *zone, size_t zone_len, + sldns_buffer *qmsg) +{ + struct dt_msg dm; + struct timeval qtime; + uint16_t qflags; + + gettimeofday(&qtime, NULL); + qflags = sldns_buffer_read_u16_at(qmsg, 2); + + /* type */ + if (qflags & BIT_RD) { + if (!env->log_forwarder_query_messages) + return; + dt_msg_init(env, &dm, DNSTAP__MESSAGE__TYPE__FORWARDER_QUERY); + } else { + if (!env->log_resolver_query_messages) + return; + dt_msg_init(env, &dm, DNSTAP__MESSAGE__TYPE__RESOLVER_QUERY); + } + + /* query_zone */ + dm.m.query_zone.data = zone; + dm.m.query_zone.len = zone_len; + dm.m.has_query_zone = 1; + + /* query_time_sec, query_time_nsec */ + dt_fill_timeval(&qtime, + &dm.m.query_time_sec, &dm.m.has_query_time_sec, + &dm.m.query_time_nsec, &dm.m.has_query_time_nsec); + + /* query_message */ + dt_fill_buffer(qmsg, &dm.m.query_message, &dm.m.has_query_message); + + /* socket_family, socket_protocol, response_address, response_port */ + log_assert(cptype == comm_udp || cptype == comm_tcp); + dt_msg_fill_net(&dm, rsock, cptype, + &dm.m.response_address, &dm.m.has_response_address, + &dm.m.response_port, &dm.m.has_response_port); + + if (dt_pack(&dm.d, &dm.buf, &dm.len_buf)) + dt_send(env, dm.buf, dm.len_buf); +} + +void +dt_msg_send_outside_response(struct dt_env *env, + struct sockaddr_storage *rsock, + enum comm_point_type cptype, + uint8_t *zone, size_t zone_len, + uint8_t *qbuf, size_t qbuf_len, + const struct timeval *qtime, + const struct timeval *rtime, + sldns_buffer *rmsg) +{ + struct dt_msg dm; + uint16_t qflags; + + log_assert(qbuf_len >= sizeof(qflags)); + memcpy(&qflags, qbuf, sizeof(qflags)); + qflags = ntohs(qflags); + + /* type */ + if (qflags & BIT_RD) { + if (!env->log_forwarder_response_messages) + return; + dt_msg_init(env, &dm, DNSTAP__MESSAGE__TYPE__FORWARDER_RESPONSE); + } else { + if (!env->log_resolver_query_messages) + return; + dt_msg_init(env, &dm, DNSTAP__MESSAGE__TYPE__RESOLVER_RESPONSE); + } + + /* query_zone */ + dm.m.query_zone.data = zone; + dm.m.query_zone.len = zone_len; + dm.m.has_query_zone = 1; + + /* query_time_sec, query_time_nsec */ + dt_fill_timeval(qtime, + &dm.m.query_time_sec, &dm.m.has_query_time_sec, + &dm.m.query_time_nsec, &dm.m.has_query_time_nsec); + + /* response_time_sec, response_time_nsec */ + dt_fill_timeval(rtime, + &dm.m.response_time_sec, &dm.m.has_response_time_sec, + &dm.m.response_time_nsec, &dm.m.has_response_time_nsec); + + /* response_message */ + dt_fill_buffer(rmsg, &dm.m.response_message, &dm.m.has_response_message); + + /* socket_family, socket_protocol, response_address, response_port */ + log_assert(cptype == comm_udp || cptype == comm_tcp); + dt_msg_fill_net(&dm, rsock, cptype, + &dm.m.response_address, &dm.m.has_response_address, + &dm.m.response_port, &dm.m.has_response_port); + + if (dt_pack(&dm.d, &dm.buf, &dm.len_buf)) + dt_send(env, dm.buf, dm.len_buf); +} + +#endif /* USE_DNSTAP */ diff --git a/usr.sbin/unbound/dnstap/dnstap.h b/usr.sbin/unbound/dnstap/dnstap.h new file mode 100644 index 00000000000..0103c1c0e20 --- /dev/null +++ b/usr.sbin/unbound/dnstap/dnstap.h @@ -0,0 +1,188 @@ +/* dnstap support for Unbound */ + +/* + * Copyright (c) 2013-2014, Farsight Security, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef UNBOUND_DNSTAP_H +#define UNBOUND_DNSTAP_H + +#include "dnstap/dnstap_config.h" + +#ifdef USE_DNSTAP + +struct config_file; +struct fstrm_io; +struct fstrm_queue; +struct sldns_buffer; + +struct dt_env { + /** dnstap I/O thread */ + struct fstrm_iothr *iothr; + + /** dnstap I/O thread input queue */ + struct fstrm_iothr_queue *ioq; + + /** dnstap "identity" field, NULL if disabled */ + char *identity; + + /** dnstap "version" field, NULL if disabled */ + char *version; + + /** length of "identity" field */ + unsigned len_identity; + + /** length of "version" field */ + unsigned len_version; + + /** whether to log Message/RESOLVER_QUERY */ + unsigned log_resolver_query_messages : 1; + /** whether to log Message/RESOLVER_RESPONSE */ + unsigned log_resolver_response_messages : 1; + /** whether to log Message/CLIENT_QUERY */ + unsigned log_client_query_messages : 1; + /** whether to log Message/CLIENT_RESPONSE */ + unsigned log_client_response_messages : 1; + /** whether to log Message/FORWARDER_QUERY */ + unsigned log_forwarder_query_messages : 1; + /** whether to log Message/FORWARDER_RESPONSE */ + unsigned log_forwarder_response_messages : 1; +}; + +/** + * Create dnstap environment object. Afterwards, call dt_apply_cfg() to fill in + * the config variables and dt_init() to fill in the per-worker state. Each + * worker needs a copy of this object but with its own I/O queue (the fq field + * of the structure) to ensure lock-free access to its own per-worker circular + * queue. Duplicate the environment object if more than one worker needs to + * share access to the dnstap I/O socket. + * @param socket_path: path to dnstap logging socket, must be non-NULL. + * @param num_workers: number of worker threads, must be > 0. + * @return dt_env object, NULL on failure. + */ +struct dt_env * +dt_create(const char *socket_path, unsigned num_workers); + +/** + * Apply config settings. + * @param env: dnstap environment object. + * @param cfg: new config settings. + */ +void +dt_apply_cfg(struct dt_env *env, struct config_file *cfg); + +/** + * Initialize per-worker state in dnstap environment object. + * @param env: dnstap environment object to initialize, created with dt_create(). + * @return: true on success, false on failure. + */ +int +dt_init(struct dt_env *env); + +/** + * Delete dnstap environment object. Closes dnstap I/O socket and deletes all + * per-worker I/O queues. + */ +void +dt_delete(struct dt_env *env); + +/** + * Create and send a new dnstap "Message" event of type CLIENT_QUERY. + * @param env: dnstap environment object. + * @param qsock: address/port of client. + * @param cptype: comm_udp or comm_tcp. + * @param qmsg: query message. + */ +void +dt_msg_send_client_query(struct dt_env *env, + struct sockaddr_storage *qsock, + enum comm_point_type cptype, + struct sldns_buffer *qmsg); + +/** + * Create and send a new dnstap "Message" event of type CLIENT_RESPONSE. + * @param env: dnstap environment object. + * @param qsock: address/port of client. + * @param cptype: comm_udp or comm_tcp. + * @param rmsg: response message. + */ +void +dt_msg_send_client_response(struct dt_env *env, + struct sockaddr_storage *qsock, + enum comm_point_type cptype, + struct sldns_buffer *rmsg); + +/** + * Create and send a new dnstap "Message" event of type RESOLVER_QUERY or + * FORWARDER_QUERY. The type used is dependent on the value of the RD bit + * in the query header. + * @param env: dnstap environment object. + * @param rsock: address/port of server the query is being sent to. + * @param cptype: comm_udp or comm_tcp. + * @param zone: query zone. + * @param zone_len: length of zone. + * @param qmsg: query message. + */ +void +dt_msg_send_outside_query(struct dt_env *env, + struct sockaddr_storage *rsock, + enum comm_point_type cptype, + uint8_t *zone, size_t zone_len, + struct sldns_buffer *qmsg); + +/** + * Create and send a new dnstap "Message" event of type RESOLVER_RESPONSE or + * FORWARDER_RESPONSE. The type used is dependent on the value of the RD bit + * in the query header. + * @param env: dnstap environment object. + * @param rsock: address/port of server the response was received from. + * @param cptype: comm_udp or comm_tcp. + * @param zone: query zone. + * @param zone_len: length of zone. + * @param qbuf: outside_network's qbuf key. + * @param qbuf_len: length of outside_network's qbuf key. + * @param qtime: time query message was sent. + * @param rtime: time response message was sent. + * @param rmsg: response message. + */ +void +dt_msg_send_outside_response(struct dt_env *env, + struct sockaddr_storage *rsock, + enum comm_point_type cptype, + uint8_t *zone, size_t zone_len, + uint8_t *qbuf, size_t qbuf_len, + const struct timeval *qtime, + const struct timeval *rtime, + struct sldns_buffer *rmsg); + +#endif /* USE_DNSTAP */ + +#endif /* UNBOUND_DNSTAP_H */ diff --git a/usr.sbin/unbound/dnstap/dnstap.m4 b/usr.sbin/unbound/dnstap/dnstap.m4 new file mode 100644 index 00000000000..5b78b3e267c --- /dev/null +++ b/usr.sbin/unbound/dnstap/dnstap.m4 @@ -0,0 +1,56 @@ +# dnstap.m4 + +# dt_DNSTAP(default_dnstap_socket_path, [action-if-true], [action-if-false]) +# -------------------------------------------------------------------------- +# Check for required dnstap libraries and add dnstap configure args. +AC_DEFUN([dt_DNSTAP], +[ + AC_ARG_ENABLE([dnstap], + AS_HELP_STRING([--enable-dnstap], + [Enable dnstap support (requires fstrm, protobuf-c)]), + [opt_dnstap=$enableval], [opt_dnstap=no]) + + AC_ARG_WITH([dnstap-socket-path], + AS_HELP_STRING([--with-dnstap-socket-path=pathname], + [set default dnstap socket path]), + [opt_dnstap_socket_path=$withval], [opt_dnstap_socket_path="$1"]) + + if test "x$opt_dnstap" != "xno"; then + AC_PATH_PROG([PROTOC_C], [protoc-c]) + if test -z "$PROTOC_C"; then + AC_MSG_ERROR([The protoc-c program was not found. Please install protobuf-c!]) + fi + AC_ARG_WITH([protobuf-c], AC_HELP_STRING([--with-protobuf-c=path], + [Path where protobuf-c is installed, for dnstap]), [ + # workaround for protobuf-c includes at old dir before protobuf-c-1.0.0 + if test -f $withval/include/google/protobuf-c/protobuf-c.h; then + CFLAGS="$CFLAGS -I$withval/include/google" + else + CFLAGS="$CFLAGS -I$withval/include" + fi + LDFLAGS="$LDFLAGS -L$withval/lib" + ], [ + # workaround for protobuf-c includes at old dir before protobuf-c-1.0.0 + if test -f /usr/include/google/protobuf-c/protobuf-c.h; then + CFLAGS="$CFLAGS -I/usr/include/google" + else + if test -f /usr/local/include/google/protobuf-c/protobuf-c.h; then + CFLAGS="$CFLAGS -I/usr/local/include/google" + LDFLAGS="$LDFLAGS -L/usr/local/lib" + fi + fi + ]) + AC_ARG_WITH([libfstrm], AC_HELP_STRING([--with-libfstrm=path], + [Path where libfstrm is installed, for dnstap]), [ + CFLAGS="$CFLAGS -I$withval/include" + LDFLAGS="$LDFLAGS -L$withval/lib" + ]) + AC_SEARCH_LIBS([fstrm_iothr_init], [fstrm], [], + AC_MSG_ERROR([The fstrm library was not found. Please install fstrm!])) + AC_SEARCH_LIBS([protobuf_c_message_pack], [protobuf-c], [], + AC_MSG_ERROR([The protobuf-c library was not found. Please install protobuf-c!])) + $2 + else + $3 + fi +]) diff --git a/usr.sbin/unbound/dnstap/dnstap.proto b/usr.sbin/unbound/dnstap/dnstap.proto new file mode 100644 index 00000000000..3504d99ed23 --- /dev/null +++ b/usr.sbin/unbound/dnstap/dnstap.proto @@ -0,0 +1,262 @@ +// dnstap: flexible, structured event replication format for DNS software +// +// This file contains the protobuf schemas for the "dnstap" structured event +// replication format for DNS software. + +// Written in 2013-2014 by Farsight Security, Inc. +// +// To the extent possible under law, the author(s) have dedicated all +// copyright and related and neighboring rights to this file to the public +// domain worldwide. This file is distributed without any warranty. +// +// You should have received a copy of the CC0 Public Domain Dedication along +// with this file. If not, see: +// +// <http://creativecommons.org/publicdomain/zero/1.0/>. + +package dnstap; + +// "Dnstap": this is the top-level dnstap type, which is a "union" type that +// contains other kinds of dnstap payloads, although currently only one type +// of dnstap payload is defined. +// See: https://developers.google.com/protocol-buffers/docs/techniques#union +message Dnstap { + // DNS server identity. + // If enabled, this is the identity string of the DNS server which generated + // this message. Typically this would be the same string as returned by an + // "NSID" (RFC 5001) query. + optional bytes identity = 1; + + // DNS server version. + // If enabled, this is the version string of the DNS server which generated + // this message. Typically this would be the same string as returned by a + // "version.bind" query. + optional bytes version = 2; + + // Extra data for this payload. + // This field can be used for adding an arbitrary byte-string annotation to + // the payload. No encoding or interpretation is applied or enforced. + optional bytes extra = 3; + + // Identifies which field below is filled in. + enum Type { + MESSAGE = 1; + } + required Type type = 15; + + // One of the following will be filled in. + optional Message message = 14; +} + +// SocketFamily: the network protocol family of a socket. This specifies how +// to interpret "network address" fields. +enum SocketFamily { + INET = 1; // IPv4 (RFC 791) + INET6 = 2; // IPv6 (RFC 2460) +} + +// SocketProtocol: the transport protocol of a socket. This specifies how to +// interpret "transport port" fields. +enum SocketProtocol { + UDP = 1; // User Datagram Protocol (RFC 768) + TCP = 2; // Transmission Control Protocol (RFC 793) +} + +// Message: a wire-format (RFC 1035 section 4) DNS message and associated +// metadata. Applications generating "Message" payloads should follow +// certain requirements based on the MessageType, see below. +message Message { + + // There are eight types of "Message" defined that correspond to the + // four arrows in the following diagram, slightly modified from RFC 1035 + // section 2: + + // +---------+ +----------+ +--------+ + // | | query | | query | | + // | Stub |-SQ--------CQ->| Recursive|-RQ----AQ->| Auth. | + // | Resolver| | Server | | Name | + // | |<-SR--------CR-| |<-RR----AR-| Server | + // +---------+ response | | response | | + // +----------+ +--------+ + + // Each arrow has two Type values each, one for each "end" of each arrow, + // because these are considered to be distinct events. Each end of each + // arrow on the diagram above has been marked with a two-letter Type + // mnemonic. Clockwise from upper left, these mnemonic values are: + // + // SQ: STUB_QUERY + // CQ: CLIENT_QUERY + // RQ: RESOLVER_QUERY + // AQ: AUTH_QUERY + // AR: AUTH_RESPONSE + // RR: RESOLVER_RESPONSE + // CR: CLIENT_RESPONSE + // SR: STUB_RESPONSE + + // Two additional types of "Message" have been defined for the + // "forwarding" case where an upstream DNS server is responsible for + // further recursion. These are not shown on the diagram above, but have + // the following mnemonic values: + + // FQ: FORWARDER_QUERY + // FR: FORWARDER_RESPONSE + + // The "Message" Type values are defined below. + + enum Type { + // AUTH_QUERY is a DNS query message received from a resolver by an + // authoritative name server, from the perspective of the authorative + // name server. + AUTH_QUERY = 1; + + // AUTH_RESPONSE is a DNS response message sent from an authoritative + // name server to a resolver, from the perspective of the authoritative + // name server. + AUTH_RESPONSE = 2; + + // RESOLVER_QUERY is a DNS query message sent from a resolver to an + // authoritative name server, from the perspective of the resolver. + // Resolvers typically clear the RD (recursion desired) bit when + // sending queries. + RESOLVER_QUERY = 3; + + // RESOLVER_RESPONSE is a DNS response message received from an + // authoritative name server by a resolver, from the perspective of + // the resolver. + RESOLVER_RESPONSE = 4; + + // CLIENT_QUERY is a DNS query message sent from a client to a DNS + // server which is expected to perform further recursion, from the + // perspective of the DNS server. The client may be a stub resolver or + // forwarder or some other type of software which typically sets the RD + // (recursion desired) bit when querying the DNS server. The DNS server + // may be a simple forwarding proxy or it may be a full recursive + // resolver. + CLIENT_QUERY = 5; + + // CLIENT_RESPONSE is a DNS response message sent from a DNS server to + // a client, from the perspective of the DNS server. The DNS server + // typically sets the RA (recursion available) bit when responding. + CLIENT_RESPONSE = 6; + + // FORWARDER_QUERY is a DNS query message sent from a downstream DNS + // server to an upstream DNS server which is expected to perform + // further recursion, from the perspective of the downstream DNS + // server. + FORWARDER_QUERY = 7; + + // FORWARDER_RESPONSE is a DNS response message sent from an upstream + // DNS server performing recursion to a downstream DNS server, from the + // perspective of the downstream DNS server. + FORWARDER_RESPONSE = 8; + + // STUB_QUERY is a DNS query message sent from a stub resolver to a DNS + // server, from the perspective of the stub resolver. + STUB_QUERY = 9; + + // STUB_RESPONSE is a DNS response message sent from a DNS server to a + // stub resolver, from the perspective of the stub resolver. + STUB_RESPONSE = 10; + } + + // One of the Type values described above. + required Type type = 1; + + // One of the SocketFamily values described above. + optional SocketFamily socket_family = 2; + + // One of the SocketProtocol values described above. + optional SocketProtocol socket_protocol = 3; + + // The network address of the message initiator. + // For SocketFamily INET, this field is 4 octets (IPv4 address). + // For SocketFamily INET6, this field is 16 octets (IPv6 address). + optional bytes query_address = 4; + + // The network address of the message responder. + // For SocketFamily INET, this field is 4 octets (IPv4 address). + // For SocketFamily INET6, this field is 16 octets (IPv6 address). + optional bytes response_address = 5; + + // The transport port of the message initiator. + // This is a 16-bit UDP or TCP port number, depending on SocketProtocol. + optional uint32 query_port = 6; + + // The transport port of the message responder. + // This is a 16-bit UDP or TCP port number, depending on SocketProtocol. + optional uint32 response_port = 7; + + // The time at which the DNS query message was sent or received, depending + // on whether this is an AUTH_QUERY, RESOLVER_QUERY, or CLIENT_QUERY. + // This is the number of seconds since the UNIX epoch. + optional uint64 query_time_sec = 8; + + // The time at which the DNS query message was sent or received. + // This is the seconds fraction, expressed as a count of nanoseconds. + optional fixed32 query_time_nsec = 9; + + // The initiator's original wire-format DNS query message, verbatim. + optional bytes query_message = 10; + + // The "zone" or "bailiwick" pertaining to the DNS query message. + // This is a wire-format DNS domain name. + optional bytes query_zone = 11; + + // The time at which the DNS response message was sent or received, + // depending on whether this is an AUTH_RESPONSE, RESOLVER_RESPONSE, or + // CLIENT_RESPONSE. + // This is the number of seconds since the UNIX epoch. + optional uint64 response_time_sec = 12; + + // The time at which the DNS response message was sent or received. + // This is the seconds fraction, expressed as a count of nanoseconds. + optional fixed32 response_time_nsec = 13; + + // The responder's original wire-format DNS response message, verbatim. + optional bytes response_message = 14; +} + +// All fields except for 'type' in the Message schema are optional. +// It is recommended that at least the following fields be filled in for +// particular types of Messages. + +// AUTH_QUERY: +// socket_family, socket_protocol +// query_address, query_port +// query_message +// query_time_sec, query_time_nsec + +// AUTH_RESPONSE: +// socket_family, socket_protocol +// query_address, query_port +// query_time_sec, query_time_nsec +// response_message +// response_time_sec, response_time_nsec + +// RESOLVER_QUERY: +// socket_family, socket_protocol +// query_name, query_type, query_class +// query_message +// query_time_sec, query_time_nsec +// query_zone +// response_address, response_port + +// RESOLVER_RESPONSE: +// socket_family, socket_protocol +// query_name, query_type, query_class +// query_time_sec, query_time_nsec +// query_zone +// response_address, response_port +// response_message +// response_time_sec, response_time_nsec + +// CLIENT_QUERY: +// socket_family, socket_protocol +// query_message +// query_time_sec, query_time_nsec + +// CLIENT_RESPONSE: +// socket_family, socket_protocol +// query_time_sec, query_time_nsec +// response_message +// response_time_sec, response_time_nsec diff --git a/usr.sbin/unbound/dnstap/dnstap_config.h.in b/usr.sbin/unbound/dnstap/dnstap_config.h.in new file mode 100644 index 00000000000..c9f74893a1d --- /dev/null +++ b/usr.sbin/unbound/dnstap/dnstap_config.h.in @@ -0,0 +1,17 @@ +#ifndef UNBOUND_DNSTAP_CONFIG_H +#define UNBOUND_DNSTAP_CONFIG_H + +/* + * Process this file (dnstap_config.h.in) with AC_CONFIG_FILES to generate + * dnstap_config.h. + * + * This file exists so that USE_DNSTAP can be used without including config.h. + */ + +#if @ENABLE_DNSTAP@ /* ENABLE_DNSTAP */ +# ifndef USE_DNSTAP +# define USE_DNSTAP 1 +# endif +#endif + +#endif /* UNBOUND_DNSTAP_CONFIG_H */ diff --git a/usr.sbin/unbound/doc/CREDITS b/usr.sbin/unbound/doc/CREDITS index 429a799d6b0..805327ad6e2 100644 --- a/usr.sbin/unbound/doc/CREDITS +++ b/usr.sbin/unbound/doc/CREDITS @@ -19,3 +19,5 @@ Brett Carr - windows beta testing. Luca Bruno - patch for windows support in libunbound hosts and resolvconf(). Tom Hendrikx - contributed split-itar.sh a useful script to 5011-track ITAR. Daisuke HIGASHI - patch for rrset-roundrobin and minimal-responses. +Simon Perrault - DNS64 module. +Robert Edmonds - dnstap code. diff --git a/usr.sbin/unbound/doc/README b/usr.sbin/unbound/doc/README index badc60fc48a..d194aa0058a 100644 --- a/usr.sbin/unbound/doc/README +++ b/usr.sbin/unbound/doc/README @@ -1,8 +1,10 @@ -README for Unbound 1.4.22 +README for Unbound 1.5.0 Copyright 2007 NLnet Labs http://unbound.net This software is under BSD license, see LICENSE for details. +The DNS64 module has BSD license in dns64/dns64.c. +The DNSTAP code has BSD license in dnstap/dnstap.c. * Download the latest release version of this software from http://unbound.net diff --git a/usr.sbin/unbound/doc/README.DNS64 b/usr.sbin/unbound/doc/README.DNS64 new file mode 100644 index 00000000000..49446ac575d --- /dev/null +++ b/usr.sbin/unbound/doc/README.DNS64 @@ -0,0 +1,30 @@ +The DNS64 code was written by Viagenie, 2009, by Simon Perrault as part +of the Ecdysis project. The code is copyright by them, and has the BSD +license (see the dns64/dns64.c file). + +To enable DNS64 functionality in Unbound, two directives in unbound.conf must +be edited: + +1. The "module-config" directive must start with "dns64". For example: + + module-config: "dns64 validator iterator" + +If you're not using DNSSEC then you may remove "validator". + +2. The "dns64-prefix" directive indicates your DNS64 prefix. For example: + + dns64-prefix: 64:FF9B::/96 + +The prefix must be a /96 or shorter. + +To test that things are working right, perform a query against Unbound for a +domain name for which no AAAA record exists. You should see a AAAA record in +the answer section. The corresponding IPv6 address will be inside the DNS64 +prefix. For example: + + $ unbound -c unbound.conf + $ dig @localhost jazz-v4.viagenie.ca aaaa + [...] + ;; ANSWER SECTION: + jazz-v4.viagenie.ca. 86400 IN AAAA 64:ff9b::ce7b:1f02 + diff --git a/usr.sbin/unbound/doc/README.svn b/usr.sbin/unbound/doc/README.svn index 7f188987b09..b887e308cd4 100644 --- a/usr.sbin/unbound/doc/README.svn +++ b/usr.sbin/unbound/doc/README.svn @@ -1,6 +1,6 @@ README.svn -For a svn checkout +For a svn checkout: * configure script, aclocal.m4, as well as yacc/lex output files are committed to the repository. * use --enable-debug flag for configure to enable dependency tracking and diff --git a/usr.sbin/unbound/doc/example.conf.in b/usr.sbin/unbound/doc/example.conf.in index c13fbae045e..294be92d51a 100644 --- a/usr.sbin/unbound/doc/example.conf.in +++ b/usr.sbin/unbound/doc/example.conf.in @@ -1,7 +1,7 @@ # # Example configuration file. # -# See unbound.conf(5) man page, version 1.4.22. +# See unbound.conf(5) man page, version 1.5.0. # # this is a comment. @@ -85,7 +85,7 @@ server: # 0 is system default. Use 4m to handle spikes on very busy servers. # so-sndbuf: 0 - # on Linux(3.9+) use SO_REUSEPORT to distribute queries over threads. + # use SO_REUSEPORT to distribute queries over threads. # so-reuseport: no # EDNS reassembly buffer to advertise to UDP peers (the actual buffer @@ -331,7 +331,7 @@ server: # minimal-responses: no # module configuration of the server. A string with identifiers - # separated by spaces. "iterator" or "validator iterator" + # separated by spaces. Syntax: "[dns64] [validator] iterator" # module-config: "validator iterator" # File with trusted keys, kept uptodate using RFC5011 probes, @@ -437,7 +437,7 @@ server: # the amount of memory to use for the negative cache (used for DLV). # plain value in bytes or you can append k, m or G. default is "1Mb". # neg-cache-size: 1m - + # By default, for a number of zones a small default 'nothing here' # reply is built-in. Query traffic is thus blocked. If you # wish to serve such zone you can unblock them by uncommenting one @@ -478,6 +478,14 @@ server: # local-zone: "a.e.f.ip6.arpa." nodefault # local-zone: "b.e.f.ip6.arpa." nodefault # local-zone: "8.b.d.0.1.0.0.2.ip6.arpa." nodefault + # And for 64.100.in-addr.arpa. to 127.100.in-addr.arpa. + + # if unbound is running service for the local host then it is useful + # to perform lan-wide lookups to the upstream, and unblock the + # long list of local-zones above. If this unbound is a dns server + # for a network of computers, disabled is better and stops information + # leakage of local lan information. + # unblock-lan-zones: no # a number of locally served zones can be configured. # local-zone: <zone> <type> @@ -526,6 +534,10 @@ server: # Default is no. Can be turned on and off with unbound-control. # ssl-upstream: no + # DNS64 prefix. Must be specified when DNS64 is use. + # Enable dns64 in module-config. Used to synthesize IPv6 from IPv4. + # dns64-prefix: 64:ff9b::0/96 + # Python config section. To enable: # o use --with-pythonmodule to configure before compiling. # o list python in the module-config string (above) to enable. diff --git a/usr.sbin/unbound/doc/libunbound.3.in b/usr.sbin/unbound/doc/libunbound.3.in index 52c0a53917e..98abd28e2d4 100644 --- a/usr.sbin/unbound/doc/libunbound.3.in +++ b/usr.sbin/unbound/doc/libunbound.3.in @@ -1,4 +1,4 @@ -.TH "libunbound" "3" "Mar 12, 2014" "NLnet Labs" "unbound 1.4.22" +.TH "libunbound" "3" "Nov 18, 2014" "NLnet Labs" "unbound 1.5.0" .\" .\" libunbound.3 -- unbound library functions manual .\" @@ -8,7 +8,6 @@ .\" .\" .SH "NAME" -.LP .B libunbound, .B unbound.h, .B ub_ctx, @@ -23,6 +22,7 @@ .B ub_ctx_resolvconf, .B ub_ctx_hosts, .B ub_ctx_add_ta, +.B ub_ctx_add_ta_autr, .B ub_ctx_add_ta_file, .B ub_ctx_trustedkeys, .B ub_ctx_debugout, @@ -42,9 +42,8 @@ .B ub_ctx_zone_remove, .B ub_ctx_data_add, .B ub_ctx_data_remove -\- Unbound DNS validating resolver 1.4.22 functions. +\- Unbound DNS validating resolver 1.5.0 functions. .SH "SYNOPSIS" -.LP .B #include <unbound.h> .LP \fIstruct ub_ctx *\fR @@ -75,6 +74,9 @@ \fBub_ctx_add_ta\fR(\fIstruct ub_ctx*\fR ctx, \fIchar*\fR ta); .LP \fIint\fR +\fBub_ctx_add_ta_autr\fR(\fIstruct ub_ctx*\fR ctx, \fIchar*\fR fname); +.LP +\fIint\fR \fBub_ctx_add_ta_file\fR(\fIstruct ub_ctx*\fR ctx, \fIchar*\fR fname); .LP \fIint\fR @@ -137,7 +139,6 @@ \fIint\fR \fBub_ctx_data_remove\fR(\fIstruct ub_ctx*\fR ctx, \fIchar*\fR data); .SH "DESCRIPTION" -.LP .B Unbound is an implementation of a DNS resolver, that does caching and DNSSEC validation. This is the library API, for using the \-lunbound library. @@ -234,6 +235,15 @@ first resolve is done. The format is a string, similar to the zone\-file format, [domainname] [type] [rdata contents]. Both DS and DNSKEY records are accepted. .TP +.B ub_ctx_add_ta_autr +Add filename with automatically tracked trust anchor to the given context. +Pass name of a file with the managed trust anchor. You can create this +file with \fIunbound\-anchor\fR(8) for the root anchor. You can also +create it with an initial file with one line with a DNSKEY or DS record. +If the file is writable, it is updated when the trust anchor changes. +At this time it is only possible to add trusted keys before the +first resolve is done. +.TP .B ub_ctx_add_ta_file Add trust anchors to the given context. Pass name of a file with DS and DNSKEY records in zone file format. @@ -342,7 +352,6 @@ Add resource record data to local authority info, like local\-data .B ub_ctx_data_remove Delete local authority data from the name given. .SH "RESULT DATA STRUCTURE" -.LP The result of the DNS resolution and validation is returned as \fIstruct ub_result\fR. The result structure contains the following entries. .P diff --git a/usr.sbin/unbound/doc/unbound-anchor.8.in b/usr.sbin/unbound/doc/unbound-anchor.8.in index 41b18ed5382..6036dd241f6 100644 --- a/usr.sbin/unbound/doc/unbound-anchor.8.in +++ b/usr.sbin/unbound/doc/unbound-anchor.8.in @@ -1,4 +1,4 @@ -.TH "unbound-anchor" "8" "Mar 12, 2014" "NLnet Labs" "unbound 1.4.22" +.TH "unbound-anchor" "8" "Nov 18, 2014" "NLnet Labs" "unbound 1.5.0" .\" .\" unbound-anchor.8 -- unbound anchor maintenance utility manual .\" @@ -8,7 +8,6 @@ .\" .\" .SH "NAME" -.LP .B unbound\-anchor \- Unbound anchor utility. .SH "SYNOPSIS" diff --git a/usr.sbin/unbound/doc/unbound-checkconf.8.in b/usr.sbin/unbound/doc/unbound-checkconf.8.in index 69e0b4f439b..6253729ccb2 100644 --- a/usr.sbin/unbound/doc/unbound-checkconf.8.in +++ b/usr.sbin/unbound/doc/unbound-checkconf.8.in @@ -1,4 +1,4 @@ -.TH "unbound-checkconf" "8" "Mar 12, 2014" "NLnet Labs" "unbound 1.4.22" +.TH "unbound-checkconf" "8" "Nov 18, 2014" "NLnet Labs" "unbound 1.5.0" .\" .\" unbound-checkconf.8 -- unbound configuration checker manual .\" @@ -8,7 +8,6 @@ .\" .\" .SH "NAME" -.LP unbound\-checkconf \- Check unbound configuration file for errors. .SH "SYNOPSIS" diff --git a/usr.sbin/unbound/doc/unbound-control.8.in b/usr.sbin/unbound/doc/unbound-control.8.in index e57231c205f..bfe24c2ed1c 100644 --- a/usr.sbin/unbound/doc/unbound-control.8.in +++ b/usr.sbin/unbound/doc/unbound-control.8.in @@ -1,4 +1,4 @@ -.TH "unbound-control" "8" "Mar 12, 2014" "NLnet Labs" "unbound 1.4.22" +.TH "unbound-control" "8" "Nov 18, 2014" "NLnet Labs" "unbound 1.5.0" .\" .\" unbound-control.8 -- unbound remote control manual .\" @@ -8,7 +8,6 @@ .\" .\" .SH "NAME" -.LP .B unbound\-control, .B unbound\-control\-setup \- Unbound remote server control utility. @@ -133,6 +132,12 @@ This needs to walk and inspect the entire cache, and is a slow operation. .B flush_bogus Remove all bogus data from the cache. .TP +.B flush_negative +Remove all negative data from the cache. This is nxdomain answers, +nodata answers and servfail answers. Also removes bad key entries +(which could be due to failed lookups) from the dnssec key cache, and +iterator last-resort lookup failures from the rrset cache. +.TP .B flush_stats Reset statistics to zero. .TP @@ -147,6 +152,8 @@ such as a higher verbosity level. Show what is worked on. Prints all queries that the server is currently working on. Prints the time that users have been waiting. For internal requests, no time is printed. And then prints out the module status. +This prints the queries from the first thread, and not queries that are +being serviced from other threads. .TP .B flush_infra \fIall|IP If all then entire infra cache is emptied. If a specific IP address, the @@ -401,6 +408,10 @@ Also printed for other opcodes, UPDATE, ... .I num.query.tcp Number of queries that were made using TCP towards the unbound server. .TP +.I num.query.tcpout +Number of queries that the unbound server made using TCP outgoing towards +other servers. +.TP .I num.query.ipv6 Number of queries that were made using IPv6 towards the unbound server. .TP @@ -451,6 +462,21 @@ Replies that were unwanted or unsolicited. Could have been random traffic, delayed duplicates, very late answers, or could be spoofing attempts. Some low level of late answers and delayed duplicates are to be expected with the UDP protocol. Very high values could indicate a threat (spoofing). +.TP +.I msg.cache.count +The number of items (DNS replies) in the message cache. +.TP +.I rrset.cache.count +The number of RRsets in the rrset cache. This includes rrsets used by +the messages in the message cache, but also delegation information. +.TP +.I infra.cache.count +The number of items in the infra cache. These are IP addresses with their +timing and protocol support information. +.TP +.I key.cache.count +The number of items in the key cache. These are DNSSEC keys, one item +per delegation point, and their validation status. .SH "FILES" .TP .I @ub_conf_file@ diff --git a/usr.sbin/unbound/doc/unbound.conf.5.in b/usr.sbin/unbound/doc/unbound.conf.5.in index 75967e1b8cb..cd0af718fb9 100644 --- a/usr.sbin/unbound/doc/unbound.conf.5.in +++ b/usr.sbin/unbound/doc/unbound.conf.5.in @@ -1,4 +1,4 @@ -.TH "unbound.conf" "5" "Mar 12, 2014" "NLnet Labs" "unbound 1.4.22" +.TH "unbound.conf" "5" "Nov 18, 2014" "NLnet Labs" "unbound 1.5.0" .\" .\" unbound.conf.5 -- unbound.conf manual .\" @@ -8,14 +8,11 @@ .\" .\" .SH "NAME" -.LP .B unbound.conf \- Unbound configuration file. .SH "SYNOPSIS" -.LP .B unbound.conf .SH "DESCRIPTION" -.LP .B unbound.conf is used to configure \fIunbound\fR(8). @@ -65,7 +62,6 @@ server: access\-control: 2001:DB8::/64 allow .fi .SH "FILE FORMAT" -.LP There must be whitespace between keywords. Attribute keywords end with a colon ':'. An attribute is followed by its containing attributes, or a value. .P @@ -169,11 +165,11 @@ Give a port number or a range of the form "low\-high", without spaces. .TP .B outgoing\-num\-tcp: \fI<number> Number of outgoing TCP buffers to allocate per thread. Default is 10. If set -to 0, or if do_tcp is "no", no TCP queries to authoritative servers are done. +to 0, or if do\-tcp is "no", no TCP queries to authoritative servers are done. .TP .B incoming\-num\-tcp: \fI<number> Number of incoming TCP buffers to allocate per thread. Default is 10. If set -to 0, or if do_tcp is "no", no TCP queries from clients are accepted. +to 0, or if do\-tcp is "no", no TCP queries from clients are accepted. .TP .B edns\-buffer\-size: \fI<number> Number of bytes size to advertise as the EDNS reassembly buffer size. @@ -262,8 +258,9 @@ to so\-rcvbuf. .B so\-reuseport: \fI<yes or no> If yes, then open dedicated listening sockets for incoming queries for each thread and try to set the SO_REUSEPORT socket option on each socket. May -distribute incoming queries to threads more evenly. Default is no. Only -supported on Linux >= 3.9. You can enable it (on any platform and kernel), +distribute incoming queries to threads more evenly. Default is no. On Linux +it is supported in kernels >= 3.9. On other systems, FreeBSD, OSX it may +also work. You can enable it (on any platform and kernel), it then attempts to open the port and passes the option if it was available at compile time, if that works it is used, if it fails, it continues silently (unless verbosity 3) without the option. @@ -310,7 +307,9 @@ Enable or disable whether ip4 queries are answered or issued. Default is yes. .B do\-ip6: \fI<yes or no> Enable or disable whether ip6 queries are answered or issued. Default is yes. If disabled, queries are not answered on IPv6, and queries are not sent on -IPv6 to the internet nameservers. +IPv6 to the internet nameservers. With this option you can disable the +ipv6 transport for sending DNS traffic, it does not impact the contents of +the DNS traffic, which may have ip4 and ip6 addresses in it. .TP .B do\-udp: \fI<yes or no> Enable or disable whether UDP queries are answered or issued. Default is yes. @@ -778,6 +777,17 @@ Number of bytes size of the aggressive negative cache. Default is 1 megabyte. A plain number is in bytes, append 'k', 'm' or 'g' for kilobytes, megabytes or gigabytes (1024*1024 bytes in a megabyte). .TP +.B unblock\-lan\-zones: \fI<yesno> +Default is disabled. If enabled, then for private address space, +the reverse lookups are no longer filtered. This allows unbound when +running as dns service on a host where it provides service for that host, +to put out all of the queries for the 'lan' upstream. When enabled, +only localhost, 127.0.0.1 reverse and ::1 reverse zones are configured +with default local zones. Disable the option when unbound is running +as a (DHCP-) DNS network resolver for a group of machines, where such +lookups should be filtered (RFC compliance), this also stops potential +data leakage about the local network to the upstream DNS servers. +.TP .B local\-zone: \fI<zone> <type> Configure a local zone. The type determines the answer to give if there is no match from local\-data. The types are deny, refuse, static, @@ -894,6 +904,7 @@ records are provided. Reverse data for zones 0.in\-addr.arpa, 254.169.in\-addr.arpa, 2.0.192.in\-addr.arpa (TEST NET 1), 100.51.198.in\-addr.arpa (TEST NET 2), 113.0.203.in\-addr.arpa (TEST NET 3), 255.255.255.255.in\-addr.arpa. +And from 64.100.in\-addr.arpa to 127.100.in\-addr.arpa (Shared Address Space). .TP 10 \h'5'\fIreverse RFC4291 IP6 unspecified\fR Reverse data for zone @@ -1071,6 +1082,19 @@ and the word "python" has to be put in the \fBmodule\-config:\fR option .TP .B python\-script: \fI<python file>\fR The script file to load. +.SS "DNS64 Module Options" +.LP +The dns64 module must be configured in the \fBmodule\-config:\fR "dns64 +validator iterator" directive and be compiled into the daemon to be +enabled. These settings go in the \fBserver:\fR section. +.TP +.B dns64\-prefix: \fI<IPv6 prefix>\fR +This sets the DNS64 prefix to use to synthesize AAAA records with. +It must be /96 or shorter. The default prefix is 64:ff9b::/96. +.TP +.B dns64\-synthall: \fI<yes or no>\fR +Debug option, default no. If enabled, synthesize all AAAA records +despite the presence of actual AAAA records. .SH "MEMORY CONTROL EXAMPLE" In the example config settings below memory usage is reduced. Some service levels are lower, notable very large data and a high TCP load are no longer diff --git a/usr.sbin/unbound/doc/unbound.doxygen b/usr.sbin/unbound/doc/unbound.doxygen index 199d7ad0de0..43f2e38d83c 100644 --- a/usr.sbin/unbound/doc/unbound.doxygen +++ b/usr.sbin/unbound/doc/unbound.doxygen @@ -287,7 +287,7 @@ TYPEDEF_HIDES_STRUCT = NO # 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, # corresponding to a cache size of 2^16 = 65536 symbols -SYMBOL_CACHE_SIZE = 0 +#SYMBOL_CACHE_SIZE = 0 #--------------------------------------------------------------------------- # Build related configuration options @@ -1272,13 +1272,13 @@ XML_OUTPUT = xml # which can be used by a validating XML parser to check the # syntax of the XML files. -XML_SCHEMA = +#XML_SCHEMA = # The XML_DTD tag can be used to specify an XML DTD, # which can be used by a validating XML parser to check the # syntax of the XML files. -XML_DTD = +#XML_DTD = # If the XML_PROGRAMLISTING tag is set to YES Doxygen will # dump the program listings (including syntax highlighting @@ -1497,7 +1497,7 @@ HAVE_DOT = NO # DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory # containing the font. -DOT_FONTNAME = FreeSans.ttf +#DOT_FONTNAME = FreeSans.ttf # The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. # The default size is 10pt. diff --git a/usr.sbin/unbound/iterator/iter_delegpt.c b/usr.sbin/unbound/iterator/iter_delegpt.c index 1d84280d2ea..b212ec0775f 100644 --- a/usr.sbin/unbound/iterator/iter_delegpt.c +++ b/usr.sbin/unbound/iterator/iter_delegpt.c @@ -147,7 +147,9 @@ delegpt_find_addr(struct delegpt* dp, struct sockaddr_storage* addr, { struct delegpt_addr* p = dp->target_list; while(p) { - if(sockaddr_cmp_addr(addr, addrlen, &p->addr, p->addrlen)==0) { + if(sockaddr_cmp_addr(addr, addrlen, &p->addr, p->addrlen)==0 + && ((struct sockaddr_in*)addr)->sin_port == + ((struct sockaddr_in*)&p->addr)->sin_port) { return p; } p = p->next_target; diff --git a/usr.sbin/unbound/iterator/iterator.h b/usr.sbin/unbound/iterator/iterator.h index 1816d12cd03..0b91760d4a4 100644 --- a/usr.sbin/unbound/iterator/iterator.h +++ b/usr.sbin/unbound/iterator/iterator.h @@ -57,7 +57,7 @@ struct iter_priv; /** max number of referrals. Makes sure resolver does not run away */ #define MAX_REFERRAL_COUNT 130 /** max number of queries-sent-out. Make sure large NS set does not loop */ -#define MAX_SENT_COUNT 16 +#define MAX_SENT_COUNT 32 /** at what query-sent-count to stop target fetch policy */ #define TARGET_FETCH_STOP 3 /** how nice is a server without further information, in msec @@ -69,10 +69,6 @@ struct iter_priv; * Equals RTT_MAX_TIMEOUT */ #define USEFUL_SERVER_TOP_TIMEOUT 120000 -/** Number of lost messages in a row that get a host blacklisted. - * With 16, a couple different queries have to time out and no working - * queries are happening */ -#define USEFUL_SERVER_MAX_LOST 16 /** number of retries on outgoing queries */ #define OUTBOUND_MSG_RETRY 5 /** RTT band, within this amount from the best, servers are chosen randomly. @@ -234,7 +230,8 @@ struct iter_qstate { int caps_fallback; /** state for capsfail: current server number to try */ size_t caps_server; - /** state for capsfail: stored query for comparisons */ + /** state for capsfail: stored query for comparisons. Can be NULL if + * no response had been seen prior to starting the fallback. */ struct reply_info* caps_reply; /** Current delegation message - returned for non-RD queries */ diff --git a/usr.sbin/unbound/ldns/keyraw.c b/usr.sbin/unbound/ldns/keyraw.c index fe650aadacb..1ff07742b88 100644 --- a/usr.sbin/unbound/ldns/keyraw.c +++ b/usr.sbin/unbound/ldns/keyraw.c @@ -324,8 +324,10 @@ sldns_ecdsa2pkey_raw(unsigned char* key, size_t keylen, uint8_t algo) ec = EC_KEY_new_by_curve_name(NID_secp384r1); } else ec = NULL; if(!ec) return NULL; - if(keylen+1 > sizeof(buf)) - return NULL; /* sanity check */ + if(keylen+1 > sizeof(buf)) { /* sanity check */ + EC_KEY_free(ec); + return NULL; + } /* prepend the 0x02 (from docs) (or actually 0x04 from implementation * of openssl) for uncompressed data */ buf[0] = POINT_CONVERSION_UNCOMPRESSED; diff --git a/usr.sbin/unbound/ldns/parse.c b/usr.sbin/unbound/ldns/parse.c index d0934ffb1dc..a605e549fca 100644 --- a/usr.sbin/unbound/ldns/parse.c +++ b/usr.sbin/unbound/ldns/parse.c @@ -218,6 +218,17 @@ sldns_fget_keyword_data_l(FILE *f, const char *keyword, const char *k_del, char } } +int +sldns_bgetc(sldns_buffer *buffer) +{ + if (!sldns_buffer_available_at(buffer, buffer->_position, sizeof(uint8_t))) { + sldns_buffer_set_position(buffer, sldns_buffer_limit(buffer)); + /* sldns_buffer_rewind(buffer);*/ + return EOF; + } + return (int)sldns_buffer_read_u8(buffer); +} + ssize_t sldns_bget_token(sldns_buffer *b, char *token, const char *delim, size_t limit) { diff --git a/usr.sbin/unbound/ldns/parseutil.c b/usr.sbin/unbound/ldns/parseutil.c index 55e3a5b1ad9..28b344ede74 100644 --- a/usr.sbin/unbound/ldns/parseutil.c +++ b/usr.sbin/unbound/ldns/parseutil.c @@ -288,9 +288,9 @@ sldns_parse_escape(uint8_t *ch_p, const char** str_p) { uint16_t val; - if ((*str_p)[0] && isdigit((*str_p)[0]) && - (*str_p)[1] && isdigit((*str_p)[1]) && - (*str_p)[2] && isdigit((*str_p)[2])) { + if ((*str_p)[0] && isdigit((unsigned char)(*str_p)[0]) && + (*str_p)[1] && isdigit((unsigned char)(*str_p)[1]) && + (*str_p)[2] && isdigit((unsigned char)(*str_p)[2])) { val = (uint16_t)(((*str_p)[0] - '0') * 100 + ((*str_p)[1] - '0') * 10 + @@ -303,7 +303,7 @@ sldns_parse_escape(uint8_t *ch_p, const char** str_p) *str_p += 3; return 1; - } else if ((*str_p)[0] && !isdigit((*str_p)[0])) { + } else if ((*str_p)[0] && !isdigit((unsigned char)(*str_p)[0])) { *ch_p = (uint8_t)*(*str_p)++; return 1; @@ -467,7 +467,7 @@ sldns_b32_pton_base(const char* src, size_t src_sz, uint8_t* dst, size_t dst_sz, ch = *src++; --src_sz; - } while (isspace(ch) && src_sz > 0); + } while (isspace((unsigned char)ch) && src_sz > 0); if (ch == '=' || ch == '\0') break; @@ -572,7 +572,7 @@ sldns_b32_pton_base(const char* src, size_t src_sz, uint8_t* dst, size_t dst_sz, ch = *src++; src_sz--; - } while (isspace(ch)); + } while (isspace((unsigned char)ch)); if (ch != '=') return -1; diff --git a/usr.sbin/unbound/ldns/rrdef.c b/usr.sbin/unbound/ldns/rrdef.c index 8f7dd3036ec..9b4bf7cfe32 100644 --- a/usr.sbin/unbound/ldns/rrdef.c +++ b/usr.sbin/unbound/ldns/rrdef.c @@ -359,14 +359,10 @@ static sldns_rr_descriptor rdata_field_descriptors[] = { /* 58 */ {LDNS_RR_TYPE_TALINK, "TALINK", 2, 2, type_talink_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 2 }, -#ifdef DRAFT_RRTYPES /* 59 */ {LDNS_RR_TYPE_CDS, "CDS", 4, 4, type_ds_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -#else -{LDNS_RR_TYPE_NULL, "TYPE59", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, -#endif - -{LDNS_RR_TYPE_NULL, "TYPE60", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, + /* 60 */ + {LDNS_RR_TYPE_CDNSKEY, "CDNSKEY", 4, 4, type_dnskey_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, {LDNS_RR_TYPE_NULL, "TYPE61", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, {LDNS_RR_TYPE_NULL, "TYPE62", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, {LDNS_RR_TYPE_NULL, "TYPE63", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 }, diff --git a/usr.sbin/unbound/ldns/rrdef.h b/usr.sbin/unbound/ldns/rrdef.h index 442eb26e0e0..933bcdfbf07 100644 --- a/usr.sbin/unbound/ldns/rrdef.h +++ b/usr.sbin/unbound/ldns/rrdef.h @@ -191,8 +191,8 @@ enum sldns_enum_rr_type LDNS_RR_TYPE_RKEY = 57, /** draft-ietf-dnsop-trust-history */ LDNS_RR_TYPE_TALINK = 58, - /** draft-barwood-dnsop-ds-publis */ - LDNS_RR_TYPE_CDS = 59, + LDNS_RR_TYPE_CDS = 59, /** RFC 7344 */ + LDNS_RR_TYPE_CDNSKEY = 60, /** RFC 7344 */ LDNS_RR_TYPE_SPF = 99, /* RFC 4408 */ @@ -419,7 +419,7 @@ enum sldns_enum_edns_option LDNS_EDNS_N3U = 7, /* RFC6975 */ LDNS_EDNS_CLIENT_SUBNET = 8 /* draft-vandergaast-edns-client-subnet */ }; -typedef enum sldns_edns_option sldns_edns_option; +typedef enum sldns_enum_edns_option sldns_edns_option; #define LDNS_EDNS_MASK_DO_BIT 0x8000 diff --git a/usr.sbin/unbound/ldns/sbuffer.c b/usr.sbin/unbound/ldns/sbuffer.c index b0b2efdcf4f..3d087bfe252 100644 --- a/usr.sbin/unbound/ldns/sbuffer.c +++ b/usr.sbin/unbound/ldns/sbuffer.c @@ -165,17 +165,6 @@ sldns_buffer_export(sldns_buffer *buffer) return buffer->_data; } -int -sldns_bgetc(sldns_buffer *buffer) -{ - if (!sldns_buffer_available_at(buffer, buffer->_position, sizeof(uint8_t))) { - sldns_buffer_set_position(buffer, sldns_buffer_limit(buffer)); - /* sldns_buffer_rewind(buffer);*/ - return EOF; - } - return (int)sldns_buffer_read_u8(buffer); -} - void sldns_buffer_copy(sldns_buffer* result, sldns_buffer* from) { diff --git a/usr.sbin/unbound/ldns/sbuffer.h b/usr.sbin/unbound/ldns/sbuffer.h index 2436763d3ea..3ce874fc7f7 100644 --- a/usr.sbin/unbound/ldns/sbuffer.h +++ b/usr.sbin/unbound/ldns/sbuffer.h @@ -35,9 +35,9 @@ INLINE uint16_t sldns_read_uint16(const void *src) { #ifdef ALLOW_UNALIGNED_ACCESSES - return ntohs(*(uint16_t *) src); + return ntohs(*(const uint16_t *) src); #else - uint8_t *p = (uint8_t *) src; + const uint8_t *p = (const uint8_t *) src; return ((uint16_t) p[0] << 8) | (uint16_t) p[1]; #endif } @@ -46,9 +46,9 @@ INLINE uint32_t sldns_read_uint32(const void *src) { #ifdef ALLOW_UNALIGNED_ACCESSES - return ntohl(*(uint32_t *) src); + return ntohl(*(const uint32_t *) src); #else - uint8_t *p = (uint8_t *) src; + const uint8_t *p = (const uint8_t *) src; return ( ((uint32_t) p[0] << 24) | ((uint32_t) p[1] << 16) | ((uint32_t) p[2] << 8) diff --git a/usr.sbin/unbound/ldns/str2wire.c b/usr.sbin/unbound/ldns/str2wire.c index 92eefa8518f..931e28f84e3 100644 --- a/usr.sbin/unbound/ldns/str2wire.c +++ b/usr.sbin/unbound/ldns/str2wire.c @@ -245,7 +245,7 @@ rrinternal_get_ttl(sldns_buffer* strbuf, char* token, size_t token_len, } *ttl = (uint32_t) sldns_str2period(token, &endptr); - if (strlen(token) > 0 && !isdigit((int)token[0])) { + if (strlen(token) > 0 && !isdigit((unsigned char)token[0])) { *not_there = 1; /* ah, it's not there or something */ if (default_ttl == 0) { @@ -337,7 +337,7 @@ rrinternal_get_delims(sldns_rdf_type rdftype, uint16_t r_cnt, uint16_t r_max) case LDNS_RDF_TYPE_WKS : /* it is the last rd field. */ case LDNS_RDF_TYPE_IPSECKEY : case LDNS_RDF_TYPE_NSEC : if (r_cnt == r_max - 1) { - return "\n\t"; + return "\n"; } break; default : break; @@ -384,11 +384,11 @@ rrinternal_spool_hex(char* token, uint8_t* rr, size_t rr_len, { char* p = token; while(*p) { - if(isspace(*p)) { + if(isspace((unsigned char)*p)) { p++; continue; } - if(!isxdigit(*p)) + if(!isxdigit((unsigned char)*p)) return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_RDATA, p-token); if(*cur_hex_data_size >= hex_data_size) @@ -827,6 +827,20 @@ const char* sldns_get_errorstr_parse(int e) return lt?lt->name:"unknown error"; } +/* Strip whitespace from the start and the end of <line>. */ +static char * +sldns_strip_ws(char *line) +{ + char *s = line, *e; + + for (s = line; *s && isspace((unsigned char)*s); s++) + ; + for (e = strchr(s, 0); e > s+2 && isspace((unsigned char)e[-1]) && e[-2] != '\\'; e--) + ; + *e = 0; + return s; +} + int sldns_fp2wire_rr_buf(FILE* in, uint8_t* rr, size_t* len, size_t* dname_len, struct sldns_file_parse_state* parse_state) { @@ -852,28 +866,23 @@ int sldns_fp2wire_rr_buf(FILE* in, uint8_t* rr, size_t* len, size_t* dname_len, return LDNS_WIREPARSE_ERR_OK; } - if(strncmp(line, "$ORIGIN", 7) == 0 && isspace(line[7])) { - size_t off = 8; + if(strncmp(line, "$ORIGIN", 7) == 0 && isspace((unsigned char)line[7])) { int s; *len = 0; *dname_len = 0; if(!parse_state) return LDNS_WIREPARSE_ERR_OK; - while(isspace(line[off])) - off++; parse_state->origin_len = sizeof(parse_state->origin); - s = sldns_str2wire_dname_buf(line+off, parse_state->origin, - &parse_state->origin_len); + s = sldns_str2wire_dname_buf(sldns_strip_ws(line+8), + parse_state->origin, &parse_state->origin_len); if(s) parse_state->origin_len = 0; return s; - } else if(strncmp(line, "$TTL", 4) == 0 && isspace(line[4])) { + } else if(strncmp(line, "$TTL", 4) == 0 && isspace((unsigned char)line[4])) { const char* end = NULL; - size_t off = 8; *len = 0; *dname_len = 0; if(!parse_state) return LDNS_WIREPARSE_ERR_OK; - while(isspace(line[off])) - off++; - parse_state->default_ttl = sldns_str2period(line+off, &end); + parse_state->default_ttl = sldns_str2period( + sldns_strip_ws(line+5), &end); } else if (strncmp(line, "$INCLUDE", 8) == 0) { *len = 0; *dname_len = 0; @@ -1188,11 +1197,11 @@ int sldns_str2wire_hex_buf(const char* str, uint8_t* rd, size_t* len) const char* s = str; size_t dlen = 0; /* number of hexdigits parsed */ while(*s) { - if(isspace(*s)) { + if(isspace((unsigned char)*s)) { s++; continue; } - if(!isxdigit(*s)) + if(!isxdigit((unsigned char)*s)) return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_HEX, s-str); if(*len < dlen/2 + 1) return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, @@ -1392,7 +1401,7 @@ static int loc_parse_cm(char* my_str, char** endstr, uint8_t* m, uint8_t* e) { uint32_t meters = 0, cm = 0, val; - while (isblank(*my_str)) { + while (isblank((unsigned char)*my_str)) { my_str++; } meters = (uint32_t)strtol(my_str, &my_str, 10); @@ -1443,17 +1452,17 @@ int sldns_str2wire_loc_buf(const char* str, uint8_t* rd, size_t* len) char *my_str = (char *) str; - if (isdigit((int) *my_str)) { + if (isdigit((unsigned char) *my_str)) { h = (uint32_t) strtol(my_str, &my_str, 10); } else { return LDNS_WIREPARSE_ERR_INVALID_STR; } - while (isblank((int) *my_str)) { + while (isblank((unsigned char) *my_str)) { my_str++; } - if (isdigit((int) *my_str)) { + if (isdigit((unsigned char) *my_str)) { m = (uint32_t) strtol(my_str, &my_str, 10); } else if (*my_str == 'N' || *my_str == 'S') { goto north; @@ -1461,16 +1470,16 @@ int sldns_str2wire_loc_buf(const char* str, uint8_t* rd, size_t* len) return LDNS_WIREPARSE_ERR_INVALID_STR; } - while (isblank((int) *my_str)) { + while (isblank((unsigned char) *my_str)) { my_str++; } - if (isdigit((int) *my_str)) { + if (isdigit((unsigned char) *my_str)) { s = strtod(my_str, &my_str); } /* skip blanks before norterness */ - while (isblank((int) *my_str)) { + while (isblank((unsigned char) *my_str)) { my_str++; } @@ -1497,21 +1506,21 @@ north: } else { latitude = equator - latitude; } - while (isblank(*my_str)) { + while (isblank((unsigned char)*my_str)) { my_str++; } - if (isdigit((int) *my_str)) { + if (isdigit((unsigned char) *my_str)) { h = (uint32_t) strtol(my_str, &my_str, 10); } else { return LDNS_WIREPARSE_ERR_INVALID_STR; } - while (isblank((int) *my_str)) { + while (isblank((unsigned char) *my_str)) { my_str++; } - if (isdigit((int) *my_str)) { + if (isdigit((unsigned char) *my_str)) { m = (uint32_t) strtol(my_str, &my_str, 10); } else if (*my_str == 'E' || *my_str == 'W') { goto east; @@ -1519,16 +1528,16 @@ north: return LDNS_WIREPARSE_ERR_INVALID_STR; } - while (isblank(*my_str)) { + while (isblank((unsigned char)*my_str)) { my_str++; } - if (isdigit((int) *my_str)) { + if (isdigit((unsigned char) *my_str)) { s = strtod(my_str, &my_str); } /* skip blanks before easterness */ - while (isblank(*my_str)) { + while (isblank((unsigned char)*my_str)) { my_str++; } @@ -1591,6 +1600,17 @@ east: return LDNS_WIREPARSE_ERR_OK; } +static void +ldns_tolower_str(char* s) +{ + if(s) { + while(*s) { + *s = (char)tolower((unsigned char)*s); + s++; + } + } +} + int sldns_str2wire_wks_buf(const char* str, uint8_t* rd, size_t* len) { int rd_len = 1; @@ -1605,6 +1625,7 @@ int sldns_str2wire_wks_buf(const char* str, uint8_t* rd, size_t* len) return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; while(sldns_bget_token(&strbuf, token, "\t\n ", sizeof(token)) > 0) { + ldns_tolower_str(token); if(!have_proto) { struct protoent *p = getprotobyname(token); have_proto = 1; @@ -1682,11 +1703,11 @@ int sldns_str2wire_nsap_buf(const char* str, uint8_t* rd, size_t* len) if(slen > LDNS_MAX_RDFLEN*2) return LDNS_WIREPARSE_ERR_LABEL_OVERFLOW; while(*s) { - if(isspace(*s) || *s == '.') { + if(isspace((unsigned char)*s) || *s == '.') { s++; continue; } - if(!isxdigit(*s)) + if(!isxdigit((unsigned char)*s)) return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_HEX, s-str); if(*len < dlen/2 + 1) return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, @@ -1713,11 +1734,11 @@ int sldns_str2wire_atma_buf(const char* str, uint8_t* rd, size_t* len) if(slen > LDNS_MAX_RDFLEN*2) return LDNS_WIREPARSE_ERR_LABEL_OVERFLOW; while(*s) { - if(isspace(*s) || *s == '.') { + if(isspace((unsigned char)*s) || *s == '.') { s++; continue; } - if(!isxdigit(*s)) + if(!isxdigit((unsigned char)*s)) return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_HEX, s-str); if(*len < dlen/2 + 1) return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, @@ -1820,7 +1841,8 @@ int sldns_str2wire_nsec3_salt_buf(const char* str, uint8_t* rd, size_t* len) return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; rd[0] = (uint8_t) (salt_length_str / 2); for (i = 0; i < salt_length_str; i += 2) { - if (isxdigit((int)str[i]) && isxdigit((int)str[i+1])) { + if (isxdigit((unsigned char)str[i]) && + isxdigit((unsigned char)str[i+1])) { rd[1+i/2] = (uint8_t)(sldns_hexdigit_to_int(str[i])*16 + sldns_hexdigit_to_int(str[i+1])); } else { @@ -1907,7 +1929,7 @@ int sldns_str2wire_tag_buf(const char* str, uint8_t* rd, size_t* len) if(*len < slen+1) return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL; for (ptr = str; *ptr; ptr++) { - if(!isalnum(*ptr)) + if(!isalnum((unsigned char)*ptr)) return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_TAG, ptr-str); } rd[0] = slen; diff --git a/usr.sbin/unbound/ldns/wire2str.c b/usr.sbin/unbound/ldns/wire2str.c index c2a1850ef9b..81e173c78d5 100644 --- a/usr.sbin/unbound/ldns/wire2str.c +++ b/usr.sbin/unbound/ldns/wire2str.c @@ -722,7 +722,7 @@ static int dname_char_print(char** s, size_t* slen, uint8_t c) { if(c == '.' || c == ';' || c == '(' || c == ')' || c == '\\') return sldns_str_print(s, slen, "\\%c", c); - else if(!(isascii((int)c) && isgraph((int)c))) + else if(!(isascii((unsigned char)c) && isgraph((unsigned char)c))) return sldns_str_print(s, slen, "\\%03u", (unsigned)c); /* plain printout */ if(*slen) { @@ -1064,7 +1064,7 @@ int sldns_wire2str_aaaa_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) /** printout escaped TYPE_STR character */ static int str_char_print(char** s, size_t* sl, uint8_t c) { - if(isprint((int)c) || c == '\t') { + if(isprint((unsigned char)c) || c == '\t') { if(c == '\"' || c == '\\') return sldns_str_print(s, sl, "\\%c", c); if(*sl) { @@ -1625,7 +1625,7 @@ int sldns_wire2str_tag_scan(uint8_t** d, size_t* dl, char** s, size_t* sl) if(*dl < 1+n) return -1; for(i=0; i<n; i++) - if(!isalnum((int)(*d)[i])) + if(!isalnum((unsigned char)(*d)[i])) return -1; for(i=0; i<n; i++) w += sldns_str_print(s, sl, "%c", (char)(*d)[i]); @@ -1713,7 +1713,7 @@ int sldns_wire2str_edns_nsid_print(char** s, size_t* sl, uint8_t* data, size_t i, printed=0; w += print_hex_buf(s, sl, data, len); for(i=0; i<len; i++) { - if(isprint((int)data[i]) || data[i] == '\t') { + if(isprint((unsigned char)data[i]) || data[i] == '\t') { if(!printed) { w += sldns_str_print(s, sl, " ("); printed = 1; diff --git a/usr.sbin/unbound/libunbound/libunbound.c b/usr.sbin/unbound/libunbound/libunbound.c index 78d31968ac6..91a663a773c 100644 --- a/usr.sbin/unbound/libunbound/libunbound.c +++ b/usr.sbin/unbound/libunbound/libunbound.c @@ -363,6 +363,26 @@ ub_ctx_add_ta_file(struct ub_ctx* ctx, const char* fname) return UB_NOERROR; } +int ub_ctx_add_ta_autr(struct ub_ctx* ctx, const char* fname) +{ + char* dup = strdup(fname); + if(!dup) return UB_NOMEM; + lock_basic_lock(&ctx->cfglock); + if(ctx->finalized) { + lock_basic_unlock(&ctx->cfglock); + free(dup); + return UB_AFTERFINAL; + } + if(!cfg_strlist_insert(&ctx->env->cfg->auto_trust_anchor_file_list, + dup)) { + lock_basic_unlock(&ctx->cfglock); + free(dup); + return UB_NOMEM; + } + lock_basic_unlock(&ctx->cfglock); + return UB_NOERROR; +} + int ub_ctx_trustedkeys(struct ub_ctx* ctx, const char* fname) { @@ -959,7 +979,7 @@ ub_ctx_resolvconf(struct ub_ctx* ctx, const char* fname) parse++; addr = parse; /* skip [0-9a-fA-F.:]*, i.e. IP4 and IP6 address */ - while(isxdigit(*parse) || *parse=='.' || *parse==':') + while(isxdigit((unsigned char)*parse) || *parse=='.' || *parse==':') parse++; /* terminate after the address, remove newline */ *parse = 0; @@ -1031,7 +1051,7 @@ ub_ctx_hosts(struct ub_ctx* ctx, const char* fname) /* format: <addr> spaces <name> spaces <name> ... */ addr = parse; /* skip addr */ - while(isxdigit(*parse) || *parse == '.' || *parse == ':') + while(isxdigit((unsigned char)*parse) || *parse == '.' || *parse == ':') parse++; if(*parse == '\n' || *parse == 0) continue; diff --git a/usr.sbin/unbound/libunbound/libworker.h b/usr.sbin/unbound/libunbound/libworker.h index 134cc507014..0103b5d8898 100644 --- a/usr.sbin/unbound/libunbound/libworker.h +++ b/usr.sbin/unbound/libunbound/libworker.h @@ -41,8 +41,8 @@ * and if in the background continues until exit, if in the foreground * returns from the procedure when done. */ -#ifndef LIBUNBOUND_WORKER_H -#define LIBUNBOUND_WORKER_H +#ifndef LIBUNBOUND_LIBWORKER_H +#define LIBUNBOUND_LIBWORKER_H #include "util/data/packed_rrset.h" struct ub_ctx; struct ub_result; @@ -136,56 +136,6 @@ void libworker_delete_event(struct libworker* w); /** cleanup the cache to remove all rrset IDs from it, arg is libworker */ void libworker_alloc_cleanup(void* arg); -/** - * Worker service routine to send serviced queries to authoritative servers. - * @param qname: query name. (host order) - * @param qnamelen: length in bytes of qname, including trailing 0. - * @param qtype: query type. (host order) - * @param qclass: query class. (host order) - * @param flags: host order flags word, with opcode and CD bit. - * @param dnssec: if set, EDNS record will have DO bit set. - * @param want_dnssec: signatures needed. - * @param addr: where to. - * @param addrlen: length of addr. - * @param zone: delegation point name. - * @param zonelen: length of zone name wireformat dname. - * @param q: wich query state to reactivate upon return. - * @return: false on failure (memory or socket related). no query was - * sent. - */ -struct outbound_entry* libworker_send_query(uint8_t* qname, size_t qnamelen, - uint16_t qtype, uint16_t qclass, uint16_t flags, int dnssec, - int want_dnssec, struct sockaddr_storage* addr, socklen_t addrlen, - uint8_t* zone, size_t zonelen, struct module_qstate* q); - -/** process incoming replies from the network */ -int libworker_handle_reply(struct comm_point* c, void* arg, int error, - struct comm_reply* reply_info); - -/** process incoming serviced query replies from the network */ -int libworker_handle_service_reply(struct comm_point* c, void* arg, int error, - struct comm_reply* reply_info); - -/** handle control command coming into server */ -void libworker_handle_control_cmd(struct tube* tube, uint8_t* msg, size_t len, - int err, void* arg); - -/** handle opportunity to write result back */ -void libworker_handle_result_write(struct tube* tube, uint8_t* msg, size_t len, - int err, void* arg); - -/** mesh callback with fg results */ -void libworker_fg_done_cb(void* arg, int rcode, struct sldns_buffer* buf, - enum sec_status s, char* why_bogus); - -/** mesh callback with bg results */ -void libworker_bg_done_cb(void* arg, int rcode, struct sldns_buffer* buf, - enum sec_status s, char* why_bogus); - -/** mesh callback with event results */ -void libworker_event_done_cb(void* arg, int rcode, struct sldns_buffer* buf, - enum sec_status s, char* why_bogus); - /** * fill result from parsed message, on error fills servfail * @param res: is clear at start, filled in at end. @@ -198,4 +148,4 @@ void libworker_event_done_cb(void* arg, int rcode, struct sldns_buffer* buf, void libworker_enter_result(struct ub_result* res, struct sldns_buffer* buf, struct regional* temp, enum sec_status msg_security); -#endif /* LIBUNBOUND_WORKER_H */ +#endif /* LIBUNBOUND_LIBWORKER_H */ diff --git a/usr.sbin/unbound/libunbound/ubsyms.def b/usr.sbin/unbound/libunbound/ubsyms.def index 866c1764cf7..ff3d9587b7c 100644 --- a/usr.sbin/unbound/libunbound/ubsyms.def +++ b/usr.sbin/unbound/libunbound/ubsyms.def @@ -8,6 +8,7 @@ ub_ctx_set_fwd ub_ctx_resolvconf ub_ctx_hosts ub_ctx_add_ta +ub_ctx_add_ta_autr ub_ctx_add_ta_file ub_ctx_trustedkeys ub_ctx_debugout diff --git a/usr.sbin/unbound/libunbound/unbound.h b/usr.sbin/unbound/libunbound/unbound.h index 86bd3bfb444..567f48271e3 100644 --- a/usr.sbin/unbound/libunbound/unbound.h +++ b/usr.sbin/unbound/libunbound/unbound.h @@ -357,6 +357,21 @@ int ub_ctx_add_ta(struct ub_ctx* ctx, const char* ta); int ub_ctx_add_ta_file(struct ub_ctx* ctx, const char* fname); /** + * Add trust anchor to the give context that is tracked with RFC5011 + * automated trust anchor maintenance. The file is written to when the + * trust anchor is changed. + * Pass the name of a file that was output from eg. unbound-anchor, + * or you can start it by providing a trusted DNSKEY or DS record on one + * line in the file. + * @param ctx: context. + * At this time it is only possible to add trusted keys before the + * first resolve is done. + * @param fname: filename of file with trust anchor. + * @return 0 if OK, else error. + */ +int ub_ctx_add_ta_autr(struct ub_ctx* ctx, const char* fname); + +/** * Add trust anchors to the given context. * Pass the name of a bind-style config file with trusted-keys{}. * @param ctx: context. @@ -508,7 +523,7 @@ void ub_resolve_free(struct ub_result* result); /** * Convert error value to a human readable string. - * @param err: error code from one of the ub_val* functions. + * @param err: error code from one of the libunbound functions. * @return pointer to constant text string, zero terminated. */ const char* ub_strerror(int err); diff --git a/usr.sbin/unbound/libunbound/worker.h b/usr.sbin/unbound/libunbound/worker.h new file mode 100644 index 00000000000..824012a0184 --- /dev/null +++ b/usr.sbin/unbound/libunbound/worker.h @@ -0,0 +1,179 @@ +/* + * libunbound/worker.h - prototypes for worker methods. + * + * Copyright (c) 2007, NLnet Labs. All rights reserved. + * + * This software is open source. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of the NLNET LABS nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \file + * + * This file declares the methods any worker has to implement. + */ + +#ifndef LIBUNBOUND_WORKER_H +#define LIBUNBOUND_WORKER_H + +#include "ldns/sbuffer.h" +#include "util/data/packed_rrset.h" /* for enum sec_status */ +struct comm_reply; +struct comm_point; +struct module_qstate; +struct tube; + +/** + * Worker service routine to send serviced queries to authoritative servers. + * @param qname: query name. (host order) + * @param qnamelen: length in bytes of qname, including trailing 0. + * @param qtype: query type. (host order) + * @param qclass: query class. (host order) + * @param flags: host order flags word, with opcode and CD bit. + * @param dnssec: if set, EDNS record will have DO bit set. + * @param want_dnssec: signatures needed. + * @param nocaps: ignore capsforid(if in config), do not perturb qname. + * @param addr: where to. + * @param addrlen: length of addr. + * @param zone: delegation point name. + * @param zonelen: length of zone name wireformat dname. + * @param q: wich query state to reactivate upon return. + * @return: false on failure (memory or socket related). no query was + * sent. + */ +struct outbound_entry* libworker_send_query(uint8_t* qname, size_t qnamelen, + uint16_t qtype, uint16_t qclass, uint16_t flags, int dnssec, + int want_dnssec, int nocaps, struct sockaddr_storage* addr, + socklen_t addrlen, uint8_t* zone, size_t zonelen, + struct module_qstate* q); + +/** process incoming replies from the network */ +int libworker_handle_reply(struct comm_point* c, void* arg, int error, + struct comm_reply* reply_info); + +/** process incoming serviced query replies from the network */ +int libworker_handle_service_reply(struct comm_point* c, void* arg, int error, + struct comm_reply* reply_info); + +/** handle control command coming into server */ +void libworker_handle_control_cmd(struct tube* tube, uint8_t* msg, size_t len, + int err, void* arg); + +/** mesh callback with fg results */ +void libworker_fg_done_cb(void* arg, int rcode, sldns_buffer* buf, + enum sec_status s, char* why_bogus); + +/** mesh callback with bg results */ +void libworker_bg_done_cb(void* arg, int rcode, sldns_buffer* buf, + enum sec_status s, char* why_bogus); + +/** mesh callback with event results */ +void libworker_event_done_cb(void* arg, int rcode, struct sldns_buffer* buf, + enum sec_status s, char* why_bogus); + +/** + * Worker signal handler function. User argument is the worker itself. + * @param sig: signal number. + * @param arg: the worker (main worker) that handles signals. + */ +void worker_sighandler(int sig, void* arg); + +/** + * Worker service routine to send serviced queries to authoritative servers. + * @param qname: query name. (host order) + * @param qnamelen: length in bytes of qname, including trailing 0. + * @param qtype: query type. (host order) + * @param qclass: query class. (host order) + * @param flags: host order flags word, with opcode and CD bit. + * @param dnssec: if set, EDNS record will have DO bit set. + * @param want_dnssec: signatures needed. + * @param nocaps: ignore capsforid(if in config), do not perturb qname. + * @param addr: where to. + * @param addrlen: length of addr. + * @param zone: wireformat dname of the zone. + * @param zonelen: length of zone name. + * @param q: wich query state to reactivate upon return. + * @return: false on failure (memory or socket related). no query was + * sent. + */ +struct outbound_entry* worker_send_query(uint8_t* qname, size_t qnamelen, + uint16_t qtype, uint16_t qclass, uint16_t flags, int dnssec, + int want_dnssec, int nocaps, struct sockaddr_storage* addr, + socklen_t addrlen, uint8_t* zone, size_t zonelen, + struct module_qstate* q); + +/** + * process control messages from the main thread. Frees the control + * command message. + * @param tube: tube control message came on. + * @param msg: message contents. Is freed. + * @param len: length of message. + * @param error: if error (NETEVENT_*) happened. + * @param arg: user argument + */ +void worker_handle_control_cmd(struct tube* tube, uint8_t* msg, size_t len, + int error, void* arg); + +/** handles callbacks from listening event interface */ +int worker_handle_request(struct comm_point* c, void* arg, int error, + struct comm_reply* repinfo); + +/** process incoming replies from the network */ +int worker_handle_reply(struct comm_point* c, void* arg, int error, + struct comm_reply* reply_info); + +/** process incoming serviced query replies from the network */ +int worker_handle_service_reply(struct comm_point* c, void* arg, int error, + struct comm_reply* reply_info); + +/** cleanup the cache to remove all rrset IDs from it, arg is worker */ +void worker_alloc_cleanup(void* arg); + +/** statistics timer callback handler */ +void worker_stat_timer_cb(void* arg); + +/** probe timer callback handler */ +void worker_probe_timer_cb(void* arg); + +/** start accept callback handler */ +void worker_start_accept(void* arg); + +/** stop accept callback handler */ +void worker_stop_accept(void* arg); + +/** handle remote control accept callbacks */ +int remote_accept_callback(struct comm_point*, void*, int, struct comm_reply*); + +/** handle remote control data callbacks */ +int remote_control_callback(struct comm_point*, void*, int, struct comm_reply*); + +/** routine to printout option values over SSL */ +void remote_get_opt_ssl(char* line, void* arg); + +#endif /* LIBUNBOUND_WORKER_H */ diff --git a/usr.sbin/unbound/services/localzone.c b/usr.sbin/unbound/services/localzone.c index ac889799b43..d285a127cbb 100644 --- a/usr.sbin/unbound/services/localzone.c +++ b/usr.sbin/unbound/services/localzone.c @@ -594,6 +594,8 @@ lz_enter_defaults(struct local_zones* zones, struct config_file* cfg) /* this list of zones is from RFC 6303 */ + /* block localhost level zones, first, later the LAN zones */ + /* localhost. zone */ if(!lz_exists(zones, "localhost.") && !lz_nodefault(cfg, "localhost.")) { @@ -650,6 +652,14 @@ lz_enter_defaults(struct local_zones* zones, struct config_file* cfg) } lock_rw_unlock(&z->lock); } + + /* if unblock lan-zones, then do not add the zones below. + * we do add the zones above, about 127.0.0.1, because localhost is + * not on the lan. */ + if(cfg->unblock_lan_zones) + return 1; + + /* block LAN level zones */ if ( !add_as112_default(zones, cfg, "10.in-addr.arpa.") || !add_as112_default(zones, cfg, "16.172.in-addr.arpa.") || !add_as112_default(zones, cfg, "17.172.in-addr.arpa.") || @@ -669,6 +679,70 @@ lz_enter_defaults(struct local_zones* zones, struct config_file* cfg) !add_as112_default(zones, cfg, "31.172.in-addr.arpa.") || !add_as112_default(zones, cfg, "168.192.in-addr.arpa.") || !add_as112_default(zones, cfg, "0.in-addr.arpa.") || + !add_as112_default(zones, cfg, "64.100.in-addr.arpa.") || + !add_as112_default(zones, cfg, "65.100.in-addr.arpa.") || + !add_as112_default(zones, cfg, "66.100.in-addr.arpa.") || + !add_as112_default(zones, cfg, "67.100.in-addr.arpa.") || + !add_as112_default(zones, cfg, "68.100.in-addr.arpa.") || + !add_as112_default(zones, cfg, "69.100.in-addr.arpa.") || + !add_as112_default(zones, cfg, "70.100.in-addr.arpa.") || + !add_as112_default(zones, cfg, "71.100.in-addr.arpa.") || + !add_as112_default(zones, cfg, "72.100.in-addr.arpa.") || + !add_as112_default(zones, cfg, "73.100.in-addr.arpa.") || + !add_as112_default(zones, cfg, "74.100.in-addr.arpa.") || + !add_as112_default(zones, cfg, "75.100.in-addr.arpa.") || + !add_as112_default(zones, cfg, "76.100.in-addr.arpa.") || + !add_as112_default(zones, cfg, "77.100.in-addr.arpa.") || + !add_as112_default(zones, cfg, "78.100.in-addr.arpa.") || + !add_as112_default(zones, cfg, "79.100.in-addr.arpa.") || + !add_as112_default(zones, cfg, "80.100.in-addr.arpa.") || + !add_as112_default(zones, cfg, "81.100.in-addr.arpa.") || + !add_as112_default(zones, cfg, "82.100.in-addr.arpa.") || + !add_as112_default(zones, cfg, "83.100.in-addr.arpa.") || + !add_as112_default(zones, cfg, "84.100.in-addr.arpa.") || + !add_as112_default(zones, cfg, "85.100.in-addr.arpa.") || + !add_as112_default(zones, cfg, "86.100.in-addr.arpa.") || + !add_as112_default(zones, cfg, "87.100.in-addr.arpa.") || + !add_as112_default(zones, cfg, "88.100.in-addr.arpa.") || + !add_as112_default(zones, cfg, "89.100.in-addr.arpa.") || + !add_as112_default(zones, cfg, "90.100.in-addr.arpa.") || + !add_as112_default(zones, cfg, "91.100.in-addr.arpa.") || + !add_as112_default(zones, cfg, "92.100.in-addr.arpa.") || + !add_as112_default(zones, cfg, "93.100.in-addr.arpa.") || + !add_as112_default(zones, cfg, "94.100.in-addr.arpa.") || + !add_as112_default(zones, cfg, "95.100.in-addr.arpa.") || + !add_as112_default(zones, cfg, "96.100.in-addr.arpa.") || + !add_as112_default(zones, cfg, "97.100.in-addr.arpa.") || + !add_as112_default(zones, cfg, "98.100.in-addr.arpa.") || + !add_as112_default(zones, cfg, "99.100.in-addr.arpa.") || + !add_as112_default(zones, cfg, "100.100.in-addr.arpa.") || + !add_as112_default(zones, cfg, "101.100.in-addr.arpa.") || + !add_as112_default(zones, cfg, "102.100.in-addr.arpa.") || + !add_as112_default(zones, cfg, "103.100.in-addr.arpa.") || + !add_as112_default(zones, cfg, "104.100.in-addr.arpa.") || + !add_as112_default(zones, cfg, "105.100.in-addr.arpa.") || + !add_as112_default(zones, cfg, "106.100.in-addr.arpa.") || + !add_as112_default(zones, cfg, "107.100.in-addr.arpa.") || + !add_as112_default(zones, cfg, "108.100.in-addr.arpa.") || + !add_as112_default(zones, cfg, "109.100.in-addr.arpa.") || + !add_as112_default(zones, cfg, "110.100.in-addr.arpa.") || + !add_as112_default(zones, cfg, "111.100.in-addr.arpa.") || + !add_as112_default(zones, cfg, "112.100.in-addr.arpa.") || + !add_as112_default(zones, cfg, "113.100.in-addr.arpa.") || + !add_as112_default(zones, cfg, "114.100.in-addr.arpa.") || + !add_as112_default(zones, cfg, "115.100.in-addr.arpa.") || + !add_as112_default(zones, cfg, "116.100.in-addr.arpa.") || + !add_as112_default(zones, cfg, "117.100.in-addr.arpa.") || + !add_as112_default(zones, cfg, "118.100.in-addr.arpa.") || + !add_as112_default(zones, cfg, "119.100.in-addr.arpa.") || + !add_as112_default(zones, cfg, "120.100.in-addr.arpa.") || + !add_as112_default(zones, cfg, "121.100.in-addr.arpa.") || + !add_as112_default(zones, cfg, "122.100.in-addr.arpa.") || + !add_as112_default(zones, cfg, "123.100.in-addr.arpa.") || + !add_as112_default(zones, cfg, "124.100.in-addr.arpa.") || + !add_as112_default(zones, cfg, "125.100.in-addr.arpa.") || + !add_as112_default(zones, cfg, "126.100.in-addr.arpa.") || + !add_as112_default(zones, cfg, "127.100.in-addr.arpa.") || !add_as112_default(zones, cfg, "254.169.in-addr.arpa.") || !add_as112_default(zones, cfg, "2.0.192.in-addr.arpa.") || !add_as112_default(zones, cfg, "100.51.198.in-addr.arpa.") || diff --git a/usr.sbin/unbound/services/modstack.c b/usr.sbin/unbound/services/modstack.c index 56515a61f36..49bb2fd15ad 100644 --- a/usr.sbin/unbound/services/modstack.c +++ b/usr.sbin/unbound/services/modstack.c @@ -43,6 +43,7 @@ #include "services/modstack.h" #include "util/module.h" #include "util/fptr_wlist.h" +#include "dns64/dns64.h" #include "iterator/iterator.h" #include "validator/validator.h" @@ -59,12 +60,12 @@ count_modules(const char* s) return 0; while(*s) { /* skip whitespace */ - while(*s && isspace((int)*s)) + while(*s && isspace((unsigned char)*s)) s++; - if(*s && !isspace((int)*s)) { + if(*s && !isspace((unsigned char)*s)) { /* skip identifier */ num++; - while(*s && !isspace((int)*s)) + while(*s && !isspace((unsigned char)*s)) s++; } } @@ -116,6 +117,7 @@ module_list_avail(void) { /* these are the modules available */ static const char* names[] = { + "dns64", #ifdef WITH_PYTHONMODULE "python", #endif @@ -133,6 +135,7 @@ static fbgetfunctype* module_funcs_avail(void) { static struct module_func_block* (*fb[])(void) = { + &dns64_get_funcblock, #ifdef WITH_PYTHONMODULE &pythonmod_get_funcblock, #endif @@ -149,7 +152,7 @@ module_func_block* module_factory(const char** str) const char* s = *str; const char** names = module_list_avail(); fbgetfunctype* fb = module_funcs_avail(); - while(*s && isspace((int)*s)) + while(*s && isspace((unsigned char)*s)) s++; while(names[i]) { if(strncmp(names[i], s, strlen(names[i])) == 0) { diff --git a/usr.sbin/unbound/services/outside_network.c b/usr.sbin/unbound/services/outside_network.c index fedbd0fa8c8..5bb52ff9fe4 100644 --- a/usr.sbin/unbound/services/outside_network.c +++ b/usr.sbin/unbound/services/outside_network.c @@ -58,6 +58,7 @@ #include "util/random.h" #include "util/fptr_wlist.h" #include "ldns/sbuffer.h" +#include "dnstap/dnstap.h" #ifdef HAVE_OPENSSL_SSL_H #include <openssl/ssl.h> #endif @@ -75,11 +76,14 @@ #define OUTBOUND_UDP_RETRY 1 /** initiate TCP transaction for serviced query */ -static void serviced_tcp_initiate(struct outside_network* outnet, - struct serviced_query* sq, sldns_buffer* buff); +static void serviced_tcp_initiate(struct serviced_query* sq, sldns_buffer* buff); /** with a fd available, randomize and send UDP */ -static int randomize_and_send_udp(struct outside_network* outnet, - struct pending* pend, sldns_buffer* packet, int timeout); +static int randomize_and_send_udp(struct pending* pend, sldns_buffer* packet, + int timeout); + +/** remove waiting tcp from the outnet waiting list */ +static void waiting_list_remove(struct outside_network* outnet, + struct waiting_tcp* w); int pending_cmp(const void* key1, const void* key2) @@ -210,12 +214,12 @@ outnet_tcp_take_into_use(struct waiting_tcp* w, uint8_t* pkt, size_t pkt_len) s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); if(s == -1) { #ifndef USE_WINSOCK - log_err("outgoing tcp: socket: %s", strerror(errno)); + log_err_addr("outgoing tcp: socket", strerror(errno), + &w->addr, w->addrlen); #else - log_err("outgoing tcp: socket: %s", - wsa_strerror(WSAGetLastError())); + log_err_addr("outgoing tcp: socket", + wsa_strerror(WSAGetLastError()), &w->addr, w->addrlen); #endif - log_addr(0, "failed address", &w->addr, w->addrlen); return 0; } if(!pick_outgoing_tcp(w, s)) @@ -231,15 +235,14 @@ outnet_tcp_take_into_use(struct waiting_tcp* w, uint8_t* pkt, size_t pkt_len) #endif if(tcp_connect_errno_needs_log( (struct sockaddr*)&w->addr, w->addrlen)) - log_err("outgoing tcp: connect: %s", - strerror(errno)); + log_err_addr("outgoing tcp: connect", + strerror(errno), &w->addr, w->addrlen); close(s); #else /* USE_WINSOCK */ if(WSAGetLastError() != WSAEINPROGRESS && WSAGetLastError() != WSAEWOULDBLOCK) { closesocket(s); #endif - log_addr(0, "failed address", &w->addr, w->addrlen); return 0; } } @@ -258,6 +261,7 @@ outnet_tcp_take_into_use(struct waiting_tcp* w, uint8_t* pkt, size_t pkt_len) w->pkt = NULL; w->next_waiting = (void*)pend; pend->id = LDNS_ID_WIRE(pkt); + w->outnet->num_tcp_outgoing++; w->outnet->tcp_free = pend->next_free; pend->next_free = NULL; pend->query = w; @@ -378,7 +382,7 @@ outnet_send_wait_udp(struct outside_network* outnet) free(pend->pkt); /* freeing now makes get_mem correct */ pend->pkt = NULL; pend->pkt_len = 0; - if(!randomize_and_send_udp(outnet, pend, outnet->udp_buff, + if(!randomize_and_send_udp(pend, outnet->udp_buff, pend->timeout)) { /* callback error on pending */ if(pend->cb) { @@ -588,7 +592,7 @@ outside_network_create(struct comm_base *base, size_t bufsize, struct ub_randstate* rnd, int use_caps_for_id, int* availports, int numavailports, size_t unwanted_threshold, void (*unwanted_action)(void*), void* unwanted_param, int do_udp, - void* sslctx, int delayclose) + void* sslctx, int delayclose, struct dt_env* dtenv) { struct outside_network* outnet = (struct outside_network*) calloc(1, sizeof(struct outside_network)); @@ -600,9 +604,15 @@ outside_network_create(struct comm_base *base, size_t bufsize, comm_base_timept(base, &outnet->now_secs, &outnet->now_tv); outnet->base = base; outnet->num_tcp = num_tcp; + outnet->num_tcp_outgoing = 0; outnet->infra = infra; outnet->rnd = rnd; outnet->sslctx = sslctx; +#ifdef USE_DNSTAP + outnet->dtenv = dtenv; +#else + (void)dtenv; +#endif outnet->svcd_overhead = 0; outnet->want_to_quit = 0; outnet->unwanted_threshold = unwanted_threshold; @@ -991,10 +1001,10 @@ select_ifport(struct outside_network* outnet, struct pending* pend, } static int -randomize_and_send_udp(struct outside_network* outnet, struct pending* pend, - sldns_buffer* packet, int timeout) +randomize_and_send_udp(struct pending* pend, sldns_buffer* packet, int timeout) { struct timeval tv; + struct outside_network* outnet = pend->sq->outnet; /* select id */ if(!select_id(outnet, pend, packet)) { @@ -1027,30 +1037,38 @@ randomize_and_send_udp(struct outside_network* outnet, struct pending* pend, tv.tv_usec = (timeout%1000)*1000; #endif comm_timer_set(pend->timer, &tv); + +#ifdef USE_DNSTAP + if(outnet->dtenv && + (outnet->dtenv->log_resolver_query_messages || + outnet->dtenv->log_forwarder_query_messages)) + dt_msg_send_outside_query(outnet->dtenv, &pend->addr, comm_udp, + pend->sq->zone, pend->sq->zonelen, packet); +#endif return 1; } struct pending* -pending_udp_query(struct outside_network* outnet, sldns_buffer* packet, - struct sockaddr_storage* addr, socklen_t addrlen, int timeout, - comm_point_callback_t* cb, void* cb_arg) +pending_udp_query(struct serviced_query* sq, struct sldns_buffer* packet, + int timeout, comm_point_callback_t* cb, void* cb_arg) { struct pending* pend = (struct pending*)calloc(1, sizeof(*pend)); if(!pend) return NULL; - pend->outnet = outnet; - pend->addrlen = addrlen; - memmove(&pend->addr, addr, addrlen); + pend->outnet = sq->outnet; + pend->sq = sq; + pend->addrlen = sq->addrlen; + memmove(&pend->addr, &sq->addr, sq->addrlen); pend->cb = cb; pend->cb_arg = cb_arg; pend->node.key = pend; - pend->timer = comm_timer_create(outnet->base, pending_udp_timer_cb, + pend->timer = comm_timer_create(sq->outnet->base, pending_udp_timer_cb, pend); if(!pend->timer) { free(pend); return NULL; } - if(outnet->unused_fds == NULL) { + if(sq->outnet->unused_fds == NULL) { /* no unused fd, cannot create a new port (randomly) */ verbose(VERB_ALGO, "no fds available, udp query waiting"); pend->timeout = timeout; @@ -1063,15 +1081,15 @@ pending_udp_query(struct outside_network* outnet, sldns_buffer* packet, return NULL; } /* put at end of waiting list */ - if(outnet->udp_wait_last) - outnet->udp_wait_last->next_waiting = pend; + if(sq->outnet->udp_wait_last) + sq->outnet->udp_wait_last->next_waiting = pend; else - outnet->udp_wait_first = pend; - outnet->udp_wait_last = pend; + sq->outnet->udp_wait_first = pend; + sq->outnet->udp_wait_last = pend; return pend; } - if(!randomize_and_send_udp(outnet, pend, packet, timeout)) { - pending_delete(outnet, pend); + if(!randomize_and_send_udp(pend, packet, timeout)) { + pending_delete(sq->outnet, pend); return NULL; } return pend; @@ -1086,17 +1104,7 @@ outnet_tcptimer(void* arg) void* cb_arg; if(w->pkt) { /* it is on the waiting list */ - struct waiting_tcp* p=outnet->tcp_wait_first, *prev=NULL; - while(p) { - if(p == w) { - if(prev) prev->next_waiting = w->next_waiting; - else outnet->tcp_wait_first=w->next_waiting; - outnet->tcp_wait_last = prev; - break; - } - prev = p; - p=p->next_waiting; - } + waiting_list_remove(outnet, w); } else { /* it was in use */ struct pending_tcp* pend=(struct pending_tcp*)w->next_waiting; @@ -1113,12 +1121,11 @@ outnet_tcptimer(void* arg) use_free_buffer(outnet); } -struct waiting_tcp* -pending_tcp_query(struct outside_network* outnet, sldns_buffer* packet, - struct sockaddr_storage* addr, socklen_t addrlen, int timeout, - comm_point_callback_t* callback, void* callback_arg, int ssl_upstream) +struct waiting_tcp* +pending_tcp_query(struct serviced_query* sq, sldns_buffer* packet, + int timeout, comm_point_callback_t* callback, void* callback_arg) { - struct pending_tcp* pend = outnet->tcp_free; + struct pending_tcp* pend = sq->outnet->tcp_free; struct waiting_tcp* w; struct timeval tv; uint16_t id; @@ -1128,20 +1135,20 @@ pending_tcp_query(struct outside_network* outnet, sldns_buffer* packet, if(!w) { return NULL; } - if(!(w->timer = comm_timer_create(outnet->base, outnet_tcptimer, w))) { + if(!(w->timer = comm_timer_create(sq->outnet->base, outnet_tcptimer, w))) { free(w); return NULL; } w->pkt = NULL; w->pkt_len = 0; - id = ((unsigned)ub_random(outnet->rnd)>>8) & 0xffff; + id = ((unsigned)ub_random(sq->outnet->rnd)>>8) & 0xffff; LDNS_ID_SET(sldns_buffer_begin(packet), id); - memcpy(&w->addr, addr, addrlen); - w->addrlen = addrlen; - w->outnet = outnet; + memcpy(&w->addr, &sq->addr, sq->addrlen); + w->addrlen = sq->addrlen; + w->outnet = sq->outnet; w->cb = callback; w->cb_arg = callback_arg; - w->ssl_upstream = ssl_upstream; + w->ssl_upstream = sq->ssl_upstream; #ifndef S_SPLINT_S tv.tv_sec = timeout; tv.tv_usec = 0; @@ -1154,16 +1161,23 @@ pending_tcp_query(struct outside_network* outnet, sldns_buffer* packet, waiting_tcp_delete(w); return NULL; } +#ifdef USE_DNSTAP + if(sq->outnet->dtenv && + (sq->outnet->dtenv->log_resolver_query_messages || + sq->outnet->dtenv->log_forwarder_query_messages)) + dt_msg_send_outside_query(sq->outnet->dtenv, &sq->addr, + comm_tcp, sq->zone, sq->zonelen, packet); +#endif } else { /* queue up */ w->pkt = (uint8_t*)w + sizeof(struct waiting_tcp); w->pkt_len = sldns_buffer_limit(packet); memmove(w->pkt, sldns_buffer_begin(packet), w->pkt_len); w->next_waiting = NULL; - if(outnet->tcp_wait_last) - outnet->tcp_wait_last->next_waiting = w; - else outnet->tcp_wait_first = w; - outnet->tcp_wait_last = w; + if(sq->outnet->tcp_wait_last) + sq->outnet->tcp_wait_last->next_waiting = w; + else sq->outnet->tcp_wait_first = w; + sq->outnet->tcp_wait_last = w; } return w; } @@ -1205,7 +1219,7 @@ lookup_serviced(struct outside_network* outnet, sldns_buffer* buff, int dnssec, /** Create new serviced entry */ static struct serviced_query* serviced_create(struct outside_network* outnet, sldns_buffer* buff, int dnssec, - int want_dnssec, int tcp_upstream, int ssl_upstream, + int want_dnssec, int nocaps, int tcp_upstream, int ssl_upstream, struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* zone, size_t zonelen, int qtype) { @@ -1232,6 +1246,7 @@ serviced_create(struct outside_network* outnet, sldns_buffer* buff, int dnssec, sq->qtype = qtype; sq->dnssec = dnssec; sq->want_dnssec = want_dnssec; + sq->nocaps = nocaps; sq->tcp_upstream = tcp_upstream; sq->ssl_upstream = ssl_upstream; memcpy(&sq->addr, addr, addrlen); @@ -1319,16 +1334,16 @@ serviced_perturb_qname(struct ub_randstate* rnd, uint8_t* qbuf, size_t len) while(lablen) { while(lablen--) { /* only perturb A-Z, a-z */ - if(isalpha((int)*d)) { + if(isalpha((unsigned char)*d)) { /* get a random bit */ if(bits == 0) { random = ub_random(rnd); bits = 30; } if(random & 0x1) { - *d = (uint8_t)toupper((int)*d); + *d = (uint8_t)toupper((unsigned char)*d); } else { - *d = (uint8_t)tolower((int)*d); + *d = (uint8_t)tolower((unsigned char)*d); } random >>= 1; bits--; @@ -1349,7 +1364,7 @@ static void serviced_encode(struct serviced_query* sq, sldns_buffer* buff, int with_edns) { /* if we are using 0x20 bits for ID randomness, perturb them */ - if(sq->outnet->use_caps_for_id) { + if(sq->outnet->use_caps_for_id && !sq->nocaps) { serviced_perturb_qname(sq->outnet->rnd, sq->qbuf, sq->qbuflen); } /* generate query */ @@ -1424,8 +1439,8 @@ serviced_udp_send(struct serviced_query* sq, sldns_buffer* buff) sq->last_sent_time = *sq->outnet->now_tv; sq->edns_lame_known = (int)edns_lame_known; verbose(VERB_ALGO, "serviced query UDP timeout=%d msec", rtt); - sq->pending = pending_udp_query(sq->outnet, buff, &sq->addr, - sq->addrlen, rtt, serviced_udp_callback, sq); + sq->pending = pending_udp_query(sq, buff, rtt, + serviced_udp_callback, sq); if(!sq->pending) return 0; return 1; @@ -1574,13 +1589,21 @@ serviced_tcp_callback(struct comm_point* c, void* arg, int error, if(error==NETEVENT_NOERROR) infra_update_tcp_works(sq->outnet->infra, &sq->addr, sq->addrlen, sq->zone, sq->zonelen); +#ifdef USE_DNSTAP + if(sq->outnet->dtenv && + (sq->outnet->dtenv->log_resolver_response_messages || + sq->outnet->dtenv->log_forwarder_response_messages)) + dt_msg_send_outside_response(sq->outnet->dtenv, &sq->addr, + c->type, sq->zone, sq->zonelen, sq->qbuf, sq->qbuflen, + &sq->last_sent_time, sq->outnet->now_tv, c->buffer); +#endif if(error==NETEVENT_NOERROR && sq->status == serviced_query_TCP_EDNS && (LDNS_RCODE_WIRE(sldns_buffer_begin(c->buffer)) == LDNS_RCODE_FORMERR || LDNS_RCODE_WIRE(sldns_buffer_begin( c->buffer)) == LDNS_RCODE_NOTIMPL) ) { /* attempt to fallback to nonEDNS */ sq->status = serviced_query_TCP_EDNS_fallback; - serviced_tcp_initiate(sq->outnet, sq, c->buffer); + serviced_tcp_initiate(sq, c->buffer); return 0; } else if(error==NETEVENT_NOERROR && sq->status == serviced_query_TCP_EDNS_fallback && @@ -1632,16 +1655,14 @@ serviced_tcp_callback(struct comm_point* c, void* arg, int error, } static void -serviced_tcp_initiate(struct outside_network* outnet, - struct serviced_query* sq, sldns_buffer* buff) +serviced_tcp_initiate(struct serviced_query* sq, sldns_buffer* buff) { verbose(VERB_ALGO, "initiate TCP query %s", sq->status==serviced_query_TCP_EDNS?"EDNS":""); serviced_encode(sq, buff, sq->status == serviced_query_TCP_EDNS); sq->last_sent_time = *sq->outnet->now_tv; - sq->pending = pending_tcp_query(outnet, buff, &sq->addr, - sq->addrlen, TCP_AUTH_QUERY_TIMEOUT, serviced_tcp_callback, - sq, sq->ssl_upstream); + sq->pending = pending_tcp_query(sq, buff, TCP_AUTH_QUERY_TIMEOUT, + serviced_tcp_callback, sq); if(!sq->pending) { /* delete from tree so that a retry by above layer does not * clash with this entry */ @@ -1665,9 +1686,8 @@ serviced_tcp_send(struct serviced_query* sq, sldns_buffer* buff) else sq->status = serviced_query_TCP; serviced_encode(sq, buff, sq->status == serviced_query_TCP_EDNS); sq->last_sent_time = *sq->outnet->now_tv; - sq->pending = pending_tcp_query(sq->outnet, buff, &sq->addr, - sq->addrlen, TCP_AUTH_QUERY_TIMEOUT, serviced_tcp_callback, - sq, sq->ssl_upstream); + sq->pending = pending_tcp_query(sq, buff, TCP_AUTH_QUERY_TIMEOUT, + serviced_tcp_callback, sq); return sq->pending != NULL; } @@ -1728,6 +1748,14 @@ serviced_udp_callback(struct comm_point* c, void* arg, int error, serviced_callbacks(sq, error, c, rep); return 0; } +#ifdef USE_DNSTAP + if(outnet->dtenv && + (outnet->dtenv->log_resolver_response_messages || + outnet->dtenv->log_forwarder_response_messages)) + dt_msg_send_outside_response(outnet->dtenv, &sq->addr, c->type, + sq->zone, sq->zonelen, sq->qbuf, sq->qbuflen, + &sq->last_sent_time, sq->outnet->now_tv, c->buffer); +#endif if(!fallback_tcp) { if( (sq->status == serviced_query_UDP_EDNS ||sq->status == serviced_query_UDP_EDNS_FRAG) @@ -1816,7 +1844,7 @@ serviced_udp_callback(struct comm_point* c, void* arg, int error, /* if we have unfinished EDNS_fallback, start again */ sq->status = serviced_query_TCP_EDNS; else sq->status = serviced_query_TCP; - serviced_tcp_initiate(outnet, sq, c->buffer); + serviced_tcp_initiate(sq, c->buffer); return 0; } /* yay! an answer */ @@ -1827,10 +1855,11 @@ serviced_udp_callback(struct comm_point* c, void* arg, int error, struct serviced_query* outnet_serviced_query(struct outside_network* outnet, uint8_t* qname, size_t qnamelen, uint16_t qtype, uint16_t qclass, - uint16_t flags, int dnssec, int want_dnssec, int tcp_upstream, - int ssl_upstream, struct sockaddr_storage* addr, socklen_t addrlen, - uint8_t* zone, size_t zonelen, comm_point_callback_t* callback, - void* callback_arg, sldns_buffer* buff) + uint16_t flags, int dnssec, int want_dnssec, int nocaps, + int tcp_upstream, int ssl_upstream, struct sockaddr_storage* addr, + socklen_t addrlen, uint8_t* zone, size_t zonelen, + comm_point_callback_t* callback, void* callback_arg, + sldns_buffer* buff) { struct serviced_query* sq; struct service_callback* cb; @@ -1843,7 +1872,7 @@ outnet_serviced_query(struct outside_network* outnet, return NULL; if(!sq) { /* make new serviced query entry */ - sq = serviced_create(outnet, buff, dnssec, want_dnssec, + sq = serviced_create(outnet, buff, dnssec, want_dnssec, nocaps, tcp_upstream, ssl_upstream, addr, addrlen, zone, zonelen, (int)qtype); if(!sq) { diff --git a/usr.sbin/unbound/services/outside_network.h b/usr.sbin/unbound/services/outside_network.h index dda9d6f5a23..9959676d33f 100644 --- a/usr.sbin/unbound/services/outside_network.h +++ b/usr.sbin/unbound/services/outside_network.h @@ -45,6 +45,7 @@ #include "util/rbtree.h" #include "util/netevent.h" +#include "dnstap/dnstap_config.h" struct pending; struct pending_timeout; struct ub_randstate; @@ -55,6 +56,8 @@ struct infra_cache; struct port_comm; struct port_if; struct sldns_buffer; +struct serviced_query; +struct dt_env; /** * Send queries to outside servers and wait for answers from servers. @@ -125,6 +128,10 @@ struct outside_network { struct ub_randstate* rnd; /** ssl context to create ssl wrapped TCP with DNS connections */ void* sslctx; +#ifdef USE_DNSTAP + /** dnstap environment */ + struct dt_env* dtenv; +#endif /** * Array of tcp pending used for outgoing TCP connections. @@ -135,6 +142,8 @@ struct outside_network { struct pending_tcp **tcp_conns; /** number of tcp communication points. */ size_t num_tcp; + /** number of tcp communication points in use. */ + size_t num_tcp_outgoing; /** list of tcp comm points that are free for use */ struct pending_tcp* tcp_free; /** list of tcp queries waiting for a buffer */ @@ -210,6 +219,8 @@ struct pending { void* cb_arg; /** the outside network it is part of */ struct outside_network* outnet; + /** the corresponding serviced_query */ + struct serviced_query* sq; /*---- filled if udp pending is waiting -----*/ /** next in waiting list. */ @@ -307,6 +318,8 @@ struct serviced_query { int dnssec; /** We want signatures, or else the answer is likely useless */ int want_dnssec; + /** ignore capsforid */ + int nocaps; /** tcp upstream used, use tcp, or ssl_upstream for SSL */ int tcp_upstream, ssl_upstream; /** where to send it */ @@ -383,6 +396,7 @@ struct serviced_query { * @param sslctx: context to create outgoing connections with (if enabled). * @param delayclose: if not 0, udp sockets are delayed before timeout closure. * msec to wait on timeouted udp sockets. + * @param dtenv: environment to send dnstap events with (if enabled). * @return: the new structure (with no pending answers) or NULL on error. */ struct outside_network* outside_network_create(struct comm_base* base, @@ -391,7 +405,7 @@ struct outside_network* outside_network_create(struct comm_base* base, struct ub_randstate* rnd, int use_caps_for_id, int* availports, int numavailports, size_t unwanted_threshold, void (*unwanted_action)(void*), void* unwanted_param, int do_udp, - void* sslctx, int delayclose); + void* sslctx, int delayclose, struct dt_env *dtenv); /** * Delete outside_network structure. @@ -408,39 +422,32 @@ void outside_network_quit_prepare(struct outside_network* outnet); /** * Send UDP query, create pending answer. * Changes the ID for the query to be random and unique for that destination. - * @param outnet: provides the event handling + * @param sq: serviced query. * @param packet: wireformat query to send to destination. - * @param addr: address to send to. - * @param addrlen: length of addr. * @param timeout: in milliseconds from now. * @param callback: function to call on error, timeout or reply. * @param callback_arg: user argument for callback function. * @return: NULL on error for malloc or socket. Else the pending query object. */ -struct pending* pending_udp_query(struct outside_network* outnet, - struct sldns_buffer* packet, struct sockaddr_storage* addr, - socklen_t addrlen, int timeout, comm_point_callback_t* callback, +struct pending* pending_udp_query(struct serviced_query* sq, + struct sldns_buffer* packet, int timeout, comm_point_callback_t* callback, void* callback_arg); /** * Send TCP query. May wait for TCP buffer. Selects ID to be random, and * checks id. - * @param outnet: provides the event handling. + * @param sq: serviced query. * @param packet: wireformat query to send to destination. copied from. - * @param addr: address to send to. - * @param addrlen: length of addr. * @param timeout: in seconds from now. * Timer starts running now. Timer may expire if all buffers are used, * without any query been sent to the server yet. * @param callback: function to call on error, timeout or reply. * @param callback_arg: user argument for callback function. - * @param ssl_upstream: if the tcp connection must use SSL. * @return: false on error for malloc or socket. Else the pending TCP object. */ -struct waiting_tcp* pending_tcp_query(struct outside_network* outnet, - struct sldns_buffer* packet, struct sockaddr_storage* addr, - socklen_t addrlen, int timeout, comm_point_callback_t* callback, - void* callback_arg, int ssl_upstream); +struct waiting_tcp* pending_tcp_query(struct serviced_query* sq, + struct sldns_buffer* packet, int timeout, comm_point_callback_t* callback, + void* callback_arg); /** * Delete pending answer. @@ -464,6 +471,7 @@ void pending_delete(struct outside_network* outnet, struct pending* p); * If the value includes BIT_DO, DO bit is set when in EDNS queries. * @param want_dnssec: signatures are needed, without EDNS the answer is * likely to be useless. + * @param nocaps: ignore use_caps_for_id and use unperturbed qname. * @param tcp_upstream: use TCP for upstream queries. * @param ssl_upstream: use SSL for upstream queries. * @param callback: callback function. @@ -480,10 +488,11 @@ void pending_delete(struct outside_network* outnet, struct pending* p); */ struct serviced_query* outnet_serviced_query(struct outside_network* outnet, uint8_t* qname, size_t qnamelen, uint16_t qtype, uint16_t qclass, - uint16_t flags, int dnssec, int want_dnssec, int tcp_upstream, - int ssl_upstream, struct sockaddr_storage* addr, socklen_t addrlen, - uint8_t* zone, size_t zonelen, comm_point_callback_t* callback, - void* callback_arg, struct sldns_buffer* buff); + uint16_t flags, int dnssec, int want_dnssec, int nocaps, + int tcp_upstream, int ssl_upstream, struct sockaddr_storage* addr, + socklen_t addrlen, uint8_t* zone, size_t zonelen, + comm_point_callback_t* callback, void* callback_arg, + struct sldns_buffer* buff); /** * Remove service query callback. diff --git a/usr.sbin/unbound/smallapp/unbound-anchor.c b/usr.sbin/unbound/smallapp/unbound-anchor.c index 8ea4726b063..9df0d95b417 100644 --- a/usr.sbin/unbound/smallapp/unbound-anchor.c +++ b/usr.sbin/unbound/smallapp/unbound-anchor.c @@ -244,7 +244,7 @@ get_builtin_ds(void) /** print hex data */ static void -print_data(char* msg, char* data, int len) +print_data(const char* msg, const char* data, int len) { int i; printf("%s: ", msg); @@ -268,8 +268,8 @@ ub_ctx_error_exit(struct ub_ctx* ctx, const char* str, const char* str2) * Create a new unbound context with the commandline settings applied */ static struct ub_ctx* -create_unbound_context(char* res_conf, char* root_hints, char* debugconf, - int ip4only, int ip6only) +create_unbound_context(const char* res_conf, const char* root_hints, + const char* debugconf, int ip4only, int ip6only) { int r; struct ub_ctx* ctx = ub_ctx_create(); @@ -306,7 +306,7 @@ create_unbound_context(char* res_conf, char* root_hints, char* debugconf, /** printout certificate in detail */ static void -verb_cert(char* msg, X509* x) +verb_cert(const char* msg, X509* x) { if(verb == 0 || verb == 1) return; if(verb == 2) { @@ -322,7 +322,7 @@ verb_cert(char* msg, X509* x) /** printout certificates in detail */ static void -verb_certs(char* msg, STACK_OF(X509)* sk) +verb_certs(const char* msg, STACK_OF(X509)* sk) { int i, num = sk_X509_num(sk); if(verb == 0 || verb == 1) return; @@ -360,7 +360,7 @@ read_cert_bio(BIO* bio) /* read the certificate file */ static STACK_OF(X509)* -read_cert_file(char* file) +read_cert_file(const char* file) { STACK_OF(X509)* sk; FILE* in; @@ -435,7 +435,7 @@ read_builtin_cert(void) /** read update cert file or use builtin */ static STACK_OF(X509)* -read_cert_or_builtin(char* file) +read_cert_or_builtin(const char* file) { STACK_OF(X509) *sk = read_cert_file(file); if(!sk) { @@ -459,7 +459,7 @@ do_list_builtin(void) /** printout IP address with message */ static void -verb_addr(char* msg, struct ip_list* ip) +verb_addr(const char* msg, struct ip_list* ip) { if(verb) { char out[100]; @@ -526,7 +526,7 @@ RR_to_ip(int tp, char* data, int len, int port) /** Resolve name, type, class and add addresses to iplist */ static void -resolve_host_ip(struct ub_ctx* ctx, char* host, int port, int tp, int cl, +resolve_host_ip(struct ub_ctx* ctx, const char* host, int port, int tp, int cl, struct ip_list** head) { struct ub_result* res = NULL; @@ -561,29 +561,27 @@ resolve_host_ip(struct ub_ctx* ctx, char* host, int port, int tp, int cl, /** parse a text IP address into a sockaddr */ static struct ip_list* -parse_ip_addr(char* str, int port) +parse_ip_addr(const char* str, int port) { socklen_t len = 0; - struct sockaddr_storage* addr = NULL; - struct sockaddr_in6 a6; - struct sockaddr_in a; + union { + struct sockaddr_in6 a6; + struct sockaddr_in a; + } addr; struct ip_list* ip; uint16_t p = (uint16_t)port; - memset(&a6, 0, sizeof(a6)); - memset(&a, 0, sizeof(a)); + memset(&addr, 0, sizeof(addr)); - if(inet_pton(AF_INET6, str, &a6.sin6_addr) > 0) { + if(inet_pton(AF_INET6, str, &addr.a6.sin6_addr) > 0) { /* it is an IPv6 */ - a6.sin6_family = AF_INET6; - a6.sin6_port = (in_port_t)htons(p); - addr = (struct sockaddr_storage*)&a6; - len = (socklen_t)sizeof(struct sockaddr_in6); + addr.a6.sin6_family = AF_INET6; + addr.a6.sin6_port = (in_port_t)htons(p); + len = (socklen_t)sizeof(addr.a6); } - if(inet_pton(AF_INET, str, &a.sin_addr) > 0) { + if(inet_pton(AF_INET, str, &addr.a.sin_addr) > 0) { /* it is an IPv4 */ - a.sin_family = AF_INET; - a.sin_port = (in_port_t)htons(p); - addr = (struct sockaddr_storage*)&a; + addr.a.sin_family = AF_INET; + addr.a.sin_port = (in_port_t)htons(p); len = (socklen_t)sizeof(struct sockaddr_in); } if(!len) return NULL; @@ -593,7 +591,7 @@ parse_ip_addr(char* str, int port) exit(0); } ip->len = len; - memmove(&ip->addr, addr, len); + memmove(&ip->addr, &addr, len); if(verb) printf("server address is %s\n", str); return ip; } @@ -613,8 +611,8 @@ parse_ip_addr(char* str, int port) * @return list of IP addresses. */ static struct ip_list* -resolve_name(char* host, int port, char* res_conf, char* root_hints, - char* debugconf, int ip4only, int ip6only) +resolve_name(const char* host, int port, const char* res_conf, + const char* root_hints, const char* debugconf, int ip4only, int ip6only) { struct ub_ctx* ctx; struct ip_list* list = NULL; @@ -669,15 +667,6 @@ count_unused(struct ip_list* p) return num; } -static int get_random(void) -{ - int r; - if (RAND_bytes((unsigned char*)&r, (int)sizeof(r)) == 1) { - return r; - } - return (int)random(); -} - /** pick random unused element from IP list */ static struct ip_list* pick_random_ip(struct ip_list* list) @@ -687,7 +676,7 @@ pick_random_ip(struct ip_list* list) int sel; if(num == 0) return NULL; /* not perfect, but random enough */ - sel = get_random() % num; + sel = (int)arc4random_uniform((uint32_t)num); /* skip over unused elements that we did not select */ while(sel > 0 && p) { if(!p->used) sel--; @@ -810,7 +799,7 @@ TLS_shutdown(int fd, SSL* ssl, SSL_CTX* sslctx) /** write a line over SSL */ static int -write_ssl_line(SSL* ssl, char* str, char* sec) +write_ssl_line(SSL* ssl, const char* str, const char* sec) { char buf[1024]; size_t l; @@ -1029,7 +1018,7 @@ do_chunked_read(SSL* ssl) /** start HTTP1.1 transaction on SSL */ static int -write_http_get(SSL* ssl, char* pathname, char* urlname) +write_http_get(SSL* ssl, const char* pathname, const char* urlname) { if(write_ssl_line(ssl, "GET /%s HTTP/1.1", pathname) && write_ssl_line(ssl, "Host: %s", urlname) && @@ -1100,7 +1089,7 @@ read_http_result(SSL* ssl) /** https to an IP addr, return BIO with pathname or NULL */ static BIO* -https_to_ip(struct ip_list* ip, char* pathname, char* urlname) +https_to_ip(struct ip_list* ip, const char* pathname, const char* urlname) { int fd; SSL* ssl; @@ -1140,7 +1129,7 @@ https_to_ip(struct ip_list* ip, char* pathname, char* urlname) * @return a memory BIO with the file in it. */ static BIO* -https(struct ip_list* ip_list, char* pathname, char* urlname) +https(struct ip_list* ip_list, const char* pathname, const char* urlname) { struct ip_list* ip; BIO* bio = NULL; @@ -1222,7 +1211,7 @@ xml_selectbio(struct xml_data* data, const char* tag) * NOT zero terminated. * @param len: length of this part of the data. */ -void +static void xml_charhandle(void *userData, const XML_Char *s, int len) { struct xml_data* data = (struct xml_data*)userData; @@ -1265,7 +1254,7 @@ xml_charhandle(void *userData, const XML_Char *s, int len) * @return the value or NULL. (ptr into atts). */ static const XML_Char* -find_att(const XML_Char **atts, XML_Char* name) +find_att(const XML_Char **atts, const XML_Char* name) { int i; for(i=0; atts[i]; i+=2) { @@ -1379,7 +1368,7 @@ handle_keydigest(struct xml_data* data, const XML_Char **atts) /** See if XML element equals the zone name */ static int -xml_is_zone_name(BIO* zone, char* name) +xml_is_zone_name(BIO* zone, const char* name) { char buf[1024]; char* z = NULL; @@ -1611,8 +1600,6 @@ xml_parse(BIO* xml, time_t now) XML_ParserFree(parser); if(verb >= 4) { - char* pp = NULL; - int len; (void)BIO_seek(data.ds, 0); len = BIO_get_mem_data(data.ds, &pp); printf("got DS bio %d: '", len); @@ -1655,7 +1642,7 @@ get_usage_of_ex(X509* cert) /** get valid signers from the list of signers in the signature */ static STACK_OF(X509)* -get_valid_signers(PKCS7* p7, char* p7signer) +get_valid_signers(PKCS7* p7, const char* p7signer) { int i; STACK_OF(X509)* validsigners = sk_X509_new_null(); @@ -1738,7 +1725,7 @@ get_valid_signers(PKCS7* p7, char* p7signer) /** verify a PKCS7 signature, false on failure */ static int -verify_p7sig(BIO* data, BIO* p7s, STACK_OF(X509)* trust, char* p7signer) +verify_p7sig(BIO* data, BIO* p7s, STACK_OF(X509)* trust, const char* p7signer) { PKCS7* p7; X509_STORE *store = X509_STORE_new(); @@ -1816,7 +1803,7 @@ verify_p7sig(BIO* data, BIO* p7s, STACK_OF(X509)* trust, char* p7signer) /** write unsigned root anchor file, a 5011 revoked tp */ static void -write_unsigned_root(char* root_anchor_file) +write_unsigned_root(const char* root_anchor_file) { FILE* out; time_t now = time(NULL); @@ -1842,7 +1829,7 @@ write_unsigned_root(char* root_anchor_file) /** write root anchor file */ static void -write_root_anchor(char* root_anchor_file, BIO* ds) +write_root_anchor(const char* root_anchor_file, BIO* ds) { char* pp = NULL; int len; @@ -1868,8 +1855,8 @@ write_root_anchor(char* root_anchor_file, BIO* ds) /** Perform the verification and update of the trustanchor file */ static void -verify_and_update_anchor(char* root_anchor_file, BIO* xml, BIO* p7s, - STACK_OF(X509)* cert, char* p7signer) +verify_and_update_anchor(const char* root_anchor_file, BIO* xml, BIO* p7s, + STACK_OF(X509)* cert, const char* p7signer) { BIO* ds; @@ -1897,10 +1884,11 @@ static void do_wsa_cleanup(void) { WSACleanup(); } /** perform actual certupdate work */ static int -do_certupdate(char* root_anchor_file, char* root_cert_file, - char* urlname, char* xmlname, char* p7sname, char* p7signer, - char* res_conf, char* root_hints, char* debugconf, - int ip4only, int ip6only, int port, struct ub_result* dnskey) +do_certupdate(const char* root_anchor_file, const char* root_cert_file, + const char* urlname, const char* xmlname, const char* p7sname, + const char* p7signer, const char* res_conf, const char* root_hints, + const char* debugconf, int ip4only, int ip6only, int port, + struct ub_result* dnskey) { STACK_OF(X509)* cert; BIO *xml, *p7s; @@ -1954,7 +1942,7 @@ do_certupdate(char* root_anchor_file, char* root_cert_file, * 2 if it is OK. */ static int -try_read_anchor(char* file) +try_read_anchor(const char* file) { int empty = 1; char line[10240]; @@ -1998,7 +1986,7 @@ try_read_anchor(char* file) /** Write the builtin root anchor to a file */ static void -write_builtin_anchor(char* file) +write_builtin_anchor(const char* file) { const char* builtin_root_anchor = get_builtin_ds(); FILE* out = fopen(file, "w"); @@ -2024,7 +2012,7 @@ write_builtin_anchor(char* file) * @return 0 if trustpoint is insecure, 1 on success. Exit on failure. */ static int -provide_builtin(char* root_anchor_file, int* used_builtin) +provide_builtin(const char* root_anchor_file, int* used_builtin) { /* try to read it */ switch(try_read_anchor(root_anchor_file)) @@ -2046,7 +2034,7 @@ provide_builtin(char* root_anchor_file, int* used_builtin) * add an autotrust anchor for the root to the context */ static void -add_5011_probe_root(struct ub_ctx* ctx, char* root_anchor_file) +add_5011_probe_root(struct ub_ctx* ctx, const char* root_anchor_file) { int r; r = ub_ctx_set_option(ctx, "auto-trust-anchor-file:", root_anchor_file); @@ -2083,7 +2071,7 @@ prime_root_key(struct ub_ctx* ctx) /** see if ADDPEND keys exist in autotrust file (if possible) */ static int -read_if_pending_keys(char* file) +read_if_pending_keys(const char* file) { FILE* in = fopen(file, "r"); char line[8192]; @@ -2105,7 +2093,7 @@ read_if_pending_keys(char* file) /** read last successful probe time from autotrust file (if possible) */ static int32_t -read_last_success_time(char* file) +read_last_success_time(const char* file) { FILE* in = fopen(file, "r"); char line[1024]; @@ -2142,7 +2130,7 @@ read_last_success_time(char* file) * @return true if certupdate is ok. */ static int -probe_date_allows_certupdate(char* root_anchor_file) +probe_date_allows_certupdate(const char* root_anchor_file) { int has_pending_keys = read_if_pending_keys(root_anchor_file); int32_t last_success = read_last_success_time(root_anchor_file); @@ -2180,10 +2168,10 @@ probe_date_allows_certupdate(char* root_anchor_file) /** perform the unbound-anchor work */ static int -do_root_update_work(char* root_anchor_file, char* root_cert_file, - char* urlname, char* xmlname, char* p7sname, char* p7signer, - char* res_conf, char* root_hints, char* debugconf, - int ip4only, int ip6only, int force, int port) +do_root_update_work(const char* root_anchor_file, const char* root_cert_file, + const char* urlname, const char* xmlname, const char* p7sname, + const char* p7signer, const char* res_conf, const char* root_hints, + const char* debugconf, int ip4only, int ip6only, int force, int port) { struct ub_ctx* ctx; struct ub_result* dnskey; @@ -2233,15 +2221,15 @@ extern char* optarg; int main(int argc, char* argv[]) { int c; - char* root_anchor_file = ROOT_ANCHOR_FILE; - char* root_cert_file = ROOT_CERT_FILE; - char* urlname = URLNAME; - char* xmlname = XMLNAME; - char* p7sname = P7SNAME; - char* p7signer = P7SIGNER; - char* res_conf = NULL; - char* root_hints = NULL; - char* debugconf = NULL; + const char* root_anchor_file = ROOT_ANCHOR_FILE; + const char* root_cert_file = ROOT_CERT_FILE; + const char* urlname = URLNAME; + const char* xmlname = XMLNAME; + const char* p7sname = P7SNAME; + const char* p7signer = P7SIGNER; + const char* res_conf = NULL; + const char* root_hints = NULL; + const char* debugconf = NULL; int dolist=0, ip4only=0, ip6only=0, force=0, port = HTTPS_PORT; /* parse the options */ while( (c=getopt(argc, argv, "46C:FP:a:c:f:hln:r:s:u:vx:")) != -1) { diff --git a/usr.sbin/unbound/smallapp/unbound-checkconf.c b/usr.sbin/unbound/smallapp/unbound-checkconf.c index 78733edcfd7..e83867f2684 100644 --- a/usr.sbin/unbound/smallapp/unbound-checkconf.c +++ b/usr.sbin/unbound/smallapp/unbound-checkconf.c @@ -392,10 +392,17 @@ morechecks(struct config_file* cfg, const char* fname) if(strcmp(cfg->module_conf, "iterator") != 0 && strcmp(cfg->module_conf, "validator iterator") != 0 + && strcmp(cfg->module_conf, "dns64 validator iterator") != 0 + && strcmp(cfg->module_conf, "dns64 iterator") != 0 #ifdef WITH_PYTHONMODULE && strcmp(cfg->module_conf, "python iterator") != 0 && strcmp(cfg->module_conf, "python validator iterator") != 0 && strcmp(cfg->module_conf, "validator python iterator") != 0 + && strcmp(cfg->module_conf, "dns64 python iterator") != 0 + && strcmp(cfg->module_conf, "dns64 python validator iterator") != 0 + && strcmp(cfg->module_conf, "dns64 validator python iterator") != 0 + && strcmp(cfg->module_conf, "python dns64 iterator") != 0 + && strcmp(cfg->module_conf, "python dns64 validator iterator") != 0 #endif ) { fatal_exit("module conf '%s' is not known to work", @@ -459,6 +466,11 @@ checkconf(const char* cfgfile, const char* opt) config_delete(cfg); exit(1); } + if(opt) { + print_option(cfg, opt); + config_delete(cfg); + return; + } morechecks(cfg, cfgfile); check_mod(cfg, iter_get_funcblock()); check_mod(cfg, val_get_funcblock()); @@ -468,8 +480,7 @@ checkconf(const char* cfgfile, const char* opt) #endif check_fwd(cfg); check_hints(cfg); - if(opt) print_option(cfg, opt); - else printf("unbound-checkconf: no errors in %s\n", cfgfile); + printf("unbound-checkconf: no errors in %s\n", cfgfile); config_delete(cfg); } diff --git a/usr.sbin/unbound/smallapp/unbound-control-setup.sh.in b/usr.sbin/unbound/smallapp/unbound-control-setup.sh.in new file mode 100644 index 00000000000..79605dc6fd4 --- /dev/null +++ b/usr.sbin/unbound/smallapp/unbound-control-setup.sh.in @@ -0,0 +1,163 @@ +#!/bin/sh +# +# unbound-control-setup.sh - set up SSL certificates for unbound-control +# +# Copyright (c) 2008, NLnet Labs. All rights reserved. +# +# This software is open source. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# Neither the name of the NLNET LABS nor the names of its contributors may +# be used to endorse or promote products derived from this software without +# specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +# TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +# settings: + +# directory for files +prefix=@prefix@ +DESTDIR=@sysconfdir@/unbound + +# issuer and subject name for certificates +SERVERNAME=unbound +CLIENTNAME=unbound-control + +# validity period for certificates +DAYS=7200 + +# size of keys in bits +BITS=1536 + +# hash algorithm +HASH=sha256 + +# base name for unbound server keys +SVR_BASE=unbound_server + +# base name for unbound-control keys +CTL_BASE=unbound_control + +# we want -rw-r----- access (say you run this as root: grp=yes (server), all=no). +umask 0027 + +# end of options + +# functions: +error ( ) { + echo "$0 fatal error: $1" + exit 1 +} + +# check arguments: +while test $# -ne 0; do + case $1 in + -d) + if test $# -eq 1; then error "need argument for -d"; fi + DESTDIR="$2" + shift + ;; + *) + echo "unbound-control-setup.sh - setup SSL keys for unbound-control" + echo " -d dir use directory to store keys and certificates." + echo " default: $DESTDIR" + echo "please run this command using the same user id that the " + echo "unbound daemon uses, it needs read privileges." + exit 1 + ;; + esac + shift +done + +# go!: +echo "setup in directory $DESTDIR" +cd "$DESTDIR" || error "could not cd to $DESTDIR" + +# create certificate keys; do not recreate if they already exist. +if test -f $SVR_BASE.key; then + echo "$SVR_BASE.key exists" +else + echo "generating $SVR_BASE.key" + openssl genrsa -out $SVR_BASE.key $BITS || error "could not genrsa" +fi +if test -f $CTL_BASE.key; then + echo "$CTL_BASE.key exists" +else + echo "generating $CTL_BASE.key" + openssl genrsa -out $CTL_BASE.key $BITS || error "could not genrsa" +fi + +# create self-signed cert for server +cat >request.cfg <<EOF +[req] +default_bits=$BITS +default_md=$HASH +prompt=no +distinguished_name=req_distinguished_name + +[req_distinguished_name] +commonName=$SERVERNAME +EOF +test -f request.cfg || error "could not create request.cfg" + +echo "create $SVR_BASE.pem (self signed certificate)" +openssl req -key $SVR_BASE.key -config request.cfg -new -x509 -days $DAYS -out $SVR_BASE.pem || error "could not create $SVR_BASE.pem" +# create trusted usage pem +openssl x509 -in $SVR_BASE.pem -addtrust serverAuth -out $SVR_BASE"_trust.pem" + +# create client request and sign it, piped +cat >request.cfg <<EOF +[req] +default_bits=$BITS +default_md=$HASH +prompt=no +distinguished_name=req_distinguished_name + +[req_distinguished_name] +commonName=$CLIENTNAME +EOF +test -f request.cfg || error "could not create request.cfg" + +echo "create $CTL_BASE.pem (signed client certificate)" +openssl req -key $CTL_BASE.key -config request.cfg -new | openssl x509 -req -days $DAYS -CA $SVR_BASE"_trust.pem" -CAkey $SVR_BASE.key -CAcreateserial -$HASH -out $CTL_BASE.pem +test -f $CTL_BASE.pem || error "could not create $CTL_BASE.pem" +# create trusted usage pem +# openssl x509 -in $CTL_BASE.pem -addtrust clientAuth -out $CTL_BASE"_trust.pem" + +# see details with openssl x509 -noout -text < $SVR_BASE.pem +# echo "create $CTL_BASE""_browser.pfx (web client certificate)" +# echo "create webbrowser PKCS#12 .PFX certificate file. In Firefox import in:" +# echo "preferences - advanced - encryption - view certificates - your certs" +# echo "empty password is used, simply click OK on the password dialog box." +# openssl pkcs12 -export -in $CTL_BASE"_trust.pem" -inkey $CTL_BASE.key -name "unbound remote control client cert" -out $CTL_BASE"_browser.pfx" -password "pass:" || error "could not create browser certificate" + +# remove unused permissions +chmod o-rw $SVR_BASE.pem $SVR_BASE.key $CTL_BASE.pem $CTL_BASE.key + +# remove crap +rm -f request.cfg +rm -f $CTL_BASE"_trust.pem" $SVR_BASE"_trust.pem" $SVR_BASE"_trust.srl" + +echo "Setup success. Certificates created. Enable in unbound.conf file to use" + +exit 0 diff --git a/usr.sbin/unbound/smallapp/unbound-control.c b/usr.sbin/unbound/smallapp/unbound-control.c index 067e133fc16..ff86184a816 100644 --- a/usr.sbin/unbound/smallapp/unbound-control.c +++ b/usr.sbin/unbound/smallapp/unbound-control.c @@ -95,6 +95,7 @@ usage() printf(" flush_zone <name> flush everything at or under name\n"); printf(" from rr and dnssec caches\n"); printf(" flush_bogus flush all bogus data\n"); + printf(" flush_negative flush all negative data\n"); printf(" flush_stats flush statistics, make zero\n"); printf(" flush_requestlist drop queries that are worked on\n"); printf(" dump_requestlist show what is worked on\n"); @@ -148,6 +149,8 @@ setup_ctx(struct config_file* cfg) ssl_err("could not allocate SSL_CTX pointer"); if(!(SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2) & SSL_OP_NO_SSLv2)) ssl_err("could not set SSL_OP_NO_SSLv2"); + if(!(SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv3) & SSL_OP_NO_SSLv3)) + ssl_err("could not set SSL_OP_NO_SSLv3"); if(!SSL_CTX_use_certificate_file(ctx,c_cert,SSL_FILETYPE_PEM) || !SSL_CTX_use_PrivateKey_file(ctx,c_key,SSL_FILETYPE_PEM) || !SSL_CTX_check_private_key(ctx)) @@ -200,15 +203,14 @@ contact_server(const char* svr, struct config_file* cfg, int statuscmd) #endif } if(connect(fd, (struct sockaddr*)&addr, addrlen) < 0) { - log_addr(0, "address", &addr, addrlen); #ifndef USE_WINSOCK - log_err("connect: %s", strerror(errno)); + log_err_addr("connect", strerror(errno), &addr, addrlen); if(errno == ECONNREFUSED && statuscmd) { printf("unbound is stopped\n"); exit(3); } #else - log_err("connect: %s", wsa_strerror(WSAGetLastError())); + log_err_addr("connect", wsa_strerror(WSAGetLastError()), &addr, addrlen); if(WSAGetLastError() == WSAECONNREFUSED && statuscmd) { printf("unbound is stopped\n"); exit(3); diff --git a/usr.sbin/unbound/smallapp/unbound-host.c b/usr.sbin/unbound/smallapp/unbound-host.c index 12c60f4060b..8020ad8c802 100644 --- a/usr.sbin/unbound/smallapp/unbound-host.c +++ b/usr.sbin/unbound/smallapp/unbound-host.c @@ -85,6 +85,8 @@ usage() printf(" -c class what class to look for, if not class IN.\n"); printf(" -y 'keystring' specify trust anchor, DS or DNSKEY, like\n"); printf(" -y 'example.com DS 31560 5 1 1CFED8478...'\n"); + printf(" -D DNSSEC enable with default root anchor\n"); + printf(" from %s\n", ROOT_ANCHOR_FILE); printf(" -f keyfile read trust anchors from file, with lines as -y.\n"); printf(" -F keyfile read named.conf-style trust anchors.\n"); printf(" -C config use the specified unbound.conf (none read by default)\n"); @@ -421,9 +423,11 @@ int main(int argc, char* argv[]) fprintf(stderr, "error: out of memory\n"); exit(1); } + /* no need to fetch additional targets, we only do few lookups */ + check_ub_res(ub_ctx_set_option(ctx, "target-fetch-policy:", "0 0 0 0 0")); /* parse the options */ - while( (c=getopt(argc, argv, "46F:c:df:hrt:vy:C:")) != -1) { + while( (c=getopt(argc, argv, "46DF:c:df:hrt:vy:C:")) != -1) { switch(c) { case '4': check_ub_res(ub_ctx_set_option(ctx, "do-ip6:", "no")); @@ -437,6 +441,9 @@ int main(int argc, char* argv[]) case 'C': check_ub_res(ub_ctx_config(ctx, optarg)); break; + case 'D': + check_ub_res(ub_ctx_add_ta_file(ctx, ROOT_ANCHOR_FILE)); + break; case 'd': debuglevel++; if(debuglevel < 2) diff --git a/usr.sbin/unbound/util/config_file.h b/usr.sbin/unbound/util/config_file.h index 7360fd30205..49ffbdde4a5 100644 --- a/usr.sbin/unbound/util/config_file.h +++ b/usr.sbin/unbound/util/config_file.h @@ -273,6 +273,8 @@ struct config_file { struct config_strlist* local_zones_nodefault; /** local data RRs configged */ struct config_strlist* local_data; + /** unblock lan zones (reverse lookups for 10/8 and so on) */ + int unblock_lan_zones; /** remote control section. enable toggle. */ int remote_control_enable; @@ -303,6 +305,38 @@ struct config_file { /* maximum UDP response size */ size_t max_udp_size; + + /* DNS64 prefix */ + char* dns64_prefix; + + /* Synthetize all AAAA record despite the presence of an authoritative one */ + int dns64_synthall; + + /** true to enable dnstap support */ + int dnstap; + /** dnstap socket path */ + char* dnstap_socket_path; + /** true to send "identity" via dnstap */ + int dnstap_send_identity; + /** true to send "version" via dnstap */ + int dnstap_send_version; + /** dnstap "identity", hostname is used if "". */ + char* dnstap_identity; + /** dnstap "version", package version is used if "". */ + char* dnstap_version; + + /** true to log dnstap RESOLVER_QUERY message events */ + int dnstap_log_resolver_query_messages; + /** true to log dnstap RESOLVER_RESPONSE message events */ + int dnstap_log_resolver_response_messages; + /** true to log dnstap CLIENT_QUERY message events */ + int dnstap_log_client_query_messages; + /** true to log dnstap CLIENT_RESPONSE message events */ + int dnstap_log_client_response_messages; + /** true to log dnstap FORWARDER_QUERY message events */ + int dnstap_log_forwarder_query_messages; + /** true to log dnstap FORWARDER_RESPONSE message events */ + int dnstap_log_forwarder_response_messages; }; /** @@ -639,6 +673,18 @@ struct config_parser_state { /** global config parser object used during config parsing */ extern struct config_parser_state* cfg_parser; +/** init lex state */ +void init_cfg_parse(void); +/** lex in file */ +extern FILE* ub_c_in; +/** lex out file */ +extern FILE* ub_c_out; +/** the yacc lex generated parse function */ +int ub_c_parse(void); +/** the lexer function */ +int ub_c_lex(void); +/** wrap function */ +int ub_c_wrap(void); /** parsing helpers: print error with file and line numbers */ void ub_c_error(const char* msg); /** parsing helpers: print error with file and line numbers */ diff --git a/usr.sbin/unbound/util/configlexer.lex b/usr.sbin/unbound/util/configlexer.lex index b36c8af8842..7ee7b9bd9a9 100644 --- a/usr.sbin/unbound/util/configlexer.lex +++ b/usr.sbin/unbound/util/configlexer.lex @@ -7,7 +7,6 @@ * See LICENSE for the license. * */ - #include <ctype.h> #include <string.h> #include <strings.h> @@ -308,6 +307,7 @@ log-queries{COLON} { YDVAR(1, VAR_LOG_QUERIES) } local-zone{COLON} { YDVAR(2, VAR_LOCAL_ZONE) } local-data{COLON} { YDVAR(1, VAR_LOCAL_DATA) } local-data-ptr{COLON} { YDVAR(1, VAR_LOCAL_DATA_PTR) } +unblock-lan-zones{COLON} { YDVAR(1, VAR_UNBLOCK_LAN_ZONES) } statistics-interval{COLON} { YDVAR(1, VAR_STATISTICS_INTERVAL) } statistics-cumulative{COLON} { YDVAR(1, VAR_STATISTICS_CUMULATIVE) } extended-statistics{COLON} { YDVAR(1, VAR_EXTENDED_STATISTICS) } @@ -325,6 +325,27 @@ domain-insecure{COLON} { YDVAR(1, VAR_DOMAIN_INSECURE) } minimal-responses{COLON} { YDVAR(1, VAR_MINIMAL_RESPONSES) } rrset-roundrobin{COLON} { YDVAR(1, VAR_RRSET_ROUNDROBIN) } max-udp-size{COLON} { YDVAR(1, VAR_MAX_UDP_SIZE) } +dns64-prefix{COLON} { YDVAR(1, VAR_DNS64_PREFIX) } +dns64-synthall{COLON} { YDVAR(1, VAR_DNS64_SYNTHALL) } +dnstap{COLON} { YDVAR(0, VAR_DNSTAP) } +dnstap-enable{COLON} { YDVAR(1, VAR_DNSTAP_ENABLE) } +dnstap-socket-path{COLON} { YDVAR(1, VAR_DNSTAP_SOCKET_PATH) } +dnstap-send-identity{COLON} { YDVAR(1, VAR_DNSTAP_SEND_IDENTITY) } +dnstap-send-version{COLON} { YDVAR(1, VAR_DNSTAP_SEND_VERSION) } +dnstap-identity{COLON} { YDVAR(1, VAR_DNSTAP_IDENTITY) } +dnstap-version{COLON} { YDVAR(1, VAR_DNSTAP_VERSION) } +dnstap-log-resolver-query-messages{COLON} { + YDVAR(1, VAR_DNSTAP_LOG_RESOLVER_QUERY_MESSAGES) } +dnstap-log-resolver-response-messages{COLON} { + YDVAR(1, VAR_DNSTAP_LOG_RESOLVER_RESPONSE_MESSAGES) } +dnstap-log-client-query-messages{COLON} { + YDVAR(1, VAR_DNSTAP_LOG_CLIENT_QUERY_MESSAGES) } +dnstap-log-client-response-messages{COLON} { + YDVAR(1, VAR_DNSTAP_LOG_CLIENT_RESPONSE_MESSAGES) } +dnstap-log-forwarder-query-messages{COLON} { + YDVAR(1, VAR_DNSTAP_LOG_FORWARDER_QUERY_MESSAGES) } +dnstap-log-forwarder-response-messages{COLON} { + YDVAR(1, VAR_DNSTAP_LOG_FORWARDER_RESPONSE_MESSAGES) } <INITIAL,val>{NEWLINE} { LEXOUT(("NL\n")); cfg_parser->line++; } /* Quoted strings. Strip leading and ending quotes */ diff --git a/usr.sbin/unbound/util/configparser.y b/usr.sbin/unbound/util/configparser.y index 74b5b79ee83..7a92d9ee789 100644 --- a/usr.sbin/unbound/util/configparser.y +++ b/usr.sbin/unbound/util/configparser.y @@ -105,13 +105,23 @@ extern struct config_parser_state* cfg_parser; %token VAR_IGNORE_CD_FLAG VAR_LOG_QUERIES VAR_TCP_UPSTREAM VAR_SSL_UPSTREAM %token VAR_SSL_SERVICE_KEY VAR_SSL_SERVICE_PEM VAR_SSL_PORT VAR_FORWARD_FIRST %token VAR_STUB_FIRST VAR_MINIMAL_RESPONSES VAR_RRSET_ROUNDROBIN -%token VAR_MAX_UDP_SIZE VAR_DELAY_CLOSE +%token VAR_MAX_UDP_SIZE VAR_DELAY_CLOSE VAR_UNBLOCK_LAN_ZONES +%token VAR_DNS64_PREFIX VAR_DNS64_SYNTHALL +%token VAR_DNSTAP VAR_DNSTAP_ENABLE VAR_DNSTAP_SOCKET_PATH +%token VAR_DNSTAP_SEND_IDENTITY VAR_DNSTAP_SEND_VERSION +%token VAR_DNSTAP_IDENTITY VAR_DNSTAP_VERSION +%token VAR_DNSTAP_LOG_RESOLVER_QUERY_MESSAGES +%token VAR_DNSTAP_LOG_RESOLVER_RESPONSE_MESSAGES +%token VAR_DNSTAP_LOG_CLIENT_QUERY_MESSAGES +%token VAR_DNSTAP_LOG_CLIENT_RESPONSE_MESSAGES +%token VAR_DNSTAP_LOG_FORWARDER_QUERY_MESSAGES +%token VAR_DNSTAP_LOG_FORWARDER_RESPONSE_MESSAGES %% toplevelvars: /* empty */ | toplevelvars toplevelvar ; toplevelvar: serverstart contents_server | stubstart contents_stub | forwardstart contents_forward | pythonstart contents_py | - rcstart contents_rc + rcstart contents_rc | dtstart contents_dt ; /* server: declaration */ @@ -163,7 +173,8 @@ content_server: server_num_threads | server_verbosity | server_port | server_log_queries | server_tcp_upstream | server_ssl_upstream | server_ssl_service_key | server_ssl_service_pem | server_ssl_port | server_minimal_responses | server_rrset_roundrobin | server_max_udp_size | - server_so_reuseport | server_delay_close + server_so_reuseport | server_delay_close | server_unblock_lan_zones | + server_dns64_prefix | server_dns64_synthall ; stubstart: VAR_STUB_ZONE { @@ -678,6 +689,16 @@ server_delay_close: VAR_DELAY_CLOSE STRING_ARG free($2); } ; +server_unblock_lan_zones: VAR_UNBLOCK_LAN_ZONES STRING_ARG + { + OUTYY(("P(server_unblock_lan_zones:%s)\n", $2)); + if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) + yyerror("expected yes or no."); + else cfg_parser->cfg->unblock_lan_zones = + (strcmp($2, "yes")==0); + free($2); + } + ; server_rrset_cache_size: VAR_RRSET_CACHE_SIZE STRING_ARG { OUTYY(("P(server_rrset_cache_size:%s)\n", $2)); @@ -1148,6 +1169,22 @@ server_max_udp_size: VAR_MAX_UDP_SIZE STRING_ARG free($2); } ; +server_dns64_prefix: VAR_DNS64_PREFIX STRING_ARG + { + OUTYY(("P(dns64_prefix:%s)\n", $2)); + free(cfg_parser->cfg->dns64_prefix); + cfg_parser->cfg->dns64_prefix = $2; + } + ; +server_dns64_synthall: VAR_DNS64_SYNTHALL STRING_ARG + { + OUTYY(("P(server_dns64_synthall:%s)\n", $2)); + if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) + yyerror("expected yes or no."); + else cfg_parser->cfg->dns64_synthall = (strcmp($2, "yes")==0); + free($2); + } + ; stub_name: VAR_NAME STRING_ARG { OUTYY(("P(name:%s)\n", $2)); @@ -1289,6 +1326,122 @@ rc_control_cert_file: VAR_CONTROL_CERT_FILE STRING_ARG cfg_parser->cfg->control_cert_file = $2; } ; +dtstart: VAR_DNSTAP + { + OUTYY(("\nP(dnstap:)\n")); + } + ; +contents_dt: contents_dt content_dt + | ; +content_dt: dt_dnstap_enable | dt_dnstap_socket_path | + dt_dnstap_send_identity | dt_dnstap_send_version | + dt_dnstap_identity | dt_dnstap_version | + dt_dnstap_log_resolver_query_messages | + dt_dnstap_log_resolver_response_messages | + dt_dnstap_log_client_query_messages | + dt_dnstap_log_client_response_messages | + dt_dnstap_log_forwarder_query_messages | + dt_dnstap_log_forwarder_response_messages + ; +dt_dnstap_enable: VAR_DNSTAP_ENABLE STRING_ARG + { + OUTYY(("P(dt_dnstap_enable:%s)\n", $2)); + if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) + yyerror("expected yes or no."); + else cfg_parser->cfg->dnstap = (strcmp($2, "yes")==0); + } + ; +dt_dnstap_socket_path: VAR_DNSTAP_SOCKET_PATH STRING_ARG + { + OUTYY(("P(dt_dnstap_socket_path:%s)\n", $2)); + free(cfg_parser->cfg->dnstap_socket_path); + cfg_parser->cfg->dnstap_socket_path = $2; + } + ; +dt_dnstap_send_identity: VAR_DNSTAP_SEND_IDENTITY STRING_ARG + { + OUTYY(("P(dt_dnstap_send_identity:%s)\n", $2)); + if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) + yyerror("expected yes or no."); + else cfg_parser->cfg->dnstap_send_identity = (strcmp($2, "yes")==0); + } + ; +dt_dnstap_send_version: VAR_DNSTAP_SEND_VERSION STRING_ARG + { + OUTYY(("P(dt_dnstap_send_version:%s)\n", $2)); + if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) + yyerror("expected yes or no."); + else cfg_parser->cfg->dnstap_send_version = (strcmp($2, "yes")==0); + } + ; +dt_dnstap_identity: VAR_DNSTAP_IDENTITY STRING_ARG + { + OUTYY(("P(dt_dnstap_identity:%s)\n", $2)); + free(cfg_parser->cfg->dnstap_identity); + cfg_parser->cfg->dnstap_identity = $2; + } + ; +dt_dnstap_version: VAR_DNSTAP_VERSION STRING_ARG + { + OUTYY(("P(dt_dnstap_version:%s)\n", $2)); + free(cfg_parser->cfg->dnstap_version); + cfg_parser->cfg->dnstap_version = $2; + } + ; +dt_dnstap_log_resolver_query_messages: VAR_DNSTAP_LOG_RESOLVER_QUERY_MESSAGES STRING_ARG + { + OUTYY(("P(dt_dnstap_log_resolver_query_messages:%s)\n", $2)); + if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) + yyerror("expected yes or no."); + else cfg_parser->cfg->dnstap_log_resolver_query_messages = + (strcmp($2, "yes")==0); + } + ; +dt_dnstap_log_resolver_response_messages: VAR_DNSTAP_LOG_RESOLVER_RESPONSE_MESSAGES STRING_ARG + { + OUTYY(("P(dt_dnstap_log_resolver_response_messages:%s)\n", $2)); + if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) + yyerror("expected yes or no."); + else cfg_parser->cfg->dnstap_log_resolver_response_messages = + (strcmp($2, "yes")==0); + } + ; +dt_dnstap_log_client_query_messages: VAR_DNSTAP_LOG_CLIENT_QUERY_MESSAGES STRING_ARG + { + OUTYY(("P(dt_dnstap_log_client_query_messages:%s)\n", $2)); + if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) + yyerror("expected yes or no."); + else cfg_parser->cfg->dnstap_log_client_query_messages = + (strcmp($2, "yes")==0); + } + ; +dt_dnstap_log_client_response_messages: VAR_DNSTAP_LOG_CLIENT_RESPONSE_MESSAGES STRING_ARG + { + OUTYY(("P(dt_dnstap_log_client_response_messages:%s)\n", $2)); + if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) + yyerror("expected yes or no."); + else cfg_parser->cfg->dnstap_log_client_response_messages = + (strcmp($2, "yes")==0); + } + ; +dt_dnstap_log_forwarder_query_messages: VAR_DNSTAP_LOG_FORWARDER_QUERY_MESSAGES STRING_ARG + { + OUTYY(("P(dt_dnstap_log_forwarder_query_messages:%s)\n", $2)); + if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) + yyerror("expected yes or no."); + else cfg_parser->cfg->dnstap_log_forwarder_query_messages = + (strcmp($2, "yes")==0); + } + ; +dt_dnstap_log_forwarder_response_messages: VAR_DNSTAP_LOG_FORWARDER_RESPONSE_MESSAGES STRING_ARG + { + OUTYY(("P(dt_dnstap_log_forwarder_response_messages:%s)\n", $2)); + if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) + yyerror("expected yes or no."); + else cfg_parser->cfg->dnstap_log_forwarder_response_messages = + (strcmp($2, "yes")==0); + } + ; pythonstart: VAR_PYTHON { OUTYY(("\nP(python:)\n")); diff --git a/usr.sbin/unbound/util/data/dname.c b/usr.sbin/unbound/util/data/dname.c index 76f2e645826..d43bbf6d240 100644 --- a/usr.sbin/unbound/util/data/dname.c +++ b/usr.sbin/unbound/util/data/dname.c @@ -114,8 +114,8 @@ query_dname_compare(register uint8_t* d1, register uint8_t* d2) while(lab1--) { /* compare bytes first for speed */ if(*d1 != *d2 && - tolower((int)*d1) != tolower((int)*d2)) { - if(tolower((int)*d1) < tolower((int)*d2)) + tolower((unsigned char)*d1) != tolower((unsigned char)*d2)) { + if(tolower((unsigned char)*d1) < tolower((unsigned char)*d2)) return -1; return 1; } @@ -138,7 +138,7 @@ query_dname_tolower(uint8_t* dname) while(labellen) { dname++; while(labellen--) { - *dname = (uint8_t)tolower((int)*dname); + *dname = (uint8_t)tolower((unsigned char)*dname); dname++; } labellen = *dname; @@ -167,7 +167,7 @@ pkt_dname_tolower(sldns_buffer* pkt, uint8_t* dname) if(dname+lablen >= sldns_buffer_end(pkt)) return; while(lablen--) { - *dname = (uint8_t)tolower((int)*dname); + *dname = (uint8_t)tolower((unsigned char)*dname); dname++; } if(dname >= sldns_buffer_end(pkt)) @@ -256,8 +256,8 @@ dname_pkt_compare(sldns_buffer* pkt, uint8_t* d1, uint8_t* d2) log_assert(len1 == len2 && len1 != 0); /* compare labels */ while(len1--) { - if(tolower((int)*d1++) != tolower((int)*d2++)) { - if(tolower((int)d1[-1]) < tolower((int)d2[-1])) + if(tolower((unsigned char)*d1++) != tolower((unsigned char)*d2++)) { + if(tolower((unsigned char)d1[-1]) < tolower((unsigned char)d2[-1])) return -1; return 1; } @@ -282,7 +282,7 @@ dname_query_hash(uint8_t* dname, hashvalue_t h) labuf[0] = lablen; i=0; while(lablen--) - labuf[++i] = (uint8_t)tolower((int)*dname++); + labuf[++i] = (uint8_t)tolower((unsigned char)*dname++); h = hashlittle(labuf, labuf[0] + 1, h); lablen = *dname++; } @@ -310,7 +310,7 @@ dname_pkt_hash(sldns_buffer* pkt, uint8_t* dname, hashvalue_t h) labuf[0] = lablen; i=0; while(lablen--) - labuf[++i] = (uint8_t)tolower((int)*dname++); + labuf[++i] = (uint8_t)tolower((unsigned char)*dname++); h = hashlittle(labuf, labuf[0] + 1, h); lablen = *dname++; } @@ -423,8 +423,8 @@ static int memlowercmp(uint8_t* p1, uint8_t* p2, uint8_t len) { while(len--) { - if(*p1 != *p2 && tolower((int)*p1) != tolower((int)*p2)) { - if(tolower((int)*p1) < tolower((int)*p2)) + if(*p1 != *p2 && tolower((unsigned char)*p1) != tolower((unsigned char)*p2)) { + if(tolower((unsigned char)*p1) < tolower((unsigned char)*p2)) return -1; return 1; } @@ -480,10 +480,10 @@ dname_lab_cmp(uint8_t* d1, int labs1, uint8_t* d2, int labs2, int* mlabs) * lastdiff = c; * lastmlabs = atlabel; } apart from d1++,d2++ */ while(len1) { - if(*d1 != *d2 && tolower((int)*d1) - != tolower((int)*d2)) { - if(tolower((int)*d1) < - tolower((int)*d2)) { + if(*d1 != *d2 && tolower((unsigned char)*d1) + != tolower((unsigned char)*d2)) { + if(tolower((unsigned char)*d1) < + tolower((unsigned char)*d2)) { lastdiff = -1; lastmlabs = atlabel; d1 += len1; @@ -561,7 +561,7 @@ void dname_str(uint8_t* dname, char* str) return; } while(lablen--) { - if(isalnum((int)*dname) + if(isalnum((unsigned char)*dname) || *dname == '-' || *dname == '_' || *dname == '*') *s++ = *(char*)dname++; diff --git a/usr.sbin/unbound/util/data/packed_rrset.h b/usr.sbin/unbound/util/data/packed_rrset.h index 4b0ef80cd74..5d7990a2b0b 100644 --- a/usr.sbin/unbound/util/data/packed_rrset.h +++ b/usr.sbin/unbound/util/data/packed_rrset.h @@ -189,7 +189,7 @@ enum sec_status { * o base struct * o rr_len size_t array * o rr_data uint8_t* array - * o rr_ttl uint32_t array (after size_t and ptrs because those may be + * o rr_ttl time_t array (after size_t and ptrs because those may be * 64bit and this array before those would make them unaligned). * Since the stuff before is 32/64bit, rr_ttl is 32 bit aligned. * o rr_data rdata wireformats diff --git a/usr.sbin/unbound/util/iana_ports.inc b/usr.sbin/unbound/util/iana_ports.inc index 252203033ff..ff971293fe9 100644 --- a/usr.sbin/unbound/util/iana_ports.inc +++ b/usr.sbin/unbound/util/iana_ports.inc @@ -650,6 +650,7 @@ 780, 800, 801, +802, 810, 828, 829, @@ -935,7 +936,6 @@ 1273, 1274, 1275, -1276, 1277, 1278, 1279, @@ -2016,7 +2016,6 @@ 2367, 2368, 2370, -2371, 2372, 2381, 2382, @@ -2486,7 +2485,6 @@ 2852, 2853, 2854, -2855, 2856, 2857, 2858, @@ -3443,7 +3441,6 @@ 3838, 3839, 3840, -3841, 3842, 3843, 3844, @@ -3798,6 +3795,7 @@ 4326, 4327, 4328, +4333, 4340, 4341, 4342, @@ -3965,6 +3963,8 @@ 4784, 4785, 4789, +4790, +4791, 4800, 4801, 4802, @@ -4002,6 +4002,7 @@ 4899, 4900, 4914, +4936, 4937, 4940, 4941, @@ -4073,6 +4074,7 @@ 5072, 5073, 5074, +5078, 5079, 5080, 5081, @@ -4157,6 +4159,7 @@ 5315, 5343, 5344, +5349, 5350, 5351, 5352, @@ -4223,6 +4226,7 @@ 5463, 5464, 5465, +5474, 5500, 5501, 5502, @@ -4276,6 +4280,7 @@ 5682, 5683, 5684, +5687, 5688, 5689, 5713, @@ -4352,6 +4357,7 @@ 6072, 6073, 6074, +6081, 6082, 6083, 6085, @@ -4632,6 +4638,7 @@ 7560, 7566, 7570, +7574, 7588, 7624, 7627, @@ -4686,6 +4693,7 @@ 7913, 7932, 7933, +7962, 7967, 7979, 7980, @@ -5017,6 +5025,7 @@ 10252, 10260, 10288, +10439, 10500, 10540, 10541, @@ -5050,6 +5059,7 @@ 11321, 11367, 11371, +11430, 11600, 11720, 11723, @@ -5144,6 +5154,7 @@ 17007, 17185, 17219, +17220, 17221, 17222, 17234, @@ -5170,6 +5181,7 @@ 18881, 18888, 19000, +19007, 19191, 19194, 19283, @@ -5249,6 +5261,7 @@ 24386, 24465, 24554, +24577, 24676, 24677, 24678, diff --git a/usr.sbin/unbound/util/locks.h b/usr.sbin/unbound/util/locks.h index d63e5f03201..3776912aaca 100644 --- a/usr.sbin/unbound/util/locks.h +++ b/usr.sbin/unbound/util/locks.h @@ -55,8 +55,10 @@ * Also thread creation and deletion functions are defined here. */ +/* if you define your own LOCKRET before including locks.h, you can get most + * locking functions without the dependency on log_err. */ +#ifndef LOCKRET #include "util/log.h" - /** * The following macro is used to check the return value of the * pthread calls. They return 0 on success and an errno on error. @@ -68,6 +70,7 @@ log_err("%s at %d could not " #func ": %s", \ __FILE__, __LINE__, strerror(lockret_err)); \ } while(0) +#endif /** DEBUG: use thread debug whenever possible */ #if defined(HAVE_PTHREAD) && defined(HAVE_PTHREAD_SPINLOCK_T) && defined(ENABLE_LOCK_CHECKS) diff --git a/usr.sbin/unbound/util/log.c b/usr.sbin/unbound/util/log.c index 39d3118a000..f90efa71c75 100644 --- a/usr.sbin/unbound/util/log.c +++ b/usr.sbin/unbound/util/log.c @@ -68,6 +68,10 @@ static FILE* logfile = 0; static int key_created = 0; /** pthread key for thread ids in logfile */ static ub_thread_key_t logkey; +#ifndef THREADS_DISABLED +/** pthread mutex to protect FILE* */ +static lock_quick_t log_lock; +#endif /** the identity of this executable/process */ static const char* ident="unbound"; #if defined(HAVE_SYSLOG_H) || defined(UB_ON_WINDOWS) @@ -86,14 +90,19 @@ log_init(const char* filename, int use_syslog, const char* chrootdir) if(!key_created) { key_created = 1; ub_thread_key_create(&logkey, NULL); + lock_quick_init(&log_lock); } + lock_quick_lock(&log_lock); if(logfile #if defined(HAVE_SYSLOG_H) || defined(UB_ON_WINDOWS) || logging_to_syslog #endif - ) - verbose(VERB_QUERY, "switching log to %s", - use_syslog?"syslog":(filename&&filename[0]?filename:"stderr")); + ) { + lock_quick_unlock(&log_lock); /* verbose() needs the lock */ + verbose(VERB_QUERY, "switching log to %s", + use_syslog?"syslog":(filename&&filename[0]?filename:"stderr")); + lock_quick_lock(&log_lock); + } if(logfile && logfile != stderr) fclose(logfile); #ifdef HAVE_SYSLOG_H @@ -106,6 +115,7 @@ log_init(const char* filename, int use_syslog, const char* chrootdir) * chroot and no longer be able to access dev/log and so on */ openlog(ident, LOG_NDELAY, LOG_DAEMON); logging_to_syslog = 1; + lock_quick_unlock(&log_lock); return; } #elif defined(UB_ON_WINDOWS) @@ -114,11 +124,13 @@ log_init(const char* filename, int use_syslog, const char* chrootdir) } if(use_syslog) { logging_to_syslog = 1; + lock_quick_unlock(&log_lock); return; } #endif /* HAVE_SYSLOG_H */ if(!filename || !filename[0]) { logfile = stderr; + lock_quick_unlock(&log_lock); return; } /* open the file for logging */ @@ -127,6 +139,7 @@ log_init(const char* filename, int use_syslog, const char* chrootdir) filename += strlen(chrootdir); f = fopen(filename, "a"); if(!f) { + lock_quick_unlock(&log_lock); log_err("Could not open logfile %s: %s", filename, strerror(errno)); return; @@ -136,11 +149,14 @@ log_init(const char* filename, int use_syslog, const char* chrootdir) setvbuf(f, NULL, (int)_IOLBF, 0); #endif logfile = f; + lock_quick_unlock(&log_lock); } void log_file(FILE *f) { + lock_quick_lock(&log_lock); logfile = f; + lock_quick_unlock(&log_lock); } void log_thread_set(int* num) @@ -211,7 +227,11 @@ log_vmsg(int pri, const char* type, return; } #endif /* HAVE_SYSLOG_H */ - if(!logfile) return; + lock_quick_lock(&log_lock); + if(!logfile) { + lock_quick_unlock(&log_lock); + return; + } if(log_now) now = (time_t)*log_now; else now = (time_t)time(NULL); @@ -236,6 +256,7 @@ log_vmsg(int pri, const char* type, /* line buffering does not work on windows */ fflush(logfile); #endif + lock_quick_unlock(&log_lock); } /** diff --git a/usr.sbin/unbound/util/mini_event.h b/usr.sbin/unbound/util/mini_event.h index 58bbc807393..1a5bcb445ae 100644 --- a/usr.sbin/unbound/util/mini_event.h +++ b/usr.sbin/unbound/util/mini_event.h @@ -58,6 +58,21 @@ #define HAVE_EVENT_BASE_FREE #endif +/* redefine to use our own namespace so that on platforms where + * linkers crosslink library-private symbols with other symbols, it works */ +#define event_init minievent_init +#define event_get_version minievent_get_version +#define event_get_method minievent_get_method +#define event_base_dispatch minievent_base_dispatch +#define event_base_loopexit minievent_base_loopexit +#define event_base_free minievent_base_free +#define event_set minievent_set +#define event_base_set minievent_base_set +#define event_add minievent_add +#define event_del minievent_del +#define signal_add minisignal_add +#define signal_del minisignal_del + /** event timeout */ #define EV_TIMEOUT 0x01 /** event fd readable */ diff --git a/usr.sbin/unbound/util/net_help.h b/usr.sbin/unbound/util/net_help.h index b92dd40e85d..54f4c9c0e7c 100644 --- a/usr.sbin/unbound/util/net_help.h +++ b/usr.sbin/unbound/util/net_help.h @@ -157,6 +157,16 @@ void log_name_addr(enum verbosity_value v, const char* str, uint8_t* zone, struct sockaddr_storage* addr, socklen_t addrlen); /** + * Log errno and addr. + * @param str: descriptive string printed with it. + * @param err: errno string to print, i.e. strerror(errno). + * @param addr: the sockaddr to print. Can be ip4 or ip6. + * @param addrlen: length of addr. + */ +void log_err_addr(const char* str, const char* err, + struct sockaddr_storage* addr, socklen_t addrlen); + +/** * Convert address string, with "@port" appendix, to sockaddr. * Uses DNS port by default. * @param str: the string diff --git a/usr.sbin/unbound/util/storage/lookup3.c b/usr.sbin/unbound/util/storage/lookup3.c index 7596033bdee..de288587bdb 100644 --- a/usr.sbin/unbound/util/storage/lookup3.c +++ b/usr.sbin/unbound/util/storage/lookup3.c @@ -53,15 +53,16 @@ on 1 byte), but shoehorning those bytes into integers efficiently is messy. #ifdef HAVE_SYS_TYPES_H # include <sys/types.h> /* attempt to define endianness (solaris) */ #endif -#ifdef linux -# include <endian.h> /* attempt to define endianness */ +#if defined(linux) || defined(__OpenBSD__) +# ifdef HAVE_ENDIAN_H +# include <endian.h> /* attempt to define endianness */ +# else +# include <machine/endian.h> /* on older OpenBSD */ +# endif #endif #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__) #include <sys/endian.h> /* attempt to define endianness */ #endif -#ifdef __OpenBSD__ -#include <machine/endian.h> /* attempt to define endianness */ -#endif /* random initial value */ static uint32_t raninit = (uint32_t)0xdeadbeef; diff --git a/usr.sbin/unbound/util/storage/slabhash.c b/usr.sbin/unbound/util/storage/slabhash.c index 128edd84ad7..0618b4c7295 100644 --- a/usr.sbin/unbound/util/storage/slabhash.c +++ b/usr.sbin/unbound/util/storage/slabhash.c @@ -211,9 +211,21 @@ void slabhash_setmarkdel(struct slabhash* sl, lruhash_markdelfunc_t md) } void slabhash_traverse(struct slabhash* sh, int wr, - void (*func)(struct lruhash_entry*, void*), void* arg) + void (*func)(struct lruhash_entry*, void*), void* arg) { size_t i; for(i=0; i<sh->size; i++) lruhash_traverse(sh->array[i], wr, func, arg); } + +size_t count_slabhash_entries(struct slabhash* sh) +{ + size_t slab, cnt = 0; + + for(slab=0; slab<sh->size; slab++) { + lock_quick_lock(&sh->array[slab]->lock); + cnt += sh->array[slab]->num; + lock_quick_unlock(&sh->array[slab]->lock); + } + return cnt; +} diff --git a/usr.sbin/unbound/util/storage/slabhash.h b/usr.sbin/unbound/util/storage/slabhash.h index cf968f9653d..031a9da0fac 100644 --- a/usr.sbin/unbound/util/storage/slabhash.h +++ b/usr.sbin/unbound/util/storage/slabhash.h @@ -184,6 +184,13 @@ void slabhash_setmarkdel(struct slabhash* table, lruhash_markdelfunc_t md); void slabhash_traverse(struct slabhash* table, int wr, void (*func)(struct lruhash_entry*, void*), void* arg); +/* + * Count entries in slabhash. + * @param table: slabbed hash table; + * @return the number of items + */ +size_t count_slabhash_entries(struct slabhash* table); + /* --- test representation --- */ /** test structure contains test key */ struct slabhash_testkey { diff --git a/usr.sbin/unbound/util/winsock_event.h b/usr.sbin/unbound/util/winsock_event.h index 40892c14b1c..f6426574347 100644 --- a/usr.sbin/unbound/util/winsock_event.h +++ b/usr.sbin/unbound/util/winsock_event.h @@ -90,6 +90,21 @@ #define HAVE_EVENT_BASE_FREE #endif +/* redefine the calls to different names so that there is no name + * collision with other code that uses libevent names. (that uses libunbound)*/ +#define event_init winsockevent_init +#define event_get_version winsockevent_get_version +#define event_get_method winsockevent_get_method +#define event_base_dispatch winsockevent_base_dispatch +#define event_base_loopexit winsockevent_base_loopexit +#define event_base_free winsockevent_base_free +#define event_set winsockevent_set +#define event_base_set winsockevent_base_set +#define event_add winsockevent_add +#define event_del winsockevent_del +#define signal_add winsocksignal_add +#define signal_del winsocksignal_del + /** event timeout */ #define EV_TIMEOUT 0x01 /** event fd readable */ diff --git a/usr.sbin/unbound/validator/autotrust.c b/usr.sbin/unbound/validator/autotrust.c index a597633828f..5e1dc4ef3cd 100644 --- a/usr.sbin/unbound/validator/autotrust.c +++ b/usr.sbin/unbound/validator/autotrust.c @@ -902,13 +902,13 @@ static int handle_origin(char* line, uint8_t** origin, size_t* origin_len) { size_t len = 0; - while(isspace((int)*line)) + while(isspace((unsigned char)*line)) line++; if(strncmp(line, "$ORIGIN", 7) != 0) return 0; free(*origin); line += 7; - while(isspace((int)*line)) + while(isspace((unsigned char)*line)) line++; *origin = sldns_str2wire_dname(line, &len); *origin_len = len; diff --git a/usr.sbin/unbound/validator/val_anchor.c b/usr.sbin/unbound/validator/val_anchor.c index a4adfe2d9dd..3a67fff454a 100644 --- a/usr.sbin/unbound/validator/val_anchor.c +++ b/usr.sbin/unbound/validator/val_anchor.c @@ -563,7 +563,7 @@ readkeyword_bindfile(FILE* in, sldns_buffer* buf, int* line, int comments) /* not a comment, complete the keyword */ if(numdone > 0) { /* check same type */ - if(isspace(c)) { + if(isspace((unsigned char)c)) { ungetc(c, in); return numdone; } @@ -582,12 +582,12 @@ readkeyword_bindfile(FILE* in, sldns_buffer* buf, int* line, int comments) } sldns_buffer_write_u8(buf, (uint8_t)c); numdone++; - if(isspace(c)) { + if(isspace((unsigned char)c)) { /* collate whitespace into ' ' */ while((c = getc(in)) != EOF ) { if(c == '\n') (*line)++; - if(!isspace(c)) { + if(!isspace((unsigned char)c)) { ungetc(c, in); break; } @@ -607,7 +607,7 @@ skip_to_special(FILE* in, sldns_buffer* buf, int* line, int spec) int rdlen; sldns_buffer_clear(buf); while((rdlen=readkeyword_bindfile(in, buf, line, 1))) { - if(rdlen == 1 && isspace((int)*sldns_buffer_begin(buf))) { + if(rdlen == 1 && isspace((unsigned char)*sldns_buffer_begin(buf))) { sldns_buffer_clear(buf); continue; } @@ -648,7 +648,7 @@ process_bind_contents(struct val_anchors* anchors, sldns_buffer* buf, sldns_buffer_clear(buf); while((rdlen=readkeyword_bindfile(in, buf, line, comments))) { if(rdlen == 1 && sldns_buffer_position(buf) == 1 - && isspace((int)*sldns_buffer_begin(buf))) { + && isspace((unsigned char)*sldns_buffer_begin(buf))) { /* starting whitespace is removed */ sldns_buffer_clear(buf); continue; @@ -703,7 +703,7 @@ process_bind_contents(struct val_anchors* anchors, sldns_buffer* buf, } return 1; } else if(rdlen == 1 && - isspace((int)sldns_buffer_current(buf)[-1])) { + isspace((unsigned char)sldns_buffer_current(buf)[-1])) { /* leave whitespace here */ } else { /* not space or whatnot, so actual content */ diff --git a/usr.sbin/unbound/validator/val_nsec3.c b/usr.sbin/unbound/validator/val_nsec3.c index fe5091c0a38..548daf2bf0a 100644 --- a/usr.sbin/unbound/validator/val_nsec3.c +++ b/usr.sbin/unbound/validator/val_nsec3.c @@ -731,8 +731,8 @@ label_compare_lower(uint8_t* lab1, uint8_t* lab2, size_t lablen) { size_t i; for(i=0; i<lablen; i++) { - if(tolower((int)*lab1) != tolower((int)*lab2)) { - if(tolower((int)*lab1) < tolower((int)*lab2)) + if(tolower((unsigned char)*lab1) != tolower((unsigned char)*lab2)) { + if(tolower((unsigned char)*lab1) < tolower((unsigned char)*lab2)) return -1; return 1; } |