mirror of
https://github.com/NLnetLabs/unbound.git
synced 2026-08-17 21:25:50 +02:00
Compare commits
274
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ac98f4806f | ||
|
|
171a7a107e | ||
|
|
6195229d76 | ||
|
|
062515d9bc | ||
|
|
311264b960 | ||
|
|
bdd2cd248d | ||
|
|
1f6a7da0b0 | ||
|
|
71d2d60b85 | ||
|
|
4e66465e22 | ||
|
|
2288777334 | ||
|
|
cf0429f3e1 | ||
|
|
dff6c5ff7a | ||
|
|
df78cb7ccb | ||
|
|
acada5a8f6 | ||
|
|
20f8dafcd4 | ||
|
|
7bb1d8a8d1 | ||
|
|
39b5f5bbc6 | ||
|
|
7ebe1fe115 | ||
|
|
843bd4156e | ||
|
|
ca8d0a0e92 | ||
|
|
5989d675ce | ||
|
|
c4869780d1 | ||
|
|
998793998d | ||
|
|
e2459be7e1 | ||
|
|
33de42e729 | ||
|
|
b3b854072b | ||
|
|
54eabdde58 | ||
|
|
6e6ff89972 | ||
|
|
0992621839 | ||
|
|
7e9d37acae | ||
|
|
bfddc0dc64 | ||
|
|
b9196d48d2 | ||
|
|
75cb40edd1 | ||
|
|
124f8d57ab | ||
|
|
f78e04a12c | ||
|
|
b93fd4e0c9 | ||
|
|
401e456a17 | ||
|
|
69828ed94b | ||
|
|
627299f5e4 | ||
|
|
e4c60435d2 | ||
|
|
486edb10db | ||
|
|
8c4e7ffb14 | ||
|
|
dd0da65da9 | ||
|
|
75395a12e5 | ||
|
|
8b2397542e | ||
|
|
6132c9f8d5 | ||
|
|
ca57014bf2 | ||
|
|
3304a4f622 | ||
|
|
6538b82928 | ||
|
|
aa1b0fca72 | ||
|
|
aa9365446b | ||
|
|
632c1e83f8 | ||
|
|
115c8f8dd5 | ||
|
|
b8f4099e55 | ||
|
|
6c899d8947 | ||
|
|
3b5b21d29f | ||
|
|
65dde0c965 | ||
|
|
eb3144bacb | ||
|
|
efd19f766f | ||
|
|
4c8fb76a72 | ||
|
|
37c1739483 | ||
|
|
71fba3d221 | ||
|
|
1a44a8402e | ||
|
|
f8000b355e | ||
|
|
1329ff5f36 | ||
|
|
658c759b3d | ||
|
|
6e0ba733f3 | ||
|
|
0b10c8da28 | ||
|
|
0d271cbb09 | ||
|
|
a40e8ae321 | ||
|
|
95544096bf | ||
|
|
58fc4b8ea8 | ||
|
|
cf2da96a28 | ||
|
|
e1b6145e5c | ||
|
|
903fe8db7e | ||
|
|
39be1377e2 | ||
|
|
de4c7bd317 | ||
|
|
f78acf53fb | ||
|
|
92d625b648 | ||
|
|
305f6f0295 | ||
|
|
7641f23f87 | ||
|
|
491b0a26e4 | ||
|
|
5febdd39a1 | ||
|
|
c5cfa6c09c | ||
|
|
d0d6e34746 | ||
|
|
1db056b19c | ||
|
|
893159454f | ||
|
|
ce54c45394 | ||
|
|
4e502fd624 | ||
|
|
ad2e157763 | ||
|
|
d42090d63b | ||
|
|
1d181f0ade | ||
|
|
93d1d33f3f | ||
|
|
9649cc8c50 | ||
|
|
cb26ca2ce7 | ||
|
|
657948dd0c | ||
|
|
7e8d548d24 | ||
|
|
4770bfbb5b | ||
|
|
3018dc636a | ||
|
|
f610f40558 | ||
|
|
eb67febcc4 | ||
|
|
3676f20923 | ||
|
|
7940e854e6 | ||
|
|
cb253fafe7 | ||
|
|
33001c8c4b | ||
|
|
a511d5d95e | ||
|
|
619b808b31 | ||
|
|
56bde1ceca | ||
|
|
7925a98141 | ||
|
|
461c8c97db | ||
|
|
593949c88e | ||
|
|
73873da0c0 | ||
|
|
dae84a96fb | ||
|
|
89c2383c71 | ||
|
|
582a7f449e | ||
|
|
8d853b7eb6 | ||
|
|
a482b5cf12 | ||
|
|
0f8b560bd5 | ||
|
|
8466ee1c62 | ||
|
|
d4e0116ba8 | ||
|
|
16f2e53d5f | ||
|
|
17dd3370fc | ||
|
|
710778dfdd | ||
|
|
ef589f8981 | ||
|
|
16428ccbd2 | ||
|
|
c9e5433a70 | ||
|
|
4b39a9eaf8 | ||
|
|
1c02193ddb | ||
|
|
2be864c218 | ||
|
|
22339c9ba9 | ||
|
|
a8bfa02af1 | ||
|
|
8fedcffc02 | ||
|
|
5a0ae9a055 | ||
|
|
4d7d32c846 | ||
|
|
e3058de235 | ||
|
|
d7304e7c75 | ||
|
|
bde9269510 | ||
|
|
a5c7c469ee | ||
|
|
4e0787dcf3 | ||
|
|
7e59ef65e6 | ||
|
|
06e794898f | ||
|
|
5591fdff8d | ||
|
|
ae31233b19 | ||
|
|
b96a41d19e | ||
|
|
a416f30459 | ||
|
|
a2bc93547f | ||
|
|
bdac428d79 | ||
|
|
f7595c3348 | ||
|
|
a5abaed4ce | ||
|
|
7338c1b892 | ||
|
|
4321a363a4 | ||
|
|
d30ae35c62 | ||
|
|
292a337dad | ||
|
|
897635b32b | ||
|
|
e56c63172c | ||
|
|
3f7af974a3 | ||
|
|
d8272d4010 | ||
|
|
1163c6345b | ||
|
|
b7a9969e73 | ||
|
|
4fb762f6e4 | ||
|
|
78fecfe558 | ||
|
|
02282ba679 | ||
|
|
553544feac | ||
|
|
b0fd814975 | ||
|
|
80029d63f0 | ||
|
|
f0bf15d2cb | ||
|
|
fadd01e93e | ||
|
|
29ac62d7b0 | ||
|
|
01697a9ab8 | ||
|
|
d1cbf19798 | ||
|
|
451e1900a9 | ||
|
|
86f0baf146 | ||
|
|
7c9584e408 | ||
|
|
f952ac1dee | ||
|
|
52dd15dd87 | ||
|
|
984c6c33bc | ||
|
|
84be084384 | ||
|
|
91bafce012 | ||
|
|
77b328475a | ||
|
|
cc31f2f6e9 | ||
|
|
a83c7764f5 | ||
|
|
f374268521 | ||
|
|
ca48de34e9 | ||
|
|
2042facc8b | ||
|
|
df947d4056 | ||
|
|
3d6783e38c | ||
|
|
6c456aa15e | ||
|
|
bf1b3c1166 | ||
|
|
45517ad616 | ||
|
|
6d57b0ddb7 | ||
|
|
038550c889 | ||
|
|
2b9d47ff01 | ||
|
|
bc64aa2cf2 | ||
|
|
a6fba1b8a6 | ||
|
|
05215e8e7d | ||
|
|
fdbac8e51d | ||
|
|
e3385174c3 | ||
|
|
94ce9cad2a | ||
|
|
6ac9904ee5 | ||
|
|
4a429c11d5 | ||
|
|
cbf8c632dc | ||
|
|
578fc220ad | ||
|
|
cae9809e11 | ||
|
|
570564a375 | ||
|
|
5058406b84 | ||
|
|
7e6e9a0155 | ||
|
|
6137f1b0b2 | ||
|
|
689fdc1d0b | ||
|
|
791767d62f | ||
|
|
7455717359 | ||
|
|
3289d8482c | ||
|
|
8ce59e67d5 | ||
|
|
5f48fa3a6e | ||
|
|
0fff8a32b5 | ||
|
|
975c915632 | ||
|
|
307c1b3321 | ||
|
|
37da5dcdb6 | ||
|
|
35ae8ef313 | ||
|
|
14ec958b8f | ||
|
|
5b34bde1a4 | ||
|
|
44cfd1d49b | ||
|
|
7b1687ac0e | ||
|
|
648c15fbac | ||
|
|
34fd9dd88d | ||
|
|
37799b8560 | ||
|
|
64adf68436 | ||
|
|
f97dcc8e40 | ||
|
|
86dcdaae33 | ||
|
|
9fb526d554 | ||
|
|
e338cb00f3 | ||
|
|
d3edcc3fab | ||
|
|
e6a54f732e | ||
|
|
2e7c9ad2f3 | ||
|
|
367c3f034e | ||
|
|
901d83fcff | ||
|
|
4b22dcb7ad | ||
|
|
86c28f2d57 | ||
|
|
41fccf9fe4 | ||
|
|
4c17395deb | ||
|
|
240a012bd8 | ||
|
|
929b623e59 | ||
|
|
709d8223f5 | ||
|
|
8746283787 | ||
|
|
ff1b857f90 | ||
|
|
c010e93d4a | ||
|
|
5d522b0017 | ||
|
|
42c2282f12 | ||
|
|
8e23542b85 | ||
|
|
ef80a99397 | ||
|
|
ba11247f93 | ||
|
|
e5431ca7e5 | ||
|
|
b019a6aad9 | ||
|
|
3a1ffe4c69 | ||
|
|
9b4b0de746 | ||
|
|
a3441215f1 | ||
|
|
5adb2dc4cf | ||
|
|
3f7248fa11 | ||
|
|
5839981255 | ||
|
|
cd7db58ce3 | ||
|
|
3d74d8e95b | ||
|
|
3869421258 | ||
|
|
b4b2c18909 | ||
|
|
95d5334783 | ||
|
|
6f757b28f3 | ||
|
|
db2cf53e7b | ||
|
|
33ba1f38d6 | ||
|
|
3d680a6d82 | ||
|
|
c9bcf1b3f7 | ||
|
|
242b255aac | ||
|
|
5351f69e49 | ||
|
|
631d2b4214 | ||
|
|
235e1399eb | ||
|
|
163e7046cb | ||
|
|
41d174b7f6 |
@@ -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
|
||||
|
||||
+393
-199
@@ -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,12 @@ 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@
|
||||
IPSECMOD_SRC=ipsecmod/ipsecmod.c ipsecmod/ipsecmod-whitelist.c
|
||||
IPSECMOD_OBJ=@IPSECMOD_OBJ@
|
||||
IPSECMOD_HEADER=@IPSECMOD_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 +112,7 @@ iterator/iter_scrub.c iterator/iter_utils.c services/listen_dnsport.c \
|
||||
services/localzone.c services/mesh.c services/modstack.c services/view.c \
|
||||
services/outbound_list.c services/outside_network.c util/alloc.c \
|
||||
util/config_file.c util/configlexer.c util/configparser.c \
|
||||
util/shm_side/shm_main.c services/authzone.c\
|
||||
util/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 +121,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) $(IPSECMOD_SRC)
|
||||
COMMON_OBJ_WITHOUT_NETCALL=dns.lo infra.lo rrset.lo dname.lo msgencode.lo \
|
||||
as112.lo msgparse.lo msgreply.lo packed_rrset.lo iterator.lo iter_delegpt.lo \
|
||||
iter_donotq.lo iter_fwd.lo iter_hints.lo iter_priv.lo iter_resptype.lo \
|
||||
@@ -123,8 +135,10 @@ fptr_wlist.lo locks.lo log.lo mini_event.lo module.lo net_help.lo \
|
||||
random.lo rbtree.lo regional.lo rtt.lo dnstree.lo lookup3.lo lruhash.lo \
|
||||
slabhash.lo timehist.lo tube.lo winsock_event.lo autotrust.lo val_anchor.lo \
|
||||
validator.lo val_kcache.lo val_kentry.lo val_neg.lo val_nsec3.lo val_nsec.lo \
|
||||
val_secalgo.lo val_sigcrypt.lo val_utils.lo dns64.lo cachedb.lo \
|
||||
$(PYTHONMOD_OBJ) $(CHECKLOCK_OBJ) $(DNSTAP_OBJ)
|
||||
val_secalgo.lo val_sigcrypt.lo val_utils.lo dns64.lo cachedb.lo authzone.lo\
|
||||
$(SUBNET_OBJ) $(PYTHONMOD_OBJ) $(CHECKLOCK_OBJ) $(DNSTAP_OBJ) $(DNSCRYPT_OBJ) \
|
||||
$(IPSECMOD_OBJ)
|
||||
COMMON_OBJ_WITHOUT_NETCALL+=respip.lo
|
||||
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 +162,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 testcode/unitauth.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 unitauth.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 +195,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 +394,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 +606,10 @@ 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?$$(srcdir)/ipsecmod/ipsecmod.h $$(srcdir)/ipsecmod/ipsecmod-whitelist.h?$$(IPSECMOD_HEADER)?g' \
|
||||
-e 's!\(.*\)\.o[ :]*!\1.lo \1.o: !g' \
|
||||
> $(DEPEND_TMP)
|
||||
cp $(DEPEND_TARGET) $(DEPEND_TMP2)
|
||||
@@ -602,17 +627,19 @@ depend:
|
||||
# Dependencies
|
||||
dns.lo dns.o: $(srcdir)/services/cache/dns.c config.h $(srcdir)/iterator/iter_delegpt.h $(srcdir)/util/log.h \
|
||||
$(srcdir)/validator/val_nsec.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h \
|
||||
$(srcdir)/util/locks.h $(srcdir)/services/cache/dns.h $(srcdir)/util/data/msgreply.h \
|
||||
$(srcdir)/services/cache/rrset.h $(srcdir)/util/storage/slabhash.h $(srcdir)/util/data/dname.h \
|
||||
$(srcdir)/util/module.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h \
|
||||
$(srcdir)/util/net_help.h $(srcdir)/util/regional.h $(srcdir)/util/config_file.h $(srcdir)/sldns/sbuffer.h
|
||||
$(srcdir)/util/locks.h $(srcdir)/validator/val_utils.h $(srcdir)/services/cache/dns.h \
|
||||
$(srcdir)/util/data/msgreply.h $(srcdir)/services/cache/rrset.h $(srcdir)/util/storage/slabhash.h \
|
||||
$(srcdir)/util/data/dname.h $(srcdir)/util/module.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h \
|
||||
$(srcdir)/sldns/rrdef.h $(srcdir)/util/net_help.h $(srcdir)/util/regional.h $(srcdir)/util/config_file.h \
|
||||
$(srcdir)/sldns/sbuffer.h
|
||||
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/dnstree.h $(srcdir)/util/rbtree.h $(srcdir)/util/rtt.h $(srcdir)/util/netevent.h \
|
||||
$(srcdir)/dnscrypt/dnscrypt.h $(srcdir)/dnscrypt/cert.h \
|
||||
$(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/slabhash.h \
|
||||
$(srcdir)/util/storage/lookup3.h $(srcdir)/util/data/dname.h $(srcdir)/util/net_help.h \
|
||||
$(srcdir)/util/config_file.h $(srcdir)/iterator/iterator.h $(srcdir)/services/outbound_list.h \
|
||||
$(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/module.h \
|
||||
$(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.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,7 +661,8 @@ 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/storage/lookup3.h $(srcdir)/util/alloc.h $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
|
||||
$(srcdir)/dnscrypt/cert.h $(srcdir)/util/net_help.h \
|
||||
$(srcdir)/util/data/dname.h $(srcdir)/util/regional.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h \
|
||||
$(srcdir)/sldns/rrdef.h $(srcdir)/util/data/msgencode.h $(srcdir)/sldns/sbuffer.h $(srcdir)/sldns/wire2str.h \
|
||||
$(srcdir)/util/module.h $(srcdir)/util/fptr_wlist.h $(srcdir)/util/tube.h $(srcdir)/services/mesh.h \
|
||||
@@ -651,10 +679,12 @@ 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/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
|
||||
$(srcdir)/util/rtt.h $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
|
||||
$(srcdir)/dnscrypt/cert.h $(srcdir)/util/net_help.h \
|
||||
$(srcdir)/util/regional.h $(srcdir)/util/data/dname.h $(srcdir)/util/data/msgencode.h \
|
||||
$(srcdir)/util/fptr_wlist.h $(srcdir)/util/tube.h $(srcdir)/services/mesh.h $(srcdir)/services/modstack.h \
|
||||
$(srcdir)/util/config_file.h $(srcdir)/util/random.h $(srcdir)/sldns/wire2str.h $(srcdir)/sldns/str2wire.h \
|
||||
$(srcdir)/sldns/parseutil.h $(srcdir)/sldns/sbuffer.h
|
||||
iter_delegpt.lo iter_delegpt.o: $(srcdir)/iterator/iter_delegpt.c config.h $(srcdir)/iterator/iter_delegpt.h \
|
||||
$(srcdir)/util/log.h $(srcdir)/services/cache/dns.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h \
|
||||
$(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/regional.h \
|
||||
@@ -695,15 +725,17 @@ 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/infra.h $(srcdir)/util/rtt.h $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
|
||||
$(srcdir)/dnscrypt/cert.h $(srcdir)/services/cache/dns.h \
|
||||
$(srcdir)/services/cache/rrset.h $(srcdir)/util/storage/slabhash.h $(srcdir)/util/net_help.h \
|
||||
$(srcdir)/util/config_file.h $(srcdir)/util/regional.h $(srcdir)/util/data/dname.h $(srcdir)/util/random.h \
|
||||
$(srcdir)/util/fptr_wlist.h $(srcdir)/util/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)/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)/services/listen_dnsport.h $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
|
||||
$(srcdir)/dnscrypt/cert.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 \
|
||||
@@ -712,23 +744,31 @@ localzone.lo localzone.o: $(srcdir)/services/localzone.c config.h $(srcdir)/serv
|
||||
$(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)/dnscrypt/cert.h \
|
||||
$(srcdir)/util/as112.h
|
||||
mesh.lo mesh.o: $(srcdir)/services/mesh.c config.h $(srcdir)/services/mesh.h $(srcdir)/util/rbtree.h \
|
||||
$(srcdir)/util/netevent.h $(srcdir)/util/data/msgparse.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h \
|
||||
$(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
|
||||
$(srcdir)/dnscrypt/cert.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)/services/view.h $(srcdir)/util/data/dname.h $(srcdir)/respip/respip.h
|
||||
modstack.lo modstack.o: $(srcdir)/services/modstack.c config.h $(srcdir)/services/modstack.h \
|
||||
$(srcdir)/util/module.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \
|
||||
$(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgparse.h \
|
||||
$(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/fptr_wlist.h $(srcdir)/util/netevent.h \
|
||||
$(srcdir)/dnscrypt/dnscrypt.h $(srcdir)/dnscrypt/cert.h \
|
||||
$(srcdir)/util/tube.h $(srcdir)/services/mesh.h $(srcdir)/util/rbtree.h $(srcdir)/dns64/dns64.h \
|
||||
$(srcdir)/iterator/iterator.h $(srcdir)/services/outbound_list.h $(srcdir)/validator/validator.h \
|
||||
$(srcdir)/validator/val_utils.h $(PYTHONMOD_HEADER)
|
||||
$(srcdir)/validator/val_utils.h $(srcdir)/respip/respip.h $(srcdir)/services/localzone.h \
|
||||
$(srcdir)/util/storage/dnstree.h $(srcdir)/services/view.h $(PYTHONMOD_HEADER) \
|
||||
$(srcdir)/cachedb/cachedb.h $(srcdir)/ipsecmod/ipsecmod.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,73 +776,107 @@ 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 \
|
||||
$(srcdir)/dnscrypt/cert.h
|
||||
outside_network.lo outside_network.o: $(srcdir)/services/outside_network.c config.h \
|
||||
$(srcdir)/services/outside_network.h $(srcdir)/util/rbtree.h $(srcdir)/util/netevent.h \
|
||||
$(srcdir)/dnscrypt/dnscrypt.h $(srcdir)/dnscrypt/cert.h \
|
||||
$(srcdir)/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/rtt.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h \
|
||||
$(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/data/msgencode.h \
|
||||
$(srcdir)/util/data/dname.h $(srcdir)/util/net_help.h $(srcdir)/util/random.h $(srcdir)/util/fptr_wlist.h \
|
||||
$(srcdir)/util/module.h $(srcdir)/util/tube.h $(srcdir)/services/mesh.h $(srcdir)/services/modstack.h \
|
||||
$(srcdir)/sldns/sbuffer.h $(srcdir)/dnstap/dnstap.h
|
||||
$(srcdir)/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/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/fptr_wlist.h $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
|
||||
$(srcdir)/dnscrypt/cert.h $(srcdir)/util/module.h \
|
||||
$(srcdir)/util/data/msgreply.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h \
|
||||
$(srcdir)/util/tube.h $(srcdir)/services/mesh.h $(srcdir)/util/rbtree.h $(srcdir)/services/modstack.h
|
||||
config_file.lo config_file.o: $(srcdir)/util/config_file.c config.h $(srcdir)/util/log.h \
|
||||
$(srcdir)/util/configyyrename.h $(srcdir)/util/config_file.h util/configparser.h \
|
||||
$(srcdir)/util/net_help.h $(srcdir)/util/data/msgparse.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h \
|
||||
$(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/module.h $(srcdir)/util/data/msgreply.h \
|
||||
$(srcdir)/util/data/packed_rrset.h $(srcdir)/util/regional.h $(srcdir)/util/fptr_wlist.h \
|
||||
$(srcdir)/util/netevent.h $(srcdir)/util/tube.h $(srcdir)/services/mesh.h $(srcdir)/util/rbtree.h \
|
||||
$(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
|
||||
$(srcdir)/dnscrypt/cert.h $(srcdir)/util/tube.h $(srcdir)/services/mesh.h $(srcdir)/util/rbtree.h \
|
||||
$(srcdir)/services/modstack.h $(srcdir)/util/data/dname.h $(srcdir)/util/rtt.h $(srcdir)/services/cache/infra.h \
|
||||
$(srcdir)/util/storage/dnstree.h $(srcdir)/sldns/wire2str.h $(srcdir)/sldns/parseutil.h \
|
||||
$(srcdir)/util/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)/libunbound/unbound.h $(srcdir)/daemon/daemon.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \
|
||||
$(srcdir)/util/alloc.h $(srcdir)/services/modstack.h \
|
||||
$(srcdir)/daemon/worker.h $(srcdir)/libunbound/worker.h \
|
||||
$(srcdir)/sldns/sbuffer.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h \
|
||||
$(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h $(srcdir)/dnscrypt/cert.h $(srcdir)/util/data/msgreply.h \
|
||||
$(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/daemon/stats.h \
|
||||
$(srcdir)/util/timehist.h $(srcdir)/util/module.h $(srcdir)/dnstap/dnstap.h $(srcdir)/services/mesh.h \
|
||||
$(srcdir)/util/rbtree.h $(srcdir)/services/cache/rrset.h $(srcdir)/util/storage/slabhash.h \
|
||||
$(srcdir)/services/cache/infra.h $(srcdir)/util/storage/dnstree.h $(srcdir)/util/rtt.h \
|
||||
$(srcdir)/validator/validator.h $(srcdir)/validator/val_utils.h $(srcdir)/util/config_file.h \
|
||||
$(srcdir)/util/fptr_wlist.h $(srcdir)/util/tube.h
|
||||
authzone.lo authzone.o: $(srcdir)/services/authzone.c config.h $(srcdir)/services/authzone.h \
|
||||
$(srcdir)/util/rbtree.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/data/dname.h \
|
||||
$(srcdir)/util/storage/lruhash.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h \
|
||||
$(srcdir)/util/regional.h $(srcdir)/util/net_help.h $(srcdir)/util/config_file.h $(srcdir)/services/cache/dns.h \
|
||||
$(srcdir)/sldns/rrdef.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/sbuffer.h $(srcdir)/sldns/str2wire.h \
|
||||
$(srcdir)/sldns/wire2str.h $(srcdir)/sldns/parseutil.h $(srcdir)/validator/val_nsec3.h \
|
||||
$(srcdir)/validator/val_secalgo.h
|
||||
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/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
|
||||
$(srcdir)/dnscrypt/cert.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)/services/authzone.h $(srcdir)/services/cache/infra.h $(srcdir)/util/rtt.h \
|
||||
$(srcdir)/services/cache/rrset.h $(srcdir)/util/storage/slabhash.h $(srcdir)/dns64/dns64.h \
|
||||
$(srcdir)/iterator/iterator.h $(srcdir)/services/outbound_list.h $(srcdir)/iterator/iter_fwd.h \
|
||||
$(srcdir)/validator/validator.h $(srcdir)/validator/val_utils.h $(srcdir)/validator/val_anchor.h \
|
||||
$(srcdir)/validator/val_nsec3.h $(srcdir)/validator/val_sigcrypt.h $(srcdir)/validator/val_kentry.h \
|
||||
$(srcdir)/validator/val_neg.h $(srcdir)/validator/autotrust.h $(srcdir)/libunbound/libworker.h \
|
||||
$(srcdir)/libunbound/context.h $(srcdir)/util/alloc.h $(srcdir)/libunbound/unbound.h \
|
||||
$(srcdir)/libunbound/worker.h $(srcdir)/sldns/sbuffer.h $(srcdir)/util/config_file.h $(srcdir)/respip/respip.h \
|
||||
$(PYTHONMOD_HEADER) $(srcdir)/cachedb/cachedb.h $(srcdir)/ipsecmod/ipsecmod.h \
|
||||
$(srcdir)/edns-subnet/subnetmod.h $(srcdir)/util/net_help.h $(srcdir)/edns-subnet/addrtree.h \
|
||||
$(srcdir)/edns-subnet/edns-subnet.h
|
||||
locks.lo locks.o: $(srcdir)/util/locks.c config.h $(srcdir)/util/locks.h $(srcdir)/util/log.h
|
||||
log.lo log.o: $(srcdir)/util/log.c config.h $(srcdir)/util/log.h $(srcdir)/util/locks.h $(srcdir)/sldns/sbuffer.h
|
||||
mini_event.lo mini_event.o: $(srcdir)/util/mini_event.c config.h $(srcdir)/util/mini_event.h $(srcdir)/util/rbtree.h \
|
||||
$(srcdir)/util/fptr_wlist.h $(srcdir)/util/netevent.h $(srcdir)/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/fptr_wlist.h $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
|
||||
$(srcdir)/dnscrypt/cert.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 \
|
||||
netevent.lo netevent.o: $(srcdir)/util/netevent.c config.h $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
|
||||
$(srcdir)/dnscrypt/cert.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
|
||||
$(srcdir)/dnstap/dnstap.h \
|
||||
|
||||
net_help.lo net_help.o: $(srcdir)/util/net_help.c config.h $(srcdir)/util/net_help.h $(srcdir)/util/log.h \
|
||||
$(srcdir)/util/data/dname.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/module.h \
|
||||
$(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgparse.h \
|
||||
$(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/regional.h $(srcdir)/sldns/parseutil.h \
|
||||
$(srcdir)/sldns/wire2str.h
|
||||
$(srcdir)/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/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
|
||||
$(srcdir)/dnscrypt/cert.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
|
||||
@@ -813,22 +887,26 @@ 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/data/msgreply.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgparse.h \
|
||||
$(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/tube.h $(srcdir)/services/mesh.h $(srcdir)/util/rbtree.h \
|
||||
$(srcdir)/services/modstack.h
|
||||
$(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/fptr_wlist.h $(srcdir)/util/netevent.h \
|
||||
$(srcdir)/dnscrypt/dnscrypt.h $(srcdir)/dnscrypt/cert.h \
|
||||
$(srcdir)/util/module.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h \
|
||||
$(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/tube.h \
|
||||
$(srcdir)/services/mesh.h $(srcdir)/util/rbtree.h $(srcdir)/services/modstack.h
|
||||
slabhash.lo slabhash.o: $(srcdir)/util/storage/slabhash.c config.h $(srcdir)/util/storage/slabhash.h \
|
||||
$(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h
|
||||
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/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
|
||||
$(srcdir)/dnscrypt/cert.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)/dnscrypt/cert.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)/dnscrypt/cert.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 +918,11 @@ 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/mesh.h $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
|
||||
$(srcdir)/dnscrypt/cert.h $(srcdir)/services/modstack.h \
|
||||
$(srcdir)/services/cache/rrset.h $(srcdir)/util/storage/slabhash.h $(srcdir)/validator/val_kcache.h \
|
||||
$(srcdir)/sldns/sbuffer.h $(srcdir)/sldns/wire2str.h $(srcdir)/sldns/str2wire.h $(srcdir)/sldns/keyraw.h
|
||||
$(srcdir)/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 +937,9 @@ 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)/dnscrypt/cert.h $(srcdir)/util/tube.h $(srcdir)/services/mesh.h $(srcdir)/services/modstack.h \
|
||||
$(srcdir)/sldns/wire2str.h $(srcdir)/sldns/str2wire.h
|
||||
val_kcache.lo val_kcache.o: $(srcdir)/validator/val_kcache.c config.h $(srcdir)/validator/val_kcache.h \
|
||||
$(srcdir)/util/storage/slabhash.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \
|
||||
$(srcdir)/validator/val_kentry.h $(srcdir)/util/config_file.h $(srcdir)/util/data/dname.h \
|
||||
@@ -867,13 +948,15 @@ val_kcache.lo val_kcache.o: $(srcdir)/validator/val_kcache.c config.h $(srcdir)/
|
||||
val_kentry.lo val_kentry.o: $(srcdir)/validator/val_kentry.c config.h $(srcdir)/validator/val_kentry.h \
|
||||
$(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/data/packed_rrset.h \
|
||||
$(srcdir)/util/data/dname.h $(srcdir)/util/storage/lookup3.h $(srcdir)/util/regional.h $(srcdir)/util/net_help.h \
|
||||
$(srcdir)/sldns/rrdef.h $(srcdir)/sldns/keyraw.h
|
||||
val_neg.lo val_neg.o: $(srcdir)/validator/val_neg.c config.h $(srcdir)/validator/val_neg.h $(srcdir)/util/locks.h \
|
||||
$(srcdir)/util/log.h $(srcdir)/util/rbtree.h $(srcdir)/validator/val_nsec.h $(srcdir)/util/data/packed_rrset.h \
|
||||
$(srcdir)/util/storage/lruhash.h $(srcdir)/validator/val_nsec3.h $(srcdir)/validator/val_utils.h \
|
||||
$(srcdir)/util/data/dname.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/net_help.h \
|
||||
$(srcdir)/util/config_file.h $(srcdir)/services/cache/rrset.h $(srcdir)/util/storage/slabhash.h \
|
||||
$(srcdir)/services/cache/dns.h $(srcdir)/sldns/rrdef.h $(srcdir)/sldns/sbuffer.h
|
||||
$(srcdir)/sldns/rrdef.h $(srcdir)/sldns/keyraw.h \
|
||||
|
||||
val_neg.lo val_neg.o: $(srcdir)/validator/val_neg.c config.h \
|
||||
$(srcdir)/validator/val_neg.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/rbtree.h \
|
||||
$(srcdir)/validator/val_nsec.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h \
|
||||
$(srcdir)/validator/val_nsec3.h $(srcdir)/validator/val_utils.h $(srcdir)/util/data/dname.h \
|
||||
$(srcdir)/util/data/msgreply.h $(srcdir)/util/net_help.h $(srcdir)/util/config_file.h \
|
||||
$(srcdir)/services/cache/rrset.h $(srcdir)/util/storage/slabhash.h $(srcdir)/services/cache/dns.h \
|
||||
$(srcdir)/sldns/rrdef.h $(srcdir)/sldns/sbuffer.h
|
||||
val_nsec3.lo val_nsec3.o: $(srcdir)/validator/val_nsec3.c config.h $(srcdir)/validator/val_nsec3.h \
|
||||
$(srcdir)/util/rbtree.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h \
|
||||
$(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/validator/val_secalgo.h $(srcdir)/validator/validator.h \
|
||||
@@ -889,14 +972,16 @@ val_nsec.lo val_nsec.o: $(srcdir)/validator/val_nsec.c config.h $(srcdir)/valida
|
||||
val_secalgo.lo val_secalgo.o: $(srcdir)/validator/val_secalgo.c config.h $(srcdir)/util/data/packed_rrset.h \
|
||||
$(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/validator/val_secalgo.h \
|
||||
$(srcdir)/validator/val_nsec3.h $(srcdir)/util/rbtree.h $(srcdir)/sldns/rrdef.h $(srcdir)/sldns/keyraw.h \
|
||||
$(srcdir)/sldns/sbuffer.h
|
||||
$(srcdir)/sldns/sbuffer.h \
|
||||
|
||||
val_sigcrypt.lo val_sigcrypt.o: $(srcdir)/validator/val_sigcrypt.c config.h \
|
||||
$(srcdir)/validator/val_sigcrypt.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h \
|
||||
$(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/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 \
|
||||
@@ -904,17 +989,72 @@ val_utils.lo val_utils.o: $(srcdir)/validator/val_utils.c config.h $(srcdir)/val
|
||||
$(srcdir)/validator/val_sigcrypt.h $(srcdir)/validator/val_anchor.h $(srcdir)/util/rbtree.h \
|
||||
$(srcdir)/validator/val_nsec.h $(srcdir)/validator/val_neg.h $(srcdir)/services/cache/rrset.h \
|
||||
$(srcdir)/util/storage/slabhash.h $(srcdir)/services/cache/dns.h $(srcdir)/util/data/dname.h \
|
||||
$(srcdir)/util/net_help.h $(srcdir)/util/regional.h $(srcdir)/sldns/wire2str.h $(srcdir)/sldns/parseutil.h
|
||||
$(srcdir)/util/net_help.h $(srcdir)/util/regional.h $(srcdir)/util/config_file.h $(srcdir)/sldns/wire2str.h \
|
||||
$(srcdir)/sldns/parseutil.h
|
||||
dns64.lo dns64.o: $(srcdir)/dns64/dns64.c config.h $(srcdir)/dns64/dns64.h $(srcdir)/util/module.h \
|
||||
$(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/data/msgreply.h \
|
||||
$(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h \
|
||||
$(srcdir)/sldns/rrdef.h $(srcdir)/services/cache/dns.h $(srcdir)/services/cache/rrset.h \
|
||||
$(srcdir)/util/storage/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)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
|
||||
$(srcdir)/dnscrypt/cert.h $(srcdir)/util/tube.h $(srcdir)/services/mesh.h $(srcdir)/util/rbtree.h \
|
||||
$(srcdir)/services/modstack.h $(srcdir)/util/net_help.h $(srcdir)/util/regional.h
|
||||
cachedb.lo cachedb.o: $(srcdir)/cachedb/cachedb.c config.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)/dnscrypt/cert.h \
|
||||
$(srcdir)/services/modstack.h $(srcdir)/services/cache/dns.h $(srcdir)/util/regional.h \
|
||||
$(srcdir)/util/config_file.h $(srcdir)/sldns/sbuffer.h
|
||||
addrtree.lo addrtree.o: $(srcdir)/edns-subnet/addrtree.c config.h $(srcdir)/util/log.h \
|
||||
$(srcdir)/util/data/msgreply.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h \
|
||||
$(srcdir)/util/data/packed_rrset.h $(srcdir)/util/module.h $(srcdir)/util/data/msgparse.h \
|
||||
$(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/edns-subnet/addrtree.h
|
||||
subnet-whitelist.lo subnet-whitelist.o: $(srcdir)/edns-subnet/subnet-whitelist.c config.h \
|
||||
$(srcdir)/edns-subnet/edns-subnet.h $(srcdir)/util/net_help.h $(srcdir)/util/log.h \
|
||||
$(srcdir)/edns-subnet/subnet-whitelist.h $(srcdir)/util/storage/dnstree.h $(srcdir)/util/rbtree.h \
|
||||
$(srcdir)/util/regional.h $(srcdir)/util/config_file.h $(srcdir)/sldns/str2wire.h $(srcdir)/sldns/rrdef.h \
|
||||
$(srcdir)/util/data/dname.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h
|
||||
cachedb.lo cachedb.o: $(srcdir)/cachedb/cachedb.c config.h $(srcdir)/cachedb/cachedb.h $(srcdir)/util/module.h \
|
||||
$(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/data/msgreply.h \
|
||||
$(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h \
|
||||
$(srcdir)/sldns/rrdef.h $(srcdir)/util/regional.h $(srcdir)/util/net_help.h $(srcdir)/util/config_file.h \
|
||||
$(srcdir)/util/data/msgencode.h $(srcdir)/services/cache/dns.h $(srcdir)/validator/val_neg.h \
|
||||
$(srcdir)/util/rbtree.h $(srcdir)/validator/val_secalgo.h $(srcdir)/iterator/iter_utils.h \
|
||||
$(srcdir)/iterator/iter_resptype.h $(srcdir)/sldns/parseutil.h $(srcdir)/sldns/wire2str.h \
|
||||
$(srcdir)/sldns/sbuffer.h
|
||||
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)/dnscrypt/cert.h $(srcdir)/util/tube.h $(srcdir)/services/mesh.h \
|
||||
$(srcdir)/services/modstack.h $(srcdir)/util/net_help.h $(srcdir)/util/regional.h $(srcdir)/respip/respip.h
|
||||
checklocks.lo checklocks.o: $(srcdir)/testcode/checklocks.c config.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \
|
||||
$(srcdir)/testcode/checklocks.h
|
||||
dnscrypt.lo dnscrypt.o: $(srcdir)/dnscrypt/dnscrypt.c config.h $(srcdir)/sldns/sbuffer.h \
|
||||
$(srcdir)/util/config_file.h $(srcdir)/util/net_help.h $(srcdir)/util/log.h $(srcdir)/util/netevent.h \
|
||||
$(srcdir)/dnscrypt/dnscrypt.h $(srcdir)/dnscrypt/cert.h
|
||||
ipsecmod.lo ipsecmod.o: $(srcdir)/ipsecmod/ipsecmod.c config.h $(srcdir)/ipsecmod/ipsecmod.h \
|
||||
$(srcdir)/util/module.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \
|
||||
$(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgparse.h \
|
||||
$(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/rbtree.h $(srcdir)/ipsecmod/ipsecmod-whitelist.h \
|
||||
$(srcdir)/util/storage/dnstree.h $(srcdir)/util/fptr_wlist.h $(srcdir)/util/netevent.h \
|
||||
$(srcdir)/dnscrypt/dnscrypt.h $(srcdir)/dnscrypt/cert.h \
|
||||
$(srcdir)/util/tube.h $(srcdir)/services/mesh.h $(srcdir)/services/modstack.h $(srcdir)/util/regional.h \
|
||||
$(srcdir)/util/net_help.h $(srcdir)/util/config_file.h $(srcdir)/services/cache/dns.h $(srcdir)/sldns/wire2str.h
|
||||
ipsecmod-whitelist.lo ipsecmod-whitelist.o: $(srcdir)/ipsecmod/ipsecmod-whitelist.c config.h \
|
||||
$(srcdir)/ipsecmod/ipsecmod.h $(srcdir)/util/module.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h \
|
||||
$(srcdir)/util/log.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h \
|
||||
$(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/rbtree.h \
|
||||
$(srcdir)/ipsecmod/ipsecmod-whitelist.h $(srcdir)/util/storage/dnstree.h $(srcdir)/util/regional.h \
|
||||
$(srcdir)/util/config_file.h $(srcdir)/util/data/dname.h $(srcdir)/sldns/str2wire.h
|
||||
unitanchor.lo unitanchor.o: $(srcdir)/testcode/unitanchor.c config.h $(srcdir)/util/log.h $(srcdir)/util/data/dname.h \
|
||||
$(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/testcode/unitmain.h \
|
||||
$(srcdir)/validator/val_anchor.h $(srcdir)/util/rbtree.h $(srcdir)/sldns/sbuffer.h $(srcdir)/sldns/rrdef.h
|
||||
@@ -923,11 +1063,15 @@ unitdname.lo unitdname.o: $(srcdir)/testcode/unitdname.c config.h $(srcdir)/util
|
||||
$(srcdir)/sldns/str2wire.h $(srcdir)/sldns/rrdef.h
|
||||
unitlruhash.lo unitlruhash.o: $(srcdir)/testcode/unitlruhash.c config.h $(srcdir)/testcode/unitmain.h \
|
||||
$(srcdir)/util/log.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/storage/slabhash.h
|
||||
unitmain.lo unitmain.o: $(srcdir)/testcode/unitmain.c config.h $(srcdir)/sldns/rrdef.h $(srcdir)/sldns/keyraw.h \
|
||||
unitmain.lo unitmain.o: $(srcdir)/testcode/unitmain.c config.h \
|
||||
$(srcdir)/sldns/rrdef.h $(srcdir)/sldns/keyraw.h \
|
||||
$(srcdir)/util/log.h $(srcdir)/testcode/unitmain.h $(srcdir)/util/alloc.h $(srcdir)/util/locks.h $(srcdir)/util/net_help.h \
|
||||
$(srcdir)/util/config_file.h $(srcdir)/util/rtt.h $(srcdir)/services/cache/infra.h \
|
||||
$(srcdir)/util/storage/lruhash.h $(srcdir)/util/storage/dnstree.h $(srcdir)/util/rbtree.h \
|
||||
$(srcdir)/util/random.h
|
||||
$(srcdir)/util/config_file.h $(srcdir)/util/rtt.h $(srcdir)/util/timehist.h $(srcdir)/libunbound/unbound.h \
|
||||
$(srcdir)/services/cache/infra.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/storage/dnstree.h \
|
||||
$(srcdir)/util/rbtree.h $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
|
||||
$(srcdir)/dnscrypt/cert.h $(srcdir)/util/data/msgreply.h \
|
||||
$(srcdir)/util/data/packed_rrset.h $(srcdir)/util/random.h $(srcdir)/respip/respip.h $(srcdir)/util/module.h \
|
||||
$(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/services/localzone.h $(srcdir)/services/view.h
|
||||
unitmsgparse.lo unitmsgparse.o: $(srcdir)/testcode/unitmsgparse.c config.h $(srcdir)/util/log.h \
|
||||
$(srcdir)/testcode/unitmain.h $(srcdir)/util/data/msgparse.h $(srcdir)/util/storage/lruhash.h \
|
||||
$(srcdir)/util/locks.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/data/msgreply.h \
|
||||
@@ -958,55 +1102,74 @@ 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
|
||||
unitauth.lo unitauth.o: $(srcdir)/testcode/unitauth.c config.h $(srcdir)/services/authzone.h \
|
||||
$(srcdir)/util/rbtree.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/testcode/unitmain.h \
|
||||
$(srcdir)/util/regional.h $(srcdir)/util/net_help.h $(srcdir)/util/data/msgreply.h \
|
||||
$(srcdir)/util/storage/lruhash.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/services/cache/dns.h \
|
||||
$(srcdir)/sldns/str2wire.h $(srcdir)/sldns/rrdef.h $(srcdir)/sldns/wire2str.h $(srcdir)/sldns/sbuffer.h
|
||||
acl_list.lo acl_list.o: $(srcdir)/daemon/acl_list.c config.h $(srcdir)/daemon/acl_list.h \
|
||||
$(srcdir)/util/storage/dnstree.h $(srcdir)/util/rbtree.h $(srcdir)/services/view.h $(srcdir)/util/locks.h \
|
||||
$(srcdir)/util/log.h $(srcdir)/util/regional.h $(srcdir)/util/config_file.h $(srcdir)/util/net_help.h \
|
||||
$(srcdir)/services/localzone.h $(srcdir)/util/module.h $(srcdir)/util/storage/lruhash.h \
|
||||
$(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgparse.h \
|
||||
$(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/sldns/str2wire.h
|
||||
cachedump.lo cachedump.o: $(srcdir)/daemon/cachedump.c config.h $(srcdir)/daemon/cachedump.h \
|
||||
$(srcdir)/daemon/remote.h $(srcdir)/daemon/worker.h $(srcdir)/libunbound/worker.h $(srcdir)/sldns/sbuffer.h \
|
||||
$(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \
|
||||
$(srcdir)/util/netevent.h $(srcdir)/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 \
|
||||
cachedump.lo cachedump.o: $(srcdir)/daemon/cachedump.c config.h \
|
||||
$(srcdir)/daemon/cachedump.h $(srcdir)/daemon/remote.h $(srcdir)/daemon/worker.h $(srcdir)/libunbound/worker.h \
|
||||
$(srcdir)/sldns/sbuffer.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h \
|
||||
$(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
|
||||
$(srcdir)/dnscrypt/cert.h $(srcdir)/util/alloc.h \
|
||||
$(srcdir)/util/data/msgreply.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h \
|
||||
$(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h $(srcdir)/libunbound/unbound.h $(srcdir)/util/module.h \
|
||||
$(srcdir)/dnstap/dnstap.h $(srcdir)/services/cache/rrset.h \
|
||||
$(srcdir)/util/storage/slabhash.h $(srcdir)/services/cache/dns.h $(srcdir)/services/cache/infra.h \
|
||||
$(srcdir)/util/storage/dnstree.h $(srcdir)/util/rbtree.h $(srcdir)/util/rtt.h $(srcdir)/util/regional.h \
|
||||
$(srcdir)/util/net_help.h $(srcdir)/util/data/dname.h $(srcdir)/iterator/iterator.h \
|
||||
$(srcdir)/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 \
|
||||
daemon.lo daemon.o: $(srcdir)/daemon/daemon.c config.h \
|
||||
$(srcdir)/daemon/daemon.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/alloc.h $(srcdir)/services/modstack.h \
|
||||
$(srcdir)/daemon/worker.h \
|
||||
$(srcdir)/libunbound/worker.h $(srcdir)/sldns/sbuffer.h $(srcdir)/util/data/packed_rrset.h \
|
||||
$(srcdir)/util/storage/lruhash.h $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
|
||||
$(srcdir)/dnscrypt/cert.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h \
|
||||
$(srcdir)/sldns/rrdef.h $(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h $(srcdir)/libunbound/unbound.h \
|
||||
$(srcdir)/util/module.h $(srcdir)/dnstap/dnstap.h $(srcdir)/daemon/remote.h \
|
||||
$(srcdir)/daemon/acl_list.h $(srcdir)/util/storage/dnstree.h $(srcdir)/util/rbtree.h $(srcdir)/services/view.h \
|
||||
$(srcdir)/util/config_file.h $(srcdir)/util/shm_side/shm_main.h $(srcdir)/util/storage/lookup3.h \
|
||||
$(srcdir)/util/storage/slabhash.h $(srcdir)/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
|
||||
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
|
||||
stats.lo stats.o: $(srcdir)/daemon/stats.c config.h $(srcdir)/daemon/stats.h $(srcdir)/util/timehist.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)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
|
||||
$(srcdir)/dnscrypt/cert.h $(srcdir)/util/alloc.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/msgparse.h \
|
||||
$(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h \
|
||||
$(srcdir)/libunbound/unbound.h $(srcdir)/util/module.h $(srcdir)/dnstap/dnstap.h \
|
||||
$(srcdir)/daemon/daemon.h $(srcdir)/services/modstack.h \
|
||||
$(srcdir)/daemon/cachedump.h $(srcdir)/util/config_file.h $(srcdir)/util/net_help.h \
|
||||
$(srcdir)/services/listen_dnsport.h $(srcdir)/services/cache/rrset.h $(srcdir)/util/storage/slabhash.h \
|
||||
$(srcdir)/services/cache/infra.h $(srcdir)/util/storage/dnstree.h $(srcdir)/util/rbtree.h $(srcdir)/util/rtt.h \
|
||||
$(srcdir)/services/mesh.h $(srcdir)/services/localzone.h $(srcdir)/services/view.h $(srcdir)/util/fptr_wlist.h \
|
||||
$(srcdir)/util/tube.h $(srcdir)/util/data/dname.h $(srcdir)/validator/validator.h \
|
||||
$(srcdir)/validator/val_utils.h $(srcdir)/validator/val_kcache.h $(srcdir)/validator/val_kentry.h \
|
||||
$(srcdir)/validator/val_anchor.h $(srcdir)/iterator/iterator.h $(srcdir)/services/outbound_list.h \
|
||||
$(srcdir)/iterator/iter_fwd.h $(srcdir)/iterator/iter_hints.h $(srcdir)/iterator/iter_delegpt.h \
|
||||
$(srcdir)/services/outside_network.h $(srcdir)/sldns/str2wire.h $(srcdir)/sldns/parseutil.h \
|
||||
$(srcdir)/sldns/wire2str.h
|
||||
stats.lo stats.o: $(srcdir)/daemon/stats.c config.h $(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h \
|
||||
$(srcdir)/libunbound/unbound.h $(srcdir)/daemon/worker.h $(srcdir)/libunbound/worker.h $(srcdir)/sldns/sbuffer.h \
|
||||
$(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \
|
||||
$(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
|
||||
$(srcdir)/dnscrypt/cert.h $(srcdir)/util/alloc.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/msgparse.h \
|
||||
$(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/module.h $(srcdir)/dnstap/dnstap.h \
|
||||
$(srcdir)/daemon/daemon.h $(srcdir)/services/modstack.h \
|
||||
$(srcdir)/services/mesh.h $(srcdir)/util/rbtree.h $(srcdir)/services/outside_network.h \
|
||||
@@ -1016,37 +1179,42 @@ stats.lo stats.o: $(srcdir)/daemon/stats.c config.h $(srcdir)/daemon/stats.h $(s
|
||||
$(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)/dnscrypt/cert.h $(srcdir)/services/cache/rrset.h $(srcdir)/util/data/packed_rrset.h \
|
||||
$(srcdir)/services/cache/infra.h $(srcdir)/util/storage/dnstree.h $(srcdir)/util/rbtree.h $(srcdir)/util/rtt.h \
|
||||
$(srcdir)/util/data/msgreply.h $(srcdir)/util/fptr_wlist.h $(srcdir)/util/module.h \
|
||||
$(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/tube.h \
|
||||
$(srcdir)/services/mesh.h $(srcdir)/util/net_help.h $(srcdir)/util/ub_event.h
|
||||
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)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
|
||||
$(srcdir)/dnscrypt/cert.h $(srcdir)/util/alloc.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/msgparse.h \
|
||||
$(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h \
|
||||
$(srcdir)/util/module.h $(srcdir)/dnstap/dnstap.h $(srcdir)/daemon/daemon.h \
|
||||
$(srcdir)/services/modstack.h $(srcdir)/daemon/remote.h $(srcdir)/daemon/acl_list.h \
|
||||
$(srcdir)/util/storage/dnstree.h $(srcdir)/util/rbtree.h $(srcdir)/services/view.h $(srcdir)/util/config_file.h \
|
||||
$(srcdir)/util/regional.h $(srcdir)/util/storage/slabhash.h $(srcdir)/services/listen_dnsport.h \
|
||||
$(srcdir)/services/outside_network.h $(srcdir)/services/outbound_list.h \
|
||||
$(srcdir)/services/cache/rrset.h $(srcdir)/services/cache/infra.h $(srcdir)/util/rtt.h \
|
||||
$(srcdir)/services/cache/dns.h $(srcdir)/services/mesh.h $(srcdir)/services/localzone.h \
|
||||
$(srcdir)/libunbound/unbound.h $(srcdir)/util/module.h $(srcdir)/dnstap/dnstap.h \
|
||||
$(srcdir)/daemon/daemon.h $(srcdir)/services/modstack.h \
|
||||
$(srcdir)/daemon/remote.h \
|
||||
$(srcdir)/daemon/acl_list.h $(srcdir)/util/storage/dnstree.h $(srcdir)/util/rbtree.h $(srcdir)/services/view.h \
|
||||
$(srcdir)/util/config_file.h $(srcdir)/util/regional.h $(srcdir)/util/storage/slabhash.h \
|
||||
$(srcdir)/services/listen_dnsport.h $(srcdir)/services/outside_network.h \
|
||||
$(srcdir)/services/outbound_list.h $(srcdir)/services/cache/rrset.h $(srcdir)/services/cache/infra.h \
|
||||
$(srcdir)/util/rtt.h $(srcdir)/services/cache/dns.h $(srcdir)/services/mesh.h $(srcdir)/services/localzone.h \
|
||||
$(srcdir)/util/data/msgencode.h $(srcdir)/util/data/dname.h $(srcdir)/util/fptr_wlist.h $(srcdir)/util/tube.h \
|
||||
$(srcdir)/iterator/iter_fwd.h $(srcdir)/iterator/iter_hints.h $(srcdir)/validator/autotrust.h \
|
||||
$(srcdir)/validator/val_anchor.h $(srcdir)/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/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)/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)/testcode/replay.h $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
|
||||
$(srcdir)/dnscrypt/cert.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,40 +1223,45 @@ 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)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
|
||||
$(srcdir)/dnscrypt/cert.h $(srcdir)/util/alloc.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/msgparse.h \
|
||||
$(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h \
|
||||
$(srcdir)/util/module.h $(srcdir)/dnstap/dnstap.h $(srcdir)/daemon/daemon.h \
|
||||
$(srcdir)/services/modstack.h $(srcdir)/daemon/remote.h $(srcdir)/daemon/acl_list.h \
|
||||
$(srcdir)/util/storage/dnstree.h $(srcdir)/util/rbtree.h $(srcdir)/services/view.h $(srcdir)/util/config_file.h \
|
||||
$(srcdir)/util/regional.h $(srcdir)/util/storage/slabhash.h $(srcdir)/services/listen_dnsport.h \
|
||||
$(srcdir)/services/outside_network.h $(srcdir)/services/outbound_list.h \
|
||||
$(srcdir)/services/cache/rrset.h $(srcdir)/services/cache/infra.h $(srcdir)/util/rtt.h \
|
||||
$(srcdir)/services/cache/dns.h $(srcdir)/services/mesh.h $(srcdir)/services/localzone.h \
|
||||
$(srcdir)/libunbound/unbound.h $(srcdir)/util/module.h $(srcdir)/dnstap/dnstap.h \
|
||||
$(srcdir)/daemon/daemon.h $(srcdir)/services/modstack.h \
|
||||
$(srcdir)/daemon/remote.h \
|
||||
$(srcdir)/daemon/acl_list.h $(srcdir)/util/storage/dnstree.h $(srcdir)/util/rbtree.h $(srcdir)/services/view.h \
|
||||
$(srcdir)/util/config_file.h $(srcdir)/util/regional.h $(srcdir)/util/storage/slabhash.h \
|
||||
$(srcdir)/services/listen_dnsport.h $(srcdir)/services/outside_network.h \
|
||||
$(srcdir)/services/outbound_list.h $(srcdir)/services/cache/rrset.h $(srcdir)/services/cache/infra.h \
|
||||
$(srcdir)/util/rtt.h $(srcdir)/services/cache/dns.h $(srcdir)/services/mesh.h $(srcdir)/services/localzone.h \
|
||||
$(srcdir)/util/data/msgencode.h $(srcdir)/util/data/dname.h $(srcdir)/util/fptr_wlist.h $(srcdir)/util/tube.h \
|
||||
$(srcdir)/iterator/iter_fwd.h $(srcdir)/iterator/iter_hints.h $(srcdir)/validator/autotrust.h \
|
||||
$(srcdir)/validator/val_anchor.h $(srcdir)/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/libworker.h $(srcdir)/sldns/wire2str.h $(srcdir)/util/shm_side/shm_main.h
|
||||
acl_list.lo acl_list.o: $(srcdir)/daemon/acl_list.c config.h $(srcdir)/daemon/acl_list.h \
|
||||
$(srcdir)/util/storage/dnstree.h $(srcdir)/util/rbtree.h $(srcdir)/services/view.h $(srcdir)/util/locks.h \
|
||||
$(srcdir)/util/log.h $(srcdir)/util/regional.h $(srcdir)/util/config_file.h $(srcdir)/util/net_help.h \
|
||||
$(srcdir)/services/localzone.h $(srcdir)/util/module.h $(srcdir)/util/storage/lruhash.h \
|
||||
$(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgparse.h \
|
||||
$(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/sldns/str2wire.h
|
||||
daemon.lo daemon.o: $(srcdir)/daemon/daemon.c config.h $(srcdir)/daemon/daemon.h $(srcdir)/util/locks.h \
|
||||
$(srcdir)/util/log.h $(srcdir)/util/alloc.h $(srcdir)/services/modstack.h \
|
||||
$(srcdir)/daemon/worker.h $(srcdir)/libunbound/worker.h $(srcdir)/sldns/sbuffer.h \
|
||||
$(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/netevent.h \
|
||||
$(srcdir)/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 \
|
||||
daemon.lo daemon.o: $(srcdir)/daemon/daemon.c config.h \
|
||||
$(srcdir)/daemon/daemon.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/alloc.h $(srcdir)/services/modstack.h \
|
||||
$(srcdir)/daemon/worker.h \
|
||||
$(srcdir)/libunbound/worker.h $(srcdir)/sldns/sbuffer.h $(srcdir)/util/data/packed_rrset.h \
|
||||
$(srcdir)/util/storage/lruhash.h $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
|
||||
$(srcdir)/dnscrypt/cert.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h \
|
||||
$(srcdir)/sldns/rrdef.h $(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h $(srcdir)/libunbound/unbound.h \
|
||||
$(srcdir)/util/module.h $(srcdir)/dnstap/dnstap.h $(srcdir)/daemon/remote.h \
|
||||
$(srcdir)/daemon/acl_list.h $(srcdir)/util/storage/dnstree.h $(srcdir)/util/rbtree.h $(srcdir)/services/view.h \
|
||||
$(srcdir)/util/config_file.h $(srcdir)/util/shm_side/shm_main.h $(srcdir)/util/storage/lookup3.h \
|
||||
$(srcdir)/util/storage/slabhash.h $(srcdir)/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)/libunbound/unbound.h $(srcdir)/daemon/worker.h $(srcdir)/libunbound/worker.h $(srcdir)/sldns/sbuffer.h \
|
||||
$(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \
|
||||
$(srcdir)/util/netevent.h $(srcdir)/util/alloc.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/msgparse.h \
|
||||
$(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
|
||||
$(srcdir)/dnscrypt/cert.h $(srcdir)/util/alloc.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/msgparse.h \
|
||||
$(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/module.h $(srcdir)/dnstap/dnstap.h \
|
||||
$(srcdir)/daemon/daemon.h $(srcdir)/services/modstack.h \
|
||||
$(srcdir)/services/mesh.h $(srcdir)/util/rbtree.h $(srcdir)/services/outside_network.h \
|
||||
@@ -1097,10 +1270,12 @@ stats.lo stats.o: $(srcdir)/daemon/stats.c config.h $(srcdir)/daemon/stats.h $(s
|
||||
$(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/config_file.h $(srcdir)/testcode/replay.h $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
|
||||
$(srcdir)/dnscrypt/cert.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/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
|
||||
$(srcdir)/dnscrypt/cert.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 \
|
||||
@@ -1110,7 +1285,8 @@ fake_event.lo fake_event.o: $(srcdir)/testcode/fake_event.c config.h $(srcdir)/t
|
||||
$(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/locks.h $(srcdir)/util/fptr_wlist.h $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
|
||||
$(srcdir)/dnscrypt/cert.h $(srcdir)/util/storage/lruhash.h \
|
||||
$(srcdir)/util/module.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h \
|
||||
$(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/tube.h \
|
||||
$(srcdir)/services/mesh.h $(srcdir)/services/modstack.h
|
||||
@@ -1121,7 +1297,8 @@ 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/locks.h $(srcdir)/util/fptr_wlist.h $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
|
||||
$(srcdir)/dnscrypt/cert.h $(srcdir)/util/storage/lruhash.h \
|
||||
$(srcdir)/util/module.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h \
|
||||
$(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/tube.h \
|
||||
$(srcdir)/services/mesh.h $(srcdir)/services/modstack.h
|
||||
@@ -1132,11 +1309,12 @@ 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 $(PYTHONMOD_HEADER)
|
||||
worker_cb.lo worker_cb.o: $(srcdir)/smallapp/worker_cb.c config.h $(srcdir)/libunbound/context.h \
|
||||
$(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/alloc.h $(srcdir)/util/rbtree.h $(srcdir)/services/modstack.h \
|
||||
$(srcdir)/libunbound/unbound.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h \
|
||||
$(srcdir)/libunbound/worker.h $(srcdir)/sldns/sbuffer.h $(srcdir)/util/fptr_wlist.h $(srcdir)/util/netevent.h \
|
||||
$(srcdir)/dnscrypt/dnscrypt.h $(srcdir)/dnscrypt/cert.h \
|
||||
$(srcdir)/util/module.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h \
|
||||
$(srcdir)/sldns/rrdef.h $(srcdir)/util/tube.h $(srcdir)/services/mesh.h
|
||||
context.lo context.o: $(srcdir)/libunbound/context.c config.h $(srcdir)/libunbound/context.h \
|
||||
@@ -1146,7 +1324,8 @@ 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)/sldns/sbuffer.h
|
||||
$(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
|
||||
$(srcdir)/dnscrypt/cert.h $(srcdir)/sldns/sbuffer.h
|
||||
libunbound.lo libunbound.o: $(srcdir)/libunbound/libunbound.c $(srcdir)/libunbound/unbound.h \
|
||||
$(srcdir)/libunbound/unbound-event.h config.h $(srcdir)/libunbound/context.h $(srcdir)/util/locks.h \
|
||||
$(srcdir)/util/log.h $(srcdir)/util/alloc.h $(srcdir)/util/rbtree.h $(srcdir)/services/modstack.h \
|
||||
@@ -1155,19 +1334,21 @@ 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)/dnscrypt/cert.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 \
|
||||
libworker.lo libworker.o: $(srcdir)/libunbound/libworker.c config.h \
|
||||
$(srcdir)/libunbound/libworker.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h \
|
||||
$(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/libunbound/context.h $(srcdir)/util/alloc.h $(srcdir)/util/rbtree.h \
|
||||
$(srcdir)/services/modstack.h $(srcdir)/libunbound/unbound.h $(srcdir)/libunbound/worker.h \
|
||||
$(srcdir)/sldns/sbuffer.h $(srcdir)/libunbound/unbound-event.h $(srcdir)/services/outside_network.h \
|
||||
$(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
|
||||
$(srcdir)/dnscrypt/cert.h $(srcdir)/services/mesh.h \
|
||||
$(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/module.h \
|
||||
$(srcdir)/util/data/msgreply.h $(srcdir)/services/localzone.h $(srcdir)/util/storage/dnstree.h \
|
||||
$(srcdir)/services/view.h $(srcdir)/services/cache/rrset.h $(srcdir)/util/storage/slabhash.h \
|
||||
$(srcdir)/services/outbound_list.h $(srcdir)/util/fptr_wlist.h $(srcdir)/util/tube.h $(srcdir)/util/regional.h \
|
||||
$(srcdir)/util/random.h $(srcdir)/util/config_file.h $(srcdir)/util/storage/lookup3.h $(srcdir)/util/net_help.h \
|
||||
$(srcdir)/util/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 \
|
||||
@@ -1180,32 +1361,40 @@ streamtcp.lo streamtcp.o: $(srcdir)/testcode/streamtcp.c config.h $(srcdir)/util
|
||||
$(srcdir)/util/net_help.h $(srcdir)/util/data/msgencode.h $(srcdir)/util/data/msgparse.h \
|
||||
$(srcdir)/util/storage/lruhash.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/data/msgreply.h \
|
||||
$(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/dname.h $(srcdir)/sldns/sbuffer.h \
|
||||
$(srcdir)/sldns/str2wire.h $(srcdir)/sldns/wire2str.h
|
||||
$(srcdir)/sldns/str2wire.h $(srcdir)/sldns/wire2str.h \
|
||||
|
||||
perf.lo perf.o: $(srcdir)/testcode/perf.c config.h $(srcdir)/util/log.h $(srcdir)/util/locks.h $(srcdir)/util/net_help.h \
|
||||
$(srcdir)/util/data/msgencode.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/storage/lruhash.h \
|
||||
$(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h \
|
||||
$(srcdir)/sldns/rrdef.h $(srcdir)/sldns/sbuffer.h $(srcdir)/sldns/wire2str.h $(srcdir)/sldns/str2wire.h
|
||||
delayer.lo delayer.o: $(srcdir)/testcode/delayer.c config.h $(srcdir)/util/net_help.h $(srcdir)/util/log.h \
|
||||
$(srcdir)/util/config_file.h $(srcdir)/sldns/sbuffer.h
|
||||
unbound-control.lo unbound-control.o: $(srcdir)/smallapp/unbound-control.c config.h $(srcdir)/util/log.h \
|
||||
$(srcdir)/util/config_file.h $(srcdir)/util/locks.h $(srcdir)/util/net_help.h
|
||||
unbound-control.lo unbound-control.o: $(srcdir)/smallapp/unbound-control.c config.h \
|
||||
$(srcdir)/util/log.h $(srcdir)/util/config_file.h $(srcdir)/util/locks.h $(srcdir)/util/net_help.h \
|
||||
$(srcdir)/util/shm_side/shm_main.h $(srcdir)/libunbound/unbound.h $(srcdir)/daemon/stats.h \
|
||||
$(srcdir)/util/timehist.h $(srcdir)/sldns/wire2str.h $(srcdir)/sldns/pkthdr.h
|
||||
unbound-anchor.lo unbound-anchor.o: $(srcdir)/smallapp/unbound-anchor.c config.h $(srcdir)/libunbound/unbound.h \
|
||||
$(srcdir)/sldns/rrdef.h $(srcdir)/sldns/parseutil.h
|
||||
petal.lo petal.o: $(srcdir)/testcode/petal.c config.h
|
||||
$(srcdir)/sldns/rrdef.h $(srcdir)/sldns/parseutil.h \
|
||||
|
||||
petal.lo petal.o: $(srcdir)/testcode/petal.c config.h \
|
||||
|
||||
pythonmod_utils.lo pythonmod_utils.o: $(srcdir)/pythonmod/pythonmod_utils.c config.h $(srcdir)/util/module.h \
|
||||
$(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/data/msgreply.h \
|
||||
$(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h \
|
||||
$(srcdir)/sldns/rrdef.h $(srcdir)/util/netevent.h $(srcdir)/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)/sldns/rrdef.h $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
|
||||
$(srcdir)/dnscrypt/cert.h $(srcdir)/util/net_help.h \
|
||||
$(srcdir)/services/cache/dns.h $(srcdir)/services/cache/rrset.h $(srcdir)/util/storage/slabhash.h \
|
||||
$(srcdir)/util/regional.h $(srcdir)/iterator/iter_delegpt.h $(srcdir)/sldns/sbuffer.h \
|
||||
|
||||
win_svc.lo win_svc.o: $(srcdir)/winrc/win_svc.c config.h $(srcdir)/winrc/win_svc.h $(srcdir)/winrc/w_inst.h \
|
||||
$(srcdir)/daemon/daemon.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/alloc.h $(srcdir)/services/modstack.h \
|
||||
$(srcdir)/daemon/worker.h $(srcdir)/libunbound/worker.h \
|
||||
$(srcdir)/sldns/sbuffer.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h \
|
||||
$(srcdir)/util/netevent.h $(srcdir)/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)/dnscrypt/cert.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h \
|
||||
$(srcdir)/sldns/rrdef.h $(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h $(srcdir)/libunbound/unbound.h \
|
||||
$(srcdir)/util/module.h $(srcdir)/dnstap/dnstap.h $(srcdir)/daemon/remote.h \
|
||||
$(srcdir)/util/config_file.h $(srcdir)/util/ub_event.h
|
||||
w_inst.lo w_inst.o: $(srcdir)/winrc/w_inst.c config.h $(srcdir)/winrc/w_inst.h $(srcdir)/winrc/win_svc.h
|
||||
unbound-service-install.lo unbound-service-install.o: $(srcdir)/winrc/unbound-service-install.c config.h \
|
||||
$(srcdir)/winrc/w_inst.h
|
||||
@@ -1213,11 +1402,14 @@ unbound-service-remove.lo unbound-service-remove.o: $(srcdir)/winrc/unbound-serv
|
||||
$(srcdir)/winrc/w_inst.h
|
||||
anchor-update.lo anchor-update.o: $(srcdir)/winrc/anchor-update.c config.h $(srcdir)/libunbound/unbound.h \
|
||||
$(srcdir)/sldns/rrdef.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/wire2str.h
|
||||
keyraw.lo keyraw.o: $(srcdir)/sldns/keyraw.c config.h $(srcdir)/sldns/keyraw.h $(srcdir)/sldns/rrdef.h
|
||||
keyraw.lo keyraw.o: $(srcdir)/sldns/keyraw.c config.h $(srcdir)/sldns/keyraw.h \
|
||||
$(srcdir)/sldns/rrdef.h \
|
||||
|
||||
sbuffer.lo sbuffer.o: $(srcdir)/sldns/sbuffer.c config.h $(srcdir)/sldns/sbuffer.h
|
||||
wire2str.lo wire2str.o: $(srcdir)/sldns/wire2str.c config.h $(srcdir)/sldns/wire2str.h $(srcdir)/sldns/str2wire.h \
|
||||
$(srcdir)/sldns/rrdef.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/parseutil.h $(srcdir)/sldns/sbuffer.h \
|
||||
$(srcdir)/sldns/keyraw.h
|
||||
$(srcdir)/sldns/keyraw.h \
|
||||
|
||||
parse.lo parse.o: $(srcdir)/sldns/parse.c config.h $(srcdir)/sldns/parse.h $(srcdir)/sldns/parseutil.h \
|
||||
$(srcdir)/sldns/sbuffer.h
|
||||
parseutil.lo parseutil.o: $(srcdir)/sldns/parseutil.c config.h $(srcdir)/sldns/parseutil.h
|
||||
@@ -1237,9 +1429,11 @@ snprintf.lo snprintf.o: $(srcdir)/compat/snprintf.c config.h
|
||||
strlcat.lo strlcat.o: $(srcdir)/compat/strlcat.c config.h
|
||||
strlcpy.lo strlcpy.o: $(srcdir)/compat/strlcpy.c config.h
|
||||
strptime.lo strptime.o: $(srcdir)/compat/strptime.c config.h
|
||||
getentropy_linux.lo getentropy_linux.o: $(srcdir)/compat/getentropy_linux.c config.h
|
||||
getentropy_linux.lo getentropy_linux.o: $(srcdir)/compat/getentropy_linux.c config.h \
|
||||
|
||||
getentropy_osx.lo getentropy_osx.o: $(srcdir)/compat/getentropy_osx.c config.h
|
||||
getentropy_solaris.lo getentropy_solaris.o: $(srcdir)/compat/getentropy_solaris.c config.h
|
||||
getentropy_solaris.lo getentropy_solaris.o: $(srcdir)/compat/getentropy_solaris.c config.h \
|
||||
|
||||
getentropy_win.lo getentropy_win.o: $(srcdir)/compat/getentropy_win.c
|
||||
explicit_bzero.lo explicit_bzero.o: $(srcdir)/compat/explicit_bzero.c config.h
|
||||
arc4random.lo arc4random.o: $(srcdir)/compat/arc4random.c config.h $(srcdir)/compat/chacha_private.h
|
||||
|
||||
+14
-3
@@ -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
|
||||
|
||||
Vendored
+326
@@ -9044,3 +9044,329 @@ m4_ifndef([_LT_PROG_F77], [AC_DEFUN([_LT_PROG_F77])])
|
||||
m4_ifndef([_LT_PROG_FC], [AC_DEFUN([_LT_PROG_FC])])
|
||||
m4_ifndef([_LT_PROG_CXX], [AC_DEFUN([_LT_PROG_CXX])])
|
||||
|
||||
dnl pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*-
|
||||
dnl serial 11 (pkg-config-0.29.1)
|
||||
dnl
|
||||
dnl Copyright © 2004 Scott James Remnant <scott@netsplit.com>.
|
||||
dnl Copyright © 2012-2015 Dan Nicholson <dbn.lists@gmail.com>
|
||||
dnl
|
||||
dnl This program is free software; you can redistribute it and/or modify
|
||||
dnl it under the terms of the GNU General Public License as published by
|
||||
dnl the Free Software Foundation; either version 2 of the License, or
|
||||
dnl (at your option) any later version.
|
||||
dnl
|
||||
dnl This program is distributed in the hope that it will be useful, but
|
||||
dnl WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
dnl General Public License for more details.
|
||||
dnl
|
||||
dnl You should have received a copy of the GNU General Public License
|
||||
dnl along with this program; if not, write to the Free Software
|
||||
dnl Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
dnl 02111-1307, USA.
|
||||
dnl
|
||||
dnl As a special exception to the GNU General Public License, if you
|
||||
dnl distribute this file as part of a program that contains a
|
||||
dnl configuration script generated by Autoconf, you may include it under
|
||||
dnl the same distribution terms that you use for the rest of that
|
||||
dnl program.
|
||||
|
||||
dnl PKG_PREREQ(MIN-VERSION)
|
||||
dnl -----------------------
|
||||
dnl Since: 0.29
|
||||
dnl
|
||||
dnl Verify that the version of the pkg-config macros are at least
|
||||
dnl MIN-VERSION. Unlike PKG_PROG_PKG_CONFIG, which checks the user's
|
||||
dnl installed version of pkg-config, this checks the developer's version
|
||||
dnl of pkg.m4 when generating configure.
|
||||
dnl
|
||||
dnl To ensure that this macro is defined, also add:
|
||||
dnl m4_ifndef([PKG_PREREQ],
|
||||
dnl [m4_fatal([must install pkg-config 0.29 or later before running autoconf/autogen])])
|
||||
dnl
|
||||
dnl See the "Since" comment for each macro you use to see what version
|
||||
dnl of the macros you require.
|
||||
m4_defun([PKG_PREREQ],
|
||||
[m4_define([PKG_MACROS_VERSION], [0.29.1])
|
||||
m4_if(m4_version_compare(PKG_MACROS_VERSION, [$1]), -1,
|
||||
[m4_fatal([pkg.m4 version $1 or higher is required but ]PKG_MACROS_VERSION[ found])])
|
||||
])dnl PKG_PREREQ
|
||||
|
||||
dnl PKG_PROG_PKG_CONFIG([MIN-VERSION])
|
||||
dnl ----------------------------------
|
||||
dnl Since: 0.16
|
||||
dnl
|
||||
dnl Search for the pkg-config tool and set the PKG_CONFIG variable to
|
||||
dnl first found in the path. Checks that the version of pkg-config found
|
||||
dnl is at least MIN-VERSION. If MIN-VERSION is not specified, 0.9.0 is
|
||||
dnl used since that's the first version where most current features of
|
||||
dnl pkg-config existed.
|
||||
AC_DEFUN([PKG_PROG_PKG_CONFIG],
|
||||
[m4_pattern_forbid([^_?PKG_[A-Z_]+$])
|
||||
m4_pattern_allow([^PKG_CONFIG(_(PATH|LIBDIR|SYSROOT_DIR|ALLOW_SYSTEM_(CFLAGS|LIBS)))?$])
|
||||
m4_pattern_allow([^PKG_CONFIG_(DISABLE_UNINSTALLED|TOP_BUILD_DIR|DEBUG_SPEW)$])
|
||||
AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility])
|
||||
AC_ARG_VAR([PKG_CONFIG_PATH], [directories to add to pkg-config's search path])
|
||||
AC_ARG_VAR([PKG_CONFIG_LIBDIR], [path overriding pkg-config's built-in search path])
|
||||
|
||||
if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then
|
||||
AC_PATH_TOOL([PKG_CONFIG], [pkg-config])
|
||||
fi
|
||||
if test -n "$PKG_CONFIG"; then
|
||||
_pkg_min_version=m4_default([$1], [0.9.0])
|
||||
AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version])
|
||||
if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then
|
||||
AC_MSG_RESULT([yes])
|
||||
else
|
||||
AC_MSG_RESULT([no])
|
||||
PKG_CONFIG=""
|
||||
fi
|
||||
fi[]dnl
|
||||
])dnl PKG_PROG_PKG_CONFIG
|
||||
|
||||
dnl PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
|
||||
dnl -------------------------------------------------------------------
|
||||
dnl Since: 0.18
|
||||
dnl
|
||||
dnl Check to see whether a particular set of modules exists. Similar to
|
||||
dnl PKG_CHECK_MODULES(), but does not set variables or print errors.
|
||||
dnl
|
||||
dnl Please remember that m4 expands AC_REQUIRE([PKG_PROG_PKG_CONFIG])
|
||||
dnl only at the first occurence in configure.ac, so if the first place
|
||||
dnl it's called might be skipped (such as if it is within an "if", you
|
||||
dnl have to call PKG_CHECK_EXISTS manually
|
||||
AC_DEFUN([PKG_CHECK_EXISTS],
|
||||
[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
|
||||
if test -n "$PKG_CONFIG" && \
|
||||
AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then
|
||||
m4_default([$2], [:])
|
||||
m4_ifvaln([$3], [else
|
||||
$3])dnl
|
||||
fi])
|
||||
|
||||
dnl _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES])
|
||||
dnl ---------------------------------------------
|
||||
dnl Internal wrapper calling pkg-config via PKG_CONFIG and setting
|
||||
dnl pkg_failed based on the result.
|
||||
m4_define([_PKG_CONFIG],
|
||||
[if test -n "$$1"; then
|
||||
pkg_cv_[]$1="$$1"
|
||||
elif test -n "$PKG_CONFIG"; then
|
||||
PKG_CHECK_EXISTS([$3],
|
||||
[pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null`
|
||||
test "x$?" != "x0" && pkg_failed=yes ],
|
||||
[pkg_failed=yes])
|
||||
else
|
||||
pkg_failed=untried
|
||||
fi[]dnl
|
||||
])dnl _PKG_CONFIG
|
||||
|
||||
dnl _PKG_SHORT_ERRORS_SUPPORTED
|
||||
dnl ---------------------------
|
||||
dnl Internal check to see if pkg-config supports short errors.
|
||||
AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED],
|
||||
[AC_REQUIRE([PKG_PROG_PKG_CONFIG])
|
||||
if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
|
||||
_pkg_short_errors_supported=yes
|
||||
else
|
||||
_pkg_short_errors_supported=no
|
||||
fi[]dnl
|
||||
])dnl _PKG_SHORT_ERRORS_SUPPORTED
|
||||
|
||||
|
||||
dnl PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND],
|
||||
dnl [ACTION-IF-NOT-FOUND])
|
||||
dnl --------------------------------------------------------------
|
||||
dnl Since: 0.4.0
|
||||
dnl
|
||||
dnl Note that if there is a possibility the first call to
|
||||
dnl PKG_CHECK_MODULES might not happen, you should be sure to include an
|
||||
dnl explicit call to PKG_PROG_PKG_CONFIG in your configure.ac
|
||||
AC_DEFUN([PKG_CHECK_MODULES],
|
||||
[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
|
||||
AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl
|
||||
AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl
|
||||
|
||||
pkg_failed=no
|
||||
AC_MSG_CHECKING([for $1])
|
||||
|
||||
_PKG_CONFIG([$1][_CFLAGS], [cflags], [$2])
|
||||
_PKG_CONFIG([$1][_LIBS], [libs], [$2])
|
||||
|
||||
m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS
|
||||
and $1[]_LIBS to avoid the need to call pkg-config.
|
||||
See the pkg-config man page for more details.])
|
||||
|
||||
if test $pkg_failed = yes; then
|
||||
AC_MSG_RESULT([no])
|
||||
_PKG_SHORT_ERRORS_SUPPORTED
|
||||
if test $_pkg_short_errors_supported = yes; then
|
||||
$1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$2" 2>&1`
|
||||
else
|
||||
$1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$2" 2>&1`
|
||||
fi
|
||||
# Put the nasty error message in config.log where it belongs
|
||||
echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD
|
||||
|
||||
m4_default([$4], [AC_MSG_ERROR(
|
||||
[Package requirements ($2) were not met:
|
||||
|
||||
$$1_PKG_ERRORS
|
||||
|
||||
Consider adjusting the PKG_CONFIG_PATH environment variable if you
|
||||
installed software in a non-standard prefix.
|
||||
|
||||
_PKG_TEXT])[]dnl
|
||||
])
|
||||
elif test $pkg_failed = untried; then
|
||||
AC_MSG_RESULT([no])
|
||||
m4_default([$4], [AC_MSG_FAILURE(
|
||||
[The pkg-config script could not be found or is too old. Make sure it
|
||||
is in your PATH or set the PKG_CONFIG environment variable to the full
|
||||
path to pkg-config.
|
||||
|
||||
_PKG_TEXT
|
||||
|
||||
To get pkg-config, see <http://pkg-config.freedesktop.org/>.])[]dnl
|
||||
])
|
||||
else
|
||||
$1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS
|
||||
$1[]_LIBS=$pkg_cv_[]$1[]_LIBS
|
||||
AC_MSG_RESULT([yes])
|
||||
$3
|
||||
fi[]dnl
|
||||
])dnl PKG_CHECK_MODULES
|
||||
|
||||
|
||||
dnl PKG_CHECK_MODULES_STATIC(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND],
|
||||
dnl [ACTION-IF-NOT-FOUND])
|
||||
dnl ---------------------------------------------------------------------
|
||||
dnl Since: 0.29
|
||||
dnl
|
||||
dnl Checks for existence of MODULES and gathers its build flags with
|
||||
dnl static libraries enabled. Sets VARIABLE-PREFIX_CFLAGS from --cflags
|
||||
dnl and VARIABLE-PREFIX_LIBS from --libs.
|
||||
dnl
|
||||
dnl Note that if there is a possibility the first call to
|
||||
dnl PKG_CHECK_MODULES_STATIC might not happen, you should be sure to
|
||||
dnl include an explicit call to PKG_PROG_PKG_CONFIG in your
|
||||
dnl configure.ac.
|
||||
AC_DEFUN([PKG_CHECK_MODULES_STATIC],
|
||||
[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
|
||||
_save_PKG_CONFIG=$PKG_CONFIG
|
||||
PKG_CONFIG="$PKG_CONFIG --static"
|
||||
PKG_CHECK_MODULES($@)
|
||||
PKG_CONFIG=$_save_PKG_CONFIG[]dnl
|
||||
])dnl PKG_CHECK_MODULES_STATIC
|
||||
|
||||
|
||||
dnl PKG_INSTALLDIR([DIRECTORY])
|
||||
dnl -------------------------
|
||||
dnl Since: 0.27
|
||||
dnl
|
||||
dnl Substitutes the variable pkgconfigdir as the location where a module
|
||||
dnl should install pkg-config .pc files. By default the directory is
|
||||
dnl $libdir/pkgconfig, but the default can be changed by passing
|
||||
dnl DIRECTORY. The user can override through the --with-pkgconfigdir
|
||||
dnl parameter.
|
||||
AC_DEFUN([PKG_INSTALLDIR],
|
||||
[m4_pushdef([pkg_default], [m4_default([$1], ['${libdir}/pkgconfig'])])
|
||||
m4_pushdef([pkg_description],
|
||||
[pkg-config installation directory @<:@]pkg_default[@:>@])
|
||||
AC_ARG_WITH([pkgconfigdir],
|
||||
[AS_HELP_STRING([--with-pkgconfigdir], pkg_description)],,
|
||||
[with_pkgconfigdir=]pkg_default)
|
||||
AC_SUBST([pkgconfigdir], [$with_pkgconfigdir])
|
||||
m4_popdef([pkg_default])
|
||||
m4_popdef([pkg_description])
|
||||
])dnl PKG_INSTALLDIR
|
||||
|
||||
|
||||
dnl PKG_NOARCH_INSTALLDIR([DIRECTORY])
|
||||
dnl --------------------------------
|
||||
dnl Since: 0.27
|
||||
dnl
|
||||
dnl Substitutes the variable noarch_pkgconfigdir as the location where a
|
||||
dnl module should install arch-independent pkg-config .pc files. By
|
||||
dnl default the directory is $datadir/pkgconfig, but the default can be
|
||||
dnl changed by passing DIRECTORY. The user can override through the
|
||||
dnl --with-noarch-pkgconfigdir parameter.
|
||||
AC_DEFUN([PKG_NOARCH_INSTALLDIR],
|
||||
[m4_pushdef([pkg_default], [m4_default([$1], ['${datadir}/pkgconfig'])])
|
||||
m4_pushdef([pkg_description],
|
||||
[pkg-config arch-independent installation directory @<:@]pkg_default[@:>@])
|
||||
AC_ARG_WITH([noarch-pkgconfigdir],
|
||||
[AS_HELP_STRING([--with-noarch-pkgconfigdir], pkg_description)],,
|
||||
[with_noarch_pkgconfigdir=]pkg_default)
|
||||
AC_SUBST([noarch_pkgconfigdir], [$with_noarch_pkgconfigdir])
|
||||
m4_popdef([pkg_default])
|
||||
m4_popdef([pkg_description])
|
||||
])dnl PKG_NOARCH_INSTALLDIR
|
||||
|
||||
|
||||
dnl PKG_CHECK_VAR(VARIABLE, MODULE, CONFIG-VARIABLE,
|
||||
dnl [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
|
||||
dnl -------------------------------------------
|
||||
dnl Since: 0.28
|
||||
dnl
|
||||
dnl Retrieves the value of the pkg-config variable for the given module.
|
||||
AC_DEFUN([PKG_CHECK_VAR],
|
||||
[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
|
||||
AC_ARG_VAR([$1], [value of $3 for $2, overriding pkg-config])dnl
|
||||
|
||||
_PKG_CONFIG([$1], [variable="][$3]["], [$2])
|
||||
AS_VAR_COPY([$1], [pkg_cv_][$1])
|
||||
|
||||
AS_VAR_IF([$1], [""], [$5], [$4])dnl
|
||||
])dnl PKG_CHECK_VAR
|
||||
|
||||
# AM_CONDITIONAL -*- Autoconf -*-
|
||||
|
||||
# Copyright (C) 1997-2014 Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# AM_CONDITIONAL(NAME, SHELL-CONDITION)
|
||||
# -------------------------------------
|
||||
# Define a conditional.
|
||||
AC_DEFUN([AM_CONDITIONAL],
|
||||
[AC_PREREQ([2.52])dnl
|
||||
m4_if([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])],
|
||||
[$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl
|
||||
AC_SUBST([$1_TRUE])dnl
|
||||
AC_SUBST([$1_FALSE])dnl
|
||||
_AM_SUBST_NOTMAKE([$1_TRUE])dnl
|
||||
_AM_SUBST_NOTMAKE([$1_FALSE])dnl
|
||||
m4_define([_AM_COND_VALUE_$1], [$2])dnl
|
||||
if $2; then
|
||||
$1_TRUE=
|
||||
$1_FALSE='#'
|
||||
else
|
||||
$1_TRUE='#'
|
||||
$1_FALSE=
|
||||
fi
|
||||
AC_CONFIG_COMMANDS_PRE(
|
||||
[if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then
|
||||
AC_MSG_ERROR([[conditional "$1" was never defined.
|
||||
Usually this means the macro was only invoked conditionally.]])
|
||||
fi])])
|
||||
|
||||
# Copyright (C) 2006-2014 Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# _AM_SUBST_NOTMAKE(VARIABLE)
|
||||
# ---------------------------
|
||||
# Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in.
|
||||
# This macro is traced by Automake.
|
||||
AC_DEFUN([_AM_SUBST_NOTMAKE])
|
||||
|
||||
# AM_SUBST_NOTMAKE(VARIABLE)
|
||||
# --------------------------
|
||||
# Public sister of _AM_SUBST_NOTMAKE.
|
||||
AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)])
|
||||
|
||||
|
||||
+1
-2
@@ -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])
|
||||
|
||||
+42
-17
@@ -171,12 +171,13 @@ static int
|
||||
cachedb_apply_cfg(struct cachedb_env* cachedb_env, struct config_file* cfg)
|
||||
{
|
||||
const char* backend_str = "testframe"; /* TODO get from cfg */
|
||||
(void)cfg; /* need this until the TODO is implemented */
|
||||
if(backend_str && backend_str[0]) {
|
||||
cachedb_env->backend = cachedb_find_backend(backend_str);
|
||||
if(!cachedb_env->backend) {
|
||||
log_err("cachedb: cannot find backend name '%s",
|
||||
backend_str);
|
||||
return NULL;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
/* TODO see if more configuration needs to be applied or not */
|
||||
@@ -374,6 +375,36 @@ good_expiry_and_qinfo(struct module_qstate* qstate, struct sldns_buffer* buf)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void
|
||||
packed_rrset_ttl_subtract(struct packed_rrset_data* data, time_t subtract)
|
||||
{
|
||||
size_t i;
|
||||
size_t total = data->count + data->rrsig_count;
|
||||
if(data->ttl > subtract)
|
||||
data->ttl -= subtract;
|
||||
else data->ttl = 0;
|
||||
for(i=0; i<total; i++) {
|
||||
if(data->rr_ttl[i] > subtract)
|
||||
data->rr_ttl[i] -= subtract;
|
||||
else data->rr_ttl[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
adjust_msg_ttl(struct dns_msg* msg, time_t adjust)
|
||||
{
|
||||
size_t i;
|
||||
if(msg->rep->ttl > adjust)
|
||||
msg->rep->ttl -= adjust;
|
||||
else msg->rep->ttl = 0;
|
||||
msg->rep->prefetch_ttl = PREFETCH_TTL_CALC(msg->rep->ttl);
|
||||
|
||||
for(i=0; i<msg->rep->rrset_count; i++) {
|
||||
packed_rrset_ttl_subtract((struct packed_rrset_data*)msg->
|
||||
rep->rrsets[i]->entry.data, adjust);
|
||||
}
|
||||
}
|
||||
|
||||
/** convert dns message in buffer to return_msg */
|
||||
static int
|
||||
parse_data(struct module_qstate* qstate, struct sldns_buffer* buf)
|
||||
@@ -420,24 +451,18 @@ parse_data(struct module_qstate* qstate, struct sldns_buffer* buf)
|
||||
qstate->return_rcode = LDNS_RCODE_NOERROR;
|
||||
|
||||
/* see how much of the TTL expired, and remove it */
|
||||
if(*qstate->env->now <= (time_t)timestamp) {
|
||||
verbose(VERB_ALGO, "cachedb msg adjust by zero");
|
||||
return 1; /* message from the future (clock skew?) */
|
||||
}
|
||||
adjust = *qstate->env->now - (time_t)timestamp;
|
||||
if(qstate->return_msg->rep->ttl < adjust) {
|
||||
verbose(VERB_ALGO, "cachedb msg expired");
|
||||
return 0; /* message expired */
|
||||
}
|
||||
verbose(VERB_ALGO, "cachedb msg adjusted down by %d", (int)adjust);
|
||||
/*adjust_msg(qstate->return_msg, adjust);*/
|
||||
/* TODO:
|
||||
msg->rep->ttl = r->ttl - adjust;
|
||||
msg->rep->prefetch_ttl = PREFETCH_TTL_CALC(msg->rep->ttl);
|
||||
for(i=0; i<d->count + d->rrsig_count; i++) {
|
||||
if(d->rr_ttl[i] < adjust)
|
||||
d->rr_ttl[i] = 0;
|
||||
else d->rr_ttl[i] -= adjust;
|
||||
}
|
||||
if(d->ttl < adjust)
|
||||
d->ttl = 0;
|
||||
else d->ttl -= adjust;
|
||||
*/
|
||||
/* TODO */
|
||||
|
||||
return 0;
|
||||
adjust_msg_ttl(qstate->return_msg, adjust);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+1
-1
@@ -48,7 +48,7 @@ void _ARC4_UNLOCK(void)
|
||||
}
|
||||
#else /* !THREADS_DISABLED */
|
||||
|
||||
static lock_quick_t arc4lock;
|
||||
static lock_quick_type arc4lock;
|
||||
static int arc4lockinit = 0;
|
||||
|
||||
void _ARC4_LOCK(void)
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@
|
||||
#include "util/locks.h"
|
||||
|
||||
/** the lock for ctime buffer */
|
||||
static lock_basic_t ctime_lock;
|
||||
static lock_basic_type ctime_lock;
|
||||
/** has it been inited */
|
||||
static int ctime_r_init = 0;
|
||||
|
||||
|
||||
+53
@@ -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
|
||||
|
||||
@@ -68,6 +71,18 @@
|
||||
if you don't. */
|
||||
#undef HAVE_DECL_ARC4RANDOM_UNIFORM
|
||||
|
||||
/* Define to 1 if you have the declaration of `inet_ntop', and to 0 if you
|
||||
don't. */
|
||||
#undef HAVE_DECL_INET_NTOP
|
||||
|
||||
/* Define to 1 if you have the declaration of `inet_pton', and to 0 if you
|
||||
don't. */
|
||||
#undef HAVE_DECL_INET_PTON
|
||||
|
||||
/* Define to 1 if you have the declaration of `NID_ED25519', and to 0 if you
|
||||
don't. */
|
||||
#undef HAVE_DECL_NID_ED25519
|
||||
|
||||
/* Define to 1 if you have the declaration of `NID_secp384r1', and to 0 if you
|
||||
don't. */
|
||||
#undef HAVE_DECL_NID_SECP384R1
|
||||
@@ -146,6 +161,9 @@
|
||||
/* Define to 1 if you have the `EVP_cleanup' function. */
|
||||
#undef HAVE_EVP_CLEANUP
|
||||
|
||||
/* Define to 1 if you have the `EVP_DigestVerify' function. */
|
||||
#undef HAVE_EVP_DIGESTVERIFY
|
||||
|
||||
/* Define to 1 if you have the `EVP_dss1' function. */
|
||||
#undef HAVE_EVP_DSS1
|
||||
|
||||
@@ -377,6 +395,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
|
||||
|
||||
@@ -446,6 +467,12 @@
|
||||
/* Define to 1 if you have the <syslog.h> header file. */
|
||||
#undef HAVE_SYSLOG_H
|
||||
|
||||
/* 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
|
||||
|
||||
@@ -455,6 +482,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
|
||||
|
||||
@@ -640,6 +670,12 @@
|
||||
/* 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 dnscrypt with xchacha20 support */
|
||||
#undef USE_DNSCRYPT_XCHACHA20
|
||||
|
||||
/* Define to 1 to enable dnstap support */
|
||||
#undef USE_DNSTAP
|
||||
|
||||
@@ -652,9 +688,15 @@
|
||||
/* Define this to enable an EVP workaround for older openssl */
|
||||
#undef USE_ECDSA_EVP_WORKAROUND
|
||||
|
||||
/* Define this to enable ED25519 support. */
|
||||
#undef USE_ED25519
|
||||
|
||||
/* Define this to enable GOST support. */
|
||||
#undef USE_GOST
|
||||
|
||||
/* Define to 1 to use ipsecmod support. */
|
||||
#undef USE_IPSECMOD
|
||||
|
||||
/* Define if you want to use internal select based events */
|
||||
#undef USE_MINI_EVENT
|
||||
|
||||
@@ -664,6 +706,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
|
||||
|
||||
@@ -1061,6 +1106,14 @@ char *strsep(char **stringp, const char *delim);
|
||||
int isblank(int c);
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INET_NTOP) && !HAVE_DECL_INET_NTOP
|
||||
const char *inet_ntop(int af, const void *src, char *dst, size_t size);
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INET_PTON) && !HAVE_DECL_INET_PTON
|
||||
int inet_pton(int af, const char* src, void* dst);
|
||||
#endif
|
||||
|
||||
#if !defined(HAVE_STRPTIME) || !defined(STRPTIME_WORKS)
|
||||
#define strptime unbound_strptime
|
||||
struct tm;
|
||||
|
||||
+133
-15
@@ -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],[0])
|
||||
m4_define([VERSION_MICRO],[4])
|
||||
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_CURRENT=7
|
||||
LIBUNBOUND_REVISION=3
|
||||
LIBUNBOUND_AGE=4
|
||||
LIBUNBOUND_AGE=5
|
||||
# 1.0.0 had 0:12:0
|
||||
# 1.0.1 had 0:13:0
|
||||
# 1.0.2 had 0:14:0
|
||||
@@ -68,6 +69,10 @@ LIBUNBOUND_AGE=4
|
||||
# 1.5.9 had 6:1: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
|
||||
# 1.6.3 had 7:2:5
|
||||
# 1.6.4 had 7:3:5
|
||||
|
||||
# Current -- the number of the binary API that we're implementing
|
||||
# Revision -- which iteration of the implementation of the binary
|
||||
@@ -105,6 +110,11 @@ case "$prefix" in
|
||||
prefix="/usr/local"
|
||||
;;
|
||||
esac
|
||||
case "$exec_prefix" in
|
||||
NONE)
|
||||
exec_prefix="$prefix"
|
||||
;;
|
||||
esac
|
||||
|
||||
# are we on MinGW?
|
||||
if uname -s 2>&1 | grep MINGW32 >/dev/null; then on_mingw="yes"
|
||||
@@ -116,10 +126,16 @@ fi
|
||||
#
|
||||
# Determine configuration file
|
||||
# the eval is to evaluate shell expansion twice
|
||||
UNBOUND_SBIN_DIR=`eval echo "${sbindir}"`
|
||||
AC_SUBST(UNBOUND_SBIN_DIR)
|
||||
UNBOUND_SYSCONF_DIR=`eval echo "${sysconfdir}"`
|
||||
AC_SUBST(UNBOUND_SYSCONF_DIR)
|
||||
UNBOUND_LOCALSTATE_DIR=`eval echo "${localstatedir}"`
|
||||
AC_SUBST(UNBOUND_LOCALSTATE_DIR)
|
||||
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],
|
||||
@@ -189,7 +205,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)
|
||||
@@ -203,7 +219,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)
|
||||
@@ -303,7 +319,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.
|
||||
@@ -549,7 +565,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])
|
||||
@@ -676,7 +692,7 @@ else
|
||||
AC_MSG_RESULT([no])
|
||||
fi
|
||||
AC_CHECK_HEADERS([openssl/conf.h openssl/engine.h openssl/bn.h openssl/dh.h openssl/dsa.h openssl/rsa.h],,, [AC_INCLUDES_DEFAULT])
|
||||
AC_CHECK_FUNCS([OPENSSL_config EVP_sha1 EVP_sha256 EVP_sha512 FIPS_mode EVP_MD_CTX_new OpenSSL_add_all_digests OPENSSL_init_crypto EVP_cleanup ERR_load_crypto_strings CRYPTO_cleanup_all_ex_data ERR_free_strings RAND_cleanup DSA_SIG_set0 EVP_dss1])
|
||||
AC_CHECK_FUNCS([OPENSSL_config EVP_sha1 EVP_sha256 EVP_sha512 FIPS_mode EVP_MD_CTX_new OpenSSL_add_all_digests OPENSSL_init_crypto EVP_cleanup ERR_load_crypto_strings CRYPTO_cleanup_all_ex_data ERR_free_strings RAND_cleanup DSA_SIG_set0 EVP_dss1 EVP_DigestVerify])
|
||||
|
||||
# these check_funcs need -lssl
|
||||
BAKLIBS="$LIBS"
|
||||
@@ -708,6 +724,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)
|
||||
@@ -717,6 +743,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])
|
||||
@@ -879,6 +918,23 @@ case "$enable_dsa" in
|
||||
;;
|
||||
esac
|
||||
|
||||
AC_ARG_ENABLE(ed25519, AC_HELP_STRING([--disable-ed25519], [Disable ED25519 support]))
|
||||
use_ed25519="no"
|
||||
case "$enable_ed25519" in
|
||||
no)
|
||||
;;
|
||||
*)
|
||||
if test $USE_NSS = "no" -a $USE_NETTLE = "no"; then
|
||||
AC_CHECK_DECLS([NID_ED25519], [
|
||||
AC_DEFINE_UNQUOTED([USE_ED25519], [1], [Define this to enable ED25519 support.])
|
||||
use_ed25519="yes"
|
||||
], [ if test "x$enable_ed25519" = "xyes"; then AC_MSG_ERROR([OpenSSL does not support ED25519 and you used --enable-ed25519.])
|
||||
fi ], [AC_INCLUDES_DEFAULT
|
||||
#include <openssl/evp.h>
|
||||
])
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
AC_ARG_ENABLE(event-api, AC_HELP_STRING([--enable-event-api], [Enable (experimental) pluggable event base libunbound API installed to unbound-event.h]))
|
||||
case "$enable_event_api" in
|
||||
@@ -1053,6 +1109,10 @@ if test x_$enable_static_exe = x_yes; then
|
||||
fi
|
||||
fi
|
||||
|
||||
# Include systemd.m4 - begin
|
||||
sinclude(systemd.m4)
|
||||
# Include systemd.m4 - end
|
||||
|
||||
# set lock checking if requested
|
||||
AC_ARG_ENABLE(lock_checks, AC_HELP_STRING([--enable-lock-checks],
|
||||
[ enable to check lock and unlock calls, for debug purposes ]),
|
||||
@@ -1143,7 +1203,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])])
|
||||
|
||||
@@ -1151,6 +1211,28 @@ AC_CHECK_FUNCS([setresgid],,[AC_CHECK_FUNCS([setregid])])
|
||||
if echo $build_os | grep darwin8 > /dev/null; then
|
||||
AC_DEFINE(DARWIN_BROKEN_SETREUID, 1, [Define this if on macOSX10.4-darwin8 and setreuid and setregid do not work])
|
||||
fi
|
||||
AC_CHECK_DECLS([inet_pton,inet_ntop], [], [], [
|
||||
AC_INCLUDES_DEFAULT
|
||||
#ifdef HAVE_NETINET_IN_H
|
||||
#include <netinet/in.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_NETINET_TCP_H
|
||||
#include <netinet/tcp.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_ARPA_INET_H
|
||||
#include <arpa/inet.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_WINSOCK2_H
|
||||
#include <winsock2.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_WS2TCPIP_H
|
||||
#include <ws2tcpip.h>
|
||||
#endif
|
||||
])
|
||||
AC_REPLACE_FUNCS(inet_aton)
|
||||
AC_REPLACE_FUNCS(inet_pton)
|
||||
AC_REPLACE_FUNCS(inet_ntop)
|
||||
@@ -1188,11 +1270,11 @@ if test "$USE_NSS" = "no"; then
|
||||
if test "$USE_WINSOCK" = 1; then
|
||||
AC_LIBOBJ(getentropy_win)
|
||||
else
|
||||
case `uname` in
|
||||
Darwin)
|
||||
case "$host" in
|
||||
Darwin|*darwin*)
|
||||
AC_LIBOBJ(getentropy_osx)
|
||||
;;
|
||||
SunOS)
|
||||
*solaris*|*sunos*|SunOS)
|
||||
AC_LIBOBJ(getentropy_solaris)
|
||||
AC_CHECK_HEADERS([sys/sha2.h],, [
|
||||
AC_CHECK_FUNCS([SHA512_Update],,[
|
||||
@@ -1205,7 +1287,7 @@ if test "$USE_NSS" = "no"; then
|
||||
fi
|
||||
AC_SEARCH_LIBS([clock_gettime], [rt])
|
||||
;;
|
||||
Linux|*)
|
||||
*linux*|Linux|*)
|
||||
AC_LIBOBJ(getentropy_linux)
|
||||
AC_CHECK_FUNCS([SHA512_Update],,[
|
||||
AC_DEFINE([COMPAT_SHA512], [1], [Do sha512 definitions in config.h])
|
||||
@@ -1276,6 +1358,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
|
||||
@@ -1287,6 +1382,21 @@ case "$enable_cachedb" in
|
||||
;;
|
||||
esac
|
||||
|
||||
# check for ipsecmod if requested
|
||||
AC_ARG_ENABLE(ipsecmod, AC_HELP_STRING([--enable-ipsecmod], [Enable ipsecmod module that facilitates opportunistic IPsec]))
|
||||
case "$enable_ipsecmod" in
|
||||
yes)
|
||||
AC_DEFINE([USE_IPSECMOD], [1], [Define to 1 to use ipsecmod support.])
|
||||
IPSECMOD_OBJ="ipsecmod.lo ipsecmod-whitelist.lo"
|
||||
AC_SUBST(IPSECMOD_OBJ)
|
||||
IPSECMOD_HEADER='$(srcdir)/ipsecmod/ipsecmod.h $(srcdir)/ipsecmod/ipsecmod-whitelist.h'
|
||||
AC_SUBST(IPSECMOD_HEADER)
|
||||
;;
|
||||
no|*)
|
||||
# nothing
|
||||
;;
|
||||
esac
|
||||
|
||||
AC_MSG_CHECKING([if ${MAKE:-make} supports $< with implicit rule in scope])
|
||||
# on openBSD, the implicit rule make $< work.
|
||||
# on Solaris, it does not work ($? is changed sources, $^ lists dependencies).
|
||||
@@ -1463,6 +1573,14 @@ char *strsep(char **stringp, const char *delim);
|
||||
int isblank(int c);
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INET_NTOP) && !HAVE_DECL_INET_NTOP
|
||||
const char *inet_ntop(int af, const void *src, char *dst, size_t size);
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_INET_PTON) && !HAVE_DECL_INET_PTON
|
||||
int inet_pton(int af, const char* src, void* dst);
|
||||
#endif
|
||||
|
||||
#if !defined(HAVE_STRPTIME) || !defined(STRPTIME_WORKS)
|
||||
#define strptime unbound_strptime
|
||||
struct tm;
|
||||
@@ -1571,6 +1689,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])
|
||||
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
|
||||
|
||||
@@ -29,3 +29,8 @@ distribution but may be helpful.
|
||||
Patch from Stephane Lapie for ASAHI Net.
|
||||
* unbound_smf22.tar.gz: Solaris SMF installation/removal scripts.
|
||||
Contributed by Yuri Voinov.
|
||||
* unbound.socket and unbound.service: systemd files for unbound, install them
|
||||
in /usr/lib/systemd/system. Contributed by Sami Kerola and Pavel Odintsov.
|
||||
* redirect-bogus.patch: Return configured address for bogus A and AAAA answers,
|
||||
instead of SERVFAIL. Contributed by SIDN.
|
||||
* fastrpz.patch: fastrpz support from Farsight Security.
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,344 @@
|
||||
Index: daemon/worker.c
|
||||
===================================================================
|
||||
--- daemon/worker.c (revision 4191)
|
||||
+++ daemon/worker.c (working copy)
|
||||
@@ -663,8 +663,21 @@
|
||||
if(!inplace_cb_reply_servfail_call(&worker->env, qinfo, NULL, rep,
|
||||
LDNS_RCODE_SERVFAIL, edns, worker->scratchpad))
|
||||
goto bail_out;
|
||||
- error_encode(repinfo->c->buffer, LDNS_RCODE_SERVFAIL,
|
||||
- qinfo, id, flags, edns);
|
||||
+ if (qinfo->qtype == LDNS_RR_TYPE_A &&
|
||||
+ worker->env.cfg->redirect_bogus_ipv4) {
|
||||
+ /* BAD cached */
|
||||
+ fixed_address_encode(repinfo->c->buffer,
|
||||
+ LDNS_RCODE_NOERROR, qinfo, id, flags, edns,
|
||||
+ worker->env.cfg->redirect_bogus_ipv4);
|
||||
+ } else if (qinfo->qtype == LDNS_RR_TYPE_AAAA &&
|
||||
+ worker->env.cfg->redirect_bogus_ipv6) {
|
||||
+ fixed_address_encode(repinfo->c->buffer,
|
||||
+ LDNS_RCODE_NOERROR, qinfo, id, flags, edns,
|
||||
+ worker->env.cfg->redirect_bogus_ipv6);
|
||||
+ } else {
|
||||
+ error_encode(repinfo->c->buffer, LDNS_RCODE_SERVFAIL,
|
||||
+ qinfo, id, flags, edns);
|
||||
+ }
|
||||
rrset_array_unlock_touch(worker->env.rrset_cache,
|
||||
worker->scratchpad, rep->ref, rep->rrset_count);
|
||||
if(worker->stats.extended) {
|
||||
Index: doc/unbound.conf.5.in
|
||||
===================================================================
|
||||
--- doc/unbound.conf.5.in (revision 4191)
|
||||
+++ doc/unbound.conf.5.in (working copy)
|
||||
@@ -1244,6 +1244,18 @@
|
||||
This can make ordinary queries complete (if repeatedly queried for),
|
||||
and enter the cache, whilst also mitigating the traffic flow by the
|
||||
factor given.
|
||||
+.TP 5
|
||||
+.B redirect-bogus-ipv4: \fI<IPv4 address>
|
||||
+Set a fixed address for DNSSEC failures that are cached
|
||||
+Instead of responding to A queries with SERVFAIL, respond
|
||||
+with NOERROR and the address specified here
|
||||
+The TTL of the response will be 5 seconds
|
||||
+.TP 5
|
||||
+.B redirect-bogus-ipv6: \fI<IPv4 address>
|
||||
+Set a fixed address for DNSSEC failures that are cached
|
||||
+Instead of responding to AAAA queries with SERVFAIL, respond
|
||||
+with NOERROR and the address specified here
|
||||
+The TTL of the response will be 5 seconds
|
||||
.SS "Remote Control Options"
|
||||
In the
|
||||
.B remote\-control:
|
||||
Index: services/mesh.c
|
||||
===================================================================
|
||||
--- services/mesh.c (revision 4191)
|
||||
+++ services/mesh.c (working copy)
|
||||
@@ -1006,6 +1006,7 @@
|
||||
struct timeval end_time;
|
||||
struct timeval duration;
|
||||
int secure;
|
||||
+ int bogus_override = 0;
|
||||
/* Copy the client's EDNS for later restore, to make sure the edns
|
||||
* compare is with the correct edns options. */
|
||||
struct edns_data edns_bak = r->edns;
|
||||
@@ -1016,6 +1017,7 @@
|
||||
rcode = LDNS_RCODE_SERVFAIL;
|
||||
if(m->s.env->cfg->stat_extended)
|
||||
m->s.env->mesh->ans_bogus++;
|
||||
+ bogus_override = 1;
|
||||
}
|
||||
if(rep && rep->security == sec_status_secure)
|
||||
secure = 1;
|
||||
@@ -1047,17 +1049,34 @@
|
||||
} else if(rcode) {
|
||||
m->s.qinfo.qname = r->qname;
|
||||
m->s.qinfo.local_alias = r->local_alias;
|
||||
- if(rcode == LDNS_RCODE_SERVFAIL) {
|
||||
- if(!inplace_cb_reply_servfail_call(m->s.env, &m->s.qinfo, &m->s,
|
||||
- rep, rcode, &r->edns, m->s.region))
|
||||
- r->edns.opt_list = NULL;
|
||||
- } else {
|
||||
- if(!inplace_cb_reply_call(m->s.env, &m->s.qinfo, &m->s, rep, rcode,
|
||||
- &r->edns, m->s.region))
|
||||
- r->edns.opt_list = NULL;
|
||||
+ if(bogus_override && m->s.qinfo.qtype == LDNS_RR_TYPE_A &&
|
||||
+ m->s.env->cfg->redirect_bogus_ipv4) {
|
||||
+ fixed_address_encode(r->query_reply.c->buffer,
|
||||
+ LDNS_RCODE_NOERROR, &m->s.qinfo, r->qid,
|
||||
+ r->qflags, &r->edns,
|
||||
+ m->s.env->cfg->redirect_bogus_ipv4);
|
||||
+ } else if(bogus_override &&
|
||||
+ m->s.qinfo.qtype == LDNS_RR_TYPE_AAAA &&
|
||||
+ m->s.env->cfg->redirect_bogus_ipv6) {
|
||||
+ fixed_address_encode(r->query_reply.c->buffer,
|
||||
+ LDNS_RCODE_NOERROR, &m->s.qinfo, r->qid,
|
||||
+ r->qflags, &r->edns,
|
||||
+ m->s.env->cfg->redirect_bogus_ipv6);
|
||||
+ } else {
|
||||
+ if(rcode == LDNS_RCODE_SERVFAIL) {
|
||||
+ if(!inplace_cb_reply_servfail_call(m->s.env,
|
||||
+ &m->s.qinfo, &m->s,
|
||||
+ rep, rcode, &r->edns, m->s.region))
|
||||
+ r->edns.opt_list = NULL;
|
||||
+ } else {
|
||||
+ if(!inplace_cb_reply_call(m->s.env, &m->s.qinfo,
|
||||
+ &m->s, rep, rcode, &r->edns,
|
||||
+ m->s.region))
|
||||
+ r->edns.opt_list = NULL;
|
||||
+ }
|
||||
+ error_encode(r->query_reply.c->buffer, rcode,
|
||||
+ &m->s.qinfo, r->qid, r->qflags, &r->edns);
|
||||
}
|
||||
- error_encode(r->query_reply.c->buffer, rcode, &m->s.qinfo,
|
||||
- r->qid, r->qflags, &r->edns);
|
||||
comm_point_send_reply(&r->query_reply);
|
||||
} else {
|
||||
size_t udp_size = r->edns.udp_size;
|
||||
Index: util/config_file.c
|
||||
===================================================================
|
||||
--- util/config_file.c (revision 4191)
|
||||
+++ util/config_file.c (working copy)
|
||||
@@ -273,6 +273,8 @@
|
||||
cfg->ratelimit_factor = 10;
|
||||
cfg->qname_minimisation = 0;
|
||||
cfg->qname_minimisation_strict = 0;
|
||||
+ cfg->redirect_bogus_ipv4 = NULL;
|
||||
+ cfg->redirect_bogus_ipv6 = NULL;
|
||||
cfg->shm_enable = 0;
|
||||
cfg->shm_key = 11777;
|
||||
cfg->dnscrypt = 0;
|
||||
@@ -602,6 +604,10 @@
|
||||
}
|
||||
oi[cfg->num_out_ifs++] = d;
|
||||
cfg->out_ifs = oi;
|
||||
+ } else if (strcmp(opt, "redirect-bogus-ipv4:") == 0) {
|
||||
+ cfg->redirect_bogus_ipv4 = strdup(val);
|
||||
+ } else if (strcmp(opt, "redirect-bogus-ipv6:") == 0) {
|
||||
+ cfg->redirect_bogus_ipv6 = strdup(val);
|
||||
} else {
|
||||
/* unknown or unsupported (from the set_option interface):
|
||||
* interface, outgoing-interface, access-control,
|
||||
@@ -1250,6 +1256,12 @@
|
||||
free(cfg->dnstap_version);
|
||||
config_deldblstrlist(cfg->ratelimit_for_domain);
|
||||
config_deldblstrlist(cfg->ratelimit_below_domain);
|
||||
+ if (cfg->redirect_bogus_ipv4) {
|
||||
+ free(cfg->redirect_bogus_ipv4);
|
||||
+ }
|
||||
+ if (cfg->redirect_bogus_ipv6) {
|
||||
+ free(cfg->redirect_bogus_ipv6);
|
||||
+ }
|
||||
#ifdef USE_IPSECMOD
|
||||
free(cfg->ipsecmod_hook);
|
||||
config_delstrlist(cfg->ipsecmod_whitelist);
|
||||
Index: util/config_file.h
|
||||
===================================================================
|
||||
--- util/config_file.h (revision 4191)
|
||||
+++ util/config_file.h (working copy)
|
||||
@@ -444,6 +444,9 @@
|
||||
/** minimise QNAME in strict mode, minimise according to RFC.
|
||||
* Do not apply fallback */
|
||||
int qname_minimisation_strict;
|
||||
+ /** construct fake responses for DNSSEC failures */
|
||||
+ char *redirect_bogus_ipv4;
|
||||
+ char *redirect_bogus_ipv6;
|
||||
/** SHM data - true if shm is enabled */
|
||||
int shm_enable;
|
||||
/** SHM data - key for the shm */
|
||||
Index: util/configlexer.lex
|
||||
===================================================================
|
||||
--- util/configlexer.lex (revision 4191)
|
||||
+++ util/configlexer.lex (working copy)
|
||||
@@ -410,6 +410,8 @@
|
||||
response-ip-tag{COLON} { YDVAR(2, VAR_RESPONSE_IP_TAG) }
|
||||
response-ip{COLON} { YDVAR(2, VAR_RESPONSE_IP) }
|
||||
response-ip-data{COLON} { YDVAR(2, VAR_RESPONSE_IP_DATA) }
|
||||
+redirect-bogus-ipv4{COLON} { YDVAR(1, VAR_REDIRECT_BOGUS_IPV4) }
|
||||
+redirect-bogus-ipv6{COLON} { YDVAR(1, VAR_REDIRECT_BOGUS_IPV6) }
|
||||
dnscrypt{COLON} { YDVAR(0, VAR_DNSCRYPT) }
|
||||
dnscrypt-enable{COLON} { YDVAR(1, VAR_DNSCRYPT_ENABLE) }
|
||||
dnscrypt-port{COLON} { YDVAR(1, VAR_DNSCRYPT_PORT) }
|
||||
Index: util/configparser.y
|
||||
===================================================================
|
||||
--- util/configparser.y (revision 4191)
|
||||
+++ util/configparser.y (working copy)
|
||||
@@ -44,6 +44,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
|
||||
+#include "sldns/str2wire.h"
|
||||
#include "util/configyyrename.h"
|
||||
#include "util/config_file.h"
|
||||
#include "util/net_help.h"
|
||||
@@ -141,6 +142,7 @@
|
||||
%token VAR_ACCESS_CONTROL_TAG_DATA VAR_VIEW VAR_ACCESS_CONTROL_VIEW
|
||||
%token VAR_VIEW_FIRST VAR_SERVE_EXPIRED VAR_FAKE_DSA VAR_FAKE_SHA1
|
||||
%token VAR_LOG_IDENTITY VAR_HIDE_TRUSTANCHOR VAR_TRUST_ANCHOR_SIGNALING
|
||||
+%token VAR_REDIRECT_BOGUS_IPV4 VAR_REDIRECT_BOGUS_IPV6
|
||||
%token VAR_USE_SYSTEMD VAR_SHM_ENABLE VAR_SHM_KEY
|
||||
%token VAR_DNSCRYPT VAR_DNSCRYPT_ENABLE VAR_DNSCRYPT_PORT VAR_DNSCRYPT_PROVIDER
|
||||
%token VAR_DNSCRYPT_SECRET_KEY VAR_DNSCRYPT_PROVIDER_CERT
|
||||
@@ -228,6 +230,7 @@
|
||||
server_access_control_tag_data | server_access_control_view |
|
||||
server_qname_minimisation_strict | server_serve_expired |
|
||||
server_fake_dsa | server_log_identity | server_use_systemd |
|
||||
+ server_redirect_bogus_ipv4 | server_redirect_bogus_ipv6 |
|
||||
server_response_ip_tag | server_response_ip | server_response_ip_data |
|
||||
server_shm_enable | server_shm_key | server_fake_sha1 |
|
||||
server_hide_trustanchor | server_trust_anchor_signaling |
|
||||
@@ -1873,6 +1876,34 @@
|
||||
#endif
|
||||
}
|
||||
;
|
||||
+server_redirect_bogus_ipv4: VAR_REDIRECT_BOGUS_IPV4 STRING_ARG
|
||||
+ {
|
||||
+ uint8_t data[4];
|
||||
+ size_t data_len = 4;
|
||||
+ OUTYY(("P(name:%s)\n", $2));
|
||||
+ if(cfg_parser->cfg->redirect_bogus_ipv4) {
|
||||
+ yyerror("redirect-bogus-ipv4, can only use one address");
|
||||
+ }
|
||||
+ if(sldns_str2wire_a_buf($2, data, &data_len) != LDNS_WIREPARSE_ERR_OK) {
|
||||
+ yyerror("redirect-bogus-ipv4, not a valid IPv4 address");
|
||||
+ }
|
||||
+ free(cfg_parser->cfg->redirect_bogus_ipv4);
|
||||
+ cfg_parser->cfg->redirect_bogus_ipv4 = $2;
|
||||
+ }
|
||||
+server_redirect_bogus_ipv6: VAR_REDIRECT_BOGUS_IPV6 STRING_ARG
|
||||
+ {
|
||||
+ uint8_t data[16];
|
||||
+ size_t data_len = 16;
|
||||
+ OUTYY(("P(name:%s)\n", $2));
|
||||
+ if(cfg_parser->cfg->redirect_bogus_ipv6) {
|
||||
+ yyerror("redirect-bogus-ipv6, can only use one address");
|
||||
+ }
|
||||
+ if(sldns_str2wire_aaaa_buf($2, data, &data_len) != LDNS_WIREPARSE_ERR_OK) {
|
||||
+ yyerror("redirect-bogus-ipv6, not a valid IPv6 address");
|
||||
+ }
|
||||
+ free(cfg_parser->cfg->redirect_bogus_ipv6);
|
||||
+ cfg_parser->cfg->redirect_bogus_ipv6 = $2;
|
||||
+ }
|
||||
stub_name: VAR_NAME STRING_ARG
|
||||
{
|
||||
OUTYY(("P(name:%s)\n", $2));
|
||||
Index: util/data/msgencode.c
|
||||
===================================================================
|
||||
--- util/data/msgencode.c (revision 4191)
|
||||
+++ util/data/msgencode.c (working copy)
|
||||
@@ -48,6 +48,7 @@
|
||||
#include "util/regional.h"
|
||||
#include "util/net_help.h"
|
||||
#include "sldns/sbuffer.h"
|
||||
+#include "sldns/str2wire.h"
|
||||
#include "services/localzone.h"
|
||||
|
||||
/** return code that means the function ran out of memory. negative so it does
|
||||
@@ -914,3 +915,63 @@
|
||||
attach_edns_record(buf, &es);
|
||||
}
|
||||
}
|
||||
+
|
||||
+void
|
||||
+fixed_address_encode(sldns_buffer* buf, int r, struct query_info* qinfo,
|
||||
+ uint16_t qid, uint16_t qflags, struct edns_data* edns, char* data)
|
||||
+{
|
||||
+ uint16_t flags;
|
||||
+ uint8_t addr_data[16];
|
||||
+ size_t addr_len = 16;
|
||||
+ if (qinfo->qtype == LDNS_RR_TYPE_A) {
|
||||
+ sldns_str2wire_a_buf(data, addr_data, &addr_len);
|
||||
+ } else if (qinfo->qtype == LDNS_RR_TYPE_AAAA) {
|
||||
+ sldns_str2wire_aaaa_buf(data, addr_data, &addr_len);
|
||||
+ } else {
|
||||
+ return error_encode(buf, LDNS_RCODE_NOERROR, qinfo, qid, qflags, edns);
|
||||
+ }
|
||||
+ sldns_buffer_clear(buf);
|
||||
+ sldns_buffer_write(buf, &qid, sizeof(uint16_t));
|
||||
+ flags = (uint16_t)(BIT_QR | BIT_RA | r); /* QR and retcode*/
|
||||
+ flags |= (qflags & (BIT_RD|BIT_CD)); /* copy RD and CD bit */
|
||||
+ sldns_buffer_write_u16(buf, flags);
|
||||
+ if(qinfo) flags = 1;
|
||||
+ else flags = 0;
|
||||
+ sldns_buffer_write_u16(buf, flags);
|
||||
+ sldns_buffer_write_u16(buf, 1);
|
||||
+ flags = 0;
|
||||
+ sldns_buffer_write(buf, &flags, sizeof(uint16_t));
|
||||
+ sldns_buffer_write(buf, &flags, sizeof(uint16_t));
|
||||
+ if(qinfo) {
|
||||
+ // query
|
||||
+ if(sldns_buffer_current(buf) == qinfo->qname)
|
||||
+ sldns_buffer_skip(buf, (ssize_t)qinfo->qname_len);
|
||||
+ else sldns_buffer_write(buf, qinfo->qname, qinfo->qname_len);
|
||||
+ sldns_buffer_write_u16(buf, qinfo->qtype);
|
||||
+ sldns_buffer_write_u16(buf, qinfo->qclass);
|
||||
+ // faked answer
|
||||
+ if(sldns_buffer_current(buf) == qinfo->qname)
|
||||
+ sldns_buffer_skip(buf, (ssize_t)qinfo->qname_len);
|
||||
+ else sldns_buffer_write(buf, qinfo->qname, qinfo->qname_len);
|
||||
+ sldns_buffer_write_u16(buf, qinfo->qtype);
|
||||
+ sldns_buffer_write_u16(buf, qinfo->qclass);
|
||||
+ sldns_buffer_write_u16(buf, 0);
|
||||
+ // TTL. Should we make this configurable too?
|
||||
+ sldns_buffer_write_u16(buf, 5);
|
||||
+ sldns_buffer_write_u16(buf, addr_len);
|
||||
+ sldns_buffer_write(buf, addr_data, addr_len);
|
||||
+ fflush(stderr);
|
||||
+ }
|
||||
+ sldns_buffer_flip(buf);
|
||||
+ if(edns) {
|
||||
+ struct edns_data es = *edns;
|
||||
+ es.edns_version = EDNS_ADVERTISED_VERSION;
|
||||
+ es.udp_size = EDNS_ADVERTISED_SIZE;
|
||||
+ es.ext_rcode = 0;
|
||||
+ es.bits &= EDNS_DO;
|
||||
+ if(sldns_buffer_limit(buf) + calc_edns_field_size(&es) >
|
||||
+ edns->udp_size)
|
||||
+ return;
|
||||
+ attach_edns_record(buf, &es);
|
||||
+ }
|
||||
+}
|
||||
Index: util/data/msgencode.h
|
||||
===================================================================
|
||||
--- util/data/msgencode.h (revision 4191)
|
||||
+++ util/data/msgencode.h (working copy)
|
||||
@@ -128,4 +128,20 @@
|
||||
void error_encode(struct sldns_buffer* pkt, int r, struct query_info* qinfo,
|
||||
uint16_t qid, uint16_t qflags, struct edns_data* edns);
|
||||
|
||||
+/**
|
||||
+ * Encode a fixed address response.
|
||||
+ * This is a fake answer to either an A or AAA query
|
||||
+ *
|
||||
+ * It will answer with that address
|
||||
+ *
|
||||
+ * @param pkt: where to store the packet.
|
||||
+ * @param r: RCODE value to encode.
|
||||
+ * @param qinfo: if not NULL, the query is included.
|
||||
+ * @param qid: query ID to set in packet. network order.
|
||||
+ * @param qflags: original query flags (to copy RD and CD bits). host order.
|
||||
+ * @param edns: if not NULL, this is the query edns info,
|
||||
+ * and an edns reply is attached. Only attached if EDNS record fits reply.
|
||||
+ */
|
||||
+void fixed_address_encode(struct sldns_buffer* pkt, int r, struct query_info* qinfo,
|
||||
+ uint16_t qid, uint16_t qflags, struct edns_data* edns, char* address);
|
||||
#endif /* UTIL_DATA_MSGENCODE_H */
|
||||
@@ -0,0 +1,28 @@
|
||||
[Unit]
|
||||
Description=Validating, recursive, and caching DNS resolver
|
||||
Documentation=man:unbound(8)
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
|
||||
[Service]
|
||||
ExecReload=/bin/kill -HUP $MAINPID
|
||||
ExecStart=@UNBOUND_SBIN_DIR@/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=@UNBOUND_SYSCONF_DIR@ @UNBOUND_LOCALSTATE_DIR@ /run @UNBOUND_RUN_DIR@
|
||||
RestrictAddressFamilies=AF_INET AF_UNIX
|
||||
RestrictRealtime=true
|
||||
SystemCallArchitectures=native
|
||||
SystemCallFilter=~@clock @cpu-emulation @debug @keyring @module mount @obsolete @resources
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
[Socket]
|
||||
ListenDatagram=127.0.0.1:1153
|
||||
ListenStream=127.0.0.1:1153
|
||||
# ListenStream=@UNBOUND_RUN_DIR@/control
|
||||
[Install]
|
||||
WantedBy=sockets.target
|
||||
+1
-1
@@ -76,7 +76,7 @@ struct acl_list {
|
||||
* Tree of the addresses that are allowed/blocked.
|
||||
* contents of type acl_addr.
|
||||
*/
|
||||
rbtree_t tree;
|
||||
rbtree_type tree;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
+59
-2
@@ -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,8 +87,13 @@
|
||||
#include "util/tube.h"
|
||||
#include "util/net_help.h"
|
||||
#include "sldns/keyraw.h"
|
||||
#include "respip/respip.h"
|
||||
#include <signal.h>
|
||||
|
||||
#ifdef HAVE_SYSTEMD
|
||||
#include <systemd/sd-daemon.h>
|
||||
#endif
|
||||
|
||||
/** How many quit requests happened. */
|
||||
static int sig_record_quit = 0;
|
||||
/** How many reload requests happened. */
|
||||
@@ -175,8 +181,15 @@ static void
|
||||
signal_handling_playback(struct worker* wrk)
|
||||
{
|
||||
#ifdef SIGHUP
|
||||
if(sig_record_reload)
|
||||
if(sig_record_reload) {
|
||||
# ifdef HAVE_SYSTEMD
|
||||
sd_notify(0, "RELOADING=1");
|
||||
# endif
|
||||
worker_sighandler(SIGHUP, wrk);
|
||||
# ifdef HAVE_SYSTEMD
|
||||
sd_notify(0, "READY=1");
|
||||
# endif
|
||||
}
|
||||
#endif
|
||||
if(sig_record_quit)
|
||||
worker_sighandler(SIGTERM, wrk);
|
||||
@@ -550,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");
|
||||
@@ -559,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.
|
||||
*/
|
||||
@@ -594,14 +638,26 @@ 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");
|
||||
#endif
|
||||
log_info("start of service (%s).", PACKAGE_STRING);
|
||||
worker_work(daemon->workers[0]);
|
||||
#ifdef HAVE_SYSTEMD
|
||||
sd_notify(0, "STOPPING=1");
|
||||
#endif
|
||||
log_info("service stopped (%s).", PACKAGE_STRING);
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
@@ -621,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() */
|
||||
@@ -653,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
|
||||
};
|
||||
|
||||
|
||||
+161
-37
@@ -124,7 +124,7 @@ timeval_subtract(struct timeval* d, const struct timeval* end,
|
||||
|
||||
/** divide sum of timers to get average */
|
||||
static void
|
||||
timeval_divide(struct timeval* avg, const struct timeval* sum, size_t d)
|
||||
timeval_divide(struct timeval* avg, const struct timeval* sum, long long d)
|
||||
{
|
||||
#ifndef S_SPLINT_S
|
||||
size_t leftover;
|
||||
@@ -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
|
||||
#if defined(SHA256_DIGEST_LENGTH) && defined(USE_ECDSA)
|
||||
/* if we have sha256, set the cipher list to have no known vulns */
|
||||
if(!SSL_CTX_set_cipher_list(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("could not set cipher list with SSL_CTX_set_cipher_list");
|
||||
#endif
|
||||
|
||||
if (cfg->remote_control_use_cert == 0) {
|
||||
/* No certificates are requested */
|
||||
@@ -381,7 +404,7 @@ add_open(const char* ip, int nr, struct listen_port** list, int noproto_is_err,
|
||||
|
||||
if(ip[0] == '/') {
|
||||
/* This looks like a local socket */
|
||||
fd = create_local_accept_sock(ip, &noproto);
|
||||
fd = create_local_accept_sock(ip, &noproto, cfg->use_systemd);
|
||||
/*
|
||||
* Change socket ownership and permissions so users other
|
||||
* than root can access it provided they are in the same
|
||||
@@ -424,7 +447,7 @@ add_open(const char* ip, int nr, struct listen_port** list, int noproto_is_err,
|
||||
|
||||
/* open fd */
|
||||
fd = create_tcp_accept_sock(res, 1, &noproto, 0,
|
||||
cfg->ip_transparent, 0, cfg->ip_freebind);
|
||||
cfg->ip_transparent, 0, cfg->ip_freebind, cfg->use_systemd);
|
||||
freeaddrinfo(res);
|
||||
}
|
||||
|
||||
@@ -757,11 +780,13 @@ do_verbosity(SSL* ssl, char* str)
|
||||
|
||||
/** print stats from statinfo */
|
||||
static int
|
||||
print_stats(SSL* ssl, const char* nm, struct stats_info* s)
|
||||
print_stats(SSL* ssl, const char* nm, struct ub_stats_info* s)
|
||||
{
|
||||
struct timeval avg;
|
||||
struct timeval sumwait, avg;
|
||||
if(!ssl_printf(ssl, "%s.num.queries"SQ"%lu\n", nm,
|
||||
(unsigned long)s->svr.num_queries)) return 0;
|
||||
if(!ssl_printf(ssl, "%s.num.queries_ip_ratelimited"SQ"%lu\n", nm,
|
||||
(unsigned long)s->svr.num_queries_ip_ratelimited)) return 0;
|
||||
if(!ssl_printf(ssl, "%s.num.cachehits"SQ"%lu\n", nm,
|
||||
(unsigned long)(s->svr.num_queries
|
||||
- s->svr.num_queries_missed_cache))) return 0;
|
||||
@@ -773,10 +798,20 @@ 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/
|
||||
(s->svr.num_queries_missed_cache+
|
||||
(double)(s->svr.num_queries_missed_cache+
|
||||
s->svr.num_queries_prefetch) : 0.0)) return 0;
|
||||
if(!ssl_printf(ssl, "%s.requestlist.max"SQ"%lu\n", nm,
|
||||
(unsigned long)s->svr.max_query_list_size)) return 0;
|
||||
@@ -788,7 +823,11 @@ print_stats(SSL* ssl, const char* nm, struct stats_info* s)
|
||||
(unsigned long)s->mesh_num_states)) return 0;
|
||||
if(!ssl_printf(ssl, "%s.requestlist.current.user"SQ"%lu\n", nm,
|
||||
(unsigned long)s->mesh_num_reply_states)) return 0;
|
||||
timeval_divide(&avg, &s->mesh_replies_sum_wait, s->mesh_replies_sent);
|
||||
#ifndef S_SPLINT_S
|
||||
sumwait.tv_sec = s->mesh_replies_sum_wait_sec;
|
||||
sumwait.tv_usec = s->mesh_replies_sum_wait_usec;
|
||||
#endif
|
||||
timeval_divide(&avg, &sumwait, s->mesh_replies_sent);
|
||||
if(!ssl_printf(ssl, "%s.recursion.time.avg"SQ ARG_LL "d.%6.6d\n", nm,
|
||||
(long long)avg.tv_sec, (int)avg.tv_usec)) return 0;
|
||||
if(!ssl_printf(ssl, "%s.recursion.time.median"SQ"%g\n", nm,
|
||||
@@ -800,7 +839,7 @@ print_stats(SSL* ssl, const char* nm, struct stats_info* s)
|
||||
|
||||
/** print stats for one thread */
|
||||
static int
|
||||
print_thread_stats(SSL* ssl, int i, struct stats_info* s)
|
||||
print_thread_stats(SSL* ssl, int i, struct ub_stats_info* s)
|
||||
{
|
||||
char nm[16];
|
||||
snprintf(nm, sizeof(nm), "thread%d", i);
|
||||
@@ -827,26 +866,24 @@ print_longnum(SSL* ssl, const char* desc, size_t x)
|
||||
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 */
|
||||
#ifdef USE_IPSECMOD
|
||||
size_t ipsecmod = 0;
|
||||
#endif /* USE_IPSECMOD */
|
||||
msg = slabhash_get_mem(daemon->env->msg_cache);
|
||||
rrset = slabhash_get_mem(&daemon->env->rrset_cache->table);
|
||||
val=0;
|
||||
iter=0;
|
||||
m = modstack_find(&worker->env.mesh->mods, "validator");
|
||||
if(m != -1) {
|
||||
fptr_ok(fptr_whitelist_mod_get_mem(worker->env.mesh->
|
||||
mods.mod[m]->get_mem));
|
||||
val = (*worker->env.mesh->mods.mod[m]->get_mem)
|
||||
(&worker->env, m);
|
||||
}
|
||||
m = modstack_find(&worker->env.mesh->mods, "iterator");
|
||||
if(m != -1) {
|
||||
fptr_ok(fptr_whitelist_mod_get_mem(worker->env.mesh->
|
||||
mods.mod[m]->get_mem));
|
||||
iter = (*worker->env.mesh->mods.mod[m]->get_mem)
|
||||
(&worker->env, m);
|
||||
}
|
||||
val = mod_get_mem(&worker->env, "validator");
|
||||
iter = mod_get_mem(&worker->env, "iterator");
|
||||
respip = mod_get_mem(&worker->env, "respip");
|
||||
#ifdef CLIENT_SUBNET
|
||||
subnet = mod_get_mem(&worker->env, "subnet");
|
||||
#endif /* CLIENT_SUBNET */
|
||||
#ifdef USE_IPSECMOD
|
||||
ipsecmod = mod_get_mem(&worker->env, "ipsecmod");
|
||||
#endif /* USE_IPSECMOD */
|
||||
|
||||
if(!print_longnum(ssl, "mem.cache.rrset"SQ, rrset))
|
||||
return 0;
|
||||
@@ -856,6 +893,16 @@ 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 */
|
||||
#ifdef USE_IPSECMOD
|
||||
if(!print_longnum(ssl, "mem.mod.ipsecmod"SQ, ipsecmod))
|
||||
return 0;
|
||||
#endif /* USE_IPSECMOD */
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -880,7 +927,7 @@ print_uptime(SSL* ssl, struct worker* worker, int reset)
|
||||
|
||||
/** print extended histogram */
|
||||
static int
|
||||
print_hist(SSL* ssl, struct stats_info* s)
|
||||
print_hist(SSL* ssl, struct ub_stats_info* s)
|
||||
{
|
||||
struct timehist* hist;
|
||||
size_t i;
|
||||
@@ -908,14 +955,14 @@ print_hist(SSL* ssl, struct stats_info* s)
|
||||
|
||||
/** print extended stats */
|
||||
static int
|
||||
print_ext(SSL* ssl, struct stats_info* s)
|
||||
print_ext(SSL* ssl, struct ub_stats_info* s)
|
||||
{
|
||||
int i;
|
||||
char nm[16];
|
||||
const sldns_rr_descriptor* desc;
|
||||
const sldns_lookup_table* lt;
|
||||
/* TYPE */
|
||||
for(i=0; i<STATS_QTYPE_NUM; i++) {
|
||||
for(i=0; i<UB_STATS_QTYPE_NUM; i++) {
|
||||
if(inhibit_zero && s->svr.qtype[i] == 0)
|
||||
continue;
|
||||
desc = sldns_rr_descript((uint16_t)i);
|
||||
@@ -942,7 +989,7 @@ print_ext(SSL* ssl, struct stats_info* s)
|
||||
(unsigned long)s->svr.qtype_big)) return 0;
|
||||
}
|
||||
/* CLASS */
|
||||
for(i=0; i<STATS_QCLASS_NUM; i++) {
|
||||
for(i=0; i<UB_STATS_QCLASS_NUM; i++) {
|
||||
if(inhibit_zero && s->svr.qclass[i] == 0)
|
||||
continue;
|
||||
lt = sldns_lookup_by_id(sldns_rr_classes, i);
|
||||
@@ -959,7 +1006,7 @@ print_ext(SSL* ssl, struct stats_info* s)
|
||||
(unsigned long)s->svr.qclass_big)) return 0;
|
||||
}
|
||||
/* OPCODE */
|
||||
for(i=0; i<STATS_OPCODE_NUM; i++) {
|
||||
for(i=0; i<UB_STATS_OPCODE_NUM; i++) {
|
||||
if(inhibit_zero && s->svr.qopcode[i] == 0)
|
||||
continue;
|
||||
lt = sldns_lookup_by_id(sldns_opcodes, i);
|
||||
@@ -1001,7 +1048,7 @@ print_ext(SSL* ssl, struct stats_info* s)
|
||||
(unsigned long)s->svr.qEDNS_DO)) return 0;
|
||||
|
||||
/* RCODE */
|
||||
for(i=0; i<STATS_RCODE_NUM; i++) {
|
||||
for(i=0; i<UB_STATS_RCODE_NUM; i++) {
|
||||
/* Always include RCODEs 0-5 */
|
||||
if(inhibit_zero && i > LDNS_RCODE_REFUSED && s->svr.ans_rcode[i] == 0)
|
||||
continue;
|
||||
@@ -1047,8 +1094,8 @@ static void
|
||||
do_stats(SSL* ssl, struct daemon_remote* rc, int reset)
|
||||
{
|
||||
struct daemon* daemon = rc->worker->daemon;
|
||||
struct stats_info total;
|
||||
struct stats_info s;
|
||||
struct ub_stats_info total;
|
||||
struct ub_stats_info s;
|
||||
int i;
|
||||
log_assert(daemon->num > 0);
|
||||
/* gather all thread statistics in one place */
|
||||
@@ -1340,6 +1387,21 @@ 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;
|
||||
}
|
||||
if(!v->isfirst) {
|
||||
/* Global local-zone is not used for this view,
|
||||
* therefore add defaults to this view-specic
|
||||
* local-zone. */
|
||||
struct config_file lz_cfg;
|
||||
memset(&lz_cfg, 0, sizeof(lz_cfg));
|
||||
local_zone_enter_defaults(v->local_zones, &lz_cfg);
|
||||
}
|
||||
}
|
||||
do_zone_add(ssl, v->local_zones, arg2);
|
||||
lock_rw_unlock(&v->lock);
|
||||
}
|
||||
@@ -1358,6 +1420,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);
|
||||
}
|
||||
@@ -1376,6 +1443,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);
|
||||
}
|
||||
@@ -1394,6 +1468,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);
|
||||
}
|
||||
@@ -1416,7 +1495,7 @@ static void
|
||||
do_cache_remove(struct worker* worker, uint8_t* nm, size_t nmlen,
|
||||
uint16_t t, uint16_t c)
|
||||
{
|
||||
hashvalue_t h;
|
||||
hashvalue_type h;
|
||||
struct query_info k;
|
||||
rrset_cache_remove(worker->env.rrset_cache, nm, nmlen, t, c, 0);
|
||||
if(t == LDNS_RR_TYPE_SOA)
|
||||
@@ -2529,7 +2608,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);
|
||||
}
|
||||
|
||||
@@ -2543,7 +2624,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);
|
||||
}
|
||||
|
||||
@@ -2559,6 +2642,8 @@ struct ratelimit_list_arg {
|
||||
time_t now;
|
||||
};
|
||||
|
||||
#define ip_ratelimit_list_arg ratelimit_list_arg
|
||||
|
||||
/** list items in the ratelimit table */
|
||||
static void
|
||||
rate_list(struct lruhash_entry* e, void* arg)
|
||||
@@ -2577,6 +2662,24 @@ rate_list(struct lruhash_entry* e, void* arg)
|
||||
ssl_printf(a->ssl, "%s %d limit %d\n", buf, max, lim);
|
||||
}
|
||||
|
||||
/** list items in the ip_ratelimit table */
|
||||
static void
|
||||
ip_rate_list(struct lruhash_entry* e, void* arg)
|
||||
{
|
||||
char ip[128];
|
||||
struct ip_ratelimit_list_arg* a = (struct ip_ratelimit_list_arg*)arg;
|
||||
struct ip_rate_key* k = (struct ip_rate_key*)e->key;
|
||||
struct ip_rate_data* d = (struct ip_rate_data*)e->data;
|
||||
int lim = infra_ip_ratelimit;
|
||||
int max = infra_rate_max(d, a->now);
|
||||
if(a->all == 0) {
|
||||
if(max < lim)
|
||||
return;
|
||||
}
|
||||
addr_to_str(&k->addr, k->addrlen, ip, sizeof(ip));
|
||||
ssl_printf(a->ssl, "%s %d limit %d\n", ip, max, lim);
|
||||
}
|
||||
|
||||
/** do the ratelimit_list command */
|
||||
static void
|
||||
do_ratelimit_list(SSL* ssl, struct worker* worker, char* arg)
|
||||
@@ -2595,6 +2698,24 @@ do_ratelimit_list(SSL* ssl, struct worker* worker, char* arg)
|
||||
slabhash_traverse(a.infra->domain_rates, 0, rate_list, &a);
|
||||
}
|
||||
|
||||
/** do the ip_ratelimit_list command */
|
||||
static void
|
||||
do_ip_ratelimit_list(SSL* ssl, struct worker* worker, char* arg)
|
||||
{
|
||||
struct ip_ratelimit_list_arg a;
|
||||
a.all = 0;
|
||||
a.infra = worker->env.infra_cache;
|
||||
a.now = *worker->env.now;
|
||||
a.ssl = ssl;
|
||||
arg = skipwhite(arg);
|
||||
if(strcmp(arg, "+a") == 0)
|
||||
a.all = 1;
|
||||
if(a.infra->client_ip_rates==NULL ||
|
||||
(a.all == 0 && infra_ip_ratelimit == 0))
|
||||
return;
|
||||
slabhash_traverse(a.infra->client_ip_rates, 0, ip_rate_list, &a);
|
||||
}
|
||||
|
||||
/** tell other processes to execute the command */
|
||||
static void
|
||||
distribute_cmd(struct daemon_remote* rc, SSL* ssl, char* cmd)
|
||||
@@ -2673,6 +2794,9 @@ execute_cmd(struct daemon_remote* rc, SSL* ssl, char* cmd,
|
||||
} else if(cmdcmp(p, "ratelimit_list", 14)) {
|
||||
do_ratelimit_list(ssl, worker, p+14);
|
||||
return;
|
||||
} else if(cmdcmp(p, "ip_ratelimit_list", 17)) {
|
||||
do_ip_ratelimit_list(ssl, worker, p+17);
|
||||
return;
|
||||
} else if(cmdcmp(p, "stub_add", 8)) {
|
||||
/* must always distribute this cmd */
|
||||
if(rc) distribute_cmd(rc, ssl, cmd);
|
||||
|
||||
+60
-48
@@ -63,57 +63,59 @@
|
||||
|
||||
/** add timers and the values do not overflow or become negative */
|
||||
static void
|
||||
timeval_add(struct timeval* d, const struct timeval* add)
|
||||
stats_timeval_add(long long* d_sec, long long* d_usec, long long add_sec, long long add_usec)
|
||||
{
|
||||
#ifndef S_SPLINT_S
|
||||
d->tv_sec += add->tv_sec;
|
||||
d->tv_usec += add->tv_usec;
|
||||
if(d->tv_usec > 1000000) {
|
||||
d->tv_usec -= 1000000;
|
||||
d->tv_sec++;
|
||||
(*d_sec) += add_sec;
|
||||
(*d_usec) += add_usec;
|
||||
if((*d_usec) > 1000000) {
|
||||
(*d_usec) -= 1000000;
|
||||
(*d_sec)++;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void server_stats_init(struct server_stats* stats, struct config_file* cfg)
|
||||
void server_stats_init(struct ub_server_stats* stats, struct config_file* cfg)
|
||||
{
|
||||
memset(stats, 0, sizeof(*stats));
|
||||
stats->extended = cfg->stat_extended;
|
||||
}
|
||||
|
||||
void server_stats_querymiss(struct server_stats* stats, struct worker* worker)
|
||||
void server_stats_querymiss(struct ub_server_stats* stats, struct worker* worker)
|
||||
{
|
||||
stats->num_queries_missed_cache++;
|
||||
stats->sum_query_list_size += worker->env.mesh->all.count;
|
||||
if(worker->env.mesh->all.count > stats->max_query_list_size)
|
||||
stats->max_query_list_size = worker->env.mesh->all.count;
|
||||
if((long long)worker->env.mesh->all.count > stats->max_query_list_size)
|
||||
stats->max_query_list_size = (long long)worker->env.mesh->all.count;
|
||||
}
|
||||
|
||||
void server_stats_prefetch(struct server_stats* stats, struct worker* worker)
|
||||
void server_stats_prefetch(struct ub_server_stats* stats, struct worker* worker)
|
||||
{
|
||||
stats->num_queries_prefetch++;
|
||||
/* changes the query list size so account that, like a querymiss */
|
||||
stats->sum_query_list_size += worker->env.mesh->all.count;
|
||||
if(worker->env.mesh->all.count > stats->max_query_list_size)
|
||||
stats->max_query_list_size = worker->env.mesh->all.count;
|
||||
if((long long)worker->env.mesh->all.count > stats->max_query_list_size)
|
||||
stats->max_query_list_size = (long long)worker->env.mesh->all.count;
|
||||
}
|
||||
|
||||
void server_stats_log(struct server_stats* stats, struct worker* worker,
|
||||
void server_stats_log(struct ub_server_stats* stats, struct worker* worker,
|
||||
int threadnum)
|
||||
{
|
||||
log_info("server stats for thread %d: %u queries, "
|
||||
"%u answers from cache, %u recursions, %u prefetch",
|
||||
"%u answers from cache, %u recursions, %u prefetch, %u rejected by "
|
||||
"ip ratelimiting",
|
||||
threadnum, (unsigned)stats->num_queries,
|
||||
(unsigned)(stats->num_queries -
|
||||
stats->num_queries_missed_cache),
|
||||
(unsigned)stats->num_queries_missed_cache,
|
||||
(unsigned)stats->num_queries_prefetch);
|
||||
(unsigned)stats->num_queries_prefetch,
|
||||
(unsigned)stats->num_queries_ip_ratelimited);
|
||||
log_info("server stats for thread %d: requestlist max %u avg %g "
|
||||
"exceeded %u jostled %u", threadnum,
|
||||
(unsigned)stats->max_query_list_size,
|
||||
(stats->num_queries_missed_cache+stats->num_queries_prefetch)?
|
||||
(double)stats->sum_query_list_size/
|
||||
(stats->num_queries_missed_cache+
|
||||
(double)(stats->num_queries_missed_cache+
|
||||
stats->num_queries_prefetch) : 0.0,
|
||||
(unsigned)worker->env.mesh->stats_dropped,
|
||||
(unsigned)worker->env.mesh->stats_jostled);
|
||||
@@ -138,49 +140,50 @@ get_rrset_bogus(struct worker* worker)
|
||||
}
|
||||
|
||||
void
|
||||
server_stats_compile(struct worker* worker, struct stats_info* s, int reset)
|
||||
server_stats_compile(struct worker* worker, struct ub_stats_info* s, int reset)
|
||||
{
|
||||
int i;
|
||||
struct listen_list* lp;
|
||||
|
||||
s->svr = worker->stats;
|
||||
s->mesh_num_states = worker->env.mesh->all.count;
|
||||
s->mesh_num_reply_states = worker->env.mesh->num_reply_states;
|
||||
s->mesh_jostled = worker->env.mesh->stats_jostled;
|
||||
s->mesh_dropped = worker->env.mesh->stats_dropped;
|
||||
s->mesh_replies_sent = worker->env.mesh->replies_sent;
|
||||
s->mesh_replies_sum_wait = worker->env.mesh->replies_sum_wait;
|
||||
s->mesh_num_states = (long long)worker->env.mesh->all.count;
|
||||
s->mesh_num_reply_states = (long long)worker->env.mesh->num_reply_states;
|
||||
s->mesh_jostled = (long long)worker->env.mesh->stats_jostled;
|
||||
s->mesh_dropped = (long long)worker->env.mesh->stats_dropped;
|
||||
s->mesh_replies_sent = (long long)worker->env.mesh->replies_sent;
|
||||
s->mesh_replies_sum_wait_sec = (long long)worker->env.mesh->replies_sum_wait.tv_sec;
|
||||
s->mesh_replies_sum_wait_usec = (long long)worker->env.mesh->replies_sum_wait.tv_usec;
|
||||
s->mesh_time_median = timehist_quartile(worker->env.mesh->histogram,
|
||||
0.50);
|
||||
|
||||
/* add in the values from the mesh */
|
||||
s->svr.ans_secure += worker->env.mesh->ans_secure;
|
||||
s->svr.ans_bogus += worker->env.mesh->ans_bogus;
|
||||
s->svr.ans_rcode_nodata += worker->env.mesh->ans_nodata;
|
||||
s->svr.ans_secure += (long long)worker->env.mesh->ans_secure;
|
||||
s->svr.ans_bogus += (long long)worker->env.mesh->ans_bogus;
|
||||
s->svr.ans_rcode_nodata += (long long)worker->env.mesh->ans_nodata;
|
||||
for(i=0; i<16; i++)
|
||||
s->svr.ans_rcode[i] += worker->env.mesh->ans_rcode[i];
|
||||
s->svr.ans_rcode[i] += (long long)worker->env.mesh->ans_rcode[i];
|
||||
timehist_export(worker->env.mesh->histogram, s->svr.hist,
|
||||
NUM_BUCKETS_HIST);
|
||||
/* values from outside network */
|
||||
s->svr.unwanted_replies = worker->back->unwanted_replies;
|
||||
s->svr.qtcp_outgoing = worker->back->num_tcp_outgoing;
|
||||
s->svr.unwanted_replies = (long long)worker->back->unwanted_replies;
|
||||
s->svr.qtcp_outgoing = (long long)worker->back->num_tcp_outgoing;
|
||||
|
||||
/* get and reset validator rrset bogus number */
|
||||
s->svr.rrset_bogus = get_rrset_bogus(worker);
|
||||
s->svr.rrset_bogus = (long long)get_rrset_bogus(worker);
|
||||
|
||||
/* get cache sizes */
|
||||
s->svr.msg_cache_count = count_slabhash_entries(worker->env.msg_cache);
|
||||
s->svr.rrset_cache_count = count_slabhash_entries(&worker->env.rrset_cache->table);
|
||||
s->svr.infra_cache_count = count_slabhash_entries(worker->env.infra_cache->hosts);
|
||||
s->svr.msg_cache_count = (long long)count_slabhash_entries(worker->env.msg_cache);
|
||||
s->svr.rrset_cache_count = (long long)count_slabhash_entries(&worker->env.rrset_cache->table);
|
||||
s->svr.infra_cache_count = (long long)count_slabhash_entries(worker->env.infra_cache->hosts);
|
||||
if(worker->env.key_cache)
|
||||
s->svr.key_cache_count = count_slabhash_entries(worker->env.key_cache->slab);
|
||||
s->svr.key_cache_count = (long long)count_slabhash_entries(worker->env.key_cache->slab);
|
||||
else s->svr.key_cache_count = 0;
|
||||
|
||||
/* get tcp accept usage */
|
||||
s->svr.tcp_accept_usage = 0;
|
||||
for(lp = worker->front->cps; lp; lp = lp->next) {
|
||||
if(lp->com->type == comm_tcp_accept)
|
||||
s->svr.tcp_accept_usage += lp->com->cur_tcp_count;
|
||||
s->svr.tcp_accept_usage += (long long)lp->com->cur_tcp_count;
|
||||
}
|
||||
|
||||
if(reset && !worker->env.cfg->stat_cumulative) {
|
||||
@@ -189,7 +192,7 @@ server_stats_compile(struct worker* worker, struct stats_info* s, int reset)
|
||||
}
|
||||
|
||||
void server_stats_obtain(struct worker* worker, struct worker* who,
|
||||
struct stats_info* s, int reset)
|
||||
struct ub_stats_info* s, int reset)
|
||||
{
|
||||
uint8_t *reply = NULL;
|
||||
uint32_t len = 0;
|
||||
@@ -215,7 +218,7 @@ void server_stats_obtain(struct worker* worker, struct worker* who,
|
||||
|
||||
void server_stats_reply(struct worker* worker, int reset)
|
||||
{
|
||||
struct stats_info s;
|
||||
struct ub_stats_info s;
|
||||
server_stats_compile(worker, &s, reset);
|
||||
verbose(VERB_ALGO, "write stats replymsg");
|
||||
if(!tube_write_msg(worker->daemon->workers[0]->cmd,
|
||||
@@ -223,12 +226,21 @@ void server_stats_reply(struct worker* worker, int reset)
|
||||
fatal_exit("could not write stat values over cmd channel");
|
||||
}
|
||||
|
||||
void server_stats_add(struct stats_info* total, struct stats_info* a)
|
||||
void server_stats_add(struct ub_stats_info* total, struct ub_stats_info* a)
|
||||
{
|
||||
total->svr.num_queries += a->svr.num_queries;
|
||||
total->svr.num_queries_ip_ratelimited += a->svr.num_queries_ip_ratelimited;
|
||||
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;
|
||||
@@ -258,13 +270,13 @@ void server_stats_add(struct stats_info* total, struct stats_info* a)
|
||||
total->svr.unwanted_replies += a->svr.unwanted_replies;
|
||||
total->svr.unwanted_queries += a->svr.unwanted_queries;
|
||||
total->svr.tcp_accept_usage += a->svr.tcp_accept_usage;
|
||||
for(i=0; i<STATS_QTYPE_NUM; i++)
|
||||
for(i=0; i<UB_STATS_QTYPE_NUM; i++)
|
||||
total->svr.qtype[i] += a->svr.qtype[i];
|
||||
for(i=0; i<STATS_QCLASS_NUM; i++)
|
||||
for(i=0; i<UB_STATS_QCLASS_NUM; i++)
|
||||
total->svr.qclass[i] += a->svr.qclass[i];
|
||||
for(i=0; i<STATS_OPCODE_NUM; i++)
|
||||
for(i=0; i<UB_STATS_OPCODE_NUM; i++)
|
||||
total->svr.qopcode[i] += a->svr.qopcode[i];
|
||||
for(i=0; i<STATS_RCODE_NUM; i++)
|
||||
for(i=0; i<UB_STATS_RCODE_NUM; i++)
|
||||
total->svr.ans_rcode[i] += a->svr.ans_rcode[i];
|
||||
for(i=0; i<NUM_BUCKETS_HIST; i++)
|
||||
total->svr.hist[i] += a->svr.hist[i];
|
||||
@@ -275,22 +287,22 @@ void server_stats_add(struct stats_info* total, struct stats_info* a)
|
||||
total->mesh_jostled += a->mesh_jostled;
|
||||
total->mesh_dropped += a->mesh_dropped;
|
||||
total->mesh_replies_sent += a->mesh_replies_sent;
|
||||
timeval_add(&total->mesh_replies_sum_wait, &a->mesh_replies_sum_wait);
|
||||
stats_timeval_add(&total->mesh_replies_sum_wait_sec, &total->mesh_replies_sum_wait_usec, a->mesh_replies_sum_wait_sec, a->mesh_replies_sum_wait_usec);
|
||||
/* the medians are averaged together, this is not as accurate as
|
||||
* taking the median over all of the data, but is good and fast
|
||||
* added up here, division later*/
|
||||
total->mesh_time_median += a->mesh_time_median;
|
||||
}
|
||||
|
||||
void server_stats_insquery(struct server_stats* stats, struct comm_point* c,
|
||||
void server_stats_insquery(struct ub_server_stats* stats, struct comm_point* c,
|
||||
uint16_t qtype, uint16_t qclass, struct edns_data* edns,
|
||||
struct comm_reply* repinfo)
|
||||
{
|
||||
uint16_t flags = sldns_buffer_read_u16_at(c->buffer, 2);
|
||||
if(qtype < STATS_QTYPE_NUM)
|
||||
if(qtype < UB_STATS_QTYPE_NUM)
|
||||
stats->qtype[qtype]++;
|
||||
else stats->qtype_big++;
|
||||
if(qclass < STATS_QCLASS_NUM)
|
||||
if(qclass < UB_STATS_QCLASS_NUM)
|
||||
stats->qclass[qclass]++;
|
||||
else stats->qclass_big++;
|
||||
stats->qopcode[ LDNS_OPCODE_WIRE(sldns_buffer_begin(c->buffer)) ]++;
|
||||
@@ -321,7 +333,7 @@ void server_stats_insquery(struct server_stats* stats, struct comm_point* c,
|
||||
}
|
||||
}
|
||||
|
||||
void server_stats_insrcode(struct server_stats* stats, sldns_buffer* buf)
|
||||
void server_stats_insrcode(struct ub_server_stats* stats, sldns_buffer* buf)
|
||||
{
|
||||
if(stats->extended && sldns_buffer_limit(buf) != 0) {
|
||||
int r = (int)LDNS_RCODE_WIRE( sldns_buffer_begin(buf) );
|
||||
|
||||
+11
-131
@@ -50,144 +50,24 @@ struct comm_reply;
|
||||
struct edns_data;
|
||||
struct sldns_buffer;
|
||||
|
||||
/** number of qtype that is stored for in array */
|
||||
#define STATS_QTYPE_NUM 256
|
||||
/** number of qclass that is stored for in array */
|
||||
#define STATS_QCLASS_NUM 256
|
||||
/** number of rcodes in stats */
|
||||
#define STATS_RCODE_NUM 16
|
||||
/** number of opcodes in stats */
|
||||
#define STATS_OPCODE_NUM 16
|
||||
|
||||
/** per worker statistics */
|
||||
struct server_stats {
|
||||
/** number of queries from clients received. */
|
||||
size_t num_queries;
|
||||
/** number of queries that had a cache-miss. */
|
||||
size_t num_queries_missed_cache;
|
||||
/** number of prefetch queries - cachehits with prefetch */
|
||||
size_t num_queries_prefetch;
|
||||
|
||||
/**
|
||||
* Sum of the querylistsize of the worker for
|
||||
* every query that missed cache. To calculate average.
|
||||
*/
|
||||
size_t sum_query_list_size;
|
||||
/** max value of query list size reached. */
|
||||
size_t max_query_list_size;
|
||||
|
||||
/** Extended stats below (bool) */
|
||||
int extended;
|
||||
|
||||
/** qtype stats */
|
||||
size_t qtype[STATS_QTYPE_NUM];
|
||||
/** bigger qtype values not in array */
|
||||
size_t qtype_big;
|
||||
/** qclass stats */
|
||||
size_t qclass[STATS_QCLASS_NUM];
|
||||
/** bigger qclass values not in array */
|
||||
size_t qclass_big;
|
||||
/** query opcodes */
|
||||
size_t qopcode[STATS_OPCODE_NUM];
|
||||
/** number of queries over TCP */
|
||||
size_t qtcp;
|
||||
/** number of outgoing queries over TCP */
|
||||
size_t qtcp_outgoing;
|
||||
/** number of queries over IPv6 */
|
||||
size_t qipv6;
|
||||
/** number of queries with QR bit */
|
||||
size_t qbit_QR;
|
||||
/** number of queries with AA bit */
|
||||
size_t qbit_AA;
|
||||
/** number of queries with TC bit */
|
||||
size_t qbit_TC;
|
||||
/** number of queries with RD bit */
|
||||
size_t qbit_RD;
|
||||
/** number of queries with RA bit */
|
||||
size_t qbit_RA;
|
||||
/** number of queries with Z bit */
|
||||
size_t qbit_Z;
|
||||
/** number of queries with AD bit */
|
||||
size_t qbit_AD;
|
||||
/** number of queries with CD bit */
|
||||
size_t qbit_CD;
|
||||
/** number of queries with EDNS OPT record */
|
||||
size_t qEDNS;
|
||||
/** number of queries with EDNS with DO flag */
|
||||
size_t qEDNS_DO;
|
||||
/** answer rcodes */
|
||||
size_t ans_rcode[STATS_RCODE_NUM];
|
||||
/** answers with pseudo rcode 'nodata' */
|
||||
size_t ans_rcode_nodata;
|
||||
/** answers that were secure (AD) */
|
||||
size_t ans_secure;
|
||||
/** answers that were bogus (withheld as SERVFAIL) */
|
||||
size_t ans_bogus;
|
||||
/** rrsets marked bogus by validator */
|
||||
size_t rrset_bogus;
|
||||
/** unwanted traffic received on server-facing ports */
|
||||
size_t unwanted_replies;
|
||||
/** unwanted traffic received on client-facing ports */
|
||||
size_t unwanted_queries;
|
||||
/** usage of tcp accept list */
|
||||
size_t tcp_accept_usage;
|
||||
/** answers served from expired cache */
|
||||
size_t zero_ttl_responses;
|
||||
/** histogram data exported to array
|
||||
* if the array is the same size, no data is lost, and
|
||||
* if all histograms are same size (is so by default) then
|
||||
* adding up works well. */
|
||||
size_t hist[NUM_BUCKETS_HIST];
|
||||
|
||||
/** number of message cache entries */
|
||||
size_t msg_cache_count;
|
||||
/** number of rrset cache entries */
|
||||
size_t rrset_cache_count;
|
||||
/** number of infra cache entries */
|
||||
size_t infra_cache_count;
|
||||
/** number of key cache entries */
|
||||
size_t key_cache_count;
|
||||
};
|
||||
|
||||
/**
|
||||
* Statistics to send over the control pipe when asked
|
||||
* This struct is made to be memcpied, sent in binary.
|
||||
*/
|
||||
struct stats_info {
|
||||
/** the thread stats */
|
||||
struct server_stats svr;
|
||||
|
||||
/** mesh stats: current number of states */
|
||||
size_t mesh_num_states;
|
||||
/** mesh stats: current number of reply (user) states */
|
||||
size_t mesh_num_reply_states;
|
||||
/** mesh stats: number of reply states overwritten with a new one */
|
||||
size_t mesh_jostled;
|
||||
/** mesh stats: number of incoming queries dropped */
|
||||
size_t mesh_dropped;
|
||||
/** mesh stats: replies sent */
|
||||
size_t mesh_replies_sent;
|
||||
/** mesh stats: sum of waiting times for the replies */
|
||||
struct timeval mesh_replies_sum_wait;
|
||||
/** mesh stats: median of waiting times for replies (in sec) */
|
||||
double mesh_time_median;
|
||||
};
|
||||
/* stats struct */
|
||||
#include "libunbound/unbound.h"
|
||||
|
||||
/**
|
||||
* Initialize server stats to 0.
|
||||
* @param stats: what to init (this is alloced by the caller).
|
||||
* @param cfg: with extended statistics option.
|
||||
*/
|
||||
void server_stats_init(struct server_stats* stats, struct config_file* cfg);
|
||||
void server_stats_init(struct ub_server_stats* stats, struct config_file* cfg);
|
||||
|
||||
/** add query if it missed the cache */
|
||||
void server_stats_querymiss(struct server_stats* stats, struct worker* worker);
|
||||
void server_stats_querymiss(struct ub_server_stats* stats, struct worker* worker);
|
||||
|
||||
/** add query if was cached and also resulted in a prefetch */
|
||||
void server_stats_prefetch(struct server_stats* stats, struct worker* worker);
|
||||
void server_stats_prefetch(struct ub_server_stats* stats, struct worker* worker);
|
||||
|
||||
/** display the stats to the log */
|
||||
void server_stats_log(struct server_stats* stats, struct worker* worker,
|
||||
void server_stats_log(struct ub_server_stats* stats, struct worker* worker,
|
||||
int threadnum);
|
||||
|
||||
/**
|
||||
@@ -198,7 +78,7 @@ void server_stats_log(struct server_stats* stats, struct worker* worker,
|
||||
* @param reset: if stats can be reset.
|
||||
*/
|
||||
void server_stats_obtain(struct worker* worker, struct worker* who,
|
||||
struct stats_info* s, int reset);
|
||||
struct ub_stats_info* s, int reset);
|
||||
|
||||
/**
|
||||
* Compile stats into structure for this thread worker.
|
||||
@@ -208,7 +88,7 @@ void server_stats_obtain(struct worker* worker, struct worker* who,
|
||||
* @param reset: if true, depending on config stats are reset.
|
||||
* if false, statistics are not reset.
|
||||
*/
|
||||
void server_stats_compile(struct worker* worker, struct stats_info* s,
|
||||
void server_stats_compile(struct worker* worker, struct ub_stats_info* s,
|
||||
int reset);
|
||||
|
||||
/**
|
||||
@@ -224,7 +104,7 @@ void server_stats_reply(struct worker* worker, int reset);
|
||||
* @param total: sum of the two entries.
|
||||
* @param a: to add to it.
|
||||
*/
|
||||
void server_stats_add(struct stats_info* total, struct stats_info* a);
|
||||
void server_stats_add(struct ub_stats_info* total, struct ub_stats_info* a);
|
||||
|
||||
/**
|
||||
* Add stats for this query
|
||||
@@ -235,7 +115,7 @@ void server_stats_add(struct stats_info* total, struct stats_info* a);
|
||||
* @param edns: edns record
|
||||
* @param repinfo: reply info with remote address
|
||||
*/
|
||||
void server_stats_insquery(struct server_stats* stats, struct comm_point* c,
|
||||
void server_stats_insquery(struct ub_server_stats* stats, struct comm_point* c,
|
||||
uint16_t qtype, uint16_t qclass, struct edns_data* edns,
|
||||
struct comm_reply* repinfo);
|
||||
|
||||
@@ -244,6 +124,6 @@ void server_stats_insquery(struct server_stats* stats, struct comm_point* c,
|
||||
* @param stats: the stats
|
||||
* @param buf: buffer with rcode. If buffer is length0: not counted.
|
||||
*/
|
||||
void server_stats_insrcode(struct server_stats* stats, struct sldns_buffer* buf);
|
||||
void server_stats_insrcode(struct ub_server_stats* stats, struct sldns_buffer* buf);
|
||||
|
||||
#endif /* DAEMON_STATS_H */
|
||||
|
||||
@@ -264,6 +264,11 @@ apply_settings(struct daemon* daemon, struct config_file* cfg,
|
||||
}
|
||||
daemon_apply_cfg(daemon, cfg);
|
||||
checkrlimits(cfg);
|
||||
|
||||
if (cfg->use_systemd && cfg->do_daemonize) {
|
||||
log_warn("use-systemd and do-daemonize should not be enabled at the same time");
|
||||
}
|
||||
|
||||
log_ident_set_fromdefault(cfg, log_default_identity);
|
||||
}
|
||||
|
||||
|
||||
+408
-34
@@ -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))
|
||||
@@ -566,7 +662,7 @@ answer_from_cache(struct worker* worker, struct query_info* qinfo,
|
||||
edns->bits &= EDNS_DO;
|
||||
if(!inplace_cb_reply_servfail_call(&worker->env, qinfo, NULL, rep,
|
||||
LDNS_RCODE_SERVFAIL, edns, worker->scratchpad))
|
||||
return 0;
|
||||
goto bail_out;
|
||||
error_encode(repinfo->c->buffer, LDNS_RCODE_SERVFAIL,
|
||||
qinfo, id, flags, edns);
|
||||
rrset_array_unlock_touch(worker->env.rrset_cache,
|
||||
@@ -599,8 +695,34 @@ answer_from_cache(struct worker* worker, struct query_info* qinfo,
|
||||
edns->bits &= EDNS_DO;
|
||||
if(!inplace_cb_reply_cache_call(&worker->env, qinfo, NULL, rep,
|
||||
(int)(flags&LDNS_RCODE_MASK), edns, worker->scratchpad))
|
||||
return 0;
|
||||
if(!reply_info_answer_encode(qinfo, rep, id, flags,
|
||||
goto bail_out;
|
||||
*alias_rrset = NULL; /* avoid confusion if caller set it to non-NULL */
|
||||
if(worker->daemon->use_response_ip && !partial_rep &&
|
||||
!apply_respip_action(worker, qinfo, cinfo, rep, repinfo, alias_rrset,
|
||||
&encode_rep)) {
|
||||
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;
|
||||
@@ -680,7 +811,73 @@ chaos_replystr(sldns_buffer* pkt, const char* str, struct edns_data* edns,
|
||||
if(!inplace_cb_reply_local_call(&worker->env, NULL, NULL, NULL,
|
||||
LDNS_RCODE_NOERROR, edns, worker->scratchpad))
|
||||
edns->opt_list = NULL;
|
||||
attach_edns_record(pkt, edns);
|
||||
if(sldns_buffer_capacity(pkt) >=
|
||||
sldns_buffer_limit(pkt)+calc_edns_field_size(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);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -709,13 +906,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 +923,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;
|
||||
}
|
||||
|
||||
@@ -787,19 +993,72 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
|
||||
{
|
||||
struct worker* worker = (struct worker*)arg;
|
||||
int ret;
|
||||
hashvalue_t h;
|
||||
hashvalue_type h;
|
||||
struct lruhash_entry* e;
|
||||
struct query_info qinfo;
|
||||
struct edns_data edns;
|
||||
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,
|
||||
@@ -825,7 +1084,29 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
|
||||
comm_point_drop_reply(repinfo);
|
||||
return 0;
|
||||
}
|
||||
|
||||
worker->stats.num_queries++;
|
||||
|
||||
/* check if this query should be dropped based on source ip rate limiting */
|
||||
if(!infra_ip_ratelimit_inc(worker->env.infra_cache, repinfo,
|
||||
*worker->env.now)) {
|
||||
/* See if we are passed through with slip factor */
|
||||
if(worker->env.cfg->ip_ratelimit_factor != 0 &&
|
||||
ub_random_max(worker->env.rnd,
|
||||
worker->env.cfg->ip_ratelimit_factor) == 1) {
|
||||
|
||||
char addrbuf[128];
|
||||
addr_to_str(&repinfo->addr, repinfo->addrlen,
|
||||
addrbuf, sizeof(addrbuf));
|
||||
verbose(VERB_OPS, "ip_ratelimit allowed through for ip address %s ",
|
||||
addrbuf);
|
||||
} else {
|
||||
worker->stats.num_queries_ip_ratelimited++;
|
||||
comm_point_drop_reply(repinfo);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* see if query is in the cache */
|
||||
if(!query_info_parse(&qinfo, c->buffer)) {
|
||||
verbose(VERB_ALGO, "worker parse request: formerror.");
|
||||
@@ -860,6 +1141,28 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
|
||||
}
|
||||
goto send_reply;
|
||||
}
|
||||
if(qinfo.qtype == LDNS_RR_TYPE_OPT ||
|
||||
qinfo.qtype == LDNS_RR_TYPE_TSIG ||
|
||||
qinfo.qtype == LDNS_RR_TYPE_TKEY ||
|
||||
qinfo.qtype == LDNS_RR_TYPE_MAILA ||
|
||||
qinfo.qtype == LDNS_RR_TYPE_MAILB ||
|
||||
(qinfo.qtype >= 128 && qinfo.qtype <= 248)) {
|
||||
verbose(VERB_ALGO, "worker request: formerror for meta-type.");
|
||||
log_addr(VERB_CLIENT,"from",&repinfo->addr, repinfo->addrlen);
|
||||
if(worker_err_ratelimit(worker, LDNS_RCODE_FORMERR) == -1) {
|
||||
comm_point_drop_reply(repinfo);
|
||||
return 0;
|
||||
}
|
||||
sldns_buffer_rewind(c->buffer);
|
||||
LDNS_QR_SET(sldns_buffer_begin(c->buffer));
|
||||
LDNS_RCODE_SET(sldns_buffer_begin(c->buffer),
|
||||
LDNS_RCODE_FORMERR);
|
||||
if(worker->stats.extended) {
|
||||
worker->stats.qtype[qinfo.qtype]++;
|
||||
server_stats_insrcode(&worker->stats, c->buffer);
|
||||
}
|
||||
goto send_reply;
|
||||
}
|
||||
if((ret=parse_edns_from_pkt(c->buffer, &edns, worker->scratchpad)) != 0) {
|
||||
struct edns_data reply_edns;
|
||||
verbose(VERB_ALGO, "worker parse edns: formerror.");
|
||||
@@ -886,7 +1189,9 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
|
||||
error_encode(c->buffer, EDNS_RCODE_BADVERS&0xf, &qinfo,
|
||||
*(uint16_t*)(void *)sldns_buffer_begin(c->buffer),
|
||||
sldns_buffer_read_u16_at(c->buffer, 2), NULL);
|
||||
attach_edns_record(c->buffer, &edns);
|
||||
if(sldns_buffer_capacity(c->buffer) >=
|
||||
sldns_buffer_limit(c->buffer)+calc_edns_field_size(&edns))
|
||||
attach_edns_record(c->buffer, &edns);
|
||||
regional_free_all(worker->scratchpad);
|
||||
goto send_reply;
|
||||
}
|
||||
@@ -992,16 +1297,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) {
|
||||
@@ -1011,16 +1343,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);
|
||||
@@ -1049,7 +1403,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);
|
||||
@@ -1059,10 +1413,25 @@ 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,
|
||||
c->type, c->buffer);
|
||||
#endif
|
||||
if(worker->env.cfg->log_replies)
|
||||
{
|
||||
struct timeval tv = {0, 0};
|
||||
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;
|
||||
}
|
||||
@@ -1119,6 +1488,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);
|
||||
}
|
||||
@@ -1300,6 +1673,7 @@ worker_init(struct worker* worker, struct config_file *cfg,
|
||||
worker->env.mesh = mesh_create(&worker->daemon->mods, &worker->env);
|
||||
worker->env.detach_subs = &mesh_detach_subs;
|
||||
worker->env.attach_sub = &mesh_attach_sub;
|
||||
worker->env.add_sub = &mesh_add_sub;
|
||||
worker->env.kill_sub = &mesh_state_delete;
|
||||
worker->env.detect_cycle = &mesh_detect_cycle;
|
||||
worker->env.scratch_buffer = sldns_buffer_new(cfg->msg_buffer_size);
|
||||
|
||||
+2
-2
@@ -85,7 +85,7 @@ struct worker {
|
||||
/** global shared daemon structure */
|
||||
struct daemon* daemon;
|
||||
/** thread id */
|
||||
ub_thread_t thr_id;
|
||||
ub_thread_type thr_id;
|
||||
/** pipe, for commands for this worker */
|
||||
struct tube* cmd;
|
||||
/** the event base this worker works with */
|
||||
@@ -116,7 +116,7 @@ struct worker {
|
||||
/** allocation cache for this thread */
|
||||
struct alloc_cache alloc;
|
||||
/** per thread statistics */
|
||||
struct server_stats stats;
|
||||
struct ub_server_stats stats;
|
||||
/** thread scratch regional */
|
||||
struct regional* scratchpad;
|
||||
|
||||
|
||||
+1
-26
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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 signed_content[64];
|
||||
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];
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,651 @@
|
||||
|
||||
#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 "dnscrypt/dnscrypt_config.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 dnsccert that was found using dnsc_find_cert.
|
||||
* 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] cert the cert 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 dnsccert *cert,
|
||||
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(cert->es_version[1] == 2) {
|
||||
#ifdef USE_DNSCRYPT_XCHACHA20
|
||||
if (crypto_box_curve25519xchacha20poly1305_beforenm(
|
||||
nmkey, nmkey, cert->keypair->crypt_secretkey) != 0) {
|
||||
return -1;
|
||||
}
|
||||
#else
|
||||
return -1;
|
||||
#endif
|
||||
} else {
|
||||
if (crypto_box_beforenm(nmkey, nmkey, cert->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);
|
||||
|
||||
if(cert->es_version[1] == 2) {
|
||||
#ifdef USE_DNSCRYPT_XCHACHA20
|
||||
if (crypto_box_curve25519xchacha20poly1305_open_easy_afternm
|
||||
(buf,
|
||||
buf + DNSCRYPT_QUERY_BOX_OFFSET,
|
||||
len - DNSCRYPT_QUERY_BOX_OFFSET, nonce,
|
||||
nmkey) != 0) {
|
||||
return -1;
|
||||
}
|
||||
#else
|
||||
return -1;
|
||||
#endif
|
||||
} else {
|
||||
if (crypto_box_open_easy_afternm
|
||||
(buf,
|
||||
buf + DNSCRYPT_QUERY_BOX_OFFSET,
|
||||
len - DNSCRYPT_QUERY_BOX_OFFSET, nonce,
|
||||
nmkey) != 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
len -= DNSCRYPT_QUERY_HEADER_SIZE;
|
||||
|
||||
while (*sldns_buffer_at(buffer, --len) == 0)
|
||||
;
|
||||
|
||||
if (*sldns_buffer_at(buffer, len) != 0x80) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
memcpy(client_nonce, nonce, crypto_box_HALF_NONCEBYTES);
|
||||
|
||||
sldns_buffer_set_position(buffer, 0);
|
||||
sldns_buffer_set_limit(buffer, len);
|
||||
|
||||
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 dnsccert 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] cert the dnsccert 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 dnsccert *cert,
|
||||
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,
|
||||
cert->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(cert->es_version[1] == 2) {
|
||||
#ifdef USE_DNSCRYPT_XCHACHA20
|
||||
if (crypto_box_curve25519xchacha20poly1305_easy_afternm
|
||||
(boxed, boxed + crypto_box_MACBYTES, len, nonce, nmkey) != 0) {
|
||||
return -1;
|
||||
}
|
||||
#else
|
||||
return -1;
|
||||
#endif
|
||||
} else {
|
||||
if (crypto_box_easy_afternm
|
||||
(boxed, boxed + crypto_box_MACBYTES, len, 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given an absolute path on the original root, returns the absolute path
|
||||
* within the chroot. If chroot is disabled, the path is not modified.
|
||||
* No char * is malloced so there is no need to free this.
|
||||
* \param[in] cfg the configuration.
|
||||
* \param[in] path the path from the original root.
|
||||
* \return the path from inside the chroot.
|
||||
*/
|
||||
static char *
|
||||
dnsc_chroot_path(struct config_file *cfg, char *path)
|
||||
{
|
||||
char *nm;
|
||||
nm = path;
|
||||
if(cfg->chrootdir && cfg->chrootdir[0] && strncmp(nm,
|
||||
cfg->chrootdir, strlen(cfg->chrootdir)) == 0)
|
||||
nm += strlen(cfg->chrootdir);
|
||||
return nm;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
char *nm;
|
||||
|
||||
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++) {
|
||||
nm = dnsc_chroot_path(cfg, head->str);
|
||||
if(dnsc_read_from_file(
|
||||
nm,
|
||||
(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 cert matching a DNSCrypt query.
|
||||
* \param[in] dnscenv The DNSCrypt enviroment, which contains the list of certs
|
||||
* supported by the server.
|
||||
* \param[in] buffer The encrypted DNS query.
|
||||
* \return a dnsccert * if we found a cert matching the magic_number of the
|
||||
* query, NULL otherwise.
|
||||
*/
|
||||
static const dnsccert *
|
||||
dnsc_find_cert(struct dnsc_env* dnscenv, struct sldns_buffer* buffer)
|
||||
{
|
||||
const dnsccert *certs = dnscenv->certs;
|
||||
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->signed_certs_count; i++) {
|
||||
if (memcmp(certs[i].magic_query, dnscrypt_header->magic_query,
|
||||
DNSCRYPT_MAGIC_HEADER_LEN) == 0) {
|
||||
return &certs[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;
|
||||
}
|
||||
|
||||
static const char *
|
||||
key_get_es_version(uint8_t version[2])
|
||||
{
|
||||
struct es_version {
|
||||
uint8_t es_version[2];
|
||||
const char *name;
|
||||
};
|
||||
|
||||
struct es_version es_versions[] = {
|
||||
{{0x00, 0x01}, "X25519-XSalsa20Poly1305"},
|
||||
{{0x00, 0x02}, "X25519-XChacha20Poly1305"},
|
||||
};
|
||||
int i;
|
||||
for(i=0; i < (int)sizeof(es_versions); i++){
|
||||
if(es_versions[i].es_version[0] == version[0] &&
|
||||
es_versions[i].es_version[1] == version[1]){
|
||||
return es_versions[i].name;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Parse the secret key files from `dnscrypt-secret-key` config and populates
|
||||
* a list of dnsccert with es_version, magic number and 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 cert_id, keypair_id;
|
||||
size_t c;
|
||||
char *nm;
|
||||
|
||||
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);
|
||||
env->certs = sodium_allocarray(env->signed_certs_count,
|
||||
sizeof *env->certs);
|
||||
|
||||
cert_id = 0U;
|
||||
keypair_id = 0U;
|
||||
for(head = cfg->dnscrypt_secret_key; head; head = head->next, keypair_id++) {
|
||||
char fingerprint[80];
|
||||
int found_cert = 0;
|
||||
KeyPair *current_keypair = &env->keypairs[keypair_id];
|
||||
nm = dnsc_chroot_path(cfg, head->str);
|
||||
if(dnsc_read_from_file(
|
||||
nm,
|
||||
(char *)(current_keypair->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(current_keypair->crypt_publickey,
|
||||
current_keypair->crypt_secretkey) != 0) {
|
||||
fatal_exit("dnsc_parse_keys: could not generate public key from %s", head->str);
|
||||
}
|
||||
dnsc_key_to_fingerprint(fingerprint, current_keypair->crypt_publickey);
|
||||
verbose(VERB_OPS, "Crypt public key fingerprint for %s: %s", head->str, fingerprint);
|
||||
// find the cert matching this key
|
||||
for(c = 0; c < env->signed_certs_count; c++) {
|
||||
if(memcmp(current_keypair->crypt_publickey,
|
||||
env->signed_certs[c].server_publickey,
|
||||
crypto_box_PUBLICKEYBYTES) == 0) {
|
||||
dnsccert *current_cert = &env->certs[cert_id++];
|
||||
found_cert = 1;
|
||||
current_cert->keypair = current_keypair;
|
||||
memcpy(current_cert->magic_query,
|
||||
env->signed_certs[c].magic_query,
|
||||
sizeof env->signed_certs[c].magic_query);
|
||||
memcpy(current_cert->es_version,
|
||||
env->signed_certs[c].version_major,
|
||||
sizeof env->signed_certs[c].version_major
|
||||
);
|
||||
dnsc_key_to_fingerprint(fingerprint,
|
||||
current_cert->keypair->crypt_publickey);
|
||||
verbose(VERB_OPS, "Crypt public key fingerprint for %s: %s",
|
||||
head->str, fingerprint);
|
||||
verbose(VERB_OPS, "Using %s",
|
||||
key_get_es_version(current_cert->es_version));
|
||||
#ifndef USE_DNSCRYPT_XCHACHA20
|
||||
if (current_cert->es_version[1] == 0x02) {
|
||||
fatal_exit("Certificate for XChacha20 but libsodium does not support it.");
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
if (!found_cert) {
|
||||
fatal_exit("dnsc_parse_keys: could not match certificate for key "
|
||||
"%s. Unable to determine ES version.",
|
||||
head->str);
|
||||
}
|
||||
}
|
||||
return cert_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->dnsc_cert = dnsc_find_cert(dnscenv, c->buffer)) != NULL) {
|
||||
if(dnscrypt_server_uncurve(repinfo->dnsc_cert,
|
||||
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->dnsc_cert,
|
||||
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;
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
#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;
|
||||
|
||||
typedef struct cert_ {
|
||||
uint8_t magic_query[DNSCRYPT_MAGIC_HEADER_LEN];
|
||||
uint8_t es_version[2];
|
||||
KeyPair *keypair;
|
||||
} dnsccert;
|
||||
|
||||
struct dnsc_env {
|
||||
struct SignedCert *signed_certs;
|
||||
dnsccert *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
|
||||
@@ -0,0 +1,36 @@
|
||||
# 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!]))
|
||||
AC_SEARCH_LIBS([crypto_box_curve25519xchacha20poly1305_beforenm], [sodium],
|
||||
[
|
||||
AC_SUBST([ENABLE_DNSCRYPT_XCHACHA20], [1])
|
||||
AC_DEFINE(
|
||||
[USE_DNSCRYPT_XCHACHA20], [1],
|
||||
[Define to 1 to enable dnscrypt with xchacha20 support])
|
||||
],
|
||||
[
|
||||
AC_SUBST([ENABLE_DNSCRYPT_XCHACHA20], [0])
|
||||
])
|
||||
$1
|
||||
else
|
||||
AC_SUBST([ENABLE_DNSCRYPT_XCHACHA20], [0])
|
||||
$2
|
||||
fi
|
||||
])
|
||||
@@ -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 */
|
||||
+8
-1
@@ -121,7 +121,9 @@ dt_msg_init(const struct dt_env *env,
|
||||
struct dt_env *
|
||||
dt_create(const char *socket_path, unsigned num_workers)
|
||||
{
|
||||
#ifdef UNBOUND_DEBUG
|
||||
fstrm_res res;
|
||||
#endif
|
||||
struct dt_env *env;
|
||||
struct fstrm_iothr_options *fopt;
|
||||
struct fstrm_unix_writer_options *fuwopt;
|
||||
@@ -138,7 +140,12 @@ dt_create(const char *socket_path, unsigned num_workers)
|
||||
return NULL;
|
||||
|
||||
fwopt = fstrm_writer_options_init();
|
||||
res = fstrm_writer_options_add_content_type(fwopt,
|
||||
#ifdef UNBOUND_DEBUG
|
||||
res =
|
||||
#else
|
||||
(void)
|
||||
#endif
|
||||
fstrm_writer_options_add_content_type(fwopt,
|
||||
DNSTAP_CONTENT_TYPE, sizeof(DNSTAP_CONTENT_TYPE) - 1);
|
||||
log_assert(res == fstrm_res_success);
|
||||
|
||||
|
||||
Binary file not shown.
+472
@@ -1,5 +1,477 @@
|
||||
22 June 2017: Wouter
|
||||
- Tag 1.6.4rc2
|
||||
|
||||
22 June 2017: Ralph
|
||||
- Added fastrpz patch to contrib
|
||||
|
||||
21 June 2017: Wouter
|
||||
- Fix #1316: heap read buffer overflow in parse_edns_options.
|
||||
|
||||
20 June 2017: Wouter
|
||||
- Fix warning in pythonmod under clang compiler.
|
||||
- Tag 1.6.4rc1
|
||||
- Fix lintian typo.
|
||||
|
||||
16 June 2017: Ralph
|
||||
- Fix #1277: disable domain ratelimit by setting value to 0.
|
||||
|
||||
16 June 2017: Wouter
|
||||
- Fix #1301: memory leak in respip and tests.
|
||||
- Free callback in edns-subnetmod on exit and restart.
|
||||
- Fix memory leak in sldns_buffer_new_frm_data.
|
||||
- Fix memory leak in dnscrypt config read.
|
||||
- Fix dnscrypt chacha cert support ifdefs.
|
||||
- Fix dnscrypt chacha cert unit test escapes in grep.
|
||||
- Remove asynclook tests that cause test and purifier problems.
|
||||
- Fix to unlock view in view test.
|
||||
|
||||
15 June 2017: Wouter
|
||||
- Fix stub zone queries leaking to the internet for
|
||||
harden-referral-path ns checks.
|
||||
- Fix query for refetch_glue of stub leaking to internet.
|
||||
|
||||
13 June 2017: Wouter
|
||||
- Fix #1279: Memory leak on reload when python module is enabled.
|
||||
- Fix #1280: Unbound fails assert when response from authoritative
|
||||
contains malformed qname. When 0x20 caps-for-id is enabled, when
|
||||
assertions are not enabled the malformed qname is handled correctly.
|
||||
- 1.6.3 tag created, with only #1280 fix, trunk is 1.6.4 development.
|
||||
- More fixes in depth for buffer checks in 0x20 qname checks.
|
||||
|
||||
12 June 2017: Wouter
|
||||
- Fix #1278: Incomplete wildcard proof.
|
||||
|
||||
8 June 2017: Ralph
|
||||
- Added domain name based ECS whitelist.
|
||||
|
||||
8 June 2017: Wouter
|
||||
- Detect chacha for dnscrypt at configure time.
|
||||
- dnscrypt unit tests with chacha.
|
||||
|
||||
7 June 2017: Wouter
|
||||
- Fix that unbound-control can set val_clean_additional and val_permissive_mode.
|
||||
- Add dnscrypt XChaCha20 tests.
|
||||
|
||||
6 June 2017: Wouter
|
||||
- Add an explicit type cast for TCP FASTOPEN fix.
|
||||
- renumbering B-Root's IPv6 address to 2001:500:200::b.
|
||||
- Fix #1275: cached data in cachedb is never used.
|
||||
- Fix #1276: [dnscrypt] add XChaCha20-Poly1305 cipher.
|
||||
|
||||
1 June 2017: Ralph
|
||||
- Fix #1274: automatically trim chroot path from dnscrypt key/cert paths
|
||||
(from Manu Bretelle).
|
||||
|
||||
1 June 2017: Wouter
|
||||
- Fix fastopen EPIPE fallthrough to perform connect.
|
||||
|
||||
31 May 2017: Ralph
|
||||
- Also use global local-zones when there is a matching view that does
|
||||
not have any local-zone specified.
|
||||
|
||||
31 May 2017: Wouter
|
||||
- Fix #1273: cachedb.c doesn't compile with -Wextra.
|
||||
- If MSG_FASTOPEN gives EPIPE fallthrough to try normal tcp write.
|
||||
|
||||
30 May 2017: Ralph
|
||||
- Fix #1269: inconsistent use of built-in local zones with views.
|
||||
- Add defaults for new local-zone trees added to views using
|
||||
unbound-control.
|
||||
|
||||
30 May 2017: Wouter
|
||||
- Support for openssl EVP_DigestVerify.
|
||||
- Support for the ED25519 algorithm with openssl (from openssl 1.1.1).
|
||||
|
||||
29 May 2017: Wouter
|
||||
- Fix assertion for low buffer size and big edns payload when worker
|
||||
overrides udpsize.
|
||||
|
||||
26 May 2017: Ralph
|
||||
- Added redirect-bogus.patch to contrib directory.
|
||||
|
||||
26 May 2017: Wouter
|
||||
- Fix #1270: unitauth.c doesn't compile with higher warning level
|
||||
and optimization
|
||||
- exec_prefix is by default equal to prefix.
|
||||
- printout localzone for duplicate local-zone warnings.
|
||||
|
||||
24 May 2017: Wouter
|
||||
- authzone cname chain, no rrset duplicates, wildcard doesn't change
|
||||
rrsets added for cname chain.
|
||||
|
||||
23 May 2017: Wouter
|
||||
- first services/authzone check in, it compiles and reads and writes
|
||||
zonefiles.
|
||||
- iana portlist update
|
||||
|
||||
22 May 2017: Wouter
|
||||
- Fix #1268: SIGSEGV after log_reopen.
|
||||
|
||||
18 May 2017: Wouter
|
||||
- Fix #1265 to use /bin/kill.
|
||||
- Fix #1267: Libunbound validator/val_secalgo.c uses obsolete APIs,
|
||||
and compatibility with BoringSSL.
|
||||
|
||||
17 May 2017: Wouter
|
||||
- Fix #1265: contrib/unbound.service contains hardcoded path.
|
||||
|
||||
17 May 2017: George
|
||||
- Use qstate's region for IPSECKEY rrset (ipsecmod).
|
||||
|
||||
16 May 2017: George
|
||||
- Implemented opportunistic IPsec support module (ipsecmod).
|
||||
- Some whitespace fixup.
|
||||
|
||||
16 May 2017: Wouter
|
||||
- updated dependencies in the makefile.
|
||||
- document trust-anchor-signaling in example config file.
|
||||
- updated configure, dependencies and flex output.
|
||||
- better module memory lookup, fix of unbound-control shm names for
|
||||
module memory printout of statistics.
|
||||
- Fix type AVC sldns rrdef.
|
||||
|
||||
12 May 2017: Wouter
|
||||
- Adjust servfail by iterator to not store in cache when serve-expired
|
||||
is enabled, to avoid overwriting useful information there.
|
||||
- Fix queries for nameservers under a stub leaking to the internet.
|
||||
|
||||
9 May 2017: Ralph
|
||||
- Add 'c' to getopt() in testbound.
|
||||
- iana portlist update
|
||||
|
||||
8 May 2017: Wouter
|
||||
- Fix tcp-mss failure printout text.
|
||||
- Set SO_REUSEADDR on outgoing tcp connections to fix the bind before
|
||||
connect limited tcp connections. With the option tcp connections
|
||||
can share the same source port (for different destinations).
|
||||
|
||||
2 May 2017: Ralph
|
||||
- Added mesh_add_sub to add detached mesh entries.
|
||||
- Use mesh_add_sub for key tag signaling query.
|
||||
|
||||
2 May 2017: Wouter
|
||||
- Added test for leak of stub information.
|
||||
- Fix sldns wire2str printout of RR type CAA tags.
|
||||
- Fix sldns int16_data parse.
|
||||
- Fix sldns parse and printout of TSIG RRs.
|
||||
- sldns SMIMEA and AVC definitions, same as getdns definitions.
|
||||
|
||||
1 May 2017: Wouter
|
||||
- Fix #1259: "--disable-ecdsa" argument overwritten
|
||||
by "#ifdef SHA256_DIGEST_LENGTH@daemon/remote.c".
|
||||
- iana portlist update
|
||||
- Fix #1258: Windows 10 X64 unbound 1.6.2 service will not start.
|
||||
and fix that 64bit getting installed in C:\Program Files (x86).
|
||||
|
||||
26 April 2017: Ralph
|
||||
- Implemented trust anchor signaling using key tag query.
|
||||
|
||||
26 April 2017: Wouter
|
||||
- Based on #1257: check parse limit before t increment in sldns RR
|
||||
string parse routine.
|
||||
|
||||
24 April 2017: Wouter
|
||||
- unbound-checkconf -o allows query of dnstap config variables.
|
||||
Also unbound-control get_option. Also for dnscrypt.
|
||||
- trunk contains 1.6.3 version number (changes from 1.6.2 back from
|
||||
when the 1.6.2rc1 tag has been created).
|
||||
|
||||
21 April 2017: Ralph
|
||||
- Fix #1254: clarify ratelimit-{for,below}-domain (from Manu Bretelle).
|
||||
- iana portlist update
|
||||
|
||||
18 April 2017: Ralph
|
||||
- Fix #1252: more indentation inconsistencies.
|
||||
- Fix #1253: unused variable in edns-subnet/addrtree.c:getbit().
|
||||
|
||||
13 April 2017: Ralph
|
||||
- Added ECS unit test (from Manu Bretelle).
|
||||
- ECS documentation fix (from Manu Bretelle).
|
||||
|
||||
13 April 2017: Wouter
|
||||
- Fix #1250: inconsistent indentation in services/listen_dnsport.c.
|
||||
- tag for 1.6.2rc1
|
||||
- (for 1.6.3:) unbound.h exports the shm stats structures. They use
|
||||
type long long and no ifdefs, and ub_ before the typenames.
|
||||
|
||||
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. -- 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.
|
||||
|
||||
10 February 2017: Wouter
|
||||
- Fix pythonmod for typedef changes.
|
||||
- Fix dnstap for warning of set but not used.
|
||||
- tag 1.6.1rc2.
|
||||
|
||||
9 February 2017: Wouter
|
||||
- tag 1.6.1rc1.
|
||||
|
||||
8 February 2017: Wouter
|
||||
- Fix for type name change and fix warning on windows compile.
|
||||
|
||||
7 February 2017: Wouter
|
||||
- Include root trust anchor id 20326 in unbound-anchor.
|
||||
|
||||
6 February 2017: Wouter
|
||||
- Fix compile on solaris of the fix to use $host detect.
|
||||
|
||||
4 February 2017: Wouter
|
||||
- fix root_anchor test for updated icannbundle.pem lower certificates.
|
||||
|
||||
26 January 2017: Wouter
|
||||
- Fix 1211: Fix can't enable interface-automatic if no IPv6 with
|
||||
more helpful error message.
|
||||
|
||||
20 January 2017: Wouter
|
||||
- Increase MAX_MODULE to 16.
|
||||
|
||||
19 January 2017: Wouter
|
||||
- Fix to Rename ub_callback_t to ub_callback_type, because POSIX
|
||||
reserves _t typedefs.
|
||||
- Fix to rename internally used types from _t to _type, because _t
|
||||
type names are reserved by POSIX.
|
||||
- iana portlist update
|
||||
|
||||
12 January 2017: Wouter
|
||||
- Fix to also block meta types 128 through to 248 with formerr.
|
||||
- Fix #1206: Some view-related commands are missing from 'unbound-control -h'
|
||||
|
||||
9 January 2017: Wouter
|
||||
- Fix #1202: Fix code comment that packed_rrset_data is not always
|
||||
'packed'.
|
||||
|
||||
6 January 2017: Wouter
|
||||
- Fix #1201: Fix missing unlock in answer_from_cache error condition.
|
||||
|
||||
5 January 2017: Wouter
|
||||
- Fix to return formerr for queries for meta-types, to avoid
|
||||
packet amplification if this meta-type is sent on to upstream.
|
||||
- Fix #1184: Log DNS replies. This includes the same logging
|
||||
information that DNS queries and response code and response size,
|
||||
patch from Larissa Feng.
|
||||
- Fix #1187: Source IP rate limiting, patch from Larissa Feng.
|
||||
|
||||
3 January 2017: Wouter
|
||||
- configure --enable-systemd and lets unbound use systemd sockets if
|
||||
you enable use-systemd: yes in unbound.conf.
|
||||
Also there are contrib/unbound.socket and contrib/unbound.service:
|
||||
systemd files for unbound, install them in /usr/lib/systemd/system.
|
||||
Contributed by Sami Kerola and Pavel Odintsov.
|
||||
- Fix reload chdir failure when also chrooted to that directory.
|
||||
|
||||
2 January 2017: Wouter
|
||||
- Fix #1194: Cross build fails when $host isn't `uname` for getentropy.
|
||||
|
||||
23 December 2016: Ralph
|
||||
- Fix #1190: Do not echo back EDNS options in local-zone error response.
|
||||
- iana portlist update
|
||||
|
||||
21 December 2016: Ralph
|
||||
- Fix #1188: Unresolved symbol 'fake_dsa' in libunbound.so when built
|
||||
with Nettle
|
||||
|
||||
19 December 2016: Ralph
|
||||
- Fix #1191: remove comment about view deletion.
|
||||
|
||||
15 December 2016: Wouter
|
||||
- iana portlist update
|
||||
- 64bit is default for windows builds.
|
||||
- Fix inet_ntop and inet_pton warnings in windows compile.
|
||||
|
||||
14 December 2016: Wouter
|
||||
- Fix #1178: attempt to fix setup error at end, pop result values
|
||||
at end of install.
|
||||
|
||||
13 December 2016: Wouter
|
||||
- Fix #1182: Fix Resource leak (socket), at startup.
|
||||
- Fix unbound-control and ipv6 only.
|
||||
|
||||
9 December 2016: Wouter
|
||||
- Fix #1176: stack size too small for Alpine Linux.
|
||||
|
||||
8 December 2016: Wouter
|
||||
- Fix downcast warnings from visual studio in sldns code.
|
||||
- tag 1.6.0rc1 which became 1.6.0 on 15 dec, and trunk is 1.6.1.
|
||||
|
||||
7 December 2016: Ralph
|
||||
- Add DSA support for OpenSSL 1.1.0
|
||||
|
||||
Binary file not shown.
@@ -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
|
||||
|
||||
@@ -200,7 +208,11 @@ server:
|
||||
# Default is 0, system default MSS.
|
||||
# outgoing-tcp-mss: 0
|
||||
|
||||
# Use systemd socket activation for UDP, TCP, and control sockets.
|
||||
# use-systemd: no
|
||||
|
||||
# Detach from the terminal, run in background, "yes" or "no".
|
||||
# Set the value to "no" when unbound runs as systemd service.
|
||||
# do-daemonize: yes
|
||||
|
||||
# control which clients are allowed to make (recursive) queries
|
||||
@@ -288,6 +300,10 @@ server:
|
||||
# print one line with time, IP, name, type, class for every query.
|
||||
# log-queries: no
|
||||
|
||||
# print one line per reply, with time, IP, name, type, class, rcode,
|
||||
# timetoresolve, fromcache and responsesize.
|
||||
# log-replies: no
|
||||
|
||||
# the pid file. Can be an absolute path outside of chroot/work dir.
|
||||
# pidfile: "@UNBOUND_PIDFILE@"
|
||||
|
||||
@@ -300,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: ""
|
||||
@@ -429,6 +448,9 @@ server:
|
||||
# and under the terms of our LICENSE (see that file in the source).
|
||||
# auto-trust-anchor-file: "@UNBOUND_ROOTKEY_FILE@"
|
||||
|
||||
# trust anchor signaling sends a RFC8145 key tag query after priming.
|
||||
# trust-anchor-signaling: no
|
||||
|
||||
# File with DLV trusted keys. Same format as trust-anchor-file.
|
||||
# There can be only one DLV configured, it is trusted from root down.
|
||||
# DLV is going to be decommissioned. Please do not use it any more.
|
||||
@@ -666,6 +688,48 @@ server:
|
||||
# can give this multiple times, the name closest to the zone is used.
|
||||
# ratelimit-below-domain: com 1000
|
||||
|
||||
# global query ratelimit for all ip addresses.
|
||||
# feature is experimental.
|
||||
# if 0(default) it is disabled, otherwise states qps allowed per ip address
|
||||
# ip-ratelimit: 0
|
||||
|
||||
# ip ratelimits are tracked in a cache, size in bytes of cache (or k,m).
|
||||
# ip-ratelimit-size: 4m
|
||||
# ip ratelimit cache slabs, reduces lock contention if equal to cpucount.
|
||||
# ip-ratelimit-slabs: 4
|
||||
|
||||
# 0 blocks when ip is ratelimited, otherwise let 1/xth traffic through
|
||||
# ip-ratelimit-factor: 10
|
||||
|
||||
# Specific options for ipsecmod. unbound needs to be configured with
|
||||
# --enable-ipsecmod for these to take effect.
|
||||
#
|
||||
# Enable or disable ipsecmod (it still needs to be defined in
|
||||
# module-config above). Can be used when ipsecmod needs to be
|
||||
# enabled/disabled via remote-control(below).
|
||||
# ipsecmod-enabled: yes
|
||||
#
|
||||
# Path to executable external hook. It must be defined when ipsecmod is
|
||||
# listed in module-config (above).
|
||||
# ipsecmod-hook: "./my_executable"
|
||||
#
|
||||
# When enabled unbound will reply with SERVFAIL if the return value of
|
||||
# the ipsecmod-hook is not 0.
|
||||
# ipsecmod-strict: no
|
||||
#
|
||||
# Maximum time to live (TTL) for cached A/AAAA records with IPSECKEY.
|
||||
# ipsecmod-max-ttl: 3600
|
||||
#
|
||||
# Reply with A/AAAA even if the relevant IPSECKEY is bogus. Mainly used for
|
||||
# testing.
|
||||
# ipsecmod-ignore-bogus: no
|
||||
#
|
||||
# Domains for which ipsecmod will be triggered. If not defined (default)
|
||||
# all domains are treated as being whitelisted.
|
||||
# ipsecmod-whitelist: "example.com"
|
||||
# ipsecmod-whitelist: "nlnetlabs.nl"
|
||||
|
||||
|
||||
# Python config section. To enable:
|
||||
# o use --with-pythonmodule to configure before compiling.
|
||||
# o list python in the module-config string (above) to enable.
|
||||
@@ -749,7 +813,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
|
||||
|
||||
+2
-2
@@ -12,7 +12,7 @@
|
||||
.B unbound.h,
|
||||
.B ub_ctx,
|
||||
.B ub_result,
|
||||
.B ub_callback_t,
|
||||
.B ub_callback_type,
|
||||
.B ub_ctx_create,
|
||||
.B ub_ctx_delete,
|
||||
.B ub_ctx_set_option,
|
||||
@@ -120,7 +120,7 @@
|
||||
.br
|
||||
\fIint\fR rrtype, \fIint\fR rrclass, \fIvoid*\fR mydata,
|
||||
.br
|
||||
\fIub_callback_t\fR callback, \fIint*\fR async_id);
|
||||
\fIub_callback_type\fR callback, \fIint*\fR async_id);
|
||||
.LP
|
||||
\fIint\fR
|
||||
\fBub_cancel\fR(\fIstruct ub_ctx*\fR ctx, \fIint\fR async_id);
|
||||
|
||||
@@ -194,7 +194,7 @@ harden\-referral\-path, prefetch, prefetch\-key, log\-queries,
|
||||
hide\-identity, hide\-version, identity, version, val\-log\-level,
|
||||
val\-log\-squelch, ignore\-cd\-flag, add\-holddown, del\-holddown,
|
||||
keep\-missing, tcp\-upstream, ssl\-upstream, max\-udp\-size, ratelimit,
|
||||
cache\-max\-ttl, cache\-min\-ttl, cache\-max\-negative\-ttl.
|
||||
ip\-ratelimit, cache\-max\-ttl, cache\-min\-ttl, cache\-max\-negative\-ttl.
|
||||
.TP
|
||||
.B get_option \fIopt
|
||||
Get the value of the option. Give the option name without a trailing ':'.
|
||||
@@ -280,6 +280,12 @@ just the ratelimited domains, with their estimated qps. The ratelimited
|
||||
domains return an error for uncached (new) queries, but cached queries work
|
||||
as normal.
|
||||
.TP
|
||||
.B ip_ratelimit_list \fR[\fI+a\fR]
|
||||
List the ip addresses that are ratelimited. Printed one per line with current
|
||||
estimated qps and qps limit from config. With +a it prints all ips, not
|
||||
just the ratelimited ips, with their estimated qps. The ratelimited
|
||||
ips are dropped before checking the cache.
|
||||
.TP
|
||||
.B view_list_local_zones \fIview\fR
|
||||
\fIlist_local_zones\fR for given view.
|
||||
.TP
|
||||
@@ -289,6 +295,9 @@ as normal.
|
||||
.B view_local_zone_remove \fIview\fR \fIname
|
||||
\fIlocal_zone_remove\fR for given view.
|
||||
.TP
|
||||
.B view_list_local_data \fIview\fR
|
||||
\fIlist_local_data\fR for given view.
|
||||
.TP
|
||||
.B view_local_data \fIview\fR \fIRR data...
|
||||
\fIlocal_data\fR for given view.
|
||||
.TP
|
||||
@@ -319,6 +328,9 @@ The \fIstats\fR command shows a number of statistic counters.
|
||||
.I threadX.num.queries
|
||||
number of queries received by thread
|
||||
.TP
|
||||
.I threadX.num.queries_ip_ratelimited
|
||||
number of queries rate limited by thread
|
||||
.TP
|
||||
.I threadX.num.cachehits
|
||||
number of queries that were successfully answered using a cache lookup
|
||||
.TP
|
||||
|
||||
+379
-168
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,532 @@
|
||||
/*
|
||||
* 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);
|
||||
(void)addrlen;
|
||||
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);
|
||||
}
|
||||
@@ -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 */
|
||||
@@ -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 */
|
||||
@@ -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 */
|
||||
@@ -0,0 +1,207 @@
|
||||
/*
|
||||
* 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"
|
||||
#include "sldns/str2wire.h"
|
||||
#include "util/data/dname.h"
|
||||
|
||||
struct ecs_whitelist*
|
||||
ecs_whitelist_create(void)
|
||||
{
|
||||
struct ecs_whitelist* whitelist =
|
||||
(struct ecs_whitelist*)calloc(1,
|
||||
sizeof(struct ecs_whitelist));
|
||||
if(!whitelist)
|
||||
return NULL;
|
||||
whitelist->region = regional_create();
|
||||
if(!whitelist->region) {
|
||||
ecs_whitelist_delete(whitelist);
|
||||
return NULL;
|
||||
}
|
||||
return whitelist;
|
||||
}
|
||||
|
||||
void
|
||||
ecs_whitelist_delete(struct ecs_whitelist* whitelist)
|
||||
{
|
||||
if(!whitelist)
|
||||
return;
|
||||
regional_destroy(whitelist->region);
|
||||
free(whitelist);
|
||||
}
|
||||
|
||||
/** insert new address into whitelist structure */
|
||||
static int
|
||||
upstream_insert(struct ecs_whitelist* whitelist,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen, int net)
|
||||
{
|
||||
struct addr_tree_node* node = (struct addr_tree_node*)regional_alloc(
|
||||
whitelist->region, sizeof(*node));
|
||||
if(!node)
|
||||
return 0;
|
||||
if(!addr_tree_insert(&whitelist->upstream, 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 ecs_whitelist* whitelist, 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(whitelist, &addr, addrlen, net)) {
|
||||
log_err("out of memory");
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** read client_subnet config */
|
||||
static int
|
||||
read_upstream(struct ecs_whitelist* whitelist, 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(whitelist, p->str))
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** read client_subnet_zone config */
|
||||
static int
|
||||
read_names(struct ecs_whitelist* whitelist, struct config_file* cfg)
|
||||
{
|
||||
/* parse names, report errors, insert into tree */
|
||||
struct config_strlist* p;
|
||||
struct name_tree_node* n;
|
||||
uint8_t* nm, *nmr;
|
||||
size_t nm_len;
|
||||
int nm_labs;
|
||||
|
||||
for(p = cfg->client_subnet_zone; p; p = p->next) {
|
||||
log_assert(p->str);
|
||||
nm = sldns_str2wire_dname(p->str, &nm_len);
|
||||
if(!nm) {
|
||||
log_err("cannot parse client-subnet-zone: %s", p->str);
|
||||
return 0;
|
||||
}
|
||||
nm_labs = dname_count_size_labels(nm, &nm_len);
|
||||
nmr = (uint8_t*)regional_alloc_init(whitelist->region, nm,
|
||||
nm_len);
|
||||
free(nm);
|
||||
if(!nmr) {
|
||||
log_err("out of memory");
|
||||
return 0;
|
||||
}
|
||||
n = (struct name_tree_node*)regional_alloc(whitelist->region,
|
||||
sizeof(*n));
|
||||
if(!n) {
|
||||
log_err("out of memory");
|
||||
return 0;
|
||||
}
|
||||
if(!name_tree_insert(&whitelist->dname, n, nmr, nm_len, nm_labs,
|
||||
LDNS_RR_CLASS_IN)) {
|
||||
verbose(VERB_QUERY, "ignoring duplicate "
|
||||
"client-subnet-zone: %s", p->str);
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
ecs_whitelist_apply_cfg(struct ecs_whitelist* whitelist,
|
||||
struct config_file* cfg)
|
||||
{
|
||||
regional_free_all(whitelist->region);
|
||||
addr_tree_init(&whitelist->upstream);
|
||||
name_tree_init(&whitelist->dname);
|
||||
if(!read_upstream(whitelist, cfg))
|
||||
return 0;
|
||||
if(!read_names(whitelist, cfg))
|
||||
return 0;
|
||||
addr_tree_init_parents(&whitelist->upstream);
|
||||
name_tree_init_parents(&whitelist->dname);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
ecs_is_whitelisted(struct ecs_whitelist* whitelist,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* qname,
|
||||
size_t qname_len, uint16_t qclass)
|
||||
{
|
||||
int labs;
|
||||
if(addr_tree_lookup(&whitelist->upstream, addr, addrlen))
|
||||
return 1;
|
||||
/* Not in upstream whitelist, check dname whitelist. */
|
||||
labs = dname_count_labels(qname);
|
||||
return name_tree_lookup(&whitelist->dname, qname, qname_len, labs,
|
||||
qclass) != NULL;
|
||||
}
|
||||
|
||||
size_t
|
||||
ecs_whitelist_get_mem(struct ecs_whitelist* whitelist)
|
||||
{
|
||||
if(!whitelist) return 0;
|
||||
return sizeof(*whitelist) + regional_get_mem(whitelist->region);
|
||||
}
|
||||
|
||||
#endif /* CLIENT_SUBNET */
|
||||
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
* 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 and domain names 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;
|
||||
|
||||
/**
|
||||
* ecs_whitelist structure
|
||||
*/
|
||||
struct ecs_whitelist {
|
||||
/** 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 upstream;
|
||||
/**
|
||||
* Tree of domain names for which Unbound will append an ECS option.
|
||||
* rbtree of struct name_tree_node.
|
||||
*/
|
||||
rbtree_type dname;
|
||||
};
|
||||
|
||||
/**
|
||||
* Create ecs_whitelist structure
|
||||
* @return new structure or NULL on error.
|
||||
*/
|
||||
struct ecs_whitelist* ecs_whitelist_create(void);
|
||||
|
||||
/**
|
||||
* Delete ecs_whitelist structure.
|
||||
* @param whitelist: to delete.
|
||||
*/
|
||||
void ecs_whitelist_delete(struct ecs_whitelist* whitelist);
|
||||
|
||||
/**
|
||||
* Process ecs_whitelist config.
|
||||
* @param whitelist: where to store.
|
||||
* @param cfg: config options.
|
||||
* @return 0 on error.
|
||||
*/
|
||||
int ecs_whitelist_apply_cfg(struct ecs_whitelist* whitelist,
|
||||
struct config_file* cfg);
|
||||
|
||||
/**
|
||||
* See if an address or domain is whitelisted.
|
||||
* @param whitelist: structure for address storage.
|
||||
* @param addr: address to check
|
||||
* @param addrlen: length of addr.
|
||||
* @param qname: dname in query
|
||||
* @param qname_len: length of dname
|
||||
* @param qclass: class in query
|
||||
* @return: true if the address is whitelisted for subnet option.
|
||||
*/
|
||||
int ecs_is_whitelisted(struct ecs_whitelist* whitelist,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* qname,
|
||||
size_t qname_len, uint16_t qclass);
|
||||
|
||||
/**
|
||||
* Get memory used by ecs_whitelist structure.
|
||||
* @param whitelist: structure for address storage.
|
||||
* @return bytes in use.
|
||||
*/
|
||||
size_t ecs_whitelist_get_mem(struct ecs_whitelist* whitelist);
|
||||
|
||||
#endif /* EDNSSUBNET_WHITELIST_H */
|
||||
@@ -0,0 +1,810 @@
|
||||
/*
|
||||
* 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* 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) ||
|
||||
ecs_is_whitelisted(sn_env->whitelist,
|
||||
addr, addrlen, qinfo->qname, qinfo->qname_len,
|
||||
qinfo->qclass))) {
|
||||
/* 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->whitelist = ecs_whitelist_create();
|
||||
if(!sn_env->whitelist ||
|
||||
!ecs_whitelist_apply_cfg(sn_env->whitelist, 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");
|
||||
ecs_whitelist_delete(sn_env->whitelist);
|
||||
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);
|
||||
inplace_cb_delete(env, inplace_cb_query_response, id);
|
||||
ecs_whitelist_delete(sn_env->whitelist);
|
||||
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) +
|
||||
ecs_whitelist_get_mem(sn_env->whitelist);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 */
|
||||
@@ -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 ecs_whitelist* whitelist;
|
||||
/** 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 */
|
||||
@@ -0,0 +1,158 @@
|
||||
/*
|
||||
* ipsecmod/ipsecmod-whitelist.h - White listed domains for the ipsecmod to
|
||||
* operate on.
|
||||
*
|
||||
* Copyright (c) 2017, 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 domains for ipsecmod.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifdef USE_IPSECMOD
|
||||
#include "ipsecmod/ipsecmod.h"
|
||||
#include "ipsecmod/ipsecmod-whitelist.h"
|
||||
#include "util/regional.h"
|
||||
#include "util/log.h"
|
||||
#include "util/config_file.h"
|
||||
#include "util/rbtree.h"
|
||||
#include "util/data/dname.h"
|
||||
#include "util/storage/dnstree.h"
|
||||
#include "sldns/str2wire.h"
|
||||
|
||||
/** Apply ipsecmod-whitelist string. */
|
||||
static int
|
||||
whitelist_str_cfg(rbtree_type* whitelist, const char* name)
|
||||
{
|
||||
struct name_tree_node* n;
|
||||
size_t len;
|
||||
uint8_t* nm = sldns_str2wire_dname(name, &len);
|
||||
if(!nm) {
|
||||
log_err("ipsecmod: could not parse %s for whitelist.", name);
|
||||
return 0;
|
||||
}
|
||||
n = (struct name_tree_node*)calloc(1, sizeof(*n));
|
||||
if(!n) {
|
||||
log_err("ipsecmod: out of memory while creating whitelist.");
|
||||
free(nm);
|
||||
return 0;
|
||||
}
|
||||
n->node.key = n;
|
||||
n->name = nm;
|
||||
n->len = len;
|
||||
n->labs = dname_count_labels(nm);
|
||||
n->dclass = LDNS_RR_CLASS_IN;
|
||||
if(!name_tree_insert(whitelist, n, nm, len, n->labs, n->dclass)) {
|
||||
/* duplicate element ignored, idempotent */
|
||||
free(n->name);
|
||||
free(n);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** Read ipsecmod-whitelist config. */
|
||||
static int
|
||||
read_whitelist(rbtree_type* whitelist, struct config_file* cfg)
|
||||
{
|
||||
struct config_strlist* p;
|
||||
for(p = cfg->ipsecmod_whitelist; p; p = p->next) {
|
||||
log_assert(p->str);
|
||||
if(!whitelist_str_cfg(whitelist, p->str))
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
ipsecmod_whitelist_apply_cfg(struct ipsecmod_env* ie,
|
||||
struct config_file* cfg)
|
||||
{
|
||||
ie->whitelist = rbtree_create(name_tree_compare);
|
||||
if(!read_whitelist(ie->whitelist, cfg))
|
||||
return 0;
|
||||
name_tree_init_parents(ie->whitelist);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** Delete ipsecmod_env->whitelist element. */
|
||||
static void
|
||||
whitelist_free(struct rbnode_type* n, void* ATTR_UNUSED(d))
|
||||
{
|
||||
if(n) {
|
||||
free(((struct name_tree_node*)n)->name);
|
||||
free(n);
|
||||
}
|
||||
}
|
||||
|
||||
/** Get memory usage of ipsecmod_env->whitelist element. */
|
||||
static void
|
||||
whitelist_get_mem(struct rbnode_type* n, void* arg)
|
||||
{
|
||||
struct name_tree_node* node = (struct name_tree_node*)n;
|
||||
size_t* size = (size_t*) arg;
|
||||
if(node) {
|
||||
*size += sizeof(node) + node->len;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ipsecmod_whitelist_delete(rbtree_type* whitelist)
|
||||
{
|
||||
if(whitelist) {
|
||||
traverse_postorder(whitelist, whitelist_free, NULL);
|
||||
free(whitelist);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
ipsecmod_domain_is_whitelisted(struct ipsecmod_env* ie, uint8_t* dname,
|
||||
size_t dname_len, uint16_t qclass)
|
||||
{
|
||||
if(!ie->whitelist) return 1; /* No whitelist, treat as whitelisted. */
|
||||
return name_tree_lookup(ie->whitelist, dname, dname_len,
|
||||
dname_count_labels(dname), qclass) != NULL;
|
||||
}
|
||||
|
||||
size_t
|
||||
ipsecmod_whitelist_get_mem(rbtree_type* whitelist)
|
||||
{
|
||||
size_t size = 0;
|
||||
if(whitelist) {
|
||||
traverse_postorder(whitelist, whitelist_get_mem, &size);
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
#endif /* USE_IPSECMOD */
|
||||
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* ipsecmod/ipsecmod-whitelist.h - White listed domains for the ipsecmod to
|
||||
* operate on.
|
||||
*
|
||||
* Copyright (c) 2017, 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 domains for ipsecmod.
|
||||
*/
|
||||
|
||||
#ifndef IPSECMOD_WHITELIST_H
|
||||
#define IPSECMOD_WHITELIST_H
|
||||
#include "util/storage/dnstree.h"
|
||||
|
||||
struct config_file;
|
||||
struct regional;
|
||||
|
||||
/**
|
||||
* Process ipsecmod_whitelist config.
|
||||
* @param ie: ipsecmod environment.
|
||||
* @param cfg: config options.
|
||||
* @return 0 on error.
|
||||
*/
|
||||
int ipsecmod_whitelist_apply_cfg(struct ipsecmod_env* ie,
|
||||
struct config_file* cfg);
|
||||
|
||||
/**
|
||||
* Delete the ipsecmod whitelist.
|
||||
* @param whitelist: ipsecmod whitelist.
|
||||
*/
|
||||
void ipsecmod_whitelist_delete(rbtree_type* whitelist);
|
||||
|
||||
/**
|
||||
* See if a domain is whitelisted.
|
||||
* @param ie: ipsecmod environment.
|
||||
* @param dname: domain name to check.
|
||||
* @param dname_len: length of domain name.
|
||||
* @param qclass: query CLASS.
|
||||
* @return: true if the domain is whitelisted for the ipsecmod.
|
||||
*/
|
||||
int ipsecmod_domain_is_whitelisted(struct ipsecmod_env* ie, uint8_t* dname,
|
||||
size_t dname_len, uint16_t qclass);
|
||||
|
||||
/**
|
||||
* Get memory used by ipsecmod whitelist.
|
||||
* @param whitelist: structure for domain storage.
|
||||
* @return bytes in use.
|
||||
*/
|
||||
size_t ipsecmod_whitelist_get_mem(rbtree_type* whitelist);
|
||||
|
||||
#endif /* IPSECMOD_WHITELIST_H */
|
||||
@@ -0,0 +1,515 @@
|
||||
/*
|
||||
* ipsecmod/ipsecmod.c - facilitate opportunistic IPsec module
|
||||
*
|
||||
* Copyright (c) 2017, NLnet Labs. All rights reserved.
|
||||
*
|
||||
* This software is open source.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* Neither the name of the NLNET LABS nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* This file contains a module that facilitates opportunistic IPsec. It does so
|
||||
* by also quering for the IPSECKEY for A/AAAA queries and calling a
|
||||
* configurable hook (eg. signaling an IKE daemon) before replying.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#ifdef USE_IPSECMOD
|
||||
#include "ipsecmod/ipsecmod.h"
|
||||
#include "ipsecmod/ipsecmod-whitelist.h"
|
||||
#include "util/fptr_wlist.h"
|
||||
#include "util/regional.h"
|
||||
#include "util/net_help.h"
|
||||
#include "util/config_file.h"
|
||||
#include "services/cache/dns.h"
|
||||
#include "sldns/wire2str.h"
|
||||
|
||||
/** Apply configuration to ipsecmod module 'global' state. */
|
||||
static int
|
||||
ipsecmod_apply_cfg(struct ipsecmod_env* ipsecmod_env, struct config_file* cfg)
|
||||
{
|
||||
if(!cfg->ipsecmod_hook || (cfg->ipsecmod_hook && !cfg->ipsecmod_hook[0])) {
|
||||
log_err("ipsecmod: missing ipsecmod-hook.");
|
||||
return 0;
|
||||
}
|
||||
if(cfg->ipsecmod_whitelist &&
|
||||
!ipsecmod_whitelist_apply_cfg(ipsecmod_env, cfg))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
ipsecmod_init(struct module_env* env, int id)
|
||||
{
|
||||
struct ipsecmod_env* ipsecmod_env = (struct ipsecmod_env*)calloc(1,
|
||||
sizeof(struct ipsecmod_env));
|
||||
if(!ipsecmod_env) {
|
||||
log_err("malloc failure");
|
||||
return 0;
|
||||
}
|
||||
env->modinfo[id] = (void*)ipsecmod_env;
|
||||
ipsecmod_env->whitelist = NULL;
|
||||
if(!ipsecmod_apply_cfg(ipsecmod_env, env->cfg)) {
|
||||
log_err("ipsecmod: could not apply configuration settings.");
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
ipsecmod_deinit(struct module_env* env, int id)
|
||||
{
|
||||
struct ipsecmod_env* ipsecmod_env;
|
||||
if(!env || !env->modinfo[id])
|
||||
return;
|
||||
ipsecmod_env = (struct ipsecmod_env*)env->modinfo[id];
|
||||
/* Free contents. */
|
||||
ipsecmod_whitelist_delete(ipsecmod_env->whitelist);
|
||||
free(ipsecmod_env);
|
||||
env->modinfo[id] = NULL;
|
||||
}
|
||||
|
||||
/** New query for ipsecmod. */
|
||||
static int
|
||||
ipsecmod_new(struct module_qstate* qstate, int id)
|
||||
{
|
||||
struct ipsecmod_qstate* iq = (struct ipsecmod_qstate*)regional_alloc(
|
||||
qstate->region, sizeof(struct ipsecmod_qstate));
|
||||
memset(iq, 0, sizeof(*iq));
|
||||
qstate->minfo[id] = iq;
|
||||
if(!iq)
|
||||
return 0;
|
||||
/* Initialise it. */
|
||||
iq->enabled = qstate->env->cfg->ipsecmod_enabled;
|
||||
iq->is_whitelisted = ipsecmod_domain_is_whitelisted(
|
||||
(struct ipsecmod_env*)qstate->env->modinfo[id], qstate->qinfo.qname,
|
||||
qstate->qinfo.qname_len, qstate->qinfo.qclass);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Exit module with an error status.
|
||||
* @param qstate: query state
|
||||
* @param id: module id.
|
||||
*/
|
||||
static void
|
||||
ipsecmod_error(struct module_qstate* qstate, int id)
|
||||
{
|
||||
qstate->ext_state[id] = module_error;
|
||||
qstate->return_rcode = LDNS_RCODE_SERVFAIL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a request for the IPSECKEY.
|
||||
*
|
||||
* @param qstate: query state that is the parent.
|
||||
* @param id: module id.
|
||||
* @param name: what name to query for.
|
||||
* @param namelen: length of name.
|
||||
* @param qtype: query type.
|
||||
* @param qclass: query class.
|
||||
* @param flags: additional flags, such as the CD bit (BIT_CD), or 0.
|
||||
* @return false on alloc failure.
|
||||
*/
|
||||
static int
|
||||
generate_request(struct module_qstate* qstate, int id, uint8_t* name,
|
||||
size_t namelen, uint16_t qtype, uint16_t qclass, uint16_t flags)
|
||||
{
|
||||
struct module_qstate* newq;
|
||||
struct query_info ask;
|
||||
ask.qname = name;
|
||||
ask.qname_len = namelen;
|
||||
ask.qtype = qtype;
|
||||
ask.qclass = qclass;
|
||||
ask.local_alias = NULL;
|
||||
log_query_info(VERB_ALGO, "ipsecmod: generate request", &ask);
|
||||
fptr_ok(fptr_whitelist_modenv_attach_sub(qstate->env->attach_sub));
|
||||
if(!(*qstate->env->attach_sub)(qstate, &ask,
|
||||
(uint16_t)(BIT_RD|flags), 0, 0, &newq)){
|
||||
log_err("Could not generate request: out of memory");
|
||||
return 0;
|
||||
}
|
||||
qstate->ext_state[id] = module_wait_subquery;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare the data and call the hook.
|
||||
*
|
||||
* @param qstate: query state.
|
||||
* @param iq: ipsecmod qstate.
|
||||
* @param ie: ipsecmod environment.
|
||||
* @return true on success, false otherwise.
|
||||
*/
|
||||
static int
|
||||
call_hook(struct module_qstate* qstate, struct ipsecmod_qstate* iq,
|
||||
struct ipsecmod_env* ATTR_UNUSED(ie))
|
||||
{
|
||||
size_t slen, tempdata_len, tempstring_len, i;
|
||||
char str[65535], *s, *tempstring;
|
||||
int w;
|
||||
struct ub_packed_rrset_key* rrset_key;
|
||||
struct packed_rrset_data* rrset_data;
|
||||
uint8_t *tempdata;
|
||||
|
||||
/* Check if a shell is available */
|
||||
if(system(NULL) == 0) {
|
||||
log_err("ipsecmod: no shell available for ipsecmod-hook");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Zero the buffer. */
|
||||
s = str;
|
||||
slen = sizeof(str);
|
||||
memset(s, 0, slen);
|
||||
|
||||
/* Copy the hook into the buffer. */
|
||||
sldns_str_print(&s, &slen, "%s", qstate->env->cfg->ipsecmod_hook);
|
||||
/* Put space into the buffer. */
|
||||
sldns_str_print(&s, &slen, " ");
|
||||
/* Copy the qname into the buffer. */
|
||||
tempstring = sldns_wire2str_dname(qstate->qinfo.qname,
|
||||
qstate->qinfo.qname_len);
|
||||
if(!tempstring) {
|
||||
log_err("ipsecmod: out of memory when calling the hook");
|
||||
return 0;
|
||||
}
|
||||
sldns_str_print(&s, &slen, "\"%s\"", tempstring);
|
||||
free(tempstring);
|
||||
/* Put space into the buffer. */
|
||||
sldns_str_print(&s, &slen, " ");
|
||||
/* Copy the IPSECKEY TTL into the buffer. */
|
||||
rrset_data = (struct packed_rrset_data*)iq->ipseckey_rrset->entry.data;
|
||||
sldns_str_print(&s, &slen, "\"%ld\"", (long)rrset_data->ttl);
|
||||
/* Put space into the buffer. */
|
||||
sldns_str_print(&s, &slen, " ");
|
||||
/* Copy the A/AAAA record(s) into the buffer. Start and end this section
|
||||
* with a double quote. */
|
||||
rrset_key = reply_find_answer_rrset(&qstate->return_msg->qinfo,
|
||||
qstate->return_msg->rep);
|
||||
rrset_data = (struct packed_rrset_data*)rrset_key->entry.data;
|
||||
sldns_str_print(&s, &slen, "\"");
|
||||
for(i=0; i<rrset_data->count; i++) {
|
||||
if(i > 0) {
|
||||
/* Put space into the buffer. */
|
||||
sldns_str_print(&s, &slen, " ");
|
||||
}
|
||||
/* Ignore the first two bytes, they are the rr_data len. */
|
||||
w = sldns_wire2str_rdata_buf(rrset_data->rr_data[i] + 2,
|
||||
rrset_data->rr_len[i] - 2, s, slen, qstate->qinfo.qtype);
|
||||
if(w < 0) {
|
||||
/* Error in printout. */
|
||||
return -1;
|
||||
} else if((size_t)w >= slen) {
|
||||
s = NULL; /* We do not want str to point outside of buffer. */
|
||||
slen = 0;
|
||||
return -1;
|
||||
} else {
|
||||
s += w;
|
||||
slen -= w;
|
||||
}
|
||||
}
|
||||
sldns_str_print(&s, &slen, "\"");
|
||||
/* Put space into the buffer. */
|
||||
sldns_str_print(&s, &slen, " ");
|
||||
/* Copy the IPSECKEY record(s) into the buffer. Start and end this section
|
||||
* with a double quote. */
|
||||
sldns_str_print(&s, &slen, "\"");
|
||||
rrset_data = (struct packed_rrset_data*)iq->ipseckey_rrset->entry.data;
|
||||
for(i=0; i<rrset_data->count; i++) {
|
||||
if(i > 0) {
|
||||
/* Put space into the buffer. */
|
||||
sldns_str_print(&s, &slen, " ");
|
||||
}
|
||||
/* Ignore the first two bytes, they are the rr_data len. */
|
||||
tempdata = rrset_data->rr_data[i] + 2;
|
||||
tempdata_len = rrset_data->rr_len[i] - 2;
|
||||
/* Save the buffer pointers. */
|
||||
tempstring = s; tempstring_len = slen;
|
||||
w = sldns_wire2str_ipseckey_scan(&tempdata, &tempdata_len, &s, &slen,
|
||||
NULL, 0);
|
||||
/* There was an error when parsing the IPSECKEY; reset the buffer
|
||||
* pointers to their previous values. */
|
||||
if(w == -1){
|
||||
s = tempstring; slen = tempstring_len;
|
||||
}
|
||||
}
|
||||
sldns_str_print(&s, &slen, "\"");
|
||||
verbose(VERB_ALGO, "ipsecmod: hook command: '%s'", str);
|
||||
/* ipsecmod-hook should return 0 on success. */
|
||||
if(system(str) != 0)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle an ipsecmod module event with a query
|
||||
* @param qstate: query state (from the mesh), passed between modules.
|
||||
* contains qstate->env module environment with global caches and so on.
|
||||
* @param iq: query state specific for this module. per-query.
|
||||
* @param ie: environment specific for this module. global.
|
||||
* @param id: module id.
|
||||
*/
|
||||
static void
|
||||
ipsecmod_handle_query(struct module_qstate* qstate,
|
||||
struct ipsecmod_qstate* iq, struct ipsecmod_env* ie, int id)
|
||||
{
|
||||
struct ub_packed_rrset_key* rrset_key;
|
||||
struct packed_rrset_data* rrset_data;
|
||||
size_t i;
|
||||
/* Pass to next module if we are not enabled and whitelisted. */
|
||||
if(!(iq->enabled && iq->is_whitelisted)) {
|
||||
qstate->ext_state[id] = module_wait_module;
|
||||
return;
|
||||
}
|
||||
/* New query, check if the query is for an A/AAAA record and disable
|
||||
* caching for other modules. */
|
||||
if(!iq->ipseckey_done) {
|
||||
if(qstate->qinfo.qtype == LDNS_RR_TYPE_A ||
|
||||
qstate->qinfo.qtype == LDNS_RR_TYPE_AAAA) {
|
||||
char type[16];
|
||||
sldns_wire2str_type_buf(qstate->qinfo.qtype, type,
|
||||
sizeof(type));
|
||||
verbose(VERB_ALGO, "ipsecmod: query for %s; engaging",
|
||||
type);
|
||||
qstate->no_cache_store = 1;
|
||||
}
|
||||
/* Pass request to next module. */
|
||||
qstate->ext_state[id] = module_wait_module;
|
||||
return;
|
||||
}
|
||||
/* IPSECKEY subquery is finished. */
|
||||
/* We have an IPSECKEY answer. */
|
||||
if(iq->ipseckey_rrset) {
|
||||
rrset_data = (struct packed_rrset_data*)iq->ipseckey_rrset->entry.data;
|
||||
if(rrset_data) {
|
||||
/* If bogus return SERVFAIL. */
|
||||
if(!qstate->env->cfg->ipsecmod_ignore_bogus &&
|
||||
rrset_data->security == sec_status_bogus) {
|
||||
log_err("ipsecmod: bogus IPSECKEY");
|
||||
ipsecmod_error(qstate, id);
|
||||
return;
|
||||
}
|
||||
/* We have a valid IPSECKEY reply, call hook. */
|
||||
if(!call_hook(qstate, iq, ie) &&
|
||||
qstate->env->cfg->ipsecmod_strict) {
|
||||
log_err("ipsecmod: ipsecmod-hook failed");
|
||||
ipsecmod_error(qstate, id);
|
||||
return;
|
||||
}
|
||||
/* Make sure the A/AAAA's TTL is equal/less than the
|
||||
* ipsecmod_max_ttl. */
|
||||
rrset_key = reply_find_answer_rrset(&qstate->return_msg->qinfo,
|
||||
qstate->return_msg->rep);
|
||||
rrset_data = (struct packed_rrset_data*)rrset_key->entry.data;
|
||||
if(rrset_data->ttl > (time_t)qstate->env->cfg->ipsecmod_max_ttl) {
|
||||
/* Update TTL for rrset to fixed value. */
|
||||
rrset_data->ttl = qstate->env->cfg->ipsecmod_max_ttl;
|
||||
for(i=0; i<rrset_data->count+rrset_data->rrsig_count; i++)
|
||||
rrset_data->rr_ttl[i] = qstate->env->cfg->ipsecmod_max_ttl;
|
||||
/* Also update reply_info's TTL */
|
||||
if(qstate->return_msg->rep->ttl > (time_t)qstate->env->cfg->ipsecmod_max_ttl) {
|
||||
qstate->return_msg->rep->ttl =
|
||||
qstate->env->cfg->ipsecmod_max_ttl;
|
||||
qstate->return_msg->rep->prefetch_ttl = PREFETCH_TTL_CALC(
|
||||
qstate->return_msg->rep->ttl);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Store A/AAAA in cache. */
|
||||
if(!dns_cache_store(qstate->env, &qstate->qinfo,
|
||||
qstate->return_msg->rep, 0, qstate->prefetch_leeway,
|
||||
0, qstate->region, qstate->query_flags)) {
|
||||
log_err("ipsecmod: out of memory caching record");
|
||||
}
|
||||
qstate->ext_state[id] = module_finished;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle an ipsecmod module event with a response from the iterator.
|
||||
* @param qstate: query state (from the mesh), passed between modules.
|
||||
* contains qstate->env module environment with global caches and so on.
|
||||
* @param iq: query state specific for this module. per-query.
|
||||
* @param ie: environment specific for this module. global.
|
||||
* @param id: module id.
|
||||
*/
|
||||
static void
|
||||
ipsecmod_handle_response(struct module_qstate* qstate,
|
||||
struct ipsecmod_qstate* ATTR_UNUSED(iq),
|
||||
struct ipsecmod_env* ATTR_UNUSED(ie), int id)
|
||||
{
|
||||
/* Pass to previous module if we are not enabled and whitelisted. */
|
||||
if(!(iq->enabled && iq->is_whitelisted)) {
|
||||
qstate->ext_state[id] = module_finished;
|
||||
return;
|
||||
}
|
||||
/* check if the response is for an A/AAAA query. */
|
||||
if((qstate->qinfo.qtype == LDNS_RR_TYPE_A ||
|
||||
qstate->qinfo.qtype == LDNS_RR_TYPE_AAAA) &&
|
||||
/* check that we had an answer for the A/AAAA query. */
|
||||
qstate->return_msg &&
|
||||
reply_find_answer_rrset(&qstate->return_msg->qinfo,
|
||||
qstate->return_msg->rep) &&
|
||||
/* check that another module didn't SERVFAIL. */
|
||||
qstate->return_rcode == LDNS_RCODE_NOERROR) {
|
||||
char type[16];
|
||||
sldns_wire2str_type_buf(qstate->qinfo.qtype, type,
|
||||
sizeof(type));
|
||||
verbose(VERB_ALGO, "ipsecmod: response for %s; generating IPSECKEY "
|
||||
"subquery", type);
|
||||
/* generate an IPSECKEY query. */
|
||||
if(!generate_request(qstate, id, qstate->qinfo.qname,
|
||||
qstate->qinfo.qname_len, LDNS_RR_TYPE_IPSECKEY,
|
||||
qstate->qinfo.qclass, 0)) {
|
||||
log_err("ipsecmod: could not generate subquery.");
|
||||
ipsecmod_error(qstate, id);
|
||||
}
|
||||
return;
|
||||
}
|
||||
/* we are done with the query. */
|
||||
qstate->ext_state[id] = module_finished;
|
||||
}
|
||||
|
||||
void
|
||||
ipsecmod_operate(struct module_qstate* qstate, enum module_ev event, int id,
|
||||
struct outbound_entry* outbound)
|
||||
{
|
||||
struct ipsecmod_env* ie = (struct ipsecmod_env*)qstate->env->modinfo[id];
|
||||
struct ipsecmod_qstate* iq = (struct ipsecmod_qstate*)qstate->minfo[id];
|
||||
verbose(VERB_QUERY, "ipsecmod[module %d] operate: extstate:%s event:%s",
|
||||
id, strextstate(qstate->ext_state[id]), strmodulevent(event));
|
||||
if(iq) log_query_info(VERB_QUERY, "ipsecmod operate: query",
|
||||
&qstate->qinfo);
|
||||
|
||||
/* create ipsecmod_qstate. */
|
||||
if((event == module_event_new || event == module_event_pass) &&
|
||||
iq == NULL) {
|
||||
if(!ipsecmod_new(qstate, id)) {
|
||||
ipsecmod_error(qstate, id);
|
||||
return;
|
||||
}
|
||||
iq = (struct ipsecmod_qstate*)qstate->minfo[id];
|
||||
}
|
||||
if(iq && (event == module_event_pass || event == module_event_new)) {
|
||||
ipsecmod_handle_query(qstate, iq, ie, id);
|
||||
return;
|
||||
}
|
||||
if(iq && (event == module_event_moddone)) {
|
||||
ipsecmod_handle_response(qstate, iq, ie, id);
|
||||
return;
|
||||
}
|
||||
if(iq && outbound) {
|
||||
/* cachedb does not need to process responses at this time
|
||||
* ignore it.
|
||||
cachedb_process_response(qstate, iq, ie, id, outbound, event);
|
||||
*/
|
||||
return;
|
||||
}
|
||||
if(event == module_event_error) {
|
||||
verbose(VERB_ALGO, "got called with event error, giving up");
|
||||
ipsecmod_error(qstate, id);
|
||||
return;
|
||||
}
|
||||
if(!iq && (event == module_event_moddone)) {
|
||||
/* during priming, module done but we never started. */
|
||||
qstate->ext_state[id] = module_finished;
|
||||
return;
|
||||
}
|
||||
|
||||
log_err("ipsecmod: bad event %s", strmodulevent(event));
|
||||
ipsecmod_error(qstate, id);
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
ipsecmod_inform_super(struct module_qstate* qstate, int id,
|
||||
struct module_qstate* super)
|
||||
{
|
||||
struct ipsecmod_qstate* siq;
|
||||
log_query_info(VERB_ALGO, "ipsecmod: inform_super, sub is",
|
||||
&qstate->qinfo);
|
||||
log_query_info(VERB_ALGO, "super is", &super->qinfo);
|
||||
siq = (struct ipsecmod_qstate*)super->minfo[id];
|
||||
if(!siq) {
|
||||
verbose(VERB_ALGO, "super has no ipsecmod state");
|
||||
return;
|
||||
}
|
||||
|
||||
if(qstate->return_msg) {
|
||||
struct ub_packed_rrset_key* rrset_key = reply_find_answer_rrset(
|
||||
&qstate->return_msg->qinfo, qstate->return_msg->rep);
|
||||
if(rrset_key) {
|
||||
/* We have an answer. */
|
||||
/* Copy to super's region. */
|
||||
rrset_key = packed_rrset_copy_region(rrset_key, super->region, 0);
|
||||
siq->ipseckey_rrset = rrset_key;
|
||||
if(!rrset_key) {
|
||||
log_err("ipsecmod: out of memory.");
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Notify super to proceed. */
|
||||
siq->ipseckey_done = 1;
|
||||
}
|
||||
|
||||
void
|
||||
ipsecmod_clear(struct module_qstate* qstate, int id)
|
||||
{
|
||||
if(!qstate)
|
||||
return;
|
||||
qstate->minfo[id] = NULL;
|
||||
}
|
||||
|
||||
size_t
|
||||
ipsecmod_get_mem(struct module_env* env, int id)
|
||||
{
|
||||
struct ipsecmod_env* ie = (struct ipsecmod_env*)env->modinfo[id];
|
||||
if(!ie)
|
||||
return 0;
|
||||
return sizeof(*ie) + ipsecmod_whitelist_get_mem(ie->whitelist);
|
||||
}
|
||||
|
||||
/**
|
||||
* The ipsecmod function block
|
||||
*/
|
||||
static struct module_func_block ipsecmod_block = {
|
||||
"ipsecmod",
|
||||
&ipsecmod_init, &ipsecmod_deinit, &ipsecmod_operate,
|
||||
&ipsecmod_inform_super, &ipsecmod_clear, &ipsecmod_get_mem
|
||||
};
|
||||
|
||||
struct module_func_block*
|
||||
ipsecmod_get_funcblock(void)
|
||||
{
|
||||
return &ipsecmod_block;
|
||||
}
|
||||
#endif /* USE_IPSECMOD */
|
||||
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* ipsecmod/ipsecmod.h - facilitate opportunistic IPsec module
|
||||
*
|
||||
* Copyright (c) 2017, NLnet Labs. All rights reserved.
|
||||
*
|
||||
* This software is open source.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* Neither the name of the NLNET LABS nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* This file contains a module that facilitates opportunistic IPsec. It does so
|
||||
* by also quering for the IPSECKEY for A/AAAA queries and calling a
|
||||
* configurable hook (eg. signaling an IKE daemon) before replying.
|
||||
*/
|
||||
|
||||
#ifndef IPSECMOD_H
|
||||
#define IPSECMOD_H
|
||||
#include "util/module.h"
|
||||
#include "util/rbtree.h"
|
||||
|
||||
/**
|
||||
* The global variable environment contents for the ipsecmod
|
||||
* Shared between threads, this represents long term information.
|
||||
*/
|
||||
struct ipsecmod_env {
|
||||
/** White listed domains for ipsecmod. */
|
||||
rbtree_type* whitelist;
|
||||
};
|
||||
|
||||
/**
|
||||
* Per query state for the ipsecmod module.
|
||||
*/
|
||||
struct ipsecmod_qstate {
|
||||
/** State of the IPsec module. */
|
||||
/** NOTE: This value is copied here from the configuration so that a change
|
||||
* with unbound-control would not complicate an already running mesh. */
|
||||
int enabled;
|
||||
/** If the qname is whitelisted or not. */
|
||||
/** NOTE: No whitelist means all qnames are whitelisted. */
|
||||
int is_whitelisted;
|
||||
/** Pointer to IPSECKEY rrset allocated in the qstate region. NULL if there
|
||||
* was no IPSECKEY reply from the subquery. */
|
||||
struct ub_packed_rrset_key* ipseckey_rrset;
|
||||
/** If the IPSECKEY subquery has finished. */
|
||||
int ipseckey_done;
|
||||
};
|
||||
|
||||
/** Init the ipsecmod module */
|
||||
int ipsecmod_init(struct module_env* env, int id);
|
||||
/** Deinit the ipsecmod module */
|
||||
void ipsecmod_deinit(struct module_env* env, int id);
|
||||
/** Operate on an event on a query (in qstate). */
|
||||
void ipsecmod_operate(struct module_qstate* qstate, enum module_ev event,
|
||||
int id, struct outbound_entry* outbound);
|
||||
/** Subordinate query done, inform this super request of its conclusion */
|
||||
void ipsecmod_inform_super(struct module_qstate* qstate, int id,
|
||||
struct module_qstate* super);
|
||||
/** clear the ipsecmod query-specific contents out of qstate */
|
||||
void ipsecmod_clear(struct module_qstate* qstate, int id);
|
||||
/** return memory estimate for the ipsecmod module */
|
||||
size_t ipsecmod_get_mem(struct module_env* env, int id);
|
||||
|
||||
/**
|
||||
* Get the function block with pointers to the ipsecmod functions
|
||||
* @return the function block for "ipsecmod".
|
||||
*/
|
||||
struct module_func_block* ipsecmod_get_funcblock(void);
|
||||
|
||||
#endif /* IPSECMOD_H */
|
||||
@@ -58,7 +58,7 @@ struct iter_donotq {
|
||||
* contents of type addr_tree_node. Each node is an address span
|
||||
* that must not be used to send queries to.
|
||||
*/
|
||||
rbtree_t tree;
|
||||
rbtree_type tree;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
+4
-4
@@ -82,7 +82,7 @@ static void fwd_zone_free(struct iter_forward_zone* n)
|
||||
free(n);
|
||||
}
|
||||
|
||||
static void delfwdnode(rbnode_t* n, void* ATTR_UNUSED(arg))
|
||||
static void delfwdnode(rbnode_type* n, void* ATTR_UNUSED(arg))
|
||||
{
|
||||
struct iter_forward_zone* node = (struct iter_forward_zone*)n;
|
||||
fwd_zone_free(node);
|
||||
@@ -332,7 +332,7 @@ forwards_apply_cfg(struct iter_forwards* fwd, struct config_file* cfg)
|
||||
struct delegpt*
|
||||
forwards_find(struct iter_forwards* fwd, uint8_t* qname, uint16_t qclass)
|
||||
{
|
||||
rbnode_t* res = NULL;
|
||||
rbnode_type* res = NULL;
|
||||
struct iter_forward_zone key;
|
||||
key.node.key = &key;
|
||||
key.dclass = qclass;
|
||||
@@ -347,7 +347,7 @@ struct delegpt*
|
||||
forwards_lookup(struct iter_forwards* fwd, uint8_t* qname, uint16_t qclass)
|
||||
{
|
||||
/* lookup the forward zone in the tree */
|
||||
rbnode_t* res = NULL;
|
||||
rbnode_type* res = NULL;
|
||||
struct iter_forward_zone *result;
|
||||
struct iter_forward_zone key;
|
||||
key.node.key = &key;
|
||||
@@ -388,7 +388,7 @@ int
|
||||
forwards_next_root(struct iter_forwards* fwd, uint16_t* dclass)
|
||||
{
|
||||
struct iter_forward_zone key;
|
||||
rbnode_t* n;
|
||||
rbnode_type* n;
|
||||
struct iter_forward_zone* p;
|
||||
if(*dclass == 0) {
|
||||
/* first root item is first item in tree */
|
||||
|
||||
+2
-2
@@ -57,7 +57,7 @@ struct iter_forwards {
|
||||
* match which gives the ancestor needed.
|
||||
* contents of type iter_forward_zone.
|
||||
*/
|
||||
rbtree_t* tree;
|
||||
rbtree_type* tree;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -65,7 +65,7 @@ struct iter_forwards {
|
||||
*/
|
||||
struct iter_forward_zone {
|
||||
/** redblacktree node, key is this structure: class and name */
|
||||
rbnode_t node;
|
||||
rbnode_type node;
|
||||
/** name */
|
||||
uint8_t* name;
|
||||
/** length of name */
|
||||
|
||||
@@ -67,7 +67,7 @@ static void hints_stub_free(struct iter_hints_stub* s)
|
||||
free(s);
|
||||
}
|
||||
|
||||
static void delhintnode(rbnode_t* n, void* ATTR_UNUSED(arg))
|
||||
static void delhintnode(rbnode_type* n, void* ATTR_UNUSED(arg))
|
||||
{
|
||||
struct iter_hints_stub* node = (struct iter_hints_stub*)n;
|
||||
hints_stub_free(node);
|
||||
@@ -144,7 +144,7 @@ compile_time_root_prime(int do_ip4, int do_ip6)
|
||||
}
|
||||
if(do_ip6) {
|
||||
if(!ah(dp, "A.ROOT-SERVERS.NET.", "2001:503:ba3e::2:30")) goto failed;
|
||||
if(!ah(dp, "B.ROOT-SERVERS.NET.", "2001:500:84::b")) goto failed;
|
||||
if(!ah(dp, "B.ROOT-SERVERS.NET.", "2001:500:200::b")) goto failed;
|
||||
if(!ah(dp, "C.ROOT-SERVERS.NET.", "2001:500:2::c")) goto failed;
|
||||
if(!ah(dp, "D.ROOT-SERVERS.NET.", "2001:500:2d::d")) goto failed;
|
||||
if(!ah(dp, "E.ROOT-SERVERS.NET.", "2001:500:a8::e")) goto failed;
|
||||
|
||||
@@ -59,7 +59,7 @@ struct iter_hints {
|
||||
* contents of type iter_hints_stub. The class IN root is in here.
|
||||
* uses name_tree_node from dnstree.h.
|
||||
*/
|
||||
rbtree_t tree;
|
||||
rbtree_type tree;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -60,14 +60,14 @@ struct iter_priv {
|
||||
* contents of type addr_tree_node.
|
||||
* No further data need, only presence or absence.
|
||||
*/
|
||||
rbtree_t a;
|
||||
rbtree_type a;
|
||||
/**
|
||||
* Tree of the domains spans that are allowed to contain
|
||||
* the blocked address spans.
|
||||
* contents of type name_tree_node.
|
||||
* No further data need, only presence or absence.
|
||||
*/
|
||||
rbtree_t n;
|
||||
rbtree_type n;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -161,8 +161,8 @@ mark_additional_rrset(sldns_buffer* pkt, struct msg_parse* msg,
|
||||
for(rr = rrset->rr_first; rr; rr = rr->next) {
|
||||
if(get_additional_name(rrset, rr, &nm, &nmlen, pkt)) {
|
||||
/* mark A */
|
||||
hashvalue_t h = pkt_hash_rrset(pkt, nm, LDNS_RR_TYPE_A,
|
||||
rrset->rrset_class, 0);
|
||||
hashvalue_type h = pkt_hash_rrset(pkt, nm,
|
||||
LDNS_RR_TYPE_A, rrset->rrset_class, 0);
|
||||
struct rrset_parse* r = msgparse_hashtable_lookup(
|
||||
msg, pkt, h, 0, nm, nmlen,
|
||||
LDNS_RR_TYPE_A, rrset->rrset_class);
|
||||
|
||||
@@ -108,7 +108,7 @@ read_fetch_policy(struct iter_env* ie, const char* str)
|
||||
|
||||
/** apply config caps whitelist items to name tree */
|
||||
static int
|
||||
caps_white_apply_cfg(rbtree_t* ntree, struct config_file* cfg)
|
||||
caps_white_apply_cfg(rbtree_type* ntree, struct config_file* cfg)
|
||||
{
|
||||
struct config_strlist* p;
|
||||
for(p=cfg->caps_whitelist; p; p=p->next) {
|
||||
|
||||
+129
-34
@@ -88,7 +88,7 @@ iter_init(struct module_env* env, int id)
|
||||
|
||||
/** delete caps_whitelist element */
|
||||
static void
|
||||
caps_free(struct rbnode_t* n, void* ATTR_UNUSED(d))
|
||||
caps_free(struct rbnode_type* n, void* ATTR_UNUSED(d))
|
||||
{
|
||||
if(n) {
|
||||
free(((struct name_tree_node*)n)->name);
|
||||
@@ -288,6 +288,22 @@ error_response_cache(struct module_qstate* qstate, int id, int rcode)
|
||||
return error_response(qstate, id, rcode);
|
||||
/* if that fails (not in cache), fall through to store err */
|
||||
}
|
||||
if(qstate->env->cfg->serve_expired) {
|
||||
/* if serving expired contents, and such content is
|
||||
* already available, don't overwrite this servfail */
|
||||
struct msgreply_entry* msg;
|
||||
if((msg=msg_cache_lookup(qstate->env,
|
||||
qstate->qinfo.qname, qstate->qinfo.qname_len,
|
||||
qstate->qinfo.qtype, qstate->qinfo.qclass,
|
||||
qstate->query_flags, 0, 0))
|
||||
!= NULL) {
|
||||
lock_rw_unlock(&msg->entry.lock);
|
||||
return error_response(qstate, id, rcode);
|
||||
}
|
||||
/* serving expired contents, but nothing is cached
|
||||
* at all, so the servfail cache entry is useful
|
||||
* (stops waste of time on this servfail NORR_TTL) */
|
||||
}
|
||||
memset(&err, 0, sizeof(err));
|
||||
err.flags = (uint16_t)(BIT_QR | BIT_RA);
|
||||
FLAGS_SET_RCODE(err.flags, rcode);
|
||||
@@ -372,6 +388,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 +493,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;
|
||||
@@ -484,6 +525,33 @@ handle_cname_response(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** see if last resort is possible - does config allow queries to parent */
|
||||
static int
|
||||
can_have_last_resort(struct module_env* env, uint8_t* nm, size_t nmlen,
|
||||
uint16_t qclass)
|
||||
{
|
||||
struct delegpt* fwddp;
|
||||
struct iter_hints_stub* stub;
|
||||
int labs = dname_count_labels(nm);
|
||||
/* do not process a last resort (the parent side) if a stub
|
||||
* or forward is configured, because we do not want to go 'above'
|
||||
* the configured servers */
|
||||
if(!dname_is_root(nm) && (stub = (struct iter_hints_stub*)
|
||||
name_tree_find(&env->hints->tree, nm, nmlen, labs, qclass)) &&
|
||||
/* has_parent side is turned off for stub_first, where we
|
||||
* are allowed to go to the parent */
|
||||
stub->dp->has_parent_side_NS) {
|
||||
return 0;
|
||||
}
|
||||
if((fwddp = forwards_find(env->fwds, nm, qclass)) &&
|
||||
/* has_parent_side is turned off for forward_first, where
|
||||
* we are allowed to go to the parent */
|
||||
fwddp->has_parent_side_NS) {
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** see if target name is caps-for-id whitelisted */
|
||||
static int
|
||||
is_caps_whitelisted(struct iter_env* ie, struct iter_qstate* iq)
|
||||
@@ -828,6 +896,9 @@ generate_ns_check(struct module_qstate* qstate, struct iter_qstate* iq, int id)
|
||||
|
||||
if(iq->depth == ie->max_dependency_depth)
|
||||
return;
|
||||
if(!can_have_last_resort(qstate->env, iq->dp->name, iq->dp->namelen,
|
||||
iq->qchase.qclass))
|
||||
return;
|
||||
/* is this query the same as the nscheck? */
|
||||
if(qstate->qinfo.qtype == LDNS_RR_TYPE_NS &&
|
||||
query_dname_compare(iq->dp->name, qstate->qinfo.qname)==0 &&
|
||||
@@ -1000,6 +1071,20 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
return next_state(iq, COLLECT_CLASS_STATE);
|
||||
}
|
||||
|
||||
/*
|
||||
* If we are restricted by a forward-zone or a stub-zone, we
|
||||
* can't re-fetch glue for this delegation point.
|
||||
* we won’t try to re-fetch glue if the iq->dp is null.
|
||||
*/
|
||||
if (iq->refetch_glue &&
|
||||
iq->dp &&
|
||||
!can_have_last_resort(qstate->env,
|
||||
iq->dp->name,
|
||||
iq->dp->namelen,
|
||||
iq->qchase.qclass)) {
|
||||
iq->refetch_glue = 0;
|
||||
}
|
||||
|
||||
/* Resolver Algorithm Step 1 -- Look for the answer in local data. */
|
||||
|
||||
/* This either results in a query restart (CNAME cache response), a
|
||||
@@ -1326,7 +1411,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",
|
||||
@@ -1533,35 +1618,6 @@ query_for_targets(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** see if last resort is possible - does config allow queries to parent */
|
||||
static int
|
||||
can_have_last_resort(struct module_env* env, struct delegpt* dp,
|
||||
struct iter_qstate* iq)
|
||||
{
|
||||
struct delegpt* fwddp;
|
||||
struct iter_hints_stub* stub;
|
||||
/* do not process a last resort (the parent side) if a stub
|
||||
* or forward is configured, because we do not want to go 'above'
|
||||
* the configured servers */
|
||||
if(!dname_is_root(dp->name) && (stub = (struct iter_hints_stub*)
|
||||
name_tree_find(&env->hints->tree, dp->name, dp->namelen,
|
||||
dp->namelabs, iq->qchase.qclass)) &&
|
||||
/* has_parent side is turned off for stub_first, where we
|
||||
* are allowed to go to the parent */
|
||||
stub->dp->has_parent_side_NS) {
|
||||
verbose(VERB_QUERY, "configured stub servers failed -- returning SERVFAIL");
|
||||
return 0;
|
||||
}
|
||||
if((fwddp = forwards_find(env->fwds, dp->name, iq->qchase.qclass)) &&
|
||||
/* has_parent_side is turned off for forward_first, where
|
||||
* we are allowed to go to the parent */
|
||||
fwddp->has_parent_side_NS) {
|
||||
verbose(VERB_QUERY, "configured forward servers failed -- returning SERVFAIL");
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by processQueryTargets when it would like extra targets to query
|
||||
* but it seems to be out of options. At last resort some less appealing
|
||||
@@ -1583,9 +1639,11 @@ processLastResort(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
verbose(VERB_ALGO, "No more query targets, attempting last resort");
|
||||
log_assert(iq->dp);
|
||||
|
||||
if(!can_have_last_resort(qstate->env, iq->dp, iq)) {
|
||||
if(!can_have_last_resort(qstate->env, iq->dp->name, iq->dp->namelen,
|
||||
iq->qchase.qclass)) {
|
||||
/* fail -- no more targets, no more hope of targets, no hope
|
||||
* of a response. */
|
||||
verbose(VERB_QUERY, "configured stub or forward servers failed -- returning SERVFAIL");
|
||||
return error_response_cache(qstate, id, LDNS_RCODE_SERVFAIL);
|
||||
}
|
||||
if(!iq->dp->has_parent_side_NS && dname_is_root(iq->dp->name)) {
|
||||
@@ -1670,6 +1728,19 @@ processLastResort(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
/* see if we can issue queries to get nameserver addresses */
|
||||
/* this lookup is not randomized, but sequential. */
|
||||
for(ns = iq->dp->nslist; ns; ns = ns->next) {
|
||||
/* if this nameserver is at a delegation point, but that
|
||||
* delegation point is a stub and we cannot go higher, skip*/
|
||||
if( ((ie->supports_ipv6 && !ns->done_pside6) ||
|
||||
(ie->supports_ipv4 && !ns->done_pside4)) &&
|
||||
!can_have_last_resort(qstate->env, ns->name, ns->namelen,
|
||||
iq->qchase.qclass)) {
|
||||
log_nametypeclass(VERB_ALGO, "cannot pside lookup ns "
|
||||
"because it is also a stub/forward,",
|
||||
ns->name, LDNS_RR_TYPE_NS, iq->qchase.qclass);
|
||||
if(ie->supports_ipv6) ns->done_pside6 = 1;
|
||||
if(ie->supports_ipv4) ns->done_pside4 = 1;
|
||||
continue;
|
||||
}
|
||||
/* query for parent-side A and AAAA for nameservers */
|
||||
if(ie->supports_ipv6 && !ns->done_pside6) {
|
||||
/* Send the AAAA request. */
|
||||
@@ -2169,6 +2240,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 +2308,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 +3252,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 */
|
||||
|
||||
+2
-2
@@ -51,7 +51,7 @@ struct iter_forwards;
|
||||
struct iter_donotq;
|
||||
struct iter_prep_list;
|
||||
struct iter_priv;
|
||||
struct rbtree_t;
|
||||
struct rbtree_type;
|
||||
|
||||
/** max number of targets spawned for a query and its subqueries */
|
||||
#define MAX_TARGET_COUNT 64
|
||||
@@ -115,7 +115,7 @@ struct iter_env {
|
||||
struct iter_priv* priv;
|
||||
|
||||
/** whitelist for capsforid names */
|
||||
struct rbtree_t* caps_white;
|
||||
struct rbtree_type* caps_white;
|
||||
|
||||
/** The maximum dependency depth that this resolver will pursue. */
|
||||
int max_dependency_depth;
|
||||
|
||||
@@ -127,7 +127,7 @@ find_id(struct ub_ctx* ctx, int* id)
|
||||
|
||||
struct ctx_query*
|
||||
context_new(struct ub_ctx* ctx, const char* name, int rrtype, int rrclass,
|
||||
ub_callback_t cb, void* cbarg)
|
||||
ub_callback_type cb, void* cbarg)
|
||||
{
|
||||
struct ctx_query* q = (struct ctx_query*)calloc(1, sizeof(*q));
|
||||
if(!q) return NULL;
|
||||
|
||||
@@ -61,17 +61,17 @@ struct ub_event_base;
|
||||
struct ub_ctx {
|
||||
/* --- pipes --- */
|
||||
/** mutex on query write pipe */
|
||||
lock_basic_t qqpipe_lock;
|
||||
lock_basic_type qqpipe_lock;
|
||||
/** the query write pipe */
|
||||
struct tube* qq_pipe;
|
||||
/** mutex on result read pipe */
|
||||
lock_basic_t rrpipe_lock;
|
||||
lock_basic_type rrpipe_lock;
|
||||
/** the result read pipe */
|
||||
struct tube* rr_pipe;
|
||||
|
||||
/* --- shared data --- */
|
||||
/** mutex for access to env.cfg, finalized and dothread */
|
||||
lock_basic_t cfglock;
|
||||
lock_basic_type cfglock;
|
||||
/**
|
||||
* The context has been finalized
|
||||
* This is after config when the first resolve is done.
|
||||
@@ -84,7 +84,7 @@ struct ub_ctx {
|
||||
/** pid of bg worker process */
|
||||
pid_t bg_pid;
|
||||
/** tid of bg worker thread */
|
||||
ub_thread_t bg_tid;
|
||||
ub_thread_type bg_tid;
|
||||
|
||||
/** do threading (instead of forking) for async resolution */
|
||||
int dothread;
|
||||
@@ -129,7 +129,7 @@ struct ub_ctx {
|
||||
* Used to see if querynum is free for use.
|
||||
* Content of type ctx_query.
|
||||
*/
|
||||
rbtree_t queries;
|
||||
rbtree_type queries;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -140,7 +140,7 @@ struct ub_ctx {
|
||||
*/
|
||||
struct ctx_query {
|
||||
/** node in rbtree, must be first entry, key is ptr to the querynum */
|
||||
struct rbnode_t node;
|
||||
struct rbnode_type node;
|
||||
/** query id number, key for node */
|
||||
int querynum;
|
||||
/** was this an async query? */
|
||||
@@ -149,7 +149,7 @@ struct ctx_query {
|
||||
int cancelled;
|
||||
|
||||
/** for async query, the callback function */
|
||||
ub_callback_t cb;
|
||||
ub_callback_type cb;
|
||||
/** for async query, the callback user arg */
|
||||
void* cb_arg;
|
||||
|
||||
@@ -242,7 +242,7 @@ void context_query_delete(struct ctx_query* q);
|
||||
* @return new ctx_query or NULL for malloc failure.
|
||||
*/
|
||||
struct ctx_query* context_new(struct ub_ctx* ctx, const char* name, int rrtype,
|
||||
int rrclass, ub_callback_t cb, void* cbarg);
|
||||
int rrclass, ub_callback_type cb, void* cbarg);
|
||||
|
||||
/**
|
||||
* Get a new alloc. Creates a new one or uses a cached one.
|
||||
|
||||
@@ -215,7 +215,7 @@ ub_ctx_create_event(struct event_base* eb)
|
||||
|
||||
/** delete q */
|
||||
static void
|
||||
delq(rbnode_t* n, void* ATTR_UNUSED(arg))
|
||||
delq(rbnode_type* n, void* ATTR_UNUSED(arg))
|
||||
{
|
||||
struct ctx_query* q = (struct ctx_query*)n;
|
||||
context_query_delete(q);
|
||||
@@ -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);
|
||||
@@ -500,7 +499,7 @@ ub_fd(struct ub_ctx* ctx)
|
||||
/** process answer from bg worker */
|
||||
static int
|
||||
process_answer_detail(struct ub_ctx* ctx, uint8_t* msg, uint32_t len,
|
||||
ub_callback_t* cb, void** cbarg, int* err,
|
||||
ub_callback_type* cb, void** cbarg, int* err,
|
||||
struct ub_result** res)
|
||||
{
|
||||
struct ctx_query* q;
|
||||
@@ -567,7 +566,7 @@ static int
|
||||
process_answer(struct ub_ctx* ctx, uint8_t* msg, uint32_t len)
|
||||
{
|
||||
int err;
|
||||
ub_callback_t cb;
|
||||
ub_callback_type cb;
|
||||
void* cbarg;
|
||||
struct ub_result* res;
|
||||
int r;
|
||||
@@ -610,7 +609,7 @@ int
|
||||
ub_wait(struct ub_ctx* ctx)
|
||||
{
|
||||
int err;
|
||||
ub_callback_t cb;
|
||||
ub_callback_type cb;
|
||||
void* cbarg;
|
||||
struct ub_result* res;
|
||||
int r;
|
||||
@@ -706,7 +705,8 @@ ub_resolve(struct ub_ctx* ctx, const char* name, int rrtype,
|
||||
|
||||
int
|
||||
ub_resolve_event(struct ub_ctx* ctx, const char* name, int rrtype,
|
||||
int rrclass, void* mydata, ub_event_callback_t callback, int* async_id)
|
||||
int rrclass, void* mydata, ub_event_callback_type callback,
|
||||
int* async_id)
|
||||
{
|
||||
struct ctx_query* q;
|
||||
int r;
|
||||
@@ -734,7 +734,7 @@ ub_resolve_event(struct ub_ctx* ctx, const char* name, int rrtype,
|
||||
ub_comm_base_now(ctx->event_worker->base);
|
||||
|
||||
/* create new ctx_query and attempt to add to the list */
|
||||
q = context_new(ctx, name, rrtype, rrclass, (ub_callback_t)callback,
|
||||
q = context_new(ctx, name, rrtype, rrclass, (ub_callback_type)callback,
|
||||
mydata);
|
||||
if(!q)
|
||||
return UB_NOMEM;
|
||||
@@ -748,7 +748,7 @@ ub_resolve_event(struct ub_ctx* ctx, const char* name, int rrtype,
|
||||
|
||||
int
|
||||
ub_resolve_async(struct ub_ctx* ctx, const char* name, int rrtype,
|
||||
int rrclass, void* mydata, ub_callback_t callback, int* async_id)
|
||||
int rrclass, void* mydata, ub_callback_type callback, int* async_id)
|
||||
{
|
||||
struct ctx_query* q;
|
||||
uint8_t* msg = NULL;
|
||||
|
||||
@@ -639,7 +639,7 @@ libworker_event_done_cb(void* arg, int rcode, sldns_buffer* buf,
|
||||
enum sec_status s, char* why_bogus)
|
||||
{
|
||||
struct ctx_query* q = (struct ctx_query*)arg;
|
||||
ub_event_callback_t cb = (ub_event_callback_t)q->cb;
|
||||
ub_event_callback_type cb = (ub_event_callback_type)q->cb;
|
||||
void* cb_arg = q->cb_arg;
|
||||
int cancelled = q->cancelled;
|
||||
|
||||
|
||||
@@ -170,7 +170,7 @@ struct ub_event {
|
||||
struct ub_event_vmt* vmt;
|
||||
};
|
||||
|
||||
typedef void (*ub_event_callback_t)(void*, int, void*, int, int, char*);
|
||||
typedef void (*ub_event_callback_type)(void*, int, void*, int, int, char*);
|
||||
|
||||
/**
|
||||
* Create a resolving and validation context.
|
||||
@@ -254,7 +254,8 @@ int ub_ctx_set_event(struct ub_ctx* ctx, struct event_base* base);
|
||||
* @return 0 if OK, else error.
|
||||
*/
|
||||
int ub_resolve_event(struct ub_ctx* ctx, const char* name, int rrtype,
|
||||
int rrclass, void* mydata, ub_event_callback_t callback, int* async_id);
|
||||
int rrclass, void* mydata, ub_event_callback_type callback,
|
||||
int* async_id);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
+163
-2
@@ -223,7 +223,7 @@ struct ub_result {
|
||||
* This structure is allocated on the heap and needs to be
|
||||
* freed with ub_resolve_free(result);
|
||||
*/
|
||||
typedef void (*ub_callback_t)(void*, int, struct ub_result*);
|
||||
typedef void (*ub_callback_type)(void*, int, struct ub_result*);
|
||||
|
||||
/**
|
||||
* Create a resolving and validation context.
|
||||
@@ -519,7 +519,7 @@ int ub_resolve(struct ub_ctx* ctx, const char* name, int rrtype,
|
||||
* @return 0 if OK, else error.
|
||||
*/
|
||||
int ub_resolve_async(struct ub_ctx* ctx, const char* name, int rrtype,
|
||||
int rrclass, void* mydata, ub_callback_t callback, int* async_id);
|
||||
int rrclass, void* mydata, ub_callback_type callback, int* async_id);
|
||||
|
||||
/**
|
||||
* Cancel an async query in progress.
|
||||
@@ -601,6 +601,167 @@ int ub_ctx_data_remove(struct ub_ctx* ctx, const char *data);
|
||||
*/
|
||||
const char* ub_version(void);
|
||||
|
||||
/**
|
||||
* Some global statistics that are not in struct stats_info,
|
||||
* this struct is shared on a shm segment (shm-key in unbound.conf)
|
||||
*/
|
||||
struct ub_shm_stat_info {
|
||||
int num_threads;
|
||||
|
||||
struct {
|
||||
long long now_sec, now_usec;
|
||||
long long up_sec, up_usec;
|
||||
long long elapsed_sec, elapsed_usec;
|
||||
} time;
|
||||
|
||||
struct {
|
||||
long long msg;
|
||||
long long rrset;
|
||||
long long val;
|
||||
long long iter;
|
||||
long long subnet;
|
||||
long long ipsecmod;
|
||||
long long respip;
|
||||
} mem;
|
||||
};
|
||||
|
||||
/** number of qtype that is stored for in array */
|
||||
#define UB_STATS_QTYPE_NUM 256
|
||||
/** number of qclass that is stored for in array */
|
||||
#define UB_STATS_QCLASS_NUM 256
|
||||
/** number of rcodes in stats */
|
||||
#define UB_STATS_RCODE_NUM 16
|
||||
/** number of opcodes in stats */
|
||||
#define UB_STATS_OPCODE_NUM 16
|
||||
/** number of histogram buckets */
|
||||
#define UB_STATS_BUCKET_NUM 40
|
||||
|
||||
/** per worker statistics. */
|
||||
struct ub_server_stats {
|
||||
/** number of queries from clients received. */
|
||||
long long num_queries;
|
||||
/** number of queries that have been dropped/ratelimited by ip. */
|
||||
long long num_queries_ip_ratelimited;
|
||||
/** number of queries that had a cache-miss. */
|
||||
long long num_queries_missed_cache;
|
||||
/** number of prefetch queries - cachehits with prefetch */
|
||||
long long num_queries_prefetch;
|
||||
|
||||
/**
|
||||
* Sum of the querylistsize of the worker for
|
||||
* every query that missed cache. To calculate average.
|
||||
*/
|
||||
long long sum_query_list_size;
|
||||
/** max value of query list size reached. */
|
||||
long long max_query_list_size;
|
||||
|
||||
/** Extended stats below (bool) */
|
||||
int extended;
|
||||
|
||||
/** qtype stats */
|
||||
long long qtype[UB_STATS_QTYPE_NUM];
|
||||
/** bigger qtype values not in array */
|
||||
long long qtype_big;
|
||||
/** qclass stats */
|
||||
long long qclass[UB_STATS_QCLASS_NUM];
|
||||
/** bigger qclass values not in array */
|
||||
long long qclass_big;
|
||||
/** query opcodes */
|
||||
long long qopcode[UB_STATS_OPCODE_NUM];
|
||||
/** number of queries over TCP */
|
||||
long long qtcp;
|
||||
/** number of outgoing queries over TCP */
|
||||
long long qtcp_outgoing;
|
||||
/** number of queries over IPv6 */
|
||||
long long qipv6;
|
||||
/** number of queries with QR bit */
|
||||
long long qbit_QR;
|
||||
/** number of queries with AA bit */
|
||||
long long qbit_AA;
|
||||
/** number of queries with TC bit */
|
||||
long long qbit_TC;
|
||||
/** number of queries with RD bit */
|
||||
long long qbit_RD;
|
||||
/** number of queries with RA bit */
|
||||
long long qbit_RA;
|
||||
/** number of queries with Z bit */
|
||||
long long qbit_Z;
|
||||
/** number of queries with AD bit */
|
||||
long long qbit_AD;
|
||||
/** number of queries with CD bit */
|
||||
long long qbit_CD;
|
||||
/** number of queries with EDNS OPT record */
|
||||
long long qEDNS;
|
||||
/** number of queries with EDNS with DO flag */
|
||||
long long qEDNS_DO;
|
||||
/** answer rcodes */
|
||||
long long ans_rcode[UB_STATS_RCODE_NUM];
|
||||
/** answers with pseudo rcode 'nodata' */
|
||||
long long ans_rcode_nodata;
|
||||
/** answers that were secure (AD) */
|
||||
long long ans_secure;
|
||||
/** answers that were bogus (withheld as SERVFAIL) */
|
||||
long long ans_bogus;
|
||||
/** rrsets marked bogus by validator */
|
||||
long long rrset_bogus;
|
||||
/** unwanted traffic received on server-facing ports */
|
||||
long long unwanted_replies;
|
||||
/** unwanted traffic received on client-facing ports */
|
||||
long long unwanted_queries;
|
||||
/** usage of tcp accept list */
|
||||
long long tcp_accept_usage;
|
||||
/** answers served from expired cache */
|
||||
long long zero_ttl_responses;
|
||||
/** histogram data exported to array
|
||||
* if the array is the same size, no data is lost, and
|
||||
* if all histograms are same size (is so by default) then
|
||||
* adding up works well. */
|
||||
long long hist[UB_STATS_BUCKET_NUM];
|
||||
|
||||
/** number of message cache entries */
|
||||
long long msg_cache_count;
|
||||
/** number of rrset cache entries */
|
||||
long long rrset_cache_count;
|
||||
/** number of infra cache entries */
|
||||
long long infra_cache_count;
|
||||
/** number of key cache entries */
|
||||
long long key_cache_count;
|
||||
|
||||
/** number of queries that used dnscrypt */
|
||||
long long num_query_dnscrypt_crypted;
|
||||
/** number of queries that queried dnscrypt certificates */
|
||||
long long num_query_dnscrypt_cert;
|
||||
/** number of queries in clear text and not asking for the certificates */
|
||||
long long num_query_dnscrypt_cleartext;
|
||||
/** number of malformed encrypted queries */
|
||||
long long num_query_dnscrypt_crypted_malformed;
|
||||
};
|
||||
|
||||
/**
|
||||
* Statistics to send over the control pipe when asked
|
||||
* This struct is made to be memcpied, sent in binary.
|
||||
* shm mapped with (number+1) at num_threads+1, with first as total
|
||||
*/
|
||||
struct ub_stats_info {
|
||||
/** the thread stats */
|
||||
struct ub_server_stats svr;
|
||||
|
||||
/** mesh stats: current number of states */
|
||||
long long mesh_num_states;
|
||||
/** mesh stats: current number of reply (user) states */
|
||||
long long mesh_num_reply_states;
|
||||
/** mesh stats: number of reply states overwritten with a new one */
|
||||
long long mesh_jostled;
|
||||
/** mesh stats: number of incoming queries dropped */
|
||||
long long mesh_dropped;
|
||||
/** mesh stats: replies sent */
|
||||
long long mesh_replies_sent;
|
||||
/** mesh stats: sum of waiting times for the replies */
|
||||
long long mesh_replies_sum_wait_sec, mesh_replies_sum_wait_usec;
|
||||
/** mesh stats: median of waiting times for replies (in sec) */
|
||||
double mesh_time_median;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
+24
-8
@@ -55,7 +55,7 @@ Generate a distribution tar file for unbound.
|
||||
Detected from svn working copy if not specified.
|
||||
-wssl openssl.xx.tar.gz Also build openssl from tarball for windows dist.
|
||||
-wxp expat.xx.tar.gz Also build expat from tarball for windows dist.
|
||||
-w64 64bit windows compile.
|
||||
-w32 32bit windows compile.
|
||||
-w ... Build windows binary dist. last args passed to configure.
|
||||
EOF
|
||||
exit 1
|
||||
@@ -178,7 +178,7 @@ storehash () {
|
||||
SNAPSHOT="no"
|
||||
RC="no"
|
||||
DOWIN="no"
|
||||
W64="no"
|
||||
W64="yes"
|
||||
WINSSL=""
|
||||
WINEXPAT=""
|
||||
|
||||
@@ -203,9 +203,8 @@ while [ "$1" ]; do
|
||||
WINEXPAT="$2"
|
||||
shift
|
||||
;;
|
||||
"-w64")
|
||||
W64="yes"
|
||||
shift
|
||||
"-w32")
|
||||
W64="no"
|
||||
;;
|
||||
"-w")
|
||||
DOWIN="yes"
|
||||
@@ -324,9 +323,20 @@ if [ "$DOWIN" = "yes" ]; then
|
||||
# procedure for making unbound installer on mingw.
|
||||
info "Creating windows dist unbound $version"
|
||||
info "Calling configure"
|
||||
echo "$configure"' --enable-debug --enable-static-exe --disable-flto '"$* $cross_flag"
|
||||
$configure --enable-debug --enable-static-exe --disable-flto $* $cross_flag \
|
||||
if test "$W64" = "no"; then
|
||||
file_flag="--with-conf-file=C:\Program Files (x86)\Unbound\service.conf"
|
||||
file2_flag="--with-rootkey-file=C:\Program Files (x86)\Unbound\root.key"
|
||||
file3_flag="--with-rootcert-file=C:\Program Files (x86)\Unbound\icannbundle.pem"
|
||||
version="$version"-w32
|
||||
fi
|
||||
echo "$configure"' --enable-debug --enable-static-exe --disable-flto '"$* $cross_flag "$file_flag" "$file2_flag" "$file3_flag""
|
||||
if test "$W64" = "no"; then
|
||||
$configure --enable-debug --enable-static-exe --disable-flto $* $cross_flag "$file_flag" "$file2_flag" "$file3_flag" \
|
||||
|| error_cleanup "Could not configure"
|
||||
else
|
||||
$configure --enable-debug --enable-static-exe --disable-flto $* $cross_flag \
|
||||
|| error_cleanup "Could not configure"
|
||||
fi
|
||||
info "Calling make"
|
||||
make || error_cleanup "Could not make"
|
||||
info "Make complete"
|
||||
@@ -335,6 +345,7 @@ if [ "$DOWIN" = "yes" ]; then
|
||||
file="unbound-$version.zip"
|
||||
rm -f $file
|
||||
info "Creating $file"
|
||||
grep '^". IN DS' smallapp/unbound-anchor.c | sed -e 's/"//' -e 's/\\n.*$//' > root.key
|
||||
mkdir tmp.$$
|
||||
# keep debug symbols
|
||||
#$strip unbound.exe
|
||||
@@ -346,16 +357,21 @@ if [ "$DOWIN" = "yes" ]; then
|
||||
#$strip unbound-service-install.exe
|
||||
#$strip unbound-service-remove.exe
|
||||
cd tmp.$$
|
||||
cp ../root.key .
|
||||
cp ../doc/example.conf ../doc/Changelog .
|
||||
cp ../unbound.exe ../unbound-anchor.exe ../unbound-host.exe ../unbound-control.exe ../unbound-checkconf.exe ../unbound-service-install.exe ../unbound-service-remove.exe ../LICENSE ../winrc/unbound-control-setup.cmd ../winrc/unbound-website.url ../winrc/service.conf ../winrc/README.txt ../contrib/create_unbound_ad_servers.cmd ../contrib/warmup.cmd ../contrib/unbound_cache.cmd .
|
||||
# zipfile
|
||||
zip ../$file LICENSE README.txt unbound.exe unbound-anchor.exe unbound-host.exe unbound-control.exe unbound-checkconf.exe unbound-service-install.exe unbound-service-remove.exe unbound-control-setup.cmd example.conf service.conf unbound-website.url create_unbound_ad_servers.cmd warmup.cmd unbound_cache.cmd Changelog
|
||||
zip ../$file LICENSE README.txt unbound.exe unbound-anchor.exe unbound-host.exe unbound-control.exe unbound-checkconf.exe unbound-service-install.exe unbound-service-remove.exe unbound-control-setup.cmd example.conf service.conf root.key unbound-website.url create_unbound_ad_servers.cmd warmup.cmd unbound_cache.cmd Changelog
|
||||
info "Testing $file"
|
||||
(cd .. ; zip -T $file )
|
||||
# installer
|
||||
info "Creating installer"
|
||||
quadversion=`cat ../config.h | grep RSRC_PACKAGE_VERSION | sed -e 's/#define RSRC_PACKAGE_VERSION //' -e 's/,/\\./g'`
|
||||
cat ../winrc/setup.nsi | sed -e 's/define VERSION.*$/define VERSION "'$version'"/' -e 's/define QUADVERSION.*$/define QUADVERSION "'$quadversion'"/' > ../winrc/setup_ed.nsi
|
||||
if test "$W64" = "yes"; then
|
||||
mv ../winrc/setup_ed.nsi ../winrc/setup_ed_old.nsi
|
||||
cat ../winrc/setup_ed_old.nsi | sed -e 's/PROGRAMFILES/PROGRAMFILES64/' > ../winrc/setup_ed.nsi
|
||||
fi
|
||||
"$makensis" ../winrc/setup_ed.nsi
|
||||
info "Created installer"
|
||||
cd ..
|
||||
|
||||
@@ -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
|
||||
|
||||
+160
-148
@@ -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,24 +244,24 @@ uint16_t ntohs(uint16_t netshort);
|
||||
%}
|
||||
}
|
||||
|
||||
#if defined(SWIGWORDSIZE64)
|
||||
typedef long int rrset_id_t;
|
||||
#else
|
||||
typedef long long int rrset_id_t;
|
||||
#endif
|
||||
#if defined(SWIGWORDSIZE64)
|
||||
typedef long int rrset_id_type;
|
||||
#else
|
||||
typedef long long int rrset_id_type;
|
||||
#endif
|
||||
|
||||
struct ub_packed_rrset_key {
|
||||
struct lruhash_entry entry;
|
||||
rrset_id_t id;
|
||||
rrset_id_type id;
|
||||
struct packed_rrset_key rk;
|
||||
};
|
||||
|
||||
struct lruhash_entry {
|
||||
lock_rw_t lock;
|
||||
lock_rw_type lock;
|
||||
struct lruhash_entry* overflow_next;
|
||||
struct lruhash_entry* lru_next;
|
||||
struct lruhash_entry* lru_prev;
|
||||
hashvalue_t hash;
|
||||
hashvalue_type hash;
|
||||
void* key;
|
||||
struct packed_rrset_data* data;
|
||||
};
|
||||
@@ -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 */
|
||||
@@ -376,7 +376,7 @@ struct reply_info {
|
||||
|
||||
struct rrset_ref {
|
||||
struct ub_packed_rrset_key* key;
|
||||
rrset_id_t id;
|
||||
rrset_id_type id;
|
||||
};
|
||||
|
||||
struct dns_msg {
|
||||
@@ -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 %{
|
||||
@@ -513,7 +513,7 @@ struct edns_option {
|
||||
}
|
||||
|
||||
PyObject* _edns_option_opt_data_get(struct edns_option* option) {
|
||||
return PyByteArray_FromStringAndSize((uint8_t*)option->opt_data,
|
||||
return PyByteArray_FromStringAndSize((void*)option->opt_data,
|
||||
option->opt_len);
|
||||
}
|
||||
%}
|
||||
@@ -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
|
||||
* ************************************************************************************ */
|
||||
/******************************
|
||||
@@ -1332,7 +1351,7 @@ int edns_register_option(uint16_t opt_code, int bypass_cache_stage,
|
||||
SWIG_exception_fail(SWIG_TypeError, "Expected bytearray!");
|
||||
return NULL;
|
||||
}
|
||||
$2 = PyByteArray_AsString($input);
|
||||
$2 = (void*)PyByteArray_AsString($input);
|
||||
$1 = PyByteArray_Size($input);
|
||||
}
|
||||
|
||||
@@ -1346,15 +1365,15 @@ 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;
|
||||
PyObject *result;
|
||||
int res = 0;
|
||||
|
||||
func = (PyObject *) python_callback;
|
||||
PyGILState_STATE gstate = PyGILState_Ensure();
|
||||
func = (PyObject *) python_callback;
|
||||
py_edns = SWIG_NewPointerObj((void*) edns, SWIGTYPE_p_edns_data, 0);
|
||||
py_qstate = SWIG_NewPointerObj((void*) qstate,
|
||||
SWIGTYPE_p_module_qstate, 0);
|
||||
@@ -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_t* cb, void* cb_arg, struct module_env* env);
|
||||
int inplace_cb_reply_cache_register(
|
||||
inplace_cb_reply_func_t* cb, void* cb_arg, struct module_env* env);
|
||||
int inplace_cb_reply_local_register(
|
||||
inplace_cb_reply_func_t* cb, void* cb_arg, struct module_env* env);
|
||||
int inplace_cb_reply_servfail_register(
|
||||
inplace_cb_reply_func_t* 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);
|
||||
|
||||
+36
-34
@@ -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.
|
||||
@@ -41,8 +41,10 @@
|
||||
/* ignore the varargs unused warning from SWIGs internal vararg support */
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic ignored "-Wunused-parameter"
|
||||
#ifndef __clang__
|
||||
#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include "config.h"
|
||||
#include "sldns/sbuffer.h"
|
||||
@@ -63,7 +65,7 @@ typedef void* PyGILState_STATE;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Global state for the module.
|
||||
* Global state for the module.
|
||||
*/
|
||||
struct pythonmod_env {
|
||||
|
||||
@@ -117,7 +119,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 +135,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 +171,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 +192,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 +205,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 +241,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 +306,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 +328,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 +337,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 +348,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 +374,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 +391,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 +399,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 */
|
||||
|
||||
@@ -74,7 +74,7 @@ int storeQueryInCache(struct module_qstate* qstate, struct query_info* qinfo, st
|
||||
/* Invalidate the message associated with query_info stored in message cache */
|
||||
void invalidateQueryInCache(struct module_qstate* qstate, struct query_info* qinfo)
|
||||
{
|
||||
hashvalue_t h;
|
||||
hashvalue_type h;
|
||||
struct lruhash_entry* e;
|
||||
struct reply_info *r;
|
||||
size_t i, j;
|
||||
|
||||
+1180
File diff suppressed because it is too large
Load Diff
+230
@@ -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 */
|
||||
+2369
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,209 @@
|
||||
/*
|
||||
* services/authzone.h - authoritative zone that is locally hosted.
|
||||
*
|
||||
* Copyright (c) 2017, NLnet Labs. All rights reserved.
|
||||
*
|
||||
* This software is open source.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* Neither the name of the NLNET LABS nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* This file contains the functions for an authority zone. This zone
|
||||
* is queried by the iterator, just like a stub or forward zone, but then
|
||||
* the data is locally held.
|
||||
*/
|
||||
|
||||
#ifndef SERVICES_AUTHZONE_H
|
||||
#define SERVICES_AUTHZONE_H
|
||||
#include "util/rbtree.h"
|
||||
#include "util/locks.h"
|
||||
struct ub_packed_rrset_key;
|
||||
struct regional;
|
||||
struct config_file;
|
||||
struct query_info;
|
||||
struct dns_msg;
|
||||
|
||||
/**
|
||||
* Authoritative zones, shared.
|
||||
*/
|
||||
struct auth_zones {
|
||||
/** lock on the authzone tree */
|
||||
lock_rw_type lock;
|
||||
/** rbtree of struct auth_zone */
|
||||
rbtree_type ztree;
|
||||
};
|
||||
|
||||
/**
|
||||
* Auth zone. Authoritative data, that is fetched from instead of sending
|
||||
* packets to the internet.
|
||||
*/
|
||||
struct auth_zone {
|
||||
/** rbtree node, key is name and class */
|
||||
rbnode_type node;
|
||||
|
||||
/** zone name, in uncompressed wireformat */
|
||||
uint8_t* name;
|
||||
/** length of zone name */
|
||||
size_t namelen;
|
||||
/** number of labels in zone name */
|
||||
int namelabs;
|
||||
/** the class of this zone, in host byteorder.
|
||||
* uses 'dclass' to not conflict with c++ keyword class. */
|
||||
uint16_t dclass;
|
||||
|
||||
/** lock on the data in the structure
|
||||
* For the node, parent, name, namelen, namelabs, dclass, you
|
||||
* need to also hold the zones_tree lock to change them (or to
|
||||
* delete this zone) */
|
||||
lock_rw_type lock;
|
||||
|
||||
/** auth data for this zone
|
||||
* rbtree of struct auth_data */
|
||||
rbtree_type data;
|
||||
|
||||
/* zonefile name (or NULL for no zonefile) */
|
||||
char* zonefile;
|
||||
/* fallback to the internet on failure or ttl-expiry of auth zone */
|
||||
int fallback_enabled;
|
||||
};
|
||||
|
||||
/**
|
||||
* Auth data. One domain name, and the RRs to go with it.
|
||||
*/
|
||||
struct auth_data {
|
||||
/** rbtree node, key is name only */
|
||||
rbnode_type node;
|
||||
/** domain name */
|
||||
uint8_t* name;
|
||||
/** length of name */
|
||||
size_t namelen;
|
||||
/** number of labels in name */
|
||||
int namelabs;
|
||||
/** the data rrsets, with different types, linked list.
|
||||
* if the list if NULL the node would be an empty non-terminal,
|
||||
* but in this data structure such nodes that represent an empty
|
||||
* non-terminal are not needed; they just don't exist.
|
||||
*/
|
||||
struct auth_rrset* rrsets;
|
||||
};
|
||||
|
||||
/**
|
||||
* A auth data RRset
|
||||
*/
|
||||
struct auth_rrset {
|
||||
/** next in list */
|
||||
struct auth_rrset* next;
|
||||
/** RR type in host byteorder */
|
||||
uint16_t type;
|
||||
/** RRset data item */
|
||||
struct packed_rrset_data* data;
|
||||
};
|
||||
|
||||
/**
|
||||
* Create auth zones structure
|
||||
*/
|
||||
struct auth_zones* auth_zones_create(void);
|
||||
|
||||
/**
|
||||
* Apply configuration to auth zones. Reads zonefiles.
|
||||
*/
|
||||
int auth_zones_apply_config(struct auth_zones* az, struct config_file* cfg);
|
||||
|
||||
/**
|
||||
* Delete auth zones structure
|
||||
*/
|
||||
void auth_zones_delete(struct auth_zones* az);
|
||||
|
||||
/**
|
||||
* Write auth zone data to file, in zonefile format.
|
||||
*/
|
||||
int auth_zone_write_file(struct auth_zone* z, const char* fname);
|
||||
|
||||
/**
|
||||
* Use auth zones to lookup the answer to a query.
|
||||
* The query is from the iterator. And the auth zones attempts to provide
|
||||
* the answer instead of going to the internet.
|
||||
*
|
||||
* @param az: auth zones structure.
|
||||
* @param qinfo: query info to lookup.
|
||||
* @param region: region to use to allocate the reply in.
|
||||
* @param msg: reply is stored here (if one).
|
||||
* @param fallback: if true, fallback to making a query to the internet.
|
||||
* @param dp_nm: name of delegation point to look for. This zone is used
|
||||
* to answer the query.
|
||||
* If the dp_nm is not found, fallback is set to true and false returned.
|
||||
* @param dp_nmlen: length of dp_nm.
|
||||
* @return 0: failure (an error of some sort, like servfail).
|
||||
* if 0 and fallback is true, fallback to the internet.
|
||||
* if 0 and fallback is false, like getting servfail.
|
||||
* If true, an answer is available.
|
||||
*/
|
||||
int auth_zones_lookup(struct auth_zones* az, struct query_info* qinfo,
|
||||
struct regional* region, struct dns_msg** msg, int* fallback,
|
||||
uint8_t* dp_nm, size_t dp_nmlen);
|
||||
|
||||
/**
|
||||
* Find the auth zone that is above the given qname.
|
||||
* Return NULL when there is no auth_zone above the give name, otherwise
|
||||
* returns the closest auth_zone above the qname that pertains to it.
|
||||
* @param az: auth zones structure.
|
||||
* @param qinfo: query info to lookup.
|
||||
* @return NULL or auth_zone that pertains to the query.
|
||||
*/
|
||||
struct auth_zone* auth_zones_find_zone(struct auth_zones* az,
|
||||
struct query_info* qinfo);
|
||||
|
||||
/** find an auth zone by name (exact match by name or NULL returned) */
|
||||
struct auth_zone* auth_zone_find(struct auth_zones* az, uint8_t* nm,
|
||||
size_t nmlen, uint16_t dclass);
|
||||
|
||||
/** create an auth zone. returns wrlocked zone. caller must have wrlock
|
||||
* on az. returns NULL on malloc failure */
|
||||
struct auth_zone* auth_zone_create(struct auth_zones* az, uint8_t* nm,
|
||||
size_t nmlen, uint16_t dclass);
|
||||
|
||||
/** set auth zone zonefile string. caller must have lock on zone */
|
||||
int auth_zone_set_zonefile(struct auth_zone* z, char* zonefile);
|
||||
|
||||
/** set auth zone fallback. caller must have lock on zone.
|
||||
* fallbackstr is "yes" or "no". false on parse failure. */
|
||||
int auth_zone_set_fallback(struct auth_zone* z, char* fallbackstr);
|
||||
|
||||
/** read auth zone from zonefile. caller must lock zone. false on failure */
|
||||
int auth_zone_read_zonefile(struct auth_zone* z);
|
||||
|
||||
/** compare auth_zones for sorted rbtree */
|
||||
int auth_zone_cmp(const void* z1, const void* z2);
|
||||
|
||||
/** compare auth_data for sorted rbtree */
|
||||
int auth_data_cmp(const void* z1, const void* z2);
|
||||
|
||||
#endif /* SERVICES_AUTHZONE_H */
|
||||
Vendored
+21
-12
@@ -41,6 +41,7 @@
|
||||
#include "config.h"
|
||||
#include "iterator/iter_delegpt.h"
|
||||
#include "validator/val_nsec.h"
|
||||
#include "validator/val_utils.h"
|
||||
#include "services/cache/dns.h"
|
||||
#include "services/cache/rrset.h"
|
||||
#include "util/data/msgreply.h"
|
||||
@@ -106,7 +107,7 @@ store_rrsets(struct module_env* env, struct reply_info* rep, time_t now,
|
||||
|
||||
void
|
||||
dns_cache_store_msg(struct module_env* env, struct query_info* qinfo,
|
||||
hashvalue_t hash, struct reply_info* rep, time_t leeway, int pside,
|
||||
hashvalue_type hash, struct reply_info* rep, time_t leeway, int pside,
|
||||
struct reply_info* qrep, struct regional* region)
|
||||
{
|
||||
struct msgreply_entry* e;
|
||||
@@ -182,13 +183,13 @@ addr_to_additional(struct ub_packed_rrset_key* rrset, struct regional* region,
|
||||
}
|
||||
|
||||
/** lookup message in message cache */
|
||||
static struct msgreply_entry*
|
||||
struct msgreply_entry*
|
||||
msg_cache_lookup(struct module_env* env, uint8_t* qname, size_t qnamelen,
|
||||
uint16_t qtype, uint16_t qclass, uint16_t flags, time_t now, int wr)
|
||||
{
|
||||
struct lruhash_entry* e;
|
||||
struct query_info k;
|
||||
hashvalue_t h;
|
||||
hashvalue_type h;
|
||||
|
||||
k.qname = qname;
|
||||
k.qname_len = qnamelen;
|
||||
@@ -479,8 +480,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 +525,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;
|
||||
}
|
||||
|
||||
@@ -709,7 +712,7 @@ dns_cache_lookup(struct module_env* env,
|
||||
{
|
||||
struct lruhash_entry* e;
|
||||
struct query_info k;
|
||||
hashvalue_t h;
|
||||
hashvalue_type h;
|
||||
time_t now = *env->now;
|
||||
struct ub_packed_rrset_key* rrset;
|
||||
|
||||
@@ -753,10 +756,16 @@ dns_cache_lookup(struct module_env* env,
|
||||
if( qtype != LDNS_RR_TYPE_DS &&
|
||||
(rrset=rrset_cache_lookup(env->rrset_cache, qname, qnamelen,
|
||||
LDNS_RR_TYPE_CNAME, qclass, 0, now, 0))) {
|
||||
struct dns_msg* msg = rrset_msg(rrset, region, now, &k);
|
||||
if(msg) {
|
||||
lock_rw_unlock(&rrset->entry.lock);
|
||||
return msg;
|
||||
uint8_t* wc = NULL;
|
||||
/* if the rrset is not a wildcard expansion, with wcname */
|
||||
/* because, if we return that CNAME rrset on its own, it is
|
||||
* missing the NSEC or NSEC3 proof */
|
||||
if(!(val_rrset_wildcard(rrset, &wc) && wc != NULL)) {
|
||||
struct dns_msg* msg = rrset_msg(rrset, region, now, &k);
|
||||
if(msg) {
|
||||
lock_rw_unlock(&rrset->entry.lock);
|
||||
return msg;
|
||||
}
|
||||
}
|
||||
lock_rw_unlock(&rrset->entry.lock);
|
||||
}
|
||||
@@ -865,7 +874,7 @@ dns_cache_store(struct module_env* env, struct query_info* msgqinf,
|
||||
} else {
|
||||
/* store msg, and rrsets */
|
||||
struct query_info qinf;
|
||||
hashvalue_t h;
|
||||
hashvalue_type h;
|
||||
|
||||
qinf = *msgqinf;
|
||||
qinf.qname = memdup(msgqinf->qname, msgqinf->qname_len);
|
||||
|
||||
Vendored
+21
-1
@@ -106,7 +106,7 @@ int dns_cache_store(struct module_env* env, struct query_info* qinf,
|
||||
* @param region: to allocate into for qmsg.
|
||||
*/
|
||||
void dns_cache_store_msg(struct module_env* env, struct query_info* qinfo,
|
||||
hashvalue_t hash, struct reply_info* rep, time_t leeway, int pside,
|
||||
hashvalue_type hash, struct reply_info* rep, time_t leeway, int pside,
|
||||
struct reply_info* qrep, struct regional* region);
|
||||
|
||||
/**
|
||||
@@ -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.
|
||||
@@ -194,4 +208,10 @@ int dns_msg_authadd(struct dns_msg* msg, struct regional* region,
|
||||
int dns_cache_prefetch_adjust(struct module_env* env, struct query_info* qinfo,
|
||||
time_t adjust, uint16_t flags);
|
||||
|
||||
/** lookup message in message cache
|
||||
* the returned nonNULL entry is locked and has to be unlocked by the caller */
|
||||
struct msgreply_entry* msg_cache_lookup(struct module_env* env,
|
||||
uint8_t* qname, size_t qnamelen, uint16_t qtype, uint16_t qclass,
|
||||
uint16_t flags, time_t now, int wr);
|
||||
|
||||
#endif /* SERVICES_CACHE_DNS_H */
|
||||
|
||||
Vendored
+132
-11
@@ -61,6 +61,10 @@
|
||||
/** ratelimit value for delegation point */
|
||||
int infra_dp_ratelimit = 0;
|
||||
|
||||
/** ratelimit value for client ip addresses,
|
||||
* in queries per second. */
|
||||
int infra_ip_ratelimit = 0;
|
||||
|
||||
size_t
|
||||
infra_sizefunc(void* k, void* ATTR_UNUSED(d))
|
||||
{
|
||||
@@ -244,11 +248,19 @@ infra_create(struct config_file* cfg)
|
||||
}
|
||||
name_tree_init_parents(&infra->domain_limits);
|
||||
}
|
||||
infra_ip_ratelimit = cfg->ip_ratelimit;
|
||||
infra->client_ip_rates = slabhash_create(cfg->ratelimit_slabs,
|
||||
INFRA_HOST_STARTSIZE, cfg->ip_ratelimit_size, &ip_rate_sizefunc,
|
||||
&ip_rate_compfunc, &ip_rate_delkeyfunc, &ip_rate_deldatafunc, NULL);
|
||||
if(!infra->client_ip_rates) {
|
||||
infra_delete(infra);
|
||||
return NULL;
|
||||
}
|
||||
return infra;
|
||||
}
|
||||
|
||||
/** delete domain_limit entries */
|
||||
static void domain_limit_free(rbnode_t* n, void* ATTR_UNUSED(arg))
|
||||
static void domain_limit_free(rbnode_type* n, void* ATTR_UNUSED(arg))
|
||||
{
|
||||
if(n) {
|
||||
free(((struct domain_limit_data*)n)->node.name);
|
||||
@@ -264,6 +276,7 @@ infra_delete(struct infra_cache* infra)
|
||||
slabhash_delete(infra->hosts);
|
||||
slabhash_delete(infra->domain_rates);
|
||||
traverse_postorder(&infra->domain_limits, domain_limit_free, NULL);
|
||||
slabhash_delete(infra->client_ip_rates);
|
||||
free(infra);
|
||||
}
|
||||
|
||||
@@ -284,31 +297,38 @@ infra_adjust(struct infra_cache* infra, struct config_file* cfg)
|
||||
return infra;
|
||||
}
|
||||
|
||||
/** calculate the hash value for a host key */
|
||||
static hashvalue_t
|
||||
hash_addr(struct sockaddr_storage* addr, socklen_t addrlen)
|
||||
/** calculate the hash value for a host key
|
||||
* set use_port to a non-0 number to use the port in
|
||||
* the hash calculation; 0 to ignore the port.*/
|
||||
static hashvalue_type
|
||||
hash_addr(struct sockaddr_storage* addr, socklen_t addrlen,
|
||||
int use_port)
|
||||
{
|
||||
hashvalue_t h = 0xab;
|
||||
hashvalue_type h = 0xab;
|
||||
/* select the pieces to hash, some OS have changing data inside */
|
||||
if(addr_is_ip6(addr, addrlen)) {
|
||||
struct sockaddr_in6* in6 = (struct sockaddr_in6*)addr;
|
||||
h = hashlittle(&in6->sin6_family, sizeof(in6->sin6_family), h);
|
||||
h = hashlittle(&in6->sin6_port, sizeof(in6->sin6_port), h);
|
||||
if(use_port){
|
||||
h = hashlittle(&in6->sin6_port, sizeof(in6->sin6_port), h);
|
||||
}
|
||||
h = hashlittle(&in6->sin6_addr, INET6_SIZE, h);
|
||||
} else {
|
||||
struct sockaddr_in* in = (struct sockaddr_in*)addr;
|
||||
h = hashlittle(&in->sin_family, sizeof(in->sin_family), h);
|
||||
h = hashlittle(&in->sin_port, sizeof(in->sin_port), h);
|
||||
if(use_port){
|
||||
h = hashlittle(&in->sin_port, sizeof(in->sin_port), h);
|
||||
}
|
||||
h = hashlittle(&in->sin_addr, INET_SIZE, h);
|
||||
}
|
||||
return h;
|
||||
}
|
||||
|
||||
/** calculate infra hash for a key */
|
||||
static hashvalue_t
|
||||
static hashvalue_type
|
||||
hash_infra(struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* name)
|
||||
{
|
||||
return dname_query_hash(name, hash_addr(addr, addrlen));
|
||||
return dname_query_hash(name, hash_addr(addr, addrlen, 1));
|
||||
}
|
||||
|
||||
/** lookup version that does not check host ttl (you check it) */
|
||||
@@ -726,12 +746,36 @@ int infra_find_ratelimit(struct infra_cache* infra, uint8_t* name,
|
||||
return infra_dp_ratelimit;
|
||||
}
|
||||
|
||||
size_t ip_rate_sizefunc(void* k, void* ATTR_UNUSED(d))
|
||||
{
|
||||
struct ip_rate_key* key = (struct ip_rate_key*)k;
|
||||
return sizeof(*key) + sizeof(struct ip_rate_data)
|
||||
+ lock_get_mem(&key->entry.lock);
|
||||
}
|
||||
|
||||
int ip_rate_compfunc(void* key1, void* key2)
|
||||
{
|
||||
struct ip_rate_key* k1 = (struct ip_rate_key*)key1;
|
||||
struct ip_rate_key* k2 = (struct ip_rate_key*)key2;
|
||||
return sockaddr_cmp_addr(&k1->addr, k1->addrlen,
|
||||
&k2->addr, k2->addrlen);
|
||||
}
|
||||
|
||||
void ip_rate_delkeyfunc(void* k, void* ATTR_UNUSED(arg))
|
||||
{
|
||||
struct ip_rate_key* key = (struct ip_rate_key*)k;
|
||||
if(!key)
|
||||
return;
|
||||
lock_rw_destroy(&key->entry.lock);
|
||||
free(key);
|
||||
}
|
||||
|
||||
/** find data item in array, for write access, caller unlocks */
|
||||
static struct lruhash_entry* infra_find_ratedata(struct infra_cache* infra,
|
||||
uint8_t* name, size_t namelen, int wr)
|
||||
{
|
||||
struct rate_key key;
|
||||
hashvalue_t h = dname_query_hash(name, 0xab);
|
||||
hashvalue_type h = dname_query_hash(name, 0xab);
|
||||
memset(&key, 0, sizeof(key));
|
||||
key.name = name;
|
||||
key.namelen = namelen;
|
||||
@@ -739,11 +783,25 @@ static struct lruhash_entry* infra_find_ratedata(struct infra_cache* infra,
|
||||
return slabhash_lookup(infra->domain_rates, h, &key, wr);
|
||||
}
|
||||
|
||||
/** find data item in array for ip addresses */
|
||||
struct lruhash_entry* infra_find_ip_ratedata(struct infra_cache* infra,
|
||||
struct comm_reply* repinfo, int wr)
|
||||
{
|
||||
struct ip_rate_key key;
|
||||
hashvalue_type h = hash_addr(&(repinfo->addr),
|
||||
repinfo->addrlen, 0);
|
||||
memset(&key, 0, sizeof(key));
|
||||
key.addr = repinfo->addr;
|
||||
key.addrlen = repinfo->addrlen;
|
||||
key.entry.hash = h;
|
||||
return slabhash_lookup(infra->client_ip_rates, h, &key, wr);
|
||||
}
|
||||
|
||||
/** create rate data item for name, number 1 in now */
|
||||
static void infra_create_ratedata(struct infra_cache* infra,
|
||||
uint8_t* name, size_t namelen, time_t timenow)
|
||||
{
|
||||
hashvalue_t h = dname_query_hash(name, 0xab);
|
||||
hashvalue_type h = dname_query_hash(name, 0xab);
|
||||
struct rate_key* k = (struct rate_key*)calloc(1, sizeof(*k));
|
||||
struct rate_data* d = (struct rate_data*)calloc(1, sizeof(*d));
|
||||
if(!k || !d) {
|
||||
@@ -767,6 +825,30 @@ static void infra_create_ratedata(struct infra_cache* infra,
|
||||
slabhash_insert(infra->domain_rates, h, &k->entry, d, NULL);
|
||||
}
|
||||
|
||||
/** create rate data item for ip address */
|
||||
static void infra_ip_create_ratedata(struct infra_cache* infra,
|
||||
struct comm_reply* repinfo, time_t timenow)
|
||||
{
|
||||
hashvalue_type h = hash_addr(&(repinfo->addr),
|
||||
repinfo->addrlen, 0);
|
||||
struct ip_rate_key* k = (struct ip_rate_key*)calloc(1, sizeof(*k));
|
||||
struct ip_rate_data* d = (struct ip_rate_data*)calloc(1, sizeof(*d));
|
||||
if(!k || !d) {
|
||||
free(k);
|
||||
free(d);
|
||||
return; /* alloc failure */
|
||||
}
|
||||
k->addr = repinfo->addr;
|
||||
k->addrlen = repinfo->addrlen;
|
||||
lock_rw_init(&k->entry.lock);
|
||||
k->entry.hash = h;
|
||||
k->entry.key = k;
|
||||
k->entry.data = d;
|
||||
d->qps[0] = 1;
|
||||
d->timestamp[0] = timenow;
|
||||
slabhash_insert(infra->client_ip_rates, h, &k->entry, d, NULL);
|
||||
}
|
||||
|
||||
/** find the second and return its rate counter, if none, remove oldest */
|
||||
static int* infra_rate_find_second(void* data, time_t t)
|
||||
{
|
||||
@@ -811,6 +893,8 @@ int infra_ratelimit_inc(struct infra_cache* infra, uint8_t* name,
|
||||
|
||||
/* find ratelimit */
|
||||
lim = infra_find_ratelimit(infra, name, namelen);
|
||||
if(!lim)
|
||||
return 1; /* disabled for this domain */
|
||||
|
||||
/* find or insert ratedata */
|
||||
entry = infra_find_ratedata(infra, name, namelen, 1);
|
||||
@@ -859,6 +943,8 @@ int infra_ratelimit_exceeded(struct infra_cache* infra, uint8_t* name,
|
||||
|
||||
/* find ratelimit */
|
||||
lim = infra_find_ratelimit(infra, name, namelen);
|
||||
if(!lim)
|
||||
return 0; /* disabled for this domain */
|
||||
|
||||
/* find current rate */
|
||||
entry = infra_find_ratedata(infra, name, namelen, 0);
|
||||
@@ -875,6 +961,41 @@ infra_get_mem(struct infra_cache* infra)
|
||||
{
|
||||
size_t s = sizeof(*infra) + slabhash_get_mem(infra->hosts);
|
||||
if(infra->domain_rates) s += slabhash_get_mem(infra->domain_rates);
|
||||
if(infra->client_ip_rates) s += slabhash_get_mem(infra->client_ip_rates);
|
||||
/* ignore domain_limits because walk through tree is big */
|
||||
return s;
|
||||
}
|
||||
|
||||
int infra_ip_ratelimit_inc(struct infra_cache* infra,
|
||||
struct comm_reply* repinfo, time_t timenow)
|
||||
{
|
||||
int max;
|
||||
struct lruhash_entry* entry;
|
||||
|
||||
/* not enabled */
|
||||
if(!infra_ip_ratelimit) {
|
||||
return 1;
|
||||
}
|
||||
/* find or insert ratedata */
|
||||
entry = infra_find_ip_ratedata(infra, repinfo, 1);
|
||||
if(entry) {
|
||||
int premax = infra_rate_max(entry->data, timenow);
|
||||
int* cur = infra_rate_find_second(entry->data, timenow);
|
||||
(*cur)++;
|
||||
max = infra_rate_max(entry->data, timenow);
|
||||
lock_rw_unlock(&entry->lock);
|
||||
|
||||
if(premax < infra_ip_ratelimit && max >= infra_ip_ratelimit) {
|
||||
char client_ip[128];
|
||||
addr_to_str((struct sockaddr_storage *)&repinfo->addr,
|
||||
repinfo->addrlen, client_ip, sizeof(client_ip));
|
||||
verbose(VERB_OPS, "ratelimit exceeded %s %d", client_ip,
|
||||
infra_ip_ratelimit);
|
||||
}
|
||||
return (max <= infra_ip_ratelimit);
|
||||
}
|
||||
|
||||
/* create */
|
||||
infra_ip_create_ratedata(infra, repinfo, timenow);
|
||||
return 1;
|
||||
}
|
||||
|
||||
Vendored
+49
-3
@@ -36,7 +36,10 @@
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* This file contains the infrastructure cache.
|
||||
* This file contains the infrastructure cache, as well as rate limiting.
|
||||
* Note that there are two sorts of rate-limiting here:
|
||||
* - Pre-cache, per-query rate limiting (query ratelimits)
|
||||
* - Post-cache, per-domain name rate limiting (infra-ratelimits)
|
||||
*/
|
||||
|
||||
#ifndef SERVICES_CACHE_INFRA_H
|
||||
@@ -44,6 +47,8 @@
|
||||
#include "util/storage/lruhash.h"
|
||||
#include "util/storage/dnstree.h"
|
||||
#include "util/rtt.h"
|
||||
#include "util/netevent.h"
|
||||
#include "util/data/msgreply.h"
|
||||
struct slabhash;
|
||||
struct config_file;
|
||||
|
||||
@@ -112,7 +117,9 @@ struct infra_cache {
|
||||
/** hash table with query rates per name: rate_key, rate_data */
|
||||
struct slabhash* domain_rates;
|
||||
/** ratelimit settings for domains, struct domain_limit_data */
|
||||
rbtree_t domain_limits;
|
||||
rbtree_type domain_limits;
|
||||
/** hash table with query rates per client ip: ip_rate_key, ip_rate_data */
|
||||
struct slabhash* client_ip_rates;
|
||||
};
|
||||
|
||||
/** ratelimit, unless overridden by domain_limits, 0 is off */
|
||||
@@ -142,6 +149,21 @@ struct rate_key {
|
||||
size_t namelen;
|
||||
};
|
||||
|
||||
/** ip ratelimit, 0 is off */
|
||||
extern int infra_ip_ratelimit;
|
||||
|
||||
/**
|
||||
* key for ip_ratelimit lookups, a source IP.
|
||||
*/
|
||||
struct ip_rate_key {
|
||||
/** lruhash key entry */
|
||||
struct lruhash_entry entry;
|
||||
/** client ip information */
|
||||
struct sockaddr_storage addr;
|
||||
/** length of address */
|
||||
socklen_t addrlen;
|
||||
};
|
||||
|
||||
/** number of seconds to track qps rate */
|
||||
#define RATE_WINDOW 2
|
||||
|
||||
@@ -160,6 +182,8 @@ struct rate_data {
|
||||
time_t timestamp[RATE_WINDOW];
|
||||
};
|
||||
|
||||
#define ip_rate_data rate_data
|
||||
|
||||
/** infra host cache default hash lookup size */
|
||||
#define INFRA_HOST_STARTSIZE 32
|
||||
/** bytes per zonename reserved in the hostcache, dnamelen(zonename.com.) */
|
||||
@@ -377,10 +401,20 @@ int infra_ratelimit_exceeded(struct infra_cache* infra, uint8_t* name,
|
||||
/** find the maximum rate stored, not too old. 0 if no information. */
|
||||
int infra_rate_max(void* data, time_t now);
|
||||
|
||||
/** find the ratelimit in qps for a domain */
|
||||
/** find the ratelimit in qps for a domain. 0 if no limit for domain. */
|
||||
int infra_find_ratelimit(struct infra_cache* infra, uint8_t* name,
|
||||
size_t namelen);
|
||||
|
||||
/** Update query ratelimit hash and decide
|
||||
* whether or not a query should be dropped.
|
||||
* @param infra: infra cache
|
||||
* @param repinfo: information about client
|
||||
* @param timenow: what time it is now.
|
||||
* @return 1 if it could be incremented. 0 if the increment overshot the
|
||||
* ratelimit and the query should be dropped. */
|
||||
int infra_ip_ratelimit_inc(struct infra_cache* infra,
|
||||
struct comm_reply* repinfo, time_t timenow);
|
||||
|
||||
/**
|
||||
* Get memory used by the infra cache.
|
||||
* @param infra: infrastructure cache.
|
||||
@@ -413,4 +447,16 @@ void rate_delkeyfunc(void* k, void* arg);
|
||||
/** delete data */
|
||||
void rate_deldatafunc(void* d, void* arg);
|
||||
|
||||
/* calculate size for the client ip hashtable */
|
||||
size_t ip_rate_sizefunc(void* k, void* d);
|
||||
|
||||
/* compare two addresses */
|
||||
int ip_rate_compfunc(void* key1, void* key2);
|
||||
|
||||
/* delete key, and destroy the lock */
|
||||
void ip_rate_delkeyfunc(void* d, void* arg);
|
||||
|
||||
/* delete data */
|
||||
#define ip_rate_deldatafunc rate_deldatafunc
|
||||
|
||||
#endif /* SERVICES_CACHE_INFRA_H */
|
||||
|
||||
Vendored
+5
-5
@@ -91,7 +91,7 @@ struct rrset_cache* rrset_cache_adjust(struct rrset_cache *r,
|
||||
|
||||
void
|
||||
rrset_cache_touch(struct rrset_cache* r, struct ub_packed_rrset_key* key,
|
||||
hashvalue_t hash, rrset_id_t id)
|
||||
hashvalue_type hash, rrset_id_type id)
|
||||
{
|
||||
struct lruhash* table = slabhash_gettable(&r->table, hash);
|
||||
/*
|
||||
@@ -186,7 +186,7 @@ rrset_cache_update(struct rrset_cache* r, struct rrset_ref* ref,
|
||||
{
|
||||
struct lruhash_entry* e;
|
||||
struct ub_packed_rrset_key* k = ref->key;
|
||||
hashvalue_t h = k->entry.hash;
|
||||
hashvalue_type h = k->entry.hash;
|
||||
uint16_t rrset_type = ntohs(k->rk.type);
|
||||
int equal = 0;
|
||||
log_assert(ref->id != 0 && k->id != 0);
|
||||
@@ -303,10 +303,10 @@ void
|
||||
rrset_array_unlock_touch(struct rrset_cache* r, struct regional* scratch,
|
||||
struct rrset_ref* ref, size_t count)
|
||||
{
|
||||
hashvalue_t* h;
|
||||
hashvalue_type* h;
|
||||
size_t i;
|
||||
if(count > RR_COUNT_MAX || !(h = (hashvalue_t*)regional_alloc(scratch,
|
||||
sizeof(hashvalue_t)*count))) {
|
||||
if(count > RR_COUNT_MAX || !(h = (hashvalue_type*)regional_alloc(
|
||||
scratch, sizeof(hashvalue_type)*count))) {
|
||||
log_warn("rrset LRU: memory allocation failed");
|
||||
h = NULL;
|
||||
} else /* store hash values */
|
||||
|
||||
Vendored
+1
-1
@@ -102,7 +102,7 @@ struct rrset_cache* rrset_cache_adjust(struct rrset_cache* r,
|
||||
* @param id: used to check that the item is unchanged and not deleted.
|
||||
*/
|
||||
void rrset_cache_touch(struct rrset_cache* r, struct ub_packed_rrset_key* key,
|
||||
hashvalue_t hash, rrset_id_t id);
|
||||
hashvalue_type hash, rrset_id_type id);
|
||||
|
||||
/**
|
||||
* Update an rrset in the rrset cache. Stores the information for later use.
|
||||
|
||||
+211
-34
@@ -63,6 +63,10 @@
|
||||
#include <sys/un.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SYSTEMD
|
||||
#include <systemd/sd-daemon.h>
|
||||
#endif
|
||||
|
||||
/** number of queued TCP connections for listen() */
|
||||
#define TCP_BACKLOG 256
|
||||
|
||||
@@ -96,11 +100,71 @@ verbose_print_addr(struct addrinfo *addr)
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HAVE_SYSTEMD
|
||||
static int
|
||||
systemd_get_activated(int family, int socktype, int listen,
|
||||
struct sockaddr *addr, socklen_t addrlen,
|
||||
const char *path)
|
||||
{
|
||||
int i = 0;
|
||||
int r = 0;
|
||||
int s = -1;
|
||||
const char* listen_pid, *listen_fds;
|
||||
|
||||
/* We should use "listen" option only for stream protocols. For UDP it should be -1 */
|
||||
|
||||
if((r = sd_booted()) < 1) {
|
||||
if(r == 0)
|
||||
log_warn("systemd is not running");
|
||||
else
|
||||
log_err("systemd sd_booted(): %s", strerror(-r));
|
||||
return -1;
|
||||
}
|
||||
|
||||
listen_pid = getenv("LISTEN_PID");
|
||||
listen_fds = getenv("LISTEN_FDS");
|
||||
|
||||
if (!listen_pid) {
|
||||
log_warn("Systemd mandatory ENV variable is not defined: LISTEN_PID");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!listen_fds) {
|
||||
log_warn("Systemd mandatory ENV variable is not defined: LISTEN_FDS");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if((r = sd_listen_fds(0)) < 1) {
|
||||
if(r == 0)
|
||||
log_warn("systemd: did not return socket, check unit configuration");
|
||||
else
|
||||
log_err("systemd sd_listen_fds(): %s", strerror(-r));
|
||||
return -1;
|
||||
}
|
||||
|
||||
for(i = 0; i < r; i++) {
|
||||
if(sd_is_socket(SD_LISTEN_FDS_START + i, family, socktype, listen)) {
|
||||
s = SD_LISTEN_FDS_START + i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (s == -1) {
|
||||
if (addr)
|
||||
log_err_addr("systemd sd_listen_fds()",
|
||||
"no such socket",
|
||||
(struct sockaddr_storage *)addr, addrlen);
|
||||
else
|
||||
log_err("systemd sd_listen_fds(): %s", path);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
create_udp_sock(int family, int socktype, struct sockaddr* addr,
|
||||
socklen_t addrlen, int v6only, int* inuse, int* noproto,
|
||||
int rcv, int snd, int listen, int* reuseport, int transparent,
|
||||
int freebind)
|
||||
int freebind, int use_systemd)
|
||||
{
|
||||
int s;
|
||||
#if defined(SO_REUSEADDR) || defined(SO_REUSEPORT) || defined(IPV6_USE_MIN_MTU) || defined(IP_TRANSPARENT) || defined(IP_BINDANY) || defined(IP_FREEBIND)
|
||||
@@ -123,6 +187,16 @@ create_udp_sock(int family, int socktype, struct sockaddr* addr,
|
||||
#endif
|
||||
#if !defined(IP_FREEBIND)
|
||||
(void)freebind;
|
||||
#endif
|
||||
#ifdef HAVE_SYSTEMD
|
||||
int got_fd_from_systemd = 0;
|
||||
|
||||
if (!use_systemd
|
||||
|| (use_systemd
|
||||
&& (s = systemd_get_activated(family, socktype, -1, addr,
|
||||
addrlen, NULL)) == -1)) {
|
||||
#else
|
||||
(void)use_systemd;
|
||||
#endif
|
||||
if((s = socket(family, socktype, 0)) == -1) {
|
||||
*inuse = 0;
|
||||
@@ -144,6 +218,11 @@ create_udp_sock(int family, int socktype, struct sockaddr* addr,
|
||||
*noproto = 0;
|
||||
return -1;
|
||||
}
|
||||
#ifdef HAVE_SYSTEMD
|
||||
} else {
|
||||
got_fd_from_systemd = 1;
|
||||
}
|
||||
#endif
|
||||
if(listen) {
|
||||
#ifdef SO_REUSEADDR
|
||||
if(setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (void*)&on,
|
||||
@@ -465,7 +544,11 @@ create_udp_sock(int family, int socktype, struct sockaddr* addr,
|
||||
}
|
||||
# endif /* IPv4 MTU */
|
||||
}
|
||||
if(bind(s, (struct sockaddr*)addr, addrlen) != 0) {
|
||||
if(
|
||||
#ifdef HAVE_SYSTEMD
|
||||
!got_fd_from_systemd &&
|
||||
#endif
|
||||
bind(s, (struct sockaddr*)addr, addrlen) != 0) {
|
||||
*noproto = 0;
|
||||
*inuse = 0;
|
||||
#ifndef USE_WINSOCK
|
||||
@@ -488,7 +571,7 @@ create_udp_sock(int family, int socktype, struct sockaddr* addr,
|
||||
(struct sockaddr_storage*)addr, addrlen);
|
||||
}
|
||||
closesocket(s);
|
||||
#endif
|
||||
#endif /* USE_WINSOCK */
|
||||
return -1;
|
||||
}
|
||||
if(!fd_set_nonblock(s)) {
|
||||
@@ -506,12 +589,15 @@ create_udp_sock(int family, int socktype, struct sockaddr* addr,
|
||||
|
||||
int
|
||||
create_tcp_accept_sock(struct addrinfo *addr, int v6only, int* noproto,
|
||||
int* reuseport, int transparent, int mss, int freebind)
|
||||
int* reuseport, int transparent, int mss, int freebind, int use_systemd)
|
||||
{
|
||||
int s;
|
||||
#if defined(SO_REUSEADDR) || defined(SO_REUSEPORT) || defined(IPV6_V6ONLY) || defined(IP_TRANSPARENT) || defined(IP_BINDANY) || defined(IP_FREEBIND)
|
||||
int on = 1;
|
||||
#endif
|
||||
#ifdef HAVE_SYSTEMD
|
||||
int got_fd_from_systemd = 0;
|
||||
#endif
|
||||
#ifdef USE_TCP_FASTOPEN
|
||||
int qlen;
|
||||
#endif
|
||||
@@ -523,6 +609,15 @@ create_tcp_accept_sock(struct addrinfo *addr, int v6only, int* noproto,
|
||||
#endif
|
||||
verbose_print_addr(addr);
|
||||
*noproto = 0;
|
||||
#ifdef HAVE_SYSTEMD
|
||||
if (!use_systemd ||
|
||||
(use_systemd
|
||||
&& (s = systemd_get_activated(addr->ai_family, addr->ai_socktype, 1,
|
||||
addr->ai_addr, addr->ai_addrlen,
|
||||
NULL)) == -1)) {
|
||||
#else
|
||||
(void)use_systemd;
|
||||
#endif
|
||||
if((s = socket(addr->ai_family, addr->ai_socktype, 0)) == -1) {
|
||||
#ifndef USE_WINSOCK
|
||||
if(errno == EAFNOSUPPORT || errno == EPROTONOSUPPORT) {
|
||||
@@ -560,6 +655,11 @@ create_tcp_accept_sock(struct addrinfo *addr, int v6only, int* noproto,
|
||||
log_warn(" setsockopt(TCP_MAXSEG) unsupported");
|
||||
#endif /* defined(IPPROTO_TCP) && defined(TCP_MAXSEG) */
|
||||
}
|
||||
#ifdef HAVE_SYSTEMD
|
||||
} else {
|
||||
got_fd_from_systemd = 1;
|
||||
}
|
||||
#endif
|
||||
#ifdef SO_REUSEADDR
|
||||
if(setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (void*)&on,
|
||||
(socklen_t)sizeof(on)) < 0) {
|
||||
@@ -637,7 +737,11 @@ create_tcp_accept_sock(struct addrinfo *addr, int v6only, int* noproto,
|
||||
(addr->ai_family==AF_INET6?"V6":""), strerror(errno));
|
||||
}
|
||||
#endif /* IP_TRANSPARENT || IP_BINDANY */
|
||||
if(bind(s, addr->ai_addr, addr->ai_addrlen) != 0) {
|
||||
if(
|
||||
#ifdef HAVE_SYSTEMD
|
||||
!got_fd_from_systemd &&
|
||||
#endif
|
||||
bind(s, addr->ai_addr, addr->ai_addrlen) != 0) {
|
||||
#ifndef USE_WINSOCK
|
||||
/* detect freebsd jail with no ipv6 permission */
|
||||
if(addr->ai_family==AF_INET6 && errno==EINVAL)
|
||||
@@ -695,11 +799,21 @@ create_tcp_accept_sock(struct addrinfo *addr, int v6only, int* noproto,
|
||||
}
|
||||
|
||||
int
|
||||
create_local_accept_sock(const char *path, int* noproto)
|
||||
create_local_accept_sock(const char *path, int* noproto, int use_systemd)
|
||||
{
|
||||
#ifdef HAVE_SYSTEMD
|
||||
int ret;
|
||||
|
||||
if (use_systemd && (ret = systemd_get_activated(AF_LOCAL, SOCK_STREAM, 1, NULL, 0, path)) != -1)
|
||||
return ret;
|
||||
else {
|
||||
#endif
|
||||
#ifdef HAVE_SYS_UN_H
|
||||
int s;
|
||||
struct sockaddr_un usock;
|
||||
#ifndef HAVE_SYSTEMD
|
||||
(void)use_systemd;
|
||||
#endif
|
||||
|
||||
verbose(VERB_ALGO, "creating unix socket %s", path);
|
||||
#ifdef HAVE_STRUCT_SOCKADDR_UN_SUN_LEN
|
||||
@@ -720,29 +834,42 @@ create_local_accept_sock(const char *path, int* noproto)
|
||||
/* The socket already exists and cannot be removed */
|
||||
log_err("Cannot remove old local socket %s (%s)",
|
||||
path, strerror(errno));
|
||||
return -1;
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (bind(s, (struct sockaddr *)&usock,
|
||||
(socklen_t)sizeof(struct sockaddr_un)) == -1) {
|
||||
log_err("Cannot bind local socket %s (%s)",
|
||||
path, strerror(errno));
|
||||
return -1;
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!fd_set_nonblock(s)) {
|
||||
log_err("Cannot set non-blocking mode");
|
||||
return -1;
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (listen(s, TCP_BACKLOG) == -1) {
|
||||
log_err("can't listen: %s", strerror(errno));
|
||||
return -1;
|
||||
goto err;
|
||||
}
|
||||
|
||||
(void)noproto; /*unused*/
|
||||
return s;
|
||||
|
||||
err:
|
||||
#ifndef USE_WINSOCK
|
||||
close(s);
|
||||
#else
|
||||
closesocket(s);
|
||||
#endif
|
||||
return -1;
|
||||
|
||||
#ifdef HAVE_SYSTEMD
|
||||
}
|
||||
#endif
|
||||
#else
|
||||
(void)use_systemd;
|
||||
(void)path;
|
||||
log_err("Local sockets are not supported");
|
||||
*noproto = 1;
|
||||
@@ -757,7 +884,7 @@ create_local_accept_sock(const char *path, int* noproto)
|
||||
static int
|
||||
make_sock(int stype, const char* ifname, const char* port,
|
||||
struct addrinfo *hints, int v6only, int* noip6, size_t rcv, size_t snd,
|
||||
int* reuseport, int transparent, int tcp_mss, int freebind)
|
||||
int* reuseport, int transparent, int tcp_mss, int freebind, int use_systemd)
|
||||
{
|
||||
struct addrinfo *res = NULL;
|
||||
int r, s, inuse, noproto;
|
||||
@@ -785,7 +912,7 @@ make_sock(int stype, const char* ifname, const char* port,
|
||||
s = create_udp_sock(res->ai_family, res->ai_socktype,
|
||||
(struct sockaddr*)res->ai_addr, res->ai_addrlen,
|
||||
v6only, &inuse, &noproto, (int)rcv, (int)snd, 1,
|
||||
reuseport, transparent, freebind);
|
||||
reuseport, transparent, freebind, use_systemd);
|
||||
if(s == -1 && inuse) {
|
||||
log_err("bind: address already in use");
|
||||
} else if(s == -1 && noproto && hints->ai_family == AF_INET6){
|
||||
@@ -793,7 +920,7 @@ make_sock(int stype, const char* ifname, const char* port,
|
||||
}
|
||||
} else {
|
||||
s = create_tcp_accept_sock(res, v6only, &noproto, reuseport,
|
||||
transparent, tcp_mss, freebind);
|
||||
transparent, tcp_mss, freebind, use_systemd);
|
||||
if(s == -1 && noproto && hints->ai_family == AF_INET6){
|
||||
*noip6 = 1;
|
||||
}
|
||||
@@ -806,7 +933,7 @@ make_sock(int stype, const char* ifname, const char* port,
|
||||
static int
|
||||
make_sock_port(int stype, const char* ifname, const char* port,
|
||||
struct addrinfo *hints, int v6only, int* noip6, size_t rcv, size_t snd,
|
||||
int* reuseport, int transparent, int tcp_mss, int freebind)
|
||||
int* reuseport, int transparent, int tcp_mss, int freebind, int use_systemd)
|
||||
{
|
||||
char* s = strchr(ifname, '@');
|
||||
if(s) {
|
||||
@@ -828,10 +955,10 @@ make_sock_port(int stype, const char* ifname, const char* port,
|
||||
(void)strlcpy(p, s+1, sizeof(p));
|
||||
p[strlen(s+1)]=0;
|
||||
return make_sock(stype, newif, p, hints, v6only, noip6,
|
||||
rcv, snd, reuseport, transparent, tcp_mss, freebind);
|
||||
rcv, snd, reuseport, transparent, tcp_mss, freebind, use_systemd);
|
||||
}
|
||||
return make_sock(stype, ifname, port, hints, v6only, noip6, rcv, snd,
|
||||
reuseport, transparent, tcp_mss, freebind);
|
||||
reuseport, transparent, tcp_mss, freebind, use_systemd);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -881,7 +1008,7 @@ set_recvpktinfo(int s, int family)
|
||||
}
|
||||
# else
|
||||
log_err("no IPV6_RECVPKTINFO and no IPV6_PKTINFO option, please "
|
||||
"disable interface-automatic in config");
|
||||
"disable interface-automatic or do-ip6 in config");
|
||||
return 0;
|
||||
# endif /* defined IPV6_RECVPKTINFO */
|
||||
|
||||
@@ -902,7 +1029,7 @@ set_recvpktinfo(int s, int family)
|
||||
}
|
||||
# else
|
||||
log_err("no IP_SENDSRCADDR or IP_PKTINFO option, please disable "
|
||||
"interface-automatic in config");
|
||||
"interface-automatic or do-ip4 in config");
|
||||
return 0;
|
||||
# endif /* IP_PKTINFO */
|
||||
|
||||
@@ -928,21 +1055,32 @@ set_recvpktinfo(int s, int family)
|
||||
* @param transparent: set IP_TRANSPARENT socket option.
|
||||
* @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 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) {
|
||||
if((s = make_sock_port(SOCK_DGRAM, ifname, port, hints, 1,
|
||||
&noip6, rcv, snd, reuseport, transparent,
|
||||
tcp_mss, freebind)) == -1) {
|
||||
tcp_mss, freebind, use_systemd)) == -1) {
|
||||
if(noip6) {
|
||||
log_warn("IPv6 protocol not available");
|
||||
return 1;
|
||||
@@ -958,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
|
||||
@@ -970,14 +1109,15 @@ ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp,
|
||||
/* regular udp socket */
|
||||
if((s = make_sock_port(SOCK_DGRAM, ifname, port, hints, 1,
|
||||
&noip6, rcv, snd, reuseport, transparent,
|
||||
tcp_mss, freebind)) == -1) {
|
||||
tcp_mss, freebind, use_systemd)) == -1) {
|
||||
if(noip6) {
|
||||
log_warn("IPv6 protocol not available");
|
||||
return 1;
|
||||
}
|
||||
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
|
||||
@@ -992,7 +1132,7 @@ ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp,
|
||||
(!strchr(ifname, '@') && atoi(port) == ssl_port));
|
||||
if((s = make_sock_port(SOCK_STREAM, ifname, port, hints, 1,
|
||||
&noip6, 0, 0, reuseport, transparent, tcp_mss,
|
||||
freebind)) == -1) {
|
||||
freebind, use_systemd)) == -1) {
|
||||
if(noip6) {
|
||||
/*log_warn("IPv6 protocol not available");*/
|
||||
return 1;
|
||||
@@ -1002,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
|
||||
@@ -1036,7 +1176,7 @@ listen_cp_insert(struct comm_point* c, struct listen_dnsport* front)
|
||||
struct listen_dnsport*
|
||||
listen_create(struct comm_base* base, struct listen_port* ports,
|
||||
size_t bufsize, int tcp_accept_count, void* sslctx,
|
||||
struct dt_env* dtenv, comm_point_callback_t* cb, void *cb_arg)
|
||||
struct dt_env* dtenv, comm_point_callback_type* cb, void *cb_arg)
|
||||
{
|
||||
struct listen_dnsport* front = (struct listen_dnsport*)
|
||||
malloc(sizeof(struct listen_dnsport));
|
||||
@@ -1044,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;
|
||||
@@ -1052,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) {
|
||||
@@ -1072,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);
|
||||
@@ -1107,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);
|
||||
}
|
||||
@@ -1150,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->tcp_mss, cfg->ip_freebind, cfg->use_systemd,
|
||||
cfg->dnscrypt_port)) {
|
||||
listening_ports_free(list);
|
||||
return NULL;
|
||||
}
|
||||
@@ -1163,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->tcp_mss, cfg->ip_freebind, cfg->use_systemd,
|
||||
cfg->dnscrypt_port)) {
|
||||
listening_ports_free(list);
|
||||
return NULL;
|
||||
}
|
||||
@@ -1178,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->tcp_mss, cfg->ip_freebind, cfg->use_systemd,
|
||||
cfg->dnscrypt_port)) {
|
||||
listening_ports_free(list);
|
||||
return NULL;
|
||||
}
|
||||
@@ -1191,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->tcp_mss, cfg->ip_freebind, cfg->use_systemd,
|
||||
cfg->dnscrypt_port)) {
|
||||
listening_ports_free(list);
|
||||
return NULL;
|
||||
}
|
||||
@@ -1219,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
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -137,7 +146,7 @@ void listening_ports_free(struct listen_port* list);
|
||||
*/
|
||||
struct listen_dnsport* listen_create(struct comm_base* base,
|
||||
struct listen_port* ports, size_t bufsize, int tcp_accept_count,
|
||||
void* sslctx, struct dt_env *dtenv, comm_point_callback_t* cb,
|
||||
void* sslctx, struct dt_env *dtenv, comm_point_callback_type* cb,
|
||||
void* cb_arg);
|
||||
|
||||
/**
|
||||
@@ -191,11 +200,12 @@ void listen_start_accept(struct listen_dnsport* listen);
|
||||
* listening UDP port. Set to false on return if it failed to do so.
|
||||
* @param transparent: set IP_TRANSPARENT socket option.
|
||||
* @param freebind: set IP_FREEBIND socket option.
|
||||
* @param use_systemd: if true, fetch sockets from systemd.
|
||||
* @return: the socket. -1 on error.
|
||||
*/
|
||||
int create_udp_sock(int family, int socktype, struct sockaddr* addr,
|
||||
socklen_t addrlen, int v6only, int* inuse, int* noproto, int rcv,
|
||||
int snd, int listen, int* reuseport, int transparent, int freebind);
|
||||
int snd, int listen, int* reuseport, int transparent, int freebind, int use_systemd);
|
||||
|
||||
/**
|
||||
* Create and bind TCP listening socket
|
||||
@@ -207,18 +217,20 @@ int create_udp_sock(int family, int socktype, struct sockaddr* addr,
|
||||
* @param transparent: set IP_TRANSPARENT socket option.
|
||||
* @param mss: maximum segment size of the socket. if zero, leaves the default.
|
||||
* @param freebind: set IP_FREEBIND socket option.
|
||||
* @param use_systemd: if true, fetch sockets from systemd.
|
||||
* @return: the socket. -1 on error.
|
||||
*/
|
||||
int create_tcp_accept_sock(struct addrinfo *addr, int v6only, int* noproto,
|
||||
int* reuseport, int transparent, int mss, int freebind);
|
||||
int* reuseport, int transparent, int mss, int freebind, int use_systemd);
|
||||
|
||||
/**
|
||||
* Create and bind local listening socket
|
||||
* @param path: path to the socket.
|
||||
* @param noproto: on error, this is set true if cause is that local sockets
|
||||
* are not supported.
|
||||
* @param use_systemd: if true, fetch sockets from systemd.
|
||||
* @return: the socket. -1 on error.
|
||||
*/
|
||||
int create_local_accept_sock(const char* path, int* noproto);
|
||||
int create_local_accept_sock(const char* path, int* noproto, int use_systemd);
|
||||
|
||||
#endif /* LISTEN_DNSPORT_H */
|
||||
|
||||
+80
-38
@@ -74,7 +74,7 @@ local_zones_create(void)
|
||||
|
||||
/** helper traverse to delete zones */
|
||||
static void
|
||||
lzdel(rbnode_t* n, void* ATTR_UNUSED(arg))
|
||||
lzdel(rbnode_type* n, void* ATTR_UNUSED(arg))
|
||||
{
|
||||
struct local_zone* z = (struct local_zone*)n->key;
|
||||
local_zone_delete(z);
|
||||
@@ -165,7 +165,7 @@ local_zone_create(uint8_t* nm, size_t len, int labs,
|
||||
return NULL;
|
||||
}
|
||||
rbtree_init(&z->data, &local_data_cmp);
|
||||
lock_protect(&z->lock, &z->parent, sizeof(*z)-sizeof(rbnode_t));
|
||||
lock_protect(&z->lock, &z->parent, sizeof(*z)-sizeof(rbnode_type));
|
||||
/* also the zones->lock protects node, parent, name*, class */
|
||||
return z;
|
||||
}
|
||||
@@ -187,7 +187,9 @@ lz_enter_zone_dname(struct local_zones* zones, uint8_t* nm, size_t len,
|
||||
lock_rw_wrlock(&z->lock);
|
||||
if(!rbtree_insert(&zones->ztree, &z->node)) {
|
||||
struct local_zone* oldz;
|
||||
log_warn("duplicate local-zone");
|
||||
char str[256];
|
||||
dname_str(nm, str);
|
||||
log_warn("duplicate local-zone %s", str);
|
||||
lock_rw_unlock(&z->lock);
|
||||
/* save zone name locally before deallocation,
|
||||
* otherwise, nm is gone if we zone_delete now. */
|
||||
@@ -229,9 +231,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 +354,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 +457,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 +514,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 */
|
||||
@@ -629,7 +630,7 @@ lz_enter_override(struct local_zones* zones, char* zname, char* netblock,
|
||||
|
||||
/* create netblock addr_tree if not present yet */
|
||||
if(!z->override_tree) {
|
||||
z->override_tree = (struct rbtree_t*)regional_alloc_zero(
|
||||
z->override_tree = (struct rbtree_type*)regional_alloc_zero(
|
||||
z->region, sizeof(*z->override_tree));
|
||||
if(!z->override_tree) {
|
||||
lock_rw_unlock(&z->lock);
|
||||
@@ -745,12 +746,15 @@ add_as112_default(struct local_zones* zones, struct config_file* cfg,
|
||||
}
|
||||
|
||||
/** enter default zones */
|
||||
static int
|
||||
lz_enter_defaults(struct local_zones* zones, struct config_file* cfg)
|
||||
int local_zone_enter_defaults(struct local_zones* zones, struct config_file* cfg)
|
||||
{
|
||||
struct local_zone* z;
|
||||
const char** zstr;
|
||||
|
||||
/* Do not add any default */
|
||||
if(cfg->local_zones_disable_default)
|
||||
return 1;
|
||||
|
||||
/* this list of zones is from RFC 6303 and RFC 7686 */
|
||||
|
||||
/* block localhost level zones first, then onion and later the LAN zones */
|
||||
@@ -1020,7 +1024,7 @@ local_zones_apply_cfg(struct local_zones* zones, struct config_file* cfg)
|
||||
return 0;
|
||||
}
|
||||
/* apply default zones+content (unless disabled, or overridden) */
|
||||
if(!lz_enter_defaults(zones, cfg)) {
|
||||
if(!local_zone_enter_defaults(zones, cfg)) {
|
||||
return 0;
|
||||
}
|
||||
/* enter local zone overrides */
|
||||
@@ -1060,7 +1064,7 @@ local_zones_tags_lookup(struct local_zones* zones,
|
||||
uint8_t* name, size_t len, int labs, uint16_t dclass,
|
||||
uint8_t* taglist, size_t taglen, int ignoretags)
|
||||
{
|
||||
rbnode_t* res = NULL;
|
||||
rbnode_type* res = NULL;
|
||||
struct local_zone *result;
|
||||
struct local_zone key;
|
||||
int m;
|
||||
@@ -1214,10 +1218,29 @@ local_encode(struct query_info* qinfo, struct module_env* env,
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** encode local error answer */
|
||||
static void
|
||||
local_error_encode(struct query_info* qinfo, struct module_env* env,
|
||||
struct edns_data* edns, sldns_buffer* buf, struct regional* temp,
|
||||
int rcode, int r)
|
||||
{
|
||||
edns->edns_version = EDNS_ADVERTISED_VERSION;
|
||||
edns->udp_size = EDNS_ADVERTISED_SIZE;
|
||||
edns->ext_rcode = 0;
|
||||
edns->bits &= EDNS_DO;
|
||||
|
||||
if(!inplace_cb_reply_local_call(env, qinfo, NULL, NULL,
|
||||
rcode, edns, temp))
|
||||
edns->opt_list = NULL;
|
||||
error_encode(buf, r, qinfo, *(uint16_t*)sldns_buffer_begin(buf),
|
||||
sldns_buffer_read_u16_at(buf, 2), edns);
|
||||
}
|
||||
|
||||
/** 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];
|
||||
@@ -1294,13 +1317,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));
|
||||
@@ -1311,9 +1345,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 */
|
||||
@@ -1414,9 +1446,8 @@ lz_zone_answer(struct local_zone* z, struct module_env* env,
|
||||
return 1;
|
||||
} else if(lz_type == local_zone_refuse
|
||||
|| lz_type == local_zone_always_refuse) {
|
||||
error_encode(buf, (LDNS_RCODE_REFUSED|BIT_AA), qinfo,
|
||||
*(uint16_t*)sldns_buffer_begin(buf),
|
||||
sldns_buffer_read_u16_at(buf, 2), edns);
|
||||
local_error_encode(qinfo, env, edns, buf, temp,
|
||||
LDNS_RCODE_REFUSED, (LDNS_RCODE_REFUSED|BIT_AA));
|
||||
return 1;
|
||||
} else if(lz_type == local_zone_static ||
|
||||
lz_type == local_zone_redirect ||
|
||||
@@ -1433,9 +1464,8 @@ lz_zone_answer(struct local_zone* z, struct module_env* env,
|
||||
if(z->soa)
|
||||
return local_encode(qinfo, env, edns, buf, temp,
|
||||
z->soa, 0, rcode);
|
||||
error_encode(buf, (rcode|BIT_AA), qinfo,
|
||||
*(uint16_t*)sldns_buffer_begin(buf),
|
||||
sldns_buffer_read_u16_at(buf, 2), edns);
|
||||
local_error_encode(qinfo, env, edns, buf, temp, rcode,
|
||||
(rcode|BIT_AA));
|
||||
return 1;
|
||||
} else if(lz_type == local_zone_typetransparent
|
||||
|| lz_type == local_zone_always_transparent) {
|
||||
@@ -1451,9 +1481,8 @@ lz_zone_answer(struct local_zone* z, struct module_env* env,
|
||||
if(z->soa)
|
||||
return local_encode(qinfo, env, edns, buf, temp,
|
||||
z->soa, 0, rcode);
|
||||
error_encode(buf, (rcode|BIT_AA), qinfo,
|
||||
*(uint16_t*)sldns_buffer_begin(buf),
|
||||
sldns_buffer_read_u16_at(buf, 2), edns);
|
||||
local_error_encode(qinfo, env, edns, buf, temp, rcode,
|
||||
(rcode|BIT_AA));
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -1479,11 +1508,9 @@ lz_inform_print(struct local_zone* z, struct query_info* qinfo,
|
||||
static enum localzone_type
|
||||
lz_type(uint8_t *taglist, size_t taglen, uint8_t *taglist2, size_t taglen2,
|
||||
uint8_t *tagactions, size_t tagactionssize, enum localzone_type lzt,
|
||||
struct comm_reply* repinfo, struct rbtree_t* override_tree, int* tag,
|
||||
char** tagname, int num_tags)
|
||||
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(
|
||||
@@ -1496,6 +1523,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++) {
|
||||
@@ -1550,7 +1590,7 @@ local_zones_answer(struct local_zones* zones, struct module_env* env,
|
||||
lock_rw_rdlock(&z->lock);
|
||||
lzt = z->type;
|
||||
}
|
||||
if(!z && !view->isfirst){
|
||||
if(view->local_zones && !z && !view->isfirst){
|
||||
lock_rw_unlock(&view->lock);
|
||||
return 0;
|
||||
}
|
||||
@@ -1635,6 +1675,8 @@ int local_zone_str2type(const char* type, enum localzone_type* t)
|
||||
*t = local_zone_always_refuse;
|
||||
else if(strcmp(type, "always_nxdomain") == 0)
|
||||
*t = local_zone_always_nxdomain;
|
||||
else if(strcmp(type, "nodefault") == 0)
|
||||
*t = local_zone_nodefault;
|
||||
else return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
+124
-7
@@ -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;
|
||||
@@ -95,9 +96,9 @@ enum localzone_type {
|
||||
*/
|
||||
struct local_zones {
|
||||
/** lock on the localzone tree */
|
||||
lock_rw_t lock;
|
||||
lock_rw_type lock;
|
||||
/** rbtree of struct local_zone */
|
||||
rbtree_t ztree;
|
||||
rbtree_type ztree;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -105,7 +106,7 @@ struct local_zones {
|
||||
*/
|
||||
struct local_zone {
|
||||
/** rbtree node, key is name and class */
|
||||
rbnode_t node;
|
||||
rbnode_type node;
|
||||
/** parent zone, if any. */
|
||||
struct local_zone* parent;
|
||||
|
||||
@@ -123,7 +124,7 @@ struct local_zone {
|
||||
* For the node, parent, name, namelen, namelabs, dclass, you
|
||||
* need to also hold the zones_tree lock to change them (or to
|
||||
* delete this zone) */
|
||||
lock_rw_t lock;
|
||||
lock_rw_type lock;
|
||||
|
||||
/** how to process zone */
|
||||
enum localzone_type type;
|
||||
@@ -133,14 +134,14 @@ struct local_zone {
|
||||
size_t taglen;
|
||||
/** netblock addr_tree with struct local_zone_override information
|
||||
* or NULL if there are no override elements */
|
||||
struct rbtree_t* override_tree;
|
||||
struct rbtree_type* override_tree;
|
||||
|
||||
/** in this region the zone's data is allocated.
|
||||
* the struct local_zone itself is malloced. */
|
||||
struct regional* region;
|
||||
/** local data for this zone
|
||||
* rbtree of struct local_data */
|
||||
rbtree_t data;
|
||||
rbtree_type data;
|
||||
/** if data contains zone apex SOA data, this is a ptr to it. */
|
||||
struct ub_packed_rrset_key* soa;
|
||||
};
|
||||
@@ -150,7 +151,7 @@ struct local_zone {
|
||||
*/
|
||||
struct local_data {
|
||||
/** rbtree node, key is name only */
|
||||
rbnode_t node;
|
||||
rbnode_type node;
|
||||
/** domain name */
|
||||
uint8_t* name;
|
||||
/** length of name */
|
||||
@@ -389,4 +390,120 @@ 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);
|
||||
|
||||
/**
|
||||
* Enter defaults to local zone.
|
||||
* @param zones: to add defaults to
|
||||
* @param cfg: containing list of zones to exclude from default set.
|
||||
* @return 1 on success; 0 otherwise.
|
||||
*/
|
||||
int local_zone_enter_defaults(struct local_zones* zones,
|
||||
struct config_file* cfg);
|
||||
|
||||
/**
|
||||
* 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 */
|
||||
|
||||
+155
-42
@@ -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
|
||||
@@ -203,7 +260,7 @@ mesh_create(struct module_stack* stack, struct module_env* env)
|
||||
|
||||
/** help mesh delete delete mesh states */
|
||||
static void
|
||||
mesh_delete_helper(rbnode_t* n)
|
||||
mesh_delete_helper(rbnode_type* n)
|
||||
{
|
||||
struct mesh_state* mstate = (struct mesh_state*)n->key;
|
||||
/* perform a full delete, not only 'cleanup' routine,
|
||||
@@ -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)) {
|
||||
@@ -321,9 +378,10 @@ void mesh_new_client(struct mesh_area* mesh, struct query_info* qinfo,
|
||||
/* see if it already exists, if not, create one */
|
||||
if(!s) {
|
||||
#ifdef UNBOUND_DEBUG
|
||||
struct rbnode_t* n;
|
||||
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,
|
||||
@@ -409,23 +467,25 @@ void mesh_new_client(struct mesh_area* mesh, struct query_info* qinfo,
|
||||
int
|
||||
mesh_new_callback(struct mesh_area* mesh, struct query_info* qinfo,
|
||||
uint16_t qflags, struct edns_data* edns, sldns_buffer* buf,
|
||||
uint16_t qid, mesh_cb_func_t cb, void* cb_arg)
|
||||
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 */
|
||||
if(!s) {
|
||||
#ifdef UNBOUND_DEBUG
|
||||
struct rbnode_t* n;
|
||||
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,10 +536,10 @@ 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_t* n;
|
||||
struct rbnode_type* n;
|
||||
#endif
|
||||
/* already exists, and for a different purpose perhaps.
|
||||
* if mesh_no_list, keep it that way. */
|
||||
@@ -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;
|
||||
@@ -729,7 +799,7 @@ void mesh_detach_subs(struct module_qstate* qstate)
|
||||
struct mesh_area* mesh = qstate->env->mesh;
|
||||
struct mesh_state_ref* ref, lookup;
|
||||
#ifdef UNBOUND_DEBUG
|
||||
struct rbnode_t* n;
|
||||
struct rbnode_type* n;
|
||||
#endif
|
||||
lookup.node.key = &lookup;
|
||||
lookup.s = qstate->mesh_info;
|
||||
@@ -751,24 +821,26 @@ void mesh_detach_subs(struct module_qstate* qstate)
|
||||
rbtree_init(&qstate->mesh_info->sub_set, &mesh_state_ref_compare);
|
||||
}
|
||||
|
||||
int mesh_attach_sub(struct module_qstate* qstate, struct query_info* qinfo,
|
||||
uint16_t qflags, int prime, int valrec, struct module_qstate** newq)
|
||||
int mesh_add_sub(struct module_qstate* qstate, struct query_info* qinfo,
|
||||
uint16_t qflags, int prime, int valrec, struct module_qstate** newq,
|
||||
struct mesh_state** sub)
|
||||
{
|
||||
/* 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);
|
||||
int was_detached;
|
||||
if(mesh_detect_cycle_found(qstate, sub)) {
|
||||
*sub = mesh_area_find(mesh, NULL, qinfo, qflags,
|
||||
prime, valrec);
|
||||
if(mesh_detect_cycle_found(qstate, *sub)) {
|
||||
verbose(VERB_ALGO, "attach failed, cycle detected");
|
||||
return 0;
|
||||
}
|
||||
if(!sub) {
|
||||
if(!*sub) {
|
||||
#ifdef UNBOUND_DEBUG
|
||||
struct rbnode_t* n;
|
||||
struct rbnode_type* n;
|
||||
#endif
|
||||
/* create a new one */
|
||||
sub = mesh_state_create(qstate->env, qinfo, qflags, prime, valrec);
|
||||
if(!sub) {
|
||||
*sub = mesh_state_create(qstate->env, qinfo, NULL, qflags, prime,
|
||||
valrec);
|
||||
if(!*sub) {
|
||||
log_err("mesh_attach_sub: out of memory");
|
||||
return 0;
|
||||
}
|
||||
@@ -777,7 +849,7 @@ int mesh_attach_sub(struct module_qstate* qstate, struct query_info* qinfo,
|
||||
#else
|
||||
(void)
|
||||
#endif
|
||||
rbtree_insert(&mesh->all, &sub->node);
|
||||
rbtree_insert(&mesh->all, &(*sub)->node);
|
||||
log_assert(n != NULL);
|
||||
/* set detached (it is now) */
|
||||
mesh->num_detached_states++;
|
||||
@@ -787,11 +859,22 @@ int mesh_attach_sub(struct module_qstate* qstate, struct query_info* qinfo,
|
||||
#else
|
||||
(void)
|
||||
#endif
|
||||
rbtree_insert(&mesh->run, &sub->run_node);
|
||||
rbtree_insert(&mesh->run, &(*sub)->run_node);
|
||||
log_assert(n != NULL);
|
||||
*newq = &sub->s;
|
||||
*newq = &(*sub)->s;
|
||||
} else
|
||||
*newq = NULL;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int mesh_attach_sub(struct module_qstate* qstate, struct query_info* qinfo,
|
||||
uint16_t qflags, int prime, int valrec, struct module_qstate** newq)
|
||||
{
|
||||
struct mesh_area* mesh = qstate->env->mesh;
|
||||
struct mesh_state* sub = NULL;
|
||||
int was_detached;
|
||||
if(!mesh_add_sub(qstate, qinfo, qflags, prime, valrec, newq, &sub))
|
||||
return 0;
|
||||
was_detached = (sub->super_set.count == 0);
|
||||
if(!mesh_state_attachment(qstate->mesh_info, sub))
|
||||
return 0;
|
||||
@@ -809,7 +892,7 @@ int mesh_attach_sub(struct module_qstate* qstate, struct query_info* qinfo,
|
||||
int mesh_state_attachment(struct mesh_state* super, struct mesh_state* sub)
|
||||
{
|
||||
#ifdef UNBOUND_DEBUG
|
||||
struct rbnode_t* n;
|
||||
struct rbnode_type* n;
|
||||
#endif
|
||||
struct mesh_state_ref* subref; /* points to sub, inserted in super */
|
||||
struct mesh_state_ref* superref; /* points to super, inserted in sub */
|
||||
@@ -1019,6 +1102,12 @@ mesh_send_reply(struct mesh_state* m, int rcode, struct reply_info* rep,
|
||||
query_reply.c->buffer)) == 0)
|
||||
m->s.env->mesh->ans_nodata++;
|
||||
}
|
||||
/* Log reply sent */
|
||||
if(m->s.env->cfg->log_replies) {
|
||||
log_reply_info(0, &m->s.qinfo, &r->query_reply.addr,
|
||||
r->query_reply.addrlen, duration, 0,
|
||||
r->query_reply.c->buffer);
|
||||
}
|
||||
}
|
||||
|
||||
void mesh_query_done(struct mesh_state* mstate)
|
||||
@@ -1029,8 +1118,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) {
|
||||
@@ -1054,7 +1160,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;
|
||||
@@ -1068,13 +1175,14 @@ 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;
|
||||
}
|
||||
|
||||
int mesh_state_add_cb(struct mesh_state* s, struct edns_data* edns,
|
||||
sldns_buffer* buf, mesh_cb_func_t cb, void* cb_arg,
|
||||
sldns_buffer* buf, mesh_cb_func_type cb, void* cb_arg,
|
||||
uint16_t qid, uint16_t qflags)
|
||||
{
|
||||
struct mesh_cb* r = regional_alloc(s->s.region,
|
||||
@@ -1218,11 +1326,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;
|
||||
@@ -1372,7 +1485,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);
|
||||
}
|
||||
|
||||
|
||||
+57
-18
@@ -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
|
||||
@@ -83,9 +84,9 @@ struct mesh_area {
|
||||
struct module_env* env;
|
||||
|
||||
/** set of runnable queries (mesh_state.run_node) */
|
||||
rbtree_t run;
|
||||
rbtree_type run;
|
||||
/** rbtree of all current queries (mesh_state.node)*/
|
||||
rbtree_t all;
|
||||
rbtree_type all;
|
||||
|
||||
/** count of the total number of mesh_reply entries */
|
||||
size_t num_reply_addrs;
|
||||
@@ -154,9 +155,9 @@ struct mesh_area {
|
||||
*/
|
||||
struct mesh_state {
|
||||
/** node in mesh_area all tree, key is this struct. Must be first. */
|
||||
rbnode_t node;
|
||||
rbnode_type node;
|
||||
/** node in mesh_area runnable tree, key is this struct */
|
||||
rbnode_t run_node;
|
||||
rbnode_type run_node;
|
||||
/** the query state. Note that the qinfo and query_flags
|
||||
* may not change. */
|
||||
struct module_qstate s;
|
||||
@@ -166,10 +167,10 @@ struct mesh_state {
|
||||
struct mesh_cb* cb_list;
|
||||
/** set of superstates (that want this state's result)
|
||||
* contains struct mesh_state_ref* */
|
||||
rbtree_t super_set;
|
||||
rbtree_type super_set;
|
||||
/** set of substates (that this state needs to continue)
|
||||
* contains struct mesh_state_ref* */
|
||||
rbtree_t sub_set;
|
||||
rbtree_type sub_set;
|
||||
/** number of activations for the mesh state */
|
||||
size_t num_activated;
|
||||
|
||||
@@ -193,7 +194,7 @@ struct mesh_state {
|
||||
*/
|
||||
struct mesh_state_ref {
|
||||
/** node in rbtree for set, key is this structure */
|
||||
rbnode_t node;
|
||||
rbnode_type node;
|
||||
/** the mesh state */
|
||||
struct mesh_state* s;
|
||||
};
|
||||
@@ -224,7 +225,7 @@ struct mesh_reply {
|
||||
* Mesh result callback func.
|
||||
* called as func(cb_arg, rcode, buffer_with_reply, security, why_bogus);
|
||||
*/
|
||||
typedef void (*mesh_cb_func_t)(void*, int, struct sldns_buffer*, enum sec_status,
|
||||
typedef void (*mesh_cb_func_type)(void*, int, struct sldns_buffer*, enum sec_status,
|
||||
char*);
|
||||
|
||||
/**
|
||||
@@ -245,7 +246,7 @@ struct mesh_cb {
|
||||
/** callback routine for results. if rcode != 0 buf has message.
|
||||
* called as cb(cb_arg, rcode, buf, sec_state);
|
||||
*/
|
||||
mesh_cb_func_t cb;
|
||||
mesh_cb_func_type cb;
|
||||
/** user arg for callback */
|
||||
void* cb_arg;
|
||||
};
|
||||
@@ -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
|
||||
@@ -300,7 +305,7 @@ void mesh_new_client(struct mesh_area* mesh, struct query_info* qinfo,
|
||||
*/
|
||||
int mesh_new_callback(struct mesh_area* mesh, struct query_info* qinfo,
|
||||
uint16_t qflags, struct edns_data* edns, struct sldns_buffer* buf,
|
||||
uint16_t qid, mesh_cb_func_t cb, void* cb_arg);
|
||||
uint16_t qid, mesh_cb_func_type cb, void* cb_arg);
|
||||
|
||||
/**
|
||||
* New prefetch message. Create new query state if needed.
|
||||
@@ -365,6 +370,35 @@ void mesh_detach_subs(struct module_qstate* qstate);
|
||||
int mesh_attach_sub(struct module_qstate* qstate, struct query_info* qinfo,
|
||||
uint16_t qflags, int prime, int valrec, struct module_qstate** newq);
|
||||
|
||||
/**
|
||||
* Add detached query.
|
||||
* Creates it if it does not exist already.
|
||||
* Does not make super/sub references.
|
||||
* Performs a cycle detection - for double check - and fails if there is one.
|
||||
* Updates stat items in mesh_area structure.
|
||||
* Pass if it is priming query or not.
|
||||
* return:
|
||||
* o if error (malloc) happened.
|
||||
* o need to initialise the new state (module init; it is a new state).
|
||||
* so that the next run of the query with this module is successful.
|
||||
* o no init needed, attachment successful.
|
||||
* o added subquery, created if it did not exist already.
|
||||
*
|
||||
* @param qstate: the state to find mesh state, and that wants to receive
|
||||
* the results from the new subquery.
|
||||
* @param qinfo: what to query for (copied).
|
||||
* @param qflags: what flags to use (RD / CD flag or not).
|
||||
* @param prime: if it is a (stub) priming query.
|
||||
* @param valrec: if it is a validation recursion query (lookup of key, DS).
|
||||
* @param newq: If the new subquery needs initialisation, it is returned,
|
||||
* otherwise NULL is returned.
|
||||
* @param sub: The added mesh state, created if it did not exist already.
|
||||
* @return: false on error, true if success (and init may be needed).
|
||||
*/
|
||||
int mesh_add_sub(struct module_qstate* qstate, struct query_info* qinfo,
|
||||
uint16_t qflags, int prime, int valrec, struct module_qstate** newq,
|
||||
struct mesh_state** sub);
|
||||
|
||||
/**
|
||||
* Query state is done, send messages to reply entries.
|
||||
* Encode messages using reply entry values and the querystate (with original
|
||||
@@ -409,14 +443,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 +487,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.
|
||||
@@ -498,8 +537,8 @@ int mesh_state_add_reply(struct mesh_state* s, struct edns_data* edns,
|
||||
* @return: 0 on alloc error.
|
||||
*/
|
||||
int mesh_state_add_cb(struct mesh_state* s, struct edns_data* edns,
|
||||
struct sldns_buffer* buf, mesh_cb_func_t cb, void* cb_arg, uint16_t qid,
|
||||
uint16_t qflags);
|
||||
struct sldns_buffer* buf, mesh_cb_func_type cb, void* cb_arg,
|
||||
uint16_t qid, uint16_t qflags);
|
||||
|
||||
/**
|
||||
* Run the mesh. Run all runnable mesh states. Which can create new
|
||||
|
||||
+41
-8
@@ -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,12 @@
|
||||
#ifdef USE_CACHEDB
|
||||
#include "cachedb/cachedb.h"
|
||||
#endif
|
||||
#ifdef USE_IPSECMOD
|
||||
#include "ipsecmod/ipsecmod.h"
|
||||
#endif
|
||||
#ifdef CLIENT_SUBNET
|
||||
#include "edns-subnet/subnetmod.h"
|
||||
#endif
|
||||
|
||||
/** count number of modules (words) in the string */
|
||||
static int
|
||||
@@ -122,13 +129,20 @@ module_list_avail(void)
|
||||
static const char* names[] = {
|
||||
"dns64",
|
||||
#ifdef WITH_PYTHONMODULE
|
||||
"python",
|
||||
"python",
|
||||
#endif
|
||||
#ifdef USE_CACHEDB
|
||||
"cachedb",
|
||||
#endif
|
||||
"validator",
|
||||
"iterator",
|
||||
#ifdef USE_IPSECMOD
|
||||
"ipsecmod",
|
||||
#endif
|
||||
#ifdef CLIENT_SUBNET
|
||||
"subnetcache",
|
||||
#endif
|
||||
"respip",
|
||||
"validator",
|
||||
"iterator",
|
||||
NULL};
|
||||
return names;
|
||||
}
|
||||
@@ -143,18 +157,25 @@ module_funcs_avail(void)
|
||||
static struct module_func_block* (*fb[])(void) = {
|
||||
&dns64_get_funcblock,
|
||||
#ifdef WITH_PYTHONMODULE
|
||||
&pythonmod_get_funcblock,
|
||||
&pythonmod_get_funcblock,
|
||||
#endif
|
||||
#ifdef USE_CACHEDB
|
||||
&cachedb_get_funcblock,
|
||||
#endif
|
||||
&val_get_funcblock,
|
||||
&iter_get_funcblock,
|
||||
#ifdef USE_IPSECMOD
|
||||
&ipsecmod_get_funcblock,
|
||||
#endif
|
||||
#ifdef CLIENT_SUBNET
|
||||
&subnetmod_get_funcblock,
|
||||
#endif
|
||||
&respip_get_funcblock,
|
||||
&val_get_funcblock,
|
||||
&iter_get_funcblock,
|
||||
NULL};
|
||||
return fb;
|
||||
}
|
||||
|
||||
struct
|
||||
struct
|
||||
module_func_block* module_factory(const char** str)
|
||||
{
|
||||
int i = 0;
|
||||
@@ -216,9 +237,21 @@ 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;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
size_t
|
||||
mod_get_mem(struct module_env* env, const char* name)
|
||||
{
|
||||
int m = modstack_find(&env->mesh->mods, name);
|
||||
if(m != -1) {
|
||||
fptr_ok(fptr_whitelist_mod_get_mem(env->mesh->
|
||||
mods.mod[m]->get_mem));
|
||||
return (*env->mesh->mods.mod[m]->get_mem)(env, m);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -110,4 +110,7 @@ void modstack_desetup(struct module_stack* stack, struct module_env* env);
|
||||
*/
|
||||
int modstack_find(struct module_stack* stack, const char* name);
|
||||
|
||||
/** fetch memory for a module by name, returns 0 if module not there */
|
||||
size_t mod_get_mem(struct module_env* env, const char* name);
|
||||
|
||||
#endif /* SERVICES_MODSTACK_H */
|
||||
|
||||
+33
-16
@@ -204,6 +204,9 @@ outnet_tcp_take_into_use(struct waiting_tcp* w, uint8_t* pkt, size_t pkt_len)
|
||||
{
|
||||
struct pending_tcp* pend = w->outnet->tcp_free;
|
||||
int s;
|
||||
#ifdef SO_REUSEADDR
|
||||
int on = 1;
|
||||
#endif
|
||||
log_assert(pend);
|
||||
log_assert(pkt);
|
||||
log_assert(w->addrlen > 0);
|
||||
@@ -225,13 +228,20 @@ outnet_tcp_take_into_use(struct waiting_tcp* w, uint8_t* pkt, size_t pkt_len)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef SO_REUSEADDR
|
||||
if(setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (void*)&on,
|
||||
(socklen_t)sizeof(on)) < 0) {
|
||||
verbose(VERB_ALGO, "outgoing tcp:"
|
||||
" setsockopt(.. SO_REUSEADDR ..) failed");
|
||||
}
|
||||
#endif
|
||||
if (w->outnet->tcp_mss > 0) {
|
||||
#if defined(IPPROTO_TCP) && defined(TCP_MAXSEG)
|
||||
if(setsockopt(s, IPPROTO_TCP, TCP_MAXSEG,
|
||||
(void*)&w->outnet->tcp_mss,
|
||||
(socklen_t)sizeof(w->outnet->tcp_mss)) < 0) {
|
||||
verbose(VERB_ALGO, "outgoing tcp:"
|
||||
" setsockopt(.. SO_REUSEADDR ..) failed");
|
||||
" setsockopt(.. TCP_MAXSEG ..) failed");
|
||||
}
|
||||
#else
|
||||
verbose(VERB_ALGO, "outgoing tcp:"
|
||||
@@ -334,7 +344,7 @@ use_free_buffer(struct outside_network* outnet)
|
||||
if(outnet->tcp_wait_last == w)
|
||||
outnet->tcp_wait_last = NULL;
|
||||
if(!outnet_tcp_take_into_use(w, w->pkt, w->pkt_len)) {
|
||||
comm_point_callback_t* cb = w->cb;
|
||||
comm_point_callback_type* cb = w->cb;
|
||||
void* cb_arg = w->cb_arg;
|
||||
waiting_tcp_delete(w);
|
||||
fptr_ok(fptr_whitelist_pending_tcp(cb));
|
||||
@@ -775,7 +785,7 @@ outside_network_create(struct comm_base *base, size_t bufsize,
|
||||
|
||||
/** helper pending delete */
|
||||
static void
|
||||
pending_node_del(rbnode_t* node, void* arg)
|
||||
pending_node_del(rbnode_type* node, void* arg)
|
||||
{
|
||||
struct pending* pend = (struct pending*)node;
|
||||
struct outside_network* outnet = (struct outside_network*)arg;
|
||||
@@ -784,7 +794,7 @@ pending_node_del(rbnode_t* node, void* arg)
|
||||
|
||||
/** helper serviced delete */
|
||||
static void
|
||||
serviced_node_del(rbnode_t* node, void* ATTR_UNUSED(arg))
|
||||
serviced_node_del(rbnode_type* node, void* ATTR_UNUSED(arg))
|
||||
{
|
||||
struct serviced_query* sq = (struct serviced_query*)node;
|
||||
struct service_callback* p = sq->cblist, *np;
|
||||
@@ -966,13 +976,13 @@ udp_sockport(struct sockaddr_storage* addr, socklen_t addrlen, int pfxlen,
|
||||
}
|
||||
fd = create_udp_sock(AF_INET6, SOCK_DGRAM,
|
||||
(struct sockaddr*)&sa, addrlen, 1, inuse, &noproto,
|
||||
0, 0, 0, NULL, 0, freebind);
|
||||
0, 0, 0, NULL, 0, freebind, 0);
|
||||
} else {
|
||||
struct sockaddr_in* sa = (struct sockaddr_in*)addr;
|
||||
sa->sin_port = (in_port_t)htons((uint16_t)port);
|
||||
fd = create_udp_sock(AF_INET, SOCK_DGRAM,
|
||||
(struct sockaddr*)addr, addrlen, 1, inuse, &noproto,
|
||||
0, 0, 0, NULL, 0, 0);
|
||||
0, 0, 0, NULL, 0, 0, 0);
|
||||
}
|
||||
return fd;
|
||||
}
|
||||
@@ -1124,7 +1134,7 @@ randomize_and_send_udp(struct pending* pend, sldns_buffer* packet, int timeout)
|
||||
|
||||
struct pending*
|
||||
pending_udp_query(struct serviced_query* sq, struct sldns_buffer* packet,
|
||||
int timeout, comm_point_callback_t* cb, void* cb_arg)
|
||||
int timeout, comm_point_callback_type* cb, void* cb_arg)
|
||||
{
|
||||
struct pending* pend = (struct pending*)calloc(1, sizeof(*pend));
|
||||
if(!pend) return NULL;
|
||||
@@ -1174,7 +1184,7 @@ outnet_tcptimer(void* arg)
|
||||
{
|
||||
struct waiting_tcp* w = (struct waiting_tcp*)arg;
|
||||
struct outside_network* outnet = w->outnet;
|
||||
comm_point_callback_t* cb;
|
||||
comm_point_callback_type* cb;
|
||||
void* cb_arg;
|
||||
if(w->pkt) {
|
||||
/* it is on the waiting list */
|
||||
@@ -1197,7 +1207,7 @@ outnet_tcptimer(void* arg)
|
||||
|
||||
struct waiting_tcp*
|
||||
pending_tcp_query(struct serviced_query* sq, sldns_buffer* packet,
|
||||
int timeout, comm_point_callback_t* callback, void* callback_arg)
|
||||
int timeout, comm_point_callback_type* callback, void* callback_arg)
|
||||
{
|
||||
struct pending_tcp* pend = sq->outnet->tcp_free;
|
||||
struct waiting_tcp* w;
|
||||
@@ -1301,7 +1311,7 @@ serviced_create(struct outside_network* outnet, sldns_buffer* buff, int dnssec,
|
||||
{
|
||||
struct serviced_query* sq = (struct serviced_query*)malloc(sizeof(*sq));
|
||||
#ifdef UNBOUND_DEBUG
|
||||
rbnode_t* ins;
|
||||
rbnode_type* ins;
|
||||
#endif
|
||||
if(!sq)
|
||||
return NULL;
|
||||
@@ -1538,18 +1548,22 @@ serviced_udp_send(struct serviced_query* sq, sldns_buffer* buff)
|
||||
static int
|
||||
serviced_check_qname(sldns_buffer* pkt, uint8_t* qbuf, size_t qbuflen)
|
||||
{
|
||||
uint8_t* d1 = sldns_buffer_at(pkt, 12);
|
||||
uint8_t* d1 = sldns_buffer_begin(pkt)+12;
|
||||
uint8_t* d2 = qbuf+10;
|
||||
uint8_t len1, len2;
|
||||
int count = 0;
|
||||
if(sldns_buffer_limit(pkt) < 12+1+4) /* packet too small for qname */
|
||||
return 0;
|
||||
log_assert(qbuflen >= 15 /* 10 header, root, type, class */);
|
||||
len1 = *d1++;
|
||||
len2 = *d2++;
|
||||
if(sldns_buffer_limit(pkt) < 12+1+4) /* packet too small for qname */
|
||||
return 0;
|
||||
while(len1 != 0 || len2 != 0) {
|
||||
if(LABEL_IS_PTR(len1)) {
|
||||
d1 = sldns_buffer_at(pkt, PTR_OFFSET(len1, *d1));
|
||||
/* check if we can read *d1 with compression ptr rest */
|
||||
if(d1 >= sldns_buffer_at(pkt, sldns_buffer_limit(pkt)))
|
||||
return 0;
|
||||
d1 = sldns_buffer_begin(pkt)+PTR_OFFSET(len1, *d1);
|
||||
/* check if we can read the destination *d1 */
|
||||
if(d1 >= sldns_buffer_at(pkt, sldns_buffer_limit(pkt)))
|
||||
return 0;
|
||||
len1 = *d1++;
|
||||
@@ -1563,6 +1577,9 @@ serviced_check_qname(sldns_buffer* pkt, uint8_t* qbuf, size_t qbuflen)
|
||||
return 0;
|
||||
if(len1 > LDNS_MAX_LABELLEN)
|
||||
return 0;
|
||||
/* check len1 + 1(next length) are okay to read */
|
||||
if(d1+len1 >= sldns_buffer_at(pkt, sldns_buffer_limit(pkt)))
|
||||
return 0;
|
||||
log_assert(len1 <= LDNS_MAX_LABELLEN);
|
||||
log_assert(len2 <= LDNS_MAX_LABELLEN);
|
||||
log_assert(len1 == len2 && len1 != 0);
|
||||
@@ -1587,7 +1604,7 @@ serviced_callbacks(struct serviced_query* sq, int error, struct comm_point* c,
|
||||
uint8_t *backup_p = NULL;
|
||||
size_t backlen = 0;
|
||||
#ifdef UNBOUND_DEBUG
|
||||
rbnode_t* rem =
|
||||
rbnode_type* rem =
|
||||
#else
|
||||
(void)
|
||||
#endif
|
||||
@@ -1990,7 +2007,7 @@ outnet_serviced_query(struct outside_network* outnet,
|
||||
int nocaps, int tcp_upstream, int ssl_upstream,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* zone,
|
||||
size_t zonelen, struct module_qstate* qstate,
|
||||
comm_point_callback_t* callback, void* callback_arg, sldns_buffer* buff,
|
||||
comm_point_callback_type* callback, void* callback_arg, sldns_buffer* buff,
|
||||
struct module_env* env)
|
||||
{
|
||||
struct serviced_query* sq;
|
||||
|
||||
+10
-10
@@ -123,9 +123,9 @@ struct outside_network {
|
||||
struct pending* udp_wait_last;
|
||||
|
||||
/** pending udp answers. sorted by id, addr */
|
||||
rbtree_t* pending;
|
||||
rbtree_type* pending;
|
||||
/** serviced queries, sorted by qbuf, addr, dnssec */
|
||||
rbtree_t* serviced;
|
||||
rbtree_type* serviced;
|
||||
/** host cache, pointer but not owned by outnet. */
|
||||
struct infra_cache* infra;
|
||||
/** where to get random numbers */
|
||||
@@ -210,7 +210,7 @@ struct port_comm {
|
||||
*/
|
||||
struct pending {
|
||||
/** redblacktree entry, key is the pending struct(id, addr). */
|
||||
rbnode_t node;
|
||||
rbnode_type node;
|
||||
/** the ID for the query. int so that a value out of range can
|
||||
* be used to signify a pending that is for certain not present in
|
||||
* the rbtree. (and for which deletion is safe). */
|
||||
@@ -224,7 +224,7 @@ struct pending {
|
||||
/** timeout event */
|
||||
struct comm_timer* timer;
|
||||
/** callback for the timeout, error or reply to the message */
|
||||
comm_point_callback_t* cb;
|
||||
comm_point_callback_type* cb;
|
||||
/** callback user argument */
|
||||
void* cb_arg;
|
||||
/** the outside network it is part of */
|
||||
@@ -285,7 +285,7 @@ struct waiting_tcp {
|
||||
/** length of query packet. */
|
||||
size_t pkt_len;
|
||||
/** callback for the timeout, error or reply to the message */
|
||||
comm_point_callback_t* cb;
|
||||
comm_point_callback_type* cb;
|
||||
/** callback user argument */
|
||||
void* cb_arg;
|
||||
/** if it uses ssl upstream */
|
||||
@@ -299,7 +299,7 @@ struct service_callback {
|
||||
/** next in callback list */
|
||||
struct service_callback* next;
|
||||
/** callback function */
|
||||
comm_point_callback_t* cb;
|
||||
comm_point_callback_type* cb;
|
||||
/** user argument for callback function */
|
||||
void* cb_arg;
|
||||
};
|
||||
@@ -317,7 +317,7 @@ struct service_callback {
|
||||
*/
|
||||
struct serviced_query {
|
||||
/** The rbtree node, key is this record */
|
||||
rbnode_t node;
|
||||
rbnode_type node;
|
||||
/** The query that needs to be answered. Starts with flags u16,
|
||||
* then qdcount, ..., including qname, qtype, qclass. Does not include
|
||||
* EDNS record. */
|
||||
@@ -443,7 +443,7 @@ void outside_network_quit_prepare(struct outside_network* outnet);
|
||||
* @return: NULL on error for malloc or socket. Else the pending query object.
|
||||
*/
|
||||
struct pending* pending_udp_query(struct serviced_query* sq,
|
||||
struct sldns_buffer* packet, int timeout, comm_point_callback_t* callback,
|
||||
struct sldns_buffer* packet, int timeout, comm_point_callback_type* callback,
|
||||
void* callback_arg);
|
||||
|
||||
/**
|
||||
@@ -459,7 +459,7 @@ struct pending* pending_udp_query(struct serviced_query* sq,
|
||||
* @return: false on error for malloc or socket. Else the pending TCP object.
|
||||
*/
|
||||
struct waiting_tcp* pending_tcp_query(struct serviced_query* sq,
|
||||
struct sldns_buffer* packet, int timeout, comm_point_callback_t* callback,
|
||||
struct sldns_buffer* packet, int timeout, comm_point_callback_type* callback,
|
||||
void* callback_arg);
|
||||
|
||||
/**
|
||||
@@ -504,7 +504,7 @@ struct serviced_query* outnet_serviced_query(struct outside_network* outnet,
|
||||
int nocaps, int tcp_upstream, int ssl_upstream,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* zone,
|
||||
size_t zonelen, struct module_qstate* qstate,
|
||||
comm_point_callback_t* callback, void* callback_arg,
|
||||
comm_point_callback_type* callback, void* callback_arg,
|
||||
struct sldns_buffer* buff, struct module_env* env);
|
||||
|
||||
/**
|
||||
|
||||
+45
-2
@@ -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,12 +77,13 @@ 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);
|
||||
}
|
||||
|
||||
static void
|
||||
delviewnode(rbnode_t* n, void* ATTR_UNUSED(arg))
|
||||
delviewnode(rbnode_type* n, void* ATTR_UNUSED(arg))
|
||||
{
|
||||
struct view* v = (struct view*)n;
|
||||
view_delete(v);
|
||||
@@ -107,7 +112,7 @@ view_create(char* name)
|
||||
return NULL;
|
||||
}
|
||||
lock_rw_init(&v->lock);
|
||||
lock_protect(&v->lock, &v->name, sizeof(*v)-sizeof(rbnode_t));
|
||||
lock_protect(&v->lock, &v->name, sizeof(*v)-sizeof(rbnode_type));
|
||||
return v;
|
||||
}
|
||||
|
||||
@@ -162,6 +167,44 @@ views_apply_cfg(struct views* vs, struct config_file* cfg)
|
||||
lz_cfg.local_data = cv->local_data;
|
||||
lz_cfg.local_zones_nodefault =
|
||||
cv->local_zones_nodefault;
|
||||
if(v->isfirst) {
|
||||
/* Do not add defaults to view-specific
|
||||
* local-zone when global local zone will be
|
||||
* used. */
|
||||
struct config_strlist* nd;
|
||||
lz_cfg.local_zones_disable_default = 1;
|
||||
/* Add nodefault zones to list of zones to add,
|
||||
* so they will be used as if they are
|
||||
* configured as type transparent */
|
||||
for(nd = cv->local_zones_nodefault; nd;
|
||||
nd = nd->next) {
|
||||
char* nd_str, *nd_type;
|
||||
nd_str = strdup(nd->str);
|
||||
if(!nd_str) {
|
||||
log_err("out of memory");
|
||||
lock_rw_unlock(&v->lock);
|
||||
return 0;
|
||||
}
|
||||
nd_type = strdup("nodefault");
|
||||
if(!nd_type) {
|
||||
log_err("out of memory");
|
||||
free(nd_str);
|
||||
lock_rw_unlock(&v->lock);
|
||||
return 0;
|
||||
}
|
||||
if(!cfg_str2list_insert(
|
||||
&lz_cfg.local_zones, nd_str,
|
||||
nd_type)) {
|
||||
log_err("failed to insert "
|
||||
"default zones into "
|
||||
"local-zone list");
|
||||
free(nd_str);
|
||||
free(nd_type);
|
||||
lock_rw_unlock(&v->lock);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!local_zones_apply_cfg(v->local_zones, &lz_cfg)){
|
||||
lock_rw_unlock(&v->lock);
|
||||
return 0;
|
||||
|
||||
+9
-7
@@ -47,6 +47,7 @@
|
||||
struct regional;
|
||||
struct config_file;
|
||||
struct config_view;
|
||||
struct respip_set;
|
||||
|
||||
|
||||
/**
|
||||
@@ -54,9 +55,9 @@ struct config_view;
|
||||
*/
|
||||
struct views {
|
||||
/** lock on the view tree */
|
||||
lock_rw_t lock;
|
||||
lock_rw_type lock;
|
||||
/** rbtree of struct view */
|
||||
rbtree_t vtree;
|
||||
rbtree_type vtree;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -64,21 +65,22 @@ struct views {
|
||||
*/
|
||||
struct view {
|
||||
/** rbtree node, key is name */
|
||||
rbnode_t node;
|
||||
rbnode_type node;
|
||||
/** view name.
|
||||
* Has to be right after rbnode_t due to pointer arithmatic in
|
||||
* view_create's lock protect */
|
||||
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;
|
||||
/** lock on the data in the structure
|
||||
* For the node and name you
|
||||
* need to also hold the views_tree lock to change them (or to
|
||||
* delete this view) */
|
||||
lock_rw_t lock;
|
||||
* For the node and name you need to also hold the views_tree lock to
|
||||
* change them. */
|
||||
lock_rw_type lock;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -388,6 +388,27 @@ sldns_ecdsa2pkey_raw(unsigned char* key, size_t keylen, uint8_t algo)
|
||||
}
|
||||
#endif /* USE_ECDSA */
|
||||
|
||||
#ifdef USE_ED25519
|
||||
EVP_PKEY*
|
||||
sldns_ed255192pkey_raw(const unsigned char* key, size_t keylen)
|
||||
{
|
||||
/* ASN1 for ED25519 is 302a300506032b6570032100 <32byteskey> */
|
||||
uint8_t pre[] = {0x30, 0x2a, 0x30, 0x05, 0x06, 0x03, 0x2b, 0x65,
|
||||
0x70, 0x03, 0x21, 0x00};
|
||||
int pre_len = 12;
|
||||
uint8_t buf[256];
|
||||
EVP_PKEY *evp_key;
|
||||
/* pp gets modified by d2i() */
|
||||
const unsigned char* pp = (unsigned char*)buf;
|
||||
if(keylen != 32 || keylen + pre_len > sizeof(buf))
|
||||
return NULL; /* wrong length */
|
||||
memmove(buf, pre, pre_len);
|
||||
memmove(buf+pre_len, key, keylen);
|
||||
evp_key = d2i_PUBKEY(NULL, &pp, (int)(pre_len+keylen));
|
||||
return evp_key;
|
||||
}
|
||||
#endif /* USE_ED25519 */
|
||||
|
||||
int
|
||||
sldns_digest_evp(unsigned char* data, unsigned int len, unsigned char* dest,
|
||||
const EVP_MD* md)
|
||||
|
||||
@@ -92,6 +92,15 @@ EVP_PKEY* sldns_ecdsa2pkey_raw(unsigned char* key, size_t keylen, uint8_t algo);
|
||||
*/
|
||||
RSA *sldns_key_buf2rsa_raw(unsigned char* key, size_t len);
|
||||
|
||||
/**
|
||||
* Converts a holding buffer with key material to EVP PKEY in openssl.
|
||||
* Only available if ldns was compiled with ED25519.
|
||||
* \param[in] key the uncompressed wireformat of the key.
|
||||
* \param[in] len length of key data
|
||||
* \return the key or NULL on error.
|
||||
*/
|
||||
EVP_PKEY* sldns_ed255192pkey_raw(const unsigned char* key, size_t len);
|
||||
|
||||
/**
|
||||
* Utility function to calculate hash using generic EVP_MD pointer.
|
||||
* \param[in] data the data to hash.
|
||||
|
||||
@@ -120,6 +120,10 @@ sldns_fget_token_l(FILE *f, char *token, const char *delim, size_t limit, int *l
|
||||
if (line_nr) {
|
||||
*line_nr = *line_nr + 1;
|
||||
}
|
||||
if (limit > 0 && (i >= limit || (size_t)(t-token) >= limit)) {
|
||||
*t = '\0';
|
||||
return -1;
|
||||
}
|
||||
*t++ = ' ';
|
||||
prev_c = c;
|
||||
continue;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user