merge conflicts
authorsthen <sthen@openbsd.org>
Mon, 17 Sep 2018 09:46:12 +0000 (09:46 +0000)
committersthen <sthen@openbsd.org>
Mon, 17 Sep 2018 09:46:12 +0000 (09:46 +0000)
82 files changed:
usr.sbin/unbound/Makefile.in
usr.sbin/unbound/cachedb/cachedb.c
usr.sbin/unbound/cachedb/cachedb.h
usr.sbin/unbound/config.h.in
usr.sbin/unbound/configure
usr.sbin/unbound/configure.ac
usr.sbin/unbound/daemon/acl_list.c
usr.sbin/unbound/daemon/acl_list.h
usr.sbin/unbound/daemon/cachedump.c
usr.sbin/unbound/daemon/daemon.c
usr.sbin/unbound/daemon/remote.c
usr.sbin/unbound/daemon/remote.h
usr.sbin/unbound/daemon/stats.c
usr.sbin/unbound/daemon/unbound.c
usr.sbin/unbound/daemon/worker.c
usr.sbin/unbound/doc/Changelog
usr.sbin/unbound/doc/README
usr.sbin/unbound/doc/example.conf.in
usr.sbin/unbound/doc/libunbound.3.in
usr.sbin/unbound/doc/unbound-anchor.8.in
usr.sbin/unbound/doc/unbound-checkconf.8.in
usr.sbin/unbound/doc/unbound-control.8.in
usr.sbin/unbound/doc/unbound-host.1.in
usr.sbin/unbound/doc/unbound.8.in
usr.sbin/unbound/doc/unbound.conf.5.in
usr.sbin/unbound/iterator/iter_delegpt.c
usr.sbin/unbound/iterator/iter_delegpt.h
usr.sbin/unbound/iterator/iter_fwd.c
usr.sbin/unbound/iterator/iter_hints.c
usr.sbin/unbound/iterator/iter_utils.c
usr.sbin/unbound/iterator/iter_utils.h
usr.sbin/unbound/iterator/iterator.c
usr.sbin/unbound/libunbound/context.c
usr.sbin/unbound/libunbound/context.h
usr.sbin/unbound/libunbound/libunbound.c
usr.sbin/unbound/libunbound/libworker.c
usr.sbin/unbound/libunbound/libworker.h
usr.sbin/unbound/libunbound/unbound.h
usr.sbin/unbound/libunbound/worker.h
usr.sbin/unbound/services/authzone.c
usr.sbin/unbound/services/authzone.h
usr.sbin/unbound/services/cache/infra.c
usr.sbin/unbound/services/cache/rrset.c
usr.sbin/unbound/services/listen_dnsport.c
usr.sbin/unbound/services/mesh.c
usr.sbin/unbound/services/outside_network.c
usr.sbin/unbound/services/outside_network.h
usr.sbin/unbound/sldns/keyraw.c
usr.sbin/unbound/sldns/keyraw.h
usr.sbin/unbound/sldns/str2wire.c
usr.sbin/unbound/smallapp/unbound-checkconf.c
usr.sbin/unbound/smallapp/unbound-control.c
usr.sbin/unbound/smallapp/unbound-host.c
usr.sbin/unbound/smallapp/worker_cb.c
usr.sbin/unbound/util/alloc.c
usr.sbin/unbound/util/alloc.h
usr.sbin/unbound/util/config_file.c
usr.sbin/unbound/util/config_file.h
usr.sbin/unbound/util/configlexer.lex
usr.sbin/unbound/util/configparser.y
usr.sbin/unbound/util/data/dname.c
usr.sbin/unbound/util/data/dname.h
usr.sbin/unbound/util/data/msgparse.c
usr.sbin/unbound/util/data/msgreply.c
usr.sbin/unbound/util/data/packed_rrset.c
usr.sbin/unbound/util/data/packed_rrset.h
usr.sbin/unbound/util/fptr_wlist.c
usr.sbin/unbound/util/fptr_wlist.h
usr.sbin/unbound/util/iana_ports.inc
usr.sbin/unbound/util/module.h
usr.sbin/unbound/util/net_help.c
usr.sbin/unbound/util/net_help.h
usr.sbin/unbound/util/netevent.c
usr.sbin/unbound/util/tube.c
usr.sbin/unbound/util/ub_event.c
usr.sbin/unbound/validator/val_anchor.c
usr.sbin/unbound/validator/val_anchor.h
usr.sbin/unbound/validator/val_neg.c
usr.sbin/unbound/validator/val_neg.h
usr.sbin/unbound/validator/val_secalgo.c
usr.sbin/unbound/validator/validator.c
usr.sbin/unbound/validator/validator.h

index 140ddb4..409cce0 100644 (file)
@@ -112,7 +112,7 @@ 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/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\
+util/shm_side/shm_main.c services/authzone.c \
 util/fptr_wlist.c util/locks.c util/log.c util/mini_event.c util/module.c \
 util/netevent.c util/net_help.c util/random.c util/rbtree.c util/regional.c \
 util/rtt.c util/storage/dnstree.c util/storage/lookup3.c \
@@ -124,7 +124,7 @@ validator/val_nsec3.c validator/val_nsec.c validator/val_secalgo.c \
 validator/val_sigcrypt.c validator/val_utils.c dns64/dns64.c \
 edns-subnet/edns-subnet.c edns-subnet/subnetmod.c \
 edns-subnet/addrtree.c edns-subnet/subnet-whitelist.c \
-cachedb/cachedb.c respip/respip.c $(CHECKLOCK_SRC) \
+cachedb/cachedb.c cachedb/redis.c respip/respip.c $(CHECKLOCK_SRC) \
 $(DNSTAP_SRC) $(DNSCRYPT_SRC) $(IPSECMOD_SRC)
 COMMON_OBJ_WITHOUT_NETCALL=dns.lo infra.lo rrset.lo dname.lo msgencode.lo \
 as112.lo msgparse.lo msgreply.lo packed_rrset.lo iterator.lo iter_delegpt.lo \
@@ -135,7 +135,7 @@ fptr_wlist.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 timehist.lo tube.lo winsock_event.lo autotrust.lo val_anchor.lo \
 validator.lo val_kcache.lo val_kentry.lo val_neg.lo val_nsec3.lo val_nsec.lo \
-val_secalgo.lo val_sigcrypt.lo val_utils.lo dns64.lo cachedb.lo authzone.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) \
 $(IPSECMOD_OBJ) respip.lo
 COMMON_OBJ_WITHOUT_UB_EVENT=$(COMMON_OBJ_WITHOUT_NETCALL) netevent.lo listen_dnsport.lo \
@@ -327,7 +327,7 @@ unbound-control$(EXEEXT):   $(CONTROL_OBJ_LINK) libunbound.la
        $(LINK) -o $@ $(CONTROL_OBJ_LINK) $(EXTRALINK) $(SSLLIB) $(LIBS)
 
 unbound-host$(EXEEXT): $(HOST_OBJ_LINK) libunbound.la
-       $(LINK) -o $@ $(HOST_OBJ_LINK) -L. -L.libs -lunbound $(LIBS)
+       $(LINK) -o $@ $(HOST_OBJ_LINK) -L. -L.libs -lunbound $(SSLLIB) $(LIBS)
 
 unbound-anchor$(EXEEXT):       $(UBANCHOR_OBJ_LINK) libunbound.la
        $(LINK) -o $@ $(UBANCHOR_OBJ_LINK) -L. -L.libs -lunbound -lexpat $(SSLLIB) $(LIBS)
@@ -360,7 +360,7 @@ memstats$(EXEEXT):  $(MEMSTATS_OBJ_LINK)
        $(LINK) -o $@ $(MEMSTATS_OBJ_LINK) $(SSLLIB) $(LIBS)
 
 asynclook$(EXEEXT):    $(ASYNCLOOK_OBJ_LINK) libunbound.la
-       $(LINK) -o $@ $(ASYNCLOOK_OBJ_LINK) $(LIBS) -L. -L.libs -lunbound
+       $(LINK) -o $@ $(ASYNCLOOK_OBJ_LINK) -L. -L.libs -lunbound $(SSLLIB) $(LIBS)
 
 streamtcp$(EXEEXT):    $(STREAMTCP_OBJ_LINK)
        $(LINK) -o $@ $(STREAMTCP_OBJ_LINK) $(SSLLIB) $(LIBS)
@@ -629,14 +629,14 @@ depend:
 # Dependencies
 dns.lo dns.o: $(srcdir)/services/cache/dns.c config.h $(srcdir)/iterator/iter_delegpt.h $(srcdir)/util/log.h \
  $(srcdir)/validator/val_nsec.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h \
- $(srcdir)/util/locks.h $(srcdir)/validator/val_utils.h $(srcdir)/sldns/pkthdr.h \
+ $(srcdir)/util/locks.h $(srcdir)/testcode/checklocks.h $(srcdir)/validator/val_utils.h $(srcdir)/sldns/pkthdr.h \
  $(srcdir)/services/cache/dns.h $(srcdir)/util/data/msgreply.h $(srcdir)/services/cache/rrset.h \
  $(srcdir)/util/storage/slabhash.h $(srcdir)/util/data/dname.h $(srcdir)/util/module.h \
  $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/net_help.h $(srcdir)/util/regional.h \
  $(srcdir)/util/config_file.h $(srcdir)/sldns/sbuffer.h
 infra.lo infra.o: $(srcdir)/services/cache/infra.c config.h $(srcdir)/sldns/rrdef.h $(srcdir)/sldns/str2wire.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)/testcode/checklocks.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 \
@@ -644,27 +644,28 @@ infra.lo infra.o: $(srcdir)/services/cache/infra.c config.h $(srcdir)/sldns/rrde
  $(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 \
- $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \
+ $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/testcode/checklocks.h \
  $(srcdir)/util/storage/slabhash.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/sldns/rrdef.h \
- $(srcdir)/util/config_file.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/regional.h $(srcdir)/util/alloc.h
+ $(srcdir)/util/config_file.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/regional.h $(srcdir)/util/alloc.h \
+ $(srcdir)/util/net_help.h
 as112.lo as112.o: $(srcdir)/util/as112.c $(srcdir)/util/as112.h
 dname.lo dname.o: $(srcdir)/util/data/dname.c config.h $(srcdir)/util/data/dname.h \
- $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \
+ $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/testcode/checklocks.h \
  $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/storage/lookup3.h \
  $(srcdir)/sldns/sbuffer.h
 msgencode.lo msgencode.o: $(srcdir)/util/data/msgencode.c config.h $(srcdir)/util/data/msgencode.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/data/msgparse.h \
+ $(srcdir)/testcode/checklocks.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgparse.h \
  $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/data/dname.h $(srcdir)/util/regional.h \
  $(srcdir)/util/net_help.h $(srcdir)/sldns/sbuffer.h $(srcdir)/services/localzone.h $(srcdir)/util/rbtree.h \
  $(srcdir)/util/storage/dnstree.h $(srcdir)/util/module.h $(srcdir)/services/view.h
 msgparse.lo msgparse.o: $(srcdir)/util/data/msgparse.c config.h $(srcdir)/util/data/msgparse.h \
- $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \
+ $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/testcode/checklocks.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)/util/storage/lookup3.h \
  $(srcdir)/util/regional.h $(srcdir)/sldns/sbuffer.h $(srcdir)/sldns/parseutil.h $(srcdir)/sldns/wire2str.h
 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/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/testcode/checklocks.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 \
@@ -673,12 +674,12 @@ msgreply.lo msgreply.o: $(srcdir)/util/data/msgreply.c config.h $(srcdir)/util/d
  $(srcdir)/util/tube.h $(srcdir)/services/mesh.h $(srcdir)/util/rbtree.h $(srcdir)/services/modstack.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)/testcode/checklocks.h $(srcdir)/util/data/dname.h $(srcdir)/util/storage/lookup3.h \
  $(srcdir)/util/alloc.h $(srcdir)/util/regional.h $(srcdir)/util/net_help.h $(srcdir)/sldns/rrdef.h \
  $(srcdir)/sldns/sbuffer.h $(srcdir)/sldns/wire2str.h
 iterator.lo iterator.o: $(srcdir)/iterator/iterator.c config.h $(srcdir)/iterator/iterator.h \
  $(srcdir)/services/outbound_list.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/locks.h $(srcdir)/util/log.h $(srcdir)/testcode/checklocks.h $(srcdir)/util/data/packed_rrset.h \
  $(srcdir)/util/module.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h \
  $(srcdir)/iterator/iter_utils.h $(srcdir)/iterator/iter_resptype.h $(srcdir)/iterator/iter_hints.h \
  $(srcdir)/util/storage/dnstree.h $(srcdir)/util/rbtree.h $(srcdir)/iterator/iter_fwd.h \
@@ -692,7 +693,7 @@ iterator.lo iterator.o: $(srcdir)/iterator/iterator.c config.h $(srcdir)/iterato
  $(srcdir)/sldns/parseutil.h $(srcdir)/sldns/sbuffer.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)/testcode/checklocks.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h \
  $(srcdir)/util/regional.h $(srcdir)/util/data/dname.h $(srcdir)/util/net_help.h $(srcdir)/sldns/rrdef.h \
  $(srcdir)/sldns/sbuffer.h
 iter_donotq.lo iter_donotq.o: $(srcdir)/iterator/iter_donotq.c config.h $(srcdir)/iterator/iter_donotq.h \
@@ -701,25 +702,25 @@ iter_donotq.lo iter_donotq.o: $(srcdir)/iterator/iter_donotq.c config.h $(srcdir
 iter_fwd.lo iter_fwd.o: $(srcdir)/iterator/iter_fwd.c config.h $(srcdir)/iterator/iter_fwd.h \
  $(srcdir)/util/rbtree.h $(srcdir)/iterator/iter_delegpt.h $(srcdir)/util/log.h $(srcdir)/util/config_file.h \
  $(srcdir)/util/net_help.h $(srcdir)/util/data/dname.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h \
- $(srcdir)/sldns/rrdef.h $(srcdir)/sldns/str2wire.h
+ $(srcdir)/testcode/checklocks.h $(srcdir)/sldns/rrdef.h $(srcdir)/sldns/str2wire.h
 iter_hints.lo iter_hints.o: $(srcdir)/iterator/iter_hints.c config.h $(srcdir)/iterator/iter_hints.h \
  $(srcdir)/util/storage/dnstree.h $(srcdir)/util/rbtree.h $(srcdir)/iterator/iter_delegpt.h $(srcdir)/util/log.h \
  $(srcdir)/util/config_file.h $(srcdir)/util/net_help.h $(srcdir)/util/data/dname.h \
- $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/sldns/rrdef.h \
+ $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/testcode/checklocks.h $(srcdir)/sldns/rrdef.h \
  $(srcdir)/sldns/str2wire.h $(srcdir)/sldns/wire2str.h
 iter_priv.lo iter_priv.o: $(srcdir)/iterator/iter_priv.c config.h $(srcdir)/iterator/iter_priv.h \
  $(srcdir)/util/rbtree.h $(srcdir)/util/regional.h $(srcdir)/util/log.h $(srcdir)/util/config_file.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/checklocks.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h \
  $(srcdir)/util/net_help.h $(srcdir)/util/storage/dnstree.h $(srcdir)/sldns/str2wire.h $(srcdir)/sldns/sbuffer.h
 iter_resptype.lo iter_resptype.o: $(srcdir)/iterator/iter_resptype.c config.h \
  $(srcdir)/iterator/iter_resptype.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)/testcode/checklocks.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h \
  $(srcdir)/util/net_help.h $(srcdir)/util/data/dname.h $(srcdir)/sldns/rrdef.h $(srcdir)/sldns/pkthdr.h
 iter_scrub.lo iter_scrub.o: $(srcdir)/iterator/iter_scrub.c config.h $(srcdir)/iterator/iter_scrub.h \
  $(srcdir)/iterator/iterator.h $(srcdir)/services/outbound_list.h $(srcdir)/util/data/msgreply.h \
- $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \
+ $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/testcode/checklocks.h \
  $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/module.h $(srcdir)/util/data/msgparse.h \
  $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/iterator/iter_priv.h $(srcdir)/util/rbtree.h \
  $(srcdir)/services/cache/rrset.h $(srcdir)/util/storage/slabhash.h $(srcdir)/util/net_help.h \
@@ -728,7 +729,7 @@ iter_scrub.lo iter_scrub.o: $(srcdir)/iterator/iter_scrub.c config.h $(srcdir)/i
 iter_utils.lo iter_utils.o: $(srcdir)/iterator/iter_utils.c config.h $(srcdir)/iterator/iter_utils.h \
  $(srcdir)/iterator/iter_resptype.h $(srcdir)/iterator/iterator.h $(srcdir)/services/outbound_list.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/module.h \
+ $(srcdir)/testcode/checklocks.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/module.h \
  $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/iterator/iter_hints.h \
  $(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 \
@@ -743,11 +744,11 @@ iter_utils.lo iter_utils.o: $(srcdir)/iterator/iter_utils.c config.h $(srcdir)/i
 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)/testcode/checklocks.h $(srcdir)/services/outside_network.h $(srcdir)/util/rbtree.h \
   $(srcdir)/util/config_file.h $(srcdir)/util/net_help.h \
  $(srcdir)/sldns/sbuffer.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/rbtree.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/testcode/checklocks.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 \
@@ -757,7 +758,7 @@ localzone.lo localzone.o: $(srcdir)/services/localzone.c config.h $(srcdir)/serv
  $(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)/dnscrypt/cert.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/testcode/checklocks.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/outbound_list.h $(srcdir)/services/cache/dns.h \
@@ -767,7 +768,7 @@ mesh.lo mesh.o: $(srcdir)/services/mesh.c config.h $(srcdir)/services/mesh.h $(s
  $(srcdir)/util/storage/dnstree.h $(srcdir)/services/view.h $(srcdir)/util/data/dname.h $(srcdir)/respip/respip.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)/testcode/checklocks.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 \
@@ -778,18 +779,19 @@ modstack.lo modstack.o: $(srcdir)/services/modstack.c config.h $(srcdir)/service
  $(srcdir)/util/alloc.h $(srcdir)/util/net_help.h $(srcdir)/util/storage/slabhash.h \
  $(srcdir)/edns-subnet/addrtree.h $(srcdir)/edns-subnet/edns-subnet.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/locks.h $(srcdir)/util/log.h $(srcdir)/testcode/checklocks.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
 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
+ $(srcdir)/dnscrypt/cert.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/testcode/checklocks.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)/util/locks.h $(srcdir)/util/log.h $(srcdir)/testcode/checklocks.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)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h \
@@ -798,7 +800,7 @@ outside_network.lo outside_network.o: $(srcdir)/services/outside_network.c confi
  $(srcdir)/services/mesh.h $(srcdir)/services/modstack.h $(srcdir)/sldns/sbuffer.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)/testcode/checklocks.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 \
@@ -807,7 +809,7 @@ alloc.lo alloc.o: $(srcdir)/util/alloc.c config.h $(srcdir)/util/alloc.h $(srcdi
 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)/testcode/checklocks.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 \
@@ -820,7 +822,7 @@ configparser.lo configparser.o: util/configparser.c config.h $(srcdir)/util/conf
  $(srcdir)/util/config_file.h $(srcdir)/util/net_help.h $(srcdir)/util/log.h
 shm_main.lo shm_main.o: $(srcdir)/util/shm_side/shm_main.c config.h $(srcdir)/util/shm_side/shm_main.h \
  $(srcdir)/libunbound/unbound.h $(srcdir)/daemon/daemon.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \
- $(srcdir)/util/alloc.h $(srcdir)/services/modstack.h \
+ $(srcdir)/testcode/checklocks.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 \
@@ -831,7 +833,7 @@ shm_main.lo shm_main.o: $(srcdir)/util/shm_side/shm_main.c config.h $(srcdir)/ut
  $(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
 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)/util/rbtree.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/testcode/checklocks.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 \
@@ -844,7 +846,7 @@ authzone.lo authzone.o: $(srcdir)/services/authzone.c config.h $(srcdir)/service
  $(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)/dnscrypt/cert.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/testcode/checklocks.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 \
@@ -857,42 +859,45 @@ fptr_wlist.lo fptr_wlist.o: $(srcdir)/util/fptr_wlist.c config.h $(srcdir)/util/
  $(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/worker.h $(srcdir)/sldns/sbuffer.h \
- $(srcdir)/util/config_file.h $(srcdir)/respip/respip.h $(PYTHONMOD_HEADER) \
- $(srcdir)/cachedb/cachedb.h $(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
-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
+ $(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)/cachedb/cachedb.h $(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
+locks.lo locks.o: $(srcdir)/util/locks.c config.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \
+ $(srcdir)/testcode/checklocks.h
+log.lo log.o: $(srcdir)/util/log.c config.h $(srcdir)/util/log.h $(srcdir)/util/locks.h $(srcdir)/testcode/checklocks.h \
+ $(srcdir)/sldns/sbuffer.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)/dnscrypt/cert.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \
- $(srcdir)/util/storage/lruhash.h $(srcdir)/util/module.h \
+ $(srcdir)/testcode/checklocks.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
 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/locks.h $(srcdir)/util/log.h $(srcdir)/testcode/checklocks.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/fptr_wlist.h \
+ $(srcdir)/testcode/checklocks.h $(srcdir)/util/ub_event.h $(srcdir)/util/net_help.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)/sldns/sbuffer.h $(srcdir)/dnstap/dnstap.h \
+ $(srcdir)/services/modstack.h $(srcdir)/sldns/sbuffer.h $(srcdir)/sldns/str2wire.h $(srcdir)/dnstap/dnstap.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)/testcode/checklocks.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)/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)/dnscrypt/cert.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/testcode/checklocks.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 \
@@ -901,33 +906,33 @@ regional.lo regional.o: $(srcdir)/util/regional.c config.h $(srcdir)/util/log.h
 rtt.lo rtt.o: $(srcdir)/util/rtt.c config.h $(srcdir)/util/rtt.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
+ $(srcdir)/util/log.h $(srcdir)/testcode/checklocks.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/locks.h $(srcdir)/util/log.h $(srcdir)/testcode/checklocks.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
 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
+ $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/testcode/checklocks.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)/dnscrypt/cert.h $(srcdir)/util/locks.h $(srcdir)/testcode/checklocks.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
 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)/dnscrypt/cert.h $(srcdir)/util/locks.h $(srcdir)/testcode/checklocks.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)/testcode/checklocks.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/mini_event.h \
@@ -935,7 +940,7 @@ ub_event_pluggable.lo ub_event_pluggable.o: $(srcdir)/util/ub_event_pluggable.c
 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 \
- $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/validator/val_anchor.h \
+ $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/testcode/checklocks.h $(srcdir)/validator/val_anchor.h \
  $(srcdir)/validator/val_utils.h $(srcdir)/sldns/pkthdr.h $(srcdir)/validator/val_sigcrypt.h \
  $(srcdir)/util/data/dname.h $(srcdir)/util/module.h $(srcdir)/util/data/msgreply.h \
  $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/net_help.h $(srcdir)/util/config_file.h \
@@ -946,36 +951,36 @@ autotrust.lo autotrust.o: $(srcdir)/validator/autotrust.c config.h $(srcdir)/val
  $(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)/util/rbtree.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/testcode/checklocks.h \
  $(srcdir)/validator/val_sigcrypt.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h \
  $(srcdir)/sldns/pkthdr.h $(srcdir)/validator/autotrust.h $(srcdir)/util/data/dname.h $(srcdir)/util/net_help.h \
  $(srcdir)/util/config_file.h $(srcdir)/util/as112.h $(srcdir)/sldns/sbuffer.h $(srcdir)/sldns/rrdef.h \
  $(srcdir)/sldns/str2wire.h
 validator.lo validator.o: $(srcdir)/validator/validator.c config.h $(srcdir)/validator/validator.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)/testcode/checklocks.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)/validator/val_utils.h \
  $(srcdir)/validator/val_anchor.h $(srcdir)/util/rbtree.h $(srcdir)/validator/val_kcache.h \
  $(srcdir)/util/storage/slabhash.h $(srcdir)/validator/val_kentry.h $(srcdir)/validator/val_nsec.h \
  $(srcdir)/validator/val_nsec3.h $(srcdir)/validator/val_neg.h $(srcdir)/validator/val_sigcrypt.h \
- $(srcdir)/validator/autotrust.h $(srcdir)/services/cache/dns.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)/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
 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)/testcode/checklocks.h $(srcdir)/validator/val_kentry.h $(srcdir)/util/config_file.h \
  $(srcdir)/util/data/dname.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
 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/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/testcode/checklocks.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)/validator/val_neg.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/testcode/checklocks.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 \
@@ -983,7 +988,7 @@ val_neg.lo val_neg.o: $(srcdir)/validator/val_neg.c config.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 \
  $(srcdir)/util/rbtree.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)/util/locks.h $(srcdir)/util/log.h $(srcdir)/testcode/checklocks.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/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/validator/val_utils.h \
  $(srcdir)/validator/val_kentry.h $(srcdir)/services/cache/rrset.h $(srcdir)/util/storage/slabhash.h \
@@ -991,19 +996,19 @@ val_nsec3.lo val_nsec3.o: $(srcdir)/validator/val_nsec3.c config.h $(srcdir)/val
  $(srcdir)/sldns/sbuffer.h
 val_nsec.lo val_nsec.o: $(srcdir)/validator/val_nsec.c config.h $(srcdir)/validator/val_nsec.h \
  $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \
- $(srcdir)/validator/val_utils.h $(srcdir)/sldns/pkthdr.h \
+ $(srcdir)/testcode/checklocks.h $(srcdir)/validator/val_utils.h $(srcdir)/sldns/pkthdr.h \
  $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/dname.h $(srcdir)/util/net_help.h $(srcdir)/util/module.h \
  $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/rrdef.h $(srcdir)/services/cache/rrset.h \
  $(srcdir)/util/storage/slabhash.h
 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)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/testcode/checklocks.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 \
  
 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)/util/locks.h $(srcdir)/util/log.h $(srcdir)/testcode/checklocks.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 \
@@ -1012,7 +1017,7 @@ val_sigcrypt.lo val_sigcrypt.o: $(srcdir)/validator/val_sigcrypt.c config.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)/testcode/checklocks.h $(srcdir)/sldns/pkthdr.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_kentry.h $(srcdir)/validator/val_sigcrypt.h $(srcdir)/validator/val_anchor.h \
  $(srcdir)/util/rbtree.h $(srcdir)/validator/val_nsec.h $(srcdir)/validator/val_neg.h \
@@ -1020,7 +1025,7 @@ val_utils.lo val_utils.o: $(srcdir)/validator/val_utils.c config.h $(srcdir)/val
  $(srcdir)/util/data/dname.h $(srcdir)/util/net_help.h $(srcdir)/util/regional.h $(srcdir)/util/config_file.h \
  $(srcdir)/sldns/wire2str.h $(srcdir)/sldns/parseutil.h
 dns64.lo dns64.o: $(srcdir)/dns64/dns64.c config.h $(srcdir)/dns64/dns64.h $(srcdir)/util/module.h \
- $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \
+ $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/testcode/checklocks.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/cache/dns.h $(srcdir)/services/cache/rrset.h \
  $(srcdir)/util/storage/slabhash.h $(srcdir)/util/config_file.h $(srcdir)/util/fptr_wlist.h \
@@ -1031,7 +1036,7 @@ edns-subnet.lo edns-subnet.o: $(srcdir)/edns-subnet/edns-subnet.c config.h \
  $(srcdir)/edns-subnet/edns-subnet.h $(srcdir)/util/net_help.h $(srcdir)/util/log.h
 subnetmod.lo subnetmod.o: $(srcdir)/edns-subnet/subnetmod.c config.h $(srcdir)/edns-subnet/subnetmod.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)/testcode/checklocks.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/outbound_list.h $(srcdir)/util/alloc.h $(srcdir)/util/net_help.h \
  $(srcdir)/util/storage/slabhash.h $(srcdir)/edns-subnet/addrtree.h $(srcdir)/edns-subnet/edns-subnet.h \
@@ -1041,23 +1046,29 @@ subnetmod.lo subnetmod.o: $(srcdir)/edns-subnet/subnetmod.c config.h $(srcdir)/e
  $(srcdir)/services/cache/dns.h $(srcdir)/util/regional.h $(srcdir)/util/config_file.h $(srcdir)/sldns/sbuffer.h
 addrtree.lo addrtree.o: $(srcdir)/edns-subnet/addrtree.c config.h $(srcdir)/util/log.h \
  $(srcdir)/util/data/msgreply.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h \
- $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/module.h \
+ $(srcdir)/testcode/checklocks.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/module.h \
  $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/edns-subnet/addrtree.h
 subnet-whitelist.lo subnet-whitelist.o: $(srcdir)/edns-subnet/subnet-whitelist.c config.h \
  $(srcdir)/edns-subnet/edns-subnet.h $(srcdir)/util/net_help.h $(srcdir)/util/log.h \
  $(srcdir)/edns-subnet/subnet-whitelist.h $(srcdir)/util/storage/dnstree.h $(srcdir)/util/rbtree.h \
  $(srcdir)/util/regional.h $(srcdir)/util/config_file.h $(srcdir)/sldns/str2wire.h $(srcdir)/sldns/rrdef.h \
- $(srcdir)/util/data/dname.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h
+ $(srcdir)/util/data/dname.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h \
+ $(srcdir)/testcode/checklocks.h
 cachedb.lo cachedb.o: $(srcdir)/cachedb/cachedb.c config.h $(srcdir)/cachedb/cachedb.h $(srcdir)/util/module.h \
- $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \
+ $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/testcode/checklocks.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/net_help.h \
- $(srcdir)/util/config_file.h $(srcdir)/util/data/msgencode.h $(srcdir)/services/cache/dns.h \
- $(srcdir)/validator/val_neg.h $(srcdir)/util/rbtree.h $(srcdir)/validator/val_secalgo.h \
- $(srcdir)/iterator/iter_utils.h $(srcdir)/iterator/iter_resptype.h $(srcdir)/sldns/parseutil.h \
- $(srcdir)/sldns/wire2str.h $(srcdir)/sldns/sbuffer.h
+ $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/cachedb/redis.h $(srcdir)/util/regional.h \
+ $(srcdir)/util/net_help.h $(srcdir)/util/config_file.h $(srcdir)/util/data/msgencode.h \
+ $(srcdir)/services/cache/dns.h $(srcdir)/validator/val_neg.h $(srcdir)/util/rbtree.h \
+ $(srcdir)/validator/val_secalgo.h $(srcdir)/iterator/iter_utils.h $(srcdir)/iterator/iter_resptype.h \
+ $(srcdir)/sldns/parseutil.h $(srcdir)/sldns/wire2str.h $(srcdir)/sldns/sbuffer.h
+redis.lo redis.o: $(srcdir)/cachedb/redis.c config.h $(srcdir)/cachedb/redis.h $(srcdir)/cachedb/cachedb.h \
+ $(srcdir)/util/module.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \
+ $(srcdir)/testcode/checklocks.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/alloc.h \
+ $(srcdir)/util/config_file.h $(srcdir)/sldns/sbuffer.h
 respip.lo respip.o: $(srcdir)/respip/respip.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/locks.h $(srcdir)/util/log.h $(srcdir)/testcode/checklocks.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 \
@@ -1069,11 +1080,11 @@ checklocks.lo checklocks.o: $(srcdir)/testcode/checklocks.c config.h $(srcdir)/u
 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/locks.h $(srcdir)/testcode/checklocks.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 $(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)/testcode/checklocks.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/fptr_wlist.h \
  $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h  \
@@ -1082,25 +1093,25 @@ ipsecmod.lo ipsecmod.o: $(srcdir)/ipsecmod/ipsecmod.c config.h $(srcdir)/ipsecmo
  $(srcdir)/sldns/wire2str.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/log.h $(srcdir)/testcode/checklocks.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
 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)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/testcode/checklocks.h \
  $(srcdir)/testcode/unitmain.h $(srcdir)/validator/val_anchor.h $(srcdir)/util/rbtree.h $(srcdir)/sldns/sbuffer.h \
  $(srcdir)/sldns/rrdef.h
 unitdname.lo unitdname.o: $(srcdir)/testcode/unitdname.c config.h $(srcdir)/util/log.h $(srcdir)/testcode/unitmain.h \
  $(srcdir)/util/data/dname.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h \
- $(srcdir)/sldns/sbuffer.h $(srcdir)/sldns/str2wire.h $(srcdir)/sldns/rrdef.h
+ $(srcdir)/testcode/checklocks.h $(srcdir)/sldns/sbuffer.h $(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/log.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/testcode/checklocks.h \
  $(srcdir)/util/storage/slabhash.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)/testcode/checklocks.h $(srcdir)/util/net_help.h $(srcdir)/util/config_file.h $(srcdir)/util/rtt.h \
  $(srcdir)/util/timehist.h $(srcdir)/libunbound/unbound.h $(srcdir)/services/cache/infra.h \
  $(srcdir)/util/storage/lruhash.h $(srcdir)/util/storage/dnstree.h $(srcdir)/util/rbtree.h \
  $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h  \
@@ -1109,22 +1120,23 @@ unitmain.lo unitmain.o: $(srcdir)/testcode/unitmain.c config.h \
  $(srcdir)/sldns/pkthdr.h $(srcdir)/services/localzone.h $(srcdir)/services/view.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/locks.h $(srcdir)/testcode/checklocks.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/alloc.h $(srcdir)/util/regional.h $(srcdir)/util/net_help.h \
  $(srcdir)/testcode/readhex.h $(srcdir)/testcode/testpkts.h $(srcdir)/sldns/sbuffer.h $(srcdir)/sldns/str2wire.h \
  $(srcdir)/sldns/wire2str.h
 unitneg.lo unitneg.o: $(srcdir)/testcode/unitneg.c config.h $(srcdir)/util/log.h $(srcdir)/util/net_help.h \
  $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h \
- $(srcdir)/util/data/dname.h $(srcdir)/testcode/unitmain.h \
+ $(srcdir)/testcode/checklocks.h $(srcdir)/util/data/dname.h $(srcdir)/testcode/unitmain.h \
  $(srcdir)/validator/val_neg.h $(srcdir)/util/rbtree.h $(srcdir)/sldns/rrdef.h
 unitregional.lo unitregional.o: $(srcdir)/testcode/unitregional.c config.h $(srcdir)/testcode/unitmain.h \
  $(srcdir)/util/log.h $(srcdir)/util/regional.h
 unitslabhash.lo unitslabhash.o: $(srcdir)/testcode/unitslabhash.c config.h $(srcdir)/testcode/unitmain.h \
- $(srcdir)/util/log.h $(srcdir)/util/storage/slabhash.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h
+ $(srcdir)/util/log.h $(srcdir)/util/storage/slabhash.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h \
+ $(srcdir)/testcode/checklocks.h
 unitverify.lo unitverify.o: $(srcdir)/testcode/unitverify.c config.h $(srcdir)/util/log.h \
  $(srcdir)/testcode/unitmain.h $(srcdir)/validator/val_sigcrypt.h $(srcdir)/util/data/packed_rrset.h \
- $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/sldns/pkthdr.h \
+ $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/testcode/checklocks.h $(srcdir)/sldns/pkthdr.h \
  $(srcdir)/validator/val_secalgo.h $(srcdir)/validator/val_nsec.h $(srcdir)/validator/val_nsec3.h \
  $(srcdir)/util/rbtree.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 \
@@ -1139,13 +1151,13 @@ testpkts.lo testpkts.o: $(srcdir)/testcode/testpkts.c config.h $(srcdir)/testcod
 unitldns.lo unitldns.o: $(srcdir)/testcode/unitldns.c config.h $(srcdir)/util/log.h $(srcdir)/testcode/unitmain.h \
  $(srcdir)/sldns/sbuffer.h $(srcdir)/sldns/str2wire.h $(srcdir)/sldns/rrdef.h $(srcdir)/sldns/wire2str.h
 unitecs.lo unitecs.o: $(srcdir)/testcode/unitecs.c config.h $(srcdir)/util/log.h $(srcdir)/util/module.h \
- $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h \
+ $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/testcode/checklocks.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)/testcode/unitmain.h $(srcdir)/edns-subnet/addrtree.h \
  $(srcdir)/edns-subnet/subnetmod.h $(srcdir)/services/outbound_list.h $(srcdir)/util/alloc.h \
  $(srcdir)/util/net_help.h $(srcdir)/util/storage/slabhash.h $(srcdir)/edns-subnet/edns-subnet.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)/util/rbtree.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/testcode/checklocks.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 \
@@ -1154,14 +1166,14 @@ unitauth.lo unitauth.o: $(srcdir)/testcode/unitauth.c config.h $(srcdir)/service
  $(srcdir)/sldns/str2wire.h $(srcdir)/sldns/wire2str.h $(srcdir)/sldns/sbuffer.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/log.h $(srcdir)/testcode/checklocks.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)/util/locks.h $(srcdir)/util/log.h $(srcdir)/testcode/checklocks.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 \
@@ -1173,7 +1185,7 @@ cachedump.lo cachedump.o: $(srcdir)/daemon/cachedump.c config.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)/daemon/daemon.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/testcode/checklocks.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 \
@@ -1191,7 +1203,7 @@ 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)/testcode/checklocks.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 \
@@ -1200,16 +1212,16 @@ remote.lo remote.o: $(srcdir)/daemon/remote.c config.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)/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 $(srcdir)/iterator/iter_fwd.h $(srcdir)/iterator/iter_hints.h \
- $(srcdir)/iterator/iter_delegpt.h $(srcdir)/services/outside_network.h $(srcdir)/sldns/str2wire.h \
- $(srcdir)/sldns/parseutil.h $(srcdir)/sldns/wire2str.h
+ $(srcdir)/services/view.h $(srcdir)/services/authzone.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 $(srcdir)/iterator/iter_fwd.h \
+ $(srcdir)/iterator/iter_hints.h $(srcdir)/iterator/iter_delegpt.h $(srcdir)/services/outside_network.h \
+ $(srcdir)/sldns/str2wire.h $(srcdir)/sldns/parseutil.h $(srcdir)/sldns/wire2str.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)/testcode/checklocks.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 \
@@ -1218,9 +1230,10 @@ stats.lo stats.o: $(srcdir)/daemon/stats.c config.h $(srcdir)/daemon/stats.h $(s
  $(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)/validator/val_kcache.h
+ $(srcdir)/util/rtt.h $(srcdir)/services/authzone.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)/util/locks.h $(srcdir)/testcode/checklocks.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 \
@@ -1232,7 +1245,7 @@ unbound.lo unbound.o: $(srcdir)/daemon/unbound.c config.h $(srcdir)/util/log.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)/testcode/checklocks.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 \
@@ -1246,12 +1259,12 @@ worker.lo worker.o: $(srcdir)/daemon/worker.c config.h $(srcdir)/util/log.h $(sr
  $(srcdir)/services/localzone.h $(srcdir)/util/data/msgencode.h $(srcdir)/util/data/dname.h \
  $(srcdir)/util/fptr_wlist.h $(srcdir)/util/tube.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/libworker.h $(srcdir)/sldns/wire2str.h \
- $(srcdir)/util/shm_side/shm_main.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)/testcode/checklocks.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  \
@@ -1266,7 +1279,7 @@ testpkts.lo testpkts.o: $(srcdir)/testcode/testpkts.c config.h $(srcdir)/testcod
 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)/testcode/checklocks.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 \
@@ -1280,16 +1293,16 @@ worker.lo worker.o: $(srcdir)/daemon/worker.c config.h $(srcdir)/util/log.h $(sr
  $(srcdir)/services/localzone.h $(srcdir)/util/data/msgencode.h $(srcdir)/util/data/dname.h \
  $(srcdir)/util/fptr_wlist.h $(srcdir)/util/tube.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/libworker.h $(srcdir)/sldns/wire2str.h \
- $(srcdir)/util/shm_side/shm_main.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/log.h $(srcdir)/testcode/checklocks.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)/daemon/daemon.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/testcode/checklocks.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 \
@@ -1306,7 +1319,7 @@ daemon.lo daemon.o: $(srcdir)/daemon/daemon.c config.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)/testcode/checklocks.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 \
@@ -1315,15 +1328,16 @@ stats.lo stats.o: $(srcdir)/daemon/stats.c config.h $(srcdir)/daemon/stats.h $(s
  $(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)/validator/val_kcache.h
+ $(srcdir)/util/rtt.h $(srcdir)/services/authzone.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/checklocks.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)/dnscrypt/cert.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/testcode/checklocks.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 \
@@ -1333,26 +1347,26 @@ fake_event.lo fake_event.o: $(srcdir)/testcode/fake_event.c config.h $(srcdir)/t
  $(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
 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)/util/locks.h $(srcdir)/testcode/checklocks.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
 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/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/testcode/checklocks.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 $(srcdir)/sldns/parseutil.h
 readhex.lo readhex.o: $(srcdir)/testcode/readhex.c config.h $(srcdir)/testcode/readhex.h $(srcdir)/util/log.h \
  $(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)/util/locks.h $(srcdir)/testcode/checklocks.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
 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)/testcode/checklocks.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/net_help.h \
  $(srcdir)/util/regional.h $(srcdir)/iterator/iterator.h $(srcdir)/services/outbound_list.h \
  $(srcdir)/iterator/iter_fwd.h $(srcdir)/util/rbtree.h $(srcdir)/iterator/iter_hints.h \
@@ -1362,26 +1376,26 @@ unbound-checkconf.lo unbound-checkconf.o: $(srcdir)/smallapp/unbound-checkconf.c
  $(srcdir)/dnscrypt/cert.h $(srcdir)/services/modstack.h $(srcdir)/respip/respip.h $(srcdir)/sldns/sbuffer.h \
  $(PYTHONMOD_HEADER) $(srcdir)/edns-subnet/subnet-whitelist.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)/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)/util/locks.h $(srcdir)/util/log.h $(srcdir)/testcode/checklocks.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
 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)/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)/util/locks.h $(srcdir)/util/log.h $(srcdir)/testcode/checklocks.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
 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)/util/log.h $(srcdir)/testcode/checklocks.h $(srcdir)/util/alloc.h $(srcdir)/util/rbtree.h \
  $(srcdir)/services/modstack.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h \
  $(srcdir)/libunbound/libworker.h $(srcdir)/util/config_file.h $(srcdir)/util/module.h \
  $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h \
@@ -1393,9 +1407,9 @@ libunbound.lo libunbound.o: $(srcdir)/libunbound/libunbound.c $(srcdir)/libunbou
  $(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/locks.h $(srcdir)/util/log.h $(srcdir)/testcode/checklocks.h $(srcdir)/libunbound/context.h \
  $(srcdir)/util/alloc.h $(srcdir)/util/rbtree.h $(srcdir)/services/modstack.h $(srcdir)/libunbound/unbound.h \
- $(srcdir)/libunbound/worker.h $(srcdir)/sldns/sbuffer.h $(srcdir)/libunbound/unbound-event.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 \
@@ -1407,26 +1421,29 @@ libworker.lo libworker.o: $(srcdir)/libunbound/libworker.c config.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)/util/data/packed_rrset.h \
- $(srcdir)/util/storage/lruhash.h $(srcdir)/sldns/rrdef.h
+ $(srcdir)/libunbound/context.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/testcode/checklocks.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 \
 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)/testcode/checklocks.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 \
  
 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)/testcode/checklocks.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/log.h $(srcdir)/util/config_file.h $(srcdir)/util/locks.h $(srcdir)/testcode/checklocks.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-anchor.lo unbound-anchor.o: $(srcdir)/smallapp/unbound-anchor.c config.h $(srcdir)/libunbound/unbound.h \
@@ -1435,7 +1452,7 @@ unbound-anchor.lo unbound-anchor.o: $(srcdir)/smallapp/unbound-anchor.c config.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/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/testcode/checklocks.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 \
@@ -1443,7 +1460,7 @@ pythonmod_utils.lo pythonmod_utils.o: $(srcdir)/pythonmod/pythonmod_utils.c conf
  $(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)/daemon/daemon.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/testcode/checklocks.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 \
@@ -1451,7 +1468,7 @@ win_svc.lo win_svc.o: $(srcdir)/winrc/win_svc.c config.h $(srcdir)/winrc/win_svc
  $(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/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
@@ -1473,7 +1490,8 @@ parseutil.lo parseutil.o: $(srcdir)/sldns/parseutil.c config.h $(srcdir)/sldns/p
 rrdef.lo rrdef.o: $(srcdir)/sldns/rrdef.c config.h $(srcdir)/sldns/rrdef.h $(srcdir)/sldns/parseutil.h
 str2wire.lo str2wire.o: $(srcdir)/sldns/str2wire.c config.h $(srcdir)/sldns/str2wire.h $(srcdir)/sldns/rrdef.h \
  $(srcdir)/sldns/wire2str.h $(srcdir)/sldns/sbuffer.h $(srcdir)/sldns/parse.h $(srcdir)/sldns/parseutil.h
-ctime_r.lo ctime_r.o: $(srcdir)/compat/ctime_r.c config.h $(srcdir)/util/locks.h $(srcdir)/util/log.h
+ctime_r.lo ctime_r.o: $(srcdir)/compat/ctime_r.c config.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \
+ $(srcdir)/testcode/checklocks.h
 fake-rfc2553.lo fake-rfc2553.o: $(srcdir)/compat/fake-rfc2553.c $(srcdir)/compat/fake-rfc2553.h config.h
 gmtime_r.lo gmtime_r.o: $(srcdir)/compat/gmtime_r.c config.h
 inet_aton.lo inet_aton.o: $(srcdir)/compat/inet_aton.c config.h
index 80bdc38..a6a609d 100644 (file)
@@ -43,6 +43,7 @@
 #include "config.h"
 #ifdef USE_CACHEDB
 #include "cachedb/cachedb.h"
+#include "cachedb/redis.h"
 #include "util/regional.h"
 #include "util/net_help.h"
 #include "util/config_file.h"
 #include "sldns/wire2str.h"
 #include "sldns/sbuffer.h"
 
-#define CACHEDB_HASHSIZE 256 /* bit hash */
+/* header file for htobe64 */
+#ifdef HAVE_ENDIAN_H
+#  include <endian.h>
+#endif
+#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
 
 /** the unit test testframe for cachedb, its module state contains
  * a cache for a couple queries (in memory). */
@@ -176,6 +190,10 @@ static struct cachedb_backend testframe_backend = { "testframe",
 static struct cachedb_backend*
 cachedb_find_backend(const char* str)
 {
+#ifdef USE_REDIS
+       if(strcmp(str, redis_backend.name) == 0)
+               return &redis_backend;
+#endif
        if(strcmp(str, testframe_backend.name) == 0)
                return &testframe_backend;
        /* TODO add more backends here */
@@ -571,7 +589,8 @@ cachedb_intcache_lookup(struct module_qstate* qstate)
                qstate->region, qstate->env->scratch,
                1 /* no partial messages with only a CNAME */
                );
-       if(!msg && qstate->env->neg_cache) {
+       if(!msg && qstate->env->neg_cache &&
+               iter_qname_indicates_dnssec(qstate->env, &qstate->qinfo)) {
                /* lookup in negative cache; may result in 
                 * NOERROR/NODATA or NXDOMAIN answers that need validation */
                msg = val_neg_getmsg(qstate->env->neg_cache, &qstate->qinfo,
index d477e90..27187dc 100644 (file)
@@ -87,6 +87,8 @@ struct cachedb_backend {
                uint8_t*, size_t);
 };
 
+#define CACHEDB_HASHSIZE 256 /* bit hash */
+
 /** Init the cachedb module */
 int cachedb_init(struct module_env* env, int id);
 /** Deinit the cachedb module */
index e740560..04356f3 100644 (file)
@@ -30,6 +30,9 @@
    internal symbols */
 #undef EXPORT_ALL_SYMBOLS
 
+/* Define to 1 if you have the `accept4' function. */
+#undef HAVE_ACCEPT4
+
 /* Define to 1 if you have the `arc4random' function. */
 #undef HAVE_ARC4RANDOM
 
    don't. */
 #undef HAVE_DECL_NID_ED25519
 
+/* Define to 1 if you have the declaration of `NID_ED448', and to 0 if you
+   don't. */
+#undef HAVE_DECL_NID_ED448
+
 /* Define to 1 if you have the declaration of `NID_secp384r1', and to 0 if you
    don't. */
 #undef HAVE_DECL_NID_SECP384R1
    don't. */
 #undef HAVE_DECL_REALLOCARRAY
 
+/* Define to 1 if you have the declaration of `redisConnect', and to 0 if you
+   don't. */
+#undef HAVE_DECL_REDISCONNECT
+
 /* Define to 1 if you have the declaration of `sk_SSL_COMP_pop_free', and to 0
    if you don't. */
 #undef HAVE_DECL_SK_SSL_COMP_POP_FREE
 /* Define to 1 if you have the <grp.h> header file. */
 #undef HAVE_GRP_H
 
+/* Define to 1 if you have the <hiredis/hiredis.h> header file. */
+#undef HAVE_HIREDIS_HIREDIS_H
+
 /* If you have HMAC_Update */
 #undef HAVE_HMAC_UPDATE
 
 /* Define to 1 if you have the `kill' function. */
 #undef HAVE_KILL
 
+/* Define to 1 if you have the <libkern/OSByteOrder.h> header file. */
+#undef HAVE_LIBKERN_OSBYTEORDER_H
+
 /* Define if we have LibreSSL */
 #undef HAVE_LIBRESSL
 
 /* Define to 1 if systemd should be used */
 #undef HAVE_SYSTEMD
 
+/* Define to 1 if you have the <sys/endian.h> header file. */
+#undef HAVE_SYS_ENDIAN_H
+
 /* Define to 1 if you have the <sys/ipc.h> header file. */
 #undef HAVE_SYS_IPC_H
 
 /* Define this to enable ED25519 support. */
 #undef USE_ED25519
 
+/* Define this to enable ED448 support. */
+#undef USE_ED448
+
 /* Define this to enable GOST support. */
 #undef USE_GOST
 
 /* Define this to enable client TCP Fast Open. */
 #undef USE_OSX_MSG_FASTOPEN
 
+/* Define this to use hiredis client. */
+#undef USE_REDIS
+
 /* Define this to enable SHA1 support. */
 #undef USE_SHA1
 
@@ -1222,6 +1248,8 @@ void *unbound_stat_realloc_log(void *ptr, size_t size, const char* file,
 
 /** default port for DNS traffic. */
 #define UNBOUND_DNS_PORT 53
+/** default port for DNS over TLS traffic. */
+#define UNBOUND_DNS_OVER_TLS_PORT 853
 /** default port for unbound control traffic, registered port with IANA,
     ub-dns-control  8953/tcp    unbound dns nameserver control */
 #define UNBOUND_CONTROL_PORT 8953
index 8581e6e..cf54a87 100644 (file)
@@ -1,6 +1,6 @@
 #! /bin/sh
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for unbound 1.7.0.
+# Generated by GNU Autoconf 2.69 for unbound 1.7.3.
 #
 # Report bugs to <unbound-bugs@nlnetlabs.nl>.
 #
@@ -590,8 +590,8 @@ MAKEFLAGS=
 # Identity of this package.
 PACKAGE_NAME='unbound'
 PACKAGE_TARNAME='unbound'
-PACKAGE_VERSION='1.7.0'
-PACKAGE_STRING='unbound 1.7.0'
+PACKAGE_VERSION='1.7.3'
+PACKAGE_STRING='unbound 1.7.3'
 PACKAGE_BUGREPORT='unbound-bugs@nlnetlabs.nl'
 PACKAGE_URL=''
 
@@ -859,11 +859,13 @@ enable_gost
 enable_ecdsa
 enable_dsa
 enable_ed25519
+enable_ed448
 enable_event_api
 enable_tfo_client
 enable_tfo_server
 with_libevent
 with_libexpat
+with_libhiredis
 enable_static_exe
 enable_systemd
 enable_lock_checks
@@ -1438,7 +1440,7 @@ if test "$ac_init_help" = "long"; then
   # Omit some internal or obsolete options to make the list less imposing.
   # This message is too long to be a string in the A/UX 3.1 sh.
   cat <<_ACEOF
-\`configure' configures unbound 1.7.0 to adapt to many kinds of systems.
+\`configure' configures unbound 1.7.3 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1503,7 +1505,7 @@ fi
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of unbound 1.7.0:";;
+     short | recursive ) echo "Configuration of unbound 1.7.3:";;
    esac
   cat <<\_ACEOF
 
@@ -1544,6 +1546,7 @@ Optional Features:
   --disable-ecdsa         Disable ECDSA support
   --disable-dsa           Disable DSA support
   --disable-ed25519       Disable ED25519 support
+  --disable-ed448         Disable ED448 support
   --enable-event-api      Enable (experimental) pluggable event base
                           libunbound API installed to unbound-event.h
   --enable-tfo-client     Enable TCP Fast Open for client mode
@@ -1610,6 +1613,7 @@ Optional Packages:
                           an explicit path). Slower, but allows use of large
                           outgoing port ranges.
   --with-libexpat=path    specify explicit path for libexpat.
+  --with-libhiredis=path  specify explicit path for libhiredis.
   --with-dnstap-socket-path=pathname
                           set default dnstap socket path
   --with-protobuf-c=path  Path where protobuf-c is installed, for dnstap
@@ -1718,7 +1722,7 @@ fi
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-unbound configure 1.7.0
+unbound configure 1.7.3
 generated by GNU Autoconf 2.69
 
 Copyright (C) 2012 Free Software Foundation, Inc.
@@ -2427,7 +2431,7 @@ cat >config.log <<_ACEOF
 This file contains any messages produced by compilers while
 running configure, to aid debugging if configure makes a mistake.
 
-It was created by unbound $as_me 1.7.0, which was
+It was created by unbound $as_me 1.7.3, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   $ $0 $@
@@ -2779,11 +2783,11 @@ UNBOUND_VERSION_MAJOR=1
 
 UNBOUND_VERSION_MINOR=7
 
-UNBOUND_VERSION_MICRO=0
+UNBOUND_VERSION_MICRO=3
 
 
 LIBUNBOUND_CURRENT=7
-LIBUNBOUND_REVISION=7
+LIBUNBOUND_REVISION=11
 LIBUNBOUND_AGE=5
 # 1.0.0 had 0:12:0
 # 1.0.1 had 0:13:0
@@ -2843,6 +2847,9 @@ LIBUNBOUND_AGE=5
 # 1.6.7 had 7:6:5
 # 1.6.8 had 7:7:5
 # 1.7.0 had 7:8:5
+# 1.7.1 had 7:9:5
+# 1.7.2 had 7:10:5
+# 1.7.3 had 7:11:5
 
 #   Current  -- the number of the binary API that we're implementing
 #   Revision -- which iteration of the implementation of the binary
@@ -14477,7 +14484,7 @@ CC=$lt_save_CC
 
 
 # Checks for header files.
-for ac_header in stdarg.h stdbool.h netinet/in.h netinet/tcp.h sys/param.h sys/socket.h sys/un.h sys/uio.h sys/resource.h arpa/inet.h syslog.h netdb.h sys/wait.h pwd.h glob.h grp.h login_cap.h winsock2.h ws2tcpip.h endian.h sys/ipc.h sys/shm.h
+for ac_header in stdarg.h stdbool.h netinet/in.h netinet/tcp.h sys/param.h sys/socket.h sys/un.h sys/uio.h sys/resource.h arpa/inet.h syslog.h netdb.h sys/wait.h pwd.h glob.h grp.h login_cap.h winsock2.h ws2tcpip.h endian.h sys/endian.h libkern/OSByteOrder.h sys/ipc.h sys/shm.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
@@ -18314,6 +18321,50 @@ _ACEOF
       ;;
 esac
 
+# Check whether --enable-ed448 was given.
+if test "${enable_ed448+set}" = set; then :
+  enableval=$enable_ed448;
+fi
+
+use_ed448="no"
+case "$enable_ed448" in
+    no)
+      ;;
+    *)
+      if test $USE_NSS = "no" -a $USE_NETTLE = "no"; then
+             ac_fn_c_check_decl "$LINENO" "NID_ED448" "ac_cv_have_decl_NID_ED448" "$ac_includes_default
+#include <openssl/evp.h>
+
+"
+if test "x$ac_cv_have_decl_NID_ED448" = xyes; then :
+  ac_have_decl=1
+else
+  ac_have_decl=0
+fi
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_DECL_NID_ED448 $ac_have_decl
+_ACEOF
+if test $ac_have_decl = 1; then :
+
+               use_ed448="yes"
+
+else
+   if test "x$enable_ed448" = "xyes"; then as_fn_error $? "OpenSSL does not support ED448 and you used --enable-ed448." "$LINENO" 5
+               fi
+fi
+
+      fi
+      if test $use_ed448 = "yes"; then
+
+cat >>confdefs.h <<_ACEOF
+#define USE_ED448 1
+_ACEOF
+
+      fi
+      ;;
+esac
+
 # Check whether --enable-event-api was given.
 if test "${enable_event_api+set}" = set; then :
   enableval=$enable_event_api;
@@ -18810,6 +18861,70 @@ cat >>confdefs.h <<_ACEOF
 _ACEOF
 
 
+# hiredis (redis C client for cachedb)
+
+# Check whether --with-libhiredis was given.
+if test "${with_libhiredis+set}" = set; then :
+  withval=$with_libhiredis;
+else
+   withval="no"
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for libhiredis" >&5
+$as_echo_n "checking for libhiredis... " >&6; }
+found_libhiredis="no"
+if test x_$withval = x_yes -o x_$withval != x_no; then
+   if test x_$withval = x_ -o x_$withval = x_yes; then
+            withval="/usr/local /opt/local /usr/lib /usr/pkg /usr/sfw /usr"
+   fi
+   for dir in $withval ; do
+            if test -f "$dir/include/hiredis/hiredis.h"; then
+               found_libhiredis="yes"
+                               if test "$dir" != "/usr"; then
+                    CPPFLAGS="$CPPFLAGS -I$dir/include"
+                   LDFLAGS="$LDFLAGS -L$dir/lib"
+               fi
+               { $as_echo "$as_me:${as_lineno-$LINENO}: result: found in $dir" >&5
+$as_echo "found in $dir" >&6; }
+
+$as_echo "#define USE_REDIS 1" >>confdefs.h
+
+               LIBS="$LIBS -lhiredis"
+                break;
+            fi
+    done
+    if test x_$found_libhiredis != x_yes; then
+       as_fn_error $? "Could not find libhiredis, hiredis.h" "$LINENO" 5
+    fi
+    for ac_header in hiredis/hiredis.h
+do :
+  ac_fn_c_check_header_compile "$LINENO" "hiredis/hiredis.h" "ac_cv_header_hiredis_hiredis_h" "$ac_includes_default
+"
+if test "x$ac_cv_header_hiredis_hiredis_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_HIREDIS_HIREDIS_H 1
+_ACEOF
+
+fi
+
+done
+
+    ac_fn_c_check_decl "$LINENO" "redisConnect" "ac_cv_have_decl_redisConnect" "$ac_includes_default
+    #include <hiredis/hiredis.h>
+
+"
+if test "x$ac_cv_have_decl_redisConnect" = xyes; then :
+  ac_have_decl=1
+else
+  ac_have_decl=0
+fi
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_DECL_REDISCONNECT $ac_have_decl
+_ACEOF
+
+fi
+
 # set static linking if requested
 
 staticexe=""
@@ -19354,7 +19469,7 @@ else
   WINDRES="$ac_cv_prog_WINDRES"
 fi
 
-       LIBS="$LIBS -liphlpapi"
+       LIBS="$LIBS -liphlpapi -lcrypt32"
        WINAPPS="unbound-service-install.exe unbound-service-remove.exe anchor-update.exe"
 
        WIN_DAEMON_SRC="winrc/win_svc.c winrc/w_inst.c"
@@ -19588,7 +19703,7 @@ if test "$ac_res" != no; then :
 
 fi
 
-for ac_func in 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
+for ac_func in 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
 do :
   as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
 ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
@@ -19648,7 +19763,7 @@ done
 
 
 # check if setreuid en setregid fail, on MacOSX10.4(darwin8).
-if echo $build_os | grep darwin8 > /dev/null; then
+if echo $target_os | grep darwin8 > /dev/null; then
 
 $as_echo "#define DARWIN_BROKEN_SETREUID 1" >>confdefs.h
 
@@ -20741,6 +20856,8 @@ if test "${enable_cachedb+set}" = set; then :
   enableval=$enable_cachedb;
 fi
 
+# turn on cachedb when hiredis support is enabled.
+if test "$found_libhiredis" = "yes"; then enable_cachedb="yes"; fi
 case "$enable_cachedb" in
     yes)
 
@@ -20928,7 +21045,7 @@ _ACEOF
 
 
 
-version=1.7.0
+version=1.7.3
 
 date=`date +'%b %e, %Y'`
 
@@ -21447,7 +21564,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
 # report actual input values of CONFIG_FILES etc. instead of their
 # values after options handling.
 ac_log="
-This file was extended by unbound $as_me 1.7.0, which was
+This file was extended by unbound $as_me 1.7.3, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -21513,7 +21630,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.7.0
+unbound config.status 1.7.3
 configured by $0, generated by GNU Autoconf 2.69,
   with options \\"\$ac_cs_config\\"
 
index a5e16eb..685dcb3 100644 (file)
@@ -11,14 +11,14 @@ sinclude(dnscrypt/dnscrypt.m4)
 # must be numbers. ac_defun because of later processing
 m4_define([VERSION_MAJOR],[1])
 m4_define([VERSION_MINOR],[7])
-m4_define([VERSION_MICRO],[0])
+m4_define([VERSION_MICRO],[3])
 AC_INIT(unbound, m4_defn([VERSION_MAJOR]).m4_defn([VERSION_MINOR]).m4_defn([VERSION_MICRO]), unbound-bugs@nlnetlabs.nl, unbound)
 AC_SUBST(UNBOUND_VERSION_MAJOR, [VERSION_MAJOR])
 AC_SUBST(UNBOUND_VERSION_MINOR, [VERSION_MINOR])
 AC_SUBST(UNBOUND_VERSION_MICRO, [VERSION_MICRO])
 
 LIBUNBOUND_CURRENT=7
-LIBUNBOUND_REVISION=7
+LIBUNBOUND_REVISION=11
 LIBUNBOUND_AGE=5
 # 1.0.0 had 0:12:0
 # 1.0.1 had 0:13:0
@@ -78,6 +78,9 @@ LIBUNBOUND_AGE=5
 # 1.6.7 had 7:6:5
 # 1.6.8 had 7:7:5
 # 1.7.0 had 7:8:5
+# 1.7.1 had 7:9:5
+# 1.7.2 had 7:10:5
+# 1.7.3 had 7:11:5
 
 #   Current  -- the number of the binary API that we're implementing
 #   Revision -- which iteration of the implementation of the binary
@@ -331,7 +334,7 @@ AC_CHECK_TOOL(STRIP, strip)
 ACX_LIBTOOL_C_ONLY
 
 # Checks for header files.
-AC_CHECK_HEADERS([stdarg.h stdbool.h netinet/in.h netinet/tcp.h sys/param.h sys/socket.h sys/un.h sys/uio.h sys/resource.h arpa/inet.h syslog.h netdb.h sys/wait.h pwd.h glob.h grp.h login_cap.h winsock2.h ws2tcpip.h endian.h sys/ipc.h sys/shm.h],,, [AC_INCLUDES_DEFAULT])
+AC_CHECK_HEADERS([stdarg.h stdbool.h netinet/in.h netinet/tcp.h sys/param.h sys/socket.h sys/un.h sys/uio.h sys/resource.h arpa/inet.h syslog.h netdb.h sys/wait.h pwd.h glob.h grp.h login_cap.h winsock2.h ws2tcpip.h endian.h sys/endian.h libkern/OSByteOrder.h sys/ipc.h sys/shm.h],,, [AC_INCLUDES_DEFAULT])
 
 # check for types.  
 # Using own tests for int64* because autoconf builtin only give 32bit.
@@ -992,6 +995,26 @@ case "$enable_ed25519" in
       ;;
 esac
 
+AC_ARG_ENABLE(ed448, AC_HELP_STRING([--disable-ed448], [Disable ED448 support]))
+use_ed448="no"
+case "$enable_ed448" in
+    no)
+      ;;
+    *)
+      if test $USE_NSS = "no" -a $USE_NETTLE = "no"; then
+             AC_CHECK_DECLS([NID_ED448], [
+               use_ed448="yes"
+             ], [ if test "x$enable_ed448" = "xyes"; then AC_MSG_ERROR([OpenSSL does not support ED448 and you used --enable-ed448.])
+               fi ], [AC_INCLUDES_DEFAULT
+#include <openssl/evp.h>
+             ])
+      fi
+      if test $use_ed448 = "yes"; then
+               AC_DEFINE_UNQUOTED([USE_ED448], [1], [Define this to enable ED448 support.])
+      fi
+      ;;
+esac
+
 AC_ARG_ENABLE(event-api, AC_HELP_STRING([--enable-event-api], [Enable (experimental) pluggable event base libunbound API installed to unbound-event.h]))
 case "$enable_event_api" in
     yes)
@@ -1150,6 +1173,39 @@ AC_CHECK_DECLS([XML_StopParser], [], [], [AC_INCLUDES_DEFAULT
 #include <expat.h>
 ])
 
+# hiredis (redis C client for cachedb)
+AC_ARG_WITH(libhiredis, AC_HELP_STRING([--with-libhiredis=path],
+    [specify explicit path for libhiredis.]),
+    [ ],[ withval="no" ])
+AC_MSG_CHECKING(for libhiredis)
+found_libhiredis="no"
+if test x_$withval = x_yes -o x_$withval != x_no; then
+   if test x_$withval = x_ -o x_$withval = x_yes; then
+            withval="/usr/local /opt/local /usr/lib /usr/pkg /usr/sfw /usr"
+   fi
+   for dir in $withval ; do
+            if test -f "$dir/include/hiredis/hiredis.h"; then
+               found_libhiredis="yes"
+               dnl assume /usr is in default path.
+               if test "$dir" != "/usr"; then
+                    CPPFLAGS="$CPPFLAGS -I$dir/include"
+                   LDFLAGS="$LDFLAGS -L$dir/lib"
+               fi
+               AC_MSG_RESULT(found in $dir)
+               AC_DEFINE([USE_REDIS], [1], [Define this to use hiredis client.])
+               LIBS="$LIBS -lhiredis"
+                break;
+            fi
+    done
+    if test x_$found_libhiredis != x_yes; then
+       AC_ERROR([Could not find libhiredis, hiredis.h])
+    fi
+    AC_CHECK_HEADERS([hiredis/hiredis.h],,, [AC_INCLUDES_DEFAULT])
+    AC_CHECK_DECLS([redisConnect], [], [], [AC_INCLUDES_DEFAULT
+    #include <hiredis/hiredis.h>
+    ])
+fi
+
 # set static linking if requested
 AC_SUBST(staticexe)
 staticexe=""
@@ -1191,7 +1247,7 @@ if test "$USE_WINSOCK" = 1; then
 #include <windows.h>
        ])
        AC_CHECK_TOOL(WINDRES, windres)
-       LIBS="$LIBS -liphlpapi"
+       LIBS="$LIBS -liphlpapi -lcrypt32"
        WINAPPS="unbound-service-install.exe unbound-service-remove.exe anchor-update.exe"
        AC_SUBST(WINAPPS)
        WIN_DAEMON_SRC="winrc/win_svc.c winrc/w_inst.c"
@@ -1264,12 +1320,12 @@ AC_INCLUDES_DEFAULT
 #endif
 ])
 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])
+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])])
 AC_CHECK_FUNCS([setresgid],,[AC_CHECK_FUNCS([setregid])])
 
 # check if setreuid en setregid fail, on MacOSX10.4(darwin8).
-if echo $build_os | grep darwin8 > /dev/null; then
+if echo $target_os | grep darwin8 > /dev/null; then
        AC_DEFINE(DARWIN_BROKEN_SETREUID, 1, [Define this if on macOSX10.4-darwin8 and setreuid and setregid do not work])
 fi
 AC_CHECK_DECLS([inet_pton,inet_ntop], [], [], [
@@ -1434,6 +1490,8 @@ dnsc_DNSCRYPT([
 
 # check for cachedb if requested
 AC_ARG_ENABLE(cachedb, AC_HELP_STRING([--enable-cachedb], [enable cachedb module that can use external cache storage]))
+# turn on cachedb when hiredis support is enabled.
+if test "$found_libhiredis" = "yes"; then enable_cachedb="yes"; fi
 case "$enable_cachedb" in
     yes)
        AC_DEFINE([USE_CACHEDB], [1], [Define to 1 to use cachedb support])
@@ -1752,6 +1810,8 @@ void *unbound_stat_realloc_log(void *ptr, size_t size, const char* file,
 
 /** default port for DNS traffic. */
 #define UNBOUND_DNS_PORT 53
+/** default port for DNS over TLS traffic. */
+#define UNBOUND_DNS_OVER_TLS_PORT 853
 /** default port for unbound control traffic, registered port with IANA,
     ub-dns-control  8953/tcp    unbound dns nameserver control */
 #define UNBOUND_CONTROL_PORT 8953
index f7d71b9..c16a920 100644 (file)
@@ -111,6 +111,8 @@ acl_list_str_cfg(struct acl_list* acl, const char* str, const char* s2,
                control = acl_refuse_non_local;
        else if(strcmp(s2, "allow_snoop") == 0)
                control = acl_allow_snoop;
+       else if(strcmp(s2, "allow_setrd") == 0)
+               control = acl_allow_setrd;
        else {
                log_err("access control type %s unknown", str);
                return 0;
index d0d42bf..3a3b94b 100644 (file)
@@ -63,7 +63,9 @@ enum acl_access {
        /** allow full access for recursion (+RD) queries */
        acl_allow,
        /** allow full access for all queries, recursion and cache snooping */
-       acl_allow_snoop
+       acl_allow_snoop,
+       /** allow full access for recursion queries and set RD flag regardless of request */
+       acl_allow_setrd
 };
 
 /**
index 8106187..5a72e9d 100644 (file)
@@ -62,7 +62,7 @@
 
 /** dump one rrset zonefile line */
 static int
-dump_rrset_line(SSL* ssl, struct ub_packed_rrset_key* k, time_t now, size_t i)
+dump_rrset_line(RES* ssl, struct ub_packed_rrset_key* k, time_t now, size_t i)
 {
        char s[65535];
        if(!packed_rr_to_string(k, i, now, s, sizeof(s))) {
@@ -73,7 +73,7 @@ dump_rrset_line(SSL* ssl, struct ub_packed_rrset_key* k, time_t now, size_t i)
 
 /** dump rrset key and data info */
 static int
-dump_rrset(SSL* ssl, struct ub_packed_rrset_key* k, 
+dump_rrset(RES* ssl, struct ub_packed_rrset_key* k, 
        struct packed_rrset_data* d, time_t now)
 {
        size_t i;
@@ -99,7 +99,7 @@ dump_rrset(SSL* ssl, struct ub_packed_rrset_key* k,
 
 /** dump lruhash rrset cache */
 static int
-dump_rrset_lruhash(SSL* ssl, struct lruhash* h, time_t now)
+dump_rrset_lruhash(RES* ssl, struct lruhash* h, time_t now)
 {
        struct lruhash_entry* e;
        /* lruhash already locked by caller */
@@ -118,7 +118,7 @@ dump_rrset_lruhash(SSL* ssl, struct lruhash* h, time_t now)
 
 /** dump rrset cache */
 static int
-dump_rrset_cache(SSL* ssl, struct worker* worker)
+dump_rrset_cache(RES* ssl, struct worker* worker)
 {
        struct rrset_cache* r = worker->env.rrset_cache;
        size_t slab;
@@ -137,7 +137,7 @@ dump_rrset_cache(SSL* ssl, struct worker* worker)
 
 /** dump message to rrset reference */
 static int
-dump_msg_ref(SSL* ssl, struct ub_packed_rrset_key* k)
+dump_msg_ref(RES* ssl, struct ub_packed_rrset_key* k)
 {
        char* nm, *tp, *cl;
        nm = sldns_wire2str_dname(k->rk.dname, k->rk.dname_len);
@@ -164,7 +164,7 @@ dump_msg_ref(SSL* ssl, struct ub_packed_rrset_key* k)
 
 /** dump message entry */
 static int
-dump_msg(SSL* ssl, struct query_info* k, struct reply_info* d, 
+dump_msg(RES* ssl, struct query_info* k, struct reply_info* d, 
        time_t now)
 {
        size_t i;
@@ -246,7 +246,7 @@ copy_msg(struct regional* region, struct lruhash_entry* e,
 
 /** dump lruhash msg cache */
 static int
-dump_msg_lruhash(SSL* ssl, struct worker* worker, struct lruhash* h)
+dump_msg_lruhash(RES* ssl, struct worker* worker, struct lruhash* h)
 {
        struct lruhash_entry* e;
        struct query_info* k;
@@ -274,7 +274,7 @@ dump_msg_lruhash(SSL* ssl, struct worker* worker, struct lruhash* h)
 
 /** dump msg cache */
 static int
-dump_msg_cache(SSL* ssl, struct worker* worker)
+dump_msg_cache(RES* ssl, struct worker* worker)
 {
        struct slabhash* sh = worker->env.msg_cache;
        size_t slab;
@@ -291,7 +291,7 @@ dump_msg_cache(SSL* ssl, struct worker* worker)
 }
 
 int
-dump_cache(SSL* ssl, struct worker* worker)
+dump_cache(RES* ssl, struct worker* worker)
 {
        if(!dump_rrset_cache(ssl, worker))
                return 0;
@@ -302,7 +302,7 @@ dump_cache(SSL* ssl, struct worker* worker)
 
 /** read a line from ssl into buffer */
 static int
-ssl_read_buf(SSL* ssl, sldns_buffer* buf)
+ssl_read_buf(RES* ssl, sldns_buffer* buf)
 {
        return ssl_read_line(ssl, (char*)sldns_buffer_begin(buf), 
                sldns_buffer_capacity(buf));
@@ -310,7 +310,7 @@ ssl_read_buf(SSL* ssl, sldns_buffer* buf)
 
 /** check fixed text on line */
 static int
-read_fixed(SSL* ssl, sldns_buffer* buf, const char* str)
+read_fixed(RES* ssl, sldns_buffer* buf, const char* str)
 {
        if(!ssl_read_buf(ssl, buf)) return 0;
        return (strcmp((char*)sldns_buffer_begin(buf), str) == 0);
@@ -318,7 +318,7 @@ read_fixed(SSL* ssl, sldns_buffer* buf, const char* str)
 
 /** load an RR into rrset */
 static int
-load_rr(SSL* ssl, sldns_buffer* buf, struct regional* region,
+load_rr(RES* ssl, sldns_buffer* buf, struct regional* region,
        struct ub_packed_rrset_key* rk, struct packed_rrset_data* d,
        unsigned int i, int is_rrsig, int* go_on, time_t now)
 {
@@ -435,7 +435,7 @@ move_into_cache(struct ub_packed_rrset_key* k,
 
 /** load an rrset entry */
 static int
-load_rrset(SSL* ssl, sldns_buffer* buf, struct worker* worker)
+load_rrset(RES* ssl, sldns_buffer* buf, struct worker* worker)
 {
        char* s = (char*)sldns_buffer_begin(buf);
        struct regional* region = worker->scratchpad;
@@ -519,7 +519,7 @@ load_rrset(SSL* ssl, sldns_buffer* buf, struct worker* worker)
 
 /** load rrset cache */
 static int
-load_rrset_cache(SSL* ssl, struct worker* worker)
+load_rrset_cache(RES* ssl, struct worker* worker)
 {
        sldns_buffer* buf = worker->env.scratch_buffer;
        if(!read_fixed(ssl, buf, "START_RRSET_CACHE")) return 0;
@@ -575,7 +575,7 @@ load_qinfo(char* str, struct query_info* qinfo, struct regional* region)
 
 /** load a msg rrset reference */
 static int
-load_ref(SSL* ssl, sldns_buffer* buf, struct worker* worker, 
+load_ref(RES* ssl, sldns_buffer* buf, struct worker* worker, 
        struct regional *region, struct ub_packed_rrset_key** rrset, 
        int* go_on)
 {
@@ -620,7 +620,7 @@ load_ref(SSL* ssl, sldns_buffer* buf, struct worker* worker,
 
 /** load a msg entry */
 static int
-load_msg(SSL* ssl, sldns_buffer* buf, struct worker* worker)
+load_msg(RES* ssl, sldns_buffer* buf, struct worker* worker)
 {
        struct regional* region = worker->scratchpad;
        struct query_info qinf;
@@ -685,7 +685,7 @@ load_msg(SSL* ssl, sldns_buffer* buf, struct worker* worker)
 
 /** load msg cache */
 static int
-load_msg_cache(SSL* ssl, struct worker* worker)
+load_msg_cache(RES* ssl, struct worker* worker)
 {
        sldns_buffer* buf = worker->env.scratch_buffer;
        if(!read_fixed(ssl, buf, "START_MSG_CACHE")) return 0;
@@ -698,7 +698,7 @@ load_msg_cache(SSL* ssl, struct worker* worker)
 }
 
 int
-load_cache(SSL* ssl, struct worker* worker)
+load_cache(RES* ssl, struct worker* worker)
 {
        if(!load_rrset_cache(ssl, worker))
                return 0;
@@ -709,7 +709,7 @@ load_cache(SSL* ssl, struct worker* worker)
 
 /** print details on a delegation point */
 static void
-print_dp_details(SSL* ssl, struct worker* worker, struct delegpt* dp)
+print_dp_details(RES* ssl, struct worker* worker, struct delegpt* dp)
 {
        char buf[257];
        struct delegpt_addr* a;
@@ -785,7 +785,7 @@ print_dp_details(SSL* ssl, struct worker* worker, struct delegpt* dp)
 
 /** print main dp info */
 static void
-print_dp_main(SSL* ssl, struct delegpt* dp, struct dns_msg* msg)
+print_dp_main(RES* ssl, struct delegpt* dp, struct dns_msg* msg)
 {
        size_t i, n_ns, n_miss, n_addr, n_res, n_avail;
 
@@ -813,7 +813,7 @@ print_dp_main(SSL* ssl, struct delegpt* dp, struct dns_msg* msg)
                return;
 }
 
-int print_deleg_lookup(SSL* ssl, struct worker* worker, uint8_t* nm,
+int print_deleg_lookup(RES* ssl, struct worker* worker, uint8_t* nm,
        size_t nmlen, int ATTR_UNUSED(nmlabs))
 {
        /* deep links into the iterator module */
index f68bd98..6820e11 100644 (file)
@@ -704,11 +704,14 @@ daemon_cleanup(struct daemon* daemon)
        free(daemon->workers);
        daemon->workers = NULL;
        daemon->num = 0;
+       alloc_clear_special(&daemon->superalloc);
 #ifdef USE_DNSTAP
        dt_delete(daemon->dtenv);
+       daemon->dtenv = NULL;
 #endif
 #ifdef USE_DNSCRYPT
        dnsc_delete(daemon->dnscenv);
+       daemon->dnscenv = NULL;
 #endif
        daemon->cfg = NULL;
 }
index 3477340..011c55e 100644 (file)
@@ -68,6 +68,7 @@
 #include "services/cache/infra.h"
 #include "services/mesh.h"
 #include "services/localzone.h"
+#include "services/authzone.h"
 #include "util/storage/slabhash.h"
 #include "util/fptr_wlist.h"
 #include "util/data/dname.h"
@@ -141,125 +142,20 @@ timeval_divide(struct timeval* avg, const struct timeval* sum, long long d)
 #endif
 }
 
-/*
- * The following function was generated using the openssl utility, using
- * the command : "openssl dhparam -C 2048"
- * (some openssl versions reject DH that is 'too small', eg. 512).
- */
-#if OPENSSL_VERSION_NUMBER < 0x10100000 || defined(HAVE_LIBRESSL)
-#ifndef S_SPLINT_S
-static DH *get_dh2048(void)
-{
-       static unsigned char dh2048_p[]={
-               0xE7,0x36,0x28,0x3B,0xE4,0xC3,0x32,0x1C,0x01,0xC3,0x67,0xD6,
-               0xF5,0xF3,0xDA,0xDC,0x71,0xC0,0x42,0x8B,0xE6,0xEB,0x8D,0x80,
-               0x35,0x7F,0x09,0x45,0x30,0xE5,0xB2,0x92,0x81,0x3F,0x08,0xCD,
-               0x36,0x5E,0x19,0x83,0x62,0xCC,0xAE,0x9B,0x81,0x66,0x24,0xEE,
-               0x16,0x6F,0xA9,0x9E,0xF4,0x82,0x1B,0xDD,0x46,0xC7,0x33,0x5D,
-               0xF4,0xCA,0xE6,0x8F,0xFC,0xD4,0xD8,0x58,0x94,0x24,0x5D,0xFF,
-               0x0A,0xE8,0xEF,0x3D,0xCE,0xBB,0x50,0x94,0xE0,0x5F,0xE8,0x41,
-               0xC3,0x35,0x30,0x37,0xD5,0xCB,0x8F,0x3D,0x95,0x15,0x1A,0x77,
-               0x42,0xB2,0x06,0x86,0xF6,0x09,0x66,0x0E,0x9A,0x25,0x94,0x3E,
-               0xD2,0x04,0x25,0x25,0x1D,0x23,0xEB,0xDC,0x4D,0x0C,0x83,0x28,
-               0x2E,0x15,0x81,0x2D,0xC1,0xAF,0x8D,0x36,0x64,0xE3,0x9A,0x83,
-               0x78,0xC2,0x8D,0xC0,0x9D,0xD9,0x3A,0x1C,0xC5,0x2B,0x50,0x68,
-               0x07,0xA9,0x4B,0x8C,0x07,0x57,0xD6,0x15,0x03,0x4E,0x9E,0x01,
-               0xF2,0x6F,0x35,0xAC,0x26,0x9C,0x92,0x68,0x61,0x13,0xFB,0x01,
-               0xBA,0x22,0x36,0x01,0x55,0xB6,0x62,0xD9,0xB2,0x98,0xCE,0x5D,
-               0x4B,0xA5,0x41,0xD6,0xE5,0x70,0x78,0x12,0x1F,0x64,0xB6,0x6F,
-               0xB0,0x91,0x51,0x91,0x92,0xC0,0x94,0x3A,0xD1,0x28,0x4D,0x30,
-               0x84,0x3E,0xE4,0xE4,0x7F,0x47,0x89,0xB1,0xB6,0x8C,0x8E,0x0E,
-               0x26,0xDB,0xCD,0x17,0x07,0x2A,0x21,0x7A,0xCC,0x68,0xE8,0x57,
-               0x94,0x9E,0x59,0x61,0xEC,0x20,0x34,0x26,0x0D,0x66,0x44,0xEB,
-               0x6F,0x02,0x58,0xE2,0xED,0xF6,0xF3,0x1B,0xBF,0x9E,0x45,0x52,
-               0x5A,0x49,0xA1,0x5B,
-               };
-       static unsigned char dh2048_g[]={
-               0x02,
-               };
-       DH *dh = NULL;
-       BIGNUM *p = NULL, *g = NULL;
-
-       dh = DH_new();
-       p = BN_bin2bn(dh2048_p, sizeof(dh2048_p), NULL);
-       g = BN_bin2bn(dh2048_g, sizeof(dh2048_g), NULL);
-       if (!dh || !p || !g)
-               goto err;
-
-#if OPENSSL_VERSION_NUMBER < 0x10100000 || defined(HAVE_LIBRESSL)
-       dh->p = p;
-       dh->g = g;
-#else
-       if (!DH_set0_pqg(dh, p, NULL, g))
-               goto err;
-#endif
-       return dh;
-err:
-       if (p)
-               BN_free(p);
-       if (g)
-               BN_free(g);
-       if (dh)
-               DH_free(dh);
-       return NULL;
-}
-#endif /* SPLINT */
-#endif /* OPENSSL_VERSION_NUMBER < 0x10100000 */
-
-struct daemon_remote*
-daemon_remote_create(struct config_file* cfg)
+static int
+remote_setup_ctx(struct daemon_remote* rc, struct config_file* cfg)
 {
        char* s_cert;
        char* s_key;
-       struct daemon_remote* rc = (struct daemon_remote*)calloc(1, 
-               sizeof(*rc));
-       if(!rc) {
-               log_err("out of memory in daemon_remote_create");
-               return NULL;
-       }
-       rc->max_active = 10;
-
-       if(!cfg->remote_control_enable) {
-               rc->ctx = NULL;
-               return rc;
-       }
        rc->ctx = SSL_CTX_new(SSLv23_server_method());
        if(!rc->ctx) {
                log_crypto_err("could not SSL_CTX_new");
-               free(rc);
-               return NULL;
+               return 0;
        }
        if(!listen_sslctx_setup(rc->ctx)) {
-               daemon_remote_delete(rc);
-               return NULL;
+               return 0;
        }
 
-       if (cfg->remote_control_use_cert == 0) {
-               /* No certificates are requested */
-#ifdef HAVE_SSL_CTX_SET_SECURITY_LEVEL
-               SSL_CTX_set_security_level(rc->ctx, 0);
-#endif
-               if(!SSL_CTX_set_cipher_list(rc->ctx, "aNULL, eNULL")) {
-                       log_crypto_err("Failed to set aNULL cipher list");
-                       daemon_remote_delete(rc);
-                       return NULL;
-               }
-
-               /* in openssl 1.1, the securitylevel 0 allows eNULL, that
-                * does not need the DH */
-#if OPENSSL_VERSION_NUMBER < 0x10100000 || defined(HAVE_LIBRESSL)
-               /* Since we have no certificates and hence no source of
-                * DH params, let's generate and set them
-                */
-               if(!SSL_CTX_set_tmp_dh(rc->ctx,get_dh2048())) {
-                       log_crypto_err("Wanted to set DH param, but failed");
-                       daemon_remote_delete(rc);
-                       return NULL;
-               }
-#endif
-               return rc;
-       }
-       rc->use_cert = 1;
        s_cert = fname_after_chroot(cfg->server_cert_file, cfg, 1);
        s_key = fname_after_chroot(cfg->server_key_file, cfg, 1);
        if(!s_cert || !s_key) {
@@ -288,14 +184,46 @@ daemon_remote_create(struct config_file* cfg)
        setup_error:
                free(s_cert);
                free(s_key);
-               daemon_remote_delete(rc);
-               return NULL;
+               return 0;
        }
        SSL_CTX_set_client_CA_list(rc->ctx, SSL_load_client_CA_file(s_cert));
        SSL_CTX_set_verify(rc->ctx, SSL_VERIFY_PEER, NULL);
        free(s_cert);
        free(s_key);
+       return 1;
+}
+
+struct daemon_remote*
+daemon_remote_create(struct config_file* cfg)
+{
+       struct daemon_remote* rc = (struct daemon_remote*)calloc(1, 
+               sizeof(*rc));
+       if(!rc) {
+               log_err("out of memory in daemon_remote_create");
+               return NULL;
+       }
+       rc->max_active = 10;
 
+       if(!cfg->remote_control_enable) {
+               rc->ctx = NULL;
+               return rc;
+       }
+       if(options_remote_is_address(cfg) && cfg->control_use_cert) {
+               if(!remote_setup_ctx(rc, cfg)) {
+                       daemon_remote_delete(rc);
+                       return NULL;
+               }
+               rc->use_cert = 1;
+       } else {
+               struct config_strlist* p;
+               rc->ctx = NULL;
+               rc->use_cert = 0;
+               if(!options_remote_is_address(cfg))
+                 for(p = cfg->control_ifs.first; p; p = p->next) {
+                       if(p->str && p->str[0] != '/')
+                               log_warn("control-interface %s is not using TLS, but plain transfer, because first control-interface in config file is a local socket (starts with a /).", p->str);
+               }
+       }
        return rc;
 }
 
@@ -436,9 +364,9 @@ struct listen_port* daemon_remote_open_ports(struct config_file* cfg)
 {
        struct listen_port* l = NULL;
        log_assert(cfg->remote_control_enable && cfg->control_port);
-       if(cfg->control_ifs) {
+       if(cfg->control_ifs.first) {
                struct config_strlist* p;
-               for(p = cfg->control_ifs; p; p = p->next) {
+               for(p = cfg->control_ifs.first; p; p = p->next) {
                        if(!add_open(p->str, cfg->control_port, &l, 1, cfg)) {
                                listening_ports_free(l);
                                return NULL;
@@ -545,6 +473,7 @@ int remote_accept_callback(struct comm_point* c, void* arg, int err,
                log_err("out of memory");
                goto close_exit;
        }
+       n->fd = newfd;
        /* start in reading state */
        n->c = comm_point_create_raw(rc->worker->base, newfd, 0, 
                &remote_control_callback, n);
@@ -559,22 +488,26 @@ int remote_accept_callback(struct comm_point* c, void* arg, int err,
        comm_point_start_listening(n->c, -1, REMOTE_CONTROL_TCP_TIMEOUT);
        memcpy(&n->c->repinfo.addr, &addr, addrlen);
        n->c->repinfo.addrlen = addrlen;
-       n->shake_state = rc_hs_read;
-       n->ssl = SSL_new(rc->ctx);
-       if(!n->ssl) {
-               log_crypto_err("could not SSL_new");
-               comm_point_delete(n->c);
-               free(n);
-               goto close_exit;
-       }
-       SSL_set_accept_state(n->ssl);
-        (void)SSL_set_mode(n->ssl, SSL_MODE_AUTO_RETRY);
-       if(!SSL_set_fd(n->ssl, newfd)) {
-               log_crypto_err("could not SSL_set_fd");
-               SSL_free(n->ssl);
-               comm_point_delete(n->c);
-               free(n);
-               goto close_exit;
+       if(rc->use_cert) {
+               n->shake_state = rc_hs_read;
+               n->ssl = SSL_new(rc->ctx);
+               if(!n->ssl) {
+                       log_crypto_err("could not SSL_new");
+                       comm_point_delete(n->c);
+                       free(n);
+                       goto close_exit;
+               }
+               SSL_set_accept_state(n->ssl);
+               (void)SSL_set_mode(n->ssl, SSL_MODE_AUTO_RETRY);
+               if(!SSL_set_fd(n->ssl, newfd)) {
+                       log_crypto_err("could not SSL_set_fd");
+                       SSL_free(n->ssl);
+                       comm_point_delete(n->c);
+                       free(n);
+                       goto close_exit;
+               }
+       } else {
+               n->ssl = NULL;
        }
 
        n->rc = rc;
@@ -616,27 +549,45 @@ clean_point(struct daemon_remote* rc, struct rc_state* s)
 }
 
 int
-ssl_print_text(SSL* ssl, const char* text)
+ssl_print_text(RES* res, const char* text)
 {
        int r;
-       if(!ssl
+       if(!res
                return 0;
-       ERR_clear_error();
-       if((r=SSL_write(ssl, text, (int)strlen(text))) <= 0) {
-               if(SSL_get_error(ssl, r) == SSL_ERROR_ZERO_RETURN) {
-                       verbose(VERB_QUERY, "warning, in SSL_write, peer "
-                               "closed connection");
+       if(res->ssl) {
+               ERR_clear_error();
+               if((r=SSL_write(res->ssl, text, (int)strlen(text))) <= 0) {
+                       if(SSL_get_error(res->ssl, r) == SSL_ERROR_ZERO_RETURN) {
+                               verbose(VERB_QUERY, "warning, in SSL_write, peer "
+                                       "closed connection");
+                               return 0;
+                       }
+                       log_crypto_err("could not SSL_write");
                        return 0;
                }
-               log_crypto_err("could not SSL_write");
-               return 0;
+       } else {
+               size_t at = 0;
+               while(at < strlen(text)) {
+                       ssize_t r = send(res->fd, text+at, strlen(text)-at, 0);
+                       if(r == -1) {
+                               if(errno == EAGAIN || errno == EINTR)
+                                       continue;
+#ifndef USE_WINSOCK
+                               log_err("could not send: %s", strerror(errno));
+#else
+                               log_err("could not send: %s", wsa_strerror(WSAGetLastError()));
+#endif
+                               return 0;
+                       }
+                       at += r;
+               }
        }
        return 1;
 }
 
 /** print text over the ssl connection */
 static int
-ssl_print_vmsg(SSL* ssl, const char* format, va_list args)
+ssl_print_vmsg(RES* ssl, const char* format, va_list args)
 {
        char msg[1024];
        vsnprintf(msg, sizeof(msg), format, args);
@@ -644,7 +595,7 @@ ssl_print_vmsg(SSL* ssl, const char* format, va_list args)
 }
 
 /** printf style printing to the ssl connection */
-int ssl_printf(SSL* ssl, const char* format, ...)
+int ssl_printf(RES* ssl, const char* format, ...)
 {
        va_list args;
        int ret;
@@ -655,21 +606,42 @@ int ssl_printf(SSL* ssl, const char* format, ...)
 }
 
 int
-ssl_read_line(SSL* ssl, char* buf, size_t max)
+ssl_read_line(RES* res, char* buf, size_t max)
 {
        int r;
        size_t len = 0;
-       if(!ssl)
+       if(!res)
                return 0;
        while(len < max) {
-               ERR_clear_error();
-               if((r=SSL_read(ssl, buf+len, 1)) <= 0) {
-                       if(SSL_get_error(ssl, r) == SSL_ERROR_ZERO_RETURN) {
-                               buf[len] = 0;
-                               return 1;
+               if(res->ssl) {
+                       ERR_clear_error();
+                       if((r=SSL_read(res->ssl, buf+len, 1)) <= 0) {
+                               if(SSL_get_error(res->ssl, r) == SSL_ERROR_ZERO_RETURN) {
+                                       buf[len] = 0;
+                                       return 1;
+                               }
+                               log_crypto_err("could not SSL_read");
+                               return 0;
+                       }
+               } else {
+                       while(1) {
+                               ssize_t rr = recv(res->fd, buf+len, 1, 0);
+                               if(rr <= 0) {
+                                       if(rr == 0) {
+                                               buf[len] = 0;
+                                               return 1;
+                                       }
+                                       if(errno == EINTR || errno == EAGAIN)
+                                               continue;
+#ifndef USE_WINSOCK
+                                       log_err("could not recv: %s", strerror(errno));
+#else
+                                       log_err("could not recv: %s", wsa_strerror(WSAGetLastError()));
+#endif
+                                       return 0;
+                               }
+                               break;
                        }
-                       log_crypto_err("could not SSL_read");
-                       return 0;
                }
                if(buf[len] == '\n') {
                        /* return string without \n */
@@ -694,14 +666,14 @@ skipwhite(char* str)
 }
 
 /** send the OK to the control client */
-static void send_ok(SSL* ssl)
+static void send_ok(RES* ssl)
 {
        (void)ssl_printf(ssl, "ok\n");
 }
 
 /** do the stop command */
 static void
-do_stop(SSL* ssl, struct daemon_remote* rc)
+do_stop(RES* ssl, struct daemon_remote* rc)
 {
        rc->worker->need_to_exit = 1;
        comm_base_exit(rc->worker->base);
@@ -710,7 +682,7 @@ do_stop(SSL* ssl, struct daemon_remote* rc)
 
 /** do the reload command */
 static void
-do_reload(SSL* ssl, struct daemon_remote* rc)
+do_reload(RES* ssl, struct daemon_remote* rc)
 {
        rc->worker->need_to_exit = 0;
        comm_base_exit(rc->worker->base);
@@ -719,7 +691,7 @@ do_reload(SSL* ssl, struct daemon_remote* rc)
 
 /** do the verbosity command */
 static void
-do_verbosity(SSL* ssl, char* str)
+do_verbosity(RES* ssl, char* str)
 {
        int val = atoi(str);
        if(val == 0 && strcmp(str, "0") != 0) {
@@ -732,7 +704,7 @@ do_verbosity(SSL* ssl, char* str)
 
 /** print stats from statinfo */
 static int
-print_stats(SSL* ssl, const char* nm, struct ub_stats_info* s)
+print_stats(RES* ssl, const char* nm, struct ub_stats_info* s)
 {
        struct timeval sumwait, avg;
        if(!ssl_printf(ssl, "%s.num.queries"SQ"%lu\n", nm, 
@@ -791,7 +763,7 @@ print_stats(SSL* ssl, const char* nm, struct ub_stats_info* s)
 
 /** print stats for one thread */
 static int
-print_thread_stats(SSL* ssl, int i, struct ub_stats_info* s)
+print_thread_stats(RES* ssl, int i, struct ub_stats_info* s)
 {
        char nm[32];
        snprintf(nm, sizeof(nm), "thread%d", i);
@@ -801,7 +773,7 @@ print_thread_stats(SSL* ssl, int i, struct ub_stats_info* s)
 
 /** print long number */
 static int
-print_longnum(SSL* ssl, const char* desc, size_t x)
+print_longnum(RES* ssl, const char* desc, size_t x)
 {
        if(x > 1024*1024*1024) {
                /* more than a Gb */
@@ -816,7 +788,7 @@ print_longnum(SSL* ssl, const char* desc, size_t x)
 
 /** print mem stats */
 static int
-print_mem(SSL* ssl, struct worker* worker, struct daemon* daemon)
+print_mem(RES* ssl, struct worker* worker, struct daemon* daemon)
 {
        size_t msg, rrset, val, iter, respip;
 #ifdef CLIENT_SUBNET
@@ -879,7 +851,7 @@ print_mem(SSL* ssl, struct worker* worker, struct daemon* daemon)
 
 /** print uptime stats */
 static int
-print_uptime(SSL* ssl, struct worker* worker, int reset)
+print_uptime(RES* ssl, struct worker* worker, int reset)
 {
        struct timeval now = *worker->env.now_tv;
        struct timeval up, dt;
@@ -898,7 +870,7 @@ print_uptime(SSL* ssl, struct worker* worker, int reset)
 
 /** print extended histogram */
 static int
-print_hist(SSL* ssl, struct ub_stats_info* s)
+print_hist(RES* ssl, struct ub_stats_info* s)
 {
        struct timehist* hist;
        size_t i;
@@ -926,7 +898,7 @@ print_hist(SSL* ssl, struct ub_stats_info* s)
 
 /** print extended stats */
 static int
-print_ext(SSL* ssl, struct ub_stats_info* s)
+print_ext(RES* ssl, struct ub_stats_info* s)
 {
        int i;
        char nm[16];
@@ -1046,6 +1018,10 @@ print_ext(SSL* ssl, struct ub_stats_info* s)
                (unsigned long)s->svr.ans_bogus)) return 0;
        if(!ssl_printf(ssl, "num.rrset.bogus"SQ"%lu\n", 
                (unsigned long)s->svr.rrset_bogus)) return 0;
+       if(!ssl_printf(ssl, "num.query.aggressive.NOERROR"SQ"%lu\n", 
+               (unsigned long)s->svr.num_neg_cache_noerror)) return 0;
+       if(!ssl_printf(ssl, "num.query.aggressive.NXDOMAIN"SQ"%lu\n", 
+               (unsigned long)s->svr.num_neg_cache_nxdomain)) return 0;
        /* threat detection */
        if(!ssl_printf(ssl, "unwanted.queries"SQ"%lu\n", 
                (unsigned long)s->svr.unwanted_queries)) return 0;
@@ -1070,12 +1046,16 @@ print_ext(SSL* ssl, struct ub_stats_info* s)
        if(!ssl_printf(ssl, "num.query.dnscrypt.replay"SQ"%lu\n",
                (unsigned long)s->svr.num_query_dnscrypt_replay)) return 0;
 #endif /* USE_DNSCRYPT */
+       if(!ssl_printf(ssl, "num.query.authzone.up"SQ"%lu\n",
+               (unsigned long)s->svr.num_query_authzone_up)) return 0;
+       if(!ssl_printf(ssl, "num.query.authzone.down"SQ"%lu\n",
+               (unsigned long)s->svr.num_query_authzone_down)) return 0;
        return 1;
 }
 
 /** do the stats command */
 static void
-do_stats(SSL* ssl, struct daemon_remote* rc, int reset)
+do_stats(RES* ssl, struct daemon_remote* rc, int reset)
 {
        struct daemon* daemon = rc->worker->daemon;
        struct ub_stats_info total;
@@ -1109,7 +1089,7 @@ do_stats(SSL* ssl, struct daemon_remote* rc, int reset)
 
 /** parse commandline argument domain name */
 static int
-parse_arg_name(SSL* ssl, char* str, uint8_t** res, size_t* len, int* labs)
+parse_arg_name(RES* ssl, char* str, uint8_t** res, size_t* len, int* labs)
 {
        uint8_t nm[LDNS_MAX_DOMAINLEN+1];
        size_t nmlen = sizeof(nm);
@@ -1135,7 +1115,7 @@ parse_arg_name(SSL* ssl, char* str, uint8_t** res, size_t* len, int* labs)
 
 /** find second argument, modifies string */
 static int
-find_arg2(SSL* ssl, char* arg, char** arg2)
+find_arg2(RES* ssl, char* arg, char** arg2)
 {
        char* as = strchr(arg, ' ');
        char* at = strchr(arg, '\t');
@@ -1160,7 +1140,7 @@ find_arg2(SSL* ssl, char* arg, char** arg2)
 
 /** Add a new zone */
 static int
-perform_zone_add(SSL* ssl, struct local_zones* zones, char* arg)
+perform_zone_add(RES* ssl, struct local_zones* zones, char* arg)
 {
        uint8_t* nm;
        int nmlabs;
@@ -1200,7 +1180,7 @@ perform_zone_add(SSL* ssl, struct local_zones* zones, char* arg)
 
 /** Do the local_zone command */
 static void
-do_zone_add(SSL* ssl, struct local_zones* zones, char* arg)
+do_zone_add(RES* ssl, struct local_zones* zones, char* arg)
 {
        if(!perform_zone_add(ssl, zones, arg))
                return;
@@ -1209,7 +1189,7 @@ do_zone_add(SSL* ssl, struct local_zones* zones, char* arg)
 
 /** Do the local_zones command */
 static void
-do_zones_add(SSL* ssl, struct local_zones* zones)
+do_zones_add(RES* ssl, struct local_zones* zones)
 {
        char buf[2048];
        int num = 0;
@@ -1228,7 +1208,7 @@ do_zones_add(SSL* ssl, struct local_zones* zones)
 
 /** Remove a zone */
 static int
-perform_zone_remove(SSL* ssl, struct local_zones* zones, char* arg)
+perform_zone_remove(RES* ssl, struct local_zones* zones, char* arg)
 {
        uint8_t* nm;
        int nmlabs;
@@ -1249,7 +1229,7 @@ perform_zone_remove(SSL* ssl, struct local_zones* zones, char* arg)
 
 /** Do the local_zone_remove command */
 static void
-do_zone_remove(SSL* ssl, struct local_zones* zones, char* arg)
+do_zone_remove(RES* ssl, struct local_zones* zones, char* arg)
 {
        if(!perform_zone_remove(ssl, zones, arg))
                return;
@@ -1258,7 +1238,7 @@ do_zone_remove(SSL* ssl, struct local_zones* zones, char* arg)
 
 /** Do the local_zones_remove command */
 static void
-do_zones_remove(SSL* ssl, struct local_zones* zones)
+do_zones_remove(RES* ssl, struct local_zones* zones)
 {
        char buf[2048];
        int num = 0;
@@ -1277,7 +1257,7 @@ do_zones_remove(SSL* ssl, struct local_zones* zones)
 
 /** Add new RR data */
 static int
-perform_data_add(SSL* ssl, struct local_zones* zones, char* arg)
+perform_data_add(RES* ssl, struct local_zones* zones, char* arg)
 {
        if(!local_zones_add_RR(zones, arg)) {
                ssl_printf(ssl,"error in syntax or out of memory, %s\n", arg);
@@ -1288,7 +1268,7 @@ perform_data_add(SSL* ssl, struct local_zones* zones, char* arg)
 
 /** Do the local_data command */
 static void
-do_data_add(SSL* ssl, struct local_zones* zones, char* arg)
+do_data_add(RES* ssl, struct local_zones* zones, char* arg)
 {
        if(!perform_data_add(ssl, zones, arg))
                return;
@@ -1297,7 +1277,7 @@ do_data_add(SSL* ssl, struct local_zones* zones, char* arg)
 
 /** Do the local_datas command */
 static void
-do_datas_add(SSL* ssl, struct local_zones* zones)
+do_datas_add(RES* ssl, struct local_zones* zones)
 {
        char buf[2048];
        int num = 0;
@@ -1316,7 +1296,7 @@ do_datas_add(SSL* ssl, struct local_zones* zones)
 
 /** Remove RR data */
 static int
-perform_data_remove(SSL* ssl, struct local_zones* zones, char* arg)
+perform_data_remove(RES* ssl, struct local_zones* zones, char* arg)
 {
        uint8_t* nm;
        int nmlabs;
@@ -1331,7 +1311,7 @@ perform_data_remove(SSL* ssl, struct local_zones* zones, char* arg)
 
 /** Do the local_data_remove command */
 static void
-do_data_remove(SSL* ssl, struct local_zones* zones, char* arg)
+do_data_remove(RES* ssl, struct local_zones* zones, char* arg)
 {
        if(!perform_data_remove(ssl, zones, arg))
                return;
@@ -1340,7 +1320,7 @@ do_data_remove(SSL* ssl, struct local_zones* zones, char* arg)
 
 /** Do the local_datas_remove command */
 static void
-do_datas_remove(SSL* ssl, struct local_zones* zones)
+do_datas_remove(RES* ssl, struct local_zones* zones)
 {
        char buf[2048];
        int num = 0;
@@ -1359,7 +1339,7 @@ do_datas_remove(SSL* ssl, struct local_zones* zones)
 
 /** Add a new zone to view */
 static void
-do_view_zone_add(SSL* ssl, struct worker* worker, char* arg)
+do_view_zone_add(RES* ssl, struct worker* worker, char* arg)
 {
        char* arg2;
        struct view* v;
@@ -1392,7 +1372,7 @@ do_view_zone_add(SSL* ssl, struct worker* worker, char* arg)
 
 /** Remove a zone from view */
 static void
-do_view_zone_remove(SSL* ssl, struct worker* worker, char* arg)
+do_view_zone_remove(RES* ssl, struct worker* worker, char* arg)
 {
        char* arg2;
        struct view* v;
@@ -1415,7 +1395,7 @@ do_view_zone_remove(SSL* ssl, struct worker* worker, char* arg)
 
 /** Add new RR data to view */
 static void
-do_view_data_add(SSL* ssl, struct worker* worker, char* arg)
+do_view_data_add(RES* ssl, struct worker* worker, char* arg)
 {
        char* arg2;
        struct view* v;
@@ -1440,7 +1420,7 @@ do_view_data_add(SSL* ssl, struct worker* worker, char* arg)
 
 /** Remove RR data from view */
 static void
-do_view_data_remove(SSL* ssl, struct worker* worker, char* arg)
+do_view_data_remove(RES* ssl, struct worker* worker, char* arg)
 {
        char* arg2;
        struct view* v;
@@ -1463,7 +1443,7 @@ do_view_data_remove(SSL* ssl, struct worker* worker, char* arg)
 
 /** cache lookup of nameservers */
 static void
-do_lookup(SSL* ssl, struct worker* worker, char* arg)
+do_lookup(RES* ssl, struct worker* worker, char* arg)
 {
        uint8_t* nm;
        int nmlabs;
@@ -1501,7 +1481,7 @@ do_cache_remove(struct worker* worker, uint8_t* nm, size_t nmlen,
 
 /** flush a type */
 static void
-do_flush_type(SSL* ssl, struct worker* worker, char* arg)
+do_flush_type(RES* ssl, struct worker* worker, char* arg)
 {
        uint8_t* nm;
        int nmlabs;
@@ -1521,7 +1501,7 @@ do_flush_type(SSL* ssl, struct worker* worker, char* arg)
 
 /** flush statistics */
 static void
-do_flush_stats(SSL* ssl, struct worker* worker)
+do_flush_stats(RES* ssl, struct worker* worker)
 {
        worker_stats_clear(worker);
        send_ok(ssl);
@@ -1576,7 +1556,7 @@ infra_del_host(struct lruhash_entry* e, void* arg)
 
 /** flush infra cache */
 static void
-do_flush_infra(SSL* ssl, struct worker* worker, char* arg)
+do_flush_infra(RES* ssl, struct worker* worker, char* arg)
 {
        struct sockaddr_storage addr;
        socklen_t len;
@@ -1610,7 +1590,7 @@ do_flush_infra(SSL* ssl, struct worker* worker, char* arg)
 
 /** flush requestlist */
 static void
-do_flush_requestlist(SSL* ssl, struct worker* worker)
+do_flush_requestlist(RES* ssl, struct worker* worker)
 {
        mesh_delete_all(worker->env.mesh);
        send_ok(ssl);
@@ -1644,6 +1624,7 @@ zone_del_msg(struct lruhash_entry* e, void* arg)
                struct reply_info* d = (struct reply_info*)e->data;
                if(d->ttl > inf->expired) {
                        d->ttl = inf->expired;
+                       d->prefetch_ttl = inf->expired;
                        inf->num_msgs++;
                }
        }
@@ -1667,7 +1648,7 @@ zone_del_kcache(struct lruhash_entry* e, void* arg)
 
 /** remove all rrsets and keys from zone from cache */
 static void
-do_flush_zone(SSL* ssl, struct worker* worker, char* arg)
+do_flush_zone(RES* ssl, struct worker* worker, char* arg)
 {
        uint8_t* nm;
        int nmlabs;
@@ -1745,7 +1726,7 @@ bogus_del_kcache(struct lruhash_entry* e, void* arg)
 
 /** remove all bogus rrsets, msgs and keys from cache */
 static void
-do_flush_bogus(SSL* ssl, struct worker* worker)
+do_flush_bogus(RES* ssl, struct worker* worker)
 {
        struct del_info inf;
        /* what we do is to set them all expired */
@@ -1820,7 +1801,7 @@ negative_del_kcache(struct lruhash_entry* e, void* arg)
 
 /** remove all negative(NODATA,NXDOMAIN), and servfail messages from cache */
 static void
-do_flush_negative(SSL* ssl, struct worker* worker)
+do_flush_negative(RES* ssl, struct worker* worker)
 {
        struct del_info inf;
        /* what we do is to set them all expired */
@@ -1848,7 +1829,7 @@ do_flush_negative(SSL* ssl, struct worker* worker)
 
 /** remove name rrset from cache */
 static void
-do_flush_name(SSL* ssl, struct worker* w, char* arg)
+do_flush_name(RES* ssl, struct worker* w, char* arg)
 {
        uint8_t* nm;
        int nmlabs;
@@ -1872,7 +1853,7 @@ do_flush_name(SSL* ssl, struct worker* w, char* arg)
 
 /** printout a delegation point info */
 static int
-ssl_print_name_dp(SSL* ssl, const char* str, uint8_t* nm, uint16_t dclass,
+ssl_print_name_dp(RES* ssl, const char* str, uint8_t* nm, uint16_t dclass,
        struct delegpt* dp)
 {
        char buf[257];
@@ -1906,7 +1887,7 @@ ssl_print_name_dp(SSL* ssl, const char* str, uint8_t* nm, uint16_t dclass,
 
 /** print root forwards */
 static int
-print_root_fwds(SSL* ssl, struct iter_forwards* fwds, uint8_t* root)
+print_root_fwds(RES* ssl, struct iter_forwards* fwds, uint8_t* root)
 {
        struct delegpt* dp;
        dp = forwards_lookup(fwds, root, LDNS_RR_CLASS_IN);
@@ -1919,7 +1900,7 @@ print_root_fwds(SSL* ssl, struct iter_forwards* fwds, uint8_t* root)
 
 /** parse args into delegpt */
 static struct delegpt*
-parse_delegpt(SSL* ssl, char* args, uint8_t* nm, int allow_names)
+parse_delegpt(RES* ssl, char* args, uint8_t* nm, int allow_names)
 {
        /* parse args and add in */
        char* p = args;
@@ -1927,6 +1908,7 @@ parse_delegpt(SSL* ssl, char* args, uint8_t* nm, int allow_names)
        struct delegpt* dp = delegpt_create_mlc(nm);
        struct sockaddr_storage addr;
        socklen_t addrlen;
+       char* auth_name;
        if(!dp) {
                (void)ssl_printf(ssl, "error out of memory\n");
                return NULL;
@@ -1939,7 +1921,7 @@ parse_delegpt(SSL* ssl, char* args, uint8_t* nm, int allow_names)
                        p = skipwhite(p); /* position at next spot */
                }
                /* parse address */
-               if(!extstrtoaddr(todo, &addr, &addrlen)) {
+               if(!authextstrtoaddr(todo, &addr, &addrlen, &auth_name)) {
                        if(allow_names) {
                                uint8_t* n = NULL;
                                size_t ln;
@@ -1967,7 +1949,8 @@ parse_delegpt(SSL* ssl, char* args, uint8_t* nm, int allow_names)
                        }
                } else {
                        /* add address */
-                       if(!delegpt_add_addr_mlc(dp, &addr, addrlen, 0, 0)) {
+                       if(!delegpt_add_addr_mlc(dp, &addr, addrlen, 0, 0,
+                               auth_name)) {
                                (void)ssl_printf(ssl, "error out of memory\n");
                                delegpt_free_mlc(dp);
                                return NULL;
@@ -1980,7 +1963,7 @@ parse_delegpt(SSL* ssl, char* args, uint8_t* nm, int allow_names)
 
 /** do the status command */
 static void
-do_forward(SSL* ssl, struct worker* worker, char* args)
+do_forward(RES* ssl, struct worker* worker, char* args)
 {
        struct iter_forwards* fwd = worker->env.fwds;
        uint8_t* root = (uint8_t*)"\000";
@@ -2011,7 +1994,7 @@ do_forward(SSL* ssl, struct worker* worker, char* args)
 }
 
 static int
-parse_fs_args(SSL* ssl, char* args, uint8_t** nm, struct delegpt** dp,
+parse_fs_args(RES* ssl, char* args, uint8_t** nm, struct delegpt** dp,
        int* insecure, int* prime)
 {
        char* zonename;
@@ -2056,7 +2039,7 @@ parse_fs_args(SSL* ssl, char* args, uint8_t** nm, struct delegpt** dp,
 
 /** do the forward_add command */
 static void
-do_forward_add(SSL* ssl, struct worker* worker, char* args)
+do_forward_add(RES* ssl, struct worker* worker, char* args)
 {
        struct iter_forwards* fwd = worker->env.fwds;
        int insecure = 0;
@@ -2084,7 +2067,7 @@ do_forward_add(SSL* ssl, struct worker* worker, char* args)
 
 /** do the forward_remove command */
 static void
-do_forward_remove(SSL* ssl, struct worker* worker, char* args)
+do_forward_remove(RES* ssl, struct worker* worker, char* args)
 {
        struct iter_forwards* fwd = worker->env.fwds;
        int insecure = 0;
@@ -2101,7 +2084,7 @@ do_forward_remove(SSL* ssl, struct worker* worker, char* args)
 
 /** do the stub_add command */
 static void
-do_stub_add(SSL* ssl, struct worker* worker, char* args)
+do_stub_add(RES* ssl, struct worker* worker, char* args)
 {
        struct iter_forwards* fwd = worker->env.fwds;
        int insecure = 0, prime = 0;
@@ -2142,7 +2125,7 @@ do_stub_add(SSL* ssl, struct worker* worker, char* args)
 
 /** do the stub_remove command */
 static void
-do_stub_remove(SSL* ssl, struct worker* worker, char* args)
+do_stub_remove(RES* ssl, struct worker* worker, char* args)
 {
        struct iter_forwards* fwd = worker->env.fwds;
        int insecure = 0;
@@ -2160,7 +2143,7 @@ do_stub_remove(SSL* ssl, struct worker* worker, char* args)
 
 /** do the insecure_add command */
 static void
-do_insecure_add(SSL* ssl, struct worker* worker, char* arg)
+do_insecure_add(RES* ssl, struct worker* worker, char* arg)
 {
        size_t nmlen;
        int nmlabs;
@@ -2181,7 +2164,7 @@ do_insecure_add(SSL* ssl, struct worker* worker, char* arg)
 
 /** do the insecure_remove command */
 static void
-do_insecure_remove(SSL* ssl, struct worker* worker, char* arg)
+do_insecure_remove(RES* ssl, struct worker* worker, char* arg)
 {
        size_t nmlen;
        int nmlabs;
@@ -2196,7 +2179,7 @@ do_insecure_remove(SSL* ssl, struct worker* worker, char* arg)
 }
 
 static void
-do_insecure_list(SSL* ssl, struct worker* worker)
+do_insecure_list(RES* ssl, struct worker* worker)
 {
        char buf[257];
        struct trust_anchor* a;
@@ -2212,7 +2195,7 @@ do_insecure_list(SSL* ssl, struct worker* worker)
 
 /** do the status command */
 static void
-do_status(SSL* ssl, struct worker* worker)
+do_status(RES* ssl, struct worker* worker)
 {
        int i;
        time_t uptime;
@@ -2233,9 +2216,12 @@ do_status(SSL* ssl, struct worker* worker)
        uptime = (time_t)time(NULL) - (time_t)worker->daemon->time_boot.tv_sec;
        if(!ssl_printf(ssl, "uptime: " ARG_LL "d seconds\n", (long long)uptime))
                return;
-       if(!ssl_printf(ssl, "options:%s%s\n" , 
+       if(!ssl_printf(ssl, "options:%s%s%s%s\n" , 
                (worker->daemon->reuseport?" reuseport":""),
-               (worker->daemon->rc->accept_list?" control(ssl)":"")))
+               (worker->daemon->rc->accept_list?" control":""),
+               (worker->daemon->rc->accept_list && worker->daemon->rc->use_cert?"(ssl)":""),
+               (worker->daemon->rc->accept_list && worker->daemon->cfg->control_ifs.first && worker->daemon->cfg->control_ifs.first->str && worker->daemon->cfg->control_ifs.first->str[0] == '/'?"(namedpipe)":"")
+               ))
                return;
        if(!ssl_printf(ssl, "unbound (pid %d) is running...\n",
                (int)getpid()))
@@ -2317,7 +2303,7 @@ get_mesh_status(struct mesh_area* mesh, struct mesh_state* m,
 
 /** do the dump_requestlist command */
 static void
-do_dump_requestlist(SSL* ssl, struct worker* worker)
+do_dump_requestlist(RES* ssl, struct worker* worker)
 {
        struct mesh_area* mesh;
        struct mesh_state* m;
@@ -2356,7 +2342,7 @@ struct infra_arg {
        /** the infra cache */
        struct infra_cache* infra;
        /** the SSL connection */
-       SSL* ssl;
+       RES* ssl;
        /** the time now */
        time_t now;
        /** ssl failure? stop writing and skip the rest.  If the tcp
@@ -2411,7 +2397,7 @@ dump_infra_host(struct lruhash_entry* e, void* arg)
 
 /** do the dump_infra command */
 static void
-do_dump_infra(SSL* ssl, struct worker* worker)
+do_dump_infra(RES* ssl, struct worker* worker)
 {
        struct infra_arg arg;
        arg.infra = worker->env.infra_cache;
@@ -2423,7 +2409,7 @@ do_dump_infra(SSL* ssl, struct worker* worker)
 
 /** do the log_reopen command */
 static void
-do_log_reopen(SSL* ssl, struct worker* worker)
+do_log_reopen(RES* ssl, struct worker* worker)
 {
        struct config_file* cfg = worker->env.cfg;
        send_ok(ssl);
@@ -2432,7 +2418,7 @@ do_log_reopen(SSL* ssl, struct worker* worker)
 
 /** do the set_option command */
 static void
-do_set_option(SSL* ssl, struct worker* worker, char* arg)
+do_set_option(RES* ssl, struct worker* worker, char* arg)
 {
        char* arg2;
        if(!find_arg2(ssl, arg, &arg2))
@@ -2455,13 +2441,13 @@ do_set_option(SSL* ssl, struct worker* worker, char* arg)
 /* routine to printout option values over SSL */
 void remote_get_opt_ssl(char* line, void* arg)
 {
-       SSL* ssl = (SSL*)arg;
+       RES* ssl = (RES*)arg;
        (void)ssl_printf(ssl, "%s\n", line);
 }
 
 /** do the get_option command */
 static void
-do_get_option(SSL* ssl, struct worker* worker, char* arg)
+do_get_option(RES* ssl, struct worker* worker, char* arg)
 {
        int r;
        r = config_get_option(worker->env.cfg, arg, remote_get_opt_ssl, ssl);
@@ -2473,7 +2459,7 @@ do_get_option(SSL* ssl, struct worker* worker, char* arg)
 
 /** do the list_forwards command */
 static void
-do_list_forwards(SSL* ssl, struct worker* worker)
+do_list_forwards(RES* ssl, struct worker* worker)
 {
        /* since its a per-worker structure no locks needed */
        struct iter_forwards* fwds = worker->env.fwds;
@@ -2501,7 +2487,7 @@ do_list_forwards(SSL* ssl, struct worker* worker)
 
 /** do the list_stubs command */
 static void
-do_list_stubs(SSL* ssl, struct worker* worker)
+do_list_stubs(RES* ssl, struct worker* worker)
 {
        struct iter_hints_stub* z;
        struct trust_anchor* a;
@@ -2527,9 +2513,39 @@ do_list_stubs(SSL* ssl, struct worker* worker)
        }
 }
 
+/** do the list_auth_zones command */
+static void
+do_list_auth_zones(RES* ssl, struct auth_zones* az)
+{
+       struct auth_zone* z;
+       char buf[257], buf2[256];
+       lock_rw_rdlock(&az->lock);
+       RBTREE_FOR(z, struct auth_zone*, &az->ztree) {
+               lock_rw_rdlock(&z->lock);
+               dname_str(z->name, buf);
+               if(z->zone_expired)
+                       snprintf(buf2, sizeof(buf2), "expired");
+               else {
+                       uint32_t serial = 0;
+                       if(auth_zone_get_serial(z, &serial))
+                               snprintf(buf2, sizeof(buf2), "serial %u",
+                                       (unsigned)serial);
+                       else    snprintf(buf2, sizeof(buf2), "no serial");
+               }
+               if(!ssl_printf(ssl, "%s\t%s\n", buf, buf2)) {
+                       /* failure to print */
+                       lock_rw_unlock(&z->lock);
+                       lock_rw_unlock(&az->lock);
+                       return;
+               }
+               lock_rw_unlock(&z->lock);
+       }
+       lock_rw_unlock(&az->lock);
+}
+
 /** do the list_local_zones command */
 static void
-do_list_local_zones(SSL* ssl, struct local_zones* zones)
+do_list_local_zones(RES* ssl, struct local_zones* zones)
 {
        struct local_zone* z;
        char buf[257];
@@ -2551,7 +2567,7 @@ do_list_local_zones(SSL* ssl, struct local_zones* zones)
 
 /** do the list_local_data command */
 static void
-do_list_local_data(SSL* ssl, struct worker* worker, struct local_zones* zones)
+do_list_local_data(RES* ssl, struct worker* worker, struct local_zones* zones)
 {
        struct local_zone* z;
        struct local_data* d;
@@ -2590,7 +2606,7 @@ do_list_local_data(SSL* ssl, struct worker* worker, struct local_zones* zones)
 
 /** do the view_list_local_zones command */
 static void
-do_view_list_local_zones(SSL* ssl, struct worker* worker, char* arg)
+do_view_list_local_zones(RES* ssl, struct worker* worker, char* arg)
 {
        struct view* v = views_find_view(worker->daemon->views,
                arg, 0 /* get read lock*/);
@@ -2606,7 +2622,7 @@ do_view_list_local_zones(SSL* ssl, struct worker* worker, char* arg)
 
 /** do the view_list_local_data command */
 static void
-do_view_list_local_data(SSL* ssl, struct worker* worker, char* arg)
+do_view_list_local_data(RES* ssl, struct worker* worker, char* arg)
 {
        struct view* v = views_find_view(worker->daemon->views,
                arg, 0 /* get read lock*/);
@@ -2625,7 +2641,7 @@ struct ratelimit_list_arg {
        /** the infra cache */
        struct infra_cache* infra;
        /** the SSL to print to */
-       SSL* ssl;
+       RES* ssl;
        /** all or only ratelimited */
        int all;
        /** current time */
@@ -2672,7 +2688,7 @@ ip_rate_list(struct lruhash_entry* e, void* arg)
 
 /** do the ratelimit_list command */
 static void
-do_ratelimit_list(SSL* ssl, struct worker* worker, char* arg)
+do_ratelimit_list(RES* ssl, struct worker* worker, char* arg)
 {
        struct ratelimit_list_arg a;
        a.all = 0;
@@ -2690,7 +2706,7 @@ do_ratelimit_list(SSL* ssl, struct worker* worker, char* arg)
 
 /** do the ip_ratelimit_list command */
 static void
-do_ip_ratelimit_list(SSL* ssl, struct worker* worker, char* arg)
+do_ip_ratelimit_list(RES* ssl, struct worker* worker, char* arg)
 {
        struct ip_ratelimit_list_arg a;
        a.all = 0;
@@ -2708,7 +2724,7 @@ do_ip_ratelimit_list(SSL* ssl, struct worker* worker, char* arg)
 
 /** tell other processes to execute the command */
 static void
-distribute_cmd(struct daemon_remote* rc, SSL* ssl, char* cmd)
+distribute_cmd(struct daemon_remote* rc, RES* ssl, char* cmd)
 {
        int i;
        if(!cmd || !ssl) 
@@ -2734,7 +2750,7 @@ cmdcmp(char* p, const char* cmd, size_t len)
 
 /** execute a remote control command */
 static void
-execute_cmd(struct daemon_remote* rc, SSL* ssl, char* cmd, 
+execute_cmd(struct daemon_remote* rc, RES* ssl, char* cmd, 
        struct worker* worker)
 {
        char* p = skipwhite(cmd);
@@ -2787,6 +2803,9 @@ execute_cmd(struct daemon_remote* rc, SSL* ssl, char* cmd,
        } else if(cmdcmp(p, "ip_ratelimit_list", 17)) {
                do_ip_ratelimit_list(ssl, worker, p+17);
                return;
+       } else if(cmdcmp(p, "list_auth_zones", 15)) {
+               do_list_auth_zones(ssl, worker->env.auth_zones);
+               return;
        } else if(cmdcmp(p, "stub_add", 8)) {
                /* must always distribute this cmd */
                if(rc) distribute_cmd(rc, ssl, cmd);
@@ -2915,7 +2934,7 @@ daemon_remote_exec(struct worker* worker)
 
 /** handle remote control request */
 static void
-handle_req(struct daemon_remote* rc, struct rc_state* s, SSL* ssl)
+handle_req(struct daemon_remote* rc, struct rc_state* s, RES* res)
 {
        int r;
        char pre[10];
@@ -2929,12 +2948,31 @@ handle_req(struct daemon_remote* rc, struct rc_state* s, SSL* ssl)
        fd_set_block(s->c->fd);
 
        /* try to read magic UBCT[version]_space_ string */
-       ERR_clear_error();
-       if((r=SSL_read(ssl, magic, (int)sizeof(magic)-1)) <= 0) {
-               if(SSL_get_error(ssl, r) == SSL_ERROR_ZERO_RETURN)
+       if(res->ssl) {
+               ERR_clear_error();
+               if((r=SSL_read(res->ssl, magic, (int)sizeof(magic)-1)) <= 0) {
+                       if(SSL_get_error(res->ssl, r) == SSL_ERROR_ZERO_RETURN)
+                               return;
+                       log_crypto_err("could not SSL_read");
                        return;
-               log_crypto_err("could not SSL_read");
-               return;
+               }
+       } else {
+               while(1) {
+                       ssize_t rr = recv(res->fd, magic, sizeof(magic)-1, 0);
+                       if(rr <= 0) {
+                               if(rr == 0) return;
+                               if(errno == EINTR || errno == EAGAIN)
+                                       continue;
+#ifndef USE_WINSOCK
+                               log_err("could not recv: %s", strerror(errno));
+#else
+                               log_err("could not recv: %s", wsa_strerror(WSAGetLastError()));
+#endif
+                               return;
+                       }
+                       r = (int)rr;
+                       break;
+               }
        }
        magic[6] = 0;
        if( r != 6 || strncmp(magic, "UBCT", 4) != 0) {
@@ -2944,25 +2982,58 @@ handle_req(struct daemon_remote* rc, struct rc_state* s, SSL* ssl)
        }
 
        /* read the command line */
-       if(!ssl_read_line(ssl, buf, sizeof(buf))) {
+       if(!ssl_read_line(res, buf, sizeof(buf))) {
                return;
        }
        snprintf(pre, sizeof(pre), "UBCT%d ", UNBOUND_CONTROL_VERSION);
        if(strcmp(magic, pre) != 0) {
                verbose(VERB_QUERY, "control connection had bad "
                        "version %s, cmd: %s", magic, buf);
-               ssl_printf(ssl, "error version mismatch\n");
+               ssl_printf(res, "error version mismatch\n");
                return;
        }
        verbose(VERB_DETAIL, "control cmd: %s", buf);
 
        /* figure out what to do */
-       execute_cmd(rc, ssl, buf, rc->worker);
+       execute_cmd(rc, res, buf, rc->worker);
+}
+
+/** handle SSL_do_handshake changes to the file descriptor to wait for later */
+static int
+remote_handshake_later(struct daemon_remote* rc, struct rc_state* s,
+       struct comm_point* c, int r, int r2)
+{
+       if(r2 == SSL_ERROR_WANT_READ) {
+               if(s->shake_state == rc_hs_read) {
+                       /* try again later */
+                       return 0;
+               }
+               s->shake_state = rc_hs_read;
+               comm_point_listen_for_rw(c, 1, 0);
+               return 0;
+       } else if(r2 == SSL_ERROR_WANT_WRITE) {
+               if(s->shake_state == rc_hs_write) {
+                       /* try again later */
+                       return 0;
+               }
+               s->shake_state = rc_hs_write;
+               comm_point_listen_for_rw(c, 0, 1);
+               return 0;
+       } else {
+               if(r == 0)
+                       log_err("remote control connection closed prematurely");
+               log_addr(1, "failed connection from",
+                       &s->c->repinfo.addr, s->c->repinfo.addrlen);
+               log_crypto_err("remote control failed ssl");
+               clean_point(rc, s);
+       }
+       return 0;
 }
 
 int remote_control_callback(struct comm_point* c, void* arg, int err, 
        struct comm_reply* ATTR_UNUSED(rep))
 {
+       RES res;
        struct rc_state* s = (struct rc_state*)arg;
        struct daemon_remote* rc = s->rc;
        int r;
@@ -2972,38 +3043,16 @@ int remote_control_callback(struct comm_point* c, void* arg, int err,
                clean_point(rc, s);
                return 0;
        }
-       /* (continue to) setup the SSL connection */
-       ERR_clear_error();
-       r = SSL_do_handshake(s->ssl);
-       if(r != 1) {
-               int r2 = SSL_get_error(s->ssl, r);
-               if(r2 == SSL_ERROR_WANT_READ) {
-                       if(s->shake_state == rc_hs_read) {
-                               /* try again later */
-                               return 0;
-                       }
-                       s->shake_state = rc_hs_read;
-                       comm_point_listen_for_rw(c, 1, 0);
-                       return 0;
-               } else if(r2 == SSL_ERROR_WANT_WRITE) {
-                       if(s->shake_state == rc_hs_write) {
-                               /* try again later */
-                               return 0;
-                       }
-                       s->shake_state = rc_hs_write;
-                       comm_point_listen_for_rw(c, 0, 1);
-                       return 0;
-               } else {
-                       if(r == 0)
-                               log_err("remote control connection closed prematurely");
-                       log_addr(1, "failed connection from",
-                               &s->c->repinfo.addr, s->c->repinfo.addrlen);
-                       log_crypto_err("remote control failed ssl");
-                       clean_point(rc, s);
-                       return 0;
+       if(s->ssl) {
+               /* (continue to) setup the SSL connection */
+               ERR_clear_error();
+               r = SSL_do_handshake(s->ssl);
+               if(r != 1) {
+                       int r2 = SSL_get_error(s->ssl, r);
+                       return remote_handshake_later(rc, s, c, r, r2);
                }
+               s->shake_state = rc_none;
        }
-       s->shake_state = rc_none;
 
        /* once handshake has completed, check authentication */
        if (!rc->use_cert) {
@@ -3026,7 +3075,9 @@ int remote_control_callback(struct comm_point* c, void* arg, int err,
        }
 
        /* if OK start to actually handle the request */
-       handle_req(rc, s, s->ssl);
+       res.ssl = s->ssl;
+       res.fd = c->fd;
+       handle_req(rc, s, &res);
 
        verbose(VERB_ALGO, "remote control operation completed");
        clean_point(rc, s);
index 190286d..217ea21 100644 (file)
@@ -73,6 +73,8 @@ struct rc_state {
        /** the ssl state */
        SSL* ssl;
 #endif
+       /** file descriptor */
+        int fd;
        /** the rc this is part of */
        struct daemon_remote* rc;
 };
@@ -103,6 +105,19 @@ struct daemon_remote {
 #endif
 };
 
+/**
+ * Connection to print to, either SSL or plain over fd
+ */
+struct remote_stream {
+#ifdef HAVE_SSL
+       /** SSL structure, nonNULL if using SSL */
+       SSL* ssl;
+#endif
+       /** file descriptor for plain transfer */
+       int fd;
+};
+typedef struct remote_stream RES;
+
 /**
  * Create new remote control state for the daemon.
  * @param cfg: config file with key file settings.
@@ -166,26 +181,26 @@ void daemon_remote_exec(struct worker* worker);
  * @param text: the text.
  * @return false on connection failure.
  */
-int ssl_print_text(SSL* ssl, const char* text);
+int ssl_print_text(RES* ssl, const char* text);
 
 /** 
  * printf style printing to the ssl connection
- * @param ssl: the SSL connection to print to. Blocking.
+ * @param ssl: the RES connection to print to. Blocking.
  * @param format: printf style format string.
  * @return success or false on a network failure.
  */
-int ssl_printf(SSL* ssl, const char* format, ...)
+int ssl_printf(RES* ssl, const char* format, ...)
         ATTR_FORMAT(printf, 2, 3);
 
 /**
  * Read until \n is encountered
- * If SSL signals EOF, the string up to then is returned (without \n).
- * @param ssl: the SSL connection to read from. blocking.
+ * If stream signals EOF, the string up to then is returned (without \n).
+ * @param ssl: the RES connection to read from. blocking.
  * @param buf: buffer to read to.
  * @param max: size of buffer.
  * @return false on connection failure.
  */
-int ssl_read_line(SSL* ssl, char* buf, size_t max);
+int ssl_read_line(RES* ssl, char* buf, size_t max);
 #endif /* HAVE_SSL */
 
 #endif /* DAEMON_REMOTE_H */
index ed78872..6f4feaa 100644 (file)
@@ -60,7 +60,9 @@
 #include "sldns/sbuffer.h"
 #include "services/cache/rrset.h"
 #include "services/cache/infra.h"
+#include "services/authzone.h"
 #include "validator/val_kcache.h"
+#include "validator/val_neg.h"
 
 /** add timers and the values do not overflow or become negative */
 static void
@@ -122,6 +124,30 @@ void server_stats_log(struct ub_server_stats* stats, struct worker* worker,
                (unsigned)worker->env.mesh->stats_jostled);
 }
 
+/** Set the neg cache stats. */
+static void
+set_neg_cache_stats(struct worker* worker, struct ub_server_stats* svr,
+       int reset)
+{
+       int m = modstack_find(&worker->env.mesh->mods, "validator");
+       struct val_env* ve;
+       struct val_neg_cache* neg;
+       if(m == -1)
+               return;
+       ve = (struct val_env*)worker->env.modinfo[m];
+       if(!ve->neg_cache)
+               return;
+       neg = ve->neg_cache;
+       lock_basic_lock(&neg->lock);
+       svr->num_neg_cache_noerror = (long long)neg->num_neg_cache_noerror;
+       svr->num_neg_cache_nxdomain = (long long)neg->num_neg_cache_nxdomain;
+       if(reset && !worker->env.cfg->stat_cumulative) {
+               neg->num_neg_cache_noerror = 0;
+               neg->num_neg_cache_nxdomain = 0;
+       }
+       lock_basic_unlock(&neg->lock);
+}
+
 /** get rrsets bogus number from validator */
 static size_t
 get_rrset_bogus(struct worker* worker, int reset)
@@ -256,6 +282,25 @@ server_stats_compile(struct worker* worker, struct ub_stats_info* s, int reset)
        s->svr.nonce_cache_count = 0;
        s->svr.num_query_dnscrypt_replay = 0;
 #endif /* USE_DNSCRYPT */
+       if(worker->env.auth_zones) {
+               if(reset && !worker->env.cfg->stat_cumulative) {
+                       lock_rw_wrlock(&worker->env.auth_zones->lock);
+               } else {
+                       lock_rw_rdlock(&worker->env.auth_zones->lock);
+               }
+               s->svr.num_query_authzone_up = (long long)worker->env.
+                       auth_zones->num_query_up;
+               s->svr.num_query_authzone_down = (long long)worker->env.
+                       auth_zones->num_query_down;
+               if(reset && !worker->env.cfg->stat_cumulative) {
+                       worker->env.auth_zones->num_query_up = 0;
+                       worker->env.auth_zones->num_query_down = 0;
+               }
+               lock_rw_unlock(&worker->env.auth_zones->lock);
+       }
+
+       /* Set neg cache usage numbers */
+       set_neg_cache_stats(worker, &s->svr, reset);
 
        /* get tcp accept usage */
        s->svr.tcp_accept_usage = 0;
index e4caf00..1383110 100644 (file)
@@ -431,7 +431,7 @@ perform_setup(struct daemon* daemon, struct config_file* cfg, int debug_mode,
                        fatal_exit("could not set up listen SSL_CTX");
        }
        if(!(daemon->connect_sslctx = connect_sslctx_create(NULL, NULL,
-               cfg->tls_cert_bundle)))
+               cfg->tls_cert_bundle, cfg->tls_win_cert)))
                fatal_exit("could not set up connect SSL_CTX");
 #endif
 
index 389a1de..44a989a 100644 (file)
@@ -342,7 +342,8 @@ worker_check_request(sldns_buffer* pkt, struct worker* worker)
                verbose(VERB_QUERY, "request bad, has TC bit on");
                return worker_err_ratelimit(worker, LDNS_RCODE_FORMERR);
        }
-       if(LDNS_OPCODE_WIRE(sldns_buffer_begin(pkt)) != LDNS_PACKET_QUERY) {
+       if(LDNS_OPCODE_WIRE(sldns_buffer_begin(pkt)) != LDNS_PACKET_QUERY &&
+               LDNS_OPCODE_WIRE(sldns_buffer_begin(pkt)) != LDNS_PACKET_NOTIFY) {
                verbose(VERB_QUERY, "request unknown opcode %d", 
                        LDNS_OPCODE_WIRE(sldns_buffer_begin(pkt)));
                return worker_err_ratelimit(worker, LDNS_RCODE_NOTIMPL);
@@ -352,7 +353,9 @@ worker_check_request(sldns_buffer* pkt, struct worker* worker)
                        LDNS_QDCOUNT(sldns_buffer_begin(pkt)));
                return worker_err_ratelimit(worker, LDNS_RCODE_FORMERR);
        }
-       if(LDNS_ANCOUNT(sldns_buffer_begin(pkt)) != 0) {
+       if(LDNS_ANCOUNT(sldns_buffer_begin(pkt)) != 0 && 
+               (LDNS_ANCOUNT(sldns_buffer_begin(pkt)) != 1 ||
+               LDNS_OPCODE_WIRE(sldns_buffer_begin(pkt)) != LDNS_PACKET_NOTIFY)) {
                verbose(VERB_QUERY, "request wrong nr an=%d", 
                        LDNS_ANCOUNT(sldns_buffer_begin(pkt)));
                return worker_err_ratelimit(worker, LDNS_RCODE_FORMERR);
@@ -499,6 +502,7 @@ answer_norec_from_cache(struct worker* worker, struct query_info* qinfo,
                         * let validator do that */
                        return 0;
                case sec_status_bogus:
+               case sec_status_secure_sentinel_fail:
                        /* some rrsets are bogus, reply servfail */
                        edns->edns_version = EDNS_ADVERTISED_VERSION;
                        edns->udp_size = EDNS_ADVERTISED_SIZE;
@@ -655,7 +659,8 @@ answer_from_cache(struct worker* worker, struct query_info* qinfo,
                }
        }
        /* check security status of the cached answer */
-       if( rep->security == sec_status_bogus && must_validate) {
+       if(must_validate && (rep->security == sec_status_bogus ||
+               rep->security == sec_status_secure_sentinel_fail)) {
                /* BAD cached */
                edns->edns_version = EDNS_ADVERTISED_VERSION;
                edns->udp_size = EDNS_ADVERTISED_SIZE;
@@ -940,6 +945,66 @@ answer_chaos(struct worker* w, struct query_info* qinfo,
        return 0;
 }
 
+/**
+ * Answer notify queries.  These are notifies for authoritative zones,
+ * the reply is an ack that the notify has been received.  We need to check
+ * access permission here.
+ * @param w: worker
+ * @param qinfo: query info. Pointer into packet buffer.
+ * @param edns: edns info from query.
+ * @param repinfo: reply info with source address.
+ * @param pkt: packet buffer.
+ */
+static void
+answer_notify(struct worker* w, struct query_info* qinfo, 
+       struct edns_data* edns, sldns_buffer* pkt, struct comm_reply* repinfo)
+{
+       int refused = 0;
+       int rcode = LDNS_RCODE_NOERROR;
+       uint32_t serial = 0;
+       int has_serial;
+       if(!w->env.auth_zones) return;
+       has_serial = auth_zone_parse_notify_serial(pkt, &serial);
+       if(auth_zones_notify(w->env.auth_zones, &w->env, qinfo->qname,
+               qinfo->qname_len, qinfo->qclass, &repinfo->addr,
+               repinfo->addrlen, has_serial, serial, &refused)) {
+               rcode = LDNS_RCODE_NOERROR;
+       } else {
+               if(refused)
+                       rcode = LDNS_RCODE_REFUSED;
+               else    rcode = LDNS_RCODE_SERVFAIL;
+       }
+
+       if(verbosity >= VERB_DETAIL) {
+               char buf[380];
+               char zname[255+1];
+               char sr[25];
+               dname_str(qinfo->qname, zname);
+               sr[0]=0;
+               if(has_serial)
+                       snprintf(sr, sizeof(sr), "serial %u ",
+                               (unsigned)serial);
+               if(rcode == LDNS_RCODE_REFUSED)
+                       snprintf(buf, sizeof(buf),
+                               "refused NOTIFY %sfor %s from", sr, zname);
+               else if(rcode == LDNS_RCODE_SERVFAIL)
+                       snprintf(buf, sizeof(buf),
+                               "servfail for NOTIFY %sfor %s from", sr, zname);
+               else    snprintf(buf, sizeof(buf),
+                               "received NOTIFY %sfor %s from", sr, zname);
+               log_addr(VERB_DETAIL, buf, &repinfo->addr, repinfo->addrlen);
+       }
+       edns->edns_version = EDNS_ADVERTISED_VERSION;
+       edns->udp_size = EDNS_ADVERTISED_SIZE;
+       edns->ext_rcode = 0;
+       edns->bits &= EDNS_DO;
+       edns->opt_list = NULL;
+       error_encode(pkt, rcode, qinfo,
+               *(uint16_t*)(void *)sldns_buffer_begin(pkt),
+               sldns_buffer_read_u16_at(pkt, 2), edns);
+       LDNS_OPCODE_SET(sldns_buffer_begin(pkt), LDNS_PACKET_NOTIFY);
+}
+
 static int
 deny_refuse(struct comm_point* c, enum acl_access acl,
        enum acl_access deny, enum acl_access refuse,
@@ -1238,6 +1303,12 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
                regional_free_all(worker->scratchpad);
                goto send_reply;
        }
+       if(LDNS_OPCODE_WIRE(sldns_buffer_begin(c->buffer)) ==
+               LDNS_PACKET_NOTIFY) {
+               answer_notify(worker, &qinfo, &edns, c->buffer, repinfo);
+               regional_free_all(worker->scratchpad);
+               goto send_reply;
+       }
        if(local_zones_answer(worker->daemon->local_zones, &worker->env, &qinfo,
                &edns, c->buffer, worker->scratchpad, repinfo, acladdr->taglist,
                acladdr->taglen, acladdr->tag_actions,
@@ -1279,6 +1350,13 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
                return ret;
        }
 
+       /* If this request does not have the recursion bit set, verify
+        * ACLs allow the recursion bit to be treated as set. */
+       if(!(LDNS_RD_WIRE(sldns_buffer_begin(c->buffer))) &&
+               acl == acl_allow_setrd ) {
+               LDNS_RD_SET(sldns_buffer_begin(c->buffer));
+       }
+
        /* If this request does not have the recursion bit set, verify
         * ACLs allow the snooping. */
        if(!(LDNS_RD_WIRE(sldns_buffer_begin(c->buffer))) &&
@@ -1806,7 +1884,7 @@ struct outbound_entry*
 worker_send_query(struct query_info* qinfo, uint16_t flags, int dnssec,
        int want_dnssec, int nocaps, struct sockaddr_storage* addr,
        socklen_t addrlen, uint8_t* zone, size_t zonelen, int ssl_upstream,
-       struct module_qstate* q)
+       char* tls_auth_name, struct module_qstate* q)
 {
        struct worker* worker = q->env->worker;
        struct outbound_entry* e = (struct outbound_entry*)regional_alloc(
@@ -1816,7 +1894,7 @@ worker_send_query(struct query_info* qinfo, uint16_t flags, int dnssec,
        e->qstate = q;
        e->qsent = outnet_serviced_query(worker->back, qinfo, flags, dnssec,
                want_dnssec, nocaps, q->env->cfg->tcp_upstream,
-               ssl_upstream, addr, addrlen, zone, zonelen, q,
+               ssl_upstream, tls_auth_name, addr, addrlen, zone, zonelen, q,
                worker_handle_service_reply, e, worker->back->udp_buff, q->env);
        if(!e->qsent) {
                return NULL;
@@ -1863,7 +1941,8 @@ struct outbound_entry* libworker_send_query(
        int ATTR_UNUSED(want_dnssec), int ATTR_UNUSED(nocaps),
        struct sockaddr_storage* ATTR_UNUSED(addr), socklen_t ATTR_UNUSED(addrlen),
        uint8_t* ATTR_UNUSED(zone), size_t ATTR_UNUSED(zonelen),
-       int ATTR_UNUSED(ssl_upstream), struct module_qstate* ATTR_UNUSED(q))
+       int ATTR_UNUSED(ssl_upstream), char* ATTR_UNUSED(tls_auth_name),
+       struct module_qstate* ATTR_UNUSED(q))
 {
        log_assert(0);
        return 0;
index f299353..3d05ae5 100644 (file)
@@ -1,6 +1,257 @@
+19 June 2018: Wouter
+       - Fix for unbound-control on Windows and set TCP socket parameters
+         more closely.
+       - Fix windows unbound-control no cert bad file descriptor error.
+
+18 June 2018: Wouter
+       - Fix that control-use-cert: no works for 127.0.0.1 to disable certs.
+       - Fix unbound-checkconf for control-use-cert.
+
+15 June 2018: Wouter
+       - tag for 1.7.3rc1.
+
+14 June 2018: Wouter
+       - #4103: Fix that auth-zone does not insist on SOA record first in
+         file for url downloads.
+       - Fix that first control-interface determines if TLS is used.  Warn
+         when IP address interfaces are used without TLS.
+       - Fix nettle compile.
+
+12 June 2018: Ralph
+       - Don't count CNAME response types received during qname minimisation as
+         query restart.
+
+12 June 2018: Wouter
+       - #4102 for NSD, but for Unbound.  Named unix pipes do not use
+         certificate and key files, access can be restricted with file and
+         directory permissions.  The option control-use-cert is no longer
+         used, and ignored if found in unbound.conf.
+       - Rename tls-additional-ports to tls-additional-port, because every
+         line adds one port.
+       - Fix buffer size warning in unit test.
+       - remade dependencies in the Makefile.
+
+6 June 2018: Wouter
+       - Patch to fix openwrt for mac os build darwin detection in configure.
+
+5 June 2018: Wouter
+       - Fix crash if ratelimit taken into use with unbound-control
+         instead of with unbound.conf.
+
+4 June 2018: Wouter
+       - Fix deadlock caused by incoming notify for auth-zone.
+       - tag for 1.7.2rc1, became 1.7.2 release on 11 June 2018,
+         trunk is 1.7.3 in development from this point.
+       - #4100: Fix stub reprime when it becomes useless.
+
+1 June 2018: Wouter
+       - Rename additional-tls-port to tls-additional-ports.
+         The older name is accepted for backwards compatibility.
+
+30 May 2018: Wouter
+       - Patch from Syzdek: Add ability to ignore RD bit and treat all
+         requests as if the RD bit is set.
+
+29 May 2018: Wouter
+       - in compat/arc4random call getentropy_urandom when getentropy fails
+         with ENOSYS.
+       - Fix that fallback for windows port.
+
+28 May 2018: Wouter
+       - Fix windows tcp and tls spin on events.
+       - Add routine from getdns to add windows cert store to the SSL_CTX.
+       - tls-win-cert option that adds the system certificate store for
+         authenticating DNS-over-TLS connections.  It can be used instead
+         of the tls-cert-bundle option, or with it to add certificates.
+
+25 May 2018: Wouter
+       - For TCP and TLS connections that don't establish, perform address
+         update in infra cache, so future selections can exclude them.
+       - Fix that tcp sticky events are removed for closed fd on windows.
+       - Fix close events for tcp only.
+
+24 May 2018: Wouter
+       - Fix that libunbound can do DNS-over-TLS, when configured.
+       - Fix that windows unbound service can use DNS-over-TLS.
+       - unbound-host initializes ssl (for potential DNS-over-TLS usage
+         inside libunbound), when ssl upstream or a cert-bundle is configured.
+
+23 May 2018: Wouter
+       - Use accept4 to speed up incoming TCP (and TLS) connections,
+         available on Linux, FreeBSD and OpenBSD.
+
+17 May 2018: Ralph
+       - Qname minimisation default changed to yes.
+
+15 May 2018: Wouter
+       - Fix low-rtt-pct to low-rtt-permil, as it is parts in one thousand.
+
+11 May 2018: Wouter
+       - Fix contrib/libunbound.pc for libssl libcrypto references,
+         from https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=226914
+
+7 May 2018: Wouter
+       - Fix windows to not have sticky TLS events for TCP.
+       - Fix read of DNS over TLS length and data in one read call.
+       - Fix mesh state assertion failure due to callback removal.
+
+3 May 2018: Wouter
+       - Fix that configure --with-libhiredis also turns on cachedb.
+       - Fix gcc 8 buffer warning in testcode.
+       - Fix function type cast warning in libunbound context callback type.
+
+2 May 2018: Wouter
+       - Fix fail to reject dead peers in forward-zone, with ssl-upstream.
+
+1 May 2018: Wouter
+       - Fix that unbound-control reload frees the rrset keys and returns
+         the memory pages to the system.
+
+30 April 2018: Wouter
+       - Fix spelling error in man page and note defaults as no instead of
+         off.
+
+26 April 2018: Wouter
+       - Fix for crash in daemon_cleanup with dnstap during reload,
+         from Saksham Manchanda.
+       - Also that for dnscrypt.
+       - tag for 1.7.1rc1 release.  Became 1.7.1 release on 3 May, trunk
+         is from here 1.7.2 in development.
+
+25 April 2018: Ralph
+       - Fix memory leak when caching wildcard records for aggressive NSEC use
+
+24 April 2018: Wouter
+       - Fix contrib/fastrpz.patch for this release.
+       - Fix auth https for libev.
+
+24 April 2018: Ralph
+       - Added root-key-sentinel support
+
+23 April 2018: Wouter
+       - makedist uses bz2 for expat code, instead of tar.gz.
+       - Fix #4092: libunbound: use-caps-for-id lacks colon in
+         config_set_option.
+       - auth zone http download stores exact copy of downloaded file,
+         including comments in the file.
+       - Fix sldns parse failure for CDS alternate delete syntax empty hex.
+       - Attempt for auth zone fix; add of callback in mesh gets from
+         callback does not skip callback of result.
+       - Fix cname classification with qname minimisation enabled.
+       - list_auth_zones unbound-control command.
+
+20 April 2018: Wouter
+       - man page documentation for dns-over-tls forward-addr '#' notation.
+       - removed free from failed parse case.
+       - Fix #4091: Fix that reload of auth-zone does not merge the zonefile
+         with the previous contents.
+       - Delete auth zone when removed from config.
+
+19 April 2018: Wouter
+       - Can set tls authentication with forward-addr: IP#tls.auth.name
+         And put the public cert bundle in tls-cert-bundle: "ca-bundle.pem".
+         such as forward-addr: 9.9.9.9@853#dns.quad9.net or
+         1.1.1.1@853#cloudflare-dns.com
+       - Fix #658: unbound using TLS in a forwarding configuration does not
+         verify the server's certificate (RFC 8310 support).
+       - For addr with #authname and no @port notation, the default is 853.
+
+18 April 2018: Wouter
+       - Fix auth-zone retry timer to be on schedule with retry timeout,
+         with backoff.  Also time a refresh at the zone expiry.
+
+17 April 2018: Wouter
+       - auth zone notify work.
+       - allow-notify: config statement for auth-zones.
+       - unit test for allow-notify
+
+16 April 2018: Wouter
+       - Fix auth zone target lookup iterator.
+       - auth zone notify with prefix
+       - auth zone notify work.
+
+13 April 2018: Wouter
+       - Fix for max include depth for authzones.
+       - Fix memory free on fail for $INCLUDE in authzone.
+       - Fix that an internal error to look up the wrong rr type for
+         auth zone gets stopped, before trying to send there.
+       - auth zone notify work.
+
+10 April 2018: Ralph
+       - num.query.aggressive.NOERROR and num.query.aggressive.NXDOMAIN
+         statistics counters.
+
+10 April 2018: Wouter
+       - documentation for low-rtt and low-rtt-pct.
+       - auth zone notify work.
+
+9 April 2018: Wouter
+       - Fix that flush_zone sets prefetch ttl expired, so that with
+         serve-expired enabled it'll start prefetching those entries.
+       - num.query.authzone.up and num.query.authzone.down statistics counters.
+       - Fix downstream auth zone, only fallback when auth zone fails to
+         answer and fallback is enabled.
+       - Accept both option names with and without colon for get_option
+         and set_option.
+       - low-rtt and low-rtt-pct in unbound.conf enable the server selection
+         of fast servers for some percentage of the time.
+
+5 April 2018: Wouter
+       - Combine write of tcp length and tcp query for dns over tls.
+       - nitpick fixes in example.conf.
+       - Fix above stub queries for type NS and useless delegation point.
+       - Fix unbound-control over pipe with openssl 1.1.1, the TLSv1.3
+         tls_choose_sigalg routine does not allow the ciphers for the pipe,
+         so use TLSv1.2.
+       - ED448 support.
+
+3 April 2018: Wouter
+       - Fix #4043: make test fails due to v6 presentation issue in macOS.
+       - Fix unable to resolve after new WLAN connection, due to auth-zone
+         failing with a forwarder set.  Now, auth-zone is only used for
+         answers (not referrals) when a forwarder is set.
+
+29 March 2018: Ralph
+       - Check "result" in dup_all(), by Florian Obser.
+
+23 March 2018: Ralph
+       - Fix unbound-control get_option aggressive-nsec
+
+21 March 2018: Ralph
+       - Do not use cached NSEC records to generate negative answers for
+         domains under DNSSEC Negative Trust Anchors.
+
+19 March 2018: Wouter
+       - iana port update.
+
+16 March 2018: Wouter
+       - corrected a minor typo in the changelog.
+       - move htobe64/be64toh portability code to cachedb.c.
+
+15 March 2018: Wouter
+       - Add --with-libhiredis, unbound support for a new cachedb backend
+         that uses a Redis server as the storage.  This implementation
+         depends on the hiredis client library (https://redislabs.com/lp/hiredis/).
+         And unbound should be built with both --enable-cachedb and
+         --with-libhiredis[=PATH] (where $PATH/include/hiredis/hiredis.h
+         should exist).  Patch from Jinmei Tatuya (Infoblox).
+       - Fix #3817: core dump happens in libunbound delete, when queued
+         servfail hits deleted message queue.
+       - Create additional tls service interfaces by opening them on other
+         portnumbers and listing the portnumbers as additional-tls-port: nr.
+
+13 March 2018: Wouter
+       - Fix typo in documentation.
+       - Fix #3736: Fix 0 TTL domains stuck on SERVFAIL unless manually
+         flushed with serve-expired on.
+
 12 March 2018: Wouter
        - Added documentation for aggressive-nsec: yes.
-       - tag 1.7.0rc3.
+       - tag 1.7.0rc3.  That became the 1.7.0 release on 15 Mar, trunk
+         now has 1.7.1 in development.
+       - Fix #3727: Protocol name is TLS, options have been renamed but
+         documentation is not consistent.
+       - Check IXFR start serial.
 
 9 March 2018: Wouter
        - Fix #3598: Fix swig build issue on rhel6 based system.
index 58cd56f..5bd23fa 100644 (file)
@@ -1,4 +1,4 @@
-README for Unbound 1.7.0
+README for Unbound 1.7.3
 Copyright 2007 NLnet Labs
 http://unbound.net
 
index a31ee6d..d1f2148 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Example configuration file.
 #
-# See unbound.conf(5) man page, version 1.7.0.
+# See unbound.conf(5) man page, version 1.7.3.
 #
 # this is a comment.
 
@@ -199,7 +199,7 @@ server:
        # upstream connections use TCP only (and no UDP), "yes" or "no"
        # useful for tunneling scenarios, default no.
        # tcp-upstream: no
-       
+
        # upstream connections also use UDP (even if do-udp is no).
        # useful if if you want UDP upstream, but don't provide UDP downstream.
        # udp-upstream-without-downstream: no
@@ -223,7 +223,8 @@ server:
        # to this server. Specify classless netblocks with /size and action.
        # By default everything is refused, except for localhost.
        # Choose deny (drop message), refuse (polite error reply),
-       # allow (recursive ok), allow_snoop (recursive and nonrecursive ok)
+       # allow (recursive ok), allow_setrd (recursive ok, rd bit is forced on),
+       # allow_snoop (recursive and nonrecursive ok)
        # deny_non_local (drop queries unless can be answered from local-data)
        # refuse_non_local (like deny_non_local but polite error reply).
        # access-control: 0.0.0.0/0 refuse
@@ -320,7 +321,7 @@ server:
 
        # enable to not answer version.server and version.bind queries.
        # hide-version: no
-       
+
        # enable to not answer trustanchor.unbound queries.
        # hide-trustanchor: no
 
@@ -372,7 +373,7 @@ server:
        # Sent minimum amount of information to upstream servers to enhance
        # privacy. Only sent minimum required labels of the QNAME and set QTYPE
        # to A when possible.
-       # qname-minimisation: no
+       # qname-minimisation: yes
 
        # QNAME minimisation in strict mode. Do not fall-back to sending full
        # QNAME to potentially broken nameservers. A lot of domains will not be
@@ -459,6 +460,9 @@ server:
        # trust anchor signaling sends a RFC8145 key tag query after priming.
        # trust-anchor-signaling: no
 
+       # Root key trust anchor sentinel (draft-ietf-dnsop-kskroll-sentinel)
+       # root-key-sentinel: yes
+
        # File with DLV trusted keys. Same format as trust-anchor-file.
        # There can be only one DLV configured, it is trusted from root down.
        # DLV is going to be decommissioned.  Please do not use it any more.
@@ -630,7 +634,7 @@ server:
        # o inform acts like transparent, but logs client IP address
        # o inform_deny drops queries and logs client IP address
        # o always_transparent, always_refuse, always_nxdomain, resolve in
-       #   that way but ignore local data for that name.
+       #   that way but ignore local data for that name
        # o noview breaks out of that view towards global local-zones.
        #
        # defaults are localhost address, reverse for 127.0.0.1 and ::1
@@ -664,20 +668,26 @@ server:
        # add a netblock specific override to a localzone, with zone type
        # local-zone-override: "example.com" 192.0.2.0/24 refuse
 
-       # service clients over SSL (on the TCP sockets), with plain DNS inside
-       # the SSL stream.  Give the certificate to use and private key.
+       # service clients over TLS (on the TCP sockets), with plain DNS inside
+       # the TLS stream.  Give the certificate to use and private key.
        # default is "" (disabled).  requires restart to take effect.
        # tls-service-key: "path/to/privatekeyfile.key"
        # tls-service-pem: "path/to/publiccertfile.pem"
        # tls-port: 853
 
-       # request upstream over SSL (with plain DNS inside the SSL stream).
+       # request upstream over TLS (with plain DNS inside the TLS stream).
        # Default is no.  Can be turned on and off with unbound-control.
        # tls-upstream: no
 
        # Certificates used to authenticate connections made upstream.
        # tls-cert-bundle: ""
 
+       # Add system certs to the cert bundle, from the Windows Cert Store
+       # tls-win-cert: no
+
+       # Also serve tls on these port numbers (eg. 443, ...), by listing
+       # tls-additional-port: portno for each of the port numbers.
+
        # DNS64 prefix. Must be specified when DNS64 is use.
        # Enable dns64 in module-config.  Used to synthesize IPv6 from IPv4.
        # dns64-prefix: 64:ff9b::0/96
@@ -715,6 +725,12 @@ server:
        # 0 blocks when ip is ratelimited, otherwise let 1/xth traffic through
        # ip-ratelimit-factor: 10
 
+       # what is considered a low rtt (ping time for upstream server), in msec
+       # low-rtt: 45
+       # select low rtt this many times out of 1000. 0 means the fast server
+       # select is disabled.  prefetches are not sped up.
+       # low-rtt-permil: 0
+
        # Specific options for ipsecmod. unbound needs to be configured with
        # --enable-ipsecmod for these to take effect.
        #
@@ -758,18 +774,20 @@ remote-control:
        # set up the keys and certificates with unbound-control-setup.
        # control-enable: no
 
-       # Set to no and use an absolute path as control-interface to use
-       # a unix local named pipe for unbound-control.
-       # control-use-cert: yes
-
        # what interfaces are listened to for remote control.
        # give 0.0.0.0 and ::0 to listen to all interfaces.
+       # set to an absolute path to use a unix local name pipe, certificates
+       # are not used for that, so key and cert files need not be present.
        # control-interface: 127.0.0.1
        # control-interface: ::1
 
        # port number for remote control operations.
        # control-port: 8953
 
+       # for localhost, you can disable use of TLS by setting this to "no"
+       # For local sockets this option is ignored, and TLS is not used.
+       # control-use-cert: "yes"
+
        # unbound server key file.
        # server-key-file: "@UNBOUND_RUN_DIR@/unbound_server.key"
 
@@ -823,6 +841,8 @@ remote-control:
 # has a copy of the root for local usage.  The second serves example.org
 # authoritatively.  zonefile: reads from file (and writes to it if you also
 # download it), master: fetches with AXFR and IXFR, or url to zonefile.
+# With allow-notify: you can give additional (apart from masters) sources of
+# notifies.
 # auth-zone:
 #      name: "."
 #      for-downstream: no
@@ -851,7 +871,7 @@ remote-control:
 #      name: "viewname"
 #      local-zone: "example.com" redirect
 #      local-data: "example.com A 192.0.2.3"
-#      local-data-ptr: "192.0.2.3 www.example.com"
+#      local-data-ptr: "192.0.2.3 www.example.com"
 #      view-first: no
 # view:
 #      name: "anotherview"
@@ -886,3 +906,11 @@ remote-control:
 #     backend: "testframe"
 #     # secret seed string to calculate hashed keys
 #     secret-seed: "default"
+#
+#     # For "redis" backend:
+#     # redis server's IP address or host name
+#     redis-server-host: 127.0.0.1
+#     # redis server's TCP port
+#     redis-server-port: 6379
+#     # timeout (in ms) for communication with the redis server
+#     redis-timeout: 100
index 357e981..d4b0efd 100644 (file)
@@ -1,4 +1,4 @@
-.TH "libunbound" "3" "Mar 15, 2018" "NLnet Labs" "unbound 1.7.0"
+.TH "libunbound" "3" "Jun 21, 2018" "NLnet Labs" "unbound 1.7.3"
 .\"
 .\" libunbound.3 -- unbound library functions manual
 .\"
@@ -43,7 +43,7 @@
 .B ub_ctx_zone_remove,
 .B ub_ctx_data_add,
 .B ub_ctx_data_remove
-\- Unbound DNS validating resolver 1.7.0 functions.
+\- Unbound DNS validating resolver 1.7.3 functions.
 .SH "SYNOPSIS"
 .B #include <unbound.h>
 .LP
index f50bf28..ca7cafa 100644 (file)
@@ -1,4 +1,4 @@
-.TH "unbound-anchor" "8" "Mar 15, 2018" "NLnet Labs" "unbound 1.7.0"
+.TH "unbound-anchor" "8" "Jun 21, 2018" "NLnet Labs" "unbound 1.7.3"
 .\"
 .\" unbound-anchor.8 -- unbound anchor maintenance utility manual
 .\"
index a07124e..9d35e64 100644 (file)
@@ -1,4 +1,4 @@
-.TH "unbound-checkconf" "8" "Mar 15, 2018" "NLnet Labs" "unbound 1.7.0"
+.TH "unbound-checkconf" "8" "Jun 21, 2018" "NLnet Labs" "unbound 1.7.3"
 .\"
 .\" unbound-checkconf.8 -- unbound configuration checker manual
 .\"
index 53af915..f3d9669 100644 (file)
@@ -1,4 +1,4 @@
-.TH "unbound-control" "8" "Mar 15, 2018" "NLnet Labs" "unbound 1.7.0"
+.TH "unbound-control" "8" "Jun 21, 2018" "NLnet Labs" "unbound 1.7.3"
 .\"
 .\" unbound-control.8 -- unbound remote control manual
 .\"
@@ -144,6 +144,9 @@ Remove the name, type information from the cache.
 Remove all information at or below the name from the cache. 
 The rrsets and key entries are removed so that new lookups will be performed.
 This needs to walk and inspect the entire cache, and is a slow operation.
+The entries are set to expired in the implementation of this command (so,
+with serve\-expired enabled, it'll serve that information but schedule a
+prefetch for new information).
 .TP
 .B flush_bogus
 Remove all bogus data from the cache.
@@ -286,6 +289,10 @@ estimated qps and qps limit from config.  With +a it prints all ips, not
 just the ratelimited ips, with their estimated qps.  The ratelimited
 ips are dropped before checking the cache.
 .TP
+.B list_auth_zones
+List the auth zones that are configured.  Printed one per line with a
+status, indicating if the zone is expired and current serial number.
+.TP
 .B view_list_local_zones \fIview\fR
 \fIlist_local_zones\fR for given view.
 .TP
@@ -598,6 +605,26 @@ dnscrypt queries replay. The client nonce must be unique for each client public
 key/server secret key pair. This cache should be able to host QPS * `replay
 window` interval keys to prevent replay of a query during `replay window`
 seconds.
+.TP
+.I num.query.authzone.up
+The number of queries answered from auth\-zone data, upstream queries.
+These queries would otherwise have been sent (with fallback enabled) to
+the internet, but are now answered from the auth zone.
+.TP
+.I num.query.authzone.down
+The number of queries for downstream answered from auth\-zone data.
+These queries are from downstream clients, and have had an answer from
+the data in the auth zone.
+.TP
+.I num.query.aggressive.NOERROR
+The number of queries answered using cached NSEC records with NODATA RCODE.
+These queries would otherwise have been sent to the internet, but are now
+answered using cached data.
+.TP
+.I num.query.aggressive.NXDOMAIN
+The number of queries answered using cached NSEC records with NXDOMAIN RCODE.
+These queries would otherwise have been sent to the internet, but are now
+answered using cached data.
 .SH "FILES"
 .TP
 .I @ub_conf_file@
index 6842514..ea95bd7 100644 (file)
@@ -1,4 +1,4 @@
-.TH "unbound\-host" "1" "Mar 15, 2018" "NLnet Labs" "unbound 1.7.0"
+.TH "unbound\-host" "1" "Jun 21, 2018" "NLnet Labs" "unbound 1.7.3"
 .\"
 .\" unbound-host.1 -- unbound DNS lookup utility
 .\"
index 3c5786a..5613ce3 100644 (file)
@@ -1,4 +1,4 @@
-.TH "unbound" "8" "Mar 15, 2018" "NLnet Labs" "unbound 1.7.0"
+.TH "unbound" "8" "Jun 21, 2018" "NLnet Labs" "unbound 1.7.3"
 .\"
 .\" unbound.8 -- unbound manual
 .\"
@@ -9,7 +9,7 @@
 .\"
 .SH "NAME"
 .B unbound
-\- Unbound DNS validating resolver 1.7.0.
+\- Unbound DNS validating resolver 1.7.3.
 .SH "SYNOPSIS"
 .B unbound
 .RB [ \-h ]
index ba30f4f..c4b8127 100644 (file)
@@ -1,4 +1,4 @@
-.TH "unbound.conf" "5" "Mar 15, 2018" "NLnet Labs" "unbound 1.7.0"
+.TH "unbound.conf" "5" "Jun 21, 2018" "NLnet Labs" "unbound 1.7.3"
 .\"
 .\" unbound.conf.5 -- unbound.conf manual
 .\"
@@ -252,7 +252,7 @@ silently (unless verbosity 3) without the option.
 .B ip\-transparent: \fI<yes or no>
 If yes, then use IP_TRANSPARENT socket option on sockets where unbound
 is listening for incoming traffic.  Default no.  Allows you to bind to
-non\-local interfaces.  For example for non\-existant IP addresses that
+non\-local interfaces.  For example for non\-existent IP addresses that
 are going to exist later on, with host failover configuration.  This is
 a lot like interface\-automatic, but that one services all interfaces
 and with this option you can select which (future) interfaces unbound
@@ -363,17 +363,19 @@ change anything.  Useful for TLS service providers, that want no udp downstream
 but use udp to fetch data upstream.
 .TP
 .B tls\-upstream: \fI<yes or no>
-Enabled or disable whether the upstream queries use SSL only for transport.
-Default is no.  Useful in tunneling scenarios.  The SSL contains plain DNS in
+Enabled or disable whether the upstream queries use TLS only for transport.
+Default is no.  Useful in tunneling scenarios.  The TLS contains plain DNS in
 TCP wireformat.  The other server must support this (see
 \fBtls\-service\-key\fR).
+If you enable this, also configure a tls\-cert\-bundle or use tls\-win\cert to
+load CA certs, otherwise the connections cannot be authenticated.
 .TP
 .B ssl\-upstream: \fI<yes or no>
 Alternate syntax for \fBtls\-upstream\fR.  If both are present in the config
 file the last is used.
 .TP
 .B tls\-service\-key: \fI<file>
-If enabled, the server provider SSL service on its TCP sockets.  The clients
+If enabled, the server provider TLS service on its TCP sockets.  The clients
 have to use tls\-upstream: yes.  The file is the private key for the TLS
 session.  The public certificate is in the tls\-service\-pem file.  Default
 is "", turned off.  Requires a restart (a reload is not enough) if changed,
@@ -393,8 +395,8 @@ turned off.
 Alternate syntax for \fBtls\-service\-pem\fR.
 .TP
 .B tls\-port: \fI<number>
-The port number on which to provide TCP SSL service, default 853, only
-interfaces configured with that port number as @number get the SSL service.
+The port number on which to provide TCP TLS service, default 853, only
+interfaces configured with that port number as @number get the TLS service.
 .TP
 .B ssl\-port: \fI<number>
 Alternate syntax for \fBtls\-port\fR.
@@ -408,6 +410,17 @@ urls, and also DNS over TLS connections.
 .B ssl\-cert\-bundle: \fI<file>
 Alternate syntax for \fBtls\-cert\-bundle\fR.
 .TP
+.B tls\-win\-cert: \fI<yes or no>
+Add the system certificates to the cert bundle certificates for authentication.
+If no cert bundle, it uses only these certificates.  Default is no.
+On windows this option uses the certificates from the cert store.  Use
+the tls\-cert\-bundle option on other systems.
+.TP
+.B tls\-additional\-port: \fI<portnr>
+List portnumbers as tls\-additional\-port, and when interfaces are defined,
+eg. with the @port suffix, as this port number, they provide dns over TLS
+service.  Can list multiple, each on a new statement.
+.TP
 .B use\-systemd: \fI<yes or no>
 Enable or disable systemd socket activation.
 Default is no.
@@ -420,7 +433,8 @@ Default is yes.
 .B access\-control: \fI<IP netblock> <action>
 The netblock is given as an IP4 or IP6 address with /size appended for a
 classless network block. The action can be \fIdeny\fR, \fIrefuse\fR,
-\fIallow\fR, \fIallow_snoop\fR, \fIdeny_non_local\fR or \fIrefuse_non_local\fR.
+\fIallow\fR, \fIallow_setrd\fR, \fIallow_snoop\fR, \fIdeny_non_local\fR or
+\fIrefuse_non_local\fR.
 The most specific netblock match is used, if none match \fIdeny\fR is used.
 .IP
 The action \fIdeny\fR stops queries from hosts from that netblock.
@@ -439,6 +453,15 @@ in the reply.  This supports normal operations where nonrecursive queries
 are made for the authoritative data.  For nonrecursive queries any replies
 from the dynamic cache are refused.
 .IP
+The \fIallow_setrd\fR action ignores the recursion desired (RD) bit and
+treats all requests as if the recursion desired bit is set.  Note that this
+behavior violates RFC 1034 which states that a name server should never perform
+recursive service unless asked via the RD bit since this interferes with
+trouble shooting of name servers and their databases. This prohibited behavior
+may be useful if another DNS server must forward requests for specific
+zones to a resolver DNS server, but only supports stub domains and
+sends queries to the resolver DNS server with the RD bit cleared.
+.IP
 The action \fIallow_snoop\fR gives nonrecursive access too.  This give
 both recursive and non recursive access.  The name \fIallow_snoop\fR refers
 to cache snooping, a technique to use nonrecursive queries to examine
@@ -641,7 +664,7 @@ infrastructure data.  Validates the replies if trust anchors are configured
 and the zones are signed.  This enforces DNSSEC validation on nameserver
 NS sets and the nameserver addresses that are encountered on the referral
 path to the answer.
-Default off, because it burdens the authority servers, and it is
+Default no, because it burdens the authority servers, and it is
 not RFC standard, and could lead to performance problems because of the
 extra query load that is generated.  Experimental option.
 If you enable it consider adding more numbers after the target\-fetch\-policy
@@ -672,7 +695,7 @@ Send minimum amount of information to upstream servers to enhance privacy.
 Only sent minimum required labels of the QNAME and set QTYPE to A when
 possible. Best effort approach; full QNAME and original QTYPE will be sent when
 upstream replies with a RCODE other than NOERROR, except when receiving
-NXDOMAIN from a DNSSEC signed zone. Default is off.
+NXDOMAIN from a DNSSEC signed zone. Default is yes.
 .TP
 .B qname\-minimisation\-strict: \fI<yes or no>
 QNAME minimisation in strict mode. Do not fall-back to sending full QNAME to
@@ -683,8 +706,8 @@ This option only has effect when qname-minimisation is enabled. Default is off.
 .B aggressive\-nsec: \fI<yes or no>
 Aggressive NSEC uses the DNSSEC NSEC chain to synthesize NXDOMAIN
 and other denials, using information from previous NXDOMAINs answers.
-Default is off.  It helps to reduce the query rate towards targets that get
-a very high nonexistant name lookup rate.
+Default is no.  It helps to reduce the query rate towards targets that get
+a very high nonexistent name lookup rate.
 .TP
 .B private\-address: \fI<IP address or subnet>
 Give IPv4 of IPv6 addresses or classless subnets. These are addresses
@@ -799,6 +822,9 @@ expanded on start and on reload.
 .B trust\-anchor\-signaling: \fI<yes or no>
 Send RFC8145 key tag query after trust anchor priming. Default is off.
 .TP
+.B root\-key\-sentinel: \fI<yes or no>
+Root key trust anchor sentinel. Default is on.
+.TP
 .B dlv\-anchor\-file: \fI<filename>
 This option was used during early days DNSSEC deployment when no parent-side
 DS record registrations were easily available.  Nowadays, it is best to have
@@ -1259,13 +1285,30 @@ to complete.  Default is 10, allowing 1/10 traffic to flow normally.
 This can make ordinary queries complete (if repeatedly queried for),
 and enter the cache, whilst also mitigating the traffic flow by the
 factor given.
+.TP 5
+.B low\-rtt: \fI<msec time>
+Set the time in millisecond that is considere a low ping time for fast
+server selection with the low\-rtt\-permil option, that turns this on or off.
+The default is 45 msec, a number from IPv6 quick response documents.
+.TP 5
+.B low\-rtt\-permil: \fI<number>
+Specify how many times out of 1000 to pick the fast server from the low
+rtt band.  0 turns the feature off.  A value of 900 would pick the fast
+server when such fast servers are available 90 percent of the time, and
+the remaining time perform normal exploration of random servers.
+When prefetch is enabled (or serve\-expired), such prefetches are not
+sped up, because there is no one waiting for it, and it presents a good
+moment to perform server exploration.  The low\-rtt option can be used
+to specify which servers are picked for fast server selection, servers
+with a ping roundtrip time below that value are considered.
+The default for low\-rtt\-permil is 0.
 .SS "Remote Control Options"
 In the
 .B remote\-control:
 clause are the declarations for the remote control facility.  If this is
 enabled, the \fIunbound\-control\fR(8) utility can be used to send
 commands to the running unbound server.  The server uses these clauses
-to setup SSLv3 / TLSv1 security for the connection.  The
+to setup TLSv1 security for the connection.  The
 \fIunbound\-control\fR(8) utility also reads the \fBremote\-control\fR
 section for options.  To setup the correct self\-signed certificates use the
 \fIunbound\-control\-setup\fR(8) utility.
@@ -1281,6 +1324,14 @@ By default localhost (127.0.0.1 and ::1) is listened to.
 Use 0.0.0.0 and ::0 to listen to all interfaces.
 If you change this and permissions have been dropped, you must restart
 the server for the change to take effect.
+.IP
+If you set it to an absolute path, a local socket is used.  The local socket
+does not use the certificates and keys, so those files need not be present.
+To restrict access, unbound sets permissions on the file to the user and
+group that is configured, the access bits are set to allow the group members
+to access the control socket file.  Put users that need to access the socket
+in the that group.  To restrict access further, create a directory to put
+the control socket in and restrict access to that directory.
 .TP 5
 .B control\-port: \fI<port number>
 The port number to listen on for IPv4 or IPv6 control interfaces,
@@ -1289,11 +1340,9 @@ If you change this and permissions have been dropped, you must restart
 the server for the change to take effect.
 .TP 5
 .B control\-use\-cert: \fI<yes or no>
-Whether to require certificate authentication of control connections.
-The default is "yes".
-This should not be changed unless there are other mechanisms in place
-to prevent untrusted users from accessing the remote control
-interface.
+For localhost control-interface you can disable the use of TLS by setting
+this option to "no", default is "yes".  For local sockets, TLS is disabled
+and the value of this option is ignored.
 .TP 5
 .B server\-key\-file: \fI<private key file>
 Path to the server private key, by default unbound_server.key.
@@ -1359,7 +1408,7 @@ IP address of stub zone nameserver. Can be IP 4 or IP 6.
 To use a nondefault port for DNS communication append '@' with the port number.
 .TP
 .B stub\-prime: \fI<yes or no>
-This option is by default off.  If enabled it performs NS set priming,
+This option is by default no.  If enabled it performs NS set priming,
 which is similar to root hints, where it starts using the list of nameservers
 currently published by the zone.  Thus, if the hint list is slightly outdated,
 the resolver picks up a correct list online.
@@ -1371,7 +1420,7 @@ the servers are unreachable, instead it is tried without this clause.
 The default is no.
 .TP
 .B stub\-tls\-upstream: \fI<yes or no>
-Enabled or disable whether the queries to this stub use SSL for transport.
+Enabled or disable whether the queries to this stub use TLS for transport.
 Default is no.
 .TP
 .B stub\-ssl\-upstream: \fI<yes or no>
@@ -1403,6 +1452,13 @@ Name of server to forward to. Is itself resolved before it is used.
 .B forward\-addr: \fI<IP address>
 IP address of server to forward to. Can be IP 4 or IP 6.
 To use a nondefault port for DNS communication append '@' with the port number.
+If tls is enabled, then you can append a '#' and a name, then it'll check
+the tls authentication certificates with that name.  If you combine
+the '@' and '#', the '@' comes first.
+.IP
+At high verbosity it logs the TLS certificate, with TLS enabled.
+If you leave out the '#' and auth name from the forward\-addr, any
+name is accepted.  The cert must also match a CA from the tls\-cert\-bundle.
 .TP
 .B forward\-first: \fI<yes or no>
 If enabled, a query is attempted without the forward clause if it fails.
@@ -1411,8 +1467,10 @@ the servers are unreachable, instead it is tried without this clause.
 The default is no.
 .TP
 .B forward\-tls\-upstream: \fI<yes or no>
-Enabled or disable whether the queries to this forwarder use SSL for transport.
+Enabled or disable whether the queries to this forwarder use TLS for transport.
 Default is no.
+If you enable this, also configure a tls\-cert\-bundle or use tls\-win\cert to
+load CA certs, otherwise the connections cannot be authenticated.
 .TP
 .B forward\-ssl\-upstream: \fI<yes or no>
 Alternate syntax for \fBforward\-tls\-upstream\fR.
@@ -1451,6 +1509,14 @@ 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 fallback\-enabled: \fI<yes or no>
 Default no.  If enabled, unbound falls back to querying the internet as
 a resolver for this zone when lookups fail.  For example for DNSSEC
@@ -1736,15 +1802,42 @@ If it finds a valid answer in the backend, Unbound uses it to respond
 to the query without performing iterative DNS resolution.
 If Unbound cannot even find an answer in the backend, it resolves the
 query as usual, and stores the answer in the backend.
+.P
+If Unbound was built with
+\fB\-\-with\-libhiredis\fR
+on a system that has installed the hiredis C client library of Redis,
+then the "redis" backend can be used.
+This backend communicates with the specified Redis server over a TCP
+connection to store and retrieve cache data.
+It can be used as a persistent and/or shared cache backend.
+It should be noted that Unbound never removes data stored in the Redis server,
+even if some data have expired in terms of DNS TTL or the Redis server has
+cached too much data;
+if necessary the Redis server must be configured to limit the cache size,
+preferably with some kind of least-recently-used eviction policy.
+This backend uses synchronous communication with the Redis server
+based on the assumption that the communication is stable and sufficiently
+fast.
+The thread waiting for a response from the Redis server cannot handle
+other DNS queries.
+Although the backend has the ability to reconnect to the server when
+the connection is closed unexpectedly and there is a configurable timeout
+in case the server is overly slow or hangs up, these cases are assumed
+to be very rare.
+If connection close or timeout happens too often, Unbound will be
+effectively unusable with this backend.
+It's the administrator's responsibility to make the assumption hold.
+.P
 The
 .B cachedb:
 clause gives custom settings of the cache DB module.
 .TP
 .B backend: \fI<backend name>\fR
 Specify the backend database name.
-Currently, only the in-memory "testframe" backend is supported.
-As the name suggests this backend is not of any practical use.
-This option defaults to "testframe".
+The default database is the in-memory backend named "testframe", which,
+as the name suggests, is not of any practical use.
+Depending on the build-time configuration, "redis" backend may also be
+used as described above.
 .TP
 .B secret-seed: \fI<"secret string">\fR
 Specify a seed to calculate a hash value from query information.
@@ -1754,6 +1847,28 @@ operationally.
 If the backend database is shared by multiple Unbound instances,
 all instances must use the same secret seed.
 This option defaults to "default".
+.P
+The following
+.B cachedb
+otions are specific to the redis backend.
+.TP
+.B redis-server-host: \fI<server address or name>\fR
+The IP (either v6 or v4) address or domain name of the Redis server.
+In general an IP address should be specified as otherwise Unbound will have to
+resolve the name of the server every time it establishes a connection
+to the server.
+This option defaults to "127.0.0.1".
+.TP
+.B redis-server-port: \fI<port number>\fR
+The TCP port number of the Redis server.
+This option defaults to 6379.
+.TP
+.B redis-timeout: \fI<msec>\fR
+The period until when Unbound waits for a response from the Redis sever.
+If this timeout expires Unbound closes the connection, treats it as
+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.
 .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 ecf88b2..f88b3e1 100644 (file)
@@ -84,7 +84,7 @@ struct delegpt* delegpt_copy(struct delegpt* dp, struct regional* region)
        }
        for(a = dp->target_list; a; a = a->next_target) {
                if(!delegpt_add_addr(copy, region, &a->addr, a->addrlen, 
-                       a->bogus, a->lame))
+                       a->bogus, a->lame, a->tls_auth_name))
                        return NULL;
        }
        return copy;
@@ -176,13 +176,13 @@ delegpt_add_target(struct delegpt* dp, struct regional* region,
                if(ns->got4 && ns->got6)
                        ns->resolved = 1;
        }
-       return delegpt_add_addr(dp, region, addr, addrlen, bogus, lame);
+       return delegpt_add_addr(dp, region, addr, addrlen, bogus, lame, NULL);
 }
 
 int 
 delegpt_add_addr(struct delegpt* dp, struct regional* region, 
        struct sockaddr_storage* addr, socklen_t addrlen, uint8_t bogus, 
-       uint8_t lame)
+       uint8_t lame, char* tls_auth_name)
 {
        struct delegpt_addr* a;
        log_assert(!dp->dp_type_mlc);
@@ -210,6 +210,13 @@ delegpt_add_addr(struct delegpt* dp, struct regional* region,
        a->bogus = bogus;
        a->lame = lame;
        a->dnsseclame = 0;
+       if(tls_auth_name) {
+               a->tls_auth_name = regional_strdup(region, tls_auth_name);
+               if(!a->tls_auth_name)
+                       return 0;
+       } else {
+               a->tls_auth_name = NULL;
+       }
        return 1;
 }
 
@@ -276,11 +283,16 @@ void delegpt_log(enum verbosity_value v, struct delegpt* dp)
                        (ns->done_pside6?" PSIDE_AAAA":""));
                }
                for(a = dp->target_list; a; a = a->next_target) {
+                       char s[128];
                        const char* str = "  ";
                        if(a->bogus && a->lame) str = "  BOGUS ADDR_LAME ";
                        else if(a->bogus) str = "  BOGUS ";
                        else if(a->lame) str = "  ADDR_LAME ";
-                       log_addr(VERB_ALGO, str, &a->addr, a->addrlen);
+                       if(a->tls_auth_name)
+                               snprintf(s, sizeof(s), "%s[%s]", str,
+                                       a->tls_auth_name);
+                       else snprintf(s, sizeof(s), "%s", str);
+                       log_addr(VERB_ALGO, s, &a->addr, a->addrlen);
                }
        }
 }
@@ -539,6 +551,7 @@ void delegpt_free_mlc(struct delegpt* dp)
        a = dp->target_list;
        while(a) {
                na = a->next_target;
+               free(a->tls_auth_name);
                free(a);
                a = na;
        }
@@ -585,7 +598,7 @@ int delegpt_add_ns_mlc(struct delegpt* dp, uint8_t* name, uint8_t lame)
 }
 
 int delegpt_add_addr_mlc(struct delegpt* dp, struct sockaddr_storage* addr,
-       socklen_t addrlen, uint8_t bogus, uint8_t lame)
+       socklen_t addrlen, uint8_t bogus, uint8_t lame, char* tls_auth_name)
 {
        struct delegpt_addr* a;
        log_assert(dp->dp_type_mlc);
@@ -612,6 +625,15 @@ int delegpt_add_addr_mlc(struct delegpt* dp, struct sockaddr_storage* addr,
        a->bogus = bogus;
        a->lame = lame;
        a->dnsseclame = 0;
+       if(tls_auth_name) {
+               a->tls_auth_name = strdup(tls_auth_name);
+               if(!a->tls_auth_name) {
+                       free(a);
+                       return 0;
+               }
+       } else {
+               a->tls_auth_name = NULL;
+       }
        return 1;
 }
 
@@ -632,7 +654,7 @@ int delegpt_add_target_mlc(struct delegpt* dp, uint8_t* name, size_t namelen,
                if(ns->got4 && ns->got6)
                        ns->resolved = 1;
        }
-       return delegpt_add_addr_mlc(dp, addr, addrlen, bogus, lame);
+       return delegpt_add_addr_mlc(dp, addr, addrlen, bogus, lame, NULL);
 }
 
 size_t delegpt_get_mem(struct delegpt* dp)
index 24f0574..354bd61 100644 (file)
@@ -151,6 +151,8 @@ struct delegpt_addr {
         * option is useful to mark the address dnsseclame.
         * This value is not copied in addr-copy and dp-copy. */
        uint8_t dnsseclame;
+       /** the TLS authentication name, (if not NULL) to use. */
+       char* tls_auth_name;
 };
 
 /**
@@ -259,11 +261,12 @@ int delegpt_add_rrset(struct delegpt* dp, struct regional* regional,
  * @param addrlen: the length of addr.
  * @param bogus: if address is bogus.
  * @param lame: if address is lame.
+ * @param tls_auth_name: TLS authentication name (or NULL).
  * @return false on error.
  */
 int delegpt_add_addr(struct delegpt* dp, struct regional* regional, 
        struct sockaddr_storage* addr, socklen_t addrlen,
-       uint8_t bogus, uint8_t lame);
+       uint8_t bogus, uint8_t lame, char* tls_auth_name);
 
 /** 
  * Find NS record in name list of delegation point.
@@ -394,10 +397,11 @@ int delegpt_add_ns_mlc(struct delegpt* dp, uint8_t* name, uint8_t lame);
  * @param addrlen: the length of addr.
  * @param bogus: if address is bogus.
  * @param lame: if address is lame.
+ * @param tls_auth_name: TLS authentication name (or NULL).
  * @return false on error.
  */
 int delegpt_add_addr_mlc(struct delegpt* dp, struct sockaddr_storage* addr,
-       socklen_t addrlen, uint8_t bogus, uint8_t lame);
+       socklen_t addrlen, uint8_t bogus, uint8_t lame, char* tls_auth_name);
 
 /**
  * Add target address to the delegation point.
index 0ba6c6d..a44f543 100644 (file)
@@ -231,14 +231,16 @@ read_fwds_addr(struct config_stub* s, struct delegpt* dp)
        struct config_strlist* p;
        struct sockaddr_storage addr;
        socklen_t addrlen;
+       char* tls_auth_name;
        for(p = s->addrs; p; p = p->next) {
                log_assert(p->str);
-               if(!extstrtoaddr(p->str, &addr, &addrlen)) {
+               if(!authextstrtoaddr(p->str, &addr, &addrlen, &tls_auth_name)) {
                        log_err("cannot parse forward %s ip address: '%s'", 
                                s->name, p->str);
                        return 0;
                }
-               if(!delegpt_add_addr_mlc(dp, &addr, addrlen, 0, 0)) {
+               if(!delegpt_add_addr_mlc(dp, &addr, addrlen, 0, 0,
+                       tls_auth_name)) {
                        log_err("out of memory");
                        return 0;
                }
index 1d4c228..e8d0933 100644 (file)
@@ -244,14 +244,16 @@ read_stubs_addr(struct config_stub* s, struct delegpt* dp)
        struct config_strlist* p;
        struct sockaddr_storage addr;
        socklen_t addrlen;
+       char* auth_name;
        for(p = s->addrs; p; p = p->next) {
                log_assert(p->str);
-               if(!extstrtoaddr(p->str, &addr, &addrlen)) {
+               if(!authextstrtoaddr(p->str, &addr, &addrlen, &auth_name)) {
                        log_err("cannot parse stub %s ip address: '%s'", 
                                s->name, p->str);
                        return 0;
                }
-               if(!delegpt_add_addr_mlc(dp, &addr, addrlen, 0, 0)) {
+               if(!delegpt_add_addr_mlc(dp, &addr, addrlen, 0, 0,
+                       auth_name)) {
                        log_err("out of memory");
                        return 0;
                }
index 70cab40..0a8f770 100644 (file)
@@ -312,9 +312,9 @@ static int
 iter_filter_order(struct iter_env* iter_env, struct module_env* env,
        uint8_t* name, size_t namelen, uint16_t qtype, time_t now, 
        struct delegpt* dp, int* selected_rtt, int open_target, 
-       struct sock_list* blacklist)
+       struct sock_list* blacklist, time_t prefetch)
 {
-       int got_num = 0, low_rtt = 0, swap_to_front;
+       int got_num = 0, low_rtt = 0, swap_to_front, rtt_band = RTT_BAND;
        struct delegpt_addr* a, *n, *prev=NULL;
 
        /* fillup sel_rtt and find best rtt in the bunch */
@@ -329,6 +329,16 @@ iter_filter_order(struct iter_env* iter_env, struct module_env* env,
                             return 0 to force the caller to fetch more */
        }
 
+       if(env->cfg->low_rtt_permil != 0 && prefetch == 0 &&
+               low_rtt < env->cfg->low_rtt &&
+               ub_random_max(env->rnd, 1000) < env->cfg->low_rtt_permil) {
+               /* the query is not prefetch, but for a downstream client,
+                * there is a low_rtt (fast) server.  We choose that x% of the
+                * time */
+               /* pick rtt numbers from 0..LOWBAND_RTT */
+               rtt_band = env->cfg->low_rtt - low_rtt;
+       }
+
        got_num = 0;
        a = dp->result_list;
        while(a) {
@@ -340,10 +350,10 @@ iter_filter_order(struct iter_env* iter_env, struct module_env* env,
                }
                /* classify the server address and determine what to do */
                swap_to_front = 0;
-               if(a->sel_rtt >= low_rtt && a->sel_rtt - low_rtt <= RTT_BAND) {
+               if(a->sel_rtt >= low_rtt && a->sel_rtt - low_rtt <= rtt_band) {
                        got_num++;
                        swap_to_front = 1;
-               } else if(a->sel_rtt<low_rtt && low_rtt-a->sel_rtt<=RTT_BAND) {
+               } else if(a->sel_rtt<low_rtt && low_rtt-a->sel_rtt<=rtt_band) {
                        got_num++;
                        swap_to_front = 1;
                }
@@ -400,13 +410,14 @@ struct delegpt_addr*
 iter_server_selection(struct iter_env* iter_env, 
        struct module_env* env, struct delegpt* dp, 
        uint8_t* name, size_t namelen, uint16_t qtype, int* dnssec_lame,
-       int* chase_to_rd, int open_target, struct sock_list* blacklist)
+       int* chase_to_rd, int open_target, struct sock_list* blacklist,
+       time_t prefetch)
 {
        int sel;
        int selrtt;
        struct delegpt_addr* a, *prev;
        int num = iter_filter_order(iter_env, env, name, namelen, qtype,
-               *env->now, dp, &selrtt, open_target, blacklist);
+               *env->now, dp, &selrtt, open_target, blacklist, prefetch);
 
        if(num == 0)
                return NULL;
@@ -625,7 +636,7 @@ iter_dp_is_useless(struct query_info* qinfo, uint16_t qflags,
 }
 
 int
-iter_indicates_dnssec_fwd(struct module_env* env, struct query_info *qinfo)
+iter_qname_indicates_dnssec(struct module_env* env, struct query_info *qinfo)
 {
        struct trust_anchor* a;
        if(!env || !env->anchors || !qinfo || !qinfo->qname)
index 602fa6d..e971d93 100644 (file)
@@ -87,13 +87,18 @@ int iter_apply_cfg(struct iter_env* iter_env, struct config_file* cfg);
  * @param open_target: number of currently outstanding target queries.
  *     If we wait for these, perhaps more server addresses become available.
  * @param blacklist: the IP blacklist to use.
+ * @param prefetch: if not 0, prefetch is in use for this query.
+ *     This means the query can have different timing, because prefetch is
+ *     not waited upon by the downstream client, and thus a good time to
+ *     perform exploration of other targets.
  * @return best target or NULL if no target.
  *     if not null, that target is removed from the result list in the dp.
  */
 struct delegpt_addr* iter_server_selection(struct iter_env* iter_env, 
        struct module_env* env, struct delegpt* dp, uint8_t* name, 
        size_t namelen, uint16_t qtype, int* dnssec_lame,
-       int* chase_to_rd, int open_target, struct sock_list* blacklist);
+       int* chase_to_rd, int open_target, struct sock_list* blacklist,
+       time_t prefetch);
 
 /**
  * Allocate dns_msg from parsed msg, in regional.
@@ -174,15 +179,14 @@ int iter_dp_is_useless(struct query_info* qinfo, uint16_t qflags,
        struct delegpt* dp);
 
 /**
- * See if qname has DNSSEC needs in the forwarding case.  This is true if
- * there is a trust anchor above it.  Whether there is an insecure delegation
- * to the data is unknown, but CD-retry is needed.
+ * See if qname has DNSSEC needs.  This is true if there is a trust anchor above
+ * it.  Whether there is an insecure delegation to the data is unknown.
  * @param env: environment with anchors.
  * @param qinfo: query name and class.
  * @return true if trust anchor above qname, false if no anchor or insecure
  * point above qname.
  */
-int iter_indicates_dnssec_fwd(struct module_env* env,
+int iter_qname_indicates_dnssec(struct module_env* env,
        struct query_info *qinfo);
 
 /**
index 7f3c657..58a9bff 100644 (file)
@@ -536,7 +536,7 @@ handle_cname_response(struct module_qstate* qstate, struct iter_qstate* iq,
 /** see if last resort is possible - does config allow queries to parent */
 static int
 can_have_last_resort(struct module_env* env, uint8_t* nm, size_t nmlen,
-       uint16_t qclass)
+       uint16_t qclass, struct delegpt** retdp)
 {
        struct delegpt* fwddp;
        struct iter_hints_stub* stub;
@@ -549,12 +549,14 @@ can_have_last_resort(struct module_env* env, uint8_t* nm, size_t nmlen,
                /* has_parent side is turned off for stub_first, where we
                 * are allowed to go to the parent */
                stub->dp->has_parent_side_NS) {
+               if(retdp) *retdp = stub->dp;
                return 0;
        }
        if((fwddp = forwards_find(env->fwds, nm, qclass)) &&
                /* has_parent_side is turned off for forward_first, where
                 * we are allowed to go to the parent */
                fwddp->has_parent_side_NS) {
+               if(retdp) *retdp = fwddp;
                return 0;
        }
        return 1;
@@ -1000,7 +1002,7 @@ generate_ns_check(struct module_qstate* qstate, struct iter_qstate* iq, int id)
        if(iq->depth == ie->max_dependency_depth)
                return;
        if(!can_have_last_resort(qstate->env, iq->dp->name, iq->dp->namelen,
-               iq->qchase.qclass))
+               iq->qchase.qclass, NULL))
                return;
        /* is this query the same as the nscheck? */
        if(qstate->qinfo.qtype == LDNS_RR_TYPE_NS &&
@@ -1184,10 +1186,8 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
         */
        if (iq->refetch_glue &&
                iq->dp &&
-               !can_have_last_resort(qstate->env,
-                                     iq->dp->name,
-                                     iq->dp->namelen,
-                                     iq->qchase.qclass)) {
+               !can_have_last_resort(qstate->env, iq->dp->name,
+                    iq->dp->namelen, iq->qchase.qclass, NULL)) {
            iq->refetch_glue = 0;
        }
 
@@ -1206,7 +1206,8 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
                        iq->qchase.qname_len, iq->qchase.qtype, 
                        iq->qchase.qclass, qstate->query_flags,
                        qstate->region, qstate->env->scratch, 0);
-               if(!msg && qstate->env->neg_cache) {
+               if(!msg && qstate->env->neg_cache &&
+                       iter_qname_indicates_dnssec(qstate->env, &iq->qchase)) {
                        /* lookup in negative cache; may result in
                         * NOERROR/NODATA or NXDOMAIN answers that need validation */
                        msg = val_neg_getmsg(qstate->env->neg_cache, &iq->qchase,
@@ -1298,7 +1299,8 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
                delnamelen = iq->qchase.qname_len;
        }
        if(iq->qchase.qtype == LDNS_RR_TYPE_DS || iq->refetch_glue ||
-          (iq->qchase.qtype == LDNS_RR_TYPE_NS && qstate->prefetch_leeway)) {
+          (iq->qchase.qtype == LDNS_RR_TYPE_NS && qstate->prefetch_leeway
+          && can_have_last_resort(qstate->env, delname, delnamelen, iq->qchase.qclass, NULL))) {
                /* remove first label from delname, root goes to hints,
                 * but only to fetch glue, not for qtype=DS. */
                /* also when prefetching an NS record, fetch it again from
@@ -1414,6 +1416,28 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
                 */
                if(iter_dp_is_useless(&qstate->qinfo, qstate->query_flags, 
                        iq->dp)) {
+                       struct delegpt* retdp = NULL;
+                       if(!can_have_last_resort(qstate->env, iq->dp->name, iq->dp->namelen, iq->qchase.qclass, &retdp)) {
+                               if(retdp) {
+                                       verbose(VERB_QUERY, "cache has stub "
+                                               "or fwd but no addresses, "
+                                               "fallback to config");
+                                       iq->dp = delegpt_copy(retdp,
+                                               qstate->region);
+                                       if(!iq->dp) {
+                                               log_err("out of memory in "
+                                                       "stub/fwd fallback");
+                                               return error_response(qstate,
+                                                   id, LDNS_RCODE_SERVFAIL);
+                                       }
+                                       break;
+                               }
+                               verbose(VERB_ALGO, "useless dp "
+                                       "but cannot go up, servfail");
+                               delegpt_log(VERB_ALGO, iq->dp);
+                               return error_response(qstate, id, 
+                                       LDNS_RCODE_SERVFAIL);
+                       }
                        if(dname_is_root(iq->dp->name)) {
                                /* use safety belt */
                                verbose(VERB_QUERY, "Cache has root NS but "
@@ -1771,7 +1795,7 @@ processLastResort(struct module_qstate* qstate, struct iter_qstate* iq,
        log_assert(iq->dp);
 
        if(!can_have_last_resort(qstate->env, iq->dp->name, iq->dp->namelen,
-               iq->qchase.qclass)) {
+               iq->qchase.qclass, NULL)) {
                /* fail -- no more targets, no more hope of targets, no hope 
                 * of a response. */
                verbose(VERB_QUERY, "configured stub or forward servers failed -- returning SERVFAIL");
@@ -1791,7 +1815,7 @@ processLastResort(struct module_qstate* qstate, struct iter_qstate* iq,
                        for(a = p->target_list; a; a=a->next_target) {
                                (void)delegpt_add_addr(iq->dp, qstate->region,
                                        &a->addr, a->addrlen, a->bogus,
-                                       a->lame);
+                                       a->lame, a->tls_auth_name);
                        }
                }
                iq->dp->has_parent_side_NS = 1;
@@ -1864,7 +1888,7 @@ processLastResort(struct module_qstate* qstate, struct iter_qstate* iq,
                if( ((ie->supports_ipv6 && !ns->done_pside6) ||
                    (ie->supports_ipv4 && !ns->done_pside4)) &&
                    !can_have_last_resort(qstate->env, ns->name, ns->namelen,
-                       iq->qchase.qclass)) {
+                       iq->qchase.qclass, NULL)) {
                        log_nametypeclass(VERB_ALGO, "cannot pside lookup ns "
                                "because it is also a stub/forward,",
                                ns->name, LDNS_RR_TYPE_NS, iq->qchase.qclass);
@@ -2160,11 +2184,18 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
                        log_dns_msg("msg from auth zone",
                                &iq->response->qinfo, iq->response->rep);
                }
-               iq->num_current_queries++;
-               iq->chase_to_rd = 0;
-               iq->dnssec_lame_query = 0;
-               iq->auth_zone_response = 1;
-               return next_state(iq, QUERY_RESP_STATE);
+               if((iq->chase_flags&BIT_RD) && !(iq->response->rep->flags&BIT_AA)) {
+                       verbose(VERB_ALGO, "forwarder, ignoring referral from auth zone");
+               } else {
+                       lock_rw_wrlock(&qstate->env->auth_zones->lock);
+                       qstate->env->auth_zones->num_query_up++;
+                       lock_rw_unlock(&qstate->env->auth_zones->lock);
+                       iq->num_current_queries++;
+                       iq->chase_to_rd = 0;
+                       iq->dnssec_lame_query = 0;
+                       iq->auth_zone_response = 1;
+                       return next_state(iq, QUERY_RESP_STATE);
+               }
        }
        iq->auth_zone_response = 0;
        if(auth_fallback == 0) {
@@ -2253,7 +2284,8 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
        target = iter_server_selection(ie, qstate->env, iq->dp, 
                iq->dp->name, iq->dp->namelen, iq->qchase.qtype,
                &iq->dnssec_lame_query, &iq->chase_to_rd, 
-               iq->num_target_queries, qstate->blacklist);
+               iq->num_target_queries, qstate->blacklist,
+               qstate->prefetch_leeway);
 
        /* If no usable target was selected... */
        if(!target) {
@@ -2366,12 +2398,13 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
                 * (blacklist nonempty) and no trust-anchors are configured
                 * above the qname or on the first attempt when dnssec is on */
                EDNS_DO| ((iq->chase_to_rd||(iq->chase_flags&BIT_RD)!=0)&&
-               !qstate->blacklist&&(!iter_indicates_dnssec_fwd(qstate->env,
+               !qstate->blacklist&&(!iter_qname_indicates_dnssec(qstate->env,
                &iq->qinfo_out)||target->attempts==1)?0:BIT_CD), 
                iq->dnssec_expected, iq->caps_fallback || is_caps_whitelisted(
                ie, iq), &target->addr, target->addrlen,
                iq->dp->name, iq->dp->namelen,
-               (iq->dp->ssl_upstream || qstate->env->cfg->ssl_upstream), qstate);
+               (iq->dp->ssl_upstream || qstate->env->cfg->ssl_upstream),
+               target->tls_auth_name, qstate);
        if(!outq) {
                log_addr(VERB_DETAIL, "error sending query to auth server", 
                        &target->addr, target->addrlen);
@@ -2440,9 +2473,10 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
        }
        type = response_type_from_server(
                (int)((iq->chase_flags&BIT_RD) || iq->chase_to_rd),
-               iq->response, &iq->qchase, iq->dp);
+               iq->response, &iq->qinfo_out, iq->dp);
        iq->chase_to_rd = 0;
-       if(type == RESPONSE_TYPE_REFERRAL && (iq->chase_flags&BIT_RD)) {
+       if(type == RESPONSE_TYPE_REFERRAL && (iq->chase_flags&BIT_RD) &&
+               !iq->auth_zone_response) {
                /* When forwarding (RD bit is set), we handle referrals 
                 * differently. No queries should be sent elsewhere */
                type = RESPONSE_TYPE_ANSWER;
@@ -2736,16 +2770,18 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
                /* set the current request's qname to the new value. */
                iq->qchase.qname = sname;
                iq->qchase.qname_len = snamelen;
-               if (qstate->env->cfg->qname_minimisation)
-                       iq->minimisation_state = INIT_MINIMISE_STATE;
                /* Clear the query state, since this is a query restart. */
                iq->deleg_msg = NULL;
                iq->dp = NULL;
                iq->dsns_point = NULL;
                iq->auth_zone_response = 0;
-               /* Note the query restart. */
-               iq->query_restart_count++;
                iq->sent_count = 0;
+               if(iq->minimisation_state != MINIMISE_STATE)
+                       /* Only count as query restart when it is not an extra
+                        * query as result of qname minimisation. */
+                       iq->query_restart_count++;
+               if(qstate->env->cfg->qname_minimisation)
+                       iq->minimisation_state = INIT_MINIMISE_STATE;
 
                /* stop current outstanding queries. 
                 * FIXME: should the outstanding queries be waited for and
index 8bff713..6ac8086 100644 (file)
@@ -130,7 +130,7 @@ find_id(struct ub_ctx* ctx, int* id)
 
 struct ctx_query* 
 context_new(struct ub_ctx* ctx, const char* name, int rrtype, int rrclass, 
-       ub_callback_type cb, void* cbarg)
+       ub_callback_type cb, ub_event_callback_type cb_event, void* cbarg)
 {
        struct ctx_query* q = (struct ctx_query*)calloc(1, sizeof(*q));
        if(!q) return NULL;
@@ -142,8 +142,9 @@ context_new(struct ub_ctx* ctx, const char* name, int rrtype, int rrclass,
        }
        lock_basic_unlock(&ctx->cfglock);
        q->node.key = &q->querynum;
-       q->async = (cb != NULL);
+       q->async = (cb != NULL || cb_event != NULL);
        q->cb = cb;
+       q->cb_event = cb_event;
        q->cb_arg = cbarg;
        q->res = (struct ub_result*)calloc(1, sizeof(*q->res));
        if(!q->res) {
index 684d11e..1114722 100644 (file)
@@ -45,6 +45,7 @@
 #include "util/rbtree.h"
 #include "services/modstack.h"
 #include "libunbound/unbound.h"
+#include "libunbound/unbound-event.h"
 #include "util/data/packed_rrset.h"
 struct libworker;
 struct tube;
@@ -148,8 +149,10 @@ struct ctx_query {
        /** was this query cancelled (for bg worker) */
        int cancelled;
 
-       /** for async query, the callback function */
+       /** for async query, the callback function of type ub_callback_type */
        ub_callback_type cb;
+       /** for event callbacks the type is ub_event_callback_type */
+        ub_event_callback_type cb_event;
        /** for async query, the callback user arg */
        void* cb_arg;
 
@@ -238,11 +241,13 @@ void context_query_delete(struct ctx_query* q);
  * @param rrtype: type
  * @param rrclass: class
  * @param cb: callback for async, or NULL for sync.
+ * @param cb_event: event callback for async, or NULL for sync.
  * @param cbarg: user arg for async queries.
  * @return new ctx_query or NULL for malloc failure.
  */
 struct ctx_query* context_new(struct ub_ctx* ctx, const char* name, int rrtype,
-        int rrclass, ub_callback_type cb, void* cbarg);
+        int rrclass,  ub_callback_type cb, ub_event_callback_type cb_event,
+       void* cbarg);
 
 /**
  * Get a new alloc. Creates a new one or uses a cached one.
index b4cd7fa..275e8d2 100644 (file)
@@ -690,7 +690,7 @@ ub_resolve(struct ub_ctx* ctx, const char* name, int rrtype,
        }
        /* create new ctx_query and attempt to add to the list */
        lock_basic_unlock(&ctx->cfglock);
-       q = context_new(ctx, name, rrtype, rrclass, NULL, NULL);
+       q = context_new(ctx, name, rrtype, rrclass, NULL, NULL, NULL);
        if(!q)
                return UB_NOMEM;
        /* become a resolver thread for a bit */
@@ -747,8 +747,7 @@ ub_resolve_event(struct ub_ctx* ctx, const char* name, int rrtype,
        ub_comm_base_now(ctx->event_worker->base);
 
        /* create new ctx_query and attempt to add to the list */
-       q = context_new(ctx, name, rrtype, rrclass, (ub_callback_type)callback,
-               mydata);
+       q = context_new(ctx, name, rrtype, rrclass, NULL, callback, mydata);
        if(!q)
                return UB_NOMEM;
 
@@ -793,7 +792,7 @@ ub_resolve_async(struct ub_ctx* ctx, const char* name, int rrtype,
        }
 
        /* create new ctx_query and attempt to add to the list */
-       q = context_new(ctx, name, rrtype, rrclass, callback, mydata);
+       q = context_new(ctx, name, rrtype, rrclass, callback, NULL, mydata);
        if(!q)
                return UB_NOMEM;
 
index 2c7b2cf..3dcaa78 100644 (file)
@@ -158,9 +158,9 @@ libworker_setup(struct ub_ctx* ctx, int is_bg, struct ub_event_base* eb)
                hints_delete(w->env->hints);
                w->env->hints = NULL;
        }
-       if(cfg->ssl_upstream) {
+       if(cfg->ssl_upstream || (cfg->tls_cert_bundle && cfg->tls_cert_bundle[0]) || cfg->tls_win_cert) {
                w->sslctx = connect_sslctx_create(NULL, NULL,
-                       cfg->tls_cert_bundle);
+                       cfg->tls_cert_bundle, cfg->tls_win_cert);
                if(!w->sslctx) {
                        /* to make the setup fail after unlock */
                        hints_delete(w->env->hints);
@@ -365,6 +365,7 @@ libworker_dobg(void* arg)
 
        /* cleanup */
        m = UB_LIBCMD_QUIT;
+       w->want_quit = 1;
        tube_remove_bg_listen(w->ctx->qq_pipe);
        tube_remove_bg_write(w->ctx->rr_pipe);
        libworker_delete(w);
@@ -512,7 +513,8 @@ libworker_enter_result(struct ub_result* res, sldns_buffer* buf,
                res->nxdomain = 1;
        if(msg_security == sec_status_secure)
                res->secure = 1;
-       if(msg_security == sec_status_bogus)
+       if(msg_security == sec_status_bogus ||
+               msg_security == sec_status_secure_sentinel_fail)
                res->bogus = 1;
 }
 
@@ -635,7 +637,7 @@ libworker_event_done_cb(void* arg, int rcode, sldns_buffer* buf,
        enum sec_status s, char* why_bogus)
 {
        struct ctx_query* q = (struct ctx_query*)arg;
-       ub_event_callback_type cb = (ub_event_callback_type)q->cb;
+       ub_event_callback_type cb = q->cb_event;
        void* cb_arg = q->cb_arg;
        int cancelled = q->cancelled;
 
@@ -713,6 +715,10 @@ add_bg_result(struct libworker* w, struct ctx_query* q, sldns_buffer* pkt,
        uint8_t* msg = NULL;
        uint32_t len = 0;
 
+       if(w->want_quit) {
+               context_query_delete(q);
+               return;
+       }
        /* serialize and delete unneeded q */
        if(w->is_bg_thread) {
                lock_basic_lock(&w->ctx->cfglock);
@@ -841,7 +847,8 @@ void libworker_alloc_cleanup(void* arg)
 struct outbound_entry* libworker_send_query(struct query_info* qinfo,
        uint16_t flags, int dnssec, int want_dnssec, int nocaps,
        struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* zone,
-       size_t zonelen, int ssl_upstream, struct module_qstate* q)
+       size_t zonelen, int ssl_upstream, char* tls_auth_name,
+       struct module_qstate* q)
 {
        struct libworker* w = (struct libworker*)q->env->worker;
        struct outbound_entry* e = (struct outbound_entry*)regional_alloc(
@@ -851,8 +858,8 @@ struct outbound_entry* libworker_send_query(struct query_info* qinfo,
        e->qstate = q;
        e->qsent = outnet_serviced_query(w->back, qinfo, flags, dnssec,
                want_dnssec, nocaps, q->env->cfg->tcp_upstream, ssl_upstream,
-               addr, addrlen, zone, zonelen, q, libworker_handle_service_reply,
-               e, w->back->udp_buff, q->env);
+               tls_auth_name, addr, addrlen, zone, zonelen, q,
+               libworker_handle_service_reply, e, w->back->udp_buff, q->env);
        if(!e->qsent) {
                return NULL;
        }
@@ -972,7 +979,8 @@ struct outbound_entry* worker_send_query(struct query_info* ATTR_UNUSED(qinfo),
        int ATTR_UNUSED(want_dnssec), int ATTR_UNUSED(nocaps),
        struct sockaddr_storage* ATTR_UNUSED(addr), socklen_t ATTR_UNUSED(addrlen),
        uint8_t* ATTR_UNUSED(zone), size_t ATTR_UNUSED(zonelen),
-       int ATTR_UNUSED(ssl_upstream), struct module_qstate* ATTR_UNUSED(q))
+       int ATTR_UNUSED(ssl_upstream), char* ATTR_UNUSED(tls_auth_name),
+       struct module_qstate* ATTR_UNUSED(q))
 {
        log_assert(0);
        return 0;
index b546e89..42aa5ba 100644 (file)
@@ -75,6 +75,8 @@ struct libworker {
        int is_bg;
        /** is this a bg worker that is threaded (not forked)? */
        int is_bg_thread;
+       /** want to quit, stop handling new content */
+       int want_quit;
 
        /** copy of the module environment with worker local entries. */
        struct module_env* env;
index 1b0f54f..fbd69ca 100644 (file)
@@ -747,6 +747,16 @@ struct ub_server_stats {
        long long num_query_dnscrypt_replay;
        /** number of dnscrypt nonces cache entries */
        long long nonce_cache_count;
+       /** number of queries for unbound's auth_zones, upstream query */
+       long long num_query_authzone_up;
+       /** number of queries for unbound's auth_zones, downstream answers */
+       long long num_query_authzone_down;
+       /** number of times neg cache records were used to generate NOERROR
+        * responses. */
+       long long num_neg_cache_noerror;
+       /** number of times neg cache records were used to generate NXDOMAIN
+        * responses. */
+       long long num_neg_cache_nxdomain;
 };
 
 /** 
index 88e1cf7..7d2ede0 100644 (file)
@@ -63,6 +63,8 @@ struct query_info;
  * @param zone: delegation point name.
  * @param zonelen: length of zone name wireformat dname.
  * @param ssl_upstream: use SSL for upstream queries.
+ * @param tls_auth_name: if ssl_upstream, use this name with TLS
+ *     authentication.
  * @param q: wich query state to reactivate upon return.
  * @return: false on failure (memory or socket related). no query was
  *      sent.
@@ -70,7 +72,8 @@ struct query_info;
 struct outbound_entry* libworker_send_query(struct query_info* qinfo,
        uint16_t flags, int dnssec, int want_dnssec, int nocaps,
        struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* zone,
-       size_t zonelen, int ssl_upstream, struct module_qstate* q);
+       size_t zonelen, int ssl_upstream, char* tls_auth_name,
+       struct module_qstate* q);
 
 /** process incoming replies from the network */
 int libworker_handle_reply(struct comm_point* c, void* arg, int error,
@@ -115,6 +118,8 @@ void worker_sighandler(int sig, void* arg);
  * @param zone: wireformat dname of the zone.
  * @param zonelen: length of zone name.
  * @param ssl_upstream: use SSL for upstream queries.
+ * @param tls_auth_name: if ssl_upstream, use this name with TLS
+ *     authentication.
  * @param q: wich query state to reactivate upon return.
  * @return: false on failure (memory or socket related). no query was
  *      sent.
@@ -122,7 +127,8 @@ void worker_sighandler(int sig, void* arg);
 struct outbound_entry* worker_send_query(struct query_info* qinfo,
        uint16_t flags, int dnssec, int want_dnssec, int nocaps,
        struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* zone,
-       size_t zonelen, int ssl_upstream, struct module_qstate* q);
+       size_t zonelen, int ssl_upstream, char* tls_auth_name,
+       struct module_qstate* q);
 
 /** 
  * process control messages from the main thread. Frees the control 
index fac8e4e..f1ca2a2 100644 (file)
 #define AUTH_HTTP_PORT 80
 /* auth https port number */
 #define AUTH_HTTPS_PORT 443
+/* max depth for nested $INCLUDEs */
+#define MAX_INCLUDE_DEPTH 10
 
 /** pick up nextprobe task to start waiting to perform transfer actions */
 static void xfr_set_timeout(struct auth_xfer* xfr, struct module_env* env,
-       int failure);
+       int failure, int lookup_only);
 /** move to sending the probe packets, next if fails. task_probe */
 static void xfr_probe_send_or_end(struct auth_xfer* xfr,
        struct module_env* env);
+/** pick up probe task with specified(or NULL) destination first,
+ * or transfer task if nothing to probe, or false if already in progress */
+static int xfr_start_probe(struct auth_xfer* xfr, struct module_env* env,
+       struct auth_master* spec);
+/** delete xfer structure (not its tree entry) */
+void auth_xfer_delete(struct auth_xfer* xfr);
 
 /** create new dns_msg */
 static struct dns_msg*
@@ -1437,11 +1445,13 @@ az_remove_rr_decompress(struct auth_zone* z, uint8_t* pkt, size_t pktlen,
  * @param state: parse state with $ORIGIN, $TTL and 'prev-dname' and so on,
  *     that is kept between includes.
  *     The lineno is set at 1 and then increased by the function.
+ * @param fname: file name.
+ * @param depth: recursion depth for includes
  * returns false on failure, has printed an error message
  */
 static int
 az_parse_file(struct auth_zone* z, FILE* in, uint8_t* rr, size_t rrbuflen,
-       struct sldns_file_parse_state* state)
+       struct sldns_file_parse_state* state, char* fname, int depth)
 {
        size_t rr_len, dname_len;
        int status;
@@ -1459,6 +1469,11 @@ az_parse_file(struct auth_zone* z, FILE* in, uint8_t* rr, size_t rrbuflen,
                                FILE* inc;
                                int lineno_orig = state->lineno;
                                char* incfile = (char*)rr + 8;
+                               if(depth > MAX_INCLUDE_DEPTH) {
+                                       log_err("%s:%d max include depth"
+                                         "exceeded", fname, state->lineno);
+                                       return 0;
+                               }
                                /* skip spaces */
                                while(*incfile == ' ' || *incfile == '\t')
                                        incfile++;
@@ -1480,11 +1495,12 @@ az_parse_file(struct auth_zone* z, FILE* in, uint8_t* rr, size_t rrbuflen,
                                }
                                /* recurse read that file now */
                                if(!az_parse_file(z, inc, rr, rrbuflen,
-                                       state)) {
+                                       state, incfile, depth+1)) {
                                        log_err("%s:%d cannot parse include "
-                                               "file %s", z->zonefile,
+                                               "file %s", fname,
                                                lineno_orig, incfile);
                                        fclose(inc);
+                                       free(incfile);
                                        return 0;
                                }
                                fclose(inc);
@@ -1496,7 +1512,7 @@ az_parse_file(struct auth_zone* z, FILE* in, uint8_t* rr, size_t rrbuflen,
                        continue;
                }
                if(status != 0) {
-                       log_err("parse error %s %d:%d: %s", z->zonefile,
+                       log_err("parse error %s %d:%d: %s", fname,
                                state->lineno, LDNS_WIREPARSE_OFFSET(status),
                                sldns_get_errorstr_parse(status));
                        return 0;
@@ -1511,7 +1527,7 @@ az_parse_file(struct auth_zone* z, FILE* in, uint8_t* rr, size_t rrbuflen,
                        sldns_wire2str_type_buf(sldns_wirerr_get_type(rr,
                                rr_len, dname_len), buf, sizeof(buf));
                        log_err("%s:%d cannot insert RR of type %s",
-                               z->zonefile, state->lineno, buf);
+                               fname, state->lineno, buf);
                        return 0;
                }
        }
@@ -1546,6 +1562,11 @@ auth_zone_read_zonefile(struct auth_zone* z)
                free(n);
                return 0;
        }
+
+       /* clear the data tree */
+       traverse_postorder(&z->data, auth_data_del, NULL);
+       rbtree_init(&z->data, &auth_data_cmp);
+
        memset(&state, 0, sizeof(state));
        /* default TTL to 3600 */
        state.default_ttl = 3600;
@@ -1555,7 +1576,7 @@ auth_zone_read_zonefile(struct auth_zone* z)
                state.origin_len = z->namelen;
        }
        /* parse the (toplevel) file */
-       if(!az_parse_file(z, in, rr, sizeof(rr), &state)) {
+       if(!az_parse_file(z, in, rr, sizeof(rr), &state, z->zonefile, 0)) {
                char* n = sldns_wire2str_dname(z->name, z->namelen);
                log_err("error parsing zonefile %s for %s",
                        z->zonefile, n?n:"error");
@@ -1569,9 +1590,9 @@ auth_zone_read_zonefile(struct auth_zone* z)
 
 /** write buffer to file and check return codes */
 static int
-write_out(FILE* out, const char* str)
+write_out(FILE* out, const char* str, size_t len)
 {
-       size_t r, len = strlen(str);
+       size_t r;
        if(len == 0)
                return 1;
        r = fwrite(str, 1, len, out);
@@ -1634,7 +1655,7 @@ auth_zone_write_rrset(struct auth_zone* z, struct auth_data* node,
                        verbose(VERB_ALGO, "failed to rr2str rr %d", (int)i);
                        continue;
                }
-               if(!write_out(out, buf))
+               if(!write_out(out, buf, strlen(buf)))
                        return 0;
        }
        return 1;
@@ -1703,6 +1724,24 @@ auth_zones_read_zones(struct auth_zones* az)
        return 1;
 }
 
+/** find serial number of zone or false if none */
+int
+auth_zone_get_serial(struct auth_zone* z, uint32_t* serial)
+{
+       struct auth_data* apex;
+       struct auth_rrset* soa;
+       struct packed_rrset_data* d;
+       apex = az_find_name(z, z->name, z->namelen);
+       if(!apex) return 0;
+       soa = az_domain_rrset(apex, LDNS_RR_TYPE_SOA);
+       if(!soa || soa->data->count==0)
+               return 0; /* no RRset or no RRs in rrset */
+       if(soa->data->rr_len[0] < 2+4*5) return 0; /* SOA too short */
+       d = soa->data;
+       *serial = sldns_read_uint32(d->rr_data[0]+(d->rr_len[0]-20));
+       return 1;
+}
+
 /** Find auth_zone SOA and populate the values in xfr(soa values). */
 static int
 xfr_find_soa(struct auth_zone* z, struct auth_xfer* xfr)
@@ -1808,6 +1847,7 @@ auth_zones_cfg(struct auth_zones* az, struct config_auth* c)
        lock_rw_unlock(&az->lock);
 
        /* set options */
+       z->zone_deleted = 0;
        if(!auth_zone_set_zonefile(z, c->zonefile)) {
                if(x) {
                        lock_basic_unlock(&x->lock);
@@ -1840,10 +1880,65 @@ auth_zones_cfg(struct auth_zones* az, struct config_auth* c)
        return 1;
 }
 
+/** set all auth zones deleted, then in auth_zones_cfg, it marks them
+ * as nondeleted (if they are still in the config), and then later
+ * we can find deleted zones */
+static void
+az_setall_deleted(struct auth_zones* az)
+{
+       struct auth_zone* z;
+       lock_rw_wrlock(&az->lock);
+       RBTREE_FOR(z, struct auth_zone*, &az->ztree) {
+               lock_rw_wrlock(&z->lock);
+               z->zone_deleted = 1;
+               lock_rw_unlock(&z->lock);
+       }
+       lock_rw_unlock(&az->lock);
+}
+
+/** find zones that are marked deleted and delete them.
+ * This is called from apply_cfg, and there are no threads and no
+ * workers, so the xfr can just be deleted. */
+static void
+az_delete_deleted_zones(struct auth_zones* az)
+{
+       struct auth_zone* z;
+       struct auth_zone* delete_list = NULL, *next;
+       struct auth_xfer* xfr;
+       lock_rw_wrlock(&az->lock);
+       RBTREE_FOR(z, struct auth_zone*, &az->ztree) {
+               lock_rw_wrlock(&z->lock);
+               if(z->zone_deleted) {
+                       /* we cannot alter the rbtree right now, but
+                        * we can put it on a linked list and then
+                        * delete it */
+                       z->delete_next = delete_list;
+                       delete_list = z;
+               }
+               lock_rw_unlock(&z->lock);
+       }
+       /* now we are out of the tree loop and we can loop and delete
+        * the zones */
+       z = delete_list;
+       while(z) {
+               next = z->delete_next;
+               xfr = auth_xfer_find(az, z->name, z->namelen, z->dclass);
+               if(xfr) {
+                       (void)rbtree_delete(&az->xtree, &xfr->node);
+                       auth_xfer_delete(xfr);
+               }
+               (void)rbtree_delete(&az->ztree, &z->node);
+               auth_zone_delete(z);
+               z = next;
+       }
+       lock_rw_unlock(&az->lock);
+}
+
 int auth_zones_apply_cfg(struct auth_zones* az, struct config_file* cfg,
        int setup)
 {
        struct config_auth* p;
+       az_setall_deleted(az);
        for(p = cfg->auths; p; p = p->next) {
                if(!p->name || p->name[0] == 0) {
                        log_warn("auth-zone without a name, skipped");
@@ -1854,6 +1949,7 @@ int auth_zones_apply_cfg(struct auth_zones* az, struct config_file* cfg,
                        return 0;
                }
        }
+       az_delete_deleted_zones(az);
        if(!auth_zones_read_zones(az))
                return 0;
        if(setup) {
@@ -1937,6 +2033,7 @@ auth_xfer_delete(struct auth_xfer* xfr)
                }
                free(xfr->task_transfer);
        }
+       auth_free_masters(xfr->allow_notify_list);
        free(xfr);
 }
 
@@ -3153,10 +3250,13 @@ int auth_zones_answer(struct auth_zones* az, struct module_env* env,
        /* answer it from zone z */
        r = auth_zone_generate_answer(z, qinfo, temp, &msg, &fallback);
        lock_rw_unlock(&z->lock);
-       if(fallback) {
+       if(!r && fallback) {
                /* fallback to regular answering (recursive) */
                return 0;
        }
+       lock_rw_wrlock(&az->lock);
+       az->num_query_down++;
+       lock_rw_unlock(&az->lock);
 
        /* encode answer */
        if(!r)
@@ -3186,6 +3286,190 @@ int auth_zones_can_fallback(struct auth_zones* az, uint8_t* nm, size_t nmlen,
        return r;
 }
 
+int
+auth_zone_parse_notify_serial(sldns_buffer* pkt, uint32_t *serial)
+{
+       struct query_info q;
+       uint16_t rdlen;
+       memset(&q, 0, sizeof(q));
+       sldns_buffer_set_position(pkt, 0);
+       if(!query_info_parse(&q, pkt)) return 0;
+       if(LDNS_ANCOUNT(sldns_buffer_begin(pkt)) == 0) return 0;
+       /* skip name of RR in answer section */
+       if(sldns_buffer_remaining(pkt) < 1) return 0;
+       if(pkt_dname_len(pkt) == 0) return 0;
+       /* check type */
+       if(sldns_buffer_remaining(pkt) < 10 /* type,class,ttl,rdatalen*/)
+               return 0;
+       if(sldns_buffer_read_u16(pkt) != LDNS_RR_TYPE_SOA) return 0;
+       sldns_buffer_skip(pkt, 2); /* class */
+       sldns_buffer_skip(pkt, 4); /* ttl */
+       rdlen = sldns_buffer_read_u16(pkt); /* rdatalen */
+       if(sldns_buffer_remaining(pkt) < rdlen) return 0;
+       if(rdlen < 22) return 0; /* bad soa length */
+       sldns_buffer_skip(pkt, (ssize_t)(rdlen-20));
+       *serial = sldns_buffer_read_u32(pkt);
+       /* return true when has serial in answer section */
+       return 1;
+}
+
+/** see if addr appears in the list */
+static int
+addr_in_list(struct auth_addr* list, struct sockaddr_storage* addr,
+       socklen_t addrlen)
+{
+       struct auth_addr* p;
+       for(p=list; p; p=p->next) {
+               if(sockaddr_cmp_addr(addr, addrlen, &p->addr, p->addrlen)==0)
+                       return 1;
+       }
+       return 0;
+}
+
+/** check if an address matches a master specification (or one of its
+ * addresses in the addr list) */
+static int
+addr_matches_master(struct auth_master* master, struct sockaddr_storage* addr,
+       socklen_t addrlen, struct auth_master** fromhost)
+{
+       struct sockaddr_storage a;
+       socklen_t alen = 0;
+       int net = 0;
+       if(addr_in_list(master->list, addr, addrlen)) {
+               *fromhost = master;
+               return 1;       
+       }
+       /* compare address (but not port number, that is the destination
+        * port of the master, the port number of the received notify is
+        * allowed to by any port on that master) */
+       if(extstrtoaddr(master->host, &a, &alen) &&
+               sockaddr_cmp_addr(addr, addrlen, &a, alen)==0) {
+               *fromhost = master;
+               return 1;
+       }
+       /* prefixes, addr/len, like 10.0.0.0/8 */
+       /* not http and has a / and there is one / */
+       if(master->allow_notify && !master->http &&
+               strchr(master->host, '/') != NULL &&
+               strchr(master->host, '/') == strrchr(master->host, '/') &&
+               netblockstrtoaddr(master->host, UNBOUND_DNS_PORT, &a, &alen,
+               &net) && alen == addrlen) {
+               if(addr_in_common(addr, (addr_is_ip6(addr, addrlen)?128:32),
+                       &a, net, alen) >= net) {
+                       *fromhost = NULL; /* prefix does not have destination
+                               to send the probe or transfer with */
+                       return 1; /* matches the netblock */
+               }
+       }
+       return 0;
+}
+
+/** check access list for notifies */
+static int
+az_xfr_allowed_notify(struct auth_xfer* xfr, struct sockaddr_storage* addr,
+       socklen_t addrlen, struct auth_master** fromhost)
+{
+       struct auth_master* p;
+       for(p=xfr->allow_notify_list; p; p=p->next) {
+               if(addr_matches_master(p, addr, addrlen, fromhost)) {
+                       return 1;
+               }
+       }
+       return 0;
+}
+
+/** see if the serial means the zone has to be updated, i.e. the serial
+ * is newer than the zone serial, or we have no zone */
+static int
+xfr_serial_means_update(struct auth_xfer* xfr, uint32_t serial)
+{
+       if(!xfr->have_zone)
+               return 1; /* no zone, anything is better */
+       if(xfr->zone_expired)
+               return 1; /* expired, the sent serial is better than expired
+                       data */
+       if(compare_serial(xfr->serial, serial) < 0)
+               return 1; /* our serial is smaller than the sent serial,
+                       the data is newer, fetch it */
+       return 0;
+}
+
+/** note notify serial, updates the notify information in the xfr struct */
+static void
+xfr_note_notify_serial(struct auth_xfer* xfr, int has_serial, uint32_t serial)
+{
+       if(xfr->notify_received && xfr->notify_has_serial && has_serial) {
+               /* see if this serial is newer */
+               if(compare_serial(xfr->notify_serial, serial) < 0)
+                       xfr->notify_serial = serial;
+       } else if(xfr->notify_received && xfr->notify_has_serial &&
+               !has_serial) {
+               /* remove serial, we have notify without serial */
+               xfr->notify_has_serial = 0;
+               xfr->notify_serial = 0;
+       } else if(xfr->notify_received && !xfr->notify_has_serial) {
+               /* we already have notify without serial, keep it
+                * that way; no serial check when current operation
+                * is done */
+       } else {
+               xfr->notify_received = 1;
+               xfr->notify_has_serial = has_serial;
+               xfr->notify_serial = serial;
+       }
+}
+
+/** process a notify serial, start new probe or note serial. xfr is locked */
+static void
+xfr_process_notify(struct auth_xfer* xfr, struct module_env* env,
+       int has_serial, uint32_t serial, struct auth_master* fromhost)
+{
+       /* if the serial of notify is older than we have, don't fetch
+        * a zone, we already have it */
+       if(has_serial && !xfr_serial_means_update(xfr, serial)) {
+               lock_basic_unlock(&xfr->lock);
+               return;
+       }
+       /* start new probe with this addr src, or note serial */
+       if(!xfr_start_probe(xfr, env, fromhost)) {
+               /* not started because already in progress, note the serial */
+               xfr_note_notify_serial(xfr, has_serial, serial);
+               lock_basic_unlock(&xfr->lock);
+       }
+       /* successful end of start_probe unlocked xfr->lock */
+}
+
+int auth_zones_notify(struct auth_zones* az, struct module_env* env,
+       uint8_t* nm, size_t nmlen, uint16_t dclass,
+       struct sockaddr_storage* addr, socklen_t addrlen, int has_serial,
+       uint32_t serial, int* refused)
+{
+       struct auth_xfer* xfr;
+       struct auth_master* fromhost = NULL;
+       /* see which zone this is */
+       lock_rw_rdlock(&az->lock);
+       xfr = auth_xfer_find(az, nm, nmlen, dclass);
+       if(!xfr) {
+               lock_rw_unlock(&az->lock);
+               /* no such zone, refuse the notify */
+               *refused = 1;
+               return 0;
+       }
+       lock_basic_lock(&xfr->lock);
+       lock_rw_unlock(&az->lock);
+       
+       /* check access list for notifies */
+       if(!az_xfr_allowed_notify(xfr, addr, addrlen, &fromhost)) {
+               lock_basic_unlock(&xfr->lock);
+               /* notify not allowed, refuse the notify */
+               *refused = 1;
+               return 0;
+       }
+
+       /* process the notify */
+       xfr_process_notify(xfr, env, has_serial, serial, fromhost);
+       return 1;
+}
+
 /** set a zone expired */
 static void
 auth_xfer_set_expired(struct auth_xfer* xfr, struct module_env* env,
@@ -3239,6 +3523,93 @@ xfr_masterlist_free_addrs(struct auth_master* list)
        }
 }
 
+/** copy a list of auth_addrs */
+static struct auth_addr*
+auth_addr_list_copy(struct auth_addr* source)
+{
+       struct auth_addr* list = NULL, *last = NULL;
+       struct auth_addr* p;
+       for(p=source; p; p=p->next) {
+               struct auth_addr* a = (struct auth_addr*)memdup(p, sizeof(*p));
+               if(!a) {
+                       log_err("malloc failure");
+                       auth_free_master_addrs(list);
+                       return NULL;
+               }
+               a->next = NULL;
+               if(last) last->next = a;
+               if(!list) list = a;
+               last = a;
+       }
+       return list;
+}
+
+/** copy a master to a new structure, NULL on alloc failure */
+static struct auth_master*
+auth_master_copy(struct auth_master* o)
+{
+       struct auth_master* m;
+       if(!o) return NULL;
+       m = (struct auth_master*)memdup(o, sizeof(*o));
+       if(!m) {
+               log_err("malloc failure");
+               return NULL;
+       }
+       m->next = NULL;
+       if(m->host) {
+               m->host = strdup(m->host);
+               if(!m->host) {
+                       free(m);
+                       log_err("malloc failure");
+                       return NULL;
+               }
+       }
+       if(m->file) {
+               m->file = strdup(m->file);
+               if(!m->file) {
+                       free(m->host);
+                       free(m);
+                       log_err("malloc failure");
+                       return NULL;
+               }
+       }
+       if(m->list) {
+               m->list = auth_addr_list_copy(m->list);
+               if(!m->list) {
+                       free(m->file);
+                       free(m->host);
+                       free(m);
+                       return NULL;
+               }
+       }
+       return m;
+}
+
+/** copy the master addresses from the task_probe lookups to the allow_notify
+ * list of masters */
+static void
+probe_copy_masters_for_allow_notify(struct auth_xfer* xfr)
+{
+       struct auth_master* list = NULL, *last = NULL;
+       struct auth_master* p;
+       /* build up new list with copies */
+       for(p = xfr->task_probe->masters; p; p=p->next) {
+               struct auth_master* m = auth_master_copy(p);
+               if(!m) {
+                       auth_free_masters(list);
+                       /* failed because of malloc failure, use old list */
+                       return;
+               }
+               m->next = NULL;
+               if(last) last->next = m;
+               if(!list) list = m;
+               last = m;
+       }
+       /* success, replace list */
+       auth_free_masters(xfr->allow_notify_list);
+       xfr->allow_notify_list = list;
+}
+
 /** start the lookups for task_transfer */
 static void
 xfr_transfer_start_lookups(struct auth_xfer* xfr)
@@ -3400,11 +3771,19 @@ xfr_transfer_nextmaster(struct auth_xfer* xfr)
        if(xfr->task_transfer->scan_specific) {
                xfr->task_transfer->scan_specific = NULL;
                xfr->task_transfer->scan_target = xfr->task_transfer->masters;
+               if(xfr->task_transfer->scan_target && xfr->task_transfer->
+                       scan_target->list)
+                       xfr->task_transfer->scan_addr =
+                               xfr->task_transfer->scan_target->list;
                return;
        }
        if(!xfr->task_transfer->scan_target)
                return;
        xfr->task_transfer->scan_target = xfr->task_transfer->scan_target->next;
+       if(xfr->task_transfer->scan_target && xfr->task_transfer->
+               scan_target->list)
+               xfr->task_transfer->scan_addr =
+                       xfr->task_transfer->scan_target->list;
        return;
 }
 
@@ -3422,11 +3801,19 @@ xfr_probe_nextmaster(struct auth_xfer* xfr)
        if(xfr->task_probe->scan_specific) {
                xfr->task_probe->scan_specific = NULL;
                xfr->task_probe->scan_target = xfr->task_probe->masters;
+               if(xfr->task_probe->scan_target && xfr->task_probe->
+                       scan_target->list)
+                       xfr->task_probe->scan_addr =
+                               xfr->task_probe->scan_target->list;
                return;
        }
        if(!xfr->task_probe->scan_target)
                return;
        xfr->task_probe->scan_target = xfr->task_probe->scan_target->next;
+       if(xfr->task_probe->scan_target && xfr->task_probe->
+               scan_target->list)
+               xfr->task_probe->scan_addr =
+                       xfr->task_probe->scan_target->list;
        return;
 }
 
@@ -3581,22 +3968,6 @@ check_packet_ok(sldns_buffer* pkt, uint16_t qtype, struct auth_xfer* xfr,
        return 1;
 }
 
-/** see if the serial means the zone has to be updated, i.e. the serial
- * is newer than the zone serial, or we have no zone */
-static int
-xfr_serial_means_update(struct auth_xfer* xfr, uint32_t serial)
-{
-       if(!xfr->have_zone)
-               return 1; /* no zone, anything is better */
-       if(xfr->zone_expired)
-               return 1; /* expired, the sent serial is better than expired
-                       data */
-       if(compare_serial(xfr->serial, serial) < 0)
-               return 1; /* our serial is smaller than the sent serial,
-                       the data is newer, fetch it */
-       return 0;
-}
-
 /** read one line from chunks into buffer at current position */
 static int
 chunkline_get_line(struct auth_chunk** chunk, size_t* chunk_pos,
@@ -3793,8 +4164,8 @@ chunkline_non_comment_RR(struct auth_chunk** chunk, size_t* chunk_pos,
        return 0;
 }
 
-/** check syntax of chunklist zonefile, parse SOA RR, return false on
- * failure and return a string in the scratch buffer (SOA RR string)
+/** check syntax of chunklist zonefile, parse first RR, return false on
+ * failure and return a string in the scratch buffer (first RR string)
  * on failure. */
 static int
 http_zonefile_syntax_check(struct auth_xfer* xfr, sldns_buffer* buf)
@@ -3822,26 +4193,11 @@ http_zonefile_syntax_check(struct auth_xfer* xfr, sldns_buffer* buf)
                pstate.origin_len?pstate.origin:NULL, pstate.origin_len,
                pstate.prev_rr_len?pstate.prev_rr:NULL, pstate.prev_rr_len);
        if(e != 0) {
-               log_err("parse failure on SOA RR[%d]: %s",
+               log_err("parse failure on first RR[%d]: %s",
                        LDNS_WIREPARSE_OFFSET(e),
                        sldns_get_errorstr_parse(LDNS_WIREPARSE_ERROR(e)));
                return 0;
        }
-       /* check that name is correct */
-       if(query_dname_compare(rr, xfr->name) != 0) {
-               char nm[255+1], zname[255+1];
-               dname_str(rr, nm);
-               dname_str(xfr->name, zname);
-               log_err("parse failure for %s, SOA RR for %s found instead",
-                       zname, nm);
-               return 0;
-       }
-       /* check that type is SOA */
-       if(sldns_wirerr_get_type(rr, rr_len, dname_len) != LDNS_RR_TYPE_SOA) {
-               log_err("parse failure: first record in downloaded zonefile "
-                       "not of type SOA");
-               return 0;
-       }
        /* check that class is correct */
        if(sldns_wirerr_get_class(rr, rr_len, dname_len) != xfr->dclass) {
                log_err("parse failure: first record in downloaded zonefile "
@@ -3870,6 +4226,11 @@ chunkline_newline_removal(sldns_buffer* buf)
        size_t i, end=sldns_buffer_limit(buf);
        for(i=0; i<end; i++) {
                char c = (char)sldns_buffer_read_u8_at(buf, i);
+               if(c == '\n' && i==end-1) {
+                       sldns_buffer_write_u8_at(buf, i, 0);
+                       sldns_buffer_set_limit(buf, end-1);
+                       return;
+               }
                if(c == '\n')
                        sldns_buffer_write_u8_at(buf, i, (uint8_t)' ');
        }
@@ -4365,6 +4726,28 @@ apply_http(struct auth_xfer* xfr, struct auth_zone* z,
        return 1;
 }
 
+/** write http chunks to zonefile to create downloaded file */
+static int
+auth_zone_write_chunks(struct auth_xfer* xfr, const char* fname)
+{
+       FILE* out;
+       struct auth_chunk* p;
+       out = fopen(fname, "w");
+       if(!out) {
+               log_err("could not open %s: %s", fname, strerror(errno));
+               return 0;
+       }
+       for(p = xfr->task_transfer->chunks_first; p ; p = p->next) {
+               if(!write_out(out, (char*)p->data, p->len)) {
+                       log_err("could not write http download to %s", fname);
+                       fclose(out);
+                       return 0;
+               }
+       }
+       fclose(out);
+       return 1;
+}
+
 /** write to zonefile after zone has been updated */
 static void
 xfr_write_after_update(struct auth_xfer* xfr, struct module_env* env)
@@ -4403,7 +4786,13 @@ xfr_write_after_update(struct auth_xfer* xfr, struct module_env* env)
        }
        snprintf(tmpfile, sizeof(tmpfile), "%s.tmp%u", z->zonefile,
                (unsigned)getpid());
-       if(!auth_zone_write_file(z, tmpfile)) {
+       if(xfr->task_transfer->master->http) {
+               /* use the stored chunk list to write them */
+               if(!auth_zone_write_chunks(xfr, tmpfile)) {
+                       unlink(tmpfile);
+                       lock_rw_unlock(&z->lock);
+               }
+       } else if(!auth_zone_write_file(z, tmpfile)) {
                unlink(tmpfile);
                lock_rw_unlock(&z->lock);
                return;
@@ -4522,6 +4911,9 @@ xfr_transfer_lookup_host(struct auth_xfer* xfr, struct module_env* env)
                /* not needed, host is in IP addr format */
                return 0;
        }
+       if(master->allow_notify)
+               return 0; /* allow-notifies are not transferred from, no
+               lookup is needed */
 
        /* use mesh_new_callback to probe for non-addr hosts,
         * and then wait for them to be looked up (in cache, or query) */
@@ -4576,6 +4968,7 @@ xfr_transfer_init_fetch(struct auth_xfer* xfr, struct module_env* env)
        socklen_t addrlen = 0;
        struct auth_master* master = xfr->task_transfer->master;
        if(!master) return 0;
+       if(master->allow_notify) return 0; /* only for notify */
 
        /* get master addr */
        if(xfr->task_transfer->scan_addr) {
@@ -4680,7 +5073,7 @@ xfr_transfer_nexttarget_or_end(struct auth_xfer* xfr, struct module_env* env)
        xfr_transfer_disown(xfr);
 
        /* pick up the nextprobe task and wait */
-       xfr_set_timeout(xfr, env, 1);
+       xfr_set_timeout(xfr, env, 1, 0);
        lock_basic_unlock(&xfr->lock);
 }
 
@@ -4692,6 +5085,8 @@ xfr_master_add_addrs(struct auth_master* m, struct ub_packed_rrset_key* rrset,
        size_t i;
        struct packed_rrset_data* data;
        if(!m || !rrset) return;
+       if(rrtype != LDNS_RR_TYPE_A && rrtype != LDNS_RR_TYPE_AAAA)
+               return;
        data = (struct packed_rrset_data*)rrset->entry.data;
        for(i=0; i<data->count; i++) {
                struct auth_addr* a;
@@ -5113,8 +5508,30 @@ process_list_end_transfer(struct auth_xfer* xfr, struct module_env* env)
                /* we fetched the zone, move to wait task */
                xfr_transfer_disown(xfr);
 
-               /* pick up the nextprobe task and wait (normail wait time) */
-               xfr_set_timeout(xfr, env, 0);
+               if(xfr->notify_received && (!xfr->notify_has_serial ||
+                       (xfr->notify_has_serial && 
+                       xfr_serial_means_update(xfr, xfr->notify_serial)))) {
+                       uint32_t sr = xfr->notify_serial;
+                       int has_sr = xfr->notify_has_serial;
+                       /* we received a notify while probe/transfer was
+                        * in progress.  start a new probe and transfer */
+                       xfr->notify_received = 0;
+                       xfr->notify_has_serial = 0;
+                       xfr->notify_serial = 0;
+                       if(!xfr_start_probe(xfr, env, NULL)) {
+                               /* if we couldn't start it, already in
+                                * progress; restore notify serial,
+                                * while xfr still locked */
+                               xfr->notify_received = 1;
+                               xfr->notify_has_serial = has_sr;
+                               xfr->notify_serial = sr;
+                               lock_basic_unlock(&xfr->lock);
+                       }
+                       return;
+               } else {
+                       /* pick up the nextprobe task and wait (normail wait time) */
+                       xfr_set_timeout(xfr, env, 0, 0);
+               }
                lock_basic_unlock(&xfr->lock);
                return;
        }
@@ -5305,6 +5722,9 @@ xfr_probe_send_probe(struct auth_xfer* xfr, struct module_env* env,
        /* pick master */
        struct auth_master* master = xfr_probe_current_master(xfr);
        if(!master) return 0;
+       if(master->allow_notify) return 0; /* only for notify */
+       if(master->http) return 0; /* only masters get SOA UDP probe,
+               not urls, if those are in this list */
 
        /* get master addr */
        if(xfr->task_probe->scan_addr) {
@@ -5457,7 +5877,7 @@ auth_xfer_probe_udp_callback(struct comm_point* c, void* arg, int err,
                                if(xfr->have_zone)
                                        xfr->lease_time = *env->now;
                                if(xfr->task_nextprobe->worker == NULL)
-                                       xfr_set_timeout(xfr, env, 0);
+                                       xfr_set_timeout(xfr, env, 0, 0);
                        }
                        /* other tasks are running, we don't do this anymore */
                        xfr_probe_disown(xfr);
@@ -5502,6 +5922,11 @@ xfr_probe_lookup_host(struct auth_xfer* xfr, struct module_env* env)
                /* not needed, host is in IP addr format */
                return 0;
        }
+       if(master->allow_notify && !master->http &&
+               strchr(master->host, '/') != NULL &&
+               strchr(master->host, '/') == strrchr(master->host, '/')) {
+               return 0; /* is IP/prefix format, not something to look up */
+       }
 
        /* use mesh_new_callback to probe for non-addr hosts,
         * and then wait for them to be looked up (in cache, or query) */
@@ -5564,6 +5989,17 @@ xfr_probe_send_or_end(struct auth_xfer* xfr, struct module_env* env)
                }
                xfr_probe_move_to_next_lookup(xfr, env);
        }
+       /* probe of list has ended.  Create or refresh the list of of
+        * allow_notify addrs */
+       probe_copy_masters_for_allow_notify(xfr);
+       if(xfr->task_probe->only_lookup) {
+               /* only wanted lookups for copy, stop probe and start wait */
+               xfr->task_probe->only_lookup = 0;
+               xfr_probe_disown(xfr);
+               xfr_set_timeout(xfr, env, 0, 0);
+               lock_basic_unlock(&xfr->lock);
+               return;
+       }
 
        /* send probe packets */
        while(!xfr_probe_end_of_list(xfr)) {
@@ -5581,7 +6017,7 @@ xfr_probe_send_or_end(struct auth_xfer* xfr, struct module_env* env)
        xfr_probe_disown(xfr);
 
        /* pick up the nextprobe task and wait */
-       xfr_set_timeout(xfr, env, 1);
+       xfr_set_timeout(xfr, env, 1, 0);
        lock_basic_unlock(&xfr->lock);
 }
 
@@ -5668,19 +6104,45 @@ auth_xfer_timer(void* arg)
 
        xfr_nextprobe_disown(xfr);
 
+       if(!xfr_start_probe(xfr, env, NULL)) {
+               /* not started because already in progress */
+               lock_basic_unlock(&xfr->lock);
+       }
+}
+
+/** return true if there are probe (SOA UDP query) targets in the master list*/
+static int
+have_probe_targets(struct auth_master* list)
+{
+       struct auth_master* p;
+       for(p=list; p; p = p->next) {
+               if(!p->allow_notify && p->host)
+                       return 1;
+       }
+       return 0;
+}
+
+/** start task_probe if possible, if no masters for probe start task_transfer
+ * returns true if task has been started, and false if the task is already
+ * in progress. */
+static int
+xfr_start_probe(struct auth_xfer* xfr, struct module_env* env,
+       struct auth_master* spec)
+{
        /* see if we need to start a probe (or maybe it is already in
         * progress (due to notify)) */
        if(xfr->task_probe->worker == NULL) {
-               if(xfr->task_probe->masters == NULL) {
+               if(!have_probe_targets(xfr->task_probe->masters) &&
+                       !(xfr->task_probe->only_lookup &&
+                       xfr->task_probe->masters != NULL)) {
                        /* useless to pick up task_probe, no masters to
                         * probe. Instead attempt to pick up task transfer */
                        if(xfr->task_transfer->worker == NULL) {
-                               xfr_start_transfer(xfr, env, NULL);
-                       } else {
-                               /* task transfer already in progress */
-                               lock_basic_unlock(&xfr->lock);
+                               xfr_start_transfer(xfr, env, spec);
+                               return 1;
                        }
-                       return;
+                       /* task transfer already in progress */
+                       return 0;
                }
 
                /* pick up the probe task ourselves */
@@ -5689,15 +6151,17 @@ auth_xfer_timer(void* arg)
                xfr->task_probe->cp = NULL;
 
                /* start the task */
-               /* this was a timeout, so no specific first master to scan */
-               xfr_probe_start_list(xfr, NULL);
+               /* if this was a timeout, no specific first master to scan */
+               /* otherwise, spec is nonNULL the notified master, scan
+                * first and also transfer first from it */
+               xfr_probe_start_list(xfr, spec);
                /* setup to start the lookup of hostnames of masters afresh */
                xfr_probe_start_lookups(xfr);
                /* send the probe packet or next send, or end task */
                xfr_probe_send_or_end(xfr, env);
-       } else {
-               lock_basic_unlock(&xfr->lock);
+               return 1;
        }
+       return 0;
 }
 
 /** for task_nextprobe.
@@ -5705,10 +6169,11 @@ auth_xfer_timer(void* arg)
  * @param xfr: task structure
  * @param env: module environment, with worker and time.
  * @param failure: set true if timer should be set for failure retry.
+ * @param lookup_only: only perform lookups when timer done, 0 sec timeout
  */
 static void
 xfr_set_timeout(struct auth_xfer* xfr, struct module_env* env,
-       int failure)
+       int failure, int lookup_only)
 {
        struct timeval tv;
        log_assert(xfr->task_nextprobe != NULL);
@@ -5718,7 +6183,7 @@ xfr_set_timeout(struct auth_xfer* xfr, struct module_env* env,
         * but if expiry is sooner, use that one.
         * after a failure, use the retry timer instead. */
        xfr->task_nextprobe->next_probe = *env->now;
-       if(xfr->lease_time)
+       if(xfr->lease_time && !failure)
                xfr->task_nextprobe->next_probe = xfr->lease_time;
        
        if(!failure) {
@@ -5741,6 +6206,12 @@ xfr_set_timeout(struct auth_xfer* xfr, struct module_env* env,
                if(failure)
                        xfr->task_nextprobe->next_probe +=
                                xfr->task_nextprobe->backoff;
+               /* put the timer exactly on expiry, if possible */
+               if(xfr->lease_time && xfr->lease_time+xfr->expiry <
+                       xfr->task_nextprobe->next_probe &&
+                       xfr->lease_time+xfr->expiry > *env->now)
+                       xfr->task_nextprobe->next_probe =
+                               xfr->lease_time+xfr->expiry;
        } else {
                xfr->task_nextprobe->next_probe +=
                        xfr->task_nextprobe->backoff;
@@ -5765,6 +6236,13 @@ xfr_set_timeout(struct auth_xfer* xfr, struct module_env* env,
                tv.tv_sec = xfr->task_nextprobe->next_probe - 
                        *(xfr->task_nextprobe->env->now);
        else    tv.tv_sec = 0;
+       if(tv.tv_sec != 0 && lookup_only && xfr->task_probe->masters) {
+               /* don't lookup_only, if lookup timeout is 0 anyway,
+                * or if we don't have masters to lookup */
+               tv.tv_sec = 0;
+               if(xfr->task_probe && xfr->task_probe->worker == NULL)
+                       xfr->task_probe->only_lookup = 1;
+       }
        if(verbosity >= VERB_ALGO) {
                char zname[255+1];
                dname_str(xfr->name, zname);
@@ -5788,8 +6266,9 @@ auth_xfer_pickup_initial(struct auth_zones* az, struct module_env* env)
                 * notes the start time when the data was acquired */
                if(x->have_zone)
                        x->lease_time = *env->now;
-               if(x->task_nextprobe && x->task_nextprobe->worker == NULL)
-                       xfr_set_timeout(x, env, 0);
+               if(x->task_nextprobe && x->task_nextprobe->worker == NULL) {
+                       xfr_set_timeout(x, env, 0, 1);
+               }
                lock_basic_unlock(&x->lock);
        }
        lock_rw_unlock(&az->lock);
@@ -6063,6 +6542,15 @@ xfer_set_masters(struct auth_master** list, struct config_auth* c,
                        return 0;
                }
        }
+       for(p = c->allow_notify; p; p = p->next) {
+               m = auth_master_new(&list);
+               m->allow_notify = 1;
+               m->host = strdup(p->str);
+               if(!m->host) {
+                       log_err("malloc failure");
+                       return 0;
+               }
+       }
        return 1;
 }
 
index d54ef4b..4e06c06 100644 (file)
@@ -77,6 +77,10 @@ struct auth_zones {
        rbtree_type xtree;
        /** do we have downstream enabled */
        int have_downstream;
+       /** number of queries upstream */
+       size_t num_query_up;
+       /** number of queries downstream */
+       size_t num_query_down;
 };
 
 /**
@@ -122,6 +126,10 @@ struct auth_zone {
        /** for upstream: this zone answers queries that unbound intends to
         * send upstream. */
        int for_upstream;
+       /** zone has been deleted */
+       int zone_deleted;
+       /** deletelist pointer, unused normally except during delete */
+       struct auth_zone* delete_next;
 };
 
 /**
@@ -214,8 +222,14 @@ struct auth_xfer {
         * Hold the lock to access this member (and the serial).
         */
        int notify_received;
+       /** true if the notify_received has a serial number */
+       int notify_has_serial;
        /** serial number of the notify */
        uint32_t notify_serial;
+       /** the list of masters for checking notifies.  This list is
+        * empty on start, and a copy of the list from the probe_task when
+        * it is done looking them up. */
+       struct auth_master* allow_notify_list;
 
        /* protected by the lock on the structure, information about
         * the loaded authority zone. */
@@ -292,6 +306,9 @@ struct auth_probe {
        struct auth_master* lookup_target;
        /** are we looking up A or AAAA, first A, then AAAA (if ip6 enabled) */
        int lookup_aaaa;
+       /** we only want to do lookups for making config work (for notify),
+        * don't proceed with UDP SOA probe queries */
+       int only_lookup;
 
        /** once notified, or the timeout has been reached. a scan starts. */
        /** the scan specific target (notify source), or NULL if none */
@@ -400,6 +417,9 @@ struct auth_master {
        int http;
        /** use IXFR for this master */
        int ixfr;
+       /** this is an allow notify member, the master can send notifies
+        * to us, but we don't send SOA probes, or zone transfer from it */
+       int allow_notify;
        /** use ssl for channel */
        int ssl;
        /** the port number (for urls) */
@@ -541,9 +561,39 @@ int auth_zone_set_fallback(struct auth_zone* z, char* fallbackstr);
 int auth_zones_can_fallback(struct auth_zones* az, uint8_t* nm, size_t nmlen,
        uint16_t dclass);
 
+/** process notify for auth zones.
+ * first checks the access list.  Then processes the notify. This starts
+ * the probe sequence or it notes the serial number (if any)
+ * @param az: auth zones structure.
+ * @param env: module env of the worker that is handling the notify. it will
+ *     pick up the task probe (or transfer), unless already in progress by
+ *     another worker.
+ * @param nm: name of the zone.  Uncompressed. from query.
+ * @param nmlen: length of name.
+ * @param dclass: class of zone.
+ * @param addr: source address of notify
+ * @param addrlen: length of addr.
+ * @param has_serial: if true, the notify has a serial attached.
+ * @param serial: the serial number, if has_serial is true.
+ * @param refused: is set to true on failure to note refused access.
+ * @return fail on failures (refused is false) and when access is
+ *     denied (refused is true).  True when processed.
+ */
+int auth_zones_notify(struct auth_zones* az, struct module_env* env,
+       uint8_t* nm, size_t nmlen, uint16_t dclass,
+       struct sockaddr_storage* addr, socklen_t addrlen, int has_serial,
+       uint32_t serial, int* refused);
+
+/** process notify packet and read serial number from SOA.
+ * returns 0 if no soa record in the notify */
+int auth_zone_parse_notify_serial(struct sldns_buffer* pkt, uint32_t *serial);
+
 /** read auth zone from zonefile. caller must lock zone. false on failure */
 int auth_zone_read_zonefile(struct auth_zone* z);
 
+/** find serial number of zone or false if none (no SOA record) */
+int auth_zone_get_serial(struct auth_zone* z, uint32_t* serial);
+
 /** compare auth_zones for sorted rbtree */
 int auth_zone_cmp(const void* z1, const void* z2);
 
index 734b796..f432030 100644 (file)
@@ -232,22 +232,20 @@ infra_create(struct config_file* cfg)
        infra->host_ttl = cfg->host_ttl;
        name_tree_init(&infra->domain_limits);
        infra_dp_ratelimit = cfg->ratelimit;
-       if(cfg->ratelimit != 0) {
-               infra->domain_rates = slabhash_create(cfg->ratelimit_slabs,
-                       INFRA_HOST_STARTSIZE, cfg->ratelimit_size,
-                       &rate_sizefunc, &rate_compfunc, &rate_delkeyfunc,
-                       &rate_deldatafunc, NULL);
-               if(!infra->domain_rates) {
-                       infra_delete(infra);
-                       return NULL;
-               }
-               /* insert config data into ratelimits */
-               if(!infra_ratelimit_cfg_insert(infra, cfg)) {
-                       infra_delete(infra);
-                       return NULL;
-               }
-               name_tree_init_parents(&infra->domain_limits);
+       infra->domain_rates = slabhash_create(cfg->ratelimit_slabs,
+               INFRA_HOST_STARTSIZE, cfg->ratelimit_size,
+               &rate_sizefunc, &rate_compfunc, &rate_delkeyfunc,
+               &rate_deldatafunc, NULL);
+       if(!infra->domain_rates) {
+               infra_delete(infra);
+               return NULL;
+       }
+       /* insert config data into ratelimits */
+       if(!infra_ratelimit_cfg_insert(infra, cfg)) {
+               infra_delete(infra);
+               return NULL;
        }
+       name_tree_init_parents(&infra->domain_limits);
        infra_ip_ratelimit = cfg->ip_ratelimit;
        infra->client_ip_rates = slabhash_create(cfg->ip_ratelimit_slabs,
            INFRA_HOST_STARTSIZE, cfg->ip_ratelimit_size, &ip_rate_sizefunc,
index 0b41fcd..26c1aeb 100644 (file)
@@ -255,9 +255,11 @@ void rrset_cache_update_wildcard(struct rrset_cache* rrset_cache,
        wc_dname[1] = (uint8_t)'*';
        memmove(wc_dname+2, ce, ce_len);
 
+       free(rrset->rk.dname);
        rrset->rk.dname_len = ce_len + 2;
        rrset->rk.dname = (uint8_t*)memdup(wc_dname, rrset->rk.dname_len);
        if(!rrset->rk.dname) {
+               alloc_special_release(alloc, rrset);
                log_err("memdup failure in rrset_cache_update_wildcard");
                return;
        }
index 7b97d45..7028416 100644 (file)
@@ -1056,6 +1056,26 @@ set_recvpktinfo(int s, int family)
        return 1;
 }
 
+/** see if interface is ssl, its port number == the ssl port number */
+static int
+if_is_ssl(const char* ifname, const char* port, int ssl_port,
+       struct config_strlist* tls_additional_port)
+{
+       struct config_strlist* s;
+       char* p = strchr(ifname, '@');
+       if(!p && atoi(port) == ssl_port)
+               return 1;
+       if(p && atoi(p+1) == ssl_port)
+               return 1;
+       for(s = tls_additional_port; s; s = s->next) {
+               if(p && atoi(p+1) == atoi(s->str))
+                       return 1;
+               if(!p && atoi(port) == atoi(s->str))
+                       return 1;
+       }
+       return 0;
+}
+
 /**
  * Helper for ports_open. Creates one interface (or NULL for default).
  * @param ifname: The interface ip address.
@@ -1069,6 +1089,7 @@ set_recvpktinfo(int s, int family)
  * @param rcv: receive buffer size for UDP
  * @param snd: send buffer size for UDP
  * @param ssl_port: ssl service port number
+ * @param tls_additional_port: list of additional ssl service port numbers.
  * @param reuseport: try to set SO_REUSEPORT if nonNULL and true.
  *     set to false on exit if reuseport failed due to no kernel support.
  * @param transparent: set IP_TRANSPARENT socket option.
@@ -1081,8 +1102,10 @@ set_recvpktinfo(int s, int family)
 static int
 ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp, 
        struct addrinfo *hints, const char* port, struct listen_port** list,
-       size_t rcv, size_t snd, int ssl_port, int* reuseport, int transparent,
-       int tcp_mss, int freebind, int use_systemd, int dnscrypt_port)
+       size_t rcv, size_t snd, int ssl_port,
+       struct config_strlist* tls_additional_port, int* reuseport,
+       int transparent, int tcp_mss, int freebind, int use_systemd,
+       int dnscrypt_port)
 {
        int s, noip6=0;
 #ifdef USE_DNSCRYPT
@@ -1146,9 +1169,8 @@ ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp,
                }
        }
        if(do_tcp) {
-               int is_ssl = ((strchr(ifname, '@') && 
-                       atoi(strchr(ifname, '@')+1) == ssl_port) ||
-                       (!strchr(ifname, '@') && atoi(port) == ssl_port));
+               int is_ssl = if_is_ssl(ifname, port, ssl_port,
+                       tls_additional_port);
                if((s = make_sock_port(SOCK_STREAM, ifname, port, hints, 1, 
                        &noip6, 0, 0, reuseport, transparent, tcp_mss,
                        freebind, use_systemd)) == -1) {
@@ -1334,8 +1356,8 @@ listening_ports_open(struct config_file* cfg, int* reuseport)
                                do_auto, cfg->do_udp, do_tcp, 
                                &hints, portbuf, &list,
                                cfg->so_rcvbuf, cfg->so_sndbuf,
-                               cfg->ssl_port, reuseport,
-                               cfg->ip_transparent,
+                               cfg->ssl_port, cfg->tls_additional_port,
+                               reuseport, cfg->ip_transparent,
                                cfg->tcp_mss, cfg->ip_freebind, cfg->use_systemd,
                                cfg->dnscrypt_port)) {
                                listening_ports_free(list);
@@ -1348,8 +1370,8 @@ listening_ports_open(struct config_file* cfg, int* reuseport)
                                do_auto, cfg->do_udp, do_tcp, 
                                &hints, portbuf, &list,
                                cfg->so_rcvbuf, cfg->so_sndbuf,
-                               cfg->ssl_port, reuseport,
-                               cfg->ip_transparent,
+                               cfg->ssl_port, cfg->tls_additional_port,
+                               reuseport, cfg->ip_transparent,
                                cfg->tcp_mss, cfg->ip_freebind, cfg->use_systemd,
                                cfg->dnscrypt_port)) {
                                listening_ports_free(list);
@@ -1364,8 +1386,8 @@ listening_ports_open(struct config_file* cfg, int* reuseport)
                        if(!ports_create_if(cfg->ifs[i], 0, cfg->do_udp, 
                                do_tcp, &hints, portbuf, &list, 
                                cfg->so_rcvbuf, cfg->so_sndbuf,
-                               cfg->ssl_port, reuseport,
-                               cfg->ip_transparent,
+                               cfg->ssl_port, cfg->tls_additional_port,
+                               reuseport, cfg->ip_transparent,
                                cfg->tcp_mss, cfg->ip_freebind, cfg->use_systemd,
                                cfg->dnscrypt_port)) {
                                listening_ports_free(list);
@@ -1378,8 +1400,8 @@ listening_ports_open(struct config_file* cfg, int* reuseport)
                        if(!ports_create_if(cfg->ifs[i], 0, cfg->do_udp, 
                                do_tcp, &hints, portbuf, &list, 
                                cfg->so_rcvbuf, cfg->so_sndbuf,
-                               cfg->ssl_port, reuseport,
-                               cfg->ip_transparent,
+                               cfg->ssl_port, cfg->tls_additional_port,
+                               reuseport, cfg->ip_transparent,
                                cfg->tcp_mss, cfg->ip_freebind, cfg->use_systemd,
                                cfg->dnscrypt_port)) {
                                listening_ports_free(list);
index 3395dc6..41aba74 100644 (file)
@@ -736,7 +736,8 @@ mesh_state_cleanup(struct mesh_state* mstate)
                        comm_point_drop_reply(&rep->query_reply);
                        mesh->num_reply_addrs--;
                }
-               for(cb=mstate->cb_list; cb; cb=cb->next) {
+               while((cb = mstate->cb_list)!=NULL) {
+                       mstate->cb_list = cb->next;
                        fptr_ok(fptr_whitelist_mesh_cb(cb->cb));
                        (*cb->cb)(cb->cb_arg, LDNS_RCODE_SERVFAIL, NULL,
                                sec_status_unchecked, NULL);
@@ -974,7 +975,8 @@ mesh_do_callback(struct mesh_state* m, int rcode, struct reply_info* rep,
        else    secure = 0;
        if(!rep && rcode == LDNS_RCODE_NOERROR)
                rcode = LDNS_RCODE_SERVFAIL;
-       if(!rcode && rep->security == sec_status_bogus) {
+       if(!rcode && (rep->security == sec_status_bogus ||
+               rep->security == sec_status_secure_sentinel_fail)) {
                if(!(reason = errinf_to_str(&m->s)))
                        rcode = LDNS_RCODE_SERVFAIL;
        }
@@ -1040,7 +1042,8 @@ mesh_send_reply(struct mesh_state* m, int rcode, struct reply_info* rep,
        /* examine security status */
        if(m->s.env->need_to_validate && (!(r->qflags&BIT_CD) ||
                m->s.env->cfg->ignore_cd) && rep && 
-               rep->security <= sec_status_bogus) {
+               (rep->security <= sec_status_bogus ||
+               rep->security == sec_status_secure_sentinel_fail)) {
                rcode = LDNS_RCODE_SERVFAIL;
                if(m->s.env->cfg->stat_extended) 
                        m->s.env->mesh->ans_bogus++;
@@ -1167,7 +1170,17 @@ void mesh_query_done(struct mesh_state* mstate)
                }
        }
        mstate->replies_sent = 1;
-       for(c = mstate->cb_list; c; c = c->next) {
+       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 */
+                       mstate->s.env->mesh->num_reply_states--;
+               }
+               mstate->cb_list = c->next;
+               if(!mstate->reply_list && !mstate->cb_list &&
+                       mstate->super_set.count == 0)
+                       mstate->s.env->mesh->num_detached_states++;
                mesh_do_callback(mstate, mstate->s.return_rcode, rep, c);
        }
 }
index 92212be..5700ef8 100644 (file)
@@ -364,6 +364,20 @@ outnet_tcp_take_into_use(struct waiting_tcp* w, uint8_t* pkt, size_t pkt_len)
                comm_point_tcp_win_bio_cb(pend->c, pend->c->ssl);
 #endif
                pend->c->ssl_shake_state = comm_ssl_shake_write;
+#ifdef HAVE_SSL_SET1_HOST
+               if(w->tls_auth_name) {
+                       SSL_set_verify(pend->c->ssl, SSL_VERIFY_PEER, NULL);
+                       /* setting the hostname makes openssl verify the
+                         * host name in the x509 certificate in the
+                         * SSL connection*/
+                        if(!SSL_set1_host(pend->c->ssl, w->tls_auth_name)) {
+                                log_err("SSL_set1_host failed");
+                               pend->c->fd = s;
+                               comm_point_close(pend->c);
+                               return 0;
+                       }
+               }
+#endif /* HAVE_SSL_SET1_HOST */
        }
        w->pkt = NULL;
        w->next_waiting = (void*)pend;
@@ -851,6 +865,7 @@ serviced_node_del(rbnode_type* node, void* ATTR_UNUSED(arg))
        struct service_callback* p = sq->cblist, *np;
        free(sq->qbuf);
        free(sq->zone);
+       free(sq->tls_auth_name);
        edns_opt_list_free(sq->opt_list);
        while(p) {
                np = p->next;
@@ -1284,9 +1299,10 @@ pending_tcp_query(struct serviced_query* sq, sldns_buffer* packet,
        w->cb = callback;
        w->cb_arg = callback_arg;
        w->ssl_upstream = sq->ssl_upstream;
+       w->tls_auth_name = sq->tls_auth_name;
 #ifndef S_SPLINT_S
-       tv.tv_sec = timeout;
-       tv.tv_usec = 0;
+       tv.tv_sec = timeout/1000;
+       tv.tv_usec = (timeout%1000)*1000;
 #endif
        comm_timer_set(w->timer, &tv);
        if(pend) {
@@ -1357,8 +1373,8 @@ lookup_serviced(struct outside_network* outnet, sldns_buffer* buff, int dnssec,
 static struct serviced_query*
 serviced_create(struct outside_network* outnet, sldns_buffer* buff, int dnssec,
        int want_dnssec, int nocaps, int tcp_upstream, int ssl_upstream,
-       struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* zone,
-       size_t zonelen, int qtype, struct edns_option* opt_list)
+       char* tls_auth_name, struct sockaddr_storage* addr, socklen_t addrlen,
+       uint8_t* zone, size_t zonelen, int qtype, struct edns_option* opt_list)
 {
        struct serviced_query* sq = (struct serviced_query*)malloc(sizeof(*sq));
 #ifdef UNBOUND_DEBUG
@@ -1386,12 +1402,24 @@ serviced_create(struct outside_network* outnet, sldns_buffer* buff, int dnssec,
        sq->nocaps = nocaps;
        sq->tcp_upstream = tcp_upstream;
        sq->ssl_upstream = ssl_upstream;
+       if(tls_auth_name) {
+               sq->tls_auth_name = strdup(tls_auth_name);
+               if(!sq->tls_auth_name) {
+                       free(sq->zone);
+                       free(sq->qbuf);
+                       free(sq);
+                       return NULL;
+               }
+       } else {
+               sq->tls_auth_name = NULL;
+       }
        memcpy(&sq->addr, addr, addrlen);
        sq->addrlen = addrlen;
        sq->opt_list = NULL;
        if(opt_list) {
                sq->opt_list = edns_opt_copy_alloc(opt_list);
                if(!sq->opt_list) {
+                       free(sq->tls_auth_name);
                        free(sq->zone);
                        free(sq->qbuf);
                        free(sq);
@@ -1784,7 +1812,12 @@ serviced_tcp_callback(struct comm_point* c, void* arg, int error,
        }
        if(sq->tcp_upstream || sq->ssl_upstream) {
            struct timeval now = *sq->outnet->now_tv;
-           if(now.tv_sec > sq->last_sent_time.tv_sec ||
+           if(error!=NETEVENT_NOERROR) {
+               if(!infra_rtt_update(sq->outnet->infra, &sq->addr,
+                   sq->addrlen, sq->zone, sq->zonelen, sq->qtype,
+                   -1, sq->last_rtt, (time_t)now.tv_sec))
+                   log_err("out of memory in TCP exponential backoff.");
+           } else if(now.tv_sec > sq->last_sent_time.tv_sec ||
                (now.tv_sec == sq->last_sent_time.tv_sec &&
                now.tv_usec > sq->last_sent_time.tv_usec)) {
                /* convert from microseconds to milliseconds */
@@ -1794,7 +1827,7 @@ serviced_tcp_callback(struct comm_point* c, void* arg, int error,
                log_assert(roundtime >= 0);
                /* only store if less then AUTH_TIMEOUT seconds, it could be
                 * huge due to system-hibernated and we woke up */
-               if(roundtime < TCP_AUTH_QUERY_TIMEOUT*1000) {
+               if(roundtime < 60000) {
                    if(!infra_rtt_update(sq->outnet->infra, &sq->addr,
                        sq->addrlen, sq->zone, sq->zonelen, sq->qtype,
                        roundtime, sq->last_rtt, (time_t)now.tv_sec))
@@ -1835,18 +1868,26 @@ serviced_tcp_initiate(struct serviced_query* sq, sldns_buffer* buff)
 static int
 serviced_tcp_send(struct serviced_query* sq, sldns_buffer* buff)
 {
-       int vs, rtt;
+       int vs, rtt, timeout;
        uint8_t edns_lame_known;
        if(!infra_host(sq->outnet->infra, &sq->addr, sq->addrlen, sq->zone,
                sq->zonelen, *sq->outnet->now_secs, &vs, &edns_lame_known,
                &rtt))
                return 0;
+       sq->last_rtt = rtt;
        if(vs != -1)
                sq->status = serviced_query_TCP_EDNS;
        else    sq->status = serviced_query_TCP;
        serviced_encode(sq, buff, sq->status == serviced_query_TCP_EDNS);
        sq->last_sent_time = *sq->outnet->now_tv;
-       sq->pending = pending_tcp_query(sq, buff, TCP_AUTH_QUERY_TIMEOUT,
+       if(sq->tcp_upstream || sq->ssl_upstream) {
+               timeout = rtt;
+               if(rtt >= 376 && rtt < TCP_AUTH_QUERY_TIMEOUT)
+                       timeout = TCP_AUTH_QUERY_TIMEOUT;
+       } else {
+               timeout = TCP_AUTH_QUERY_TIMEOUT;
+       }
+       sq->pending = pending_tcp_query(sq, buff, timeout,
                serviced_tcp_callback, sq);
        return sq->pending != NULL;
 }
@@ -2055,7 +2096,7 @@ serviced_udp_callback(struct comm_point* c, void* arg, int error,
 struct serviced_query* 
 outnet_serviced_query(struct outside_network* outnet,
        struct query_info* qinfo, uint16_t flags, int dnssec, int want_dnssec,
-       int nocaps, int tcp_upstream, int ssl_upstream,
+       int nocaps, int tcp_upstream, int ssl_upstream, char* tls_auth_name,
        struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* zone,
        size_t zonelen, struct module_qstate* qstate,
        comm_point_callback_type* callback, void* callback_arg, sldns_buffer* buff,
@@ -2078,8 +2119,9 @@ outnet_serviced_query(struct outside_network* outnet,
        if(!sq) {
                /* make new serviced query entry */
                sq = serviced_create(outnet, buff, dnssec, want_dnssec, nocaps,
-                       tcp_upstream, ssl_upstream, addr, addrlen, zone,
-                       zonelen, (int)qinfo->qtype, qstate->edns_opts_back_out);
+                       tcp_upstream, ssl_upstream, tls_auth_name, addr,
+                       addrlen, zone, zonelen, (int)qinfo->qtype,
+                       qstate->edns_opts_back_out);
                if(!sq) {
                        free(cb);
                        return NULL;
index 09b2e6c..01a3074 100644 (file)
@@ -290,6 +290,8 @@ struct waiting_tcp {
        void* cb_arg;
        /** if it uses ssl upstream */
        int ssl_upstream;
+       /** ref to the tls_auth_name from the serviced_query */
+       char* tls_auth_name;
 };
 
 /**
@@ -332,6 +334,9 @@ struct serviced_query {
        int nocaps;
        /** tcp upstream used, use tcp, or ssl_upstream for SSL */
        int tcp_upstream, ssl_upstream;
+       /** the name of the tls authentication name, eg. 'ns.example.com'
+        * or NULL */
+       char* tls_auth_name;
        /** where to send it */
        struct sockaddr_storage addr;
        /** length of addr field in use. */
@@ -371,7 +376,7 @@ struct serviced_query {
        int retry;
        /** time last UDP was sent */
        struct timeval last_sent_time;
-       /** rtt of last (UDP) message */
+       /** rtt of last message */
        int last_rtt;
        /** do we know edns probe status already, for UDP_EDNS queries */
        int edns_lame_known;
@@ -451,7 +456,7 @@ struct pending* pending_udp_query(struct serviced_query* sq,
  * checks id.
  * @param sq: serviced query.
  * @param packet: wireformat query to send to destination. copied from.
- * @param timeout: in seconds from now.
+ * @param timeout: in milliseconds from now.
  *    Timer starts running now. Timer may expire if all buffers are used,
  *    without any query been sent to the server yet.
  * @param callback: function to call on error, timeout or reply.
@@ -484,6 +489,8 @@ void pending_delete(struct outside_network* outnet, struct pending* p);
  * @param nocaps: ignore use_caps_for_id and use unperturbed qname.
  * @param tcp_upstream: use TCP for upstream queries.
  * @param ssl_upstream: use SSL for upstream queries.
+ * @param tls_auth_name: when ssl_upstream is true, use this name to check
+ *     the server's peer certificate.
  * @param addr: to which server to send the query.
  * @param addrlen: length of addr.
  * @param zone: name of the zone of the delegation point. wireformat dname.
@@ -501,7 +508,7 @@ void pending_delete(struct outside_network* outnet, struct pending* p);
  */
 struct serviced_query* outnet_serviced_query(struct outside_network* outnet,
        struct query_info* qinfo, uint16_t flags, int dnssec, int want_dnssec,
-       int nocaps, int tcp_upstream, int ssl_upstream,
+       int nocaps, int tcp_upstream, int ssl_upstream, char* tls_auth_name,
        struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* zone,
        size_t zonelen, struct module_qstate* qstate,
        comm_point_callback_type* callback, void* callback_arg,
index e2f14f2..2ec225b 100644 (file)
@@ -89,6 +89,14 @@ sldns_rr_dnskey_key_size_raw(const unsigned char* keydata,
                 return 256;
         case LDNS_ECDSAP384SHA384:
                 return 384;
+#endif
+#ifdef USE_ED25519
+       case LDNS_ED25519:
+               return 256;
+#endif
+#ifdef USE_ED448
+       case LDNS_ED448:
+               return 456;
 #endif
        default:
                return 0;
@@ -409,6 +417,27 @@ sldns_ed255192pkey_raw(const unsigned char* key, size_t keylen)
 }
 #endif /* USE_ED25519 */
 
+#ifdef USE_ED448
+EVP_PKEY*
+sldns_ed4482pkey_raw(const unsigned char* key, size_t keylen)
+{
+       /* ASN1 for ED448 is 3043300506032b6571033a00 <57byteskey> */
+       uint8_t pre[] = {0x30, 0x43, 0x30, 0x05, 0x06, 0x03, 0x2b, 0x65,
+               0x71, 0x03, 0x3a, 0x00};
+        int pre_len = 12;
+       uint8_t buf[256];
+        EVP_PKEY *evp_key;
+       /* pp gets modified by d2i() */
+        const unsigned char* pp = (unsigned char*)buf;
+       if(keylen != 57 || keylen + pre_len > sizeof(buf))
+               return NULL; /* wrong length */
+       memmove(buf, pre, pre_len);
+       memmove(buf+pre_len, key, keylen);
+       evp_key = d2i_PUBKEY(NULL, &pp, (int)(pre_len+keylen));
+        return evp_key;
+}
+#endif /* USE_ED448 */
+
 int
 sldns_digest_evp(unsigned char* data, unsigned int len, unsigned char* dest,
        const EVP_MD* md)
index 19653b4..989b02c 100644 (file)
@@ -101,6 +101,15 @@ RSA *sldns_key_buf2rsa_raw(unsigned char* key, size_t len);
  */
 EVP_PKEY* sldns_ed255192pkey_raw(const unsigned char* key, size_t len);
 
+/**
+ * Converts a holding buffer with key material to EVP PKEY in openssl.
+ * Only available if ldns was compiled with ED448.
+ * \param[in] key the uncompressed wireformat of the key.
+ * \param[in] len length of key data
+ * \return the key or NULL on error.
+ */
+EVP_PKEY* sldns_ed4482pkey_raw(const unsigned char* key, size_t len);
+
 /**
  * Utility function to calculate hash using generic EVP_MD pointer.
  * \param[in] data the data to hash.
index fdb3557..1a51bb6 100644 (file)
@@ -1225,6 +1225,17 @@ int sldns_str2wire_b32_ext_buf(const char* str, uint8_t* rd, size_t* len)
        return LDNS_WIREPARSE_ERR_OK;
 }
 
+/** see if the string ends, or ends in whitespace */
+static int
+sldns_is_last_of_string(const char* str)
+{
+       if(*str == 0) return 1;
+       while(isspace((unsigned char)*str))
+               str++;
+       if(*str == 0) return 1;
+       return 0;
+}
+
 int sldns_str2wire_hex_buf(const char* str, uint8_t* rd, size_t* len)
 {
        const char* s = str;
@@ -1234,7 +1245,7 @@ int sldns_str2wire_hex_buf(const char* str, uint8_t* rd, size_t* len)
                        s++;
                        continue;
                }
-               if(dlen == 0 && *s == '0' && *(s+1) == 0) {
+               if(dlen == 0 && *s == '0' && sldns_is_last_of_string(s+1)) {
                        *len = 0;
                        return LDNS_WIREPARSE_ERR_OK;
                }
index e205c3e..37ba9ea 100644 (file)
@@ -542,7 +542,8 @@ morechecks(struct config_file* cfg, const char* fname)
 #  endif
        }
 #endif
-       if(cfg->remote_control_enable && cfg->remote_control_use_cert) {
+       if(cfg->remote_control_enable && options_remote_is_address(cfg)
+               && cfg->control_use_cert) {
                check_chroot_string("server-key-file", &cfg->server_key_file,
                        cfg->chrootdir, cfg);
                check_chroot_string("server-cert-file", &cfg->server_cert_file,
index 086afa8..d165417 100644 (file)
@@ -142,6 +142,7 @@ usage(void)
        printf("  ratelimit_list [+a]           list ratelimited domains\n");
        printf("  ip_ratelimit_list [+a]        list ratelimited ip addresses\n");
        printf("                +a              list all, also not ratelimited\n");
+       printf("  list_auth_zones               list auth zones\n");
        printf("  view_list_local_zones view    list local-zones in view\n");
        printf("  view_list_local_data  view    list local-data RRs in view\n");
        printf("  view_local_zone view name type        add local-zone in view\n");
@@ -349,6 +350,8 @@ static void print_extended(struct ub_stats_info* s)
        PR_UL("num.answer.secure", s->svr.ans_secure);
        PR_UL("num.answer.bogus", s->svr.ans_bogus);
        PR_UL("num.rrset.bogus", s->svr.rrset_bogus);
+       PR_UL("num.query.aggressive.NOERROR", s->svr.num_neg_cache_noerror);
+       PR_UL("num.query.aggressive.NXDOMAIN", s->svr.num_neg_cache_nxdomain);
        /* threat detection */
        PR_UL("unwanted.queries", s->svr.unwanted_queries);
        PR_UL("unwanted.replies", s->svr.unwanted_replies);
@@ -366,6 +369,8 @@ static void print_extended(struct ub_stats_info* s)
        PR_UL("num.query.dnscrypt.replay",
                         s->svr.num_query_dnscrypt_replay);
 #endif /* USE_DNSCRYPT */
+       PR_UL("num.query.authzone.up", s->svr.num_query_authzone_up);
+       PR_UL("num.query.authzone.down", s->svr.num_query_authzone_down);
 }
 
 /** print statistics out of memory structures */
@@ -446,42 +451,33 @@ setup_ctx(struct config_file* cfg)
        char* s_cert=NULL, *c_key=NULL, *c_cert=NULL;
        SSL_CTX* ctx;
 
-       if(cfg->remote_control_use_cert) {
-               s_cert = fname_after_chroot(cfg->server_cert_file, cfg, 1);
-               c_key = fname_after_chroot(cfg->control_key_file, cfg, 1);
-               c_cert = fname_after_chroot(cfg->control_cert_file, cfg, 1);
-               if(!s_cert || !c_key || !c_cert)
-                       fatal_exit("out of memory");
-       }
+       if(!(options_remote_is_address(cfg) && cfg->control_use_cert))
+               return NULL;
+       s_cert = fname_after_chroot(cfg->server_cert_file, cfg, 1);
+       c_key = fname_after_chroot(cfg->control_key_file, cfg, 1);
+       c_cert = fname_after_chroot(cfg->control_cert_file, cfg, 1);
+       if(!s_cert || !c_key || !c_cert)
+               fatal_exit("out of memory");
        ctx = SSL_CTX_new(SSLv23_client_method());
        if(!ctx)
                ssl_err("could not allocate SSL_CTX pointer");
        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");
-       if(cfg->remote_control_use_cert) {
-               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");
-               if(!SSL_CTX_use_certificate_chain_file(ctx,c_cert) ||
-                   !SSL_CTX_use_PrivateKey_file(ctx,c_key,SSL_FILETYPE_PEM)
-                   || !SSL_CTX_check_private_key(ctx))
-                       ssl_err("Error setting up SSL_CTX client key and cert");
-               if (SSL_CTX_load_verify_locations(ctx, s_cert, NULL) != 1)
-                       ssl_err("Error setting up SSL_CTX verify, server cert");
-               SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL);
-
-               free(s_cert);
-               free(c_key);
-               free(c_cert);
-       } else {
-               /* Use ciphers that don't require authentication  */
-#ifdef HAVE_SSL_CTX_SET_SECURITY_LEVEL
-               SSL_CTX_set_security_level(ctx, 0);
-#endif
-               if(!SSL_CTX_set_cipher_list(ctx, "aNULL, eNULL"))
-                       ssl_err("Error setting NULL cipher!");
-       }
+       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");
+       if(!SSL_CTX_use_certificate_chain_file(ctx,c_cert) ||
+           !SSL_CTX_use_PrivateKey_file(ctx,c_key,SSL_FILETYPE_PEM)
+           || !SSL_CTX_check_private_key(ctx))
+               ssl_err("Error setting up SSL_CTX client key and cert");
+       if (SSL_CTX_load_verify_locations(ctx, s_cert, NULL) != 1)
+               ssl_err("Error setting up SSL_CTX verify, server cert");
+       SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL);
+
+       free(s_cert);
+       free(c_key);
+       free(c_cert);
        return ctx;
 }
 
@@ -491,12 +487,12 @@ contact_server(const char* svr, struct config_file* cfg, int statuscmd)
 {
        struct sockaddr_storage addr;
        socklen_t addrlen;
-       int addrfamily = 0;
-       int fd;
+       int addrfamily = 0, proto = IPPROTO_TCP;
+       int fd, useport = 1;
        /* use svr or the first config entry */
        if(!svr) {
-               if(cfg->control_ifs) {
-                       svr = cfg->control_ifs->str;
+               if(cfg->control_ifs.first) {
+                       svr = cfg->control_ifs.first->str;
                } else if(cfg->do_ip4) {
                        svr = "127.0.0.1";
                } else {
@@ -524,6 +520,8 @@ contact_server(const char* svr, struct config_file* cfg, int statuscmd)
                (void)strlcpy(usock->sun_path, svr, sizeof(usock->sun_path));
                addrlen = (socklen_t)sizeof(struct sockaddr_un);
                addrfamily = AF_LOCAL;
+               useport = 0;
+               proto = 0;
 #endif
        } else {
                if(!ipstrtoaddr(svr, cfg->control_port, &addr, &addrlen))
@@ -531,8 +529,8 @@ contact_server(const char* svr, struct config_file* cfg, int statuscmd)
        }
 
        if(addrfamily == 0)
-               addrfamily = addr_is_ip6(&addr, addrlen)?AF_INET6:AF_INET;
-       fd = socket(addrfamily, SOCK_STREAM, 0);
+               addrfamily = addr_is_ip6(&addr, addrlen)?PF_INET6:PF_INET;
+       fd = socket(addrfamily, SOCK_STREAM, proto);
        if(fd == -1) {
 #ifndef USE_WINSOCK
                fatal_exit("socket: %s", strerror(errno));
@@ -542,14 +540,18 @@ contact_server(const char* svr, struct config_file* cfg, int statuscmd)
        }
        if(connect(fd, (struct sockaddr*)&addr, addrlen) < 0) {
 #ifndef USE_WINSOCK
-               log_err_addr("connect", strerror(errno), &addr, addrlen);
-               if(errno == ECONNREFUSED && statuscmd) {
+               int err = errno;
+               if(!useport) log_err("connect: %s for %s", strerror(err), svr);
+               else log_err_addr("connect", strerror(err), &addr, addrlen);
+               if(err == ECONNREFUSED && statuscmd) {
                        printf("unbound is stopped\n");
                        exit(3);
                }
 #else
-               log_err_addr("connect", wsa_strerror(WSAGetLastError()), &addr, addrlen);
-               if(WSAGetLastError() == WSAECONNREFUSED && statuscmd) {
+               int wsaerr = WSAGetLastError();
+               if(!useport) log_err("connect: %s for %s", wsa_strerror(wsaerr), svr);
+               else log_err_addr("connect", wsa_strerror(wsaerr), &addr, addrlen);
+               if(wsaerr == WSAECONNREFUSED && statuscmd) {
                        printf("unbound is stopped\n");
                        exit(3);
                }
@@ -561,12 +563,13 @@ contact_server(const char* svr, struct config_file* cfg, int statuscmd)
 
 /** setup SSL on the connection */
 static SSL*
-setup_ssl(SSL_CTX* ctx, int fd, struct config_file* cfg)
+setup_ssl(SSL_CTX* ctx, int fd)
 {
        SSL* ssl;
        X509* x;
        int r;
 
+       if(!ctx) return NULL;
        ssl = SSL_new(ctx);
        if(!ssl)
                ssl_err("could not SSL_new");
@@ -587,78 +590,115 @@ setup_ssl(SSL_CTX* ctx, int fd, struct config_file* cfg)
        /* check authenticity of server */
        if(SSL_get_verify_result(ssl) != X509_V_OK)
                ssl_err("SSL verification failed");
-       if(cfg->remote_control_use_cert) {
-               x = SSL_get_peer_certificate(ssl);
-               if(!x)
-                       ssl_err("Server presented no peer certificate");
-               X509_free(x);
-       }
+       x = SSL_get_peer_certificate(ssl);
+       if(!x)
+               ssl_err("Server presented no peer certificate");
+       X509_free(x);
 
        return ssl;
 }
 
+/** read from ssl or fd, fatalexit on error, 0 EOF, 1 success */
+static int
+remote_read(SSL* ssl, int fd, char* buf, size_t len)
+{
+       if(ssl) {
+               int r;
+               ERR_clear_error();
+               if((r = SSL_read(ssl, buf, (int)len-1)) <= 0) {
+                       if(SSL_get_error(ssl, r) == SSL_ERROR_ZERO_RETURN) {
+                               /* EOF */
+                               return 0;
+                       }
+                       ssl_err("could not SSL_read");
+               }
+               buf[r] = 0;
+       } else {
+               ssize_t rr = recv(fd, buf, len-1, 0);
+               if(rr <= 0) {
+                       if(rr == 0) {
+                               /* EOF */
+                               return 0;
+                       }
+#ifndef USE_WINSOCK
+                       fatal_exit("could not recv: %s", strerror(errno));
+#else
+                       fatal_exit("could not recv: %s", wsa_strerror(WSAGetLastError()));
+#endif
+               }
+               buf[rr] = 0;
+       }
+       return 1;
+}
+
+/** write to ssl or fd, fatalexit on error */
+static void
+remote_write(SSL* ssl, int fd, const char* buf, size_t len)
+{
+       if(ssl) {
+               if(SSL_write(ssl, buf, (int)len) <= 0)
+                       ssl_err("could not SSL_write");
+       } else {
+               if(send(fd, buf, len, 0) < (ssize_t)len) {
+#ifndef USE_WINSOCK
+                       fatal_exit("could not send: %s", strerror(errno));
+#else
+                       fatal_exit("could not send: %s", wsa_strerror(WSAGetLastError()));
+#endif
+               }
+       }
+}
+
 /** send stdin to server */
 static void
-send_file(SSL* ssl, FILE* in, char* buf, size_t sz)
+send_file(SSL* ssl, int fd, FILE* in, char* buf, size_t sz)
 {
        while(fgets(buf, (int)sz, in)) {
-               if(SSL_write(ssl, buf, (int)strlen(buf)) <= 0)
-                       ssl_err("could not SSL_write contents");
+               remote_write(ssl, fd, buf, strlen(buf));
        }
 }
 
 /** send end-of-file marker to server */
 static void
-send_eof(SSL* ssl)
+send_eof(SSL* ssl, int fd)
 {
        char e[] = {0x04, 0x0a};
-       if(SSL_write(ssl, e, (int)sizeof(e)) <= 0)
-               ssl_err("could not SSL_write end-of-file marker");
+       remote_write(ssl, fd, e, sizeof(e));
 }
 
 /** send command and display result */
 static int
-go_cmd(SSL* ssl, int quiet, int argc, char* argv[])
+go_cmd(SSL* ssl, int fd, int quiet, int argc, char* argv[])
 {
        char pre[10];
        const char* space=" ";
        const char* newline="\n";
        int was_error = 0, first_line = 1;
-       int r, i;
+       int i;
        char buf[1024];
        snprintf(pre, sizeof(pre), "UBCT%d ", UNBOUND_CONTROL_VERSION);
-       if(SSL_write(ssl, pre, (int)strlen(pre)) <= 0)
-               ssl_err("could not SSL_write");
+       remote_write(ssl, fd, pre, strlen(pre));
        for(i=0; i<argc; i++) {
-               if(SSL_write(ssl, space, (int)strlen(space)) <= 0)
-                       ssl_err("could not SSL_write");
-               if(SSL_write(ssl, argv[i], (int)strlen(argv[i])) <= 0)
-                       ssl_err("could not SSL_write");
+               remote_write(ssl, fd, space, strlen(space));
+               remote_write(ssl, fd, argv[i], strlen(argv[i]));
        }
-       if(SSL_write(ssl, newline, (int)strlen(newline)) <= 0)
-               ssl_err("could not SSL_write");
+       remote_write(ssl, fd, newline, strlen(newline));
 
        if(argc == 1 && strcmp(argv[0], "load_cache") == 0) {
-               send_file(ssl, stdin, buf, sizeof(buf));
+               send_file(ssl, fd, stdin, buf, sizeof(buf));
        }
        else if(argc == 1 && (strcmp(argv[0], "local_zones") == 0 ||
                strcmp(argv[0], "local_zones_remove") == 0 ||
                strcmp(argv[0], "local_datas") == 0 ||
                strcmp(argv[0], "local_datas_remove") == 0)) {
-               send_file(ssl, stdin, buf, sizeof(buf));
-               send_eof(ssl);
+               send_file(ssl, fd, stdin, buf, sizeof(buf));
+               send_eof(ssl, fd);
        }
 
        while(1) {
-               ERR_clear_error();
-               if((r = SSL_read(ssl, buf, (int)sizeof(buf)-1)) <= 0) {
-                       if(SSL_get_error(ssl, r) == SSL_ERROR_ZERO_RETURN) {
-                               /* EOF */
-                               break;
-                       }
-                       ssl_err("could not SSL_read");
+               if(remote_read(ssl, fd, buf, sizeof(buf)) == 0) {
+                       break; /* EOF */
                }
-               buf[r] = 0;
                if(first_line && strncmp(buf, "error", 5) == 0) {
                        printf("%s", buf);
                        was_error = 1;
@@ -693,18 +733,18 @@ go(const char* cfgfile, char* svr, int quiet, int argc, char* argv[])
 
        /* contact server */
        fd = contact_server(svr, cfg, argc>0&&strcmp(argv[0],"status")==0);
-       ssl = setup_ssl(ctx, fd, cfg);
+       ssl = setup_ssl(ctx, fd);
 
        /* send command */
-       ret = go_cmd(ssl, quiet, argc, argv);
+       ret = go_cmd(ssl, fd, quiet, argc, argv);
 
-       SSL_free(ssl);
+       if(ssl) SSL_free(ssl);
 #ifndef USE_WINSOCK
        close(fd);
 #else
        closesocket(fd);
 #endif
-       SSL_CTX_free(ctx);
+       if(ctx) SSL_CTX_free(ctx);
        config_delete(cfg);
        return ret;
 }
index 93b5e48..cd1ffe3 100644 (file)
 /* nss3 */
 #include "nss.h"
 #endif
+#ifdef HAVE_SSL
+#ifdef HAVE_OPENSSL_SSL_H
+#include <openssl/ssl.h>
+#endif
+#ifdef HAVE_OPENSSL_ERR_H
+#include <openssl/err.h>
+#endif
+#endif /* HAVE_SSL */
 
 /** verbosity for unbound-host app */
 static int verb = 0;
@@ -487,6 +495,26 @@ int main(int argc, char* argv[])
        if(argc != 1)
                usage();
 
+#ifdef HAVE_SSL
+#ifdef HAVE_ERR_LOAD_CRYPTO_STRINGS
+       ERR_load_crypto_strings();
+#endif
+#if OPENSSL_VERSION_NUMBER < 0x10100000 || !defined(HAVE_OPENSSL_INIT_SSL)
+       ERR_load_SSL_strings();
+#endif
+#if OPENSSL_VERSION_NUMBER < 0x10100000 || !defined(HAVE_OPENSSL_INIT_CRYPTO)
+       OpenSSL_add_all_algorithms();
+#else
+       OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS
+               | OPENSSL_INIT_ADD_ALL_DIGESTS
+               | OPENSSL_INIT_LOAD_CRYPTO_STRINGS, NULL);
+#endif
+#if OPENSSL_VERSION_NUMBER < 0x10100000 || !defined(HAVE_OPENSSL_INIT_SSL)
+       (void)SSL_library_init();
+#else
+       (void)OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS, NULL);
+#endif
+#endif /* HAVE_SSL */
 #ifdef HAVE_NSS
         if(NSS_NoDB_Init(".") != SECSuccess) {
                fprintf(stderr, "could not init NSS\n");
index e88e8c8..dda94cc 100644 (file)
@@ -105,7 +105,7 @@ struct outbound_entry* worker_send_query(
        int ATTR_UNUSED(nocaps), struct sockaddr_storage* ATTR_UNUSED(addr),
        socklen_t ATTR_UNUSED(addrlen), uint8_t* ATTR_UNUSED(zone),
        size_t ATTR_UNUSED(zonelen), int ATTR_UNUSED(ssl_upstream),
-       struct module_qstate* ATTR_UNUSED(q))
+       char* ATTR_UNUSED(tls_auth_name), struct module_qstate* ATTR_UNUSED(q))
 {
        log_assert(0);
        return 0;
@@ -137,7 +137,7 @@ struct outbound_entry* libworker_send_query(
        int ATTR_UNUSED(nocaps), struct sockaddr_storage* ATTR_UNUSED(addr),
        socklen_t ATTR_UNUSED(addrlen), uint8_t* ATTR_UNUSED(zone),
        size_t ATTR_UNUSED(zonelen), int ATTR_UNUSED(ssl_upstream),
-       struct module_qstate* ATTR_UNUSED(q))
+       char* ATTR_UNUSED(tls_auth_name), struct module_qstate* ATTR_UNUSED(q))
 {
        log_assert(0);
        return 0;
index 2c6e1a2..908b1f4 100644 (file)
@@ -126,10 +126,40 @@ alloc_init(struct alloc_cache* alloc, struct alloc_cache* super,
        }
 }
 
+/** free the special list */
+static void
+alloc_clear_special_list(struct alloc_cache* alloc)
+{
+       alloc_special_type* p, *np;
+       /* free */
+       p = alloc->quar;
+       while(p) {
+               np = alloc_special_next(p);
+               /* deinit special type */
+               lock_rw_destroy(&p->entry.lock);
+               free(p);
+               p = np;
+       }
+}
+
+void
+alloc_clear_special(struct alloc_cache* alloc)
+{
+       if(!alloc->super) {
+               lock_quick_lock(&alloc->lock);
+       }
+       alloc_clear_special_list(alloc);
+       alloc->quar = 0;
+       alloc->num_quar = 0;
+       if(!alloc->super) {
+               lock_quick_unlock(&alloc->lock);
+       }
+}
+
 void 
 alloc_clear(struct alloc_cache* alloc)
 {
-       alloc_special_type* p, *np;
+       alloc_special_type* p;
        struct regional* r, *nr;
        if(!alloc)
                return;
@@ -147,15 +177,7 @@ alloc_clear(struct alloc_cache* alloc)
                alloc->super->num_quar += alloc->num_quar;
                lock_quick_unlock(&alloc->super->lock);
        } else {
-               /* free */
-               p = alloc->quar;
-               while(p) {
-                       np = alloc_special_next(p);
-                       /* deinit special type */
-                       lock_rw_destroy(&p->entry.lock);
-                       free(p);
-                       p = np;
-               }
+               alloc_clear_special_list(alloc);
        }
        alloc->quar = 0;
        alloc->num_quar = 0;
index 9839a45..ee03b07 100644 (file)
@@ -115,6 +115,14 @@ void alloc_init(struct alloc_cache* alloc, struct alloc_cache* super,
  */
 void alloc_clear(struct alloc_cache* alloc);
 
+/**
+ * Free the special alloced items.  The rrset and message caches must be
+ * empty, there must be no more references to rrset pointers into the
+ * rrset cache.
+ * @param alloc: the special allocs are freed.
+ */
+void alloc_clear_special(struct alloc_cache* alloc);
+
 /**
  * Get a new special_type element.
  * @param alloc: where to alloc it.
index 02c9d15..5513144 100644 (file)
@@ -106,9 +106,10 @@ config_create(void)
        cfg->outgoing_tcp_mss = 0;
        cfg->ssl_service_key = NULL;
        cfg->ssl_service_pem = NULL;
-       cfg->ssl_port = 853;
+       cfg->ssl_port = UNBOUND_DNS_OVER_TLS_PORT;
        cfg->ssl_upstream = 0;
        cfg->tls_cert_bundle = NULL;
+       cfg->tls_win_cert = 0;
        cfg->use_syslog = 1;
        cfg->log_identity = NULL; /* changed later with argv[0] */
        cfg->log_time_ascii = 0;
@@ -161,6 +162,8 @@ config_create(void)
        if(!(cfg->logfile = strdup(""))) goto error_exit;
        if(!(cfg->pidfile = strdup(PIDFILE))) goto error_exit;
        if(!(cfg->target_fetch_policy = strdup("3 2 1 0 0"))) goto error_exit;
+       cfg->low_rtt_permil = 0;
+       cfg->low_rtt = 45;
        cfg->donotqueryaddrs = NULL;
        cfg->donotquery_localhost = 1;
        cfg->root_hints = NULL;
@@ -211,6 +214,7 @@ config_create(void)
        cfg->trust_anchor_list = NULL;
        cfg->trusted_keys_file_list = NULL;
        cfg->trust_anchor_signaling = 0;
+       cfg->root_key_sentinel = 1;
        cfg->dlv_anchor_file = NULL;
        cfg->dlv_anchor_list = NULL;
        cfg->domain_insecure = NULL;
@@ -240,9 +244,10 @@ config_create(void)
        cfg->insecure_lan_zones = 0;
        cfg->python_script = NULL;
        cfg->remote_control_enable = 0;
-       cfg->control_ifs = NULL;
+       cfg->control_ifs.first = NULL;
+       cfg->control_ifs.last = NULL;
        cfg->control_port = UNBOUND_CONTROL_PORT;
-       cfg->remote_control_use_cert = 1;
+       cfg->control_use_cert = 1;
        cfg->minimal_responses = 0;
        cfg->rrset_roundrobin = 0;
        cfg->max_udp_size = 4096;
@@ -277,7 +282,7 @@ config_create(void)
        cfg->ratelimit_below_domain = NULL;
        cfg->ip_ratelimit_factor = 10;
        cfg->ratelimit_factor = 10;
-       cfg->qname_minimisation = 0;
+       cfg->qname_minimisation = 1;
        cfg->qname_minimisation_strict = 0;
        cfg->shm_enable = 0;
        cfg->shm_key = 11777;
@@ -382,10 +387,19 @@ struct config_file* config_create_forlib(void)
 #define S_STRLIST_UNIQ(str, var) if(strcmp(opt, str)==0) \
        { if(cfg_strlist_find(cfg->var, val)) { return 0;} \
          return cfg_strlist_insert(&cfg->var, strdup(val)); }
+/** append string to strlist */
+#define S_STRLIST_APPEND(str, var) if(strcmp(opt, str)==0) \
+       { return cfg_strlist_append(&cfg->var, strdup(val)); }
 
 int config_set_option(struct config_file* cfg, const char* opt,
        const char* val)
 {
+       char buf[64];
+       if(!opt) return 0;
+       if(opt[strlen(opt)-1] != ':' && strlen(opt)+2<sizeof(buf)) {
+               snprintf(buf, sizeof(buf), "%s:", opt);
+               opt = buf;
+       }
        S_NUMBER_OR_ZERO("verbosity:", verbosity)
        else if(strcmp(opt, "statistics-interval:") == 0) {
                if(strcmp(val, "0") == 0 || strcmp(val, "") == 0)
@@ -446,6 +460,10 @@ int config_set_option(struct config_file* cfg, const char* opt,
        else S_STR("ssl-service-pem:", ssl_service_pem)
        else S_NUMBER_NONZERO("ssl-port:", ssl_port)
        else S_STR("tls-cert-bundle:", tls_cert_bundle)
+       else S_YNO("tls-win-cert:", tls_win_cert)
+       else S_STRLIST("additional-tls-port:", tls_additional_port)
+       else S_STRLIST("tls-additional-ports:", tls_additional_port)
+       else S_STRLIST("tls-additional-port:", tls_additional_port)
        else S_YNO("interface-automatic:", if_automatic)
        else S_YNO("use-systemd:", use_systemd)
        else S_YNO("do-daemonize:", do_daemonize)
@@ -500,7 +518,7 @@ int config_set_option(struct config_file* cfg, const char* opt,
        else S_YNO("harden-below-nxdomain:", harden_below_nxdomain)
        else S_YNO("harden-referral-path:", harden_referral_path)
        else S_YNO("harden-algo-downgrade:", harden_algo_downgrade)
-       else S_YNO("use-caps-for-id", use_caps_bits_for_id)
+       else S_YNO("use-caps-for-id:", use_caps_bits_for_id)
        else S_STRLIST("caps-whitelist:", caps_whitelist)
        else S_SIZET_OR_ZERO("unwanted-reply-threshold:", unwanted_threshold)
        else S_STRLIST("private-address:", private_address)
@@ -512,6 +530,7 @@ int config_set_option(struct config_file* cfg, const char* opt,
        else S_STRLIST("trust-anchor:", trust_anchor_list)
        else S_STRLIST("trusted-keys-file:", trusted_keys_file_list)
        else S_YNO("trust-anchor-signaling:", trust_anchor_signaling)
+       else S_YNO("root-key-sentinel:", root_key_sentinel)
        else S_STR("dlv-anchor-file:", dlv_anchor_file)
        else S_STRLIST("dlv-anchor:", dlv_anchor_list)
        else S_STRLIST("domain-insecure:", domain_insecure)
@@ -541,7 +560,7 @@ int config_set_option(struct config_file* cfg, const char* opt,
        else S_YNO("unblock-lan-zones:", unblock_lan_zones)
        else S_YNO("insecure-lan-zones:", insecure_lan_zones)
        else S_YNO("control-enable:", remote_control_enable)
-       else S_STRLIST("control-interface:", control_ifs)
+       else S_STRLIST_APPEND("control-interface:", control_ifs)
        else S_NUMBER_NONZERO("control-port:", control_port)
        else S_STR("server-key-file:", server_key_file)
        else S_STR("server-cert-file:", server_cert_file)
@@ -606,6 +625,9 @@ int config_set_option(struct config_file* cfg, const char* opt,
        else S_POW2("ratelimit-slabs:", ratelimit_slabs)
        else S_NUMBER_OR_ZERO("ip-ratelimit-factor:", ip_ratelimit_factor)
        else S_NUMBER_OR_ZERO("ratelimit-factor:", ratelimit_factor)
+       else S_NUMBER_OR_ZERO("low-rtt:", low_rtt)
+       else S_NUMBER_OR_ZERO("low-rtt-pct:", low_rtt_permil)
+       else S_NUMBER_OR_ZERO("low-rtt-permil:", low_rtt_permil)
        else S_YNO("qname-minimisation:", qname_minimisation)
        else S_YNO("qname-minimisation-strict:", qname_minimisation_strict)
 #ifdef USE_IPSECMOD
@@ -800,8 +822,13 @@ int
 config_get_option(struct config_file* cfg, const char* opt, 
        void (*func)(char*,void*), void* arg)
 {
-       char buf[1024];
+       char buf[1024], nopt[64];
        size_t len = sizeof(buf);
+       if(opt && opt[strlen(opt)-1] == ':' && strlen(opt)<sizeof(nopt)) {
+               memmove(nopt, opt, strlen(opt));
+               nopt[strlen(opt)-1] = 0;
+               opt = nopt;
+       }
        fptr_ok(fptr_whitelist_print_func(func));
        O_DEC(opt, "verbosity", verbosity)
        else O_DEC(opt, "statistics-interval", stat_interval)
@@ -856,6 +883,8 @@ config_get_option(struct config_file* cfg, const char* opt,
        else O_STR(opt, "ssl-service-pem", ssl_service_pem)
        else O_DEC(opt, "ssl-port", ssl_port)
        else O_STR(opt, "tls-cert-bundle", tls_cert_bundle)
+       else O_YNO(opt, "tls-win-cert", tls_win_cert)
+       else O_LST(opt, "tls-additional-port", tls_additional_port)
        else O_YNO(opt, "use-systemd", use_systemd)
        else O_YNO(opt, "do-daemonize", do_daemonize)
        else O_STR(opt, "chroot", chrootdir)
@@ -888,7 +917,7 @@ config_get_option(struct config_file* cfg, const char* opt,
        else O_YNO(opt, "val-clean-additional", val_clean_additional)
        else O_DEC(opt, "val-log-level", val_log_level)
        else O_YNO(opt, "val-permissive-mode", val_permissive_mode)
-       else O_YNO(opt, "aggressive-nsec:", aggressive_nsec)
+       else O_YNO(opt, "aggressive-nsec", aggressive_nsec)
        else O_YNO(opt, "ignore-cd-flag", ignore_cd)
        else O_YNO(opt, "serve-expired", serve_expired)
        else O_STR(opt, "val-nsec3-keysize-iterations",val_nsec3_key_iterations)
@@ -915,8 +944,9 @@ config_get_option(struct config_file* cfg, const char* opt,
        else O_LST(opt, "trust-anchor", trust_anchor_list)
        else O_LST(opt, "trusted-keys-file", trusted_keys_file_list)
        else O_YNO(opt, "trust-anchor-signaling", trust_anchor_signaling)
+       else O_YNO(opt, "root-key-sentinel", root_key_sentinel)
        else O_LST(opt, "dlv-anchor", dlv_anchor_list)
-       else O_LST(opt, "control-interface", control_ifs)
+       else O_LST(opt, "control-interface", control_ifs.first)
        else O_LST(opt, "domain-insecure", domain_insecure)
        else O_UNS(opt, "val-override-date", val_date_override)
        else O_YNO(opt, "minimal-responses", minimal_responses)
@@ -980,6 +1010,9 @@ config_get_option(struct config_file* cfg, const char* opt,
        else O_LS2(opt, "ratelimit-below-domain", ratelimit_below_domain)
        else O_DEC(opt, "ip-ratelimit-factor", ip_ratelimit_factor)
        else O_DEC(opt, "ratelimit-factor", ratelimit_factor)
+       else O_DEC(opt, "low-rtt", low_rtt)
+       else O_DEC(opt, "low-rtt-pct", low_rtt_permil)
+       else O_DEC(opt, "low-rtt-permil", low_rtt_permil)
        else O_DEC(opt, "val-sig-skew-min", val_sig_skew_min)
        else O_DEC(opt, "val-sig-skew-max", val_sig_skew_max)
        else O_YNO(opt, "qname-minimisation", qname_minimisation)
@@ -1178,6 +1211,7 @@ config_delauth(struct config_auth* p)
        free(p->name);
        config_delstrlist(p->masters);
        config_delstrlist(p->urls);
+       config_delstrlist(p->allow_notify);
        free(p->zonefile);
        free(p);
 }
@@ -1274,6 +1308,7 @@ config_delete(struct config_file* cfg)
        free(cfg->ssl_service_key);
        free(cfg->ssl_service_pem);
        free(cfg->tls_cert_bundle);
+       config_delstrlist(cfg->tls_additional_port);
        free(cfg->log_identity);
        config_del_strarray(cfg->ifs, cfg->num_ifs);
        config_del_strarray(cfg->out_ifs, cfg->num_out_ifs);
@@ -1314,7 +1349,7 @@ config_delete(struct config_file* cfg)
        config_del_strbytelist(cfg->respip_tags);
        config_deltrplstrlist(cfg->acl_tag_actions);
        config_deltrplstrlist(cfg->acl_tag_datas);
-       config_delstrlist(cfg->control_ifs);
+       config_delstrlist(cfg->control_ifs.first);
        free(cfg->server_key_file);
        free(cfg->server_cert_file);
        free(cfg->control_key_file);
@@ -2234,3 +2269,12 @@ void errinf_dname(struct module_qstate* qstate, const char* str, uint8_t* dname)
        snprintf(b, sizeof(b), "%s %s", str, buf);
        errinf(qstate, b);
 }
+
+int options_remote_is_address(struct config_file* cfg)
+{
+       if(!cfg->remote_control_enable) return 0;
+       if(!cfg->control_ifs.first) return 1;
+       if(!cfg->control_ifs.first->str) return 1;
+       if(cfg->control_ifs.first->str[0] == 0) return 1;
+       return (cfg->control_ifs.first->str[0] != '/');
+}
index 2e1c53e..4206eb9 100644 (file)
@@ -53,6 +53,14 @@ struct sock_list;
 struct ub_packed_rrset_key;
 struct regional;
 
+/** List head for strlist processing, used for append operation. */
+struct config_strlist_head {
+       /** first in list of text items */
+       struct config_strlist* first;
+       /** last in list of text items */
+       struct config_strlist* last;
+};
+
 /**
  * The configuration options.
  * Strings are malloced.
@@ -102,6 +110,10 @@ struct config_file {
        int ssl_upstream;
        /** cert bundle for outgoing connections */
        char* tls_cert_bundle;
+       /** should the system certificate store get added to the cert bundle */
+       int tls_win_cert;
+       /** additional tls ports */
+       struct config_strlist* tls_additional_port;
 
        /** outgoing port range number of ports (per thread) */
        int outgoing_num_ports;
@@ -141,6 +153,10 @@ struct config_file {
 
        /** the target fetch policy for the iterator */
        char* target_fetch_policy;
+       /** percent*10, how many times in 1000 to pick low rtt destinations */
+       int low_rtt_permil;
+       /** what time in msec is a low rtt destination */
+       int low_rtt;
 
        /** automatic interface for incoming messages. Uses ipv6 remapping,
         * and recvmsg/sendmsg ancillary data to detect interfaces, boolean */
@@ -285,6 +301,8 @@ struct config_file {
        struct config_strlist* domain_insecure;
        /** send key tag query */
        int trust_anchor_signaling;
+       /** enable root key sentinel */
+       int root_key_sentinel;
 
        /** if not 0, this value is the validation date for RRSIGs */
        int32_t val_date_override;
@@ -364,11 +382,11 @@ struct config_file {
        /** remote control section. enable toggle. */
        int remote_control_enable;
        /** the interfaces the remote control should listen on */
-       struct config_strlist* control_ifs;
+       struct config_strlist_head control_ifs;
+       /** if the use-cert option is set */
+       int control_use_cert;
        /** port number for the control port */
        int control_port;
-       /** use certificates for remote control */
-       int remote_control_use_cert;
        /** private key file for server */
        char* server_key_file;
        /** certificate file for server */
@@ -507,6 +525,14 @@ struct config_file {
        char* cachedb_backend;
        /** secret seed for hash key calculation */
        char* cachedb_secret;
+#ifdef USE_REDIS
+       /** redis server's IP address or host name */
+       char* redis_server_host;
+       /** redis server's TCP port */
+       int redis_server_port;
+       /** timeout (in ms) for communication with the redis server */
+       int redis_timeout;
+#endif
 #endif
 };
 
@@ -549,6 +575,8 @@ struct config_auth {
        struct config_strlist* masters;
        /** list of urls */
        struct config_strlist* urls;
+       /** list of allow-notify */
+       struct config_strlist* allow_notify;
        /** zonefile (or NULL) */
        char* zonefile;
        /** provide downstream answers */
@@ -633,14 +661,6 @@ struct config_strbytelist {
        size_t str2len;
 };
 
-/** List head for strlist processing, used for append operation. */
-struct config_strlist_head {
-       /** first in list of text items */
-       struct config_strlist* first;
-       /** last in list of text items */
-       struct config_strlist* last;
-};
-
 /**
  * Create config file structure. Filled with default values.
  * @return: the new structure or NULL on memory error.
@@ -874,6 +894,10 @@ void config_delview(struct config_view* p);
  */
 void config_delviews(struct config_view* list);
 
+/** check if config for remote control turns on IP-address interface
+ * with certificates or a named pipe without certificates. */
+int options_remote_is_address(struct config_file* cfg);
+
 /**
  * Convert 14digit to time value
  * @param str: string of 14 digits
index 0e158d1..6124e32 100644 (file)
@@ -238,6 +238,11 @@ ssl-port{COLON}                    { YDVAR(1, VAR_SSL_PORT) }
 tls-port{COLON}                        { YDVAR(1, VAR_SSL_PORT) }
 ssl-cert-bundle{COLON}         { YDVAR(1, VAR_TLS_CERT_BUNDLE) }
 tls-cert-bundle{COLON}         { YDVAR(1, VAR_TLS_CERT_BUNDLE) }
+tls-win-cert{COLON}            { YDVAR(1, VAR_TLS_WIN_CERT) }
+additional-ssl-port{COLON}     { YDVAR(1, VAR_TLS_ADDITIONAL_PORT) }
+additional-tls-port{COLON}     { YDVAR(1, VAR_TLS_ADDITIONAL_PORT) }
+tls-additional-ports{COLON}    { YDVAR(1, VAR_TLS_ADDITIONAL_PORT) }
+tls-additional-port{COLON}     { YDVAR(1, VAR_TLS_ADDITIONAL_PORT) }
 use-systemd{COLON}             { YDVAR(1, VAR_USE_SYSTEMD) }
 do-daemonize{COLON}            { YDVAR(1, VAR_DO_DAEMONIZE) }
 interface{COLON}               { YDVAR(1, VAR_INTERFACE) }
@@ -306,6 +311,7 @@ auth-zone{COLON}            { YDVAR(0, VAR_AUTH_ZONE) }
 zonefile{COLON}                        { YDVAR(1, VAR_ZONEFILE) }
 master{COLON}                  { YDVAR(1, VAR_MASTER) }
 url{COLON}                     { YDVAR(1, VAR_URL) }
+allow-notify{COLON}            { YDVAR(1, VAR_ALLOW_NOTIFY) }
 for-downstream{COLON}          { YDVAR(1, VAR_FOR_DOWNSTREAM) }
 for-upstream{COLON}            { YDVAR(1, VAR_FOR_UPSTREAM) }
 fallback-enabled{COLON}                { YDVAR(1, VAR_FALLBACK_ENABLED) }
@@ -333,6 +339,7 @@ auto-trust-anchor-file{COLON}       { YDVAR(1, VAR_AUTO_TRUST_ANCHOR_FILE) }
 trusted-keys-file{COLON}       { YDVAR(1, VAR_TRUSTED_KEYS_FILE) }
 trust-anchor{COLON}            { YDVAR(1, VAR_TRUST_ANCHOR) }
 trust-anchor-signaling{COLON}  { YDVAR(1, VAR_TRUST_ANCHOR_SIGNALING) }
+root-key-sentinel{COLON}       { YDVAR(1, VAR_ROOT_KEY_SENTINEL) }
 val-override-date{COLON}       { YDVAR(1, VAR_VAL_OVERRIDE_DATE) }
 val-sig-skew-min{COLON}                { YDVAR(1, VAR_VAL_SIG_SKEW_MIN) }
 val-sig-skew-max{COLON}                { YDVAR(1, VAR_VAL_SIG_SKEW_MAX) }
@@ -423,6 +430,9 @@ ratelimit-for-domain{COLON} { YDVAR(2, VAR_RATELIMIT_FOR_DOMAIN) }
 ratelimit-below-domain{COLON}  { YDVAR(2, VAR_RATELIMIT_BELOW_DOMAIN) }
 ip-ratelimit-factor{COLON}             { YDVAR(1, VAR_IP_RATELIMIT_FACTOR) }
 ratelimit-factor{COLON}                { YDVAR(1, VAR_RATELIMIT_FACTOR) }
+low-rtt{COLON}                 { YDVAR(1, VAR_LOW_RTT) }
+low-rtt-pct{COLON}             { YDVAR(1, VAR_LOW_RTT_PERMIL) }
+low-rtt-permil{COLON}          { YDVAR(1, VAR_LOW_RTT_PERMIL) }
 response-ip-tag{COLON}         { YDVAR(2, VAR_RESPONSE_IP_TAG) }
 response-ip{COLON}             { YDVAR(2, VAR_RESPONSE_IP) }
 response-ip-data{COLON}                { YDVAR(2, VAR_RESPONSE_IP_DATA) }
@@ -448,6 +458,9 @@ ipsecmod-strict{COLON}              { YDVAR(1, VAR_IPSECMOD_STRICT) }
 cachedb{COLON}                 { YDVAR(0, VAR_CACHEDB) }
 backend{COLON}                 { YDVAR(1, VAR_CACHEDB_BACKEND) }
 secret-seed{COLON}             { YDVAR(1, VAR_CACHEDB_SECRETSEED) }
+redis-server-host{COLON}       { YDVAR(1, VAR_CACHEDB_REDISHOST) }
+redis-server-port{COLON}       { YDVAR(1, VAR_CACHEDB_REDISPORT) }
+redis-timeout{COLON}           { YDVAR(1, VAR_CACHEDB_REDISTIMEOUT) }
 udp-upstream-without-downstream{COLON} { YDVAR(1, VAR_UDP_UPSTREAM_WITHOUT_DOWNSTREAM) }
 <INITIAL,val>{NEWLINE}         { LEXOUT(("NL\n")); cfg_parser->line++; }
 
index 7e23fca..e34665a 100644 (file)
@@ -142,6 +142,7 @@ extern struct config_parser_state* cfg_parser;
 %token VAR_VIEW_FIRST VAR_SERVE_EXPIRED 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_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
@@ -152,9 +153,11 @@ extern struct config_parser_state* cfg_parser;
 %token VAR_IPSECMOD_ENABLED VAR_IPSECMOD_HOOK VAR_IPSECMOD_IGNORE_BOGUS
 %token VAR_IPSECMOD_MAX_TTL VAR_IPSECMOD_WHITELIST VAR_IPSECMOD_STRICT
 %token VAR_CACHEDB VAR_CACHEDB_BACKEND VAR_CACHEDB_SECRETSEED
+%token VAR_CACHEDB_REDISHOST VAR_CACHEDB_REDISPORT VAR_CACHEDB_REDISTIMEOUT
 %token VAR_UDP_UPSTREAM_WITHOUT_DOWNSTREAM VAR_FOR_UPSTREAM
 %token VAR_AUTH_ZONE VAR_ZONEFILE VAR_MASTER VAR_URL VAR_FOR_DOWNSTREAM
-%token VAR_FALLBACK_ENABLED
+%token VAR_FALLBACK_ENABLED VAR_TLS_ADDITIONAL_PORT VAR_LOW_RTT VAR_LOW_RTT_PERMIL
+%token VAR_ALLOW_NOTIFY VAR_TLS_WIN_CERT
 
 %%
 toplevelvars: /* empty */ | toplevelvars toplevelvar ;
@@ -240,11 +243,13 @@ content_server: server_num_threads | server_verbosity | server_port |
        server_response_ip_tag | server_response_ip | server_response_ip_data |
        server_shm_enable | server_shm_key | server_fake_sha1 |
        server_hide_trustanchor | server_trust_anchor_signaling |
+       server_root_key_sentinel |
        server_ipsecmod_enabled | server_ipsecmod_hook |
        server_ipsecmod_ignore_bogus | server_ipsecmod_max_ttl |
        server_ipsecmod_whitelist | server_ipsecmod_strict |
        server_udp_upstream_without_downstream | server_aggressive_nsec |
-       server_tls_cert_bundle
+       server_tls_cert_bundle | server_tls_additional_port | server_low_rtt |
+       server_low_rtt_permil | server_tls_win_cert
        ;
 stubstart: VAR_STUB_ZONE
        {
@@ -318,7 +323,8 @@ authstart: VAR_AUTH_ZONE
 contents_auth: contents_auth content_auth 
        | ;
 content_auth: auth_name | auth_zonefile | auth_master | auth_url |
-       auth_for_downstream | auth_for_upstream | auth_fallback_enabled
+       auth_for_downstream | auth_for_upstream | auth_fallback_enabled |
+       auth_allow_notify
        ;
 server_num_threads: VAR_NUM_THREADS STRING_ARG 
        { 
@@ -682,6 +688,23 @@ server_tls_cert_bundle: VAR_TLS_CERT_BUNDLE STRING_ARG
                cfg_parser->cfg->tls_cert_bundle = $2;
        }
        ;
+server_tls_win_cert: VAR_TLS_WIN_CERT STRING_ARG
+       {
+               OUTYY(("P(server_tls_win_cert:%s)\n", $2));
+               if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0)
+                       yyerror("expected yes or no.");
+               else cfg_parser->cfg->tls_win_cert = (strcmp($2, "yes")==0);
+               free($2);
+       }
+       ;
+server_tls_additional_port: VAR_TLS_ADDITIONAL_PORT STRING_ARG
+       {
+               OUTYY(("P(server_tls_additional_port:%s)\n", $2));
+               if(!cfg_strlist_insert(&cfg_parser->cfg->tls_additional_port,
+                       $2))
+                       yyerror("out of memory");
+       }
+       ;
 server_use_systemd: VAR_USE_SYSTEMD STRING_ARG
        {
                OUTYY(("P(server_use_systemd:%s)\n", $2));
@@ -859,6 +882,17 @@ server_trust_anchor_signaling: VAR_TRUST_ANCHOR_SIGNALING STRING_ARG
                free($2);
        }
        ;
+server_root_key_sentinel: VAR_ROOT_KEY_SENTINEL STRING_ARG
+       {
+               OUTYY(("P(server_root_key_sentinel:%s)\n", $2));
+               if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0)
+                       yyerror("expected yes or no.");
+               else
+                       cfg_parser->cfg->root_key_sentinel =
+                               (strcmp($2, "yes")==0);
+               free($2);
+       }
+       ;
 server_domain_insecure: VAR_DOMAIN_INSECURE STRING_ARG
        {
                OUTYY(("P(server_domain_insecure:%s)\n", $2));
@@ -1280,11 +1314,12 @@ server_access_control: VAR_ACCESS_CONTROL STRING_ARG STRING_ARG
                if(strcmp($3, "deny")!=0 && strcmp($3, "refuse")!=0 &&
                        strcmp($3, "deny_non_local")!=0 &&
                        strcmp($3, "refuse_non_local")!=0 &&
+                       strcmp($3, "allow_setrd")!=0 && 
                        strcmp($3, "allow")!=0 && 
                        strcmp($3, "allow_snoop")!=0) {
                        yyerror("expected deny, refuse, deny_non_local, "
-                               "refuse_non_local, allow or allow_snoop "
-                               "in access control action");
+                               "refuse_non_local, allow, allow_setrd or "
+                               "allow_snoop in access control action");
                } else {
                        if(!cfg_str2list_insert(&cfg_parser->cfg->acls, $2, $3))
                                fatal_exit("out of memory adding acl");
@@ -1851,6 +1886,24 @@ server_ratelimit_factor: VAR_RATELIMIT_FACTOR STRING_ARG
                free($2);
        }
        ;
+server_low_rtt: VAR_LOW_RTT STRING_ARG 
+       { 
+               OUTYY(("P(server_low_rtt:%s)\n", $2)); 
+               if(atoi($2) == 0 && strcmp($2, "0") != 0)
+                       yyerror("number expected");
+               else cfg_parser->cfg->low_rtt = atoi($2);
+               free($2);
+       }
+       ;
+server_low_rtt_permil: VAR_LOW_RTT_PERMIL STRING_ARG 
+       { 
+               OUTYY(("P(server_low_rtt_permil:%s)\n", $2)); 
+               if(atoi($2) == 0 && strcmp($2, "0") != 0)
+                       yyerror("number expected");
+               else cfg_parser->cfg->low_rtt_permil = atoi($2);
+               free($2);
+       }
+       ;
 server_qname_minimisation: VAR_QNAME_MINIMISATION STRING_ARG
        {
                OUTYY(("P(server_qname_minimisation:%s)\n", $2));
@@ -2072,6 +2125,14 @@ auth_url: VAR_URL STRING_ARG
                        yyerror("out of memory");
        }
        ;
+auth_allow_notify: VAR_ALLOW_NOTIFY STRING_ARG
+       {
+               OUTYY(("P(allow-notify:%s)\n", $2));
+               if(!cfg_strlist_insert(&cfg_parser->cfg->auths->allow_notify,
+                       $2))
+                       yyerror("out of memory");
+       }
+       ;
 auth_for_downstream: VAR_FOR_DOWNSTREAM STRING_ARG
        {
                OUTYY(("P(for-downstream:%s)\n", $2));
@@ -2226,17 +2287,14 @@ rc_control_port: VAR_CONTROL_PORT STRING_ARG
 rc_control_interface: VAR_CONTROL_INTERFACE STRING_ARG
        {
                OUTYY(("P(control_interface:%s)\n", $2));
-               if(!cfg_strlist_insert(&cfg_parser->cfg->control_ifs, $2))
+               if(!cfg_strlist_append(&cfg_parser->cfg->control_ifs, $2))
                        yyerror("out of memory");
        }
        ;
 rc_control_use_cert: VAR_CONTROL_USE_CERT STRING_ARG
        {
                OUTYY(("P(control_use_cert:%s)\n", $2));
-               if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0)
-                       yyerror("expected yes or no.");
-               else cfg_parser->cfg->remote_control_use_cert =
-                       (strcmp($2, "yes")==0);
+               cfg_parser->cfg->control_use_cert = (strcmp($2, "yes")==0);
                free($2);
        }
        ;
@@ -2551,7 +2609,8 @@ cachedbstart: VAR_CACHEDB
        ;
 contents_cachedb: contents_cachedb content_cachedb
        | ;
-content_cachedb: cachedb_backend_name | cachedb_secret_seed
+content_cachedb: cachedb_backend_name | cachedb_secret_seed |
+       redis_server_host | redis_server_port | redis_timeout
        ;
 cachedb_backend_name: VAR_CACHEDB_BACKEND STRING_ARG
        {
@@ -2582,6 +2641,46 @@ cachedb_secret_seed: VAR_CACHEDB_SECRETSEED STRING_ARG
        #endif
        }
        ;
+redis_server_host: VAR_CACHEDB_REDISHOST STRING_ARG
+       {
+       #if defined(USE_CACHEDB) && defined(USE_REDIS)
+               OUTYY(("P(redis_server_host:%s)\n", $2));
+               free(cfg_parser->cfg->redis_server_host);
+               cfg_parser->cfg->redis_server_host = $2;
+       #else
+               OUTYY(("P(Compiled without cachedb or redis, ignoring)\n"));
+               free($2);
+       #endif
+       }
+       ;
+redis_server_port: VAR_CACHEDB_REDISPORT STRING_ARG
+       {
+       #if defined(USE_CACHEDB) && defined(USE_REDIS)
+               int port;
+               OUTYY(("P(redis_server_port:%s)\n", $2));
+               port = atoi($2);
+               if(port == 0 || port < 0 || port > 65535)
+                       yyerror("valid redis server port number expected");
+               else cfg_parser->cfg->redis_server_port = port;
+       #else
+               OUTYY(("P(Compiled without cachedb or redis, ignoring)\n"));
+       #endif
+               free($2);
+       }
+       ;
+redis_timeout: VAR_CACHEDB_REDISTIMEOUT STRING_ARG
+       {
+       #if defined(USE_CACHEDB) && defined(USE_REDIS)
+               OUTYY(("P(redis_timeout:%s)\n", $2));
+               if(atoi($2) == 0)
+                       yyerror("redis timeout value expected");
+               else cfg_parser->cfg->redis_timeout = atoi($2);
+       #else
+               OUTYY(("P(Compiled without cachedb or redis, ignoring)\n"));
+       #endif
+               free($2);
+       }
+       ;
 %%
 
 /* parse helper routines could be here */
index 517af28..c7360f7 100644 (file)
@@ -523,6 +523,29 @@ dname_lab_cmp(uint8_t* d1, int labs1, uint8_t* d2, int labs2, int* mlabs)
        return lastdiff;
 }
 
+int
+dname_lab_startswith(uint8_t* label, char* prefix, char** endptr)
+{
+       size_t plen = strlen(prefix);
+       size_t orig_plen = plen;
+       size_t lablen = (size_t)*label;
+       if(plen > lablen)
+               return 0;
+       label++;
+       while(plen--) {
+               if(*prefix != tolower((unsigned char)*label)) {
+                       return 0;
+               }
+               prefix++; label++;
+       }
+       if(orig_plen < lablen)
+               *endptr = (char *)label;
+       else
+               /* prefix length == label length */
+               *endptr = NULL;
+       return 1;
+}
+
 int 
 dname_buffer_write(sldns_buffer* pkt, uint8_t* dname)
 {
index 53b341b..53a33c6 100644 (file)
@@ -185,6 +185,17 @@ int dname_count_size_labels(uint8_t* dname, size_t* size);
  */
 int dname_lab_cmp(uint8_t* d1, int labs1, uint8_t* d2, int labs2, int* mlabs);
 
+/**
+ * Check if labels starts with given prefix 
+ * @param label: dname label
+ * @param prefix: the string to match label with, null terminated.
+ * @param endptr: pointer to location in label after prefix, only if return
+ *     value is 1. NULL if nothing in the label after the prefix, i.e. prefix
+ *     and label are the same.
+ * @return: 1 if label starts with prefix, else 0
+ */
+int dname_lab_startswith(uint8_t* label, char* prefix, char** endptr);
+
 /**
  * See if domain name d1 is a strict subdomain of d2.
  * That is a subdomain, but not equal. 
index 2887200..13cad8a 100644 (file)
@@ -1028,6 +1028,32 @@ parse_extract_edns(struct msg_parse* msg, struct edns_data* edns,
        return 0;
 }
 
+/** skip RR in packet */
+static int
+skip_pkt_rr(sldns_buffer* pkt)
+{
+       if(sldns_buffer_remaining(pkt) < 1) return 0;
+       if(!pkt_dname_len(pkt))
+               return 0;
+       if(sldns_buffer_remaining(pkt) < 4) return 0;
+       sldns_buffer_skip(pkt, 4); /* type and class */
+       if(!skip_ttl_rdata(pkt))
+               return 0;
+       return 1;
+}
+
+/** skip RRs from packet */
+static int
+skip_pkt_rrs(sldns_buffer* pkt, int num)
+{
+       int i;
+       for(i=0; i<num; i++) {
+               if(!skip_pkt_rr(pkt))
+                       return 0;
+       }
+       return 1;
+}
+
 int 
 parse_edns_from_pkt(sldns_buffer* pkt, struct edns_data* edns,
        struct regional* region)
@@ -1035,8 +1061,12 @@ parse_edns_from_pkt(sldns_buffer* pkt, struct edns_data* edns,
        size_t rdata_len;
        uint8_t* rdata_ptr;
        log_assert(LDNS_QDCOUNT(sldns_buffer_begin(pkt)) == 1);
-       log_assert(LDNS_ANCOUNT(sldns_buffer_begin(pkt)) == 0);
-       log_assert(LDNS_NSCOUNT(sldns_buffer_begin(pkt)) == 0);
+       if(LDNS_ANCOUNT(sldns_buffer_begin(pkt)) != 0 ||
+               LDNS_NSCOUNT(sldns_buffer_begin(pkt)) != 0) {
+               if(!skip_pkt_rrs(pkt, ((int)LDNS_ANCOUNT(sldns_buffer_begin(pkt)))+
+                       ((int)LDNS_NSCOUNT(sldns_buffer_begin(pkt)))))
+                       return 0;
+       }
        /* check edns section is present */
        if(LDNS_ARCOUNT(sldns_buffer_begin(pkt)) > 1) {
                return LDNS_RCODE_FORMERR;
index e25b42c..772f5d1 100644 (file)
@@ -534,8 +534,9 @@ query_info_parse(struct query_info* m, sldns_buffer* query)
        /* minimum size: header + \0 + qtype + qclass */
        if(sldns_buffer_limit(query) < LDNS_HEADER_SIZE + 5)
                return 0;
-       if(LDNS_OPCODE_WIRE(q) != LDNS_PACKET_QUERY || 
-               LDNS_QDCOUNT(q) != 1 || sldns_buffer_position(query) != 0)
+       if((LDNS_OPCODE_WIRE(q) != LDNS_PACKET_QUERY && LDNS_OPCODE_WIRE(q) !=
+               LDNS_PACKET_NOTIFY) || LDNS_QDCOUNT(q) != 1 ||
+               sldns_buffer_position(query) != 0)
                return 0;
        sldns_buffer_skip(query, LDNS_HEADER_SIZE);
        m->qname = sldns_buffer_current(query);
index 9944087..7b9d549 100644 (file)
@@ -253,6 +253,7 @@ sec_status_to_string(enum sec_status s)
        case sec_status_bogus:          return "sec_status_bogus";
        case sec_status_indeterminate:  return "sec_status_indeterminate";
        case sec_status_insecure:       return "sec_status_insecure";
+       case sec_status_secure_sentinel_fail:   return "sec_status_secure_sentinel_fail";
        case sec_status_secure:         return "sec_status_secure";
        }
        return "unknown_sec_status_value";
index 28f603d..3a5335d 100644 (file)
@@ -187,6 +187,10 @@ enum sec_status {
         * insecure. Generally this means that this RRset is below a trust 
         * anchor, but also below a verified, insecure delegation. */
        sec_status_insecure,
+       /** SECURE_SENTINEL_FAIL means that the object (RRset or message)
+        * validated according to local policy but did not succeed in the root
+        * KSK sentinel test (draft-ietf-dnsop-kskroll-sentinel). */
+       sec_status_secure_sentinel_fail,
        /** SECURE means that the object (RRset or message) validated 
         * according to local policy. */
        sec_status_secure
index 400a15d..302b6f7 100644 (file)
@@ -311,7 +311,8 @@ int
 fptr_whitelist_modenv_send_query(struct outbound_entry* (*fptr)(
        struct query_info* qinfo, uint16_t flags, int dnssec, int want_dnssec,
        int nocaps, struct sockaddr_storage* addr, socklen_t addrlen,
-       uint8_t* zone, size_t zonelen, int ssl_upstream, struct module_qstate* q))
+       uint8_t* zone, size_t zonelen, int ssl_upstream, char* tls_auth_name,
+       struct module_qstate* q))
 {
        if(fptr == &worker_send_query) return 1;
        else if(fptr == &libworker_send_query) return 1;
index 39e3f2d..03c2b92 100644 (file)
@@ -212,7 +212,8 @@ int fptr_whitelist_hash_markdelfunc(lruhash_markdelfunc_type fptr);
 int fptr_whitelist_modenv_send_query(struct outbound_entry* (*fptr)(
        struct query_info* qinfo, uint16_t flags, int dnssec, int want_dnssec,
        int nocaps, struct sockaddr_storage* addr, socklen_t addrlen,
-       uint8_t* zone, size_t zonelen, int ssl_upstream, struct module_qstate* q));
+       uint8_t* zone, size_t zonelen, int ssl_upstream, char* tls_auth_name,
+       struct module_qstate* q));
 
 /**
  * Check function pointer whitelist for module_env detach_subs callback values.
index 73db994..c6e5164 100644 (file)
@@ -338,6 +338,8 @@ struct module_env {
         * @param zone: delegation point name.
         * @param zonelen: length of zone name.
         * @param ssl_upstream: use SSL for upstream queries.
+        * @param tls_auth_name: if ssl_upstream, use this name with TLS
+        *      authentication.
         * @param q: wich query state to reactivate upon return.
         * @return: false on failure (memory or socket related). no query was
         *      sent. Or returns an outbound entry with qsent and qstate set.
@@ -348,7 +350,7 @@ struct module_env {
                uint16_t flags, int dnssec, int want_dnssec, int nocaps,
                struct sockaddr_storage* addr, socklen_t addrlen,
                uint8_t* zone, size_t zonelen, int ssl_upstream,
-               struct module_qstate* q);
+               char* tls_auth_name, struct module_qstate* q);
 
        /**
         * Detach-subqueries.
index fdc8b05..a5059b0 100644 (file)
@@ -52,6 +52,9 @@
 #ifdef HAVE_OPENSSL_ERR_H
 #include <openssl/err.h>
 #endif
+#ifdef USE_WINSOCK
+#include <wincrypt.h>
+#endif
 
 /** max length of an IP address (the address portion) that we allow */
 #define MAX_ADDR_STRLEN 128 /* characters */
@@ -241,7 +244,8 @@ ipstrtoaddr(const char* ip, int port, struct sockaddr_storage* addr,
 int netblockstrtoaddr(const char* str, int port, struct sockaddr_storage* addr,
         socklen_t* addrlen, int* net)
 {
-       char* s = NULL;
+       char buf[64];
+       char* s;
        *net = (str_is_ip6(str)?128:32);
        if((s=strchr(str, '/'))) {
                if(atoi(s+1) > *net) {
@@ -253,24 +257,65 @@ int netblockstrtoaddr(const char* str, int port, struct sockaddr_storage* addr,
                        log_err("cannot parse netblock: '%s'", str);
                        return 0;
                }
-               if(!(s = strdup(str))) {
-                       log_err("out of memory");
-                       return 0;
-               }
-               *strchr(s, '/') = '\0';
+               strlcpy(buf, str, sizeof(buf));
+               s = strchr(buf, '/');
+               if(s) *s = 0;
+               s = buf;
        }
        if(!ipstrtoaddr(s?s:str, port, addr, addrlen)) {
-               free(s);
                log_err("cannot parse ip address: '%s'", str);
                return 0;
        }
        if(s) {
-               free(s);
                addr_mask(addr, *addrlen, *net);
        }
        return 1;
 }
 
+int authextstrtoaddr(char* str, struct sockaddr_storage* addr, 
+       socklen_t* addrlen, char** auth_name)
+{
+       char* s;
+       int port = UNBOUND_DNS_PORT;
+       if((s=strchr(str, '@'))) {
+               char buf[MAX_ADDR_STRLEN];
+               size_t len = (size_t)(s-str);
+               char* hash = strchr(s+1, '#');
+               if(hash) {
+                       *auth_name = hash+1;
+               } else {
+                       *auth_name = NULL;
+               }
+               if(len >= MAX_ADDR_STRLEN) {
+                       return 0;
+               }
+               (void)strlcpy(buf, str, sizeof(buf));
+               buf[len] = 0;
+               port = atoi(s+1);
+               if(port == 0) {
+                       if(!hash && strcmp(s+1,"0")!=0)
+                               return 0;
+                       if(hash && strncmp(s+1,"0#",2)!=0)
+                               return 0;
+               }
+               return ipstrtoaddr(buf, port, addr, addrlen);
+       }
+       if((s=strchr(str, '#'))) {
+               char buf[MAX_ADDR_STRLEN];
+               size_t len = (size_t)(s-str);
+               if(len >= MAX_ADDR_STRLEN) {
+                       return 0;
+               }
+               (void)strlcpy(buf, str, sizeof(buf));
+               buf[len] = 0;
+               port = UNBOUND_DNS_OVER_TLS_PORT;
+               *auth_name = s+1;
+               return ipstrtoaddr(buf, port, addr, addrlen);
+       }
+       *auth_name = NULL;
+       return ipstrtoaddr(str, port, addr, addrlen);
+}
+
 /** store port number into sockaddr structure */
 void
 sockaddr_store_port(struct sockaddr_storage* addr, socklen_t addrlen, int port)
@@ -754,7 +799,97 @@ void* listen_sslctx_create(char* key, char* pem, char* verifypem)
 #endif
 }
 
-void* connect_sslctx_create(char* key, char* pem, char* verifypem)
+#ifdef USE_WINSOCK
+/* For windows, the CA trust store is not read by openssl.
+   Add code to open the trust store using wincrypt API and add
+   the root certs into openssl trust store */
+static int
+add_WIN_cacerts_to_openssl_store(SSL_CTX* tls_ctx)
+{
+       HCERTSTORE      hSystemStore;
+       PCCERT_CONTEXT  pTargetCert = NULL;
+       X509_STORE*     store;
+
+       verbose(VERB_ALGO, "Adding Windows certificates from system root store to CA store");
+
+       /* load just once per context lifetime for this version
+          TODO: dynamically update CA trust changes as they are available */
+       if (!tls_ctx)
+               return 0;
+
+       /* Call wincrypt's CertOpenStore to open the CA root store. */
+
+       if ((hSystemStore = CertOpenStore(
+               CERT_STORE_PROV_SYSTEM,
+               0,
+               0,
+               /* NOTE: mingw does not have this const: replace with 1 << 16 from code 
+                  CERT_SYSTEM_STORE_CURRENT_USER, */
+               1 << 16,
+               L"root")) == 0)
+       {
+               return 0;
+       }
+
+       store = SSL_CTX_get_cert_store(tls_ctx);
+       if (!store)
+               return 0;
+
+       /* failure if the CA store is empty or the call fails */
+       if ((pTargetCert = CertEnumCertificatesInStore(
+               hSystemStore, pTargetCert)) == 0) {
+               verbose(VERB_ALGO, "CA certificate store for Windows is empty.");
+               return 0;
+       }
+       /* iterate over the windows cert store and add to openssl store */
+       do
+       {
+               X509 *cert1 = d2i_X509(NULL,
+                       (const unsigned char **)&pTargetCert->pbCertEncoded,
+                       pTargetCert->cbCertEncoded);
+               if (!cert1) {
+                       /* return error if a cert fails */
+                       verbose(VERB_ALGO, "%s %d:%s",
+                               "Unable to parse certificate in memory",
+                               (int)ERR_get_error(), ERR_error_string(ERR_get_error(), NULL));
+                       return 0;
+               }
+               else {
+                       /* return error if a cert add to store fails */
+                       if (X509_STORE_add_cert(store, cert1) == 0) {
+                               unsigned long error = ERR_peek_last_error();
+
+                               /* Ignore error X509_R_CERT_ALREADY_IN_HASH_TABLE which means the
+                               * certificate is already in the store.  */
+                               if(ERR_GET_LIB(error) != ERR_LIB_X509 ||
+                                  ERR_GET_REASON(error) != X509_R_CERT_ALREADY_IN_HASH_TABLE) {
+                                       verbose(VERB_ALGO, "%s %d:%s\n",
+                                           "Error adding certificate", (int)ERR_get_error(),
+                                            ERR_error_string(ERR_get_error(), NULL));
+                                       X509_free(cert1);
+                                       return 0;
+                               }
+                       }
+                       X509_free(cert1);
+               }
+       } while ((pTargetCert = CertEnumCertificatesInStore(
+               hSystemStore, pTargetCert)) != 0);
+
+       /* Clean up memory and quit. */
+       if (pTargetCert)
+               CertFreeCertificateContext(pTargetCert);
+       if (hSystemStore)
+       {
+               if (!CertCloseStore(
+                       hSystemStore, 0))
+                       return 0;
+       }
+       verbose(VERB_ALGO, "Completed adding Windows certificates to CA store successfully");
+       return 1;
+}
+#endif /* USE_WINSOCK */
+
+void* connect_sslctx_create(char* key, char* pem, char* verifypem, int wincert)
 {
 #ifdef HAVE_SSL
        SSL_CTX* ctx = SSL_CTX_new(SSLv23_client_method());
@@ -794,17 +929,30 @@ void* connect_sslctx_create(char* key, char* pem, char* verifypem)
                        return NULL;
                }
        }
-       if(verifypem && verifypem[0]) {
-               if(!SSL_CTX_load_verify_locations(ctx, verifypem, NULL)) {
-                       log_crypto_err("error in SSL_CTX verify");
-                       SSL_CTX_free(ctx);
-                       return NULL;
+       if((verifypem && verifypem[0]) || wincert) {
+               if(verifypem && verifypem[0]) {
+                       if(!SSL_CTX_load_verify_locations(ctx, verifypem, NULL)) {
+                               log_crypto_err("error in SSL_CTX verify");
+                               SSL_CTX_free(ctx);
+                               return NULL;
+                       }
+               }
+#ifdef USE_WINSOCK
+               if(wincert) {
+                       if(!add_WIN_cacerts_to_openssl_store(ctx)) {
+                               log_crypto_err("error in add_WIN_cacerts_to_openssl_store");
+                               SSL_CTX_free(ctx);
+                               return NULL;
+                       }
                }
+#else
+               (void)wincert;
+#endif
                SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL);
        }
        return ctx;
 #else
-       (void)key; (void)pem; (void)verifypem;
+       (void)key; (void)pem; (void)verifypem; (void)wincert;
        return NULL;
 #endif
 }
index 2d6fce9..de2e1ac 100644 (file)
@@ -73,10 +73,10 @@ struct regional;
 /** set RCODE bits in uint16 flags */
 #define FLAGS_SET_RCODE(f, r) (f = (((f) & 0xfff0) | (r)))
 
-/** timeout in seconds for UDP queries to auth servers. */
-#define UDP_AUTH_QUERY_TIMEOUT 4
-/** timeout in seconds for TCP queries to auth servers. */
-#define TCP_AUTH_QUERY_TIMEOUT 30
+/** timeout in milliseconds for UDP queries to auth servers. */
+#define UDP_AUTH_QUERY_TIMEOUT 3000
+/** timeout in milliseconds for TCP queries to auth servers. */
+#define TCP_AUTH_QUERY_TIMEOUT 3000
 /** Advertised version of EDNS capabilities */
 #define EDNS_ADVERTISED_VERSION         0
 /** Advertised size of EDNS capabilities */
@@ -190,7 +190,7 @@ int ipstrtoaddr(const char* ip, int port, struct sockaddr_storage* addr,
 
 /**
  * Convert ip netblock (ip/netsize) string and port to sockaddr.
- * *SLOW*, does a malloc internally to avoid writing over 'ip' string.
+ * performs a copy internally to avoid writing over 'ip' string.
  * @param ip: ip4 or ip6 address string.
  * @param port: port number, host format.
  * @param addr: where to store sockaddr.
@@ -201,6 +201,20 @@ int ipstrtoaddr(const char* ip, int port, struct sockaddr_storage* addr,
 int netblockstrtoaddr(const char* ip, int port, struct sockaddr_storage* addr,
        socklen_t* addrlen, int* net);
 
+/**
+ * Convert address string, with "@port" appendix, to sockaddr.
+ * It can also have an "#tls-auth-name" appendix (after the port).
+ * The returned tls-auth-name string is a pointer into the input string.
+ * Uses DNS port by default.
+ * @param str: the string
+ * @param addr: where to store sockaddr.
+ * @param addrlen: length of stored sockaddr is returned.
+ * @param auth_name: returned pointer to tls_auth_name, or NULL if none.
+ * @return 0 on error.
+ */
+int authextstrtoaddr(char* str, struct sockaddr_storage* addr, 
+       socklen_t* addrlen, char** auth_name);
+
 /**
  * Store port number into sockaddr structure
  * @param addr: sockaddr structure, ip4 or ip6.
@@ -381,9 +395,11 @@ void* listen_sslctx_create(char* key, char* pem, char* verifypem);
  * @param key: if nonNULL (also pem nonNULL), the client private key.
  * @param pem: client public key (or NULL if key is NULL).
  * @param verifypem: if nonNULL used for verifylocation file.
+ * @param wincert: add system certificate store to ctx (add to verifypem ca
+ *     certs).
  * @return SSL_CTX* or NULL on failure (logged).
  */
-void* connect_sslctx_create(char* key, char* pem, char* verifypem);
+void* connect_sslctx_create(char* key, char* pem, char* verifypem, int wincert);
 
 /**
  * accept a new fd and wrap it in a BIO in SSL
index fc6f6a9..5cc8606 100644 (file)
@@ -46,6 +46,7 @@
 #include "util/fptr_wlist.h"
 #include "sldns/pkthdr.h"
 #include "sldns/sbuffer.h"
+#include "sldns/str2wire.h"
 #include "dnstap/dnstap.h"
 #include "dnscrypt/dnscrypt.h"
 #ifdef HAVE_OPENSSL_SSL_H
@@ -763,7 +764,12 @@ int comm_point_perform_accept(struct comm_point* c,
 {
        int new_fd;
        *addrlen = (socklen_t)sizeof(*addr);
+#ifndef HAVE_ACCEPT4
        new_fd = accept(c->fd, (struct sockaddr*)addr, addrlen);
+#else
+       /* SOCK_NONBLOCK saves extra calls to fcntl for the same result */
+       new_fd = accept4(c->fd, (struct sockaddr*)addr, addrlen, SOCK_NONBLOCK);
+#endif
        if(new_fd == -1) {
 #ifndef USE_WINSOCK
                /* EINTR is signal interrupt. others are closed connection. */
@@ -826,7 +832,9 @@ int comm_point_perform_accept(struct comm_point* c,
 #endif
                return -1;
        }
+#ifndef HAVE_ACCEPT4
        fd_set_nonblock(new_fd);
+#endif
        return new_fd;
 }
 
@@ -834,20 +842,21 @@ int comm_point_perform_accept(struct comm_point* c,
 static long win_bio_cb(BIO *b, int oper, const char* ATTR_UNUSED(argp),
         int ATTR_UNUSED(argi), long argl, long retvalue)
 {
+       int wsa_err = WSAGetLastError(); /* store errcode before it is gone */
        verbose(VERB_ALGO, "bio_cb %d, %s %s %s", oper,
                (oper&BIO_CB_RETURN)?"return":"before",
                (oper&BIO_CB_READ)?"read":((oper&BIO_CB_WRITE)?"write":"other"),
-               WSAGetLastError()==WSAEWOULDBLOCK?"wsawb":"");
+               wsa_err==WSAEWOULDBLOCK?"wsawb":"");
        /* on windows, check if previous operation caused EWOULDBLOCK */
        if( (oper == (BIO_CB_READ|BIO_CB_RETURN) && argl == 0) ||
                (oper == (BIO_CB_GETS|BIO_CB_RETURN) && argl == 0)) {
-               if(WSAGetLastError() == WSAEWOULDBLOCK)
+               if(wsa_err == WSAEWOULDBLOCK)
                        ub_winsock_tcp_wouldblock((struct ub_event*)
                                BIO_get_callback_arg(b), UB_EV_READ);
        }
        if( (oper == (BIO_CB_WRITE|BIO_CB_RETURN) && argl == 0) ||
                (oper == (BIO_CB_PUTS|BIO_CB_RETURN) && argl == 0)) {
-               if(WSAGetLastError() == WSAEWOULDBLOCK)
+               if(wsa_err == WSAEWOULDBLOCK)
                        ub_winsock_tcp_wouldblock((struct ub_event*)
                                BIO_get_callback_arg(b), UB_EV_WRITE);
        }
@@ -1127,6 +1136,7 @@ ssl_handle_read(struct comm_point* c)
                        if(want == SSL_ERROR_ZERO_RETURN) {
                                return 0; /* shutdown, closed */
                        } else if(want == SSL_ERROR_WANT_READ) {
+                               ub_winsock_tcp_wouldblock(c->ev->ev, UB_EV_READ);
                                return 1; /* read more later */
                        } else if(want == SSL_ERROR_WANT_WRITE) {
                                c->ssl_shake_state = comm_ssl_shake_hs_write;
@@ -1142,7 +1152,7 @@ ssl_handle_read(struct comm_point* c)
                        return 0;
                }
                c->tcp_byte_count += r;
-               if(c->tcp_byte_count != sizeof(uint16_t))
+               if(c->tcp_byte_count < sizeof(uint16_t))
                        return 1;
                if(sldns_buffer_read_u16_at(c->buffer, 0) >
                        sldns_buffer_capacity(c->buffer)) {
@@ -1155,33 +1165,36 @@ ssl_handle_read(struct comm_point* c)
                        verbose(VERB_QUERY, "ssl: dropped bogus too short.");
                        return 0;
                }
+               sldns_buffer_skip(c->buffer, (ssize_t)(c->tcp_byte_count-sizeof(uint16_t)));
                verbose(VERB_ALGO, "Reading ssl tcp query of length %d",
                        (int)sldns_buffer_limit(c->buffer));
        }
-       log_assert(sldns_buffer_remaining(c->buffer) > 0);
-       ERR_clear_error();
-       r = SSL_read(c->ssl, (void*)sldns_buffer_current(c->buffer),
-               (int)sldns_buffer_remaining(c->buffer));
-       if(r <= 0) {
-               int want = SSL_get_error(c->ssl, r);
-               if(want == SSL_ERROR_ZERO_RETURN) {
-                       return 0; /* shutdown, closed */
-               } else if(want == SSL_ERROR_WANT_READ) {
-                       return 1; /* read more later */
-               } else if(want == SSL_ERROR_WANT_WRITE) {
-                       c->ssl_shake_state = comm_ssl_shake_hs_write;
-                       comm_point_listen_for_rw(c, 0, 1);
-                       return 1;
-               } else if(want == SSL_ERROR_SYSCALL) {
-                       if(errno != 0)
-                               log_err("SSL_read syscall: %s",
-                                       strerror(errno));
+       if(sldns_buffer_remaining(c->buffer) > 0) {
+               ERR_clear_error();
+               r = SSL_read(c->ssl, (void*)sldns_buffer_current(c->buffer),
+                       (int)sldns_buffer_remaining(c->buffer));
+               if(r <= 0) {
+                       int want = SSL_get_error(c->ssl, r);
+                       if(want == SSL_ERROR_ZERO_RETURN) {
+                               return 0; /* shutdown, closed */
+                       } else if(want == SSL_ERROR_WANT_READ) {
+                               ub_winsock_tcp_wouldblock(c->ev->ev, UB_EV_READ);
+                               return 1; /* read more later */
+                       } else if(want == SSL_ERROR_WANT_WRITE) {
+                               c->ssl_shake_state = comm_ssl_shake_hs_write;
+                               comm_point_listen_for_rw(c, 0, 1);
+                               return 1;
+                       } else if(want == SSL_ERROR_SYSCALL) {
+                               if(errno != 0)
+                                       log_err("SSL_read syscall: %s",
+                                               strerror(errno));
+                               return 0;
+                       }
+                       log_crypto_err("could not SSL_read");
                        return 0;
                }
-               log_crypto_err("could not SSL_read");
-               return 0;
+               sldns_buffer_skip(c->buffer, (ssize_t)r);
        }
-       sldns_buffer_skip(c->buffer, (ssize_t)r);
        if(sldns_buffer_remaining(c->buffer) <= 0) {
                tcp_callback_reader(c);
        }
@@ -1209,9 +1222,24 @@ ssl_handle_write(struct comm_point* c)
        if(c->tcp_byte_count < sizeof(uint16_t)) {
                uint16_t len = htons(sldns_buffer_limit(c->buffer));
                ERR_clear_error();
-               r = SSL_write(c->ssl,
-                       (void*)(((uint8_t*)&len)+c->tcp_byte_count),
-                       (int)(sizeof(uint16_t)-c->tcp_byte_count));
+               if(sizeof(uint16_t)+sldns_buffer_remaining(c->buffer) <
+                       LDNS_RR_BUF_SIZE) {
+                       /* combine the tcp length and the query for write,
+                        * this emulates writev */
+                       uint8_t buf[LDNS_RR_BUF_SIZE];
+                       memmove(buf, &len, sizeof(uint16_t));
+                       memmove(buf+sizeof(uint16_t),
+                               sldns_buffer_current(c->buffer),
+                               sldns_buffer_remaining(c->buffer));
+                       r = SSL_write(c->ssl, (void*)(buf+c->tcp_byte_count),
+                               (int)(sizeof(uint16_t)+
+                               sldns_buffer_remaining(c->buffer)
+                               - c->tcp_byte_count));
+               } else {
+                       r = SSL_write(c->ssl,
+                               (void*)(((uint8_t*)&len)+c->tcp_byte_count),
+                               (int)(sizeof(uint16_t)-c->tcp_byte_count));
+               }
                if(r <= 0) {
                        int want = SSL_get_error(c->ssl, r);
                        if(want == SSL_ERROR_ZERO_RETURN) {
@@ -1221,6 +1249,7 @@ ssl_handle_write(struct comm_point* c)
                                comm_point_listen_for_rw(c, 1, 0);
                                return 1; /* wait for read condition */
                        } else if(want == SSL_ERROR_WANT_WRITE) {
+                               ub_winsock_tcp_wouldblock(c->ev->ev, UB_EV_WRITE);
                                return 1; /* write more later */
                        } else if(want == SSL_ERROR_SYSCALL) {
                                if(errno != 0)
@@ -1254,6 +1283,7 @@ ssl_handle_write(struct comm_point* c)
                        comm_point_listen_for_rw(c, 1, 0);
                        return 1; /* wait for read condition */
                } else if(want == SSL_ERROR_WANT_WRITE) {
+                       ub_winsock_tcp_wouldblock(c->ev->ev, UB_EV_WRITE);
                        return 1; /* write more later */
                } else if(want == SSL_ERROR_SYSCALL) {
                        if(errno != 0)
@@ -2871,12 +2901,18 @@ comm_point_close(struct comm_point* c)
 {
        if(!c)
                return;
-       if(c->fd != -1)
+       if(c->fd != -1) {
                if(ub_event_del(c->ev->ev) != 0) {
                        log_err("could not event_del on close");
                }
+       }
        /* close fd after removing from event lists, or epoll.. is messed up */
        if(c->fd != -1 && !c->do_not_close) {
+               if(c->type == comm_tcp || c->type == comm_http) {
+                       /* delete sticky events for the fd, it gets closed */
+                       ub_winsock_tcp_wouldblock(c->ev->ev, UB_EV_READ);
+                       ub_winsock_tcp_wouldblock(c->ev->ev, UB_EV_WRITE);
+               }
                verbose(VERB_ALGO, "close fd %d", c->fd);
 #ifndef USE_WINSOCK
                close(c->fd);
index f42d22c..dc6e3c2 100644 (file)
@@ -454,8 +454,9 @@ int tube_setup_bg_write(struct tube* tube, struct comm_base* base)
 
 int tube_queue_item(struct tube* tube, uint8_t* msg, size_t len)
 {
-       struct tube_res_list* item = 
-               (struct tube_res_list*)malloc(sizeof(*item));
+       struct tube_res_list* item;
+       if(!tube || !tube->res_com) return 0;
+       item = (struct tube_res_list*)malloc(sizeof(*item));
        if(!item) {
                free(msg);
                log_err("out of memory for async answer");
@@ -687,8 +688,9 @@ int tube_setup_bg_write(struct tube* ATTR_UNUSED(tube),
 
 int tube_queue_item(struct tube* tube, uint8_t* msg, size_t len)
 {
-       struct tube_res_list* item = 
-               (struct tube_res_list*)malloc(sizeof(*item));
+       struct tube_res_list* item;
+       if(!tube) return 0;
+       item = (struct tube_res_list*)malloc(sizeof(*item));
        verbose(VERB_ALGO, "tube queue_item len %d", (int)len);
        if(!item) {
                free(msg);
index fba2f24..78481a9 100644 (file)
@@ -95,6 +95,7 @@ UB_EV_BITS_CB(comm_timer_callback)
 UB_EV_BITS_CB(comm_signal_callback)
 UB_EV_BITS_CB(comm_point_local_handle_callback)
 UB_EV_BITS_CB(comm_point_raw_handle_callback)
+UB_EV_BITS_CB(comm_point_http_handle_callback)
 UB_EV_BITS_CB(tube_handle_signal)
 UB_EV_BITS_CB(comm_base_handle_slow_accept)
 
@@ -116,12 +117,17 @@ static void (*NATIVE_BITS_CB(void (*cb)(int, short, void*)))(int, short, void*)
                return my_comm_point_local_handle_callback;
        else if(cb == comm_point_raw_handle_callback)
                return my_comm_point_raw_handle_callback;
+       else if(cb == comm_point_http_handle_callback)
+               return my_comm_point_http_handle_callback;
        else if(cb == tube_handle_signal)
                return my_tube_handle_signal;
        else if(cb == comm_base_handle_slow_accept)
                return my_comm_base_handle_slow_accept;
-       else
+       else {
+               log_assert(0); /* this NULL callback pointer should not happen,
+                       we should have the necessary routine listed above */
                return NULL;
+       }
 }
 #else 
 #  define NATIVE_BITS(b) (b)
index 6c63224..8ae9e7f 100644 (file)
@@ -1309,3 +1309,44 @@ anchor_list_keytags(struct trust_anchor* ta, uint16_t* list, size_t num)
        qsort(list, ret, sizeof(*list), keytag_compare);
        return ret;
 }
+
+int
+anchor_has_keytag(struct val_anchors* anchors, uint8_t* name, int namelabs,
+       size_t namelen, uint16_t dclass, uint16_t keytag)
+{
+       uint16_t* taglist;
+       uint16_t* tl;
+       size_t numtag, i;
+       struct trust_anchor* anchor = anchor_find(anchors,
+               name, namelabs, namelen, dclass);
+       if(!anchor)
+               return 0;
+       if(!anchor->numDS && !anchor->numDNSKEY) {
+               lock_basic_unlock(&anchor->lock);
+               return 0;
+       }
+
+       taglist = calloc(anchor->numDS + anchor->numDNSKEY, sizeof(*taglist));
+       if(!taglist) {
+               lock_basic_unlock(&anchor->lock);
+               return 0;
+       }
+
+       numtag = anchor_list_keytags(anchor, taglist,
+               anchor->numDS+anchor->numDNSKEY);
+       lock_basic_unlock(&anchor->lock);
+       if(!numtag) {
+               free(taglist);
+               return 0;
+       }
+       tl = taglist;
+       for(i=0; i<numtag; i++) {
+               if(*tl == keytag) {
+                       free(taglist);
+                       return 1;
+               }
+               tl++;
+       }
+       free(taglist);
+       return 0;
+}
index 318a2b2..a2a795d 100644 (file)
@@ -227,4 +227,19 @@ void anchors_delete_insecure(struct val_anchors* anchors, uint16_t c,
  */
 size_t anchor_list_keytags(struct trust_anchor* ta, uint16_t* list, size_t num);
 
+/**
+ * Check if there is a trust anchor for given zone with this keytag.
+ *
+ * @param anchors: anchor storage
+ * @param name: name of trust anchor (wireformat)
+ * @param namelabs: labels in name
+ * @param namelen: length of name
+ * @param dclass: class of trust anchor
+ * @param keytag: keytag
+ * @return 1 if there is a trust anchor in the trustachor store for this zone
+ * and keytag, else 0.
+ */
+int anchor_has_keytag(struct val_anchors* anchors, uint8_t* name, int namelabs,
+       size_t namelen, uint16_t dclass, uint16_t keytag);
+
 #endif /* VALIDATOR_VAL_ANCHOR_H */
index 5412381..c494a6b 100644 (file)
@@ -1515,6 +1515,10 @@ val_neg_getmsg(struct val_neg_cache* neg, struct query_info* qinfo,
                        return NULL;
                if(addsoa && !add_soa(rrset_cache, now, region, msg, NULL))
                        return NULL;
+
+               lock_basic_lock(&neg->lock);
+               neg->num_neg_cache_noerror++;
+               lock_basic_unlock(&neg->lock);
                return msg;
        } else if(nsec && val_nsec_proves_name_error(nsec, qinfo->qname)) {
                if(!(msg = dns_msg_create(qinfo->qname, qinfo->qname_len, 
@@ -1578,7 +1582,7 @@ val_neg_getmsg(struct val_neg_cache* neg, struct query_info* qinfo,
                                        rcode = LDNS_RCODE_NXDOMAIN;
                                else if(!nsec_proves_nodata(wcrr, &wc_qinfo,
                                        &nodata_wc) || nodata_wc)
-                                       /* &nodata_wc shoudn't be set, wc_qinfo
+                                       /* &nodata_wc shouldn't be set, wc_qinfo
                                         * already contains wildcard domain. */
                                        /* NSEC doesn't prove anything for
                                         * wildcard. */
@@ -1595,6 +1599,14 @@ val_neg_getmsg(struct val_neg_cache* neg, struct query_info* qinfo,
                if(addsoa && !add_soa(rrset_cache, now, region, msg, NULL))
                        return NULL;
 
+               /* Increment statistic counters */
+               lock_basic_lock(&neg->lock);
+               if(rcode == LDNS_RCODE_NOERROR)
+                       neg->num_neg_cache_noerror++;
+               else if(rcode == LDNS_RCODE_NXDOMAIN)
+                       neg->num_neg_cache_nxdomain++;
+               lock_basic_unlock(&neg->lock);
+
                FLAGS_SET_RCODE(msg->rep->flags, rcode);
                return msg;
        }
index 00dad6d..877f5c9 100644 (file)
@@ -80,6 +80,12 @@ struct val_neg_cache {
        size_t max;
        /** max nsec3 iterations allowed */
        size_t nsec3_max_iter;
+       /** number of times neg cache records were used to generate NOERROR
+        * responses. */
+       size_t num_neg_cache_noerror;
+       /** number of times neg cache records were used to generate NXDOMAIN
+        * responses. */
+       size_t num_neg_cache_nxdomain;
 };
 
 /**
index 7f5c518..95200a4 100644 (file)
@@ -231,7 +231,10 @@ dnskey_algo_id_is_supported(int id)
 #ifdef USE_ED25519
        case LDNS_ED25519:
 #endif
-#if (defined(HAVE_EVP_SHA256) && defined(USE_SHA2)) || (defined(HAVE_EVP_SHA512) && defined(USE_SHA2)) || defined(USE_ECDSA)
+#ifdef USE_ED448
+       case LDNS_ED448:
+#endif
+#if (defined(HAVE_EVP_SHA256) && defined(USE_SHA2)) || (defined(HAVE_EVP_SHA512) && defined(USE_SHA2)) || defined(USE_ECDSA) || defined(USE_ED25519) || defined(USE_ED448)
                return 1;
 #endif
 
@@ -569,6 +572,17 @@ setup_key_digest(int algo, EVP_PKEY** evp_key, const EVP_MD** digest_type,
                        *digest_type = NULL;
                        break;
 #endif /* USE_ED25519 */
+#ifdef USE_ED448
+               case LDNS_ED448:
+                       *evp_key = sldns_ed4482pkey_raw(key, keylen);
+                       if(!*evp_key) {
+                               verbose(VERB_QUERY, "verify: "
+                                       "sldns_ed4482pkey_raw failed");
+                               return 0;
+                       }
+                       *digest_type = NULL;
+                       break;
+#endif /* USE_ED448 */
                default:
                        verbose(VERB_QUERY, "verify: unknown algorithm %d", 
                                algo);
index 5ed45e9..5777b29 100644 (file)
@@ -40,6 +40,7 @@
  * According to RFC 4034.
  */
 #include "config.h"
+#include <ctype.h>
 #include "validator/validator.h"
 #include "validator/val_anchor.h"
 #include "validator/val_kcache.h"
@@ -477,6 +478,31 @@ generate_keytag_query(struct module_qstate* qstate, int id,
        return 1;
 }
 
+/**
+ * Get keytag as uint16_t from string
+ *
+ * @param start: start of string containing keytag
+ * @param keytag: pointer where to store the extracted keytag
+ * @return: 1 if keytag was extracted, else 0.
+ */
+static int
+sentinel_get_keytag(char* start, uint16_t* keytag) {
+       char* keytag_str;
+       char* e = NULL;
+       keytag_str = calloc(1, SENTINEL_KEYTAG_LEN + 1 /* null byte */);
+       if(!keytag_str)
+               return 0;
+       memmove(keytag_str, start, SENTINEL_KEYTAG_LEN);
+       keytag_str[SENTINEL_KEYTAG_LEN] = '\0';
+       *keytag = (uint16_t)strtol(keytag_str, &e, 10);
+       if(!e || *e != '\0') {
+               free(keytag_str);
+               return 0;
+       }
+       free(keytag_str);
+       return 1;
+}
+
 /**
  * Prime trust anchor for use.
  * Generate and dispatch a priming query for the given trust anchor.
@@ -2223,6 +2249,34 @@ processFinished(struct module_qstate* qstate, struct val_qstate* vq,
                        vq->orig_msg->rep->security = sec_status_indeterminate;
        }
 
+       if(vq->orig_msg->rep->security == sec_status_secure &&
+               qstate->env->cfg->root_key_sentinel &&
+               (qstate->qinfo.qtype == LDNS_RR_TYPE_A ||
+               qstate->qinfo.qtype == LDNS_RR_TYPE_AAAA)) {
+               char* keytag_start;
+               uint16_t keytag;
+               if(*qstate->qinfo.qname == strlen(SENTINEL_IS) +
+                       SENTINEL_KEYTAG_LEN &&
+                       dname_lab_startswith(qstate->qinfo.qname, SENTINEL_IS,
+                       &keytag_start)) {
+                       if(sentinel_get_keytag(keytag_start, &keytag) &&
+                               !anchor_has_keytag(qstate->env->anchors,
+                               (uint8_t*)"", 1, 0, vq->qchase.qclass, keytag)) {
+                               vq->orig_msg->rep->security =
+                                       sec_status_secure_sentinel_fail;
+                       }
+               } else if(*qstate->qinfo.qname == strlen(SENTINEL_NOT) +
+                       SENTINEL_KEYTAG_LEN &&
+                       dname_lab_startswith(qstate->qinfo.qname, SENTINEL_NOT,
+                       &keytag_start)) {
+                       if(sentinel_get_keytag(keytag_start, &keytag) &&
+                               anchor_has_keytag(qstate->env->anchors,
+                               (uint8_t*)"", 1, 0, vq->qchase.qclass, keytag)) {
+                               vq->orig_msg->rep->security =
+                                       sec_status_secure_sentinel_fail;
+                       }
+               }
+       }
        /* store results in cache */
        if(qstate->query_flags&BIT_RD) {
                /* if secure, this will override cache anyway, no need
index 9a59107..9e4c8a9 100644 (file)
@@ -67,6 +67,13 @@ struct config_strlist;
 /** max number of query restarts, number of IPs to probe */
 #define VAL_MAX_RESTART_COUNT 5
 
+/** Root key sentinel is ta preamble */
+#define SENTINEL_IS            "root-key-sentinel-is-ta-"
+/** Root key sentinel is not ta preamble */
+#define SENTINEL_NOT           "root-key-sentinel-not-ta-"
+/** Root key sentinal keytag length */
+#define SENTINEL_KEYTAG_LEN    5
+
 /**
  * Global state for the validator. 
  */