aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDag-Erling Smørgrav <des@FreeBSD.org>2018-05-12 11:56:38 +0000
committerDag-Erling Smørgrav <des@FreeBSD.org>2018-05-12 11:56:38 +0000
commit197f1a0fe3e81cde0cd25a3a1f37ebedf9a99488 (patch)
tree9a121ad4cef31a32608c065400c31246d549c0dc
parentb5c63b395d5df7ff6ee4d41a7dfecd938d894037 (diff)
downloadsrc-vendor/unbound/1.7.0.tar.gz
src-vendor/unbound/1.7.0.zip
Vendor import of Unbound 1.7.0.vendor/unbound/1.7.0
-rw-r--r--Makefile.in1001
-rw-r--r--cachedb/cachedb.c7
-rw-r--r--compat/arc4_lock.c15
-rw-r--r--config.h.in10
-rwxr-xr-xconfigure261
-rw-r--r--configure.ac59
-rw-r--r--contrib/README1
-rw-r--r--contrib/fastrpz.patch352
-rw-r--r--contrib/libunbound.so.conf41
-rw-r--r--daemon/cachedump.c1
-rw-r--r--daemon/daemon.c18
-rw-r--r--daemon/unbound.c30
-rw-r--r--daemon/worker.c47
-rw-r--r--dnscrypt/dnscrypt.c76
-rw-r--r--dnscrypt/dnscrypt.h2
-rw-r--r--dnscrypt/dnscrypt.m48
-rw-r--r--dnstap/dnstap.proto1
-rw-r--r--doc/Changelog237
-rw-r--r--doc/README2
-rw-r--r--doc/example.conf.in48
-rw-r--r--doc/libunbound.3.in18
-rw-r--r--doc/unbound-anchor.8.in2
-rw-r--r--doc/unbound-checkconf.8.in2
-rw-r--r--doc/unbound-control.8.in2
-rw-r--r--doc/unbound-host.1.in2
-rw-r--r--doc/unbound.8.in4
-rw-r--r--doc/unbound.conf.5.in152
-rw-r--r--edns-subnet/addrtree.c2
-rw-r--r--edns-subnet/subnetmod.c4
-rw-r--r--iterator/iter_delegpt.h2
-rw-r--r--iterator/iter_hints.c2
-rw-r--r--iterator/iter_scrub.c18
-rw-r--r--iterator/iter_utils.c5
-rw-r--r--iterator/iter_utils.h2
-rw-r--r--iterator/iterator.c405
-rw-r--r--iterator/iterator.h5
-rw-r--r--libunbound/context.c3
-rw-r--r--libunbound/libunbound.c13
-rw-r--r--libunbound/libworker.c52
-rw-r--r--services/authzone.c3800
-rw-r--r--services/authzone.h406
-rw-r--r--services/cache/dns.c56
-rw-r--r--services/cache/dns.h17
-rw-r--r--services/cache/rrset.c32
-rw-r--r--services/cache/rrset.h18
-rw-r--r--services/listen_dnsport.c26
-rw-r--r--services/localzone.c69
-rw-r--r--services/localzone.h4
-rw-r--r--services/outside_network.c279
-rw-r--r--services/outside_network.h64
-rw-r--r--sldns/str2wire.c11
-rw-r--r--sldns/str2wire.h6
-rw-r--r--sldns/wire2str.c6
-rw-r--r--sldns/wire2str.h16
-rw-r--r--smallapp/unbound-checkconf.c23
-rw-r--r--testcode/fake_event.c400
-rw-r--r--testcode/replay.c9
-rw-r--r--testcode/replay.h13
-rw-r--r--testcode/testbound.c76
-rw-r--r--testcode/testpkts.c16
-rw-r--r--testcode/unitauth.c60
-rw-r--r--testcode/unitmain.c1
-rw-r--r--testcode/unitverify.c1
-rw-r--r--testdata/03-testbound.tdir/03-testbound.test33
-rw-r--r--testdata/auth_axfr.tdir/auth_axfr.conf18
-rw-r--r--testdata/auth_axfr.tdir/auth_axfr.dsc16
-rw-r--r--testdata/auth_axfr.tdir/auth_axfr.post10
-rw-r--r--testdata/auth_axfr.tdir/auth_axfr.pre31
-rw-r--r--testdata/auth_axfr.tdir/auth_axfr.test51
-rw-r--r--testdata/auth_axfr.tdir/auth_axfr.testns27
-rw-r--r--testdata/auth_https.tdir/127.0.0.1/example.com.zone3
-rw-r--r--testdata/auth_https.tdir/auth_https.conf18
-rw-r--r--testdata/auth_https.tdir/auth_https.dsc16
-rw-r--r--testdata/auth_https.tdir/auth_https.post11
-rw-r--r--testdata/auth_https.tdir/auth_https.pre34
-rw-r--r--testdata/auth_https.tdir/auth_https.test51
-rw-r--r--testdata/auth_https.tdir/petal.key21
-rw-r--r--testdata/auth_https.tdir/petal.pem14
-rw-r--r--testdata/auth_xfr.rpl232
-rw-r--r--testdata/auth_xfr_host.rpl247
-rw-r--r--testdata/auth_xfr_ixfr.rpl276
-rw-r--r--testdata/auth_xfr_ixfrisaxfr.rpl235
-rw-r--r--testdata/auth_xfr_ixfrmismatch.rpl266
-rw-r--r--testdata/auth_xfr_ixfrnotimpl.rpl249
-rw-r--r--testdata/auth_xfr_probesoa.rpl219
-rw-r--r--testdata/auth_zonefile.rpl189
-rw-r--r--testdata/auth_zonefile_dnssec.rpl194
-rw-r--r--testdata/auth_zonefile_dnssec_fail.rpl202
-rw-r--r--testdata/auth_zonefile_down.rpl185
-rw-r--r--testdata/auth_zonefile_noup.rpl184
-rw-r--r--testdata/auth_zonefile_root.rpl181
-rw-r--r--testdata/iter_ds_referral.rpl213
-rw-r--r--testdata/iter_ds_reply.rpl225
-rw-r--r--testdata/iter_ns_badip.rpl2
-rw-r--r--testdata/test_signatures.921
-rw-r--r--testdata/val_negcache_nodata.rpl166
-rw-r--r--testdata/val_negcache_nxdomain.rpl109
-rw-r--r--testdata/val_nodata_failwc.rpl71
-rw-r--r--testdata/val_nx_failwc.rpl69
-rw-r--r--util/config_file.c60
-rw-r--r--util/config_file.h55
-rw-r--r--util/configlexer.c5705
-rw-r--r--util/configlexer.lex18
-rw-r--r--util/configparser.c2767
-rw-r--r--util/configparser.h378
-rw-r--r--util/configparser.y137
-rw-r--r--util/data/msgreply.c30
-rw-r--r--util/data/msgreply.h4
-rw-r--r--util/fptr_wlist.c9
-rw-r--r--util/iana_ports.inc6
-rw-r--r--util/log.c11
-rw-r--r--util/log.h9
-rw-r--r--util/module.h9
-rw-r--r--util/net_help.c15
-rw-r--r--util/net_help.h9
-rw-r--r--util/netevent.c796
-rw-r--r--util/netevent.h41
-rw-r--r--util/ub_event.c2
-rw-r--r--validator/val_neg.c272
-rw-r--r--validator/val_neg.h3
-rw-r--r--validator/val_nsec.c7
-rw-r--r--validator/val_sigcrypt.c64
-rw-r--r--validator/val_utils.c6
-rw-r--r--validator/val_utils.h4
-rw-r--r--validator/validator.c61
125 files changed, 17469 insertions, 5419 deletions
diff --git a/Makefile.in b/Makefile.in
index 1c33070336ef..923bb4fd7372 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -137,8 +137,7 @@ 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\
$(SUBNET_OBJ) $(PYTHONMOD_OBJ) $(CHECKLOCK_OBJ) $(DNSTAP_OBJ) $(DNSCRYPT_OBJ) \
-$(IPSECMOD_OBJ)
-COMMON_OBJ_WITHOUT_NETCALL+=respip.lo
+$(IPSECMOD_OBJ) respip.lo
COMMON_OBJ_WITHOUT_UB_EVENT=$(COMMON_OBJ_WITHOUT_NETCALL) netevent.lo listen_dnsport.lo \
outside_network.lo
COMMON_OBJ=$(COMMON_OBJ_WITHOUT_UB_EVENT) ub_event.lo
@@ -265,7 +264,7 @@ ALL_OBJ=$(COMMON_OBJ) $(UNITTEST_OBJ) $(DAEMON_OBJ) \
COMPILE=$(LIBTOOL) --tag=CC --mode=compile $(CC) $(CPPFLAGS) $(CFLAGS) @PTHREAD_CFLAGS_ONLY@
LINK=$(LIBTOOL) --tag=CC --mode=link $(CC) $(staticexe) $(RUNTIME_PATH) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS)
-LINK_LIB=$(LIBTOOL) --tag=CC --mode=link $(CC) $(RUNTIME_PATH) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) $(staticexe) -version-info @LIBUNBOUND_CURRENT@:@LIBUNBOUND_REVISION@:@LIBUNBOUND_AGE@ -no-undefined
+LINK_LIB=$(LIBTOOL) --tag=CC --mode=link $(CC) $(RUNTIME_PATH) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -version-info @LIBUNBOUND_CURRENT@:@LIBUNBOUND_REVISION@:@LIBUNBOUND_AGE@ -no-undefined
.PHONY: clean realclean doc lint all install uninstall tests test strip lib longtest longcheck check alltargets
@@ -390,7 +389,7 @@ dnstap.lo dnstap.o: $(srcdir)/dnstap/dnstap.c config.h dnstap/dnstap_config.h \
dnstap/dnstap.pb-c.c dnstap/dnstap.pb-c.h: $(srcdir)/dnstap/dnstap.proto
@-if test ! -d dnstap; then $(INSTALL) -d dnstap; fi
- $(PROTOC_C) --c_out=. $(srcdir)/dnstap/dnstap.proto
+ $(PROTOC_C) --c_out=. --proto_path=$(srcdir) $(srcdir)/dnstap/dnstap.proto
dnstap.pb-c.lo dnstap.pb-c.o: dnstap/dnstap.pb-c.c dnstap/dnstap.pb-c.h
@@ -533,6 +532,8 @@ install-all: all $(PYTHONMOD_INSTALL) $(PYUNBOUND_INSTALL) $(UNBOUND_EVENT_INSTA
$(INSTALL) -m 755 -d $(DESTDIR)$(mandir)/man8
$(INSTALL) -m 755 -d $(DESTDIR)$(mandir)/man5
$(INSTALL) -m 755 -d $(DESTDIR)$(mandir)/man1
+ $(INSTALL) -m 755 -d $(DESTDIR)$(libdir)/pkgconfig
+ $(INSTALL) -m 644 contrib/libunbound.pc $(DESTDIR)$(libdir)/pkgconfig
$(LIBTOOL) --mode=install cp -f unbound$(EXEEXT) $(DESTDIR)$(sbindir)/unbound$(EXEEXT)
$(LIBTOOL) --mode=install cp -f unbound-checkconf$(EXEEXT) $(DESTDIR)$(sbindir)/unbound-checkconf$(EXEEXT)
$(LIBTOOL) --mode=install cp -f unbound-control$(EXEEXT) $(DESTDIR)$(sbindir)/unbound-control$(EXEEXT)
@@ -627,102 +628,107 @@ 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)/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/pkthdr.h \
- $(srcdir)/sldns/rrdef.h $(srcdir)/util/net_help.h $(srcdir)/util/regional.h $(srcdir)/util/config_file.h \
- $(srcdir)/sldns/sbuffer.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)/util/netevent.h \
- $(srcdir)/dnscrypt/dnscrypt.h $(srcdir)/dnscrypt/cert.h \
- $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/slabhash.h \
- $(srcdir)/util/storage/lookup3.h $(srcdir)/util/data/dname.h $(srcdir)/util/net_help.h \
- $(srcdir)/util/config_file.h $(srcdir)/iterator/iterator.h $(srcdir)/services/outbound_list.h \
- $(srcdir)/util/module.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.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 \
+ $(srcdir)/util/net_help.h $(srcdir)/util/config_file.h $(srcdir)/iterator/iterator.h \
+ $(srcdir)/services/outbound_list.h $(srcdir)/util/module.h $(srcdir)/util/data/msgparse.h \
+ $(srcdir)/sldns/pkthdr.h
rrset.lo rrset.o: $(srcdir)/services/cache/rrset.c config.h $(srcdir)/services/cache/rrset.h \
- $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.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/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
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/data/msgparse.h \
- $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/storage/lookup3.h $(srcdir)/sldns/sbuffer.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)/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)/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)/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
+ $(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/data/packed_rrset.h \
- $(srcdir)/util/storage/lookup3.h $(srcdir)/util/alloc.h $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
- $(srcdir)/dnscrypt/cert.h $(srcdir)/util/net_help.h \
- $(srcdir)/util/data/dname.h $(srcdir)/util/regional.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h \
- $(srcdir)/sldns/rrdef.h $(srcdir)/util/data/msgencode.h $(srcdir)/sldns/sbuffer.h $(srcdir)/sldns/wire2str.h \
- $(srcdir)/util/module.h $(srcdir)/util/fptr_wlist.h $(srcdir)/util/tube.h $(srcdir)/services/mesh.h \
- $(srcdir)/util/rbtree.h $(srcdir)/services/modstack.h
+ $(srcdir)/util/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 \
+ $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/data/msgencode.h \
+ $(srcdir)/sldns/sbuffer.h $(srcdir)/sldns/wire2str.h $(srcdir)/util/module.h $(srcdir)/util/fptr_wlist.h \
+ $(srcdir)/util/tube.h $(srcdir)/services/mesh.h $(srcdir)/util/rbtree.h $(srcdir)/services/modstack.h
packed_rrset.lo packed_rrset.o: $(srcdir)/util/data/packed_rrset.c config.h \
$(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \
- $(srcdir)/util/data/dname.h $(srcdir)/util/storage/lookup3.h $(srcdir)/util/alloc.h $(srcdir)/util/regional.h \
- $(srcdir)/util/net_help.h $(srcdir)/sldns/rrdef.h $(srcdir)/sldns/sbuffer.h $(srcdir)/sldns/wire2str.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/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 $(srcdir)/iterator/iter_donotq.h \
- $(srcdir)/iterator/iter_delegpt.h $(srcdir)/iterator/iter_scrub.h $(srcdir)/iterator/iter_priv.h \
- $(srcdir)/validator/val_neg.h $(srcdir)/services/cache/dns.h $(srcdir)/services/cache/infra.h \
- $(srcdir)/util/rtt.h $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
- $(srcdir)/dnscrypt/cert.h $(srcdir)/util/net_help.h \
- $(srcdir)/util/regional.h $(srcdir)/util/data/dname.h $(srcdir)/util/data/msgencode.h \
- $(srcdir)/util/fptr_wlist.h $(srcdir)/util/tube.h $(srcdir)/services/mesh.h $(srcdir)/services/modstack.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 \
+ $(srcdir)/iterator/iter_donotq.h $(srcdir)/iterator/iter_delegpt.h $(srcdir)/iterator/iter_scrub.h \
+ $(srcdir)/iterator/iter_priv.h $(srcdir)/validator/val_neg.h $(srcdir)/services/cache/dns.h \
+ $(srcdir)/services/cache/infra.h $(srcdir)/util/rtt.h $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
+ $(srcdir)/dnscrypt/cert.h $(srcdir)/services/authzone.h \
+ $(srcdir)/services/mesh.h $(srcdir)/services/modstack.h $(srcdir)/util/net_help.h $(srcdir)/util/regional.h \
+ $(srcdir)/util/data/dname.h $(srcdir)/util/data/msgencode.h $(srcdir)/util/fptr_wlist.h $(srcdir)/util/tube.h \
$(srcdir)/util/config_file.h $(srcdir)/util/random.h $(srcdir)/sldns/wire2str.h $(srcdir)/sldns/str2wire.h \
$(srcdir)/sldns/parseutil.h $(srcdir)/sldns/sbuffer.h
iter_delegpt.lo iter_delegpt.o: $(srcdir)/iterator/iter_delegpt.c config.h $(srcdir)/iterator/iter_delegpt.h \
$(srcdir)/util/log.h $(srcdir)/services/cache/dns.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h \
- $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/regional.h \
- $(srcdir)/util/data/dname.h $(srcdir)/util/net_help.h $(srcdir)/sldns/rrdef.h $(srcdir)/sldns/sbuffer.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 \
$(srcdir)/util/storage/dnstree.h $(srcdir)/util/rbtree.h $(srcdir)/util/regional.h $(srcdir)/util/log.h \
$(srcdir)/util/config_file.h $(srcdir)/util/net_help.h
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)/sldns/str2wire.h \
- $(srcdir)/sldns/wire2str.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)/util/net_help.h \
- $(srcdir)/util/storage/dnstree.h $(srcdir)/sldns/str2wire.h $(srcdir)/sldns/sbuffer.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)/util/net_help.h \
- $(srcdir)/util/data/dname.h $(srcdir)/sldns/rrdef.h $(srcdir)/sldns/pkthdr.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/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 $(srcdir)/util/regional.h \
- $(srcdir)/util/config_file.h $(srcdir)/util/data/dname.h $(srcdir)/util/alloc.h $(srcdir)/sldns/sbuffer.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 \
+ $(srcdir)/util/regional.h $(srcdir)/util/config_file.h $(srcdir)/util/data/dname.h $(srcdir)/util/alloc.h \
+ $(srcdir)/sldns/sbuffer.h
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)/util/data/msgparse.h \
- $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/iterator/iter_hints.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 \
$(srcdir)/services/cache/infra.h $(srcdir)/util/rtt.h $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
@@ -736,33 +742,34 @@ 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)/util/config_file.h $(srcdir)/util/net_help.h $(srcdir)/sldns/sbuffer.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/storage/dnstree.h \
- $(srcdir)/util/module.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/data/msgreply.h \
- $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h \
- $(srcdir)/sldns/rrdef.h $(srcdir)/services/view.h $(srcdir)/sldns/str2wire.h $(srcdir)/sldns/sbuffer.h \
- $(srcdir)/util/regional.h $(srcdir)/util/config_file.h $(srcdir)/util/data/dname.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 \
+ $(srcdir)/sldns/sbuffer.h $(srcdir)/util/regional.h $(srcdir)/util/config_file.h $(srcdir)/util/data/dname.h \
$(srcdir)/util/data/msgencode.h $(srcdir)/util/net_help.h $(srcdir)/util/netevent.h \
$(srcdir)/dnscrypt/dnscrypt.h $(srcdir)/dnscrypt/cert.h \
$(srcdir)/util/as112.h
mesh.lo mesh.o: $(srcdir)/services/mesh.c config.h $(srcdir)/services/mesh.h $(srcdir)/util/rbtree.h \
$(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
- $(srcdir)/dnscrypt/cert.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/data/msgparse.h \
- $(srcdir)/util/storage/lruhash.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/module.h \
- $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/services/modstack.h \
- $(srcdir)/services/outbound_list.h $(srcdir)/services/cache/dns.h $(srcdir)/util/net_help.h \
- $(srcdir)/util/regional.h $(srcdir)/util/data/msgencode.h $(srcdir)/util/timehist.h $(srcdir)/util/fptr_wlist.h \
- $(srcdir)/util/tube.h $(srcdir)/util/alloc.h $(srcdir)/util/config_file.h $(srcdir)/sldns/sbuffer.h \
- $(srcdir)/sldns/wire2str.h $(srcdir)/services/localzone.h $(srcdir)/util/storage/dnstree.h \
- $(srcdir)/services/view.h $(srcdir)/util/data/dname.h $(srcdir)/respip/respip.h
+ $(srcdir)/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 \
+ $(srcdir)/util/net_help.h $(srcdir)/util/regional.h $(srcdir)/util/data/msgencode.h $(srcdir)/util/timehist.h \
+ $(srcdir)/util/fptr_wlist.h $(srcdir)/util/tube.h $(srcdir)/util/alloc.h $(srcdir)/util/config_file.h \
+ $(srcdir)/sldns/sbuffer.h $(srcdir)/sldns/wire2str.h $(srcdir)/services/localzone.h \
+ $(srcdir)/util/storage/dnstree.h $(srcdir)/services/view.h $(srcdir)/util/data/dname.h $(srcdir)/respip/respip.h
modstack.lo modstack.o: $(srcdir)/services/modstack.c config.h $(srcdir)/services/modstack.h \
$(srcdir)/util/module.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \
- $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgparse.h \
- $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/fptr_wlist.h $(srcdir)/util/netevent.h \
- $(srcdir)/dnscrypt/dnscrypt.h $(srcdir)/dnscrypt/cert.h \
- $(srcdir)/util/tube.h $(srcdir)/services/mesh.h $(srcdir)/util/rbtree.h $(srcdir)/dns64/dns64.h \
+ $(srcdir)/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 \
$(srcdir)/iterator/iterator.h $(srcdir)/services/outbound_list.h $(srcdir)/validator/validator.h \
$(srcdir)/validator/val_utils.h $(srcdir)/respip/respip.h $(srcdir)/services/localzone.h \
$(srcdir)/util/storage/dnstree.h $(srcdir)/services/view.h $(PYTHONMOD_HEADER) \
@@ -770,168 +777,186 @@ 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/storage/dnstree.h \
- $(srcdir)/util/module.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/data/msgreply.h \
- $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h \
- $(srcdir)/sldns/rrdef.h $(srcdir)/util/config_file.h
+ $(srcdir)/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)/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 $(srcdir)/sldns/rrdef.h $(srcdir)/util/data/msgencode.h \
- $(srcdir)/util/data/dname.h $(srcdir)/util/net_help.h $(srcdir)/util/random.h $(srcdir)/util/fptr_wlist.h \
- $(srcdir)/util/module.h $(srcdir)/util/tube.h $(srcdir)/services/mesh.h $(srcdir)/services/modstack.h \
- $(srcdir)/sldns/sbuffer.h $(srcdir)/dnstap/dnstap.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 \
+ $(srcdir)/sldns/rrdef.h $(srcdir)/util/data/msgencode.h $(srcdir)/util/data/dname.h $(srcdir)/util/net_help.h \
+ $(srcdir)/util/random.h $(srcdir)/util/fptr_wlist.h $(srcdir)/util/module.h $(srcdir)/util/tube.h \
+ $(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)/util/storage/lruhash.h \
- $(srcdir)/util/fptr_wlist.h $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
- $(srcdir)/dnscrypt/cert.h $(srcdir)/util/module.h \
- $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h \
- $(srcdir)/util/tube.h $(srcdir)/services/mesh.h $(srcdir)/util/rbtree.h $(srcdir)/services/modstack.h
+ $(srcdir)/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 \
+ $(srcdir)/sldns/rrdef.h $(srcdir)/util/tube.h $(srcdir)/services/mesh.h $(srcdir)/util/rbtree.h \
+ $(srcdir)/services/modstack.h
config_file.lo config_file.o: $(srcdir)/util/config_file.c config.h $(srcdir)/util/log.h \
$(srcdir)/util/configyyrename.h $(srcdir)/util/config_file.h util/configparser.h \
$(srcdir)/util/net_help.h $(srcdir)/util/data/msgparse.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h \
- $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/module.h $(srcdir)/util/data/msgreply.h \
- $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/regional.h $(srcdir)/util/fptr_wlist.h \
- $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
- $(srcdir)/dnscrypt/cert.h $(srcdir)/util/tube.h $(srcdir)/services/mesh.h $(srcdir)/util/rbtree.h \
- $(srcdir)/services/modstack.h $(srcdir)/util/data/dname.h $(srcdir)/util/rtt.h $(srcdir)/services/cache/infra.h \
- $(srcdir)/util/storage/dnstree.h $(srcdir)/sldns/wire2str.h $(srcdir)/sldns/parseutil.h \
- $(srcdir)/edns-subnet/edns-subnet.h $(srcdir)/util/iana_ports.inc
+ $(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 \
+ $(srcdir)/util/rbtree.h $(srcdir)/services/modstack.h $(srcdir)/util/data/dname.h $(srcdir)/util/rtt.h \
+ $(srcdir)/services/cache/infra.h $(srcdir)/util/storage/dnstree.h $(srcdir)/sldns/wire2str.h \
+ $(srcdir)/sldns/parseutil.h $(srcdir)/edns-subnet/edns-subnet.h $(srcdir)/util/iana_ports.inc
configlexer.lo configlexer.o: util/configlexer.c config.h $(srcdir)/util/configyyrename.h \
$(srcdir)/util/config_file.h util/configparser.h
configparser.lo configparser.o: util/configparser.c config.h $(srcdir)/util/configyyrename.h \
$(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)/daemon/worker.h $(srcdir)/libunbound/worker.h \
- $(srcdir)/sldns/sbuffer.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h \
- $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h $(srcdir)/dnscrypt/cert.h $(srcdir)/util/data/msgreply.h \
- $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/daemon/stats.h \
- $(srcdir)/util/timehist.h $(srcdir)/util/module.h $(srcdir)/dnstap/dnstap.h $(srcdir)/services/mesh.h \
- $(srcdir)/util/rbtree.h $(srcdir)/services/cache/rrset.h $(srcdir)/util/storage/slabhash.h \
- $(srcdir)/services/cache/infra.h $(srcdir)/util/storage/dnstree.h $(srcdir)/util/rtt.h \
- $(srcdir)/validator/validator.h $(srcdir)/validator/val_utils.h $(srcdir)/util/config_file.h \
- $(srcdir)/util/fptr_wlist.h $(srcdir)/util/tube.h
+ $(srcdir)/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 \
+ $(srcdir)/dnscrypt/cert.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h \
+ $(srcdir)/sldns/rrdef.h $(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h $(srcdir)/util/module.h \
+ $(srcdir)/dnstap/dnstap.h $(srcdir)/services/mesh.h $(srcdir)/util/rbtree.h $(srcdir)/services/cache/rrset.h \
+ $(srcdir)/util/storage/slabhash.h $(srcdir)/services/cache/infra.h $(srcdir)/util/storage/dnstree.h \
+ $(srcdir)/util/rtt.h $(srcdir)/validator/validator.h $(srcdir)/validator/val_utils.h \
+ $(srcdir)/util/config_file.h $(srcdir)/util/fptr_wlist.h $(srcdir)/util/tube.h
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/data/dname.h \
- $(srcdir)/util/storage/lruhash.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h \
- $(srcdir)/util/regional.h $(srcdir)/util/net_help.h $(srcdir)/util/config_file.h $(srcdir)/services/cache/dns.h \
- $(srcdir)/sldns/rrdef.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/sbuffer.h $(srcdir)/sldns/str2wire.h \
- $(srcdir)/sldns/wire2str.h $(srcdir)/sldns/parseutil.h $(srcdir)/validator/val_nsec3.h \
- $(srcdir)/validator/val_secalgo.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 \
+ $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/services/modstack.h \
+ $(srcdir)/util/data/dname.h $(srcdir)/util/data/msgencode.h $(srcdir)/util/regional.h $(srcdir)/util/net_help.h \
+ $(srcdir)/util/config_file.h $(srcdir)/util/random.h $(srcdir)/services/cache/dns.h \
+ $(srcdir)/services/outside_network.h \
+ $(srcdir)/services/listen_dnsport.h $(srcdir)/sldns/sbuffer.h $(srcdir)/sldns/str2wire.h \
+ $(srcdir)/sldns/wire2str.h $(srcdir)/sldns/parseutil.h $(srcdir)/sldns/keyraw.h \
+ $(srcdir)/validator/val_nsec3.h $(srcdir)/validator/val_secalgo.h
fptr_wlist.lo fptr_wlist.o: $(srcdir)/util/fptr_wlist.c config.h $(srcdir)/util/fptr_wlist.h \
$(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
- $(srcdir)/dnscrypt/cert.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/storage/lruhash.h \
- $(srcdir)/util/module.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h \
- $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/tube.h \
- $(srcdir)/services/mesh.h $(srcdir)/util/rbtree.h $(srcdir)/services/modstack.h $(srcdir)/util/mini_event.h \
- $(srcdir)/util/rbtree.h $(srcdir)/services/outside_network.h \
- $(srcdir)/services/localzone.h $(srcdir)/util/storage/dnstree.h $(srcdir)/services/view.h \
- $(srcdir)/services/authzone.h $(srcdir)/services/cache/infra.h $(srcdir)/util/rtt.h \
- $(srcdir)/services/cache/rrset.h $(srcdir)/util/storage/slabhash.h $(srcdir)/dns64/dns64.h \
- $(srcdir)/iterator/iterator.h $(srcdir)/services/outbound_list.h $(srcdir)/iterator/iter_fwd.h \
- $(srcdir)/validator/validator.h $(srcdir)/validator/val_utils.h $(srcdir)/validator/val_anchor.h \
- $(srcdir)/validator/val_nsec3.h $(srcdir)/validator/val_sigcrypt.h $(srcdir)/validator/val_kentry.h \
- $(srcdir)/validator/val_neg.h $(srcdir)/validator/autotrust.h $(srcdir)/libunbound/libworker.h \
- $(srcdir)/libunbound/context.h $(srcdir)/util/alloc.h $(srcdir)/libunbound/unbound.h \
- $(srcdir)/libunbound/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
-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)/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 \
+ $(srcdir)/services/modstack.h $(srcdir)/util/mini_event.h $(srcdir)/util/rbtree.h \
+ $(srcdir)/services/outside_network.h $(srcdir)/services/localzone.h \
+ $(srcdir)/util/storage/dnstree.h $(srcdir)/services/view.h $(srcdir)/services/authzone.h \
+ $(srcdir)/services/cache/infra.h $(srcdir)/util/rtt.h $(srcdir)/services/cache/rrset.h \
+ $(srcdir)/util/storage/slabhash.h $(srcdir)/dns64/dns64.h $(srcdir)/iterator/iterator.h \
+ $(srcdir)/services/outbound_list.h $(srcdir)/iterator/iter_fwd.h $(srcdir)/validator/validator.h \
+ $(srcdir)/validator/val_utils.h $(srcdir)/validator/val_anchor.h $(srcdir)/validator/val_nsec3.h \
+ $(srcdir)/validator/val_sigcrypt.h $(srcdir)/validator/val_kentry.h $(srcdir)/validator/val_neg.h \
+ $(srcdir)/validator/autotrust.h $(srcdir)/libunbound/libworker.h $(srcdir)/libunbound/context.h \
+ $(srcdir)/util/alloc.h $(srcdir)/libunbound/unbound.h $(srcdir)/libunbound/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)/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/data/packed_rrset.h \
- $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/sldns/wire2str.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)/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)/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 \
+ \
net_help.lo net_help.o: $(srcdir)/util/net_help.c config.h $(srcdir)/util/net_help.h $(srcdir)/util/log.h \
- $(srcdir)/util/data/dname.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/module.h \
- $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgparse.h \
- $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/regional.h $(srcdir)/sldns/parseutil.h \
- $(srcdir)/sldns/wire2str.h \
+ $(srcdir)/util/data/dname.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.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)/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)/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 \
+ $(srcdir)/services/modstack.h
regional.lo regional.o: $(srcdir)/util/regional.c config.h $(srcdir)/util/log.h $(srcdir)/util/regional.h
rtt.lo rtt.o: $(srcdir)/util/rtt.c config.h $(srcdir)/util/rtt.h
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/netevent.h \
- $(srcdir)/dnscrypt/dnscrypt.h $(srcdir)/dnscrypt/cert.h \
- $(srcdir)/util/module.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h \
- $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/tube.h \
- $(srcdir)/services/mesh.h $(srcdir)/util/rbtree.h $(srcdir)/services/modstack.h
+ $(srcdir)/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)/util/storage/lruhash.h \
- $(srcdir)/util/module.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h \
- $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/services/mesh.h \
- $(srcdir)/util/rbtree.h $(srcdir)/services/modstack.h $(srcdir)/util/ub_event.h
+ $(srcdir)/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)/util/mini_event.h $(srcdir)/util/rbtree.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)/util/module.h \
- $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgparse.h \
- $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/tube.h $(srcdir)/services/mesh.h $(srcdir)/util/rbtree.h \
- $(srcdir)/services/modstack.h $(srcdir)/util/mini_event.h $(srcdir)/util/rbtree.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 \
+ $(srcdir)/util/rbtree.h
winsock_event.lo winsock_event.o: $(srcdir)/util/winsock_event.c config.h
autotrust.lo autotrust.o: $(srcdir)/validator/autotrust.c config.h $(srcdir)/validator/autotrust.h \
$(srcdir)/util/rbtree.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h \
- $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/validator/val_anchor.h $(srcdir)/validator/val_utils.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/pkthdr.h $(srcdir)/sldns/rrdef.h \
- $(srcdir)/util/net_help.h $(srcdir)/util/config_file.h $(srcdir)/util/regional.h $(srcdir)/util/random.h \
- $(srcdir)/services/mesh.h $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
- $(srcdir)/dnscrypt/cert.h $(srcdir)/services/modstack.h \
- $(srcdir)/services/cache/rrset.h $(srcdir)/util/storage/slabhash.h $(srcdir)/validator/val_kcache.h \
- $(srcdir)/sldns/sbuffer.h $(srcdir)/sldns/wire2str.h $(srcdir)/sldns/str2wire.h $(srcdir)/sldns/keyraw.h \
+ $(srcdir)/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 \
+ $(srcdir)/util/regional.h $(srcdir)/util/random.h $(srcdir)/services/mesh.h $(srcdir)/util/netevent.h \
+ $(srcdir)/dnscrypt/dnscrypt.h $(srcdir)/dnscrypt/cert.h \
+ $(srcdir)/services/modstack.h $(srcdir)/services/cache/rrset.h $(srcdir)/util/storage/slabhash.h \
+ $(srcdir)/validator/val_kcache.h $(srcdir)/sldns/sbuffer.h $(srcdir)/sldns/wire2str.h $(srcdir)/sldns/str2wire.h \
+ $(srcdir)/sldns/keyraw.h \
val_anchor.lo val_anchor.o: $(srcdir)/validator/val_anchor.c config.h $(srcdir)/validator/val_anchor.h \
- $(srcdir)/util/rbtree.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/validator/val_sigcrypt.h \
- $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h $(srcdir)/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
+ $(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)/util/data/msgparse.h \
- $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/validator/val_utils.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 \
@@ -942,59 +967,64 @@ validator.lo validator.o: $(srcdir)/validator/validator.c config.h $(srcdir)/val
$(srcdir)/sldns/wire2str.h $(srcdir)/sldns/str2wire.h
val_kcache.lo val_kcache.o: $(srcdir)/validator/val_kcache.c config.h $(srcdir)/validator/val_kcache.h \
$(srcdir)/util/storage/slabhash.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \
- $(srcdir)/validator/val_kentry.h $(srcdir)/util/config_file.h $(srcdir)/util/data/dname.h \
- $(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)/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/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 \
+ $(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)/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)/util/data/dname.h \
- $(srcdir)/util/data/msgreply.h $(srcdir)/util/net_help.h $(srcdir)/util/config_file.h \
- $(srcdir)/services/cache/rrset.h $(srcdir)/util/storage/slabhash.h $(srcdir)/services/cache/dns.h \
- $(srcdir)/sldns/rrdef.h $(srcdir)/sldns/sbuffer.h
+ $(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 \
+ $(srcdir)/util/config_file.h $(srcdir)/services/cache/rrset.h $(srcdir)/util/storage/slabhash.h \
+ $(srcdir)/services/cache/dns.h $(srcdir)/sldns/rrdef.h $(srcdir)/sldns/sbuffer.h
val_nsec3.lo val_nsec3.o: $(srcdir)/validator/val_nsec3.c config.h $(srcdir)/validator/val_nsec3.h \
$(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)/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 $(srcdir)/util/regional.h \
- $(srcdir)/util/net_help.h $(srcdir)/util/data/dname.h $(srcdir)/validator/val_nsec.h $(srcdir)/sldns/sbuffer.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 \
+ $(srcdir)/util/regional.h $(srcdir)/util/net_help.h $(srcdir)/util/data/dname.h $(srcdir)/validator/val_nsec.h \
+ $(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)/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/pkthdr.h \
- $(srcdir)/sldns/rrdef.h $(srcdir)/services/cache/rrset.h $(srcdir)/util/storage/slabhash.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)/validator/val_secalgo.h \
- $(srcdir)/validator/val_nsec3.h $(srcdir)/util/rbtree.h $(srcdir)/sldns/rrdef.h $(srcdir)/sldns/keyraw.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)/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)/util/data/dname.h $(srcdir)/util/rbtree.h \
- $(srcdir)/util/net_help.h $(srcdir)/util/regional.h $(srcdir)/util/config_file.h $(srcdir)/sldns/keyraw.h \
+ $(srcdir)/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 \
+ $(srcdir)/util/regional.h $(srcdir)/util/config_file.h $(srcdir)/sldns/keyraw.h \
$(srcdir)/sldns/sbuffer.h $(srcdir)/sldns/parseutil.h $(srcdir)/sldns/wire2str.h \
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)/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_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 $(srcdir)/services/cache/rrset.h \
- $(srcdir)/util/storage/slabhash.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)/sldns/wire2str.h \
- $(srcdir)/sldns/parseutil.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 \
+ $(srcdir)/services/cache/rrset.h $(srcdir)/util/storage/slabhash.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)/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/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/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 \
$(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
$(srcdir)/dnscrypt/cert.h $(srcdir)/util/tube.h $(srcdir)/services/mesh.h $(srcdir)/util/rbtree.h \
@@ -1003,37 +1033,38 @@ 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)/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 $(srcdir)/edns-subnet/subnet-whitelist.h \
- $(srcdir)/util/storage/dnstree.h $(srcdir)/util/rbtree.h $(srcdir)/services/mesh.h $(srcdir)/util/netevent.h \
- $(srcdir)/dnscrypt/dnscrypt.h $(srcdir)/dnscrypt/cert.h \
- $(srcdir)/services/modstack.h $(srcdir)/services/cache/dns.h $(srcdir)/util/regional.h \
- $(srcdir)/util/config_file.h $(srcdir)/sldns/sbuffer.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 \
+ $(srcdir)/edns-subnet/subnet-whitelist.h $(srcdir)/util/storage/dnstree.h $(srcdir)/util/rbtree.h \
+ $(srcdir)/services/mesh.h $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
+ $(srcdir)/dnscrypt/cert.h $(srcdir)/services/modstack.h \
+ $(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)/util/data/msgparse.h \
- $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/edns-subnet/addrtree.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/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)/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
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/module.h \
- $(srcdir)/util/storage/lruhash.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h \
- $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/services/view.h \
- $(srcdir)/services/cache/dns.h $(srcdir)/sldns/str2wire.h $(srcdir)/util/config_file.h \
- $(srcdir)/util/fptr_wlist.h $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
+ $(srcdir)/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 \
+ $(srcdir)/util/config_file.h $(srcdir)/util/fptr_wlist.h $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
$(srcdir)/dnscrypt/cert.h $(srcdir)/util/tube.h $(srcdir)/services/mesh.h \
$(srcdir)/services/modstack.h $(srcdir)/util/net_help.h $(srcdir)/util/regional.h $(srcdir)/respip/respip.h
checklocks.lo checklocks.o: $(srcdir)/testcode/checklocks.c config.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \
@@ -1041,59 +1072,66 @@ 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/storage/lruhash.h \
- $(srcdir)/util/storage/lookup3.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)/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 $(srcdir)/dnscrypt/cert.h \
- $(srcdir)/util/tube.h $(srcdir)/services/mesh.h $(srcdir)/services/modstack.h $(srcdir)/util/regional.h \
- $(srcdir)/util/net_help.h $(srcdir)/util/config_file.h $(srcdir)/services/cache/dns.h $(srcdir)/sldns/wire2str.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 \
+ $(srcdir)/dnscrypt/cert.h $(srcdir)/util/tube.h $(srcdir)/services/mesh.h $(srcdir)/services/modstack.h \
+ $(srcdir)/util/regional.h $(srcdir)/util/net_help.h $(srcdir)/util/config_file.h $(srcdir)/services/cache/dns.h \
+ $(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/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
+ $(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)/testcode/unitmain.h \
- $(srcdir)/validator/val_anchor.h $(srcdir)/util/rbtree.h $(srcdir)/sldns/sbuffer.h $(srcdir)/sldns/rrdef.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)/util/data/dname.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.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/storage/slabhash.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)/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 \
- $(srcdir)/dnscrypt/cert.h $(srcdir)/util/data/msgreply.h \
- $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/random.h $(srcdir)/respip/respip.h $(srcdir)/util/module.h \
- $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/services/localzone.h $(srcdir)/services/view.h
+ $(srcdir)/util/log.h $(srcdir)/testcode/unitmain.h $(srcdir)/util/alloc.h $(srcdir)/util/locks.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 \
+ $(srcdir)/dnscrypt/cert.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h \
+ $(srcdir)/util/random.h $(srcdir)/respip/respip.h $(srcdir)/util/module.h $(srcdir)/util/data/msgparse.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/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
+ $(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)/validator/val_neg.h $(srcdir)/util/rbtree.h \
- $(srcdir)/sldns/rrdef.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)/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/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/validator/val_utils.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 \
$(srcdir)/testcode/testpkts.h $(srcdir)/util/data/dname.h $(srcdir)/util/regional.h $(srcdir)/util/alloc.h \
$(srcdir)/util/net_help.h $(srcdir)/util/config_file.h $(srcdir)/sldns/sbuffer.h $(srcdir)/sldns/keyraw.h \
$(srcdir)/sldns/str2wire.h $(srcdir)/sldns/wire2str.h
@@ -1105,84 +1143,89 @@ 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/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)/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)/testcode/unitmain.h \
- $(srcdir)/util/regional.h $(srcdir)/util/net_help.h $(srcdir)/util/data/msgreply.h \
- $(srcdir)/util/storage/lruhash.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/services/cache/dns.h \
- $(srcdir)/sldns/str2wire.h $(srcdir)/sldns/rrdef.h $(srcdir)/sldns/wire2str.h $(srcdir)/sldns/sbuffer.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 \
+ $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/services/modstack.h \
+ $(srcdir)/testcode/unitmain.h $(srcdir)/util/regional.h $(srcdir)/util/net_help.h $(srcdir)/services/cache/dns.h \
+ $(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/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
+ $(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)/dnscrypt/dnscrypt.h \
- $(srcdir)/dnscrypt/cert.h $(srcdir)/util/alloc.h \
- $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h \
- $(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h $(srcdir)/libunbound/unbound.h $(srcdir)/util/module.h \
- $(srcdir)/dnstap/dnstap.h $(srcdir)/services/cache/rrset.h \
- $(srcdir)/util/storage/slabhash.h $(srcdir)/services/cache/dns.h $(srcdir)/services/cache/infra.h \
- $(srcdir)/util/storage/dnstree.h $(srcdir)/util/rbtree.h $(srcdir)/util/rtt.h $(srcdir)/util/regional.h \
- $(srcdir)/util/net_help.h $(srcdir)/util/data/dname.h $(srcdir)/iterator/iterator.h \
+ $(srcdir)/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 \
+ $(srcdir)/util/module.h $(srcdir)/dnstap/dnstap.h \
+ $(srcdir)/services/cache/rrset.h $(srcdir)/util/storage/slabhash.h $(srcdir)/services/cache/dns.h \
+ $(srcdir)/services/cache/infra.h $(srcdir)/util/storage/dnstree.h $(srcdir)/util/rbtree.h $(srcdir)/util/rtt.h \
+ $(srcdir)/util/regional.h $(srcdir)/util/net_help.h $(srcdir)/util/data/dname.h $(srcdir)/iterator/iterator.h \
$(srcdir)/services/outbound_list.h $(srcdir)/iterator/iter_delegpt.h $(srcdir)/iterator/iter_utils.h \
$(srcdir)/iterator/iter_resptype.h $(srcdir)/iterator/iter_fwd.h $(srcdir)/iterator/iter_hints.h \
$(srcdir)/sldns/wire2str.h $(srcdir)/sldns/str2wire.h
daemon.lo daemon.o: $(srcdir)/daemon/daemon.c config.h \
- $(srcdir)/daemon/daemon.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/alloc.h $(srcdir)/services/modstack.h \
- $(srcdir)/daemon/worker.h \
- $(srcdir)/libunbound/worker.h $(srcdir)/sldns/sbuffer.h $(srcdir)/util/data/packed_rrset.h \
- $(srcdir)/util/storage/lruhash.h $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
- $(srcdir)/dnscrypt/cert.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h \
- $(srcdir)/sldns/rrdef.h $(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h $(srcdir)/libunbound/unbound.h \
- $(srcdir)/util/module.h $(srcdir)/dnstap/dnstap.h $(srcdir)/daemon/remote.h \
+ $(srcdir)/daemon/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 \
+ $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h $(srcdir)/dnscrypt/cert.h $(srcdir)/util/data/msgreply.h \
+ $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/daemon/stats.h \
+ $(srcdir)/util/timehist.h $(srcdir)/libunbound/unbound.h $(srcdir)/util/module.h $(srcdir)/dnstap/dnstap.h \
+ $(srcdir)/daemon/remote.h \
$(srcdir)/daemon/acl_list.h $(srcdir)/util/storage/dnstree.h $(srcdir)/util/rbtree.h $(srcdir)/services/view.h \
$(srcdir)/util/config_file.h $(srcdir)/util/shm_side/shm_main.h $(srcdir)/util/storage/lookup3.h \
$(srcdir)/util/storage/slabhash.h $(srcdir)/services/listen_dnsport.h $(srcdir)/services/cache/rrset.h \
- $(srcdir)/services/cache/infra.h $(srcdir)/util/rtt.h $(srcdir)/services/localzone.h $(srcdir)/util/random.h \
- $(srcdir)/util/tube.h $(srcdir)/util/net_help.h $(srcdir)/sldns/keyraw.h $(srcdir)/respip/respip.h
+ $(srcdir)/services/cache/infra.h $(srcdir)/util/rtt.h $(srcdir)/services/localzone.h \
+ $(srcdir)/services/authzone.h $(srcdir)/services/mesh.h $(srcdir)/util/random.h $(srcdir)/util/tube.h \
+ $(srcdir)/util/net_help.h $(srcdir)/sldns/keyraw.h $(srcdir)/respip/respip.h
remote.lo remote.o: $(srcdir)/daemon/remote.c config.h \
$(srcdir)/daemon/remote.h \
$(srcdir)/daemon/worker.h $(srcdir)/libunbound/worker.h $(srcdir)/sldns/sbuffer.h \
$(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \
- $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
- $(srcdir)/dnscrypt/cert.h $(srcdir)/util/alloc.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/msgparse.h \
- $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h \
- $(srcdir)/libunbound/unbound.h $(srcdir)/util/module.h $(srcdir)/dnstap/dnstap.h \
- $(srcdir)/daemon/daemon.h $(srcdir)/services/modstack.h \
- $(srcdir)/daemon/cachedump.h $(srcdir)/util/config_file.h $(srcdir)/util/net_help.h \
- $(srcdir)/services/listen_dnsport.h $(srcdir)/services/cache/rrset.h $(srcdir)/util/storage/slabhash.h \
- $(srcdir)/services/cache/infra.h $(srcdir)/util/storage/dnstree.h $(srcdir)/util/rbtree.h $(srcdir)/util/rtt.h \
- $(srcdir)/services/mesh.h $(srcdir)/services/localzone.h $(srcdir)/services/view.h $(srcdir)/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)/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 \
+ $(srcdir)/dnstap/dnstap.h $(srcdir)/daemon/daemon.h \
+ $(srcdir)/services/modstack.h $(srcdir)/daemon/cachedump.h $(srcdir)/util/config_file.h \
+ $(srcdir)/util/net_help.h $(srcdir)/services/listen_dnsport.h $(srcdir)/services/cache/rrset.h \
+ $(srcdir)/util/storage/slabhash.h $(srcdir)/services/cache/infra.h $(srcdir)/util/storage/dnstree.h \
+ $(srcdir)/util/rbtree.h $(srcdir)/util/rtt.h $(srcdir)/services/mesh.h $(srcdir)/services/localzone.h \
+ $(srcdir)/services/view.h $(srcdir)/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)/dnscrypt/cert.h $(srcdir)/util/alloc.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/msgparse.h \
- $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/module.h $(srcdir)/dnstap/dnstap.h \
- $(srcdir)/daemon/daemon.h $(srcdir)/services/modstack.h \
- $(srcdir)/services/mesh.h $(srcdir)/util/rbtree.h $(srcdir)/services/outside_network.h \
- $(srcdir)/services/listen_dnsport.h $(srcdir)/util/config_file.h $(srcdir)/util/tube.h $(srcdir)/util/net_help.h \
- $(srcdir)/validator/validator.h $(srcdir)/validator/val_utils.h $(srcdir)/iterator/iterator.h \
- $(srcdir)/services/outbound_list.h $(srcdir)/services/cache/rrset.h $(srcdir)/util/storage/slabhash.h \
- $(srcdir)/services/cache/infra.h $(srcdir)/util/storage/dnstree.h $(srcdir)/util/rtt.h \
- $(srcdir)/validator/val_kcache.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 \
+ $(srcdir)/services/modstack.h $(srcdir)/services/mesh.h $(srcdir)/util/rbtree.h \
+ $(srcdir)/services/outside_network.h $(srcdir)/services/listen_dnsport.h $(srcdir)/util/config_file.h \
+ $(srcdir)/util/tube.h $(srcdir)/util/net_help.h $(srcdir)/validator/validator.h $(srcdir)/validator/val_utils.h \
+ $(srcdir)/iterator/iterator.h $(srcdir)/services/outbound_list.h $(srcdir)/services/cache/rrset.h \
+ $(srcdir)/util/storage/slabhash.h $(srcdir)/services/cache/infra.h $(srcdir)/util/storage/dnstree.h \
+ $(srcdir)/util/rtt.h $(srcdir)/validator/val_kcache.h
unbound.lo unbound.o: $(srcdir)/daemon/unbound.c config.h $(srcdir)/util/log.h $(srcdir)/daemon/daemon.h \
- $(srcdir)/util/locks.h $(srcdir)/util/alloc.h $(srcdir)/services/modstack.h \
- $(srcdir)/daemon/remote.h \
+ $(srcdir)/util/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 \
$(srcdir)/dnscrypt/cert.h $(srcdir)/services/cache/rrset.h $(srcdir)/util/data/packed_rrset.h \
@@ -1193,25 +1236,27 @@ 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)/dnscrypt/cert.h $(srcdir)/util/alloc.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/msgparse.h \
- $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h \
- $(srcdir)/libunbound/unbound.h $(srcdir)/util/module.h $(srcdir)/dnstap/dnstap.h \
- $(srcdir)/daemon/daemon.h $(srcdir)/services/modstack.h \
- $(srcdir)/daemon/remote.h \
+ $(srcdir)/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 \
+ $(srcdir)/dnstap/dnstap.h $(srcdir)/daemon/daemon.h \
+ $(srcdir)/services/modstack.h $(srcdir)/daemon/remote.h \
$(srcdir)/daemon/acl_list.h $(srcdir)/util/storage/dnstree.h $(srcdir)/util/rbtree.h $(srcdir)/services/view.h \
$(srcdir)/util/config_file.h $(srcdir)/util/regional.h $(srcdir)/util/storage/slabhash.h \
$(srcdir)/services/listen_dnsport.h $(srcdir)/services/outside_network.h \
$(srcdir)/services/outbound_list.h $(srcdir)/services/cache/rrset.h $(srcdir)/services/cache/infra.h \
- $(srcdir)/util/rtt.h $(srcdir)/services/cache/dns.h $(srcdir)/services/mesh.h $(srcdir)/services/localzone.h \
- $(srcdir)/util/data/msgencode.h $(srcdir)/util/data/dname.h $(srcdir)/util/fptr_wlist.h $(srcdir)/util/tube.h \
- $(srcdir)/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)/util/rtt.h $(srcdir)/services/cache/dns.h $(srcdir)/services/authzone.h $(srcdir)/services/mesh.h \
+ $(srcdir)/services/localzone.h $(srcdir)/util/data/msgencode.h $(srcdir)/util/data/dname.h \
+ $(srcdir)/util/fptr_wlist.h $(srcdir)/util/tube.h $(srcdir)/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
testbound.lo testbound.o: $(srcdir)/testcode/testbound.c config.h $(srcdir)/testcode/testpkts.h \
$(srcdir)/testcode/replay.h $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
$(srcdir)/dnscrypt/cert.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \
- $(srcdir)/util/rbtree.h $(srcdir)/testcode/fake_event.h $(srcdir)/daemon/remote.h \
+ $(srcdir)/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 \
$(srcdir)/util/storage/slabhash.h $(srcdir)/util/storage/lruhash.h $(srcdir)/services/listen_dnsport.h \
@@ -1225,180 +1270,191 @@ 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)/dnscrypt/cert.h $(srcdir)/util/alloc.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/msgparse.h \
- $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h \
- $(srcdir)/libunbound/unbound.h $(srcdir)/util/module.h $(srcdir)/dnstap/dnstap.h \
- $(srcdir)/daemon/daemon.h $(srcdir)/services/modstack.h \
- $(srcdir)/daemon/remote.h \
+ $(srcdir)/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 \
+ $(srcdir)/dnstap/dnstap.h $(srcdir)/daemon/daemon.h \
+ $(srcdir)/services/modstack.h $(srcdir)/daemon/remote.h \
$(srcdir)/daemon/acl_list.h $(srcdir)/util/storage/dnstree.h $(srcdir)/util/rbtree.h $(srcdir)/services/view.h \
$(srcdir)/util/config_file.h $(srcdir)/util/regional.h $(srcdir)/util/storage/slabhash.h \
$(srcdir)/services/listen_dnsport.h $(srcdir)/services/outside_network.h \
$(srcdir)/services/outbound_list.h $(srcdir)/services/cache/rrset.h $(srcdir)/services/cache/infra.h \
- $(srcdir)/util/rtt.h $(srcdir)/services/cache/dns.h $(srcdir)/services/mesh.h $(srcdir)/services/localzone.h \
- $(srcdir)/util/data/msgencode.h $(srcdir)/util/data/dname.h $(srcdir)/util/fptr_wlist.h $(srcdir)/util/tube.h \
- $(srcdir)/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)/util/rtt.h $(srcdir)/services/cache/dns.h $(srcdir)/services/authzone.h $(srcdir)/services/mesh.h \
+ $(srcdir)/services/localzone.h $(srcdir)/util/data/msgencode.h $(srcdir)/util/data/dname.h \
+ $(srcdir)/util/fptr_wlist.h $(srcdir)/util/tube.h $(srcdir)/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
acl_list.lo acl_list.o: $(srcdir)/daemon/acl_list.c config.h $(srcdir)/daemon/acl_list.h \
$(srcdir)/util/storage/dnstree.h $(srcdir)/util/rbtree.h $(srcdir)/services/view.h $(srcdir)/util/locks.h \
- $(srcdir)/util/log.h $(srcdir)/util/regional.h $(srcdir)/util/config_file.h $(srcdir)/util/net_help.h \
- $(srcdir)/services/localzone.h $(srcdir)/util/module.h $(srcdir)/util/storage/lruhash.h \
- $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgparse.h \
- $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/sldns/str2wire.h
+ $(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)/util/alloc.h $(srcdir)/services/modstack.h \
- $(srcdir)/daemon/worker.h \
- $(srcdir)/libunbound/worker.h $(srcdir)/sldns/sbuffer.h $(srcdir)/util/data/packed_rrset.h \
- $(srcdir)/util/storage/lruhash.h $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
- $(srcdir)/dnscrypt/cert.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h \
- $(srcdir)/sldns/rrdef.h $(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h $(srcdir)/libunbound/unbound.h \
- $(srcdir)/util/module.h $(srcdir)/dnstap/dnstap.h $(srcdir)/daemon/remote.h \
+ $(srcdir)/daemon/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 \
+ $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h $(srcdir)/dnscrypt/cert.h $(srcdir)/util/data/msgreply.h \
+ $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/daemon/stats.h \
+ $(srcdir)/util/timehist.h $(srcdir)/libunbound/unbound.h $(srcdir)/util/module.h $(srcdir)/dnstap/dnstap.h \
+ $(srcdir)/daemon/remote.h \
$(srcdir)/daemon/acl_list.h $(srcdir)/util/storage/dnstree.h $(srcdir)/util/rbtree.h $(srcdir)/services/view.h \
$(srcdir)/util/config_file.h $(srcdir)/util/shm_side/shm_main.h $(srcdir)/util/storage/lookup3.h \
$(srcdir)/util/storage/slabhash.h $(srcdir)/services/listen_dnsport.h $(srcdir)/services/cache/rrset.h \
- $(srcdir)/services/cache/infra.h $(srcdir)/util/rtt.h $(srcdir)/services/localzone.h $(srcdir)/util/random.h \
- $(srcdir)/util/tube.h $(srcdir)/util/net_help.h $(srcdir)/sldns/keyraw.h $(srcdir)/respip/respip.h
+ $(srcdir)/services/cache/infra.h $(srcdir)/util/rtt.h $(srcdir)/services/localzone.h \
+ $(srcdir)/services/authzone.h $(srcdir)/services/mesh.h $(srcdir)/util/random.h $(srcdir)/util/tube.h \
+ $(srcdir)/util/net_help.h $(srcdir)/sldns/keyraw.h $(srcdir)/respip/respip.h
stats.lo stats.o: $(srcdir)/daemon/stats.c config.h $(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h \
$(srcdir)/libunbound/unbound.h $(srcdir)/daemon/worker.h $(srcdir)/libunbound/worker.h $(srcdir)/sldns/sbuffer.h \
$(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \
- $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
- $(srcdir)/dnscrypt/cert.h $(srcdir)/util/alloc.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/msgparse.h \
- $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/module.h $(srcdir)/dnstap/dnstap.h \
- $(srcdir)/daemon/daemon.h $(srcdir)/services/modstack.h \
- $(srcdir)/services/mesh.h $(srcdir)/util/rbtree.h $(srcdir)/services/outside_network.h \
- $(srcdir)/services/listen_dnsport.h $(srcdir)/util/config_file.h $(srcdir)/util/tube.h $(srcdir)/util/net_help.h \
- $(srcdir)/validator/validator.h $(srcdir)/validator/val_utils.h $(srcdir)/iterator/iterator.h \
- $(srcdir)/services/outbound_list.h $(srcdir)/services/cache/rrset.h $(srcdir)/util/storage/slabhash.h \
- $(srcdir)/services/cache/infra.h $(srcdir)/util/storage/dnstree.h $(srcdir)/util/rtt.h \
- $(srcdir)/validator/val_kcache.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 \
+ $(srcdir)/services/modstack.h $(srcdir)/services/mesh.h $(srcdir)/util/rbtree.h \
+ $(srcdir)/services/outside_network.h $(srcdir)/services/listen_dnsport.h $(srcdir)/util/config_file.h \
+ $(srcdir)/util/tube.h $(srcdir)/util/net_help.h $(srcdir)/validator/validator.h $(srcdir)/validator/val_utils.h \
+ $(srcdir)/iterator/iterator.h $(srcdir)/services/outbound_list.h $(srcdir)/services/cache/rrset.h \
+ $(srcdir)/util/storage/slabhash.h $(srcdir)/services/cache/infra.h $(srcdir)/util/storage/dnstree.h \
+ $(srcdir)/util/rtt.h $(srcdir)/validator/val_kcache.h
replay.lo replay.o: $(srcdir)/testcode/replay.c config.h $(srcdir)/util/log.h $(srcdir)/util/net_help.h \
$(srcdir)/util/config_file.h $(srcdir)/testcode/replay.h $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
$(srcdir)/dnscrypt/cert.h $(srcdir)/util/locks.h \
- $(srcdir)/testcode/testpkts.h $(srcdir)/util/rbtree.h $(srcdir)/testcode/fake_event.h $(srcdir)/sldns/str2wire.h \
- $(srcdir)/sldns/rrdef.h
+ $(srcdir)/testcode/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)/util/net_help.h \
- $(srcdir)/util/data/msgparse.h $(srcdir)/util/storage/lruhash.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h \
- $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgencode.h \
- $(srcdir)/util/data/dname.h $(srcdir)/util/config_file.h $(srcdir)/services/listen_dnsport.h \
- $(srcdir)/services/outside_network.h $(srcdir)/util/rbtree.h \
- $(srcdir)/services/cache/infra.h $(srcdir)/util/storage/dnstree.h $(srcdir)/util/rtt.h \
- $(srcdir)/testcode/replay.h $(srcdir)/testcode/testpkts.h $(srcdir)/util/fptr_wlist.h $(srcdir)/util/module.h \
- $(srcdir)/util/tube.h $(srcdir)/services/mesh.h $(srcdir)/services/modstack.h $(srcdir)/sldns/sbuffer.h \
- $(srcdir)/sldns/wire2str.h $(srcdir)/sldns/str2wire.h
+ $(srcdir)/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 \
+ $(srcdir)/util/config_file.h $(srcdir)/services/listen_dnsport.h $(srcdir)/services/outside_network.h \
+ $(srcdir)/util/rbtree.h $(srcdir)/services/cache/infra.h \
+ $(srcdir)/util/storage/dnstree.h $(srcdir)/util/rtt.h $(srcdir)/testcode/replay.h $(srcdir)/testcode/testpkts.h \
+ $(srcdir)/util/fptr_wlist.h $(srcdir)/util/module.h $(srcdir)/util/tube.h $(srcdir)/services/mesh.h \
+ $(srcdir)/services/modstack.h $(srcdir)/sldns/sbuffer.h $(srcdir)/sldns/wire2str.h $(srcdir)/sldns/str2wire.h
lock_verify.lo lock_verify.o: $(srcdir)/testcode/lock_verify.c config.h $(srcdir)/util/log.h $(srcdir)/util/rbtree.h \
- $(srcdir)/util/locks.h $(srcdir)/util/fptr_wlist.h $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
- $(srcdir)/dnscrypt/cert.h $(srcdir)/util/storage/lruhash.h \
- $(srcdir)/util/module.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h \
- $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/tube.h \
- $(srcdir)/services/mesh.h $(srcdir)/services/modstack.h
+ $(srcdir)/util/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/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
+ $(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)/dnscrypt/dnscrypt.h \
- $(srcdir)/dnscrypt/cert.h $(srcdir)/util/storage/lruhash.h \
- $(srcdir)/util/module.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h \
- $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/tube.h \
- $(srcdir)/services/mesh.h $(srcdir)/services/modstack.h
+ $(srcdir)/util/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)/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 $(srcdir)/util/storage/dnstree.h \
- $(srcdir)/validator/validator.h $(srcdir)/validator/val_utils.h $(srcdir)/services/localzone.h \
- $(srcdir)/services/view.h $(srcdir)/respip/respip.h $(srcdir)/sldns/sbuffer.h $(PYTHONMOD_HEADER) \
- $(srcdir)/edns-subnet/subnet-whitelist.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 \
+ $(srcdir)/util/storage/dnstree.h $(srcdir)/validator/validator.h $(srcdir)/validator/val_utils.h \
+ $(srcdir)/services/localzone.h $(srcdir)/services/view.h $(srcdir)/services/authzone.h $(srcdir)/services/mesh.h \
+ $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
+ $(srcdir)/dnscrypt/cert.h $(srcdir)/services/modstack.h $(srcdir)/respip/respip.h $(srcdir)/sldns/sbuffer.h \
+ $(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)/dnscrypt/cert.h \
- $(srcdir)/util/module.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h \
- $(srcdir)/sldns/rrdef.h $(srcdir)/util/tube.h $(srcdir)/services/mesh.h
+ $(srcdir)/util/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)/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)/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)/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)/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 $(srcdir)/util/regional.h \
- $(srcdir)/util/random.h $(srcdir)/util/net_help.h $(srcdir)/util/tube.h $(srcdir)/util/ub_event.h \
- $(srcdir)/services/localzone.h $(srcdir)/util/storage/dnstree.h $(srcdir)/services/view.h \
- $(srcdir)/services/cache/infra.h $(srcdir)/util/rtt.h $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
- $(srcdir)/dnscrypt/cert.h $(srcdir)/services/cache/rrset.h \
- $(srcdir)/util/storage/slabhash.h $(srcdir)/sldns/sbuffer.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 \
+ $(srcdir)/util/regional.h $(srcdir)/util/random.h $(srcdir)/util/net_help.h $(srcdir)/util/tube.h \
+ $(srcdir)/util/ub_event.h $(srcdir)/services/localzone.h $(srcdir)/util/storage/dnstree.h \
+ $(srcdir)/services/view.h $(srcdir)/services/cache/infra.h $(srcdir)/util/rtt.h $(srcdir)/util/netevent.h \
+ $(srcdir)/dnscrypt/dnscrypt.h $(srcdir)/dnscrypt/cert.h \
+ $(srcdir)/services/cache/rrset.h $(srcdir)/util/storage/slabhash.h $(srcdir)/services/authzone.h \
+ $(srcdir)/services/mesh.h $(srcdir)/sldns/sbuffer.h
libworker.lo libworker.o: $(srcdir)/libunbound/libworker.c config.h \
$(srcdir)/libunbound/libworker.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h \
- $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/libunbound/context.h $(srcdir)/util/alloc.h $(srcdir)/util/rbtree.h \
- $(srcdir)/services/modstack.h $(srcdir)/libunbound/unbound.h $(srcdir)/libunbound/worker.h \
- $(srcdir)/sldns/sbuffer.h $(srcdir)/libunbound/unbound-event.h $(srcdir)/services/outside_network.h \
- $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
- $(srcdir)/dnscrypt/cert.h $(srcdir)/services/mesh.h \
- $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/module.h \
- $(srcdir)/util/data/msgreply.h $(srcdir)/services/localzone.h $(srcdir)/util/storage/dnstree.h \
- $(srcdir)/services/view.h $(srcdir)/services/cache/rrset.h $(srcdir)/util/storage/slabhash.h \
- $(srcdir)/services/outbound_list.h $(srcdir)/util/fptr_wlist.h $(srcdir)/util/tube.h $(srcdir)/util/regional.h \
- $(srcdir)/util/random.h $(srcdir)/util/config_file.h $(srcdir)/util/storage/lookup3.h $(srcdir)/util/net_help.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)/services/outside_network.h $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
+ $(srcdir)/dnscrypt/cert.h \
+ $(srcdir)/services/mesh.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h \
+ $(srcdir)/util/module.h $(srcdir)/util/data/msgreply.h $(srcdir)/services/localzone.h \
+ $(srcdir)/util/storage/dnstree.h $(srcdir)/services/view.h $(srcdir)/services/cache/rrset.h \
+ $(srcdir)/util/storage/slabhash.h $(srcdir)/services/outbound_list.h $(srcdir)/services/authzone.h \
+ $(srcdir)/util/fptr_wlist.h $(srcdir)/util/tube.h $(srcdir)/util/regional.h $(srcdir)/util/random.h \
+ $(srcdir)/util/config_file.h $(srcdir)/util/storage/lookup3.h $(srcdir)/util/net_help.h \
$(srcdir)/util/data/dname.h $(srcdir)/util/data/msgencode.h $(srcdir)/iterator/iter_fwd.h \
$(srcdir)/iterator/iter_hints.h $(srcdir)/sldns/str2wire.h
unbound-host.lo unbound-host.o: $(srcdir)/smallapp/unbound-host.c config.h $(srcdir)/libunbound/unbound.h \
$(srcdir)/sldns/rrdef.h $(srcdir)/sldns/wire2str.h
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)/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)/util/data/msgparse.h \
- $(srcdir)/util/storage/lruhash.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/data/msgreply.h \
- $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/dname.h $(srcdir)/sldns/sbuffer.h \
- $(srcdir)/sldns/str2wire.h $(srcdir)/sldns/wire2str.h \
+ $(srcdir)/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)/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
+perf.lo perf.o: $(srcdir)/testcode/perf.c config.h $(srcdir)/util/log.h $(srcdir)/util/locks.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/net_help.h \
- $(srcdir)/util/shm_side/shm_main.h $(srcdir)/libunbound/unbound.h $(srcdir)/daemon/stats.h \
- $(srcdir)/util/timehist.h $(srcdir)/sldns/wire2str.h $(srcdir)/sldns/pkthdr.h
+ $(srcdir)/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 \
$(srcdir)/sldns/rrdef.h $(srcdir)/sldns/parseutil.h \
petal.lo petal.o: $(srcdir)/testcode/petal.c config.h \
pythonmod_utils.lo pythonmod_utils.o: $(srcdir)/pythonmod/pythonmod_utils.c config.h $(srcdir)/util/module.h \
- $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/data/msgreply.h \
- $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h \
- $(srcdir)/sldns/rrdef.h $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
+ $(srcdir)/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 \
$(srcdir)/services/cache/dns.h $(srcdir)/services/cache/rrset.h $(srcdir)/util/storage/slabhash.h \
$(srcdir)/util/regional.h $(srcdir)/iterator/iter_delegpt.h $(srcdir)/sldns/sbuffer.h \
win_svc.lo win_svc.o: $(srcdir)/winrc/win_svc.c config.h $(srcdir)/winrc/win_svc.h $(srcdir)/winrc/w_inst.h \
- $(srcdir)/daemon/daemon.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/alloc.h $(srcdir)/services/modstack.h \
- $(srcdir)/daemon/worker.h \
- $(srcdir)/libunbound/worker.h $(srcdir)/sldns/sbuffer.h $(srcdir)/util/data/packed_rrset.h \
- $(srcdir)/util/storage/lruhash.h $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
- $(srcdir)/dnscrypt/cert.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h \
- $(srcdir)/sldns/rrdef.h $(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h $(srcdir)/libunbound/unbound.h \
- $(srcdir)/util/module.h $(srcdir)/dnstap/dnstap.h $(srcdir)/daemon/remote.h \
+ $(srcdir)/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 \
+ $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h $(srcdir)/dnscrypt/cert.h $(srcdir)/util/data/msgreply.h \
+ $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/daemon/stats.h \
+ $(srcdir)/util/timehist.h $(srcdir)/libunbound/unbound.h $(srcdir)/util/module.h $(srcdir)/dnstap/dnstap.h \
+ $(srcdir)/daemon/remote.h \
$(srcdir)/util/config_file.h $(srcdir)/util/ub_event.h
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 \
@@ -1421,7 +1477,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
diff --git a/cachedb/cachedb.c b/cachedb/cachedb.c
index d07d76973fd2..80bdc380f3f6 100644
--- a/cachedb/cachedb.c
+++ b/cachedb/cachedb.c
@@ -568,14 +568,17 @@ cachedb_intcache_lookup(struct module_qstate* qstate)
msg = dns_cache_lookup(qstate->env, qstate->qinfo.qname,
qstate->qinfo.qname_len, qstate->qinfo.qtype,
qstate->qinfo.qclass, qstate->query_flags,
- qstate->region, qstate->env->scratch);
+ qstate->region, qstate->env->scratch,
+ 1 /* no partial messages with only a CNAME */
+ );
if(!msg && qstate->env->neg_cache) {
/* 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,
qstate->region, qstate->env->rrset_cache,
qstate->env->scratch_buffer,
- *qstate->env->now, 1/*add SOA*/, NULL);
+ *qstate->env->now, 1/*add SOA*/, NULL,
+ qstate->env->cfg);
}
if(!msg)
return 0;
diff --git a/compat/arc4_lock.c b/compat/arc4_lock.c
index 0c45ad01b042..a78f75232350 100644
--- a/compat/arc4_lock.c
+++ b/compat/arc4_lock.c
@@ -33,6 +33,9 @@
*/
#include "config.h"
#define LOCKRET(func) func
+#ifdef ENABLE_LOCK_CHECKS
+#undef ENABLE_LOCK_CHECKS
+#endif
#include "util/locks.h"
void _ARC4_LOCK(void);
@@ -46,6 +49,10 @@ void _ARC4_LOCK(void)
void _ARC4_UNLOCK(void)
{
}
+
+void _ARC4_LOCK_DESTROY(void)
+{
+}
#else /* !THREADS_DISABLED */
static lock_quick_type arc4lock;
@@ -64,4 +71,12 @@ void _ARC4_UNLOCK(void)
{
lock_quick_unlock(&arc4lock);
}
+
+void _ARC4_LOCK_DESTROY(void)
+{
+ if(arc4lockinit) {
+ arc4lockinit = 0;
+ lock_quick_destroy(&arc4lock);
+ }
+}
#endif /* THREADS_DISABLED */
diff --git a/config.h.in b/config.h.in
index 16a7b0281a1f..e7405603ddad 100644
--- a/config.h.in
+++ b/config.h.in
@@ -425,6 +425,12 @@
/* Define to 1 if you have the `SSL_CTX_set_security_level' function. */
#undef HAVE_SSL_CTX_SET_SECURITY_LEVEL
+/* Define to 1 if you have the `SSL_get0_peername' function. */
+#undef HAVE_SSL_GET0_PEERNAME
+
+/* Define to 1 if you have the `SSL_set1_host' function. */
+#undef HAVE_SSL_SET1_HOST
+
/* Define to 1 if you have the <stdarg.h> header file. */
#undef HAVE_STDARG_H
@@ -646,6 +652,9 @@
/* define if (v)snprintf does not return length needed, (but length used) */
#undef SNPRINTF_RET_BROKEN
+/* Define to 1 if libsodium supports sodium_set_misuse_handler */
+#undef SODIUM_MISUSE_HANDLER
+
/* Define to 1 if you have the ANSI C header files. */
#undef STDC_HEADERS
@@ -1147,6 +1156,7 @@ uint32_t arc4random(void);
void arc4random_buf(void* buf, size_t n);
void _ARC4_LOCK(void);
void _ARC4_UNLOCK(void);
+void _ARC4_LOCK_DESTROY(void);
#endif
#ifndef HAVE_ARC4RANDOM_UNIFORM
uint32_t arc4random_uniform(uint32_t upper_bound);
diff --git a/configure b/configure
index 96fb7eb19bab..8f830dc15ceb 100755
--- a/configure
+++ b/configure
@@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for unbound 1.6.8.
+# Generated by GNU Autoconf 2.69 for unbound 1.7.0.
#
# 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.6.8'
-PACKAGE_STRING='unbound 1.6.8'
+PACKAGE_VERSION='1.7.0'
+PACKAGE_STRING='unbound 1.7.0'
PACKAGE_BUGREPORT='unbound-bugs@nlnetlabs.nl'
PACKAGE_URL=''
@@ -848,6 +848,7 @@ with_pthreads
with_solaris_threads
with_pyunbound
with_pythonmodule
+enable_swig_version_check
with_nss
with_nettle
with_ssl
@@ -1437,7 +1438,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.6.8 to adapt to many kinds of systems.
+\`configure' configures unbound 1.7.0 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1502,7 +1503,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
- short | recursive ) echo "Configuration of unbound 1.6.8:";;
+ short | recursive ) echo "Configuration of unbound 1.7.0:";;
esac
cat <<\_ACEOF
@@ -1532,6 +1533,9 @@ Optional Features:
enable nonregional allocs, slow but exposes regional
allocations to other memory purifiers, for debug
purposes
+ --disable-swig-version-check
+ Disable swig version check to build python modules
+ with older swig even though that is unreliable
--disable-sha1 Disable SHA1 RRSIG support, does not disable nsec3
support
--disable-sha2 Disable SHA256 and SHA512 RRSIG support
@@ -1714,7 +1718,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
-unbound configure 1.6.8
+unbound configure 1.7.0
generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc.
@@ -2423,7 +2427,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.6.8, which was
+It was created by unbound $as_me 1.7.0, which was
generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@
@@ -2773,13 +2777,13 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
UNBOUND_VERSION_MAJOR=1
-UNBOUND_VERSION_MINOR=6
+UNBOUND_VERSION_MINOR=7
-UNBOUND_VERSION_MICRO=8
+UNBOUND_VERSION_MICRO=0
LIBUNBOUND_CURRENT=7
-LIBUNBOUND_REVISION=7
+LIBUNBOUND_REVISION=8
LIBUNBOUND_AGE=5
# 1.0.0 had 0:12:0
# 1.0.1 had 0:13:0
@@ -2838,6 +2842,7 @@ LIBUNBOUND_AGE=5
# 1.6.6 had 7:5:5
# 1.6.7 had 7:6:5
# 1.6.8 had 7:7:5
+# 1.7.0 had 7:8:5
# Current -- the number of the binary API that we're implementing
# Revision -- which iteration of the implementation of the binary
@@ -4429,6 +4434,7 @@ ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $
ac_compiler_gnu=$ac_cv_c_compiler_gnu
# allow user to override the -g -O2 flags.
+default_cflags=no
if test "x$CFLAGS" = "x" ; then
@@ -4492,6 +4498,7 @@ $as_echo "no" >&6; }
fi
+default_cflags=yes
fi
ac_ext=c
ac_cpp='$CPP $CPPFLAGS'
@@ -5945,6 +5952,10 @@ $as_echo "#define UNBOUND_DEBUG /**/" >>confdefs.h
# nothing to do.
;;
esac
+if test "$default_cflags" = "yes"; then
+ # only when CFLAGS was "" at the start, if the users wants to
+ # override we shouldn't add default cflags, because they wouldn't
+ # be able to turn off these options and set the CFLAGS wanted.
# Check whether --enable-flto was given.
if test "${enable_flto+set}" = set; then :
@@ -6079,6 +6090,7 @@ rm -f core conftest.err conftest.$ac_objext \
fi
+fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for inline" >&5
$as_echo_n "checking for inline... " >&6; }
@@ -16915,6 +16927,12 @@ $as_echo "#define HAVE_PYTHON 1" >>confdefs.h
# Check for SWIG
ub_have_swig=no
+ # Check whether --enable-swig-version-check was given.
+if test "${enable_swig_version_check+set}" = set; then :
+ enableval=$enable_swig_version_check;
+fi
+
+ if test "$enable_swig_version_check" = "yes"; then
# Extract the first word of "swig", so it can be a program name with args.
set dummy swig; ac_word=$2
@@ -17031,6 +17049,124 @@ $as_echo "$as_me: WARNING: cannot determine SWIG version" >&2;}
fi
+ else
+
+ # Extract the first word of "swig", so it can be a program name with args.
+set dummy swig; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_SWIG+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ case $SWIG in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_SWIG="$SWIG" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_path_SWIG="$as_dir/$ac_word$ac_exec_ext"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac
+fi
+SWIG=$ac_cv_path_SWIG
+if test -n "$SWIG"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $SWIG" >&5
+$as_echo "$SWIG" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ if test -z "$SWIG" ; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cannot find 'swig' program. You should look at http://www.swig.org" >&5
+$as_echo "$as_me: WARNING: cannot find 'swig' program. You should look at http://www.swig.org" >&2;}
+ SWIG='echo "Error: SWIG is not installed. You should look at http://www.swig.org" ; false'
+ elif test -n "" ; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for SWIG version" >&5
+$as_echo_n "checking for SWIG version... " >&6; }
+ swig_version=`$SWIG -version 2>&1 | grep 'SWIG Version' | sed 's/.*\([0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\).*/\1/g'`
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $swig_version" >&5
+$as_echo "$swig_version" >&6; }
+ if test -n "$swig_version" ; then
+ # Calculate the required version number components
+ required=
+ required_major=`echo $required | sed 's/[^0-9].*//'`
+ if test -z "$required_major" ; then
+ required_major=0
+ fi
+ required=`echo $required | sed 's/[0-9]*[^0-9]//'`
+ required_minor=`echo $required | sed 's/[^0-9].*//'`
+ if test -z "$required_minor" ; then
+ required_minor=0
+ fi
+ required=`echo $required | sed 's/[0-9]*[^0-9]//'`
+ required_patch=`echo $required | sed 's/[^0-9].*//'`
+ if test -z "$required_patch" ; then
+ required_patch=0
+ fi
+ # Calculate the available version number components
+ available=$swig_version
+ available_major=`echo $available | sed 's/[^0-9].*//'`
+ if test -z "$available_major" ; then
+ available_major=0
+ fi
+ available=`echo $available | sed 's/[0-9]*[^0-9]//'`
+ available_minor=`echo $available | sed 's/[^0-9].*//'`
+ if test -z "$available_minor" ; then
+ available_minor=0
+ fi
+ available=`echo $available | sed 's/[0-9]*[^0-9]//'`
+ available_patch=`echo $available | sed 's/[^0-9].*//'`
+ if test -z "$available_patch" ; then
+ available_patch=0
+ fi
+ badversion=0
+ if test $available_major -lt $required_major ; then
+ badversion=1
+ fi
+ if test $available_major -eq $required_major \
+ -a $available_minor -lt $required_minor ; then
+ badversion=1
+ fi
+ if test $available_major -eq $required_major \
+ -a $available_minor -eq $required_minor \
+ -a $available_patch -lt $required_patch ; then
+ badversion=1
+ fi
+ if test $badversion -eq 1 ; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: SWIG version >= is required. You have $swig_version. You should look at http://www.swig.org" >&5
+$as_echo "$as_me: WARNING: SWIG version >= is required. You have $swig_version. You should look at http://www.swig.org" >&2;}
+ SWIG='echo "Error: SWIG version >= is required. You have '"$swig_version"'. You should look at http://www.swig.org" ; false'
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: SWIG executable is '$SWIG'" >&5
+$as_echo "$as_me: SWIG executable is '$SWIG'" >&6;}
+ SWIG_LIB=`$SWIG -swiglib`
+ { $as_echo "$as_me:${as_lineno-$LINENO}: SWIG library directory is '$SWIG_LIB'" >&5
+$as_echo "$as_me: SWIG library directory is '$SWIG_LIB'" >&6;}
+ fi
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cannot determine SWIG version" >&5
+$as_echo "$as_me: WARNING: cannot determine SWIG version" >&2;}
+ SWIG='echo "Error: Cannot determine SWIG version. You should look at http://www.swig.org" ; false'
+ fi
+ fi
+
+
+ fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking SWIG" >&5
$as_echo_n "checking SWIG... " >&6; }
if test ! -x "$SWIG"; then
@@ -17651,7 +17787,7 @@ done
# these check_funcs need -lssl
BAKLIBS="$LIBS"
LIBS="-lssl $LIBS"
-for ac_func in OPENSSL_init_ssl SSL_CTX_set_security_level
+for ac_func in OPENSSL_init_ssl SSL_CTX_set_security_level SSL_set1_host SSL_get0_peername
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"
@@ -18070,6 +18206,28 @@ case "$enable_dsa" in
ac_fn_c_check_func "$LINENO" "DSA_SIG_new" "ac_cv_func_DSA_SIG_new"
if test "x$ac_cv_func_DSA_SIG_new" = xyes; then :
+ as_ac_Type=`$as_echo "ac_cv_type_DSA_SIG*" | $as_tr_sh`
+ac_fn_c_check_type "$LINENO" "DSA_SIG*" "$as_ac_Type" "
+$ac_includes_default
+#ifdef HAVE_OPENSSL_ERR_H
+#include <openssl/err.h>
+#endif
+
+#ifdef HAVE_OPENSSL_RAND_H
+#include <openssl/rand.h>
+#endif
+
+#ifdef HAVE_OPENSSL_CONF_H
+#include <openssl/conf.h>
+#endif
+
+#ifdef HAVE_OPENSSL_ENGINE_H
+#include <openssl/engine.h>
+#endif
+
+"
+if eval test \"x\$"$as_ac_Type"\" = x"yes"; then :
+
cat >>confdefs.h <<_ACEOF
#define USE_DSA 1
@@ -18081,6 +18239,12 @@ else
fi
fi
+
+else
+ if test "x$enable_dsa" = "xyes"; then as_fn_error $? "OpenSSL does not support DSA and you used --enable-dsa." "$LINENO" 5
+ fi
+fi
+
else
cat >>confdefs.h <<_ACEOF
@@ -20488,6 +20652,66 @@ else
fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing sodium_set_misuse_handler" >&5
+$as_echo_n "checking for library containing sodium_set_misuse_handler... " >&6; }
+if ${ac_cv_search_sodium_set_misuse_handler+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_func_search_save_LIBS=$LIBS
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char sodium_set_misuse_handler ();
+int
+main ()
+{
+return sodium_set_misuse_handler ();
+ ;
+ return 0;
+}
+_ACEOF
+for ac_lib in '' sodium; do
+ if test -z "$ac_lib"; then
+ ac_res="none required"
+ else
+ ac_res=-l$ac_lib
+ LIBS="-l$ac_lib $ac_func_search_save_LIBS"
+ fi
+ if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_search_sodium_set_misuse_handler=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext
+ if ${ac_cv_search_sodium_set_misuse_handler+:} false; then :
+ break
+fi
+done
+if ${ac_cv_search_sodium_set_misuse_handler+:} false; then :
+
+else
+ ac_cv_search_sodium_set_misuse_handler=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_sodium_set_misuse_handler" >&5
+$as_echo "$ac_cv_search_sodium_set_misuse_handler" >&6; }
+ac_res=$ac_cv_search_sodium_set_misuse_handler
+if test "$ac_res" != no; then :
+ test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+
+$as_echo "#define SODIUM_MISUSE_HANDLER 1" >>confdefs.h
+
+
+fi
+
$as_echo "#define USE_DNSCRYPT 1" >>confdefs.h
@@ -20601,6 +20825,15 @@ if test "${with_libunbound_only+set}" = set; then :
fi
+if test $ALLTARGET = "alltargets"; then
+ if test $USE_NSS = "yes"; then
+ as_fn_error $? "--with-nss can only be used in combination with --with-libunbound-only." "$LINENO" 5
+ fi
+ if test $USE_NETTLE = "yes"; then
+ as_fn_error $? "--with-nettle can only be used in combination with --with-libunbound-only." "$LINENO" 5
+ fi
+fi
+
@@ -20695,7 +20928,7 @@ _ACEOF
-version=1.6.8
+version=1.7.0
date=`date +'%b %e, %Y'`
@@ -21214,7 +21447,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.6.8, which was
+This file was extended by unbound $as_me 1.7.0, which was
generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -21280,7 +21513,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.6.8
+unbound config.status 1.7.0
configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\"
diff --git a/configure.ac b/configure.ac
index 5c2059ed793f..5417160fb66d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -10,15 +10,15 @@ sinclude(dnscrypt/dnscrypt.m4)
# must be numbers. ac_defun because of later processing
m4_define([VERSION_MAJOR],[1])
-m4_define([VERSION_MINOR],[6])
-m4_define([VERSION_MICRO],[8])
+m4_define([VERSION_MINOR],[7])
+m4_define([VERSION_MICRO],[0])
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=8
LIBUNBOUND_AGE=5
# 1.0.0 had 0:12:0
# 1.0.1 had 0:13:0
@@ -77,6 +77,7 @@ LIBUNBOUND_AGE=5
# 1.6.6 had 7:5:5
# 1.6.7 had 7:6:5
# 1.6.8 had 7:7:5
+# 1.7.0 had 7:8:5
# Current -- the number of the binary API that we're implementing
# Revision -- which iteration of the implementation of the binary
@@ -246,9 +247,11 @@ AC_DEFINE_UNQUOTED(RSRC_PACKAGE_VERSION, [$wnvs], [version number for resource f
AC_C_CONST
AC_LANG_C
# allow user to override the -g -O2 flags.
+default_cflags=no
if test "x$CFLAGS" = "x" ; then
ACX_CHECK_COMPILER_FLAG(g, [CFLAGS="$CFLAGS -g"])
ACX_CHECK_COMPILER_FLAG(O2, [CFLAGS="$CFLAGS -O2"])
+default_cflags=yes
fi
AC_PROG_CC
ACX_DEPFLAG
@@ -272,9 +275,14 @@ case "$debug_enabled" in
# nothing to do.
;;
esac
-ACX_CHECK_FLTO
-ACX_CHECK_PIE
-ACX_CHECK_RELRO_NOW
+if test "$default_cflags" = "yes"; then
+ # only when CFLAGS was "" at the start, if the users wants to
+ # override we shouldn't add default cflags, because they wouldn't
+ # be able to turn off these options and set the CFLAGS wanted.
+ ACX_CHECK_FLTO
+ ACX_CHECK_PIE
+ ACX_CHECK_RELRO_NOW
+fi
AC_C_INLINE
ACX_CHECK_FORMAT_ATTRIBUTE
@@ -579,7 +587,12 @@ if test x_$ub_test_python != x_no; then
# Check for SWIG
ub_have_swig=no
- AC_PROG_SWIG(2.0.1)
+ AC_ARG_ENABLE(swig-version-check, AC_HELP_STRING([--disable-swig-version-check], [Disable swig version check to build python modules with older swig even though that is unreliable]))
+ if test "$enable_swig_version_check" = "yes"; then
+ AC_PROG_SWIG(2.0.1)
+ else
+ AC_PROG_SWIG
+ fi
AC_MSG_CHECKING(SWIG)
if test ! -x "$SWIG"; then
AC_ERROR([failed to find swig tool, install it, or do not build Python module and PyUnbound])
@@ -711,7 +724,7 @@ AC_CHECK_FUNCS([OPENSSL_config EVP_sha1 EVP_sha256 EVP_sha512 FIPS_mode EVP_MD_C
# these check_funcs need -lssl
BAKLIBS="$LIBS"
LIBS="-lssl $LIBS"
-AC_CHECK_FUNCS([OPENSSL_init_ssl SSL_CTX_set_security_level])
+AC_CHECK_FUNCS([OPENSSL_init_ssl SSL_CTX_set_security_level SSL_set1_host SSL_get0_peername])
LIBS="$BAKLIBS"
AC_CHECK_DECLS([SSL_COMP_get_compression_methods,sk_SSL_COMP_pop_free,SSL_CTX_set_ecdh_auto], [], [], [
@@ -927,8 +940,28 @@ case "$enable_dsa" in
# detect if DSA is supported, and turn it off if not.
if test $USE_NSS = "no" -a $USE_NETTLE = "no"; then
AC_CHECK_FUNC(DSA_SIG_new, [
+ AC_CHECK_TYPE(DSA_SIG*, [
AC_DEFINE_UNQUOTED([USE_DSA], [1], [Define this to enable DSA support.])
], [if test "x$enable_dsa" = "xyes"; then AC_MSG_ERROR([OpenSSL does not support DSA and you used --enable-dsa.])
+ fi ], [
+AC_INCLUDES_DEFAULT
+#ifdef HAVE_OPENSSL_ERR_H
+#include <openssl/err.h>
+#endif
+
+#ifdef HAVE_OPENSSL_RAND_H
+#include <openssl/rand.h>
+#endif
+
+#ifdef HAVE_OPENSSL_CONF_H
+#include <openssl/conf.h>
+#endif
+
+#ifdef HAVE_OPENSSL_ENGINE_H
+#include <openssl/engine.h>
+#endif
+ ])
+ ], [if test "x$enable_dsa" = "xyes"; then AC_MSG_ERROR([OpenSSL does not support DSA and you used --enable-dsa.])
fi ])
else
AC_DEFINE_UNQUOTED([USE_DSA], [1], [Define this to enable DSA support.])
@@ -1471,6 +1504,15 @@ AC_ARG_WITH(libunbound-only, AC_HELP_STRING([--with-libunbound-only],
INSTALLTARGET="install-lib"
fi
])
+if test $ALLTARGET = "alltargets"; then
+ if test $USE_NSS = "yes"; then
+ AC_ERROR([--with-nss can only be used in combination with --with-libunbound-only.])
+ fi
+ if test $USE_NETTLE = "yes"; then
+ AC_ERROR([--with-nettle can only be used in combination with --with-libunbound-only.])
+ fi
+fi
+
AC_SUBST(ALLTARGET)
AC_SUBST(INSTALLTARGET)
@@ -1644,6 +1686,7 @@ uint32_t arc4random(void);
void arc4random_buf(void* buf, size_t n);
void _ARC4_LOCK(void);
void _ARC4_UNLOCK(void);
+void _ARC4_LOCK_DESTROY(void);
#endif
#ifndef HAVE_ARC4RANDOM_UNIFORM
uint32_t arc4random_uniform(uint32_t upper_bound);
diff --git a/contrib/README b/contrib/README
index 8aa5fb4eb064..2a59e0330f0d 100644
--- a/contrib/README
+++ b/contrib/README
@@ -34,3 +34,4 @@ distribution but may be helpful.
* redirect-bogus.patch: Return configured address for bogus A and AAAA answers,
instead of SERVFAIL. Contributed by SIDN.
* fastrpz.patch: fastrpz support from Farsight Security.
+* libunbound.so.conf: ltrace.conf file, see ltrace.conf(5), for libunbound.
diff --git a/contrib/fastrpz.patch b/contrib/fastrpz.patch
index 362e07cc6a8d..6e78bf1b7cf3 100644
--- a/contrib/fastrpz.patch
+++ b/contrib/fastrpz.patch
@@ -1,10 +1,15 @@
+Description: based on the included patch contrib/fastrpz.patch
+Author: fastrpz@farsightsecurity.com
+---
+This patch header follows DEP-3: http://dep.debian.net/deps/dep3/
===================================================================
RCS file: ./RCS/Makefile.in,v
retrieving revision 1.1
-diff -u --unidirectional-new-file -r1.1 ./Makefile.in
---- ./Makefile.in
-+++ ./Makefile.in
-@@ -23,6 +23,8 @@
+Index: unbound-1.7.0~rc1/Makefile.in
+===================================================================
+--- unbound-1.7.0~rc1.orig/Makefile.in
++++ unbound-1.7.0~rc1/Makefile.in
+@@ -23,6 +23,8 @@ CHECKLOCK_SRC=testcode/checklocks.c
CHECKLOCK_OBJ=@CHECKLOCK_OBJ@
DNSTAP_SRC=@DNSTAP_SRC@
DNSTAP_OBJ=@DNSTAP_OBJ@
@@ -13,7 +18,7 @@ diff -u --unidirectional-new-file -r1.1 ./Makefile.in
DNSCRYPT_SRC=@DNSCRYPT_SRC@
DNSCRYPT_OBJ=@DNSCRYPT_OBJ@
WITH_PYTHONMODULE=@WITH_PYTHONMODULE@
-@@ -125,7 +127,7 @@
+@@ -125,7 +127,7 @@ validator/val_sigcrypt.c validator/val_u
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) \
@@ -22,16 +27,16 @@ diff -u --unidirectional-new-file -r1.1 ./Makefile.in
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 \
iter_donotq.lo iter_fwd.lo iter_hints.lo iter_priv.lo iter_resptype.lo \
-@@ -137,7 +139,7 @@
+@@ -137,7 +139,7 @@ slabhash.lo timehist.lo tube.lo winsock_
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 \
+ val_secalgo.lo val_sigcrypt.lo val_utils.lo dns64.lo cachedb.lo authzone.lo\
$(SUBNET_OBJ) $(PYTHONMOD_OBJ) $(CHECKLOCK_OBJ) $(DNSTAP_OBJ) $(DNSCRYPT_OBJ) \
--$(IPSECMOD_OBJ)
-+$(FASTRPZ_OBJ) $(DNSCRYPT_OBJ)
- COMMON_OBJ_WITHOUT_NETCALL+=respip.lo
+-$(IPSECMOD_OBJ) respip.lo
++$(FASTRPZ_OBJ) $(IPSECMOD_OBJ) respip.lo
COMMON_OBJ_WITHOUT_UB_EVENT=$(COMMON_OBJ_WITHOUT_NETCALL) netevent.lo listen_dnsport.lo \
outside_network.lo
-@@ -398,6 +401,11 @@
+ COMMON_OBJ=$(COMMON_OBJ_WITHOUT_UB_EVENT) ub_event.lo
+@@ -400,6 +402,11 @@ dnscrypt.lo dnscrypt.o: $(srcdir)/dnscry
$(srcdir)/util/config_file.h $(srcdir)/util/log.h \
$(srcdir)/util/netevent.h
@@ -43,13 +48,11 @@ diff -u --unidirectional-new-file -r1.1 ./Makefile.in
# Python Module
pythonmod.lo pythonmod.o: $(srcdir)/pythonmod/pythonmod.c config.h \
pythonmod/interface.h \
+Index: unbound-1.7.0~rc1/config.h.in
===================================================================
-RCS file: ./RCS/config.h.in,v
-retrieving revision 1.1
-diff -u --unidirectional-new-file -r1.1 ./config.h.in
---- ./config.h.in
-+++ ./config.h.in
-@@ -1199,4 +1199,11 @@
+--- unbound-1.7.0~rc1.orig/config.h.in
++++ unbound-1.7.0~rc1/config.h.in
+@@ -1228,4 +1228,11 @@ void *unbound_stat_realloc_log(void *ptr
/** the version of unbound-control that this software implements */
#define UNBOUND_CONTROL_VERSION 1
@@ -62,13 +65,11 @@ diff -u --unidirectional-new-file -r1.1 ./config.h.in
+#undef FASTRPZ_LIB_OPEN
+/** turn on fastrpz response policy zones */
+#undef ENABLE_FASTRPZ
+Index: unbound-1.7.0~rc1/configure.ac
===================================================================
-RCS file: ./RCS/configure.ac,v
-retrieving revision 1.1
-diff -u --unidirectional-new-file -r1.1 ./configure.ac
---- ./configure.ac
-+++ ./configure.ac
-@@ -6,6 +6,7 @@
+--- unbound-1.7.0~rc1.orig/configure.ac
++++ unbound-1.7.0~rc1/configure.ac
+@@ -6,6 +6,7 @@ sinclude(ax_pthread.m4)
sinclude(acx_python.m4)
sinclude(ac_pkg_swig.m4)
sinclude(dnstap/dnstap.m4)
@@ -76,8 +77,8 @@ diff -u --unidirectional-new-file -r1.1 ./configure.ac
sinclude(dnscrypt/dnscrypt.m4)
# must be numbers. ac_defun because of later processing
-@@ -1352,6 +1353,9 @@
- ;;
+@@ -1453,6 +1454,9 @@ case "$enable_ipsecmod" in
+ ;;
esac
+# check for Fastrpz with fastrpz/rpz.m4
@@ -86,13 +87,11 @@ diff -u --unidirectional-new-file -r1.1 ./configure.ac
AC_MSG_CHECKING([if ${MAKE:-make} supports $< with implicit rule in scope])
# on openBSD, the implicit rule make $< work.
# on Solaris, it does not work ($? is changed sources, $^ lists dependencies).
+Index: unbound-1.7.0~rc1/daemon/daemon.c
===================================================================
-RCS file: ./daemon/RCS/daemon.c,v
-retrieving revision 1.1
-diff -u --unidirectional-new-file -r1.1 ./daemon/daemon.c
---- ./daemon/daemon.c
-+++ ./daemon/daemon.c
-@@ -89,6 +89,9 @@
+--- unbound-1.7.0~rc1.orig/daemon/daemon.c
++++ unbound-1.7.0~rc1/daemon/daemon.c
+@@ -90,6 +90,9 @@
#include "sldns/keyraw.h"
#include "respip/respip.h"
#include <signal.h>
@@ -102,7 +101,7 @@ diff -u --unidirectional-new-file -r1.1 ./daemon/daemon.c
#ifdef HAVE_SYSTEMD
#include <systemd/sd-daemon.h>
-@@ -451,6 +454,14 @@
+@@ -461,6 +464,14 @@ daemon_create_workers(struct daemon* dae
fatal_exit("dnstap enabled in config but not built with dnstap support");
#endif
}
@@ -117,9 +116,9 @@ diff -u --unidirectional-new-file -r1.1 ./daemon/daemon.c
for(i=0; i<daemon->num; i++) {
if(!(daemon->workers[i] = worker_create(daemon, i,
shufport+numport*i/daemon->num,
-@@ -691,6 +702,9 @@
- #ifdef USE_DNSTAP
- dt_delete(daemon->dtenv);
+@@ -710,6 +721,9 @@ daemon_cleanup(struct daemon* daemon)
+ #ifdef USE_DNSCRYPT
+ dnsc_delete(daemon->dnscenv);
#endif
+#ifdef ENABLE_FASTRPZ
+ rpz_delete(&daemon->rpz_clist, &daemon->rpz_client);
@@ -127,13 +126,11 @@ diff -u --unidirectional-new-file -r1.1 ./daemon/daemon.c
daemon->cfg = NULL;
}
+Index: unbound-1.7.0~rc1/daemon/daemon.h
===================================================================
-RCS file: ./daemon/RCS/daemon.h,v
-retrieving revision 1.1
-diff -u --unidirectional-new-file -r1.1 ./daemon/daemon.h
---- ./daemon/daemon.h
-+++ ./daemon/daemon.h
-@@ -134,6 +134,11 @@
+--- unbound-1.7.0~rc1.orig/daemon/daemon.h
++++ unbound-1.7.0~rc1/daemon/daemon.h
+@@ -134,6 +134,11 @@ struct daemon {
/** the dnscrypt environment */
struct dnsc_env* dnscenv;
#endif
@@ -145,13 +142,11 @@ diff -u --unidirectional-new-file -r1.1 ./daemon/daemon.h
};
/**
+Index: unbound-1.7.0~rc1/daemon/worker.c
===================================================================
-RCS file: ./daemon/RCS/worker.c,v
-retrieving revision 1.1
-diff -u --unidirectional-new-file -r1.1 ./daemon/worker.c
---- ./daemon/worker.c
-+++ ./daemon/worker.c
-@@ -73,6 +73,9 @@
+--- unbound-1.7.0~rc1.orig/daemon/worker.c
++++ unbound-1.7.0~rc1/daemon/worker.c
+@@ -74,6 +74,9 @@
#include "libunbound/context.h"
#include "libunbound/libworker.h"
#include "sldns/sbuffer.h"
@@ -161,7 +156,7 @@ diff -u --unidirectional-new-file -r1.1 ./daemon/worker.c
#include "sldns/wire2str.h"
#include "util/shm_side/shm_main.h"
#include "dnscrypt/dnscrypt.h"
-@@ -526,8 +529,27 @@
+@@ -527,8 +530,27 @@ answer_norec_from_cache(struct worker* w
/* not secure */
secure = 0;
break;
@@ -189,7 +184,7 @@ diff -u --unidirectional-new-file -r1.1 ./daemon/worker.c
/* return this delegation from the cache */
edns->edns_version = EDNS_ADVERTISED_VERSION;
edns->udp_size = EDNS_ADVERTISED_SIZE;
-@@ -688,6 +710,23 @@
+@@ -689,6 +711,23 @@ answer_from_cache(struct worker* worker,
secure = 0;
}
} else secure = 0;
@@ -213,7 +208,7 @@ diff -u --unidirectional-new-file -r1.1 ./daemon/worker.c
edns->edns_version = EDNS_ADVERTISED_VERSION;
edns->udp_size = EDNS_ADVERTISED_SIZE;
-@@ -1267,6 +1306,15 @@
+@@ -1291,6 +1330,15 @@ worker_handle_request(struct comm_point*
log_addr(VERB_ALGO, "refused nonrec (cache snoop) query from",
&repinfo->addr, repinfo->addrlen);
goto send_reply;
@@ -229,16 +224,16 @@ diff -u --unidirectional-new-file -r1.1 ./daemon/worker.c
}
/* If we've found a local alias, replace the qname with the alias
-@@ -1315,12 +1363,21 @@
+@@ -1339,12 +1387,21 @@ lookup_cache:
h = query_info_hash(lookup_qinfo, sldns_buffer_read_u16_at(c->buffer, 2));
if((e=slabhash_lookup(worker->env.msg_cache, h, lookup_qinfo, 0))) {
/* answer from cache - we have acquired a readlock on it */
-- if(answer_from_cache(worker, &qinfo,
-+ ret = answer_from_cache(worker, &qinfo,
+- if(answer_from_cache(worker, &qinfo,
++ ret = answer_from_cache(worker, &qinfo,
cinfo, &need_drop, &alias_rrset, &partial_rep,
- (struct reply_info*)e->data,
- *(uint16_t*)(void *)sldns_buffer_begin(c->buffer),
- sldns_buffer_read_u16_at(c->buffer, 2), repinfo,
+ (struct reply_info*)e->data,
+ *(uint16_t*)(void *)sldns_buffer_begin(c->buffer),
+ sldns_buffer_read_u16_at(c->buffer, 2), repinfo,
- &edns)) {
+ &edns);
+#ifdef ENABLE_FASTRPZ
@@ -253,7 +248,7 @@ diff -u --unidirectional-new-file -r1.1 ./daemon/worker.c
/* prefetch it if the prefetch TTL expired.
* Note that if there is more than one pass
* its qname must be that used for cache
-@@ -1371,11 +1428,19 @@
+@@ -1398,11 +1455,19 @@ lookup_cache:
lock_rw_unlock(&e->lock);
}
if(!LDNS_RD_WIRE(sldns_buffer_begin(c->buffer))) {
@@ -275,13 +270,11 @@ diff -u --unidirectional-new-file -r1.1 ./daemon/worker.c
goto send_reply;
}
verbose(VERB_ALGO, "answer norec from cache -- "
+Index: unbound-1.7.0~rc1/doc/unbound.conf.5.in
===================================================================
-RCS file: ./doc/RCS/unbound.conf.5.in,v
-retrieving revision 1.1
-diff -u --unidirectional-new-file -r1.1 ./doc/unbound.conf.5.in
---- ./doc/unbound.conf.5.in
-+++ ./doc/unbound.conf.5.in
-@@ -1446,6 +1446,81 @@
+--- unbound-1.7.0~rc1.orig/doc/unbound.conf.5.in
++++ unbound-1.7.0~rc1/doc/unbound.conf.5.in
+@@ -1581,6 +1581,81 @@ It must be /96 or shorter. The default
.B dns64\-synthall: \fI<yes or no>\fR
Debug option, default no. If enabled, synthesize all AAAA records
despite the presence of actual AAAA records.
@@ -363,12 +356,10 @@ diff -u --unidirectional-new-file -r1.1 ./doc/unbound.conf.5.in
.SS "DNSCrypt Options"
.LP
The
+Index: unbound-1.7.0~rc1/fastrpz/librpz.h
===================================================================
-RCS file: ./fastrpz/RCS/librpz.h,v
-retrieving revision 1.1
-diff -u --unidirectional-new-file -r1.1 ./fastrpz/librpz.h
---- ./fastrpz/librpz.h
-+++ ./fastrpz/librpz.h
+--- /dev/null
++++ unbound-1.7.0~rc1/fastrpz/librpz.h
@@ -0,0 +1,957 @@
+/*
+ * Define the interface from a DNS resolver to the Response Policy Zone
@@ -1327,12 +1318,10 @@ diff -u --unidirectional-new-file -r1.1 ./fastrpz/librpz.h
+#endif /* LIBRPZ_LIB_OPEN */
+
+#endif /* LIBRPZ_H */
+Index: unbound-1.7.0~rc1/fastrpz/rpz.c
===================================================================
-RCS file: ./fastrpz/RCS/rpz.c,v
-retrieving revision 1.1
-diff -u --unidirectional-new-file -r1.1 ./fastrpz/rpz.c
---- ./fastrpz/rpz.c
-+++ ./fastrpz/rpz.c
+--- /dev/null
++++ unbound-1.7.0~rc1/fastrpz/rpz.c
@@ -0,0 +1,1357 @@
+/*
+ * fastrpz/rpz.c - interface to the fastrpz response policy zone library
@@ -2691,12 +2680,10 @@ diff -u --unidirectional-new-file -r1.1 ./fastrpz/rpz.c
+}
+
+#endif /* ENABLE_FASTRPZ */
+Index: unbound-1.7.0~rc1/fastrpz/rpz.h
===================================================================
-RCS file: ./fastrpz/RCS/rpz.h,v
-retrieving revision 1.1
-diff -u --unidirectional-new-file -r1.1 ./fastrpz/rpz.h
---- ./fastrpz/rpz.h
-+++ ./fastrpz/rpz.h
+--- /dev/null
++++ unbound-1.7.0~rc1/fastrpz/rpz.h
@@ -0,0 +1,138 @@
+/*
+ * fastrpz/rpz.h - interface to the fastrpz response policy zone library
@@ -2836,12 +2823,10 @@ diff -u --unidirectional-new-file -r1.1 ./fastrpz/rpz.h
+
+#endif /* ENABLE_FASTRPZ */
+#endif /* UNBOUND_FASTRPZ_RPZ_H */
+Index: unbound-1.7.0~rc1/fastrpz/rpz.m4
===================================================================
-RCS file: ./fastrpz/RCS/rpz.m4,v
-retrieving revision 1.1
-diff -u --unidirectional-new-file -r1.1 ./fastrpz/rpz.m4
---- ./fastrpz/rpz.m4
-+++ ./fastrpz/rpz.m4
+--- /dev/null
++++ unbound-1.7.0~rc1/fastrpz/rpz.m4
@@ -0,0 +1,64 @@
+# fastrpz/rpz.m4
+
@@ -2907,13 +2892,11 @@ diff -u --unidirectional-new-file -r1.1 ./fastrpz/rpz.m4
+ AC_MSG_WARN([[dlopen and librpz.so needed for fastrpz]])
+ fi
+])
+Index: unbound-1.7.0~rc1/iterator/iterator.c
===================================================================
-RCS file: ./iterator/RCS/iterator.c,v
-retrieving revision 1.1
-diff -u --unidirectional-new-file -r1.1 ./iterator/iterator.c
---- ./iterator/iterator.c
-+++ ./iterator/iterator.c
-@@ -67,6 +67,9 @@
+--- unbound-1.7.0~rc1.orig/iterator/iterator.c
++++ unbound-1.7.0~rc1/iterator/iterator.c
+@@ -68,6 +68,9 @@
#include "sldns/str2wire.h"
#include "sldns/parseutil.h"
#include "sldns/sbuffer.h"
@@ -2923,7 +2906,7 @@ diff -u --unidirectional-new-file -r1.1 ./iterator/iterator.c
int
iter_init(struct module_env* env, int id)
-@@ -487,6 +490,23 @@
+@@ -511,6 +514,23 @@ handle_cname_response(struct module_qsta
if(ntohs(r->rk.type) == LDNS_RR_TYPE_CNAME &&
query_dname_compare(*mname, r->rk.dname) == 0 &&
!iter_find_rrset_in_prepend_answer(iq, r)) {
@@ -2947,7 +2930,7 @@ diff -u --unidirectional-new-file -r1.1 ./iterator/iterator.c
/* Add this relevant CNAME rrset to the prepend list.*/
if(!iter_add_prepend_answer(qstate, iq, r))
return 0;
-@@ -495,6 +515,9 @@
+@@ -519,6 +539,9 @@ handle_cname_response(struct module_qsta
/* Other rrsets in the section are ignored. */
}
@@ -2957,7 +2940,7 @@ diff -u --unidirectional-new-file -r1.1 ./iterator/iterator.c
/* add authority rrsets to authority prepend, for wildcarded CNAMEs */
for(i=msg->rep->an_numrrsets; i<msg->rep->an_numrrsets +
msg->rep->ns_numrrsets; i++) {
-@@ -996,6 +1019,7 @@
+@@ -1148,6 +1171,7 @@ processInitRequest(struct module_qstate*
uint8_t* delname;
size_t delnamelen;
struct dns_msg* msg = NULL;
@@ -2965,7 +2948,7 @@ diff -u --unidirectional-new-file -r1.1 ./iterator/iterator.c
log_query_info(VERB_DETAIL, "resolving", &qstate->qinfo);
/* check effort */
-@@ -1056,8 +1080,7 @@
+@@ -1223,8 +1247,7 @@ processInitRequest(struct module_qstate*
}
if(msg) {
/* handle positive cache response */
@@ -2975,7 +2958,7 @@ diff -u --unidirectional-new-file -r1.1 ./iterator/iterator.c
if(verbosity >= VERB_ALGO) {
log_dns_msg("msg from cache lookup", &msg->qinfo,
msg->rep);
-@@ -1065,7 +1088,22 @@
+@@ -1232,7 +1255,22 @@ processInitRequest(struct module_qstate*
(int)msg->rep->ttl,
(int)msg->rep->prefetch_ttl);
}
@@ -2998,7 +2981,7 @@ diff -u --unidirectional-new-file -r1.1 ./iterator/iterator.c
if(type == RESPONSE_TYPE_CNAME) {
uint8_t* sname = 0;
size_t slen = 0;
-@@ -2321,6 +2359,62 @@
+@@ -2552,6 +2590,62 @@ processQueryResponse(struct module_qstat
sock_list_insert(&qstate->reply_origin,
&qstate->reply->addr, qstate->reply->addrlen,
qstate->region);
@@ -3061,7 +3044,7 @@ diff -u --unidirectional-new-file -r1.1 ./iterator/iterator.c
if(iq->minimisation_state != DONOT_MINIMISE_STATE) {
if(FLAGS_GET_RCODE(iq->response->rep->flags) !=
LDNS_RCODE_NOERROR) {
-@@ -3022,12 +3116,44 @@
+@@ -3273,12 +3367,44 @@ processFinished(struct module_qstate* qs
* but only if we did recursion. The nonrecursion referral
* from cache does not need to be stored in the msg cache. */
if(!qstate->no_cache_store && qstate->query_flags&BIT_RD) {
@@ -3106,13 +3089,11 @@ diff -u --unidirectional-new-file -r1.1 ./iterator/iterator.c
qstate->return_rcode = LDNS_RCODE_NOERROR;
qstate->return_msg = iq->response;
return 0;
+Index: unbound-1.7.0~rc1/iterator/iterator.h
===================================================================
-RCS file: ./iterator/RCS/iterator.h,v
-retrieving revision 1.1
-diff -u --unidirectional-new-file -r1.1 ./iterator/iterator.h
---- ./iterator/iterator.h
-+++ ./iterator/iterator.h
-@@ -381,6 +381,16 @@
+--- unbound-1.7.0~rc1.orig/iterator/iterator.h
++++ unbound-1.7.0~rc1/iterator/iterator.h
+@@ -383,6 +383,16 @@ struct iter_qstate {
*/
int minimise_count;
@@ -3129,17 +3110,15 @@ diff -u --unidirectional-new-file -r1.1 ./iterator/iterator.h
/**
* Count number of time-outs. Used to prevent resolving failures when
* the QNAME minimisation QTYPE is blocked. */
+Index: unbound-1.7.0~rc1/services/cache/dns.c
===================================================================
-RCS file: ./services/cache/RCS/dns.c,v
-retrieving revision 1.1
-diff -u --unidirectional-new-file -r1.1 ./services/cache/dns.c
---- ./services/cache/dns.c
-+++ ./services/cache/dns.c
-@@ -838,6 +838,14 @@
- struct regional* region, uint16_t flags)
+--- unbound-1.7.0~rc1.orig/services/cache/dns.c
++++ unbound-1.7.0~rc1/services/cache/dns.c
+@@ -876,6 +876,14 @@ dns_cache_store(struct module_env* env,
+ struct regional* region, uint32_t flags)
{
struct reply_info* rep = NULL;
-+
++
+#ifdef ENABLE_FASTRPZ
+ /* Never save RPZ rewritten data. */
+ if (msgrep->security == sec_status_rpz_drop ||
@@ -3150,12 +3129,10 @@ diff -u --unidirectional-new-file -r1.1 ./services/cache/dns.c
/* alloc, malloc properly (not in region, like msg is) */
rep = reply_info_copy(msgrep, env->alloc, NULL);
if(!rep)
+Index: unbound-1.7.0~rc1/services/mesh.c
===================================================================
-RCS file: ./services/RCS/mesh.c,v
-retrieving revision 1.1
-diff -u --unidirectional-new-file -r1.1 ./services/mesh.c
---- ./services/mesh.c
-+++ ./services/mesh.c
+--- unbound-1.7.0~rc1.orig/services/mesh.c
++++ unbound-1.7.0~rc1/services/mesh.c
@@ -59,6 +59,9 @@
#include "sldns/wire2str.h"
#include "services/localzone.h"
@@ -3166,7 +3143,7 @@ diff -u --unidirectional-new-file -r1.1 ./services/mesh.c
#include "respip/respip.h"
/** subtract timers and the values do not overflow or become negative */
-@@ -1011,6 +1014,13 @@
+@@ -1050,6 +1053,13 @@ mesh_send_reply(struct mesh_state* m, in
else secure = 0;
if(!rep && rcode == LDNS_RCODE_NOERROR)
rcode = LDNS_RCODE_SERVFAIL;
@@ -3180,7 +3157,7 @@ diff -u --unidirectional-new-file -r1.1 ./services/mesh.c
/* send the reply */
/* We don't reuse the encoded answer if either the previous or current
* response has a local alias. We could compare the alias records
-@@ -1160,6 +1170,7 @@
+@@ -1199,6 +1209,7 @@ struct mesh_state* mesh_area_find(struct
key.s.is_valrec = valrec;
key.s.qinfo = *qinfo;
key.s.query_flags = qflags;
@@ -3188,7 +3165,7 @@ diff -u --unidirectional-new-file -r1.1 ./services/mesh.c
/* We are searching for a similar mesh state when we DO want to
* aggregate the state. Thus unique is set to NULL. (default when we
* desire aggregation).*/
-@@ -1206,6 +1217,10 @@
+@@ -1245,6 +1256,10 @@ int mesh_state_add_reply(struct mesh_sta
if(!r)
return 0;
r->query_reply = *rep;
@@ -3199,13 +3176,11 @@ diff -u --unidirectional-new-file -r1.1 ./services/mesh.c
r->edns = *edns;
if(edns->opt_list) {
r->edns.opt_list = edns_opt_copy_region(edns->opt_list,
+Index: unbound-1.7.0~rc1/util/config_file.c
===================================================================
-RCS file: ./util/RCS/config_file.c,v
-retrieving revision 1.1
-diff -u --unidirectional-new-file -r1.1 ./util/config_file.c
---- ./util/config_file.c
-+++ ./util/config_file.c
-@@ -1167,6 +1167,8 @@
+--- unbound-1.7.0~rc1.orig/util/config_file.c
++++ unbound-1.7.0~rc1/util/config_file.c
+@@ -1323,6 +1323,8 @@ config_delete(struct config_file* cfg)
free(cfg->dnstap_socket_path);
free(cfg->dnstap_identity);
free(cfg->dnstap_version);
@@ -3213,14 +3188,12 @@ diff -u --unidirectional-new-file -r1.1 ./util/config_file.c
+ free(cfg->rpz_cstr);
config_deldblstrlist(cfg->ratelimit_for_domain);
config_deldblstrlist(cfg->ratelimit_below_domain);
- free(cfg);
+ #ifdef USE_IPSECMOD
+Index: unbound-1.7.0~rc1/util/config_file.h
===================================================================
-RCS file: ./util/RCS/config_file.h,v
-retrieving revision 1.1
-diff -u --unidirectional-new-file -r1.1 ./util/config_file.h
---- ./util/config_file.h
-+++ ./util/config_file.h
-@@ -416,6 +416,11 @@
+--- unbound-1.7.0~rc1.orig/util/config_file.h
++++ unbound-1.7.0~rc1/util/config_file.h
+@@ -431,6 +431,11 @@ struct config_file {
/** true to disable DNSSEC lameness check in iterator */
int disable_dnssec_lame_check;
@@ -3232,13 +3205,11 @@ diff -u --unidirectional-new-file -r1.1 ./util/config_file.h
/** ratelimit for ip addresses. 0 is off, otherwise qps (unless overridden) */
int ip_ratelimit;
/** number of slabs for ip_ratelimit cache */
+Index: unbound-1.7.0~rc1/util/configlexer.lex
===================================================================
-RCS file: ./util/RCS/configlexer.lex,v
-retrieving revision 1.1
-diff -u --unidirectional-new-file -r1.1 ./util/configlexer.lex
---- ./util/configlexer.lex
-+++ ./util/configlexer.lex
-@@ -395,6 +395,10 @@
+--- unbound-1.7.0~rc1.orig/util/configlexer.lex
++++ unbound-1.7.0~rc1/util/configlexer.lex
+@@ -412,6 +412,10 @@ dnstap-log-forwarder-query-messages{COLO
YDVAR(1, VAR_DNSTAP_LOG_FORWARDER_QUERY_MESSAGES) }
dnstap-log-forwarder-response-messages{COLON} {
YDVAR(1, VAR_DNSTAP_LOG_FORWARDER_RESPONSE_MESSAGES) }
@@ -3249,13 +3220,11 @@ diff -u --unidirectional-new-file -r1.1 ./util/configlexer.lex
disable-dnssec-lame-check{COLON} { YDVAR(1, VAR_DISABLE_DNSSEC_LAME_CHECK) }
ip-ratelimit{COLON} { YDVAR(1, VAR_IP_RATELIMIT) }
ratelimit{COLON} { YDVAR(1, VAR_RATELIMIT) }
+Index: unbound-1.7.0~rc1/util/configparser.y
===================================================================
-RCS file: ./util/RCS/configparser.y,v
-retrieving revision 1.1
-diff -u --unidirectional-new-file -r1.1 ./util/configparser.y
---- ./util/configparser.y
-+++ ./util/configparser.y
-@@ -124,6 +124,7 @@
+--- unbound-1.7.0~rc1.orig/util/configparser.y
++++ unbound-1.7.0~rc1/util/configparser.y
+@@ -124,6 +124,7 @@ extern struct config_parser_state* cfg_p
%token VAR_DNSTAP_LOG_CLIENT_RESPONSE_MESSAGES
%token VAR_DNSTAP_LOG_FORWARDER_QUERY_MESSAGES
%token VAR_DNSTAP_LOG_FORWARDER_RESPONSE_MESSAGES
@@ -3263,16 +3232,16 @@ diff -u --unidirectional-new-file -r1.1 ./util/configparser.y
%token VAR_RESPONSE_IP_TAG VAR_RESPONSE_IP VAR_RESPONSE_IP_DATA
%token VAR_HARDEN_ALGO_DOWNGRADE VAR_IP_TRANSPARENT
%token VAR_DISABLE_DNSSEC_LAME_CHECK
-@@ -153,7 +154,7 @@
- toplevelvar: serverstart contents_server | stubstart contents_stub |
+@@ -158,7 +159,7 @@ extern struct config_parser_state* cfg_p
+
+ %%
+ toplevelvars: /* empty */ | toplevelvars toplevelvar ;
+-toplevelvar: serverstart contents_server | stubstart contents_stub |
++toplevelvar: serverstart contents_server | stubstart contents_stub | rpzstart contents_rpz |
forwardstart contents_forward | pythonstart contents_py |
- rcstart contents_rc | dtstart contents_dt | viewstart
-- contents_view |
-+ contents_view | rpzstart contents_rpz |
- dnscstart contents_dnsc |
- cachedbstart contents_cachedb
- ;
-@@ -2160,6 +2161,50 @@
+ rcstart contents_rc | dtstart contents_dt | viewstart contents_view |
+ dnscstart contents_dnsc | cachedbstart contents_cachedb |
+@@ -2384,6 +2385,50 @@ dt_dnstap_log_forwarder_response_message
(strcmp($2, "yes")==0);
}
;
@@ -3323,13 +3292,11 @@ diff -u --unidirectional-new-file -r1.1 ./util/configparser.y
pythonstart: VAR_PYTHON
{
OUTYY(("\nP(python:)\n"));
+Index: unbound-1.7.0~rc1/util/data/msgencode.c
===================================================================
-RCS file: ./util/data/RCS/msgencode.c,v
-retrieving revision 1.1
-diff -u --unidirectional-new-file -r1.1 ./util/data/msgencode.c
---- ./util/data/msgencode.c
-+++ ./util/data/msgencode.c
-@@ -585,6 +585,35 @@
+--- unbound-1.7.0~rc1.orig/util/data/msgencode.c
++++ unbound-1.7.0~rc1/util/data/msgencode.c
+@@ -585,6 +585,35 @@ insert_section(struct reply_info* rep, s
return RETVAL_OK;
}
@@ -3365,7 +3332,7 @@ diff -u --unidirectional-new-file -r1.1 ./util/data/msgencode.c
/** store query section in wireformat buffer, return RETVAL */
static int
insert_query(struct query_info* qinfo, struct compress_tree_node** tree,
-@@ -748,6 +777,19 @@
+@@ -750,6 +779,19 @@ reply_info_encode(struct query_info* qin
return 0;
}
sldns_buffer_write_u16_at(buffer, 10, arcount);
@@ -3385,13 +3352,11 @@ diff -u --unidirectional-new-file -r1.1 ./util/data/msgencode.c
}
sldns_buffer_flip(buffer);
return 1;
+Index: unbound-1.7.0~rc1/util/data/packed_rrset.c
===================================================================
-RCS file: ./util/data/RCS/packed_rrset.c,v
-retrieving revision 1.1
-diff -u --unidirectional-new-file -r1.1 ./util/data/packed_rrset.c
---- ./util/data/packed_rrset.c
-+++ ./util/data/packed_rrset.c
-@@ -254,6 +254,10 @@
+--- unbound-1.7.0~rc1.orig/util/data/packed_rrset.c
++++ unbound-1.7.0~rc1/util/data/packed_rrset.c
+@@ -254,6 +254,10 @@ sec_status_to_string(enum sec_status s)
case sec_status_indeterminate: return "sec_status_indeterminate";
case sec_status_insecure: return "sec_status_insecure";
case sec_status_secure: return "sec_status_secure";
@@ -3402,13 +3367,11 @@ diff -u --unidirectional-new-file -r1.1 ./util/data/packed_rrset.c
}
return "unknown_sec_status_value";
}
+Index: unbound-1.7.0~rc1/util/data/packed_rrset.h
===================================================================
-RCS file: ./util/data/RCS/packed_rrset.h,v
-retrieving revision 1.1
-diff -u --unidirectional-new-file -r1.1 ./util/data/packed_rrset.h
---- ./util/data/packed_rrset.h
-+++ ./util/data/packed_rrset.h
-@@ -189,7 +189,15 @@
+--- unbound-1.7.0~rc1.orig/util/data/packed_rrset.h
++++ unbound-1.7.0~rc1/util/data/packed_rrset.h
+@@ -189,7 +189,15 @@ enum sec_status {
sec_status_insecure,
/** SECURE means that the object (RRset or message) validated
* according to local policy. */
@@ -3425,12 +3388,10 @@ diff -u --unidirectional-new-file -r1.1 ./util/data/packed_rrset.h
};
/**
+Index: unbound-1.7.0~rc1/util/netevent.c
===================================================================
-RCS file: ./util/RCS/netevent.c,v
-retrieving revision 1.1
-diff -u --unidirectional-new-file -r1.1 ./util/netevent.c
---- ./util/netevent.c
-+++ ./util/netevent.c
+--- unbound-1.7.0~rc1.orig/util/netevent.c
++++ unbound-1.7.0~rc1/util/netevent.c
@@ -54,6 +54,9 @@
#ifdef HAVE_OPENSSL_ERR_H
#include <openssl/err.h>
@@ -3441,7 +3402,7 @@ diff -u --unidirectional-new-file -r1.1 ./util/netevent.c
/* -------- Start of local definitions -------- */
/** if CMSG_ALIGN is not defined on this platform, a workaround */
-@@ -579,6 +582,9 @@
+@@ -585,6 +588,9 @@ comm_point_udp_ancil_callback(int fd, sh
struct cmsghdr* cmsg;
#endif /* S_SPLINT_S */
@@ -3451,9 +3412,9 @@ diff -u --unidirectional-new-file -r1.1 ./util/netevent.c
rep.c = (struct comm_point*)arg;
log_assert(rep.c->type == comm_udp);
-@@ -668,6 +674,9 @@
+@@ -674,6 +680,9 @@ comm_point_udp_callback(int fd, short ev
int i;
- struct sldns_buffer *buffer;
+ struct sldns_buffer *buffer;
+#ifdef ENABLE_FASTRPZ
+ rep.rpz = NULL;
@@ -3461,17 +3422,17 @@ diff -u --unidirectional-new-file -r1.1 ./util/netevent.c
rep.c = (struct comm_point*)arg;
log_assert(rep.c->type == comm_udp);
-@@ -711,6 +720,9 @@
+@@ -717,6 +726,9 @@ comm_point_udp_callback(int fd, short ev
(void)comm_point_send_udp_msg(rep.c, buffer,
(struct sockaddr*)&rep.addr, rep.addrlen);
}
+#ifdef ENABLE_FASTRPZ
+ rpz_end(&rep);
+#endif
- if(rep.c->fd != fd) /* commpoint closed to -1 or reused for
+ if(!rep.c || rep.c->fd != fd) /* commpoint closed to -1 or reused for
another UDP port. Note rep.c cannot be reused with TCP fd. */
break;
-@@ -2145,6 +2157,9 @@
+@@ -2956,6 +2968,9 @@ comm_point_send_reply(struct comm_reply
comm_point_start_listening(repinfo->c, -1,
repinfo->c->tcp_timeout_msec);
}
@@ -3481,7 +3442,7 @@ diff -u --unidirectional-new-file -r1.1 ./util/netevent.c
}
void
-@@ -2154,6 +2169,9 @@
+@@ -2965,6 +2980,9 @@ comm_point_drop_reply(struct comm_reply*
return;
log_assert(repinfo && repinfo->c);
log_assert(repinfo->c->type != comm_tcp_accept);
@@ -3491,7 +3452,7 @@ diff -u --unidirectional-new-file -r1.1 ./util/netevent.c
if(repinfo->c->type == comm_udp)
return;
reclaim_tcp_handler(repinfo->c);
-@@ -2173,6 +2191,9 @@
+@@ -2984,6 +3002,9 @@ comm_point_start_listening(struct comm_p
{
verbose(VERB_ALGO, "comm point start listening %d",
c->fd==-1?newfd:c->fd);
@@ -3501,13 +3462,11 @@ diff -u --unidirectional-new-file -r1.1 ./util/netevent.c
if(c->type == comm_tcp_accept && !c->tcp_free) {
/* no use to start listening no free slots. */
return;
+Index: unbound-1.7.0~rc1/util/netevent.h
===================================================================
-RCS file: ./util/RCS/netevent.h,v
-retrieving revision 1.1
-diff -u --unidirectional-new-file -r1.1 ./util/netevent.h
---- ./util/netevent.h
-+++ ./util/netevent.h
-@@ -117,6 +117,10 @@
+--- unbound-1.7.0~rc1.orig/util/netevent.h
++++ unbound-1.7.0~rc1/util/netevent.h
+@@ -119,6 +119,10 @@ struct comm_reply {
/** return type 0 (none), 4(IP4), 6(IP6) */
int srctype;
/* DnsCrypt context */
@@ -3518,13 +3477,11 @@ diff -u --unidirectional-new-file -r1.1 ./util/netevent.h
#ifdef USE_DNSCRYPT
uint8_t client_nonce[crypto_box_HALF_NONCEBYTES];
uint8_t nmkey[crypto_box_BEFORENMBYTES];
+Index: unbound-1.7.0~rc1/validator/validator.c
===================================================================
-RCS file: ./validator/RCS/validator.c,v
-retrieving revision 1.1
-diff -u --unidirectional-new-file -r1.1 ./validator/validator.c
---- ./validator/validator.c
-+++ ./validator/validator.c
-@@ -2552,6 +2552,12 @@
+--- unbound-1.7.0~rc1.orig/validator/validator.c
++++ unbound-1.7.0~rc1/validator/validator.c
+@@ -2688,6 +2688,12 @@ ds_response_to_ke(struct module_qstate*
default:
/* NSEC proof did not work, try next */
break;
@@ -3537,7 +3494,7 @@ diff -u --unidirectional-new-file -r1.1 ./validator/validator.c
}
sec = nsec3_prove_nods(qstate->env, ve,
-@@ -2584,6 +2590,12 @@
+@@ -2721,6 +2727,12 @@ ds_response_to_ke(struct module_qstate*
default:
/* NSEC3 proof did not work */
break;
@@ -3550,3 +3507,4 @@ diff -u --unidirectional-new-file -r1.1 ./validator/validator.c
}
/* Apparently, no available NSEC/NSEC3 proved NODATA, so
+
diff --git a/contrib/libunbound.so.conf b/contrib/libunbound.so.conf
new file mode 100644
index 000000000000..3b78fca7f378
--- /dev/null
+++ b/contrib/libunbound.so.conf
@@ -0,0 +1,41 @@
+# See ltrace.conf(5) for description of syntax of this file.
+typedef ub_type = enum(TYPE_A=1,TYPE_NS=2,TYPE_SOA=6,TYPE_MX=15,TYPE_TXT=16,TYPE_AAAA=28,TYPE_DS=43,TYPE_DNSKEY=48,TYPE_TLSA=52,TYPE_ANY=255);
+typedef ub_class = enum(CLASS_IN=1,CLASS_CH=3,CLASS_NONE=254,CLASS_ANY=255);
+typedef ub_rcode = enum(RCODE_NOERROR,RCODE_FORMERR,RCODE_SERVFAIL,RCODE_NXDOMAIN,RCODE_NOTIMPL,RCODE_REFUSED,RCODE_YXDOMAIN,RCODE_YXRRSET,RCODE_NXRRSET,RCODE_NOTAUTH,RCODE_NOTZONE);
+typedef ub_havedata = enum(no_data, have_data);
+typedef ub_nxdomain = enum(name_exists, nxdomain);
+typedef ub_secure = enum(not_secure, secure);
+typedef ub_bogus = enum(not_bogus, bogus);
+typedef ub_result = struct(string, ub_type, ub_class, array(void*,zero)*, array(int,zero)*, string, ub_rcode, void*, int, ub_havedata, ub_nxdomain, ub_secure, ub_bogus, string, int);
+typedef ub_ctx = void;
+ub_ctx* ub_ctx_create(void);
+void ub_ctx_delete(ub_ctx*);
+int ub_ctx_set_option(ub_ctx*, string, string);
+int ub_ctx_get_option(ub_ctx*, string, +string*);
+int ub_ctx_config(ub_ctx*, string);
+int ub_ctx_set_fwd(ub_ctx*, string);
+int ub_ctx_set_stub(ub_ctx*, string, string, bool(int));
+int ub_ctx_resolvconf(ub_ctx*, string);
+int ub_ctx_hosts(ub_ctx*, string);
+int ub_ctx_add_ta(ub_ctx*, string);
+int ub_ctx_add_ta_file(ub_ctx*, string);
+int ub_ctx_add_ta_autr(ub_ctx*, string);
+int ub_ctx_trustedkeys(ub_ctx*, string);
+int ub_ctx_debugout(ub_ctx*, void*);
+int ub_ctx_debuglevel(ub_ctx*, int);
+int ub_ctx_async(ub_ctx*, bool(int));
+int ub_poll(ub_ctx*);
+int ub_wait(ub_ctx*);
+int ub_fd(ub_ctx*);
+int ub_process(ub_ctx*);
+int ub_resolve(ub_ctx*, string, ub_type, ub_class, +ub_result**);
+int ub_resolve_async(ub_ctx*, string, ub_type, ub_class, void*, void*, +int*);
+int ub_cancel(ub_ctx*, int);
+void ub_resolve_free(ub_result*);
+string ub_strerror(int);
+int ub_ctx_print_local_zones(ub_ctx*);
+int ub_ctx_zone_add(ub_ctx*, string, string);
+int ub_ctx_zone_remove(ub_ctx*, string);
+int ub_ctx_data_add(ub_ctx*, string);
+int ub_ctx_data_remove(ub_ctx*, string);
+string ub_version(void);
diff --git a/daemon/cachedump.c b/daemon/cachedump.c
index 8992e6cb8f3d..81061870b581 100644
--- a/daemon/cachedump.c
+++ b/daemon/cachedump.c
@@ -79,6 +79,7 @@ dump_rrset(SSL* ssl, struct ub_packed_rrset_key* k,
size_t i;
/* rd lock held by caller */
if(!k || !d) return 1;
+ if(k->id == 0) return 1; /* deleted */
if(d->ttl < now) return 1; /* expired */
/* meta line */
diff --git a/daemon/daemon.c b/daemon/daemon.c
index 7411fabe7573..f68bd981b01b 100644
--- a/daemon/daemon.c
+++ b/daemon/daemon.c
@@ -82,6 +82,7 @@
#include "services/localzone.h"
#include "services/view.h"
#include "services/modstack.h"
+#include "services/authzone.h"
#include "util/module.h"
#include "util/random.h"
#include "util/tube.h"
@@ -281,6 +282,13 @@ daemon_init(void)
if(gettimeofday(&daemon->time_boot, NULL) < 0)
log_err("gettimeofday: %s", strerror(errno));
daemon->time_last_stat = daemon->time_boot;
+ if((daemon->env->auth_zones = auth_zones_create()) == 0) {
+ acl_list_delete(daemon->acl);
+ edns_known_options_delete(daemon->env);
+ free(daemon->env);
+ free(daemon);
+ return NULL;
+ }
return daemon;
}
@@ -603,6 +611,10 @@ daemon_fork(struct daemon* daemon)
fatal_exit("Could not set up per-view response IP sets");
daemon->use_response_ip = !respip_set_is_empty(daemon->respip_set) ||
have_view_respip_cfg;
+
+ /* read auth zonefiles */
+ if(!auth_zones_apply_cfg(daemon->env->auth_zones, daemon->cfg, 1))
+ fatal_exit("auth_zones could not be setup");
/* setup modules */
daemon_setup_modules(daemon);
@@ -683,6 +695,8 @@ daemon_cleanup(struct daemon* daemon)
daemon->respip_set = NULL;
views_delete(daemon->views);
daemon->views = NULL;
+ if(daemon->env->auth_zones)
+ auth_zones_cleanup(daemon->env->auth_zones);
/* key cache is cleared by module desetup during next daemon_fork() */
daemon_remote_clear(daemon->rc);
for(i=0; i<daemon->num; i++)
@@ -716,6 +730,7 @@ daemon_delete(struct daemon* daemon)
rrset_cache_delete(daemon->env->rrset_cache);
infra_delete(daemon->env->infra_cache);
edns_known_options_delete(daemon->env);
+ auth_zones_delete(daemon->env->auth_zones);
}
ub_randfree(daemon->rand);
alloc_clear(&daemon->superalloc);
@@ -763,6 +778,9 @@ daemon_delete(struct daemon* daemon)
# if defined(HAVE_SSL) && defined(OPENSSL_THREADS) && !defined(THREADS_DISABLED)
ub_openssl_lock_delete();
# endif
+#ifndef HAVE_ARC4RANDOM
+ _ARC4_LOCK_DESTROY();
+#endif
#elif defined(HAVE_NSS)
NSS_Shutdown();
#endif /* HAVE_SSL or HAVE_NSS */
diff --git a/daemon/unbound.c b/daemon/unbound.c
index 432aa912e681..e4caf004819e 100644
--- a/daemon/unbound.c
+++ b/daemon/unbound.c
@@ -421,17 +421,6 @@ perform_setup(struct daemon* daemon, struct config_file* cfg, int debug_mode,
w_config_adjust_directory(cfg);
#endif
- /* init syslog (as root) if needed, before daemonize, otherwise
- * a fork error could not be printed since daemonize closed stderr.*/
- if(cfg->use_syslog) {
- log_init(cfg->logfile, cfg->use_syslog, cfg->chrootdir);
- }
- /* if using a logfile, we cannot open it because the logfile would
- * be created with the wrong permissions, we cannot chown it because
- * we cannot chown system logfiles, so we do not open at all.
- * So, using a logfile, the user does not see errors unless -d is
- * given to unbound on the commandline. */
-
/* read ssl keys while superuser and outside chroot */
#ifdef HAVE_SSL
if(!(daemon->rc = daemon_remote_create(cfg)))
@@ -441,10 +430,22 @@ perform_setup(struct daemon* daemon, struct config_file* cfg, int debug_mode,
cfg->ssl_service_key, cfg->ssl_service_pem, NULL)))
fatal_exit("could not set up listen SSL_CTX");
}
- if(!(daemon->connect_sslctx = connect_sslctx_create(NULL, NULL, NULL)))
+ if(!(daemon->connect_sslctx = connect_sslctx_create(NULL, NULL,
+ cfg->tls_cert_bundle)))
fatal_exit("could not set up connect SSL_CTX");
#endif
+ /* init syslog (as root) if needed, before daemonize, otherwise
+ * a fork error could not be printed since daemonize closed stderr.*/
+ if(cfg->use_syslog) {
+ log_init(cfg->logfile, cfg->use_syslog, cfg->chrootdir);
+ }
+ /* if using a logfile, we cannot open it because the logfile would
+ * be created with the wrong permissions, we cannot chown it because
+ * we cannot chown system logfiles, so we do not open at all.
+ * So, using a logfile, the user does not see errors unless -d is
+ * given to unbound on the commandline. */
+
#ifdef HAVE_KILL
/* true if pidfile is inside chrootdir, or nochroot */
pidinchroot = need_pidfile && (!(cfg->chrootdir && cfg->chrootdir[0]) ||
@@ -744,5 +745,10 @@ main(int argc, char* argv[])
run_daemon(cfgfile, cmdline_verbose, debug_mode, log_ident_default, need_pidfile);
log_init(NULL, 0, NULL); /* close logfile */
+#ifndef unbound_testbound
+ if(log_get_lock()) {
+ lock_quick_destroy((lock_quick_type*)log_get_lock());
+ }
+#endif
return 0;
}
diff --git a/daemon/worker.c b/daemon/worker.c
index ac7053abddf3..389a1de530ec 100644
--- a/daemon/worker.c
+++ b/daemon/worker.c
@@ -58,6 +58,7 @@
#include "services/cache/rrset.h"
#include "services/cache/infra.h"
#include "services/cache/dns.h"
+#include "services/authzone.h"
#include "services/mesh.h"
#include "services/localzone.h"
#include "util/data/msgparse.h"
@@ -1046,7 +1047,7 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
strcasecmp(buf,
worker->daemon->dnscenv->provider_name) == 0)) {
verbose(VERB_ALGO,
- "dnscrypt: not TXT %s. Receive: %s %s",
+ "dnscrypt: not TXT \"%s\". Received: %s \"%s\"",
worker->daemon->dnscenv->provider_name,
sldns_rr_descript(qinfo.qtype)->_name,
buf);
@@ -1251,6 +1252,22 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
server_stats_insrcode(&worker->stats, c->buffer);
goto send_reply;
}
+ if(worker->env.auth_zones &&
+ auth_zones_answer(worker->env.auth_zones, &worker->env,
+ &qinfo, &edns, c->buffer, worker->scratchpad)) {
+ regional_free_all(worker->scratchpad);
+ if(sldns_buffer_limit(c->buffer) == 0) {
+ comm_point_drop_reply(repinfo);
+ return 0;
+ }
+ /* set RA for everyone that can have recursion (based on
+ * access control list) */
+ if(LDNS_RD_WIRE(sldns_buffer_begin(c->buffer)) &&
+ acl != acl_deny_non_local && acl != acl_refuse_non_local)
+ LDNS_RA_SET(sldns_buffer_begin(c->buffer));
+ server_stats_insrcode(&worker->stats, c->buffer);
+ goto send_reply;
+ }
/* We've looked in our local zones. If the answer isn't there, we
* might need to bail out based on ACLs now. */
@@ -1266,13 +1283,9 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
* ACLs allow the snooping. */
if(!(LDNS_RD_WIRE(sldns_buffer_begin(c->buffer))) &&
acl != acl_allow_snoop ) {
- sldns_buffer_set_limit(c->buffer, LDNS_HEADER_SIZE);
- sldns_buffer_write_at(c->buffer, 4,
- (uint8_t*)"\0\0\0\0\0\0\0\0", 8);
- LDNS_QR_SET(sldns_buffer_begin(c->buffer));
- LDNS_RCODE_SET(sldns_buffer_begin(c->buffer),
- LDNS_RCODE_REFUSED);
- sldns_buffer_flip(c->buffer);
+ error_encode(c->buffer, LDNS_RCODE_REFUSED, &qinfo,
+ *(uint16_t*)(void *)sldns_buffer_begin(c->buffer),
+ sldns_buffer_read_u16_at(c->buffer, 2), NULL);
regional_free_all(worker->scratchpad);
server_stats_insrcode(&worker->stats, c->buffer);
log_addr(VERB_ALGO, "refused nonrec (cache snoop) query from",
@@ -1326,11 +1339,11 @@ lookup_cache:
h = query_info_hash(lookup_qinfo, sldns_buffer_read_u16_at(c->buffer, 2));
if((e=slabhash_lookup(worker->env.msg_cache, h, lookup_qinfo, 0))) {
/* answer from cache - we have acquired a readlock on it */
- if(answer_from_cache(worker, &qinfo,
+ if(answer_from_cache(worker, &qinfo,
cinfo, &need_drop, &alias_rrset, &partial_rep,
- (struct reply_info*)e->data,
- *(uint16_t*)(void *)sldns_buffer_begin(c->buffer),
- sldns_buffer_read_u16_at(c->buffer, 2), repinfo,
+ (struct reply_info*)e->data,
+ *(uint16_t*)(void *)sldns_buffer_begin(c->buffer),
+ sldns_buffer_read_u16_at(c->buffer, 2), repinfo,
&edns)) {
/* prefetch it if the prefetch TTL expired.
* Note that if there is more than one pass
@@ -1672,8 +1685,10 @@ worker_init(struct worker* worker, struct config_file *cfg,
if(worker->thread_num == 0)
log_set_time(worker->env.now);
worker->env.worker = worker;
+ worker->env.worker_base = worker->base;
worker->env.send_query = &worker_send_query;
worker->env.alloc = &worker->alloc;
+ worker->env.outnet = worker->back;
worker->env.rnd = worker->rndstate;
/* If case prefetch is triggered, the corresponding mesh will clear
* the scratchpad for the module env in the middle of request handling.
@@ -1723,6 +1738,14 @@ worker_init(struct worker* worker, struct config_file *cfg,
comm_timer_set(worker->env.probe_timer, &tv);
}
}
+ /* zone transfer tasks, setup once per process, if any */
+ if(worker->env.auth_zones
+#ifndef THREADS_DISABLED
+ && worker->thread_num == 0
+#endif
+ ) {
+ auth_xfer_pickup_initial(worker->env.auth_zones, &worker->env);
+ }
if(!worker->env.mesh || !worker->env.scratch_buffer) {
worker_delete(worker);
return 0;
diff --git a/dnscrypt/dnscrypt.c b/dnscrypt/dnscrypt.c
index a0db12077093..3545d3d9b43f 100644
--- a/dnscrypt/dnscrypt.c
+++ b/dnscrypt/dnscrypt.c
@@ -5,6 +5,7 @@
#ifdef HAVE_TIME_H
#include <time.h>
#endif
+#include <inttypes.h>
#include <sys/time.h>
#include <sys/types.h>
#include "sldns/sbuffer.h"
@@ -588,18 +589,26 @@ dnsc_chroot_path(struct config_file *cfg, char *path)
static int
dnsc_parse_certs(struct dnsc_env *env, struct config_file *cfg)
{
- struct config_strlist *head;
+ struct config_strlist *head, *head2;
size_t signed_cert_id;
+ size_t rotated_cert_id;
char *nm;
env->signed_certs_count = 0U;
+ env->rotated_certs_count = 0U;
for (head = cfg->dnscrypt_provider_cert; head; head = head->next) {
env->signed_certs_count++;
}
+ for (head = cfg->dnscrypt_provider_cert_rotated; head; head = head->next) {
+ env->rotated_certs_count++;
+ }
env->signed_certs = sodium_allocarray(env->signed_certs_count,
sizeof *env->signed_certs);
+ env->rotated_certs = sodium_allocarray(env->rotated_certs_count,
+ sizeof env->signed_certs);
signed_cert_id = 0U;
+ rotated_cert_id = 0U;
for(head = cfg->dnscrypt_provider_cert; head; head = head->next, signed_cert_id++) {
nm = dnsc_chroot_path(cfg, head->str);
if(dnsc_read_from_file(
@@ -608,6 +617,14 @@ dnsc_parse_certs(struct dnsc_env *env, struct config_file *cfg)
sizeof(struct SignedCert)) != 0) {
fatal_exit("dnsc_parse_certs: failed to load %s: %s", head->str, strerror(errno));
}
+ for(head2 = cfg->dnscrypt_provider_cert_rotated; head2; head2 = head2->next) {
+ if(strcmp(head->str, head2->str) == 0) {
+ *(env->rotated_certs + rotated_cert_id) = env->signed_certs + signed_cert_id;
+ rotated_cert_id++;
+ verbose(VERB_OPS, "Cert %s is rotated and will not be distributed via DNS", head->str);
+ break;
+ }
+ }
verbose(VERB_OPS, "Loaded cert %s", head->str);
}
return signed_cert_id;
@@ -692,27 +709,54 @@ dnsc_load_local_data(struct dnsc_env* dnscenv, struct config_file *cfg)
// 2.dnscrypt-cert.example.com 86400 IN TXT "DNSC......"
for(i=0; i<dnscenv->signed_certs_count; i++) {
const char *ttl_class_type = " 86400 IN TXT \"";
+ int rotated_cert = 0;
+ uint32_t serial;
+ uint16_t rrlen;
+ char* rr;
struct SignedCert *cert = dnscenv->signed_certs + i;
- uint16_t rrlen = strlen(dnscenv->provider_name) +
+ // Check if the certificate is being rotated and should not be published
+ for(j=0; j<dnscenv->rotated_certs_count; j++){
+ if(cert == dnscenv->rotated_certs[j]) {
+ rotated_cert = 1;
+ break;
+ }
+ }
+ memcpy(&serial, cert->serial, sizeof serial);
+ serial = htonl(serial);
+ if(rotated_cert) {
+ verbose(VERB_OPS,
+ "DNSCrypt: not adding cert with serial #%"
+ PRIu32
+ " to local-data as it is rotated",
+ serial
+ );
+ continue;
+ }
+ rrlen = strlen(dnscenv->provider_name) +
strlen(ttl_class_type) +
4 * sizeof(struct SignedCert) + // worst case scenario
1 + // trailing double quote
1;
- char *rr = malloc(rrlen);
+ rr = malloc(rrlen);
if(!rr) {
log_err("Could not allocate memory");
return -2;
}
snprintf(rr, rrlen - 1, "%s 86400 IN TXT \"", dnscenv->provider_name);
for(j=0; j<sizeof(struct SignedCert); j++) {
- int c = (int)*((const uint8_t *) cert + j);
+ int c = (int)*((const uint8_t *) cert + j);
if (isprint(c) && c != '"' && c != '\\') {
snprintf(rr + strlen(rr), rrlen - 1 - strlen(rr), "%c", c);
} else {
snprintf(rr + strlen(rr), rrlen - 1 - strlen(rr), "\\%03d", c);
}
}
- verbose(VERB_OPS, "DNSCrypt: adding local data to config: %s", rr);
+ verbose(VERB_OPS,
+ "DNSCrypt: adding cert with serial #%"
+ PRIu32
+ " to local-data to config: %s",
+ serial, rr
+ );
snprintf(rr + strlen(rr), rrlen - 1 - strlen(rr), "\"");
cfg_strlist_insert(&cfg->local_data, strdup(rr));
free(rr);
@@ -826,6 +870,16 @@ dnsc_parse_keys(struct dnsc_env *env, struct config_file *cfg)
return cert_id;
}
+static void
+sodium_misuse_handler(void)
+{
+ fatal_exit(
+ "dnscrypt: libsodium could not be initialized, this typically"
+ " happens when no good source of entropy is found. If you run"
+ " unbound in a chroot, make sure /dev/random is available. See"
+ " https://www.unbound.net/documentation/unbound.conf.html");
+}
+
/**
* #########################################################
@@ -889,6 +943,9 @@ struct dnsc_env *
dnsc_create(void)
{
struct dnsc_env *env;
+#ifdef SODIUM_MISUSE_HANDLER
+ sodium_set_misuse_handler(sodium_misuse_handler);
+#endif
if (sodium_init() == -1) {
fatal_exit("dnsc_create: could not initialize libsodium.");
}
@@ -923,6 +980,7 @@ dnsc_apply_cfg(struct dnsc_env *env, struct config_file *cfg)
if(dnsc_load_local_data(env, cfg) <= 0) {
fatal_exit("dnsc_apply_cfg: could not load local data");
}
+ lock_basic_lock(&env->shared_secrets_cache_lock);
env->shared_secrets_cache = slabhash_create(
cfg->dnscrypt_shared_secret_cache_slabs,
HASH_DEFAULT_STARTARRAY,
@@ -933,9 +991,11 @@ dnsc_apply_cfg(struct dnsc_env *env, struct config_file *cfg)
dnsc_shared_secrets_deldatafunc,
NULL
);
+ lock_basic_unlock(&env->shared_secrets_cache_lock);
if(!env->shared_secrets_cache){
fatal_exit("dnsc_apply_cfg: could not create shared secrets cache.");
}
+ lock_basic_lock(&env->nonces_cache_lock);
env->nonces_cache = slabhash_create(
cfg->dnscrypt_nonce_cache_slabs,
HASH_DEFAULT_STARTARRAY,
@@ -946,6 +1006,7 @@ dnsc_apply_cfg(struct dnsc_env *env, struct config_file *cfg)
dnsc_nonces_deldatafunc,
NULL
);
+ lock_basic_unlock(&env->nonces_cache_lock);
return 0;
}
@@ -957,12 +1018,13 @@ dnsc_delete(struct dnsc_env *env)
}
verbose(VERB_OPS, "DNSCrypt: Freeing environment.");
sodium_free(env->signed_certs);
+ sodium_free(env->rotated_certs);
sodium_free(env->certs);
sodium_free(env->keypairs);
- slabhash_delete(env->shared_secrets_cache);
- slabhash_delete(env->nonces_cache);
lock_basic_destroy(&env->shared_secrets_cache_lock);
lock_basic_destroy(&env->nonces_cache_lock);
+ slabhash_delete(env->shared_secrets_cache);
+ slabhash_delete(env->nonces_cache);
free(env);
}
diff --git a/dnscrypt/dnscrypt.h b/dnscrypt/dnscrypt.h
index 7dec2c488cf3..666f54e62aa4 100644
--- a/dnscrypt/dnscrypt.h
+++ b/dnscrypt/dnscrypt.h
@@ -54,8 +54,10 @@ typedef struct cert_ {
struct dnsc_env {
struct SignedCert *signed_certs;
+ struct SignedCert **rotated_certs;
dnsccert *certs;
size_t signed_certs_count;
+ size_t rotated_certs_count;
uint8_t provider_publickey[crypto_sign_ed25519_PUBLICKEYBYTES];
uint8_t provider_secretkey[crypto_sign_ed25519_SECRETKEYBYTES];
KeyPair *keypairs;
diff --git a/dnscrypt/dnscrypt.m4 b/dnscrypt/dnscrypt.m4
index 7193519fcf03..591bd1375581 100644
--- a/dnscrypt/dnscrypt.m4
+++ b/dnscrypt/dnscrypt.m4
@@ -28,6 +28,14 @@ AC_DEFUN([dnsc_DNSCRYPT],
[
AC_SUBST([ENABLE_DNSCRYPT_XCHACHA20], [0])
])
+ AC_SEARCH_LIBS([sodium_set_misuse_handler], [sodium],
+ [
+ AC_DEFINE(
+ [SODIUM_MISUSE_HANDLER], [1],
+ [Define to 1 if libsodium supports sodium_set_misuse_handler])
+ ],
+ [
+ ])
$1
else
AC_SUBST([ENABLE_DNSCRYPT_XCHACHA20], [0])
diff --git a/dnstap/dnstap.proto b/dnstap/dnstap.proto
index 32871f409cfc..88bfb4e94129 100644
--- a/dnstap/dnstap.proto
+++ b/dnstap/dnstap.proto
@@ -13,6 +13,7 @@
// with this file. If not, see:
//
// <http://creativecommons.org/publicdomain/zero/1.0/>.
+syntax = "proto2";
package dnstap;
diff --git a/doc/Changelog b/doc/Changelog
index 5c6be3ada8b7..f29935375ba7 100644
--- a/doc/Changelog
+++ b/doc/Changelog
@@ -1,9 +1,244 @@
-19 January 2018: Wouter
+12 March 2018: Wouter
+ - Added documentation for aggressive-nsec: yes.
+ - tag 1.7.0rc3.
+
+9 March 2018: Wouter
+ - Fix #3598: Fix swig build issue on rhel6 based system.
+ configure --disable-swig-version-check stops the swig version check.
+
+8 March 2018: Wouter
+ - tag 1.7.0rc2.
+
+7 March 2018: Wouter
+ - Fixed contrib/fastrpz.patch, even though this already applied
+ cleanly for me, now also for others.
+ - patch to log creates keytag queries, from A. Schulze.
+ - patch suggested by Debian lintian: allow to -> allow one to, from
+ A. Schulze.
+ - Attempt to remove warning about trailing whitespace.
+
+6 March 2018: Wouter
+ - Reverted fix for #3512, this may not be the best way forward;
+ although it could be changed at a later time, to stay similar to
+ other implementations.
+ - svn trunk contains 1.7.0, this is the number for the next release.
+ - Fix for windows compile.
+ - tag 1.7.0rc1.
+
+5 March 2018: Wouter
+ - Fix to check define of DSA for when openssl is without deprecated.
+ - iana port update.
+ - Fix #3582: Squelch address already in use log when reuseaddr option
+ causes same port to be used twice for tcp connections.
+
+27 February 2018: Wouter
+ - Fixup contrib/fastrpz.patch so that it applies.
+ - Fix compile without threads, and remove unused variable.
+ - Fix compile with staticexe and python module.
+ - Fix nettle compile.
+
+22 February 2018: Ralph
+ - Save wildcard RRset from answer with original owner for use in
+ aggressive NSEC.
+
+21 February 2018: Wouter
+ - Fix #3512: unbound incorrectly reports SERVFAIL for CAA query
+ when there is a CNAME loop.
+ - Fix validation for CNAME loops. When it detects a cname loop,
+ by finding the cname, cname in the existing list, it returns
+ the partial result with the validation result up to then.
+ - more robust cachedump rrset routine.
+
+19 February 2018: Wouter
+ - Fix #3505: Documentation for default local zones references
+ wrong RFC.
+ - Fix #3494: local-zone noview can be used to break out of the view
+ to the global local zone contents, for queries for that zone.
+ - Fix for more maintainable code in localzone.
+
+16 February 2018: Wouter
+ - Fixes for clang static analyzer, the missing ; in
+ edns-subnet/addrtree.c after the assert made clang analyzer
+ produce a failure to analyze it.
+
+13 February 2018: Ralph
+ - Aggressive NSEC tests
+
+13 February 2018: Wouter
+ - tls-cert-bundle option in unbound.conf enables TLS authentication.
+ - iana port update.
+
+12 February 2018: Wouter
+ - Unit test for auth zone https url download.
+
+12 February 2018: Ralph
+ - Added tests with wildcard expanded NSEC records (CVE-2017-15105 test)
+ - Processed aggressive NSEC code review remarks Wouter
+
+8 February 2018: Ralph
+ - Aggressive use of NSEC implementation. Use cached NSEC records to
+ generate NXDOMAIN, NODATA and positive wildcard answers.
+
+8 February 2018: Wouter
+ - iana port update.
+ - auth zone url config.
+
+5 February 2018: Wouter
+ - Fix #3451: dnstap not building when you have a separate build dir.
+ And removed protoc warning, set dnstap.proto syntax to proto2.
+ - auth-zone provides a way to configure RFC7706 from unbound.conf,
+ eg. with auth-zone: name: "." for-downstream: no for-upstream: yes
+ fallback-enabled: yes and masters or a zonefile with data.
+
+2 February 2018: Wouter
+ - Fix unfreed locks in log and arc4random at exit of unbound.
+ - unit test with valgrind
+ - Fix lock race condition in dns cache dname synthesis.
+ - lock subnet new item before insertion to please checklocks,
+ no modification of critical regions outside of lock region.
+
+1 February 2018: Wouter
+ - fix unaligned structure making a false positive in checklock
+ unitialised memory.
+
+29 January 2018: Ralph
+ - Use NSEC with longest ce to prove wildcard absence.
+ - Only use *.ce to prove wildcard absence, no longer names.
+
+25 January 2018: Wouter
+ - ltrace.conf file for libunbound in contrib.
+
+23 January 2018: Wouter
+ - Fix that unbound-checkconf -f flag works with auto-trust-anchor-file
+ for startup scripts to get the full pathname(s) of anchor file(s).
+ - Print fatal errors about remote control setup before log init,
+ so that it is printed to console.
+
+22 January 2018: Wouter
+ - Accept tls-upstream in unbound.conf, the ssl-upstream keyword is
+ also recognized and means the same. Also for tls-port,
+ tls-service-key, tls-service-pem, stub-tls-upstream and
+ forward-tls-upstream.
+ - Fix #3397: Fix that cachedb could return a partial CNAME chain.
+ - Fix #3397: Fix that when the cache contains an unsigned DNAME in
+ the middle of a cname chain, a result without the DNAME could
+ be returned.
+
+19 January 2018: Wouter
+ - tag 1.6.8 for release with CVE fix.
+ - trunk has 1.6.9 with fix and previous commits.
- patch for CVE-2017-15105: vulnerability in the processing of
wildcard synthesized NSEC records.
+ - iana port update.
+ - make depend: code dependencies updated in Makefile.
+
+4 January 2018: Ralph
+ - Copy query and correctly set flags on REFUSED answers when cache
+ snooping is not allowed.
+
+3 January 2018: Ralph
+ - Fix queries being leaked above stub when refetching glue.
+
+2 January 2017: Wouter
+ - Fix that DS queries with referral replies are answered straight
+ away, without a repeat query picking the DS from cache.
+ The correct reply should have been an answer, the reply is fixed
+ by the scrubber to have the answer in the answer section.
+ - Remove clang optimizer disable,
+ Fix that expiration date checks don't fail with clang -O2.
+
+15 December 2017: Wouter
+ - Fix timestamp failure because of clang optimizer failure, by
+ disabling -O2 when the compiler --version is clang.
+ - iana port update.
+ - Also disable -flto for clang, to make incep-expi signature check
+ work.
+
+12 December 2017: Ralph
+ - Fix qname-minimisation documentation (A QTYPE, not NS)
+
+12 December 2017: Wouter
+ - authzone work, transfer connect.
+
+7 December 2017: Ralph
+ - Check whether --with-libunbound-only is set when using --with-nettle
+ or --with-nss.
+
+4 December 2017: Wouter
+ - Fix link failure on OmniOS.
+
+1 December 2017: Wouter
+ - auth zone work.
+
+30 November 2017: Wouter
+ - Fix #3299 - forward CNAME daisy chain is not working
+
+14 November 2017: Wouter
+ - Fix #2882: Unbound behaviour changes (wrong) when domain-insecure is
+ set for stub zone. It no longer searches for DNSSEC information.
+ - auth xfer work on probe timer and lookup.
+
+13 November 2017: Wouter
+ - Fix #2801: Install libunbound.pc.
+ - Fix qname minimisation to send AAAA queries at zonecut like type A.
+ - reverted AAAA change.
+
+7 November 2017: Wouter
+ - Fix #2492: Documentation libunbound.
+
+3 November 2017: Wouter
+ - Fix #2362: TLS1.3/openssl-1.1.1 not working.
+ - Fix #2034 - Autoconf and -flto.
+ - Fix #2141 - for libsodium detect lack of entropy in chroot, print
+ a message and exit.
+
+2 November 2017: Wouter
+ - Fix #1913: ub_ctx_config is under circumstances thread-safe.
+ - make ip-transparent option work on OpenBSD.
+
+31 October 2017: Wouter
+ - Document that errno is left informative on libunbound config read
+ fail.
+ - lexer output.
+ - iana port update.
+
+25 October 2017: Ralph
+ - Fixed libunbound manual typo.
+ - Fix #1949: [dnscrypt] make provider name mismatch more obvious.
+ - Fix #2031: Double included headers
+
+24 October 2017: Ralph
+ - Update B root ipv4 address.
+
+19 October 2017: Wouter
+ - authzone work, probe timer setup.
+
+18 October 2017: Wouter
+ - lint for recent authzone commit.
+
+17 October 2017: Wouter
+ - Fix #1749: With harden-referral-path: performance drops, due to
+ circular dependency in NS and DS lookups.
+ - [dnscrypt] prevent dnscrypt-secret-key, dnscrypt-provider-cert
+ duplicates
+ - [dnscrypt] introduce dnscrypt-provider-cert-rotated option,
+ from Manu Bretelle.
+ This option allows handling multiple cert/key pairs while only
+ distributing some of them.
+ In order to reliably match a client magic with a given key without
+ strong assumption as to how those were generated, we need both key and
+ cert. Likewise, in order to know which ES version should be used.
+ On the other hand, when rotating a cert, it can be desirable to only
+ serve the new cert but still be able to handle clients that are still
+ using the old certs's public key.
+ The `dnscrypt-provider-cert-rotated` allow to instruct unbound to not
+ publish the cert as part of the DNS's provider_name's TXT answer.
+ - Better documentation for cache-max-negative-ttl.
+ - Work on local root zone code.
10 October 2017: Wouter
- tag 1.6.7
+ - trunk has version 1.6.8.
6 October 2017: Wouter
- Fix spelling in unbound-control man page.
diff --git a/doc/README b/doc/README
index d3bea2e0bab2..58cd56fa8095 100644
--- a/doc/README
+++ b/doc/README
@@ -1,4 +1,4 @@
-README for Unbound 1.6.8
+README for Unbound 1.7.0
Copyright 2007 NLnet Labs
http://unbound.net
diff --git a/doc/example.conf.in b/doc/example.conf.in
index b18513600700..73ed7fde0e5a 100644
--- a/doc/example.conf.in
+++ b/doc/example.conf.in
@@ -1,7 +1,7 @@
#
# Example configuration file.
#
-# See unbound.conf(5) man page, version 1.6.8.
+# See unbound.conf(5) man page, version 1.7.0.
#
# this is a comment.
@@ -371,7 +371,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 NS when possible.
+ # to A when possible.
# qname-minimisation: no
# QNAME minimisation in strict mode. Do not fall-back to sending full
@@ -380,6 +380,10 @@ server:
# This option only has effect when qname-minimisation is enabled.
# qname-minimisation-strict: no
+ # Aggressive NSEC uses the DNSSEC NSEC chain to synthesize NXDOMAIN
+ # and other denials, using information from previous NXDOMAINs answers.
+ # aggressive-nsec: no
+
# Use 0x20-encoded random bits in the query to foil spoof attempts.
# This feature is an experimental implementation of draft dns-0x20.
# use-caps-for-id: no
@@ -627,6 +631,7 @@ server:
# 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.
+ # o noview breaks out of that view towards global local-zones.
#
# defaults are localhost address, reverse for 127.0.0.1 and ::1
# and nxdomain for AS112 zones. If you configure one of these zones
@@ -662,13 +667,16 @@ server:
# service clients over SSL (on the TCP sockets), with plain DNS inside
# the SSL stream. Give the certificate to use and private key.
# default is "" (disabled). requires restart to take effect.
- # ssl-service-key: "path/to/privatekeyfile.key"
- # ssl-service-pem: "path/to/publiccertfile.pem"
- # ssl-port: 853
+ # 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).
# Default is no. Can be turned on and off with unbound-control.
- # ssl-upstream: no
+ # tls-upstream: no
+
+ # Certificates used to authenticate connections made upstream.
+ # tls-cert-bundle: ""
# DNS64 prefix. Must be specified when DNS64 is use.
# Enable dns64 in module-config. Used to synthesize IPv6 from IPv4.
@@ -787,7 +795,7 @@ remote-control:
# stub-addr: 192.0.2.68
# stub-prime: no
# stub-first: no
-# stub-ssl-upstream: no
+# stub-tls-upstream: no
# stub-zone:
# name: "example.org"
# stub-host: ns.example.com.
@@ -803,11 +811,35 @@ remote-control:
# forward-addr: 192.0.2.68
# forward-addr: 192.0.2.73@5355 # forward to port 5355.
# forward-first: no
-# forward-ssl-upstream: no
+# forward-tls-upstream: no
# forward-zone:
# name: "example.org"
# forward-host: fwd.example.com
+# Authority zones
+# The data for these zones is kept locally, from a file or downloaded.
+# The data can be served to downstream clients, or used instead of the
+# upstream (which saves a lookup to the upstream). The first example
+# 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.
+# auth-zone:
+# name: "."
+# for-downstream: no
+# for-upstream: yes
+# fallback-enabled: yes
+# master: b.root-servers.net
+# master: c.root-servers.net
+# master: e.root-servers.net
+# master: f.root-servers.net
+# master: g.root-servers.net
+# master: k.root-servers.net
+# auth-zone:
+# name: "example.org"
+# for-downstream: yes
+# for-upstream: yes
+# zonefile: "example.org.zone"
+
# Views
# Create named views. Name must be unique. Map views to requests using
# the access-control-view option. Views can contain zero or more local-zone
diff --git a/doc/libunbound.3.in b/doc/libunbound.3.in
index 0b8ca2afe32c..357e981fff4b 100644
--- a/doc/libunbound.3.in
+++ b/doc/libunbound.3.in
@@ -1,4 +1,4 @@
-.TH "libunbound" "3" "Jan 19, 2018" "NLnet Labs" "unbound 1.6.8"
+.TH "libunbound" "3" "Mar 15, 2018" "NLnet Labs" "unbound 1.7.0"
.\"
.\" 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.6.8 functions.
+\- Unbound DNS validating resolver 1.7.0 functions.
.SH "SYNOPSIS"
.B #include <unbound.h>
.LP
@@ -150,7 +150,8 @@
is an implementation of a DNS resolver, that does caching and
DNSSEC validation. This is the library API, for using the \-lunbound library.
The server daemon is described in \fIunbound\fR(8).
-The library can be used to convert hostnames to ip addresses, and back,
+The library works independent from a running unbound server, and
+can be used to convert hostnames to ip addresses, and back,
and obtain other information from the DNS. The library performs public\-key
validation of results with DNSSEC.
.P
@@ -162,7 +163,7 @@ and deleting it with
It can be created and deleted at any time. Creating it anew removes any
previous configuration (such as trusted keys) and clears any cached results.
.P
-The functions are thread\-safe, and a context an be used in a threaded (as
+The functions are thread\-safe, and a context can be used in a threaded (as
well as in a non\-threaded) environment. Also resolution (and validation)
can be performed blocking and non\-blocking (also called asynchronous).
The async method returns from the call immediately, so that processing
@@ -203,7 +204,10 @@ without trailing ':'. The returned value must be free(2)d by the caller.
A power\-user interface that lets you specify an unbound config file, see
\fIunbound.conf\fR(5), which is read for configuration. Not all options are
relevant. For some specific options, such as adding trust anchors, special
-routines exist.
+routines exist. This function is thread\-safe only if a single instance of
+ub_ctx* exists in the application. If several instances exist the
+application has to ensure that ub_ctx_config is not called in parallel by
+the different instances.
.TP
.B ub_ctx_set_fwd
Set machine to forward DNS queries to, the caching resolver to use.
@@ -407,6 +411,10 @@ returns NULL on an error (a malloc failure).
returns true if some information may be available, false otherwise.
.B ub_fd
returns a file descriptor or \-1 on error.
+.B ub_ctx_config
+and
+.B ub_ctx_resolvconf
+attempt to leave errno informative on a function return with file read failure.
.SH "SEE ALSO"
\fIunbound.conf\fR(5),
\fIunbound\fR(8).
diff --git a/doc/unbound-anchor.8.in b/doc/unbound-anchor.8.in
index 093b75aa7cd3..f50bf28af3f5 100644
--- a/doc/unbound-anchor.8.in
+++ b/doc/unbound-anchor.8.in
@@ -1,4 +1,4 @@
-.TH "unbound-anchor" "8" "Jan 19, 2018" "NLnet Labs" "unbound 1.6.8"
+.TH "unbound-anchor" "8" "Mar 15, 2018" "NLnet Labs" "unbound 1.7.0"
.\"
.\" unbound-anchor.8 -- unbound anchor maintenance utility manual
.\"
diff --git a/doc/unbound-checkconf.8.in b/doc/unbound-checkconf.8.in
index bfc55bdc0919..a07124e57a26 100644
--- a/doc/unbound-checkconf.8.in
+++ b/doc/unbound-checkconf.8.in
@@ -1,4 +1,4 @@
-.TH "unbound-checkconf" "8" "Jan 19, 2018" "NLnet Labs" "unbound 1.6.8"
+.TH "unbound-checkconf" "8" "Mar 15, 2018" "NLnet Labs" "unbound 1.7.0"
.\"
.\" unbound-checkconf.8 -- unbound configuration checker manual
.\"
diff --git a/doc/unbound-control.8.in b/doc/unbound-control.8.in
index 24e5ce23ad1d..53af91514eb7 100644
--- a/doc/unbound-control.8.in
+++ b/doc/unbound-control.8.in
@@ -1,4 +1,4 @@
-.TH "unbound-control" "8" "Jan 19, 2018" "NLnet Labs" "unbound 1.6.8"
+.TH "unbound-control" "8" "Mar 15, 2018" "NLnet Labs" "unbound 1.7.0"
.\"
.\" unbound-control.8 -- unbound remote control manual
.\"
diff --git a/doc/unbound-host.1.in b/doc/unbound-host.1.in
index 42e6096ef597..6842514d287e 100644
--- a/doc/unbound-host.1.in
+++ b/doc/unbound-host.1.in
@@ -1,4 +1,4 @@
-.TH "unbound\-host" "1" "Jan 19, 2018" "NLnet Labs" "unbound 1.6.8"
+.TH "unbound\-host" "1" "Mar 15, 2018" "NLnet Labs" "unbound 1.7.0"
.\"
.\" unbound-host.1 -- unbound DNS lookup utility
.\"
diff --git a/doc/unbound.8.in b/doc/unbound.8.in
index 1e2adb1ea53d..3c5786a79773 100644
--- a/doc/unbound.8.in
+++ b/doc/unbound.8.in
@@ -1,4 +1,4 @@
-.TH "unbound" "8" "Jan 19, 2018" "NLnet Labs" "unbound 1.6.8"
+.TH "unbound" "8" "Mar 15, 2018" "NLnet Labs" "unbound 1.7.0"
.\"
.\" unbound.8 -- unbound manual
.\"
@@ -9,7 +9,7 @@
.\"
.SH "NAME"
.B unbound
-\- Unbound DNS validating resolver 1.6.8.
+\- Unbound DNS validating resolver 1.7.0.
.SH "SYNOPSIS"
.B unbound
.RB [ \-h ]
diff --git a/doc/unbound.conf.5.in b/doc/unbound.conf.5.in
index f6e53111d2d9..156e3bed5f47 100644
--- a/doc/unbound.conf.5.in
+++ b/doc/unbound.conf.5.in
@@ -1,4 +1,4 @@
-.TH "unbound.conf" "5" "Jan 19, 2018" "NLnet Labs" "unbound 1.6.8"
+.TH "unbound.conf" "5" "Mar 15, 2018" "NLnet Labs" "unbound 1.7.0"
.\"
.\" unbound.conf.5 -- unbound.conf manual
.\"
@@ -293,7 +293,8 @@ 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
provides service on. This option needs unbound to be started with root
-permissions on some systems. The option uses IP_BINDANY on FreeBSD systems.
+permissions on some systems. The option uses IP_BINDANY on FreeBSD systems
+and SO_BINDANY on OpenBSD systems.
.TP
.B ip\-freebind: \fI<yes or no>
If yes, then use IP_FREEBIND socket option on sockets where unbound
@@ -330,6 +331,7 @@ the data in the cache does not match up with the actual data any more.
.B cache\-max\-negative\-ttl: \fI<seconds>
Time to live maximum for negative responses, these have a SOA in the
authority section that is limited in time. Default is 3600.
+This applies to nxdomain and nodata answers.
.TP
.B infra\-host\-ttl: \fI<seconds>
Time to live for entries in the host cache. The host cache contains
@@ -396,30 +398,52 @@ Enable udp upstream even if do-udp is no. Default is no, and this does not
change anything. Useful for TLS service providers, that want no udp downstream
but use udp to fetch data upstream.
.TP
-.B ssl\-upstream: \fI<yes or no>
+.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
TCP wireformat. The other server must support this (see
-\fBssl\-service\-key\fR).
+\fBtls\-service\-key\fR).
+.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 ssl\-service-key: \fI<file>
+.B tls\-service\-key: \fI<file>
If enabled, the server provider SSL service on its TCP sockets. The clients
-have to use ssl\-upstream: yes. The file is the private key for the TLS
-session. The public certificate is in the ssl\-service\-pem file. Default
+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,
because the private key is read while root permissions are held and before
chroot (if any). Normal DNS TCP service is not provided and gives errors,
this service is best run with a different \fBport:\fR config or \fI@port\fR
suffixes in the \fBinterface\fR config.
.TP
-.B ssl\-service\-pem: \fI<file>
-The public key certificate pem file for the ssl service. Default is "",
+.B ssl\-service\-key: \fI<file>
+Alternate syntax for \fBtls\-service\-key\fR.
+.TP
+.B tls\-service\-pem: \fI<file>
+The public key certificate pem file for the tls service. Default is "",
turned off.
.TP
-.B ssl\-port: \fI<number>
+.B ssl\-service\-pem: \fI<file>
+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.
.TP
+.B ssl\-port: \fI<number>
+Alternate syntax for \fBtls\-port\fR.
+.TP
+.B tls\-cert\-bundle: \fI<file>
+If null or "", no file is used. Set it to the certificate bundle file,
+for example "/etc/pki/tls/certs/ca\-bundle.crt". These certificates are used
+for authenticating connections made to outside peers. For example auth\-zone
+urls, and also DNS over TLS connections.
+.TP
+.B ssl\-cert\-bundle: \fI<file>
+Alternate syntax for \fBtls\-cert\-bundle\fR.
+.TP
.B use\-systemd: \fI<yes or no>
Enable or disable systemd socket activation.
Default is no.
@@ -690,7 +714,7 @@ Can be given multiple times, for different domains.
.TP
.B qname\-minimisation: \fI<yes or no>
Send minimum amount of information to upstream servers to enhance privacy.
-Only sent minimum required labels of the QNAME and set QTYPE to NS when
+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.
@@ -701,6 +725,12 @@ potentially broken nameservers. A lot of domains will not be resolvable when
this option in enabled. Only use if you know what you are doing.
This option only has effect when qname-minimisation is enabled. Default is off.
.TP
+.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.
+.TP
.B private\-address: \fI<IP address or subnet>
Give IPv4 of IPv6 addresses or classless subnets. These are addresses
on your private network, and are not allowed to be returned for
@@ -976,7 +1006,7 @@ address space are not validated. This is usually required whenever
Configure a local zone. The type determines the answer to give if
there is no match from local\-data. The types are deny, refuse, static,
transparent, redirect, nodefault, typetransparent, inform, inform_deny,
-always_transparent, always_refuse, always_nxdomain,
+always_transparent, always_refuse, always_nxdomain, noview,
and are explained below. After that the default settings are listed. Use
local\-data: to enter data into the local zone. Answers for local zones
are authoritative DNS answers. By default the zones are class IN.
@@ -1046,6 +1076,13 @@ Like refuse, but ignores local data and refuses the query.
\h'5'\fIalways_nxdomain\fR
Like static, but ignores local data and returns nxdomain for the query.
.TP 10
+\h'5'\fInoview\fR
+Breaks out of that view and moves towards the global local zones for answer
+to the query. If the view first is no, it'll resolve normally. If view first
+is enabled, it'll break perform that step and check the global answers.
+For when the view has view specific overrides but some zone has to be
+answered from global local zone contents.
+.TP 10
\h'5'\fInodefault\fR
Used to turn off default contents for AS112 zones. The other types
also turn off default contents for the zone. The 'nodefault' option
@@ -1109,7 +1146,7 @@ local\-data: "onion. 10800 IN
SOA localhost. nobody.invalid. 1 3600 1200 604800 10800"
.fi
.TP 10
-\h'5'\fItest (RFC 7686)\fR
+\h'5'\fItest (RFC 2606)\fR
Default content:
.nf
local\-zone: "test." static
@@ -1118,7 +1155,7 @@ local\-data: "test. 10800 IN
SOA localhost. nobody.invalid. 1 3600 1200 604800 10800"
.fi
.TP 10
-\h'5'\fIinvalid (RFC 7686)\fR
+\h'5'\fIinvalid (RFC 2606)\fR
Default content:
.nf
local\-zone: "invalid." static
@@ -1378,9 +1415,12 @@ The data could not be retrieved and would have caused SERVFAIL because
the servers are unreachable, instead it is tried without this clause.
The default is no.
.TP
-.B stub\-ssl\-upstream: \fI<yes or no>
+.B stub\-tls\-upstream: \fI<yes or no>
Enabled or disable whether the queries to this stub use SSL for transport.
Default is no.
+.TP
+.B stub\-ssl\-upstream: \fI<yes or no>
+Alternate syntax for \fBstub\-tls\-upstream\fR.
.SS "Forward Zone Options"
.LP
There may be multiple
@@ -1392,6 +1432,9 @@ forward the queries to. The servers listed as \fBforward\-host:\fR and
those servers are not authority servers, but are (just like unbound is)
recursive servers too; unbound does not perform recursion itself for the
forward zone, it lets the remote server do it. Class IN is assumed.
+CNAMEs are chased by unbound itself, asking the remote server for every
+name in the indirection chain, to protect the local cache from illegal
+indirect referenced items.
A forward\-zone entry with name "." and a forward\-addr target will
forward all queries to that other server (unless it can answer from
the cache).
@@ -1412,9 +1455,73 @@ The data could not be retrieved and would have caused SERVFAIL because
the servers are unreachable, instead it is tried without this clause.
The default is no.
.TP
-.B forward\-ssl\-upstream: \fI<yes or no>
+.B forward\-tls\-upstream: \fI<yes or no>
Enabled or disable whether the queries to this forwarder use SSL for transport.
Default is no.
+.TP
+.B forward\-ssl\-upstream: \fI<yes or no>
+Alternate syntax for \fBforward\-tls\-upstream\fR.
+.SS "Authority Zone Options"
+.LP
+Authority zones are configured with \fBauth\-zone:\fR, and each one must
+have a \fBname:\fR. There can be multiple ones, by listing multiple auth\-zone clauses, each with a different name, pertaining to that part of the namespace.
+The authority zone with the name closest to the name looked up is used.
+Authority zones are processed after \fBlocal\-zones\fR and before
+cache (\fBfor\-downstream:\fR \fIyes\fR), and when used in this manner
+make unbound respond like an authority server. Authority zones are also
+processed after cache, just before going to the network to fetch
+information for recursion (\fBfor\-upstream:\fR \fIyes\fR), and when used
+in this manner provide a local copy of an authority server that speeds up
+lookups of that data.
+.LP
+Authority zones can be read from zonefile. And can be kept updated via
+AXFR and IXFR. After update the zonefile is rewritten. The update mechanism
+uses the SOA timer values and performs SOA UDP queries to detect zone changes.
+.TP
+.B name: \fI<zone name>
+Name of the authority zone.
+.TP
+.B master: \fI<IP address or host name>
+Where to download a copy of the zone from, with AXFR and IXFR. Multiple
+masters can be specified. They are all tried if one fails.
+.TP
+.B url: \fI<url to zonefile>
+Where to download a zonefile for the zone. With http or https. An example
+for the url is "http://www.example.com/example.org.zone". Multiple url
+statements can be given, they are tried in turn. If only urls are given
+the SOA refresh timer is used to wait for making new downloads. If also
+masters are listed, the masters are first probed with UDP SOA queries to
+see if the SOA serial number has changed, reducing the number of downloads.
+If none of the urls work, the masters are tried with IXFR and AXFR.
+For https, the \fBtls\-cert\-bundle\fR and the hostname from the url are used
+to authenticate the connection.
+.TP
+.B 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
+validation failures.
+.TP
+.B for\-downstream: \fI<yes or no>
+Default yes. If enabled, unbound serves authority responses to
+downstream clients for this zone. This option makes unbound behave, for
+the queries with names in this zone, like one of the authority servers for
+that zone. Turn it off if you want unbound to provide recursion for the
+zone but have a local copy of zone data. If for\-downstream is no and
+for\-upstream is yes, then unbound will DNSSEC validate the contents of the
+zone before serving the zone contents to clients and store validation
+results in the cache.
+.TP
+.B for\-upstream: \fI<yes or no>
+Default yes. If enabled, unbound fetches data from this data collection
+for answering recursion queries. Instead of sending queries over the internet
+to the authority servers for this zone, it'll fetch the data directly from
+the zone data. Turn it on when you want unbound to provide recursion for
+downstream clients, and use the zone data as a local copy to speed up lookups.
+.TP
+.B zonefile: \fI<filename>
+The filename where the zone is stored. If not given then no zonefile is used.
+If the file does not exist or is empty, unbound will attempt to fetch zone
+data (eg. from the master servers).
.SS "View Options"
.LP
There may be multiple
@@ -1513,6 +1620,19 @@ times.
Path to the certificate related to the \fBdnscrypt\-secret\-key\fRs.
This option may be specified multiple times.
.TP
+.B dnscrypt\-provider\-cert\-rotated: \fI<path to cert file>\fR
+Path to a certificate that we should be able to serve existing connection from
+but do not want to advertise over \fBdnscrypt\-provider\fR's TXT record certs
+distribution.
+A typical use case is when rotating certificates, existing clients may still use
+the client magic from the old cert in their queries until they fetch and update
+the new cert. Likewise, it would allow one to prime the new cert/key without
+distributing the new cert yet, this can be useful when using a network of
+servers using anycast and on which the configuration may not get updated at the
+exact same time. By priming the cert, the servers can handle both old and new
+certs traffic while distributing only one.
+This option may be specified multiple times.
+.TP
.B dnscrypt\-shared\-secret\-cache\-size: \fI<memory size>
Give the size of the data structure in which the shared secret keys are kept
in. Default 4m. In bytes or use m(mega), k(kilo), g(giga).
diff --git a/edns-subnet/addrtree.c b/edns-subnet/addrtree.c
index 050eb31fc98f..9a02db062c51 100644
--- a/edns-subnet/addrtree.c
+++ b/edns-subnet/addrtree.c
@@ -485,7 +485,7 @@ addrtree_find(struct addrtree *tree, const addrkey_t *addr,
/* does this node have data? if yes, see if we have a match */
if (node->elem && node->ttl >= now) {
/* saved at wrong depth */;
- log_assert(node->scope >= depth)
+ log_assert(node->scope >= depth);
if (depth == node->scope ||
(node->scope > sourcemask &&
depth == sourcemask)) {
diff --git a/edns-subnet/subnetmod.c b/edns-subnet/subnetmod.c
index 4b8a4b211275..ae2523b86c23 100644
--- a/edns-subnet/subnetmod.c
+++ b/edns-subnet/subnetmod.c
@@ -339,6 +339,7 @@ update_cache(struct module_qstate *qstate, int id)
return;
}
lru_entry = &mrep_entry->entry;
+ lock_rw_wrlock(&lru_entry->lock);
lru_entry->data = calloc(1,
sizeof(struct subnet_msg_cache_data));
if (!lru_entry->data) {
@@ -352,7 +353,9 @@ update_cache(struct module_qstate *qstate, int id)
log_err("Subnet cache insertion failed");
return;
}
+ lock_quick_lock(&sne->alloc.lock);
rep = reply_info_copy(qstate->return_msg->rep, &sne->alloc, NULL);
+ lock_quick_unlock(&sne->alloc.lock);
if (!rep) {
if (acquired_lock) lock_rw_unlock(&lru_entry->lock);
log_err("Subnet cache insertion failed");
@@ -374,6 +377,7 @@ update_cache(struct module_qstate *qstate, int id)
if (acquired_lock) {
lock_rw_unlock(&lru_entry->lock);
} else {
+ lock_rw_unlock(&lru_entry->lock);
slabhash_insert(subnet_msg_cache, h, lru_entry, lru_entry->data,
NULL);
}
diff --git a/iterator/iter_delegpt.h b/iterator/iter_delegpt.h
index 4bd79c81af09..24f0574901d9 100644
--- a/iterator/iter_delegpt.h
+++ b/iterator/iter_delegpt.h
@@ -83,6 +83,8 @@ struct delegpt {
uint8_t dp_type_mlc;
/** use SSL for upstream query */
uint8_t ssl_upstream;
+ /** delegpt from authoritative zone that is locally hosted */
+ uint8_t auth_dp;
};
/**
diff --git a/iterator/iter_hints.c b/iterator/iter_hints.c
index 47af96687fe6..1d4c228fabc2 100644
--- a/iterator/iter_hints.c
+++ b/iterator/iter_hints.c
@@ -129,7 +129,7 @@ compile_time_root_prime(int do_ip4, int do_ip6)
dp->has_parent_side_NS = 1;
if(do_ip4) {
if(!ah(dp, "A.ROOT-SERVERS.NET.", "198.41.0.4")) goto failed;
- if(!ah(dp, "B.ROOT-SERVERS.NET.", "192.228.79.201")) goto failed;
+ if(!ah(dp, "B.ROOT-SERVERS.NET.", "199.9.14.201")) goto failed;
if(!ah(dp, "C.ROOT-SERVERS.NET.", "192.33.4.12")) goto failed;
if(!ah(dp, "D.ROOT-SERVERS.NET.", "199.7.91.13")) goto failed;
if(!ah(dp, "E.ROOT-SERVERS.NET.", "192.203.230.10")) goto failed;
diff --git a/iterator/iter_scrub.c b/iterator/iter_scrub.c
index 1bee85c0b991..12580dcdb539 100644
--- a/iterator/iter_scrub.c
+++ b/iterator/iter_scrub.c
@@ -503,6 +503,24 @@ scrub_normalize(sldns_buffer* pkt, struct msg_parse* msg,
continue;
}
}
+ /* if this is type DS and we query for type DS we just got
+ * a referral answer for our type DS query, fix packet */
+ if(rrset->type==LDNS_RR_TYPE_DS &&
+ qinfo->qtype == LDNS_RR_TYPE_DS &&
+ dname_pkt_compare(pkt, qinfo->qname, rrset->dname) == 0) {
+ rrset->section = LDNS_SECTION_ANSWER;
+ msg->ancount = rrset->rr_count + rrset->rrsig_count;
+ msg->nscount = 0;
+ msg->arcount = 0;
+ msg->an_rrsets = 1;
+ msg->ns_rrsets = 0;
+ msg->ar_rrsets = 0;
+ msg->rrset_count = 1;
+ msg->rrset_first = rrset;
+ msg->rrset_last = rrset;
+ rrset->rrset_all_next = NULL;
+ return 1;
+ }
mark_additional_rrset(pkt, msg, rrset);
prev = rrset;
rrset = rrset->rrset_all_next;
diff --git a/iterator/iter_utils.c b/iterator/iter_utils.c
index 0b1b456113f7..70cab40faa80 100644
--- a/iterator/iter_utils.c
+++ b/iterator/iter_utils.c
@@ -656,6 +656,11 @@ iter_indicates_dnssec(struct module_env* env, struct delegpt* dp,
/* a trust anchor exists with this name, RRSIGs expected */
if((a=anchor_find(env->anchors, dp->name, dp->namelabs, dp->namelen,
dclass))) {
+ if(a->numDS == 0 && a->numDNSKEY == 0) {
+ /* insecure trust point */
+ lock_basic_unlock(&a->lock);
+ return 0;
+ }
lock_basic_unlock(&a->lock);
return 1;
}
diff --git a/iterator/iter_utils.h b/iterator/iter_utils.h
index d0629a83e0df..602fa6db3d0d 100644
--- a/iterator/iter_utils.h
+++ b/iterator/iter_utils.h
@@ -193,7 +193,7 @@ int iter_indicates_dnssec_fwd(struct module_env* env,
* @param dp: delegation point.
* @param msg: delegation message, with DS if a secure referral.
* @param dclass: class of query.
- * @return 1 if dnssec is expected, 0 if not.
+ * @return 1 if dnssec is expected, 0 if not or insecure point above qname.
*/
int iter_indicates_dnssec(struct module_env* env, struct delegpt* dp,
struct dns_msg* msg, uint16_t dclass);
diff --git a/iterator/iterator.c b/iterator/iterator.c
index 6c49709adea3..7f3c65737d59 100644
--- a/iterator/iterator.c
+++ b/iterator/iterator.c
@@ -53,6 +53,7 @@
#include "validator/val_neg.h"
#include "services/cache/dns.h"
#include "services/cache/infra.h"
+#include "services/authzone.h"
#include "util/module.h"
#include "util/netevent.h"
#include "util/net_help.h"
@@ -771,6 +772,11 @@ prime_stub(struct module_qstate* qstate, struct iter_qstate* iq, int id,
if(!stub)
return 0;
stub_dp = stub->dp;
+ /* if we have an auth_zone dp, and stub is equal, don't prime stub
+ * yet, unless we want to fallback and avoid the auth_zone */
+ if(!iq->auth_zone_avoid && iq->dp && iq->dp->auth_dp &&
+ query_dname_compare(iq->dp->name, stub_dp->name) == 0)
+ return 0;
/* is it a noprime stub (always use) */
if(stub->noprime) {
@@ -832,6 +838,96 @@ prime_stub(struct module_qstate* qstate, struct iter_qstate* iq, int id,
}
/**
+ * Generate a delegation point for an auth zone (unless cached dp is better)
+ * false on alloc failure.
+ */
+static int
+auth_zone_delegpt(struct module_qstate* qstate, struct iter_qstate* iq,
+ uint8_t* delname, size_t delnamelen)
+{
+ struct auth_zone* z;
+ if(iq->auth_zone_avoid)
+ return 1;
+ if(!delname) {
+ delname = iq->qchase.qname;
+ delnamelen = iq->qchase.qname_len;
+ }
+ lock_rw_rdlock(&qstate->env->auth_zones->lock);
+ z = auth_zones_find_zone(qstate->env->auth_zones, delname, delnamelen,
+ qstate->qinfo.qclass);
+ if(!z) {
+ lock_rw_unlock(&qstate->env->auth_zones->lock);
+ return 1;
+ }
+ lock_rw_rdlock(&z->lock);
+ lock_rw_unlock(&qstate->env->auth_zones->lock);
+ if(z->for_upstream) {
+ if(iq->dp && query_dname_compare(z->name, iq->dp->name) == 0
+ && iq->dp->auth_dp && qstate->blacklist &&
+ z->fallback_enabled) {
+ /* cache is blacklisted and fallback, and we
+ * already have an auth_zone dp */
+ if(verbosity>=VERB_ALGO) {
+ char buf[255+1];
+ dname_str(z->name, buf);
+ verbose(VERB_ALGO, "auth_zone %s "
+ "fallback because cache blacklisted",
+ buf);
+ }
+ lock_rw_unlock(&z->lock);
+ iq->dp = NULL;
+ return 1;
+ }
+ if(iq->dp==NULL || dname_subdomain_c(z->name, iq->dp->name)) {
+ struct delegpt* dp;
+ if(qstate->blacklist && z->fallback_enabled) {
+ /* cache is blacklisted because of a DNSSEC
+ * validation failure, and the zone allows
+ * fallback to the internet, query there. */
+ if(verbosity>=VERB_ALGO) {
+ char buf[255+1];
+ dname_str(z->name, buf);
+ verbose(VERB_ALGO, "auth_zone %s "
+ "fallback because cache blacklisted",
+ buf);
+ }
+ lock_rw_unlock(&z->lock);
+ return 1;
+ }
+ dp = (struct delegpt*)regional_alloc_zero(
+ qstate->region, sizeof(*dp));
+ if(!dp) {
+ log_err("alloc failure");
+ if(z->fallback_enabled) {
+ lock_rw_unlock(&z->lock);
+ return 1; /* just fallback */
+ }
+ lock_rw_unlock(&z->lock);
+ return 0;
+ }
+ dp->name = regional_alloc_init(qstate->region,
+ z->name, z->namelen);
+ if(!dp->name) {
+ log_err("alloc failure");
+ if(z->fallback_enabled) {
+ lock_rw_unlock(&z->lock);
+ return 1; /* just fallback */
+ }
+ lock_rw_unlock(&z->lock);
+ return 0;
+ }
+ dp->namelen = z->namelen;
+ dp->namelabs = z->namelabs;
+ dp->auth_dp = 1;
+ iq->dp = dp;
+ }
+ }
+
+ lock_rw_unlock(&z->lock);
+ return 1;
+}
+
+/**
* Generate A and AAAA checks for glue that is in-zone for the referral
* we just got to obtain authoritative information on the addresses.
*
@@ -914,6 +1010,9 @@ generate_ns_check(struct module_qstate* qstate, struct iter_qstate* iq, int id)
generate_a_aaaa_check(qstate, iq, id);
return;
}
+ /* no need to get the NS record for DS, it is above the zonecut */
+ if(qstate->qinfo.qtype == LDNS_RR_TYPE_DS)
+ return;
log_nametypeclass(VERB_ALGO, "schedule ns fetch",
iq->dp->name, LDNS_RR_TYPE_NS, iq->qchase.qclass);
@@ -1106,14 +1205,15 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
msg = dns_cache_lookup(qstate->env, iq->qchase.qname,
iq->qchase.qname_len, iq->qchase.qtype,
iq->qchase.qclass, qstate->query_flags,
- qstate->region, qstate->env->scratch);
+ qstate->region, qstate->env->scratch, 0);
if(!msg && qstate->env->neg_cache) {
/* 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,
qstate->region, qstate->env->rrset_cache,
qstate->env->scratch_buffer,
- *qstate->env->now, 1/*add SOA*/, NULL);
+ *qstate->env->now, 1/*add SOA*/, NULL,
+ qstate->env->cfg);
}
/* item taken from cache does not match our query name, thus
* security needs to be re-examined later */
@@ -1164,7 +1264,7 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
iq->response = msg;
return final_state(iq);
}
-
+
/* attempt to forward the request */
if(forward_request(qstate, iq))
{
@@ -1225,8 +1325,15 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
/* If the cache has returned nothing, then we have a
* root priming situation. */
if(iq->dp == NULL) {
+ int r;
+ /* if under auth zone, no prime needed */
+ if(!auth_zone_delegpt(qstate, iq, delname, delnamelen))
+ return error_response(qstate, id,
+ LDNS_RCODE_SERVFAIL);
+ if(iq->dp) /* use auth zone dp */
+ return next_state(iq, INIT_REQUEST_2_STATE);
/* if there is a stub, then no root prime needed */
- int r = prime_stub(qstate, iq, id, delname,
+ r = prime_stub(qstate, iq, id, delname,
iq->qchase.qclass);
if(r == 2)
break; /* got noprime-stub-zone, continue */
@@ -1371,22 +1478,36 @@ processInitRequest2(struct module_qstate* qstate, struct iter_qstate* iq,
log_query_info(VERB_QUERY, "resolving (init part 2): ",
&qstate->qinfo);
+ delname = iq->qchase.qname;
+ delnamelen = iq->qchase.qname_len;
if(iq->refetch_glue) {
+ struct iter_hints_stub* stub;
if(!iq->dp) {
log_err("internal or malloc fail: no dp for refetch");
return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
}
- delname = iq->dp->name;
- delnamelen = iq->dp->namelen;
- } else {
- delname = iq->qchase.qname;
- delnamelen = iq->qchase.qname_len;
+ /* Do not send queries above stub, do not set delname to dp if
+ * this is above stub without stub-first. */
+ stub = hints_lookup_stub(
+ qstate->env->hints, iq->qchase.qname, iq->qchase.qclass,
+ iq->dp);
+ if(!stub || !stub->dp->has_parent_side_NS ||
+ dname_subdomain_c(iq->dp->name, stub->dp->name)) {
+ delname = iq->dp->name;
+ delnamelen = iq->dp->namelen;
+ }
}
if(iq->qchase.qtype == LDNS_RR_TYPE_DS || iq->refetch_glue) {
if(!dname_is_root(delname))
dname_remove_label(&delname, &delnamelen);
iq->refetch_glue = 0; /* if CNAME causes restart, no refetch */
}
+
+ /* see if we have an auth zone to answer from, improves dp from cache
+ * (if any dp from cache) with auth zone dp, if that is lower */
+ if(!auth_zone_delegpt(qstate, iq, delname, delnamelen))
+ return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
+
/* Check to see if we need to prime a stub zone. */
if(prime_stub(qstate, iq, id, delname, iq->qchase.qclass)) {
/* A priming sub request was made */
@@ -1871,6 +1992,7 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
int tf_policy;
struct delegpt_addr* target;
struct outbound_entry* outq;
+ int auth_fallback = 0;
/* NOTE: a request will encounter this state for each target it
* needs to send a query to. That is, at least one per referral,
@@ -1915,6 +2037,152 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
return 0;
}
+ if(iq->minimisation_state == INIT_MINIMISE_STATE) {
+ /* (Re)set qinfo_out to (new) delegation point, except when
+ * qinfo_out is already a subdomain of dp. This happens when
+ * increasing by more than one label at once (QNAMEs with more
+ * than MAX_MINIMISE_COUNT labels). */
+ if(!(iq->qinfo_out.qname_len
+ && dname_subdomain_c(iq->qchase.qname,
+ iq->qinfo_out.qname)
+ && dname_subdomain_c(iq->qinfo_out.qname,
+ iq->dp->name))) {
+ iq->qinfo_out.qname = iq->dp->name;
+ iq->qinfo_out.qname_len = iq->dp->namelen;
+ iq->qinfo_out.qtype = LDNS_RR_TYPE_A;
+ iq->qinfo_out.qclass = iq->qchase.qclass;
+ iq->qinfo_out.local_alias = NULL;
+ iq->minimise_count = 0;
+ }
+
+ iq->minimisation_state = MINIMISE_STATE;
+ }
+ if(iq->minimisation_state == MINIMISE_STATE) {
+ int qchaselabs = dname_count_labels(iq->qchase.qname);
+ int labdiff = qchaselabs -
+ dname_count_labels(iq->qinfo_out.qname);
+
+ iq->qinfo_out.qname = iq->qchase.qname;
+ iq->qinfo_out.qname_len = iq->qchase.qname_len;
+ iq->minimise_count++;
+ iq->minimise_timeout_count = 0;
+
+ iter_dec_attempts(iq->dp, 1);
+
+ /* Limit number of iterations for QNAMEs with more
+ * than MAX_MINIMISE_COUNT labels. Send first MINIMISE_ONE_LAB
+ * labels of QNAME always individually.
+ */
+ if(qchaselabs > MAX_MINIMISE_COUNT && labdiff > 1 &&
+ iq->minimise_count > MINIMISE_ONE_LAB) {
+ if(iq->minimise_count < MAX_MINIMISE_COUNT) {
+ int multilabs = qchaselabs - 1 -
+ MINIMISE_ONE_LAB;
+ int extralabs = multilabs /
+ MINIMISE_MULTIPLE_LABS;
+
+ if (MAX_MINIMISE_COUNT - iq->minimise_count >=
+ multilabs % MINIMISE_MULTIPLE_LABS)
+ /* Default behaviour is to add 1 label
+ * every iteration. Therefore, decrement
+ * the extralabs by 1 */
+ extralabs--;
+ if (extralabs < labdiff)
+ labdiff -= extralabs;
+ else
+ labdiff = 1;
+ }
+ /* Last minimised iteration, send all labels with
+ * QTYPE=NS */
+ else
+ labdiff = 1;
+ }
+
+ if(labdiff > 1) {
+ verbose(VERB_QUERY, "removing %d labels", labdiff-1);
+ dname_remove_labels(&iq->qinfo_out.qname,
+ &iq->qinfo_out.qname_len,
+ labdiff-1);
+ }
+ if(labdiff < 1 || (labdiff < 2
+ && (iq->qchase.qtype == LDNS_RR_TYPE_DS
+ || iq->qchase.qtype == LDNS_RR_TYPE_A)))
+ /* Stop minimising this query, resolve "as usual" */
+ iq->minimisation_state = DONOT_MINIMISE_STATE;
+ else if(!qstate->no_cache_lookup) {
+ struct dns_msg* msg = dns_cache_lookup(qstate->env,
+ iq->qinfo_out.qname, iq->qinfo_out.qname_len,
+ iq->qinfo_out.qtype, iq->qinfo_out.qclass,
+ qstate->query_flags, qstate->region,
+ qstate->env->scratch, 0);
+ if(msg && msg->rep->an_numrrsets == 0
+ && FLAGS_GET_RCODE(msg->rep->flags) ==
+ LDNS_RCODE_NOERROR)
+ /* no need to send query if it is already
+ * cached as NOERROR/NODATA */
+ return 1;
+ }
+ }
+ if(iq->minimisation_state == SKIP_MINIMISE_STATE) {
+ if(iq->minimise_timeout_count < MAX_MINIMISE_TIMEOUT_COUNT)
+ /* Do not increment qname, continue incrementing next
+ * iteration */
+ iq->minimisation_state = MINIMISE_STATE;
+ else if(!qstate->env->cfg->qname_minimisation_strict)
+ /* Too many time-outs detected for this QNAME and QTYPE.
+ * We give up, disable QNAME minimisation. */
+ iq->minimisation_state = DONOT_MINIMISE_STATE;
+ }
+ if(iq->minimisation_state == DONOT_MINIMISE_STATE)
+ iq->qinfo_out = iq->qchase;
+
+ /* now find an answer to this query */
+ /* see if authority zones have an answer */
+ /* now we know the dp, we can check the auth zone for locally hosted
+ * contents */
+ if(!iq->auth_zone_avoid && qstate->blacklist) {
+ if(auth_zones_can_fallback(qstate->env->auth_zones,
+ iq->dp->name, iq->dp->namelen, iq->qinfo_out.qclass)) {
+ /* if cache is blacklisted and this zone allows us
+ * to fallback to the internet, then do so, and
+ * fetch results from the internet servers */
+ iq->auth_zone_avoid = 1;
+ }
+ }
+ if(iq->auth_zone_avoid) {
+ iq->auth_zone_avoid = 0;
+ auth_fallback = 1;
+ } else if(auth_zones_lookup(qstate->env->auth_zones, &iq->qinfo_out,
+ qstate->region, &iq->response, &auth_fallback, iq->dp->name,
+ iq->dp->namelen)) {
+ /* use this as a response to be processed by the iterator */
+ if(verbosity >= VERB_ALGO) {
+ 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);
+ }
+ iq->auth_zone_response = 0;
+ if(auth_fallback == 0) {
+ /* like we got servfail from the auth zone lookup, and
+ * no internet fallback */
+ verbose(VERB_ALGO, "auth zone lookup failed, no fallback,"
+ " servfail");
+ return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
+ }
+ if(iq->dp && iq->dp->auth_dp) {
+ /* we wanted to fallback, but had no delegpt, only the
+ * auth zone generated delegpt, create an actual one */
+ iq->auth_zone_avoid = 1;
+ return next_state(iq, INIT_REQUEST_STATE);
+ }
+ /* but mostly, fallback==1 (like, when no such auth zone exists)
+ * and we continue with lookups */
+
tf_policy = 0;
/* < not <=, because although the array is large enough for <=, the
* generated query will immediately be discarded due to depth and
@@ -2082,105 +2350,6 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
}
}
- if(iq->minimisation_state == INIT_MINIMISE_STATE) {
- /* (Re)set qinfo_out to (new) delegation point, except when
- * qinfo_out is already a subdomain of dp. This happens when
- * increasing by more than one label at once (QNAMEs with more
- * than MAX_MINIMISE_COUNT labels). */
- if(!(iq->qinfo_out.qname_len
- && dname_subdomain_c(iq->qchase.qname,
- iq->qinfo_out.qname)
- && dname_subdomain_c(iq->qinfo_out.qname,
- iq->dp->name))) {
- iq->qinfo_out.qname = iq->dp->name;
- iq->qinfo_out.qname_len = iq->dp->namelen;
- iq->qinfo_out.qtype = LDNS_RR_TYPE_A;
- iq->qinfo_out.qclass = iq->qchase.qclass;
- iq->qinfo_out.local_alias = NULL;
- iq->minimise_count = 0;
- }
-
- iq->minimisation_state = MINIMISE_STATE;
- }
- if(iq->minimisation_state == MINIMISE_STATE) {
- int qchaselabs = dname_count_labels(iq->qchase.qname);
- int labdiff = qchaselabs -
- dname_count_labels(iq->qinfo_out.qname);
-
- iq->qinfo_out.qname = iq->qchase.qname;
- iq->qinfo_out.qname_len = iq->qchase.qname_len;
- iq->minimise_count++;
- iq->minimise_timeout_count = 0;
-
- iter_dec_attempts(iq->dp, 1);
-
- /* Limit number of iterations for QNAMEs with more
- * than MAX_MINIMISE_COUNT labels. Send first MINIMISE_ONE_LAB
- * labels of QNAME always individually.
- */
- if(qchaselabs > MAX_MINIMISE_COUNT && labdiff > 1 &&
- iq->minimise_count > MINIMISE_ONE_LAB) {
- if(iq->minimise_count < MAX_MINIMISE_COUNT) {
- int multilabs = qchaselabs - 1 -
- MINIMISE_ONE_LAB;
- int extralabs = multilabs /
- MINIMISE_MULTIPLE_LABS;
-
- if (MAX_MINIMISE_COUNT - iq->minimise_count >=
- multilabs % MINIMISE_MULTIPLE_LABS)
- /* Default behaviour is to add 1 label
- * every iteration. Therefore, decrement
- * the extralabs by 1 */
- extralabs--;
- if (extralabs < labdiff)
- labdiff -= extralabs;
- else
- labdiff = 1;
- }
- /* Last minimised iteration, send all labels with
- * QTYPE=NS */
- else
- labdiff = 1;
- }
-
- if(labdiff > 1) {
- verbose(VERB_QUERY, "removing %d labels", labdiff-1);
- dname_remove_labels(&iq->qinfo_out.qname,
- &iq->qinfo_out.qname_len,
- labdiff-1);
- }
- if(labdiff < 1 || (labdiff < 2
- && (iq->qchase.qtype == LDNS_RR_TYPE_DS
- || iq->qchase.qtype == LDNS_RR_TYPE_A)))
- /* Stop minimising this query, resolve "as usual" */
- iq->minimisation_state = DONOT_MINIMISE_STATE;
- else if(!qstate->no_cache_lookup) {
- struct dns_msg* msg = dns_cache_lookup(qstate->env,
- iq->qinfo_out.qname, iq->qinfo_out.qname_len,
- iq->qinfo_out.qtype, iq->qinfo_out.qclass,
- qstate->query_flags, qstate->region,
- qstate->env->scratch);
- if(msg && msg->rep->an_numrrsets == 0
- && FLAGS_GET_RCODE(msg->rep->flags) ==
- LDNS_RCODE_NOERROR)
- /* no need to send query if it is already
- * cached as NOERROR/NODATA */
- return 1;
- }
- }
- if(iq->minimisation_state == SKIP_MINIMISE_STATE) {
- if(iq->minimise_timeout_count < MAX_MINIMISE_TIMEOUT_COUNT)
- /* Do not increment qname, continue incrementing next
- * iteration */
- iq->minimisation_state = MINIMISE_STATE;
- else if(!qstate->env->cfg->qname_minimisation_strict)
- /* Too many time-outs detected for this QNAME and QTYPE.
- * We give up, disable QNAME minimisation. */
- iq->minimisation_state = DONOT_MINIMISE_STATE;
- }
- if(iq->minimisation_state == DONOT_MINIMISE_STATE)
- iq->qinfo_out = iq->qchase;
-
/* We have a valid target. */
if(verbosity >= VERB_QUERY) {
log_query_info(VERB_QUERY, "sending query:", &iq->qinfo_out);
@@ -2573,6 +2742,7 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
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;
@@ -2645,6 +2815,25 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
if (qstate->env->cfg->qname_minimisation &&
!qstate->env->cfg->qname_minimisation_strict)
iq->minimisation_state = DONOT_MINIMISE_STATE;
+ if(iq->auth_zone_response) {
+ /* can we fallback? */
+ iq->auth_zone_response = 0;
+ if(!auth_zones_can_fallback(qstate->env->auth_zones,
+ iq->dp->name, iq->dp->namelen, qstate->qinfo.qclass)) {
+ verbose(VERB_ALGO, "auth zone response bad, and no"
+ " fallback possible, servfail");
+ return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
+ }
+ verbose(VERB_ALGO, "auth zone response was bad, "
+ "fallback enabled");
+ iq->auth_zone_avoid = 1;
+ if(iq->dp->auth_dp) {
+ /* we are using a dp for the auth zone, with no
+ * nameservers, get one first */
+ iq->dp = NULL;
+ return next_state(iq, INIT_REQUEST_STATE);
+ }
+ }
return next_state(iq, QUERYTARGETS_STATE);
}
diff --git a/iterator/iterator.h b/iterator/iterator.h
index 841a3643669c..67ffeb147631 100644
--- a/iterator/iterator.h
+++ b/iterator/iterator.h
@@ -387,6 +387,11 @@ struct iter_qstate {
* Count number of time-outs. Used to prevent resolving failures when
* the QNAME minimisation QTYPE is blocked. */
int minimise_timeout_count;
+
+ /** True if the current response is from auth_zone */
+ int auth_zone_response;
+ /** True if the auth_zones should not be consulted for the query */
+ int auth_zone_avoid;
};
/**
diff --git a/libunbound/context.c b/libunbound/context.c
index e203111b70d8..8bff713bca30 100644
--- a/libunbound/context.c
+++ b/libunbound/context.c
@@ -47,6 +47,7 @@
#include "services/localzone.h"
#include "services/cache/rrset.h"
#include "services/cache/infra.h"
+#include "services/authzone.h"
#include "util/data/msgreply.h"
#include "util/storage/slabhash.h"
#include "sldns/sbuffer.h"
@@ -68,6 +69,8 @@ context_finalize(struct ub_ctx* ctx)
return UB_NOMEM;
if(!local_zones_apply_cfg(ctx->local_zones, cfg))
return UB_INITFAIL;
+ if(!auth_zones_apply_cfg(ctx->env->auth_zones, cfg, 1))
+ return UB_INITFAIL;
if(!ctx->env->msg_cache ||
cfg->msg_cache_size != slabhash_get_size(ctx->env->msg_cache) ||
cfg->msg_cache_slabs != ctx->env->msg_cache->size) {
diff --git a/libunbound/libunbound.c b/libunbound/libunbound.c
index 9b4dcab15794..b4cd7fa0bcc2 100644
--- a/libunbound/libunbound.c
+++ b/libunbound/libunbound.c
@@ -62,6 +62,7 @@
#include "services/localzone.h"
#include "services/cache/infra.h"
#include "services/cache/rrset.h"
+#include "services/authzone.h"
#include "sldns/sbuffer.h"
#ifdef HAVE_PTHREAD
#include <signal.h>
@@ -88,6 +89,7 @@ static struct ub_ctx* ub_ctx_create_nopipe(void)
WSADATA wsa_data;
#endif
+ checklock_start();
log_init(NULL, 0, NULL); /* logs to stderr */
log_ident_set("libunbound");
#ifdef USE_WINSOCK
@@ -141,6 +143,16 @@ static struct ub_ctx* ub_ctx_create_nopipe(void)
errno = ENOMEM;
return NULL;
}
+ ctx->env->auth_zones = auth_zones_create();
+ if(!ctx->env->auth_zones) {
+ edns_known_options_delete(ctx->env);
+ config_delete(ctx->env->cfg);
+ free(ctx->env);
+ ub_randfree(ctx->seed_rnd);
+ free(ctx);
+ errno = ENOMEM;
+ return NULL;
+ }
ctx->env->alloc = &ctx->superalloc;
ctx->env->worker = NULL;
ctx->env->need_to_validate = 0;
@@ -310,6 +322,7 @@ ub_ctx_delete(struct ub_ctx* ctx)
infra_delete(ctx->env->infra_cache);
config_delete(ctx->env->cfg);
edns_known_options_delete(ctx->env);
+ auth_zones_delete(ctx->env->auth_zones);
free(ctx->env);
}
ub_randfree(ctx->seed_rnd);
diff --git a/libunbound/libworker.c b/libunbound/libworker.c
index 4067ef4d2853..2c7b2cf072ac 100644
--- a/libunbound/libworker.c
+++ b/libunbound/libworker.c
@@ -55,6 +55,7 @@
#include "services/localzone.h"
#include "services/cache/rrset.h"
#include "services/outbound_list.h"
+#include "services/authzone.h"
#include "util/fptr_wlist.h"
#include "util/module.h"
#include "util/regional.h"
@@ -158,7 +159,8 @@ libworker_setup(struct ub_ctx* ctx, int is_bg, struct ub_event_base* eb)
w->env->hints = NULL;
}
if(cfg->ssl_upstream) {
- w->sslctx = connect_sslctx_create(NULL, NULL, NULL);
+ w->sslctx = connect_sslctx_create(NULL, NULL,
+ cfg->tls_cert_bundle);
if(!w->sslctx) {
/* to make the setup fail after unlock */
hints_delete(w->env->hints);
@@ -214,6 +216,7 @@ libworker_setup(struct ub_ctx* ctx, int is_bg, struct ub_event_base* eb)
libworker_delete(w);
return NULL;
}
+ w->env->worker_base = w->base;
if(!w->is_bg || w->is_bg_thread) {
lock_basic_lock(&ctx->cfglock);
}
@@ -235,6 +238,7 @@ libworker_setup(struct ub_ctx* ctx, int is_bg, struct ub_event_base* eb)
cfg->outgoing_tcp_mss, &libworker_alloc_cleanup, w,
cfg->do_udp || cfg->udp_upstream_without_downstream, w->sslctx,
cfg->delay_close, NULL);
+ w->env->outnet = w->back;
if(!w->is_bg || w->is_bg_thread) {
lock_basic_unlock(&ctx->cfglock);
}
@@ -419,25 +423,6 @@ int libworker_bg(struct ub_ctx* ctx)
return UB_NOERROR;
}
-/** get msg reply struct (in temp region) */
-static struct reply_info*
-parse_reply(sldns_buffer* pkt, struct regional* region, struct query_info* qi)
-{
- struct reply_info* rep;
- struct msg_parse* msg;
- if(!(msg = regional_alloc(region, sizeof(*msg)))) {
- return NULL;
- }
- memset(msg, 0, sizeof(*msg));
- sldns_buffer_set_position(pkt, 0);
- if(parse_packet(pkt, msg, region) != 0)
- return 0;
- if(!parse_create_msg(pkt, msg, NULL, qi, &rep, region)) {
- return 0;
- }
- return rep;
-}
-
/** insert canonname */
static int
fill_canon(struct ub_result* res, uint8_t* s)
@@ -511,7 +496,7 @@ libworker_enter_result(struct ub_result* res, sldns_buffer* buf,
struct query_info rq;
struct reply_info* rep;
res->rcode = LDNS_RCODE_SERVFAIL;
- rep = parse_reply(buf, temp, &rq);
+ rep = parse_reply_in_temp_region(buf, temp, &rq);
if(!rep) {
log_err("cannot parse buf");
return; /* error parsing buf, or out of memory */
@@ -621,6 +606,15 @@ int libworker_fg(struct ub_ctx* ctx, struct ctx_query* q)
free(qinfo.qname);
return UB_NOERROR;
}
+ if(ctx->env->auth_zones && auth_zones_answer(ctx->env->auth_zones,
+ w->env, &qinfo, &edns, w->back->udp_buff, w->env->scratch)) {
+ regional_free_all(w->env->scratch);
+ libworker_fillup_fg(q, LDNS_RCODE_NOERROR,
+ w->back->udp_buff, sec_status_insecure, NULL);
+ libworker_delete(w);
+ free(qinfo.qname);
+ return UB_NOERROR;
+ }
/* process new query */
if(!mesh_new_callback(w->env->mesh, &qinfo, qflags, &edns,
w->back->udp_buff, qid, libworker_fg_done_cb, q)) {
@@ -691,6 +685,14 @@ int libworker_attach_mesh(struct ub_ctx* ctx, struct ctx_query* q,
w->back->udp_buff, sec_status_insecure, NULL);
return UB_NOERROR;
}
+ if(ctx->env->auth_zones && auth_zones_answer(ctx->env->auth_zones,
+ w->env, &qinfo, &edns, w->back->udp_buff, w->env->scratch)) {
+ regional_free_all(w->env->scratch);
+ free(qinfo.qname);
+ libworker_event_done_cb(q, LDNS_RCODE_NOERROR,
+ w->back->udp_buff, sec_status_insecure, NULL);
+ return UB_NOERROR;
+ }
/* process new query */
if(async_id)
*async_id = q->querynum;
@@ -812,6 +814,14 @@ handle_newq(struct libworker* w, uint8_t* buf, uint32_t len)
free(qinfo.qname);
return;
}
+ if(w->ctx->env->auth_zones && auth_zones_answer(w->ctx->env->auth_zones,
+ w->env, &qinfo, &edns, w->back->udp_buff, w->env->scratch)) {
+ regional_free_all(w->env->scratch);
+ q->msg_security = sec_status_insecure;
+ add_bg_result(w, q, w->back->udp_buff, UB_NOERROR, NULL);
+ free(qinfo.qname);
+ return;
+ }
q->w = w;
/* process new query */
if(!mesh_new_callback(w->env->mesh, &qinfo, qflags, &edns,
diff --git a/services/authzone.c b/services/authzone.c
index 88beddbf9229..1da924d841ea 100644
--- a/services/authzone.c
+++ b/services/authzone.c
@@ -44,26 +44,55 @@
#include "config.h"
#include "services/authzone.h"
#include "util/data/dname.h"
+#include "util/data/msgparse.h"
#include "util/data/msgreply.h"
+#include "util/data/msgencode.h"
#include "util/data/packed_rrset.h"
#include "util/regional.h"
#include "util/net_help.h"
+#include "util/netevent.h"
#include "util/config_file.h"
#include "util/log.h"
+#include "util/module.h"
+#include "util/random.h"
#include "services/cache/dns.h"
+#include "services/outside_network.h"
+#include "services/listen_dnsport.h"
+#include "services/mesh.h"
#include "sldns/rrdef.h"
#include "sldns/pkthdr.h"
#include "sldns/sbuffer.h"
#include "sldns/str2wire.h"
#include "sldns/wire2str.h"
#include "sldns/parseutil.h"
+#include "sldns/keyraw.h"
#include "validator/val_nsec3.h"
#include "validator/val_secalgo.h"
+#include <ctype.h>
/** bytes to use for NSEC3 hash buffer. 20 for sha1 */
#define N3HASHBUFLEN 32
/** max number of CNAMEs we are willing to follow (in one answer) */
#define MAX_CNAME_CHAIN 8
+/** timeout for probe packets for SOA */
+#define AUTH_PROBE_TIMEOUT 100 /* msec */
+/** when to stop with SOA probes (when exponential timeouts exceed this) */
+#define AUTH_PROBE_TIMEOUT_STOP 1000 /* msec */
+/* auth transfer timeout for TCP connections, in msec */
+#define AUTH_TRANSFER_TIMEOUT 10000 /* msec */
+/* auth transfer max backoff for failed tranfers and probes */
+#define AUTH_TRANSFER_MAX_BACKOFF 86400 /* sec */
+/* auth http port number */
+#define AUTH_HTTP_PORT 80
+/* auth https port number */
+#define AUTH_HTTPS_PORT 443
+
+/** 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);
+/** 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);
/** create new dns_msg */
static struct dns_msg*
@@ -252,9 +281,11 @@ struct auth_zones* auth_zones_create(void)
return NULL;
}
rbtree_init(&az->ztree, &auth_zone_cmp);
+ rbtree_init(&az->xtree, &auth_xfer_cmp);
lock_rw_init(&az->lock);
lock_protect(&az->lock, &az->ztree, sizeof(az->ztree));
- /* also lock protects the rbnode's in struct auth_zone */
+ lock_protect(&az->lock, &az->xtree, sizeof(az->xtree));
+ /* also lock protects the rbnode's in struct auth_zone, auth_xfer */
return az;
}
@@ -285,6 +316,23 @@ int auth_data_cmp(const void* z1, const void* z2)
b->namelabs, &m);
}
+int auth_xfer_cmp(const void* z1, const void* z2)
+{
+ /* first sort on class, so that hierarchy can be maintained within
+ * a class */
+ struct auth_xfer* a = (struct auth_xfer*)z1;
+ struct auth_xfer* b = (struct auth_xfer*)z2;
+ int m;
+ if(a->dclass != b->dclass) {
+ if(a->dclass < b->dclass)
+ return -1;
+ return 1;
+ }
+ /* sorted such that higher zones sort before lower zones (their
+ * contents) */
+ return dname_lab_cmp(a->name, a->namelabs, b->name, b->namelabs, &m);
+}
+
/** delete auth rrset node */
static void
auth_rrset_delete(struct auth_rrset* rrset)
@@ -374,6 +422,19 @@ auth_zone_find(struct auth_zones* az, uint8_t* nm, size_t nmlen,
return (struct auth_zone*)rbtree_search(&az->ztree, &key);
}
+struct auth_xfer*
+auth_xfer_find(struct auth_zones* az, uint8_t* nm, size_t nmlen,
+ uint16_t dclass)
+{
+ struct auth_xfer key;
+ key.node.key = &key;
+ key.dclass = dclass;
+ key.name = nm;
+ key.namelen = nmlen;
+ key.namelabs = dname_count_labels(nm);
+ return (struct auth_xfer*)rbtree_search(&az->xtree, &key);
+}
+
/** find an auth zone or sorted less-or-equal, return true if exact */
static int
auth_zone_find_less_equal(struct auth_zones* az, uint8_t* nm, size_t nmlen,
@@ -388,30 +449,36 @@ auth_zone_find_less_equal(struct auth_zones* az, uint8_t* nm, size_t nmlen,
return rbtree_find_less_equal(&az->ztree, &key, (rbnode_type**)z);
}
-/** find the auth zone that is above the given qname */
+
+/** find the auth zone that is above the given name */
struct auth_zone*
-auth_zones_find_zone(struct auth_zones* az, struct query_info* qinfo)
+auth_zones_find_zone(struct auth_zones* az, uint8_t* name, size_t name_len,
+ uint16_t dclass)
{
- uint8_t* nm = qinfo->qname;
- size_t nmlen = qinfo->qname_len;
+ uint8_t* nm = name;
+ size_t nmlen = name_len;
struct auth_zone* z;
- if(auth_zone_find_less_equal(az, nm, nmlen, qinfo->qclass, &z)) {
+ if(auth_zone_find_less_equal(az, nm, nmlen, dclass, &z)) {
/* exact match */
return z;
} else {
/* less-or-nothing */
if(!z) return NULL; /* nothing smaller, nothing above it */
- /* we found smaller name; smaller may be above the qname,
+ /* we found smaller name; smaller may be above the name,
* but not below it. */
- nm = dname_get_shared_topdomain(z->name, qinfo->qname);
+ nm = dname_get_shared_topdomain(z->name, name);
dname_count_size_labels(nm, &nmlen);
+ z = NULL;
}
+
/* search up */
- while(!z && !dname_is_root(nm)) {
+ while(!z) {
+ z = auth_zone_find(az, nm, nmlen, dclass);
+ if(z) return z;
+ if(dname_is_root(nm)) break;
dname_remove_label(&nm, &nmlen);
- z = auth_zone_find(az, nm, nmlen, qinfo->qclass);
}
- return z;
+ return NULL;
}
/** find or create zone with name str. caller must have lock on az.
@@ -437,6 +504,22 @@ auth_zones_find_or_add_zone(struct auth_zones* az, char* name)
return z;
}
+/** find or create xfer zone with name str. caller must have lock on az.
+ * returns a locked xfer */
+static struct auth_xfer*
+auth_zones_find_or_add_xfer(struct auth_zones* az, struct auth_zone* z)
+{
+ struct auth_xfer* x;
+ x = auth_xfer_find(az, z->name, z->namelen, z->dclass);
+ if(!x) {
+ /* not found, create the zone */
+ x = auth_xfer_create(az, z);
+ } else {
+ lock_basic_lock(&x->lock);
+ }
+ return x;
+}
+
int
auth_zone_set_zonefile(struct auth_zone* z, char* zonefile)
{
@@ -564,6 +647,40 @@ domain_remove_rrset(struct auth_data* node, uint16_t rr_type)
}
}
+/** find an rr index in the rrset. returns true if found */
+static int
+az_rrset_find_rr(struct packed_rrset_data* d, uint8_t* rdata, size_t len,
+ size_t* index)
+{
+ size_t i;
+ for(i=0; i<d->count; i++) {
+ if(d->rr_len[i] != len)
+ continue;
+ if(memcmp(d->rr_data[i], rdata, len) == 0) {
+ *index = i;
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/** find an rrsig index in the rrset. returns true if found */
+static int
+az_rrset_find_rrsig(struct packed_rrset_data* d, uint8_t* rdata, size_t len,
+ size_t* index)
+{
+ size_t i;
+ for(i=d->count; i<d->count + d->rrsig_count; i++) {
+ if(d->rr_len[i] != len)
+ continue;
+ if(memcmp(d->rr_data[i], rdata, len) == 0) {
+ *index = i;
+ return 1;
+ }
+ }
+ return 0;
+}
+
/** see if rdata is duplicate */
static int
rdata_duplicate(struct packed_rrset_data* d, uint8_t* rdata, size_t len)
@@ -591,6 +708,68 @@ rrsig_rdata_get_type_covered(uint8_t* rdata, size_t rdatalen)
return sldns_read_uint16(rdata+2);
}
+/** remove RR from existing RRset. Also sig, if it is a signature.
+ * reallocates the packed rrset for a new one, false on alloc failure */
+static int
+rrset_remove_rr(struct auth_rrset* rrset, size_t index)
+{
+ struct packed_rrset_data* d, *old = rrset->data;
+ size_t i;
+ if(index >= old->count + old->rrsig_count)
+ return 0; /* index out of bounds */
+ d = (struct packed_rrset_data*)calloc(1, packed_rrset_sizeof(old) - (
+ sizeof(size_t) + sizeof(uint8_t*) + sizeof(time_t) +
+ old->rr_len[index]));
+ if(!d) {
+ log_err("malloc failure");
+ return 0;
+ }
+ d->ttl = old->ttl;
+ d->count = old->count;
+ d->rrsig_count = old->rrsig_count;
+ if(index < d->count) d->count--;
+ else d->rrsig_count--;
+ d->trust = old->trust;
+ d->security = old->security;
+
+ /* set rr_len, needed for ptr_fixup */
+ d->rr_len = (size_t*)((uint8_t*)d +
+ sizeof(struct packed_rrset_data));
+ if(index > 0)
+ memmove(d->rr_len, old->rr_len, (index)*sizeof(size_t));
+ if(index+1 < old->count+old->rrsig_count)
+ memmove(&d->rr_len[index], &old->rr_len[index+1],
+ (old->count+old->rrsig_count - (index+1))*sizeof(size_t));
+ packed_rrset_ptr_fixup(d);
+
+ /* move over ttls */
+ if(index > 0)
+ memmove(d->rr_ttl, old->rr_ttl, (index)*sizeof(time_t));
+ if(index+1 < old->count+old->rrsig_count)
+ memmove(&d->rr_ttl[index], &old->rr_ttl[index+1],
+ (old->count+old->rrsig_count - (index+1))*sizeof(time_t));
+
+ /* move over rr_data */
+ for(i=0; i<d->count+d->rrsig_count; i++) {
+ size_t oldi;
+ if(i < index) oldi = i;
+ else oldi = i+1;
+ memmove(d->rr_data[i], old->rr_data[oldi], d->rr_len[i]);
+ }
+
+ /* recalc ttl (lowest of remaining RR ttls) */
+ if(d->count + d->rrsig_count > 0)
+ d->ttl = d->rr_ttl[0];
+ for(i=0; i<d->count+d->rrsig_count; i++) {
+ if(d->rr_ttl[i] < d->ttl)
+ d->ttl = d->rr_ttl[i];
+ }
+
+ free(rrset->data);
+ rrset->data = d;
+ return 1;
+}
+
/** add RR to existing RRset. If insert_sig is true, add to rrsigs.
* This reallocates the packed rrset for a new one */
static int
@@ -750,7 +929,6 @@ rrset_moveover_rrsigs(struct auth_data* node, uint16_t rr_type,
/* 0 rrsigs to move over, done */
return 1;
}
- log_info("moveover %d sigs size %d", (int)sigs, (int)sigsz);
/* allocate rrset sigsz larger for extra sigs elements, and
* allocate rrsig sigsz smaller for less sigs elements. */
@@ -867,11 +1045,38 @@ rrset_moveover_rrsigs(struct auth_data* node, uint16_t rr_type,
return 1;
}
+/** copy the rrsigs from the rrset to the rrsig rrset, because the rrset
+ * is going to be deleted. reallocates the RRSIG rrset data. */
+static int
+rrsigs_copy_from_rrset_to_rrsigset(struct auth_rrset* rrset,
+ struct auth_rrset* rrsigset)
+{
+ size_t i;
+ if(rrset->data->rrsig_count == 0)
+ return 1;
+
+ /* move them over one by one, because there might be duplicates,
+ * duplicates are ignored */
+ for(i=rrset->data->count;
+ i<rrset->data->count+rrset->data->rrsig_count; i++) {
+ uint8_t* rdata = rrset->data->rr_data[i];
+ size_t rdatalen = rrset->data->rr_len[i];
+ time_t rr_ttl = rrset->data->rr_ttl[i];
+
+ if(rdata_duplicate(rrsigset->data, rdata, rdatalen)) {
+ continue;
+ }
+ if(!rrset_add_rr(rrsigset, rr_ttl, rdata, rdatalen, 0))
+ return 0;
+ }
+ return 1;
+}
+
/** Add rr to node, ignores duplicate RRs,
* rdata points to buffer with rdatalen octets, starts with 2bytelength. */
static int
az_domain_add_rr(struct auth_data* node, uint16_t rr_type, uint32_t rr_ttl,
- uint8_t* rdata, size_t rdatalen)
+ uint8_t* rdata, size_t rdatalen, int* duplicate)
{
struct auth_rrset* rrset;
/* packed rrsets have their rrsigs along with them, sort them out */
@@ -880,14 +1085,18 @@ az_domain_add_rr(struct auth_data* node, uint16_t rr_type, uint32_t rr_ttl,
if((rrset=az_domain_rrset(node, ctype))!= NULL) {
/* a node of the correct type exists, add the RRSIG
* to the rrset of the covered data type */
- if(rdata_duplicate(rrset->data, rdata, rdatalen))
+ if(rdata_duplicate(rrset->data, rdata, rdatalen)) {
+ if(duplicate) *duplicate = 1;
return 1;
+ }
if(!rrset_add_rr(rrset, rr_ttl, rdata, rdatalen, 1))
return 0;
} else if((rrset=az_domain_rrset(node, rr_type))!= NULL) {
/* add RRSIG to rrset of type RRSIG */
- if(rdata_duplicate(rrset->data, rdata, rdatalen))
+ if(rdata_duplicate(rrset->data, rdata, rdatalen)) {
+ if(duplicate) *duplicate = 1;
return 1;
+ }
if(!rrset_add_rr(rrset, rr_ttl, rdata, rdatalen, 0))
return 0;
} else {
@@ -900,8 +1109,10 @@ az_domain_add_rr(struct auth_data* node, uint16_t rr_type, uint32_t rr_ttl,
/* normal RR type */
if((rrset=az_domain_rrset(node, rr_type))!= NULL) {
/* add data to existing node with data type */
- if(rdata_duplicate(rrset->data, rdata, rdatalen))
+ if(rdata_duplicate(rrset->data, rdata, rdatalen)) {
+ if(duplicate) *duplicate = 1;
return 1;
+ }
if(!rrset_add_rr(rrset, rr_ttl, rdata, rdatalen, 0))
return 0;
} else {
@@ -928,7 +1139,7 @@ az_domain_add_rr(struct auth_data* node, uint16_t rr_type, uint32_t rr_ttl,
/** insert RR into zone, ignore duplicates */
static int
az_insert_rr(struct auth_zone* z, uint8_t* rr, size_t rr_len,
- size_t dname_len)
+ size_t dname_len, int* duplicate)
{
struct auth_data* node;
uint8_t* dname = rr;
@@ -948,13 +1159,273 @@ az_insert_rr(struct auth_zone* z, uint8_t* rr, size_t rr_len,
log_err("cannot create domain");
return 0;
}
- if(!az_domain_add_rr(node, rr_type, rr_ttl, rdata, rdatalen)) {
+ if(!az_domain_add_rr(node, rr_type, rr_ttl, rdata, rdatalen,
+ duplicate)) {
log_err("cannot add RR to domain");
return 0;
}
return 1;
}
+/** Remove rr from node, ignores nonexisting RRs,
+ * rdata points to buffer with rdatalen octets, starts with 2bytelength. */
+static int
+az_domain_remove_rr(struct auth_data* node, uint16_t rr_type,
+ uint8_t* rdata, size_t rdatalen, int* nonexist)
+{
+ struct auth_rrset* rrset;
+ size_t index = 0;
+
+ /* find the plain RR of the given type */
+ if((rrset=az_domain_rrset(node, rr_type))!= NULL) {
+ if(az_rrset_find_rr(rrset->data, rdata, rdatalen, &index)) {
+ if(rrset->data->count == 1 &&
+ rrset->data->rrsig_count == 0) {
+ /* last RR, delete the rrset */
+ domain_remove_rrset(node, rr_type);
+ } else if(rrset->data->count == 1 &&
+ rrset->data->rrsig_count != 0) {
+ /* move RRSIGs to the RRSIG rrset, or
+ * this one becomes that RRset */
+ struct auth_rrset* rrsigset = az_domain_rrset(
+ node, LDNS_RR_TYPE_RRSIG);
+ if(rrsigset) {
+ /* move left over rrsigs to the
+ * existing rrset of type RRSIG */
+ rrsigs_copy_from_rrset_to_rrsigset(
+ rrset, rrsigset);
+ /* and then delete the rrset */
+ domain_remove_rrset(node, rr_type);
+ } else {
+ /* no rrset of type RRSIG, this
+ * set is now of that type,
+ * just remove the rr */
+ if(!rrset_remove_rr(rrset, index))
+ return 0;
+ rrset->type = LDNS_RR_TYPE_RRSIG;
+ rrset->data->count = rrset->data->rrsig_count;
+ rrset->data->rrsig_count = 0;
+ }
+ } else {
+ /* remove the RR from the rrset */
+ if(!rrset_remove_rr(rrset, index))
+ return 0;
+ }
+ return 1;
+ }
+ /* rr not found in rrset */
+ }
+
+ /* is it a type RRSIG, look under the covered type */
+ if(rr_type == LDNS_RR_TYPE_RRSIG) {
+ uint16_t ctype = rrsig_rdata_get_type_covered(rdata, rdatalen);
+ if((rrset=az_domain_rrset(node, ctype))!= NULL) {
+ if(az_rrset_find_rrsig(rrset->data, rdata, rdatalen,
+ &index)) {
+ /* rrsig should have d->count > 0, be
+ * over some rr of that type */
+ /* remove the rrsig from the rrsigs list of the
+ * rrset */
+ if(!rrset_remove_rr(rrset, index))
+ return 0;
+ return 1;
+ }
+ }
+ /* also RRSIG not found */
+ }
+
+ /* nothing found to delete */
+ if(nonexist) *nonexist = 1;
+ return 1;
+}
+
+/** remove RR from zone, ignore if it does not exist, false on alloc failure*/
+static int
+az_remove_rr(struct auth_zone* z, uint8_t* rr, size_t rr_len,
+ size_t dname_len, int* nonexist)
+{
+ struct auth_data* node;
+ uint8_t* dname = rr;
+ uint16_t rr_type = sldns_wirerr_get_type(rr, rr_len, dname_len);
+ uint16_t rr_class = sldns_wirerr_get_class(rr, rr_len, dname_len);
+ size_t rdatalen = ((size_t)sldns_wirerr_get_rdatalen(rr, rr_len,
+ dname_len))+2;
+ /* rdata points to rdata prefixed with uint16 rdatalength */
+ uint8_t* rdata = sldns_wirerr_get_rdatawl(rr, rr_len, dname_len);
+
+ if(rr_class != z->dclass) {
+ log_err("wrong class for RR");
+ /* really also a nonexisting entry, because no records
+ * of that class in the zone, but return an error because
+ * getting records of the wrong class is a failure of the
+ * zone transfer */
+ return 0;
+ }
+ node = az_find_name(z, dname, dname_len);
+ if(!node) {
+ /* node with that name does not exist */
+ /* nonexisting entry, because no such name */
+ *nonexist = 1;
+ return 1;
+ }
+ if(!az_domain_remove_rr(node, rr_type, rdata, rdatalen, nonexist)) {
+ /* alloc failure or so */
+ return 0;
+ }
+ /* remove the node, if necessary */
+ /* an rrsets==NULL entry is not kept around for empty nonterminals,
+ * and also parent nodes are not kept around, so we just delete it */
+ if(node->rrsets == NULL) {
+ (void)rbtree_delete(&z->data, node);
+ auth_data_delete(node);
+ }
+ return 1;
+}
+
+/** decompress an RR into the buffer where it'll be an uncompressed RR
+ * with uncompressed dname and uncompressed rdata (dnames) */
+static int
+decompress_rr_into_buffer(struct sldns_buffer* buf, uint8_t* pkt,
+ size_t pktlen, uint8_t* dname, uint16_t rr_type, uint16_t rr_class,
+ uint32_t rr_ttl, uint8_t* rr_data, uint16_t rr_rdlen)
+{
+ sldns_buffer pktbuf;
+ size_t dname_len = 0;
+ size_t rdlenpos;
+ size_t rdlen;
+ uint8_t* rd;
+ const sldns_rr_descriptor* desc;
+ sldns_buffer_init_frm_data(&pktbuf, pkt, pktlen);
+ sldns_buffer_clear(buf);
+
+ /* decompress dname */
+ sldns_buffer_set_position(&pktbuf,
+ (size_t)(dname - sldns_buffer_current(&pktbuf)));
+ dname_len = pkt_dname_len(&pktbuf);
+ if(dname_len == 0) return 0; /* parse fail on dname */
+ if(!sldns_buffer_available(buf, dname_len)) return 0;
+ dname_pkt_copy(&pktbuf, sldns_buffer_current(buf), dname);
+ sldns_buffer_skip(buf, (ssize_t)dname_len);
+
+ /* type, class, ttl and rdatalength fields */
+ if(!sldns_buffer_available(buf, 10)) return 0;
+ sldns_buffer_write_u16(buf, rr_type);
+ sldns_buffer_write_u16(buf, rr_class);
+ sldns_buffer_write_u32(buf, rr_ttl);
+ rdlenpos = sldns_buffer_position(buf);
+ sldns_buffer_write_u16(buf, 0); /* rd length position */
+
+ /* decompress rdata */
+ desc = sldns_rr_descript(rr_type);
+ rd = rr_data;
+ rdlen = rr_rdlen;
+ if(rdlen > 0 && desc && desc->_dname_count > 0) {
+ int count = (int)desc->_dname_count;
+ int rdf = 0;
+ size_t len; /* how much rdata to plain copy */
+ size_t uncompressed_len, compressed_len;
+ size_t oldpos;
+ /* decompress dnames. */
+ while(rdlen > 0 && count) {
+ switch(desc->_wireformat[rdf]) {
+ case LDNS_RDF_TYPE_DNAME:
+ sldns_buffer_set_position(&pktbuf,
+ (size_t)(rd -
+ sldns_buffer_begin(&pktbuf)));
+ oldpos = sldns_buffer_position(&pktbuf);
+ /* moves pktbuf to right after the
+ * compressed dname, and returns uncompressed
+ * dname length */
+ uncompressed_len = pkt_dname_len(&pktbuf);
+ if(!uncompressed_len)
+ return 0; /* parse error in dname */
+ if(!sldns_buffer_available(buf,
+ uncompressed_len))
+ /* dname too long for buffer */
+ return 0;
+ dname_pkt_copy(&pktbuf,
+ sldns_buffer_current(buf), rd);
+ sldns_buffer_skip(buf, (ssize_t)uncompressed_len);
+ compressed_len = sldns_buffer_position(
+ &pktbuf) - oldpos;
+ rd += compressed_len;
+ rdlen -= compressed_len;
+ count--;
+ len = 0;
+ break;
+ case LDNS_RDF_TYPE_STR:
+ len = rd[0] + 1;
+ break;
+ default:
+ len = get_rdf_size(desc->_wireformat[rdf]);
+ break;
+ }
+ if(len) {
+ if(!sldns_buffer_available(buf, len))
+ return 0; /* too long for buffer */
+ sldns_buffer_write(buf, rd, len);
+ rd += len;
+ rdlen -= len;
+ }
+ rdf++;
+ }
+ }
+ /* copy remaining data */
+ if(rdlen > 0) {
+ if(!sldns_buffer_available(buf, rdlen)) return 0;
+ sldns_buffer_write(buf, rd, rdlen);
+ }
+ /* fixup rdlength */
+ sldns_buffer_write_u16_at(buf, rdlenpos,
+ sldns_buffer_position(buf)-rdlenpos-2);
+ sldns_buffer_flip(buf);
+ return 1;
+}
+
+/** insert RR into zone, from packet, decompress RR,
+ * if duplicate is nonNULL set the flag but otherwise ignore duplicates */
+static int
+az_insert_rr_decompress(struct auth_zone* z, uint8_t* pkt, size_t pktlen,
+ struct sldns_buffer* scratch_buffer, uint8_t* dname, uint16_t rr_type,
+ uint16_t rr_class, uint32_t rr_ttl, uint8_t* rr_data,
+ uint16_t rr_rdlen, int* duplicate)
+{
+ uint8_t* rr;
+ size_t rr_len;
+ size_t dname_len;
+ if(!decompress_rr_into_buffer(scratch_buffer, pkt, pktlen, dname,
+ rr_type, rr_class, rr_ttl, rr_data, rr_rdlen)) {
+ log_err("could not decompress RR");
+ return 0;
+ }
+ rr = sldns_buffer_begin(scratch_buffer);
+ rr_len = sldns_buffer_limit(scratch_buffer);
+ dname_len = dname_valid(rr, rr_len);
+ return az_insert_rr(z, rr, rr_len, dname_len, duplicate);
+}
+
+/** remove RR from zone, from packet, decompress RR,
+ * if nonexist is nonNULL set the flag but otherwise ignore nonexisting entries*/
+static int
+az_remove_rr_decompress(struct auth_zone* z, uint8_t* pkt, size_t pktlen,
+ struct sldns_buffer* scratch_buffer, uint8_t* dname, uint16_t rr_type,
+ uint16_t rr_class, uint32_t rr_ttl, uint8_t* rr_data,
+ uint16_t rr_rdlen, int* nonexist)
+{
+ uint8_t* rr;
+ size_t rr_len;
+ size_t dname_len;
+ if(!decompress_rr_into_buffer(scratch_buffer, pkt, pktlen, dname,
+ rr_type, rr_class, rr_ttl, rr_data, rr_rdlen)) {
+ log_err("could not decompress RR");
+ return 0;
+ }
+ rr = sldns_buffer_begin(scratch_buffer);
+ rr_len = sldns_buffer_limit(scratch_buffer);
+ dname_len = dname_valid(rr, rr_len);
+ return az_remove_rr(z, rr, rr_len, dname_len, nonexist);
+}
+
/**
* Parse zonefile
* @param z: zone to read in.
@@ -991,6 +1462,11 @@ az_parse_file(struct auth_zone* z, FILE* in, uint8_t* rr, size_t rrbuflen,
/* skip spaces */
while(*incfile == ' ' || *incfile == '\t')
incfile++;
+ incfile = strdup(incfile);
+ if(!incfile) {
+ log_err("malloc failure");
+ return 0;
+ }
verbose(VERB_ALGO, "opening $INCLUDE %s",
incfile);
inc = fopen(incfile, "r");
@@ -999,6 +1475,7 @@ az_parse_file(struct auth_zone* z, FILE* in, uint8_t* rr, size_t rrbuflen,
"file %s: %s", z->zonefile,
lineno_orig, incfile,
strerror(errno));
+ free(incfile);
return 0;
}
/* recurse read that file now */
@@ -1013,6 +1490,7 @@ az_parse_file(struct auth_zone* z, FILE* in, uint8_t* rr, size_t rrbuflen,
fclose(inc);
verbose(VERB_ALGO, "done with $INCLUDE %s",
incfile);
+ free(incfile);
state->lineno = lineno_orig;
}
continue;
@@ -1028,7 +1506,7 @@ az_parse_file(struct auth_zone* z, FILE* in, uint8_t* rr, size_t rrbuflen,
continue;
}
/* insert wirerr in rrbuf */
- if(!az_insert_rr(z, rr, rr_len, dname_len)) {
+ if(!az_insert_rr(z, rr, rr_len, dname_len, NULL)) {
char buf[17];
sldns_wire2str_type_buf(sldns_wirerr_get_type(rr,
rr_len, dname_len), buf, sizeof(buf));
@@ -1048,10 +1526,21 @@ auth_zone_read_zonefile(struct auth_zone* z)
FILE* in;
if(!z || !z->zonefile || z->zonefile[0]==0)
return 1; /* no file, or "", nothing to read */
- verbose(VERB_ALGO, "read zonefile %s", z->zonefile);
+ if(verbosity >= VERB_ALGO) {
+ char nm[255+1];
+ dname_str(z->name, nm);
+ verbose(VERB_ALGO, "read zonefile %s for %s", z->zonefile, nm);
+ }
in = fopen(z->zonefile, "r");
if(!in) {
char* n = sldns_wire2str_dname(z->name, z->namelen);
+ if(z->zone_is_slave && errno == ENOENT) {
+ /* we fetch the zone contents later, no file yet */
+ verbose(VERB_ALGO, "no zonefile %s for %s",
+ z->zonefile, n?n:"error");
+ free(n);
+ return 1;
+ }
log_err("cannot open zonefile %s for %s: %s",
z->zonefile, n?n:"error", strerror(errno));
free(n);
@@ -1096,6 +1585,42 @@ write_out(FILE* out, const char* str)
return 1;
}
+/** convert auth rr to string */
+static int
+auth_rr_to_string(uint8_t* nm, size_t nmlen, uint16_t tp, uint16_t cl,
+ struct packed_rrset_data* data, size_t i, char* s, size_t buflen)
+{
+ int w = 0;
+ size_t slen = buflen, datlen;
+ uint8_t* dat;
+ if(i >= data->count) tp = LDNS_RR_TYPE_RRSIG;
+ dat = nm;
+ datlen = nmlen;
+ w += sldns_wire2str_dname_scan(&dat, &datlen, &s, &slen, NULL, 0);
+ w += sldns_str_print(&s, &slen, "\t");
+ w += sldns_str_print(&s, &slen, "%lu\t", (unsigned long)data->rr_ttl[i]);
+ w += sldns_wire2str_class_print(&s, &slen, cl);
+ w += sldns_str_print(&s, &slen, "\t");
+ w += sldns_wire2str_type_print(&s, &slen, tp);
+ w += sldns_str_print(&s, &slen, "\t");
+ datlen = data->rr_len[i]-2;
+ dat = data->rr_data[i]+2;
+ w += sldns_wire2str_rdata_scan(&dat, &datlen, &s, &slen, tp, NULL, 0);
+
+ if(tp == LDNS_RR_TYPE_DNSKEY) {
+ w += sldns_str_print(&s, &slen, " ;{id = %u}",
+ sldns_calc_keytag_raw(data->rr_data[i]+2,
+ data->rr_len[i]-2));
+ }
+ w += sldns_str_print(&s, &slen, "\n");
+
+ if(w > (int)buflen) {
+ log_nametypeclass(0, "RR too long to print", nm, tp, cl);
+ return 0;
+ }
+ return 1;
+}
+
/** write rrset to file */
static int
auth_zone_write_rrset(struct auth_zone* z, struct auth_data* node,
@@ -1104,15 +1629,8 @@ auth_zone_write_rrset(struct auth_zone* z, struct auth_data* node,
size_t i, count = r->data->count + r->data->rrsig_count;
char buf[LDNS_RR_BUF_SIZE];
for(i=0; i<count; i++) {
- struct ub_packed_rrset_key key;
- memset(&key, 0, sizeof(key));
- key.entry.key = &key;
- key.entry.data = r->data;
- key.rk.dname = node->name;
- key.rk.dname_len = node->namelen;
- key.rk.type = htons(r->type);
- key.rk.rrset_class = htons(z->dclass);
- if(!packed_rr_to_string(&key, i, 0, buf, sizeof(buf))) {
+ if(!auth_rr_to_string(node->name, node->namelen, r->type,
+ z->dclass, r->data, i, buf, sizeof(buf))) {
verbose(VERB_ALGO, "failed to rr2str rr %d", (int)i);
continue;
}
@@ -1185,68 +1703,243 @@ auth_zones_read_zones(struct auth_zones* az)
return 1;
}
-/** set str2list with (zonename, zonefile) config items and create zones */
+/** 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)
+{
+ 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 */
+ /* SOA record ends with serial, refresh, retry, expiry, minimum,
+ * as 4 byte fields */
+ d = soa->data;
+ xfr->have_zone = 1;
+ xfr->serial = sldns_read_uint32(d->rr_data[0]+(d->rr_len[0]-20));
+ xfr->refresh = sldns_read_uint32(d->rr_data[0]+(d->rr_len[0]-16));
+ xfr->retry = sldns_read_uint32(d->rr_data[0]+(d->rr_len[0]-12));
+ xfr->expiry = sldns_read_uint32(d->rr_data[0]+(d->rr_len[0]-8));
+ /* soa minimum at d->rr_len[0]-4 */
+ return 1;
+}
+
+/**
+ * Setup auth_xfer zone
+ * This populates the have_zone, soa values, and so on times.
+ * Doesn't do network traffic yet, can set option flags.
+ * @param z: locked by caller, and modified for setup
+ * @param x: locked by caller, and modified.
+ * @return false on failure.
+ */
+static int
+auth_xfer_setup(struct auth_zone* z, struct auth_xfer* x)
+{
+ /* for a zone without zone transfers, x==NULL, so skip them,
+ * i.e. the zone config is fixed with no masters or urls */
+ if(!z || !x) return 1;
+ if(!xfr_find_soa(z, x)) {
+ return 1;
+ }
+ /* nothing for probe, nextprobe and transfer tasks */
+ return 1;
+}
+
+/**
+ * Setup all zones
+ * @param az: auth zones structure
+ * @return false on failure.
+ */
static int
-auth_zones_cfg_zonefile(struct auth_zones* az, struct config_str2list* zlist)
+auth_zones_setup_zones(struct auth_zones* az)
{
struct auth_zone* z;
- while(zlist) {
- lock_rw_wrlock(&az->lock);
- if(!(z=auth_zones_find_or_add_zone(az, zlist->str))) {
- lock_rw_unlock(&az->lock);
- return 0;
+ struct auth_xfer* x;
+ lock_rw_wrlock(&az->lock);
+ RBTREE_FOR(z, struct auth_zone*, &az->ztree) {
+ lock_rw_wrlock(&z->lock);
+ x = auth_xfer_find(az, z->name, z->namelen, z->dclass);
+ if(x) {
+ lock_basic_lock(&x->lock);
}
- lock_rw_unlock(&az->lock);
- if(!auth_zone_set_zonefile(z, zlist->str2)) {
+ if(!auth_xfer_setup(z, x)) {
+ if(x) {
+ lock_basic_unlock(&x->lock);
+ }
lock_rw_unlock(&z->lock);
+ lock_rw_unlock(&az->lock);
return 0;
}
+ if(x) {
+ lock_basic_unlock(&x->lock);
+ }
lock_rw_unlock(&z->lock);
- zlist = zlist->next;
}
+ lock_rw_unlock(&az->lock);
return 1;
}
-/** set str2list with (zonename, fallback) config items and create zones */
+/** set config items and create zones */
static int
-auth_zones_cfg_fallback(struct auth_zones* az, struct config_str2list* zlist)
+auth_zones_cfg(struct auth_zones* az, struct config_auth* c)
{
struct auth_zone* z;
- while(zlist) {
- lock_rw_wrlock(&az->lock);
- if(!(z=auth_zones_find_or_add_zone(az, zlist->str))) {
+ struct auth_xfer* x = NULL;
+
+ /* create zone */
+ lock_rw_wrlock(&az->lock);
+ if(!(z=auth_zones_find_or_add_zone(az, c->name))) {
+ lock_rw_unlock(&az->lock);
+ return 0;
+ }
+ if(c->masters || c->urls) {
+ if(!(x=auth_zones_find_or_add_xfer(az, z))) {
lock_rw_unlock(&az->lock);
+ lock_rw_unlock(&z->lock);
return 0;
}
- lock_rw_unlock(&az->lock);
- if(!auth_zone_set_fallback(z, zlist->str2)) {
+ }
+ if(c->for_downstream)
+ az->have_downstream = 1;
+ lock_rw_unlock(&az->lock);
+
+ /* set options */
+ if(!auth_zone_set_zonefile(z, c->zonefile)) {
+ if(x) {
+ lock_basic_unlock(&x->lock);
+ }
+ lock_rw_unlock(&z->lock);
+ return 0;
+ }
+ z->for_downstream = c->for_downstream;
+ z->for_upstream = c->for_upstream;
+ z->fallback_enabled = c->fallback_enabled;
+
+ /* xfer zone */
+ if(x) {
+ z->zone_is_slave = 1;
+ /* set options on xfer zone */
+ if(!xfer_set_masters(&x->task_probe->masters, c, 0)) {
+ lock_basic_unlock(&x->lock);
lock_rw_unlock(&z->lock);
return 0;
}
- lock_rw_unlock(&z->lock);
- zlist = zlist->next;
+ if(!xfer_set_masters(&x->task_transfer->masters, c, 1)) {
+ lock_basic_unlock(&x->lock);
+ lock_rw_unlock(&z->lock);
+ return 0;
+ }
+ lock_basic_unlock(&x->lock);
}
+
+ lock_rw_unlock(&z->lock);
return 1;
}
-int auth_zones_apply_config(struct auth_zones* az, struct config_file* cfg)
+int auth_zones_apply_cfg(struct auth_zones* az, struct config_file* cfg,
+ int setup)
{
- (void)cfg;
- /* TODO cfg str2lists */
- /* create config items for
- * auth-zone: name: "example.com"
- * zonefile: "zones/example.com"
- * fallback: yes
- */
- if(!auth_zones_cfg_zonefile(az, NULL /*cfg->auth_zones*/))
- return 0;
- if(!auth_zones_cfg_fallback(az, NULL /*cfg->auth_zones*/))
- return 0;
+ struct config_auth* p;
+ for(p = cfg->auths; p; p = p->next) {
+ if(!p->name || p->name[0] == 0) {
+ log_warn("auth-zone without a name, skipped");
+ continue;
+ }
+ if(!auth_zones_cfg(az, p)) {
+ log_err("cannot config auth zone %s", p->name);
+ return 0;
+ }
+ }
if(!auth_zones_read_zones(az))
return 0;
+ if(setup) {
+ if(!auth_zones_setup_zones(az))
+ return 0;
+ }
return 1;
}
+/** delete chunks
+ * @param at: transfer structure with chunks list. The chunks and their
+ * data are freed.
+ */
+void
+auth_chunks_delete(struct auth_transfer* at)
+{
+ if(at->chunks_first) {
+ struct auth_chunk* c, *cn;
+ c = at->chunks_first;
+ while(c) {
+ cn = c->next;
+ free(c->data);
+ free(c);
+ c = cn;
+ }
+ }
+ at->chunks_first = NULL;
+ at->chunks_last = NULL;
+}
+
+/** free master addr list */
+static void
+auth_free_master_addrs(struct auth_addr* list)
+{
+ struct auth_addr *n;
+ while(list) {
+ n = list->next;
+ free(list);
+ list = n;
+ }
+}
+
+/** free the masters list */
+static void
+auth_free_masters(struct auth_master* list)
+{
+ struct auth_master* n;
+ while(list) {
+ n = list->next;
+ auth_free_master_addrs(list->list);
+ free(list->host);
+ free(list->file);
+ free(list);
+ list = n;
+ }
+}
+
+/** delete auth xfer structure
+ * @param xfr: delete this xfer and its tasks.
+ */
+void
+auth_xfer_delete(struct auth_xfer* xfr)
+{
+ if(!xfr) return;
+ lock_basic_destroy(&xfr->lock);
+ free(xfr->name);
+ if(xfr->task_nextprobe) {
+ comm_timer_delete(xfr->task_nextprobe->timer);
+ free(xfr->task_nextprobe);
+ }
+ if(xfr->task_probe) {
+ auth_free_masters(xfr->task_probe->masters);
+ comm_point_delete(xfr->task_probe->cp);
+ free(xfr->task_probe);
+ }
+ if(xfr->task_transfer) {
+ auth_free_masters(xfr->task_transfer->masters);
+ comm_point_delete(xfr->task_transfer->cp);
+ if(xfr->task_transfer->chunks_first) {
+ auth_chunks_delete(xfr->task_transfer);
+ }
+ free(xfr->task_transfer);
+ }
+ free(xfr);
+}
+
/** helper traverse to delete zones */
static void
auth_zone_del(rbnode_type* n, void* ATTR_UNUSED(arg))
@@ -1255,11 +1948,20 @@ auth_zone_del(rbnode_type* n, void* ATTR_UNUSED(arg))
auth_zone_delete(z);
}
+/** helper traverse to delete xfer zones */
+static void
+auth_xfer_del(rbnode_type* n, void* ATTR_UNUSED(arg))
+{
+ struct auth_xfer* z = (struct auth_xfer*)n->key;
+ auth_xfer_delete(z);
+}
+
void auth_zones_delete(struct auth_zones* az)
{
if(!az) return;
lock_rw_destroy(&az->lock);
traverse_postorder(&az->ztree, auth_zone_del, NULL);
+ traverse_postorder(&az->xtree, auth_xfer_del, NULL);
free(az);
}
@@ -1360,9 +2062,9 @@ az_domain_go_up(struct auth_zone* z, struct auth_data* n)
* return true if the node (param node) is existing, nonobscured and
* can be used to generate answers from. It is then also node_exact.
* returns false if the node is not good enough (or it wasn't node_exact)
- * in this case the ce can be filled.
- * if ce is NULL, no ce exists, and likely the zone is completely empty,
- * not even with a zone apex.
+ * in this case the ce can be filled.
+ * if ce is NULL, no ce exists, and likely the zone is completely empty,
+ * not even with a zone apex.
* if ce is nonNULL it is the closest enclosing upper name (that exists
* itself for answer purposes). That name may have DNAME, NS or wildcard
* rrset is the closest DNAME or NS rrset that was found.
@@ -1848,7 +2550,7 @@ az_nsec3_find_cover(struct auth_zone* z, uint8_t* nm, size_t nmlen,
!az_domain_rrset(node, LDNS_RR_TYPE_NSEC3)) {
node = (struct auth_data*)rbtree_previous(&node->node);
}
- if((rbnode_type*)node == RBTREE_NULL)
+ if((rbnode_type*)node == RBTREE_NULL)
node = NULL;
return node;
}
@@ -2160,12 +2862,6 @@ az_generate_wildcard_answer(struct auth_zone* z, struct query_info* qinfo,
struct auth_data* wildcard, struct auth_data* node)
{
struct auth_rrset* rrset, *nsec;
- if(verbosity>=VERB_ALGO) {
- char wcname[256];
- sldns_wire2str_dname_buf(wildcard->name, wildcard->namelen,
- wcname, sizeof(wcname));
- log_info("wildcard %s", wcname);
- }
if((rrset=az_domain_rrset(wildcard, qinfo->qtype)) != NULL) {
/* wildcard has type, add it */
if(!msg_add_rrset_an(z, region, msg, wildcard, rrset))
@@ -2348,13 +3044,11 @@ int auth_zones_lookup(struct auth_zones* az, struct query_info* qinfo,
{
int r;
struct auth_zone* z;
-
/* find the zone that should contain the answer. */
lock_rw_rdlock(&az->lock);
z = auth_zone_find(az, dp_nm, dp_nmlen, qinfo->qclass);
if(!z) {
lock_rw_unlock(&az->lock);
- verbose(VERB_ALGO, "no auth zone for query, fallback");
/* no auth zone, fallback to internet */
*fallback = 1;
return 0;
@@ -2362,8 +3056,2970 @@ int auth_zones_lookup(struct auth_zones* az, struct query_info* qinfo,
lock_rw_rdlock(&z->lock);
lock_rw_unlock(&az->lock);
+ /* if not for upstream queries, fallback */
+ if(!z->for_upstream) {
+ lock_rw_unlock(&z->lock);
+ *fallback = 1;
+ return 0;
+ }
/* see what answer that zone would generate */
r = auth_zone_generate_answer(z, qinfo, region, msg, fallback);
lock_rw_unlock(&z->lock);
return r;
}
+
+/** encode auth answer */
+static void
+auth_answer_encode(struct query_info* qinfo, struct module_env* env,
+ struct edns_data* edns, sldns_buffer* buf, struct regional* temp,
+ struct dns_msg* msg)
+{
+ uint16_t udpsize;
+ udpsize = edns->udp_size;
+ edns->edns_version = EDNS_ADVERTISED_VERSION;
+ edns->udp_size = EDNS_ADVERTISED_SIZE;
+ edns->ext_rcode = 0;
+ edns->bits &= EDNS_DO;
+
+ if(!inplace_cb_reply_local_call(env, qinfo, NULL, msg->rep,
+ (int)FLAGS_GET_RCODE(msg->rep->flags), edns, temp)
+ || !reply_info_answer_encode(qinfo, msg->rep,
+ *(uint16_t*)sldns_buffer_begin(buf),
+ sldns_buffer_read_u16_at(buf, 2),
+ buf, 0, 0, temp, udpsize, edns,
+ (int)(edns->bits&EDNS_DO), 0)) {
+ error_encode(buf, (LDNS_RCODE_SERVFAIL|BIT_AA), qinfo,
+ *(uint16_t*)sldns_buffer_begin(buf),
+ sldns_buffer_read_u16_at(buf, 2), edns);
+ }
+}
+
+/** encode auth error answer */
+static void
+auth_error_encode(struct query_info* qinfo, struct module_env* env,
+ struct edns_data* edns, sldns_buffer* buf, struct regional* temp,
+ int rcode)
+{
+ edns->edns_version = EDNS_ADVERTISED_VERSION;
+ edns->udp_size = EDNS_ADVERTISED_SIZE;
+ edns->ext_rcode = 0;
+ edns->bits &= EDNS_DO;
+
+ if(!inplace_cb_reply_local_call(env, qinfo, NULL, NULL,
+ rcode, edns, temp))
+ edns->opt_list = NULL;
+ error_encode(buf, rcode|BIT_AA, qinfo,
+ *(uint16_t*)sldns_buffer_begin(buf),
+ sldns_buffer_read_u16_at(buf, 2), edns);
+}
+
+int auth_zones_answer(struct auth_zones* az, struct module_env* env,
+ struct query_info* qinfo, struct edns_data* edns, struct sldns_buffer* buf,
+ struct regional* temp)
+{
+ struct dns_msg* msg = NULL;
+ struct auth_zone* z;
+ int r;
+ int fallback = 0;
+
+ lock_rw_rdlock(&az->lock);
+ if(!az->have_downstream) {
+ /* no downstream auth zones */
+ lock_rw_unlock(&az->lock);
+ return 0;
+ }
+ if(qinfo->qtype == LDNS_RR_TYPE_DS) {
+ uint8_t* delname = qinfo->qname;
+ size_t delnamelen = qinfo->qname_len;
+ dname_remove_label(&delname, &delnamelen);
+ z = auth_zones_find_zone(az, delname, delnamelen,
+ qinfo->qclass);
+ } else {
+ z = auth_zones_find_zone(az, qinfo->qname, qinfo->qname_len,
+ qinfo->qclass);
+ }
+ if(!z) {
+ /* no zone above it */
+ lock_rw_unlock(&az->lock);
+ return 0;
+ }
+ lock_rw_rdlock(&z->lock);
+ lock_rw_unlock(&az->lock);
+ if(!z->for_downstream) {
+ lock_rw_unlock(&z->lock);
+ return 0;
+ }
+
+ /* answer it from zone z */
+ r = auth_zone_generate_answer(z, qinfo, temp, &msg, &fallback);
+ lock_rw_unlock(&z->lock);
+ if(fallback) {
+ /* fallback to regular answering (recursive) */
+ return 0;
+ }
+
+ /* encode answer */
+ if(!r)
+ auth_error_encode(qinfo, env, edns, buf, temp,
+ LDNS_RCODE_SERVFAIL);
+ else auth_answer_encode(qinfo, env, edns, buf, temp, msg);
+
+ return 1;
+}
+
+int auth_zones_can_fallback(struct auth_zones* az, uint8_t* nm, size_t nmlen,
+ uint16_t dclass)
+{
+ int r;
+ struct auth_zone* z;
+ lock_rw_rdlock(&az->lock);
+ z = auth_zone_find(az, nm, nmlen, dclass);
+ if(!z) {
+ lock_rw_unlock(&az->lock);
+ /* no such auth zone, fallback */
+ return 1;
+ }
+ lock_rw_rdlock(&z->lock);
+ lock_rw_unlock(&az->lock);
+ r = z->fallback_enabled || (!z->for_upstream);
+ lock_rw_unlock(&z->lock);
+ return r;
+}
+
+/** set a zone expired */
+static void
+auth_xfer_set_expired(struct auth_xfer* xfr, struct module_env* env,
+ int expired)
+{
+ struct auth_zone* z;
+
+ /* expire xfr */
+ lock_basic_lock(&xfr->lock);
+ xfr->zone_expired = expired;
+ lock_basic_unlock(&xfr->lock);
+
+ /* find auth_zone */
+ lock_rw_rdlock(&env->auth_zones->lock);
+ z = auth_zone_find(env->auth_zones, xfr->name, xfr->namelen,
+ xfr->dclass);
+ if(!z) {
+ lock_rw_unlock(&env->auth_zones->lock);
+ return;
+ }
+ lock_rw_wrlock(&z->lock);
+ lock_rw_unlock(&env->auth_zones->lock);
+
+ /* expire auth_zone */
+ z->zone_expired = expired;
+ lock_rw_unlock(&z->lock);
+}
+
+/** find master (from notify or probe) in list of masters */
+static struct auth_master*
+find_master_by_host(struct auth_master* list, char* host)
+{
+ struct auth_master* p;
+ for(p=list; p; p=p->next) {
+ if(strcmp(p->host, host) == 0)
+ return p;
+ }
+ return NULL;
+}
+
+/** delete the looked up auth_addrs for all the masters in the list */
+static void
+xfr_masterlist_free_addrs(struct auth_master* list)
+{
+ struct auth_master* m;
+ for(m=list; m; m=m->next) {
+ if(m->list) {
+ auth_free_master_addrs(m->list);
+ m->list = NULL;
+ }
+ }
+}
+
+/** start the lookups for task_transfer */
+static void
+xfr_transfer_start_lookups(struct auth_xfer* xfr)
+{
+ /* delete all the looked up addresses in the list */
+ xfr_masterlist_free_addrs(xfr->task_transfer->masters);
+
+ /* start lookup at the first master */
+ xfr->task_transfer->lookup_target = xfr->task_transfer->masters;
+ xfr->task_transfer->lookup_aaaa = 0;
+}
+
+/** move to the next lookup of hostname for task_transfer */
+static void
+xfr_transfer_move_to_next_lookup(struct auth_xfer* xfr, struct module_env* env)
+{
+ if(!xfr->task_transfer->lookup_target)
+ return; /* already at end of list */
+ if(!xfr->task_transfer->lookup_aaaa && env->cfg->do_ip6) {
+ /* move to lookup AAAA */
+ xfr->task_transfer->lookup_aaaa = 1;
+ return;
+ }
+ xfr->task_transfer->lookup_target =
+ xfr->task_transfer->lookup_target->next;
+ xfr->task_transfer->lookup_aaaa = 0;
+ if(!env->cfg->do_ip4 && xfr->task_transfer->lookup_target!=NULL)
+ xfr->task_transfer->lookup_aaaa = 1;
+}
+
+/** start the lookups for task_probe */
+static void
+xfr_probe_start_lookups(struct auth_xfer* xfr)
+{
+ /* delete all the looked up addresses in the list */
+ xfr_masterlist_free_addrs(xfr->task_probe->masters);
+
+ /* start lookup at the first master */
+ xfr->task_probe->lookup_target = xfr->task_probe->masters;
+ xfr->task_probe->lookup_aaaa = 0;
+}
+
+/** move to the next lookup of hostname for task_probe */
+static void
+xfr_probe_move_to_next_lookup(struct auth_xfer* xfr, struct module_env* env)
+{
+ if(!xfr->task_probe->lookup_target)
+ return; /* already at end of list */
+ if(!xfr->task_probe->lookup_aaaa && env->cfg->do_ip6) {
+ /* move to lookup AAAA */
+ xfr->task_probe->lookup_aaaa = 1;
+ return;
+ }
+ xfr->task_probe->lookup_target = xfr->task_probe->lookup_target->next;
+ xfr->task_probe->lookup_aaaa = 0;
+ if(!env->cfg->do_ip4 && xfr->task_probe->lookup_target!=NULL)
+ xfr->task_probe->lookup_aaaa = 1;
+}
+
+/** start the iteration of the task_transfer list of masters */
+static void
+xfr_transfer_start_list(struct auth_xfer* xfr, struct auth_master* spec)
+{
+ if(spec) {
+ xfr->task_transfer->scan_specific = find_master_by_host(
+ xfr->task_transfer->masters, spec->host);
+ if(xfr->task_transfer->scan_specific) {
+ xfr->task_transfer->scan_target = NULL;
+ xfr->task_transfer->scan_addr = NULL;
+ if(xfr->task_transfer->scan_specific->list)
+ xfr->task_transfer->scan_addr =
+ xfr->task_transfer->scan_specific->list;
+ return;
+ }
+ }
+ /* no specific (notified) host to scan */
+ xfr->task_transfer->scan_specific = NULL;
+ xfr->task_transfer->scan_addr = NULL;
+ /* pick up first scan target */
+ 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;
+}
+
+/** start the iteration of the task_probe list of masters */
+static void
+xfr_probe_start_list(struct auth_xfer* xfr, struct auth_master* spec)
+{
+ if(spec) {
+ xfr->task_probe->scan_specific = find_master_by_host(
+ xfr->task_probe->masters, spec->host);
+ if(xfr->task_probe->scan_specific) {
+ xfr->task_probe->scan_target = NULL;
+ xfr->task_probe->scan_addr = NULL;
+ if(xfr->task_probe->scan_specific->list)
+ xfr->task_probe->scan_addr =
+ xfr->task_probe->scan_specific->list;
+ return;
+ }
+ }
+ /* no specific (notified) host to scan */
+ xfr->task_probe->scan_specific = NULL;
+ xfr->task_probe->scan_addr = NULL;
+ /* pick up first scan target */
+ 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;
+}
+
+/** pick up the master that is being scanned right now, task_transfer */
+static struct auth_master*
+xfr_transfer_current_master(struct auth_xfer* xfr)
+{
+ if(xfr->task_transfer->scan_specific)
+ return xfr->task_transfer->scan_specific;
+ return xfr->task_transfer->scan_target;
+}
+
+/** pick up the master that is being scanned right now, task_probe */
+static struct auth_master*
+xfr_probe_current_master(struct auth_xfer* xfr)
+{
+ if(xfr->task_probe->scan_specific)
+ return xfr->task_probe->scan_specific;
+ return xfr->task_probe->scan_target;
+}
+
+/** true if at end of list, task_transfer */
+static int
+xfr_transfer_end_of_list(struct auth_xfer* xfr)
+{
+ return !xfr->task_transfer->scan_specific &&
+ !xfr->task_transfer->scan_target;
+}
+
+/** true if at end of list, task_probe */
+static int
+xfr_probe_end_of_list(struct auth_xfer* xfr)
+{
+ return !xfr->task_probe->scan_specific && !xfr->task_probe->scan_target;
+}
+
+/** move to next master in list, task_transfer */
+static void
+xfr_transfer_nextmaster(struct auth_xfer* xfr)
+{
+ if(!xfr->task_transfer->scan_specific &&
+ !xfr->task_transfer->scan_target)
+ return;
+ if(xfr->task_transfer->scan_addr) {
+ xfr->task_transfer->scan_addr =
+ xfr->task_transfer->scan_addr->next;
+ if(xfr->task_transfer->scan_addr)
+ return;
+ }
+ if(xfr->task_transfer->scan_specific) {
+ xfr->task_transfer->scan_specific = NULL;
+ xfr->task_transfer->scan_target = xfr->task_transfer->masters;
+ return;
+ }
+ if(!xfr->task_transfer->scan_target)
+ return;
+ xfr->task_transfer->scan_target = xfr->task_transfer->scan_target->next;
+ return;
+}
+
+/** move to next master in list, task_probe */
+static void
+xfr_probe_nextmaster(struct auth_xfer* xfr)
+{
+ if(!xfr->task_probe->scan_specific && !xfr->task_probe->scan_target)
+ return;
+ if(xfr->task_probe->scan_addr) {
+ xfr->task_probe->scan_addr = xfr->task_probe->scan_addr->next;
+ if(xfr->task_probe->scan_addr)
+ return;
+ }
+ if(xfr->task_probe->scan_specific) {
+ xfr->task_probe->scan_specific = NULL;
+ xfr->task_probe->scan_target = xfr->task_probe->masters;
+ return;
+ }
+ if(!xfr->task_probe->scan_target)
+ return;
+ xfr->task_probe->scan_target = xfr->task_probe->scan_target->next;
+ return;
+}
+
+/** create SOA probe packet for xfr */
+static void
+xfr_create_soa_probe_packet(struct auth_xfer* xfr, sldns_buffer* buf,
+ uint16_t id)
+{
+ struct query_info qinfo;
+
+ memset(&qinfo, 0, sizeof(qinfo));
+ qinfo.qname = xfr->name;
+ qinfo.qname_len = xfr->namelen;
+ qinfo.qtype = LDNS_RR_TYPE_SOA;
+ qinfo.qclass = xfr->dclass;
+ qinfo_query_encode(buf, &qinfo);
+ sldns_buffer_write_u16_at(buf, 0, id);
+}
+
+/** create IXFR/AXFR packet for xfr */
+static void
+xfr_create_ixfr_packet(struct auth_xfer* xfr, sldns_buffer* buf, uint16_t id,
+ struct auth_master* master)
+{
+ struct query_info qinfo;
+ uint32_t serial;
+ int have_zone;
+ have_zone = xfr->have_zone;
+ serial = xfr->serial;
+
+ memset(&qinfo, 0, sizeof(qinfo));
+ qinfo.qname = xfr->name;
+ qinfo.qname_len = xfr->namelen;
+ xfr->task_transfer->got_xfr_serial = 0;
+ xfr->task_transfer->rr_scan_num = 0;
+ xfr->task_transfer->incoming_xfr_serial = 0;
+ xfr->task_transfer->on_ixfr_is_axfr = 0;
+ xfr->task_transfer->on_ixfr = 1;
+ qinfo.qtype = LDNS_RR_TYPE_IXFR;
+ if(!have_zone || xfr->task_transfer->ixfr_fail || !master->ixfr) {
+ qinfo.qtype = LDNS_RR_TYPE_AXFR;
+ xfr->task_transfer->ixfr_fail = 0;
+ xfr->task_transfer->on_ixfr = 0;
+ }
+
+ qinfo.qclass = xfr->dclass;
+ qinfo_query_encode(buf, &qinfo);
+ sldns_buffer_write_u16_at(buf, 0, id);
+
+ /* append serial for IXFR */
+ if(qinfo.qtype == LDNS_RR_TYPE_IXFR) {
+ size_t end = sldns_buffer_limit(buf);
+ sldns_buffer_clear(buf);
+ sldns_buffer_set_position(buf, end);
+ /* auth section count 1 */
+ sldns_buffer_write_u16_at(buf, LDNS_NSCOUNT_OFF, 1);
+ /* write SOA */
+ sldns_buffer_write_u8(buf, 0xC0); /* compressed ptr to qname */
+ sldns_buffer_write_u8(buf, 0x0C);
+ sldns_buffer_write_u16(buf, LDNS_RR_TYPE_SOA);
+ sldns_buffer_write_u16(buf, qinfo.qclass);
+ sldns_buffer_write_u32(buf, 0); /* ttl */
+ sldns_buffer_write_u16(buf, 22); /* rdata length */
+ sldns_buffer_write_u8(buf, 0); /* . */
+ sldns_buffer_write_u8(buf, 0); /* . */
+ sldns_buffer_write_u32(buf, serial); /* serial */
+ sldns_buffer_write_u32(buf, 0); /* refresh */
+ sldns_buffer_write_u32(buf, 0); /* retry */
+ sldns_buffer_write_u32(buf, 0); /* expire */
+ sldns_buffer_write_u32(buf, 0); /* minimum */
+ sldns_buffer_flip(buf);
+ }
+}
+
+/** check if returned packet is OK */
+static int
+check_packet_ok(sldns_buffer* pkt, uint16_t qtype, struct auth_xfer* xfr,
+ uint32_t* serial)
+{
+ /* parse to see if packet worked, valid reply */
+
+ /* check serial number of SOA */
+ if(sldns_buffer_limit(pkt) < LDNS_HEADER_SIZE)
+ return 0;
+
+ /* check ID */
+ if(LDNS_ID_WIRE(sldns_buffer_begin(pkt)) != xfr->task_probe->id)
+ return 0;
+
+ /* check flag bits and rcode */
+ if(!LDNS_QR_WIRE(sldns_buffer_begin(pkt)))
+ return 0;
+ if(LDNS_OPCODE_WIRE(sldns_buffer_begin(pkt)) != LDNS_PACKET_QUERY)
+ return 0;
+ if(LDNS_RCODE_WIRE(sldns_buffer_begin(pkt)) != LDNS_RCODE_NOERROR)
+ return 0;
+
+ /* check qname */
+ if(LDNS_QDCOUNT(sldns_buffer_begin(pkt)) != 1)
+ return 0;
+ sldns_buffer_skip(pkt, LDNS_HEADER_SIZE);
+ if(sldns_buffer_remaining(pkt) < xfr->namelen)
+ return 0;
+ if(query_dname_compare(sldns_buffer_current(pkt), xfr->name) != 0)
+ return 0;
+ sldns_buffer_skip(pkt, (ssize_t)xfr->namelen);
+
+ /* check qtype, qclass */
+ if(sldns_buffer_remaining(pkt) < 4)
+ return 0;
+ if(sldns_buffer_read_u16(pkt) != qtype)
+ return 0;
+ if(sldns_buffer_read_u16(pkt) != xfr->dclass)
+ return 0;
+
+ if(serial) {
+ uint16_t rdlen;
+ /* read serial number, from answer section SOA */
+ if(LDNS_ANCOUNT(sldns_buffer_begin(pkt)) == 0)
+ return 0;
+ /* read from first record SOA record */
+ if(sldns_buffer_remaining(pkt) < 1)
+ return 0;
+ if(dname_pkt_compare(pkt, sldns_buffer_current(pkt),
+ xfr->name) != 0)
+ return 0;
+ if(!pkt_dname_len(pkt))
+ return 0;
+ /* type, class, ttl, rdatalen */
+ if(sldns_buffer_remaining(pkt) < 4+4+2)
+ return 0;
+ if(sldns_buffer_read_u16(pkt) != qtype)
+ return 0;
+ if(sldns_buffer_read_u16(pkt) != xfr->dclass)
+ return 0;
+ sldns_buffer_skip(pkt, 4); /* ttl */
+ rdlen = sldns_buffer_read_u16(pkt);
+ if(sldns_buffer_remaining(pkt) < rdlen)
+ return 0;
+ if(sldns_buffer_remaining(pkt) < 1)
+ return 0;
+ if(!pkt_dname_len(pkt)) /* soa name */
+ return 0;
+ if(sldns_buffer_remaining(pkt) < 1)
+ return 0;
+ if(!pkt_dname_len(pkt)) /* soa name */
+ return 0;
+ if(sldns_buffer_remaining(pkt) < 20)
+ return 0;
+ *serial = sldns_buffer_read_u32(pkt);
+ }
+ 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,
+ sldns_buffer* buf)
+{
+ int readsome = 0;
+ while(*chunk) {
+ /* more text in this chunk? */
+ if(*chunk_pos < (*chunk)->len) {
+ readsome = 1;
+ while(*chunk_pos < (*chunk)->len) {
+ char c = (char)((*chunk)->data[*chunk_pos]);
+ (*chunk_pos)++;
+ if(sldns_buffer_remaining(buf) < 2) {
+ /* buffer too short */
+ verbose(VERB_ALGO, "http chunkline, "
+ "line too long");
+ return 0;
+ }
+ sldns_buffer_write_u8(buf, (uint8_t)c);
+ if(c == '\n') {
+ /* we are done */
+ return 1;
+ }
+ }
+ }
+ /* move to next chunk */
+ *chunk = (*chunk)->next;
+ *chunk_pos = 0;
+ }
+ /* no more text */
+ if(readsome) return 1;
+ return 0;
+}
+
+/** count number of open and closed parenthesis in a chunkline */
+static int
+chunkline_count_parens(sldns_buffer* buf, size_t start)
+{
+ size_t end = sldns_buffer_position(buf);
+ size_t i;
+ int count = 0;
+ int squote = 0, dquote = 0;
+ for(i=start; i<end; i++) {
+ char c = (char)sldns_buffer_read_u8_at(buf, i);
+ if(squote && c != '\'') continue;
+ if(dquote && c != '"') continue;
+ if(c == '"')
+ dquote = !dquote; /* skip quoted part */
+ else if(c == '\'')
+ squote = !squote; /* skip quoted part */
+ else if(c == '(')
+ count ++;
+ else if(c == ')')
+ count --;
+ else if(c == ';') {
+ /* rest is a comment */
+ return count;
+ }
+ }
+ return count;
+}
+
+/** remove trailing ;... comment from a line in the chunkline buffer */
+static void
+chunkline_remove_trailcomment(sldns_buffer* buf, size_t start)
+{
+ size_t end = sldns_buffer_position(buf);
+ size_t i;
+ int squote = 0, dquote = 0;
+ for(i=start; i<end; i++) {
+ char c = (char)sldns_buffer_read_u8_at(buf, i);
+ if(squote && c != '\'') continue;
+ if(dquote && c != '"') continue;
+ if(c == '"')
+ dquote = !dquote; /* skip quoted part */
+ else if(c == '\'')
+ squote = !squote; /* skip quoted part */
+ else if(c == ';') {
+ /* rest is a comment */
+ sldns_buffer_set_position(buf, i);
+ return;
+ }
+ }
+ /* nothing to remove */
+}
+
+/** see if a chunkline is a comment line (or empty line) */
+static int
+chunkline_is_comment_line_or_empty(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 == ';')
+ return 1; /* comment */
+ else if(c != ' ' && c != '\t' && c != '\r' && c != '\n')
+ return 0; /* not a comment */
+ }
+ return 1; /* empty */
+}
+
+/** find a line with ( ) collated */
+static int
+chunkline_get_line_collated(struct auth_chunk** chunk, size_t* chunk_pos,
+ sldns_buffer* buf)
+{
+ size_t pos;
+ int parens = 0;
+ sldns_buffer_clear(buf);
+ pos = sldns_buffer_position(buf);
+ if(!chunkline_get_line(chunk, chunk_pos, buf)) {
+ if(sldns_buffer_position(buf) < sldns_buffer_limit(buf))
+ sldns_buffer_write_u8_at(buf, sldns_buffer_position(buf), 0);
+ else sldns_buffer_write_u8_at(buf, sldns_buffer_position(buf)-1, 0);
+ sldns_buffer_flip(buf);
+ return 0;
+ }
+ parens += chunkline_count_parens(buf, pos);
+ while(parens > 0) {
+ chunkline_remove_trailcomment(buf, pos);
+ pos = sldns_buffer_position(buf);
+ if(!chunkline_get_line(chunk, chunk_pos, buf)) {
+ if(sldns_buffer_position(buf) < sldns_buffer_limit(buf))
+ sldns_buffer_write_u8_at(buf, sldns_buffer_position(buf), 0);
+ else sldns_buffer_write_u8_at(buf, sldns_buffer_position(buf)-1, 0);
+ sldns_buffer_flip(buf);
+ return 0;
+ }
+ parens += chunkline_count_parens(buf, pos);
+ }
+
+ if(sldns_buffer_remaining(buf) < 1) {
+ verbose(VERB_ALGO, "http chunkline: "
+ "line too long");
+ return 0;
+ }
+ sldns_buffer_write_u8_at(buf, sldns_buffer_position(buf), 0);
+ sldns_buffer_flip(buf);
+ return 1;
+}
+
+/** process $ORIGIN for http */
+static int
+http_parse_origin(sldns_buffer* buf, struct sldns_file_parse_state* pstate)
+{
+ char* line = (char*)sldns_buffer_begin(buf);
+ if(strncmp(line, "$ORIGIN", 7) == 0 &&
+ isspace((unsigned char)line[7])) {
+ int s;
+ pstate->origin_len = sizeof(pstate->origin);
+ s = sldns_str2wire_dname_buf(sldns_strip_ws(line+8),
+ pstate->origin, &pstate->origin_len);
+ if(s) pstate->origin_len = 0;
+ return 1;
+ }
+ return 0;
+}
+
+/** process $TTL for http */
+static int
+http_parse_ttl(sldns_buffer* buf, struct sldns_file_parse_state* pstate)
+{
+ char* line = (char*)sldns_buffer_begin(buf);
+ if(strncmp(line, "$TTL", 4) == 0 &&
+ isspace((unsigned char)line[4])) {
+ const char* end = NULL;
+ pstate->default_ttl = sldns_str2period(
+ sldns_strip_ws(line+5), &end);
+ return 1;
+ }
+ return 0;
+}
+
+/** find noncomment RR line in chunks, collates lines if ( ) format */
+static int
+chunkline_non_comment_RR(struct auth_chunk** chunk, size_t* chunk_pos,
+ sldns_buffer* buf, struct sldns_file_parse_state* pstate)
+{
+ while(chunkline_get_line_collated(chunk, chunk_pos, buf)) {
+ if(chunkline_is_comment_line_or_empty(buf)) {
+ /* a comment, go to next line */
+ continue;
+ }
+ if(http_parse_origin(buf, pstate)) {
+ continue; /* $ORIGIN has been handled */
+ }
+ if(http_parse_ttl(buf, pstate)) {
+ continue; /* $TTL has been handled */
+ }
+ return 1;
+ }
+ /* no noncomments, fail */
+ 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)
+ * on failure. */
+static int
+http_zonefile_syntax_check(struct auth_xfer* xfr, sldns_buffer* buf)
+{
+ uint8_t rr[LDNS_RR_BUF_SIZE];
+ size_t rr_len, dname_len = 0;
+ struct sldns_file_parse_state pstate;
+ struct auth_chunk* chunk;
+ size_t chunk_pos;
+ int e;
+ memset(&pstate, 0, sizeof(pstate));
+ pstate.default_ttl = 3600;
+ if(xfr->namelen < sizeof(pstate.origin)) {
+ pstate.origin_len = xfr->namelen;
+ memmove(pstate.origin, xfr->name, xfr->namelen);
+ }
+ chunk = xfr->task_transfer->chunks_first;
+ chunk_pos = 0;
+ if(!chunkline_non_comment_RR(&chunk, &chunk_pos, buf, &pstate)) {
+ return 0;
+ }
+ rr_len = sizeof(rr);
+ e=sldns_str2wire_rr_buf((char*)sldns_buffer_begin(buf), rr, &rr_len,
+ &dname_len, pstate.default_ttl,
+ 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",
+ 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 "
+ "from wrong RR class");
+ return 0;
+ }
+ return 1;
+}
+
+/** sum sizes of chunklist */
+static size_t
+chunklist_sum(struct auth_chunk* list)
+{
+ struct auth_chunk* p;
+ size_t s = 0;
+ for(p=list; p; p=p->next) {
+ s += p->len;
+ }
+ return s;
+}
+
+/** remove newlines from collated line */
+static void
+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')
+ sldns_buffer_write_u8_at(buf, i, (uint8_t)' ');
+ }
+}
+
+/** for http download, parse and add RR to zone */
+static int
+http_parse_add_rr(struct auth_xfer* xfr, struct auth_zone* z,
+ sldns_buffer* buf, struct sldns_file_parse_state* pstate)
+{
+ uint8_t rr[LDNS_RR_BUF_SIZE];
+ size_t rr_len, dname_len = 0;
+ int e;
+ char* line = (char*)sldns_buffer_begin(buf);
+ rr_len = sizeof(rr);
+ e = sldns_str2wire_rr_buf(line, rr, &rr_len, &dname_len,
+ pstate->default_ttl,
+ 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("%s/%s parse failure RR[%d]: %s in '%s'",
+ xfr->task_transfer->master->host,
+ xfr->task_transfer->master->file,
+ LDNS_WIREPARSE_OFFSET(e),
+ sldns_get_errorstr_parse(LDNS_WIREPARSE_ERROR(e)),
+ line);
+ return 0;
+ }
+ if(rr_len == 0)
+ return 1; /* empty line or so */
+
+ /* set prev */
+ if(dname_len < sizeof(pstate->prev_rr)) {
+ memmove(pstate->prev_rr, rr, dname_len);
+ pstate->prev_rr_len = dname_len;
+ }
+
+ return az_insert_rr(z, rr, rr_len, dname_len, NULL);
+}
+
+/** RR list iterator, returns RRs from answer section one by one from the
+ * dns packets in the chunklist */
+static void
+chunk_rrlist_start(struct auth_xfer* xfr, struct auth_chunk** rr_chunk,
+ int* rr_num, size_t* rr_pos)
+{
+ *rr_chunk = xfr->task_transfer->chunks_first;
+ *rr_num = 0;
+ *rr_pos = 0;
+}
+
+/** RR list iterator, see if we are at the end of the list */
+static int
+chunk_rrlist_end(struct auth_chunk* rr_chunk, int rr_num)
+{
+ while(rr_chunk) {
+ if(rr_chunk->len < LDNS_HEADER_SIZE)
+ return 1;
+ if(rr_num < (int)LDNS_ANCOUNT(rr_chunk->data))
+ return 0;
+ /* no more RRs in this chunk */
+ /* continue with next chunk, see if it has RRs */
+ rr_chunk = rr_chunk->next;
+ rr_num = 0;
+ }
+ return 1;
+}
+
+/** RR list iterator, move to next RR */
+static void
+chunk_rrlist_gonext(struct auth_chunk** rr_chunk, int* rr_num,
+ size_t* rr_pos, size_t rr_nextpos)
+{
+ /* already at end of chunks? */
+ if(!*rr_chunk)
+ return;
+ /* move within this chunk */
+ if((*rr_chunk)->len >= LDNS_HEADER_SIZE &&
+ (*rr_num)+1 < (int)LDNS_ANCOUNT((*rr_chunk)->data)) {
+ (*rr_num) += 1;
+ *rr_pos = rr_nextpos;
+ return;
+ }
+ /* no more RRs in this chunk */
+ /* continue with next chunk, see if it has RRs */
+ if(*rr_chunk)
+ *rr_chunk = (*rr_chunk)->next;
+ while(*rr_chunk) {
+ *rr_num = 0;
+ *rr_pos = 0;
+ if((*rr_chunk)->len >= LDNS_HEADER_SIZE &&
+ LDNS_ANCOUNT((*rr_chunk)->data) > 0) {
+ return;
+ }
+ *rr_chunk = (*rr_chunk)->next;
+ }
+}
+
+/** RR iterator, get current RR information, false on parse error */
+static int
+chunk_rrlist_get_current(struct auth_chunk* rr_chunk, int rr_num,
+ size_t rr_pos, uint8_t** rr_dname, uint16_t* rr_type,
+ uint16_t* rr_class, uint32_t* rr_ttl, uint16_t* rr_rdlen,
+ uint8_t** rr_rdata, size_t* rr_nextpos)
+{
+ sldns_buffer pkt;
+ /* integrity checks on position */
+ if(!rr_chunk) return 0;
+ if(rr_chunk->len < LDNS_HEADER_SIZE) return 0;
+ if(rr_num >= (int)LDNS_ANCOUNT(rr_chunk->data)) return 0;
+ if(rr_pos >= rr_chunk->len) return 0;
+
+ /* fetch rr information */
+ sldns_buffer_init_frm_data(&pkt, rr_chunk->data, rr_chunk->len);
+ if(rr_pos == 0) {
+ size_t i;
+ /* skip question section */
+ sldns_buffer_set_position(&pkt, LDNS_HEADER_SIZE);
+ for(i=0; i<LDNS_QDCOUNT(rr_chunk->data); i++) {
+ if(pkt_dname_len(&pkt) == 0) return 0;
+ if(sldns_buffer_remaining(&pkt) < 4) return 0;
+ sldns_buffer_skip(&pkt, 4); /* type and class */
+ }
+ } else {
+ sldns_buffer_set_position(&pkt, rr_pos);
+ }
+ *rr_dname = sldns_buffer_current(&pkt);
+ if(pkt_dname_len(&pkt) == 0) return 0;
+ if(sldns_buffer_remaining(&pkt) < 10) return 0;
+ *rr_type = sldns_buffer_read_u16(&pkt);
+ *rr_class = sldns_buffer_read_u16(&pkt);
+ *rr_ttl = sldns_buffer_read_u32(&pkt);
+ *rr_rdlen = sldns_buffer_read_u16(&pkt);
+ if(sldns_buffer_remaining(&pkt) < (*rr_rdlen)) return 0;
+ *rr_rdata = sldns_buffer_current(&pkt);
+ sldns_buffer_skip(&pkt, (ssize_t)(*rr_rdlen));
+ *rr_nextpos = sldns_buffer_position(&pkt);
+ return 1;
+}
+
+/** print log message where we are in parsing the zone transfer */
+static void
+log_rrlist_position(const char* label, struct auth_chunk* rr_chunk,
+ uint8_t* rr_dname, uint16_t rr_type, size_t rr_counter)
+{
+ sldns_buffer pkt;
+ size_t dlen;
+ uint8_t buf[256];
+ char str[256];
+ char typestr[32];
+ sldns_buffer_init_frm_data(&pkt, rr_chunk->data, rr_chunk->len);
+ sldns_buffer_set_position(&pkt, (size_t)(rr_dname -
+ sldns_buffer_begin(&pkt)));
+ if((dlen=pkt_dname_len(&pkt)) == 0) return;
+ if(dlen >= sizeof(buf)) return;
+ dname_pkt_copy(&pkt, buf, rr_dname);
+ dname_str(buf, str);
+ (void)sldns_wire2str_type_buf(rr_type, typestr, sizeof(typestr));
+ verbose(VERB_ALGO, "%s at[%d] %s %s", label, (int)rr_counter,
+ str, typestr);
+}
+
+/** apply IXFR to zone in memory. z is locked. false on failure(mallocfail) */
+static int
+apply_ixfr(struct auth_xfer* xfr, struct auth_zone* z,
+ struct sldns_buffer* scratch_buffer)
+{
+ struct auth_chunk* rr_chunk;
+ int rr_num;
+ size_t rr_pos;
+ uint8_t* rr_dname, *rr_rdata;
+ uint16_t rr_type, rr_class, rr_rdlen;
+ uint32_t rr_ttl;
+ size_t rr_nextpos;
+ int have_transfer_serial = 0;
+ uint32_t transfer_serial = 0;
+ size_t rr_counter = 0;
+ int delmode = 0;
+ int softfail = 0;
+
+ /* start RR iterator over chunklist of packets */
+ chunk_rrlist_start(xfr, &rr_chunk, &rr_num, &rr_pos);
+ while(!chunk_rrlist_end(rr_chunk, rr_num)) {
+ if(!chunk_rrlist_get_current(rr_chunk, rr_num, rr_pos,
+ &rr_dname, &rr_type, &rr_class, &rr_ttl, &rr_rdlen,
+ &rr_rdata, &rr_nextpos)) {
+ /* failed to parse RR */
+ return 0;
+ }
+ if(verbosity>=7) log_rrlist_position("apply ixfr",
+ rr_chunk, rr_dname, rr_type, rr_counter);
+ /* twiddle add/del mode and check for start and end */
+ if(rr_counter == 0 && rr_type != LDNS_RR_TYPE_SOA)
+ return 0;
+ if(rr_counter == 1 && rr_type != LDNS_RR_TYPE_SOA) {
+ /* this is an AXFR returned from the IXFR master */
+ /* but that should already have been detected, by
+ * on_ixfr_is_axfr */
+ return 0;
+ }
+ if(rr_type == LDNS_RR_TYPE_SOA) {
+ uint32_t serial;
+ if(rr_rdlen < 22) return 0; /* bad SOA rdlen */
+ serial = sldns_read_uint32(rr_rdata+rr_rdlen-20);
+ if(have_transfer_serial == 0) {
+ have_transfer_serial = 1;
+ transfer_serial = serial;
+ delmode = 1; /* gets negated below */
+ } else if(transfer_serial == serial) {
+ have_transfer_serial++;
+ if(rr_counter == 1) {
+ /* empty AXFR, with SOA; SOA; */
+ /* should have been detected by
+ * on_ixfr_is_axfr */
+ return 0;
+ }
+ if(have_transfer_serial == 3) {
+ /* see serial three times for end */
+ /* eg. IXFR:
+ * SOA 3 start
+ * SOA 1 second RR, followed by del
+ * SOA 2 followed by add
+ * SOA 2 followed by del
+ * SOA 3 followed by add
+ * SOA 3 end */
+ /* ended by SOA record */
+ xfr->serial = transfer_serial;
+ break;
+ }
+ }
+ /* twiddle add/del mode */
+ /* switch from delete part to add part and back again
+ * just before the soa, it gets deleted and added too
+ * this means we switch to delete mode for the final
+ * SOA(so skip that one) */
+ delmode = !delmode;
+ }
+ /* process this RR */
+ /* if the RR is deleted twice or added twice, then we
+ * softfail, and continue with the rest of the IXFR, so
+ * that we serve something fairly nice during the refetch */
+ if(verbosity>=7) log_rrlist_position((delmode?"del":"add"),
+ rr_chunk, rr_dname, rr_type, rr_counter);
+ if(delmode) {
+ /* delete this RR */
+ int nonexist = 0;
+ if(!az_remove_rr_decompress(z, rr_chunk->data,
+ rr_chunk->len, scratch_buffer, rr_dname,
+ rr_type, rr_class, rr_ttl, rr_rdata, rr_rdlen,
+ &nonexist)) {
+ /* failed, malloc error or so */
+ return 0;
+ }
+ if(nonexist) {
+ /* it was removal of a nonexisting RR */
+ if(verbosity>=4) log_rrlist_position(
+ "IXFR error nonexistent RR",
+ rr_chunk, rr_dname, rr_type, rr_counter);
+ softfail = 1;
+ }
+ } else if(rr_counter != 0) {
+ /* skip first SOA RR for addition, it is added in
+ * the addition part near the end of the ixfr, when
+ * that serial is seen the second time. */
+ int duplicate = 0;
+ /* add this RR */
+ if(!az_insert_rr_decompress(z, rr_chunk->data,
+ rr_chunk->len, scratch_buffer, rr_dname,
+ rr_type, rr_class, rr_ttl, rr_rdata, rr_rdlen,
+ &duplicate)) {
+ /* failed, malloc error or so */
+ return 0;
+ }
+ if(duplicate) {
+ /* it was a duplicate */
+ if(verbosity>=4) log_rrlist_position(
+ "IXFR error duplicate RR",
+ rr_chunk, rr_dname, rr_type, rr_counter);
+ softfail = 1;
+ }
+ }
+
+ rr_counter++;
+ chunk_rrlist_gonext(&rr_chunk, &rr_num, &rr_pos, rr_nextpos);
+ }
+ if(softfail) {
+ verbose(VERB_ALGO, "IXFR did not apply cleanly, fetching full zone");
+ return 0;
+ }
+ return 1;
+}
+
+/** apply AXFR to zone in memory. z is locked. false on failure(mallocfail) */
+static int
+apply_axfr(struct auth_xfer* xfr, struct auth_zone* z,
+ struct sldns_buffer* scratch_buffer)
+{
+ struct auth_chunk* rr_chunk;
+ int rr_num;
+ size_t rr_pos;
+ uint8_t* rr_dname, *rr_rdata;
+ uint16_t rr_type, rr_class, rr_rdlen;
+ uint32_t rr_ttl;
+ uint32_t serial = 0;
+ size_t rr_nextpos;
+ size_t rr_counter = 0;
+ int have_end_soa = 0;
+
+ /* clear the data tree */
+ traverse_postorder(&z->data, auth_data_del, NULL);
+ rbtree_init(&z->data, &auth_data_cmp);
+ xfr->have_zone = 0;
+ xfr->serial = 0;
+
+ /* insert all RRs in to the zone */
+ /* insert the SOA only once, skip the last one */
+ /* start RR iterator over chunklist of packets */
+ chunk_rrlist_start(xfr, &rr_chunk, &rr_num, &rr_pos);
+ while(!chunk_rrlist_end(rr_chunk, rr_num)) {
+ if(!chunk_rrlist_get_current(rr_chunk, rr_num, rr_pos,
+ &rr_dname, &rr_type, &rr_class, &rr_ttl, &rr_rdlen,
+ &rr_rdata, &rr_nextpos)) {
+ /* failed to parse RR */
+ return 0;
+ }
+ if(verbosity>=7) log_rrlist_position("apply_axfr",
+ rr_chunk, rr_dname, rr_type, rr_counter);
+ if(rr_type == LDNS_RR_TYPE_SOA) {
+ if(rr_counter != 0) {
+ /* end of the axfr */
+ have_end_soa = 1;
+ break;
+ }
+ if(rr_rdlen < 22) return 0; /* bad SOA rdlen */
+ serial = sldns_read_uint32(rr_rdata+rr_rdlen-20);
+ }
+
+ /* add this RR */
+ if(!az_insert_rr_decompress(z, rr_chunk->data, rr_chunk->len,
+ scratch_buffer, rr_dname, rr_type, rr_class, rr_ttl,
+ rr_rdata, rr_rdlen, NULL)) {
+ /* failed, malloc error or so */
+ return 0;
+ }
+
+ rr_counter++;
+ chunk_rrlist_gonext(&rr_chunk, &rr_num, &rr_pos, rr_nextpos);
+ }
+ if(!have_end_soa) {
+ log_err("no end SOA record for AXFR");
+ return 0;
+ }
+
+ xfr->serial = serial;
+ xfr->have_zone = 1;
+ return 1;
+}
+
+/** apply HTTP to zone in memory. z is locked. false on failure(mallocfail) */
+static int
+apply_http(struct auth_xfer* xfr, struct auth_zone* z,
+ struct sldns_buffer* scratch_buffer)
+{
+ /* parse data in chunks */
+ /* parse RR's and read into memory. ignore $INCLUDE from the
+ * downloaded file*/
+ struct sldns_file_parse_state pstate;
+ struct auth_chunk* chunk;
+ size_t chunk_pos;
+ memset(&pstate, 0, sizeof(pstate));
+ pstate.default_ttl = 3600;
+ if(xfr->namelen < sizeof(pstate.origin)) {
+ pstate.origin_len = xfr->namelen;
+ memmove(pstate.origin, xfr->name, xfr->namelen);
+ }
+
+ if(verbosity >= VERB_ALGO)
+ verbose(VERB_ALGO, "http download %s of size %d",
+ xfr->task_transfer->master->file,
+ (int)chunklist_sum(xfr->task_transfer->chunks_first));
+ if(xfr->task_transfer->chunks_first && verbosity >= VERB_ALGO) {
+ char preview[1024];
+ if(xfr->task_transfer->chunks_first->len+1 > sizeof(preview)) {
+ memmove(preview, xfr->task_transfer->chunks_first->data,
+ sizeof(preview)-1);
+ preview[sizeof(preview)-1]=0;
+ } else {
+ memmove(preview, xfr->task_transfer->chunks_first->data,
+ xfr->task_transfer->chunks_first->len);
+ preview[xfr->task_transfer->chunks_first->len]=0;
+ }
+ log_info("auth zone http downloaded content preview: %s",
+ preview);
+ }
+
+ /* perhaps a little syntax check before we try to apply the data? */
+ if(!http_zonefile_syntax_check(xfr, scratch_buffer)) {
+ log_err("http download %s/%s does not contain a zonefile, "
+ "but got '%s'", xfr->task_transfer->master->host,
+ xfr->task_transfer->master->file,
+ sldns_buffer_begin(scratch_buffer));
+ return 0;
+ }
+
+ /* clear the data tree */
+ traverse_postorder(&z->data, auth_data_del, NULL);
+ rbtree_init(&z->data, &auth_data_cmp);
+ xfr->have_zone = 0;
+ xfr->serial = 0;
+
+ chunk = xfr->task_transfer->chunks_first;
+ chunk_pos = 0;
+ pstate.lineno = 0;
+ while(chunkline_get_line_collated(&chunk, &chunk_pos, scratch_buffer)) {
+ /* process this line */
+ pstate.lineno++;
+ chunkline_newline_removal(scratch_buffer);
+ if(chunkline_is_comment_line_or_empty(scratch_buffer)) {
+ continue;
+ }
+ /* parse line and add RR */
+ if(http_parse_origin(scratch_buffer, &pstate)) {
+ continue; /* $ORIGIN has been handled */
+ }
+ if(http_parse_ttl(scratch_buffer, &pstate)) {
+ continue; /* $TTL has been handled */
+ }
+ if(!http_parse_add_rr(xfr, z, scratch_buffer, &pstate)) {
+ verbose(VERB_ALGO, "error parsing line [%s:%d] %s",
+ xfr->task_transfer->master->file,
+ pstate.lineno,
+ sldns_buffer_begin(scratch_buffer));
+ return 0;
+ }
+ }
+ return 1;
+}
+
+/** write to zonefile after zone has been updated */
+static void
+xfr_write_after_update(struct auth_xfer* xfr, struct module_env* env)
+{
+ struct auth_zone* z;
+ char tmpfile[1024];
+ lock_basic_unlock(&xfr->lock);
+
+ /* get lock again, so it is a readlock and concurrently queries
+ * can be answered */
+ lock_rw_rdlock(&env->auth_zones->lock);
+ z = auth_zone_find(env->auth_zones, xfr->name, xfr->namelen,
+ xfr->dclass);
+ if(!z) {
+ lock_rw_unlock(&env->auth_zones->lock);
+ /* the zone is gone, ignore xfr results */
+ lock_basic_lock(&xfr->lock);
+ return;
+ }
+ lock_rw_rdlock(&z->lock);
+ lock_basic_lock(&xfr->lock);
+ lock_rw_unlock(&env->auth_zones->lock);
+
+ if(z->zonefile == NULL) {
+ lock_rw_unlock(&z->lock);
+ /* no write needed, no zonefile set */
+ return;
+ }
+
+ /* write to tempfile first */
+ if((size_t)strlen(z->zonefile) + 16 > sizeof(tmpfile)) {
+ verbose(VERB_ALGO, "tmpfilename too long, cannot update "
+ " zonefile %s", z->zonefile);
+ lock_rw_unlock(&z->lock);
+ return;
+ }
+ snprintf(tmpfile, sizeof(tmpfile), "%s.tmp%u", z->zonefile,
+ (unsigned)getpid());
+ if(!auth_zone_write_file(z, tmpfile)) {
+ unlink(tmpfile);
+ lock_rw_unlock(&z->lock);
+ return;
+ }
+ if(rename(tmpfile, z->zonefile) < 0) {
+ log_err("could not rename(%s, %s): %s", tmpfile, z->zonefile,
+ strerror(errno));
+ unlink(tmpfile);
+ lock_rw_unlock(&z->lock);
+ return;
+ }
+ lock_rw_unlock(&z->lock);
+}
+
+/** process chunk list and update zone in memory,
+ * return false if it did not work */
+static int
+xfr_process_chunk_list(struct auth_xfer* xfr, struct module_env* env,
+ int* ixfr_fail)
+{
+ struct auth_zone* z;
+
+ /* obtain locks and structures */
+ /* release xfr lock, then, while holding az->lock grab both
+ * z->lock and xfr->lock */
+ lock_basic_unlock(&xfr->lock);
+ lock_rw_rdlock(&env->auth_zones->lock);
+ z = auth_zone_find(env->auth_zones, xfr->name, xfr->namelen,
+ xfr->dclass);
+ if(!z) {
+ lock_rw_unlock(&env->auth_zones->lock);
+ /* the zone is gone, ignore xfr results */
+ lock_basic_lock(&xfr->lock);
+ return 0;
+ }
+ lock_rw_wrlock(&z->lock);
+ lock_basic_lock(&xfr->lock);
+ lock_rw_unlock(&env->auth_zones->lock);
+
+ /* apply data */
+ if(xfr->task_transfer->master->http) {
+ if(!apply_http(xfr, z, env->scratch_buffer)) {
+ lock_rw_unlock(&z->lock);
+ verbose(VERB_ALGO, "http from %s: could not store data",
+ xfr->task_transfer->master->host);
+ return 0;
+ }
+ } else if(xfr->task_transfer->on_ixfr &&
+ !xfr->task_transfer->on_ixfr_is_axfr) {
+ if(!apply_ixfr(xfr, z, env->scratch_buffer)) {
+ lock_rw_unlock(&z->lock);
+ verbose(VERB_ALGO, "xfr from %s: could not store IXFR"
+ " data", xfr->task_transfer->master->host);
+ *ixfr_fail = 1;
+ return 0;
+ }
+ } else {
+ if(!apply_axfr(xfr, z, env->scratch_buffer)) {
+ lock_rw_unlock(&z->lock);
+ verbose(VERB_ALGO, "xfr from %s: could not store AXFR"
+ " data", xfr->task_transfer->master->host);
+ return 0;
+ }
+ }
+ xfr->zone_expired = 0;
+ z->zone_expired = 0;
+ if(!xfr_find_soa(z, xfr)) {
+ lock_rw_unlock(&z->lock);
+ verbose(VERB_ALGO, "xfr from %s: no SOA in zone after update"
+ " (or malformed RR)", xfr->task_transfer->master->host);
+ return 0;
+ }
+ if(xfr->have_zone)
+ xfr->lease_time = *env->now;
+
+ /* unlock */
+ lock_rw_unlock(&z->lock);
+
+ if(verbosity >= VERB_QUERY && xfr->have_zone) {
+ char zname[256];
+ dname_str(xfr->name, zname);
+ verbose(VERB_QUERY, "auth zone %s updated to serial %u", zname,
+ (unsigned)xfr->serial);
+ }
+ /* see if we need to write to a zonefile */
+ xfr_write_after_update(xfr, env);
+ return 1;
+}
+
+/** disown task_transfer. caller must hold xfr.lock */
+static void
+xfr_transfer_disown(struct auth_xfer* xfr)
+{
+ /* remove the commpoint */
+ comm_point_delete(xfr->task_transfer->cp);
+ xfr->task_transfer->cp = NULL;
+ /* we don't own this item anymore */
+ xfr->task_transfer->worker = NULL;
+ xfr->task_transfer->env = NULL;
+}
+
+/** lookup a host name for its addresses, if needed */
+static int
+xfr_transfer_lookup_host(struct auth_xfer* xfr, struct module_env* env)
+{
+ struct sockaddr_storage addr;
+ socklen_t addrlen = 0;
+ struct auth_master* master = xfr->task_transfer->lookup_target;
+ struct query_info qinfo;
+ uint16_t qflags = BIT_RD;
+ uint8_t dname[LDNS_MAX_DOMAINLEN+1];
+ struct edns_data edns;
+ sldns_buffer* buf = env->scratch_buffer;
+ if(!master) return 0;
+ if(extstrtoaddr(master->host, &addr, &addrlen)) {
+ /* not needed, host is in IP addr format */
+ return 0;
+ }
+
+ /* use mesh_new_callback to probe for non-addr hosts,
+ * and then wait for them to be looked up (in cache, or query) */
+ qinfo.qname_len = sizeof(dname);
+ if(sldns_str2wire_dname_buf(master->host, dname, &qinfo.qname_len)
+ != 0) {
+ log_err("cannot parse host name of master %s", master->host);
+ return 0;
+ }
+ qinfo.qname = dname;
+ qinfo.qclass = xfr->dclass;
+ qinfo.qtype = LDNS_RR_TYPE_A;
+ if(xfr->task_transfer->lookup_aaaa)
+ qinfo.qtype = LDNS_RR_TYPE_AAAA;
+ qinfo.local_alias = NULL;
+ if(verbosity >= VERB_ALGO) {
+ char buf[512];
+ char buf2[LDNS_MAX_DOMAINLEN+1];
+ dname_str(xfr->name, buf2);
+ snprintf(buf, sizeof(buf), "auth zone %s: master lookup"
+ " for task_transfer", buf2);
+ log_query_info(VERB_ALGO, buf, &qinfo);
+ }
+ edns.edns_present = 1;
+ edns.ext_rcode = 0;
+ edns.edns_version = 0;
+ edns.bits = EDNS_DO;
+ edns.opt_list = NULL;
+ if(sldns_buffer_capacity(buf) < 65535)
+ edns.udp_size = (uint16_t)sldns_buffer_capacity(buf);
+ else edns.udp_size = 65535;
+
+ /* unlock xfr during mesh_new_callback() because the callback can be
+ * called straight away */
+ lock_basic_unlock(&xfr->lock);
+ if(!mesh_new_callback(env->mesh, &qinfo, qflags, &edns, buf, 0,
+ &auth_xfer_transfer_lookup_callback, xfr)) {
+ lock_basic_lock(&xfr->lock);
+ log_err("out of memory lookup up master %s", master->host);
+ return 0;
+ }
+ lock_basic_lock(&xfr->lock);
+ return 1;
+}
+
+/** initiate TCP to the target and fetch zone.
+ * returns true if that was successfully started, and timeout setup. */
+static int
+xfr_transfer_init_fetch(struct auth_xfer* xfr, struct module_env* env)
+{
+ struct sockaddr_storage addr;
+ socklen_t addrlen = 0;
+ struct auth_master* master = xfr->task_transfer->master;
+ if(!master) return 0;
+
+ /* get master addr */
+ if(xfr->task_transfer->scan_addr) {
+ addrlen = xfr->task_transfer->scan_addr->addrlen;
+ memmove(&addr, &xfr->task_transfer->scan_addr->addr, addrlen);
+ } else {
+ if(!extstrtoaddr(master->host, &addr, &addrlen)) {
+ /* the ones that are not in addr format are supposed
+ * to be looked up. The lookup has failed however,
+ * so skip them */
+ char zname[255+1];
+ dname_str(xfr->name, zname);
+ log_err("%s: failed lookup, cannot transfer from master %s",
+ zname, master->host);
+ return 0;
+ }
+ }
+
+ /* remove previous TCP connection (if any) */
+ if(xfr->task_transfer->cp) {
+ comm_point_delete(xfr->task_transfer->cp);
+ xfr->task_transfer->cp = NULL;
+ }
+
+ if(master->http) {
+ /* perform http fetch */
+ /* store http port number into sockaddr,
+ * unless someone used unbound's host@port notation */
+ if(strchr(master->host, '@') == NULL)
+ sockaddr_store_port(&addr, addrlen, master->port);
+ xfr->task_transfer->cp = outnet_comm_point_for_http(
+ env->outnet, auth_xfer_transfer_http_callback, xfr,
+ &addr, addrlen, AUTH_TRANSFER_TIMEOUT, master->ssl,
+ master->host, master->file);
+ if(!xfr->task_transfer->cp) {
+ char zname[255+1];
+ dname_str(xfr->name, zname);
+ verbose(VERB_ALGO, "cannot create http cp "
+ "connection for %s to %s", zname,
+ master->host);
+ return 0;
+ }
+ return 1;
+ }
+
+ /* perform AXFR/IXFR */
+ /* set the packet to be written */
+ /* create new ID */
+ xfr->task_transfer->id = (uint16_t)(ub_random(env->rnd)&0xffff);
+ xfr_create_ixfr_packet(xfr, env->scratch_buffer,
+ xfr->task_transfer->id, master);
+
+ /* connect on fd */
+ xfr->task_transfer->cp = outnet_comm_point_for_tcp(env->outnet,
+ auth_xfer_transfer_tcp_callback, xfr, &addr, addrlen,
+ env->scratch_buffer, AUTH_TRANSFER_TIMEOUT);
+ if(!xfr->task_transfer->cp) {
+ char zname[255+1];
+ dname_str(xfr->name, zname);
+ verbose(VERB_ALGO, "cannot create tcp cp connection for "
+ "xfr %s to %s", zname, master->host);
+ return 0;
+ }
+ return 1;
+}
+
+/** perform next lookup, next transfer TCP, or end and resume wait time task */
+static void
+xfr_transfer_nexttarget_or_end(struct auth_xfer* xfr, struct module_env* env)
+{
+ log_assert(xfr->task_transfer->worker == env->worker);
+
+ /* are we performing lookups? */
+ while(xfr->task_transfer->lookup_target) {
+ if(xfr_transfer_lookup_host(xfr, env)) {
+ /* wait for lookup to finish,
+ * note that the hostname may be in unbound's cache
+ * and we may then get an instant cache response,
+ * and that calls the callback just like a full
+ * lookup and lookup failures also call callback */
+ lock_basic_unlock(&xfr->lock);
+ return;
+ }
+ xfr_transfer_move_to_next_lookup(xfr, env);
+ }
+
+ /* initiate TCP and fetch the zone from the master */
+ /* and set timeout on it */
+ while(!xfr_transfer_end_of_list(xfr)) {
+ xfr->task_transfer->master = xfr_transfer_current_master(xfr);
+ if(xfr_transfer_init_fetch(xfr, env)) {
+ /* successfully started, wait for callback */
+ lock_basic_unlock(&xfr->lock);
+ return;
+ }
+ /* failed to fetch, next master */
+ xfr_transfer_nextmaster(xfr);
+ }
+
+ /* we failed to fetch the zone, move to wait task
+ * use the shorter retry timeout */
+ xfr_transfer_disown(xfr);
+
+ /* pick up the nextprobe task and wait */
+ xfr_set_timeout(xfr, env, 1);
+ lock_basic_unlock(&xfr->lock);
+}
+
+/** add addrs from A or AAAA rrset to the master */
+static void
+xfr_master_add_addrs(struct auth_master* m, struct ub_packed_rrset_key* rrset,
+ uint16_t rrtype)
+{
+ size_t i;
+ struct packed_rrset_data* data;
+ if(!m || !rrset) return;
+ data = (struct packed_rrset_data*)rrset->entry.data;
+ for(i=0; i<data->count; i++) {
+ struct auth_addr* a;
+ size_t len = data->rr_len[i] - 2;
+ uint8_t* rdata = data->rr_data[i]+2;
+ if(rrtype == LDNS_RR_TYPE_A && len != INET_SIZE)
+ continue; /* wrong length for A */
+ if(rrtype == LDNS_RR_TYPE_AAAA && len != INET6_SIZE)
+ continue; /* wrong length for AAAA */
+
+ /* add and alloc it */
+ a = (struct auth_addr*)calloc(1, sizeof(*a));
+ if(!a) {
+ log_err("out of memory");
+ return;
+ }
+ if(rrtype == LDNS_RR_TYPE_A) {
+ struct sockaddr_in* sa;
+ a->addrlen = (socklen_t)sizeof(*sa);
+ sa = (struct sockaddr_in*)&a->addr;
+ sa->sin_family = AF_INET;
+ sa->sin_port = (in_port_t)htons(UNBOUND_DNS_PORT);
+ memmove(&sa->sin_addr, rdata, INET_SIZE);
+ } else {
+ struct sockaddr_in6* sa;
+ a->addrlen = (socklen_t)sizeof(*sa);
+ sa = (struct sockaddr_in6*)&a->addr;
+ sa->sin6_family = AF_INET6;
+ sa->sin6_port = (in_port_t)htons(UNBOUND_DNS_PORT);
+ memmove(&sa->sin6_addr, rdata, INET6_SIZE);
+ }
+ if(verbosity >= VERB_ALGO) {
+ char s[64];
+ addr_to_str(&a->addr, a->addrlen, s, sizeof(s));
+ verbose(VERB_ALGO, "auth host %s lookup %s",
+ m->host, s);
+ }
+ /* append to list */
+ a->next = m->list;
+ m->list = a;
+ }
+}
+
+/** callback for task_transfer lookup of host name, of A or AAAA */
+void auth_xfer_transfer_lookup_callback(void* arg, int rcode, sldns_buffer* buf,
+ enum sec_status ATTR_UNUSED(sec), char* ATTR_UNUSED(why_bogus))
+{
+ struct auth_xfer* xfr = (struct auth_xfer*)arg;
+ struct module_env* env;
+ log_assert(xfr->task_transfer);
+ lock_basic_lock(&xfr->lock);
+ env = xfr->task_transfer->env;
+ if(env->outnet->want_to_quit) {
+ lock_basic_unlock(&xfr->lock);
+ return; /* stop on quit */
+ }
+
+ /* process result */
+ if(rcode == LDNS_RCODE_NOERROR) {
+ uint16_t wanted_qtype = LDNS_RR_TYPE_A;
+ struct regional* temp = env->scratch;
+ struct query_info rq;
+ struct reply_info* rep;
+ if(xfr->task_transfer->lookup_aaaa)
+ wanted_qtype = LDNS_RR_TYPE_AAAA;
+ memset(&rq, 0, sizeof(rq));
+ rep = parse_reply_in_temp_region(buf, temp, &rq);
+ if(rep && rq.qtype == wanted_qtype &&
+ FLAGS_GET_RCODE(rep->flags) == LDNS_RCODE_NOERROR) {
+ /* parsed successfully */
+ struct ub_packed_rrset_key* answer =
+ reply_find_answer_rrset(&rq, rep);
+ if(answer) {
+ xfr_master_add_addrs(xfr->task_transfer->
+ lookup_target, answer, wanted_qtype);
+ }
+ }
+ }
+ if(xfr->task_transfer->lookup_target->list &&
+ xfr->task_transfer->lookup_target == xfr_transfer_current_master(xfr))
+ xfr->task_transfer->scan_addr = xfr->task_transfer->lookup_target->list;
+
+ /* move to lookup AAAA after A lookup, move to next hostname lookup,
+ * or move to fetch the zone, or, if nothing to do, end task_transfer */
+ xfr_transfer_move_to_next_lookup(xfr, env);
+ xfr_transfer_nexttarget_or_end(xfr, env);
+}
+
+/** check if xfer (AXFR or IXFR) packet is OK.
+ * return false if we lost connection (SERVFAIL, or unreadable).
+ * return false if we need to move from IXFR to AXFR, with gonextonfail
+ * set to false, so the same master is tried again, but with AXFR.
+ * return true if fine to link into data.
+ * return true with transferdone=true when the transfer has ended.
+ */
+static int
+check_xfer_packet(sldns_buffer* pkt, struct auth_xfer* xfr,
+ int* gonextonfail, int* transferdone)
+{
+ uint8_t* wire = sldns_buffer_begin(pkt);
+ int i;
+ if(sldns_buffer_limit(pkt) < LDNS_HEADER_SIZE) {
+ verbose(VERB_ALGO, "xfr to %s failed, packet too small",
+ xfr->task_transfer->master->host);
+ return 0;
+ }
+ if(!LDNS_QR_WIRE(wire)) {
+ verbose(VERB_ALGO, "xfr to %s failed, packet has no QR flag",
+ xfr->task_transfer->master->host);
+ return 0;
+ }
+ if(LDNS_TC_WIRE(wire)) {
+ verbose(VERB_ALGO, "xfr to %s failed, packet has TC flag",
+ xfr->task_transfer->master->host);
+ return 0;
+ }
+ /* check ID */
+ if(LDNS_ID_WIRE(wire) != xfr->task_transfer->id) {
+ verbose(VERB_ALGO, "xfr to %s failed, packet wrong ID",
+ xfr->task_transfer->master->host);
+ return 0;
+ }
+ if(LDNS_RCODE_WIRE(wire) != LDNS_RCODE_NOERROR) {
+ char rcode[32];
+ sldns_wire2str_rcode_buf((int)LDNS_RCODE_WIRE(wire), rcode,
+ sizeof(rcode));
+ /* if we are doing IXFR, check for fallback */
+ if(xfr->task_transfer->on_ixfr) {
+ if(LDNS_RCODE_WIRE(wire) == LDNS_RCODE_NOTIMPL ||
+ LDNS_RCODE_WIRE(wire) == LDNS_RCODE_SERVFAIL ||
+ LDNS_RCODE_WIRE(wire) == LDNS_RCODE_REFUSED ||
+ LDNS_RCODE_WIRE(wire) == LDNS_RCODE_FORMERR) {
+ verbose(VERB_ALGO, "xfr to %s, fallback "
+ "from IXFR to AXFR (with rcode %s)",
+ xfr->task_transfer->master->host,
+ rcode);
+ xfr->task_transfer->ixfr_fail = 1;
+ *gonextonfail = 0;
+ return 0;
+ }
+ }
+ verbose(VERB_ALGO, "xfr to %s failed, packet with rcode %s",
+ xfr->task_transfer->master->host, rcode);
+ return 0;
+ }
+ if(LDNS_OPCODE_WIRE(wire) != LDNS_PACKET_QUERY) {
+ verbose(VERB_ALGO, "xfr to %s failed, packet with bad opcode",
+ xfr->task_transfer->master->host);
+ return 0;
+ }
+ if(LDNS_QDCOUNT(wire) > 1) {
+ verbose(VERB_ALGO, "xfr to %s failed, packet has qdcount %d",
+ xfr->task_transfer->master->host,
+ (int)LDNS_QDCOUNT(wire));
+ return 0;
+ }
+
+ /* check qname */
+ sldns_buffer_set_position(pkt, LDNS_HEADER_SIZE);
+ for(i=0; i<(int)LDNS_QDCOUNT(wire); i++) {
+ size_t pos = sldns_buffer_position(pkt);
+ uint16_t qtype, qclass;
+ if(pkt_dname_len(pkt) == 0) {
+ verbose(VERB_ALGO, "xfr to %s failed, packet with "
+ "malformed dname",
+ xfr->task_transfer->master->host);
+ return 0;
+ }
+ if(dname_pkt_compare(pkt, sldns_buffer_at(pkt, pos),
+ xfr->name) != 0) {
+ verbose(VERB_ALGO, "xfr to %s failed, packet with "
+ "wrong qname",
+ xfr->task_transfer->master->host);
+ return 0;
+ }
+ if(sldns_buffer_remaining(pkt) < 4) {
+ verbose(VERB_ALGO, "xfr to %s failed, packet with "
+ "truncated query RR",
+ xfr->task_transfer->master->host);
+ return 0;
+ }
+ qtype = sldns_buffer_read_u16(pkt);
+ qclass = sldns_buffer_read_u16(pkt);
+ if(qclass != xfr->dclass) {
+ verbose(VERB_ALGO, "xfr to %s failed, packet with "
+ "wrong qclass",
+ xfr->task_transfer->master->host);
+ return 0;
+ }
+ if(xfr->task_transfer->on_ixfr) {
+ if(qtype != LDNS_RR_TYPE_IXFR) {
+ verbose(VERB_ALGO, "xfr to %s failed, packet "
+ "with wrong qtype, expected IXFR",
+ xfr->task_transfer->master->host);
+ return 0;
+ }
+ } else {
+ if(qtype != LDNS_RR_TYPE_AXFR) {
+ verbose(VERB_ALGO, "xfr to %s failed, packet "
+ "with wrong qtype, expected AXFR",
+ xfr->task_transfer->master->host);
+ return 0;
+ }
+ }
+ }
+
+ /* check parse of RRs in packet, store first SOA serial
+ * to be able to detect last SOA (with that serial) to see if done */
+ /* also check for IXFR 'zone up to date' reply */
+ for(i=0; i<(int)LDNS_ANCOUNT(wire); i++) {
+ size_t pos = sldns_buffer_position(pkt);
+ uint16_t tp, rdlen;
+ if(pkt_dname_len(pkt) == 0) {
+ verbose(VERB_ALGO, "xfr to %s failed, packet with "
+ "malformed dname in answer section",
+ xfr->task_transfer->master->host);
+ return 0;
+ }
+ if(sldns_buffer_remaining(pkt) < 10) {
+ verbose(VERB_ALGO, "xfr to %s failed, packet with "
+ "truncated RR",
+ xfr->task_transfer->master->host);
+ return 0;
+ }
+ tp = sldns_buffer_read_u16(pkt);
+ (void)sldns_buffer_read_u16(pkt); /* class */
+ (void)sldns_buffer_read_u32(pkt); /* ttl */
+ rdlen = sldns_buffer_read_u16(pkt);
+ if(sldns_buffer_remaining(pkt) < rdlen) {
+ verbose(VERB_ALGO, "xfr to %s failed, packet with "
+ "truncated RR rdata",
+ xfr->task_transfer->master->host);
+ return 0;
+ }
+
+ /* RR parses (haven't checked rdata itself), now look at
+ * SOA records to see serial number */
+ if(xfr->task_transfer->rr_scan_num == 0 &&
+ tp != LDNS_RR_TYPE_SOA) {
+ verbose(VERB_ALGO, "xfr to %s failed, packet with "
+ "malformed zone transfer, no start SOA",
+ xfr->task_transfer->master->host);
+ return 0;
+ }
+ if(xfr->task_transfer->rr_scan_num == 1 &&
+ tp != LDNS_RR_TYPE_SOA) {
+ /* second RR is not a SOA record, this is not an IXFR
+ * the master is replying with an AXFR */
+ xfr->task_transfer->on_ixfr_is_axfr = 1;
+ }
+ if(tp == LDNS_RR_TYPE_SOA) {
+ uint32_t serial;
+ if(rdlen < 22) {
+ verbose(VERB_ALGO, "xfr to %s failed, packet "
+ "with SOA with malformed rdata",
+ xfr->task_transfer->master->host);
+ return 0;
+ }
+ if(dname_pkt_compare(pkt, sldns_buffer_at(pkt, pos),
+ xfr->name) != 0) {
+ verbose(VERB_ALGO, "xfr to %s failed, packet "
+ "with SOA with wrong dname",
+ xfr->task_transfer->master->host);
+ return 0;
+ }
+
+ /* read serial number of SOA */
+ serial = sldns_buffer_read_u32_at(pkt,
+ sldns_buffer_position(pkt)+rdlen-20);
+
+ /* check for IXFR 'zone has SOA x' reply */
+ if(xfr->task_transfer->on_ixfr &&
+ xfr->task_transfer->rr_scan_num == 0 &&
+ LDNS_ANCOUNT(wire)==1) {
+ verbose(VERB_ALGO, "xfr to %s ended, "
+ "IXFR reply that zone has serial %u",
+ xfr->task_transfer->master->host,
+ (unsigned)serial);
+ return 0;
+ }
+
+ /* if first SOA, store serial number */
+ if(xfr->task_transfer->got_xfr_serial == 0) {
+ xfr->task_transfer->got_xfr_serial = 1;
+ xfr->task_transfer->incoming_xfr_serial =
+ serial;
+ verbose(VERB_ALGO, "xfr %s: contains "
+ "SOA serial %u",
+ xfr->task_transfer->master->host,
+ (unsigned)serial);
+ /* see if end of AXFR */
+ } else if(!xfr->task_transfer->on_ixfr ||
+ xfr->task_transfer->on_ixfr_is_axfr) {
+ /* second SOA with serial is the end
+ * for AXFR */
+ *transferdone = 1;
+ verbose(VERB_ALGO, "xfr %s: last AXFR packet",
+ xfr->task_transfer->master->host);
+ /* for IXFR, count SOA records with that serial */
+ } else if(xfr->task_transfer->incoming_xfr_serial ==
+ serial && xfr->task_transfer->got_xfr_serial
+ == 1) {
+ xfr->task_transfer->got_xfr_serial++;
+ /* if not first soa, if serial==firstserial, the
+ * third time we are at the end, for IXFR */
+ } else if(xfr->task_transfer->incoming_xfr_serial ==
+ serial && xfr->task_transfer->got_xfr_serial
+ == 2) {
+ verbose(VERB_ALGO, "xfr %s: last IXFR packet",
+ xfr->task_transfer->master->host);
+ *transferdone = 1;
+ /* continue parse check, if that succeeds,
+ * transfer is done */
+ }
+ }
+ xfr->task_transfer->rr_scan_num++;
+
+ /* skip over RR rdata to go to the next RR */
+ sldns_buffer_skip(pkt, (ssize_t)rdlen);
+ }
+
+ /* check authority section */
+ /* we skip over the RRs checking packet format */
+ for(i=0; i<(int)LDNS_NSCOUNT(wire); i++) {
+ uint16_t rdlen;
+ if(pkt_dname_len(pkt) == 0) {
+ verbose(VERB_ALGO, "xfr to %s failed, packet with "
+ "malformed dname in authority section",
+ xfr->task_transfer->master->host);
+ return 0;
+ }
+ if(sldns_buffer_remaining(pkt) < 10) {
+ verbose(VERB_ALGO, "xfr to %s failed, packet with "
+ "truncated RR",
+ xfr->task_transfer->master->host);
+ return 0;
+ }
+ (void)sldns_buffer_read_u16(pkt); /* type */
+ (void)sldns_buffer_read_u16(pkt); /* class */
+ (void)sldns_buffer_read_u32(pkt); /* ttl */
+ rdlen = sldns_buffer_read_u16(pkt);
+ if(sldns_buffer_remaining(pkt) < rdlen) {
+ verbose(VERB_ALGO, "xfr to %s failed, packet with "
+ "truncated RR rdata",
+ xfr->task_transfer->master->host);
+ return 0;
+ }
+ /* skip over RR rdata to go to the next RR */
+ sldns_buffer_skip(pkt, (ssize_t)rdlen);
+ }
+
+ /* check additional section */
+ for(i=0; i<(int)LDNS_ARCOUNT(wire); i++) {
+ uint16_t rdlen;
+ if(pkt_dname_len(pkt) == 0) {
+ verbose(VERB_ALGO, "xfr to %s failed, packet with "
+ "malformed dname in additional section",
+ xfr->task_transfer->master->host);
+ return 0;
+ }
+ if(sldns_buffer_remaining(pkt) < 10) {
+ verbose(VERB_ALGO, "xfr to %s failed, packet with "
+ "truncated RR",
+ xfr->task_transfer->master->host);
+ return 0;
+ }
+ (void)sldns_buffer_read_u16(pkt); /* type */
+ (void)sldns_buffer_read_u16(pkt); /* class */
+ (void)sldns_buffer_read_u32(pkt); /* ttl */
+ rdlen = sldns_buffer_read_u16(pkt);
+ if(sldns_buffer_remaining(pkt) < rdlen) {
+ verbose(VERB_ALGO, "xfr to %s failed, packet with "
+ "truncated RR rdata",
+ xfr->task_transfer->master->host);
+ return 0;
+ }
+ /* skip over RR rdata to go to the next RR */
+ sldns_buffer_skip(pkt, (ssize_t)rdlen);
+ }
+
+ return 1;
+}
+
+/** Link the data from this packet into the worklist of transferred data */
+static int
+xfer_link_data(sldns_buffer* pkt, struct auth_xfer* xfr)
+{
+ /* alloc it */
+ struct auth_chunk* e;
+ e = (struct auth_chunk*)calloc(1, sizeof(*e));
+ if(!e) return 0;
+ e->next = NULL;
+ e->len = sldns_buffer_limit(pkt);
+ e->data = memdup(sldns_buffer_begin(pkt), e->len);
+ if(!e->data) {
+ free(e);
+ return 0;
+ }
+
+ /* alloc succeeded, link into list */
+ if(!xfr->task_transfer->chunks_first)
+ xfr->task_transfer->chunks_first = e;
+ if(xfr->task_transfer->chunks_last)
+ xfr->task_transfer->chunks_last->next = e;
+ xfr->task_transfer->chunks_last = e;
+ return 1;
+}
+
+/** task transfer. the list of data is complete. process it and if failed
+ * move to next master, if succeeded, end the task transfer */
+static void
+process_list_end_transfer(struct auth_xfer* xfr, struct module_env* env)
+{
+ int ixfr_fail = 0;
+ if(xfr_process_chunk_list(xfr, env, &ixfr_fail)) {
+ /* it worked! */
+ auth_chunks_delete(xfr->task_transfer);
+
+ /* 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);
+ lock_basic_unlock(&xfr->lock);
+ return;
+ }
+ /* processing failed */
+ /* when done, delete data from list */
+ auth_chunks_delete(xfr->task_transfer);
+ if(ixfr_fail) {
+ xfr->task_transfer->ixfr_fail = 1;
+ } else {
+ xfr_transfer_nextmaster(xfr);
+ }
+ xfr_transfer_nexttarget_or_end(xfr, env);
+}
+
+/** callback for task_transfer tcp connections */
+int
+auth_xfer_transfer_tcp_callback(struct comm_point* c, void* arg, int err,
+ struct comm_reply* ATTR_UNUSED(repinfo))
+{
+ struct auth_xfer* xfr = (struct auth_xfer*)arg;
+ struct module_env* env;
+ int gonextonfail = 1;
+ int transferdone = 0;
+ log_assert(xfr->task_transfer);
+ lock_basic_lock(&xfr->lock);
+ env = xfr->task_transfer->env;
+ if(env->outnet->want_to_quit) {
+ lock_basic_unlock(&xfr->lock);
+ return 0; /* stop on quit */
+ }
+
+ if(err != NETEVENT_NOERROR) {
+ /* connection failed, closed, or timeout */
+ /* stop this transfer, cleanup
+ * and continue task_transfer*/
+ verbose(VERB_ALGO, "xfr stopped, connection lost to %s",
+ xfr->task_transfer->master->host);
+ failed:
+ /* delete transferred data from list */
+ auth_chunks_delete(xfr->task_transfer);
+ comm_point_delete(xfr->task_transfer->cp);
+ xfr->task_transfer->cp = NULL;
+ xfr_transfer_nextmaster(xfr);
+ xfr_transfer_nexttarget_or_end(xfr, env);
+ return 0;
+ }
+
+ /* handle returned packet */
+ /* if it fails, cleanup and end this transfer */
+ /* if it needs to fallback from IXFR to AXFR, do that */
+ if(!check_xfer_packet(c->buffer, xfr, &gonextonfail, &transferdone)) {
+ goto failed;
+ }
+ /* if it is good, link it into the list of data */
+ /* if the link into list of data fails (malloc fail) cleanup and end */
+ if(!xfer_link_data(c->buffer, xfr)) {
+ verbose(VERB_ALGO, "xfr stopped to %s, malloc failed",
+ xfr->task_transfer->master->host);
+ goto failed;
+ }
+ /* if the transfer is done now, disconnect and process the list */
+ if(transferdone) {
+ comm_point_delete(xfr->task_transfer->cp);
+ xfr->task_transfer->cp = NULL;
+ process_list_end_transfer(xfr, env);
+ return 0;
+ }
+
+ /* if we want to read more messages, setup the commpoint to read
+ * a DNS packet, and the timeout */
+ lock_basic_unlock(&xfr->lock);
+ c->tcp_is_reading = 1;
+ sldns_buffer_clear(c->buffer);
+ comm_point_start_listening(c, -1, AUTH_TRANSFER_TIMEOUT);
+ return 0;
+}
+
+/** callback for task_transfer http connections */
+int
+auth_xfer_transfer_http_callback(struct comm_point* c, void* arg, int err,
+ struct comm_reply* repinfo)
+{
+ struct auth_xfer* xfr = (struct auth_xfer*)arg;
+ struct module_env* env;
+ log_assert(xfr->task_transfer);
+ lock_basic_lock(&xfr->lock);
+ env = xfr->task_transfer->env;
+ if(env->outnet->want_to_quit) {
+ lock_basic_unlock(&xfr->lock);
+ return 0; /* stop on quit */
+ }
+ verbose(VERB_ALGO, "auth zone transfer http callback");
+
+ if(err != NETEVENT_NOERROR && err != NETEVENT_DONE) {
+ /* connection failed, closed, or timeout */
+ /* stop this transfer, cleanup
+ * and continue task_transfer*/
+ verbose(VERB_ALGO, "http stopped, connection lost to %s",
+ xfr->task_transfer->master->host);
+ failed:
+ /* delete transferred data from list */
+ auth_chunks_delete(xfr->task_transfer);
+ if(repinfo) repinfo->c = NULL; /* signal cp deleted to
+ the routine calling this callback */
+ comm_point_delete(xfr->task_transfer->cp);
+ xfr->task_transfer->cp = NULL;
+ xfr_transfer_nextmaster(xfr);
+ xfr_transfer_nexttarget_or_end(xfr, env);
+ return 0;
+ }
+
+ /* if it is good, link it into the list of data */
+ /* if the link into list of data fails (malloc fail) cleanup and end */
+ if(sldns_buffer_limit(c->buffer) > 0) {
+ verbose(VERB_ALGO, "auth zone http queued up %d bytes",
+ (int)sldns_buffer_limit(c->buffer));
+ if(!xfer_link_data(c->buffer, xfr)) {
+ verbose(VERB_ALGO, "http stopped to %s, malloc failed",
+ xfr->task_transfer->master->host);
+ goto failed;
+ }
+ }
+ /* if the transfer is done now, disconnect and process the list */
+ if(err == NETEVENT_DONE) {
+ if(repinfo) repinfo->c = NULL; /* signal cp deleted to
+ the routine calling this callback */
+ comm_point_delete(xfr->task_transfer->cp);
+ xfr->task_transfer->cp = NULL;
+ process_list_end_transfer(xfr, env);
+ return 0;
+ }
+
+ /* if we want to read more messages, setup the commpoint to read
+ * a DNS packet, and the timeout */
+ lock_basic_unlock(&xfr->lock);
+ c->tcp_is_reading = 1;
+ sldns_buffer_clear(c->buffer);
+ comm_point_start_listening(c, -1, AUTH_TRANSFER_TIMEOUT);
+ return 0;
+}
+
+
+/** start transfer task by this worker , xfr is locked. */
+static void
+xfr_start_transfer(struct auth_xfer* xfr, struct module_env* env,
+ struct auth_master* master)
+{
+ log_assert(xfr->task_transfer != NULL);
+ log_assert(xfr->task_transfer->worker == NULL);
+ log_assert(xfr->task_transfer->chunks_first == NULL);
+ log_assert(xfr->task_transfer->chunks_last == NULL);
+ xfr->task_transfer->worker = env->worker;
+ xfr->task_transfer->env = env;
+
+ /* init transfer process */
+ /* find that master in the transfer's list of masters? */
+ xfr_transfer_start_list(xfr, master);
+ /* start lookup for hostnames in transfer master list */
+ xfr_transfer_start_lookups(xfr);
+
+ /* initiate TCP, and set timeout on it */
+ xfr_transfer_nexttarget_or_end(xfr, env);
+}
+
+/** disown task_probe. caller must hold xfr.lock */
+static void
+xfr_probe_disown(struct auth_xfer* xfr)
+{
+ /* remove timer (from this worker's event base) */
+ comm_timer_delete(xfr->task_probe->timer);
+ xfr->task_probe->timer = NULL;
+ /* remove the commpoint */
+ comm_point_delete(xfr->task_probe->cp);
+ xfr->task_probe->cp = NULL;
+ /* we don't own this item anymore */
+ xfr->task_probe->worker = NULL;
+ xfr->task_probe->env = NULL;
+}
+
+/** send the UDP probe to the master, this is part of task_probe */
+static int
+xfr_probe_send_probe(struct auth_xfer* xfr, struct module_env* env,
+ int timeout)
+{
+ struct sockaddr_storage addr;
+ socklen_t addrlen = 0;
+ struct timeval t;
+ /* pick master */
+ struct auth_master* master = xfr_probe_current_master(xfr);
+ if(!master) return 0;
+
+ /* get master addr */
+ if(xfr->task_probe->scan_addr) {
+ addrlen = xfr->task_probe->scan_addr->addrlen;
+ memmove(&addr, &xfr->task_probe->scan_addr->addr, addrlen);
+ } else {
+ if(!extstrtoaddr(master->host, &addr, &addrlen)) {
+ /* the ones that are not in addr format are supposed
+ * to be looked up. The lookup has failed however,
+ * so skip them */
+ char zname[255+1];
+ dname_str(xfr->name, zname);
+ log_err("%s: failed lookup, cannot probe to master %s",
+ zname, master->host);
+ return 0;
+ }
+ }
+
+ /* create packet */
+ /* create new ID for new probes, but not on timeout retries,
+ * this means we'll accept replies to previous retries to same ip */
+ if(timeout == AUTH_PROBE_TIMEOUT)
+ xfr->task_probe->id = (uint16_t)(ub_random(env->rnd)&0xffff);
+ xfr_create_soa_probe_packet(xfr, env->scratch_buffer,
+ xfr->task_probe->id);
+ if(!xfr->task_probe->cp) {
+ xfr->task_probe->cp = outnet_comm_point_for_udp(env->outnet,
+ auth_xfer_probe_udp_callback, xfr, &addr, addrlen);
+ if(!xfr->task_probe->cp) {
+ char zname[255+1];
+ dname_str(xfr->name, zname);
+ verbose(VERB_ALGO, "cannot create udp cp for "
+ "probe %s to %s", zname, master->host);
+ return 0;
+ }
+ }
+ if(!xfr->task_probe->timer) {
+ xfr->task_probe->timer = comm_timer_create(env->worker_base,
+ auth_xfer_probe_timer_callback, xfr);
+ if(!xfr->task_probe->timer) {
+ log_err("malloc failure");
+ return 0;
+ }
+ }
+
+ /* send udp packet */
+ if(!comm_point_send_udp_msg(xfr->task_probe->cp, env->scratch_buffer,
+ (struct sockaddr*)&addr, addrlen)) {
+ char zname[255+1];
+ dname_str(xfr->name, zname);
+ verbose(VERB_ALGO, "failed to send soa probe for %s to %s",
+ zname, master->host);
+ return 0;
+ }
+ xfr->task_probe->timeout = timeout;
+#ifndef S_SPLINT_S
+ t.tv_sec = timeout/1000;
+ t.tv_usec = (timeout%1000)*1000;
+#endif
+ comm_timer_set(xfr->task_probe->timer, &t);
+
+ return 1;
+}
+
+/** callback for task_probe timer */
+void
+auth_xfer_probe_timer_callback(void* arg)
+{
+ struct auth_xfer* xfr = (struct auth_xfer*)arg;
+ struct module_env* env;
+ log_assert(xfr->task_probe);
+ lock_basic_lock(&xfr->lock);
+ env = xfr->task_probe->env;
+ if(env->outnet->want_to_quit) {
+ lock_basic_unlock(&xfr->lock);
+ return; /* stop on quit */
+ }
+
+ if(xfr->task_probe->timeout <= AUTH_PROBE_TIMEOUT_STOP) {
+ /* try again with bigger timeout */
+ if(xfr_probe_send_probe(xfr, env, xfr->task_probe->timeout*2)) {
+ lock_basic_unlock(&xfr->lock);
+ return;
+ }
+ }
+ /* delete commpoint so a new one is created, with a fresh port nr */
+ comm_point_delete(xfr->task_probe->cp);
+ xfr->task_probe->cp = NULL;
+
+ /* too many timeouts (or fail to send), move to next or end */
+ xfr_probe_nextmaster(xfr);
+ xfr_probe_send_or_end(xfr, env);
+}
+
+/** callback for task_probe udp packets */
+int
+auth_xfer_probe_udp_callback(struct comm_point* c, void* arg, int err,
+ struct comm_reply* repinfo)
+{
+ struct auth_xfer* xfr = (struct auth_xfer*)arg;
+ struct module_env* env;
+ log_assert(xfr->task_probe);
+ lock_basic_lock(&xfr->lock);
+ env = xfr->task_probe->env;
+ if(env->outnet->want_to_quit) {
+ lock_basic_unlock(&xfr->lock);
+ return 0; /* stop on quit */
+ }
+
+ /* the comm_point_udp_callback is in a for loop for NUM_UDP_PER_SELECT
+ * and we set rep.c=NULL to stop if from looking inside the commpoint*/
+ repinfo->c = NULL;
+ /* stop the timer */
+ comm_timer_disable(xfr->task_probe->timer);
+
+ /* see if we got a packet and what that means */
+ if(err == NETEVENT_NOERROR) {
+ uint32_t serial = 0;
+ if(check_packet_ok(c->buffer, LDNS_RR_TYPE_SOA, xfr,
+ &serial)) {
+ /* successful lookup */
+ if(verbosity >= VERB_ALGO) {
+ char buf[256];
+ dname_str(xfr->name, buf);
+ verbose(VERB_ALGO, "auth zone %s: soa probe "
+ "serial is %u", buf, (unsigned)serial);
+ }
+ /* see if this serial indicates that the zone has
+ * to be updated */
+ if(xfr_serial_means_update(xfr, serial)) {
+ /* if updated, start the transfer task, if needed */
+ verbose(VERB_ALGO, "auth_zone updated, start transfer");
+ if(xfr->task_transfer->worker == NULL) {
+ struct auth_master* master =
+ xfr_probe_current_master(xfr);
+ /* if we have download URLs use them
+ * in preference to this master we
+ * just probed the SOA from */
+ if(xfr->task_transfer->masters &&
+ xfr->task_transfer->masters->http)
+ master = NULL;
+ xfr_probe_disown(xfr);
+ xfr_start_transfer(xfr, env, master);
+ return 0;
+
+ }
+ } else {
+ /* if zone not updated, start the wait timer again */
+ verbose(VERB_ALGO, "auth_zone unchanged, new lease, wait");
+ if(xfr->have_zone)
+ xfr->lease_time = *env->now;
+ if(xfr->task_nextprobe->worker == NULL)
+ xfr_set_timeout(xfr, env, 0);
+ }
+ /* other tasks are running, we don't do this anymore */
+ xfr_probe_disown(xfr);
+ lock_basic_unlock(&xfr->lock);
+ /* return, we don't sent a reply to this udp packet,
+ * and we setup the tasks to do next */
+ return 0;
+ }
+ }
+ if(verbosity >= VERB_ALGO) {
+ char buf[256];
+ dname_str(xfr->name, buf);
+ verbose(VERB_ALGO, "auth zone %s: soa probe failed", buf);
+ }
+
+ /* failed lookup */
+ /* delete commpoint so a new one is created, with a fresh port nr */
+ comm_point_delete(xfr->task_probe->cp);
+ xfr->task_probe->cp = NULL;
+
+ /* if the result was not a successfull probe, we need
+ * to send the next one */
+ xfr_probe_nextmaster(xfr);
+ xfr_probe_send_or_end(xfr, env);
+ return 0;
+}
+
+/** lookup a host name for its addresses, if needed */
+static int
+xfr_probe_lookup_host(struct auth_xfer* xfr, struct module_env* env)
+{
+ struct sockaddr_storage addr;
+ socklen_t addrlen = 0;
+ struct auth_master* master = xfr->task_probe->lookup_target;
+ struct query_info qinfo;
+ uint16_t qflags = BIT_RD;
+ uint8_t dname[LDNS_MAX_DOMAINLEN+1];
+ struct edns_data edns;
+ sldns_buffer* buf = env->scratch_buffer;
+ if(!master) return 0;
+ if(extstrtoaddr(master->host, &addr, &addrlen)) {
+ /* not needed, host is in IP addr format */
+ return 0;
+ }
+
+ /* use mesh_new_callback to probe for non-addr hosts,
+ * and then wait for them to be looked up (in cache, or query) */
+ qinfo.qname_len = sizeof(dname);
+ if(sldns_str2wire_dname_buf(master->host, dname, &qinfo.qname_len)
+ != 0) {
+ log_err("cannot parse host name of master %s", master->host);
+ return 0;
+ }
+ qinfo.qname = dname;
+ qinfo.qclass = xfr->dclass;
+ qinfo.qtype = LDNS_RR_TYPE_A;
+ if(xfr->task_probe->lookup_aaaa)
+ qinfo.qtype = LDNS_RR_TYPE_AAAA;
+ qinfo.local_alias = NULL;
+ if(verbosity >= VERB_ALGO) {
+ char buf[512];
+ char buf2[LDNS_MAX_DOMAINLEN+1];
+ dname_str(xfr->name, buf2);
+ snprintf(buf, sizeof(buf), "auth zone %s: master lookup"
+ " for task_probe", buf2);
+ log_query_info(VERB_ALGO, buf, &qinfo);
+ }
+ edns.edns_present = 1;
+ edns.ext_rcode = 0;
+ edns.edns_version = 0;
+ edns.bits = EDNS_DO;
+ edns.opt_list = NULL;
+ if(sldns_buffer_capacity(buf) < 65535)
+ edns.udp_size = (uint16_t)sldns_buffer_capacity(buf);
+ else edns.udp_size = 65535;
+
+ /* unlock xfr during mesh_new_callback() because the callback can be
+ * called straight away */
+ lock_basic_unlock(&xfr->lock);
+ if(!mesh_new_callback(env->mesh, &qinfo, qflags, &edns, buf, 0,
+ &auth_xfer_probe_lookup_callback, xfr)) {
+ lock_basic_lock(&xfr->lock);
+ log_err("out of memory lookup up master %s", master->host);
+ return 0;
+ }
+ lock_basic_lock(&xfr->lock);
+ return 1;
+}
+
+/** 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)
+{
+ /* are we doing hostname lookups? */
+ while(xfr->task_probe->lookup_target) {
+ if(xfr_probe_lookup_host(xfr, env)) {
+ /* wait for lookup to finish,
+ * note that the hostname may be in unbound's cache
+ * and we may then get an instant cache response,
+ * and that calls the callback just like a full
+ * lookup and lookup failures also call callback */
+ lock_basic_unlock(&xfr->lock);
+ return;
+ }
+ xfr_probe_move_to_next_lookup(xfr, env);
+ }
+
+ /* send probe packets */
+ while(!xfr_probe_end_of_list(xfr)) {
+ if(xfr_probe_send_probe(xfr, env, AUTH_PROBE_TIMEOUT)) {
+ /* successfully sent probe, wait for callback */
+ lock_basic_unlock(&xfr->lock);
+ return;
+ }
+ /* failed to send probe, next master */
+ xfr_probe_nextmaster(xfr);
+ }
+
+ /* we failed to send this as well, move to the wait task,
+ * use the shorter retry timeout */
+ xfr_probe_disown(xfr);
+
+ /* pick up the nextprobe task and wait */
+ xfr_set_timeout(xfr, env, 1);
+ lock_basic_unlock(&xfr->lock);
+}
+
+/** callback for task_probe lookup of host name, of A or AAAA */
+void auth_xfer_probe_lookup_callback(void* arg, int rcode, sldns_buffer* buf,
+ enum sec_status ATTR_UNUSED(sec), char* ATTR_UNUSED(why_bogus))
+{
+ struct auth_xfer* xfr = (struct auth_xfer*)arg;
+ struct module_env* env;
+ log_assert(xfr->task_probe);
+ lock_basic_lock(&xfr->lock);
+ env = xfr->task_probe->env;
+ if(env->outnet->want_to_quit) {
+ lock_basic_unlock(&xfr->lock);
+ return; /* stop on quit */
+ }
+
+ /* process result */
+ if(rcode == LDNS_RCODE_NOERROR) {
+ uint16_t wanted_qtype = LDNS_RR_TYPE_A;
+ struct regional* temp = env->scratch;
+ struct query_info rq;
+ struct reply_info* rep;
+ if(xfr->task_probe->lookup_aaaa)
+ wanted_qtype = LDNS_RR_TYPE_AAAA;
+ memset(&rq, 0, sizeof(rq));
+ rep = parse_reply_in_temp_region(buf, temp, &rq);
+ if(rep && rq.qtype == wanted_qtype &&
+ FLAGS_GET_RCODE(rep->flags) == LDNS_RCODE_NOERROR) {
+ /* parsed successfully */
+ struct ub_packed_rrset_key* answer =
+ reply_find_answer_rrset(&rq, rep);
+ if(answer) {
+ xfr_master_add_addrs(xfr->task_probe->
+ lookup_target, answer, wanted_qtype);
+ }
+ }
+ }
+ if(xfr->task_probe->lookup_target->list &&
+ xfr->task_probe->lookup_target == xfr_probe_current_master(xfr))
+ xfr->task_probe->scan_addr = xfr->task_probe->lookup_target->list;
+
+ /* move to lookup AAAA after A lookup, move to next hostname lookup,
+ * or move to send the probes, or, if nothing to do, end task_probe */
+ xfr_probe_move_to_next_lookup(xfr, env);
+ xfr_probe_send_or_end(xfr, env);
+}
+
+/** disown task_nextprobe. caller must hold xfr.lock */
+static void
+xfr_nextprobe_disown(struct auth_xfer* xfr)
+{
+ /* delete the timer, because the next worker to pick this up may
+ * not have the same event base */
+ comm_timer_delete(xfr->task_nextprobe->timer);
+ xfr->task_nextprobe->timer = NULL;
+ xfr->task_nextprobe->next_probe = 0;
+ /* we don't own this item anymore */
+ xfr->task_nextprobe->worker = NULL;
+ xfr->task_nextprobe->env = NULL;
+}
+
+/** xfer nextprobe timeout callback, this is part of task_nextprobe */
+void
+auth_xfer_timer(void* arg)
+{
+ struct auth_xfer* xfr = (struct auth_xfer*)arg;
+ struct module_env* env;
+ log_assert(xfr->task_nextprobe);
+ lock_basic_lock(&xfr->lock);
+ env = xfr->task_nextprobe->env;
+ if(env->outnet->want_to_quit) {
+ lock_basic_unlock(&xfr->lock);
+ return; /* stop on quit */
+ }
+
+ /* see if zone has expired, and if so, also set auth_zone expired */
+ if(xfr->have_zone && !xfr->zone_expired &&
+ *env->now >= xfr->lease_time + xfr->expiry) {
+ lock_basic_unlock(&xfr->lock);
+ auth_xfer_set_expired(xfr, env, 1);
+ lock_basic_lock(&xfr->lock);
+ }
+
+ xfr_nextprobe_disown(xfr);
+
+ /* 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) {
+ /* 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);
+ }
+ return;
+ }
+
+ /* pick up the probe task ourselves */
+ xfr->task_probe->worker = env->worker;
+ xfr->task_probe->env = env;
+ 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);
+ /* 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);
+ }
+}
+
+/** for task_nextprobe.
+ * determine next timeout for auth_xfer. Also (re)sets timer.
+ * @param xfr: task structure
+ * @param env: module environment, with worker and time.
+ * @param failure: set true if timer should be set for failure retry.
+ */
+static void
+xfr_set_timeout(struct auth_xfer* xfr, struct module_env* env,
+ int failure)
+{
+ struct timeval tv;
+ log_assert(xfr->task_nextprobe != NULL);
+ log_assert(xfr->task_nextprobe->worker == NULL ||
+ xfr->task_nextprobe->worker == env->worker);
+ /* normally, nextprobe = startoflease + refresh,
+ * 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)
+ xfr->task_nextprobe->next_probe = xfr->lease_time;
+
+ if(!failure) {
+ xfr->task_nextprobe->backoff = 0;
+ } else {
+ if(xfr->task_nextprobe->backoff == 0)
+ xfr->task_nextprobe->backoff = 3;
+ else xfr->task_nextprobe->backoff *= 2;
+ if(xfr->task_nextprobe->backoff > AUTH_TRANSFER_MAX_BACKOFF)
+ xfr->task_nextprobe->backoff =
+ AUTH_TRANSFER_MAX_BACKOFF;
+ }
+
+ if(xfr->have_zone) {
+ time_t wait = xfr->refresh;
+ if(failure) wait = xfr->retry;
+ if(xfr->expiry < wait)
+ xfr->task_nextprobe->next_probe += xfr->expiry;
+ else xfr->task_nextprobe->next_probe += wait;
+ if(failure)
+ xfr->task_nextprobe->next_probe +=
+ xfr->task_nextprobe->backoff;
+ } else {
+ xfr->task_nextprobe->next_probe +=
+ xfr->task_nextprobe->backoff;
+ }
+
+ if(!xfr->task_nextprobe->timer) {
+ xfr->task_nextprobe->timer = comm_timer_create(
+ env->worker_base, auth_xfer_timer, xfr);
+ if(!xfr->task_nextprobe->timer) {
+ /* failed to malloc memory. likely zone transfer
+ * also fails for that. skip the timeout */
+ char zname[255+1];
+ dname_str(xfr->name, zname);
+ log_err("cannot allocate timer, no refresh for %s",
+ zname);
+ return;
+ }
+ }
+ xfr->task_nextprobe->worker = env->worker;
+ xfr->task_nextprobe->env = env;
+ if(*(xfr->task_nextprobe->env->now) <= xfr->task_nextprobe->next_probe)
+ tv.tv_sec = xfr->task_nextprobe->next_probe -
+ *(xfr->task_nextprobe->env->now);
+ else tv.tv_sec = 0;
+ if(verbosity >= VERB_ALGO) {
+ char zname[255+1];
+ dname_str(xfr->name, zname);
+ verbose(VERB_ALGO, "auth zone %s timeout in %d seconds",
+ zname, (int)tv.tv_sec);
+ }
+ tv.tv_usec = 0;
+ comm_timer_set(xfr->task_nextprobe->timer, &tv);
+}
+
+/** initial pick up of worker timeouts, ties events to worker event loop */
+void
+auth_xfer_pickup_initial(struct auth_zones* az, struct module_env* env)
+{
+ struct auth_xfer* x;
+ lock_rw_wrlock(&az->lock);
+ RBTREE_FOR(x, struct auth_xfer*, &az->xtree) {
+ lock_basic_lock(&x->lock);
+ /* set lease_time, because we now have timestamp in env,
+ * (not earlier during startup and apply_cfg), and this
+ * 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);
+ lock_basic_unlock(&x->lock);
+ }
+ lock_rw_unlock(&az->lock);
+}
+
+void auth_zones_cleanup(struct auth_zones* az)
+{
+ struct auth_xfer* x;
+ lock_rw_wrlock(&az->lock);
+ RBTREE_FOR(x, struct auth_xfer*, &az->xtree) {
+ lock_basic_lock(&x->lock);
+ if(x->task_nextprobe && x->task_nextprobe->worker != NULL) {
+ xfr_nextprobe_disown(x);
+ }
+ if(x->task_probe && x->task_probe->worker != NULL) {
+ xfr_probe_disown(x);
+ }
+ if(x->task_transfer && x->task_transfer->worker != NULL) {
+ auth_chunks_delete(x->task_transfer);
+ xfr_transfer_disown(x);
+ }
+ lock_basic_unlock(&x->lock);
+ }
+ lock_rw_unlock(&az->lock);
+}
+
+/**
+ * malloc the xfer and tasks
+ * @param z: auth_zone with name of zone.
+ */
+static struct auth_xfer*
+auth_xfer_new(struct auth_zone* z)
+{
+ struct auth_xfer* xfr;
+ xfr = (struct auth_xfer*)calloc(1, sizeof(*xfr));
+ if(!xfr) return NULL;
+ xfr->name = memdup(z->name, z->namelen);
+ if(!xfr->name) {
+ free(xfr);
+ return NULL;
+ }
+ xfr->node.key = xfr;
+ xfr->namelen = z->namelen;
+ xfr->namelabs = z->namelabs;
+ xfr->dclass = z->dclass;
+
+ xfr->task_nextprobe = (struct auth_nextprobe*)calloc(1,
+ sizeof(struct auth_nextprobe));
+ if(!xfr->task_nextprobe) {
+ free(xfr->name);
+ free(xfr);
+ return NULL;
+ }
+ xfr->task_probe = (struct auth_probe*)calloc(1,
+ sizeof(struct auth_probe));
+ if(!xfr->task_probe) {
+ free(xfr->task_nextprobe);
+ free(xfr->name);
+ free(xfr);
+ return NULL;
+ }
+ xfr->task_transfer = (struct auth_transfer*)calloc(1,
+ sizeof(struct auth_transfer));
+ if(!xfr->task_transfer) {
+ free(xfr->task_probe);
+ free(xfr->task_nextprobe);
+ free(xfr->name);
+ free(xfr);
+ return NULL;
+ }
+
+ lock_basic_init(&xfr->lock);
+ lock_protect(&xfr->lock, &xfr->name, sizeof(xfr->name));
+ lock_protect(&xfr->lock, &xfr->namelen, sizeof(xfr->namelen));
+ lock_protect(&xfr->lock, xfr->name, xfr->namelen);
+ lock_protect(&xfr->lock, &xfr->namelabs, sizeof(xfr->namelabs));
+ lock_protect(&xfr->lock, &xfr->dclass, sizeof(xfr->dclass));
+ lock_protect(&xfr->lock, &xfr->notify_received, sizeof(xfr->notify_received));
+ lock_protect(&xfr->lock, &xfr->notify_serial, sizeof(xfr->notify_serial));
+ lock_protect(&xfr->lock, &xfr->zone_expired, sizeof(xfr->zone_expired));
+ lock_protect(&xfr->lock, &xfr->have_zone, sizeof(xfr->have_zone));
+ lock_protect(&xfr->lock, &xfr->serial, sizeof(xfr->serial));
+ lock_protect(&xfr->lock, &xfr->retry, sizeof(xfr->retry));
+ lock_protect(&xfr->lock, &xfr->refresh, sizeof(xfr->refresh));
+ lock_protect(&xfr->lock, &xfr->expiry, sizeof(xfr->expiry));
+ lock_protect(&xfr->lock, &xfr->lease_time, sizeof(xfr->lease_time));
+ lock_protect(&xfr->lock, &xfr->task_nextprobe->worker,
+ sizeof(xfr->task_nextprobe->worker));
+ lock_protect(&xfr->lock, &xfr->task_probe->worker,
+ sizeof(xfr->task_probe->worker));
+ lock_protect(&xfr->lock, &xfr->task_transfer->worker,
+ sizeof(xfr->task_transfer->worker));
+ lock_basic_lock(&xfr->lock);
+ return xfr;
+}
+
+/** Create auth_xfer structure.
+ * This populates the have_zone, soa values, and so on times.
+ * and sets the timeout, if a zone transfer is needed a short timeout is set.
+ * For that the auth_zone itself must exist (and read in zonefile)
+ * returns false on alloc failure. */
+struct auth_xfer*
+auth_xfer_create(struct auth_zones* az, struct auth_zone* z)
+{
+ struct auth_xfer* xfr;
+
+ /* malloc it */
+ xfr = auth_xfer_new(z);
+ if(!xfr) {
+ log_err("malloc failure");
+ return NULL;
+ }
+ /* insert in tree */
+ (void)rbtree_insert(&az->xtree, &xfr->node);
+ return xfr;
+}
+
+/** create new auth_master structure */
+static struct auth_master*
+auth_master_new(struct auth_master*** list)
+{
+ struct auth_master *m;
+ m = (struct auth_master*)calloc(1, sizeof(*m));
+ if(!m) {
+ log_err("malloc failure");
+ return NULL;
+ }
+ /* set first pointer to m, or next pointer of previous element to m */
+ (**list) = m;
+ /* store m's next pointer as future point to store at */
+ (*list) = &(m->next);
+ return m;
+}
+
+/** dup_prefix : create string from initial part of other string, malloced */
+static char*
+dup_prefix(char* str, size_t num)
+{
+ char* result;
+ size_t len = strlen(str);
+ if(len < num) num = len; /* not more than strlen */
+ result = (char*)malloc(num+1);
+ if(!result) {
+ log_err("malloc failure");
+ return result;
+ }
+ memmove(result, str, num);
+ result[num] = 0;
+ return result;
+}
+
+/** dup string and print error on error */
+static char*
+dup_all(char* str)
+{
+ char* result = strdup(str);
+ if(!str) {
+ log_err("malloc failure");
+ return NULL;
+ }
+ return result;
+}
+
+/** find first of two characters */
+static char*
+str_find_first_of_chars(char* s, char a, char b)
+{
+ char* ra = strchr(s, a);
+ char* rb = strchr(s, b);
+ if(!ra) return rb;
+ if(!rb) return ra;
+ if(ra < rb) return ra;
+ return rb;
+}
+
+/** parse URL into host and file parts, false on malloc or parse error */
+static int
+parse_url(char* url, char** host, char** file, int* port, int* ssl)
+{
+ char* p = url;
+ /* parse http://www.example.com/file.htm
+ * or http://127.0.0.1 (index.html)
+ * or https://[::1@1234]/a/b/c/d */
+ *ssl = 1;
+ *port = AUTH_HTTPS_PORT;
+
+ /* parse http:// or https:// */
+ if(strncmp(p, "http://", 7) == 0) {
+ p += 7;
+ *ssl = 0;
+ *port = AUTH_HTTP_PORT;
+ } else if(strncmp(p, "https://", 8) == 0) {
+ p += 8;
+ } else if(strstr(p, "://") && strchr(p, '/') > strstr(p, "://") &&
+ strchr(p, ':') >= strstr(p, "://")) {
+ char* uri = dup_prefix(p, (size_t)(strstr(p, "://")-p));
+ log_err("protocol %s:// not supported (for url %s)",
+ uri?uri:"", p);
+ free(uri);
+ return 0;
+ }
+
+ /* parse hostname part */
+ if(p[0] == '[') {
+ char* end = strchr(p, ']');
+ p++; /* skip over [ */
+ if(end) {
+ *host = dup_prefix(p, (size_t)(end-p));
+ if(!*host) return 0;
+ p = end+1; /* skip over ] */
+ } else {
+ *host = dup_all(p);
+ if(!*host) return 0;
+ p = end;
+ }
+ } else {
+ char* end = str_find_first_of_chars(p, ':', '/');
+ if(end) {
+ *host = dup_prefix(p, (size_t)(end-p));
+ if(!*host) return 0;
+ } else {
+ *host = dup_all(p);
+ if(!*host) return 0;
+ }
+ p = end; /* at next : or / or NULL */
+ }
+
+ /* parse port number */
+ if(p && p[0] == ':') {
+ char* end = NULL;
+ *port = strtol(p+1, &end, 10);
+ p = end;
+ }
+
+ /* parse filename part */
+ while(p && *p == '/')
+ p++;
+ if(!p || p[0] == 0)
+ *file = strdup("index.html");
+ else *file = strdup(p);
+ if(!*file) {
+ log_err("malloc failure");
+ return 0;
+ }
+ return 1;
+}
+
+int
+xfer_set_masters(struct auth_master** list, struct config_auth* c,
+ int with_http)
+{
+ struct auth_master* m;
+ struct config_strlist* p;
+ /* list points to the first, or next pointer for the new element */
+ while(*list) {
+ list = &( (*list)->next );
+ }
+ if(with_http)
+ for(p = c->urls; p; p = p->next) {
+ m = auth_master_new(&list);
+ m->http = 1;
+ if(!parse_url(p->str, &m->host, &m->file, &m->port, &m->ssl))
+ return 0;
+ }
+ for(p = c->masters; p; p = p->next) {
+ m = auth_master_new(&list);
+ m->ixfr = 1; /* this flag is not configurable */
+ m->host = strdup(p->str);
+ if(!m->host) {
+ log_err("malloc failure");
+ return 0;
+ }
+ }
+ return 1;
+}
+
+#define SERIAL_BITS 32
+int
+compare_serial(uint32_t a, uint32_t b)
+{
+ const uint32_t cutoff = ((uint32_t) 1 << (SERIAL_BITS - 1));
+
+ if (a == b) {
+ return 0;
+ } else if ((a < b && b - a < cutoff) || (a > b && a - b > cutoff)) {
+ return -1;
+ } else {
+ return 1;
+ }
+}
diff --git a/services/authzone.h b/services/authzone.h
index 5b4623b65200..d54ef4b96e49 100644
--- a/services/authzone.h
+++ b/services/authzone.h
@@ -45,20 +45,38 @@
#define SERVICES_AUTHZONE_H
#include "util/rbtree.h"
#include "util/locks.h"
+#include "services/mesh.h"
struct ub_packed_rrset_key;
struct regional;
struct config_file;
+struct config_auth;
struct query_info;
struct dns_msg;
+struct edns_data;
+struct module_env;
+struct worker;
+struct comm_point;
+struct comm_timer;
+struct comm_reply;
+struct auth_rrset;
+struct auth_nextprobe;
+struct auth_probe;
+struct auth_transfer;
+struct auth_master;
+struct auth_chunk;
/**
* Authoritative zones, shared.
*/
struct auth_zones {
- /** lock on the authzone tree */
+ /** lock on the authzone trees */
lock_rw_type lock;
/** rbtree of struct auth_zone */
rbtree_type ztree;
+ /** rbtree of struct auth_xfer */
+ rbtree_type xtree;
+ /** do we have downstream enabled */
+ int have_downstream;
};
/**
@@ -89,10 +107,21 @@ struct auth_zone {
* rbtree of struct auth_data */
rbtree_type data;
- /* zonefile name (or NULL for no zonefile) */
+ /** zonefile name (or NULL for no zonefile) */
char* zonefile;
- /* fallback to the internet on failure or ttl-expiry of auth zone */
+ /** fallback to the internet on failure or ttl-expiry of auth zone */
int fallback_enabled;
+ /** the zone has expired (enabled by the xfer worker), fallback
+ * happens if that option is enabled. */
+ int zone_expired;
+ /** zone is a slave zone (it has masters) */
+ int zone_is_slave;
+ /** for downstream: this zone answers queries towards the downstream
+ * clients */
+ int for_downstream;
+ /** for upstream: this zone answers queries that unbound intends to
+ * send upstream. */
+ int for_upstream;
};
/**
@@ -128,14 +157,297 @@ struct auth_rrset {
};
/**
+ * Authoritative zone transfer structure.
+ * Create and destroy needs the auth_zones* biglock.
+ * The structure consists of different tasks. Each can be unowned (-1) or
+ * owner by a worker (worker-num). A worker can pick up a task and then do
+ * it. This means the events (timeouts, sockets) are for that worker.
+ *
+ * (move this to tasks).
+ * They don't have locks themselves, the worker (that owns it) uses it,
+ * also as part of callbacks, hence it has separate zonename pointers for
+ * lookup in the main zonetree. If the zone has no transfers, this
+ * structure is not created.
+ */
+struct auth_xfer {
+ /** rbtree node, key is name and class */
+ rbnode_type node;
+
+ /** lock on this structure, and on the workernum elements of the
+ * tasks. First hold the tree-lock in auth_zones, find the auth_xfer,
+ * lock this lock. Then a worker can reassign itself to fill up
+ * one of the tasks.
+ * Once it has the task assigned to it, the worker can access the
+ * other elements of the task structure without a lock, because that
+ * is necessary for the eventloop and callbacks from that. */
+ lock_basic_type lock;
+
+ /** zone name, in uncompressed wireformat */
+ uint8_t* name;
+ /** length of zone name */
+ size_t namelen;
+ /** number of labels in zone name */
+ int namelabs;
+ /** the class of this zone, in host byteorder.
+ * uses 'dclass' to not conflict with c++ keyword class. */
+ uint16_t dclass;
+
+ /** task to wait for next-probe-timeout,
+ * once timeouted, see if a SOA probe is needed, or already
+ * in progress */
+ struct auth_nextprobe* task_nextprobe;
+
+ /** task for SOA probe. Check if the zone can be updated */
+ struct auth_probe* task_probe;
+
+ /** Task for transfer. Transferring and updating the zone. This
+ * includes trying (potentially) several upstream masters. Downloading
+ * and storing the zone */
+ struct auth_transfer* task_transfer;
+
+ /** a notify was received, but a zone transfer or probe was already
+ * acted on.
+ * However, the zone transfer could signal a newer serial number.
+ * The serial number of that notify is saved below. The transfer and
+ * probe tasks should check this once done to see if they need to
+ * restart the transfer task for the newer notify serial.
+ * Hold the lock to access this member (and the serial).
+ */
+ int notify_received;
+ /** serial number of the notify */
+ uint32_t notify_serial;
+
+ /* protected by the lock on the structure, information about
+ * the loaded authority zone. */
+ /** is the zone currently considered expired? after expiry also older
+ * serial numbers are allowed (not just newer) */
+ int zone_expired;
+ /** do we have a zone (if 0, no zone data at all) */
+ int have_zone;
+
+ /** current serial (from SOA), if we have no zone, 0 */
+ uint32_t serial;
+ /** retry time (from SOA), time to wait with next_probe
+ * if no master responds */
+ time_t retry;
+ /** refresh time (from SOA), time to wait with next_probe
+ * if everything is fine */
+ time_t refresh;
+ /** expiry time (from SOA), time until zone data is not considered
+ * valid any more, if no master responds within this time, either
+ * with the current zone or a new zone. */
+ time_t expiry;
+
+ /** zone lease start time (start+expiry is expiration time).
+ * this is renewed every SOA probe and transfer. On zone load
+ * from zonefile it is also set (with probe set soon to check) */
+ time_t lease_time;
+};
+
+/**
+ * The next probe task.
+ * This task consists of waiting for the probetimeout. It is a task because
+ * it needs an event in the eventtable. Once the timeout has passed, that
+ * worker can (potentially) become the auth_probe worker, or if another worker
+ * is already doing that, do nothing. Tasks becomes unowned.
+ * The probe worker, if it detects nothing has to be done picks up this task,
+ * if unowned.
+ */
+struct auth_nextprobe {
+ /* Worker pointer. NULL means unowned. */
+ struct worker* worker;
+ /* module env for this task */
+ struct module_env* env;
+
+ /** increasing backoff for failures */
+ time_t backoff;
+ /** Timeout for next probe (for SOA) */
+ time_t next_probe;
+ /** timeout callback for next_probe or expiry(if that is sooner).
+ * it is on the worker's event_base */
+ struct comm_timer* timer;
+};
+
+/**
+ * The probe task.
+ * Send a SOA UDP query to see if the zone needs to be updated (or similar,
+ * potential, HTTP probe query) and check serial number.
+ * If yes, start the auth_transfer task. If no, make sure auth_nextprobe
+ * timeout wait task is running.
+ * Needs to be a task, because the UDP query needs an event entry.
+ * This task could also be started by eg. a NOTIFY being received, even though
+ * another worker is performing the nextprobe task (and that worker keeps
+ * waiting uninterrupted).
+ */
+struct auth_probe {
+ /* Worker pointer. NULL means unowned. */
+ struct worker* worker;
+ /* module env for this task */
+ struct module_env* env;
+
+ /** list of upstream masters for this zone, from config */
+ struct auth_master* masters;
+
+ /** for the hostname lookups, which master is current */
+ struct auth_master* lookup_target;
+ /** are we looking up A or AAAA, first A, then AAAA (if ip6 enabled) */
+ int lookup_aaaa;
+
+ /** once notified, or the timeout has been reached. a scan starts. */
+ /** the scan specific target (notify source), or NULL if none */
+ struct auth_master* scan_specific;
+ /** scan tries all the upstream masters. the scan current target.
+ * or NULL if not working on sequential scan */
+ struct auth_master* scan_target;
+ /** if not NULL, the specific addr for the current master */
+ struct auth_addr* scan_addr;
+
+ /** dns id of packet in flight */
+ uint16_t id;
+ /** the SOA probe udp event.
+ * on the workers event base. */
+ struct comm_point* cp;
+ /** timeout for packets.
+ * on the workers event base. */
+ struct comm_timer* timer;
+ /** timeout in msec */
+ int timeout;
+};
+
+/**
+ * The transfer task.
+ * Once done, make sure the nextprobe waiting task is running, whether done
+ * with failure or success. If failure, use shorter timeout for wait time.
+ */
+struct auth_transfer {
+ /* Worker pointer. NULL means unowned. */
+ struct worker* worker;
+ /* module env for this task */
+ struct module_env* env;
+
+ /** xfer data that has been transferred, the data is applied
+ * once the transfer has completed correctly */
+ struct auth_chunk* chunks_first;
+ /** last element in chunks list (to append new data at the end) */
+ struct auth_chunk* chunks_last;
+
+ /** list of upstream masters for this zone, from config */
+ struct auth_master* masters;
+
+ /** for the hostname lookups, which master is current */
+ struct auth_master* lookup_target;
+ /** are we looking up A or AAAA, first A, then AAAA (if ip6 enabled) */
+ int lookup_aaaa;
+
+ /** once notified, or the timeout has been reached. a scan starts. */
+ /** the scan specific target (notify source), or NULL if none */
+ struct auth_master* scan_specific;
+ /** scan tries all the upstream masters. the scan current target.
+ * or NULL if not working on sequential scan */
+ struct auth_master* scan_target;
+ /** what address we are scanning for the master, or NULL if the
+ * master is in IP format itself */
+ struct auth_addr* scan_addr;
+ /** the zone transfer in progress (or NULL if in scan). It is
+ * from this master */
+ struct auth_master* master;
+
+ /** failed ixfr transfer, retry with axfr (to the current master),
+ * the IXFR was 'REFUSED', 'SERVFAIL', 'NOTIMPL' or the contents of
+ * the IXFR did not apply cleanly (out of sync, delete of nonexistent
+ * data or add of duplicate data). Flag is cleared once the retry
+ * with axfr is done. */
+ int ixfr_fail;
+ /** we are doing IXFR right now */
+ int on_ixfr;
+ /** did we detect the current AXFR/IXFR serial number yet, 0 not yet,
+ * 1 we saw the first, 2 we saw the second, 3 must be last SOA in xfr*/
+ int got_xfr_serial;
+ /** number of RRs scanned for AXFR/IXFR detection */
+ size_t rr_scan_num;
+ /** we are doing an IXFR but we detected an AXFR contents */
+ int on_ixfr_is_axfr;
+ /** the serial number for the current AXFR/IXFR incoming reply,
+ * for IXFR, the outermost SOA records serial */
+ uint32_t incoming_xfr_serial;
+
+ /** dns id of AXFR query */
+ uint16_t id;
+ /** the transfer (TCP) to the master.
+ * on the workers event base. */
+ struct comm_point* cp;
+};
+
+/** list of addresses */
+struct auth_addr {
+ /** next in list */
+ struct auth_addr* next;
+ /** IP address */
+ struct sockaddr_storage addr;
+ /** addr length */
+ socklen_t addrlen;
+};
+
+/** auth zone master upstream, and the config settings for it */
+struct auth_master {
+ /** next master in list */
+ struct auth_master* next;
+ /** master IP address (and port), or hostname, string */
+ char* host;
+ /** for http, filename */
+ char* file;
+ /** use HTTP for this master */
+ int http;
+ /** use IXFR for this master */
+ int ixfr;
+ /** use ssl for channel */
+ int ssl;
+ /** the port number (for urls) */
+ int port;
+ /** if the host is a hostname, the list of resolved addrs, if any*/
+ struct auth_addr* list;
+};
+
+/** auth zone master zone transfer data chunk */
+struct auth_chunk {
+ /** next chunk in list */
+ struct auth_chunk* next;
+ /** the data from this chunk, this is what was received.
+ * for an IXFR that means results from comm_net tcp actions,
+ * packets. also for an AXFR. For HTTP a zonefile chunk. */
+ uint8_t* data;
+ /** length of allocated data */
+ size_t len;
+};
+
+/**
* Create auth zones structure
*/
struct auth_zones* auth_zones_create(void);
/**
* Apply configuration to auth zones. Reads zonefiles.
+ * @param az: auth zones structure
+ * @param cfg: config to apply.
+ * @param setup: if true, also sets up values in the auth zones structure
+ * @return false on failure.
+ */
+int auth_zones_apply_cfg(struct auth_zones* az, struct config_file* cfg,
+ int setup);
+
+/** initial pick up of worker timeouts, ties events to worker event loop
+ * @param az: auth zones structure
+ * @param env: worker env, of first worker that receives the events (if any)
+ * in its eventloop.
+ */
+void auth_xfer_pickup_initial(struct auth_zones* az, struct module_env* env);
+
+/**
+ * Cleanup auth zones. This removes all events from event bases.
+ * Stops the xfr tasks. But leaves zone data.
+ * @param az: auth zones structure.
*/
-int auth_zones_apply_config(struct auth_zones* az, struct config_file* cfg);
+void auth_zones_cleanup(struct auth_zones* az);
/**
* Delete auth zones structure
@@ -170,21 +482,41 @@ int auth_zones_lookup(struct auth_zones* az, struct query_info* qinfo,
struct regional* region, struct dns_msg** msg, int* fallback,
uint8_t* dp_nm, size_t dp_nmlen);
+/**
+ * Answer query from auth zone. Create authoritative answer.
+ * @param az: auth zones structure.
+ * @param env: the module environment.
+ * @param qinfo: query info (parsed).
+ * @param edns: edns info (parsed).
+ * @param buf: buffer with query ID and flags, also for reply.
+ * @param temp: temporary storage region.
+ * @return false if not answered
+ */
+int auth_zones_answer(struct auth_zones* az, struct module_env* env,
+ struct query_info* qinfo, struct edns_data* edns, struct sldns_buffer* buf,
+ struct regional* temp);
+
/**
* Find the auth zone that is above the given qname.
* Return NULL when there is no auth_zone above the give name, otherwise
* returns the closest auth_zone above the qname that pertains to it.
* @param az: auth zones structure.
- * @param qinfo: query info to lookup.
+ * @param name: query to look up for.
+ * @param name_len: length of name.
+ * @param dclass: class of zone to find.
* @return NULL or auth_zone that pertains to the query.
*/
struct auth_zone* auth_zones_find_zone(struct auth_zones* az,
- struct query_info* qinfo);
+ uint8_t* name, size_t name_len, uint16_t dclass);
/** find an auth zone by name (exact match by name or NULL returned) */
struct auth_zone* auth_zone_find(struct auth_zones* az, uint8_t* nm,
size_t nmlen, uint16_t dclass);
+/** find an xfer zone by name (exact match by name or NULL returned) */
+struct auth_xfer* auth_xfer_find(struct auth_zones* az, uint8_t* nm,
+ size_t nmlen, uint16_t dclass);
+
/** create an auth zone. returns wrlocked zone. caller must have wrlock
* on az. returns NULL on malloc failure */
struct auth_zone* auth_zone_create(struct auth_zones* az, uint8_t* nm,
@@ -197,6 +529,18 @@ int auth_zone_set_zonefile(struct auth_zone* z, char* zonefile);
* fallbackstr is "yes" or "no". false on parse failure. */
int auth_zone_set_fallback(struct auth_zone* z, char* fallbackstr);
+/** see if the auth zone for the name can fallback
+ * @param az: auth zones
+ * @param nm: name of delegation point.
+ * @param nmlen: length of nm.
+ * @param dclass: class of zone to look for.
+ * @return true if fallback_enabled is true. false if not.
+ * if the zone does not exist, fallback is true (more lenient)
+ * also true if zone does not do upstream requests.
+ */
+int auth_zones_can_fallback(struct auth_zones* az, uint8_t* nm, size_t nmlen,
+ uint16_t dclass);
+
/** read auth zone from zonefile. caller must lock zone. false on failure */
int auth_zone_read_zonefile(struct auth_zone* z);
@@ -206,4 +550,54 @@ int auth_zone_cmp(const void* z1, const void* z2);
/** compare auth_data for sorted rbtree */
int auth_data_cmp(const void* z1, const void* z2);
+/** compare auth_xfer for sorted rbtree */
+int auth_xfer_cmp(const void* z1, const void* z2);
+
+/** Create auth_xfer structure.
+ * Caller must have wrlock on az. Returns locked xfer zone.
+ * @param az: zones structure.
+ * @param z: zone with name and class
+ * @return xfer zone or NULL
+ */
+struct auth_xfer* auth_xfer_create(struct auth_zones* az, struct auth_zone* z);
+
+/**
+ * Set masters in auth xfer structure from config.
+ * @param list: pointer to start of list. The malloced list is returned here.
+ * @param c: the config items to copy over.
+ * @param with_http: if true, http urls are also included, before the masters.
+ * @return false on failure.
+ */
+int xfer_set_masters(struct auth_master** list, struct config_auth* c,
+ int with_http);
+
+/** xfer nextprobe timeout callback, this is part of task_nextprobe */
+void auth_xfer_timer(void* arg);
+
+/** callback for commpoint udp replies to task_probe */
+int auth_xfer_probe_udp_callback(struct comm_point* c, void* arg, int err,
+ struct comm_reply* repinfo);
+/** callback for task_transfer tcp connections */
+int auth_xfer_transfer_tcp_callback(struct comm_point* c, void* arg, int err,
+ struct comm_reply* repinfo);
+/** callback for task_transfer http connections */
+int auth_xfer_transfer_http_callback(struct comm_point* c, void* arg, int err,
+ struct comm_reply* repinfo);
+/** xfer probe timeout callback, part of task_probe */
+void auth_xfer_probe_timer_callback(void* arg);
+/** mesh callback for task_probe on lookup of host names */
+void auth_xfer_probe_lookup_callback(void* arg, int rcode,
+ struct sldns_buffer* buf, enum sec_status sec, char* why_bogus);
+/** mesh callback for task_transfer on lookup of host names */
+void auth_xfer_transfer_lookup_callback(void* arg, int rcode,
+ struct sldns_buffer* buf, enum sec_status sec, char* why_bogus);
+
+/*
+ * Compares two 32-bit serial numbers as defined in RFC1982. Returns
+ * <0 if a < b, 0 if a == b, and >0 if a > b. The result is undefined
+ * if a != b but neither is greater or smaller (see RFC1982 section
+ * 3.2.).
+ */
+int compare_serial(uint32_t a, uint32_t b);
+
#endif /* SERVICES_AUTHZONE_H */
diff --git a/services/cache/dns.c b/services/cache/dns.c
index f9dc5922f682..411793c6c270 100644
--- a/services/cache/dns.c
+++ b/services/cache/dns.c
@@ -395,8 +395,7 @@ dns_msg_authadd(struct dns_msg* msg, struct regional* region,
return 1;
}
-/** add rrset to answer section */
-static int
+int
dns_msg_ansadd(struct dns_msg* msg, struct regional* region,
struct ub_packed_rrset_key* rrset, time_t now)
{
@@ -568,7 +567,7 @@ rrset_msg(struct ub_packed_rrset_key* rrset, struct regional* region,
/** synthesize DNAME+CNAME response from cached DNAME item */
static struct dns_msg*
synth_dname_msg(struct ub_packed_rrset_key* rrset, struct regional* region,
- time_t now, struct query_info* q)
+ time_t now, struct query_info* q, enum sec_status* sec_status)
{
struct dns_msg* msg;
struct ub_packed_rrset_key* ck;
@@ -580,8 +579,9 @@ synth_dname_msg(struct ub_packed_rrset_key* rrset, struct regional* region,
return NULL;
/* only allow validated (with DNSSEC) DNAMEs used from cache
* for insecure DNAMEs, query again. */
- if(d->security != sec_status_secure)
- return NULL;
+ *sec_status = d->security;
+ /* return sec status, so the status of the CNAME can be checked
+ * by the calling routine. */
msg = gen_dns_msg(region, q, 2); /* DNAME + CNAME RRset */
if(!msg)
return NULL;
@@ -711,7 +711,8 @@ fill_any(struct module_env* env,
struct dns_msg*
dns_cache_lookup(struct module_env* env,
uint8_t* qname, size_t qnamelen, uint16_t qtype, uint16_t qclass,
- uint16_t flags, struct regional* region, struct regional* scratch)
+ uint16_t flags, struct regional* region, struct regional* scratch,
+ int no_partial)
{
struct lruhash_entry* e;
struct query_info k;
@@ -743,27 +744,54 @@ dns_cache_lookup(struct module_env* env,
/* see if a DNAME exists. Checked for first, to enforce that DNAMEs
* are more important, the CNAME is resynthesized and thus
* consistent with the DNAME */
- if( (rrset=find_closest_of_type(env, qname, qnamelen, qclass, now,
+ if(!no_partial &&
+ (rrset=find_closest_of_type(env, qname, qnamelen, qclass, now,
LDNS_RR_TYPE_DNAME, 1))) {
/* synthesize a DNAME+CNAME message based on this */
- struct dns_msg* msg = synth_dname_msg(rrset, region, now, &k);
+ enum sec_status sec_status = sec_status_unchecked;
+ struct dns_msg* msg = synth_dname_msg(rrset, region, now, &k,
+ &sec_status);
if(msg) {
+ struct ub_packed_rrset_key* cname_rrset;
+ lock_rw_unlock(&rrset->entry.lock);
+ /* now, after unlocking the DNAME rrset lock,
+ * check the sec_status, and see if we need to look
+ * up the CNAME record associated before it can
+ * be used */
+ /* normally, only secure DNAMEs allowed from cache*/
+ if(sec_status == sec_status_secure)
+ return msg;
+ /* but if we have a CNAME cached with this name, then we
+ * have previously already allowed this name to pass.
+ * the next cache lookup is going to fetch that CNAME itself,
+ * but it is better to have the (unsigned)DNAME + CNAME in
+ * that case */
+ cname_rrset = rrset_cache_lookup(
+ env->rrset_cache, qname, qnamelen,
+ LDNS_RR_TYPE_CNAME, qclass, 0, now, 0);
+ if(cname_rrset) {
+ /* CNAME already synthesized by
+ * synth_dname_msg routine, so we can
+ * straight up return the msg */
+ lock_rw_unlock(&cname_rrset->entry.lock);
+ return msg;
+ }
+ } else {
lock_rw_unlock(&rrset->entry.lock);
- return msg;
}
- lock_rw_unlock(&rrset->entry.lock);
}
/* see if we have CNAME for this domain,
* but not for DS records (which are part of the parent) */
- if( qtype != LDNS_RR_TYPE_DS &&
+ if(!no_partial && qtype != LDNS_RR_TYPE_DS &&
(rrset=rrset_cache_lookup(env->rrset_cache, qname, qnamelen,
LDNS_RR_TYPE_CNAME, qclass, 0, now, 0))) {
uint8_t* wc = NULL;
+ size_t wl;
/* if the rrset is not a wildcard expansion, with wcname */
/* because, if we return that CNAME rrset on its own, it is
* missing the NSEC or NSEC3 proof */
- if(!(val_rrset_wildcard(rrset, &wc) && wc != NULL)) {
+ if(!(val_rrset_wildcard(rrset, &wc, &wl) && wc != NULL)) {
struct dns_msg* msg = rrset_msg(rrset, region, now, &k);
if(msg) {
lock_rw_unlock(&rrset->entry.lock);
@@ -842,7 +870,7 @@ dns_cache_lookup(struct module_env* env,
return NULL;
}
-int
+int
dns_cache_store(struct module_env* env, struct query_info* msgqinf,
struct reply_info* msgrep, int is_referral, time_t leeway, int pside,
struct regional* region, uint32_t flags)
@@ -852,7 +880,7 @@ dns_cache_store(struct module_env* env, struct query_info* msgqinf,
rep = reply_info_copy(msgrep, env->alloc, NULL);
if(!rep)
return 0;
- /* ttl must be relative ;i.e. 0..86400 not time(0)+86400.
+ /* ttl must be relative ;i.e. 0..86400 not time(0)+86400.
* the env->now is added to message and RRsets in this routine. */
/* the leeway is used to invalidate other rrsets earlier */
diff --git a/services/cache/dns.h b/services/cache/dns.h
index 9e10f437f1b4..78f81e799522 100644
--- a/services/cache/dns.h
+++ b/services/cache/dns.h
@@ -159,13 +159,16 @@ struct dns_msg* tomsg(struct module_env* env, struct query_info* q,
* @param flags: flags with BIT_CD for AAAA queries in dns64 translation.
* @param region: where to allocate result.
* @param scratch: where to allocate temporary data.
+ * @param no_partial: if true, only complete messages and not a partial
+ * one (with only the start of the CNAME chain and not the rest).
* @return new response message (alloced in region, rrsets do not have IDs).
* or NULL on error or if not found in cache.
* TTLs are made relative to the current time.
*/
struct dns_msg* dns_cache_lookup(struct module_env* env,
uint8_t* qname, size_t qnamelen, uint16_t qtype, uint16_t qclass,
- uint16_t flags, struct regional* region, struct regional* scratch);
+ uint16_t flags, struct regional* region, struct regional* scratch,
+ int no_partial);
/**
* find and add A and AAAA records for missing nameservers in delegpt
@@ -205,6 +208,18 @@ int dns_msg_authadd(struct dns_msg* msg, struct regional* region,
struct ub_packed_rrset_key* rrset, time_t now);
/**
+ * Add rrset to authority section in unpacked dns_msg message. Must have enough
+ * space left, does not grow the array.
+ * @param msg: msg to put it in.
+ * @param region: region to alloc in
+ * @param rrset: to add in authority section
+ * @param now: now.
+ * @return true if worked, false on fail
+ */
+int dns_msg_ansadd(struct dns_msg* msg, struct regional* region,
+ struct ub_packed_rrset_key* rrset, time_t now);
+
+/**
* Adjust the prefetch_ttl for a cached message. This adds a value to the
* prefetch ttl - postponing the time when it will be prefetched for future
* incoming queries.
diff --git a/services/cache/rrset.c b/services/cache/rrset.c
index 7e5732b760f2..0b41fcd7dc3f 100644
--- a/services/cache/rrset.c
+++ b/services/cache/rrset.c
@@ -47,6 +47,7 @@
#include "util/data/msgreply.h"
#include "util/regional.h"
#include "util/alloc.h"
+#include "util/net_help.h"
void
rrset_markdel(void* key)
@@ -237,6 +238,37 @@ rrset_cache_update(struct rrset_cache* r, struct rrset_ref* ref,
return 0;
}
+void rrset_cache_update_wildcard(struct rrset_cache* rrset_cache,
+ struct ub_packed_rrset_key* rrset, uint8_t* ce, size_t ce_len,
+ struct alloc_cache* alloc, time_t timenow)
+{
+ struct rrset_ref ref;
+ uint8_t wc_dname[LDNS_MAX_DOMAINLEN+3];
+ rrset = packed_rrset_copy_alloc(rrset, alloc, timenow);
+ if(!rrset) {
+ log_err("malloc failure in rrset_cache_update_wildcard");
+ return;
+ }
+ /* ce has at least one label less then qname, we can therefore safely
+ * add the wildcard label. */
+ wc_dname[0] = 1;
+ wc_dname[1] = (uint8_t)'*';
+ memmove(wc_dname+2, ce, ce_len);
+
+ rrset->rk.dname_len = ce_len + 2;
+ rrset->rk.dname = (uint8_t*)memdup(wc_dname, rrset->rk.dname_len);
+ if(!rrset->rk.dname) {
+ log_err("memdup failure in rrset_cache_update_wildcard");
+ return;
+ }
+
+ rrset->entry.hash = rrset_key_hash(&rrset->rk);
+ ref.key = rrset;
+ ref.id = rrset->id;
+ /* ignore ret: if it was in the cache, ref updated */
+ (void)rrset_cache_update(rrset_cache, &ref, alloc, timenow);
+}
+
struct ub_packed_rrset_key*
rrset_cache_lookup(struct rrset_cache* r, uint8_t* qname, size_t qnamelen,
uint16_t qtype, uint16_t qclass, uint32_t flags, time_t timenow,
diff --git a/services/cache/rrset.h b/services/cache/rrset.h
index d5439ef085b7..35a0d732b048 100644
--- a/services/cache/rrset.h
+++ b/services/cache/rrset.h
@@ -134,6 +134,24 @@ int rrset_cache_update(struct rrset_cache* r, struct rrset_ref* ref,
struct alloc_cache* alloc, time_t timenow);
/**
+ * Update or add an rrset in the rrset cache using a wildcard dname.
+ * Generates wildcard dname by prepending the wildcard label to the closest
+ * encloser. Will lookup if the rrset is in the cache and perform an update if
+ * necessary.
+ *
+ * @param rrset_cache: the rrset cache.
+ * @param rrset: which rrset to cache as wildcard. This rrset is left
+ * untouched.
+ * @param ce: the closest encloser, will be uses to generate the wildcard dname.
+ * @param ce_len: the closest encloser lenght.
+ * @param alloc: how to allocate (and deallocate) the special rrset key.
+ * @param timenow: current time (to see if ttl in cache is expired).
+ */
+void rrset_cache_update_wildcard(struct rrset_cache* rrset_cache,
+ struct ub_packed_rrset_key* rrset, uint8_t* ce, size_t ce_len,
+ struct alloc_cache* alloc, time_t timenow);
+
+/**
* Lookup rrset. You obtain read/write lock. You must unlock before lookup
* anything of else.
* @param r: the rrset cache.
diff --git a/services/listen_dnsport.c b/services/listen_dnsport.c
index 3b53676d0e06..d099ca9449b7 100644
--- a/services/listen_dnsport.c
+++ b/services/listen_dnsport.c
@@ -167,7 +167,7 @@ create_udp_sock(int family, int socktype, struct sockaddr* addr,
int freebind, int use_systemd)
{
int s;
-#if defined(SO_REUSEADDR) || defined(SO_REUSEPORT) || defined(IPV6_USE_MIN_MTU) || defined(IP_TRANSPARENT) || defined(IP_BINDANY) || defined(IP_FREEBIND)
+#if defined(SO_REUSEADDR) || defined(SO_REUSEPORT) || defined(IPV6_USE_MIN_MTU) || defined(IP_TRANSPARENT) || defined(IP_BINDANY) || defined(IP_FREEBIND) || defined (SO_BINDANY)
int on=1;
#endif
#ifdef IPV6_MTU
@@ -182,7 +182,7 @@ create_udp_sock(int family, int socktype, struct sockaddr* addr,
#ifndef IPV6_V6ONLY
(void)v6only;
#endif
-#if !defined(IP_TRANSPARENT) && !defined(IP_BINDANY)
+#if !defined(IP_TRANSPARENT) && !defined(IP_BINDANY) && !defined(SO_BINDANY)
(void)transparent;
#endif
#if !defined(IP_FREEBIND)
@@ -281,7 +281,14 @@ create_udp_sock(int family, int socktype, struct sockaddr* addr,
log_warn("setsockopt(.. IP%s_BINDANY ..) failed: %s",
(family==AF_INET6?"V6":""), strerror(errno));
}
-#endif /* IP_TRANSPARENT || IP_BINDANY */
+#elif defined(SO_BINDANY)
+ if (transparent &&
+ setsockopt(s, SOL_SOCKET, SO_BINDANY, (void*)&on,
+ (socklen_t)sizeof(on)) < 0) {
+ log_warn("setsockopt(.. SO_BINDANY ..) failed: %s",
+ strerror(errno));
+ }
+#endif /* IP_TRANSPARENT || IP_BINDANY || SO_BINDANY */
}
#ifdef IP_FREEBIND
if(freebind &&
@@ -592,7 +599,7 @@ create_tcp_accept_sock(struct addrinfo *addr, int v6only, int* noproto,
int* reuseport, int transparent, int mss, int freebind, int use_systemd)
{
int s;
-#if defined(SO_REUSEADDR) || defined(SO_REUSEPORT) || defined(IPV6_V6ONLY) || defined(IP_TRANSPARENT) || defined(IP_BINDANY) || defined(IP_FREEBIND)
+#if defined(SO_REUSEADDR) || defined(SO_REUSEPORT) || defined(IPV6_V6ONLY) || defined(IP_TRANSPARENT) || defined(IP_BINDANY) || defined(IP_FREEBIND) || defined(SO_BINDANY)
int on = 1;
#endif
#ifdef HAVE_SYSTEMD
@@ -601,7 +608,7 @@ create_tcp_accept_sock(struct addrinfo *addr, int v6only, int* noproto,
#ifdef USE_TCP_FASTOPEN
int qlen;
#endif
-#if !defined(IP_TRANSPARENT) && !defined(IP_BINDANY)
+#if !defined(IP_TRANSPARENT) && !defined(IP_BINDANY) && !defined(SO_BINDANY)
(void)transparent;
#endif
#if !defined(IP_FREEBIND)
@@ -736,7 +743,14 @@ create_tcp_accept_sock(struct addrinfo *addr, int v6only, int* noproto,
log_warn("setsockopt(.. IP%s_BINDANY ..) failed: %s",
(addr->ai_family==AF_INET6?"V6":""), strerror(errno));
}
-#endif /* IP_TRANSPARENT || IP_BINDANY */
+#elif defined(SO_BINDANY)
+ if (transparent &&
+ setsockopt(s, SOL_SOCKET, SO_BINDANY, (void*)&on, (socklen_t)
+ sizeof(on)) < 0) {
+ log_warn("setsockopt(.. SO_BINDANY ..) failed: %s",
+ strerror(errno));
+ }
+#endif /* IP_TRANSPARENT || IP_BINDANY || SO_BINDANY */
if(
#ifdef HAVE_SYSTEMD
!got_fd_from_systemd &&
diff --git a/services/localzone.c b/services/localzone.c
index 6bde432e8d09..0f608170c850 100644
--- a/services/localzone.c
+++ b/services/localzone.c
@@ -52,7 +52,6 @@
#include "util/data/msgreply.h"
#include "util/data/msgparse.h"
#include "util/as112.h"
-#include "util/config_file.h"
/* maximum RRs in an RRset, to cap possible 'endless' list RRs.
* with 16 bytes for an A record, a 64K packet has about 4000 max */
@@ -1133,57 +1132,11 @@ void local_zones_print(struct local_zones* zones)
lock_rw_rdlock(&zones->lock);
log_info("number of auth zones %u", (unsigned)zones->ztree.count);
RBTREE_FOR(z, struct local_zone*, &zones->ztree) {
+ char buf[64];
lock_rw_rdlock(&z->lock);
- switch(z->type) {
- case local_zone_deny:
- log_nametypeclass(0, "deny zone",
- z->name, 0, z->dclass);
- break;
- case local_zone_refuse:
- log_nametypeclass(0, "refuse zone",
- z->name, 0, z->dclass);
- break;
- case local_zone_redirect:
- log_nametypeclass(0, "redirect zone",
- z->name, 0, z->dclass);
- break;
- case local_zone_transparent:
- log_nametypeclass(0, "transparent zone",
- z->name, 0, z->dclass);
- break;
- case local_zone_typetransparent:
- log_nametypeclass(0, "typetransparent zone",
- z->name, 0, z->dclass);
- break;
- case local_zone_static:
- log_nametypeclass(0, "static zone",
- z->name, 0, z->dclass);
- break;
- case local_zone_inform:
- log_nametypeclass(0, "inform zone",
- z->name, 0, z->dclass);
- break;
- case local_zone_inform_deny:
- log_nametypeclass(0, "inform_deny zone",
- z->name, 0, z->dclass);
- break;
- case local_zone_always_transparent:
- log_nametypeclass(0, "always_transparent zone",
- z->name, 0, z->dclass);
- break;
- case local_zone_always_refuse:
- log_nametypeclass(0, "always_refuse zone",
- z->name, 0, z->dclass);
- break;
- case local_zone_always_nxdomain:
- log_nametypeclass(0, "always_nxdomain zone",
- z->name, 0, z->dclass);
- break;
- default:
- log_nametypeclass(0, "badtyped zone",
- z->name, 0, z->dclass);
- break;
- }
+ snprintf(buf, sizeof(buf), "%s zone",
+ local_zone_type2str(z->type));
+ log_nametypeclass(0, buf, z->name, 0, z->dclass);
local_zone_out(z);
lock_rw_unlock(&z->lock);
}
@@ -1590,12 +1543,17 @@ local_zones_answer(struct local_zones* zones, struct module_env* env,
(z = local_zones_lookup(view->local_zones,
qinfo->qname, qinfo->qname_len, labs,
qinfo->qclass, qinfo->qtype))) {
- verbose(VERB_ALGO,
- "using localzone from view: %s",
- view->name);
+ if(z->type != local_zone_noview)
+ verbose(VERB_ALGO,
+ "using localzone from view: %s",
+ view->name);
lock_rw_rdlock(&z->lock);
lzt = z->type;
}
+ if(lzt == local_zone_noview) {
+ lock_rw_unlock(&z->lock);
+ z = NULL;
+ }
if(view->local_zones && !z && !view->isfirst){
lock_rw_unlock(&view->lock);
return 0;
@@ -1653,6 +1611,7 @@ const char* local_zone_type2str(enum localzone_type t)
case local_zone_always_transparent: return "always_transparent";
case local_zone_always_refuse: return "always_refuse";
case local_zone_always_nxdomain: return "always_nxdomain";
+ case local_zone_noview: return "noview";
}
return "badtyped";
}
@@ -1681,6 +1640,8 @@ int local_zone_str2type(const char* type, enum localzone_type* t)
*t = local_zone_always_refuse;
else if(strcmp(type, "always_nxdomain") == 0)
*t = local_zone_always_nxdomain;
+ else if(strcmp(type, "noview") == 0)
+ *t = local_zone_noview;
else if(strcmp(type, "nodefault") == 0)
*t = local_zone_nodefault;
else return 0;
diff --git a/services/localzone.h b/services/localzone.h
index 0a8759268bb2..dd7aa584c461 100644
--- a/services/localzone.h
+++ b/services/localzone.h
@@ -88,7 +88,9 @@ enum localzone_type {
/** answer with error, even when there is local data */
local_zone_always_refuse,
/** answer with nxdomain, even when there is local data */
- local_zone_always_nxdomain
+ local_zone_always_nxdomain,
+ /** answer not from the view, but global or no-answer */
+ local_zone_noview
};
/**
diff --git a/services/outside_network.c b/services/outside_network.c
index ec9e11a0e7af..92212be02f0d 100644
--- a/services/outside_network.c
+++ b/services/outside_network.c
@@ -198,21 +198,17 @@ pick_outgoing_tcp(struct waiting_tcp* w, int s)
return 1;
}
-/** use next free buffer to service a tcp query */
-static int
-outnet_tcp_take_into_use(struct waiting_tcp* w, uint8_t* pkt, size_t pkt_len)
+/** get TCP file descriptor for address, returns -1 on failure,
+ * tcp_mss is 0 or maxseg size to set for TCP packets. */
+int
+outnet_get_tcp_fd(struct sockaddr_storage* addr, socklen_t addrlen, int tcp_mss)
{
- struct pending_tcp* pend = w->outnet->tcp_free;
int s;
#ifdef SO_REUSEADDR
int on = 1;
#endif
- log_assert(pend);
- log_assert(pkt);
- log_assert(w->addrlen > 0);
- /* open socket */
#ifdef INET6
- if(addr_is_ip6(&w->addr, w->addrlen))
+ if(addr_is_ip6(addr, addrlen))
s = socket(PF_INET6, SOCK_STREAM, IPPROTO_TCP);
else
#endif
@@ -220,12 +216,12 @@ outnet_tcp_take_into_use(struct waiting_tcp* w, uint8_t* pkt, size_t pkt_len)
if(s == -1) {
#ifndef USE_WINSOCK
log_err_addr("outgoing tcp: socket", strerror(errno),
- &w->addr, w->addrlen);
+ addr, addrlen);
#else
log_err_addr("outgoing tcp: socket",
- wsa_strerror(WSAGetLastError()), &w->addr, w->addrlen);
+ wsa_strerror(WSAGetLastError()), addr, addrlen);
#endif
- return 0;
+ return -1;
}
#ifdef SO_REUSEADDR
@@ -235,11 +231,11 @@ outnet_tcp_take_into_use(struct waiting_tcp* w, uint8_t* pkt, size_t pkt_len)
" setsockopt(.. SO_REUSEADDR ..) failed");
}
#endif
- if (w->outnet->tcp_mss > 0) {
+
+ if(tcp_mss > 0) {
#if defined(IPPROTO_TCP) && defined(TCP_MAXSEG)
if(setsockopt(s, IPPROTO_TCP, TCP_MAXSEG,
- (void*)&w->outnet->tcp_mss,
- (socklen_t)sizeof(w->outnet->tcp_mss)) < 0) {
+ (void*)&tcp_mss, (socklen_t)sizeof(tcp_mss)) < 0) {
verbose(VERB_ALGO, "outgoing tcp:"
" setsockopt(.. TCP_MAXSEG ..) failed");
}
@@ -249,6 +245,50 @@ outnet_tcp_take_into_use(struct waiting_tcp* w, uint8_t* pkt, size_t pkt_len)
#endif /* defined(IPPROTO_TCP) && defined(TCP_MAXSEG) */
}
+ return s;
+}
+
+/** connect tcp connection to addr, 0 on failure */
+int
+outnet_tcp_connect(int s, struct sockaddr_storage* addr, socklen_t addrlen)
+{
+ if(connect(s, (struct sockaddr*)addr, addrlen) == -1) {
+#ifndef USE_WINSOCK
+#ifdef EINPROGRESS
+ if(errno != EINPROGRESS) {
+#endif
+ if(tcp_connect_errno_needs_log(
+ (struct sockaddr*)addr, addrlen))
+ log_err_addr("outgoing tcp: connect",
+ strerror(errno), addr, addrlen);
+ close(s);
+ return 0;
+#ifdef EINPROGRESS
+ }
+#endif
+#else /* USE_WINSOCK */
+ if(WSAGetLastError() != WSAEINPROGRESS &&
+ WSAGetLastError() != WSAEWOULDBLOCK) {
+ closesocket(s);
+ return 0;
+ }
+#endif
+ }
+ return 1;
+}
+
+/** use next free buffer to service a tcp query */
+static int
+outnet_tcp_take_into_use(struct waiting_tcp* w, uint8_t* pkt, size_t pkt_len)
+{
+ struct pending_tcp* pend = w->outnet->tcp_free;
+ int s;
+ log_assert(pend);
+ log_assert(pkt);
+ log_assert(w->addrlen > 0);
+ /* open socket */
+ s = outnet_get_tcp_fd(&w->addr, w->addrlen, w->outnet->tcp_mss);
+
if(!pick_outgoing_tcp(w, s))
return 0;
@@ -2101,6 +2141,215 @@ void outnet_serviced_query_stop(struct serviced_query* sq, void* cb_arg)
}
}
+/** create fd to send to this destination */
+static int
+fd_for_dest(struct outside_network* outnet, struct sockaddr_storage* to_addr,
+ socklen_t to_addrlen)
+{
+ struct sockaddr_storage* addr;
+ socklen_t addrlen;
+ int i;
+ int try;
+
+ /* select interface */
+ if(addr_is_ip6(to_addr, to_addrlen)) {
+ if(outnet->num_ip6 == 0) {
+ char to[64];
+ addr_to_str(to_addr, to_addrlen, to, sizeof(to));
+ verbose(VERB_QUERY, "need ipv6 to send, but no ipv6 outgoing interfaces, for %s", to);
+ return -1;
+ }
+ i = ub_random_max(outnet->rnd, outnet->num_ip6);
+ addr = &outnet->ip6_ifs[i].addr;
+ addrlen = outnet->ip6_ifs[i].addrlen;
+ } else {
+ if(outnet->num_ip4 == 0) {
+ char to[64];
+ addr_to_str(to_addr, to_addrlen, to, sizeof(to));
+ verbose(VERB_QUERY, "need ipv4 to send, but no ipv4 outgoing interfaces, for %s", to);
+ return -1;
+ }
+ i = ub_random_max(outnet->rnd, outnet->num_ip4);
+ addr = &outnet->ip4_ifs[i].addr;
+ addrlen = outnet->ip4_ifs[i].addrlen;
+ }
+
+ /* create fd */
+ for(try = 0; try<1000; try++) {
+ int freebind = 0;
+ int noproto = 0;
+ int inuse = 0;
+ int port = ub_random(outnet->rnd)&0xffff;
+ int fd = -1;
+ if(addr_is_ip6(to_addr, to_addrlen)) {
+ struct sockaddr_in6 sa = *(struct sockaddr_in6*)addr;
+ sa.sin6_port = (in_port_t)htons((uint16_t)port);
+ fd = create_udp_sock(AF_INET6, SOCK_DGRAM,
+ (struct sockaddr*)&sa, addrlen, 1, &inuse, &noproto,
+ 0, 0, 0, NULL, 0, freebind, 0);
+ } else {
+ struct sockaddr_in* sa = (struct sockaddr_in*)addr;
+ sa->sin_port = (in_port_t)htons((uint16_t)port);
+ fd = create_udp_sock(AF_INET, SOCK_DGRAM,
+ (struct sockaddr*)addr, addrlen, 1, &inuse, &noproto,
+ 0, 0, 0, NULL, 0, freebind, 0);
+ }
+ if(fd != -1) {
+ return fd;
+ }
+ if(!inuse) {
+ return -1;
+ }
+ }
+ /* too many tries */
+ log_err("cannot send probe, ports are in use");
+ return -1;
+}
+
+struct comm_point*
+outnet_comm_point_for_udp(struct outside_network* outnet,
+ comm_point_callback_type* cb, void* cb_arg,
+ struct sockaddr_storage* to_addr, socklen_t to_addrlen)
+{
+ struct comm_point* cp;
+ int fd = fd_for_dest(outnet, to_addr, to_addrlen);
+ if(fd == -1) {
+ return NULL;
+ }
+ cp = comm_point_create_udp(outnet->base, fd, outnet->udp_buff,
+ cb, cb_arg);
+ if(!cp) {
+ log_err("malloc failure");
+ close(fd);
+ return NULL;
+ }
+ return cp;
+}
+
+struct comm_point*
+outnet_comm_point_for_tcp(struct outside_network* outnet,
+ comm_point_callback_type* cb, void* cb_arg,
+ struct sockaddr_storage* to_addr, socklen_t to_addrlen,
+ sldns_buffer* query, int timeout)
+{
+ struct comm_point* cp;
+ int fd = outnet_get_tcp_fd(to_addr, to_addrlen, outnet->tcp_mss);
+ if(fd == -1) {
+ return 0;
+ }
+ fd_set_nonblock(fd);
+ if(!outnet_tcp_connect(fd, to_addr, to_addrlen)) {
+ /* outnet_tcp_connect has closed fd on error for us */
+ return 0;
+ }
+ cp = comm_point_create_tcp_out(outnet->base, 65552, cb, cb_arg);
+ if(!cp) {
+ log_err("malloc failure");
+ close(fd);
+ return 0;
+ }
+ cp->repinfo.addrlen = to_addrlen;
+ memcpy(&cp->repinfo.addr, to_addr, to_addrlen);
+ /* set timeout on TCP connection */
+ comm_point_start_listening(cp, fd, timeout);
+ /* copy scratch buffer to cp->buffer */
+ sldns_buffer_copy(cp->buffer, query);
+ return cp;
+}
+
+/** setup http request headers in buffer for sending query to destination */
+static int
+setup_http_request(sldns_buffer* buf, char* host, char* path)
+{
+ sldns_buffer_clear(buf);
+ sldns_buffer_printf(buf, "GET /%s HTTP/1.1\r\n", path);
+ sldns_buffer_printf(buf, "Host: %s\r\n", host);
+ sldns_buffer_printf(buf, "User-Agent: unbound/%s\r\n",
+ PACKAGE_VERSION);
+ /* We do not really do multiple queries per connection,
+ * but this header setting is also not needed.
+ * sldns_buffer_printf(buf, "Connection: close\r\n") */
+ sldns_buffer_printf(buf, "\r\n");
+ if(sldns_buffer_position(buf)+10 > sldns_buffer_capacity(buf))
+ return 0; /* somehow buffer too short, but it is about 60K
+ and the request is only a couple bytes long. */
+ sldns_buffer_flip(buf);
+ return 1;
+}
+
+struct comm_point*
+outnet_comm_point_for_http(struct outside_network* outnet,
+ comm_point_callback_type* cb, void* cb_arg,
+ struct sockaddr_storage* to_addr, socklen_t to_addrlen, int timeout,
+ int ssl, char* host, char* path)
+{
+ /* cp calls cb with err=NETEVENT_DONE when transfer is done */
+ struct comm_point* cp;
+ int fd = outnet_get_tcp_fd(to_addr, to_addrlen, outnet->tcp_mss);
+ if(fd == -1) {
+ return 0;
+ }
+ fd_set_nonblock(fd);
+ if(!outnet_tcp_connect(fd, to_addr, to_addrlen)) {
+ /* outnet_tcp_connect has closed fd on error for us */
+ return 0;
+ }
+ cp = comm_point_create_http_out(outnet->base, 65552, cb, cb_arg,
+ outnet->udp_buff);
+ if(!cp) {
+ log_err("malloc failure");
+ close(fd);
+ return 0;
+ }
+ cp->repinfo.addrlen = to_addrlen;
+ memcpy(&cp->repinfo.addr, to_addr, to_addrlen);
+
+ /* setup for SSL (if needed) */
+ if(ssl) {
+ cp->ssl = outgoing_ssl_fd(outnet->sslctx, fd);
+ if(!cp->ssl) {
+ log_err("cannot setup https");
+ comm_point_delete(cp);
+ return NULL;
+ }
+#ifdef USE_WINSOCK
+ comm_point_tcp_win_bio_cb(cp, cp->ssl);
+#endif
+ cp->ssl_shake_state = comm_ssl_shake_write;
+ /* https verification */
+#ifdef HAVE_SSL_SET1_HOST
+ if((SSL_CTX_get_verify_mode(outnet->sslctx)&SSL_VERIFY_PEER)) {
+ /* because we set SSL_VERIFY_PEER, in netevent in
+ * ssl_handshake, it'll check if the certificate
+ * verification has succeeded */
+ /* SSL_VERIFY_PEER is set on the sslctx */
+ /* and the certificates to verify with are loaded into
+ * it with SSL_load_verify_locations or
+ * SSL_CTX_set_default_verify_paths */
+ /* setting the hostname makes openssl verify the
+ * host name in the x509 certificate in the
+ * SSL connection*/
+ if(!SSL_set1_host(cp->ssl, host)) {
+ log_err("SSL_set1_host failed");
+ comm_point_delete(cp);
+ return NULL;
+ }
+ }
+#endif /* HAVE_SSL_SET1_HOST */
+ }
+
+ /* set timeout on TCP connection */
+ comm_point_start_listening(cp, fd, timeout);
+
+ /* setup http request in cp->buffer */
+ if(!setup_http_request(cp->buffer, host, path)) {
+ log_err("error setting up http request");
+ comm_point_delete(cp);
+ return NULL;
+ }
+ return cp;
+}
+
/** get memory used by waiting tcp entry (in use or not) */
static size_t
waiting_tcp_get_mem(struct waiting_tcp* w)
diff --git a/services/outside_network.h b/services/outside_network.h
index befd512f0dad..09b2e6cedff6 100644
--- a/services/outside_network.h
+++ b/services/outside_network.h
@@ -533,6 +533,70 @@ size_t outnet_get_mem(struct outside_network* outnet);
*/
size_t serviced_get_mem(struct serviced_query* sq);
+/** get TCP file descriptor for address, returns -1 on failure,
+ * tcp_mss is 0 or maxseg size to set for TCP packets. */
+int outnet_get_tcp_fd(struct sockaddr_storage* addr, socklen_t addrlen, int tcp_mss);
+
+/**
+ * Create udp commpoint suitable for sending packets to the destination.
+ * @param outnet: outside_network with the comm_base it is attached to,
+ * with the outgoing interfaces chosen from, and rnd gen for random.
+ * @param cb: callback function for the commpoint.
+ * @param cb_arg: callback argument for cb.
+ * @param to_addr: intended destination.
+ * @param to_addrlen: length of to_addr.
+ * @return commpoint that you can comm_point_send_udp_msg with, or NULL.
+ */
+struct comm_point* outnet_comm_point_for_udp(struct outside_network* outnet,
+ comm_point_callback_type* cb, void* cb_arg,
+ struct sockaddr_storage* to_addr, socklen_t to_addrlen);
+
+/**
+ * Create tcp commpoint suitable for communication to the destination.
+ * It also performs connect() to the to_addr.
+ * @param outnet: outside_network with the comm_base it is attached to,
+ * and the tcp_mss.
+ * @param cb: callback function for the commpoint.
+ * @param cb_arg: callback argument for cb.
+ * @param to_addr: intended destination.
+ * @param to_addrlen: length of to_addr.
+ * @param query: initial packet to send writing, in buffer. It is copied
+ * to the commpoint buffer that is created.
+ * @param timeout: timeout for the TCP connection.
+ * timeout in milliseconds, or -1 for no (change to the) timeout.
+ * So seconds*1000.
+ * @return tcp_out commpoint, or NULL.
+ */
+struct comm_point* outnet_comm_point_for_tcp(struct outside_network* outnet,
+ comm_point_callback_type* cb, void* cb_arg,
+ struct sockaddr_storage* to_addr, socklen_t to_addrlen,
+ struct sldns_buffer* query, int timeout);
+
+/**
+ * Create http commpoint suitable for communication to the destination.
+ * Creates the http request buffer. It also performs connect() to the to_addr.
+ * @param outnet: outside_network with the comm_base it is attached to,
+ * and the tcp_mss.
+ * @param cb: callback function for the commpoint.
+ * @param cb_arg: callback argument for cb.
+ * @param to_addr: intended destination.
+ * @param to_addrlen: length of to_addr.
+ * @param timeout: timeout for the TCP connection.
+ * timeout in milliseconds, or -1 for no (change to the) timeout.
+ * So seconds*1000.
+ * @param ssl: set to true for https.
+ * @param host: hostname to use for the destination. part of http request.
+ * @param path: pathname to lookup, eg. name of the file on the destination.
+ * @return http_out commpoint, or NULL.
+ */
+struct comm_point* outnet_comm_point_for_http(struct outside_network* outnet,
+ comm_point_callback_type* cb, void* cb_arg,
+ struct sockaddr_storage* to_addr, socklen_t to_addrlen, int timeout,
+ int ssl, char* host, char* path);
+
+/** connect tcp connection to addr, 0 on failure */
+int outnet_tcp_connect(int s, struct sockaddr_storage* addr, socklen_t addrlen);
+
/** callback for incoming udp answers from the network */
int outnet_udp_cb(struct comm_point* c, void* arg, int error,
struct comm_reply *reply_info);
diff --git a/sldns/str2wire.c b/sldns/str2wire.c
index 6759944e4a7f..fdb355754028 100644
--- a/sldns/str2wire.c
+++ b/sldns/str2wire.c
@@ -836,7 +836,7 @@ const char* sldns_get_errorstr_parse(int e)
}
/* Strip whitespace from the start and the end of <line>. */
-static char *
+char *
sldns_strip_ws(char *line)
{
char *s = line, *e;
@@ -906,7 +906,7 @@ int sldns_fp2wire_rr_buf(FILE* in, uint8_t* rr, size_t* len, size_t* dname_len,
*dname_len = 0;
return LDNS_WIREPARSE_ERR_INCLUDE;
} else {
- return sldns_str2wire_rr_buf(line, rr, len, dname_len,
+ int r = sldns_str2wire_rr_buf(line, rr, len, dname_len,
parse_state?parse_state->default_ttl:0,
(parse_state&&parse_state->origin_len)?
parse_state->origin:NULL,
@@ -914,6 +914,13 @@ int sldns_fp2wire_rr_buf(FILE* in, uint8_t* rr, size_t* len, size_t* dname_len,
(parse_state&&parse_state->prev_rr_len)?
parse_state->prev_rr:NULL,
parse_state?parse_state->prev_rr_len:0);
+ if(r == LDNS_WIREPARSE_ERR_OK && (*dname_len) != 0 &&
+ parse_state &&
+ (*dname_len) <= sizeof(parse_state->prev_rr)) {
+ memmove(parse_state->prev_rr, rr, *dname_len);
+ parse_state->prev_rr_len = (*dname_len);
+ }
+ return r;
}
return LDNS_WIREPARSE_ERR_OK;
}
diff --git a/sldns/str2wire.h b/sldns/str2wire.h
index a0d6f55b03e8..70070e4f5752 100644
--- a/sldns/str2wire.h
+++ b/sldns/str2wire.h
@@ -554,6 +554,12 @@ int sldns_str2wire_hip_buf(const char* str, uint8_t* rd, size_t* len);
*/
int sldns_str2wire_int16_data_buf(const char* str, uint8_t* rd, size_t* len);
+/**
+ * Strip whitespace from the start and the end of line.
+ * @param line: modified with 0 to shorten it.
+ * @return new start with spaces skipped.
+ */
+char * sldns_strip_ws(char *line);
#ifdef __cplusplus
}
#endif
diff --git a/sldns/wire2str.c b/sldns/wire2str.c
index 861b7648adec..832239f9b76a 100644
--- a/sldns/wire2str.c
+++ b/sldns/wire2str.c
@@ -255,6 +255,12 @@ int sldns_wire2str_rr_buf(uint8_t* d, size_t dlen, char* s, size_t slen)
return sldns_wire2str_rr_scan(&d, &dlen, &s, &slen, NULL, 0);
}
+int sldns_wire2str_rrquestion_buf(uint8_t* d, size_t dlen, char* s, size_t slen)
+{
+ /* use arguments as temporary variables */
+ return sldns_wire2str_rrquestion_scan(&d, &dlen, &s, &slen, NULL, 0);
+}
+
int sldns_wire2str_rdata_buf(uint8_t* rdata, size_t rdata_len, char* str,
size_t str_len, uint16_t rrtype)
{
diff --git a/sldns/wire2str.h b/sldns/wire2str.h
index aac13c548acd..a64f5807269c 100644
--- a/sldns/wire2str.h
+++ b/sldns/wire2str.h
@@ -359,6 +359,22 @@ int sldns_wire2str_rr_buf(uint8_t* rr, size_t rr_len, char* str,
size_t str_len);
/**
+ * Convert question RR to string presentation format, on one line. User buffer.
+ * @param rr: wireformat RR data
+ * @param rr_len: length of the rr wire data.
+ * @param str: the string buffer to write to.
+ * If you pass NULL as the str, the return value of the function is
+ * the str_len you need for the entire packet. It does not include
+ * the 0 byte at the end.
+ * @param str_len: the size of the string buffer. If more is needed, it'll
+ * silently truncate the output to fit in the buffer.
+ * @return the number of characters for this element, excluding zerobyte.
+ * Is larger or equal than str_len if output was truncated.
+ */
+int sldns_wire2str_rrquestion_buf(uint8_t* rr, size_t rr_len, char* str,
+ size_t str_len);
+
+/**
* 3597 printout of an RR in unknown rr format.
* There are more format and comment options available for printout
* with the function: TBD(TODO)
diff --git a/smallapp/unbound-checkconf.c b/smallapp/unbound-checkconf.c
index 7e9cb4740ae3..e205c3e9c49c 100644
--- a/smallapp/unbound-checkconf.c
+++ b/smallapp/unbound-checkconf.c
@@ -54,6 +54,7 @@
#include "validator/validator.h"
#include "services/localzone.h"
#include "services/view.h"
+#include "services/authzone.h"
#include "respip/respip.h"
#include "sldns/sbuffer.h"
#ifdef HAVE_GETOPT_H
@@ -108,6 +109,16 @@ print_option(struct config_file* cfg, const char* opt, int final)
free(p);
return;
}
+ if(strcmp(opt, "auto-trust-anchor-file") == 0 && final) {
+ struct config_strlist* s = cfg->auto_trust_anchor_file_list;
+ for(; s; s=s->next) {
+ char *p = fname_after_chroot(s->str, cfg, 1);
+ if(!p) fatal_exit("out of memory");
+ printf("%s\n", p);
+ free(p);
+ }
+ return;
+ }
if(!config_get_option(cfg, opt, config_print_func, stdout))
fatal_exit("cannot print option '%s'", opt);
}
@@ -573,6 +584,17 @@ check_hints(struct config_file* cfg)
hints_delete(hints);
}
+/** check auth zones */
+static void
+check_auth(struct config_file* cfg)
+{
+ struct auth_zones* az = auth_zones_create();
+ if(!az || !auth_zones_apply_cfg(az, cfg, 0)) {
+ fatal_exit("Could not setup authority zones");
+ }
+ auth_zones_delete(az);
+}
+
/** check config file */
static void
checkconf(const char* cfgfile, const char* opt, int final)
@@ -607,6 +629,7 @@ checkconf(const char* cfgfile, const char* opt, int final)
#endif
check_fwd(cfg);
check_hints(cfg);
+ check_auth(cfg);
printf("unbound-checkconf: no errors in %s\n", cfgfile);
config_delete(cfg);
}
diff --git a/testcode/fake_event.c b/testcode/fake_event.c
index cd23b8feb49a..300a42c154ab 100644
--- a/testcode/fake_event.c
+++ b/testcode/fake_event.c
@@ -67,6 +67,29 @@
struct worker;
struct daemon_remote;
+/** unique code to check that fake_commpoint is that structure */
+#define FAKE_COMMPOINT_TYPECODE 97347923
+/** fake commpoint, stores information */
+struct fake_commpoint {
+ /** typecode */
+ int typecode;
+ /** if this is a udp outgoing type of commpoint */
+ int type_udp_out;
+ /** if this is a tcp outgoing type of commpoint */
+ int type_tcp_out;
+ /** if this is a http outgoing type of commpoint. */
+ int type_http_out;
+
+ /** the callback, stored for usage */
+ comm_point_callback_type* cb;
+ /** the callback userarg, stored for usage */
+ void* cb_arg;
+ /** runtime ptr */
+ struct replay_runtime* runtime;
+ /** the pending entry for this commpoint (if any) */
+ struct fake_pending* pending;
+};
+
/** Global variable: the scenario. Saved here for when event_init is done. */
static struct replay_scenario* saved_scenario = NULL;
@@ -137,6 +160,7 @@ repevt_string(enum replay_event_type t)
case repevt_back_reply: return "REPLY";
case repevt_back_query: return "CHECK_OUT_QUERY";
case repevt_autotrust_check: return "CHECK_AUTOTRUST";
+ case repevt_tempfile_check: return "CHECK_TEMPFILE";
case repevt_error: return "ERROR";
case repevt_assign: return "ASSIGN";
case repevt_traffic: return "TRAFFIC";
@@ -247,7 +271,11 @@ pending_matches_range(struct replay_runtime* runtime,
struct fake_pending* p = runtime->pending_list;
/* slow, O(N*N), but it works as advertised with weird matching */
while(p) {
- log_info("check of pending");
+ if(p->tcp_pkt_counter != 0) {
+ /* continue tcp transfer */
+ *pend = p;
+ return 1;
+ }
if(pending_find_match(runtime, entry, p)) {
*pend = p;
return 1;
@@ -278,24 +306,46 @@ pending_list_delete(struct replay_runtime* runtime, struct fake_pending* pend)
}
}
+/** number of replies in entry */
+static int
+count_reply_packets(struct entry* entry)
+{
+ int count = 0;
+ struct reply_packet* reppkt = entry->reply_list;
+ while(reppkt) {
+ count++;
+ reppkt = reppkt->next;
+ }
+ return count;
+}
+
/**
* Fill buffer with reply from the entry.
*/
static void
fill_buffer_with_reply(sldns_buffer* buffer, struct entry* entry, uint8_t* q,
- size_t qlen)
+ size_t qlen, int tcp_pkt_counter)
{
+ struct reply_packet* reppkt;
uint8_t* c;
size_t clen;
log_assert(entry && entry->reply_list);
sldns_buffer_clear(buffer);
- if(entry->reply_list->reply_from_hex) {
- c = sldns_buffer_begin(entry->reply_list->reply_from_hex);
- clen = sldns_buffer_limit(entry->reply_list->reply_from_hex);
+ reppkt = entry->reply_list;
+ if(tcp_pkt_counter > 0) {
+ int i = tcp_pkt_counter;
+ while(reppkt && i--)
+ reppkt = reppkt->next;
+ if(!reppkt) fatal_exit("extra packet read from TCP stream but none is available");
+ log_pkt("extra_packet ", reppkt->reply_pkt, reppkt->reply_len);
+ }
+ if(reppkt->reply_from_hex) {
+ c = sldns_buffer_begin(reppkt->reply_from_hex);
+ clen = sldns_buffer_limit(reppkt->reply_from_hex);
if(!c) fatal_exit("out of memory");
} else {
- c = entry->reply_list->reply_pkt;
- clen = entry->reply_list->reply_len;
+ c = reppkt->reply_pkt;
+ clen = reppkt->reply_len;
}
if(c) {
if(q) adjust_packet(entry, &c, &clen, q, qlen);
@@ -326,12 +376,20 @@ answer_callback_from_entry(struct replay_runtime* runtime,
c.type = comm_udp;
if(pend->transport == transport_tcp)
c.type = comm_tcp;
- fill_buffer_with_reply(c.buffer, entry, pend->pkt, pend->pkt_len);
+ fill_buffer_with_reply(c.buffer, entry, pend->pkt, pend->pkt_len,
+ pend->tcp_pkt_counter);
repinfo.c = &c;
repinfo.addrlen = pend->addrlen;
memcpy(&repinfo.addr, &pend->addr, pend->addrlen);
- if(!pend->serviced)
- pending_list_delete(runtime, pend);
+ if(!pend->serviced) {
+ if(entry->reply_list->next &&
+ pend->tcp_pkt_counter < count_reply_packets(entry)) {
+ /* go to next packet next time */
+ pend->tcp_pkt_counter++;
+ } else {
+ pending_list_delete(runtime, pend);
+ }
+ }
if((*cb)(&c, cb_arg, NETEVENT_NOERROR, &repinfo)) {
fatal_exit("testbound: unexpected: callback returned 1");
}
@@ -397,7 +455,7 @@ fake_front_query(struct replay_runtime* runtime, struct replay_moment *todo)
if(todo->match->match_transport == transport_tcp)
repinfo.c->type = comm_tcp;
else repinfo.c->type = comm_udp;
- fill_buffer_with_reply(repinfo.c->buffer, todo->match, NULL, 0);
+ fill_buffer_with_reply(repinfo.c->buffer, todo->match, NULL, 0, 0);
log_info("testbound: incoming QUERY");
log_pkt("query pkt", todo->match->reply_list->reply_pkt,
todo->match->reply_list->reply_len);
@@ -434,13 +492,20 @@ fake_pending_callback(struct replay_runtime* runtime,
c.type = comm_tcp;
if(todo->evt_type == repevt_back_reply && todo->match) {
fill_buffer_with_reply(c.buffer, todo->match, p->pkt,
- p->pkt_len);
+ p->pkt_len, p->tcp_pkt_counter);
}
repinfo.c = &c;
repinfo.addrlen = p->addrlen;
memcpy(&repinfo.addr, &p->addr, p->addrlen);
- if(!p->serviced)
- pending_list_delete(runtime, p);
+ if(!p->serviced) {
+ if(todo->match->reply_list->next && !error &&
+ p->tcp_pkt_counter < count_reply_packets(todo->match)) {
+ /* go to next packet next time */
+ p->tcp_pkt_counter++;
+ } else {
+ pending_list_delete(runtime, p);
+ }
+ }
if((*cb)(&c, cb_arg, error, &repinfo)) {
fatal_exit("unexpected: pending callback returned 1");
}
@@ -550,6 +615,59 @@ autotrust_check(struct replay_runtime* runtime, struct replay_moment* mom)
log_info("autotrust %s is OK", mom->autotrust_id);
}
+/** check tempfile file contents */
+static void
+tempfile_check(struct replay_runtime* runtime, struct replay_moment* mom)
+{
+ char name[1024], line[1024];
+ FILE *in;
+ int lineno = 0, oke=1;
+ char* expanded;
+ struct config_strlist* p;
+ line[sizeof(line)-1] = 0;
+ log_assert(mom->autotrust_id);
+ fake_temp_file("_temp_", mom->autotrust_id, name, sizeof(name));
+ in = fopen(name, "r");
+ if(!in) fatal_exit("could not open %s: %s", name, strerror(errno));
+ for(p=mom->file_content; p; p=p->next) {
+ lineno++;
+ if(!fgets(line, (int)sizeof(line)-1, in)) {
+ log_err("tempfile check failed, could not read line");
+ log_err("file %s, line %d", name, lineno);
+ log_err("should be: %s", p->str);
+ fatal_exit("tempfile_check failed");
+ }
+ if(line[0]) line[strlen(line)-1] = 0; /* remove newline */
+ expanded = macro_process(runtime->vars, runtime, p->str);
+ if(!expanded)
+ fatal_exit("could not expand macro line %d", lineno);
+ if(verbosity >= 7 && strcmp(p->str, expanded) != 0)
+ log_info("expanded '%s' to '%s'", p->str, expanded);
+ if(strcmp(expanded, line) != 0) {
+ log_err("mismatch in file %s, line %d", name, lineno);
+ log_err("file has : %s", line);
+ log_err("should be: %s", expanded);
+ free(expanded);
+ oke = 0;
+ continue;
+ }
+ free(expanded);
+ fprintf(stderr, "%s:%2d ok : %s\n", name, lineno, line);
+ }
+ if(fgets(line, (int)sizeof(line)-1, in)) {
+ log_err("tempfile check failed, extra lines in %s after %d",
+ name, lineno);
+ do {
+ fprintf(stderr, "file has: %s", line);
+ } while(fgets(line, (int)sizeof(line)-1, in));
+ oke = 0;
+ }
+ fclose(in);
+ if(!oke)
+ fatal_exit("tempfile_check STEP %d failed", mom->time_step);
+ log_info("tempfile %s is OK", mom->autotrust_id);
+}
+
/** Store RTT in infra cache */
static void
do_infra_rtt(struct replay_runtime* runtime)
@@ -659,6 +777,10 @@ do_moment_and_advance(struct replay_runtime* runtime)
autotrust_check(runtime, runtime->now);
advance_moment(runtime);
break;
+ case repevt_tempfile_check:
+ tempfile_check(runtime, runtime->now);
+ advance_moment(runtime);
+ break;
case repevt_assign:
moment_assign(runtime, runtime->now);
advance_moment(runtime);
@@ -1168,7 +1290,11 @@ struct comm_point* comm_point_create_local(struct comm_base* ATTR_UNUSED(base),
comm_point_callback_type* ATTR_UNUSED(callback),
void* ATTR_UNUSED(callback_arg))
{
- return calloc(1, 1);
+ struct fake_commpoint* fc = (struct fake_commpoint*)calloc(1,
+ sizeof(*fc));
+ if(!fc) return NULL;
+ fc->typecode = FAKE_COMMPOINT_TYPECODE;
+ return (struct comm_point*)fc;
}
struct comm_point* comm_point_create_raw(struct comm_base* ATTR_UNUSED(base),
@@ -1177,7 +1303,11 @@ struct comm_point* comm_point_create_raw(struct comm_base* ATTR_UNUSED(base),
void* ATTR_UNUSED(callback_arg))
{
/* no pipe comm possible */
- return calloc(1, 1);
+ struct fake_commpoint* fc = (struct fake_commpoint*)calloc(1,
+ sizeof(*fc));
+ if(!fc) return NULL;
+ fc->typecode = FAKE_COMMPOINT_TYPECODE;
+ return (struct comm_point*)fc;
}
void comm_point_start_listening(struct comm_point* ATTR_UNUSED(c),
@@ -1194,6 +1324,13 @@ void comm_point_stop_listening(struct comm_point* ATTR_UNUSED(c))
/* only cmd com _local gets deleted */
void comm_point_delete(struct comm_point* c)
{
+ struct fake_commpoint* fc = (struct fake_commpoint*)c;
+ if(c == NULL) return;
+ log_assert(fc->typecode == FAKE_COMMPOINT_TYPECODE);
+ if(fc->type_tcp_out) {
+ /* remove tcp pending, so no more callbacks to it */
+ pending_list_delete(fc->runtime, fc->pending);
+ }
free(c);
}
@@ -1285,6 +1422,12 @@ void comm_signal_callback(int ATTR_UNUSED(fd),
log_assert(0);
}
+void comm_point_http_handle_callback(int ATTR_UNUSED(fd),
+ short ATTR_UNUSED(event), void* ATTR_UNUSED(arg))
+{
+ log_assert(0);
+}
+
void comm_point_local_handle_callback(int ATTR_UNUSED(fd),
short ATTR_UNUSED(event), void* ATTR_UNUSED(arg))
{
@@ -1420,4 +1563,229 @@ void daemon_remote_stop_accept(struct daemon_remote* ATTR_UNUSED(rc))
{
}
+int create_udp_sock(int ATTR_UNUSED(family), int ATTR_UNUSED(socktype),
+ struct sockaddr* ATTR_UNUSED(addr), socklen_t ATTR_UNUSED(addrlen),
+ int ATTR_UNUSED(v6only), int* ATTR_UNUSED(inuse),
+ int* ATTR_UNUSED(noproto), int ATTR_UNUSED(rcv), int ATTR_UNUSED(snd),
+ int ATTR_UNUSED(listen), int* ATTR_UNUSED(reuseport),
+ int ATTR_UNUSED(transparent), int ATTR_UNUSED(freebind),
+ int ATTR_UNUSED(use_systemd))
+{
+ /* if you actually print to this, it'll be stdout during test */
+ return 1;
+}
+
+struct comm_point* comm_point_create_udp(struct comm_base *ATTR_UNUSED(base),
+ int ATTR_UNUSED(fd), sldns_buffer* ATTR_UNUSED(buffer),
+ comm_point_callback_type* ATTR_UNUSED(callback),
+ void* ATTR_UNUSED(callback_arg))
+{
+ log_assert(0);
+ return NULL;
+}
+
+struct comm_point* comm_point_create_tcp_out(struct comm_base*
+ ATTR_UNUSED(base), size_t ATTR_UNUSED(bufsize),
+ comm_point_callback_type* ATTR_UNUSED(callback),
+ void* ATTR_UNUSED(callback_arg))
+{
+ log_assert(0);
+ return NULL;
+}
+
+struct comm_point* outnet_comm_point_for_udp(struct outside_network* outnet,
+ comm_point_callback_type* cb, void* cb_arg,
+ struct sockaddr_storage* ATTR_UNUSED(to_addr),
+ socklen_t ATTR_UNUSED(to_addrlen))
+{
+ struct replay_runtime* runtime = (struct replay_runtime*)
+ outnet->base;
+ struct fake_commpoint* fc = (struct fake_commpoint*)calloc(1,
+ sizeof(*fc));
+ if(!fc) return NULL;
+ fc->typecode = FAKE_COMMPOINT_TYPECODE;
+ fc->type_udp_out = 1;
+ fc->cb = cb;
+ fc->cb_arg = cb_arg;
+ fc->runtime = runtime;
+ /* used by authzone transfers */
+ return (struct comm_point*)fc;
+}
+
+struct comm_point* outnet_comm_point_for_tcp(struct outside_network* outnet,
+ comm_point_callback_type* cb, void* cb_arg,
+ struct sockaddr_storage* to_addr, socklen_t to_addrlen,
+ struct sldns_buffer* query, int timeout)
+{
+ struct replay_runtime* runtime = (struct replay_runtime*)
+ outnet->base;
+ struct fake_commpoint* fc = (struct fake_commpoint*)calloc(1,
+ sizeof(*fc));
+ struct fake_pending* pend = (struct fake_pending*)calloc(1,
+ sizeof(struct fake_pending));
+ if(!fc || !pend) {
+ free(fc);
+ free(pend);
+ return NULL;
+ }
+ fc->typecode = FAKE_COMMPOINT_TYPECODE;
+ fc->type_tcp_out = 1;
+ fc->cb = cb;
+ fc->cb_arg = cb_arg;
+ fc->runtime = runtime;
+ fc->pending = pend;
+
+ /* used by authzone transfers */
+ /* create pending item */
+ pend->buffer = sldns_buffer_new(sldns_buffer_limit(query)+10);
+ if(!pend->buffer) {
+ free(fc);
+ free(pend);
+ return NULL;
+ }
+ sldns_buffer_copy(pend->buffer, query);
+ memcpy(&pend->addr, to_addr, to_addrlen);
+ pend->addrlen = to_addrlen;
+ pend->zone = NULL;
+ pend->zonelen = 0;
+ if(LDNS_QDCOUNT(sldns_buffer_begin(query)) > 0) {
+ char buf[512];
+ char addrbuf[128];
+ (void)sldns_wire2str_rrquestion_buf(sldns_buffer_at(query, LDNS_HEADER_SIZE), sldns_buffer_limit(query)-LDNS_HEADER_SIZE, buf, sizeof(buf));
+ addr_to_str((struct sockaddr_storage*)to_addr, to_addrlen,
+ addrbuf, sizeof(addrbuf));
+ if(verbosity >= VERB_ALGO) {
+ if(buf[0] != 0) buf[strlen(buf)-1] = 0; /* del newline*/
+ log_info("tcp to %s: %s", addrbuf, buf);
+ }
+ log_assert(sldns_buffer_limit(query)-LDNS_HEADER_SIZE >= 2);
+ pend->qtype = (int)sldns_buffer_read_u16_at(query,
+ LDNS_HEADER_SIZE+
+ dname_valid(sldns_buffer_at(query, LDNS_HEADER_SIZE),
+ sldns_buffer_limit(query)-LDNS_HEADER_SIZE));
+ }
+ pend->callback = cb;
+ pend->cb_arg = cb_arg;
+ pend->timeout = timeout;
+ pend->transport = transport_tcp;
+ pend->pkt = NULL;
+ pend->runtime = runtime;
+ pend->serviced = 0;
+ pend->pkt_len = sldns_buffer_limit(pend->buffer);
+ pend->pkt = memdup(sldns_buffer_begin(pend->buffer), pend->pkt_len);
+ if(!pend->pkt) fatal_exit("out of memory");
+
+ log_info("testbound: created fake pending for tcp_out");
+
+ /* add to list */
+ pend->next = runtime->pending_list;
+ runtime->pending_list = pend;
+
+ return (struct comm_point*)fc;
+}
+
+struct comm_point* outnet_comm_point_for_http(struct outside_network* outnet,
+ comm_point_callback_type* cb, void* cb_arg,
+ struct sockaddr_storage* to_addr, socklen_t to_addrlen, int timeout,
+ int ssl, char* host, char* path)
+{
+ struct replay_runtime* runtime = (struct replay_runtime*)
+ outnet->base;
+ struct fake_commpoint* fc = (struct fake_commpoint*)calloc(1,
+ sizeof(*fc));
+ if(!fc) {
+ return NULL;
+ }
+ fc->typecode = FAKE_COMMPOINT_TYPECODE;
+ fc->type_http_out = 1;
+ fc->cb = cb;
+ fc->cb_arg = cb_arg;
+ fc->runtime = runtime;
+
+ (void)to_addr;
+ (void)to_addrlen;
+ (void)timeout;
+
+ (void)ssl;
+ (void)host;
+ (void)path;
+
+ /* handle http comm point and return contents from test script */
+ return (struct comm_point*)fc;
+}
+
+int comm_point_send_udp_msg(struct comm_point *c, sldns_buffer* packet,
+ struct sockaddr* addr, socklen_t addrlen)
+{
+ struct fake_commpoint* fc = (struct fake_commpoint*)c;
+ struct replay_runtime* runtime = fc->runtime;
+ struct fake_pending* pend = (struct fake_pending*)calloc(1,
+ sizeof(struct fake_pending));
+ if(!pend) {
+ log_err("malloc failure");
+ return 0;
+ }
+ fc->pending = pend;
+ /* used by authzone transfers */
+ /* create pending item */
+ pend->buffer = sldns_buffer_new(sldns_buffer_limit(packet) + 10);
+ if(!pend->buffer) {
+ free(pend);
+ return 0;
+ }
+ sldns_buffer_copy(pend->buffer, packet);
+ memcpy(&pend->addr, addr, addrlen);
+ pend->addrlen = addrlen;
+ pend->zone = NULL;
+ pend->zonelen = 0;
+ if(LDNS_QDCOUNT(sldns_buffer_begin(packet)) > 0) {
+ char buf[512];
+ char addrbuf[128];
+ (void)sldns_wire2str_rrquestion_buf(sldns_buffer_at(packet, LDNS_HEADER_SIZE), sldns_buffer_limit(packet)-LDNS_HEADER_SIZE, buf, sizeof(buf));
+ addr_to_str((struct sockaddr_storage*)addr, addrlen,
+ addrbuf, sizeof(addrbuf));
+ if(verbosity >= VERB_ALGO) {
+ if(buf[0] != 0) buf[strlen(buf)-1] = 0; /* del newline*/
+ log_info("udp to %s: %s", addrbuf, buf);
+ }
+ log_assert(sldns_buffer_limit(packet)-LDNS_HEADER_SIZE >= 2);
+ pend->qtype = (int)sldns_buffer_read_u16_at(packet,
+ LDNS_HEADER_SIZE+
+ dname_valid(sldns_buffer_at(packet, LDNS_HEADER_SIZE),
+ sldns_buffer_limit(packet)-LDNS_HEADER_SIZE));
+ }
+ pend->callback = fc->cb;
+ pend->cb_arg = fc->cb_arg;
+ pend->timeout = UDP_AUTH_QUERY_TIMEOUT;
+ pend->transport = transport_udp;
+ pend->pkt = NULL;
+ pend->runtime = runtime;
+ pend->serviced = 0;
+ pend->pkt_len = sldns_buffer_limit(pend->buffer);
+ pend->pkt = memdup(sldns_buffer_begin(pend->buffer), pend->pkt_len);
+ if(!pend->pkt) fatal_exit("out of memory");
+
+ log_info("testbound: created fake pending for send_udp_msg");
+
+ /* add to list */
+ pend->next = runtime->pending_list;
+ runtime->pending_list = pend;
+
+ return 1;
+}
+
+int outnet_get_tcp_fd(struct sockaddr_storage* ATTR_UNUSED(addr),
+ socklen_t ATTR_UNUSED(addrlen), int ATTR_UNUSED(tcp_mss))
+{
+ log_assert(0);
+ return -1;
+}
+
+int outnet_tcp_connect(int ATTR_UNUSED(s), struct sockaddr_storage* ATTR_UNUSED(addr),
+ socklen_t ATTR_UNUSED(addrlen))
+{
+ log_assert(0);
+ return 0;
+}
+
/*********** End of Dummy routines ***********/
diff --git a/testcode/replay.c b/testcode/replay.c
index 085c314759fd..08d87470bd00 100644
--- a/testcode/replay.c
+++ b/testcode/replay.c
@@ -323,6 +323,15 @@ replay_moment_read(char* remain, FILE* in, const char* name,
mom->autotrust_id = strdup(remain);
if(!mom->autotrust_id) fatal_exit("out of memory");
read_file_content(in, &pstate->lineno, mom);
+ } else if(parse_keyword(&remain, "CHECK_TEMPFILE")) {
+ mom->evt_type = repevt_tempfile_check;
+ while(isspace((unsigned char)*remain))
+ remain++;
+ if(strlen(remain)>0 && remain[strlen(remain)-1]=='\n')
+ remain[strlen(remain)-1] = 0;
+ mom->autotrust_id = strdup(remain);
+ if(!mom->autotrust_id) fatal_exit("out of memory");
+ read_file_content(in, &pstate->lineno, mom);
} else if(parse_keyword(&remain, "ERROR")) {
mom->evt_type = repevt_error;
} else if(parse_keyword(&remain, "TRAFFIC")) {
diff --git a/testcode/replay.h b/testcode/replay.h
index b33950304d12..81f0a2c275b2 100644
--- a/testcode/replay.h
+++ b/testcode/replay.h
@@ -49,6 +49,14 @@
* AUTOTRUST_FILE id
* ; contents of that file
* AUTOTRUST_END
+ * ; temp file names are echoed as "tmp/xxx.fname"
+ * TEMPFILE_NAME fname
+ * ; temp file contents, inline, deleted at end of run
+ * TEMPFILE_CONTENTS fname
+ * ; contents of that file
+ * ; this creates $INCLUDE /tmp/xxx.fname
+ * $INCLUDE_TEMPFILE fname
+ * TEMPFILE_END
* CONFIG_END
* ; comment line.
* SCENARIO_BEGIN name_of_scenario
@@ -75,6 +83,7 @@
* the step waits for traffic to stop.
* o CHECK_AUTOTRUST [id] - followed by FILE_BEGIN [to match] FILE_END.
* The file contents is macro expanded before match.
+ * o CHECK_TEMPFILE [fname] - followed by FILE_BEGIN [to match] FILE_END
* o INFRA_RTT [ip] [dp] [rtt] - update infra cache entry with rtt.
* o ERROR
* ; following entry starts on the next line, ENTRY_BEGIN.
@@ -195,6 +204,8 @@ struct replay_moment {
repevt_back_query,
/** check autotrust key file */
repevt_autotrust_check,
+ /** check a temp file */
+ repevt_tempfile_check,
/** an error happens to outbound query */
repevt_error,
/** assignment to a variable */
@@ -340,6 +351,8 @@ struct fake_pending {
enum transport_type transport;
/** if this is a serviced query */
int serviced;
+ /** if we are handling a multi pkt tcp stream, non 0 and the pkt nr*/
+ int tcp_pkt_counter;
/** the runtime structure this is part of */
struct replay_runtime* runtime;
};
diff --git a/testcode/testbound.c b/testcode/testbound.c
index 20c99608fdd7..56b89c7f0d7e 100644
--- a/testcode/testbound.c
+++ b/testcode/testbound.c
@@ -135,6 +135,65 @@ echo_cmdline(int argc, char* argv[])
fprintf(stderr, "\n");
}
+/** spool temp file name */
+static void
+spool_temp_file_name(int* lineno, FILE* cfg, char* id)
+{
+ char line[MAX_LINE_LEN];
+ /* find filename for new file */
+ while(isspace((unsigned char)*id))
+ id++;
+ if(*id == '\0')
+ fatal_exit("TEMPFILE_NAME must have id, line %d", *lineno);
+ id[strlen(id)-1]=0; /* remove newline */
+ fake_temp_file("_temp_", id, line, sizeof(line));
+ fprintf(cfg, "\"%s\"\n", line);
+}
+
+/** spool temp file */
+static void
+spool_temp_file(FILE* in, int* lineno, char* id)
+{
+ char line[MAX_LINE_LEN];
+ char* parse;
+ FILE* spool;
+ /* find filename for new file */
+ while(isspace((unsigned char)*id))
+ id++;
+ if(*id == '\0')
+ fatal_exit("TEMPFILE_CONTENTS must have id, line %d", *lineno);
+ id[strlen(id)-1]=0; /* remove newline */
+ fake_temp_file("_temp_", id, line, sizeof(line));
+ /* open file and spool to it */
+ spool = fopen(line, "w");
+ if(!spool) fatal_exit("could not open %s: %s", line, strerror(errno));
+ fprintf(stderr, "testbound is spooling temp file: %s\n", line);
+ if(!cfg_strlist_insert(&cfgfiles, strdup(line)))
+ fatal_exit("out of memory");
+ line[sizeof(line)-1] = 0;
+ while(fgets(line, MAX_LINE_LEN-1, in)) {
+ parse = line;
+ (*lineno)++;
+ while(isspace((unsigned char)*parse))
+ parse++;
+ if(strncmp(parse, "$INCLUDE_TEMPFILE", 17) == 0) {
+ char l2[MAX_LINE_LEN];
+ char* tid = parse+17;
+ while(isspace((unsigned char)*tid))
+ tid++;
+ tid[strlen(tid)-1]=0; /* remove newline */
+ fake_temp_file("_temp_", tid, l2, sizeof(l2));
+ snprintf(line, sizeof(line), "$INCLUDE %s\n", l2);
+ }
+ if(strncmp(parse, "TEMPFILE_END", 12) == 0) {
+ fclose(spool);
+ return;
+ }
+ fputs(line, spool);
+ }
+ fatal_exit("no TEMPFILE_END in input file");
+}
+
/** spool autotrust file */
static void
spool_auto_file(FILE* in, int* lineno, FILE* cfg, char* id)
@@ -213,6 +272,14 @@ setup_config(FILE* in, int* lineno, int* pass_argc, char* pass_argv[])
spool_auto_file(in, lineno, cfg, parse+14);
continue;
}
+ if(strncmp(parse, "TEMPFILE_NAME", 13) == 0) {
+ spool_temp_file_name(lineno, cfg, parse+13);
+ continue;
+ }
+ if(strncmp(parse, "TEMPFILE_CONTENTS", 17) == 0) {
+ spool_temp_file(in, lineno, parse+17);
+ continue;
+ }
if(strncmp(parse, "CONFIG_END", 10) == 0) {
fclose(cfg);
return;
@@ -287,6 +354,10 @@ main(int argc, char* argv[])
case 's':
free(pass_argv[1]);
testbound_selftest();
+ checklock_stop();
+ if(log_get_lock()) {
+ lock_quick_destroy((lock_quick_type*)log_get_lock());
+ }
exit(0);
case '1':
#ifdef USE_SHA1
@@ -389,7 +460,10 @@ main(int argc, char* argv[])
for(c=1; c<pass_argc; c++)
free(pass_argv[c]);
if(res == 0) {
- log_info("Testbound Exit Success");
+ log_info("Testbound Exit Success\n");
+ if(log_get_lock()) {
+ lock_quick_destroy((lock_quick_type*)log_get_lock());
+ }
#ifdef HAVE_PTHREAD
/* dlopen frees its thread state (dlopen of gost engine) */
pthread_exit(NULL);
diff --git a/testcode/testpkts.c b/testcode/testpkts.c
index e1a7768abed0..ec0f7fe2449a 100644
--- a/testcode/testpkts.c
+++ b/testcode/testpkts.c
@@ -572,7 +572,15 @@ read_entry(FILE* in, const char* name, struct sldns_file_parse_state* pstate,
} else if(str_keyword(&parse, "ADJUST")) {
adjustline(parse, current, cur_reply);
} else if(str_keyword(&parse, "EXTRA_PACKET")) {
+ /* copy current packet into buffer */
+ cur_reply->reply_pkt = memdup(pktbuf, pktlen);
+ cur_reply->reply_len = pktlen;
+ if(!cur_reply->reply_pkt)
+ error("out of memory");
cur_reply = entry_add_reply(current);
+ /* clear for next packet */
+ pktlen = LDNS_HEADER_SIZE;
+ memset(pktbuf, 0, pktlen); /* ID = 0, FLAGS="", and rr counts 0 */
} else if(str_keyword(&parse, "SECTION")) {
if(str_keyword(&parse, "QUESTION"))
add_section = LDNS_SECTION_QUESTION;
@@ -1558,10 +1566,10 @@ adjust_packet(struct entry* match, uint8_t** answer_pkt, size_t *answer_len,
return;
}
/* copy the ID */
- if(match->copy_id && reslen >= 2)
- res[1] = orig[1];
- if(match->copy_id && reslen >= 1)
- res[0] = orig[0];
+ if(match->copy_id && reslen >= 2 && query_len >= 2)
+ res[1] = query_pkt[1];
+ if(match->copy_id && reslen >= 1 && query_len >= 1)
+ res[0] = query_pkt[0];
if(match->copy_ednsdata_assume_clientsubnet) {
/** Assume there is only one EDNS option, which is ECS.
diff --git a/testcode/unitauth.c b/testcode/unitauth.c
index f6c022aa03d7..4b538ef62687 100644
--- a/testcode/unitauth.c
+++ b/testcode/unitauth.c
@@ -95,42 +95,42 @@ static const char* zone_example_com =
/* and some tests for RRSIGs (rrsig is www.nlnetlabs.nl copy) */
/* normal: domain and 1 rrsig */
"z1.example.com. 3600 IN A 10.0.0.10\n"
-"z1.example.com. 3600 IN RRSIG A 8 3 10200 20170612005010 20170515005010 42393 nlnetlabs.nl. NhEDrHkuIgHkjWhDRVsGOIJWZpSs+QdduilWFe5d+/ZhOheLJbaTYD5w6+ZZ3yPh1tNud+jlg+GyiOSVapLEO31swDCIarL1UfRjRSpxxDCHGag5Zu+S4hF+KURxO3cJk8jLBELMQyRuMRHoKrw/wsiLGVu1YpAyAPPMcjFBNbk= ;{id = 42393}\n"
+"z1.example.com. 3600 IN RRSIG A 8 3 10200 20170612005010 20170515005010 42393 nlnetlabs.nl. NhEDrHkuIgHkjWhDRVsGOIJWZpSs+QdduilWFe5d+/ZhOheLJbaTYD5w6+ZZ3yPh1tNud+jlg+GyiOSVapLEO31swDCIarL1UfRjRSpxxDCHGag5Zu+S4hF+KURxO3cJk8jLBELMQyRuMRHoKrw/wsiLGVu1YpAyAPPMcjFBNbk=\n"
/* normal: domain and 2 rrsigs */
"z2.example.com. 3600 IN A 10.0.0.10\n"
-"z2.example.com. 3600 IN RRSIG A 8 3 10200 20170612005010 20170515005010 42393 nlnetlabs.nl. NhEDrHkuIgHkjWhDRVsGOIJWZpSs+QdduilWFe5d+/ZhOheLJbaTYD5w6+ZZ3yPh1tNud+jlg+GyiOSVapLEO31swDCIarL1UfRjRSpxxDCHGag5Zu+S4hF+KURxO3cJk8jLBELMQyRuMRHoKrw/wsiLGVu1YpAyAPPMcjFBNbk= ;{id = 42393}\n"
-"z2.example.com. 3600 IN RRSIG A 8 3 10200 20170612005010 20170515005010 12345 nlnetlabs.nl. NhEDrHkuIgHkjWhDRVsGOIJWZpSs+QdduilWFe5d+/ZhOheLJbaTYD5w6+ZZ3yPh1tNud+jlg+GyiOSVapLEO31swDCIarL1UfRjRSpxxDCHGag5Zu+S4hF+KURxO3cJk8jLBELMQyRuMRHoKrw/wsiLGVu1YpAyAPPMcjFBNbk= ;{id = 12345}\n"
+"z2.example.com. 3600 IN RRSIG A 8 3 10200 20170612005010 20170515005010 42393 nlnetlabs.nl. NhEDrHkuIgHkjWhDRVsGOIJWZpSs+QdduilWFe5d+/ZhOheLJbaTYD5w6+ZZ3yPh1tNud+jlg+GyiOSVapLEO31swDCIarL1UfRjRSpxxDCHGag5Zu+S4hF+KURxO3cJk8jLBELMQyRuMRHoKrw/wsiLGVu1YpAyAPPMcjFBNbk=\n"
+"z2.example.com. 3600 IN RRSIG A 8 3 10200 20170612005010 20170515005010 12345 nlnetlabs.nl. NhEDrHkuIgHkjWhDRVsGOIJWZpSs+QdduilWFe5d+/ZhOheLJbaTYD5w6+ZZ3yPh1tNud+jlg+GyiOSVapLEO31swDCIarL1UfRjRSpxxDCHGag5Zu+S4hF+KURxO3cJk8jLBELMQyRuMRHoKrw/wsiLGVu1YpAyAPPMcjFBNbk=\n"
/* normal: domain and 3 rrsigs */
"z3.example.com. 3600 IN A 10.0.0.10\n"
"z3.example.com. 3600 IN A 10.0.0.11\n"
-"z3.example.com. 3600 IN RRSIG A 8 3 10200 20170612005010 20170515005010 42393 nlnetlabs.nl. NhEDrHkuIgHkjWhDRVsGOIJWZpSs+QdduilWFe5d+/ZhOheLJbaTYD5w6+ZZ3yPh1tNud+jlg+GyiOSVapLEO31swDCIarL1UfRjRSpxxDCHGag5Zu+S4hF+KURxO3cJk8jLBELMQyRuMRHoKrw/wsiLGVu1YpAyAPPMcjFBNbk= ;{id = 42393}\n"
-"z3.example.com. 3600 IN RRSIG A 8 3 10200 20170612005010 20170515005010 12345 nlnetlabs.nl. NhEDrHkuIgHkjWhDRVsGOIJWZpSs+QdduilWFe5d+/ZhOheLJbaTYD5w6+ZZ3yPh1tNud+jlg+GyiOSVapLEO31swDCIarL1UfRjRSpxxDCHGag5Zu+S4hF+KURxO3cJk8jLBELMQyRuMRHoKrw/wsiLGVu1YpAyAPPMcjFBNbk= ;{id = 12345}\n"
-"z3.example.com. 3600 IN RRSIG A 8 3 10200 20170612005010 20170515005010 12356 nlnetlabs.nl. NhEDrHkuIgHkjWhDRVsGOIJWZpSs+QdduilWFe5d+/ZhOheLJbaTYD5w6+ZZ3yPh1tNud+jlg+GyiOSVapLEO31swDCIarL1UfRjRSpxxDCHGag5Zu+S4hF+KURxO3cJk8jLBELMQyRuMRHoKrw/wsiLGVu1YpAyAPPMcjFBNbk= ;{id = 12356}\n"
+"z3.example.com. 3600 IN RRSIG A 8 3 10200 20170612005010 20170515005010 42393 nlnetlabs.nl. NhEDrHkuIgHkjWhDRVsGOIJWZpSs+QdduilWFe5d+/ZhOheLJbaTYD5w6+ZZ3yPh1tNud+jlg+GyiOSVapLEO31swDCIarL1UfRjRSpxxDCHGag5Zu+S4hF+KURxO3cJk8jLBELMQyRuMRHoKrw/wsiLGVu1YpAyAPPMcjFBNbk=\n"
+"z3.example.com. 3600 IN RRSIG A 8 3 10200 20170612005010 20170515005010 12345 nlnetlabs.nl. NhEDrHkuIgHkjWhDRVsGOIJWZpSs+QdduilWFe5d+/ZhOheLJbaTYD5w6+ZZ3yPh1tNud+jlg+GyiOSVapLEO31swDCIarL1UfRjRSpxxDCHGag5Zu+S4hF+KURxO3cJk8jLBELMQyRuMRHoKrw/wsiLGVu1YpAyAPPMcjFBNbk=\n"
+"z3.example.com. 3600 IN RRSIG A 8 3 10200 20170612005010 20170515005010 12356 nlnetlabs.nl. NhEDrHkuIgHkjWhDRVsGOIJWZpSs+QdduilWFe5d+/ZhOheLJbaTYD5w6+ZZ3yPh1tNud+jlg+GyiOSVapLEO31swDCIarL1UfRjRSpxxDCHGag5Zu+S4hF+KURxO3cJk8jLBELMQyRuMRHoKrw/wsiLGVu1YpAyAPPMcjFBNbk=\n"
/* just an RRSIG rrset with nothing else */
-"z4.example.com. 3600 IN RRSIG A 8 3 10200 20170612005010 20170515005010 42393 nlnetlabs.nl. NhEDrHkuIgHkjWhDRVsGOIJWZpSs+QdduilWFe5d+/ZhOheLJbaTYD5w6+ZZ3yPh1tNud+jlg+GyiOSVapLEO31swDCIarL1UfRjRSpxxDCHGag5Zu+S4hF+KURxO3cJk8jLBELMQyRuMRHoKrw/wsiLGVu1YpAyAPPMcjFBNbk= ;{id = 42393}\n"
+"z4.example.com. 3600 IN RRSIG A 8 3 10200 20170612005010 20170515005010 42393 nlnetlabs.nl. NhEDrHkuIgHkjWhDRVsGOIJWZpSs+QdduilWFe5d+/ZhOheLJbaTYD5w6+ZZ3yPh1tNud+jlg+GyiOSVapLEO31swDCIarL1UfRjRSpxxDCHGag5Zu+S4hF+KURxO3cJk8jLBELMQyRuMRHoKrw/wsiLGVu1YpAyAPPMcjFBNbk=\n"
/* just an RRSIG rrset with nothing else, 2 rrsigs */
-"z5.example.com. 3600 IN RRSIG A 8 3 10200 20170612005010 20170515005010 42393 nlnetlabs.nl. NhEDrHkuIgHkjWhDRVsGOIJWZpSs+QdduilWFe5d+/ZhOheLJbaTYD5w6+ZZ3yPh1tNud+jlg+GyiOSVapLEO31swDCIarL1UfRjRSpxxDCHGag5Zu+S4hF+KURxO3cJk8jLBELMQyRuMRHoKrw/wsiLGVu1YpAyAPPMcjFBNbk= ;{id = 42393}\n"
-"z5.example.com. 3600 IN RRSIG A 8 3 10200 20170612005010 20170515005010 12345 nlnetlabs.nl. NhEDrHkuIgHkjWhDRVsGOIJWZpSs+QdduilWFe5d+/ZhOheLJbaTYD5w6+ZZ3yPh1tNud+jlg+GyiOSVapLEO31swDCIarL1UfRjRSpxxDCHGag5Zu+S4hF+KURxO3cJk8jLBELMQyRuMRHoKrw/wsiLGVu1YpAyAPPMcjFBNbk= ;{id = 12345}\n"
+"z5.example.com. 3600 IN RRSIG A 8 3 10200 20170612005010 20170515005010 42393 nlnetlabs.nl. NhEDrHkuIgHkjWhDRVsGOIJWZpSs+QdduilWFe5d+/ZhOheLJbaTYD5w6+ZZ3yPh1tNud+jlg+GyiOSVapLEO31swDCIarL1UfRjRSpxxDCHGag5Zu+S4hF+KURxO3cJk8jLBELMQyRuMRHoKrw/wsiLGVu1YpAyAPPMcjFBNbk=\n"
+"z5.example.com. 3600 IN RRSIG A 8 3 10200 20170612005010 20170515005010 12345 nlnetlabs.nl. NhEDrHkuIgHkjWhDRVsGOIJWZpSs+QdduilWFe5d+/ZhOheLJbaTYD5w6+ZZ3yPh1tNud+jlg+GyiOSVapLEO31swDCIarL1UfRjRSpxxDCHGag5Zu+S4hF+KURxO3cJk8jLBELMQyRuMRHoKrw/wsiLGVu1YpAyAPPMcjFBNbk=\n"
#if 0 /* comparison of file does not work on this part because duplicates */
/* are removed and the rrsets are reordered */
/* first rrsig, then A record */
-"z6.example.com. 3600 IN RRSIG A 8 3 10200 20170612005010 20170515005010 42393 nlnetlabs.nl. NhEDrHkuIgHkjWhDRVsGOIJWZpSs+QdduilWFe5d+/ZhOheLJbaTYD5w6+ZZ3yPh1tNud+jlg+GyiOSVapLEO31swDCIarL1UfRjRSpxxDCHGag5Zu+S4hF+KURxO3cJk8jLBELMQyRuMRHoKrw/wsiLGVu1YpAyAPPMcjFBNbk= ;{id = 42393}\n"
+"z6.example.com. 3600 IN RRSIG A 8 3 10200 20170612005010 20170515005010 42393 nlnetlabs.nl. NhEDrHkuIgHkjWhDRVsGOIJWZpSs+QdduilWFe5d+/ZhOheLJbaTYD5w6+ZZ3yPh1tNud+jlg+GyiOSVapLEO31swDCIarL1UfRjRSpxxDCHGag5Zu+S4hF+KURxO3cJk8jLBELMQyRuMRHoKrw/wsiLGVu1YpAyAPPMcjFBNbk=\n"
"z6.example.com. 3600 IN A 10.0.0.10\n"
/* first two rrsigs, then A record */
-"z7.example.com. 3600 IN RRSIG A 8 3 10200 20170612005010 20170515005010 42393 nlnetlabs.nl. NhEDrHkuIgHkjWhDRVsGOIJWZpSs+QdduilWFe5d+/ZhOheLJbaTYD5w6+ZZ3yPh1tNud+jlg+GyiOSVapLEO31swDCIarL1UfRjRSpxxDCHGag5Zu+S4hF+KURxO3cJk8jLBELMQyRuMRHoKrw/wsiLGVu1YpAyAPPMcjFBNbk= ;{id = 42393}\n"
-"z7.example.com. 3600 IN RRSIG A 8 3 10200 20170612005010 20170515005010 12345 nlnetlabs.nl. NhEDrHkuIgHkjWhDRVsGOIJWZpSs+QdduilWFe5d+/ZhOheLJbaTYD5w6+ZZ3yPh1tNud+jlg+GyiOSVapLEO31swDCIarL1UfRjRSpxxDCHGag5Zu+S4hF+KURxO3cJk8jLBELMQyRuMRHoKrw/wsiLGVu1YpAyAPPMcjFBNbk= ;{id = 12345}\n"
+"z7.example.com. 3600 IN RRSIG A 8 3 10200 20170612005010 20170515005010 42393 nlnetlabs.nl. NhEDrHkuIgHkjWhDRVsGOIJWZpSs+QdduilWFe5d+/ZhOheLJbaTYD5w6+ZZ3yPh1tNud+jlg+GyiOSVapLEO31swDCIarL1UfRjRSpxxDCHGag5Zu+S4hF+KURxO3cJk8jLBELMQyRuMRHoKrw/wsiLGVu1YpAyAPPMcjFBNbk=\n"
+"z7.example.com. 3600 IN RRSIG A 8 3 10200 20170612005010 20170515005010 12345 nlnetlabs.nl. NhEDrHkuIgHkjWhDRVsGOIJWZpSs+QdduilWFe5d+/ZhOheLJbaTYD5w6+ZZ3yPh1tNud+jlg+GyiOSVapLEO31swDCIarL1UfRjRSpxxDCHGag5Zu+S4hF+KURxO3cJk8jLBELMQyRuMRHoKrw/wsiLGVu1YpAyAPPMcjFBNbk=\n"
"z7.example.com. 3600 IN A 10.0.0.10\n"
/* first two rrsigs, then two A records */
-"z8.example.com. 3600 IN RRSIG A 8 3 10200 20170612005010 20170515005010 42393 nlnetlabs.nl. NhEDrHkuIgHkjWhDRVsGOIJWZpSs+QdduilWFe5d+/ZhOheLJbaTYD5w6+ZZ3yPh1tNud+jlg+GyiOSVapLEO31swDCIarL1UfRjRSpxxDCHGag5Zu+S4hF+KURxO3cJk8jLBELMQyRuMRHoKrw/wsiLGVu1YpAyAPPMcjFBNbk= ;{id = 42393}\n"
-"z8.example.com. 3600 IN RRSIG A 8 3 10200 20170612005010 20170515005010 12345 nlnetlabs.nl. NhEDrHkuIgHkjWhDRVsGOIJWZpSs+QdduilWFe5d+/ZhOheLJbaTYD5w6+ZZ3yPh1tNud+jlg+GyiOSVapLEO31swDCIarL1UfRjRSpxxDCHGag5Zu+S4hF+KURxO3cJk8jLBELMQyRuMRHoKrw/wsiLGVu1YpAyAPPMcjFBNbk= ;{id = 12345}\n"
+"z8.example.com. 3600 IN RRSIG A 8 3 10200 20170612005010 20170515005010 42393 nlnetlabs.nl. NhEDrHkuIgHkjWhDRVsGOIJWZpSs+QdduilWFe5d+/ZhOheLJbaTYD5w6+ZZ3yPh1tNud+jlg+GyiOSVapLEO31swDCIarL1UfRjRSpxxDCHGag5Zu+S4hF+KURxO3cJk8jLBELMQyRuMRHoKrw/wsiLGVu1YpAyAPPMcjFBNbk=\n"
+"z8.example.com. 3600 IN RRSIG A 8 3 10200 20170612005010 20170515005010 12345 nlnetlabs.nl. NhEDrHkuIgHkjWhDRVsGOIJWZpSs+QdduilWFe5d+/ZhOheLJbaTYD5w6+ZZ3yPh1tNud+jlg+GyiOSVapLEO31swDCIarL1UfRjRSpxxDCHGag5Zu+S4hF+KURxO3cJk8jLBELMQyRuMRHoKrw/wsiLGVu1YpAyAPPMcjFBNbk=\n"
"z8.example.com. 3600 IN A 10.0.0.10\n"
"z8.example.com. 3600 IN A 10.0.0.11\n"
/* duplicate RR, duplicate RRsig */
"z9.example.com. 3600 IN A 10.0.0.10\n"
"z9.example.com. 3600 IN A 10.0.0.11\n"
"z9.example.com. 3600 IN A 10.0.0.10\n"
-"z9.example.com. 3600 IN RRSIG A 8 3 10200 20170612005010 20170515005010 42393 nlnetlabs.nl. NhEDrHkuIgHkjWhDRVsGOIJWZpSs+QdduilWFe5d+/ZhOheLJbaTYD5w6+ZZ3yPh1tNud+jlg+GyiOSVapLEO31swDCIarL1UfRjRSpxxDCHGag5Zu+S4hF+KURxO3cJk8jLBELMQyRuMRHoKrw/wsiLGVu1YpAyAPPMcjFBNbk= ;{id = 42393}\n"
-"z9.example.com. 3600 IN RRSIG A 8 3 10200 20170612005010 20170515005010 42393 nlnetlabs.nl. NhEDrHkuIgHkjWhDRVsGOIJWZpSs+QdduilWFe5d+/ZhOheLJbaTYD5w6+ZZ3yPh1tNud+jlg+GyiOSVapLEO31swDCIarL1UfRjRSpxxDCHGag5Zu+S4hF+KURxO3cJk8jLBELMQyRuMRHoKrw/wsiLGVu1YpAyAPPMcjFBNbk= ;{id = 42393}\n"
+"z9.example.com. 3600 IN RRSIG A 8 3 10200 20170612005010 20170515005010 42393 nlnetlabs.nl. NhEDrHkuIgHkjWhDRVsGOIJWZpSs+QdduilWFe5d+/ZhOheLJbaTYD5w6+ZZ3yPh1tNud+jlg+GyiOSVapLEO31swDCIarL1UfRjRSpxxDCHGag5Zu+S4hF+KURxO3cJk8jLBELMQyRuMRHoKrw/wsiLGVu1YpAyAPPMcjFBNbk=\n"
+"z9.example.com. 3600 IN RRSIG A 8 3 10200 20170612005010 20170515005010 42393 nlnetlabs.nl. NhEDrHkuIgHkjWhDRVsGOIJWZpSs+QdduilWFe5d+/ZhOheLJbaTYD5w6+ZZ3yPh1tNud+jlg+GyiOSVapLEO31swDCIarL1UfRjRSpxxDCHGag5Zu+S4hF+KURxO3cJk8jLBELMQyRuMRHoKrw/wsiLGVu1YpAyAPPMcjFBNbk=\n"
#endif /* if0 for duplicates and reordering */
;
@@ -521,6 +521,7 @@ addzone(struct auth_zones* az, const char* name, char* fname)
lock_rw_unlock(&az->lock);
if(!z) fatal_exit("cannot find zone");
auth_zone_set_zonefile(z, fname);
+ z->for_upstream = 1;
if(!auth_zone_read_zonefile(z)) {
fatal_exit("parse failure for auth zone %s", name);
@@ -685,8 +686,12 @@ msgtostr(struct dns_msg* msg)
char* str;
sldns_buffer* buf = sldns_buffer_new(65535);
if(!buf) fatal_exit("out of memory");
- pr_flags(buf, msg->rep->flags);
- pr_rrs(buf, msg->rep);
+ if(!msg) {
+ sldns_buffer_printf(buf, "null packet\n");
+ } else {
+ pr_flags(buf, msg->rep->flags);
+ pr_rrs(buf, msg->rep);
+ }
str = strdup((char*)sldns_buffer_begin(buf));
if(!str) fatal_exit("out of memory");
@@ -831,6 +836,24 @@ check_queries(const char* name, const char* zone, struct q_ans* queries)
auth_zones_delete(az);
}
+/** Test authzone compare_serial */
+static void
+authzone_compare_serial(void)
+{
+ if(vbmp) printf("Testing compare_serial\n");
+ unit_assert(compare_serial(0, 1) < 0);
+ unit_assert(compare_serial(1, 0) > 0);
+ unit_assert(compare_serial(0, 0) == 0);
+ unit_assert(compare_serial(1, 1) == 0);
+ unit_assert(compare_serial(0xf0000000, 0xf0000000) == 0);
+ unit_assert(compare_serial(0, 0xf0000000) > 0);
+ unit_assert(compare_serial(0xf0000000, 0) < 0);
+ unit_assert(compare_serial(0xf0000000, 0xf0000001) < 0);
+ unit_assert(compare_serial(0xf0000002, 0xf0000001) > 0);
+ unit_assert(compare_serial(0x70000000, 0x80000000) < 0);
+ unit_assert(compare_serial(0x90000000, 0x70000000) > 0);
+}
+
/** Test authzone read from file */
static void
authzone_read_test(void)
@@ -853,6 +876,7 @@ authzone_test(void)
{
unit_show_feature("authzone");
atexit(tmpfilecleanup);
+ authzone_compare_serial();
authzone_read_test();
authzone_query_test();
}
diff --git a/testcode/unitmain.c b/testcode/unitmain.c
index d662991bab5d..57883d183b9f 100644
--- a/testcode/unitmain.c
+++ b/testcode/unitmain.c
@@ -433,7 +433,6 @@ rtt_test(void)
}
#include "services/cache/infra.h"
-#include "util/config_file.h"
/* lookup and get key and data structs easily */
static struct infra_data* infra_lookup_host(struct infra_cache* infra,
diff --git a/testcode/unitverify.c b/testcode/unitverify.c
index eec11df60778..06691f822e40 100644
--- a/testcode/unitverify.c
+++ b/testcode/unitverify.c
@@ -524,6 +524,7 @@ verify_test(void)
#endif
#if (defined(HAVE_EVP_SHA512) || defined(HAVE_NSS) || defined(HAVE_NETTLE)) && defined(USE_SHA2)
verifytest_file("testdata/test_sigs.rsasha512_draft", "20070829144150");
+ verifytest_file("testdata/test_signatures.9", "20171215000000");
#endif
#ifdef USE_SHA1
verifytest_file("testdata/test_sigs.hinfo", "20090107100022");
diff --git a/testdata/03-testbound.tdir/03-testbound.test b/testdata/03-testbound.tdir/03-testbound.test
index e23151c41657..aefdc18554f4 100644
--- a/testdata/03-testbound.tdir/03-testbound.test
+++ b/testdata/03-testbound.tdir/03-testbound.test
@@ -11,7 +11,12 @@ get_make
exitval=0
# quiet="" to make verbose
-do_valgrind=no
+if test -f $PRE/unbound_do_valgrind_in_test; then
+ do_valgrind=yes
+else
+ do_valgrind=no
+fi
+VALGRIND_FLAGS="--leak-check=full --show-leak-kinds=all"
# valgrind mode for debug
#if grep "staticexe=-static" $PRE/Makefile >/dev/null 2>&1; then
# if test -x "`which valgrind`"; then
@@ -21,19 +26,28 @@ do_valgrind=no
# self-test (unit test of testbound)
if test $do_valgrind = "yes"; then
- if (valgrind $PRE/testbound -s >tmpout 2>&1;); then
+ if (valgrind $VALGRIND_FLAGS $PRE/testbound -s >tmpout 2>&1;); then
echo "selftest OK "
else
echo "selftest FAILED"
exit 1
fi
- if grep "All heap blocks were freed -- no leaks are possible." tmpout >/dev/null 2>&1; then
+ if grep "All heap blocks were freed -- no leaks are possible" tmpout >/dev/null 2>&1; then
: # clean
else
+ cat tmpout
echo "Memory leaked in selftest"
grep "in use at exit" tmpout
exit 1
fi
+ if grep "ERROR SUMMARY: 0 errors from 0 contexts" tmpout >/dev/null 2>&1; then
+ : # clean
+ else
+ cat tmpout
+ echo "Errors in selftest"
+ grep "ERROR SUMMARY" tmpout
+ exit 1
+ fi
else
if ($PRE/testbound -s >/dev/null 2>&1;); then
echo "selftest OK "
@@ -88,19 +102,28 @@ for input in $PRE/testdata/*.rpl $PRE/testdata/*.crpl; do
fi
if test $do_valgrind = "yes"; then
- if (valgrind $PRE/testbound -p $input >tmpout 2>&1;); then
+ if (valgrind $VALGRIND_FLAGS $PRE/testbound -p $input >tmpout 2>&1;); then
echo " OK $cleaninput: $header"
else
echo "FAILED $cleaninput: $header"
exitval=1
fi
- if grep "All heap blocks were freed -- no leaks are possible." tmpout >/dev/null 2>&1; then
+ if grep "All heap blocks were freed -- no leaks are possible" tmpout >/dev/null 2>&1; then
: # clean
else
+ grep "^==" tmpout
echo "Memory leaked in $cleaninput"
grep "in use at exit" tmpout
exitval=1
fi
+ if grep "ERROR SUMMARY: 0 errors from 0 contexts" tmpout >/dev/null 2>&1; then
+ : # clean
+ else
+ grep "^==" tmpout
+ echo "Errors in $cleaninput"
+ grep "ERROR SUMMARY" tmpout
+ exitval=1
+ fi
else
# do valgrind=no
if ($PRE/testbound -p $input >/dev/null 2>&1;); then
diff --git a/testdata/auth_axfr.tdir/auth_axfr.conf b/testdata/auth_axfr.tdir/auth_axfr.conf
new file mode 100644
index 000000000000..b7f03bb480c7
--- /dev/null
+++ b/testdata/auth_axfr.tdir/auth_axfr.conf
@@ -0,0 +1,18 @@
+server:
+ verbosity: 7
+ # num-threads: 1
+ interface: 127.0.0.1
+ port: @PORT@
+ use-syslog: no
+ directory: ""
+ pidfile: "unbound.pid"
+ chroot: ""
+ username: ""
+ do-not-query-localhost: no
+ use-caps-for-id: yes
+auth-zone:
+ name: "example.com"
+ for-upstream: yes
+ for-downstream: yes
+ master: "127.0.0.1@@TOPORT@"
+
diff --git a/testdata/auth_axfr.tdir/auth_axfr.dsc b/testdata/auth_axfr.tdir/auth_axfr.dsc
new file mode 100644
index 000000000000..a3386713798d
--- /dev/null
+++ b/testdata/auth_axfr.tdir/auth_axfr.dsc
@@ -0,0 +1,16 @@
+BaseName: auth_axfr
+Version: 1.0
+Description: Perform AXFR for authority zone
+CreationDate: Tue 13 Jun 09:35:40 CEST 2017
+Maintainer: dr. W.C.A. Wijngaards
+Category:
+Component:
+CmdDepends:
+Depends:
+Help:
+Pre: auth_axfr.pre
+Post: auth_axfr.post
+Test: auth_axfr.test
+AuxFiles:
+Passed:
+Failure:
diff --git a/testdata/auth_axfr.tdir/auth_axfr.post b/testdata/auth_axfr.tdir/auth_axfr.post
new file mode 100644
index 000000000000..5b2f7c62050b
--- /dev/null
+++ b/testdata/auth_axfr.tdir/auth_axfr.post
@@ -0,0 +1,10 @@
+# #-- auth_axfr.post --#
+# source the master var file when it's there
+[ -f ../.tpkg.var.master ] && source ../.tpkg.var.master
+# source the test var file when it's there
+[ -f .tpkg.var.test ] && source .tpkg.var.test
+#
+# do your teardown here
+. ../common.sh
+kill_pid $FWD_PID
+kill_pid $UNBOUND_PID
diff --git a/testdata/auth_axfr.tdir/auth_axfr.pre b/testdata/auth_axfr.tdir/auth_axfr.pre
new file mode 100644
index 000000000000..01e9cea1a84a
--- /dev/null
+++ b/testdata/auth_axfr.tdir/auth_axfr.pre
@@ -0,0 +1,31 @@
+# #-- auth_axfr.pre--#
+# source the master var file when it's there
+[ -f ../.tpkg.var.master ] && source ../.tpkg.var.master
+# use .tpkg.var.test for in test variable passing
+[ -f .tpkg.var.test ] && source .tpkg.var.test
+
+. ../common.sh
+get_random_port 2
+UNBOUND_PORT=$RND_PORT
+FWD_PORT=$(($RND_PORT + 1))
+echo "UNBOUND_PORT=$UNBOUND_PORT" >> .tpkg.var.test
+echo "FWD_PORT=$FWD_PORT" >> .tpkg.var.test
+
+# start forwarder
+get_ldns_testns
+$LDNS_TESTNS -p $FWD_PORT auth_axfr.testns >fwd.log 2>&1 &
+FWD_PID=$!
+echo "FWD_PID=$FWD_PID" >> .tpkg.var.test
+
+# make config file
+sed -e 's/@PORT\@/'$UNBOUND_PORT'/' -e 's/@TOPORT\@/'$FWD_PORT'/' < auth_axfr.conf > ub.conf
+# start unbound in the background
+PRE="../.."
+$PRE/unbound -d -c ub.conf >unbound.log 2>&1 &
+UNBOUND_PID=$!
+echo "UNBOUND_PID=$UNBOUND_PID" >> .tpkg.var.test
+
+cat .tpkg.var.test
+wait_ldns_testns_up fwd.log
+wait_unbound_up unbound.log
+
diff --git a/testdata/auth_axfr.tdir/auth_axfr.test b/testdata/auth_axfr.tdir/auth_axfr.test
new file mode 100644
index 000000000000..f9171eea0728
--- /dev/null
+++ b/testdata/auth_axfr.tdir/auth_axfr.test
@@ -0,0 +1,51 @@
+# #-- auth_axfr.test --#
+# source the master var file when it's there
+[ -f ../.tpkg.var.master ] && source ../.tpkg.var.master
+# use .tpkg.var.test for in test variable passing
+[ -f .tpkg.var.test ] && source .tpkg.var.test
+
+PRE="../.."
+# do the test
+echo "> dig www.example.com."
+dig @localhost -p $UNBOUND_PORT www.example.com. | tee outfile
+if grep SERVFAIL outfile; then
+ echo "> try again"
+ dig @localhost -p $UNBOUND_PORT www.example.com. | tee outfile
+fi
+if grep SERVFAIL outfile; then
+ echo "> try again"
+ sleep 1
+ dig @localhost -p $UNBOUND_PORT www.example.com. | tee outfile
+fi
+if grep SERVFAIL outfile; then
+ echo "> try again"
+ sleep 1
+ dig @localhost -p $UNBOUND_PORT www.example.com. | tee outfile
+fi
+if grep SERVFAIL outfile; then
+ echo "> try again"
+ sleep 1
+ dig @localhost -p $UNBOUND_PORT www.example.com. | tee outfile
+fi
+if grep SERVFAIL outfile; then
+ echo "> try again"
+ sleep 10
+ dig @localhost -p $UNBOUND_PORT www.example.com. | tee outfile
+fi
+if grep SERVFAIL outfile; then
+ echo "> try again"
+ sleep 10
+ dig @localhost -p $UNBOUND_PORT www.example.com. | tee outfile
+fi
+echo "> cat logfiles"
+cat fwd.log
+cat unbound.log
+echo "> check answer"
+if grep "1.2.3.4" outfile; then
+ echo "OK"
+else
+ echo "Not OK"
+ exit 1
+fi
+
+exit 0
diff --git a/testdata/auth_axfr.tdir/auth_axfr.testns b/testdata/auth_axfr.tdir/auth_axfr.testns
new file mode 100644
index 000000000000..f1678a1ccc30
--- /dev/null
+++ b/testdata/auth_axfr.tdir/auth_axfr.testns
@@ -0,0 +1,27 @@
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+example.com. IN SOA
+SECTION ANSWER
+example.com. IN SOA ns.example.com. hostmaster.example.com. 1 3600 900 86400 3600
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+example.com. IN AXFR
+SECTION ANSWER
+example.com. IN SOA ns.example.com. hostmaster.example.com. 1 3600 900 86400 3600
+example.com. IN NS ns.example.net.
+EXTRA_PACKET
+REPLY QR AA NOERROR
+SECTION QUESTION
+example.com. IN AXFR
+SECTION ANSWER
+www.example.com. IN A 1.2.3.4
+example.com. IN SOA ns.example.com. hostmaster.example.com. 1 3600 900 86400 3600
+ENTRY_END
diff --git a/testdata/auth_https.tdir/127.0.0.1/example.com.zone b/testdata/auth_https.tdir/127.0.0.1/example.com.zone
new file mode 100644
index 000000000000..695eb1c32bd4
--- /dev/null
+++ b/testdata/auth_https.tdir/127.0.0.1/example.com.zone
@@ -0,0 +1,3 @@
+example.com. IN SOA ns.example.com. hostmaster.example.com. 1 3600 900 86400 3600
+example.com. IN NS ns.example.net.
+www.example.com. IN A 1.2.3.4
diff --git a/testdata/auth_https.tdir/auth_https.conf b/testdata/auth_https.tdir/auth_https.conf
new file mode 100644
index 000000000000..add166f6d582
--- /dev/null
+++ b/testdata/auth_https.tdir/auth_https.conf
@@ -0,0 +1,18 @@
+server:
+ verbosity: 7
+ # num-threads: 1
+ interface: 127.0.0.1
+ port: @PORT@
+ use-syslog: no
+ directory: ""
+ pidfile: "unbound.pid"
+ chroot: ""
+ username: ""
+ do-not-query-localhost: no
+ use-caps-for-id: yes
+auth-zone:
+ name: "example.com"
+ for-upstream: yes
+ for-downstream: yes
+ url: "https://127.0.0.1:@TOPORT@/example.com.zone"
+
diff --git a/testdata/auth_https.tdir/auth_https.dsc b/testdata/auth_https.tdir/auth_https.dsc
new file mode 100644
index 000000000000..bf4341198ec7
--- /dev/null
+++ b/testdata/auth_https.tdir/auth_https.dsc
@@ -0,0 +1,16 @@
+BaseName: auth_https
+Version: 1.0
+Description: Perform https for authority zone
+CreationDate: Tue 13 Jun 09:35:40 CEST 2017
+Maintainer: dr. W.C.A. Wijngaards
+Category:
+Component:
+CmdDepends:
+Depends:
+Help:
+Pre: auth_https.pre
+Post: auth_https.post
+Test: auth_https.test
+AuxFiles:
+Passed:
+Failure:
diff --git a/testdata/auth_https.tdir/auth_https.post b/testdata/auth_https.tdir/auth_https.post
new file mode 100644
index 000000000000..3c1b7ef99e12
--- /dev/null
+++ b/testdata/auth_https.tdir/auth_https.post
@@ -0,0 +1,11 @@
+# #-- auth_https.post --#
+# source the master var file when it's there
+[ -f ../.tpkg.var.master ] && source ../.tpkg.var.master
+# source the test var file when it's there
+[ -f .tpkg.var.test ] && source .tpkg.var.test
+#
+# do your teardown here
+PRE="../.."
+. ../common.sh
+kill_pid $UNBOUND_PID
+kill_pid $PETAL_PID
diff --git a/testdata/auth_https.tdir/auth_https.pre b/testdata/auth_https.tdir/auth_https.pre
new file mode 100644
index 000000000000..e50fd5faa32d
--- /dev/null
+++ b/testdata/auth_https.tdir/auth_https.pre
@@ -0,0 +1,34 @@
+# #-- auth_https.pre--#
+# source the master var file when it's there
+[ -f ../.tpkg.var.master ] && source ../.tpkg.var.master
+# use .tpkg.var.test for in test variable passing
+[ -f .tpkg.var.test ] && source .tpkg.var.test
+
+PRE="../.."
+. ../common.sh
+get_random_port 2
+UNBOUND_PORT=$RND_PORT
+PETAL_PORT=$(($RND_PORT + 1))
+echo "UNBOUND_PORT=$UNBOUND_PORT" >> .tpkg.var.test
+echo "PETAL_PORT=$PETAL_PORT" >> .tpkg.var.test
+
+get_make
+(cd $PRE; $MAKE petal)
+
+# start https daemon
+$PRE/petal -v -a "127.0.0.1" -p $PETAL_PORT >petal.log 2>&1 &
+PETAL_PID=$!
+echo "PETAL_PID=$PETAL_PID" >> .tpkg.var.test
+cat .tpkg.var.test
+wait_petal_up petal.log
+
+# make config file
+sed -e 's/@PORT\@/'$UNBOUND_PORT'/' -e 's/@TOPORT\@/'$PETAL_PORT'/' < auth_https.conf > ub.conf
+# start unbound in the background
+$PRE/unbound -d -c ub.conf >unbound.log 2>&1 &
+UNBOUND_PID=$!
+echo "UNBOUND_PID=$UNBOUND_PID" >> .tpkg.var.test
+
+cat .tpkg.var.test
+wait_unbound_up unbound.log
+
diff --git a/testdata/auth_https.tdir/auth_https.test b/testdata/auth_https.tdir/auth_https.test
new file mode 100644
index 000000000000..cff93544b14a
--- /dev/null
+++ b/testdata/auth_https.tdir/auth_https.test
@@ -0,0 +1,51 @@
+# #-- auth_https.test --#
+# source the master var file when it's there
+[ -f ../.tpkg.var.master ] && source ../.tpkg.var.master
+# use .tpkg.var.test for in test variable passing
+[ -f .tpkg.var.test ] && source .tpkg.var.test
+
+PRE="../.."
+# do the test
+echo "> dig www.example.com."
+dig @localhost -p $UNBOUND_PORT www.example.com. | tee outfile
+if grep SERVFAIL outfile; then
+ echo "> try again"
+ dig @localhost -p $UNBOUND_PORT www.example.com. | tee outfile
+fi
+if grep SERVFAIL outfile; then
+ echo "> try again"
+ sleep 1
+ dig @localhost -p $UNBOUND_PORT www.example.com. | tee outfile
+fi
+if grep SERVFAIL outfile; then
+ echo "> try again"
+ sleep 1
+ dig @localhost -p $UNBOUND_PORT www.example.com. | tee outfile
+fi
+if grep SERVFAIL outfile; then
+ echo "> try again"
+ sleep 1
+ dig @localhost -p $UNBOUND_PORT www.example.com. | tee outfile
+fi
+if grep SERVFAIL outfile; then
+ echo "> try again"
+ sleep 10
+ dig @localhost -p $UNBOUND_PORT www.example.com. | tee outfile
+fi
+if grep SERVFAIL outfile; then
+ echo "> try again"
+ sleep 10
+ dig @localhost -p $UNBOUND_PORT www.example.com. | tee outfile
+fi
+echo "> cat logfiles"
+cat petal.log
+cat unbound.log
+echo "> check answer"
+if grep "1.2.3.4" outfile; then
+ echo "OK"
+else
+ echo "Not OK"
+ exit 1
+fi
+
+exit 0
diff --git a/testdata/auth_https.tdir/petal.key b/testdata/auth_https.tdir/petal.key
new file mode 100644
index 000000000000..6614e498fcd2
--- /dev/null
+++ b/testdata/auth_https.tdir/petal.key
@@ -0,0 +1,21 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIDfQIBAAKBwQC1xQ/Kca6zszZbcCtdOTIH2Uy2gOy/DfabMUU7TmNPm0dVE0NJ
+RuN+Rm304SonpwghfP2/ULZNnuDgpG03/32yI7k/VzG6iA4hiF7tT/KAAWC/+2l1
+QCsawCV2bSrFK0VhcZr7ALqXd8vkDaQ867K029ypjOQtAJ85qdO3mERy7TGtdUcu
+O6hLeVet419YeQ2F8cfNxn63d7bOzNGLPW5xwaCd3UcgD+Ib0k4xfFvbinvPQUeU
+J/i4YDWexFYSL+ECAwEAAQKBwCLXXQl+9O+5AEhSnd1Go1Jh0pSA7eBJOuXQcebG
+Rb7ykp+6C4G2NtDziwwPRNdI6wQQQ0sym18RfyVQHydGr78/nbiIbB3HCn5e92Mh
+mefzW6ow9Kvm2txLzGKA1lvoyRbNm81jnG/eygi3u7Nqd5PNv+4dHj2RkTlmxOeh
+qnDMVP5md8uZPv6lYNnrnIzvLCR5vnPNdVwn89AqzI85IcDZdy0R9ZX4NBbsDgAU
+6ig6uXuRXvSGiyJ/OUXSrnogaQJhAOjvkHUhVZQkPOxO90TNH4j0GdKKtbSWxIdz
+lKfuJeBAEqs0TL+C6vbS81Xw3W1alyDdUBk3rJMOBqW6Ryq5HNL+j5H+Jfsh7fvc
+Yle+5wHGci0P9zCFZCrY8It7n9XFIwJhAMfEi6oJa2G8waPJ1bQhxka82Tf9pnKM
+XCn/1BBOFjVIx5F842cpA+zp5a62GENTGYPQTTRBB/2/ZwnW5aIkrlg54AtmbqBZ
+Oh+2kJdJQD/tfoVmc5soUE2ScTHadK5RKwJhAN4w9kjkXS+MSZjX0kIMsBIBVkhh
+C+aREjJqa9ir7/Ey7RvmLXdYuCxtGLRXp7/R8+rjcK49Tx6O+IRJZe042mfhbq3C
+EhS1Tr86f4xXix9EXlDhs9bSxrOgcAN9Dv/opQJhAK7eBcPaav0rVfYh/8emqQHS
+3fJ9Pu6WnzbEksWTFS2ff9KDGCx9YspIFJ5TF/oXDAaumGZdZrlgirm6O1kr8tGY
+F97i04PZl1+bWAaWQH+1TUNI43m2WFUPE7coG2tb8QJgcddDg9VlXliZqgcETZfJ
+kJmYETxrcSn3ao6v116N8yxhEgUgjkmsCTiFgx36iDVnXwK6PIt+sIu8MC7eYNa3
+berrv/M21K0LRn20IWRxvUobG070weHCAgkko7fTWgr2
+-----END RSA PRIVATE KEY-----
diff --git a/testdata/auth_https.tdir/petal.pem b/testdata/auth_https.tdir/petal.pem
new file mode 100644
index 000000000000..19c8b895ba86
--- /dev/null
+++ b/testdata/auth_https.tdir/petal.pem
@@ -0,0 +1,14 @@
+-----BEGIN CERTIFICATE-----
+MIICFzCCAUACCQDO660L5y5LGDANBgkqhkiG9w0BAQUFADAQMQ4wDAYDVQQDEwVw
+ZXRhbDAeFw0xMDA5MzAxMzQzMDFaFw0zMDA2MTcxMzQzMDFaMBAxDjAMBgNVBAMT
+BXBldGFsMIHfMA0GCSqGSIb3DQEBAQUAA4HNADCByQKBwQC1xQ/Kca6zszZbcCtd
+OTIH2Uy2gOy/DfabMUU7TmNPm0dVE0NJRuN+Rm304SonpwghfP2/ULZNnuDgpG03
+/32yI7k/VzG6iA4hiF7tT/KAAWC/+2l1QCsawCV2bSrFK0VhcZr7ALqXd8vkDaQ8
+67K029ypjOQtAJ85qdO3mERy7TGtdUcuO6hLeVet419YeQ2F8cfNxn63d7bOzNGL
+PW5xwaCd3UcgD+Ib0k4xfFvbinvPQUeUJ/i4YDWexFYSL+ECAwEAATANBgkqhkiG
+9w0BAQUFAAOBwQBBkX9KDP2RXbg+xPmdJ4P6CwvA5x1LZwC++ydVx4NlvT0pWicD
+ZUnXjcWAJlkeOuUBAqFG7WHTrXpUUAjmdqFVq2yFjteUYBdrFz0RDB2jM9feeKYO
+mTgxdZyT9a6humxCxt5VfgT02axLjm/2AqCyFPMbf4PASoJDln01AEuZLZ8Xl2gV
+bYHMnHTGoD1Hu6FNEzRgkMC6XT8X3YjHvzQhpc/qL5wEfEsinQGdX4twsuWbf8xd
+q7miNnkO8vd0maw=
+-----END CERTIFICATE-----
diff --git a/testdata/auth_xfr.rpl b/testdata/auth_xfr.rpl
new file mode 100644
index 000000000000..2dd2b7ae267c
--- /dev/null
+++ b/testdata/auth_xfr.rpl
@@ -0,0 +1,232 @@
+; config options
+server:
+ target-fetch-policy: "0 0 0 0 0"
+
+auth-zone:
+ name: "example.com."
+ ## zonefile (or none).
+ ## zonefile: "example.com.zone"
+ ## master by IP address or hostname
+ ## can list multiple masters, each on one line.
+ ## master:
+ master: 1.2.3.44
+ ## url for http fetch
+ ## url:
+ ## queries from downstream clients get authoritative answers.
+ ## for-downstream: yes
+ for-downstream: yes
+ ## queries are used to fetch authoritative answers from this zone,
+ ## instead of unbound itself sending queries there.
+ ## for-upstream: yes
+ for-upstream: yes
+ ## on failures with for-upstream, fallback to sending queries to
+ ## the authority servers
+ ## fallback-enabled: no
+
+ ## this line generates zonefile: \n"/tmp/xxx.example.com"\n
+ zonefile:
+TEMPFILE_NAME example.com
+ ## this is the inline file /tmp/xxx.example.com
+ ## the tempfiles are deleted when the testrun is over.
+TEMPFILE_CONTENTS example.com
+TEMPFILE_END
+
+stub-zone:
+ name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN Test authority zone with AXFR
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.44
+ENTRY_END
+RANGE_END
+
+; ns.example.net.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.44
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.net. IN NS
+SECTION ANSWER
+example.net. IN NS ns.example.net.
+SECTION ADDITIONAL
+ns.example.net. IN A 1.2.3.44
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.net. IN A
+SECTION ANSWER
+ns.example.net. IN A 1.2.3.44
+SECTION AUTHORITY
+example.net. IN NS ns.example.net.
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.net. IN AAAA
+SECTION AUTHORITY
+example.net. IN NS ns.example.net.
+SECTION ADDITIONAL
+www.example.net. IN A 1.2.3.44
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.net.
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN SOA
+SECTION ANSWER
+; serial, refresh, retry, expire, minimum
+example.com. IN SOA ns.example.com. hostmaster.example.com. 1 3600 900 86400 3600
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+example.com. IN AXFR
+SECTION ANSWER
+example.com. IN SOA ns.example.com. hostmaster.example.com. 1 3600 900 86400 3600
+example.com. IN NS ns.example.net.
+EXTRA_PACKET
+REPLY QR AA NOERROR
+SECTION QUESTION
+example.com. IN AXFR
+SECTION ANSWER
+www.example.com. IN A 1.2.3.4
+example.com. IN SOA ns.example.com. hostmaster.example.com. 1 3600 900 86400 3600
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 20 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR AA RD RA SERVFAIL
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+ENTRY_END
+
+STEP 30 TIME_PASSES ELAPSE 10
+STEP 40 TRAFFIC
+
+STEP 50 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 60 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR AA RD RA NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 1.2.3.4
+ENTRY_END
+
+; the zonefile was updated with new contents
+STEP 70 CHECK_TEMPFILE example.com
+FILE_BEGIN
+example.com. 3600 IN SOA ns.example.com. hostmaster.example.com. 1 3600 900 86400 3600
+example.com. 3600 IN NS ns.example.net.
+www.example.com. 3600 IN A 1.2.3.4
+FILE_END
+
+SCENARIO_END
diff --git a/testdata/auth_xfr_host.rpl b/testdata/auth_xfr_host.rpl
new file mode 100644
index 000000000000..4b3b1879ea33
--- /dev/null
+++ b/testdata/auth_xfr_host.rpl
@@ -0,0 +1,247 @@
+; config options
+server:
+ target-fetch-policy: "0 0 0 0 0"
+
+auth-zone:
+ name: "example.com."
+ ## zonefile (or none).
+ ## zonefile: "example.com.zone"
+ ## master by IP address or hostname
+ ## can list multiple masters, each on one line.
+ ## master:
+ master: ns.example.net.
+ #master: 1.2.3.44
+ ## url for http fetch
+ ## url:
+ ## queries from downstream clients get authoritative answers.
+ ## for-downstream: yes
+ for-downstream: yes
+ ## queries are used to fetch authoritative answers from this zone,
+ ## instead of unbound itself sending queries there.
+ ## for-upstream: yes
+ for-upstream: yes
+ ## on failures with for-upstream, fallback to sending queries to
+ ## the authority servers
+ ## fallback-enabled: no
+
+ ## this line generates zonefile: \n"/tmp/xxx.example.com"\n
+ zonefile:
+TEMPFILE_NAME example.com
+ ## this is the inline file /tmp/xxx.example.com
+ ## the tempfiles are deleted when the testrun is over.
+TEMPFILE_CONTENTS example.com
+TEMPFILE_END
+
+stub-zone:
+ name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN Test authority zone that needs host name lookup
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+ns.example.net. IN A
+SECTION ANSWER
+ns.example.net. IN A 1.2.3.44
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+ns.example.net. IN AAAA
+SECTION ANSWER
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.44
+ENTRY_END
+RANGE_END
+
+; ns.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.44
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.44
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.com. IN A
+SECTION ANSWER
+ns.example.com. IN A 1.2.3.44
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.com. IN AAAA
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+www.example.com. IN A 1.2.3.44
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.com.
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN SOA
+SECTION ANSWER
+; serial, refresh, retry, expire, minimum
+example.com. IN SOA ns.example.com. hostmaster.example.com. 1 3600 900 86400 3600
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+example.com. IN AXFR
+SECTION ANSWER
+example.com. IN SOA ns.example.com. hostmaster.example.com. 1 3600 900 86400 3600
+example.com. IN NS ns.example.com.
+www.example.com. IN A 1.2.3.4
+example.com. IN SOA ns.example.com. hostmaster.example.com. 1 3600 900 86400 3600
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 20 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR AA RD RA SERVFAIL
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+ENTRY_END
+
+STEP 30 TIME_PASSES ELAPSE 10
+STEP 40 TRAFFIC
+
+STEP 50 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 60 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR AA RD RA NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 1.2.3.4
+ENTRY_END
+
+; the zonefile was updated with new contents
+STEP 70 CHECK_TEMPFILE example.com
+FILE_BEGIN
+example.com. 3600 IN SOA ns.example.com. hostmaster.example.com. 1 3600 900 86400 3600
+example.com. 3600 IN NS ns.example.com.
+www.example.com. 3600 IN A 1.2.3.4
+FILE_END
+
+SCENARIO_END
diff --git a/testdata/auth_xfr_ixfr.rpl b/testdata/auth_xfr_ixfr.rpl
new file mode 100644
index 000000000000..91cc8b30365d
--- /dev/null
+++ b/testdata/auth_xfr_ixfr.rpl
@@ -0,0 +1,276 @@
+; config options
+server:
+ target-fetch-policy: "0 0 0 0 0"
+
+auth-zone:
+ name: "example.com."
+ ## zonefile (or none).
+ ## zonefile: "example.com.zone"
+ ## master by IP address or hostname
+ ## can list multiple masters, each on one line.
+ ## master:
+ master: 1.2.3.44
+ ## url for http fetch
+ ## url:
+ ## queries from downstream clients get authoritative answers.
+ ## for-downstream: yes
+ for-downstream: yes
+ ## queries are used to fetch authoritative answers from this zone,
+ ## instead of unbound itself sending queries there.
+ ## for-upstream: yes
+ for-upstream: yes
+ ## on failures with for-upstream, fallback to sending queries to
+ ## the authority servers
+ ## fallback-enabled: no
+
+ ## this line generates zonefile: \n"/tmp/xxx.example.com"\n
+ zonefile:
+TEMPFILE_NAME example.com
+ ## this is the inline file /tmp/xxx.example.com
+ ## the tempfiles are deleted when the testrun is over.
+TEMPFILE_CONTENTS example.com
+example.com. 3600 IN SOA ns.example.com. hostmaster.example.com. 1 3600 900 86400 3600
+example.com. 3600 IN NS ns.example.net.
+www.example.com. 3600 IN A 1.2.3.4
+mail.example.com. 3600 IN A 1.2.3.4
+mail.example.com. 3600 IN A 1.2.3.5
+mail.example.com. 3600 IN A 1.2.3.6
+mail.example.com. 3600 IN A 1.2.3.7
+zup.example.com. 3600 IN A 1.2.3.4
+yyy.example.com. 3600 IN A 1.2.3.4
+yyy.example.com. 3600 IN AAAA ::5
+r1.example.com. 3600 IN A 1.2.3.4
+r1.example.com. 3600 IN RRSIG A 8 3 10200 20170612005010 20170515005010 42393 nlnetlabs.nl. NhEDrHkuIgHkjWhDRVsGOIJWZpSs+QdduilWFe5d+/ZhOheLJbaTYD5w6+ZZ3yPh1tNud+jlg+GyiOSVapLEO31swDCIarL1UfRjRSpxxDCHGag5Zu+S4hF+KURxO3cJk8jLBELMQyRuMRHoKrw/wsiLGVu1YpAyAPPMcjFBNbk=
+r2.example.com. 3600 IN A 1.2.3.4
+r2.example.com. 3600 IN RRSIG A 8 3 10200 20170612005010 20170515005010 42393 nlnetlabs.nl. NhEDrHkuIgHkjWhDRVsGOIJWZpSs+QdduilWFe5d+/ZhOheLJbaTYD5w6+ZZ3yPh1tNud+jlg+GyiOSVapLEO31swDCIarL1UfRjRSpxxDCHGag5Zu+S4hF+KURxO3cJk8jLBELMQyRuMRHoKrw/wsiLGVu1YpAyAPPMcjFBNbk=
+r2.example.com. 3600 IN RRSIG AAAA 8 3 10200 20170612005010 20170515005010 42393 nlnetlabs.nl. NhEDrHkuIgHkjWhDRVsGOIJWZpSs+QdduilWFe5d+/ZhOheLJbaTYD5w6+ZZ3yPh1tNud+jlg+GyiOSVapLEO31swDCIarL1UfRjRSpxxDCHGag5Zu+S4hF+KURxO3cJk8jLBELMQyRuMRHoKrw/wsiLGVu1YpAyAPPMcjFBNbk=
+r3.example.com. 3600 IN A 1.2.3.4
+r3.example.com. 3600 IN RRSIG A 8 3 10200 20170612005010 20170515005010 42393 nlnetlabs.nl. NhEDrHkuIgHkjWhDRVsGOIJWZpSs+QdduilWFe5d+/ZhOheLJbaTYD5w6+ZZ3yPh1tNud+jlg+GyiOSVapLEO31swDCIarL1UfRjRSpxxDCHGag5Zu+S4hF+KURxO3cJk8jLBELMQyRuMRHoKrw/wsiLGVu1YpAyAPPMcjFBNbk=
+r3.example.com. 3600 IN RRSIG A 8 3 10200 20170612005010 20170515005010 12345 nlnetlabs.nl. NhEDrHkuIgHkjWhDRVsGOIJWZpSs+QdduilWFe5d+/ZhOheLJbaTYD5w6+ZZ3yPh1tNud+jlg+GyiOSVapLEO31swDCIarL1UfRjRSpxxDCHGag5Zu+S4hF+KURxO3cJk8jLBELMQyRuMRHoKrw/wsiLGVu1YpAyAPPMcjFBNbk=
+add.example.com. 3600 IN A 1.2.3.4
+TEMPFILE_END
+
+stub-zone:
+ name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN Test authority zone with IXFR
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.44
+ENTRY_END
+RANGE_END
+
+; ns.example.net.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.44
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.net. IN NS
+SECTION ANSWER
+example.net. IN NS ns.example.net.
+SECTION ADDITIONAL
+ns.example.net. IN A 1.2.3.44
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.net. IN A
+SECTION ANSWER
+ns.example.net. IN A 1.2.3.44
+SECTION AUTHORITY
+example.net. IN NS ns.example.net.
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.net. IN AAAA
+SECTION AUTHORITY
+example.net. IN NS ns.example.net.
+SECTION ADDITIONAL
+www.example.net. IN A 1.2.3.44
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.net.
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN SOA
+SECTION ANSWER
+; serial, refresh, retry, expire, minimum
+example.com. 3600 IN SOA ns.example.com. hostmaster.example.com. 2 3600 900 86400 3600
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+example.com. IN IXFR
+SECTION ANSWER
+example.com. IN SOA ns.example.com. hostmaster.example.com. 2 3600 900 86400 3600
+example.com. IN SOA ns.example.com. hostmaster.example.com. 1 3600 900 86400 3600
+www.example.com. IN A 1.2.3.4
+mail.example.com. 3600 IN A 1.2.3.6
+zup.example.com. 3600 IN A 1.2.3.4
+yyy.example.com. 3600 IN AAAA ::5
+r1.example.com. 3600 IN A 1.2.3.4
+r2.example.com. 3600 IN A 1.2.3.4
+r3.example.com. 3600 IN RRSIG A 8 3 10200 20170612005010 20170515005010 12345 nlnetlabs.nl. NhEDrHkuIgHkjWhDRVsGOIJWZpSs+QdduilWFe5d+/ZhOheLJbaTYD5w6+ZZ3yPh1tNud+jlg+GyiOSVapLEO31swDCIarL1UfRjRSpxxDCHGag5Zu+S4hF+KURxO3cJk8jLBELMQyRuMRHoKrw/wsiLGVu1YpAyAPPMcjFBNbk=
+example.com. IN SOA ns.example.com. hostmaster.example.com. 2 3600 900 86400 3600
+EXTRA_PACKET
+REPLY QR AA NOERROR
+SECTION QUESTION
+example.com. IN IXFR
+SECTION ANSWER
+www.example.com. IN A 1.2.3.5
+mail.example.com. 3600 IN A 1.2.3.8
+mail.example.com. IN AAAA ::5
+add2.example.com. 3600 IN A 1.2.3.4
+example.com. IN SOA ns.example.com. hostmaster.example.com. 2 3600 900 86400 3600
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 20 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR AA RD RA NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 1.2.3.4
+ENTRY_END
+
+STEP 30 TIME_PASSES ELAPSE 3600
+STEP 40 TRAFFIC
+
+STEP 50 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 60 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR AA RD RA NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 1.2.3.5
+ENTRY_END
+
+; the zonefile was updated with new contents
+STEP 70 CHECK_TEMPFILE example.com
+FILE_BEGIN
+example.com. 3600 IN SOA ns.example.com. hostmaster.example.com. 2 3600 900 86400 3600
+example.com. 3600 IN NS ns.example.net.
+add.example.com. 3600 IN A 1.2.3.4
+add2.example.com. 3600 IN A 1.2.3.4
+mail.example.com. 3600 IN A 1.2.3.4
+mail.example.com. 3600 IN A 1.2.3.5
+mail.example.com. 3600 IN A 1.2.3.7
+mail.example.com. 3600 IN A 1.2.3.8
+mail.example.com. 3600 IN AAAA ::5
+r1.example.com. 3600 IN RRSIG A 8 3 10200 20170612005010 20170515005010 42393 nlnetlabs.nl. NhEDrHkuIgHkjWhDRVsGOIJWZpSs+QdduilWFe5d+/ZhOheLJbaTYD5w6+ZZ3yPh1tNud+jlg+GyiOSVapLEO31swDCIarL1UfRjRSpxxDCHGag5Zu+S4hF+KURxO3cJk8jLBELMQyRuMRHoKrw/wsiLGVu1YpAyAPPMcjFBNbk=
+r2.example.com. 3600 IN RRSIG AAAA 8 3 10200 20170612005010 20170515005010 42393 nlnetlabs.nl. NhEDrHkuIgHkjWhDRVsGOIJWZpSs+QdduilWFe5d+/ZhOheLJbaTYD5w6+ZZ3yPh1tNud+jlg+GyiOSVapLEO31swDCIarL1UfRjRSpxxDCHGag5Zu+S4hF+KURxO3cJk8jLBELMQyRuMRHoKrw/wsiLGVu1YpAyAPPMcjFBNbk=
+r2.example.com. 3600 IN RRSIG A 8 3 10200 20170612005010 20170515005010 42393 nlnetlabs.nl. NhEDrHkuIgHkjWhDRVsGOIJWZpSs+QdduilWFe5d+/ZhOheLJbaTYD5w6+ZZ3yPh1tNud+jlg+GyiOSVapLEO31swDCIarL1UfRjRSpxxDCHGag5Zu+S4hF+KURxO3cJk8jLBELMQyRuMRHoKrw/wsiLGVu1YpAyAPPMcjFBNbk=
+r3.example.com. 3600 IN A 1.2.3.4
+r3.example.com. 3600 IN RRSIG A 8 3 10200 20170612005010 20170515005010 42393 nlnetlabs.nl. NhEDrHkuIgHkjWhDRVsGOIJWZpSs+QdduilWFe5d+/ZhOheLJbaTYD5w6+ZZ3yPh1tNud+jlg+GyiOSVapLEO31swDCIarL1UfRjRSpxxDCHGag5Zu+S4hF+KURxO3cJk8jLBELMQyRuMRHoKrw/wsiLGVu1YpAyAPPMcjFBNbk=
+www.example.com. 3600 IN A 1.2.3.5
+yyy.example.com. 3600 IN A 1.2.3.4
+FILE_END
+
+SCENARIO_END
diff --git a/testdata/auth_xfr_ixfrisaxfr.rpl b/testdata/auth_xfr_ixfrisaxfr.rpl
new file mode 100644
index 000000000000..ac6d4db766ad
--- /dev/null
+++ b/testdata/auth_xfr_ixfrisaxfr.rpl
@@ -0,0 +1,235 @@
+; config options
+server:
+ target-fetch-policy: "0 0 0 0 0"
+
+auth-zone:
+ name: "example.com."
+ ## zonefile (or none).
+ ## zonefile: "example.com.zone"
+ ## master by IP address or hostname
+ ## can list multiple masters, each on one line.
+ ## master:
+ master: 1.2.3.44
+ ## url for http fetch
+ ## url:
+ ## queries from downstream clients get authoritative answers.
+ ## for-downstream: yes
+ for-downstream: yes
+ ## queries are used to fetch authoritative answers from this zone,
+ ## instead of unbound itself sending queries there.
+ ## for-upstream: yes
+ for-upstream: yes
+ ## on failures with for-upstream, fallback to sending queries to
+ ## the authority servers
+ ## fallback-enabled: no
+
+ ## this line generates zonefile: \n"/tmp/xxx.example.com"\n
+ zonefile:
+TEMPFILE_NAME example.com
+ ## this is the inline file /tmp/xxx.example.com
+ ## the tempfiles are deleted when the testrun is over.
+TEMPFILE_CONTENTS example.com
+example.com. 3600 IN SOA ns.example.com. hostmaster.example.com. 1 3600 900 86400 3600
+example.com. 3600 IN NS ns.example.net.
+www.example.com. 3600 IN A 1.2.3.4
+mail.example.com. 3600 IN A 1.2.3.4
+mail.example.com. 3600 IN A 1.2.3.5
+mail.example.com. 3600 IN A 1.2.3.6
+mail.example.com. 3600 IN A 1.2.3.7
+TEMPFILE_END
+
+stub-zone:
+ name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN Test authority zone with IXFR reply really is an AXFR
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.44
+ENTRY_END
+RANGE_END
+
+; ns.example.net.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.44
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.net. IN NS
+SECTION ANSWER
+example.net. IN NS ns.example.net.
+SECTION ADDITIONAL
+ns.example.net. IN A 1.2.3.44
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.net. IN A
+SECTION ANSWER
+ns.example.net. IN A 1.2.3.44
+SECTION AUTHORITY
+example.net. IN NS ns.example.net.
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.net. IN AAAA
+SECTION AUTHORITY
+example.net. IN NS ns.example.net.
+SECTION ADDITIONAL
+www.example.net. IN A 1.2.3.44
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.net.
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN SOA
+SECTION ANSWER
+; serial, refresh, retry, expire, minimum
+example.com. 3600 IN SOA ns.example.com. hostmaster.example.com. 2 3600 900 86400 3600
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+example.com. IN IXFR
+SECTION ANSWER
+example.com. IN SOA ns.example.com. hostmaster.example.com. 2 3600 900 86400 3600
+example.com. IN NS ns.example.net.
+www.example.com. IN A 1.2.3.6
+example.com. IN SOA ns.example.com. hostmaster.example.com. 2 3600 900 86400 3600
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 20 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR AA RD RA NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 1.2.3.4
+ENTRY_END
+
+STEP 30 TIME_PASSES ELAPSE 3600
+STEP 40 TRAFFIC
+
+STEP 50 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 60 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR AA RD RA NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 1.2.3.6
+ENTRY_END
+
+; the zonefile was updated with new contents
+STEP 70 CHECK_TEMPFILE example.com
+FILE_BEGIN
+example.com. 3600 IN SOA ns.example.com. hostmaster.example.com. 2 3600 900 86400 3600
+example.com. 3600 IN NS ns.example.net.
+www.example.com. 3600 IN A 1.2.3.6
+FILE_END
+
+SCENARIO_END
diff --git a/testdata/auth_xfr_ixfrmismatch.rpl b/testdata/auth_xfr_ixfrmismatch.rpl
new file mode 100644
index 000000000000..f12e766d0ece
--- /dev/null
+++ b/testdata/auth_xfr_ixfrmismatch.rpl
@@ -0,0 +1,266 @@
+; config options
+server:
+ target-fetch-policy: "0 0 0 0 0"
+
+auth-zone:
+ name: "example.com."
+ ## zonefile (or none).
+ ## zonefile: "example.com.zone"
+ ## master by IP address or hostname
+ ## can list multiple masters, each on one line.
+ ## master:
+ master: 1.2.3.44
+ ## url for http fetch
+ ## url:
+ ## queries from downstream clients get authoritative answers.
+ ## for-downstream: yes
+ for-downstream: yes
+ ## queries are used to fetch authoritative answers from this zone,
+ ## instead of unbound itself sending queries there.
+ ## for-upstream: yes
+ for-upstream: yes
+ ## on failures with for-upstream, fallback to sending queries to
+ ## the authority servers
+ ## fallback-enabled: no
+
+ ## this line generates zonefile: \n"/tmp/xxx.example.com"\n
+ zonefile:
+TEMPFILE_NAME example.com
+ ## this is the inline file /tmp/xxx.example.com
+ ## the tempfiles are deleted when the testrun is over.
+TEMPFILE_CONTENTS example.com
+example.com. 3600 IN SOA ns.example.com. hostmaster.example.com. 1 3600 900 86400 3600
+example.com. 3600 IN NS ns.example.net.
+www.example.com. 3600 IN A 1.2.3.4
+mail.example.com. 3600 IN A 1.2.3.4
+mail.example.com. 3600 IN A 1.2.3.5
+mail.example.com. 3600 IN A 1.2.3.6
+mail.example.com. 3600 IN A 1.2.3.7
+TEMPFILE_END
+
+stub-zone:
+ name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN Test authority zone with IXFR that has mismatched data
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.44
+ENTRY_END
+RANGE_END
+
+; ns.example.net.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.44
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.net. IN NS
+SECTION ANSWER
+example.net. IN NS ns.example.net.
+SECTION ADDITIONAL
+ns.example.net. IN A 1.2.3.44
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.net. IN A
+SECTION ANSWER
+ns.example.net. IN A 1.2.3.44
+SECTION AUTHORITY
+example.net. IN NS ns.example.net.
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.net. IN AAAA
+SECTION AUTHORITY
+example.net. IN NS ns.example.net.
+SECTION ADDITIONAL
+www.example.net. IN A 1.2.3.44
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.net.
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN SOA
+SECTION ANSWER
+; serial, refresh, retry, expire, minimum
+example.com. 3600 IN SOA ns.example.com. hostmaster.example.com. 2 3600 900 86400 3600
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+example.com. IN IXFR
+SECTION ANSWER
+example.com. IN SOA ns.example.com. hostmaster.example.com. 2 3600 900 86400 3600
+example.com. IN SOA ns.example.com. hostmaster.example.com. 1 3600 900 86400 3600
+www.example.com. IN A 1.2.3.4
+mail.example.com. 3600 IN A 1.2.3.6
+; this is the delete of the nonexistant entry
+nonexist.example.com. 3600 IN A 1.2.3.4
+example.com. IN SOA ns.example.com. hostmaster.example.com. 2 3600 900 86400 3600
+EXTRA_PACKET
+REPLY QR AA NOERROR
+SECTION QUESTION
+example.com. IN IXFR
+SECTION ANSWER
+www.example.com. IN A 1.2.3.5
+mail.example.com. 3600 IN A 1.2.3.8
+mail.example.com. IN AAAA ::5
+add2.example.com. 3600 IN A 1.2.3.4
+example.com. IN SOA ns.example.com. hostmaster.example.com. 2 3600 900 86400 3600
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+example.com. IN AXFR
+SECTION ANSWER
+example.com. IN SOA ns.example.com. hostmaster.example.com. 2 3600 900 86400 3600
+example.com. IN NS ns.example.net.
+EXTRA_PACKET
+REPLY QR AA NOERROR
+SECTION QUESTION
+example.com. IN AXFR
+SECTION ANSWER
+www.example.com. IN A 1.2.3.6
+example.com. IN SOA ns.example.com. hostmaster.example.com. 2 3600 900 86400 3600
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 20 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR AA RD RA NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 1.2.3.4
+ENTRY_END
+
+STEP 30 TIME_PASSES ELAPSE 3600
+STEP 40 TRAFFIC
+
+STEP 50 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 60 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR AA RD RA NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 1.2.3.6
+ENTRY_END
+
+; the zonefile was updated with new contents
+STEP 70 CHECK_TEMPFILE example.com
+FILE_BEGIN
+example.com. 3600 IN SOA ns.example.com. hostmaster.example.com. 2 3600 900 86400 3600
+example.com. 3600 IN NS ns.example.net.
+www.example.com. 3600 IN A 1.2.3.6
+FILE_END
+
+SCENARIO_END
diff --git a/testdata/auth_xfr_ixfrnotimpl.rpl b/testdata/auth_xfr_ixfrnotimpl.rpl
new file mode 100644
index 000000000000..94f03eb93e22
--- /dev/null
+++ b/testdata/auth_xfr_ixfrnotimpl.rpl
@@ -0,0 +1,249 @@
+; config options
+server:
+ target-fetch-policy: "0 0 0 0 0"
+
+auth-zone:
+ name: "example.com."
+ ## zonefile (or none).
+ ## zonefile: "example.com.zone"
+ ## master by IP address or hostname
+ ## can list multiple masters, each on one line.
+ ## master:
+ master: 1.2.3.44
+ ## url for http fetch
+ ## url:
+ ## queries from downstream clients get authoritative answers.
+ ## for-downstream: yes
+ for-downstream: yes
+ ## queries are used to fetch authoritative answers from this zone,
+ ## instead of unbound itself sending queries there.
+ ## for-upstream: yes
+ for-upstream: yes
+ ## on failures with for-upstream, fallback to sending queries to
+ ## the authority servers
+ ## fallback-enabled: no
+
+ ## this line generates zonefile: \n"/tmp/xxx.example.com"\n
+ zonefile:
+TEMPFILE_NAME example.com
+ ## this is the inline file /tmp/xxx.example.com
+ ## the tempfiles are deleted when the testrun is over.
+TEMPFILE_CONTENTS example.com
+example.com. 3600 IN SOA ns.example.com. hostmaster.example.com. 1 3600 900 86400 3600
+example.com. 3600 IN NS ns.example.net.
+www.example.com. 3600 IN A 1.2.3.4
+mail.example.com. 3600 IN A 1.2.3.4
+mail.example.com. 3600 IN A 1.2.3.5
+mail.example.com. 3600 IN A 1.2.3.6
+mail.example.com. 3600 IN A 1.2.3.7
+TEMPFILE_END
+
+stub-zone:
+ name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN Test authority zone with IXFR NOTIMPL fallback
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.44
+ENTRY_END
+RANGE_END
+
+; ns.example.net.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.44
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.net. IN NS
+SECTION ANSWER
+example.net. IN NS ns.example.net.
+SECTION ADDITIONAL
+ns.example.net. IN A 1.2.3.44
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.net. IN A
+SECTION ANSWER
+ns.example.net. IN A 1.2.3.44
+SECTION AUTHORITY
+example.net. IN NS ns.example.net.
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.net. IN AAAA
+SECTION AUTHORITY
+example.net. IN NS ns.example.net.
+SECTION ADDITIONAL
+www.example.net. IN A 1.2.3.44
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.net.
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN SOA
+SECTION ANSWER
+; serial, refresh, retry, expire, minimum
+example.com. 3600 IN SOA ns.example.com. hostmaster.example.com. 2 3600 900 86400 3600
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOTIMPL
+SECTION QUESTION
+example.com. IN IXFR
+SECTION ANSWER
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+example.com. IN AXFR
+SECTION ANSWER
+example.com. IN SOA ns.example.com. hostmaster.example.com. 2 3600 900 86400 3600
+example.com. IN NS ns.example.net.
+EXTRA_PACKET
+REPLY QR AA NOERROR
+SECTION QUESTION
+example.com. IN AXFR
+SECTION ANSWER
+www.example.com. IN A 1.2.3.6
+example.com. IN SOA ns.example.com. hostmaster.example.com. 2 3600 900 86400 3600
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 20 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR AA RD RA NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 1.2.3.4
+ENTRY_END
+
+STEP 30 TIME_PASSES ELAPSE 3600
+STEP 40 TRAFFIC
+
+STEP 50 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 60 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR AA RD RA NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 1.2.3.6
+ENTRY_END
+
+; the zonefile was updated with new contents
+STEP 70 CHECK_TEMPFILE example.com
+FILE_BEGIN
+example.com. 3600 IN SOA ns.example.com. hostmaster.example.com. 2 3600 900 86400 3600
+example.com. 3600 IN NS ns.example.net.
+www.example.com. 3600 IN A 1.2.3.6
+FILE_END
+
+SCENARIO_END
diff --git a/testdata/auth_xfr_probesoa.rpl b/testdata/auth_xfr_probesoa.rpl
new file mode 100644
index 000000000000..865ac87de096
--- /dev/null
+++ b/testdata/auth_xfr_probesoa.rpl
@@ -0,0 +1,219 @@
+; config options
+server:
+ target-fetch-policy: "0 0 0 0 0"
+
+auth-zone:
+ name: "example.com."
+ ## zonefile (or none).
+ ## zonefile: "example.com.zone"
+ ## master by IP address or hostname
+ ## can list multiple masters, each on one line.
+ ## master:
+ master: 1.2.3.44
+ ## url for http fetch
+ ## url:
+ ## queries from downstream clients get authoritative answers.
+ ## for-downstream: yes
+ for-downstream: yes
+ ## queries are used to fetch authoritative answers from this zone,
+ ## instead of unbound itself sending queries there.
+ ## for-upstream: yes
+ for-upstream: yes
+ ## on failures with for-upstream, fallback to sending queries to
+ ## the authority servers
+ ## fallback-enabled: no
+
+ ## this line generates zonefile: \n"/tmp/xxx.example.com"\n
+ zonefile:
+TEMPFILE_NAME example.com
+ ## this is the inline file /tmp/xxx.example.com
+ ## the tempfiles are deleted when the testrun is over.
+TEMPFILE_CONTENTS example.com
+example.com. 3600 IN SOA ns.example.com. hostmaster.example.com. 1 3600 900 86400 3600
+example.com. 3600 IN NS ns.example.net.
+www.example.com. 3600 IN A 1.2.3.4
+TEMPFILE_END
+
+stub-zone:
+ name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN Test authority zone with probe of SOA
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.44
+ENTRY_END
+RANGE_END
+
+; ns.example.net.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.44
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.net. IN NS
+SECTION ANSWER
+example.net. IN NS ns.example.net.
+SECTION ADDITIONAL
+ns.example.net. IN A 1.2.3.44
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.net. IN A
+SECTION ANSWER
+ns.example.net. IN A 1.2.3.44
+SECTION AUTHORITY
+example.net. IN NS ns.example.net.
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.net. IN AAAA
+SECTION AUTHORITY
+example.net. IN NS ns.example.net.
+SECTION ADDITIONAL
+www.example.net. IN A 1.2.3.44
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.net.
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN SOA
+SECTION ANSWER
+; serial, refresh, retry, expire, minimum
+example.com. IN SOA ns.example.com. hostmaster.example.com. 1 3600 900 86400 3600
+ENTRY_END
+
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 20 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR AA RD RA NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 1.2.3.4
+ENTRY_END
+
+STEP 30 TIME_PASSES ELAPSE 3600
+STEP 40 TRAFFIC
+
+STEP 50 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 60 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR AA RD RA NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 1.2.3.4
+ENTRY_END
+
+; the zonefile was updated with new contents
+STEP 70 CHECK_TEMPFILE example.com
+FILE_BEGIN
+example.com. 3600 IN SOA ns.example.com. hostmaster.example.com. 1 3600 900 86400 3600
+example.com. 3600 IN NS ns.example.net.
+www.example.com. 3600 IN A 1.2.3.4
+FILE_END
+
+SCENARIO_END
diff --git a/testdata/auth_zonefile.rpl b/testdata/auth_zonefile.rpl
new file mode 100644
index 000000000000..23c4efc60261
--- /dev/null
+++ b/testdata/auth_zonefile.rpl
@@ -0,0 +1,189 @@
+; config options
+server:
+ target-fetch-policy: "0 0 0 0 0"
+
+auth-zone:
+ name: "example.com."
+ ## zonefile (or none).
+ ## zonefile: "example.com.zone"
+ ## master by IP address or hostname
+ ## can list multiple masters, each on one line.
+ ## master:
+ ## url for http fetch
+ ## url:
+ ## queries from downstream clients get authoritative answers.
+ ## for-downstream: yes
+ for-downstream: no
+ ## queries are used to fetch authoritative answers from this zone,
+ ## instead of unbound itself sending queries there.
+ ## for-upstream: yes
+ for-upstream: yes
+ ## on failures with for-upstream, fallback to sending queries to
+ ## the authority servers
+ ## fallback-enabled: no
+
+ ## this line generates zonefile: \n"/tmp/xxx.example.com"\n
+ zonefile:
+TEMPFILE_NAME example.com
+ ## this is the inline file /tmp/xxx.example.com
+ ## the tempfiles are deleted when the testrun is over.
+TEMPFILE_CONTENTS example.com
+$ORIGIN com.
+example 3600 IN SOA dns.example.de. hostmaster.dns.example.de. (
+ 1379078166 28800 7200 604800 7200 )
+ 3600 IN NS ns1.example.com.
+ 3600 IN NS ns2.example.com.
+$ORIGIN example.com.
+www 3600 IN A 1.2.3.4
+mail 3600 IN A 1.2.3.5
+ 3600 IN AAAA ::5
+ns1 3600 IN A 1.2.3.4
+ns2 3600 IN AAAA ::2
+$INCLUDE_TEMPFILE example.inc
+TEMPFILE_END
+TEMPFILE_CONTENTS example.inc
+other 7200 IN A 1.2.3.6
+TEMPFILE_END
+
+stub-zone:
+ name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN Test authority zone with zonefile
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.44
+ENTRY_END
+RANGE_END
+
+; ns.example.net.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.44
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.net. IN NS
+SECTION ANSWER
+example.net. IN NS ns.example.net.
+SECTION ADDITIONAL
+ns.example.net. IN A 1.2.3.44
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.net. IN A
+SECTION ANSWER
+ns.example.net. IN A 1.2.3.44
+SECTION AUTHORITY
+example.net. IN NS ns.example.net.
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.net. IN AAAA
+SECTION AUTHORITY
+example.net. IN NS ns.example.net.
+SECTION ADDITIONAL
+www.example.net. IN A 1.2.3.44
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.net.
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 20 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 1.2.3.4
+ENTRY_END
+
+SCENARIO_END
diff --git a/testdata/auth_zonefile_dnssec.rpl b/testdata/auth_zonefile_dnssec.rpl
new file mode 100644
index 000000000000..eb264ee8bbb2
--- /dev/null
+++ b/testdata/auth_zonefile_dnssec.rpl
@@ -0,0 +1,194 @@
+; config options
+server:
+ trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b"
+ val-override-date: "20070916134226"
+ target-fetch-policy: "0 0 0 0 0"
+ fake-sha1: yes
+ trust-anchor-signaling: no
+
+auth-zone:
+ name: "example.com."
+ ## zonefile (or none).
+ ## zonefile: "example.com.zone"
+ ## master by IP address or hostname
+ ## can list multiple masters, each on one line.
+ ## master:
+ ## url for http fetch
+ ## url:
+ ## queries from downstream clients get authoritative answers.
+ ## for-downstream: yes
+ for-downstream: no
+ ## queries are used to fetch authoritative answers from this zone,
+ ## instead of unbound itself sending queries there.
+ ## for-upstream: yes
+ for-upstream: yes
+ ## on failures with for-upstream, fallback to sending queries to
+ ## the authority servers
+ ## fallback-enabled: no
+
+ ## this line generates zonefile: \n"/tmp/xxx.example.com"\n
+ zonefile:
+TEMPFILE_NAME example.com
+ ## this is the inline file /tmp/xxx.example.com
+ ## the tempfiles are deleted when the testrun is over.
+TEMPFILE_CONTENTS example.com
+$ORIGIN example.com.
+example 3600 IN SOA dns.example.de. hostmaster.dns.example.de. (
+ 1379078166 28800 7200 604800 7200 )
+ 3600 IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854}
+example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b}
+example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134802 20070829134802 2854 example.com. MCwCFG1yhRNtTEa3Eno2zhVVuy2EJX3wAhQeLyUp6+UXcpC5qGNu9tkrTEgPUg== ;{id = 2854}
+
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854}
+
+www.example.com. IN A 10.20.30.40
+www.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFC99iE9K5y2WNgI0gFvBWaTi9wm6AhUAoUqOpDtG5Zct+Qr9F3mSdnbc6V4= ;{id = 2854}
+
+TEMPFILE_END
+
+stub-zone:
+ name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN Test authority zone with zonefile and dnssec
+; the zone file has signatures, used upstream, unbound validates the reply.
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.44
+ENTRY_END
+RANGE_END
+
+; ns.example.net.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.44
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.net. IN NS
+SECTION ANSWER
+example.net. IN NS ns.example.net.
+SECTION ADDITIONAL
+ns.example.net. IN A 1.2.3.44
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.net. IN A
+SECTION ANSWER
+ns.example.net. IN A 1.2.3.44
+SECTION AUTHORITY
+example.net. IN NS ns.example.net.
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.net. IN AAAA
+SECTION AUTHORITY
+example.net. IN NS ns.example.net.
+SECTION ADDITIONAL
+www.example.net. IN A 1.2.3.44
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.net.
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 20 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD DO RA AD NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+www.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFC99iE9K5y2WNgI0gFvBWaTi9wm6AhUAoUqOpDtG5Zct+Qr9F3mSdnbc6V4= ;{id = 2854}
+ENTRY_END
+
+SCENARIO_END
diff --git a/testdata/auth_zonefile_dnssec_fail.rpl b/testdata/auth_zonefile_dnssec_fail.rpl
new file mode 100644
index 000000000000..49da19993a63
--- /dev/null
+++ b/testdata/auth_zonefile_dnssec_fail.rpl
@@ -0,0 +1,202 @@
+; config options
+server:
+ trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b"
+ val-override-date: "20070916134226"
+ target-fetch-policy: "0 0 0 0 0"
+ fake-sha1: yes
+ trust-anchor-signaling: no
+
+auth-zone:
+ name: "example.com."
+ ## zonefile (or none).
+ ## zonefile: "example.com.zone"
+ ## master by IP address or hostname
+ ## can list multiple masters, each on one line.
+ ## master:
+ ## url for http fetch
+ ## url:
+ ## queries from downstream clients get authoritative answers.
+ ## for-downstream: yes
+ for-downstream: no
+ ## queries are used to fetch authoritative answers from this zone,
+ ## instead of unbound itself sending queries there.
+ ## for-upstream: yes
+ for-upstream: yes
+ ## on failures with for-upstream, fallback to sending queries to
+ ## the authority servers
+ ## fallback-enabled: no
+ fallback-enabled: yes
+
+ ## this line generates zonefile: \n"/tmp/xxx.example.com"\n
+ zonefile:
+TEMPFILE_NAME example.com
+ ## this is the inline file /tmp/xxx.example.com
+ ## the tempfiles are deleted when the testrun is over.
+TEMPFILE_CONTENTS example.com
+$ORIGIN example.com.
+example 3600 IN SOA dns.example.de. hostmaster.dns.example.de. (
+ 1379078166 28800 7200 604800 7200 )
+ 3600 IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854}
+example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b}
+example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134802 20070829134802 2854 example.com. MCwCFG1yhRNtTEa3Eno2zhVVuy2EJX3wAhQeLyUp6+UXcpC5qGNu9tkrTEgPUg== ;{id = 2854}
+
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854}
+
+; this RR is edited to create the failure
+;www.example.com. IN A 10.20.30.40
+www.example.com. IN A 127.0.0.1
+www.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFC99iE9K5y2WNgI0gFvBWaTi9wm6AhUAoUqOpDtG5Zct+Qr9F3mSdnbc6V4= ;{id = 2854}
+
+TEMPFILE_END
+
+stub-zone:
+ name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN Test authority zone with zonefile and dnssec failure
+; the zone file has signatures, used upstream, unbound validates the reply.
+; but that fails and now it tries again, with failover to internet hosted
+; (correct) contents.
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.44
+ENTRY_END
+RANGE_END
+
+; ns.example.net.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.44
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.net. IN NS
+SECTION ANSWER
+example.net. IN NS ns.example.net.
+SECTION ADDITIONAL
+ns.example.net. IN A 1.2.3.44
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.net. IN A
+SECTION ANSWER
+ns.example.net. IN A 1.2.3.44
+SECTION AUTHORITY
+example.net. IN NS ns.example.net.
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.net. IN AAAA
+SECTION AUTHORITY
+example.net. IN NS ns.example.net.
+SECTION ADDITIONAL
+www.example.net. IN A 1.2.3.44
+ENTRY_END
+
+; response to DNSKEY priming query
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN DNSKEY
+SECTION ANSWER
+example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b}
+example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134802 20070829134802 2854 example.com. MCwCFG1yhRNtTEa3Eno2zhVVuy2EJX3wAhQeLyUp6+UXcpC5qGNu9tkrTEgPUg== ;{id = 2854}
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+www.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFC99iE9K5y2WNgI0gFvBWaTi9wm6AhUAoUqOpDtG5Zct+Qr9F3mSdnbc6V4= ;{id = 2854}
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 20 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD DO RA AD NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+www.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFC99iE9K5y2WNgI0gFvBWaTi9wm6AhUAoUqOpDtG5Zct+Qr9F3mSdnbc6V4= ;{id = 2854}
+ENTRY_END
+
+SCENARIO_END
diff --git a/testdata/auth_zonefile_down.rpl b/testdata/auth_zonefile_down.rpl
new file mode 100644
index 000000000000..09e7fd061407
--- /dev/null
+++ b/testdata/auth_zonefile_down.rpl
@@ -0,0 +1,185 @@
+; config options
+server:
+ target-fetch-policy: "0 0 0 0 0"
+
+auth-zone:
+ name: "example.com."
+ ## zonefile (or none).
+ ## zonefile: "example.com.zone"
+ ## master by IP address or hostname
+ ## can list multiple masters, each on one line.
+ ## master:
+ ## url for http fetch
+ ## url:
+ ## queries from downstream clients get authoritative answers.
+ ## for-downstream: yes
+ for-downstream: yes
+ ## queries are used to fetch authoritative answers from this zone,
+ ## instead of unbound itself sending queries there.
+ ## for-upstream: yes
+ for-upstream: no
+ ## on failures with for-upstream, fallback to sending queries to
+ ## the authority servers
+ ## fallback-enabled: no
+
+ ## this line generates zonefile: \n"/tmp/xxx.example.com"\n
+ zonefile:
+TEMPFILE_NAME example.com
+ ## this is the inline file /tmp/xxx.example.com
+ ## the tempfiles are deleted when the testrun is over.
+TEMPFILE_CONTENTS example.com
+$ORIGIN com.
+example 3600 IN SOA dns.example.de. hostmaster.dns.example.de. (
+ 1379078166 28800 7200 604800 7200 )
+ 3600 IN NS ns1.example.com.
+ 3600 IN NS ns2.example.com.
+$ORIGIN example.com.
+www 3600 IN A 1.2.3.4
+mail 3600 IN A 1.2.3.5
+ 3600 IN AAAA ::5
+ns1 3600 IN A 1.2.3.4
+ns2 3600 IN AAAA ::2
+TEMPFILE_END
+
+stub-zone:
+ name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN Test authority zone with zonefile for downstream responses
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.44
+ENTRY_END
+RANGE_END
+
+; ns.example.net.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.44
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.net. IN NS
+SECTION ANSWER
+example.net. IN NS ns.example.net.
+SECTION ADDITIONAL
+ns.example.net. IN A 1.2.3.44
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.net. IN A
+SECTION ANSWER
+ns.example.net. IN A 1.2.3.44
+SECTION AUTHORITY
+example.net. IN NS ns.example.net.
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.net. IN AAAA
+SECTION AUTHORITY
+example.net. IN NS ns.example.net.
+SECTION ADDITIONAL
+www.example.net. IN A 1.2.3.44
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.net.
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 20 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA AA NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 1.2.3.4
+ENTRY_END
+
+SCENARIO_END
diff --git a/testdata/auth_zonefile_noup.rpl b/testdata/auth_zonefile_noup.rpl
new file mode 100644
index 000000000000..da0dd76672ec
--- /dev/null
+++ b/testdata/auth_zonefile_noup.rpl
@@ -0,0 +1,184 @@
+; config options
+server:
+ target-fetch-policy: "0 0 0 0 0"
+
+auth-zone:
+ name: "example.com."
+ ## zonefile (or none).
+ ## zonefile: "example.com.zone"
+ ## master by IP address or hostname
+ ## can list multiple masters, each on one line.
+ ## master:
+ ## url for http fetch
+ ## url:
+ ## queries from downstream clients get authoritative answers.
+ ## for-downstream: yes
+ for-downstream: no
+ ## queries are used to fetch authoritative answers from this zone,
+ ## instead of unbound itself sending queries there.
+ ## for-upstream: yes
+ for-upstream: no
+ ## on failures with for-upstream, fallback to sending queries to
+ ## the authority servers
+ ## fallback-enabled: no
+
+ ## this line generates zonefile: \n"/tmp/xxx.example.com"\n
+ zonefile:
+TEMPFILE_NAME example.com
+ ## this is the inline file /tmp/xxx.example.com
+ ## the tempfiles are deleted when the testrun is over.
+TEMPFILE_CONTENTS example.com
+$ORIGIN com.
+example 3600 IN SOA dns.example.de. hostmaster.dns.example.de. (
+ 1379078166 28800 7200 604800 7200 )
+ 3600 IN NS ns1.example.com.
+ 3600 IN NS ns2.example.com.
+$ORIGIN example.com.
+www 3600 IN A 1.2.3.4
+ns1 3600 IN A 1.2.3.4
+ns2 3600 IN AAAA ::2
+TEMPFILE_END
+
+stub-zone:
+ name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN Test authority zone with zonefile with no upstream enabled
+; and therefore fallback is going to be used.
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.44
+ENTRY_END
+RANGE_END
+
+; ns.example.net.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.44
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.net. IN NS
+SECTION ANSWER
+example.net. IN NS ns.example.net.
+SECTION ADDITIONAL
+ns.example.net. IN A 1.2.3.44
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.net. IN A
+SECTION ANSWER
+ns.example.net. IN A 1.2.3.44
+SECTION AUTHORITY
+example.net. IN NS ns.example.net.
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.net. IN AAAA
+SECTION AUTHORITY
+example.net. IN NS ns.example.net.
+SECTION ADDITIONAL
+www.example.net. IN A 1.2.3.44
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.net.
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 20 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+ENTRY_END
+
+SCENARIO_END
diff --git a/testdata/auth_zonefile_root.rpl b/testdata/auth_zonefile_root.rpl
new file mode 100644
index 000000000000..9755f91e156a
--- /dev/null
+++ b/testdata/auth_zonefile_root.rpl
@@ -0,0 +1,181 @@
+; config options
+server:
+ target-fetch-policy: "0 0 0 0 0"
+
+auth-zone:
+ name: "."
+ ## zonefile (or none).
+ ## zonefile: "example.com.zone"
+ ## master by IP address or hostname
+ ## can list multiple masters, each on one line.
+ ## master:
+ ## url for http fetch
+ ## url:
+ ## queries from downstream clients get authoritative answers.
+ ## for-downstream: yes
+ for-downstream: no
+ ## queries are used to fetch authoritative answers from this zone,
+ ## instead of unbound itself sending queries there.
+ ## for-upstream: yes
+ for-upstream: yes
+ ## on failures with for-upstream, fallback to sending queries to
+ ## the authority servers
+ ## fallback-enabled: no
+ fallback-enabled: yes
+
+ ## this line generates zonefile: \n"/tmp/xxx.example.com"\n
+ zonefile:
+TEMPFILE_NAME root.zone
+ ## this is the inline file /tmp/xxx.example.com
+ ## the tempfiles are deleted when the testrun is over.
+TEMPFILE_CONTENTS root.zone
+. 86400 IN SOA a.root-servers.net. nstld.verisign-grs.com. 2018013100 1800 900 604800 86400
+. 518400 IN NS k.root-servers.net.
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+com. IN NS a.gtld-servers.net.
+a.gtld-servers.net. IN A 192.5.6.30
+TEMPFILE_END
+
+stub-zone:
+ name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN Test authority zone with zonefile for root referrals
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+; disable this referral for the test, we want to use the builtin copy of the zone
+; a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.44
+ENTRY_END
+RANGE_END
+
+; ns.example.net.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.44
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.net. IN NS
+SECTION ANSWER
+example.net. IN NS ns.example.net.
+SECTION ADDITIONAL
+ns.example.net. IN A 1.2.3.44
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.net. IN A
+SECTION ANSWER
+ns.example.net. IN A 1.2.3.44
+SECTION AUTHORITY
+example.net. IN NS ns.example.net.
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+ns.example.net. IN AAAA
+SECTION AUTHORITY
+example.net. IN NS ns.example.net.
+SECTION ADDITIONAL
+www.example.net. IN A 1.2.3.44
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.net.
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 20 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A 10.20.30.40
+ENTRY_END
+
+SCENARIO_END
diff --git a/testdata/iter_ds_referral.rpl b/testdata/iter_ds_referral.rpl
new file mode 100644
index 000000000000..e320942d6e9b
--- /dev/null
+++ b/testdata/iter_ds_referral.rpl
@@ -0,0 +1,213 @@
+; config options
+; The island of trust is at example.com
+server:
+ trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b"
+ val-override-date: "20070916134226"
+ target-fetch-policy: "0 0 0 0 0"
+ fake-sha1: yes
+ trust-anchor-signaling: no
+
+stub-zone:
+ name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN Test iterator with DS query and referral reply
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN A
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN A
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+RANGE_END
+
+; ns.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.4
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854}
+ENTRY_END
+
+; response to DNSKEY priming query
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN DNSKEY
+SECTION ANSWER
+example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b}
+example.com. 3600 IN RRSIG DNSKEY DSA 2 3600 20070926134150 20070829134150 2854 example.com. MCwCFBQRtlR4BEv9ohi+PGFjp+AHsJuHAhRCvz0shggvnvI88DFnBDCczHUcVA== ;{id = 2854}
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854}
+ENTRY_END
+
+; note, no specific DS answer here, it replies with the referral for
+; the type DS query
+
+; response for delegation to sub.example.com.
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+sub.example.com. IN A
+SECTION ANSWER
+SECTION AUTHORITY
+sub.example.com. IN NS ns.sub.example.com.
+sub.example.com. 3600 IN DS 30899 RSASHA1 1 f7ed618f24d5e5202927e1d27bc2e84a141cb4b3
+sub.example.com. 3600 IN RRSIG DS 3 3 3600 20070926134150 20070829134150 2854 example.com. MCwCFCW3ix0GD4BSvNLWIbROCJt5DAW9AhRt/kg9kBKJ20UBUdumrBUHqnskdA== ;{id = 2854}
+SECTION ADDITIONAL
+ns.sub.example.com. IN A 1.2.3.6
+ENTRY_END
+
+RANGE_END
+
+; ns.sub.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.6
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+sub.example.com. IN NS
+SECTION ANSWER
+sub.example.com. IN NS ns.sub.example.com.
+sub.example.com. 3600 IN RRSIG NS 5 3 3600 20070926134150 20070829134150 30899 sub.example.com. wcpHeBILHfo8C9uxMhcW03gcURZeUffiKdSTb50ZjzTHgMNhRyMfpcvSpXEd9548A9UTmWKeLZChfr5Z/glONw== ;{id = 30899}
+SECTION ADDITIONAL
+ns.sub.example.com. IN A 1.2.3.6
+ns.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. UF7shD/gt1FOp2UHgLTNbPzVykklSXFMEtJ1xD+Hholwf/PIzd7zoaIttIYibNa4fUXCqMg22H9P7MRhfmFe6g== ;{id = 30899}
+ENTRY_END
+
+; response to DNSKEY priming query
+; sub.example.com. 3600 IN DS 30899 RSASHA1 1 f7ed618f24d5e5202927e1d27bc2e84a141cb4b3
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+sub.example.com. IN DNSKEY
+SECTION ANSWER
+sub.example.com. 3600 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b}
+sub.example.com. 3600 IN RRSIG DNSKEY 5 3 3600 20070926134150 20070829134150 30899 sub.example.com. uNGp99iznjD7oOX02XnQbDnbg75UwBHRvZSKYUorTKvPUnCWMHKdRsQ+mf+Fx3GZ+Fz9BVjoCmQqpnfgXLEYqw== ;{id = 30899}
+SECTION AUTHORITY
+sub.example.com. IN NS ns.sub.example.com.
+sub.example.com. 3600 IN RRSIG NS 5 3 3600 20070926134150 20070829134150 30899 sub.example.com. wcpHeBILHfo8C9uxMhcW03gcURZeUffiKdSTb50ZjzTHgMNhRyMfpcvSpXEd9548A9UTmWKeLZChfr5Z/glONw== ;{id = 30899}
+SECTION ADDITIONAL
+ns.sub.example.com. IN A 1.2.3.6
+ns.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. UF7shD/gt1FOp2UHgLTNbPzVykklSXFMEtJ1xD+Hholwf/PIzd7zoaIttIYibNa4fUXCqMg22H9P7MRhfmFe6g== ;{id = 30899}
+ENTRY_END
+
+; response to A query
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.sub.example.com. IN A
+SECTION ANSWER
+www.sub.example.com. IN A 11.11.11.11
+www.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. 0DqqRfRtm7VSEQ4mmBbzrKRqQAay3JAE8DPDGmjtokrrjN9F1G/HxozDV7bjdIh2EChlQea8FPwf/GepJMUVxg== ;{id = 30899}
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+
+; something for wrong type DS query here
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR REFUSED
+SECTION QUESTION
+sub.example.com. IN DS
+SECTION ANSWER
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+sub.example.com. IN DS
+ENTRY_END
+
+; recursion happens here.
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA AD DO NOERROR
+SECTION QUESTION
+sub.example.com. IN DS
+SECTION ANSWER
+sub.example.com. 3600 IN DS 30899 RSASHA1 1 f7ed618f24d5e5202927e1d27bc2e84a141cb4b3
+sub.example.com. 3600 IN RRSIG DS 3 3 3600 20070926134150 20070829134150 2854 example.com. MCwCFCW3ix0GD4BSvNLWIbROCJt5DAW9AhRt/kg9kBKJ20UBUdumrBUHqnskdA== ;{id = 2854}
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+
+SCENARIO_END
diff --git a/testdata/iter_ds_reply.rpl b/testdata/iter_ds_reply.rpl
new file mode 100644
index 000000000000..ea2b69de211f
--- /dev/null
+++ b/testdata/iter_ds_reply.rpl
@@ -0,0 +1,225 @@
+; config options
+; The island of trust is at example.com
+server:
+ trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b"
+ val-override-date: "20070916134226"
+ target-fetch-policy: "0 0 0 0 0"
+ fake-sha1: yes
+ trust-anchor-signaling: no
+
+stub-zone:
+ name: "."
+ stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN Test iterator with DS query and answer reply
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+ ADDRESS 193.0.14.129
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET. IN A 193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN A
+SECTION AUTHORITY
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+ ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com. IN NS a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net. IN A 192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN A
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ENTRY_END
+RANGE_END
+
+; ns.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.4
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854}
+ENTRY_END
+
+; response to DNSKEY priming query
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN DNSKEY
+SECTION ANSWER
+example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b}
+example.com. 3600 IN RRSIG DNSKEY DSA 2 3600 20070926134150 20070829134150 2854 example.com. MCwCFBQRtlR4BEv9ohi+PGFjp+AHsJuHAhRCvz0shggvnvI88DFnBDCczHUcVA== ;{id = 2854}
+SECTION AUTHORITY
+example.com. IN NS ns.example.com.
+example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854}
+SECTION ADDITIONAL
+ns.example.com. IN A 1.2.3.4
+ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854}
+ENTRY_END
+
+; DS gets an answer from the authoritative server
+; (like NSD 4.1.0 answers it)
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR AA NOERROR
+SECTION QUESTION
+sub.example.com. IN DS
+SECTION ANSWER
+sub.example.com. 3600 IN DS 30899 RSASHA1 1 f7ed618f24d5e5202927e1d27bc2e84a141cb4b3
+sub.example.com. 3600 IN RRSIG DS 3 3 3600 20070926134150 20070829134150 2854 example.com. MCwCFCW3ix0GD4BSvNLWIbROCJt5DAW9AhRt/kg9kBKJ20UBUdumrBUHqnskdA== ;{id = 2854}
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+
+; response for delegation to sub.example.com.
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+sub.example.com. IN A
+SECTION ANSWER
+SECTION AUTHORITY
+sub.example.com. IN NS ns.sub.example.com.
+sub.example.com. 3600 IN DS 30899 RSASHA1 1 f7ed618f24d5e5202927e1d27bc2e84a141cb4b3
+sub.example.com. 3600 IN RRSIG DS 3 3 3600 20070926134150 20070829134150 2854 example.com. MCwCFCW3ix0GD4BSvNLWIbROCJt5DAW9AhRt/kg9kBKJ20UBUdumrBUHqnskdA== ;{id = 2854}
+SECTION ADDITIONAL
+ns.sub.example.com. IN A 1.2.3.6
+ENTRY_END
+
+RANGE_END
+
+; ns.sub.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 1.2.3.6
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+sub.example.com. IN NS
+SECTION ANSWER
+sub.example.com. IN NS ns.sub.example.com.
+sub.example.com. 3600 IN RRSIG NS 5 3 3600 20070926134150 20070829134150 30899 sub.example.com. wcpHeBILHfo8C9uxMhcW03gcURZeUffiKdSTb50ZjzTHgMNhRyMfpcvSpXEd9548A9UTmWKeLZChfr5Z/glONw== ;{id = 30899}
+SECTION ADDITIONAL
+ns.sub.example.com. IN A 1.2.3.6
+ns.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. UF7shD/gt1FOp2UHgLTNbPzVykklSXFMEtJ1xD+Hholwf/PIzd7zoaIttIYibNa4fUXCqMg22H9P7MRhfmFe6g== ;{id = 30899}
+ENTRY_END
+
+; response to DNSKEY priming query
+; sub.example.com. 3600 IN DS 30899 RSASHA1 1 f7ed618f24d5e5202927e1d27bc2e84a141cb4b3
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+sub.example.com. IN DNSKEY
+SECTION ANSWER
+sub.example.com. 3600 IN DNSKEY 256 3 5 AQPQ41chR9DEHt/aIzIFAqanbDlRflJoRs5yz1jFsoRIT7dWf0r+PeDuewdxkszNH6wnU4QL8pfKFRh5PIYVBLK3 ;{id = 30899 (zsk), size = 512b}
+sub.example.com. 3600 IN RRSIG DNSKEY 5 3 3600 20070926134150 20070829134150 30899 sub.example.com. uNGp99iznjD7oOX02XnQbDnbg75UwBHRvZSKYUorTKvPUnCWMHKdRsQ+mf+Fx3GZ+Fz9BVjoCmQqpnfgXLEYqw== ;{id = 30899}
+SECTION AUTHORITY
+sub.example.com. IN NS ns.sub.example.com.
+sub.example.com. 3600 IN RRSIG NS 5 3 3600 20070926134150 20070829134150 30899 sub.example.com. wcpHeBILHfo8C9uxMhcW03gcURZeUffiKdSTb50ZjzTHgMNhRyMfpcvSpXEd9548A9UTmWKeLZChfr5Z/glONw== ;{id = 30899}
+SECTION ADDITIONAL
+ns.sub.example.com. IN A 1.2.3.6
+ns.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. UF7shD/gt1FOp2UHgLTNbPzVykklSXFMEtJ1xD+Hholwf/PIzd7zoaIttIYibNa4fUXCqMg22H9P7MRhfmFe6g== ;{id = 30899}
+ENTRY_END
+
+; response to A query
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+www.sub.example.com. IN A
+SECTION ANSWER
+www.sub.example.com. IN A 11.11.11.11
+www.sub.example.com. 3600 IN RRSIG A 5 4 3600 20070926134150 20070829134150 30899 sub.example.com. 0DqqRfRtm7VSEQ4mmBbzrKRqQAay3JAE8DPDGmjtokrrjN9F1G/HxozDV7bjdIh2EChlQea8FPwf/GepJMUVxg== ;{id = 30899}
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+
+; something for wrong type DS query here
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR REFUSED
+SECTION QUESTION
+sub.example.com. IN DS
+SECTION ANSWER
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+sub.example.com. IN DS
+ENTRY_END
+
+; recursion happens here.
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA AD DO NOERROR
+SECTION QUESTION
+sub.example.com. IN DS
+SECTION ANSWER
+sub.example.com. 3600 IN DS 30899 RSASHA1 1 f7ed618f24d5e5202927e1d27bc2e84a141cb4b3
+sub.example.com. 3600 IN RRSIG DS 3 3 3600 20070926134150 20070829134150 2854 example.com. MCwCFCW3ix0GD4BSvNLWIbROCJt5DAW9AhRt/kg9kBKJ20UBUdumrBUHqnskdA== ;{id = 2854}
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+
+SCENARIO_END
diff --git a/testdata/iter_ns_badip.rpl b/testdata/iter_ns_badip.rpl
index 49abdd6887f0..021e552b74c5 100644
--- a/testdata/iter_ns_badip.rpl
+++ b/testdata/iter_ns_badip.rpl
@@ -7,7 +7,7 @@ stub-zone:
stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
CONFIG_END
-SCENARIO_BEGIN Test iterator with delagation with bad IP address
+SCENARIO_BEGIN Test iterator with delegation with bad IP address
; K.ROOT-SERVERS.NET.
RANGE_BEGIN 0 100
diff --git a/testdata/test_signatures.9 b/testdata/test_signatures.9
new file mode 100644
index 000000000000..7f4b350e71aa
--- /dev/null
+++ b/testdata/test_signatures.9
@@ -0,0 +1,21 @@
+; Signature test file
+
+; first entry is a DNSKEY answer, with the DNSKEY rrset used for verification.
+; later entries are verified with it.
+
+ENTRY_BEGIN
+SECTION QUESTION
+nsec.0skar.cz. IN DNSKEY
+SECTION ANSWER
+nsec.0skar.cz. 297 IN DNSKEY 257 3 10 AwEAAcfJERXDHOSg4JsxSO8WmFdi/PPbtgB6N6xDyyaDqRzr9QCL4LXH yLYjGmriFn7xhVDQTyQQp/nox5RK8YeAFHoiglQuwQVs2TyZTAZskTRj K4NL3+TuMxtCMObzHkAxa0rYvAV5RBh5tdLHUHJLe33xrFNcVidkHMAP F+kjY/9UNi1at2LTohE8VQD0mcv3Gvm79heIjq8Xt3SuqPpk7eQm1r8m 7cIsuojbCum964/H93LeyafExa1eEMhZIIiSG+ik2jDhdeybmMyeoKsO jIL/9N/Yd6u60VkWvUMennyv9rKQTOY84yg2T9yAVjusepggcxMpCVX5 HdWxakruR80=
+ENTRY_END
+
+; entry to test ; note timestamp in 2080.
+ENTRY_BEGIN
+SECTION QUESTION
+nsec.0skar.cz. IN DNSKEY
+SECTION ANSWER
+nsec.0skar.cz. 297 IN DNSKEY 257 3 10 AwEAAcfJERXDHOSg4JsxSO8WmFdi/PPbtgB6N6xDyyaDqRzr9QCL4LXH yLYjGmriFn7xhVDQTyQQp/nox5RK8YeAFHoiglQuwQVs2TyZTAZskTRj K4NL3+TuMxtCMObzHkAxa0rYvAV5RBh5tdLHUHJLe33xrFNcVidkHMAP F+kjY/9UNi1at2LTohE8VQD0mcv3Gvm79heIjq8Xt3SuqPpk7eQm1r8m 7cIsuojbCum964/H93LeyafExa1eEMhZIIiSG+ik2jDhdeybmMyeoKsO jIL/9N/Yd6u60VkWvUMennyv9rKQTOY84yg2T9yAVjusepggcxMpCVX5 HdWxakruR80=
+nsec.0skar.cz. 297 IN RRSIG DNSKEY 10 3 300 20800101000000 20140130121330 28887 nsec.0skar.cz. Ef6Jmf/d9BR0VcRakUD8dEjrMmbAF6qqYRBllLOvibFvpgdEJ7egCO9t d8jliD2VRXhqej2lqECNOvARJ+YyYekpniueiYZsBjleU2kJAyFAS2q3 7aBIii1WdM3h+noayDnjiuhEO3GLxxHWc3kyd2yDesPddiFl09fx+rcz 9BwXaS9A/vdWv+92R1j4nijVI5jxZgkQ4lnD0ZtAVRdBRO7qDRpkRHDM pnaSq51B/9XCZEv2CW8UQ5dGd9D20a3uA2lAKHLgj2/Rcuar4o2Y4ERa ms9pyDCQDhGaveZQdx01EXX0ehe5qIKOKk7iFP95TbWPMRyk1bfKTUoT Rq5rhQ==
+ENTRY_END
+
diff --git a/testdata/val_negcache_nodata.rpl b/testdata/val_negcache_nodata.rpl
new file mode 100644
index 000000000000..374ac4038b0a
--- /dev/null
+++ b/testdata/val_negcache_nodata.rpl
@@ -0,0 +1,166 @@
+; config options
+; The island of trust is at example.com
+server:
+ trust-anchor: "testzone.nlnetlabs.nl. IN DS 2926 8 2 6f8512d1e82eecbd684fc4a76f39f8c5b411af385494873bdead663ddb78a88b"
+ val-override-date: "20180213111425"
+ target-fetch-policy: "0 0 0 0 0"
+ trust-anchor-signaling: no
+ aggressive-nsec: yes
+
+stub-zone:
+ name: "testzone.nlnetlabs.nl"
+ stub-addr: 185.49.140.60
+CONFIG_END
+
+SCENARIO_BEGIN Test validator with negative cache NXDOMAIN response (aggressive NSEC)
+
+; testzone.nlnetlabs.nl nameserver
+RANGE_BEGIN 0 100
+ ADDRESS 185.49.140.60
+
+; response to DNSKEY priming query
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+testzone.nlnetlabs.nl. IN DNSKEY
+SECTION ANSWER
+testzone.nlnetlabs.nl. 3600 IN DNSKEY 256 3 8 AwEAAbrNEg01ByEpUUiip+GNAkNVjUfeX7sl9kPUssR3JQvhCJWVs7aBY0Ae1cNtQWgzCmidGorlXvEY2nNBiMM4l7IXqopJsgyj+Cb3nQPVLi/7yVwUb+AIwSJw1gRFElMYonsMOL9qUrJi8BBCnCR0EqkL+X4slmtkXSJbzQAwvHI7
+testzone.nlnetlabs.nl. 3600 IN DNSKEY 257 3 8 AwEAAbn0eGV0wqMBQNSVTY//BoiOD7bexC7FcVv0fH9bwjKOA8I+ob377E14vZN2xRLC2b1GG5iBckjeI+N2dB9eC2KRnScU3Gbmtw75BBYfm/y4Hu72zEjEZ0ZGv6gjSZRv/1o87ODAwQaxN8/dQD+5U/5xu12XM39bCJZx2GWTbf5L
+testzone.nlnetlabs.nl. 3600 IN RRSIG DNSKEY 8 3 3600 20180313101254 20180213101254 2926 testzone.nlnetlabs.nl. gSLZb/dSKutRlAKSo8ZCC1R+SkvABMYBRQsms77WPfYCDbt5GbXeuGqwGdadjEN8gGSU+qrYNxBZRhlYY6d2vtl+DGh67qwteHSwOCw0VvU64eVh38maJA1U673U4JtlBALzBOA/UHmXPlCgPPoW3BG0U3T2Qir/mqOmegmpBcw=
+SECTION AUTHORITY
+testzone.nlnetlabs.nl. 3600 IN NS ns.nlnetlabs.nl.
+testzone.nlnetlabs.nl. 3600 IN RRSIG NS 8 3 3600 20180313102201 20180213102201 44940 testzone.nlnetlabs.nl. Ox0iKc+z3i1qR1wMr8TBPYzuYO5UTaLrBsDagJAd25fvCkGN+h3HPmWlCIW0cBHsS+IaHXr1JhWutjSCc4UBcY+sT7Y7Fw3V1qdZW2KzbSgWUyPkTXoYcIIVLacSUTXEyltW6jj61WEI/RaUGUCJortvwH5iv1Hzee343isxObI=
+SECTION ADDITIONAL
+ENTRY_END
+
+; NODATA response for alligator.testzone.nlnetlabs.nl A type
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+alligator.testzone.nlnetlabs.nl. IN A
+SECTION ANSWER
+SECTION AUTHORITY
+alligator.testzone.nlnetlabs.nl. 3600 IN NSEC cheetah.testzone.nlnetlabs.nl. TXT RRSIG NSEC
+alligator.testzone.nlnetlabs.nl. 3600 IN RRSIG NSEC 8 4 3600 20180313102201 20180213102201 44940 testzone.nlnetlabs.nl. QAgQ0AsMoYG02+VPfoOctSPlTHdQOkQt5fFkSkzIbVhUzNOqa+dB/Qkc81AwFeJosA+PvYjt6utcVkIWmK2Djy9eXC49gILtVF79vUe4G7ZrybO5NXjqNa5ANoUGM+yew4wkjeNOMVAsvs+1kvFY7S8RAa/0AIYlZHQ8vNBPNaI=
+testzone.nlnetlabs.nl. 3600 IN SOA ns.nlnetlabs.nl. ralph.nlnetlabs.nl. 1 14400 3600 604800 3600
+testzone.nlnetlabs.nl. 3600 IN RRSIG SOA 8 3 3600 20180313102201 20180213102201 44940 testzone.nlnetlabs.nl. GhmXNFQktZIgaBpGKwj9Q2mfq5+jcbRPK+PPgtRVicUPZga/d/iGEL8PV/8DzGwkaZbM14pamSUMgdJibW4zNhLz/ukjPilbjoj6giH1jtbdZLAQ6iK9pZ/4jKUEq4txviTczZNnDeolgPEEl4xo4NclQmi7zj1XBlQRbjvG0/0=
+SECTION ADDITIONAL
+ENTRY_END
+
+; NXDOMAIN response for emu.testzone.nlnetlabs.nl
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NXDOMAIN
+SECTION QUESTION
+emu.testzone.nlnetlabs.nl. IN TXT
+SECTION ANSWER
+SECTION AUTHORITY
+*.elephant.testzone.nlnetlabs.nl. 3600 IN NSEC duck.ent.testzone.nlnetlabs.nl. TXT RRSIG NSEC
+*.elephant.testzone.nlnetlabs.nl. 3600 IN RRSIG NSEC 8 4 3600 20180313102201 20180213102201 44940 testzone.nlnetlabs.nl. GC4dtR5zYvfuIgMpr6gF8jV69wsi2GwGlftTl532H2sZP7nWa5cJmJ59+q4evBZ+P3fLxaZeGBpsp3fn1e7yadLW5PGiA25qrjG0TGVQgOPdIV+lo45sxn7Yn8apiXcJf/vtXZMR7FcHYK/BieTo2hafa2zaftfQVRA7hpJ/HDc=
+testzone.nlnetlabs.nl. 3600 IN NSEC alligator.testzone.nlnetlabs.nl. NS SOA RRSIG NSEC DNSKEY
+testzone.nlnetlabs.nl. 3600 IN RRSIG NSEC 8 3 3600 20180313102201 20180213102201 44940 testzone.nlnetlabs.nl. gTKn6U1nal9oA79IRxLa/7zexl6A0yJZzeEGBbZ5rh5feyAr2X4LTR9bPCgcHeMVggf4FP+kD1L/sxzj/YLwB1ZKGKlwnzsHtPFTlmvDClaqQ76DRZq5Vejr2ZfnclBUb2vtxaXywTRW8oueaaq9flcShEQ/cQ+KRU8sc344qd0=
+testzone.nlnetlabs.nl. 3600 IN SOA ns.nlnetlabs.nl. ralph.nlnetlabs.nl. 1 14400 3600 604800 3600
+testzone.nlnetlabs.nl. 3600 IN RRSIG SOA 8 3 3600 20180313102201 20180213102201 44940 testzone.nlnetlabs.nl. GhmXNFQktZIgaBpGKwj9Q2mfq5+jcbRPK+PPgtRVicUPZga/d/iGEL8PV/8DzGwkaZbM14pamSUMgdJibW4zNhLz/ukjPilbjoj6giH1jtbdZLAQ6iK9pZ/4jKUEq4txviTczZNnDeolgPEEl4xo4NclQmi7zj1XBlQRbjvG0/0=
+SECTION ADDITIONAL
+ENTRY_END
+
+; No answer for ant.testzone.nlnetlabs.nl
+
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+alligator.testzone.nlnetlabs.nl. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA DO AD NOERROR
+SECTION QUESTION
+alligator.testzone.nlnetlabs.nl. IN A
+SECTION ANSWER
+SECTION AUTHORITY
+alligator.testzone.nlnetlabs.nl. 3600 IN NSEC cheetah.testzone.nlnetlabs.nl. TXT RRSIG NSEC
+alligator.testzone.nlnetlabs.nl. 3600 IN RRSIG NSEC 8 4 3600 20180313102201 20180213102201 44940 testzone.nlnetlabs.nl. QAgQ0AsMoYG02+VPfoOctSPlTHdQOkQt5fFkSkzIbVhUzNOqa+dB/Qkc81AwFeJosA+PvYjt6utcVkIWmK2Djy9eXC49gILtVF79vUe4G7ZrybO5NXjqNa5ANoUGM+yew4wkjeNOMVAsvs+1kvFY7S8RAa/0AIYlZHQ8vNBPNaI=
+testzone.nlnetlabs.nl. 3600 IN SOA ns.nlnetlabs.nl. ralph.nlnetlabs.nl. 1 14400 3600 604800 3600
+testzone.nlnetlabs.nl. 3600 IN RRSIG SOA 8 3 3600 20180313102201 20180213102201 44940 testzone.nlnetlabs.nl. GhmXNFQktZIgaBpGKwj9Q2mfq5+jcbRPK+PPgtRVicUPZga/d/iGEL8PV/8DzGwkaZbM14pamSUMgdJibW4zNhLz/ukjPilbjoj6giH1jtbdZLAQ6iK9pZ/4jKUEq4txviTczZNnDeolgPEEl4xo4NclQmi7zj1XBlQRbjvG0/0=
+SECTION ADDITIONAL
+ENTRY_END
+
+; AAAA query for alligator.testzone.nlnetlabs.nl, which isn't on the testzone nameserver
+STEP 20 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+alligator.testzone.nlnetlabs.nl. IN AAAA
+ENTRY_END
+
+STEP 30 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA AD DO NOERROR
+SECTION QUESTION
+alligator.testzone.nlnetlabs.nl. IN AAAA
+SECTION ANSWER
+SECTION AUTHORITY
+alligator.testzone.nlnetlabs.nl. 3600 IN NSEC cheetah.testzone.nlnetlabs.nl. TXT RRSIG NSEC
+alligator.testzone.nlnetlabs.nl. 3600 IN RRSIG NSEC 8 4 3600 20180313102201 20180213102201 44940 testzone.nlnetlabs.nl. QAgQ0AsMoYG02+VPfoOctSPlTHdQOkQt5fFkSkzIbVhUzNOqa+dB/Qkc81AwFeJosA+PvYjt6utcVkIWmK2Djy9eXC49gILtVF79vUe4G7ZrybO5NXjqNa5ANoUGM+yew4wkjeNOMVAsvs+1kvFY7S8RAa/0AIYlZHQ8vNBPNaI=
+testzone.nlnetlabs.nl. 3600 IN SOA ns.nlnetlabs.nl. ralph.nlnetlabs.nl. 1 14400 3600 604800 3600
+testzone.nlnetlabs.nl. 3600 IN RRSIG SOA 8 3 3600 20180313102201 20180213102201 44940 testzone.nlnetlabs.nl. GhmXNFQktZIgaBpGKwj9Q2mfq5+jcbRPK+PPgtRVicUPZga/d/iGEL8PV/8DzGwkaZbM14pamSUMgdJibW4zNhLz/ukjPilbjoj6giH1jtbdZLAQ6iK9pZ/4jKUEq4txviTczZNnDeolgPEEl4xo4NclQmi7zj1XBlQRbjvG0/0=
+ENTRY_END
+
+STEP 40 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+emu.testzone.nlnetlabs.nl. IN TXT
+ENTRY_END
+
+STEP 50 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA AD DO NXDOMAIN
+SECTION QUESTION
+emu.testzone.nlnetlabs.nl. IN TXT
+SECTION ANSWER
+SECTION AUTHORITY
+*.elephant.testzone.nlnetlabs.nl. 3600 IN NSEC duck.ent.testzone.nlnetlabs.nl. TXT RRSIG NSEC
+*.elephant.testzone.nlnetlabs.nl. 3600 IN RRSIG NSEC 8 4 3600 20180313102201 20180213102201 44940 testzone.nlnetlabs.nl. GC4dtR5zYvfuIgMpr6gF8jV69wsi2GwGlftTl532H2sZP7nWa5cJmJ59+q4evBZ+P3fLxaZeGBpsp3fn1e7yadLW5PGiA25qrjG0TGVQgOPdIV+lo45sxn7Yn8apiXcJf/vtXZMR7FcHYK/BieTo2hafa2zaftfQVRA7hpJ/HDc=
+testzone.nlnetlabs.nl. 3600 IN NSEC alligator.testzone.nlnetlabs.nl. NS SOA RRSIG NSEC DNSKEY
+testzone.nlnetlabs.nl. 3600 IN RRSIG NSEC 8 3 3600 20180313102201 20180213102201 44940 testzone.nlnetlabs.nl. gTKn6U1nal9oA79IRxLa/7zexl6A0yJZzeEGBbZ5rh5feyAr2X4LTR9bPCgcHeMVggf4FP+kD1L/sxzj/YLwB1ZKGKlwnzsHtPFTlmvDClaqQ76DRZq5Vejr2ZfnclBUb2vtxaXywTRW8oueaaq9flcShEQ/cQ+KRU8sc344qd0=
+testzone.nlnetlabs.nl. 3600 IN SOA ns.nlnetlabs.nl. ralph.nlnetlabs.nl. 1 14400 3600 604800 3600
+testzone.nlnetlabs.nl. 3600 IN RRSIG SOA 8 3 3600 20180313102201 20180213102201 44940 testzone.nlnetlabs.nl. GhmXNFQktZIgaBpGKwj9Q2mfq5+jcbRPK+PPgtRVicUPZga/d/iGEL8PV/8DzGwkaZbM14pamSUMgdJibW4zNhLz/ukjPilbjoj6giH1jtbdZLAQ6iK9pZ/4jKUEq4txviTczZNnDeolgPEEl4xo4NclQmi7zj1XBlQRbjvG0/0=
+ENTRY_END
+
+STEP 60 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+ent.testzone.nlnetlabs.nl. IN TXT
+ENTRY_END
+
+; query for ENT, must result in NOERROR answer
+STEP 70 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA AD DO NOERROR
+SECTION QUESTION
+ent.testzone.nlnetlabs.nl. IN TXT
+SECTION ANSWER
+SECTION AUTHORITY
+*.elephant.testzone.nlnetlabs.nl. 3600 IN NSEC duck.ent.testzone.nlnetlabs.nl. TXT RRSIG NSEC
+*.elephant.testzone.nlnetlabs.nl. 3600 IN RRSIG NSEC 8 4 3600 20180313102201 20180213102201 44940 testzone.nlnetlabs.nl. GC4dtR5zYvfuIgMpr6gF8jV69wsi2GwGlftTl532H2sZP7nWa5cJmJ59+q4evBZ+P3fLxaZeGBpsp3fn1e7yadLW5PGiA25qrjG0TGVQgOPdIV+lo45sxn7Yn8apiXcJf/vtXZMR7FcHYK/BieTo2hafa2zaftfQVRA7hpJ/HDc=
+testzone.nlnetlabs.nl. 3600 IN SOA ns.nlnetlabs.nl. ralph.nlnetlabs.nl. 1 14400 3600 604800 3600
+testzone.nlnetlabs.nl. 3600 IN RRSIG SOA 8 3 3600 20180313102201 20180213102201 44940 testzone.nlnetlabs.nl. GhmXNFQktZIgaBpGKwj9Q2mfq5+jcbRPK+PPgtRVicUPZga/d/iGEL8PV/8DzGwkaZbM14pamSUMgdJibW4zNhLz/ukjPilbjoj6giH1jtbdZLAQ6iK9pZ/4jKUEq4txviTczZNnDeolgPEEl4xo4NclQmi7zj1XBlQRbjvG0/0=
+ENTRY_END
+
+SCENARIO_END
diff --git a/testdata/val_negcache_nxdomain.rpl b/testdata/val_negcache_nxdomain.rpl
new file mode 100644
index 000000000000..06f115bfefef
--- /dev/null
+++ b/testdata/val_negcache_nxdomain.rpl
@@ -0,0 +1,109 @@
+; config options
+; The island of trust is at example.com
+server:
+ trust-anchor: "testzone.nlnetlabs.nl. IN DS 2926 8 2 6f8512d1e82eecbd684fc4a76f39f8c5b411af385494873bdead663ddb78a88b"
+ val-override-date: "20180213111425"
+ target-fetch-policy: "0 0 0 0 0"
+ trust-anchor-signaling: no
+ aggressive-nsec: yes
+
+stub-zone:
+ name: "testzone.nlnetlabs.nl"
+ stub-addr: 185.49.140.60
+CONFIG_END
+
+SCENARIO_BEGIN Test validator with negative cache NXDOMAIN response (aggressive NSEC)
+
+; testzone.nlnetlabs.nl nameserver
+RANGE_BEGIN 0 100
+ ADDRESS 185.49.140.60
+
+; response to DNSKEY priming query
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+testzone.nlnetlabs.nl. IN DNSKEY
+SECTION ANSWER
+testzone.nlnetlabs.nl. 3600 IN DNSKEY 256 3 8 AwEAAbrNEg01ByEpUUiip+GNAkNVjUfeX7sl9kPUssR3JQvhCJWVs7aBY0Ae1cNtQWgzCmidGorlXvEY2nNBiMM4l7IXqopJsgyj+Cb3nQPVLi/7yVwUb+AIwSJw1gRFElMYonsMOL9qUrJi8BBCnCR0EqkL+X4slmtkXSJbzQAwvHI7
+testzone.nlnetlabs.nl. 3600 IN DNSKEY 257 3 8 AwEAAbn0eGV0wqMBQNSVTY//BoiOD7bexC7FcVv0fH9bwjKOA8I+ob377E14vZN2xRLC2b1GG5iBckjeI+N2dB9eC2KRnScU3Gbmtw75BBYfm/y4Hu72zEjEZ0ZGv6gjSZRv/1o87ODAwQaxN8/dQD+5U/5xu12XM39bCJZx2GWTbf5L
+testzone.nlnetlabs.nl. 3600 IN RRSIG DNSKEY 8 3 3600 20180313101254 20180213101254 2926 testzone.nlnetlabs.nl. gSLZb/dSKutRlAKSo8ZCC1R+SkvABMYBRQsms77WPfYCDbt5GbXeuGqwGdadjEN8gGSU+qrYNxBZRhlYY6d2vtl+DGh67qwteHSwOCw0VvU64eVh38maJA1U673U4JtlBALzBOA/UHmXPlCgPPoW3BG0U3T2Qir/mqOmegmpBcw=
+SECTION AUTHORITY
+testzone.nlnetlabs.nl. 3600 IN NS ns.nlnetlabs.nl.
+testzone.nlnetlabs.nl. 3600 IN RRSIG NS 8 3 3600 20180313102201 20180213102201 44940 testzone.nlnetlabs.nl. Ox0iKc+z3i1qR1wMr8TBPYzuYO5UTaLrBsDagJAd25fvCkGN+h3HPmWlCIW0cBHsS+IaHXr1JhWutjSCc4UBcY+sT7Y7Fw3V1qdZW2KzbSgWUyPkTXoYcIIVLacSUTXEyltW6jj61WEI/RaUGUCJortvwH5iv1Hzee343isxObI=
+SECTION ADDITIONAL
+ENTRY_END
+
+; response for antelope.testzone.nlnetlabs.nl.
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NXDOMAIN
+SECTION QUESTION
+antelope.testzone.nlnetlabs.nl. IN TXT
+SECTION ANSWER
+SECTION AUTHORITY
+testzone.nlnetlabs.nl. 3600 IN NSEC alligator.testzone.nlnetlabs.nl. NS SOA RRSIG NSEC DNSKEY
+testzone.nlnetlabs.nl. 3600 IN RRSIG NSEC 8 3 3600 20180313102201 20180213102201 44940 testzone.nlnetlabs.nl. gTKn6U1nal9oA79IRxLa/7zexl6A0yJZzeEGBbZ5rh5feyAr2X4LTR9bPCgcHeMVggf4FP+kD1L/sxzj/YLwB1ZKGKlwnzsHtPFTlmvDClaqQ76DRZq5Vejr2ZfnclBUb2vtxaXywTRW8oueaaq9flcShEQ/cQ+KRU8sc344qd0=
+alligator.testzone.nlnetlabs.nl. 3600 IN NSEC cheetah.testzone.nlnetlabs.nl. TXT RRSIG NSEC
+alligator.testzone.nlnetlabs.nl. 3600 IN RRSIG NSEC 8 4 3600 20180313102201 20180213102201 44940 testzone.nlnetlabs.nl. QAgQ0AsMoYG02+VPfoOctSPlTHdQOkQt5fFkSkzIbVhUzNOqa+dB/Qkc81AwFeJosA+PvYjt6utcVkIWmK2Djy9eXC49gILtVF79vUe4G7ZrybO5NXjqNa5ANoUGM+yew4wkjeNOMVAsvs+1kvFY7S8RAa/0AIYlZHQ8vNBPNaI=
+testzone.nlnetlabs.nl. 3600 IN SOA ns.nlnetlabs.nl. ralph.nlnetlabs.nl. 1 14400 3600 604800 3600
+testzone.nlnetlabs.nl. 3600 IN RRSIG SOA 8 3 3600 20180313102201 20180213102201 44940 testzone.nlnetlabs.nl. GhmXNFQktZIgaBpGKwj9Q2mfq5+jcbRPK+PPgtRVicUPZga/d/iGEL8PV/8DzGwkaZbM14pamSUMgdJibW4zNhLz/ukjPilbjoj6giH1jtbdZLAQ6iK9pZ/4jKUEq4txviTczZNnDeolgPEEl4xo4NclQmi7zj1XBlQRbjvG0/0=
+SECTION ADDITIONAL
+ENTRY_END
+
+; No answer for ant.testzone.nlnetlabs.nl
+
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+antelope.testzone.nlnetlabs.nl. IN TXT
+ENTRY_END
+
+; recursion happens here.
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA DO AD NXDOMAIN
+SECTION QUESTION
+antelope.testzone.nlnetlabs.nl. IN TXT
+SECTION ANSWER
+SECTION AUTHORITY
+testzone.nlnetlabs.nl. 3600 IN NSEC alligator.testzone.nlnetlabs.nl. NS SOA RRSIG NSEC DNSKEY
+testzone.nlnetlabs.nl. 3600 IN RRSIG NSEC 8 3 3600 20180313102201 20180213102201 44940 testzone.nlnetlabs.nl. gTKn6U1nal9oA79IRxLa/7zexl6A0yJZzeEGBbZ5rh5feyAr2X4LTR9bPCgcHeMVggf4FP+kD1L/sxzj/YLwB1ZKGKlwnzsHtPFTlmvDClaqQ76DRZq5Vejr2ZfnclBUb2vtxaXywTRW8oueaaq9flcShEQ/cQ+KRU8sc344qd0=
+alligator.testzone.nlnetlabs.nl. 3600 IN NSEC cheetah.testzone.nlnetlabs.nl. TXT RRSIG NSEC
+alligator.testzone.nlnetlabs.nl. 3600 IN RRSIG NSEC 8 4 3600 20180313102201 20180213102201 44940 testzone.nlnetlabs.nl. QAgQ0AsMoYG02+VPfoOctSPlTHdQOkQt5fFkSkzIbVhUzNOqa+dB/Qkc81AwFeJosA+PvYjt6utcVkIWmK2Djy9eXC49gILtVF79vUe4G7ZrybO5NXjqNa5ANoUGM+yew4wkjeNOMVAsvs+1kvFY7S8RAa/0AIYlZHQ8vNBPNaI=
+testzone.nlnetlabs.nl. 3600 IN SOA ns.nlnetlabs.nl. ralph.nlnetlabs.nl. 1 14400 3600 604800 3600
+testzone.nlnetlabs.nl. 3600 IN RRSIG SOA 8 3 3600 20180313102201 20180213102201 44940 testzone.nlnetlabs.nl. GhmXNFQktZIgaBpGKwj9Q2mfq5+jcbRPK+PPgtRVicUPZga/d/iGEL8PV/8DzGwkaZbM14pamSUMgdJibW4zNhLz/ukjPilbjoj6giH1jtbdZLAQ6iK9pZ/4jKUEq4txviTczZNnDeolgPEEl4xo4NclQmi7zj1XBlQRbjvG0/0=
+SECTION ADDITIONAL
+ENTRY_END
+
+; query for ant.testzone.nlnetlabs.nl, which isn't on the testzone nameserver
+STEP 20 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+ant.testzone.nlnetlabs.nl. IN TXT
+ENTRY_END
+
+STEP 30 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA AD DO NXDOMAIN
+SECTION QUESTION
+ant.testzone.nlnetlabs.nl. IN TXT
+SECTION ANSWER
+SECTION AUTHORITY
+testzone.nlnetlabs.nl. 3600 IN NSEC alligator.testzone.nlnetlabs.nl. NS SOA RRSIG NSEC DNSKEY
+testzone.nlnetlabs.nl. 3600 IN RRSIG NSEC 8 3 3600 20180313102201 20180213102201 44940 testzone.nlnetlabs.nl. gTKn6U1nal9oA79IRxLa/7zexl6A0yJZzeEGBbZ5rh5feyAr2X4LTR9bPCgcHeMVggf4FP+kD1L/sxzj/YLwB1ZKGKlwnzsHtPFTlmvDClaqQ76DRZq5Vejr2ZfnclBUb2vtxaXywTRW8oueaaq9flcShEQ/cQ+KRU8sc344qd0=
+alligator.testzone.nlnetlabs.nl. 3600 IN NSEC cheetah.testzone.nlnetlabs.nl. TXT RRSIG NSEC
+alligator.testzone.nlnetlabs.nl. 3600 IN RRSIG NSEC 8 4 3600 20180313102201 20180213102201 44940 testzone.nlnetlabs.nl. QAgQ0AsMoYG02+VPfoOctSPlTHdQOkQt5fFkSkzIbVhUzNOqa+dB/Qkc81AwFeJosA+PvYjt6utcVkIWmK2Djy9eXC49gILtVF79vUe4G7ZrybO5NXjqNa5ANoUGM+yew4wkjeNOMVAsvs+1kvFY7S8RAa/0AIYlZHQ8vNBPNaI=
+testzone.nlnetlabs.nl. 3600 IN SOA ns.nlnetlabs.nl. ralph.nlnetlabs.nl. 1 14400 3600 604800 3600
+testzone.nlnetlabs.nl. 3600 IN RRSIG SOA 8 3 3600 20180313102201 20180213102201 44940 testzone.nlnetlabs.nl. GhmXNFQktZIgaBpGKwj9Q2mfq5+jcbRPK+PPgtRVicUPZga/d/iGEL8PV/8DzGwkaZbM14pamSUMgdJibW4zNhLz/ukjPilbjoj6giH1jtbdZLAQ6iK9pZ/4jKUEq4txviTczZNnDeolgPEEl4xo4NclQmi7zj1XBlQRbjvG0/0=
+ENTRY_END
+
+SCENARIO_END
diff --git a/testdata/val_nodata_failwc.rpl b/testdata/val_nodata_failwc.rpl
new file mode 100644
index 000000000000..4e4a7c30881c
--- /dev/null
+++ b/testdata/val_nodata_failwc.rpl
@@ -0,0 +1,71 @@
+; config options
+; The island of trust is at nsecwc.nlnetlabs.nl
+server:
+ trust-anchor: "nsecwc.nlnetlabs.nl. 10024 IN DS 565 8 2 0C15C04C022700C8713028F6F64CF2343DE627B8F83CDA1C421C65DB 52908A2E"
+ val-override-date: "20181202115531"
+ target-fetch-policy: "0 0 0 0 0"
+ fake-sha1: yes
+ trust-anchor-signaling: no
+stub-zone:
+ name: "nsecwc.nlnetlabs.nl"
+ stub-addr: "185.49.140.60"
+
+CONFIG_END
+
+SCENARIO_BEGIN Test validator with nodata response with wildcard expanded NSEC record, original NSEC owner does not provide proof for QNAME. CVE-2017-15105 test.
+
+ ; ns.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 185.49.140.60
+
+; response to DNSKEY priming query
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+nsecwc.nlnetlabs.nl. IN DNSKEY
+SECTION ANSWER
+nsecwc.nlnetlabs.nl. 3600 IN DNSKEY 257 3 8 AwEAAbTluF4BfJ/FT7Ak5a3VvYG1AqhT8FXxOsVwGTyueyE/hW+fMFMd QlLMf2Lf/gmsnFgn/p7GDmJBLlPTATmLeP3isvAZbK3MDEP2O5UjTVmt LZriTv8xfxYW6emCM54EQjWii64BFWrOeLm9zQqzyaLl53CbIIXqiacV KPteh8GX
+nsecwc.nlnetlabs.nl. 3600 IN RRSIG DNSKEY 8 3 3600 20200101000000 20171108114635 565 nsecwc.nlnetlabs.nl. q3bG4e8EtvXKDcNWcyYHeQxLF9l9aJKdmeSubyN6Qc3UVHugd6t3YSxD hlD+g43y7FcdnNHdAPh/jpgC4wtOb5J+5XAuESDHwesmIXOCTJjrb+A8 r+xQK+vsY8FhNZ2r81JZ/KQ/+TcCS5tbYeNZQgENduWAxgGiw3fdrMOV xiU=
+ENTRY_END
+
+; response to query of interest
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+_25._tcp.mail.nsecwc.nlnetlabs.nl. IN TLSA
+SECTION ANSWER
+SECTION AUTHORITY
+nsecwc.nlnetlabs.nl. 3600 IN SOA ns.nlnetlabs.nl. ralph.nlnetlabs.nl. 1 14400 3600 604800 3600
+nsecwc.nlnetlabs.nl. 3600 IN RRSIG SOA 8 3 3600 20200101000000 20171108114635 565 nsecwc.nlnetlabs.nl. bYibpCDg1LgrnYJgVahgu94LBqLIcNs4iC0SW8LV7pTI1hhuFKbLkO2O ekPdkJAWmu/KTytf8D+cdcK6X/9VS8QCVIF5S0hraHtNezu0f1B5ztg3 7Rqy+uJSucNKoykueAsz2z43GMgO0rGH3bqM7+3ii8p2E2rhzqEtG/D3 qyY=
+; NSEC has a label lenght of 3, indication that the original owner name is:
+; *.nsecwc.nlnetlabs.nl. The NSEC therefore does no prove the NODATA answer.
+_25._tcp.mail.nsecwc.nlnetlabs.nl. 3600 IN NSEC delegation.nsecwc.nlnetlabs.nl. TXT RRSIG NSEC
+_25._tcp.mail.nsecwc.nlnetlabs.nl. 3600 IN RRSIG NSEC 8 3 3600 20200101000000 20171108114635 565 nsecwc.nlnetlabs.nl. ddy1MRbshFuFJswlouNGHsZUF/tYu8BOCztY2JuHeTMyWL7rhRKp73q/ 1RAXMwywKsynT5ioY0bMtEQszeIEn29IYaPDHieLAobjF6BMu1kO7U2/ oEBrSHM/fx28BcaM5G4nfCIm3BlhQhWvk1NDHLn3Q26x4hF/dnmFOUet aXw=
+SECTION ADDITIONAL
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+_25._tcp.mail.nsecwc.nlnetlabs.nl. IN TLSA
+ENTRY_END
+
+; recursion happens here.
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA DO SERVFAIL
+SECTION QUESTION
+_25._tcp.mail.nsecwc.nlnetlabs.nl. IN TLSA
+SECTION ANSWER
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+
+SCENARIO_END
diff --git a/testdata/val_nx_failwc.rpl b/testdata/val_nx_failwc.rpl
new file mode 100644
index 000000000000..dc580854cbb4
--- /dev/null
+++ b/testdata/val_nx_failwc.rpl
@@ -0,0 +1,69 @@
+; config options
+; The island of trust is at nsecwc.nlnetlabs.nl
+server:
+ trust-anchor: "nsecwc.nlnetlabs.nl. 10024 IN DS 565 8 2 0C15C04C022700C8713028F6F64CF2343DE627B8F83CDA1C421C65DB 52908A2E"
+ val-override-date: "20181202115531"
+ target-fetch-policy: "0 0 0 0 0"
+ fake-sha1: yes
+ trust-anchor-signaling: no
+stub-zone:
+ name: "nsecwc.nlnetlabs.nl"
+ stub-addr: "185.49.140.60"
+
+CONFIG_END
+
+SCENARIO_BEGIN Test validator with nxdomain response with wildcard expanded NSEC record, original NSEC owner does not provide proof for QNAME. CVE-2017-15105 test.
+
+ ; ns.example.com.
+RANGE_BEGIN 0 100
+ ADDRESS 185.49.140.60
+
+; response to DNSKEY priming query
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+nsecwc.nlnetlabs.nl. IN DNSKEY
+SECTION ANSWER
+nsecwc.nlnetlabs.nl. 3600 IN DNSKEY 257 3 8 AwEAAbTluF4BfJ/FT7Ak5a3VvYG1AqhT8FXxOsVwGTyueyE/hW+fMFMd QlLMf2Lf/gmsnFgn/p7GDmJBLlPTATmLeP3isvAZbK3MDEP2O5UjTVmt LZriTv8xfxYW6emCM54EQjWii64BFWrOeLm9zQqzyaLl53CbIIXqiacV KPteh8GX
+nsecwc.nlnetlabs.nl. 3600 IN RRSIG DNSKEY 8 3 3600 20200101000000 20171108114635 565 nsecwc.nlnetlabs.nl. q3bG4e8EtvXKDcNWcyYHeQxLF9l9aJKdmeSubyN6Qc3UVHugd6t3YSxD hlD+g43y7FcdnNHdAPh/jpgC4wtOb5J+5XAuESDHwesmIXOCTJjrb+A8 r+xQK+vsY8FhNZ2r81JZ/KQ/+TcCS5tbYeNZQgENduWAxgGiw3fdrMOV xiU=
+ENTRY_END
+
+; response to query of interest
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NXDOMAIN
+SECTION QUESTION
+a.nsecwc.nlnetlabs.nl. IN TXT
+SECTION ANSWER
+SECTION AUTHORITY
+!.nsecwc.nlnetlabs.nl. 3600 IN NSEC delegation.nsecwc.nlnetlabs.nl. TXT RRSIG NSEC
+!.nsecwc.nlnetlabs.nl. 3600 IN RRSIG NSEC 8 3 3600 20200101000000 20171108114635 565 nsecwc.nlnetlabs.nl. ddy1MRbshFuFJswlouNGHsZUF/tYu8BOCztY2JuHeTMyWL7rhRKp73q/ 1RAXMwywKsynT5ioY0bMtEQszeIEn29IYaPDHieLAobjF6BMu1kO7U2/ oEBrSHM/fx28BcaM5G4nfCIm3BlhQhWvk1NDHLn3Q26x4hF/dnmFOUet aXw=
+nsecwc.nlnetlabs.nl. 3600 IN SOA ns.nlnetlabs.nl. ralph.nlnetlabs.nl. 1 14400 3600 604800 3600
+nsecwc.nlnetlabs.nl. 3600 IN RRSIG SOA 8 3 3600 20200101000000 20171108114635 565 nsecwc.nlnetlabs.nl. bYibpCDg1LgrnYJgVahgu94LBqLIcNs4iC0SW8LV7pTI1hhuFKbLkO2O ekPdkJAWmu/KTytf8D+cdcK6X/9VS8QCVIF5S0hraHtNezu0f1B5ztg3 7Rqy+uJSucNKoykueAsz2z43GMgO0rGH3bqM7+3ii8p2E2rhzqEtG/D3 qyY=
+SECTION ADDITIONAL
+ENTRY_END
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD DO
+SECTION QUESTION
+a.nsecwc.nlnetlabs.nl. IN TXT
+ENTRY_END
+
+; recursion happens here.
+STEP 10 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA DO SERVFAIL
+SECTION QUESTION
+a.nsecwc.nlnetlabs.nl. IN TXT
+SECTION ANSWER
+SECTION AUTHORITY
+SECTION ADDITIONAL
+ENTRY_END
+
+SCENARIO_END
diff --git a/util/config_file.c b/util/config_file.c
index ae3b6682ebf5..0784f055912d 100644
--- a/util/config_file.c
+++ b/util/config_file.c
@@ -108,6 +108,7 @@ config_create(void)
cfg->ssl_service_pem = NULL;
cfg->ssl_port = 853;
cfg->ssl_upstream = 0;
+ cfg->tls_cert_bundle = NULL;
cfg->use_syslog = 1;
cfg->log_identity = NULL; /* changed later with argv[0] */
cfg->log_time_ascii = 0;
@@ -177,6 +178,7 @@ config_create(void)
cfg->out_ifs = NULL;
cfg->stubs = NULL;
cfg->forwards = NULL;
+ cfg->auths = NULL;
#ifdef CLIENT_SUBNET
cfg->client_subnet = NULL;
cfg->client_subnet_zone = NULL;
@@ -219,6 +221,7 @@ config_create(void)
cfg->val_log_level = 0;
cfg->val_log_squelch = 0;
cfg->val_permissive_mode = 0;
+ cfg->aggressive_nsec = 0;
cfg->ignore_cd = 0;
cfg->serve_expired = 0;
cfg->add_holddown = 30*24*3600;
@@ -282,6 +285,7 @@ config_create(void)
cfg->dnscrypt_port = 0;
cfg->dnscrypt_provider = NULL;
cfg->dnscrypt_provider_cert = NULL;
+ cfg->dnscrypt_provider_cert_rotated = NULL;
cfg->dnscrypt_secret_key = NULL;
cfg->dnscrypt_shared_secret_cache_size = 4*1024*1024;
cfg->dnscrypt_shared_secret_cache_slabs = 4;
@@ -374,6 +378,10 @@ struct config_file* config_create_forlib(void)
/** put string into strlist */
#define S_STRLIST(str, var) if(strcmp(opt, str)==0) \
{ return cfg_strlist_insert(&cfg->var, strdup(val)); }
+/** put string into strlist if not present yet*/
+#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)); }
int config_set_option(struct config_file* cfg, const char* opt,
const char* val)
@@ -437,6 +445,7 @@ int config_set_option(struct config_file* cfg, const char* opt,
else S_STR("ssl-service-key:", ssl_service_key)
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("interface-automatic:", if_automatic)
else S_YNO("use-systemd:", use_systemd)
else S_YNO("do-daemonize:", do_daemonize)
@@ -513,6 +522,7 @@ int config_set_option(struct config_file* cfg, const char* opt,
else S_YNO("log-queries:", log_queries)
else S_YNO("log-replies:", log_replies)
else S_YNO("val-permissive-mode:", val_permissive_mode)
+ else S_YNO("aggressive-nsec:", aggressive_nsec)
else S_YNO("ignore-cd-flag:", ignore_cd)
else S_YNO("serve-expired:", serve_expired)
else S_STR("val-nsec3-keysize-iterations:", val_nsec3_key_iterations)
@@ -570,8 +580,9 @@ int config_set_option(struct config_file* cfg, const char* opt,
else S_YNO("dnscrypt-enable:", dnscrypt)
else S_NUMBER_NONZERO("dnscrypt-port:", dnscrypt_port)
else S_STR("dnscrypt-provider:", dnscrypt_provider)
- else S_STRLIST("dnscrypt-provider-cert:", dnscrypt_provider_cert)
- else S_STRLIST("dnscrypt-secret-key:", dnscrypt_secret_key)
+ else S_STRLIST_UNIQ("dnscrypt-provider-cert:", dnscrypt_provider_cert)
+ else S_STRLIST("dnscrypt-provider-cert-rotated:", dnscrypt_provider_cert_rotated)
+ else S_STRLIST_UNIQ("dnscrypt-secret-key:", dnscrypt_secret_key)
else S_MEMSIZE("dnscrypt-shared-secret-cache-size:",
dnscrypt_shared_secret_cache_size)
else S_POW2("dnscrypt-shared-secret-cache-slabs:",
@@ -628,7 +639,7 @@ int config_set_option(struct config_file* cfg, const char* opt,
* interface, outgoing-interface, access-control,
* stub-zone, name, stub-addr, stub-host, stub-prime
* forward-first, stub-first, forward-ssl-upstream,
- * stub-ssl-upstream, forward-zone,
+ * stub-ssl-upstream, forward-zone, auth-zone
* name, forward-addr, forward-host,
* ratelimit-for-domain, ratelimit-below-domain,
* local-zone-tag, access-control-view,
@@ -844,6 +855,7 @@ config_get_option(struct config_file* cfg, const char* opt,
else O_STR(opt, "ssl-service-key", ssl_service_key)
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, "use-systemd", use_systemd)
else O_YNO(opt, "do-daemonize", do_daemonize)
else O_STR(opt, "chroot", chrootdir)
@@ -876,6 +888,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, "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)
@@ -941,6 +954,7 @@ config_get_option(struct config_file* cfg, const char* opt,
else O_DEC(opt, "dnscrypt-port", dnscrypt_port)
else O_STR(opt, "dnscrypt-provider", dnscrypt_provider)
else O_LST(opt, "dnscrypt-provider-cert", dnscrypt_provider_cert)
+ else O_LST(opt, "dnscrypt-provider-cert-rotated", dnscrypt_provider_cert_rotated)
else O_LST(opt, "dnscrypt-secret-key", dnscrypt_secret_key)
else O_MEM(opt, "dnscrypt-shared-secret-cache-size",
dnscrypt_shared_secret_cache_size)
@@ -1158,6 +1172,28 @@ config_deltrplstrlist(struct config_str3list* p)
}
void
+config_delauth(struct config_auth* p)
+{
+ if(!p) return;
+ free(p->name);
+ config_delstrlist(p->masters);
+ config_delstrlist(p->urls);
+ free(p->zonefile);
+ free(p);
+}
+
+void
+config_delauths(struct config_auth* p)
+{
+ struct config_auth* np;
+ while(p) {
+ np = p->next;
+ config_delauth(p);
+ p = np;
+ }
+}
+
+void
config_delstub(struct config_stub* p)
{
if(!p) return;
@@ -1237,11 +1273,13 @@ config_delete(struct config_file* cfg)
free(cfg->target_fetch_policy);
free(cfg->ssl_service_key);
free(cfg->ssl_service_pem);
+ free(cfg->tls_cert_bundle);
free(cfg->log_identity);
config_del_strarray(cfg->ifs, cfg->num_ifs);
config_del_strarray(cfg->out_ifs, cfg->num_out_ifs);
config_delstubs(cfg->stubs);
config_delstubs(cfg->forwards);
+ config_delauths(cfg->auths);
config_delviews(cfg->views);
config_delstrlist(cfg->donotqueryaddrs);
config_delstrlist(cfg->root_hints);
@@ -1458,6 +1496,22 @@ cfg_region_strlist_insert(struct regional* region,
return 1;
}
+struct config_strlist*
+cfg_strlist_find(struct config_strlist* head, const char *item)
+{
+ struct config_strlist *s = head;
+ if(!head){
+ return NULL;
+ }
+ while(s) {
+ if(strcmp(s-&