#1 Simple bump of unbound to 1.13.1
Opened 3 years ago by malmond. Modified 3 years ago

file modified
+1 -1
@@ -1,1 +1,1 @@ 

- SOURCES/unbound-1.7.3.tar.gz

+ SOURCES/unbound-1.13.1.tar.gz

file modified
+1 -1
@@ -1,1 +1,1 @@ 

- 106789bdca173d033d769c67be3441b47611612a SOURCES/unbound-1.7.3.tar.gz

+ 561522b06943f6d1c33bd78132db1f7020fc4fd1 SOURCES/unbound-1.13.1.tar.gz

@@ -1,320 +0,0 @@ 

- From b5aab36d41f374eddb0f66f28f251588f53a1e1e Mon Sep 17 00:00:00 2001

- From: Wouter Wijngaards <wouter@nlnetlabs.nl>

- Date: Wed, 27 Jun 2018 05:46:36 +0000

- Subject: [PATCH 1/2] - #4109: Fix that package config depends on python

-  unconditionally.

- 

- git-svn-id: file:///svn/unbound/trunk@4757 be551aaa-1e26-0410-a405-d3ace91eadb9

- ---

-  configure    | 257 +++++++++++++++++++++++++++++++----------------------------

-  configure.ac |   5 +-

-  2 files changed, 137 insertions(+), 125 deletions(-)

- 

- diff --git a/configure b/configure

- index 3f1c372a..2a1687ae 100755

- --- a/configure

- +++ b/configure

- @@ -670,9 +670,6 @@ SYSTEMD_DAEMON_LIBS

-  SYSTEMD_DAEMON_CFLAGS

-  SYSTEMD_LIBS

-  SYSTEMD_CFLAGS

- -PKG_CONFIG_LIBDIR

- -PKG_CONFIG_PATH

- -PKG_CONFIG

-  staticexe

-  PC_LIBEVENT_DEPENDENCY

-  UNBOUND_EVENT_UNINSTALL

- @@ -697,6 +694,9 @@ swig

-  SWIG_LIB

-  SWIG

-  PC_PY_DEPENDENCY

- +PKG_CONFIG_LIBDIR

- +PKG_CONFIG_PATH

- +PKG_CONFIG

-  PY_MAJOR_VERSION

-  PYTHON_SITE_PKG

-  PYTHON_LDFLAGS

- @@ -16930,7 +16930,136 @@ $as_echo "#define HAVE_PYTHON 1" >>confdefs.h

-          CPPFLAGS="$PYTHON_CPPFLAGS"

-        fi

-        ub_have_python=yes

- -      PC_PY_DEPENDENCY="python"

- +

- +

- +

- +

- +

- +

- +

- +if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then

- +	if test -n "$ac_tool_prefix"; then

- +  # Extract the first word of "${ac_tool_prefix}pkg-config", so it can be a program name with args.

- +set dummy ${ac_tool_prefix}pkg-config; ac_word=$2

- +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5

- +$as_echo_n "checking for $ac_word... " >&6; }

- +if ${ac_cv_path_PKG_CONFIG+:} false; then :

- +  $as_echo_n "(cached) " >&6

- +else

- +  case $PKG_CONFIG in

- +  [\\/]* | ?:[\\/]*)

- +  ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path.

- +  ;;

- +  *)

- +  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR

- +for as_dir in $PATH

- +do

- +  IFS=$as_save_IFS

- +  test -z "$as_dir" && as_dir=.

- +    for ac_exec_ext in '' $ac_executable_extensions; do

- +  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then

- +    ac_cv_path_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext"

- +    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5

- +    break 2

- +  fi

- +done

- +  done

- +IFS=$as_save_IFS

- +

- +  ;;

- +esac

- +fi

- +PKG_CONFIG=$ac_cv_path_PKG_CONFIG

- +if test -n "$PKG_CONFIG"; then

- +  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PKG_CONFIG" >&5

- +$as_echo "$PKG_CONFIG" >&6; }

- +else

- +  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5

- +$as_echo "no" >&6; }

- +fi

- +

- +

- +fi

- +if test -z "$ac_cv_path_PKG_CONFIG"; then

- +  ac_pt_PKG_CONFIG=$PKG_CONFIG

- +  # Extract the first word of "pkg-config", so it can be a program name with args.

- +set dummy pkg-config; ac_word=$2

- +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5

- +$as_echo_n "checking for $ac_word... " >&6; }

- +if ${ac_cv_path_ac_pt_PKG_CONFIG+:} false; then :

- +  $as_echo_n "(cached) " >&6

- +else

- +  case $ac_pt_PKG_CONFIG in

- +  [\\/]* | ?:[\\/]*)

- +  ac_cv_path_ac_pt_PKG_CONFIG="$ac_pt_PKG_CONFIG" # Let the user override the test with a path.

- +  ;;

- +  *)

- +  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR

- +for as_dir in $PATH

- +do

- +  IFS=$as_save_IFS

- +  test -z "$as_dir" && as_dir=.

- +    for ac_exec_ext in '' $ac_executable_extensions; do

- +  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then

- +    ac_cv_path_ac_pt_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext"

- +    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5

- +    break 2

- +  fi

- +done

- +  done

- +IFS=$as_save_IFS

- +

- +  ;;

- +esac

- +fi

- +ac_pt_PKG_CONFIG=$ac_cv_path_ac_pt_PKG_CONFIG

- +if test -n "$ac_pt_PKG_CONFIG"; then

- +  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_PKG_CONFIG" >&5

- +$as_echo "$ac_pt_PKG_CONFIG" >&6; }

- +else

- +  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5

- +$as_echo "no" >&6; }

- +fi

- +

- +  if test "x$ac_pt_PKG_CONFIG" = x; then

- +    PKG_CONFIG=""

- +  else

- +    case $cross_compiling:$ac_tool_warned in

- +yes:)

- +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5

- +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}

- +ac_tool_warned=yes ;;

- +esac

- +    PKG_CONFIG=$ac_pt_PKG_CONFIG

- +  fi

- +else

- +  PKG_CONFIG="$ac_cv_path_PKG_CONFIG"

- +fi

- +

- +fi

- +if test -n "$PKG_CONFIG"; then

- +	_pkg_min_version=0.9.0

- +	{ $as_echo "$as_me:${as_lineno-$LINENO}: checking pkg-config is at least version $_pkg_min_version" >&5

- +$as_echo_n "checking pkg-config is at least version $_pkg_min_version... " >&6; }

- +	if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then

- +		{ $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; }

- +		PKG_CONFIG=""

- +	fi

- +fi

- +      if test -n "$PKG_CONFIG" && \

- +    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"\"python\${PY_MAJOR_VERSION}\"\""; } >&5

- +  ($PKG_CONFIG --exists --print-errors ""python${PY_MAJOR_VERSION}"") 2>&5

- +  ac_status=$?

- +  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5

- +  test $ac_status = 0; }; then

- +  PC_PY_DEPENDENCY="python${PY_MAJOR_VERSION}"

- +else

- +  PC_PY_DEPENDENCY="python"

- +fi

-  

-  

-        # Check for SWIG

- @@ -18960,126 +19089,6 @@ else

-  fi

-  

-  have_systemd=no

- -

- -

- -

- -

- -

- -

- -

- -if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then

- -	if test -n "$ac_tool_prefix"; then

- -  # Extract the first word of "${ac_tool_prefix}pkg-config", so it can be a program name with args.

- -set dummy ${ac_tool_prefix}pkg-config; ac_word=$2

- -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5

- -$as_echo_n "checking for $ac_word... " >&6; }

- -if ${ac_cv_path_PKG_CONFIG+:} false; then :

- -  $as_echo_n "(cached) " >&6

- -else

- -  case $PKG_CONFIG in

- -  [\\/]* | ?:[\\/]*)

- -  ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path.

- -  ;;

- -  *)

- -  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR

- -for as_dir in $PATH

- -do

- -  IFS=$as_save_IFS

- -  test -z "$as_dir" && as_dir=.

- -    for ac_exec_ext in '' $ac_executable_extensions; do

- -  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then

- -    ac_cv_path_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext"

- -    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5

- -    break 2

- -  fi

- -done

- -  done

- -IFS=$as_save_IFS

- -

- -  ;;

- -esac

- -fi

- -PKG_CONFIG=$ac_cv_path_PKG_CONFIG

- -if test -n "$PKG_CONFIG"; then

- -  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PKG_CONFIG" >&5

- -$as_echo "$PKG_CONFIG" >&6; }

- -else

- -  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5

- -$as_echo "no" >&6; }

- -fi

- -

- -

- -fi

- -if test -z "$ac_cv_path_PKG_CONFIG"; then

- -  ac_pt_PKG_CONFIG=$PKG_CONFIG

- -  # Extract the first word of "pkg-config", so it can be a program name with args.

- -set dummy pkg-config; ac_word=$2

- -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5

- -$as_echo_n "checking for $ac_word... " >&6; }

- -if ${ac_cv_path_ac_pt_PKG_CONFIG+:} false; then :

- -  $as_echo_n "(cached) " >&6

- -else

- -  case $ac_pt_PKG_CONFIG in

- -  [\\/]* | ?:[\\/]*)

- -  ac_cv_path_ac_pt_PKG_CONFIG="$ac_pt_PKG_CONFIG" # Let the user override the test with a path.

- -  ;;

- -  *)

- -  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR

- -for as_dir in $PATH

- -do

- -  IFS=$as_save_IFS

- -  test -z "$as_dir" && as_dir=.

- -    for ac_exec_ext in '' $ac_executable_extensions; do

- -  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then

- -    ac_cv_path_ac_pt_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext"

- -    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5

- -    break 2

- -  fi

- -done

- -  done

- -IFS=$as_save_IFS

- -

- -  ;;

- -esac

- -fi

- -ac_pt_PKG_CONFIG=$ac_cv_path_ac_pt_PKG_CONFIG

- -if test -n "$ac_pt_PKG_CONFIG"; then

- -  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_PKG_CONFIG" >&5

- -$as_echo "$ac_pt_PKG_CONFIG" >&6; }

- -else

- -  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5

- -$as_echo "no" >&6; }

- -fi

- -

- -  if test "x$ac_pt_PKG_CONFIG" = x; then

- -    PKG_CONFIG=""

- -  else

- -    case $cross_compiling:$ac_tool_warned in

- -yes:)

- -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5

- -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}

- -ac_tool_warned=yes ;;

- -esac

- -    PKG_CONFIG=$ac_pt_PKG_CONFIG

- -  fi

- -else

- -  PKG_CONFIG="$ac_cv_path_PKG_CONFIG"

- -fi

- -

- -fi

- -if test -n "$PKG_CONFIG"; then

- -	_pkg_min_version=0.9.0

- -	{ $as_echo "$as_me:${as_lineno-$LINENO}: checking pkg-config is at least version $_pkg_min_version" >&5

- -$as_echo_n "checking pkg-config is at least version $_pkg_min_version... " >&6; }

- -	if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then

- -		{ $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; }

- -		PKG_CONFIG=""

- -	fi

- -fi

-  if test "x$enable_systemd" != xno; then :

-  

-  

- diff --git a/configure.ac b/configure.ac

- index 1828253c..b2c95d1a 100644

- --- a/configure.ac

- +++ b/configure.ac

- @@ -586,7 +586,10 @@ if test x_$ub_test_python != x_no; then

-          CPPFLAGS="$PYTHON_CPPFLAGS"

-        fi

-        ub_have_python=yes

- -      PC_PY_DEPENDENCY="python"

- +      PKG_PROG_PKG_CONFIG

- +      PKG_CHECK_EXISTS(["python${PY_MAJOR_VERSION}"],

- +                       [PC_PY_DEPENDENCY="python${PY_MAJOR_VERSION}"],

- +                       [PC_PY_DEPENDENCY="python"])

-        AC_SUBST(PC_PY_DEPENDENCY)

-  

-        # Check for SWIG

- -- 

- 2.14.4

- 

@@ -1,31 +0,0 @@ 

- From bca54a8b252d4a75e940424dc761c6a4e487eb84 Mon Sep 17 00:00:00 2001

- From: Wouter Wijngaards <wouter@nlnetlabs.nl>

- Date: Wed, 27 Jun 2018 06:07:31 +0000

- Subject: [PATCH 2/2] =?UTF-8?q?-=20Patch,=20do=20not=20export=20python=20f?=

-  =?UTF-8?q?rom=20pkg-config,=20from=20Petr=20Men=C5=A1=C3=ADk.?=

- MIME-Version: 1.0

- Content-Type: text/plain; charset=UTF-8

- Content-Transfer-Encoding: 8bit

- 

- git-svn-id: file:///svn/unbound/trunk@4758 be551aaa-1e26-0410-a405-d3ace91eadb9

- ---

-  contrib/libunbound.pc.in | 3 ++-

-  1 file changed, 2 insertions(+), 1 deletion(-)

- 

- diff --git a/contrib/libunbound.pc.in b/contrib/libunbound.pc.in

- index 0cb9f875..810c5713 100644

- --- a/contrib/libunbound.pc.in

- +++ b/contrib/libunbound.pc.in

- @@ -7,7 +7,8 @@ Name: unbound

-  Description: Library with validating, recursive, and caching DNS resolver

-  URL: http://www.unbound.net

-  Version: @PACKAGE_VERSION@

- -Requires: @PC_LIBEVENT_DEPENDENCY@ @PC_PY_DEPENDENCY@

- +Requires: libcrypto libssl @PC_LIBEVENT_DEPENDENCY@

- +Requires.private: @PC_PY_DEPENDENCY@

-  Libs: -L${libdir} -lunbound -lssl -lcrypto

-  Libs.private: @SSLLIB@ @LIBS@

-  Cflags: -I${includedir} 

- -- 

- 2.14.4

- 

@@ -1,36 +0,0 @@ 

- From 377d5b426a30fc915cf7905786f93c0ec89845b7 Mon Sep 17 00:00:00 2001

- From: Wouter Wijngaards <wouter@nlnetlabs.nl>

- Date: Tue, 25 Sep 2018 09:01:13 +0000

- Subject: [PATCH] - Add SSL cleanup for tcp timeout.

- 

- git-svn-id: file:///svn/unbound/trunk@4915 be551aaa-1e26-0410-a405-d3ace91eadb9

- ---

-  services/outside_network.c | 11 +++++++++++

-  1 files changed, 9 insertions(+)

- diff --git a/services/outside_network.c b/services/outside_network.c

- index 5700ef8..b52cdab 100644

- --- a/services/outside_network.c

- +++ b/services/outside_network.c

- @@ -373,6 +373,8 @@ outnet_tcp_take_into_use(struct waiting_tcp* w, uint8_t* pkt, size_t pkt_len)

-                          if(!SSL_set1_host(pend->c->ssl, w->tls_auth_name)) {

-                                  log_err("SSL_set1_host failed");

-  				pend->c->fd = s;

- +				SSL_free(pend->c->ssl);

- +				pend->c->ssl = NULL;

-  				comm_point_close(pend->c);

-  				return 0;

-  			}

- @@ -1258,6 +1260,13 @@ outnet_tcptimer(void* arg)

-  	} else {

-  		/* it was in use */

-  		struct pending_tcp* pend=(struct pending_tcp*)w->next_waiting;

- +		if(pend->c->ssl) {

- +#ifdef HAVE_SSL

- +			SSL_shutdown(pend->c->ssl);

- +			SSL_free(pend->c->ssl);

- +			pend->c->ssl = NULL;

- +#endif

- +		}

-  		comm_point_close(pend->c);

-  		pend->query = NULL;

-  		pend->next_free = outnet->tcp_free;

@@ -1,553 +0,0 @@ 

- diff --git a/daemon/worker.c b/daemon/worker.c

- index 44a989a..3acecc1 100644

- --- a/daemon/worker.c

- +++ b/daemon/worker.c

- @@ -1193,7 +1193,7 @@ worker_handle_request(struct comm_point* c, void* arg, int error,

-  	if(worker->env.cfg->log_queries) {

-  		char ip[128];

-  		addr_to_str(&repinfo->addr, repinfo->addrlen, ip, sizeof(ip));

- -		log_nametypeclass(0, ip, qinfo.qname, qinfo.qtype, qinfo.qclass);

- +		log_query_in(ip, qinfo.qname, qinfo.qtype, qinfo.qclass);

-  	}

-  	if(qinfo.qtype == LDNS_RR_TYPE_AXFR || 

-  		qinfo.qtype == LDNS_RR_TYPE_IXFR) {

- diff --git a/doc/Changelog b/doc/Changelog

- index 3d05ae5..bb74461 100644

- --- a/doc/Changelog

- +++ b/doc/Changelog

- @@ -1,3 +1,15 @@

- +30 November 2018: Wouter

- +	- log-tag-queryreply: yes in unbound.conf tags the log-queries and

- +	  log-replies in the log file for easier log filter maintenance.

- +

- +21 August 2018: Wouter

- +	- log-local-actions: yes option for unbound.conf that logs all the

- +	  local zone actions, a patch from Saksham Manchanda (Secure64).

- +

- +17 August 2018: Wouter

- +	- log-servfail: yes prints log lines that say why queries are

- +	  returning SERVFAIL to clients.

- +

-  19 June 2018: Wouter

-  	- Fix for unbound-control on Windows and set TCP socket parameters

-  	  more closely.

- diff --git a/doc/example.conf.in b/doc/example.conf.in

- index be83bda..aa06cee 100644

- --- a/doc/example.conf.in

- +++ b/doc/example.conf.in

- @@ -309,6 +309,17 @@ server:

-  	# timetoresolve, fromcache and responsesize.

-  	# log-replies: no

-  

- +	# log with tag 'query' and 'reply' instead of 'info' for

- +	# filtering log-queries and log-replies from the log.

- +	# log-tag-queryreply: no

- +

- +	# log the local-zone actions, like local-zone type inform is enabled

- +	# also for the other local zone types.

- +	# log-local-actions: no

- +

- +	# print log lines that say why queries return SERVFAIL to clients.

- +	# log-servfail: no

- +

-  	# the pid file. Can be an absolute path outside of chroot/work dir.

-  	# pidfile: "@UNBOUND_PIDFILE@"

-  

- diff --git a/doc/unbound.conf.5.in b/doc/unbound.conf.5.in

- index 9167a5a..b73bc70 100644

- --- a/doc/unbound.conf.5.in

- +++ b/doc/unbound.conf.5.in

- @@ -618,6 +618,21 @@ Default is no.  Note that it takes time to print these

-  lines which makes the server (significantly) slower.  Odd (nonprintable)

-  characters in names are printed as '?'.

-  .TP

- +.B log\-tag\-queryreply: \fI<yes or no>

- +Prints the word 'query' and 'reply' with log\-queries and log\-replies.

- +This makes filtering logs easier.  The default is off (for backwards

- +compatibility).

- +.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

- +types of local zones.

- +.TP

- +.B log\-servfail: \fI<yes or no>

- +Print log lines that say why queries return SERVFAIL to clients.

- +This is separate from the verbosity debug logs, much smaller, and printed

- +at the error level, not the info level of debug info from verbosity.

- +.TP

-  .B pidfile: \fI<filename>

-  The process id is written to the file. Default is "@UNBOUND_PIDFILE@".

-  So,

- diff --git a/services/localzone.c b/services/localzone.c

- index 0f60817..a85619b 100644

- --- a/services/localzone.c

- +++ b/services/localzone.c

- @@ -1459,7 +1459,7 @@ lz_inform_print(struct local_zone* z, struct query_info* qinfo,

-  	uint16_t port = ntohs(((struct sockaddr_in*)&repinfo->addr)->sin_port);

-  	dname_str(z->name, zname);

-  	addr_to_str(&repinfo->addr, repinfo->addrlen, ip, sizeof(ip));

- -	snprintf(txt, sizeof(txt), "%s inform %s@%u", zname, ip,

- +	snprintf(txt, sizeof(txt), "%s %s %s@%u", zname, local_zone_type2str(z->type), ip,

-  		(unsigned)port);

-  	log_nametypeclass(0, txt, qinfo->qname, qinfo->qtype, qinfo->qclass);

-  }

- @@ -1576,7 +1576,8 @@ local_zones_answer(struct local_zones* zones, struct module_env* env,

-  			z->override_tree, &tag, tagname, num_tags);

-  		lock_rw_unlock(&zones->lock);

-  	}

- -	if((lzt == local_zone_inform || lzt == local_zone_inform_deny)

- +	if((env->cfg->log_local_actions ||

- +		lzt == local_zone_inform || lzt == local_zone_inform_deny)

-  		&& repinfo)

-  		lz_inform_print(z, qinfo, repinfo);

-  

- diff --git a/services/mesh.c b/services/mesh.c

- index 41aba74..55c1947 100644

- --- a/services/mesh.c

- +++ b/services/mesh.c

- @@ -977,7 +977,7 @@ mesh_do_callback(struct mesh_state* m, int rcode, struct reply_info* rep,

-  		rcode = LDNS_RCODE_SERVFAIL;

-  	if(!rcode && (rep->security == sec_status_bogus ||

-  		rep->security == sec_status_secure_sentinel_fail)) {

- -		if(!(reason = errinf_to_str(&m->s)))

- +		if(!(reason = errinf_to_str_bogus(&m->s)))

-  			rcode = LDNS_RCODE_SERVFAIL;

-  	}

-  	/* send the reply */

- @@ -1148,6 +1148,15 @@ void mesh_query_done(struct mesh_state* mstate)

-  	struct mesh_cb* c;

-  	struct reply_info* rep = (mstate->s.return_msg?

-  		mstate->s.return_msg->rep:NULL);

- +	if((mstate->s.return_rcode == LDNS_RCODE_SERVFAIL ||

- +		(rep && FLAGS_GET_RCODE(rep->flags) == LDNS_RCODE_SERVFAIL))

- +		&& mstate->s.env->cfg->log_servfail

- +		&& !mstate->s.env->cfg->val_log_squelch) {

- +			char* err = errinf_to_str_servfail(&mstate->s);

- +			if(err)

- +				log_err("%s", err);

- +			free(err);

- +	}

-  	for(r = mstate->reply_list; r; r = r->next) {

-  		/* if a response-ip address block has been stored the

-  		 *  information should be logged for each client. */

- diff --git a/util/config_file.c b/util/config_file.c

- index b061760..68a0a15 100644

- --- a/util/config_file.c

- +++ b/util/config_file.c

- @@ -115,6 +115,9 @@ config_create(void)

-  	cfg->log_time_ascii = 0;

-  	cfg->log_queries = 0;

-  	cfg->log_replies = 0;

- +	cfg->log_tag_queryreply = 0;

- +	cfg->log_local_actions = 0;

- +	cfg->log_servfail = 0;

-  #ifndef USE_WINSOCK

-  #  ifdef USE_MINI_EVENT

-  	/* select max 1024 sockets */

- @@ -540,6 +543,9 @@ int config_set_option(struct config_file* cfg, const char* opt,

-  	else S_YNO("val-log-squelch:", val_log_squelch)

-  	else S_YNO("log-queries:", log_queries)

-  	else S_YNO("log-replies:", log_replies)

- +	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("val-permissive-mode:", val_permissive_mode)

-  	else S_YNO("aggressive-nsec:", aggressive_nsec)

-  	else S_YNO("ignore-cd-flag:", ignore_cd)

- @@ -893,6 +899,9 @@ config_get_option(struct config_file* cfg, const char* opt,

-  	else O_STR(opt, "logfile", logfile)

-  	else O_YNO(opt, "log-queries", log_queries)

-  	else O_YNO(opt, "log-replies", log_replies)

- +	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_STR(opt, "pidfile", pidfile)

-  	else O_YNO(opt, "hide-identity", hide_identity)

-  	else O_YNO(opt, "hide-version", hide_version)

- @@ -1845,6 +1854,7 @@ config_apply(struct config_file* config)

-  	EDNS_ADVERTISED_SIZE = (uint16_t)config->edns_buffer_size;

-  	MINIMAL_RESPONSES = config->minimal_responses;

-  	RRSET_ROUNDROBIN = config->rrset_roundrobin;

- +	LOG_TAG_QUERYREPLY = config->log_tag_queryreply;

-  	log_set_time_asc(config->log_time_ascii);

-  	autr_permit_small_holddown = config->permit_small_holddown;

-  }

- @@ -2220,7 +2230,7 @@ void errinf_origin(struct module_qstate* qstate, struct sock_list *origin)

-  	}

-  }

-  

- -char* errinf_to_str(struct module_qstate* qstate)

- +char* errinf_to_str_bogus(struct module_qstate* qstate)

-  {

-  	char buf[20480];

-  	char* p = buf;

- @@ -2245,6 +2255,31 @@ char* errinf_to_str(struct module_qstate* qstate)

-  	return p;

-  }

-  

- +char* errinf_to_str_servfail(struct module_qstate* qstate)

- +{

- +    char buf[20480];

- +    char* p = buf;

- +    size_t left = sizeof(buf);

- +    struct config_strlist* s;

- +    char dname[LDNS_MAX_DOMAINLEN+1];

- +    char t[16], c[16];

- +    sldns_wire2str_type_buf(qstate->qinfo.qtype, t, sizeof(t));

- +    sldns_wire2str_class_buf(qstate->qinfo.qclass, c, sizeof(c));

- +    dname_str(qstate->qinfo.qname, dname);

- +    snprintf(p, left, "SERVFAIL <%s %s %s>:", dname, t, c);

- +    left -= strlen(p); p += strlen(p);

- +    if(!qstate->errinf)

- +        snprintf(p, left, " misc failure");

- +    else for(s=qstate->errinf; s; s=s->next) {

- +        snprintf(p, left, " %s", s->str);

- +        left -= strlen(p); p += strlen(p);

- +    }

- +    p = strdup(buf);

- +    if(!p)

- +        log_err("malloc failure in errinf_to_str");

- +    return p;

- +}

- +

-  void errinf_rrset(struct module_qstate* qstate, struct ub_packed_rrset_key *rr)

-  {

-  	char buf[1024];

- diff --git a/util/config_file.h b/util/config_file.h

- index 4206eb9..1e7f402 100644

- --- a/util/config_file.h

- +++ b/util/config_file.h

- @@ -268,6 +268,12 @@ struct config_file {

-  	int log_queries;

-  	/** log replies with one line per reply */

-  	int log_replies;

- +	/** tag log_queries and log_replies for filtering */

- +	int log_tag_queryreply;

- +	/** log every local-zone hit **/

- +	int log_local_actions;

- +	/** log servfails with a reason */

- +	int log_servfail;

-  	/** log identity to report */

-  	char* log_identity;

-  

- @@ -1070,7 +1076,15 @@ void errinf_dname(struct module_qstate* qstate, const char* str,

-   * @return string or NULL on malloc failure (already logged).

-   *    This string is malloced and has to be freed by caller.

-   */

- -char* errinf_to_str(struct module_qstate* qstate);

- +char* errinf_to_str_bogus(struct module_qstate* qstate);

- +

- +/**

- + * Create error info in string.  For other servfails.

- + * @param qstate: query state.

- + * @return string or NULL on malloc failure (already logged).

- + *    This string is malloced and has to be freed by caller.

- + */

- +char* errinf_to_str_servfail(struct module_qstate* qstate);

-  

-  /**

-   * Used during options parsing

- diff --git a/util/configlexer.lex b/util/configlexer.lex

- index 6124e32..9b22db1 100644

- --- a/util/configlexer.lex

- +++ b/util/configlexer.lex

- @@ -366,6 +366,9 @@ log-identity{COLON}		{ YDVAR(1, VAR_LOG_IDENTITY) }

-  log-time-ascii{COLON}		{ YDVAR(1, VAR_LOG_TIME_ASCII) }

-  log-queries{COLON}		{ YDVAR(1, VAR_LOG_QUERIES) }

-  log-replies{COLON}		{ YDVAR(1, VAR_LOG_REPLIES) }

- +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) }

-  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) }

- diff --git a/util/configparser.y b/util/configparser.y

- index e34665a..4b23a71 100644

- --- a/util/configparser.y

- +++ b/util/configparser.y

- @@ -106,7 +106,7 @@ extern struct config_parser_state* cfg_parser;

-  %token VAR_AUTO_TRUST_ANCHOR_FILE VAR_KEEP_MISSING VAR_ADD_HOLDDOWN 

-  %token VAR_DEL_HOLDDOWN VAR_SO_RCVBUF VAR_EDNS_BUFFER_SIZE VAR_PREFETCH

-  %token VAR_PREFETCH_KEY VAR_SO_SNDBUF VAR_SO_REUSEPORT VAR_HARDEN_BELOW_NXDOMAIN

- -%token VAR_IGNORE_CD_FLAG VAR_LOG_QUERIES VAR_LOG_REPLIES

- +%token VAR_IGNORE_CD_FLAG VAR_LOG_QUERIES VAR_LOG_REPLIES VAR_LOG_LOCAL_ACTIONS

-  %token VAR_TCP_UPSTREAM VAR_SSL_UPSTREAM

-  %token VAR_SSL_SERVICE_KEY VAR_SSL_SERVICE_PEM VAR_SSL_PORT VAR_FORWARD_FIRST

-  %token VAR_STUB_SSL_UPSTREAM VAR_FORWARD_SSL_UPSTREAM VAR_TLS_CERT_BUNDLE

- @@ -158,6 +158,8 @@ extern struct config_parser_state* cfg_parser;

-  %token VAR_AUTH_ZONE VAR_ZONEFILE VAR_MASTER VAR_URL VAR_FOR_DOWNSTREAM

-  %token VAR_FALLBACK_ENABLED VAR_TLS_ADDITIONAL_PORT VAR_LOW_RTT VAR_LOW_RTT_PERMIL

-  %token VAR_ALLOW_NOTIFY VAR_TLS_WIN_CERT

- +%token VAR_FORWARD_NO_CACHE VAR_STUB_NO_CACHE VAR_LOG_SERVFAIL

- +%token VAR_UNKNOWN_SERVER_TIME_LIMIT VAR_LOG_TAG_QUERYREPLY

-  

-  %%

-  toplevelvars: /* empty */ | toplevelvars toplevelvar ;

- @@ -217,6 +219,7 @@ content_server: server_num_threads | server_verbosity | server_port |

-  	server_edns_buffer_size | server_prefetch | server_prefetch_key |

-  	server_so_sndbuf | server_harden_below_nxdomain | server_ignore_cd_flag |

-  	server_log_queries | server_log_replies | server_tcp_upstream | server_ssl_upstream |

- +	server_log_local_actions |

-  	server_ssl_service_key | server_ssl_service_pem | server_ssl_port |

-  	server_minimal_responses | server_rrset_roundrobin | server_max_udp_size |

-  	server_so_reuseport | server_delay_close |

- @@ -249,7 +252,9 @@ content_server: server_num_threads | server_verbosity | server_port |

-  	server_ipsecmod_whitelist | server_ipsecmod_strict |

-  	server_udp_upstream_without_downstream | server_aggressive_nsec |

-  	server_tls_cert_bundle | server_tls_additional_port | server_low_rtt |

- -	server_low_rtt_permil | server_tls_win_cert

- +	server_low_rtt_permil | server_tls_win_cert |

- +	server_tcp_connection_limit | server_log_servfail |

- +	server_unknown_server_time_limit | server_log_tag_queryreply

-  	;

-  stubstart: VAR_STUB_ZONE

-  	{

- @@ -764,6 +769,33 @@ server_log_replies: VAR_LOG_REPLIES STRING_ARG

-    	free($2);

-    }

-    ;

- +server_log_tag_queryreply: VAR_LOG_TAG_QUERYREPLY STRING_ARG

- +  {

- +    OUTYY(("P(server_log_tag_queryreply:%s)\n", $2));

- +    if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0)

- +        yyerror("expected yes or no.");

- +    else cfg_parser->cfg->log_tag_queryreply = (strcmp($2, "yes")==0);

- +    free($2);

- +  }

- +  ;

- +server_log_servfail: VAR_LOG_SERVFAIL STRING_ARG

- +  {

- +	OUTYY(("P(server_log_servfail:%s)\n", $2));

- +	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_local_actions: VAR_LOG_LOCAL_ACTIONS STRING_ARG

- +  {

- +	OUTYY(("P(server_log_local_actions:%s)\n", $2));

- +	if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0)

- +		yyerror("expected yes or no.");

- +	else cfg_parser->cfg->log_local_actions = (strcmp($2, "yes")==0);

- +	free($2);

- +  }

- +  ;

-  server_chroot: VAR_CHROOT STRING_ARG

-  	{

-  		OUTYY(("P(server_chroot:%s)\n", $2));

- diff --git a/util/data/msgreply.c b/util/data/msgreply.c

- index 772f5d1..df2131c 100644

- --- a/util/data/msgreply.c

- +++ b/util/data/msgreply.c

- @@ -844,7 +844,9 @@ log_reply_info(enum verbosity_value v, struct query_info *qinf,

-  	addr_to_str(addr, addrlen, clientip_buf, sizeof(clientip_buf));

-  	if(rcode == LDNS_RCODE_FORMERR)

-  	{

- -		log_info("%s - - - %s - - - ", clientip_buf, rcode_buf);

- +		if(LOG_TAG_QUERYREPLY)

- +			log_reply("%s - - - %s - - - ", clientip_buf, rcode_buf);

- +		else log_info("%s - - - %s - - - ", clientip_buf, rcode_buf);

-  	} else {

-  		if(qinf->qname)

-  			dname_str(qinf->qname, qname_buf);

- @@ -852,7 +854,11 @@ log_reply_info(enum verbosity_value v, struct query_info *qinf,

-  		pktlen = sldns_buffer_limit(rmsg);

-  		sldns_wire2str_type_buf(qinf->qtype, type_buf, sizeof(type_buf));

-  		sldns_wire2str_class_buf(qinf->qclass, class_buf, sizeof(class_buf));

- -		log_info("%s %s %s %s %s " ARG_LL "d.%6.6d %d %d",

- +		if(LOG_TAG_QUERYREPLY)

- +			log_reply("%s %s %s %s %s " ARG_LL "d.%6.6d %d %d",

- +				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",

-  			clientip_buf, qname_buf, type_buf, class_buf,

-  			rcode_buf, (long long)dur.tv_sec, (int)dur.tv_usec, cached, (int)pktlen);

-  	}

- diff --git a/util/log.c b/util/log.c

- index 43dd572..fff4319 100644

- --- a/util/log.c

- +++ b/util/log.c

- @@ -391,6 +391,24 @@ log_hex(const char* msg, void* data, size_t length)

-  	log_hex_f(verbosity, msg, data, length);

-  }

-  

- +void

- +log_query(const char *format, ...)

- +{

- +	va_list args;

- +	va_start(args, format);

- +	log_vmsg(LOG_INFO, "query", format, args);

- +	va_end(args);

- +}

- +

- +void

- +log_reply(const char *format, ...)

- +{

- +	va_list args;

- +	va_start(args, format);

- +	log_vmsg(LOG_INFO, "reply", format, args);

- +	va_end(args);

- +}

- +

-  void log_buf(enum verbosity_value level, const char* msg, sldns_buffer* buf)

-  {

-  	if(verbosity < level)

- diff --git a/util/log.h b/util/log.h

- index 7bc3d9e..172cd01 100644

- --- a/util/log.h

- +++ b/util/log.h

- @@ -160,6 +160,20 @@ void log_warn(const char* format, ...) ATTR_FORMAT(printf, 1, 2);

-   */

-  void log_hex(const char* msg, void* data, size_t length);

-  

- +/**

- + * Log query.

- + * Pass printf formatted arguments. No trailing newline is needed.

- + * @param format: printf-style format string. Arguments follow.

- + */

- +void log_query(const char* format, ...) ATTR_FORMAT(printf, 1, 2);

- +

- +/**

- + * Log reply.

- + * Pass printf formatted arguments. No trailing newline is needed.

- + * @param format: printf-style format string. Arguments follow.

- + */

- +void log_reply(const char* format, ...) ATTR_FORMAT(printf, 1, 2);

- +

-  /**

-   * Easy alternative for log_hex, takes a sldns_buffer.

-   * @param level: verbosity level for this message, compared to global 

- diff --git a/util/net_help.c b/util/net_help.c

- index a193c36..617a896 100644

- --- a/util/net_help.c

- +++ b/util/net_help.c

- @@ -67,6 +67,9 @@ int MINIMAL_RESPONSES = 0;

-  /** rrset order roundrobin: default is no */

-  int RRSET_ROUNDROBIN = 0;

-  

- +/** log tag queries with name instead of 'info' for filtering */

- +int LOG_TAG_QUERYREPLY = 0;

- +

-  /* returns true is string addr is an ip6 specced address */

-  int

-  str_is_ip6(const char* str)

- @@ -335,7 +338,7 @@ log_nametypeclass(enum verbosity_value v, const char* str, uint8_t* name,

-  {

-  	char buf[LDNS_MAX_DOMAINLEN+1];

-  	char t[12], c[12];

- -	const char *ts, *cs; 

- +	const char *ts, *cs;

-  	if(verbosity < v)

-  		return;

-  	dname_str(name, buf);

- @@ -361,6 +364,37 @@ log_nametypeclass(enum verbosity_value v, const char* str, uint8_t* name,

-  	log_info("%s %s %s %s", str, buf, ts, cs);

-  }

-  

- +void

- +log_query_in(const char* str, uint8_t* name, uint16_t type, uint16_t dclass)

- +{

- +    char buf[LDNS_MAX_DOMAINLEN+1];

- +    char t[12], c[12];

- +    const char *ts, *cs;

- +    dname_str(name, buf);

- +    if(type == LDNS_RR_TYPE_TSIG) ts = "TSIG";

- +    else if(type == LDNS_RR_TYPE_IXFR) ts = "IXFR";

- +    else if(type == LDNS_RR_TYPE_AXFR) ts = "AXFR";

- +    else if(type == LDNS_RR_TYPE_MAILB) ts = "MAILB";

- +    else if(type == LDNS_RR_TYPE_MAILA) ts = "MAILA";

- +    else if(type == LDNS_RR_TYPE_ANY) ts = "ANY";

- +    else if(sldns_rr_descript(type) && sldns_rr_descript(type)->_name)

- +        ts = sldns_rr_descript(type)->_name;

- +    else {

- +        snprintf(t, sizeof(t), "TYPE%d", (int)type);

- +        ts = t;

- +    }

- +    if(sldns_lookup_by_id(sldns_rr_classes, (int)dclass) &&

- +        sldns_lookup_by_id(sldns_rr_classes, (int)dclass)->name)

- +        cs = sldns_lookup_by_id(sldns_rr_classes, (int)dclass)->name;

- +    else {

- +        snprintf(c, sizeof(c), "CLASS%d", (int)dclass);

- +        cs = c;

- +    }

- +    if(LOG_TAG_QUERYREPLY)

- +            log_query("%s %s %s %s", str, buf, ts, cs);

- +    else    log_info("%s %s %s %s", str, buf, ts, cs);

- +}

- +

-  void log_name_addr(enum verbosity_value v, const char* str, uint8_t* zone, 

-  	struct sockaddr_storage* addr, socklen_t addrlen)

-  {

- diff --git a/util/net_help.h b/util/net_help.h

- index de2e1ac..f2e0e43 100644

- --- a/util/net_help.h

- +++ b/util/net_help.h

- @@ -99,6 +99,9 @@ extern int MINIMAL_RESPONSES;

-  /** rrset order roundrobin */

-  extern int RRSET_ROUNDROBIN;

-  

- +/** log tag queries with name instead of 'info' for filtering */

- +extern int LOG_TAG_QUERYREPLY;

- +

-  /**

-   * See if string is ip4 or ip6.

-   * @param str: IP specification.

- @@ -235,6 +238,12 @@ void sockaddr_store_port(struct sockaddr_storage* addr, socklen_t addrlen,

-  void log_nametypeclass(enum verbosity_value v, const char* str, 

-  	uint8_t* name, uint16_t type, uint16_t dclass);

-  

- +/**

- + * Like log_nametypeclass, but logs with log_query for query logging

- + */

- +void log_query_in(const char* str, uint8_t* name, uint16_t type,

- +       uint16_t dclass);

- +

-  /**

-   * Compare two sockaddrs. Imposes an ordering on the addresses.

-   * Compares address and port.

- diff --git a/validator/val_kcache.c b/validator/val_kcache.c

- index 22070cc..e0b88b6 100644

- --- a/validator/val_kcache.c

- +++ b/validator/val_kcache.c

- @@ -89,7 +89,7 @@ key_cache_insert(struct key_cache* kcache, struct key_entry_key* kkey,

-  	if(key_entry_isbad(k) && qstate->errinf &&

-  		qstate->env->cfg->val_log_level >= 2) {

-  		/* on malloc failure there is simply no reason string */

- -		key_entry_set_reason(k, errinf_to_str(qstate));

- +		key_entry_set_reason(k, errinf_to_str_bogus(qstate));

-  	}

-  	key_entry_hash(k);

-  	slabhash_insert(kcache->slab, k->entry.hash, &k->entry, 

- diff --git a/validator/validator.c b/validator/validator.c

- index 5777b29..2d9cc17 100644

- --- a/validator/validator.c

- +++ b/validator/validator.c

- @@ -2227,13 +2227,15 @@ processFinished(struct module_qstate* qstate, struct val_qstate* vq,

-  		vq->orig_msg->rep->ttl = ve->bogus_ttl;

-  		vq->orig_msg->rep->prefetch_ttl = 

-  			PREFETCH_TTL_CALC(vq->orig_msg->rep->ttl);

- -		if(qstate->env->cfg->val_log_level >= 1 &&

- +		if((qstate->env->cfg->val_log_level >= 1 ||

- +			qstate->env->cfg->log_servfail) &&

-  			!qstate->env->cfg->val_log_squelch) {

- -			if(qstate->env->cfg->val_log_level < 2)

- +            if(qstate->env->cfg->val_log_level < 2 &&

- +				!qstate->env->cfg->log_servfail)

-  				log_query_info(0, "validation failure",

-  					&qstate->qinfo);

-  			else {

- -				char* err = errinf_to_str(qstate);

- +				char* err = errinf_to_str_bogus(qstate);

-  				if(err) log_info("%s", err);

-  				free(err);

-  			}

- @@ -2332,6 +2334,7 @@ processDLVLookup(struct module_qstate* qstate, struct val_qstate* vq,

-  

-  	if(vq->dlv_status == dlv_error) {

-  		verbose(VERB_QUERY, "failed DLV lookup");

- +		errinf(qstate, "failed DLV lookup");

-  		return val_error(qstate, id);

-  	} else if(vq->dlv_status == dlv_success) {

-  		uint8_t* nm;

@@ -1,944 +0,0 @@ 

- diff --git a/iterator/iter_delegpt.c b/iterator/iter_delegpt.c

- index f88b3e1..522e0e9 100644

- --- a/iterator/iter_delegpt.c

- +++ b/iterator/iter_delegpt.c

- @@ -84,7 +84,7 @@ struct delegpt* delegpt_copy(struct delegpt* dp, struct regional* region)

-  	}

-  	for(a = dp->target_list; a; a = a->next_target) {

-  		if(!delegpt_add_addr(copy, region, &a->addr, a->addrlen, 

- -			a->bogus, a->lame, a->tls_auth_name))

- +           a->bogus, a->lame, a->tls_auth_name, NULL))

-  			return NULL;

-  	}

-  	return copy;

- @@ -161,7 +161,7 @@ delegpt_find_addr(struct delegpt* dp, struct sockaddr_storage* addr,

-  int 

-  delegpt_add_target(struct delegpt* dp, struct regional* region, 

-  	uint8_t* name, size_t namelen, struct sockaddr_storage* addr, 

- -	socklen_t addrlen, uint8_t bogus, uint8_t lame)

- +   socklen_t addrlen, uint8_t bogus, uint8_t lame, int* additions)

-  {

-  	struct delegpt_ns* ns = delegpt_find_ns(dp, name, namelen);

-  	log_assert(!dp->dp_type_mlc);

- @@ -176,13 +176,14 @@ delegpt_add_target(struct delegpt* dp, struct regional* region,

-  		if(ns->got4 && ns->got6)

-  			ns->resolved = 1;

-  	}

- -	return delegpt_add_addr(dp, region, addr, addrlen, bogus, lame, NULL);

- +	return delegpt_add_addr(dp, region, addr, addrlen, bogus, lame, NULL,

- +        additions);

-  }

-  

-  int 

-  delegpt_add_addr(struct delegpt* dp, struct regional* region, 

-  	struct sockaddr_storage* addr, socklen_t addrlen, uint8_t bogus, 

- -	uint8_t lame, char* tls_auth_name)

- +	uint8_t lame, char* tls_auth_name, int* additions)

-  {

-  	struct delegpt_addr* a;

-  	log_assert(!dp->dp_type_mlc);

- @@ -195,6 +196,9 @@ delegpt_add_addr(struct delegpt* dp, struct regional* region,

-  		return 1;

-  	}

-  

- +    if(additions)

- +        *additions = 1;

- +

-  	a = (struct delegpt_addr*)regional_alloc(region,

-  		sizeof(struct delegpt_addr));

-  	if(!a)

- @@ -382,10 +386,10 @@ delegpt_from_message(struct dns_msg* msg, struct regional* region)

-  			continue;

-  

-  		if(ntohs(s->rk.type) == LDNS_RR_TYPE_A) {

- -			if(!delegpt_add_rrset_A(dp, region, s, 0))

- +			if(!delegpt_add_rrset_A(dp, region, s, 0, NULL))

-  				return NULL;

-  		} else if(ntohs(s->rk.type) == LDNS_RR_TYPE_AAAA) {

- -			if(!delegpt_add_rrset_AAAA(dp, region, s, 0))

- +			if(!delegpt_add_rrset_AAAA(dp, region, s, 0, NULL))

-  				return NULL;

-  		}

-  	}

- @@ -416,7 +420,7 @@ delegpt_rrset_add_ns(struct delegpt* dp, struct regional* region,

-  

-  int 

-  delegpt_add_rrset_A(struct delegpt* dp, struct regional* region,

- -	struct ub_packed_rrset_key* ak, uint8_t lame)

- +	struct ub_packed_rrset_key* ak, uint8_t lame, int* additions)

-  {

-          struct packed_rrset_data* d=(struct packed_rrset_data*)ak->entry.data;

-          size_t i;

- @@ -432,7 +436,7 @@ delegpt_add_rrset_A(struct delegpt* dp, struct regional* region,

-                  memmove(&sa.sin_addr, d->rr_data[i]+2, INET_SIZE);

-                  if(!delegpt_add_target(dp, region, ak->rk.dname,

-                          ak->rk.dname_len, (struct sockaddr_storage*)&sa,

- -                        len, (d->security==sec_status_bogus), lame))

- +                        len, (d->security==sec_status_bogus), lame, additions))

-                          return 0;

-          }

-          return 1;

- @@ -440,7 +444,7 @@ delegpt_add_rrset_A(struct delegpt* dp, struct regional* region,

-  

-  int 

-  delegpt_add_rrset_AAAA(struct delegpt* dp, struct regional* region,

- -	struct ub_packed_rrset_key* ak, uint8_t lame)

- +	struct ub_packed_rrset_key* ak, uint8_t lame, int* additions)

-  {

-          struct packed_rrset_data* d=(struct packed_rrset_data*)ak->entry.data;

-          size_t i;

- @@ -456,7 +460,7 @@ delegpt_add_rrset_AAAA(struct delegpt* dp, struct regional* region,

-                  memmove(&sa.sin6_addr, d->rr_data[i]+2, INET6_SIZE);

-                  if(!delegpt_add_target(dp, region, ak->rk.dname,

-                          ak->rk.dname_len, (struct sockaddr_storage*)&sa,

- -                        len, (d->security==sec_status_bogus), lame))

- +                        len, (d->security==sec_status_bogus), lame, additions))

-                          return 0;

-          }

-          return 1;

- @@ -464,20 +468,32 @@ delegpt_add_rrset_AAAA(struct delegpt* dp, struct regional* region,

-  

-  int 

-  delegpt_add_rrset(struct delegpt* dp, struct regional* region,

- -        struct ub_packed_rrset_key* rrset, uint8_t lame)

- +        struct ub_packed_rrset_key* rrset, uint8_t lame, int* additions)

-  {

-  	if(!rrset)

-  		return 1;

-  	if(ntohs(rrset->rk.type) == LDNS_RR_TYPE_NS)

-  		return delegpt_rrset_add_ns(dp, region, rrset, lame);

-  	else if(ntohs(rrset->rk.type) == LDNS_RR_TYPE_A)

- -		return delegpt_add_rrset_A(dp, region, rrset, lame);

- +		return delegpt_add_rrset_A(dp, region, rrset, lame, additions);

-  	else if(ntohs(rrset->rk.type) == LDNS_RR_TYPE_AAAA)

- -		return delegpt_add_rrset_AAAA(dp, region, rrset, lame);

- +		return delegpt_add_rrset_AAAA(dp, region, rrset, lame, additions);

-  	log_warn("Unknown rrset type added to delegpt");

-  	return 1;

-  }

-  

- +void delegpt_mark_neg(struct delegpt_ns* ns, uint16_t qtype)

- +{

- +    if(ns) {

- +        if(qtype == LDNS_RR_TYPE_A)

- +            ns->got4 = 2;

- +        else if(qtype == LDNS_RR_TYPE_AAAA)

- +            ns->got6 = 2;

- +        if(ns->got4 && ns->got6)

- +            ns->resolved = 1;

- +    }

- +}

- +

-  void delegpt_add_neg_msg(struct delegpt* dp, struct msgreply_entry* msg)

-  {

-  	struct reply_info* rep = (struct reply_info*)msg->entry.data;

- @@ -487,14 +503,7 @@ void delegpt_add_neg_msg(struct delegpt* dp, struct msgreply_entry* msg)

-  	if(FLAGS_GET_RCODE(rep->flags) != 0 || rep->an_numrrsets == 0) {

-  		struct delegpt_ns* ns = delegpt_find_ns(dp, msg->key.qname, 

-  			msg->key.qname_len);

- -		if(ns) {

- -			if(msg->key.qtype == LDNS_RR_TYPE_A)

- -				ns->got4 = 1;

- -			else if(msg->key.qtype == LDNS_RR_TYPE_AAAA)

- -				ns->got6 = 1;

- -			if(ns->got4 && ns->got6)

- -				ns->resolved = 1;

- -		}

- +        delegpt_mark_neg(ns, msg->key.qtype);

-  	}

-  }

-  

- diff --git a/iterator/iter_delegpt.h b/iterator/iter_delegpt.h

- index 354bd61..3aded22 100644

- --- a/iterator/iter_delegpt.h

- +++ b/iterator/iter_delegpt.h

- @@ -104,9 +104,10 @@ struct delegpt_ns {

-  	 * and marked true if got4 and got6 are both true.

-  	 */

-  	int resolved;

- -	/** if the ipv4 address is in the delegpt */

- +	/** if the ipv4 address is in the delegpt, 0=not, 1=yes 2=negative,

- +     * negative means it was done, but no content. */

-  	uint8_t got4;

- -	/** if the ipv6 address is in the delegpt */

- +	/** if the ipv6 address is in the delegpt, 0=not, 1=yes 2=negative */

-  	uint8_t got6;

-  	/**

-  	 * If the name is parent-side only and thus dispreferred.

- @@ -213,11 +214,12 @@ int delegpt_rrset_add_ns(struct delegpt* dp, struct regional* regional,

-   * @param addrlen: the length of addr.

-   * @param bogus: security status for the address, pass true if bogus.

-   * @param lame: address is lame.

- + * @param additions: will be set to 1 if a new address is added

-   * @return false on error.

-   */

-  int delegpt_add_target(struct delegpt* dp, struct regional* regional, 

-  	uint8_t* name, size_t namelen, struct sockaddr_storage* addr, 

- -	socklen_t addrlen, uint8_t bogus, uint8_t lame);

- +	socklen_t addrlen, uint8_t bogus, uint8_t lame, int* additions);

-  

-  /**

-   * Add A RRset to delegpt.

- @@ -225,10 +227,11 @@ int delegpt_add_target(struct delegpt* dp, struct regional* regional,

-   * @param regional: where to allocate the info.

-   * @param rrset: RRset A to add.

-   * @param lame: rrset is lame, disprefer it.

- + * @param additions: will be set to 1 if a new address is added

-   * @return 0 on alloc error.

-   */

-  int delegpt_add_rrset_A(struct delegpt* dp, struct regional* regional, 

- -	struct ub_packed_rrset_key* rrset, uint8_t lame);

- +	struct ub_packed_rrset_key* rrset, uint8_t lame, int* additions);

-  

-  /**

-   * Add AAAA RRset to delegpt.

- @@ -236,10 +239,11 @@ int delegpt_add_rrset_A(struct delegpt* dp, struct regional* regional,

-   * @param regional: where to allocate the info.

-   * @param rrset: RRset AAAA to add.

-   * @param lame: rrset is lame, disprefer it.

- + * @param additions: will be set to 1 if a new address is added

-   * @return 0 on alloc error.

-   */

-  int delegpt_add_rrset_AAAA(struct delegpt* dp, struct regional* regional, 

- -	struct ub_packed_rrset_key* rrset, uint8_t lame);

- +	struct ub_packed_rrset_key* rrset, uint8_t lame, int* additions);

-  

-  /**

-   * Add any RRset to delegpt.

- @@ -248,10 +252,11 @@ int delegpt_add_rrset_AAAA(struct delegpt* dp, struct regional* regional,

-   * @param regional: where to allocate the info.

-   * @param rrset: RRset to add, NS, A, AAAA.

-   * @param lame: rrset is lame, disprefer it.

- + * @param additions: will be set to 1 if a new address is added

-   * @return 0 on alloc error.

-   */

-  int delegpt_add_rrset(struct delegpt* dp, struct regional* regional, 

- -	struct ub_packed_rrset_key* rrset, uint8_t lame);

- +	struct ub_packed_rrset_key* rrset, uint8_t lame, int* additions);

-  

-  /**

-   * Add address to the delegation point. No servername is associated or checked.

- @@ -262,11 +267,13 @@ int delegpt_add_rrset(struct delegpt* dp, struct regional* regional,

-   * @param bogus: if address is bogus.

-   * @param lame: if address is lame.

-   * @param tls_auth_name: TLS authentication name (or NULL).

- + * @param additions: will be set to 1 if a new address is added

- + * @return 0 on alloc error.

-   * @return false on error.

-   */

-  int delegpt_add_addr(struct delegpt* dp, struct regional* regional, 

-  	struct sockaddr_storage* addr, socklen_t addrlen,

- -	uint8_t bogus, uint8_t lame, char* tls_auth_name);

- +	uint8_t bogus, uint8_t lame, char* tls_auth_name, int* additions);

-  

-  /** 

-   * Find NS record in name list of delegation point.

- @@ -339,6 +346,14 @@ size_t delegpt_count_targets(struct delegpt* dp);

-  struct delegpt* delegpt_from_message(struct dns_msg* msg, 

-  	struct regional* regional);

-  

- +/**

- +* Mark negative return in delegation point for specific nameserver.

- +* sets the got4 or got6 to negative, updates the ns->resolved.

- +* @param ns: the nameserver in the delegpt.

- +* @param qtype: A or AAAA (host order).

- +*/

- +void delegpt_mark_neg(struct delegpt_ns* ns, uint16_t qtype);

- +

-  /**

-   * Add negative message to delegation point.

-   * @param dp: delegation point.

- diff --git a/iterator/iter_scrub.c b/iterator/iter_scrub.c

- index 12580dc..8230d17 100644

- --- a/iterator/iter_scrub.c

- +++ b/iterator/iter_scrub.c

- @@ -185,8 +185,9 @@ mark_additional_rrset(sldns_buffer* pkt, struct msg_parse* msg,

-  /** Get target name of a CNAME */

-  static int

-  parse_get_cname_target(struct rrset_parse* rrset, uint8_t** sname, 

- -	size_t* snamelen)

- +	size_t* snamelen, sldns_buffer* pkt)

-  {

- +    size_t oldpos, dlen;

-  	if(rrset->rr_count != 1) {

-  		struct rr_parse* sig;

-  		verbose(VERB_ALGO, "Found CNAME rrset with "

- @@ -204,6 +205,19 @@ parse_get_cname_target(struct rrset_parse* rrset, uint8_t** sname,

-  	*sname = rrset->rr_first->ttl_data + sizeof(uint32_t)

-  		+ sizeof(uint16_t); /* skip ttl, rdatalen */

-  	*snamelen = rrset->rr_first->size - sizeof(uint16_t);

- +

- +    if(rrset->rr_first->outside_packet) {

- +        if(!dname_valid(*sname, *snamelen))

- +            return 0;

- +        return 1;

- +    }

- +    oldpos = sldns_buffer_position(pkt);

- +    sldns_buffer_set_position(pkt, (size_t)(*sname - sldns_buffer_begin(pkt)));

- +    dlen = pkt_dname_len(pkt);

- +    sldns_buffer_set_position(pkt, oldpos);

- +    if(dlen == 0)

- +        return 0; /* parse fail on the rdata name */

- +    *snamelen = dlen;

-  	return 1;

-  }

-  

- @@ -215,7 +229,7 @@ synth_cname(uint8_t* qname, size_t qnamelen, struct rrset_parse* dname_rrset,

-  	/* we already know that sname is a strict subdomain of DNAME owner */

-  	uint8_t* dtarg = NULL;

-  	size_t dtarglen;

- -	if(!parse_get_cname_target(dname_rrset, &dtarg, &dtarglen))

- +	if(!parse_get_cname_target(dname_rrset, &dtarg, &dtarglen, pkt))

-  		return 0; 

-  	log_assert(qnamelen > dname_rrset->dname_len);

-  	/* DNAME from com. to net. with qname example.com. -> example.net. */

- @@ -372,7 +386,7 @@ scrub_normalize(sldns_buffer* pkt, struct msg_parse* msg,

-  				/* check next cname */

-  				uint8_t* t = NULL;

-  				size_t tlen = 0;

- -				if(!parse_get_cname_target(nx, &t, &tlen))

- +				if(!parse_get_cname_target(nx, &t, &tlen, pkt))

-  					return 0;

-  				if(dname_pkt_compare(pkt, alias, t) == 0) {

-  					/* it's OK and better capitalized */

- @@ -423,7 +437,7 @@ scrub_normalize(sldns_buffer* pkt, struct msg_parse* msg,

-  				size_t tlen = 0;

-  				if(synth_cname(sname, snamelen, nx, alias,

-  					&aliaslen, pkt) &&

- -					parse_get_cname_target(rrset, &t, &tlen) &&

- +					parse_get_cname_target(rrset, &t, &tlen, pkt) &&

-  			   		dname_pkt_compare(pkt, alias, t) == 0) {

-  					/* the synthesized CNAME equals the

-  					 * current CNAME.  This CNAME is the

- @@ -442,7 +456,7 @@ scrub_normalize(sldns_buffer* pkt, struct msg_parse* msg,

-  			}

-  

-  			/* move to next name in CNAME chain */

- -			if(!parse_get_cname_target(rrset, &sname, &snamelen))

- +			if(!parse_get_cname_target(rrset, &sname, &snamelen, pkt))

-  				return 0;

-  			prev = rrset;

-  			rrset = rrset->rrset_all_next;

- diff --git a/iterator/iter_utils.c b/iterator/iter_utils.c

- index 0a8f770..a107bee 100644

- --- a/iterator/iter_utils.c

- +++ b/iterator/iter_utils.c

- @@ -1008,7 +1008,7 @@ int iter_lookup_parent_glue_from_cache(struct module_env* env,

-  			log_rrset_key(VERB_ALGO, "found parent-side", akey);

-  			ns->done_pside4 = 1;

-  			/* a negative-cache-element has no addresses it adds */

- -			if(!delegpt_add_rrset_A(dp, region, akey, 1))

- +			if(!delegpt_add_rrset_A(dp, region, akey, 1, NULL))

-  				log_err("malloc failure in lookup_parent_glue");

-  			lock_rw_unlock(&akey->entry.lock);

-  		}

- @@ -1020,7 +1020,7 @@ int iter_lookup_parent_glue_from_cache(struct module_env* env,

-  			log_rrset_key(VERB_ALGO, "found parent-side", akey);

-  			ns->done_pside6 = 1;

-  			/* a negative-cache-element has no addresses it adds */

- -			if(!delegpt_add_rrset_AAAA(dp, region, akey, 1))

- +			if(!delegpt_add_rrset_AAAA(dp, region, akey, 1, NULL))

-  				log_err("malloc failure in lookup_parent_glue");

-  			lock_rw_unlock(&akey->entry.lock);

-  		}

- diff --git a/iterator/iterator.c b/iterator/iterator.c

- index 58a9bff..a4ad319 100644

- --- a/iterator/iterator.c

- +++ b/iterator/iterator.c

- @@ -69,6 +69,8 @@

-  #include "sldns/parseutil.h"

-  #include "sldns/sbuffer.h"

-  

- +static void target_count_increase_nx(struct iter_qstate* iq, int num);

- +

-  int 

-  iter_init(struct module_env* env, int id)

-  {

- @@ -147,6 +149,7 @@ iter_new(struct module_qstate* qstate, int id)

-  	iq->sent_count = 0;

-  	iq->ratelimit_ok = 0;

-  	iq->target_count = NULL;

- +    iq->dp_target_count = 0;

-  	iq->wait_priming_stub = 0;

-  	iq->refetch_glue = 0;

-  	iq->dnssec_expected = 0;

- @@ -218,6 +221,7 @@ final_state(struct iter_qstate* iq)

-  static void

-  error_supers(struct module_qstate* qstate, int id, struct module_qstate* super)

-  {

- +    struct iter_env* ie = (struct iter_env*)qstate->env->modinfo[id];

-  	struct iter_qstate* super_iq = (struct iter_qstate*)super->minfo[id];

-  

-  	if(qstate->qinfo.qtype == LDNS_RR_TYPE_A ||

- @@ -242,7 +246,11 @@ error_supers(struct module_qstate* qstate, int id, struct module_qstate* super)

-  				super->region, super_iq->dp))

-  				log_err("out of memory adding missing");

-  		}

- +        delegpt_mark_neg(dpns, qstate->qinfo.qtype);

-  		dpns->resolved = 1; /* mark as failed */

- +        if((dpns->got4 == 2 || !ie->supports_ipv4) &&

- +            (dpns->got6 == 2 || !ie->supports_ipv6))

- +            target_count_increase_nx(super_iq, 1);

-  	}

-  	if(qstate->qinfo.qtype == LDNS_RR_TYPE_NS) {

-  		/* prime failed to get delegation */

- @@ -577,7 +585,7 @@ static void

-  target_count_create(struct iter_qstate* iq)

-  {

-  	if(!iq->target_count) {

- -		iq->target_count = (int*)calloc(2, sizeof(int));

- +		iq->target_count = (int*)calloc(3, sizeof(int));

-  		/* if calloc fails we simply do not track this number */

-  		if(iq->target_count)

-  			iq->target_count[0] = 1;

- @@ -590,6 +598,15 @@ target_count_increase(struct iter_qstate* iq, int num)

-  	target_count_create(iq);

-  	if(iq->target_count)

-  		iq->target_count[1] += num;

- +    iq->dp_target_count++;

- +}

- +

- +static void

- +target_count_increase_nx(struct iter_qstate* iq, int num)

- +{

- +   target_count_create(iq);

- +   if(iq->target_count)

- +       iq->target_count[2] += num;

-  }

-  

-  /**

- @@ -612,13 +629,15 @@ target_count_increase(struct iter_qstate* iq, int num)

-   * @param subq_ret: if newly allocated, the subquerystate, or NULL if it does

-   * 	not need initialisation.

-   * @param v: if true, validation is done on the subquery.

- + * @param detached: true if this qstate should not attach to the subquery

-   * @return false on error (malloc).

-   */

-  static int

-  generate_sub_request(uint8_t* qname, size_t qnamelen, uint16_t qtype, 

-  	uint16_t qclass, struct module_qstate* qstate, int id,

-  	struct iter_qstate* iq, enum iter_state initial_state, 

- -	enum iter_state finalstate, struct module_qstate** subq_ret, int v)

- +	enum iter_state finalstate, struct module_qstate** subq_ret, int v,

- +    int detached)

-  {

-  	struct module_qstate* subq = NULL;

-  	struct iter_qstate* subiq = NULL;

- @@ -645,12 +664,24 @@ generate_sub_request(uint8_t* qname, size_t qnamelen, uint16_t qtype,

-  		valrec = 1;

-  	}

-  	

- -	/* attach subquery, lookup existing or make a new one */

- -	fptr_ok(fptr_whitelist_modenv_attach_sub(qstate->env->attach_sub));

- -	if(!(*qstate->env->attach_sub)(qstate, &qinf, qflags, prime, valrec,

- -		&subq)) {

- -		return 0;

- -	}

- +    if(detached) {

- +        struct mesh_state* sub = NULL;

- +        fptr_ok(fptr_whitelist_modenv_add_sub(

- +            qstate->env->add_sub));

- +        if(!(*qstate->env->add_sub)(qstate, &qinf,

- +            qflags, prime, valrec, &subq, &sub)){

- +            return 0;

- +        }

- +    }

- +    else {

- +        /* attach subquery, lookup existing or make a new one */

- +        fptr_ok(fptr_whitelist_modenv_attach_sub(

- +            qstate->env->attach_sub));

- +        if(!(*qstate->env->attach_sub)(qstate, &qinf, qflags, prime,

- +            valrec, &subq)) {

- +            return 0;

- +        }

- +    }

-  	*subq_ret = subq;

-  	if(subq) {

-  		/* initialise the new subquery */

- @@ -672,6 +703,7 @@ generate_sub_request(uint8_t* qname, size_t qnamelen, uint16_t qtype,

-  		subiq->target_count = iq->target_count;

-  		if(iq->target_count)

-  			iq->target_count[0] ++; /* extra reference */

- +        subiq->dp_target_count = 0;

-  		subiq->num_current_queries = 0;

-  		subiq->depth = iq->depth+1;

-  		outbound_list_init(&subiq->outlist);

- @@ -715,7 +747,7 @@ prime_root(struct module_qstate* qstate, struct iter_qstate* iq, int id,

-  	 * the normal INIT state logic (which would cause an infloop). */

-  	if(!generate_sub_request((uint8_t*)"\000", 1, LDNS_RR_TYPE_NS, 

-  		qclass, qstate, id, iq, QUERYTARGETS_STATE, PRIME_RESP_STATE,

- -		&subq, 0)) {

- +		&subq, 0, 0)) {

-  		verbose(VERB_ALGO, "could not prime root");

-  		return 0;

-  	}

- @@ -805,7 +837,7 @@ prime_stub(struct module_qstate* qstate, struct iter_qstate* iq, int id,

-  	 * redundant INIT state processing. */

-  	if(!generate_sub_request(stub_dp->name, stub_dp->namelen, 

-  		LDNS_RR_TYPE_NS, qclass, qstate, id, iq,

- -		QUERYTARGETS_STATE, PRIME_RESP_STATE, &subq, 0)) {

- +		QUERYTARGETS_STATE, PRIME_RESP_STATE, &subq, 0, 0)) {

-  		verbose(VERB_ALGO, "could not prime stub");

-  		(void)error_response(qstate, id, LDNS_RCODE_SERVFAIL);

-  		return 1; /* return 1 to make module stop, with error */

- @@ -976,7 +1008,7 @@ generate_a_aaaa_check(struct module_qstate* qstate, struct iter_qstate* iq,

-  		if(!generate_sub_request(s->rk.dname, s->rk.dname_len, 

-  			ntohs(s->rk.type), ntohs(s->rk.rrset_class),

-  			qstate, id, iq,

- -			INIT_REQUEST_STATE, FINISHED_STATE, &subq, 1)) {

- +			INIT_REQUEST_STATE, FINISHED_STATE, &subq, 1, 0)) {

-  			verbose(VERB_ALGO, "could not generate addr check");

-  			return;

-  		}

- @@ -1020,7 +1052,7 @@ generate_ns_check(struct module_qstate* qstate, struct iter_qstate* iq, int id)

-  		iq->dp->name, LDNS_RR_TYPE_NS, iq->qchase.qclass);

-  	if(!generate_sub_request(iq->dp->name, iq->dp->namelen, 

-  		LDNS_RR_TYPE_NS, iq->qchase.qclass, qstate, id, iq,

- -		INIT_REQUEST_STATE, FINISHED_STATE, &subq, 1)) {

- +		INIT_REQUEST_STATE, FINISHED_STATE, &subq, 1, 0)) {

-  		verbose(VERB_ALGO, "could not generate ns check");

-  		return;

-  	}

- @@ -1077,7 +1109,7 @@ generate_dnskey_prefetch(struct module_qstate* qstate,

-  		iq->dp->name, LDNS_RR_TYPE_DNSKEY, iq->qchase.qclass);

-  	if(!generate_sub_request(iq->dp->name, iq->dp->namelen, 

-  		LDNS_RR_TYPE_DNSKEY, iq->qchase.qclass, qstate, id, iq,

- -		INIT_REQUEST_STATE, FINISHED_STATE, &subq, 0)) {

- +		INIT_REQUEST_STATE, FINISHED_STATE, &subq, 0, 0)) {

-  		/* we'll be slower, but it'll work */

-  		verbose(VERB_ALGO, "could not generate dnskey prefetch");

-  		return;

- @@ -1251,6 +1283,7 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,

-  			iq->refetch_glue = 0;

-  			iq->query_restart_count++;

-  			iq->sent_count = 0;

- +            iq->dp_target_count = 0;

-  			sock_list_insert(&qstate->reply_origin, NULL, 0, qstate->region);

-  			if(qstate->env->cfg->qname_minimisation)

-  				iq->minimisation_state = INIT_MINIMISE_STATE;

- @@ -1613,7 +1646,7 @@ generate_parentside_target_query(struct module_qstate* qstate,

-  {

-  	struct module_qstate* subq;

-  	if(!generate_sub_request(name, namelen, qtype, qclass, qstate, 

- -		id, iq, INIT_REQUEST_STATE, FINISHED_STATE, &subq, 0))

- +		id, iq, INIT_REQUEST_STATE, FINISHED_STATE, &subq, 0, 0))

-  		return 0;

-  	if(subq) {

-  		struct iter_qstate* subiq = 

- @@ -1664,7 +1697,7 @@ generate_target_query(struct module_qstate* qstate, struct iter_qstate* iq,

-  {

-  	struct module_qstate* subq;

-  	if(!generate_sub_request(name, namelen, qtype, qclass, qstate, 

- -		id, iq, INIT_REQUEST_STATE, FINISHED_STATE, &subq, 0))

- +		id, iq, INIT_REQUEST_STATE, FINISHED_STATE, &subq, 0, 0))

-  		return 0;

-  	log_nametypeclass(VERB_QUERY, "new target", name, qtype, qclass);

-  	return 1;

- @@ -1703,6 +1736,14 @@ query_for_targets(struct module_qstate* qstate, struct iter_qstate* iq,

-  			"number of glue fetches %d", s, iq->target_count[1]);

-  		return 0;

-  	}

- +    if(iq->dp_target_count > MAX_DP_TARGET_COUNT) {

- +        char s[LDNS_MAX_DOMAINLEN+1];

- +        dname_str(qstate->qinfo.qname, s);

- +        verbose(VERB_QUERY, "request %s has exceeded the maximum "

- +            "number of glue fetches %d to a single delegation point",

- +            s, iq->dp_target_count);

- +        return 0;

- +    }

-  

-  	iter_mark_cycle_targets(qstate, iq->dp);

-  	missing = (int)delegpt_count_missing_targets(iq->dp);

- @@ -1815,7 +1856,7 @@ processLastResort(struct module_qstate* qstate, struct iter_qstate* iq,

-  			for(a = p->target_list; a; a=a->next_target) {

-  				(void)delegpt_add_addr(iq->dp, qstate->region,

-  					&a->addr, a->addrlen, a->bogus,

- -					a->lame, a->tls_auth_name);

- +					a->lame, a->tls_auth_name, NULL);

-  			}

-  		}

-  		iq->dp->has_parent_side_NS = 1;

- @@ -1832,6 +1873,7 @@ processLastResort(struct module_qstate* qstate, struct iter_qstate* iq,

-  			iq->refetch_glue = 1;

-  			iq->query_restart_count++;

-  			iq->sent_count = 0;

- +            iq->dp_target_count = 0;

-  			if(qstate->env->cfg->qname_minimisation)

-  				iq->minimisation_state = INIT_MINIMISE_STATE;

-  			return next_state(iq, INIT_REQUEST_STATE);

- @@ -1986,7 +2028,7 @@ processDSNSFind(struct module_qstate* qstate, struct iter_qstate* iq, int id)

-  		iq->dsns_point, LDNS_RR_TYPE_NS, iq->qchase.qclass);

-  	if(!generate_sub_request(iq->dsns_point, iq->dsns_point_len, 

-  		LDNS_RR_TYPE_NS, iq->qchase.qclass, qstate, id, iq,

- -		INIT_REQUEST_STATE, FINISHED_STATE, &subq, 0)) {

- +		INIT_REQUEST_STATE, FINISHED_STATE, &subq, 0, 0)) {

-  		return error_response_cache(qstate, id, LDNS_RCODE_SERVFAIL);

-  	}

-  

- @@ -2039,7 +2081,14 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,

-  			"number of sends with %d", iq->sent_count);

-  		return error_response(qstate, id, LDNS_RCODE_SERVFAIL);

-  	}

- -	

- +    if(iq->target_count && iq->target_count[2] > MAX_TARGET_NX) {

- +        verbose(VERB_QUERY, "request has exceeded the maximum "

- +            " number of nxdomain nameserver lookups with %d",

- +            iq->target_count[2]);

- +        errinf(qstate, "exceeded the maximum nameserver nxdomains");

- +        return error_response(qstate, id, LDNS_RCODE_SERVFAIL);

- +    }

- +

-  	/* Make sure we have a delegation point, otherwise priming failed

-  	 * or another failure occurred */

-  	if(!iq->dp) {

- @@ -2139,12 +2188,41 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,

-  				iq->qinfo_out.qtype, iq->qinfo_out.qclass, 

-  				qstate->query_flags, qstate->region, 

-  				qstate->env->scratch, 0);

- -			if(msg && msg->rep->an_numrrsets == 0

- -				&& FLAGS_GET_RCODE(msg->rep->flags) == 

- +            if(msg && FLAGS_GET_RCODE(msg->rep->flags) ==

-  				LDNS_RCODE_NOERROR)

-  				/* no need to send query if it is already 

- -				 * cached as NOERROR/NODATA */

- +				 * cached as NOERROR */

-  				return 1;

- +            if(msg && FLAGS_GET_RCODE(msg->rep->flags) ==

- +                LDNS_RCODE_NXDOMAIN &&

- +                qstate->env->need_to_validate &&

- +                qstate->env->cfg->harden_below_nxdomain) {

- +                if(msg->rep->security == sec_status_secure) {

- +                    iq->response = msg;

- +                    return final_state(iq);

- +                }

- +                if(msg->rep->security == sec_status_unchecked) {

- +                    struct module_qstate* subq = NULL;

- +                    if(!generate_sub_request(

- +                        iq->qinfo_out.qname,

- +                        iq->qinfo_out.qname_len,

- +                        iq->qinfo_out.qtype,

- +                        iq->qinfo_out.qclass,

- +                        qstate, id, iq,

- +                        INIT_REQUEST_STATE,

- +                        FINISHED_STATE, &subq, 1, 1))

- +                        verbose(VERB_ALGO,

- +                        "could not validate NXDOMAIN "

- +                        "response");

- +                }

- +            }

- +            if(msg && FLAGS_GET_RCODE(msg->rep->flags) ==

- +                LDNS_RCODE_NXDOMAIN) {

- +                /* return and add a label in the next

- +                 * minimisation iteration.

- +                 */

- +                return 1;

- +            }

-  		}

-  	}

-  	if(iq->minimisation_state == SKIP_MINIMISE_STATE) {

- @@ -2219,6 +2297,8 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,

-  	 * generated query will immediately be discarded due to depth and

-  	 * that servfail is cached, which is not good as opportunism goes. */

-  	if(iq->depth < ie->max_dependency_depth

- +        && iq->num_target_queries == 0

- +        && (!iq->target_count || iq->target_count[2]==0)

-  		&& iq->sent_count < TARGET_FETCH_STOP) {

-  		tf_policy = ie->target_fetch_policy[iq->depth];

-  	}

- @@ -2256,6 +2336,7 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,

-  			iq->num_current_queries++; /* RespState decrements it*/

-  			iq->referral_count++; /* make sure we don't loop */

-  			iq->sent_count = 0;

- +            iq->dp_target_count = 0;

-  			iq->state = QUERY_RESP_STATE;

-  			return 1;

-  		}

- @@ -2341,6 +2422,7 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,

-  					iq->num_current_queries++; /* RespState decrements it*/

-  					iq->referral_count++; /* make sure we don't loop */

-  					iq->sent_count = 0;

- +                    iq->dp_target_count = 0;

-  					iq->state = QUERY_RESP_STATE;

-  					return 1;

-  				}

- @@ -2607,7 +2689,8 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,

-  				/* Make subrequest to validate intermediate

-  				 * NXDOMAIN if harden-below-nxdomain is

-  				 * enabled. */

- -				if(qstate->env->cfg->harden_below_nxdomain) {

- +				if(qstate->env->cfg->harden_below_nxdomain &&

- +                    qstate->env->need_to_validate) {

-  					struct module_qstate* subq = NULL;

-  					log_query_info(VERB_QUERY,

-  						"schedule NXDOMAIN validation:",

- @@ -2619,7 +2702,7 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,

-  						iq->response->qinfo.qclass,

-  						qstate, id, iq,

-  						INIT_REQUEST_STATE,

- -						FINISHED_STATE, &subq, 1))

- +						FINISHED_STATE, &subq, 1, 1))

-  						verbose(VERB_ALGO,

-  						"could not validate NXDOMAIN "

-  						"response");

- @@ -2702,6 +2785,7 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,

-  		/* Count this as a referral. */

-  		iq->referral_count++;

-  		iq->sent_count = 0;

- +        iq->dp_target_count = 0;

-  		/* see if the next dp is a trust anchor, or a DS was sent

-  		 * along, indicating dnssec is expected for next zone */

-  		iq->dnssec_expected = iter_indicates_dnssec(qstate->env, 

- @@ -2776,6 +2860,7 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,

-  		iq->dsns_point = NULL;

-  		iq->auth_zone_response = 0;

-  		iq->sent_count = 0;

- +        iq->dp_target_count = 0;

-  		if(iq->minimisation_state != MINIMISE_STATE)

-  			/* Only count as query restart when it is not an extra

-  			 * query as result of qname minimisation. */

- @@ -2964,7 +3049,7 @@ processPrimeResponse(struct module_qstate* qstate, int id)

-  		if(!generate_sub_request(qstate->qinfo.qname, 

-  			qstate->qinfo.qname_len, qstate->qinfo.qtype,

-  			qstate->qinfo.qclass, qstate, id, iq,

- -			INIT_REQUEST_STATE, FINISHED_STATE, &subq, 1)) {

- +			INIT_REQUEST_STATE, FINISHED_STATE, &subq, 1, 0)) {

-  			verbose(VERB_ALGO, "could not generate prime check");

-  		}

-  		generate_a_aaaa_check(qstate, iq, id);

- @@ -2992,6 +3077,7 @@ static void

-  processTargetResponse(struct module_qstate* qstate, int id,

-  	struct module_qstate* forq)

-  {

- +    struct iter_env* ie = (struct iter_env*)qstate->env->modinfo[id];

-  	struct iter_qstate* iq = (struct iter_qstate*)qstate->minfo[id];

-  	struct iter_qstate* foriq = (struct iter_qstate*)forq->minfo[id];

-  	struct ub_packed_rrset_key* rrset;

- @@ -3029,7 +3115,7 @@ processTargetResponse(struct module_qstate* qstate, int id,

-  		log_rrset_key(VERB_ALGO, "add parentside glue to dp", 

-  			iq->pside_glue);

-  		if(!delegpt_add_rrset(foriq->dp, forq->region, 

- -			iq->pside_glue, 1))

- +			iq->pside_glue, 1, NULL))

-  			log_err("out of memory adding pside glue");

-  	}

-  

- @@ -3040,6 +3126,7 @@ processTargetResponse(struct module_qstate* qstate, int id,

-  	 * response type was ANSWER. */

-  	rrset = reply_find_answer_rrset(&iq->qchase, qstate->return_msg->rep);

-  	if(rrset) {

- +        int additions = 0;

-  		/* if CNAMEs have been followed - add new NS to delegpt. */

-  		/* BTW. RFC 1918 says NS should not have got CNAMEs. Robust. */

-  		if(!delegpt_find_ns(foriq->dp, rrset->rk.dname, 

- @@ -3051,13 +3138,23 @@ processTargetResponse(struct module_qstate* qstate, int id,

-  		}

-  		/* if dpns->lame then set the address(es) lame too */

-  		if(!delegpt_add_rrset(foriq->dp, forq->region, rrset, 

- -			dpns->lame))

- +			dpns->lame, &additions))

-  			log_err("out of memory adding targets");

- +        if(!additions) {

- +            /* no new addresses, increase the nxns counter, like

- +             * this could be a list of wildcards with no new

- +             * addresses */

- +            target_count_increase_nx(foriq, 1);

- +        }

-  		verbose(VERB_ALGO, "added target response");

-  		delegpt_log(VERB_ALGO, foriq->dp);

-  	} else {

-  		verbose(VERB_ALGO, "iterator TargetResponse failed");

- +        delegpt_mark_neg(dpns, qstate->qinfo.qtype);

-  		dpns->resolved = 1; /* fail the target */

- +        if((dpns->got4 == 2 || !ie->supports_ipv4) &&

- +            (dpns->got6 == 2 || !ie->supports_ipv6))

- +            target_count_increase_nx(foriq, 1);

-  	}

-  }

-  

- @@ -3228,7 +3325,7 @@ processCollectClass(struct module_qstate* qstate, int id)

-  				qstate->qinfo.qname_len, qstate->qinfo.qtype,

-  				c, qstate, id, iq, INIT_REQUEST_STATE,

-  				FINISHED_STATE, &subq, 

- -				(int)!(qstate->query_flags&BIT_CD))) {

- +				(int)!(qstate->query_flags&BIT_CD), 0)) {

-  				return error_response(qstate, id, 

-  					LDNS_RCODE_SERVFAIL);

-  			}

- diff --git a/iterator/iterator.h b/iterator/iterator.h

- index 67ffeb1..4b325b5 100644

- --- a/iterator/iterator.h

- +++ b/iterator/iterator.h

- @@ -55,6 +55,11 @@ struct rbtree_type;

-  

-  /** max number of targets spawned for a query and its subqueries */

-  #define MAX_TARGET_COUNT	64

- +/** max number of target lookups per qstate, per delegation point */

- +#define MAX_DP_TARGET_COUNT    16

- +/** max number of nxdomains allowed for target lookups for a query and

- + * its subqueries */

- +#define MAX_TARGET_NX      5

-  /** max number of query restarts. Determines max number of CNAME chain. */

-  #define MAX_RESTART_COUNT       8

-  /** max number of referrals. Makes sure resolver does not run away */

- @@ -305,9 +310,14 @@ struct iter_qstate {

-  	int sent_count;

-  	

-  	/** number of target queries spawned in [1], for this query and its

- -	 * subqueries, the malloced-array is shared, [0] refcount. */

- +	 * subqueries, the malloced-array is shared, [0] refcount.

- +	 * in [2] the number of nxdomains is counted. */

-  	int* target_count;

-  

- +    /** number of target lookups per delegation point. Reset to 0 after

- +     * receiving referral answer. Not shared with subqueries. */

- +    int dp_target_count;

- +

-  	/** if true, already tested for ratelimiting and passed the test */

-  	int ratelimit_ok;

-  

- diff --git a/services/cache/dns.c b/services/cache/dns.c

- index 35adc35..23ec68e 100644

- --- a/services/cache/dns.c

- +++ b/services/cache/dns.c

- @@ -271,7 +271,7 @@ find_add_addrs(struct module_env* env, uint16_t qclass,

-  		akey = rrset_cache_lookup(env->rrset_cache, ns->name, 

-  			ns->namelen, LDNS_RR_TYPE_A, qclass, 0, now, 0);

-  		if(akey) {

- -			if(!delegpt_add_rrset_A(dp, region, akey, 0)) {

- +			if(!delegpt_add_rrset_A(dp, region, akey, 0, NULL)) {

-  				lock_rw_unlock(&akey->entry.lock);

-  				return 0;

-  			}

- @@ -291,7 +291,7 @@ find_add_addrs(struct module_env* env, uint16_t qclass,

-  		akey = rrset_cache_lookup(env->rrset_cache, ns->name, 

-  			ns->namelen, LDNS_RR_TYPE_AAAA, qclass, 0, now, 0);

-  		if(akey) {

- -			if(!delegpt_add_rrset_AAAA(dp, region, akey, 0)) {

- +			if(!delegpt_add_rrset_AAAA(dp, region, akey, 0, NULL)) {

-  				lock_rw_unlock(&akey->entry.lock);

-  				return 0;

-  			}

- @@ -325,7 +325,8 @@ cache_fill_missing(struct module_env* env, uint16_t qclass,

-  		akey = rrset_cache_lookup(env->rrset_cache, ns->name, 

-  			ns->namelen, LDNS_RR_TYPE_A, qclass, 0, now, 0);

-  		if(akey) {

- -			if(!delegpt_add_rrset_A(dp, region, akey, ns->lame)) {

- +			if(!delegpt_add_rrset_A(dp, region, akey, ns->lame,

- +                NULL)) {

-  				lock_rw_unlock(&akey->entry.lock);

-  				return 0;

-  			}

- @@ -345,7 +346,8 @@ cache_fill_missing(struct module_env* env, uint16_t qclass,

-  		akey = rrset_cache_lookup(env->rrset_cache, ns->name, 

-  			ns->namelen, LDNS_RR_TYPE_AAAA, qclass, 0, now, 0);

-  		if(akey) {

- -			if(!delegpt_add_rrset_AAAA(dp, region, akey, ns->lame)) {

- +			if(!delegpt_add_rrset_AAAA(dp, region, akey, ns->lame,

- +                NULL)) {

-  				lock_rw_unlock(&akey->entry.lock);

-  				return 0;

-  			}

- diff --git a/util/data/dname.c b/util/data/dname.c

- index c7360f7..b744f06 100644

- --- a/util/data/dname.c

- +++ b/util/data/dname.c

- @@ -231,17 +231,28 @@ int

-  dname_pkt_compare(sldns_buffer* pkt, uint8_t* d1, uint8_t* d2)

-  {

-  	uint8_t len1, len2;

- +    int count1 = 0, count2 = 0;

-  	log_assert(pkt && d1 && d2);

-  	len1 = *d1++;

-  	len2 = *d2++;

-  	while( len1 != 0 || len2 != 0 ) {

-  		/* resolve ptrs */

-  		if(LABEL_IS_PTR(len1)) {

- +            if((size_t)PTR_OFFSET(len1, *d1)

- +                >= sldns_buffer_limit(pkt))

- +                return -1;

- +            if(count1++ > MAX_COMPRESS_PTRS)

- +                return -1;

-  			d1 = sldns_buffer_at(pkt, PTR_OFFSET(len1, *d1));

-  			len1 = *d1++;

-  			continue;

-  		}

-  		if(LABEL_IS_PTR(len2)) {

- +            if((size_t)PTR_OFFSET(len2, *d2)

- +                >= sldns_buffer_limit(pkt))

- +                return 1;

- +            if(count2++ > MAX_COMPRESS_PTRS)

- +                return 1;

-  			d2 = sldns_buffer_at(pkt, PTR_OFFSET(len2, *d2));

-  			len2 = *d2++;

-  			continue;

- @@ -300,12 +311,19 @@ dname_pkt_hash(sldns_buffer* pkt, uint8_t* dname, hashvalue_type h)

-  	uint8_t labuf[LDNS_MAX_LABELLEN+1];

-  	uint8_t lablen;

-  	int i;

- +    int count = 0;

-  

-  	/* preserve case of query, make hash label by label */

-  	lablen = *dname++;

-  	while(lablen) {

-  		if(LABEL_IS_PTR(lablen)) {

-  			/* follow pointer */

- +            if((size_t)PTR_OFFSET(lablen, *dname)

- +                >= sldns_buffer_limit(pkt))

- +                return h;

- +            if(count++ > MAX_COMPRESS_PTRS)

- +                return h;

- +

-  			dname = sldns_buffer_at(pkt, PTR_OFFSET(lablen, *dname));

-  			lablen = *dname++;

-  			continue;

- @@ -333,6 +351,9 @@ void dname_pkt_copy(sldns_buffer* pkt, uint8_t* to, uint8_t* dname)

-  	while(lablen) {

-  		if(LABEL_IS_PTR(lablen)) {

-  			/* follow pointer */

- +            if((size_t)PTR_OFFSET(lablen, *dname)

- +                >= sldns_buffer_limit(pkt))

- +                return;

-  			dname = sldns_buffer_at(pkt, PTR_OFFSET(lablen, *dname));

-  			lablen = *dname++;

-  			continue;

- @@ -357,6 +378,7 @@ void dname_pkt_copy(sldns_buffer* pkt, uint8_t* to, uint8_t* dname)

-  void dname_print(FILE* out, struct sldns_buffer* pkt, uint8_t* dname)

-  {

-  	uint8_t lablen;

- +    int count = 0;

-  	if(!out) out = stdout;

-  	if(!dname) return;

-  

- @@ -370,6 +392,15 @@ void dname_print(FILE* out, struct sldns_buffer* pkt, uint8_t* dname)

-  				fputs("??compressionptr??", out);

-  				return;

-  			}

- +            if((size_t)PTR_OFFSET(lablen, *dname)

- +                >= sldns_buffer_limit(pkt)) {

- +                fputs("??compressionptr??", out);

- +                return;

- +            }

- +            if(count++ > MAX_COMPRESS_PTRS) {

- +                fputs("??compressionptr??", out);

- +                return;

- +            }

-  			dname = sldns_buffer_at(pkt, PTR_OFFSET(lablen, *dname));

-  			lablen = *dname++;

-  			continue;

- diff --git a/util/data/msgparse.c b/util/data/msgparse.c

- index 13cad8a..c8a5384 100644

- --- a/util/data/msgparse.c

- +++ b/util/data/msgparse.c

- @@ -55,7 +55,11 @@ smart_compare(sldns_buffer* pkt, uint8_t* dnow,

-  {

-  	if(LABEL_IS_PTR(*dnow)) {

-  		/* ptr points to a previous dname */

- -		uint8_t* p = sldns_buffer_at(pkt, PTR_OFFSET(dnow[0], dnow[1]));

- +       uint8_t* p;

- +       if((size_t)PTR_OFFSET(dnow[0], dnow[1])

- +           >= sldns_buffer_limit(pkt))

- +           return -1;

- +       p = sldns_buffer_at(pkt, PTR_OFFSET(dnow[0], dnow[1]));

-  		if( p == dprfirst || p == dprlast )

-  			return 0;

-  		/* prev dname is also a ptr, both ptrs are the same. */

@@ -1,182 +0,0 @@ 

- From 81e9f82a8ddd811d7ebafe2fd0ee5af836d0b405 Mon Sep 17 00:00:00 2001

- From: Wouter Wijngaards <wouter@nlnetlabs.nl>

- Date: Wed, 4 Jul 2018 10:02:16 +0000

- Subject: [PATCH] - Fix #4112: Fix that unbound-anchor -f /etc/resolv.conf will

-  not pass   if DNSSEC is not enabled.  New option -R allows fallback from  

-  resolv.conf to direct queries.

- 

- git-svn-id: file:///svn/unbound/trunk@4770 be551aaa-1e26-0410-a405-d3ace91eadb9

- ---

-  doc/unbound-anchor.8.in   |  5 ++++

-  smallapp/unbound-anchor.c | 66 ++++++++++++++++++++++++++++++++++-------------

-  2 files changed, 53 insertions(+), 18 deletions(-)

- 

- diff --git a/doc/unbound-anchor.8.in b/doc/unbound-anchor.8.in

- index 02a3e781..e114eb25 100644

- --- a/doc/unbound-anchor.8.in

- +++ b/doc/unbound-anchor.8.in

- @@ -109,6 +109,11 @@ It does so, because the tool when used for bootstrapping the recursive

-  resolver, cannot use that recursive resolver itself because it is bootstrapping

-  that server.

-  .TP

- +.B \-R

- +Allow fallback from \-f resolv.conf file to direct root servers query.

- +It allows you to prefer local resolvers, but fallback automatically

- +to direct root query if they do not respond or do not support DNSSEC.

- +.TP

-  .B \-v

-  More verbose. Once prints informational messages, multiple times may enable

-  large debug amounts (such as full certificates or byte\-dumps of downloaded

- diff --git a/smallapp/unbound-anchor.c b/smallapp/unbound-anchor.c

- index b3009108..f3985090 100644

- --- a/smallapp/unbound-anchor.c

- +++ b/smallapp/unbound-anchor.c

- @@ -192,9 +192,10 @@ usage(void)

-  	printf("-n name		signer's subject emailAddress, default %s\n", P7SIGNER);

-  	printf("-4		work using IPv4 only\n");

-  	printf("-6		work using IPv6 only\n");

- -	printf("-f resolv.conf	use given resolv.conf to resolve -u name\n");

- -	printf("-r root.hints	use given root.hints to resolve -u name\n"

- +	printf("-f resolv.conf	use given resolv.conf\n");

- +	printf("-r root.hints	use given root.hints\n"

-  		"		builtin root hints are used by default\n");

- +	printf("-R		fallback from -f to root query on error\n");

-  	printf("-v		more verbose\n");

-  	printf("-C conf		debug, read config\n");

-  	printf("-P port		use port for https connect, default 443\n");

- @@ -1920,8 +1921,7 @@ static int

-  do_certupdate(const char* root_anchor_file, const char* root_cert_file,

-  	const char* urlname, const char* xmlname, const char* p7sname,

-  	const char* p7signer, const char* res_conf, const char* root_hints,

- -	const char* debugconf, int ip4only, int ip6only, int port,

- -	struct ub_result* dnskey)

- +	const char* debugconf, int ip4only, int ip6only, int port)

-  {

-  	STACK_OF(X509)* cert;

-  	BIO *xml, *p7s;

- @@ -1961,7 +1961,6 @@ do_certupdate(const char* root_anchor_file, const char* root_cert_file,

-  #ifndef S_SPLINT_S

-  	sk_X509_pop_free(cert, X509_free);

-  #endif

- -	ub_resolve_free(dnskey);

-  	ip_list_free(ip_list);

-  	return 1;

-  }

- @@ -2199,16 +2198,33 @@ probe_date_allows_certupdate(const char* root_anchor_file)

-  	return 0;

-  }

-  

- +static struct ub_result *

- +fetch_root_key(const char* root_anchor_file, const char* res_conf,

- +	const char* root_hints, const char* debugconf,

- +	int ip4only, int ip6only)

- +{

- +	struct ub_ctx* ctx;

- +	struct ub_result* dnskey;

- +

- +	ctx = create_unbound_context(res_conf, root_hints, debugconf,

- +		ip4only, ip6only);

- +	add_5011_probe_root(ctx, root_anchor_file);

- +	dnskey = prime_root_key(ctx);

- +	ub_ctx_delete(ctx);

- +	return dnskey;

- +}

- +

-  /** perform the unbound-anchor work */

-  static int

-  do_root_update_work(const char* root_anchor_file, const char* root_cert_file,

-  	const char* urlname, const char* xmlname, const char* p7sname,

-  	const char* p7signer, const char* res_conf, const char* root_hints,

- -	const char* debugconf, int ip4only, int ip6only, int force, int port)

- +	const char* debugconf, int ip4only, int ip6only, int force,

- +	int res_conf_fallback, int port)

-  {

- -	struct ub_ctx* ctx;

-  	struct ub_result* dnskey;

-  	int used_builtin = 0;

- +	int rcode;

-  

-  	/* see if builtin rootanchor needs to be provided, or if

-  	 * rootanchor is 'revoked-trust-point' */

- @@ -2217,12 +2233,22 @@ do_root_update_work(const char* root_anchor_file, const char* root_cert_file,

-  

-  	/* make unbound context with 5011-probe for root anchor,

-  	 * and probe . DNSKEY */

- -	ctx = create_unbound_context(res_conf, root_hints, debugconf,

- -		ip4only, ip6only);

- -	add_5011_probe_root(ctx, root_anchor_file);

- -	dnskey = prime_root_key(ctx);

- -	ub_ctx_delete(ctx);

- -	

- +	dnskey = fetch_root_key(root_anchor_file, res_conf,

- +		root_hints, debugconf, ip4only, ip6only);

- +	rcode = dnskey->rcode;

- +

- +	if (res_conf_fallback && res_conf && !dnskey->secure) {

- +		if (verb) printf("%s failed, retrying direct\n", res_conf);

- +		ub_resolve_free(dnskey);

- +		/* try direct query without res_conf */

- +		dnskey = fetch_root_key(root_anchor_file, NULL,

- +			root_hints, debugconf, ip4only, ip6only);

- +		if (rcode != 0 && dnskey->rcode == 0) {

- +			res_conf = NULL;

- +			rcode = 0;

- +		}

- +	}

- +

-  	/* if secure: exit */

-  	if(dnskey->secure && !force) {

-  		if(verb) printf("success: the anchor is ok\n");

- @@ -2230,18 +2256,18 @@ do_root_update_work(const char* root_anchor_file, const char* root_cert_file,

-  		return used_builtin;

-  	}

-  	if(force && verb) printf("debug cert update forced\n");

- +	ub_resolve_free(dnskey);

-  

-  	/* if not (and NOERROR): check date and do certupdate */

- -	if((dnskey->rcode == 0 &&

- +	if((rcode == 0 &&

-  		probe_date_allows_certupdate(root_anchor_file)) || force) {

-  		if(do_certupdate(root_anchor_file, root_cert_file, urlname,

-  			xmlname, p7sname, p7signer, res_conf, root_hints,

- -			debugconf, ip4only, ip6only, port, dnskey))

- +			debugconf, ip4only, ip6only, port))

-  			return 1;

-  		return used_builtin;

-  	}

-  	if(verb) printf("fail: the anchor is NOT ok and could not be fixed\n");

- -	ub_resolve_free(dnskey);

-  	return used_builtin;

-  }

-  

- @@ -2264,8 +2290,9 @@ int main(int argc, char* argv[])

-  	const char* root_hints = NULL;

-  	const char* debugconf = NULL;

-  	int dolist=0, ip4only=0, ip6only=0, force=0, port = HTTPS_PORT;

- +	int res_conf_fallback = 0;

-  	/* parse the options */

- -	while( (c=getopt(argc, argv, "46C:FP:a:c:f:hln:r:s:u:vx:")) != -1) {

- +	while( (c=getopt(argc, argv, "46C:FRP:a:c:f:hln:r:s:u:vx:")) != -1) {

-  		switch(c) {

-  		case 'l':

-  			dolist = 1;

- @@ -2300,6 +2327,9 @@ int main(int argc, char* argv[])

-  		case 'r':

-  			root_hints = optarg;

-  			break;

- +		case 'R':

- +			res_conf_fallback = 1;

- +			break;

-  		case 'C':

-  			debugconf = optarg;

-  			break;

- @@ -2346,5 +2376,5 @@ int main(int argc, char* argv[])

-  

-  	return do_root_update_work(root_anchor_file, root_cert_file, urlname,

-  		xmlname, p7sname, p7signer, res_conf, root_hints, debugconf,

- -		ip4only, ip6only, force, port);

- +		ip4only, ip6only, force, res_conf_fallback, port);

-  }

- -- 

- 2.14.4

- 

@@ -1,65 +0,0 @@ 

- --- a/services/authzone.c	2018-06-14 09:09:01.000000000 +0200

- +++ b/services/authzone.c	2020-04-16 18:55:50.806693241 +0200

- @@ -5139,7 +5139,7 @@

-  	log_assert(xfr->task_transfer);

-  	lock_basic_lock(&xfr->lock);

-  	env = xfr->task_transfer->env;

- -	if(env->outnet->want_to_quit) {

- +	if(!env || env->outnet->want_to_quit) {

-  		lock_basic_unlock(&xfr->lock);

-  		return; /* stop on quit */

-  	}

- @@ -5558,7 +5558,7 @@

-  	log_assert(xfr->task_transfer);

-  	lock_basic_lock(&xfr->lock);

-  	env = xfr->task_transfer->env;

- -	if(env->outnet->want_to_quit) {

- +	if(!env || env->outnet->want_to_quit) {

-  		lock_basic_unlock(&xfr->lock);

-  		return 0; /* stop on quit */

-  	}

- @@ -5619,7 +5619,7 @@

-  	log_assert(xfr->task_transfer);

-  	lock_basic_lock(&xfr->lock);

-  	env = xfr->task_transfer->env;

- -	if(env->outnet->want_to_quit) {

- +	if(!env || env->outnet->want_to_quit) {

-  		lock_basic_unlock(&xfr->lock);

-  		return 0; /* stop on quit */

-  	}

- @@ -5798,7 +5798,7 @@

-  	log_assert(xfr->task_probe);

-  	lock_basic_lock(&xfr->lock);

-  	env = xfr->task_probe->env;

- -	if(env->outnet->want_to_quit) {

- +	if(!env || env->outnet->want_to_quit) {

-  		lock_basic_unlock(&xfr->lock);

-  		return; /* stop on quit */

-  	}

- @@ -5829,7 +5829,7 @@

-  	log_assert(xfr->task_probe);

-  	lock_basic_lock(&xfr->lock);

-  	env = xfr->task_probe->env;

- -	if(env->outnet->want_to_quit) {

- +	if(!env || env->outnet->want_to_quit) {

-  		lock_basic_unlock(&xfr->lock);

-  		return 0; /* stop on quit */

-  	}

- @@ -6030,7 +6030,7 @@

-  	log_assert(xfr->task_probe);

-  	lock_basic_lock(&xfr->lock);

-  	env = xfr->task_probe->env;

- -	if(env->outnet->want_to_quit) {

- +	if(!env || env->outnet->want_to_quit) {

-  		lock_basic_unlock(&xfr->lock);

-  		return; /* stop on quit */

-  	}

- @@ -6089,7 +6089,7 @@

-  	log_assert(xfr->task_nextprobe);

-  	lock_basic_lock(&xfr->lock);

-  	env = xfr->task_nextprobe->env;

- -	if(env->outnet->want_to_quit) {

- +	if(!env || env->outnet->want_to_quit) {

-  		lock_basic_unlock(&xfr->lock);

-  		return; /* stop on quit */

-  	}

@@ -1,13 +0,0 @@ 

- diff --git a/util/net_help.c b/util/net_help.c

- index a5059b0..a193c36 100644

- --- a/util/net_help.c

- +++ b/util/net_help.c

- @@ -703,7 +703,7 @@ listen_sslctx_setup(void* ctxt)

-  #endif

-  #if defined(SHA256_DIGEST_LENGTH) && defined(USE_ECDSA)

-  	/* if we have sha256, set the cipher list to have no known vulns */

- -	if(!SSL_CTX_set_cipher_list(ctx, "TLS13-CHACHA20-POLY1305-SHA256:TLS13-AES-256-GCM-SHA384:TLS13-AES-128-GCM-SHA256:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256"))

- +	if(!SSL_CTX_set_cipher_list(ctx, "PROFILE=SYSTEM"))

-  		log_crypto_err("could not set cipher list with SSL_CTX_set_cipher_list");

-  #endif

-  

@@ -1,12 +0,0 @@ 

- diff --git a/smallapp/unbound-host.c b/smallapp/unbound-host.c

- index 53bf3277..f02511fe 100644

- --- a/smallapp/unbound-host.c

- +++ b/smallapp/unbound-host.c

- @@ -340,6 +340,7 @@ pretty_output(char* q, int t, int c, struct ub_result* result, int docname)

-  					exit(1);

-  				}

-  				printf("%s\n", s);

- +				free(s);

-  			} else	printf(" has no %s record", tstr);

-  			printf(" %s\n", secstatus);

-  		}

@@ -1,218 +0,0 @@ 

- diff --git a/ipsecmod/ipsecmod.c b/ipsecmod/ipsecmod.c

- index c8400c6..9e916d6 100644

- --- a/ipsecmod/ipsecmod.c

- +++ b/ipsecmod/ipsecmod.c

- @@ -162,6 +162,71 @@ generate_request(struct module_qstate* qstate, int id, uint8_t* name,

-  }

-  

-  /**

- + * Check if the string passed is a valid domain name with safe characters to

- + * pass to a shell.

- + * This will only allow:

- + *  - digits

- + *  - alphas

- + *  - hyphen (not at the start)

- + *  - dot (not at the start, or the only character)

- + *  - underscore

- + * @param s: pointer to the string.

- + * @param slen: string's length.

- + * @return true if s only contains safe characters; false otherwise.

- + */

- +static int

- +domainname_has_safe_characters(char* s, size_t slen) {

- +	size_t i;

- +	for(i = 0; i < slen; i++) {

- +		if(s[i] == '\0') return 1;

- +		if((s[i] == '-' && i != 0)

- +			|| (s[i] == '.' && (i != 0 || s[1] == '\0'))

- +			|| (s[i] == '_') || (s[i] >= '0' && s[i] <= '9')

- +			|| (s[i] >= 'A' && s[i] <= 'Z')

- +			|| (s[i] >= 'a' && s[i] <= 'z')) {

- +			continue;

- +		}

- +		return 0;

- +	}

- +	return 1;

- +}

- +

- +/**

- + * Check if the stringified IPSECKEY RDATA contains safe characters to pass to

- + * a shell.

- + * This is only relevant for checking the gateway when the gateway type is 3

- + * (domainname).

- + * @param s: pointer to the string.

- + * @param slen: string's length.

- + * @return true if s contains only safe characters; false otherwise.

- + */

- +static int

- +ipseckey_has_safe_characters(char* s, size_t slen) {

- +	int precedence, gateway_type, algorithm;

- +	char* gateway;

- +	gateway = (char*)calloc(slen, sizeof(char));

- +	if(!gateway) {

- +		log_err("ipsecmod: out of memory when calling the hook");

- +		return 0;

- +	}

- +	if(sscanf(s, "%d %d %d %s ",

- +			&precedence, &gateway_type, &algorithm, gateway) != 4) {

- +		free(gateway);

- +		return 0;

- +	}

- +	if(gateway_type != 3) {

- +		free(gateway);

- +		return 1;

- +	}

- +	if(domainname_has_safe_characters(gateway, slen)) {

- +		free(gateway);

- +		return 1;

- +	}

- +	free(gateway);

- +	return 0;

- +}

- +

- +/**

-   *  Prepare the data and call the hook.

-   *

-   *  @param qstate: query state.

- @@ -175,7 +240,7 @@ call_hook(struct module_qstate* qstate, struct ipsecmod_qstate* iq,

-  {

-  	size_t slen, tempdata_len, tempstring_len, i;

-  	char str[65535], *s, *tempstring;

- -	int w;

- +	int w = 0, w_temp, qtype;

-  	struct ub_packed_rrset_key* rrset_key;

-  	struct packed_rrset_data* rrset_data;

-  	uint8_t *tempdata;

- @@ -192,9 +257,9 @@ call_hook(struct module_qstate* qstate, struct ipsecmod_qstate* iq,

-  	memset(s, 0, slen);

-  

-  	/* Copy the hook into the buffer. */

- -	sldns_str_print(&s, &slen, "%s", qstate->env->cfg->ipsecmod_hook);

- +	w += sldns_str_print(&s, &slen, "%s", qstate->env->cfg->ipsecmod_hook);

-  	/* Put space into the buffer. */

- -	sldns_str_print(&s, &slen, " ");

- +	w += sldns_str_print(&s, &slen, " ");

-  	/* Copy the qname into the buffer. */

-  	tempstring = sldns_wire2str_dname(qstate->qinfo.qname,

-  		qstate->qinfo.qname_len);

- @@ -202,68 +267,96 @@ call_hook(struct module_qstate* qstate, struct ipsecmod_qstate* iq,

-  		log_err("ipsecmod: out of memory when calling the hook");

-  		return 0;

-  	}

- -	sldns_str_print(&s, &slen, "\"%s\"", tempstring);

- +	if(!domainname_has_safe_characters(tempstring, strlen(tempstring))) {

- +		log_err("ipsecmod: qname has unsafe characters");

- +		free(tempstring);

- +		return 0;

- +	}

- +	w += sldns_str_print(&s, &slen, "\"%s\"", tempstring);

-  	free(tempstring);

-  	/* Put space into the buffer. */

- -	sldns_str_print(&s, &slen, " ");

- +	w += sldns_str_print(&s, &slen, " ");

-  	/* Copy the IPSECKEY TTL into the buffer. */

-  	rrset_data = (struct packed_rrset_data*)iq->ipseckey_rrset->entry.data;

- -	sldns_str_print(&s, &slen, "\"%ld\"", (long)rrset_data->ttl);

- +	w += sldns_str_print(&s, &slen, "\"%ld\"", (long)rrset_data->ttl);

-  	/* Put space into the buffer. */

- -	sldns_str_print(&s, &slen, " ");

- -	/* Copy the A/AAAA record(s) into the buffer. Start and end this section

- -	 * with a double quote. */

- +	w += sldns_str_print(&s, &slen, " ");

-  	rrset_key = reply_find_answer_rrset(&qstate->return_msg->qinfo,

-  		qstate->return_msg->rep);

- +	/* Double check that the records are indeed A/AAAA.

- +	 * This should never happen as this function is only executed for A/AAAA

- +	 * queries but make sure we don't pass anything other than A/AAAA to the

- +	 * shell. */

- +	qtype = ntohs(rrset_key->rk.type);

- +	if(qtype != LDNS_RR_TYPE_AAAA && qtype != LDNS_RR_TYPE_A) {

- +		log_err("ipsecmod: Answer is not of A or AAAA type");

- +		return 0;

- +	}

-  	rrset_data = (struct packed_rrset_data*)rrset_key->entry.data;

- -	sldns_str_print(&s, &slen, "\"");

- +	/* Copy the A/AAAA record(s) into the buffer. Start and end this section

- +	 * with a double quote. */

- +	w += sldns_str_print(&s, &slen, "\"");

-  	for(i=0; i<rrset_data->count; i++) {

-  		if(i > 0) {

-  			/* Put space into the buffer. */

- -			sldns_str_print(&s, &slen, " ");

- +			w += sldns_str_print(&s, &slen, " ");

-  		}

-  		/* Ignore the first two bytes, they are the rr_data len. */

- -		w = sldns_wire2str_rdata_buf(rrset_data->rr_data[i] + 2,

- +		w_temp = sldns_wire2str_rdata_buf(rrset_data->rr_data[i] + 2,

-  			rrset_data->rr_len[i] - 2, s, slen, qstate->qinfo.qtype);

- -		if(w < 0) {

- +		if(w_temp < 0) {

-  			/* Error in printout. */

- -			return -1;

- -		} else if((size_t)w >= slen) {

- +			log_err("ipsecmod: Error in printing IP address");

- +			return 0;

- +		} else if((size_t)w_temp >= slen) {

-  			s = NULL; /* We do not want str to point outside of buffer. */

-  			slen = 0;

- -			return -1;

- +			log_err("ipsecmod: shell command too long");

- +			return 0;

-  		} else {

- -			s += w;

- -			slen -= w;

- +			s += w_temp;

- +			slen -= w_temp;

- +			w += w_temp;

-  		}

-  	}

- -	sldns_str_print(&s, &slen, "\"");

- +	w += sldns_str_print(&s, &slen, "\"");

-  	/* Put space into the buffer. */

- -	sldns_str_print(&s, &slen, " ");

- +	w += sldns_str_print(&s, &slen, " ");

-  	/* Copy the IPSECKEY record(s) into the buffer. Start and end this section

-  	 * with a double quote. */

- -	sldns_str_print(&s, &slen, "\"");

- +	w += sldns_str_print(&s, &slen, "\"");

-  	rrset_data = (struct packed_rrset_data*)iq->ipseckey_rrset->entry.data;

-  	for(i=0; i<rrset_data->count; i++) {

-  		if(i > 0) {

-  			/* Put space into the buffer. */

- -			sldns_str_print(&s, &slen, " ");

- +			w += sldns_str_print(&s, &slen, " ");

-  		}

-  		/* Ignore the first two bytes, they are the rr_data len. */

-  		tempdata = rrset_data->rr_data[i] + 2;

-  		tempdata_len = rrset_data->rr_len[i] - 2;

-  		/* Save the buffer pointers. */

-  		tempstring = s; tempstring_len = slen;

- -		w = sldns_wire2str_ipseckey_scan(&tempdata, &tempdata_len, &s, &slen,

- -			NULL, 0);

- +		w_temp = sldns_wire2str_ipseckey_scan(&tempdata, &tempdata_len, &s,

- +			&slen, NULL, 0);

-  		/* There was an error when parsing the IPSECKEY; reset the buffer

-  		 * pointers to their previous values. */

- -		if(w == -1){

- +		if(w_temp == -1) {

-  			s = tempstring; slen = tempstring_len;

- +		} else if(w_temp > 0) {

- +			if(!ipseckey_has_safe_characters(

- +					tempstring, tempstring_len - slen)) {

- +				log_err("ipsecmod: ipseckey has unsafe characters");

- +				return 0;

- +			}

- +			w += w_temp;

-  		}

-  	}

- -	sldns_str_print(&s, &slen, "\"");

- -	verbose(VERB_ALGO, "ipsecmod: hook command: '%s'", str);

- +	w += sldns_str_print(&s, &slen, "\"");

- +	if(w >= (int)sizeof(str)) {

- +		log_err("ipsecmod: shell command too long");

- +		return 0;

- +	}

- +	verbose(VERB_ALGO, "ipsecmod: shell command: '%s'", str);

-  	/* ipsecmod-hook should return 0 on success. */

-  	if(system(str) != 0)

-  		return 0;

@@ -1,14 +0,0 @@ 

- diff --git a/smallapp/unbound-anchor.c b/smallapp/unbound-anchor.c

- index 2bf5b3ab..a30523c7 100644

- --- a/smallapp/unbound-anchor.c

- +++ b/smallapp/unbound-anchor.c

- @@ -246,9 +246,7 @@ get_builtin_ds(void)

-  	return

-  /* The anchors must start on a new line with ". IN DS and end with \n"[;]

-   * because the makedist script greps on the source here */

- -/* anchor 19036 is from 2010 */

-  /* anchor 20326 is from 2017 */

- -". IN DS 19036 8 2 49AAC11D7B6F6446702E54A1607371607A1A41855200FD2CE1CDDE32F24E8FB5\n"

-  ". IN DS 20326 8 2 E06D44B80B8F1D39A95C0B0D7C65D08458E880409BBC683457104237C7F8EC8D\n";

-  }

-  

@@ -1,677 +0,0 @@ 

- diff --git a/config.h.in b/config.h.in

- index 04356f3..3b06bfa 100644

- --- a/config.h.in

- +++ b/config.h.in

- @@ -666,6 +666,9 @@

-  /* Shared data */

-  #undef SHARE_DIR

-  

- +/* The size of `size_t', as computed by sizeof. */

- +#undef SIZEOF_SIZE_T

- +

-  /* The size of `time_t', as computed by sizeof. */

-  #undef SIZEOF_TIME_T

-  

- diff --git a/configure.ac b/configure.ac

- index c5e0c7b..1bff4ed 100644

- --- a/configure.ac

- +++ b/configure.ac

- @@ -371,6 +371,7 @@ AC_INCLUDES_DEFAULT

-  # endif

-  #endif

-  ])

- +AC_CHECK_SIZEOF(size_t)

-  

-  # add option to disable the evil rpath

-  ACX_ARG_RPATH

- diff --git a/contrib/create_unbound_ad_servers.sh b/contrib/create_unbound_ad_servers.sh

- index d31f078..49fdbff 100644

- --- a/contrib/create_unbound_ad_servers.sh

- +++ b/contrib/create_unbound_ad_servers.sh

- @@ -9,12 +9,13 @@

-  # Variables

-  dst_dir="/etc/opt/csw/unbound"

-  work_dir="/tmp"

- -list_addr="http://pgl.yoyo.org/adservers/serverlist.php?hostformat=nohtml&showintro=1&startdate%5Bday%5D=&startdate%5Bmonth%5D=&startdate%5Byear%5D="

- +list_addr="https://pgl.yoyo.org/adservers/serverlist.php?hostformat=nohtml&showintro=1&startdate%5Bday%5D=&startdate%5Bmonth%5D=&startdate%5Byear%5D="

-  

-  # OS commands

-  CAT=`which cat`

-  ECHO=`which echo`

-  WGET=`which wget`

- +TR=`which tr`

-  

-  # Check Wget installed

-  if [ ! -f $WGET ]; then

- @@ -22,8 +23,10 @@ if [ ! -f $WGET ]; then

-   exit 1

-  fi

-  

- +# remove special characters with tr to protect unbound.conf

-  $WGET -O $work_dir/yoyo_ad_servers "$list_addr" && \

-  $CAT $work_dir/yoyo_ad_servers | \

- +$TR -d '";$\\' | \

-  while read line ; \

-   do \

-     $ECHO "local-zone: \"$line\" redirect" ;\

- @@ -36,4 +39,4 @@ echo "Done."

-  #  the unbound_ad_servers file:

-  #

-  #   include: $dst_dir/unbound_ad_servers

- -#

- \ No newline at end of file

- +#

- diff --git a/daemon/daemon.c b/daemon/daemon.c

- index 6820e11..1b4f329 100644

- --- a/daemon/daemon.c

- +++ b/daemon/daemon.c

- @@ -426,9 +426,7 @@ daemon_create_workers(struct daemon* daemon)

-  	int* shufport;

-  	log_assert(daemon && daemon->cfg);

-  	if(!daemon->rand) {

- -		unsigned int seed = (unsigned int)time(NULL) ^ 

- -			(unsigned int)getpid() ^ 0x438;

- -		daemon->rand = ub_initstate(seed, NULL);

- +		daemon->rand = ub_initstate(NULL);

-  		if(!daemon->rand)

-  			fatal_exit("could not init random generator");

-  		hash_set_raninit((uint32_t)ub_random(daemon->rand));

- diff --git a/daemon/worker.c b/daemon/worker.c

- index 3acecc1..8354010 100644

- --- a/daemon/worker.c

- +++ b/daemon/worker.c

- @@ -1629,18 +1629,14 @@ worker_create(struct daemon* daemon, int id, int* ports, int n)

-  		return NULL;

-  	}

-  	/* create random state here to avoid locking trouble in RAND_bytes */

- -	seed = (unsigned int)time(NULL) ^ (unsigned int)getpid() ^

- -		(((unsigned int)worker->thread_num)<<17);

- -		/* shift thread_num so it does not match out pid bits */

- -	if(!(worker->rndstate = ub_initstate(seed, daemon->rand))) {

- -		seed = 0;

- +	if(!(worker->rndstate = ub_initstate(daemon->rand))) {

-  		log_err("could not init random numbers.");

-  		tube_delete(worker->cmd);

-  		free(worker->ports);

-  		free(worker);

-  		return NULL;

-  	}

- -	seed = 0;

- +	explicit_bzero(&seed, sizeof(seed));

-  #ifdef USE_DNSTAP

-  	if(daemon->cfg->dnstap) {

-  		log_assert(daemon->dtenv != NULL);

- diff --git a/dns64/dns64.c b/dns64/dns64.c

- index 7889d72..300202c 100644

- --- a/dns64/dns64.c

- +++ b/dns64/dns64.c

- @@ -782,6 +782,16 @@ dns64_inform_super(struct module_qstate* qstate, int id,

-  	 * Signal that the sub-query is finished, no matter whether we are

-  	 * successful or not. This lets the state machine terminate.

-  	 */

- +	if(!super->minfo[id]) {

- +		super->minfo[id] = (enum dns64_qstate *)regional_alloc(super->region,

- +			sizeof(*(super->minfo[id])));

- +		if(!super->minfo[id]) {

- +			log_err("out of memory");

- +			super->return_rcode = LDNS_RCODE_SERVFAIL;

- +			super->return_msg = NULL;

- +			return;

- +		}

- +	}

- 	super->minfo[id] = (void*)DNS64_SUBQUERY_FINISHED;

-  

-  	/* If there is no successful answer, we're done. */

- diff --git a/dnscrypt/dnscrypt.c b/dnscrypt/dnscrypt.c

- index 3545d3d..7dd2ce5 100644

- --- a/dnscrypt/dnscrypt.c

- +++ b/dnscrypt/dnscrypt.c

- @@ -732,6 +732,11 @@ dnsc_load_local_data(struct dnsc_env* dnscenv, struct config_file *cfg)

-              );

-              continue;

-          }

- +        if((unsigned)strlen(dnscenv->provider_name) >= (unsigned)0xffff0000) {

- +		    /* guard against integer overflow in rrlen calculation */

- +		    verbose(VERB_OPS, "cert #%" PRIu32 " is too long", serial);

- +		    continue;

- +        }

-          rrlen = strlen(dnscenv->provider_name) +

-                           strlen(ttl_class_type) +

-                           4 * sizeof(struct SignedCert) + // worst case scenario

- diff --git a/doc/Changelog b/doc/Changelog

- index bb74461..4cb080e 100644

- --- a/doc/Changelog

- +++ b/doc/Changelog

- @@ -1,3 +1,55 @@

- +3 December 2019: Wouter

- +	- Fix Assert Causing DoS in synth_cname(),

- +	  reported by X41 D-Sec.

- +	- Fix Assert Causing DoS in dname_pkt_copy(),

- +	  reported by X41 D-Sec.

- +	- Fix OOB Read in sldns_wire2str_dname_scan(),

- +	  reported by X41 D-Sec.

- +	- Fix Out of Bounds Write in sldns_str2wire_str_buf(),

- +	  reported by X41 D-Sec.

- +	- Fix Out of Bounds Write in sldns_b64_pton(),

- +	  fixed by check in sldns_str2wire_int16_data_buf(),

- +	  reported by X41 D-Sec.

- +	- Fix Insufficient Handling of Compressed Names in dname_pkt_copy(),

- +	  reported by X41 D-Sec.

- +	- Fix Out of Bound Write Compressed Names in rdata_copy(),

- +	  reported by X41 D-Sec.

- +	- Fix Hang in sldns_wire2str_pkt_scan(),

- +	  reported by X41 D-Sec.

- +

- +20 November 2019: Wouter

- +	- Fix Out of Bounds Read in rrinternal_get_owner(),

- +	  reported by X41 D-Sec.

- +	- Fix Race Condition in autr_tp_create(),

- +	  reported by X41 D-Sec.

- +	- Fix Shared Memory World Writeable,

- +	  reported by X41 D-Sec.

- +	- Adjust unbound-control to make stats_shm a read only operation.

- +	- Fix Weak Entropy Used For Nettle,

- +	  reported by X41 D-Sec.

- +	- Fix Randomness Error not Handled Properly,

- +	  reported by X41 D-Sec.

- +	- Fix Out-of-Bounds Read in dname_valid(),

- +	  reported by X41 D-Sec.

- +	- Fix Config Injection in create_unbound_ad_servers.sh,

- +	  reported by X41 D-Sec.

- +

- +19 November 2019: Wouter

- +	- Fix Integer Overflow in Regional Allocator,

- +	  reported by X41 D-Sec.

- +	- Fix Unchecked NULL Pointer in dns64_inform_super()

- +	  and ipsecmod_new(), reported by X41 D-Sec.

- +	- Fix Out-of-bounds Read in rr_comment_dnskey(),

- +	  reported by X41 D-Sec.

- +	- Fix Integer Overflows in Size Calculations,

- +	  reported by X41 D-Sec.

- +	- Fix Integer Overflow to Buffer Overflow in

- +	  sldns_str2wire_dname_buf_origin(), reported by X41 D-Sec.

- +	- Fix Out of Bounds Read in sldns_str2wire_dname(),

- +	  reported by X41 D-Sec.

- +	- Fix Out of Bounds Write in sldns_bget_token_par(),

- +	  reported by X41 D-Sec.

- +

-  30 November 2018: Wouter

-  	- log-tag-queryreply: yes in unbound.conf tags the log-queries and

-  	  log-replies in the log file for easier log filter maintenance.

- diff --git a/ipsecmod/ipsecmod.c b/ipsecmod/ipsecmod.c

- index 3572f12..1422a62 100644

- --- a/ipsecmod/ipsecmod.c

- +++ b/ipsecmod/ipsecmod.c

- @@ -103,11 +103,11 @@ ipsecmod_new(struct module_qstate* qstate, int id)

-  {

-  	struct ipsecmod_qstate* iq = (struct ipsecmod_qstate*)regional_alloc(

-  		qstate->region, sizeof(struct ipsecmod_qstate));

- -	memset(iq, 0, sizeof(*iq));

-  	qstate->minfo[id] = iq;

-  	if(!iq)

-  		return 0;

-  	/* Initialise it. */

- +	memset(iq, 0, sizeof(*iq));

-  	iq->enabled = qstate->env->cfg->ipsecmod_enabled;

-  	iq->is_whitelisted = ipsecmod_domain_is_whitelisted(

-  		(struct ipsecmod_env*)qstate->env->modinfo[id], qstate->qinfo.qname,

- diff --git a/iterator/iter_scrub.c b/iterator/iter_scrub.c

- index 8230d17..942c3d5 100644

- --- a/iterator/iter_scrub.c

- +++ b/iterator/iter_scrub.c

- @@ -231,6 +231,10 @@ synth_cname(uint8_t* qname, size_t qnamelen, struct rrset_parse* dname_rrset,

-  	size_t dtarglen;

-  	if(!parse_get_cname_target(dname_rrset, &dtarg, &dtarglen, pkt))

-  		return 0; 

- +	if(qnamelen <= dname_rrset->dname_len)

- +		return 0;

- +	if(qnamelen == 0)

- +		return 0;

-  	log_assert(qnamelen > dname_rrset->dname_len);

-  	/* DNAME from com. to net. with qname example.com. -> example.net. */

-  	/* so: \3com\0 to \3net\0 and qname \7example\3com\0 */

- diff --git a/libunbound/libunbound.c b/libunbound/libunbound.c

- index 275e8d2..a8979c2 100644

- --- a/libunbound/libunbound.c

- +++ b/libunbound/libunbound.c

- @@ -83,7 +83,6 @@

-  static struct ub_ctx* ub_ctx_create_nopipe(void)

-  {

-  	struct ub_ctx* ctx;

- -	unsigned int seed;

-  #ifdef USE_WINSOCK

-  	int r;

-  	WSADATA wsa_data;

- @@ -107,15 +106,12 @@ static struct ub_ctx* ub_ctx_create_nopipe(void)

-  		return NULL;

-  	}

-  	alloc_init(&ctx->superalloc, NULL, 0);

- -	seed = (unsigned int)time(NULL) ^ (unsigned int)getpid();

- -	if(!(ctx->seed_rnd = ub_initstate(seed, NULL))) {

- -		seed = 0;

- +	if(!(ctx->seed_rnd = ub_initstate(NULL))) {

-  		ub_randfree(ctx->seed_rnd);

-  		free(ctx);

-  		errno = ENOMEM;

-  		return NULL;

-  	}

- -	seed = 0;

-  	lock_basic_init(&ctx->qqpipe_lock);

-  	lock_basic_init(&ctx->rrpipe_lock);

-  	lock_basic_init(&ctx->cfglock);

- diff --git a/libunbound/libworker.c b/libunbound/libworker.c

- index 3dcaa78..07a08c6 100644

- --- a/libunbound/libworker.c

- +++ b/libunbound/libworker.c

- @@ -122,7 +122,6 @@ libworker_delete_event(struct libworker* w)

-  static struct libworker*

-  libworker_setup(struct ub_ctx* ctx, int is_bg, struct ub_event_base* eb)

-  {

- -	unsigned int seed;

-  	struct libworker* w = (struct libworker*)calloc(1, sizeof(*w));

-  	struct config_file* cfg = ctx->env->cfg;

-  	int* ports;

- @@ -177,17 +176,13 @@ libworker_setup(struct ub_ctx* ctx, int is_bg, struct ub_event_base* eb)

-  	}

-  	w->env->worker = (struct worker*)w;

-  	w->env->probe_timer = NULL;

- -	seed = (unsigned int)time(NULL) ^ (unsigned int)getpid() ^

- -		(((unsigned int)w->thread_num)<<17);

- -	seed ^= (unsigned int)w->env->alloc->next_id;

-  	if(!w->is_bg || w->is_bg_thread) {

-  		lock_basic_lock(&ctx->cfglock);

-  	}

- -	if(!(w->env->rnd = ub_initstate(seed, ctx->seed_rnd))) {

- +	if(!(w->env->rnd = ub_initstate(ctx->seed_rnd))) {

-  		if(!w->is_bg || w->is_bg_thread) {

-  			lock_basic_unlock(&ctx->cfglock);

-  		}

- -		seed = 0;

-  		libworker_delete(w);

-  		return NULL;

-  	}

- @@ -207,7 +202,6 @@ libworker_setup(struct ub_ctx* ctx, int is_bg, struct ub_event_base* eb)

-  			hash_set_raninit((uint32_t)ub_random(w->env->rnd));

-  		}

-  	}

- -	seed = 0;

-  

-  	if(eb)

-  		w->base = comm_base_create_event(eb);

- diff --git a/respip/respip.c b/respip/respip.c

- index 2e9313f..7d2a588 100644

- --- a/respip/respip.c

- +++ b/respip/respip.c

- @@ -475,10 +475,16 @@ copy_rrset(const struct ub_packed_rrset_key* key, struct regional* region)

-  	if(!ck->rk.dname)

-  		return NULL;

-  

- +	if((unsigned)data->count >= 0xffff00U)

- +		return NULL; /* guard against integer overflow in dsize */

-  	dsize = sizeof(struct packed_rrset_data) + data->count *

-  		(sizeof(size_t)+sizeof(uint8_t*)+sizeof(time_t));

- -	for(i=0; i<data->count; i++)

- +	for(i=0; i<data->count; i++) {

- +		if((unsigned)dsize >= 0x0fffffffU ||

- +			(unsigned)data->rr_len[i] >= 0x0fffffffU)

- +			return NULL; /* guard against integer overflow */

-  		dsize += data->rr_len[i];

- +	}

-  	d = regional_alloc(region, dsize);

-  	if(!d)

-  		return NULL;

- diff --git a/sldns/parse.c b/sldns/parse.c

- index b62c405..b30264e 100644

- --- a/sldns/parse.c

- +++ b/sldns/parse.c

- @@ -325,8 +325,14 @@ sldns_bget_token_par(sldns_buffer *b, char *token, const char *delim,

-  		if (c == '\n' && p != 0) {

-  			/* in parentheses */

-  			/* do not write ' ' if we want to skip spaces */

- -			if(!(skipw && (strchr(skipw, c)||strchr(skipw, ' '))))

- +			if(!(skipw && (strchr(skipw, c)||strchr(skipw, ' ')))) {

- +				/* check for space for the space character */

- +				if (limit > 0 && (i >= limit || (size_t)(t-token) >= limit)) {

- +					*t = '\0';

- +					return -1;

- +				}

-  				*t++ = ' ';

- +			}

-  			lc = c;

-  			continue;

-  		}

- diff --git a/sldns/str2wire.c b/sldns/str2wire.c

- index 1a51bb6..414b7b8 100644

- --- a/sldns/str2wire.c

- +++ b/sldns/str2wire.c

- @@ -150,6 +150,10 @@ int sldns_str2wire_dname_buf_origin(const char* str, uint8_t* buf, size_t* len,

-  	if(s) return s;

-  

-  	if(rel && origin && dlen > 0) {

- +		if((unsigned)dlen >= 0x00ffffffU ||

- +			(unsigned)origin_len >= 0x00ffffffU)

- +			/* guard against integer overflow in addition */

- +			return RET_ERR(LDNS_WIREPARSE_ERR_GENERAL, *len);

-  		if(dlen + origin_len - 1 > LDNS_MAX_DOMAINLEN)

-  			return RET_ERR(LDNS_WIREPARSE_ERR_DOMAINNAME_OVERFLOW,

-  				LDNS_MAX_DOMAINLEN);

- @@ -168,7 +172,9 @@ uint8_t* sldns_str2wire_dname(const char* str, size_t* len)

-  	uint8_t dname[LDNS_MAX_DOMAINLEN+1];

-  	*len = sizeof(dname);

-  	if(sldns_str2wire_dname_buf(str, dname, len) == 0) {

- -		uint8_t* r = (uint8_t*)malloc(*len);

- +		uint8_t* r;

- +		if(*len > sizeof(dname)) return NULL;

- +		r = (uint8_t*)malloc(*len);

-  		if(r) return memcpy(r, dname, *len);

-  	}

-  	*len = 0;

- @@ -187,6 +193,9 @@ rrinternal_get_owner(sldns_buffer* strbuf, uint8_t* rr, size_t* len,

-  			sldns_buffer_position(strbuf));

-  	}

-  

- +	if(token_len < 2) /* make sure there is space to read "@" or "" */

- +		return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL,

- +			sldns_buffer_position(strbuf));

-  	if(strcmp(token, "@") == 0) {

-  		uint8_t* tocopy;

-  		if (origin) {

- @@ -1094,7 +1103,7 @@ int sldns_str2wire_str_buf(const char* str, uint8_t* rd, size_t* len)

-  	while(sldns_parse_char(&ch, &s)) {

-  		if(sl >= 255)

-  			return RET_ERR(LDNS_WIREPARSE_ERR_INVALID_STR, s-str);

- -		if(*len < sl+1)

- +		if(*len < sl+2)

-  			return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL,

-  				s-str);

-  		rd[++sl] = ch;

- @@ -2095,6 +2104,8 @@ int sldns_str2wire_int16_data_buf(const char* str, uint8_t* rd, size_t* len)

-  	char* s;

-  	int n;

-  	n = strtol(str, &s, 10);

- +	if(n < 0) /* negative number not allowed */

- +		return LDNS_WIREPARSE_ERR_SYNTAX;

-  	if(*len < ((size_t)n)+2)

-  		return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL;

-  	if(n > 65535)

- diff --git a/sldns/wire2str.c b/sldns/wire2str.c

- index 832239f..a95c9b3 100644

- --- a/sldns/wire2str.c

- +++ b/sldns/wire2str.c

- @@ -585,6 +585,7 @@ static int rr_comment_dnskey(char** s, size_t* slen, uint8_t* rr,

-  	if(rrlen < dname_off + 10) return 0;

-  	rdlen = sldns_read_uint16(rr+dname_off+8);

-  	if(rrlen < dname_off + 10 + rdlen) return 0;

- +	if(rdlen < 2) return 0;

-  	rdata = rr + dname_off + 10;

-  	flags = (int)sldns_read_uint16(rdata);

-  	w += sldns_str_print(s, slen, " ;{");

- @@ -781,7 +782,7 @@ int sldns_wire2str_dname_scan(uint8_t** d, size_t* dlen, char** s, size_t* slen,

-  	/* spool labels onto the string, use compression if its there */

-  	uint8_t* pos = *d;

-  	unsigned i, counter=0;

- -	const unsigned maxcompr = 1000; /* loop detection, max compr ptrs */

- +	const unsigned maxcompr = 256; /* loop detection, max compr ptrs */

-  	int in_buf = 1;

-  	if(*dlen == 0) return sldns_str_print(s, slen, "ErrorMissingDname");

-  	if(*pos == 0) {

- @@ -789,7 +790,7 @@ int sldns_wire2str_dname_scan(uint8_t** d, size_t* dlen, char** s, size_t* slen,

-  		(*dlen)--;

-  		return sldns_str_print(s, slen, ".");

-  	}

- -	while(*pos) {

- +	while((!pkt || pos < pkt+pktlen) && *pos) {

-  		/* read label length */

-  		uint8_t labellen = *pos++;

-  		if(in_buf) { (*d)++; (*dlen)--; }

- diff --git a/smallapp/unbound-control.c b/smallapp/unbound-control.c

- index d165417..2884309 100644

- --- a/smallapp/unbound-control.c

- +++ b/smallapp/unbound-control.c

- @@ -407,19 +407,19 @@ static void print_stats_shm(const char* cfgfile)

-  	if(!config_read(cfg, cfgfile, NULL))

-  		fatal_exit("could not read config file");

-  	/* get shm segments */

- -	id_ctl = shmget(cfg->shm_key, sizeof(int), SHM_R|SHM_W);

- +	id_ctl = shmget(cfg->shm_key, sizeof(int), SHM_R);

-  	if(id_ctl == -1) {

-  		fatal_exit("shmget(%d): %s", cfg->shm_key, strerror(errno));

-  	}

- -	id_arr = shmget(cfg->shm_key+1, sizeof(int), SHM_R|SHM_W);

- +	id_arr = shmget(cfg->shm_key+1, sizeof(int), SHM_R);

-  	if(id_arr == -1) {

-  		fatal_exit("shmget(%d): %s", cfg->shm_key+1, strerror(errno));

-  	}

- -	shm_stat = (struct ub_shm_stat_info*)shmat(id_ctl, NULL, 0);

- +	shm_stat = (struct ub_shm_stat_info*)shmat(id_ctl, NULL, SHM_RDONLY);

-  	if(shm_stat == (void*)-1) {

-  		fatal_exit("shmat(%d): %s", id_ctl, strerror(errno));

-  	}

- -	stats = (struct ub_stats_info*)shmat(id_arr, NULL, 0);

- +	stats = (struct ub_stats_info*)shmat(id_arr, NULL, SHM_RDONLY);

-  	if(stats == (void*)-1) {

-  		fatal_exit("shmat(%d): %s", id_arr, strerror(errno));

-  	}

- diff --git a/testcode/unitmain.c b/testcode/unitmain.c

- index fecde80..96a6654 100644

- --- a/testcode/unitmain.c

- +++ b/testcode/unitmain.c

- @@ -537,10 +537,8 @@ rnd_test(void)

-  	struct ub_randstate* r;

-  	int num = 1000, i;

-  	long int a[1000];

- -	unsigned int seed = (unsigned)time(NULL);

-  	unit_show_feature("ub_random");

- -	printf("ub_random seed is %u\n", seed);

- -	unit_assert( (r = ub_initstate(seed, NULL)) );

- +	unit_assert( (r = ub_initstate(NULL)) );

-  	for(i=0; i<num; i++) {

-  		a[i] = ub_random(r);

-  		unit_assert(a[i] >= 0);

- diff --git a/util/data/dname.c b/util/data/dname.c

- index b744f06..923be02 100644

- --- a/util/data/dname.c

- +++ b/util/data/dname.c

- @@ -75,6 +75,8 @@ dname_valid(uint8_t* dname, size_t maxlen)

-  {

-  	size_t len = 0;

-  	size_t labellen;

- +	if(maxlen == 0)

- +		return 0; /* too short, shortest is '0' root label */

-  	labellen = *dname++;

-  	while(labellen) {

-  		if(labellen&0xc0)

- @@ -345,11 +347,17 @@ dname_pkt_hash(sldns_buffer* pkt, uint8_t* dname, hashvalue_type h)

-  void dname_pkt_copy(sldns_buffer* pkt, uint8_t* to, uint8_t* dname)

-  {

-  	/* copy over the dname and decompress it at the same time */

- +	size_t comprcount = 0;

-  	size_t len = 0;

-  	uint8_t lablen;

-  	lablen = *dname++;

-  	while(lablen) {

-  		if(LABEL_IS_PTR(lablen)) {

- +			if(comprcount++ > MAX_COMPRESS_PTRS) {

- +				/* too many compression pointers */

- +				*to = 0; /* end the result prematurely */

- +				return;

- +			}

-  			/* follow pointer */

-              if((size_t)PTR_OFFSET(lablen, *dname)

-                  >= sldns_buffer_limit(pkt))

- @@ -358,6 +366,10 @@ void dname_pkt_copy(sldns_buffer* pkt, uint8_t* to, uint8_t* dname)

-  			lablen = *dname++;

-  			continue;

-  		}

- +		if(lablen > LDNS_MAX_LABELLEN) {

- +			*to = 0; /* end the result prematurely */

- +			return;

- +		}

-  		log_assert(lablen <= LDNS_MAX_LABELLEN);

-  		len += (size_t)lablen+1;

-  		if(len >= LDNS_MAX_DOMAINLEN) {

- diff --git a/util/data/msgreply.c b/util/data/msgreply.c

- index df2131c..dbae34d 100644

- --- a/util/data/msgreply.c

- +++ b/util/data/msgreply.c

- @@ -238,10 +238,10 @@ rdata_copy(sldns_buffer* pkt, struct packed_rrset_data* data, uint8_t* to,

-  				break;

-  			}

-  			if(len) {

- +				log_assert(len <= pkt_len);

-  				memmove(to, sldns_buffer_current(pkt), len);

-  				to += len;

-  				sldns_buffer_skip(pkt, (ssize_t)len);

- -				log_assert(len <= pkt_len);

-  				pkt_len -= len;

-  			}

-  			rdf++;

- diff --git a/util/random.c b/util/random.c

- index 8332960..9380502 100644

- --- a/util/random.c

- +++ b/util/random.c

- @@ -86,8 +86,7 @@ ub_systemseed(unsigned int ATTR_UNUSED(seed))

-  }

-  

-  struct ub_randstate* 

- -ub_initstate(unsigned int ATTR_UNUSED(seed),

- -	struct ub_randstate* ATTR_UNUSED(from))

- +ub_initstate(struct ub_randstate* ATTR_UNUSED(from))

-  {

-  	struct ub_randstate* s = (struct ub_randstate*)malloc(1);

-  	if(!s) {

- @@ -123,8 +122,8 @@ void ub_systemseed(unsigned int ATTR_UNUSED(seed))

-  {

-  }

-  

- -struct ub_randstate* ub_initstate(unsigned int ATTR_UNUSED(seed), 

- -	struct ub_randstate* ATTR_UNUSED(from))

- +struct ub_randstate* 

- +ub_initstate(struct ub_randstate* ATTR_UNUSED(from))

-  {

-  	struct ub_randstate* s = (struct ub_randstate*)calloc(1, sizeof(*s));

-  	if(!s) {

- @@ -140,7 +139,9 @@ long int ub_random(struct ub_randstate* ATTR_UNUSED(state))

-  	/* random 31 bit value. */

-  	SECStatus s = PK11_GenerateRandom((unsigned char*)&x, (int)sizeof(x));

-  	if(s != SECSuccess) {

- -		log_err("PK11_GenerateRandom error: %s",

- +		/* unbound needs secure randomness for randomized

- +		 * ID bits and port numbers in packets to upstream servers */

- +		fatal_exit("PK11_GenerateRandom error: %s",

-  			PORT_ErrorToString(PORT_GetError()));

-  	}

-  	return x & MAX_VALUE;

- @@ -166,8 +167,7 @@ void ub_systemseed(unsigned int ATTR_UNUSED(seed))

-  	log_err("Re-seeding not supported, generator untouched");

-  }

-  

- -struct ub_randstate* ub_initstate(unsigned int seed,

- -	struct ub_randstate* ATTR_UNUSED(from))

- +struct ub_randstate* ub_initstate(struct ub_randstate* ATTR_UNUSED(from))

-  {

-  	struct ub_randstate* s = (struct ub_randstate*)calloc(1, sizeof(*s));

-  	uint8_t buf[YARROW256_SEED_FILE_SIZE];

- @@ -183,15 +183,10 @@ struct ub_randstate* ub_initstate(unsigned int seed,

-  		yarrow256_seed(&s->ctx, YARROW256_SEED_FILE_SIZE, buf);

-  		s->seeded = yarrow256_is_seeded(&s->ctx);

-  	} else {

- -		/* Stretch the uint32 input seed and feed it to Yarrow */

- -		uint32_t v = seed;

- -		size_t i;

- -		for(i=0; i < (YARROW256_SEED_FILE_SIZE/sizeof(seed)); i++) {

- -			memmove(buf+i*sizeof(seed), &v, sizeof(seed));

- -			v = v*seed + (uint32_t)i;

- -		}

- -		yarrow256_seed(&s->ctx, YARROW256_SEED_FILE_SIZE, buf);

- -		s->seeded = yarrow256_is_seeded(&s->ctx);

- +		log_err("nettle random(yarrow) cannot initialize, "

- +			"getentropy failed: %s", strerror(errno));

- +		free(s);

- +		return NULL;

-  	}

-  

-  	return s;

- diff --git a/util/random.h b/util/random.h

- index a05a994..e75157d 100644

- --- a/util/random.h

- +++ b/util/random.h

- @@ -57,15 +57,12 @@ void ub_systemseed(unsigned int seed);

-  

-  /**

-   * Initialize a random generator state for use 

- - * @param seed: seed value to create state contents.

- - *	(ignored for arc4random).

-   * @param from: if not NULL, the seed is taken from this random structure.

-   * 	can be used to seed random states via a parent-random-state that

-   * 	is itself seeded with entropy.

-   * @return new state or NULL alloc failure.

-   */

- -struct ub_randstate* ub_initstate(unsigned int seed, 

- -	struct ub_randstate* from);

- +struct ub_randstate* ub_initstate(struct ub_randstate* from);

-  

-  /**

-   * Generate next random number from the state passed along.

- diff --git a/util/regional.c b/util/regional.c

- index 899a54e..5be09eb 100644

- --- a/util/regional.c

- +++ b/util/regional.c

- @@ -120,8 +120,18 @@ regional_destroy(struct regional *r)

-  void *

-  regional_alloc(struct regional *r, size_t size)

-  {

- -	size_t a = ALIGN_UP(size, ALIGNMENT);

- +	size_t a;

-  	void *s;

- +	if(

- +#if SIZEOF_SIZE_T == 8

- +		(unsigned long long)size >= 0xffffffffffffff00ULL

- +#else

- +		(unsigned)size >= (unsigned)0xffffff00UL

- +#endif

- +		)

- +		return NULL; /* protect against integer overflow in

- +			malloc and ALIGN_UP */

- +	a = ALIGN_UP(size, ALIGNMENT);

-  	/* large objects */

-  	if(a > REGIONAL_LARGE_OBJECT_SIZE) {

-  		s = malloc(ALIGNMENT + size);

- diff --git a/util/shm_side/shm_main.c b/util/shm_side/shm_main.c

- index a783c09..69bee4d 100644

- --- a/util/shm_side/shm_main.c

- +++ b/util/shm_side/shm_main.c

- @@ -121,7 +121,7 @@ int shm_main_init(struct daemon* daemon)

-  		shmctl(daemon->shm_info->id_arr, IPC_RMID, NULL);

-  

-  	/* SHM: Create the segment */

- -	daemon->shm_info->id_ctl = shmget(daemon->shm_info->key, sizeof(struct ub_shm_stat_info), IPC_CREAT | 0666);

- +	daemon->shm_info->id_ctl = shmget(daemon->shm_info->key, sizeof(struct ub_shm_stat_info), IPC_CREAT | 0644);

-  

-  	if (daemon->shm_info->id_ctl < 0)

-  	{

- @@ -134,7 +134,7 @@ int shm_main_init(struct daemon* daemon)

-  		return 0;

-  	}

-  

- -	daemon->shm_info->id_arr = shmget(daemon->shm_info->key + 1, shm_size, IPC_CREAT | 0666);

- +	daemon->shm_info->id_arr = shmget(daemon->shm_info->key + 1, shm_size, IPC_CREAT | 0644);

-  

-  	if (daemon->shm_info->id_arr < 0)

-  	{

- diff --git a/validator/autotrust.c b/validator/autotrust.c

- index 7bc5577..e19bd7b 100644

- --- a/validator/autotrust.c

- +++ b/validator/autotrust.c

- @@ -370,10 +370,10 @@ autr_tp_create(struct val_anchors* anchors, uint8_t* own, size_t own_len,

-  		free(tp);

-  		return NULL;

-  	}

- -	lock_basic_unlock(&anchors->lock);

-  	lock_basic_init(&tp->lock);

-  	lock_protect(&tp->lock, tp, sizeof(*tp));

-  	lock_protect(&tp->lock, tp->autr, sizeof(*tp->autr));

- +	lock_basic_unlock(&anchors->lock);

-  	return tp;

-  }

-  

@@ -1,43 +0,0 @@ 

- diff --git a/unbound-1.7.3/daemon/unbound.c b/unbound-1.7.3/daemon/unbound.c

- index 1383110..66ed61d 100644

- --- a/daemon/unbound.c

- +++ b/daemon/unbound.c

- @@ -327,18 +327,32 @@ readpid (const char* file)

-  static void

-  writepid (const char* pidfile, pid_t pid)

-  {

- -	FILE* f;

- +	int fd;

- +	char pidbuf[32];

- +	size_t count = 0;

- +	snprintf(pidbuf, sizeof(pidbuf), "%lu\n", (unsigned long)pid);

-  

- -	if ((f = fopen(pidfile, "w")) ==  NULL ) {

- +    if((fd = open(pidfile, O_WRONLY | O_CREAT | O_TRUNC

- +#ifdef O_NOFOLLOW

- +		| O_NOFOLLOW

- +#endif

- +		, 0644)) == -1) {

-  		log_err("cannot open pidfile %s: %s", 

-  			pidfile, strerror(errno));

-  		return;

-  	}

- -	if(fprintf(f, "%lu\n", (unsigned long)pid) < 0) {

- -		log_err("cannot write to pidfile %s: %s", 

- -			pidfile, strerror(errno));

- +    while(count < strlen(pidbuf)) {

- +		ssize_t r = write(fd, pidbuf+count, strlen(pidbuf)-count);

- +		if(r == -1) {

- +			if(errno == EAGAIN || errno == EINTR)

- +				continue;

- +			log_err("cannot write to pidfile %s: %s",

- +				pidfile, strerror(errno));

- +			break;

- +		}

- +		count += r;

-  	}

- -	fclose(f);

- +	close(fd);

-  }

-  

-  /**

@@ -1,109 +0,0 @@ 

- diff --git a/util/log.c b/util/log.c

- index 75a58f9..43dd572 100644

- --- a/util/log.c

- +++ b/util/log.c

- @@ -70,7 +70,7 @@ static int key_created = 0;

-  static ub_thread_key_type logkey;

-  #ifndef THREADS_DISABLED

-  /** pthread mutex to protect FILE* */

- -static lock_quick_type log_lock;

- +static lock_basic_type log_lock;

-  #endif

-  /** the identity of this executable/process */

-  static const char* ident="unbound";

- @@ -90,18 +90,18 @@ log_init(const char* filename, int use_syslog, const char* chrootdir)

-  	if(!key_created) {

-  		key_created = 1;

-  		ub_thread_key_create(&logkey, NULL);

- -		lock_quick_init(&log_lock);

- +		lock_basic_init(&log_lock);

-  	}

- -	lock_quick_lock(&log_lock);

- +	lock_basic_lock(&log_lock);

-  	if(logfile 

-  #if defined(HAVE_SYSLOG_H) || defined(UB_ON_WINDOWS)

-  	|| logging_to_syslog

-  #endif

-  	) {

- -		lock_quick_unlock(&log_lock); /* verbose() needs the lock */

- +		lock_basic_unlock(&log_lock); /* verbose() needs the lock */

-  		verbose(VERB_QUERY, "switching log to %s", 

-  			use_syslog?"syslog":(filename&&filename[0]?filename:"stderr"));

- -		lock_quick_lock(&log_lock);

- +		lock_basic_lock(&log_lock);

-  	}

-  	if(logfile && logfile != stderr) {

-  		FILE* cl = logfile;

- @@ -119,7 +119,7 @@ log_init(const char* filename, int use_syslog, const char* chrootdir)

-  		 * chroot and no longer be able to access dev/log and so on */

-  		openlog(ident, LOG_NDELAY, LOG_DAEMON);

-  		logging_to_syslog = 1;

- -		lock_quick_unlock(&log_lock);

- +		lock_basic_unlock(&log_lock);

-  		return;

-  	}

-  #elif defined(UB_ON_WINDOWS)

- @@ -128,13 +128,13 @@ log_init(const char* filename, int use_syslog, const char* chrootdir)

-  	}

-  	if(use_syslog) {

-  		logging_to_syslog = 1;

- -		lock_quick_unlock(&log_lock);

- +		lock_basic_unlock(&log_lock);

-  		return;

-  	}

-  #endif /* HAVE_SYSLOG_H */

-  	if(!filename || !filename[0]) {

-  		logfile = stderr;

- -		lock_quick_unlock(&log_lock);

- +		lock_basic_unlock(&log_lock);

-  		return;

-  	}

-  	/* open the file for logging */

- @@ -143,7 +143,7 @@ log_init(const char* filename, int use_syslog, const char* chrootdir)

-  		filename += strlen(chrootdir);

-  	f = fopen(filename, "a");

-  	if(!f) {

- -		lock_quick_unlock(&log_lock);

- +		lock_basic_unlock(&log_lock);

-  		log_err("Could not open logfile %s: %s", filename, 

-  			strerror(errno));

-  		return;

- @@ -153,14 +153,14 @@ log_init(const char* filename, int use_syslog, const char* chrootdir)

-  	setvbuf(f, NULL, (int)_IOLBF, 0);

-  #endif

-  	logfile = f;

- -	lock_quick_unlock(&log_lock);

- +	lock_basic_unlock(&log_lock);

-  }

-  

-  void log_file(FILE *f)

-  {

- -	lock_quick_lock(&log_lock);

- +	lock_basic_lock(&log_lock);

-  	logfile = f;

- -	lock_quick_unlock(&log_lock);

- +	lock_basic_unlock(&log_lock);

-  }

-  

-  void log_thread_set(int* num)

- @@ -250,9 +250,9 @@ log_vmsg(int pri, const char* type,

-  		return;

-  	}

-  #endif /* HAVE_SYSLOG_H */

- -	lock_quick_lock(&log_lock);

- +	lock_basic_lock(&log_lock);

-  	if(!logfile) {

- -		lock_quick_unlock(&log_lock);

- +		lock_basic_unlock(&log_lock);

-  		return;

-  	}

-  	if(log_now)

- @@ -279,7 +279,7 @@ log_vmsg(int pri, const char* type,

-  	/* line buffering does not work on windows */

-  	fflush(logfile);

-  #endif

- -	lock_quick_unlock(&log_lock);

- +	lock_basic_unlock(&log_lock);

-  }

-  

-  /**

file modified
+5 -31
@@ -33,8 +33,8 @@ 

  

  Summary: Validating, recursive, and caching DNS(SEC) resolver

  Name: unbound

- Version: 1.7.3

- Release: 15%{?extra_version:.%{extra_version}}%{?dist}

+ Version: 1.13.1

+ Release: 1%{?extra_version:.%{extra_version}}%{?dist}

  License: BSD

  Url: https://www.unbound.net/

  Source: https://www.unbound.net/downloads/%{name}-%{version}%{?extra_version}.tar.gz
@@ -55,21 +55,6 @@ 

  Source16: unbound-munin.README

  Source17: unbound-anchor.service

  

- Patch2: unbound-1.7.2-python3-devel.patch

- Patch3: unbound-1.7.2-python3-pkgconfig.patch

- Patch4: unbound-1.7.3-anchor-fallback.patch

- Patch5: unbound-1.7.3-host-any.patch

- Patch6: unbound-1.7.3-use-basic-lock.patch

- Patch7: unbound-1.7.3-ipsec-hook.patch

- Patch8: unbound-1.7.3-auth-callback.patch

- Patch9: unbound-1.7.3-ksk-2010-revoked.patch

- Patch10: unbound-1.7.3-DNS-over-TLS-memory-leak.patch

- Patch11: unbound-1.7.3-amplifying-an-incoming-query.patch

- Patch12: unbound-1.7.3-crypto-policy-non-compliance-openssl.patch

- Patch13: unbound-1.7.3-additional-logging.patch

- Patch14: unbound-1.7.3-security-hardening.patch

- Patch15: unbound-1.7.3-symlink-traversal.patch

- 

  BuildRequires: gdb

  BuildRequires: gcc, make

  BuildRequires: byacc, flex, openssl-devel
@@ -165,20 +150,6 @@ 

  %setup -qcn %{pkgname}

  

  pushd %{pkgname}

- %patch2 -p1 -b .python3

- %patch3 -p1 -b .python3

- %patch4 -p1 -b .anchor-fallback

- %patch5 -p1 -b .host-any

- %patch6 -p1 -b .use-basic-lock

- %patch7 -p1 -b .ipsec-hook

- %patch8 -p1 -b .auth-callback

- %patch9 -p1 -b .ksk-2010-revoked

- %patch10 -p1 -b .DNS-over-TLS-memory-leak

- %patch11 -p1 -b .amplifying-an-incoming-query

- %patch12 -p1 -b .crypto-policy

- %patch13 -p1 -b .additional-logging

- %patch14 -p1 -b .security-hardening

- %patch15 -p1 -b .symlink-traversal

  

  # only for snapshots

  # autoreconf -iv
@@ -452,6 +423,9 @@ 

  %verify(not md5 size mtime) %{_sharedstatedir}/%{name}/root.key

  

  %changelog

+ * Fri Mar 19 2021 Matthew Almond <malmond@fb.com> - 1.13.1-1

+ - Simple test rebuild with a version bump. Goal is to test CentOS SIG PR workflow

+ 

  * Tue Sep 01 2020 Anna Khaitovich <akhaitov@redhat.com> - 1.7.3-15

  - Fix SPEC file to not check md5 mtime and size of /var/lib/unbound/root.key

  - Resolves: rhbz#1714175