summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDag-Erling Smørgrav <des@FreeBSD.org>2019-06-30 15:01:11 +0000
committerDag-Erling Smørgrav <des@FreeBSD.org>2019-06-30 15:01:11 +0000
commit366b94c4a9552acfb560d3234aea0955ebc1eb8e (patch)
tree0bee3a4dbb699714374eeab0af43e63f1bf9672d
parent4713c21a1ac91081e50e474d11fcec002b43a562 (diff)
downloadsrc-test2-366b94c4a9552acfb560d3234aea0955ebc1eb8e.tar.gz
src-test2-366b94c4a9552acfb560d3234aea0955ebc1eb8e.zip
Notes
-rw-r--r--.gitignore14
-rw-r--r--.travis.yml16
-rw-r--r--README.md37
-rw-r--r--cachedb/cachedb.c13
-rw-r--r--config.h.in15
-rwxr-xr-xconfigure90
-rw-r--r--configure.ac38
-rw-r--r--contrib/fastrpz.patch321
-rw-r--r--daemon/unbound.c3
-rw-r--r--daemon/worker.c18
-rw-r--r--doc/Changelog165
-rw-r--r--doc/README2
-rw-r--r--doc/example.conf.in45
-rw-r--r--doc/libunbound.3.in4
-rw-r--r--doc/unbound-anchor.8.in2
-rw-r--r--doc/unbound-checkconf.8.in2
-rw-r--r--doc/unbound-control.8.in2
-rw-r--r--doc/unbound-host.1.in2
-rw-r--r--doc/unbound.8.in4
-rw-r--r--doc/unbound.conf.5.in7
-rw-r--r--doc/unbound.doxygen1
-rw-r--r--edns-subnet/subnetmod.c31
-rw-r--r--iterator/iter_utils.c13
-rw-r--r--iterator/iter_utils.h7
-rw-r--r--iterator/iterator.c11
-rw-r--r--libunbound/python/libunbound.i8
-rw-r--r--pythonmod/doc/examples/example0-1.py5
-rw-r--r--pythonmod/doc/examples/example0.rst19
-rw-r--r--pythonmod/examples/avahi-resolver.py567
-rw-r--r--pythonmod/examples/edns.py2
-rw-r--r--pythonmod/examples/inplace_callbacks.py2
-rw-r--r--pythonmod/interface.i132
-rw-r--r--services/authzone.c253
-rw-r--r--services/authzone.h7
-rw-r--r--services/cache/dns.c6
-rw-r--r--services/listen_dnsport.c29
-rw-r--r--services/mesh.c35
-rw-r--r--services/outside_network.c104
-rw-r--r--services/outside_network.h4
-rw-r--r--testcode/fake_event.c3
-rw-r--r--testdata/auth_nsec3_ent.rpl224
-rw-r--r--testdata/auth_nsec3_wild.rpl27
-rw-r--r--util/alloc.c8
-rw-r--r--util/data/msgreply.h2
-rw-r--r--util/fptr_wlist.c1
-rw-r--r--util/iana_ports.inc2
-rw-r--r--util/net_help.c17
-rw-r--r--util/netevent.c98
-rw-r--r--util/storage/lookup3.c8
-rw-r--r--util/ub_event.c14
50 files changed, 1980 insertions, 460 deletions
diff --git a/.gitignore b/.gitignore
index f4527fd812eb..93de1c215494 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,6 +4,7 @@
/Makefile
/autom4te.cache/
/config.h
+/config.h.in~
/config.log
/config.status
/dnstap/dnstap_config.h
@@ -18,6 +19,7 @@
/doc/unbound.conf.5
/libtool
/libunbound.la
+/_unbound.la
/smallapp/unbound-control-setup.sh
/unbound
/unbound-anchor
@@ -39,4 +41,14 @@
/contrib/libunbound.pc
/contrib/unbound.service
/contrib/unbound.socket
-
+/dnstap/dnstap.pb-c.c
+/dnstap/dnstap.pb-c.h
+/libunbound/python/libunbound_wrap.c
+/libunbound/python/unbound.py
+/pythonmod/interface.h
+/pythonmod/unboundmodule.py
+/testdata/result.*
+/testdata/.done-*
+/testdata/.perfstats.txt
+/doc/html
+/doc/xml
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 000000000000..45a7cb153501
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,16 @@
+sudo: false
+language: c
+compiler:
+ - gcc
+addons:
+ apt:
+ packages:
+ - libssl-dev
+ - libevent-dev
+ - libexpat-dev
+ - clang
+script:
+ - ./configure --enable-debug --disable-flto
+ - make
+ - make test
+ - (cd testdata/clang-analysis.tdir; bash clang-analysis.test)
diff --git a/README.md b/README.md
new file mode 100644
index 000000000000..b3d3424c99ff
--- /dev/null
+++ b/README.md
@@ -0,0 +1,37 @@
+# Unbound
+
+[![Travis Build Status](https://travis-ci.org/NLnetLabs/unbound.svg?branch=master)](https://travis-ci.org/NLnetLabs/unbound)
+[![Packaging status](https://repology.org/badge/tiny-repos/unbound.svg)](https://repology.org/project/unbound/versions)
+
+Unbound is a validating, recursive, caching DNS resolver. It is designed to be
+fast and lean and incorporates modern features based on open standards. If you
+have any feedback, we would love to hear from you. Don’t hesitate to
+[create an issue on Github](https://github.com/NLnetLabs/unbound/issues/new)
+or post a message on the [Unbound mailing list](https://nlnetlabs.nl/mailman/listinfo/unbound-users).
+You can lean more about Unbound by reading our
+[documentation](https://nlnetlabs.nl/documentation/unbound/).
+
+## Compiling
+
+Make sure you have the C toolchain, OpenSSL and its include files, and libexpat
+installed. Unbound can be compiled and installed using:
+
+```
+./configure && make && make install
+```
+
+You can use libevent if you want. libevent is useful when using many (10000)
+outgoing ports. By default max 256 ports are opened at the same time and the
+builtin alternative is equally capable and a little faster.
+
+Use the `--with-libevent=dir` configure option to compile Unbound with libevent
+support.
+
+## Unbound configuration
+
+All of Unbound's configuration options are described in the man pages, which
+will be installed and are available on the Unbound
+[documentation page](https://nlnetlabs.nl/documentation/unbound/).
+
+An example configuration file is located in
+[doc/example.conf](https://github.com/NLnetLabs/unbound/blob/master/doc/example.conf.in).
diff --git a/cachedb/cachedb.c b/cachedb/cachedb.c
index 5a179a2bb419..08389a4323d4 100644
--- a/cachedb/cachedb.c
+++ b/cachedb/cachedb.c
@@ -72,6 +72,19 @@
# define be64toh(x) OSSwapBigToHostInt64(x)
#endif
+/* Some compilers do not define __BYTE_ORDER__, like IBM XLC on AIX */
+#ifndef be64toh
+#if defined(__sun) || defined(_AIX)
+# if __BIG_ENDIAN__
+# define be64toh(n) (n)
+# define htobe64(n) (n)
+# else
+# define be64toh(n) (((uint64_t)htonl((n) & 0xFFFFFFFF) << 32) | htonl((n) >> 32))
+# define htobe64(n) (((uint64_t)htonl((n) & 0xFFFFFFFF) << 32) | htonl((n) >> 32))
+# endif
+#endif
+#endif /* be64toh */
+
/** the unit test testframe for cachedb, its module state contains
* a cache for a couple queries (in memory). */
struct testframe_moddata {
diff --git a/config.h.in b/config.h.in
index f0eb7d6aa9f8..e2d3116cccf0 100644
--- a/config.h.in
+++ b/config.h.in
@@ -86,6 +86,10 @@
if you don't. */
#undef HAVE_DECL_ARC4RANDOM_UNIFORM
+/* Define to 1 if you have the declaration of `evsignal_assign', and to 0 if
+ you don't. */
+#undef HAVE_DECL_EVSIGNAL_ASSIGN
+
/* Define to 1 if you have the declaration of `inet_ntop', and to 0 if you
don't. */
#undef HAVE_DECL_INET_NTOP
@@ -166,6 +170,9 @@
/* Define to 1 if you have the `ERR_load_crypto_strings' function. */
#undef HAVE_ERR_LOAD_CRYPTO_STRINGS
+/* Define to 1 if you have the `event_assign' function. */
+#undef HAVE_EVENT_ASSIGN
+
/* Define to 1 if you have the `event_base_free' function. */
#undef HAVE_EVENT_BASE_FREE
@@ -406,7 +413,7 @@
/* Define to 1 if you have the `RAND_cleanup' function. */
#undef HAVE_RAND_CLEANUP
-/* Define to 1 if you have the `reallocarray' function. */
+/* If we have reallocarray(3) */
#undef HAVE_REALLOCARRAY
/* Define to 1 if you have the `recvmsg' function. */
@@ -965,8 +972,14 @@
+#ifndef _OPENBSD_SOURCE
+#define _OPENBSD_SOURCE 1
+#endif
+
#ifndef UNBOUND_DEBUG
+# ifndef NDEBUG
# define NDEBUG
+# endif
#endif
/** Use small-ldns codebase */
diff --git a/configure b/configure
index 45a251285273..21721689dc3a 100755
--- a/configure
+++ b/configure
@@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for unbound 1.9.1.
+# Generated by GNU Autoconf 2.69 for unbound 1.9.2.
#
# Report bugs to <unbound-bugs@nlnetlabs.nl>.
#
@@ -590,8 +590,8 @@ MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='unbound'
PACKAGE_TARNAME='unbound'
-PACKAGE_VERSION='1.9.1'
-PACKAGE_STRING='unbound 1.9.1'
+PACKAGE_VERSION='1.9.2'
+PACKAGE_STRING='unbound 1.9.2'
PACKAGE_BUGREPORT='unbound-bugs@nlnetlabs.nl'
PACKAGE_URL=''
@@ -1440,7 +1440,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
-\`configure' configures unbound 1.9.1 to adapt to many kinds of systems.
+\`configure' configures unbound 1.9.2 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1505,7 +1505,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
- short | recursive ) echo "Configuration of unbound 1.9.1:";;
+ short | recursive ) echo "Configuration of unbound 1.9.2:";;
esac
cat <<\_ACEOF
@@ -1722,7 +1722,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
-unbound configure 1.9.1
+unbound configure 1.9.2
generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc.
@@ -2431,7 +2431,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
-It was created by unbound $as_me 1.9.1, which was
+It was created by unbound $as_me 1.9.2, which was
generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@
@@ -2783,11 +2783,11 @@ UNBOUND_VERSION_MAJOR=1
UNBOUND_VERSION_MINOR=9
-UNBOUND_VERSION_MICRO=1
+UNBOUND_VERSION_MICRO=2
LIBUNBOUND_CURRENT=9
-LIBUNBOUND_REVISION=1
+LIBUNBOUND_REVISION=2
LIBUNBOUND_AGE=1
# 1.0.0 had 0:12:0
# 1.0.1 had 0:13:0
@@ -2856,6 +2856,7 @@ LIBUNBOUND_AGE=1
# 1.8.3 had 8:3:0
# 1.9.0 had 9:0:1 # add ub_ctx_set_tls
# 1.9.1 had 9:1:1
+# 1.9.2 had 9:2:1
# Current -- the number of the binary API that we're implementing
# Revision -- which iteration of the implementation of the binary
@@ -19012,6 +19013,35 @@ _ACEOF
fi
done
# only in libev. (tested on 4.00)
+ for ac_func in event_assign
+do :
+ ac_fn_c_check_func "$LINENO" "event_assign" "ac_cv_func_event_assign"
+if test "x$ac_cv_func_event_assign" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_EVENT_ASSIGN 1
+_ACEOF
+
+fi
+done
+ # in libevent, for thread-safety
+ ac_fn_c_check_decl "$LINENO" "evsignal_assign" "ac_cv_have_decl_evsignal_assign" "$ac_includes_default
+#ifdef HAVE_EVENT_H
+# include <event.h>
+#else
+# include \"event2/event.h\"
+#endif
+
+"
+if test "x$ac_cv_have_decl_evsignal_assign" = xyes; then :
+ ac_have_decl=1
+else
+ ac_have_decl=0
+fi
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_DECL_EVSIGNAL_ASSIGN $ac_have_decl
+_ACEOF
+
PC_LIBEVENT_DEPENDENCY="libevent"
if test -n "$BAK_LDFLAGS_SET"; then
@@ -20114,20 +20144,44 @@ fi
LIBOBJ_WITHOUT_CTIMEARC4="$LIBOBJS"
-ac_fn_c_check_func "$LINENO" "reallocarray" "ac_cv_func_reallocarray"
-if test "x$ac_cv_func_reallocarray" = xyes; then :
- $as_echo "#define HAVE_REALLOCARRAY 1" >>confdefs.h
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for reallocarray" >&5
+$as_echo_n "checking for reallocarray... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$ac_includes_default
+
+#ifndef _OPENBSD_SOURCE
+#define _OPENBSD_SOURCE 1
+#endif
+#include <stdlib.h>
+int main(void) {
+ void* p = reallocarray(NULL, 10, 100);
+ free(p);
+ return 0;
+}
+
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+$as_echo "#define HAVE_REALLOCARRAY 1" >>confdefs.h
+
else
- case " $LIBOBJS " in
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ case " $LIBOBJS " in
*" reallocarray.$ac_objext "* ) ;;
*) LIBOBJS="$LIBOBJS reallocarray.$ac_objext"
;;
esac
-fi
-
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
if test "$USE_NSS" = "no"; then
ac_fn_c_check_func "$LINENO" "arc4random" "ac_cv_func_arc4random"
if test "x$ac_cv_func_arc4random" = xyes; then :
@@ -21150,7 +21204,7 @@ _ACEOF
-version=1.9.1
+version=1.9.2
date=`date +'%b %e, %Y'`
@@ -21669,7 +21723,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
-This file was extended by unbound $as_me 1.9.1, which was
+This file was extended by unbound $as_me 1.9.2, which was
generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -21735,7 +21789,7 @@ _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\
-unbound config.status 1.9.1
+unbound config.status 1.9.2
configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\"
diff --git a/configure.ac b/configure.ac
index ff6f05ad75a1..fc9448f51a09 100644
--- a/configure.ac
+++ b/configure.ac
@@ -11,14 +11,14 @@ sinclude(dnscrypt/dnscrypt.m4)
# must be numbers. ac_defun because of later processing
m4_define([VERSION_MAJOR],[1])
m4_define([VERSION_MINOR],[9])
-m4_define([VERSION_MICRO],[1])
+m4_define([VERSION_MICRO],[2])
AC_INIT(unbound, m4_defn([VERSION_MAJOR]).m4_defn([VERSION_MINOR]).m4_defn([VERSION_MICRO]), unbound-bugs@nlnetlabs.nl, unbound)
AC_SUBST(UNBOUND_VERSION_MAJOR, [VERSION_MAJOR])
AC_SUBST(UNBOUND_VERSION_MINOR, [VERSION_MINOR])
AC_SUBST(UNBOUND_VERSION_MICRO, [VERSION_MICRO])
LIBUNBOUND_CURRENT=9
-LIBUNBOUND_REVISION=1
+LIBUNBOUND_REVISION=2
LIBUNBOUND_AGE=1
# 1.0.0 had 0:12:0
# 1.0.1 had 0:13:0
@@ -87,6 +87,7 @@ LIBUNBOUND_AGE=1
# 1.8.3 had 8:3:0
# 1.9.0 had 9:0:1 # add ub_ctx_set_tls
# 1.9.1 had 9:1:1
+# 1.9.2 had 9:2:1
# Current -- the number of the binary API that we're implementing
# Revision -- which iteration of the implementation of the binary
@@ -1199,6 +1200,14 @@ large outgoing port ranges. ])
AC_CHECK_FUNCS([event_base_get_method]) # only in libevent 1.4.3 and later
AC_CHECK_FUNCS([ev_loop]) # only in libev. (tested on 3.51)
AC_CHECK_FUNCS([ev_default_loop]) # only in libev. (tested on 4.00)
+ AC_CHECK_FUNCS([event_assign]) # in libevent, for thread-safety
+ AC_CHECK_DECLS([evsignal_assign], [], [], [AC_INCLUDES_DEFAULT
+#ifdef HAVE_EVENT_H
+# include <event.h>
+#else
+# include "event2/event.h"
+#endif
+ ])
PC_LIBEVENT_DEPENDENCY="libevent"
AC_SUBST(PC_LIBEVENT_DEPENDENCY)
if test -n "$BAK_LDFLAGS_SET"; then
@@ -1438,7 +1447,24 @@ AC_REPLACE_FUNCS(explicit_bzero)
dnl without CTIME, ARC4-functions and without reallocarray.
LIBOBJ_WITHOUT_CTIMEARC4="$LIBOBJS"
AC_SUBST(LIBOBJ_WITHOUT_CTIMEARC4)
-AC_REPLACE_FUNCS(reallocarray)
+AC_MSG_CHECKING([for reallocarray])
+AC_LINK_IFELSE([AC_LANG_SOURCE(AC_INCLUDES_DEFAULT
+[[
+#ifndef _OPENBSD_SOURCE
+#define _OPENBSD_SOURCE 1
+#endif
+#include <stdlib.h>
+int main(void) {
+ void* p = reallocarray(NULL, 10, 100);
+ free(p);
+ return 0;
+}
+]])], [AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_REALLOCARRAY, 1, [If we have reallocarray(3)])
+], [
+ AC_MSG_RESULT(no)
+ AC_LIBOBJ(reallocarray)
+])
if test "$USE_NSS" = "no"; then
AC_REPLACE_FUNCS(arc4random)
AC_REPLACE_FUNCS(arc4random_uniform)
@@ -1651,8 +1677,14 @@ AHX_CONFIG_EXT_FLAGS
dnl includes
[
+#ifndef _OPENBSD_SOURCE
+#define _OPENBSD_SOURCE 1
+#endif
+
#ifndef UNBOUND_DEBUG
+# ifndef NDEBUG
# define NDEBUG
+# endif
#endif
/** Use small-ldns codebase */
diff --git a/contrib/fastrpz.patch b/contrib/fastrpz.patch
index 0291ea3d81a4..d3d81b48c901 100644
--- a/contrib/fastrpz.patch
+++ b/contrib/fastrpz.patch
@@ -1,11 +1,11 @@
Description: based on the included patch contrib/fastrpz.patch
Author: fastrpz@farsightsecurity.com
---
-Index: unboundfastrpz/Makefile.in
-===================================================================
---- unboundfastrpz/Makefile.in (revision 5073)
-+++ unboundfastrpz/Makefile.in (working copy)
-@@ -23,6 +23,8 @@
+diff --git a/Makefile.in b/Makefile.in
+index 03a6347..6758bea 100644
+--- a/Makefile.in
++++ b/Makefile.in
+@@ -23,6 +23,8 @@ CHECKLOCK_SRC=testcode/checklocks.c
CHECKLOCK_OBJ=@CHECKLOCK_OBJ@
DNSTAP_SRC=@DNSTAP_SRC@
DNSTAP_OBJ=@DNSTAP_OBJ@
@@ -14,7 +14,7 @@ Index: unboundfastrpz/Makefile.in
DNSCRYPT_SRC=@DNSCRYPT_SRC@
DNSCRYPT_OBJ=@DNSCRYPT_OBJ@
WITH_PYTHONMODULE=@WITH_PYTHONMODULE@
-@@ -126,7 +128,7 @@
+@@ -126,7 +128,7 @@ validator/val_sigcrypt.c validator/val_utils.c dns64/dns64.c \
edns-subnet/edns-subnet.c edns-subnet/subnetmod.c \
edns-subnet/addrtree.c edns-subnet/subnet-whitelist.c \
cachedb/cachedb.c cachedb/redis.c respip/respip.c $(CHECKLOCK_SRC) \
@@ -23,7 +23,7 @@ Index: unboundfastrpz/Makefile.in
COMMON_OBJ_WITHOUT_NETCALL=dns.lo infra.lo rrset.lo dname.lo msgencode.lo \
as112.lo msgparse.lo msgreply.lo packed_rrset.lo iterator.lo iter_delegpt.lo \
iter_donotq.lo iter_fwd.lo iter_hints.lo iter_priv.lo iter_resptype.lo \
-@@ -139,7 +141,7 @@
+@@ -139,7 +141,7 @@ autotrust.lo val_anchor.lo \
validator.lo val_kcache.lo val_kentry.lo val_neg.lo val_nsec3.lo val_nsec.lo \
val_secalgo.lo val_sigcrypt.lo val_utils.lo dns64.lo cachedb.lo redis.lo authzone.lo \
$(SUBNET_OBJ) $(PYTHONMOD_OBJ) $(CHECKLOCK_OBJ) $(DNSTAP_OBJ) $(DNSCRYPT_OBJ) \
@@ -32,7 +32,7 @@ Index: unboundfastrpz/Makefile.in
COMMON_OBJ_WITHOUT_UB_EVENT=$(COMMON_OBJ_WITHOUT_NETCALL) netevent.lo listen_dnsport.lo \
outside_network.lo
COMMON_OBJ=$(COMMON_OBJ_WITHOUT_UB_EVENT) ub_event.lo
-@@ -405,6 +407,11 @@
+@@ -405,6 +407,11 @@ dnscrypt.lo dnscrypt.o: $(srcdir)/dnscrypt/dnscrypt.c config.h \
$(srcdir)/util/config_file.h $(srcdir)/util/log.h \
$(srcdir)/util/netevent.h
@@ -44,11 +44,11 @@ Index: unboundfastrpz/Makefile.in
# Python Module
pythonmod.lo pythonmod.o: $(srcdir)/pythonmod/pythonmod.c config.h \
pythonmod/interface.h \
-Index: unboundfastrpz/config.h.in
-===================================================================
---- unboundfastrpz/config.h.in (revision 5073)
-+++ unboundfastrpz/config.h.in (working copy)
-@@ -1293,4 +1293,11 @@
+diff --git a/config.h.in b/config.h.in
+index 74c14d1..a18f4ff 100644
+--- a/config.h.in
++++ b/config.h.in
+@@ -1305,4 +1305,11 @@ void *unbound_stat_realloc_log(void *ptr, size_t size, const char* file,
/** the version of unbound-control that this software implements */
#define UNBOUND_CONTROL_VERSION 1
@@ -61,11 +61,11 @@ Index: unboundfastrpz/config.h.in
+#undef FASTRPZ_LIB_OPEN
+/** turn on fastrpz response policy zones */
+#undef ENABLE_FASTRPZ
-Index: unboundfastrpz/configure.ac
-===================================================================
---- unboundfastrpz/configure.ac (revision 5073)
-+++ unboundfastrpz/configure.ac (working copy)
-@@ -6,6 +6,7 @@
+diff --git a/configure.ac b/configure.ac
+index abbecf0..6454274 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -6,6 +6,7 @@ sinclude(ax_pthread.m4)
sinclude(acx_python.m4)
sinclude(ac_pkg_swig.m4)
sinclude(dnstap/dnstap.m4)
@@ -73,7 +73,7 @@ Index: unboundfastrpz/configure.ac
sinclude(dnscrypt/dnscrypt.m4)
# must be numbers. ac_defun because of later processing
-@@ -1575,6 +1576,9 @@
+@@ -1586,6 +1587,9 @@ case "$enable_ipsecmod" in
;;
esac
@@ -83,10 +83,10 @@ Index: unboundfastrpz/configure.ac
AC_MSG_CHECKING([if ${MAKE:-make} supports $< with implicit rule in scope])
# on openBSD, the implicit rule make $< work.
# on Solaris, it does not work ($? is changed sources, $^ lists dependencies).
-Index: unboundfastrpz/daemon/daemon.c
-===================================================================
---- unboundfastrpz/daemon/daemon.c (revision 5073)
-+++ unboundfastrpz/daemon/daemon.c (working copy)
+diff --git a/daemon/daemon.c b/daemon/daemon.c
+index 7461a26..706f8f6 100644
+--- a/daemon/daemon.c
++++ b/daemon/daemon.c
@@ -91,6 +91,9 @@
#include "sldns/keyraw.h"
#include "respip/respip.h"
@@ -97,36 +97,36 @@ Index: unboundfastrpz/daemon/daemon.c
#ifdef HAVE_SYSTEMD
#include <systemd/sd-daemon.h>
-@@ -462,6 +465,14 @@
+@@ -460,6 +463,14 @@ daemon_create_workers(struct daemon* daemon)
+ dt_apply_cfg(daemon->dtenv, daemon->cfg);
+ #else
fatal_exit("dnstap enabled in config but not built with dnstap support");
- #endif
- }
++#endif
++ }
+ if(daemon->cfg->rpz_enable) {
+#ifdef ENABLE_FASTRPZ
+ rpz_init(&daemon->rpz_clist, &daemon->rpz_client, daemon->cfg);
+#else
+ fatal_exit("fastrpz enabled in config"
+ " but not built with fastrpz");
-+#endif
-+ }
+ #endif
+ }
for(i=0; i<daemon->num; i++) {
- if(!(daemon->workers[i] = worker_create(daemon, i,
- shufport+numport*i/daemon->num,
-@@ -719,6 +730,9 @@
+@@ -718,6 +729,9 @@ daemon_cleanup(struct daemon* daemon)
+ #ifdef USE_DNSCRYPT
dnsc_delete(daemon->dnscenv);
daemon->dnscenv = NULL;
- #endif
++#endif
+#ifdef ENABLE_FASTRPZ
+ rpz_delete(&daemon->rpz_clist, &daemon->rpz_client);
-+#endif
+ #endif
daemon->cfg = NULL;
}
-
-Index: unboundfastrpz/daemon/daemon.h
-===================================================================
---- unboundfastrpz/daemon/daemon.h (revision 5073)
-+++ unboundfastrpz/daemon/daemon.h (working copy)
-@@ -136,6 +136,11 @@
+diff --git a/daemon/daemon.h b/daemon/daemon.h
+index 5749dbe..64ce230 100644
+--- a/daemon/daemon.h
++++ b/daemon/daemon.h
+@@ -136,6 +136,11 @@ struct daemon {
/** the dnscrypt environment */
struct dnsc_env* dnscenv;
#endif
@@ -138,10 +138,10 @@ Index: unboundfastrpz/daemon/daemon.h
};
/**
-Index: unboundfastrpz/daemon/worker.c
-===================================================================
---- unboundfastrpz/daemon/worker.c (revision 5073)
-+++ unboundfastrpz/daemon/worker.c (working copy)
+diff --git a/daemon/worker.c b/daemon/worker.c
+index fc93817..e435226 100644
+--- a/daemon/worker.c
++++ b/daemon/worker.c
@@ -75,6 +75,9 @@
#include "libunbound/context.h"
#include "libunbound/libworker.h"
@@ -152,7 +152,7 @@ Index: unboundfastrpz/daemon/worker.c
#include "sldns/wire2str.h"
#include "util/shm_side/shm_main.h"
#include "dnscrypt/dnscrypt.h"
-@@ -533,8 +536,27 @@
+@@ -533,8 +536,27 @@ answer_norec_from_cache(struct worker* worker, struct query_info* qinfo,
/* not secure */
secure = 0;
break;
@@ -180,7 +180,7 @@ Index: unboundfastrpz/daemon/worker.c
/* return this delegation from the cache */
edns_bak = *edns;
edns->edns_version = EDNS_ADVERTISED_VERSION;
-@@ -702,6 +724,23 @@
+@@ -699,6 +721,23 @@ answer_from_cache(struct worker* worker, struct query_info* qinfo,
secure = 0;
}
} else secure = 0;
@@ -204,7 +204,7 @@ Index: unboundfastrpz/daemon/worker.c
edns_bak = *edns;
edns->edns_version = EDNS_ADVERTISED_VERSION;
-@@ -1407,6 +1446,15 @@
+@@ -1409,6 +1448,15 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
log_addr(VERB_ALGO, "refused nonrec (cache snoop) query from",
&repinfo->addr, repinfo->addrlen);
goto send_reply;
@@ -220,7 +220,7 @@ Index: unboundfastrpz/daemon/worker.c
}
/* If we've found a local alias, replace the qname with the alias
-@@ -1455,12 +1503,21 @@
+@@ -1457,12 +1505,21 @@ lookup_cache:
h = query_info_hash(lookup_qinfo, sldns_buffer_read_u16_at(c->buffer, 2));
if((e=slabhash_lookup(worker->env.msg_cache, h, lookup_qinfo, 0))) {
/* answer from cache - we have acquired a readlock on it */
@@ -244,7 +244,7 @@ Index: unboundfastrpz/daemon/worker.c
/* prefetch it if the prefetch TTL expired.
* Note that if there is more than one pass
* its qname must be that used for cache
-@@ -1514,11 +1571,19 @@
+@@ -1516,11 +1573,19 @@ lookup_cache:
lock_rw_unlock(&e->lock);
}
if(!LDNS_RD_WIRE(sldns_buffer_begin(c->buffer))) {
@@ -266,11 +266,11 @@ Index: unboundfastrpz/daemon/worker.c
goto send_reply;
}
verbose(VERB_ALGO, "answer norec from cache -- "
-Index: unboundfastrpz/doc/unbound.conf.5.in
-===================================================================
---- unboundfastrpz/doc/unbound.conf.5.in (revision 5073)
-+++ unboundfastrpz/doc/unbound.conf.5.in (working copy)
-@@ -1781,6 +1781,81 @@
+diff --git a/doc/unbound.conf.5.in b/doc/unbound.conf.5.in
+index c14ee27..0b71eaf 100644
+--- a/doc/unbound.conf.5.in
++++ b/doc/unbound.conf.5.in
+@@ -1795,6 +1795,81 @@ List domain for which the AAAA records are ignored and the A record is
used by dns64 processing instead. Can be entered multiple times, list a
new domain for which it applies, one per line. Applies also to names
underneath the name given.
@@ -352,10 +352,11 @@ Index: unboundfastrpz/doc/unbound.conf.5.in
.SS "DNSCrypt Options"
.LP
The
-Index: unboundfastrpz/fastrpz/librpz.h
-===================================================================
---- unboundfastrpz/fastrpz/librpz.h (nonexistent)
-+++ unboundfastrpz/fastrpz/librpz.h (working copy)
+diff --git a/fastrpz/librpz.h b/fastrpz/librpz.h
+new file mode 100644
+index 0000000..645279d
+--- /dev/null
++++ b/fastrpz/librpz.h
@@ -0,0 +1,957 @@
+/*
+ * Define the interface from a DNS resolver to the Response Policy Zone
@@ -1314,10 +1315,11 @@ Index: unboundfastrpz/fastrpz/librpz.h
+#endif /* LIBRPZ_LIB_OPEN */
+
+#endif /* LIBRPZ_H */
-Index: unboundfastrpz/fastrpz/rpz.c
-===================================================================
---- unboundfastrpz/fastrpz/rpz.c (nonexistent)
-+++ unboundfastrpz/fastrpz/rpz.c (working copy)
+diff --git a/fastrpz/rpz.c b/fastrpz/rpz.c
+new file mode 100644
+index 0000000..c5ab780
+--- /dev/null
++++ b/fastrpz/rpz.c
@@ -0,0 +1,1352 @@
+/*
+ * fastrpz/rpz.c - interface to the fastrpz response policy zone library
@@ -2671,10 +2673,11 @@ Index: unboundfastrpz/fastrpz/rpz.c
+}
+
+#endif /* ENABLE_FASTRPZ */
-Index: unboundfastrpz/fastrpz/rpz.h
-===================================================================
---- unboundfastrpz/fastrpz/rpz.h (nonexistent)
-+++ unboundfastrpz/fastrpz/rpz.h (working copy)
+diff --git a/fastrpz/rpz.h b/fastrpz/rpz.h
+new file mode 100644
+index 0000000..5d7e31c
+--- /dev/null
++++ b/fastrpz/rpz.h
@@ -0,0 +1,138 @@
+/*
+ * fastrpz/rpz.h - interface to the fastrpz response policy zone library
@@ -2814,10 +2817,11 @@ Index: unboundfastrpz/fastrpz/rpz.h
+
+#endif /* ENABLE_FASTRPZ */
+#endif /* UNBOUND_FASTRPZ_RPZ_H */
-Index: unboundfastrpz/fastrpz/rpz.m4
-===================================================================
---- unboundfastrpz/fastrpz/rpz.m4 (nonexistent)
-+++ unboundfastrpz/fastrpz/rpz.m4 (working copy)
+diff --git a/fastrpz/rpz.m4 b/fastrpz/rpz.m4
+new file mode 100644
+index 0000000..2123535
+--- /dev/null
++++ b/fastrpz/rpz.m4
@@ -0,0 +1,64 @@
+# fastrpz/rpz.m4
+
@@ -2883,10 +2887,10 @@ Index: unboundfastrpz/fastrpz/rpz.m4
+ AC_MSG_WARN([[dlopen and librpz.so needed for fastrpz]])
+ fi
+])
-Index: unboundfastrpz/iterator/iterator.c
-===================================================================
---- unboundfastrpz/iterator/iterator.c (revision 5073)
-+++ unboundfastrpz/iterator/iterator.c (working copy)
+diff --git a/iterator/iterator.c b/iterator/iterator.c
+index c906c27..55bf218 100644
+--- a/iterator/iterator.c
++++ b/iterator/iterator.c
@@ -68,6 +68,9 @@
#include "sldns/str2wire.h"
#include "sldns/parseutil.h"
@@ -2897,7 +2901,7 @@ Index: unboundfastrpz/iterator/iterator.c
/* in msec */
int UNKNOWN_SERVER_NICENESS = 376;
-@@ -551,6 +554,23 @@
+@@ -551,6 +554,23 @@ handle_cname_response(struct module_qstate* qstate, struct iter_qstate* iq,
if(ntohs(r->rk.type) == LDNS_RR_TYPE_CNAME &&
query_dname_compare(*mname, r->rk.dname) == 0 &&
!iter_find_rrset_in_prepend_answer(iq, r)) {
@@ -2921,7 +2925,7 @@ Index: unboundfastrpz/iterator/iterator.c
/* Add this relevant CNAME rrset to the prepend list.*/
if(!iter_add_prepend_answer(qstate, iq, r))
return 0;
-@@ -559,6 +579,9 @@
+@@ -559,6 +579,9 @@ handle_cname_response(struct module_qstate* qstate, struct iter_qstate* iq,
/* Other rrsets in the section are ignored. */
}
@@ -2931,7 +2935,7 @@ Index: unboundfastrpz/iterator/iterator.c
/* add authority rrsets to authority prepend, for wildcarded CNAMEs */
for(i=msg->rep->an_numrrsets; i<msg->rep->an_numrrsets +
msg->rep->ns_numrrsets; i++) {
-@@ -1195,6 +1218,7 @@
+@@ -1195,6 +1218,7 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
uint8_t* delname;
size_t delnamelen;
struct dns_msg* msg = NULL;
@@ -2939,7 +2943,7 @@ Index: unboundfastrpz/iterator/iterator.c
log_query_info(VERB_DETAIL, "resolving", &qstate->qinfo);
/* check effort */
-@@ -1281,8 +1305,7 @@
+@@ -1281,8 +1305,7 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
}
if(msg) {
/* handle positive cache response */
@@ -2949,7 +2953,7 @@ Index: unboundfastrpz/iterator/iterator.c
if(verbosity >= VERB_ALGO) {
log_dns_msg("msg from cache lookup", &msg->qinfo,
msg->rep);
-@@ -1290,7 +1313,22 @@
+@@ -1290,7 +1313,22 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
(int)msg->rep->ttl,
(int)msg->rep->prefetch_ttl);
}
@@ -2972,7 +2976,7 @@ Index: unboundfastrpz/iterator/iterator.c
if(type == RESPONSE_TYPE_CNAME) {
uint8_t* sname = 0;
size_t slen = 0;
-@@ -2694,6 +2732,62 @@
+@@ -2714,6 +2752,62 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
sock_list_insert(&qstate->reply_origin,
&qstate->reply->addr, qstate->reply->addrlen,
qstate->region);
@@ -3035,7 +3039,7 @@ Index: unboundfastrpz/iterator/iterator.c
if(iq->minimisation_state != DONOT_MINIMISE_STATE
&& !(iq->chase_flags & BIT_RD)) {
if(FLAGS_GET_RCODE(iq->response->rep->flags) !=
-@@ -3440,6 +3534,10 @@
+@@ -3467,12 +3561,44 @@ processFinished(struct module_qstate* qstate, struct iter_qstate* iq,
* but only if we did recursion. The nonrecursion referral
* from cache does not need to be stored in the msg cache. */
if(!qstate->no_cache_store && qstate->query_flags&BIT_RD) {
@@ -3046,7 +3050,6 @@ Index: unboundfastrpz/iterator/iterator.c
iter_dns_store(qstate->env, &qstate->qinfo,
iq->response->rep, 0, qstate->prefetch_leeway,
iq->dp&&iq->dp->has_parent_side_NS,
-@@ -3446,6 +3544,34 @@
qstate->region, qstate->query_flags);
}
}
@@ -3081,11 +3084,11 @@ Index: unboundfastrpz/iterator/iterator.c
qstate->return_rcode = LDNS_RCODE_NOERROR;
qstate->return_msg = iq->response;
return 0;
-Index: unboundfastrpz/iterator/iterator.h
-===================================================================
---- unboundfastrpz/iterator/iterator.h (revision 5073)
-+++ unboundfastrpz/iterator/iterator.h (working copy)
-@@ -386,6 +386,16 @@
+diff --git a/iterator/iterator.h b/iterator/iterator.h
+index a2f1b57..e1e4a73 100644
+--- a/iterator/iterator.h
++++ b/iterator/iterator.h
+@@ -386,6 +386,16 @@ struct iter_qstate {
*/
int minimise_count;
@@ -3102,11 +3105,11 @@ Index: unboundfastrpz/iterator/iterator.h
/**
* Count number of time-outs. Used to prevent resolving failures when
* the QNAME minimisation QTYPE is blocked. */
-Index: unboundfastrpz/services/cache/dns.c
-===================================================================
---- unboundfastrpz/services/cache/dns.c (revision 5073)
-+++ unboundfastrpz/services/cache/dns.c (working copy)
-@@ -939,6 +939,14 @@
+diff --git a/services/cache/dns.c b/services/cache/dns.c
+index aa4efec..5dd3412 100644
+--- a/services/cache/dns.c
++++ b/services/cache/dns.c
+@@ -945,6 +945,14 @@ dns_cache_store(struct module_env* env, struct query_info* msgqinf,
struct regional* region, uint32_t flags)
{
struct reply_info* rep = NULL;
@@ -3121,10 +3124,10 @@ Index: unboundfastrpz/services/cache/dns.c
/* alloc, malloc properly (not in region, like msg is) */
rep = reply_info_copy(msgrep, env->alloc, NULL);
if(!rep)
-Index: unboundfastrpz/services/mesh.c
-===================================================================
---- unboundfastrpz/services/mesh.c (revision 5073)
-+++ unboundfastrpz/services/mesh.c (working copy)
+diff --git a/services/mesh.c b/services/mesh.c
+index d96289e..2e9f267 100644
+--- a/services/mesh.c
++++ b/services/mesh.c
@@ -60,6 +60,9 @@
#include "sldns/wire2str.h"
#include "services/localzone.h"
@@ -3135,7 +3138,7 @@ Index: unboundfastrpz/services/mesh.c
#include "respip/respip.h"
#include "services/listen_dnsport.h"
-@@ -1072,6 +1075,13 @@
+@@ -1072,6 +1075,13 @@ mesh_send_reply(struct mesh_state* m, int rcode, struct reply_info* rep,
else secure = 0;
if(!rep && rcode == LDNS_RCODE_NOERROR)
rcode = LDNS_RCODE_SERVFAIL;
@@ -3149,7 +3152,7 @@ Index: unboundfastrpz/services/mesh.c
/* send the reply */
/* We don't reuse the encoded answer if either the previous or current
* response has a local alias. We could compare the alias records
-@@ -1247,6 +1257,7 @@
+@@ -1247,6 +1257,7 @@ struct mesh_state* mesh_area_find(struct mesh_area* mesh,
key.s.is_valrec = valrec;
key.s.qinfo = *qinfo;
key.s.query_flags = qflags;
@@ -3157,7 +3160,7 @@ Index: unboundfastrpz/services/mesh.c
/* We are searching for a similar mesh state when we DO want to
* aggregate the state. Thus unique is set to NULL. (default when we
* desire aggregation).*/
-@@ -1293,6 +1304,10 @@
+@@ -1293,6 +1304,10 @@ int mesh_state_add_reply(struct mesh_state* s, struct edns_data* edns,
if(!r)
return 0;
r->query_reply = *rep;
@@ -3168,11 +3171,11 @@ Index: unboundfastrpz/services/mesh.c
r->edns = *edns;
if(edns->opt_list) {
r->edns.opt_list = edns_opt_copy_region(edns->opt_list,
-Index: unboundfastrpz/util/config_file.c
-===================================================================
---- unboundfastrpz/util/config_file.c (revision 5073)
-+++ unboundfastrpz/util/config_file.c (working copy)
-@@ -1418,6 +1418,8 @@
+diff --git a/util/config_file.c b/util/config_file.c
+index 9b60254..d791f8f 100644
+--- a/util/config_file.c
++++ b/util/config_file.c
+@@ -1418,6 +1418,8 @@ config_delete(struct config_file* cfg)
free(cfg->dnstap_socket_path);
free(cfg->dnstap_identity);
free(cfg->dnstap_version);
@@ -3181,11 +3184,11 @@ Index: unboundfastrpz/util/config_file.c
config_deldblstrlist(cfg->ratelimit_for_domain);
config_deldblstrlist(cfg->ratelimit_below_domain);
#ifdef USE_IPSECMOD
-Index: unboundfastrpz/util/config_file.h
-===================================================================
---- unboundfastrpz/util/config_file.h (revision 5073)
-+++ unboundfastrpz/util/config_file.h (working copy)
-@@ -490,6 +490,11 @@
+diff --git a/util/config_file.h b/util/config_file.h
+index 3cffdbf..e0fa1c8 100644
+--- a/util/config_file.h
++++ b/util/config_file.h
+@@ -490,6 +490,11 @@ struct config_file {
/** true to disable DNSSEC lameness check in iterator */
int disable_dnssec_lame_check;
@@ -3197,11 +3200,11 @@ Index: unboundfastrpz/util/config_file.h
/** ratelimit for ip addresses. 0 is off, otherwise qps (unless overridden) */
int ip_ratelimit;
/** number of slabs for ip_ratelimit cache */
-Index: unboundfastrpz/util/configlexer.lex
-===================================================================
---- unboundfastrpz/util/configlexer.lex (revision 5073)
-+++ unboundfastrpz/util/configlexer.lex (working copy)
-@@ -439,6 +439,10 @@
+diff --git a/util/configlexer.lex b/util/configlexer.lex
+index 16b5bc5..038045d 100644
+--- a/util/configlexer.lex
++++ b/util/configlexer.lex
+@@ -439,6 +439,10 @@ 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) }
@@ -3212,11 +3215,11 @@ Index: unboundfastrpz/util/configlexer.lex
disable-dnssec-lame-check{COLON} { YDVAR(1, VAR_DISABLE_DNSSEC_LAME_CHECK) }
ip-ratelimit{COLON} { YDVAR(1, VAR_IP_RATELIMIT) }
ratelimit{COLON} { YDVAR(1, VAR_RATELIMIT) }
-Index: unboundfastrpz/util/configparser.y
-===================================================================
---- unboundfastrpz/util/configparser.y (revision 5073)
-+++ unboundfastrpz/util/configparser.y (working copy)
-@@ -125,6 +125,7 @@
+diff --git a/util/configparser.y b/util/configparser.y
+index c7b9169..bef15b5 100644
+--- a/util/configparser.y
++++ b/util/configparser.y
+@@ -125,6 +125,7 @@ extern struct config_parser_state* cfg_parser;
%token VAR_DNSTAP_LOG_CLIENT_RESPONSE_MESSAGES
%token VAR_DNSTAP_LOG_FORWARDER_QUERY_MESSAGES
%token VAR_DNSTAP_LOG_FORWARDER_RESPONSE_MESSAGES
@@ -3224,7 +3227,7 @@ Index: unboundfastrpz/util/configparser.y
%token VAR_RESPONSE_IP_TAG VAR_RESPONSE_IP VAR_RESPONSE_IP_DATA
%token VAR_HARDEN_ALGO_DOWNGRADE VAR_IP_TRANSPARENT
%token VAR_DISABLE_DNSSEC_LAME_CHECK
-@@ -170,7 +171,7 @@
+@@ -170,7 +171,7 @@ extern struct config_parser_state* cfg_parser;
%%
toplevelvars: /* empty */ | toplevelvars toplevelvar ;
@@ -3233,7 +3236,7 @@ Index: unboundfastrpz/util/configparser.y
forwardstart contents_forward | pythonstart contents_py |
rcstart contents_rc | dtstart contents_dt | viewstart contents_view |
dnscstart contents_dnsc | cachedbstart contents_cachedb |
-@@ -2708,6 +2709,50 @@
+@@ -2710,6 +2711,50 @@ dt_dnstap_log_forwarder_response_messages: VAR_DNSTAP_LOG_FORWARDER_RESPONSE_MES
free($2);
}
;
@@ -3284,11 +3287,11 @@ Index: unboundfastrpz/util/configparser.y
pythonstart: VAR_PYTHON
{
OUTYY(("\nP(python:)\n"));
-Index: unboundfastrpz/util/data/msgencode.c
-===================================================================
---- unboundfastrpz/util/data/msgencode.c (revision 5073)
-+++ unboundfastrpz/util/data/msgencode.c (working copy)
-@@ -590,6 +590,35 @@
+diff --git a/util/data/msgencode.c b/util/data/msgencode.c
+index 4c0a555..e51e9b8 100644
+--- a/util/data/msgencode.c
++++ b/util/data/msgencode.c
+@@ -590,6 +590,35 @@ insert_section(struct reply_info* rep, size_t num_rrsets, uint16_t* num_rrs,
return RETVAL_OK;
}
@@ -3324,7 +3327,7 @@ Index: unboundfastrpz/util/data/msgencode.c
/** store query section in wireformat buffer, return RETVAL */
static int
insert_query(struct query_info* qinfo, struct compress_tree_node** tree,
-@@ -753,6 +782,19 @@
+@@ -753,6 +782,19 @@ reply_info_encode(struct query_info* qinfo, struct reply_info* rep,
return 0;
}
sldns_buffer_write_u16_at(buffer, 10, arcount);
@@ -3344,11 +3347,11 @@ Index: unboundfastrpz/util/data/msgencode.c
}
sldns_buffer_flip(buffer);
return 1;
-Index: unboundfastrpz/util/data/packed_rrset.c
-===================================================================
---- unboundfastrpz/util/data/packed_rrset.c (revision 5073)
-+++ unboundfastrpz/util/data/packed_rrset.c (working copy)
-@@ -255,6 +255,10 @@
+diff --git a/util/data/packed_rrset.c b/util/data/packed_rrset.c
+index 7b9d549..e44b2ce 100644
+--- a/util/data/packed_rrset.c
++++ b/util/data/packed_rrset.c
+@@ -255,6 +255,10 @@ sec_status_to_string(enum sec_status s)
case sec_status_insecure: return "sec_status_insecure";
case sec_status_secure_sentinel_fail: return "sec_status_secure_sentinel_fail";
case sec_status_secure: return "sec_status_secure";
@@ -3359,11 +3362,11 @@ Index: unboundfastrpz/util/data/packed_rrset.c
}
return "unknown_sec_status_value";
}
-Index: unboundfastrpz/util/data/packed_rrset.h
-===================================================================
---- unboundfastrpz/util/data/packed_rrset.h (revision 5073)
-+++ unboundfastrpz/util/data/packed_rrset.h (working copy)
-@@ -193,7 +193,15 @@
+diff --git a/util/data/packed_rrset.h b/util/data/packed_rrset.h
+index 3a5335d..2011321 100644
+--- a/util/data/packed_rrset.h
++++ b/util/data/packed_rrset.h
+@@ -193,7 +193,15 @@ enum sec_status {
sec_status_secure_sentinel_fail,
/** SECURE means that the object (RRset or message) validated
* according to local policy. */
@@ -3380,10 +3383,10 @@ Index: unboundfastrpz/util/data/packed_rrset.h
};
/**
-Index: unboundfastrpz/util/netevent.c
-===================================================================
---- unboundfastrpz/util/netevent.c (revision 5073)
-+++ unboundfastrpz/util/netevent.c (working copy)
+diff --git a/util/netevent.c b/util/netevent.c
+index b8b2a09..5ccc29a 100644
+--- a/util/netevent.c
++++ b/util/netevent.c
@@ -57,6 +57,9 @@
#ifdef HAVE_OPENSSL_ERR_H
#include <openssl/err.h>
@@ -3394,7 +3397,7 @@ Index: unboundfastrpz/util/netevent.c
/* -------- Start of local definitions -------- */
/** if CMSG_ALIGN is not defined on this platform, a workaround */
-@@ -590,6 +593,9 @@
+@@ -590,6 +593,9 @@ comm_point_udp_ancil_callback(int fd, short event, void* arg)
struct cmsghdr* cmsg;
#endif /* S_SPLINT_S */
@@ -3404,7 +3407,7 @@ Index: unboundfastrpz/util/netevent.c
rep.c = (struct comm_point*)arg;
log_assert(rep.c->type == comm_udp);
-@@ -679,6 +685,9 @@
+@@ -679,6 +685,9 @@ comm_point_udp_callback(int fd, short event, void* arg)
int i;
struct sldns_buffer *buffer;
@@ -3414,7 +3417,7 @@ Index: unboundfastrpz/util/netevent.c
rep.c = (struct comm_point*)arg;
log_assert(rep.c->type == comm_udp);
-@@ -722,6 +731,9 @@
+@@ -722,6 +731,9 @@ comm_point_udp_callback(int fd, short event, void* arg)
(void)comm_point_send_udp_msg(rep.c, buffer,
(struct sockaddr*)&rep.addr, rep.addrlen);
}
@@ -3424,7 +3427,7 @@ Index: unboundfastrpz/util/netevent.c
if(!rep.c || rep.c->fd != fd) /* commpoint closed to -1 or reused for
another UDP port. Note rep.c cannot be reused with TCP fd. */
break;
-@@ -3108,6 +3120,9 @@
+@@ -3142,6 +3154,9 @@ comm_point_send_reply(struct comm_reply *repinfo)
repinfo->c->tcp_timeout_msec);
}
}
@@ -3434,7 +3437,7 @@ Index: unboundfastrpz/util/netevent.c
}
void
-@@ -3117,6 +3132,9 @@
+@@ -3151,6 +3166,9 @@ comm_point_drop_reply(struct comm_reply* repinfo)
return;
log_assert(repinfo && repinfo->c);
log_assert(repinfo->c->type != comm_tcp_accept);
@@ -3444,21 +3447,21 @@ Index: unboundfastrpz/util/netevent.c
if(repinfo->c->type == comm_udp)
return;
if(repinfo->c->tcp_req_info)
-@@ -3138,6 +3156,9 @@
+@@ -3172,6 +3190,9 @@ comm_point_start_listening(struct comm_point* c, int newfd, int msec)
{
- verbose(VERB_ALGO, "comm point start listening %d",
- c->fd==-1?newfd:c->fd);
+ verbose(VERB_ALGO, "comm point start listening %d (%d msec)",
+ c->fd==-1?newfd:c->fd, msec);
+#ifdef ENABLE_FASTRPZ
+ rpz_end(&c->repinfo);
+#endif
if(c->type == comm_tcp_accept && !c->tcp_free) {
/* no use to start listening no free slots. */
return;
-Index: unboundfastrpz/util/netevent.h
-===================================================================
---- unboundfastrpz/util/netevent.h (revision 5073)
-+++ unboundfastrpz/util/netevent.h (working copy)
-@@ -120,6 +120,10 @@
+diff --git a/util/netevent.h b/util/netevent.h
+index d80c72b..0233292 100644
+--- a/util/netevent.h
++++ b/util/netevent.h
+@@ -120,6 +120,10 @@ struct comm_reply {
/** return type 0 (none), 4(IP4), 6(IP6) */
int srctype;
/* DnsCrypt context */
@@ -3469,11 +3472,11 @@ Index: unboundfastrpz/util/netevent.h
#ifdef USE_DNSCRYPT
uint8_t client_nonce[crypto_box_HALF_NONCEBYTES];
uint8_t nmkey[crypto_box_BEFORENMBYTES];
-Index: unboundfastrpz/validator/validator.c
-===================================================================
---- unboundfastrpz/validator/validator.c (revision 5073)
-+++ unboundfastrpz/validator/validator.c (working copy)
-@@ -2755,6 +2755,12 @@
+diff --git a/validator/validator.c b/validator/validator.c
+index fa8d541..5628ef0 100644
+--- a/validator/validator.c
++++ b/validator/validator.c
+@@ -2755,6 +2755,12 @@ ds_response_to_ke(struct module_qstate* qstate, struct val_qstate* vq,
default:
/* NSEC proof did not work, try next */
break;
@@ -3486,7 +3489,7 @@ Index: unboundfastrpz/validator/validator.c
}
sec = nsec3_prove_nods(qstate->env, ve,
-@@ -2788,6 +2794,12 @@
+@@ -2788,6 +2794,12 @@ ds_response_to_ke(struct module_qstate* qstate, struct val_qstate* vq,
default:
/* NSEC3 proof did not work */
break;
diff --git a/daemon/unbound.c b/daemon/unbound.c
index 4a508c13878b..6cc8225f5d18 100644
--- a/daemon/unbound.c
+++ b/daemon/unbound.c
@@ -443,7 +443,8 @@ perform_setup(struct daemon* daemon, struct config_file* cfg, int debug_mode,
}
}
#endif
- if(cfg->tls_session_ticket_keys.first) {
+ if(cfg->tls_session_ticket_keys.first &&
+ cfg->tls_session_ticket_keys.first->str[0] != 0) {
if(!listen_sslctx_setup_ticket_keys(daemon->listen_sslctx, cfg->tls_session_ticket_keys.first)) {
fatal_exit("could not set session ticket SSL_CTX");
}
diff --git a/daemon/worker.c b/daemon/worker.c
index 433b96fd527a..661f6967d41d 100644
--- a/daemon/worker.c
+++ b/daemon/worker.c
@@ -660,10 +660,7 @@ answer_from_cache(struct worker* worker, struct query_info* qinfo,
if(!reply_check_cname_chain(qinfo, rep)) {
/* cname chain invalid, redo iterator steps */
verbose(VERB_ALGO, "Cache reply: cname chain broken");
- bail_out:
- rrset_array_unlock_touch(worker->env.rrset_cache,
- worker->scratchpad, rep->ref, rep->rrset_count);
- return 0;
+ goto bail_out;
}
}
/* check security status of the cached answer */
@@ -758,6 +755,11 @@ answer_from_cache(struct worker* worker, struct query_info* qinfo,
}
/* go and return this buffer to the client */
return 1;
+
+bail_out:
+ rrset_array_unlock_touch(worker->env.rrset_cache,
+ worker->scratchpad, rep->ref, rep->rrset_count);
+ return 0;
}
/** Reply to client and perform prefetch to keep cache up to date.
@@ -770,8 +772,14 @@ reply_and_prefetch(struct worker* worker, struct query_info* qinfo,
{
/* first send answer to client to keep its latency
* as small as a cachereply */
- if(sldns_buffer_limit(repinfo->c->buffer) != 0)
+ if(sldns_buffer_limit(repinfo->c->buffer) != 0) {
+ if(repinfo->c->tcp_req_info) {
+ sldns_buffer_copy(
+ repinfo->c->tcp_req_info->spool_buffer,
+ repinfo->c->buffer);
+ }
comm_point_send_reply(repinfo);
+ }
server_stats_prefetch(&worker->stats, worker);
/* create the prefetch in the mesh as a normal lookup without
diff --git a/doc/Changelog b/doc/Changelog
index ac7c2acde6e9..420f6ab7c18e 100644
--- a/doc/Changelog
+++ b/doc/Changelog
@@ -1,3 +1,168 @@
+12 June 2019: Wouter
+ - Fix another spoolbuf storage code point, in prefetch.
+ - 1.9.2rc3 release candidate tag.
+
+11 June 2019: Wouter
+ - Fix that fixes the Fix that spoolbuf is not used to store tcp
+ pipelined response between mesh send and callback end, this fixes
+ error cases that did not use the correct spoolbuf.
+ - 1.9.2rc2 release candidate tag.
+
+6 June 2019: Wouter
+ - 1.9.2rc1 release candidate tag.
+
+4 June 2019: Wouter
+ - iana portlist updated.
+
+29 May 2019: Wouter
+ - Fix to guard _OPENBSD_SOURCE from redefinition.
+
+28 May 2019: Wouter
+ - Fix to define _OPENBSD_SOURCE to get reallocarray on NetBSD.
+ - gitignore config.h.in~.
+
+27 May 2019: Wouter
+ - Fix double file close in tcp pipelined response code.
+
+24 May 2019: Wouter
+ - Fix that spoolbuf is not used to store tcp pipelined response
+ between mesh send and callback end.
+
+20 May 2019: Wouter
+ - Note that so-reuseport at extreme load is better turned off,
+ otherwise queries are not distributed evenly, on Linux 4.4.x.
+
+16 May 2019: Wouter
+ - Fix #31: swig 4.0 and python module.
+
+13 May 2019: Wouter
+ - Squelch log messages from tcp send about connection reset by peer.
+ They can be enabled with verbosity at higher values for diagnosing
+ network connectivity issues.
+ - Attempt to fix malformed tcp response.
+
+9 May 2019: Wouter
+ - Revert fix for oss-fuzz, error is in that build script that
+ unconditionally includes .o files detected by configure, also
+ when the machine architecture uses different LIBOBJS files.
+
+8 May 2019: Wouter
+ - Attempt to fix build failure in oss-fuzz because of reallocarray.
+ https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=14648.
+ Does not omit compile flags from commandline.
+
+7 May 2019: Wouter
+ - Fix edns-subnet locks, in error cases the lock was not unlocked.
+ - Fix doxygen output error on readme markdown vignettes.
+
+6 May 2019: Wouter
+ - Fix #29: Solaris 11.3 and missing symbols be64toh, htobe64.
+ - Fix #30: AddressSanitizer finding in lookup3.c. This sets the
+ hash function to use a slower but better auditable code that does
+ not read beyond array boundaries. This makes code better security
+ checkable, and is better for security. It is fixed to be slower,
+ but not read outside of the array.
+
+2 May 2019: Wouter
+ - contrib/fastrpz.patch updated for code changes, and with git diff.
+ - Fix .gitignore, add pythonmod and dnstap generated files.
+ And unit test generated files, and generated doc files.
+
+1 May 2019: Wouter
+ - Update makedist for git.
+ - Nicer travis output for clang analysis.
+ - PR #16: XoT support, AXFR over TLS, turn it on with
+ master: <ip>#<authname> in unbound.conf. This uses TLS to
+ download the AXFR (or IXFR).
+
+25 April 2019: Wouter
+ - Fix wrong query name in local zone redirect answers with a CNAME,
+ the copy of the local alias is in unpacked form.
+
+18 April 2019: Ralph
+ - Scrub RRs from answer section when reusing NXDOMAIN message for
+ subdomain answers.
+ - For harden-below-nxdomain: do not consider a name to be non-exitent
+ when message contains a CNAME record.
+
+18 April 2019: Wouter
+ - travis build file.
+
+16 April 2019: Wouter
+ - Better braces in if statement in TCP fastopen code.
+ - iana portlist updated.
+
+15 April 2019: Wouter
+ - Fix tls write event for read state change to re-call SSL_write and
+ not resume the TLS handshake.
+
+11 April 2019: George
+ - Update python documentation for init_standard().
+ - Typos.
+
+11 April 2019: Wouter
+ - Fix that auth zone uses correct network type for sockets for
+ SOA serial probes. This fixes that probes fail because earlier
+ probe addresses are unreachable.
+ - Fix that auth zone fails over to next master for timeout in tcp.
+ - Squelch SSL read and write connection reset by peer and broken pipe
+ messages. Verbosity 2 and higher enables them.
+
+8 April 2019: Wouter
+ - Fix to use event_assign with libevent for thread-safety.
+ - verbose information about auth zone lookup process, also lookup
+ start, timeout and fail.
+ - Fix #17: Add python module example from Jan Janak, that is a
+ plugin for the Unbound DNS resolver to resolve DNS records in
+ multicast DNS [RFC 6762] via Avahi. The plugin communicates
+ with Avahi via DBus. The comment section at the beginning of
+ the file contains detailed documentation.
+ - Fix to wipe ssl ticket keys from memory with explicit_bzero,
+ if available.
+
+5 April 2019: Wouter
+ - Fix to reinit event structure for accepted TCP (and TLS) sockets.
+
+4 April 2019: Wouter
+ - Fix spelling error in log output for event method.
+
+3 April 2019: Wouter
+ - Move goto label in answer_from_cache to the end of the function
+ where it is more visible.
+ - Fix auth-zone NSEC3 response for wildcard nodata answers,
+ include the closest encloser in the answer.
+
+2 April 2019: Wouter
+ - Fix auth-zone NSEC3 response for empty nonterminals with exact
+ match nsec3 records.
+ - Fix for out of bounds integers, thanks to OSTIF audit. It is in
+ allocation debug code.
+ - Fix for auth zone nsec3 ent fix for wildcard nodata.
+
+25 March 2019: Wouter
+ - Fix that tls-session-ticket-keys: "" on its own in unbound.conf
+ disables the tls session ticker key calls into the OpenSSL API.
+ - Fix crash if tls-servic-pem not filled in when necessary.
+
+21 March 2019: Wouter
+ - Fix #4240: Fix whitespace cleanup in example.conf.
+
+19 March 2019: Wouter
+ - add type CAA to libpyunbound (accessing libunbound from python).
+
+18 March 2019: Wouter
+ - Add log message, at verbosity 4, that says the query is encrypted
+ with TLS, if that is enabled for the query.
+ - Fix #4239: set NOTIMPL when deny-any is enabled, for RFC8482.
+
+7 March 2019: Wouter
+ - Fix for #4233: guard use of NDEBUG, so that it can be passed in
+ CFLAGS into configure.
+
+5 March 2019: Wouter
+ - Tag release 1.9.1rc1. Which became 1.9.1 on 12 March 2019. Trunk
+ has 1.9.2 in development.
+
1 March 2019: Wouter
- output forwarder log in ssl_req_order test.
diff --git a/doc/README b/doc/README
index f6bb52672d28..d468688b9b2b 100644
--- a/doc/README
+++ b/doc/README
@@ -1,4 +1,4 @@
-README for Unbound 1.9.1
+README for Unbound 1.9.2
Copyright 2007 NLnet Labs
http://unbound.net
diff --git a/doc/example.conf.in b/doc/example.conf.in
index bd68f715f972..c58242d31551 100644
--- a/doc/example.conf.in
+++ b/doc/example.conf.in
@@ -1,7 +1,7 @@
#
# Example configuration file.
#
-# See unbound.conf(5) man page, version 1.9.1.
+# See unbound.conf(5) man page, version 1.9.2.
#
# this is a comment.
@@ -103,6 +103,7 @@ server:
# so-sndbuf: 0
# use SO_REUSEPORT to distribute queries over threads.
+ # at extreme load it could be better to turn it off to distribute even.
# so-reuseport: yes
# use IP_TRANSPARENT so the interface: addresses can be non-local
@@ -492,7 +493,7 @@ server:
# trust anchor signaling sends a RFC8145 key tag query after priming.
# trust-anchor-signaling: yes
-
+
# Root key trust anchor sentinel (draft-ietf-dnsop-kskroll-sentinel)
# root-key-sentinel: yes
@@ -721,7 +722,7 @@ server:
# cipher setting for TLSv1.2
# tls-ciphers: "DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256"
- # cipher setting for TLSv1.3
+ # cipher setting for TLSv1.3
# tls-ciphersuites: "TLS_AES_128_GCM_SHA256:TLS_AES_128_CCM_8_SHA256:TLS_AES_128_CCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256"
# Add the secret file for TLS Session Ticket.
@@ -793,7 +794,7 @@ server:
# fast-server-permil: 0
# the number of servers that will be used in the fast server selection.
# fast-server-num: 3
-
+
# Specific options for ipsecmod. unbound needs to be configured with
# --enable-ipsecmod for these to take effect.
#
@@ -912,24 +913,24 @@ remote-control:
# notifies.
# auth-zone:
# name: "."
-# master: 199.9.14.201 # b.root-servers.net
-# master: 192.33.4.12 # c.root-servers.net
-# master: 199.7.91.13 # d.root-servers.net
-# master: 192.5.5.241 # f.root-servers.net
-# master: 192.112.36.4 # g.root-servers.net
-# master: 193.0.14.129 # k.root-servers.net
-# master: 192.0.47.132 # xfr.cjr.dns.icann.org
-# master: 192.0.32.132 # xfr.lax.dns.icann.org
-# master: 2001:500:200::b # b.root-servers.net
-# master: 2001:500:2::c # c.root-servers.net
-# master: 2001:500:2d::d # d.root-servers.net
-# master: 2001:500:2f::f # f.root-servers.net
-# master: 2001:500:12::d0d # g.root-servers.net
-# master: 2001:7fd::1 # k.root-servers.net
-# master: 2620:0:2830:202::132 # xfr.cjr.dns.icann.org
-# master: 2620:0:2d0:202::132 # xfr.lax.dns.icann.org
-# fallback-enabled: yes
-# for-downstream: no
+# master: 199.9.14.201 # b.root-servers.net
+# master: 192.33.4.12 # c.root-servers.net
+# master: 199.7.91.13 # d.root-servers.net
+# master: 192.5.5.241 # f.root-servers.net
+# master: 192.112.36.4 # g.root-servers.net
+# master: 193.0.14.129 # k.root-servers.net
+# master: 192.0.47.132 # xfr.cjr.dns.icann.org
+# master: 192.0.32.132 # xfr.lax.dns.icann.org
+# master: 2001:500:200::b # b.root-servers.net
+# master: 2001:500:2::c # c.root-servers.net
+# master: 2001:500:2d::d # d.root-servers.net
+# master: 2001:500:2f::f # f.root-servers.net
+# master: 2001:500:12::d0d # g.root-servers.net
+# master: 2001:7fd::1 # k.root-servers.net
+# master: 2620:0:2830:202::132 # xfr.cjr.dns.icann.org
+# master: 2620:0:2d0:202::132 # xfr.lax.dns.icann.org
+# fallback-enabled: yes
+# for-downstream: no
# for-upstream: yes
# auth-zone:
# name: "example.org"
diff --git a/doc/libunbound.3.in b/doc/libunbound.3.in
index fc53e0934f4e..fd5c336e0903 100644
--- a/doc/libunbound.3.in
+++ b/doc/libunbound.3.in
@@ -1,4 +1,4 @@
-.TH "libunbound" "3" "Mar 12, 2019" "NLnet Labs" "unbound 1.9.1"
+.TH "libunbound" "3" "Jun 17, 2019" "NLnet Labs" "unbound 1.9.2"
.\"
.\" libunbound.3 -- unbound library functions manual
.\"
@@ -44,7 +44,7 @@
.B ub_ctx_zone_remove,
.B ub_ctx_data_add,
.B ub_ctx_data_remove
-\- Unbound DNS validating resolver 1.9.1 functions.
+\- Unbound DNS validating resolver 1.9.2 functions.
.SH "SYNOPSIS"
.B #include <unbound.h>
.LP
diff --git a/doc/unbound-anchor.8.in b/doc/unbound-anchor.8.in
index 41bc62483641..76f4ea21f0cd 100644
--- a/doc/unbound-anchor.8.in
+++ b/doc/unbound-anchor.8.in
@@ -1,4 +1,4 @@
-.TH "unbound-anchor" "8" "Mar 12, 2019" "NLnet Labs" "unbound 1.9.1"
+.TH "unbound-anchor" "8" "Jun 17, 2019" "NLnet Labs" "unbound 1.9.2"
.\"
.\" unbound-anchor.8 -- unbound anchor maintenance utility manual
.\"
diff --git a/doc/unbound-checkconf.8.in b/doc/unbound-checkconf.8.in
index 04421e72dd99..b3e6ff3c54b1 100644
--- a/doc/unbound-checkconf.8.in
+++ b/doc/unbound-checkconf.8.in
@@ -1,4 +1,4 @@
-.TH "unbound-checkconf" "8" "Mar 12, 2019" "NLnet Labs" "unbound 1.9.1"
+.TH "unbound-checkconf" "8" "Jun 17, 2019" "NLnet Labs" "unbound 1.9.2"
.\"
.\" unbound-checkconf.8 -- unbound configuration checker manual
.\"
diff --git a/doc/unbound-control.8.in b/doc/unbound-control.8.in
index d713d2acbeeb..2e16ac97a7bb 100644
--- a/doc/unbound-control.8.in
+++ b/doc/unbound-control.8.in
@@ -1,4 +1,4 @@
-.TH "unbound-control" "8" "Mar 12, 2019" "NLnet Labs" "unbound 1.9.1"
+.TH "unbound-control" "8" "Jun 17, 2019" "NLnet Labs" "unbound 1.9.2"
.\"
.\" unbound-control.8 -- unbound remote control manual
.\"
diff --git a/doc/unbound-host.1.in b/doc/unbound-host.1.in
index 668de37c7a79..58505d2370e6 100644
--- a/doc/unbound-host.1.in
+++ b/doc/unbound-host.1.in
@@ -1,4 +1,4 @@
-.TH "unbound\-host" "1" "Mar 12, 2019" "NLnet Labs" "unbound 1.9.1"
+.TH "unbound\-host" "1" "Jun 17, 2019" "NLnet Labs" "unbound 1.9.2"
.\"
.\" unbound-host.1 -- unbound DNS lookup utility
.\"
diff --git a/doc/unbound.8.in b/doc/unbound.8.in
index ed55005a54fe..4d408dba6f0f 100644
--- a/doc/unbound.8.in
+++ b/doc/unbound.8.in
@@ -1,4 +1,4 @@
-.TH "unbound" "8" "Mar 12, 2019" "NLnet Labs" "unbound 1.9.1"
+.TH "unbound" "8" "Jun 17, 2019" "NLnet Labs" "unbound 1.9.2"
.\"
.\" unbound.8 -- unbound manual
.\"
@@ -9,7 +9,7 @@
.\"
.SH "NAME"
.B unbound
-\- Unbound DNS validating resolver 1.9.1.
+\- Unbound DNS validating resolver 1.9.2.
.SH "SYNOPSIS"
.B unbound
.RB [ \-h ]
diff --git a/doc/unbound.conf.5.in b/doc/unbound.conf.5.in
index 8cdc2da7e3b6..24ca5f73682f 100644
--- a/doc/unbound.conf.5.in
+++ b/doc/unbound.conf.5.in
@@ -1,4 +1,4 @@
-.TH "unbound.conf" "5" "Mar 12, 2019" "NLnet Labs" "unbound 1.9.1"
+.TH "unbound.conf" "5" "Jun 17, 2019" "NLnet Labs" "unbound 1.9.2"
.\"
.\" unbound.conf.5 -- unbound.conf manual
.\"
@@ -300,6 +300,8 @@ 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.
+At extreme load it could be better to turn it off to distribute the queries
+evenly, reported for Linux systems (4.4.x).
.TP
.B ip\-transparent: \fI<yes or no>
If yes, then use IP_TRANSPARENT socket option on sockets where unbound
@@ -828,7 +830,7 @@ Can be given multiple times, for different domains.
.TP
.B qname\-minimisation: \fI<yes or no>
Send minimum amount of information to upstream servers to enhance privacy.
-Only sent minimum required labels of the QNAME and set QTYPE to A when
+Only send minimum required labels of the QNAME and set QTYPE to A when
possible. Best effort approach; full QNAME and original QTYPE will be sent when
upstream replies with a RCODE other than NOERROR, except when receiving
NXDOMAIN from a DNSSEC signed zone. Default is yes.
@@ -1675,6 +1677,7 @@ Name of the authority zone.
.B master: \fI<IP address or host name>
Where to download a copy of the zone from, with AXFR and IXFR. Multiple
masters can be specified. They are all tried if one fails.
+With the "ip#name" notation a AXFR over TLS can be used.
.TP
.B url: \fI<url to zonefile>
Where to download a zonefile for the zone. With http or https. An example
diff --git a/doc/unbound.doxygen b/doc/unbound.doxygen
index 24f4203a83ed..45f49b36722e 100644
--- a/doc/unbound.doxygen
+++ b/doc/unbound.doxygen
@@ -629,6 +629,7 @@ EXCLUDE = ./build \
libunbound/python/doc \
libunbound/python/examples \
./ldns-src \
+ README.md \
doc/control_proto_spec.txt \
doc/requirements.txt
diff --git a/edns-subnet/subnetmod.c b/edns-subnet/subnetmod.c
index 69e743ddc364..907f40d5859d 100644
--- a/edns-subnet/subnetmod.c
+++ b/edns-subnet/subnetmod.c
@@ -334,33 +334,37 @@ update_cache(struct module_qstate *qstate, int id)
/* Step 1, general qinfo lookup */
struct lruhash_entry *lru_entry = slabhash_lookup(subnet_msg_cache, h,
&qstate->qinfo, 1);
- int acquired_lock = (lru_entry != NULL);
+ int need_to_insert = (lru_entry == NULL);
if (!lru_entry) {
+ void* data = calloc(1,
+ sizeof(struct subnet_msg_cache_data));
+ if(!data) {
+ log_err("malloc failed");
+ return;
+ }
qinf = qstate->qinfo;
qinf.qname = memdup(qstate->qinfo.qname,
qstate->qinfo.qname_len);
if(!qinf.qname) {
+ free(data);
log_err("memdup failed");
return;
}
- mrep_entry = query_info_entrysetup(&qinf, NULL, h);
+ mrep_entry = query_info_entrysetup(&qinf, data, h);
free(qinf.qname); /* if qname 'consumed', it is set to NULL */
if (!mrep_entry) {
+ free(data);
log_err("query_info_entrysetup failed");
return;
}
lru_entry = &mrep_entry->entry;
lock_rw_wrlock(&lru_entry->lock);
- lru_entry->data = calloc(1,
- sizeof(struct subnet_msg_cache_data));
- if (!lru_entry->data) {
- log_err("malloc failed");
- return;
- }
}
+ /* lru_entry->lock is locked regardless of how we got here,
+ * either from the slabhash_lookup, or above in the new allocated */
/* Step 2, find the correct tree */
if (!(tree = get_tree(lru_entry->data, edns, sne, qstate->env->cfg))) {
- if (acquired_lock) lock_rw_unlock(&lru_entry->lock);
+ lock_rw_unlock(&lru_entry->lock);
log_err("Subnet cache insertion failed");
return;
}
@@ -368,7 +372,7 @@ update_cache(struct module_qstate *qstate, int id)
rep = reply_info_copy(qstate->return_msg->rep, &sne->alloc, NULL);
lock_quick_unlock(&sne->alloc.lock);
if (!rep) {
- if (acquired_lock) lock_rw_unlock(&lru_entry->lock);
+ lock_rw_unlock(&lru_entry->lock);
log_err("Subnet cache insertion failed");
return;
}
@@ -385,10 +389,9 @@ update_cache(struct module_qstate *qstate, int id)
edns->subnet_source_mask,
sq->ecs_server_in.subnet_scope_mask, rep,
rep->ttl, *qstate->env->now);
- if (acquired_lock) {
- lock_rw_unlock(&lru_entry->lock);
- } else {
- lock_rw_unlock(&lru_entry->lock);
+
+ lock_rw_unlock(&lru_entry->lock);
+ if (need_to_insert) {
slabhash_insert(subnet_msg_cache, h, lru_entry, lru_entry->data,
NULL);
}
diff --git a/iterator/iter_utils.c b/iterator/iter_utils.c
index be7965a60e39..2ab55ceb4977 100644
--- a/iterator/iter_utils.c
+++ b/iterator/iter_utils.c
@@ -1211,6 +1211,19 @@ iter_scrub_ds(struct dns_msg* msg, struct ub_packed_rrset_key* ns, uint8_t* z)
}
}
+void
+iter_scrub_nxdomain(struct dns_msg* msg)
+{
+ if(msg->rep->an_numrrsets == 0)
+ return;
+
+ memmove(msg->rep->rrsets, msg->rep->rrsets+msg->rep->an_numrrsets,
+ sizeof(struct ub_packed_rrset_key*) *
+ (msg->rep->rrset_count-msg->rep->an_numrrsets));
+ msg->rep->rrset_count -= msg->rep->an_numrrsets;
+ msg->rep->an_numrrsets = 0;
+}
+
void iter_dec_attempts(struct delegpt* dp, int d)
{
struct delegpt_addr* a;
diff --git a/iterator/iter_utils.h b/iterator/iter_utils.h
index ccfb280224b3..f771930bba2b 100644
--- a/iterator/iter_utils.h
+++ b/iterator/iter_utils.h
@@ -335,6 +335,13 @@ void iter_scrub_ds(struct dns_msg* msg, struct ub_packed_rrset_key* ns,
uint8_t* z);
/**
+ * Prepare an NXDOMAIN message to be used for a subdomain answer by removing all
+ * RRs from the ANSWER section.
+ * @param msg: the response to scrub.
+ */
+void iter_scrub_nxdomain(struct dns_msg* msg);
+
+/**
* Remove query attempts from all available ips. For 0x20.
* @param dp: delegpt.
* @param d: decrease.
diff --git a/iterator/iterator.c b/iterator/iterator.c
index c73fb5177489..c906c2714483 100644
--- a/iterator/iterator.c
+++ b/iterator/iterator.c
@@ -2718,8 +2718,15 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
&& !(iq->chase_flags & BIT_RD)) {
if(FLAGS_GET_RCODE(iq->response->rep->flags) !=
LDNS_RCODE_NOERROR) {
- if(qstate->env->cfg->qname_minimisation_strict)
- return final_state(iq);
+ if(qstate->env->cfg->qname_minimisation_strict) {
+ if(FLAGS_GET_RCODE(iq->response->rep->flags) ==
+ LDNS_RCODE_NXDOMAIN) {
+ iter_scrub_nxdomain(iq->response);
+ return final_state(iq);
+ }
+ return error_response(qstate, id,
+ LDNS_RCODE_SERVFAIL);
+ }
/* Best effort qname-minimisation.
* Stop minimising and send full query when
* RCODE is not NOERROR. */
diff --git a/libunbound/python/libunbound.i b/libunbound/python/libunbound.i
index 6196a3979c4a..a23c45b9c708 100644
--- a/libunbound/python/libunbound.i
+++ b/libunbound/python/libunbound.i
@@ -242,6 +242,7 @@
RR_TYPE_MAILA = 254,
/** any type (wildcard) */
RR_TYPE_ANY = 255,
+ RR_TYPE_CAA = 257,
/* RFC 4431, 5074, DNSSEC Lookaside Validation */
RR_TYPE_DLV = 32769,
@@ -823,8 +824,7 @@ Result: ['74.125.43.147', '74.125.43.99', '74.125.43.103', '74.125.43.104']
"""
return self.rcode2str[self.rcode]
- __swig_getmethods__["rcode_str"] = _get_rcode_str
- if _newclass:rcode_str = _swig_property(_get_rcode_str)
+ rcode_str = property(_get_rcode_str)
def _get_raw_data(self):
"""Result data, a list of network order DNS rdata items.
@@ -833,15 +833,13 @@ Result: ['74.125.43.147', '74.125.43.99', '74.125.43.103', '74.125.43.104']
"""
return self._ub_result_data(self)
- __swig_getmethods__["rawdata"] = _get_raw_data
rawdata = property(_get_raw_data, doc="Returns raw data, a list of rdata items. To decode RAW data use the :attr:`data` attribute which returns an instance of :class:`ub_data` containing the conversion functions.")
def _get_data(self):
if not self.havedata: return None
return ub_data(self._ub_result_data(self))
- __swig_getmethods__["data"] = _get_data
- __swig_getmethods__["packet"] = _packet
+ packet = property(_packet)
data = property(_get_data, doc="Returns :class:`ub_data` instance containing various decoding functions or None")
%}
diff --git a/pythonmod/doc/examples/example0-1.py b/pythonmod/doc/examples/example0-1.py
index 5ae48d16674a..7904f73a55e8 100644
--- a/pythonmod/doc/examples/example0-1.py
+++ b/pythonmod/doc/examples/example0-1.py
@@ -1,8 +1,11 @@
-
def init(id, cfg):
log_info("pythonmod: init called, module id is %d port: %d script: %s" % (id, cfg.port, cfg.python_script))
return True
+def init_standard(id, env):
+ log_info("pythonmod: init called, module id is %d port: %d script: %s" % (id, env.cfg.port, env.cfg.python_script))
+ return True
+
def deinit(id):
log_info("pythonmod: deinit called, module id is %d" % id)
return True
diff --git a/pythonmod/doc/examples/example0.rst b/pythonmod/doc/examples/example0.rst
index 8fff41f33c72..693972a141a4 100644
--- a/pythonmod/doc/examples/example0.rst
+++ b/pythonmod/doc/examples/example0.rst
@@ -54,6 +54,25 @@ Script file must contain four compulsory functions:
return True
+.. function:: init_standard(id, env)
+
+ Initialize module internals, like database etc.
+ Called just once on module load.
+
+ *Preferred* over the init() function above as this function's signature is the
+ same as the C counterpart and allows for extra functionality during init.
+ The previously accessible configuration options can now be found in env.cfg.
+
+ :param id: module identifier (integer)
+ :param env: :class:`module_env` module environment
+
+::
+
+ def init_standard(id, env):
+ log_info("pythonmod: init called, module id is %d port: %d script: %s" % (id, env.cfg.port, env.cfg.python_script))
+ return True
+
+
.. function:: deinit(id)
Deinitialize module internals.
diff --git a/pythonmod/examples/avahi-resolver.py b/pythonmod/examples/avahi-resolver.py
new file mode 100644
index 000000000000..b1d4e36fc887
--- /dev/null
+++ b/pythonmod/examples/avahi-resolver.py
@@ -0,0 +1,567 @@
+#!/usr/bin/env python3
+#
+# A plugin for the Unbound DNS resolver to resolve DNS records in
+# multicast DNS [RFC 6762] via Avahi.
+#
+# Copyright (C) 2018-2019 Internet Real-Time Lab, Columbia University
+# http://www.cs.columbia.edu/irt/
+#
+# Written by Jan Janak <janakj@cs.columbia.edu>
+#
+# Permission is hereby granted, free of charge, to any person
+# obtaining a copy of this software and associated documentation files
+# (the "Software"), to deal in the Software without restriction,
+# including without limitation the rights to use, copy, modify, merge,
+# publish, distribute, sublicense, and/or sell copies of the Software,
+# and to permit persons to whom the Software is furnished to do so,
+# subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+#
+#
+# Dependendies:
+# Unbound with pythonmodule configured for Python 3
+# dnspython [http://www.dnspython.org]
+# pydbus [https://github.com/LEW21/pydbus]
+#
+# To enable Python 3 support, configure Unbound as follows:
+# PYTHON_VERSION=3 ./configure --with-pythonmodule
+#
+# The plugin in meant to be used as a fallback resolver that resolves
+# records in multicast DNS if the upstream server cannot be reached or
+# provides no answer (NXDOMAIN).
+#
+# mDNS requests for negative records, i.e., records for which Avahi
+# returns no answer (NXDOMAIN), are expensive. Since there is no
+# single authoritative server in mDNS, such requests terminate only
+# via a timeout. The timeout is about a second (if MDNS_TIMEOUT is not
+# configured), or the value configured via MDNS_TIMEOUT. The
+# corresponding Unbound thread will be blocked for this amount of
+# time. For this reason, it is important to configure an appropriate
+# number of threads in unbound.conf and limit the RR types and names
+# that will be resolved via Avahi via the environment variables
+# described later.
+#
+# An example unbound.conf with the plugin enabled:
+#
+# | server:
+# | module-config: "validator python iterator"
+# | num-threads: 32
+# | cache-max-negative-ttl: 60
+# | cache-max-ttl: 60
+#
+#
+# The plugin can also be run interactively. Provide the name and
+# record type to be resolved as command line arguments and the
+# resolved record will be printed to standard output:
+#
+# $ ./avahi-resolver.py voip-phx4.phxnet.org A
+# voip-phx4.phxnet.org. 120 IN A 10.4.3.2
+#
+#
+# The behavior of the plugin can be controlled via the following
+# environment variables:
+#
+# DBUS_SYSTEM_BUS_ADDRESS
+#
+# The address of the system DBus bus, in the format expected by DBus,
+# e.g., unix:path=/run/avahi/system-bus.sock
+#
+#
+# DEBUG
+#
+# Set this environment variable to "yes", "true", "on", or "1" to
+# enable debugging. In debugging mode, the plugin will output a lot
+# more information about what it is doing either to the standard
+# output (when run interactively) or to Unbound via log_info and
+# log_error.
+#
+# By default debugging is disabled.
+#
+#
+# MDNS_TTL
+#
+# Avahi does not provide the TTL value for the records it returns.
+# This environment variable can be used to configure the TTL value for
+# such records.
+#
+# The default value is 120 seconds.
+#
+#
+# MDNS_TIMEOUT
+#
+# The maximum amount of time (in milliseconds) an Avahi request is
+# allowed to run. This value sets the time it takes to resolve
+# negative (non-existent) records in Avahi. If unset, the request
+# terminates when Avahi sends the "AllForNow" signal, telling the
+# client that more records are unlikely to arrive. This takes roughly
+# about one second. You may need to configure a longer value here on
+# slower networks, e.g., networks that relay mDNS packets such as
+# MANETs.
+#
+#
+# MDNS_GETONE
+#
+# If set to "true", "1", or "on", an Avahi request will terminate as
+# soon as at least one record has been found. If there are multiple
+# nodes in the mDNS network publishing the same record, only one (or
+# subset) will be returned.
+#
+# If set to "false", "0", or "off", the plugin will gather records for
+# MDNS_TIMEOUT and return all records found. This is only useful in
+# networks where multiple nodes are known to publish different records
+# under the same name and the client needs to be able to obtain them
+# all. When configured this way, all Avahi requests will always take
+# MDNS_TIMEOUT to complete!
+#
+# This option is set to true by default.
+#
+#
+# MDNS_REJECT_TYPES
+#
+# A comma-separated list of record types that will NOT be resolved in
+# mDNS via Avahi. Use this environment variable to prevent specific
+# record types from being resolved via Avahi. For example, if your
+# network does not support IPv6, you can put AAAA on this list.
+#
+# The default value is an empty list.
+#
+# Example: MDNS_REJECT_TYPES=aaaa,mx,soa
+#
+#
+# MDNS_ACCEPT_TYPES
+#
+# If set, a record type will be resolved via Avahi if and only if it
+# is present on this comma-separated list. In other words, this is a
+# whitelist.
+#
+# The default value is an empty list which means all record types will
+# be resolved via Avahi.
+#
+# Example: MDNS_ACCEPT_TYPES=a,ptr,txt,srv,aaaa,cname
+#
+#
+# MDNS_REJECT_NAMES
+#
+# If the name being resolved matches the regular expression in this
+# environment variable, the name will NOT be resolved via Avahi. In
+# other words, this environment variable provides a blacklist.
+#
+# The default value is empty--no names will be reject.
+#
+# Example: MDNS_REJECT_NAMES=(^|\.)example\.com\.$
+#
+#
+# MDNS_ACCEPT_NAMES
+#
+# If set to a regular expression, a name will be resolved via Avahi if
+# and only if it matches the regular expression. In other words, this
+# variable provides a whitelist.
+#
+# The default value is empty--all names will be resolved via Avahi.
+#
+# Example: MDNS_ACCEPT_NAMES=^.*\.example\.com\.$
+#
+
+import os
+import re
+import array
+import threading
+import traceback
+import dns.rdata
+import dns.rdatatype
+import dns.rdataclass
+from queue import Queue
+from gi.repository import GLib
+from pydbus import SystemBus
+
+
+IF_UNSPEC = -1
+PROTO_UNSPEC = -1
+
+sysbus = None
+avahi = None
+trampoline = dict()
+thread_local = threading.local()
+dbus_thread = None
+dbus_loop = None
+
+
+def str2bool(v):
+ if v.lower() in ['false', 'no', '0', 'off', '']:
+ return False
+ return True
+
+
+def dbg(msg):
+ if DEBUG != False:
+ log_info('avahi-resolver: %s' % msg)
+
+
+#
+# Although pydbus has an internal facility for handling signals, we
+# cannot use that with Avahi. When responding from an internal cache,
+# Avahi sends the first signal very quickly, before pydbus has had a
+# chance to subscribe for the signal. This will result in lost signal
+# and missed data:
+#
+# https://github.com/LEW21/pydbus/issues/87
+#
+# As a workaround, we subscribe to all signals before creating a
+# record browser and do our own signal matching and dispatching via
+# the following function.
+#
+def signal_dispatcher(connection, sender, path, interface, name, args):
+ o = trampoline.get(path, None)
+ if o is None:
+ return
+
+ if name == 'ItemNew': o.itemNew(*args)
+ elif name == 'ItemRemove': o.itemRemove(*args)
+ elif name == 'AllForNow': o.allForNow(*args)
+ elif name == 'Failure': o.failure(*args)
+
+
+class RecordBrowser:
+ def __init__(self, callback, name, type_, timeout=None, getone=True):
+ self.callback = callback
+ self.records = []
+ self.error = None
+ self.getone = getone
+
+ self.timer = None if timeout is None else GLib.timeout_add(timeout, self.timedOut)
+
+ self.browser_path = avahi.RecordBrowserNew(IF_UNSPEC, PROTO_UNSPEC, name, dns.rdataclass.IN, type_, 0)
+ trampoline[self.browser_path] = self
+ self.browser = sysbus.get('.Avahi', self.browser_path)
+ self.dbg('Created RecordBrowser(name=%s, type=%s, getone=%s, timeout=%s)'
+ % (name, dns.rdatatype.to_text(type_), getone, timeout))
+
+ def dbg(self, msg):
+ dbg('[%s] %s' % (self.browser_path, msg))
+
+ def _done(self):
+ del trampoline[self.browser_path]
+ self.dbg('Freeing')
+ self.browser.Free()
+
+ if self.timer is not None:
+ self.dbg('Removing timer')
+ GLib.source_remove(self.timer)
+
+ self.callback(self.records, self.error)
+
+ def itemNew(self, interface, protocol, name, class_, type_, rdata, flags):
+ self.dbg('Got signal ItemNew')
+ self.records.append((name, class_, type_, rdata))
+ if self.getone:
+ self._done()
+
+ def itemRemove(self, interface, protocol, name, class_, type_, rdata, flags):
+ self.dbg('Got signal ItemRemove')
+ self.records.remove((name, class_, type_, rdata))
+
+ def failure(self, error):
+ self.dbg('Got signal Failure')
+ self.error = Exception(error)
+ self._done()
+
+ def allForNow(self):
+ self.dbg('Got signal AllForNow')
+ if self.timer is None:
+ self._done()
+
+ def timedOut(self):
+ self.dbg('Timed out')
+ self._done()
+ return False
+
+
+#
+# This function runs the main event loop for DBus (GLib). This
+# function must be run in a dedicated worker thread.
+#
+def dbus_main():
+ global sysbus, avahi, dbus_loop
+
+ dbg('Connecting to system DBus')
+ sysbus = SystemBus()
+
+ dbg('Subscribing to .Avahi.RecordBrowser signals')
+ sysbus.con.signal_subscribe('org.freedesktop.Avahi',
+ 'org.freedesktop.Avahi.RecordBrowser',
+ None, None, None, 0, signal_dispatcher)
+
+ avahi = sysbus.get('.Avahi', '/')
+
+ dbg("Connected to Avahi Daemon: %s (API %s) [%s]"
+ % (avahi.GetVersionString(), avahi.GetAPIVersion(), avahi.GetHostNameFqdn()))
+
+ dbg('Starting DBus main loop')
+ dbus_loop = GLib.MainLoop()
+ dbus_loop.run()
+
+
+#
+# This function must be run in the DBus worker thread. It creates a
+# new RecordBrowser instance and once it has finished doing it thing,
+# it will send the result back to the original thread via the queue.
+#
+def start_resolver(queue, *args, **kwargs):
+ try:
+ RecordBrowser(lambda *v: queue.put_nowait(v), *args, **kwargs)
+ except Exception as e:
+ queue.put_nowait((None, e))
+
+ return False
+
+
+#
+# To resolve a request, we setup a queue, post a task to the DBus
+# worker thread, and wait for the result (or error) to arrive over the
+# queue. If the worker thread reports an error, raise the error as an
+# exception.
+#
+def resolve(*args, **kwargs):
+ try:
+ queue = thread_local.queue
+ except AttributeError:
+ dbg('Creating new per-thread queue')
+ queue = Queue()
+ thread_local.queue = queue
+
+ GLib.idle_add(lambda: start_resolver(queue, *args, **kwargs))
+
+ records, error = queue.get()
+ queue.task_done()
+
+ if error is not None:
+ raise error
+
+ return records
+
+
+def parse_type_list(lst):
+ return list(map(dns.rdatatype.from_text, [v.strip() for v in lst.split(',') if len(v)]))
+
+
+def init(*args, **kwargs):
+ global dbus_thread, DEBUG
+ global MDNS_TTL, MDNS_GETONE, MDNS_TIMEOUT
+ global MDNS_REJECT_TYPES, MDNS_ACCEPT_TYPES
+ global MDNS_REJECT_NAMES, MDNS_ACCEPT_NAMES
+
+ DEBUG = str2bool(os.environ.get('DEBUG', str(False)))
+
+ MDNS_TTL = int(os.environ.get('MDNS_TTL', 120))
+ dbg("TTL for records from Avahi: %d" % MDNS_TTL)
+
+ MDNS_REJECT_TYPES = parse_type_list(os.environ.get('MDNS_REJECT_TYPES', ''))
+ if MDNS_REJECT_TYPES:
+ dbg('Types NOT resolved via Avahi: %s' % MDNS_REJECT_TYPES)
+
+ MDNS_ACCEPT_TYPES = parse_type_list(os.environ.get('MDNS_ACCEPT_TYPES', ''))
+ if MDNS_ACCEPT_TYPES:
+ dbg('ONLY resolving the following types via Avahi: %s' % MDNS_ACCEPT_TYPES)
+
+ v = os.environ.get('MDNS_REJECT_NAMES', None)
+ MDNS_REJECT_NAMES = re.compile(v, flags=re.I | re.S) if v is not None else None
+ if MDNS_REJECT_NAMES is not None:
+ dbg('Names NOT resolved via Avahi: %s' % MDNS_REJECT_NAMES.pattern)
+
+ v = os.environ.get('MDNS_ACCEPT_NAMES', None)
+ MDNS_ACCEPT_NAMES = re.compile(v, flags=re.I | re.S) if v is not None else None
+ if MDNS_ACCEPT_NAMES is not None:
+ dbg('ONLY resolving the following names via Avahi: %s' % MDNS_ACCEPT_NAMES.pattern)
+
+ v = os.environ.get('MDNS_TIMEOUT', None)
+ MDNS_TIMEOUT = int(v) if v is not None else None
+ if MDNS_TIMEOUT is not None:
+ dbg('Avahi request timeout: %s' % MDNS_TIMEOUT)
+
+ MDNS_GETONE = str2bool(os.environ.get('MDNS_GETONE', str(True)))
+ dbg('Terminate Avahi requests on first record: %s' % MDNS_GETONE)
+
+ dbus_thread = threading.Thread(target=dbus_main)
+ dbus_thread.daemon = True
+ dbus_thread.start()
+
+
+def deinit(*args, **kwargs):
+ dbus_loop.quit()
+ dbus_thread.join()
+ return True
+
+
+def inform_super(id, qstate, superqstate, qdata):
+ return True
+
+
+def get_rcode(msg):
+ if not msg:
+ return RCODE_SERVFAIL
+
+ return msg.rep.flags & 0xf
+
+
+def rr2text(rec, ttl):
+ name, class_, type_, rdata = rec
+ wire = array.array('B', rdata).tostring()
+ return '%s. %d %s %s %s' % (
+ name,
+ ttl,
+ dns.rdataclass.to_text(class_),
+ dns.rdatatype.to_text(type_),
+ dns.rdata.from_wire(class_, type_, wire, 0, len(wire), None))
+
+
+def operate(id, event, qstate, qdata):
+ qi = qstate.qinfo
+ name = qi.qname_str
+ type_ = qi.qtype
+ type_str = dns.rdatatype.to_text(type_)
+ class_ = qi.qclass
+ class_str = dns.rdataclass.to_text(class_)
+ rc = get_rcode(qstate.return_msg)
+
+ if event == MODULE_EVENT_NEW or event == MODULE_EVENT_PASS:
+ qstate.ext_state[id] = MODULE_WAIT_MODULE
+ return True
+
+ if event != MODULE_EVENT_MODDONE:
+ log_err("avahi-resolver: Unexpected event %d" % event)
+ qstate.ext_state[id] = MODULE_ERROR
+ return True
+
+ qstate.ext_state[id] = MODULE_FINISHED
+
+ # Only resolve via Avahi if we got NXDOMAIn from the upstream DNS
+ # server, or if we could not reach the upstream DNS server. If we
+ # got some records for the name from the upstream DNS server
+ # already, do not resolve the record in Avahi.
+ if rc != RCODE_NXDOMAIN and rc != RCODE_SERVFAIL:
+ return True
+
+ dbg("Got request for '%s %s %s'" % (name, class_str, type_str))
+
+ # Avahi only supports the IN class
+ if class_ != RR_CLASS_IN:
+ dbg('Rejected, Avahi only supports the IN class')
+ return True
+
+ # Avahi does not support meta queries (e.g., ANY)
+ if dns.rdatatype.is_metatype(type_):
+ dbg('Rejected, Avahi does not support the type %s' % type_str)
+ return True
+
+ # If we have a type blacklist and the requested type is on the
+ # list, reject it.
+ if MDNS_REJECT_TYPES and type_ in MDNS_REJECT_TYPES:
+ dbg('Rejected, type %s is on the blacklist' % type_str)
+ return True
+
+ # If we have a type whitelist and if the requested type is not on
+ # the list, reject it.
+ if MDNS_ACCEPT_TYPES and type_ not in MDNS_ACCEPT_TYPES:
+ dbg('Rejected, type %s is not on the whitelist' % type_str)
+ return True
+
+ # If we have a name blacklist and if the requested name matches
+ # the blacklist, reject it.
+ if MDNS_REJECT_NAMES is not None:
+ if MDNS_REJECT_NAMES.search(name):
+ dbg('Rejected, name %s is on the blacklist' % name)
+ return True
+
+ # If we have a name whitelist and if the requested name does not
+ # match the whitelist, reject it.
+ if MDNS_ACCEPT_NAMES is not None:
+ if not MDNS_ACCEPT_NAMES.search(name):
+ dbg('Rejected, name %s is not on the whitelist' % name)
+ return True
+
+ dbg("Resolving '%s %s %s' via Avahi" % (name, class_str, type_str))
+
+ recs = resolve(name, type_, getone=MDNS_GETONE, timeout=MDNS_TIMEOUT)
+
+ if not recs:
+ dbg('Result: Not found (NXDOMAIN)')
+ qstate.return_rcode = RCODE_NXDOMAIN
+ return True
+
+ m = DNSMessage(name, type_, class_, PKT_QR | PKT_RD | PKT_RA)
+ for r in recs:
+ s = rr2text(r, MDNS_TTL)
+ dbg('Result: %s' % s)
+ m.answer.append(s)
+
+ if not m.set_return_msg(qstate):
+ raise Exception("Error in set_return_msg")
+
+ if not storeQueryInCache(qstate, qstate.return_msg.qinfo, qstate.return_msg.rep, 0):
+ raise Exception("Error in storeQueryInCache")
+
+ qstate.return_msg.rep.security = 2
+ qstate.return_rcode = RCODE_NOERROR
+ return True
+
+
+#
+# It does not appear to be sufficient to check __name__ to determine
+# whether we are being run in interactive mode. As a workaround, try
+# to import module unboundmodule and if that fails, assume we're being
+# run in interactive mode.
+#
+try:
+ import unboundmodule
+ embedded = True
+except ImportError:
+ embedded = False
+
+if __name__ == '__main__' and not embedded:
+ import sys
+
+ def log_info(msg):
+ print(msg)
+
+ def log_err(msg):
+ print('ERROR: %s' % msg, file=sys.stderr)
+
+ if len(sys.argv) != 3:
+ print('Usage: %s <name> <rr_type>' % sys.argv[0])
+ sys.exit(2)
+
+ name = sys.argv[1]
+ type_str = sys.argv[2]
+
+ try:
+ type_ = dns.rdatatype.from_text(type_str)
+ except dns.rdatatype.UnknownRdatatype:
+ log_err('Unsupported DNS record type "%s"' % type_str)
+ sys.exit(2)
+
+ if dns.rdatatype.is_metatype(type_):
+ log_err('Meta record type "%s" cannot be resolved via Avahi' % type_str)
+ sys.exit(2)
+
+ init()
+ try:
+ recs = resolve(name, type_, getone=MDNS_GETONE, timeout=MDNS_TIMEOUT)
+ if not len(recs):
+ print('%s not found (NXDOMAIN)' % name)
+ sys.exit(1)
+
+ for r in recs:
+ print(rr2text(r, MDNS_TTL))
+ finally:
+ deinit()
diff --git a/pythonmod/examples/edns.py b/pythonmod/examples/edns.py
index 37ce9e27923d..ca1bb8da710d 100644
--- a/pythonmod/examples/edns.py
+++ b/pythonmod/examples/edns.py
@@ -78,7 +78,7 @@ def init_standard(id, env):
extra functionality during init.
..note:: This function is preferred by unbound over the old init function.
..note:: The previously accessible configuration options can now be found in
- env.cgf.
+ env.cfg.
"""
log_info("python: inited script {}".format(env.cfg.python_script))
diff --git a/pythonmod/examples/inplace_callbacks.py b/pythonmod/examples/inplace_callbacks.py
index 776add8c29ad..768c2d0138c5 100644
--- a/pythonmod/examples/inplace_callbacks.py
+++ b/pythonmod/examples/inplace_callbacks.py
@@ -275,7 +275,7 @@ def init_standard(id, env):
..note:: This function is preferred by unbound over the old init function.
..note:: The previously accessible configuration options can now be found in
- env.cgf.
+ env.cfg.
"""
log_info("python: inited script {}".format(env.cfg.python_script))
diff --git a/pythonmod/interface.i b/pythonmod/interface.i
index f9fd07b513d6..14f0299eeb57 100644
--- a/pythonmod/interface.i
+++ b/pythonmod/interface.i
@@ -196,22 +196,17 @@ struct query_info {
%extend query_info {
%pythoncode %{
def _get_qtype_str(self): return sldns_wire2str_type(self.qtype)
- __swig_getmethods__["qtype_str"] = _get_qtype_str
- if _newclass:qtype_str = _swig_property(_get_qtype_str)
+ qtype_str = property(_get_qtype_str)
def _get_qclass_str(self): return sldns_wire2str_class(self.qclass)
- __swig_getmethods__["qclass_str"] = _get_qclass_str
- if _newclass:qclass_str = _swig_property(_get_qclass_str)
+ qclass_str = property(_get_qclass_str)
- __swig_getmethods__["qname"] = _unboundmodule._get_qname
- if _newclass:qname = _swig_property(_unboundmodule._get_qname)
+ qname = property(_unboundmodule._get_qname)
- __swig_getmethods__["qname_list"] = _unboundmodule._get_qname_components
- if _newclass:qname_list = _swig_property(_unboundmodule._get_qname_components)
+ qname_list = property(_unboundmodule._get_qname_components)
def _get_qname_str(self): return dnameAsStr(self.qname)
- __swig_getmethods__["qname_str"] = _get_qname_str
- if _newclass:qname_str = _swig_property(_get_qname_str)
+ qname_str = property(_get_qname_str)
%}
}
@@ -251,22 +246,17 @@ uint16_t ntohs(uint16_t netshort);
%extend packed_rrset_key {
%pythoncode %{
def _get_type_str(self): return sldns_wire2str_type(_unboundmodule.ntohs(self.type))
- __swig_getmethods__["type_str"] = _get_type_str
- if _newclass:type_str = _swig_property(_get_type_str)
+ type_str = property(_get_type_str)
def _get_class_str(self): return sldns_wire2str_class(_unboundmodule.ntohs(self.rrset_class))
- __swig_getmethods__["rrset_class_str"] = _get_class_str
- if _newclass:rrset_class_str = _swig_property(_get_class_str)
+ rrset_class_str = property(_get_class_str)
- __swig_getmethods__["dname"] = _unboundmodule._get_dname
- if _newclass:dname = _swig_property(_unboundmodule._get_dname)
+ dname = property(_unboundmodule._get_dname)
- __swig_getmethods__["dname_list"] = _unboundmodule._get_dname_components
- if _newclass:dname_list = _swig_property(_unboundmodule._get_dname_components)
+ dname_list = property(_unboundmodule._get_dname_components)
def _get_dname_str(self): return dnameAsStr(self.dname)
- __swig_getmethods__["dname_str"] = _get_dname_str
- if _newclass:dname_str = _swig_property(_get_dname_str)
+ dname_str = property(_get_dname_str)
%}
}
@@ -364,14 +354,11 @@ struct packed_rrset_data {
%extend packed_rrset_data {
%pythoncode %{
def _get_data_rr_len(self): return RRSetData_RRLen(self)
- __swig_getmethods__["rr_len"] = _get_data_rr_len
- if _newclass:rr_len = _swig_property(_get_data_rr_len)
+ rr_len = property(_get_data_rr_len)
def _get_data_rr_ttl(self): return RRSetData_RRTTL(self)
- __swig_getmethods__["rr_ttl"] =_get_data_rr_ttl
- if _newclass:rr_len = _swig_property(_get_data_rr_ttl)
+ rr_ttl = property(_get_data_rr_ttl)
def _get_data_rr_data(self): return RRSetData_RRData(self)
- __swig_getmethods__["rr_data"] = _get_data_rr_data
- if _newclass:rr_len = _swig_property(_get_data_rr_data)
+ rr_data = property(_get_data_rr_data)
%}
}
@@ -443,12 +430,10 @@ struct dns_msg {
%extend reply_info {
%pythoncode %{
def _rrset_ref_get(self): return ReplyInfo_Ref(self)
- __swig_getmethods__["ref"] = _rrset_ref_get
- if _newclass:ref = _swig_property(_rrset_ref_get)
+ ref = property(_rrset_ref_get)
def _rrset_rrsets_get(self): return ReplyInfo_RRSet(self)
- __swig_getmethods__["rrsets"] = _rrset_rrsets_get
- if _newclass:rrsets = _swig_property(_rrset_rrsets_get)
+ rrsets = property(_rrset_rrsets_get)
%}
}
@@ -589,28 +574,22 @@ struct sockaddr_storage {};
%extend sockaddr_storage {
%pythoncode %{
def _family_get(self): return _sockaddr_storage_family(self)
- __swig_getmethods__["family"] = _family_get
- if _newclass: family = _swig_property(_family_get)
+ family = property(_family_get)
def _addr_get(self): return _sockaddr_storage_addr(self)
- __swig_getmethods__["addr"] = _addr_get
- if _newclass: addr = _swig_property(_addr_get)
+ addr = property(_addr_get)
def _raw_addr_get(self): return _sockaddr_storage_raw_addr(self)
- __swig_getmethods__["raw_addr"] = _raw_addr_get
- if _newclass: raw_addr = _swig_property(_raw_addr_get)
+ raw_addr = property(_raw_addr_get)
def _port_get(self): return _sockaddr_storage_port(self)
- __swig_getmethods__["port"] = _port_get
- if _newclass: port = _swig_property(_port_get)
+ port = property(_port_get)
def _flowinfo_get(self): return _sockaddr_storage_flowinfo(self)
- __swig_getmethods__["flowinfo"] = _flowinfo_get
- if _newclass: flowinfo = _swig_property(_flowinfo_get)
+ flowinfo = property(_flowinfo_get)
def _scope_id_get(self): return _sockaddr_storage_scope_id(self)
- __swig_getmethods__["scope_id"] = _scope_id_get
- if _newclass: scope_id = _swig_property(_scope_id_get)
+ scope_id = property(_scope_id_get)
%}
}
@@ -634,16 +613,13 @@ struct comm_reply {
%extend comm_reply {
%pythoncode %{
def _addr_get(self): return _sockaddr_storage_addr(self._addr)
- __swig_getmethods__["addr"] = _addr_get
- if _newclass:addr = _swig_property(_addr_get)
+ addr = property(_addr_get)
def _port_get(self): return _sockaddr_storage_port(self._addr)
- __swig_getmethods__["port"] = _port_get
- if _newclass:port = _swig_property(_port_get)
+ port = property(_port_get)
def _family_get(self): return _sockaddr_storage_family(self._addr)
- __swig_getmethods__["family"] = _family_get
- if _newclass:family = _swig_property(_family_get)
+ family = property(_family_get)
%}
}
@@ -678,12 +654,10 @@ struct edns_option {
%extend edns_option {
%pythoncode %{
def _opt_code_get(self): return _edns_option_opt_code_get(self)
- __swig_getmethods__["code"] = _opt_code_get
- if _newclass: opt_code = _swig_property(_opt_code_get)
+ code = property(_opt_code_get)
def _opt_data_get(self): return _edns_option_opt_data_get(self)
- __swig_getmethods__["data"] = _opt_data_get
- if _newclass: opt_data = _swig_property(_opt_data_get)
+ data = property(_opt_data_get)
%}
}
@@ -710,11 +684,9 @@ struct edns_data {
%extend edns_data {
%pythoncode %{
def _opt_list_iter(self): return EdnsOptsListIter(self.opt_list)
- __swig_getmethods__["opt_list_iter"] = _opt_list_iter
- if _newclass:opt_list_iter = _swig_property(_opt_list_iter)
+ opt_list_iter = property(_opt_list_iter)
def _opt_list(self): return _edns_data_opt_list_get(self)
- __swig_getmethods__["opt_list"] = _opt_list
- if _newclass:opt_list = _swig_property(_opt_list)
+ opt_list = property(_opt_list)
%}
}
@@ -915,34 +887,25 @@ struct module_qstate {
_unboundmodule._ext_state_set(self, id, state)
def __ext_state_get(self): return ExtState(self)
- __swig_getmethods__["ext_state"] = __ext_state_get
- if _newclass:ext_state = _swig_property(__ext_state_get)#, __ext_state_set)
+ ext_state = property(__ext_state_get) #, __ext_state_set
def _edns_opts_front_in_iter(self): return EdnsOptsListIter(self.edns_opts_front_in)
- __swig_getmethods__["edns_opts_front_in_iter"] = _edns_opts_front_in_iter
- if _newclass:edns_opts_front_in_iter = _swig_property(_edns_opts_front_in_iter)
+ edns_opts_front_in_iter = property(_edns_opts_front_in_iter)
def _edns_opts_back_out_iter(self): return EdnsOptsListIter(self.edns_opts_back_out)
- __swig_getmethods__["edns_opts_back_out_iter"] = _edns_opts_back_out_iter
- if _newclass:edns_opts_back_out_iter = _swig_property(_edns_opts_back_out_iter)
+ edns_opts_back_out_iter = property(_edns_opts_back_out_iter)
def _edns_opts_back_in_iter(self): return EdnsOptsListIter(self.edns_opts_back_in)
- __swig_getmethods__["edns_opts_back_in_iter"] = _edns_opts_back_in_iter
- if _newclass:edns_opts_back_in_iter = _swig_property(_edns_opts_back_in_iter)
+ edns_opts_back_in_iter = property(_edns_opts_back_in_iter)
def _edns_opts_front_out_iter(self): return EdnsOptsListIter(self.edns_opts_front_out)
- __swig_getmethods__["edns_opts_front_out_iter"] = _edns_opts_front_out_iter
- if _newclass:edns_opts_front_out_iter = _swig_property(_edns_opts_front_out_iter)
+ edns_opts_front_out_iter = property(_edns_opts_front_out_iter)
def _edns_opts_front_in(self): return _edns_opts_front_in_get(self)
- __swig_getmethods__["edns_opts_front_in"] = _edns_opts_front_in
- if _newclass:edns_opts_front_in = _swig_property(_edns_opts_front_in)
+ edns_opts_front_in = property(_edns_opts_front_in)
def _edns_opts_back_out(self): return _edns_opts_back_out_get(self)
- __swig_getmethods__["edns_opts_back_out"] = _edns_opts_back_out
- if _newclass:edns_opts_back_out = _swig_property(_edns_opts_back_out)
+ edns_opts_back_out = property(_edns_opts_back_out)
def _edns_opts_back_in(self): return _edns_opts_back_in_get(self)
- __swig_getmethods__["edns_opts_back_in"] = _edns_opts_back_in
- if _newclass:edns_opts_back_in = _swig_property(_edns_opts_back_in)
+ edns_opts_back_in = property(_edns_opts_back_in)
def _edns_opts_front_out(self): return _edns_opts_front_out_get(self)
- __swig_getmethods__["edns_opts_front_out"] = _edns_opts_front_out
- if _newclass:edns_opts_front_out = _swig_property(_edns_opts_front_out)
+ edns_opts_front_out = property(_edns_opts_front_out)
%}
}
@@ -1112,35 +1075,28 @@ struct delegpt {
%extend delegpt {
%pythoncode %{
- __swig_getmethods__["dname"] = _unboundmodule._get_dp_dname
- if _newclass:dname = _swig_property(_unboundmodule._get_dp_dname)
+ dname = property(_unboundmodule._get_dp_dname)
- __swig_getmethods__["dname_list"] = _unboundmodule._get_dp_dname_components
- if _newclass:dname_list = _swig_property(_unboundmodule._get_dp_dname_components)
+ dname_list = property(_unboundmodule._get_dp_dname_components)
def _get_dname_str(self): return dnameAsStr(self.dname)
- __swig_getmethods__["dname_str"] = _get_dname_str
- if _newclass:dname_str = _swig_property(_get_dname_str)
+ dname_str = property(_get_dname_str)
%}
}
%extend delegpt_ns {
%pythoncode %{
- __swig_getmethods__["dname"] = _unboundmodule._get_dpns_dname
- if _newclass:dname = _swig_property(_unboundmodule._get_dpns_dname)
+ dname = property(_unboundmodule._get_dpns_dname)
- __swig_getmethods__["dname_list"] = _unboundmodule._get_dpns_dname_components
- if _newclass:dname_list = _swig_property(_unboundmodule._get_dpns_dname_components)
+ dname_list = property(_unboundmodule._get_dpns_dname_components)
def _get_dname_str(self): return dnameAsStr(self.dname)
- __swig_getmethods__["dname_str"] = _get_dname_str
- if _newclass:dname_str = _swig_property(_get_dname_str)
+ dname_str = property(_get_dname_str)
%}
}
%extend delegpt_addr {
%pythoncode %{
def _addr_get(self): return _delegpt_addr_addr_get(self)
- __swig_getmethods__["addr"] = _addr_get
- if _newclass:addr = _swig_property(_addr_get)
+ addr = property(_addr_get)
%}
}
diff --git a/services/authzone.c b/services/authzone.c
index a87c2274fb9e..1426f423a1b2 100644
--- a/services/authzone.c
+++ b/services/authzone.c
@@ -2042,11 +2042,13 @@ auth_xfer_delete(struct auth_xfer* xfr)
if(xfr->task_probe) {
auth_free_masters(xfr->task_probe->masters);
comm_point_delete(xfr->task_probe->cp);
+ comm_timer_delete(xfr->task_probe->timer);
free(xfr->task_probe);
}
if(xfr->task_transfer) {
auth_free_masters(xfr->task_transfer->masters);
comm_point_delete(xfr->task_transfer->cp);
+ comm_timer_delete(xfr->task_transfer->timer);
if(xfr->task_transfer->chunks_first) {
auth_chunks_delete(xfr->task_transfer);
}
@@ -2746,6 +2748,7 @@ az_nsec3_insert(struct auth_zone* z, struct regional* region,
* that is an exact match that should exist for it.
* If that does not exist, a higher exact match + nxproof is enabled
* (for some sort of opt-out empty nonterminal cases).
+ * nodataproof: search for exact match and include that instead.
* ceproof: include ce proof NSEC3 (omitted for wildcard replies).
* nxproof: include denial of the qname.
* wcproof: include denial of wildcard (wildcard.ce).
@@ -2753,7 +2756,8 @@ az_nsec3_insert(struct auth_zone* z, struct regional* region,
static int
az_add_nsec3_proof(struct auth_zone* z, struct regional* region,
struct dns_msg* msg, uint8_t* cenm, size_t cenmlen, uint8_t* qname,
- size_t qname_len, int ceproof, int nxproof, int wcproof)
+ size_t qname_len, int nodataproof, int ceproof, int nxproof,
+ int wcproof)
{
int algo;
size_t iter, saltlen;
@@ -2764,6 +2768,19 @@ az_add_nsec3_proof(struct auth_zone* z, struct regional* region,
/* find parameters of nsec3 proof */
if(!az_nsec3_param(z, &algo, &iter, &salt, &saltlen))
return 1; /* no nsec3 */
+ if(nodataproof) {
+ /* see if the node has a hash of itself for the nodata
+ * proof nsec3, this has to be an exact match nsec3. */
+ struct auth_data* match;
+ match = az_nsec3_find_exact(z, qname, qname_len, algo,
+ iter, salt, saltlen);
+ if(match) {
+ if(!az_nsec3_insert(z, region, msg, match))
+ return 0;
+ /* only nodata NSEC3 needed, no CE or others. */
+ return 1;
+ }
+ }
/* find ce that has an NSEC3 */
if(ceproof) {
node = az_nsec3_find_ce(z, &cenm, &cenmlen, &no_exact_ce,
@@ -2916,7 +2933,7 @@ az_generate_notype_answer(struct auth_zone* z, struct regional* region,
/* DNSSEC denial NSEC3 */
if(!az_add_nsec3_proof(z, region, msg, node->name,
node->namelen, msg->qinfo.qname,
- msg->qinfo.qname_len, 1, 0, 0))
+ msg->qinfo.qname_len, 1, 1, 0, 0))
return 0;
}
return 1;
@@ -2943,7 +2960,7 @@ az_generate_referral_answer(struct auth_zone* z, struct regional* region,
} else {
if(!az_add_nsec3_proof(z, region, msg, ce->name,
ce->namelen, msg->qinfo.qname,
- msg->qinfo.qname_len, 1, 0, 0))
+ msg->qinfo.qname_len, 1, 1, 0, 0))
return 0;
}
}
@@ -2982,6 +2999,7 @@ az_generate_wildcard_answer(struct auth_zone* z, struct query_info* qinfo,
struct auth_data* wildcard, struct auth_data* node)
{
struct auth_rrset* rrset, *nsec;
+ int insert_ce = 0;
if((rrset=az_domain_rrset(wildcard, qinfo->qtype)) != NULL) {
/* wildcard has type, add it */
if(!msg_add_rrset_an(z, region, msg, wildcard, rrset))
@@ -3008,6 +3026,10 @@ az_generate_wildcard_answer(struct auth_zone* z, struct query_info* qinfo,
/* call other notype routine for dnssec notype denials */
if(!az_generate_notype_answer(z, region, msg, wildcard))
return 0;
+ /* because the notype, there is no positive data with an
+ * RRSIG that indicates the wildcard position. Thus the
+ * wildcard qname denial needs to have a CE nsec3. */
+ insert_ce = 1;
}
/* ce and node for dnssec denial of wildcard original name */
@@ -3019,7 +3041,7 @@ az_generate_wildcard_answer(struct auth_zone* z, struct query_info* qinfo,
dname_remove_label(&wildup, &wilduplen);
if(!az_add_nsec3_proof(z, region, msg, wildup,
wilduplen, msg->qinfo.qname,
- msg->qinfo.qname_len, 0, 1, 0))
+ msg->qinfo.qname_len, 0, insert_ce, 1, 0))
return 0;
}
@@ -3045,7 +3067,7 @@ az_generate_nxdomain_answer(struct auth_zone* z, struct regional* region,
} else if(ce) {
if(!az_add_nsec3_proof(z, region, msg, ce->name,
ce->namelen, msg->qinfo.qname,
- msg->qinfo.qname_len, 1, 1, 1))
+ msg->qinfo.qname_len, 0, 1, 1, 1))
return 0;
}
return 1;
@@ -4953,6 +4975,9 @@ xfr_process_chunk_list(struct auth_xfer* xfr, struct module_env* env,
static void
xfr_transfer_disown(struct auth_xfer* xfr)
{
+ /* remove timer (from this worker's event base) */
+ comm_timer_delete(xfr->task_transfer->timer);
+ xfr->task_transfer->timer = NULL;
/* remove the commpoint */
comm_point_delete(xfr->task_transfer->cp);
xfr->task_transfer->cp = NULL;
@@ -5034,6 +5059,9 @@ xfr_transfer_init_fetch(struct auth_xfer* xfr, struct module_env* env)
struct sockaddr_storage addr;
socklen_t addrlen = 0;
struct auth_master* master = xfr->task_transfer->master;
+ char *auth_name = NULL;
+ struct timeval t;
+ int timeout;
if(!master) return 0;
if(master->allow_notify) return 0; /* only for notify */
@@ -5042,7 +5070,7 @@ xfr_transfer_init_fetch(struct auth_xfer* xfr, struct module_env* env)
addrlen = xfr->task_transfer->scan_addr->addrlen;
memmove(&addr, &xfr->task_transfer->scan_addr->addr, addrlen);
} else {
- if(!extstrtoaddr(master->host, &addr, &addrlen)) {
+ if(!authextstrtoaddr(master->host, &addr, &addrlen, &auth_name)) {
/* the ones that are not in addr format are supposed
* to be looked up. The lookup has failed however,
* so skip them */
@@ -5059,25 +5087,46 @@ xfr_transfer_init_fetch(struct auth_xfer* xfr, struct module_env* env)
comm_point_delete(xfr->task_transfer->cp);
xfr->task_transfer->cp = NULL;
}
+ if(!xfr->task_transfer->timer) {
+ xfr->task_transfer->timer = comm_timer_create(env->worker_base,
+ auth_xfer_transfer_timer_callback, xfr);
+ if(!xfr->task_transfer->timer) {
+ log_err("malloc failure");
+ return 0;
+ }
+ }
+ timeout = AUTH_TRANSFER_TIMEOUT;
+#ifndef S_SPLINT_S
+ t.tv_sec = timeout/1000;
+ t.tv_usec = (timeout%1000)*1000;
+#endif
if(master->http) {
/* perform http fetch */
/* store http port number into sockaddr,
* unless someone used unbound's host@port notation */
+ xfr->task_transfer->on_ixfr = 0;
if(strchr(master->host, '@') == NULL)
sockaddr_store_port(&addr, addrlen, master->port);
xfr->task_transfer->cp = outnet_comm_point_for_http(
env->outnet, auth_xfer_transfer_http_callback, xfr,
- &addr, addrlen, AUTH_TRANSFER_TIMEOUT, master->ssl,
- master->host, master->file);
+ &addr, addrlen, -1, master->ssl, master->host,
+ master->file);
if(!xfr->task_transfer->cp) {
- char zname[255+1];
+ char zname[255+1], as[256];
dname_str(xfr->name, zname);
+ addr_to_str(&addr, addrlen, as, sizeof(as));
verbose(VERB_ALGO, "cannot create http cp "
- "connection for %s to %s", zname,
- master->host);
+ "connection for %s to %s", zname, as);
return 0;
}
+ comm_timer_set(xfr->task_transfer->timer, &t);
+ if(verbosity >= VERB_ALGO) {
+ char zname[255+1], as[256];
+ dname_str(xfr->name, zname);
+ addr_to_str(&addr, addrlen, as, sizeof(as));
+ verbose(VERB_ALGO, "auth zone %s transfer next HTTP fetch from %s started", zname, as);
+ }
return 1;
}
@@ -5091,14 +5140,24 @@ xfr_transfer_init_fetch(struct auth_xfer* xfr, struct module_env* env)
/* connect on fd */
xfr->task_transfer->cp = outnet_comm_point_for_tcp(env->outnet,
auth_xfer_transfer_tcp_callback, xfr, &addr, addrlen,
- env->scratch_buffer, AUTH_TRANSFER_TIMEOUT);
+ env->scratch_buffer, -1,
+ auth_name != NULL, auth_name);
if(!xfr->task_transfer->cp) {
- char zname[255+1];
- dname_str(xfr->name, zname);
+ char zname[255+1], as[256];
+ dname_str(xfr->name, zname);
+ addr_to_str(&addr, addrlen, as, sizeof(as));
verbose(VERB_ALGO, "cannot create tcp cp connection for "
- "xfr %s to %s", zname, master->host);
+ "xfr %s to %s", zname, as);
return 0;
}
+ comm_timer_set(xfr->task_transfer->timer, &t);
+ if(verbosity >= VERB_ALGO) {
+ char zname[255+1], as[256];
+ dname_str(xfr->name, zname);
+ addr_to_str(&addr, addrlen, as, sizeof(as));
+ verbose(VERB_ALGO, "auth zone %s transfer next %s fetch from %s started", zname,
+ (xfr->task_transfer->on_ixfr?"IXFR":"AXFR"), as);
+ }
return 1;
}
@@ -5116,6 +5175,11 @@ xfr_transfer_nexttarget_or_end(struct auth_xfer* xfr, struct module_env* env)
* and we may then get an instant cache response,
* and that calls the callback just like a full
* lookup and lookup failures also call callback */
+ if(verbosity >= VERB_ALGO) {
+ char zname[255+1];
+ dname_str(xfr->name, zname);
+ verbose(VERB_ALGO, "auth zone %s transfer next target lookup", zname);
+ }
lock_basic_unlock(&xfr->lock);
return;
}
@@ -5134,6 +5198,11 @@ xfr_transfer_nexttarget_or_end(struct auth_xfer* xfr, struct module_env* env)
/* failed to fetch, next master */
xfr_transfer_nextmaster(xfr);
}
+ if(verbosity >= VERB_ALGO) {
+ char zname[255+1];
+ dname_str(xfr->name, zname);
+ verbose(VERB_ALGO, "auth zone %s transfer failed, wait", zname);
+ }
/* we failed to fetch the zone, move to wait task
* use the shorter retry timeout */
@@ -5231,8 +5300,26 @@ void auth_xfer_transfer_lookup_callback(void* arg, int rcode, sldns_buffer* buf,
if(answer) {
xfr_master_add_addrs(xfr->task_transfer->
lookup_target, answer, wanted_qtype);
+ } else {
+ if(verbosity >= VERB_ALGO) {
+ char zname[255+1];
+ dname_str(xfr->name, zname);
+ verbose(VERB_ALGO, "auth zone %s host %s type %s transfer lookup has nodata", zname, xfr->task_transfer->lookup_target->host, (xfr->task_transfer->lookup_aaaa?"AAAA":"A"));
+ }
+ }
+ } else {
+ if(verbosity >= VERB_ALGO) {
+ char zname[255+1];
+ dname_str(xfr->name, zname);
+ verbose(VERB_ALGO, "auth zone %s host %s type %s transfer lookup has no answer", zname, xfr->task_transfer->lookup_target->host, (xfr->task_transfer->lookup_aaaa?"AAAA":"A"));
}
}
+ } else {
+ if(verbosity >= VERB_ALGO) {
+ char zname[255+1];
+ dname_str(xfr->name, zname);
+ verbose(VERB_ALGO, "auth zone %s host %s type %s transfer lookup failed", zname, xfr->task_transfer->lookup_target->host, (xfr->task_transfer->lookup_aaaa?"AAAA":"A"));
+ }
}
if(xfr->task_transfer->lookup_target->list &&
xfr->task_transfer->lookup_target == xfr_transfer_current_master(xfr))
@@ -5616,6 +5703,46 @@ process_list_end_transfer(struct auth_xfer* xfr, struct module_env* env)
xfr_transfer_nexttarget_or_end(xfr, env);
}
+/** callback for the task_transfer timer */
+void
+auth_xfer_transfer_timer_callback(void* arg)
+{
+ struct auth_xfer* xfr = (struct auth_xfer*)arg;
+ struct module_env* env;
+ int gonextonfail = 1;
+ log_assert(xfr->task_transfer);
+ lock_basic_lock(&xfr->lock);
+ env = xfr->task_transfer->env;
+ if(env->outnet->want_to_quit) {
+ lock_basic_unlock(&xfr->lock);
+ return; /* stop on quit */
+ }
+
+ verbose(VERB_ALGO, "xfr stopped, connection timeout to %s",
+ xfr->task_transfer->master->host);
+
+ /* see if IXFR caused the failure, if so, try AXFR */
+ if(xfr->task_transfer->on_ixfr) {
+ xfr->task_transfer->ixfr_possible_timeout_count++;
+ if(xfr->task_transfer->ixfr_possible_timeout_count >=
+ NUM_TIMEOUTS_FALLBACK_IXFR) {
+ verbose(VERB_ALGO, "xfr to %s, fallback "
+ "from IXFR to AXFR (because of timeouts)",
+ xfr->task_transfer->master->host);
+ xfr->task_transfer->ixfr_fail = 1;
+ gonextonfail = 0;
+ }
+ }
+
+ /* delete transferred data from list */
+ auth_chunks_delete(xfr->task_transfer);
+ comm_point_delete(xfr->task_transfer->cp);
+ xfr->task_transfer->cp = NULL;
+ if(gonextonfail)
+ xfr_transfer_nextmaster(xfr);
+ xfr_transfer_nexttarget_or_end(xfr, env);
+}
+
/** callback for task_transfer tcp connections */
int
auth_xfer_transfer_tcp_callback(struct comm_point* c, void* arg, int err,
@@ -5632,6 +5759,8 @@ auth_xfer_transfer_tcp_callback(struct comm_point* c, void* arg, int err,
lock_basic_unlock(&xfr->lock);
return 0; /* stop on quit */
}
+ /* stop the timer */
+ comm_timer_disable(xfr->task_transfer->timer);
if(err != NETEVENT_NOERROR) {
/* connection failed, closed, or timeout */
@@ -5712,6 +5841,8 @@ auth_xfer_transfer_http_callback(struct comm_point* c, void* arg, int err,
return 0; /* stop on quit */
}
verbose(VERB_ALGO, "auth zone transfer http callback");
+ /* stop the timer */
+ comm_timer_disable(xfr->task_transfer->timer);
if(err != NETEVENT_NOERROR && err != NETEVENT_DONE) {
/* connection failed, closed, or timeout */
@@ -5809,6 +5940,7 @@ xfr_probe_send_probe(struct auth_xfer* xfr, struct module_env* env,
struct timeval t;
/* pick master */
struct auth_master* master = xfr_probe_current_master(xfr);
+ char *auth_name = NULL;
if(!master) return 0;
if(master->allow_notify) return 0; /* only for notify */
if(master->http) return 0; /* only masters get SOA UDP probe,
@@ -5819,7 +5951,7 @@ xfr_probe_send_probe(struct auth_xfer* xfr, struct module_env* env,
addrlen = xfr->task_probe->scan_addr->addrlen;
memmove(&addr, &xfr->task_probe->scan_addr->addr, addrlen);
} else {
- if(!extstrtoaddr(master->host, &addr, &addrlen)) {
+ if(!authextstrtoaddr(master->host, &addr, &addrlen, &auth_name)) {
/* the ones that are not in addr format are supposed
* to be looked up. The lookup has failed however,
* so skip them */
@@ -5829,6 +5961,18 @@ xfr_probe_send_probe(struct auth_xfer* xfr, struct module_env* env,
zname, master->host);
return 0;
}
+ if (auth_name != NULL) {
+ if (addr.ss_family == AF_INET
+ && ntohs(((struct sockaddr_in *)&addr)->sin_port)
+ == env->cfg->ssl_port)
+ ((struct sockaddr_in *)&addr)->sin_port
+ = htons(env->cfg->port);
+ else if (addr.ss_family == AF_INET6
+ && ntohs(((struct sockaddr_in6 *)&addr)->sin6_port)
+ == env->cfg->ssl_port)
+ ((struct sockaddr_in6 *)&addr)->sin6_port
+ = htons(env->cfg->port);
+ }
}
/* create packet */
@@ -5838,14 +5982,26 @@ xfr_probe_send_probe(struct auth_xfer* xfr, struct module_env* env,
xfr->task_probe->id = (uint16_t)(ub_random(env->rnd)&0xffff);
xfr_create_soa_probe_packet(xfr, env->scratch_buffer,
xfr->task_probe->id);
+ /* we need to remove the cp if we have a different ip4/ip6 type now */
+ if(xfr->task_probe->cp &&
+ ((xfr->task_probe->cp_is_ip6 && !addr_is_ip6(&addr, addrlen)) ||
+ (!xfr->task_probe->cp_is_ip6 && addr_is_ip6(&addr, addrlen)))
+ ) {
+ comm_point_delete(xfr->task_probe->cp);
+ xfr->task_probe->cp = NULL;
+ }
if(!xfr->task_probe->cp) {
+ if(addr_is_ip6(&addr, addrlen))
+ xfr->task_probe->cp_is_ip6 = 1;
+ else xfr->task_probe->cp_is_ip6 = 0;
xfr->task_probe->cp = outnet_comm_point_for_udp(env->outnet,
auth_xfer_probe_udp_callback, xfr, &addr, addrlen);
if(!xfr->task_probe->cp) {
- char zname[255+1];
+ char zname[255+1], as[256];
dname_str(xfr->name, zname);
+ addr_to_str(&addr, addrlen, as, sizeof(as));
verbose(VERB_ALGO, "cannot create udp cp for "
- "probe %s to %s", zname, master->host);
+ "probe %s to %s", zname, as);
return 0;
}
}
@@ -5861,12 +6017,20 @@ xfr_probe_send_probe(struct auth_xfer* xfr, struct module_env* env,
/* send udp packet */
if(!comm_point_send_udp_msg(xfr->task_probe->cp, env->scratch_buffer,
(struct sockaddr*)&addr, addrlen)) {
- char zname[255+1];
+ char zname[255+1], as[256];
dname_str(xfr->name, zname);
+ addr_to_str(&addr, addrlen, as, sizeof(as));
verbose(VERB_ALGO, "failed to send soa probe for %s to %s",
- zname, master->host);
+ zname, as);
return 0;
}
+ if(verbosity >= VERB_ALGO) {
+ char zname[255+1], as[256];
+ dname_str(xfr->name, zname);
+ addr_to_str(&addr, addrlen, as, sizeof(as));
+ verbose(VERB_ALGO, "auth zone %s soa probe sent to %s", zname,
+ as);
+ }
xfr->task_probe->timeout = timeout;
#ifndef S_SPLINT_S
t.tv_sec = timeout/1000;
@@ -5891,6 +6055,11 @@ auth_xfer_probe_timer_callback(void* arg)
return; /* stop on quit */
}
+ if(verbosity >= VERB_ALGO) {
+ char zname[255+1];
+ dname_str(xfr->name, zname);
+ verbose(VERB_ALGO, "auth zone %s soa probe timeout", zname);
+ }
if(xfr->task_probe->timeout <= AUTH_PROBE_TIMEOUT_STOP) {
/* try again with bigger timeout */
if(xfr_probe_send_probe(xfr, env, xfr->task_probe->timeout*2)) {
@@ -6078,6 +6247,11 @@ xfr_probe_send_or_end(struct auth_xfer* xfr, struct module_env* env)
* and we may then get an instant cache response,
* and that calls the callback just like a full
* lookup and lookup failures also call callback */
+ if(verbosity >= VERB_ALGO) {
+ char zname[255+1];
+ dname_str(xfr->name, zname);
+ verbose(VERB_ALGO, "auth zone %s probe next target lookup", zname);
+ }
lock_basic_unlock(&xfr->lock);
return;
}
@@ -6086,9 +6260,19 @@ xfr_probe_send_or_end(struct auth_xfer* xfr, struct module_env* env)
/* probe of list has ended. Create or refresh the list of of
* allow_notify addrs */
probe_copy_masters_for_allow_notify(xfr);
+ if(verbosity >= VERB_ALGO) {
+ char zname[255+1];
+ dname_str(xfr->name, zname);
+ verbose(VERB_ALGO, "auth zone %s probe: notify addrs updated", zname);
+ }
if(xfr->task_probe->only_lookup) {
/* only wanted lookups for copy, stop probe and start wait */
xfr->task_probe->only_lookup = 0;
+ if(verbosity >= VERB_ALGO) {
+ char zname[255+1];
+ dname_str(xfr->name, zname);
+ verbose(VERB_ALGO, "auth zone %s probe: finished only_lookup", zname);
+ }
xfr_probe_disown(xfr);
if(xfr->task_nextprobe->worker == NULL)
xfr_set_timeout(xfr, env, 0, 0);
@@ -6110,13 +6294,22 @@ xfr_probe_send_or_end(struct auth_xfer* xfr, struct module_env* env)
/* done with probe sequence, wait */
if(xfr->task_probe->have_new_lease) {
/* if zone not updated, start the wait timer again */
- verbose(VERB_ALGO, "auth_zone unchanged, new lease, wait");
+ if(verbosity >= VERB_ALGO) {
+ char zname[255+1];
+ dname_str(xfr->name, zname);
+ verbose(VERB_ALGO, "auth_zone %s unchanged, new lease, wait", zname);
+ }
xfr_probe_disown(xfr);
if(xfr->have_zone)
xfr->lease_time = *env->now;
if(xfr->task_nextprobe->worker == NULL)
xfr_set_timeout(xfr, env, 0, 0);
} else {
+ if(verbosity >= VERB_ALGO) {
+ char zname[255+1];
+ dname_str(xfr->name, zname);
+ verbose(VERB_ALGO, "auth zone %s soa probe failed, wait to retry", zname);
+ }
/* we failed to send this as well, move to the wait task,
* use the shorter retry timeout */
xfr_probe_disown(xfr);
@@ -6161,7 +6354,25 @@ void auth_xfer_probe_lookup_callback(void* arg, int rcode, sldns_buffer* buf,
if(answer) {
xfr_master_add_addrs(xfr->task_probe->
lookup_target, answer, wanted_qtype);
+ } else {
+ if(verbosity >= VERB_ALGO) {
+ char zname[255+1];
+ dname_str(xfr->name, zname);
+ verbose(VERB_ALGO, "auth zone %s host %s type %s probe lookup has nodata", zname, xfr->task_probe->lookup_target->host, (xfr->task_probe->lookup_aaaa?"AAAA":"A"));
+ }
}
+ } else {
+ if(verbosity >= VERB_ALGO) {
+ char zname[255+1];
+ dname_str(xfr->name, zname);
+ verbose(VERB_ALGO, "auth zone %s host %s type %s probe lookup has no address", zname, xfr->task_probe->lookup_target->host, (xfr->task_probe->lookup_aaaa?"AAAA":"A"));
+ }
+ }
+ } else {
+ if(verbosity >= VERB_ALGO) {
+ char zname[255+1];
+ dname_str(xfr->name, zname);
+ verbose(VERB_ALGO, "auth zone %s host %s type %s probe lookup failed", zname, xfr->task_probe->lookup_target->host, (xfr->task_probe->lookup_aaaa?"AAAA":"A"));
}
}
if(xfr->task_probe->lookup_target->list &&
diff --git a/services/authzone.h b/services/authzone.h
index 4706803a86b3..a695bd029b56 100644
--- a/services/authzone.h
+++ b/services/authzone.h
@@ -327,6 +327,8 @@ struct auth_probe {
/** the SOA probe udp event.
* on the workers event base. */
struct comm_point* cp;
+ /** is the cp for ip6 or ip4 */
+ int cp_is_ip6;
/** timeout for packets.
* on the workers event base. */
struct comm_timer* timer;
@@ -398,6 +400,9 @@ struct auth_transfer {
/** the transfer (TCP) to the master.
* on the workers event base. */
struct comm_point* cp;
+ /** timeout for the transfer.
+ * on the workers event base. */
+ struct comm_timer* timer;
};
/** list of addresses */
@@ -647,6 +652,8 @@ int auth_xfer_transfer_http_callback(struct comm_point* c, void* arg, int err,
struct comm_reply* repinfo);
/** xfer probe timeout callback, part of task_probe */
void auth_xfer_probe_timer_callback(void* arg);
+/** xfer transfer timeout callback, part of task_transfer */
+void auth_xfer_transfer_timer_callback(void* arg);
/** mesh callback for task_probe on lookup of host names */
void auth_xfer_probe_lookup_callback(void* arg, int rcode,
struct sldns_buffer* buf, enum sec_status sec, char* why_bogus,
diff --git a/services/cache/dns.c b/services/cache/dns.c
index 47611ac5aef5..aa4efec73f41 100644
--- a/services/cache/dns.c
+++ b/services/cache/dns.c
@@ -40,6 +40,7 @@
*/
#include "config.h"
#include "iterator/iter_delegpt.h"
+#include "iterator/iter_utils.h"
#include "validator/val_nsec.h"
#include "validator/val_utils.h"
#include "services/cache/dns.h"
@@ -728,6 +729,8 @@ fill_any(struct module_env* env,
if(!msg) {
return NULL;
}
+ /* set NOTIMPL for RFC 8482 */
+ msg->rep->flags |= LDNS_RCODE_NOTIMPL;
msg->rep->security = sec_status_indeterminate;
return msg;
}
@@ -912,12 +915,15 @@ dns_cache_lookup(struct module_env* env,
struct dns_msg* msg;
if(FLAGS_GET_RCODE(data->flags) == LDNS_RCODE_NXDOMAIN
&& data->security == sec_status_secure
+ && (data->an_numrrsets == 0 ||
+ ntohs(data->rrsets[0]->rk.type) != LDNS_RR_TYPE_CNAME)
&& (msg=tomsg(env, &k, data, region, now, scratch))){
lock_rw_unlock(&e->lock);
msg->qinfo.qname=qname;
msg->qinfo.qname_len=qnamelen;
/* check that DNSSEC really works out */
msg->rep->security = sec_status_unchecked;
+ iter_scrub_nxdomain(msg);
return msg;
}
lock_rw_unlock(&e->lock);
diff --git a/services/listen_dnsport.c b/services/listen_dnsport.c
index e74d1abcffc5..7e2afd843be8 100644
--- a/services/listen_dnsport.c
+++ b/services/listen_dnsport.c
@@ -851,13 +851,16 @@ create_tcp_accept_sock(struct addrinfo *addr, int v6only, int* noproto,
#ifdef ENOPROTOOPT
/* squelch ENOPROTOOPT: freebsd server mode with kernel support
disabled, except when verbosity enabled for debugging */
- if(errno != ENOPROTOOPT || verbosity >= 3)
+ if(errno != ENOPROTOOPT || verbosity >= 3) {
#endif
if(errno == EPERM) {
log_warn("Setting TCP Fast Open as server failed: %s ; this could likely be because sysctl net.inet.tcp.fastopen.enabled, net.inet.tcp.fastopen.server_enable, or net.ipv4.tcp_fastopen is disabled", strerror(errno));
} else {
log_err("Setting TCP Fast Open as server failed: %s", strerror(errno));
}
+#ifdef ENOPROTOOPT
+ }
+#endif
}
#endif
return s;
@@ -1749,6 +1752,7 @@ tcp_req_info_handle_readdone(struct tcp_req_info* req)
req->is_drop = 0;
req->is_reply = 0;
req->in_worker_handle = 1;
+ sldns_buffer_set_limit(req->spool_buffer, 0);
/* handle the current request */
/* this calls the worker handle request routine that could give
* a cache response, or localdata response, or drop the reply,
@@ -1771,24 +1775,12 @@ tcp_req_info_handle_readdone(struct tcp_req_info* req)
* If mesh failed to add a new entry and called commpoint_drop_reply.
* Then the mesh state has been cleared. */
if(req->is_drop) {
- /* we can now call drop_reply without recursing into ourselves
- * whilst in the callback */
- /* we have to close the stream because there is no reply,
- * no servfail to send, but the query needs an action, for
- * a stream that is close the connection */
- sldns_buffer_clear(c->buffer);
- comm_point_drop_reply(&c->repinfo);
+ /* the reply has been dropped, stream has been closed. */
return;
}
/* If mesh failed(mallocfail) and called commpoint_send_reply with
* something like servfail then we pick up that reply below. */
if(req->is_reply) {
- /* reply from mesh is in the spool_buffer */
- sldns_buffer_clear(c->buffer);
- sldns_buffer_write(c->buffer,
- sldns_buffer_begin(req->spool_buffer),
- sldns_buffer_limit(req->spool_buffer));
- sldns_buffer_flip(c->buffer);
goto send_it;
}
@@ -1867,7 +1859,14 @@ void
tcp_req_info_send_reply(struct tcp_req_info* req)
{
if(req->in_worker_handle) {
- /* It is in the right buffer to answer straight away */
+ /* reply from mesh is in the spool_buffer */
+ /* copy now, so that the spool buffer is free for other tasks
+ * before the callback is done */
+ sldns_buffer_clear(req->cp->buffer);
+ sldns_buffer_write(req->cp->buffer,
+ sldns_buffer_begin(req->spool_buffer),
+ sldns_buffer_limit(req->spool_buffer));
+ sldns_buffer_flip(req->cp->buffer);
req->is_reply = 1;
return;
}
diff --git a/services/mesh.c b/services/mesh.c
index bee0f76a4ad6..59ee9a08ec0e 100644
--- a/services/mesh.c
+++ b/services/mesh.c
@@ -354,6 +354,10 @@ void mesh_new_client(struct mesh_area* mesh, struct query_info* qinfo,
int was_detached = 0;
int was_noreply = 0;
int added = 0;
+ struct sldns_buffer* r_buffer = rep->c->buffer;
+ if(rep->c->tcp_req_info) {
+ r_buffer = rep->c->tcp_req_info->spool_buffer;
+ }
if(!unique)
s = mesh_area_find(mesh, cinfo, qinfo, qflags&(BIT_RD|BIT_CD), 0, 0);
/* does this create a new reply state? */
@@ -389,7 +393,7 @@ void mesh_new_client(struct mesh_area* mesh, struct query_info* qinfo,
if(!inplace_cb_reply_servfail_call(mesh->env, qinfo, NULL, NULL,
LDNS_RCODE_SERVFAIL, edns, rep, mesh->env->scratch))
edns->opt_list = NULL;
- error_encode(rep->c->buffer, LDNS_RCODE_SERVFAIL,
+ error_encode(r_buffer, LDNS_RCODE_SERVFAIL,
qinfo, qid, qflags, edns);
comm_point_send_reply(rep);
return;
@@ -405,7 +409,7 @@ void mesh_new_client(struct mesh_area* mesh, struct query_info* qinfo,
if(!inplace_cb_reply_servfail_call(mesh->env, qinfo, NULL,
NULL, LDNS_RCODE_SERVFAIL, edns, rep, mesh->env->scratch))
edns->opt_list = NULL;
- error_encode(rep->c->buffer, LDNS_RCODE_SERVFAIL,
+ error_encode(r_buffer, LDNS_RCODE_SERVFAIL,
qinfo, qid, qflags, edns);
comm_point_send_reply(rep);
return;
@@ -434,7 +438,7 @@ void mesh_new_client(struct mesh_area* mesh, struct query_info* qinfo,
if(!inplace_cb_reply_servfail_call(mesh->env, qinfo, &s->s,
NULL, LDNS_RCODE_SERVFAIL, edns, rep, mesh->env->scratch))
edns->opt_list = NULL;
- error_encode(rep->c->buffer, LDNS_RCODE_SERVFAIL,
+ error_encode(r_buffer, LDNS_RCODE_SERVFAIL,
qinfo, qid, qflags, edns);
comm_point_send_reply(rep);
if(added)
@@ -1192,12 +1196,16 @@ void mesh_query_done(struct mesh_state* mstate)
comm_point_drop_reply(&r->query_reply);
else {
struct sldns_buffer* r_buffer = r->query_reply.c->buffer;
- if(r->query_reply.c->tcp_req_info)
+ if(r->query_reply.c->tcp_req_info) {
r_buffer = r->query_reply.c->tcp_req_info->spool_buffer;
+ prev_buffer = NULL;
+ }
mesh_send_reply(mstate, mstate->s.return_rcode, rep,
r, r_buffer, prev, prev_buffer);
- if(r->query_reply.c->tcp_req_info)
+ if(r->query_reply.c->tcp_req_info) {
tcp_req_info_remove_mesh_state(r->query_reply.c->tcp_req_info, mstate);
+ r_buffer = NULL;
+ }
prev = r;
prev_buffer = r_buffer;
}
@@ -1341,21 +1349,14 @@ int mesh_state_add_reply(struct mesh_state* s, struct edns_data* edns,
log_assert(qinfo->local_alias->rrset->rk.dname ==
sldns_buffer_at(rep->c->buffer, LDNS_HEADER_SIZE));
- d = regional_alloc_init(s->s.region, dsrc,
- sizeof(struct packed_rrset_data)
- + sizeof(size_t) + sizeof(uint8_t*) + sizeof(time_t));
+ /* the rrset is not packed, like in the cache, but it is
+ * individualy allocated with an allocator from localzone. */
+ d = regional_alloc_zero(s->s.region, sizeof(*d));
if(!d)
return 0;
r->local_alias->rrset->entry.data = d;
- d->rr_len = (size_t*)((uint8_t*)d +
- sizeof(struct packed_rrset_data));
- d->rr_data = (uint8_t**)&(d->rr_len[1]);
- d->rr_ttl = (time_t*)&(d->rr_data[1]);
- d->rr_len[0] = dsrc->rr_len[0];
- d->rr_ttl[0] = dsrc->rr_ttl[0];
- d->rr_data[0] = regional_alloc_init(s->s.region,
- dsrc->rr_data[0], d->rr_len[0]);
- if(!d->rr_data[0])
+ if(!rrset_insert_rr(s->s.region, d, dsrc->rr_data[0],
+ dsrc->rr_len[0], dsrc->rr_ttl[0], "CNAME local alias"))
return 0;
} else
r->local_alias = NULL;
diff --git a/services/outside_network.c b/services/outside_network.c
index 16d63df4395a..0323f1b30c93 100644
--- a/services/outside_network.c
+++ b/services/outside_network.c
@@ -364,6 +364,8 @@ outnet_tcp_take_into_use(struct waiting_tcp* w, uint8_t* pkt, size_t pkt_len)
comm_point_close(pend->c);
return 0;
}
+ verbose(VERB_ALGO, "the query is using TLS encryption, for %s",
+ (w->tls_auth_name?w->tls_auth_name:"an unauthenticated connection"));
#ifdef USE_WINSOCK
comm_point_tcp_win_bio_cb(pend->c, pend->c->ssl);
#endif
@@ -404,6 +406,8 @@ outnet_tcp_take_into_use(struct waiting_tcp* w, uint8_t* pkt, size_t pkt_len)
}
SSL_set_verify(pend->c->ssl, SSL_VERIFY_PEER, NULL);
}
+#else
+ verbose(VERB_ALGO, "the query has an auth_name, but libssl has no call to perform TLS authentication");
#endif /* HAVE_SSL_SET1_HOST */
}
w->pkt = NULL;
@@ -2277,11 +2281,60 @@ outnet_comm_point_for_udp(struct outside_network* outnet,
return cp;
}
+/** setup SSL for comm point */
+static int
+setup_comm_ssl(struct comm_point* cp, struct outside_network* outnet,
+ int fd, char* host)
+{
+ cp->ssl = outgoing_ssl_fd(outnet->sslctx, fd);
+ if(!cp->ssl) {
+ log_err("cannot create SSL object");
+ return 0;
+ }
+#ifdef USE_WINSOCK
+ comm_point_tcp_win_bio_cb(cp, cp->ssl);
+#endif
+ cp->ssl_shake_state = comm_ssl_shake_write;
+ /* https verification */
+#ifdef HAVE_SSL_SET1_HOST
+ if((SSL_CTX_get_verify_mode(outnet->sslctx)&SSL_VERIFY_PEER)) {
+ /* because we set SSL_VERIFY_PEER, in netevent in
+ * ssl_handshake, it'll check if the certificate
+ * verification has succeeded */
+ /* SSL_VERIFY_PEER is set on the sslctx */
+ /* and the certificates to verify with are loaded into
+ * it with SSL_load_verify_locations or
+ * SSL_CTX_set_default_verify_paths */
+ /* setting the hostname makes openssl verify the
+ * host name in the x509 certificate in the
+ * SSL connection*/
+ if(!SSL_set1_host(cp->ssl, host)) {
+ log_err("SSL_set1_host failed");
+ return 0;
+ }
+ }
+#elif defined(HAVE_X509_VERIFY_PARAM_SET1_HOST)
+ /* openssl 1.0.2 has this function that can be used for
+ * set1_host like verification */
+ if((SSL_CTX_get_verify_mode(outnet->sslctx)&SSL_VERIFY_PEER)) {
+ X509_VERIFY_PARAM* param = SSL_get0_param(cp->ssl);
+ X509_VERIFY_PARAM_set_hostflags(param, X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS);
+ if(!X509_VERIFY_PARAM_set1_host(param, host, strlen(host))) {
+ log_err("X509_VERIFY_PARAM_set1_host failed");
+ return 0;
+ }
+ }
+#else
+ (void)host;
+#endif /* HAVE_SSL_SET1_HOST */
+ return 1;
+}
+
struct comm_point*
outnet_comm_point_for_tcp(struct outside_network* outnet,
comm_point_callback_type* cb, void* cb_arg,
struct sockaddr_storage* to_addr, socklen_t to_addrlen,
- sldns_buffer* query, int timeout)
+ sldns_buffer* query, int timeout, int ssl, char* host)
{
struct comm_point* cp;
int fd = outnet_get_tcp_fd(to_addr, to_addrlen, outnet->tcp_mss);
@@ -2301,6 +2354,16 @@ outnet_comm_point_for_tcp(struct outside_network* outnet,
}
cp->repinfo.addrlen = to_addrlen;
memcpy(&cp->repinfo.addr, to_addr, to_addrlen);
+
+ /* setup for SSL (if needed) */
+ if(ssl) {
+ if(!setup_comm_ssl(cp, outnet, fd, host)) {
+ log_err("cannot setup XoT");
+ comm_point_delete(cp);
+ return NULL;
+ }
+ }
+
/* set timeout on TCP connection */
comm_point_start_listening(cp, fd, timeout);
/* copy scratch buffer to cp->buffer */
@@ -2357,48 +2420,11 @@ outnet_comm_point_for_http(struct outside_network* outnet,
/* setup for SSL (if needed) */
if(ssl) {
- cp->ssl = outgoing_ssl_fd(outnet->sslctx, fd);
- if(!cp->ssl) {
+ if(!setup_comm_ssl(cp, outnet, fd, host)) {
log_err("cannot setup https");
comm_point_delete(cp);
return NULL;
}
-#ifdef USE_WINSOCK
- comm_point_tcp_win_bio_cb(cp, cp->ssl);
-#endif
- cp->ssl_shake_state = comm_ssl_shake_write;
- /* https verification */
-#ifdef HAVE_SSL_SET1_HOST
- if((SSL_CTX_get_verify_mode(outnet->sslctx)&SSL_VERIFY_PEER)) {
- /* because we set SSL_VERIFY_PEER, in netevent in
- * ssl_handshake, it'll check if the certificate
- * verification has succeeded */
- /* SSL_VERIFY_PEER is set on the sslctx */
- /* and the certificates to verify with are loaded into
- * it with SSL_load_verify_locations or
- * SSL_CTX_set_default_verify_paths */
- /* setting the hostname makes openssl verify the
- * host name in the x509 certificate in the
- * SSL connection*/
- if(!SSL_set1_host(cp->ssl, host)) {
- log_err("SSL_set1_host failed");
- comm_point_delete(cp);
- return NULL;
- }
- }
-#elif defined(HAVE_X509_VERIFY_PARAM_SET1_HOST)
- /* openssl 1.0.2 has this function that can be used for
- * set1_host like verification */
- if((SSL_CTX_get_verify_mode(outnet->sslctx)&SSL_VERIFY_PEER)) {
- X509_VERIFY_PARAM* param = SSL_get0_param(cp->ssl);
- X509_VERIFY_PARAM_set_hostflags(param, X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS);
- if(!X509_VERIFY_PARAM_set1_host(param, host, strlen(host))) {
- log_err("X509_VERIFY_PARAM_set1_host failed");
- comm_point_delete(cp);
- return NULL;
- }
- }
-#endif /* HAVE_SSL_SET1_HOST */
}
/* set timeout on TCP connection */
diff --git a/services/outside_network.h b/services/outside_network.h
index 48ef03edba7c..3456a3da38b0 100644
--- a/services/outside_network.h
+++ b/services/outside_network.h
@@ -570,12 +570,14 @@ struct comm_point* outnet_comm_point_for_udp(struct outside_network* outnet,
* @param timeout: timeout for the TCP connection.
* timeout in milliseconds, or -1 for no (change to the) timeout.
* So seconds*1000.
+ * @param ssl: set to true for TLS.
+ * @param host: hostname for host name verification of TLS (or NULL if no TLS).
* @return tcp_out commpoint, or NULL.
*/
struct comm_point* outnet_comm_point_for_tcp(struct outside_network* outnet,
comm_point_callback_type* cb, void* cb_arg,
struct sockaddr_storage* to_addr, socklen_t to_addrlen,
- struct sldns_buffer* query, int timeout);
+ struct sldns_buffer* query, int timeout, int ssl, char* host);
/**
* Create http commpoint suitable for communication to the destination.
diff --git a/testcode/fake_event.c b/testcode/fake_event.c
index 4fb9bc8ed683..713e247592b7 100644
--- a/testcode/fake_event.c
+++ b/testcode/fake_event.c
@@ -1629,7 +1629,8 @@ struct comm_point* outnet_comm_point_for_udp(struct outside_network* outnet,
struct comm_point* outnet_comm_point_for_tcp(struct outside_network* outnet,
comm_point_callback_type* cb, void* cb_arg,
struct sockaddr_storage* to_addr, socklen_t to_addrlen,
- struct sldns_buffer* query, int timeout)
+ struct sldns_buffer* query, int timeout, int ATTR_UNUSED(ssl),
+ char* ATTR_UNUSED(host))
{
struct replay_runtime* runtime = (struct replay_runtime*)
outnet->base;
diff --git a/testdata/auth_nsec3_ent.rpl b/testdata/auth_nsec3_ent.rpl
new file mode 100644
index 000000000000..5730c8d52326
--- /dev/null
+++ b/testdata/auth_nsec3_ent.rpl
@@ -0,0 +1,224 @@
+; config options
+server:
+ target-fetch-policy: "0 0 0 0 0"
+
+auth-zone:
+ name: "unbound-auth-test.nlnetlabs.nl."
+ ## zonefile (or none).
+ ## zonefile: "example.com.zone"
+ ## master by IP address or hostname
+ ## can list multiple masters, each on one line.
+ ## master:
+ ## url for http fetch
+ ## url:
+ ## queries from downstream clients get authoritative answers.
+ ## for-downstream: yes
+ for-downstream: yes
+ ## queries are used to fetch authoritative answers from this zone,
+ ## instead of unbound itself sending queries there.
+ ## for-upstream: yes
+ for-upstream: yes
+ ## on failures with for-upstream, fallback to sending queries to
+ ## the authority servers
+ ## fallback-enabled: no
+
+ ## this line generates zonefile: \n"/tmp/xxx.example.com"\n
+ zonefile:
+TEMPFILE_NAME unbound-auth-test.nlnetlabs.nl
+ ## this is the inline file /tmp/xxx.unbound-auth-test.nlnetlabs.nl
+ ## the tempfiles are deleted when the testrun is over.
+TEMPFILE_CONTENTS unbound-auth-test.nlnetlabs.nl
+;; Zone: unbound-auth-test.nlnetlabs.nl.
+;
+unbound-auth-test.nlnetlabs.nl. 3600 IN SOA ns.nlnetlabs.nl. ralph.nlnetlabs.nl. 1554201247 14400 3600 604800 3600
+unbound-auth-test.nlnetlabs.nl. 3600 IN RRSIG SOA 13 3 3600 20190430103407 20190402103407 15486 unbound-auth-test.nlnetlabs.nl. NLFcC2oet+HC+1dhT4D/2JJFIcMiRtTM81KwvT7u8ybF3iDE4bnyrILvQk8DsizpYKwk+D3J3tMC3TV5+//qFw==
+;
+unbound-auth-test.nlnetlabs.nl. 3600 IN NS ns.nlnetlabs.nl.
+unbound-auth-test.nlnetlabs.nl. 3600 IN RRSIG NS 13 3 3600 20190430103407 20190402103407 15486 unbound-auth-test.nlnetlabs.nl. Gm0UF77ljiInG4/HZ6Tkzx7z9N45WwwmbBt9KxeN3z1BkdBLiy10Du71ZBFLP71b+USs1rv5SJQ0hteZFbl8sg==
+unbound-auth-test.nlnetlabs.nl. 3600 IN DNSKEY 256 3 13 S3Da9HqpFj0pEbI8WXOdkvN3vgZ6qxNSz4XyKkmWWAG28kq5T+/lWp36DUDvnMI9wJNuixzUHtgZ6oZoAaVrPg== ;{id = 15486 (zsk), size = 256b}
+unbound-auth-test.nlnetlabs.nl. 3600 IN RRSIG DNSKEY 13 3 3600 20190430103407 20190402103407 15486 unbound-auth-test.nlnetlabs.nl. 1cLFaDb6kP8KnRJujW1ieHUdS5Tgdv59TCZ+FloCRJMJBwQAow6UKAIY7HHlTb8IHTajyUrjlxX/dN8S/5VwuA==
+unbound-auth-test.nlnetlabs.nl. 3600 IN NSEC3PARAM 1 0 1 -
+unbound-auth-test.nlnetlabs.nl. 3600 IN RRSIG NSEC3PARAM 13 3 3600 20190430103407 20190402103407 15486 unbound-auth-test.nlnetlabs.nl. GWgtJArNpfJ4ifoinUBUVRTlkk0CMemdozhMKY13dk3EQMP0jb4g49PcTAgEP2dBUs9efttQVQQpmFPyTGfN1w==
+tvdhfml24jp7cott1qijj9812qu9ibh3.unbound-auth-test.nlnetlabs.nl. 3600 IN NSEC3 1 0 1 - 41pcah2j3fr8k99gj5pveh4igrjfc871 NS SOA RRSIG DNSKEY NSEC3PARAM ;{ flags: -, from: unbound-auth-test.nlnetlabs.nl. to: b.b.unbound-auth-test.nlnetlabs.nl.}
+tvdhfml24jp7cott1qijj9812qu9ibh3.unbound-auth-test.nlnetlabs.nl. 3600 IN RRSIG NSEC3 13 4 3600 20190430103407 20190402103407 15486 unbound-auth-test.nlnetlabs.nl. DzwQTaZj4j29eHXEKllIFcq4yNWA7VMqkh8+gCrBO+GEek9+hGxL6ANsU0Hv6glyBmPDeYUZcy4xy0EEj1R4hQ==
+;
+;; Empty nonterminal: b.unbound-auth-test.nlnetlabs.nl.
+apejmh1fqds9gir0nnsf4d5gtno10tg1.unbound-auth-test.nlnetlabs.nl. 3600 IN NSEC3 1 0 1 - dbs0aj50410urbvt3ghfr644n7h06gs5 ;{ flags: -, from: b.unbound-auth-test.nlnetlabs.nl. to: c.b.unbound-auth-test.nlnetlabs.nl.}
+apejmh1fqds9gir0nnsf4d5gtno10tg1.unbound-auth-test.nlnetlabs.nl. 3600 IN RRSIG NSEC3 13 4 3600 20190430103407 20190402103407 15486 unbound-auth-test.nlnetlabs.nl. m9B0W8xDZF6ml/m8OujrZZBiF1O0wAeKciK/5FMT/hCjHR0hMrbXBPg/ZntpVJD/Pko2HcBvWKu87U721yTHyQ==
+;
+;; Empty nonterminal: a.b.unbound-auth-test.nlnetlabs.nl.
+toqivctpt4pdcp5g19neqt19fvtgbgeu.unbound-auth-test.nlnetlabs.nl. 3600 IN NSEC3 1 0 1 - tvdhfml24jp7cott1qijj9812qu9ibh3 ;{ flags: -, from: a.b.unbound-auth-test.nlnetlabs.nl. to: unbound-auth-test.nlnetlabs.nl.}
+toqivctpt4pdcp5g19neqt19fvtgbgeu.unbound-auth-test.nlnetlabs.nl. 3600 IN RRSIG NSEC3 13 4 3600 20190430103407 20190402103407 15486 unbound-auth-test.nlnetlabs.nl. Jr1oPPs+DGBVV13n4gG4AGVFsleItluLbtCIyQDcYZEA+e5JMkrLzfW3rXqXaUSUauR4iEu5FmTfs4GTsumdUw==
+;
+*.a.b.unbound-auth-test.nlnetlabs.nl. 3600 IN TXT "*.a.b"
+*.a.b.unbound-auth-test.nlnetlabs.nl. 3600 IN RRSIG TXT 13 5 3600 20190430103407 20190402103407 15486 unbound-auth-test.nlnetlabs.nl. NrMUaNzZp88lXit/HLL/iDBHspDSfoM//K+/0VwUYRZjmVJQQHCHtHBGgR4NgrLi3ffvCAWq2LNGxDm+YMSl3g==
+jrtu61ssgd18lfjglqrbbs5b2vmbh6cl.unbound-auth-test.nlnetlabs.nl. 3600 IN NSEC3 1 0 1 - k8r2bchsbehs5dbu5d6ivjfnmjb3jc8s TXT RRSIG ;{ flags: -, from: *.a.b.unbound-auth-test.nlnetlabs.nl. to: *.c.b.unbound-auth-test.nlnetlabs.nl.}
+jrtu61ssgd18lfjglqrbbs5b2vmbh6cl.unbound-auth-test.nlnetlabs.nl. 3600 IN RRSIG NSEC3 13 4 3600 20190430103407 20190402103407 15486 unbound-auth-test.nlnetlabs.nl. kLIhE9+iz1OybJwXbtRJZst+Mk5u4OAtpZGWSwJUfqD6dXAk+h6msKAR18jpPeL7cCjXjIAKIv3x4oYRkl+uKw==
+;
+;; Empty nonterminal: b.b.unbound-auth-test.nlnetlabs.nl.
+41pcah2j3fr8k99gj5pveh4igrjfc871.unbound-auth-test.nlnetlabs.nl. 3600 IN NSEC3 1 0 1 - apejmh1fqds9gir0nnsf4d5gtno10tg1 ;{ flags: -, from: b.b.unbound-auth-test.nlnetlabs.nl. to: b.unbound-auth-test.nlnetlabs.nl.}
+41pcah2j3fr8k99gj5pveh4igrjfc871.unbound-auth-test.nlnetlabs.nl. 3600 IN RRSIG NSEC3 13 4 3600 20190430103407 20190402103407 15486 unbound-auth-test.nlnetlabs.nl. XlIjnuF313w0GXn6vymrAcsyuxZSaN6IShFjxQ5T2HUFePHBNvtRkL+TtMQZNlR8nTR3+MWcON0cOZIGjVCCjg==
+;
+*.b.b.unbound-auth-test.nlnetlabs.nl. 3600 IN TXT "*.b.b"
+*.b.b.unbound-auth-test.nlnetlabs.nl. 3600 IN RRSIG TXT 13 5 3600 20190430103407 20190402103407 15486 unbound-auth-test.nlnetlabs.nl. FkS3ceWpoHyOKaa8OtywIl148Bwo0vkzBd263vqYe0puhuRa6IvNEk5ERdwfWt9eNEq+6IlizPT/dYxA2fXYXA==
+ft7dasbom0copm9e2ak9k151dj08kjfs.unbound-auth-test.nlnetlabs.nl. 3600 IN NSEC3 1 0 1 - jrtu61ssgd18lfjglqrbbs5b2vmbh6cl TXT RRSIG ;{ flags: -, from: *.b.b.unbound-auth-test.nlnetlabs.nl. to: *.a.b.unbound-auth-test.nlnetlabs.nl.}
+ft7dasbom0copm9e2ak9k151dj08kjfs.unbound-auth-test.nlnetlabs.nl. 3600 IN RRSIG NSEC3 13 4 3600 20190430103407 20190402103407 15486 unbound-auth-test.nlnetlabs.nl. 5QhLGohTRLQSGC8vstzDjqcwfrbOnLUG2OelSjvsZFy1smsWUxJBCQXQdx1+JX7xamZHlZESQtS+cELuZUqpvA==
+;
+;; Empty nonterminal: c.b.unbound-auth-test.nlnetlabs.nl.
+dbs0aj50410urbvt3ghfr644n7h06gs5.unbound-auth-test.nlnetlabs.nl. 3600 IN NSEC3 1 0 1 - ft7dasbom0copm9e2ak9k151dj08kjfs ;{ flags: -, from: c.b.unbound-auth-test.nlnetlabs.nl. to: *.b.b.unbound-auth-test.nlnetlabs.nl.}
+dbs0aj50410urbvt3ghfr644n7h06gs5.unbound-auth-test.nlnetlabs.nl. 3600 IN RRSIG NSEC3 13 4 3600 20190430103407 20190402103407 15486 unbound-auth-test.nlnetlabs.nl. hjk1foJWW68JK3O1Ktf0ZogoXVrMDw3mHVBBYTrpaBKX1gWR5icmJiOCYZWYx3z88PUnGkfH+kx4oDUjioqN+Q==
+;
+*.c.b.unbound-auth-test.nlnetlabs.nl. 3600 IN TXT "*.c.b"
+*.c.b.unbound-auth-test.nlnetlabs.nl. 3600 IN RRSIG TXT 13 5 3600 20190430103407 20190402103407 15486 unbound-auth-test.nlnetlabs.nl. b7rFR5tlx5Y5SQqNdYBtfD6DrkNx9h79GCmnZfWrUzRz+A256k2v08IPRJDK+WxEHuYHjfNnVWxjRr9M1OW2Iw==
+k8r2bchsbehs5dbu5d6ivjfnmjb3jc8s.unbound-auth-test.nlnetlabs.nl. 3600 IN NSEC3 1 0 1 - toqivctpt4pdcp5g19neqt19fvtgbgeu TXT RRSIG ;{ flags: -, from: *.c.b.unbound-auth-test.nlnetlabs.nl. to: a.b.unbound-auth-test.nlnetlabs.nl.}
+k8r2bchsbehs5dbu5d6ivjfnmjb3jc8s.unbound-auth-test.nlnetlabs.nl. 3600 IN RRSIG NSEC3 13 4 3600 20190430103407 20190402103407 15486 unbound-auth-test.nlnetlabs.nl. 34BS1ajedCNdfXgUfxTyiAK1ichfFLshhJ3TnfplrUps0UsZaQLEG+EIlP4wTBtro2c6V8YCSmOuxuce4gYoDw==
+;
+TEMPFILE_END
+
+stub-zone:
+ name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN Test authority zone with NSEC3 empty nonterminal
+; with exact match NSEC3 in existence (eg. not a CE-proof)
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.44
+ENTRY_END
+RANGE_END
+
+; ns.example.net.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.44
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.net. IN NS
+SECTION ANSWER
+example.net. IN NS ns.example.net.
+SECTION ADDITIONAL
+ns.example.net. IN A 1.2.3.44
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.net. IN A
+SECTION ANSWER
+ns.example.net. IN A 1.2.3.44
+SECTION AUTHORITY
+example.net. IN NS ns.example.net.
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.net. IN AAAA
+SECTION AUTHORITY
+example.net. IN NS ns.example.net.
+SECTION ADDITIONAL
+www.example.net. IN A 1.2.3.44
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.net.
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+a.b.unbound-auth-test.nlnetlabs.nl. IN TXT
+ENTRY_END
+
+; recursion happens here.
+STEP 20 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR AA RD RA DO NOERROR
+SECTION QUESTION
+a.b.unbound-auth-test.nlnetlabs.nl. IN TXT
+SECTION ANSWER
+SECTION AUTHORITY
+unbound-auth-test.nlnetlabs.nl. 3600 IN SOA ns.nlnetlabs.nl. ralph.nlnetlabs.nl. 1554201247 14400 3600 604800 3600
+unbound-auth-test.nlnetlabs.nl. 3600 IN RRSIG SOA 13 3 3600 20190430103407 20190402103407 15486 unbound-auth-test.nlnetlabs.nl. NLFcC2oet+HC+1dhT4D/2JJFIcMiRtTM81KwvT7u8ybF3iDE4bnyrILv Qk8DsizpYKwk+D3J3tMC3TV5+//qFw==
+toqivctpt4pdcp5g19neqt19fvtgbgeu.unbound-auth-test.nlnetlabs.nl. 3600 IN NSEC3 1 0 1 - TVDHFML24JP7COTT1QIJJ9812QU9IBH3
+toqivctpt4pdcp5g19neqt19fvtgbgeu.unbound-auth-test.nlnetlabs.nl. 3600 IN RRSIG NSEC3 13 4 3600 20190430103407 20190402103407 15486 unbound-auth-test.nlnetlabs.nl. Jr1oPPs+DGBVV13n4gG4AGVFsleItluLbtCIyQDcYZEA+e5JMkrLzfW3 rXqXaUSUauR4iEu5FmTfs4GTsumdUw==
+ENTRY_END
+
+SCENARIO_END
diff --git a/testdata/auth_nsec3_wild.rpl b/testdata/auth_nsec3_wild.rpl
index acfe63bae8ce..1aeeebacc088 100644
--- a/testdata/auth_nsec3_wild.rpl
+++ b/testdata/auth_nsec3_wild.rpl
@@ -200,4 +200,31 @@ i6pi4e3o98e7vtkpjfhqn7g77d3mjcnv.test-ns-signed.dev.internet.nl. 3600 IN NSEC3 1
i6pi4e3o98e7vtkpjfhqn7g77d3mjcnv.test-ns-signed.dev.internet.nl. 3600 IN RRSIG NSEC3 8 5 3600 20190205132351 20190108132351 32784 test-ns-signed.dev.internet.nl. xLysIqn3r3rdHE3GvwVjZwUyuFClhkhgrQdwyc66RuHKE3MfSuhVr9cHTCJzhipF5TwQTbUpLOr74r99bzdiIY8Xkgjy2M0nc76v1ObSGJdPPjGTevbhDOnavUURwOR/q0NqqO2iPrgFjOVMZ+8uwRJtCty2iAVZfVG+qDzs8hU=
ENTRY_END
+; Check that the reply for a wildcard nodata answer contains the NSEC3s.
+; qname denial NSEC3, closest encloser NSEC3, and type bitmap NSEC3.
+STEP 30 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+something.a.b.test-ns-signed.dev.internet.nl. IN AAAA
+ENTRY_END
+
+STEP 40 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR AA RD RA DO NOERROR
+SECTION QUESTION
+something.a.b.test-ns-signed.dev.internet.nl. IN AAAA
+SECTION ANSWER
+SECTION AUTHORITY
+test-ns-signed.dev.internet.nl. 3600 IN SOA ns.nlnetlabs.nl. ralph.nlnetlabs.nl. 4 14400 3600 604800 3600
+test-ns-signed.dev.internet.nl. 3600 IN RRSIG SOA 8 4 3600 20190205132351 20190108132351 32784 test-ns-signed.dev.internet.nl. ybb0Hc7NC+QOFEEv4cX2+Umlk+miiOAHmeP2Uwvg6lqfxkk+3g7yWBEKMinXjLKz0odWZ6fki6M/3yBPQX8SV0OCRY5gYvAHAjbxAIHozIM+5iwOkRQhNF1DRgQ3BLjL93f6T5e5Z4y1812iOpu4GYswXW/UTOZACXz2UiaCPAg= ;{id = 32784}
+7ag3p2pfrvq09dpn63cvga8ub1rnrrg1.test-ns-signed.dev.internet.nl. 3600 IN NSEC3 1 0 1 - 93stp7o7i5n9gb83uu7vv6h8qltk14ig TXT RRSIG
+7ag3p2pfrvq09dpn63cvga8ub1rnrrg1.test-ns-signed.dev.internet.nl. 3600 IN RRSIG NSEC3 8 5 3600 20190205132351 20190108132351 32784 test-ns-signed.dev.internet.nl. gtxoiTa3FRUqoRLvkWSxmWQ+DfijVd26gpKH3+GmGIcNB/sr/Cf8kERRwVVHvgzYIcvdJcys5b2LUXnZJwcdAlx7efZPWgNZzWxJrw6ES25LCWJOrp31isWn9FlAZGIbnpyEXxD2apBSmtyPnKbTgU6lHHS9jrsYHu4G8Zouv3k= ;{id = 32784}
+fee0c2kfhi6bnljce6vehaenqq3pbupu.test-ns-signed.dev.internet.nl. 3600 IN NSEC3 1 0 1 - i6pi4e3o98e7vtkpjfhqn7g77d3mjcnv
+fee0c2kfhi6bnljce6vehaenqq3pbupu.test-ns-signed.dev.internet.nl. 3600 IN RRSIG NSEC3 8 5 3600 20190205132351 20190108132351 32784 test-ns-signed.dev.internet.nl. WIb3ISP1nlafbyWoWa4z7sG5IS+V86PyvEMHdD/64hgsFkrCu483XK7VNnBz28SL/631JXA1R19O+UxeWhTUyctp8QSt6cEZcMPY8b7yG97rNFNvhSw75rSXXt+JwgIYHPHQV5oqPtVmEpQM5SfJd+hs+Nn1bJcWB3UaESNNAMQ= ;{id = 32784}
+i6pi4e3o98e7vtkpjfhqn7g77d3mjcnv.test-ns-signed.dev.internet.nl. 3600 IN NSEC3 1 0 1 - kl94uofq16t2vlq0bmampf6e4o9k5hbi A AAAA RRSIG
+i6pi4e3o98e7vtkpjfhqn7g77d3mjcnv.test-ns-signed.dev.internet.nl. 3600 IN RRSIG NSEC3 8 5 3600 20190205132351 20190108132351 32784 test-ns-signed.dev.internet.nl. xLysIqn3r3rdHE3GvwVjZwUyuFClhkhgrQdwyc66RuHKE3MfSuhVr9cHTCJzhipF5TwQTbUpLOr74r99bzdiIY8Xkgjy2M0nc76v1ObSGJdPPjGTevbhDOnavUURwOR/q0NqqO2iPrgFjOVMZ+8uwRJtCty2iAVZfVG+qDzs8hU= ;{id = 32784}
+ENTRY_END
+
SCENARIO_END
diff --git a/util/alloc.c b/util/alloc.c
index 908b1f42361f..7e9618931ca6 100644
--- a/util/alloc.c
+++ b/util/alloc.c
@@ -376,6 +376,7 @@ void *unbound_stat_malloc(size_t size)
{
void* res;
if(size == 0) size = 1;
+ log_assert(size <= SIZE_MAX-16);
res = malloc(size+16);
if(!res) return NULL;
unbound_mem_alloc += size;
@@ -398,6 +399,7 @@ void *unbound_stat_calloc(size_t nmemb, size_t size)
if(nmemb != 0 && INT_MAX/nmemb < size)
return NULL; /* integer overflow check */
s = (nmemb*size==0)?(size_t)1:nmemb*size;
+ log_assert(s <= SIZE_MAX-16);
res = calloc(1, s+16);
if(!res) return NULL;
log_info("stat %p=calloc(%u, %u)", res+16, (unsigned)nmemb, (unsigned)size);
@@ -447,6 +449,7 @@ void *unbound_stat_realloc(void *ptr, size_t size)
/* nothing changes */
return ptr;
}
+ log_assert(size <= SIZE_MAX-16);
res = malloc(size+16);
if(!res) return NULL;
unbound_mem_alloc += size;
@@ -521,7 +524,9 @@ void *unbound_stat_malloc_lite(size_t size, const char* file, int line,
const char* func)
{
/* [prefix .. len .. actual data .. suffix] */
- void* res = malloc(size+lite_pad*2+sizeof(size_t));
+ void* res;
+ log_assert(size <= SIZE_MAX-(lite_pad*2+sizeof(size_t)));
+ res = malloc(size+lite_pad*2+sizeof(size_t));
if(!res) return NULL;
memmove(res, lite_pre, lite_pad);
memmove(res+lite_pad, &size, sizeof(size_t));
@@ -538,6 +543,7 @@ void *unbound_stat_calloc_lite(size_t nmemb, size_t size, const char* file,
if(nmemb != 0 && INT_MAX/nmemb < size)
return NULL; /* integer overflow check */
req = nmemb * size;
+ log_assert(req <= SIZE_MAX-(lite_pad*2+sizeof(size_t)));
res = malloc(req+lite_pad*2+sizeof(size_t));
if(!res) return NULL;
memmove(res, lite_pre, lite_pad);
diff --git a/util/data/msgreply.h b/util/data/msgreply.h
index a455c4d2b374..8d75f9b12f3a 100644
--- a/util/data/msgreply.h
+++ b/util/data/msgreply.h
@@ -157,7 +157,7 @@ struct reply_info {
time_t prefetch_ttl;
/**
- * Reply TTL extended with serve exipred TTL, to limit time to serve
+ * Reply TTL extended with serve expired TTL, to limit time to serve
* expired message.
*/
time_t serve_expired_ttl;
diff --git a/util/fptr_wlist.c b/util/fptr_wlist.c
index 02f85e8dc4ab..94d23fa3a32a 100644
--- a/util/fptr_wlist.c
+++ b/util/fptr_wlist.c
@@ -127,6 +127,7 @@ fptr_whitelist_comm_timer(void (*fptr)(void*))
#endif
else if(fptr == &auth_xfer_timer) return 1;
else if(fptr == &auth_xfer_probe_timer_callback) return 1;
+ else if(fptr == &auth_xfer_transfer_timer_callback) return 1;
return 0;
}
diff --git a/util/iana_ports.inc b/util/iana_ports.inc
index 5ead47f0f665..aa972a67bd5d 100644
--- a/util/iana_ports.inc
+++ b/util/iana_ports.inc
@@ -4768,6 +4768,7 @@
8088,
8097,
8100,
+8111,
8115,
8116,
8118,
@@ -4864,6 +4865,7 @@
8805,
8807,
8808,
+8809,
8873,
8880,
8883,
diff --git a/util/net_help.c b/util/net_help.c
index 2b1be92460ba..13bcdf8085bf 100644
--- a/util/net_help.c
+++ b/util/net_help.c
@@ -802,6 +802,16 @@ void* listen_sslctx_create(char* key, char* pem, char* verifypem)
log_crypto_err("could not SSL_CTX_new");
return NULL;
}
+ if(!key || key[0] == 0) {
+ log_err("error: no tls-service-key file specified");
+ SSL_CTX_free(ctx);
+ return NULL;
+ }
+ if(!pem || pem[0] == 0) {
+ log_err("error: no tls-service-pem file specified");
+ SSL_CTX_free(ctx);
+ return NULL;
+ }
if(!listen_sslctx_setup(ctx)) {
SSL_CTX_free(ctx);
return NULL;
@@ -1235,7 +1245,12 @@ listen_sslctx_delete_ticket_keys(void)
struct tls_session_ticket_key *key;
if(!ticket_keys) return;
for(key = ticket_keys; key->key_name != NULL; key++) {
- memset(key->key_name, 0xdd, 80); /* wipe key data from memory*/
+ /* wipe key data from memory*/
+#ifdef HAVE_EXPLICIT_BZERO
+ explicit_bzero(key->key_name, 80);
+#else
+ memset(key->key_name, 0xdd, 80);
+#endif
free(key->key_name);
}
free(ticket_keys);
diff --git a/util/netevent.c b/util/netevent.c
index f33e44058b11..9e2ba92b5fdf 100644
--- a/util/netevent.c
+++ b/util/netevent.c
@@ -178,7 +178,7 @@ comm_base_create(int sigs)
}
ub_comm_base_now(b);
ub_get_event_sys(b->eb->base, &evnm, &evsys, &evmethod);
- verbose(VERB_ALGO, "%s %s user %s method.", evnm, evsys, evmethod);
+ verbose(VERB_ALGO, "%s %s uses %s method.", evnm, evsys, evmethod);
return b;
}
@@ -926,6 +926,14 @@ comm_point_tcp_accept_callback(int fd, short event, void* arg)
}
/* accept incoming connection. */
c_hdl = c->tcp_free;
+ /* clear leftover flags from previous use, and then set the
+ * correct event base for the event structure for libevent */
+ ub_event_free(c_hdl->ev->ev);
+ c_hdl->ev->ev = ub_event_new(c_hdl->ev->base->eb->base, -1, UB_EV_PERSIST | UB_EV_READ | UB_EV_TIMEOUT, comm_point_tcp_handle_callback, c_hdl);
+ if(!c_hdl->ev->ev) {
+ log_warn("could not ub_event_new, dropped tcp");
+ return;
+ }
log_assert(fd != -1);
(void)fd;
new_fd = comm_point_perform_accept(c, &c_hdl->repinfo.addr,
@@ -1184,6 +1192,10 @@ ssl_handle_read(struct comm_point* c)
comm_point_listen_for_rw(c, 0, 1);
return 1;
} else if(want == SSL_ERROR_SYSCALL) {
+#ifdef ECONNRESET
+ if(errno == ECONNRESET && verbosity < 2)
+ return 0; /* silence reset by peer */
+#endif
if(errno != 0)
log_err("SSL_read syscall: %s",
strerror(errno));
@@ -1228,6 +1240,10 @@ ssl_handle_read(struct comm_point* c)
comm_point_listen_for_rw(c, 0, 1);
return 1;
} else if(want == SSL_ERROR_SYSCALL) {
+#ifdef ECONNRESET
+ if(errno == ECONNRESET && verbosity < 2)
+ return 0; /* silence reset by peer */
+#endif
if(errno != 0)
log_err("SSL_read syscall: %s",
strerror(errno));
@@ -1288,13 +1304,17 @@ ssl_handle_write(struct comm_point* c)
if(want == SSL_ERROR_ZERO_RETURN) {
return 0; /* closed */
} else if(want == SSL_ERROR_WANT_READ) {
- c->ssl_shake_state = comm_ssl_shake_read;
+ c->ssl_shake_state = comm_ssl_shake_hs_read;
comm_point_listen_for_rw(c, 1, 0);
return 1; /* wait for read condition */
} else if(want == SSL_ERROR_WANT_WRITE) {
ub_winsock_tcp_wouldblock(c->ev->ev, UB_EV_WRITE);
return 1; /* write more later */
} else if(want == SSL_ERROR_SYSCALL) {
+#ifdef EPIPE
+ if(errno == EPIPE && verbosity < 2)
+ return 0; /* silence 'broken pipe' */
+#endif
if(errno != 0)
log_err("SSL_write syscall: %s",
strerror(errno));
@@ -1322,13 +1342,17 @@ ssl_handle_write(struct comm_point* c)
if(want == SSL_ERROR_ZERO_RETURN) {
return 0; /* closed */
} else if(want == SSL_ERROR_WANT_READ) {
- c->ssl_shake_state = comm_ssl_shake_read;
+ c->ssl_shake_state = comm_ssl_shake_hs_read;
comm_point_listen_for_rw(c, 1, 0);
return 1; /* wait for read condition */
} else if(want == SSL_ERROR_WANT_WRITE) {
ub_winsock_tcp_wouldblock(c->ev->ev, UB_EV_WRITE);
return 1; /* write more later */
} else if(want == SSL_ERROR_SYSCALL) {
+#ifdef EPIPE
+ if(errno == EPIPE && verbosity < 2)
+ return 0; /* silence 'broken pipe' */
+#endif
if(errno != 0)
log_err("SSL_write syscall: %s",
strerror(errno));
@@ -1543,7 +1567,6 @@ comm_point_tcp_handle_write(int fd, struct comm_point* c)
iov[1].iov_base = sldns_buffer_begin(buffer);
iov[1].iov_len = sldns_buffer_limit(buffer);
log_assert(iov[0].iov_len > 0);
- log_assert(iov[1].iov_len > 0);
msg.msg_name = &c->repinfo.addr;
msg.msg_namelen = c->repinfo.addrlen;
msg.msg_iov = iov;
@@ -1610,7 +1633,6 @@ comm_point_tcp_handle_write(int fd, struct comm_point* c)
iov[1].iov_base = sldns_buffer_begin(buffer);
iov[1].iov_len = sldns_buffer_limit(buffer);
log_assert(iov[0].iov_len > 0);
- log_assert(iov[1].iov_len > 0);
r = writev(fd, iov, 2);
#else /* HAVE_WRITEV */
r = send(fd, (void*)(((uint8_t*)&len)+c->tcp_byte_count),
@@ -1624,6 +1646,10 @@ comm_point_tcp_handle_write(int fd, struct comm_point* c)
#endif
if(errno == EINTR || errno == EAGAIN)
return 1;
+#ifdef ECONNRESET
+ if(errno == ECONNRESET && verbosity < 2)
+ return 0; /* silence reset by peer */
+#endif
# ifdef HAVE_WRITEV
log_err_addr("tcp writev", strerror(errno),
&c->repinfo.addr, c->repinfo.addrlen);
@@ -1641,6 +1667,8 @@ comm_point_tcp_handle_write(int fd, struct comm_point* c)
UB_EV_WRITE);
return 1;
}
+ if(WSAGetLastError() == WSAECONNRESET && verbosity < 2)
+ return 0; /* silence reset by peer */
log_err_addr("tcp send s",
wsa_strerror(WSAGetLastError()),
&c->repinfo.addr, c->repinfo.addrlen);
@@ -1664,6 +1692,10 @@ comm_point_tcp_handle_write(int fd, struct comm_point* c)
#ifndef USE_WINSOCK
if(errno == EINTR || errno == EAGAIN)
return 1;
+#ifdef ECONNRESET
+ if(errno == ECONNRESET && verbosity < 2)
+ return 0; /* silence reset by peer */
+#endif
log_err_addr("tcp send r", strerror(errno),
&c->repinfo.addr, c->repinfo.addrlen);
#else
@@ -1673,6 +1705,8 @@ comm_point_tcp_handle_write(int fd, struct comm_point* c)
ub_winsock_tcp_wouldblock(c->ev->ev, UB_EV_WRITE);
return 1;
}
+ if(WSAGetLastError() == WSAECONNRESET && verbosity < 2)
+ return 0; /* silence reset by peer */
log_err_addr("tcp send r", wsa_strerror(WSAGetLastError()),
&c->repinfo.addr, c->repinfo.addrlen);
#endif
@@ -1738,6 +1772,16 @@ comm_point_tcp_handle_callback(int fd, short event, void* arg)
}
#endif
+ if(event&UB_EV_TIMEOUT) {
+ verbose(VERB_QUERY, "tcp took too long, dropped");
+ reclaim_tcp_handler(c);
+ if(!c->tcp_do_close) {
+ fptr_ok(fptr_whitelist_comm_point(c->callback));
+ (void)(*c->callback)(c, c->cb_arg,
+ NETEVENT_TIMEOUT, NULL);
+ }
+ return;
+ }
if(event&UB_EV_READ) {
int has_tcpq = (c->tcp_req_info != NULL);
if(!comm_point_tcp_handle_read(fd, c, 0)) {
@@ -1768,16 +1812,6 @@ comm_point_tcp_handle_callback(int fd, short event, void* arg)
tcp_req_info_read_again(fd, c);
return;
}
- if(event&UB_EV_TIMEOUT) {
- verbose(VERB_QUERY, "tcp took too long, dropped");
- reclaim_tcp_handler(c);
- if(!c->tcp_do_close) {
- fptr_ok(fptr_whitelist_comm_point(c->callback));
- (void)(*c->callback)(c, c->cb_arg,
- NETEVENT_TIMEOUT, NULL);
- }
- return;
- }
log_err("Ignored event %d for tcphdl.", event);
}
@@ -1826,6 +1860,10 @@ ssl_http_read_more(struct comm_point* c)
comm_point_listen_for_rw(c, 0, 1);
return 1;
} else if(want == SSL_ERROR_SYSCALL) {
+#ifdef ECONNRESET
+ if(errno == ECONNRESET && verbosity < 2)
+ return 0; /* silence reset by peer */
+#endif
if(errno != 0)
log_err("SSL_read syscall: %s",
strerror(errno));
@@ -2268,12 +2306,16 @@ ssl_http_write_more(struct comm_point* c)
if(want == SSL_ERROR_ZERO_RETURN) {
return 0; /* closed */
} else if(want == SSL_ERROR_WANT_READ) {
- c->ssl_shake_state = comm_ssl_shake_read;
+ c->ssl_shake_state = comm_ssl_shake_hs_read;
comm_point_listen_for_rw(c, 1, 0);
return 1; /* wait for read condition */
} else if(want == SSL_ERROR_WANT_WRITE) {
return 1; /* write more later */
} else if(want == SSL_ERROR_SYSCALL) {
+#ifdef EPIPE
+ if(errno == EPIPE && verbosity < 2)
+ return 0; /* silence 'broken pipe' */
+#endif
if(errno != 0)
log_err("SSL_write syscall: %s",
strerror(errno));
@@ -2382,6 +2424,16 @@ comm_point_http_handle_callback(int fd, short event, void* arg)
log_assert(c->type == comm_http);
ub_comm_base_now(c->ev->base);
+ if(event&UB_EV_TIMEOUT) {
+ verbose(VERB_QUERY, "http took too long, dropped");
+ reclaim_http_handler(c);
+ if(!c->tcp_do_close) {
+ fptr_ok(fptr_whitelist_comm_point(c->callback));
+ (void)(*c->callback)(c, c->cb_arg,
+ NETEVENT_TIMEOUT, NULL);
+ }
+ return;
+ }
if(event&UB_EV_READ) {
if(!comm_point_http_handle_read(fd, c)) {
reclaim_http_handler(c);
@@ -2406,16 +2458,6 @@ comm_point_http_handle_callback(int fd, short event, void* arg)
}
return;
}
- if(event&UB_EV_TIMEOUT) {
- verbose(VERB_QUERY, "http took too long, dropped");
- reclaim_http_handler(c);
- if(!c->tcp_do_close) {
- fptr_ok(fptr_whitelist_comm_point(c->callback));
- (void)(*c->callback)(c, c->cb_arg,
- NETEVENT_TIMEOUT, NULL);
- }
- return;
- }
log_err("Ignored event %d for httphdl.", event);
}
@@ -3138,8 +3180,8 @@ comm_point_stop_listening(struct comm_point* c)
void
comm_point_start_listening(struct comm_point* c, int newfd, int msec)
{
- verbose(VERB_ALGO, "comm point start listening %d",
- c->fd==-1?newfd:c->fd);
+ verbose(VERB_ALGO, "comm point start listening %d (%d msec)",
+ c->fd==-1?newfd:c->fd, msec);
if(c->type == comm_tcp_accept && !c->tcp_free) {
/* no use to start listening no free slots. */
return;
diff --git a/util/storage/lookup3.c b/util/storage/lookup3.c
index cc110748156f..bb25eb433c94 100644
--- a/util/storage/lookup3.c
+++ b/util/storage/lookup3.c
@@ -1,4 +1,7 @@
/*
+ May 2019(Wouter) patch to enable the valgrind clean implementation all the
+ time. This enables better security audit and checks, which is better
+ than the speedup. Git issue #30. Renamed the define ARRAY_CLEAN_ACCESS.
February 2013(Wouter) patch defines for BSD endianness, from Brad Smith.
January 2012(Wouter) added randomised initial value, fallout from 28c3.
March 2007(Wouter) adapted from lookup3.c original, add config.h include.
@@ -44,6 +47,7 @@ on 1 byte), but shoehorning those bytes into integers efficiently is messy.
-------------------------------------------------------------------------------
*/
/*#define SELF_TEST 1*/
+#define ARRAY_CLEAN_ACCESS 1
#include "config.h"
#include "util/storage/lookup3.h"
@@ -336,7 +340,7 @@ uint32_t hashlittle( const void *key, size_t length, uint32_t initval)
u.ptr = key;
if (HASH_LITTLE_ENDIAN && ((u.i & 0x3) == 0)) {
const uint32_t *k = (const uint32_t *)key; /* read 32-bit chunks */
-#ifdef VALGRIND
+#ifdef ARRAY_CLEAN_ACCESS
const uint8_t *k8;
#endif
@@ -361,7 +365,7 @@ uint32_t hashlittle( const void *key, size_t length, uint32_t initval)
* still catch it and complain. The masking trick does make the hash
* noticeably faster for short strings (like English words).
*/
-#ifndef VALGRIND
+#ifndef ARRAY_CLEAN_ACCESS
switch(length)
{
diff --git a/util/ub_event.c b/util/ub_event.c
index 78481a982055..e097fbc40158 100644
--- a/util/ub_event.c
+++ b/util/ub_event.c
@@ -295,11 +295,18 @@ ub_event_new(struct ub_event_base* base, int fd, short bits,
if (!ev)
return NULL;
+#ifndef HAVE_EVENT_ASSIGN
event_set(ev, fd, NATIVE_BITS(bits), NATIVE_BITS_CB(cb), arg);
if (event_base_set(AS_EVENT_BASE(base), ev) != 0) {
free(ev);
return NULL;
}
+#else
+ if (event_assign(ev, AS_EVENT_BASE(base), fd, bits, cb, arg) != 0) {
+ free(ev);
+ return NULL;
+ }
+#endif
return AS_UB_EVENT(ev);
}
@@ -312,11 +319,18 @@ ub_signal_new(struct ub_event_base* base, int fd,
if (!ev)
return NULL;
+#if !HAVE_DECL_EVSIGNAL_ASSIGN
signal_set(ev, fd, NATIVE_BITS_CB(cb), arg);
if (event_base_set(AS_EVENT_BASE(base), ev) != 0) {
free(ev);
return NULL;
}
+#else
+ if (evsignal_assign(ev, AS_EVENT_BASE(base), fd, cb, arg) != 0) {
+ free(ev);
+ return NULL;
+ }
+#endif
return AS_UB_EVENT(ev);
}