mirror of
https://github.com/opnsense/src.git
synced 2026-06-08 16:22:46 -04:00
Vendor import of Unbound 1.6.2.
This commit is contained in:
parent
fbdb9ac866
commit
6cacf549d3
331 changed files with 16781 additions and 4016 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -7,6 +7,7 @@
|
|||
/config.log
|
||||
/config.status
|
||||
/dnstap/dnstap_config.h
|
||||
/dnscrypt/dnscrypt_config.h
|
||||
/doc/example.conf
|
||||
/doc/libunbound.3
|
||||
/doc/unbound-anchor.8
|
||||
|
|
|
|||
513
Makefile.in
513
Makefile.in
|
|
@ -23,6 +23,8 @@ CHECKLOCK_SRC=testcode/checklocks.c
|
|||
CHECKLOCK_OBJ=@CHECKLOCK_OBJ@
|
||||
DNSTAP_SRC=@DNSTAP_SRC@
|
||||
DNSTAP_OBJ=@DNSTAP_OBJ@
|
||||
DNSCRYPT_SRC=@DNSCRYPT_SRC@
|
||||
DNSCRYPT_OBJ=@DNSCRYPT_OBJ@
|
||||
WITH_PYTHONMODULE=@WITH_PYTHONMODULE@
|
||||
WITH_PYUNBOUND=@WITH_PYUNBOUND@
|
||||
PY_MAJOR_VERSION=@PY_MAJOR_VERSION@
|
||||
|
|
@ -95,6 +97,9 @@ PYTHONMOD_HEADER=@PYTHONMOD_HEADER@
|
|||
PYUNBOUND_SRC=
|
||||
# libunbound_wrap.lo if python libunbound wrapper enabled.
|
||||
PYUNBOUND_OBJ=@PYUNBOUND_OBJ@
|
||||
SUBNET_SRC=edns-subnet/edns-subnet.c edns-subnet/subnetmod.c edns-subnet/addrtree.c edns-subnet/subnet-whitelist.c
|
||||
SUBNET_OBJ=@SUBNET_OBJ@
|
||||
SUBNET_HEADER=@SUBNET_HEADER@
|
||||
COMMON_SRC=services/cache/dns.c services/cache/infra.c services/cache/rrset.c \
|
||||
util/as112.c util/data/dname.c util/data/msgencode.c util/data/msgparse.c \
|
||||
util/data/msgreply.c util/data/packed_rrset.c iterator/iterator.c \
|
||||
|
|
@ -104,6 +109,7 @@ iterator/iter_scrub.c iterator/iter_utils.c services/listen_dnsport.c \
|
|||
services/localzone.c services/mesh.c services/modstack.c services/view.c \
|
||||
services/outbound_list.c services/outside_network.c util/alloc.c \
|
||||
util/config_file.c util/configlexer.c util/configparser.c \
|
||||
util/shm_side/shm_main.c \
|
||||
util/fptr_wlist.c util/locks.c util/log.c util/mini_event.c util/module.c \
|
||||
util/netevent.c util/net_help.c util/random.c util/rbtree.c util/regional.c \
|
||||
util/rtt.c util/storage/dnstree.c util/storage/lookup3.c \
|
||||
|
|
@ -112,8 +118,11 @@ util/ub_event.c util/ub_event_pluggable.c util/winsock_event.c \
|
|||
validator/autotrust.c validator/val_anchor.c validator/validator.c \
|
||||
validator/val_kcache.c validator/val_kentry.c validator/val_neg.c \
|
||||
validator/val_nsec3.c validator/val_nsec.c validator/val_secalgo.c \
|
||||
validator/val_sigcrypt.c validator/val_utils.c dns64/dns64.c cachedb/cachedb.c $(CHECKLOCK_SRC) \
|
||||
$(DNSTAP_SRC)
|
||||
validator/val_sigcrypt.c validator/val_utils.c dns64/dns64.c \
|
||||
edns-subnet/edns-subnet.c edns-subnet/subnetmod.c \
|
||||
edns-subnet/addrtree.c edns-subnet/subnet-whitelist.c \
|
||||
cachedb/cachedb.c respip/respip.c $(CHECKLOCK_SRC) \
|
||||
$(DNSTAP_SRC) $(DNSCRYPT_SRC)
|
||||
COMMON_OBJ_WITHOUT_NETCALL=dns.lo infra.lo rrset.lo dname.lo msgencode.lo \
|
||||
as112.lo msgparse.lo msgreply.lo packed_rrset.lo iterator.lo iter_delegpt.lo \
|
||||
iter_donotq.lo iter_fwd.lo iter_hints.lo iter_priv.lo iter_resptype.lo \
|
||||
|
|
@ -124,7 +133,8 @@ random.lo rbtree.lo regional.lo rtt.lo dnstree.lo lookup3.lo lruhash.lo \
|
|||
slabhash.lo timehist.lo tube.lo winsock_event.lo autotrust.lo val_anchor.lo \
|
||||
validator.lo val_kcache.lo val_kentry.lo val_neg.lo val_nsec3.lo val_nsec.lo \
|
||||
val_secalgo.lo val_sigcrypt.lo val_utils.lo dns64.lo cachedb.lo \
|
||||
$(PYTHONMOD_OBJ) $(CHECKLOCK_OBJ) $(DNSTAP_OBJ)
|
||||
$(SUBNET_OBJ) $(PYTHONMOD_OBJ) $(CHECKLOCK_OBJ) $(DNSTAP_OBJ) $(DNSCRYPT_OBJ)
|
||||
COMMON_OBJ_WITHOUT_NETCALL+=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
|
||||
|
|
@ -148,15 +158,16 @@ str2wire.lo
|
|||
UNITTEST_SRC=testcode/unitanchor.c testcode/unitdname.c \
|
||||
testcode/unitlruhash.c testcode/unitmain.c testcode/unitmsgparse.c \
|
||||
testcode/unitneg.c testcode/unitregional.c testcode/unitslabhash.c \
|
||||
testcode/unitverify.c testcode/readhex.c testcode/testpkts.c testcode/unitldns.c
|
||||
testcode/unitverify.c testcode/readhex.c testcode/testpkts.c testcode/unitldns.c \
|
||||
testcode/unitecs.c
|
||||
UNITTEST_OBJ=unitanchor.lo unitdname.lo unitlruhash.lo unitmain.lo \
|
||||
unitmsgparse.lo unitneg.lo unitregional.lo unitslabhash.lo unitverify.lo \
|
||||
readhex.lo testpkts.lo unitldns.lo
|
||||
readhex.lo testpkts.lo unitldns.lo unitecs.lo
|
||||
UNITTEST_OBJ_LINK=$(UNITTEST_OBJ) worker_cb.lo $(COMMON_OBJ) $(SLDNS_OBJ) \
|
||||
$(COMPAT_OBJ)
|
||||
DAEMON_SRC=daemon/acl_list.c daemon/cachedump.c daemon/daemon.c \
|
||||
daemon/remote.c daemon/stats.c daemon/unbound.c daemon/worker.c @WIN_DAEMON_SRC@
|
||||
DAEMON_OBJ=acl_list.lo cachedump.lo daemon.lo remote.lo stats.lo unbound.lo \
|
||||
DAEMON_OBJ=acl_list.lo cachedump.lo daemon.lo shm_main.lo remote.lo stats.lo unbound.lo \
|
||||
worker.lo @WIN_DAEMON_OBJ@
|
||||
DAEMON_OBJ_LINK=$(DAEMON_OBJ) $(COMMON_OBJ_ALL_SYMBOLS) $(SLDNS_OBJ) \
|
||||
$(COMPAT_OBJ) @WIN_DAEMON_OBJ_LINK@
|
||||
|
|
@ -180,7 +191,7 @@ daemon/worker.c daemon/acl_list.c daemon/daemon.c daemon/stats.c \
|
|||
testcode/replay.c testcode/fake_event.c
|
||||
TESTBOUND_OBJ=testbound.lo replay.lo fake_event.lo
|
||||
TESTBOUND_OBJ_LINK=$(TESTBOUND_OBJ) testpkts.lo worker.lo acl_list.lo \
|
||||
daemon.lo stats.lo $(COMMON_OBJ_WITHOUT_NETCALL) ub_event.lo $(SLDNS_OBJ) \
|
||||
daemon.lo stats.lo shm_main.lo $(COMMON_OBJ_WITHOUT_NETCALL) ub_event.lo $(SLDNS_OBJ) \
|
||||
$(COMPAT_OBJ)
|
||||
LOCKVERIFY_SRC=testcode/lock_verify.c
|
||||
LOCKVERIFY_OBJ=lock_verify.lo
|
||||
|
|
@ -379,6 +390,13 @@ dnstap/dnstap.pb-c.c dnstap/dnstap.pb-c.h: $(srcdir)/dnstap/dnstap.proto
|
|||
|
||||
dnstap.pb-c.lo dnstap.pb-c.o: dnstap/dnstap.pb-c.c dnstap/dnstap.pb-c.h
|
||||
|
||||
# dnscrypt
|
||||
dnscrypt.lo dnscrypt.o: $(srcdir)/dnscrypt/dnscrypt.c config.h \
|
||||
dnscrypt/dnscrypt_config.h \
|
||||
$(srcdir)/dnscrypt/dnscrypt.h $(srcdir)/dnscrypt/cert.h \
|
||||
$(srcdir)/util/config_file.h $(srcdir)/util/log.h \
|
||||
$(srcdir)/util/netevent.h
|
||||
|
||||
# Python Module
|
||||
pythonmod.lo pythonmod.o: $(srcdir)/pythonmod/pythonmod.c config.h \
|
||||
pythonmod/interface.h \
|
||||
|
|
@ -584,7 +602,9 @@ depend:
|
|||
-e 's?$$(srcdir)/util/configparser.c?util/configparser.c?g' \
|
||||
-e 's?$$(srcdir)/util/configparser.h?util/configparser.h?g' \
|
||||
-e 's?$$(srcdir)/dnstap/dnstap_config.h??g' \
|
||||
-e 's?$$(srcdir)/dnscrypt/dnscrypt_config.h??g' \
|
||||
-e 's?$$(srcdir)/pythonmod/pythonmod.h?$$(PYTHONMOD_HEADER)?g' \
|
||||
-e 's?$$(srcdir)/edns-subnet/subnetmod.h $$(srcdir)/edns-subnet/subnet-whitelist.h $$(srcdir)/edns-subnet/edns-subnet.h $$(srcdir)/edns-subnet/addrtree.h?$$(SUBNET_HEADER)?g' \
|
||||
-e 's!\(.*\)\.o[ :]*!\1.lo \1.o: !g' \
|
||||
> $(DEPEND_TMP)
|
||||
cp $(DEPEND_TARGET) $(DEPEND_TMP2)
|
||||
|
|
@ -608,11 +628,12 @@ dns.lo dns.o: $(srcdir)/services/cache/dns.c config.h $(srcdir)/iterator/iter_de
|
|||
$(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/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/data/msgreply.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/module.h \
|
||||
$(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h
|
||||
$(srcdir)/util/storage/dnstree.h $(srcdir)/util/rbtree.h $(srcdir)/util/rtt.h $(srcdir)/util/netevent.h \
|
||||
$(srcdir)/dnscrypt/dnscrypt.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 \
|
||||
|
|
@ -634,11 +655,12 @@ msgparse.lo msgparse.o: $(srcdir)/util/data/msgparse.c config.h $(srcdir)/util/d
|
|||
$(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)/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/lookup3.h $(srcdir)/util/alloc.h $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.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 \
|
||||
|
|
@ -651,7 +673,8 @@ iterator.lo iterator.o: $(srcdir)/iterator/iterator.c config.h $(srcdir)/iterato
|
|||
$(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)/util/net_help.h $(srcdir)/util/regional.h \
|
||||
$(srcdir)/util/rtt.h $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.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/config_file.h $(srcdir)/util/random.h \
|
||||
$(srcdir)/sldns/wire2str.h $(srcdir)/sldns/str2wire.h $(srcdir)/sldns/parseutil.h $(srcdir)/sldns/sbuffer.h
|
||||
|
|
@ -695,40 +718,46 @@ iter_utils.lo iter_utils.o: $(srcdir)/iterator/iter_utils.c config.h $(srcdir)/i
|
|||
$(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)/services/cache/dns.h \
|
||||
$(srcdir)/services/cache/rrset.h $(srcdir)/util/storage/slabhash.h $(srcdir)/util/net_help.h \
|
||||
$(srcdir)/util/config_file.h $(srcdir)/util/regional.h $(srcdir)/util/data/dname.h $(srcdir)/util/random.h \
|
||||
$(srcdir)/util/fptr_wlist.h $(srcdir)/util/netevent.h $(srcdir)/util/tube.h $(srcdir)/services/mesh.h \
|
||||
$(srcdir)/services/modstack.h $(srcdir)/validator/val_anchor.h $(srcdir)/validator/val_kcache.h \
|
||||
$(srcdir)/validator/val_kentry.h $(srcdir)/validator/val_utils.h $(srcdir)/validator/val_sigcrypt.h \
|
||||
$(srcdir)/sldns/sbuffer.h $(srcdir)/sldns/str2wire.h
|
||||
$(srcdir)/services/cache/infra.h $(srcdir)/util/rtt.h $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
|
||||
$(srcdir)/services/cache/dns.h $(srcdir)/services/cache/rrset.h \
|
||||
$(srcdir)/util/storage/slabhash.h $(srcdir)/util/net_help.h $(srcdir)/util/config_file.h \
|
||||
$(srcdir)/util/regional.h $(srcdir)/util/data/dname.h $(srcdir)/util/random.h $(srcdir)/util/fptr_wlist.h \
|
||||
$(srcdir)/util/tube.h $(srcdir)/services/mesh.h $(srcdir)/services/modstack.h $(srcdir)/validator/val_anchor.h \
|
||||
$(srcdir)/validator/val_kcache.h $(srcdir)/validator/val_kentry.h $(srcdir)/validator/val_utils.h \
|
||||
$(srcdir)/validator/val_sigcrypt.h $(srcdir)/sldns/sbuffer.h $(srcdir)/sldns/str2wire.h
|
||||
listen_dnsport.lo listen_dnsport.o: $(srcdir)/services/listen_dnsport.c config.h \
|
||||
$(srcdir)/services/listen_dnsport.h $(srcdir)/util/netevent.h $(srcdir)/services/outside_network.h \
|
||||
$(srcdir)/util/rbtree.h $(srcdir)/util/log.h $(srcdir)/util/config_file.h \
|
||||
$(srcdir)/util/net_help.h $(srcdir)/sldns/sbuffer.h
|
||||
$(srcdir)/services/listen_dnsport.h $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
|
||||
$(srcdir)/services/outside_network.h $(srcdir)/util/rbtree.h \
|
||||
$(srcdir)/util/log.h $(srcdir)/util/config_file.h $(srcdir)/util/net_help.h \
|
||||
$(srcdir)/sldns/sbuffer.h
|
||||
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/data/msgencode.h $(srcdir)/util/net_help.h $(srcdir)/util/netevent.h $(srcdir)/util/as112.h
|
||||
$(srcdir)/util/data/msgencode.h $(srcdir)/util/net_help.h $(srcdir)/util/netevent.h \
|
||||
$(srcdir)/dnscrypt/dnscrypt.h $(srcdir)/util/as112.h
|
||||
mesh.lo mesh.o: $(srcdir)/services/mesh.c config.h $(srcdir)/services/mesh.h $(srcdir)/util/rbtree.h \
|
||||
$(srcdir)/util/netevent.h $(srcdir)/util/data/msgparse.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h \
|
||||
$(srcdir)/util/log.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/module.h \
|
||||
$(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/services/modstack.h \
|
||||
$(srcdir)/services/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)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
|
||||
$(srcdir)/util/data/msgparse.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \
|
||||
$(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/module.h $(srcdir)/util/data/msgreply.h \
|
||||
$(srcdir)/util/data/packed_rrset.h $(srcdir)/services/modstack.h $(srcdir)/services/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)/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 $(PYTHONMOD_HEADER)
|
||||
$(srcdir)/dnscrypt/dnscrypt.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 $(srcdir)/edns-subnet/subnetmod.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
|
||||
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 \
|
||||
|
|
@ -736,19 +765,22 @@ view.lo view.o: $(srcdir)/services/view.c config.h $(srcdir)/services/view.h $(s
|
|||
$(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)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.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)/services/listen_dnsport.h $(srcdir)/services/cache/infra.h \
|
||||
$(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/storage/dnstree.h \
|
||||
$(srcdir)/util/rtt.h $(srcdir)/util/data/msgparse.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/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)/dnscrypt/dnscrypt.h \
|
||||
$(srcdir)/services/listen_dnsport.h $(srcdir)/services/cache/infra.h $(srcdir)/util/storage/lruhash.h \
|
||||
$(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/storage/dnstree.h $(srcdir)/util/rtt.h \
|
||||
$(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/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)/util/module.h $(srcdir)/util/data/msgreply.h \
|
||||
$(srcdir)/util/fptr_wlist.h $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.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 \
|
||||
|
|
@ -756,45 +788,61 @@ config_file.lo config_file.o: $(srcdir)/util/config_file.c config.h $(srcdir)/ut
|
|||
$(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)/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/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
|
||||
$(srcdir)/util/tube.h $(srcdir)/services/mesh.h $(srcdir)/util/rbtree.h $(srcdir)/services/modstack.h \
|
||||
$(srcdir)/util/data/dname.h $(srcdir)/util/rtt.h $(srcdir)/services/cache/infra.h \
|
||||
$(srcdir)/util/storage/dnstree.h $(srcdir)/sldns/wire2str.h $(srcdir)/sldns/parseutil.h \
|
||||
$(srcdir)/util/iana_ports.inc
|
||||
$(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)/daemon/daemon.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/alloc.h $(srcdir)/services/modstack.h \
|
||||
$(srcdir)/daemon/worker.h \
|
||||
$(srcdir)/libunbound/worker.h $(srcdir)/sldns/sbuffer.h $(srcdir)/util/data/packed_rrset.h \
|
||||
$(srcdir)/util/storage/lruhash.h $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
|
||||
$(srcdir)/util/data/msgreply.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h \
|
||||
$(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h $(srcdir)/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
|
||||
fptr_wlist.lo fptr_wlist.o: $(srcdir)/util/fptr_wlist.c config.h $(srcdir)/util/fptr_wlist.h \
|
||||
$(srcdir)/util/netevent.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \
|
||||
$(srcdir)/util/module.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h \
|
||||
$(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/tube.h \
|
||||
$(srcdir)/services/mesh.h $(srcdir)/util/rbtree.h $(srcdir)/services/modstack.h $(srcdir)/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/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 $(PYTHONMOD_HEADER)
|
||||
$(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
|
||||
$(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/module.h \
|
||||
$(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgparse.h \
|
||||
$(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/tube.h $(srcdir)/services/mesh.h $(srcdir)/util/rbtree.h \
|
||||
$(srcdir)/services/modstack.h $(srcdir)/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/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 \
|
||||
$(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)/util/storage/lruhash.h $(srcdir)/util/locks.h \
|
||||
$(srcdir)/util/fptr_wlist.h $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
|
||||
$(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h \
|
||||
$(srcdir)/util/log.h $(srcdir)/util/module.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h \
|
||||
$(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/tube.h \
|
||||
$(srcdir)/services/mesh.h $(srcdir)/util/rbtree.h $(srcdir)/services/modstack.h
|
||||
module.lo module.o: $(srcdir)/util/module.c config.h $(srcdir)/util/module.h $(srcdir)/util/storage/lruhash.h \
|
||||
$(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h \
|
||||
$(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/sldns/wire2str.h
|
||||
netevent.lo netevent.o: $(srcdir)/util/netevent.c config.h $(srcdir)/util/netevent.h $(srcdir)/util/ub_event.h \
|
||||
$(srcdir)/util/log.h $(srcdir)/util/net_help.h $(srcdir)/util/fptr_wlist.h $(srcdir)/util/storage/lruhash.h \
|
||||
$(srcdir)/util/locks.h $(srcdir)/util/module.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h \
|
||||
$(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/tube.h \
|
||||
$(srcdir)/services/mesh.h $(srcdir)/util/rbtree.h $(srcdir)/services/modstack.h $(srcdir)/sldns/sbuffer.h \
|
||||
$(srcdir)/dnstap/dnstap.h
|
||||
netevent.lo netevent.o: $(srcdir)/util/netevent.c config.h $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
|
||||
$(srcdir)/util/ub_event.h $(srcdir)/util/log.h $(srcdir)/util/net_help.h \
|
||||
$(srcdir)/util/fptr_wlist.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/module.h \
|
||||
$(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgparse.h \
|
||||
$(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/tube.h $(srcdir)/services/mesh.h $(srcdir)/util/rbtree.h \
|
||||
$(srcdir)/services/modstack.h $(srcdir)/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 \
|
||||
|
|
@ -802,10 +850,11 @@ net_help.lo net_help.o: $(srcdir)/util/net_help.c config.h $(srcdir)/util/net_he
|
|||
$(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)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \
|
||||
$(srcdir)/util/module.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h \
|
||||
$(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/tube.h \
|
||||
$(srcdir)/services/mesh.h $(srcdir)/util/rbtree.h $(srcdir)/services/modstack.h
|
||||
$(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
|
||||
$(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/module.h \
|
||||
$(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgparse.h \
|
||||
$(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/tube.h $(srcdir)/services/mesh.h $(srcdir)/util/rbtree.h \
|
||||
$(srcdir)/services/modstack.h
|
||||
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 \
|
||||
|
|
@ -813,7 +862,8 @@ dnstree.lo dnstree.o: $(srcdir)/util/storage/dnstree.c config.h $(srcdir)/util/s
|
|||
$(srcdir)/util/log.h $(srcdir)/util/net_help.h
|
||||
lookup3.lo lookup3.o: $(srcdir)/util/storage/lookup3.c config.h $(srcdir)/util/storage/lookup3.h
|
||||
lruhash.lo lruhash.o: $(srcdir)/util/storage/lruhash.c config.h $(srcdir)/util/storage/lruhash.h \
|
||||
$(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/fptr_wlist.h $(srcdir)/util/netevent.h $(srcdir)/util/module.h \
|
||||
$(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/fptr_wlist.h $(srcdir)/util/netevent.h \
|
||||
$(srcdir)/dnscrypt/dnscrypt.h $(srcdir)/util/module.h \
|
||||
$(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgparse.h \
|
||||
$(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/tube.h $(srcdir)/services/mesh.h $(srcdir)/util/rbtree.h \
|
||||
$(srcdir)/services/modstack.h
|
||||
|
|
@ -821,14 +871,17 @@ slabhash.lo slabhash.o: $(srcdir)/util/storage/slabhash.c config.h $(srcdir)/uti
|
|||
$(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.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)/util/fptr_wlist.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h \
|
||||
$(srcdir)/util/module.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h \
|
||||
$(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/services/mesh.h \
|
||||
$(srcdir)/util/rbtree.h $(srcdir)/services/modstack.h $(srcdir)/util/ub_event.h
|
||||
$(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
|
||||
$(srcdir)/util/fptr_wlist.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/module.h \
|
||||
$(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgparse.h \
|
||||
$(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/services/mesh.h $(srcdir)/util/rbtree.h \
|
||||
$(srcdir)/services/modstack.h $(srcdir)/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)/util/tube.h $(srcdir)/util/mini_event.h $(srcdir)/util/rbtree.h
|
||||
$(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.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)/util/log.h $(srcdir)/util/fptr_wlist.h \
|
||||
$(srcdir)/libunbound/unbound-event.h $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
|
||||
$(srcdir)/util/log.h $(srcdir)/util/fptr_wlist.h \
|
||||
$(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/module.h $(srcdir)/util/data/msgreply.h \
|
||||
$(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h \
|
||||
$(srcdir)/sldns/rrdef.h $(srcdir)/util/tube.h $(srcdir)/services/mesh.h $(srcdir)/util/rbtree.h \
|
||||
|
|
@ -840,9 +893,10 @@ autotrust.lo autotrust.o: $(srcdir)/validator/autotrust.c config.h $(srcdir)/val
|
|||
$(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)/services/modstack.h \
|
||||
$(srcdir)/services/cache/rrset.h $(srcdir)/util/storage/slabhash.h $(srcdir)/validator/val_kcache.h \
|
||||
$(srcdir)/sldns/sbuffer.h $(srcdir)/sldns/wire2str.h $(srcdir)/sldns/str2wire.h $(srcdir)/sldns/keyraw.h
|
||||
$(srcdir)/services/mesh.h $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.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 \
|
||||
|
|
@ -857,8 +911,8 @@ validator.lo validator.o: $(srcdir)/validator/validator.c config.h $(srcdir)/val
|
|||
$(srcdir)/validator/val_nsec3.h $(srcdir)/validator/val_neg.h $(srcdir)/validator/val_sigcrypt.h \
|
||||
$(srcdir)/validator/autotrust.h $(srcdir)/services/cache/dns.h $(srcdir)/util/data/dname.h \
|
||||
$(srcdir)/util/net_help.h $(srcdir)/util/regional.h $(srcdir)/util/config_file.h $(srcdir)/util/fptr_wlist.h \
|
||||
$(srcdir)/util/netevent.h $(srcdir)/util/tube.h $(srcdir)/services/mesh.h $(srcdir)/services/modstack.h \
|
||||
$(srcdir)/sldns/wire2str.h
|
||||
$(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
|
||||
$(srcdir)/util/tube.h $(srcdir)/services/mesh.h $(srcdir)/services/modstack.h $(srcdir)/sldns/wire2str.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 \
|
||||
|
|
@ -895,8 +949,8 @@ val_sigcrypt.lo val_sigcrypt.o: $(srcdir)/validator/val_sigcrypt.c config.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)/sldns/keyraw.h $(srcdir)/sldns/sbuffer.h \
|
||||
$(srcdir)/sldns/parseutil.h $(srcdir)/sldns/wire2str.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 \
|
||||
|
|
@ -910,9 +964,37 @@ dns64.lo dns64.o: $(srcdir)/dns64/dns64.c config.h $(srcdir)/dns64/dns64.h $(src
|
|||
$(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)/util/tube.h $(srcdir)/services/mesh.h $(srcdir)/util/rbtree.h \
|
||||
$(srcdir)/services/modstack.h $(srcdir)/util/net_help.h $(srcdir)/util/regional.h
|
||||
$(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
|
||||
$(srcdir)/util/tube.h $(srcdir)/services/mesh.h $(srcdir)/util/rbtree.h $(srcdir)/services/modstack.h \
|
||||
$(srcdir)/util/net_help.h $(srcdir)/util/regional.h
|
||||
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)/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
|
||||
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
|
||||
cachedb.lo cachedb.o: $(srcdir)/cachedb/cachedb.c config.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/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 \
|
||||
$(srcdir)/testcode/checklocks.h
|
||||
unitanchor.lo unitanchor.o: $(srcdir)/testcode/unitanchor.c config.h $(srcdir)/util/log.h $(srcdir)/util/data/dname.h \
|
||||
|
|
@ -927,7 +1009,10 @@ unitmain.lo unitmain.o: $(srcdir)/testcode/unitmain.c config.h $(srcdir)/sldns/r
|
|||
$(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)/services/cache/infra.h \
|
||||
$(srcdir)/util/storage/lruhash.h $(srcdir)/util/storage/dnstree.h $(srcdir)/util/rbtree.h \
|
||||
$(srcdir)/util/random.h
|
||||
$(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.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 \
|
||||
|
|
@ -958,6 +1043,12 @@ testpkts.lo testpkts.o: $(srcdir)/testcode/testpkts.c config.h $(srcdir)/testcod
|
|||
$(srcdir)/sldns/str2wire.h $(srcdir)/sldns/wire2str.h
|
||||
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)/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
|
||||
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 \
|
||||
|
|
@ -967,68 +1058,72 @@ acl_list.lo acl_list.o: $(srcdir)/daemon/acl_list.c config.h $(srcdir)/daemon/ac
|
|||
cachedump.lo cachedump.o: $(srcdir)/daemon/cachedump.c config.h $(srcdir)/daemon/cachedump.h \
|
||||
$(srcdir)/daemon/remote.h $(srcdir)/daemon/worker.h $(srcdir)/libunbound/worker.h $(srcdir)/sldns/sbuffer.h \
|
||||
$(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \
|
||||
$(srcdir)/util/netevent.h $(srcdir)/util/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)/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/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
|
||||
$(srcdir)/util/alloc.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h \
|
||||
$(srcdir)/sldns/rrdef.h $(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h $(srcdir)/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)/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)/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/storage/lookup3.h \
|
||||
$(srcdir)/daemon/worker.h $(srcdir)/libunbound/worker.h \
|
||||
$(srcdir)/sldns/sbuffer.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h \
|
||||
$(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h $(srcdir)/util/data/msgreply.h \
|
||||
$(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/daemon/stats.h \
|
||||
$(srcdir)/util/timehist.h $(srcdir)/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)/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)/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)/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)/dnscrypt/dnscrypt.h $(srcdir)/util/alloc.h \
|
||||
$(srcdir)/util/data/msgreply.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h \
|
||||
$(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h $(srcdir)/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)/daemon/worker.h $(srcdir)/libunbound/worker.h $(srcdir)/sldns/sbuffer.h \
|
||||
$(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \
|
||||
$(srcdir)/util/netevent.h $(srcdir)/util/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)/services/cache/rrset.h \
|
||||
$(srcdir)/util/storage/slabhash.h $(srcdir)/services/cache/infra.h $(srcdir)/util/storage/dnstree.h \
|
||||
$(srcdir)/util/rtt.h $(srcdir)/validator/val_kcache.h
|
||||
$(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
|
||||
$(srcdir)/util/alloc.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h \
|
||||
$(srcdir)/sldns/rrdef.h $(srcdir)/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)/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/config_file.h $(srcdir)/util/storage/slabhash.h \
|
||||
$(srcdir)/util/storage/lruhash.h $(srcdir)/services/listen_dnsport.h $(srcdir)/util/netevent.h \
|
||||
$(srcdir)/services/cache/rrset.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/services/cache/infra.h \
|
||||
$(srcdir)/util/storage/dnstree.h $(srcdir)/util/rbtree.h $(srcdir)/util/rtt.h $(srcdir)/util/fptr_wlist.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/net_help.h \
|
||||
$(srcdir)/util/ub_event.h
|
||||
$(srcdir)/daemon/remote.h $(srcdir)/util/config_file.h \
|
||||
$(srcdir)/util/storage/slabhash.h $(srcdir)/util/storage/lruhash.h $(srcdir)/services/listen_dnsport.h \
|
||||
$(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h $(srcdir)/services/cache/rrset.h \
|
||||
$(srcdir)/util/data/packed_rrset.h $(srcdir)/services/cache/infra.h $(srcdir)/util/storage/dnstree.h \
|
||||
$(srcdir)/util/rbtree.h $(srcdir)/util/rtt.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/fptr_wlist.h \
|
||||
$(srcdir)/util/module.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h \
|
||||
$(srcdir)/util/tube.h $(srcdir)/services/mesh.h $(srcdir)/util/net_help.h $(srcdir)/util/ub_event.h
|
||||
worker.lo worker.o: $(srcdir)/daemon/worker.c config.h $(srcdir)/util/log.h $(srcdir)/util/net_help.h \
|
||||
$(srcdir)/util/random.h $(srcdir)/daemon/worker.h $(srcdir)/libunbound/worker.h $(srcdir)/sldns/sbuffer.h \
|
||||
$(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h \
|
||||
$(srcdir)/util/netevent.h $(srcdir)/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)/util/module.h $(srcdir)/dnstap/dnstap.h $(srcdir)/daemon/daemon.h \
|
||||
$(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
|
||||
$(srcdir)/util/alloc.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h \
|
||||
$(srcdir)/sldns/rrdef.h $(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h $(srcdir)/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 \
|
||||
|
|
@ -1037,16 +1132,18 @@ worker.lo worker.o: $(srcdir)/daemon/worker.c config.h $(srcdir)/util/log.h $(sr
|
|||
$(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)/libunbound/context.h $(srcdir)/libunbound/unbound.h \
|
||||
$(srcdir)/libunbound/libworker.h
|
||||
$(srcdir)/validator/val_anchor.h $(srcdir)/respip/respip.h $(srcdir)/libunbound/context.h \
|
||||
$(srcdir)/libunbound/unbound.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)/util/rbtree.h $(srcdir)/testcode/fake_event.h \
|
||||
$(srcdir)/testcode/replay.h $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
|
||||
$(srcdir)/util/rbtree.h $(srcdir)/testcode/fake_event.h \
|
||||
$(srcdir)/daemon/remote.h $(srcdir)/util/config_file.h $(srcdir)/sldns/keyraw.h $(srcdir)/daemon/unbound.c \
|
||||
$(srcdir)/util/log.h $(srcdir)/daemon/daemon.h $(srcdir)/util/locks.h $(srcdir)/util/alloc.h $(srcdir)/services/modstack.h \
|
||||
$(srcdir)/util/storage/slabhash.h $(srcdir)/util/storage/lruhash.h \
|
||||
$(srcdir)/services/listen_dnsport.h $(srcdir)/services/cache/rrset.h \
|
||||
$(srcdir)/util/data/packed_rrset.h $(srcdir)/services/cache/infra.h $(srcdir)/util/storage/dnstree.h \
|
||||
$(srcdir)/util/rtt.h $(srcdir)/util/fptr_wlist.h $(srcdir)/util/module.h $(srcdir)/util/data/msgreply.h \
|
||||
$(srcdir)/util/rtt.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/fptr_wlist.h $(srcdir)/util/module.h \
|
||||
$(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/tube.h \
|
||||
$(srcdir)/services/mesh.h $(srcdir)/util/net_help.h $(srcdir)/util/ub_event.h
|
||||
testpkts.lo testpkts.o: $(srcdir)/testcode/testpkts.c config.h $(srcdir)/testcode/testpkts.h \
|
||||
|
|
@ -1055,9 +1152,10 @@ 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)/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)/util/module.h $(srcdir)/dnstap/dnstap.h $(srcdir)/daemon/daemon.h \
|
||||
$(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
|
||||
$(srcdir)/util/alloc.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h \
|
||||
$(srcdir)/sldns/rrdef.h $(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h $(srcdir)/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 \
|
||||
|
|
@ -1066,8 +1164,9 @@ worker.lo worker.o: $(srcdir)/daemon/worker.c config.h $(srcdir)/util/log.h $(sr
|
|||
$(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)/libunbound/context.h $(srcdir)/libunbound/unbound.h \
|
||||
$(srcdir)/libunbound/libworker.h
|
||||
$(srcdir)/validator/val_anchor.h $(srcdir)/respip/respip.h $(srcdir)/libunbound/context.h \
|
||||
$(srcdir)/libunbound/unbound.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 \
|
||||
|
|
@ -1076,44 +1175,47 @@ acl_list.lo acl_list.o: $(srcdir)/daemon/acl_list.c config.h $(srcdir)/daemon/ac
|
|||
$(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)/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)/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/storage/lookup3.h \
|
||||
$(srcdir)/daemon/worker.h $(srcdir)/libunbound/worker.h \
|
||||
$(srcdir)/sldns/sbuffer.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h \
|
||||
$(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h $(srcdir)/util/data/msgreply.h \
|
||||
$(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/daemon/stats.h \
|
||||
$(srcdir)/util/timehist.h $(srcdir)/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)/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)/daemon/worker.h $(srcdir)/libunbound/worker.h $(srcdir)/sldns/sbuffer.h \
|
||||
$(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \
|
||||
$(srcdir)/util/netevent.h $(srcdir)/util/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)/services/cache/rrset.h \
|
||||
$(srcdir)/util/storage/slabhash.h $(srcdir)/services/cache/infra.h $(srcdir)/util/storage/dnstree.h \
|
||||
$(srcdir)/util/rtt.h $(srcdir)/validator/val_kcache.h
|
||||
$(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
|
||||
$(srcdir)/util/alloc.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h \
|
||||
$(srcdir)/sldns/rrdef.h $(srcdir)/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)/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)/testcode/testpkts.h \
|
||||
$(srcdir)/util/rbtree.h $(srcdir)/testcode/fake_event.h $(srcdir)/sldns/str2wire.h $(srcdir)/sldns/rrdef.h
|
||||
$(srcdir)/util/config_file.h $(srcdir)/testcode/replay.h $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.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)/util/net_help.h $(srcdir)/util/log.h $(srcdir)/util/data/msgparse.h \
|
||||
$(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h \
|
||||
$(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgencode.h \
|
||||
$(srcdir)/util/data/dname.h $(srcdir)/util/config_file.h $(srcdir)/services/listen_dnsport.h \
|
||||
$(srcdir)/services/outside_network.h $(srcdir)/util/rbtree.h \
|
||||
$(srcdir)/services/cache/infra.h $(srcdir)/util/storage/dnstree.h $(srcdir)/util/rtt.h \
|
||||
$(srcdir)/testcode/replay.h $(srcdir)/testcode/testpkts.h $(srcdir)/util/fptr_wlist.h $(srcdir)/util/module.h \
|
||||
$(srcdir)/util/tube.h $(srcdir)/services/mesh.h $(srcdir)/services/modstack.h $(srcdir)/sldns/sbuffer.h \
|
||||
$(srcdir)/sldns/wire2str.h $(srcdir)/sldns/str2wire.h
|
||||
$(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
|
||||
$(srcdir)/util/net_help.h $(srcdir)/util/log.h $(srcdir)/util/data/msgparse.h $(srcdir)/util/storage/lruhash.h \
|
||||
$(srcdir)/util/locks.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/data/msgreply.h \
|
||||
$(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgencode.h $(srcdir)/util/data/dname.h \
|
||||
$(srcdir)/util/config_file.h $(srcdir)/services/listen_dnsport.h $(srcdir)/services/outside_network.h \
|
||||
$(srcdir)/util/rbtree.h $(srcdir)/services/cache/infra.h \
|
||||
$(srcdir)/util/storage/dnstree.h $(srcdir)/util/rtt.h $(srcdir)/testcode/replay.h $(srcdir)/testcode/testpkts.h \
|
||||
$(srcdir)/util/fptr_wlist.h $(srcdir)/util/module.h $(srcdir)/util/tube.h $(srcdir)/services/mesh.h \
|
||||
$(srcdir)/services/modstack.h $(srcdir)/sldns/sbuffer.h $(srcdir)/sldns/wire2str.h $(srcdir)/sldns/str2wire.h
|
||||
lock_verify.lo lock_verify.o: $(srcdir)/testcode/lock_verify.c config.h $(srcdir)/util/log.h $(srcdir)/util/rbtree.h \
|
||||
$(srcdir)/util/locks.h $(srcdir)/util/fptr_wlist.h $(srcdir)/util/netevent.h $(srcdir)/util/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)/util/fptr_wlist.h $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.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 \
|
||||
|
|
@ -1121,10 +1223,11 @@ pktview.lo pktview.o: $(srcdir)/testcode/pktview.c config.h $(srcdir)/util/log.h
|
|||
readhex.lo readhex.o: $(srcdir)/testcode/readhex.c config.h $(srcdir)/testcode/readhex.h $(srcdir)/util/log.h \
|
||||
$(srcdir)/sldns/sbuffer.h $(srcdir)/sldns/parseutil.h
|
||||
memstats.lo memstats.o: $(srcdir)/testcode/memstats.c config.h $(srcdir)/util/log.h $(srcdir)/util/rbtree.h \
|
||||
$(srcdir)/util/locks.h $(srcdir)/util/fptr_wlist.h $(srcdir)/util/netevent.h $(srcdir)/util/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)/util/fptr_wlist.h $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.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 \
|
||||
|
|
@ -1132,13 +1235,14 @@ unbound-checkconf.lo unbound-checkconf.o: $(srcdir)/smallapp/unbound-checkconf.c
|
|||
$(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)/sldns/sbuffer.h $(PYTHONMOD_HEADER)
|
||||
$(srcdir)/services/view.h $(srcdir)/respip/respip.h $(srcdir)/sldns/sbuffer.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)/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)/dnscrypt/dnscrypt.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 \
|
||||
|
|
@ -1146,6 +1250,7 @@ context.lo context.o: $(srcdir)/libunbound/context.c config.h $(srcdir)/libunbou
|
|||
$(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)/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 \
|
||||
|
|
@ -1155,21 +1260,23 @@ libunbound.lo libunbound.o: $(srcdir)/libunbound/libunbound.c $(srcdir)/libunbou
|
|||
$(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)/services/cache/rrset.h \
|
||||
$(srcdir)/services/cache/infra.h $(srcdir)/util/rtt.h $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
|
||||
$(srcdir)/services/cache/rrset.h \
|
||||
$(srcdir)/util/storage/slabhash.h $(srcdir)/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)/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/data/dname.h $(srcdir)/util/data/msgencode.h $(srcdir)/iterator/iter_fwd.h \
|
||||
$(srcdir)/iterator/iter_hints.h $(srcdir)/sldns/str2wire.h
|
||||
$(srcdir)/dnscrypt/dnscrypt.h \
|
||||
$(srcdir)/services/mesh.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h \
|
||||
$(srcdir)/util/module.h $(srcdir)/util/data/msgreply.h $(srcdir)/services/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/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 \
|
||||
|
|
@ -1188,24 +1295,26 @@ perf.lo perf.o: $(srcdir)/testcode/perf.c config.h $(srcdir)/util/log.h $(srcdir
|
|||
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/config_file.h $(srcdir)/util/locks.h $(srcdir)/util/net_help.h $(srcdir)/util/shm_side/shm_main.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)/util/net_help.h $(srcdir)/services/cache/dns.h \
|
||||
$(srcdir)/sldns/rrdef.h $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
|
||||
$(srcdir)/util/net_help.h $(srcdir)/services/cache/dns.h \
|
||||
$(srcdir)/services/cache/rrset.h $(srcdir)/util/storage/slabhash.h $(srcdir)/util/regional.h \
|
||||
$(srcdir)/iterator/iter_delegpt.h $(srcdir)/sldns/sbuffer.h \
|
||||
|
||||
$(srcdir)/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)/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)/daemon/remote.h $(srcdir)/util/config_file.h $(srcdir)/util/ub_event.h
|
||||
$(srcdir)/daemon/worker.h \
|
||||
$(srcdir)/libunbound/worker.h $(srcdir)/sldns/sbuffer.h $(srcdir)/util/data/packed_rrset.h \
|
||||
$(srcdir)/util/storage/lruhash.h $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
|
||||
$(srcdir)/util/data/msgreply.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h \
|
||||
$(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h $(srcdir)/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 \
|
||||
$(srcdir)/winrc/w_inst.h
|
||||
|
|
|
|||
|
|
@ -103,9 +103,20 @@ AC_DEFUN([AC_PROG_SWIG],[
|
|||
if test -z "$available_patch" ; then
|
||||
[available_patch=0]
|
||||
fi
|
||||
if test $available_major -ne $required_major \
|
||||
-o $available_minor -ne $required_minor \
|
||||
-o $available_patch -lt $required_patch ; then
|
||||
[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
|
||||
AC_MSG_WARN([SWIG version >= $1 is required. You have $swig_version. You should look at http://www.swig.org])
|
||||
SWIG='echo "Error: SWIG version >= $1 is required. You have '"$swig_version"'. You should look at http://www.swig.org" ; false'
|
||||
else
|
||||
|
|
|
|||
|
|
@ -22,8 +22,7 @@ AC_DEFUN([AC_PYTHON_DEVEL],[
|
|||
# Check if you have distutils, else fail
|
||||
#
|
||||
AC_MSG_CHECKING([for the distutils Python package])
|
||||
ac_distutils_result=`$PYTHON -c "import distutils" 2>&1`
|
||||
if test -z "$ac_distutils_result"; then
|
||||
if ac_distutils_result=`$PYTHON -c "import distutils" 2>&1`; then
|
||||
AC_MSG_RESULT([yes])
|
||||
else
|
||||
AC_MSG_RESULT([no])
|
||||
|
|
|
|||
18
config.h.in
18
config.h.in
|
|
@ -3,6 +3,9 @@
|
|||
/* Directory to chroot to */
|
||||
#undef CHROOT_DIR
|
||||
|
||||
/* Define this to enable client subnet option. */
|
||||
#undef CLIENT_SUBNET
|
||||
|
||||
/* Do sha512 definitions in config.h */
|
||||
#undef COMPAT_SHA512
|
||||
|
||||
|
|
@ -385,6 +388,9 @@
|
|||
/* Define to 1 if you have the `SHA512_Update' function. */
|
||||
#undef HAVE_SHA512_UPDATE
|
||||
|
||||
/* Define to 1 if you have the `shmget' function. */
|
||||
#undef HAVE_SHMGET
|
||||
|
||||
/* Define to 1 if you have the `sigprocmask' function. */
|
||||
#undef HAVE_SIGPROCMASK
|
||||
|
||||
|
|
@ -457,6 +463,9 @@
|
|||
/* Define to 1 if systemd should be used */
|
||||
#undef HAVE_SYSTEMD
|
||||
|
||||
/* Define to 1 if you have the <sys/ipc.h> header file. */
|
||||
#undef HAVE_SYS_IPC_H
|
||||
|
||||
/* Define to 1 if you have the <sys/param.h> header file. */
|
||||
#undef HAVE_SYS_PARAM_H
|
||||
|
||||
|
|
@ -466,6 +475,9 @@
|
|||
/* Define to 1 if you have the <sys/sha2.h> header file. */
|
||||
#undef HAVE_SYS_SHA2_H
|
||||
|
||||
/* Define to 1 if you have the <sys/shm.h> header file. */
|
||||
#undef HAVE_SYS_SHM_H
|
||||
|
||||
/* Define to 1 if you have the <sys/socket.h> header file. */
|
||||
#undef HAVE_SYS_SOCKET_H
|
||||
|
||||
|
|
@ -651,6 +663,9 @@
|
|||
/* Define to 1 to use cachedb support */
|
||||
#undef USE_CACHEDB
|
||||
|
||||
/* Define to 1 to enable dnscrypt support */
|
||||
#undef USE_DNSCRYPT
|
||||
|
||||
/* Define to 1 to enable dnstap support */
|
||||
#undef USE_DNSTAP
|
||||
|
||||
|
|
@ -675,6 +690,9 @@
|
|||
/* Define this to enable client TCP Fast Open. */
|
||||
#undef USE_OSX_MSG_FASTOPEN
|
||||
|
||||
/* Define this to enable SHA1 support. */
|
||||
#undef USE_SHA1
|
||||
|
||||
/* Define this to enable SHA256 and SHA512 support. */
|
||||
#undef USE_SHA2
|
||||
|
||||
|
|
|
|||
220
configure
vendored
220
configure
vendored
|
|
@ -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.1.
|
||||
# Generated by GNU Autoconf 2.69 for unbound 1.6.2.
|
||||
#
|
||||
# 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.1'
|
||||
PACKAGE_STRING='unbound 1.6.1'
|
||||
PACKAGE_VERSION='1.6.2'
|
||||
PACKAGE_STRING='unbound 1.6.2'
|
||||
PACKAGE_BUGREPORT='unbound-bugs@nlnetlabs.nl'
|
||||
PACKAGE_URL=''
|
||||
|
||||
|
|
@ -638,6 +638,9 @@ INSTALLTARGET
|
|||
ALLTARGET
|
||||
SOURCEFILE
|
||||
SOURCEDETERMINE
|
||||
DNSCRYPT_OBJ
|
||||
DNSCRYPT_SRC
|
||||
ENABLE_DNSCRYPT
|
||||
DNSTAP_OBJ
|
||||
DNSTAP_SRC
|
||||
opt_dnstap_socket_path
|
||||
|
|
@ -671,6 +674,8 @@ staticexe
|
|||
PC_LIBEVENT_DEPENDENCY
|
||||
UNBOUND_EVENT_UNINSTALL
|
||||
UNBOUND_EVENT_INSTALL
|
||||
SUBNET_HEADER
|
||||
SUBNET_OBJ
|
||||
SSLLIB
|
||||
HAVE_SSL
|
||||
CONFIG_DATE
|
||||
|
|
@ -840,7 +845,9 @@ with_pythonmodule
|
|||
with_nss
|
||||
with_nettle
|
||||
with_ssl
|
||||
enable_sha1
|
||||
enable_sha2
|
||||
enable_subnet
|
||||
enable_gost
|
||||
enable_ecdsa
|
||||
enable_dsa
|
||||
|
|
@ -857,6 +864,8 @@ enable_dnstap
|
|||
with_dnstap_socket_path
|
||||
with_protobuf_c
|
||||
with_libfstrm
|
||||
enable_dnscrypt
|
||||
with_libsodium
|
||||
enable_cachedb
|
||||
with_libunbound_only
|
||||
'
|
||||
|
|
@ -1420,7 +1429,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.1 to adapt to many kinds of systems.
|
||||
\`configure' configures unbound 1.6.2 to adapt to many kinds of systems.
|
||||
|
||||
Usage: $0 [OPTION]... [VAR=VALUE]...
|
||||
|
||||
|
|
@ -1485,7 +1494,7 @@ fi
|
|||
|
||||
if test -n "$ac_init_help"; then
|
||||
case $ac_init_help in
|
||||
short | recursive ) echo "Configuration of unbound 1.6.1:";;
|
||||
short | recursive ) echo "Configuration of unbound 1.6.2:";;
|
||||
esac
|
||||
cat <<\_ACEOF
|
||||
|
||||
|
|
@ -1515,7 +1524,10 @@ Optional Features:
|
|||
enable nonregional allocs, slow but exposes regional
|
||||
allocations to other memory purifiers, for debug
|
||||
purposes
|
||||
--disable-sha1 Disable SHA1 RRSIG support, does not disable nsec3
|
||||
support
|
||||
--disable-sha2 Disable SHA256 and SHA512 RRSIG support
|
||||
--enable-subnet Enable client subnet
|
||||
--disable-gost Disable GOST support
|
||||
--disable-ecdsa Disable ECDSA support
|
||||
--disable-dsa Disable DSA support
|
||||
|
|
@ -1532,6 +1544,7 @@ Optional Features:
|
|||
to it, smaller install size but libunbound export
|
||||
table is polluted by internal symbols
|
||||
--enable-dnstap Enable dnstap support (requires fstrm, protobuf-c)
|
||||
--enable-dnscrypt Enable dnscrypt support (requires libsodium)
|
||||
--enable-cachedb enable cachedb module that can use external cache
|
||||
storage
|
||||
|
||||
|
|
@ -1586,6 +1599,7 @@ Optional Packages:
|
|||
set default dnstap socket path
|
||||
--with-protobuf-c=path Path where protobuf-c is installed, for dnstap
|
||||
--with-libfstrm=path Path where libfstrm is installed, for dnstap
|
||||
--with-libsodium=path Path where libsodium is installed, for dnscrypt
|
||||
--with-libunbound-only do not build daemon and tool programs
|
||||
|
||||
Some influential environment variables:
|
||||
|
|
@ -1689,7 +1703,7 @@ fi
|
|||
test -n "$ac_init_help" && exit $ac_status
|
||||
if $ac_init_version; then
|
||||
cat <<\_ACEOF
|
||||
unbound configure 1.6.1
|
||||
unbound configure 1.6.2
|
||||
generated by GNU Autoconf 2.69
|
||||
|
||||
Copyright (C) 2012 Free Software Foundation, Inc.
|
||||
|
|
@ -2398,7 +2412,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.1, which was
|
||||
It was created by unbound $as_me 1.6.2, which was
|
||||
generated by GNU Autoconf 2.69. Invocation command line was
|
||||
|
||||
$ $0 $@
|
||||
|
|
@ -2750,12 +2764,12 @@ UNBOUND_VERSION_MAJOR=1
|
|||
|
||||
UNBOUND_VERSION_MINOR=6
|
||||
|
||||
UNBOUND_VERSION_MICRO=1
|
||||
UNBOUND_VERSION_MICRO=2
|
||||
|
||||
|
||||
LIBUNBOUND_CURRENT=6
|
||||
LIBUNBOUND_REVISION=4
|
||||
LIBUNBOUND_AGE=4
|
||||
LIBUNBOUND_CURRENT=7
|
||||
LIBUNBOUND_REVISION=1
|
||||
LIBUNBOUND_AGE=5
|
||||
# 1.0.0 had 0:12:0
|
||||
# 1.0.1 had 0:13:0
|
||||
# 1.0.2 had 0:14:0
|
||||
|
|
@ -2806,6 +2820,7 @@ LIBUNBOUND_AGE=4
|
|||
# 1.5.10 had 6:2:4
|
||||
# 1.6.0 had 6:3:4
|
||||
# 1.6.1 had 7:0:5 # ub_callback_t typedef renamed to ub_callback_type
|
||||
# 1.6.2 had 7:1:5
|
||||
|
||||
# Current -- the number of the binary API that we're implementing
|
||||
# Revision -- which iteration of the implementation of the binary
|
||||
|
|
@ -4104,7 +4119,7 @@ fi
|
|||
if test $on_mingw = "no"; then
|
||||
ub_conf_file=`eval echo "${sysconfdir}/unbound/unbound.conf"`
|
||||
else
|
||||
ub_conf_file="C:\\Program Files (x86)\\Unbound\\service.conf"
|
||||
ub_conf_file="C:\\Program Files\\Unbound\\service.conf"
|
||||
fi
|
||||
|
||||
# Check whether --with-conf_file was given.
|
||||
|
|
@ -4235,7 +4250,7 @@ else
|
|||
if test $on_mingw = no; then
|
||||
UNBOUND_ROOTKEY_FILE="$UNBOUND_RUN_DIR/root.key"
|
||||
else
|
||||
UNBOUND_ROOTKEY_FILE="C:\\Program Files (x86)\\Unbound\\root.key"
|
||||
UNBOUND_ROOTKEY_FILE="C:\\Program Files\\Unbound\\root.key"
|
||||
fi
|
||||
|
||||
fi
|
||||
|
|
@ -4257,7 +4272,7 @@ else
|
|||
if test $on_mingw = no; then
|
||||
UNBOUND_ROOTCERT_FILE="$UNBOUND_RUN_DIR/icannbundle.pem"
|
||||
else
|
||||
UNBOUND_ROOTCERT_FILE="C:\\Program Files (x86)\\Unbound\\icannbundle.pem"
|
||||
UNBOUND_ROOTCERT_FILE="C:\\Program Files\\Unbound\\icannbundle.pem"
|
||||
fi
|
||||
|
||||
fi
|
||||
|
|
@ -14422,7 +14437,7 @@ CC=$lt_save_CC
|
|||
|
||||
|
||||
# Checks for header files.
|
||||
for ac_header in stdarg.h stdbool.h netinet/in.h netinet/tcp.h sys/param.h sys/socket.h sys/un.h sys/uio.h sys/resource.h arpa/inet.h syslog.h netdb.h sys/wait.h pwd.h glob.h grp.h login_cap.h winsock2.h ws2tcpip.h endian.h
|
||||
for ac_header in stdarg.h stdbool.h netinet/in.h netinet/tcp.h sys/param.h sys/socket.h sys/un.h sys/uio.h sys/resource.h arpa/inet.h syslog.h netdb.h sys/wait.h pwd.h glob.h grp.h login_cap.h winsock2.h ws2tcpip.h endian.h sys/ipc.h sys/shm.h
|
||||
do :
|
||||
as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
|
||||
ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default
|
||||
|
|
@ -16717,8 +16732,7 @@ fi
|
|||
#
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for the distutils Python package" >&5
|
||||
$as_echo_n "checking for the distutils Python package... " >&6; }
|
||||
ac_distutils_result=`$PYTHON -c "import distutils" 2>&1`
|
||||
if test -z "$ac_distutils_result"; then
|
||||
if ac_distutils_result=`$PYTHON -c "import distutils" 2>&1`; then
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
|
||||
$as_echo "yes" >&6; }
|
||||
else
|
||||
|
|
@ -16908,7 +16922,7 @@ fi
|
|||
{ $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
|
||||
elif test -n "2.0.1" ; 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'`
|
||||
|
|
@ -16916,7 +16930,7 @@ $as_echo_n "checking for SWIG version... " >&6; }
|
|||
$as_echo "$swig_version" >&6; }
|
||||
if test -n "$swig_version" ; then
|
||||
# Calculate the required version number components
|
||||
required=
|
||||
required=2.0.1
|
||||
required_major=`echo $required | sed 's/[^0-9].*//'`
|
||||
if test -z "$required_major" ; then
|
||||
required_major=0
|
||||
|
|
@ -16947,12 +16961,23 @@ $as_echo "$swig_version" >&6; }
|
|||
if test -z "$available_patch" ; then
|
||||
available_patch=0
|
||||
fi
|
||||
if test $available_major -ne $required_major \
|
||||
-o $available_minor -ne $required_minor \
|
||||
-o $available_patch -lt $required_patch ; 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'
|
||||
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 >= 2.0.1 is required. You have $swig_version. You should look at http://www.swig.org" >&5
|
||||
$as_echo "$as_me: WARNING: SWIG version >= 2.0.1 is required. You have $swig_version. You should look at http://www.swig.org" >&2;}
|
||||
SWIG='echo "Error: SWIG version >= 2.0.1 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;}
|
||||
|
|
@ -17697,6 +17722,22 @@ fi
|
|||
|
||||
|
||||
|
||||
# Check whether --enable-sha1 was given.
|
||||
if test "${enable_sha1+set}" = set; then :
|
||||
enableval=$enable_sha1;
|
||||
fi
|
||||
|
||||
case "$enable_sha1" in
|
||||
no)
|
||||
;;
|
||||
yes|*)
|
||||
|
||||
$as_echo "#define USE_SHA1 1" >>confdefs.h
|
||||
|
||||
;;
|
||||
esac
|
||||
|
||||
|
||||
# Check whether --enable-sha2 was given.
|
||||
if test "${enable_sha2+set}" = set; then :
|
||||
enableval=$enable_sha2;
|
||||
|
|
@ -17712,6 +17753,25 @@ $as_echo "#define USE_SHA2 1" >>confdefs.h
|
|||
;;
|
||||
esac
|
||||
|
||||
# Check whether --enable-subnet was given.
|
||||
if test "${enable_subnet+set}" = set; then :
|
||||
enableval=$enable_subnet;
|
||||
fi
|
||||
|
||||
case "$enable_subnet" in
|
||||
yes)
|
||||
|
||||
$as_echo "#define CLIENT_SUBNET 1" >>confdefs.h
|
||||
|
||||
SUBNET_OBJ="edns-subnet.lo subnetmod.lo addrtree.lo subnet-whitelist.lo"
|
||||
|
||||
SUBNET_HEADER='$(srcdir)/edns-subnet/subnetmod.h $(srcdir)/edns-subnet/edns-subnet.h $(srcdir)/edns-subnet/subnet-whitelist.h $(srcdir)/edns-subnet/addrtree.h'
|
||||
|
||||
;;
|
||||
no|*)
|
||||
;;
|
||||
esac
|
||||
|
||||
# check wether gost also works
|
||||
|
||||
# Check whether --enable-gost was given.
|
||||
|
|
@ -19251,7 +19311,7 @@ if test "$ac_res" != no; then :
|
|||
|
||||
fi
|
||||
|
||||
for ac_func in tzset sigprocmask fcntl getpwnam endpwent getrlimit setrlimit setsid chroot kill chown sleep usleep random srandom recvmsg sendmsg writev socketpair glob initgroups strftime localtime_r setusercontext _beginthreadex endservent endprotoent fsync
|
||||
for ac_func in tzset sigprocmask fcntl getpwnam endpwent getrlimit setrlimit setsid chroot kill chown sleep usleep random srandom recvmsg sendmsg writev socketpair glob initgroups strftime localtime_r setusercontext _beginthreadex endservent endprotoent fsync shmget
|
||||
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"
|
||||
|
|
@ -20170,6 +20230,105 @@ _ACEOF
|
|||
fi
|
||||
|
||||
|
||||
# check for dnscrypt if requested
|
||||
|
||||
# Check whether --enable-dnscrypt was given.
|
||||
if test "${enable_dnscrypt+set}" = set; then :
|
||||
enableval=$enable_dnscrypt; opt_dnscrypt=$enableval
|
||||
else
|
||||
opt_dnscrypt=no
|
||||
fi
|
||||
|
||||
|
||||
if test "x$opt_dnscrypt" != "xno"; then
|
||||
|
||||
# Check whether --with-libsodium was given.
|
||||
if test "${with_libsodium+set}" = set; then :
|
||||
withval=$with_libsodium;
|
||||
CFLAGS="$CFLAGS -I$withval/include"
|
||||
LDFLAGS="$LDFLAGS -L$withval/lib"
|
||||
|
||||
fi
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing sodium_init" >&5
|
||||
$as_echo_n "checking for library containing sodium_init... " >&6; }
|
||||
if ${ac_cv_search_sodium_init+:} 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_init ();
|
||||
int
|
||||
main ()
|
||||
{
|
||||
return sodium_init ();
|
||||
;
|
||||
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_init=$ac_res
|
||||
fi
|
||||
rm -f core conftest.err conftest.$ac_objext \
|
||||
conftest$ac_exeext
|
||||
if ${ac_cv_search_sodium_init+:} false; then :
|
||||
break
|
||||
fi
|
||||
done
|
||||
if ${ac_cv_search_sodium_init+:} false; then :
|
||||
|
||||
else
|
||||
ac_cv_search_sodium_init=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_init" >&5
|
||||
$as_echo "$ac_cv_search_sodium_init" >&6; }
|
||||
ac_res=$ac_cv_search_sodium_init
|
||||
if test "$ac_res" != no; then :
|
||||
test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
|
||||
|
||||
else
|
||||
as_fn_error $? "The sodium library was not found. Please install sodium!" "$LINENO" 5
|
||||
fi
|
||||
|
||||
|
||||
|
||||
$as_echo "#define USE_DNSCRYPT 1" >>confdefs.h
|
||||
|
||||
ENABLE_DNSCRYPT=1
|
||||
|
||||
|
||||
DNSCRYPT_SRC="dnscrypt/dnscrypt.c"
|
||||
|
||||
DNSCRYPT_OBJ="dnscrypt.lo"
|
||||
|
||||
|
||||
else
|
||||
|
||||
ENABLE_DNSCRYPT=0
|
||||
|
||||
|
||||
|
||||
fi
|
||||
|
||||
|
||||
# check for cachedb if requested
|
||||
# Check whether --enable-cachedb was given.
|
||||
if test "${enable_cachedb+set}" = set; then :
|
||||
|
|
@ -20328,12 +20487,12 @@ _ACEOF
|
|||
|
||||
|
||||
|
||||
version=1.6.1
|
||||
version=1.6.2
|
||||
|
||||
date=`date +'%b %e, %Y'`
|
||||
|
||||
|
||||
ac_config_files="$ac_config_files Makefile doc/example.conf doc/libunbound.3 doc/unbound.8 doc/unbound-anchor.8 doc/unbound-checkconf.8 doc/unbound.conf.5 doc/unbound-control.8 doc/unbound-host.1 smallapp/unbound-control-setup.sh dnstap/dnstap_config.h contrib/libunbound.pc contrib/unbound.socket contrib/unbound.service"
|
||||
ac_config_files="$ac_config_files Makefile doc/example.conf doc/libunbound.3 doc/unbound.8 doc/unbound-anchor.8 doc/unbound-checkconf.8 doc/unbound.conf.5 doc/unbound-control.8 doc/unbound-host.1 smallapp/unbound-control-setup.sh dnstap/dnstap_config.h dnscrypt/dnscrypt_config.h contrib/libunbound.pc contrib/unbound.socket contrib/unbound.service"
|
||||
|
||||
ac_config_headers="$ac_config_headers config.h"
|
||||
|
||||
|
|
@ -20847,7 +21006,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.1, which was
|
||||
This file was extended by unbound $as_me 1.6.2, which was
|
||||
generated by GNU Autoconf 2.69. Invocation command line was
|
||||
|
||||
CONFIG_FILES = $CONFIG_FILES
|
||||
|
|
@ -20913,7 +21072,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.1
|
||||
unbound config.status 1.6.2
|
||||
configured by $0, generated by GNU Autoconf 2.69,
|
||||
with options \\"\$ac_cs_config\\"
|
||||
|
||||
|
|
@ -21335,6 +21494,7 @@ do
|
|||
"doc/unbound-host.1") CONFIG_FILES="$CONFIG_FILES doc/unbound-host.1" ;;
|
||||
"smallapp/unbound-control-setup.sh") CONFIG_FILES="$CONFIG_FILES smallapp/unbound-control-setup.sh" ;;
|
||||
"dnstap/dnstap_config.h") CONFIG_FILES="$CONFIG_FILES dnstap/dnstap_config.h" ;;
|
||||
"dnscrypt/dnscrypt_config.h") CONFIG_FILES="$CONFIG_FILES dnscrypt/dnscrypt_config.h" ;;
|
||||
"contrib/libunbound.pc") CONFIG_FILES="$CONFIG_FILES contrib/libunbound.pc" ;;
|
||||
"contrib/unbound.socket") CONFIG_FILES="$CONFIG_FILES contrib/unbound.socket" ;;
|
||||
"contrib/unbound.service") CONFIG_FILES="$CONFIG_FILES contrib/unbound.service" ;;
|
||||
|
|
|
|||
60
configure.ac
60
configure.ac
|
|
@ -6,19 +6,20 @@ sinclude(ax_pthread.m4)
|
|||
sinclude(acx_python.m4)
|
||||
sinclude(ac_pkg_swig.m4)
|
||||
sinclude(dnstap/dnstap.m4)
|
||||
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],[1])
|
||||
m4_define([VERSION_MICRO],[2])
|
||||
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=6
|
||||
LIBUNBOUND_REVISION=4
|
||||
LIBUNBOUND_AGE=4
|
||||
LIBUNBOUND_CURRENT=7
|
||||
LIBUNBOUND_REVISION=1
|
||||
LIBUNBOUND_AGE=5
|
||||
# 1.0.0 had 0:12:0
|
||||
# 1.0.1 had 0:13:0
|
||||
# 1.0.2 had 0:14:0
|
||||
|
|
@ -69,6 +70,7 @@ LIBUNBOUND_AGE=4
|
|||
# 1.5.10 had 6:2:4
|
||||
# 1.6.0 had 6:3:4
|
||||
# 1.6.1 had 7:0:5 # ub_callback_t typedef renamed to ub_callback_type
|
||||
# 1.6.2 had 7:1:5
|
||||
|
||||
# Current -- the number of the binary API that we're implementing
|
||||
# Revision -- which iteration of the implementation of the binary
|
||||
|
|
@ -120,7 +122,7 @@ fi
|
|||
if test $on_mingw = "no"; then
|
||||
ub_conf_file=`eval echo "${sysconfdir}/unbound/unbound.conf"`
|
||||
else
|
||||
ub_conf_file="C:\\Program Files (x86)\\Unbound\\service.conf"
|
||||
ub_conf_file="C:\\Program Files\\Unbound\\service.conf"
|
||||
fi
|
||||
AC_ARG_WITH([conf_file],
|
||||
AC_HELP_STRING([--with-conf-file=path],
|
||||
|
|
@ -190,7 +192,7 @@ AC_ARG_WITH(rootkey-file,
|
|||
if test $on_mingw = no; then
|
||||
UNBOUND_ROOTKEY_FILE="$UNBOUND_RUN_DIR/root.key"
|
||||
else
|
||||
UNBOUND_ROOTKEY_FILE="C:\\Program Files (x86)\\Unbound\\root.key"
|
||||
UNBOUND_ROOTKEY_FILE="C:\\Program Files\\Unbound\\root.key"
|
||||
fi
|
||||
)
|
||||
AC_SUBST(UNBOUND_ROOTKEY_FILE)
|
||||
|
|
@ -204,7 +206,7 @@ AC_ARG_WITH(rootcert-file,
|
|||
if test $on_mingw = no; then
|
||||
UNBOUND_ROOTCERT_FILE="$UNBOUND_RUN_DIR/icannbundle.pem"
|
||||
else
|
||||
UNBOUND_ROOTCERT_FILE="C:\\Program Files (x86)\\Unbound\\icannbundle.pem"
|
||||
UNBOUND_ROOTCERT_FILE="C:\\Program Files\\Unbound\\icannbundle.pem"
|
||||
fi
|
||||
)
|
||||
AC_SUBST(UNBOUND_ROOTCERT_FILE)
|
||||
|
|
@ -304,7 +306,7 @@ AC_CHECK_TOOL(STRIP, strip)
|
|||
ACX_LIBTOOL_C_ONLY
|
||||
|
||||
# Checks for header files.
|
||||
AC_CHECK_HEADERS([stdarg.h stdbool.h netinet/in.h netinet/tcp.h sys/param.h sys/socket.h sys/un.h sys/uio.h sys/resource.h arpa/inet.h syslog.h netdb.h sys/wait.h pwd.h glob.h grp.h login_cap.h winsock2.h ws2tcpip.h endian.h],,, [AC_INCLUDES_DEFAULT])
|
||||
AC_CHECK_HEADERS([stdarg.h stdbool.h netinet/in.h netinet/tcp.h sys/param.h sys/socket.h sys/un.h sys/uio.h sys/resource.h arpa/inet.h syslog.h netdb.h sys/wait.h pwd.h glob.h grp.h login_cap.h winsock2.h ws2tcpip.h endian.h sys/ipc.h sys/shm.h],,, [AC_INCLUDES_DEFAULT])
|
||||
|
||||
# check for types.
|
||||
# Using own tests for int64* because autoconf builtin only give 32bit.
|
||||
|
|
@ -550,7 +552,7 @@ if test x_$ub_test_python != x_no; then
|
|||
|
||||
# Check for SWIG
|
||||
ub_have_swig=no
|
||||
AC_PROG_SWIG
|
||||
AC_PROG_SWIG(2.0.1)
|
||||
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])
|
||||
|
|
@ -709,6 +711,16 @@ fi
|
|||
AC_SUBST(SSLLIB)
|
||||
|
||||
|
||||
AC_ARG_ENABLE(sha1, AC_HELP_STRING([--disable-sha1], [Disable SHA1 RRSIG support, does not disable nsec3 support]))
|
||||
case "$enable_sha1" in
|
||||
no)
|
||||
;;
|
||||
yes|*)
|
||||
AC_DEFINE([USE_SHA1], [1], [Define this to enable SHA1 support.])
|
||||
;;
|
||||
esac
|
||||
|
||||
|
||||
AC_ARG_ENABLE(sha2, AC_HELP_STRING([--disable-sha2], [Disable SHA256 and SHA512 RRSIG support]))
|
||||
case "$enable_sha2" in
|
||||
no)
|
||||
|
|
@ -718,6 +730,19 @@ case "$enable_sha2" in
|
|||
;;
|
||||
esac
|
||||
|
||||
AC_ARG_ENABLE(subnet, AC_HELP_STRING([--enable-subnet], [Enable client subnet]))
|
||||
case "$enable_subnet" in
|
||||
yes)
|
||||
AC_DEFINE([CLIENT_SUBNET], [1], [Define this to enable client subnet option.])
|
||||
SUBNET_OBJ="edns-subnet.lo subnetmod.lo addrtree.lo subnet-whitelist.lo"
|
||||
AC_SUBST(SUBNET_OBJ)
|
||||
SUBNET_HEADER='$(srcdir)/edns-subnet/subnetmod.h $(srcdir)/edns-subnet/edns-subnet.h $(srcdir)/edns-subnet/subnet-whitelist.h $(srcdir)/edns-subnet/addrtree.h'
|
||||
AC_SUBST(SUBNET_HEADER)
|
||||
;;
|
||||
no|*)
|
||||
;;
|
||||
esac
|
||||
|
||||
# check wether gost also works
|
||||
AC_DEFUN([AC_CHECK_GOST_WORKS],
|
||||
[AC_REQUIRE([AC_PROG_CC])
|
||||
|
|
@ -1148,7 +1173,7 @@ AC_INCLUDES_DEFAULT
|
|||
#endif
|
||||
])
|
||||
AC_SEARCH_LIBS([setusercontext], [util])
|
||||
AC_CHECK_FUNCS([tzset sigprocmask fcntl getpwnam endpwent getrlimit setrlimit setsid chroot kill chown sleep usleep random srandom recvmsg sendmsg writev socketpair glob initgroups strftime localtime_r setusercontext _beginthreadex endservent endprotoent fsync])
|
||||
AC_CHECK_FUNCS([tzset sigprocmask fcntl getpwnam endpwent getrlimit setrlimit setsid chroot kill chown sleep usleep random srandom recvmsg sendmsg writev socketpair glob initgroups strftime localtime_r setusercontext _beginthreadex endservent endprotoent fsync shmget])
|
||||
AC_CHECK_FUNCS([setresuid],,[AC_CHECK_FUNCS([setreuid])])
|
||||
AC_CHECK_FUNCS([setresgid],,[AC_CHECK_FUNCS([setregid])])
|
||||
|
||||
|
|
@ -1303,6 +1328,19 @@ dt_DNSTAP([$UNBOUND_RUN_DIR/dnstap.sock],
|
|||
]
|
||||
)
|
||||
|
||||
# check for dnscrypt if requested
|
||||
dnsc_DNSCRYPT([
|
||||
AC_DEFINE([USE_DNSCRYPT], [1], [Define to 1 to enable dnscrypt support])
|
||||
AC_SUBST([ENABLE_DNSCRYPT], [1])
|
||||
|
||||
AC_SUBST([DNSCRYPT_SRC], ["dnscrypt/dnscrypt.c"])
|
||||
AC_SUBST([DNSCRYPT_OBJ], ["dnscrypt.lo"])
|
||||
],
|
||||
[
|
||||
AC_SUBST([ENABLE_DNSCRYPT], [0])
|
||||
]
|
||||
)
|
||||
|
||||
# check for cachedb if requested
|
||||
AC_ARG_ENABLE(cachedb, AC_HELP_STRING([--enable-cachedb], [enable cachedb module that can use external cache storage]))
|
||||
case "$enable_cachedb" in
|
||||
|
|
@ -1606,6 +1644,6 @@ dnl if this is a distro tarball, that was already done by makedist.sh
|
|||
AC_SUBST(version, [VERSION_MAJOR.VERSION_MINOR.VERSION_MICRO])
|
||||
AC_SUBST(date, [`date +'%b %e, %Y'`])
|
||||
|
||||
AC_CONFIG_FILES([Makefile doc/example.conf doc/libunbound.3 doc/unbound.8 doc/unbound-anchor.8 doc/unbound-checkconf.8 doc/unbound.conf.5 doc/unbound-control.8 doc/unbound-host.1 smallapp/unbound-control-setup.sh dnstap/dnstap_config.h contrib/libunbound.pc contrib/unbound.socket contrib/unbound.service])
|
||||
AC_CONFIG_FILES([Makefile doc/example.conf doc/libunbound.3 doc/unbound.8 doc/unbound-anchor.8 doc/unbound-checkconf.8 doc/unbound.conf.5 doc/unbound-control.8 doc/unbound-host.1 smallapp/unbound-control-setup.sh dnstap/dnstap_config.h dnscrypt/dnscrypt_config.h contrib/libunbound.pc contrib/unbound.socket contrib/unbound.service])
|
||||
AC_CONFIG_HEADER([config.h])
|
||||
AC_OUTPUT
|
||||
|
|
|
|||
|
|
@ -1,8 +1,28 @@
|
|||
[Service]
|
||||
Type=notify
|
||||
NotifyAccess=main
|
||||
ExecStart=/home/vagrant/unbound_systemd/unbound
|
||||
ExecReload=/bin/kill -HUP $MAINPID
|
||||
[Unit]
|
||||
Description=Validating, recursive, and caching DNS resolver
|
||||
Documentation=man:unbound(8)
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
|
||||
[Service]
|
||||
ExecReload=/bin/kill -HUP $MAINPID
|
||||
ExecStart=/home/vagrant/unbound_systemd/unbound
|
||||
NotifyAccess=main
|
||||
Type=notify
|
||||
CapabilityBoundingSet=CAP_IPC_LOCK CAP_NET_BIND_SERVICE CAP_SETGID CAP_SETUID CAP_SYS_CHROOT
|
||||
MemoryDenyWriteExecute=true
|
||||
NoNewPrivileges=true
|
||||
PrivateDevices=true
|
||||
PrivateTmp=true
|
||||
ProtectHome=true
|
||||
ProtectControlGroups=true
|
||||
ProtectKernelModules=true
|
||||
ProtectKernelTunables=true
|
||||
ProtectSystem=strict
|
||||
ReadWritePaths=/etc/unbound /run
|
||||
RestrictAddressFamilies=AF_INET AF_UNIX
|
||||
RestrictRealtime=true
|
||||
SystemCallArchitectures=native
|
||||
SystemCallFilter=~@clock @cpu-emulation @debug @keyring @module mount @obsolete @resources
|
||||
|
||||
|
|
|
|||
|
|
@ -73,6 +73,7 @@
|
|||
#include "util/log.h"
|
||||
#include "util/config_file.h"
|
||||
#include "util/data/msgreply.h"
|
||||
#include "util/shm_side/shm_main.h"
|
||||
#include "util/storage/lookup3.h"
|
||||
#include "util/storage/slabhash.h"
|
||||
#include "services/listen_dnsport.h"
|
||||
|
|
@ -86,6 +87,7 @@
|
|||
#include "util/tube.h"
|
||||
#include "util/net_help.h"
|
||||
#include "sldns/keyraw.h"
|
||||
#include "respip/respip.h"
|
||||
#include <signal.h>
|
||||
|
||||
#ifdef HAVE_SYSTEMD
|
||||
|
|
@ -561,6 +563,8 @@ daemon_stop_others(struct daemon* daemon)
|
|||
void
|
||||
daemon_fork(struct daemon* daemon)
|
||||
{
|
||||
int have_view_respip_cfg = 0;
|
||||
|
||||
log_assert(daemon);
|
||||
if(!(daemon->views = views_create()))
|
||||
fatal_exit("Could not create views: out of memory");
|
||||
|
|
@ -570,15 +574,44 @@ daemon_fork(struct daemon* daemon)
|
|||
|
||||
if(!acl_list_apply_cfg(daemon->acl, daemon->cfg, daemon->views))
|
||||
fatal_exit("Could not setup access control list");
|
||||
if(daemon->cfg->dnscrypt) {
|
||||
#ifdef USE_DNSCRYPT
|
||||
daemon->dnscenv = dnsc_create();
|
||||
if (!daemon->dnscenv)
|
||||
fatal_exit("dnsc_create failed");
|
||||
dnsc_apply_cfg(daemon->dnscenv, daemon->cfg);
|
||||
#else
|
||||
fatal_exit("dnscrypt enabled in config but unbound was not built with "
|
||||
"dnscrypt support");
|
||||
#endif
|
||||
}
|
||||
/* create global local_zones */
|
||||
if(!(daemon->local_zones = local_zones_create()))
|
||||
fatal_exit("Could not create local zones: out of memory");
|
||||
if(!local_zones_apply_cfg(daemon->local_zones, daemon->cfg))
|
||||
fatal_exit("Could not set up local zones");
|
||||
|
||||
/* process raw response-ip configuration data */
|
||||
if(!(daemon->respip_set = respip_set_create()))
|
||||
fatal_exit("Could not create response IP set");
|
||||
if(!respip_global_apply_cfg(daemon->respip_set, daemon->cfg))
|
||||
fatal_exit("Could not set up response IP set");
|
||||
if(!respip_views_apply_cfg(daemon->views, daemon->cfg,
|
||||
&have_view_respip_cfg))
|
||||
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;
|
||||
|
||||
/* setup modules */
|
||||
daemon_setup_modules(daemon);
|
||||
|
||||
/* response-ip-xxx options don't work as expected without the respip
|
||||
* module. To avoid run-time operational surprise we reject such
|
||||
* configuration. */
|
||||
if(daemon->use_response_ip &&
|
||||
modstack_find(&daemon->mods, "respip") < 0)
|
||||
fatal_exit("response-ip options require respip module");
|
||||
|
||||
/* first create all the worker structures, so we can pass
|
||||
* them to the newly created threads.
|
||||
*/
|
||||
|
|
@ -605,6 +638,9 @@ daemon_fork(struct daemon* daemon)
|
|||
#endif
|
||||
signal_handling_playback(daemon->workers[0]);
|
||||
|
||||
if (!shm_main_init(daemon))
|
||||
log_warn("SHM has failed");
|
||||
|
||||
/* Start resolver service on main thread. */
|
||||
#ifdef HAVE_SYSTEMD
|
||||
sd_notify(0, "READY=1");
|
||||
|
|
@ -619,6 +655,9 @@ daemon_fork(struct daemon* daemon)
|
|||
/* we exited! a signal happened! Stop other threads */
|
||||
daemon_stop_others(daemon);
|
||||
|
||||
/* Shutdown SHM */
|
||||
shm_main_shutdown(daemon);
|
||||
|
||||
daemon->need_to_exit = daemon->workers[0]->need_to_exit;
|
||||
}
|
||||
|
||||
|
|
@ -638,6 +677,8 @@ daemon_cleanup(struct daemon* daemon)
|
|||
slabhash_clear(daemon->env->msg_cache);
|
||||
local_zones_delete(daemon->local_zones);
|
||||
daemon->local_zones = NULL;
|
||||
respip_set_delete(daemon->respip_set);
|
||||
daemon->respip_set = NULL;
|
||||
views_delete(daemon->views);
|
||||
daemon->views = NULL;
|
||||
/* key cache is cleared by module desetup during next daemon_fork() */
|
||||
|
|
@ -670,7 +711,6 @@ daemon_delete(struct daemon* daemon)
|
|||
rrset_cache_delete(daemon->env->rrset_cache);
|
||||
infra_delete(daemon->env->infra_cache);
|
||||
edns_known_options_delete(daemon->env);
|
||||
inplace_cb_lists_delete(daemon->env);
|
||||
}
|
||||
ub_randfree(daemon->rand);
|
||||
alloc_clear(&daemon->superalloc);
|
||||
|
|
|
|||
|
|
@ -56,12 +56,19 @@ struct local_zones;
|
|||
struct views;
|
||||
struct ub_randstate;
|
||||
struct daemon_remote;
|
||||
struct respip_set;
|
||||
struct shm_main_info;
|
||||
|
||||
#include "dnstap/dnstap_config.h"
|
||||
#ifdef USE_DNSTAP
|
||||
struct dt_env;
|
||||
#endif
|
||||
|
||||
#include "dnscrypt/dnscrypt_config.h"
|
||||
#ifdef USE_DNSCRYPT
|
||||
struct dnsc_env;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Structure holding worker list.
|
||||
* Holds globally visible information.
|
||||
|
|
@ -117,6 +124,15 @@ struct daemon {
|
|||
#ifdef USE_DNSTAP
|
||||
/** the dnstap environment master value, copied and changed by threads*/
|
||||
struct dt_env* dtenv;
|
||||
#endif
|
||||
struct shm_main_info* shm_info;
|
||||
/** response-ip set with associated actions and tags. */
|
||||
struct respip_set* respip_set;
|
||||
/** some response-ip tags or actions are configured if true */
|
||||
int use_response_ip;
|
||||
#ifdef USE_DNSCRYPT
|
||||
/** the dnscrypt environment */
|
||||
struct dnsc_env* dnscenv;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -242,6 +242,29 @@ daemon_remote_create(struct config_file* cfg)
|
|||
daemon_remote_delete(rc);
|
||||
return NULL;
|
||||
}
|
||||
#if defined(SSL_OP_NO_TLSv1) && defined(SSL_OP_NO_TLSv1_1)
|
||||
/* if we have tls 1.1 disable 1.0 */
|
||||
if((SSL_CTX_set_options(rc->ctx, SSL_OP_NO_TLSv1) & SSL_OP_NO_TLSv1)
|
||||
!= SSL_OP_NO_TLSv1){
|
||||
log_crypto_err("could not set SSL_OP_NO_TLSv1");
|
||||
daemon_remote_delete(rc);
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
#if defined(SSL_OP_NO_TLSv1_1) && defined(SSL_OP_NO_TLSv1_2)
|
||||
/* if we have tls 1.2 disable 1.1 */
|
||||
if((SSL_CTX_set_options(rc->ctx, SSL_OP_NO_TLSv1_1) & SSL_OP_NO_TLSv1_1)
|
||||
!= SSL_OP_NO_TLSv1_1){
|
||||
log_crypto_err("could not set SSL_OP_NO_TLSv1_1");
|
||||
daemon_remote_delete(rc);
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
#ifdef SHA256_DIGEST_LENGTH
|
||||
/* if we have sha256, set the cipher list to have no known vulns */
|
||||
if(!SSL_CTX_set_cipher_list(rc->ctx, "ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256"))
|
||||
log_crypto_err("coult not set cipher list with SSL_CTX_set_cipher_list");
|
||||
#endif
|
||||
|
||||
if (cfg->remote_control_use_cert == 0) {
|
||||
/* No certificates are requested */
|
||||
|
|
@ -775,6 +798,16 @@ print_stats(SSL* ssl, const char* nm, struct stats_info* s)
|
|||
(unsigned long)s->svr.zero_ttl_responses)) return 0;
|
||||
if(!ssl_printf(ssl, "%s.num.recursivereplies"SQ"%lu\n", nm,
|
||||
(unsigned long)s->mesh_replies_sent)) return 0;
|
||||
#ifdef USE_DNSCRYPT
|
||||
if(!ssl_printf(ssl, "%s.num.dnscrypt.crypted"SQ"%lu\n", nm,
|
||||
(unsigned long)s->svr.num_query_dnscrypt_crypted)) return 0;
|
||||
if(!ssl_printf(ssl, "%s.num.dnscrypt.cert"SQ"%lu\n", nm,
|
||||
(unsigned long)s->svr.num_query_dnscrypt_cert)) return 0;
|
||||
if(!ssl_printf(ssl, "%s.num.dnscrypt.cleartext"SQ"%lu\n", nm,
|
||||
(unsigned long)s->svr.num_query_dnscrypt_cleartext)) return 0;
|
||||
if(!ssl_printf(ssl, "%s.num.dnscrypt.malformed"SQ"%lu\n", nm,
|
||||
(unsigned long)s->svr.num_query_dnscrypt_crypted_malformed)) return 0;
|
||||
#endif
|
||||
if(!ssl_printf(ssl, "%s.requestlist.avg"SQ"%g\n", nm,
|
||||
(s->svr.num_queries_missed_cache+s->svr.num_queries_prefetch)?
|
||||
(double)s->svr.sum_query_list_size/
|
||||
|
|
@ -830,11 +863,15 @@ static int
|
|||
print_mem(SSL* ssl, struct worker* worker, struct daemon* daemon)
|
||||
{
|
||||
int m;
|
||||
size_t msg, rrset, val, iter;
|
||||
size_t msg, rrset, val, iter, respip;
|
||||
#ifdef CLIENT_SUBNET
|
||||
size_t subnet = 0;
|
||||
#endif /* CLIENT_SUBNET */
|
||||
msg = slabhash_get_mem(daemon->env->msg_cache);
|
||||
rrset = slabhash_get_mem(&daemon->env->rrset_cache->table);
|
||||
val=0;
|
||||
iter=0;
|
||||
respip=0;
|
||||
m = modstack_find(&worker->env.mesh->mods, "validator");
|
||||
if(m != -1) {
|
||||
fptr_ok(fptr_whitelist_mod_get_mem(worker->env.mesh->
|
||||
|
|
@ -849,6 +886,22 @@ print_mem(SSL* ssl, struct worker* worker, struct daemon* daemon)
|
|||
iter = (*worker->env.mesh->mods.mod[m]->get_mem)
|
||||
(&worker->env, m);
|
||||
}
|
||||
m = modstack_find(&worker->env.mesh->mods, "respip");
|
||||
if(m != -1) {
|
||||
fptr_ok(fptr_whitelist_mod_get_mem(worker->env.mesh->
|
||||
mods.mod[m]->get_mem));
|
||||
respip = (*worker->env.mesh->mods.mod[m]->get_mem)
|
||||
(&worker->env, m);
|
||||
}
|
||||
#ifdef CLIENT_SUBNET
|
||||
m = modstack_find(&worker->env.mesh->mods, "subnet");
|
||||
if(m != -1) {
|
||||
fptr_ok(fptr_whitelist_mod_get_mem(worker->env.mesh->
|
||||
mods.mod[m]->get_mem));
|
||||
subnet = (*worker->env.mesh->mods.mod[m]->get_mem)
|
||||
(&worker->env, m);
|
||||
}
|
||||
#endif /* CLIENT_SUBNET */
|
||||
|
||||
if(!print_longnum(ssl, "mem.cache.rrset"SQ, rrset))
|
||||
return 0;
|
||||
|
|
@ -858,6 +911,12 @@ print_mem(SSL* ssl, struct worker* worker, struct daemon* daemon)
|
|||
return 0;
|
||||
if(!print_longnum(ssl, "mem.mod.validator"SQ, val))
|
||||
return 0;
|
||||
if(!print_longnum(ssl, "mem.mod.respip"SQ, respip))
|
||||
return 0;
|
||||
#ifdef CLIENT_SUBNET
|
||||
if(!print_longnum(ssl, "mem.mod.subnet"SQ, subnet))
|
||||
return 0;
|
||||
#endif /* CLIENT_SUBNET */
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
@ -1342,6 +1401,13 @@ do_view_zone_add(SSL* ssl, struct worker* worker, char* arg)
|
|||
ssl_printf(ssl,"no view with name: %s\n", arg);
|
||||
return;
|
||||
}
|
||||
if(!v->local_zones) {
|
||||
if(!(v->local_zones = local_zones_create())){
|
||||
lock_rw_unlock(&v->lock);
|
||||
ssl_printf(ssl,"error out of memory\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
do_zone_add(ssl, v->local_zones, arg2);
|
||||
lock_rw_unlock(&v->lock);
|
||||
}
|
||||
|
|
@ -1360,6 +1426,11 @@ do_view_zone_remove(SSL* ssl, struct worker* worker, char* arg)
|
|||
ssl_printf(ssl,"no view with name: %s\n", arg);
|
||||
return;
|
||||
}
|
||||
if(!v->local_zones) {
|
||||
lock_rw_unlock(&v->lock);
|
||||
send_ok(ssl);
|
||||
return;
|
||||
}
|
||||
do_zone_remove(ssl, v->local_zones, arg2);
|
||||
lock_rw_unlock(&v->lock);
|
||||
}
|
||||
|
|
@ -1378,6 +1449,13 @@ do_view_data_add(SSL* ssl, struct worker* worker, char* arg)
|
|||
ssl_printf(ssl,"no view with name: %s\n", arg);
|
||||
return;
|
||||
}
|
||||
if(!v->local_zones) {
|
||||
if(!(v->local_zones = local_zones_create())){
|
||||
lock_rw_unlock(&v->lock);
|
||||
ssl_printf(ssl,"error out of memory\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
do_data_add(ssl, v->local_zones, arg2);
|
||||
lock_rw_unlock(&v->lock);
|
||||
}
|
||||
|
|
@ -1396,6 +1474,11 @@ do_view_data_remove(SSL* ssl, struct worker* worker, char* arg)
|
|||
ssl_printf(ssl,"no view with name: %s\n", arg);
|
||||
return;
|
||||
}
|
||||
if(!v->local_zones) {
|
||||
lock_rw_unlock(&v->lock);
|
||||
send_ok(ssl);
|
||||
return;
|
||||
}
|
||||
do_data_remove(ssl, v->local_zones, arg2);
|
||||
lock_rw_unlock(&v->lock);
|
||||
}
|
||||
|
|
@ -2531,7 +2614,9 @@ do_view_list_local_zones(SSL* ssl, struct worker* worker, char* arg)
|
|||
ssl_printf(ssl,"no view with name: %s\n", arg);
|
||||
return;
|
||||
}
|
||||
do_list_local_zones(ssl, v->local_zones);
|
||||
if(v->local_zones) {
|
||||
do_list_local_zones(ssl, v->local_zones);
|
||||
}
|
||||
lock_rw_unlock(&v->lock);
|
||||
}
|
||||
|
||||
|
|
@ -2545,7 +2630,9 @@ do_view_list_local_data(SSL* ssl, struct worker* worker, char* arg)
|
|||
ssl_printf(ssl,"no view with name: %s\n", arg);
|
||||
return;
|
||||
}
|
||||
do_list_local_data(ssl, worker, v->local_zones);
|
||||
if(v->local_zones) {
|
||||
do_list_local_data(ssl, worker, v->local_zones);
|
||||
}
|
||||
lock_rw_unlock(&v->lock);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -232,6 +232,14 @@ void server_stats_add(struct stats_info* total, struct stats_info* a)
|
|||
total->svr.num_queries_missed_cache += a->svr.num_queries_missed_cache;
|
||||
total->svr.num_queries_prefetch += a->svr.num_queries_prefetch;
|
||||
total->svr.sum_query_list_size += a->svr.sum_query_list_size;
|
||||
#ifdef USE_DNSCRYPT
|
||||
total->svr.num_query_dnscrypt_crypted += a->svr.num_query_dnscrypt_crypted;
|
||||
total->svr.num_query_dnscrypt_cert += a->svr.num_query_dnscrypt_cert;
|
||||
total->svr.num_query_dnscrypt_cleartext += \
|
||||
a->svr.num_query_dnscrypt_cleartext;
|
||||
total->svr.num_query_dnscrypt_crypted_malformed += \
|
||||
a->svr.num_query_dnscrypt_crypted_malformed;
|
||||
#endif
|
||||
/* the max size reached is upped to higher of both */
|
||||
if(a->svr.max_query_list_size > total->svr.max_query_list_size)
|
||||
total->svr.max_query_list_size = a->svr.max_query_list_size;
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@
|
|||
#ifndef DAEMON_STATS_H
|
||||
#define DAEMON_STATS_H
|
||||
#include "util/timehist.h"
|
||||
#include "dnscrypt/dnscrypt_config.h"
|
||||
struct worker;
|
||||
struct config_file;
|
||||
struct comm_point;
|
||||
|
|
@ -149,6 +150,16 @@ struct server_stats {
|
|||
size_t infra_cache_count;
|
||||
/** number of key cache entries */
|
||||
size_t key_cache_count;
|
||||
#ifdef USE_DNSCRYPT
|
||||
/** number of queries that used dnscrypt */
|
||||
size_t num_query_dnscrypt_crypted;
|
||||
/** number of queries that queried dnscrypt certificates */
|
||||
size_t num_query_dnscrypt_cert;
|
||||
/** number of queries in clear text and not asking for the certificates */
|
||||
size_t num_query_dnscrypt_cleartext;
|
||||
/** number of malformed encrypted queries */
|
||||
size_t num_query_dnscrypt_crypted_malformed;
|
||||
#endif
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
372
daemon/worker.c
372
daemon/worker.c
|
|
@ -69,9 +69,13 @@
|
|||
#include "iterator/iter_hints.h"
|
||||
#include "validator/autotrust.h"
|
||||
#include "validator/val_anchor.h"
|
||||
#include "respip/respip.h"
|
||||
#include "libunbound/context.h"
|
||||
#include "libunbound/libworker.h"
|
||||
#include "sldns/sbuffer.h"
|
||||
#include "sldns/wire2str.h"
|
||||
#include "util/shm_side/shm_main.h"
|
||||
#include "dnscrypt/dnscrypt.h"
|
||||
|
||||
#ifdef HAVE_SYS_TYPES_H
|
||||
# include <sys/types.h>
|
||||
|
|
@ -113,6 +117,9 @@ worker_mem_report(struct worker* ATTR_UNUSED(worker),
|
|||
size_t total, front, back, mesh, msg, rrset, infra, ac, superac;
|
||||
size_t me, iter, val, anch;
|
||||
int i;
|
||||
#ifdef CLIENT_SUBNET
|
||||
size_t subnet = 0;
|
||||
#endif /* CLIENT_SUBNET */
|
||||
if(verbosity < VERB_ALGO)
|
||||
return;
|
||||
front = listen_get_mem(worker->front);
|
||||
|
|
@ -132,6 +139,12 @@ worker_mem_report(struct worker* ATTR_UNUSED(worker),
|
|||
if(strcmp(worker->env.mesh->mods.mod[i]->name, "validator")==0)
|
||||
val += (*worker->env.mesh->mods.mod[i]->get_mem)
|
||||
(&worker->env, i);
|
||||
#ifdef CLIENT_SUBNET
|
||||
else if(strcmp(worker->env.mesh->mods.mod[i]->name,
|
||||
"subnet")==0)
|
||||
subnet += (*worker->env.mesh->mods.mod[i]->get_mem)
|
||||
(&worker->env, i);
|
||||
#endif /* CLIENT_SUBNET */
|
||||
else iter += (*worker->env.mesh->mods.mod[i]->get_mem)
|
||||
(&worker->env, i);
|
||||
}
|
||||
|
|
@ -149,6 +162,17 @@ worker_mem_report(struct worker* ATTR_UNUSED(worker),
|
|||
me += serviced_get_mem(cur_serv);
|
||||
}
|
||||
total = front+back+mesh+msg+rrset+infra+iter+val+ac+superac+me;
|
||||
#ifdef CLIENT_SUBNET
|
||||
total += subnet;
|
||||
log_info("Memory conditions: %u front=%u back=%u mesh=%u msg=%u "
|
||||
"rrset=%u infra=%u iter=%u val=%u subnet=%u anchors=%u "
|
||||
"alloccache=%u globalalloccache=%u me=%u",
|
||||
(unsigned)total, (unsigned)front, (unsigned)back,
|
||||
(unsigned)mesh, (unsigned)msg, (unsigned)rrset, (unsigned)infra,
|
||||
(unsigned)iter, (unsigned)val,
|
||||
(unsigned)subnet, (unsigned)anch, (unsigned)ac,
|
||||
(unsigned)superac, (unsigned)me);
|
||||
#else /* no CLIENT_SUBNET */
|
||||
log_info("Memory conditions: %u front=%u back=%u mesh=%u msg=%u "
|
||||
"rrset=%u infra=%u iter=%u val=%u anchors=%u "
|
||||
"alloccache=%u globalalloccache=%u me=%u",
|
||||
|
|
@ -156,11 +180,15 @@ worker_mem_report(struct worker* ATTR_UNUSED(worker),
|
|||
(unsigned)mesh, (unsigned)msg, (unsigned)rrset,
|
||||
(unsigned)infra, (unsigned)iter, (unsigned)val, (unsigned)anch,
|
||||
(unsigned)ac, (unsigned)superac, (unsigned)me);
|
||||
#endif /* CLIENT_SUBNET */
|
||||
log_info("Total heap memory estimate: %u total-alloc: %u "
|
||||
"total-free: %u", (unsigned)total,
|
||||
(unsigned)unbound_mem_alloc, (unsigned)unbound_mem_freed);
|
||||
#else /* no UNBOUND_ALLOC_STATS */
|
||||
size_t val = 0;
|
||||
#ifdef CLIENT_SUBNET
|
||||
size_t subnet = 0;
|
||||
#endif /* CLIENT_SUBNET */
|
||||
int i;
|
||||
if(verbosity < VERB_QUERY)
|
||||
return;
|
||||
|
|
@ -170,12 +198,27 @@ worker_mem_report(struct worker* ATTR_UNUSED(worker),
|
|||
if(strcmp(worker->env.mesh->mods.mod[i]->name, "validator")==0)
|
||||
val += (*worker->env.mesh->mods.mod[i]->get_mem)
|
||||
(&worker->env, i);
|
||||
#ifdef CLIENT_SUBNET
|
||||
else if(strcmp(worker->env.mesh->mods.mod[i]->name,
|
||||
"subnet")==0)
|
||||
subnet += (*worker->env.mesh->mods.mod[i]->get_mem)
|
||||
(&worker->env, i);
|
||||
#endif /* CLIENT_SUBNET */
|
||||
}
|
||||
#ifdef CLIENT_SUBNET
|
||||
verbose(VERB_QUERY, "cache memory msg=%u rrset=%u infra=%u val=%u "
|
||||
"subnet=%u",
|
||||
(unsigned)slabhash_get_mem(worker->env.msg_cache),
|
||||
(unsigned)slabhash_get_mem(&worker->env.rrset_cache->table),
|
||||
(unsigned)infra_get_mem(worker->env.infra_cache),
|
||||
(unsigned)val, (unsigned)subnet);
|
||||
#else /* no CLIENT_SUBNET */
|
||||
verbose(VERB_QUERY, "cache memory msg=%u rrset=%u infra=%u val=%u",
|
||||
(unsigned)slabhash_get_mem(worker->env.msg_cache),
|
||||
(unsigned)slabhash_get_mem(&worker->env.rrset_cache->table),
|
||||
(unsigned)infra_get_mem(worker->env.infra_cache),
|
||||
(unsigned)val);
|
||||
#endif /* CLIENT_SUBNET */
|
||||
#endif /* UNBOUND_ALLOC_STATS */
|
||||
}
|
||||
|
||||
|
|
@ -510,17 +553,70 @@ answer_norec_from_cache(struct worker* worker, struct query_info* qinfo,
|
|||
return 1;
|
||||
}
|
||||
|
||||
/** answer query from the cache */
|
||||
/** Apply, if applicable, a response IP action to a cached answer.
|
||||
* If the answer is rewritten as a result of an action, '*encode_repp' will
|
||||
* point to the reply info containing the modified answer. '*encode_repp' will
|
||||
* be intact otherwise.
|
||||
* It returns 1 on success, 0 otherwise. */
|
||||
static int
|
||||
apply_respip_action(struct worker* worker, const struct query_info* qinfo,
|
||||
struct respip_client_info* cinfo, struct reply_info* rep,
|
||||
struct comm_reply* repinfo, struct ub_packed_rrset_key** alias_rrset,
|
||||
struct reply_info** encode_repp)
|
||||
{
|
||||
struct respip_action_info actinfo = {respip_none, NULL};
|
||||
|
||||
if(qinfo->qtype != LDNS_RR_TYPE_A &&
|
||||
qinfo->qtype != LDNS_RR_TYPE_AAAA &&
|
||||
qinfo->qtype != LDNS_RR_TYPE_ANY)
|
||||
return 1;
|
||||
|
||||
if(!respip_rewrite_reply(qinfo, cinfo, rep, encode_repp, &actinfo,
|
||||
alias_rrset, 0, worker->scratchpad))
|
||||
return 0;
|
||||
|
||||
/* xxx_deny actions mean dropping the reply, unless the original reply
|
||||
* was redirected to response-ip data. */
|
||||
if((actinfo.action == respip_deny ||
|
||||
actinfo.action == respip_inform_deny) &&
|
||||
*encode_repp == rep)
|
||||
*encode_repp = NULL;
|
||||
|
||||
/* If address info is returned, it means the action should be an
|
||||
* 'inform' variant and the information should be logged. */
|
||||
if(actinfo.addrinfo) {
|
||||
respip_inform_print(actinfo.addrinfo, qinfo->qname,
|
||||
qinfo->qtype, qinfo->qclass, qinfo->local_alias,
|
||||
repinfo);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** answer query from the cache.
|
||||
* Normally, the answer message will be built in repinfo->c->buffer; if the
|
||||
* answer is supposed to be suppressed or the answer is supposed to be an
|
||||
* incomplete CNAME chain, the buffer is explicitly cleared to signal the
|
||||
* caller as such. In the latter case *partial_rep will point to the incomplete
|
||||
* reply, and this function is (possibly) supposed to be called again with that
|
||||
* *partial_rep value to complete the chain. In addition, if the query should
|
||||
* be completely dropped, '*need_drop' will be set to 1. */
|
||||
static int
|
||||
answer_from_cache(struct worker* worker, struct query_info* qinfo,
|
||||
struct respip_client_info* cinfo, int* need_drop,
|
||||
struct ub_packed_rrset_key** alias_rrset,
|
||||
struct reply_info** partial_repp,
|
||||
struct reply_info* rep, uint16_t id, uint16_t flags,
|
||||
struct comm_reply* repinfo, struct edns_data* edns)
|
||||
{
|
||||
time_t timenow = *worker->env.now;
|
||||
uint16_t udpsize = edns->udp_size;
|
||||
struct reply_info* encode_rep = rep;
|
||||
struct reply_info* partial_rep = *partial_repp;
|
||||
int secure;
|
||||
int must_validate = (!(flags&BIT_CD) || worker->env.cfg->ignore_cd)
|
||||
&& worker->env.need_to_validate;
|
||||
*partial_repp = NULL; /* avoid accidental further pass */
|
||||
if(worker->env.cfg->serve_expired) {
|
||||
/* always lock rrsets, rep->ttl is ignored */
|
||||
if(!rrset_array_lock(rep->ref, rep->rrset_count, 0))
|
||||
|
|
@ -600,7 +696,33 @@ answer_from_cache(struct worker* worker, struct query_info* qinfo,
|
|||
if(!inplace_cb_reply_cache_call(&worker->env, qinfo, NULL, rep,
|
||||
(int)(flags&LDNS_RCODE_MASK), edns, worker->scratchpad))
|
||||
goto bail_out;
|
||||
if(!reply_info_answer_encode(qinfo, rep, id, flags,
|
||||
*alias_rrset = NULL; /* avoid confusion if caller set it to non-NULL */
|
||||
if(worker->daemon->use_response_ip && !partial_rep &&
|
||||
!apply_respip_action(worker, qinfo, cinfo, rep, repinfo, alias_rrset,
|
||||
&encode_rep)) {
|
||||
goto bail_out;
|
||||
} else if(partial_rep &&
|
||||
!respip_merge_cname(partial_rep, qinfo, rep, cinfo,
|
||||
must_validate, &encode_rep, worker->scratchpad)) {
|
||||
goto bail_out;
|
||||
}
|
||||
if(encode_rep != rep)
|
||||
secure = 0; /* if rewritten, it can't be considered "secure" */
|
||||
if(!encode_rep || *alias_rrset) {
|
||||
sldns_buffer_clear(repinfo->c->buffer);
|
||||
sldns_buffer_flip(repinfo->c->buffer);
|
||||
if(!encode_rep)
|
||||
*need_drop = 1;
|
||||
else {
|
||||
/* If a partial CNAME chain is found, we first need to
|
||||
* make a copy of the reply in the scratchpad so we
|
||||
* can release the locks and lookup the cache again. */
|
||||
*partial_repp = reply_info_copy(encode_rep, NULL,
|
||||
worker->scratchpad);
|
||||
if(!*partial_repp)
|
||||
goto bail_out;
|
||||
}
|
||||
} else if(!reply_info_answer_encode(qinfo, encode_rep, id, flags,
|
||||
repinfo->c->buffer, timenow, 1, worker->scratchpad,
|
||||
udpsize, edns, (int)(edns->bits & EDNS_DO), secure)) {
|
||||
if(!inplace_cb_reply_servfail_call(&worker->env, qinfo, NULL, NULL,
|
||||
|
|
@ -621,14 +743,18 @@ answer_from_cache(struct worker* worker, struct query_info* qinfo,
|
|||
return 1;
|
||||
}
|
||||
|
||||
/** Reply to client and perform prefetch to keep cache up to date */
|
||||
/** Reply to client and perform prefetch to keep cache up to date.
|
||||
* If the buffer for the reply is empty, it indicates that only prefetch is
|
||||
* necessary and the reply should be suppressed (because it's dropped or
|
||||
* being deferred). */
|
||||
static void
|
||||
reply_and_prefetch(struct worker* worker, struct query_info* qinfo,
|
||||
uint16_t flags, struct comm_reply* repinfo, time_t leeway)
|
||||
{
|
||||
/* first send answer to client to keep its latency
|
||||
* as small as a cachereply */
|
||||
comm_point_send_reply(repinfo);
|
||||
if(sldns_buffer_limit(repinfo->c->buffer) != 0)
|
||||
comm_point_send_reply(repinfo);
|
||||
server_stats_prefetch(&worker->stats, worker);
|
||||
|
||||
/* create the prefetch in the mesh as a normal lookup without
|
||||
|
|
@ -643,36 +769,41 @@ reply_and_prefetch(struct worker* worker, struct query_info* qinfo,
|
|||
* Fill CH class answer into buffer. Keeps query.
|
||||
* @param pkt: buffer
|
||||
* @param str: string to put into text record (<255).
|
||||
* array of strings, every string becomes a text record.
|
||||
* @param num: number of strings in array.
|
||||
* @param edns: edns reply information.
|
||||
* @param worker: worker with scratch region.
|
||||
*/
|
||||
static void
|
||||
chaos_replystr(sldns_buffer* pkt, const char* str, struct edns_data* edns,
|
||||
chaos_replystr(sldns_buffer* pkt, char** str, int num, struct edns_data* edns,
|
||||
struct worker* worker)
|
||||
{
|
||||
size_t len = strlen(str);
|
||||
int i;
|
||||
unsigned int rd = LDNS_RD_WIRE(sldns_buffer_begin(pkt));
|
||||
unsigned int cd = LDNS_CD_WIRE(sldns_buffer_begin(pkt));
|
||||
if(len>255) len=255; /* cap size of TXT record */
|
||||
sldns_buffer_clear(pkt);
|
||||
sldns_buffer_skip(pkt, (ssize_t)sizeof(uint16_t)); /* skip id */
|
||||
sldns_buffer_write_u16(pkt, (uint16_t)(BIT_QR|BIT_RA));
|
||||
if(rd) LDNS_RD_SET(sldns_buffer_begin(pkt));
|
||||
if(cd) LDNS_CD_SET(sldns_buffer_begin(pkt));
|
||||
sldns_buffer_write_u16(pkt, 1); /* qdcount */
|
||||
sldns_buffer_write_u16(pkt, 1); /* ancount */
|
||||
sldns_buffer_write_u16(pkt, (uint16_t)num); /* ancount */
|
||||
sldns_buffer_write_u16(pkt, 0); /* nscount */
|
||||
sldns_buffer_write_u16(pkt, 0); /* arcount */
|
||||
(void)query_dname_len(pkt); /* skip qname */
|
||||
sldns_buffer_skip(pkt, (ssize_t)sizeof(uint16_t)); /* skip qtype */
|
||||
sldns_buffer_skip(pkt, (ssize_t)sizeof(uint16_t)); /* skip qclass */
|
||||
sldns_buffer_write_u16(pkt, 0xc00c); /* compr ptr to query */
|
||||
sldns_buffer_write_u16(pkt, LDNS_RR_TYPE_TXT);
|
||||
sldns_buffer_write_u16(pkt, LDNS_RR_CLASS_CH);
|
||||
sldns_buffer_write_u32(pkt, 0); /* TTL */
|
||||
sldns_buffer_write_u16(pkt, sizeof(uint8_t) + len);
|
||||
sldns_buffer_write_u8(pkt, len);
|
||||
sldns_buffer_write(pkt, str, len);
|
||||
for(i=0; i<num; i++) {
|
||||
size_t len = strlen(str[i]);
|
||||
if(len>255) len=255; /* cap size of TXT record */
|
||||
sldns_buffer_write_u16(pkt, 0xc00c); /* compr ptr to query */
|
||||
sldns_buffer_write_u16(pkt, LDNS_RR_TYPE_TXT);
|
||||
sldns_buffer_write_u16(pkt, LDNS_RR_CLASS_CH);
|
||||
sldns_buffer_write_u32(pkt, 0); /* TTL */
|
||||
sldns_buffer_write_u16(pkt, sizeof(uint8_t) + len);
|
||||
sldns_buffer_write_u8(pkt, len);
|
||||
sldns_buffer_write(pkt, str[i], len);
|
||||
}
|
||||
sldns_buffer_flip(pkt);
|
||||
edns->edns_version = EDNS_ADVERTISED_VERSION;
|
||||
edns->udp_size = EDNS_ADVERTISED_SIZE;
|
||||
|
|
@ -683,6 +814,70 @@ chaos_replystr(sldns_buffer* pkt, const char* str, struct edns_data* edns,
|
|||
attach_edns_record(pkt, edns);
|
||||
}
|
||||
|
||||
/** Reply with one string */
|
||||
static void
|
||||
chaos_replyonestr(sldns_buffer* pkt, const char* str, struct edns_data* edns,
|
||||
struct worker* worker)
|
||||
{
|
||||
chaos_replystr(pkt, (char**)&str, 1, edns, worker);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create CH class trustanchor answer.
|
||||
* @param pkt: buffer
|
||||
* @param edns: edns reply information.
|
||||
* @param w: worker with scratch region.
|
||||
*/
|
||||
static void
|
||||
chaos_trustanchor(sldns_buffer* pkt, struct edns_data* edns, struct worker* w)
|
||||
{
|
||||
#define TA_RESPONSE_MAX_TXT 16 /* max number of TXT records */
|
||||
#define TA_RESPONSE_MAX_TAGS 32 /* max number of tags printed per zone */
|
||||
char* str_array[TA_RESPONSE_MAX_TXT];
|
||||
uint16_t tags[TA_RESPONSE_MAX_TAGS];
|
||||
int num = 0;
|
||||
struct trust_anchor* ta;
|
||||
|
||||
if(!w->env.need_to_validate) {
|
||||
/* no validator module, reply no trustanchors */
|
||||
chaos_replystr(pkt, NULL, 0, edns, w);
|
||||
return;
|
||||
}
|
||||
|
||||
/* fill the string with contents */
|
||||
lock_basic_lock(&w->env.anchors->lock);
|
||||
RBTREE_FOR(ta, struct trust_anchor*, w->env.anchors->tree) {
|
||||
char* str;
|
||||
size_t i, numtag, str_len = 255;
|
||||
if(num == TA_RESPONSE_MAX_TXT) continue;
|
||||
str = (char*)regional_alloc(w->scratchpad, str_len);
|
||||
if(!str) continue;
|
||||
lock_basic_lock(&ta->lock);
|
||||
numtag = anchor_list_keytags(ta, tags, TA_RESPONSE_MAX_TAGS);
|
||||
if(numtag == 0) {
|
||||
/* empty, insecure point */
|
||||
lock_basic_unlock(&ta->lock);
|
||||
continue;
|
||||
}
|
||||
str_array[num] = str;
|
||||
num++;
|
||||
|
||||
/* spool name of anchor */
|
||||
(void)sldns_wire2str_dname_buf(ta->name, ta->namelen, str, str_len);
|
||||
str_len -= strlen(str); str += strlen(str);
|
||||
/* spool tags */
|
||||
for(i=0; i<numtag; i++) {
|
||||
snprintf(str, str_len, " %u", (unsigned)tags[i]);
|
||||
str_len -= strlen(str); str += strlen(str);
|
||||
}
|
||||
lock_basic_unlock(&ta->lock);
|
||||
}
|
||||
lock_basic_unlock(&w->env.anchors->lock);
|
||||
|
||||
chaos_replystr(pkt, str_array, num, edns, w);
|
||||
regional_free_all(w->scratchpad);
|
||||
}
|
||||
|
||||
/**
|
||||
* Answer CH class queries.
|
||||
* @param w: worker
|
||||
|
|
@ -709,13 +904,13 @@ answer_chaos(struct worker* w, struct query_info* qinfo,
|
|||
char buf[MAXHOSTNAMELEN+1];
|
||||
if (gethostname(buf, MAXHOSTNAMELEN) == 0) {
|
||||
buf[MAXHOSTNAMELEN] = 0;
|
||||
chaos_replystr(pkt, buf, edns, w);
|
||||
chaos_replyonestr(pkt, buf, edns, w);
|
||||
} else {
|
||||
log_err("gethostname: %s", strerror(errno));
|
||||
chaos_replystr(pkt, "no hostname", edns, w);
|
||||
chaos_replyonestr(pkt, "no hostname", edns, w);
|
||||
}
|
||||
}
|
||||
else chaos_replystr(pkt, cfg->identity, edns, w);
|
||||
else chaos_replyonestr(pkt, cfg->identity, edns, w);
|
||||
return 1;
|
||||
}
|
||||
if(query_dname_compare(qinfo->qname,
|
||||
|
|
@ -726,10 +921,19 @@ answer_chaos(struct worker* w, struct query_info* qinfo,
|
|||
if(cfg->hide_version)
|
||||
return 0;
|
||||
if(cfg->version==NULL || cfg->version[0]==0)
|
||||
chaos_replystr(pkt, PACKAGE_STRING, edns, w);
|
||||
else chaos_replystr(pkt, cfg->version, edns, w);
|
||||
chaos_replyonestr(pkt, PACKAGE_STRING, edns, w);
|
||||
else chaos_replyonestr(pkt, cfg->version, edns, w);
|
||||
return 1;
|
||||
}
|
||||
if(query_dname_compare(qinfo->qname,
|
||||
(uint8_t*)"\013trustanchor\007unbound") == 0)
|
||||
{
|
||||
if(cfg->hide_trustanchor)
|
||||
return 0;
|
||||
chaos_trustanchor(pkt, edns, w);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -794,12 +998,60 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
|
|||
enum acl_access acl;
|
||||
struct acl_addr* acladdr;
|
||||
int rc = 0;
|
||||
int need_drop = 0;
|
||||
/* We might have to chase a CNAME chain internally, in which case
|
||||
* we'll have up to two replies and combine them to build a complete
|
||||
* answer. These variables control this case. */
|
||||
struct ub_packed_rrset_key* alias_rrset = NULL;
|
||||
struct reply_info* partial_rep = NULL;
|
||||
struct query_info* lookup_qinfo = &qinfo;
|
||||
struct query_info qinfo_tmp; /* placeholdoer for lookup_qinfo */
|
||||
struct respip_client_info* cinfo = NULL, cinfo_tmp;
|
||||
|
||||
if(error != NETEVENT_NOERROR) {
|
||||
/* some bad tcp query DNS formats give these error calls */
|
||||
verbose(VERB_ALGO, "handle request called with err=%d", error);
|
||||
return 0;
|
||||
}
|
||||
#ifdef USE_DNSCRYPT
|
||||
repinfo->max_udp_size = worker->daemon->cfg->max_udp_size;
|
||||
if(!dnsc_handle_curved_request(worker->daemon->dnscenv, repinfo)) {
|
||||
worker->stats.num_query_dnscrypt_crypted_malformed++;
|
||||
return 0;
|
||||
}
|
||||
if(c->dnscrypt && !repinfo->is_dnscrypted) {
|
||||
char buf[LDNS_MAX_DOMAINLEN+1];
|
||||
// Check if this is unencrypted and asking for certs
|
||||
if(worker_check_request(c->buffer, worker) != 0) {
|
||||
verbose(VERB_ALGO, "dnscrypt: worker check request: bad query.");
|
||||
log_addr(VERB_CLIENT,"from",&repinfo->addr, repinfo->addrlen);
|
||||
comm_point_drop_reply(repinfo);
|
||||
return 0;
|
||||
}
|
||||
if(!query_info_parse(&qinfo, c->buffer)) {
|
||||
verbose(VERB_ALGO, "dnscrypt: worker parse request: formerror.");
|
||||
log_addr(VERB_CLIENT,"from",&repinfo->addr, repinfo->addrlen);
|
||||
comm_point_drop_reply(repinfo);
|
||||
return 0;
|
||||
}
|
||||
dname_str(qinfo.qname, buf);
|
||||
if(!(qinfo.qtype == LDNS_RR_TYPE_TXT &&
|
||||
strcasecmp(buf, worker->daemon->dnscenv->provider_name) == 0)) {
|
||||
verbose(VERB_ALGO,
|
||||
"dnscrypt: not TXT %s. Receive: %s %s",
|
||||
worker->daemon->dnscenv->provider_name,
|
||||
sldns_rr_descript(qinfo.qtype)->_name,
|
||||
buf);
|
||||
comm_point_drop_reply(repinfo);
|
||||
worker->stats.num_query_dnscrypt_cleartext++;
|
||||
return 0;
|
||||
}
|
||||
worker->stats.num_query_dnscrypt_cert++;
|
||||
sldns_buffer_rewind(c->buffer);
|
||||
} else if(c->dnscrypt && repinfo->is_dnscrypted) {
|
||||
worker->stats.num_query_dnscrypt_crypted++;
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_DNSTAP
|
||||
if(worker->dtenv.log_client_query_messages)
|
||||
dt_msg_send_client_query(&worker->dtenv, &repinfo->addr, c->type,
|
||||
|
|
@ -1036,16 +1288,43 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
|
|||
qinfo.qname_len = d->rr_len[0] - 2;
|
||||
}
|
||||
|
||||
/* If we may apply IP-based actions to the answer, build the client
|
||||
* information. As this can be expensive, skip it if there is
|
||||
* absolutely no possibility of it. */
|
||||
if(worker->daemon->use_response_ip &&
|
||||
(qinfo.qtype == LDNS_RR_TYPE_A ||
|
||||
qinfo.qtype == LDNS_RR_TYPE_AAAA ||
|
||||
qinfo.qtype == LDNS_RR_TYPE_ANY)) {
|
||||
cinfo_tmp.taglist = acladdr->taglist;
|
||||
cinfo_tmp.taglen = acladdr->taglen;
|
||||
cinfo_tmp.tag_actions = acladdr->tag_actions;
|
||||
cinfo_tmp.tag_actions_size = acladdr->tag_actions_size;
|
||||
cinfo_tmp.tag_datas = acladdr->tag_datas;
|
||||
cinfo_tmp.tag_datas_size = acladdr->tag_datas_size;
|
||||
cinfo_tmp.view = acladdr->view;
|
||||
cinfo_tmp.respip_set = worker->daemon->respip_set;
|
||||
cinfo = &cinfo_tmp;
|
||||
}
|
||||
|
||||
lookup_cache:
|
||||
/* Lookup the cache. In case we chase an intermediate CNAME chain
|
||||
* this is a two-pass operation, and lookup_qinfo is different for
|
||||
* each pass. We should still pass the original qinfo to
|
||||
* answer_from_cache(), however, since it's used to build the reply. */
|
||||
if(!edns_bypass_cache_stage(edns.opt_list, &worker->env)) {
|
||||
h = query_info_hash(&qinfo, sldns_buffer_read_u16_at(c->buffer, 2));
|
||||
if((e=slabhash_lookup(worker->env.msg_cache, h, &qinfo, 0))) {
|
||||
h = query_info_hash(lookup_qinfo, sldns_buffer_read_u16_at(c->buffer, 2));
|
||||
if((e=slabhash_lookup(worker->env.msg_cache, h, lookup_qinfo, 0))) {
|
||||
/* answer from cache - we have acquired a readlock on it */
|
||||
if(answer_from_cache(worker, &qinfo,
|
||||
cinfo, &need_drop, &alias_rrset, &partial_rep,
|
||||
(struct reply_info*)e->data,
|
||||
*(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 */
|
||||
/* prefetch it if the prefetch TTL expired.
|
||||
* Note that if there is more than one pass
|
||||
* its qname must be that used for cache
|
||||
* lookup. */
|
||||
if((worker->env.cfg->prefetch || worker->env.cfg->serve_expired)
|
||||
&& *worker->env.now >=
|
||||
((struct reply_info*)e->data)->prefetch_ttl) {
|
||||
|
|
@ -1055,16 +1334,38 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
|
|||
< *worker->env.now)
|
||||
leeway = 0;
|
||||
lock_rw_unlock(&e->lock);
|
||||
reply_and_prefetch(worker, &qinfo,
|
||||
reply_and_prefetch(worker, lookup_qinfo,
|
||||
sldns_buffer_read_u16_at(c->buffer, 2),
|
||||
repinfo, leeway);
|
||||
rc = 0;
|
||||
if(!partial_rep) {
|
||||
rc = 0;
|
||||
regional_free_all(worker->scratchpad);
|
||||
goto send_reply_rc;
|
||||
}
|
||||
} else if(!partial_rep) {
|
||||
lock_rw_unlock(&e->lock);
|
||||
regional_free_all(worker->scratchpad);
|
||||
goto send_reply_rc;
|
||||
goto send_reply;
|
||||
}
|
||||
/* We've found a partial reply ending with an
|
||||
* alias. Replace the lookup qinfo for the
|
||||
* alias target and lookup the cache again to
|
||||
* (possibly) complete the reply. As we're
|
||||
* passing the "base" reply, there will be no
|
||||
* more alias chasing. */
|
||||
lock_rw_unlock(&e->lock);
|
||||
regional_free_all(worker->scratchpad);
|
||||
goto send_reply;
|
||||
memset(&qinfo_tmp, 0, sizeof(qinfo_tmp));
|
||||
get_cname_target(alias_rrset, &qinfo_tmp.qname,
|
||||
&qinfo_tmp.qname_len);
|
||||
if(!qinfo_tmp.qname) {
|
||||
log_err("unexpected: invalid answer alias");
|
||||
regional_free_all(worker->scratchpad);
|
||||
return 0; /* drop query */
|
||||
}
|
||||
qinfo_tmp.qtype = qinfo.qtype;
|
||||
qinfo_tmp.qclass = qinfo.qclass;
|
||||
lookup_qinfo = &qinfo_tmp;
|
||||
goto lookup_cache;
|
||||
}
|
||||
verbose(VERB_ALGO, "answer from the cache failed");
|
||||
lock_rw_unlock(&e->lock);
|
||||
|
|
@ -1093,7 +1394,7 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
|
|||
}
|
||||
|
||||
/* grab a work request structure for this new request */
|
||||
mesh_new_client(worker->env.mesh, &qinfo,
|
||||
mesh_new_client(worker->env.mesh, &qinfo, cinfo,
|
||||
sldns_buffer_read_u16_at(c->buffer, 2),
|
||||
&edns, repinfo, *(uint16_t*)(void *)sldns_buffer_begin(c->buffer));
|
||||
regional_free_all(worker->scratchpad);
|
||||
|
|
@ -1103,6 +1404,10 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
|
|||
send_reply:
|
||||
rc = 1;
|
||||
send_reply_rc:
|
||||
if(need_drop) {
|
||||
comm_point_drop_reply(repinfo);
|
||||
return 0;
|
||||
}
|
||||
#ifdef USE_DNSTAP
|
||||
if(worker->dtenv.log_client_response_messages)
|
||||
dt_msg_send_client_response(&worker->dtenv, &repinfo->addr,
|
||||
|
|
@ -1114,6 +1419,11 @@ send_reply_rc:
|
|||
log_reply_info(0, &qinfo, &repinfo->addr, repinfo->addrlen,
|
||||
tv, 1, c->buffer);
|
||||
}
|
||||
#ifdef USE_DNSCRYPT
|
||||
if(!dnsc_handle_uncurved_request(repinfo)) {
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
|
@ -1169,6 +1479,10 @@ void worker_stat_timer_cb(void* arg)
|
|||
server_stats_log(&worker->stats, worker, worker->thread_num);
|
||||
mesh_stats(worker->env.mesh, "mesh has");
|
||||
worker_mem_report(worker, NULL);
|
||||
/* SHM is enabled, process data to SHM */
|
||||
if (worker->daemon->cfg->shm_enable) {
|
||||
shm_main_run(worker);
|
||||
}
|
||||
if(!worker->daemon->cfg->stat_cumulative) {
|
||||
worker_stats_clear(worker);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -411,31 +411,6 @@ handle_ipv6_ptr(struct module_qstate* qstate, int id)
|
|||
return module_wait_subquery;
|
||||
}
|
||||
|
||||
/** allocate (special) rrset keys, return 0 on error */
|
||||
static int
|
||||
repinfo_alloc_rrset_keys(struct reply_info* rep,
|
||||
struct regional* region)
|
||||
{
|
||||
size_t i;
|
||||
for(i=0; i<rep->rrset_count; i++) {
|
||||
if(region) {
|
||||
rep->rrsets[i] = (struct ub_packed_rrset_key*)
|
||||
regional_alloc(region,
|
||||
sizeof(struct ub_packed_rrset_key));
|
||||
if(rep->rrsets[i]) {
|
||||
memset(rep->rrsets[i], 0,
|
||||
sizeof(struct ub_packed_rrset_key));
|
||||
rep->rrsets[i]->entry.key = rep->rrsets[i];
|
||||
}
|
||||
}
|
||||
else return 0;/* rep->rrsets[i] = alloc_special_obtain(alloc);*/
|
||||
if(!rep->rrsets[i])
|
||||
return 0;
|
||||
rep->rrsets[i]->entry.data = NULL;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static enum module_ext_state
|
||||
generate_type_A_query(struct module_qstate* qstate, int id)
|
||||
{
|
||||
|
|
@ -707,7 +682,7 @@ dns64_adjust_a(int id, struct module_qstate* super, struct module_qstate* qstate
|
|||
return;
|
||||
|
||||
/* allocate ub_key structures special or not */
|
||||
if(!repinfo_alloc_rrset_keys(cp, super->region)) {
|
||||
if(!reply_info_alloc_rrset_keys(cp, NULL, super->region)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
32
dnscrypt/cert.h
Normal file
32
dnscrypt/cert.h
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
#ifndef UNBOUND_DNSCRYPT_CERT_H
|
||||
#define UNBOUND_DNSCRYPT_CERT_H
|
||||
|
||||
/**
|
||||
* \file
|
||||
* certificate type for dnscrypt for use in other header files
|
||||
*/
|
||||
|
||||
#include <sodium.h>
|
||||
#define CERT_MAGIC_CERT "DNSC"
|
||||
#define CERT_MAJOR_VERSION 1
|
||||
#define CERT_MINOR_VERSION 0
|
||||
#define CERT_OLD_MAGIC_HEADER "7PYqwfzt"
|
||||
|
||||
#define CERT_FILE_EXPIRE_DAYS 365
|
||||
|
||||
struct SignedCert {
|
||||
uint8_t magic_cert[4];
|
||||
uint8_t version_major[2];
|
||||
uint8_t version_minor[2];
|
||||
|
||||
// Signed Content
|
||||
uint8_t server_publickey[crypto_box_PUBLICKEYBYTES];
|
||||
uint8_t magic_query[8];
|
||||
uint8_t serial[4];
|
||||
uint8_t ts_begin[4];
|
||||
uint8_t ts_end[4];
|
||||
uint8_t end[64];
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
531
dnscrypt/dnscrypt.c
Normal file
531
dnscrypt/dnscrypt.c
Normal file
|
|
@ -0,0 +1,531 @@
|
|||
|
||||
#include "config.h"
|
||||
#include <stdlib.h>
|
||||
#include <fcntl.h>
|
||||
#ifdef HAVE_TIME_H
|
||||
#include <time.h>
|
||||
#endif
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include "sldns/sbuffer.h"
|
||||
#include "util/config_file.h"
|
||||
#include "util/net_help.h"
|
||||
#include "util/netevent.h"
|
||||
#include "util/log.h"
|
||||
|
||||
#include "dnscrypt/cert.h"
|
||||
#include "dnscrypt/dnscrypt.h"
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
/**
|
||||
* \file
|
||||
* dnscrypt functions for encrypting DNS packets.
|
||||
*/
|
||||
|
||||
#define DNSCRYPT_QUERY_BOX_OFFSET \
|
||||
(DNSCRYPT_MAGIC_HEADER_LEN + crypto_box_PUBLICKEYBYTES + crypto_box_HALF_NONCEBYTES)
|
||||
|
||||
// 8 bytes: magic header (CERT_MAGIC_HEADER)
|
||||
// 12 bytes: the client's nonce
|
||||
// 12 bytes: server nonce extension
|
||||
// 16 bytes: Poly1305 MAC (crypto_box_ZEROBYTES - crypto_box_BOXZEROBYTES)
|
||||
|
||||
#define DNSCRYPT_REPLY_BOX_OFFSET \
|
||||
(DNSCRYPT_MAGIC_HEADER_LEN + crypto_box_HALF_NONCEBYTES + crypto_box_HALF_NONCEBYTES)
|
||||
|
||||
/**
|
||||
* Decrypt a query using the keypair that was found using dnsc_find_keypair.
|
||||
* The client nonce will be extracted from the encrypted query and stored in
|
||||
* client_nonce, a shared secret will be computed and stored in nmkey and the
|
||||
* buffer will be decrypted inplace.
|
||||
* \param[in] keypair the keypair that matches this encrypted query.
|
||||
* \param[in] client_nonce where the client nonce will be stored.
|
||||
* \param[in] nmkey where the shared secret key will be written.
|
||||
* \param[in] buffer the encrypted buffer.
|
||||
* \return 0 on success.
|
||||
*/
|
||||
static int
|
||||
dnscrypt_server_uncurve(const KeyPair *keypair,
|
||||
uint8_t client_nonce[crypto_box_HALF_NONCEBYTES],
|
||||
uint8_t nmkey[crypto_box_BEFORENMBYTES],
|
||||
struct sldns_buffer* buffer)
|
||||
{
|
||||
size_t len = sldns_buffer_limit(buffer);
|
||||
uint8_t *const buf = sldns_buffer_begin(buffer);
|
||||
uint8_t nonce[crypto_box_NONCEBYTES];
|
||||
struct dnscrypt_query_header *query_header;
|
||||
|
||||
if (len <= DNSCRYPT_QUERY_HEADER_SIZE) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
query_header = (struct dnscrypt_query_header *)buf;
|
||||
memcpy(nmkey, query_header->publickey, crypto_box_PUBLICKEYBYTES);
|
||||
if (crypto_box_beforenm(nmkey, nmkey, keypair->crypt_secretkey) != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
memcpy(nonce, query_header->nonce, crypto_box_HALF_NONCEBYTES);
|
||||
memset(nonce + crypto_box_HALF_NONCEBYTES, 0, crypto_box_HALF_NONCEBYTES);
|
||||
|
||||
sldns_buffer_set_at(buffer,
|
||||
DNSCRYPT_QUERY_BOX_OFFSET - crypto_box_BOXZEROBYTES,
|
||||
0, crypto_box_BOXZEROBYTES);
|
||||
|
||||
if (crypto_box_open_afternm
|
||||
(buf + DNSCRYPT_QUERY_BOX_OFFSET - crypto_box_BOXZEROBYTES,
|
||||
buf + DNSCRYPT_QUERY_BOX_OFFSET - crypto_box_BOXZEROBYTES,
|
||||
len - DNSCRYPT_QUERY_BOX_OFFSET + crypto_box_BOXZEROBYTES, nonce,
|
||||
nmkey) != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
while (*sldns_buffer_at(buffer, --len) == 0)
|
||||
;
|
||||
|
||||
if (*sldns_buffer_at(buffer, len) != 0x80) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
memcpy(client_nonce, nonce, crypto_box_HALF_NONCEBYTES);
|
||||
memmove(sldns_buffer_begin(buffer),
|
||||
sldns_buffer_at(buffer, DNSCRYPT_QUERY_HEADER_SIZE),
|
||||
len - DNSCRYPT_QUERY_HEADER_SIZE);
|
||||
|
||||
sldns_buffer_set_position(buffer, 0);
|
||||
sldns_buffer_set_limit(buffer, len - DNSCRYPT_QUERY_HEADER_SIZE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add random padding to a buffer, according to a client nonce.
|
||||
* The length has to depend on the query in order to avoid reply attacks.
|
||||
*
|
||||
* @param buf a buffer
|
||||
* @param len the initial size of the buffer
|
||||
* @param max_len the maximum size
|
||||
* @param nonce a nonce, made of the client nonce repeated twice
|
||||
* @param secretkey
|
||||
* @return the new size, after padding
|
||||
*/
|
||||
size_t
|
||||
dnscrypt_pad(uint8_t *buf, const size_t len, const size_t max_len,
|
||||
const uint8_t *nonce, const uint8_t *secretkey)
|
||||
{
|
||||
uint8_t *buf_padding_area = buf + len;
|
||||
size_t padded_len;
|
||||
uint32_t rnd;
|
||||
|
||||
// no padding
|
||||
if (max_len < len + DNSCRYPT_MIN_PAD_LEN)
|
||||
return len;
|
||||
|
||||
assert(nonce[crypto_box_HALF_NONCEBYTES] == nonce[0]);
|
||||
|
||||
crypto_stream((unsigned char *)&rnd, (unsigned long long)sizeof(rnd), nonce,
|
||||
secretkey);
|
||||
padded_len =
|
||||
len + DNSCRYPT_MIN_PAD_LEN + rnd % (max_len - len -
|
||||
DNSCRYPT_MIN_PAD_LEN + 1);
|
||||
padded_len += DNSCRYPT_BLOCK_SIZE - padded_len % DNSCRYPT_BLOCK_SIZE;
|
||||
if (padded_len > max_len)
|
||||
padded_len = max_len;
|
||||
|
||||
memset(buf_padding_area, 0, padded_len - len);
|
||||
*buf_padding_area = 0x80;
|
||||
|
||||
return padded_len;
|
||||
}
|
||||
|
||||
uint64_t
|
||||
dnscrypt_hrtime(void)
|
||||
{
|
||||
struct timeval tv;
|
||||
uint64_t ts = (uint64_t)0U;
|
||||
int ret;
|
||||
|
||||
ret = gettimeofday(&tv, NULL);
|
||||
if (ret == 0) {
|
||||
ts = (uint64_t)tv.tv_sec * 1000000U + (uint64_t)tv.tv_usec;
|
||||
} else {
|
||||
log_err("gettimeofday: %s", strerror(errno));
|
||||
}
|
||||
return ts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the server nonce part to once.
|
||||
* The nonce is made half of client nonce and the seconf half of the server
|
||||
* nonce, both of them of size crypto_box_HALF_NONCEBYTES.
|
||||
* \param[in] nonce: a uint8_t* of size crypto_box_NONCEBYTES
|
||||
*/
|
||||
static void
|
||||
add_server_nonce(uint8_t *nonce)
|
||||
{
|
||||
uint64_t ts;
|
||||
uint64_t tsn;
|
||||
uint32_t suffix;
|
||||
ts = dnscrypt_hrtime();
|
||||
// TODO? dnscrypt-wrapper does some logic with context->nonce_ts_last
|
||||
// unclear if we really need it, so skipping it for now.
|
||||
tsn = (ts << 10) | (randombytes_random() & 0x3ff);
|
||||
#if (BYTE_ORDER == LITTLE_ENDIAN)
|
||||
tsn =
|
||||
(((uint64_t)htonl((uint32_t)tsn)) << 32) | htonl((uint32_t)(tsn >> 32));
|
||||
#endif
|
||||
memcpy(nonce + crypto_box_HALF_NONCEBYTES, &tsn, 8);
|
||||
suffix = randombytes_random();
|
||||
memcpy(nonce + crypto_box_HALF_NONCEBYTES + 8, &suffix, 4);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encrypt a reply using the keypair that was used with the query.
|
||||
* The client nonce will be extracted from the encrypted query and stored in
|
||||
* The buffer will be encrypted inplace.
|
||||
* \param[in] keypair the keypair that matches this encrypted query.
|
||||
* \param[in] client_nonce client nonce used during the query
|
||||
* \param[in] nmkey shared secret key used during the query.
|
||||
* \param[in] buffer the buffer where to encrypt the reply.
|
||||
* \param[in] udp if whether or not it is a UDP query.
|
||||
* \param[in] max_udp_size configured max udp size.
|
||||
* \return 0 on success.
|
||||
*/
|
||||
static int
|
||||
dnscrypt_server_curve(const KeyPair *keypair,
|
||||
uint8_t client_nonce[crypto_box_HALF_NONCEBYTES],
|
||||
uint8_t nmkey[crypto_box_BEFORENMBYTES],
|
||||
struct sldns_buffer* buffer,
|
||||
uint8_t udp,
|
||||
size_t max_udp_size)
|
||||
{
|
||||
size_t dns_reply_len = sldns_buffer_limit(buffer);
|
||||
size_t max_len = dns_reply_len + DNSCRYPT_MAX_PADDING + DNSCRYPT_REPLY_HEADER_SIZE;
|
||||
size_t max_reply_size = max_udp_size - 20U - 8U;
|
||||
uint8_t nonce[crypto_box_NONCEBYTES];
|
||||
uint8_t *boxed;
|
||||
uint8_t *const buf = sldns_buffer_begin(buffer);
|
||||
size_t len = sldns_buffer_limit(buffer);
|
||||
|
||||
if(udp){
|
||||
if (max_len > max_reply_size)
|
||||
max_len = max_reply_size;
|
||||
}
|
||||
|
||||
|
||||
memcpy(nonce, client_nonce, crypto_box_HALF_NONCEBYTES);
|
||||
memcpy(nonce + crypto_box_HALF_NONCEBYTES, client_nonce,
|
||||
crypto_box_HALF_NONCEBYTES);
|
||||
|
||||
boxed = buf + DNSCRYPT_REPLY_BOX_OFFSET;
|
||||
memmove(boxed + crypto_box_MACBYTES, buf, len);
|
||||
len = dnscrypt_pad(boxed + crypto_box_MACBYTES, len,
|
||||
max_len - DNSCRYPT_REPLY_HEADER_SIZE, nonce,
|
||||
keypair->crypt_secretkey);
|
||||
sldns_buffer_set_at(buffer,
|
||||
DNSCRYPT_REPLY_BOX_OFFSET - crypto_box_BOXZEROBYTES,
|
||||
0, crypto_box_ZEROBYTES);
|
||||
|
||||
// add server nonce extension
|
||||
add_server_nonce(nonce);
|
||||
|
||||
if (crypto_box_afternm
|
||||
(boxed - crypto_box_BOXZEROBYTES, boxed - crypto_box_BOXZEROBYTES,
|
||||
len + crypto_box_ZEROBYTES, nonce, nmkey) != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
sldns_buffer_write_at(buffer, 0, DNSCRYPT_MAGIC_RESPONSE, DNSCRYPT_MAGIC_HEADER_LEN);
|
||||
sldns_buffer_write_at(buffer, DNSCRYPT_MAGIC_HEADER_LEN, nonce, crypto_box_NONCEBYTES);
|
||||
sldns_buffer_set_limit(buffer, len + DNSCRYPT_REPLY_HEADER_SIZE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the content of fname into buf.
|
||||
* \param[in] fname name of the file to read.
|
||||
* \param[in] buf the buffer in which to read the content of the file.
|
||||
* \param[in] count number of bytes to read.
|
||||
* \return 0 on success.
|
||||
*/
|
||||
static int
|
||||
dnsc_read_from_file(char *fname, char *buf, size_t count)
|
||||
{
|
||||
int fd;
|
||||
fd = open(fname, O_RDONLY);
|
||||
if (fd == -1) {
|
||||
return -1;
|
||||
}
|
||||
if (read(fd, buf, count) != (ssize_t)count) {
|
||||
close(fd);
|
||||
return -2;
|
||||
}
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse certificates files provided by the configuration and load them into
|
||||
* dnsc_env.
|
||||
* \param[in] env the dnsc_env structure to load the certs into.
|
||||
* \param[in] cfg the configuration.
|
||||
* \return the number of certificates loaded.
|
||||
*/
|
||||
static int
|
||||
dnsc_parse_certs(struct dnsc_env *env, struct config_file *cfg)
|
||||
{
|
||||
struct config_strlist *head;
|
||||
size_t signed_cert_id;
|
||||
|
||||
env->signed_certs_count = 0U;
|
||||
for (head = cfg->dnscrypt_provider_cert; head; head = head->next) {
|
||||
env->signed_certs_count++;
|
||||
}
|
||||
env->signed_certs = sodium_allocarray(env->signed_certs_count,
|
||||
sizeof *env->signed_certs);
|
||||
|
||||
signed_cert_id = 0U;
|
||||
for(head = cfg->dnscrypt_provider_cert; head; head = head->next, signed_cert_id++) {
|
||||
if(dnsc_read_from_file(
|
||||
head->str,
|
||||
(char *)(env->signed_certs + signed_cert_id),
|
||||
sizeof(struct SignedCert)) != 0) {
|
||||
fatal_exit("dnsc_parse_certs: failed to load %s: %s", head->str, strerror(errno));
|
||||
}
|
||||
verbose(VERB_OPS, "Loaded cert %s", head->str);
|
||||
}
|
||||
return signed_cert_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to convert a binary key into a printable fingerprint.
|
||||
* \param[in] fingerprint the buffer in which to write the printable key.
|
||||
* \param[in] key the key to convert.
|
||||
*/
|
||||
void
|
||||
dnsc_key_to_fingerprint(char fingerprint[80U], const uint8_t * const key)
|
||||
{
|
||||
const size_t fingerprint_size = 80U;
|
||||
size_t fingerprint_pos = (size_t) 0U;
|
||||
size_t key_pos = (size_t) 0U;
|
||||
|
||||
for (;;) {
|
||||
assert(fingerprint_size > fingerprint_pos);
|
||||
snprintf(&fingerprint[fingerprint_pos],
|
||||
fingerprint_size - fingerprint_pos, "%02X%02X",
|
||||
key[key_pos], key[key_pos + 1U]);
|
||||
key_pos += 2U;
|
||||
if (key_pos >= crypto_box_PUBLICKEYBYTES) {
|
||||
break;
|
||||
}
|
||||
fingerprint[fingerprint_pos + 4U] = ':';
|
||||
fingerprint_pos += 5U;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the keypair matching a DNSCrypt query.
|
||||
* \param[in] dnscenv The DNSCrypt enviroment, which contains the list of keys
|
||||
* supported by the server.
|
||||
* \param[in] buffer The encrypted DNS query.
|
||||
* \return a KeyPair * if we found a key pair matching the query, NULL otherwise.
|
||||
*/
|
||||
static const KeyPair *
|
||||
dnsc_find_keypair(struct dnsc_env* dnscenv, struct sldns_buffer* buffer)
|
||||
{
|
||||
const KeyPair *keypairs = dnscenv->keypairs;
|
||||
struct dnscrypt_query_header *dnscrypt_header;
|
||||
size_t i;
|
||||
|
||||
if (sldns_buffer_limit(buffer) < DNSCRYPT_QUERY_HEADER_SIZE) {
|
||||
return NULL;
|
||||
}
|
||||
dnscrypt_header = (struct dnscrypt_query_header *)sldns_buffer_begin(buffer);
|
||||
for (i = 0U; i < dnscenv->keypairs_count; i++) {
|
||||
if (memcmp(keypairs[i].crypt_publickey, dnscrypt_header->magic_query,
|
||||
DNSCRYPT_MAGIC_HEADER_LEN) == 0) {
|
||||
return &keypairs[i];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert local-zone and local-data into configuration.
|
||||
* In order to be able to serve certs over TXT, we can reuse the local-zone and
|
||||
* local-data config option. The zone and qname are infered from the
|
||||
* provider_name and the content of the TXT record from the certificate content.
|
||||
* returns the number of certtificate TXT record that were loaded.
|
||||
* < 0 in case of error.
|
||||
*/
|
||||
static int
|
||||
dnsc_load_local_data(struct dnsc_env* dnscenv, struct config_file *cfg)
|
||||
{
|
||||
size_t i, j;
|
||||
// Insert 'local-zone: "2.dnscrypt-cert.example.com" deny'
|
||||
if(!cfg_str2list_insert(&cfg->local_zones,
|
||||
strdup(dnscenv->provider_name),
|
||||
strdup("deny"))) {
|
||||
log_err("Could not load dnscrypt local-zone: %s deny",
|
||||
dnscenv->provider_name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Add local data entry of type:
|
||||
// 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 \"";
|
||||
struct SignedCert *cert = dnscenv->signed_certs + i;
|
||||
uint16_t 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);
|
||||
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);
|
||||
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);
|
||||
}
|
||||
}
|
||||
snprintf(rr + strlen(rr), rrlen - 1 - strlen(rr), "\"");
|
||||
cfg_strlist_insert(&cfg->local_data, strdup(rr));
|
||||
free(rr);
|
||||
}
|
||||
return dnscenv->signed_certs_count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the secret key files from `dnscrypt-secret-key` config and populates
|
||||
* a list of secret/public keys supported by dnscrypt listener.
|
||||
* \param[in] env The dnsc_env structure which will hold the keypairs.
|
||||
* \param[in] cfg The config with the secret key file paths.
|
||||
*/
|
||||
static int
|
||||
dnsc_parse_keys(struct dnsc_env *env, struct config_file *cfg)
|
||||
{
|
||||
struct config_strlist *head;
|
||||
size_t keypair_id;
|
||||
|
||||
env->keypairs_count = 0U;
|
||||
for (head = cfg->dnscrypt_secret_key; head; head = head->next) {
|
||||
env->keypairs_count++;
|
||||
}
|
||||
env->keypairs = sodium_allocarray(env->keypairs_count,
|
||||
sizeof *env->keypairs);
|
||||
|
||||
keypair_id = 0U;
|
||||
for(head = cfg->dnscrypt_secret_key; head; head = head->next, keypair_id++) {
|
||||
char fingerprint[80];
|
||||
if(dnsc_read_from_file(
|
||||
head->str,
|
||||
(char *)(env->keypairs[keypair_id].crypt_secretkey),
|
||||
crypto_box_SECRETKEYBYTES) != 0) {
|
||||
fatal_exit("dnsc_parse_keys: failed to load %s: %s", head->str, strerror(errno));
|
||||
}
|
||||
verbose(VERB_OPS, "Loaded key %s", head->str);
|
||||
if (crypto_scalarmult_base(env->keypairs[keypair_id].crypt_publickey,
|
||||
env->keypairs[keypair_id].crypt_secretkey) != 0) {
|
||||
fatal_exit("dnsc_parse_keys: could not generate public key from %s", head->str);
|
||||
}
|
||||
dnsc_key_to_fingerprint(fingerprint, env->keypairs[keypair_id].crypt_publickey);
|
||||
verbose(VERB_OPS, "Crypt public key fingerprint for %s: %s", head->str, fingerprint);
|
||||
}
|
||||
return keypair_id;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* #########################################################
|
||||
* ############# Publicly accessible functions #############
|
||||
* #########################################################
|
||||
*/
|
||||
|
||||
int
|
||||
dnsc_handle_curved_request(struct dnsc_env* dnscenv,
|
||||
struct comm_reply* repinfo)
|
||||
{
|
||||
struct comm_point* c = repinfo->c;
|
||||
|
||||
repinfo->is_dnscrypted = 0;
|
||||
if( !c->dnscrypt ) {
|
||||
return 1;
|
||||
}
|
||||
// Attempt to decrypt the query. If it is not crypted, we may still need
|
||||
// to serve the certificate.
|
||||
verbose(VERB_ALGO, "handle request called on DNSCrypt socket");
|
||||
if ((repinfo->keypair = dnsc_find_keypair(dnscenv, c->buffer)) != NULL) {
|
||||
if(dnscrypt_server_uncurve(repinfo->keypair,
|
||||
repinfo->client_nonce,
|
||||
repinfo->nmkey,
|
||||
c->buffer) != 0){
|
||||
verbose(VERB_ALGO, "dnscrypt: Failed to uncurve");
|
||||
comm_point_drop_reply(repinfo);
|
||||
return 0;
|
||||
}
|
||||
repinfo->is_dnscrypted = 1;
|
||||
sldns_buffer_rewind(c->buffer);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
dnsc_handle_uncurved_request(struct comm_reply *repinfo)
|
||||
{
|
||||
if(!repinfo->c->dnscrypt) {
|
||||
return 1;
|
||||
}
|
||||
sldns_buffer_copy(repinfo->c->dnscrypt_buffer, repinfo->c->buffer);
|
||||
if(!repinfo->is_dnscrypted) {
|
||||
return 1;
|
||||
}
|
||||
if(dnscrypt_server_curve(repinfo->keypair,
|
||||
repinfo->client_nonce,
|
||||
repinfo->nmkey,
|
||||
repinfo->c->dnscrypt_buffer,
|
||||
repinfo->c->type == comm_udp,
|
||||
repinfo->max_udp_size) != 0){
|
||||
verbose(VERB_ALGO, "dnscrypt: Failed to curve cached missed answer");
|
||||
comm_point_drop_reply(repinfo);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
struct dnsc_env *
|
||||
dnsc_create(void)
|
||||
{
|
||||
struct dnsc_env *env;
|
||||
if (sodium_init() == -1) {
|
||||
fatal_exit("dnsc_create: could not initialize libsodium.");
|
||||
}
|
||||
env = (struct dnsc_env *) calloc(1, sizeof(struct dnsc_env));
|
||||
return env;
|
||||
}
|
||||
|
||||
int
|
||||
dnsc_apply_cfg(struct dnsc_env *env, struct config_file *cfg)
|
||||
{
|
||||
if(dnsc_parse_certs(env, cfg) <= 0) {
|
||||
fatal_exit("dnsc_apply_cfg: no cert file loaded");
|
||||
}
|
||||
if(dnsc_parse_keys(env, cfg) <= 0) {
|
||||
fatal_exit("dnsc_apply_cfg: no key file loaded");
|
||||
}
|
||||
randombytes_buf(env->hash_key, sizeof env->hash_key);
|
||||
env->provider_name = cfg->dnscrypt_provider;
|
||||
|
||||
if(dnsc_load_local_data(env, cfg) <= 0) {
|
||||
fatal_exit("dnsc_apply_cfg: could not load local data");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
102
dnscrypt/dnscrypt.h
Normal file
102
dnscrypt/dnscrypt.h
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
#ifndef UNBOUND_DNSCRYPT_H
|
||||
#define UNBOUND_DNSCRYPT_H
|
||||
|
||||
/**
|
||||
* \file
|
||||
* dnscrypt functions for encrypting DNS packets.
|
||||
*/
|
||||
|
||||
#include "dnscrypt/dnscrypt_config.h"
|
||||
#ifdef USE_DNSCRYPT
|
||||
|
||||
#define DNSCRYPT_MAGIC_HEADER_LEN 8U
|
||||
#define DNSCRYPT_MAGIC_RESPONSE "r6fnvWj8"
|
||||
|
||||
#ifndef DNSCRYPT_MAX_PADDING
|
||||
# define DNSCRYPT_MAX_PADDING 256U
|
||||
#endif
|
||||
#ifndef DNSCRYPT_BLOCK_SIZE
|
||||
# define DNSCRYPT_BLOCK_SIZE 64U
|
||||
#endif
|
||||
#ifndef DNSCRYPT_MIN_PAD_LEN
|
||||
# define DNSCRYPT_MIN_PAD_LEN 8U
|
||||
#endif
|
||||
|
||||
#define crypto_box_HALF_NONCEBYTES (crypto_box_NONCEBYTES / 2U)
|
||||
|
||||
#include "config.h"
|
||||
#include "dnscrypt/cert.h"
|
||||
|
||||
#define DNSCRYPT_QUERY_HEADER_SIZE \
|
||||
(DNSCRYPT_MAGIC_HEADER_LEN + crypto_box_PUBLICKEYBYTES + crypto_box_HALF_NONCEBYTES + crypto_box_MACBYTES)
|
||||
#define DNSCRYPT_RESPONSE_HEADER_SIZE \
|
||||
(DNSCRYPT_MAGIC_HEADER_LEN + crypto_box_NONCEBYTES + crypto_box_MACBYTES)
|
||||
|
||||
#define DNSCRYPT_REPLY_HEADER_SIZE \
|
||||
(DNSCRYPT_MAGIC_HEADER_LEN + crypto_box_HALF_NONCEBYTES * 2 + crypto_box_MACBYTES)
|
||||
|
||||
struct sldns_buffer;
|
||||
struct config_file;
|
||||
struct comm_reply;
|
||||
|
||||
typedef struct KeyPair_ {
|
||||
uint8_t crypt_publickey[crypto_box_PUBLICKEYBYTES];
|
||||
uint8_t crypt_secretkey[crypto_box_SECRETKEYBYTES];
|
||||
} KeyPair;
|
||||
|
||||
struct dnsc_env {
|
||||
struct SignedCert *signed_certs;
|
||||
size_t signed_certs_count;
|
||||
uint8_t provider_publickey[crypto_sign_ed25519_PUBLICKEYBYTES];
|
||||
uint8_t provider_secretkey[crypto_sign_ed25519_SECRETKEYBYTES];
|
||||
KeyPair *keypairs;
|
||||
size_t keypairs_count;
|
||||
uint64_t nonce_ts_last;
|
||||
unsigned char hash_key[crypto_shorthash_KEYBYTES];
|
||||
char * provider_name;
|
||||
};
|
||||
|
||||
struct dnscrypt_query_header {
|
||||
uint8_t magic_query[DNSCRYPT_MAGIC_HEADER_LEN];
|
||||
uint8_t publickey[crypto_box_PUBLICKEYBYTES];
|
||||
uint8_t nonce[crypto_box_HALF_NONCEBYTES];
|
||||
uint8_t mac[crypto_box_MACBYTES];
|
||||
};
|
||||
|
||||
/**
|
||||
* Initialize DNSCrypt enviroment.
|
||||
* Initialize sodium library and allocate the dnsc_env structure.
|
||||
* \return an uninitialized struct dnsc_env.
|
||||
*/
|
||||
struct dnsc_env * dnsc_create(void);
|
||||
|
||||
/**
|
||||
* Apply configuration.
|
||||
* Read certificates and secret keys from configuration. Initialize hashkey and
|
||||
* provider name as well as loading cert TXT records.
|
||||
* In case of issue applying configuration, this function fatals.
|
||||
* \param[in] env the struct dnsc_env to populate.
|
||||
* \param[in] cfg the config_file struct with dnscrypt options.
|
||||
* \return 0 on success.
|
||||
*/
|
||||
int dnsc_apply_cfg(struct dnsc_env *env, struct config_file *cfg);
|
||||
|
||||
/**
|
||||
* handle a crypted dnscrypt request.
|
||||
* Determine wether or not a query is coming over the dnscrypt listener and
|
||||
* attempt to uncurve it or detect if it is a certificate query.
|
||||
* return 0 in case of failure.
|
||||
*/
|
||||
int dnsc_handle_curved_request(struct dnsc_env* dnscenv,
|
||||
struct comm_reply* repinfo);
|
||||
/**
|
||||
* handle an unencrypted dnscrypt request.
|
||||
* Determine wether or not a query is going over the dnscrypt channel and
|
||||
* attempt to curve it unless it was not crypted like when it is a
|
||||
* certificate query.
|
||||
* \return 0 in case of failure.
|
||||
*/
|
||||
|
||||
int dnsc_handle_uncurved_request(struct comm_reply *repinfo);
|
||||
#endif /* USE_DNSCRYPT */
|
||||
#endif
|
||||
25
dnscrypt/dnscrypt.m4
Normal file
25
dnscrypt/dnscrypt.m4
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
# dnscrypt.m4
|
||||
|
||||
# dnsc_DNSCRYPT([action-if-true], [action-if-false])
|
||||
# --------------------------------------------------------------------------
|
||||
# Check for required dnscrypt libraries and add dnscrypt configure args.
|
||||
AC_DEFUN([dnsc_DNSCRYPT],
|
||||
[
|
||||
AC_ARG_ENABLE([dnscrypt],
|
||||
AS_HELP_STRING([--enable-dnscrypt],
|
||||
[Enable dnscrypt support (requires libsodium)]),
|
||||
[opt_dnscrypt=$enableval], [opt_dnscrypt=no])
|
||||
|
||||
if test "x$opt_dnscrypt" != "xno"; then
|
||||
AC_ARG_WITH([libsodium], AC_HELP_STRING([--with-libsodium=path],
|
||||
[Path where libsodium is installed, for dnscrypt]), [
|
||||
CFLAGS="$CFLAGS -I$withval/include"
|
||||
LDFLAGS="$LDFLAGS -L$withval/lib"
|
||||
])
|
||||
AC_SEARCH_LIBS([sodium_init], [sodium], [],
|
||||
AC_MSG_ERROR([The sodium library was not found. Please install sodium!]))
|
||||
$1
|
||||
else
|
||||
$2
|
||||
fi
|
||||
])
|
||||
17
dnscrypt/dnscrypt_config.h.in
Normal file
17
dnscrypt/dnscrypt_config.h.in
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
#ifndef UNBOUND_DNSCRYPT_CONFIG_H
|
||||
#define UNBOUND_DNSCRYPT_CONFIG_H
|
||||
|
||||
/*
|
||||
* Process this file (dnscrypt_config.h.in) with AC_CONFIG_FILES to generate
|
||||
* dnscrypt_config.h.
|
||||
*
|
||||
* This file exists so that USE_DNSCRYPT can be used without including config.h.
|
||||
*/
|
||||
|
||||
#if @ENABLE_DNSCRYPT@ /* ENABLE_DNSCRYPT */
|
||||
# ifndef USE_DNSCRYPT
|
||||
# define USE_DNSCRYPT 1
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#endif /* UNBOUND_DNSCRYPT_CONFIG_H */
|
||||
Binary file not shown.
184
doc/Changelog
184
doc/Changelog
|
|
@ -1,5 +1,187 @@
|
|||
13 April 2017: Wouter
|
||||
- Fix #1250: inconsistent indentation in services/listen_dnsport.c.
|
||||
- tag for 1.6.2rc1
|
||||
|
||||
12 April 2017: Wouter
|
||||
- subnet mem value is available in shm, also when not enabled,
|
||||
to make the struct easier to memmap by other applications,
|
||||
independent of the configuration of unbound.
|
||||
|
||||
12 April 2017: Ralph
|
||||
- Fix #1247: unbound does not shorten source prefix length when
|
||||
forwarding ECS.
|
||||
- Properly check for allocation failure in local_data_find_tag_datas.
|
||||
- Fix #1249: unbound doesn't return FORMERR to bogus ECS.
|
||||
- Set SHM ECS memory usage to 0 when module not loaded.
|
||||
|
||||
11 April 2017: Ralph
|
||||
- Display ECS module memory usage.
|
||||
|
||||
10 April 2017: Wouter
|
||||
- harden-algo-downgrade: no also makes unbound more lenient about
|
||||
digest algorithms in DS records.
|
||||
|
||||
10 April 2017: Ralph
|
||||
- Remove ECS option after REFUSED answer.
|
||||
- Fix small memory leak in edns_opt_copy_alloc.
|
||||
- Respip dereference after NULL check.
|
||||
- Zero initialize addrtree allocation.
|
||||
- Use correct identifier for SHM destroy.
|
||||
|
||||
7 April 2017: George
|
||||
- Fix pythonmod for cb changes.
|
||||
- Some whitespace fixup.
|
||||
|
||||
7 April 2017: Ralph
|
||||
- Unlock view in respip unit test
|
||||
|
||||
6 April 2017: Ralph
|
||||
- Generalise inplace callback (de)registration
|
||||
- (de)register inplace callbacks for module id
|
||||
- No unbound-control set_option for ECS options
|
||||
- Deprecated client-subnet-opcode config option
|
||||
- Introduced client-subnet-always-forward config option
|
||||
- Changed max-client-subnet-ipv6 default to 56 (as in RFC)
|
||||
- Removed extern ECS config options
|
||||
- module_restart_next now calls clear on all following modules
|
||||
- Also create ECS module qstate on module_event_pass event
|
||||
- remove malloc from inplace_cb_register
|
||||
|
||||
6 April 2017: Wouter
|
||||
- Small fixup for documentation.
|
||||
- iana portlist update
|
||||
- Fix respip for braces when locks arent used.
|
||||
- Fix pythonmod for cb changes.
|
||||
|
||||
4 April 2017: Wouter
|
||||
- Fix #1244: document that use of chroot requires trust anchor file to
|
||||
be under chroot.
|
||||
- iana portlist update
|
||||
|
||||
3 April 2017: Ralph
|
||||
- Do not add current time twice to TTL before ECS cache store.
|
||||
- Do not touch rrset cache after ECS cache message generation.
|
||||
- Use LDNS_EDNS_CLIENT_SUBNET as default ECS opcode.
|
||||
|
||||
3 April 2017: Wouter
|
||||
- Fix #1217: Add metrics to unbound-control interface showing
|
||||
crypted, cert request, plaintext and malformed queries (from
|
||||
Manu Bretelle).
|
||||
- iana portlist update
|
||||
|
||||
27 March 2017: Wouter
|
||||
- Remove (now unused) event2 include from dnscrypt code.
|
||||
|
||||
24 March 2017: George
|
||||
- Fix to prevent non-referal query from being cached as referal when the
|
||||
no_cache_store flag was set.
|
||||
|
||||
23 March 2017: Wouter
|
||||
- Fix #1239: configure fails to find python distutils if python
|
||||
prints warning.
|
||||
|
||||
22 March 2017: Wouter
|
||||
- Fix #1238: segmentation fault when adding through the remote
|
||||
interface a per-view local zone to a view with no previous
|
||||
(configured) local zones.
|
||||
- Fix #1229: Systemd service sandboxing, options in wrong sections.
|
||||
|
||||
21 March 2017: Ralph
|
||||
- Merge EDNS Client subnet implementation from feature branch into main
|
||||
branch, using new EDNS processing framework.
|
||||
|
||||
21 March 2017: Wouter
|
||||
- Fix doxygen for dnscrypt files.
|
||||
|
||||
20 March 2017: Wouter
|
||||
- #1217. DNSCrypt support, with --enable-dnscrypt, libsodium and then
|
||||
enabled in the config file from Manu Bretelle.
|
||||
- make depend, autoconf, remove warnings about statement before var.
|
||||
- lru_demote and lruhash_insert_or_retrieve functions for getdns.
|
||||
- fixup for lruhash (whitespace and header file comment).
|
||||
- dnscrypt tests.
|
||||
|
||||
17 March 2017: Wouter
|
||||
- Patch for view functionality for local-data-ptr from Björn Ketelaars.
|
||||
- Fix #1237 - Wrong resolving in chain, for norec queries that get
|
||||
SERVFAIL returned.
|
||||
|
||||
16 March 2017: Wouter
|
||||
- Fix that SHM is not inited if not enabled.
|
||||
- Add trustanchor.unbound CH TXT that gets a response with a number
|
||||
of TXT RRs with a string like "example.com. 2345 1234" with
|
||||
the trust anchors and their keytags.
|
||||
- Fix that looped DNAMEs do not cause unbound to spend effort.
|
||||
- trustanchor tags are sorted. reusable routine to fetch taglist.
|
||||
|
||||
13 March 2017: Wouter
|
||||
- testbound understands Deckard MATCH rcode question answer commands.
|
||||
- Fix #1235: Fix too long DNAME expansion produces SERVFAIL instead
|
||||
of YXDOMAIN + query loop, reported by Petr Spacek.
|
||||
|
||||
10 March 2017: Wouter
|
||||
- Fix #1234: shortening DNAME loop produces duplicate DNAME records
|
||||
in ANSWER section.
|
||||
|
||||
9 March 2017: Wouter
|
||||
- --disable-sha1 disables SHA1 support in RRSIG, so from DNSKEY and
|
||||
DS records. NSEC3 is not disabled.
|
||||
- fake-sha1 test option; print warning if used. To make unit tests.
|
||||
- unbound-control list local zone and data commands listed in the
|
||||
help output.
|
||||
|
||||
8 March 2017: Wouter
|
||||
- make depend for build dependencies.
|
||||
- swig version 2.0.1 required.
|
||||
- fix enum conversion warnings
|
||||
|
||||
7 March 2017: Wouter
|
||||
- Fix #1230: swig version 2.0.0 is required for pythonmod, with
|
||||
1.3.40 it crashes when running repeatly unbound-control reload.
|
||||
- Response actions based on IP address from Jinmei Tatuya (Infoblox).
|
||||
|
||||
6 March 2017: Wouter
|
||||
- Fix #1229: Systemd service sandboxing in contrib/unbound.service.
|
||||
- iana portlist update
|
||||
|
||||
28 February 2017: Ralph
|
||||
- Fix testpkts.c, check if DO bit is set, not only if there is an OPT
|
||||
record.
|
||||
|
||||
28 February 2017: Wouter
|
||||
- For #1227: if we have sha256, set the cipher list to have no
|
||||
known vulns.
|
||||
|
||||
27 February 2017: Wouter
|
||||
- Fix #1227: Fix that Unbound control allows weak ciphersuits.
|
||||
- Fix #1226: provide official 32bit binary for windows.
|
||||
|
||||
24 February 2017: Wouter
|
||||
- include sys/time.h for new shm code on NetBSD.
|
||||
|
||||
23 February 2017: Wouter
|
||||
- Fix doc/CNAME-basedRedirectionDesignNotes.pdf zone static to
|
||||
redirect.
|
||||
- Patch from Luiz Fernando Softov for Stats Shared Memory.
|
||||
- unbound-control stats_shm command prints stats using shared memory,
|
||||
which uses less cpu.
|
||||
- make depend, autoconf, doxygen and lint fixed up.
|
||||
|
||||
22 February 2017: Wouter
|
||||
- Fix #1224: Fix that defaults should not fall back to "Program Files
|
||||
(x86) if Unbound is 64bit by default on windows.
|
||||
|
||||
21 February 2017: Wouter
|
||||
- iana portlist update
|
||||
|
||||
16 February 2017: Wouter
|
||||
- sldns updated for vfixed and buffer resize indication from getdns.
|
||||
|
||||
15 February 2017: Wouter
|
||||
- sldns has ED25519 and ED448 algorithm number and name for display.
|
||||
|
||||
14 February 2017: Wouter
|
||||
- tag 1.6.1rc3.
|
||||
- tag 1.6.1rc3. -- which became 1.6.1 on 21feb, trunk has 1.6.2
|
||||
|
||||
13 February 2017: Wouter
|
||||
- Fix autoconf of systemd check for lack of pkg-config.
|
||||
|
|
|
|||
BIN
doc/IP-BasedActions.pdf
Normal file
BIN
doc/IP-BasedActions.pdf
Normal file
Binary file not shown.
|
|
@ -1,4 +1,4 @@
|
|||
README for Unbound 1.6.1
|
||||
README for Unbound 1.6.2
|
||||
Copyright 2007 NLnet Labs
|
||||
http://unbound.net
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#
|
||||
# Example configuration file.
|
||||
#
|
||||
# See unbound.conf(5) man page, version 1.6.1.
|
||||
# See unbound.conf(5) man page, version 1.6.2.
|
||||
#
|
||||
# this is a comment.
|
||||
|
||||
|
|
@ -19,6 +19,14 @@ server:
|
|||
# Set to "" or 0 to disable. Default is disabled.
|
||||
# statistics-interval: 0
|
||||
|
||||
# enable shm for stats, default no. if you enable also enable
|
||||
# statistics-interval, every time it also writes stats to the
|
||||
# shared memory segment keyed with shm-key.
|
||||
# shm-enable: no
|
||||
|
||||
# shm for stats uses this key, and key+1 for the shared mem segment.
|
||||
# shm-key: 11777
|
||||
|
||||
# enable cumulative statistics, without clearing them after printing.
|
||||
# statistics-cumulative: no
|
||||
|
||||
|
|
@ -308,6 +316,9 @@ server:
|
|||
|
||||
# enable to not answer version.server and version.bind queries.
|
||||
# hide-version: no
|
||||
|
||||
# enable to not answer trustanchor.unbound queries.
|
||||
# hide-trustanchor: no
|
||||
|
||||
# the identity to report. Leave "" or default to return hostname.
|
||||
# identity: ""
|
||||
|
|
@ -771,7 +782,28 @@ remote-control:
|
|||
# name: "viewname"
|
||||
# local-zone: "example.com" redirect
|
||||
# local-data: "example.com A 192.0.2.3"
|
||||
# local-data-ptr: "192.0.2.3 www.example.com"
|
||||
# view-first: no
|
||||
# view:
|
||||
# name: "anotherview"
|
||||
# local-zone: "example.com" refuse
|
||||
|
||||
# DNSCrypt
|
||||
# Caveats:
|
||||
# 1. the keys/certs cannot be produced by unbound. You can use dnscrypt-wrapper
|
||||
# for this: https://github.com/cofyc/dnscrypt-wrapper/blob/master/README.md#usage
|
||||
# 2. dnscrypt channel attaches to an interface. you MUST set interfaces to
|
||||
# listen on `dnscrypt-port` with the follo0wing snippet:
|
||||
# server:
|
||||
# interface: 0.0.0.0@443
|
||||
# interface: ::0@443
|
||||
#
|
||||
# Finally, `dnscrypt` config has its own section.
|
||||
# dnscrypt:
|
||||
# dnscrypt-enable: yes
|
||||
# dnscrypt-port: 443
|
||||
# dnscrypt-provider: 2.dnscrypt-cert.example.com.
|
||||
# dnscrypt-secret-key: /path/unbound-conf/keys1/1.key
|
||||
# dnscrypt-secret-key: /path/unbound-conf/keys2/1.key
|
||||
# dnscrypt-provider-cert: /path/unbound-conf/keys1/1.cert
|
||||
# dnscrypt-provider-cert: /path/unbound-conf/keys2/1.cert
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
.TH "libunbound" "3" "Feb 21, 2017" "NLnet Labs" "unbound 1.6.1"
|
||||
.TH "libunbound" "3" "Apr 24, 2017" "NLnet Labs" "unbound 1.6.2"
|
||||
.\"
|
||||
.\" 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.1 functions.
|
||||
\- Unbound DNS validating resolver 1.6.2 functions.
|
||||
.SH "SYNOPSIS"
|
||||
.B #include <unbound.h>
|
||||
.LP
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
.TH "unbound-anchor" "8" "Feb 21, 2017" "NLnet Labs" "unbound 1.6.1"
|
||||
.TH "unbound-anchor" "8" "Apr 24, 2017" "NLnet Labs" "unbound 1.6.2"
|
||||
.\"
|
||||
.\" unbound-anchor.8 -- unbound anchor maintenance utility manual
|
||||
.\"
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
.TH "unbound-checkconf" "8" "Feb 21, 2017" "NLnet Labs" "unbound 1.6.1"
|
||||
.TH "unbound-checkconf" "8" "Apr 24, 2017" "NLnet Labs" "unbound 1.6.2"
|
||||
.\"
|
||||
.\" unbound-checkconf.8 -- unbound configuration checker manual
|
||||
.\"
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
.TH "unbound-control" "8" "Feb 21, 2017" "NLnet Labs" "unbound 1.6.1"
|
||||
.TH "unbound-control" "8" "Apr 24, 2017" "NLnet Labs" "unbound 1.6.2"
|
||||
.\"
|
||||
.\" unbound-control.8 -- unbound remote control manual
|
||||
.\"
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
.TH "unbound\-host" "1" "Feb 21, 2017" "NLnet Labs" "unbound 1.6.1"
|
||||
.TH "unbound\-host" "1" "Apr 24, 2017" "NLnet Labs" "unbound 1.6.2"
|
||||
.\"
|
||||
.\" unbound-host.1 -- unbound DNS lookup utility
|
||||
.\"
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
.TH "unbound" "8" "Feb 21, 2017" "NLnet Labs" "unbound 1.6.1"
|
||||
.TH "unbound" "8" "Apr 24, 2017" "NLnet Labs" "unbound 1.6.2"
|
||||
.\"
|
||||
.\" unbound.8 -- unbound manual
|
||||
.\"
|
||||
|
|
@ -9,7 +9,7 @@
|
|||
.\"
|
||||
.SH "NAME"
|
||||
.B unbound
|
||||
\- Unbound DNS validating resolver 1.6.1.
|
||||
\- Unbound DNS validating resolver 1.6.2.
|
||||
.SH "SYNOPSIS"
|
||||
.B unbound
|
||||
.RB [ \-h ]
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
.TH "unbound.conf" "5" "Feb 21, 2017" "NLnet Labs" "unbound 1.6.1"
|
||||
.TH "unbound.conf" "5" "Apr 24, 2017" "NLnet Labs" "unbound 1.6.2"
|
||||
.\"
|
||||
.\" unbound.conf.5 -- unbound.conf manual
|
||||
.\"
|
||||
|
|
@ -596,6 +596,9 @@ If enabled version.server and version.bind queries are refused.
|
|||
Set the version to report. If set to "", the default, then the package
|
||||
version is returned.
|
||||
.TP
|
||||
.B hide\-trustanchor: \fI<yes or no>
|
||||
If enabled trustanchor.unbound queries are refused.
|
||||
.TP
|
||||
.B target\-fetch\-policy: \fI<"list of numbers">
|
||||
Set the target fetch policy used by unbound to determine if it should fetch
|
||||
nameserver target addresses opportunistically. The policy is described per
|
||||
|
|
@ -782,7 +785,8 @@ frequently. The initial file can be one with contents as described in
|
|||
\fBtrust\-anchor\-file\fR. The file is written to when the anchor is updated,
|
||||
so the unbound user must have write permission. Write permission to the file,
|
||||
but also to the directory it is in (to create a temporary file, which is
|
||||
necessary to deal with filesystem full events).
|
||||
necessary to deal with filesystem full events), it must also be inside the
|
||||
chroot (if that is used).
|
||||
.TP
|
||||
.B trust\-anchor: \fI<"Resource Record">
|
||||
A DS or DNSKEY RR for a key to use for validation. Multiple entries can be
|
||||
|
|
@ -1403,6 +1407,10 @@ global local\-zone elements.
|
|||
View specific local\-data elements. Has the same behaviour as the global
|
||||
local\-data elements.
|
||||
.TP
|
||||
.B local\-data\-ptr: \fI"IPaddr name"
|
||||
View specific local\-data\-ptr elements. Has the same behaviour as the global
|
||||
local\-data\-ptr elements.
|
||||
.TP
|
||||
.B view\-first: \fI<yes or no>
|
||||
If enabled, it attempts to use the global local\-zone and local\-data if there
|
||||
is no match in the view specific options.
|
||||
|
|
@ -1438,6 +1446,79 @@ It must be /96 or shorter. The default prefix is 64:ff9b::/96.
|
|||
.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.
|
||||
.SS "DNSCrypt Options"
|
||||
.LP
|
||||
The
|
||||
.B dnscrypt:
|
||||
clause give the settings of the dnscrypt channel. While those options are
|
||||
available, they are only meaningful if unbound was compiled with
|
||||
\fB\-\-enable\-dnscrypt\fR.
|
||||
Currently certificate and secret/public keys cannot be generated by unbound.
|
||||
You can use dnscrypt-wrapper to generate those: https://github.com/cofyc/dnscrypt-wrapper/blob/master/README.md#usage
|
||||
.TP
|
||||
.B dnscrypt\-enable: \fI<yes or no>\fR
|
||||
Whether or not the \fBdnscrypt\fR config should be enabled. You may define
|
||||
configuration but not activate it.
|
||||
The default is no.
|
||||
.TP
|
||||
.B dnscrypt\-port: \fI<port number>
|
||||
On which port should \fBdnscrypt\fR should be activated. Note that you should
|
||||
have a matching \fBinterface\fR option defined in the \fBserver\fR section for
|
||||
this port.
|
||||
.TP
|
||||
.B dnscrypt\-provider: \fI<provider name>\fR
|
||||
The provider name to use to distribute certificates. This is of the form:
|
||||
\fB2.dnscrypt-cert.example.com.\fR. The name \fIMUST\fR end with a dot.
|
||||
.TP
|
||||
.B dnscrypt\-secret\-key: \fI<path to secret key file>\fR
|
||||
Path to the time limited secret key file. This option may be specified multiple
|
||||
times.
|
||||
.TP
|
||||
.B dnscrypt\-provider\-cert: \fI<path to cert file>\fR
|
||||
Path to the certificate related to the \fBdnscrypt\-secret\-key\fRs. This option
|
||||
may be specified multiple times.
|
||||
.SS "EDNS Client Subnet Module Options"
|
||||
.LP
|
||||
The ECS module must be configured in the \fBmodule\-config:\fR "subnetcache
|
||||
validator iterator" directive and be compiled into the daemon to be
|
||||
enabled. These settings go in the \fBserver:\fR section.
|
||||
.LP
|
||||
If the destination address is whitelisted with Unbound will add the EDNS0 option
|
||||
to the query containing the relevant part of the client's address. When an
|
||||
answer contains the ECS option the response and the option are placed in a
|
||||
specialized cache. If the authority indicated no support, the response is stored
|
||||
in the regular cache.
|
||||
.LP
|
||||
Additionally, when a client includes the option in its queries, Unbound will
|
||||
forward the option to the authority regardless of the authorities presence in
|
||||
the whitelist. In this case the lookup in the regular cache is skipped.
|
||||
.LP
|
||||
The maximum size of the ECS cache is controlled by 'msg-cache-size' in the
|
||||
configuration file. On top of that, for each query only 100 different subnets
|
||||
are allowed to be stored for each address family. Exceeding that number, older
|
||||
entries will be purged from cache.
|
||||
.TP
|
||||
.B send\-client\-subnet: \fI<IP address>\fR
|
||||
Send client source address to this authority. Append /num to indicate a
|
||||
classless delegation netblock, for example like 10.2.3.4/24 or 2001::11/64. Can
|
||||
be given multiple times. Authorities not listed will not receive edns-subnet
|
||||
information.
|
||||
.TP
|
||||
.B client\-subnet\-always\-forward: \fI<yes or no>\fR
|
||||
Specify whether the ECS whitelist check (configured using
|
||||
\fBsend\-client\-subnet\fR) is applied for all queries, even if the triggering
|
||||
query contains an ECS record, or only for queries for which the ECS record is
|
||||
generated using the querier address (and therefore did not contain ECS data in
|
||||
the client query). If enabled, the whitelist check is skipped when the client
|
||||
query contains an ECS record. Default is no.
|
||||
.TP
|
||||
.B max\-client\-subnet\-ipv6: \fI<number>\fR
|
||||
Specifies the maximum prefix length of the client source address we are willing
|
||||
to expose to third parties for IPv6. Defaults to 56.
|
||||
.TP
|
||||
.B max\-client\-subnet\-ipv4: \fI<number>\fR
|
||||
Specifies the maximum prefix length of the client source address we are willing
|
||||
to expose to third parties for IPv4. Defaults to 24.
|
||||
.SH "MEMORY CONTROL EXAMPLE"
|
||||
In the example config settings below memory usage is reduced. Some service
|
||||
levels are lower, notable very large data and a high TCP load are no longer
|
||||
|
|
|
|||
531
edns-subnet/addrtree.c
Normal file
531
edns-subnet/addrtree.c
Normal file
|
|
@ -0,0 +1,531 @@
|
|||
/*
|
||||
* edns-subnet/addrtree.c -- radix tree for edns subnet cache.
|
||||
*
|
||||
* Copyright (c) 2013, NLnet Labs. All rights reserved.
|
||||
*
|
||||
* This software is open source.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* Neither the name of the NLNET LABS nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
/** \file
|
||||
* addrtree -- radix tree for edns subnet cache.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "util/log.h"
|
||||
#include "util/data/msgreply.h"
|
||||
#include "util/module.h"
|
||||
#include "addrtree.h"
|
||||
|
||||
/**
|
||||
* Create a new edge
|
||||
* @param node: Child node this edge will connect to.
|
||||
* @param addr: full key to this edge.
|
||||
* @param addrlen: length of relevant part of key for this node
|
||||
* @param parent_node: Parent node for node
|
||||
* @param parent_index: Index of child node at parent node
|
||||
* @return new addredge or NULL on failure
|
||||
*/
|
||||
static struct addredge *
|
||||
edge_create(struct addrnode *node, const addrkey_t *addr,
|
||||
addrlen_t addrlen, struct addrnode *parent_node, int parent_index)
|
||||
{
|
||||
size_t n;
|
||||
struct addredge *edge = (struct addredge *)malloc( sizeof (*edge) );
|
||||
if (!edge)
|
||||
return NULL;
|
||||
edge->node = node;
|
||||
edge->len = addrlen;
|
||||
edge->parent_index = parent_index;
|
||||
edge->parent_node = parent_node;
|
||||
/* ceil() */
|
||||
n = (size_t)((addrlen / KEYWIDTH) + ((addrlen % KEYWIDTH != 0)?1:0));
|
||||
edge->str = (addrkey_t *)calloc(n, sizeof (addrkey_t));
|
||||
if (!edge->str) {
|
||||
free(edge);
|
||||
return NULL;
|
||||
}
|
||||
memcpy(edge->str, addr, n * sizeof (addrkey_t));
|
||||
/* Only manipulate other objects after successful alloc */
|
||||
node->parent_edge = edge;
|
||||
log_assert(parent_node->edge[parent_index] == NULL);
|
||||
parent_node->edge[parent_index] = edge;
|
||||
return edge;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new node
|
||||
* @param tree: Tree the node lives in.
|
||||
* @param elem: Element to store at this node
|
||||
* @param scope: Scopemask from server reply
|
||||
* @param ttl: Element is valid up to this time. Absolute, seconds
|
||||
* @return new addrnode or NULL on failure
|
||||
*/
|
||||
static struct addrnode *
|
||||
node_create(struct addrtree *tree, void *elem, addrlen_t scope,
|
||||
time_t ttl)
|
||||
{
|
||||
struct addrnode* node = (struct addrnode *)malloc( sizeof (*node) );
|
||||
if (!node)
|
||||
return NULL;
|
||||
node->elem = elem;
|
||||
tree->node_count++;
|
||||
node->scope = scope;
|
||||
node->ttl = ttl;
|
||||
node->edge[0] = NULL;
|
||||
node->edge[1] = NULL;
|
||||
node->parent_edge = NULL;
|
||||
node->next = NULL;
|
||||
node->prev = NULL;
|
||||
return node;
|
||||
}
|
||||
|
||||
/** Size in bytes of node and parent edge
|
||||
* @param tree: tree the node lives in
|
||||
* @param n: node which size must be calculated
|
||||
* @return size in bytes.
|
||||
**/
|
||||
static inline size_t
|
||||
node_size(const struct addrtree *tree, const struct addrnode *n)
|
||||
{
|
||||
return sizeof *n + sizeof *n->parent_edge + n->parent_edge->len +
|
||||
(n->elem?tree->sizefunc(n->elem):0);
|
||||
}
|
||||
|
||||
struct addrtree *
|
||||
addrtree_create(addrlen_t max_depth, void (*delfunc)(void *, void *),
|
||||
size_t (*sizefunc)(void *), void *env, unsigned int max_node_count)
|
||||
{
|
||||
struct addrtree *tree;
|
||||
log_assert(delfunc != NULL);
|
||||
log_assert(sizefunc != NULL);
|
||||
tree = (struct addrtree *)calloc(1, sizeof(*tree));
|
||||
if (!tree)
|
||||
return NULL;
|
||||
tree->root = node_create(tree, NULL, 0, 0);
|
||||
if (!tree->root) {
|
||||
free(tree);
|
||||
return NULL;
|
||||
}
|
||||
tree->size_bytes = sizeof *tree + sizeof *tree->root;
|
||||
tree->first = NULL;
|
||||
tree->last = NULL;
|
||||
tree->max_depth = max_depth;
|
||||
tree->delfunc = delfunc;
|
||||
tree->sizefunc = sizefunc;
|
||||
tree->env = env;
|
||||
tree->node_count = 0;
|
||||
tree->max_node_count = max_node_count;
|
||||
return tree;
|
||||
}
|
||||
|
||||
/**
|
||||
* Scrub a node clean of elem
|
||||
* @param tree: tree the node lives in.
|
||||
* @param node: node to be cleaned.
|
||||
*/
|
||||
static void
|
||||
clean_node(struct addrtree *tree, struct addrnode *node)
|
||||
{
|
||||
if (!node->elem) return;
|
||||
tree->size_bytes -= tree->sizefunc(node->elem);
|
||||
tree->delfunc(tree->env, node->elem);
|
||||
node->elem = NULL;
|
||||
}
|
||||
|
||||
/** Remove specified node from LRU list */
|
||||
static void
|
||||
lru_pop(struct addrtree *tree, struct addrnode *node)
|
||||
{
|
||||
if (node == tree->first) {
|
||||
if (!node->next) { /* it is the last as well */
|
||||
tree->first = NULL;
|
||||
tree->last = NULL;
|
||||
} else {
|
||||
tree->first = node->next;
|
||||
tree->first->prev = NULL;
|
||||
}
|
||||
} else if (node == tree->last) { /* but not the first */
|
||||
tree->last = node->prev;
|
||||
tree->last->next = NULL;
|
||||
} else {
|
||||
node->prev->next = node->next;
|
||||
node->next->prev = node->prev;
|
||||
}
|
||||
}
|
||||
|
||||
/** Add node to LRU list as most recently used. */
|
||||
static void
|
||||
lru_push(struct addrtree *tree, struct addrnode *node)
|
||||
{
|
||||
if (!tree->first) {
|
||||
tree->first = node;
|
||||
node->prev = NULL;
|
||||
} else {
|
||||
tree->last->next = node;
|
||||
node->prev = tree->last;
|
||||
}
|
||||
tree->last = node;
|
||||
node->next = NULL;
|
||||
}
|
||||
|
||||
/** Move node to the end of LRU list */
|
||||
static void
|
||||
lru_update(struct addrtree *tree, struct addrnode *node)
|
||||
{
|
||||
if (tree->root == node) return;
|
||||
lru_pop(tree, node);
|
||||
lru_push(tree, node);
|
||||
}
|
||||
|
||||
/**
|
||||
* Purge a node from the tree. Node and parentedge are cleaned and
|
||||
* free'd.
|
||||
* @param tree: Tree the node lives in.
|
||||
* @param node: Node to be freed
|
||||
*/
|
||||
static void
|
||||
purge_node(struct addrtree *tree, struct addrnode *node)
|
||||
{
|
||||
struct addredge *parent_edge, *child_edge = NULL;
|
||||
int index;
|
||||
int keep = node->edge[0] && node->edge[1];
|
||||
|
||||
clean_node(tree, node);
|
||||
parent_edge = node->parent_edge;
|
||||
if (keep || !parent_edge) return;
|
||||
tree->node_count--;
|
||||
index = parent_edge->parent_index;
|
||||
child_edge = node->edge[!node->edge[0]];
|
||||
if (child_edge) {
|
||||
child_edge->parent_node = parent_edge->parent_node;
|
||||
child_edge->parent_index = index;
|
||||
}
|
||||
parent_edge->parent_node->edge[index] = child_edge;
|
||||
tree->size_bytes -= node_size(tree, node);
|
||||
free(parent_edge->str);
|
||||
free(parent_edge);
|
||||
lru_pop(tree, node);
|
||||
free(node);
|
||||
}
|
||||
|
||||
/**
|
||||
* If a limit is set remove old nodes while above that limit.
|
||||
* @param tree: Tree to be cleaned up.
|
||||
*/
|
||||
static void
|
||||
lru_cleanup(struct addrtree *tree)
|
||||
{
|
||||
struct addrnode *n, *p;
|
||||
int children;
|
||||
if (tree->max_node_count == 0) return;
|
||||
while (tree->node_count > tree->max_node_count) {
|
||||
n = tree->first;
|
||||
if (!n) break;
|
||||
children = (n->edge[0] != NULL) + (n->edge[1] != NULL);
|
||||
/** Don't remove this node, it is either the root or we can't
|
||||
* do without it because it has 2 children */
|
||||
if (children == 2 || !n->parent_edge) {
|
||||
lru_update(tree, n);
|
||||
continue;
|
||||
}
|
||||
p = n->parent_edge->parent_node;
|
||||
purge_node(tree, n);
|
||||
/** Since we removed n, n's parent p is eligible for deletion
|
||||
* if it is not the root node, caries no data and has only 1
|
||||
* child */
|
||||
children = (p->edge[0] != NULL) + (p->edge[1] != NULL);
|
||||
if (!p->elem && children == 1 && p->parent_edge) {
|
||||
purge_node(tree, p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline size_t
|
||||
addrtree_size(const struct addrtree *tree)
|
||||
{
|
||||
return tree?tree->size_bytes:0;
|
||||
}
|
||||
|
||||
void addrtree_delete(struct addrtree *tree)
|
||||
{
|
||||
struct addrnode *n;
|
||||
if (!tree) return;
|
||||
clean_node(tree, tree->root);
|
||||
free(tree->root);
|
||||
tree->size_bytes -= sizeof(struct addrnode);
|
||||
while ((n = tree->first)) {
|
||||
tree->first = n->next;
|
||||
clean_node(tree, n);
|
||||
tree->size_bytes -= node_size(tree, n);
|
||||
free(n->parent_edge->str);
|
||||
free(n->parent_edge);
|
||||
free(n);
|
||||
}
|
||||
log_assert(sizeof *tree == addrtree_size(tree));
|
||||
free(tree);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get N'th bit from address
|
||||
* @param addr: address to inspect
|
||||
* @param addrlen: length of addr in bits
|
||||
* @param n: index of bit to test. Must be in range [0, addrlen)
|
||||
* @return 0 or 1
|
||||
*/
|
||||
static int
|
||||
getbit(const addrkey_t *addr, addrlen_t addrlen, addrlen_t n)
|
||||
{
|
||||
log_assert(addrlen > n);
|
||||
return (int)(addr[n/KEYWIDTH]>>((KEYWIDTH-1)-(n%KEYWIDTH))) & 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for equality on N'th bit.
|
||||
* @return 0 for equal, 1 otherwise
|
||||
*/
|
||||
static inline int
|
||||
cmpbit(const addrkey_t *key1, const addrkey_t *key2, addrlen_t n)
|
||||
{
|
||||
addrkey_t c = key1[n/KEYWIDTH] ^ key2[n/KEYWIDTH];
|
||||
return (int)(c >> ((KEYWIDTH-1)-(n%KEYWIDTH))) & 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Common number of bits in prefix.
|
||||
* @param s1: first prefix.
|
||||
* @param l1: length of s1 in bits.
|
||||
* @param s2: second prefix.
|
||||
* @param l2: length of s2 in bits.
|
||||
* @param skip: nr of bits already checked.
|
||||
* @return common number of bits.
|
||||
*/
|
||||
static addrlen_t
|
||||
bits_common(const addrkey_t *s1, addrlen_t l1,
|
||||
const addrkey_t *s2, addrlen_t l2, addrlen_t skip)
|
||||
{
|
||||
addrlen_t len, i;
|
||||
len = (l1 > l2) ? l2 : l1;
|
||||
log_assert(skip < len);
|
||||
for (i = skip; i < len; i++) {
|
||||
if (cmpbit(s1, s2, i)) return i;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests if s1 is a substring of s2
|
||||
* @param s1: first prefix.
|
||||
* @param l1: length of s1 in bits.
|
||||
* @param s2: second prefix.
|
||||
* @param l2: length of s2 in bits.
|
||||
* @param skip: nr of bits already checked.
|
||||
* @return 1 for substring, 0 otherwise
|
||||
*/
|
||||
static int
|
||||
issub(const addrkey_t *s1, addrlen_t l1,
|
||||
const addrkey_t *s2, addrlen_t l2, addrlen_t skip)
|
||||
{
|
||||
return bits_common(s1, l1, s2, l2, skip) == l1;
|
||||
}
|
||||
|
||||
void
|
||||
addrtree_insert(struct addrtree *tree, const addrkey_t *addr,
|
||||
addrlen_t sourcemask, addrlen_t scope, void *elem, time_t ttl,
|
||||
time_t now)
|
||||
{
|
||||
struct addrnode *newnode, *node;
|
||||
struct addredge *edge;
|
||||
int index;
|
||||
addrlen_t common, depth;
|
||||
|
||||
node = tree->root;
|
||||
log_assert(node != NULL);
|
||||
|
||||
/* Protect our cache against too much fine-grained data */
|
||||
if (tree->max_depth < scope) scope = tree->max_depth;
|
||||
/* Server answer was less specific than question */
|
||||
if (scope < sourcemask) sourcemask = scope;
|
||||
|
||||
depth = 0;
|
||||
while (1) {
|
||||
log_assert(depth <= sourcemask);
|
||||
/* Case 1: update existing node */
|
||||
if (depth == sourcemask) {
|
||||
/* update this node's scope and data */
|
||||
clean_node(tree, node);
|
||||
node->ttl = ttl;
|
||||
node->elem = elem;
|
||||
node->scope = scope;
|
||||
tree->size_bytes += tree->sizefunc(elem);
|
||||
return;
|
||||
}
|
||||
index = getbit(addr, sourcemask, depth);
|
||||
/* Get an edge to an unexpired node */
|
||||
edge = node->edge[index];
|
||||
while (edge) {
|
||||
/* Purge all expired nodes on path */
|
||||
if (!edge->node->elem || edge->node->ttl >= now)
|
||||
break;
|
||||
purge_node(tree, edge->node);
|
||||
edge = node->edge[index];
|
||||
}
|
||||
/* Case 2: New leafnode */
|
||||
if (!edge) {
|
||||
newnode = node_create(tree, elem, scope, ttl);
|
||||
if (!newnode) return;
|
||||
if (!edge_create(newnode, addr, sourcemask, node,
|
||||
index)) {
|
||||
clean_node(tree, newnode);
|
||||
tree->node_count--;
|
||||
free(newnode);
|
||||
return;
|
||||
}
|
||||
tree->size_bytes += node_size(tree, newnode);
|
||||
lru_push(tree, newnode);
|
||||
lru_cleanup(tree);
|
||||
return;
|
||||
}
|
||||
/* Case 3: Traverse edge */
|
||||
common = bits_common(edge->str, edge->len, addr, sourcemask,
|
||||
depth);
|
||||
if (common == edge->len) {
|
||||
/* We update the scope of intermediate nodes. Apparently
|
||||
* the * authority changed its mind. If we would not do
|
||||
* this we might not be able to reach our new node. */
|
||||
node->scope = scope;
|
||||
depth = edge->len;
|
||||
node = edge->node;
|
||||
continue;
|
||||
}
|
||||
/* Case 4: split. */
|
||||
if (!(newnode = node_create(tree, NULL, 0, 0)))
|
||||
return;
|
||||
node->edge[index] = NULL;
|
||||
if (!edge_create(newnode, addr, common, node, index)) {
|
||||
node->edge[index] = edge;
|
||||
clean_node(tree, newnode);
|
||||
tree->node_count--;
|
||||
free(newnode);
|
||||
return;
|
||||
}
|
||||
lru_push(tree, newnode);
|
||||
/* connect existing child to our new node */
|
||||
index = getbit(edge->str, edge->len, common);
|
||||
newnode->edge[index] = edge;
|
||||
edge->parent_node = newnode;
|
||||
edge->parent_index = (int)index;
|
||||
|
||||
if (common == sourcemask) {
|
||||
/* Data is stored in the node */
|
||||
newnode->elem = elem;
|
||||
newnode->scope = scope;
|
||||
newnode->ttl = ttl;
|
||||
}
|
||||
|
||||
tree->size_bytes += node_size(tree, newnode);
|
||||
|
||||
if (common != sourcemask) {
|
||||
/* Data is stored in other leafnode */
|
||||
node = newnode;
|
||||
newnode = node_create(tree, elem, scope, ttl);
|
||||
if (!edge_create(newnode, addr, sourcemask, node,
|
||||
index^1)) {
|
||||
clean_node(tree, newnode);
|
||||
tree->node_count--;
|
||||
free(newnode);
|
||||
return;
|
||||
}
|
||||
tree->size_bytes += node_size(tree, newnode);
|
||||
lru_push(tree, newnode);
|
||||
}
|
||||
lru_cleanup(tree);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
struct addrnode *
|
||||
addrtree_find(struct addrtree *tree, const addrkey_t *addr,
|
||||
addrlen_t sourcemask, time_t now)
|
||||
{
|
||||
struct addrnode *node = tree->root;
|
||||
struct addredge *edge = NULL;
|
||||
addrlen_t depth = 0;
|
||||
|
||||
log_assert(node != NULL);
|
||||
while (1) {
|
||||
/* Current node more specific then question. */
|
||||
log_assert(depth <= sourcemask);
|
||||
/* 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)
|
||||
if (depth == node->scope ||
|
||||
(node->scope > sourcemask &&
|
||||
depth == sourcemask)) {
|
||||
/* Authority indicates it does not have a more
|
||||
* precise answer or we cannot ask a more
|
||||
* specific question. */
|
||||
lru_update(tree, node);
|
||||
return node;
|
||||
}
|
||||
}
|
||||
/* This is our final depth, but we haven't found an answer. */
|
||||
if (depth == sourcemask)
|
||||
return NULL;
|
||||
/* Find an edge to traverse */
|
||||
edge = node->edge[getbit(addr, sourcemask, depth)];
|
||||
if (!edge || !edge->node)
|
||||
return NULL;
|
||||
if (edge->len > sourcemask )
|
||||
return NULL;
|
||||
if (!issub(edge->str, edge->len, addr, sourcemask, depth))
|
||||
return NULL;
|
||||
log_assert(depth < edge->len);
|
||||
depth = edge->len;
|
||||
node = edge->node;
|
||||
}
|
||||
}
|
||||
|
||||
/** Wrappers for static functions to unit test */
|
||||
int unittest_wrapper_addrtree_cmpbit(const addrkey_t *key1,
|
||||
const addrkey_t *key2, addrlen_t n) {
|
||||
return cmpbit(key1, key2, n);
|
||||
}
|
||||
addrlen_t unittest_wrapper_addrtree_bits_common(const addrkey_t *s1,
|
||||
addrlen_t l1, const addrkey_t *s2, addrlen_t l2, addrlen_t skip) {
|
||||
return bits_common(s1, l1, s2, l2, skip);
|
||||
}
|
||||
int unittest_wrapper_addrtree_getbit(const addrkey_t *addr,
|
||||
addrlen_t addrlen, addrlen_t n) {
|
||||
return getbit(addr, addrlen, n);
|
||||
}
|
||||
int unittest_wrapper_addrtree_issub(const addrkey_t *s1, addrlen_t l1,
|
||||
const addrkey_t *s2, addrlen_t l2, addrlen_t skip) {
|
||||
return issub(s1, l1, s2, l2, skip);
|
||||
}
|
||||
187
edns-subnet/addrtree.h
Normal file
187
edns-subnet/addrtree.h
Normal file
|
|
@ -0,0 +1,187 @@
|
|||
/*
|
||||
* edns-subnet/addrtree.h -- radix tree for edns subnet cache.
|
||||
*
|
||||
* Copyright (c) 2013, NLnet Labs. All rights reserved.
|
||||
*
|
||||
* This software is open source.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* Neither the name of the NLNET LABS nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
* The addrtree is a radix tree designed for edns subnet. Most notable
|
||||
* is the addition of 'scope' to a node. Scope is only relevant for
|
||||
* nodes with elem set, it indicates the number of bits the authority
|
||||
* desires.
|
||||
*
|
||||
* For retrieving data one needs an address and address length
|
||||
* (sourcemask). While traversing the tree the first matching node is
|
||||
* returned. A node matches when
|
||||
* node.scope<=sourcemask && node.elem!=NULL
|
||||
* (This is the most specific answer the authority has.)
|
||||
* or
|
||||
* node.sourcemask==sourcemask && node.elem!=NULL
|
||||
* (This is the most specific question the client can ask.)
|
||||
*
|
||||
* Insertion needs an address, sourcemask and scope. The length of the
|
||||
* address is capped by min(sourcemask, scope). While traversing the
|
||||
* tree the scope of all visited nodes is updated. This ensures we are
|
||||
* always able to find the most specific answer available.
|
||||
*/
|
||||
|
||||
#ifndef ADDRTREE_H
|
||||
#define ADDRTREE_H
|
||||
|
||||
typedef uint8_t addrlen_t;
|
||||
typedef uint8_t addrkey_t;
|
||||
#define KEYWIDTH 8
|
||||
|
||||
struct addrtree {
|
||||
struct addrnode *root;
|
||||
/** Number of elements in the tree (not always equal to number of
|
||||
* nodes) */
|
||||
unsigned int node_count;
|
||||
/** Maximum number of allowed nodes, will be enforced by LRU list.
|
||||
* Excluding the root node, 0 for unlimited */
|
||||
unsigned int max_node_count;
|
||||
/** Size of tree in bytes */
|
||||
size_t size_bytes;
|
||||
/** Maximum prefix length we are willing to cache. */
|
||||
addrlen_t max_depth;
|
||||
/** External function to delete elem. Called as
|
||||
* delfunc(addrnode->elem, addrtree->env) */
|
||||
void (*delfunc)(void *, void *);
|
||||
/** Environment for delfunc */
|
||||
void *env;
|
||||
/** External function returning size of elem. Called as
|
||||
* sizefunc(addrnode->elem) */
|
||||
size_t (*sizefunc)(void *);
|
||||
/** first node in LRU list, first candidate to go */
|
||||
struct addrnode* first;
|
||||
/** last node in LRU list, last candidate to go */
|
||||
struct addrnode *last;
|
||||
};
|
||||
|
||||
struct addrnode {
|
||||
/** Payload of node, may be NULL */
|
||||
void *elem;
|
||||
/** Abs time in seconds in which elem is meaningful */
|
||||
time_t ttl;
|
||||
/** Number of significant bits in address. */
|
||||
addrlen_t scope;
|
||||
/** A node can have 0-2 edges, set to NULL for unused */
|
||||
struct addredge *edge[2];
|
||||
/** edge between this node and parent */
|
||||
struct addredge *parent_edge;
|
||||
/** previous node in LRU list */
|
||||
struct addrnode *prev;
|
||||
/** next node in LRU list */
|
||||
struct addrnode *next;
|
||||
};
|
||||
|
||||
struct addredge {
|
||||
/** address of connected node */
|
||||
addrkey_t *str;
|
||||
/** lenght in bits of str */
|
||||
addrlen_t len;
|
||||
/** child node this edge is connected to */
|
||||
struct addrnode *node;
|
||||
/** Parent node this ege is connected to */
|
||||
struct addrnode *parent_node;
|
||||
/** Index of this edge in parent_node */
|
||||
int parent_index;
|
||||
};
|
||||
|
||||
/**
|
||||
* Size of tree in bytes.
|
||||
* @param tree: Tree.
|
||||
* @return size of tree in bytes.
|
||||
*/
|
||||
size_t addrtree_size(const struct addrtree *tree);
|
||||
|
||||
/**
|
||||
* Create a new tree.
|
||||
* @param max_depth: Tree will cap keys to this length.
|
||||
* @param delfunc: f(element, env) delete element.
|
||||
* @param sizefunc: f(element) returning the size of element.
|
||||
* @param env: Module environment for alloc information.
|
||||
* @param max_node_count: Maximum size of this data structure in nodes.
|
||||
* 0 for unlimited.
|
||||
* @return new addrtree or NULL on failure.
|
||||
*/
|
||||
struct addrtree *
|
||||
addrtree_create(addrlen_t max_depth, void (*delfunc)(void *, void *),
|
||||
size_t (*sizefunc)(void *), void *env, unsigned int max_node_count);
|
||||
|
||||
/**
|
||||
* Free tree and all nodes below.
|
||||
* @param tree: Tree to be freed.
|
||||
*/
|
||||
void addrtree_delete(struct addrtree *tree);
|
||||
|
||||
/**
|
||||
* Insert an element in the tree. Failures are silent. Sourcemask and
|
||||
* scope might be changed according to local policy. Caller should no
|
||||
* longer access elem, it could be free'd now or later during future
|
||||
* inserts.
|
||||
*
|
||||
* @param tree: Tree insert elem in.
|
||||
* @param addr: key for element lookup.
|
||||
* @param sourcemask: Length of addr in bits.
|
||||
* @param scope: Number of significant bits in addr.
|
||||
* @param elem: data to store in the tree.
|
||||
* @param ttl: elem is valid up to this time, seconds.
|
||||
* @param now: Current time in seconds.
|
||||
*/
|
||||
void addrtree_insert(struct addrtree *tree, const addrkey_t *addr,
|
||||
addrlen_t sourcemask, addrlen_t scope, void *elem, time_t ttl,
|
||||
time_t now);
|
||||
|
||||
/**
|
||||
* Find a node containing an element in the tree.
|
||||
*
|
||||
* @param tree: Tree to search.
|
||||
* @param addr: key for element lookup.
|
||||
* @param sourcemask: Length of addr in bits.
|
||||
* @param now: Current time in seconds.
|
||||
* @return addrnode or NULL on miss.
|
||||
*/
|
||||
struct addrnode * addrtree_find(struct addrtree *tree,
|
||||
const addrkey_t *addr, addrlen_t sourcemask, time_t now);
|
||||
|
||||
/** Wrappers for static functions to unit test */
|
||||
int unittest_wrapper_addrtree_cmpbit(const addrkey_t *key1,
|
||||
const addrkey_t *key2, addrlen_t n);
|
||||
addrlen_t unittest_wrapper_addrtree_bits_common(const addrkey_t *s1,
|
||||
addrlen_t l1, const addrkey_t *s2, addrlen_t l2, addrlen_t skip);
|
||||
int unittest_wrapper_addrtree_getbit(const addrkey_t *addr,
|
||||
addrlen_t addrlen, addrlen_t n);
|
||||
int unittest_wrapper_addrtree_issub(const addrkey_t *s1, addrlen_t l1,
|
||||
const addrkey_t *s2, addrlen_t l2, addrlen_t skip);
|
||||
#endif /* ADDRTREE_H */
|
||||
65
edns-subnet/edns-subnet.c
Normal file
65
edns-subnet/edns-subnet.c
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
* edns-subnet/edns-subnet.c - Subnet option related constants
|
||||
*
|
||||
* Copyright (c) 2013, NLnet Labs. All rights reserved.
|
||||
*
|
||||
* This software is open source.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* Neither the name of the NLNET LABS nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
/**
|
||||
* \file
|
||||
* Subnet option related constants.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifdef CLIENT_SUBNET /* keeps splint happy */
|
||||
#include "edns-subnet/edns-subnet.h"
|
||||
#include <string.h>
|
||||
|
||||
int
|
||||
copy_clear(uint8_t* dst, size_t dstlen, uint8_t* src, size_t srclen, size_t n)
|
||||
{
|
||||
size_t intpart = n / 8; /* bytes */
|
||||
size_t fracpart = n % 8; /* bits */
|
||||
size_t written = intpart;
|
||||
if (intpart > dstlen || intpart > srclen)
|
||||
return 1;
|
||||
if (fracpart && (intpart+1 > dstlen || intpart+1 > srclen))
|
||||
return 1;
|
||||
memcpy(dst, src, intpart);
|
||||
if (fracpart) {
|
||||
dst[intpart] = src[intpart] & ~(0xFF >> fracpart);
|
||||
written++;
|
||||
}
|
||||
memset(dst + written, 0, dstlen - written);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* CLIENT_SUBNET */
|
||||
67
edns-subnet/edns-subnet.h
Normal file
67
edns-subnet/edns-subnet.h
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
* edns-subnet/edns-subnet.h - Subnet option related constants
|
||||
*
|
||||
* Copyright (c) 2013, NLnet Labs. All rights reserved.
|
||||
*
|
||||
* This software is open source.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* Neither the name of the NLNET LABS nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
/**
|
||||
* \file
|
||||
* Subnet option related constants.
|
||||
*/
|
||||
|
||||
#include "util/net_help.h"
|
||||
|
||||
#ifndef EDNSSUBNET_EDNSSUBNET_H
|
||||
#define EDNSSUBNET_EDNSSUBNET_H
|
||||
|
||||
/** In use by the edns subnet option code, as assigned by IANA */
|
||||
#define EDNSSUBNET_ADDRFAM_IP4 1
|
||||
#define EDNSSUBNET_ADDRFAM_IP6 2
|
||||
|
||||
/**
|
||||
* ECS option
|
||||
*/
|
||||
struct ecs_data {
|
||||
uint16_t subnet_addr_fam;
|
||||
uint8_t subnet_source_mask;
|
||||
uint8_t subnet_scope_mask;
|
||||
uint8_t subnet_addr[INET6_SIZE];
|
||||
int subnet_validdata;
|
||||
};
|
||||
|
||||
/**
|
||||
* copy the first n BITS from src to dst iff both src and dst
|
||||
* are large enough, return 0 on succes
|
||||
*/
|
||||
int
|
||||
copy_clear(uint8_t* dst, size_t dstlen, uint8_t* src, size_t srclen, size_t n);
|
||||
|
||||
#endif /* EDNSSUBNET_EDNSSUBNET_H */
|
||||
153
edns-subnet/subnet-whitelist.c
Normal file
153
edns-subnet/subnet-whitelist.c
Normal file
|
|
@ -0,0 +1,153 @@
|
|||
/*
|
||||
* edns-subnet/subnet-whitelist.c - Hosts we actively try to send subnet option
|
||||
* to.
|
||||
*
|
||||
* Copyright (c) 2013, NLnet Labs. All rights reserved.
|
||||
*
|
||||
* This software is open source.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* Neither the name of the NLNET LABS nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* Keep track of the white listed servers for subnet option. Based
|
||||
* on acl_list.c|h
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifdef CLIENT_SUBNET /* keeps splint happy */
|
||||
#include "edns-subnet/edns-subnet.h"
|
||||
#include "edns-subnet/subnet-whitelist.h"
|
||||
#include "util/regional.h"
|
||||
#include "util/log.h"
|
||||
#include "util/config_file.h"
|
||||
#include "util/net_help.h"
|
||||
#include "util/storage/dnstree.h"
|
||||
|
||||
struct ednssubnet_upstream*
|
||||
upstream_create(void)
|
||||
{
|
||||
struct ednssubnet_upstream* upstream =
|
||||
(struct ednssubnet_upstream*)calloc(1,
|
||||
sizeof(struct ednssubnet_upstream));
|
||||
if(!upstream)
|
||||
return NULL;
|
||||
upstream->region = regional_create();
|
||||
if(!upstream->region) {
|
||||
upstream_delete(upstream);
|
||||
return NULL;
|
||||
}
|
||||
return upstream;
|
||||
}
|
||||
|
||||
void
|
||||
upstream_delete(struct ednssubnet_upstream* upstream)
|
||||
{
|
||||
if(!upstream)
|
||||
return;
|
||||
regional_destroy(upstream->region);
|
||||
free(upstream);
|
||||
}
|
||||
|
||||
/** insert new address into upstream structure */
|
||||
static int
|
||||
upstream_insert(struct ednssubnet_upstream* upstream,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen, int net)
|
||||
{
|
||||
struct addr_tree_node* node = (struct addr_tree_node*)regional_alloc(
|
||||
upstream->region, sizeof(*node));
|
||||
if(!node)
|
||||
return 0;
|
||||
if(!addr_tree_insert(&upstream->tree, node, addr, addrlen, net)) {
|
||||
verbose(VERB_QUERY,
|
||||
"duplicate send-client-subnet address ignored.");
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** apply edns-subnet string */
|
||||
static int
|
||||
upstream_str_cfg(struct ednssubnet_upstream* upstream, const char* str)
|
||||
{
|
||||
struct sockaddr_storage addr;
|
||||
int net;
|
||||
socklen_t addrlen;
|
||||
verbose(VERB_ALGO, "send-client-subnet: %s", str);
|
||||
if(!netblockstrtoaddr(str, UNBOUND_DNS_PORT, &addr, &addrlen, &net)) {
|
||||
log_err("cannot parse send-client-subnet netblock: %s", str);
|
||||
return 0;
|
||||
}
|
||||
if(!upstream_insert(upstream, &addr, addrlen, net)) {
|
||||
log_err("out of memory");
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** read client_subnet config */
|
||||
static int
|
||||
read_upstream(struct ednssubnet_upstream* upstream, struct config_file* cfg)
|
||||
{
|
||||
struct config_strlist* p;
|
||||
for(p = cfg->client_subnet; p; p = p->next) {
|
||||
log_assert(p->str);
|
||||
if(!upstream_str_cfg(upstream, p->str))
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
upstream_apply_cfg(struct ednssubnet_upstream* upstream,
|
||||
struct config_file* cfg)
|
||||
{
|
||||
regional_free_all(upstream->region);
|
||||
addr_tree_init(&upstream->tree);
|
||||
if(!read_upstream(upstream, cfg))
|
||||
return 0;
|
||||
addr_tree_init_parents(&upstream->tree);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
upstream_is_whitelisted(struct ednssubnet_upstream* upstream,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen)
|
||||
{
|
||||
return addr_tree_lookup(&upstream->tree, addr, addrlen) != NULL;
|
||||
}
|
||||
|
||||
size_t
|
||||
upstream_get_mem(struct ednssubnet_upstream* upstream)
|
||||
{
|
||||
if(!upstream) return 0;
|
||||
return sizeof(*upstream) + regional_get_mem(upstream->region);
|
||||
}
|
||||
|
||||
#endif /* CLIENT_SUBNET */
|
||||
102
edns-subnet/subnet-whitelist.h
Normal file
102
edns-subnet/subnet-whitelist.h
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
/*
|
||||
* edns-subnet/subnet-whitelist.h - Hosts we actively try to send subnet option
|
||||
* to.
|
||||
*
|
||||
* Copyright (c) 2013, NLnet Labs. All rights reserved.
|
||||
*
|
||||
* This software is open source.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* Neither the name of the NLNET LABS nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* Keep track of the white listed servers for subnet option. Based
|
||||
* on acl_list.c|h
|
||||
*/
|
||||
|
||||
#ifndef EDNSSUBNET_WHITELIST_H
|
||||
#define EDNSSUBNET_WHITELIST_H
|
||||
#include "util/storage/dnstree.h"
|
||||
|
||||
struct config_file;
|
||||
struct regional;
|
||||
|
||||
/**
|
||||
* ednssubnet_upstream structure
|
||||
*/
|
||||
struct ednssubnet_upstream {
|
||||
/** regional for allocation */
|
||||
struct regional* region;
|
||||
/**
|
||||
* Tree of the address spans that are whitelisted.
|
||||
* contents of type addr_tree_node. Each node is an address span
|
||||
* Unbound will append subnet option for.
|
||||
*/
|
||||
rbtree_type tree;
|
||||
};
|
||||
|
||||
/**
|
||||
* Create ednssubnet_upstream structure
|
||||
* @return new structure or NULL on error.
|
||||
*/
|
||||
struct ednssubnet_upstream* upstream_create(void);
|
||||
|
||||
/**
|
||||
* Delete ednssubnet_upstream structure.
|
||||
* @param upstream: to delete.
|
||||
*/
|
||||
void upstream_delete(struct ednssubnet_upstream* upstream);
|
||||
|
||||
/**
|
||||
* Process ednssubnet_upstream config.
|
||||
* @param upstream: where to store.
|
||||
* @param cfg: config options.
|
||||
* @return 0 on error.
|
||||
*/
|
||||
int upstream_apply_cfg(struct ednssubnet_upstream* upstream,
|
||||
struct config_file* cfg);
|
||||
|
||||
/**
|
||||
* See if an address is whitelisted.
|
||||
* @param upstream: structure for address storage.
|
||||
* @param addr: address to check
|
||||
* @param addrlen: length of addr.
|
||||
* @return: true if the address is whitelisted for subnet option.
|
||||
*/
|
||||
int upstream_is_whitelisted(struct ednssubnet_upstream* upstream,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen);
|
||||
|
||||
/**
|
||||
* Get memory used by ednssubnet_upstream structure.
|
||||
* @param upstream: structure for address storage.
|
||||
* @return bytes in use.
|
||||
*/
|
||||
size_t upstream_get_mem(struct ednssubnet_upstream* upstream);
|
||||
|
||||
#endif /* EDNSSUBNET_WHITELIST_H */
|
||||
808
edns-subnet/subnetmod.c
Normal file
808
edns-subnet/subnetmod.c
Normal file
|
|
@ -0,0 +1,808 @@
|
|||
/*
|
||||
* edns-subnet/subnetmod.c - edns subnet module. Must be called before validator
|
||||
* and iterator.
|
||||
*
|
||||
* Copyright (c) 2013, NLnet Labs. All rights reserved.
|
||||
*
|
||||
* This software is open source.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* Neither the name of the NLNET LABS nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
/**
|
||||
* \file
|
||||
* subnet module for unbound.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifdef CLIENT_SUBNET /* keeps splint happy */
|
||||
|
||||
#include "edns-subnet/subnetmod.h"
|
||||
#include "edns-subnet/edns-subnet.h"
|
||||
#include "edns-subnet/addrtree.h"
|
||||
#include "edns-subnet/subnet-whitelist.h"
|
||||
|
||||
#include "services/mesh.h"
|
||||
#include "services/cache/dns.h"
|
||||
#include "util/module.h"
|
||||
#include "util/regional.h"
|
||||
#include "util/storage/slabhash.h"
|
||||
#include "util/config_file.h"
|
||||
#include "util/data/msgreply.h"
|
||||
#include "sldns/sbuffer.h"
|
||||
|
||||
#define ECS_MAX_TREESIZE 100
|
||||
|
||||
/** externally called */
|
||||
void
|
||||
subnet_data_delete(void *d, void *ATTR_UNUSED(arg))
|
||||
{
|
||||
struct subnet_msg_cache_data *r;
|
||||
r = (struct subnet_msg_cache_data*)d;
|
||||
addrtree_delete(r->tree4);
|
||||
addrtree_delete(r->tree6);
|
||||
free(r);
|
||||
}
|
||||
|
||||
/** externally called */
|
||||
size_t
|
||||
msg_cache_sizefunc(void *k, void *d)
|
||||
{
|
||||
struct msgreply_entry *q = (struct msgreply_entry*)k;
|
||||
struct subnet_msg_cache_data *r = (struct subnet_msg_cache_data*)d;
|
||||
size_t s = sizeof(struct msgreply_entry)
|
||||
+ sizeof(struct subnet_msg_cache_data)
|
||||
+ q->key.qname_len + lock_get_mem(&q->entry.lock);
|
||||
s += addrtree_size(r->tree4);
|
||||
s += addrtree_size(r->tree6);
|
||||
return s;
|
||||
}
|
||||
|
||||
/** new query for ecs module */
|
||||
static int
|
||||
subnet_new_qstate(struct module_qstate *qstate, int id)
|
||||
{
|
||||
struct subnet_qstate *sq = (struct subnet_qstate*)regional_alloc(
|
||||
qstate->region, sizeof(struct subnet_qstate));
|
||||
if(!sq)
|
||||
return 0;
|
||||
qstate->minfo[id] = sq;
|
||||
memset(sq, 0, sizeof(*sq));
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** Add ecs struct to edns list, after parsing it to wire format. */
|
||||
static void
|
||||
ecs_opt_list_append(struct ecs_data* ecs, struct edns_option** list,
|
||||
struct module_qstate *qstate)
|
||||
{
|
||||
size_t sn_octs, sn_octs_remainder;
|
||||
sldns_buffer* buf = qstate->env->scratch_buffer;
|
||||
|
||||
if(ecs->subnet_validdata) {
|
||||
log_assert(ecs->subnet_addr_fam == EDNSSUBNET_ADDRFAM_IP4 ||
|
||||
ecs->subnet_addr_fam == EDNSSUBNET_ADDRFAM_IP6);
|
||||
log_assert(ecs->subnet_addr_fam != EDNSSUBNET_ADDRFAM_IP4 ||
|
||||
ecs->subnet_source_mask <= INET_SIZE*8);
|
||||
log_assert(ecs->subnet_addr_fam != EDNSSUBNET_ADDRFAM_IP6 ||
|
||||
ecs->subnet_source_mask <= INET6_SIZE*8);
|
||||
|
||||
sn_octs = ecs->subnet_source_mask / 8;
|
||||
sn_octs_remainder =
|
||||
(size_t)((ecs->subnet_source_mask % 8)>0?1:0);
|
||||
|
||||
log_assert(sn_octs + sn_octs_remainder <= INET6_SIZE);
|
||||
|
||||
sldns_buffer_clear(buf);
|
||||
sldns_buffer_write_u16(buf, ecs->subnet_addr_fam);
|
||||
sldns_buffer_write_u8(buf, ecs->subnet_source_mask);
|
||||
sldns_buffer_write_u8(buf, ecs->subnet_scope_mask);
|
||||
sldns_buffer_write(buf, ecs->subnet_addr, sn_octs);
|
||||
if(sn_octs_remainder)
|
||||
sldns_buffer_write_u8(buf, ecs->subnet_addr[sn_octs] &
|
||||
~(0xFF >> (ecs->subnet_source_mask % 8)));
|
||||
sldns_buffer_flip(buf);
|
||||
|
||||
edns_opt_list_append(list,
|
||||
qstate->env->cfg->client_subnet_opcode,
|
||||
sn_octs + sn_octs_remainder + 4,
|
||||
sldns_buffer_begin(buf), qstate->region);
|
||||
}
|
||||
}
|
||||
|
||||
int ecs_whitelist_check(struct query_info* ATTR_UNUSED(qinfo),
|
||||
uint16_t ATTR_UNUSED(flags), struct module_qstate* qstate,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen,
|
||||
uint8_t* ATTR_UNUSED(zone), size_t ATTR_UNUSED(zonelen),
|
||||
struct regional* ATTR_UNUSED(region), int id, void* ATTR_UNUSED(cbargs))
|
||||
{
|
||||
struct subnet_qstate *sq;
|
||||
struct subnet_env *sn_env;
|
||||
|
||||
if(!(sq=(struct subnet_qstate*)qstate->minfo[id]))
|
||||
return 1;
|
||||
sn_env = (struct subnet_env*)qstate->env->modinfo[id];
|
||||
|
||||
/* Cache by default, might be disabled after parsing EDNS option
|
||||
* received from nameserver. */
|
||||
qstate->no_cache_store = 0;
|
||||
|
||||
if(sq->ecs_server_out.subnet_validdata && ((sq->subnet_downstream &&
|
||||
qstate->env->cfg->client_subnet_always_forward) ||
|
||||
upstream_is_whitelisted(sn_env->edns_subnet_upstreams,
|
||||
addr, addrlen))) {
|
||||
/* Address on whitelist or client query contains ECS option, we
|
||||
* want to sent out ECS. Only add option if it is not already
|
||||
* set. */
|
||||
if(!(sq->subnet_sent)) {
|
||||
ecs_opt_list_append(&sq->ecs_server_out,
|
||||
&qstate->edns_opts_back_out, qstate);
|
||||
sq->subnet_sent = 1;
|
||||
}
|
||||
}
|
||||
else if(sq->subnet_sent) {
|
||||
/* Outgoing ECS option is set, but we don't want to sent it to
|
||||
* this address, remove option. */
|
||||
edns_opt_list_remove(&qstate->edns_opts_back_out,
|
||||
qstate->env->cfg->client_subnet_opcode);
|
||||
sq->subnet_sent = 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
subnetmod_init(struct module_env *env, int id)
|
||||
{
|
||||
struct subnet_env *sn_env = (struct subnet_env*)calloc(1,
|
||||
sizeof(struct subnet_env));
|
||||
if(!sn_env) {
|
||||
log_err("malloc failure");
|
||||
return 0;
|
||||
}
|
||||
alloc_init(&sn_env->alloc, NULL, 0);
|
||||
env->modinfo[id] = (void*)sn_env;
|
||||
/* Copy msg_cache settings */
|
||||
sn_env->subnet_msg_cache = slabhash_create(env->cfg->msg_cache_slabs,
|
||||
HASH_DEFAULT_STARTARRAY, env->cfg->msg_cache_size,
|
||||
msg_cache_sizefunc, query_info_compare, query_entry_delete,
|
||||
subnet_data_delete, NULL);
|
||||
if(!sn_env->subnet_msg_cache) {
|
||||
log_err("subnet: could not create cache");
|
||||
free(sn_env);
|
||||
env->modinfo[id] = NULL;
|
||||
return 0;
|
||||
}
|
||||
/* whitelist for edns subnet capable servers */
|
||||
sn_env->edns_subnet_upstreams = upstream_create();
|
||||
if(!sn_env->edns_subnet_upstreams ||
|
||||
!upstream_apply_cfg(sn_env->edns_subnet_upstreams, env->cfg)) {
|
||||
log_err("subnet: could not create ECS whitelist");
|
||||
slabhash_delete(sn_env->subnet_msg_cache);
|
||||
free(sn_env);
|
||||
env->modinfo[id] = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
verbose(VERB_QUERY, "subnet: option registered (%d)",
|
||||
env->cfg->client_subnet_opcode);
|
||||
/* Create new mesh state for all queries. */
|
||||
env->unique_mesh = 1;
|
||||
if(!edns_register_option(env->cfg->client_subnet_opcode,
|
||||
env->cfg->client_subnet_always_forward /* bypass cache */,
|
||||
0 /* no aggregation */, env)) {
|
||||
log_err("subnet: could not register opcode");
|
||||
upstream_delete(sn_env->edns_subnet_upstreams);
|
||||
slabhash_delete(sn_env->subnet_msg_cache);
|
||||
free(sn_env);
|
||||
env->modinfo[id] = NULL;
|
||||
return 0;
|
||||
}
|
||||
inplace_cb_register((void*)ecs_whitelist_check, inplace_cb_query, NULL,
|
||||
env, id);
|
||||
inplace_cb_register((void*)ecs_edns_back_parsed,
|
||||
inplace_cb_edns_back_parsed, NULL, env, id);
|
||||
inplace_cb_register((void*)ecs_query_response,
|
||||
inplace_cb_query_response, NULL, env, id);
|
||||
lock_rw_init(&sn_env->biglock);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
subnetmod_deinit(struct module_env *env, int id)
|
||||
{
|
||||
struct subnet_env *sn_env;
|
||||
if(!env || !env->modinfo[id])
|
||||
return;
|
||||
sn_env = (struct subnet_env*)env->modinfo[id];
|
||||
lock_rw_destroy(&sn_env->biglock);
|
||||
inplace_cb_delete(env, inplace_cb_edns_back_parsed, id);
|
||||
inplace_cb_delete(env, inplace_cb_query, id);
|
||||
upstream_delete(sn_env->edns_subnet_upstreams);
|
||||
slabhash_delete(sn_env->subnet_msg_cache);
|
||||
alloc_clear(&sn_env->alloc);
|
||||
free(sn_env);
|
||||
env->modinfo[id] = NULL;
|
||||
}
|
||||
|
||||
/** Tells client that upstream has no/improper support */
|
||||
static void
|
||||
cp_edns_bad_response(struct ecs_data *target, struct ecs_data *source)
|
||||
{
|
||||
target->subnet_scope_mask = 0;
|
||||
target->subnet_source_mask = source->subnet_source_mask;
|
||||
target->subnet_addr_fam = source->subnet_addr_fam;
|
||||
memcpy(target->subnet_addr, source->subnet_addr, INET6_SIZE);
|
||||
target->subnet_validdata = 1;
|
||||
}
|
||||
|
||||
static void
|
||||
delfunc(void *envptr, void *elemptr) {
|
||||
struct reply_info *elem = (struct reply_info *)elemptr;
|
||||
struct subnet_env *env = (struct subnet_env *)envptr;
|
||||
reply_info_parsedelete(elem, &env->alloc);
|
||||
}
|
||||
|
||||
static size_t
|
||||
sizefunc(void *elemptr) {
|
||||
struct reply_info *elem = (struct reply_info *)elemptr;
|
||||
return sizeof (struct reply_info) - sizeof (struct rrset_ref)
|
||||
+ elem->rrset_count * sizeof (struct rrset_ref)
|
||||
+ elem->rrset_count * sizeof (struct ub_packed_rrset_key *);
|
||||
}
|
||||
|
||||
/**
|
||||
* Select tree from cache entry based on edns data.
|
||||
* If for address family not present it will create a new one.
|
||||
* NULL on failure to create. */
|
||||
static struct addrtree*
|
||||
get_tree(struct subnet_msg_cache_data *data, struct ecs_data *edns,
|
||||
struct subnet_env *env, struct config_file* cfg)
|
||||
{
|
||||
struct addrtree *tree;
|
||||
if (edns->subnet_addr_fam == EDNSSUBNET_ADDRFAM_IP4) {
|
||||
if (!data->tree4)
|
||||
data->tree4 = addrtree_create(
|
||||
cfg->max_client_subnet_ipv4, &delfunc,
|
||||
&sizefunc, env, ECS_MAX_TREESIZE);
|
||||
tree = data->tree4;
|
||||
} else {
|
||||
if (!data->tree6)
|
||||
data->tree6 = addrtree_create(
|
||||
cfg->max_client_subnet_ipv6, &delfunc,
|
||||
&sizefunc, env, ECS_MAX_TREESIZE);
|
||||
tree = data->tree6;
|
||||
}
|
||||
return tree;
|
||||
}
|
||||
|
||||
static void
|
||||
update_cache(struct module_qstate *qstate, int id)
|
||||
{
|
||||
struct msgreply_entry *mrep_entry;
|
||||
struct addrtree *tree;
|
||||
struct reply_info *rep;
|
||||
struct query_info qinf;
|
||||
struct subnet_env *sne = qstate->env->modinfo[id];
|
||||
struct subnet_qstate *sq = (struct subnet_qstate*)qstate->minfo[id];
|
||||
struct slabhash *subnet_msg_cache = sne->subnet_msg_cache;
|
||||
struct ecs_data *edns = &sq->ecs_client_in;
|
||||
size_t i;
|
||||
|
||||
/* We already calculated hash upon lookup */
|
||||
hashvalue_type h = qstate->minfo[id] ?
|
||||
((struct subnet_qstate*)qstate->minfo[id])->qinfo_hash :
|
||||
query_info_hash(&qstate->qinfo, qstate->query_flags);
|
||||
/* Step 1, general qinfo lookup */
|
||||
struct lruhash_entry *lru_entry = slabhash_lookup(subnet_msg_cache, h,
|
||||
&qstate->qinfo, 1);
|
||||
int acquired_lock = (lru_entry != NULL);
|
||||
if (!lru_entry) {
|
||||
qinf = qstate->qinfo;
|
||||
qinf.qname = memdup(qstate->qinfo.qname,
|
||||
qstate->qinfo.qname_len);
|
||||
if(!qinf.qname) {
|
||||
log_err("memdup failed");
|
||||
return;
|
||||
}
|
||||
mrep_entry = query_info_entrysetup(&qinf, NULL, h);
|
||||
free(qinf.qname); /* if qname 'consumed', it is set to NULL */
|
||||
if (!mrep_entry) {
|
||||
log_err("query_info_entrysetup failed");
|
||||
return;
|
||||
}
|
||||
lru_entry = &mrep_entry->entry;
|
||||
lru_entry->data = calloc(1,
|
||||
sizeof(struct subnet_msg_cache_data));
|
||||
if (!lru_entry->data) {
|
||||
log_err("malloc failed");
|
||||
return;
|
||||
}
|
||||
}
|
||||
/* Step 2, find the correct tree */
|
||||
if (!(tree = get_tree(lru_entry->data, edns, sne, qstate->env->cfg))) {
|
||||
if (acquired_lock) lock_rw_unlock(&lru_entry->lock);
|
||||
log_err("Subnet cache insertion failed");
|
||||
return;
|
||||
}
|
||||
rep = reply_info_copy(qstate->return_msg->rep, &sne->alloc, NULL);
|
||||
if (!rep) {
|
||||
if (acquired_lock) lock_rw_unlock(&lru_entry->lock);
|
||||
log_err("Subnet cache insertion failed");
|
||||
return;
|
||||
}
|
||||
|
||||
/* store RRsets */
|
||||
for(i=0; i<rep->rrset_count; i++) {
|
||||
rep->ref[i].key = rep->rrsets[i];
|
||||
rep->ref[i].id = rep->rrsets[i]->id;
|
||||
}
|
||||
reply_info_set_ttls(rep, *qstate->env->now);
|
||||
rep->flags |= (BIT_RA | BIT_QR); /* fix flags to be sensible for */
|
||||
rep->flags &= ~(BIT_AA | BIT_CD);/* a reply based on the cache */
|
||||
addrtree_insert(tree, (addrkey_t*)edns->subnet_addr,
|
||||
edns->subnet_source_mask,
|
||||
sq->ecs_server_in.subnet_scope_mask, rep,
|
||||
rep->ttl, *qstate->env->now);
|
||||
if (acquired_lock) {
|
||||
lock_rw_unlock(&lru_entry->lock);
|
||||
} else {
|
||||
slabhash_insert(subnet_msg_cache, h, lru_entry, lru_entry->data,
|
||||
NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/** Lookup in cache and reply true iff reply is sent. */
|
||||
static int
|
||||
lookup_and_reply(struct module_qstate *qstate, int id, struct subnet_qstate *sq)
|
||||
{
|
||||
struct lruhash_entry *e;
|
||||
struct module_env *env = qstate->env;
|
||||
struct subnet_env *sne = (struct subnet_env*)env->modinfo[id];
|
||||
hashvalue_type h = query_info_hash(&qstate->qinfo, qstate->query_flags);
|
||||
struct subnet_msg_cache_data *data;
|
||||
struct ecs_data *ecs = &sq->ecs_client_in;
|
||||
struct addrtree *tree;
|
||||
struct addrnode *node;
|
||||
uint8_t scope;
|
||||
|
||||
memset(&sq->ecs_client_out, 0, sizeof(sq->ecs_client_out));
|
||||
|
||||
if (sq) sq->qinfo_hash = h; /* Might be useful on cache miss */
|
||||
e = slabhash_lookup(sne->subnet_msg_cache, h, &qstate->qinfo, 1);
|
||||
if (!e) return 0; /* qinfo not in cache */
|
||||
data = e->data;
|
||||
tree = (ecs->subnet_addr_fam == EDNSSUBNET_ADDRFAM_IP4)?
|
||||
data->tree4 : data->tree6;
|
||||
if (!tree) { /* qinfo in cache but not for this family */
|
||||
lock_rw_unlock(&e->lock);
|
||||
return 0;
|
||||
}
|
||||
node = addrtree_find(tree, (addrkey_t*)ecs->subnet_addr,
|
||||
ecs->subnet_source_mask, *env->now);
|
||||
if (!node) { /* plain old cache miss */
|
||||
lock_rw_unlock(&e->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
qstate->return_msg = tomsg(NULL, &qstate->qinfo,
|
||||
(struct reply_info *)node->elem, qstate->region, *env->now,
|
||||
env->scratch);
|
||||
scope = (uint8_t)node->scope;
|
||||
lock_rw_unlock(&e->lock);
|
||||
|
||||
if (!qstate->return_msg) { /* Failed allocation or expired TTL */
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (sq->subnet_downstream) { /* relay to interested client */
|
||||
sq->ecs_client_out.subnet_scope_mask = scope;
|
||||
sq->ecs_client_out.subnet_addr_fam = ecs->subnet_addr_fam;
|
||||
sq->ecs_client_out.subnet_source_mask = ecs->subnet_source_mask;
|
||||
memcpy(&sq->ecs_client_out.subnet_addr, &ecs->subnet_addr,
|
||||
INET6_SIZE);
|
||||
sq->ecs_client_out.subnet_validdata = 1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test first bits of addresses for equality. Caller is responsible
|
||||
* for making sure that both a and b are at least net/8 octets long.
|
||||
* @param a: first address.
|
||||
* @param a: seconds address.
|
||||
* @param net: Number of bits to test.
|
||||
* @return: 1 if equal, 0 otherwise.
|
||||
*/
|
||||
static int
|
||||
common_prefix(uint8_t *a, uint8_t *b, uint8_t net)
|
||||
{
|
||||
size_t n = (size_t)net / 8;
|
||||
return !memcmp(a, b, n) && ((net % 8) == 0 || a[n] == b[n]);
|
||||
}
|
||||
|
||||
static enum module_ext_state
|
||||
eval_response(struct module_qstate *qstate, int id, struct subnet_qstate *sq)
|
||||
{
|
||||
struct subnet_env *sne = qstate->env->modinfo[id];
|
||||
|
||||
struct ecs_data *c_in = &sq->ecs_client_in; /* rcvd from client */
|
||||
struct ecs_data *c_out = &sq->ecs_client_out;/* will send to client */
|
||||
struct ecs_data *s_in = &sq->ecs_server_in; /* rcvd from auth */
|
||||
struct ecs_data *s_out = &sq->ecs_server_out;/* sent to auth */
|
||||
|
||||
memset(c_out, 0, sizeof(*c_out));
|
||||
|
||||
if (!qstate->return_msg) return module_error;
|
||||
|
||||
/* We have not asked for subnet data */
|
||||
if (!sq->subnet_sent) {
|
||||
if (s_in->subnet_validdata)
|
||||
verbose(VERB_QUERY, "subnet: received spurious data");
|
||||
if (sq->subnet_downstream) /* Copy back to client */
|
||||
cp_edns_bad_response(c_out, c_in);
|
||||
return module_finished;
|
||||
}
|
||||
|
||||
/* subnet sent but nothing came back */
|
||||
if (!s_in->subnet_validdata) {
|
||||
/* The authority indicated no support for edns subnet. As a
|
||||
* consequence the answer ended up in the regular cache. It
|
||||
* is still usefull to put it in the edns subnet cache for
|
||||
* when a client explicitly asks for subnet specific answer. */
|
||||
verbose(VERB_QUERY, "subnet: Authority indicates no support");
|
||||
lock_rw_wrlock(&sne->biglock);
|
||||
update_cache(qstate, id);
|
||||
lock_rw_unlock(&sne->biglock);
|
||||
if (sq->subnet_downstream)
|
||||
cp_edns_bad_response(c_out, c_in);
|
||||
return module_finished;
|
||||
}
|
||||
|
||||
/* Being here means we have asked for and got a subnet specific
|
||||
* answer. Also, the answer from the authority is not yet cached
|
||||
* anywhere. */
|
||||
|
||||
/* can we accept response? */
|
||||
if(s_out->subnet_addr_fam != s_in->subnet_addr_fam ||
|
||||
s_out->subnet_source_mask != s_in->subnet_source_mask ||
|
||||
!common_prefix(s_out->subnet_addr, s_in->subnet_addr,
|
||||
s_out->subnet_source_mask))
|
||||
{
|
||||
/* we can not accept, restart query without option */
|
||||
verbose(VERB_QUERY, "subnet: forged data");
|
||||
s_out->subnet_validdata = 0;
|
||||
(void)edns_opt_list_remove(&qstate->edns_opts_back_out,
|
||||
qstate->env->cfg->client_subnet_opcode);
|
||||
sq->subnet_sent = 0;
|
||||
return module_restart_next;
|
||||
}
|
||||
|
||||
lock_rw_wrlock(&sne->biglock);
|
||||
update_cache(qstate, id);
|
||||
lock_rw_unlock(&sne->biglock);
|
||||
|
||||
if (sq->subnet_downstream) {
|
||||
/* Client wants to see the answer, echo option back
|
||||
* and adjust the scope. */
|
||||
c_out->subnet_addr_fam = c_in->subnet_addr_fam;
|
||||
c_out->subnet_source_mask = c_in->subnet_source_mask;
|
||||
memcpy(&c_out->subnet_addr, &c_in->subnet_addr, INET6_SIZE);
|
||||
c_out->subnet_scope_mask = s_in->subnet_scope_mask;
|
||||
c_out->subnet_validdata = 1;
|
||||
}
|
||||
return module_finished;
|
||||
}
|
||||
|
||||
/** Parse EDNS opt data containing ECS */
|
||||
static int
|
||||
parse_subnet_option(struct edns_option* ecs_option, struct ecs_data* ecs)
|
||||
{
|
||||
memset(ecs, 0, sizeof(*ecs));
|
||||
if (ecs_option->opt_len < 4)
|
||||
return 0;
|
||||
|
||||
ecs->subnet_addr_fam = sldns_read_uint16(ecs_option->opt_data);
|
||||
ecs->subnet_source_mask = ecs_option->opt_data[2];
|
||||
ecs->subnet_scope_mask = ecs_option->opt_data[3];
|
||||
/* remaing bytes indicate address */
|
||||
|
||||
/* validate input*/
|
||||
/* option length matches calculated length? */
|
||||
if (ecs_option->opt_len != (size_t)((ecs->subnet_source_mask+7)/8 + 4))
|
||||
return 0;
|
||||
if (ecs_option->opt_len - 4 > INET6_SIZE || ecs_option->opt_len == 0)
|
||||
return 0;
|
||||
if (ecs->subnet_addr_fam == EDNSSUBNET_ADDRFAM_IP4) {
|
||||
if (ecs->subnet_source_mask > 32 || ecs->subnet_scope_mask > 32)
|
||||
return 0;
|
||||
} else if (ecs->subnet_addr_fam == EDNSSUBNET_ADDRFAM_IP6) {
|
||||
if (ecs->subnet_source_mask > 128 ||
|
||||
ecs->subnet_scope_mask > 128)
|
||||
return 0;
|
||||
} else
|
||||
return 0;
|
||||
|
||||
/* valid ECS data, write to ecs_data */
|
||||
if (copy_clear(ecs->subnet_addr, INET6_SIZE, ecs_option->opt_data + 4,
|
||||
ecs_option->opt_len - 4, ecs->subnet_source_mask))
|
||||
return 0;
|
||||
ecs->subnet_validdata = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void
|
||||
subnet_option_from_ss(struct sockaddr_storage *ss, struct ecs_data* ecs,
|
||||
struct config_file* cfg)
|
||||
{
|
||||
void* sinaddr;
|
||||
|
||||
/* Construct subnet option from original query */
|
||||
if(((struct sockaddr_in*)ss)->sin_family == AF_INET) {
|
||||
ecs->subnet_source_mask = cfg->max_client_subnet_ipv4;
|
||||
ecs->subnet_addr_fam = EDNSSUBNET_ADDRFAM_IP4;
|
||||
sinaddr = &((struct sockaddr_in*)ss)->sin_addr;
|
||||
if (!copy_clear( ecs->subnet_addr, INET6_SIZE,
|
||||
(uint8_t *)sinaddr, INET_SIZE,
|
||||
ecs->subnet_source_mask)) {
|
||||
ecs->subnet_validdata = 1;
|
||||
}
|
||||
}
|
||||
#ifdef INET6
|
||||
else {
|
||||
ecs->subnet_source_mask = cfg->max_client_subnet_ipv6;
|
||||
ecs->subnet_addr_fam = EDNSSUBNET_ADDRFAM_IP6;
|
||||
sinaddr = &((struct sockaddr_in6*)ss)->sin6_addr;
|
||||
if (!copy_clear( ecs->subnet_addr, INET6_SIZE,
|
||||
(uint8_t *)sinaddr, INET6_SIZE,
|
||||
ecs->subnet_source_mask)) {
|
||||
ecs->subnet_validdata = 1;
|
||||
}
|
||||
}
|
||||
#else
|
||||
/* We don't know how to handle ip6, just pass */
|
||||
#endif /* INET6 */
|
||||
}
|
||||
|
||||
int
|
||||
ecs_query_response(struct module_qstate* qstate, struct dns_msg* response,
|
||||
int id, void* ATTR_UNUSED(cbargs))
|
||||
{
|
||||
struct subnet_qstate *sq;
|
||||
|
||||
if(!response || !(sq=(struct subnet_qstate*)qstate->minfo[id]))
|
||||
return 1;
|
||||
|
||||
if(sq->subnet_sent &&
|
||||
FLAGS_GET_RCODE(response->rep->flags) == LDNS_RCODE_REFUSED) {
|
||||
/* REFUSED reponse to ECS query, remove ECS option. */
|
||||
edns_opt_list_remove(&qstate->edns_opts_back_out,
|
||||
qstate->env->cfg->client_subnet_opcode);
|
||||
sq->subnet_sent = 0;
|
||||
memset(&sq->ecs_server_out, 0, sizeof(sq->ecs_server_out));
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
ecs_edns_back_parsed(struct module_qstate* qstate, int id,
|
||||
void* ATTR_UNUSED(cbargs))
|
||||
{
|
||||
struct subnet_qstate *sq;
|
||||
struct edns_option* ecs_opt;
|
||||
|
||||
if(!(sq=(struct subnet_qstate*)qstate->minfo[id]))
|
||||
return 1;
|
||||
if((ecs_opt = edns_opt_list_find(
|
||||
qstate->edns_opts_back_in,
|
||||
qstate->env->cfg->client_subnet_opcode))) {
|
||||
if(parse_subnet_option(ecs_opt, &sq->ecs_server_in) &&
|
||||
sq->subnet_sent &&
|
||||
sq->ecs_server_in.subnet_validdata)
|
||||
/* Only skip global cache store if we sent an ECS option
|
||||
* and received one back. Answers from non-whitelisted
|
||||
* servers will end up in global cache. Ansers for
|
||||
* queries with 0 source will not (unless nameserver
|
||||
* does not support ECS). */
|
||||
qstate->no_cache_store = 1;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
subnetmod_operate(struct module_qstate *qstate, enum module_ev event,
|
||||
int id, struct outbound_entry* outbound)
|
||||
{
|
||||
struct subnet_env *sne = qstate->env->modinfo[id];
|
||||
struct subnet_qstate *sq = (struct subnet_qstate*)qstate->minfo[id];
|
||||
|
||||
verbose(VERB_QUERY, "subnet[module %d] operate: extstate:%s "
|
||||
"event:%s", id, strextstate(qstate->ext_state[id]),
|
||||
strmodulevent(event));
|
||||
log_query_info(VERB_QUERY, "subnet operate: query", &qstate->qinfo);
|
||||
|
||||
if((event == module_event_new || event == module_event_pass) &&
|
||||
sq == NULL) {
|
||||
struct edns_option* ecs_opt;
|
||||
if(!subnet_new_qstate(qstate, id)) {
|
||||
qstate->return_msg = NULL;
|
||||
qstate->ext_state[id] = module_finished;
|
||||
return;
|
||||
}
|
||||
|
||||
sq = (struct subnet_qstate*)qstate->minfo[id];
|
||||
|
||||
if((ecs_opt = edns_opt_list_find(
|
||||
qstate->edns_opts_front_in,
|
||||
qstate->env->cfg->client_subnet_opcode))) {
|
||||
if(!parse_subnet_option(ecs_opt, &sq->ecs_client_in)) {
|
||||
/* Wrongly formatted ECS option. RFC mandates to
|
||||
* return FORMERROR. */
|
||||
qstate->return_rcode = LDNS_RCODE_FORMERR;
|
||||
qstate->ext_state[id] = module_finished;
|
||||
return;
|
||||
}
|
||||
sq->subnet_downstream = 1;
|
||||
}
|
||||
else if(qstate->mesh_info->reply_list) {
|
||||
subnet_option_from_ss(
|
||||
&qstate->mesh_info->reply_list->query_reply.addr,
|
||||
&sq->ecs_client_in, qstate->env->cfg);
|
||||
}
|
||||
|
||||
if(sq->ecs_client_in.subnet_validdata == 0) {
|
||||
/* No clients are interested in result or we could not
|
||||
* parse it, we don't do client subnet */
|
||||
sq->ecs_server_out.subnet_validdata = 0;
|
||||
verbose(VERB_ALGO, "subnet: pass to next module");
|
||||
qstate->ext_state[id] = module_wait_module;
|
||||
return;
|
||||
}
|
||||
|
||||
lock_rw_wrlock(&sne->biglock);
|
||||
if (lookup_and_reply(qstate, id, sq)) {
|
||||
lock_rw_unlock(&sne->biglock);
|
||||
verbose(VERB_QUERY, "subnet: answered from cache");
|
||||
qstate->ext_state[id] = module_finished;
|
||||
|
||||
ecs_opt_list_append(&sq->ecs_client_out,
|
||||
&qstate->edns_opts_front_out, qstate);
|
||||
return;
|
||||
}
|
||||
lock_rw_unlock(&sne->biglock);
|
||||
|
||||
sq->ecs_server_out.subnet_addr_fam =
|
||||
sq->ecs_client_in.subnet_addr_fam;
|
||||
sq->ecs_server_out.subnet_source_mask =
|
||||
sq->ecs_client_in.subnet_source_mask;
|
||||
/* Limit source prefix to configured maximum */
|
||||
if(sq->ecs_server_out.subnet_addr_fam == EDNSSUBNET_ADDRFAM_IP4
|
||||
&& sq->ecs_server_out.subnet_source_mask >
|
||||
qstate->env->cfg->max_client_subnet_ipv4)
|
||||
sq->ecs_server_out.subnet_source_mask =
|
||||
qstate->env->cfg->max_client_subnet_ipv4;
|
||||
else if(sq->ecs_server_out.subnet_addr_fam == EDNSSUBNET_ADDRFAM_IP6
|
||||
&& sq->ecs_server_out.subnet_source_mask >
|
||||
qstate->env->cfg->max_client_subnet_ipv6)
|
||||
sq->ecs_server_out.subnet_source_mask =
|
||||
qstate->env->cfg->max_client_subnet_ipv6;
|
||||
/* Safe to copy completely, even if the source is limited by the
|
||||
* configuration. ecs_opt_list_append() will limit the address.
|
||||
* */
|
||||
memcpy(&sq->ecs_server_out.subnet_addr,
|
||||
sq->ecs_client_in.subnet_addr, INET6_SIZE);
|
||||
sq->ecs_server_out.subnet_scope_mask = 0;
|
||||
sq->ecs_server_out.subnet_validdata = 1;
|
||||
if(sq->ecs_server_out.subnet_source_mask != 0 &&
|
||||
sq->subnet_downstream)
|
||||
/* ECS specific data required, do not look at the global
|
||||
* cache in other modules. */
|
||||
qstate->no_cache_lookup = 1;
|
||||
|
||||
/* pass request to next module */
|
||||
verbose(VERB_ALGO,
|
||||
"subnet: not found in cache. pass to next module");
|
||||
qstate->ext_state[id] = module_wait_module;
|
||||
return;
|
||||
}
|
||||
/* Query handed back by next module, we have a 'final' answer */
|
||||
if(sq && event == module_event_moddone) {
|
||||
qstate->ext_state[id] = eval_response(qstate, id, sq);
|
||||
if(qstate->ext_state[id] == module_finished) {
|
||||
ecs_opt_list_append(&sq->ecs_client_out,
|
||||
&qstate->edns_opts_front_out, qstate);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if(sq && outbound) {
|
||||
return;
|
||||
}
|
||||
/* We are being revisited */
|
||||
if(event == module_event_pass || event == module_event_new) {
|
||||
/* Just pass it on, we already did the work */
|
||||
verbose(VERB_ALGO, "subnet: pass to next module");
|
||||
qstate->ext_state[id] = module_wait_module;
|
||||
return;
|
||||
}
|
||||
if(!sq && (event == module_event_moddone)) {
|
||||
/* during priming, module done but we never started */
|
||||
qstate->ext_state[id] = module_finished;
|
||||
return;
|
||||
}
|
||||
log_err("subnet: bad event %s", strmodulevent(event));
|
||||
qstate->ext_state[id] = module_error;
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
subnetmod_clear(struct module_qstate *ATTR_UNUSED(qstate),
|
||||
int ATTR_UNUSED(id))
|
||||
{
|
||||
/* qstate has no data outside region */
|
||||
}
|
||||
|
||||
void
|
||||
subnetmod_inform_super(struct module_qstate *ATTR_UNUSED(qstate),
|
||||
int ATTR_UNUSED(id), struct module_qstate *ATTR_UNUSED(super))
|
||||
{
|
||||
/* Not used */
|
||||
}
|
||||
|
||||
size_t
|
||||
subnetmod_get_mem(struct module_env *env, int id)
|
||||
{
|
||||
struct subnet_env *sn_env = env->modinfo[id];
|
||||
if (!sn_env) return 0;
|
||||
return sizeof(*sn_env) +
|
||||
slabhash_get_mem(sn_env->subnet_msg_cache) +
|
||||
upstream_get_mem(sn_env->edns_subnet_upstreams);
|
||||
}
|
||||
|
||||
/**
|
||||
* The module function block
|
||||
*/
|
||||
static struct module_func_block subnetmod_block = {
|
||||
"subnet", &subnetmod_init, &subnetmod_deinit, &subnetmod_operate,
|
||||
&subnetmod_inform_super, &subnetmod_clear, &subnetmod_get_mem
|
||||
};
|
||||
|
||||
struct module_func_block*
|
||||
subnetmod_get_funcblock(void)
|
||||
{
|
||||
return &subnetmod_block;
|
||||
}
|
||||
|
||||
/** Wrappers for static functions to unit test */
|
||||
size_t
|
||||
unittest_wrapper_subnetmod_sizefunc(void *elemptr)
|
||||
{
|
||||
return sizefunc(elemptr);
|
||||
}
|
||||
|
||||
#endif /* CLIENT_SUBNET */
|
||||
130
edns-subnet/subnetmod.h
Normal file
130
edns-subnet/subnetmod.h
Normal file
|
|
@ -0,0 +1,130 @@
|
|||
/*
|
||||
* edns-subnet/subnetmod.h - edns subnet module. Must be called before validator
|
||||
* and iterator.
|
||||
*
|
||||
* Copyright (c) 2013, NLnet Labs. All rights reserved.
|
||||
*
|
||||
* This software is open source.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* Neither the name of the NLNET LABS nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
/**
|
||||
* \file
|
||||
* subnet module for unbound.
|
||||
*/
|
||||
|
||||
#ifndef SUBNETMOD_H
|
||||
#define SUBNETMOD_H
|
||||
#include "util/module.h"
|
||||
#include "services/outbound_list.h"
|
||||
#include "util/alloc.h"
|
||||
#include "util/net_help.h"
|
||||
#include "util/storage/slabhash.h"
|
||||
#include "edns-subnet/addrtree.h"
|
||||
#include "edns-subnet/edns-subnet.h"
|
||||
|
||||
/**
|
||||
* Global state for the subnet module.
|
||||
*/
|
||||
struct subnet_env {
|
||||
/** shared message cache
|
||||
* key: struct query_info*
|
||||
* data: struct subnet_msg_cache_data* */
|
||||
struct slabhash* subnet_msg_cache;
|
||||
/** access control, which upstream servers we send client address */
|
||||
struct ednssubnet_upstream* edns_subnet_upstreams;
|
||||
/** allocation service */
|
||||
struct alloc_cache alloc;
|
||||
lock_rw_type biglock;
|
||||
};
|
||||
|
||||
struct subnet_msg_cache_data {
|
||||
struct addrtree* tree4;
|
||||
struct addrtree* tree6;
|
||||
};
|
||||
|
||||
struct subnet_qstate {
|
||||
/** We need the hash for both cache lookup and insert */
|
||||
hashvalue_type qinfo_hash;
|
||||
/** ecs_data for client communication */
|
||||
struct ecs_data ecs_client_in;
|
||||
struct ecs_data ecs_client_out;
|
||||
/** ecss data for server communication */
|
||||
struct ecs_data ecs_server_in;
|
||||
struct ecs_data ecs_server_out;
|
||||
int subnet_downstream;
|
||||
int subnet_sent;
|
||||
};
|
||||
|
||||
void subnet_data_delete(void* d, void* ATTR_UNUSED(arg));
|
||||
size_t msg_cache_sizefunc(void* k, void* d);
|
||||
|
||||
/**
|
||||
* Get the module function block.
|
||||
* @return: function block with function pointers to module methods.
|
||||
*/
|
||||
struct module_func_block* subnetmod_get_funcblock(void);
|
||||
|
||||
/** subnet module init */
|
||||
int subnetmod_init(struct module_env* env, int id);
|
||||
|
||||
/** subnet module deinit */
|
||||
void subnetmod_deinit(struct module_env* env, int id);
|
||||
|
||||
/** subnet module operate on a query */
|
||||
void subnetmod_operate(struct module_qstate* qstate, enum module_ev event,
|
||||
int id, struct outbound_entry* outbound);
|
||||
|
||||
/** subnet module */
|
||||
void subnetmod_inform_super(struct module_qstate* qstate, int id,
|
||||
struct module_qstate* super);
|
||||
|
||||
/** subnet module cleanup query state */
|
||||
void subnetmod_clear(struct module_qstate* qstate, int id);
|
||||
|
||||
/** subnet module alloc size routine */
|
||||
size_t subnetmod_get_mem(struct module_env* env, int id);
|
||||
|
||||
/** Wrappers for static functions to unit test */
|
||||
size_t unittest_wrapper_subnetmod_sizefunc(void *elemptr);
|
||||
|
||||
/** Whitelist check, called just before query is sent upstream. */
|
||||
int ecs_whitelist_check(struct query_info* qinfo, uint16_t flags,
|
||||
struct module_qstate* qstate, struct sockaddr_storage* addr,
|
||||
socklen_t addrlen, uint8_t* zone, size_t zonelen,
|
||||
struct regional* region, int id, void* cbargs);
|
||||
|
||||
/** Check whether reponse from server contains ECS record, if so, skip cache
|
||||
* store. Called just after parsing EDNS data from server. */
|
||||
int ecs_edns_back_parsed(struct module_qstate* qstate, int id, void* cbargs);
|
||||
|
||||
/** Remove ECS record from back_out when query resulted in REFUSED response. */
|
||||
int ecs_query_response(struct module_qstate* qstate, struct dns_msg* response,
|
||||
int id, void* cbargs);
|
||||
|
||||
#endif /* SUBNETMOD_H */
|
||||
|
|
@ -372,6 +372,29 @@ iter_prepend(struct iter_qstate* iq, struct dns_msg* msg,
|
|||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find rrset in ANSWER prepend list.
|
||||
* to avoid duplicate DNAMEs when a DNAME is traversed twice.
|
||||
* @param iq: iterator query state.
|
||||
* @param rrset: rrset to add.
|
||||
* @return false if not found
|
||||
*/
|
||||
static int
|
||||
iter_find_rrset_in_prepend_answer(struct iter_qstate* iq,
|
||||
struct ub_packed_rrset_key* rrset)
|
||||
{
|
||||
struct iter_prep_list* p = iq->an_prepend_list;
|
||||
while(p) {
|
||||
if(ub_rrset_compare(p->rrset, rrset) == 0 &&
|
||||
rrsetdata_equal((struct packed_rrset_data*)p->rrset
|
||||
->entry.data, (struct packed_rrset_data*)rrset
|
||||
->entry.data))
|
||||
return 1;
|
||||
p = p->next;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add rrset to ANSWER prepend list
|
||||
* @param qstate: query state.
|
||||
|
|
@ -454,14 +477,16 @@ handle_cname_response(struct module_qstate* qstate, struct iter_qstate* iq,
|
|||
* by this DNAME following, so we don't process the DNAME
|
||||
* directly. */
|
||||
if(ntohs(r->rk.type) == LDNS_RR_TYPE_DNAME &&
|
||||
dname_strict_subdomain_c(*mname, r->rk.dname)) {
|
||||
dname_strict_subdomain_c(*mname, r->rk.dname) &&
|
||||
!iter_find_rrset_in_prepend_answer(iq, r)) {
|
||||
if(!iter_add_prepend_answer(qstate, iq, r))
|
||||
return 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
if(ntohs(r->rk.type) == LDNS_RR_TYPE_CNAME &&
|
||||
query_dname_compare(*mname, r->rk.dname) == 0) {
|
||||
query_dname_compare(*mname, r->rk.dname) == 0 &&
|
||||
!iter_find_rrset_in_prepend_answer(iq, r)) {
|
||||
/* Add this relevant CNAME rrset to the prepend list.*/
|
||||
if(!iter_add_prepend_answer(qstate, iq, r))
|
||||
return 0;
|
||||
|
|
@ -1326,7 +1351,7 @@ processInitRequest3(struct module_qstate* qstate, struct iter_qstate* iq,
|
|||
|
||||
/* If the RD flag wasn't set, then we just finish with the
|
||||
* cached referral as the response. */
|
||||
if(!(qstate->query_flags & BIT_RD)) {
|
||||
if(!(qstate->query_flags & BIT_RD) && iq->deleg_msg) {
|
||||
iq->response = iq->deleg_msg;
|
||||
if(verbosity >= VERB_ALGO && iq->response)
|
||||
log_dns_msg("no RD requested, using delegation msg",
|
||||
|
|
@ -2169,6 +2194,10 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
|
|||
int dnsseclame = 0;
|
||||
enum response_type type;
|
||||
iq->num_current_queries--;
|
||||
|
||||
if(!inplace_cb_query_response_call(qstate->env, qstate, iq->response))
|
||||
log_err("unable to call query_response callback");
|
||||
|
||||
if(iq->response == NULL) {
|
||||
/* Don't increment qname when QNAME minimisation is enabled */
|
||||
if(qstate->env->cfg->qname_minimisation)
|
||||
|
|
@ -2233,6 +2262,22 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
|
|||
} else
|
||||
iter_scrub_ds(iq->response, ns, iq->dp->name);
|
||||
} else iter_scrub_ds(iq->response, NULL, NULL);
|
||||
if(type == RESPONSE_TYPE_THROWAWAY &&
|
||||
FLAGS_GET_RCODE(iq->response->rep->flags) == LDNS_RCODE_YXDOMAIN) {
|
||||
/* YXDOMAIN is a permanent error, no need to retry */
|
||||
type = RESPONSE_TYPE_ANSWER;
|
||||
}
|
||||
if(type == RESPONSE_TYPE_CNAME && iq->response->rep->an_numrrsets >= 1
|
||||
&& ntohs(iq->response->rep->rrsets[0]->rk.type) == LDNS_RR_TYPE_DNAME) {
|
||||
uint8_t* sname = NULL;
|
||||
size_t snamelen = 0;
|
||||
get_cname_target(iq->response->rep->rrsets[0], &sname,
|
||||
&snamelen);
|
||||
if(snamelen && dname_subdomain_c(sname, iq->response->rep->rrsets[0]->rk.dname)) {
|
||||
/* DNAME to a subdomain loop; do not recurse */
|
||||
type = RESPONSE_TYPE_ANSWER;
|
||||
}
|
||||
}
|
||||
|
||||
/* handle each of the type cases */
|
||||
if(type == RESPONSE_TYPE_ANSWER) {
|
||||
|
|
@ -3161,6 +3206,10 @@ process_response(struct module_qstate* qstate, struct iter_qstate* iq,
|
|||
/* like packet got dropped */
|
||||
goto handle_it;
|
||||
}
|
||||
if(!inplace_cb_edns_back_parsed_call(qstate->env, qstate)) {
|
||||
log_err("unable to call edns_back_parsed callback");
|
||||
goto handle_it;
|
||||
}
|
||||
}
|
||||
|
||||
/* remove CD-bit, we asked for in case we handle validation ourself */
|
||||
|
|
|
|||
|
|
@ -310,7 +310,6 @@ ub_ctx_delete(struct ub_ctx* ctx)
|
|||
infra_delete(ctx->env->infra_cache);
|
||||
config_delete(ctx->env->cfg);
|
||||
edns_known_options_delete(ctx->env);
|
||||
inplace_cb_lists_delete(ctx->env);
|
||||
free(ctx->env);
|
||||
}
|
||||
ub_randfree(ctx->seed_rnd);
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ We can register such function as:
|
|||
|
||||
.. code-block:: python
|
||||
|
||||
if not register_inplace_cb_reply(inplace_reply_callback, env):
|
||||
if not register_inplace_cb_reply(inplace_reply_callback, env, id):
|
||||
log_info("python: Could not register inplace callback function.")
|
||||
|
||||
|
||||
|
|
@ -99,7 +99,7 @@ We can register such function as:
|
|||
|
||||
.. code-block:: python
|
||||
|
||||
if not register_inplace_cb_reply_cache(inplace_cache_callback, env):
|
||||
if not register_inplace_cb_reply_cache(inplace_cache_callback, env, id):
|
||||
log_info("python: Could not register inplace callback function.")
|
||||
|
||||
|
||||
|
|
@ -135,7 +135,7 @@ We can register such function as:
|
|||
|
||||
.. code-block:: python
|
||||
|
||||
if not register_inplace_cb_reply_local(inplace_local_callback, env):
|
||||
if not register_inplace_cb_reply_local(inplace_local_callback, env, id):
|
||||
log_info("python: Could not register inplace callback function.")
|
||||
|
||||
|
||||
|
|
@ -172,7 +172,7 @@ We can register such function as:
|
|||
|
||||
.. code-block:: python
|
||||
|
||||
if not register_inplace_cb_reply_servfail(inplace_servfail_callback, env):
|
||||
if not register_inplace_cb_reply_servfail(inplace_servfail_callback, env, id):
|
||||
log_info("python: Could not register inplace callback function.")
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -46,22 +46,22 @@
|
|||
# (unbound needs to be validating for this example to work)
|
||||
|
||||
# Useful functions:
|
||||
# register_inplace_cb_reply(inplace_reply_callback, env):
|
||||
# register_inplace_cb_reply(inplace_reply_callback, env, id):
|
||||
# Register the reply_callback function as an inplace callback function
|
||||
# when answering with a resolved query.
|
||||
# Return True on success, False on failure.
|
||||
#
|
||||
# register_inplace_cb_reply_cache(inplace_reply_cache_callback, env):
|
||||
# register_inplace_cb_reply_cache(inplace_reply_cache_callback, env, id):
|
||||
# Register the reply_cache_callback function as an inplace callback
|
||||
# function when answering from cache.
|
||||
# Return True on success, False on failure.
|
||||
#
|
||||
# register_inplace_cb_reply_local(inplace_reply_local_callback, env):
|
||||
# register_inplace_cb_reply_local(inplace_reply_local_callback, env, id):
|
||||
# Register the reply_local_callback function as an inplace callback
|
||||
# function when answering from local data or chaos reply.
|
||||
# Return True on success, False on failure.
|
||||
#
|
||||
# register_inplace_cb_reply_servfail(inplace_reply_servfail_callback, env):
|
||||
# register_inplace_cb_reply_servfail(inplace_reply_servfail_callback, env, id):
|
||||
# Register the reply_servfail_callback function as an inplace callback
|
||||
# function when answering with servfail.
|
||||
# Return True on success, False on failure.
|
||||
|
|
@ -193,22 +193,22 @@ def init_standard(id, env):
|
|||
|
||||
# Register the inplace_reply_callback function as an inplace callback
|
||||
# function when answering a resolved query.
|
||||
if not register_inplace_cb_reply(inplace_reply_callback, env):
|
||||
if not register_inplace_cb_reply(inplace_reply_callback, env, id):
|
||||
return False
|
||||
|
||||
# Register the inplace_cache_callback function as an inplace callback
|
||||
# function when answering from cache.
|
||||
if not register_inplace_cb_reply_cache(inplace_cache_callback, env):
|
||||
if not register_inplace_cb_reply_cache(inplace_cache_callback, env, id):
|
||||
return False
|
||||
|
||||
# Register the inplace_local_callback function as an inplace callback
|
||||
# function when answering from local data.
|
||||
if not register_inplace_cb_reply_local(inplace_local_callback, env):
|
||||
if not register_inplace_cb_reply_local(inplace_local_callback, env, id):
|
||||
return False
|
||||
|
||||
# Register the inplace_servfail_callback function as an inplace callback
|
||||
# function when answering with SERVFAIL.
|
||||
if not register_inplace_cb_reply_servfail(inplace_servfail_callback, env):
|
||||
if not register_inplace_cb_reply_servfail(inplace_servfail_callback, env, id):
|
||||
return False
|
||||
|
||||
return True
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
%module unboundmodule
|
||||
%{
|
||||
/**
|
||||
* \file
|
||||
* \file
|
||||
* This is the interface between the unbound server and a python module
|
||||
* called to perform operations on queries.
|
||||
*/
|
||||
|
|
@ -58,7 +58,7 @@
|
|||
}
|
||||
%}
|
||||
|
||||
/* ************************************************************************************ *
|
||||
/* ************************************************************************************ *
|
||||
Structure query_info
|
||||
* ************************************************************************************ */
|
||||
/* Query info */
|
||||
|
|
@ -76,24 +76,24 @@ struct query_info {
|
|||
};
|
||||
|
||||
%inline %{
|
||||
enum enum_rr_class {
|
||||
enum enum_rr_class {
|
||||
RR_CLASS_IN = 1,
|
||||
RR_CLASS_CH = 3,
|
||||
RR_CLASS_HS = 4,
|
||||
RR_CLASS_NONE = 254,
|
||||
RR_CLASS_ANY = 255,
|
||||
};
|
||||
|
||||
|
||||
enum enum_rr_type {
|
||||
RR_TYPE_A = 1,
|
||||
RR_TYPE_NS = 2,
|
||||
RR_TYPE_MD = 3,
|
||||
RR_TYPE_MF = 4,
|
||||
RR_TYPE_CNAME = 5,
|
||||
RR_TYPE_SOA = 6,
|
||||
RR_TYPE_MB = 7,
|
||||
RR_TYPE_MG = 8,
|
||||
RR_TYPE_MR = 9,
|
||||
RR_TYPE_A = 1,
|
||||
RR_TYPE_NS = 2,
|
||||
RR_TYPE_MD = 3,
|
||||
RR_TYPE_MF = 4,
|
||||
RR_TYPE_CNAME = 5,
|
||||
RR_TYPE_SOA = 6,
|
||||
RR_TYPE_MB = 7,
|
||||
RR_TYPE_MG = 8,
|
||||
RR_TYPE_MR = 9,
|
||||
RR_TYPE_NULL = 10,
|
||||
RR_TYPE_WKS = 11,
|
||||
RR_TYPE_PTR = 12,
|
||||
|
|
@ -131,7 +131,7 @@ struct query_info {
|
|||
RR_TYPE_SSHFP = 44,
|
||||
RR_TYPE_IPSECKEY = 45,
|
||||
RR_TYPE_RRSIG = 46,
|
||||
RR_TYPE_NSEC = 47,
|
||||
RR_TYPE_NSEC = 47,
|
||||
RR_TYPE_DNSKEY = 48,
|
||||
RR_TYPE_DHCID = 49,
|
||||
RR_TYPE_NSEC3 = 50,
|
||||
|
|
@ -151,7 +151,7 @@ struct query_info {
|
|||
|
||||
PyObject* _get_qname(struct query_info* q) {
|
||||
return PyBytes_FromStringAndSize((char*)q->qname, q->qname_len);
|
||||
}
|
||||
}
|
||||
|
||||
PyObject* _get_qname_components(struct query_info* q) {
|
||||
return GetNameAsLabelList((const char*)q->qname, q->qname_len);
|
||||
|
|
@ -179,7 +179,7 @@ struct query_info {
|
|||
|
||||
__swig_getmethods__["qname"] = _unboundmodule._get_qname
|
||||
if _newclass:qname = _swig_property(_unboundmodule._get_qname)
|
||||
|
||||
|
||||
__swig_getmethods__["qname_list"] = _unboundmodule._get_qname_components
|
||||
if _newclass:qname_list = _swig_property(_unboundmodule._get_qname_components)
|
||||
|
||||
|
|
@ -189,7 +189,7 @@ struct query_info {
|
|||
%}
|
||||
}
|
||||
|
||||
/* ************************************************************************************ *
|
||||
/* ************************************************************************************ *
|
||||
Structure packed_rrset_key
|
||||
* ************************************************************************************ */
|
||||
%ignore packed_rrset_key::dname;
|
||||
|
|
@ -200,7 +200,7 @@ struct packed_rrset_key {
|
|||
%immutable;
|
||||
char* dname;
|
||||
size_t dname_len;
|
||||
uint32_t flags;
|
||||
uint32_t flags;
|
||||
uint16_t type; /* rrset type in network format */
|
||||
uint16_t rrset_class; /* rrset class in network format */
|
||||
%mutable;
|
||||
|
|
@ -216,7 +216,7 @@ uint16_t ntohs(uint16_t netshort);
|
|||
%inline %{
|
||||
PyObject* _get_dname(struct packed_rrset_key* k) {
|
||||
return PyBytes_FromStringAndSize((char*)k->dname, k->dname_len);
|
||||
}
|
||||
}
|
||||
PyObject* _get_dname_components(struct packed_rrset_key* k) {
|
||||
return GetNameAsLabelList((char*)k->dname, k->dname_len);
|
||||
}
|
||||
|
|
@ -244,11 +244,11 @@ uint16_t ntohs(uint16_t netshort);
|
|||
%}
|
||||
}
|
||||
|
||||
#if defined(SWIGWORDSIZE64)
|
||||
#if defined(SWIGWORDSIZE64)
|
||||
typedef long int rrset_id_type;
|
||||
#else
|
||||
#else
|
||||
typedef long long int rrset_id_type;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
struct ub_packed_rrset_key {
|
||||
struct lruhash_entry entry;
|
||||
|
|
@ -279,7 +279,7 @@ struct packed_rrset_data {
|
|||
/* number of rrsigs */
|
||||
size_t rrsig_count;
|
||||
|
||||
enum rrset_trust trust;
|
||||
enum rrset_trust trust;
|
||||
enum sec_status security;
|
||||
|
||||
/* length of every rr's rdata */
|
||||
|
|
@ -309,26 +309,26 @@ struct packed_rrset_data {
|
|||
|
||||
%inline %{
|
||||
PyObject* _get_data_rr_len(struct packed_rrset_data* d, int idx) {
|
||||
if ((d != NULL) && (idx >= 0) &&
|
||||
((size_t)idx < (d->count+d->rrsig_count)))
|
||||
if ((d != NULL) && (idx >= 0) &&
|
||||
((size_t)idx < (d->count+d->rrsig_count)))
|
||||
return PyInt_FromLong(d->rr_len[idx]);
|
||||
return Py_None;
|
||||
}
|
||||
void _set_data_rr_ttl(struct packed_rrset_data* d, int idx, uint32_t ttl)
|
||||
{
|
||||
if ((d != NULL) && (idx >= 0) &&
|
||||
((size_t)idx < (d->count+d->rrsig_count)))
|
||||
if ((d != NULL) && (idx >= 0) &&
|
||||
((size_t)idx < (d->count+d->rrsig_count)))
|
||||
d->rr_ttl[idx] = ttl;
|
||||
}
|
||||
PyObject* _get_data_rr_ttl(struct packed_rrset_data* d, int idx) {
|
||||
if ((d != NULL) && (idx >= 0) &&
|
||||
((size_t)idx < (d->count+d->rrsig_count)))
|
||||
if ((d != NULL) && (idx >= 0) &&
|
||||
((size_t)idx < (d->count+d->rrsig_count)))
|
||||
return PyInt_FromLong(d->rr_ttl[idx]);
|
||||
return Py_None;
|
||||
}
|
||||
PyObject* _get_data_rr_data(struct packed_rrset_data* d, int idx) {
|
||||
if ((d != NULL) && (idx >= 0) &&
|
||||
((size_t)idx < (d->count+d->rrsig_count)))
|
||||
if ((d != NULL) && (idx >= 0) &&
|
||||
((size_t)idx < (d->count+d->rrsig_count)))
|
||||
return PyBytes_FromStringAndSize((char*)d->rr_data[idx],
|
||||
d->rr_len[idx]);
|
||||
return Py_None;
|
||||
|
|
@ -349,7 +349,7 @@ struct packed_rrset_data {
|
|||
%}
|
||||
}
|
||||
|
||||
/* ************************************************************************************ *
|
||||
/* ************************************************************************************ *
|
||||
Structure reply_info
|
||||
* ************************************************************************************ */
|
||||
/* Messages */
|
||||
|
|
@ -426,7 +426,7 @@ struct dns_msg {
|
|||
%}
|
||||
}
|
||||
|
||||
/* ************************************************************************************ *
|
||||
/* ************************************************************************************ *
|
||||
Structure mesh_state
|
||||
* ************************************************************************************ */
|
||||
struct mesh_state {
|
||||
|
|
@ -439,7 +439,7 @@ struct mesh_reply {
|
|||
};
|
||||
|
||||
struct comm_reply {
|
||||
|
||||
|
||||
};
|
||||
|
||||
%inline %{
|
||||
|
|
@ -489,7 +489,7 @@ struct comm_reply {
|
|||
%}
|
||||
}
|
||||
|
||||
/* ************************************************************************************ *
|
||||
/* ************************************************************************************ *
|
||||
Structure edns_option
|
||||
* ************************************************************************************ */
|
||||
/* Rename the members to follow the python convention of marking them as
|
||||
|
|
@ -500,10 +500,10 @@ struct comm_reply {
|
|||
%rename(_opt_len) edns_option::opt_len;
|
||||
%rename(_opt_data) edns_option::opt_data;
|
||||
struct edns_option {
|
||||
struct edns_option* next;
|
||||
uint16_t opt_code;
|
||||
size_t opt_len;
|
||||
uint8_t* opt_data;
|
||||
struct edns_option* next;
|
||||
uint16_t opt_code;
|
||||
size_t opt_len;
|
||||
uint8_t* opt_data;
|
||||
};
|
||||
|
||||
%inline %{
|
||||
|
|
@ -529,7 +529,7 @@ struct edns_option {
|
|||
%}
|
||||
}
|
||||
|
||||
/* ************************************************************************************ *
|
||||
/* ************************************************************************************ *
|
||||
Structure edns_data
|
||||
* ************************************************************************************ */
|
||||
/* This is ignored because we will pass a double pointer of this to Python
|
||||
|
|
@ -537,12 +537,12 @@ struct edns_option {
|
|||
* pointers as None. */
|
||||
%ignore edns_data::opt_list;
|
||||
struct edns_data {
|
||||
int edns_present;
|
||||
uint8_t ext_rcode;
|
||||
uint8_t edns_version;
|
||||
uint16_t bits;
|
||||
uint16_t udp_size;
|
||||
struct edns_option* opt_list;
|
||||
int edns_present;
|
||||
uint8_t ext_rcode;
|
||||
uint8_t edns_version;
|
||||
uint16_t bits;
|
||||
uint16_t udp_size;
|
||||
struct edns_option* opt_list;
|
||||
};
|
||||
%inline %{
|
||||
struct edns_option** _edns_data_opt_list_get(struct edns_data* edns) {
|
||||
|
|
@ -564,49 +564,48 @@ struct edns_data {
|
|||
Structure module_env
|
||||
* ************************************************************************************ */
|
||||
struct module_env {
|
||||
struct config_file* cfg;
|
||||
struct slabhash* msg_cache;
|
||||
struct rrset_cache* rrset_cache;
|
||||
struct infra_cache* infra_cache;
|
||||
struct key_cache* key_cache;
|
||||
struct config_file* cfg;
|
||||
struct slabhash* msg_cache;
|
||||
struct rrset_cache* rrset_cache;
|
||||
struct infra_cache* infra_cache;
|
||||
struct key_cache* key_cache;
|
||||
|
||||
/* --- services --- */
|
||||
struct outbound_entry* (*send_query)(struct query_info* qinfo,
|
||||
uint16_t flags, int dnssec, int want_dnssec, int nocaps,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen,
|
||||
uint8_t* zone, size_t zonelen, int ssl_upstream,
|
||||
struct module_qstate* q);
|
||||
void (*detach_subs)(struct module_qstate* qstate);
|
||||
int (*attach_sub)(struct module_qstate* qstate,
|
||||
struct query_info* qinfo, uint16_t qflags, int prime,
|
||||
int valrec, struct module_qstate** newq);
|
||||
void (*kill_sub)(struct module_qstate* newq);
|
||||
int (*detect_cycle)(struct module_qstate* qstate,
|
||||
struct query_info* qinfo, uint16_t flags, int prime,
|
||||
int valrec);
|
||||
/* --- services --- */
|
||||
struct outbound_entry* (*send_query)(struct query_info* qinfo,
|
||||
uint16_t flags, int dnssec, int want_dnssec, int nocaps,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen,
|
||||
uint8_t* zone, size_t zonelen, int ssl_upstream,
|
||||
struct module_qstate* q);
|
||||
void (*detach_subs)(struct module_qstate* qstate);
|
||||
int (*attach_sub)(struct module_qstate* qstate,
|
||||
struct query_info* qinfo, uint16_t qflags, int prime,
|
||||
int valrec, struct module_qstate** newq);
|
||||
void (*kill_sub)(struct module_qstate* newq);
|
||||
int (*detect_cycle)(struct module_qstate* qstate,
|
||||
struct query_info* qinfo, uint16_t flags, int prime,
|
||||
int valrec);
|
||||
|
||||
struct regional* scratch;
|
||||
struct sldns_buffer* scratch_buffer;
|
||||
struct worker* worker;
|
||||
struct mesh_area* mesh;
|
||||
struct alloc_cache* alloc;
|
||||
struct ub_randstate* rnd;
|
||||
time_t* now;
|
||||
struct timeval* now_tv;
|
||||
int need_to_validate;
|
||||
struct val_anchors* anchors;
|
||||
struct val_neg_cache* neg_cache;
|
||||
struct comm_timer* probe_timer;
|
||||
struct iter_forwards* fwds;
|
||||
struct iter_hints* hints;
|
||||
void* modinfo[MAX_MODULE];
|
||||
struct regional* scratch;
|
||||
struct sldns_buffer* scratch_buffer;
|
||||
struct worker* worker;
|
||||
struct mesh_area* mesh;
|
||||
struct alloc_cache* alloc;
|
||||
struct ub_randstate* rnd;
|
||||
time_t* now;
|
||||
struct timeval* now_tv;
|
||||
int need_to_validate;
|
||||
struct val_anchors* anchors;
|
||||
struct val_neg_cache* neg_cache;
|
||||
struct comm_timer* probe_timer;
|
||||
struct iter_forwards* fwds;
|
||||
struct iter_hints* hints;
|
||||
void* modinfo[MAX_MODULE];
|
||||
|
||||
void* inplace_cb_lists[inplace_cb_types_total];
|
||||
struct edns_known_option* edns_known_options;
|
||||
size_t edns_known_options_num;
|
||||
void* inplace_cb_lists[inplace_cb_types_total];
|
||||
struct edns_known_option* edns_known_options;
|
||||
size_t edns_known_options_num;
|
||||
};
|
||||
|
||||
|
||||
/* ************************************************************************************ *
|
||||
Structure module_qstate
|
||||
* ************************************************************************************ */
|
||||
|
|
@ -710,14 +709,14 @@ struct module_qstate {
|
|||
enum module_ext_state _ext_state_get(struct module_qstate* q, int idx) {
|
||||
if ((q != NULL) && (idx >= 0) && (idx < MAX_MODULE)) {
|
||||
return q->ext_state[idx];
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void _ext_state_set(struct module_qstate* q, int idx, enum module_ext_state state) {
|
||||
if ((q != NULL) && (idx >= 0) && (idx < MAX_MODULE)) {
|
||||
q->ext_state[idx] = state;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int edns_opt_list_is_empty(struct edns_option** opt) {
|
||||
|
|
@ -789,7 +788,7 @@ struct module_qstate {
|
|||
%}
|
||||
}
|
||||
|
||||
/* ************************************************************************************ *
|
||||
/* ************************************************************************************ *
|
||||
Structure config_strlist
|
||||
* ************************************************************************************ */
|
||||
struct config_strlist {
|
||||
|
|
@ -797,7 +796,7 @@ struct config_strlist {
|
|||
char* str;
|
||||
};
|
||||
|
||||
/* ************************************************************************************ *
|
||||
/* ************************************************************************************ *
|
||||
Structure config_str2list
|
||||
* ************************************************************************************ */
|
||||
struct config_str2list {
|
||||
|
|
@ -806,7 +805,7 @@ struct config_str2list {
|
|||
char* str2;
|
||||
};
|
||||
|
||||
/* ************************************************************************************ *
|
||||
/* ************************************************************************************ *
|
||||
Structure config_file
|
||||
* ************************************************************************************ */
|
||||
struct config_file {
|
||||
|
|
@ -873,7 +872,7 @@ struct config_file {
|
|||
struct config_strlist* dlv_anchor_list;
|
||||
int max_ttl;
|
||||
int32_t val_date_override;
|
||||
int bogus_ttl;
|
||||
int bogus_ttl;
|
||||
int val_clean_additional;
|
||||
int val_permissive_mode;
|
||||
char* val_nsec3_key_iterations;
|
||||
|
|
@ -894,7 +893,7 @@ struct config_file {
|
|||
char* python_script;
|
||||
};
|
||||
|
||||
/* ************************************************************************************ *
|
||||
/* ************************************************************************************ *
|
||||
ASN: Adding structures related to forwards_lookup and dns_cache_find_delegation
|
||||
* ************************************************************************************ */
|
||||
struct delegpt_ns {
|
||||
|
|
@ -932,7 +931,7 @@ struct delegpt {
|
|||
%inline %{
|
||||
PyObject* _get_dp_dname(struct delegpt* dp) {
|
||||
return PyBytes_FromStringAndSize((char*)dp->name, dp->namelen);
|
||||
}
|
||||
}
|
||||
PyObject* _get_dp_dname_components(struct delegpt* dp) {
|
||||
return GetNameAsLabelList((char*)dp->name, dp->namelen);
|
||||
}
|
||||
|
|
@ -987,7 +986,7 @@ struct delegpt {
|
|||
%}
|
||||
}
|
||||
|
||||
/* ************************************************************************************ *
|
||||
/* ************************************************************************************ *
|
||||
Enums
|
||||
* ************************************************************************************ */
|
||||
%rename ("MODULE_STATE_INITIAL") "module_state_initial";
|
||||
|
|
@ -1040,6 +1039,26 @@ enum verbosity_value {
|
|||
VERB_ALGO
|
||||
};
|
||||
|
||||
enum inplace_cb_list_type {
|
||||
/* Inplace callbacks for when a resolved reply is ready to be sent to the
|
||||
* front.*/
|
||||
inplace_cb_reply = 0,
|
||||
/* Inplace callbacks for when a reply is given from the cache. */
|
||||
inplace_cb_reply_cache,
|
||||
/* Inplace callbacks for when a reply is given with local data
|
||||
* (or Chaos reply). */
|
||||
inplace_cb_reply_local,
|
||||
/* Inplace callbacks for when the reply is servfail. */
|
||||
inplace_cb_reply_servfail,
|
||||
/* Inplace callbacks for when a query is ready to be sent to the back.*/
|
||||
inplace_cb_query,
|
||||
/* Inplace callback for when a reply is received from the back. */
|
||||
inplace_cb_edns_back_parsed,
|
||||
/* Total number of types. Used for array initialization.
|
||||
* Should always be last. */
|
||||
inplace_cb_types_total
|
||||
};
|
||||
|
||||
%constant uint16_t PKT_QR = 1; /* QueRy - query flag */
|
||||
%constant uint16_t PKT_AA = 2; /* Authoritative Answer - server flag */
|
||||
%constant uint16_t PKT_TC = 4; /* TrunCated - server flag */
|
||||
|
|
@ -1049,17 +1068,17 @@ enum verbosity_value {
|
|||
%constant uint16_t PKT_AD = 64; /* Authenticated Data - server flag */
|
||||
|
||||
%{
|
||||
int checkList(PyObject *l)
|
||||
int checkList(PyObject *l)
|
||||
{
|
||||
PyObject* item;
|
||||
int i;
|
||||
|
||||
if (l == Py_None)
|
||||
if (l == Py_None)
|
||||
return 1;
|
||||
|
||||
if (PyList_Check(l))
|
||||
if (PyList_Check(l))
|
||||
{
|
||||
for (i=0; i < PyList_Size(l); i++)
|
||||
for (i=0; i < PyList_Size(l); i++)
|
||||
{
|
||||
item = PyList_GetItem(l, i);
|
||||
if (!PyBytes_Check(item))
|
||||
|
|
@ -1078,7 +1097,7 @@ int pushRRList(sldns_buffer* qb, PyObject *l, uint32_t default_ttl, int qsec,
|
|||
int i;
|
||||
size_t len;
|
||||
|
||||
for (i=0; i < PyList_Size(l); i++)
|
||||
for (i=0; i < PyList_Size(l); i++)
|
||||
{
|
||||
item = PyList_GetItem(l, i);
|
||||
|
||||
|
|
@ -1102,9 +1121,9 @@ int pushRRList(sldns_buffer* qb, PyObject *l, uint32_t default_ttl, int qsec,
|
|||
return 1;
|
||||
}
|
||||
|
||||
int set_return_msg(struct module_qstate* qstate,
|
||||
int set_return_msg(struct module_qstate* qstate,
|
||||
const char* rr_name, sldns_rr_type rr_type, sldns_rr_class rr_class , uint16_t flags, uint32_t default_ttl,
|
||||
PyObject* question, PyObject* answer, PyObject* authority, PyObject* additional)
|
||||
PyObject* question, PyObject* answer, PyObject* authority, PyObject* additional)
|
||||
{
|
||||
sldns_buffer *qb = 0;
|
||||
int res = 1;
|
||||
|
|
@ -1116,7 +1135,7 @@ int set_return_msg(struct module_qstate* qstate,
|
|||
uint16_t PKT_CD = 16;
|
||||
uint16_t PKT_RA = 32;
|
||||
uint16_t PKT_AD = 64;
|
||||
|
||||
|
||||
if ((!checkList(question)) || (!checkList(answer)) || (!checkList(authority)) || (!checkList(additional)))
|
||||
return 0;
|
||||
if ((qb = sldns_buffer_new(LDNS_RR_BUF_SIZE)) == 0) return 0;
|
||||
|
|
@ -1165,7 +1184,7 @@ int set_return_msg(struct module_qstate* qstate,
|
|||
}
|
||||
%}
|
||||
|
||||
int set_return_msg(struct module_qstate* qstate,
|
||||
int set_return_msg(struct module_qstate* qstate,
|
||||
const char* rr_name, int rr_type, int rr_class , uint16_t flags, uint32_t default_ttl,
|
||||
PyObject* question, PyObject* answer, PyObject* authority, PyObject* additional);
|
||||
|
||||
|
|
@ -1185,17 +1204,17 @@ int set_return_msg(struct module_qstate* qstate,
|
|||
|
||||
def set_return_msg(self, qstate):
|
||||
"""Returns 1 if OK"""
|
||||
status = _unboundmodule.set_return_msg(qstate, self.rr_name, self.rr_type, self.rr_class,
|
||||
status = _unboundmodule.set_return_msg(qstate, self.rr_name, self.rr_type, self.rr_class,
|
||||
self.query_flags, self.default_ttl,
|
||||
self.question, self.answer, self.authority, self.additional)
|
||||
|
||||
if (status) and (PKT_AA & self.query_flags):
|
||||
qstate.return_msg.rep.authoritative = 1
|
||||
|
||||
return status
|
||||
return status
|
||||
|
||||
%}
|
||||
/* ************************************************************************************ *
|
||||
/* ************************************************************************************ *
|
||||
ASN: Delegation pointer related functions
|
||||
* ************************************************************************************ */
|
||||
|
||||
|
|
@ -1254,7 +1273,7 @@ struct delegpt* find_delegation(struct module_qstate* qstate, char *nm, size_t n
|
|||
}
|
||||
%}
|
||||
|
||||
/* ************************************************************************************ *
|
||||
/* ************************************************************************************ *
|
||||
Functions
|
||||
* ************************************************************************************ */
|
||||
/******************************
|
||||
|
|
@ -1346,7 +1365,7 @@ int edns_opt_list_append(struct edns_option** list, uint16_t code, size_t len,
|
|||
int python_inplace_cb_reply_generic(struct query_info* qinfo,
|
||||
struct module_qstate* qstate, struct reply_info* rep, int rcode,
|
||||
struct edns_data* edns, struct edns_option** opt_list_out,
|
||||
struct regional* region, void* python_callback)
|
||||
struct regional* region, int id, void* python_callback)
|
||||
{
|
||||
PyObject *func, *py_edns, *py_qstate, *py_opt_list_out, *py_qinfo;
|
||||
PyObject *py_rep, *py_region;
|
||||
|
|
@ -1379,56 +1398,49 @@ int edns_opt_list_append(struct edns_option** list, uint16_t code, size_t len,
|
|||
return res;
|
||||
}
|
||||
|
||||
/* register a callback */
|
||||
static int python_inplace_cb_register(enum inplace_cb_list_type type,
|
||||
PyObject* py_cb, struct module_env* env, int id)
|
||||
{
|
||||
int ret = inplace_cb_register(python_inplace_cb_reply_generic,
|
||||
type, (void*) py_cb, env, id);
|
||||
if (ret) Py_INCREF(py_cb);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Swig implementations for Python */
|
||||
static int register_inplace_cb_reply(PyObject* py_cb,
|
||||
struct module_env* env)
|
||||
struct module_env* env, int id)
|
||||
{
|
||||
int ret = inplace_cb_reply_register(
|
||||
python_inplace_cb_reply_generic, (void*) py_cb, env);
|
||||
if (ret) Py_INCREF(py_cb);
|
||||
return ret;
|
||||
return python_inplace_cb_register(inplace_cb_reply, py_cb, env, id);
|
||||
}
|
||||
static int register_inplace_cb_reply_cache(PyObject* py_cb,
|
||||
struct module_env* env)
|
||||
struct module_env* env, int id)
|
||||
{
|
||||
int ret = inplace_cb_reply_cache_register(
|
||||
python_inplace_cb_reply_generic, (void*) py_cb, env);
|
||||
if (ret) Py_INCREF(py_cb);
|
||||
return ret;
|
||||
return python_inplace_cb_register(inplace_cb_reply_cache, py_cb, env, id);
|
||||
}
|
||||
static int register_inplace_cb_reply_local(PyObject* py_cb,
|
||||
struct module_env* env)
|
||||
struct module_env* env, int id)
|
||||
{
|
||||
int ret = inplace_cb_reply_local_register(
|
||||
python_inplace_cb_reply_generic, (void*) py_cb, env);
|
||||
if (ret) Py_INCREF(py_cb);
|
||||
return ret;
|
||||
return python_inplace_cb_register(inplace_cb_reply_local, py_cb, env, id);
|
||||
}
|
||||
static int register_inplace_cb_reply_servfail(PyObject* py_cb,
|
||||
struct module_env* env)
|
||||
struct module_env* env, int id)
|
||||
{
|
||||
int ret = inplace_cb_reply_servfail_register(
|
||||
python_inplace_cb_reply_generic, (void*) py_cb, env);
|
||||
if (ret) Py_INCREF(py_cb);
|
||||
return ret;
|
||||
return python_inplace_cb_register(inplace_cb_reply_servfail,
|
||||
py_cb, env, id);
|
||||
}
|
||||
%}
|
||||
/* C declarations */
|
||||
int inplace_cb_reply_register(
|
||||
inplace_cb_reply_func_type* cb, void* cb_arg, struct module_env* env);
|
||||
int inplace_cb_reply_cache_register(
|
||||
inplace_cb_reply_func_type* cb, void* cb_arg, struct module_env* env);
|
||||
int inplace_cb_reply_local_register(
|
||||
inplace_cb_reply_func_type* cb, void* cb_arg, struct module_env* env);
|
||||
int inplace_cb_reply_servfail_register(
|
||||
inplace_cb_reply_func_type* cb, void* cb_arg, struct module_env* env);
|
||||
int inplace_cb_register(void* cb, enum inplace_cb_list_type type, void* cbarg,
|
||||
struct module_env* env, int id);
|
||||
|
||||
/* Swig declarations */
|
||||
static int register_inplace_cb_reply(PyObject* py_cb,
|
||||
struct module_env* env);
|
||||
struct module_env* env, int id);
|
||||
static int register_inplace_cb_reply_cache(PyObject* py_cb,
|
||||
struct module_env* env);
|
||||
struct module_env* env, int id);
|
||||
static int register_inplace_cb_reply_local(PyObject* py_cb,
|
||||
struct module_env* env);
|
||||
struct module_env* env, int id);
|
||||
static int register_inplace_cb_reply_servfail(PyObject* py_cb,
|
||||
struct module_env* env);
|
||||
struct module_env* env, int id);
|
||||
|
|
|
|||
|
|
@ -1,22 +1,22 @@
|
|||
/*
|
||||
* pythonmod.c: unbound module C wrapper
|
||||
*
|
||||
*
|
||||
* Copyright (c) 2009, Zdenek Vasicek (vasicek AT fit.vutbr.cz)
|
||||
* Marek Vavrusa (xvavru00 AT stud.fit.vutbr.cz)
|
||||
*
|
||||
* This software is open source.
|
||||
*
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
*
|
||||
* * Neither the name of the organization nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
|
|
@ -63,7 +63,7 @@ typedef void* PyGILState_STATE;
|
|||
#endif
|
||||
|
||||
/**
|
||||
* Global state for the module.
|
||||
* Global state for the module.
|
||||
*/
|
||||
struct pythonmod_env {
|
||||
|
||||
|
|
@ -117,7 +117,7 @@ int pythonmod_init(struct module_env* env, int id)
|
|||
int init_standard = 1;
|
||||
|
||||
struct pythonmod_env* pe = (struct pythonmod_env*)calloc(1, sizeof(struct pythonmod_env));
|
||||
if (!pe)
|
||||
if (!pe)
|
||||
{
|
||||
log_err("pythonmod: malloc failure");
|
||||
return 0;
|
||||
|
|
@ -133,7 +133,7 @@ int pythonmod_init(struct module_env* env, int id)
|
|||
}
|
||||
|
||||
/* Initialize Python libraries */
|
||||
if (!Py_IsInitialized())
|
||||
if (!Py_IsInitialized())
|
||||
{
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
wchar_t progname[8];
|
||||
|
|
@ -169,13 +169,13 @@ int pythonmod_init(struct module_env* env, int id)
|
|||
PyRun_SimpleString("sys.path.append(distutils.sysconfig.get_python_lib(1,0)) \n");
|
||||
if (PyRun_SimpleString("from unboundmodule import *\n") < 0)
|
||||
{
|
||||
log_err("pythonmod: cannot initialize core module: unboundmodule.py");
|
||||
log_err("pythonmod: cannot initialize core module: unboundmodule.py");
|
||||
PyGILState_Release(gil);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Check Python file load */
|
||||
if ((script_py = fopen(pe->fname, "r")) == NULL)
|
||||
if ((script_py = fopen(pe->fname, "r")) == NULL)
|
||||
{
|
||||
log_err("pythonmod: can't open file %s for reading", pe->fname);
|
||||
PyGILState_Release(gil);
|
||||
|
|
@ -190,8 +190,8 @@ int pythonmod_init(struct module_env* env, int id)
|
|||
PyModule_AddObject(pe->module, "mod_env", pe->data);
|
||||
|
||||
/* TODO: deallocation of pe->... if an error occurs */
|
||||
|
||||
if (PyRun_SimpleFile(script_py, pe->fname) < 0)
|
||||
|
||||
if (PyRun_SimpleFile(script_py, pe->fname) < 0)
|
||||
{
|
||||
log_err("pythonmod: can't parse Python script %s", pe->fname);
|
||||
PyGILState_Release(gil);
|
||||
|
|
@ -203,26 +203,26 @@ int pythonmod_init(struct module_env* env, int id)
|
|||
if ((pe->func_init = PyDict_GetItemString(pe->dict, "init_standard")) == NULL)
|
||||
{
|
||||
init_standard = 0;
|
||||
if ((pe->func_init = PyDict_GetItemString(pe->dict, "init")) == NULL)
|
||||
if ((pe->func_init = PyDict_GetItemString(pe->dict, "init")) == NULL)
|
||||
{
|
||||
log_err("pythonmod: function init is missing in %s", pe->fname);
|
||||
PyGILState_Release(gil);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if ((pe->func_deinit = PyDict_GetItemString(pe->dict, "deinit")) == NULL)
|
||||
if ((pe->func_deinit = PyDict_GetItemString(pe->dict, "deinit")) == NULL)
|
||||
{
|
||||
log_err("pythonmod: function deinit is missing in %s", pe->fname);
|
||||
PyGILState_Release(gil);
|
||||
return 0;
|
||||
}
|
||||
if ((pe->func_operate = PyDict_GetItemString(pe->dict, "operate")) == NULL)
|
||||
if ((pe->func_operate = PyDict_GetItemString(pe->dict, "operate")) == NULL)
|
||||
{
|
||||
log_err("pythonmod: function operate is missing in %s", pe->fname);
|
||||
PyGILState_Release(gil);
|
||||
return 0;
|
||||
}
|
||||
if ((pe->func_inform = PyDict_GetItemString(pe->dict, "inform_super")) == NULL)
|
||||
if ((pe->func_inform = PyDict_GetItemString(pe->dict, "inform_super")) == NULL)
|
||||
{
|
||||
log_err("pythonmod: function inform_super is missing in %s", pe->fname);
|
||||
PyGILState_Release(gil);
|
||||
|
|
@ -239,7 +239,7 @@ int pythonmod_init(struct module_env* env, int id)
|
|||
SWIGTYPE_p_config_file, 0);
|
||||
}
|
||||
res = PyObject_CallFunction(pe->func_init, "iO", id, py_init_arg);
|
||||
if (PyErr_Occurred())
|
||||
if (PyErr_Occurred())
|
||||
{
|
||||
log_err("pythonmod: Exception occurred in function init");
|
||||
PyErr_Print();
|
||||
|
|
@ -304,20 +304,20 @@ void pythonmod_inform_super(struct module_qstate* qstate, int id, struct module_
|
|||
py_qstate = SWIG_NewPointerObj((void*) qstate, SWIGTYPE_p_module_qstate, 0);
|
||||
py_sqstate = SWIG_NewPointerObj((void*) super, SWIGTYPE_p_module_qstate, 0);
|
||||
|
||||
res = PyObject_CallFunction(pe->func_inform, "iOOO", id, py_qstate,
|
||||
res = PyObject_CallFunction(pe->func_inform, "iOOO", id, py_qstate,
|
||||
py_sqstate, pq->data);
|
||||
|
||||
if (PyErr_Occurred())
|
||||
if (PyErr_Occurred())
|
||||
{
|
||||
log_err("pythonmod: Exception occurred in function inform_super");
|
||||
PyErr_Print();
|
||||
qstate->ext_state[id] = module_error;
|
||||
}
|
||||
else if ((res == NULL) || (!PyObject_IsTrue(res)))
|
||||
}
|
||||
else if ((res == NULL) || (!PyObject_IsTrue(res)))
|
||||
{
|
||||
log_err("pythonmod: python returned bad code in inform_super");
|
||||
qstate->ext_state[id] = module_error;
|
||||
}
|
||||
}
|
||||
|
||||
Py_XDECREF(res);
|
||||
Py_XDECREF(py_sqstate);
|
||||
|
|
@ -326,7 +326,7 @@ void pythonmod_inform_super(struct module_qstate* qstate, int id, struct module_
|
|||
PyGILState_Release(gil);
|
||||
}
|
||||
|
||||
void pythonmod_operate(struct module_qstate* qstate, enum module_ev event,
|
||||
void pythonmod_operate(struct module_qstate* qstate, enum module_ev event,
|
||||
int id, struct outbound_entry* ATTR_UNUSED(outbound))
|
||||
{
|
||||
struct pythonmod_env* pe = (struct pythonmod_env*)qstate->env->modinfo[id];
|
||||
|
|
@ -335,10 +335,10 @@ void pythonmod_operate(struct module_qstate* qstate, enum module_ev event,
|
|||
PyGILState_STATE gil = PyGILState_Ensure();
|
||||
|
||||
if ( pq == NULL)
|
||||
{
|
||||
{
|
||||
/* create qstate */
|
||||
pq = qstate->minfo[id] = malloc(sizeof(struct pythonmod_qstate));
|
||||
|
||||
|
||||
/* Initialize per query data */
|
||||
pq->data = Py_None;
|
||||
Py_INCREF(pq->data);
|
||||
|
|
@ -346,19 +346,19 @@ void pythonmod_operate(struct module_qstate* qstate, enum module_ev event,
|
|||
|
||||
/* Call operate */
|
||||
py_qstate = SWIG_NewPointerObj((void*) qstate, SWIGTYPE_p_module_qstate, 0);
|
||||
res = PyObject_CallFunction(pe->func_operate, "iiOO", id, (int) event,
|
||||
res = PyObject_CallFunction(pe->func_operate, "iiOO", id, (int) event,
|
||||
py_qstate, pq->data);
|
||||
if (PyErr_Occurred())
|
||||
if (PyErr_Occurred())
|
||||
{
|
||||
log_err("pythonmod: Exception occurred in function operate, event: %s", strmodulevent(event));
|
||||
PyErr_Print();
|
||||
qstate->ext_state[id] = module_error;
|
||||
}
|
||||
else if ((res == NULL) || (!PyObject_IsTrue(res)))
|
||||
}
|
||||
else if ((res == NULL) || (!PyObject_IsTrue(res)))
|
||||
{
|
||||
log_err("pythonmod: python returned bad code, event: %s", strmodulevent(event));
|
||||
qstate->ext_state[id] = module_error;
|
||||
}
|
||||
}
|
||||
Py_XDECREF(res);
|
||||
Py_XDECREF(py_qstate);
|
||||
|
||||
|
|
@ -372,7 +372,7 @@ void pythonmod_clear(struct module_qstate* qstate, int id)
|
|||
return;
|
||||
|
||||
pq = (struct pythonmod_qstate*)qstate->minfo[id];
|
||||
verbose(VERB_ALGO, "pythonmod: clear, id: %d, pq:%lX", id,
|
||||
verbose(VERB_ALGO, "pythonmod: clear, id: %d, pq:%lX", id,
|
||||
(unsigned long int)pq);
|
||||
if(pq != NULL)
|
||||
{
|
||||
|
|
@ -389,7 +389,7 @@ void pythonmod_clear(struct module_qstate* qstate, int id)
|
|||
size_t pythonmod_get_mem(struct module_env* env, int id)
|
||||
{
|
||||
struct pythonmod_env* pe = (struct pythonmod_env*)env->modinfo[id];
|
||||
verbose(VERB_ALGO, "pythonmod: get_mem, id: %d, pe:%lX", id,
|
||||
verbose(VERB_ALGO, "pythonmod: get_mem, id: %d, pe:%lX", id,
|
||||
(unsigned long int)pe);
|
||||
if(!pe)
|
||||
return 0;
|
||||
|
|
@ -397,11 +397,11 @@ size_t pythonmod_get_mem(struct module_env* env, int id)
|
|||
}
|
||||
|
||||
/**
|
||||
* The module function block
|
||||
* The module function block
|
||||
*/
|
||||
static struct module_func_block pythonmod_block = {
|
||||
"python",
|
||||
&pythonmod_init, &pythonmod_deinit, &pythonmod_operate, &pythonmod_inform_super,
|
||||
&pythonmod_init, &pythonmod_deinit, &pythonmod_operate, &pythonmod_inform_super,
|
||||
&pythonmod_clear, &pythonmod_get_mem
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -72,5 +72,5 @@ size_t pythonmod_get_mem(struct module_env* env, int id);
|
|||
int python_inplace_cb_reply_generic(struct query_info* qinfo,
|
||||
struct module_qstate* qstate, struct reply_info* rep, int rcode,
|
||||
struct edns_data* edns, struct edns_option** opt_list_out,
|
||||
struct regional* region, void* python_callback);
|
||||
struct regional* region, int id, void* python_callback);
|
||||
#endif /* PYTHONMOD_H */
|
||||
|
|
|
|||
1179
respip/respip.c
Normal file
1179
respip/respip.c
Normal file
File diff suppressed because it is too large
Load diff
230
respip/respip.h
Normal file
230
respip/respip.h
Normal file
|
|
@ -0,0 +1,230 @@
|
|||
/*
|
||||
* respip/respip.h - IP-based response modification module
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* This file contains a module that selectively modifies query responses
|
||||
* based on their AAAA/A IP addresses.
|
||||
*/
|
||||
|
||||
#ifndef RESPIP_RESPIP_H
|
||||
#define RESPIP_RESPIP_H
|
||||
|
||||
#include "util/module.h"
|
||||
#include "services/localzone.h"
|
||||
|
||||
/**
|
||||
* Set of response IP addresses with associated actions and tags.
|
||||
* Forward declaration only here. Actual definition is hidden within the
|
||||
* module.
|
||||
*/
|
||||
struct respip_set;
|
||||
|
||||
/**
|
||||
* Forward declaration for the structure that represents a node in the
|
||||
* respip_set address tree
|
||||
*/
|
||||
struct resp_addr;
|
||||
|
||||
/**
|
||||
* Forward declaration for the structure that represents a tree of view data.
|
||||
*/
|
||||
struct views;
|
||||
|
||||
struct respip_addr_info;
|
||||
|
||||
/**
|
||||
* Client-specific attributes that can affect IP-based actions.
|
||||
* This is essentially a subset of acl_addr (except for respip_set) but
|
||||
* defined as a separate structure to avoid dependency on the daemon-specific
|
||||
* structure.
|
||||
* respip_set is supposed to refer to the response-ip set for the global view.
|
||||
*/
|
||||
struct respip_client_info {
|
||||
uint8_t* taglist;
|
||||
size_t taglen;
|
||||
uint8_t* tag_actions;
|
||||
size_t tag_actions_size;
|
||||
struct config_strlist** tag_datas;
|
||||
size_t tag_datas_size;
|
||||
struct view* view;
|
||||
struct respip_set* respip_set;
|
||||
};
|
||||
|
||||
/**
|
||||
* Data items representing the result of response-ip processing.
|
||||
* Note: this structure currently only define a few members, but exists
|
||||
* as a separate struct mainly for the convenience of custom extensions.
|
||||
*/
|
||||
struct respip_action_info {
|
||||
enum respip_action action;
|
||||
struct respip_addr_info* addrinfo; /* set only for inform variants */
|
||||
};
|
||||
|
||||
/**
|
||||
* Forward declaration for the structure that represents a node in the
|
||||
* respip_set address tree
|
||||
*/
|
||||
struct resp_addr;
|
||||
|
||||
/**
|
||||
* Create response IP set.
|
||||
* @return new struct or NULL on error.
|
||||
*/
|
||||
struct respip_set* respip_set_create(void);
|
||||
|
||||
/**
|
||||
* Delete response IP set.
|
||||
* @param set: to delete.
|
||||
*/
|
||||
void respip_set_delete(struct respip_set* set);
|
||||
|
||||
/**
|
||||
* Apply response-ip config settings to the global (default) view.
|
||||
* It assumes exclusive access to set (no internal locks).
|
||||
* @param set: processed global respip config data
|
||||
* @param cfg: config data.
|
||||
* @return 1 on success, 0 on error.
|
||||
*/
|
||||
int respip_global_apply_cfg(struct respip_set* set, struct config_file* cfg);
|
||||
|
||||
/**
|
||||
* Apply response-ip config settings in named views.
|
||||
* @param vs: view structures with processed config data
|
||||
* @param cfg: config data.
|
||||
* @param have_view_respip_cfg: set to true if any named view has respip
|
||||
* configuration; otherwise set to false
|
||||
* @return 1 on success, 0 on error.
|
||||
*/
|
||||
int respip_views_apply_cfg(struct views* vs, struct config_file* cfg,
|
||||
int* have_view_respip_cfg);
|
||||
|
||||
/**
|
||||
* Merge two replies to build a complete CNAME chain.
|
||||
* It appends the content of 'tgt_rep' to 'base_rep', assuming (but not
|
||||
* checking) the former ends with a CNAME and the latter resolves its target.
|
||||
* A merged new reply will be built using 'region' and *new_repp will point
|
||||
* to the new one on success.
|
||||
* If the target reply would also be subject to a response-ip action for
|
||||
* 'cinfo', this function uses 'base_rep' as the merged reply, ignoring
|
||||
* 'tgt_rep'. This is for avoiding cases like a CNAME loop or failure of
|
||||
* applying an action to an address.
|
||||
* RRSIGs in 'tgt_rep' will be excluded in the merged reply, as the resulting
|
||||
* reply is assumed to be faked due to a response-ip action and can't be
|
||||
* considered secure in terms of DNSSEC.
|
||||
* The caller must ensure that neither 'base_rep' nor 'tgt_rep' can be modified
|
||||
* until this function returns.
|
||||
* @param base_rep: the reply info containing an incomplete CNAME.
|
||||
* @param qinfo: query info corresponding to 'base_rep'.
|
||||
* @param tgt_rep: the reply info that completes the CNAME chain.
|
||||
* @param cinfo: client info corresponding to 'base_rep'.
|
||||
* @param must_validate: whether 'tgt_rep' must be DNSSEC-validated.
|
||||
* @param new_repp: pointer placeholder for the merged reply. will be intact
|
||||
* on error.
|
||||
* @param region: allocator to build *new_repp.
|
||||
* @return 1 on success, 0 on error.
|
||||
*/
|
||||
int respip_merge_cname(struct reply_info* base_rep,
|
||||
const struct query_info* qinfo, const struct reply_info* tgt_rep,
|
||||
const struct respip_client_info* cinfo, int must_validate,
|
||||
struct reply_info** new_repp, struct regional* region);
|
||||
|
||||
/**
|
||||
* See if any IP-based action should apply to any IP address of AAAA/A answer
|
||||
* record in the reply. If so, apply the action. In some cases it rewrites
|
||||
* the reply rrsets, in which case *new_repp will point to the updated reply
|
||||
* info. Depending on the action, some of the rrsets in 'rep' will be
|
||||
* shallow-copied into '*new_repp'; the caller must ensure that the rrsets
|
||||
* in 'rep' are valid throughout the lifetime of *new_repp, and it must
|
||||
* provide appropriate mutex if the rrsets can be shared by multiple threads.
|
||||
* @param qinfo: query info corresponding to the reply.
|
||||
* @param cinfo: client-specific info to identify the best matching action.
|
||||
* can be NULL.
|
||||
* @param rep: original reply info. must not be NULL.
|
||||
* @param new_repp: can be set to the rewritten reply info (intact on failure).
|
||||
* @param actinfo: result of response-ip processing
|
||||
* @param alias_rrset: must not be NULL.
|
||||
* @param search_only: if true, only check if an action would apply. actionp
|
||||
* will be set (or intact) accordingly but the modified reply won't be built.
|
||||
* @param region: allocator to build *new_repp.
|
||||
* @return 1 on success, 0 on error.
|
||||
*/
|
||||
int respip_rewrite_reply(const struct query_info* qinfo,
|
||||
const struct respip_client_info* cinfo,
|
||||
const struct reply_info *rep, struct reply_info** new_repp,
|
||||
struct respip_action_info* actinfo,
|
||||
struct ub_packed_rrset_key** alias_rrset,
|
||||
int search_only, struct regional* region);
|
||||
|
||||
/**
|
||||
* Get the response-ip function block.
|
||||
* @return: function block with function pointers to response-ip methods.
|
||||
*/
|
||||
struct module_func_block* respip_get_funcblock(void);
|
||||
|
||||
/** response-ip init */
|
||||
int respip_init(struct module_env* env, int id);
|
||||
|
||||
/** response-ip deinit */
|
||||
void respip_deinit(struct module_env* env, int id);
|
||||
|
||||
/** response-ip operate on a query */
|
||||
void respip_operate(struct module_qstate* qstate, enum module_ev event, int id,
|
||||
struct outbound_entry* outbound);
|
||||
|
||||
/** inform response-ip super */
|
||||
void respip_inform_super(struct module_qstate* qstate, int id,
|
||||
struct module_qstate* super);
|
||||
|
||||
/** response-ip cleanup query state */
|
||||
void respip_clear(struct module_qstate* qstate, int id);
|
||||
|
||||
/**
|
||||
* returns address of the IP address tree of the specified respip set;
|
||||
* returns NULL for NULL input; exists for test purposes only
|
||||
*/
|
||||
struct rbtree_type* respip_set_get_tree(struct respip_set* set);
|
||||
|
||||
/**
|
||||
* returns respip action for the specified node in the respip address
|
||||
* returns respip_none for NULL input; exists for test purposes only
|
||||
*/
|
||||
enum respip_action resp_addr_get_action(const struct resp_addr* addr);
|
||||
|
||||
/**
|
||||
* returns rrset portion of the specified node in the respip address
|
||||
* tree; returns NULL for NULL input; exists for test purposes only
|
||||
*/
|
||||
struct ub_packed_rrset_key* resp_addr_get_rrset(struct resp_addr* addr);
|
||||
|
||||
/** response-ip alloc size routine */
|
||||
size_t respip_get_mem(struct module_env* env, int id);
|
||||
|
||||
/**
|
||||
* respip set emptiness test
|
||||
* @param set respip set to test
|
||||
* @return 0 if the specified set exists (non-NULL) and is non-empty;
|
||||
* otherwise returns 1
|
||||
*/
|
||||
int respip_set_is_empty(const struct respip_set* set);
|
||||
|
||||
/**
|
||||
* print log information for a query subject to an inform or inform-deny
|
||||
* response-ip action.
|
||||
* @param respip_addr: response-ip information that causes the action
|
||||
* @param qname: query name in the context, will be ignored if local_alias is
|
||||
* non-NULL.
|
||||
* @param qtype: query type, in host byte order.
|
||||
* @param qclass: query class, in host byte order.
|
||||
* @param local_alias: set to a local alias if the query matches an alias in
|
||||
* a local zone. In this case its owner name will be considered the actual
|
||||
* query name.
|
||||
* @param repinfo: reply info containing the client's source address and port.
|
||||
*/
|
||||
void respip_inform_print(struct respip_addr_info* respip_addr, uint8_t* qname,
|
||||
uint16_t qtype, uint16_t qclass, struct local_rrset* local_alias,
|
||||
struct comm_reply* repinfo);
|
||||
|
||||
#endif /* RESPIP_RESPIP_H */
|
||||
8
services/cache/dns.c
vendored
8
services/cache/dns.c
vendored
|
|
@ -479,8 +479,7 @@ gen_dns_msg(struct regional* region, struct query_info* q, size_t num)
|
|||
return msg;
|
||||
}
|
||||
|
||||
/** generate dns_msg from cached message */
|
||||
static struct dns_msg*
|
||||
struct dns_msg*
|
||||
tomsg(struct module_env* env, struct query_info* q, struct reply_info* r,
|
||||
struct regional* region, time_t now, struct regional* scratch)
|
||||
{
|
||||
|
|
@ -525,8 +524,11 @@ tomsg(struct module_env* env, struct query_info* q, struct reply_info* r,
|
|||
return NULL;
|
||||
}
|
||||
}
|
||||
rrset_array_unlock_touch(env->rrset_cache, scratch, r->ref,
|
||||
if(env)
|
||||
rrset_array_unlock_touch(env->rrset_cache, scratch, r->ref,
|
||||
r->rrset_count);
|
||||
else
|
||||
rrset_array_unlock(r->ref, r->rrset_count);
|
||||
return msg;
|
||||
}
|
||||
|
||||
|
|
|
|||
14
services/cache/dns.h
vendored
14
services/cache/dns.h
vendored
|
|
@ -126,6 +126,20 @@ struct delegpt* dns_cache_find_delegation(struct module_env* env,
|
|||
uint8_t* qname, size_t qnamelen, uint16_t qtype, uint16_t qclass,
|
||||
struct regional* region, struct dns_msg** msg, time_t timenow);
|
||||
|
||||
/**
|
||||
* generate dns_msg from cached message
|
||||
* @param env: module environment with the DNS cache. NULL if the LRU from cache
|
||||
* does not need to be touched.
|
||||
* @param q: query info, contains qname that will make up the dns message.
|
||||
* @param r: reply info that, together with qname, will make up the dns message.
|
||||
* @param region: where to allocate dns message.
|
||||
* @param now: the time now, for check if TTL on cache entry is ok.
|
||||
* @param scratch: where to allocate temporary data.
|
||||
* */
|
||||
struct dns_msg* tomsg(struct module_env* env, struct query_info* q,
|
||||
struct reply_info* r, struct regional* region, time_t now,
|
||||
struct regional* scratch);
|
||||
|
||||
/**
|
||||
* Find cached message
|
||||
* @param env: module environment with the DNS cache.
|
||||
|
|
|
|||
|
|
@ -1056,15 +1056,25 @@ set_recvpktinfo(int s, int family)
|
|||
* @param tcp_mss: maximum segment size of tcp socket. default if zero.
|
||||
* @param freebind: set IP_FREEBIND socket option.
|
||||
* @param use_systemd: if true, fetch sockets from systemd.
|
||||
* @param dnscrypt_port: dnscrypt service port number
|
||||
* @return: returns false on error.
|
||||
*/
|
||||
static int
|
||||
ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp,
|
||||
struct addrinfo *hints, const char* port, struct listen_port** list,
|
||||
size_t rcv, size_t snd, int ssl_port, int* reuseport, int transparent,
|
||||
int tcp_mss, int freebind, int use_systemd)
|
||||
int tcp_mss, int freebind, int use_systemd, int dnscrypt_port)
|
||||
{
|
||||
int s, noip6=0;
|
||||
#ifdef USE_DNSCRYPT
|
||||
int is_dnscrypt = ((strchr(ifname, '@') &&
|
||||
atoi(strchr(ifname, '@')+1) == dnscrypt_port) ||
|
||||
(!strchr(ifname, '@') && atoi(port) == dnscrypt_port));
|
||||
#else
|
||||
int is_dnscrypt = 0;
|
||||
(void)dnscrypt_port;
|
||||
#endif
|
||||
|
||||
if(!do_udp && !do_tcp)
|
||||
return 0;
|
||||
if(do_auto) {
|
||||
|
|
@ -1086,7 +1096,8 @@ ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp,
|
|||
#endif
|
||||
return 0;
|
||||
}
|
||||
if(!port_insert(list, s, listen_type_udpancil)) {
|
||||
if(!port_insert(list, s,
|
||||
is_dnscrypt?listen_type_udpancil_dnscrypt:listen_type_udpancil)) {
|
||||
#ifndef USE_WINSOCK
|
||||
close(s);
|
||||
#else
|
||||
|
|
@ -1105,7 +1116,8 @@ ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp,
|
|||
}
|
||||
return 0;
|
||||
}
|
||||
if(!port_insert(list, s, listen_type_udp)) {
|
||||
if(!port_insert(list, s,
|
||||
is_dnscrypt?listen_type_udp_dnscrypt:listen_type_udp)) {
|
||||
#ifndef USE_WINSOCK
|
||||
close(s);
|
||||
#else
|
||||
|
|
@ -1130,7 +1142,7 @@ ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp,
|
|||
if(is_ssl)
|
||||
verbose(VERB_ALGO, "setup TCP for SSL service");
|
||||
if(!port_insert(list, s, is_ssl?listen_type_ssl:
|
||||
listen_type_tcp)) {
|
||||
(is_dnscrypt?listen_type_tcp_dnscrypt:listen_type_tcp))) {
|
||||
#ifndef USE_WINSOCK
|
||||
close(s);
|
||||
#else
|
||||
|
|
@ -1172,6 +1184,9 @@ listen_create(struct comm_base* base, struct listen_port* ports,
|
|||
return NULL;
|
||||
front->cps = NULL;
|
||||
front->udp_buff = sldns_buffer_new(bufsize);
|
||||
#ifdef USE_DNSCRYPT
|
||||
front->dnscrypt_udp_buff = NULL;
|
||||
#endif
|
||||
if(!front->udp_buff) {
|
||||
free(front);
|
||||
return NULL;
|
||||
|
|
@ -1180,17 +1195,20 @@ listen_create(struct comm_base* base, struct listen_port* ports,
|
|||
/* create comm points as needed */
|
||||
while(ports) {
|
||||
struct comm_point* cp = NULL;
|
||||
if(ports->ftype == listen_type_udp)
|
||||
if(ports->ftype == listen_type_udp ||
|
||||
ports->ftype == listen_type_udp_dnscrypt)
|
||||
cp = comm_point_create_udp(base, ports->fd,
|
||||
front->udp_buff, cb, cb_arg);
|
||||
else if(ports->ftype == listen_type_tcp)
|
||||
else if(ports->ftype == listen_type_tcp ||
|
||||
ports->ftype == listen_type_tcp_dnscrypt)
|
||||
cp = comm_point_create_tcp(base, ports->fd,
|
||||
tcp_accept_count, bufsize, cb, cb_arg);
|
||||
else if(ports->ftype == listen_type_ssl) {
|
||||
cp = comm_point_create_tcp(base, ports->fd,
|
||||
tcp_accept_count, bufsize, cb, cb_arg);
|
||||
cp->ssl = sslctx;
|
||||
} else if(ports->ftype == listen_type_udpancil)
|
||||
} else if(ports->ftype == listen_type_udpancil ||
|
||||
ports->ftype == listen_type_udpancil_dnscrypt)
|
||||
cp = comm_point_create_udp_ancil(base, ports->fd,
|
||||
front->udp_buff, cb, cb_arg);
|
||||
if(!cp) {
|
||||
|
|
@ -1200,6 +1218,21 @@ listen_create(struct comm_base* base, struct listen_port* ports,
|
|||
}
|
||||
cp->dtenv = dtenv;
|
||||
cp->do_not_close = 1;
|
||||
#ifdef USE_DNSCRYPT
|
||||
if (ports->ftype == listen_type_udp_dnscrypt ||
|
||||
ports->ftype == listen_type_tcp_dnscrypt ||
|
||||
ports->ftype == listen_type_udpancil_dnscrypt) {
|
||||
cp->dnscrypt = 1;
|
||||
cp->dnscrypt_buffer = sldns_buffer_new(bufsize);
|
||||
if(!cp->dnscrypt_buffer) {
|
||||
log_err("can't alloc dnscrypt_buffer");
|
||||
comm_point_delete(cp);
|
||||
listen_delete(front);
|
||||
return NULL;
|
||||
}
|
||||
front->dnscrypt_udp_buff = cp->dnscrypt_buffer;
|
||||
}
|
||||
#endif
|
||||
if(!listen_cp_insert(cp, front)) {
|
||||
log_err("malloc failed");
|
||||
comm_point_delete(cp);
|
||||
|
|
@ -1235,6 +1268,12 @@ listen_delete(struct listen_dnsport* front)
|
|||
if(!front)
|
||||
return;
|
||||
listen_list_delete(front->cps);
|
||||
#ifdef USE_DNSCRYPT
|
||||
if(front->dnscrypt_udp_buff &&
|
||||
front->udp_buff != front->dnscrypt_udp_buff) {
|
||||
sldns_buffer_free(front->dnscrypt_udp_buff);
|
||||
}
|
||||
#endif
|
||||
sldns_buffer_free(front->udp_buff);
|
||||
free(front);
|
||||
}
|
||||
|
|
@ -1278,7 +1317,8 @@ listening_ports_open(struct config_file* cfg, int* reuseport)
|
|||
cfg->so_rcvbuf, cfg->so_sndbuf,
|
||||
cfg->ssl_port, reuseport,
|
||||
cfg->ip_transparent,
|
||||
cfg->tcp_mss, cfg->ip_freebind, cfg->use_systemd)) {
|
||||
cfg->tcp_mss, cfg->ip_freebind, cfg->use_systemd,
|
||||
cfg->dnscrypt_port)) {
|
||||
listening_ports_free(list);
|
||||
return NULL;
|
||||
}
|
||||
|
|
@ -1291,7 +1331,8 @@ listening_ports_open(struct config_file* cfg, int* reuseport)
|
|||
cfg->so_rcvbuf, cfg->so_sndbuf,
|
||||
cfg->ssl_port, reuseport,
|
||||
cfg->ip_transparent,
|
||||
cfg->tcp_mss, cfg->ip_freebind, cfg->use_systemd)) {
|
||||
cfg->tcp_mss, cfg->ip_freebind, cfg->use_systemd,
|
||||
cfg->dnscrypt_port)) {
|
||||
listening_ports_free(list);
|
||||
return NULL;
|
||||
}
|
||||
|
|
@ -1306,7 +1347,8 @@ listening_ports_open(struct config_file* cfg, int* reuseport)
|
|||
cfg->so_rcvbuf, cfg->so_sndbuf,
|
||||
cfg->ssl_port, reuseport,
|
||||
cfg->ip_transparent,
|
||||
cfg->tcp_mss, cfg->ip_freebind, cfg->use_systemd)) {
|
||||
cfg->tcp_mss, cfg->ip_freebind, cfg->use_systemd,
|
||||
cfg->dnscrypt_port)) {
|
||||
listening_ports_free(list);
|
||||
return NULL;
|
||||
}
|
||||
|
|
@ -1319,7 +1361,8 @@ listening_ports_open(struct config_file* cfg, int* reuseport)
|
|||
cfg->so_rcvbuf, cfg->so_sndbuf,
|
||||
cfg->ssl_port, reuseport,
|
||||
cfg->ip_transparent,
|
||||
cfg->tcp_mss, cfg->ip_freebind, cfg->use_systemd)) {
|
||||
cfg->tcp_mss, cfg->ip_freebind, cfg->use_systemd,
|
||||
cfg->dnscrypt_port)) {
|
||||
listening_ports_free(list);
|
||||
return NULL;
|
||||
}
|
||||
|
|
@ -1347,10 +1390,16 @@ void listening_ports_free(struct listen_port* list)
|
|||
|
||||
size_t listen_get_mem(struct listen_dnsport* listen)
|
||||
{
|
||||
struct listen_list* p;
|
||||
size_t s = sizeof(*listen) + sizeof(*listen->base) +
|
||||
sizeof(*listen->udp_buff) +
|
||||
sldns_buffer_capacity(listen->udp_buff);
|
||||
struct listen_list* p;
|
||||
#ifdef USE_DNSCRYPT
|
||||
s += sizeof(*listen->dnscrypt_udp_buff);
|
||||
if(listen->udp_buff != listen->dnscrypt_udp_buff){
|
||||
s += sldns_buffer_capacity(listen->dnscrypt_udp_buff);
|
||||
}
|
||||
#endif
|
||||
for(p = listen->cps; p; p = p->next) {
|
||||
s += sizeof(*p);
|
||||
s += comm_point_get_mem(p->com);
|
||||
|
|
|
|||
|
|
@ -59,7 +59,9 @@ struct listen_dnsport {
|
|||
/** buffer shared by UDP connections, since there is only one
|
||||
datagram at any time. */
|
||||
struct sldns_buffer* udp_buff;
|
||||
|
||||
#ifdef USE_DNSCRYPT
|
||||
struct sldns_buffer* dnscrypt_udp_buff;
|
||||
#endif
|
||||
/** list of comm points used to get incoming events */
|
||||
struct listen_list* cps;
|
||||
};
|
||||
|
|
@ -85,7 +87,14 @@ enum listen_type {
|
|||
/** udp ipv6 (v4mapped) for use with ancillary data */
|
||||
listen_type_udpancil,
|
||||
/** ssl over tcp type */
|
||||
listen_type_ssl
|
||||
listen_type_ssl,
|
||||
/** udp type + dnscrypt*/
|
||||
listen_type_udp_dnscrypt,
|
||||
/** tcp type + dnscrypt */
|
||||
listen_type_tcp_dnscrypt,
|
||||
/** udp ipv6 (v4mapped) for use with ancillary data + dnscrypt*/
|
||||
listen_type_udpancil_dnscrypt
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -229,9 +229,8 @@ lz_enter_zone(struct local_zones* zones, const char* name, const char* type,
|
|||
return z;
|
||||
}
|
||||
|
||||
/** return name and class and rdata of rr; parses string */
|
||||
static int
|
||||
get_rr_content(const char* str, uint8_t** nm, uint16_t* type,
|
||||
int
|
||||
rrstr_get_rr_content(const char* str, uint8_t** nm, uint16_t* type,
|
||||
uint16_t* dclass, time_t* ttl, uint8_t* rr, size_t len,
|
||||
uint8_t** rdata, size_t* rdata_len)
|
||||
{
|
||||
|
|
@ -353,8 +352,8 @@ new_local_rrset(struct regional* region, struct local_data* node,
|
|||
}
|
||||
|
||||
/** insert RR into RRset data structure; Wastes a couple of bytes */
|
||||
static int
|
||||
insert_rr(struct regional* region, struct packed_rrset_data* pd,
|
||||
int
|
||||
rrset_insert_rr(struct regional* region, struct packed_rrset_data* pd,
|
||||
uint8_t* rdata, size_t rdata_len, time_t ttl, const char* rrstr)
|
||||
{
|
||||
size_t* oldlen = pd->rr_len;
|
||||
|
|
@ -456,8 +455,8 @@ lz_enter_rr_into_zone(struct local_zone* z, const char* rrstr)
|
|||
uint8_t rr[LDNS_RR_BUF_SIZE];
|
||||
uint8_t* rdata;
|
||||
size_t rdata_len;
|
||||
if(!get_rr_content(rrstr, &nm, &rrtype, &rrclass, &ttl, rr, sizeof(rr),
|
||||
&rdata, &rdata_len)) {
|
||||
if(!rrstr_get_rr_content(rrstr, &nm, &rrtype, &rrclass, &ttl, rr,
|
||||
sizeof(rr), &rdata, &rdata_len)) {
|
||||
log_err("bad local-data: %s", rrstr);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -513,7 +512,7 @@ lz_enter_rr_into_zone(struct local_zone* z, const char* rrstr)
|
|||
verbose(VERB_ALGO, "ignoring duplicate RR: %s", rrstr);
|
||||
return 1;
|
||||
}
|
||||
return insert_rr(z->region, pd, rdata, rdata_len, ttl, rrstr);
|
||||
return rrset_insert_rr(z->region, pd, rdata, rdata_len, ttl, rrstr);
|
||||
}
|
||||
|
||||
/** enter a data RR into auth data; a zone for it must exist */
|
||||
|
|
@ -1233,9 +1232,10 @@ local_error_encode(struct query_info* qinfo, struct module_env* env,
|
|||
}
|
||||
|
||||
/** find local data tag string match for the given type in the list */
|
||||
static int
|
||||
find_tag_datas(struct query_info* qinfo, struct config_strlist* list,
|
||||
struct ub_packed_rrset_key* r, struct regional* temp)
|
||||
int
|
||||
local_data_find_tag_datas(const struct query_info* qinfo,
|
||||
struct config_strlist* list, struct ub_packed_rrset_key* r,
|
||||
struct regional* temp)
|
||||
{
|
||||
struct config_strlist* p;
|
||||
char buf[65536];
|
||||
|
|
@ -1312,13 +1312,24 @@ find_tag_datas(struct query_info* qinfo, struct config_strlist* list,
|
|||
sldns_wirerr_get_rdatawl(rr, len, 1),
|
||||
d->rr_len[d->count]);
|
||||
if(!d->rr_data[d->count])
|
||||
if(!d) return 0; /* out of memory */
|
||||
return 0; /* out of memory */
|
||||
d->count++;
|
||||
}
|
||||
if(r->rk.dname)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
find_tag_datas(struct query_info* qinfo, struct config_strlist* list,
|
||||
struct ub_packed_rrset_key* r, struct regional* temp)
|
||||
{
|
||||
int result = local_data_find_tag_datas(qinfo, list, r, temp);
|
||||
|
||||
/* If we've found a non-exact alias type of local data, make a shallow
|
||||
* copy of the RRset and remember it in qinfo to complete the alias
|
||||
* chain later. */
|
||||
if(r->rk.dname && qinfo->qtype != LDNS_RR_TYPE_CNAME &&
|
||||
if(result && qinfo->qtype != LDNS_RR_TYPE_CNAME &&
|
||||
r->rk.type == htons(LDNS_RR_TYPE_CNAME)) {
|
||||
qinfo->local_alias =
|
||||
regional_alloc_zero(temp, sizeof(struct local_rrset));
|
||||
|
|
@ -1329,9 +1340,7 @@ find_tag_datas(struct query_info* qinfo, struct config_strlist* list,
|
|||
if(!qinfo->local_alias->rrset)
|
||||
return 0; /* out of memory */
|
||||
}
|
||||
if(r->rk.dname)
|
||||
return 1;
|
||||
return 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
/** answer local data match */
|
||||
|
|
@ -1497,8 +1506,6 @@ lz_type(uint8_t *taglist, size_t taglen, uint8_t *taglist2, size_t taglen2,
|
|||
struct comm_reply* repinfo, struct rbtree_type* override_tree,
|
||||
int* tag, char** tagname, int num_tags)
|
||||
{
|
||||
size_t i, j;
|
||||
uint8_t tagmatch;
|
||||
struct local_zone_override* lzo;
|
||||
if(repinfo && override_tree) {
|
||||
lzo = (struct local_zone_override*)addr_tree_lookup(
|
||||
|
|
@ -1511,6 +1518,19 @@ lz_type(uint8_t *taglist, size_t taglen, uint8_t *taglist2, size_t taglen2,
|
|||
}
|
||||
if(!taglist || !taglist2)
|
||||
return lzt;
|
||||
return local_data_find_tag_action(taglist, taglen, taglist2, taglen2,
|
||||
tagactions, tagactionssize, lzt, tag, tagname, num_tags);
|
||||
}
|
||||
|
||||
enum localzone_type
|
||||
local_data_find_tag_action(const uint8_t* taglist, size_t taglen,
|
||||
const uint8_t* taglist2, size_t taglen2, const uint8_t* tagactions,
|
||||
size_t tagactionssize, enum localzone_type lzt, int* tag,
|
||||
char* const* tagname, int num_tags)
|
||||
{
|
||||
size_t i, j;
|
||||
uint8_t tagmatch;
|
||||
|
||||
for(i=0; i<taglen && i<taglen2; i++) {
|
||||
tagmatch = (taglist[i] & taglist2[i]);
|
||||
for(j=0; j<8 && tagmatch>0; j++) {
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@
|
|||
#include "util/storage/dnstree.h"
|
||||
#include "util/module.h"
|
||||
#include "services/view.h"
|
||||
struct packed_rrset_data;
|
||||
struct ub_packed_rrset_key;
|
||||
struct regional;
|
||||
struct config_file;
|
||||
|
|
@ -389,4 +390,111 @@ void local_zones_del_data(struct local_zones* zones,
|
|||
*/
|
||||
int parse_dname(const char* str, uint8_t** res, size_t* len, int* labs);
|
||||
|
||||
/**
|
||||
* Find local data tag string match for the given type (in qinfo) in the list.
|
||||
* If found, 'r' will be filled with corresponding rrset information.
|
||||
* @param qinfo: contains name, type, and class for the data
|
||||
* @param list: stores local tag data to be searched
|
||||
* @param r: rrset key to be filled for matched data
|
||||
* @param temp: region to allocate rrset in 'r'
|
||||
* @return 1 if a match is found and rrset is built; otherwise 0 including
|
||||
* errors.
|
||||
*/
|
||||
int local_data_find_tag_datas(const struct query_info* qinfo,
|
||||
struct config_strlist* list, struct ub_packed_rrset_key* r,
|
||||
struct regional* temp);
|
||||
|
||||
/**
|
||||
* See if two sets of tag lists (in the form of bitmap) have the same tag that
|
||||
* has an action. If so, '*tag' will be set to the found tag index, and the
|
||||
* corresponding action will be returned in the form of local zone type.
|
||||
* Otherwise the passed type (lzt) will be returned as the default action.
|
||||
* Pointers except tagactions must not be NULL.
|
||||
* @param taglist: 1st list of tags
|
||||
* @param taglen: size of taglist in bytes
|
||||
* @param taglist2: 2nd list of tags
|
||||
* @param taglen2: size of taglist2 in bytes
|
||||
* @param tagactions: local data actions for tags. May be NULL.
|
||||
* @param tagactionssize: length of the tagactions.
|
||||
* @param lzt: default action (local zone type) if no tag action is found.
|
||||
* @param tag: see above.
|
||||
* @param tagname: array of tag name strings (for debug output).
|
||||
* @param num_tags: number of items in tagname array.
|
||||
* @return found tag action or the default action.
|
||||
*/
|
||||
enum localzone_type local_data_find_tag_action(const uint8_t* taglist,
|
||||
size_t taglen, const uint8_t* taglist2, size_t taglen2,
|
||||
const uint8_t* tagactions, size_t tagactionssize,
|
||||
enum localzone_type lzt, int* tag, char* const* tagname, int num_tags);
|
||||
|
||||
/**
|
||||
* Parses resource record string into wire format, also returning its field values.
|
||||
* @param str: input resource record
|
||||
* @param nm: domain name field
|
||||
* @param type: record type field
|
||||
* @param dclass: record class field
|
||||
* @param ttl: ttl field
|
||||
* @param rr: buffer for the parsed rr in wire format
|
||||
* @param len: buffer length
|
||||
* @param rdata: rdata field
|
||||
* @param rdata_len: rdata field length
|
||||
* @return 1 on success; 0 otherwise.
|
||||
*/
|
||||
int rrstr_get_rr_content(const char* str, uint8_t** nm, uint16_t* type,
|
||||
uint16_t* dclass, time_t* ttl, uint8_t* rr, size_t len,
|
||||
uint8_t** rdata, size_t* rdata_len);
|
||||
|
||||
/**
|
||||
* Insert specified rdata into the specified resource record.
|
||||
* @param region: allocator
|
||||
* @param pd: data portion of the destination resource record
|
||||
* @param rdata: source rdata
|
||||
* @param rdata_len: source rdata length
|
||||
* @param ttl: time to live
|
||||
* @param rrstr: resource record in text form (for logging)
|
||||
* @return 1 on success; 0 otherwise.
|
||||
*/
|
||||
int rrset_insert_rr(struct regional* region, struct packed_rrset_data* pd,
|
||||
uint8_t* rdata, size_t rdata_len, time_t ttl, const char* rrstr);
|
||||
|
||||
/**
|
||||
* Valid response ip actions for the IP-response-driven-action feature;
|
||||
* defined here instead of in the respip module to enable sharing of enum
|
||||
* values with the localzone_type enum.
|
||||
* Note that these values except 'none' are the same as localzone types of
|
||||
* the 'same semantics'. It's intentional as we use these values via
|
||||
* access-control-tags, which can be shared for both response ip actions and
|
||||
* local zones.
|
||||
*/
|
||||
enum respip_action {
|
||||
/** no respip action */
|
||||
respip_none = local_zone_unset,
|
||||
/** don't answer */
|
||||
respip_deny = local_zone_deny,
|
||||
/** redirect as per provided data */
|
||||
respip_redirect = local_zone_redirect,
|
||||
/** log query source and answer query */
|
||||
respip_inform = local_zone_inform,
|
||||
/** log query source and don't answer query */
|
||||
respip_inform_deny = local_zone_inform_deny,
|
||||
/** resolve normally, even when there is response-ip data */
|
||||
respip_always_transparent = local_zone_always_transparent,
|
||||
/** answer with 'refused' response */
|
||||
respip_always_refuse = local_zone_always_refuse,
|
||||
/** answer with 'no such domain' response */
|
||||
respip_always_nxdomain = local_zone_always_nxdomain,
|
||||
|
||||
/* The rest of the values are only possible as
|
||||
* access-control-tag-action */
|
||||
|
||||
/** serves response data (if any), else, drops queries. */
|
||||
respip_refuse = local_zone_refuse,
|
||||
/** serves response data, else, nodata answer. */
|
||||
respip_static = local_zone_static,
|
||||
/** gives response data (if any), else nodata answer. */
|
||||
respip_transparent = local_zone_transparent,
|
||||
/** gives response data (if any), else nodata answer. */
|
||||
respip_typetransparent = local_zone_typetransparent,
|
||||
};
|
||||
|
||||
#endif /* SERVICES_LOCALZONE_H */
|
||||
|
|
|
|||
144
services/mesh.c
144
services/mesh.c
|
|
@ -59,6 +59,7 @@
|
|||
#include "sldns/wire2str.h"
|
||||
#include "services/localzone.h"
|
||||
#include "util/data/dname.h"
|
||||
#include "respip/respip.h"
|
||||
|
||||
/** subtract timers and the values do not overflow or become negative */
|
||||
static void
|
||||
|
|
@ -124,11 +125,64 @@ timeval_smaller(const struct timeval* x, const struct timeval* y)
|
|||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Compare two response-ip client info entries for the purpose of mesh state
|
||||
* compare. It returns 0 if ci_a and ci_b are considered equal; otherwise
|
||||
* 1 or -1 (they mean 'ci_a is larger/smaller than ci_b', respectively, but
|
||||
* in practice it should be only used to mean they are different).
|
||||
* We cannot share the mesh state for two queries if different response-ip
|
||||
* actions can apply in the end, even if those queries are otherwise identical.
|
||||
* For this purpose we compare tag lists and tag action lists; they should be
|
||||
* identical to share the same state.
|
||||
* For tag data, we don't look into the data content, as it can be
|
||||
* expensive; unless tag data are not defined for both or they point to the
|
||||
* exact same data in memory (i.e., they come from the same ACL entry), we
|
||||
* consider these data different.
|
||||
* Likewise, if the client info is associated with views, we don't look into
|
||||
* the views. They are considered different unless they are exactly the same
|
||||
* even if the views only differ in the names.
|
||||
*/
|
||||
static int
|
||||
client_info_compare(const struct respip_client_info* ci_a,
|
||||
const struct respip_client_info* ci_b)
|
||||
{
|
||||
int cmp;
|
||||
|
||||
if(!ci_a && !ci_b)
|
||||
return 0;
|
||||
if(ci_a && !ci_b)
|
||||
return -1;
|
||||
if(!ci_a && ci_b)
|
||||
return 1;
|
||||
if(ci_a->taglen != ci_b->taglen)
|
||||
return (ci_a->taglen < ci_b->taglen) ? -1 : 1;
|
||||
cmp = memcmp(ci_a->taglist, ci_b->taglist, ci_a->taglen);
|
||||
if(cmp != 0)
|
||||
return cmp;
|
||||
if(ci_a->tag_actions_size != ci_b->tag_actions_size)
|
||||
return (ci_a->tag_actions_size < ci_b->tag_actions_size) ?
|
||||
-1 : 1;
|
||||
cmp = memcmp(ci_a->tag_actions, ci_b->tag_actions,
|
||||
ci_a->tag_actions_size);
|
||||
if(cmp != 0)
|
||||
return cmp;
|
||||
if(ci_a->tag_datas != ci_b->tag_datas)
|
||||
return ci_a->tag_datas < ci_b->tag_datas ? -1 : 1;
|
||||
if(ci_a->view != ci_b->view)
|
||||
return ci_a->view < ci_b->view ? -1 : 1;
|
||||
/* For the unbound daemon these should be non-NULL and identical,
|
||||
* but we check that just in case. */
|
||||
if(ci_a->respip_set != ci_b->respip_set)
|
||||
return ci_a->respip_set < ci_b->respip_set ? -1 : 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
mesh_state_compare(const void* ap, const void* bp)
|
||||
{
|
||||
struct mesh_state* a = (struct mesh_state*)ap;
|
||||
struct mesh_state* b = (struct mesh_state*)bp;
|
||||
int cmp;
|
||||
|
||||
if(a->unique < b->unique)
|
||||
return -1;
|
||||
|
|
@ -155,7 +209,10 @@ mesh_state_compare(const void* ap, const void* bp)
|
|||
if(!(a->s.query_flags&BIT_CD) && (b->s.query_flags&BIT_CD))
|
||||
return 1;
|
||||
|
||||
return query_info_compare(&a->s.qinfo, &b->s.qinfo);
|
||||
cmp = query_info_compare(&a->s.qinfo, &b->s.qinfo);
|
||||
if(cmp != 0)
|
||||
return cmp;
|
||||
return client_info_compare(a->s.client_info, b->s.client_info);
|
||||
}
|
||||
|
||||
int
|
||||
|
|
@ -287,16 +344,16 @@ int mesh_make_new_space(struct mesh_area* mesh, sldns_buffer* qbuf)
|
|||
}
|
||||
|
||||
void mesh_new_client(struct mesh_area* mesh, struct query_info* qinfo,
|
||||
uint16_t qflags, struct edns_data* edns, struct comm_reply* rep,
|
||||
uint16_t qid)
|
||||
struct respip_client_info* cinfo, uint16_t qflags,
|
||||
struct edns_data* edns, struct comm_reply* rep, uint16_t qid)
|
||||
{
|
||||
struct mesh_state* s = NULL;
|
||||
int unique = edns_unique_mesh_state(edns->opt_list, mesh->env);
|
||||
int unique = unique_mesh_state(edns->opt_list, mesh->env);
|
||||
int was_detached = 0;
|
||||
int was_noreply = 0;
|
||||
int added = 0;
|
||||
if(!unique)
|
||||
s = mesh_area_find(mesh, qinfo, qflags&(BIT_RD|BIT_CD), 0, 0);
|
||||
s = mesh_area_find(mesh, cinfo, qinfo, qflags&(BIT_RD|BIT_CD), 0, 0);
|
||||
/* does this create a new reply state? */
|
||||
if(!s || s->list_select == mesh_no_list) {
|
||||
if(!mesh_make_new_space(mesh, rep->c->buffer)) {
|
||||
|
|
@ -323,7 +380,8 @@ void mesh_new_client(struct mesh_area* mesh, struct query_info* qinfo,
|
|||
#ifdef UNBOUND_DEBUG
|
||||
struct rbnode_type* n;
|
||||
#endif
|
||||
s = mesh_state_create(mesh->env, qinfo, qflags&(BIT_RD|BIT_CD), 0, 0);
|
||||
s = mesh_state_create(mesh->env, qinfo, cinfo,
|
||||
qflags&(BIT_RD|BIT_CD), 0, 0);
|
||||
if(!s) {
|
||||
log_err("mesh_state_create: out of memory; SERVFAIL");
|
||||
if(!inplace_cb_reply_servfail_call(mesh->env, qinfo, NULL, NULL,
|
||||
|
|
@ -412,12 +470,13 @@ mesh_new_callback(struct mesh_area* mesh, struct query_info* qinfo,
|
|||
uint16_t qid, mesh_cb_func_type cb, void* cb_arg)
|
||||
{
|
||||
struct mesh_state* s = NULL;
|
||||
int unique = edns_unique_mesh_state(edns->opt_list, mesh->env);
|
||||
int unique = unique_mesh_state(edns->opt_list, mesh->env);
|
||||
int was_detached = 0;
|
||||
int was_noreply = 0;
|
||||
int added = 0;
|
||||
if(!unique)
|
||||
s = mesh_area_find(mesh, qinfo, qflags&(BIT_RD|BIT_CD), 0, 0);
|
||||
s = mesh_area_find(mesh, NULL, qinfo, qflags&(BIT_RD|BIT_CD), 0, 0);
|
||||
|
||||
/* there are no limits on the number of callbacks */
|
||||
|
||||
/* see if it already exists, if not, create one */
|
||||
|
|
@ -425,7 +484,8 @@ mesh_new_callback(struct mesh_area* mesh, struct query_info* qinfo,
|
|||
#ifdef UNBOUND_DEBUG
|
||||
struct rbnode_type* n;
|
||||
#endif
|
||||
s = mesh_state_create(mesh->env, qinfo, qflags&(BIT_RD|BIT_CD), 0, 0);
|
||||
s = mesh_state_create(mesh->env, qinfo, NULL,
|
||||
qflags&(BIT_RD|BIT_CD), 0, 0);
|
||||
if(!s) {
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -476,8 +536,8 @@ mesh_new_callback(struct mesh_area* mesh, struct query_info* qinfo,
|
|||
void mesh_new_prefetch(struct mesh_area* mesh, struct query_info* qinfo,
|
||||
uint16_t qflags, time_t leeway)
|
||||
{
|
||||
struct mesh_state* s = mesh_area_find(mesh, qinfo, qflags&(BIT_RD|BIT_CD),
|
||||
0, 0);
|
||||
struct mesh_state* s = mesh_area_find(mesh, NULL, qinfo,
|
||||
qflags&(BIT_RD|BIT_CD), 0, 0);
|
||||
#ifdef UNBOUND_DEBUG
|
||||
struct rbnode_type* n;
|
||||
#endif
|
||||
|
|
@ -497,7 +557,8 @@ void mesh_new_prefetch(struct mesh_area* mesh, struct query_info* qinfo,
|
|||
return;
|
||||
}
|
||||
|
||||
s = mesh_state_create(mesh->env, qinfo, qflags&(BIT_RD|BIT_CD), 0, 0);
|
||||
s = mesh_state_create(mesh->env, qinfo, NULL,
|
||||
qflags&(BIT_RD|BIT_CD), 0, 0);
|
||||
if(!s) {
|
||||
log_err("prefetch mesh_state_create: out of memory");
|
||||
return;
|
||||
|
|
@ -546,7 +607,8 @@ void mesh_report_reply(struct mesh_area* mesh, struct outbound_entry* e,
|
|||
|
||||
struct mesh_state*
|
||||
mesh_state_create(struct module_env* env, struct query_info* qinfo,
|
||||
uint16_t qflags, int prime, int valrec)
|
||||
struct respip_client_info* cinfo, uint16_t qflags, int prime,
|
||||
int valrec)
|
||||
{
|
||||
struct regional* region = alloc_reg_obtain(env->alloc);
|
||||
struct mesh_state* mstate;
|
||||
|
|
@ -582,6 +644,14 @@ mesh_state_create(struct module_env* env, struct query_info* qinfo,
|
|||
alloc_reg_release(env->alloc, region);
|
||||
return NULL;
|
||||
}
|
||||
if(cinfo) {
|
||||
mstate->s.client_info = regional_alloc_init(region, cinfo,
|
||||
sizeof(*cinfo));
|
||||
if(!mstate->s.client_info) {
|
||||
alloc_reg_release(env->alloc, region);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
/* remove all weird bits from qflags */
|
||||
mstate->s.query_flags = (qflags & (BIT_RD|BIT_CD));
|
||||
mstate->s.is_priming = prime;
|
||||
|
|
@ -756,7 +826,8 @@ int mesh_attach_sub(struct module_qstate* qstate, struct query_info* qinfo,
|
|||
{
|
||||
/* find it, if not, create it */
|
||||
struct mesh_area* mesh = qstate->env->mesh;
|
||||
struct mesh_state* sub = mesh_area_find(mesh, qinfo, qflags, prime, valrec);
|
||||
struct mesh_state* sub = mesh_area_find(mesh, NULL, qinfo, qflags,
|
||||
prime, valrec);
|
||||
int was_detached;
|
||||
if(mesh_detect_cycle_found(qstate, sub)) {
|
||||
verbose(VERB_ALGO, "attach failed, cycle detected");
|
||||
|
|
@ -767,7 +838,8 @@ int mesh_attach_sub(struct module_qstate* qstate, struct query_info* qinfo,
|
|||
struct rbnode_type* n;
|
||||
#endif
|
||||
/* create a new one */
|
||||
sub = mesh_state_create(qstate->env, qinfo, qflags, prime, valrec);
|
||||
sub = mesh_state_create(qstate->env, qinfo, NULL, qflags, prime,
|
||||
valrec);
|
||||
if(!sub) {
|
||||
log_err("mesh_attach_sub: out of memory");
|
||||
return 0;
|
||||
|
|
@ -1035,8 +1107,25 @@ void mesh_query_done(struct mesh_state* mstate)
|
|||
struct reply_info* rep = (mstate->s.return_msg?
|
||||
mstate->s.return_msg->rep:NULL);
|
||||
for(r = mstate->reply_list; r; r = r->next) {
|
||||
mesh_send_reply(mstate, mstate->s.return_rcode, rep, r, prev);
|
||||
prev = r;
|
||||
/* if a response-ip address block has been stored the
|
||||
* information should be logged for each client. */
|
||||
if(mstate->s.respip_action_info &&
|
||||
mstate->s.respip_action_info->addrinfo) {
|
||||
respip_inform_print(mstate->s.respip_action_info->addrinfo,
|
||||
r->qname, mstate->s.qinfo.qtype,
|
||||
mstate->s.qinfo.qclass, r->local_alias,
|
||||
&r->query_reply);
|
||||
}
|
||||
|
||||
/* if this query is determined to be dropped during the
|
||||
* mesh processing, this is the point to take that action. */
|
||||
if(mstate->s.is_drop)
|
||||
comm_point_drop_reply(&r->query_reply);
|
||||
else {
|
||||
mesh_send_reply(mstate, mstate->s.return_rcode, rep,
|
||||
r, prev);
|
||||
prev = r;
|
||||
}
|
||||
}
|
||||
mstate->replies_sent = 1;
|
||||
for(c = mstate->cb_list; c; c = c->next) {
|
||||
|
|
@ -1060,7 +1149,8 @@ void mesh_walk_supers(struct mesh_area* mesh, struct mesh_state* mstate)
|
|||
}
|
||||
|
||||
struct mesh_state* mesh_area_find(struct mesh_area* mesh,
|
||||
struct query_info* qinfo, uint16_t qflags, int prime, int valrec)
|
||||
struct respip_client_info* cinfo, struct query_info* qinfo,
|
||||
uint16_t qflags, int prime, int valrec)
|
||||
{
|
||||
struct mesh_state key;
|
||||
struct mesh_state* result;
|
||||
|
|
@ -1074,6 +1164,7 @@ struct mesh_state* mesh_area_find(struct mesh_area* mesh,
|
|||
* aggregate the state. Thus unique is set to NULL. (default when we
|
||||
* desire aggregation).*/
|
||||
key.unique = NULL;
|
||||
key.s.client_info = cinfo;
|
||||
|
||||
result = (struct mesh_state*)rbtree_search(&mesh->all, &key);
|
||||
return result;
|
||||
|
|
@ -1224,11 +1315,16 @@ mesh_continue(struct mesh_area* mesh, struct mesh_state* mstate,
|
|||
return mesh_continue(mesh, mstate, module_error, ev);
|
||||
}
|
||||
if(s == module_restart_next) {
|
||||
fptr_ok(fptr_whitelist_mod_clear(
|
||||
mesh->mods.mod[mstate->s.curmod]->clear));
|
||||
(*mesh->mods.mod[mstate->s.curmod]->clear)
|
||||
(&mstate->s, mstate->s.curmod);
|
||||
mstate->s.minfo[mstate->s.curmod] = NULL;
|
||||
int curmod = mstate->s.curmod;
|
||||
for(; mstate->s.curmod < mesh->mods.num;
|
||||
mstate->s.curmod++) {
|
||||
fptr_ok(fptr_whitelist_mod_clear(
|
||||
mesh->mods.mod[mstate->s.curmod]->clear));
|
||||
(*mesh->mods.mod[mstate->s.curmod]->clear)
|
||||
(&mstate->s, mstate->s.curmod);
|
||||
mstate->s.minfo[mstate->s.curmod] = NULL;
|
||||
}
|
||||
mstate->s.curmod = curmod;
|
||||
}
|
||||
*ev = module_event_pass;
|
||||
return 1;
|
||||
|
|
@ -1378,7 +1474,7 @@ mesh_detect_cycle(struct module_qstate* qstate, struct query_info* qinfo,
|
|||
struct mesh_area* mesh = qstate->env->mesh;
|
||||
struct mesh_state* dep_m = NULL;
|
||||
if(!mesh_state_is_unique(qstate->mesh_info))
|
||||
dep_m = mesh_area_find(mesh, qinfo, flags, prime, valrec);
|
||||
dep_m = mesh_area_find(mesh, NULL, qinfo, flags, prime, valrec);
|
||||
return mesh_detect_cycle_found(qstate, dep_m);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -59,6 +59,7 @@ struct query_info;
|
|||
struct reply_info;
|
||||
struct outbound_entry;
|
||||
struct timehist;
|
||||
struct respip_client_info;
|
||||
|
||||
/**
|
||||
* Maximum number of mesh state activations. Any more is likely an
|
||||
|
|
@ -274,14 +275,18 @@ void mesh_delete(struct mesh_area* mesh);
|
|||
*
|
||||
* @param mesh: the mesh.
|
||||
* @param qinfo: query from client.
|
||||
* @param cinfo: additional information associated with the query client.
|
||||
* 'cinfo' itself is ephemeral but data pointed to by its members
|
||||
* can be assumed to be valid and unchanged until the query processing is
|
||||
* completed.
|
||||
* @param qflags: flags from client query.
|
||||
* @param edns: edns data from client query.
|
||||
* @param rep: where to reply to.
|
||||
* @param qid: query id to reply with.
|
||||
*/
|
||||
void mesh_new_client(struct mesh_area* mesh, struct query_info* qinfo,
|
||||
uint16_t qflags, struct edns_data* edns, struct comm_reply* rep,
|
||||
uint16_t qid);
|
||||
struct respip_client_info* cinfo, uint16_t qflags,
|
||||
struct edns_data* edns, struct comm_reply* rep, uint16_t qid);
|
||||
|
||||
/**
|
||||
* New query with callback. Create new query state if needed, and
|
||||
|
|
@ -409,14 +414,16 @@ void mesh_state_delete(struct module_qstate* qstate);
|
|||
* Does not put the mesh state into rbtrees and so on.
|
||||
* @param env: module environment to set.
|
||||
* @param qinfo: query info that the mesh is for.
|
||||
* @param cinfo: control info for the query client (can be NULL).
|
||||
* @param qflags: flags for query (RD / CD flag).
|
||||
* @param prime: if true, it is a priming query, set is_priming on mesh state.
|
||||
* @param valrec: if true, it is a validation recursion query, and sets
|
||||
* is_valrec on the mesh state.
|
||||
* @return: new mesh state or NULL on allocation error.
|
||||
*/
|
||||
struct mesh_state* mesh_state_create(struct module_env* env,
|
||||
struct query_info* qinfo, uint16_t qflags, int prime, int valrec);
|
||||
struct mesh_state* mesh_state_create(struct module_env* env,
|
||||
struct query_info* qinfo, struct respip_client_info* cinfo,
|
||||
uint16_t qflags, int prime, int valrec);
|
||||
|
||||
/**
|
||||
* Check if the mesh state is unique.
|
||||
|
|
@ -451,14 +458,17 @@ void mesh_delete_all(struct mesh_area* mesh);
|
|||
* Find a mesh state in the mesh area. Pass relevant flags.
|
||||
*
|
||||
* @param mesh: the mesh area to look in.
|
||||
* @param cinfo: if non-NULL client specific info that may affect IP-based
|
||||
* actions that apply to the query result.
|
||||
* @param qinfo: what query
|
||||
* @param qflags: if RD / CD bit is set or not.
|
||||
* @param prime: if it is a priming query.
|
||||
* @param valrec: if it is a validation-recursion query.
|
||||
* @return: mesh state or NULL if not found.
|
||||
*/
|
||||
struct mesh_state* mesh_area_find(struct mesh_area* mesh,
|
||||
struct query_info* qinfo, uint16_t qflags, int prime, int valrec);
|
||||
struct mesh_state* mesh_area_find(struct mesh_area* mesh,
|
||||
struct respip_client_info* cinfo, struct query_info* qinfo,
|
||||
uint16_t qflags, int prime, int valrec);
|
||||
|
||||
/**
|
||||
* Setup attachment super/sub relation between super and sub mesh state.
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@
|
|||
#include "dns64/dns64.h"
|
||||
#include "iterator/iterator.h"
|
||||
#include "validator/validator.h"
|
||||
#include "respip/respip.h"
|
||||
|
||||
#ifdef WITH_PYTHONMODULE
|
||||
#include "pythonmod/pythonmod.h"
|
||||
|
|
@ -53,6 +54,9 @@
|
|||
#ifdef USE_CACHEDB
|
||||
#include "cachedb/cachedb.h"
|
||||
#endif
|
||||
#ifdef CLIENT_SUBNET
|
||||
#include "edns-subnet/subnetmod.h"
|
||||
#endif
|
||||
|
||||
/** count number of modules (words) in the string */
|
||||
static int
|
||||
|
|
@ -127,6 +131,10 @@ module_list_avail(void)
|
|||
#ifdef USE_CACHEDB
|
||||
"cachedb",
|
||||
#endif
|
||||
#ifdef CLIENT_SUBNET
|
||||
"subnetcache",
|
||||
#endif
|
||||
"respip",
|
||||
"validator",
|
||||
"iterator",
|
||||
NULL};
|
||||
|
|
@ -148,6 +156,10 @@ module_funcs_avail(void)
|
|||
#ifdef USE_CACHEDB
|
||||
&cachedb_get_funcblock,
|
||||
#endif
|
||||
#ifdef CLIENT_SUBNET
|
||||
&subnetmod_get_funcblock,
|
||||
#endif
|
||||
&respip_get_funcblock,
|
||||
&val_get_funcblock,
|
||||
&iter_get_funcblock,
|
||||
NULL};
|
||||
|
|
@ -216,7 +228,7 @@ int
|
|||
modstack_find(struct module_stack* stack, const char* name)
|
||||
{
|
||||
int i;
|
||||
for(i=0; i<stack->num; i++) {
|
||||
for(i=0; i<stack->num; i++) {
|
||||
if(strcmp(stack->mod[i]->name, name) == 0)
|
||||
return i;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -66,6 +66,10 @@ views_create(void)
|
|||
return v;
|
||||
}
|
||||
|
||||
/** This prototype is defined in in respip.h, but we want to avoid
|
||||
* unnecessary dependencies */
|
||||
void respip_set_delete(struct respip_set *set);
|
||||
|
||||
void
|
||||
view_delete(struct view* v)
|
||||
{
|
||||
|
|
@ -73,6 +77,7 @@ view_delete(struct view* v)
|
|||
return;
|
||||
lock_rw_destroy(&v->lock);
|
||||
local_zones_delete(v->local_zones);
|
||||
respip_set_delete(v->respip_set);
|
||||
free(v->name);
|
||||
free(v);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@
|
|||
struct regional;
|
||||
struct config_file;
|
||||
struct config_view;
|
||||
struct respip_set;
|
||||
|
||||
|
||||
/**
|
||||
|
|
@ -71,6 +72,8 @@ struct view {
|
|||
char* name;
|
||||
/** view specific local authority zones */
|
||||
struct local_zones* local_zones;
|
||||
/** response-ip configuration data for this view */
|
||||
struct respip_set* respip_set;
|
||||
/** Fallback to global local_zones when there is no match in the view
|
||||
* specific tree. 1 for yes, 0 for no */
|
||||
int isfirst;
|
||||
|
|
|
|||
|
|
@ -372,6 +372,8 @@ enum sldns_enum_algorithm
|
|||
LDNS_ECC_GOST = 12, /* RFC 5933 */
|
||||
LDNS_ECDSAP256SHA256 = 13, /* RFC 6605 */
|
||||
LDNS_ECDSAP384SHA384 = 14, /* RFC 6605 */
|
||||
LDNS_ED25519 = 15, /* RFC 8080 */
|
||||
LDNS_ED448 = 16, /* RFC 8080 */
|
||||
LDNS_INDIRECT = 252,
|
||||
LDNS_PRIVATEDNS = 253,
|
||||
LDNS_PRIVATEOID = 254
|
||||
|
|
@ -420,7 +422,8 @@ enum sldns_enum_edns_option
|
|||
LDNS_EDNS_DAU = 5, /* RFC6975 */
|
||||
LDNS_EDNS_DHU = 6, /* RFC6975 */
|
||||
LDNS_EDNS_N3U = 7, /* RFC6975 */
|
||||
LDNS_EDNS_CLIENT_SUBNET = 8, /* draft-vandergaast-edns-client-subnet */
|
||||
LDNS_EDNS_CLIENT_SUBNET = 8, /* RFC7871 */
|
||||
LDNS_EDNS_KEEPALIVE = 11, /* draft-ietf-dnsop-edns-tcp-keepalive*/
|
||||
LDNS_EDNS_PADDING = 12 /* RFC7830 */
|
||||
};
|
||||
typedef enum sldns_enum_edns_option sldns_edns_option;
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ sldns_buffer_new(size_t capacity)
|
|||
buffer->_position = 0;
|
||||
buffer->_limit = buffer->_capacity = capacity;
|
||||
buffer->_fixed = 0;
|
||||
buffer->_vfixed = 0;
|
||||
buffer->_status_err = 0;
|
||||
|
||||
sldns_buffer_invariant(buffer);
|
||||
|
|
@ -48,6 +49,7 @@ sldns_buffer_new_frm_data(sldns_buffer *buffer, void *data, size_t size)
|
|||
buffer->_position = 0;
|
||||
buffer->_limit = buffer->_capacity = size;
|
||||
buffer->_fixed = 0;
|
||||
buffer->_vfixed = 0;
|
||||
buffer->_data = malloc(size);
|
||||
if(!buffer->_data) {
|
||||
buffer->_status_err = 1;
|
||||
|
|
@ -66,6 +68,17 @@ sldns_buffer_init_frm_data(sldns_buffer *buffer, void *data, size_t size)
|
|||
buffer->_data = data;
|
||||
buffer->_capacity = buffer->_limit = size;
|
||||
buffer->_fixed = 1;
|
||||
buffer->_vfixed = 0;
|
||||
}
|
||||
|
||||
void
|
||||
sldns_buffer_init_vfixed_frm_data(sldns_buffer *buffer, void *data, size_t size)
|
||||
{
|
||||
memset(buffer, 0, sizeof(*buffer));
|
||||
buffer->_data = data;
|
||||
buffer->_capacity = buffer->_limit = size;
|
||||
buffer->_fixed = 1;
|
||||
buffer->_vfixed = 1;
|
||||
}
|
||||
|
||||
int
|
||||
|
|
@ -74,7 +87,7 @@ sldns_buffer_set_capacity(sldns_buffer *buffer, size_t capacity)
|
|||
void *data;
|
||||
|
||||
sldns_buffer_invariant(buffer);
|
||||
assert(buffer->_position <= capacity);
|
||||
assert(buffer->_position <= capacity && !buffer->_fixed);
|
||||
|
||||
data = (uint8_t *) realloc(buffer->_data, capacity);
|
||||
if (!data) {
|
||||
|
|
@ -126,7 +139,7 @@ sldns_buffer_printf(sldns_buffer *buffer, const char *format, ...)
|
|||
if (written == -1) {
|
||||
buffer->_status_err = 1;
|
||||
return -1;
|
||||
} else if ((size_t) written >= remaining) {
|
||||
} else if (!buffer->_vfixed && (size_t) written >= remaining) {
|
||||
if (!sldns_buffer_reserve(buffer, (size_t) written + 1)) {
|
||||
buffer->_status_err = 1;
|
||||
return -1;
|
||||
|
|
|
|||
114
sldns/sbuffer.h
114
sldns/sbuffer.h
|
|
@ -87,6 +87,19 @@ sldns_write_uint32(void *dst, uint32_t data)
|
|||
}
|
||||
|
||||
|
||||
INLINE void
|
||||
sldns_write_uint48(void *dst, uint64_t data)
|
||||
{
|
||||
uint8_t *p = (uint8_t *) dst;
|
||||
p[0] = (uint8_t) ((data >> 40) & 0xff);
|
||||
p[1] = (uint8_t) ((data >> 32) & 0xff);
|
||||
p[2] = (uint8_t) ((data >> 24) & 0xff);
|
||||
p[3] = (uint8_t) ((data >> 16) & 0xff);
|
||||
p[4] = (uint8_t) ((data >> 8) & 0xff);
|
||||
p[5] = (uint8_t) (data & 0xff);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* \file sbuffer.h
|
||||
*
|
||||
|
|
@ -117,6 +130,17 @@ struct sldns_buffer
|
|||
/** If the buffer is fixed it cannot be resized */
|
||||
unsigned _fixed : 1;
|
||||
|
||||
/** If the buffer is vfixed, no more than capacity bytes willl be
|
||||
* written to _data, however the _position counter will be updated
|
||||
* with the amount that would have been written in consecutive
|
||||
* writes. This allows for a modus operandi in which a sequence is
|
||||
* written on a fixed capacity buffer (perhaps with _data on stack).
|
||||
* When everything could be written, then the _data is immediately
|
||||
* usable, if not, then a buffer could be allocated sized precisely
|
||||
* to fit the data for a second attempt.
|
||||
*/
|
||||
unsigned _vfixed : 1;
|
||||
|
||||
/** The current state of the buffer. If writing to the buffer fails
|
||||
* for any reason, this value is changed. This way, you can perform
|
||||
* multiple writes in sequence and check for success afterwards. */
|
||||
|
|
@ -134,9 +158,9 @@ INLINE void
|
|||
sldns_buffer_invariant(sldns_buffer *buffer)
|
||||
{
|
||||
assert(buffer != NULL);
|
||||
assert(buffer->_position <= buffer->_limit);
|
||||
assert(buffer->_position <= buffer->_limit || buffer->_vfixed);
|
||||
assert(buffer->_limit <= buffer->_capacity);
|
||||
assert(buffer->_data != NULL);
|
||||
assert(buffer->_data != NULL || (buffer->_vfixed && buffer->_capacity == 0));
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
@ -168,6 +192,19 @@ void sldns_buffer_new_frm_data(sldns_buffer *buffer, void *data, size_t size);
|
|||
*/
|
||||
void sldns_buffer_init_frm_data(sldns_buffer *buffer, void *data, size_t size);
|
||||
|
||||
/**
|
||||
* Setup a buffer with the data pointed to. No data copied, no memory allocs.
|
||||
* The buffer is "virtually" fixed. Writes beyond size (the capacity) will
|
||||
* only update position, but no data will be written beyond capacity. This
|
||||
* allows to determine how big the buffer should have been to contain all the
|
||||
* written data, by looking at the position with sldns_buffer_position(),
|
||||
* similarly to the return value of POSIX's snprintf.
|
||||
* \param[in] buffer pointer to the buffer to put the data in
|
||||
* \param[in] data the data to encapsulate in the buffer
|
||||
* \param[in] size the size of the data
|
||||
*/
|
||||
void sldns_buffer_init_vfixed_frm_data(sldns_buffer *buffer, void *data, size_t size);
|
||||
|
||||
/**
|
||||
* clears the buffer and make it ready for writing. The buffer's limit
|
||||
* is set to the capacity and the position is set to 0.
|
||||
|
|
@ -231,7 +268,7 @@ sldns_buffer_position(sldns_buffer *buffer)
|
|||
INLINE void
|
||||
sldns_buffer_set_position(sldns_buffer *buffer, size_t mark)
|
||||
{
|
||||
assert(mark <= buffer->_limit);
|
||||
assert(mark <= buffer->_limit || buffer->_vfixed);
|
||||
buffer->_position = mark;
|
||||
}
|
||||
|
||||
|
|
@ -245,7 +282,7 @@ sldns_buffer_set_position(sldns_buffer *buffer, size_t mark)
|
|||
INLINE void
|
||||
sldns_buffer_skip(sldns_buffer *buffer, ssize_t count)
|
||||
{
|
||||
assert(buffer->_position + count <= buffer->_limit);
|
||||
assert(buffer->_position + count <= buffer->_limit || buffer->_vfixed);
|
||||
buffer->_position += count;
|
||||
}
|
||||
|
||||
|
|
@ -317,7 +354,7 @@ int sldns_buffer_reserve(sldns_buffer *buffer, size_t amount);
|
|||
INLINE uint8_t *
|
||||
sldns_buffer_at(const sldns_buffer *buffer, size_t at)
|
||||
{
|
||||
assert(at <= buffer->_limit);
|
||||
assert(at <= buffer->_limit || buffer->_vfixed);
|
||||
return buffer->_data + at;
|
||||
}
|
||||
|
||||
|
|
@ -367,8 +404,8 @@ INLINE size_t
|
|||
sldns_buffer_remaining_at(sldns_buffer *buffer, size_t at)
|
||||
{
|
||||
sldns_buffer_invariant(buffer);
|
||||
assert(at <= buffer->_limit);
|
||||
return buffer->_limit - at;
|
||||
assert(at <= buffer->_limit || buffer->_vfixed);
|
||||
return at < buffer->_limit ? buffer->_limit - at : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -420,10 +457,42 @@ sldns_buffer_available(sldns_buffer *buffer, size_t count)
|
|||
INLINE void
|
||||
sldns_buffer_write_at(sldns_buffer *buffer, size_t at, const void *data, size_t count)
|
||||
{
|
||||
assert(sldns_buffer_available_at(buffer, at, count));
|
||||
if (!buffer->_vfixed)
|
||||
assert(sldns_buffer_available_at(buffer, at, count));
|
||||
else if (sldns_buffer_remaining_at(buffer, at) == 0)
|
||||
return;
|
||||
else if (count > sldns_buffer_remaining_at(buffer, at)) {
|
||||
memcpy(buffer->_data + at, data,
|
||||
sldns_buffer_remaining_at(buffer, at));
|
||||
return;
|
||||
}
|
||||
memcpy(buffer->_data + at, data, count);
|
||||
}
|
||||
|
||||
/**
|
||||
* set the given byte to the buffer at the specified position
|
||||
* \param[in] buffer the buffer
|
||||
* \param[in] at the position (in number of bytes) to write the data at
|
||||
* \param[in] c the byte to set to the buffer
|
||||
* \param[in] count the number of bytes of bytes to write
|
||||
*/
|
||||
|
||||
INLINE void
|
||||
sldns_buffer_set_at(sldns_buffer *buffer, size_t at, int c, size_t count)
|
||||
{
|
||||
if (!buffer->_vfixed)
|
||||
assert(sldns_buffer_available_at(buffer, at, count));
|
||||
else if (sldns_buffer_remaining_at(buffer, at) == 0)
|
||||
return;
|
||||
else if (count > sldns_buffer_remaining_at(buffer, at)) {
|
||||
memset(buffer->_data + at, c,
|
||||
sldns_buffer_remaining_at(buffer, at));
|
||||
return;
|
||||
}
|
||||
memset(buffer->_data + at, c, count);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* writes count bytes of data to the current position of the buffer
|
||||
* \param[in] buffer the buffer
|
||||
|
|
@ -469,6 +538,7 @@ sldns_buffer_write_string(sldns_buffer *buffer, const char *str)
|
|||
INLINE void
|
||||
sldns_buffer_write_u8_at(sldns_buffer *buffer, size_t at, uint8_t data)
|
||||
{
|
||||
if (buffer->_vfixed && at + sizeof(data) > buffer->_limit) return;
|
||||
assert(sldns_buffer_available_at(buffer, at, sizeof(data)));
|
||||
buffer->_data[at] = data;
|
||||
}
|
||||
|
|
@ -494,6 +564,7 @@ sldns_buffer_write_u8(sldns_buffer *buffer, uint8_t data)
|
|||
INLINE void
|
||||
sldns_buffer_write_u16_at(sldns_buffer *buffer, size_t at, uint16_t data)
|
||||
{
|
||||
if (buffer->_vfixed && at + sizeof(data) > buffer->_limit) return;
|
||||
assert(sldns_buffer_available_at(buffer, at, sizeof(data)));
|
||||
sldns_write_uint16(buffer->_data + at, data);
|
||||
}
|
||||
|
|
@ -519,10 +590,25 @@ sldns_buffer_write_u16(sldns_buffer *buffer, uint16_t data)
|
|||
INLINE void
|
||||
sldns_buffer_write_u32_at(sldns_buffer *buffer, size_t at, uint32_t data)
|
||||
{
|
||||
if (buffer->_vfixed && at + sizeof(data) > buffer->_limit) return;
|
||||
assert(sldns_buffer_available_at(buffer, at, sizeof(data)));
|
||||
sldns_write_uint32(buffer->_data + at, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* writes the given 6 byte integer at the given position in the buffer
|
||||
* \param[in] buffer the buffer
|
||||
* \param[in] at the position in the buffer
|
||||
* \param[in] data the (lower) 48 bits to write
|
||||
*/
|
||||
INLINE void
|
||||
sldns_buffer_write_u48_at(sldns_buffer *buffer, size_t at, uint64_t data)
|
||||
{
|
||||
if (buffer->_vfixed && at + 6 > buffer->_limit) return;
|
||||
assert(sldns_buffer_available_at(buffer, at, 6));
|
||||
sldns_write_uint48(buffer->_data + at, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* writes the given 4 byte integer at the current position in the buffer
|
||||
* \param[in] buffer the buffer
|
||||
|
|
@ -535,6 +621,18 @@ sldns_buffer_write_u32(sldns_buffer *buffer, uint32_t data)
|
|||
buffer->_position += sizeof(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* writes the given 6 byte integer at the current position in the buffer
|
||||
* \param[in] buffer the buffer
|
||||
* \param[in] data the 48 bits to write
|
||||
*/
|
||||
INLINE void
|
||||
sldns_buffer_write_u48(sldns_buffer *buffer, uint64_t data)
|
||||
{
|
||||
sldns_buffer_write_u48_at(buffer, buffer->_position, data);
|
||||
buffer->_position += 6;
|
||||
}
|
||||
|
||||
/**
|
||||
* copies count bytes of data at the given position to the given data-array
|
||||
* \param[in] buffer the buffer
|
||||
|
|
|
|||
|
|
@ -47,6 +47,8 @@ static sldns_lookup_table sldns_algorithms_data[] = {
|
|||
{ LDNS_ECC_GOST, "ECC-GOST"},
|
||||
{ LDNS_ECDSAP256SHA256, "ECDSAP256SHA256"},
|
||||
{ LDNS_ECDSAP384SHA384, "ECDSAP384SHA384"},
|
||||
{ LDNS_ED25519, "ED25519"},
|
||||
{ LDNS_ED448, "ED448"},
|
||||
{ LDNS_INDIRECT, "INDIRECT" },
|
||||
{ LDNS_PRIVATEDNS, "PRIVATEDNS" },
|
||||
{ LDNS_PRIVATEOID, "PRIVATEOID" },
|
||||
|
|
@ -165,6 +167,7 @@ static sldns_lookup_table sldns_edns_options_data[] = {
|
|||
{ 6, "DHU" },
|
||||
{ 7, "N3U" },
|
||||
{ 8, "edns-client-subnet" },
|
||||
{ 11, "edns-tcp-keepalive"},
|
||||
{ 12, "Padding" },
|
||||
{ 0, NULL}
|
||||
};
|
||||
|
|
@ -270,6 +273,12 @@ int sldns_wire2str_rcode_buf(int rcode, char* s, size_t slen)
|
|||
return sldns_wire2str_rcode_print(&s, &slen, rcode);
|
||||
}
|
||||
|
||||
int sldns_wire2str_opcode_buf(int opcode, char* s, size_t slen)
|
||||
{
|
||||
/* use arguments as temporary variables */
|
||||
return sldns_wire2str_opcode_print(&s, &slen, opcode);
|
||||
}
|
||||
|
||||
int sldns_wire2str_dname_buf(uint8_t* d, size_t dlen, char* s, size_t slen)
|
||||
{
|
||||
/* use arguments as temporary variables */
|
||||
|
|
@ -1838,6 +1847,25 @@ int sldns_wire2str_edns_subnet_print(char** s, size_t* sl, uint8_t* data,
|
|||
return w;
|
||||
}
|
||||
|
||||
int sldns_wire2str_edns_keepalive_print(char** s, size_t* sl, uint8_t* data,
|
||||
size_t len)
|
||||
{
|
||||
int w = 0;
|
||||
uint16_t timeout;
|
||||
if(!(len == 0 || len == 2)) {
|
||||
w += sldns_str_print(s, sl, "malformed keepalive ");
|
||||
w += print_hex_buf(s, sl, data, len);
|
||||
return w;
|
||||
}
|
||||
if(len == 0 ) {
|
||||
w += sldns_str_print(s, sl, "no timeout value (only valid for client option) ");
|
||||
} else {
|
||||
timeout = sldns_read_uint16(data);
|
||||
w += sldns_str_print(s, sl, "timeout value in units of 100ms %u", (int)timeout);
|
||||
}
|
||||
return w;
|
||||
}
|
||||
|
||||
int sldns_wire2str_edns_option_print(char** s, size_t* sl,
|
||||
uint16_t option_code, uint8_t* optdata, size_t optlen)
|
||||
{
|
||||
|
|
@ -1866,6 +1894,9 @@ int sldns_wire2str_edns_option_print(char** s, size_t* sl,
|
|||
case LDNS_EDNS_CLIENT_SUBNET:
|
||||
w += sldns_wire2str_edns_subnet_print(s, sl, optdata, optlen);
|
||||
break;
|
||||
case LDNS_EDNS_KEEPALIVE:
|
||||
w += sldns_wire2str_edns_keepalive_print(s, sl, optdata, optlen);
|
||||
break;
|
||||
case LDNS_EDNS_PADDING:
|
||||
w += print_hex_buf(s, sl, optdata, optlen);
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -441,6 +441,17 @@ int sldns_wire2str_class_buf(uint16_t rrclass, char* str, size_t len);
|
|||
*/
|
||||
int sldns_wire2str_rcode_buf(int rcode, char* str, size_t len);
|
||||
|
||||
/**
|
||||
* Convert host format opcode to a string. 'QUERY', 'NOTIFY', 'UPDATE'.
|
||||
* With user buffer.
|
||||
* @param opcode: opcode as integer in host order
|
||||
* @param str: the string to write to.
|
||||
* @param len: length of str.
|
||||
* @return the number of characters for this element, excluding zerobyte.
|
||||
* Is larger or equal than str_len if output was truncated.
|
||||
*/
|
||||
int sldns_wire2str_opcode_buf(int opcode, char* str, size_t len);
|
||||
|
||||
/**
|
||||
* Convert wire dname to a string, "example.com.". With user buffer.
|
||||
* @param dname: the dname in uncompressed wireformat.
|
||||
|
|
|
|||
|
|
@ -53,6 +53,8 @@
|
|||
#include "iterator/iter_hints.h"
|
||||
#include "validator/validator.h"
|
||||
#include "services/localzone.h"
|
||||
#include "services/view.h"
|
||||
#include "respip/respip.h"
|
||||
#include "sldns/sbuffer.h"
|
||||
#ifdef HAVE_GETOPT_H
|
||||
#include <getopt.h>
|
||||
|
|
@ -141,6 +143,27 @@ localzonechecks(struct config_file* cfg)
|
|||
local_zones_delete(zs);
|
||||
}
|
||||
|
||||
/** check view and response-ip configuration */
|
||||
static void
|
||||
view_and_respipchecks(struct config_file* cfg)
|
||||
{
|
||||
struct views* views = NULL;
|
||||
struct respip_set* respip = NULL;
|
||||
int ignored = 0;
|
||||
if(!(views = views_create()))
|
||||
fatal_exit("Could not create views: out of memory");
|
||||
if(!(respip = respip_set_create()))
|
||||
fatal_exit("Could not create respip set: out of memory");
|
||||
if(!views_apply_cfg(views, cfg))
|
||||
fatal_exit("Could not set up views");
|
||||
if(!respip_global_apply_cfg(respip, cfg))
|
||||
fatal_exit("Could not setup respip set");
|
||||
if(!respip_views_apply_cfg(views, cfg, &ignored))
|
||||
fatal_exit("Could not setup per-view respip sets");
|
||||
views_delete(views);
|
||||
respip_set_delete(respip);
|
||||
}
|
||||
|
||||
/** emit warnings for IP in hosts */
|
||||
static void
|
||||
warn_hosts(const char* typ, struct config_stub* list)
|
||||
|
|
@ -406,11 +429,17 @@ morechecks(struct config_file* cfg, const char* fname)
|
|||
/* remove chroot setting so that modules are not stripping pathnames*/
|
||||
free(cfg->chrootdir);
|
||||
cfg->chrootdir = NULL;
|
||||
|
||||
|
||||
/* There should be no reason for 'respip' module not to work with
|
||||
* dns64, but it's not explicitly confirmed, so the combination is
|
||||
* excluded below. It's simply unknown yet for the combination of
|
||||
* respip and other modules. */
|
||||
if(strcmp(cfg->module_conf, "iterator") != 0
|
||||
&& strcmp(cfg->module_conf, "validator iterator") != 0
|
||||
&& strcmp(cfg->module_conf, "dns64 validator iterator") != 0
|
||||
&& strcmp(cfg->module_conf, "dns64 iterator") != 0
|
||||
&& strcmp(cfg->module_conf, "respip iterator") != 0
|
||||
&& strcmp(cfg->module_conf, "respip validator iterator") != 0
|
||||
#ifdef WITH_PYTHONMODULE
|
||||
&& strcmp(cfg->module_conf, "python iterator") != 0
|
||||
&& strcmp(cfg->module_conf, "python validator iterator") != 0
|
||||
|
|
@ -426,6 +455,8 @@ morechecks(struct config_file* cfg, const char* fname)
|
|||
&& strcmp(cfg->module_conf, "cachedb iterator") != 0
|
||||
&& strcmp(cfg->module_conf, "dns64 validator cachedb iterator") != 0
|
||||
&& strcmp(cfg->module_conf, "dns64 cachedb iterator") != 0
|
||||
#endif
|
||||
#if defined(WITH_PYTHONMODULE) && defined(USE_CACHEDB)
|
||||
&& strcmp(cfg->module_conf, "python dns64 cachedb iterator") != 0
|
||||
&& strcmp(cfg->module_conf, "python dns64 validator cachedb iterator") != 0
|
||||
&& strcmp(cfg->module_conf, "dns64 python cachedb iterator") != 0
|
||||
|
|
@ -435,6 +466,18 @@ morechecks(struct config_file* cfg, const char* fname)
|
|||
&& strcmp(cfg->module_conf, "cachedb python iterator") != 0
|
||||
&& strcmp(cfg->module_conf, "validator cachedb python iterator") != 0
|
||||
&& strcmp(cfg->module_conf, "validator python cachedb iterator") != 0
|
||||
#endif
|
||||
#ifdef CLIENT_SUBNET
|
||||
&& strcmp(cfg->module_conf, "subnetcache iterator") != 0
|
||||
&& strcmp(cfg->module_conf, "subnetcache validator iterator") != 0
|
||||
#endif
|
||||
#if defined(WITH_PYTHONMODULE) && defined(CLIENT_SUBNET)
|
||||
&& strcmp(cfg->module_conf, "python subnetcache iterator") != 0
|
||||
&& strcmp(cfg->module_conf, "subnetcache python iterator") != 0
|
||||
&& strcmp(cfg->module_conf, "subnetcache validator iterator") != 0
|
||||
&& strcmp(cfg->module_conf, "python subnetcache validator iterator") != 0
|
||||
&& strcmp(cfg->module_conf, "subnetcache python validator iterator") != 0
|
||||
&& strcmp(cfg->module_conf, "subnetcache validator python iterator") != 0
|
||||
#endif
|
||||
) {
|
||||
fatal_exit("module conf '%s' is not known to work",
|
||||
|
|
@ -464,6 +507,7 @@ morechecks(struct config_file* cfg, const char* fname)
|
|||
}
|
||||
|
||||
localzonechecks(cfg);
|
||||
view_and_respipchecks(cfg);
|
||||
}
|
||||
|
||||
/** check forwards */
|
||||
|
|
|
|||
|
|
@ -58,7 +58,17 @@
|
|||
#include "util/config_file.h"
|
||||
#include "util/locks.h"
|
||||
#include "util/net_help.h"
|
||||
#include "util/shm_side/shm_main.h"
|
||||
#include "daemon/stats.h"
|
||||
#include "sldns/wire2str.h"
|
||||
#include "sldns/pkthdr.h"
|
||||
|
||||
#ifdef HAVE_SYS_IPC_H
|
||||
#include "sys/ipc.h"
|
||||
#endif
|
||||
#ifdef HAVE_SYS_SHM_H
|
||||
#include "sys/shm.h"
|
||||
#endif
|
||||
#ifdef HAVE_SYS_UN_H
|
||||
#include <sys/un.h>
|
||||
#endif
|
||||
|
|
@ -81,6 +91,9 @@ usage(void)
|
|||
printf(" (this flushes data, stats, requestlist)\n");
|
||||
printf(" stats print statistics\n");
|
||||
printf(" stats_noreset peek at statistics\n");
|
||||
#ifdef HAVE_SHMGET
|
||||
printf(" stats_shm print statistics using shm\n");
|
||||
#endif
|
||||
printf(" status display status of server\n");
|
||||
printf(" verbosity <number> change logging detail\n");
|
||||
printf(" log_reopen close and open the logfile\n");
|
||||
|
|
@ -89,6 +102,9 @@ usage(void)
|
|||
printf(" local_data <RR data...> add local data, for example\n");
|
||||
printf(" local_data www.example.com A 192.0.2.1\n");
|
||||
printf(" local_data_remove <name> remove local RR data from name\n");
|
||||
printf(" local_zones, local_zones_remove, local_datas, local_datas_remove\n");
|
||||
printf(" same, but read list from stdin\n");
|
||||
printf(" (one entry per line).\n");
|
||||
printf(" dump_cache print cache to stdout\n");
|
||||
printf(" load_cache load cache from stdin\n");
|
||||
printf(" lookup <name> print nameservers for name\n");
|
||||
|
|
@ -138,6 +154,256 @@ usage(void)
|
|||
exit(1);
|
||||
}
|
||||
|
||||
#ifdef HAVE_SHMGET
|
||||
/** what to put on statistics lines between var and value, ": " or "=" */
|
||||
#define SQ "="
|
||||
/** if true, inhibits a lot of =0 lines from the stats output */
|
||||
static const int inhibit_zero = 1;
|
||||
/** divide sum of timers to get average */
|
||||
static void
|
||||
timeval_divide(struct timeval* avg, const struct timeval* sum, size_t d)
|
||||
{
|
||||
#ifndef S_SPLINT_S
|
||||
size_t leftover;
|
||||
if(d == 0) {
|
||||
avg->tv_sec = 0;
|
||||
avg->tv_usec = 0;
|
||||
return;
|
||||
}
|
||||
avg->tv_sec = sum->tv_sec / d;
|
||||
avg->tv_usec = sum->tv_usec / d;
|
||||
/* handle fraction from seconds divide */
|
||||
leftover = sum->tv_sec - avg->tv_sec*d;
|
||||
avg->tv_usec += (leftover*1000000)/d;
|
||||
#endif
|
||||
}
|
||||
|
||||
/** print unsigned long stats value */
|
||||
#define PR_UL_NM(str, var) printf("%s."str SQ"%lu\n", nm, (unsigned long)(var));
|
||||
#define PR_UL(str, var) printf(str SQ"%lu\n", (unsigned long)(var));
|
||||
#define PR_UL_SUB(str, nm, var) printf(str".%s"SQ"%lu\n", nm, (unsigned long)(var));
|
||||
#define PR_TIMEVAL(str, var) printf(str SQ ARG_LL "d.%6.6d\n", \
|
||||
(long long)var.tv_sec, (int)var.tv_usec);
|
||||
#define PR_LL(str, var) printf(str SQ ARG_LL"d\n", (long long)(var));
|
||||
|
||||
/** print stat block */
|
||||
static void pr_stats(const char* nm, struct stats_info* s)
|
||||
{
|
||||
struct timeval avg;
|
||||
PR_UL_NM("num.queries", s->svr.num_queries);
|
||||
PR_UL_NM("num.queries_ip_ratelimited",
|
||||
s->svr.num_queries_ip_ratelimited);
|
||||
PR_UL_NM("num.cachehits",
|
||||
s->svr.num_queries - s->svr.num_queries_missed_cache);
|
||||
PR_UL_NM("num.cachemiss", s->svr.num_queries_missed_cache);
|
||||
PR_UL_NM("num.prefetch", s->svr.num_queries_prefetch);
|
||||
PR_UL_NM("num.zero_ttl", s->svr.zero_ttl_responses);
|
||||
PR_UL_NM("num.recursivereplies", s->mesh_replies_sent);
|
||||
#ifdef USE_DNSCRYPT
|
||||
PR_UL_NM("num.dnscrypt.crypted", s->svr.num_query_dnscrypt_crypted);
|
||||
PR_UL_NM("num.dnscrypt.cert", s->svr.num_query_dnscrypt_cert);
|
||||
PR_UL_NM("num.dnscrypt.cleartext", s->svr.num_query_dnscrypt_cleartext);
|
||||
PR_UL_NM("num.dnscrypt.malformed",
|
||||
s->svr.num_query_dnscrypt_crypted_malformed);
|
||||
#endif
|
||||
printf("%s.requestlist.avg"SQ"%g\n", nm,
|
||||
(s->svr.num_queries_missed_cache+s->svr.num_queries_prefetch)?
|
||||
(double)s->svr.sum_query_list_size/
|
||||
(s->svr.num_queries_missed_cache+
|
||||
s->svr.num_queries_prefetch) : 0.0);
|
||||
PR_UL_NM("requestlist.max", s->svr.max_query_list_size);
|
||||
PR_UL_NM("requestlist.overwritten", s->mesh_jostled);
|
||||
PR_UL_NM("requestlist.exceeded", s->mesh_dropped);
|
||||
PR_UL_NM("requestlist.current.all", s->mesh_num_states);
|
||||
PR_UL_NM("requestlist.current.user", s->mesh_num_reply_states);
|
||||
timeval_divide(&avg, &s->mesh_replies_sum_wait, s->mesh_replies_sent);
|
||||
printf("%s.", nm);
|
||||
PR_TIMEVAL("recursion.time.avg", avg);
|
||||
printf("%s.recursion.time.median"SQ"%g\n", nm, s->mesh_time_median);
|
||||
PR_UL_NM("tcpusage", s->svr.tcp_accept_usage);
|
||||
}
|
||||
|
||||
/** print uptime */
|
||||
static void print_uptime(struct shm_stat_info* shm_stat)
|
||||
{
|
||||
PR_TIMEVAL("time.now", shm_stat->time.now);
|
||||
PR_TIMEVAL("time.up", shm_stat->time.up);
|
||||
PR_TIMEVAL("time.elapsed", shm_stat->time.elapsed);
|
||||
}
|
||||
|
||||
/** print memory usage */
|
||||
static void print_mem(struct shm_stat_info* shm_stat)
|
||||
{
|
||||
PR_LL("mem.cache.rrset", shm_stat->mem.rrset);
|
||||
PR_LL("mem.cache.message", shm_stat->mem.msg);
|
||||
PR_LL("mem.cache.iterator", shm_stat->mem.iter);
|
||||
PR_LL("mem.cache.validator", shm_stat->mem.val);
|
||||
#ifdef CLIENT_SUBNET
|
||||
PR_LL("mem.cache.subnet", shm_stat->mem.subnet);
|
||||
#endif
|
||||
}
|
||||
|
||||
/** print histogram */
|
||||
static void print_hist(struct stats_info* s)
|
||||
{
|
||||
struct timehist* hist;
|
||||
size_t i;
|
||||
hist = timehist_setup();
|
||||
if(!hist)
|
||||
fatal_exit("out of memory");
|
||||
timehist_import(hist, s->svr.hist, NUM_BUCKETS_HIST);
|
||||
for(i=0; i<hist->num; i++) {
|
||||
printf("histogram.%6.6d.%6.6d.to.%6.6d.%6.6d=%lu\n",
|
||||
(int)hist->buckets[i].lower.tv_sec,
|
||||
(int)hist->buckets[i].lower.tv_usec,
|
||||
(int)hist->buckets[i].upper.tv_sec,
|
||||
(int)hist->buckets[i].upper.tv_usec,
|
||||
(unsigned long)hist->buckets[i].count);
|
||||
}
|
||||
timehist_delete(hist);
|
||||
}
|
||||
|
||||
/** print extended */
|
||||
static void print_extended(struct stats_info* s)
|
||||
{
|
||||
int i;
|
||||
char nm[16];
|
||||
|
||||
/* TYPE */
|
||||
for(i=0; i<STATS_QTYPE_NUM; i++) {
|
||||
if(inhibit_zero && s->svr.qtype[i] == 0)
|
||||
continue;
|
||||
sldns_wire2str_type_buf((uint16_t)i, nm, sizeof(nm));
|
||||
PR_UL_SUB("num.query.type", nm, s->svr.qtype[i]);
|
||||
}
|
||||
if(!inhibit_zero || s->svr.qtype_big) {
|
||||
PR_UL("num.query.type.other", s->svr.qtype_big);
|
||||
}
|
||||
|
||||
/* CLASS */
|
||||
for(i=0; i<STATS_QCLASS_NUM; i++) {
|
||||
if(inhibit_zero && s->svr.qclass[i] == 0)
|
||||
continue;
|
||||
sldns_wire2str_class_buf((uint16_t)i, nm, sizeof(nm));
|
||||
PR_UL_SUB("num.query.class", nm, s->svr.qclass[i]);
|
||||
}
|
||||
if(!inhibit_zero || s->svr.qclass_big) {
|
||||
PR_UL("num.query.class.other", s->svr.qclass_big);
|
||||
}
|
||||
|
||||
/* OPCODE */
|
||||
for(i=0; i<STATS_OPCODE_NUM; i++) {
|
||||
if(inhibit_zero && s->svr.qopcode[i] == 0)
|
||||
continue;
|
||||
sldns_wire2str_opcode_buf(i, nm, sizeof(nm));
|
||||
PR_UL_SUB("num.query.opcode", nm, s->svr.qopcode[i]);
|
||||
}
|
||||
|
||||
/* transport */
|
||||
PR_UL("num.query.tcp", s->svr.qtcp);
|
||||
PR_UL("num.query.tcpout", s->svr.qtcp_outgoing);
|
||||
PR_UL("num.query.ipv6", s->svr.qipv6);
|
||||
|
||||
/* flags */
|
||||
PR_UL("num.query.flags.QR", s->svr.qbit_QR);
|
||||
PR_UL("num.query.flags.AA", s->svr.qbit_AA);
|
||||
PR_UL("num.query.flags.TC", s->svr.qbit_TC);
|
||||
PR_UL("num.query.flags.RD", s->svr.qbit_RD);
|
||||
PR_UL("num.query.flags.RA", s->svr.qbit_RA);
|
||||
PR_UL("num.query.flags.Z", s->svr.qbit_Z);
|
||||
PR_UL("num.query.flags.AD", s->svr.qbit_AD);
|
||||
PR_UL("num.query.flags.CD", s->svr.qbit_CD);
|
||||
PR_UL("num.query.edns.present", s->svr.qEDNS);
|
||||
PR_UL("num.query.edns.DO", s->svr.qEDNS_DO);
|
||||
|
||||
/* RCODE */
|
||||
for(i=0; i<STATS_RCODE_NUM; i++) {
|
||||
/* Always include RCODEs 0-5 */
|
||||
if(inhibit_zero && i > LDNS_RCODE_REFUSED && s->svr.ans_rcode[i] == 0)
|
||||
continue;
|
||||
sldns_wire2str_rcode_buf(i, nm, sizeof(nm));
|
||||
PR_UL_SUB("num.answer.rcode", nm, s->svr.ans_rcode[i]);
|
||||
}
|
||||
if(!inhibit_zero || s->svr.ans_rcode_nodata) {
|
||||
PR_UL("num.answer.rcode.nodata", s->svr.ans_rcode_nodata);
|
||||
}
|
||||
/* validation */
|
||||
PR_UL("num.answer.secure", s->svr.ans_secure);
|
||||
PR_UL("num.answer.bogus", s->svr.ans_bogus);
|
||||
PR_UL("num.rrset.bogus", s->svr.rrset_bogus);
|
||||
/* threat detection */
|
||||
PR_UL("unwanted.queries", s->svr.unwanted_queries);
|
||||
PR_UL("unwanted.replies", s->svr.unwanted_replies);
|
||||
/* cache counts */
|
||||
PR_UL("msg.cache.count", s->svr.msg_cache_count);
|
||||
PR_UL("rrset.cache.count", s->svr.rrset_cache_count);
|
||||
PR_UL("infra.cache.count", s->svr.infra_cache_count);
|
||||
PR_UL("key.cache.count", s->svr.key_cache_count);
|
||||
}
|
||||
|
||||
/** print statistics out of memory structures */
|
||||
static void do_stats_shm(struct config_file* cfg, struct stats_info* stats,
|
||||
struct shm_stat_info* shm_stat)
|
||||
{
|
||||
int i;
|
||||
char nm[16];
|
||||
for(i=0; i<cfg->num_threads; i++) {
|
||||
snprintf(nm, sizeof(nm), "thread%d", i);
|
||||
pr_stats(nm, &stats[i+1]);
|
||||
}
|
||||
pr_stats("total", &stats[0]);
|
||||
print_uptime(shm_stat);
|
||||
if(cfg->stat_extended) {
|
||||
print_mem(shm_stat);
|
||||
print_hist(stats);
|
||||
print_extended(stats);
|
||||
}
|
||||
}
|
||||
#endif /* HAVE_SHMGET */
|
||||
|
||||
/** print statistics from shm memory segment */
|
||||
static void print_stats_shm(const char* cfgfile)
|
||||
{
|
||||
#ifdef HAVE_SHMGET
|
||||
struct config_file* cfg;
|
||||
struct stats_info* stats;
|
||||
struct shm_stat_info* shm_stat;
|
||||
int id_ctl, id_arr;
|
||||
/* read config */
|
||||
if(!(cfg = config_create()))
|
||||
fatal_exit("out of memory");
|
||||
if(!config_read(cfg, cfgfile, NULL))
|
||||
fatal_exit("could not read config file");
|
||||
/* get shm segments */
|
||||
id_ctl = shmget(cfg->shm_key, sizeof(int), SHM_R|SHM_W);
|
||||
if(id_ctl == -1) {
|
||||
fatal_exit("shmget(%d): %s", cfg->shm_key, strerror(errno));
|
||||
}
|
||||
id_arr = shmget(cfg->shm_key+1, sizeof(int), SHM_R|SHM_W);
|
||||
if(id_arr == -1) {
|
||||
fatal_exit("shmget(%d): %s", cfg->shm_key+1, strerror(errno));
|
||||
}
|
||||
shm_stat = (struct shm_stat_info*)shmat(id_ctl, NULL, 0);
|
||||
if(shm_stat == (void*)-1) {
|
||||
fatal_exit("shmat(%d): %s", id_ctl, strerror(errno));
|
||||
}
|
||||
stats = (struct stats_info*)shmat(id_arr, NULL, 0);
|
||||
if(stats == (void*)-1) {
|
||||
fatal_exit("shmat(%d): %s", id_arr, strerror(errno));
|
||||
}
|
||||
|
||||
/* print the stats */
|
||||
do_stats_shm(cfg, stats, shm_stat);
|
||||
|
||||
/* shutdown */
|
||||
shmdt(shm_stat);
|
||||
shmdt(stats);
|
||||
config_delete(cfg);
|
||||
#else
|
||||
(void)cfgfile;
|
||||
#endif /* HAVE_SHMGET */
|
||||
}
|
||||
|
||||
/** exit with ssl error */
|
||||
static void ssl_err(const char* s)
|
||||
{
|
||||
|
|
@ -160,13 +426,13 @@ setup_ctx(struct config_file* cfg)
|
|||
if(!s_cert || !c_key || !c_cert)
|
||||
fatal_exit("out of memory");
|
||||
}
|
||||
ctx = SSL_CTX_new(SSLv23_client_method());
|
||||
ctx = SSL_CTX_new(SSLv23_client_method());
|
||||
if(!ctx)
|
||||
ssl_err("could not allocate SSL_CTX pointer");
|
||||
if((SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2) & SSL_OP_NO_SSLv2)
|
||||
if((SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2) & SSL_OP_NO_SSLv2)
|
||||
!= SSL_OP_NO_SSLv2)
|
||||
ssl_err("could not set SSL_OP_NO_SSLv2");
|
||||
if(cfg->remote_control_use_cert) {
|
||||
if(cfg->remote_control_use_cert) {
|
||||
if((SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv3) & SSL_OP_NO_SSLv3)
|
||||
!= SSL_OP_NO_SSLv3)
|
||||
ssl_err("could not set SSL_OP_NO_SSLv3");
|
||||
|
|
@ -441,44 +707,10 @@ int main(int argc, char* argv[])
|
|||
log_init(NULL, 0, NULL);
|
||||
checklock_start();
|
||||
#ifdef USE_WINSOCK
|
||||
if((r = WSAStartup(MAKEWORD(2,2), &wsa_data)) != 0)
|
||||
fatal_exit("WSAStartup failed: %s", wsa_strerror(r));
|
||||
/* use registry config file in preference to compiletime location */
|
||||
if(!(cfgfile=w_lookup_reg_str("Software\\Unbound", "ConfigFile")))
|
||||
cfgfile = CONFIGFILE;
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_ERR_LOAD_CRYPTO_STRINGS
|
||||
ERR_load_crypto_strings();
|
||||
#endif
|
||||
ERR_load_SSL_strings();
|
||||
#if OPENSSL_VERSION_NUMBER < 0x10100000 || !defined(HAVE_OPENSSL_INIT_CRYPTO)
|
||||
OpenSSL_add_all_algorithms();
|
||||
#else
|
||||
OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS
|
||||
| OPENSSL_INIT_ADD_ALL_DIGESTS
|
||||
| OPENSSL_INIT_LOAD_CRYPTO_STRINGS, NULL);
|
||||
#endif
|
||||
#if OPENSSL_VERSION_NUMBER < 0x10100000 || !defined(HAVE_OPENSSL_INIT_SSL)
|
||||
(void)SSL_library_init();
|
||||
#else
|
||||
(void)OPENSSL_init_ssl(0, NULL);
|
||||
#endif
|
||||
|
||||
if(!RAND_status()) {
|
||||
/* try to seed it */
|
||||
unsigned char buf[256];
|
||||
unsigned int seed=(unsigned)time(NULL) ^ (unsigned)getpid();
|
||||
unsigned int v = seed;
|
||||
size_t i;
|
||||
for(i=0; i<256/sizeof(v); i++) {
|
||||
memmove(buf+i*sizeof(v), &v, sizeof(v));
|
||||
v = v*seed + (unsigned int)i;
|
||||
}
|
||||
RAND_seed(buf, 256);
|
||||
log_warn("no entropy, seeding openssl PRNG with time\n");
|
||||
}
|
||||
|
||||
/* parse the options */
|
||||
while( (c=getopt(argc, argv, "c:s:qh")) != -1) {
|
||||
switch(c) {
|
||||
|
|
@ -508,11 +740,51 @@ int main(int argc, char* argv[])
|
|||
strerror(errno));
|
||||
}
|
||||
}
|
||||
if(argc >= 1 && strcmp(argv[0], "stats_shm")==0) {
|
||||
print_stats_shm(cfgfile);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef USE_WINSOCK
|
||||
if((r = WSAStartup(MAKEWORD(2,2), &wsa_data)) != 0)
|
||||
fatal_exit("WSAStartup failed: %s", wsa_strerror(r));
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_ERR_LOAD_CRYPTO_STRINGS
|
||||
ERR_load_crypto_strings();
|
||||
#endif
|
||||
ERR_load_SSL_strings();
|
||||
#if OPENSSL_VERSION_NUMBER < 0x10100000 || !defined(HAVE_OPENSSL_INIT_CRYPTO)
|
||||
OpenSSL_add_all_algorithms();
|
||||
#else
|
||||
OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS
|
||||
| OPENSSL_INIT_ADD_ALL_DIGESTS
|
||||
| OPENSSL_INIT_LOAD_CRYPTO_STRINGS, NULL);
|
||||
#endif
|
||||
#if OPENSSL_VERSION_NUMBER < 0x10100000 || !defined(HAVE_OPENSSL_INIT_SSL)
|
||||
(void)SSL_library_init();
|
||||
#else
|
||||
(void)OPENSSL_init_ssl(0, NULL);
|
||||
#endif
|
||||
|
||||
if(!RAND_status()) {
|
||||
/* try to seed it */
|
||||
unsigned char buf[256];
|
||||
unsigned int seed=(unsigned)time(NULL) ^ (unsigned)getpid();
|
||||
unsigned int v = seed;
|
||||
size_t i;
|
||||
for(i=0; i<256/sizeof(v); i++) {
|
||||
memmove(buf+i*sizeof(v), &v, sizeof(v));
|
||||
v = v*seed + (unsigned int)i;
|
||||
}
|
||||
RAND_seed(buf, 256);
|
||||
log_warn("no entropy, seeding openssl PRNG with time\n");
|
||||
}
|
||||
|
||||
ret = go(cfgfile, svr, quiet, argc, argv);
|
||||
|
||||
#ifdef USE_WINSOCK
|
||||
WSACleanup();
|
||||
WSACleanup();
|
||||
#endif
|
||||
checklock_stop();
|
||||
return ret;
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ NEED_CURL='06-ianaports.tpkg root_anchor.tpkg'
|
|||
NEED_WHOAMI='07-confroot.tpkg'
|
||||
NEED_IPV6='fwd_ancil.tpkg fwd_tcp_tc6.tpkg stub_udp6.tpkg edns_cache.tpkg'
|
||||
NEED_NOMINGW='tcp_sigpipe.tpkg 07-confroot.tpkg 08-host-lib.tpkg fwd_ancil.tpkg'
|
||||
NEED_DNSCRYPT_PROXY='dnscrypt_queries.tpkg'
|
||||
|
||||
# test if dig and ldns-testns are available.
|
||||
test_tool_avail "dig"
|
||||
|
|
@ -39,6 +40,7 @@ for test in `ls *.tpkg`; do
|
|||
skip_if_in_list $test "$NEED_XXD" "xxd"
|
||||
skip_if_in_list $test "$NEED_NC" "nc"
|
||||
skip_if_in_list $test "$NEED_WHOAMI" "whoami"
|
||||
skip_if_in_list $test "$NEED_DNSCRYPT_PROXY" "dnscrypt-proxy"
|
||||
|
||||
if echo $NEED_IPV6 | grep $test >/dev/null; then
|
||||
if test "$HAVE_IPV6" = no; then
|
||||
|
|
|
|||
|
|
@ -1070,8 +1070,13 @@ struct serviced_query* outnet_serviced_query(struct outside_network* outnet,
|
|||
sldns_buffer_write_u16(pend->buffer, qinfo->qclass);
|
||||
sldns_buffer_flip(pend->buffer);
|
||||
if(1) {
|
||||
/* add edns */
|
||||
struct edns_data edns;
|
||||
if(!inplace_cb_query_call(env, qinfo, flags, addr, addrlen,
|
||||
zone, zonelen, qstate, qstate->region)) {
|
||||
free(pend);
|
||||
return NULL;
|
||||
}
|
||||
/* add edns */
|
||||
edns.edns_present = 1;
|
||||
edns.ext_rcode = 0;
|
||||
edns.edns_version = EDNS_ADVERTISED_VERSION;
|
||||
|
|
|
|||
|
|
@ -73,9 +73,11 @@ testbound_usage(void)
|
|||
printf("\ttest the unbound daemon.\n");
|
||||
printf("-h this help\n");
|
||||
printf("-p file playback text file\n");
|
||||
printf("-1 detect SHA1 support (exit code 0 or 1)\n");
|
||||
printf("-2 detect SHA256 support (exit code 0 or 1)\n");
|
||||
printf("-g detect GOST support (exit code 0 or 1)\n");
|
||||
printf("-e detect ECDSA support (exit code 0 or 1)\n");
|
||||
printf("-c detect CLIENT_SUBNET support (exit code 0 or 1)\n");
|
||||
printf("-s testbound self-test - unit test of testbound parts.\n");
|
||||
printf("-o str unbound commandline options separated by spaces.\n");
|
||||
printf("Version %s\n", PACKAGE_VERSION);
|
||||
|
|
@ -279,12 +281,21 @@ main(int argc, char* argv[])
|
|||
pass_argc = 1;
|
||||
pass_argv[0] = "unbound";
|
||||
add_opts("-d", &pass_argc, pass_argv);
|
||||
while( (c=getopt(argc, argv, "2egho:p:s")) != -1) {
|
||||
while( (c=getopt(argc, argv, "12egho:p:s")) != -1) {
|
||||
switch(c) {
|
||||
case 's':
|
||||
free(pass_argv[1]);
|
||||
testbound_selftest();
|
||||
exit(0);
|
||||
case '1':
|
||||
#ifdef USE_SHA1
|
||||
printf("SHA1 supported\n");
|
||||
exit(0);
|
||||
#else
|
||||
printf("SHA1 not supported\n");
|
||||
exit(1);
|
||||
#endif
|
||||
break;
|
||||
case '2':
|
||||
#if (defined(HAVE_EVP_SHA256) || defined(HAVE_NSS) || defined(HAVE_NETTLE)) && defined(USE_SHA2)
|
||||
printf("SHA256 supported\n");
|
||||
|
|
@ -315,6 +326,15 @@ main(int argc, char* argv[])
|
|||
#else
|
||||
printf("GOST not supported\n");
|
||||
exit(1);
|
||||
#endif
|
||||
break;
|
||||
case 'c':
|
||||
#ifdef CLIENT_SUBNET
|
||||
printf("CLIENT_SUBNET supported\n");
|
||||
exit(0);
|
||||
#else
|
||||
printf("CLIENT_SUBNET not supported\n");
|
||||
exit(1);
|
||||
#endif
|
||||
break;
|
||||
case 'p':
|
||||
|
|
|
|||
|
|
@ -98,6 +98,7 @@ entry_add_reply(struct entry* entry)
|
|||
pkt->packet_sleep = 0;
|
||||
pkt->reply_pkt = NULL;
|
||||
pkt->reply_from_hex = NULL;
|
||||
pkt->raw_ednsdata = NULL;
|
||||
/* link at end */
|
||||
while(*p)
|
||||
p = &((*p)->next);
|
||||
|
|
@ -118,6 +119,12 @@ static void matchline(char* line, struct entry* e)
|
|||
e->match_qtype = 1;
|
||||
} else if(str_keyword(&parse, "qname")) {
|
||||
e->match_qname = 1;
|
||||
} else if(str_keyword(&parse, "rcode")) {
|
||||
e->match_rcode = 1;
|
||||
} else if(str_keyword(&parse, "question")) {
|
||||
e->match_question = 1;
|
||||
} else if(str_keyword(&parse, "answer")) {
|
||||
e->match_answer = 1;
|
||||
} else if(str_keyword(&parse, "subdomain")) {
|
||||
e->match_subdomain = 1;
|
||||
} else if(str_keyword(&parse, "all")) {
|
||||
|
|
@ -128,6 +135,8 @@ static void matchline(char* line, struct entry* e)
|
|||
e->match_do = 1;
|
||||
} else if(str_keyword(&parse, "noedns")) {
|
||||
e->match_noedns = 1;
|
||||
} else if(str_keyword(&parse, "ednsdata")) {
|
||||
e->match_ednsdata_raw = 1;
|
||||
} else if(str_keyword(&parse, "UDP")) {
|
||||
e->match_transport = transport_udp;
|
||||
} else if(str_keyword(&parse, "TCP")) {
|
||||
|
|
@ -224,6 +233,8 @@ static void adjustline(char* line, struct entry* e,
|
|||
e->copy_id = 1;
|
||||
} else if(str_keyword(&parse, "copy_query")) {
|
||||
e->copy_query = 1;
|
||||
} else if(str_keyword(&parse, "copy_ednsdata_assume_clientsubnet")) {
|
||||
e->copy_ednsdata_assume_clientsubnet = 1;
|
||||
} else if(str_keyword(&parse, "sleep=")) {
|
||||
e->sleeptime = (unsigned int) strtol(parse, (char**)&parse, 10);
|
||||
while(isspace((unsigned char)*parse))
|
||||
|
|
@ -247,6 +258,9 @@ static struct entry* new_entry(void)
|
|||
e->match_opcode = 0;
|
||||
e->match_qtype = 0;
|
||||
e->match_qname = 0;
|
||||
e->match_rcode = 0;
|
||||
e->match_question = 0;
|
||||
e->match_answer = 0;
|
||||
e->match_subdomain = 0;
|
||||
e->match_all = 0;
|
||||
e->match_ttl = 0;
|
||||
|
|
@ -258,6 +272,7 @@ static struct entry* new_entry(void)
|
|||
e->reply_list = NULL;
|
||||
e->copy_id = 0;
|
||||
e->copy_query = 0;
|
||||
e->copy_ednsdata_assume_clientsubnet = 0;
|
||||
e->sleeptime = 0;
|
||||
e->next = NULL;
|
||||
return e;
|
||||
|
|
@ -475,25 +490,28 @@ static void add_rr(char* rrstr, uint8_t* pktbuf, size_t pktsize,
|
|||
else error("internal error bad section %d", (int)add_section);
|
||||
}
|
||||
|
||||
/* add EDNS 4096 DO opt record */
|
||||
/* add EDNS 4096 opt record */
|
||||
static void
|
||||
add_do_flag(uint8_t* pktbuf, size_t pktsize, size_t* pktlen)
|
||||
add_edns(uint8_t* pktbuf, size_t pktsize, int do_flag, uint8_t *ednsdata,
|
||||
uint16_t ednslen, size_t* pktlen)
|
||||
{
|
||||
uint8_t edns[] = {0x00, /* root label */
|
||||
0x00, LDNS_RR_TYPE_OPT, /* type */
|
||||
0x10, 0x00, /* class is UDPSIZE 4096 */
|
||||
0x00, /* TTL[0] is ext rcode */
|
||||
0x00, /* TTL[1] is edns version */
|
||||
0x80, 0x00, /* TTL[2-3] is edns flags, DO */
|
||||
0x00, 0x00 /* rdatalength (0 options) */
|
||||
(uint8_t)(do_flag?0x80:0x00), 0x00, /* TTL[2-3] is edns flags, DO */
|
||||
(uint8_t)((ednslen >> 8) & 0xff),
|
||||
(uint8_t)(ednslen & 0xff), /* rdatalength */
|
||||
};
|
||||
if(*pktlen < LDNS_HEADER_SIZE)
|
||||
return;
|
||||
if(*pktlen + sizeof(edns) > pktsize)
|
||||
if(*pktlen + sizeof(edns) + ednslen > pktsize)
|
||||
error("not enough space for EDNS OPT record");
|
||||
memmove(pktbuf+*pktlen, edns, sizeof(edns));
|
||||
memmove(pktbuf+*pktlen+sizeof(edns), ednsdata, ednslen);
|
||||
sldns_write_uint16(pktbuf+10, LDNS_ARCOUNT(pktbuf)+1);
|
||||
*pktlen += sizeof(edns);
|
||||
*pktlen += (sizeof(edns) + ednslen);
|
||||
}
|
||||
|
||||
/* Reads one entry from file. Returns entry or NULL on error. */
|
||||
|
|
@ -507,7 +525,9 @@ read_entry(FILE* in, const char* name, struct sldns_file_parse_state* pstate,
|
|||
sldns_pkt_section add_section = LDNS_SECTION_QUESTION;
|
||||
struct reply_packet *cur_reply = NULL;
|
||||
int reading_hex = 0;
|
||||
int reading_hex_ednsdata = 0;
|
||||
sldns_buffer* hex_data_buffer = NULL;
|
||||
sldns_buffer* hex_ednsdata_buffer = NULL;
|
||||
uint8_t pktbuf[MAX_PACKETLEN];
|
||||
size_t pktlen = LDNS_HEADER_SIZE;
|
||||
int do_flag = 0; /* DO flag in EDNS */
|
||||
|
|
@ -574,21 +594,45 @@ read_entry(FILE* in, const char* name, struct sldns_file_parse_state* pstate,
|
|||
cur_reply->reply_from_hex = hex_buffer2wire(hex_data_buffer);
|
||||
sldns_buffer_free(hex_data_buffer);
|
||||
hex_data_buffer = NULL;
|
||||
} else if(reading_hex) {
|
||||
sldns_buffer_printf(hex_data_buffer, "%s", line);
|
||||
} else if(str_keyword(&parse, "HEX_EDNSDATA_BEGIN")) {
|
||||
hex_ednsdata_buffer = sldns_buffer_new(MAX_PACKETLEN);
|
||||
reading_hex_ednsdata = 1;
|
||||
} else if(str_keyword(&parse, "HEX_EDNSDATA_END")) {
|
||||
if (!reading_hex_ednsdata) {
|
||||
error("%s line %d: HEX_EDNSDATA_END read but no"
|
||||
"HEX_EDNSDATA_BEGIN keyword seen", name, pstate->lineno);
|
||||
}
|
||||
reading_hex_ednsdata = 0;
|
||||
cur_reply->raw_ednsdata = hex_buffer2wire(hex_ednsdata_buffer);
|
||||
sldns_buffer_free(hex_ednsdata_buffer);
|
||||
hex_ednsdata_buffer = NULL;
|
||||
} else if(reading_hex_ednsdata) {
|
||||
sldns_buffer_printf(hex_ednsdata_buffer, "%s", line);
|
||||
} else if(str_keyword(&parse, "ENTRY_END")) {
|
||||
if(hex_data_buffer)
|
||||
sldns_buffer_free(hex_data_buffer);
|
||||
if(hex_ednsdata_buffer)
|
||||
sldns_buffer_free(hex_ednsdata_buffer);
|
||||
if(pktlen != 0) {
|
||||
if(do_flag)
|
||||
add_do_flag(pktbuf, sizeof(pktbuf),
|
||||
&pktlen);
|
||||
if(do_flag || cur_reply->raw_ednsdata) {
|
||||
if(cur_reply->raw_ednsdata &&
|
||||
sldns_buffer_limit(cur_reply->raw_ednsdata))
|
||||
add_edns(pktbuf, sizeof(pktbuf), do_flag,
|
||||
sldns_buffer_begin(cur_reply->raw_ednsdata),
|
||||
(uint16_t)sldns_buffer_limit(cur_reply->raw_ednsdata),
|
||||
&pktlen);
|
||||
else
|
||||
add_edns(pktbuf, sizeof(pktbuf), do_flag,
|
||||
NULL, 0, &pktlen);
|
||||
}
|
||||
cur_reply->reply_pkt = memdup(pktbuf, pktlen);
|
||||
cur_reply->reply_len = pktlen;
|
||||
if(!cur_reply->reply_pkt)
|
||||
error("out of memory");
|
||||
}
|
||||
return current;
|
||||
} else if(reading_hex) {
|
||||
sldns_buffer_printf(hex_data_buffer, "%s", line);
|
||||
} else {
|
||||
add_rr(skip_whitespace?parse:line, pktbuf,
|
||||
sizeof(pktbuf), &pktlen, pstate, add_section,
|
||||
|
|
@ -596,10 +640,14 @@ read_entry(FILE* in, const char* name, struct sldns_file_parse_state* pstate,
|
|||
}
|
||||
|
||||
}
|
||||
if (reading_hex) {
|
||||
if(reading_hex) {
|
||||
error("%s: End of file reached while still reading hex, "
|
||||
"missing HEX_ANSWER_END\n", name);
|
||||
}
|
||||
if(reading_hex_ednsdata) {
|
||||
error("%s: End of file reached while still reading edns data, "
|
||||
"missing HEX_EDNSDATA_END\n", name);
|
||||
}
|
||||
if(current) {
|
||||
error("%s: End of file reached while reading entry. "
|
||||
"missing ENTRY_END\n", name);
|
||||
|
|
@ -691,6 +739,14 @@ static int get_opcode(uint8_t* pkt, size_t pktlen)
|
|||
return (int)LDNS_OPCODE_WIRE(pkt);
|
||||
}
|
||||
|
||||
/** returns rcode from packet */
|
||||
static int get_rcode(uint8_t* pkt, size_t pktlen)
|
||||
{
|
||||
if(pktlen < LDNS_HEADER_SIZE)
|
||||
return 0;
|
||||
return (int)LDNS_RCODE_WIRE(pkt);
|
||||
}
|
||||
|
||||
/** get authority section SOA serial value */
|
||||
static uint32_t get_serial(uint8_t* p, size_t plen)
|
||||
{
|
||||
|
|
@ -761,16 +817,16 @@ pkt_find_edns_opt(uint8_t** p, size_t* plen)
|
|||
wlen -= LDNS_HEADER_SIZE;
|
||||
|
||||
/* skip other records with wire2str_scan */
|
||||
for(i=0; i < LDNS_QDCOUNT(p); i++)
|
||||
for(i=0; i < LDNS_QDCOUNT(*p); i++)
|
||||
(void)sldns_wire2str_rrquestion_scan(&w, &wlen, &snull, &sl,
|
||||
*p, *plen);
|
||||
for(i=0; i < LDNS_ANCOUNT(p); i++)
|
||||
for(i=0; i < LDNS_ANCOUNT(*p); i++)
|
||||
(void)sldns_wire2str_rr_scan(&w, &wlen, &snull, &sl, *p, *plen);
|
||||
for(i=0; i < LDNS_NSCOUNT(p); i++)
|
||||
for(i=0; i < LDNS_NSCOUNT(*p); i++)
|
||||
(void)sldns_wire2str_rr_scan(&w, &wlen, &snull, &sl, *p, *plen);
|
||||
|
||||
/* walk through additional section */
|
||||
for(i=0; i < LDNS_ARCOUNT(p); i++) {
|
||||
for(i=0; i < LDNS_ARCOUNT(*p); i++) {
|
||||
/* if this is OPT then done */
|
||||
uint8_t* dstart = w;
|
||||
size_t dlen = wlen;
|
||||
|
|
@ -802,8 +858,8 @@ get_do_flag(uint8_t* pkt, size_t len)
|
|||
uint16_t edns_bits;
|
||||
uint8_t* walk = pkt;
|
||||
size_t walk_len = len;
|
||||
if(pkt_find_edns_opt(&walk, &walk_len)) {
|
||||
return 1;
|
||||
if(!pkt_find_edns_opt(&walk, &walk_len)) {
|
||||
return 0;
|
||||
}
|
||||
if(walk_len < 6)
|
||||
return 0; /* malformed */
|
||||
|
|
@ -1086,6 +1142,138 @@ static void lowercase_pkt(uint8_t* pkt, size_t pktlen)
|
|||
}
|
||||
}
|
||||
|
||||
/** match question section of packet */
|
||||
static int
|
||||
match_question(uint8_t* q, size_t qlen, uint8_t* p, size_t plen, int mttl)
|
||||
{
|
||||
char* qstr, *pstr, *s, *qcmpstr, *pcmpstr;
|
||||
uint8_t* qb = q, *pb = p;
|
||||
int r;
|
||||
/* zero TTLs */
|
||||
qb = memdup(q, qlen);
|
||||
pb = memdup(p, plen);
|
||||
if(!qb || !pb) error("out of memory");
|
||||
if(!mttl) {
|
||||
zerottls(qb, qlen);
|
||||
zerottls(pb, plen);
|
||||
}
|
||||
lowercase_pkt(qb, qlen);
|
||||
lowercase_pkt(pb, plen);
|
||||
qstr = sldns_wire2str_pkt(qb, qlen);
|
||||
pstr = sldns_wire2str_pkt(pb, plen);
|
||||
if(!qstr || !pstr) error("cannot pkt2string");
|
||||
|
||||
/* remove before ;; QUESTION */
|
||||
s = strstr(qstr, ";; QUESTION SECTION");
|
||||
qcmpstr = s;
|
||||
s = strstr(pstr, ";; QUESTION SECTION");
|
||||
pcmpstr = s;
|
||||
if(!qcmpstr && !pcmpstr) {
|
||||
free(qstr);
|
||||
free(pstr);
|
||||
free(qb);
|
||||
free(pb);
|
||||
return 1;
|
||||
}
|
||||
if(!qcmpstr || !pcmpstr) {
|
||||
free(qstr);
|
||||
free(pstr);
|
||||
free(qb);
|
||||
free(pb);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* remove after answer section, (;; AUTH, ;; ADD, ;; MSG size ..) */
|
||||
s = strstr(qcmpstr, ";; ANSWER SECTION");
|
||||
if(!s) s = strstr(qcmpstr, ";; AUTHORITY SECTION");
|
||||
if(!s) s = strstr(qcmpstr, ";; ADDITIONAL SECTION");
|
||||
if(!s) s = strstr(qcmpstr, ";; MSG SIZE");
|
||||
if(s) *s = 0;
|
||||
s = strstr(pcmpstr, ";; ANSWER SECTION");
|
||||
if(!s) s = strstr(pcmpstr, ";; AUTHORITY SECTION");
|
||||
if(!s) s = strstr(pcmpstr, ";; ADDITIONAL SECTION");
|
||||
if(!s) s = strstr(pcmpstr, ";; MSG SIZE");
|
||||
if(s) *s = 0;
|
||||
|
||||
r = (strcmp(qcmpstr, pcmpstr) == 0);
|
||||
|
||||
if(!r) {
|
||||
verbose(3, "mismatch question section '%s' and '%s'",
|
||||
qcmpstr, pcmpstr);
|
||||
}
|
||||
|
||||
free(qstr);
|
||||
free(pstr);
|
||||
free(qb);
|
||||
free(pb);
|
||||
return r;
|
||||
}
|
||||
|
||||
/** match answer section of packet */
|
||||
static int
|
||||
match_answer(uint8_t* q, size_t qlen, uint8_t* p, size_t plen, int mttl)
|
||||
{
|
||||
char* qstr, *pstr, *s, *qcmpstr, *pcmpstr;
|
||||
uint8_t* qb = q, *pb = p;
|
||||
int r;
|
||||
/* zero TTLs */
|
||||
qb = memdup(q, qlen);
|
||||
pb = memdup(p, plen);
|
||||
if(!qb || !pb) error("out of memory");
|
||||
if(!mttl) {
|
||||
zerottls(qb, qlen);
|
||||
zerottls(pb, plen);
|
||||
}
|
||||
lowercase_pkt(qb, qlen);
|
||||
lowercase_pkt(pb, plen);
|
||||
qstr = sldns_wire2str_pkt(qb, qlen);
|
||||
pstr = sldns_wire2str_pkt(pb, plen);
|
||||
if(!qstr || !pstr) error("cannot pkt2string");
|
||||
|
||||
/* remove before ;; ANSWER */
|
||||
s = strstr(qstr, ";; ANSWER SECTION");
|
||||
qcmpstr = s;
|
||||
s = strstr(pstr, ";; ANSWER SECTION");
|
||||
pcmpstr = s;
|
||||
if(!qcmpstr && !pcmpstr) {
|
||||
free(qstr);
|
||||
free(pstr);
|
||||
free(qb);
|
||||
free(pb);
|
||||
return 1;
|
||||
}
|
||||
if(!qcmpstr || !pcmpstr) {
|
||||
free(qstr);
|
||||
free(pstr);
|
||||
free(qb);
|
||||
free(pb);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* remove after answer section, (;; AUTH, ;; ADD, ;; MSG size ..) */
|
||||
s = strstr(qcmpstr, ";; AUTHORITY SECTION");
|
||||
if(!s) s = strstr(qcmpstr, ";; ADDITIONAL SECTION");
|
||||
if(!s) s = strstr(qcmpstr, ";; MSG SIZE");
|
||||
if(s) *s = 0;
|
||||
s = strstr(pcmpstr, ";; AUTHORITY SECTION");
|
||||
if(!s) s = strstr(pcmpstr, ";; ADDITIONAL SECTION");
|
||||
if(!s) s = strstr(pcmpstr, ";; MSG SIZE");
|
||||
if(s) *s = 0;
|
||||
|
||||
r = (strcmp(qcmpstr, pcmpstr) == 0);
|
||||
|
||||
if(!r) {
|
||||
verbose(3, "mismatch answer section '%s' and '%s'",
|
||||
qcmpstr, pcmpstr);
|
||||
}
|
||||
|
||||
free(qstr);
|
||||
free(pstr);
|
||||
free(qb);
|
||||
free(pb);
|
||||
return r;
|
||||
}
|
||||
|
||||
/** match all of the packet */
|
||||
int
|
||||
match_all(uint8_t* q, size_t qlen, uint8_t* p, size_t plen, int mttl,
|
||||
|
|
@ -1128,6 +1316,9 @@ match_all(uint8_t* q, size_t qlen, uint8_t* p, size_t plen, int mttl,
|
|||
/* check for reordered sections */
|
||||
r = match_noloc(qstr, pstr, q, qlen, p, plen);
|
||||
}
|
||||
if(!r) {
|
||||
verbose(3, "mismatch pkt '%s' and '%s'", qstr, pstr);
|
||||
}
|
||||
free(qstr);
|
||||
free(pstr);
|
||||
free(qb);
|
||||
|
|
@ -1186,6 +1377,31 @@ static int subdomain_dname(uint8_t* q, size_t qlen, uint8_t* p, size_t plen)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/** Match OPT RDATA (not the EDNS payload size or flags) */
|
||||
static int
|
||||
match_ednsdata(uint8_t* q, size_t qlen, uint8_t* p, size_t plen)
|
||||
{
|
||||
uint8_t* walk_q = q;
|
||||
size_t walk_qlen = qlen;
|
||||
uint8_t* walk_p = p;
|
||||
size_t walk_plen = plen;
|
||||
|
||||
if(!pkt_find_edns_opt(&walk_q, &walk_qlen))
|
||||
walk_qlen = 0;
|
||||
if(!pkt_find_edns_opt(&walk_p, &walk_plen))
|
||||
walk_plen = 0;
|
||||
|
||||
/* class + ttl + rdlen = 8 */
|
||||
if(walk_qlen <= 8 && walk_plen <= 8) {
|
||||
verbose(3, "NO edns opt, move on");
|
||||
return 1;
|
||||
}
|
||||
if(walk_qlen != walk_plen)
|
||||
return 0;
|
||||
|
||||
return (memcmp(walk_p+8, walk_q+8, walk_qlen-8) == 0);
|
||||
}
|
||||
|
||||
/* finds entry in list, or returns NULL */
|
||||
struct entry*
|
||||
find_match(struct entry* entries, uint8_t* query_pkt, size_t len,
|
||||
|
|
@ -1214,6 +1430,31 @@ find_match(struct entry* entries, uint8_t* query_pkt, size_t len,
|
|||
continue;
|
||||
}
|
||||
}
|
||||
if(p->match_rcode) {
|
||||
if(get_rcode(query_pkt, len) != get_rcode(reply, rlen)) {
|
||||
char *r1 = sldns_wire2str_rcode(get_rcode(query_pkt, len));
|
||||
char *r2 = sldns_wire2str_rcode(get_rcode(reply, rlen));
|
||||
verbose(3, "bad rcode %s instead of %s\n",
|
||||
r1, r2);
|
||||
free(r1);
|
||||
free(r2);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if(p->match_question) {
|
||||
if(!match_question(query_pkt, len, reply, rlen,
|
||||
(int)p->match_ttl)) {
|
||||
verbose(3, "bad question section\n");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if(p->match_answer) {
|
||||
if(!match_answer(query_pkt, len, reply, rlen,
|
||||
(int)p->match_ttl)) {
|
||||
verbose(3, "bad answer section\n");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if(p->match_subdomain) {
|
||||
if(!subdomain_dname(query_pkt, len, reply, rlen)) {
|
||||
verbose(3, "bad subdomain\n");
|
||||
|
|
@ -1232,6 +1473,11 @@ find_match(struct entry* entries, uint8_t* query_pkt, size_t len,
|
|||
verbose(3, "bad; EDNS OPT present\n");
|
||||
continue;
|
||||
}
|
||||
if(p->match_ednsdata_raw &&
|
||||
!match_ednsdata(query_pkt, len, reply, rlen)) {
|
||||
verbose(3, "bad EDNS data match.\n");
|
||||
continue;
|
||||
}
|
||||
if(p->match_transport != transport_any && p->match_transport != transport) {
|
||||
verbose(3, "bad transport\n");
|
||||
continue;
|
||||
|
|
@ -1317,6 +1563,29 @@ adjust_packet(struct entry* match, uint8_t** answer_pkt, size_t *answer_len,
|
|||
if(match->copy_id && reslen >= 1)
|
||||
res[0] = orig[0];
|
||||
|
||||
if(match->copy_ednsdata_assume_clientsubnet) {
|
||||
/** Assume there is only one EDNS option, which is ECS.
|
||||
* Copy source mask from query to scope mask in reply. Assume
|
||||
* rest of ECS data in response (eg address) matches the query.
|
||||
*/
|
||||
uint8_t* walk_q = orig;
|
||||
size_t walk_qlen = origlen;
|
||||
uint8_t* walk_p = res;
|
||||
size_t walk_plen = reslen;
|
||||
|
||||
if(!pkt_find_edns_opt(&walk_q, &walk_qlen)) {
|
||||
walk_qlen = 0;
|
||||
}
|
||||
if(!pkt_find_edns_opt(&walk_p, &walk_plen)) {
|
||||
walk_plen = 0;
|
||||
}
|
||||
/* class + ttl + rdlen + optcode + optlen + ecs fam + ecs source
|
||||
* + ecs scope = index 15 */
|
||||
if(walk_qlen >= 15 && walk_plen >= 15) {
|
||||
walk_p[15] = walk_q[14];
|
||||
}
|
||||
}
|
||||
|
||||
if(match->sleeptime > 0) {
|
||||
verbose(3, "sleeping for %d seconds\n", match->sleeptime);
|
||||
#ifdef HAVE_SLEEP
|
||||
|
|
@ -1410,6 +1679,7 @@ void delete_replylist(struct reply_packet* replist)
|
|||
np = p->next;
|
||||
free(p->reply_pkt);
|
||||
sldns_buffer_free(p->reply_from_hex);
|
||||
sldns_buffer_free(p->raw_ednsdata);
|
||||
free(p);
|
||||
p=np;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -50,6 +50,10 @@ struct sldns_file_parse_state;
|
|||
; 'ttl' used with all, rrs in packet must also have matching TTLs.
|
||||
; 'DO' will match only queries with DO bit set.
|
||||
; 'noedns' matches queries without EDNS OPT records.
|
||||
; 'rcode' makes the query match the rcode from the reply
|
||||
; 'question' makes the query match the question section
|
||||
; 'answer' makes the query match the answer section
|
||||
; 'ednsdata' matches queries to HEX_EDNS section.
|
||||
MATCH [opcode] [qtype] [qname] [serial=<value>] [all] [ttl]
|
||||
MATCH [UDP|TCP] DO
|
||||
MATCH ...
|
||||
|
|
@ -84,6 +88,11 @@ struct sldns_file_parse_state;
|
|||
; be parsed, ADJUST rules for the answer packet
|
||||
; are ignored. Only copy_id is done.
|
||||
HEX_ANSWER_END
|
||||
HEX_EDNS_BEGIN ; follow with hex data.
|
||||
; Raw EDNS data to match against. It must be an
|
||||
; exact match (all options are matched) and will be
|
||||
; evaluated only when 'MATCH ednsdata' given.
|
||||
HEX_EDNS_END
|
||||
ENTRY_END
|
||||
|
||||
|
||||
|
|
@ -144,6 +153,8 @@ struct reply_packet {
|
|||
uint8_t* reply_pkt;
|
||||
/** length of reply pkt */
|
||||
size_t reply_len;
|
||||
/** Additional EDNS data for matching queries. */
|
||||
struct sldns_buffer* raw_ednsdata;
|
||||
/** or reply pkt in hex if not parsable */
|
||||
struct sldns_buffer* reply_from_hex;
|
||||
/** seconds to sleep before giving packet */
|
||||
|
|
@ -161,6 +172,12 @@ struct entry {
|
|||
uint8_t match_qtype;
|
||||
/** match qname with answer qname */
|
||||
uint8_t match_qname;
|
||||
/** match rcode with answer rcode */
|
||||
uint8_t match_rcode;
|
||||
/** match question section */
|
||||
uint8_t match_question;
|
||||
/** match answer section */
|
||||
uint8_t match_answer;
|
||||
/** match qname as subdomain of answer qname */
|
||||
uint8_t match_subdomain;
|
||||
/** match SOA serial number, from auth section */
|
||||
|
|
@ -173,6 +190,8 @@ struct entry {
|
|||
uint8_t match_do;
|
||||
/** match absence of EDNS OPT record in query */
|
||||
uint8_t match_noedns;
|
||||
/** match edns data field given in hex */
|
||||
uint8_t match_ednsdata_raw;
|
||||
/** match query serial with this value. */
|
||||
uint32_t ixfr_soa_serial;
|
||||
/** match on UDP/TCP */
|
||||
|
|
@ -186,6 +205,9 @@ struct entry {
|
|||
uint8_t copy_id;
|
||||
/** copy the query nametypeclass from query into the answer */
|
||||
uint8_t copy_query;
|
||||
/** copy ednsdata to reply, assume it is clientsubnet and
|
||||
* adjust scopemask to match sourcemask */
|
||||
uint8_t copy_ednsdata_assume_clientsubnet;
|
||||
/** in seconds */
|
||||
unsigned int sleeptime;
|
||||
|
||||
|
|
|
|||
284
testcode/unitecs.c
Normal file
284
testcode/unitecs.c
Normal file
|
|
@ -0,0 +1,284 @@
|
|||
/*
|
||||
* testcode/unitecs.c - unit test for ecs routines.
|
||||
*
|
||||
* Copyright (c) 2013, NLnet Labs. All rights reserved.
|
||||
*
|
||||
* This software is open source.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* Neither the name of the NLNET LABS nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
* Calls ecs related unit tests. Exits with code 1 on a failure.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifdef CLIENT_SUBNET
|
||||
|
||||
#include "util/log.h"
|
||||
#include "util/module.h"
|
||||
#include "testcode/unitmain.h"
|
||||
#include "edns-subnet/addrtree.h"
|
||||
#include "edns-subnet/subnetmod.h"
|
||||
|
||||
/*
|
||||
void printkey(addrkey_t *k, addrlen_t bits)
|
||||
{
|
||||
int byte;
|
||||
int bytes = bits/8 + ((bits%8)>0);
|
||||
char msk = 0xFF;
|
||||
for (byte = 0; byte < bytes; byte++) {
|
||||
//~ if (byte+1 == bytes)
|
||||
//~ msk = 0xFF<<(8-bits%8);
|
||||
printf("%02x ", k[byte]&msk);
|
||||
}
|
||||
}
|
||||
|
||||
void print_tree(struct addrnode* node, int indent, int maxdepth)
|
||||
{
|
||||
struct addredge* edge;
|
||||
int i, s, byte;
|
||||
if (indent == 0) printf("-----Tree-----\n");
|
||||
if (indent > maxdepth) {
|
||||
printf("\n");
|
||||
return;
|
||||
}
|
||||
printf("[node elem:%d] (%d)\n", node->elem != NULL, node);
|
||||
for (i = 0; i<2; i++) {
|
||||
if (node->edge[i]) {
|
||||
for (s = 0; s < indent; s++) printf(" ");
|
||||
printkey(node->edge[i]->str, node->edge[i]->len);
|
||||
printf("(len %d bits, %d bytes) ", node->edge[i]->len,
|
||||
node->edge[i]->len/8 + ((node->edge[i]->len%8)>0));
|
||||
print_tree(node->edge[i]->node, indent+1, maxdepth);
|
||||
}
|
||||
}
|
||||
if (indent == 0) printf("-----Tree-----");
|
||||
}
|
||||
*/
|
||||
|
||||
/* what should we check?
|
||||
* X - is it balanced? (a node with 1 child shoudl not have
|
||||
* a node with 1 child MUST have elem
|
||||
* child must be sub of parent
|
||||
* edge must be longer than parent edge
|
||||
* */
|
||||
static int addrtree_inconsistent_subtree(struct addrtree* tree,
|
||||
struct addredge* parent_edge, addrlen_t depth)
|
||||
{
|
||||
struct addredge* edge;
|
||||
struct addrnode* node = parent_edge->node;
|
||||
int childcount, i, r;
|
||||
if (depth > tree->max_depth) return 15;
|
||||
childcount = (node->edge[0] != NULL) + (node->edge[1] != NULL);
|
||||
/* Only nodes with 2 children should possibly have no element. */
|
||||
if (childcount < 2 && !node->elem) return 10;
|
||||
for (i = 0; i<2; i++) {
|
||||
edge = node->edge[i];
|
||||
if (!edge) continue;
|
||||
if (!edge->node) return 11;
|
||||
if (!edge->str) return 12;
|
||||
if (edge->len <= parent_edge->len) return 13;
|
||||
if (!unittest_wrapper_addrtree_issub(parent_edge->str,
|
||||
parent_edge->len, edge->str, edge->len, 0))
|
||||
return 14;
|
||||
if ((r = addrtree_inconsistent_subtree(tree, edge, depth+1)) != 0)
|
||||
return 100+r;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int addrtree_inconsistent(struct addrtree* tree)
|
||||
{
|
||||
struct addredge* edge;
|
||||
int i, r;
|
||||
|
||||
if (!tree) return 0;
|
||||
if (!tree->root) return 1;
|
||||
|
||||
for (i = 0; i<2; i++) {
|
||||
edge = tree->root->edge[i];
|
||||
if (!edge) continue;
|
||||
if (!edge->node) return 3;
|
||||
if (!edge->str) return 4;
|
||||
if ((r = addrtree_inconsistent_subtree(tree, edge, 1)) != 0)
|
||||
return r;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static addrlen_t randomkey(addrkey_t **k, int maxlen)
|
||||
{
|
||||
int byte;
|
||||
int bits = rand() % maxlen;
|
||||
int bytes = bits/8 + (bits%8>0); /*ceil*/
|
||||
*k = (addrkey_t *) malloc(bytes * sizeof(addrkey_t));
|
||||
for (byte = 0; byte < bytes; byte++) {
|
||||
(*k)[byte] = (addrkey_t)(rand() & 0xFF);
|
||||
}
|
||||
return (addrlen_t)bits;
|
||||
}
|
||||
|
||||
static void elemfree(void *envptr, void *elemptr)
|
||||
{
|
||||
struct reply_info *elem = (struct reply_info *)elemptr;
|
||||
(void)envptr;
|
||||
free(elem);
|
||||
}
|
||||
|
||||
static void consistency_test(void)
|
||||
{
|
||||
addrlen_t l;
|
||||
time_t i;
|
||||
unsigned int count;
|
||||
addrkey_t *k;
|
||||
struct addrtree* t;
|
||||
struct module_env env;
|
||||
struct reply_info *elem;
|
||||
time_t timenow = 0;
|
||||
unit_show_func("edns-subnet/addrtree.h", "Tree consistency check");
|
||||
srand(9195); /* just some value for reproducibility */
|
||||
|
||||
t = addrtree_create(100, &elemfree, &unittest_wrapper_subnetmod_sizefunc, &env, 0);
|
||||
count = t->node_count;
|
||||
unit_assert(count == 0);
|
||||
for (i = 0; i < 1000; i++) {
|
||||
l = randomkey(&k, 128);
|
||||
elem = (struct reply_info *) calloc(1, sizeof(struct reply_info));
|
||||
addrtree_insert(t, k, l, 64, elem, timenow + 10, timenow);
|
||||
/* This should always hold because no items ever expire. They
|
||||
* could be overwritten, though. */
|
||||
unit_assert( count <= t->node_count );
|
||||
count = t->node_count;
|
||||
free(k);
|
||||
unit_assert( !addrtree_inconsistent(t) );
|
||||
}
|
||||
addrtree_delete(t);
|
||||
|
||||
unit_show_func("edns-subnet/addrtree.h", "Tree consistency with purge");
|
||||
t = addrtree_create(8, &elemfree, &unittest_wrapper_subnetmod_sizefunc, &env, 0);
|
||||
unit_assert(t->node_count == 0);
|
||||
for (i = 0; i < 1000; i++) {
|
||||
l = randomkey(&k, 128);
|
||||
elem = (struct reply_info *) calloc(1, sizeof(struct reply_info));
|
||||
addrtree_insert(t, k, l, 64, elem, i + 10, i);
|
||||
free(k);
|
||||
unit_assert( !addrtree_inconsistent(t) );
|
||||
}
|
||||
addrtree_delete(t);
|
||||
|
||||
unit_show_func("edns-subnet/addrtree.h", "Tree consistency with limit");
|
||||
t = addrtree_create(8, &elemfree, &unittest_wrapper_subnetmod_sizefunc, &env, 27);
|
||||
unit_assert(t->node_count == 0);
|
||||
for (i = 0; i < 1000; i++) {
|
||||
l = randomkey(&k, 128);
|
||||
elem = (struct reply_info *) calloc(1, sizeof(struct reply_info));
|
||||
addrtree_insert(t, k, l, 64, elem, i + 10, i);
|
||||
unit_assert( t->node_count <= 27);
|
||||
free(k);
|
||||
unit_assert( !addrtree_inconsistent(t) );
|
||||
}
|
||||
addrtree_delete(t);
|
||||
}
|
||||
|
||||
static void issub_test(void)
|
||||
{
|
||||
addrkey_t k1[] = {0x55, 0x55, 0x5A};
|
||||
addrkey_t k2[] = {0x55, 0x5D, 0x5A};
|
||||
unit_show_func("edns-subnet/addrtree.h", "issub");
|
||||
unit_assert( !unittest_wrapper_addrtree_issub(k1, 24, k2, 24, 0) );
|
||||
unit_assert( unittest_wrapper_addrtree_issub(k1, 8, k2, 16, 0) );
|
||||
unit_assert( unittest_wrapper_addrtree_issub(k2, 12, k1, 13, 0) );
|
||||
unit_assert( !unittest_wrapper_addrtree_issub(k1, 16, k2, 12, 0) );
|
||||
unit_assert( unittest_wrapper_addrtree_issub(k1, 12, k2, 12, 0) );
|
||||
unit_assert( !unittest_wrapper_addrtree_issub(k1, 13, k2, 13, 0) );
|
||||
unit_assert( unittest_wrapper_addrtree_issub(k1, 24, k2, 24, 13) );
|
||||
unit_assert( !unittest_wrapper_addrtree_issub(k1, 24, k2, 20, 13) );
|
||||
unit_assert( unittest_wrapper_addrtree_issub(k1, 20, k2, 24, 13) );
|
||||
}
|
||||
|
||||
static void getbit_test(void)
|
||||
{
|
||||
addrkey_t k1[] = {0x55, 0x55, 0x5A};
|
||||
int i;
|
||||
unit_show_func("edns-subnet/addrtree.h", "getbit");
|
||||
for(i = 0; i<20; i++) {
|
||||
unit_assert( unittest_wrapper_addrtree_getbit(k1, 20, (addrlen_t)i) == (i&1) );
|
||||
}
|
||||
}
|
||||
|
||||
static void bits_common_test(void)
|
||||
{
|
||||
addrkey_t k1[] = {0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0};
|
||||
addrkey_t k2[] = {0,0,0,0,0,0,0,0};
|
||||
addrlen_t i;
|
||||
|
||||
unit_show_func("edns-subnet/addrtree.h", "bits_common");
|
||||
for(i = 0; i<64; i++) {
|
||||
unit_assert( unittest_wrapper_addrtree_bits_common(k1, 64, k1, 64, i) == 64 );
|
||||
}
|
||||
for(i = 0; i<8; i++) {
|
||||
k2[i] = k1[i]^(1<<i);
|
||||
}
|
||||
unit_assert( unittest_wrapper_addrtree_bits_common(k1, 64, k2, 64, 0) == 0*8+7 );
|
||||
unit_assert( unittest_wrapper_addrtree_bits_common(k1, 64, k2, 64, 8) == 1*8+6 );
|
||||
unit_assert( unittest_wrapper_addrtree_bits_common(k1, 64, k2, 64, 16) == 2*8+5 );
|
||||
unit_assert( unittest_wrapper_addrtree_bits_common(k1, 64, k2, 64, 24) == 3*8+4 );
|
||||
unit_assert( unittest_wrapper_addrtree_bits_common(k1, 64, k2, 64, 32) == 4*8+3 );
|
||||
unit_assert( unittest_wrapper_addrtree_bits_common(k1, 64, k2, 64, 40) == 5*8+2 );
|
||||
unit_assert( unittest_wrapper_addrtree_bits_common(k1, 64, k2, 64, 48) == 6*8+1 );
|
||||
unit_assert( unittest_wrapper_addrtree_bits_common(k1, 64, k2, 64, 56) == 7*8+0 );
|
||||
}
|
||||
|
||||
static void cmpbit_test(void)
|
||||
{
|
||||
addrkey_t k1[] = {0xA5, 0x0F};
|
||||
addrkey_t k2[] = {0x5A, 0xF0};
|
||||
addrlen_t i;
|
||||
|
||||
unit_show_func("edns-subnet/addrtree.h", "cmpbit");
|
||||
for(i = 0; i<16; i++) {
|
||||
unit_assert( !unittest_wrapper_addrtree_cmpbit(k1,k1,i) );
|
||||
unit_assert( unittest_wrapper_addrtree_cmpbit(k1,k2,i) );
|
||||
}
|
||||
}
|
||||
|
||||
void ecs_test(void)
|
||||
{
|
||||
unit_show_feature("ecs");
|
||||
cmpbit_test();
|
||||
bits_common_test();
|
||||
getbit_test();
|
||||
issub_test();
|
||||
consistency_test();
|
||||
}
|
||||
#endif /* CLIENT_SUBNET */
|
||||
|
||||
|
|
@ -558,6 +558,269 @@ rnd_test(void)
|
|||
ub_randfree(r);
|
||||
}
|
||||
|
||||
#include "respip/respip.h"
|
||||
#include "services/localzone.h"
|
||||
#include "util/data/packed_rrset.h"
|
||||
typedef struct addr_action {char* ip; char* sact; enum respip_action act;}
|
||||
addr_action_t;
|
||||
|
||||
/** Utility function that verifies that the respip set has actions as expected */
|
||||
static void
|
||||
verify_respip_set_actions(struct respip_set* set, addr_action_t actions[],
|
||||
int actions_len)
|
||||
{
|
||||
int i = 0;
|
||||
struct rbtree_type* tree = respip_set_get_tree(set);
|
||||
for (i=0; i<actions_len; i++) {
|
||||
struct sockaddr_storage addr;
|
||||
int net;
|
||||
socklen_t addrlen;
|
||||
struct resp_addr* node;
|
||||
netblockstrtoaddr(actions[i].ip, UNBOUND_DNS_PORT, &addr,
|
||||
&addrlen, &net);
|
||||
node = (struct resp_addr*)addr_tree_find(tree, &addr, addrlen, net);
|
||||
|
||||
/** we have the node and the node has the correct action
|
||||
* and has no data */
|
||||
unit_assert(node);
|
||||
unit_assert(actions[i].act ==
|
||||
resp_addr_get_action(node));
|
||||
unit_assert(resp_addr_get_rrset(node) == NULL);
|
||||
}
|
||||
unit_assert(actions_len && i == actions_len);
|
||||
unit_assert(actions_len == (int)tree->count);
|
||||
}
|
||||
|
||||
/** Global respip actions test; apply raw config data and verify that
|
||||
* all the nodes in the respip set, looked up by address, have expected
|
||||
* actions */
|
||||
static void
|
||||
respip_conf_actions_test(void)
|
||||
{
|
||||
addr_action_t config_response_ip[] = {
|
||||
{"192.0.1.0/24", "deny", respip_deny},
|
||||
{"192.0.2.0/24", "redirect", respip_redirect},
|
||||
{"192.0.3.0/26", "inform", respip_inform},
|
||||
{"192.0.4.0/27", "inform_deny", respip_inform_deny},
|
||||
{"2001:db8:1::/48", "always_transparent", respip_always_transparent},
|
||||
{"2001:db8:2::/49", "always_refuse", respip_always_refuse},
|
||||
{"2001:db8:3::/50", "always_nxdomain", respip_always_nxdomain},
|
||||
};
|
||||
int i;
|
||||
struct respip_set* set = respip_set_create();
|
||||
struct config_file cfg;
|
||||
int clen = (int)(sizeof(config_response_ip) / sizeof(addr_action_t));
|
||||
|
||||
unit_assert(set);
|
||||
unit_show_feature("global respip config actions apply");
|
||||
memset(&cfg, 0, sizeof(cfg));
|
||||
for(i=0; i<clen; i++) {
|
||||
char* ip = strdup(config_response_ip[i].ip);
|
||||
char* sact = strdup(config_response_ip[i].sact);
|
||||
unit_assert(ip && sact);
|
||||
if(!cfg_str2list_insert(&cfg.respip_actions, ip, sact))
|
||||
unit_assert(0);
|
||||
}
|
||||
unit_assert(respip_global_apply_cfg(set, &cfg));
|
||||
verify_respip_set_actions(set, config_response_ip, clen);
|
||||
}
|
||||
|
||||
/** Per-view respip actions test; apply raw configuration with two views
|
||||
* and verify that actions are as expected in respip sets of both views */
|
||||
static void
|
||||
respip_view_conf_actions_test(void)
|
||||
{
|
||||
addr_action_t config_response_ip_view1[] = {
|
||||
{"192.0.1.0/24", "deny", respip_deny},
|
||||
{"192.0.2.0/24", "redirect", respip_redirect},
|
||||
{"192.0.3.0/26", "inform", respip_inform},
|
||||
{"192.0.4.0/27", "inform_deny", respip_inform_deny},
|
||||
};
|
||||
addr_action_t config_response_ip_view2[] = {
|
||||
{"2001:db8:1::/48", "always_transparent", respip_always_transparent},
|
||||
{"2001:db8:2::/49", "always_refuse", respip_always_refuse},
|
||||
{"2001:db8:3::/50", "always_nxdomain", respip_always_nxdomain},
|
||||
};
|
||||
int i;
|
||||
struct config_file cfg;
|
||||
int clen1 = (int)(sizeof(config_response_ip_view1) / sizeof(addr_action_t));
|
||||
int clen2 = (int)(sizeof(config_response_ip_view2) / sizeof(addr_action_t));
|
||||
struct config_view* cv1;
|
||||
struct config_view* cv2;
|
||||
int have_respip_cfg = 0;
|
||||
struct views* views = NULL;
|
||||
struct view* v = NULL;
|
||||
|
||||
unit_show_feature("per-view respip config actions apply");
|
||||
memset(&cfg, 0, sizeof(cfg));
|
||||
cv1 = (struct config_view*)calloc(1, sizeof(struct config_view));
|
||||
cv2 = (struct config_view*)calloc(1, sizeof(struct config_view));
|
||||
unit_assert(cv1 && cv2);
|
||||
cv1->name = strdup("view1");
|
||||
cv2->name = strdup("view2");
|
||||
unit_assert(cv1->name && cv2->name);
|
||||
cv1->next = cv2;
|
||||
cfg.views = cv1;
|
||||
|
||||
for(i=0; i<clen1; i++) {
|
||||
char* ip = strdup(config_response_ip_view1[i].ip);
|
||||
char* sact = strdup(config_response_ip_view1[i].sact);
|
||||
unit_assert(ip && sact);
|
||||
if(!cfg_str2list_insert(&cv1->respip_actions, ip, sact))
|
||||
unit_assert(0);
|
||||
}
|
||||
for(i=0; i<clen2; i++) {
|
||||
char* ip = strdup(config_response_ip_view2[i].ip);
|
||||
char* sact = strdup(config_response_ip_view2[i].sact);
|
||||
unit_assert(ip && sact);
|
||||
if(!cfg_str2list_insert(&cv2->respip_actions, ip, sact))
|
||||
unit_assert(0);
|
||||
}
|
||||
views = views_create();
|
||||
unit_assert(views);
|
||||
unit_assert(views_apply_cfg(views, &cfg));
|
||||
unit_assert(respip_views_apply_cfg(views, &cfg, &have_respip_cfg));
|
||||
|
||||
/* now verify the respip sets in each view */
|
||||
v = views_find_view(views, "view1", 0);
|
||||
unit_assert(v);
|
||||
verify_respip_set_actions(v->respip_set, config_response_ip_view1, clen1);
|
||||
lock_rw_unlock(&v->lock);
|
||||
v = views_find_view(views, "view2", 0);
|
||||
unit_assert(v);
|
||||
verify_respip_set_actions(v->respip_set, config_response_ip_view2, clen2);
|
||||
lock_rw_unlock(&v->lock);
|
||||
}
|
||||
|
||||
typedef struct addr_data {char* ip; char* data;} addr_data_t;
|
||||
|
||||
/** find the respip address node in the specified tree (by address lookup)
|
||||
* and verify type and address of the specified rdata (by index) in this
|
||||
* node's rrset */
|
||||
static void
|
||||
verify_rrset(struct respip_set* set, const char* ipstr,
|
||||
const char* rdatastr, size_t rdi, uint16_t type)
|
||||
{
|
||||
struct sockaddr_storage addr;
|
||||
int net;
|
||||
char buf[65536];
|
||||
socklen_t addrlen;
|
||||
struct rbtree_type* tree;
|
||||
struct resp_addr* node;
|
||||
const struct ub_packed_rrset_key* rrs;
|
||||
|
||||
netblockstrtoaddr(ipstr, UNBOUND_DNS_PORT, &addr, &addrlen, &net);
|
||||
tree = respip_set_get_tree(set);
|
||||
node = (struct resp_addr*)addr_tree_find(tree, &addr, addrlen, net);
|
||||
unit_assert(node);
|
||||
unit_assert((rrs = resp_addr_get_rrset(node)));
|
||||
unit_assert(ntohs(rrs->rk.type) == type);
|
||||
packed_rr_to_string((struct ub_packed_rrset_key*)rrs,
|
||||
rdi, 0, buf, sizeof(buf));
|
||||
unit_assert(strstr(buf, rdatastr));
|
||||
}
|
||||
|
||||
/** Dataset used to test redirect rrset initialization for both
|
||||
* global and per-view respip redirect configuration */
|
||||
static addr_data_t config_response_ip_data[] = {
|
||||
{"192.0.1.0/24", "A 1.2.3.4"},
|
||||
{"192.0.1.0/24", "A 11.12.13.14"},
|
||||
{"192.0.2.0/24", "CNAME www.example.com."},
|
||||
{"2001:db8:1::/48", "AAAA 2001:db8:1::2:1"},
|
||||
};
|
||||
|
||||
/** Populate raw respip redirect config data, used for both global and
|
||||
* view-based respip redirect test case */
|
||||
static void
|
||||
cfg_insert_respip_data(struct config_str2list** respip_actions,
|
||||
struct config_str2list** respip_data)
|
||||
{
|
||||
int clen = (int)(sizeof(config_response_ip_data) / sizeof(addr_data_t));
|
||||
int i = 0;
|
||||
|
||||
/* insert actions (duplicate netblocks don't matter) */
|
||||
for(i=0; i<clen; i++) {
|
||||
char* ip = strdup(config_response_ip_data[i].ip);
|
||||
char* sact = strdup("redirect");
|
||||
unit_assert(ip && sact);
|
||||
if(!cfg_str2list_insert(respip_actions, ip, sact))
|
||||
unit_assert(0);
|
||||
}
|
||||
/* insert data */
|
||||
for(i=0; i<clen; i++) {
|
||||
char* ip = strdup(config_response_ip_data[i].ip);
|
||||
char* data = strdup(config_response_ip_data[i].data);
|
||||
unit_assert(ip && data);
|
||||
if(!cfg_str2list_insert(respip_data, ip, data))
|
||||
unit_assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
/** Test global respip redirect w/ data directives */
|
||||
static void
|
||||
respip_conf_data_test(void)
|
||||
{
|
||||
struct respip_set* set = respip_set_create();
|
||||
struct config_file cfg;
|
||||
|
||||
unit_show_feature("global respip config data apply");
|
||||
memset(&cfg, 0, sizeof(cfg));
|
||||
|
||||
cfg_insert_respip_data(&cfg.respip_actions, &cfg.respip_data);
|
||||
|
||||
/* apply configuration and verify rrsets */
|
||||
unit_assert(respip_global_apply_cfg(set, &cfg));
|
||||
verify_rrset(set, "192.0.1.0/24", "1.2.3.4", 0, LDNS_RR_TYPE_A);
|
||||
verify_rrset(set, "192.0.1.0/24", "11.12.13.14", 1, LDNS_RR_TYPE_A);
|
||||
verify_rrset(set, "192.0.2.0/24", "www.example.com", 0, LDNS_RR_TYPE_CNAME);
|
||||
verify_rrset(set, "2001:db8:1::/48", "2001:db8:1::2:1", 0, LDNS_RR_TYPE_AAAA);
|
||||
}
|
||||
|
||||
/** Test per-view respip redirect w/ data directives */
|
||||
static void
|
||||
respip_view_conf_data_test(void)
|
||||
{
|
||||
struct config_file cfg;
|
||||
struct config_view* cv;
|
||||
int have_respip_cfg = 0;
|
||||
struct views* views = NULL;
|
||||
struct view* v = NULL;
|
||||
|
||||
unit_show_feature("per-view respip config data apply");
|
||||
memset(&cfg, 0, sizeof(cfg));
|
||||
cv = (struct config_view*)calloc(1, sizeof(struct config_view));
|
||||
unit_assert(cv);
|
||||
cv->name = strdup("view1");
|
||||
unit_assert(cv->name);
|
||||
cfg.views = cv;
|
||||
cfg_insert_respip_data(&cv->respip_actions, &cv->respip_data);
|
||||
views = views_create();
|
||||
unit_assert(views);
|
||||
unit_assert(views_apply_cfg(views, &cfg));
|
||||
|
||||
/* apply configuration and verify rrsets */
|
||||
unit_assert(respip_views_apply_cfg(views, &cfg, &have_respip_cfg));
|
||||
v = views_find_view(views, "view1", 0);
|
||||
unit_assert(v);
|
||||
verify_rrset(v->respip_set, "192.0.1.0/24", "1.2.3.4",
|
||||
0, LDNS_RR_TYPE_A);
|
||||
verify_rrset(v->respip_set, "192.0.1.0/24", "11.12.13.14",
|
||||
1, LDNS_RR_TYPE_A);
|
||||
verify_rrset(v->respip_set, "192.0.2.0/24", "www.example.com",
|
||||
0, LDNS_RR_TYPE_CNAME);
|
||||
verify_rrset(v->respip_set, "2001:db8:1::/48", "2001:db8:1::2:1",
|
||||
0, LDNS_RR_TYPE_AAAA);
|
||||
}
|
||||
|
||||
/** respip unit tests */
|
||||
static void respip_test(void)
|
||||
{
|
||||
respip_view_conf_data_test();
|
||||
respip_conf_data_test();
|
||||
respip_view_conf_actions_test();
|
||||
respip_conf_actions_test();
|
||||
}
|
||||
|
||||
void unit_show_func(const char* file, const char* func)
|
||||
{
|
||||
printf("test %s:%s\n", file, func);
|
||||
|
|
@ -604,6 +867,7 @@ main(int argc, char* argv[])
|
|||
checklock_start();
|
||||
neg_test();
|
||||
rnd_test();
|
||||
respip_test();
|
||||
verify_test();
|
||||
net_test();
|
||||
config_memsize_test();
|
||||
|
|
@ -618,6 +882,9 @@ main(int argc, char* argv[])
|
|||
infra_test();
|
||||
ldns_test();
|
||||
msgparse_test();
|
||||
#ifdef CLIENT_SUBNET
|
||||
ecs_test();
|
||||
#endif /* CLIENT_SUBNET */
|
||||
checklock_stop();
|
||||
printf("%d checks ok.\n", testcount);
|
||||
#ifdef HAVE_SSL
|
||||
|
|
|
|||
|
|
@ -72,6 +72,10 @@ void verify_test(void);
|
|||
void neg_test(void);
|
||||
/** unit test for regional allocator functions */
|
||||
void regional_test(void);
|
||||
#ifdef CLIENT_SUBNET
|
||||
/** Unit test for ECS functions */
|
||||
void ecs_test(void);
|
||||
#endif /* CLIENT_SUBNET */
|
||||
/** unit test for ldns functions */
|
||||
void ldns_test(void);
|
||||
|
||||
|
|
|
|||
|
|
@ -496,8 +496,10 @@ void
|
|||
verify_test(void)
|
||||
{
|
||||
unit_show_feature("signature verify");
|
||||
#ifdef USE_SHA1
|
||||
verifytest_file("testdata/test_signatures.1", "20070818005004");
|
||||
#ifdef USE_DSA
|
||||
#endif
|
||||
#if defined(USE_DSA) && defined(USE_SHA1)
|
||||
verifytest_file("testdata/test_signatures.2", "20080414005004");
|
||||
verifytest_file("testdata/test_signatures.3", "20080416005004");
|
||||
verifytest_file("testdata/test_signatures.4", "20080416005004");
|
||||
|
|
@ -505,17 +507,23 @@ verify_test(void)
|
|||
verifytest_file("testdata/test_signatures.6", "20080416005004");
|
||||
verifytest_file("testdata/test_signatures.7", "20070829144150");
|
||||
#endif /* USE_DSA */
|
||||
#ifdef USE_SHA1
|
||||
verifytest_file("testdata/test_signatures.8", "20070829144150");
|
||||
#endif
|
||||
#if (defined(HAVE_EVP_SHA256) || defined(HAVE_NSS) || defined(HAVE_NETTLE)) && defined(USE_SHA2)
|
||||
verifytest_file("testdata/test_sigs.rsasha256", "20070829144150");
|
||||
# ifdef USE_SHA1
|
||||
verifytest_file("testdata/test_sigs.sha1_and_256", "20070829144150");
|
||||
# endif
|
||||
verifytest_file("testdata/test_sigs.rsasha256_draft", "20090101000000");
|
||||
#endif
|
||||
#if (defined(HAVE_EVP_SHA512) || defined(HAVE_NSS) || defined(HAVE_NETTLE)) && defined(USE_SHA2)
|
||||
verifytest_file("testdata/test_sigs.rsasha512_draft", "20070829144150");
|
||||
#endif
|
||||
#ifdef USE_SHA1
|
||||
verifytest_file("testdata/test_sigs.hinfo", "20090107100022");
|
||||
verifytest_file("testdata/test_sigs.revoked", "20080414005004");
|
||||
#endif
|
||||
#ifdef USE_GOST
|
||||
if(sldns_key_EVP_load_gost_id())
|
||||
verifytest_file("testdata/test_sigs.gost", "20090807060504");
|
||||
|
|
@ -529,7 +537,9 @@ verify_test(void)
|
|||
}
|
||||
dstest_file("testdata/test_ds.sha384");
|
||||
#endif
|
||||
#ifdef USE_SHA1
|
||||
dstest_file("testdata/test_ds.sha1");
|
||||
#endif
|
||||
nsectest();
|
||||
nsec3_hash_test("testdata/test_nsec3_hash.1");
|
||||
}
|
||||
|
|
|
|||
BIN
testdata/03-testbound.tpkg
vendored
BIN
testdata/03-testbound.tpkg
vendored
Binary file not shown.
BIN
testdata/10-unbound-anchor.tpkg
vendored
BIN
testdata/10-unbound-anchor.tpkg
vendored
Binary file not shown.
1
testdata/autotrust_10key.rpl
vendored
1
testdata/autotrust_10key.rpl
vendored
|
|
@ -2,6 +2,7 @@
|
|||
server:
|
||||
target-fetch-policy: "0 0 0 0 0"
|
||||
log-time-ascii: yes
|
||||
fake-sha1: yes
|
||||
stub-zone:
|
||||
name: "."
|
||||
stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
|
||||
|
|
|
|||
1
testdata/autotrust_addpend_2exceed.rpl
vendored
1
testdata/autotrust_addpend_2exceed.rpl
vendored
|
|
@ -2,6 +2,7 @@
|
|||
server:
|
||||
target-fetch-policy: "0 0 0 0 0"
|
||||
log-time-ascii: yes
|
||||
fake-sha1: yes
|
||||
stub-zone:
|
||||
name: "."
|
||||
stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
|
||||
|
|
|
|||
1
testdata/autotrust_addpend_early.rpl
vendored
1
testdata/autotrust_addpend_early.rpl
vendored
|
|
@ -2,6 +2,7 @@
|
|||
server:
|
||||
target-fetch-policy: "0 0 0 0 0"
|
||||
log-time-ascii: yes
|
||||
fake-sha1: yes
|
||||
stub-zone:
|
||||
name: "."
|
||||
stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
|
||||
|
|
|
|||
1
testdata/autotrust_addpend_nosign.rpl
vendored
1
testdata/autotrust_addpend_nosign.rpl
vendored
|
|
@ -2,6 +2,7 @@
|
|||
server:
|
||||
target-fetch-policy: "0 0 0 0 0"
|
||||
log-time-ascii: yes
|
||||
fake-sha1: yes
|
||||
stub-zone:
|
||||
name: "."
|
||||
stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
|
||||
|
|
|
|||
1
testdata/autotrust_addpend_nosignnew.rpl
vendored
1
testdata/autotrust_addpend_nosignnew.rpl
vendored
|
|
@ -2,6 +2,7 @@
|
|||
server:
|
||||
target-fetch-policy: "0 0 0 0 0"
|
||||
log-time-ascii: yes
|
||||
fake-sha1: yes
|
||||
stub-zone:
|
||||
name: "."
|
||||
stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
|
||||
|
|
|
|||
1
testdata/autotrust_addpend_once.rpl
vendored
1
testdata/autotrust_addpend_once.rpl
vendored
|
|
@ -2,6 +2,7 @@
|
|||
server:
|
||||
target-fetch-policy: "0 0 0 0 0"
|
||||
log-time-ascii: yes
|
||||
fake-sha1: yes
|
||||
stub-zone:
|
||||
name: "."
|
||||
stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
|
||||
|
|
|
|||
1
testdata/autotrust_addpend_twice.rpl
vendored
1
testdata/autotrust_addpend_twice.rpl
vendored
|
|
@ -2,6 +2,7 @@
|
|||
server:
|
||||
target-fetch-policy: "0 0 0 0 0"
|
||||
log-time-ascii: yes
|
||||
fake-sha1: yes
|
||||
stub-zone:
|
||||
name: "."
|
||||
stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
|
||||
|
|
|
|||
1
testdata/autotrust_init.rpl
vendored
1
testdata/autotrust_init.rpl
vendored
|
|
@ -2,6 +2,7 @@
|
|||
server:
|
||||
target-fetch-policy: "0 0 0 0 0"
|
||||
log-time-ascii: yes
|
||||
fake-sha1: yes
|
||||
stub-zone:
|
||||
name: "."
|
||||
stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
|
||||
|
|
|
|||
1
testdata/autotrust_init_ds.rpl
vendored
1
testdata/autotrust_init_ds.rpl
vendored
|
|
@ -2,6 +2,7 @@
|
|||
server:
|
||||
target-fetch-policy: "0 0 0 0 0"
|
||||
log-time-ascii: yes
|
||||
fake-sha1: yes
|
||||
stub-zone:
|
||||
name: "."
|
||||
stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
|
||||
|
|
|
|||
1
testdata/autotrust_init_fail.rpl
vendored
1
testdata/autotrust_init_fail.rpl
vendored
|
|
@ -2,6 +2,7 @@
|
|||
server:
|
||||
target-fetch-policy: "0 0 0 0 0"
|
||||
log-time-ascii: yes
|
||||
fake-sha1: yes
|
||||
stub-zone:
|
||||
name: "."
|
||||
stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
|
||||
|
|
|
|||
1
testdata/autotrust_init_failsig.rpl
vendored
1
testdata/autotrust_init_failsig.rpl
vendored
|
|
@ -2,6 +2,7 @@
|
|||
server:
|
||||
target-fetch-policy: "0 0 0 0 0"
|
||||
log-time-ascii: yes
|
||||
fake-sha1: yes
|
||||
stub-zone:
|
||||
name: "."
|
||||
stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
|
||||
|
|
|
|||
1
testdata/autotrust_init_legacy.rpl
vendored
1
testdata/autotrust_init_legacy.rpl
vendored
|
|
@ -2,6 +2,7 @@
|
|||
server:
|
||||
target-fetch-policy: "0 0 0 0 0"
|
||||
log-time-ascii: yes
|
||||
fake-sha1: yes
|
||||
stub-zone:
|
||||
name: "."
|
||||
stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
|
||||
|
|
|
|||
1
testdata/autotrust_init_sigs.rpl
vendored
1
testdata/autotrust_init_sigs.rpl
vendored
|
|
@ -2,6 +2,7 @@
|
|||
server:
|
||||
target-fetch-policy: "0 0 0 0 0"
|
||||
log-time-ascii: yes
|
||||
fake-sha1: yes
|
||||
stub-zone:
|
||||
name: "."
|
||||
stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
|
||||
|
|
|
|||
1
testdata/autotrust_init_zsk.rpl
vendored
1
testdata/autotrust_init_zsk.rpl
vendored
|
|
@ -2,6 +2,7 @@
|
|||
server:
|
||||
target-fetch-policy: "0 0 0 0 0"
|
||||
log-time-ascii: yes
|
||||
fake-sha1: yes
|
||||
stub-zone:
|
||||
name: "."
|
||||
stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
|
||||
|
|
|
|||
1
testdata/autotrust_missing.rpl
vendored
1
testdata/autotrust_missing.rpl
vendored
|
|
@ -2,6 +2,7 @@
|
|||
server:
|
||||
target-fetch-policy: "0 0 0 0 0"
|
||||
log-time-ascii: yes
|
||||
fake-sha1: yes
|
||||
stub-zone:
|
||||
name: "."
|
||||
stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
|
||||
|
|
|
|||
1
testdata/autotrust_missing_all.rpl
vendored
1
testdata/autotrust_missing_all.rpl
vendored
|
|
@ -2,6 +2,7 @@
|
|||
server:
|
||||
target-fetch-policy: "0 0 0 0 0"
|
||||
log-time-ascii: yes
|
||||
fake-sha1: yes
|
||||
stub-zone:
|
||||
name: "."
|
||||
stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
|
||||
|
|
|
|||
1
testdata/autotrust_missing_returns.rpl
vendored
1
testdata/autotrust_missing_returns.rpl
vendored
|
|
@ -2,6 +2,7 @@
|
|||
server:
|
||||
target-fetch-policy: "0 0 0 0 0"
|
||||
log-time-ascii: yes
|
||||
fake-sha1: yes
|
||||
stub-zone:
|
||||
name: "."
|
||||
stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
|
||||
|
|
|
|||
1
testdata/autotrust_probefail.rpl
vendored
1
testdata/autotrust_probefail.rpl
vendored
|
|
@ -2,6 +2,7 @@
|
|||
server:
|
||||
target-fetch-policy: "0 0 0 0 0"
|
||||
log-time-ascii: yes
|
||||
fake-sha1: yes
|
||||
stub-zone:
|
||||
name: "."
|
||||
stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
|
||||
|
|
|
|||
1
testdata/autotrust_probefailsig.rpl
vendored
1
testdata/autotrust_probefailsig.rpl
vendored
|
|
@ -2,6 +2,7 @@
|
|||
server:
|
||||
target-fetch-policy: "0 0 0 0 0"
|
||||
log-time-ascii: yes
|
||||
fake-sha1: yes
|
||||
stub-zone:
|
||||
name: "."
|
||||
stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
|
||||
|
|
|
|||
1
testdata/autotrust_revoked_use.rpl
vendored
1
testdata/autotrust_revoked_use.rpl
vendored
|
|
@ -2,6 +2,7 @@
|
|||
server:
|
||||
target-fetch-policy: "0 0 0 0 0"
|
||||
log-time-ascii: yes
|
||||
fake-sha1: yes
|
||||
stub-zone:
|
||||
name: "."
|
||||
stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
|
||||
|
|
|
|||
1
testdata/autotrust_revoked_with_invalid.rpl
vendored
1
testdata/autotrust_revoked_with_invalid.rpl
vendored
|
|
@ -2,6 +2,7 @@
|
|||
server:
|
||||
target-fetch-policy: "0 0 0 0 0"
|
||||
log-time-ascii: yes
|
||||
fake-sha1: yes
|
||||
stub-zone:
|
||||
name: "."
|
||||
stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue