Index | Thread | Search

From:
Stuart Henderson <stu@spacehopper.org>
Subject:
unbound 1.19.3
To:
tech <tech@openbsd.org>
Cc:
Florian Obser <florian@openbsd.org>
Date:
Fri, 12 Apr 2024 16:54:50 +0100

Download raw body.

Thread
  • Stuart Henderson:

    unbound 1.19.3

applies on top of 1.19.2 which I _just_ committed

Index: doc/Changelog
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/doc/Changelog,v
diff -u -p -r1.50 Changelog
--- doc/Changelog	12 Apr 2024 15:45:24 -0000	1.50
+++ doc/Changelog	12 Apr 2024 15:50:24 -0000
@@ -1,6 +1,144 @@
+8 March 2024: Wouter
+	- Fix unbound-control-setup.cmd to use 3072 bits so that certificates
+	  are long enough for newer OpenSSL versions.
+	- Fix TTL of synthesized CNAME when a DNAME is used from cache.
+	- Fix unbound-control-setup.cmd to have CA v3 basicConstraints,
+	  like unbound-control-setup.sh has.
+
+7 March 2024: Wouter
+	- Version set to 1.19.3 for release. After 1.19.2 point release with
+	  security fix for CVE-2024-1931, Denial of service when trimming
+	  EDE text on positive replies. The code repo includes the fix and
+	  is for version 1.19.3.
+
+5 March 2024: Wouter
+	- Fix for #1022: Fix ede prohibited in access control refused answers.
+
+4 March 2024: Wouter
+	- Fix edns subnet replies for scope zero answers to not get stored
+	  in the global cache, and in cachedb, when the upstream replies
+	  without an EDNS record.
+
+28 February 2024: Wouter
+	- Move github workflows to use checkoutv4.
+
+23 February 2024: Yorgos
+	- Document the suspend argument for process_ds_response().
+
+22 February 2024: Wouter
+	- Fix trim of EDE text from large udp responses from spinning cpu.
+
+20 February 2024: Yorgos
+	- Merge #1010: Mention REFUSED has the TC bit set with unmatched
+	  allow_cookie acl in the manpage. It also fixes the code to match the
+	  documentation about clients with a valid cookie that bypass the
+	  ratelimit regardless of the allow_cookie acl.
+
+13 February 2024: Wouter
+	- Fix CVE-2023-50387, DNSSEC verification complexity can be exploited
+	  to exhaust CPU resources and stall DNS resolvers.
+	- Fix CVE-2023-50868, NSEC3 closest encloser proof can exhaust CPU.
+	- These fixes are part of the 1.19.1 release, that is a security
+	  point release on 1.19.0, the code repository continues with these
+	  fixes, with version number 1.19.2.
+
+8 February 2024: Wouter
+	- Fix documentation for access-control in the unbound.conf man page.
+
+7 February 2024: Yorgos
+	- Fix #1006: Can't find protobuf-c package since #999.
+
+30 January 2024: Wouter
+	- Merge #999: Search for protobuf-c with pkg-config.
+
+23 January 2024: Yorgos
+	- Update message TTL when using cached RRSETs. It could result in
+	  non-expired messages with expired RRSETs (non-usable messages by
+	  Unbound).
+
+22 January 2024: Yorgos
+	- Update error printout for duplicate trust anchors to include the
+	  trust anchor name (relates to #920).
+
+22 January 2024: Wouter
+	- Fix for #997: Print details for SSL certificate failure.
+
+17 January 2024: Wouter
+	- Update workflow for ports to use newer openssl on windows compile.
+	- Fix warning for windres on resource files due to redefinition.
+
+16 January 2024: Wouter
+	- Fix to link with libssp for libcrypto and getaddrinfo check for
+	  only header. Also update crosscompile to remove ssp for 32bit.
+	- Merge #993: Update b.root-servers.net also in example config file.
+
+15 January 2024: Wouter
+	- Fix to link with -lcrypt32 for OpenSSL 3.2.0 on Windows.
+
+9 January 2024: Wouter
+	- Merge #988: Fix NLnetLabs#981: dump_cache truncates large records.
+
+5 January 2024: Wouter
+	- Merge #987: skip edns frag retry if advertised udp payload size is
+	  not smaller.
+	- Fix unit test for #987 change in udp1xxx retry packet send.
+
+4 January 2024: Wouter
+	- Remove unneeded newlines and improve indentation in remote control
+	  code.
+
+3 January 2024: Wouter
+	- Merge #980: DoH: reject non-h2 early. To fix #979: Improve errors
+	  for non-HTTP/2 DoH clients.
+	- Merge #985: Add DoH and DoT to dnstap message.
+	- Fix #983: Sha1 runtime insecure change was incomplete.
+
+22 December 2023: Yorgos
+	- Update example.conf with cookie options.
+
+8 December 2023: Yorgos
+	- Merge PR #973: Use the origin (DNAME) TTL for synthesized CNAMEs as
+	  per RFC 6672.
+
+8 December 2023: Wouter
+	- Fix root_zonemd unit test, it checks that the root ZONEMD verifies,
+	  now that the root has a valid ZONEMD.
+
+7 December 2023: Wouter
+	- Fix #974: doc: default number of outgoing ports without libevent.
+	- Merge #975: Fixed some syntax errors in rpl files.
+
+6 December 2023: Wouter
+	- Fix to sync the tests script file common.sh.
+	- iana portlist update.
+	- Updated IPv4 and IPv6 address for b.root-servers.net in root hints.
+	- Update test script file common.sh.
+	- Fix tests to use new common.sh functions, wait_logfile and
+	  kill_from_pidfile.
+
+5 December 2023: Wouter
+	- Merge #971: fix 'WARNING: Message has 41 extra bytes at end'.
+	- Fix #969: [FR] distinguish Do53, DoT and DoH in the logs.
+	- Fix dnstap that assertion failed on logging other than UDP and TCP
+	  traffic. It lists it as TCP traffic.
+
+27 November 2023: Yorgos
+	- Merge #968: Replace the obsolescent fgrep with grep -F in tests.
+
+27 November 2023: Wouter
+	- Fix #964: config.h.in~ backup file in release tar balls.
+
+24 November 2023: Yorgos
+	- Use 127.0.0.1 explicitly in tests to avoid delays and errors on
+	  newer systems.
+
+9 November 2023: Wouter
+	- Fix unit test parse of origin syntax.
+
 2 November 2023: Wouter
 	- Set version number to 1.19.0.
-	- Tag for 1.19.0rc1 release.
+	- Tag for 1.19.0rc1 release. It became 1.19.0 release on 8 nov 2023.
+	  The repository continues with 1.19.1.
 
 1 November 2023: George
 	- Mention flex and bison in README.md when building from repository
Index: acx_nlnetlabs.m4
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/acx_nlnetlabs.m4,v
diff -u -p -r1.12 acx_nlnetlabs.m4
--- acx_nlnetlabs.m4	5 Sep 2023 11:12:09 -0000	1.12
+++ acx_nlnetlabs.m4	12 Apr 2024 15:50:23 -0000
@@ -2,7 +2,10 @@
 # Copyright 2009, Wouter Wijngaards, NLnet Labs.   
 # BSD licensed.
 #
-# Version 46
+# Version 48
+# 2024-01-16 fix to add -l:libssp.a to -lcrypto link check.
+#	     and check for getaddrinfo with only header.
+# 2024-01-15 fix to add crypt32 to -lcrypto link check when checking for gdi32.
 # 2023-05-04 fix to remove unused whitespace.
 # 2023-01-26 fix -Wstrict-prototypes.
 # 2022-09-01 fix checking if nonblocking sockets work on OpenBSD.
@@ -707,7 +710,7 @@ AC_DEFUN([ACX_SSL_CHECKS], [
 		    LIBSSL_LDFLAGS="$LIBSSL_LDFLAGS -L$ssldir_lib"
 	    	    ACX_RUNTIME_PATH_ADD([$ssldir_lib])
 	    fi
-        
+
             AC_MSG_CHECKING([for EVP_sha256 in -lcrypto])
             LIBS="$LIBS -lcrypto"
             LIBSSL_LIBS="$LIBSSL_LIBS -lcrypto"
@@ -732,40 +735,73 @@ AC_DEFUN([ACX_SSL_CHECKS], [
                   ]])],[
                     AC_DEFINE([HAVE_EVP_SHA256], 1,
                         [If you have EVP_sha256])
-                    AC_MSG_RESULT(yes) 
+                    AC_MSG_RESULT(yes)
                   ],[
                     AC_MSG_RESULT(no)
                     LIBS="$BAKLIBS"
                     LIBSSL_LIBS="$BAKSSLLIBS"
-                    LIBS="$LIBS -ldl"
-                    LIBSSL_LIBS="$LIBSSL_LIBS -ldl"
-                    AC_MSG_CHECKING([if -lcrypto needs -ldl])
-                    AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[
-                        int EVP_sha256(void);
-                        (void)EVP_sha256();
-                      ]])],[
-                        AC_DEFINE([HAVE_EVP_SHA256], 1,
-                            [If you have EVP_sha256])
-                        AC_MSG_RESULT(yes) 
-                      ],[
-                        AC_MSG_RESULT(no)
-                        LIBS="$BAKLIBS"
-                        LIBSSL_LIBS="$BAKSSLLIBS"
-                        LIBS="$LIBS -ldl -pthread"
-                        LIBSSL_LIBS="$LIBSSL_LIBS -ldl -pthread"
-                        AC_MSG_CHECKING([if -lcrypto needs -ldl -pthread])
-                        AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[
-                            int EVP_sha256(void);
-                            (void)EVP_sha256();
-                          ]])],[
-                            AC_DEFINE([HAVE_EVP_SHA256], 1,
-                                [If you have EVP_sha256])
-                            AC_MSG_RESULT(yes) 
-                          ],[
-                            AC_MSG_RESULT(no)
-                            AC_MSG_ERROR([OpenSSL found in $ssldir, but version 0.9.7 or higher is required])
+
+		    LIBS="$LIBS -lgdi32 -lws2_32 -lcrypt32"
+		    LIBSSL_LIBS="$LIBSSL_LIBS -lgdi32 -lws2_32 -lcrypt32"
+                    AC_MSG_CHECKING([if -lcrypto needs -lgdi32 -lws2_32 -lcrypt32])
+		    AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[
+			int EVP_sha256(void);
+			(void)EVP_sha256();
+		      ]])],[
+			AC_DEFINE([HAVE_EVP_SHA256], 1,
+			    [If you have EVP_sha256])
+			AC_MSG_RESULT(yes)
+		      ],[
+			AC_MSG_RESULT(no)
+			LIBS="$BAKLIBS"
+			LIBSSL_LIBS="$BAKSSLLIBS"
+
+			LIBS="$LIBS -lgdi32 -lws2_32 -lcrypt32 -l:libssp.a"
+			LIBSSL_LIBS="$LIBSSL_LIBS -lgdi32 -lws2_32 -lcrypt32 -l:libssp.a"
+			AC_MSG_CHECKING([if -lcrypto needs -lgdi32 -lws2_32 -lcrypt32 -l:libssp.a])
+			AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[
+			    int EVP_sha256(void);
+			    (void)EVP_sha256();
+			  ]])],[
+			    AC_DEFINE([HAVE_EVP_SHA256], 1,
+				[If you have EVP_sha256])
+			    AC_MSG_RESULT(yes)
+			  ],[
+			    AC_MSG_RESULT(no)
+			    LIBS="$BAKLIBS"
+			    LIBSSL_LIBS="$BAKSSLLIBS"
+
+			    LIBS="$LIBS -ldl"
+			    LIBSSL_LIBS="$LIBSSL_LIBS -ldl"
+			    AC_MSG_CHECKING([if -lcrypto needs -ldl])
+			    AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[
+				int EVP_sha256(void);
+				(void)EVP_sha256();
+			      ]])],[
+				AC_DEFINE([HAVE_EVP_SHA256], 1,
+				    [If you have EVP_sha256])
+				AC_MSG_RESULT(yes)
+			      ],[
+				AC_MSG_RESULT(no)
+				LIBS="$BAKLIBS"
+				LIBSSL_LIBS="$BAKSSLLIBS"
+				LIBS="$LIBS -ldl -pthread"
+				LIBSSL_LIBS="$LIBSSL_LIBS -ldl -pthread"
+				AC_MSG_CHECKING([if -lcrypto needs -ldl -pthread])
+				AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[
+				    int EVP_sha256(void);
+				    (void)EVP_sha256();
+				  ]])],[
+				    AC_DEFINE([HAVE_EVP_SHA256], 1,
+					[If you have EVP_sha256])
+				    AC_MSG_RESULT(yes)
+				  ],[
+				    AC_MSG_RESULT(no)
+				    AC_MSG_ERROR([OpenSSL found in $ssldir, but version 0.9.7 or higher is required])
+				])
+			    ])
 			])
-                    ])
+		    ])
                 ])
             ])
         fi
@@ -779,7 +815,7 @@ AC_CHECK_HEADERS([openssl/rand.h],,, [AC
 
 dnl Check for SSL, where SSL is mandatory
 dnl Adds --with-ssl option, searches for openssl and defines HAVE_SSL if found
-dnl Setup of CPPFLAGS, CFLAGS.  Adds -lcrypto to LIBS. 
+dnl Setup of CPPFLAGS, CFLAGS.  Adds -lcrypto to LIBS.
 dnl Checks main header files of SSL.
 dnl
 AC_DEFUN([ACX_WITH_SSL],
@@ -872,7 +908,7 @@ dnl see if on windows
 if test "$ac_cv_header_windows_h" = "yes"; then
 	AC_DEFINE(USE_WINSOCK, 1, [Whether the windows socket API is used])
 	USE_WINSOCK="1"
-	if echo $LIBS | grep 'lws2_32' >/dev/null; then
+	if echo "$LIBS" | grep 'lws2_32' >/dev/null; then
 		:
 	else
 		LIBS="$LIBS -lws2_32"
@@ -880,6 +916,24 @@ if test "$ac_cv_header_windows_h" = "yes
 fi
 ],
 dnl no quick getaddrinfo, try mingw32 and winsock2 library.
+dnl perhaps getaddrinfo needs only the include
+AC_LINK_IFELSE(
+[AC_LANG_PROGRAM(
+[
+#ifdef HAVE_WS2TCPIP_H
+#include <ws2tcpip.h>
+#endif
+],
+[
+        (void)getaddrinfo(NULL, NULL, NULL, NULL);
+]
+)],
+[
+ac_cv_func_getaddrinfo="yes"
+AC_DEFINE(USE_WINSOCK, 1, [Whether the windows socket API is used])
+USE_WINSOCK="1"
+],
+
 ORIGLIBS="$LIBS"
 LIBS="$LIBS -lws2_32"
 AC_LINK_IFELSE(
@@ -903,6 +957,7 @@ USE_WINSOCK="1"
 ac_cv_func_getaddrinfo="no"
 LIBS="$ORIGLIBS"
 ])
+)
 )
 
 AC_MSG_RESULT($ac_cv_func_getaddrinfo)
Index: configure
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/configure,v
diff -u -p -r1.52 configure
--- configure	12 Apr 2024 15:45:24 -0000	1.52
+++ configure	12 Apr 2024 15:50:24 -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.19.2.
+# Generated by GNU Autoconf 2.69 for unbound 1.19.3.
 #
 # Report bugs to <unbound-bugs@nlnetlabs.nl or https://github.com/NLnetLabs/unbound/issues>.
 #
@@ -591,8 +591,8 @@ MAKEFLAGS=
 # Identity of this package.
 PACKAGE_NAME='unbound'
 PACKAGE_TARNAME='unbound'
-PACKAGE_VERSION='1.19.2'
-PACKAGE_STRING='unbound 1.19.2'
+PACKAGE_VERSION='1.19.3'
+PACKAGE_STRING='unbound 1.19.3'
 PACKAGE_BUGREPORT='unbound-bugs@nlnetlabs.nl or https://github.com/NLnetLabs/unbound/issues'
 PACKAGE_URL=''
 
@@ -655,6 +655,8 @@ DNSTAP_SOCKET_TESTBIN
 DNSTAP_SOCKET_PATH
 opt_dnstap_socket_path
 ENABLE_DNSTAP
+PROTOBUFC_LIBS
+PROTOBUFC_CFLAGS
 PROTOC_C
 UBSYMS
 EXTRALINK
@@ -926,7 +928,9 @@ SYSTEMD_CFLAGS
 SYSTEMD_LIBS
 SYSTEMD_DAEMON_CFLAGS
 SYSTEMD_DAEMON_LIBS
-PYTHON_VERSION'
+PYTHON_VERSION
+PROTOBUFC_CFLAGS
+PROTOBUFC_LIBS'
 
 
 # Initialize some variables set by options.
@@ -1477,7 +1481,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.19.2 to adapt to many kinds of systems.
+\`configure' configures unbound 1.19.3 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1543,7 +1547,7 @@ fi
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of unbound 1.19.2:";;
+     short | recursive ) echo "Configuration of unbound 1.19.3:";;
    esac
   cat <<\_ACEOF
 
@@ -1718,6 +1722,10 @@ Some influential environment variables:
               The installed Python version to use, for example '2.3'. This
               string will be appended to the Python interpreter canonical
               name.
+  PROTOBUFC_CFLAGS
+              C compiler flags for PROTOBUFC, overriding pkg-config
+  PROTOBUFC_LIBS
+              linker flags for PROTOBUFC, overriding pkg-config
 
 Use these variables to override the choices made by `configure' or to help
 it to find libraries and programs with nonstandard names/locations.
@@ -1785,7 +1793,7 @@ fi
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-unbound configure 1.19.2
+unbound configure 1.19.3
 generated by GNU Autoconf 2.69
 
 Copyright (C) 2012 Free Software Foundation, Inc.
@@ -2494,7 +2502,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.19.2, which was
+It was created by unbound $as_me 1.19.3, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   $ $0 $@
@@ -2846,11 +2854,11 @@ UNBOUND_VERSION_MAJOR=1
 
 UNBOUND_VERSION_MINOR=19
 
-UNBOUND_VERSION_MICRO=2
+UNBOUND_VERSION_MICRO=3
 
 
 LIBUNBOUND_CURRENT=9
-LIBUNBOUND_REVISION=25
+LIBUNBOUND_REVISION=26
 LIBUNBOUND_AGE=1
 # 1.0.0 had 0:12:0
 # 1.0.1 had 0:13:0
@@ -2943,6 +2951,7 @@ LIBUNBOUND_AGE=1
 # 1.19.0 had 9:23:1
 # 1.19.1 had 9:24:1
 # 1.19.2 had 9:25:1
+# 1.19.3 had 9:26:1
 
 #   Current  -- the number of the binary API that we're implementing
 #   Revision -- which iteration of the implementation of the binary
@@ -14417,7 +14426,7 @@ CC=$lt_save_CC
 
 
 # pkg-config is only needed for these options, do not require it otherwise
-if test "$enable_systemd" = "yes" -o "$with_pyunbound" = "yes" -o "$with_pythonmod" = "yes"; then
+if test "$enable_systemd" = "yes" -o "$enable_dnstap" = "yes" -o "$with_pyunbound" = "yes" -o "$with_pythonmod" = "yes"; then
 
 
 
@@ -18105,19 +18114,86 @@ else
 $as_echo "no" >&6; }
                     LIBS="$BAKLIBS"
                     LIBSSL_LIBS="$BAKSSLLIBS"
-                    LIBS="$LIBS -ldl"
-                    LIBSSL_LIBS="$LIBSSL_LIBS -ldl"
-                    { $as_echo "$as_me:${as_lineno-$LINENO}: checking if -lcrypto needs -ldl" >&5
+
+		    LIBS="$LIBS -lgdi32 -lws2_32 -lcrypt32"
+		    LIBSSL_LIBS="$LIBSSL_LIBS -lgdi32 -lws2_32 -lcrypt32"
+                    { $as_echo "$as_me:${as_lineno-$LINENO}: checking if -lcrypto needs -lgdi32 -lws2_32 -lcrypt32" >&5
+$as_echo_n "checking if -lcrypto needs -lgdi32 -lws2_32 -lcrypt32... " >&6; }
+		    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+			int EVP_sha256(void);
+			(void)EVP_sha256();
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+
+
+$as_echo "#define HAVE_EVP_SHA256 1" >>confdefs.h
+
+			{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+else
+
+			{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+			LIBS="$BAKLIBS"
+			LIBSSL_LIBS="$BAKSSLLIBS"
+
+			LIBS="$LIBS -lgdi32 -lws2_32 -lcrypt32 -l:libssp.a"
+			LIBSSL_LIBS="$LIBSSL_LIBS -lgdi32 -lws2_32 -lcrypt32 -l:libssp.a"
+			{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if -lcrypto needs -lgdi32 -lws2_32 -lcrypt32 -l:libssp.a" >&5
+$as_echo_n "checking if -lcrypto needs -lgdi32 -lws2_32 -lcrypt32 -l:libssp.a... " >&6; }
+			cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+			    int EVP_sha256(void);
+			    (void)EVP_sha256();
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+
+
+$as_echo "#define HAVE_EVP_SHA256 1" >>confdefs.h
+
+			    { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+else
+
+			    { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+			    LIBS="$BAKLIBS"
+			    LIBSSL_LIBS="$BAKSSLLIBS"
+
+			    LIBS="$LIBS -ldl"
+			    LIBSSL_LIBS="$LIBSSL_LIBS -ldl"
+			    { $as_echo "$as_me:${as_lineno-$LINENO}: checking if -lcrypto needs -ldl" >&5
 $as_echo_n "checking if -lcrypto needs -ldl... " >&6; }
-                    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+			    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
 int
 main ()
 {
 
-                        int EVP_sha256(void);
-                        (void)EVP_sha256();
+				int EVP_sha256(void);
+				(void)EVP_sha256();
 
   ;
   return 0;
@@ -18128,28 +18204,28 @@ if ac_fn_c_try_link "$LINENO"; then :
 
 $as_echo "#define HAVE_EVP_SHA256 1" >>confdefs.h
 
-                        { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+				{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
 $as_echo "yes" >&6; }
 
 else
 
-                        { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+				{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
 $as_echo "no" >&6; }
-                        LIBS="$BAKLIBS"
-                        LIBSSL_LIBS="$BAKSSLLIBS"
-                        LIBS="$LIBS -ldl -pthread"
-                        LIBSSL_LIBS="$LIBSSL_LIBS -ldl -pthread"
-                        { $as_echo "$as_me:${as_lineno-$LINENO}: checking if -lcrypto needs -ldl -pthread" >&5
+				LIBS="$BAKLIBS"
+				LIBSSL_LIBS="$BAKSSLLIBS"
+				LIBS="$LIBS -ldl -pthread"
+				LIBSSL_LIBS="$LIBSSL_LIBS -ldl -pthread"
+				{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if -lcrypto needs -ldl -pthread" >&5
 $as_echo_n "checking if -lcrypto needs -ldl -pthread... " >&6; }
-                        cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+				cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
 int
 main ()
 {
 
-                            int EVP_sha256(void);
-                            (void)EVP_sha256();
+				    int EVP_sha256(void);
+				    (void)EVP_sha256();
 
   ;
   return 0;
@@ -18160,14 +18236,22 @@ if ac_fn_c_try_link "$LINENO"; then :
 
 $as_echo "#define HAVE_EVP_SHA256 1" >>confdefs.h
 
-                            { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+				    { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
 $as_echo "yes" >&6; }
 
 else
 
-                            { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+				    { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
 $as_echo "no" >&6; }
-                            as_fn_error $? "OpenSSL found in $ssldir, but version 0.9.7 or higher is required" "$LINENO" 5
+				    as_fn_error $? "OpenSSL found in $ssldir, but version 0.9.7 or higher is required" "$LINENO" 5
+
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
 
 fi
 rm -f core conftest.err conftest.$ac_objext \
@@ -19848,7 +19932,7 @@ if test x_$enable_static_exe = x_yes; th
 	if test "$on_mingw" = yes; then
 		staticexe="-all-static"
 		# for static compile, include gdi32 and zlib here.
-		if echo $LIBS | grep 'lgdi32' >/dev/null; then
+		if echo "$LIBS" | grep 'lgdi32' >/dev/null; then
 			:
 		else
 			LIBS="$LIBS -lgdi32"
@@ -19893,7 +19977,11 @@ if test "x$ac_cv_lib_z_compress" = xyes;
    LIBS="$LIBS -lz"
 fi
 
-		LIBS="$LIBS -l:libssp.a"
+		if echo "$LIBS" | grep -e "libssp.a" -e "lssp" >/dev/null; then
+			:
+		else
+			LIBS="$LIBS -l:libssp.a"
+		fi
 	fi
 fi
 
@@ -19952,7 +20040,11 @@ if test "x$ac_cv_lib_z_compress" = xyes;
    LIBS="$LIBS -lz"
 fi
 
-		LIBS="$LIBS -l:libssp.a"
+		if echo "$LIBS" | grep -e "libssp.a" -e "lssp" >/dev/null; then
+			:
+		else
+			LIBS="$LIBS -l:libssp.a"
+		fi
 	fi
 fi
 
@@ -19999,7 +20091,7 @@ if test "$ac_cv_header_windows_h" = "yes
 $as_echo "#define USE_WINSOCK 1" >>confdefs.h
 
 	USE_WINSOCK="1"
-	if echo $LIBS | grep 'lws2_32' >/dev/null; then
+	if echo "$LIBS" | grep 'lws2_32' >/dev/null; then
 		:
 	else
 		LIBS="$LIBS -lws2_32"
@@ -20007,6 +20099,33 @@ $as_echo "#define USE_WINSOCK 1" >>confd
 fi
 
 else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#ifdef HAVE_WS2TCPIP_H
+#include <ws2tcpip.h>
+#endif
+
+int
+main ()
+{
+
+        (void)getaddrinfo(NULL, NULL, NULL, NULL);
+
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+
+ac_cv_func_getaddrinfo="yes"
+
+$as_echo "#define USE_WINSOCK 1" >>confdefs.h
+
+USE_WINSOCK="1"
+
+else
   ORIGLIBS="$LIBS"
 LIBS="$LIBS -lws2_32"
 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -20048,6 +20167,10 @@ fi
 rm -f core conftest.err conftest.$ac_objext \
     conftest$ac_exeext conftest.$ac_ext
 
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+
 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_getaddrinfo" >&5
 $as_echo "$ac_cv_func_getaddrinfo" >&6; }
 if test $ac_cv_func_getaddrinfo = yes; then
@@ -20167,7 +20290,11 @@ else
   WINDRES="$ac_cv_prog_WINDRES"
 fi
 
-	LIBS="$LIBS -liphlpapi -lcrypt32"
+	if echo "$LIBS" | grep crypt32 >/dev/null; then
+		LIBS="$LIBS -liphlpapi"
+	else
+		LIBS="$LIBS -liphlpapi -lcrypt32"
+	fi
 	WINAPPS="unbound-service-install.exe unbound-service-remove.exe anchor-update.exe"
 
 	WIN_DAEMON_SRC="winrc/win_svc.c winrc/w_inst.c"
@@ -21200,7 +21327,7 @@ fi
 
 # check for dnstap if requested
 
-  # Check whether --enable-dnstap was given.
+    # Check whether --enable-dnstap was given.
 if test "${enable_dnstap+set}" = set; then :
   enableval=$enable_dnstap; opt_dnstap=$enableval
 else
@@ -21217,8 +21344,8 @@ else
 fi
 
 
-  if test "x$opt_dnstap" != "xno"; then
-    # Extract the first word of "protoc-c", so it can be a program name with args.
+    if test "x$opt_dnstap" != "xno"; then
+        # Extract the first word of "protoc-c", so it can be a program name with args.
 set dummy protoc-c; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
@@ -21258,36 +21385,132 @@ $as_echo "no" >&6; }
 fi
 
 
-    if test -z "$PROTOC_C"; then
-      as_fn_error $? "The protoc-c program was not found. Please install protobuf-c!" "$LINENO" 5
-    fi
+        if test -z "$PROTOC_C"; then
+          as_fn_error $? "The protoc-c program was not found. Please install protobuf-c!" "$LINENO" 5
+        fi
 
 # Check whether --with-protobuf-c was given.
 if test "${with_protobuf_c+set}" = set; then :
   withval=$with_protobuf_c;
-	  # workaround for protobuf-c includes at old dir before protobuf-c-1.0.0
-	  if test -f $withval/include/google/protobuf-c/protobuf-c.h; then
-	    CFLAGS="$CFLAGS -I$withval/include/google"
-	  else
-	    CFLAGS="$CFLAGS -I$withval/include"
-	  fi
-	  LDFLAGS="$LDFLAGS -L$withval/lib"
+                # workaround for protobuf-c includes at old dir before protobuf-c-1.0.0
+                if test -f $withval/include/google/protobuf-c/protobuf-c.h; then
+                    CFLAGS="$CFLAGS -I$withval/include/google"
+                else
+                    CFLAGS="$CFLAGS -I$withval/include"
+                fi
+                LDFLAGS="$LDFLAGS -L$withval/lib"
 
 else
 
-	  # workaround for protobuf-c includes at old dir before protobuf-c-1.0.0
-	  if test -f /usr/include/google/protobuf-c/protobuf-c.h; then
-	    CFLAGS="$CFLAGS -I/usr/include/google"
-	  else
-	    if test -f /usr/local/include/google/protobuf-c/protobuf-c.h; then
-	      CFLAGS="$CFLAGS -I/usr/local/include/google"
-	      LDFLAGS="$LDFLAGS -L/usr/local/lib"
-	    fi
-	  fi
 
+
+pkg_failed=no
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for PROTOBUFC" >&5
+$as_echo_n "checking for PROTOBUFC... " >&6; }
+
+if test -n "$PROTOBUFC_CFLAGS"; then
+    pkg_cv_PROTOBUFC_CFLAGS="$PROTOBUFC_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+    if test -n "$PKG_CONFIG" && \
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libprotobuf-c\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "libprotobuf-c") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+  pkg_cv_PROTOBUFC_CFLAGS=`$PKG_CONFIG --cflags "libprotobuf-c" 2>/dev/null`
+		      test "x$?" != "x0" && pkg_failed=yes
+else
+  pkg_failed=yes
+fi
+ else
+    pkg_failed=untried
+fi
+if test -n "$PROTOBUFC_LIBS"; then
+    pkg_cv_PROTOBUFC_LIBS="$PROTOBUFC_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+    if test -n "$PKG_CONFIG" && \
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libprotobuf-c\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "libprotobuf-c") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+  pkg_cv_PROTOBUFC_LIBS=`$PKG_CONFIG --libs "libprotobuf-c" 2>/dev/null`
+		      test "x$?" != "x0" && pkg_failed=yes
+else
+  pkg_failed=yes
+fi
+ else
+    pkg_failed=untried
+fi
+
+
+
+if test $pkg_failed = yes; then
+   	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
+        _pkg_short_errors_supported=yes
+else
+        _pkg_short_errors_supported=no
 fi
+        if test $_pkg_short_errors_supported = yes; then
+	        PROTOBUFC_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libprotobuf-c" 2>&1`
+        else
+	        PROTOBUFC_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libprotobuf-c" 2>&1`
+        fi
+	# Put the nasty error message in config.log where it belongs
+	echo "$PROTOBUFC_PKG_ERRORS" >&5
+
+
+                                # pkg-config failed; try falling back to known values
+                                # workaround for protobuf-c includes at old dir before protobuf-c-1.0.0
+                                if test -f /usr/include/google/protobuf-c/protobuf-c.h; then
+                                    CFLAGS="$CFLAGS -I/usr/include/google"
+                                else
+                                    if test -f /usr/local/include/google/protobuf-c/protobuf-c.h; then
+                                        CFLAGS="$CFLAGS -I/usr/local/include/google"
+                                        LDFLAGS="$LDFLAGS -L/usr/local/lib"
+                                    else
+                                        as_fn_error $? "The protobuf-c package was not found with pkg-config. Please install protobuf-c!" "$LINENO" 5
+                                    fi
+                                fi
+
 
-    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing protobuf_c_message_pack" >&5
+elif test $pkg_failed = untried; then
+     	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+                                # pkg-config failed; try falling back to known values
+                                # workaround for protobuf-c includes at old dir before protobuf-c-1.0.0
+                                if test -f /usr/include/google/protobuf-c/protobuf-c.h; then
+                                    CFLAGS="$CFLAGS -I/usr/include/google"
+                                else
+                                    if test -f /usr/local/include/google/protobuf-c/protobuf-c.h; then
+                                        CFLAGS="$CFLAGS -I/usr/local/include/google"
+                                        LDFLAGS="$LDFLAGS -L/usr/local/lib"
+                                    else
+                                        as_fn_error $? "The protobuf-c package was not found with pkg-config. Please install protobuf-c!" "$LINENO" 5
+                                    fi
+                                fi
+
+
+else
+	PROTOBUFC_CFLAGS=$pkg_cv_PROTOBUFC_CFLAGS
+	PROTOBUFC_LIBS=$pkg_cv_PROTOBUFC_LIBS
+        { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+                                CFLAGS="$CFLAGS $PROTOBUFC_CFLAGS"
+                                LIBS="$LIBS $PROTOBUFC_LIBS"
+
+fi
+
+
+
+fi
+
+        { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing protobuf_c_message_pack" >&5
 $as_echo_n "checking for library containing protobuf_c_message_pack... " >&6; }
 if ${ac_cv_search_protobuf_c_message_pack+:} false; then :
   $as_echo_n "(cached) " >&6
@@ -21369,13 +21592,13 @@ _ACEOF
         DNSTAP_OBJ="dnstap.lo dnstap.pb-c.lo dnstap_fstrm.lo dtstream.lo"
 
 
-  else
+    else
 
         ENABLE_DNSTAP=0
 
 
 
-  fi
+    fi
 
 
 # check for dnscrypt if requested
@@ -21896,7 +22119,7 @@ _ACEOF
 
 
 
-version=1.19.2
+version=1.19.3
 
 date=`date +'%b %e, %Y'`
 
@@ -22415,7 +22638,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.19.2, which was
+This file was extended by unbound $as_me 1.19.3, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -22481,7 +22704,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.19.2
+unbound config.status 1.19.3
 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
diff -u -p -r1.52 configure.ac
--- configure.ac	12 Apr 2024 15:45:24 -0000	1.52
+++ configure.ac	12 Apr 2024 15:50:24 -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],[19])
-m4_define([VERSION_MICRO],[2])
+m4_define([VERSION_MICRO],[3])
 AC_INIT([unbound],m4_defn([VERSION_MAJOR]).m4_defn([VERSION_MINOR]).m4_defn([VERSION_MICRO]),[unbound-bugs@nlnetlabs.nl or https://github.com/NLnetLabs/unbound/issues],[unbound])
 AC_SUBST(UNBOUND_VERSION_MAJOR, [VERSION_MAJOR])
 AC_SUBST(UNBOUND_VERSION_MINOR, [VERSION_MINOR])
 AC_SUBST(UNBOUND_VERSION_MICRO, [VERSION_MICRO])
 
 LIBUNBOUND_CURRENT=9
-LIBUNBOUND_REVISION=25
+LIBUNBOUND_REVISION=26
 LIBUNBOUND_AGE=1
 # 1.0.0 had 0:12:0
 # 1.0.1 had 0:13:0
@@ -111,6 +111,7 @@ LIBUNBOUND_AGE=1
 # 1.19.0 had 9:23:1
 # 1.19.1 had 9:24:1
 # 1.19.2 had 9:25:1
+# 1.19.3 had 9:26:1
 
 #   Current  -- the number of the binary API that we're implementing
 #   Revision -- which iteration of the implementation of the binary
@@ -408,7 +409,7 @@ AC_CHECK_TOOL(STRIP, strip)
 ACX_LIBTOOL_C_ONLY
 
 # pkg-config is only needed for these options, do not require it otherwise
-if test "$enable_systemd" = "yes" -o "$with_pyunbound" = "yes" -o "$with_pythonmod" = "yes"; then
+if test "$enable_systemd" = "yes" -o "$enable_dnstap" = "yes" -o "$with_pyunbound" = "yes" -o "$with_pythonmod" = "yes"; then
 PKG_PROG_PKG_CONFIG
 fi
 
@@ -1527,13 +1528,17 @@ if test x_$enable_static_exe = x_yes; th
 	if test "$on_mingw" = yes; then
 		staticexe="-all-static"
 		# for static compile, include gdi32 and zlib here.
-		if echo $LIBS | grep 'lgdi32' >/dev/null; then
+		if echo "$LIBS" | grep 'lgdi32' >/dev/null; then
 			:
 		else
 			LIBS="$LIBS -lgdi32"
 		fi
 		AC_CHECK_LIB([z], [compress], [ LIBS="$LIBS -lz" ])
-		LIBS="$LIBS -l:libssp.a"
+		if echo "$LIBS" | grep -e "libssp.a" -e "lssp" >/dev/null; then
+			:
+		else
+			LIBS="$LIBS -l:libssp.a"
+		fi
 	fi
 fi
 
@@ -1550,7 +1555,11 @@ if test x_$enable_fully_static = x_yes; 
 			LIBS="$LIBS -lgdi32"
 		fi
 		AC_CHECK_LIB([z], [compress], [ LIBS="$LIBS -lz" ])
-		LIBS="$LIBS -l:libssp.a"
+		if echo "$LIBS" | grep -e "libssp.a" -e "lssp" >/dev/null; then
+			:
+		else
+			LIBS="$LIBS -l:libssp.a"
+		fi
 	fi
 fi
 
@@ -1570,7 +1579,11 @@ if test "$USE_WINSOCK" = 1; then
 #include <windows.h>
 	])
 	AC_CHECK_TOOL(WINDRES, windres)
-	LIBS="$LIBS -liphlpapi -lcrypt32"
+	if echo "$LIBS" | grep crypt32 >/dev/null; then
+		LIBS="$LIBS -liphlpapi"
+	else
+		LIBS="$LIBS -liphlpapi -lcrypt32"
+	fi
 	WINAPPS="unbound-service-install.exe unbound-service-remove.exe anchor-update.exe"
 	AC_SUBST(WINAPPS)
 	WIN_DAEMON_SRC="winrc/win_svc.c winrc/w_inst.c"
Index: daemon/remote.c
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/daemon/remote.c,v
diff -u -p -r1.37 remote.c
--- daemon/remote.c	12 Apr 2024 15:45:24 -0000	1.37
+++ daemon/remote.c	12 Apr 2024 15:50:24 -0000
@@ -553,7 +553,7 @@ ssl_print_text(RES* res, const char* tex
 static int
 ssl_print_vmsg(RES* ssl, const char* format, va_list args)
 {
-	char msg[1024];
+	char msg[65535];
 	vsnprintf(msg, sizeof(msg), format, args);
 	return ssl_print_text(ssl, msg);
 }
@@ -3181,10 +3181,10 @@ execute_cmd(struct daemon_remote* rc, RE
 		do_flush_bogus(ssl, worker);
 	} else if(cmdcmp(p, "flush_negative", 14)) {
 		do_flush_negative(ssl, worker);
-    } else if(cmdcmp(p, "rpz_enable", 10)) {
-        do_rpz_enable(ssl, worker, skipwhite(p+10));
-    } else if(cmdcmp(p, "rpz_disable", 11)) {
-        do_rpz_disable(ssl, worker, skipwhite(p+11));
+	} else if(cmdcmp(p, "rpz_enable", 10)) {
+		do_rpz_enable(ssl, worker, skipwhite(p+10));
+	} else if(cmdcmp(p, "rpz_disable", 11)) {
+		do_rpz_disable(ssl, worker, skipwhite(p+11));
 	} else {
 		(void)ssl_printf(ssl, "error unknown command '%s'\n", p);
 	}
Index: daemon/worker.c
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/daemon/worker.c,v
diff -u -p -r1.38 worker.c
--- daemon/worker.c	12 Apr 2024 15:45:24 -0000	1.38
+++ daemon/worker.c	12 Apr 2024 15:50:24 -0000
@@ -1151,7 +1151,7 @@ deny_refuse(struct comm_point* c, enum a
 		log_assert(sldns_buffer_limit(c->buffer) >= LDNS_HEADER_SIZE
 			&& LDNS_QDCOUNT(sldns_buffer_begin(c->buffer)) == 1);
 
-		sldns_buffer_skip(c->buffer, LDNS_HEADER_SIZE); /* skip header */
+		sldns_buffer_set_position(c->buffer, LDNS_HEADER_SIZE); /* skip header */
 
 		/* check additional section is present and that we respond with EDEs */
 		if(LDNS_ARCOUNT(sldns_buffer_begin(c->buffer)) != 1
@@ -1163,6 +1163,7 @@ deny_refuse(struct comm_point* c, enum a
 			LDNS_QR_SET(sldns_buffer_begin(c->buffer));
 			LDNS_RCODE_SET(sldns_buffer_begin(c->buffer),
 				LDNS_RCODE_REFUSED);
+			sldns_buffer_set_position(c->buffer, LDNS_HEADER_SIZE);
 			sldns_buffer_flip(c->buffer);
 			return 1;
 		}
@@ -1326,15 +1327,6 @@ deny_refuse_non_local(struct comm_point*
 		worker, repinfo, acladdr, ede, check_result);
 }
 
-/* Returns 1 if the ip rate limit check can happen before EDNS parsing,
- * else 0 */
-static int
-pre_edns_ip_ratelimit_check(enum acl_access acl)
-{
-	if(acl == acl_allow_cookie) return 0;
-	return 1;
-}
-
 /* Check if the query is blocked by source IP rate limiting.
  * Returns 1 if it passes the check, 0 otherwise. */
 static int
@@ -1463,7 +1455,7 @@ worker_handle_request(struct comm_point*
 	if(worker->dtenv.log_client_query_messages) {
 		log_addr(VERB_ALGO, "request from client", &repinfo->client_addr, repinfo->client_addrlen);
 		log_addr(VERB_ALGO, "to local addr", (void*)repinfo->c->socket->addr->ai_addr, repinfo->c->socket->addr->ai_addrlen);
-		dt_msg_send_client_query(&worker->dtenv, &repinfo->client_addr, (void*)repinfo->c->socket->addr->ai_addr, c->type, c->buffer,
+		dt_msg_send_client_query(&worker->dtenv, &repinfo->client_addr, (void*)repinfo->c->socket->addr->ai_addr, c->type, c->ssl, c->buffer,
 		((worker->env.cfg->sock_queue_timeout && timeval_isset(&c->recv_tv))?&c->recv_tv:NULL));
 	}
 #endif
@@ -1498,7 +1490,9 @@ worker_handle_request(struct comm_point*
 	}
 
 	worker->stats.num_queries++;
-	pre_edns_ip_ratelimit = pre_edns_ip_ratelimit_check(acl);
+	pre_edns_ip_ratelimit = !worker->env.cfg->do_answer_cookie
+		|| sldns_buffer_limit(c->buffer) < LDNS_HEADER_SIZE
+		|| LDNS_ARCOUNT(sldns_buffer_begin(c->buffer)) == 0;
 
 	/* If the IP rate limiting check needs extra EDNS information (e.g.,
 	 * DNS Cookies) postpone the check until after EDNS is parsed. */
@@ -1952,7 +1946,7 @@ send_reply_rc:
 	if(worker->dtenv.log_client_response_messages) {
 		log_addr(VERB_ALGO, "from local addr", (void*)repinfo->c->socket->addr->ai_addr, repinfo->c->socket->addr->ai_addrlen);
 		log_addr(VERB_ALGO, "response to client", &repinfo->client_addr, repinfo->client_addrlen);
-		dt_msg_send_client_response(&worker->dtenv, &repinfo->client_addr, (void*)repinfo->c->socket->addr->ai_addr, c->type, c->buffer);
+		dt_msg_send_client_response(&worker->dtenv, &repinfo->client_addr, (void*)repinfo->c->socket->addr->ai_addr, c->type, c->ssl, c->buffer);
 	}
 #endif
 	if(worker->env.cfg->log_replies)
@@ -1966,11 +1960,15 @@ send_reply_rc:
 			qinfo.qname = qinfo.local_alias->rrset->rk.dname;
 			log_reply_info(NO_VERBOSE, &qinfo,
 				&repinfo->client_addr, repinfo->client_addrlen,
-				tv, 1, c->buffer);
+				tv, 1, c->buffer,
+				(worker->env.cfg->log_destaddr?(void*)repinfo->c->socket->addr->ai_addr:NULL),
+				c->type);
 		} else {
 			log_reply_info(NO_VERBOSE, &qinfo,
 				&repinfo->client_addr, repinfo->client_addrlen,
-				tv, 1, c->buffer);
+				tv, 1, c->buffer,
+				(worker->env.cfg->log_destaddr?(void*)repinfo->c->socket->addr->ai_addr:NULL),
+				c->type);
 		}
 	}
 #ifdef USE_DNSCRYPT
Index: dnstap/dnstap.c
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/dnstap/dnstap.c,v
diff -u -p -r1.10 dnstap.c
--- dnstap/dnstap.c	5 Sep 2023 11:12:10 -0000	1.10
+++ dnstap/dnstap.c	12 Apr 2024 15:50:24 -0000
@@ -305,6 +305,7 @@ dt_msg_fill_net(struct dt_msg *dm,
 		struct sockaddr_storage *qs,
 		struct sockaddr_storage *rs,
 		enum comm_point_type cptype,
+		void *cpssl,
 		ProtobufCBinaryData *qaddr, protobuf_c_boolean *has_qaddr,
 		uint32_t *qport, protobuf_c_boolean *has_qport,
 		ProtobufCBinaryData *raddr, protobuf_c_boolean *has_raddr,
@@ -371,13 +372,26 @@ dt_msg_fill_net(struct dt_msg *dm,
                 *has_rport = 1;
         }
 
-	log_assert(cptype == comm_udp || cptype == comm_tcp);
 	if (cptype == comm_udp) {
 		/* socket_protocol */
 		dm->m.socket_protocol = DNSTAP__SOCKET_PROTOCOL__UDP;
 		dm->m.has_socket_protocol = 1;
 	} else if (cptype == comm_tcp) {
+		if (cpssl == NULL) {
+			/* socket_protocol */
+			dm->m.socket_protocol = DNSTAP__SOCKET_PROTOCOL__TCP;
+			dm->m.has_socket_protocol = 1;
+		} else {
+			/* socket_protocol */
+			dm->m.socket_protocol = DNSTAP__SOCKET_PROTOCOL__DOT;
+			dm->m.has_socket_protocol = 1;
+		}
+	} else if (cptype == comm_http) {
 		/* socket_protocol */
+		dm->m.socket_protocol = DNSTAP__SOCKET_PROTOCOL__DOH;
+		dm->m.has_socket_protocol = 1;
+	} else {
+		/* other socket protocol */
 		dm->m.socket_protocol = DNSTAP__SOCKET_PROTOCOL__TCP;
 		dm->m.has_socket_protocol = 1;
 	}
@@ -388,6 +402,7 @@ dt_msg_send_client_query(struct dt_env *
 			 struct sockaddr_storage *qsock,
 			 struct sockaddr_storage *rsock,
 			 enum comm_point_type cptype,
+			 void *cpssl,
 			 sldns_buffer *qmsg,
 			 struct timeval* tstamp)
 {
@@ -410,8 +425,7 @@ dt_msg_send_client_query(struct dt_env *
 	dt_fill_buffer(qmsg, &dm.m.query_message, &dm.m.has_query_message);
 
 	/* socket_family, socket_protocol, query_address, query_port, response_address, response_port */
-	log_assert(cptype == comm_udp || cptype == comm_tcp);
-	dt_msg_fill_net(&dm, qsock, rsock, cptype,
+	dt_msg_fill_net(&dm, qsock, rsock, cptype, cpssl,
 			&dm.m.query_address, &dm.m.has_query_address,
 			&dm.m.query_port, &dm.m.has_query_port,
 			&dm.m.response_address, &dm.m.has_response_address,
@@ -427,6 +441,7 @@ dt_msg_send_client_response(struct dt_en
 			    struct sockaddr_storage *qsock,
 			    struct sockaddr_storage *rsock,
 			    enum comm_point_type cptype,
+			    void *cpssl,
 			    sldns_buffer *rmsg)
 {
 	struct dt_msg dm;
@@ -446,8 +461,7 @@ dt_msg_send_client_response(struct dt_en
 	dt_fill_buffer(rmsg, &dm.m.response_message, &dm.m.has_response_message);
 
 	/* socket_family, socket_protocol, query_address, query_port, response_address, response_port */
-	log_assert(cptype == comm_udp || cptype == comm_tcp);
-	dt_msg_fill_net(&dm, qsock, rsock, cptype,
+	dt_msg_fill_net(&dm, qsock, rsock, cptype, cpssl,
 			&dm.m.query_address, &dm.m.has_query_address,
 			&dm.m.query_port, &dm.m.has_query_port,
                         &dm.m.response_address, &dm.m.has_response_address,
@@ -462,6 +476,7 @@ dt_msg_send_outside_query(struct dt_env 
 			  struct sockaddr_storage *rsock,
 			  struct sockaddr_storage *qsock,
 			  enum comm_point_type cptype,
+			  void *cpssl,
 			  uint8_t *zone, size_t zone_len,
 			  sldns_buffer *qmsg)
 {
@@ -497,8 +512,7 @@ dt_msg_send_outside_query(struct dt_env 
 	dt_fill_buffer(qmsg, &dm.m.query_message, &dm.m.has_query_message);
 
 	/* socket_family, socket_protocol, response_address, response_port, query_address, query_port */
-	log_assert(cptype == comm_udp || cptype == comm_tcp);
-	dt_msg_fill_net(&dm, rsock, qsock, cptype,
+	dt_msg_fill_net(&dm, rsock, qsock, cptype, cpssl,
 			&dm.m.response_address, &dm.m.has_response_address,
 			&dm.m.response_port, &dm.m.has_response_port,
 			&dm.m.query_address, &dm.m.has_query_address,
@@ -513,6 +527,7 @@ dt_msg_send_outside_response(struct dt_e
 	struct sockaddr_storage *rsock,
 	struct sockaddr_storage *qsock,
 	enum comm_point_type cptype,
+	void *cpssl,
 	uint8_t *zone, size_t zone_len,
 	uint8_t *qbuf, size_t qbuf_len,
 	const struct timeval *qtime,
@@ -556,8 +571,7 @@ dt_msg_send_outside_response(struct dt_e
 	dt_fill_buffer(rmsg, &dm.m.response_message, &dm.m.has_response_message);
 
 	/* socket_family, socket_protocol, response_address, response_port, query_address, query_port */
-	log_assert(cptype == comm_udp || cptype == comm_tcp);
-	dt_msg_fill_net(&dm, rsock, qsock, cptype,
+	dt_msg_fill_net(&dm, rsock, qsock, cptype, cpssl,
 			&dm.m.response_address, &dm.m.has_response_address,
 			&dm.m.response_port, &dm.m.has_response_port,
 			&dm.m.query_address, &dm.m.has_query_address,
Index: dnstap/dnstap.h
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/dnstap/dnstap.h,v
diff -u -p -r1.1.1.5 dnstap.h
--- dnstap/dnstap.h	5 Sep 2023 11:07:49 -0000	1.1.1.5
+++ dnstap/dnstap.h	12 Apr 2024 15:50:24 -0000
@@ -133,6 +133,7 @@ dt_msg_send_client_query(struct dt_env *
 			 struct sockaddr_storage *qsock,
 			 struct sockaddr_storage *rsock,
 			 enum comm_point_type cptype,
+			 void *cpssl,
 			 struct sldns_buffer *qmsg,
 			 struct timeval* tstamp);
 
@@ -149,6 +150,7 @@ dt_msg_send_client_response(struct dt_en
 			    struct sockaddr_storage *qsock,
 			    struct sockaddr_storage *rsock,
 			    enum comm_point_type cptype,
+			    void *cpssl,
 			    struct sldns_buffer *rmsg);
 
 /**
@@ -168,6 +170,7 @@ dt_msg_send_outside_query(struct dt_env 
 			  struct sockaddr_storage *rsock,
 			  struct sockaddr_storage *qsock,
 			  enum comm_point_type cptype,
+			  void *cpssl,
 			  uint8_t *zone, size_t zone_len,
 			  struct sldns_buffer *qmsg);
 
@@ -192,6 +195,7 @@ dt_msg_send_outside_response(struct dt_e
 			     struct sockaddr_storage *rsock,
 			     struct sockaddr_storage *qsock,
 			     enum comm_point_type cptype,
+			     void *cpssl,
 			     uint8_t *zone, size_t zone_len,
 			     uint8_t *qbuf, size_t qbuf_len,
 			     const struct timeval *qtime,
Index: dnstap/dnstap.m4
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/dnstap/dnstap.m4,v
diff -u -p -r1.1.1.4 dnstap.m4
--- dnstap/dnstap.m4	12 Apr 2024 15:44:27 -0000	1.1.1.4
+++ dnstap/dnstap.m4	12 Apr 2024 15:50:24 -0000
@@ -5,45 +5,76 @@
 # Check for required dnstap libraries and add dnstap configure args.
 AC_DEFUN([dt_DNSTAP],
 [
-  AC_ARG_ENABLE([dnstap],
-    AS_HELP_STRING([--enable-dnstap],
-                   [Enable dnstap support (requires protobuf-c)]),
-    [opt_dnstap=$enableval], [opt_dnstap=no])
+    AC_ARG_ENABLE([dnstap],
+        AS_HELP_STRING([--enable-dnstap],
+            [Enable dnstap support (requires protobuf-c)]),
+        [opt_dnstap=$enableval],
+        [opt_dnstap=no])
 
-  AC_ARG_WITH([dnstap-socket-path],
-    AS_HELP_STRING([--with-dnstap-socket-path=pathname],
-                   [set default dnstap socket path]),
-    [opt_dnstap_socket_path=$withval], [opt_dnstap_socket_path="$1"])
+    AC_ARG_WITH([dnstap-socket-path],
+        AS_HELP_STRING([--with-dnstap-socket-path=pathname],
+            [set default dnstap socket path]),
+        [opt_dnstap_socket_path=$withval],
+        [opt_dnstap_socket_path="$1"])
 
-  if test "x$opt_dnstap" != "xno"; then
-    AC_PATH_PROG([PROTOC_C], [protoc-c])
-    if test -z "$PROTOC_C"; then
-      AC_MSG_ERROR([The protoc-c program was not found. Please install protobuf-c!])
+    if test "x$opt_dnstap" != "xno"; then
+        AC_PATH_PROG([PROTOC_C], [protoc-c])
+        if test -z "$PROTOC_C"; then
+          AC_MSG_ERROR([The protoc-c program was not found. Please install protobuf-c!])
+        fi
+        AC_ARG_WITH([protobuf-c],
+            AS_HELP_STRING([--with-protobuf-c=path], [Path where protobuf-c is installed, for dnstap]),
+            [
+                # workaround for protobuf-c includes at old dir before protobuf-c-1.0.0
+                if test -f $withval/include/google/protobuf-c/protobuf-c.h; then
+                    CFLAGS="$CFLAGS -I$withval/include/google"
+                else
+                    CFLAGS="$CFLAGS -I$withval/include"
+                fi
+                LDFLAGS="$LDFLAGS -L$withval/lib"
+            ],
+            [
+                ifdef([PKG_CHECK_MODULES],
+                    [
+                        PKG_CHECK_MODULES([PROTOBUFC], [libprotobuf-c],
+                            [
+                                CFLAGS="$CFLAGS $PROTOBUFC_CFLAGS"
+                                LIBS="$LIBS $PROTOBUFC_LIBS"
+                            ],
+                            [
+                                # pkg-config failed; try falling back to known values
+                                # workaround for protobuf-c includes at old dir before protobuf-c-1.0.0
+                                if test -f /usr/include/google/protobuf-c/protobuf-c.h; then
+                                    CFLAGS="$CFLAGS -I/usr/include/google"
+                                else
+                                    if test -f /usr/local/include/google/protobuf-c/protobuf-c.h; then
+                                        CFLAGS="$CFLAGS -I/usr/local/include/google"
+                                        LDFLAGS="$LDFLAGS -L/usr/local/lib"
+                                    else
+                                        AC_MSG_ERROR([The protobuf-c package was not found with pkg-config. Please install protobuf-c!])
+                                    fi
+                                fi
+                            ]
+                        )
+                    ],
+                    [
+                        # workaround for protobuf-c includes at old dir before protobuf-c-1.0.0
+                        if test -f /usr/include/google/protobuf-c/protobuf-c.h; then
+                            CFLAGS="$CFLAGS -I/usr/include/google"
+                        else
+                            if test -f /usr/local/include/google/protobuf-c/protobuf-c.h; then
+                                CFLAGS="$CFLAGS -I/usr/local/include/google"
+                                LDFLAGS="$LDFLAGS -L/usr/local/lib"
+                            fi
+                        fi
+                    ]
+                )
+            ]
+        )
+        AC_SEARCH_LIBS([protobuf_c_message_pack], [protobuf-c], [],
+            AC_MSG_ERROR([The protobuf-c library was not found. Please install the development libraries for protobuf-c!]))
+        $2
+    else
+        $3
     fi
-    AC_ARG_WITH([protobuf-c], AS_HELP_STRING([--with-protobuf-c=path],
-    	[Path where protobuf-c is installed, for dnstap]), [
-	  # workaround for protobuf-c includes at old dir before protobuf-c-1.0.0
-	  if test -f $withval/include/google/protobuf-c/protobuf-c.h; then
-	    CFLAGS="$CFLAGS -I$withval/include/google"
-	  else
-	    CFLAGS="$CFLAGS -I$withval/include"
-	  fi
-	  LDFLAGS="$LDFLAGS -L$withval/lib"
-	], [
-	  # workaround for protobuf-c includes at old dir before protobuf-c-1.0.0
-	  if test -f /usr/include/google/protobuf-c/protobuf-c.h; then
-	    CFLAGS="$CFLAGS -I/usr/include/google"
-	  else
-	    if test -f /usr/local/include/google/protobuf-c/protobuf-c.h; then
-	      CFLAGS="$CFLAGS -I/usr/local/include/google"
-	      LDFLAGS="$LDFLAGS -L/usr/local/lib"
-	    fi
-	  fi
-    ])
-    AC_SEARCH_LIBS([protobuf_c_message_pack], [protobuf-c], [],
-      AC_MSG_ERROR([The protobuf-c library was not found. Please install the development libraries for protobuf-c!]))
-    $2
-  else
-    $3
-  fi
 ])
Index: dnstap/dnstap.proto
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/dnstap/dnstap.proto,v
diff -u -p -r1.3 dnstap.proto
--- dnstap/dnstap.proto	29 Mar 2018 19:44:35 -0000	1.3
+++ dnstap/dnstap.proto	12 Apr 2024 15:50:24 -0000
@@ -13,8 +13,8 @@
 // with this file. If not, see:
 //
 // <http://creativecommons.org/publicdomain/zero/1.0/>.
-syntax = "proto2";
 
+syntax = "proto2";
 package dnstap;
 
 // "Dnstap": this is the top-level dnstap type, which is a "union" type that
@@ -56,11 +56,60 @@ enum SocketFamily {
     INET6 = 2;  // IPv6 (RFC 2460)
 }
 
-// SocketProtocol: the transport protocol of a socket. This specifies how to
-// interpret "transport port" fields.
+// SocketProtocol: the protocol used to transport a DNS message.
 enum SocketProtocol {
-    UDP = 1;    // User Datagram Protocol (RFC 768)
-    TCP = 2;    // Transmission Control Protocol (RFC 793)
+    UDP = 1;         // DNS over UDP transport (RFC 1035 section 4.2.1)
+    TCP = 2;         // DNS over TCP transport (RFC 1035 section 4.2.2)
+    DOT = 3;         // DNS over TLS (RFC 7858)
+    DOH = 4;         // DNS over HTTPS (RFC 8484)
+    DNSCryptUDP = 5; // DNSCrypt over UDP (https://dnscrypt.info/protocol)
+    DNSCryptTCP = 6; // DNSCrypt over TCP (https://dnscrypt.info/protocol)
+    DOQ = 7;         // DNS over QUIC (RFC 9250)
+}
+
+// Policy: information about any name server operator policy
+// applied to the processing of a DNS message.
+message Policy {
+
+    // Match: what aspect of the message or message exchange
+    // triggered the application of the Policy.
+    enum Match {
+        QNAME = 1;       // Name in question section of query
+        CLIENT_IP = 2;   // Client IP address
+        RESPONSE_IP = 3; // Address in A/AAAA RRSet
+        NS_NAME = 4;     // Authoritative name server, by name
+        NS_IP = 5;       // Authoritative name server, by IP address
+    }
+
+    // The Action taken to implement the Policy.
+    enum Action {
+        NXDOMAIN = 1;   // Respond with NXDOMAIN
+        NODATA = 2;     // Respond with empty answer section
+        PASS = 3;       // Do not alter the response (passthrough)
+        DROP = 4;       // Do not respond.
+        TRUNCATE = 5;   // Truncate UDP response, forcing TCP retry
+        LOCAL_DATA = 6; // Respond with local data from policy
+    }
+
+    // type: the type of policy applied, e.g. "RPZ" for a
+    // policy from a Response Policy Zone.
+    optional string type = 1;
+
+    // rule: the rule matched by the message.
+    //
+    // In a RPZ context, this is the owner name of the rule in
+    // the Reponse Policy Zone in wire format.
+    optional bytes rule = 2;
+
+    // action: the policy action taken in response to the
+    // rule match.
+    optional Action action = 3;
+
+    // match: the feature of the message exchange which matched the rule.
+    optional Match match = 4;
+
+    // The matched value. Format depends on the matched feature .
+    optional bytes value = 5;
 }
 
 // Message: a wire-format (RFC 1035 section 4) DNS message and associated
@@ -158,6 +207,24 @@ message Message {
         // STUB_RESPONSE is a DNS response message sent from a DNS server to a
         // stub resolver, from the perspective of the stub resolver.
         STUB_RESPONSE = 10;
+
+        // TOOL_QUERY is a DNS query message sent from a DNS software tool to a
+        // DNS server, from the perspective of the tool.
+        TOOL_QUERY = 11;
+
+        // TOOL_RESPONSE is a DNS response message received by a DNS software
+        // tool from a DNS server, from the perspective of the tool.
+        TOOL_RESPONSE = 12;
+
+        // UPDATE_QUERY is a Dynamic DNS Update request (RFC 2136) received
+        // by an authoritative name server, from the perspective of the
+        // authoritative name server.
+        UPDATE_QUERY = 13;
+
+        // UPDATE_RESPONSE is a Dynamic DNS Update response (RFC 2136) sent
+        // from an authoritative name server, from the perspective of the
+        // authoritative name server.
+        UPDATE_RESPONSE = 14;
     }
 
     // One of the Type values described above.
@@ -215,6 +282,9 @@ message Message {
 
     // The responder's original wire-format DNS response message, verbatim.
     optional bytes              response_message = 14;
+
+    // Operator policy applied to the processing of this message, if any.
+    optional Policy             policy = 15;
 }
 
 // All fields except for 'type' in the Message schema are optional.
@@ -236,7 +306,6 @@ message Message {
 
 // RESOLVER_QUERY:
 //      socket_family, socket_protocol
-//      query_name, query_type, query_class
 //      query_message
 //      query_time_sec, query_time_nsec
 //      query_zone
@@ -244,7 +313,6 @@ message Message {
 
 // RESOLVER_RESPONSE:
 //      socket_family, socket_protocol
-//      query_name, query_type, query_class
 //      query_time_sec, query_time_nsec
 //      query_zone
 //      response_address, response_port
Index: doc/README
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/doc/README,v
diff -u -p -r1.36 README
--- doc/README	12 Apr 2024 15:45:24 -0000	1.36
+++ doc/README	12 Apr 2024 15:50:24 -0000
@@ -1,4 +1,4 @@
-README for Unbound 1.19.2
+README for Unbound 1.19.3
 Copyright 2007 NLnet Labs
 http://unbound.net
 
@@ -19,11 +19,10 @@ The DNSTAP code has BSD license in dnsta
 * Make and install: ./configure; make; make install
   * --with-libevent=/path/to/libevent
   	Can be set to either the system install or the build directory.
-	--with-libevent=no (default) gives a builtin alternative 
-	implementation. libevent is useful when having many (thousands) 
-	of outgoing ports. This improves randomization and spoof 
-	resistance. For the default of 16 ports the builtin alternative 
-	works well and is a little faster.
+	--with-libevent=no gives a builtin alternative implementation.
+	Libevent is enabled by default, it is useful when having many
+	(thousands) of outgoing ports. This improves randomization and spoof
+	resistance. It also allows a higher number of outgoing queries.
   * --with-libexpat=/path/to/libexpat
   	Can be set to the install directory of libexpat.
   * --without-pthreads 
Index: doc/example.conf.in
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/doc/example.conf.in,v
diff -u -p -r1.41 example.conf.in
--- doc/example.conf.in	12 Apr 2024 15:45:24 -0000	1.41
+++ doc/example.conf.in	12 Apr 2024 15:50:24 -0000
@@ -1,7 +1,7 @@
 #
 # Example configuration file.
 #
-# See unbound.conf(5) man page, version 1.19.2.
+# See unbound.conf(5) man page, version 1.19.3.
 #
 # this is a comment.
 
@@ -303,6 +303,7 @@ server:
 	# Choose deny (drop message), refuse (polite error reply),
 	# allow (recursive ok), allow_setrd (recursive ok, rd bit is forced on),
 	# allow_snoop (recursive and nonrecursive ok)
+	# allow_cookie (allow UDP with valid cookie or stateful transport)
 	# deny_non_local (drop queries unless can be answered from local-data)
 	# refuse_non_local (like deny_non_local but polite error reply).
 	# access-control: 127.0.0.0/8 allow
@@ -441,6 +442,9 @@ server:
 	# filtering log-queries and log-replies from the log.
 	# log-tag-queryreply: no
 
+	# log with destination address, port and type for log-replies.
+	# log-destaddr: no
+
 	# log the local-zone actions, like local-zone type inform is enabled
 	# also for the other local zone types.
 	# log-local-actions: no
@@ -983,6 +987,13 @@ server:
 	# if 0(default) it is disabled, otherwise states qps allowed per ip address
 	# ip-ratelimit: 0
 
+	# global query ratelimit for all ip addresses with a valid DNS Cookie.
+	# feature is experimental.
+	# if 0(default) it is disabled, otherwise states qps allowed per ip address
+	# useful in combination with 'allow_cookie'.
+	# If used, suggested to be higher than ip-ratelimit, tenfold.
+	# ip-ratelimit-cookie: 0
+
 	# ip ratelimits are tracked in a cache, size in bytes of cache (or k,m).
 	# ip-ratelimit-size: 4m
 	# ip ratelimit cache slabs, reduces lock contention if equal to cpucount.
@@ -1004,6 +1015,14 @@ server:
 	# the number of servers that will be used in the fast server selection.
 	# fast-server-num: 3
 
+	# reply to requests containing DNS Cookies as specified in RFC 7873 and RFC 9018.
+	# answer-cookie: no
+
+	# secret for DNS Cookie generation.
+	# useful for anycast deployments.
+	# example value "000102030405060708090a0b0c0d0e0f".
+	# cookie-secret: <128 bit random hex string>
+
 	# Enable to attach Extended DNS Error codes (RFC8914) to responses.
 	# ede: no
 
@@ -1150,7 +1169,7 @@ remote-control:
 # sources of notifies.
 # auth-zone:
 #	name: "."
-#	primary: 199.9.14.201         # b.root-servers.net
+#	primary: 170.247.170.2        # b.root-servers.net
 #	primary: 192.33.4.12          # c.root-servers.net
 #	primary: 199.7.91.13          # d.root-servers.net
 #	primary: 192.5.5.241          # f.root-servers.net
@@ -1158,7 +1177,7 @@ remote-control:
 #	primary: 193.0.14.129         # k.root-servers.net
 #	primary: 192.0.47.132         # xfr.cjr.dns.icann.org
 #	primary: 192.0.32.132         # xfr.lax.dns.icann.org
-#	primary: 2001:500:200::b      # b.root-servers.net
+#	primary: 2801:1b8:10::b       # b.root-servers.net
 #	primary: 2001:500:2::c        # c.root-servers.net
 #	primary: 2001:500:2d::d       # d.root-servers.net
 #	primary: 2001:500:2f::f       # f.root-servers.net
Index: doc/libunbound.3.in
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/doc/libunbound.3.in,v
diff -u -p -r1.39 libunbound.3.in
--- doc/libunbound.3.in	12 Apr 2024 15:45:24 -0000	1.39
+++ doc/libunbound.3.in	12 Apr 2024 15:50:24 -0000
@@ -1,4 +1,4 @@
-.TH "libunbound" "3" "Mar  7, 2024" "NLnet Labs" "unbound 1.19.2"
+.TH "libunbound" "3" "Mar 14, 2024" "NLnet Labs" "unbound 1.19.3"
 .\"
 .\" 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.19.2 functions.
+\- Unbound DNS validating resolver 1.19.3 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
diff -u -p -r1.38 unbound-anchor.8.in
--- doc/unbound-anchor.8.in	12 Apr 2024 15:45:24 -0000	1.38
+++ doc/unbound-anchor.8.in	12 Apr 2024 15:50:24 -0000
@@ -1,4 +1,4 @@
-.TH "unbound-anchor" "8" "Mar  7, 2024" "NLnet Labs" "unbound 1.19.2"
+.TH "unbound-anchor" "8" "Mar 14, 2024" "NLnet Labs" "unbound 1.19.3"
 .\"
 .\" 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
diff -u -p -r1.38 unbound-checkconf.8.in
--- doc/unbound-checkconf.8.in	12 Apr 2024 15:45:24 -0000	1.38
+++ doc/unbound-checkconf.8.in	12 Apr 2024 15:50:24 -0000
@@ -1,4 +1,4 @@
-.TH "unbound-checkconf" "8" "Mar  7, 2024" "NLnet Labs" "unbound 1.19.2"
+.TH "unbound-checkconf" "8" "Mar 14, 2024" "NLnet Labs" "unbound 1.19.3"
 .\"
 .\" 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
diff -u -p -r1.40 unbound-control.8.in
--- doc/unbound-control.8.in	12 Apr 2024 15:45:24 -0000	1.40
+++ doc/unbound-control.8.in	12 Apr 2024 15:50:24 -0000
@@ -1,4 +1,4 @@
-.TH "unbound-control" "8" "Mar  7, 2024" "NLnet Labs" "unbound 1.19.2"
+.TH "unbound-control" "8" "Mar 14, 2024" "NLnet Labs" "unbound 1.19.3"
 .\"
 .\" 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
diff -u -p -r1.40 unbound-host.1.in
--- doc/unbound-host.1.in	12 Apr 2024 15:45:24 -0000	1.40
+++ doc/unbound-host.1.in	12 Apr 2024 15:50:24 -0000
@@ -1,4 +1,4 @@
-.TH "unbound\-host" "1" "Mar  7, 2024" "NLnet Labs" "unbound 1.19.2"
+.TH "unbound\-host" "1" "Mar 14, 2024" "NLnet Labs" "unbound 1.19.3"
 .\"
 .\" unbound-host.1 -- unbound DNS lookup utility
 .\"
Index: doc/unbound.8.in
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/doc/unbound.8.in,v
diff -u -p -r1.41 unbound.8.in
--- doc/unbound.8.in	12 Apr 2024 15:45:24 -0000	1.41
+++ doc/unbound.8.in	12 Apr 2024 15:50:24 -0000
@@ -1,4 +1,4 @@
-.TH "unbound" "8" "Mar  7, 2024" "NLnet Labs" "unbound 1.19.2"
+.TH "unbound" "8" "Mar 14, 2024" "NLnet Labs" "unbound 1.19.3"
 .\"
 .\" unbound.8 -- unbound manual
 .\"
@@ -9,7 +9,7 @@
 .\"
 .SH "NAME"
 .B unbound
-\- Unbound DNS validating resolver 1.19.2.
+\- Unbound DNS validating resolver 1.19.3.
 .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
diff -u -p -r1.45 unbound.conf.5.in
--- doc/unbound.conf.5.in	12 Apr 2024 15:45:24 -0000	1.45
+++ doc/unbound.conf.5.in	12 Apr 2024 15:50:24 -0000
@@ -1,4 +1,4 @@
-.TH "unbound.conf" "5" "Mar  7, 2024" "NLnet Labs" "unbound 1.19.2"
+.TH "unbound.conf" "5" "Mar 14, 2024" "NLnet Labs" "unbound 1.19.3"
 .\"
 .\" unbound.conf.5 -- unbound.conf manual
 .\"
@@ -663,6 +663,12 @@ When at the limit, further connections a
 This option is experimental at this time.
 .TP
 .B access\-control: \fI<IP netblock> <action>
+Specify treatment of incoming queries from their originating IP address.
+Queries can be allowed to have access to this server that gives DNS
+answers, or refused, with other actions possible. The IP address range
+can be specified as a netblock, it is possible to give the statement
+several times in order to specify the treatment of different netblocks.
+.IP
 The netblock is given as an IP4 or IP6 address with /size appended for a
 classless network block. The action can be \fIdeny\fR, \fIrefuse\fR,
 \fIallow\fR, \fIallow_setrd\fR, \fIallow_snoop\fR, \fIallow_cookie\fR,
@@ -702,7 +708,7 @@ the cache contents (for malicious acts).
 also be a valuable debugging tool (when you want to examine the cache
 contents). In that case use \fIallow_snoop\fR for your administration host.
 .IP
-The \fIallow_cookie\fR action allows access to UDP queries that contain a
+The \fIallow_cookie\fR action allows access only to UDP queries that contain a
 valid DNS Cookie as specified in RFC 7873 and RFC 9018, when the
 \fBanswer\-cookie\fR option is enabled.
 UDP queries containing only a DNS Client Cookie and no Server Cookie, or an
@@ -711,10 +717,8 @@ generated DNS Cookie, allowing clients t
 The \fIallow_cookie\fR action will also accept requests over stateful
 transports, regardless of the presence of an DNS Cookie and regardless of the
 \fBanswer\-cookie\fR setting.
-If \fBip\-ratelimit\fR is used, clients with a valid DNS Cookie will bypass the
-ratelimit.
-If a ratelimit for such clients is still needed, \fBip\-ratelimit\-cookie\fR
-can be used instead.
+UDP queries without a DNS Cookie receive REFUSED responses with the TC flag set,
+that may trigger fall back to TCP for those clients.
 .IP
 By default only localhost is \fIallow\fRed, the rest is \fIrefuse\fRd.
 The default is \fIrefuse\fRd, because that is protocol\-friendly. The DNS
@@ -877,6 +881,11 @@ Prints the word 'query' and 'reply' with
 This makes filtering logs easier.  The default is off (for backwards
 compatibility).
 .TP
+.B log\-destaddr: \fI<yes or no>
+Prints the destination address, port and type in the log\-replies output.
+This disambiguates what type of traffic, eg. udp or tcp, and to what local
+port the traffic was sent to.
+.TP
 .B log\-local\-actions: \fI<yes or no>
 Print log lines to inform about local zone actions.  These lines are like the
 local\-zone type inform prints out, but they are also printed for the other
@@ -1794,6 +1803,9 @@ The ratelimit is in queries per second t
 completely dropped and will not receive a reply, SERVFAIL or otherwise.
 IP ratelimiting happens before looking in the cache. This may be useful for
 mitigating amplification attacks.
+Clients with a valid DNS Cookie will bypass the ratelimit.
+If a ratelimit for such clients is still needed, \fBip\-ratelimit\-cookie\fR
+can be used instead.
 Default is 0 (disabled).
 .TP 5
 .B ip\-ratelimit\-cookie: \fI<number or 0>
Index: iterator/iter_fwd.c
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/iterator/iter_fwd.c,v
diff -u -p -r1.7 iter_fwd.c
--- iterator/iter_fwd.c	23 Feb 2022 12:04:05 -0000	1.7
+++ iterator/iter_fwd.c	12 Apr 2024 15:50:24 -0000
@@ -523,4 +523,3 @@ forwards_delete_stub_hole(struct iter_fo
 	fwd_zone_free(z);
 	fwd_init_parents(fwd);
 }
-
Index: iterator/iter_hints.c
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/iterator/iter_hints.c,v
diff -u -p -r1.16 iter_hints.c
--- iterator/iter_hints.c	20 Oct 2022 08:26:14 -0000	1.16
+++ iterator/iter_hints.c	12 Apr 2024 15:50:24 -0000
@@ -129,7 +129,7 @@ compile_time_root_prime(int do_ip4, int 
 	dp->has_parent_side_NS = 1;
       if(do_ip4) {
 	if(!ah(dp, "A.ROOT-SERVERS.NET.", "198.41.0.4"))	goto failed;
-	if(!ah(dp, "B.ROOT-SERVERS.NET.", "199.9.14.201")) goto failed;
+	if(!ah(dp, "B.ROOT-SERVERS.NET.", "170.247.170.2"))	goto failed;
 	if(!ah(dp, "C.ROOT-SERVERS.NET.", "192.33.4.12"))	goto failed;
 	if(!ah(dp, "D.ROOT-SERVERS.NET.", "199.7.91.13"))	goto failed;
 	if(!ah(dp, "E.ROOT-SERVERS.NET.", "192.203.230.10")) goto failed;
@@ -144,7 +144,7 @@ compile_time_root_prime(int do_ip4, int 
       }
       if(do_ip6) {
 	if(!ah(dp, "A.ROOT-SERVERS.NET.", "2001:503:ba3e::2:30")) goto failed;
-	if(!ah(dp, "B.ROOT-SERVERS.NET.", "2001:500:200::b")) goto failed;
+	if(!ah(dp, "B.ROOT-SERVERS.NET.", "2801:1b8:10::b")) goto failed;
 	if(!ah(dp, "C.ROOT-SERVERS.NET.", "2001:500:2::c")) goto failed;
 	if(!ah(dp, "D.ROOT-SERVERS.NET.", "2001:500:2d::d")) goto failed;
 	if(!ah(dp, "E.ROOT-SERVERS.NET.", "2001:500:a8::e")) goto failed;
@@ -560,4 +560,3 @@ hints_delete_stub(struct iter_hints* hin
 	hints_stub_free(z);
 	name_tree_init_parents(&hints->tree);
 }
-
Index: iterator/iter_scrub.c
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/iterator/iter_scrub.c,v
diff -u -p -r1.14 iter_scrub.c
--- iterator/iter_scrub.c	12 Apr 2024 15:45:24 -0000	1.14
+++ iterator/iter_scrub.c	12 Apr 2024 15:50:24 -0000
@@ -283,7 +283,8 @@ synth_cname_rrset(uint8_t** sname, size_
 		sizeof(uint32_t)+sizeof(uint16_t)+aliaslen);
 	if(!cn->rr_first->ttl_data)
 		return NULL;
-	sldns_write_uint32(cn->rr_first->ttl_data, 0); /* TTL = 0 */
+	memmove(cn->rr_first->ttl_data, rrset->rr_first->ttl_data,
+		sizeof(uint32_t)); /* RFC6672: synth CNAME TTL == DNAME TTL */
 	sldns_write_uint16(cn->rr_first->ttl_data+4, aliaslen);
 	memmove(cn->rr_first->ttl_data+6, alias, aliaslen);
 	cn->rr_first->size = sizeof(uint16_t)+aliaslen;
Index: iterator/iterator.c
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/iterator/iterator.c,v
diff -u -p -r1.35 iterator.c
--- iterator/iterator.c	12 Apr 2024 15:45:24 -0000	1.35
+++ iterator/iterator.c	12 Apr 2024 15:50:24 -0000
@@ -4151,10 +4151,10 @@ process_response(struct module_qstate* q
 			/* like packet got dropped */
 			goto handle_it;
 		}
-		if(!inplace_cb_edns_back_parsed_call(qstate->env, qstate)) {
-			log_err("unable to call edns_back_parsed callback");
-			goto handle_it;
-		}
+	}
+	if(!inplace_cb_edns_back_parsed_call(qstate->env, qstate)) {
+		log_err("unable to call edns_back_parsed callback");
+		goto handle_it;
 	}
 
 	/* remove CD-bit, we asked for in case we handle validation ourself */
Index: services/authzone.c
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/services/authzone.c,v
diff -u -p -r1.25 authzone.c
--- services/authzone.c	12 Apr 2024 15:45:24 -0000	1.25
+++ services/authzone.c	12 Apr 2024 15:50:24 -0000
@@ -2702,7 +2702,7 @@ create_synth_cname(uint8_t* qname, size_
 	if(!d)
 		return 0; /* out of memory */
 	(*cname)->entry.data = d;
-	d->ttl = 0; /* 0 for synthesized CNAME TTL */
+	d->ttl = dname->data->ttl; /* RFC6672: synth CNAME TTL == DNAME TTL */
 	d->count = 1;
 	d->rrsig_count = 0;
 	d->trust = rrset_trust_ans_noAA;
Index: services/localzone.c
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/services/localzone.c,v
diff -u -p -r1.20 localzone.c
--- services/localzone.c	5 Sep 2023 11:12:10 -0000	1.20
+++ services/localzone.c	12 Apr 2024 15:50:24 -0000
@@ -1532,7 +1532,7 @@ local_data_answer(struct local_zone* z, 
 			return 0; /* invalid cname */
 		if(dname_is_wild(ctarget)) {
 			/* synthesize cname target */
-			struct packed_rrset_data* d;
+			struct packed_rrset_data* d, *lr_d;
 			/* -3 for wildcard label and root label from qname */
 			size_t newtargetlen = qinfo->qname_len + ctargetlen - 3;
 
@@ -1560,8 +1560,10 @@ local_data_answer(struct local_zone* z, 
 				+ newtargetlen);
 			if(!d)
 				return 0; /* out of memory */
+			lr_d = (struct packed_rrset_data*)lr->rrset->entry.data;
 			qinfo->local_alias->rrset->entry.data = d;
-			d->ttl = 0; /* 0 for synthesized CNAME TTL */
+			d->ttl = lr_d->rr_ttl[0]; /* RFC6672-like behavior:
+					    synth CNAME TTL uses original TTL*/
 			d->count = 1;
 			d->rrsig_count = 0;
 			d->trust = rrset_trust_ans_noAA;
Index: services/mesh.c
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/services/mesh.c,v
diff -u -p -r1.27 mesh.c
--- services/mesh.c	12 Apr 2024 15:45:24 -0000	1.27
+++ services/mesh.c	12 Apr 2024 15:50:24 -0000
@@ -69,6 +69,12 @@
 #include "edns-subnet/subnetmod.h"
 #include "edns-subnet/edns-subnet.h"
 #endif
+#ifdef HAVE_SYS_TYPES_H
+#  include <sys/types.h>
+#endif
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
 
 /**
  * Compare two response-ip client info entries for the purpose of mesh state
@@ -1429,7 +1435,9 @@ mesh_send_reply(struct mesh_state* m, in
 	if(m->s.env->cfg->log_replies) {
 		log_reply_info(NO_VERBOSE, &m->s.qinfo,
 			&r->query_reply.client_addr,
-			r->query_reply.client_addrlen, duration, 0, r_buffer);
+			r->query_reply.client_addrlen, duration, 0, r_buffer,
+			(m->s.env->cfg->log_destaddr?(void*)r->query_reply.c->socket->addr->ai_addr:NULL),
+			r->query_reply.c->type);
 	}
 }
 
Index: services/outside_network.c
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/services/outside_network.c,v
diff -u -p -r1.29 outside_network.c
--- services/outside_network.c	12 Apr 2024 15:45:24 -0000	1.29
+++ services/outside_network.c	12 Apr 2024 15:50:24 -0000
@@ -1009,7 +1009,7 @@ use_free_buffer(struct outside_network* 
 			sldns_buffer tmp;
 			sldns_buffer_init_frm_data(&tmp, w->pkt, w->pkt_len);
 			dt_msg_send_outside_query(outnet->dtenv, &w->sq->addr,
-				&pend_tcp->pi->addr, comm_tcp, w->sq->zone,
+				&pend_tcp->pi->addr, comm_tcp, NULL, w->sq->zone,
 				w->sq->zonelen, &tmp);
 		}
 #endif
@@ -2237,7 +2237,7 @@ randomize_and_send_udp(struct pending* p
 		outnet->dtenv->log_forwarder_query_messages)) {
 			log_addr(VERB_ALGO, "from local addr", &pend->pc->pif->addr, pend->pc->pif->addrlen);
 			log_addr(VERB_ALGO, "request to upstream", &pend->addr, pend->addrlen);
-			dt_msg_send_outside_query(outnet->dtenv, &pend->addr, &pend->pc->pif->addr, comm_udp,
+			dt_msg_send_outside_query(outnet->dtenv, &pend->addr, &pend->pc->pif->addr, comm_udp, NULL,
 				pend->sq->zone, pend->sq->zonelen, packet);
 	}
 #endif
@@ -2517,7 +2517,7 @@ pending_tcp_query(struct serviced_query*
 			sldns_buffer tmp;
 			sldns_buffer_init_frm_data(&tmp, w->pkt, w->pkt_len);
 			dt_msg_send_outside_query(sq->outnet->dtenv, &sq->addr,
-				&pend->pi->addr, comm_tcp, sq->zone,
+				&pend->pi->addr, comm_tcp, NULL, sq->zone,
 				sq->zonelen, &tmp);
 		}
 #endif
@@ -2820,6 +2820,25 @@ serviced_perturb_qname(struct ub_randsta
 	}
 }
 
+static uint16_t
+serviced_query_udp_size(struct serviced_query* sq, enum serviced_query_status status) {
+	uint16_t udp_size;
+	if(status == serviced_query_UDP_EDNS_FRAG) {
+		if(addr_is_ip6(&sq->addr, sq->addrlen)) {
+			if(EDNS_FRAG_SIZE_IP6 < EDNS_ADVERTISED_SIZE)
+				udp_size = EDNS_FRAG_SIZE_IP6;
+			else	udp_size = EDNS_ADVERTISED_SIZE;
+		} else {
+			if(EDNS_FRAG_SIZE_IP4 < EDNS_ADVERTISED_SIZE)
+				udp_size = EDNS_FRAG_SIZE_IP4;
+			else	udp_size = EDNS_ADVERTISED_SIZE;
+		}
+	} else {
+		udp_size = EDNS_ADVERTISED_SIZE;
+	}
+	return udp_size;
+}
+
 /** put serviced query into a buffer */
 static void
 serviced_encode(struct serviced_query* sq, sldns_buffer* buff, int with_edns)
@@ -2843,19 +2862,7 @@ serviced_encode(struct serviced_query* s
 		edns.opt_list_in = NULL;
 		edns.opt_list_out = sq->opt_list;
 		edns.opt_list_inplace_cb_out = NULL;
-		if(sq->status == serviced_query_UDP_EDNS_FRAG) {
-			if(addr_is_ip6(&sq->addr, sq->addrlen)) {
-				if(EDNS_FRAG_SIZE_IP6 < EDNS_ADVERTISED_SIZE)
-					edns.udp_size = EDNS_FRAG_SIZE_IP6;
-				else	edns.udp_size = EDNS_ADVERTISED_SIZE;
-			} else {
-				if(EDNS_FRAG_SIZE_IP4 < EDNS_ADVERTISED_SIZE)
-					edns.udp_size = EDNS_FRAG_SIZE_IP4;
-				else	edns.udp_size = EDNS_ADVERTISED_SIZE;
-			}
-		} else {
-			edns.udp_size = EDNS_ADVERTISED_SIZE;
-		}
+		edns.udp_size = serviced_query_udp_size(sq, sq->status);
 		edns.bits = 0;
 		if(sq->dnssec & EDNS_DO)
 			edns.bits = EDNS_DO;
@@ -3083,7 +3090,7 @@ serviced_tcp_callback(struct comm_point*
 		log_addr(VERB_ALGO, "response from upstream", &sq->addr, sq->addrlen);
 		log_addr(VERB_ALGO, "to local addr", &pi->addr, pi->addrlen);
 		dt_msg_send_outside_response(sq->outnet->dtenv, &sq->addr,
-			&pi->addr, c->type, sq->zone, sq->zonelen, sq->qbuf,
+			&pi->addr, c->type, c->ssl, sq->zone, sq->zonelen, sq->qbuf,
 			sq->qbuflen, &sq->last_sent_time, sq->outnet->now_tv,
 			c->buffer);
 	}
@@ -3252,7 +3259,8 @@ serviced_udp_callback(struct comm_point*
 
 	sq->pending = NULL; /* removed after callback */
 	if(error == NETEVENT_TIMEOUT) {
-		if(sq->status == serviced_query_UDP_EDNS && sq->last_rtt < 5000) {
+		if(sq->status == serviced_query_UDP_EDNS && sq->last_rtt < 5000 &&
+		   (serviced_query_udp_size(sq, serviced_query_UDP_EDNS_FRAG) < serviced_query_udp_size(sq, serviced_query_UDP_EDNS))) {
 			/* fallback to 1480/1280 */
 			sq->status = serviced_query_UDP_EDNS_FRAG;
 			log_name_addr(VERB_ALGO, "try edns1xx0", sq->qbuf+10,
@@ -3296,7 +3304,7 @@ serviced_udp_callback(struct comm_point*
 		log_addr(VERB_ALGO, "to local addr", &p->pc->pif->addr,
 			p->pc->pif->addrlen);
 		dt_msg_send_outside_response(outnet->dtenv, &sq->addr,
-			&p->pc->pif->addr, c->type, sq->zone, sq->zonelen,
+			&p->pc->pif->addr, c->type, c->ssl, sq->zone, sq->zonelen,
 			sq->qbuf, sq->qbuflen, &sq->last_sent_time,
 			sq->outnet->now_tv, c->buffer);
 	}
Index: services/cache/dns.c
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/services/cache/dns.c,v
diff -u -p -r1.22 dns.c
--- services/cache/dns.c	13 Feb 2024 12:57:11 -0000	1.22
+++ services/cache/dns.c	12 Apr 2024 15:50:24 -0000
@@ -80,6 +80,7 @@ store_rrsets(struct module_env* env, str
 	struct regional* region, time_t qstarttime)
 {
 	size_t i;
+	time_t ttl, min_ttl = rep->ttl;
 	/* see if rrset already exists in cache, if not insert it. */
 	for(i=0; i<rep->rrset_count; i++) {
 		rep->ref[i].key = rep->rrsets[i];
@@ -112,6 +113,15 @@ store_rrsets(struct module_env* env, str
 		case 1: /* ref updated, item inserted */
 			rep->rrsets[i] = rep->ref[i].key;
 		}
+		/* if ref was updated make sure the message ttl is updated to
+		 * the minimum of the current rrsets. */
+		ttl = ((struct packed_rrset_data*)rep->rrsets[i]->entry.data)->ttl;
+		if(ttl < min_ttl) min_ttl = ttl;
+	}
+	if(min_ttl < rep->ttl) {
+		rep->ttl = min_ttl;
+		rep->prefetch_ttl = PREFETCH_TTL_CALC(rep->ttl);
+		rep->serve_expired_ttl = rep->ttl + SERVE_EXPIRED_TTL;
 	}
 }
 
@@ -818,7 +828,7 @@ synth_dname_msg(struct ub_packed_rrset_k
 	if(!newd)
 		return NULL;
 	ck->entry.data = newd;
-	newd->ttl = 0; /* 0 for synthesized CNAME TTL */
+	newd->ttl = d->ttl - now; /* RFC6672: synth CNAME TTL == DNAME TTL */
 	newd->count = 1;
 	newd->rrsig_count = 0;
 	newd->trust = rrset_trust_ans_noAA;
Index: testcode/testpkts.c
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/testcode/testpkts.c,v
diff -u -p -r1.1.1.8 testpkts.c
--- testcode/testpkts.c	5 Sep 2023 11:07:49 -0000	1.1.1.8
+++ testcode/testpkts.c	12 Apr 2024 15:50:24 -0000
@@ -470,6 +470,7 @@ get_origin(const char* name, struct sldn
 	store = *end;
 	*end = 0;
 	verbose(3, "parsing '%s'\n", parse);
+	pstate->origin_len = sizeof(pstate->origin);
 	status = sldns_str2wire_dname_buf(parse, pstate->origin,
 		&pstate->origin_len);
 	*end = store;
Index: testcode/unitauth.c
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/testcode/unitauth.c,v
diff -u -p -r1.1.1.5 unitauth.c
--- testcode/unitauth.c	12 Apr 2024 15:44:27 -0000	1.1.1.5
+++ testcode/unitauth.c	12 Apr 2024 15:50:24 -0000
@@ -279,14 +279,14 @@ static struct q_ans example_com_queries[
 ";flags QR AA rcode NOERROR\n"
 ";answer section\n"
 "redir.example.com.	3600	IN	DNAME	redir.example.org.\n"
-"abc.redir.example.com.	0	IN	CNAME	abc.redir.example.org.\n"
+"abc.redir.example.com.	3600	IN	CNAME	abc.redir.example.org.\n"
 	},
 
 	{ "example.com", "foo.abc.redir.example.com. A", "",
 ";flags QR AA rcode NOERROR\n"
 ";answer section\n"
 "redir.example.com.	3600	IN	DNAME	redir.example.org.\n"
-"foo.abc.redir.example.com.	0	IN	CNAME	foo.abc.redir.example.org.\n"
+"foo.abc.redir.example.com.	3600	IN	CNAME	foo.abc.redir.example.org.\n"
 	},
 
 	{ "example.com", "redir2.example.com. DNAME", "",
@@ -299,42 +299,42 @@ static struct q_ans example_com_queries[
 ";flags QR AA rcode NOERROR\n"
 ";answer section\n"
 "redir2.example.com.	3600	IN	DNAME	redir2.example.org.\n"
-"abc.redir2.example.com.	0	IN	CNAME	abc.redir2.example.org.\n"
+"abc.redir2.example.com.	3600	IN	CNAME	abc.redir2.example.org.\n"
 	},
 
 	{ "example.com", "obscured.redir2.example.com. A", "",
 ";flags QR AA rcode NOERROR\n"
 ";answer section\n"
 "redir2.example.com.	3600	IN	DNAME	redir2.example.org.\n"
-"obscured.redir2.example.com.	0	IN	CNAME	obscured.redir2.example.org.\n"
+"obscured.redir2.example.com.	3600	IN	CNAME	obscured.redir2.example.org.\n"
 	},
 
 	{ "example.com", "under2.redir2.example.com. A", "",
 ";flags QR AA rcode NOERROR\n"
 ";answer section\n"
 "redir2.example.com.	3600	IN	DNAME	redir2.example.org.\n"
-"under2.redir2.example.com.	0	IN	CNAME	under2.redir2.example.org.\n"
+"under2.redir2.example.com.	3600	IN	CNAME	under2.redir2.example.org.\n"
 	},
 
 	{ "example.com", "doubleobscured.under2.redir2.example.com. A", "",
 ";flags QR AA rcode NOERROR\n"
 ";answer section\n"
 "redir2.example.com.	3600	IN	DNAME	redir2.example.org.\n"
-"doubleobscured.under2.redir2.example.com.	0	IN	CNAME	doubleobscured.under2.redir2.example.org.\n"
+"doubleobscured.under2.redir2.example.com.	3600	IN	CNAME	doubleobscured.under2.redir2.example.org.\n"
 	},
 
 	{ "example.com", "foo.doubleobscured.under2.redir2.example.com. A", "",
 ";flags QR AA rcode NOERROR\n"
 ";answer section\n"
 "redir2.example.com.	3600	IN	DNAME	redir2.example.org.\n"
-"foo.doubleobscured.under2.redir2.example.com.	0	IN	CNAME	foo.doubleobscured.under2.redir2.example.org.\n"
+"foo.doubleobscured.under2.redir2.example.com.	3600	IN	CNAME	foo.doubleobscured.under2.redir2.example.org.\n"
 	},
 
 	{ "example.com", "foo.under2.redir2.example.com. A", "",
 ";flags QR AA rcode NOERROR\n"
 ";answer section\n"
 "redir2.example.com.	3600	IN	DNAME	redir2.example.org.\n"
-"foo.under2.redir2.example.com.	0	IN	CNAME	foo.under2.redir2.example.org.\n"
+"foo.under2.redir2.example.com.	3600	IN	CNAME	foo.under2.redir2.example.org.\n"
 	},
 
 	{ "example.com", "sub.example.com. NS", "",
Index: util/config_file.c
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/util/config_file.c,v
diff -u -p -r1.33 config_file.c
--- util/config_file.c	12 Apr 2024 15:45:24 -0000	1.33
+++ util/config_file.c	12 Apr 2024 15:50:24 -0000
@@ -142,6 +142,7 @@ config_create(void)
 	cfg->log_tag_queryreply = 0;
 	cfg->log_local_actions = 0;
 	cfg->log_servfail = 0;
+	cfg->log_destaddr = 0;
 #ifndef USE_WINSOCK
 #  ifdef USE_MINI_EVENT
 	/* select max 1024 sockets */
@@ -690,6 +691,7 @@ int config_set_option(struct config_file
 	else S_YNO("log-tag-queryreply:", log_tag_queryreply)
 	else S_YNO("log-local-actions:", log_local_actions)
 	else S_YNO("log-servfail:", log_servfail)
+	else S_YNO("log-destaddr:", log_destaddr)
 	else S_YNO("val-permissive-mode:", val_permissive_mode)
 	else S_YNO("aggressive-nsec:", aggressive_nsec)
 	else S_YNO("ignore-cd-flag:", ignore_cd)
@@ -1127,6 +1129,7 @@ config_get_option(struct config_file* cf
 	else O_YNO(opt, "log-tag-queryreply", log_tag_queryreply)
 	else O_YNO(opt, "log-local-actions", log_local_actions)
 	else O_YNO(opt, "log-servfail", log_servfail)
+	else O_YNO(opt, "log-destaddr", log_destaddr)
 	else O_STR(opt, "pidfile", pidfile)
 	else O_YNO(opt, "hide-identity", hide_identity)
 	else O_YNO(opt, "hide-version", hide_version)
Index: util/config_file.h
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/util/config_file.h,v
diff -u -p -r1.31 config_file.h
--- util/config_file.h	12 Apr 2024 15:45:24 -0000	1.31
+++ util/config_file.h	12 Apr 2024 15:50:24 -0000
@@ -349,6 +349,8 @@ struct config_file {
 	int log_servfail;
 	/** log identity to report */
 	char* log_identity;
+	/** log dest addr for log_replies */
+	int log_destaddr;
 
 	/** do not report identity (id.server, hostname.bind) */
 	int hide_identity;
Index: util/configlexer.lex
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/util/configlexer.lex,v
diff -u -p -r1.28 configlexer.lex
--- util/configlexer.lex	12 Apr 2024 15:45:24 -0000	1.28
+++ util/configlexer.lex	12 Apr 2024 15:50:24 -0000
@@ -434,6 +434,7 @@ log-replies{COLON}		{ YDVAR(1, VAR_LOG_R
 log-tag-queryreply{COLON}	{ YDVAR(1, VAR_LOG_TAG_QUERYREPLY) }
 log-local-actions{COLON}       { YDVAR(1, VAR_LOG_LOCAL_ACTIONS) }
 log-servfail{COLON}		{ YDVAR(1, VAR_LOG_SERVFAIL) }
+log-destaddr{COLON}		{ YDVAR(1, VAR_LOG_DESTADDR) }
 local-zone{COLON}		{ YDVAR(2, VAR_LOCAL_ZONE) }
 local-data{COLON}		{ YDVAR(1, VAR_LOCAL_DATA) }
 local-data-ptr{COLON}		{ YDVAR(1, VAR_LOCAL_DATA_PTR) }
Index: util/configparser.y
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/util/configparser.y,v
diff -u -p -r1.28 configparser.y
--- util/configparser.y	12 Apr 2024 15:45:24 -0000	1.28
+++ util/configparser.y	12 Apr 2024 15:50:24 -0000
@@ -200,6 +200,7 @@ extern struct config_parser_state* cfg_p
 %token VAR_INTERFACE_TAG_ACTION VAR_INTERFACE_TAG_DATA
 %token VAR_PROXY_PROTOCOL_PORT VAR_STATISTICS_INHIBIT_ZERO
 %token VAR_HARDEN_UNKNOWN_ADDITIONAL VAR_DISABLE_EDNS_DO VAR_CACHEDB_NO_STORE
+%token VAR_LOG_DESTADDR
 
 %%
 toplevelvars: /* empty */ | toplevelvars toplevelvar ;
@@ -333,7 +334,8 @@ content_server: server_num_threads | ser
 	server_tcp_reuse_timeout | server_tcp_auth_query_timeout |
 	server_interface_automatic_ports | server_ede |
 	server_proxy_protocol_port | server_statistics_inhibit_zero |
-	server_harden_unknown_additional | server_disable_edns_do
+	server_harden_unknown_additional | server_disable_edns_do |
+	server_log_destaddr
 	;
 stubstart: VAR_STUB_ZONE
 	{
@@ -1247,6 +1249,15 @@ server_log_servfail: VAR_LOG_SERVFAIL ST
 		if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0)
 			yyerror("expected yes or no.");
 		else cfg_parser->cfg->log_servfail = (strcmp($2, "yes")==0);
+		free($2);
+	}
+	;
+server_log_destaddr: VAR_LOG_DESTADDR STRING_ARG
+	{
+		OUTYY(("P(server_log_destaddr:%s)\n", $2));
+		if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0)
+			yyerror("expected yes or no.");
+		else cfg_parser->cfg->log_destaddr = (strcmp($2, "yes")==0);
 		free($2);
 	}
 	;
Index: util/iana_ports.inc
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/util/iana_ports.inc,v
diff -u -p -r1.27 iana_ports.inc
--- util/iana_ports.inc	5 Sep 2023 11:12:10 -0000	1.27
+++ util/iana_ports.inc	12 Apr 2024 15:50:24 -0000
@@ -258,7 +258,6 @@
 356,
 357,
 358,
-359,
 360,
 361,
 362,
Index: util/netevent.c
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/util/netevent.c,v
diff -u -p -r1.36 netevent.c
--- util/netevent.c	12 Apr 2024 15:45:24 -0000	1.36
+++ util/netevent.c	12 Apr 2024 15:50:24 -0000
@@ -1672,8 +1672,13 @@ ssl_handshake(struct comm_point* c)
 		} else {
 			unsigned long err = ERR_get_error();
 			if(!squelch_err_ssl_handshake(err)) {
+				long vr;
 				log_crypto_err_io_code("ssl handshake failed",
 					want, err);
+				if((vr=SSL_get_verify_result(c->ssl)) != 0)
+					log_err("ssl handshake cert error: %s",
+						X509_verify_cert_error_string(
+						vr));
 				log_addr(VERB_OPS, "ssl handshake failed",
 					&c->repinfo.remote_addr,
 					c->repinfo.remote_addrlen);
@@ -1748,6 +1753,9 @@ ssl_handshake(struct comm_point* c)
 			/* connection upgraded to HTTP2 */
 			c->tcp_do_toggle_rw = 0;
 			c->use_h2 = 1;
+		} else {
+			verbose(VERB_ALGO, "client doesn't support HTTP/2");
+			return 0;
 		}
 	}
 #endif
@@ -4766,7 +4774,7 @@ comm_point_send_reply(struct comm_reply 
 		if(repinfo->c->dtenv != NULL && repinfo->c->dtenv->log_client_response_messages) {
 			log_addr(VERB_ALGO, "from local addr", (void*)repinfo->c->socket->addr->ai_addr, repinfo->c->socket->addr->ai_addrlen);
 			log_addr(VERB_ALGO, "response to client", &repinfo->client_addr, repinfo->client_addrlen);
-			dt_msg_send_client_response(repinfo->c->dtenv, &repinfo->client_addr, (void*)repinfo->c->socket->addr->ai_addr, repinfo->c->type, repinfo->c->buffer);
+			dt_msg_send_client_response(repinfo->c->dtenv, &repinfo->client_addr, (void*)repinfo->c->socket->addr->ai_addr, repinfo->c->type, repinfo->c->ssl, repinfo->c->buffer);
 		}
 #endif
 	} else {
@@ -4777,7 +4785,7 @@ comm_point_send_reply(struct comm_reply 
 		if(repinfo->c->tcp_parent->dtenv != NULL && repinfo->c->tcp_parent->dtenv->log_client_response_messages) {
 			log_addr(VERB_ALGO, "from local addr", (void*)repinfo->c->socket->addr->ai_addr, repinfo->c->socket->addr->ai_addrlen);
 			log_addr(VERB_ALGO, "response to client", &repinfo->client_addr, repinfo->client_addrlen);
-			dt_msg_send_client_response(repinfo->c->tcp_parent->dtenv, &repinfo->client_addr, (void*)repinfo->c->socket->addr->ai_addr, repinfo->c->type,
+			dt_msg_send_client_response(repinfo->c->tcp_parent->dtenv, &repinfo->client_addr, (void*)repinfo->c->socket->addr->ai_addr, repinfo->c->type, repinfo->c->ssl,
 				( repinfo->c->tcp_req_info? repinfo->c->tcp_req_info->spool_buffer: repinfo->c->buffer ));
 		}
 #endif
Index: util/data/msgreply.c
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/util/data/msgreply.c,v
diff -u -p -r1.23 msgreply.c
--- util/data/msgreply.c	5 Sep 2023 11:12:11 -0000	1.23
+++ util/data/msgreply.c	12 Apr 2024 15:50:24 -0000
@@ -918,13 +918,15 @@ log_dns_msg(const char* str, struct quer
 void
 log_reply_info(enum verbosity_value v, struct query_info *qinf,
 	struct sockaddr_storage *addr, socklen_t addrlen, struct timeval dur,
-	int cached, struct sldns_buffer *rmsg)
+	int cached, struct sldns_buffer *rmsg, struct sockaddr_storage* daddr,
+	enum comm_point_type tp)
 {
 	char qname_buf[LDNS_MAX_DOMAINLEN+1];
 	char clientip_buf[128];
 	char rcode_buf[16];
 	char type_buf[16];
 	char class_buf[16];
+	char dest_buf[160];
 	size_t pktlen;
 	uint16_t rcode = FLAGS_GET_RCODE(sldns_buffer_read_u16_at(rmsg, 2));
 
@@ -933,11 +935,46 @@ log_reply_info(enum verbosity_value v, s
 
 	sldns_wire2str_rcode_buf((int)rcode, rcode_buf, sizeof(rcode_buf));
 	addr_to_str(addr, addrlen, clientip_buf, sizeof(clientip_buf));
+	if(daddr) {
+		char da[128];
+		int port = 0;
+		char* comm;
+		if(daddr->ss_family == AF_INET6) {
+			struct sockaddr_in6 *d = (struct sockaddr_in6 *)daddr;
+			if(inet_ntop(d->sin6_family, &d->sin6_addr, da,
+				sizeof(*d)) == 0)
+				snprintf(dest_buf, sizeof(dest_buf),
+					"(inet_ntop_error)");
+			port = ntohs(d->sin6_port);
+		} else if(daddr->ss_family == AF_INET) {
+			struct sockaddr_in *d = (struct sockaddr_in *)daddr;
+			if(inet_ntop(d->sin_family, &d->sin_addr, da,
+				sizeof(*d)) == 0)
+				snprintf(dest_buf, sizeof(dest_buf),
+					"(inet_ntop_error)");
+			port = ntohs(d->sin_port);
+		} else {
+			snprintf(da, sizeof(da), "socket%d",
+				(int)daddr->ss_family);
+		}
+		comm = "udp";
+		if(tp == comm_tcp) comm = "tcp";
+		else if(tp == comm_tcp_accept) comm = "tcp";
+		else if(tp == comm_http) comm = "dot";
+		else if(tp == comm_local) comm = "unix";
+		else if(tp == comm_raw) comm = "raw";
+		snprintf(dest_buf, sizeof(dest_buf), " on %s %s %d",
+			comm, da, port);
+	} else {
+		dest_buf[0]=0;
+	}
 	if(rcode == LDNS_RCODE_FORMERR)
 	{
 		if(LOG_TAG_QUERYREPLY)
-			log_reply("%s - - - %s - - - ", clientip_buf, rcode_buf);
-		else	log_info("%s - - - %s - - - ", clientip_buf, rcode_buf);
+			log_reply("%s - - - %s - - -%s", clientip_buf,
+				rcode_buf, dest_buf);
+		else	log_info("%s - - - %s - - -%s", clientip_buf,
+				rcode_buf, dest_buf);
 	} else {
 		if(qinf->qname)
 			dname_str(qinf->qname, qname_buf);
@@ -946,12 +983,14 @@ log_reply_info(enum verbosity_value v, s
 		sldns_wire2str_type_buf(qinf->qtype, type_buf, sizeof(type_buf));
 		sldns_wire2str_class_buf(qinf->qclass, class_buf, sizeof(class_buf));
 		if(LOG_TAG_QUERYREPLY)
-		     log_reply("%s %s %s %s %s " ARG_LL "d.%6.6d %d %d",
+		     log_reply("%s %s %s %s %s " ARG_LL "d.%6.6d %d %d%s",
 			clientip_buf, qname_buf, type_buf, class_buf,
-			rcode_buf, (long long)dur.tv_sec, (int)dur.tv_usec, cached, (int)pktlen);
-		else log_info("%s %s %s %s %s " ARG_LL "d.%6.6d %d %d",
+			rcode_buf, (long long)dur.tv_sec, (int)dur.tv_usec,
+			cached, (int)pktlen, dest_buf);
+		else log_info("%s %s %s %s %s " ARG_LL "d.%6.6d %d %d%s",
 			clientip_buf, qname_buf, type_buf, class_buf,
-			rcode_buf, (long long)dur.tv_sec, (int)dur.tv_usec, cached, (int)pktlen);
+			rcode_buf, (long long)dur.tv_sec, (int)dur.tv_usec,
+			cached, (int)pktlen, dest_buf);
 	}
 }
 
Index: util/data/msgreply.h
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/util/data/msgreply.h,v
diff -u -p -r1.14 msgreply.h
--- util/data/msgreply.h	5 Sep 2023 11:12:11 -0000	1.14
+++ util/data/msgreply.h	12 Apr 2024 15:50:24 -0000
@@ -58,6 +58,7 @@ struct msg_parse;
 struct rrset_parse;
 struct local_rrset;
 struct dns_msg;
+enum comm_point_type;
 
 /** calculate the prefetch TTL as 90% of original. Calculation
  * without numerical overflow (uin32_t) */
@@ -520,10 +521,13 @@ void log_dns_msg(const char* str, struct
  * @param cached: whether or not the reply is coming from
  *                    the cache, or an outside network.
  * @param rmsg: sldns buffer packet.
+ * @param daddr: if not NULL, the destination address and port are logged.
+ * @param tp: type of the comm point for logging destination connection type.
  */
 void log_reply_info(enum verbosity_value v, struct query_info *qinf,
 	struct sockaddr_storage *addr, socklen_t addrlen, struct timeval dur,
-	int cached, struct sldns_buffer *rmsg);
+	int cached, struct sldns_buffer *rmsg, struct sockaddr_storage* daddr,
+	enum comm_point_type tp);
 
 /**
  * Print string with neat domain name, type, class from query info.
Index: util/data/packed_rrset.c
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/util/data/packed_rrset.c,v
diff -u -p -r1.6 packed_rrset.c
--- util/data/packed_rrset.c	12 Mar 2021 19:45:28 -0000	1.6
+++ util/data/packed_rrset.c	12 Apr 2024 15:50:24 -0000
@@ -275,6 +275,7 @@ int packed_rr_to_string(struct ub_packed
 	struct packed_rrset_data* d = (struct packed_rrset_data*)rrset->
 		entry.data;
 	uint8_t rr[65535];
+	size_t wlen;
 	size_t rlen = rrset->rk.dname_len + 2 + 2 + 4 + d->rr_len[i];
 	time_t adjust = 0;
 	log_assert(dest_len > 0 && dest);
@@ -292,7 +293,9 @@ int packed_rr_to_string(struct ub_packed
 	sldns_write_uint32(rr+rrset->rk.dname_len+4,
 		(uint32_t)(d->rr_ttl[i]-adjust));
 	memmove(rr+rrset->rk.dname_len+8, d->rr_data[i], d->rr_len[i]);
-	if(sldns_wire2str_rr_buf(rr, rlen, dest, dest_len) == -1) {
+	wlen = (size_t)sldns_wire2str_rr_buf(rr, rlen, dest, dest_len);
+	if(wlen >= dest_len) {
+		/* the output string was truncated */
 		log_info("rrbuf failure %d %s", (int)d->rr_len[i], dest);
 		dest[0] = 0;
 		return 0;
Index: validator/autotrust.c
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/validator/autotrust.c,v
diff -u -p -r1.17 autotrust.c
--- validator/autotrust.c	5 Sep 2023 11:12:11 -0000	1.17
+++ validator/autotrust.c	12 Apr 2024 15:50:24 -0000
@@ -353,17 +353,21 @@ autr_tp_create(struct val_anchors* ancho
 
 	lock_basic_lock(&anchors->lock);
 	if(!rbtree_insert(anchors->tree, &tp->node)) {
+		char buf[LDNS_MAX_DOMAINLEN+1];
 		lock_basic_unlock(&anchors->lock);
-		log_err("trust anchor presented twice");
+		dname_str(tp->name, buf);
+		log_err("trust anchor for '%s' presented twice", buf);
 		free(tp->name);
 		free(tp->autr);
 		free(tp);
 		return NULL;
 	}
 	if(!rbtree_insert(&anchors->autr->probe, &tp->autr->pnode)) {
+		char buf[LDNS_MAX_DOMAINLEN+1];
 		(void)rbtree_delete(anchors->tree, tp);
 		lock_basic_unlock(&anchors->lock);
-		log_err("trust anchor in probetree twice");
+		dname_str(tp->name, buf);
+		log_err("trust anchor for '%s' in probetree twice", buf);
 		free(tp->name);
 		free(tp->autr);
 		free(tp);
Index: validator/val_sigcrypt.c
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/validator/val_sigcrypt.c,v
diff -u -p -r1.13 val_sigcrypt.c
--- validator/val_sigcrypt.c	13 Feb 2024 12:57:11 -0000	1.13
+++ validator/val_sigcrypt.c	12 Apr 2024 15:50:24 -0000
@@ -748,7 +748,6 @@ dnskey_verify_rrset(struct module_env* e
 			return sec_status_bogus;
 		}
 	}
-	verbose(VERB_ALGO, "rrset failed to verify: all signatures are bogus");
 	if(!numchecked) {
 		*reason = "signature for expected key and algorithm missing";
 		if(reason_bogus)
@@ -761,6 +760,7 @@ dnskey_verify_rrset(struct module_env* e
 		*reason = "algorithm refused by cryptolib";
 		return sec_status_indeterminate;
 	}
+	verbose(VERB_ALGO, "rrset failed to verify: all signatures are bogus");
 	return sec_status_bogus;
 }
 
Index: validator/val_utils.c
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/validator/val_utils.c,v
diff -u -p -r1.14 val_utils.c
--- validator/val_utils.c	13 Feb 2024 12:57:11 -0000	1.14
+++ validator/val_utils.c	12 Apr 2024 15:50:24 -0000
@@ -424,11 +424,13 @@ static enum sec_status
 verify_dnskeys_with_ds_rr(struct module_env* env, struct val_env* ve,
 	struct ub_packed_rrset_key* dnskey_rrset,
         struct ub_packed_rrset_key* ds_rrset, size_t ds_idx, char** reason,
-	sldns_ede_code *reason_bogus, struct module_qstate* qstate)
+	sldns_ede_code *reason_bogus, struct module_qstate* qstate,
+	int *nonechecked)
 {
 	enum sec_status sec = sec_status_bogus;
 	size_t i, num, numchecked = 0, numhashok = 0, numsizesupp = 0;
 	num = rrset_get_count(dnskey_rrset);
+	*nonechecked = 0;
 	for(i=0; i<num; i++) {
 		/* Skip DNSKEYs that don't match the basic criteria. */
 		if(ds_get_key_algo(ds_rrset, ds_idx) 
@@ -476,13 +478,15 @@ verify_dnskeys_with_ds_rr(struct module_
 		/* there is a working DS, but that DNSKEY is not supported */
 		return sec_status_insecure;
 	}
-	if(numchecked == 0)
+	if(numchecked == 0) {
 		algo_needs_reason(env, ds_get_key_algo(ds_rrset, ds_idx),
 			reason, "no keys have a DS");
-	else if(numhashok == 0)
+		*nonechecked = 1;
+	} else if(numhashok == 0) {
 		*reason = "DS hash mismatches key";
-	else if(!*reason)
+	} else if(!*reason) {
 		*reason = "keyset not secured by DNSKEY that matches DS";
+	}
 	return sec_status_bogus;
 }
 
@@ -511,7 +515,8 @@ val_verify_DNSKEY_with_DS(struct module_
 {
 	/* as long as this is false, we can consider this DS rrset to be
 	 * equivalent to no DS rrset. */
-	int has_useful_ds = 0, digest_algo, alg;
+	int has_useful_ds = 0, digest_algo, alg, has_algo_refusal = 0,
+		nonechecked, has_checked_ds = 0;
 	struct algo_needs needs;
 	size_t i, num;
 	enum sec_status sec;
@@ -544,9 +549,16 @@ val_verify_DNSKEY_with_DS(struct module_
 		}
 
 		sec = verify_dnskeys_with_ds_rr(env, ve, dnskey_rrset,
-			ds_rrset, i, reason, reason_bogus, qstate);
-		if(sec == sec_status_insecure)
+			ds_rrset, i, reason, reason_bogus, qstate,
+			&nonechecked);
+		if(sec == sec_status_insecure) {
+			/* DNSKEY too large unsupported or algo refused by
+			 * crypto lib. */
+			has_algo_refusal = 1;
 			continue;
+		}
+		if(!nonechecked)
+			has_checked_ds = 1;
 
 		/* Once we see a single DS with a known digestID and 
 		 * algorithm, we cannot return INSECURE (with a 
@@ -571,6 +583,15 @@ val_verify_DNSKEY_with_DS(struct module_
 
 	/* None of the DS's worked out. */
 
+	/* If none of the DSes have been checked, eg. that means no matches
+	 * for keytags, and the other dses are all algo_refusal, it is an
+	 * insecure delegation point, since the only matched DS records
+	 * have an algo refusal, or are unsupported. */
+	if(has_algo_refusal && !has_checked_ds) {
+		verbose(VERB_ALGO, "No supported DS records were found -- "
+			"treating as insecure.");
+		return sec_status_insecure;
+	}
 	/* If no DSs were understandable, then this is OK. */
 	if(!has_useful_ds) {
 		verbose(VERB_ALGO, "No usable DS records were found -- "
@@ -624,7 +645,8 @@ val_verify_DNSKEY_with_TA(struct module_
 {
 	/* as long as this is false, we can consider this anchor to be
 	 * equivalent to no anchor. */
-	int has_useful_ta = 0, digest_algo = 0, alg;
+	int has_useful_ta = 0, digest_algo = 0, alg, has_algo_refusal = 0,
+		nonechecked, has_checked_ds = 0;
 	struct algo_needs needs;
 	size_t i, num;
 	enum sec_status sec;
@@ -670,9 +692,13 @@ val_verify_DNSKEY_with_TA(struct module_
 			continue;
 
 		sec = verify_dnskeys_with_ds_rr(env, ve, dnskey_rrset,
-			ta_ds, i, reason, reason_bogus, qstate);
-		if(sec == sec_status_insecure)
+			ta_ds, i, reason, reason_bogus, qstate, &nonechecked);
+		if(sec == sec_status_insecure) {
+			has_algo_refusal = 1;
 			continue;
+		}
+		if(!nonechecked)
+			has_checked_ds = 1;
 
 		/* Once we see a single DS with a known digestID and 
 		 * algorithm, we cannot return INSECURE (with a 
@@ -728,6 +754,15 @@ val_verify_DNSKEY_with_TA(struct module_
 	    }
 	}
 
+	/* If none of the DSes have been checked, eg. that means no matches
+	 * for keytags, and the other dses are all algo_refusal, it is an
+	 * insecure delegation point, since the only matched DS records
+	 * have an algo refusal, or are unsupported. */
+	if(has_algo_refusal && !has_checked_ds) {
+		verbose(VERB_ALGO, "No supported trust anchors were found -- "
+			"treating as insecure.");
+		return sec_status_insecure;
+	}
 	/* If no DSs were understandable, then this is OK. */
 	if(!has_useful_ta) {
 		verbose(VERB_ALGO, "No usable trust anchors were found -- "
Index: validator/validator.c
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/validator/validator.c,v
diff -u -p -r1.22 validator.c
--- validator/validator.c	12 Apr 2024 15:45:24 -0000	1.22
+++ validator/validator.c	12 Apr 2024 15:50:24 -0000
@@ -3010,6 +3010,8 @@ return_bogus:
  * @param msg: result message (if rcode is OK).
  * @param qinfo: from the sub query state, query info.
  * @param origin: the origin of msg.
+ * @param suspend: returned true if the task takes too long and needs to
+ * 	suspend to continue the effort later.
  */
 static void
 process_ds_response(struct module_qstate* qstate, struct val_qstate* vq,