unbound 1.10.0

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

unbound 1.10.0

Stuart Henderson
Lots of churn again.. most of the new + are related to the new rpz and
serve-stale support. I've been running it for a few days with my usual
setup with no problems, haven't tried the new things yet. Anyone want
to test?


 Makefile.in                  |  784 +++++++++++++++++----------------
 README                       |    2
 README.md                    |    2
 aclocal.m4                   |  115 +++-
 cachedb/cachedb.c            |   94 ++-
 config.guess                 |  586 ++++++++++++------------
 config.h.in                  |   20
 config.sub                   |  262 ++++++-----
 configure                    |  257 ++++++++--
 configure.ac                 |   69 ++
 daemon/daemon.c              |    9
 daemon/daemon.h              |    2
 daemon/remote.c              |   40 +
 daemon/stats.c               |    8
 daemon/unbound.c             |   25 -
 daemon/worker.c              |  146 +++---
 doc/Changelog                |  169 +++++++
 doc/README                   |    2
 doc/example.conf.in          |   33 +
 doc/libunbound.3.in          |   11
 doc/unbound-anchor.8.in      |    2
 doc/unbound-checkconf.8.in   |    2
 doc/unbound-control.8.in     |   16
 doc/unbound-host.1.in        |    2
 doc/unbound.8.in             |    4
 doc/unbound.conf.5.in        |  120 ++++-
 edns-subnet/subnetmod.c      |    2
 install-sh                   |   25 -
 libunbound/context.c         |    3
 libunbound/libworker.c       |    1
 libunbound/unbound.h         |   13
 respip/respip.c              |  325 +++++++++----
 respip/respip.h              |   99 +++-
 services/authzone.c          |   97 +++-
 services/authzone.h          |   11
 services/cache/dns.c         |  118 ++--
 services/cache/dns.h         |    7
 services/localzone.c         |  220 ++++++---
 services/localzone.h         |  115 ++++
 services/mesh.c              |  426 ++++++++++++++++--
 services/mesh.h              |   31 +
 services/outside_network.c   |    8
 services/rpz.c               | 1015 +++++++++++++++++++++++++++++++++++++++++++
 services/rpz.h               |  201 ++++++++
 services/view.c              |    2
 sldns/parse.c                |   11
 sldns/str2wire.c             |    4
 smallapp/unbound-checkconf.c |   34 +
 smallapp/unbound-control.c   |   21
 testcode/petal.c             |    2
 testcode/replay.h            |   20
 testcode/unitdname.c         |   29 +
 util/config_file.c           |   49 +-
 util/config_file.h           |   22
 util/configlexer.lex         |    8
 util/configparser.y          |  133 +++++
 util/data/dname.c            |   28 +
 util/data/dname.h            |    9
 util/data/msgencode.c        |    6
 util/data/msgparse.h         |    4
 util/data/msgreply.c         |    4
 util/data/packed_rrset.c     |   21
 util/data/packed_rrset.h     |   13
 util/fptr_wlist.c            |    7
 util/fptr_wlist.h            |    7
 util/iana_ports.inc          |    1
 util/log.c                   |   19
 util/log.h                   |   20
 util/module.h                |   21
 util/net_help.c              |  123 +++++
 util/net_help.h              |   15
 util/netevent.c              |    8
 util/random.c                |    8
 util/storage/dnstree.c       |   13
 util/storage/dnstree.h       |    7
 validator/val_secalgo.c      |   31 +
 validator/validator.c        |    6
 77 files changed, 4779 insertions(+), 1426 deletions(-)

Index: doc/Changelog
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/doc/Changelog,v
retrieving revision 1.35
diff -u -p -r1.35 Changelog
--- doc/Changelog 18 Dec 2019 11:04:13 -0000 1.35
+++ doc/Changelog 15 Mar 2020 16:31:04 -0000
@@ -1,6 +1,175 @@
+20 February 2020: Wouter
+ - Updated contrib/unbound_smf23.tar.gz with Solaris SMF service for
+  Unbound from Yuri Voinov.
+
+17 February 2020: Ralph
+ - Add respip to supported module-config options in unbound-checkconf.
+
+17 February 2020: George
+ - Remove unused variable.
+
+17 February 2020: Wouter
+ - contrib/drop2rpz: perl script that converts the Spamhaus DROP-List
+  in RPZ-Format, contributed by Andreas Schulze.
+
+14 February 2020: Wouter
+ - Fix spelling in unbound.conf.5.in.
+ - Stop unbound-checkconf from insisting that auth-zone and rpz
+  zonefiles have to exist.  They can not exist, and download later.
+
+13 February 2020: Wouter
+ - tag for 1.10.0rc1 release.
+
+12 February 2020: Wouter
+ - Fix with libnettle make test with dsa disabled.
+ - Fix contrib/fastrpz.patch to apply cleanly.  Fix for serve-stale
+  fixes, but it does not compile, conflicts with new rpz code.
+ - Fix to clean memory leak of respip_addr.lock when ip_tree deleted.
+ - Fix compile warning when threads disabled.
+ - updated version number to 1.10.0.
+
+10 February 2020: George
+ - Document 'ub_result.was_ratelimited' in libunbound.
+ - Fix use after free on log-identity after a reload; Fixes #163.
+
+6 February 2020: George
+ - Fix num_reply_states and num_detached_states counting with
+  serve_expired_callback.
+ - Cleaner code in mesh_serve_expired_lookup.
+ - Document in unbound.conf manpage that configuration clauses can be
+  repeated in the configuration file.
+
+6 February 2020: Wouter
+ - Fix num_reply_addr counting in mesh and tcp drop due to size
+  after serve_stale commit.
+ - Fix to create and destroy rpz_lock in auth_zones structure.
+ - Fix to lock zone before adding rpz qname trigger.
+ - Fix to lock and release once in mesh_serve_expired_lookup.
+ - Fix to put braces around empty if body when threading is disabled.
+
+5 February 2020: George
+ - Added serve-stale functionality as described in
+  draft-ietf-dnsop-serve-stale-10. `serve-expired-*` options can be used
+  to configure the behavior.
+ - Updated cachedb to honor `serve-expired-ttl`; Fixes #107.
+ - Renamed statistic `num.zero_ttl` to `num.expired` as expired replies
+  come with a configurable TTL value (`serve-expired-reply-ttl`).
+ - Fixed stats when replying with cached, cname-aliased records.
+ - Added missing default values for redis cachedb backend.
+
+3 February 2020: Ralph
+ - Add assertion to please static analyzer
+
+31 January 2020: Wouter
+ - Fix fclose on error in TLS session ticket code.
+
+30 January 2020: Ralph
+ - Fix memory leak in error condition remote.c
+ - Fix double free in error condition view.c
+ - Fix memory leak in do_auth_zone_transfer on success
+ - Merge RPZ support into master. Only QNAME and Response IP triggers are
+  supported.
+ - Stop working on socket when socket() call returns an error.
+ - Check malloc return values in TLS session ticket code
+
+30 January 2020: Wouter
+ - Fix subnet tests for disabled DSA algorithm by default.
+ - Update contrib/fastrpz.patch for clean diff with current code.
+ - Merge PR#151: Fixes for systemd units, by Maryse47, Edmonds
+  and Frzk.  Updates the unbound.service systemd file and adds
+  a portable systemd service file.
+ - updated .gitignore for added contrib file.
+ - Add build rule for ipset to Makefile
+ - Add getentropy_freebsd.o to Makefile dependencies.
+
+29 January 2020: Ralph
+ - Merge PR#156 from Alexander Berkes; Added unbound-control
+  view_local_datas_remove command.
+
+29 January 2020: Wouter
+ - Fix #157: undefined reference to `htobe64'.
+
+28 January 2020: Ralph
+ - Merge PR#147; change rfc reference for reserved top level dns names.
+
+28 January 2020: Wouter
+ - iana portlist updated.
+ - Fix to silence the tls handshake errors for broken pipe and reset
+  by peer, unless verbosity is set to 2 or higher.
+
+27 January 2020: Ralph
+ - Merge PR#154; Allow use of libbsd functions with configure option
+  --with-libbsd. By Robert Edmonds and Steven Chamberlain.
+ - Merge PR#148; Add some TLS stats to unbound_munin_. By Fredrik Pettai.
+
+27 January 2020: Wouter
+ - Merge PR#155 from Robert Edmonds: contrib/libunbound.pc.in: Fixes
+  to Libs/Requires for crypto library dependencies.
+ - Fix #153: Disable validation for DSA algorithms.  RFC 8624
+  compliance.
+
+23 January 2020: Wouter
+ - Merge PR#150 from Frzk: Systemd unit without chroot.  It add
+  contrib/unbound_nochroot.service.in, a systemd file for use with
+  chroot: "", see comments in the file, it uses systemd protections
+  instead.
+
+14 January 2020: Wouter
+ - Removed the dnscrypt_queries and dnscrypt_queries_chacha tests,
+  because dnscrypt-proxy (2.0.36) does not support the test setup
+  any more, and also the config file format does not seem to have
+  the appropriate keys to recreate that setup.
+ - Fix crash after reload where a stats lookup could reference old key
+  cache and neg cache structures.
+ - Fix for memory leak when edns subnet config options are read when
+  compiled without edns subnet support.
+ - Fix auth zone support for NSEC3 records without salt.
+
+10 January 2020: Wouter
+ - Fix the relationship between serve-expired and prefetch options,
+  patch from Saksham Manchanda from Secure64.
+ - Fix unreachable code in ssl set options code.
+
+8 January 2020: Ralph
+ - Fix #138: stop binding pidfile inside chroot dir in systemd service
+  file.
+
+8 January 2020: Wouter
+ - Fix 'make test' to work for --disable-sha1 configure option.
+ - Fix out-of-bounds null-byte write in sldns_bget_token_par while
+  parsing type WKS, reported by Luis Merino from X41 D-Sec.
+ - Updated sldns_bget_token_par fix for also space for the zero
+  delimiter after the character.  And update for more spare space.
+
+6 January 2020: George
+ - Downgrade compat/getentropy_solaris.c to version 1.4 from OpenBSD.
+  The dl_iterate_phdr() function introduced in newer versions raises
+  compilation errors on solaris 10.
+ - Changes to compat/getentropy_solaris.c for,
+  ifdef stdint.h inclusion for older systems.
+  ifdef sha2.h inclusion for older systems.
+
+6 January 2020: Wouter
+ - Merge #135 from Florian Obser: Use passed in neg and key cache
+  if non-NULL.
+ - Fix #140: Document slave not downloading new zonefile upon update.
+
+16 December 2019: George
+ - Update mailing list URL.
+
+12 December 2019: Ralph
+ - Master is 1.9.7 in development.
+ - Fix typo to let serve-expired-ttl work with ub_ctx_set_option(), by
+  Florian Obser
+
+10 December 2019: Wouter
+ - Fix to make auth zone IXFR to fallback to AXFR if a single
+  response RR is received over TCP with the SOA in it.
+
 6 December 2019: Wouter
  - Fix ipsecmod compile.
  - Fix Makefile.in for ipset module compile, from Adi Prasaja.
+ - release-1.9.6 tag, which became the 1.9.6 release
 
 5 December 2019: Wouter
  - unbound-fuzzers.tar.bz2: three programs for fuzzing, that are 1:1
Index: Makefile.in
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/Makefile.in,v
retrieving revision 1.32
diff -u -p -r1.32 Makefile.in
--- Makefile.in 18 Dec 2019 11:04:13 -0000 1.32
+++ Makefile.in 15 Mar 2020 16:31:04 -0000
@@ -110,6 +110,7 @@ iterator/iter_delegpt.c iterator/iter_do
 iterator/iter_hints.c iterator/iter_priv.c iterator/iter_resptype.c \
 iterator/iter_scrub.c iterator/iter_utils.c services/listen_dnsport.c \
 services/localzone.c services/mesh.c services/modstack.c services/view.c \
+services/rpz.c \
 services/outbound_list.c services/outside_network.c util/alloc.c \
 util/config_file.c util/configlexer.c util/configparser.c \
 util/shm_side/shm_main.c services/authzone.c \
@@ -135,7 +136,7 @@ outbound_list.lo alloc.lo config_file.lo
 fptr_wlist.lo edns.lo locks.lo log.lo mini_event.lo module.lo net_help.lo \
 random.lo rbtree.lo regional.lo rtt.lo dnstree.lo lookup3.lo lruhash.lo \
 slabhash.lo tcp_conn_limit.lo timehist.lo tube.lo winsock_event.lo \
-autotrust.lo val_anchor.lo \
+autotrust.lo val_anchor.lo rpz.lo \
 validator.lo val_kcache.lo val_kentry.lo val_neg.lo val_nsec3.lo val_nsec.lo \
 val_secalgo.lo val_sigcrypt.lo val_utils.lo dns64.lo cachedb.lo redis.lo authzone.lo \
 $(SUBNET_OBJ) $(PYTHONMOD_OBJ) $(CHECKLOCK_OBJ) $(DNSTAP_OBJ) $(DNSCRYPT_OBJ) \
@@ -643,6 +644,9 @@ depend:
  fi
  rm -f $(DEPEND_TMP) $(DEPEND_TMP2)
 
+# build rules
+ipset.lo ipset.o: $(srcdir)/ipset/ipset.c
+
 # Dependencies
 dns.lo dns.o: $(srcdir)/services/cache/dns.c config.h $(srcdir)/iterator/iter_delegpt.h $(srcdir)/util/log.h \
  $(srcdir)/iterator/iter_utils.h $(srcdir)/iterator/iter_resptype.h $(srcdir)/validator/val_nsec.h \
@@ -655,9 +659,9 @@ infra.lo infra.o: $(srcdir)/services/cac
  $(srcdir)/sldns/sbuffer.h $(srcdir)/sldns/wire2str.h $(srcdir)/services/cache/infra.h \
  $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/storage/dnstree.h \
  $(srcdir)/util/rbtree.h $(srcdir)/util/rtt.h $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
-  $(srcdir)/dnscrypt/cert.h $(srcdir)/util/data/msgreply.h \
- $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/slabhash.h $(srcdir)/util/storage/lookup3.h \
- $(srcdir)/util/data/dname.h $(srcdir)/util/net_help.h $(srcdir)/util/config_file.h $(srcdir)/iterator/iterator.h \
+  $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h \
+ $(srcdir)/util/storage/slabhash.h $(srcdir)/util/storage/lookup3.h $(srcdir)/util/data/dname.h \
+ $(srcdir)/util/net_help.h $(srcdir)/util/config_file.h $(srcdir)/iterator/iterator.h \
  $(srcdir)/services/outbound_list.h $(srcdir)/util/module.h $(srcdir)/util/data/msgparse.h \
  $(srcdir)/sldns/pkthdr.h
 rrset.lo rrset.o: $(srcdir)/services/cache/rrset.c config.h $(srcdir)/services/cache/rrset.h \
@@ -682,11 +686,14 @@ msgparse.lo msgparse.o: $(srcdir)/util/d
 msgreply.lo msgreply.o: $(srcdir)/util/data/msgreply.c config.h $(srcdir)/util/data/msgreply.h \
  $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/data/packed_rrset.h \
  $(srcdir)/util/storage/lookup3.h $(srcdir)/util/alloc.h $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
-  $(srcdir)/dnscrypt/cert.h $(srcdir)/util/net_help.h \
- $(srcdir)/util/data/dname.h $(srcdir)/util/regional.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h \
- $(srcdir)/sldns/rrdef.h $(srcdir)/util/data/msgencode.h $(srcdir)/sldns/sbuffer.h $(srcdir)/sldns/wire2str.h \
- $(srcdir)/util/module.h $(srcdir)/util/fptr_wlist.h $(srcdir)/util/tube.h $(srcdir)/services/mesh.h \
- $(srcdir)/util/rbtree.h $(srcdir)/services/modstack.h
+  $(srcdir)/util/net_help.h $(srcdir)/util/data/dname.h \
+ $(srcdir)/util/regional.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h \
+ $(srcdir)/util/data/msgencode.h $(srcdir)/sldns/sbuffer.h $(srcdir)/sldns/wire2str.h $(srcdir)/util/module.h \
+ $(srcdir)/util/fptr_wlist.h $(srcdir)/util/tube.h $(srcdir)/services/mesh.h $(srcdir)/util/rbtree.h \
+ $(srcdir)/services/modstack.h $(srcdir)/services/rpz.h $(srcdir)/services/localzone.h \
+ $(srcdir)/util/storage/dnstree.h $(srcdir)/services/view.h $(srcdir)/util/config_file.h \
+ $(srcdir)/services/authzone.h $(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h $(srcdir)/libunbound/unbound.h \
+ $(srcdir)/respip/respip.h
 packed_rrset.lo packed_rrset.o: $(srcdir)/util/data/packed_rrset.c config.h \
  $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \
  $(srcdir)/util/data/dname.h $(srcdir)/util/storage/lookup3.h $(srcdir)/util/alloc.h $(srcdir)/util/regional.h \
@@ -700,11 +707,12 @@ iterator.lo iterator.o: $(srcdir)/iterat
  $(srcdir)/iterator/iter_delegpt.h $(srcdir)/iterator/iter_scrub.h $(srcdir)/iterator/iter_priv.h \
  $(srcdir)/validator/val_neg.h $(srcdir)/services/cache/dns.h $(srcdir)/services/cache/infra.h \
  $(srcdir)/util/rtt.h $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
-  $(srcdir)/dnscrypt/cert.h $(srcdir)/services/authzone.h \
- $(srcdir)/services/mesh.h $(srcdir)/services/modstack.h $(srcdir)/util/net_help.h $(srcdir)/util/regional.h \
+  $(srcdir)/services/authzone.h $(srcdir)/services/mesh.h \
+ $(srcdir)/services/modstack.h $(srcdir)/services/rpz.h $(srcdir)/services/localzone.h $(srcdir)/services/view.h \
+ $(srcdir)/sldns/sbuffer.h $(srcdir)/util/config_file.h $(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h \
+ $(srcdir)/libunbound/unbound.h $(srcdir)/respip/respip.h $(srcdir)/util/net_help.h $(srcdir)/util/regional.h \
  $(srcdir)/util/data/dname.h $(srcdir)/util/data/msgencode.h $(srcdir)/util/fptr_wlist.h $(srcdir)/util/tube.h \
- $(srcdir)/util/config_file.h $(srcdir)/util/random.h $(srcdir)/sldns/wire2str.h $(srcdir)/sldns/str2wire.h \
- $(srcdir)/sldns/parseutil.h $(srcdir)/sldns/sbuffer.h
+ $(srcdir)/util/random.h $(srcdir)/sldns/wire2str.h $(srcdir)/sldns/str2wire.h $(srcdir)/sldns/parseutil.h
 iter_delegpt.lo iter_delegpt.o: $(srcdir)/iterator/iter_delegpt.c config.h $(srcdir)/iterator/iter_delegpt.h \
  $(srcdir)/util/log.h $(srcdir)/services/cache/dns.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h \
  $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/regional.h \
@@ -746,88 +754,106 @@ iter_utils.lo iter_utils.o: $(srcdir)/it
  $(srcdir)/util/storage/dnstree.h $(srcdir)/util/rbtree.h $(srcdir)/iterator/iter_fwd.h \
  $(srcdir)/iterator/iter_donotq.h $(srcdir)/iterator/iter_delegpt.h $(srcdir)/iterator/iter_priv.h \
  $(srcdir)/services/cache/infra.h $(srcdir)/util/rtt.h $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
-  $(srcdir)/dnscrypt/cert.h $(srcdir)/services/cache/dns.h \
- $(srcdir)/services/cache/rrset.h $(srcdir)/util/storage/slabhash.h $(srcdir)/util/net_help.h \
- $(srcdir)/util/config_file.h $(srcdir)/util/regional.h $(srcdir)/util/data/dname.h $(srcdir)/util/random.h \
- $(srcdir)/util/fptr_wlist.h $(srcdir)/util/tube.h $(srcdir)/services/mesh.h $(srcdir)/services/modstack.h \
+  $(srcdir)/services/cache/dns.h $(srcdir)/services/cache/rrset.h \
+ $(srcdir)/util/storage/slabhash.h $(srcdir)/util/net_help.h $(srcdir)/util/config_file.h \
+ $(srcdir)/util/regional.h $(srcdir)/util/data/dname.h $(srcdir)/util/random.h $(srcdir)/util/fptr_wlist.h \
+ $(srcdir)/util/tube.h $(srcdir)/services/mesh.h $(srcdir)/services/modstack.h $(srcdir)/services/rpz.h \
+ $(srcdir)/services/localzone.h $(srcdir)/services/view.h $(srcdir)/sldns/sbuffer.h $(srcdir)/services/authzone.h \
+ $(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h $(srcdir)/libunbound/unbound.h $(srcdir)/respip/respip.h \
  $(srcdir)/validator/val_anchor.h $(srcdir)/validator/val_kcache.h $(srcdir)/validator/val_kentry.h \
- $(srcdir)/validator/val_utils.h $(srcdir)/validator/val_sigcrypt.h $(srcdir)/sldns/sbuffer.h \
- $(srcdir)/sldns/str2wire.h
+ $(srcdir)/validator/val_utils.h $(srcdir)/validator/val_sigcrypt.h $(srcdir)/sldns/str2wire.h
 listen_dnsport.lo listen_dnsport.o: $(srcdir)/services/listen_dnsport.c config.h \
  $(srcdir)/services/listen_dnsport.h $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
-  $(srcdir)/dnscrypt/cert.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \
- $(srcdir)/services/outside_network.h $(srcdir)/util/rbtree.h  \
- $(srcdir)/util/config_file.h $(srcdir)/util/net_help.h $(srcdir)/sldns/sbuffer.h $(srcdir)/services/mesh.h \
- $(srcdir)/util/data/msgparse.h $(srcdir)/util/storage/lruhash.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h \
+  $(srcdir)/services/outside_network.h $(srcdir)/util/rbtree.h \
+  $(srcdir)/util/log.h $(srcdir)/util/config_file.h $(srcdir)/util/net_help.h \
+ $(srcdir)/sldns/sbuffer.h $(srcdir)/services/mesh.h $(srcdir)/util/data/msgparse.h \
+ $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h \
  $(srcdir)/util/module.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h \
- $(srcdir)/services/modstack.h $(srcdir)/util/fptr_wlist.h $(srcdir)/util/tube.h
+ $(srcdir)/services/modstack.h $(srcdir)/services/rpz.h $(srcdir)/services/localzone.h \
+ $(srcdir)/util/storage/dnstree.h $(srcdir)/services/view.h $(srcdir)/services/authzone.h \
+ $(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h $(srcdir)/libunbound/unbound.h $(srcdir)/respip/respip.h \
+ $(srcdir)/util/fptr_wlist.h $(srcdir)/util/tube.h
 localzone.lo localzone.o: $(srcdir)/services/localzone.c config.h $(srcdir)/services/localzone.h \
  $(srcdir)/util/rbtree.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/storage/dnstree.h \
  $(srcdir)/util/module.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/data/msgreply.h \
  $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h \
- $(srcdir)/sldns/rrdef.h $(srcdir)/services/view.h $(srcdir)/sldns/str2wire.h $(srcdir)/sldns/sbuffer.h \
+ $(srcdir)/sldns/rrdef.h $(srcdir)/services/view.h $(srcdir)/sldns/sbuffer.h $(srcdir)/sldns/str2wire.h \
  $(srcdir)/util/regional.h $(srcdir)/util/config_file.h $(srcdir)/util/data/dname.h \
  $(srcdir)/util/data/msgencode.h $(srcdir)/util/net_help.h $(srcdir)/util/netevent.h \
- $(srcdir)/dnscrypt/dnscrypt.h  $(srcdir)/dnscrypt/cert.h \
- $(srcdir)/util/as112.h
+ $(srcdir)/dnscrypt/dnscrypt.h  $(srcdir)/util/as112.h
 mesh.lo mesh.o: $(srcdir)/services/mesh.c config.h $(srcdir)/services/mesh.h $(srcdir)/util/rbtree.h \
  $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h  \
- $(srcdir)/dnscrypt/cert.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/data/msgparse.h \
- $(srcdir)/util/storage/lruhash.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/module.h \
- $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/services/modstack.h \
+ $(srcdir)/util/data/msgparse.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \
+ $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/module.h $(srcdir)/util/data/msgreply.h \
+ $(srcdir)/util/data/packed_rrset.h $(srcdir)/services/modstack.h $(srcdir)/services/rpz.h \
+ $(srcdir)/services/localzone.h $(srcdir)/util/storage/dnstree.h $(srcdir)/services/view.h \
+ $(srcdir)/sldns/sbuffer.h $(srcdir)/util/config_file.h $(srcdir)/services/authzone.h $(srcdir)/daemon/stats.h \
+ $(srcdir)/util/timehist.h $(srcdir)/libunbound/unbound.h $(srcdir)/respip/respip.h \
  $(srcdir)/services/outbound_list.h $(srcdir)/services/cache/dns.h $(srcdir)/util/net_help.h \
- $(srcdir)/util/regional.h $(srcdir)/util/data/msgencode.h $(srcdir)/util/timehist.h $(srcdir)/util/fptr_wlist.h \
- $(srcdir)/util/tube.h $(srcdir)/util/alloc.h $(srcdir)/util/config_file.h $(srcdir)/util/edns.h $(srcdir)/sldns/sbuffer.h \
- $(srcdir)/sldns/wire2str.h $(srcdir)/services/localzone.h $(srcdir)/util/storage/dnstree.h \
- $(srcdir)/services/view.h $(srcdir)/util/data/dname.h $(srcdir)/respip/respip.h \
+ $(srcdir)/util/regional.h $(srcdir)/util/data/msgencode.h $(srcdir)/util/fptr_wlist.h $(srcdir)/util/tube.h \
+ $(srcdir)/util/alloc.h $(srcdir)/util/edns.h $(srcdir)/sldns/wire2str.h $(srcdir)/util/data/dname.h \
  $(srcdir)/services/listen_dnsport.h
 modstack.lo modstack.o: $(srcdir)/services/modstack.c config.h $(srcdir)/services/modstack.h \
  $(srcdir)/util/module.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \
  $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgparse.h \
  $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/fptr_wlist.h $(srcdir)/util/netevent.h \
- $(srcdir)/dnscrypt/dnscrypt.h  $(srcdir)/dnscrypt/cert.h \
- $(srcdir)/util/tube.h $(srcdir)/services/mesh.h $(srcdir)/util/rbtree.h $(srcdir)/dns64/dns64.h \
- $(srcdir)/iterator/iterator.h $(srcdir)/services/outbound_list.h $(srcdir)/validator/validator.h \
- $(srcdir)/validator/val_utils.h $(srcdir)/respip/respip.h $(srcdir)/services/localzone.h \
- $(srcdir)/util/storage/dnstree.h $(srcdir)/services/view.h $(PYTHONMOD_HEADER) $(srcdir)/ipsecmod/ipsecmod.h \
- $(srcdir)/util/storage/slabhash.h $(srcdir)/edns-subnet/addrtree.h $(srcdir)/edns-subnet/edns-subnet.h \
- $(srcdir)/ipset/ipset.h
+ $(srcdir)/dnscrypt/dnscrypt.h  $(srcdir)/util/tube.h \
+ $(srcdir)/services/mesh.h $(srcdir)/util/rbtree.h $(srcdir)/services/rpz.h $(srcdir)/services/localzone.h \
+ $(srcdir)/util/storage/dnstree.h $(srcdir)/services/view.h $(srcdir)/sldns/sbuffer.h \
+ $(srcdir)/util/config_file.h $(srcdir)/services/authzone.h $(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h \
+ $(srcdir)/libunbound/unbound.h $(srcdir)/respip/respip.h $(srcdir)/dns64/dns64.h $(srcdir)/iterator/iterator.h \
+ $(srcdir)/services/outbound_list.h $(srcdir)/validator/validator.h $(srcdir)/validator/val_utils.h
 view.lo view.o: $(srcdir)/services/view.c config.h $(srcdir)/services/view.h $(srcdir)/util/rbtree.h \
  $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/services/localzone.h $(srcdir)/util/storage/dnstree.h \
  $(srcdir)/util/module.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/data/msgreply.h \
  $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h \
- $(srcdir)/sldns/rrdef.h $(srcdir)/util/config_file.h
+ $(srcdir)/sldns/rrdef.h $(srcdir)/sldns/sbuffer.h $(srcdir)/util/config_file.h
+rpz.lo rpz.o: $(srcdir)/services/rpz.c config.h $(srcdir)/services/rpz.h $(srcdir)/services/localzone.h \
+ $(srcdir)/util/rbtree.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/storage/dnstree.h \
+ $(srcdir)/util/module.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/data/msgreply.h \
+ $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h \
+ $(srcdir)/sldns/rrdef.h $(srcdir)/services/view.h $(srcdir)/sldns/sbuffer.h $(srcdir)/util/config_file.h \
+ $(srcdir)/services/authzone.h $(srcdir)/services/mesh.h $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
+  $(srcdir)/services/modstack.h $(srcdir)/libunbound/unbound.h \
+ $(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h $(srcdir)/respip/respip.h $(srcdir)/sldns/wire2str.h \
+ $(srcdir)/sldns/str2wire.h $(srcdir)/util/data/dname.h $(srcdir)/util/net_help.h $(srcdir)/util/regional.h
 outbound_list.lo outbound_list.o: $(srcdir)/services/outbound_list.c config.h \
  $(srcdir)/services/outbound_list.h $(srcdir)/services/outside_network.h $(srcdir)/util/rbtree.h \
  $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h  \
- $(srcdir)/dnscrypt/cert.h $(srcdir)/util/locks.h $(srcdir)/util/log.h
+
 outside_network.lo outside_network.o: $(srcdir)/services/outside_network.c config.h \
  $(srcdir)/services/outside_network.h $(srcdir)/util/rbtree.h $(srcdir)/util/netevent.h \
- $(srcdir)/dnscrypt/dnscrypt.h  $(srcdir)/dnscrypt/cert.h \
- $(srcdir)/util/locks.h $(srcdir)/util/log.h  $(srcdir)/services/listen_dnsport.h \
- $(srcdir)/services/cache/infra.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/storage/dnstree.h \
- $(srcdir)/util/rtt.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h \
- $(srcdir)/iterator/iterator.h $(srcdir)/services/outbound_list.h $(srcdir)/util/module.h \
- $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/data/msgencode.h \
- $(srcdir)/util/data/dname.h $(srcdir)/util/net_help.h $(srcdir)/util/random.h $(srcdir)/util/fptr_wlist.h \
- $(srcdir)/util/tube.h $(srcdir)/services/mesh.h $(srcdir)/services/modstack.h $(srcdir)/sldns/sbuffer.h \
- $(srcdir)/dnstap/dnstap.h \
-
+ $(srcdir)/dnscrypt/dnscrypt.h   \
+ $(srcdir)/services/listen_dnsport.h $(srcdir)/services/cache/infra.h $(srcdir)/util/storage/lruhash.h \
+ $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/storage/dnstree.h $(srcdir)/util/rtt.h \
+ $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/iterator/iterator.h \
+ $(srcdir)/services/outbound_list.h $(srcdir)/util/module.h $(srcdir)/util/data/msgparse.h \
+ $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/data/msgencode.h $(srcdir)/util/data/dname.h \
+ $(srcdir)/util/net_help.h $(srcdir)/util/random.h $(srcdir)/util/fptr_wlist.h $(srcdir)/util/tube.h \
+ $(srcdir)/services/mesh.h $(srcdir)/services/modstack.h $(srcdir)/services/rpz.h $(srcdir)/services/localzone.h \
+ $(srcdir)/services/view.h $(srcdir)/sldns/sbuffer.h $(srcdir)/util/config_file.h $(srcdir)/services/authzone.h \
+ $(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h $(srcdir)/libunbound/unbound.h $(srcdir)/respip/respip.h \
+ $(srcdir)/dnstap/dnstap.h
 alloc.lo alloc.o: $(srcdir)/util/alloc.c config.h $(srcdir)/util/alloc.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \
  $(srcdir)/util/regional.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h \
  $(srcdir)/util/fptr_wlist.h $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
-  $(srcdir)/dnscrypt/cert.h $(srcdir)/util/module.h \
- $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h \
- $(srcdir)/util/tube.h $(srcdir)/services/mesh.h $(srcdir)/util/rbtree.h $(srcdir)/services/modstack.h
+  $(srcdir)/util/module.h $(srcdir)/util/data/msgreply.h \
+ $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/tube.h \
+ $(srcdir)/services/mesh.h $(srcdir)/util/rbtree.h $(srcdir)/services/modstack.h $(srcdir)/services/rpz.h \
+ $(srcdir)/services/localzone.h $(srcdir)/util/storage/dnstree.h $(srcdir)/services/view.h \
+ $(srcdir)/sldns/sbuffer.h $(srcdir)/util/config_file.h $(srcdir)/services/authzone.h $(srcdir)/daemon/stats.h \
+ $(srcdir)/util/timehist.h $(srcdir)/libunbound/unbound.h $(srcdir)/respip/respip.h
 config_file.lo config_file.o: $(srcdir)/util/config_file.c config.h $(srcdir)/util/log.h \
  $(srcdir)/util/configyyrename.h $(srcdir)/util/config_file.h util/configparser.h \
  $(srcdir)/util/net_help.h $(srcdir)/util/data/msgparse.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h \
  $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/module.h $(srcdir)/util/data/msgreply.h \
  $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/regional.h $(srcdir)/util/fptr_wlist.h \
  $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h  \
- $(srcdir)/dnscrypt/cert.h $(srcdir)/util/tube.h $(srcdir)/services/mesh.h $(srcdir)/util/rbtree.h \
- $(srcdir)/services/modstack.h $(srcdir)/util/data/dname.h $(srcdir)/util/rtt.h $(srcdir)/services/cache/infra.h \
- $(srcdir)/util/storage/dnstree.h $(srcdir)/sldns/wire2str.h $(srcdir)/sldns/parseutil.h \
+ $(srcdir)/util/tube.h $(srcdir)/services/mesh.h $(srcdir)/util/rbtree.h $(srcdir)/services/modstack.h \
+ $(srcdir)/services/rpz.h $(srcdir)/services/localzone.h $(srcdir)/util/storage/dnstree.h \
+ $(srcdir)/services/view.h $(srcdir)/sldns/sbuffer.h $(srcdir)/services/authzone.h $(srcdir)/daemon/stats.h \
+ $(srcdir)/util/timehist.h $(srcdir)/libunbound/unbound.h $(srcdir)/respip/respip.h $(srcdir)/util/data/dname.h \
+ $(srcdir)/util/rtt.h $(srcdir)/services/cache/infra.h $(srcdir)/sldns/wire2str.h $(srcdir)/sldns/parseutil.h \
  $(srcdir)/iterator/iterator.h $(srcdir)/services/outbound_list.h $(srcdir)/util/iana_ports.inc
 configlexer.lo configlexer.o: util/configlexer.c config.h $(srcdir)/util/configyyrename.h \
  $(srcdir)/util/config_file.h util/configparser.h
@@ -838,71 +864,83 @@ shm_main.lo shm_main.o: $(srcdir)/util/s
  $(srcdir)/util/alloc.h $(srcdir)/services/modstack.h  \
   $(srcdir)/daemon/worker.h $(srcdir)/libunbound/worker.h \
  $(srcdir)/sldns/sbuffer.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h \
- $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h $(srcdir)/dnscrypt/cert.h $(srcdir)/util/data/msgreply.h \
+ $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h $(srcdir)/util/data/msgreply.h \
  $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/daemon/stats.h \
  $(srcdir)/util/timehist.h $(srcdir)/util/module.h $(srcdir)/dnstap/dnstap.h $(srcdir)/services/mesh.h \
- $(srcdir)/util/rbtree.h $(srcdir)/services/cache/rrset.h $(srcdir)/util/storage/slabhash.h \
- $(srcdir)/services/cache/infra.h $(srcdir)/util/storage/dnstree.h $(srcdir)/util/rtt.h \
- $(srcdir)/validator/validator.h $(srcdir)/validator/val_utils.h $(srcdir)/util/config_file.h \
- $(srcdir)/util/fptr_wlist.h $(srcdir)/util/tube.h
+ $(srcdir)/util/rbtree.h $(srcdir)/services/rpz.h $(srcdir)/services/localzone.h $(srcdir)/util/storage/dnstree.h \
+ $(srcdir)/services/view.h $(srcdir)/util/config_file.h $(srcdir)/services/authzone.h $(srcdir)/respip/respip.h \
+ $(srcdir)/services/cache/rrset.h $(srcdir)/util/storage/slabhash.h $(srcdir)/services/cache/infra.h \
+ $(srcdir)/util/rtt.h $(srcdir)/validator/validator.h $(srcdir)/validator/val_utils.h $(srcdir)/util/fptr_wlist.h \
+ $(srcdir)/util/tube.h
 authzone.lo authzone.o: $(srcdir)/services/authzone.c config.h $(srcdir)/services/authzone.h \
  $(srcdir)/util/rbtree.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/services/mesh.h $(srcdir)/util/netevent.h \
- $(srcdir)/dnscrypt/dnscrypt.h  $(srcdir)/dnscrypt/cert.h \
- $(srcdir)/util/data/msgparse.h $(srcdir)/util/storage/lruhash.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h \
- $(srcdir)/util/module.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h \
- $(srcdir)/services/modstack.h $(srcdir)/util/data/dname.h $(srcdir)/util/data/msgencode.h \
- $(srcdir)/util/regional.h $(srcdir)/util/net_help.h $(srcdir)/util/config_file.h $(srcdir)/util/random.h \
+ $(srcdir)/dnscrypt/dnscrypt.h  $(srcdir)/util/data/msgparse.h \
+ $(srcdir)/util/storage/lruhash.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/module.h \
+ $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/services/modstack.h \
+ $(srcdir)/services/rpz.h $(srcdir)/services/localzone.h $(srcdir)/util/storage/dnstree.h \
+ $(srcdir)/services/view.h $(srcdir)/sldns/sbuffer.h $(srcdir)/util/config_file.h $(srcdir)/daemon/stats.h \
+ $(srcdir)/util/timehist.h $(srcdir)/libunbound/unbound.h $(srcdir)/respip/respip.h $(srcdir)/util/data/dname.h \
+ $(srcdir)/util/data/msgencode.h $(srcdir)/util/regional.h $(srcdir)/util/net_help.h $(srcdir)/util/random.h \
  $(srcdir)/services/cache/dns.h $(srcdir)/services/outside_network.h  \
- $(srcdir)/services/listen_dnsport.h $(srcdir)/sldns/sbuffer.h $(srcdir)/sldns/str2wire.h \
- $(srcdir)/sldns/wire2str.h $(srcdir)/sldns/parseutil.h $(srcdir)/sldns/keyraw.h \
- $(srcdir)/validator/val_nsec3.h $(srcdir)/validator/val_secalgo.h
+ $(srcdir)/services/listen_dnsport.h $(srcdir)/sldns/str2wire.h $(srcdir)/sldns/wire2str.h \
+ $(srcdir)/sldns/parseutil.h $(srcdir)/sldns/keyraw.h $(srcdir)/validator/val_nsec3.h \
+ $(srcdir)/validator/val_secalgo.h
 fptr_wlist.lo fptr_wlist.o: $(srcdir)/util/fptr_wlist.c config.h $(srcdir)/util/fptr_wlist.h \
  $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h  \
- $(srcdir)/dnscrypt/cert.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/storage/lruhash.h \
- $(srcdir)/util/module.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h \
- $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/tube.h \
- $(srcdir)/services/mesh.h $(srcdir)/util/rbtree.h $(srcdir)/services/modstack.h $(srcdir)/util/mini_event.h \
- $(srcdir)/services/outside_network.h  $(srcdir)/services/localzone.h \
- $(srcdir)/util/storage/dnstree.h $(srcdir)/services/view.h $(srcdir)/services/authzone.h \
- $(srcdir)/services/cache/infra.h $(srcdir)/util/rtt.h $(srcdir)/services/cache/rrset.h \
- $(srcdir)/util/storage/slabhash.h $(srcdir)/dns64/dns64.h $(srcdir)/iterator/iterator.h \
- $(srcdir)/services/outbound_list.h $(srcdir)/iterator/iter_fwd.h $(srcdir)/validator/validator.h \
- $(srcdir)/validator/val_utils.h $(srcdir)/validator/val_anchor.h $(srcdir)/validator/val_nsec3.h \
- $(srcdir)/validator/val_sigcrypt.h $(srcdir)/validator/val_kentry.h $(srcdir)/validator/val_neg.h \
- $(srcdir)/validator/autotrust.h $(srcdir)/libunbound/libworker.h $(srcdir)/libunbound/context.h \
- $(srcdir)/util/alloc.h $(srcdir)/libunbound/unbound.h $(srcdir)/libunbound/unbound-event.h \
- $(srcdir)/libunbound/worker.h $(srcdir)/sldns/sbuffer.h $(srcdir)/util/config_file.h $(srcdir)/respip/respip.h \
- $(PYTHONMOD_HEADER) $(srcdir)/ipsecmod/ipsecmod.h $(srcdir)/edns-subnet/subnetmod.h $(srcdir)/util/net_help.h \
- $(srcdir)/edns-subnet/addrtree.h $(srcdir)/edns-subnet/edns-subnet.h $(srcdir)/ipset/ipset.h
+ $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/module.h \
+ $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgparse.h \
+ $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/tube.h $(srcdir)/services/mesh.h $(srcdir)/util/rbtree.h \
+ $(srcdir)/services/modstack.h $(srcdir)/services/rpz.h $(srcdir)/services/localzone.h \
+ $(srcdir)/util/storage/dnstree.h $(srcdir)/services/view.h $(srcdir)/sldns/sbuffer.h \
+ $(srcdir)/util/config_file.h $(srcdir)/services/authzone.h $(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h \
+ $(srcdir)/libunbound/unbound.h $(srcdir)/respip/respip.h $(srcdir)/util/mini_event.h $(srcdir)/util/rbtree.h \
+ $(srcdir)/services/outside_network.h  $(srcdir)/services/cache/infra.h \
+ $(srcdir)/util/rtt.h $(srcdir)/services/cache/rrset.h $(srcdir)/util/storage/slabhash.h $(srcdir)/dns64/dns64.h \
+ $(srcdir)/iterator/iterator.h $(srcdir)/services/outbound_list.h $(srcdir)/iterator/iter_fwd.h \
+ $(srcdir)/validator/validator.h $(srcdir)/validator/val_utils.h $(srcdir)/validator/val_anchor.h \
+ $(srcdir)/validator/val_nsec3.h $(srcdir)/validator/val_sigcrypt.h $(srcdir)/validator/val_kentry.h \
+ $(srcdir)/validator/val_neg.h $(srcdir)/validator/autotrust.h $(srcdir)/libunbound/libworker.h \
+ $(srcdir)/libunbound/context.h $(srcdir)/util/alloc.h $(srcdir)/libunbound/unbound-event.h \
+ $(srcdir)/libunbound/worker.h
 locks.lo locks.o: $(srcdir)/util/locks.c config.h $(srcdir)/util/locks.h $(srcdir)/util/log.h
 log.lo log.o: $(srcdir)/util/log.c config.h $(srcdir)/util/log.h $(srcdir)/util/locks.h $(srcdir)/sldns/sbuffer.h
-mini_event.lo mini_event.o: $(srcdir)/util/mini_event.c config.h $(srcdir)/util/mini_event.h
+mini_event.lo mini_event.o: $(srcdir)/util/mini_event.c config.h $(srcdir)/util/mini_event.h $(srcdir)/util/rbtree.h \
+ $(srcdir)/util/fptr_wlist.h $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
+  $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h \
+ $(srcdir)/util/log.h $(srcdir)/util/module.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h \
+ $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/tube.h \
+ $(srcdir)/services/mesh.h $(srcdir)/util/rbtree.h $(srcdir)/services/modstack.h $(srcdir)/services/rpz.h \
+ $(srcdir)/services/localzone.h $(srcdir)/util/storage/dnstree.h $(srcdir)/services/view.h \
+ $(srcdir)/sldns/sbuffer.h $(srcdir)/util/config_file.h $(srcdir)/services/authzone.h $(srcdir)/daemon/stats.h \
+ $(srcdir)/util/timehist.h $(srcdir)/libunbound/unbound.h $(srcdir)/respip/respip.h
 module.lo module.o: $(srcdir)/util/module.c config.h $(srcdir)/util/module.h $(srcdir)/util/storage/lruhash.h \
  $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h \
  $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/sldns/wire2str.h
 netevent.lo netevent.o: $(srcdir)/util/netevent.c config.h $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
-  $(srcdir)/dnscrypt/cert.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \
- $(srcdir)/util/ub_event.h $(srcdir)/util/net_help.h $(srcdir)/util/tcp_conn_limit.h \
- $(srcdir)/util/storage/dnstree.h $(srcdir)/util/rbtree.h $(srcdir)/util/fptr_wlist.h \
- $(srcdir)/util/storage/lruhash.h $(srcdir)/util/module.h $(srcdir)/util/data/msgreply.h \
- $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h \
- $(srcdir)/sldns/rrdef.h $(srcdir)/util/tube.h $(srcdir)/services/mesh.h $(srcdir)/services/modstack.h \
- $(srcdir)/sldns/sbuffer.h $(srcdir)/sldns/str2wire.h $(srcdir)/dnstap/dnstap.h  \
- $(srcdir)/services/listen_dnsport.h \
-
+  $(srcdir)/util/ub_event.h $(srcdir)/util/log.h $(srcdir)/util/net_help.h \
+ $(srcdir)/util/tcp_conn_limit.h $(srcdir)/util/storage/dnstree.h $(srcdir)/util/rbtree.h $(srcdir)/util/locks.h \
+ $(srcdir)/util/fptr_wlist.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/module.h \
+ $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgparse.h \
+ $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/tube.h $(srcdir)/services/mesh.h \
+ $(srcdir)/services/modstack.h $(srcdir)/services/rpz.h $(srcdir)/services/localzone.h $(srcdir)/services/view.h \
+ $(srcdir)/sldns/sbuffer.h $(srcdir)/util/config_file.h $(srcdir)/services/authzone.h $(srcdir)/daemon/stats.h \
+ $(srcdir)/util/timehist.h $(srcdir)/libunbound/unbound.h $(srcdir)/respip/respip.h $(srcdir)/sldns/str2wire.h \
+ $(srcdir)/dnstap/dnstap.h  $(srcdir)/services/listen_dnsport.h
 net_help.lo net_help.o: $(srcdir)/util/net_help.c config.h $(srcdir)/util/net_help.h $(srcdir)/util/log.h \
  $(srcdir)/util/data/dname.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/module.h \
  $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgparse.h \
  $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/regional.h $(srcdir)/util/config_file.h \
- $(srcdir)/sldns/parseutil.h $(srcdir)/sldns/wire2str.h \
-
+ $(srcdir)/sldns/parseutil.h $(srcdir)/sldns/wire2str.h
 random.lo random.o: $(srcdir)/util/random.c config.h $(srcdir)/util/random.h $(srcdir)/util/log.h
 rbtree.lo rbtree.o: $(srcdir)/util/rbtree.c config.h $(srcdir)/util/log.h $(srcdir)/util/fptr_wlist.h \
  $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h  \
- $(srcdir)/dnscrypt/cert.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/storage/lruhash.h \
- $(srcdir)/util/module.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h \
- $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/tube.h \
- $(srcdir)/services/mesh.h $(srcdir)/util/rbtree.h $(srcdir)/services/modstack.h
+ $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/module.h \
+ $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgparse.h \
+ $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/tube.h $(srcdir)/services/mesh.h $(srcdir)/util/rbtree.h \
+ $(srcdir)/services/modstack.h $(srcdir)/services/rpz.h $(srcdir)/services/localzone.h \
+ $(srcdir)/util/storage/dnstree.h $(srcdir)/services/view.h $(srcdir)/sldns/sbuffer.h \
+ $(srcdir)/util/config_file.h $(srcdir)/services/authzone.h $(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h \
+ $(srcdir)/libunbound/unbound.h $(srcdir)/respip/respip.h
 regional.lo regional.o: $(srcdir)/util/regional.c config.h $(srcdir)/util/log.h $(srcdir)/util/regional.h
 rtt.lo rtt.o: $(srcdir)/util/rtt.c config.h $(srcdir)/util/rtt.h $(srcdir)/iterator/iterator.h \
  $(srcdir)/services/outbound_list.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/storage/lruhash.h \
@@ -910,19 +948,22 @@ rtt.lo rtt.o: $(srcdir)/util/rtt.c confi
  $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h
 edns.lo edns.o: $(srcdir)/util/edns.c config.h $(srcdir)/util/edns.h $(srcdir)/util/config_file.h \
  $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h  \
- $(srcdir)/dnscrypt/cert.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/regional.h \
- $(srcdir)/util/data/msgparse.h $(srcdir)/util/storage/lruhash.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h \
- $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h
+ $(srcdir)/util/regional.h $(srcdir)/util/data/msgparse.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h \
+ $(srcdir)/util/log.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/data/msgreply.h \
+ $(srcdir)/util/data/packed_rrset.h
 dnstree.lo dnstree.o: $(srcdir)/util/storage/dnstree.c config.h $(srcdir)/util/storage/dnstree.h \
  $(srcdir)/util/rbtree.h $(srcdir)/util/data/dname.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h \
  $(srcdir)/util/log.h $(srcdir)/util/net_help.h
 lookup3.lo lookup3.o: $(srcdir)/util/storage/lookup3.c config.h $(srcdir)/util/storage/lookup3.h
 lruhash.lo lruhash.o: $(srcdir)/util/storage/lruhash.c config.h $(srcdir)/util/storage/lruhash.h \
  $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/fptr_wlist.h $(srcdir)/util/netevent.h \
- $(srcdir)/dnscrypt/dnscrypt.h  $(srcdir)/dnscrypt/cert.h \
- $(srcdir)/util/module.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h \
- $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/tube.h \
- $(srcdir)/services/mesh.h $(srcdir)/util/rbtree.h $(srcdir)/services/modstack.h
+ $(srcdir)/dnscrypt/dnscrypt.h  $(srcdir)/util/module.h \
+ $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgparse.h \
+ $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/tube.h $(srcdir)/services/mesh.h $(srcdir)/util/rbtree.h \
+ $(srcdir)/services/modstack.h $(srcdir)/services/rpz.h $(srcdir)/services/localzone.h \
+ $(srcdir)/util/storage/dnstree.h $(srcdir)/services/view.h $(srcdir)/sldns/sbuffer.h \
+ $(srcdir)/util/config_file.h $(srcdir)/services/authzone.h $(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h \
+ $(srcdir)/libunbound/unbound.h $(srcdir)/respip/respip.h
 slabhash.lo slabhash.o: $(srcdir)/util/storage/slabhash.c config.h $(srcdir)/util/storage/slabhash.h \
  $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h
 tcp_conn_limit.lo tcp_conn_limit.o: $(srcdir)/util/tcp_conn_limit.c config.h $(srcdir)/util/regional.h \
@@ -930,26 +971,30 @@ tcp_conn_limit.lo tcp_conn_limit.o: $(sr
  $(srcdir)/util/storage/dnstree.h $(srcdir)/util/rbtree.h $(srcdir)/util/locks.h $(srcdir)/services/localzone.h \
  $(srcdir)/util/module.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/data/msgreply.h \
  $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h \
- $(srcdir)/sldns/rrdef.h $(srcdir)/services/view.h $(srcdir)/sldns/str2wire.h
+ $(srcdir)/sldns/rrdef.h $(srcdir)/services/view.h $(srcdir)/sldns/sbuffer.h $(srcdir)/sldns/str2wire.h
 timehist.lo timehist.o: $(srcdir)/util/timehist.c config.h $(srcdir)/util/timehist.h $(srcdir)/util/log.h
 tube.lo tube.o: $(srcdir)/util/tube.c config.h $(srcdir)/util/tube.h $(srcdir)/util/log.h $(srcdir)/util/net_help.h \
  $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h  \
- $(srcdir)/dnscrypt/cert.h $(srcdir)/util/locks.h $(srcdir)/util/fptr_wlist.h $(srcdir)/util/storage/lruhash.h \
- $(srcdir)/util/module.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h \
- $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/services/mesh.h \
- $(srcdir)/util/rbtree.h $(srcdir)/services/modstack.h $(srcdir)/util/ub_event.h
+ $(srcdir)/util/fptr_wlist.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/module.h \
+ $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgparse.h \
+ $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/services/mesh.h $(srcdir)/util/rbtree.h \
+ $(srcdir)/services/modstack.h $(srcdir)/services/rpz.h $(srcdir)/services/localzone.h \
+ $(srcdir)/util/storage/dnstree.h $(srcdir)/services/view.h $(srcdir)/sldns/sbuffer.h \
+ $(srcdir)/util/config_file.h $(srcdir)/services/authzone.h $(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h \
+ $(srcdir)/libunbound/unbound.h $(srcdir)/respip/respip.h $(srcdir)/util/ub_event.h
 ub_event.lo ub_event.o: $(srcdir)/util/ub_event.c config.h $(srcdir)/util/ub_event.h $(srcdir)/util/log.h \
  $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h  \
- $(srcdir)/dnscrypt/cert.h $(srcdir)/util/locks.h $(srcdir)/util/tube.h \
-
+ $(srcdir)/util/tube.h $(srcdir)/util/mini_event.h $(srcdir)/util/rbtree.h
 ub_event_pluggable.lo ub_event_pluggable.o: $(srcdir)/util/ub_event_pluggable.c config.h $(srcdir)/util/ub_event.h \
  $(srcdir)/libunbound/unbound-event.h $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
-  $(srcdir)/dnscrypt/cert.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \
- $(srcdir)/util/fptr_wlist.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/module.h \
- $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgparse.h \
- $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/tube.h $(srcdir)/services/mesh.h $(srcdir)/util/rbtree.h \
- $(srcdir)/services/modstack.h \
-
+  $(srcdir)/util/log.h $(srcdir)/util/fptr_wlist.h \
+ $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/module.h $(srcdir)/util/data/msgreply.h \
+ $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h \
+ $(srcdir)/sldns/rrdef.h $(srcdir)/util/tube.h $(srcdir)/services/mesh.h $(srcdir)/util/rbtree.h \
+ $(srcdir)/services/modstack.h $(srcdir)/services/rpz.h $(srcdir)/services/localzone.h \
+ $(srcdir)/util/storage/dnstree.h $(srcdir)/services/view.h $(srcdir)/sldns/sbuffer.h \
+ $(srcdir)/util/config_file.h $(srcdir)/services/authzone.h $(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h \
+ $(srcdir)/libunbound/unbound.h $(srcdir)/respip/respip.h $(srcdir)/util/mini_event.h $(srcdir)/util/rbtree.h
 winsock_event.lo winsock_event.o: $(srcdir)/util/winsock_event.c config.h
 autotrust.lo autotrust.o: $(srcdir)/validator/autotrust.c config.h $(srcdir)/validator/autotrust.h \
  $(srcdir)/util/rbtree.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h \
@@ -958,10 +1003,11 @@ autotrust.lo autotrust.o: $(srcdir)/vali
  $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/net_help.h \
  $(srcdir)/util/config_file.h $(srcdir)/util/regional.h $(srcdir)/util/random.h $(srcdir)/services/mesh.h \
  $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h  \
- $(srcdir)/dnscrypt/cert.h $(srcdir)/services/modstack.h $(srcdir)/services/cache/rrset.h \
- $(srcdir)/util/storage/slabhash.h $(srcdir)/validator/val_kcache.h $(srcdir)/sldns/sbuffer.h \
- $(srcdir)/sldns/wire2str.h $(srcdir)/sldns/str2wire.h $(srcdir)/sldns/keyraw.h \
-
+ $(srcdir)/services/modstack.h $(srcdir)/services/rpz.h $(srcdir)/services/localzone.h \
+ $(srcdir)/util/storage/dnstree.h $(srcdir)/services/view.h $(srcdir)/sldns/sbuffer.h \
+ $(srcdir)/services/authzone.h $(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h $(srcdir)/libunbound/unbound.h \
+ $(srcdir)/respip/respip.h $(srcdir)/services/cache/rrset.h $(srcdir)/util/storage/slabhash.h \
+ $(srcdir)/validator/val_kcache.h $(srcdir)/sldns/wire2str.h $(srcdir)/sldns/str2wire.h $(srcdir)/sldns/keyraw.h
 val_anchor.lo val_anchor.o: $(srcdir)/validator/val_anchor.c config.h $(srcdir)/validator/val_anchor.h \
  $(srcdir)/util/rbtree.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/validator/val_sigcrypt.h \
  $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h $(srcdir)/sldns/pkthdr.h \
@@ -978,8 +1024,11 @@ validator.lo validator.o: $(srcdir)/vali
  $(srcdir)/validator/autotrust.h $(srcdir)/services/cache/dns.h $(srcdir)/services/cache/rrset.h \
  $(srcdir)/util/data/dname.h $(srcdir)/util/net_help.h $(srcdir)/util/regional.h $(srcdir)/util/config_file.h \
  $(srcdir)/util/fptr_wlist.h $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
-  $(srcdir)/dnscrypt/cert.h $(srcdir)/util/tube.h $(srcdir)/services/mesh.h \
- $(srcdir)/services/modstack.h $(srcdir)/sldns/wire2str.h $(srcdir)/sldns/str2wire.h
+  $(srcdir)/util/tube.h $(srcdir)/services/mesh.h \
+ $(srcdir)/services/modstack.h $(srcdir)/services/rpz.h $(srcdir)/services/localzone.h \
+ $(srcdir)/util/storage/dnstree.h $(srcdir)/services/view.h $(srcdir)/sldns/sbuffer.h \
+ $(srcdir)/services/authzone.h $(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h $(srcdir)/libunbound/unbound.h \
+ $(srcdir)/respip/respip.h $(srcdir)/sldns/wire2str.h $(srcdir)/sldns/str2wire.h
 val_kcache.lo val_kcache.o: $(srcdir)/validator/val_kcache.c config.h $(srcdir)/validator/val_kcache.h \
  $(srcdir)/util/storage/slabhash.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \
  $(srcdir)/validator/val_kentry.h $(srcdir)/util/config_file.h $(srcdir)/util/data/dname.h \
@@ -988,13 +1037,11 @@ val_kcache.lo val_kcache.o: $(srcdir)/va
 val_kentry.lo val_kentry.o: $(srcdir)/validator/val_kentry.c config.h $(srcdir)/validator/val_kentry.h \
  $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/data/packed_rrset.h \
  $(srcdir)/util/data/dname.h $(srcdir)/util/storage/lookup3.h $(srcdir)/util/regional.h $(srcdir)/util/net_help.h \
- $(srcdir)/sldns/rrdef.h $(srcdir)/sldns/keyraw.h \
-
-val_neg.lo val_neg.o: $(srcdir)/validator/val_neg.c config.h \
- $(srcdir)/validator/val_neg.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/rbtree.h \
- $(srcdir)/validator/val_nsec.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h \
- $(srcdir)/validator/val_nsec3.h $(srcdir)/validator/val_utils.h $(srcdir)/sldns/pkthdr.h \
- $(srcdir)/util/data/dname.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/net_help.h \
+ $(srcdir)/sldns/rrdef.h $(srcdir)/sldns/keyraw.h
+val_neg.lo val_neg.o: $(srcdir)/validator/val_neg.c config.h $(srcdir)/validator/val_neg.h $(srcdir)/util/locks.h \
+ $(srcdir)/util/log.h $(srcdir)/util/rbtree.h $(srcdir)/validator/val_nsec.h $(srcdir)/util/data/packed_rrset.h \
+ $(srcdir)/util/storage/lruhash.h $(srcdir)/validator/val_nsec3.h $(srcdir)/validator/val_utils.h \
+ $(srcdir)/sldns/pkthdr.h $(srcdir)/util/data/dname.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/net_help.h \
  $(srcdir)/util/config_file.h $(srcdir)/services/cache/rrset.h $(srcdir)/util/storage/slabhash.h \
  $(srcdir)/services/cache/dns.h $(srcdir)/sldns/rrdef.h $(srcdir)/sldns/sbuffer.h
 val_nsec3.lo val_nsec3.o: $(srcdir)/validator/val_nsec3.c config.h $(srcdir)/validator/val_nsec3.h \
@@ -1012,17 +1059,15 @@ val_nsec.lo val_nsec.o: $(srcdir)/valida
 val_secalgo.lo val_secalgo.o: $(srcdir)/validator/val_secalgo.c config.h $(srcdir)/util/data/packed_rrset.h \
  $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/validator/val_secalgo.h \
  $(srcdir)/validator/val_nsec3.h $(srcdir)/util/rbtree.h $(srcdir)/sldns/rrdef.h $(srcdir)/sldns/keyraw.h \
- $(srcdir)/sldns/sbuffer.h \
-
+ $(srcdir)/sldns/sbuffer.h
 val_sigcrypt.lo val_sigcrypt.o: $(srcdir)/validator/val_sigcrypt.c config.h \
  $(srcdir)/validator/val_sigcrypt.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h \
  $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/sldns/pkthdr.h $(srcdir)/validator/val_secalgo.h \
  $(srcdir)/validator/validator.h $(srcdir)/util/module.h $(srcdir)/util/data/msgreply.h \
  $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/rrdef.h $(srcdir)/validator/val_utils.h \
  $(srcdir)/util/data/dname.h $(srcdir)/util/rbtree.h $(srcdir)/util/net_help.h $(srcdir)/util/regional.h \
- $(srcdir)/util/config_file.h $(srcdir)/sldns/keyraw.h \
- $(srcdir)/sldns/sbuffer.h $(srcdir)/sldns/parseutil.h $(srcdir)/sldns/wire2str.h \
-
+ $(srcdir)/util/config_file.h $(srcdir)/sldns/keyraw.h $(srcdir)/sldns/sbuffer.h $(srcdir)/sldns/parseutil.h \
+ $(srcdir)/sldns/wire2str.h
 val_utils.lo val_utils.o: $(srcdir)/validator/val_utils.c config.h $(srcdir)/validator/val_utils.h \
  $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \
  $(srcdir)/sldns/pkthdr.h $(srcdir)/validator/validator.h $(srcdir)/util/module.h $(srcdir)/util/data/msgreply.h \
@@ -1038,9 +1083,11 @@ dns64.lo dns64.o: $(srcdir)/dns64/dns64.
  $(srcdir)/sldns/rrdef.h $(srcdir)/services/cache/dns.h $(srcdir)/services/cache/rrset.h \
  $(srcdir)/util/storage/slabhash.h $(srcdir)/util/config_file.h $(srcdir)/util/fptr_wlist.h \
  $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h  \
- $(srcdir)/dnscrypt/cert.h $(srcdir)/util/tube.h $(srcdir)/services/mesh.h $(srcdir)/util/rbtree.h \
- $(srcdir)/services/modstack.h $(srcdir)/util/net_help.h $(srcdir)/util/regional.h \
- $(srcdir)/util/storage/dnstree.h $(srcdir)/util/data/dname.h $(srcdir)/sldns/str2wire.h
+ $(srcdir)/util/tube.h $(srcdir)/services/mesh.h $(srcdir)/util/rbtree.h $(srcdir)/services/modstack.h \
+ $(srcdir)/services/rpz.h $(srcdir)/services/localzone.h $(srcdir)/util/storage/dnstree.h \
+ $(srcdir)/services/view.h $(srcdir)/sldns/sbuffer.h $(srcdir)/services/authzone.h $(srcdir)/daemon/stats.h \
+ $(srcdir)/util/timehist.h $(srcdir)/libunbound/unbound.h $(srcdir)/respip/respip.h $(srcdir)/util/net_help.h \
+ $(srcdir)/util/regional.h $(srcdir)/util/data/dname.h $(srcdir)/sldns/str2wire.h
 edns-subnet.lo edns-subnet.o: $(srcdir)/edns-subnet/edns-subnet.c config.h
 subnetmod.lo subnetmod.o: $(srcdir)/edns-subnet/subnetmod.c config.h
 addrtree.lo addrtree.o: $(srcdir)/edns-subnet/addrtree.c config.h $(srcdir)/util/log.h \
@@ -1054,36 +1101,16 @@ respip.lo respip.o: $(srcdir)/respip/res
  $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/storage/dnstree.h $(srcdir)/util/module.h \
  $(srcdir)/util/storage/lruhash.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h \
  $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/services/view.h \
- $(srcdir)/services/cache/dns.h $(srcdir)/sldns/str2wire.h $(srcdir)/util/config_file.h \
- $(srcdir)/util/fptr_wlist.h $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
-  $(srcdir)/dnscrypt/cert.h $(srcdir)/util/tube.h $(srcdir)/services/mesh.h \
- $(srcdir)/services/modstack.h $(srcdir)/util/net_help.h $(srcdir)/util/regional.h $(srcdir)/respip/respip.h
+ $(srcdir)/sldns/sbuffer.h $(srcdir)/services/authzone.h $(srcdir)/services/mesh.h $(srcdir)/util/netevent.h \
+ $(srcdir)/dnscrypt/dnscrypt.h  $(srcdir)/services/modstack.h \
+ $(srcdir)/services/rpz.h $(srcdir)/util/config_file.h $(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h \
+ $(srcdir)/libunbound/unbound.h $(srcdir)/respip/respip.h $(srcdir)/services/cache/dns.h \
+ $(srcdir)/sldns/str2wire.h $(srcdir)/util/fptr_wlist.h $(srcdir)/util/tube.h $(srcdir)/util/net_help.h \
+ $(srcdir)/util/regional.h
 checklocks.lo checklocks.o: $(srcdir)/testcode/checklocks.c config.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \
  $(srcdir)/testcode/checklocks.h
-dnstap.lo dnstap.o: $(srcdir)/dnstap/dnstap.c  config.h $(srcdir)/sldns/sbuffer.h \
- $(srcdir)/util/config_file.h $(srcdir)/util/net_help.h $(srcdir)/util/log.h $(srcdir)/util/netevent.h \
- $(srcdir)/dnscrypt/dnscrypt.h  $(srcdir)/dnscrypt/cert.h \
- $(srcdir)/util/locks.h $(srcdir)/dnstap/dnstap.h \
- dnstap/dnstap.pb-c.h
-dnstap.pb-c.lo dnstap.pb-c.o: dnstap/dnstap.pb-c.c dnstap/dnstap.pb-c.h \
-
-dnscrypt.lo dnscrypt.o: $(srcdir)/dnscrypt/dnscrypt.c config.h $(srcdir)/sldns/sbuffer.h \
- $(srcdir)/util/config_file.h $(srcdir)/util/net_help.h $(srcdir)/util/log.h $(srcdir)/util/netevent.h \
- $(srcdir)/dnscrypt/dnscrypt.h  $(srcdir)/dnscrypt/cert.h \
- $(srcdir)/util/locks.h $(srcdir)/util/storage/slabhash.h $(srcdir)/util/storage/lruhash.h \
- $(srcdir)/util/storage/lookup3.h
 ipsecmod.lo ipsecmod.o: $(srcdir)/ipsecmod/ipsecmod.c config.h
-ipsecmod-whitelist.lo ipsecmod-whitelist.o: $(srcdir)/ipsecmod/ipsecmod-whitelist.c config.h \
- $(srcdir)/ipsecmod/ipsecmod.h $(srcdir)/util/module.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h \
- $(srcdir)/util/log.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h \
- $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/rbtree.h \
- $(srcdir)/ipsecmod/ipsecmod-whitelist.h $(srcdir)/util/storage/dnstree.h $(srcdir)/util/regional.h \
- $(srcdir)/util/config_file.h $(srcdir)/util/data/dname.h $(srcdir)/sldns/str2wire.h
-ipset.lo ipset.o: $(srcdir)/ipset/ipset.c config.h $(srcdir)/ipset/ipset.h $(srcdir)/util/module.h \
- $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/data/msgreply.h \
- $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h \
- $(srcdir)/sldns/rrdef.h $(srcdir)/util/regional.h $(srcdir)/util/config_file.h $(srcdir)/services/cache/dns.h \
- $(srcdir)/sldns/sbuffer.h $(srcdir)/sldns/wire2str.h $(srcdir)/sldns/parseutil.h
+ipsecmod-whitelist.lo ipsecmod-whitelist.o: $(srcdir)/ipsecmod/ipsecmod-whitelist.c config.h
 unitanchor.lo unitanchor.o: $(srcdir)/testcode/unitanchor.c config.h $(srcdir)/util/log.h $(srcdir)/util/data/dname.h \
  $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/testcode/unitmain.h \
  $(srcdir)/validator/val_anchor.h $(srcdir)/util/rbtree.h $(srcdir)/sldns/sbuffer.h $(srcdir)/sldns/rrdef.h
@@ -1092,16 +1119,15 @@ unitdname.lo unitdname.o: $(srcdir)/test
  $(srcdir)/sldns/str2wire.h $(srcdir)/sldns/rrdef.h
 unitlruhash.lo unitlruhash.o: $(srcdir)/testcode/unitlruhash.c config.h $(srcdir)/testcode/unitmain.h \
  $(srcdir)/util/log.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/storage/slabhash.h
-unitmain.lo unitmain.o: $(srcdir)/testcode/unitmain.c config.h \
- $(srcdir)/sldns/rrdef.h $(srcdir)/sldns/keyraw.h \
+unitmain.lo unitmain.o: $(srcdir)/testcode/unitmain.c config.h $(srcdir)/sldns/rrdef.h $(srcdir)/sldns/keyraw.h \
  $(srcdir)/util/log.h $(srcdir)/testcode/unitmain.h $(srcdir)/util/alloc.h $(srcdir)/util/locks.h $(srcdir)/util/net_help.h \
  $(srcdir)/util/config_file.h $(srcdir)/util/rtt.h $(srcdir)/util/timehist.h $(srcdir)/iterator/iterator.h \
  $(srcdir)/services/outbound_list.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/storage/lruhash.h \
  $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/module.h $(srcdir)/util/data/msgparse.h \
  $(srcdir)/sldns/pkthdr.h $(srcdir)/libunbound/unbound.h $(srcdir)/services/cache/infra.h \
  $(srcdir)/util/storage/dnstree.h $(srcdir)/util/rbtree.h $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
-  $(srcdir)/dnscrypt/cert.h $(srcdir)/util/random.h $(srcdir)/respip/respip.h \
- $(srcdir)/services/localzone.h $(srcdir)/services/view.h
+  $(srcdir)/util/random.h $(srcdir)/respip/respip.h \
+ $(srcdir)/services/localzone.h $(srcdir)/services/view.h $(srcdir)/sldns/sbuffer.h
 unitmsgparse.lo unitmsgparse.o: $(srcdir)/testcode/unitmsgparse.c config.h $(srcdir)/util/log.h \
  $(srcdir)/testcode/unitmain.h $(srcdir)/util/data/msgparse.h $(srcdir)/util/storage/lruhash.h \
  $(srcdir)/util/locks.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/data/msgreply.h \
@@ -1135,59 +1161,59 @@ unitldns.lo unitldns.o: $(srcdir)/testco
 unitecs.lo unitecs.o: $(srcdir)/testcode/unitecs.c config.h
 unitauth.lo unitauth.o: $(srcdir)/testcode/unitauth.c config.h $(srcdir)/services/authzone.h \
  $(srcdir)/util/rbtree.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/services/mesh.h $(srcdir)/util/netevent.h \
- $(srcdir)/dnscrypt/dnscrypt.h  $(srcdir)/dnscrypt/cert.h \
- $(srcdir)/util/data/msgparse.h $(srcdir)/util/storage/lruhash.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h \
- $(srcdir)/util/module.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h \
- $(srcdir)/services/modstack.h $(srcdir)/testcode/unitmain.h $(srcdir)/util/regional.h $(srcdir)/util/net_help.h \
- $(srcdir)/util/config_file.h $(srcdir)/services/cache/dns.h $(srcdir)/sldns/str2wire.h \
- $(srcdir)/sldns/wire2str.h $(srcdir)/sldns/sbuffer.h
+ $(srcdir)/dnscrypt/dnscrypt.h  $(srcdir)/util/data/msgparse.h \
+ $(srcdir)/util/storage/lruhash.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/module.h \
+ $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/services/modstack.h \
+ $(srcdir)/services/rpz.h $(srcdir)/services/localzone.h $(srcdir)/util/storage/dnstree.h \
+ $(srcdir)/services/view.h $(srcdir)/sldns/sbuffer.h $(srcdir)/util/config_file.h $(srcdir)/daemon/stats.h \
+ $(srcdir)/util/timehist.h $(srcdir)/libunbound/unbound.h $(srcdir)/respip/respip.h $(srcdir)/testcode/unitmain.h \
+ $(srcdir)/util/regional.h $(srcdir)/util/net_help.h $(srcdir)/services/cache/dns.h $(srcdir)/sldns/str2wire.h \
+ $(srcdir)/sldns/wire2str.h
 acl_list.lo acl_list.o: $(srcdir)/daemon/acl_list.c config.h $(srcdir)/daemon/acl_list.h \
  $(srcdir)/util/storage/dnstree.h $(srcdir)/util/rbtree.h $(srcdir)/services/view.h $(srcdir)/util/locks.h \
  $(srcdir)/util/log.h $(srcdir)/util/regional.h $(srcdir)/util/config_file.h $(srcdir)/util/net_help.h \
  $(srcdir)/services/localzone.h $(srcdir)/util/module.h $(srcdir)/util/storage/lruhash.h \
  $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgparse.h \
- $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/sldns/str2wire.h
-cachedump.lo cachedump.o: $(srcdir)/daemon/cachedump.c config.h \
- $(srcdir)/daemon/cachedump.h $(srcdir)/daemon/remote.h $(srcdir)/daemon/worker.h $(srcdir)/libunbound/worker.h \
- $(srcdir)/sldns/sbuffer.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h \
- $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
-  $(srcdir)/dnscrypt/cert.h $(srcdir)/util/alloc.h \
- $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h \
- $(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h $(srcdir)/libunbound/unbound.h $(srcdir)/util/module.h \
- $(srcdir)/dnstap/dnstap.h  $(srcdir)/services/cache/rrset.h \
- $(srcdir)/util/storage/slabhash.h $(srcdir)/services/cache/dns.h $(srcdir)/services/cache/infra.h \
- $(srcdir)/util/storage/dnstree.h $(srcdir)/util/rbtree.h $(srcdir)/util/rtt.h $(srcdir)/util/regional.h \
- $(srcdir)/util/net_help.h $(srcdir)/util/data/dname.h $(srcdir)/iterator/iterator.h \
+ $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/sldns/sbuffer.h $(srcdir)/sldns/str2wire.h
+cachedump.lo cachedump.o: $(srcdir)/daemon/cachedump.c config.h $(srcdir)/daemon/cachedump.h \
+ $(srcdir)/daemon/remote.h $(srcdir)/daemon/worker.h $(srcdir)/libunbound/worker.h $(srcdir)/sldns/sbuffer.h \
+ $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \
+ $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h  \
+ $(srcdir)/util/alloc.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h \
+ $(srcdir)/sldns/rrdef.h $(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h $(srcdir)/libunbound/unbound.h \
+ $(srcdir)/util/module.h $(srcdir)/dnstap/dnstap.h  \
+ $(srcdir)/services/cache/rrset.h $(srcdir)/util/storage/slabhash.h $(srcdir)/services/cache/dns.h \
+ $(srcdir)/services/cache/infra.h $(srcdir)/util/storage/dnstree.h $(srcdir)/util/rbtree.h $(srcdir)/util/rtt.h \
+ $(srcdir)/util/regional.h $(srcdir)/util/net_help.h $(srcdir)/util/data/dname.h $(srcdir)/iterator/iterator.h \
  $(srcdir)/services/outbound_list.h $(srcdir)/iterator/iter_delegpt.h $(srcdir)/iterator/iter_utils.h \
  $(srcdir)/iterator/iter_resptype.h $(srcdir)/iterator/iter_fwd.h $(srcdir)/iterator/iter_hints.h \
  $(srcdir)/sldns/wire2str.h $(srcdir)/sldns/str2wire.h
-daemon.lo daemon.o: $(srcdir)/daemon/daemon.c config.h \
- $(srcdir)/daemon/daemon.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/alloc.h $(srcdir)/services/modstack.h \
-   $(srcdir)/daemon/worker.h \
+daemon.lo daemon.o: $(srcdir)/daemon/daemon.c config.h $(srcdir)/daemon/daemon.h $(srcdir)/util/locks.h \
+ $(srcdir)/util/log.h $(srcdir)/util/alloc.h $(srcdir)/services/modstack.h  \
+  $(srcdir)/daemon/worker.h $(srcdir)/libunbound/worker.h \
+ $(srcdir)/sldns/sbuffer.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h \
+ $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h $(srcdir)/util/data/msgreply.h \
+ $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/daemon/stats.h \
+ $(srcdir)/util/timehist.h $(srcdir)/libunbound/unbound.h $(srcdir)/util/module.h $(srcdir)/dnstap/dnstap.h \
+ $(srcdir)/daemon/remote.h $(srcdir)/daemon/acl_list.h $(srcdir)/util/storage/dnstree.h $(srcdir)/util/rbtree.h \
+ $(srcdir)/services/view.h $(srcdir)/util/config_file.h $(srcdir)/util/shm_side/shm_main.h \
+ $(srcdir)/util/storage/lookup3.h $(srcdir)/util/storage/slabhash.h $(srcdir)/util/tcp_conn_limit.h \
+ $(srcdir)/services/listen_dnsport.h $(srcdir)/services/cache/rrset.h $(srcdir)/services/cache/infra.h \
+ $(srcdir)/util/rtt.h $(srcdir)/services/localzone.h $(srcdir)/services/authzone.h $(srcdir)/services/mesh.h \
+ $(srcdir)/services/rpz.h $(srcdir)/respip/respip.h $(srcdir)/util/random.h $(srcdir)/util/tube.h $(srcdir)/util/net_help.h \
+ $(srcdir)/sldns/keyraw.h
+remote.lo remote.o: $(srcdir)/daemon/remote.c config.h $(srcdir)/daemon/remote.h $(srcdir)/daemon/worker.h \
  $(srcdir)/libunbound/worker.h $(srcdir)/sldns/sbuffer.h $(srcdir)/util/data/packed_rrset.h \
- $(srcdir)/util/storage/lruhash.h $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
- $(srcdir)/dnscrypt/cert.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h \
- $(srcdir)/sldns/rrdef.h $(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h $(srcdir)/libunbound/unbound.h \
- $(srcdir)/util/module.h $(srcdir)/dnstap/dnstap.h $(srcdir)/daemon/remote.h \
- $(srcdir)/daemon/acl_list.h $(srcdir)/util/storage/dnstree.h $(srcdir)/util/rbtree.h $(srcdir)/services/view.h \
- $(srcdir)/util/config_file.h $(srcdir)/util/shm_side/shm_main.h $(srcdir)/util/storage/lookup3.h \
- $(srcdir)/util/storage/slabhash.h $(srcdir)/util/tcp_conn_limit.h $(srcdir)/services/listen_dnsport.h \
- $(srcdir)/services/cache/rrset.h $(srcdir)/services/cache/infra.h $(srcdir)/util/rtt.h \
- $(srcdir)/services/localzone.h $(srcdir)/services/authzone.h $(srcdir)/services/mesh.h $(srcdir)/util/random.h \
- $(srcdir)/util/tube.h $(srcdir)/util/net_help.h $(srcdir)/sldns/keyraw.h $(srcdir)/respip/respip.h
-remote.lo remote.o: $(srcdir)/daemon/remote.c config.h \
- $(srcdir)/daemon/remote.h \
- $(srcdir)/daemon/worker.h $(srcdir)/libunbound/worker.h $(srcdir)/sldns/sbuffer.h \
- $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \
- $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h  \
- $(srcdir)/dnscrypt/cert.h $(srcdir)/util/alloc.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/msgparse.h \
- $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h \
- $(srcdir)/libunbound/unbound.h $(srcdir)/util/module.h $(srcdir)/dnstap/dnstap.h \
-  $(srcdir)/daemon/daemon.h $(srcdir)/services/modstack.h \
- $(srcdir)/daemon/cachedump.h $(srcdir)/util/config_file.h $(srcdir)/util/net_help.h \
- $(srcdir)/services/listen_dnsport.h $(srcdir)/services/cache/rrset.h $(srcdir)/util/storage/slabhash.h \
- $(srcdir)/services/cache/infra.h $(srcdir)/util/storage/dnstree.h $(srcdir)/util/rbtree.h $(srcdir)/util/rtt.h \
- $(srcdir)/services/mesh.h $(srcdir)/services/localzone.h $(srcdir)/services/view.h $(srcdir)/services/authzone.h \
+ $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/netevent.h \
+ $(srcdir)/dnscrypt/dnscrypt.h  $(srcdir)/util/alloc.h \
+ $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h \
+ $(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h $(srcdir)/libunbound/unbound.h $(srcdir)/util/module.h \
+ $(srcdir)/dnstap/dnstap.h  $(srcdir)/daemon/daemon.h \
+ $(srcdir)/services/modstack.h $(srcdir)/daemon/cachedump.h $(srcdir)/util/config_file.h \
+ $(srcdir)/util/net_help.h $(srcdir)/services/listen_dnsport.h $(srcdir)/services/cache/rrset.h \
+ $(srcdir)/util/storage/slabhash.h $(srcdir)/services/cache/infra.h $(srcdir)/util/storage/dnstree.h \
+ $(srcdir)/util/rbtree.h $(srcdir)/util/rtt.h $(srcdir)/services/mesh.h $(srcdir)/services/rpz.h \
+ $(srcdir)/services/localzone.h $(srcdir)/services/view.h $(srcdir)/services/authzone.h $(srcdir)/respip/respip.h \
  $(srcdir)/util/fptr_wlist.h $(srcdir)/util/tube.h $(srcdir)/util/data/dname.h $(srcdir)/validator/validator.h \
  $(srcdir)/validator/val_utils.h $(srcdir)/validator/val_kcache.h $(srcdir)/validator/val_kentry.h \
  $(srcdir)/validator/val_anchor.h $(srcdir)/iterator/iterator.h $(srcdir)/services/outbound_list.h \
@@ -1198,56 +1224,59 @@ stats.lo stats.o: $(srcdir)/daemon/stats
  $(srcdir)/libunbound/unbound.h $(srcdir)/daemon/worker.h $(srcdir)/libunbound/worker.h $(srcdir)/sldns/sbuffer.h \
  $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \
  $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h  \
- $(srcdir)/dnscrypt/cert.h $(srcdir)/util/alloc.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/msgparse.h \
- $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/module.h $(srcdir)/dnstap/dnstap.h \
-  $(srcdir)/daemon/daemon.h $(srcdir)/services/modstack.h \
- $(srcdir)/services/mesh.h $(srcdir)/util/rbtree.h $(srcdir)/services/outside_network.h \
- $(srcdir)/services/listen_dnsport.h $(srcdir)/util/config_file.h $(srcdir)/util/tube.h $(srcdir)/util/net_help.h \
- $(srcdir)/validator/validator.h $(srcdir)/validator/val_utils.h $(srcdir)/iterator/iterator.h \
- $(srcdir)/services/outbound_list.h $(srcdir)/services/cache/rrset.h $(srcdir)/util/storage/slabhash.h \
- $(srcdir)/services/cache/infra.h $(srcdir)/util/storage/dnstree.h $(srcdir)/util/rtt.h \
- $(srcdir)/services/authzone.h $(srcdir)/validator/val_kcache.h $(srcdir)/validator/val_neg.h \
-
+ $(srcdir)/util/alloc.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h \
+ $(srcdir)/sldns/rrdef.h $(srcdir)/util/module.h $(srcdir)/dnstap/dnstap.h  \
+ $(srcdir)/daemon/daemon.h $(srcdir)/services/modstack.h $(srcdir)/services/mesh.h $(srcdir)/util/rbtree.h \
+ $(srcdir)/services/rpz.h $(srcdir)/services/localzone.h $(srcdir)/util/storage/dnstree.h \
+ $(srcdir)/services/view.h $(srcdir)/util/config_file.h $(srcdir)/services/authzone.h $(srcdir)/respip/respip.h \
+ $(srcdir)/services/outside_network.h $(srcdir)/services/listen_dnsport.h $(srcdir)/util/tube.h \
+ $(srcdir)/util/net_help.h $(srcdir)/validator/validator.h $(srcdir)/validator/val_utils.h \
+ $(srcdir)/iterator/iterator.h $(srcdir)/services/outbound_list.h $(srcdir)/services/cache/rrset.h \
+ $(srcdir)/util/storage/slabhash.h $(srcdir)/services/cache/infra.h $(srcdir)/util/rtt.h \
+ $(srcdir)/validator/val_kcache.h $(srcdir)/validator/val_neg.h
 unbound.lo unbound.o: $(srcdir)/daemon/unbound.c config.h $(srcdir)/util/log.h $(srcdir)/daemon/daemon.h \
  $(srcdir)/util/locks.h $(srcdir)/util/alloc.h $(srcdir)/services/modstack.h  \
-  $(srcdir)/daemon/remote.h \
- $(srcdir)/util/config_file.h $(srcdir)/util/storage/slabhash.h $(srcdir)/util/storage/lruhash.h \
- $(srcdir)/services/listen_dnsport.h $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
- $(srcdir)/dnscrypt/cert.h $(srcdir)/services/cache/rrset.h $(srcdir)/util/data/packed_rrset.h \
- $(srcdir)/services/cache/infra.h $(srcdir)/util/storage/dnstree.h $(srcdir)/util/rbtree.h $(srcdir)/util/rtt.h \
- $(srcdir)/util/data/msgreply.h $(srcdir)/util/fptr_wlist.h $(srcdir)/util/module.h \
- $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/tube.h \
- $(srcdir)/services/mesh.h $(srcdir)/util/net_help.h $(srcdir)/util/ub_event.h
+  $(srcdir)/daemon/remote.h $(srcdir)/util/config_file.h \
+ $(srcdir)/util/storage/slabhash.h $(srcdir)/util/storage/lruhash.h $(srcdir)/services/listen_dnsport.h \
+ $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h $(srcdir)/services/cache/rrset.h \
+ $(srcdir)/util/data/packed_rrset.h $(srcdir)/services/cache/infra.h $(srcdir)/util/storage/dnstree.h \
+ $(srcdir)/util/rbtree.h $(srcdir)/util/rtt.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/fptr_wlist.h \
+ $(srcdir)/util/module.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h \
+ $(srcdir)/util/tube.h $(srcdir)/services/mesh.h $(srcdir)/services/rpz.h $(srcdir)/services/localzone.h \
+ $(srcdir)/services/view.h $(srcdir)/sldns/sbuffer.h $(srcdir)/services/authzone.h $(srcdir)/daemon/stats.h \
+ $(srcdir)/util/timehist.h $(srcdir)/libunbound/unbound.h $(srcdir)/respip/respip.h $(srcdir)/util/net_help.h \
+ $(srcdir)/util/ub_event.h
 worker.lo worker.o: $(srcdir)/daemon/worker.c config.h $(srcdir)/util/log.h $(srcdir)/util/net_help.h \
  $(srcdir)/util/random.h $(srcdir)/daemon/worker.h $(srcdir)/libunbound/worker.h $(srcdir)/sldns/sbuffer.h \
  $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h \
  $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h  \
- $(srcdir)/dnscrypt/cert.h $(srcdir)/util/alloc.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/msgparse.h \
- $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h \
- $(srcdir)/libunbound/unbound.h $(srcdir)/util/module.h $(srcdir)/dnstap/dnstap.h \
-  $(srcdir)/daemon/daemon.h $(srcdir)/services/modstack.h \
- $(srcdir)/daemon/remote.h \
- $(srcdir)/daemon/acl_list.h $(srcdir)/util/storage/dnstree.h $(srcdir)/util/rbtree.h $(srcdir)/services/view.h \
- $(srcdir)/util/config_file.h $(srcdir)/util/regional.h $(srcdir)/util/storage/slabhash.h \
- $(srcdir)/services/listen_dnsport.h $(srcdir)/services/outside_network.h \
- $(srcdir)/services/outbound_list.h $(srcdir)/services/cache/rrset.h $(srcdir)/services/cache/infra.h \
- $(srcdir)/util/rtt.h $(srcdir)/services/cache/dns.h $(srcdir)/services/authzone.h $(srcdir)/services/mesh.h \
- $(srcdir)/services/localzone.h $(srcdir)/util/data/msgencode.h $(srcdir)/util/data/dname.h \
- $(srcdir)/util/fptr_wlist.h $(srcdir)/util/tube.h $(srcdir)/util/edns.h $(srcdir)/iterator/iter_fwd.h \
- $(srcdir)/iterator/iter_hints.h $(srcdir)/validator/autotrust.h $(srcdir)/validator/val_anchor.h \
- $(srcdir)/respip/respip.h $(srcdir)/libunbound/context.h $(srcdir)/libunbound/unbound-event.h \
+ $(srcdir)/util/alloc.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h \
+ $(srcdir)/sldns/rrdef.h $(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h $(srcdir)/libunbound/unbound.h \
+ $(srcdir)/util/module.h $(srcdir)/dnstap/dnstap.h  $(srcdir)/daemon/daemon.h \
+ $(srcdir)/services/modstack.h $(srcdir)/daemon/remote.h $(srcdir)/daemon/acl_list.h \
+ $(srcdir)/util/storage/dnstree.h $(srcdir)/util/rbtree.h $(srcdir)/services/view.h $(srcdir)/util/config_file.h \
+ $(srcdir)/util/regional.h $(srcdir)/util/storage/slabhash.h $(srcdir)/services/listen_dnsport.h \
+ $(srcdir)/services/outside_network.h $(srcdir)/services/outbound_list.h \
+ $(srcdir)/services/cache/rrset.h $(srcdir)/services/cache/infra.h $(srcdir)/util/rtt.h \
+ $(srcdir)/services/cache/dns.h $(srcdir)/services/authzone.h $(srcdir)/services/mesh.h $(srcdir)/services/rpz.h \
+ $(srcdir)/services/localzone.h $(srcdir)/respip/respip.h $(srcdir)/util/data/msgencode.h \
+ $(srcdir)/util/data/dname.h $(srcdir)/util/fptr_wlist.h $(srcdir)/util/tube.h $(srcdir)/util/edns.h \
+ $(srcdir)/iterator/iter_fwd.h $(srcdir)/iterator/iter_hints.h $(srcdir)/validator/autotrust.h \
+ $(srcdir)/validator/val_anchor.h $(srcdir)/libunbound/context.h $(srcdir)/libunbound/unbound-event.h \
  $(srcdir)/libunbound/libworker.h $(srcdir)/sldns/wire2str.h $(srcdir)/util/shm_side/shm_main.h
 testbound.lo testbound.o: $(srcdir)/testcode/testbound.c config.h $(srcdir)/testcode/testpkts.h \
  $(srcdir)/testcode/replay.h $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
-  $(srcdir)/dnscrypt/cert.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \
- $(srcdir)/util/rbtree.h $(srcdir)/testcode/fake_event.h $(srcdir)/daemon/remote.h \
- $(srcdir)/util/config_file.h $(srcdir)/sldns/keyraw.h $(srcdir)/daemon/unbound.c $(srcdir)/daemon/daemon.h \
- $(srcdir)/util/alloc.h $(srcdir)/services/modstack.h  \
- $(srcdir)/util/storage/slabhash.h $(srcdir)/util/storage/lruhash.h $(srcdir)/services/listen_dnsport.h \
- $(srcdir)/services/cache/rrset.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/services/cache/infra.h \
- $(srcdir)/util/storage/dnstree.h $(srcdir)/util/rtt.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/fptr_wlist.h \
- $(srcdir)/util/module.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h \
- $(srcdir)/util/tube.h $(srcdir)/services/mesh.h $(srcdir)/util/net_help.h $(srcdir)/util/ub_event.h
+  $(srcdir)/util/rbtree.h $(srcdir)/testcode/fake_event.h \
+ $(srcdir)/daemon/remote.h $(srcdir)/util/config_file.h $(srcdir)/sldns/keyraw.h $(srcdir)/daemon/unbound.c \
+ $(srcdir)/util/log.h $(srcdir)/daemon/daemon.h $(srcdir)/util/locks.h $(srcdir)/util/alloc.h $(srcdir)/services/modstack.h \
+  $(srcdir)/util/storage/slabhash.h $(srcdir)/util/storage/lruhash.h \
+ $(srcdir)/services/listen_dnsport.h $(srcdir)/services/cache/rrset.h \
+ $(srcdir)/util/data/packed_rrset.h $(srcdir)/services/cache/infra.h $(srcdir)/util/storage/dnstree.h \
+ $(srcdir)/util/rtt.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/fptr_wlist.h $(srcdir)/util/module.h \
+ $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/tube.h \
+ $(srcdir)/services/mesh.h $(srcdir)/services/rpz.h $(srcdir)/services/localzone.h $(srcdir)/services/view.h \
+ $(srcdir)/sldns/sbuffer.h $(srcdir)/services/authzone.h $(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h \
+ $(srcdir)/libunbound/unbound.h $(srcdir)/respip/respip.h $(srcdir)/util/net_help.h $(srcdir)/util/ub_event.h
 testpkts.lo testpkts.o: $(srcdir)/testcode/testpkts.c config.h $(srcdir)/testcode/testpkts.h \
  $(srcdir)/util/net_help.h $(srcdir)/util/log.h $(srcdir)/sldns/sbuffer.h $(srcdir)/sldns/rrdef.h $(srcdir)/sldns/pkthdr.h \
  $(srcdir)/sldns/str2wire.h $(srcdir)/sldns/wire2str.h
@@ -1255,77 +1284,79 @@ worker.lo worker.o: $(srcdir)/daemon/wor
  $(srcdir)/util/random.h $(srcdir)/daemon/worker.h $(srcdir)/libunbound/worker.h $(srcdir)/sldns/sbuffer.h \
  $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h \
  $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h  \
- $(srcdir)/dnscrypt/cert.h $(srcdir)/util/alloc.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/msgparse.h \
- $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h \
- $(srcdir)/libunbound/unbound.h $(srcdir)/util/module.h $(srcdir)/dnstap/dnstap.h \
-  $(srcdir)/daemon/daemon.h $(srcdir)/services/modstack.h \
- $(srcdir)/daemon/remote.h \
- $(srcdir)/daemon/acl_list.h $(srcdir)/util/storage/dnstree.h $(srcdir)/util/rbtree.h $(srcdir)/services/view.h \
- $(srcdir)/util/config_file.h $(srcdir)/util/regional.h $(srcdir)/util/storage/slabhash.h \
- $(srcdir)/services/listen_dnsport.h $(srcdir)/services/outside_network.h \
- $(srcdir)/services/outbound_list.h $(srcdir)/services/cache/rrset.h $(srcdir)/services/cache/infra.h \
- $(srcdir)/util/rtt.h $(srcdir)/services/cache/dns.h $(srcdir)/services/authzone.h $(srcdir)/services/mesh.h \
- $(srcdir)/services/localzone.h $(srcdir)/util/data/msgencode.h $(srcdir)/util/data/dname.h \
- $(srcdir)/util/fptr_wlist.h $(srcdir)/util/tube.h $(srcdir)/util/edns.h $(srcdir)/iterator/iter_fwd.h \
- $(srcdir)/iterator/iter_hints.h $(srcdir)/validator/autotrust.h $(srcdir)/validator/val_anchor.h \
- $(srcdir)/respip/respip.h $(srcdir)/libunbound/context.h $(srcdir)/libunbound/unbound-event.h \
+ $(srcdir)/util/alloc.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h \
+ $(srcdir)/sldns/rrdef.h $(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h $(srcdir)/libunbound/unbound.h \
+ $(srcdir)/util/module.h $(srcdir)/dnstap/dnstap.h  $(srcdir)/daemon/daemon.h \
+ $(srcdir)/services/modstack.h $(srcdir)/daemon/remote.h $(srcdir)/daemon/acl_list.h \
+ $(srcdir)/util/storage/dnstree.h $(srcdir)/util/rbtree.h $(srcdir)/services/view.h $(srcdir)/util/config_file.h \
+ $(srcdir)/util/regional.h $(srcdir)/util/storage/slabhash.h $(srcdir)/services/listen_dnsport.h \
+ $(srcdir)/services/outside_network.h $(srcdir)/services/outbound_list.h \
+ $(srcdir)/services/cache/rrset.h $(srcdir)/services/cache/infra.h $(srcdir)/util/rtt.h \
+ $(srcdir)/services/cache/dns.h $(srcdir)/services/authzone.h $(srcdir)/services/mesh.h $(srcdir)/services/rpz.h \
+ $(srcdir)/services/localzone.h $(srcdir)/respip/respip.h $(srcdir)/util/data/msgencode.h \
+ $(srcdir)/util/data/dname.h $(srcdir)/util/fptr_wlist.h $(srcdir)/util/tube.h $(srcdir)/util/edns.h \
+ $(srcdir)/iterator/iter_fwd.h $(srcdir)/iterator/iter_hints.h $(srcdir)/validator/autotrust.h \
+ $(srcdir)/validator/val_anchor.h $(srcdir)/libunbound/context.h $(srcdir)/libunbound/unbound-event.h \
  $(srcdir)/libunbound/libworker.h $(srcdir)/sldns/wire2str.h $(srcdir)/util/shm_side/shm_main.h
 acl_list.lo acl_list.o: $(srcdir)/daemon/acl_list.c config.h $(srcdir)/daemon/acl_list.h \
  $(srcdir)/util/storage/dnstree.h $(srcdir)/util/rbtree.h $(srcdir)/services/view.h $(srcdir)/util/locks.h \
  $(srcdir)/util/log.h $(srcdir)/util/regional.h $(srcdir)/util/config_file.h $(srcdir)/util/net_help.h \
  $(srcdir)/services/localzone.h $(srcdir)/util/module.h $(srcdir)/util/storage/lruhash.h \
  $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgparse.h \
- $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/sldns/str2wire.h
-daemon.lo daemon.o: $(srcdir)/daemon/daemon.c config.h \
- $(srcdir)/daemon/daemon.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/alloc.h $(srcdir)/services/modstack.h \
-   $(srcdir)/daemon/worker.h \
- $(srcdir)/libunbound/worker.h $(srcdir)/sldns/sbuffer.h $(srcdir)/util/data/packed_rrset.h \
- $(srcdir)/util/storage/lruhash.h $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
- $(srcdir)/dnscrypt/cert.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h \
- $(srcdir)/sldns/rrdef.h $(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h $(srcdir)/libunbound/unbound.h \
- $(srcdir)/util/module.h $(srcdir)/dnstap/dnstap.h $(srcdir)/daemon/remote.h \
- $(srcdir)/daemon/acl_list.h $(srcdir)/util/storage/dnstree.h $(srcdir)/util/rbtree.h $(srcdir)/services/view.h \
- $(srcdir)/util/config_file.h $(srcdir)/util/shm_side/shm_main.h $(srcdir)/util/storage/lookup3.h \
- $(srcdir)/util/storage/slabhash.h $(srcdir)/util/tcp_conn_limit.h $(srcdir)/services/listen_dnsport.h \
- $(srcdir)/services/cache/rrset.h $(srcdir)/services/cache/infra.h $(srcdir)/util/rtt.h \
- $(srcdir)/services/localzone.h $(srcdir)/services/authzone.h $(srcdir)/services/mesh.h $(srcdir)/util/random.h \
- $(srcdir)/util/tube.h $(srcdir)/util/net_help.h $(srcdir)/sldns/keyraw.h $(srcdir)/respip/respip.h
+ $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/sldns/sbuffer.h $(srcdir)/sldns/str2wire.h
+daemon.lo daemon.o: $(srcdir)/daemon/daemon.c config.h $(srcdir)/daemon/daemon.h $(srcdir)/util/locks.h \
+ $(srcdir)/util/log.h $(srcdir)/util/alloc.h $(srcdir)/services/modstack.h  \
+  $(srcdir)/daemon/worker.h $(srcdir)/libunbound/worker.h \
+ $(srcdir)/sldns/sbuffer.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h \
+ $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h $(srcdir)/util/data/msgreply.h \
+ $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/daemon/stats.h \
+ $(srcdir)/util/timehist.h $(srcdir)/libunbound/unbound.h $(srcdir)/util/module.h $(srcdir)/dnstap/dnstap.h \
+ $(srcdir)/daemon/remote.h $(srcdir)/daemon/acl_list.h $(srcdir)/util/storage/dnstree.h $(srcdir)/util/rbtree.h \
+ $(srcdir)/services/view.h $(srcdir)/util/config_file.h $(srcdir)/util/shm_side/shm_main.h \
+ $(srcdir)/util/storage/lookup3.h $(srcdir)/util/storage/slabhash.h $(srcdir)/util/tcp_conn_limit.h \
+ $(srcdir)/services/listen_dnsport.h $(srcdir)/services/cache/rrset.h $(srcdir)/services/cache/infra.h \
+ $(srcdir)/util/rtt.h $(srcdir)/services/localzone.h $(srcdir)/services/authzone.h $(srcdir)/services/mesh.h \
+ $(srcdir)/services/rpz.h $(srcdir)/respip/respip.h $(srcdir)/util/random.h $(srcdir)/util/tube.h $(srcdir)/util/net_help.h \
+ $(srcdir)/sldns/keyraw.h
 stats.lo stats.o: $(srcdir)/daemon/stats.c config.h $(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h \
  $(srcdir)/libunbound/unbound.h $(srcdir)/daemon/worker.h $(srcdir)/libunbound/worker.h $(srcdir)/sldns/sbuffer.h \
  $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \
  $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h  \
- $(srcdir)/dnscrypt/cert.h $(srcdir)/util/alloc.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/msgparse.h \
- $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/module.h $(srcdir)/dnstap/dnstap.h \
-  $(srcdir)/daemon/daemon.h $(srcdir)/services/modstack.h \
- $(srcdir)/services/mesh.h $(srcdir)/util/rbtree.h $(srcdir)/services/outside_network.h \
- $(srcdir)/services/listen_dnsport.h $(srcdir)/util/config_file.h $(srcdir)/util/tube.h $(srcdir)/util/net_help.h \
- $(srcdir)/validator/validator.h $(srcdir)/validator/val_utils.h $(srcdir)/iterator/iterator.h \
- $(srcdir)/services/outbound_list.h $(srcdir)/services/cache/rrset.h $(srcdir)/util/storage/slabhash.h \
- $(srcdir)/services/cache/infra.h $(srcdir)/util/storage/dnstree.h $(srcdir)/util/rtt.h \
- $(srcdir)/services/authzone.h $(srcdir)/validator/val_kcache.h $(srcdir)/validator/val_neg.h \
-
+ $(srcdir)/util/alloc.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h \
+ $(srcdir)/sldns/rrdef.h $(srcdir)/util/module.h $(srcdir)/dnstap/dnstap.h  \
+ $(srcdir)/daemon/daemon.h $(srcdir)/services/modstack.h $(srcdir)/services/mesh.h $(srcdir)/util/rbtree.h \
+ $(srcdir)/services/rpz.h $(srcdir)/services/localzone.h $(srcdir)/util/storage/dnstree.h \
+ $(srcdir)/services/view.h $(srcdir)/util/config_file.h $(srcdir)/services/authzone.h $(srcdir)/respip/respip.h \
+ $(srcdir)/services/outside_network.h $(srcdir)/services/listen_dnsport.h $(srcdir)/util/tube.h \
+ $(srcdir)/util/net_help.h $(srcdir)/validator/validator.h $(srcdir)/validator/val_utils.h \
+ $(srcdir)/iterator/iterator.h $(srcdir)/services/outbound_list.h $(srcdir)/services/cache/rrset.h \
+ $(srcdir)/util/storage/slabhash.h $(srcdir)/services/cache/infra.h $(srcdir)/util/rtt.h \
+ $(srcdir)/validator/val_kcache.h $(srcdir)/validator/val_neg.h
 replay.lo replay.o: $(srcdir)/testcode/replay.c config.h $(srcdir)/util/log.h $(srcdir)/util/net_help.h \
  $(srcdir)/util/config_file.h $(srcdir)/testcode/replay.h $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
-  $(srcdir)/dnscrypt/cert.h $(srcdir)/util/locks.h \
- $(srcdir)/testcode/testpkts.h $(srcdir)/util/rbtree.h $(srcdir)/testcode/fake_event.h $(srcdir)/sldns/str2wire.h \
- $(srcdir)/sldns/rrdef.h
+  $(srcdir)/testcode/testpkts.h $(srcdir)/util/rbtree.h \
+ $(srcdir)/testcode/fake_event.h $(srcdir)/sldns/str2wire.h $(srcdir)/sldns/rrdef.h
 fake_event.lo fake_event.o: $(srcdir)/testcode/fake_event.c config.h $(srcdir)/testcode/fake_event.h \
  $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h  \
- $(srcdir)/dnscrypt/cert.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/net_help.h \
- $(srcdir)/util/data/msgparse.h $(srcdir)/util/storage/lruhash.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h \
- $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgencode.h \
- $(srcdir)/util/data/dname.h $(srcdir)/util/config_file.h $(srcdir)/services/listen_dnsport.h \
- $(srcdir)/services/outside_network.h $(srcdir)/util/rbtree.h  \
- $(srcdir)/services/cache/infra.h $(srcdir)/util/storage/dnstree.h $(srcdir)/util/rtt.h \
- $(srcdir)/testcode/replay.h $(srcdir)/testcode/testpkts.h $(srcdir)/util/fptr_wlist.h $(srcdir)/util/module.h \
- $(srcdir)/util/tube.h $(srcdir)/services/mesh.h $(srcdir)/services/modstack.h $(srcdir)/sldns/sbuffer.h \
- $(srcdir)/sldns/wire2str.h $(srcdir)/sldns/str2wire.h
+ $(srcdir)/util/net_help.h $(srcdir)/util/log.h $(srcdir)/util/data/msgparse.h $(srcdir)/util/storage/lruhash.h \
+ $(srcdir)/util/locks.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/data/msgreply.h \
+ $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgencode.h $(srcdir)/util/data/dname.h \
+ $(srcdir)/util/config_file.h $(srcdir)/services/listen_dnsport.h $(srcdir)/services/outside_network.h \
+ $(srcdir)/util/rbtree.h  $(srcdir)/services/cache/infra.h \
+ $(srcdir)/util/storage/dnstree.h $(srcdir)/util/rtt.h $(srcdir)/testcode/replay.h $(srcdir)/testcode/testpkts.h \
+ $(srcdir)/util/fptr_wlist.h $(srcdir)/util/module.h $(srcdir)/util/tube.h $(srcdir)/services/mesh.h \
+ $(srcdir)/services/modstack.h $(srcdir)/services/rpz.h $(srcdir)/services/localzone.h $(srcdir)/services/view.h \
+ $(srcdir)/sldns/sbuffer.h $(srcdir)/services/authzone.h $(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h \
+ $(srcdir)/libunbound/unbound.h $(srcdir)/respip/respip.h $(srcdir)/sldns/wire2str.h $(srcdir)/sldns/str2wire.h
 lock_verify.lo lock_verify.o: $(srcdir)/testcode/lock_verify.c config.h $(srcdir)/util/log.h $(srcdir)/util/rbtree.h \
  $(srcdir)/util/locks.h $(srcdir)/util/fptr_wlist.h $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
-  $(srcdir)/dnscrypt/cert.h $(srcdir)/util/storage/lruhash.h \
- $(srcdir)/util/module.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h \
- $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/tube.h \
- $(srcdir)/services/mesh.h $(srcdir)/services/modstack.h
+  $(srcdir)/util/storage/lruhash.h $(srcdir)/util/module.h \
+ $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgparse.h \
+ $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/tube.h $(srcdir)/services/mesh.h \
+ $(srcdir)/services/modstack.h $(srcdir)/services/rpz.h $(srcdir)/services/localzone.h \
+ $(srcdir)/util/storage/dnstree.h $(srcdir)/services/view.h $(srcdir)/sldns/sbuffer.h \
+ $(srcdir)/util/config_file.h $(srcdir)/services/authzone.h $(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h \
+ $(srcdir)/libunbound/unbound.h $(srcdir)/respip/respip.h
 pktview.lo pktview.o: $(srcdir)/testcode/pktview.c config.h $(srcdir)/util/log.h $(srcdir)/util/data/dname.h \
  $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h \
  $(srcdir)/sldns/rrdef.h $(srcdir)/testcode/unitmain.h $(srcdir)/testcode/readhex.h $(srcdir)/sldns/sbuffer.h \
@@ -1334,10 +1365,13 @@ readhex.lo readhex.o: $(srcdir)/testcode
  $(srcdir)/sldns/sbuffer.h $(srcdir)/sldns/parseutil.h
 memstats.lo memstats.o: $(srcdir)/testcode/memstats.c config.h $(srcdir)/util/log.h $(srcdir)/util/rbtree.h \
  $(srcdir)/util/locks.h $(srcdir)/util/fptr_wlist.h $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
-  $(srcdir)/dnscrypt/cert.h $(srcdir)/util/storage/lruhash.h \
- $(srcdir)/util/module.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h \
- $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/tube.h \
- $(srcdir)/services/mesh.h $(srcdir)/services/modstack.h
+  $(srcdir)/util/storage/lruhash.h $(srcdir)/util/module.h \
+ $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgparse.h \
+ $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/tube.h $(srcdir)/services/mesh.h \
+ $(srcdir)/services/modstack.h $(srcdir)/services/rpz.h $(srcdir)/services/localzone.h \
+ $(srcdir)/util/storage/dnstree.h $(srcdir)/services/view.h $(srcdir)/sldns/sbuffer.h \
+ $(srcdir)/util/config_file.h $(srcdir)/services/authzone.h $(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h \
+ $(srcdir)/libunbound/unbound.h $(srcdir)/respip/respip.h
 unbound-checkconf.lo unbound-checkconf.o: $(srcdir)/smallapp/unbound-checkconf.c config.h $(srcdir)/util/log.h \
  $(srcdir)/util/config_file.h $(srcdir)/util/module.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h \
  $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgparse.h \
@@ -1345,27 +1379,31 @@ unbound-checkconf.lo unbound-checkconf.o
  $(srcdir)/iterator/iterator.h $(srcdir)/services/outbound_list.h $(srcdir)/iterator/iter_fwd.h \
  $(srcdir)/util/rbtree.h $(srcdir)/iterator/iter_hints.h $(srcdir)/util/storage/dnstree.h \
  $(srcdir)/validator/validator.h $(srcdir)/validator/val_utils.h $(srcdir)/services/localzone.h \
- $(srcdir)/services/view.h $(srcdir)/services/authzone.h $(srcdir)/services/mesh.h $(srcdir)/util/netevent.h \
- $(srcdir)/dnscrypt/dnscrypt.h  $(srcdir)/dnscrypt/cert.h \
- $(srcdir)/services/modstack.h $(srcdir)/respip/respip.h $(srcdir)/sldns/sbuffer.h
+ $(srcdir)/services/view.h $(srcdir)/sldns/sbuffer.h $(srcdir)/services/authzone.h $(srcdir)/services/mesh.h \
+ $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h  \
+ $(srcdir)/services/modstack.h $(srcdir)/services/rpz.h $(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h \
+ $(srcdir)/libunbound/unbound.h $(srcdir)/respip/respip.h
 worker_cb.lo worker_cb.o: $(srcdir)/smallapp/worker_cb.c config.h $(srcdir)/libunbound/context.h \
  $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/alloc.h $(srcdir)/util/rbtree.h $(srcdir)/services/modstack.h \
  $(srcdir)/libunbound/unbound.h $(srcdir)/libunbound/unbound-event.h $(srcdir)/util/data/packed_rrset.h \
  $(srcdir)/util/storage/lruhash.h $(srcdir)/libunbound/worker.h $(srcdir)/sldns/sbuffer.h \
  $(srcdir)/util/fptr_wlist.h $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
-  $(srcdir)/dnscrypt/cert.h $(srcdir)/util/module.h \
- $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h \
- $(srcdir)/util/tube.h $(srcdir)/services/mesh.h
+  $(srcdir)/util/module.h $(srcdir)/util/data/msgreply.h \
+ $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/tube.h \
+ $(srcdir)/services/mesh.h $(srcdir)/services/rpz.h $(srcdir)/services/localzone.h \
+ $(srcdir)/util/storage/dnstree.h $(srcdir)/services/view.h $(srcdir)/util/config_file.h \
+ $(srcdir)/services/authzone.h $(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h $(srcdir)/respip/respip.h
 context.lo context.o: $(srcdir)/libunbound/context.c config.h $(srcdir)/libunbound/context.h \
  $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/alloc.h $(srcdir)/util/rbtree.h $(srcdir)/services/modstack.h \
  $(srcdir)/libunbound/unbound.h $(srcdir)/libunbound/unbound-event.h $(srcdir)/util/data/packed_rrset.h \
  $(srcdir)/util/storage/lruhash.h $(srcdir)/util/module.h $(srcdir)/util/data/msgreply.h \
  $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/config_file.h \
  $(srcdir)/util/net_help.h $(srcdir)/services/localzone.h $(srcdir)/util/storage/dnstree.h \
- $(srcdir)/services/view.h $(srcdir)/services/cache/rrset.h $(srcdir)/util/storage/slabhash.h \
- $(srcdir)/services/cache/infra.h $(srcdir)/util/rtt.h $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
-  $(srcdir)/dnscrypt/cert.h $(srcdir)/services/authzone.h \
- $(srcdir)/services/mesh.h $(srcdir)/sldns/sbuffer.h
+ $(srcdir)/services/view.h $(srcdir)/sldns/sbuffer.h $(srcdir)/services/cache/rrset.h \
+ $(srcdir)/util/storage/slabhash.h $(srcdir)/services/cache/infra.h $(srcdir)/util/rtt.h \
+ $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h  \
+ $(srcdir)/services/authzone.h $(srcdir)/services/mesh.h $(srcdir)/services/rpz.h $(srcdir)/daemon/stats.h \
+ $(srcdir)/util/timehist.h $(srcdir)/respip/respip.h
 libunbound.lo libunbound.o: $(srcdir)/libunbound/libunbound.c $(srcdir)/libunbound/unbound.h \
  $(srcdir)/libunbound/unbound-event.h config.h $(srcdir)/libunbound/context.h $(srcdir)/util/locks.h \
  $(srcdir)/util/log.h $(srcdir)/util/alloc.h $(srcdir)/util/rbtree.h $(srcdir)/services/modstack.h \
@@ -1374,70 +1412,70 @@ libunbound.lo libunbound.o: $(srcdir)/li
  $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/regional.h \
  $(srcdir)/util/random.h $(srcdir)/util/net_help.h $(srcdir)/util/tube.h $(srcdir)/util/ub_event.h \
  $(srcdir)/services/localzone.h $(srcdir)/util/storage/dnstree.h $(srcdir)/services/view.h \
- $(srcdir)/services/cache/infra.h $(srcdir)/util/rtt.h $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
-  $(srcdir)/dnscrypt/cert.h $(srcdir)/services/cache/rrset.h \
+ $(srcdir)/sldns/sbuffer.h $(srcdir)/services/cache/infra.h $(srcdir)/util/rtt.h $(srcdir)/util/netevent.h \
+ $(srcdir)/dnscrypt/dnscrypt.h  $(srcdir)/services/cache/rrset.h \
  $(srcdir)/util/storage/slabhash.h $(srcdir)/services/authzone.h $(srcdir)/services/mesh.h \
- $(srcdir)/sldns/sbuffer.h
-libworker.lo libworker.o: $(srcdir)/libunbound/libworker.c config.h \
- $(srcdir)/libunbound/libworker.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h \
- $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/libunbound/context.h $(srcdir)/util/alloc.h $(srcdir)/util/rbtree.h \
- $(srcdir)/services/modstack.h $(srcdir)/libunbound/unbound.h $(srcdir)/libunbound/unbound-event.h \
- $(srcdir)/libunbound/worker.h $(srcdir)/sldns/sbuffer.h $(srcdir)/services/outside_network.h \
- $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h  \
- $(srcdir)/dnscrypt/cert.h  $(srcdir)/services/mesh.h \
- $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/module.h \
- $(srcdir)/util/data/msgreply.h $(srcdir)/services/localzone.h $(srcdir)/util/storage/dnstree.h \
- $(srcdir)/services/view.h $(srcdir)/services/cache/rrset.h $(srcdir)/util/storage/slabhash.h \
- $(srcdir)/services/outbound_list.h $(srcdir)/services/authzone.h $(srcdir)/util/fptr_wlist.h \
- $(srcdir)/util/tube.h $(srcdir)/util/regional.h $(srcdir)/util/random.h $(srcdir)/util/config_file.h \
+ $(srcdir)/services/rpz.h $(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h $(srcdir)/respip/respip.h
+libworker.lo libworker.o: $(srcdir)/libunbound/libworker.c config.h $(srcdir)/libunbound/libworker.h \
+ $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \
+ $(srcdir)/libunbound/context.h $(srcdir)/util/alloc.h $(srcdir)/util/rbtree.h $(srcdir)/services/modstack.h \
+ $(srcdir)/libunbound/unbound.h $(srcdir)/libunbound/unbound-event.h $(srcdir)/libunbound/worker.h \
+ $(srcdir)/sldns/sbuffer.h $(srcdir)/services/outside_network.h $(srcdir)/util/netevent.h \
+ $(srcdir)/dnscrypt/dnscrypt.h   \
+ $(srcdir)/services/mesh.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h \
+ $(srcdir)/util/module.h $(srcdir)/util/data/msgreply.h $(srcdir)/services/rpz.h $(srcdir)/services/localzone.h \
+ $(srcdir)/util/storage/dnstree.h $(srcdir)/services/view.h $(srcdir)/util/config_file.h \
+ $(srcdir)/services/authzone.h $(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h $(srcdir)/respip/respip.h \
+ $(srcdir)/services/cache/rrset.h $(srcdir)/util/storage/slabhash.h $(srcdir)/services/outbound_list.h \
+ $(srcdir)/util/fptr_wlist.h $(srcdir)/util/tube.h $(srcdir)/util/regional.h $(srcdir)/util/random.h \
  $(srcdir)/util/storage/lookup3.h $(srcdir)/util/net_help.h $(srcdir)/util/data/dname.h \
  $(srcdir)/util/data/msgencode.h $(srcdir)/iterator/iter_fwd.h $(srcdir)/iterator/iter_hints.h \
  $(srcdir)/sldns/str2wire.h
 unbound-host.lo unbound-host.o: $(srcdir)/smallapp/unbound-host.c config.h $(srcdir)/libunbound/unbound.h \
- $(srcdir)/sldns/rrdef.h $(srcdir)/sldns/wire2str.h \
-
+ $(srcdir)/sldns/rrdef.h $(srcdir)/sldns/wire2str.h
 asynclook.lo asynclook.o: $(srcdir)/testcode/asynclook.c config.h $(srcdir)/libunbound/unbound.h \
  $(srcdir)/libunbound/context.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/alloc.h $(srcdir)/util/rbtree.h \
  $(srcdir)/services/modstack.h $(srcdir)/libunbound/unbound-event.h $(srcdir)/util/data/packed_rrset.h \
- $(srcdir)/util/storage/lruhash.h $(srcdir)/sldns/rrdef.h \
-
+ $(srcdir)/util/storage/lruhash.h $(srcdir)/sldns/rrdef.h
 streamtcp.lo streamtcp.o: $(srcdir)/testcode/streamtcp.c config.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \
  $(srcdir)/util/net_help.h $(srcdir)/util/data/msgencode.h $(srcdir)/util/data/msgparse.h \
  $(srcdir)/util/storage/lruhash.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/data/msgreply.h \
  $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/dname.h $(srcdir)/sldns/sbuffer.h \
- $(srcdir)/sldns/str2wire.h $(srcdir)/sldns/wire2str.h \
-
+ $(srcdir)/sldns/str2wire.h $(srcdir)/sldns/wire2str.h
 perf.lo perf.o: $(srcdir)/testcode/perf.c config.h $(srcdir)/util/log.h $(srcdir)/util/locks.h $(srcdir)/util/net_help.h \
  $(srcdir)/util/data/msgencode.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/storage/lruhash.h \
  $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h \
  $(srcdir)/sldns/rrdef.h $(srcdir)/sldns/sbuffer.h $(srcdir)/sldns/wire2str.h $(srcdir)/sldns/str2wire.h
 delayer.lo delayer.o: $(srcdir)/testcode/delayer.c config.h $(srcdir)/util/net_help.h $(srcdir)/util/log.h \
  $(srcdir)/util/config_file.h $(srcdir)/sldns/sbuffer.h
-unbound-control.lo unbound-control.o: $(srcdir)/smallapp/unbound-control.c config.h \
- $(srcdir)/util/log.h $(srcdir)/util/config_file.h $(srcdir)/util/locks.h $(srcdir)/util/net_help.h \
- $(srcdir)/util/shm_side/shm_main.h $(srcdir)/libunbound/unbound.h $(srcdir)/daemon/stats.h \
- $(srcdir)/util/timehist.h $(srcdir)/sldns/wire2str.h $(srcdir)/sldns/pkthdr.h
+unbound-control.lo unbound-control.o: $(srcdir)/smallapp/unbound-control.c config.h $(srcdir)/util/log.h \
+ $(srcdir)/util/config_file.h $(srcdir)/util/locks.h $(srcdir)/util/net_help.h $(srcdir)/util/shm_side/shm_main.h \
+ $(srcdir)/libunbound/unbound.h $(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h $(srcdir)/sldns/wire2str.h \
+ $(srcdir)/sldns/pkthdr.h $(srcdir)/services/rpz.h $(srcdir)/services/localzone.h $(srcdir)/util/rbtree.h \
+ $(srcdir)/util/storage/dnstree.h $(srcdir)/util/module.h $(srcdir)/util/storage/lruhash.h \
+ $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgparse.h \
+ $(srcdir)/sldns/rrdef.h $(srcdir)/services/view.h $(srcdir)/sldns/sbuffer.h $(srcdir)/services/authzone.h \
+ $(srcdir)/services/mesh.h $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
+  $(srcdir)/services/modstack.h $(srcdir)/respip/respip.h
 unbound-anchor.lo unbound-anchor.o: $(srcdir)/smallapp/unbound-anchor.c config.h $(srcdir)/libunbound/unbound.h \
- $(srcdir)/sldns/rrdef.h $(srcdir)/sldns/parseutil.h \
-
-petal.lo petal.o: $(srcdir)/testcode/petal.c config.h \
-
+ $(srcdir)/sldns/rrdef.h $(srcdir)/sldns/parseutil.h
+petal.lo petal.o: $(srcdir)/testcode/petal.c config.h
 pythonmod_utils.lo pythonmod_utils.o: $(srcdir)/pythonmod/pythonmod_utils.c config.h $(srcdir)/util/module.h \
  $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/data/msgreply.h \
  $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h \
  $(srcdir)/sldns/rrdef.h $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
-  $(srcdir)/dnscrypt/cert.h $(srcdir)/util/net_help.h \
- $(srcdir)/services/cache/dns.h $(srcdir)/services/cache/rrset.h $(srcdir)/util/storage/slabhash.h \
- $(srcdir)/util/regional.h $(srcdir)/iterator/iter_delegpt.h $(srcdir)/sldns/sbuffer.h
+  $(srcdir)/util/net_help.h $(srcdir)/services/cache/dns.h \
+ $(srcdir)/services/cache/rrset.h $(srcdir)/util/storage/slabhash.h $(srcdir)/util/regional.h \
+ $(srcdir)/iterator/iter_delegpt.h $(srcdir)/sldns/sbuffer.h
 win_svc.lo win_svc.o: $(srcdir)/winrc/win_svc.c config.h $(srcdir)/winrc/win_svc.h $(srcdir)/winrc/w_inst.h \
  $(srcdir)/daemon/daemon.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/alloc.h $(srcdir)/services/modstack.h \
    $(srcdir)/daemon/worker.h \
  $(srcdir)/libunbound/worker.h $(srcdir)/sldns/sbuffer.h $(srcdir)/util/data/packed_rrset.h \
  $(srcdir)/util/storage/lruhash.h $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
- $(srcdir)/dnscrypt/cert.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h \
- $(srcdir)/sldns/rrdef.h $(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h $(srcdir)/libunbound/unbound.h \
- $(srcdir)/util/module.h $(srcdir)/dnstap/dnstap.h $(srcdir)/daemon/remote.h \
- $(srcdir)/util/config_file.h $(srcdir)/util/ub_event.h $(srcdir)/util/net_help.h
+ $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h \
+ $(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h $(srcdir)/libunbound/unbound.h $(srcdir)/util/module.h \
+ $(srcdir)/dnstap/dnstap.h $(srcdir)/daemon/remote.h $(srcdir)/util/config_file.h $(srcdir)/util/ub_event.h \
+ $(srcdir)/util/net_help.h
 w_inst.lo w_inst.o: $(srcdir)/winrc/w_inst.c config.h $(srcdir)/winrc/w_inst.h $(srcdir)/winrc/win_svc.h
 unbound-service-install.lo unbound-service-install.o: $(srcdir)/winrc/unbound-service-install.c config.h \
  $(srcdir)/winrc/w_inst.h
@@ -1445,14 +1483,12 @@ unbound-service-remove.lo unbound-servic
  $(srcdir)/winrc/w_inst.h
 anchor-update.lo anchor-update.o: $(srcdir)/winrc/anchor-update.c config.h $(srcdir)/libunbound/unbound.h \
  $(srcdir)/sldns/rrdef.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/wire2str.h
-keyraw.lo keyraw.o: $(srcdir)/sldns/keyraw.c config.h $(srcdir)/sldns/keyraw.h \
- $(srcdir)/sldns/rrdef.h \
-
+keyraw.lo keyraw.o: $(srcdir)/sldns/keyraw.c config.h $(srcdir)/sldns/keyraw.h $(srcdir)/sldns/rrdef.h
 sbuffer.lo sbuffer.o: $(srcdir)/sldns/sbuffer.c config.h $(srcdir)/sldns/sbuffer.h
 wire2str.lo wire2str.o: $(srcdir)/sldns/wire2str.c config.h $(srcdir)/sldns/wire2str.h $(srcdir)/sldns/str2wire.h \
  $(srcdir)/sldns/rrdef.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/parseutil.h $(srcdir)/sldns/sbuffer.h \
- $(srcdir)/sldns/keyraw.h \
- $(srcdir)/util/data/dname.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h
+ $(srcdir)/sldns/keyraw.h $(srcdir)/util/data/dname.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h \
+ $(srcdir)/util/log.h
 parse.lo parse.o: $(srcdir)/sldns/parse.c config.h $(srcdir)/sldns/parse.h $(srcdir)/sldns/parseutil.h \
  $(srcdir)/sldns/sbuffer.h
 parseutil.lo parseutil.o: $(srcdir)/sldns/parseutil.c config.h $(srcdir)/sldns/parseutil.h
@@ -1473,11 +1509,9 @@ strlcat.lo strlcat.o: $(srcdir)/compat/s
 strlcpy.lo strlcpy.o: $(srcdir)/compat/strlcpy.c config.h
 strptime.lo strptime.o: $(srcdir)/compat/strptime.c config.h
 getentropy_freebsd.lo getentropy_freebsd.o: $(srcdir)/compat/getentropy_freebsd.c
-getentropy_linux.lo getentropy_linux.o: $(srcdir)/compat/getentropy_linux.c config.h \
-
+getentropy_linux.lo getentropy_linux.o: $(srcdir)/compat/getentropy_linux.c config.h
 getentropy_osx.lo getentropy_osx.o: $(srcdir)/compat/getentropy_osx.c
-getentropy_solaris.lo getentropy_solaris.o: $(srcdir)/compat/getentropy_solaris.c config.h \
-
+getentropy_solaris.lo getentropy_solaris.o: $(srcdir)/compat/getentropy_solaris.c config.h
 getentropy_win.lo getentropy_win.o: $(srcdir)/compat/getentropy_win.c
 explicit_bzero.lo explicit_bzero.o: $(srcdir)/compat/explicit_bzero.c config.h
 arc4random.lo arc4random.o: $(srcdir)/compat/arc4random.c config.h $(srcdir)/compat/chacha_private.h
Index: README
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/README,v
retrieving revision 1.4
diff -u -p -r1.4 README
--- README 4 Oct 2019 20:55:28 -0000 1.4
+++ README 15 Mar 2020 16:31:04 -0000
@@ -1,4 +1,4 @@
-README for Unbound 1.9.4
+Unbound README
 * ./configure && make && make install
 * You can use libevent if you want. libevent is useful when using
   many (10000) outgoing ports. By default max 256 ports are opened at
Index: README.md
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/README.md,v
retrieving revision 1.3
diff -u -p -r1.3 README.md
--- README.md 18 Dec 2019 11:04:13 -0000 1.3
+++ README.md 15 Mar 2020 16:31:04 -0000
@@ -8,7 +8,7 @@ Unbound is a validating, recursive, cach
 fast and lean and incorporates modern features based on open standards. If you
 have any feedback, we would love to hear from you. Don’t hesitate to
 [create an issue on Github](https://github.com/NLnetLabs/unbound/issues/new)
-or post a message on the [Unbound mailing list](https://nlnetlabs.nl/mailman/listinfo/unbound-users).
+or post a message on the [Unbound mailing list](https://lists.nlnetlabs.nl/mailman/listinfo/unbound-users).
 You can lean more about Unbound by reading our
 [documentation](https://nlnetlabs.nl/documentation/unbound/).
 
Index: aclocal.m4
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/aclocal.m4,v
retrieving revision 1.7
diff -u -p -r1.7 aclocal.m4
--- aclocal.m4 18 Dec 2019 11:04:13 -0000 1.7
+++ aclocal.m4 15 Mar 2020 16:31:04 -0000
@@ -1,6 +1,6 @@
-# generated automatically by aclocal 1.15.1 -*- Autoconf -*-
+# generated automatically by aclocal 1.16.1 -*- Autoconf -*-
 
-# Copyright (C) 1996-2017 Free Software Foundation, Inc.
+# Copyright (C) 1996-2018 Free Software Foundation, Inc.
 
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
@@ -736,6 +736,7 @@ _LT_CONFIG_SAVE_COMMANDS([
     cat <<_LT_EOF >> "$cfgfile"
 #! $SHELL
 # Generated automatically by $as_me ($PACKAGE) $VERSION
+# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
 # NOTE: Changes made to this file will be lost: look at ltmain.sh.
 
 # Provide generalized library-building support services.
@@ -2872,6 +2873,9 @@ linux* | k*bsd*-gnu | kopensolaris*-gnu
   # before this can be enabled.
   hardcode_into_libs=yes
 
+  # Add ABI-specific directories to the system library path.
+  sys_lib_dlsearch_path_spec="/lib64 /usr/lib64 /lib /usr/lib"
+
   # Ideally, we could use ldconfig to report *all* directores which are
   # searched for libraries, however this is still not possible.  Aside from not
   # being certain /sbin/ldconfig is available, command
@@ -2880,7 +2884,7 @@ linux* | k*bsd*-gnu | kopensolaris*-gnu
   # appending ld.so.conf contents (and includes) to the search path.
   if test -f /etc/ld.so.conf; then
     lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \[$]2)); skip = 1; } { if (!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '`
-    sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra"
+    sys_lib_dlsearch_path_spec="$sys_lib_dlsearch_path_spec $lt_ld_extra"
   fi
 
   # We used to test for /lib/ld.so.1 and disable shared libraries on
@@ -2892,18 +2896,6 @@ linux* | k*bsd*-gnu | kopensolaris*-gnu
   dynamic_linker='GNU/Linux ld.so'
   ;;
 
-netbsdelf*-gnu)
-  version_type=linux
-  need_lib_prefix=no
-  need_version=no
-  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
-  soname_spec='${libname}${release}${shared_ext}$major'
-  shlibpath_var=LD_LIBRARY_PATH
-  shlibpath_overrides_runpath=no
-  hardcode_into_libs=yes
-  dynamic_linker='NetBSD ld.elf_so'
-  ;;
-
 netbsd*)
   version_type=sunos
   need_lib_prefix=no
@@ -3563,7 +3555,7 @@ linux* | k*bsd*-gnu | kopensolaris*-gnu
   lt_cv_deplibs_check_method=pass_all
   ;;
 
-netbsd* | netbsdelf*-gnu)
+netbsd*)
   if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then
     lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$'
   else
@@ -4441,7 +4433,7 @@ m4_if([$1], [CXX], [
     ;;
  esac
  ;;
-      netbsd* | netbsdelf*-gnu)
+      netbsd*)
  ;;
       *qnx* | *nto*)
         # QNX uses GNU C++, but need to define -shared option too, otherwise
@@ -4953,9 +4945,6 @@ m4_if([$1], [CXX], [
       ;;
     esac
     ;;
-  linux* | k*bsd*-gnu | gnu*)
-    _LT_TAGVAR(link_all_deplibs, $1)=no
-    ;;
   *)
     _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
     ;;
@@ -5018,9 +5007,6 @@ dnl Note also adjust exclude_expsyms for
   openbsd* | bitrig*)
     with_gnu_ld=no
     ;;
-  linux* | k*bsd*-gnu | gnu*)
-    _LT_TAGVAR(link_all_deplibs, $1)=no
-    ;;
   esac
 
   _LT_TAGVAR(ld_shlibs, $1)=yes
@@ -5275,7 +5261,7 @@ _LT_EOF
       fi
       ;;
 
-    netbsd* | netbsdelf*-gnu)
+    netbsd*)
       if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
  _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib'
  wlarc=
@@ -5796,7 +5782,6 @@ _LT_EOF
  if test yes = "$lt_cv_irix_exported_symbol"; then
           _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations $wl-exports_file $wl$export_symbols -o $lib'
  fi
- _LT_TAGVAR(link_all_deplibs, $1)=no
       else
  _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib'
  _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -exports_file $export_symbols -o $lib'
@@ -5818,7 +5803,7 @@ _LT_EOF
       esac
       ;;
 
-    netbsd* | netbsdelf*-gnu)
+    netbsd*)
       if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
  _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'  # a.out
       else
@@ -9059,9 +9044,9 @@ m4_ifndef([_LT_PROG_F77], [AC_DEFUN([_L
 m4_ifndef([_LT_PROG_FC], [AC_DEFUN([_LT_PROG_FC])])
 m4_ifndef([_LT_PROG_CXX], [AC_DEFUN([_LT_PROG_CXX])])
 
-dnl pkg.m4 - Macros to locate and utilise pkg-config.   -*- Autoconf -*-
-dnl serial 11 (pkg-config-0.29.1)
-dnl
+# pkg.m4 - Macros to locate and utilise pkg-config.   -*- Autoconf -*-
+# serial 11 (pkg-config-0.29.1)
+
 dnl Copyright © 2004 Scott James Remnant <[hidden email]>.
 dnl Copyright © 2012-2015 Dan Nicholson <[hidden email]>
 dnl
@@ -9335,9 +9320,77 @@ AS_VAR_COPY([$1], [pkg_cv_][$1])
 AS_VAR_IF([$1], [""], [$5], [$4])dnl
 ])dnl PKG_CHECK_VAR
 
+dnl PKG_WITH_MODULES(VARIABLE-PREFIX, MODULES,
+dnl   [ACTION-IF-FOUND],[ACTION-IF-NOT-FOUND],
+dnl   [DESCRIPTION], [DEFAULT])
+dnl ------------------------------------------
+dnl
+dnl Prepare a "--with-" configure option using the lowercase
+dnl [VARIABLE-PREFIX] name, merging the behaviour of AC_ARG_WITH and
+dnl PKG_CHECK_MODULES in a single macro.
+AC_DEFUN([PKG_WITH_MODULES],
+[
+m4_pushdef([with_arg], m4_tolower([$1]))
+
+m4_pushdef([description],
+           [m4_default([$5], [build with ]with_arg[ support])])
+
+m4_pushdef([def_arg], [m4_default([$6], [auto])])
+m4_pushdef([def_action_if_found], [AS_TR_SH([with_]with_arg)=yes])
+m4_pushdef([def_action_if_not_found], [AS_TR_SH([with_]with_arg)=no])
+
+m4_case(def_arg,
+            [yes],[m4_pushdef([with_without], [--without-]with_arg)],
+            [m4_pushdef([with_without],[--with-]with_arg)])
+
+AC_ARG_WITH(with_arg,
+     AS_HELP_STRING(with_without, description[ @<:@default=]def_arg[@:>@]),,
+    [AS_TR_SH([with_]with_arg)=def_arg])
+
+AS_CASE([$AS_TR_SH([with_]with_arg)],
+            [yes],[PKG_CHECK_MODULES([$1],[$2],$3,$4)],
+            [auto],[PKG_CHECK_MODULES([$1],[$2],
+                                        [m4_n([def_action_if_found]) $3],
+                                        [m4_n([def_action_if_not_found]) $4])])
+
+m4_popdef([with_arg])
+m4_popdef([description])
+m4_popdef([def_arg])
+
+])dnl PKG_WITH_MODULES
+
+dnl PKG_HAVE_WITH_MODULES(VARIABLE-PREFIX, MODULES,
+dnl   [DESCRIPTION], [DEFAULT])
+dnl -----------------------------------------------
+dnl
+dnl Convenience macro to trigger AM_CONDITIONAL after PKG_WITH_MODULES
+dnl check._[VARIABLE-PREFIX] is exported as make variable.
+AC_DEFUN([PKG_HAVE_WITH_MODULES],
+[
+PKG_WITH_MODULES([$1],[$2],,,[$3],[$4])
+
+AM_CONDITIONAL([HAVE_][$1],
+               [test "$AS_TR_SH([with_]m4_tolower([$1]))" = "yes"])
+])dnl PKG_HAVE_WITH_MODULES
+
+dnl PKG_HAVE_DEFINE_WITH_MODULES(VARIABLE-PREFIX, MODULES,
+dnl   [DESCRIPTION], [DEFAULT])
+dnl ------------------------------------------------------
+dnl
+dnl Convenience macro to run AM_CONDITIONAL and AC_DEFINE after
+dnl PKG_WITH_MODULES check. HAVE_[VARIABLE-PREFIX] is exported as make
+dnl and preprocessor variable.
+AC_DEFUN([PKG_HAVE_DEFINE_WITH_MODULES],
+[
+PKG_HAVE_WITH_MODULES([$1],[$2],[$3],[$4])
+
+AS_IF([test "$AS_TR_SH([with_]m4_tolower([$1]))" = "yes"],
+        [AC_DEFINE([HAVE_][$1], 1, [Enable ]m4_tolower([$1])[ support])])
+])dnl PKG_HAVE_DEFINE_WITH_MODULES
+
 # AM_CONDITIONAL                                            -*- Autoconf -*-
 
-# Copyright (C) 1997-2017 Free Software Foundation, Inc.
+# Copyright (C) 1997-2018 Free Software Foundation, Inc.
 #
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
@@ -9368,7 +9421,7 @@ AC_CONFIG_COMMANDS_PRE(
 Usually this means the macro was only invoked conditionally.]])
 fi])])
 
-# Copyright (C) 2006-2017 Free Software Foundation, Inc.
+# Copyright (C) 2006-2018 Free Software Foundation, Inc.
 #
 # This file is free software; the Free Software Foundation
 # gives unlimited permission to copy and/or distribute it,
Index: config.guess
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/config.guess,v
retrieving revision 1.4
diff -u -p -r1.4 config.guess
--- config.guess 18 Dec 2019 11:04:13 -0000 1.4
+++ config.guess 15 Mar 2020 16:31:04 -0000
@@ -1,8 +1,8 @@
-#! /bin/sh
+#!/usr/bin/sh
 # Attempt to guess a canonical system name.
-#   Copyright 1992-2018 Free Software Foundation, Inc.
+#   Copyright 1992-2016 Free Software Foundation, Inc.
 
-timestamp='2018-02-24'
+timestamp='2016-10-02'
 
 # This file is free software; you can redistribute it and/or modify it
 # under the terms of the GNU General Public License as published by
@@ -15,7 +15,7 @@ timestamp='2018-02-24'
 # General Public License for more details.
 #
 # You should have received a copy of the GNU General Public License
-# along with this program; if not, see <https://www.gnu.org/licenses/>.
+# along with this program; if not, see <http://www.gnu.org/licenses/>.
 #
 # As a special exception to the GNU General Public License, if you
 # distribute this file as part of a program that contains a
@@ -27,7 +27,7 @@ timestamp='2018-02-24'
 # Originally written by Per Bothner; maintained since 2000 by Ben Elliston.
 #
 # You can get the latest version of this script from:
-# https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess
+# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess
 #
 # Please send patches to <[hidden email]>.
 
@@ -39,7 +39,7 @@ Usage: $0 [OPTION]
 
 Output the configuration name of the system \`$me' is run on.
 
-Options:
+Operation modes:
   -h, --help         print this help, then exit
   -t, --time-stamp   print date of last modification, then exit
   -v, --version      print version number, then exit
@@ -50,7 +50,7 @@ version="\
 GNU config.guess ($timestamp)
 
 Originally written by Per Bothner.
-Copyright 1992-2018 Free Software Foundation, Inc.
+Copyright 1992-2016 Free Software Foundation, Inc.
 
 This is free software; see the source for copying conditions.  There is NO
 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
@@ -107,9 +107,9 @@ trap "rm -f \$tmpfiles 2>/dev/null; rmdi
 dummy=$tmp/dummy ;
 tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ;
 case $CC_FOR_BUILD,$HOST_CC,$CC in
- ,,)    echo "int x;" > "$dummy.c" ;
+ ,,)    echo "int x;" > $dummy.c ;
  for c in cc gcc c89 c99 ; do
-  if ($c -c -o "$dummy.o" "$dummy.c") >/dev/null 2>&1 ; then
+  if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then
      CC_FOR_BUILD="$c"; break ;
   fi ;
  done ;
@@ -132,14 +132,14 @@ UNAME_RELEASE=`(uname -r) 2>/dev/null` |
 UNAME_SYSTEM=`(uname -s) 2>/dev/null`  || UNAME_SYSTEM=unknown
 UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
 
-case "$UNAME_SYSTEM" in
+case "${UNAME_SYSTEM}" in
 Linux|GNU|GNU/*)
  # If the system lacks a compiler, then just pick glibc.
  # We could probably try harder.
  LIBC=gnu
 
- eval "$set_cc_for_build"
- cat <<-EOF > "$dummy.c"
+ eval $set_cc_for_build
+ cat <<-EOF > $dummy.c
  #include <features.h>
  #if defined(__UCLIBC__)
  LIBC=uclibc
@@ -149,20 +149,13 @@ Linux|GNU|GNU/*)
  LIBC=gnu
  #endif
  EOF
- eval "`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^LIBC' | sed 's, ,,g'`"
-
- # If ldd exists, use it to detect musl libc.
- if command -v ldd >/dev/null && \
- ldd --version 2>&1 | grep -q ^musl
- then
-    LIBC=musl
- fi
+ eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC' | sed 's, ,,g'`
  ;;
 esac
 
 # Note: order is significant - the case branches are not exclusive.
 
-case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in
+case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
     *:NetBSD:*:*)
  # NetBSD (nbsd) targets should (where applicable) match one or
  # more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*,
@@ -176,30 +169,30 @@ case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAM
  # portion of the name.  We always set it to "unknown".
  sysctl="sysctl -n hw.machine_arch"
  UNAME_MACHINE_ARCH=`(uname -p 2>/dev/null || \
-    "/sbin/$sysctl" 2>/dev/null || \
-    "/usr/sbin/$sysctl" 2>/dev/null || \
+    /sbin/$sysctl 2>/dev/null || \
+    /usr/sbin/$sysctl 2>/dev/null || \
     echo unknown)`
- case "$UNAME_MACHINE_ARCH" in
+ case "${UNAME_MACHINE_ARCH}" in
     armeb) machine=armeb-unknown ;;
     arm*) machine=arm-unknown ;;
     sh3el) machine=shl-unknown ;;
     sh3eb) machine=sh-unknown ;;
     sh5el) machine=sh5le-unknown ;;
     earmv*)
- arch=`echo "$UNAME_MACHINE_ARCH" | sed -e 's,^e\(armv[0-9]\).*$,\1,'`
- endian=`echo "$UNAME_MACHINE_ARCH" | sed -ne 's,^.*\(eb\)$,\1,p'`
- machine="${arch}${endian}"-unknown
+ arch=`echo ${UNAME_MACHINE_ARCH} | sed -e 's,^e\(armv[0-9]\).*$,\1,'`
+ endian=`echo ${UNAME_MACHINE_ARCH} | sed -ne 's,^.*\(eb\)$,\1,p'`
+ machine=${arch}${endian}-unknown
  ;;
-    *) machine="$UNAME_MACHINE_ARCH"-unknown ;;
+    *) machine=${UNAME_MACHINE_ARCH}-unknown ;;
  esac
  # The Operating System including object format, if it has switched
  # to ELF recently (or will in the future) and ABI.
- case "$UNAME_MACHINE_ARCH" in
+ case "${UNAME_MACHINE_ARCH}" in
     earm*)
  os=netbsdelf
  ;;
     arm*|i386|m68k|ns32k|sh3*|sparc|vax)
- eval "$set_cc_for_build"
+ eval $set_cc_for_build
  if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
  | grep -q __ELF__
  then
@@ -215,10 +208,10 @@ case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAM
  ;;
  esac
  # Determine ABI tags.
- case "$UNAME_MACHINE_ARCH" in
+ case "${UNAME_MACHINE_ARCH}" in
     earm*)
  expr='s/^earmv[0-9]/-eabi/;s/eb$//'
- abi=`echo "$UNAME_MACHINE_ARCH" | sed -e "$expr"`
+ abi=`echo ${UNAME_MACHINE_ARCH} | sed -e "$expr"`
  ;;
  esac
  # The OS release
@@ -226,55 +219,46 @@ case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAM
  # thus, need a distinct triplet. However, they do not need
  # kernel version information, so it can be replaced with a
  # suitable tag, in the style of linux-gnu.
- case "$UNAME_VERSION" in
+ case "${UNAME_VERSION}" in
     Debian*)
  release='-gnu'
  ;;
     *)
- release=`echo "$UNAME_RELEASE" | sed -e 's/[-_].*//' | cut -d. -f1,2`
+ release=`echo ${UNAME_RELEASE} | sed -e 's/[-_].*//' | cut -d. -f1,2`
  ;;
  esac
  # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
  # contains redundant information, the shorter form:
  # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
- echo "$machine-${os}${release}${abi}"
+ echo "${machine}-${os}${release}${abi}"
  exit ;;
     *:Bitrig:*:*)
  UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'`
- echo "$UNAME_MACHINE_ARCH"-unknown-bitrig"$UNAME_RELEASE"
+ echo ${UNAME_MACHINE_ARCH}-unknown-bitrig${UNAME_RELEASE}
  exit ;;
     *:OpenBSD:*:*)
  UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'`
- echo "$UNAME_MACHINE_ARCH"-unknown-openbsd"$UNAME_RELEASE"
+ echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE}
  exit ;;
     *:LibertyBSD:*:*)
  UNAME_MACHINE_ARCH=`arch | sed 's/^.*BSD\.//'`
- echo "$UNAME_MACHINE_ARCH"-unknown-libertybsd"$UNAME_RELEASE"
- exit ;;
-    *:MidnightBSD:*:*)
- echo "$UNAME_MACHINE"-unknown-midnightbsd"$UNAME_RELEASE"
+ echo ${UNAME_MACHINE_ARCH}-unknown-libertybsd${UNAME_RELEASE}
  exit ;;
     *:ekkoBSD:*:*)
- echo "$UNAME_MACHINE"-unknown-ekkobsd"$UNAME_RELEASE"
+ echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE}
  exit ;;
     *:SolidBSD:*:*)
- echo "$UNAME_MACHINE"-unknown-solidbsd"$UNAME_RELEASE"
+ echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE}
  exit ;;
     macppc:MirBSD:*:*)
- echo powerpc-unknown-mirbsd"$UNAME_RELEASE"
+ echo powerpc-unknown-mirbsd${UNAME_RELEASE}
  exit ;;
     *:MirBSD:*:*)
- echo "$UNAME_MACHINE"-unknown-mirbsd"$UNAME_RELEASE"
+ echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE}
  exit ;;
     *:Sortix:*:*)
- echo "$UNAME_MACHINE"-unknown-sortix
+ echo ${UNAME_MACHINE}-unknown-sortix
  exit ;;
-    *:Redox:*:*)
- echo "$UNAME_MACHINE"-unknown-redox
- exit ;;
-    mips:OSF1:*.*)
-        echo mips-dec-osf1
-        exit ;;
     alpha:OSF1:*:*)
  case $UNAME_RELEASE in
  *4.0)
@@ -326,19 +310,28 @@ case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAM
  # A Tn.n version is a released field test version.
  # A Xn.n version is an unreleased experimental baselevel.
  # 1.2 uses "1.2" for uname -r.
- echo "$UNAME_MACHINE"-dec-osf"`echo "$UNAME_RELEASE" | sed -e 's/^[PVTX]//' | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz`"
+ echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz`
  # Reset EXIT trap before exiting to avoid spurious non-zero exit code.
  exitcode=$?
  trap '' 0
  exit $exitcode ;;
+    Alpha\ *:Windows_NT*:*)
+ # How do we know it's Interix rather than the generic POSIX subsystem?
+ # Should we change UNAME_MACHINE based on the output of uname instead
+ # of the specific Alpha model?
+ echo alpha-pc-interix
+ exit ;;
+    21064:Windows_NT:50:3)
+ echo alpha-dec-winnt3.5
+ exit ;;
     Amiga*:UNIX_System_V:4.0:*)
  echo m68k-unknown-sysv4
  exit ;;
     *:[Aa]miga[Oo][Ss]:*:*)
- echo "$UNAME_MACHINE"-unknown-amigaos
+ echo ${UNAME_MACHINE}-unknown-amigaos
  exit ;;
     *:[Mm]orph[Oo][Ss]:*:*)
- echo "$UNAME_MACHINE"-unknown-morphos
+ echo ${UNAME_MACHINE}-unknown-morphos
  exit ;;
     *:OS/390:*:*)
  echo i370-ibm-openedition
@@ -350,7 +343,7 @@ case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAM
  echo powerpc-ibm-os400
  exit ;;
     arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
- echo arm-acorn-riscix"$UNAME_RELEASE"
+ echo arm-acorn-riscix${UNAME_RELEASE}
  exit ;;
     arm*:riscos:*:*|arm*:RISCOS:*:*)
  echo arm-unknown-riscos
@@ -377,19 +370,19 @@ case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAM
     sparc) echo sparc-icl-nx7; exit ;;
  esac ;;
     s390x:SunOS:*:*)
- echo "$UNAME_MACHINE"-ibm-solaris2"`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`"
+ echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
  exit ;;
     sun4H:SunOS:5.*:*)
- echo sparc-hal-solaris2"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`"
+ echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
  exit ;;
     sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
- echo sparc-sun-solaris2"`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`"
+ echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
  exit ;;
     i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*)
- echo i386-pc-auroraux"$UNAME_RELEASE"
+ echo i386-pc-auroraux${UNAME_RELEASE}
  exit ;;
     i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*)
- eval "$set_cc_for_build"
+ eval $set_cc_for_build
  SUN_ARCH=i386
  # If there is a compiler, see if it is configured for 64-bit objects.
  # Note that the Sun cc does not turn __LP64__ into 1 like gcc does.
@@ -402,13 +395,13 @@ case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAM
  SUN_ARCH=x86_64
     fi
  fi
- echo "$SUN_ARCH"-pc-solaris2"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`"
+ echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
  exit ;;
     sun4*:SunOS:6*:*)
  # According to config.sub, this is the proper way to canonicalize
  # SunOS6.  Hard to guess exactly what SunOS6 will be like, but
  # it's likely to be more like Solaris than SunOS4.
- echo sparc-sun-solaris3"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`"
+ echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
  exit ;;
     sun4*:SunOS:*:*)
  case "`/usr/bin/arch -k`" in
@@ -417,25 +410,25 @@ case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAM
  ;;
  esac
  # Japanese Language versions have a version number like `4.1.3-JL'.
- echo sparc-sun-sunos"`echo "$UNAME_RELEASE"|sed -e 's/-/_/'`"
+ echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'`
  exit ;;
     sun3*:SunOS:*:*)
- echo m68k-sun-sunos"$UNAME_RELEASE"
+ echo m68k-sun-sunos${UNAME_RELEASE}
  exit ;;
     sun*:*:4.2BSD:*)
  UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
- test "x$UNAME_RELEASE" = x && UNAME_RELEASE=3
+ test "x${UNAME_RELEASE}" = x && UNAME_RELEASE=3
  case "`/bin/arch`" in
     sun3)
- echo m68k-sun-sunos"$UNAME_RELEASE"
+ echo m68k-sun-sunos${UNAME_RELEASE}
  ;;
     sun4)
- echo sparc-sun-sunos"$UNAME_RELEASE"
+ echo sparc-sun-sunos${UNAME_RELEASE}
  ;;
  esac
  exit ;;
     aushp:SunOS:*:*)
- echo sparc-auspex-sunos"$UNAME_RELEASE"
+ echo sparc-auspex-sunos${UNAME_RELEASE}
  exit ;;
     # The situation for MiNT is a little confusing.  The machine name
     # can be virtually everything (everything which is not
@@ -446,44 +439,44 @@ case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAM
     # MiNT.  But MiNT is downward compatible to TOS, so this should
     # be no problem.
     atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
- echo m68k-atari-mint"$UNAME_RELEASE"
+ echo m68k-atari-mint${UNAME_RELEASE}
  exit ;;
     atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
- echo m68k-atari-mint"$UNAME_RELEASE"
+ echo m68k-atari-mint${UNAME_RELEASE}
  exit ;;
     *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
- echo m68k-atari-mint"$UNAME_RELEASE"
+ echo m68k-atari-mint${UNAME_RELEASE}
  exit ;;
     milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
- echo m68k-milan-mint"$UNAME_RELEASE"
+ echo m68k-milan-mint${UNAME_RELEASE}
  exit ;;
     hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
- echo m68k-hades-mint"$UNAME_RELEASE"
+ echo m68k-hades-mint${UNAME_RELEASE}
  exit ;;
     *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
- echo m68k-unknown-mint"$UNAME_RELEASE"
+ echo m68k-unknown-mint${UNAME_RELEASE}
  exit ;;
     m68k:machten:*:*)
- echo m68k-apple-machten"$UNAME_RELEASE"
+ echo m68k-apple-machten${UNAME_RELEASE}
  exit ;;
     powerpc:machten:*:*)
- echo powerpc-apple-machten"$UNAME_RELEASE"
+ echo powerpc-apple-machten${UNAME_RELEASE}
  exit ;;
     RISC*:Mach:*:*)
  echo mips-dec-mach_bsd4.3
  exit ;;
     RISC*:ULTRIX:*:*)
- echo mips-dec-ultrix"$UNAME_RELEASE"
+ echo mips-dec-ultrix${UNAME_RELEASE}
  exit ;;
     VAX*:ULTRIX*:*:*)
- echo vax-dec-ultrix"$UNAME_RELEASE"
+ echo vax-dec-ultrix${UNAME_RELEASE}
  exit ;;
     2020:CLIX:*:* | 2430:CLIX:*:*)
- echo clipper-intergraph-clix"$UNAME_RELEASE"
+ echo clipper-intergraph-clix${UNAME_RELEASE}
  exit ;;
     mips:*:*:UMIPS | mips:*:*:RISCos)
- eval "$set_cc_for_build"
- sed 's/^ //' << EOF > "$dummy.c"
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
 #ifdef __cplusplus
 #include <stdio.h>  /* for printf() prototype */
  int main (int argc, char *argv[]) {
@@ -492,23 +485,23 @@ case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAM
 #endif
  #if defined (host_mips) && defined (MIPSEB)
  #if defined (SYSTYPE_SYSV)
-  printf ("mips-mips-riscos%ssysv\\n", argv[1]); exit (0);
+  printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0);
  #endif
  #if defined (SYSTYPE_SVR4)
-  printf ("mips-mips-riscos%ssvr4\\n", argv[1]); exit (0);
+  printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0);
  #endif
  #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)
-  printf ("mips-mips-riscos%sbsd\\n", argv[1]); exit (0);
+  printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0);
  #endif
  #endif
   exit (-1);
  }
 EOF
- $CC_FOR_BUILD -o "$dummy" "$dummy.c" &&
-  dummyarg=`echo "$UNAME_RELEASE" | sed -n 's/\([0-9]*\).*/\1/p'` &&
-  SYSTEM_NAME=`"$dummy" "$dummyarg"` &&
+ $CC_FOR_BUILD -o $dummy $dummy.c &&
+  dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` &&
+  SYSTEM_NAME=`$dummy $dummyarg` &&
     { echo "$SYSTEM_NAME"; exit; }
- echo mips-mips-riscos"$UNAME_RELEASE"
+ echo mips-mips-riscos${UNAME_RELEASE}
  exit ;;
     Motorola:PowerMAX_OS:*:*)
  echo powerpc-motorola-powermax
@@ -534,17 +527,17 @@ EOF
     AViiON:dgux:*:*)
  # DG/UX returns AViiON for all architectures
  UNAME_PROCESSOR=`/usr/bin/uname -p`
- if [ "$UNAME_PROCESSOR" = mc88100 ] || [ "$UNAME_PROCESSOR" = mc88110 ]
+ if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ]
  then
-    if [ "$TARGET_BINARY_INTERFACE"x = m88kdguxelfx ] || \
-       [ "$TARGET_BINARY_INTERFACE"x = x ]
+    if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \
+       [ ${TARGET_BINARY_INTERFACE}x = x ]
     then
- echo m88k-dg-dgux"$UNAME_RELEASE"
+ echo m88k-dg-dgux${UNAME_RELEASE}
     else
- echo m88k-dg-dguxbcs"$UNAME_RELEASE"
+ echo m88k-dg-dguxbcs${UNAME_RELEASE}
     fi
  else
-    echo i586-dg-dgux"$UNAME_RELEASE"
+    echo i586-dg-dgux${UNAME_RELEASE}
  fi
  exit ;;
     M88*:DolphinOS:*:*) # DolphinOS (SVR3)
@@ -561,7 +554,7 @@ EOF
  echo m68k-tektronix-bsd
  exit ;;
     *:IRIX*:*:*)
- echo mips-sgi-irix"`echo "$UNAME_RELEASE"|sed -e 's/-/_/g'`"
+ echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`
  exit ;;
     ????????:AIX?:[12].1:2)   # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
  echo romp-ibm-aix     # uname -m gives an 8 hex-code CPU id
@@ -573,14 +566,14 @@ EOF
  if [ -x /usr/bin/oslevel ] ; then
  IBM_REV=`/usr/bin/oslevel`
  else
- IBM_REV="$UNAME_VERSION.$UNAME_RELEASE"
+ IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
  fi
- echo "$UNAME_MACHINE"-ibm-aix"$IBM_REV"
+ echo ${UNAME_MACHINE}-ibm-aix${IBM_REV}
  exit ;;
     *:AIX:2:3)
  if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
- eval "$set_cc_for_build"
- sed 's/^ //' << EOF > "$dummy.c"
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
  #include <sys/systemcfg.h>
 
  main()
@@ -591,7 +584,7 @@ EOF
  exit(0);
  }
 EOF
- if $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=`"$dummy"`
+ if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy`
  then
  echo "$SYSTEM_NAME"
  else
@@ -605,7 +598,7 @@ EOF
  exit ;;
     *:AIX:*:[4567])
  IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`
- if /usr/sbin/lsattr -El "$IBM_CPU_ID" | grep ' POWER' >/dev/null 2>&1; then
+ if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then
  IBM_ARCH=rs6000
  else
  IBM_ARCH=powerpc
@@ -614,18 +607,18 @@ EOF
  IBM_REV=`/usr/bin/lslpp -Lqc bos.rte.libc |
    awk -F: '{ print $3 }' | sed s/[0-9]*$/0/`
  else
- IBM_REV="$UNAME_VERSION.$UNAME_RELEASE"
+ IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
  fi
- echo "$IBM_ARCH"-ibm-aix"$IBM_REV"
+ echo ${IBM_ARCH}-ibm-aix${IBM_REV}
  exit ;;
     *:AIX:*:*)
  echo rs6000-ibm-aix
  exit ;;
-    ibmrt:4.4BSD:*|romp-ibm:4.4BSD:*)
+    ibmrt:4.4BSD:*|romp-ibm:BSD:*)
  echo romp-ibm-bsd4.4
  exit ;;
     ibmrt:*BSD:*|romp-ibm:BSD:*)            # covers RT/PC BSD and
- echo romp-ibm-bsd"$UNAME_RELEASE"   # 4.3 with uname added to
+ echo romp-ibm-bsd${UNAME_RELEASE}   # 4.3 with uname added to
  exit ;;                             # report: romp-ibm BSD 4.3
     *:BOSX:*:*)
  echo rs6000-bull-bosx
@@ -640,28 +633,28 @@ EOF
  echo m68k-hp-bsd4.4
  exit ;;
     9000/[34678]??:HP-UX:*:*)
- HPUX_REV=`echo "$UNAME_RELEASE"|sed -e 's/[^.]*.[0B]*//'`
- case "$UNAME_MACHINE" in
-    9000/31?)            HP_ARCH=m68000 ;;
-    9000/[34]??)         HP_ARCH=m68k ;;
+ HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+ case "${UNAME_MACHINE}" in
+    9000/31? )            HP_ARCH=m68000 ;;
+    9000/[34]?? )         HP_ARCH=m68k ;;
     9000/[678][0-9][0-9])
  if [ -x /usr/bin/getconf ]; then
     sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
     sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
-    case "$sc_cpu_version" in
+    case "${sc_cpu_version}" in
       523) HP_ARCH=hppa1.0 ;; # CPU_PA_RISC1_0
       528) HP_ARCH=hppa1.1 ;; # CPU_PA_RISC1_1
       532)                      # CPU_PA_RISC2_0
- case "$sc_kernel_bits" in
+ case "${sc_kernel_bits}" in
   32) HP_ARCH=hppa2.0n ;;
   64) HP_ARCH=hppa2.0w ;;
   '') HP_ARCH=hppa2.0 ;;   # HP-UX 10.20
  esac ;;
     esac
  fi
- if [ "$HP_ARCH" = "" ]; then
-    eval "$set_cc_for_build"
-    sed 's/^ //' << EOF > "$dummy.c"
+ if [ "${HP_ARCH}" = "" ]; then
+    eval $set_cc_for_build
+    sed 's/^ //' << EOF >$dummy.c
 
  #define _HPUX_SOURCE
  #include <stdlib.h>
@@ -694,13 +687,13 @@ EOF
     exit (0);
  }
 EOF
-    (CCOPTS="" $CC_FOR_BUILD -o "$dummy" "$dummy.c" 2>/dev/null) && HP_ARCH=`"$dummy"`
+    (CCOPTS="" $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy`
     test -z "$HP_ARCH" && HP_ARCH=hppa
  fi ;;
  esac
- if [ "$HP_ARCH" = hppa2.0w ]
+ if [ ${HP_ARCH} = hppa2.0w ]
  then
-    eval "$set_cc_for_build"
+    eval $set_cc_for_build
 
     # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating
     # 32-bit code.  hppa64-hp-hpux* has the same kernel and a compiler
@@ -719,15 +712,15 @@ EOF
  HP_ARCH=hppa64
     fi
  fi
- echo "$HP_ARCH"-hp-hpux"$HPUX_REV"
+ echo ${HP_ARCH}-hp-hpux${HPUX_REV}
  exit ;;
     ia64:HP-UX:*:*)
- HPUX_REV=`echo "$UNAME_RELEASE"|sed -e 's/[^.]*.[0B]*//'`
- echo ia64-hp-hpux"$HPUX_REV"
+ HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+ echo ia64-hp-hpux${HPUX_REV}
  exit ;;
     3050*:HI-UX:*:*)
- eval "$set_cc_for_build"
- sed 's/^ //' << EOF > "$dummy.c"
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
  #include <unistd.h>
  int
  main ()
@@ -752,11 +745,11 @@ EOF
   exit (0);
  }
 EOF
- $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=`"$dummy"` &&
+ $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` &&
  { echo "$SYSTEM_NAME"; exit; }
  echo unknown-hitachi-hiuxwe2
  exit ;;
-    9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:*)
+    9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
  echo hppa1.1-hp-bsd
  exit ;;
     9000/8??:4.3bsd:*:*)
@@ -765,7 +758,7 @@ EOF
     *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*)
  echo hppa1.0-hp-mpeix
  exit ;;
-    hp7??:OSF1:*:* | hp8?[79]:OSF1:*:*)
+    hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
  echo hppa1.1-hp-osf
  exit ;;
     hp8??:OSF1:*:*)
@@ -773,9 +766,9 @@ EOF
  exit ;;
     i*86:OSF1:*:*)
  if [ -x /usr/sbin/sysversion ] ; then
-    echo "$UNAME_MACHINE"-unknown-osf1mk
+    echo ${UNAME_MACHINE}-unknown-osf1mk
  else
-    echo "$UNAME_MACHINE"-unknown-osf1
+    echo ${UNAME_MACHINE}-unknown-osf1
  fi
  exit ;;
     parisc*:Lites*:*:*)
@@ -800,109 +793,127 @@ EOF
  echo c4-convex-bsd
  exit ;;
     CRAY*Y-MP:*:*:*)
- echo ymp-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'
+ echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
  exit ;;
     CRAY*[A-Z]90:*:*:*)
- echo "$UNAME_MACHINE"-cray-unicos"$UNAME_RELEASE" \
+ echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \
  | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
       -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \
       -e 's/\.[^.]*$/.X/'
  exit ;;
     CRAY*TS:*:*:*)
- echo t90-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'
+ echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
  exit ;;
     CRAY*T3E:*:*:*)
- echo alphaev5-cray-unicosmk"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'
+ echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
  exit ;;
     CRAY*SV1:*:*:*)
- echo sv1-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'
+ echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
  exit ;;
     *:UNICOS/mp:*:*)
- echo craynv-cray-unicosmp"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'
+ echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
  exit ;;
     F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
  FUJITSU_PROC=`uname -m | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz`
  FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'`
- FUJITSU_REL=`echo "$UNAME_RELEASE" | sed -e 's/ /_/'`
+ FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
  echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
  exit ;;
     5000:UNIX_System_V:4.*:*)
  FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'`
- FUJITSU_REL=`echo "$UNAME_RELEASE" | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/ /_/'`
+ FUJITSU_REL=`echo ${UNAME_RELEASE} | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/ /_/'`
  echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
  exit ;;
     i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
- echo "$UNAME_MACHINE"-pc-bsdi"$UNAME_RELEASE"
+ echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
  exit ;;
     sparc*:BSD/OS:*:*)
- echo sparc-unknown-bsdi"$UNAME_RELEASE"
+ echo sparc-unknown-bsdi${UNAME_RELEASE}
  exit ;;
     *:BSD/OS:*:*)
- echo "$UNAME_MACHINE"-unknown-bsdi"$UNAME_RELEASE"
+ echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
  exit ;;
     *:FreeBSD:*:*)
  UNAME_PROCESSOR=`/usr/bin/uname -p`
- case "$UNAME_PROCESSOR" in
+ case ${UNAME_PROCESSOR} in
     amd64)
- UNAME_PROCESSOR=x86_64 ;;
-    i386)
- UNAME_PROCESSOR=i586 ;;
+ echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+    *)
+ echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
  esac
- echo "$UNAME_PROCESSOR"-unknown-freebsd"`echo "$UNAME_RELEASE"|sed -e 's/[-(].*//'`"
  exit ;;
     i*:CYGWIN*:*)
- echo "$UNAME_MACHINE"-pc-cygwin
+ echo ${UNAME_MACHINE}-pc-cygwin
  exit ;;
     *:MINGW64*:*)
- echo "$UNAME_MACHINE"-pc-mingw64
+ echo ${UNAME_MACHINE}-pc-mingw64
  exit ;;
     *:MINGW*:*)
- echo "$UNAME_MACHINE"-pc-mingw32
+ echo ${UNAME_MACHINE}-pc-mingw32
  exit ;;
     *:MSYS*:*)
- echo "$UNAME_MACHINE"-pc-msys
+ echo ${UNAME_MACHINE}-pc-msys
+ exit ;;
+    i*:windows32*:*)
+ # uname -m includes "-pc" on this system.
+ echo ${UNAME_MACHINE}-mingw32
  exit ;;
     i*:PW*:*)
- echo "$UNAME_MACHINE"-pc-pw32
+ echo ${UNAME_MACHINE}-pc-pw32
  exit ;;
     *:Interix*:*)
- case "$UNAME_MACHINE" in
+ case ${UNAME_MACHINE} in
     x86)
- echo i586-pc-interix"$UNAME_RELEASE"
+ echo i586-pc-interix${UNAME_RELEASE}
  exit ;;
     authenticamd | genuineintel | EM64T)
- echo x86_64-unknown-interix"$UNAME_RELEASE"
+ echo x86_64-unknown-interix${UNAME_RELEASE}
  exit ;;
     IA64)
- echo ia64-unknown-interix"$UNAME_RELEASE"
+ echo ia64-unknown-interix${UNAME_RELEASE}
  exit ;;
  esac ;;
+    [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*)
+ echo i${UNAME_MACHINE}-pc-mks
+ exit ;;
+    8664:Windows_NT:*)
+ echo x86_64-pc-mks
+ exit ;;
+    i*:Windows_NT*:* | Pentium*:Windows_NT*:*)
+ # How do we know it's Interix rather than the generic POSIX subsystem?
+ # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we
+ # UNAME_MACHINE based on the output of uname instead of i386?
+ echo i586-pc-interix
+ exit ;;
     i*:UWIN*:*)
- echo "$UNAME_MACHINE"-pc-uwin
+ echo ${UNAME_MACHINE}-pc-uwin
  exit ;;
     amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*)
  echo x86_64-unknown-cygwin
  exit ;;
+    p*:CYGWIN*:*)
+ echo powerpcle-unknown-cygwin
+ exit ;;
     prep*:SunOS:5.*:*)
- echo powerpcle-unknown-solaris2"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`"
+ echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
  exit ;;
     *:GNU:*:*)
  # the GNU system
- echo "`echo "$UNAME_MACHINE"|sed -e 's,[-/].*$,,'`-unknown-$LIBC`echo "$UNAME_RELEASE"|sed -e 's,/.*$,,'`"
+ echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-${LIBC}`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
  exit ;;
     *:GNU/*:*:*)
  # other systems with GNU libc and userland
- echo "$UNAME_MACHINE-unknown-`echo "$UNAME_SYSTEM" | sed 's,^[^/]*/,,' | tr "[:upper:]" "[:lower:]"``echo "$UNAME_RELEASE"|sed -e 's/[-(].*//'`-$LIBC"
+ echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr "[:upper:]" "[:lower:]"``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-${LIBC}
  exit ;;
     i*86:Minix:*:*)
- echo "$UNAME_MACHINE"-pc-minix
+ echo ${UNAME_MACHINE}-pc-minix
  exit ;;
     aarch64:Linux:*:*)
- echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
  exit ;;
     aarch64_be:Linux:*:*)
  UNAME_MACHINE=aarch64_be
- echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
  exit ;;
     alpha:Linux:*:*)
  case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
@@ -916,63 +927,63 @@ EOF
  esac
  objdump --private-headers /bin/sh | grep -q ld.so.1
  if test "$?" = 0 ; then LIBC=gnulibc1 ; fi
- echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
  exit ;;
     arc:Linux:*:* | arceb:Linux:*:*)
- echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
  exit ;;
     arm*:Linux:*:*)
- eval "$set_cc_for_build"
+ eval $set_cc_for_build
  if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \
     | grep -q __ARM_EABI__
  then
-    echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
+    echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
  else
     if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \
  | grep -q __ARM_PCS_VFP
     then
- echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"eabi
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabi
     else
- echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"eabihf
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabihf
     fi
  fi
  exit ;;
     avr32*:Linux:*:*)
- echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
  exit ;;
     cris:Linux:*:*)
- echo "$UNAME_MACHINE"-axis-linux-"$LIBC"
+ echo ${UNAME_MACHINE}-axis-linux-${LIBC}
  exit ;;
     crisv32:Linux:*:*)
- echo "$UNAME_MACHINE"-axis-linux-"$LIBC"
+ echo ${UNAME_MACHINE}-axis-linux-${LIBC}
  exit ;;
     e2k:Linux:*:*)
- echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
  exit ;;
     frv:Linux:*:*)
- echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
  exit ;;
     hexagon:Linux:*:*)
- echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
  exit ;;
     i*86:Linux:*:*)
- echo "$UNAME_MACHINE"-pc-linux-"$LIBC"
+ echo ${UNAME_MACHINE}-pc-linux-${LIBC}
  exit ;;
     ia64:Linux:*:*)
- echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
  exit ;;
     k1om:Linux:*:*)
- echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
  exit ;;
     m32r*:Linux:*:*)
- echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
  exit ;;
     m68*:Linux:*:*)
- echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
  exit ;;
     mips:Linux:*:* | mips64:Linux:*:*)
- eval "$set_cc_for_build"
- sed 's/^ //' << EOF > "$dummy.c"
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
  #undef CPU
  #undef ${UNAME_MACHINE}
  #undef ${UNAME_MACHINE}el
@@ -986,74 +997,70 @@ EOF
  #endif
  #endif
 EOF
- eval "`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^CPU'`"
- test "x$CPU" != x && { echo "$CPU-unknown-linux-$LIBC"; exit; }
+ eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'`
+ test x"${CPU}" != x && { echo "${CPU}-unknown-linux-${LIBC}"; exit; }
  ;;
     mips64el:Linux:*:*)
- echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
  exit ;;
     openrisc*:Linux:*:*)
- echo or1k-unknown-linux-"$LIBC"
+ echo or1k-unknown-linux-${LIBC}
  exit ;;
     or32:Linux:*:* | or1k*:Linux:*:*)
- echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
  exit ;;
     padre:Linux:*:*)
- echo sparc-unknown-linux-"$LIBC"
+ echo sparc-unknown-linux-${LIBC}
  exit ;;
     parisc64:Linux:*:* | hppa64:Linux:*:*)
- echo hppa64-unknown-linux-"$LIBC"
+ echo hppa64-unknown-linux-${LIBC}
  exit ;;
     parisc:Linux:*:* | hppa:Linux:*:*)
  # Look for CPU level
  case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
-  PA7*) echo hppa1.1-unknown-linux-"$LIBC" ;;
-  PA8*) echo hppa2.0-unknown-linux-"$LIBC" ;;
-  *)    echo hppa-unknown-linux-"$LIBC" ;;
+  PA7*) echo hppa1.1-unknown-linux-${LIBC} ;;
+  PA8*) echo hppa2.0-unknown-linux-${LIBC} ;;
+  *)    echo hppa-unknown-linux-${LIBC} ;;
  esac
  exit ;;
     ppc64:Linux:*:*)
- echo powerpc64-unknown-linux-"$LIBC"
+ echo powerpc64-unknown-linux-${LIBC}
  exit ;;
     ppc:Linux:*:*)
- echo powerpc-unknown-linux-"$LIBC"
+ echo powerpc-unknown-linux-${LIBC}
  exit ;;
     ppc64le:Linux:*:*)
- echo powerpc64le-unknown-linux-"$LIBC"
+ echo powerpc64le-unknown-linux-${LIBC}
  exit ;;
     ppcle:Linux:*:*)
- echo powerpcle-unknown-linux-"$LIBC"
+ echo powerpcle-unknown-linux-${LIBC}
  exit ;;
     riscv32:Linux:*:* | riscv64:Linux:*:*)
- echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
  exit ;;
     s390:Linux:*:* | s390x:Linux:*:*)
- echo "$UNAME_MACHINE"-ibm-linux-"$LIBC"
+ echo ${UNAME_MACHINE}-ibm-linux-${LIBC}
  exit ;;
     sh64*:Linux:*:*)
- echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
  exit ;;
     sh*:Linux:*:*)
- echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
  exit ;;
     sparc:Linux:*:* | sparc64:Linux:*:*)
- echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
  exit ;;
     tile*:Linux:*:*)
- echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
  exit ;;
     vax:Linux:*:*)
- echo "$UNAME_MACHINE"-dec-linux-"$LIBC"
+ echo ${UNAME_MACHINE}-dec-linux-${LIBC}
  exit ;;
     x86_64:Linux:*:*)
- if objdump -f /bin/sh | grep -q elf32-x86-64; then
-    echo "$UNAME_MACHINE"-pc-linux-"$LIBC"x32
- else
-    echo "$UNAME_MACHINE"-pc-linux-"$LIBC"
- fi
+ echo ${UNAME_MACHINE}-pc-linux-${LIBC}
  exit ;;
     xtensa*:Linux:*:*)
- echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
  exit ;;
     i*86:DYNIX/ptx:4*:*)
  # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
@@ -1067,34 +1074,34 @@ EOF
  # I am not positive that other SVR4 systems won't match this,
  # I just have to hope.  -- rms.
  # Use sysv4.2uw... so that sysv4* matches it.
- echo "$UNAME_MACHINE"-pc-sysv4.2uw"$UNAME_VERSION"
+ echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
  exit ;;
     i*86:OS/2:*:*)
  # If we were able to find `uname', then EMX Unix compatibility
  # is probably installed.
- echo "$UNAME_MACHINE"-pc-os2-emx
+ echo ${UNAME_MACHINE}-pc-os2-emx
  exit ;;
     i*86:XTS-300:*:STOP)
- echo "$UNAME_MACHINE"-unknown-stop
+ echo ${UNAME_MACHINE}-unknown-stop
  exit ;;
     i*86:atheos:*:*)
- echo "$UNAME_MACHINE"-unknown-atheos
+ echo ${UNAME_MACHINE}-unknown-atheos
  exit ;;
     i*86:syllable:*:*)
- echo "$UNAME_MACHINE"-pc-syllable
+ echo ${UNAME_MACHINE}-pc-syllable
  exit ;;
     i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*)
- echo i386-unknown-lynxos"$UNAME_RELEASE"
+ echo i386-unknown-lynxos${UNAME_RELEASE}
  exit ;;
     i*86:*DOS:*:*)
- echo "$UNAME_MACHINE"-pc-msdosdjgpp
+ echo ${UNAME_MACHINE}-pc-msdosdjgpp
  exit ;;
-    i*86:*:4.*:*)
- UNAME_REL=`echo "$UNAME_RELEASE" | sed 's/\/MP$//'`
+    i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*)
+ UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'`
  if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
- echo "$UNAME_MACHINE"-univel-sysv"$UNAME_REL"
+ echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL}
  else
- echo "$UNAME_MACHINE"-pc-sysv"$UNAME_REL"
+ echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL}
  fi
  exit ;;
     i*86:*:5:[678]*)
@@ -1104,12 +1111,12 @@ EOF
     *Pentium)     UNAME_MACHINE=i586 ;;
     *Pent*|*Celeron) UNAME_MACHINE=i686 ;;
  esac
- echo "$UNAME_MACHINE-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}{$UNAME_VERSION}"
+ echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}
  exit ;;
     i*86:*:3.2:*)
  if test -f /usr/options/cb.name; then
  UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
- echo "$UNAME_MACHINE"-pc-isc"$UNAME_REL"
+ echo ${UNAME_MACHINE}-pc-isc$UNAME_REL
  elif /bin/uname -X 2>/dev/null >/dev/null ; then
  UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')`
  (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486
@@ -1119,9 +1126,9 @@ EOF
  && UNAME_MACHINE=i686
  (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \
  && UNAME_MACHINE=i686
- echo "$UNAME_MACHINE"-pc-sco"$UNAME_REL"
+ echo ${UNAME_MACHINE}-pc-sco$UNAME_REL
  else
- echo "$UNAME_MACHINE"-pc-sysv32
+ echo ${UNAME_MACHINE}-pc-sysv32
  fi
  exit ;;
     pc:*:*:*)
@@ -1141,9 +1148,9 @@ EOF
  exit ;;
     i860:*:4.*:*) # i860-SVR4
  if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
-  echo i860-stardent-sysv"$UNAME_RELEASE" # Stardent Vistra i860-SVR4
+  echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4
  else # Add other i860-SVR4 vendors below as they are discovered.
-  echo i860-unknown-sysv"$UNAME_RELEASE"  # Unknown i860-SVR4
+  echo i860-unknown-sysv${UNAME_RELEASE}  # Unknown i860-SVR4
  fi
  exit ;;
     mini*:CTIX:SYS*5:*)
@@ -1163,9 +1170,9 @@ EOF
  test -r /etc/.relid \
  && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
  /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
-  && { echo i486-ncr-sysv4.3"$OS_REL"; exit; }
+  && { echo i486-ncr-sysv4.3${OS_REL}; exit; }
  /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
-  && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } ;;
+  && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
     3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
  /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
   && { echo i486-ncr-sysv4; exit; } ;;
@@ -1174,28 +1181,28 @@ EOF
  test -r /etc/.relid \
     && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
  /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
-    && { echo i486-ncr-sysv4.3"$OS_REL"; exit; }
+    && { echo i486-ncr-sysv4.3${OS_REL}; exit; }
  /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
-    && { echo i586-ncr-sysv4.3"$OS_REL"; exit; }
+    && { echo i586-ncr-sysv4.3${OS_REL}; exit; }
  /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \
-    && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } ;;
+    && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
     m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)
- echo m68k-unknown-lynxos"$UNAME_RELEASE"
+ echo m68k-unknown-lynxos${UNAME_RELEASE}
  exit ;;
     mc68030:UNIX_System_V:4.*:*)
  echo m68k-atari-sysv4
  exit ;;
     TSUNAMI:LynxOS:2.*:*)
- echo sparc-unknown-lynxos"$UNAME_RELEASE"
+ echo sparc-unknown-lynxos${UNAME_RELEASE}
  exit ;;
     rs6000:LynxOS:2.*:*)
- echo rs6000-unknown-lynxos"$UNAME_RELEASE"
+ echo rs6000-unknown-lynxos${UNAME_RELEASE}
  exit ;;
     PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*)
- echo powerpc-unknown-lynxos"$UNAME_RELEASE"
+ echo powerpc-unknown-lynxos${UNAME_RELEASE}
  exit ;;
     SM[BE]S:UNIX_SV:*:*)
- echo mips-dde-sysv"$UNAME_RELEASE"
+ echo mips-dde-sysv${UNAME_RELEASE}
  exit ;;
     RM*:ReliantUNIX-*:*:*)
  echo mips-sni-sysv4
@@ -1206,7 +1213,7 @@ EOF
     *:SINIX-*:*:*)
  if uname -p 2>/dev/null >/dev/null ; then
  UNAME_MACHINE=`(uname -p) 2>/dev/null`
- echo "$UNAME_MACHINE"-sni-sysv4
+ echo ${UNAME_MACHINE}-sni-sysv4
  else
  echo ns32k-sni-sysv
  fi
@@ -1226,23 +1233,23 @@ EOF
  exit ;;
     i*86:VOS:*:*)
  # From [hidden email].
- echo "$UNAME_MACHINE"-stratus-vos
+ echo ${UNAME_MACHINE}-stratus-vos
  exit ;;
     *:VOS:*:*)
  # From [hidden email].
  echo hppa1.1-stratus-vos
  exit ;;
     mc68*:A/UX:*:*)
- echo m68k-apple-aux"$UNAME_RELEASE"
+ echo m68k-apple-aux${UNAME_RELEASE}
  exit ;;
     news*:NEWS-OS:6*:*)
  echo mips-sony-newsos6
  exit ;;
     R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
  if [ -d /usr/nec ]; then
- echo mips-nec-sysv"$UNAME_RELEASE"
+ echo mips-nec-sysv${UNAME_RELEASE}
  else
- echo mips-unknown-sysv"$UNAME_RELEASE"
+ echo mips-unknown-sysv${UNAME_RELEASE}
  fi
  exit ;;
     BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only.
@@ -1261,56 +1268,49 @@ EOF
  echo x86_64-unknown-haiku
  exit ;;
     SX-4:SUPER-UX:*:*)
- echo sx4-nec-superux"$UNAME_RELEASE"
+ echo sx4-nec-superux${UNAME_RELEASE}
  exit ;;
     SX-5:SUPER-UX:*:*)
- echo sx5-nec-superux"$UNAME_RELEASE"
+ echo sx5-nec-superux${UNAME_RELEASE}
  exit ;;
     SX-6:SUPER-UX:*:*)
- echo sx6-nec-superux"$UNAME_RELEASE"
+ echo sx6-nec-superux${UNAME_RELEASE}
  exit ;;
     SX-7:SUPER-UX:*:*)
- echo sx7-nec-superux"$UNAME_RELEASE"
+ echo sx7-nec-superux${UNAME_RELEASE}
  exit ;;
     SX-8:SUPER-UX:*:*)
- echo sx8-nec-superux"$UNAME_RELEASE"
+ echo sx8-nec-superux${UNAME_RELEASE}
  exit ;;
     SX-8R:SUPER-UX:*:*)
- echo sx8r-nec-superux"$UNAME_RELEASE"
+ echo sx8r-nec-superux${UNAME_RELEASE}
  exit ;;
     SX-ACE:SUPER-UX:*:*)
- echo sxace-nec-superux"$UNAME_RELEASE"
+ echo sxace-nec-superux${UNAME_RELEASE}
  exit ;;
     Power*:Rhapsody:*:*)
- echo powerpc-apple-rhapsody"$UNAME_RELEASE"
+ echo powerpc-apple-rhapsody${UNAME_RELEASE}
  exit ;;
     *:Rhapsody:*:*)
- echo "$UNAME_MACHINE"-apple-rhapsody"$UNAME_RELEASE"
+ echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE}
  exit ;;
     *:Darwin:*:*)
  UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown
- eval "$set_cc_for_build"
+ eval $set_cc_for_build
  if test "$UNAME_PROCESSOR" = unknown ; then
     UNAME_PROCESSOR=powerpc
  fi
- if test "`echo "$UNAME_RELEASE" | sed -e 's/\..*//'`" -le 10 ; then
+ if test `echo "$UNAME_RELEASE" | sed -e 's/\..*//'` -le 10 ; then
     if [ "$CC_FOR_BUILD" != no_compiler_found ]; then
  if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \
-       (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
-       grep IS_64BIT_ARCH >/dev/null
+    (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
+    grep IS_64BIT_ARCH >/dev/null
  then
     case $UNAME_PROCESSOR in
  i386) UNAME_PROCESSOR=x86_64 ;;
  powerpc) UNAME_PROCESSOR=powerpc64 ;;
     esac
  fi
- # On 10.4-10.6 one might compile for PowerPC via gcc -arch ppc
- if (echo '#ifdef __POWERPC__'; echo IS_PPC; echo '#endif') | \
-       (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
-       grep IS_PPC >/dev/null
- then
-    UNAME_PROCESSOR=powerpc
- fi
     fi
  elif test "$UNAME_PROCESSOR" = i386 ; then
     # Avoid executing cc on OS X 10.9, as it ships with a stub
@@ -1321,7 +1321,7 @@ EOF
     # that Apple uses in portable devices.
     UNAME_PROCESSOR=x86_64
  fi
- echo "$UNAME_PROCESSOR"-apple-darwin"$UNAME_RELEASE"
+ echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
  exit ;;
     *:procnto*:*:* | *:QNX:[0123456789]*:*)
  UNAME_PROCESSOR=`uname -p`
@@ -1329,25 +1329,19 @@ EOF
  UNAME_PROCESSOR=i386
  UNAME_MACHINE=pc
  fi
- echo "$UNAME_PROCESSOR"-"$UNAME_MACHINE"-nto-qnx"$UNAME_RELEASE"
+ echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE}
  exit ;;
     *:QNX:*:4*)
  echo i386-pc-qnx
  exit ;;
-    NEO-*:NONSTOP_KERNEL:*:*)
- echo neo-tandem-nsk"$UNAME_RELEASE"
+    NEO-?:NONSTOP_KERNEL:*:*)
+ echo neo-tandem-nsk${UNAME_RELEASE}
  exit ;;
     NSE-*:NONSTOP_KERNEL:*:*)
- echo nse-tandem-nsk"$UNAME_RELEASE"
- exit ;;
-    NSR-*:NONSTOP_KERNEL:*:*)
- echo nsr-tandem-nsk"$UNAME_RELEASE"
- exit ;;
-    NSV-*:NONSTOP_KERNEL:*:*)
- echo nsv-tandem-nsk"$UNAME_RELEASE"
+ echo nse-tandem-nsk${UNAME_RELEASE}
  exit ;;
-    NSX-*:NONSTOP_KERNEL:*:*)
- echo nsx-tandem-nsk"$UNAME_RELEASE"
+    NSR-?:NONSTOP_KERNEL:*:*)
+ echo nsr-tandem-nsk${UNAME_RELEASE}
  exit ;;
     *:NonStop-UX:*:*)
  echo mips-compaq-nonstopux
@@ -1356,7 +1350,7 @@ EOF
  echo bs2000-siemens-sysv
  exit ;;
     DS/*:UNIX_System_V:*:*)
- echo "$UNAME_MACHINE"-"$UNAME_SYSTEM"-"$UNAME_RELEASE"
+ echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE}
  exit ;;
     *:Plan9:*:*)
  # "uname -m" is not consistent, so use $cputype instead. 386
@@ -1367,7 +1361,7 @@ EOF
  else
     UNAME_MACHINE="$cputype"
  fi
- echo "$UNAME_MACHINE"-unknown-plan9
+ echo ${UNAME_MACHINE}-unknown-plan9
  exit ;;
     *:TOPS-10:*:*)
  echo pdp10-unknown-tops10
@@ -1388,14 +1382,14 @@ EOF
  echo pdp10-unknown-its
  exit ;;
     SEI:*:*:SEIUX)
- echo mips-sei-seiux"$UNAME_RELEASE"
+ echo mips-sei-seiux${UNAME_RELEASE}
  exit ;;
     *:DragonFly:*:*)
- echo "$UNAME_MACHINE"-unknown-dragonfly"`echo "$UNAME_RELEASE"|sed -e 's/[-(].*//'`"
+ echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
  exit ;;
     *:*VMS:*:*)
  UNAME_MACHINE=`(uname -p) 2>/dev/null`
- case "$UNAME_MACHINE" in
+ case "${UNAME_MACHINE}" in
     A*) echo alpha-dec-vms ; exit ;;
     I*) echo ia64-dec-vms ; exit ;;
     V*) echo vax-dec-vms ; exit ;;
@@ -1404,44 +1398,32 @@ EOF
  echo i386-pc-xenix
  exit ;;
     i*86:skyos:*:*)
- echo "$UNAME_MACHINE"-pc-skyos"`echo "$UNAME_RELEASE" | sed -e 's/ .*$//'`"
+ echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE} | sed -e 's/ .*$//'`
  exit ;;
     i*86:rdos:*:*)
- echo "$UNAME_MACHINE"-pc-rdos
+ echo ${UNAME_MACHINE}-pc-rdos
  exit ;;
     i*86:AROS:*:*)
- echo "$UNAME_MACHINE"-pc-aros
+ echo ${UNAME_MACHINE}-pc-aros
  exit ;;
     x86_64:VMkernel:*:*)
- echo "$UNAME_MACHINE"-unknown-esx
+ echo ${UNAME_MACHINE}-unknown-esx
  exit ;;
     amd64:Isilon\ OneFS:*:*)
  echo x86_64-unknown-onefs
  exit ;;
 esac
 
-echo "$0: unable to guess system type" >&2
-
-case "$UNAME_MACHINE:$UNAME_SYSTEM" in
-    mips:Linux | mips64:Linux)
- # If we got here on MIPS GNU/Linux, output extra information.
- cat >&2 <<EOF
-
-NOTE: MIPS GNU/Linux systems require a C compiler to fully recognize
-the system type. Please install a C compiler and try again.
-EOF
- ;;
-esac
-
 cat >&2 <<EOF
+$0: unable to guess system type
 
 This script (version $timestamp), has failed to recognize the
-operating system you are using. If your script is old, overwrite *all*
-copies of config.guess and config.sub with the latest versions from:
+operating system you are using. If your script is old, overwrite
+config.guess and config.sub with the latest versions from:
 
-  https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess
+  http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess
 and
-  https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub
+  http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub
 
 If $0 has already been updated, send the following data and any
 information you think might be pertinent to [hidden email] to
@@ -1464,16 +1446,16 @@ hostinfo               = `(hostinfo) 2>/
 /usr/bin/oslevel       = `(/usr/bin/oslevel) 2>/dev/null`
 /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null`
 
-UNAME_MACHINE = "$UNAME_MACHINE"
-UNAME_RELEASE = "$UNAME_RELEASE"
-UNAME_SYSTEM  = "$UNAME_SYSTEM"
-UNAME_VERSION = "$UNAME_VERSION"
+UNAME_MACHINE = ${UNAME_MACHINE}
+UNAME_RELEASE = ${UNAME_RELEASE}
+UNAME_SYSTEM  = ${UNAME_SYSTEM}
+UNAME_VERSION = ${UNAME_VERSION}
 EOF
 
 exit 1
 
 # Local variables:
-# eval: (add-hook 'write-file-functions 'time-stamp)
+# eval: (add-hook 'write-file-hooks 'time-stamp)
 # time-stamp-start: "timestamp='"
 # time-stamp-format: "%:y-%02m-%02d"
 # time-stamp-end: "'"
Index: config.h.in
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/config.h.in,v
retrieving revision 1.18
diff -u -p -r1.18 config.h.in
--- config.h.in 18 Dec 2019 11:04:13 -0000 1.18
+++ config.h.in 15 Mar 2020 16:31:04 -0000
@@ -63,6 +63,15 @@
 /* Whether the C compiler accepts the "weak" attribute */
 #undef HAVE_ATTR_WEAK
 
+/* If we have be64toh */
+#undef HAVE_BE64TOH
+
+/* Define to 1 if you have the <bsd/stdlib.h> header file. */
+#undef HAVE_BSD_STDLIB_H
+
+/* Define to 1 if you have the <bsd/string.h> header file. */
+#undef HAVE_BSD_STRING_H
+
 /* Define to 1 if you have the `chown' function. */
 #undef HAVE_CHOWN
 
@@ -284,6 +293,9 @@
 /* If you have HMAC_Update */
 #undef HAVE_HMAC_UPDATE
 
+/* If we have htobe64 */
+#undef HAVE_HTOBE64
+
 /* Define to 1 if you have the `inet_aton' function. */
 #undef HAVE_INET_ATON
 
@@ -311,6 +323,9 @@
 /* Define to 1 if you have the `kill' function. */
 #undef HAVE_KILL
 
+/* Use portable libbsd functions */
+#undef HAVE_LIBBSD
+
 /* Define to 1 if you have the <libkern/OSByteOrder.h> header file. */
 #undef HAVE_LIBKERN_OSBYTEORDER_H
 
@@ -1229,6 +1244,11 @@ char *strptime(const char *s, const char
 
 #if !HAVE_DECL_REALLOCARRAY
 void *reallocarray(void *ptr, size_t nmemb, size_t size);
+#endif
+
+#ifdef HAVE_LIBBSD
+#include <bsd/string.h>
+#include <bsd/stdlib.h>
 #endif
 
 #ifdef HAVE_LIBRESSL
Index: config.sub
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/config.sub,v
retrieving revision 1.4
diff -u -p -r1.4 config.sub
--- config.sub 18 Dec 2019 11:04:13 -0000 1.4
+++ config.sub 15 Mar 2020 16:31:04 -0000
@@ -1,8 +1,8 @@
-#! /bin/sh
+#!/usr/bin/sh
 # Configuration validation subroutine script.
-#   Copyright 1992-2018 Free Software Foundation, Inc.
+#   Copyright 1992-2016 Free Software Foundation, Inc.
 
-timestamp='2018-02-22'
+timestamp='2016-09-05'
 
 # This file is free software; you can redistribute it and/or modify it
 # under the terms of the GNU General Public License as published by
@@ -15,7 +15,7 @@ timestamp='2018-02-22'
 # General Public License for more details.
 #
 # You should have received a copy of the GNU General Public License
-# along with this program; if not, see <https://www.gnu.org/licenses/>.
+# along with this program; if not, see <http://www.gnu.org/licenses/>.
 #
 # As a special exception to the GNU General Public License, if you
 # distribute this file as part of a program that contains a
@@ -33,7 +33,7 @@ timestamp='2018-02-22'
 # Otherwise, we print the canonical config type on stdout and succeed.
 
 # You can get the latest version of this script from:
-# https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub
+# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub
 
 # This file is supposed to be the same for all GNU packages
 # and recognize all the CPU types, system types and aliases
@@ -57,7 +57,7 @@ Usage: $0 [OPTION] CPU-MFR-OPSYS or ALIA
 
 Canonicalize a configuration name.
 
-Options:
+Operation modes:
   -h, --help         print this help, then exit
   -t, --time-stamp   print date of last modification, then exit
   -v, --version      print version number, then exit
@@ -67,7 +67,7 @@ Report bugs and patches to <config-patch
 version="\
 GNU config.sub ($timestamp)
 
-Copyright 1992-2018 Free Software Foundation, Inc.
+Copyright 1992-2016 Free Software Foundation, Inc.
 
 This is free software; see the source for copying conditions.  There is NO
 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
@@ -94,7 +94,7 @@ while test $# -gt 0 ; do
 
     *local*)
        # First pass through any local machine types.
-       echo "$1"
+       echo $1
        exit ;;
 
     * )
@@ -112,7 +112,7 @@ esac
 
 # Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any).
 # Here we must recognize all the valid KERNEL-OS combinations.
-maybe_os=`echo "$1" | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
+maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
 case $maybe_os in
   nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \
   linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \
@@ -120,16 +120,16 @@ case $maybe_os in
   kopensolaris*-gnu* | cloudabi*-eabi* | \
   storm-chaos* | os2-emx* | rtmk-nova*)
     os=-$maybe_os
-    basic_machine=`echo "$1" | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
+    basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
     ;;
   android-linux)
     os=-linux-android
-    basic_machine=`echo "$1" | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown
+    basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown
     ;;
   *)
-    basic_machine=`echo "$1" | sed 's/-[^-]*$//'`
-    if [ "$basic_machine" != "$1" ]
-    then os=`echo "$1" | sed 's/.*-/-/'`
+    basic_machine=`echo $1 | sed 's/-[^-]*$//'`
+    if [ $basic_machine != $1 ]
+    then os=`echo $1 | sed 's/.*-/-/'`
     else os=; fi
     ;;
 esac
@@ -178,44 +178,44 @@ case $os in
  ;;
  -sco6)
  os=-sco5v6
- basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'`
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
  ;;
  -sco5)
  os=-sco3.2v5
- basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'`
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
  ;;
  -sco4)
  os=-sco3.2v4
- basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'`
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
  ;;
  -sco3.2.[4-9]*)
  os=`echo $os | sed -e 's/sco3.2./sco3.2v/'`
- basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'`
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
  ;;
  -sco3.2v[4-9]*)
  # Don't forget version if it is 3.2v4 or newer.
- basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'`
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
  ;;
  -sco5v6*)
  # Don't forget version if it is 3.2v4 or newer.
- basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'`
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
  ;;
  -sco*)
  os=-sco3.2v2
- basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'`
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
  ;;
  -udk*)
- basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'`
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
  ;;
  -isc)
  os=-isc2.2
- basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'`
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
  ;;
  -clix*)
  basic_machine=clipper-intergraph
  ;;
  -isc*)
- basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'`
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
  ;;
  -lynx*178)
  os=-lynxos178
@@ -227,7 +227,10 @@ case $os in
  os=-lynxos
  ;;
  -ptx*)
- basic_machine=`echo "$1" | sed -e 's/86-.*/86-sequent/'`
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'`
+ ;;
+ -windowsnt*)
+ os=`echo $os | sed -e 's/windowsnt/winnt/'`
  ;;
  -psos*)
  os=-psos
@@ -260,7 +263,7 @@ case $basic_machine in
  | fido | fr30 | frv | ft32 \
  | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
  | hexagon \
- | i370 | i860 | i960 | ia16 | ia64 \
+ | i370 | i860 | i960 | ia64 \
  | ip2k | iq2000 \
  | k1om \
  | le32 | le64 \
@@ -296,9 +299,8 @@ case $basic_machine in
  | nios | nios2 | nios2eb | nios2el \
  | ns16k | ns32k \
  | open8 | or1k | or1knd | or32 \
- | pdp10 | pj | pjl \
+ | pdp10 | pdp11 | pj | pjl \
  | powerpc | powerpc64 | powerpc64le | powerpcle \
- | pru \
  | pyramid \
  | riscv32 | riscv64 \
  | rl78 | rx \
@@ -312,7 +314,7 @@ case $basic_machine in
  | ubicom32 \
  | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \
  | visium \
- | wasm32 \
+ | we32k \
  | x86 | xc16x | xstormy16 | xtensa \
  | z8k | z80)
  basic_machine=$basic_machine-unknown
@@ -333,7 +335,7 @@ case $basic_machine in
  basic_machine=$basic_machine-unknown
  os=-none
  ;;
- m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65)
+ m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k)
  ;;
  ms1)
  basic_machine=mt-unknown
@@ -362,7 +364,7 @@ case $basic_machine in
   ;;
  # Object if more than one company name word.
  *-*-*)
- echo Invalid configuration \`"$1"\': machine \`"$basic_machine"\' not recognized 1>&2
+ echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
  exit 1
  ;;
  # Recognize the basic CPU types with company name.
@@ -385,7 +387,7 @@ case $basic_machine in
  | h8300-* | h8500-* \
  | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
  | hexagon-* \
- | i*86-* | i860-* | i960-* | ia16-* | ia64-* \
+ | i*86-* | i860-* | i960-* | ia64-* \
  | ip2k-* | iq2000-* \
  | k1om-* \
  | le32-* | le64-* \
@@ -426,7 +428,6 @@ case $basic_machine in
  | orion-* \
  | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
  | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \
- | pru-* \
  | pyramid-* \
  | riscv32-* | riscv64-* \
  | rl78-* | romp-* | rs6000-* | rx-* \
@@ -443,7 +444,6 @@ case $basic_machine in
  | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \
  | vax-* \
  | visium-* \
- | wasm32-* \
  | we32k-* \
  | x86-* | x86_64-* | xc16x-* | xps100-* \
  | xstormy16-* | xtensa*-* \
@@ -457,7 +457,7 @@ case $basic_machine in
  # Recognize the various machine names and aliases which stand
  # for a CPU type and a company and sometimes even an OS.
  386bsd)
- basic_machine=i386-pc
+ basic_machine=i386-unknown
  os=-bsd
  ;;
  3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)
@@ -491,7 +491,7 @@ case $basic_machine in
  basic_machine=x86_64-pc
  ;;
  amd64-*)
- basic_machine=x86_64-`echo "$basic_machine" | sed 's/^[^-]*-//'`
+ basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'`
  ;;
  amdahl)
  basic_machine=580-amdahl
@@ -536,7 +536,7 @@ case $basic_machine in
  os=-linux
  ;;
  blackfin-*)
- basic_machine=bfin-`echo "$basic_machine" | sed 's/^[^-]*-//'`
+ basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'`
  os=-linux
  ;;
  bluegene*)
@@ -544,13 +544,13 @@ case $basic_machine in
  os=-cnk
  ;;
  c54x-*)
- basic_machine=tic54x-`echo "$basic_machine" | sed 's/^[^-]*-//'`
+ basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'`
  ;;
  c55x-*)
- basic_machine=tic55x-`echo "$basic_machine" | sed 's/^[^-]*-//'`
+ basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'`
  ;;
  c6x-*)
- basic_machine=tic6x-`echo "$basic_machine" | sed 's/^[^-]*-//'`
+ basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'`
  ;;
  c90)
  basic_machine=c90-cray
@@ -639,7 +639,7 @@ case $basic_machine in
  basic_machine=rs6000-bull
  os=-bosx
  ;;
- dpx2*)
+ dpx2* | dpx2*-bull)
  basic_machine=m68k-bull
  os=-sysv3
  ;;
@@ -648,7 +648,7 @@ case $basic_machine in
  os=$os"spe"
  ;;
  e500v[12]-*)
- basic_machine=powerpc-`echo "$basic_machine" | sed 's/^[^-]*-//'`
+ basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
  os=$os"spe"
  ;;
  ebmon29k)
@@ -740,6 +740,9 @@ case $basic_machine in
  hp9k8[0-9][0-9] | hp8[0-9][0-9])
  basic_machine=hppa1.0-hp
  ;;
+ hppa-next)
+ os=-nextstep3
+ ;;
  hppaosf)
  basic_machine=hppa1.1-hp
  os=-osf
@@ -752,26 +755,26 @@ case $basic_machine in
  basic_machine=i370-ibm
  ;;
  i*86v32)
- basic_machine=`echo "$1" | sed -e 's/86.*/86-pc/'`
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
  os=-sysv32
  ;;
  i*86v4*)
- basic_machine=`echo "$1" | sed -e 's/86.*/86-pc/'`
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
  os=-sysv4
  ;;
  i*86v)
- basic_machine=`echo "$1" | sed -e 's/86.*/86-pc/'`
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
  os=-sysv
  ;;
  i*86sol2)
- basic_machine=`echo "$1" | sed -e 's/86.*/86-pc/'`
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
  os=-solaris2
  ;;
  i386mach)
  basic_machine=i386-mach
  os=-mach
  ;;
- vsta)
+ i386-vsta | vsta)
  basic_machine=i386-unknown
  os=-vsta
  ;;
@@ -790,16 +793,19 @@ case $basic_machine in
  os=-sysv
  ;;
  leon-*|leon[3-9]-*)
- basic_machine=sparc-`echo "$basic_machine" | sed 's/-.*//'`
+ basic_machine=sparc-`echo $basic_machine | sed 's/-.*//'`
  ;;
  m68knommu)
  basic_machine=m68k-unknown
  os=-linux
  ;;
  m68knommu-*)
- basic_machine=m68k-`echo "$basic_machine" | sed 's/^[^-]*-//'`
+ basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'`
  os=-linux
  ;;
+ m88k-omron*)
+ basic_machine=m88k-omron
+ ;;
  magnum | m3230)
  basic_machine=mips-mips
  os=-sysv
@@ -831,10 +837,10 @@ case $basic_machine in
  os=-mint
  ;;
  mips3*-*)
- basic_machine=`echo "$basic_machine" | sed -e 's/mips3/mips64/'`
+ basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`
  ;;
  mips3*)
- basic_machine=`echo "$basic_machine" | sed -e 's/mips3/mips64/'`-unknown
+ basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
  ;;
  monitor)
  basic_machine=m68k-rom68k
@@ -853,7 +859,7 @@ case $basic_machine in
  os=-msdos
  ;;
  ms1-*)
- basic_machine=`echo "$basic_machine" | sed -e 's/ms1-/mt-/'`
+ basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'`
  ;;
  msys)
  basic_machine=i686-pc
@@ -895,7 +901,7 @@ case $basic_machine in
  basic_machine=v70-nec
  os=-sysv
  ;;
- next | m*-next)
+ next | m*-next )
  basic_machine=m68k-next
  case $os in
     -nextstep* )
@@ -940,12 +946,6 @@ case $basic_machine in
  nsr-tandem)
  basic_machine=nsr-tandem
  ;;
- nsv-tandem)
- basic_machine=nsv-tandem
- ;;
- nsx-tandem)
- basic_machine=nsx-tandem
- ;;
  op50n-* | op60c-*)
  basic_machine=hppa1.1-oki
  os=-proelf
@@ -978,7 +978,7 @@ case $basic_machine in
  os=-linux
  ;;
  parisc-*)
- basic_machine=hppa-`echo "$basic_machine" | sed 's/^[^-]*-//'`
+ basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'`
  os=-linux
  ;;
  pbd)
@@ -994,7 +994,7 @@ case $basic_machine in
  basic_machine=i386-pc
  ;;
  pc98-*)
- basic_machine=i386-`echo "$basic_machine" | sed 's/^[^-]*-//'`
+ basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'`
  ;;
  pentium | p5 | k5 | k6 | nexgen | viac3)
  basic_machine=i586-pc
@@ -1009,16 +1009,16 @@ case $basic_machine in
  basic_machine=i786-pc
  ;;
  pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*)
- basic_machine=i586-`echo "$basic_machine" | sed 's/^[^-]*-//'`
+ basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`
  ;;
  pentiumpro-* | p6-* | 6x86-* | athlon-*)
- basic_machine=i686-`echo "$basic_machine" | sed 's/^[^-]*-//'`
+ basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
  ;;
  pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*)
- basic_machine=i686-`echo "$basic_machine" | sed 's/^[^-]*-//'`
+ basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
  ;;
  pentium4-*)
- basic_machine=i786-`echo "$basic_machine" | sed 's/^[^-]*-//'`
+ basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'`
  ;;
  pn)
  basic_machine=pn-gould
@@ -1028,23 +1028,23 @@ case $basic_machine in
  ppc | ppcbe) basic_machine=powerpc-unknown
  ;;
  ppc-* | ppcbe-*)
- basic_machine=powerpc-`echo "$basic_machine" | sed 's/^[^-]*-//'`
+ basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
  ;;
  ppcle | powerpclittle)
  basic_machine=powerpcle-unknown
  ;;
  ppcle-* | powerpclittle-*)
- basic_machine=powerpcle-`echo "$basic_machine" | sed 's/^[^-]*-//'`
+ basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'`
  ;;
  ppc64) basic_machine=powerpc64-unknown
  ;;
- ppc64-*) basic_machine=powerpc64-`echo "$basic_machine" | sed 's/^[^-]*-//'`
+ ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'`
  ;;
  ppc64le | powerpc64little)
  basic_machine=powerpc64le-unknown
  ;;
  ppc64le-* | powerpc64little-*)
- basic_machine=powerpc64le-`echo "$basic_machine" | sed 's/^[^-]*-//'`
+ basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'`
  ;;
  ps2)
  basic_machine=i386-ibm
@@ -1098,10 +1098,17 @@ case $basic_machine in
  sequent)
  basic_machine=i386-sequent
  ;;
+ sh)
+ basic_machine=sh-hitachi
+ os=-hms
+ ;;
  sh5el)
  basic_machine=sh5le-unknown
  ;;
- simso-wrs)
+ sh64)
+ basic_machine=sh64-unknown
+ ;;
+ sparclite-wrs | simso-wrs)
  basic_machine=sparclite-wrs
  os=-vxworks
  ;;
@@ -1120,7 +1127,7 @@ case $basic_machine in
  os=-sysv4
  ;;
  strongarm-* | thumb-*)
- basic_machine=arm-`echo "$basic_machine" | sed 's/^[^-]*-//'`
+ basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'`
  ;;
  sun2)
  basic_machine=m68000-sun
@@ -1242,9 +1249,6 @@ case $basic_machine in
  basic_machine=hppa1.1-winbond
  os=-proelf
  ;;
- x64)
- basic_machine=x86_64-pc
- ;;
  xbox)
  basic_machine=i686-pc
  os=-mingw32
@@ -1253,12 +1257,20 @@ case $basic_machine in
  basic_machine=xps100-honeywell
  ;;
  xscale-* | xscalee[bl]-*)
- basic_machine=`echo "$basic_machine" | sed 's/^xscale/arm/'`
+ basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'`
  ;;
  ymp)
  basic_machine=ymp-cray
  os=-unicos
  ;;
+ z8k-*-coff)
+ basic_machine=z8k-unknown
+ os=-sim
+ ;;
+ z80-*-coff)
+ basic_machine=z80-unknown
+ os=-sim
+ ;;
  none)
  basic_machine=none-none
  os=-none
@@ -1287,6 +1299,10 @@ case $basic_machine in
  vax)
  basic_machine=vax-dec
  ;;
+ pdp10)
+ # there are many clones, so DEC is not a safe bet
+ basic_machine=pdp10-unknown
+ ;;
  pdp11)
  basic_machine=pdp11-dec
  ;;
@@ -1296,6 +1312,9 @@ case $basic_machine in
  sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele)
  basic_machine=sh-unknown
  ;;
+ sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v)
+ basic_machine=sparc-sun
+ ;;
  cydra)
  basic_machine=cydra-cydrome
  ;;
@@ -1315,7 +1334,7 @@ case $basic_machine in
  # Make sure to match an already-canonicalized machine name.
  ;;
  *)
- echo Invalid configuration \`"$1"\': machine \`"$basic_machine"\' not recognized 1>&2
+ echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
  exit 1
  ;;
 esac
@@ -1323,10 +1342,10 @@ esac
 # Here we canonicalize certain aliases for manufacturers.
 case $basic_machine in
  *-digital*)
- basic_machine=`echo "$basic_machine" | sed 's/digital.*/dec/'`
+ basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'`
  ;;
  *-commodore*)
- basic_machine=`echo "$basic_machine" | sed 's/commodore.*/cbm/'`
+ basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'`
  ;;
  *)
  ;;
@@ -1337,8 +1356,8 @@ esac
 if [ x"$os" != x"" ]
 then
 case $os in
- # First match some system type aliases that might get confused
- # with valid system types.
+ # First match some system type aliases
+ # that might get confused with valid system types.
  # -solaris* is a basic system type, with this one exception.
  -auroraux)
  os=-auroraux
@@ -1349,19 +1368,18 @@ case $os in
  -solaris)
  os=-solaris2
  ;;
+ -svr4*)
+ os=-sysv4
+ ;;
  -unixware*)
  os=-sysv4.2uw
  ;;
  -gnu/linux*)
  os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'`
  ;;
- # es1800 is here to avoid being matched by es* (a different OS)
- -es1800*)
- os=-ose
- ;;
- # Now accept the basic system types.
+ # First accept the basic system types.
  # The portable systems comes first.
- # Each alternative MUST end in a * to match a version number.
+ # Each alternative MUST END IN A *, to match a version number.
  # -sysv* is not here because it comes later, after sysvr4.
  -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
       | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\
@@ -1371,26 +1389,25 @@ case $os in
       | -aos* | -aros* | -cloudabi* | -sortix* \
       | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
       | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
-      | -hiux* | -knetbsd* | -mirbsd* | -netbsd* \
+      | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \
       | -bitrig* | -openbsd* | -solidbsd* | -libertybsd* \
       | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \
       | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
       | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
       | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
-      | -chorusos* | -chorusrdb* | -cegcc* | -glidix* \
+      | -chorusos* | -chorusrdb* | -cegcc* \
       | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
       | -midipix* | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \
       | -linux-newlib* | -linux-musl* | -linux-uclibc* \
       | -uxpv* | -beos* | -mpeix* | -udk* | -moxiebox* \
-      | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* \
+      | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
       | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
       | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
       | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
-      | -morphos* | -superux* | -rtmk* | -windiss* \
+      | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
       | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
       | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* \
-      | -onefs* | -tirtos* | -phoenix* | -fuchsia* | -redox* | -bme* \
-      | -midnightbsd*)
+      | -onefs* | -tirtos* | -phoenix*)
  # Remember, each alternative MUST END IN *, to match a version number.
  ;;
  -qnx*)
@@ -1407,12 +1424,12 @@ case $os in
  -nto*)
  os=`echo $os | sed -e 's|nto|nto-qnx|'`
  ;;
- -sim | -xray | -os68k* | -v88r* \
-      | -windows* | -osx | -abug | -netware* | -os9* \
+ -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \
+      | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \
       | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*)
  ;;
  -mac*)
- os=`echo "$os" | sed -e 's|mac|macos|'`
+ os=`echo $os | sed -e 's|mac|macos|'`
  ;;
  -linux-dietlibc)
  os=-linux-dietlibc
@@ -1421,10 +1438,10 @@ case $os in
  os=`echo $os | sed -e 's|linux|linux-gnu|'`
  ;;
  -sunos5*)
- os=`echo "$os" | sed -e 's|sunos5|solaris2|'`
+ os=`echo $os | sed -e 's|sunos5|solaris2|'`
  ;;
  -sunos6*)
- os=`echo "$os" | sed -e 's|sunos6|solaris3|'`
+ os=`echo $os | sed -e 's|sunos6|solaris3|'`
  ;;
  -opened*)
  os=-openedition
@@ -1435,6 +1452,12 @@ case $os in
  -wince*)
  os=-wince
  ;;
+ -osfrose*)
+ os=-osfrose
+ ;;
+ -osf*)
+ os=-osf
+ ;;
  -utek*)
  os=-bsd
  ;;
@@ -1459,7 +1482,7 @@ case $os in
  -nova*)
  os=-rtmk-nova
  ;;
- -ns2)
+ -ns2 )
  os=-nextstep2
  ;;
  -nsk*)
@@ -1481,7 +1504,7 @@ case $os in
  -oss*)
  os=-sysv3
  ;;
- -svr4*)
+ -svr4)
  os=-sysv4
  ;;
  -svr3)
@@ -1496,28 +1519,24 @@ case $os in
  -ose*)
  os=-ose
  ;;
+ -es1800*)
+ os=-ose
+ ;;
+ -xenix)
+ os=-xenix
+ ;;
  -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
  os=-mint
  ;;
+ -aros*)
+ os=-aros
+ ;;
  -zvmoe)
  os=-zvmoe
  ;;
  -dicos*)
  os=-dicos
  ;;
- -pikeos*)
- # Until real need of OS specific support for
- # particular features comes up, bare metal
- # configurations are quite functional.
- case $basic_machine in
-    arm*)
- os=-eabi
- ;;
-    *)
- os=-elf
- ;;
- esac
- ;;
  -nacl*)
  ;;
  -ios)
@@ -1527,7 +1546,7 @@ case $os in
  *)
  # Get rid of the `-' at the beginning of $os.
  os=`echo $os | sed 's/[^-]*-//'`
- echo Invalid configuration \`"$1"\': system \`"$os"\' not recognized 1>&2
+ echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2
  exit 1
  ;;
 esac
@@ -1617,12 +1636,12 @@ case $basic_machine in
  sparc-* | *-sun)
  os=-sunos4.1.1
  ;;
- pru-*)
- os=-elf
- ;;
  *-be)
  os=-beos
  ;;
+ *-haiku)
+ os=-haiku
+ ;;
  *-ibm)
  os=-aix
  ;;
@@ -1662,7 +1681,7 @@ case $basic_machine in
  m88k-omron*)
  os=-luna
  ;;
- *-next)
+ *-next )
  os=-nextstep
  ;;
  *-sequent)
@@ -1677,6 +1696,9 @@ case $basic_machine in
  i370-*)
  os=-mvs
  ;;
+ *-next)
+ os=-nextstep3
+ ;;
  *-gould)
  os=-sysv
  ;;
@@ -1786,15 +1808,15 @@ case $basic_machine in
  vendor=stratus
  ;;
  esac
- basic_machine=`echo "$basic_machine" | sed "s/unknown/$vendor/"`
+ basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"`
  ;;
 esac
 
-echo "$basic_machine$os"
+echo $basic_machine$os
 exit
 
 # Local variables:
-# eval: (add-hook 'write-file-functions 'time-stamp)
+# eval: (add-hook 'write-file-hooks 'time-stamp)
 # time-stamp-start: "timestamp='"
 # time-stamp-format: "%:y-%02m-%02d"
 # time-stamp-end: "'"
Index: configure
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/configure,v
retrieving revision 1.36
diff -u -p -r1.36 configure
--- configure 18 Dec 2019 11:04:13 -0000 1.36
+++ configure 15 Mar 2020 16:31:04 -0000
@@ -1,6 +1,6 @@
 #! /bin/sh
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for unbound 1.9.6.
+# Generated by GNU Autoconf 2.69 for unbound 1.10.0.
 #
 # Report bugs to <[hidden email] or https://github.com/NLnetLabs/unbound/issues>.
 #
@@ -591,8 +591,8 @@ MAKEFLAGS=
 # Identity of this package.
 PACKAGE_NAME='unbound'
 PACKAGE_TARNAME='unbound'
-PACKAGE_VERSION='1.9.6'
-PACKAGE_STRING='unbound 1.9.6'
+PACKAGE_VERSION='1.10.0'
+PACKAGE_STRING='unbound 1.10.0'
 PACKAGE_BUGREPORT='[hidden email] or https://github.com/NLnetLabs/unbound/issues'
 PACKAGE_URL=''
 
@@ -673,8 +673,10 @@ UNBOUND_EVENT_UNINSTALL
 UNBOUND_EVENT_INSTALL
 SUBNET_HEADER
 SUBNET_OBJ
+PC_LIBBSD_DEPENDENCY
 SSLLIB
 HAVE_SSL
+PC_CRYPTO_DEPENDENCY
 CONFIG_DATE
 NETBSD_LINTFLAGS
 PYUNBOUND_UNINSTALL
@@ -801,7 +803,6 @@ infodir
 docdir
 oldincludedir
 includedir
-runstatedir
 localstatedir
 sharedstatedir
 sysconfdir
@@ -860,6 +861,7 @@ enable_swig_version_check
 with_nss
 with_nettle
 with_ssl
+with_libbsd
 enable_sha1
 enable_sha2
 enable_subnet
@@ -948,7 +950,6 @@ datadir='${datarootdir}'
 sysconfdir='${prefix}/etc'
 sharedstatedir='${prefix}/com'
 localstatedir='${prefix}/var'
-runstatedir='${localstatedir}/run'
 includedir='${prefix}/include'
 oldincludedir='/usr/include'
 docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
@@ -1201,15 +1202,6 @@ do
   | -silent | --silent | --silen | --sile | --sil)
     silent=yes ;;
 
-  -runstatedir | --runstatedir | --runstatedi | --runstated \
-  | --runstate | --runstat | --runsta | --runst | --runs \
-  | --run | --ru | --r)
-    ac_prev=runstatedir ;;
-  -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \
-  | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \
-  | --run=* | --ru=* | --r=*)
-    runstatedir=$ac_optarg ;;
-
   -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
     ac_prev=sbindir ;;
   -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
@@ -1347,7 +1339,7 @@ fi
 for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \
  datadir sysconfdir sharedstatedir localstatedir includedir \
  oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
- libdir localedir mandir runstatedir
+ libdir localedir mandir
 do
   eval ac_val=\$$ac_var
   # Remove trailing slashes.
@@ -1460,7 +1452,7 @@ if test "$ac_init_help" = "long"; then
   # Omit some internal or obsolete options to make the list less imposing.
   # This message is too long to be a string in the A/UX 3.1 sh.
   cat <<_ACEOF
-\`configure' configures unbound 1.9.6 to adapt to many kinds of systems.
+\`configure' configures unbound 1.10.0 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1500,7 +1492,6 @@ Fine tuning of the installation director
   --sysconfdir=DIR        read-only single-machine data [PREFIX/etc]
   --sharedstatedir=DIR    modifiable architecture-independent data [PREFIX/com]
   --localstatedir=DIR     modifiable single-machine data [PREFIX/var]
-  --runstatedir=DIR       modifiable per-process data [LOCALSTATEDIR/run]
   --libdir=DIR            object code libraries [EPREFIX/lib]
   --includedir=DIR        C header files [PREFIX/include]
   --oldincludedir=DIR     C header files for non-gcc [/usr/include]
@@ -1526,7 +1517,7 @@ fi
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of unbound 1.9.6:";;
+     short | recursive ) echo "Configuration of unbound 1.10.0:";;
    esac
   cat <<\_ACEOF
 
@@ -1632,6 +1623,7 @@ Optional Packages:
   --with-ssl=pathname     enable SSL (will check /usr/local/ssl /usr/lib/ssl
                           /usr/ssl /usr/pkg /usr/local /opt/local /usr/sfw
                           /usr)
+  --with-libbsd           Use portable libbsd functions
   --with-libevent=pathname
                           use libevent (will check /usr/local /opt/local
                           /usr/lib /usr/pkg /usr/sfw /usr or you can specify
@@ -1748,7 +1740,7 @@ fi
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-unbound configure 1.9.6
+unbound configure 1.10.0
 generated by GNU Autoconf 2.69
 
 Copyright (C) 2012 Free Software Foundation, Inc.
@@ -2457,7 +2449,7 @@ cat >config.log <<_ACEOF
 This file contains any messages produced by compilers while
 running configure, to aid debugging if configure makes a mistake.
 
-It was created by unbound $as_me 1.9.6, which was
+It was created by unbound $as_me 1.10.0, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   $ $0 $@
@@ -2807,13 +2799,13 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
 
 UNBOUND_VERSION_MAJOR=1
 
-UNBOUND_VERSION_MINOR=9
+UNBOUND_VERSION_MINOR=10
 
-UNBOUND_VERSION_MICRO=6
+UNBOUND_VERSION_MICRO=0
 
 
 LIBUNBOUND_CURRENT=9
-LIBUNBOUND_REVISION=6
+LIBUNBOUND_REVISION=7
 LIBUNBOUND_AGE=1
 # 1.0.0 had 0:12:0
 # 1.0.1 had 0:13:0
@@ -2887,6 +2879,7 @@ LIBUNBOUND_AGE=1
 # 1.9.4 had 9:4:1
 # 1.9.5 had 9:5:1
 # 1.9.6 had 9:6:1
+# 1.10.0 had 9:7:1
 
 #   Current  -- the number of the binary API that we're implementing
 #   Revision -- which iteration of the implementation of the binary
@@ -8061,7 +8054,7 @@ linux* | k*bsd*-gnu | kopensolaris*-gnu
   lt_cv_deplibs_check_method=pass_all
   ;;
 
-netbsd* | netbsdelf*-gnu)
+netbsd*)
   if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then
     lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$'
   else
@@ -11526,9 +11519,6 @@ $as_echo_n "checking whether the $compil
   openbsd* | bitrig*)
     with_gnu_ld=no
     ;;
-  linux* | k*bsd*-gnu | gnu*)
-    link_all_deplibs=no
-    ;;
   esac
 
   ld_shlibs=yes
@@ -11783,7 +11773,7 @@ _LT_EOF
       fi
       ;;
 
-    netbsd* | netbsdelf*-gnu)
+    netbsd*)
       if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
  archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib'
  wlarc=
@@ -12453,7 +12443,6 @@ $as_echo "$lt_cv_irix_exported_symbol" >
  if test yes = "$lt_cv_irix_exported_symbol"; then
           archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations $wl-exports_file $wl$export_symbols -o $lib'
  fi
- link_all_deplibs=no
       else
  archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib'
  archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -exports_file $export_symbols -o $lib'
@@ -12475,7 +12464,7 @@ $as_echo "$lt_cv_irix_exported_symbol" >
       esac
       ;;
 
-    netbsd* | netbsdelf*-gnu)
+    netbsd*)
       if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
  archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'  # a.out
       else
@@ -13570,6 +13559,9 @@ fi
   # before this can be enabled.
   hardcode_into_libs=yes
 
+  # Add ABI-specific directories to the system library path.
+  sys_lib_dlsearch_path_spec="/lib64 /usr/lib64 /lib /usr/lib"
+
   # Ideally, we could use ldconfig to report *all* directores which are
   # searched for libraries, however this is still not possible.  Aside from not
   # being certain /sbin/ldconfig is available, command
@@ -13578,7 +13570,7 @@ fi
   # appending ld.so.conf contents (and includes) to the search path.
   if test -f /etc/ld.so.conf; then
     lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '`
-    sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra"
+    sys_lib_dlsearch_path_spec="$sys_lib_dlsearch_path_spec $lt_ld_extra"
   fi
 
   # We used to test for /lib/ld.so.1 and disable shared libraries on
@@ -13590,18 +13582,6 @@ fi
   dynamic_linker='GNU/Linux ld.so'
   ;;
 
-netbsdelf*-gnu)
-  version_type=linux
-  need_lib_prefix=no
-  need_version=no
-  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
-  soname_spec='${libname}${release}${shared_ext}$major'
-  shlibpath_var=LD_LIBRARY_PATH
-  shlibpath_overrides_runpath=no
-  hardcode_into_libs=yes
-  dynamic_linker='NetBSD ld.elf_so'
-  ;;
-
 netbsd*)
   version_type=sunos
   need_lib_prefix=no
@@ -15668,7 +15648,7 @@ else
     We can't simply define LARGE_OFF_T to be 9223372036854775807,
     since some C++ compilers masquerading as C compilers
     incorrectly reject 9223372036854775807.  */
-#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
+#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
   int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
        && LARGE_OFF_T % 2147483647 == 1)
       ? 1 : -1];
@@ -15714,7 +15694,7 @@ else
     We can't simply define LARGE_OFF_T to be 9223372036854775807,
     since some C++ compilers masquerading as C compilers
     incorrectly reject 9223372036854775807.  */
-#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
+#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
   int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
        && LARGE_OFF_T % 2147483647 == 1)
       ? 1 : -1];
@@ -15738,7 +15718,7 @@ rm -f core conftest.err conftest.$ac_obj
     We can't simply define LARGE_OFF_T to be 9223372036854775807,
     since some C++ compilers masquerading as C compilers
     incorrectly reject 9223372036854775807.  */
-#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
+#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
   int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
        && LARGE_OFF_T % 2147483647 == 1)
       ? 1 : -1];
@@ -15783,7 +15763,7 @@ else
     We can't simply define LARGE_OFF_T to be 9223372036854775807,
     since some C++ compilers masquerading as C compilers
     incorrectly reject 9223372036854775807.  */
-#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
+#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
   int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
        && LARGE_OFF_T % 2147483647 == 1)
       ? 1 : -1];
@@ -15807,7 +15787,7 @@ rm -f core conftest.err conftest.$ac_obj
     We can't simply define LARGE_OFF_T to be 9223372036854775807,
     since some C++ compilers masquerading as C compilers
     incorrectly reject 9223372036854775807.  */
-#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
+#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
   int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
        && LARGE_OFF_T % 2147483647 == 1)
       ? 1 : -1];
@@ -17783,6 +17763,8 @@ $as_echo "#define HAVE_NSS 1" >>confdefs
  fi
         LIBS="$LIBS -lnss3 -lnspr4"
  SSLLIB=""
+ PC_CRYPTO_DEPENDENCY="nss nspr"
+
 
 
 fi
@@ -17826,6 +17808,8 @@ done
  fi
         LIBS="$LIBS -lhogweed -lnettle -lgmp"
  SSLLIB=""
+ PC_CRYPTO_DEPENDENCY="hogweed nettle"
+
 
 
 fi
@@ -18176,6 +18160,9 @@ rm -f core conftest.err conftest.$ac_obj
     conftest$ac_exeext conftest.$ac_ext
 SSLLIB="-lssl"
 
+PC_CRYPTO_DEPENDENCY="libcrypto libssl"
+
+
 # check if -lcrypt32 is needed because CAPIENG needs that. (on windows)
 BAKLIBS="$LIBS"
 LIBS="-lssl $LIBS"
@@ -18466,6 +18453,96 @@ fi
 fi
 
 
+# libbsd
+
+# Check whether --with-libbsd was given.
+if test "${with_libbsd+set}" = set; then :
+  withval=$with_libbsd;
+ for ac_header in bsd/string.h bsd/stdlib.h
+do :
+  as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default
+"
+if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
+  cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+ if test "x$ac_cv_header_bsd_string_h" = xyes -a "x$ac_cv_header_bsd_stdlib_h" = xyes; then
+ for func in strlcpy strlcat arc4random arc4random_uniform reallocarray; do
+ as_ac_Search=`$as_echo "ac_cv_search_$func" | $as_tr_sh`
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing $func" >&5
+$as_echo_n "checking for library containing $func... " >&6; }
+if eval \${$as_ac_Search+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_func_search_save_LIBS=$LIBS
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char $func ();
+int
+main ()
+{
+return $func ();
+  ;
+  return 0;
+}
+_ACEOF
+for ac_lib in '' bsd; do
+  if test -z "$ac_lib"; then
+    ac_res="none required"
+  else
+    ac_res=-l$ac_lib
+    LIBS="-l$ac_lib  $ac_func_search_save_LIBS"
+  fi
+  if ac_fn_c_try_link "$LINENO"; then :
+  eval "$as_ac_Search=\$ac_res"
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext
+  if eval \${$as_ac_Search+:} false; then :
+  break
+fi
+done
+if eval \${$as_ac_Search+:} false; then :
+
+else
+  eval "$as_ac_Search=no"
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+eval ac_res=\$$as_ac_Search
+       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+eval ac_res=\$$as_ac_Search
+if test "$ac_res" != no; then :
+  test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+
+$as_echo "#define HAVE_LIBBSD 1" >>confdefs.h
+
+ PC_LIBBSD_DEPENDENCY=libbsd
+
+
+fi
+
+ done
+ fi
+
+fi
+
 
 # Check whether --enable-sha1 was given.
 if test "${enable_sha1+set}" = set; then :
@@ -18769,9 +18846,7 @@ fi
 
 use_dsa="no"
 case "$enable_dsa" in
-    no)
-      ;;
-    *)
+    yes)
       # detect if DSA is supported, and turn it off if not.
       if test $USE_NSS = "no" -a $USE_NETTLE = "no"; then
       ac_fn_c_check_func "$LINENO" "DSA_SIG_new" "ac_cv_func_DSA_SIG_new"
@@ -18824,6 +18899,10 @@ _ACEOF
 
       fi
       ;;
+    *)
+      # disable dsa by default, RFC 8624 section 3.1, validators MUST NOT
+      # support DSA for DNSSEC Validation.
+      ;;
 esac
 
 # Check whether --enable-ed25519 was given.
@@ -19948,6 +20027,75 @@ _ACEOF
 
 fi
 
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for htobe64" >&5
+$as_echo_n "checking for htobe64... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#include <stdio.h>
+#ifdef HAVE_ENDIAN_H
+#  include <endian.h>
+#endif
+#ifdef HAVE_SYS_ENDIAN_H
+#  include <sys/endian.h>
+#endif
+
+int
+main ()
+{
+unsigned long long x = htobe64(0); printf("%u", (unsigned)x);
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+$as_echo "#define HAVE_HTOBE64 1" >>confdefs.h
+
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for be64toh" >&5
+$as_echo_n "checking for be64toh... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+#include <stdio.h>
+#ifdef HAVE_ENDIAN_H
+#  include <endian.h>
+#endif
+#ifdef HAVE_SYS_ENDIAN_H
+#  include <sys/endian.h>
+#endif
+
+int
+main ()
+{
+unsigned long long x = be64toh(0); printf("%u", (unsigned)x);
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+$as_echo "#define HAVE_BE64TOH 1" >>confdefs.h
+
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing setusercontext" >&5
 $as_echo_n "checking for library containing setusercontext... " >&6; }
 if ${ac_cv_search_setusercontext+:} false; then :
@@ -21450,7 +21598,7 @@ _ACEOF
 
 
 
-version=1.9.6
+version=1.10.0
 
 date=`date +'%b %e, %Y'`
 
@@ -21969,7 +22117,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_wri
 # report actual input values of CONFIG_FILES etc. instead of their
 # values after options handling.
 ac_log="
-This file was extended by unbound $as_me 1.9.6, which was
+This file was extended by unbound $as_me 1.10.0, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -22035,7 +22183,7 @@ _ACEOF
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
 ac_cs_version="\\
-unbound config.status 1.9.6
+unbound config.status 1.10.0
 configured by $0, generated by GNU Autoconf 2.69,
   with options \\"\$ac_cs_config\\"
 
@@ -23024,6 +23172,7 @@ $as_echo "$as_me: executing $ac_file com
     cat <<_LT_EOF >> "$cfgfile"
 #! $SHELL
 # Generated automatically by $as_me ($PACKAGE) $VERSION
+# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
 # NOTE: Changes made to this file will be lost: look at ltmain.sh.
 
 # Provide generalized library-building support services.
Index: configure.ac
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/configure.ac,v
retrieving revision 1.36
diff -u -p -r1.36 configure.ac
--- configure.ac 18 Dec 2019 11:04:13 -0000 1.36
+++ configure.ac 15 Mar 2020 16:31:04 -0000
@@ -10,15 +10,15 @@ sinclude(dnscrypt/dnscrypt.m4)
 
 # must be numbers. ac_defun because of later processing
 m4_define([VERSION_MAJOR],[1])
-m4_define([VERSION_MINOR],[9])
-m4_define([VERSION_MICRO],[6])
+m4_define([VERSION_MINOR],[10])
+m4_define([VERSION_MICRO],[0])
 AC_INIT(unbound, m4_defn([VERSION_MAJOR]).m4_defn([VERSION_MINOR]).m4_defn([VERSION_MICRO]), [hidden email] or https://github.com/NLnetLabs/unbound/issues, unbound)
 AC_SUBST(UNBOUND_VERSION_MAJOR, [VERSION_MAJOR])
 AC_SUBST(UNBOUND_VERSION_MINOR, [VERSION_MINOR])
 AC_SUBST(UNBOUND_VERSION_MICRO, [VERSION_MICRO])
 
 LIBUNBOUND_CURRENT=9
-LIBUNBOUND_REVISION=6
+LIBUNBOUND_REVISION=7
 LIBUNBOUND_AGE=1
 # 1.0.0 had 0:12:0
 # 1.0.1 had 0:13:0
@@ -92,6 +92,7 @@ LIBUNBOUND_AGE=1
 # 1.9.4 had 9:4:1
 # 1.9.5 had 9:5:1
 # 1.9.6 had 9:6:1
+# 1.10.0 had 9:7:1
 
 #   Current  -- the number of the binary API that we're implementing
 #   Revision -- which iteration of the implementation of the binary
@@ -760,6 +761,8 @@ AC_ARG_WITH([nss], AC_HELP_STRING([--wit
  fi
         LIBS="$LIBS -lnss3 -lnspr4"
  SSLLIB=""
+ PC_CRYPTO_DEPENDENCY="nss nspr"
+ AC_SUBST(PC_CRYPTO_DEPENDENCY)
  ]
 )
 
@@ -780,6 +783,8 @@ AC_ARG_WITH([nettle], AC_HELP_STRING([--
  fi
         LIBS="$LIBS -lhogweed -lnettle -lgmp"
  SSLLIB=""
+ PC_CRYPTO_DEPENDENCY="hogweed nettle"
+ AC_SUBST(PC_CRYPTO_DEPENDENCY)
  ]
 )
 
@@ -789,6 +794,9 @@ ACX_WITH_SSL
 ACX_LIB_SSL
 SSLLIB="-lssl"
 
+PC_CRYPTO_DEPENDENCY="libcrypto libssl"
+AC_SUBST(PC_CRYPTO_DEPENDENCY)
+
 # check if -lcrypt32 is needed because CAPIENG needs that. (on windows)
 BAKLIBS="$LIBS"
 LIBS="-lssl $LIBS"
@@ -880,6 +888,19 @@ fi
 fi
 AC_SUBST(SSLLIB)
 
+# libbsd
+AC_ARG_WITH([libbsd], AC_HELP_STRING([--with-libbsd], [Use portable libbsd functions]), [
+ AC_CHECK_HEADERS([bsd/string.h bsd/stdlib.h],,, [AC_INCLUDES_DEFAULT])
+ if test "x$ac_cv_header_bsd_string_h" = xyes -a "x$ac_cv_header_bsd_stdlib_h" = xyes; then
+ for func in strlcpy strlcat arc4random arc4random_uniform reallocarray; do
+ AC_SEARCH_LIBS([$func], [bsd], [
+ AC_DEFINE(HAVE_LIBBSD, 1, [Use portable libbsd functions])
+ PC_LIBBSD_DEPENDENCY=libbsd
+ AC_SUBST(PC_LIBBSD_DEPENDENCY)
+ ])
+ done
+ fi
+])
 
 AC_ARG_ENABLE(sha1, AC_HELP_STRING([--disable-sha1], [Disable SHA1 RRSIG support, does not disable nsec3 support]))
 case "$enable_sha1" in
@@ -1064,9 +1085,7 @@ esac
 AC_ARG_ENABLE(dsa, AC_HELP_STRING([--disable-dsa], [Disable DSA support]))
 use_dsa="no"
 case "$enable_dsa" in
-    no)
-      ;;
-    *)
+    yes)
       # detect if DSA is supported, and turn it off if not.
       if test $USE_NSS = "no" -a $USE_NETTLE = "no"; then
       AC_CHECK_FUNC(DSA_SIG_new, [
@@ -1097,6 +1116,10 @@ AC_INCLUDES_DEFAULT
       AC_DEFINE_UNQUOTED([USE_DSA], [1], [Define this to enable DSA support.])
       fi
       ;;
+    *)
+      # disable dsa by default, RFC 8624 section 3.1, validators MUST NOT
+      # support DSA for DNSSEC Validation.
+      ;;
 esac
 
 AC_ARG_ENABLE(ed25519, AC_HELP_STRING([--disable-ed25519], [Disable ED25519 support]))
@@ -1467,6 +1490,35 @@ AC_INCLUDES_DEFAULT
 #include <ws2tcpip.h>
 #endif
 ])
+
+AC_MSG_CHECKING([for htobe64])
+AC_LINK_IFELSE([AC_LANG_PROGRAM([
+#include <stdio.h>
+#ifdef HAVE_ENDIAN_H
+#  include <endian.h>
+#endif
+#ifdef HAVE_SYS_ENDIAN_H
+#  include <sys/endian.h>
+#endif
+], [unsigned long long x = htobe64(0); printf("%u", (unsigned)x);])],
+  AC_MSG_RESULT(yes)
+  AC_DEFINE(HAVE_HTOBE64, 1, [If we have htobe64]),
+  AC_MSG_RESULT(no))
+
+AC_MSG_CHECKING([for be64toh])
+AC_LINK_IFELSE([AC_LANG_PROGRAM([
+#include <stdio.h>
+#ifdef HAVE_ENDIAN_H
+#  include <endian.h>
+#endif
+#ifdef HAVE_SYS_ENDIAN_H
+#  include <sys/endian.h>
+#endif
+], [unsigned long long x = be64toh(0); printf("%u", (unsigned)x);])],
+  AC_MSG_RESULT(yes)
+  AC_DEFINE(HAVE_BE64TOH, 1, [If we have be64toh]),
+  AC_MSG_RESULT(no))
+
 AC_SEARCH_LIBS([setusercontext], [util])
 AC_CHECK_FUNCS([tzset sigprocmask fcntl getpwnam endpwent getrlimit setrlimit setsid chroot kill chown sleep usleep random srandom recvmsg sendmsg writev socketpair glob initgroups strftime localtime_r setusercontext _beginthreadex endservent endprotoent fsync shmget accept4])
 AC_CHECK_FUNCS([setresuid],,[AC_CHECK_FUNCS([setreuid])])
@@ -1943,6 +1995,11 @@ char *strptime(const char *s, const char
 
 #if !HAVE_DECL_REALLOCARRAY
 void *reallocarray(void *ptr, size_t nmemb, size_t size);
+#endif
+
+#ifdef HAVE_LIBBSD
+#include <bsd/string.h>
+#include <bsd/stdlib.h>
 #endif
 
 #ifdef HAVE_LIBRESSL
Index: install-sh
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/install-sh,v
retrieving revision 1.4
diff -u -p -r1.4 install-sh
--- install-sh 18 Dec 2019 11:04:13 -0000 1.4
+++ install-sh 15 Mar 2020 16:31:04 -0000
@@ -1,7 +1,7 @@
-#!/bin/sh
+#!/usr/bin/sh
 # install - install a program, script, or datafile
 
-scriptversion=2014-09-12.12; # UTC
+scriptversion=2013-12-25.23; # UTC
 
 # This originates from X11R5 (mit/util/scripts/install.sh), which was
 # later released in X11R6 (xc/config/util/install.sh) with the
@@ -324,41 +324,34 @@ do
             # is incompatible with FreeBSD 'install' when (umask & 300) != 0.
             ;;
           *)
-            # $RANDOM is not portable (e.g. dash);  use it when possible to
-            # lower collision chance
             tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
-            trap 'ret=$?; rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" 2>/dev/null; exit $ret' 0
+            trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0
 
-            # As "mkdir -p" follows symlinks and we work in /tmp possibly;  so
-            # create the $tmpdir first (and fail if unsuccessful) to make sure
-            # that nobody tries to guess the $tmpdir name.
             if (umask $mkdir_umask &&
-                $mkdirprog $mkdir_mode "$tmpdir" &&
-                exec $mkdirprog $mkdir_mode -p -- "$tmpdir/a/b") >/dev/null 2>&1
+                exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1
             then
               if test -z "$dir_arg" || {
                    # Check for POSIX incompatibilities with -m.
                    # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
                    # other-writable bit of parent directory when it shouldn't.
                    # FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
-                   test_tmpdir="$tmpdir/a"
-                   ls_ld_tmpdir=`ls -ld "$test_tmpdir"`
+                   ls_ld_tmpdir=`ls -ld "$tmpdir"`
                    case $ls_ld_tmpdir in
                      d????-?r-*) different_mode=700;;
                      d????-?--*) different_mode=755;;
                      *) false;;
                    esac &&
-                   $mkdirprog -m$different_mode -p -- "$test_tmpdir" && {
-                     ls_ld_tmpdir_1=`ls -ld "$test_tmpdir"`
+                   $mkdirprog -m$different_mode -p -- "$tmpdir" && {
+                     ls_ld_tmpdir_1=`ls -ld "$tmpdir"`
                      test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
                    }
                  }
               then posix_mkdir=:
               fi
-              rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir"
+              rmdir "$tmpdir/d" "$tmpdir"
             else
               # Remove any dirs left behind by ancient mkdir implementations.
-              rmdir ./$mkdir_mode ./-p ./-- "$tmpdir" 2>/dev/null
+              rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null
             fi
             trap '' 0;;
         esac;;
Index: cachedb/cachedb.c
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/cachedb/cachedb.c,v
retrieving revision 1.10
diff -u -p -r1.10 cachedb.c
--- cachedb/cachedb.c 18 Dec 2019 11:04:13 -0000 1.10
+++ cachedb/cachedb.c 15 Mar 2020 16:31:04 -0000
@@ -64,26 +64,26 @@
 #ifdef HAVE_SYS_ENDIAN_H
 #  include <sys/endian.h>
 #endif
-#ifdef HAVE_LIBKERN_OSBYTEORDER_H
-/* In practice this is specific to MacOS X.  We assume it doesn't have
-* htobe64/be64toh but has alternatives with a different name. */
-#  include <libkern/OSByteOrder.h>
-#  define htobe64(x) OSSwapHostToBigInt64(x)
-#  define be64toh(x) OSSwapBigToHostInt64(x)
-#endif
 
-/* Some compilers do not define __BYTE_ORDER__, like IBM XLC on AIX */
-#ifndef be64toh
-#if defined(__sun) || defined(_AIX)
-#  if __BIG_ENDIAN__
-#    define be64toh(n) (n)
-#    define htobe64(n) (n)
+#ifndef HAVE_HTOBE64
+#  ifdef HAVE_LIBKERN_OSBYTEORDER_H
+     /* In practice this is specific to MacOS X.  We assume it doesn't have
+      * htobe64/be64toh but has alternatives with a different name. */
+#    include <libkern/OSByteOrder.h>
+#    define htobe64(x) OSSwapHostToBigInt64(x)
+#    define be64toh(x) OSSwapBigToHostInt64(x)
 #  else
-#    define be64toh(n) (((uint64_t)htonl((n) & 0xFFFFFFFF) << 32) | htonl((n) >> 32))
-#    define htobe64(n) (((uint64_t)htonl((n) & 0xFFFFFFFF) << 32) | htonl((n) >> 32))
-#  endif
-#endif
-#endif /* be64toh */
+     /* not OSX */
+     /* Some compilers do not define __BYTE_ORDER__, like IBM XLC on AIX */
+#    if __BIG_ENDIAN__
+#      define be64toh(n) (n)
+#      define htobe64(n) (n)
+#    else
+#      define be64toh(n) (((uint64_t)htonl((n) & 0xFFFFFFFF) << 32) | htonl((n) >> 32))
+#      define htobe64(n) (((uint64_t)htonl((n) & 0xFFFFFFFF) << 32) | htonl((n) >> 32))
+#    endif /* _ENDIAN */
+#  endif /* HAVE_LIBKERN_OSBYTEORDER_H */
+#endif /* HAVE_BE64TOH */
 
 /** the unit test testframe for cachedb, its module state contains
  * a cache for a couple queries (in memory). */
@@ -218,10 +218,6 @@ static int
 cachedb_apply_cfg(struct cachedb_env* cachedb_env, struct config_file* cfg)
 {
  const char* backend_str = cfg->cachedb_backend;
-
- /* If unspecified we use the in-memory test DB. */
- if(!backend_str)
- backend_str = "testframe";
  cachedb_env->backend = cachedb_find_backend(backend_str);
  if(!cachedb_env->backend) {
  log_err("cachedb: cannot find backend name '%s'", backend_str);
@@ -259,6 +255,15 @@ cachedb_init(struct module_env* env, int
  return 0;
  }
  cachedb_env->enabled = 1;
+ if(env->cfg->serve_expired_reply_ttl)
+ log_warn(
+ "cachedb: serve-expired-reply-ttl is set but not working for data "
+ "originating from the external cache; 0 TLL is used for those.");
+ if(env->cfg->serve_expired_client_timeout)
+ log_warn(
+ "cachedb: serve-expired-client-timeout is set but not working for "
+ "data originating from the external cache; expired data are used "
+ "in the reply without first trying to refresh the data.");
  return 1;
 }
 
@@ -329,8 +334,7 @@ calc_hash(struct module_qstate* qstate,
  size_t clen = 0;
  uint8_t hash[CACHEDB_HASHSIZE/8];
  const char* hex = "0123456789ABCDEF";
- const char* secret = qstate->env->cfg->cachedb_secret ?
- qstate->env->cfg->cachedb_secret : "default";
+ const char* secret = qstate->env->cfg->cachedb_secret;
  size_t i;
 
  /* copy the hash info into the clear buffer */
@@ -433,8 +437,14 @@ good_expiry_and_qinfo(struct module_qsta
  &expiry, sizeof(expiry));
  expiry = be64toh(expiry);
 
+ /* Check if we are allowed to return expired entries:
+ * - serve_expired needs to be set
+ * - if SERVE_EXPIRED_TTL is set make sure that the record is not older
+ *   than that. */
  if((time_t)expiry < *qstate->env->now &&
- !qstate->env->cfg->serve_expired)
+ (!qstate->env->cfg->serve_expired ||
+ (SERVE_EXPIRED_TTL &&
+ *qstate->env->now - (time_t)expiry > SERVE_EXPIRED_TTL)))
  return 0;
 
  return 1;
@@ -445,15 +455,15 @@ good_expiry_and_qinfo(struct module_qsta
 static void
 packed_rrset_ttl_subtract(struct packed_rrset_data* data, time_t subtract)
 {
-        size_t i;
-        size_t total = data->count + data->rrsig_count;
+ size_t i;
+ size_t total = data->count + data->rrsig_count;
  if(subtract >= 0 && data->ttl > subtract)
  data->ttl -= subtract;
  else data->ttl = 0;
-        for(i=0; i<total; i++) {
+ for(i=0; i<total; i++) {
  if(subtract >= 0 && data->rr_ttl[i] > subtract)
-                 data->rr_ttl[i] -= subtract;
-                else data->rr_ttl[i] = 0;
+ data->rr_ttl[i] -= subtract;
+ else data->rr_ttl[i] = 0;
  }
 }
 
@@ -465,7 +475,8 @@ adjust_msg_ttl(struct dns_msg* msg, time
  size_t i;
  if(adjust >= 0 && msg->rep->ttl > adjust)
  msg->rep->ttl -= adjust;
- else msg->rep->ttl = 0;
+ else
+ msg->rep->ttl = 0;
  msg->rep->prefetch_ttl = PREFETCH_TTL_CALC(msg->rep->ttl);
  msg->rep->serve_expired_ttl = msg->rep->ttl + SERVE_EXPIRED_TTL;
 
@@ -673,7 +684,8 @@ cachedb_handle_query(struct module_qstat
  return;
  }
 
- /* lookup inside unbound's internal cache */
+ /* lookup inside unbound's internal cache.
+ * This does not look for expired entries. */
  if(cachedb_intcache_lookup(qstate)) {
  if(verbosity >= VERB_ALGO) {
  if(qstate->return_msg->rep)
@@ -681,8 +693,9 @@ cachedb_handle_query(struct module_qstat
  &qstate->return_msg->qinfo,
  qstate->return_msg->rep);
  else log_info("cachedb internal cache lookup: rcode %s",
- sldns_lookup_by_id(sldns_rcodes, qstate->return_rcode)?
- sldns_lookup_by_id(sldns_rcodes, qstate->return_rcode)->name:"??");
+ sldns_lookup_by_id(sldns_rcodes, qstate->return_rcode)
+ ?sldns_lookup_by_id(sldns_rcodes, qstate->return_rcode)->name
+ :"??");
  }
  /* we are done with the query */
  qstate->ext_state[id] = module_finished;
@@ -697,6 +710,19 @@ cachedb_handle_query(struct module_qstat
  qstate->return_msg->rep);
  /* store this result in internal cache */
  cachedb_intcache_store(qstate);
+ /* In case we have expired data but there is a client timer for expired
+ * answers, pass execution to next module in order to try updating the
+ * data first.
+ * TODO: this needs revisit. The expired data stored from cachedb has
+ * 0 TTL which is picked up by iterator later when looking in the cache.
+ * Document that ext cachedb does not work properly with
+ * serve_stale_reply_ttl yet. */
+ if(qstate->need_refetch && qstate->serve_expired_data &&
+ qstate->serve_expired_data->timer) {
+ qstate->return_msg = NULL;
+ qstate->ext_state[id] = module_wait_module;
+ return;
+ }
  /* we are done with the query */
  qstate->ext_state[id] = module_finished;
  return;
Index: daemon/daemon.c
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/daemon/daemon.c,v
retrieving revision 1.14
diff -u -p -r1.14 daemon.c
--- daemon/daemon.c 18 Dec 2019 11:04:13 -0000 1.14
+++ daemon/daemon.c 15 Mar 2020 16:31:04 -0000
@@ -617,7 +617,8 @@ daemon_fork(struct daemon* daemon)
  have_view_respip_cfg;
 
  /* read auth zonefiles */
- if(!auth_zones_apply_cfg(daemon->env->auth_zones, daemon->cfg, 1))
+ if(!auth_zones_apply_cfg(daemon->env->auth_zones, daemon->cfg, 1,
+ &daemon->use_rpz))
  fatal_exit("auth_zones could not be setup");
 
  /* setup modules */
@@ -629,6 +630,12 @@ daemon_fork(struct daemon* daemon)
  if(daemon->use_response_ip &&
  modstack_find(&daemon->mods, "respip") < 0)
  fatal_exit("response-ip options require respip module");
+ /* RPZ response ip triggers don't work as expected without the respip
+ * module.  To avoid run-time operational surprise we reject such
+ * configuration. */
+ if(daemon->use_rpz &&
+ modstack_find(&daemon->mods, "respip") < 0)
+ fatal_exit("RPZ requires the respip module");
 
  /* first create all the worker structures, so we can pass
  * them to the newly created threads.
Index: daemon/daemon.h
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/daemon/daemon.h,v
retrieving revision 1.5
diff -u -p -r1.5 daemon.h
--- daemon/daemon.h 20 Sep 2018 23:15:39 -0000 1.5
+++ daemon/daemon.h 15 Mar 2020 16:31:04 -0000
@@ -132,6 +132,8 @@ struct daemon {
  struct respip_set* respip_set;
  /** some response-ip tags or actions are configured if true */
  int use_response_ip;
+ /** some RPZ policies are configured */
+ int use_rpz;
 #ifdef USE_DNSCRYPT
  /** the dnscrypt environment */
  struct dnsc_env* dnscenv;
Index: daemon/remote.c
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/daemon/remote.c,v
retrieving revision 1.27
diff -u -p -r1.27 remote.c
--- daemon/remote.c 18 Dec 2019 11:04:13 -0000 1.27
+++ daemon/remote.c 15 Mar 2020 16:31:04 -0000
@@ -69,6 +69,7 @@
 #include "services/mesh.h"
 #include "services/localzone.h"
 #include "services/authzone.h"
+#include "services/rpz.h"
 #include "util/storage/slabhash.h"
 #include "util/fptr_wlist.h"
 #include "util/data/dname.h"
@@ -719,8 +720,8 @@ print_stats(RES* ssl, const char* nm, st
  (unsigned long)s->svr.num_queries_missed_cache)) return 0;
  if(!ssl_printf(ssl, "%s.num.prefetch"SQ"%lu\n", nm,
  (unsigned long)s->svr.num_queries_prefetch)) return 0;
- if(!ssl_printf(ssl, "%s.num.zero_ttl"SQ"%lu\n", nm,
- (unsigned long)s->svr.zero_ttl_responses)) return 0;
+ if(!ssl_printf(ssl, "%s.num.expired"SQ"%lu\n", nm,
+ (unsigned long)s->svr.ans_expired)) return 0;
  if(!ssl_printf(ssl, "%s.num.recursivereplies"SQ"%lu\n", nm,
  (unsigned long)s->mesh_replies_sent)) return 0;
 #ifdef USE_DNSCRYPT
@@ -1045,6 +1046,16 @@ print_ext(RES* ssl, struct ub_stats_info
  (unsigned)s->svr.infra_cache_count)) return 0;
  if(!ssl_printf(ssl, "key.cache.count"SQ"%u\n",
  (unsigned)s->svr.key_cache_count)) return 0;
+ /* applied RPZ actions */
+ for(i=0; i<UB_STATS_RPZ_ACTION_NUM; i++) {
+ if(i == RPZ_NO_OVERRIDE_ACTION)
+ continue;
+ if(inhibit_zero && s->svr.rpz_action[i] == 0)
+ continue;
+ if(!ssl_printf(ssl, "num.rpz.action.%s"SQ"%lu\n",
+ rpz_action_to_string(i),
+ (unsigned long)s->svr.rpz_action[i])) return 0;
+ }
 #ifdef USE_DNSCRYPT
  if(!ssl_printf(ssl, "dnscrypt_shared_secret.cache.count"SQ"%u\n",
  (unsigned)s->svr.shared_secret_cache_count)) return 0;
@@ -1479,6 +1490,27 @@ do_view_data_remove(RES* ssl, struct wor
  lock_rw_unlock(&v->lock);
 }
 
+/** Remove RR data from stdin from view */
+static void
+do_view_datas_remove(RES* ssl, struct worker* worker, char* arg)
+{
+ struct view* v;
+ v = views_find_view(worker->daemon->views,
+ arg, 1 /* get write lock*/);
+ if(!v) {
+ ssl_printf(ssl,"no view with name: %s\n", arg);
+ return;
+ }
+ if(!v->local_zones){
+ lock_rw_unlock(&v->lock);
+ ssl_printf(ssl, "removed 0 datas\n");
+ return;
+ }
+
+ do_datas_remove(ssl, v->local_zones);
+ lock_rw_unlock(&v->lock);
+}
+
 /** cache lookup of nameservers */
 static void
 do_lookup(RES* ssl, struct worker* worker, char* arg)
@@ -2506,8 +2538,10 @@ do_auth_zone_transfer(RES* ssl, struct w
  if(!az || !auth_zones_startprobesequence(az, &worker->env, nm, nmlen,
  LDNS_RR_CLASS_IN)) {
  (void)ssl_printf(ssl, "error zone xfr task not found %s\n", arg);
+ free(nm);
  return;
  }
+ free(nm);
  send_ok(ssl);
 }
 
@@ -2989,6 +3023,8 @@ execute_cmd(struct daemon_remote* rc, RE
  do_view_zone_add(ssl, worker, skipwhite(p+15));
  } else if(cmdcmp(p, "view_local_data_remove", 22)) {
  do_view_data_remove(ssl, worker, skipwhite(p+22));
+ } else if(cmdcmp(p, "view_local_datas_remove", 23)){
+ do_view_datas_remove(ssl, worker, skipwhite(p+23));
  } else if(cmdcmp(p, "view_local_data", 15)) {
  do_view_data_add(ssl, worker, skipwhite(p+15));
  } else if(cmdcmp(p, "view_local_datas", 16)) {
Index: daemon/stats.c
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/daemon/stats.c,v
retrieving revision 1.9
diff -u -p -r1.9 stats.c
--- daemon/stats.c 11 Sep 2019 14:13:27 -0000 1.9
+++ daemon/stats.c 15 Mar 2020 16:31:04 -0000
@@ -271,8 +271,10 @@ server_stats_compile(struct worker* work
  s->svr.ans_secure += (long long)worker->env.mesh->ans_secure;
  s->svr.ans_bogus += (long long)worker->env.mesh->ans_bogus;
  s->svr.ans_rcode_nodata += (long long)worker->env.mesh->ans_nodata;
- for(i=0; i<16; i++)
+ for(i=0; i<UB_STATS_RCODE_NUM; i++)
  s->svr.ans_rcode[i] += (long long)worker->env.mesh->ans_rcode[i];
+ for(i=0; i<UB_STATS_RPZ_ACTION_NUM; i++)
+ s->svr.rpz_action[i] += (long long)worker->env.mesh->rpz_action[i];
  timehist_export(worker->env.mesh->histogram, s->svr.hist,
  NUM_BUCKETS_HIST);
  /* values from outside network */
@@ -398,6 +400,7 @@ void server_stats_add(struct ub_stats_in
  total->svr.num_queries_missed_cache += a->svr.num_queries_missed_cache;
  total->svr.num_queries_prefetch += a->svr.num_queries_prefetch;
  total->svr.sum_query_list_size += a->svr.sum_query_list_size;
+ total->svr.ans_expired += a->svr.ans_expired;
 #ifdef USE_DNSCRYPT
  total->svr.num_query_dnscrypt_crypted += a->svr.num_query_dnscrypt_crypted;
  total->svr.num_query_dnscrypt_cert += a->svr.num_query_dnscrypt_cert;
@@ -430,7 +433,6 @@ void server_stats_add(struct ub_stats_in
  total->svr.qEDNS += a->svr.qEDNS;
  total->svr.qEDNS_DO += a->svr.qEDNS_DO;
  total->svr.ans_rcode_nodata += a->svr.ans_rcode_nodata;
- total->svr.zero_ttl_responses += a->svr.zero_ttl_responses;
  total->svr.ans_secure += a->svr.ans_secure;
  total->svr.ans_bogus += a->svr.ans_bogus;
  total->svr.unwanted_replies += a->svr.unwanted_replies;
@@ -446,6 +448,8 @@ void server_stats_add(struct ub_stats_in
  total->svr.ans_rcode[i] += a->svr.ans_rcode[i];
  for(i=0; i<NUM_BUCKETS_HIST; i++)
  total->svr.hist[i] += a->svr.hist[i];
+ for(i=0; i<UB_STATS_RPZ_ACTION_NUM; i++)
+ total->svr.rpz_action[i] += a->svr.rpz_action[i];
  }
 
  total->mesh_num_states += a->mesh_num_states;
Index: daemon/unbound.c
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/daemon/unbound.c,v
retrieving revision 1.25
diff -u -p -r1.25 unbound.c
--- daemon/unbound.c 18 Dec 2019 11:04:13 -0000 1.25
+++ daemon/unbound.c 15 Mar 2020 16:31:04 -0000
@@ -259,21 +259,10 @@ checkrlimits(struct config_file* cfg)
 #endif /* S_SPLINT_S */
 }
 
-/** set default logfile identity based on value from argv[0] at startup **/
-static void
-log_ident_set_fromdefault(struct config_file* cfg,
- const char *log_default_identity)
-{
- if(cfg->log_identity == NULL || cfg->log_identity[0] == 0)
- log_ident_set(log_default_identity);
- else
- log_ident_set(cfg->log_identity);
-}
-
 /** set verbosity, check rlimits, cache settings */
 static void
-apply_settings(struct daemon* daemon, struct config_file* cfg,
- int cmdline_verbose, int debug_mode, const char* log_default_identity)
+apply_settings(struct daemon* daemon, struct config_file* cfg,
+ int cmdline_verbose, int debug_mode)
 {
  /* apply if they have changed */
  verbosity = cmdline_verbose + cfg->verbosity;
@@ -289,7 +278,7 @@ apply_settings(struct daemon* daemon, st
  log_warn("use-systemd and do-daemonize should not be enabled at the same time");
  }
 
- log_ident_set_fromdefault(cfg, log_default_identity);
+ log_ident_set_or_default(cfg->log_identity);
 }
 
 #ifdef HAVE_KILL
@@ -639,11 +628,10 @@ perform_setup(struct daemon* daemon, str
  * @param cmdline_verbose: verbosity resulting from commandline -v.
  *    These increase verbosity as specified in the config file.
  * @param debug_mode: if set, do not daemonize.
- * @param log_default_identity: Default identity to report in logs
  * @param need_pidfile: if false, no pidfile is checked or created.
  */
 static void
-run_daemon(const char* cfgfile, int cmdline_verbose, int debug_mode, const char* log_default_identity, int need_pidfile)
+run_daemon(const char* cfgfile, int cmdline_verbose, int debug_mode, int need_pidfile)
 {
  struct config_file* cfg = NULL;
  struct daemon* daemon = NULL;
@@ -667,7 +655,7 @@ run_daemon(const char* cfgfile, int cmdl
  "or unbound-checkconf", cfgfile);
  log_warn("Continuing with default config settings");
  }
- apply_settings(daemon, cfg, cmdline_verbose, debug_mode, log_default_identity);
+ apply_settings(daemon, cfg, cmdline_verbose, debug_mode);
  if(!done_setup)
  config_lookup_uid(cfg);
 
@@ -733,6 +721,7 @@ main(int argc, char* argv[])
 
  log_init(NULL, 0, NULL);
  log_ident_default = strrchr(argv[0],'/')?strrchr(argv[0],'/')+1:argv[0];
+ log_ident_set_default(log_ident_default);
  log_ident_set(log_ident_default);
  /* parse the options */
  while( (c=getopt(argc, argv, "c:dhpvw:V")) != -1) {
@@ -783,7 +772,7 @@ main(int argc, char* argv[])
  return 1;
  }
 
- run_daemon(cfgfile, cmdline_verbose, debug_mode, log_ident_default, need_pidfile);
+ run_daemon(cfgfile, cmdline_verbose, debug_mode, need_pidfile);
  log_init(NULL, 0, NULL); /* close logfile */
 #ifndef unbound_testbound
  if(log_get_lock()) {
Index: daemon/worker.c
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/daemon/worker.c,v
retrieving revision 1.26
diff -u -p -r1.26 worker.c
--- daemon/worker.c 18 Dec 2019 11:04:13 -0000 1.26
+++ daemon/worker.c 15 Mar 2020 16:31:04 -0000
@@ -61,6 +61,7 @@
 #include "services/authzone.h"
 #include "services/mesh.h"
 #include "services/localzone.h"
+#include "services/rpz.h"
 #include "util/data/msgparse.h"
 #include "util/data/msgencode.h"
 #include "util/data/dname.h"
@@ -572,9 +573,10 @@ static int
 apply_respip_action(struct worker* worker, const struct query_info* qinfo,
  struct respip_client_info* cinfo, struct reply_info* rep,
  struct comm_reply* repinfo, struct ub_packed_rrset_key** alias_rrset,
- struct reply_info** encode_repp)
+ struct reply_info** encode_repp, struct auth_zones* az)
 {
- struct respip_action_info actinfo = {respip_none, NULL};
+ struct respip_action_info actinfo = {0};
+ actinfo.action = respip_none;
 
  if(qinfo->qtype != LDNS_RR_TYPE_A &&
  qinfo->qtype != LDNS_RR_TYPE_AAAA &&
@@ -582,7 +584,7 @@ apply_respip_action(struct worker* worke
  return 1;
 
  if(!respip_rewrite_reply(qinfo, cinfo, rep, encode_repp, &actinfo,
- alias_rrset, 0, worker->scratchpad))
+ alias_rrset, 0, worker->scratchpad, az))
  return 0;
 
  /* xxx_deny actions mean dropping the reply, unless the original reply
@@ -595,9 +597,19 @@ apply_respip_action(struct worker* worke
  /* If address info is returned, it means the action should be an
  * 'inform' variant and the information should be logged. */
  if(actinfo.addrinfo) {
- respip_inform_print(actinfo.addrinfo, qinfo->qname,
+ respip_inform_print(&actinfo, qinfo->qname,
  qinfo->qtype, qinfo->qclass, qinfo->local_alias,
  repinfo);
+
+ if(worker->stats.extended && actinfo.rpz_used) {
+ if(actinfo.rpz_disabled)
+ worker->stats.rpz_action[RPZ_DISABLED_ACTION]++;
+ if(actinfo.rpz_cname_override)
+ worker->stats.rpz_action[RPZ_CNAME_OVERRIDE_ACTION]++;
+ else
+ worker->stats.rpz_action[
+ respip_action_to_rpz_action(actinfo.action)]++;
+ }
  }
 
  return 1;
@@ -613,10 +625,10 @@ apply_respip_action(struct worker* worke
  * be completely dropped, '*need_drop' will be set to 1. */
 static int
 answer_from_cache(struct worker* worker, struct query_info* qinfo,
- struct respip_client_info* cinfo, int* need_drop,
- struct ub_packed_rrset_key** alias_rrset,
+ struct respip_client_info* cinfo, int* need_drop, int* is_expired_answer,
+ int* is_secure_answer, struct ub_packed_rrset_key** alias_rrset,
  struct reply_info** partial_repp,
- struct reply_info* rep, uint16_t id, uint16_t flags,
+ struct reply_info* rep, uint16_t id, uint16_t flags,
  struct comm_reply* repinfo, struct edns_data* edns)
 {
  struct edns_data edns_bak;
@@ -624,38 +636,37 @@ answer_from_cache(struct worker* worker,
  uint16_t udpsize = edns->udp_size;
  struct reply_info* encode_rep = rep;
  struct reply_info* partial_rep = *partial_repp;
- int secure;
  int must_validate = (!(flags&BIT_CD) || worker->env.cfg->ignore_cd)
  && worker->env.need_to_validate;
- *partial_repp = NULL; /* avoid accidental further pass */
- if(worker->env.cfg->serve_expired) {
- if(worker->env.cfg->serve_expired_ttl &&
- rep->serve_expired_ttl < timenow)
- return 0;
- if(!rrset_array_lock(rep->ref, rep->rrset_count, 0))
- return 0;
- /* below, rrsets with ttl before timenow become TTL 0 in
- * the response */
- /* This response was served with zero TTL */
- if (timenow >= rep->ttl) {
- worker->stats.zero_ttl_responses++;
- }
- } else {
- /* see if it is possible */
- if(rep->ttl < timenow) {
+ *partial_repp = NULL;  /* avoid accidental further pass */
+
+ /* Check TTL */
+ if(rep->ttl < timenow) {
+ /* Check if we need to serve expired now */
+ if(worker->env.cfg->serve_expired &&
+ !worker->env.cfg->serve_expired_client_timeout) {
+ if(worker->env.cfg->serve_expired_ttl &&
+ rep->serve_expired_ttl < timenow)
+ return 0;
+ if(!rrset_array_lock(rep->ref, rep->rrset_count, 0))
+ return 0;
+ *is_expired_answer = 1;
+ } else {
  /* the rrsets may have been updated in the meantime.
  * we will refetch the message format from the
- * authoritative server
+ * authoritative server
  */
  return 0;
  }
+ } else {
  if(!rrset_array_lock(rep->ref, rep->rrset_count, timenow))
  return 0;
- /* locked and ids and ttls are OK. */
  }
+ /* locked and ids and ttls are OK. */
+
  /* check CNAME chain (if any) */
- if(rep->an_numrrsets > 0 && (rep->rrsets[0]->rk.type ==
- htons(LDNS_RR_TYPE_CNAME) || rep->rrsets[0]->rk.type ==
+ if(rep->an_numrrsets > 0 && (rep->rrsets[0]->rk.type ==
+ htons(LDNS_RR_TYPE_CNAME) || rep->rrsets[0]->rk.type ==
  htons(LDNS_RR_TYPE_DNAME))) {
  if(!reply_check_cname_chain(qinfo, rep)) {
  /* cname chain invalid, redo iterator steps */
@@ -674,31 +685,31 @@ answer_from_cache(struct worker* worker,
  if(!inplace_cb_reply_servfail_call(&worker->env, qinfo, NULL, rep,
  LDNS_RCODE_SERVFAIL, edns, repinfo, worker->scratchpad))
  goto bail_out;
- error_encode(repinfo->c->buffer, LDNS_RCODE_SERVFAIL,
+ error_encode(repinfo->c->buffer, LDNS_RCODE_SERVFAIL,
  qinfo, id, flags, edns);
- rrset_array_unlock_touch(worker->env.rrset_cache,
+ rrset_array_unlock_touch(worker->env.rrset_cache,
  worker->scratchpad, rep->ref, rep->rrset_count);
  if(worker->stats.extended) {
  worker->stats.ans_bogus ++;
  worker->stats.ans_rcode[LDNS_RCODE_SERVFAIL] ++;
  }
  return 1;
- } else if( rep->security == sec_status_unchecked && must_validate) {
+ } else if(rep->security == sec_status_unchecked && must_validate) {
  verbose(VERB_ALGO, "Cache reply: unchecked entry needs "
  "validation");
  goto bail_out; /* need to validate cache entry first */
  } else if(rep->security == sec_status_secure) {
- if(reply_all_rrsets_secure(rep))
- secure = 1;
- else {
+ if(reply_all_rrsets_secure(rep)) {
+ *is_secure_answer = 1;
+ } else {
  if(must_validate) {
  verbose(VERB_ALGO, "Cache reply: secure entry"
  " changed status");
  goto bail_out; /* rrset changed, re-verify */
  }
- secure = 0;
+ *is_secure_answer = 0;
  }
- } else secure = 0;
+ } else *is_secure_answer = 0;
 
  edns_bak = *edns;
  edns->edns_version = EDNS_ADVERTISED_VERSION;
@@ -709,17 +720,21 @@ answer_from_cache(struct worker* worker,
  (int)(flags&LDNS_RCODE_MASK), edns, repinfo, worker->scratchpad))
  goto bail_out;
  *alias_rrset = NULL; /* avoid confusion if caller set it to non-NULL */
- if(worker->daemon->use_response_ip && !partial_rep &&
-   !apply_respip_action(worker, qinfo, cinfo, rep, repinfo, alias_rrset,
- &encode_rep)) {
+ if((worker->daemon->use_response_ip || worker->daemon->use_rpz) &&
+ !partial_rep && !apply_respip_action(worker, qinfo, cinfo, rep,
+ repinfo, alias_rrset,
+ &encode_rep, worker->env.auth_zones)) {
  goto bail_out;
  } else if(partial_rep &&
  !respip_merge_cname(partial_rep, qinfo, rep, cinfo,
- must_validate, &encode_rep, worker->scratchpad)) {
+ must_validate, &encode_rep, worker->scratchpad,
+ worker->env.auth_zones)) {
  goto bail_out;
  }
- if(encode_rep != rep)
- secure = 0; /* if rewritten, it can't be considered "secure" */
+ if(encode_rep != rep) {
+ /* if rewritten, it can't be considered "secure" */
+ *is_secure_answer = 0;
+ }
  if(!encode_rep || *alias_rrset) {
  if(!encode_rep)
  *need_drop = 1;
@@ -736,7 +751,7 @@ answer_from_cache(struct worker* worker,
  repinfo->c, worker->scratchpad) ||
  !reply_info_answer_encode(qinfo, encode_rep, id, flags,
  repinfo->c->buffer, timenow, 1, worker->scratchpad,
- udpsize, edns, (int)(edns->bits & EDNS_DO), secure)) {
+ udpsize, edns, (int)(edns->bits & EDNS_DO), *is_secure_answer)) {
  if(!inplace_cb_reply_servfail_call(&worker->env, qinfo, NULL, NULL,
  LDNS_RCODE_SERVFAIL, edns, repinfo, worker->scratchpad))
  edns->opt_list = NULL;
@@ -747,10 +762,6 @@ answer_from_cache(struct worker* worker,
  * is bad while holding locks. */
  rrset_array_unlock_touch(worker->env.rrset_cache, worker->scratchpad,
  rep->ref, rep->rrset_count);
- if(worker->stats.extended) {
- if(secure) worker->stats.ans_secure++;
- server_stats_insrcode(&worker->stats, repinfo->c->buffer);
- }
  /* go and return this buffer to the client */
  return 1;
 
@@ -1085,6 +1096,8 @@ worker_handle_request(struct comm_point*
  struct acl_addr* acladdr;
  int rc = 0;
  int need_drop = 0;
+ int is_expired_answer = 0;
+ int is_secure_answer = 0;
  /* We might have to chase a CNAME chain internally, in which case
  * we'll have up to two replies and combine them to build a complete
  * answer.  These variables control this case. */
@@ -1365,6 +1378,18 @@ worker_handle_request(struct comm_point*
  goto send_reply;
  }
  if(worker->env.auth_zones &&
+ rpz_apply_qname_trigger(worker->env.auth_zones,
+ &worker->env, &qinfo, &edns, c->buffer, worker->scratchpad,
+ repinfo, acladdr->taglist, acladdr->taglen, &worker->stats)) {
+ regional_free_all(worker->scratchpad);
+ if(sldns_buffer_limit(c->buffer) == 0) {
+ comm_point_drop_reply(repinfo);
+ return 0;
+ }
+ server_stats_insrcode(&worker->stats, c->buffer);
+ goto send_reply;
+ }
+ if(worker->env.auth_zones &&
  auth_zones_answer(worker->env.auth_zones, &worker->env,
  &qinfo, &edns, repinfo, c->buffer, worker->scratchpad)) {
  regional_free_all(worker->scratchpad);
@@ -1434,7 +1459,7 @@ worker_handle_request(struct comm_point*
  /* If we may apply IP-based actions to the answer, build the client
  * information.  As this can be expensive, skip it if there is
  * absolutely no possibility of it. */
- if(worker->daemon->use_response_ip &&
+ if((worker->daemon->use_response_ip || worker->daemon->use_rpz) &&
  (qinfo.qtype == LDNS_RR_TYPE_A ||
  qinfo.qtype == LDNS_RR_TYPE_AAAA ||
  qinfo.qtype == LDNS_RR_TYPE_ANY)) {
@@ -1455,12 +1480,14 @@ lookup_cache:
  * each pass.  We should still pass the original qinfo to
  * answer_from_cache(), however, since it's used to build the reply. */
  if(!edns_bypass_cache_stage(edns.opt_list, &worker->env)) {
+ is_expired_answer = 0;
+ is_secure_answer = 0;
  h = query_info_hash(lookup_qinfo, sldns_buffer_read_u16_at(c->buffer, 2));
  if((e=slabhash_lookup(worker->env.msg_cache, h, lookup_qinfo, 0))) {
  /* answer from cache - we have acquired a readlock on it */
  if(answer_from_cache(worker, &qinfo,
- cinfo, &need_drop, &alias_rrset, &partial_rep,
- (struct reply_info*)e->data,
+ cinfo, &need_drop, &is_expired_answer, &is_secure_answer,
+ &alias_rrset, &partial_rep, (struct reply_info*)e->data,
  *(uint16_t*)(void *)sldns_buffer_begin(c->buffer),
  sldns_buffer_read_u16_at(c->buffer, 2), repinfo,
  &edns)) {
@@ -1468,9 +1495,11 @@ lookup_cache:
  * Note that if there is more than one pass
  * its qname must be that used for cache
  * lookup. */
- if((worker->env.cfg->prefetch || worker->env.cfg->serve_expired)
- && *worker->env.now >=
- ((struct reply_info*)e->data)->prefetch_ttl) {
+ if((worker->env.cfg->prefetch && *worker->env.now >=
+ ((struct reply_info*)e->data)->prefetch_ttl) ||
+ (worker->env.cfg->serve_expired &&
+ *worker->env.now >= ((struct reply_info*)e->data)->ttl)) {
+
  time_t leeway = ((struct reply_info*)e->
  data)->ttl - *worker->env.now;
  if(((struct reply_info*)e->data)->ttl
@@ -1555,6 +1584,13 @@ send_reply_rc:
  comm_point_drop_reply(repinfo);
  return 0;
  }
+ if(is_expired_answer) {
+ worker->stats.ans_expired++;
+ }
+ if(worker->stats.extended) {
+ if(is_secure_answer) worker->stats.ans_secure++;
+ server_stats_insrcode(&worker->stats, repinfo->c->buffer);
+ }
 #ifdef USE_DNSTAP
  if(worker->dtenv.log_client_response_messages)
  dt_msg_send_client_response(&worker->dtenv, &repinfo->addr,
@@ -1830,6 +1866,10 @@ worker_init(struct worker* worker, struc
  return 0;
  }
  worker->env.mesh = mesh_create(&worker->daemon->mods, &worker->env);
+ /* Pass on daemon variables that we would need in the mesh area */
+ worker->env.mesh->use_response_ip = worker->daemon->use_response_ip;
+ worker->env.mesh->use_rpz = worker->daemon->use_rpz;
+
  worker->env.detach_subs = &mesh_detach_subs;
  worker->env.attach_sub = &mesh_attach_sub;
  worker->env.add_sub = &mesh_add_sub;
Index: doc/README
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/doc/README,v
retrieving revision 1.22
diff -u -p -r1.22 README
--- doc/README 18 Dec 2019 11:04:13 -0000 1.22
+++ doc/README 15 Mar 2020 16:31:04 -0000
@@ -1,4 +1,4 @@
-README for Unbound 1.9.6
+README for Unbound 1.10.0
 Copyright 2007 NLnet Labs
 http://unbound.net
 
Index: doc/example.conf.in
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/doc/example.conf.in,v
retrieving revision 1.27
diff -u -p -r1.27 example.conf.in
--- doc/example.conf.in 18 Dec 2019 11:04:13 -0000 1.27
+++ doc/example.conf.in 15 Mar 2020 16:31:04 -0000
@@ -1,7 +1,7 @@
 #
 # Example configuration file.
 #
-# See unbound.conf(5) man page, version 1.9.6.
+# See unbound.conf(5) man page, version 1.10.0.
 #
 # this is a comment.
 
@@ -558,8 +558,8 @@ server:
  # that set CD but cannot validate themselves.
  # ignore-cd-flag: no
 
- # Serve expired responses from cache, with TTL 0 in the response,
- # and then attempt to fetch the data afresh.
+ # Serve expired responses from cache, with serve-expired-reply-ttl in
+ # the response, and then attempt to fetch the data afresh.
  # serve-expired: no
  #
  # Limit serving of expired responses to configured seconds after
@@ -571,6 +571,16 @@ server:
  # that the expired records will be served as long as there are queries
  # for it.
  # serve-expired-ttl-reset: no
+ #
+ # TTL value to use when replying with expired data.
+ # serve-expired-reply-ttl: 30
+ #
+ # Time in milliseconds before replying to the client with expired data.
+ # This essentially enables the serve-stale behavior as specified in
+ # draft-ietf-dnsop-serve-stale-10 that first tries to resolve before
+ # immediately responding with expired data.  0 disables this behavior.
+ # A recommended value is 1800.
+ # serve-expired-client-timeout: 0
 
  # Have the validator log failed validations for your diagnosis.
  # 0: off. 1: A line per failed user query. 2: With reason and bad IP.
@@ -1006,3 +1016,20 @@ remote-control:
 #     name-v6: "list-v6"
 #
 
+# Response Policy Zones
+# RPZ policies. Applied in order of configuration. QNAME and Response IP
+# Address trigger are the only supported triggers. Supported actions are:
+# NXDOMAIN, NODATA, PASSTHRU, DROP and Local Data. Policies can be loaded from
+# file, using zone transfer, or using HTTP. The respip module needs to be added
+# to the module-config, e.g.: module-config: "respip validator iterator".
+# rpz:
+#     name: "rpz.example.com"
+#     zonefile: "rpz.example.com"
+#     master: 192.0.2.0
+#     allow-notify: 192.0.2.0/32
+#     url: http://www.example.com/rpz.example.org.zone
+#     rpz-action-override: cname
+#     rpz-cname-override: www.example.org
+#     rpz-log: yes
+#     rpz-log-name: "example policy"
+#     tags: "example"
Index: doc/libunbound.3.in
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/doc/libunbound.3.in,v
retrieving revision 1.25
diff -u -p -r1.25 libunbound.3.in
--- doc/libunbound.3.in 18 Dec 2019 11:04:13 -0000 1.25
+++ doc/libunbound.3.in 15 Mar 2020 16:31:04 -0000
@@ -1,4 +1,4 @@
-.TH "libunbound" "3" "dec 12, 2019" "NLnet Labs" "unbound 1.9.6"
+.TH "libunbound" "3" "Feb 20, 2020" "NLnet Labs" "unbound 1.10.0"
 .\"
 .\" libunbound.3 -- unbound library functions manual
 .\"
@@ -44,7 +44,7 @@
 .B ub_ctx_zone_remove,
 .B ub_ctx_data_add,
 .B ub_ctx_data_remove
-\- Unbound DNS validating resolver 1.9.6 functions.
+\- Unbound DNS validating resolver 1.10.0 functions.
 .SH "SYNOPSIS"
 .B #include <unbound.h>
 .LP
@@ -396,12 +396,13 @@ The result of the DNS resolution and val
  char* canonname; /* canonical name of result */
  int rcode;   /* additional error code in case of no data */
  void* answer_packet; /* full network format answer packet */
- int answer_len; /* length of packet in octets */
+ int answer_len;  /* length of packet in octets */
  int havedata; /* true if there is data */
  int nxdomain; /* true if nodata because name does not exist */
- int secure;  /* true if result is secure */
- int bogus;   /* true if a security failure happened */
+ int secure;   /* true if result is secure */
+ int bogus;    /* true if a security failure happened */
  char* why_bogus; /* string with error if bogus */
+ int was_ratelimited; /* true if the query was ratelimited (SERVFAIL) by unbound */
  int ttl;     /* number of seconds the result is valid */
  };
 .fi
Index: doc/unbound-anchor.8.in
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/doc/unbound-anchor.8.in,v
retrieving revision 1.24
diff -u -p -r1.24 unbound-anchor.8.in
--- doc/unbound-anchor.8.in 18 Dec 2019 11:04:13 -0000 1.24
+++ doc/unbound-anchor.8.in 15 Mar 2020 16:31:04 -0000
@@ -1,4 +1,4 @@
-.TH "unbound-anchor" "8" "dec 12, 2019" "NLnet Labs" "unbound 1.9.6"
+.TH "unbound-anchor" "8" "Feb 20, 2020" "NLnet Labs" "unbound 1.10.0"
 .\"
 .\" unbound-anchor.8 -- unbound anchor maintenance utility manual
 .\"
Index: doc/unbound-checkconf.8.in
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/doc/unbound-checkconf.8.in,v
retrieving revision 1.24
diff -u -p -r1.24 unbound-checkconf.8.in
--- doc/unbound-checkconf.8.in 18 Dec 2019 11:04:13 -0000 1.24
+++ doc/unbound-checkconf.8.in 15 Mar 2020 16:31:04 -0000
@@ -1,4 +1,4 @@
-.TH "unbound-checkconf" "8" "dec 12, 2019" "NLnet Labs" "unbound 1.9.6"
+.TH "unbound-checkconf" "8" "Feb 20, 2020" "NLnet Labs" "unbound 1.10.0"
 .\"
 .\" unbound-checkconf.8 -- unbound configuration checker manual
 .\"
Index: doc/unbound-control.8.in
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/doc/unbound-control.8.in,v
retrieving revision 1.26
diff -u -p -r1.26 unbound-control.8.in
--- doc/unbound-control.8.in 18 Dec 2019 11:04:13 -0000 1.26
+++ doc/unbound-control.8.in 15 Mar 2020 16:31:04 -0000
@@ -1,4 +1,4 @@
-.TH "unbound-control" "8" "dec 12, 2019" "NLnet Labs" "unbound 1.9.6"
+.TH "unbound-control" "8" "Feb 20, 2020" "NLnet Labs" "unbound 1.10.0"
 .\"
 .\" unbound-control.8 -- unbound remote control manual
 .\"
@@ -323,6 +323,9 @@ serial check).  And then the zone is tra
 .B view_local_data_remove \fIview\fR \fIname
 \fIlocal_data_remove\fR for given view.
 .TP
+.B view_local_datas_remove \fIview\fR
+Remove a list of \fIlocal_data\fR for given view from stdin. Like local_datas_remove.
+.TP
 .B view_local_datas \fIview\fR
 Add a list of \fIlocal_data\fR for given view from stdin.  Like local_datas.
 .SH "EXIT CODE"
@@ -379,8 +382,8 @@ and resulted in recursive processing, ta
 Not part of the recursivereplies (or the histogram thereof) or cachemiss,
 as a cache response was sent.
 .TP
-.I threadX.num.zero_ttl
-number of replies with ttl zero, because they served an expired cache entry.
+.I threadX.num.expired
+number of replies that served an expired cache entry.
 .TP
 .I threadX.num.recursivereplies
 The number of replies sent to queries that needed recursive processing. Could be smaller than threadX.num.cachemiss if due to timeouts no replies were sent for some queries.
@@ -443,7 +446,7 @@ summed over threads.
 .I total.num.prefetch
 summed over threads.
 .TP
-.I total.num.zero_ttl
+.I total.num.expired
 summed over threads.
 .TP
 .I total.num.recursivereplies
@@ -660,6 +663,11 @@ Number of queries that got an answer tha
 Number of queries answered from the edns client subnet cache.  These are
 counted as cachemiss by the main counters, but hit the client subnet
 specific cache, after getting processed by the edns client subnet module.
+.TP
+.I num.rpz.action.<rpz_action>
+Number of queries answered using configured RPZ policy, per RPZ action type.
+Possible actions are: nxdomain, nodata, passthru, drop, local_data, disabled,
+and cname_override.
 .SH "FILES"
 .TP
 .I @ub_conf_file@
Index: doc/unbound-host.1.in
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/doc/unbound-host.1.in,v
retrieving revision 1.26
diff -u -p -r1.26 unbound-host.1.in
--- doc/unbound-host.1.in 18 Dec 2019 11:04:13 -0000 1.26
+++ doc/unbound-host.1.in 15 Mar 2020 16:31:04 -0000
@@ -1,4 +1,4 @@
-.TH "unbound\-host" "1" "dec 12, 2019" "NLnet Labs" "unbound 1.9.6"
+.TH "unbound\-host" "1" "Feb 20, 2020" "NLnet Labs" "unbound 1.10.0"
 .\"
 .\" unbound-host.1 -- unbound DNS lookup utility
 .\"
Index: doc/unbound.8.in
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/doc/unbound.8.in,v
retrieving revision 1.27
diff -u -p -r1.27 unbound.8.in
--- doc/unbound.8.in 18 Dec 2019 11:04:13 -0000 1.27
+++ doc/unbound.8.in 15 Mar 2020 16:31:04 -0000
@@ -1,4 +1,4 @@
-.TH "unbound" "8" "dec 12, 2019" "NLnet Labs" "unbound 1.9.6"
+.TH "unbound" "8" "Feb 20, 2020" "NLnet Labs" "unbound 1.10.0"
 .\"
 .\" unbound.8 -- unbound manual
 .\"
@@ -9,7 +9,7 @@
 .\"
 .SH "NAME"
 .B unbound
-\- Unbound DNS validating resolver 1.9.6.
+\- Unbound DNS validating resolver 1.10.0.
 .SH "SYNOPSIS"
 .B unbound
 .RB [ \-h ]
Index: doc/unbound.conf.5.in
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/doc/unbound.conf.5.in,v
retrieving revision 1.30
diff -u -p -r1.30 unbound.conf.5.in
--- doc/unbound.conf.5.in 18 Dec 2019 11:04:13 -0000 1.30
+++ doc/unbound.conf.5.in 15 Mar 2020 16:31:04 -0000
@@ -1,4 +1,4 @@
-.TH "unbound.conf" "5" "dec 12, 2019" "NLnet Labs" "unbound 1.9.6"
+.TH "unbound.conf" "5" "Feb 20, 2020" "NLnet Labs" "unbound 1.10.0"
 .\"
 .\" unbound.conf.5 -- unbound.conf manual
 .\"
@@ -27,8 +27,10 @@ The utility
 \fIunbound\-checkconf\fR(8)
 can be used to check unbound.conf prior to usage.
 .SH "FILE FORMAT"
-There must be whitespace between keywords. Attribute keywords end with a colon ':'.
-An attribute is followed by its containing attributes, or a value.
+There must be whitespace between keywords.  Attribute keywords end with a
+colon ':'.  An attribute is followed by a value, or its containing attributes
+in which case it is referred to as a clause.  Clauses can be repeated throughout
+the file (or included files) to group attributes under the same clause.
 .P
 Files can be included using the
 .B include:
@@ -1025,20 +1027,35 @@ The default value is "no".
 .TP
 .B serve\-expired: \fI<yes or no>
 If enabled, unbound attempts to serve old responses from cache with a
-TTL of 0 in the response without waiting for the actual resolution to finish.
-The actual resolution answer ends up in the cache later on.  Default is "no".
+TTL of \fBserve\-expired\-reply\-ttl\fR in the response without waiting for the
+actual resolution to finish.  The actual resolution answer ends up in the cache
+later on.  Default is "no".
 .TP
 .B serve\-expired\-ttl: \fI<seconds>
 Limit serving of expired responses to configured seconds after expiration. 0
-disables the limit. This option only applies when \fBserve\-expired\fR is
-enabled. The default is 0.
+disables the limit.  This option only applies when \fBserve\-expired\fR is
+enabled.  A suggested value per draft-ietf-dnsop-serve-stale-10 is between
+86400 (1 day) and 259200 (3 days).  The default is 0.
 .TP
 .B serve\-expired\-ttl\-reset: \fI<yes or no>
 Set the TTL of expired records to the \fBserve\-expired\-ttl\fR value after a
-failed attempt to retrieve the record from upstream. This makes sure that the
-expired records will be served as long as there are queries for it. Default is
+failed attempt to retrieve the record from upstream.  This makes sure that the
+expired records will be served as long as there are queries for it.  Default is
 "no".
 .TP
+.B serve\-expired\-reply\-ttl: \fI<seconds>
+TTL value to use when replying with expired data.  If
+\fBserve\-expired\-client\-timeout\fR is also used then it is RECOMMENDED to
+use 30 as the value (draft-ietf-dnsop-serve-stale-10).  The default is 30.
+.TP
+.B serve\-expired\-client\-timeout: \fI<msec>
+Time in milliseconds before replying to the client with expired data.  This
+essentially enables the serve-stale behavior as specified in
+draft-ietf-dnsop-serve-stale-10 that first tries to resolve before immediately
+responding with expired data.  A recommended value per
+draft-ietf-dnsop-serve-stale-10 is 1800.  Setting this to 0 will disable this
+behavior.  Default is 0.
+.TP
 .B val\-nsec3\-keysize\-iterations: \fI<"list of values">
 List of keysize and iteration count values, separated by spaces, surrounded
 by quotes. Default is "1024 150 2048 500 4096 2500". This determines the
@@ -1251,7 +1268,7 @@ local\-data: "onion. 10800 IN
     SOA localhost. nobody.invalid. 1 3600 1200 604800 10800"
 .fi
 .TP 10
-\h'5'\fItest (RFC 2606)\fR
+\h'5'\fItest (RFC 6761)\fR
 Default content:
 .nf
 local\-zone: "test." static
@@ -1260,7 +1277,7 @@ local\-data: "test. 10800 IN
     SOA localhost. nobody.invalid. 1 3600 1200 604800 10800"
 .fi
 .TP 10
-\h'5'\fIinvalid (RFC 2606)\fR
+\h'5'\fIinvalid (RFC 6761)\fR
 Default content:
 .nf
 local\-zone: "invalid." static
@@ -1635,6 +1652,12 @@ Name of the authority zone.
 Where to download a copy of the zone from, with AXFR and IXFR.  Multiple
 masters can be specified.  They are all tried if one fails.
 With the "ip#name" notation a AXFR over TLS can be used.
+If you point it at another Unbound instance, it would not work because
+that does not support AXFR/IXFR for the zone, but if you used \fBurl:\fR to download
+the zonefile as a text file from a webserver that would work.
+If you specify the hostname, you cannot use the domain from the zonefile,
+because it may not have that when retrieving that data, instead use a plain
+IP address to avoid a circular dependency on retrieving that IP address.
 .TP
 .B url: \fI<url to zonefile>
 Where to download a zonefile for the zone.  With http or https.  An example
@@ -1646,6 +1669,10 @@ see if the SOA serial number has changed
 If none of the urls work, the masters are tried with IXFR and AXFR.
 For https, the \fBtls\-cert\-bundle\fR and the hostname from the url are used
 to authenticate the connection.
+If you specify a hostname in the URL, you cannot use the domain from the
+zonefile, because it may not have that when retrieving that data, instead
+use a plain IP address to avoid a circular dependency on retrieving that IP
+address.  Avoid dependencies on name lookups by using a notation like "http://192.0.2.1/unbound-master/example.com.zone", with an explicit IP address.
 .TP
 .B allow\-notify: \fI<IP address or host name or netblockIP/prefix>
 With allow\-notify you can specify additional sources of notifies.
@@ -1969,6 +1996,13 @@ to the query without performing iterativ
 If Unbound cannot even find an answer in the backend, it resolves the
 query as usual, and stores the answer in the backend.
 .P
+This module interacts with the \fBserve\-expired\-*\fR options and will reply
+with expired data if unbound is configured for that.  Currently the use
+of \fBserve\-expired\-client\-timeout:\fR and
+\fBserve\-expired\-reply\-ttl:\fR is not consistent for data originating from
+the external cache as these will result in a reply with 0 TTL without trying to
+update the data first, ignoring the configured values.
+.P
 If Unbound was built with
 \fB\-\-with\-libhiredis\fR
 on a system that has installed the hiredis C client library of Redis,
@@ -2035,6 +2069,70 @@ If this timeout expires Unbound closes t
 if the Redis server does not have the requested data, and will try to
 re-establish a new connection later.
 This option defaults to 100 milliseconds.
+.SS Response Policy Zone Options
+.LP
+Response Policy Zones are configured with \fBrpz:\fR, and each one must have a
+\fBname:\fR. There can be multiple ones, by listing multiple rpz clauses, each
+with a different name. RPZ clauses are applied in order of configuration. The
+\fBrespip\fR module needs to be added to the \fBmodule-config\fR, e.g.:
+\fBmodule-config: "respip validator iterator"\fR.
+.P
+Only the QNAME and Response IP Address triggers are supported. The supported RPZ
+actions are: NXDOMAIN, NODATA, PASSTHRU, DROP and Local Data. RPZ QNAME triggers
+are applied after
+\fBlocal-zones\fR and before \fBauth-zones\fR.
+.TP
+.B name: \fI<zone name>
+Name of the authority zone.
+.TP
+.B master: \fI<IP address or host name>
+Where to download a copy of the zone from, with AXFR and IXFR.  Multiple
+masters can be specified.  They are all tried if one fails.
+.TP
+.B url: \fI<url to zonefile>
+Where to download a zonefile for the zone.  With http or https.  An example
+for the url is "http://www.example.com/example.org.zone".  Multiple url
+statements can be given, they are tried in turn.  If only urls are given
+the SOA refresh timer is used to wait for making new downloads.  If also
+masters are listed, the masters are first probed with UDP SOA queries to
+see if the SOA serial number has changed, reducing the number of downloads.
+If none of the urls work, the masters are tried with IXFR and AXFR.
+For https, the \fBtls\-cert\-bundle\fR and the hostname from the url are used
+to authenticate the connection.
+.TP
+.B allow\-notify: \fI<IP address or host name or netblockIP/prefix>
+With allow\-notify you can specify additional sources of notifies.
+When notified, the server attempts to first probe and then zone transfer.
+If the notify is from a master, it first attempts that master.  Otherwise
+other masters are attempted.  If there are no masters, but only urls, the
+file is downloaded when notified.  The masters from master: statements are
+allowed notify by default.
+.TP
+.B zonefile: \fI<filename>
+The filename where the zone is stored.  If not given then no zonefile is used.
+If the file does not exist or is empty, unbound will attempt to fetch zone
+data (eg. from the master servers).
+.TP
+.B rpz\-action\-override: \fI<action>
+Always use this RPZ action for matching triggers from this zone. Possible action
+are: nxdomain, nodata, passthru, drop, disabled and cname.
+.TP
+.B rpz\-cname\-override: \fI<domain>
+The CNAME target domain to use if the cname action is configured for
+\fBrpz\-action\-override\fR.
+.TP
+.B rpz\-log: \fI<yes or no>
+Log all applied RPZ actions for this RPZ zone. Default is no.
+.TP
+.B rpz\-log\-name: \fI<name>
+Specify a string to be part of the log line, for easy referencing.
+.TP
+.B tags: \fI<list of tags>
+Limit the policies from this RPZ clause to clients with a matching tag. Tags
+need to be defined in \fBdefine\-tag\fR and can be assigned to client addresses
+using \fBaccess\-control\-tag\fR. Enclose list of tags in quotes ("") and put
+spaces between tags. If no tags are specified the policies from this clause will
+be applied for all clients.
 .SH "MEMORY CONTROL EXAMPLE"
 In the example config settings below memory usage is reduced. Some service
 levels are lower, notable very large data and a high TCP load are no longer
Index: edns-subnet/subnetmod.c
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/edns-subnet/subnetmod.c,v
retrieving revision 1.6
diff -u -p -r1.6 subnetmod.c
--- edns-subnet/subnetmod.c 28 Jun 2019 15:17:16 -0000 1.6
+++ edns-subnet/subnetmod.c 15 Mar 2020 16:31:04 -0000
@@ -431,7 +431,7 @@ lookup_and_reply(struct module_qstate *q
  }
 
  qstate->return_msg = tomsg(NULL, &qstate->qinfo,
- (struct reply_info *)node->elem, qstate->region, *env->now,
+ (struct reply_info *)node->elem, qstate->region, *env->now, 0,
  env->scratch);
  scope = (uint8_t)node->scope;
  lock_rw_unlock(&e->lock);
Index: libunbound/context.c
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/libunbound/context.c,v
retrieving revision 1.7
diff -u -p -r1.7 context.c
--- libunbound/context.c 11 Sep 2019 14:13:27 -0000 1.7
+++ libunbound/context.c 15 Mar 2020 16:31:04 -0000
@@ -55,6 +55,7 @@
 int
 context_finalize(struct ub_ctx* ctx)
 {
+ int is_rpz = 0;
  struct config_file* cfg = ctx->env->cfg;
  verbosity = cfg->verbosity;
  if(ctx_logfile_overridden && !ctx->logfile_override) {
@@ -76,7 +77,7 @@ context_finalize(struct ub_ctx* ctx)
  return UB_NOMEM;
  if(!local_zones_apply_cfg(ctx->local_zones, cfg))
  return UB_INITFAIL;
- if(!auth_zones_apply_cfg(ctx->env->auth_zones, cfg, 1))
+ if(!auth_zones_apply_cfg(ctx->env->auth_zones, cfg, 1, &is_rpz))
  return UB_INITFAIL;
  if(!slabhash_is_size(ctx->env->msg_cache, cfg->msg_cache_size,
  cfg->msg_cache_slabs)) {
Index: libunbound/libworker.c
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/libunbound/libworker.c,v
retrieving revision 1.21
diff -u -p -r1.21 libworker.c
--- libunbound/libworker.c 18 Dec 2019 11:04:13 -0000 1.21
+++ libunbound/libworker.c 15 Mar 2020 16:31:04 -0000
@@ -561,7 +561,6 @@ setup_qinfo_edns(struct libworker* w, st
  if(!qinfo->qname) {
  return 0;
  }
- qinfo->local_alias = NULL;
  edns->edns_present = 1;
  edns->ext_rcode = 0;
  edns->edns_version = 0;
Index: libunbound/unbound.h
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/libunbound/unbound.h,v
retrieving revision 1.9
diff -u -p -r1.9 unbound.h
--- libunbound/unbound.h 8 Feb 2019 10:29:08 -0000 1.9
+++ libunbound/unbound.h 15 Mar 2020 16:31:04 -0000
@@ -204,8 +204,9 @@ struct ub_result {
  char* why_bogus;
 
  /**
- * If the query or one of its subqueries was ratelimited. Useful if
- * ratelimiting is enabled and answer is SERVFAIL.
+ * If the query or one of its subqueries was ratelimited.  Useful if
+ * ratelimiting is enabled and answer to the client is SERVFAIL as a
+ * result.
  */
  int was_ratelimited;
 
@@ -654,6 +655,8 @@ struct ub_shm_stat_info {
 #define UB_STATS_OPCODE_NUM 16
 /** number of histogram buckets */
 #define UB_STATS_BUCKET_NUM 40
+/** number of RPZ actions */
+#define UB_STATS_RPZ_ACTION_NUM 10
 
 /** per worker statistics. */
 struct ub_server_stats {
@@ -733,8 +736,8 @@ struct ub_server_stats {
  long long unwanted_queries;
  /** usage of tcp accept list */
  long long tcp_accept_usage;
- /** answers served from expired cache */
- long long zero_ttl_responses;
+ /** expired answers served from cache */
+ long long ans_expired;
  /** histogram data exported to array
  * if the array is the same size, no data is lost, and
  * if all histograms are same size (is so by default) then
@@ -785,6 +788,8 @@ struct ub_server_stats {
  long long mem_stream_wait;
  /** number of TLS connection resume */
  long long qtls_resume;
+ /** RPZ action stats */
+ long long rpz_action[UB_STATS_RPZ_ACTION_NUM];
 };
 
 /**
Index: respip/respip.c
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/respip/respip.c,v
retrieving revision 1.7
diff -u -p -r1.7 respip.c
--- respip/respip.c 18 Dec 2019 11:04:13 -0000 1.7
+++ respip/respip.c 15 Mar 2020 16:31:04 -0000
@@ -12,6 +12,7 @@
 #include "config.h"
 
 #include "services/localzone.h"
+#include "services/authzone.h"
 #include "services/cache/dns.h"
 #include "sldns/str2wire.h"
 #include "util/config_file.h"
@@ -25,30 +26,6 @@
 #include "services/view.h"
 #include "sldns/rrdef.h"
 
-/**
- * Conceptual set of IP addresses for response AAAA or A records that should
- * trigger special actions.
- */
-struct respip_set {
- struct regional* region;
- struct rbtree_type ip_tree;
- char* const* tagname; /* shallow copy of tag names, for logging */
- int num_tags; /* number of tagname entries */
-};
-
-/** An address span with response control information */
-struct resp_addr {
- /** node in address tree */
- struct addr_tree_node node;
- /** tag bitlist */
- uint8_t* taglist;
- /** length of the taglist (in bytes) */
- size_t taglen;
- /** action for this address span */
- enum respip_action action;
-        /** "local data" for this node */
- struct ub_packed_rrset_key* data;
-};
 
 /** Subset of resp_addr.node, used for inform-variant logging */
 struct respip_addr_info {
@@ -88,14 +65,28 @@ respip_set_create(void)
  return NULL;
  }
  addr_tree_init(&set->ip_tree);
+ lock_rw_init(&set->lock);
  return set;
 }
 
+/** helper traverse to delete resp_addr nodes */
+static void
+resp_addr_del(rbnode_type* n, void* ATTR_UNUSED(arg))
+{
+ struct resp_addr* r = (struct resp_addr*)n->key;
+ lock_rw_destroy(&r->lock);
+#ifdef THREADS_DISABLED
+ (void)r;
+#endif
+}
+
 void
 respip_set_delete(struct respip_set* set)
 {
  if(!set)
  return;
+ lock_rw_destroy(&set->lock);
+ traverse_postorder(&set->ip_tree, resp_addr_del, NULL);
  regional_destroy(set->region);
  free(set);
 }
@@ -108,29 +99,21 @@ respip_set_get_tree(struct respip_set* s
  return &set->ip_tree;
 }
 
-/** returns the node in the address tree for the specified netblock string;
- * non-existent node will be created if 'create' is true */
-static struct resp_addr*
-respip_find_or_create(struct respip_set* set, const char* ipstr, int create)
+struct resp_addr*
+respip_sockaddr_find_or_create(struct respip_set* set, struct sockaddr_storage* addr,
+ socklen_t addrlen, int net, int create, const char* ipstr)
 {
  struct resp_addr* node;
- struct sockaddr_storage addr;
- int net;
- socklen_t addrlen;
-
- if(!netblockstrtoaddr(ipstr, 0, &addr, &addrlen, &net)) {
- log_err("cannot parse netblock: '%s'", ipstr);
- return NULL;
- }
- node = (struct resp_addr*)addr_tree_find(&set->ip_tree, &addr, addrlen, net);
+ node = (struct resp_addr*)addr_tree_find(&set->ip_tree, addr, addrlen, net);
  if(!node && create) {
  node = regional_alloc_zero(set->region, sizeof(*node));
  if(!node) {
  log_err("out of memory");
  return NULL;
  }
+ lock_rw_init(&node->lock);
  node->action = respip_none;
- if(!addr_tree_insert(&set->ip_tree, &node->node, &addr,
+ if(!addr_tree_insert(&set->ip_tree, &node->node, addr,
  addrlen, net)) {
  /* We know we didn't find it, so this should be
  * impossible. */
@@ -140,6 +123,37 @@ respip_find_or_create(struct respip_set*
  return node;
 }
 
+void
+respip_sockaddr_delete(struct respip_set* set, struct resp_addr* node)
+{
+ struct resp_addr* prev;
+ prev = (struct resp_addr*)rbtree_previous((struct rbnode_type*)node);
+ lock_rw_destroy(&node->lock);
+ rbtree_delete(&set->ip_tree, node);
+ /* no free'ing, all allocated in region */
+ if(!prev)
+ addr_tree_init_parents((rbtree_type*)set);
+ else
+ addr_tree_init_parents_node(&prev->node);
+}
+
+/** returns the node in the address tree for the specified netblock string;
+ * non-existent node will be created if 'create' is true */
+static struct resp_addr*
+respip_find_or_create(struct respip_set* set, const char* ipstr, int create)
+{
+ struct sockaddr_storage addr;
+ int net;
+ socklen_t addrlen;
+
+ if(!netblockstrtoaddr(ipstr, 0, &addr, &addrlen, &net)) {
+ log_err("cannot parse netblock: '%s'", ipstr);
+ return NULL;
+ }
+ return respip_sockaddr_find_or_create(set, &addr, addrlen, net, create,
+ ipstr);
+}
+
 static int
 respip_tag_cfg(struct respip_set* set, const char* ipstr,
  const uint8_t* taglist, size_t taglen)
@@ -191,6 +205,10 @@ respip_action_cfg(struct respip_set* set
                 action = respip_always_refuse;
         else if(strcmp(actnstr, "always_nxdomain") == 0)
                 action = respip_always_nxdomain;
+        else if(strcmp(actnstr, "always_nodata") == 0)
+                action = respip_always_nodata;
+        else if(strcmp(actnstr, "always_deny") == 0)
+                action = respip_always_deny;
         else {
                 log_err("unknown response-ip action %s", actnstr);
                 return 0;
@@ -232,8 +250,43 @@ new_rrset(struct regional* region, uint1
 }
 
 /** enter local data as resource records into a response-ip node */
-static int
+
+int
 respip_enter_rr(struct regional* region, struct resp_addr* raddr,
+ uint16_t rrtype, uint16_t rrclass, time_t ttl, uint8_t* rdata,
+ size_t rdata_len, const char* rrstr, const char* netblockstr)
+{
+ struct packed_rrset_data* pd;
+ struct sockaddr* sa;
+ sa = (struct sockaddr*)&raddr->node.addr;
+ if (rrtype == LDNS_RR_TYPE_CNAME && raddr->data) {
+ log_err("CNAME response-ip data (%s) can not co-exist with other "
+ "response-ip data for netblock %s", rrstr, netblockstr);
+ return 0;
+ } else if (raddr->data &&
+ raddr->data->rk.type == htons(LDNS_RR_TYPE_CNAME)) {
+ log_err("response-ip data (%s) can not be added; CNAME response-ip "
+ "data already in place for netblock %s", rrstr, netblockstr);
+ return 0;
+ } else if((rrtype != LDNS_RR_TYPE_CNAME) &&
+ ((sa->sa_family == AF_INET && rrtype != LDNS_RR_TYPE_A) ||
+ (sa->sa_family == AF_INET6 && rrtype != LDNS_RR_TYPE_AAAA))) {
+ log_err("response-ip data %s record type does not correspond "
+ "to netblock %s address family", rrstr, netblockstr);
+ return 0;
+ }
+
+ if(!raddr->data) {
+ raddr->data = new_rrset(region, rrtype, rrclass);
+ if(!raddr->data)
+ return 0;
+ }
+ pd = raddr->data->entry.data;
+ return rrset_insert_rr(region, pd, rdata, rdata_len, ttl, rrstr);
+}
+
+static int
+respip_enter_rrstr(struct regional* region, struct resp_addr* raddr,
  const char* rrstr, const char* netblock)
 {
  uint8_t* nm;
@@ -244,8 +297,6 @@ respip_enter_rr(struct regional* region,
  size_t rdata_len = 0;
  char buf[65536];
  char bufshort[64];
- struct packed_rrset_data* pd;
- struct sockaddr* sa;
  int ret;
  if(raddr->action != respip_redirect
  && raddr->action != respip_inform_redirect) {
@@ -265,31 +316,8 @@ respip_enter_rr(struct regional* region,
  return 0;
  }
  free(nm);
- sa = (struct sockaddr*)&raddr->node.addr;
- if (rrtype == LDNS_RR_TYPE_CNAME && raddr->data) {
- log_err("CNAME response-ip data (%s) can not co-exist with other "
- "response-ip data for netblock %s", rrstr, netblock);
- return 0;
- } else if (raddr->data &&
- raddr->data->rk.type == htons(LDNS_RR_TYPE_CNAME)) {
- log_err("response-ip data (%s) can not be added; CNAME response-ip "
- "data already in place for netblock %s", rrstr, netblock);
- return 0;
- } else if((rrtype != LDNS_RR_TYPE_CNAME) &&
- ((sa->sa_family == AF_INET && rrtype != LDNS_RR_TYPE_A) ||
- (sa->sa_family == AF_INET6 && rrtype != LDNS_RR_TYPE_AAAA))) {
- log_err("response-ip data %s record type does not correspond "
- "to netblock %s address family", rrstr, netblock);
- return 0;
- }
-
- if(!raddr->data) {
- raddr->data = new_rrset(region, rrtype, rrclass);
- if(!raddr->data)
- return 0;
- }
- pd = raddr->data->entry.data;
- return rrset_insert_rr(region, pd, rdata, rdata_len, ttl, rrstr);
+ return respip_enter_rr(region, raddr, rrtype, rrclass, ttl, rdata,
+ rdata_len, rrstr, netblock);
 }
 
 static int
@@ -303,7 +331,7 @@ respip_data_cfg(struct respip_set* set,
  "response-ip node for %s not found", rrstr, ipstr);
  return 0;
  }
- return respip_enter_rr(set->region, node, rrstr, ipstr);
+ return respip_enter_rrstr(set->region, node, rrstr, ipstr);
 }
 
 static int
@@ -564,9 +592,10 @@ rdata2sockaddr(const struct packed_rrset
  * rep->rrsets for the RRset that contains the matching IP address record
  * (the index is normally 0, but can be larger than that if this is a CNAME
  * chain or type-ANY response).
+ * Returns resp_addr holding read lock.
  */
-static const struct resp_addr*
-respip_addr_lookup(const struct reply_info *rep, struct rbtree_type* iptree,
+static struct resp_addr*
+respip_addr_lookup(const struct reply_info *rep, struct respip_set* rs,
  size_t* rrset_id)
 {
  size_t i;
@@ -574,6 +603,7 @@ respip_addr_lookup(const struct reply_in
  struct sockaddr_storage ss;
  socklen_t addrlen;
 
+ lock_rw_rdlock(&rs->lock);
  for(i=0; i<rep->an_numrrsets; i++) {
  size_t j;
  const struct packed_rrset_data* rd;
@@ -585,15 +615,17 @@ respip_addr_lookup(const struct reply_in
  for(j = 0; j < rd->count; j++) {
  if(!rdata2sockaddr(rd, rtype, j, &ss, &addrlen))
  continue;
- ra = (struct resp_addr*)addr_tree_lookup(iptree, &ss,
- addrlen);
+ ra = (struct resp_addr*)addr_tree_lookup(&rs->ip_tree,
+ &ss, addrlen);
  if(ra) {
  *rrset_id = i;
+ lock_rw_rdlock(&ra->lock);
+ lock_rw_unlock(&rs->lock);
  return ra;
  }
  }
  }
-
+ lock_rw_unlock(&rs->lock);
  return NULL;
 }
 
@@ -642,8 +674,8 @@ make_new_reply_info(const struct reply_i
  * Note that this function distinguishes error conditions from "success but
  * not overridden".  This is because we want to avoid accidentally applying
  * the "no data" action in case of error.
- * @param raddr: address span that requires an action
  * @param action: action to apply
+ * @param data: RRset to use for override
  * @param qtype: original query type
  * @param rep: original reply message
  * @param rrset_id: the rrset ID in 'rep' to which the action should apply
@@ -658,14 +690,15 @@ make_new_reply_info(const struct reply_i
  * @return 1 if overridden, 0 if not overridden, -1 on error.
  */
 static int
-respip_data_answer(const struct resp_addr* raddr, enum respip_action action,
+respip_data_answer(enum respip_action action,
+ struct ub_packed_rrset_key* data,
  uint16_t qtype, const struct reply_info* rep,
  size_t rrset_id, struct reply_info** new_repp, int tag,
  struct config_strlist** tag_datas, size_t tag_datas_size,
  char* const* tagname, int num_tags,
  struct ub_packed_rrset_key** redirect_rrsetp, struct regional* region)
 {
- struct ub_packed_rrset_key* rp = raddr->data;
+ struct ub_packed_rrset_key* rp = data;
  struct reply_info* new_rep;
  *redirect_rrsetp = NULL;
 
@@ -703,7 +736,7 @@ respip_data_answer(const struct resp_add
  * to replace the rrset's dname.  Note that, unlike local data, we
  * rename the dname for other actions than redirect.  This is because
  * response-ip-data isn't associated to any specific name. */
- if(rp == raddr->data) {
+ if(rp == data) {
  rp = copy_rrset(rp, region);
  if(!rp)
  return -1;
@@ -761,6 +794,7 @@ respip_nodata_answer(uint16_t qtype, enu
  return 1;
  } else if(action == respip_static || action == respip_redirect ||
  action == respip_always_nxdomain ||
+ action == respip_always_nodata ||
  action == respip_inform_redirect) {
  /* Since we don't know about other types of the owner name,
  * we generally return NOERROR/NODATA unless an NXDOMAIN action
@@ -794,16 +828,22 @@ populate_action_info(struct respip_actio
  enum respip_action action, const struct resp_addr* raddr,
  const struct ub_packed_rrset_key* ATTR_UNUSED(rrset),
  int ATTR_UNUSED(tag), const struct respip_set* ATTR_UNUSED(ipset),
- int ATTR_UNUSED(action_only), struct regional* region)
+ int ATTR_UNUSED(action_only), struct regional* region, int rpz_used,
+ int rpz_log, char* log_name, int rpz_cname_override)
 {
  if(action == respip_none || !raddr)
  return 1;
  actinfo->action = action;
+ actinfo->rpz_used = rpz_used;
+ actinfo->rpz_log = rpz_log;
+ actinfo->log_name = log_name;
+ actinfo->rpz_cname_override = rpz_cname_override;
 
  /* for inform variants, make a copy of the matched address block for
  * later logging.  We make a copy to proactively avoid disruption if
  *  and when we allow a dynamic update to the respip tree. */
- if(action == respip_inform || action == respip_inform_deny) {
+ if(action == respip_inform || action == respip_inform_deny ||
+ rpz_used) {
  struct respip_addr_info* a =
  regional_alloc_zero(region, sizeof(*a));
  if(!a) {
@@ -819,12 +859,39 @@ populate_action_info(struct respip_actio
  return 1;
 }
 
+static int
+respip_use_rpz(struct resp_addr* raddr, struct rpz* r,
+ enum respip_action* action,
+ struct ub_packed_rrset_key** data, int* rpz_log, char** log_name,
+ int* rpz_cname_override, struct regional* region, int* is_rpz)
+{
+ if(r->action_override == RPZ_DISABLED_ACTION) {
+ *is_rpz = 0;
+ return 1;
+ }
+ else if(r->action_override == RPZ_NO_OVERRIDE_ACTION)
+ *action = raddr->action;
+ else
+ *action = rpz_action_to_respip_action(r->action_override);
+ if(r->action_override == RPZ_CNAME_OVERRIDE_ACTION &&
+ r->cname_override) {
+ *data = r->cname_override;
+ *rpz_cname_override = 1;
+ }
+ *rpz_log = r->log;
+ if(r->log_name)
+ if(!(*log_name = regional_strdup(region, r->log_name)))
+ return 0;
+ *is_rpz = 1;
+ return 1;
+}
+
 int
 respip_rewrite_reply(const struct query_info* qinfo,
  const struct respip_client_info* cinfo, const struct reply_info* rep,
  struct reply_info** new_repp, struct respip_action_info* actinfo,
  struct ub_packed_rrset_key** alias_rrset, int search_only,
- struct regional* region)
+ struct regional* region, struct auth_zones* az)
 {
  const uint8_t* ctaglist;
  size_t ctaglen;
@@ -837,9 +904,15 @@ respip_rewrite_reply(const struct query_
  size_t rrset_id = 0;
  enum respip_action action = respip_none;
  int tag = -1;
- const struct resp_addr* raddr = NULL;
+ struct resp_addr* raddr = NULL;
  int ret = 1;
  struct ub_packed_rrset_key* redirect_rrset = NULL;
+ struct rpz* r;
+ struct ub_packed_rrset_key* data = NULL;
+ int rpz_used = 0;
+ int rpz_log = 0;
+ int rpz_cname_override = 0;
+ char* log_name = NULL;
 
  if(!cinfo)
  goto done;
@@ -852,6 +925,8 @@ respip_rewrite_reply(const struct query_
  view = cinfo->view;
  ipset = cinfo->respip_set;
 
+ log_assert(ipset);
+
  /** Try to use response-ip config from the view first; use
   * global response-ip config if we don't have the view or we don't
   * have the matching per-view config (and the view allows the use
@@ -866,7 +941,7 @@ respip_rewrite_reply(const struct query_
  lock_rw_rdlock(&view->lock);
  if(view->respip_set) {
  if((raddr = respip_addr_lookup(rep,
- &view->respip_set->ip_tree, &rrset_id))) {
+ view->respip_set, &rrset_id))) {
  /** for per-view respip directives the action
  * can only be direct (i.e. not tag-based) */
  action = raddr->action;
@@ -875,7 +950,7 @@ respip_rewrite_reply(const struct query_
  if(!raddr && !view->isfirst)
  goto done;
  }
- if(!raddr && ipset && (raddr = respip_addr_lookup(rep, &ipset->ip_tree,
+ if(!raddr && (raddr = respip_addr_lookup(rep, ipset,
  &rrset_id))) {
  action = (enum respip_action)local_data_find_tag_action(
  raddr->taglist, raddr->taglen, ctaglist, ctaglen,
@@ -883,6 +958,29 @@ respip_rewrite_reply(const struct query_
  (enum localzone_type)raddr->action, &tag,
  ipset->tagname, ipset->num_tags);
  }
+ lock_rw_rdlock(&az->rpz_lock);
+ for(r = az->rpz_first; r && !raddr; r = r->next) {
+ if(!r->taglist || taglist_intersect(r->taglist,
+ r->taglistlen, ctaglist, ctaglen)) {
+ if((raddr = respip_addr_lookup(rep,
+ r->respip_set, &rrset_id))) {
+ if(!respip_use_rpz(raddr, r, &action, &data,
+ &rpz_log, &log_name, &rpz_cname_override,
+ region, &rpz_used)) {
+ log_err("out of memory");
+ lock_rw_unlock(&raddr->lock);
+ lock_rw_unlock(&az->rpz_lock);
+ return 0;
+ }
+ if(!rpz_used) {
+ lock_rw_unlock(&raddr->lock);
+ raddr = NULL;
+ actinfo->rpz_disabled++;
+ }
+ }
+ }
+ }
+ lock_rw_unlock(&az->rpz_lock);
  if(raddr && !search_only) {
  int result = 0;
 
@@ -891,10 +989,13 @@ respip_rewrite_reply(const struct query_
  if(action != respip_always_refuse
  && action != respip_always_transparent
  && action != respip_always_nxdomain
- && (result = respip_data_answer(raddr, action,
- qinfo->qtype, rep, rrset_id, new_repp, tag, tag_datas,
- tag_datas_size, ipset->tagname, ipset->num_tags,
- &redirect_rrset, region)) < 0) {
+ && action != respip_always_nodata
+ && action != respip_always_deny
+ && (result = respip_data_answer(action,
+ (data) ? data : raddr->data, qinfo->qtype, rep,
+ rrset_id, new_repp, tag, tag_datas, tag_datas_size,
+ ipset->tagname, ipset->num_tags, &redirect_rrset,
+ region)) < 0) {
  ret = 0;
  goto done;
  }
@@ -925,7 +1026,11 @@ respip_rewrite_reply(const struct query_
  *alias_rrset = redirect_rrset;
  /* on success, populate respip result structure */
  ret = populate_action_info(actinfo, action, raddr,
- redirect_rrset, tag, ipset, search_only, region);
+ redirect_rrset, tag, ipset, search_only, region,
+ rpz_used, rpz_log, log_name, rpz_cname_override);
+ }
+ if(raddr) {
+ lock_rw_unlock(&raddr->lock);
  }
  return ret;
 }
@@ -981,14 +1086,15 @@ respip_operate(struct module_qstate* qst
  qstate->qinfo.qtype == LDNS_RR_TYPE_AAAA ||
  qstate->qinfo.qtype == LDNS_RR_TYPE_ANY) &&
  qstate->return_msg && qstate->return_msg->rep) {
- struct respip_action_info actinfo = {respip_none, NULL};
  struct reply_info* new_rep = qstate->return_msg->rep;
  struct ub_packed_rrset_key* alias_rrset = NULL;
+ struct respip_action_info actinfo = {0};
+ actinfo.action = respip_none;
 
  if(!respip_rewrite_reply(&qstate->qinfo,
  qstate->client_info, qstate->return_msg->rep,
  &new_rep, &actinfo, &alias_rrset, 0,
- qstate->region)) {
+ qstate->region, qstate->env->auth_zones)) {
  goto servfail;
  }
  if(actinfo.action != respip_none) {
@@ -1004,9 +1110,10 @@ respip_operate(struct module_qstate* qst
  } else {
  qstate->respip_action_info = NULL;
  }
- if (new_rep == qstate->return_msg->rep &&
+ if (actinfo.action == respip_always_deny ||
+ (new_rep == qstate->return_msg->rep &&
  (actinfo.action == respip_deny ||
- actinfo.action == respip_inform_deny)) {
+ actinfo.action == respip_inform_deny))) {
  /* for deny-variant actions (unless response-ip
  * data is applied), mark the query state so
  * the response will be dropped for all
@@ -1034,14 +1141,16 @@ int
 respip_merge_cname(struct reply_info* base_rep,
  const struct query_info* qinfo, const struct reply_info* tgt_rep,
  const struct respip_client_info* cinfo, int must_validate,
- struct reply_info** new_repp, struct regional* region)
+ struct reply_info** new_repp, struct regional* region,
+ struct auth_zones* az)
 {
  struct reply_info* new_rep;
  struct reply_info* tmp_rep = NULL; /* just a placeholder */
  struct ub_packed_rrset_key* alias_rrset = NULL; /* ditto */
  uint16_t tgt_rcode;
  size_t i, j;
- struct respip_action_info actinfo = {respip_none, NULL};
+ struct respip_action_info actinfo = {0};
+ actinfo.action = respip_none;
 
  /* If the query for the CNAME target would result in an unusual rcode,
  * we generally translate it as a failure for the base query
@@ -1060,7 +1169,7 @@ respip_merge_cname(struct reply_info* ba
 
  /* see if the target reply would be subject to a response-ip action. */
  if(!respip_rewrite_reply(qinfo, cinfo, tgt_rep, &tmp_rep, &actinfo,
- &alias_rrset, 1, region))
+ &alias_rrset, 1, region, az))
  return 0;
  if(actinfo.action != respip_none) {
  log_info("CNAME target of redirect response-ip action would "
@@ -1112,7 +1221,8 @@ respip_inform_super(struct module_qstate
 
  if(!respip_merge_cname(super->return_msg->rep, &qstate->qinfo,
  qstate->return_msg->rep, super->client_info,
- super->env->need_to_validate, &new_rep, super->region))
+ super->env->need_to_validate, &new_rep, super->region,
+ qstate->env->auth_zones))
  goto fail;
  super->return_msg->rep = new_rep;
  return;
@@ -1171,12 +1281,15 @@ respip_set_is_empty(const struct respip_
 }
 
 void
-respip_inform_print(struct respip_addr_info* respip_addr, uint8_t* qname,
+respip_inform_print(struct respip_action_info* respip_actinfo, uint8_t* qname,
  uint16_t qtype, uint16_t qclass, struct local_rrset* local_alias,
  struct comm_reply* repinfo)
 {
  char srcip[128], respip[128], txt[512];
  unsigned port;
+ struct respip_addr_info* respip_addr = respip_actinfo->addrinfo;
+ size_t txtlen = 0;
+ const char* actionstr = NULL;
 
  if(local_alias)
  qname = local_alias->rrset->rk.dname;
@@ -1186,7 +1299,23 @@ respip_inform_print(struct respip_addr_i
  addr_to_str(&repinfo->addr, repinfo->addrlen, srcip, sizeof(srcip));
  addr_to_str(&respip_addr->addr, respip_addr->addrlen,
  respip, sizeof(respip));
- snprintf(txt, sizeof(txt), "%s/%d inform %s@%u", respip,
- respip_addr->net, srcip, port);
+ if(respip_actinfo->rpz_log) {
+ txtlen += snprintf(txt+txtlen, sizeof(txt)-txtlen, "%s",
+ "RPZ applied ");
+ if(respip_actinfo->rpz_cname_override)
+ actionstr = rpz_action_to_string(
+ RPZ_CNAME_OVERRIDE_ACTION);
+ else
+ actionstr = rpz_action_to_string(
+ respip_action_to_rpz_action(
+ respip_actinfo->action));
+ }
+ if(respip_actinfo->log_name) {
+ txtlen += snprintf(txt+txtlen, sizeof(txt)-txtlen,
+ "[%s] ", respip_actinfo->log_name);
+ }
+ snprintf(txt+txtlen, sizeof(txt)-txtlen,
+ "%s/%d %s %s@%u", respip, respip_addr->net,
+ (actionstr) ? actionstr : "inform", srcip, port);
  log_nametypeclass(NO_VERBOSE, txt, qname, qtype, qclass);
 }
Index: respip/respip.h
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/respip/respip.h,v
retrieving revision 1.1
diff -u -p -r1.1 respip.h
--- respip/respip.h 12 Aug 2017 11:22:46 -0000 1.1
+++ respip/respip.h 15 Mar 2020 16:31:04 -0000
@@ -14,23 +14,42 @@
 
 #include "util/module.h"
 #include "services/localzone.h"
+#include "util/locks.h"
 
 /**
- * Set of response IP addresses with associated actions and tags.
- * Forward declaration only here.  Actual definition is hidden within the
- * module.
+ * Conceptual set of IP addresses for response AAAA or A records that should
+ * trigger special actions.
  */
-struct respip_set;
+struct respip_set {
+ struct regional* region;
+ struct rbtree_type ip_tree;
+ lock_rw_type lock; /* lock on the respip tree */
+ char* const* tagname; /* shallow copy of tag names, for logging */
+ int num_tags; /* number of tagname entries */
+};
+
+
+/** An address span with response control information */
+struct resp_addr {
+ /** node in address tree */
+ struct addr_tree_node node;
+ /** lock on the node item */
+ lock_rw_type lock;
+ /** tag bitlist */
+ uint8_t* taglist;
+ /** length of the taglist (in bytes) */
+ size_t taglen;
+ /** action for this address span */
+ enum respip_action action;
+        /** "local data" for this node */
+ struct ub_packed_rrset_key* data;
+};
 
-/**
- * Forward declaration for the structure that represents a node in the
- * respip_set address tree
- */
-struct resp_addr;
 
 /**
  * Forward declaration for the structure that represents a tree of view data.
  */
+
 struct views;
 
 struct respip_addr_info;
@@ -60,6 +79,11 @@ struct respip_client_info {
  */
 struct respip_action_info {
  enum respip_action action;
+ int rpz_used;
+ int rpz_log;
+ int rpz_disabled;
+ char* log_name;
+ int rpz_cname_override;
  struct respip_addr_info* addrinfo; /* set only for inform variants */
 };
 
@@ -124,12 +148,14 @@ int respip_views_apply_cfg(struct views*
  * @param new_repp: pointer placeholder for the merged reply.  will be intact
  *   on error.
  * @param region: allocator to build *new_repp.
+ * @param az: auth zones containing RPZ information.
  * @return 1 on success, 0 on error.
  */
 int respip_merge_cname(struct reply_info* base_rep,
  const struct query_info* qinfo, const struct reply_info* tgt_rep,
  const struct respip_client_info* cinfo, int must_validate,
- struct reply_info** new_repp, struct regional* region);
+ struct reply_info** new_repp, struct regional* region,
+ struct auth_zones* az);
 
 /**
  * See if any IP-based action should apply to any IP address of AAAA/A answer
@@ -148,6 +174,7 @@ int respip_merge_cname(struct reply_info
  * @param alias_rrset: must not be NULL.
  * @param search_only: if true, only check if an action would apply.  actionp
  *   will be set (or intact) accordingly but the modified reply won't be built.
+ * @param az: auth zones containing RPZ information.
  * @param region: allocator to build *new_repp.
  * @return 1 on success, 0 on error.
  */
@@ -156,7 +183,7 @@ int respip_rewrite_reply(const struct qu
  const struct reply_info *rep, struct reply_info** new_repp,
  struct respip_action_info* actinfo,
  struct ub_packed_rrset_key** alias_rrset,
- int search_only, struct regional* region);
+ int search_only, struct regional* region, struct auth_zones* az);
 
 /**
  * Get the response-ip function block.
@@ -213,7 +240,7 @@ int respip_set_is_empty(const struct res
 /**
  * print log information for a query subject to an inform or inform-deny
  * response-ip action.
- * @param respip_addr: response-ip information that causes the action
+ * @param respip_actinfo: response-ip information that causes the action
  * @param qname: query name in the context, will be ignored if local_alias is
  *   non-NULL.
  * @param qtype: query type, in host byte order.
@@ -223,8 +250,48 @@ int respip_set_is_empty(const struct res
  *  query name.
  * @param repinfo: reply info containing the client's source address and port.
  */
-void respip_inform_print(struct respip_addr_info* respip_addr, uint8_t* qname,
- uint16_t qtype, uint16_t qclass, struct local_rrset* local_alias,
- struct comm_reply* repinfo);
-
+void respip_inform_print(struct respip_action_info* respip_actinfo,
+ uint8_t* qname, uint16_t qtype, uint16_t qclass,
+ struct local_rrset* local_alias, struct comm_reply* repinfo);
+
+/**
+ * Find resp_addr in tree, create and add to tree if it does not exist.
+ * @param set: struct containing the tree and region to alloc new node on.
+ * should hold write lock.
+ * @param addr: address to look up.
+ * @param addrlen: length of addr.
+ * @param net: netblock to lookup.
+ * @param create: create node if it does not exist when 1.
+ * @param ipstr: human redable ip string, for logging.
+ * @return newly created of found node, not holding lock.
+ */
+struct resp_addr*
+respip_sockaddr_find_or_create(struct respip_set* set, struct sockaddr_storage* addr,
+ socklen_t addrlen, int net, int create, const char* ipstr);
+
+/**
+ * Add RR to resp_addr's RRset. Create RRset if not existing.
+ * @param region: region to alloc RR(set).
+ * @param raddr: resp_addr containing RRset. Must hold write lock.
+ * @param rrtype: RR type.
+ * @param rrclass: RR class.
+ * @param ttl: TTL.
+ * @param rdata: RDATA.
+ * @param rdata_len: length of rdata.
+ * @param rrstr: RR as string, for logging
+ * @param netblockstr: netblock as string, for logging
+ * @return 0 on error
+ */
+int
+respip_enter_rr(struct regional* region, struct resp_addr* raddr,
+ uint16_t rrtype, uint16_t rrclass, time_t ttl, uint8_t* rdata,
+ size_t rdata_len, const char* rrstr, const char* netblockstr);
+
+/**
+ * Delete resp_addr node from tree.
+ * @param set: struct containing tree. Must hold write lock.
+ * @param node: node to delete. Not locked.
+ */
+void
+respip_sockaddr_delete(struct respip_set* set, struct resp_addr* node);
 #endif /* RESPIP_RESPIP_H */
Index: services/authzone.c
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/services/authzone.c,v
retrieving revision 1.13
diff -u -p -r1.13 authzone.c
--- services/authzone.c 18 Dec 2019 11:04:14 -0000 1.13
+++ services/authzone.c 15 Mar 2020 16:31:04 -0000
@@ -299,6 +299,8 @@ struct auth_zones* auth_zones_create(voi
  lock_protect(&az->lock, &az->ztree, sizeof(az->ztree));
  lock_protect(&az->lock, &az->xtree, sizeof(az->xtree));
  /* also lock protects the rbnode's in struct auth_zone, auth_xfer */
+ lock_rw_init(&az->rpz_lock);
+ lock_protect(&az->rpz_lock, &az->rpz_first, sizeof(az->rpz_first));
  return az;
 }
 
@@ -381,11 +383,25 @@ auth_data_del(rbnode_type* n, void* ATTR
 
 /** delete an auth zone structure (tree remove must be done elsewhere) */
 static void
-auth_zone_delete(struct auth_zone* z)
+auth_zone_delete(struct auth_zone* z, struct auth_zones* az)
 {
  if(!z) return;
  lock_rw_destroy(&z->lock);
  traverse_postorder(&z->data, auth_data_del, NULL);
+
+ if(az && z->rpz) {
+ /* keep RPZ linked list intact */
+ lock_rw_wrlock(&az->rpz_lock);
+ if(z->rpz->prev)
+ z->rpz->prev->next = z->rpz->next;
+ else
+ az->rpz_first = z->rpz->next;
+ if(z->rpz->next)
+ z->rpz->next->prev = z->rpz->prev;
+ lock_rw_unlock(&az->rpz_lock);
+ }
+ if(z->rpz)
+ rpz_delete(z->rpz);
  free(z->name);
  free(z->zonefile);
  free(z);
@@ -415,7 +431,7 @@ auth_zone_create(struct auth_zones* az,
  /* z lock protects all, except rbtree itself, which is az->lock */
  if(!rbtree_insert(&az->ztree, &z->node)) {
  lock_rw_unlock(&z->lock);
- auth_zone_delete(z);
+ auth_zone_delete(z, NULL);
  log_warn("duplicate auth zone");
  return NULL;
  }
@@ -660,23 +676,6 @@ domain_remove_rrset(struct auth_data* no
  }
 }
 
-/** find an rr index in the rrset.  returns true if found */
-static int
-az_rrset_find_rr(struct packed_rrset_data* d, uint8_t* rdata, size_t len,
- size_t* index)
-{
- size_t i;
- for(i=0; i<d->count; i++) {
- if(d->rr_len[i] != len)
- continue;
- if(memcmp(d->rr_data[i], rdata, len) == 0) {
- *index = i;
- return 1;
- }
- }
- return 0;
-}
-
 /** find an rrsig index in the rrset.  returns true if found */
 static int
 az_rrset_find_rrsig(struct packed_rrset_data* d, uint8_t* rdata, size_t len,
@@ -1178,6 +1177,12 @@ az_insert_rr(struct auth_zone* z, uint8_
  log_err("cannot add RR to domain");
  return 0;
  }
+ if(z->rpz) {
+ if(!(rpz_insert_rr(z->rpz, z->namelen, dname, dname_len,
+ rr_type, rr_class, rr_ttl, rdata, rdatalen, rr,
+ rr_len)))
+ return 0;
+ }
  return 1;
 }
 
@@ -1192,7 +1197,7 @@ az_domain_remove_rr(struct auth_data* no
 
  /* find the plain RR of the given type */
  if((rrset=az_domain_rrset(node, rr_type))!= NULL) {
- if(az_rrset_find_rr(rrset->data, rdata, rdatalen, &index)) {
+ if(packed_rrset_find_rr(rrset->data, rdata, rdatalen, &index)) {
  if(rrset->data->count == 1 &&
  rrset->data->rrsig_count == 0) {
  /* last RR, delete the rrset */
@@ -1293,6 +1298,10 @@ az_remove_rr(struct auth_zone* z, uint8_
  (void)rbtree_delete(&z->data, node);
  auth_data_delete(node);
  }
+ if(z->rpz) {
+ rpz_remove_rr(z->rpz, z->namelen, dname, dname_len, rr_type,
+ rr_class, rdata, rdatalen);
+ }
  return 1;
 }
 
@@ -1585,6 +1594,9 @@ auth_zone_read_zonefile(struct auth_zone
  /* clear the data tree */
  traverse_postorder(&z->data, auth_data_del, NULL);
  rbtree_init(&z->data, &auth_data_cmp);
+ /* clear the RPZ policies */
+ if(z->rpz)
+ rpz_clear(z->rpz);
 
  memset(&state, 0, sizeof(state));
  /* default TTL to 3600 */
@@ -1604,6 +1616,9 @@ auth_zone_read_zonefile(struct auth_zone
  return 0;
  }
  fclose(in);
+
+ if(z->rpz)
+ rpz_finish_config(z->rpz);
  return 1;
 }
 
@@ -1877,6 +1892,18 @@ auth_zones_cfg(struct auth_zones* az, st
  z->for_downstream = c->for_downstream;
  z->for_upstream = c->for_upstream;
  z->fallback_enabled = c->fallback_enabled;
+ if(c->isrpz && !z->rpz){
+ if(!(z->rpz = rpz_create(c))){
+ fatal_exit("Could not setup RPZ zones");
+ return 0;
+ }
+ lock_rw_wrlock(&az->rpz_lock);
+ z->rpz->next = az->rpz_first;
+ if(az->rpz_first)
+ az->rpz_first->prev = z->rpz;
+ az->rpz_first = z->rpz;
+ lock_rw_unlock(&az->rpz_lock);
+ }
 
  /* xfer zone */
  if(x) {
@@ -1947,14 +1974,14 @@ az_delete_deleted_zones(struct auth_zone
  auth_xfer_delete(xfr);
  }
  (void)rbtree_delete(&az->ztree, &z->node);
- auth_zone_delete(z);
+ auth_zone_delete(z, az);
  z = next;
  }
  lock_rw_unlock(&az->lock);
 }
 
 int auth_zones_apply_cfg(struct auth_zones* az, struct config_file* cfg,
- int setup)
+ int setup, int* is_rpz)
 {
  struct config_auth* p;
  az_setall_deleted(az);
@@ -1963,6 +1990,7 @@ int auth_zones_apply_cfg(struct auth_zon
  log_warn("auth-zone without a name, skipped");
  continue;
  }
+ *is_rpz = (*is_rpz || p->isrpz);
  if(!auth_zones_cfg(az, p)) {
  log_err("cannot config auth zone %s", p->name);
  return 0;
@@ -2063,7 +2091,7 @@ static void
 auth_zone_del(rbnode_type* n, void* ATTR_UNUSED(arg))
 {
  struct auth_zone* z = (struct auth_zone*)n->key;
- auth_zone_delete(z);
+ auth_zone_delete(z, NULL);
 }
 
 /** helper traverse to delete xfer zones */
@@ -2078,6 +2106,7 @@ void auth_zones_delete(struct auth_zones
 {
  if(!az) return;
  lock_rw_destroy(&az->lock);
+ lock_rw_destroy(&az->rpz_lock);
  traverse_postorder(&az->ztree, auth_zone_del, NULL);
  traverse_postorder(&az->xtree, auth_xfer_del, NULL);
  free(az);
@@ -2586,12 +2615,14 @@ az_nsec3_hash(uint8_t* buf, size_t bufle
  /* hashfunc(name, salt) */
  memmove(p, nm, nmlen);
  query_dname_tolower(p);
- memmove(p+nmlen, salt, saltlen);
+ if(salt && saltlen > 0)
+ memmove(p+nmlen, salt, saltlen);
  (void)secalgo_nsec3_hash(algo, p, nmlen+saltlen, (unsigned char*)buf);
  for(i=0; i<iter; i++) {
  /* hashfunc(hash, salt) */
  memmove(p, buf, hlen);
- memmove(p+hlen, salt, saltlen);
+ if(salt && saltlen > 0)
+ memmove(p+hlen, salt, saltlen);
  (void)secalgo_nsec3_hash(algo, p, hlen+saltlen,
  (unsigned char*)buf);
  }
@@ -4688,6 +4719,10 @@ apply_axfr(struct auth_xfer* xfr, struct
  /* clear the data tree */
  traverse_postorder(&z->data, auth_data_del, NULL);
  rbtree_init(&z->data, &auth_data_cmp);
+ /* clear the RPZ policies */
+ if(z->rpz)
+ rpz_clear(z->rpz);
+
  xfr->have_zone = 0;
  xfr->serial = 0;
 
@@ -4784,6 +4819,10 @@ apply_http(struct auth_xfer* xfr, struct
  /* clear the data tree */
  traverse_postorder(&z->data, auth_data_del, NULL);
  rbtree_init(&z->data, &auth_data_cmp);
+ /* clear the RPZ policies */
+ if(z->rpz)
+ rpz_clear(z->rpz);
+
  xfr->have_zone = 0;
  xfr->serial = 0;
 
@@ -4969,6 +5008,9 @@ xfr_process_chunk_list(struct auth_xfer*
  if(xfr->have_zone)
  xfr->lease_time = *env->now;
 
+ if(z->rpz)
+ rpz_finish_config(z->rpz);
+
  /* unlock */
  lock_rw_unlock(&z->lock);
 
@@ -5530,9 +5572,12 @@ check_xfer_packet(sldns_buffer* pkt, str
  xfr->task_transfer->rr_scan_num == 0 &&
  LDNS_ANCOUNT(wire)==1) {
  verbose(VERB_ALGO, "xfr to %s ended, "
- "IXFR reply that zone has serial %u",
+ "IXFR reply that zone has serial %u,"
+ " fallback from IXFR to AXFR",
  xfr->task_transfer->master->host,
  (unsigned)serial);
+ xfr->task_transfer->ixfr_fail = 1;
+ *gonextonfail = 0;
  return 0;
  }
 
Index: services/authzone.h
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/services/authzone.h,v
retrieving revision 1.8
diff -u -p -r1.8 authzone.h
--- services/authzone.h 28 Jun 2019 15:17:16 -0000 1.8
+++ services/authzone.h 15 Mar 2020 16:31:04 -0000
@@ -46,6 +46,7 @@
 #include "util/rbtree.h"
 #include "util/locks.h"
 #include "services/mesh.h"
+#include "services/rpz.h"
 struct ub_packed_rrset_key;
 struct regional;
 struct config_file;
@@ -81,6 +82,11 @@ struct auth_zones {
  size_t num_query_up;
  /** number of queries downstream */
  size_t num_query_down;
+ /** first rpz item in linked list */
+ struct rpz* rpz_first;
+ /** rw lock for rpz linked list, needed when iterating or editing linked
+ * list. */
+ lock_rw_type rpz_lock;
 };
 
 /**
@@ -126,6 +132,8 @@ struct auth_zone {
  /** for upstream: this zone answers queries that unbound intends to
  * send upstream. */
  int for_upstream;
+ /** RPZ zones */
+ struct rpz* rpz;
  /** zone has been deleted */
  int zone_deleted;
  /** deletelist pointer, unused normally except during delete */
@@ -460,10 +468,11 @@ struct auth_zones* auth_zones_create(voi
  * @param az: auth zones structure
  * @param cfg: config to apply.
  * @param setup: if true, also sets up values in the auth zones structure
+ * @param is_rpz: set to 1 if at least one RPZ zone is configured.
  * @return false on failure.
  */
 int auth_zones_apply_cfg(struct auth_zones* az, struct config_file* cfg,
- int setup);
+ int setup, int* is_rpz);
 
 /** initial pick up of worker timeouts, ties events to worker event loop
  * @param az: auth zones structure
Index: services/localzone.c
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/services/localzone.c,v
retrieving revision 1.11
diff -u -p -r1.11 localzone.c
--- services/localzone.c 18 Dec 2019 11:04:14 -0000 1.11
+++ services/localzone.c 15 Mar 2020 16:31:04 -0000
@@ -41,7 +41,6 @@
 #include "config.h"
 #include "services/localzone.h"
 #include "sldns/str2wire.h"
-#include "sldns/sbuffer.h"
 #include "util/regional.h"
 #include "util/config_file.h"
 #include "util/data/dname.h"
@@ -395,9 +394,30 @@ rrset_insert_rr(struct regional* region,
  return 1;
 }
 
-/** find a data node by exact name */
-static struct local_data*
-lz_find_node(struct local_zone* z, uint8_t* nm, size_t nmlen, int nmlabs)
+/** Delete RR from local-zone RRset, wastes memory as the deleted RRs cannot be
+ * free'd (regionally alloc'd) */
+int
+local_rrset_remove_rr(struct packed_rrset_data* pd, size_t index)
+{
+ log_assert(pd->count > 0);
+ if(index >= pd->count) {
+ log_warn("Trying to remove RR with out of bound index");
+ return 0;
+ }
+ if(index + 1 < pd->count) {
+ /* not removing last element */
+ size_t nexti = index + 1;
+ size_t num = pd->count - nexti;
+ memmove(pd->rr_len+index, pd->rr_len+nexti, sizeof(*pd->rr_len)*num);
+ memmove(pd->rr_ttl+index, pd->rr_ttl+nexti, sizeof(*pd->rr_ttl)*num);
+ memmove(pd->rr_data+index, pd->rr_data+nexti, sizeof(*pd->rr_data)*num);
+ }
+ pd->count--;
+ return 1;
+}
+
+struct local_data*
+local_zone_find_data(struct local_zone* z, uint8_t* nm, size_t nmlen, int nmlabs)
 {
  struct local_data key;
  key.node.key = &key;
@@ -412,7 +432,7 @@ static int
 lz_find_create_node(struct local_zone* z, uint8_t* nm, size_t nmlen,
  int nmlabs, struct local_data** res)
 {
- struct local_data* ld = lz_find_node(z, nm, nmlen, nmlabs);
+ struct local_data* ld = local_zone_find_data(z, nm, nmlen, nmlabs);
  if(!ld) {
  /* create a domain name to store rr. */
  ld = (struct local_data*)regional_alloc_zero(z->region,
@@ -443,42 +463,19 @@ lz_find_create_node(struct local_zone* z
  return 1;
 }
 
-/** enter data RR into auth zone */
-static int
-lz_enter_rr_into_zone(struct local_zone* z, const char* rrstr)
+int
+local_zone_enter_rr(struct local_zone* z, uint8_t* nm, size_t nmlen,
+ int nmlabs, uint16_t rrtype, uint16_t rrclass, time_t ttl,
+ uint8_t* rdata, size_t rdata_len, const char* rrstr)
 {
- uint8_t* nm;
- size_t nmlen;
- int nmlabs;
  struct local_data* node;
  struct local_rrset* rrset;
  struct packed_rrset_data* pd;
- uint16_t rrtype = 0, rrclass = 0;
- time_t ttl = 0;
- uint8_t rr[LDNS_RR_BUF_SIZE];
- uint8_t* rdata;
- size_t rdata_len;
- if(!rrstr_get_rr_content(rrstr, &nm, &rrtype, &rrclass, &ttl, rr,
- sizeof(rr), &rdata, &rdata_len)) {
- log_err("bad local-data: %s", rrstr);
- return 0;
- }
- log_assert(z->dclass == rrclass);
- if((z->type == local_zone_redirect ||
- z->type == local_zone_inform_redirect) &&
- query_dname_compare(z->name, nm) != 0) {
- log_err("local-data in redirect zone must reside at top of zone"
- ", not at %s", rrstr);
- free(nm);
- return 0;
- }
- nmlabs = dname_count_size_labels(nm, &nmlen);
+
  if(!lz_find_create_node(z, nm, nmlen, nmlabs, &node)) {
- free(nm);
  return 0;
  }
  log_assert(node);
- free(nm);
 
  /* Reject it if we would end up having CNAME and other data (including
  * another CNAME) for a redirect zone. */
@@ -520,6 +517,39 @@ lz_enter_rr_into_zone(struct local_zone*
  return rrset_insert_rr(z->region, pd, rdata, rdata_len, ttl, rrstr);
 }
 
+/** enter data RR into auth zone */
+int
+lz_enter_rr_into_zone(struct local_zone* z, const char* rrstr)
+{
+ uint8_t* nm;
+ size_t nmlen;
+ int nmlabs, ret;
+ uint16_t rrtype = 0, rrclass = 0;
+ time_t ttl = 0;
+ uint8_t rr[LDNS_RR_BUF_SIZE];
+ uint8_t* rdata;
+ size_t rdata_len;
+ if(!rrstr_get_rr_content(rrstr, &nm, &rrtype, &rrclass, &ttl, rr,
+ sizeof(rr), &rdata, &rdata_len)) {
+ log_err("bad local-data: %s", rrstr);
+ return 0;
+ }
+ log_assert(z->dclass == rrclass);
+ if((z->type == local_zone_redirect ||
+ z->type == local_zone_inform_redirect) &&
+ query_dname_compare(z->name, nm) != 0) {
+ log_err("local-data in redirect zone must reside at top of zone"
+ ", not at %s", rrstr);
+ free(nm);
+ return 0;
+ }
+ nmlabs = dname_count_size_labels(nm, &nmlen);
+ ret = local_zone_enter_rr(z, nm, nmlen, nmlabs, rrtype, rrclass, ttl,
+ rdata, rdata_len, rrstr);
+ free(nm);
+ return ret;
+}
+
 /** enter a data RR into auth data; a zone for it must exist */
 static int
 lz_enter_rr_str(struct local_zones* zones, const char* rr)
@@ -823,12 +853,12 @@ int local_zone_enter_defaults(struct loc
  log_err("out of memory adding default zone");
  return 0;
  }
- /* test. zone (RFC 7686) */
+ /* test. zone (RFC 6761) */
  if(!add_empty_default(zones, cfg, "test.")) {
  log_err("out of memory adding default zone");
  return 0;
  }
- /* invalid. zone (RFC 7686) */
+ /* invalid. zone (RFC 6761) */
  if(!add_empty_default(zones, cfg, "invalid.")) {
  log_err("out of memory adding default zone");
  return 0;
@@ -1113,6 +1143,22 @@ local_zones_find(struct local_zones* zon
  return (struct local_zone*)rbtree_search(&zones->ztree, &key);
 }
 
+struct local_zone*
+local_zones_find_le(struct local_zones* zones,
+        uint8_t* name, size_t len, int labs, uint16_t dclass,
+ int* exact)
+{
+ struct local_zone key;
+ rbnode_type *node;
+ key.node.key = &key;
+ key.dclass = dclass;
+ key.name = name;
+ key.namelen = len;
+ key.namelabs = labs;
+ *exact = rbtree_find_less_equal(&zones->ztree, &key, &node);
+ return (struct local_zone*)node;
+}
+
 /** print all RRsets in local zone */
 static void
 local_zone_out(struct local_zone* z)
@@ -1309,8 +1355,7 @@ find_tag_datas(struct query_info* qinfo,
  return result;
 }
 
-/** answer local data match */
-static int
+int
 local_data_answer(struct local_zone* z, struct module_env* env,
  struct query_info* qinfo, struct edns_data* edns,
  struct comm_reply* repinfo, sldns_buffer* buf,
@@ -1362,16 +1407,69 @@ local_data_answer(struct local_zone* z,
  lz_type == local_zone_inform_redirect) &&
  qinfo->qtype != LDNS_RR_TYPE_CNAME &&
  lr->rrset->rk.type == htons(LDNS_RR_TYPE_CNAME)) {
+ uint8_t* ctarget;
+ size_t ctargetlen = 0;
+
  qinfo->local_alias =
  regional_alloc_zero(temp, sizeof(struct local_rrset));
  if(!qinfo->local_alias)
  return 0; /* out of memory */
- qinfo->local_alias->rrset =
- regional_alloc_init(temp, lr->rrset, sizeof(*lr->rrset));
+ qinfo->local_alias->rrset = regional_alloc_init(
+ temp, lr->rrset, sizeof(*lr->rrset));
  if(!qinfo->local_alias->rrset)
  return 0; /* out of memory */
  qinfo->local_alias->rrset->rk.dname = qinfo->qname;
  qinfo->local_alias->rrset->rk.dname_len = qinfo->qname_len;
+ get_cname_target(lr->rrset, &ctarget, &ctargetlen);
+ if(!ctargetlen)
+ return 0; /* invalid cname */
+ if(dname_is_wild(ctarget)) {
+ /* synthesize cname target */
+ struct packed_rrset_data* d;
+ /* -3 for wildcard label and root label from qname */
+ size_t newtargetlen = qinfo->qname_len + ctargetlen - 3;
+
+ log_assert(ctargetlen >= 3);
+ log_assert(qinfo->qname_len >= 1);
+
+ if(newtargetlen > LDNS_MAX_DOMAINLEN) {
+ qinfo->local_alias = NULL;
+ local_error_encode(qinfo, env, edns, repinfo,
+ buf, temp, LDNS_RCODE_YXDOMAIN,
+ (LDNS_RCODE_YXDOMAIN|BIT_AA));
+ return 1;
+ }
+ memset(&qinfo->local_alias->rrset->entry, 0,
+ sizeof(qinfo->local_alias->rrset->entry));
+ qinfo->local_alias->rrset->entry.key =
+ qinfo->local_alias->rrset;
+ qinfo->local_alias->rrset->entry.hash =
+ rrset_key_hash(&qinfo->local_alias->rrset->rk);
+ d = (struct packed_rrset_data*)regional_alloc_zero(temp,
+ sizeof(struct packed_rrset_data) + sizeof(size_t) +
+ sizeof(uint8_t*) + sizeof(time_t) + sizeof(uint16_t)
+ + newtargetlen);
+ if(!d)
+ return 0; /* out of memory */
+ qinfo->local_alias->rrset->entry.data = d;
+ d->ttl = 0; /* 0 for synthesized CNAME TTL */
+ d->count = 1;
+ d->rrsig_count = 0;
+ d->trust = rrset_trust_ans_noAA;
+ d->rr_len = (size_t*)((uint8_t*)d +
+ sizeof(struct packed_rrset_data));
+ d->rr_len[0] = newtargetlen + sizeof(uint16_t);
+ packed_rrset_ptr_fixup(d);
+ d->rr_ttl[0] = d->ttl;
+ sldns_write_uint16(d->rr_data[0], newtargetlen);
+ /* write qname */
+ memmove(d->rr_data[0] + sizeof(uint16_t), qinfo->qname,
+ qinfo->qname_len - 1);
+ /* write cname target wilcard wildcard label */
+ memmove(d->rr_data[0] + sizeof(uint16_t) +
+ qinfo->qname_len - 1, ctarget + 2,
+ ctargetlen - 2);
+ }
  return 1;
  }
  if(lz_type == local_zone_redirect ||
@@ -1416,26 +1514,15 @@ local_zone_does_not_cover(struct local_z
  return (lr == NULL);
 }
 
-/**
- * Answer in case where no exact match is found.
- * @param z: zone for query.
- * @param env: module environment.
- * @param qinfo: query.
- * @param edns: edns from query.
- * @param repinfo: source address for checks. may be NULL.
- * @param buf: buffer for answer.
- * @param temp: temp region for encoding.
- * @param ld: local data, if NULL, no such name exists in localdata.
- * @param lz_type: type of the local zone.
- * @return 1 if a reply is to be sent, 0 if not.
- */
-static int
-lz_zone_answer(struct local_zone* z, struct module_env* env,
+int
+local_zones_zone_answer(struct local_zone* z, struct module_env* env,
  struct query_info* qinfo, struct edns_data* edns,
  struct comm_reply* repinfo, sldns_buffer* buf, struct regional* temp,
  struct local_data* ld, enum localzone_type lz_type)
 {
- if(lz_type == local_zone_deny || lz_type == local_zone_inform_deny) {
+ if(lz_type == local_zone_deny ||
+ lz_type == local_zone_always_deny ||
+ lz_type == local_zone_inform_deny) {
  /** no reply at all, signal caller by clearing buffer. */
  sldns_buffer_clear(buf);
  sldns_buffer_flip(buf);
@@ -1448,7 +1535,8 @@ lz_zone_answer(struct local_zone* z, str
  } else if(lz_type == local_zone_static ||
  lz_type == local_zone_redirect ||
  lz_type == local_zone_inform_redirect ||
- lz_type == local_zone_always_nxdomain) {
+ lz_type == local_zone_always_nxdomain ||
+ lz_type == local_zone_always_nodata) {
  /* for static, reply nodata or nxdomain
  * for redirect, reply nodata */
  /* no additional section processing,
@@ -1457,7 +1545,8 @@ lz_zone_answer(struct local_zone* z, str
  * or using closest match for returning delegation downwards
  */
  int rcode = (ld || lz_type == local_zone_redirect ||
- lz_type == local_zone_inform_redirect)?
+ lz_type == local_zone_inform_redirect ||
+ lz_type == local_zone_always_nodata)?
  LDNS_RCODE_NOERROR:LDNS_RCODE_NXDOMAIN;
  if(z->soa)
  return local_encode(qinfo, env, edns, repinfo, buf, temp,
@@ -1640,6 +1729,8 @@ local_zones_answer(struct local_zones* z
  if(lzt != local_zone_always_refuse
  && lzt != local_zone_always_transparent
  && lzt != local_zone_always_nxdomain
+ && lzt != local_zone_always_nodata
+ && lzt != local_zone_always_deny
  && local_data_answer(z, env, qinfo, edns, repinfo, buf, temp, labs,
  &ld, lzt, tag, tag_datas, tag_datas_size, tagname, num_tags)) {
  lock_rw_unlock(&z->lock);
@@ -1647,7 +1738,7 @@ local_zones_answer(struct local_zones* z
  * a local alias. */
  return !qinfo->local_alias;
  }
- r = lz_zone_answer(z, env, qinfo, edns, repinfo, buf, temp, ld, lzt);
+ r = local_zones_zone_answer(z, env, qinfo, edns, repinfo, buf, temp, ld, lzt);
  lock_rw_unlock(&z->lock);
  return r && !qinfo->local_alias; /* see above */
 }
@@ -1669,7 +1760,10 @@ const char* local_zone_type2str(enum loc
  case local_zone_always_transparent: return "always_transparent";
  case local_zone_always_refuse: return "always_refuse";
  case local_zone_always_nxdomain: return "always_nxdomain";
+ case local_zone_always_nodata: return "always_nodata";
+ case local_zone_always_deny: return "always_deny";
  case local_zone_noview: return "noview";
+ case local_zone_invalid: return "invalid";
  }
  return "badtyped";
 }
@@ -1700,6 +1794,10 @@ int local_zone_str2type(const char* type
  *t = local_zone_always_refuse;
  else if(strcmp(type, "always_nxdomain") == 0)
  *t = local_zone_always_nxdomain;
+ else if(strcmp(type, "always_nodata") == 0)
+ *t = local_zone_always_nodata;
+ else if(strcmp(type, "always_deny") == 0)
+ *t = local_zone_always_deny;
  else if(strcmp(type, "noview") == 0)
  *t = local_zone_noview;
  else if(strcmp(type, "nodefault") == 0)
@@ -1843,7 +1941,7 @@ del_empty_term(struct local_zone* z, str
  return;
  dname_remove_label(&name, &len);
  labs--;
- d = lz_find_node(z, name, len, labs);
+ d = local_zone_find_data(z, name, len, labs);
  }
 }
 
@@ -1876,7 +1974,7 @@ void local_zones_del_data(struct local_z
  z = local_zones_lookup(zones, name, len, labs, dclass, LDNS_RR_TYPE_DS);
  if(z) {
  lock_rw_wrlock(&z->lock);
- d = lz_find_node(z, name, len, labs);
+ d = local_zone_find_data(z, name, len, labs);
  if(d) {
  del_local_rrset(d, LDNS_RR_TYPE_DS);
  del_empty_term(z, d, name, len, labs);
@@ -1897,7 +1995,7 @@ void local_zones_del_data(struct local_z
  lock_rw_unlock(&zones->lock);
 
  /* find the domain */
- d = lz_find_node(z, name, len, labs);
+ d = local_zone_find_data(z, name, len, labs);
  if(d) {
  /* no memory recycling for zone deletions ... */
  d->rrsets = NULL;
Index: services/localzone.h
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/services/localzone.h,v
retrieving revision 1.7
diff -u -p -r1.7 localzone.h
--- services/localzone.h 27 Mar 2019 12:06:18 -0000 1.7
+++ services/localzone.h 15 Mar 2020 16:31:04 -0000
@@ -46,6 +46,7 @@
 #include "util/storage/dnstree.h"
 #include "util/module.h"
 #include "services/view.h"
+#include "sldns/sbuffer.h"
 struct packed_rrset_data;
 struct ub_packed_rrset_key;
 struct regional;
@@ -91,8 +92,14 @@ enum localzone_type {
  local_zone_always_refuse,
  /** answer with nxdomain, even when there is local data */
  local_zone_always_nxdomain,
+ /** answer with noerror/nodata, even when there is local data */
+ local_zone_always_nodata,
+ /** drop query, even when there is local data */
+ local_zone_always_deny,
  /** answer not from the view, but global or no-answer */
- local_zone_noview
+ local_zone_noview,
+ /** Invalid type, cannot be used to generate answer */
+ local_zone_invalid
 };
 
 /**
@@ -310,6 +317,25 @@ int local_zones_answer(struct local_zone
  struct config_strlist** tag_datas, size_t tag_datas_size,
  char** tagname, int num_tags, struct view* view);
 
+/**
+ * Answer using the local zone only (not local data used).
+ * @param z: zone for query.
+ * @param env: module environment.
+ * @param qinfo: query.
+ * @param edns: edns from query.
+ * @param repinfo: source address for checks. may be NULL.
+ * @param buf: buffer for answer.
+ * @param temp: temp region for encoding.
+ * @param ld: local data, if NULL, no such name exists in localdata.
+ * @param lz_type: type of the local zone.
+ * @return 1 if a reply is to be sent, 0 if not.
+ */
+int
+local_zones_zone_answer(struct local_zone* z, struct module_env* env,
+ struct query_info* qinfo, struct edns_data* edns,
+ struct comm_reply* repinfo, sldns_buffer* buf, struct regional* temp,
+ struct local_data* ld, enum localzone_type lz_type);
+
 /**
  * Parse the string into localzone type.
  *
@@ -341,6 +367,22 @@ struct local_zone* local_zones_find(stru
  uint8_t* name, size_t len, int labs, uint16_t dclass);
 
 /**
+ * Find zone that with exactly or smaller name/class
+ * User must lock the tree or result zone.
+ * @param zones: the zones tree
+ * @param name: dname to lookup
+ * @param len: length of name.
+ * @param labs: labelcount of name.
+ * @param dclass: class to lookup.
+ * @param exact: 1 on return is this is an exact match.
+ * @return the exact or smaller local_zone or NULL.
+ */
+struct local_zone*
+local_zones_find_le(struct local_zones* zones,
+        uint8_t* name, size_t len, int labs, uint16_t dclass,
+ int* exact);
+
+/**
  * Add a new zone. Caller must hold the zones lock.
  * Adjusts the other zones as well (parent pointers) after insertion.
  * The zone must NOT exist (returns NULL and logs error).
@@ -474,6 +516,15 @@ int rrset_insert_rr(struct regional* reg
  uint8_t* rdata, size_t rdata_len, time_t ttl, const char* rrstr);
 
 /**
+ * Remove RR from rrset that is created using localzone's rrset_insert_rr.
+ * @param pd: the RRset containing the RR to remove
+ * @param index: index of RR to remove
+ * @return: 1 on success; 0 otherwise.
+ */
+int
+local_rrset_remove_rr(struct packed_rrset_data* pd, size_t index);
+
+/**
   * Valid response ip actions for the IP-response-driven-action feature;
   * defined here instead of in the respip module to enable sharing of enum
   * values with the localzone_type enum.
@@ -501,6 +552,10 @@ enum respip_action {
  respip_always_refuse = local_zone_always_refuse,
         /** answer with 'no such domain' response */
  respip_always_nxdomain = local_zone_always_nxdomain,
+        /** answer with nodata response */
+ respip_always_nodata = local_zone_always_nodata,
+        /** answer with nodata response */
+ respip_always_deny = local_zone_always_deny,
 
  /* The rest of the values are only possible as
  * access-control-tag-action */
@@ -513,6 +568,64 @@ enum respip_action {
  respip_transparent = local_zone_transparent,
  /** gives response data (if any), else nodata answer. */
  respip_typetransparent = local_zone_typetransparent,
+ /** type invalid */
+ respip_invalid = local_zone_invalid,
 };
 
+/**
+ * Get local data from local zone and encode answer.
+ * @param z: local zone to use
+ * @param env: module env
+ * @param qinfo: qinfo
+ * @param edns: edns data, for message encoding
+ * @param repinfo: reply info, for message encoding
+ * @param buf: commpoint buffer
+ * @param temp: scratchpad region
+ * @param labs: number of labels in qname
+ * @param ldp: where to store local data
+ * @param lz_type: type of local zone
+ * @param tag: matching tag index
+ * @param tag_datas: alc specific tag data list
+ * @param tag_datas_size: size of tag_datas
+ * @param tagname: list of names of tags, for logging purpose
+ * @param num_tags: number of tags
+ * @return 1 on success
+ */
+int
+local_data_answer(struct local_zone* z, struct module_env* env,
+ struct query_info* qinfo, struct edns_data* edns,
+ struct comm_reply* repinfo, sldns_buffer* buf,
+ struct regional* temp, int labs, struct local_data** ldp,
+ enum localzone_type lz_type, int tag, struct config_strlist** tag_datas,
+ size_t tag_datas_size, char** tagname, int num_tags);
+
+/**
+ * Add RR to local zone.
+ * @param z: local zone to add RR to
+ * @param nm: dname of RR
+ * @param nmlen: length of nm
+ * @param nmlabs: number of labels of nm
+ * @param rrtype: RR type
+ * @param rrclass: RR class
+ * @param ttl: TTL of RR to add
+ * @param rdata: RDATA of RR to add
+ * @param rdata_len: length of rdata
+ * @param rrstr: RR in string format, for logging
+ * @return: 1 on success
+ */
+int
+local_zone_enter_rr(struct local_zone* z, uint8_t* nm, size_t nmlen,
+ int nmlabs, uint16_t rrtype, uint16_t rrclass, time_t ttl,
+ uint8_t* rdata, size_t rdata_len, const char* rrstr);
+
+/**
+ * Find a data node by exact name for a local zone
+ * @param z: local_zone containing data tree
+ * @param nm: name of local-data element to find
+ * @param nmlen: length of nm
+ * @param nmlabs: labs of nm
+ * @return local_data on exact match, NULL otherwise.
+ */
+struct local_data*
+local_zone_find_data(struct local_zone* z, uint8_t* nm, size_t nmlen, int nmlabs);
 #endif /* SERVICES_LOCALZONE_H */
Index: services/mesh.c
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/services/mesh.c,v
retrieving revision 1.14
diff -u -p -r1.14 mesh.c
--- services/mesh.c 18 Dec 2019 11:04:14 -0000 1.14
+++ services/mesh.c 15 Mar 2020 16:31:04 -0000
@@ -46,6 +46,7 @@
 #include "services/mesh.h"
 #include "services/outbound_list.h"
 #include "services/cache/dns.h"
+#include "services/cache/rrset.h"
 #include "util/log.h"
 #include "util/net_help.h"
 #include "util/module.h"
@@ -127,7 +128,7 @@ timeval_smaller(const struct timeval* x,
 #endif
 }
 
-/*
+/**
  * Compare two response-ip client info entries for the purpose of mesh state
  * compare.  It returns 0 if ci_a and ci_b are considered equal; otherwise
  * 1 or -1 (they mean 'ci_a is larger/smaller than ci_b', respectively, but
@@ -250,6 +251,7 @@ mesh_create(struct module_stack* stack,
  mesh->num_forever_states = 0;
  mesh->stats_jostled = 0;
  mesh->stats_dropped = 0;
+ mesh->ans_expired = 0;
  mesh->max_reply_states = env->cfg->num_queries_per_thread;
  mesh->max_forever_states = (mesh->max_reply_states+1)/2;
 #ifndef S_SPLINT_S
@@ -345,6 +347,97 @@ int mesh_make_new_space(struct mesh_area
  return 0;
 }
 
+struct dns_msg*
+mesh_serve_expired_lookup(struct module_qstate* qstate,
+ struct query_info* lookup_qinfo)
+{
+ hashvalue_type h;
+ struct lruhash_entry* e;
+ struct dns_msg* msg;
+ struct reply_info* data;
+ struct msgreply_entry* key;
+ time_t timenow = *qstate->env->now;
+ int must_validate = (!(qstate->query_flags&BIT_CD)
+ || qstate->env->cfg->ignore_cd) && qstate->env->need_to_validate;
+ /* Lookup cache */
+ h = query_info_hash(lookup_qinfo, qstate->query_flags);
+ e = slabhash_lookup(qstate->env->msg_cache, h, lookup_qinfo, 0);
+ if(!e) return NULL;
+
+ key = (struct msgreply_entry*)e->key;
+ data = (struct reply_info*)e->data;
+ msg = tomsg(qstate->env, &key->key, data, qstate->region, timenow,
+ qstate->env->cfg->serve_expired, qstate->env->scratch);
+ if(!msg)
+ goto bail_out;
+
+ /* Check CNAME chain (if any)
+ * This is part of tomsg above; no need to check now. */
+
+ /* Check security status of the cached answer.
+ * tomsg above has a subset of these checks, so we are leaving
+ * these as is.
+ * In case of bogus or revalidation we don't care to reply here. */
+ if(must_validate && (msg->rep->security == sec_status_bogus ||
+ msg->rep->security == sec_status_secure_sentinel_fail)) {
+ verbose(VERB_ALGO, "Serve expired: bogus answer found in cache");
+ goto bail_out;
+ } else if(msg->rep->security == sec_status_unchecked && must_validate) {
+ verbose(VERB_ALGO, "Serve expired: unchecked entry needs "
+ "validation");
+ goto bail_out; /* need to validate cache entry first */
+ } else if(msg->rep->security == sec_status_secure &&
+ !reply_all_rrsets_secure(msg->rep) && must_validate) {
+ verbose(VERB_ALGO, "Serve expired: secure entry"
+ " changed status");
+ goto bail_out; /* rrset changed, re-verify */
+ }
+
+ lock_rw_unlock(&e->lock);
+ return msg;
+
+bail_out:
+ lock_rw_unlock(&e->lock);
+ return NULL;
+}
+
+
+/** Init the serve expired data structure */
+static int
+mesh_serve_expired_init(struct mesh_state* mstate, int timeout)
+{
+ struct timeval t;
+
+ /* Create serve_expired_data if not there yet */
+ if(!mstate->s.serve_expired_data) {
+ mstate->s.serve_expired_data = (struct serve_expired_data*)
+ regional_alloc_zero(
+ mstate->s.region, sizeof(struct serve_expired_data));
+ if(!mstate->s.serve_expired_data)
+ return 0;
+ }
+
+ /* Don't overwrite the function if already set */
+ mstate->s.serve_expired_data->get_cached_answer =
+ mstate->s.serve_expired_data->get_cached_answer?
+ mstate->s.serve_expired_data->get_cached_answer:
+ mesh_serve_expired_lookup;
+
+ /* In case this timer already popped, start it again */
+ if(!mstate->s.serve_expired_data->timer) {
+ mstate->s.serve_expired_data->timer = comm_timer_create(
+ mstate->s.env->worker_base, mesh_serve_expired_callback, mstate);
+ if(!mstate->s.serve_expired_data->timer)
+ return 0;
+#ifndef S_SPLINT_S
+ t.tv_sec = timeout/1000;
+ t.tv_usec = (timeout%1000)*1000;
+#endif
+ comm_timer_set(mstate->s.serve_expired_data->timer, &t);
+ }
+ return 1;
+}
+
 void mesh_new_client(struct mesh_area* mesh, struct query_info* qinfo,
  struct respip_client_info* cinfo, uint16_t qflags,
  struct edns_data* edns, struct comm_reply* rep, uint16_t qid)
@@ -354,6 +447,8 @@ void mesh_new_client(struct mesh_area* m
  int was_detached = 0;
  int was_noreply = 0;
  int added = 0;
+ int timeout = mesh->env->cfg->serve_expired?
+ mesh->env->cfg->serve_expired_client_timeout:0;
  struct sldns_buffer* r_buffer = rep->c->buffer;
  if(rep->c->tcp_req_info) {
  r_buffer = rep->c->tcp_req_info->spool_buffer;
@@ -366,7 +461,7 @@ void mesh_new_client(struct mesh_area* m
  verbose(VERB_ALGO, "Too many queries. dropping "
  "incoming query.");
  comm_point_drop_reply(rep);
- mesh->stats_dropped ++;
+ mesh->stats_dropped++;
  return;
  }
  /* for this new reply state, the reply address is free,
@@ -376,8 +471,8 @@ void mesh_new_client(struct mesh_area* m
  if(mesh->num_reply_addrs > mesh->max_reply_states*16) {
  verbose(VERB_ALGO, "Too many requests queued. "
  "dropping incoming query.");
- mesh->stats_dropped++;
  comm_point_drop_reply(rep);
+ mesh->stats_dropped++;
  return;
  }
  }
@@ -427,23 +522,16 @@ void mesh_new_client(struct mesh_area* m
  mesh->num_detached_states++;
  added = 1;
  }
- if(!s->reply_list && !s->cb_list && s->super_set.count == 0)
- was_detached = 1;
- if(!s->reply_list && !s->cb_list)
+ if(!s->reply_list && !s->cb_list) {
  was_noreply = 1;
+ if(s->super_set.count == 0) {
+ was_detached = 1;
+ }
+ }
  /* add reply to s */
  if(!mesh_state_add_reply(s, edns, rep, qid, qflags, qinfo)) {
- log_err("mesh_new_client: out of memory; SERVFAIL");
- servfail_mem:
- if(!inplace_cb_reply_servfail_call(mesh->env, qinfo, &s->s,
- NULL, LDNS_RCODE_SERVFAIL, edns, rep, mesh->env->scratch))
- edns->opt_list = NULL;
- error_encode(r_buffer, LDNS_RCODE_SERVFAIL,
- qinfo, qid, qflags, edns);
- comm_point_send_reply(rep);
- if(added)
- mesh_state_delete(&s->s);
- return;
+ log_err("mesh_new_client: out of memory; SERVFAIL");
+ goto servfail_mem;
  }
  if(rep->c->tcp_req_info) {
  if(!tcp_req_info_add_meshstate(rep->c->tcp_req_info, mesh, s)) {
@@ -451,6 +539,11 @@ void mesh_new_client(struct mesh_area* m
  goto servfail_mem;
  }
  }
+ /* add serve expired timer if required and not already there */
+ if(timeout && !mesh_serve_expired_init(s, timeout)) {
+ log_err("mesh_new_client: out of memory initializing serve expired");
+ goto servfail_mem;
+ }
  /* update statistics */
  if(was_detached) {
  log_assert(mesh->num_detached_states > 0);
@@ -475,6 +568,18 @@ void mesh_new_client(struct mesh_area* m
  }
  if(added)
  mesh_run(mesh, s, module_event_new, NULL);
+ return;
+
+servfail_mem:
+ if(!inplace_cb_reply_servfail_call(mesh->env, qinfo, &s->s,
+ NULL, LDNS_RCODE_SERVFAIL, edns, rep, mesh->env->scratch))
+ edns->opt_list = NULL;
+ error_encode(r_buffer, LDNS_RCODE_SERVFAIL,
+ qinfo, qid, qflags, edns);
+ comm_point_send_reply(rep);
+ if(added)
+ mesh_state_delete(&s->s);
+ return;
 }
 
 int
@@ -484,6 +589,8 @@ mesh_new_callback(struct mesh_area* mesh
 {
  struct mesh_state* s = NULL;
  int unique = unique_mesh_state(edns->opt_list, mesh->env);
+ int timeout = mesh->env->cfg->serve_expired?
+ mesh->env->cfg->serve_expired_client_timeout:0;
  int was_detached = 0;
  int was_noreply = 0;
  int added = 0;
@@ -522,15 +629,21 @@ mesh_new_callback(struct mesh_area* mesh
  mesh->num_detached_states++;
  added = 1;
  }
- if(!s->reply_list && !s->cb_list && s->super_set.count == 0)
- was_detached = 1;
- if(!s->reply_list && !s->cb_list)
+ if(!s->reply_list && !s->cb_list) {
  was_noreply = 1;
+ if(s->super_set.count == 0) {
+ was_detached = 1;
+ }
+ }
  /* add reply to s */
  if(!mesh_state_add_cb(s, edns, buf, cb, cb_arg, qid, qflags)) {
- if(added)
- mesh_state_delete(&s->s);
- return 0;
+ if(added)
+ mesh_state_delete(&s->s);
+ return 0;
+ }
+ /* add serve expired timer if not already there */
+ if(timeout && !mesh_serve_expired_init(s, timeout)) {
+ return 0;
  }
  /* update statistics */
  if(was_detached) {
@@ -546,15 +659,6 @@ mesh_new_callback(struct mesh_area* mesh
  return 1;
 }
 
-static void mesh_schedule_prefetch(struct mesh_area* mesh,
- struct query_info* qinfo, uint16_t qflags, time_t leeway, int run);
-
-void mesh_new_prefetch(struct mesh_area* mesh, struct query_info* qinfo,
-        uint16_t qflags, time_t leeway)
-{
- mesh_schedule_prefetch(mesh, qinfo, qflags, leeway, 1);
-}
-
 /* Internal backend routine of mesh_new_prefetch().  It takes one additional
  * parameter, 'run', which controls whether to run the prefetch state
  * immediately.  When this function is called internally 'run' could be
@@ -631,6 +735,12 @@ static void mesh_schedule_prefetch(struc
  mesh_run(mesh, s, module_event_new, NULL);
 }
 
+void mesh_new_prefetch(struct mesh_area* mesh, struct query_info* qinfo,
+        uint16_t qflags, time_t leeway)
+{
+ mesh_schedule_prefetch(mesh, qinfo, qflags, leeway, 1);
+}
+
 void mesh_report_reply(struct mesh_area* mesh, struct outbound_entry* e,
         struct comm_reply* reply, int what)
 {
@@ -703,6 +813,7 @@ mesh_state_create(struct module_env* env
  mstate->s.env = env;
  mstate->s.mesh_info = mstate;
  mstate->s.prefetch_leeway = 0;
+ mstate->s.serve_expired_data = NULL;
  mstate->s.no_cache_lookup = 0;
  mstate->s.no_cache_store = 0;
  mstate->s.need_refetch = 0;
@@ -742,6 +853,11 @@ mesh_state_cleanup(struct mesh_state* ms
  if(!mstate)
  return;
  mesh = mstate->s.env->mesh;
+ /* Stop and delete the serve expired timer */
+ if(mstate->s.serve_expired_data && mstate->s.serve_expired_data->timer) {
+ comm_timer_delete(mstate->s.serve_expired_data->timer);
+ mstate->s.serve_expired_data->timer = NULL;
+ }
  /* drop unsent replies */
  if(!mstate->replies_sent) {
  struct mesh_reply* rep = mstate->reply_list;
@@ -752,6 +868,7 @@ mesh_state_cleanup(struct mesh_state* ms
  mstate->reply_list = NULL;
  for(; rep; rep=rep->next) {
  comm_point_drop_reply(&rep->query_reply);
+ log_assert(mesh->num_reply_addrs > 0);
  mesh->num_reply_addrs--;
  }
  while((cb = mstate->cb_list)!=NULL) {
@@ -759,6 +876,7 @@ mesh_state_cleanup(struct mesh_state* ms
  fptr_ok(fptr_whitelist_mesh_cb(cb->cb));
  (*cb->cb)(cb->cb_arg, LDNS_RCODE_SERVFAIL, NULL,
  sec_status_unchecked, NULL, 0);
+ log_assert(mesh->num_reply_addrs > 0);
  mesh->num_reply_addrs--;
  }
  }
@@ -826,7 +944,7 @@ find_in_subsub(struct mesh_state* m, str
 }
 
 /** find cycle for already looked up mesh_state */
-static int
+static int
 mesh_detect_cycle_found(struct module_qstate* qstate, struct mesh_state* dep_m)
 {
  struct mesh_state* cyc_m = qstate->mesh_info;
@@ -1038,6 +1156,7 @@ mesh_do_callback(struct mesh_state* m, i
  }
  }
  free(reason);
+ log_assert(m->s.env->mesh->num_reply_addrs > 0);
  m->s.env->mesh->num_reply_addrs--;
 }
 
@@ -1139,6 +1258,7 @@ mesh_send_reply(struct mesh_state* m, in
  comm_point_send_reply(&r->query_reply);
  }
  /* account */
+ log_assert(m->s.env->mesh->num_reply_addrs > 0);
  m->s.env->mesh->num_reply_addrs--;
  end_time = *m->s.env->now_tv;
  timeval_subtract(&duration, &end_time, &r->start_time);
@@ -1164,37 +1284,76 @@ mesh_send_reply(struct mesh_state* m, in
 
 void mesh_query_done(struct mesh_state* mstate)
 {
- struct mesh_reply* r;
+ struct mesh_reply* r, *reply_list = NULL;
  struct mesh_reply* prev = NULL;
  struct sldns_buffer* prev_buffer = NULL;
  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))
+ /* No need for the serve expired timer anymore; we are going to reply. */
+ if(mstate->s.serve_expired_data) {
+ comm_timer_delete(mstate->s.serve_expired_data->timer);
+ mstate->s.serve_expired_data->timer = NULL;
+ }
+ if(mstate->s.return_rcode == LDNS_RCODE_SERVFAIL ||
+ (rep && FLAGS_GET_RCODE(rep->flags) == LDNS_RCODE_SERVFAIL)) {
+ /* we are SERVFAILing; check for expired asnwer here */
+ mesh_serve_expired_callback(mstate);
+ if((mstate->reply_list || mstate->cb_list)
  && 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);
+ char* err = errinf_to_str_servfail(&mstate->s);
+ if(err)
+ log_err("%s", err);
+ free(err);
+ }
+ }
+ if(mstate->reply_list) {
+ /* set the reply_list to NULL during the mesh_query_done
+ * processing, so that calls back into the mesh from
+ * tcp_req_info (deciding to drop the reply and thus
+ * unregister the mesh_reply from the mstate) are stopped
+ * because the list is empty.
+ * The mstate is then likely not a reply_state, and maybe
+ * also a detached_state.
+ */
+ reply_list = mstate->reply_list;
+ mstate->reply_list = NULL;
+ if(!mstate->reply_list && !mstate->cb_list) {
+ /* was a reply state, not anymore */
+ log_assert(mstate->s.env->mesh->num_reply_states > 0);
+ mstate->s.env->mesh->num_reply_states--;
+ }
+ if(!mstate->reply_list && !mstate->cb_list &&
+ mstate->super_set.count == 0)
+ mstate->s.env->mesh->num_detached_states++;
  }
- for(r = mstate->reply_list; r; r = r->next) {
+ for(r = reply_list; r; r = r->next) {
  /* if a response-ip address block has been stored the
  *  information should be logged for each client. */
  if(mstate->s.respip_action_info &&
  mstate->s.respip_action_info->addrinfo) {
- respip_inform_print(mstate->s.respip_action_info->addrinfo,
+ respip_inform_print(mstate->s.respip_action_info,
  r->qname, mstate->s.qinfo.qtype,
  mstate->s.qinfo.qclass, r->local_alias,
  &r->query_reply);
+ if(mstate->s.env->cfg->stat_extended &&
+ mstate->s.respip_action_info->rpz_used) {
+ if(mstate->s.respip_action_info->rpz_disabled)
+ mstate->s.env->mesh->rpz_action[RPZ_DISABLED_ACTION]++;
+ if(mstate->s.respip_action_info->rpz_cname_override)
+ mstate->s.env->mesh->rpz_action[RPZ_CNAME_OVERRIDE_ACTION]++;
+ else
+ mstate->s.env->mesh->rpz_action[respip_action_to_rpz_action(
+ mstate->s.respip_action_info->action)]++;
+ }
  }
 
  /* if this query is determined to be dropped during the
  * mesh processing, this is the point to take that action. */
- if(mstate->s.is_drop)
+ if(mstate->s.is_drop) {
  comm_point_drop_reply(&r->query_reply);
- else {
+ } else {
  struct sldns_buffer* r_buffer = r->query_reply.c->buffer;
  if(r->query_reply.c->tcp_req_info) {
  r_buffer = r->query_reply.c->tcp_req_info->spool_buffer;
@@ -1216,6 +1375,7 @@ void mesh_query_done(struct mesh_state*
  * changed, eg. by adds from the callback routine */
  if(!mstate->reply_list && mstate->cb_list && !c->next) {
  /* was a reply state, not anymore */
+ log_assert(mstate->s.env->mesh->num_reply_states > 0);
  mstate->s.env->mesh->num_reply_states--;
  }
  mstate->cb_list = c->next;
@@ -1581,7 +1741,9 @@ mesh_stats_clear(struct mesh_area* mesh)
  timehist_clear(mesh->histogram);
  mesh->ans_secure = 0;
  mesh->ans_bogus = 0;
- memset(&mesh->ans_rcode[0], 0, sizeof(size_t)*16);
+ mesh->ans_expired = 0;
+ memset(&mesh->ans_rcode[0], 0, sizeof(size_t)*UB_STATS_RCODE_NUM);
+ memset(&mesh->rpz_action[0], 0, sizeof(size_t)*UB_STATS_RPZ_ACTION_NUM);
  mesh->ans_nodata = 0;
 }
 
@@ -1647,6 +1809,7 @@ void mesh_state_remove_reply(struct mesh
  if(prev) prev->next = n->next;
  else m->reply_list = n->next;
  /* delete it, but allocated in m region */
+ log_assert(mesh->num_reply_addrs > 0);
  mesh->num_reply_addrs--;
 
  /* prev = prev; */
@@ -1665,5 +1828,178 @@ void mesh_state_remove_reply(struct mesh
  if(!m->reply_list && !m->cb_list) {
  log_assert(mesh->num_reply_states > 0);
  mesh->num_reply_states--;
+ }
+}
+
+
+static int
+apply_respip_action(struct module_qstate* qstate,
+ const struct query_info* qinfo, struct respip_client_info* cinfo,
+ struct respip_action_info* actinfo, struct reply_info* rep,
+ struct ub_packed_rrset_key** alias_rrset,
+ struct reply_info** encode_repp, struct auth_zones* az)
+{
+ if(qinfo->qtype != LDNS_RR_TYPE_A &&
+ qinfo->qtype != LDNS_RR_TYPE_AAAA &&
+ qinfo->qtype != LDNS_RR_TYPE_ANY)
+ return 1;
+
+ if(!respip_rewrite_reply(qinfo, cinfo, rep, encode_repp, actinfo,
+ alias_rrset, 0, qstate->region, az))
+ return 0;
+
+ /* xxx_deny actions mean dropping the reply, unless the original reply
+ * was redirected to response-ip data. */
+ if((actinfo->action == respip_deny ||
+ actinfo->action == respip_inform_deny) &&
+ *encode_repp == rep)
+ *encode_repp = NULL;
+
+ return 1;
+}
+
+void
+mesh_serve_expired_callback(void* arg)
+{
+ struct mesh_state* mstate = (struct mesh_state*) arg;
+ struct module_qstate* qstate = &mstate->s;
+ struct mesh_reply* r;
+ struct mesh_area* mesh = qstate->env->mesh;
+ struct dns_msg* msg;
+ struct mesh_cb* c;
+ struct mesh_reply* prev = NULL;
+ struct sldns_buffer* prev_buffer = NULL;
+ struct sldns_buffer* r_buffer = NULL;
+ struct reply_info* partial_rep = NULL;
+ struct ub_packed_rrset_key* alias_rrset = NULL;
+ struct reply_info* encode_rep = NULL;
+ struct respip_action_info actinfo;
+ struct query_info* lookup_qinfo = &qstate->qinfo;
+ struct query_info qinfo_tmp;
+ int must_validate = (!(qstate->query_flags&BIT_CD)
+ || qstate->env->cfg->ignore_cd) && qstate->env->need_to_validate;
+ if(!qstate->serve_expired_data) return;
+ verbose(VERB_ALGO, "Serve expired: Trying to reply with expired data");
+ comm_timer_delete(qstate->serve_expired_data->timer);
+ qstate->serve_expired_data->timer = NULL;
+ if(qstate->blacklist || qstate->no_cache_lookup || qstate->is_drop) {
+ verbose(VERB_ALGO,
+ "Serve expired: Not allowed to look into cache for stale");
+ return;
+ }
+ /* The following while is used instead of the `goto lookup_cache`
+ * like in the worker. */
+ while(1) {
+ fptr_ok(fptr_whitelist_serve_expired_lookup(
+ qstate->serve_expired_data->get_cached_answer));
+ msg = qstate->serve_expired_data->get_cached_answer(qstate,
+ lookup_qinfo);
+ if(!msg)
+ return;
+ /* Reset these in case we pass a second time from here. */
+ encode_rep = msg->rep;
+ memset(&actinfo, 0, sizeof(actinfo));
+ actinfo.action = respip_none;
+ alias_rrset = NULL;
+ if((mesh->use_response_ip || mesh->use_rpz) &&
+ !partial_rep && !apply_respip_action(qstate, &qstate->qinfo,
+ qstate->client_info, &actinfo, msg->rep, &alias_rrset, &encode_rep,
+ qstate->env->auth_zones)) {
+ return;
+ } else if(partial_rep &&
+ !respip_merge_cname(partial_rep, &qstate->qinfo, msg->rep,
+ qstate->client_info, must_validate, &encode_rep, qstate->region,
+ qstate->env->auth_zones)) {
+ return;
+ }
+ if(!encode_rep || alias_rrset) {
+ if(!encode_rep) {
+ /* Needs drop */
+ return;
+ } else {
+ /* A partial CNAME chain is found. */
+ partial_rep = encode_rep;
+ }
+ }
+ /* We've found a partial reply ending with an
+ * alias.  Replace the lookup qinfo for the
+ * alias target and lookup the cache again to
+ * (possibly) complete the reply.  As we're
+ * passing the "base" reply, there will be no
+ * more alias chasing. */
+ if(partial_rep) {
+ memset(&qinfo_tmp, 0, sizeof(qinfo_tmp));
+ get_cname_target(alias_rrset, &qinfo_tmp.qname,
+ &qinfo_tmp.qname_len);
+ if(!qinfo_tmp.qname) {
+ log_err("Serve expired: unexpected: invalid answer alias");
+ return;
+ }
+ qinfo_tmp.qtype = qstate->qinfo.qtype;
+ qinfo_tmp.qclass = qstate->qinfo.qclass;
+ lookup_qinfo = &qinfo_tmp;
+ continue;
+ }
+ break;
+ }
+
+ if(verbosity >= VERB_ALGO)
+ log_dns_msg("Serve expired lookup", &qstate->qinfo, msg->rep);
+
+ r = mstate->reply_list;
+ mstate->reply_list = NULL;
+ if(!mstate->reply_list && !mstate->cb_list) {
+ log_assert(mesh->num_reply_states > 0);
+ mesh->num_reply_states--;
+ if(mstate->super_set.count == 0) {
+ mesh->num_detached_states++;
+ }
+ }
+ for(; r; r = r->next) {
+ /* If address info is returned, it means the action should be an
+ * 'inform' variant and the information should be logged. */
+ if(actinfo.addrinfo) {
+ respip_inform_print(&actinfo, r->qname,
+ qstate->qinfo.qtype, qstate->qinfo.qclass,
+ r->local_alias, &r->query_reply);
+
+ if(qstate->env->cfg->stat_extended && actinfo.rpz_used) {
+ if(actinfo.rpz_disabled)
+ qstate->env->mesh->rpz_action[RPZ_DISABLED_ACTION]++;
+ if(actinfo.rpz_cname_override)
+ qstate->env->mesh->rpz_action[RPZ_CNAME_OVERRIDE_ACTION]++;
+ else
+ qstate->env->mesh->rpz_action[
+ respip_action_to_rpz_action(actinfo.action)]++;
+ }
+ }
+
+ r_buffer = r->query_reply.c->buffer;
+ if(r->query_reply.c->tcp_req_info)
+ r_buffer = r->query_reply.c->tcp_req_info->spool_buffer;
+ mesh_send_reply(mstate, LDNS_RCODE_NOERROR, msg->rep,
+ r, r_buffer, prev, prev_buffer);
+ if(r->query_reply.c->tcp_req_info)
+ tcp_req_info_remove_mesh_state(r->query_reply.c->tcp_req_info, mstate);
+ prev = r;
+ prev_buffer = r_buffer;
+
+ /* Account for each reply sent. */
+ mesh->ans_expired++;
+
+ }
+ while((c = mstate->cb_list) != NULL) {
+ /* take this cb off the list; so that the list can be
+ * changed, eg. by adds from the callback routine */
+ if(!mstate->reply_list && mstate->cb_list && !c->next) {
+ /* was a reply state, not anymore */
+ log_assert(qstate->env->mesh->num_reply_states > 0);
+ qstate->env->mesh->num_reply_states--;
+ }
+ mstate->cb_list = c->next;
+ if(!mstate->reply_list && !mstate->cb_list &&
+ mstate->super_set.count == 0)
+ qstate->env->mesh->num_detached_states++;
+ mesh_do_callback(mstate, LDNS_RCODE_NOERROR, msg->rep, c);
  }
 }
Index: services/mesh.h
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/services/mesh.h,v
retrieving revision 1.6
diff -u -p -r1.6 mesh.h
--- services/mesh.h 8 Feb 2019 10:29:08 -0000 1.6
+++ services/mesh.h 15 Mar 2020 16:31:04 -0000
@@ -51,6 +51,8 @@
 #include "util/data/msgparse.h"
 #include "util/module.h"
 #include "services/modstack.h"
+#include "services/rpz.h"
+#include "libunbound/unbound.h"
 struct sldns_buffer;
 struct mesh_state;
 struct mesh_reply;
@@ -110,6 +112,8 @@ struct mesh_area {
  size_t stats_jostled;
  /** stats, cumulative number of incoming client msgs dropped */
  size_t stats_dropped;
+ /** stats, number of expired replies sent */
+ size_t ans_expired;
  /** number of replies sent */
  size_t replies_sent;
  /** sum of waiting times for the replies */
@@ -121,9 +125,11 @@ struct mesh_area {
  /** (extended stats) bogus replies */
  size_t ans_bogus;
  /** (extended stats) rcodes in replies */
- size_t ans_rcode[16];
+ size_t ans_rcode[UB_STATS_RCODE_NUM];
  /** (extended stats) rcode nodata in replies */
  size_t ans_nodata;
+ /** (extended stats) type of applied RPZ action */
+ size_t rpz_action[UB_STATS_RPZ_ACTION_NUM];
 
  /** backup of query if other operations recurse and need the
  * network buffers */
@@ -142,6 +148,11 @@ struct mesh_area {
  struct mesh_state* jostle_last;
  /** timeout for jostling. if age is lower, it does not get jostled. */
  struct timeval jostle_max;
+
+ /** If we need to use response ip (value passed from daemon)*/
+ int use_response_ip;
+ /** If we need to use RPZ (value passed from daemon) */
+ int use_rpz;
 };
 
 /**
@@ -642,5 +653,23 @@ void mesh_list_remove(struct mesh_state*
  */
 void mesh_state_remove_reply(struct mesh_area* mesh, struct mesh_state* m,
  struct comm_point* cp);
+
+/** Callback for when the serve expired client timer has run out.  Tries to
+ * find an expired answer in the cache and reply that to the client.
+ * @param arg: the argument passed to the callback.
+ */
+void mesh_serve_expired_callback(void* arg);
+
+/**
+ * Try to get a (expired) cached answer.
+ * This needs to behave like the worker's answer_from_cache() in order to have
+ * the same behavior as when replying from cache.
+ * @param qstate: the module qstate.
+ * @param lookup_qinfo: the query info to look for in the cache.
+ * @return dns_msg if a cached answer was found, otherwise NULL.
+ */
+struct dns_msg*
+mesh_serve_expired_lookup(struct module_qstate* qstate,
+ struct query_info* lookup_qinfo);
 
 #endif /* SERVICES_MESH_H */
Index: services/outside_network.c
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/services/outside_network.c,v
retrieving revision 1.16
diff -u -p -r1.16 outside_network.c
--- services/outside_network.c 18 Dec 2019 11:04:14 -0000 1.16
+++ services/outside_network.c 15 Mar 2020 16:31:04 -0000
@@ -293,6 +293,9 @@ outnet_tcp_take_into_use(struct waiting_
  /* open socket */
  s = outnet_get_tcp_fd(&w->addr, w->addrlen, w->outnet->tcp_mss);
 
+ if(s == -1)
+ return 0;
+
  if(!pick_outgoing_tcp(w, s))
  return 0;
 
@@ -1971,7 +1974,6 @@ serviced_udp_callback(struct comm_point*
 
  sq->pending = NULL; /* removed after callback */
  if(error == NETEVENT_TIMEOUT) {
- int rto = 0;
  if(sq->status == serviced_query_UDP_EDNS && sq->last_rtt < 5000) {
  /* fallback to 1480/1280 */
  sq->status = serviced_query_UDP_EDNS_FRAG;
@@ -1987,9 +1989,9 @@ serviced_udp_callback(struct comm_point*
  sq->status = serviced_query_UDP_EDNS;
  }
  sq->retry++;
- if(!(rto=infra_rtt_update(outnet->infra, &sq->addr, sq->addrlen,
+ if(!infra_rtt_update(outnet->infra, &sq->addr, sq->addrlen,
  sq->zone, sq->zonelen, sq->qtype, -1, sq->last_rtt,
- (time_t)now.tv_sec)))
+ (time_t)now.tv_sec))
  log_err("out of memory in UDP exponential backoff");
  if(sq->retry < OUTBOUND_UDP_RETRY) {
  log_name_addr(VERB_ALGO, "retry query", sq->qbuf+10,
Index: services/rpz.c
===================================================================
RCS file: services/rpz.c
diff -N services/rpz.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ services/rpz.c 15 Mar 2020 16:31:04 -0000
@@ -0,0 +1,1015 @@
+/*
+ * services/rpz.c - rpz service
+ *
+ * Copyright (c) 2019, NLnet Labs. All rights reserved.
+ *
+ * This software is open source.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of the NLNET LABS nor the names of its contributors may
+ * be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * \file
+ *
+ * This file contains functions to enable RPZ service.
+ */
+
+#include "config.h"
+#include "services/rpz.h"
+#include "util/config_file.h"
+#include "sldns/wire2str.h"
+#include "sldns/str2wire.h"
+#include "util/data/dname.h"
+#include "util/net_help.h"
+#include "util/log.h"
+#include "util/data/dname.h"
+#include "util/locks.h"
+#include "util/regional.h"
+
+/** string for RPZ action enum */
+const char*
+rpz_action_to_string(enum rpz_action a)
+{
+ switch(a) {
+ case RPZ_NXDOMAIN_ACTION: return "nxdomain";
+ case RPZ_NODATA_ACTION: return "nodata";
+ case RPZ_PASSTHRU_ACTION: return "passthru";
+ case RPZ_DROP_ACTION: return "drop";
+ case RPZ_TCP_ONLY_ACTION: return "tcp_only";
+ case RPZ_INVALID_ACTION: return "invalid";
+ case RPZ_LOCAL_DATA_ACTION: return "local_data";
+ case RPZ_DISABLED_ACTION: return "disabled";
+ case RPZ_CNAME_OVERRIDE_ACTION: return "cname_override";
+ case RPZ_NO_OVERRIDE_ACTION: return "no_override";
+ }
+ return "unknown";
+}
+
+/** RPZ action enum for config string */
+static enum rpz_action
+rpz_config_to_action(char* a)
+{
+ if(strcmp(a, "nxdomain") == 0)
+ return RPZ_NXDOMAIN_ACTION;
+ else if(strcmp(a, "nodata") == 0)
+ return RPZ_NODATA_ACTION;
+ else if(strcmp(a, "passthru") == 0)
+ return RPZ_PASSTHRU_ACTION;
+ else if(strcmp(a, "drop") == 0)
+ return RPZ_DROP_ACTION;
+ else if(strcmp(a, "tcp_only") == 0)
+ return RPZ_TCP_ONLY_ACTION;
+ else if(strcmp(a, "cname") == 0)
+ return RPZ_CNAME_OVERRIDE_ACTION;
+ else if(strcmp(a, "disabled") == 0)
+ return RPZ_DISABLED_ACTION;
+ return RPZ_INVALID_ACTION;
+}
+
+/** string for RPZ trigger enum */
+static const char*
+rpz_trigger_to_string(enum rpz_trigger r)
+{
+ switch(r) {
+ case RPZ_QNAME_TRIGGER: return "qname";
+ case RPZ_CLIENT_IP_TRIGGER: return "client_ip";
+ case RPZ_RESPONSE_IP_TRIGGER: return "response_ip";
+ case RPZ_NSDNAME_TRIGGER: return "nsdname";
+ case RPZ_NSIP_TRIGGER: return "nsip";
+ case RPZ_INVALID_TRIGGER: return "invalid";
+ }
+ return "unknown";
+}
+
+/**
+ * Get the label that is just before the root label.
+ * @param dname: dname to work on
+ * @param maxdnamelen: maximum length of the dname
+ * @return: pointer to TLD label, NULL if not found or invalid dname
+ */
+static uint8_t*
+get_tld_label(uint8_t* dname, size_t maxdnamelen)
+{
+ uint8_t* prevlab = dname;
+ size_t dnamelen = 0;
+
+ /* one byte needed for label length */
+ if(dnamelen+1 > maxdnamelen)
+ return NULL;
+
+ /* only root label */
+ if(*dname == 0)
+ return NULL;
+
+ while(*dname) {
+ dnamelen += ((size_t)*dname)+1;
+ if(dnamelen+1 > maxdnamelen)
+ return NULL;
+ dname = dname+((size_t)*dname)+1;
+ if(*dname != 0)
+ prevlab = dname;
+ }
+ return prevlab;
+}
+
+/**
+ * Classify RPZ action for RR type/rdata
+ * @param rr_type: the RR type
+ * @param rdatawl: RDATA with 2 bytes length
+ * @param rdatalen: the length of rdatawl (including its 2 bytes length)
+ * @return: the RPZ action
+ */
+static enum rpz_action
+rpz_rr_to_action(uint16_t rr_type, uint8_t* rdatawl, size_t rdatalen)
+{
+ char* endptr;
+ uint8_t* rdata;
+ int rdatalabs;
+ uint8_t* tldlab = NULL;
+
+ switch(rr_type) {
+ case LDNS_RR_TYPE_SOA:
+ case LDNS_RR_TYPE_NS:
+ case LDNS_RR_TYPE_DNAME:
+ /* all DNSSEC-related RRs must be ignored */
+ case LDNS_RR_TYPE_DNSKEY:
+ case LDNS_RR_TYPE_DS:
+ case LDNS_RR_TYPE_RRSIG:
+ case LDNS_RR_TYPE_NSEC:
+ case LDNS_RR_TYPE_NSEC3:
+ return RPZ_INVALID_ACTION;
+ case LDNS_RR_TYPE_CNAME:
+ break;
+ default:
+ return RPZ_LOCAL_DATA_ACTION;
+ }
+
+ /* use CNAME target to determine RPZ action */
+ log_assert(rr_type == LDNS_RR_TYPE_CNAME);
+ if(rdatalen < 3)
+ return RPZ_INVALID_ACTION;
+
+ rdata = rdatawl + 2; /* 2 bytes of rdata length */
+ if(dname_valid(rdata, rdatalen-2) != rdatalen-2)
+ return RPZ_INVALID_ACTION;
+
+ rdatalabs = dname_count_labels(rdata);
+ if(rdatalabs == 1)
+ return RPZ_NXDOMAIN_ACTION;
+ else if(rdatalabs == 2) {
+ if(dname_subdomain_c(rdata, (uint8_t*)&"\001*\000"))
+ return RPZ_NODATA_ACTION;
+ else if(dname_subdomain_c(rdata,
+ (uint8_t*)&"\014rpz-passthru\000"))
+ return RPZ_PASSTHRU_ACTION;
+ else if(dname_subdomain_c(rdata, (uint8_t*)&"\010rpz-drop\000"))
+ return RPZ_DROP_ACTION;
+ else if(dname_subdomain_c(rdata,
+ (uint8_t*)&"\014rpz-tcp-only\000"))
+ return RPZ_TCP_ONLY_ACTION;
+ }
+
+ /* all other TLDs starting with "rpz-" are invalid */
+ tldlab = get_tld_label(rdata, rdatalen-2);
+ if(tldlab && dname_lab_startswith(tldlab, "rpz-", &endptr))
+ return RPZ_INVALID_ACTION;
+
+ /* no special label found */
+ return RPZ_LOCAL_DATA_ACTION;
+}
+
+static enum localzone_type
+rpz_action_to_localzone_type(enum rpz_action a)
+{
+ switch(a) {
+ case RPZ_NXDOMAIN_ACTION: return local_zone_always_nxdomain;
+ case RPZ_NODATA_ACTION: return local_zone_always_nodata;
+ case RPZ_DROP_ACTION: return local_zone_always_deny;
+ case RPZ_PASSTHRU_ACTION: return local_zone_always_transparent;
+ case RPZ_LOCAL_DATA_ACTION: /* fallthrough */
+ case RPZ_CNAME_OVERRIDE_ACTION: return local_zone_redirect;
+ case RPZ_INVALID_ACTION: /* fallthrough */
+ case RPZ_TCP_ONLY_ACTION: /* fallthrough */
+ default: return local_zone_invalid;
+ }
+}
+
+enum respip_action
+rpz_action_to_respip_action(enum rpz_action a)
+{
+ switch(a) {
+ case RPZ_NXDOMAIN_ACTION: return respip_always_nxdomain;
+ case RPZ_NODATA_ACTION: return respip_always_nodata;
+ case RPZ_DROP_ACTION: return respip_always_deny;
+ case RPZ_PASSTHRU_ACTION: return respip_always_transparent;
+ case RPZ_LOCAL_DATA_ACTION: /* fallthrough */
+ case RPZ_CNAME_OVERRIDE_ACTION: return respip_redirect;
+ case RPZ_INVALID_ACTION: /* fallthrough */
+ case RPZ_TCP_ONLY_ACTION: /* fallthrough */
+ default: return respip_invalid;
+ }
+}
+
+static enum rpz_action
+localzone_type_to_rpz_action(enum localzone_type lzt)
+{
+ switch(lzt) {
+ case local_zone_always_nxdomain: return RPZ_NXDOMAIN_ACTION;
+ case local_zone_always_nodata: return RPZ_NODATA_ACTION;
+ case local_zone_always_deny: return RPZ_DROP_ACTION;
+ case local_zone_always_transparent: return RPZ_PASSTHRU_ACTION;
+ case local_zone_redirect: return RPZ_LOCAL_DATA_ACTION;
+ case local_zone_invalid:
+ default:
+ return RPZ_INVALID_ACTION;
+ }
+}
+
+enum rpz_action
+respip_action_to_rpz_action(enum respip_action a)
+{
+ switch(a) {
+ case respip_always_nxdomain: return RPZ_NXDOMAIN_ACTION;
+ case respip_always_nodata: return RPZ_NODATA_ACTION;
+ case respip_always_deny: return RPZ_DROP_ACTION;
+ case respip_always_transparent: return RPZ_PASSTHRU_ACTION;
+ case respip_redirect: return RPZ_LOCAL_DATA_ACTION;
+ case respip_invalid:
+ default:
+ return RPZ_INVALID_ACTION;
+ }
+}
+
+/**
+ * Get RPZ trigger for dname
+ * @param dname: dname containing RPZ trigger
+ * @param dname_len: length of the dname
+ * @return: RPZ trigger enum
+ */
+static enum rpz_trigger
+rpz_dname_to_trigger(uint8_t* dname, size_t dname_len)
+{
+ uint8_t* tldlab;
+ char* endptr;
+
+ if(dname_valid(dname, dname_len) != dname_len)
+ return RPZ_INVALID_TRIGGER;
+
+ tldlab = get_tld_label(dname, dname_len);
+ if(!tldlab || !dname_lab_startswith(tldlab, "rpz-", &endptr))
+ return RPZ_QNAME_TRIGGER;
+
+ if(dname_subdomain_c(tldlab,
+ (uint8_t*)&"\015rpz-client-ip\000"))
+ return RPZ_CLIENT_IP_TRIGGER;
+ else if(dname_subdomain_c(tldlab, (uint8_t*)&"\006rpz-ip\000"))
+ return RPZ_RESPONSE_IP_TRIGGER;
+ else if(dname_subdomain_c(tldlab, (uint8_t*)&"\013rpz-nsdname\000"))
+ return RPZ_NSDNAME_TRIGGER;
+ else if(dname_subdomain_c(tldlab, (uint8_t*)&"\010rpz-nsip\000"))
+ return RPZ_NSIP_TRIGGER;
+
+ return RPZ_QNAME_TRIGGER;
+}
+
+void rpz_delete(struct rpz* r)
+{
+ if(!r)
+ return;
+ local_zones_delete(r->local_zones);
+ respip_set_delete(r->respip_set);
+ regional_destroy(r->region);
+ free(r->taglist);
+ free(r->log_name);
+ free(r);
+}
+
+int
+rpz_clear(struct rpz* r)
+{
+ /* must hold write lock on auth_zone */
+ local_zones_delete(r->local_zones);
+ respip_set_delete(r->respip_set);
+ if(!(r->local_zones = local_zones_create())){
+ return 0;
+ }
+ if(!(r->respip_set = respip_set_create())) {
+ return 0;
+ }
+ return 1;
+}
+
+void
+rpz_finish_config(struct rpz* r)
+{
+ lock_rw_wrlock(&r->respip_set->lock);
+ addr_tree_init_parents(&r->respip_set->ip_tree);
+ lock_rw_unlock(&r->respip_set->lock);
+}
+
+/** new rrset containing CNAME override, does not yet contain a dname */
+static struct ub_packed_rrset_key*
+new_cname_override(struct regional* region, uint8_t* ct, size_t ctlen)
+{
+ struct ub_packed_rrset_key* rrset;
+ struct packed_rrset_data* pd;
+ uint16_t rdlength = htons(ctlen);
+ rrset = (struct ub_packed_rrset_key*)regional_alloc_zero(region,
+ sizeof(*rrset));
+ if(!rrset) {
+ log_err("out of memory");
+ return NULL;
+ }
+ rrset->entry.key = rrset;
+ pd = (struct packed_rrset_data*)regional_alloc_zero(region, sizeof(*pd));
+ if(!pd) {
+ log_err("out of memory");
+ return NULL;
+ }
+ pd->trust = rrset_trust_prim_noglue;
+ pd->security = sec_status_insecure;
+
+ pd->count = 1;
+ pd->rr_len = regional_alloc_zero(region, sizeof(*pd->rr_len));
+ pd->rr_ttl = regional_alloc_zero(region, sizeof(*pd->rr_ttl));
+ pd->rr_data = regional_alloc_zero(region, sizeof(*pd->rr_data));
+ if(!pd->rr_len || !pd->rr_ttl || !pd->rr_data) {
+ log_err("out of memory");
+ return NULL;
+ }
+ pd->rr_len[0] = ctlen+2;
+ pd->rr_ttl[0] = 3600;
+ pd->rr_data[0] = regional_alloc_zero(region, 2 /* rdlength */ + ctlen);
+ if(!pd->rr_data[0]) {
+ log_err("out of memory");
+ return NULL;
+ }
+ memmove(pd->rr_data[0], &rdlength, 2);
+ memmove(pd->rr_data[0]+2, ct, ctlen);
+
+ rrset->entry.data = pd;
+ rrset->rk.type = htons(LDNS_RR_TYPE_CNAME);
+ rrset->rk.rrset_class = htons(LDNS_RR_CLASS_IN);
+ return rrset;
+}
+
+struct rpz*
+rpz_create(struct config_auth* p)
+{
+ struct rpz* r = calloc(1, sizeof(*r));
+ if(!r)
+ goto err;
+
+ r->region = regional_create_custom(sizeof(struct regional));
+ if(!r->region) {
+ goto err;
+ }
+
+ if(!(r->local_zones = local_zones_create())){
+ goto err;
+ }
+ if(!(r->respip_set = respip_set_create())) {
+ goto err;
+ }
+ r->taglistlen = p->rpz_taglistlen;
+ r->taglist = memdup(p->rpz_taglist, r->taglistlen);
+ if(p->rpz_action_override) {
+ r->action_override = rpz_config_to_action(p->rpz_action_override);
+ }
+ else
+ r->action_override = RPZ_NO_OVERRIDE_ACTION;
+
+ if(r->action_override == RPZ_CNAME_OVERRIDE_ACTION) {
+ uint8_t nm[LDNS_MAX_DOMAINLEN+1];
+ size_t nmlen = sizeof(nm);
+
+ if(!p->rpz_cname) {
+ log_err("RPZ override with cname action found, but no "
+ "rpz-cname-override configured");
+ goto err;
+ }
+
+ if(sldns_str2wire_dname_buf(p->rpz_cname, nm, &nmlen) != 0) {
+ log_err("cannot parse RPZ cname override: %s",
+ p->rpz_cname);
+ goto err;
+ }
+ r->cname_override = new_cname_override(r->region, nm, nmlen);
+ if(!r->cname_override) {
+ goto err;
+ }
+ }
+ r->log = p->rpz_log;
+ if(p->rpz_log_name) {
+ if(!(r->log_name = strdup(p->rpz_log_name))) {
+ log_err("malloc failure on RPZ log_name strdup");
+ goto err;
+ }
+ }
+ return r;
+err:
+ if(r) {
+ if(r->local_zones)
+ local_zones_delete(r->local_zones);
+ if(r->respip_set)
+ respip_set_delete(r->respip_set);
+ if(r->taglist)
+ free(r->taglist);
+ free(r);
+ }
+ return NULL;
+}
+
+/**
+ * Remove RPZ zone name from dname
+ * Copy dname to newdname, without the originlen number of trailing bytes
+ */
+static size_t
+strip_dname_origin(uint8_t* dname, size_t dnamelen, size_t originlen,
+ uint8_t* newdname, size_t maxnewdnamelen)
+{
+ size_t newdnamelen;
+ if(dnamelen < originlen)
+ return 0;
+ newdnamelen = dnamelen - originlen;
+ if(newdnamelen+1 > maxnewdnamelen)
+ return 0;
+ memmove(newdname, dname, newdnamelen);
+ newdname[newdnamelen] = 0;
+ return newdnamelen + 1; /* + 1 for root label */
+}
+
+/** Insert RR into RPZ's local-zone */
+static void
+rpz_insert_qname_trigger(struct rpz* r, uint8_t* dname, size_t dnamelen,
+ enum rpz_action a, uint16_t rrtype, uint16_t rrclass, uint32_t ttl,
+ uint8_t* rdata, size_t rdata_len, uint8_t* rr, size_t rr_len)
+{
+ struct local_zone* z;
+ enum localzone_type tp = local_zone_always_transparent;
+ int dnamelabs = dname_count_labels(dname);
+ char* rrstr;
+ int newzone = 0;
+
+ if(a == RPZ_TCP_ONLY_ACTION || a == RPZ_INVALID_ACTION) {
+ verbose(VERB_ALGO, "RPZ: skipping unsupported action: %s",
+ rpz_action_to_string(a));
+ free(dname);
+ return;
+ }
+
+ lock_rw_wrlock(&r->local_zones->lock);
+ /* exact match */
+ z = local_zones_find(r->local_zones, dname, dnamelen, dnamelabs,
+ LDNS_RR_CLASS_IN);
+ if(z && a != RPZ_LOCAL_DATA_ACTION) {
+ rrstr = sldns_wire2str_rr(rr, rr_len);
+ if(!rrstr) {
+ log_err("malloc error while inserting RPZ qname "
+ "trigger");
+ free(dname);
+ lock_rw_unlock(&r->local_zones->lock);
+ return;
+ }
+ verbose(VERB_ALGO, "RPZ: skipping duplicate record: '%s'",
+ rrstr);
+ free(rrstr);
+ free(dname);
+ lock_rw_unlock(&r->local_zones->lock);
+ return;
+ }
+ if(!z) {
+ tp = rpz_action_to_localzone_type(a);
+ if(!(z = local_zones_add_zone(r->local_zones, dname, dnamelen,
+ dnamelabs, rrclass, tp))) {
+ log_warn("RPZ create failed");
+ lock_rw_unlock(&r->local_zones->lock);
+ /* dname will be free'd in failed local_zone_create() */
+ return;
+ }
+ newzone = 1;
+ }
+ if(a == RPZ_LOCAL_DATA_ACTION) {
+ rrstr = sldns_wire2str_rr(rr, rr_len);
+ if(!rrstr) {
+ log_err("malloc error while inserting RPZ qname "
+ "trigger");
+ free(dname);
+ lock_rw_unlock(&r->local_zones->lock);
+ return;
+ }
+ lock_rw_wrlock(&z->lock);
+ local_zone_enter_rr(z, dname, dnamelen, dnamelabs,
+ rrtype, rrclass, ttl, rdata, rdata_len, rrstr);
+ lock_rw_unlock(&z->lock);
+ free(rrstr);
+ }
+ if(!newzone)
+ free(dname);
+ lock_rw_unlock(&r->local_zones->lock);
+ return;
+}
+
+/** Insert RR into RPZ's respip_set */
+static int
+rpz_insert_response_ip_trigger(struct rpz* r, uint8_t* dname, size_t dnamelen,
+ enum rpz_action a, uint16_t rrtype, uint16_t rrclass, uint32_t ttl,
+ uint8_t* rdata, size_t rdata_len, uint8_t* rr, size_t rr_len)
+{
+ struct resp_addr* node;
+ struct sockaddr_storage addr;
+ socklen_t addrlen;
+ int net, af;
+ char* rrstr;
+ enum respip_action respa = rpz_action_to_respip_action(a);
+
+ if(a == RPZ_TCP_ONLY_ACTION || a == RPZ_INVALID_ACTION ||
+ respa == respip_invalid) {
+ verbose(VERB_ALGO, "RPZ: skipping unsupported action: %s",
+ rpz_action_to_string(a));
+ return 0;
+ }
+
+ if(!netblockdnametoaddr(dname, dnamelen, &addr, &addrlen, &net, &af))
+ return 0;
+
+ lock_rw_wrlock(&r->respip_set->lock);
+ rrstr = sldns_wire2str_rr(rr, rr_len);
+ if(!rrstr) {
+ log_err("malloc error while inserting RPZ respip trigger");
+ lock_rw_unlock(&r->respip_set->lock);
+ return 0;
+ }
+ if(!(node=respip_sockaddr_find_or_create(r->respip_set, &addr, addrlen,
+ net, 1, rrstr))) {
+ lock_rw_unlock(&r->respip_set->lock);
+ free(rrstr);
+ return 0;
+ }
+
+ lock_rw_wrlock(&node->lock);
+ lock_rw_unlock(&r->respip_set->lock);
+ node->action = respa;
+
+ if(a == RPZ_LOCAL_DATA_ACTION) {
+ respip_enter_rr(r->respip_set->region, node, rrtype,
+ rrclass, ttl, rdata, rdata_len, rrstr, "");
+ }
+ lock_rw_unlock(&node->lock);
+ free(rrstr);
+ return 1;
+}
+
+int
+rpz_insert_rr(struct rpz* r, size_t aznamelen, uint8_t* dname,
+ size_t dnamelen, uint16_t rr_type, uint16_t rr_class, uint32_t rr_ttl,
+ uint8_t* rdatawl, size_t rdatalen, uint8_t* rr, size_t rr_len)
+{
+ size_t policydnamelen;
+ /* name is free'd in local_zone delete */
+ enum rpz_trigger t;
+ enum rpz_action a;
+ uint8_t* policydname;
+
+ log_assert(dnamelen >= aznamelen);
+ if(!(policydname = calloc(1, (dnamelen-aznamelen)+1)))
+ return 0;
+
+ a = rpz_rr_to_action(rr_type, rdatawl, rdatalen);
+ if(!(policydnamelen = strip_dname_origin(dname, dnamelen, aznamelen,
+ policydname, (dnamelen-aznamelen)+1))) {
+ free(policydname);
+ return 0;
+ }
+ t = rpz_dname_to_trigger(policydname, policydnamelen);
+ if(t == RPZ_INVALID_TRIGGER) {
+ free(policydname);
+ verbose(VERB_ALGO, "RPZ: skipping invalid trigger");
+ return 1;
+ }
+ if(t == RPZ_QNAME_TRIGGER) {
+ rpz_insert_qname_trigger(r, policydname, policydnamelen,
+ a, rr_type, rr_class, rr_ttl, rdatawl, rdatalen, rr,
+ rr_len);
+ }
+ else if(t == RPZ_RESPONSE_IP_TRIGGER) {
+ rpz_insert_response_ip_trigger(r, policydname, policydnamelen,
+ a, rr_type, rr_class, rr_ttl, rdatawl, rdatalen, rr,
+ rr_len);
+ free(policydname);
+ }
+ else {
+ free(policydname);
+ verbose(VERB_ALGO, "RPZ: skipping unsupported trigger: %s",
+ rpz_trigger_to_string(t));
+ }
+ return 1;
+}
+
+/**
+ * Find RPZ local-zone by qname.
+ * @param r: rpz containing local-zone tree
+ * @param qname: qname
+ * @param qname_len: length of qname
+ * @param qclass: qclass
+ * @param only_exact: if 1 only excact (non wildcard) matches are returned
+ * @param wr: get write lock for local-zone if 1, read lock if 0
+ * @param zones_keep_lock: if set do not release the r->local_zones lock, this
+ *  makes the caller of this function responsible for releasing the lock.
+ * @return: NULL or local-zone holding rd or wr lock
+ */
+static struct local_zone*
+rpz_find_zone(struct rpz* r, uint8_t* qname, size_t qname_len, uint16_t qclass,
+ int only_exact, int wr, int zones_keep_lock)
+{
+ uint8_t* ce;
+ size_t ce_len, ce_labs;
+ uint8_t wc[LDNS_MAX_DOMAINLEN+1];
+ int exact;
+ struct local_zone* z = NULL;
+ if(wr) {
+ lock_rw_wrlock(&r->local_zones->lock);
+ } else {
+ lock_rw_rdlock(&r->local_zones->lock);
+ }
+ z = local_zones_find_le(r->local_zones, qname, qname_len,
+ dname_count_labels(qname),
+ LDNS_RR_CLASS_IN, &exact);
+ if(!z || (only_exact && !exact)) {
+ lock_rw_unlock(&r->local_zones->lock);
+ return NULL;
+ }
+ if(wr) {
+ lock_rw_wrlock(&z->lock);
+ } else {
+ lock_rw_rdlock(&z->lock);
+ }
+ if(!zones_keep_lock) {
+ lock_rw_unlock(&r->local_zones->lock);
+ }
+
+ if(exact)
+ return z;
+
+ /* No exact match found, lookup wildcard. closest encloser must
+ * be the shared parent between the qname and the best local
+ * zone match, append '*' to that and do another lookup. */
+
+ ce = dname_get_shared_topdomain(z->name, qname);
+ if(!ce /* should not happen */ || !*ce /* root */) {
+ lock_rw_unlock(&z->lock);
+ if(zones_keep_lock) {
+ lock_rw_unlock(&r->local_zones->lock);
+ }
+ return NULL;
+ }
+ ce_labs = dname_count_size_labels(ce, &ce_len);
+ if(ce_len+2 > sizeof(wc)) {
+ lock_rw_unlock(&z->lock);
+ if(zones_keep_lock) {
+ lock_rw_unlock(&r->local_zones->lock);
+ }
+ return NULL;
+ }
+ wc[0] = 1; /* length of wildcard label */
+ wc[1] = (uint8_t)'*'; /* wildcard label */
+ memmove(wc+2, ce, ce_len);
+ lock_rw_unlock(&z->lock);
+
+ if(!zones_keep_lock) {
+ if(wr) {
+ lock_rw_wrlock(&r->local_zones->lock);
+ } else {
+ lock_rw_rdlock(&r->local_zones->lock);
+ }
+ }
+ z = local_zones_find_le(r->local_zones, wc,
+ ce_len+2, ce_labs+1, qclass, &exact);
+ if(!z || !exact) {
+ lock_rw_unlock(&r->local_zones->lock);
+ return NULL;
+ }
+ if(wr) {
+ lock_rw_wrlock(&z->lock);
+ } else {
+ lock_rw_rdlock(&z->lock);
+ }
+ if(!zones_keep_lock) {
+ lock_rw_unlock(&r->local_zones->lock);
+ }
+ return z;
+}
+
+/**
+ * Remove RR from RPZ's local-data
+ * @param z: local-zone for RPZ, holding write lock
+ * @param policydname: dname of RR to remove
+ * @param policydnamelen: lenth of policydname
+ * @param rr_type: RR type of RR to remove
+ * @param rdata: rdata of RR to remove
+ * @param rdatalen: length of rdata
+ * @return: 1 if zone must be removed after RR deletion
+ */
+static int
+rpz_data_delete_rr(struct local_zone* z, uint8_t* policydname,
+ size_t policydnamelen, uint16_t rr_type, uint8_t* rdata,
+ size_t rdatalen)
+{
+ struct local_data* ld;
+ struct packed_rrset_data* d;
+ size_t index;
+ ld = local_zone_find_data(z, policydname, policydnamelen,
+ dname_count_labels(policydname));
+ if(ld) {
+ struct local_rrset* prev=NULL, *p=ld->rrsets;
+ while(p && ntohs(p->rrset->rk.type) != rr_type) {
+ prev = p;
+ p = p->next;
+ }
+ if(!p)
+ return 0;
+ d = (struct packed_rrset_data*)p->rrset->entry.data;
+ if(packed_rrset_find_rr(d, rdata, rdatalen, &index)) {
+ if(d->count == 1) {
+ /* no memory recycling for zone deletions ... */
+ if(prev) prev->next = p->next;
+ else ld->rrsets = p->next;
+ }
+ if(d->count > 1) {
+ if(!local_rrset_remove_rr(d, index))
+ return 0;
+ }
+ }
+ }
+ if(ld && ld->rrsets)
+ return 0;
+ return 1;
+}
+
+/**
+ * Remove RR from RPZ's respip set
+ * @param raddr: respip node
+ * @param rr_type: RR type of RR to remove
+ * @param rdata: rdata of RR to remove
+ * @param rdatalen: length of rdata
+ * @return: 1 if zone must be removed after RR deletion
+ */
+static int
+rpz_rrset_delete_rr(struct resp_addr* raddr, uint16_t rr_type, uint8_t* rdata,
+ size_t rdatalen)
+{
+ size_t index;
+ struct packed_rrset_data* d;
+ if(!raddr->data)
+ return 1;
+ d = raddr->data->entry.data;
+ if(ntohs(raddr->data->rk.type) != rr_type) {
+ return 0;
+ }
+ if(packed_rrset_find_rr(d, rdata, rdatalen, &index)) {
+ if(d->count == 1) {
+ /* regional alloc'd */
+ raddr->data->entry.data = NULL;
+ raddr->data = NULL;
+ return 1;
+ }
+ if(d->count > 1) {
+ if(!local_rrset_remove_rr(d, index))
+ return 0;
+ }
+ }
+ return 0;
+
+}
+
+/** Remove RR from RPZ's local-zone */
+static void
+rpz_remove_qname_trigger(struct rpz* r, uint8_t* dname, size_t dnamelen,
+ enum rpz_action a, uint16_t rr_type, uint16_t rr_class,
+ uint8_t* rdatawl, size_t rdatalen)
+{
+ struct local_zone* z;
+ int delete_zone = 1;
+ z = rpz_find_zone(r, dname, dnamelen, rr_class,
+ 1 /* only exact */, 1 /* wr lock */, 1 /* keep lock*/);
+ if(!z) {
+ verbose(VERB_ALGO, "RPZ: cannot remove RR from IXFR, "
+ "RPZ domain not found");
+ return;
+ }
+ if(a == RPZ_LOCAL_DATA_ACTION)
+ delete_zone = rpz_data_delete_rr(z, dname,
+ dnamelen, rr_type, rdatawl, rdatalen);
+ else if(a != localzone_type_to_rpz_action(z->type)) {
+ return;
+ }
+ lock_rw_unlock(&z->lock);
+ if(delete_zone) {
+ local_zones_del_zone(r->local_zones, z);
+ }
+ lock_rw_unlock(&r->local_zones->lock);
+ return;
+}
+
+static void
+rpz_remove_response_ip_trigger(struct rpz* r, uint8_t* dname, size_t dnamelen,
+ enum rpz_action a, uint16_t rr_type, uint8_t* rdatawl, size_t rdatalen)
+{
+ struct resp_addr* node;
+ struct sockaddr_storage addr;
+ socklen_t addrlen;
+ int net, af;
+ int delete_respip = 1;
+
+ if(!netblockdnametoaddr(dname, dnamelen, &addr, &addrlen, &net, &af))
+ return;
+
+ lock_rw_wrlock(&r->respip_set->lock);
+ if(!(node = (struct resp_addr*)addr_tree_find(
+ &r->respip_set->ip_tree, &addr, addrlen, net))) {
+ verbose(VERB_ALGO, "RPZ: cannot remove RR from IXFR, "
+ "RPZ domain not found");
+ lock_rw_unlock(&r->respip_set->lock);
+ return;
+ }
+
+ lock_rw_wrlock(&node->lock);
+ if(a == RPZ_LOCAL_DATA_ACTION) {
+ /* remove RR, signal whether RR can be removed */
+ delete_respip = rpz_rrset_delete_rr(node, rr_type, rdatawl,
+ rdatalen);
+ }
+ lock_rw_unlock(&node->lock);
+ if(delete_respip)
+ respip_sockaddr_delete(r->respip_set, node);
+ lock_rw_unlock(&r->respip_set->lock);
+}
+
+void
+rpz_remove_rr(struct rpz* r, size_t aznamelen, uint8_t* dname, size_t dnamelen,
+ uint16_t rr_type, uint16_t rr_class, uint8_t* rdatawl, size_t rdatalen)
+{
+ size_t policydnamelen;
+ enum rpz_trigger t;
+ enum rpz_action a;
+ uint8_t* policydname;
+
+ if(!(policydname = calloc(1, LDNS_MAX_DOMAINLEN + 1)))
+ return;
+
+ a = rpz_rr_to_action(rr_type, rdatawl, rdatalen);
+ if(a == RPZ_INVALID_ACTION) {
+ free(policydname);
+ return;
+ }
+ if(!(policydnamelen = strip_dname_origin(dname, dnamelen, aznamelen,
+ policydname, LDNS_MAX_DOMAINLEN + 1))) {
+ free(policydname);
+ return;
+ }
+ t = rpz_dname_to_trigger(policydname, policydnamelen);
+ if(t == RPZ_QNAME_TRIGGER) {
+ rpz_remove_qname_trigger(r, policydname, policydnamelen, a,
+ rr_type, rr_class, rdatawl, rdatalen);
+ } else if(t == RPZ_RESPONSE_IP_TRIGGER) {
+ rpz_remove_response_ip_trigger(r, policydname, policydnamelen,
+ a, rr_type, rdatawl, rdatalen);
+ }
+ free(policydname);
+}
+
+/** print log information for an applied RPZ policy. Based on local-zone's
+ * lz_inform_print().
+ */
+static void
+log_rpz_apply(uint8_t* dname, enum rpz_action a, struct query_info* qinfo,
+ struct comm_reply* repinfo, char* log_name)
+{
+ char ip[128], txt[512];
+ char dnamestr[LDNS_MAX_DOMAINLEN+1];
+ uint16_t port = ntohs(((struct sockaddr_in*)&repinfo->addr)->sin_port);
+ dname_str(dname, dnamestr);
+ addr_to_str(&repinfo->addr, repinfo->addrlen, ip, sizeof(ip));
+ if(log_name)
+ snprintf(txt, sizeof(txt), "RPZ applied [%s] %s %s %s@%u",
+ log_name, dnamestr, rpz_action_to_string(a), ip,
+ (unsigned)port);
+ else
+ snprintf(txt, sizeof(txt), "RPZ applied %s %s %s@%u",
+ dnamestr, rpz_action_to_string(a), ip, (unsigned)port);
+ log_nametypeclass(0, txt, qinfo->qname, qinfo->qtype, qinfo->qclass);
+}
+
+int
+rpz_apply_qname_trigger(struct auth_zones* az, struct module_env* env,
+ struct query_info* qinfo, struct edns_data* edns, sldns_buffer* buf,
+ struct regional* temp, struct comm_reply* repinfo,
+ uint8_t* taglist, size_t taglen, struct ub_server_stats* stats)
+{
+ struct rpz* r;
+ int ret;
+ enum localzone_type lzt;
+ struct local_zone* z = NULL;
+ struct local_data* ld = NULL;
+ lock_rw_rdlock(&az->rpz_lock);
+ for(r = az->rpz_first; r; r = r->next) {
+ if(!r->taglist || taglist_intersect(r->taglist,
+ r->taglistlen, taglist, taglen)) {
+ z = rpz_find_zone(r, qinfo->qname, qinfo->qname_len,
+ qinfo->qclass, 0, 0, 0);
+ if(z && r->action_override == RPZ_DISABLED_ACTION) {
+ if(r->log)
+ log_rpz_apply(z->name,
+ r->action_override,
+ qinfo, repinfo, r->log_name);
+ /* TODO only register stats when stats_extended?
+ * */
+ stats->rpz_action[r->action_override]++;
+ lock_rw_unlock(&z->lock);
+ z = NULL;
+ }
+ if(z)
+ break;
+ }
+ }
+ lock_rw_unlock(&az->rpz_lock);
+ if(!z)
+ return 0;
+
+
+ if(r->action_override == RPZ_NO_OVERRIDE_ACTION)
+ lzt = z->type;
+ else
+ lzt = rpz_action_to_localzone_type(r->action_override);
+
+ if(r->action_override == RPZ_CNAME_OVERRIDE_ACTION) {
+ qinfo->local_alias =
+ regional_alloc_zero(temp, sizeof(struct local_rrset));
+ if(!qinfo->local_alias) {
+ lock_rw_unlock(&z->lock);
+ return 0; /* out of memory */
+ }
+ qinfo->local_alias->rrset =
+ regional_alloc_init(temp, r->cname_override,
+ sizeof(*r->cname_override));
+ if(!qinfo->local_alias->rrset) {
+ lock_rw_unlock(&z->lock);
+ return 0; /* out of memory */
+ }
+ qinfo->local_alias->rrset->rk.dname = qinfo->qname;
+ qinfo->local_alias->rrset->rk.dname_len = qinfo->qname_len;
+ if(r->log)
+ log_rpz_apply(z->name, RPZ_CNAME_OVERRIDE_ACTION,
+ qinfo, repinfo, r->log_name);
+ stats->rpz_action[RPZ_CNAME_OVERRIDE_ACTION]++;
+ lock_rw_unlock(&z->lock);
+ return 0;
+ }
+
+ if(lzt == local_zone_redirect && local_data_answer(z, env, qinfo,
+ edns, repinfo, buf, temp, dname_count_labels(qinfo->qname),
+ &ld, lzt, -1, NULL, 0, NULL, 0)) {
+ if(r->log)
+ log_rpz_apply(z->name,
+ localzone_type_to_rpz_action(lzt), qinfo,
+ repinfo, r->log_name);
+ stats->rpz_action[localzone_type_to_rpz_action(lzt)]++;
+ lock_rw_unlock(&z->lock);
+ return !qinfo->local_alias;
+ }
+
+ ret = local_zones_zone_answer(z, env, qinfo, edns, repinfo, buf, temp,
+ 0 /* no local data used */, lzt);
+ if(r->log)
+ log_rpz_apply(z->name, localzone_type_to_rpz_action(lzt),
+ qinfo, repinfo, r->log_name);
+ stats->rpz_action[localzone_type_to_rpz_action(lzt)]++;
+ lock_rw_unlock(&z->lock);
+
+ return ret;
+}
Index: services/rpz.h
===================================================================
RCS file: services/rpz.h
diff -N services/rpz.h
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ services/rpz.h 15 Mar 2020 16:31:04 -0000
@@ -0,0 +1,201 @@
+/*
+ * services/rpz.h - rpz service
+ *
+ * Copyright (c) 2019, NLnet Labs. All rights reserved.
+ *
+ * This software is open source.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of the NLNET LABS nor the names of its contributors may
+ * be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * \file
+ *
+ * This file contains functions to enable RPZ service.
+ */
+
+#ifndef SERVICES_RPZ_H
+#define SERVICES_RPZ_H
+
+#include "services/localzone.h"
+#include "util/locks.h"
+#include "util/log.h"
+#include "util/config_file.h"
+#include "services/authzone.h"
+#include "sldns/sbuffer.h"
+#include "daemon/stats.h"
+#include "respip/respip.h"
+
+/**
+ * RPZ triggers, only the QNAME trigger is currently supported in Unbound.
+ */
+enum rpz_trigger {
+ RPZ_QNAME_TRIGGER = 0,
+ /* unsupported triggers */
+ RPZ_CLIENT_IP_TRIGGER, /* rpz-client-ip */
+ RPZ_RESPONSE_IP_TRIGGER, /* rpz-ip */
+ RPZ_NSDNAME_TRIGGER, /* rpz-nsdname */
+ RPZ_NSIP_TRIGGER, /* rpz-nsip */
+ RPZ_INVALID_TRIGGER, /* dname does not contain valid trigger */
+};
+
+/**
+ * RPZ actions.
+ */
+enum rpz_action {
+ RPZ_NXDOMAIN_ACTION = 0,/* CNAME . */
+ RPZ_NODATA_ACTION, /* CNAME *. */
+ RPZ_PASSTHRU_ACTION, /* CNAME rpz-passthru. */
+ RPZ_DROP_ACTION, /* CNAME rpz-drop. */
+ RPZ_TCP_ONLY_ACTION, /* CNAME rpz-tcp-only. */
+ RPZ_INVALID_ACTION, /* CNAME with (child of) TLD starting with
+   "rpz-" in target, SOA, NS, DNAME and
+   DNSSEC-related records. */
+ RPZ_LOCAL_DATA_ACTION, /* anything else */
+ /* RPZ override actions */
+ RPZ_DISABLED_ACTION,    /* RPZ action disabled using override */
+ RPZ_NO_OVERRIDE_ACTION, /* RPZ action no override*/
+ RPZ_CNAME_OVERRIDE_ACTION, /* RPZ CNAME action override*/
+};
+
+/**
+ * RPZ containing policies. Pointed to from corresponding auth-zone. Part of a
+ * linked list to keep configuration order. Iterating or changing the linked
+ * list requires the rpz_lock from struct auth_zones.
+ */
+struct rpz {
+ struct local_zones* local_zones;
+ struct respip_set* respip_set;
+ uint8_t* taglist;
+ size_t taglistlen;
+ enum rpz_action action_override;
+ struct ub_packed_rrset_key* cname_override;
+ int log;
+ char* log_name;
+ struct rpz* next;
+ struct rpz* prev;
+ struct regional* region;
+};
+
+/**
+ * Create policy from RR and add to this RPZ.
+ * @param r: the rpz to add the policy to.
+ * @param aznamelen: the length of the auth-zone name
+ * @param dname: dname of the RR
+ * @param dnamelen: length of the dname
+ * @param rr_type: RR type of the RR
+ * @param rr_class: RR class of the RR
+ * @param rr_ttl: TTL of the RR
+ * @param rdatawl: rdata of the RR, prepended with the rdata size
+ * @param rdatalen: length if the RR, including the prepended rdata size
+ * @param rr: the complete RR, for logging purposes
+ * @param rr_len: the length of the complete RR
+ * @return: 0 on error
+ */
+int rpz_insert_rr(struct rpz* r, size_t aznamelen, uint8_t* dname,
+ size_t dnamelen, uint16_t rr_type, uint16_t rr_class, uint32_t rr_ttl,
+ uint8_t* rdatawl, size_t rdatalen, uint8_t* rr, size_t rr_len);
+
+/**
+ * Delete policy matching RR, used for IXFR.
+ * @param r: the rpz to add the policy to.
+ * @param aznamelen: the length of the auth-zone name
+ * @param dname: dname of the RR
+ * @param dnamelen: length of the dname
+ * @param rr_type: RR type of the RR
+ * @param rr_class: RR class of the RR
+ * @param rdatawl: rdata of the RR, prepended with the rdata size
+ * @param rdatalen: length if the RR, including the prepended rdata size
+ */
+void rpz_remove_rr(struct rpz* r, size_t aznamelen, uint8_t* dname,
+ size_t dnamelen, uint16_t rr_type, uint16_t rr_class, uint8_t* rdatawl,
+ size_t rdatalen);
+
+/**
+ * Walk over the RPZ zones to find and apply a QNAME trigger policy.
+ * @param az: auth_zones struct, containing first RPZ item and RPZ lock
+ * @param env: module env
+ * @param qinfo: qinfo containing qname and qtype
+ * @param edns: edns data
+ * @param buf: buffer to write answer to
+ * @param temp: scratchpad
+ * @param repinfo: reply info
+ * @param taglist: taglist to lookup.
+ * @param taglen: lenth of taglist.
+ * @param stats: worker stats struct
+ * @return: 1 if client answer is ready, 0 to continue resolving
+ */
+int rpz_apply_qname_trigger(struct auth_zones* az, struct module_env* env,
+ struct query_info* qinfo, struct edns_data* edns, sldns_buffer* buf,
+ struct regional* temp, struct comm_reply* repinfo,
+ uint8_t* taglist, size_t taglen, struct ub_server_stats* stats);
+
+/**
+ * Delete RPZ
+ * @param r: RPZ struct to delete
+ */
+void rpz_delete(struct rpz* r);
+
+/**
+ * Clear local-zones and respip data in RPZ, used after reloading file or
+ * AXFR/HTTP transfer.
+ * @param r: RPZ to use
+ */
+int rpz_clear(struct rpz* r);
+
+/**
+ * Create RPZ. RPZ must be added to linked list after creation.
+ * @return: the newly created RPZ
+ */
+struct rpz* rpz_create(struct config_auth* p);
+
+/**
+ * String for RPZ action enum
+ * @param a: RPZ action to get string for
+ * @return: string for RPZ action
+ */
+const char* rpz_action_to_string(enum rpz_action a);
+
+enum rpz_action
+respip_action_to_rpz_action(enum respip_action a);
+
+/**
+ * Prepare RPZ after procesing feed content.
+ * @param r: RPZ to use
+ */
+void rpz_finish_config(struct rpz* r);
+
+/**
+ * Classify respip action for RPZ action
+ * @param a: RPZ action
+ * @return: the respip action
+ */
+enum respip_action
+rpz_action_to_respip_action(enum rpz_action a);
+
+#endif /* SERVICES_RPZ_H */
Index: services/view.c
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/services/view.c,v
retrieving revision 1.2
diff -u -p -r1.2 view.c
--- services/view.c 12 Aug 2017 11:22:46 -0000 1.2
+++ services/view.c 15 Mar 2020 16:31:04 -0000
@@ -198,8 +198,6 @@ views_apply_cfg(struct views* vs, struct
  log_err("failed to insert "
  "default zones into "
  "local-zone list");
- free(nd_str);
- free(nd_type);
  lock_rw_unlock(&v->lock);
  return 0;
  }
Index: services/cache/dns.c
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/services/cache/dns.c,v
retrieving revision 1.13
diff -u -p -r1.13 dns.c
--- services/cache/dns.c 28 Jun 2019 15:17:16 -0000 1.13
+++ services/cache/dns.c 15 Mar 2020 16:31:04 -0000
@@ -45,6 +45,7 @@
 #include "validator/val_utils.h"
 #include "services/cache/dns.h"
 #include "services/cache/rrset.h"
+#include "util/data/msgparse.h"
 #include "util/data/msgreply.h"
 #include "util/data/packed_rrset.h"
 #include "util/data/dname.h"
@@ -73,15 +74,15 @@ store_rrsets(struct module_env* env, str
  time_t leeway, int pside, struct reply_info* qrep,
  struct regional* region)
 {
-        size_t i;
-        /* see if rrset already exists in cache, if not insert it. */
-        for(i=0; i<rep->rrset_count; i++) {
-                rep->ref[i].key = rep->rrsets[i];
-                rep->ref[i].id = rep->rrsets[i]->id;
- /* update ref if it was in the cache */
+ size_t i;
+ /* see if rrset already exists in cache, if not insert it. */
+ for(i=0; i<rep->rrset_count; i++) {
+ rep->ref[i].key = rep->rrsets[i];
+ rep->ref[i].id = rep->rrsets[i]->id;
+ /* update ref if it was in the cache */
  switch(rrset_cache_update(env->rrset_cache, &rep->ref[i],
-                        env->alloc, now + ((ntohs(rep->ref[i].key->rk.type)==
- LDNS_RR_TYPE_NS && !pside)?0:leeway))) {
+ env->alloc, now + ((ntohs(rep->ref[i].key->rk.type)==
+ LDNS_RR_TYPE_NS && !pside)?0:leeway))) {
  case 0: /* ref unchanged, item inserted */
  break;
  case 2: /* ref updated, cache is superior */
@@ -104,9 +105,9 @@ store_rrsets(struct module_env* env, str
  * the fallthrough warning */
  /* fallthrough */
  case 1: /* ref updated, item inserted */
-                        rep->rrsets[i] = rep->ref[i].key;
+ rep->rrsets[i] = rep->ref[i].key;
  }
-        }
+ }
 }
 
 /** delete message from message cache */
@@ -532,31 +533,51 @@ gen_dns_msg(struct regional* region, str
 }
 
 struct dns_msg*
-tomsg(struct module_env* env, struct query_info* q, struct reply_info* r,
- struct regional* region, time_t now, struct regional* scratch)
+tomsg(struct module_env* env, struct query_info* q, struct reply_info* r,
+ struct regional* region, time_t now, int allow_expired,
+ struct regional* scratch)
 {
  struct dns_msg* msg;
  size_t i;
- if(now > r->ttl)
- return NULL;
+ int is_expired = 0;
+ time_t now_control = now;
+ if(now > r->ttl) {
+ /* Check if we are allowed to serve expired */
+ if(allow_expired) {
+ if(env->cfg->serve_expired_ttl &&
+ r->serve_expired_ttl < now) {
+ return NULL;
+ }
+ } else {
+ return NULL;
+ }
+ /* Change the current time so we can pass the below TTL checks when
+ * serving expired data. */
+ now_control = r->ttl - env->cfg->serve_expired_reply_ttl;
+ is_expired = 1;
+ }
+
  msg = gen_dns_msg(region, q, r->rrset_count);
- if(!msg)
- return NULL;
+ if(!msg) return NULL;
  msg->rep->flags = r->flags;
  msg->rep->qdcount = r->qdcount;
- msg->rep->ttl = r->ttl - now;
+ msg->rep->ttl = is_expired
+ ?SERVE_EXPIRED_REPLY_TTL
+ :r->ttl - now;
  if(r->prefetch_ttl > now)
  msg->rep->prefetch_ttl = r->prefetch_ttl - now;
- else msg->rep->prefetch_ttl = PREFETCH_TTL_CALC(msg->rep->ttl);
+ else
+ msg->rep->prefetch_ttl = PREFETCH_TTL_CALC(msg->rep->ttl);
  msg->rep->serve_expired_ttl = msg->rep->ttl + SERVE_EXPIRED_TTL;
  msg->rep->security = r->security;
  msg->rep->an_numrrsets = r->an_numrrsets;
  msg->rep->ns_numrrsets = r->ns_numrrsets;
  msg->rep->ar_numrrsets = r->ar_numrrsets;
  msg->rep->rrset_count = r->rrset_count;
-        msg->rep->authoritative = r->authoritative;
- if(!rrset_array_lock(r->ref, r->rrset_count, now))
+ msg->rep->authoritative = r->authoritative;
+ if(!rrset_array_lock(r->ref, r->rrset_count, now_control)) {
  return NULL;
+ }
  if(r->an_numrrsets > 0 && (r->rrsets[0]->rk.type == htons(
  LDNS_RR_TYPE_CNAME) || r->rrsets[0]->rk.type == htons(
  LDNS_RR_TYPE_DNAME)) && !reply_check_cname_chain(q, r)) {
@@ -570,7 +591,7 @@ tomsg(struct module_env* env, struct que
  return NULL;
  }
  for(i=0; i<msg->rep->rrset_count; i++) {
- msg->rep->rrsets[i] = packed_rrset_copy_region(r->rrsets[i],
+ msg->rep->rrsets[i] = packed_rrset_copy_region(r->rrsets[i],
  region, now);
  if(!msg->rep->rrsets[i]) {
  rrset_array_unlock(r->ref, r->rrset_count);
@@ -797,7 +818,7 @@ dns_cache_lookup(struct module_env* env,
  if(e) {
  struct msgreply_entry* key = (struct msgreply_entry*)e->key;
  struct reply_info* data = (struct reply_info*)e->data;
- struct dns_msg* msg = tomsg(env, &key->key, data, region, now,
+ struct dns_msg* msg = tomsg(env, &key->key, data, region, now, 0,
  scratch);
  if(msg) {
  lock_rw_unlock(&e->lock);
@@ -899,37 +920,38 @@ dns_cache_lookup(struct module_env* env,
  * Empty nonterminals are NOERROR, so an NXDOMAIN for foo
  * means bla.foo also does not exist.  The DNSSEC proofs are
  * the same.  We search upwards for NXDOMAINs. */
- if(env->cfg->harden_below_nxdomain)
-    while(!dname_is_root(k.qname)) {
- dname_remove_label(&k.qname, &k.qname_len);
- h = query_info_hash(&k, flags);
- e = slabhash_lookup(env->msg_cache, h, &k, 0);
- if(!e && k.qtype != LDNS_RR_TYPE_A &&
- env->cfg->qname_minimisation) {
- k.qtype = LDNS_RR_TYPE_A;
+ if(env->cfg->harden_below_nxdomain) {
+ while(!dname_is_root(k.qname)) {
+ dname_remove_label(&k.qname, &k.qname_len);
  h = query_info_hash(&k, flags);
  e = slabhash_lookup(env->msg_cache, h, &k, 0);
- }
- if(e) {
- struct reply_info* data = (struct reply_info*)e->data;
- struct dns_msg* msg;
- if(FLAGS_GET_RCODE(data->flags) == LDNS_RCODE_NXDOMAIN
-  && data->security == sec_status_secure
-  && (data->an_numrrsets == 0 ||
- ntohs(data->rrsets[0]->rk.type) != LDNS_RR_TYPE_CNAME)
-  && (msg=tomsg(env, &k, data, region, now, scratch))){
+ if(!e && k.qtype != LDNS_RR_TYPE_A &&
+ env->cfg->qname_minimisation) {
+ k.qtype = LDNS_RR_TYPE_A;
+ h = query_info_hash(&k, flags);
+ e = slabhash_lookup(env->msg_cache, h, &k, 0);
+ }
+ if(e) {
+ struct reply_info* data = (struct reply_info*)e->data;
+ struct dns_msg* msg;
+ if(FLAGS_GET_RCODE(data->flags) == LDNS_RCODE_NXDOMAIN
+ && data->security == sec_status_secure
+ && (data->an_numrrsets == 0 ||
+ ntohs(data->rrsets[0]->rk.type) != LDNS_RR_TYPE_CNAME)
+ && (msg=tomsg(env, &k, data, region, now, 0, scratch))) {
+ lock_rw_unlock(&e->lock);
+ msg->qinfo.qname=qname;
+ msg->qinfo.qname_len=qnamelen;
+ /* check that DNSSEC really works out */
+ msg->rep->security = sec_status_unchecked;
+ iter_scrub_nxdomain(msg);
+ return msg;
+ }
  lock_rw_unlock(&e->lock);
- msg->qinfo.qname=qname;
- msg->qinfo.qname_len=qnamelen;
- /* check that DNSSEC really works out */
- msg->rep->security = sec_status_unchecked;
- iter_scrub_nxdomain(msg);
- return msg;
  }
- lock_rw_unlock(&e->lock);
+ k.qtype = qtype;
  }
- k.qtype = qtype;
-    }
+ }
 
  /* fill common RR types for ANY response to avoid requery */
  if(qtype == LDNS_RR_TYPE_ANY) {
Index: services/cache/dns.h
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/services/cache/dns.h,v
retrieving revision 1.7
diff -u -p -r1.7 dns.h
--- services/cache/dns.h 20 Sep 2018 23:15:39 -0000 1.7
+++ services/cache/dns.h 15 Mar 2020 16:31:04 -0000
@@ -143,11 +143,14 @@ struct delegpt* dns_cache_find_delegatio
  * @param r: reply info that, together with qname, will make up the dns message.
  * @param region: where to allocate dns message.
  * @param now: the time now, for check if TTL on cache entry is ok.
+ * @param allow_expired: if true and serve-expired is enabled, it will allow
+ * for expired dns_msg to be generated based on the configured serve-expired
+ * logic.
  * @param scratch: where to allocate temporary data.
  * */
 struct dns_msg* tomsg(struct module_env* env, struct query_info* q,
  struct reply_info* r, struct regional* region, time_t now,
- struct regional* scratch);
+ int allow_expired, struct regional* scratch);
 
 /**
  * Find cached message
@@ -160,7 +163,7 @@ struct dns_msg* tomsg(struct module_env*
  * @param region: where to allocate result.
  * @param scratch: where to allocate temporary data.
  * @param no_partial: if true, only complete messages and not a partial
- *   one (with only the start of the CNAME chain and not the rest).
+ * one (with only the start of the CNAME chain and not the rest).
  * @return new response message (alloced in region, rrsets do not have IDs).
  * or NULL on error or if not found in cache.
  * TTLs are made relative to the current time.
Index: sldns/parse.c
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/sldns/parse.c,v
retrieving revision 1.4
diff -u -p -r1.4 parse.c
--- sldns/parse.c 18 Dec 2019 11:04:14 -0000 1.4
+++ sldns/parse.c 15 Mar 2020 16:31:04 -0000
@@ -120,7 +120,7 @@ sldns_fget_token_l(FILE *f, char *token,
  if (line_nr) {
  *line_nr = *line_nr + 1;
  }
- if (limit > 0 && (i >= limit || (size_t)(t-token) >= limit)) {
+ if (limit > 0 && (i+1 >= limit || (size_t)(t-token)+1 >= limit)) {
  *t = '\0';
  return -1;
  }
@@ -141,7 +141,8 @@ sldns_fget_token_l(FILE *f, char *token,
  if (c != '\0' && c != '\n') {
  i++;
  }
- if (limit > 0 && (i >= limit || (size_t)(t-token) >= limit)) {
+ /* is there space for the character and the zero after it */
+ if (limit > 0 && (i+1 >= limit || (size_t)(t-token)+1 >= limit)) {
  *t = '\0';
  return -1;
  }
@@ -326,8 +327,8 @@ sldns_bget_token_par(sldns_buffer *b, ch
  /* in parentheses */
  /* do not write ' ' if we want to skip spaces */
  if(!(skipw && (strchr(skipw, c)||strchr(skipw, ' ')))) {
- /* check for space for the space character */
- if (limit > 0 && (i >= limit || (size_t)(t-token) >= limit)) {
+ /* check for space for the space character and a zero delimiter after that. */
+ if (limit > 0 && (i+1 >= limit || (size_t)(t-token)+1 >= limit)) {
  *t = '\0';
  return -1;
  }
@@ -354,7 +355,7 @@ sldns_bget_token_par(sldns_buffer *b, ch
  }
 
  i++;
- if (limit > 0 && (i >= limit || (size_t)(t-token) >= limit)) {
+ if (limit > 0 && (i+1 >= limit || (size_t)(t-token)+1 >= limit)) {
  *t = '\0';
  return -1;
  }
Index: sldns/str2wire.c
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/sldns/str2wire.c,v
retrieving revision 1.11
diff -u -p -r1.11 str2wire.c
--- sldns/str2wire.c 18 Dec 2019 11:04:14 -0000 1.11
+++ sldns/str2wire.c 15 Mar 2020 16:31:04 -0000
@@ -80,7 +80,7 @@ static int sldns_str2wire_dname_buf_rel(
  for (s = str; *s; s++, q++) {
  if (q >= buf + *olen)
  return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, q-buf);
- if (q > buf + LDNS_MAX_DOMAINLEN)
+ if (q >= buf + LDNS_MAX_DOMAINLEN)
  return RET_ERR(LDNS_WIREPARSE_ERR_DOMAINNAME_OVERFLOW, q-buf);
  switch (*s) {
  case '.':
@@ -117,7 +117,7 @@ static int sldns_str2wire_dname_buf_rel(
  if(rel) *rel = 1;
  if (q >= buf + *olen)
  return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL, q-buf);
- if (q > buf + LDNS_MAX_DOMAINLEN) {
+ if (q >= buf + LDNS_MAX_DOMAINLEN) {
  return RET_ERR(LDNS_WIREPARSE_ERR_DOMAINNAME_OVERFLOW, q-buf);
  }
                 if (label_len > LDNS_MAX_LABELLEN) {
Index: smallapp/unbound-checkconf.c
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/smallapp/unbound-checkconf.c,v
retrieving revision 1.13
diff -u -p -r1.13 unbound-checkconf.c
--- smallapp/unbound-checkconf.c 11 Sep 2019 14:13:27 -0000 1.13
+++ smallapp/unbound-checkconf.c 15 Mar 2020 16:31:04 -0000
@@ -548,10 +548,7 @@ morechecks(struct config_file* cfg)
  /* check that the modules listed in module_conf exist */
  check_modules_exist(cfg->module_conf);
 
- /* There should be no reason for 'respip' module not to work with
- * dns64, but it's not explicitly confirmed,  so the combination is
- * excluded below.   It's simply unknown yet for the combination of
- * respip and other modules. */
+ /* Respip is known to *not* work with dns64. */
  if(strcmp(cfg->module_conf, "iterator") != 0
  && strcmp(cfg->module_conf, "validator iterator") != 0
  && strcmp(cfg->module_conf, "dns64 validator iterator") != 0
@@ -560,7 +557,9 @@ morechecks(struct config_file* cfg)
  && strcmp(cfg->module_conf, "respip validator iterator") != 0
 #ifdef WITH_PYTHONMODULE
  && strcmp(cfg->module_conf, "python iterator") != 0
+ && strcmp(cfg->module_conf, "python respip iterator") != 0
  && strcmp(cfg->module_conf, "python validator iterator") != 0
+ && strcmp(cfg->module_conf, "python respip validator iterator") != 0
  && strcmp(cfg->module_conf, "validator python iterator") != 0
  && strcmp(cfg->module_conf, "dns64 python iterator") != 0
  && strcmp(cfg->module_conf, "dns64 python validator iterator") != 0
@@ -570,7 +569,9 @@ morechecks(struct config_file* cfg)
 #endif
 #ifdef USE_CACHEDB
  && strcmp(cfg->module_conf, "validator cachedb iterator") != 0
+ && strcmp(cfg->module_conf, "respip validator cachedb iterator") != 0
  && strcmp(cfg->module_conf, "cachedb iterator") != 0
+ && strcmp(cfg->module_conf, "respip cachedb iterator") != 0
  && strcmp(cfg->module_conf, "dns64 validator cachedb iterator") != 0
  && strcmp(cfg->module_conf, "dns64 cachedb iterator") != 0
 #endif
@@ -580,39 +581,61 @@ morechecks(struct config_file* cfg)
  && strcmp(cfg->module_conf, "dns64 python cachedb iterator") != 0
  && strcmp(cfg->module_conf, "dns64 python validator cachedb iterator") != 0
  && strcmp(cfg->module_conf, "python cachedb iterator") != 0
+ && strcmp(cfg->module_conf, "python respip cachedb iterator") != 0
  && strcmp(cfg->module_conf, "python validator cachedb iterator") != 0
+ && strcmp(cfg->module_conf, "python respip validator cachedb iterator") != 0
  && strcmp(cfg->module_conf, "cachedb python iterator") != 0
+ && strcmp(cfg->module_conf, "respip cachedb python iterator") != 0
  && strcmp(cfg->module_conf, "validator cachedb python iterator") != 0
+ && strcmp(cfg->module_conf, "respip validator cachedb python iterator") != 0
  && strcmp(cfg->module_conf, "validator python cachedb iterator") != 0
+ && strcmp(cfg->module_conf, "respip validator python cachedb iterator") != 0
 #endif
 #ifdef CLIENT_SUBNET
  && strcmp(cfg->module_conf, "subnetcache iterator") != 0
+ && strcmp(cfg->module_conf, "respip subnetcache iterator") != 0
  && strcmp(cfg->module_conf, "subnetcache validator iterator") != 0
+ && strcmp(cfg->module_conf, "respip subnetcache validator iterator") != 0
  && strcmp(cfg->module_conf, "dns64 subnetcache iterator") != 0
  && strcmp(cfg->module_conf, "dns64 subnetcache validator iterator") != 0
 #endif
 #if defined(WITH_PYTHONMODULE) && defined(CLIENT_SUBNET)
  && strcmp(cfg->module_conf, "python subnetcache iterator") != 0
+ && strcmp(cfg->module_conf, "python respip subnetcache iterator") != 0
  && strcmp(cfg->module_conf, "subnetcache python iterator") != 0
+ && strcmp(cfg->module_conf, "respip subnetcache python iterator") != 0
  && strcmp(cfg->module_conf, "python subnetcache validator iterator") != 0
+ && strcmp(cfg->module_conf, "python respip subnetcache validator iterator") != 0
  && strcmp(cfg->module_conf, "subnetcache python validator iterator") != 0
+ && strcmp(cfg->module_conf, "respip subnetcache python validator iterator") != 0
  && strcmp(cfg->module_conf, "subnetcache validator python iterator") != 0
+ && strcmp(cfg->module_conf, "respip subnetcache validator python iterator") != 0
 #endif
 #ifdef USE_IPSECMOD
  && strcmp(cfg->module_conf, "ipsecmod iterator") != 0
+ && strcmp(cfg->module_conf, "ipsecmod respip iterator") != 0
  && strcmp(cfg->module_conf, "ipsecmod validator iterator") != 0
+ && strcmp(cfg->module_conf, "ipsecmod respip validator iterator") != 0
 #endif
 #if defined(WITH_PYTHONMODULE) && defined(USE_IPSECMOD)
  && strcmp(cfg->module_conf, "python ipsecmod iterator") != 0
+ && strcmp(cfg->module_conf, "python ipsecmod respip iterator") != 0
  && strcmp(cfg->module_conf, "ipsecmod python iterator") != 0
+ && strcmp(cfg->module_conf, "ipsecmod python respip iterator") != 0
  && strcmp(cfg->module_conf, "ipsecmod validator iterator") != 0
+ && strcmp(cfg->module_conf, "ipsecmod respip validator iterator") != 0
  && strcmp(cfg->module_conf, "python ipsecmod validator iterator") != 0
+ && strcmp(cfg->module_conf, "python ipsecmod respip validator iterator") != 0
  && strcmp(cfg->module_conf, "ipsecmod python validator iterator") != 0
+ && strcmp(cfg->module_conf, "ipsecmod python respip validator iterator") != 0
  && strcmp(cfg->module_conf, "ipsecmod validator python iterator") != 0
+ && strcmp(cfg->module_conf, "ipsecmod respip validator python iterator") != 0
 #endif
 #ifdef USE_IPSET
  && strcmp(cfg->module_conf, "validator ipset iterator") != 0
+ && strcmp(cfg->module_conf, "validator ipset respip iterator") != 0
  && strcmp(cfg->module_conf, "ipset iterator") != 0
+ && strcmp(cfg->module_conf, "ipset respip iterator") != 0
 #endif
  ) {
  fatal_exit("module conf '%s' is not known to work",
@@ -680,8 +703,9 @@ check_hints(struct config_file* cfg)
 static void
 check_auth(struct config_file* cfg)
 {
+ int is_rpz = 0;
  struct auth_zones* az = auth_zones_create();
- if(!az || !auth_zones_apply_cfg(az, cfg, 0)) {
+ if(!az || !auth_zones_apply_cfg(az, cfg, 0i, &is_rpz)) {
  fatal_exit("Could not setup authority zones");
  }
  auth_zones_delete(az);
Index: smallapp/unbound-control.c
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/smallapp/unbound-control.c,v
retrieving revision 1.16
diff -u -p -r1.16 unbound-control.c
--- smallapp/unbound-control.c 18 Dec 2019 11:04:14 -0000 1.16
+++ smallapp/unbound-control.c 15 Mar 2020 16:31:04 -0000
@@ -62,6 +62,7 @@
 #include "daemon/stats.h"
 #include "sldns/wire2str.h"
 #include "sldns/pkthdr.h"
+#include "services/rpz.h"
 
 #ifdef HAVE_SYS_IPC_H
 #include "sys/ipc.h"
@@ -157,6 +158,8 @@ usage(void)
  printf("  view_local_datas view add list of local-data to view\n");
  printf("   one entry per line read from stdin\n");
  printf("  view_local_data_remove view name   remove local-data in view\n");
+ printf("  view_local_datas_remove view remove list of local-data from view\n");
+ printf("   one entry per line read from stdin\n");
  printf("Version %s\n", PACKAGE_VERSION);
  printf("BSD licensed, see LICENSE in source package for details.\n");
  printf("Report bugs to %s\n", PACKAGE_BUGREPORT);
@@ -208,7 +211,7 @@ static void pr_stats(const char* nm, str
  s->svr.num_queries - s->svr.num_queries_missed_cache);
  PR_UL_NM("num.cachemiss", s->svr.num_queries_missed_cache);
  PR_UL_NM("num.prefetch", s->svr.num_queries_prefetch);
- PR_UL_NM("num.zero_ttl", s->svr.zero_ttl_responses);
+ PR_UL_NM("num.expired", s->svr.ans_expired);
  PR_UL_NM("num.recursivereplies", s->mesh_replies_sent);
 #ifdef USE_DNSCRYPT
     PR_UL_NM("num.dnscrypt.crypted", s->svr.num_query_dnscrypt_crypted);
@@ -372,6 +375,14 @@ static void print_extended(struct ub_sta
  PR_UL("rrset.cache.count", s->svr.rrset_cache_count);
  PR_UL("infra.cache.count", s->svr.infra_cache_count);
  PR_UL("key.cache.count", s->svr.key_cache_count);
+ /* applied RPZ actions */
+ for(i=0; i<UB_STATS_RPZ_ACTION_NUM; i++) {
+ if(i == RPZ_NO_OVERRIDE_ACTION)
+ continue;
+ if(inhibit_zero && s->svr.rpz_action[i] == 0)
+ continue;
+ PR_UL_SUB("num.rpz.action", rpz_action_to_string(i), s->svr.rpz_action[i]);
+ }
 #ifdef USE_DNSCRYPT
  PR_UL("dnscrypt_shared_secret.cache.count",
  s->svr.shared_secret_cache_count);
@@ -493,9 +504,11 @@ setup_ctx(struct config_file* cfg)
  ctx = SSL_CTX_new(SSLv23_client_method());
  if(!ctx)
  ssl_err("could not allocate SSL_CTX pointer");
+#if SSL_OP_NO_SSLv2 != 0
  if((SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2) & SSL_OP_NO_SSLv2)
  != SSL_OP_NO_SSLv2)
  ssl_err("could not set SSL_OP_NO_SSLv2");
+#endif
  if((SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv3) & SSL_OP_NO_SSLv3)
  != SSL_OP_NO_SSLv3)
  ssl_err("could not set SSL_OP_NO_SSLv3");
@@ -704,7 +717,8 @@ check_args_for_listcmd(int argc, char* a
  fatal_exit("too many arguments for command '%s', "
  "content is piped in from stdin", argv[0]);
  }
- if(argc >= 1 && strcmp(argv[0], "view_local_datas") == 0 &&
+ if(argc >= 1 && (strcmp(argv[0], "view_local_datas") == 0 ||
+ strcmp(argv[0], "view_local_datas_remove") == 0) &&
  argc >= 3) {
  fatal_exit("too many arguments for command '%s', "
  "content is piped in from stdin", argv[0]);
@@ -753,7 +767,8 @@ go_cmd(SSL* ssl, int fd, int quiet, int
  strcmp(argv[0], "local_zones_remove") == 0 ||
  strcmp(argv[0], "local_datas") == 0 ||
  strcmp(argv[0], "view_local_datas") == 0 ||
- strcmp(argv[0], "local_datas_remove") == 0)) {
+ strcmp(argv[0], "local_datas_remove") == 0 ||
+ strcmp(argv[0], "view_local_datas_remove") == 0)) {
  send_file(ssl, fd, stdin, buf, sizeof(buf));
  send_eof(ssl, fd);
  }
Index: testcode/petal.c
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/testcode/petal.c,v
retrieving revision 1.1.1.4
diff -u -p -r1.1.1.4 petal.c
--- testcode/petal.c 18 Dec 2019 11:02:59 -0000 1.1.1.4
+++ testcode/petal.c 15 Mar 2020 16:31:04 -0000
@@ -234,7 +234,9 @@ setup_ctx(char* key, char* cert)
 {
  SSL_CTX* ctx = SSL_CTX_new(SSLv23_server_method());
  if(!ctx) print_exit("out of memory");
+#if SSL_OP_NO_SSLv2 != 0
  (void)SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2);
+#endif
  (void)SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv3);
  if(!SSL_CTX_use_certificate_chain_file(ctx, cert))
  print_exit("cannot read cert");
Index: testcode/replay.h
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/testcode/replay.h,v
retrieving revision 1.1.1.2
diff -u -p -r1.1.1.2 replay.h
--- testcode/replay.h 20 Sep 2018 23:14:39 -0000 1.1.1.2
+++ testcode/replay.h 15 Mar 2020 16:31:04 -0000
@@ -74,18 +74,18 @@
  * o CHECK_ANSWER - followed by entry
  * o CHECK_OUT_QUERY - followed by entry (if copy-id it is also reply).
  * o REPLY - followed by entry
- *      o TIMEOUT
- *      o TIME_PASSES ELAPSE [seconds] - increase 'now' time counter, can be
- *       a floating point number.
- *        TIME_PASSES EVAL [macro] - expanded for seconds to move time.
- *      o TRAFFIC - like CHECK_ANSWER, causes traffic to flow.
+ * o TIMEOUT
+ * o TIME_PASSES ELAPSE [seconds] - increase 'now' time counter, can be
+ * a floating point number.
+ *  TIME_PASSES EVAL [macro] - expanded for seconds to move time.
+ * o TRAFFIC - like CHECK_ANSWER, causes traffic to flow.
  * actually the traffic flows before this step is taken.
  * the step waits for traffic to stop.
- *      o CHECK_AUTOTRUST [id] - followed by FILE_BEGIN [to match] FILE_END.
- *       The file contents is macro expanded before match.
- *      o CHECK_TEMPFILE [fname] - followed by FILE_BEGIN [to match] FILE_END
- *      o INFRA_RTT [ip] [dp] [rtt] - update infra cache entry with rtt.
- *      o ERROR
+ * o CHECK_AUTOTRUST [id] - followed by FILE_BEGIN [to match] FILE_END.
+ * The file contents is macro expanded before match.
+ * o CHECK_TEMPFILE [fname] - followed by FILE_BEGIN [to match] FILE_END
+ * o INFRA_RTT [ip] [dp] [rtt] - update infra cache entry with rtt.
+ * o ERROR
  * ; following entry starts on the next line, ENTRY_BEGIN.
  * ; more STEP items
  * SCENARIO_END
Index: testcode/unitdname.c
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/testcode/unitdname.c,v
retrieving revision 1.1.1.1
diff -u -p -r1.1.1.1 unitdname.c
--- testcode/unitdname.c 17 Sep 2018 09:43:45 -0000 1.1.1.1
+++ testcode/unitdname.c 15 Mar 2020 16:31:04 -0000
@@ -794,6 +794,34 @@ dname_test_valid(void)
  , 4096) == 0);
 }
 
+/** Test dname_has_label */
+static void
+dname_test_has_label(void)
+{
+ unit_show_func("util/data/dname.c", "dname_has_label");
+ /* label past root label */
+ unit_assert(dname_has_label((uint8_t*)"\01a\0\01c", 5, (uint8_t*)"\01c") == 0);
+ /* label not found */
+ unit_assert(dname_has_label((uint8_t*)"\02ab\01c\0", 6, (uint8_t*)"\01e") == 0);
+ /* buffer too short */
+ unit_assert(dname_has_label((uint8_t*)"\02ab\01c\0", 5, (uint8_t*)"\0") == 0);
+ unit_assert(dname_has_label((uint8_t*)"\1a\0", 2, (uint8_t*)"\0") == 0);
+ unit_assert(dname_has_label((uint8_t*)"\0", 0, (uint8_t*)"\0") == 0);
+ unit_assert(dname_has_label((uint8_t*)"\02ab\01c", 4, (uint8_t*)"\01c") == 0);
+ unit_assert(dname_has_label((uint8_t*)"\02ab\03qwe\06oqieur\03def\01c\0", 19, (uint8_t*)"\01c") == 0);
+
+ /* positive cases  */
+ unit_assert(dname_has_label((uint8_t*)"\0", 1, (uint8_t*)"\0") == 1);
+ unit_assert(dname_has_label((uint8_t*)"\1a\0", 3, (uint8_t*)"\0") == 1);
+ unit_assert(dname_has_label((uint8_t*)"\01a\0\01c", 5, (uint8_t*)"\0") == 1);
+ unit_assert(dname_has_label((uint8_t*)"\02ab\01c", 5, (uint8_t*)"\01c") == 1);
+ unit_assert(dname_has_label((uint8_t*)"\02ab\01c\0", 10, (uint8_t*)"\0") == 1);
+ unit_assert(dname_has_label((uint8_t*)"\02ab\01c\0", 7, (uint8_t*)"\0") == 1);
+ unit_assert(dname_has_label((uint8_t*)"\02ab\03qwe\06oqieur\03def\01c\0", 22, (uint8_t*)"\03def") == 1);
+ unit_assert(dname_has_label((uint8_t*)"\02ab\03qwe\06oqieur\03def\01c\0", 22, (uint8_t*)"\02ab") == 1);
+ unit_assert(dname_has_label((uint8_t*)"\02ab\03qwe\06oqieur\03def\01c\0", 22, (uint8_t*)"\01c") == 1);
+}
+
 /** test pkt_dname_tolower */
 static void
 dname_test_pdtl(sldns_buffer* loopbuf, sldns_buffer* boundbuf)
@@ -855,6 +883,7 @@ void dname_test(void)
  dname_test_canoncmp();
  dname_test_topdomain();
  dname_test_valid();
+ dname_test_has_label();
  sldns_buffer_free(buff);
  sldns_buffer_free(loopbuf);
  sldns_buffer_free(boundbuf);
Index: util/config_file.c
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/util/config_file.c,v
retrieving revision 1.21
diff -u -p -r1.21 config_file.c
--- util/config_file.c 11 Sep 2019 14:13:27 -0000 1.21
+++ util/config_file.c 15 Mar 2020 16:31:04 -0000
@@ -246,6 +246,8 @@ config_create(void)
  cfg->serve_expired = 0;
  cfg->serve_expired_ttl = 0;
  cfg->serve_expired_ttl_reset = 0;
+ cfg->serve_expired_reply_ttl = 30;
+ cfg->serve_expired_client_timeout = 0;
  cfg->add_holddown = 30*24*3600;
  cfg->del_holddown = 30*24*3600;
  cfg->keep_missing = 366*24*3600; /* one year plus a little leeway */
@@ -327,9 +329,14 @@ config_create(void)
  cfg->ipsecmod_strict = 0;
 #endif
 #ifdef USE_CACHEDB
- cfg->cachedb_backend = NULL;
- cfg->cachedb_secret = NULL;
-#endif
+ if(!(cfg->cachedb_backend = strdup("testframe"))) goto error_exit;
+ if(!(cfg->cachedb_secret = strdup("default"))) goto error_exit;
+#ifdef USE_REDIS
+ if(!(cfg->redis_server_host = strdup("127.0.0.1"))) goto error_exit;
+ cfg->redis_timeout = 100;
+ cfg->redis_server_port = 6379;
+#endif  /* USE_REDIS */
+#endif  /* USE_CACHEDB */
 #ifdef USE_IPSET
  cfg->ipset_name_v4 = NULL;
  cfg->ipset_name_v6 = NULL;
@@ -581,10 +588,15 @@ int config_set_option(struct config_file
  else S_YNO("val-permissive-mode:", val_permissive_mode)
  else S_YNO("aggressive-nsec:", aggressive_nsec)
  else S_YNO("ignore-cd-flag:", ignore_cd)
- else S_YNO("serve-expired:", serve_expired)
- else if(strcmp(opt, "serve_expired_ttl:") == 0)
+ else if(strcmp(opt, "serve-expired:") == 0)
+ { IS_YES_OR_NO; cfg->serve_expired = (strcmp(val, "yes") == 0);
+  SERVE_EXPIRED = cfg->serve_expired; }
+ else if(strcmp(opt, "serve-expired-ttl:") == 0)
  { IS_NUMBER_OR_ZERO; cfg->serve_expired_ttl = atoi(val); SERVE_EXPIRED_TTL=(time_t)cfg->serve_expired_ttl;}
  else S_YNO("serve-expired-ttl-reset:", serve_expired_ttl_reset)
+ else if(strcmp(opt, "serve-expired-reply-ttl:") == 0)
+ { IS_NUMBER_OR_ZERO; cfg->serve_expired_reply_ttl = atoi(val); SERVE_EXPIRED_REPLY_TTL=(time_t)cfg->serve_expired_reply_ttl;}
+ else S_NUMBER_OR_ZERO("serve-expired-client-timeout:", serve_expired_client_timeout)
  else S_STR("val-nsec3-keysize-iterations:", val_nsec3_key_iterations)
  else S_UNSIGNED_OR_ZERO("add-holddown:", add_holddown)
  else S_UNSIGNED_OR_ZERO("del-holddown:", del_holddown)
@@ -977,6 +989,8 @@ config_get_option(struct config_file* cf
  else O_YNO(opt, "serve-expired", serve_expired)
  else O_DEC(opt, "serve-expired-ttl", serve_expired_ttl)
  else O_YNO(opt, "serve-expired-ttl-reset", serve_expired_ttl_reset)
+ else O_DEC(opt, "serve-expired-reply-ttl", serve_expired_reply_ttl)
+ else O_DEC(opt, "serve-expired-client-timeout", serve_expired_client_timeout)
  else O_STR(opt, "val-nsec3-keysize-iterations",val_nsec3_key_iterations)
  else O_UNS(opt, "add-holddown", add_holddown)
  else O_UNS(opt, "del-holddown", del_holddown)
@@ -1098,7 +1112,12 @@ config_get_option(struct config_file* cf
 #ifdef USE_CACHEDB
  else O_STR(opt, "backend", cachedb_backend)
  else O_STR(opt, "secret-seed", cachedb_secret)
-#endif
+#ifdef USE_REDIS
+ else O_STR(opt, "redis-server-host", redis_server_host)
+ else O_DEC(opt, "redis-server-port", redis_server_port)
+ else O_DEC(opt, "redis-timeout", redis_timeout)
+#endif  /* USE_REDIS */
+#endif  /* USE_CACHEDB */
 #ifdef USE_IPSET
  else O_STR(opt, "name-v4", ipset_name_v4)
  else O_STR(opt, "name-v6", ipset_name_v6)
@@ -1279,6 +1298,10 @@ config_delauth(struct config_auth* p)
  config_delstrlist(p->urls);
  config_delstrlist(p->allow_notify);
  free(p->zonefile);
+ free(p->rpz_taglist);
+ free(p->rpz_action_override);
+ free(p->rpz_cname);
+ free(p->rpz_log_name);
  free(p);
 }
 
@@ -1381,7 +1404,10 @@ config_delete(struct config_file* cfg)
  config_delstrlist(cfg->tls_session_ticket_keys.first);
  free(cfg->tls_ciphers);
  free(cfg->tls_ciphersuites);
- free(cfg->log_identity);
+ if(cfg->log_identity) {
+ log_ident_revert_to_default();
+ free(cfg->log_identity);
+ }
  config_del_strarray(cfg->ifs, cfg->num_ifs);
  config_del_strarray(cfg->out_ifs, cfg->num_out_ifs);
  config_delstubs(cfg->stubs);
@@ -1444,7 +1470,10 @@ config_delete(struct config_file* cfg)
 #ifdef USE_CACHEDB
  free(cfg->cachedb_backend);
  free(cfg->cachedb_secret);
-#endif
+#ifdef USE_REDIS
+ free(cfg->redis_server_host);
+#endif  /* USE_REDIS */
+#endif  /* USE_CACHEDB */
 #ifdef USE_IPSET
  free(cfg->ipset_name_v4);
  free(cfg->ipset_name_v6);
@@ -1942,7 +1971,7 @@ char* config_taglist2str(struct config_f
  return strdup(buf);
 }
 
-int taglist_intersect(uint8_t* list1, size_t list1len, uint8_t* list2,
+int taglist_intersect(uint8_t* list1, size_t list1len, const uint8_t* list2,
  size_t list2len)
 {
  size_t i;
@@ -1960,7 +1989,9 @@ config_apply(struct config_file* config)
 {
  MAX_TTL = (time_t)config->max_ttl;
  MIN_TTL = (time_t)config->min_ttl;
+ SERVE_EXPIRED = config->serve_expired;
  SERVE_EXPIRED_TTL = (time_t)config->serve_expired_ttl;
+ SERVE_EXPIRED_REPLY_TTL = (time_t)config->serve_expired_reply_ttl;
  MAX_NEG_TTL = (time_t)config->max_negative_ttl;
  RTT_MIN_TIMEOUT = config->infra_cache_min_rtt;
  EDNS_ADVERTISED_SIZE = (uint16_t)config->edns_buffer_size;
Index: util/config_file.h
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/util/config_file.h,v
retrieving revision 1.19
diff -u -p -r1.19 config_file.h
--- util/config_file.h 11 Sep 2019 14:13:27 -0000 1.19
+++ util/config_file.h 15 Mar 2020 16:31:04 -0000
@@ -362,6 +362,11 @@ struct config_file {
  int serve_expired_ttl;
  /** reset serve expired TTL after failed update attempt */
  int serve_expired_ttl_reset;
+ /** TTL for the serve expired replies */
+ int serve_expired_reply_ttl;
+ /** serve expired entries only after trying to update the entries and this
+ *  timeout (in milliseconds) is reached */
+ int serve_expired_client_timeout;
  /** nsec3 maximum iterations per key size, string */
  char* val_nsec3_key_iterations;
  /** autotrust add holddown time, in seconds */
@@ -641,6 +646,21 @@ struct config_auth {
  /** fallback to recursion to authorities if zone expired and other
  * reasons perhaps (like, query bogus) */
  int fallback_enabled;
+ /** this zone is used to create local-zone policies */
+ int isrpz;
+ /** rpz tags (or NULL) */
+ uint8_t* rpz_taglist;
+ /** length of the taglist (in bytes) */
+ size_t rpz_taglistlen;
+ /** Override RPZ action for this zone, regardless of zone content */
+ char* rpz_action_override;
+ /** Log when this RPZ policy is applied */
+ int rpz_log;
+ /** Display this name in the log when RPZ policy is applied */
+ char* rpz_log_name;
+ /** Always reply with this CNAME target if the cname override action is
+ * used */
+ char* rpz_cname;
 };
 
 /**
@@ -1043,7 +1063,7 @@ char* config_taglist2str(struct config_f
  * @param list2len: length in bytes of second list.
  * @return true if there are tags in common, 0 if not.
  */
-int taglist_intersect(uint8_t* list1, size_t list1len, uint8_t* list2,
+int taglist_intersect(uint8_t* list1, size_t list1len, const uint8_t* list2,
  size_t list2len);
 
 /**
Index: util/configlexer.lex
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/util/configlexer.lex,v
retrieving revision 1.16
diff -u -p -r1.16 configlexer.lex
--- util/configlexer.lex 18 Dec 2019 11:04:14 -0000 1.16
+++ util/configlexer.lex 15 Mar 2020 16:31:04 -0000
@@ -316,6 +316,12 @@ forward-no-cache{COLON} { YDVAR(1, VAR_
 forward-ssl-upstream{COLON} { YDVAR(1, VAR_FORWARD_SSL_UPSTREAM) }
 forward-tls-upstream{COLON} { YDVAR(1, VAR_FORWARD_SSL_UPSTREAM) }
 auth-zone{COLON} { YDVAR(0, VAR_AUTH_ZONE) }
+rpz{COLON} { YDVAR(0, VAR_RPZ) }
+tags{COLON} { YDVAR(1, VAR_TAGS) }
+rpz-action-override{COLON} { YDVAR(1, VAR_RPZ_ACTION_OVERRIDE) }
+rpz-cname-override{COLON} { YDVAR(1, VAR_RPZ_CNAME_OVERRIDE) }
+rpz-log{COLON} { YDVAR(1, VAR_RPZ_LOG) }
+rpz-log-name{COLON} { YDVAR(1, VAR_RPZ_LOG_NAME) }
 zonefile{COLON} { YDVAR(1, VAR_ZONEFILE) }
 master{COLON} { YDVAR(1, VAR_MASTER) }
 url{COLON} { YDVAR(1, VAR_URL) }
@@ -363,6 +369,8 @@ ignore-cd-flag{COLON} { YDVAR(1, VAR_IG
 serve-expired{COLON} { YDVAR(1, VAR_SERVE_EXPIRED) }
 serve-expired-ttl{COLON} { YDVAR(1, VAR_SERVE_EXPIRED_TTL) }
 serve-expired-ttl-reset{COLON} { YDVAR(1, VAR_SERVE_EXPIRED_TTL_RESET) }
+serve-expired-reply-ttl{COLON} { YDVAR(1, VAR_SERVE_EXPIRED_REPLY_TTL) }
+serve-expired-client-timeout{COLON} { YDVAR(1, VAR_SERVE_EXPIRED_CLIENT_TIMEOUT) }
 fake-dsa{COLON} { YDVAR(1, VAR_FAKE_DSA) }
 fake-sha1{COLON} { YDVAR(1, VAR_FAKE_SHA1) }
 val-log-level{COLON} { YDVAR(1, VAR_VAL_LOG_LEVEL) }
Index: util/configparser.y
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/util/configparser.y,v
retrieving revision 1.16
diff -u -p -r1.16 configparser.y
--- util/configparser.y 11 Sep 2019 14:13:27 -0000 1.16
+++ util/configparser.y 15 Mar 2020 16:31:04 -0000
@@ -143,10 +143,11 @@ extern struct config_parser_state* cfg_p
 %token VAR_LOCAL_ZONE_OVERRIDE VAR_ACCESS_CONTROL_TAG_ACTION
 %token VAR_ACCESS_CONTROL_TAG_DATA VAR_VIEW VAR_ACCESS_CONTROL_VIEW
 %token VAR_VIEW_FIRST VAR_SERVE_EXPIRED VAR_SERVE_EXPIRED_TTL
-%token VAR_SERVE_EXPIRED_TTL_RESET VAR_FAKE_DSA VAR_FAKE_SHA1
-%token VAR_LOG_IDENTITY VAR_HIDE_TRUSTANCHOR VAR_TRUST_ANCHOR_SIGNALING
-%token VAR_AGGRESSIVE_NSEC VAR_USE_SYSTEMD VAR_SHM_ENABLE VAR_SHM_KEY
-%token VAR_ROOT_KEY_SENTINEL
+%token VAR_SERVE_EXPIRED_TTL_RESET VAR_SERVE_EXPIRED_REPLY_TTL
+%token VAR_SERVE_EXPIRED_CLIENT_TIMEOUT VAR_FAKE_DSA
+%token VAR_FAKE_SHA1 VAR_LOG_IDENTITY VAR_HIDE_TRUSTANCHOR
+%token VAR_TRUST_ANCHOR_SIGNALING VAR_AGGRESSIVE_NSEC VAR_USE_SYSTEMD
+%token VAR_SHM_ENABLE VAR_SHM_KEY VAR_ROOT_KEY_SENTINEL
 %token VAR_DNSCRYPT VAR_DNSCRYPT_ENABLE VAR_DNSCRYPT_PORT VAR_DNSCRYPT_PROVIDER
 %token VAR_DNSCRYPT_SECRET_KEY VAR_DNSCRYPT_PROVIDER_CERT
 %token VAR_DNSCRYPT_PROVIDER_CERT_ROTATED
@@ -166,8 +167,9 @@ extern struct config_parser_state* cfg_p
 %token VAR_FORWARD_NO_CACHE VAR_STUB_NO_CACHE VAR_LOG_SERVFAIL VAR_DENY_ANY
 %token VAR_UNKNOWN_SERVER_TIME_LIMIT VAR_LOG_TAG_QUERYREPLY
 %token VAR_STREAM_WAIT_SIZE VAR_TLS_CIPHERS VAR_TLS_CIPHERSUITES
-%token VAR_TLS_SESSION_TICKET_KEYS
 %token VAR_IPSET VAR_IPSET_NAME_V4 VAR_IPSET_NAME_V6
+%token VAR_TLS_SESSION_TICKET_KEYS VAR_RPZ VAR_TAGS VAR_RPZ_ACTION_OVERRIDE
+%token VAR_RPZ_CNAME_OVERRIDE VAR_RPZ_LOG VAR_RPZ_LOG_NAME
 
 %%
 toplevelvars: /* empty */ | toplevelvars toplevelvar ;
@@ -175,7 +177,8 @@ toplevelvar: serverstart contents_server
  forwardstart contents_forward | pythonstart contents_py |
  rcstart contents_rc | dtstart contents_dt | viewstart contents_view |
  dnscstart contents_dnsc | cachedbstart contents_cachedb |
- ipsetstart contents_ipset | authstart contents_auth
+ ipsetstart contents_ipset | authstart contents_auth |
+ rpzstart contents_rpz
  ;
 
 /* server: declaration */
@@ -254,6 +257,7 @@ content_server: server_num_threads | ser
  server_access_control_tag_data | server_access_control_view |
  server_qname_minimisation_strict | server_serve_expired |
  server_serve_expired_ttl | server_serve_expired_ttl_reset |
+ server_serve_expired_reply_ttl | server_serve_expired_client_timeout |
  server_fake_dsa | server_log_identity | server_use_systemd |
  server_response_ip_tag | server_response_ip | server_response_ip_data |
  server_shm_enable | server_shm_key | server_fake_sha1 |
@@ -335,6 +339,7 @@ authstart: VAR_AUTH_ZONE
  s->for_downstream = 1;
  s->for_upstream = 1;
  s->fallback_enabled = 0;
+ s->isrpz = 0;
  } else
  yyerror("out of memory");
  }
@@ -345,6 +350,92 @@ content_auth: auth_name | auth_zonefile
  auth_for_downstream | auth_for_upstream | auth_fallback_enabled |
  auth_allow_notify
  ;
+
+rpz_tag: VAR_TAGS STRING_ARG
+ {
+ uint8_t* bitlist;
+ size_t len = 0;
+ OUTYY(("P(server_local_zone_tag:%s)\n", $2));
+ bitlist = config_parse_taglist(cfg_parser->cfg, $2,
+ &len);
+ free($2);
+ if(!bitlist) {
+ yyerror("could not parse tags, (define-tag them first)");
+ }
+ if(bitlist) {
+ cfg_parser->cfg->auths->rpz_taglist = bitlist;
+ cfg_parser->cfg->auths->rpz_taglistlen = len;
+
+ }
+ }
+ ;
+
+rpz_action_override: VAR_RPZ_ACTION_OVERRIDE STRING_ARG
+ {
+ OUTYY(("P(rpz_action_override:%s)\n", $2));
+ if(strcmp($2, "nxdomain")!=0 && strcmp($2, "nodata")!=0 &&
+   strcmp($2, "passthru")!=0 && strcmp($2, "drop")!=0 &&
+   strcmp($2, "cname")!=0 && strcmp($2, "disabled")!=0) {
+ yyerror("rpz-action-override action: expected nxdomain, "
+ "nodata, passthru, drop, cname or disabled");
+ free($2);
+ cfg_parser->cfg->auths->rpz_action_override = NULL;
+ }
+ else {
+ cfg_parser->cfg->auths->rpz_action_override = $2;
+ }
+ }
+ ;
+
+rpz_cname_override: VAR_RPZ_CNAME_OVERRIDE STRING_ARG
+ {
+ OUTYY(("P(rpz_cname_override:%s)\n", $2));
+ free(cfg_parser->cfg->auths->rpz_cname);
+ cfg_parser->cfg->auths->rpz_cname = $2;
+ }
+ ;
+
+rpz_log: VAR_RPZ_LOG STRING_ARG
+ {
+ OUTYY(("P(rpz_log:%s)\n", $2));
+ if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0)
+ yyerror("expected yes or no.");
+ else cfg_parser->cfg->auths->rpz_log = (strcmp($2, "yes")==0);
+ free($2);
+ }
+ ;
+
+rpz_log_name: VAR_RPZ_LOG_NAME STRING_ARG
+ {
+ OUTYY(("P(rpz_log_name:%s)\n", $2));
+ free(cfg_parser->cfg->auths->rpz_log_name);
+ cfg_parser->cfg->auths->rpz_log_name = $2;
+ }
+ ;
+
+rpzstart: VAR_RPZ
+ {
+ struct config_auth* s;
+ OUTYY(("\nP(rpz:)\n"));
+ s = (struct config_auth*)calloc(1, sizeof(struct config_auth));
+ if(s) {
+ s->next = cfg_parser->cfg->auths;
+ cfg_parser->cfg->auths = s;
+ /* defaults for RPZ auth zone */
+ s->for_downstream = 0;
+ s->for_upstream = 0;
+ s->fallback_enabled = 0;
+ s->isrpz = 1;
+ } else
+ yyerror("out of memory");
+ }
+ ;
+contents_rpz: contents_rpz content_rpz
+ | ;
+content_rpz: auth_name | auth_zonefile | rpz_tag | auth_master | auth_url |
+   auth_allow_notify | rpz_action_override | rpz_cname_override |
+   rpz_log | rpz_log_name
+ ;
 server_num_threads: VAR_NUM_THREADS STRING_ARG
  {
  OUTYY(("P(server_num_threads:%s)\n", $2));
@@ -429,6 +520,7 @@ server_send_client_subnet: VAR_SEND_CLIE
  fatal_exit("out of memory adding client-subnet");
  #else
  OUTYY(("P(Compiled without edns subnet option, ignoring)\n"));
+ free($2);
  #endif
  }
  ;
@@ -441,6 +533,7 @@ server_client_subnet_zone: VAR_CLIENT_SU
  fatal_exit("out of memory adding client-subnet-zone");
  #else
  OUTYY(("P(Compiled without edns subnet option, ignoring)\n"));
+ free($2);
  #endif
  }
  ;
@@ -1666,12 +1759,30 @@ server_serve_expired_ttl_reset: VAR_SERV
  free($2);
  }
  ;
+server_serve_expired_reply_ttl: VAR_SERVE_EXPIRED_REPLY_TTL STRING_ARG
+ {
+ OUTYY(("P(server_serve_expired_reply_ttl:%s)\n", $2));
+ if(atoi($2) == 0 && strcmp($2, "0") != 0)
+ yyerror("number expected");
+ else cfg_parser->cfg->serve_expired_reply_ttl = atoi($2);
+ free($2);
+ }
+ ;
+server_serve_expired_client_timeout: VAR_SERVE_EXPIRED_CLIENT_TIMEOUT STRING_ARG
+ {
+ OUTYY(("P(server_serve_expired_client_timeout:%s)\n", $2));
+ if(atoi($2) == 0 && strcmp($2, "0") != 0)
+ yyerror("number expected");
+ else cfg_parser->cfg->serve_expired_client_timeout = atoi($2);
+ free($2);
+ }
+ ;
 server_fake_dsa: VAR_FAKE_DSA STRING_ARG
  {
  OUTYY(("P(server_fake_dsa:%s)\n", $2));
  if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0)
  yyerror("expected yes or no.");
-#ifdef HAVE_SSL
+#if defined(HAVE_SSL) || defined(HAVE_NETTLE)
  else fake_dsa = (strcmp($2, "yes")==0);
  if(fake_dsa)
  log_warn("test option fake_dsa is enabled");
@@ -1684,7 +1795,7 @@ server_fake_sha1: VAR_FAKE_SHA1 STRING_A
  OUTYY(("P(server_fake_sha1:%s)\n", $2));
  if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0)
  yyerror("expected yes or no.");
-#ifdef HAVE_SSL
+#if defined(HAVE_SSL) || defined(HAVE_NETTLE)
  else fake_sha1 = (strcmp($2, "yes")==0);
  if(fake_sha1)
  log_warn("test option fake_sha1 is enabled");
@@ -2898,9 +3009,6 @@ cachedb_backend_name: VAR_CACHEDB_BACKEN
  {
  #ifdef USE_CACHEDB
  OUTYY(("P(backend:%s)\n", $2));
- if(cfg_parser->cfg->cachedb_backend)
- yyerror("cachedb backend override, there must be one "
- "backend");
  free(cfg_parser->cfg->cachedb_backend);
  cfg_parser->cfg->cachedb_backend = $2;
  #else
@@ -2913,9 +3021,6 @@ cachedb_secret_seed: VAR_CACHEDB_SECRETS
  {
  #ifdef USE_CACHEDB
  OUTYY(("P(secret-seed:%s)\n", $2));
- if(cfg_parser->cfg->cachedb_secret)
- yyerror("cachedb secret-seed override, there must be "
- "only one secret");
  free(cfg_parser->cfg->cachedb_secret);
  cfg_parser->cfg->cachedb_secret = $2;
  #else
Index: util/fptr_wlist.c
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/util/fptr_wlist.c,v
retrieving revision 1.16
diff -u -p -r1.16 fptr_wlist.c
--- util/fptr_wlist.c 11 Sep 2019 14:13:27 -0000 1.16
+++ util/fptr_wlist.c 15 Mar 2020 16:31:04 -0000
@@ -131,6 +131,7 @@ fptr_whitelist_comm_timer(void (*fptr)(v
  else if(fptr == &auth_xfer_timer) return 1;
  else if(fptr == &auth_xfer_probe_timer_callback) return 1;
  else if(fptr == &auth_xfer_transfer_timer_callback) return 1;
+ else if(fptr == &mesh_serve_expired_callback) return 1;
  return 0;
 }
 
@@ -619,3 +620,9 @@ int fptr_whitelist_inplace_cb_query_resp
  return 0;
 }
 
+int fptr_whitelist_serve_expired_lookup(serve_expired_lookup_func_type* fptr)
+{
+ if(fptr == &mesh_serve_expired_lookup)
+ return 1;
+ return 0;
+}
Index: util/fptr_wlist.h
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/util/fptr_wlist.h,v
retrieving revision 1.9
diff -u -p -r1.9 fptr_wlist.h
--- util/fptr_wlist.h 17 Sep 2018 09:46:12 -0000 1.9
+++ util/fptr_wlist.h 15 Mar 2020 16:31:04 -0000
@@ -377,6 +377,13 @@ int fptr_whitelist_inplace_cb_edns_back_
 int fptr_whitelist_inplace_cb_query_response(
  inplace_cb_query_response_func_type* fptr);
 
+/**
+ * Check function pointer whitelist for serve_expired_lookup func values.
+ * @param fptr: function pointer to check.
+ * @return false if not in whitelist.
+ */
+int fptr_whitelist_serve_expired_lookup(serve_expired_lookup_func_type* fptr);
+
 /** Due to module breakage by fptr wlist, these test app declarations
  * are presented here */
 /**
Index: util/iana_ports.inc
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/util/iana_ports.inc,v
retrieving revision 1.18
diff -u -p -r1.18 iana_ports.inc
--- util/iana_ports.inc 18 Dec 2019 11:04:14 -0000 1.18
+++ util/iana_ports.inc 15 Mar 2020 16:31:04 -0000
@@ -3904,6 +3904,7 @@
 4600,
 4601,
 4621,
+4646,
 4658,
 4659,
 4660,
Index: util/log.c
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/util/log.c,v
retrieving revision 1.7
diff -u -p -r1.7 log.c
--- util/log.c 18 Dec 2019 11:04:14 -0000 1.7
+++ util/log.c 15 Mar 2020 16:31:04 -0000
@@ -74,6 +74,7 @@ static lock_basic_type log_lock;
 #endif
 /** the identity of this executable/process */
 static const char* ident="unbound";
+static const char* default_ident="unbound";
 #if defined(HAVE_SYSLOG_H) || defined(UB_ON_WINDOWS)
 /** are we using syslog(3) to log to */
 static int logging_to_syslog = 0;
@@ -179,6 +180,24 @@ int log_thread_get(void)
 void log_ident_set(const char* id)
 {
  ident = id;
+}
+
+void log_ident_set_default(const char* id)
+{
+ default_ident = id;
+}
+
+void log_ident_revert_to_default()
+{
+ ident = default_ident;
+}
+
+void log_ident_set_or_default(const char* identity)
+{
+ if(identity == NULL || identity[0] == 0)
+ log_ident_set(default_ident);
+ else
+ log_ident_set(identity);
 }
 
 void log_set_time_asc(int use_asc)
Index: util/log.h
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/util/log.h,v
retrieving revision 1.5
diff -u -p -r1.5 log.h
--- util/log.h 8 Feb 2019 10:29:08 -0000 1.5
+++ util/log.h 15 Mar 2020 16:31:04 -0000
@@ -107,10 +107,28 @@ void log_thread_set(int* num);
 int log_thread_get(void);
 
 /**
- * Set identity to print, default is 'unbound'.
+ * Set identity to print, default is 'unbound'.
  * @param id: string to print. Name of executable.
  */
 void log_ident_set(const char* id);
+
+/**
+ * Set default identity to print, default is 'unbound'.
+ * @param id: string to print. Name of executable.
+ */
+void log_ident_set_default(const char* id);
+
+/**
+ * Revert identity to print, back to the recorded default value.
+ */
+void log_ident_revert_to_default();
+
+/**
+ * Set identity to print if there is an identity, otherwise
+ * set the default.
+ * @param identity: the identity to set.
+ */
+void log_ident_set_or_default(const char* identity);
 
 /**
  * Set if the time value is printed ascii or decimal in log entries.
Index: util/module.h
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/util/module.h,v
retrieving revision 1.8
diff -u -p -r1.8 module.h
--- util/module.h 20 Sep 2018 23:15:40 -0000 1.8
+++ util/module.h 15 Mar 2020 16:31:04 -0000
@@ -307,6 +307,17 @@ typedef int inplace_cb_query_response_fu
  struct dns_msg* response, int id, void* cb_args);
 
 /**
+ * Function called when looking for (expired) cached answers during the serve
+ * expired logic.
+ * Called as func(qstate, lookup_qinfo)
+ * Where:
+ * qstate: the query state.
+ * lookup_qinfo: the qinfo to lookup for.
+ */
+typedef struct dns_msg* serve_expired_lookup_func_type(
+ struct module_qstate* qstate, struct query_info* lookup_qinfo);
+
+/**
  * Module environment.
  * Services and data provided to the module.
  */
@@ -572,6 +583,14 @@ struct sock_list {
 struct respip_action_info;
 
 /**
+ * Struct to hold relevant data for serve expired
+ */
+struct serve_expired_data {
+ struct comm_timer* timer;
+ serve_expired_lookup_func_type* get_cached_answer;
+};
+
+/**
  * Module state, per query.
  */
 struct module_qstate {
@@ -612,6 +631,8 @@ struct module_qstate {
  struct mesh_state* mesh_info;
  /** how many seconds before expiry is this prefetched (0 if not) */
  time_t prefetch_leeway;
+ /** serve expired data */
+ struct serve_expired_data* serve_expired_data;
 
  /** incoming edns options from the front end */
  struct edns_option* edns_opts_front_in;
Index: util/net_help.c
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/util/net_help.c,v
retrieving revision 1.18
diff -u -p -r1.18 net_help.c
--- util/net_help.c 18 Dec 2019 11:04:14 -0000 1.18
+++ util/net_help.c 15 Mar 2020 16:31:04 -0000
@@ -284,6 +284,113 @@ int netblockstrtoaddr(const char* str, i
  return 1;
 }
 
+/* RPZ format address dname to network byte order address */
+static int ipdnametoaddr(uint8_t* dname, size_t dnamelen,
+ struct sockaddr_storage* addr, socklen_t* addrlen, int* af)
+{
+ uint8_t* ia;
+ size_t dnamelabs = dname_count_labels(dname);
+ uint8_t lablen;
+ char* e = NULL;
+ int z = 0;
+ size_t len = 0;
+ int i;
+ *af = AF_INET;
+
+ /* need 1 byte for label length */
+ if(dnamelen < 1)
+ return 0;
+
+ if(dnamelabs > 6 ||
+ dname_has_label(dname, dnamelen, (uint8_t*)"\002zz")) {
+ *af = AF_INET6;
+ }
+ len = *dname;
+ lablen = *dname++;
+ i = (*af == AF_INET) ? 3 : 15;
+ if(*af == AF_INET6) {
+ struct sockaddr_in6* sa = (struct sockaddr_in6*)addr;
+ *addrlen = (socklen_t)sizeof(struct sockaddr_in6);
+ memset(sa, 0, *addrlen);
+ sa->sin6_family = AF_INET6;
+ ia = (uint8_t*)&sa->sin6_addr;
+ } else { /* ip4 */
+ struct sockaddr_in* sa = (struct sockaddr_in*)addr;
+ *addrlen = (socklen_t)sizeof(struct sockaddr_in);
+ memset(sa, 0, *addrlen);
+ sa->sin_family = AF_INET;
+ ia = (uint8_t*)&sa->sin_addr;
+ }
+ while(lablen && i >= 0 && len <= dnamelen) {
+ char buff[LDNS_MAX_LABELLEN+1];
+ uint16_t chunk; /* big enough to not overflow on IPv6 hextet */
+ if((*af == AF_INET && (lablen > 3 || dnamelabs > 6)) ||
+ (*af == AF_INET6 && (lablen > 4 || dnamelabs > 10))) {
+ return 0;
+ }
+ if(memcmp(dname, "zz", 2) == 0 && *af == AF_INET6) {
+ /* Add one or more 0 labels. Address is initialised at
+ * 0, so just skip the zero part. */
+ int zl = 11 - dnamelabs;
+ if(z || zl < 0)
+ return 0;
+ z = 1;
+ i -= (zl*2);
+ } else {
+ memcpy(buff, dname, lablen);
+ buff[lablen] = '\0';
+ chunk = strtol(buff, &e, (*af == AF_INET) ? 10 : 16);
+ if(!e || *e != '\0' || (*af == AF_INET && chunk > 255))
+ return 0;
+ if(*af == AF_INET) {
+ log_assert(i < 4 && i >= 0);
+ ia[i] = (uint8_t)chunk;
+ i--;
+ } else {
+ log_assert(i < 16 && i >= 1);
+ /* ia in network byte order */
+ ia[i-1] = (uint8_t)(chunk >> 8);
+ ia[i] = (uint8_t)(chunk & 0x00FF);
+ i -= 2;
+ }
+ }
+ dname += lablen;
+ lablen = *dname++;
+ len += lablen;
+ }
+ if(i != -1)
+ /* input too short */
+ return 0;
+ return 1;
+}
+
+int netblockdnametoaddr(uint8_t* dname, size_t dnamelen,
+ struct sockaddr_storage* addr, socklen_t* addrlen, int* net, int* af)
+{
+ char buff[3 /* 3 digit netblock */ + 1];
+ size_t nlablen;
+ if(dnamelen < 1 || *dname > 3)
+ /* netblock invalid */
+ return 0;
+ nlablen = *dname;
+
+ if(dnamelen < 1 + nlablen)
+ return 0;
+
+ memcpy(buff, dname+1, nlablen);
+ buff[nlablen] = '\0';
+ *net = atoi(buff);
+ if(*net == 0 && strcmp(buff, "0") != 0)
+ return 0;
+ dname += nlablen;
+ dname++;
+ if(!ipdnametoaddr(dname, dnamelen-1-nlablen, addr, addrlen, af))
+ return 0;
+ if((*af == AF_INET6 && *net > 128) || (*af == AF_INET && *net > 32))
+ return 0;
+ return 1;
+}
+
 int authextstrtoaddr(char* str, struct sockaddr_storage* addr,
  socklen_t* addrlen, char** auth_name)
 {
@@ -728,11 +835,13 @@ listen_sslctx_setup(void* ctxt)
 #ifdef HAVE_SSL
  SSL_CTX* ctx = (SSL_CTX*)ctxt;
  /* no SSLv2, SSLv3 because has defects */
+#if SSL_OP_NO_SSLv2 != 0
  if((SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2) & SSL_OP_NO_SSLv2)
  != SSL_OP_NO_SSLv2){
  log_crypto_err("could not set SSL_OP_NO_SSLv2");
  return 0;
  }
+#endif
  if((SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv3) & SSL_OP_NO_SSLv3)
  != SSL_OP_NO_SSLv3){
  log_crypto_err("could not set SSL_OP_NO_SSLv3");
@@ -968,12 +1077,14 @@ void* connect_sslctx_create(char* key, c
  log_crypto_err("could not allocate SSL_CTX pointer");
  return NULL;
  }
+#if SSL_OP_NO_SSLv2 != 0
  if((SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2) & SSL_OP_NO_SSLv2)
  != SSL_OP_NO_SSLv2) {
  log_crypto_err("could not set SSL_OP_NO_SSLv2");
  SSL_CTX_free(ctx);
  return NULL;
  }
+#endif
  if((SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv3) & SSL_OP_NO_SSLv3)
  != SSL_OP_NO_SSLv3) {
  log_crypto_err("could not set SSL_OP_NO_SSLv3");
@@ -1160,13 +1271,21 @@ int listen_sslctx_setup_ticket_keys(void
  s++;
  }
  keys = calloc(s, sizeof(struct tls_session_ticket_key));
+ if(!keys)
+ return 0;
  memset(keys, 0, s*sizeof(*keys));
  ticket_keys = keys;
 
  for(p = tls_session_ticket_keys; p; p = p->next) {
  size_t n;
- unsigned char *data = (unsigned char *)malloc(80);
- FILE *f = fopen(p->str, "r");
+ unsigned char *data;
+ FILE *f;
+
+ data = (unsigned char *)malloc(80);
+ if(!data)
+ return 0;
+
+ f = fopen(p->str, "r");
  if(!f) {
  log_err("could not read tls-session-ticket-key %s: %s", p->str, strerror(errno));
  free(data);
Index: util/net_help.h
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/util/net_help.h,v
retrieving revision 1.6
diff -u -p -r1.6 net_help.h
--- util/net_help.h 18 Dec 2019 11:04:14 -0000 1.6
+++ util/net_help.h 15 Mar 2020 16:31:04 -0000
@@ -471,4 +471,19 @@ int tls_session_ticket_key_cb(void *s, u
 /** Free memory used for TLS session ticket keys */
 void listen_sslctx_delete_ticket_keys(void);
 
+/**
+ * RPZ format netblock to network byte order address and netblock
+ * example RPZ netblock format dnames:
+ *  - 24.10.100.51.198.rpz-ip -> 198.51.100.10/24
+ *  - 32.10.zz.db8.2001.rpz-ip -> 2001:db8:0:0:0:0:0:10/32
+ * @param dname: the dname containing RPZ format netblock
+ * @param dnamelen: length of dname
+ * @param addr: where to store sockaddr.
+ * @param addrlen: length of stored sockaddr is returned.
+ * @param net: where to store netmask
+ * @param af: where to store address family.
+ * @return 0 on error.
+ */
+int netblockdnametoaddr(uint8_t* dname, size_t dnamelen,
+ struct sockaddr_storage* addr, socklen_t* addrlen, int* net, int* af);
 #endif /* NET_HELP_H */
Index: util/netevent.c
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/util/netevent.c,v
retrieving revision 1.22
diff -u -p -r1.22 netevent.c
--- util/netevent.c 18 Dec 2019 11:04:14 -0000 1.22
+++ util/netevent.c 15 Mar 2020 16:31:04 -0000
@@ -1120,6 +1120,14 @@ ssl_handshake(struct comm_point* c)
  return 0; /* closed */
  } else if(want == SSL_ERROR_SYSCALL) {
  /* SYSCALL and errno==0 means closed uncleanly */
+#ifdef EPIPE
+ if(errno == EPIPE && verbosity < 2)
+ return 0; /* silence 'broken pipe' */
+#endif
+#ifdef ECONNRESET
+ if(errno == ECONNRESET && verbosity < 2)
+ return 0; /* silence reset by peer */
+#endif
  if(errno != 0)
  log_err("SSL_handshake syscall: %s",
  strerror(errno));
Index: util/random.c
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/util/random.c,v
retrieving revision 1.6
diff -u -p -r1.6 random.c
--- util/random.c 18 Dec 2019 11:04:14 -0000 1.6
+++ util/random.c 15 Mar 2020 16:31:04 -0000
@@ -78,7 +78,7 @@
  */
 #define MAX_VALUE 0x7fffffff
 
-#if defined(HAVE_SSL)
+#if defined(HAVE_SSL) || defined(HAVE_LIBBSD)
 struct ub_randstate*
 ub_initstate(struct ub_randstate* ATTR_UNUSED(from))
 {
@@ -183,10 +183,10 @@ long int ub_random(struct ub_randstate*
  }
  return x & MAX_VALUE;
 }
-#endif /* HAVE_SSL or HAVE_NSS or HAVE_NETTLE */
+#endif /* HAVE_SSL or HAVE_LIBBSD or HAVE_NSS or HAVE_NETTLE */
 
 
-#if defined(HAVE_NSS) || defined(HAVE_NETTLE)
+#if defined(HAVE_NSS) || defined(HAVE_NETTLE) && !defined(HAVE_LIBBSD)
 long int
 ub_random_max(struct ub_randstate* state, long int x)
 {
@@ -198,7 +198,7 @@ ub_random_max(struct ub_randstate* state
  v = ub_random(state);
  return (v % x);
 }
-#endif /* HAVE_NSS or HAVE_NETTLE */
+#endif /* HAVE_NSS or HAVE_NETTLE and !HAVE_LIBBSD */
 
 void
 ub_randfree(struct ub_randstate* s)
Index: util/data/dname.c
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/util/data/dname.c,v
retrieving revision 1.5
diff -u -p -r1.5 dname.c
--- util/data/dname.c 18 Dec 2019 11:04:14 -0000 1.5
+++ util/data/dname.c 15 Mar 2020 16:31:04 -0000
@@ -558,6 +558,34 @@ dname_lab_startswith(uint8_t* label, cha
  return 1;
 }
 
+int
+dname_has_label(uint8_t* dname, size_t dnamelen, uint8_t* label)
+{
+ size_t len;
+
+ /* 1 byte needed for the label length */
+ if(dnamelen < 1)
+ return 0;
+
+ len = *dname;
+ while(len <= dnamelen) {
+ if(!(*dname)) {
+ if(*dname == *label)
+ return 1; /* empty label match */
+ /* termination label found, stop iterating */
+ return 0;
+ }
+ if(*dname == *label && *label &&
+ memlowercmp(dname+1, label+1, *dname) == 0)
+ return 1;
+ len += *dname;
+ dname += *dname;
+ dname++;
+ len++;
+ }
+ return 0;
+}
+
 int
 dname_buffer_write(sldns_buffer* pkt, uint8_t* dname)
 {
Index: util/data/dname.h
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/util/data/dname.h,v
retrieving revision 1.3
diff -u -p -r1.3 dname.h
--- util/data/dname.h 17 Sep 2018 09:46:12 -0000 1.3
+++ util/data/dname.h 15 Mar 2020 16:31:04 -0000
@@ -197,6 +197,15 @@ int dname_lab_cmp(uint8_t* d1, int labs1
 int dname_lab_startswith(uint8_t* label, char* prefix, char** endptr);
 
 /**
+ * Check if dname contains label
+ * @param dname: dname
+ * @param dnamelen: length of dname
+ * @param label: label to be checked for presence in dname
+ * @return: 1 if dname has this label, 0 otherwise
+ */
+int dname_has_label(uint8_t* dname, size_t dnamelen, uint8_t* label);
+
+/**
  * See if domain name d1 is a strict subdomain of d2.
  * That is a subdomain, but not equal.
  * @param d1: domain name, uncompressed wireformat
Index: util/data/msgencode.c
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/util/data/msgencode.c,v
retrieving revision 1.8
diff -u -p -r1.8 msgencode.c
--- util/data/msgencode.c 11 Sep 2019 14:13:27 -0000 1.8
+++ util/data/msgencode.c 15 Mar 2020 16:31:04 -0000
@@ -480,7 +480,8 @@ packed_rrset_encode(struct ub_packed_rrs
  sldns_buffer_write(pkt, &key->rk.type, 2);
  sldns_buffer_write(pkt, &key->rk.rrset_class, 2);
  if(data->rr_ttl[j] < timenow)
- sldns_buffer_write_u32(pkt, 0);
+ sldns_buffer_write_u32(pkt,
+ SERVE_EXPIRED?SERVE_EXPIRED_REPLY_TTL:0);
  else sldns_buffer_write_u32(pkt,
  data->rr_ttl[j]-timenow);
  if(c) {
@@ -517,7 +518,8 @@ packed_rrset_encode(struct ub_packed_rrs
  sldns_buffer_write_u16(pkt, LDNS_RR_TYPE_RRSIG);
  sldns_buffer_write(pkt, &key->rk.rrset_class, 2);
  if(data->rr_ttl[i] < timenow)
- sldns_buffer_write_u32(pkt, 0);
+ sldns_buffer_write_u32(pkt,
+ SERVE_EXPIRED?SERVE_EXPIRED_REPLY_TTL:0);
  else sldns_buffer_write_u32(pkt,
  data->rr_ttl[i]-timenow);
  /* rrsig rdata cannot be compressed, perform 100+ byte
Index: util/data/msgparse.h
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/util/data/msgparse.h,v
retrieving revision 1.4
diff -u -p -r1.4 msgparse.h
--- util/data/msgparse.h 20 Sep 2018 23:15:40 -0000 1.4
+++ util/data/msgparse.h 15 Mar 2020 16:31:04 -0000
@@ -79,8 +79,12 @@ extern time_t MAX_TTL;
 extern time_t MIN_TTL;
 /** Maximum Negative TTL that is allowed */
 extern time_t MAX_NEG_TTL;
+/** If we serve expired entries and prefetch them */
+extern int SERVE_EXPIRED;
 /** Time to serve records after expiration */
 extern time_t SERVE_EXPIRED_TTL;
+/** TTL to use for expired records */
+extern time_t SERVE_EXPIRED_REPLY_TTL;
 /** Negative cache time (for entries without any RRs.) */
 #define NORR_TTL 5 /* seconds */
 
Index: util/data/msgreply.c
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/util/data/msgreply.c,v
retrieving revision 1.16
diff -u -p -r1.16 msgreply.c
--- util/data/msgreply.c 18 Dec 2019 11:04:14 -0000 1.16
+++ util/data/msgreply.c 15 Mar 2020 16:31:04 -0000
@@ -61,8 +61,12 @@ time_t MAX_TTL = 3600 * 24 * 10; /* ten
 time_t MIN_TTL = 0;
 /** MAX Negative TTL, for SOA records in authority section */
 time_t MAX_NEG_TTL = 3600; /* one hour */
+/** If we serve expired entries and prefetch them */
+int SERVE_EXPIRED = 0;
 /** Time to serve records after expiration */
 time_t SERVE_EXPIRED_TTL = 0;
+/** TTL to use for expired records */
+time_t SERVE_EXPIRED_REPLY_TTL = 30;
 
 /** allocate qinfo, return 0 on error */
 static int
Index: util/data/packed_rrset.c
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/util/data/packed_rrset.c,v
retrieving revision 1.4
diff -u -p -r1.4 packed_rrset.c
--- util/data/packed_rrset.c 17 Sep 2018 09:46:12 -0000 1.4
+++ util/data/packed_rrset.c 15 Mar 2020 16:31:04 -0000
@@ -40,6 +40,7 @@
  */
 
 #include "config.h"
+#include "util/data/msgparse.h"
 #include "util/data/packed_rrset.h"
 #include "util/data/dname.h"
 #include "util/storage/lookup3.h"
@@ -351,11 +352,11 @@ packed_rrset_copy_region(struct ub_packe
  /* make TTLs relative - once per rrset */
  for(i=0; i<d->count + d->rrsig_count; i++) {
  if(d->rr_ttl[i] < now)
- d->rr_ttl[i] = 0;
+ d->rr_ttl[i] = SERVE_EXPIRED?SERVE_EXPIRED_REPLY_TTL:0;
  else d->rr_ttl[i] -= now;
  }
  if(d->ttl < now)
- d->ttl = 0;
+ d->ttl = SERVE_EXPIRED?SERVE_EXPIRED_REPLY_TTL:0;
  else d->ttl -= now;
  return ck;
 }
@@ -385,4 +386,20 @@ packed_rrset_copy_alloc(struct ub_packed
  dk->entry.data = (void*)dd;
  packed_rrset_ttl_add(dd, now);
  return dk;
+}
+
+int
+packed_rrset_find_rr(struct packed_rrset_data* d, uint8_t* rdata, size_t len,
+ size_t* index)
+{
+ size_t i;
+ for(i=0; i<d->count; i++) {
+ if(d->rr_len[i] != len)
+ continue;
+ if(memcmp(d->rr_data[i], rdata, len) == 0) {
+ *index = i;
+ return 1;
+ }
+ }
+ return 0;
 }
Index: util/data/packed_rrset.h
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/util/data/packed_rrset.h,v
retrieving revision 1.4
diff -u -p -r1.4 packed_rrset.h
--- util/data/packed_rrset.h 17 Sep 2018 09:46:12 -0000 1.4
+++ util/data/packed_rrset.h 15 Mar 2020 16:31:04 -0000
@@ -446,4 +446,17 @@ struct ub_packed_rrset_key* packed_rrset
  struct ub_packed_rrset_key* key, struct alloc_cache* alloc,
  time_t now);
 
+/**
+ * Find RR index in packed rrset
+ * Raw comparison, does not canonicalize RDATA
+ * @param d: packed rrset
+ * @param rdata: RDATA of RR to find
+ * @param len: length of rdata
+ * @param index: pointer to int to store index of found RR
+ * @return 1 if RR found, 0 otherwise
+ */
+int
+packed_rrset_find_rr(struct packed_rrset_data* d, uint8_t* rdata, size_t len,
+ size_t* index);
+
 #endif /* UTIL_DATA_PACKED_RRSET_H */
Index: util/storage/dnstree.c
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/util/storage/dnstree.c,v
retrieving revision 1.2
diff -u -p -r1.2 dnstree.c
--- util/storage/dnstree.c 17 Feb 2017 18:53:32 -0000 1.2
+++ util/storage/dnstree.c 15 Mar 2020 16:31:04 -0000
@@ -104,11 +104,12 @@ int addr_tree_insert(rbtree_type* tree,
  return rbtree_insert(tree, &node->node) != NULL;
 }
 
-void addr_tree_init_parents(rbtree_type* tree)
+void addr_tree_init_parents_node(struct addr_tree_node* node)
 {
-        struct addr_tree_node* node, *prev = NULL, *p;
+ struct addr_tree_node* prev = NULL, *p;
         int m;
-        RBTREE_FOR(node, struct addr_tree_node*, tree) {
+ for(; (rbnode_type*)node != RBTREE_NULL;
+ node = (struct addr_tree_node*)rbtree_next((rbnode_type*)node)) {
                 node->parent = NULL;
                 if(!prev || prev->addrlen != node->addrlen) {
                         prev = node;
@@ -128,6 +129,12 @@ void addr_tree_init_parents(rbtree_type*
                         }
                 prev = node;
         }
+}
+
+void addr_tree_init_parents(rbtree_type* tree)
+{
+ addr_tree_init_parents_node(
+ (struct addr_tree_node*)rbtree_first(tree));
 }
 
 void name_tree_init_parents(rbtree_type* tree)
Index: util/storage/dnstree.h
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/util/storage/dnstree.h,v
retrieving revision 1.2
diff -u -p -r1.2 dnstree.h
--- util/storage/dnstree.h 17 Feb 2017 18:53:32 -0000 1.2
+++ util/storage/dnstree.h 15 Mar 2020 16:31:04 -0000
@@ -174,6 +174,13 @@ int addr_tree_insert(rbtree_type* tree,
 void addr_tree_init_parents(rbtree_type* tree);
 
 /**
+ * Initialize parent pointers in partial addr tree.
+ * Reinitialize pointer for part of tree, used after node deletion
+ * @param node: node to start parent pointer initialization for.
+ */
+void addr_tree_init_parents_node(struct addr_tree_node* node);
+
+/**
  * Lookup closest encloser in addr tree.
  * @param tree: addr tree
  * @param addr: to lookup.
Index: validator/val_secalgo.c
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/validator/val_secalgo.c,v
retrieving revision 1.11
diff -u -p -r1.11 val_secalgo.c
--- validator/val_secalgo.c 18 Dec 2019 11:04:14 -0000 1.11
+++ validator/val_secalgo.c 15 Mar 2020 16:31:04 -0000
@@ -54,6 +54,11 @@
 #error "Need crypto library to do digital signature cryptography"
 #endif
 
+/** fake DSA support for unit tests */
+int fake_dsa = 0;
+/** fake SHA1 support for unit tests */
+int fake_sha1 = 0;
+
 /* OpenSSL implementation */
 #ifdef HAVE_SSL
 #ifdef HAVE_OPENSSL_ERR_H
@@ -72,11 +77,6 @@
 #include <openssl/engine.h>
 #endif
 
-/** fake DSA support for unit tests */
-int fake_dsa = 0;
-/** fake SHA1 support for unit tests */
-int fake_sha1 = 0;
-
 /**
  * Output a libcrypto openssl error to the logfile.
  * @param str: string to add to it.
@@ -1509,13 +1509,21 @@ dnskey_algo_id_is_supported(int id)
 {
  /* uses libnettle */
  switch(id) {
-#if defined(USE_DSA) && defined(USE_SHA1)
  case LDNS_DSA:
  case LDNS_DSA_NSEC3:
+#if defined(USE_DSA) && defined(USE_SHA1)
+ return 1;
+#else
+ if(fake_dsa || fake_sha1) return 1;
+ return 0;
 #endif
-#ifdef USE_SHA1
  case LDNS_RSASHA1:
  case LDNS_RSASHA1_NSEC3:
+#ifdef USE_SHA1
+ return 1;
+#else
+ if(fake_sha1) return 1;
+ return 0;
 #endif
 #ifdef USE_SHA2
  case LDNS_RSASHA256:
@@ -1819,6 +1827,15 @@ verify_canonrrset(sldns_buffer* buf, int
  *reason = "null signature";
  return sec_status_bogus;
  }
+
+#ifndef USE_DSA
+ if((algo == LDNS_DSA || algo == LDNS_DSA_NSEC3) &&(fake_dsa||fake_sha1))
+ return sec_status_secure;
+#endif
+#ifndef USE_SHA1
+ if(fake_sha1 && (algo == LDNS_DSA || algo == LDNS_DSA_NSEC3 || algo == LDNS_RSASHA1 || algo == LDNS_RSASHA1_NSEC3))
+ return sec_status_secure;
+#endif
 
  switch(algo) {
 #if defined(USE_DSA) && defined(USE_SHA1)
Index: validator/validator.c
===================================================================
RCS file: /cvs/src/usr.sbin/unbound/validator/validator.c,v
retrieving revision 1.13
diff -u -p -r1.13 validator.c
--- validator/validator.c 18 Dec 2019 11:04:14 -0000 1.13
+++ validator/validator.c 15 Mar 2020 16:31:04 -0000
@@ -121,6 +121,8 @@ val_apply_cfg(struct module_env* env, st
  log_err("out of memory");
  return 0;
  }
+ if (env->key_cache)
+ val_env->kcache = env->key_cache;
  if(!val_env->kcache)
  val_env->kcache = key_cache_create(cfg);
  if(!val_env->kcache) {
@@ -146,6 +148,8 @@ val_apply_cfg(struct module_env* env, st
  log_err("validator: cannot apply nsec3 key iterations");
  return 0;
  }
+ if (env->neg_cache)
+ val_env->neg_cache = env->neg_cache;
  if(!val_env->neg_cache)
  val_env->neg_cache = val_neg_create(cfg,
  val_env->nsec3_maxiter[val_env->nsec3_keyiter_count-1]);
@@ -196,7 +200,9 @@ val_deinit(struct module_env* env, int i
  anchors_delete(env->anchors);
  env->anchors = NULL;
  key_cache_delete(val_env->kcache);
+ env->key_cache = NULL;
  neg_cache_delete(val_env->neg_cache);
+ env->neg_cache = NULL;
  free(val_env->nsec3_keysize);
  free(val_env->nsec3_maxiter);
  free(val_env);

Reply | Threaded
Open this post in threaded view
|

Re: unbound 1.10.0

Renaud Allard-2


On 15/03/2020 17:36, Stuart Henderson wrote:
> Lots of churn again.. most of the new + are related to the new rpz and
> serve-stale support. I've been running it for a few days with my usual
> setup with no problems, haven't tried the new things yet. Anyone want
> to test?
>

I have had a lot of stalling issues with unbound 1.9.4 being a DoT
server. It went better with 1.9.6, but there are still stalling issues.
I am now trying your patch on 6.6-stable to see if it solves the
stalling issues.


smime.p7s (5K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: unbound 1.10.0

Stuart Henderson
On 2020/03/15 19:05, Renaud Allard wrote:

>
>
> On 15/03/2020 17:36, Stuart Henderson wrote:
> > Lots of churn again.. most of the new + are related to the new rpz and
> > serve-stale support. I've been running it for a few days with my usual
> > setup with no problems, haven't tried the new things yet. Anyone want
> > to test?
> >
>
> I have had a lot of stalling issues with unbound 1.9.4 being a DoT server.
> It went better with 1.9.6, but there are still stalling issues.
> I am now trying your patch on 6.6-stable to see if it solves the stalling
> issues.
>



I would be interested to know if it helps, but I don't think all that
much has changed for DoT in this release so I think it's unlikely.

Honestly I would just put dnsdist in front if you want good DoT (or DoH)
service, it is solid.

Reply | Threaded
Open this post in threaded view
|

Re: unbound 1.10.0

Renaud Allard-2


On 3/15/20 9:53 PM, Stuart Henderson wrote:

> On 2020/03/15 19:05, Renaud Allard wrote:
>>
>>
>> On 15/03/2020 17:36, Stuart Henderson wrote:
>>> Lots of churn again.. most of the new + are related to the new rpz and
>>> serve-stale support. I've been running it for a few days with my usual
>>> setup with no problems, haven't tried the new things yet. Anyone want
>>> to test?
>>>
>>
>> I have had a lot of stalling issues with unbound 1.9.4 being a DoT server.
>> It went better with 1.9.6, but there are still stalling issues.
>> I am now trying your patch on 6.6-stable to see if it solves the stalling
>> issues.
>>
>
>
>
> I would be interested to know if it helps, but I don't think all that
> much has changed for DoT in this release so I think it's unlikely.
>
> Honestly I would just put dnsdist in front if you want good DoT (or DoH)
> service, it is solid.
>
 From my time limited testing of about 15 hours, I got no stall at all
with 1.10.0 on any of the 3 servers tested. Down from at least 10 times
in this kind of timeframe with 1.9.4 and 4-5 with 1.9.6. I think the
problem is more related to tcp sessions themselves than DoT.


smime.p7s (5K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: unbound 1.10.0

Jordan Geoghegan-3


On 2020-03-16 06:01, Renaud Allard wrote:

>
>
> On 3/15/20 9:53 PM, Stuart Henderson wrote:
>> On 2020/03/15 19:05, Renaud Allard wrote:
>>>
>>>
>>> On 15/03/2020 17:36, Stuart Henderson wrote:
>>>> Lots of churn again.. most of the new + are related to the new rpz and
>>>> serve-stale support. I've been running it for a few days with my usual
>>>> setup with no problems, haven't tried the new things yet. Anyone want
>>>> to test?
>>>>
>>>
>>> I have had a lot of stalling issues with unbound 1.9.4 being a DoT
>>> server.
>>> It went better with 1.9.6, but there are still stalling issues.
>>> I am now trying your patch on 6.6-stable to see if it solves the
>>> stalling
>>> issues.
>>>
>>
>>
>>
>> I would be interested to know if it helps, but I don't think all that
>> much has changed for DoT in this release so I think it's unlikely.
>>
>> Honestly I would just put dnsdist in front if you want good DoT (or DoH)
>> service, it is solid.
>>
>
> From my time limited testing of about 15 hours, I got no stall at all
> with 1.10.0 on any of the 3 servers tested. Down from at least 10
> times in this kind of timeframe with 1.9.4 and 4-5 with 1.9.6. I think
> the problem is more related to tcp sessions themselves than DoT.
>
That's good to hear, I've had a number of issues with DoT stalling on
1.9.4 and 1.9.6. I've found having multiple entries in my forwarders
section has somewhat mitigated the issue. I wonder if the stalling
problem is related to this:
https://github.com/NLnetLabs/unbound/issues/47

Reply | Threaded
Open this post in threaded view
|

Re: unbound 1.10.0

Renaud Allard-2


On 3/16/20 10:54 PM, Jordan Geoghegan wrote:
>>
> That's good to hear, I've had a number of issues with DoT stalling on
> 1.9.4 and 1.9.6. I've found having multiple entries in my forwarders
> section has somewhat mitigated the issue. I wonder if the stalling
> problem is related to this:
> https://github.com/NLnetLabs/unbound/issues/47

I was talking about DoT servers, I haven't really noticed any big issue
with DoT forwarding.

That said, I had 2 stalls over the night, so unbound 1.10.0 still
doesn't solve the issue.
Besides, I noticed that the android app "nebulo" wasn't happy with
either 1.9.6 or 1.10.0, but works fine with dnsdist which I am now
trying following sthen@ advise.


smime.p7s (5K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: unbound 1.10.0

Renaud Allard-2
In reply to this post by Stuart Henderson


On 3/15/20 9:53 PM, Stuart Henderson wrote:

> On 2020/03/15 19:05, Renaud Allard wrote:
>>
>>
>> On 15/03/2020 17:36, Stuart Henderson wrote:
>>> Lots of churn again.. most of the new + are related to the new rpz and
>>> serve-stale support. I've been running it for a few days with my usual
>>> setup with no problems, haven't tried the new things yet. Anyone want
>>> to test?
>>>
>>
>> I have had a lot of stalling issues with unbound 1.9.4 being a DoT server.
>> It went better with 1.9.6, but there are still stalling issues.
>> I am now trying your patch on 6.6-stable to see if it solves the stalling
>> issues.
>>
>
>
>
> I would be interested to know if it helps, but I don't think all that
> much has changed for DoT in this release so I think it's unlikely.
>
> Honestly I would just put dnsdist in front if you want good DoT (or DoH)
> service, it is solid.
>
After some days of testing I didn't see any real problem with that diff.
It's working as expected.

Also, I found out that putting "so-reuseport: no" completely stops all
the stalling problems I had with unbound as a DoT server. It might be a
good idea to mention somewhere that in case of problems with TCP
connections, putting that option seems to solve all the TCP stalling.


smime.p7s (5K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: unbound 1.10.0

Stuart Henderson
On 2020/03/19 09:27, Renaud Allard wrote:
>
> After some days of testing I didn't see any real problem with that diff.
> It's working as expected.
>
> Also, I found out that putting "so-reuseport: no" completely stops all the
> stalling problems I had with unbound as a DoT server. It might be a good
> idea to mention somewhere that in case of problems with TCP connections,
> putting that option seems to solve all the TCP stalling.

Yes I think SO_REUSEPORT may have some gotchas on OpenBSD - we had
problems with this and relayd in the past.

Reply | Threaded
Open this post in threaded view
|

Re: unbound 1.10.0

Renaud Allard-2


On 3/19/20 10:36 AM, Stuart Henderson wrote:

> On 2020/03/19 09:27, Renaud Allard wrote:
>>
>> After some days of testing I didn't see any real problem with that diff.
>> It's working as expected.
>>
>> Also, I found out that putting "so-reuseport: no" completely stops all the
>> stalling problems I had with unbound as a DoT server. It might be a good
>> idea to mention somewhere that in case of problems with TCP connections,
>> putting that option seems to solve all the TCP stalling.
>
> Yes I think SO_REUSEPORT may have some gotchas on OpenBSD - we had
> problems with this and relayd in the past.
>
Just to confirm. With unbound 1.10.0 and "so_reuseport:no", I haven't
had a single stall in days on any server.


smime.p7s (5K) Download Attachment