unbound 1.9.2rc1

classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|

unbound 1.9.2rc1

Stuart Henderson
New unbound is in rc testing, here's a diff if anyone is interested.

"This release contains a number of bug fixes for crashes introduced in
1.9, session ticket code, stream pipeline code, auth zone code and it
also fixes qname minimisation packet scrub failures."


Index: doc/Changelog
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/doc/Changelog,v
retrieving revision 1.32
diff -u -p -r1.32 Changelog
--- doc/Changelog 27 Mar 2019 12:06:18 -0000 1.32
+++ doc/Changelog 8 Jun 2019 12:44:18 -0000
@@ -1,3 +1,158 @@
+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.
 
Index: config.h.in
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/config.h.in,v
retrieving revision 1.15
diff -u -p -r1.15 config.h.in
--- config.h.in 27 Mar 2019 12:06:17 -0000 1.15
+++ config.h.in 8 Jun 2019 12:44:17 -0000
@@ -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 */
Index: configure
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/configure,v
retrieving revision 1.32
diff -u -p -r1.32 configure
--- configure 27 Mar 2019 12:06:17 -0000 1.32
+++ configure 8 Jun 2019 12:44:17 -0000
@@ -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.2rc1.
 #
 # Report bugs to <[hidden email]>.
 #
@@ -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.2rc1'
+PACKAGE_STRING='unbound 1.9.2rc1'
 PACKAGE_BUGREPORT='[hidden email]'
 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.2rc1 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.2rc1:";;
    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.2rc1
 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.2rc1, 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=2rc1
 
 
 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.2rc1
 
 date=`date +'%b %e, %Y'`
 
@@ -21669,7 +21723,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_wri
 # 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.2rc1, 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.2rc1
 configured by $0, generated by GNU Autoconf 2.69,
   with options \\"\$ac_cs_config\\"
 
Index: configure.ac
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/configure.ac,v
retrieving revision 1.32
diff -u -p -r1.32 configure.ac
--- configure.ac 27 Mar 2019 12:06:17 -0000 1.32
+++ configure.ac 8 Jun 2019 12:44:17 -0000
@@ -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],[2rc1])
 AC_INIT(unbound, m4_defn([VERSION_MAJOR]).m4_defn([VERSION_MINOR]).m4_defn([VERSION_MICRO]), [hidden email], 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 */
Index: cachedb/cachedb.c
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/cachedb/cachedb.c,v
retrieving revision 1.8
diff -u -p -r1.8 cachedb.c
--- cachedb/cachedb.c 20 Sep 2018 23:15:39 -0000 1.8
+++ cachedb/cachedb.c 8 Jun 2019 12:44:18 -0000
@@ -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 {
Index: daemon/unbound.c
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/daemon/unbound.c,v
retrieving revision 1.22
diff -u -p -r1.22 unbound.c
--- daemon/unbound.c 8 Feb 2019 10:29:08 -0000 1.22
+++ daemon/unbound.c 8 Jun 2019 12:44:18 -0000
@@ -443,7 +443,8 @@ perform_setup(struct daemon* daemon, str
  }
  }
 #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");
  }
Index: daemon/worker.c
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/daemon/worker.c,v
retrieving revision 1.23
diff -u -p -r1.23 worker.c
--- daemon/worker.c 27 Mar 2019 12:06:17 -0000 1.23
+++ daemon/worker.c 8 Jun 2019 12:44:18 -0000
@@ -660,10 +660,7 @@ answer_from_cache(struct worker* worker,
  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,
  }
  /* 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.
Index: doc/README
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/doc/README,v
retrieving revision 1.19
diff -u -p -r1.19 README
--- doc/README 27 Mar 2019 12:06:18 -0000 1.19
+++ doc/README 8 Jun 2019 12:44:18 -0000
@@ -1,4 +1,4 @@
-README for Unbound 1.9.1
+README for Unbound 1.9.2rc1
 Copyright 2007 NLnet Labs
 http://unbound.net
 
Index: doc/example.conf.in
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/doc/example.conf.in,v
retrieving revision 1.23
diff -u -p -r1.23 example.conf.in
--- doc/example.conf.in 27 Mar 2019 12:06:18 -0000 1.23
+++ doc/example.conf.in 8 Jun 2019 12:44:18 -0000
@@ -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.2rc1.
 #
 # 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
@@ -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"
Index: doc/libunbound.3.in
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/doc/libunbound.3.in,v
retrieving revision 1.21
diff -u -p -r1.21 libunbound.3.in
--- doc/libunbound.3.in 27 Mar 2019 12:06:18 -0000 1.21
+++ doc/libunbound.3.in 8 Jun 2019 12:44:18 -0000
@@ -1,4 +1,4 @@
-.TH "libunbound" "3" "Mar 12, 2019" "NLnet Labs" "unbound 1.9.1"
+.TH "libunbound" "3" "Jun  6, 2019" "NLnet Labs" "unbound 1.9.2rc1"
 .\"
 .\" 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.2rc1 functions.
 .SH "SYNOPSIS"
 .B #include <unbound.h>
 .LP
Index: doc/unbound-anchor.8.in
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/doc/unbound-anchor.8.in,v
retrieving revision 1.20
diff -u -p -r1.20 unbound-anchor.8.in
--- doc/unbound-anchor.8.in 27 Mar 2019 12:06:18 -0000 1.20
+++ doc/unbound-anchor.8.in 8 Jun 2019 12:44:18 -0000
@@ -1,4 +1,4 @@
-.TH "unbound-anchor" "8" "Mar 12, 2019" "NLnet Labs" "unbound 1.9.1"
+.TH "unbound-anchor" "8" "Jun  6, 2019" "NLnet Labs" "unbound 1.9.2rc1"
 .\"
 .\" unbound-anchor.8 -- unbound anchor maintenance utility manual
 .\"
Index: doc/unbound-checkconf.8.in
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/doc/unbound-checkconf.8.in,v
retrieving revision 1.20
diff -u -p -r1.20 unbound-checkconf.8.in
--- doc/unbound-checkconf.8.in 27 Mar 2019 12:06:18 -0000 1.20
+++ doc/unbound-checkconf.8.in 8 Jun 2019 12:44:18 -0000
@@ -1,4 +1,4 @@
-.TH "unbound-checkconf" "8" "Mar 12, 2019" "NLnet Labs" "unbound 1.9.1"
+.TH "unbound-checkconf" "8" "Jun  6, 2019" "NLnet Labs" "unbound 1.9.2rc1"
 .\"
 .\" unbound-checkconf.8 -- unbound configuration checker manual
 .\"
Index: doc/unbound-control.8.in
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/doc/unbound-control.8.in,v
retrieving revision 1.22
diff -u -p -r1.22 unbound-control.8.in
--- doc/unbound-control.8.in 27 Mar 2019 12:06:18 -0000 1.22
+++ doc/unbound-control.8.in 8 Jun 2019 12:44:18 -0000
@@ -1,4 +1,4 @@
-.TH "unbound-control" "8" "Mar 12, 2019" "NLnet Labs" "unbound 1.9.1"
+.TH "unbound-control" "8" "Jun  6, 2019" "NLnet Labs" "unbound 1.9.2rc1"
 .\"
 .\" unbound-control.8 -- unbound remote control manual
 .\"
Index: doc/unbound-host.1.in
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/doc/unbound-host.1.in,v
retrieving revision 1.22
diff -u -p -r1.22 unbound-host.1.in
--- doc/unbound-host.1.in 27 Mar 2019 12:06:18 -0000 1.22
+++ doc/unbound-host.1.in 8 Jun 2019 12:44:18 -0000
@@ -1,4 +1,4 @@
-.TH "unbound\-host" "1" "Mar 12, 2019" "NLnet Labs" "unbound 1.9.1"
+.TH "unbound\-host" "1" "Jun  6, 2019" "NLnet Labs" "unbound 1.9.2rc1"
 .\"
 .\" unbound-host.1 -- unbound DNS lookup utility
 .\"
Index: doc/unbound.8.in
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/doc/unbound.8.in,v
retrieving revision 1.23
diff -u -p -r1.23 unbound.8.in
--- doc/unbound.8.in 27 Mar 2019 12:06:18 -0000 1.23
+++ doc/unbound.8.in 8 Jun 2019 12:44:18 -0000
@@ -1,4 +1,4 @@
-.TH "unbound" "8" "Mar 12, 2019" "NLnet Labs" "unbound 1.9.1"
+.TH "unbound" "8" "Jun  6, 2019" "NLnet Labs" "unbound 1.9.2rc1"
 .\"
 .\" 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.2rc1.
 .SH "SYNOPSIS"
 .B unbound
 .RB [ \-h ]
Index: doc/unbound.conf.5.in
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/doc/unbound.conf.5.in,v
retrieving revision 1.26
diff -u -p -r1.26 unbound.conf.5.in
--- doc/unbound.conf.5.in 27 Mar 2019 12:06:18 -0000 1.26
+++ doc/unbound.conf.5.in 8 Jun 2019 12:44:18 -0000
@@ -1,4 +1,4 @@
-.TH "unbound.conf" "5" "Mar 12, 2019" "NLnet Labs" "unbound 1.9.1"
+.TH "unbound.conf" "5" "Jun  6, 2019" "NLnet Labs" "unbound 1.9.2rc1"
 .\"
 .\" unbound.conf.5 -- unbound.conf manual
 .\"
@@ -264,6 +264,8 @@ it may also work.  You can enable it (on
 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
@@ -783,7 +785,7 @@ Can be given multiple times, for differe
 .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.
@@ -1630,6 +1632,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
Index: doc/unbound.doxygen
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/doc/unbound.doxygen,v
retrieving revision 1.3
diff -u -p -r1.3 unbound.doxygen
--- doc/unbound.doxygen 4 Dec 2018 12:05:07 -0000 1.3
+++ doc/unbound.doxygen 8 Jun 2019 12:44:18 -0000
@@ -629,6 +629,7 @@ EXCLUDE                = ./build \
                          libunbound/python/doc \
                          libunbound/python/examples \
                          ./ldns-src \
+ README.md \
  doc/control_proto_spec.txt \
  doc/requirements.txt
 
Index: edns-subnet/subnetmod.c
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/edns-subnet/subnetmod.c,v
retrieving revision 1.5
diff -u -p -r1.5 subnetmod.c
--- edns-subnet/subnetmod.c 4 Dec 2018 12:05:07 -0000 1.5
+++ edns-subnet/subnetmod.c 8 Jun 2019 12:44:18 -0000
@@ -334,33 +334,37 @@ update_cache(struct module_qstate *qstat
  /* 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 *qstat
  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 *qstat
  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);
  }
Index: iterator/iter_utils.c
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/iterator/iter_utils.c,v
retrieving revision 1.12
diff -u -p -r1.12 iter_utils.c
--- iterator/iter_utils.c 27 Mar 2019 12:06:18 -0000 1.12
+++ iterator/iter_utils.c 8 Jun 2019 12:44:18 -0000
@@ -1211,6 +1211,19 @@ iter_scrub_ds(struct dns_msg* msg, struc
  }
 }
 
+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;
Index: iterator/iter_utils.h
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/iterator/iter_utils.h,v
retrieving revision 1.8
diff -u -p -r1.8 iter_utils.h
--- iterator/iter_utils.h 4 Dec 2018 12:05:07 -0000 1.8
+++ iterator/iter_utils.h 8 Jun 2019 12:44:18 -0000
@@ -335,6 +335,13 @@ void iter_scrub_ds(struct dns_msg* msg,
  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.
Index: iterator/iterator.c
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/iterator/iterator.c,v
retrieving revision 1.22
diff -u -p -r1.22 iterator.c
--- iterator/iterator.c 27 Mar 2019 12:06:18 -0000 1.22
+++ iterator/iterator.c 8 Jun 2019 12:44:18 -0000
@@ -2718,8 +2718,15 @@ processQueryResponse(struct module_qstat
  && !(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. */
Index: services/authzone.c
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/services/authzone.c,v
retrieving revision 1.10
diff -u -p -r1.10 authzone.c
--- services/authzone.c 8 Feb 2019 10:29:08 -0000 1.10
+++ services/authzone.c 8 Jun 2019 12:44:18 -0000
@@ -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, str
  * 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, str
 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,
  /* 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_zo
  /* 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_
  } 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_
  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_
  /* 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_
  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_
  } 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*
 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
  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
  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
  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
  /* 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 au
  * 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 au
  /* 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(
  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_xf
  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 c
  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
  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* x
  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* x
  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* x
  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* x
  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* x
  /* 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*
  * 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*
  /* 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*
  /* 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(voi
  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 &&
Index: services/authzone.h
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/services/authzone.h,v
retrieving revision 1.7
diff -u -p -r1.7 authzone.h
--- services/authzone.h 8 Feb 2019 10:29:08 -0000 1.7
+++ services/authzone.h 8 Jun 2019 12:44:18 -0000
@@ -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(str
         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,
Index: services/listen_dnsport.c
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/services/listen_dnsport.c,v
retrieving revision 1.22
diff -u -p -r1.22 listen_dnsport.c
--- services/listen_dnsport.c 27 Mar 2019 12:06:18 -0000 1.22
+++ services/listen_dnsport.c 8 Jun 2019 12:44:18 -0000
@@ -851,13 +851,16 @@ create_tcp_accept_sock(struct addrinfo *
 #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;
@@ -1771,24 +1774,12 @@ tcp_req_info_handle_readdone(struct tcp_
  * 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 +1858,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;
  }
Index: services/mesh.c
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/services/mesh.c,v
retrieving revision 1.11
diff -u -p -r1.11 mesh.c
--- services/mesh.c 8 Feb 2019 10:29:08 -0000 1.11
+++ services/mesh.c 8 Jun 2019 12:44:18 -0000
@@ -1192,12 +1192,16 @@ void mesh_query_done(struct mesh_state*
  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 +1345,14 @@ int mesh_state_add_reply(struct mesh_sta
  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;
Index: services/outside_network.c
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/services/outside_network.c,v
retrieving revision 1.14
diff -u -p -r1.14 outside_network.c
--- services/outside_network.c 27 Mar 2019 12:06:18 -0000 1.14
+++ services/outside_network.c 8 Jun 2019 12:44:18 -0000
@@ -364,6 +364,8 @@ outnet_tcp_take_into_use(struct waiting_
  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_
  }
  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
  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
  }
  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 outsid
 
  /* 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 */
Index: services/outside_network.h
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/services/outside_network.h,v
retrieving revision 1.8
diff -u -p -r1.8 outside_network.h
--- services/outside_network.h 8 Feb 2019 10:29:08 -0000 1.8
+++ services/outside_network.h 8 Jun 2019 12:44:18 -0000
@@ -570,12 +570,14 @@ struct comm_point* outnet_comm_point_for
  * @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.
Index: services/cache/dns.c
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/services/cache/dns.c,v
retrieving revision 1.12
diff -u -p -r1.12 dns.c
--- services/cache/dns.c 4 Dec 2018 12:05:07 -0000 1.12
+++ services/cache/dns.c 8 Jun 2019 12:44:18 -0000
@@ -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);
Index: testcode/fake_event.c
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/testcode/fake_event.c,v
retrieving revision 1.1.1.3
diff -u -p -r1.1.1.3 fake_event.c
--- testcode/fake_event.c 8 Feb 2019 10:26:32 -0000 1.1.1.3
+++ testcode/fake_event.c 8 Jun 2019 12:44:18 -0000
@@ -1629,7 +1629,8 @@ struct comm_point* outnet_comm_point_for
 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;
Index: util/alloc.c
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/util/alloc.c,v
retrieving revision 1.3
diff -u -p -r1.3 alloc.c
--- util/alloc.c 17 Sep 2018 09:46:12 -0000 1.3
+++ util/alloc.c 8 Jun 2019 12:44:18 -0000
@@ -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,
  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, si
  /* 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 si
         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 nm
  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);
Index: util/fptr_wlist.c
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/util/fptr_wlist.c,v
retrieving revision 1.14
diff -u -p -r1.14 fptr_wlist.c
--- util/fptr_wlist.c 4 Dec 2018 12:05:07 -0000 1.14
+++ util/fptr_wlist.c 8 Jun 2019 12:44:18 -0000
@@ -127,6 +127,7 @@ fptr_whitelist_comm_timer(void (*fptr)(v
 #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;
 }
 
Index: util/iana_ports.inc
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/util/iana_ports.inc,v
retrieving revision 1.15
diff -u -p -r1.15 iana_ports.inc
--- util/iana_ports.inc 4 Dec 2018 12:05:07 -0000 1.15
+++ util/iana_ports.inc 8 Jun 2019 12:44:18 -0000
@@ -4768,6 +4768,7 @@
 8088,
 8097,
 8100,
+8111,
 8115,
 8116,
 8118,
@@ -4864,6 +4865,7 @@
 8805,
 8807,
 8808,
+8809,
 8873,
 8880,
 8883,
Index: util/net_help.c
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/util/net_help.c,v
retrieving revision 1.15
diff -u -p -r1.15 net_help.c
--- util/net_help.c 27 Mar 2019 12:06:18 -0000 1.15
+++ util/net_help.c 8 Jun 2019 12:44:18 -0000
@@ -802,6 +802,16 @@ void* listen_sslctx_create(char* key, ch
  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);
Index: util/netevent.c
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/util/netevent.c,v
retrieving revision 1.20
diff -u -p -r1.20 netevent.c
--- util/netevent.c 27 Mar 2019 12:06:18 -0000 1.20
+++ util/netevent.c 8 Jun 2019 12:44:18 -0000
@@ -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, s
  }
  /* 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));
@@ -1624,6 +1648,10 @@ comm_point_tcp_handle_write(int fd, stru
   #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 +1669,8 @@ comm_point_tcp_handle_write(int fd, stru
  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 +1694,10 @@ comm_point_tcp_handle_write(int fd, stru
 #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 +1707,8 @@ comm_point_tcp_handle_write(int fd, stru
  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 +1774,16 @@ comm_point_tcp_handle_callback(int fd, s
  }
 #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 +1814,6 @@ comm_point_tcp_handle_callback(int fd, s
  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 +1862,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 +2308,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 +2426,16 @@ comm_point_http_handle_callback(int fd,
  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 +2460,6 @@ comm_point_http_handle_callback(int fd,
  }
  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 +3182,8 @@ comm_point_stop_listening(struct comm_po
 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;
Index: util/ub_event.c
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/util/ub_event.c,v
retrieving revision 1.4
diff -u -p -r1.4 ub_event.c
--- util/ub_event.c 17 Sep 2018 09:46:12 -0000 1.4
+++ util/ub_event.c 8 Jun 2019 12:44:18 -0000
@@ -295,11 +295,18 @@ ub_event_new(struct ub_event_base* base,
  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
  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);
 }
 
Index: util/data/msgreply.h
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/util/data/msgreply.h,v
retrieving revision 1.8
diff -u -p -r1.8 msgreply.h
--- util/data/msgreply.h 20 Sep 2018 23:15:40 -0000 1.8
+++ util/data/msgreply.h 8 Jun 2019 12:44:18 -0000
@@ -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;
Index: util/storage/lookup3.c
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/util/storage/lookup3.c,v
retrieving revision 1.4
diff -u -p -r1.4 lookup3.c
--- util/storage/lookup3.c 29 Sep 2017 16:27:14 -0000 1.4
+++ util/storage/lookup3.c 8 Jun 2019 12:44:18 -0000
@@ -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
 -------------------------------------------------------------------------------
 */
 /*#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, si
   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, si
      * 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)
     {

Reply | Threaded
Open this post in threaded view
|

Re: unbound 1.9.2rc1

Stuart Henderson
On 2019/06/08 13:53, Stuart Henderson wrote:
> New unbound is in rc testing, here's a diff if anyone is interested.
>
> "This release contains a number of bug fixes for crashes introduced in
> 1.9, session ticket code, stream pipeline code, auth zone code and it
> also fixes qname minimisation packet scrub failures."

Updated for the final 1.9.2 release, a couple of small fixes since the
last one. Anyone want to do more tests? should I just go ahead?

(https://pbot.rmdir.de/JZfX8qiGvSJ-AMsFC5oSmA is what I think is an
equivalent diff for the copy in unwind but that's as yet untested).

Index: doc/Changelog
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/doc/Changelog,v
retrieving revision 1.32
diff -u -p -r1.32 Changelog
--- doc/Changelog 27 Mar 2019 12:06:18 -0000 1.32
+++ doc/Changelog 24 Jun 2019 20:06:17 -0000
@@ -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.
 
Index: config.h.in
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/config.h.in,v
retrieving revision 1.15
diff -u -p -r1.15 config.h.in
--- config.h.in 27 Mar 2019 12:06:17 -0000 1.15
+++ config.h.in 24 Jun 2019 20:06:17 -0000
@@ -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 */
Index: configure
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/configure,v
retrieving revision 1.32
diff -u -p -r1.32 configure
--- configure 27 Mar 2019 12:06:17 -0000 1.32
+++ configure 24 Jun 2019 20:06:17 -0000
@@ -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 <[hidden email]>.
 #
@@ -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='[hidden email]'
 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_wri
 # 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\\"
 
Index: configure.ac
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/configure.ac,v
retrieving revision 1.32
diff -u -p -r1.32 configure.ac
--- configure.ac 27 Mar 2019 12:06:17 -0000 1.32
+++ configure.ac 24 Jun 2019 20:06:17 -0000
@@ -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]), [hidden email], 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 */
Index: cachedb/cachedb.c
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/cachedb/cachedb.c,v
retrieving revision 1.8
diff -u -p -r1.8 cachedb.c
--- cachedb/cachedb.c 20 Sep 2018 23:15:39 -0000 1.8
+++ cachedb/cachedb.c 24 Jun 2019 20:06:17 -0000
@@ -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 {
Index: daemon/unbound.c
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/daemon/unbound.c,v
retrieving revision 1.22
diff -u -p -r1.22 unbound.c
--- daemon/unbound.c 8 Feb 2019 10:29:08 -0000 1.22
+++ daemon/unbound.c 24 Jun 2019 20:06:17 -0000
@@ -443,7 +443,8 @@ perform_setup(struct daemon* daemon, str
  }
  }
 #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");
  }
Index: daemon/worker.c
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/daemon/worker.c,v
retrieving revision 1.23
diff -u -p -r1.23 worker.c
--- daemon/worker.c 27 Mar 2019 12:06:17 -0000 1.23
+++ daemon/worker.c 24 Jun 2019 20:06:17 -0000
@@ -660,10 +660,7 @@ answer_from_cache(struct worker* worker,
  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,
  }
  /* 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
 {
  /* 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
Index: doc/README
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/doc/README,v
retrieving revision 1.19
diff -u -p -r1.19 README
--- doc/README 27 Mar 2019 12:06:18 -0000 1.19
+++ doc/README 24 Jun 2019 20:06:17 -0000
@@ -1,4 +1,4 @@
-README for Unbound 1.9.1
+README for Unbound 1.9.2
 Copyright 2007 NLnet Labs
 http://unbound.net
 
Index: doc/example.conf.in
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/doc/example.conf.in,v
retrieving revision 1.23
diff -u -p -r1.23 example.conf.in
--- doc/example.conf.in 27 Mar 2019 12:06:18 -0000 1.23
+++ doc/example.conf.in 24 Jun 2019 20:06:17 -0000
@@ -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
@@ -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"
Index: doc/libunbound.3.in
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/doc/libunbound.3.in,v
retrieving revision 1.21
diff -u -p -r1.21 libunbound.3.in
--- doc/libunbound.3.in 27 Mar 2019 12:06:18 -0000 1.21
+++ doc/libunbound.3.in 24 Jun 2019 20:06:17 -0000
@@ -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
Index: doc/unbound-anchor.8.in
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/doc/unbound-anchor.8.in,v
retrieving revision 1.20
diff -u -p -r1.20 unbound-anchor.8.in
--- doc/unbound-anchor.8.in 27 Mar 2019 12:06:18 -0000 1.20
+++ doc/unbound-anchor.8.in 24 Jun 2019 20:06:17 -0000
@@ -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
 .\"
Index: doc/unbound-checkconf.8.in
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/doc/unbound-checkconf.8.in,v
retrieving revision 1.20
diff -u -p -r1.20 unbound-checkconf.8.in
--- doc/unbound-checkconf.8.in 27 Mar 2019 12:06:18 -0000 1.20
+++ doc/unbound-checkconf.8.in 24 Jun 2019 20:06:17 -0000
@@ -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
 .\"
Index: doc/unbound-control.8.in
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/doc/unbound-control.8.in,v
retrieving revision 1.22
diff -u -p -r1.22 unbound-control.8.in
--- doc/unbound-control.8.in 27 Mar 2019 12:06:18 -0000 1.22
+++ doc/unbound-control.8.in 24 Jun 2019 20:06:17 -0000
@@ -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
 .\"
Index: doc/unbound-host.1.in
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/doc/unbound-host.1.in,v
retrieving revision 1.22
diff -u -p -r1.22 unbound-host.1.in
--- doc/unbound-host.1.in 27 Mar 2019 12:06:18 -0000 1.22
+++ doc/unbound-host.1.in 24 Jun 2019 20:06:17 -0000
@@ -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
 .\"
Index: doc/unbound.8.in
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/doc/unbound.8.in,v
retrieving revision 1.23
diff -u -p -r1.23 unbound.8.in
--- doc/unbound.8.in 27 Mar 2019 12:06:18 -0000 1.23
+++ doc/unbound.8.in 24 Jun 2019 20:06:17 -0000
@@ -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 ]
Index: doc/unbound.conf.5.in
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/doc/unbound.conf.5.in,v
retrieving revision 1.26
diff -u -p -r1.26 unbound.conf.5.in
--- doc/unbound.conf.5.in 27 Mar 2019 12:06:18 -0000 1.26
+++ doc/unbound.conf.5.in 24 Jun 2019 20:06:17 -0000
@@ -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
 .\"
@@ -264,6 +264,8 @@ it may also work.  You can enable it (on
 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
@@ -783,7 +785,7 @@ Can be given multiple times, for differe
 .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.
@@ -1630,6 +1632,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
Index: doc/unbound.doxygen
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/doc/unbound.doxygen,v
retrieving revision 1.3
diff -u -p -r1.3 unbound.doxygen
--- doc/unbound.doxygen 4 Dec 2018 12:05:07 -0000 1.3
+++ doc/unbound.doxygen 24 Jun 2019 20:06:17 -0000
@@ -629,6 +629,7 @@ EXCLUDE                = ./build \
                          libunbound/python/doc \
                          libunbound/python/examples \
                          ./ldns-src \
+ README.md \
  doc/control_proto_spec.txt \
  doc/requirements.txt
 
Index: edns-subnet/subnetmod.c
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/edns-subnet/subnetmod.c,v
retrieving revision 1.5
diff -u -p -r1.5 subnetmod.c
--- edns-subnet/subnetmod.c 4 Dec 2018 12:05:07 -0000 1.5
+++ edns-subnet/subnetmod.c 24 Jun 2019 20:06:17 -0000
@@ -334,33 +334,37 @@ update_cache(struct module_qstate *qstat
  /* 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 *qstat
  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 *qstat
  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);
  }
Index: iterator/iter_utils.c
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/iterator/iter_utils.c,v
retrieving revision 1.12
diff -u -p -r1.12 iter_utils.c
--- iterator/iter_utils.c 27 Mar 2019 12:06:18 -0000 1.12
+++ iterator/iter_utils.c 24 Jun 2019 20:06:17 -0000
@@ -1211,6 +1211,19 @@ iter_scrub_ds(struct dns_msg* msg, struc
  }
 }
 
+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;
Index: iterator/iter_utils.h
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/iterator/iter_utils.h,v
retrieving revision 1.8
diff -u -p -r1.8 iter_utils.h
--- iterator/iter_utils.h 4 Dec 2018 12:05:07 -0000 1.8
+++ iterator/iter_utils.h 24 Jun 2019 20:06:17 -0000
@@ -335,6 +335,13 @@ void iter_scrub_ds(struct dns_msg* msg,
  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.
Index: iterator/iterator.c
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/iterator/iterator.c,v
retrieving revision 1.22
diff -u -p -r1.22 iterator.c
--- iterator/iterator.c 27 Mar 2019 12:06:18 -0000 1.22
+++ iterator/iterator.c 24 Jun 2019 20:06:17 -0000
@@ -2718,8 +2718,15 @@ processQueryResponse(struct module_qstat
  && !(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. */
Index: services/authzone.c
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/services/authzone.c,v
retrieving revision 1.10
diff -u -p -r1.10 authzone.c
--- services/authzone.c 8 Feb 2019 10:29:08 -0000 1.10
+++ services/authzone.c 24 Jun 2019 20:06:17 -0000
@@ -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, str
  * 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, str
 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,
  /* 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_zo
  /* 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_
  } 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_
  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_
  /* 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_
  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_
  } 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*
 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
  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
  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
  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
  /* 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 au
  * 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 au
  /* 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(
  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_xf
  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 c
  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
  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* x
  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* x
  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* x
  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* x
  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* x
  /* 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*
  * 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*
  /* 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*
  /* 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(voi
  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 &&
Index: services/authzone.h
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/services/authzone.h,v
retrieving revision 1.7
diff -u -p -r1.7 authzone.h
--- services/authzone.h 8 Feb 2019 10:29:08 -0000 1.7
+++ services/authzone.h 24 Jun 2019 20:06:17 -0000
@@ -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(str
         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,
Index: services/listen_dnsport.c
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/services/listen_dnsport.c,v
retrieving revision 1.22
diff -u -p -r1.22 listen_dnsport.c
--- services/listen_dnsport.c 27 Mar 2019 12:06:18 -0000 1.22
+++ services/listen_dnsport.c 24 Jun 2019 20:06:17 -0000
@@ -851,13 +851,16 @@ create_tcp_accept_sock(struct addrinfo *
 #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->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_
  * 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;
  }
Index: services/mesh.c
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/services/mesh.c,v
retrieving revision 1.11
diff -u -p -r1.11 mesh.c
--- services/mesh.c 8 Feb 2019 10:29:08 -0000 1.11
+++ services/mesh.c 24 Jun 2019 20:06:17 -0000
@@ -354,6 +354,10 @@ void mesh_new_client(struct mesh_area* m
  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* m
  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* m
  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* m
  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*
  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_sta
  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;
Index: services/outside_network.c
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/services/outside_network.c,v
retrieving revision 1.14
diff -u -p -r1.14 outside_network.c
--- services/outside_network.c 27 Mar 2019 12:06:18 -0000 1.14
+++ services/outside_network.c 24 Jun 2019 20:06:17 -0000
@@ -364,6 +364,8 @@ outnet_tcp_take_into_use(struct waiting_
  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_
  }
  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
  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
  }
  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 outsid
 
  /* 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 */
Index: services/outside_network.h
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/services/outside_network.h,v
retrieving revision 1.8
diff -u -p -r1.8 outside_network.h
--- services/outside_network.h 8 Feb 2019 10:29:08 -0000 1.8
+++ services/outside_network.h 24 Jun 2019 20:06:17 -0000
@@ -570,12 +570,14 @@ struct comm_point* outnet_comm_point_for
  * @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.
Index: services/cache/dns.c
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/services/cache/dns.c,v
retrieving revision 1.12
diff -u -p -r1.12 dns.c
--- services/cache/dns.c 4 Dec 2018 12:05:07 -0000 1.12
+++ services/cache/dns.c 24 Jun 2019 20:06:17 -0000
@@ -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);
Index: testcode/fake_event.c
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/testcode/fake_event.c,v
retrieving revision 1.1.1.3
diff -u -p -r1.1.1.3 fake_event.c
--- testcode/fake_event.c 8 Feb 2019 10:26:32 -0000 1.1.1.3
+++ testcode/fake_event.c 24 Jun 2019 20:06:17 -0000
@@ -1629,7 +1629,8 @@ struct comm_point* outnet_comm_point_for
 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;
Index: util/alloc.c
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/util/alloc.c,v
retrieving revision 1.3
diff -u -p -r1.3 alloc.c
--- util/alloc.c 17 Sep 2018 09:46:12 -0000 1.3
+++ util/alloc.c 24 Jun 2019 20:06:17 -0000
@@ -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,
  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, si
  /* 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 si
         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 nm
  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);
Index: util/fptr_wlist.c
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/util/fptr_wlist.c,v
retrieving revision 1.14
diff -u -p -r1.14 fptr_wlist.c
--- util/fptr_wlist.c 4 Dec 2018 12:05:07 -0000 1.14
+++ util/fptr_wlist.c 24 Jun 2019 20:06:17 -0000
@@ -127,6 +127,7 @@ fptr_whitelist_comm_timer(void (*fptr)(v
 #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;
 }
 
Index: util/iana_ports.inc
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/util/iana_ports.inc,v
retrieving revision 1.15
diff -u -p -r1.15 iana_ports.inc
--- util/iana_ports.inc 4 Dec 2018 12:05:07 -0000 1.15
+++ util/iana_ports.inc 24 Jun 2019 20:06:17 -0000
@@ -4768,6 +4768,7 @@
 8088,
 8097,
 8100,
+8111,
 8115,
 8116,
 8118,
@@ -4864,6 +4865,7 @@
 8805,
 8807,
 8808,
+8809,
 8873,
 8880,
 8883,
Index: util/net_help.c
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/util/net_help.c,v
retrieving revision 1.15
diff -u -p -r1.15 net_help.c
--- util/net_help.c 27 Mar 2019 12:06:18 -0000 1.15
+++ util/net_help.c 24 Jun 2019 20:06:17 -0000
@@ -802,6 +802,16 @@ void* listen_sslctx_create(char* key, ch
  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);
Index: util/netevent.c
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/util/netevent.c,v
retrieving revision 1.20
diff -u -p -r1.20 netevent.c
--- util/netevent.c 27 Mar 2019 12:06:18 -0000 1.20
+++ util/netevent.c 24 Jun 2019 20:06:17 -0000
@@ -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, s
  }
  /* 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, stru
  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, stru
  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, stru
   #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, stru
  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, stru
 #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, stru
  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, s
  }
 #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, s
  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,
  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,
  }
  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_po
 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;
Index: util/ub_event.c
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/util/ub_event.c,v
retrieving revision 1.4
diff -u -p -r1.4 ub_event.c
--- util/ub_event.c 17 Sep 2018 09:46:12 -0000 1.4
+++ util/ub_event.c 24 Jun 2019 20:06:17 -0000
@@ -295,11 +295,18 @@ ub_event_new(struct ub_event_base* base,
  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
  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);
 }
 
Index: util/data/msgreply.h
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/util/data/msgreply.h,v
retrieving revision 1.8
diff -u -p -r1.8 msgreply.h
--- util/data/msgreply.h 20 Sep 2018 23:15:40 -0000 1.8
+++ util/data/msgreply.h 24 Jun 2019 20:06:17 -0000
@@ -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;
Index: util/storage/lookup3.c
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/util/storage/lookup3.c,v
retrieving revision 1.4
diff -u -p -r1.4 lookup3.c
--- util/storage/lookup3.c 29 Sep 2017 16:27:14 -0000 1.4
+++ util/storage/lookup3.c 24 Jun 2019 20:06:17 -0000
@@ -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
 -------------------------------------------------------------------------------
 */
 /*#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, si
   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, si
      * 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)
     {