mirror of
https://github.com/NLnetLabs/unbound.git
synced 2026-08-17 21:25:50 +02:00
Compare commits
397
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5b37cd6e4c | ||
|
|
13e10ae512 | ||
|
|
c6dd1e116d | ||
|
|
92f2a1ca69 | ||
|
|
882903f2fa | ||
|
|
3352b1090e | ||
|
|
c4d17dd231 | ||
|
|
5f78f67e39 | ||
|
|
b1d99bb6b6 | ||
|
|
8914e9fd03 | ||
|
|
8d1d728d88 | ||
|
|
59c14c747a | ||
|
|
ccdf29a5f8 | ||
|
|
a7e079ea16 | ||
|
|
a97bed9d22 | ||
|
|
0ce68e97a7 | ||
|
|
3f66230874 | ||
|
|
35d0a8a843 | ||
|
|
44c3d4d2dc | ||
|
|
167772fbca | ||
|
|
2f0b11673a | ||
|
|
c5aa6a2286 | ||
|
|
d5522c3480 | ||
|
|
c1e5e6781e | ||
|
|
dd086e5bfd | ||
|
|
213bb7c6ed | ||
|
|
0c88f98a3b | ||
|
|
23ae0a9838 | ||
|
|
0f78bea4a3 | ||
|
|
4b627bd29e | ||
|
|
e4510c76e5 | ||
|
|
122dd6c11e | ||
|
|
63a5280f8f | ||
|
|
07149f576a | ||
|
|
dbd2a43ab1 | ||
|
|
4a211a9117 | ||
|
|
18ebe165ba | ||
|
|
908e1cb11a | ||
|
|
5c6c57ed89 | ||
|
|
47094fd83f | ||
|
|
67153f897e | ||
|
|
f2528dc3ac | ||
|
|
935bc162e1 | ||
|
|
d5954aff08 | ||
|
|
e98b89651e | ||
|
|
516f90abdb | ||
|
|
c09320c651 | ||
|
|
6d0812b567 | ||
|
|
b05154218c | ||
|
|
c8ae3de610 | ||
|
|
ae96aa0a6d | ||
|
|
1e85749e6e | ||
|
|
b624ed5050 | ||
|
|
b865aca03a | ||
|
|
2e7714e80c | ||
|
|
39df4f0923 | ||
|
|
eff3e01ec3 | ||
|
|
13d4504dfc | ||
|
|
9342bf685e | ||
|
|
f804c087e4 | ||
|
|
0102360e92 | ||
|
|
ca481322d4 | ||
|
|
654a7eab62 | ||
|
|
4e5b0b7eec | ||
|
|
9aaafddf04 | ||
|
|
9cd282e001 | ||
|
|
bd5dc855af | ||
|
|
31218166fc | ||
|
|
6bdecdbc5a | ||
|
|
45e6e71652 | ||
|
|
3abb32c3ba | ||
|
|
6e65343895 | ||
|
|
d1977c679b | ||
|
|
0ee44ef384 | ||
|
|
1c8f0e0fc5 | ||
|
|
17a557dfd5 | ||
|
|
8c751d48a2 | ||
|
|
5b8a7340bb | ||
|
|
33784e612a | ||
|
|
fdd5f8ff83 | ||
|
|
63616a5fce | ||
|
|
dfc00271d1 | ||
|
|
1143050ea6 | ||
|
|
5ab4a9330a | ||
|
|
2cd7c719ef | ||
|
|
ed00129866 | ||
|
|
10843805ac | ||
|
|
f0e15272b2 | ||
|
|
d4c4537b33 | ||
|
|
ba1183bb6e | ||
|
|
85ee5284f5 | ||
|
|
3795e37410 | ||
|
|
d396d8dae3 | ||
|
|
8da117b086 | ||
|
|
6e43145382 | ||
|
|
be53e37b15 | ||
|
|
3160d6ac08 | ||
|
|
d1f388ec93 | ||
|
|
5bd07f8e88 | ||
|
|
3ea6f730ac | ||
|
|
083770cb39 | ||
|
|
8756ad63dd | ||
|
|
c4566aa5d3 | ||
|
|
2791ccbe02 | ||
|
|
5f423906de | ||
|
|
4844fa3481 | ||
|
|
0f5fecd516 | ||
|
|
a1c82ac5fd | ||
|
|
1c85901cc4 | ||
|
|
b1c707e551 | ||
|
|
2b1028bdad | ||
|
|
bab5ad623c | ||
|
|
49e4258102 | ||
|
|
81e219827e | ||
|
|
02ac374640 | ||
|
|
025d810b45 | ||
|
|
4ccb613396 | ||
|
|
9025be814a | ||
|
|
fbc0256825 | ||
|
|
8580a74b37 | ||
|
|
b6e2f4dbf8 | ||
|
|
702f485587 | ||
|
|
6e47c1e05b | ||
|
|
d4145772b5 | ||
|
|
00a08beee9 | ||
|
|
5b55a46550 | ||
|
|
2cc9563cf8 | ||
|
|
8aec671860 | ||
|
|
990b12bc8e | ||
|
|
11f12bc981 | ||
|
|
08e11284fb | ||
|
|
f531011e85 | ||
|
|
d18813be30 | ||
|
|
5f76e201f0 | ||
|
|
dcd0191d7e | ||
|
|
8936f3496e | ||
|
|
f97927a47e | ||
|
|
6819c1e444 | ||
|
|
6487d6febe | ||
|
|
373904f865 | ||
|
|
0912015fb9 | ||
|
|
c15cfb4bd9 | ||
|
|
66c95e8081 | ||
|
|
843fc69927 | ||
|
|
50ea4a1072 | ||
|
|
1e47eea6e3 | ||
|
|
6289238cd6 | ||
|
|
97fdd0e2eb | ||
|
|
201da1f50a | ||
|
|
51c189394d | ||
|
|
2e257fff2a | ||
|
|
4776f749be | ||
|
|
04053d39a0 | ||
|
|
ef9f7f113f | ||
|
|
2d33bba3c0 | ||
|
|
36b38cea74 | ||
|
|
40f446a499 | ||
|
|
e839771ddf | ||
|
|
ae2c2be1a5 | ||
|
|
bf37487dca | ||
|
|
8d45c1592b | ||
|
|
862fa0d514 | ||
|
|
27c028cf27 | ||
|
|
5b7faca7db | ||
|
|
d29bc712b1 | ||
|
|
0b131d5a31 | ||
|
|
90b434c260 | ||
|
|
846b158304 | ||
|
|
95604a90e8 | ||
|
|
f5a2a58ce3 | ||
|
|
78c284e05d | ||
|
|
299f55b0d1 | ||
|
|
52f0387cac | ||
|
|
606e5a0a5f | ||
|
|
15b8d8b96a | ||
|
|
67e52ea9c5 | ||
|
|
7240ecbeb0 | ||
|
|
a952ac17be | ||
|
|
40e47bf767 | ||
|
|
0afe58a06e | ||
|
|
2069271384 | ||
|
|
014db3fb03 | ||
|
|
5aa47fb1fa | ||
|
|
1962991937 | ||
|
|
5be7f1ef8a | ||
|
|
48a6ff14a4 | ||
|
|
ade710a9fd | ||
|
|
31d38d2cfe | ||
|
|
380e3de140 | ||
|
|
fc8bf269e9 | ||
|
|
7696074fa9 | ||
|
|
bea61fc37c | ||
|
|
41dac805f5 | ||
|
|
2207a55107 | ||
|
|
196f8a68f6 | ||
|
|
0d13b4ec4c | ||
|
|
f1537e2041 | ||
|
|
47cf44cc70 | ||
|
|
1cd75cccfc | ||
|
|
d10a889a68 | ||
|
|
64476280ed | ||
|
|
b1bcde3137 | ||
|
|
b02f9befcd | ||
|
|
0f1ea7e490 | ||
|
|
f9317d65b3 | ||
|
|
2cf0359ffe | ||
|
|
35885e5a70 | ||
|
|
0585b1d75a | ||
|
|
a25fc52818 | ||
|
|
52581f8644 | ||
|
|
9412b9c2ca | ||
|
|
65230bd117 | ||
|
|
db5cf5851d | ||
|
|
3c3fd7a795 | ||
|
|
4f52be4db9 | ||
|
|
512236d705 | ||
|
|
d57986724e | ||
|
|
4e39d3dfe1 | ||
|
|
a21bc23139 | ||
|
|
62d54d8091 | ||
|
|
17559c737b | ||
|
|
59fd48c226 | ||
|
|
da78c42f88 | ||
|
|
a07ccbae9a | ||
|
|
2a2598dbf2 | ||
|
|
1fb78afc29 | ||
|
|
b2cba7b707 | ||
|
|
8dd09e31d2 | ||
|
|
806c3d7330 | ||
|
|
cac1d13fda | ||
|
|
80153decd1 | ||
|
|
2695eb9d1a | ||
|
|
20184483df | ||
|
|
adb4aeb609 | ||
|
|
70c2b587fc | ||
|
|
a50ddd7ab9 | ||
|
|
4a04ba813a | ||
|
|
1aa2c318e7 | ||
|
|
e1ec3cf893 | ||
|
|
8058dc9127 | ||
|
|
144f29638c | ||
|
|
7081b0340f | ||
|
|
263096d1f6 | ||
|
|
e577ab105e | ||
|
|
04540f82e5 | ||
|
|
2e6ddd6032 | ||
|
|
a197aac2f6 | ||
|
|
15a2add0f8 | ||
|
|
648ad4db6f | ||
|
|
4bcc0a0a7a | ||
|
|
542f717bf9 | ||
|
|
b5cc8b6c59 | ||
|
|
cba1350886 | ||
|
|
fe46bc47d7 | ||
|
|
e11d206a82 | ||
|
|
8de8c8f6f7 | ||
|
|
4954df5859 | ||
|
|
a3ef9dd53b | ||
|
|
d6c33e1757 | ||
|
|
7033234a48 | ||
|
|
c7618a9b80 | ||
|
|
312035f58a | ||
|
|
7e6a7f310d | ||
|
|
1ac9b7548b | ||
|
|
eb7eff4fc7 | ||
|
|
072be3300f | ||
|
|
9d7b1d3127 | ||
|
|
e850ca67f1 | ||
|
|
2a100ee9ee | ||
|
|
8f83c0a2cb | ||
|
|
d7e7761141 | ||
|
|
a97d7175a6 | ||
|
|
4f25d75d4b | ||
|
|
184248eb0e | ||
|
|
319119943f | ||
|
|
60304f972e | ||
|
|
d97c174f50 | ||
|
|
ed07c5424d | ||
|
|
fb187d1a60 | ||
|
|
71e0ddc94a | ||
|
|
b89d0d1cce | ||
|
|
d1f5ded1d9 | ||
|
|
fb06364014 | ||
|
|
02a77f0567 | ||
|
|
eb81761b13 | ||
|
|
96c70d91ca | ||
|
|
488811157e | ||
|
|
e225e4bcab | ||
|
|
1c1c5d72d3 | ||
|
|
87a8c80fcb | ||
|
|
a8977df4d9 | ||
|
|
4953daa016 | ||
|
|
5ab5b3b43a | ||
|
|
0bf55e6063 | ||
|
|
24e6d1e18e | ||
|
|
45142868ec | ||
|
|
8b9382998d | ||
|
|
c482999898 | ||
|
|
6bf677e7de | ||
|
|
d666e9bd13 | ||
|
|
77f15428c9 | ||
|
|
111e66ae64 | ||
|
|
6a4a9435d1 | ||
|
|
55a28d6946 | ||
|
|
ddecffd918 | ||
|
|
6afdc336ba | ||
|
|
c9233f8429 | ||
|
|
8df1e58209 | ||
|
|
d69f875261 | ||
|
|
b12ab31ae3 | ||
|
|
cfd3bcb21e | ||
|
|
90d42148de | ||
|
|
469133e8df | ||
|
|
785c938106 | ||
|
|
52a4ccee18 | ||
|
|
aa621f1c04 | ||
|
|
0fed35a4b7 | ||
|
|
4517dcd439 | ||
|
|
c5c4f6d40b | ||
|
|
0419b06ca4 | ||
|
|
90831af981 | ||
|
|
ba6325f24f | ||
|
|
2025946247 | ||
|
|
e92bd614c0 | ||
|
|
f93fdb5e09 | ||
|
|
d5b9a790fe | ||
|
|
70260273a4 | ||
|
|
1224cd9d25 | ||
|
|
0682d4371e | ||
|
|
7716d26d46 | ||
|
|
857d6ce3a1 | ||
|
|
af2ef61c49 | ||
|
|
df411b3f28 | ||
|
|
71db243b0d | ||
|
|
67cf625608 | ||
|
|
c61b2121b5 | ||
|
|
859d0f2dfe | ||
|
|
1a2e6aabac | ||
|
|
726aa5b0f5 | ||
|
|
5204c14e6d | ||
|
|
2daaebf3aa | ||
|
|
dd3984eae9 | ||
|
|
6b8642b662 | ||
|
|
5c041c0ba9 | ||
|
|
d7a9def160 | ||
|
|
ef8111ece7 | ||
|
|
90f6cb1158 | ||
|
|
effbf99281 | ||
|
|
81861aee05 | ||
|
|
6f7da59b77 | ||
|
|
a96c64d966 | ||
|
|
79d39e7f4d | ||
|
|
b86a97019f | ||
|
|
896f7a8306 | ||
|
|
a7ac109e4e | ||
|
|
79108f4c3d | ||
|
|
6dcba49ff1 | ||
|
|
8b4a8493d0 | ||
|
|
b65ff768bc | ||
|
|
f72116883b | ||
|
|
4e305e644b | ||
|
|
89d9b25090 | ||
|
|
dda1d9544c | ||
|
|
52a9e6268e | ||
|
|
8367b24bc5 | ||
|
|
8df26b132b | ||
|
|
64fb06f892 | ||
|
|
5bf4c505db | ||
|
|
5158876bfd | ||
|
|
bd2c202674 | ||
|
|
75f3fbdd65 | ||
|
|
71f23ef354 | ||
|
|
0b176750bd | ||
|
|
f0989fc754 | ||
|
|
c9f90def0a | ||
|
|
57c4f28f20 | ||
|
|
d731fa2e21 | ||
|
|
dcfcde2ec8 | ||
|
|
5f309d0018 | ||
|
|
b642c5fe1f | ||
|
|
f3fa363443 | ||
|
|
8d939691a3 | ||
|
|
b465e0cfc0 | ||
|
|
73b3b32062 | ||
|
|
6e31d1f5be | ||
|
|
14fe4669e7 | ||
|
|
fccb2eb2e8 | ||
|
|
1464b166a4 | ||
|
|
91c298c901 | ||
|
|
8afbc0944f | ||
|
|
d19e12ab5d | ||
|
|
5b2eda28e3 | ||
|
|
766244bd81 | ||
|
|
07c0d04a14 | ||
|
|
0e3068559c | ||
|
|
41fa45c99e | ||
|
|
28b45e1d87 |
@@ -163,7 +163,7 @@ jobs:
|
||||
make: "no"
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: false
|
||||
- name: test_windows
|
||||
@@ -175,6 +175,12 @@ jobs:
|
||||
cd ..
|
||||
export prepath=`pwd`
|
||||
echo prepath=${prepath}
|
||||
echo "choco install winflexbison3"
|
||||
choco install winflexbison3
|
||||
echo 'LEX="win_flex"'
|
||||
export LEX="win_flex"
|
||||
echo 'YACC="win_bison -y"'
|
||||
export YACC="win_bison -y"
|
||||
#echo "curl cpanm"
|
||||
#curl -L -k -s -S -o cpanm https://cpanmin.us/
|
||||
#echo "perl cpanm Pod::Usage"
|
||||
|
||||
@@ -12,7 +12,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
- name: configure
|
||||
run: ./configure --enable-debug
|
||||
- name: make
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
/config.status
|
||||
/dnstap/dnstap_config.h
|
||||
/dnscrypt/dnscrypt_config.h
|
||||
/clubsyms.def
|
||||
/doc/example.conf
|
||||
/doc/libunbound.3
|
||||
/doc/unbound-anchor.8
|
||||
|
||||
+28
-23
@@ -122,15 +122,15 @@ iterator/iter_delegpt.c iterator/iter_donotq.c iterator/iter_fwd.c \
|
||||
iterator/iter_hints.c iterator/iter_priv.c iterator/iter_resptype.c \
|
||||
iterator/iter_scrub.c iterator/iter_utils.c services/listen_dnsport.c \
|
||||
services/localzone.c services/mesh.c services/modstack.c services/view.c \
|
||||
services/rpz.c \
|
||||
services/rpz.c util/rfc_1982.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/edns.c util/storage/dnstree.c util/storage/lookup3.c \
|
||||
util/rtt.c util/siphash.c util/edns.c util/storage/dnstree.c util/storage/lookup3.c \
|
||||
util/storage/lruhash.c util/storage/slabhash.c util/tcp_conn_limit.c \
|
||||
util/timehist.c util/tube.c util/proxy_protocol.c \
|
||||
util/timehist.c util/tube.c util/proxy_protocol.c util/timeval_func.c \
|
||||
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 \
|
||||
@@ -145,14 +145,14 @@ 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 \
|
||||
iter_scrub.lo iter_utils.lo localzone.lo mesh.lo modstack.lo view.lo \
|
||||
outbound_list.lo alloc.lo config_file.lo configlexer.lo configparser.lo \
|
||||
fptr_wlist.lo edns.lo locks.lo log.lo mini_event.lo module.lo net_help.lo \
|
||||
fptr_wlist.lo siphash.lo edns.lo locks.lo log.lo mini_event.lo module.lo net_help.lo \
|
||||
random.lo rbtree.lo regional.lo rtt.lo dnstree.lo lookup3.lo lruhash.lo \
|
||||
slabhash.lo tcp_conn_limit.lo timehist.lo tube.lo winsock_event.lo \
|
||||
autotrust.lo val_anchor.lo rpz.lo proxy_protocol.lo \
|
||||
autotrust.lo val_anchor.lo rpz.lo rfc_1982.lo proxy_protocol.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_OBJ) authzone.lo \
|
||||
$(SUBNET_OBJ) $(PYTHONMOD_OBJ) $(CHECKLOCK_OBJ) $(DNSTAP_OBJ) $(DNSCRYPT_OBJ) \
|
||||
$(IPSECMOD_OBJ) $(IPSET_OBJ) $(DYNLIBMOD_OBJ) respip.lo
|
||||
$(IPSECMOD_OBJ) $(IPSET_OBJ) $(DYNLIBMOD_OBJ) respip.lo timeval_func.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
|
||||
@@ -198,7 +198,7 @@ CHECKCONF_OBJ=unbound-checkconf.lo worker_cb.lo
|
||||
CHECKCONF_OBJ_LINK=$(CHECKCONF_OBJ) $(COMMON_OBJ_ALL_SYMBOLS) $(SLDNS_OBJ) \
|
||||
$(COMPAT_OBJ) @WIN_CHECKCONF_OBJ_LINK@
|
||||
CONTROL_SRC=smallapp/unbound-control.c
|
||||
CONTROL_OBJ=unbound-control.lo
|
||||
CONTROL_OBJ=unbound-control.lo
|
||||
CONTROL_OBJ_LINK=$(CONTROL_OBJ) worker_cb.lo $(COMMON_OBJ_ALL_SYMBOLS) \
|
||||
$(SLDNS_OBJ) $(COMPAT_OBJ) @WIN_CONTROL_OBJ_LINK@
|
||||
HOST_SRC=smallapp/unbound-host.c
|
||||
@@ -455,6 +455,7 @@ unbound-dnstap-socket.lo unbound-dnstap-socket.o: $(srcdir)/dnstap/unbound-dnsta
|
||||
dynlibmod.lo dynlibdmod.o: $(srcdir)/dynlibmod/dynlibmod.c config.h $(srcdir)/dynlibmod/dynlibmod.h
|
||||
cachedb.lo cachedb.o: $(srcdir)/cachedb/cachedb.c config.h $(srcdir)/cachedb/cachedb.h
|
||||
redis.lo redis.o: $(srcdir)/cachedb/redis.c config.h $(srcdir)/cachedb/redis.h
|
||||
timeval_func.lo timeval_func.o: $(srcdir)/util/timeval_func.c $(srcdir)/util/timeval_func.h
|
||||
|
||||
# dnscrypt
|
||||
dnscrypt.lo dnscrypt.o: $(srcdir)/dnscrypt/dnscrypt.c config.h \
|
||||
@@ -498,6 +499,7 @@ util/configlexer.c: $(srcdir)/util/configlexer.lex util/configparser.h
|
||||
echo "#include \"util/configyyrename.h\"" >> $@ ;\
|
||||
$(LEX) -t $(srcdir)/util/configlexer.lex >> $@ ;\
|
||||
fi
|
||||
@if test ! -f $@; then echo "No $@ : need flex and bison to compile from source repository"; exit 1; fi
|
||||
|
||||
util/configparser.c util/configparser.h: $(srcdir)/util/configparser.y
|
||||
@-if test ! -d util; then $(INSTALL) -d util; fi
|
||||
@@ -516,7 +518,7 @@ distclean: clean
|
||||
rm -f doc/example.conf doc/libunbound.3 doc/unbound-anchor.8 doc/unbound-checkconf.8 doc/unbound-control.8 doc/unbound.8 doc/unbound.conf.5 doc/unbound-host.1
|
||||
rm -f smallapp/unbound-control-setup.sh dnstap/dnstap_config.h dnscrypt/dnscrypt_config.h contrib/libunbound.pc contrib/unbound.socket contrib/unbound.service
|
||||
rm -f $(TEST_BIN)
|
||||
rm -f Makefile
|
||||
rm -f Makefile
|
||||
|
||||
maintainer-clean: distclean
|
||||
rm -f util/configlexer.c util/configparser.c util/configparser.h
|
||||
@@ -616,7 +618,7 @@ install-all: all $(PYTHONMOD_INSTALL) $(PYUNBOUND_INSTALL) $(UNBOUND_EVENT_INSTA
|
||||
$(INSTALL) -c -m 644 doc/unbound.conf.5 $(DESTDIR)$(mandir)/man5
|
||||
$(INSTALL) -c -m 644 doc/unbound-host.1 $(DESTDIR)$(mandir)/man1
|
||||
$(INSTALL) -c -m 755 unbound-control-setup $(DESTDIR)$(sbindir)/unbound-control-setup
|
||||
if test ! -e $(DESTDIR)$(configfile); then $(INSTALL) -d `dirname $(DESTDIR)$(configfile)`; $(INSTALL) -c -m 644 doc/example.conf $(DESTDIR)$(configfile); fi
|
||||
if test ! -e "$(DESTDIR)$(configfile)"; then $(INSTALL) -d `dirname "$(DESTDIR)$(configfile)"`; $(INSTALL) -c -m 644 doc/example.conf "$(DESTDIR)$(configfile)"; fi
|
||||
|
||||
pythonmod-uninstall:
|
||||
rm -f -- $(DESTDIR)$(PYTHON_SITE_PKG)/unboundmodule.py
|
||||
@@ -645,11 +647,11 @@ uninstall: $(PYTHONMOD_UNINSTALL) $(PYUNBOUND_UNINSTALL) $(UNBOUND_EVENT_UNINSTA
|
||||
rm -f -- $(DESTDIR)$(includedir)/unbound.h
|
||||
$(LIBTOOL) --mode=uninstall rm -f $(DESTDIR)$(libdir)/libunbound.la
|
||||
@echo
|
||||
@echo "You still need to remove "`dirname $(DESTDIR)$(configfile)`" , $(DESTDIR)$(configfile) by hand"
|
||||
@echo "You still need to remove "`dirname "$(DESTDIR)$(configfile)"`" , $(DESTDIR)$(configfile) by hand"
|
||||
|
||||
iana_update:
|
||||
curl -o port-numbers.tmp https://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.xml --compressed
|
||||
if file port-numbers.tmp | grep 'gzip' >/dev/null; then zcat port-numbers.tmp; else cat port-numbers.tmp; fi | awk '/<record>/ {p=0;} /<protocol>udp/ {p=1;} /<protocol>[^u]/ {p=0;} /Decomissioned|Decommissioned|Removed|De-registered|unassigned|Unassigned|Reserved/ {u=1;} /<number>/ { if(u==1) {u=0;} else { if(p==1) { match($$0,/[0-9]+/); print substr($$0, RSTART, RLENGTH) ","}}}' | sort -nu > util/iana_ports.inc
|
||||
if file port-numbers.tmp | grep 'gzip' >/dev/null; then zcat port-numbers.tmp; else cat port-numbers.tmp; fi | awk '/<record>/ {p=0;} /<protocol>udp/ {p=1;} /<protocol>[^u]/ {p=0;} /Decomissioned|Decommissioned|Removed|De-registered|unassigned|Unassigned|Reserved/ {u=1;} /<number>/ { if(u==1) {u=0;} else { if(p==1) { match($$0,/[0-9]+/); print substr($$0, RSTART, RLENGTH) ","}}}' | sort -nu > util/iana_ports.inc
|
||||
rm -f port-numbers.tmp
|
||||
|
||||
# dependency generation
|
||||
@@ -736,7 +738,7 @@ msgencode.lo msgencode.o: $(srcdir)/util/data/msgencode.c config.h $(srcdir)/uti
|
||||
msgparse.lo msgparse.o: $(srcdir)/util/data/msgparse.c config.h $(srcdir)/util/data/msgparse.h \
|
||||
$(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/sldns/pkthdr.h \
|
||||
$(srcdir)/sldns/rrdef.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h \
|
||||
$(srcdir)/util/data/dname.h $(srcdir)/util/storage/lookup3.h $(srcdir)/util/regional.h $(srcdir)/sldns/sbuffer.h \
|
||||
$(srcdir)/util/data/dname.h $(srcdir)/util/storage/lookup3.h $(srcdir)/util/regional.h $(srcdir)/util/net_help.h $(srcdir)/sldns/sbuffer.h \
|
||||
$(srcdir)/sldns/parseutil.h $(srcdir)/sldns/wire2str.h
|
||||
msgreply.lo msgreply.o: $(srcdir)/util/data/msgreply.c config.h $(srcdir)/util/data/msgreply.h \
|
||||
$(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/data/packed_rrset.h \
|
||||
@@ -791,7 +793,7 @@ iter_priv.lo iter_priv.o: $(srcdir)/iterator/iter_priv.c config.h $(srcdir)/iter
|
||||
$(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/net_help.h \
|
||||
$(srcdir)/util/storage/dnstree.h $(srcdir)/sldns/str2wire.h $(srcdir)/sldns/sbuffer.h
|
||||
iter_resptype.lo iter_resptype.o: $(srcdir)/iterator/iter_resptype.c config.h \
|
||||
$(srcdir)/iterator/iter_resptype.h $(srcdir)/iterator/iter_delegpt.h $(srcdir)/util/log.h \
|
||||
$(srcdir)/iterator/iter_resptype.h $(srcdir)/iterator/iter_delegpt.h $(srcdir)/iterator/iterator.h $(srcdir)/util/log.h \
|
||||
$(srcdir)/services/cache/dns.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h \
|
||||
$(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/net_help.h \
|
||||
$(srcdir)/util/data/dname.h $(srcdir)/sldns/rrdef.h $(srcdir)/sldns/pkthdr.h
|
||||
@@ -877,7 +879,7 @@ rpz.lo rpz.o: $(srcdir)/services/rpz.c config.h $(srcdir)/services/rpz.h $(srcdi
|
||||
outbound_list.lo outbound_list.o: $(srcdir)/services/outbound_list.c config.h \
|
||||
$(srcdir)/services/outbound_list.h $(srcdir)/services/outside_network.h $(srcdir)/util/rbtree.h \
|
||||
$(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
|
||||
|
||||
|
||||
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 \
|
||||
@@ -915,7 +917,8 @@ config_file.lo config_file.o: $(srcdir)/util/config_file.c config.h $(srcdir)/ut
|
||||
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
|
||||
$(srcdir)/util/config_file.h $(srcdir)/util/net_help.h $(srcdir)/util/log.h $(srcdir)/sldns/str2wire.h \
|
||||
$(srcdir)/sldns/rrdef.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 \
|
||||
@@ -928,7 +931,7 @@ shm_main.lo shm_main.o: $(srcdir)/util/shm_side/shm_main.c config.h $(srcdir)/ut
|
||||
$(srcdir)/services/view.h $(srcdir)/util/config_file.h $(srcdir)/services/authzone.h $(srcdir)/respip/respip.h \
|
||||
$(srcdir)/services/cache/rrset.h $(srcdir)/util/storage/slabhash.h $(srcdir)/services/cache/infra.h \
|
||||
$(srcdir)/util/rtt.h $(srcdir)/validator/validator.h $(srcdir)/validator/val_utils.h $(srcdir)/util/fptr_wlist.h \
|
||||
$(srcdir)/util/tube.h
|
||||
$(srcdir)/util/tube.h $(srcdir)/util/timeval_func.h
|
||||
authzone.lo authzone.o: $(srcdir)/services/authzone.c config.h $(srcdir)/services/authzone.h \
|
||||
$(srcdir)/util/rbtree.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/services/mesh.h $(srcdir)/util/netevent.h \
|
||||
$(srcdir)/dnscrypt/dnscrypt.h $(srcdir)/util/data/msgparse.h \
|
||||
@@ -983,7 +986,7 @@ netevent.lo netevent.o: $(srcdir)/util/netevent.c config.h $(srcdir)/util/neteve
|
||||
$(srcdir)/services/modstack.h $(srcdir)/services/rpz.h $(srcdir)/services/localzone.h $(srcdir)/services/view.h \
|
||||
$(srcdir)/sldns/sbuffer.h $(srcdir)/util/config_file.h $(srcdir)/services/authzone.h $(srcdir)/daemon/stats.h \
|
||||
$(srcdir)/util/timehist.h $(srcdir)/libunbound/unbound.h $(srcdir)/respip/respip.h $(srcdir)/sldns/str2wire.h \
|
||||
$(srcdir)/dnstap/dnstap.h $(srcdir)/services/listen_dnsport.h
|
||||
$(srcdir)/dnstap/dnstap.h $(srcdir)/services/listen_dnsport.h $(srcdir)/util/timeval_func.h
|
||||
proxy_protocol.lo proxy_protocol.o: $(srcdir)/util/proxy_protocol.c config.h \
|
||||
$(srcdir)/util/proxy_protocol.h $(srcdir)/sldns/sbuffer.h
|
||||
net_help.lo net_help.o: $(srcdir)/util/net_help.c config.h $(srcdir)/util/net_help.h $(srcdir)/util/log.h \
|
||||
@@ -1006,6 +1009,8 @@ rtt.lo rtt.o: $(srcdir)/util/rtt.c config.h $(srcdir)/util/rtt.h $(srcdir)/itera
|
||||
$(srcdir)/services/outbound_list.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/storage/lruhash.h \
|
||||
$(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/module.h \
|
||||
$(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h
|
||||
siphash.lo siphash.o: $(srcdir)/util/siphash.c
|
||||
rfc_1982.lo rfc_1982.o: $(srcdir)/util/rfc_1982.c
|
||||
edns.lo edns.o: $(srcdir)/util/edns.c config.h $(srcdir)/util/edns.h $(srcdir)/util/storage/dnstree.h \
|
||||
$(srcdir)/util/rbtree.h $(srcdir)/util/config_file.h $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
|
||||
$(srcdir)/util/net_help.h $(srcdir)/util/log.h $(srcdir)/util/regional.h \
|
||||
@@ -1186,7 +1191,7 @@ unitmain.lo unitmain.o: $(srcdir)/testcode/unitmain.c config.h $(srcdir)/sldns/r
|
||||
$(srcdir)/util/storage/dnstree.h $(srcdir)/util/rbtree.h $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
|
||||
$(srcdir)/util/random.h $(srcdir)/respip/respip.h \
|
||||
$(srcdir)/services/localzone.h $(srcdir)/services/view.h $(srcdir)/sldns/sbuffer.h \
|
||||
$(srcdir)/services/outside_network.h
|
||||
$(srcdir)/services/outside_network.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 \
|
||||
@@ -1321,7 +1326,7 @@ unbound.lo unbound.o: $(srcdir)/daemon/unbound.c config.h $(srcdir)/util/log.h $
|
||||
worker.lo worker.o: $(srcdir)/daemon/worker.c config.h $(srcdir)/util/log.h $(srcdir)/util/net_help.h \
|
||||
$(srcdir)/util/random.h $(srcdir)/daemon/worker.h $(srcdir)/libunbound/worker.h $(srcdir)/sldns/sbuffer.h \
|
||||
$(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h \
|
||||
$(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
|
||||
$(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h $(srcdir)/util/timeval_func.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 \
|
||||
@@ -1343,7 +1348,7 @@ testbound.lo testbound.o: $(srcdir)/testcode/testbound.c config.h $(srcdir)/test
|
||||
$(srcdir)/daemon/remote.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/config_file.h $(srcdir)/sldns/keyraw.h $(srcdir)/daemon/unbound.c $(srcdir)/daemon/daemon.h \
|
||||
$(srcdir)/util/alloc.h $(srcdir)/services/modstack.h \
|
||||
$(srcdir)/util/alloc.h $(srcdir)/util/timeval_func.h $(srcdir)/services/modstack.h \
|
||||
$(srcdir)/util/storage/slabhash.h $(srcdir)/services/listen_dnsport.h $(srcdir)/services/cache/rrset.h \
|
||||
$(srcdir)/services/cache/infra.h $(srcdir)/util/storage/dnstree.h $(srcdir)/util/rtt.h \
|
||||
$(srcdir)/util/data/msgreply.h $(srcdir)/util/fptr_wlist.h $(srcdir)/util/module.h \
|
||||
@@ -1357,7 +1362,7 @@ testpkts.lo testpkts.o: $(srcdir)/testcode/testpkts.c config.h $(srcdir)/testcod
|
||||
worker.lo worker.o: $(srcdir)/daemon/worker.c config.h $(srcdir)/util/log.h $(srcdir)/util/net_help.h \
|
||||
$(srcdir)/util/random.h $(srcdir)/daemon/worker.h $(srcdir)/libunbound/worker.h $(srcdir)/sldns/sbuffer.h \
|
||||
$(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h \
|
||||
$(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
|
||||
$(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h $(srcdir)/util/timeval_func.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 \
|
||||
@@ -1409,7 +1414,7 @@ stats.lo stats.o: $(srcdir)/daemon/stats.c config.h $(srcdir)/daemon/stats.h $(s
|
||||
$(srcdir)/validator/val_kcache.h $(srcdir)/validator/val_neg.h
|
||||
replay.lo replay.o: $(srcdir)/testcode/replay.c config.h $(srcdir)/util/log.h $(srcdir)/util/net_help.h \
|
||||
$(srcdir)/util/config_file.h $(srcdir)/testcode/replay.h $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
|
||||
$(srcdir)/testcode/testpkts.h $(srcdir)/util/rbtree.h \
|
||||
$(srcdir)/testcode/testpkts.h $(srcdir)/util/rbtree.h $(srcdir)/util/timeval_func.h \
|
||||
$(srcdir)/testcode/fake_event.h $(srcdir)/sldns/str2wire.h $(srcdir)/sldns/rrdef.h
|
||||
fake_event.lo fake_event.o: $(srcdir)/testcode/fake_event.c config.h $(srcdir)/testcode/fake_event.h \
|
||||
$(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
|
||||
@@ -1417,7 +1422,7 @@ fake_event.lo fake_event.o: $(srcdir)/testcode/fake_event.c config.h $(srcdir)/t
|
||||
$(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/edns.h $(srcdir)/util/storage/dnstree.h $(srcdir)/util/rbtree.h $(srcdir)/util/config_file.h \
|
||||
$(srcdir)/services/listen_dnsport.h $(srcdir)/services/outside_network.h \
|
||||
$(srcdir)/services/listen_dnsport.h $(srcdir)/services/outside_network.h $(srcdir)/util/timeval_func.h \
|
||||
$(srcdir)/services/cache/infra.h $(srcdir)/util/rtt.h \
|
||||
$(srcdir)/testcode/replay.h $(srcdir)/testcode/testpkts.h $(srcdir)/util/fptr_wlist.h $(srcdir)/util/module.h \
|
||||
$(srcdir)/util/tube.h $(srcdir)/services/mesh.h $(srcdir)/services/modstack.h $(srcdir)/services/rpz.h \
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
# Unbound
|
||||
|
||||
[](https://travis-ci.org/NLnetLabs/unbound)
|
||||
[](https://github.com/NLnetLabs/unbound/actions)
|
||||
[](https://repology.org/project/unbound/versions)
|
||||
[](https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:unbound)
|
||||
[](https://unbound.readthedocs.io/en/latest/?badge=latest)
|
||||
[](https://fosstodon.org/@nlnetlabs)
|
||||
|
||||
Unbound is a validating, recursive, caching DNS resolver. It is designed to be
|
||||
fast and lean and incorporates modern features based on open standards. If you
|
||||
@@ -16,7 +17,9 @@ You can learn more about Unbound by reading our
|
||||
## Compiling
|
||||
|
||||
Make sure you have the C toolchain, OpenSSL and its include files, and libexpat
|
||||
installed. Unbound can be compiled and installed using:
|
||||
installed.
|
||||
If building from the repository source you also need flex and bison installed.
|
||||
Unbound can be compiled and installed using:
|
||||
|
||||
```
|
||||
./configure && make && make install
|
||||
@@ -26,7 +29,7 @@ You can use libevent if you want. libevent is useful when using many (10000)
|
||||
outgoing ports. By default max 256 ports are opened at the same time and the
|
||||
builtin alternative is equally capable and a little faster.
|
||||
|
||||
Use the `--with-libevent=dir` configure option to compile Unbound with libevent
|
||||
Use the `--with-libevent` configure option to compile Unbound with libevent
|
||||
support.
|
||||
|
||||
## Unbound configuration
|
||||
|
||||
+19
-17
@@ -2,7 +2,9 @@
|
||||
# Copyright 2009, Wouter Wijngaards, NLnet Labs.
|
||||
# BSD licensed.
|
||||
#
|
||||
# Version 44
|
||||
# Version 46
|
||||
# 2023-05-04 fix to remove unused whitespace.
|
||||
# 2023-01-26 fix -Wstrict-prototypes.
|
||||
# 2022-09-01 fix checking if nonblocking sockets work on OpenBSD.
|
||||
# 2021-08-17 fix sed script in ssldir split handling.
|
||||
# 2021-08-17 fix for openssl to detect split version, with ssldir_include
|
||||
@@ -187,7 +189,7 @@ dnl cache=`echo $1 | sed 'y%.=/+- %___p__%'`
|
||||
AC_CACHE_VAL(cv_prog_cc_flag_needed_$cache,
|
||||
[
|
||||
echo '$2' > conftest.c
|
||||
echo 'void f(){}' >>conftest.c
|
||||
echo 'void f(void){}' >>conftest.c
|
||||
if test -z "`$CC $CPPFLAGS $CFLAGS $ERRFLAG -c conftest.c 2>&1`"; then
|
||||
eval "cv_prog_cc_flag_needed_$cache=no"
|
||||
else
|
||||
@@ -233,7 +235,7 @@ dnl DEPFLAG: set to flag that generates dependencies.
|
||||
AC_DEFUN([ACX_DEPFLAG],
|
||||
[
|
||||
AC_MSG_CHECKING([$CC dependency flag])
|
||||
echo 'void f(){}' >conftest.c
|
||||
echo 'void f(void){}' >conftest.c
|
||||
if test "`$CC -MM conftest.c 2>&1`" = "conftest.o: conftest.c"; then
|
||||
DEPFLAG="-MM"
|
||||
else
|
||||
@@ -272,7 +274,7 @@ ACX_CHECK_COMPILER_FLAG_NEEDED($C99FLAG -D__EXTENSIONS__ -D_BSD_SOURCE -D_DEFAUL
|
||||
#include <getopt.h>
|
||||
#endif
|
||||
|
||||
int test() {
|
||||
int test(void) {
|
||||
int a;
|
||||
char **opts = NULL;
|
||||
struct timeval tv;
|
||||
@@ -309,7 +311,7 @@ ACX_CHECK_COMPILER_FLAG_NEEDED($C99FLAG -D__EXTENSIONS__ -D_BSD_SOURCE -D_DEFAUL
|
||||
#include <getopt.h>
|
||||
#endif
|
||||
|
||||
int test() {
|
||||
int test(void) {
|
||||
int a;
|
||||
char **opts = NULL;
|
||||
struct timeval tv;
|
||||
@@ -335,7 +337,7 @@ ACX_CHECK_COMPILER_FLAG_NEEDED($C99FLAG,
|
||||
[
|
||||
#include <stdbool.h>
|
||||
#include <ctype.h>
|
||||
int test() {
|
||||
int test(void) {
|
||||
int a = 0;
|
||||
return a;
|
||||
}
|
||||
@@ -345,7 +347,7 @@ ACX_CHECK_COMPILER_FLAG_NEEDED(-D_BSD_SOURCE -D_DEFAULT_SOURCE,
|
||||
[
|
||||
#include <ctype.h>
|
||||
|
||||
int test() {
|
||||
int test(void) {
|
||||
int a;
|
||||
a = isascii(32);
|
||||
return a;
|
||||
@@ -356,7 +358,7 @@ ACX_CHECK_COMPILER_FLAG_NEEDED(-D_GNU_SOURCE,
|
||||
[
|
||||
#include <netinet/in.h>
|
||||
|
||||
int test() {
|
||||
int test(void) {
|
||||
struct in6_pktinfo inf;
|
||||
int a = (int)sizeof(inf);
|
||||
return a;
|
||||
@@ -370,7 +372,7 @@ ACX_CHECK_COMPILER_FLAG_NEEDED(-D_GNU_SOURCE -D_FRSRESGID,
|
||||
[
|
||||
#include <unistd.h>
|
||||
|
||||
int test() {
|
||||
int test(void) {
|
||||
int a = setresgid(0,0,0);
|
||||
a = setresuid(0,0,0);
|
||||
return a;
|
||||
@@ -385,7 +387,7 @@ ACX_CHECK_COMPILER_FLAG_NEEDED(-D_POSIX_C_SOURCE=200112,
|
||||
#endif
|
||||
#include <netdb.h>
|
||||
|
||||
int test() {
|
||||
int test(void) {
|
||||
int a = 0;
|
||||
char *t;
|
||||
time_t time = 0;
|
||||
@@ -413,7 +415,7 @@ ACX_CHECK_COMPILER_FLAG_NEEDED(-D__EXTENSIONS__,
|
||||
#include <getopt.h>
|
||||
#endif
|
||||
|
||||
int test() {
|
||||
int test(void) {
|
||||
int a;
|
||||
char **opts = NULL;
|
||||
struct timeval tv;
|
||||
@@ -475,7 +477,7 @@ fi
|
||||
dnl Setup ATTR_FORMAT config.h parts.
|
||||
dnl make sure you call ACX_CHECK_FORMAT_ATTRIBUTE also.
|
||||
AC_DEFUN([AHX_CONFIG_FORMAT_ATTRIBUTE],
|
||||
[
|
||||
[
|
||||
#ifdef HAVE_ATTR_FORMAT
|
||||
# define ATTR_FORMAT(archetype, string_index, first_to_check) \
|
||||
__attribute__ ((format (archetype, string_index, first_to_check)))
|
||||
@@ -834,7 +836,7 @@ dnl try to see if an additional _LARGEFILE_SOURCE 1 is needed to get fseeko
|
||||
ACX_CHECK_COMPILER_FLAG_NEEDED(-D_LARGEFILE_SOURCE=1,
|
||||
[
|
||||
#include <stdio.h>
|
||||
int test() {
|
||||
int test(void) {
|
||||
int a = fseeko(stdin, 0, 0);
|
||||
return a;
|
||||
}
|
||||
@@ -859,7 +861,7 @@ char* (*f) () = getaddrinfo;
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
int main() {
|
||||
int main(void) {
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
@@ -923,7 +925,7 @@ cache=`echo $1 | sed 'y%.=/+-%___p_%'`
|
||||
AC_CACHE_VAL(cv_cc_deprecated_$cache,
|
||||
[
|
||||
echo '$3' >conftest.c
|
||||
echo 'void f(){ $2 }' >>conftest.c
|
||||
echo 'void f(void){ $2 }' >>conftest.c
|
||||
if test -z "`$CC $CPPFLAGS $CFLAGS -c conftest.c 2>&1 | grep -e deprecated -e unavailable`"; then
|
||||
eval "cv_cc_deprecated_$cache=no"
|
||||
else
|
||||
@@ -1317,7 +1319,7 @@ AC_DEFUN([AHX_CONFIG_W32_FD_SET_T],
|
||||
#ifdef HAVE_WINSOCK2_H
|
||||
#define FD_SET_T (u_int)
|
||||
#else
|
||||
#define FD_SET_T
|
||||
#define FD_SET_T
|
||||
#endif
|
||||
])
|
||||
|
||||
@@ -1355,7 +1357,7 @@ dnl $3: define value, 1
|
||||
AC_DEFUN([AHX_CONFIG_FLAG_OMITTED],
|
||||
[#if defined($1) && !defined($2)
|
||||
#define $2 $3
|
||||
[#]endif ])
|
||||
[#]endif])
|
||||
|
||||
dnl Wrapper for AHX_CONFIG_FLAG_OMITTED for -D style flags
|
||||
dnl $1: the -DNAME or -DNAME=value string.
|
||||
|
||||
+45
-16
@@ -17,33 +17,62 @@ AC_DEFUN([AC_PYTHON_DEVEL],[
|
||||
PYTHON_VERSION=`$PYTHON -c "import sys; \
|
||||
print(sys.version.split()[[0]])"`
|
||||
fi
|
||||
# calculate the version number components.
|
||||
[
|
||||
v="$PYTHON_VERSION"
|
||||
PYTHON_VERSION_MAJOR=`echo $v | sed 's/[^0-9].*//'`
|
||||
if test -z "$PYTHON_VERSION_MAJOR"; then PYTHON_VERSION_MAJOR="0"; fi
|
||||
v=`echo $v | sed -e 's/^[0-9]*$//' -e 's/[0-9]*[^0-9]//'`
|
||||
PYTHON_VERSION_MINOR=`echo $v | sed 's/[^0-9].*//'`
|
||||
if test -z "$PYTHON_VERSION_MINOR"; then PYTHON_VERSION_MINOR="0"; fi
|
||||
v=`echo $v | sed -e 's/^[0-9]*$//' -e 's/[0-9]*[^0-9]//'`
|
||||
PYTHON_VERSION_PATCH=`echo $v | sed 's/[^0-9].*//'`
|
||||
if test -z "$PYTHON_VERSION_PATCH"; then PYTHON_VERSION_PATCH="0"; fi
|
||||
]
|
||||
|
||||
# Check if you have sysconfig
|
||||
AC_MSG_CHECKING([for the sysconfig Python module])
|
||||
if ac_sysconfig_result=`$PYTHON -c "import sysconfig" 2>&1`; then
|
||||
# For some systems, sysconfig exists, but has the wrong paths,
|
||||
# on Debian 10, for python 2.7 and 3.7. So, we check the version,
|
||||
# and for older versions try distutils.sysconfig first. For newer
|
||||
# versions>=3.10, where distutils.sysconfig is deprecated, use
|
||||
# sysconfig first and then attempt the other one.
|
||||
py_distutils_first="no"
|
||||
if test $PYTHON_VERSION_MAJOR -lt 3; then
|
||||
py_distutils_first="yes"
|
||||
fi
|
||||
if test $PYTHON_VERSION_MAJOR -eq 3 -a $PYTHON_VERSION_MINOR -lt 10; then
|
||||
py_distutils_first="yes"
|
||||
fi
|
||||
|
||||
# Check if you have the first module
|
||||
if test "$py_distutils_first" = "yes"; then m="distutils"; else m="sysconfig"; fi
|
||||
sysconfig_module=""
|
||||
AC_MSG_CHECKING([for the $m Python module])
|
||||
if ac_modulecheck_result1=`$PYTHON -c "import $m" 2>&1`; then
|
||||
AC_MSG_RESULT([yes])
|
||||
sysconfig_module="sysconfig"
|
||||
# if yes, use sysconfig, because distutils is deprecated.
|
||||
sysconfig_module="$m"
|
||||
else
|
||||
AC_MSG_RESULT([no])
|
||||
# if no, try to use distutils
|
||||
fi
|
||||
|
||||
#
|
||||
# Check if you have distutils, else fail
|
||||
#
|
||||
AC_MSG_CHECKING([for the distutils Python package])
|
||||
if ac_distutils_result=`$PYTHON -c "import distutils" 2>&1`; then
|
||||
# if not found, try the other one.
|
||||
if test -z "$sysconfig_module"; then
|
||||
if test "$py_distutils_first" = "yes"; then m2="sysconfig"; else m2="distutils"; fi
|
||||
AC_MSG_CHECKING([for the $m2 Python module])
|
||||
if ac_modulecheck_result2=`$PYTHON -c "import $m2" 2>&1`; then
|
||||
AC_MSG_RESULT([yes])
|
||||
sysconfig_module="$m2"
|
||||
else
|
||||
AC_MSG_RESULT([no])
|
||||
AC_MSG_ERROR([cannot import Python module "distutils".
|
||||
Please check your Python installation. The error was:
|
||||
$ac_distutils_result])
|
||||
AC_MSG_ERROR([cannot import Python module "$m", or "$m2".
|
||||
Please check your Python installation. The errors are:
|
||||
$m
|
||||
$ac_modulecheck_result1
|
||||
$m2
|
||||
$ac_modulecheck_result2])
|
||||
PYTHON_VERSION=""
|
||||
fi
|
||||
|
||||
sysconfig_module="distutils.sysconfig"
|
||||
fi
|
||||
if test "$sysconfig_module" = "distutils"; then sysconfig_module="distutils.sysconfig"; fi
|
||||
|
||||
#
|
||||
# Check for Python include path
|
||||
|
||||
+66
-14
@@ -102,7 +102,6 @@ static int
|
||||
testframe_init(struct module_env* env, struct cachedb_env* cachedb_env)
|
||||
{
|
||||
struct testframe_moddata* d;
|
||||
(void)env;
|
||||
verbose(VERB_ALGO, "testframe_init");
|
||||
d = (struct testframe_moddata*)calloc(1,
|
||||
sizeof(struct testframe_moddata));
|
||||
@@ -111,6 +110,15 @@ testframe_init(struct module_env* env, struct cachedb_env* cachedb_env)
|
||||
log_err("out of memory");
|
||||
return 0;
|
||||
}
|
||||
/* Register an EDNS option (65534) to bypass the worker cache lookup
|
||||
* for testing */
|
||||
if(!edns_register_option(LDNS_EDNS_UNBOUND_CACHEDB_TESTFRAME_TEST,
|
||||
1 /* bypass cache */,
|
||||
0 /* no aggregation */, env)) {
|
||||
log_err("testframe_init, could not register test opcode");
|
||||
free(d);
|
||||
return 0;
|
||||
}
|
||||
lock_basic_init(&d->lock);
|
||||
lock_protect(&d->lock, d, sizeof(*d));
|
||||
return 1;
|
||||
@@ -218,6 +226,8 @@ static int
|
||||
cachedb_apply_cfg(struct cachedb_env* cachedb_env, struct config_file* cfg)
|
||||
{
|
||||
const char* backend_str = cfg->cachedb_backend;
|
||||
if(!backend_str || *backend_str==0)
|
||||
return 1;
|
||||
cachedb_env->backend = cachedb_find_backend(backend_str);
|
||||
if(!cachedb_env->backend) {
|
||||
log_err("cachedb: cannot find backend name '%s'", backend_str);
|
||||
@@ -228,7 +238,7 @@ cachedb_apply_cfg(struct cachedb_env* cachedb_env, struct config_file* cfg)
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
int
|
||||
cachedb_init(struct module_env* env, int id)
|
||||
{
|
||||
struct cachedb_env* cachedb_env = (struct cachedb_env*)calloc(1,
|
||||
@@ -255,11 +265,11 @@ cachedb_init(struct module_env* env, int id)
|
||||
return 0;
|
||||
}
|
||||
cachedb_env->enabled = 1;
|
||||
if(env->cfg->serve_expired_reply_ttl)
|
||||
if(env->cfg->serve_expired && env->cfg->serve_expired_reply_ttl)
|
||||
log_warn(
|
||||
"cachedb: serve-expired-reply-ttl is set but not working for data "
|
||||
"originating from the external cache; 0 TLL is used for those.");
|
||||
if(env->cfg->serve_expired_client_timeout)
|
||||
"originating from the external cache; 0 TTL is used for those.");
|
||||
if(env->cfg->serve_expired && env->cfg->serve_expired_client_timeout)
|
||||
log_warn(
|
||||
"cachedb: serve-expired-client-timeout is set but not working for "
|
||||
"data originating from the external cache; expired data are used "
|
||||
@@ -267,19 +277,16 @@ cachedb_init(struct module_env* env, int id)
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
void
|
||||
cachedb_deinit(struct module_env* env, int id)
|
||||
{
|
||||
struct cachedb_env* cachedb_env;
|
||||
if(!env || !env->modinfo[id])
|
||||
return;
|
||||
cachedb_env = (struct cachedb_env*)env->modinfo[id];
|
||||
/* free contents */
|
||||
/* TODO */
|
||||
if(cachedb_env->enabled) {
|
||||
(*cachedb_env->backend->deinit)(env, cachedb_env);
|
||||
}
|
||||
|
||||
free(cachedb_env);
|
||||
env->modinfo[id] = NULL;
|
||||
}
|
||||
@@ -406,6 +413,14 @@ prep_data(struct module_qstate* qstate, struct sldns_buffer* buf)
|
||||
if(qstate->return_msg->rep->ttl == 0 &&
|
||||
!qstate->env->cfg->serve_expired)
|
||||
return 0;
|
||||
|
||||
/* The EDE is added to the out-list so it is encoded in the cached message */
|
||||
if (qstate->env->cfg->ede && qstate->return_msg->rep->reason_bogus != LDNS_EDE_NONE) {
|
||||
edns_opt_list_append_ede(&edns.opt_list_out, qstate->env->scratch,
|
||||
qstate->return_msg->rep->reason_bogus,
|
||||
qstate->return_msg->rep->reason_bogus_str);
|
||||
}
|
||||
|
||||
if(verbosity >= VERB_ALGO)
|
||||
log_dns_msg("cachedb encoding", &qstate->return_msg->qinfo,
|
||||
qstate->return_msg->rep);
|
||||
@@ -502,6 +517,7 @@ parse_data(struct module_qstate* qstate, struct sldns_buffer* buf)
|
||||
{
|
||||
struct msg_parse* prs;
|
||||
struct edns_data edns;
|
||||
struct edns_option* ede;
|
||||
uint64_t timestamp, expiry;
|
||||
time_t adjust;
|
||||
size_t lim = sldns_buffer_limit(buf);
|
||||
@@ -539,6 +555,24 @@ parse_data(struct module_qstate* qstate, struct sldns_buffer* buf)
|
||||
if(!qstate->return_msg)
|
||||
return 0;
|
||||
|
||||
/* We find the EDE in the in-list after parsing */
|
||||
if(qstate->env->cfg->ede &&
|
||||
(ede = edns_opt_list_find(edns.opt_list_in, LDNS_EDNS_EDE))) {
|
||||
if(ede->opt_len >= 2) {
|
||||
qstate->return_msg->rep->reason_bogus =
|
||||
sldns_read_uint16(ede->opt_data);
|
||||
}
|
||||
/* allocate space and store the error string and it's size */
|
||||
if(ede->opt_len > 2) {
|
||||
size_t ede_len = ede->opt_len - 2;
|
||||
qstate->return_msg->rep->reason_bogus_str = regional_alloc(
|
||||
qstate->region, sizeof(char) * (ede_len+1));
|
||||
memcpy(qstate->return_msg->rep->reason_bogus_str,
|
||||
ede->opt_data+2, ede_len);
|
||||
qstate->return_msg->rep->reason_bogus_str[ede_len] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
qstate->return_rcode = LDNS_RCODE_NOERROR;
|
||||
|
||||
/* see how much of the TTL expired, and remove it */
|
||||
@@ -551,10 +585,16 @@ parse_data(struct module_qstate* qstate, struct sldns_buffer* buf)
|
||||
verbose(VERB_ALGO, "cachedb msg expired");
|
||||
/* If serve-expired is enabled, we still use an expired message
|
||||
* setting the TTL to 0. */
|
||||
if(qstate->env->cfg->serve_expired)
|
||||
adjust = -1;
|
||||
else
|
||||
if(!qstate->env->cfg->serve_expired ||
|
||||
(FLAGS_GET_RCODE(qstate->return_msg->rep->flags)
|
||||
!= LDNS_RCODE_NOERROR &&
|
||||
FLAGS_GET_RCODE(qstate->return_msg->rep->flags)
|
||||
!= LDNS_RCODE_NXDOMAIN &&
|
||||
FLAGS_GET_RCODE(qstate->return_msg->rep->flags)
|
||||
!= LDNS_RCODE_YXDOMAIN))
|
||||
return 0; /* message expired */
|
||||
else
|
||||
adjust = -1;
|
||||
}
|
||||
verbose(VERB_ALGO, "cachedb msg adjusted down by %d", (int)adjust);
|
||||
adjust_msg_ttl(qstate->return_msg, adjust);
|
||||
@@ -624,11 +664,15 @@ cachedb_extcache_store(struct module_qstate* qstate, struct cachedb_env* ie)
|
||||
* See if unbound's internal cache can answer the query
|
||||
*/
|
||||
static int
|
||||
cachedb_intcache_lookup(struct module_qstate* qstate)
|
||||
cachedb_intcache_lookup(struct module_qstate* qstate, struct cachedb_env* cde)
|
||||
{
|
||||
uint8_t* dpname=NULL;
|
||||
size_t dpnamelen=0;
|
||||
struct dns_msg* msg;
|
||||
/* for testframe bypass this lookup */
|
||||
if(cde->backend == &testframe_backend) {
|
||||
return 0;
|
||||
}
|
||||
if(iter_stub_fwd_no_cache(qstate, &qstate->qinfo,
|
||||
&dpname, &dpnamelen))
|
||||
return 0; /* no cache for these queries */
|
||||
@@ -687,6 +731,7 @@ cachedb_handle_query(struct module_qstate* qstate,
|
||||
struct cachedb_qstate* ATTR_UNUSED(iq),
|
||||
struct cachedb_env* ie, int id)
|
||||
{
|
||||
qstate->is_cachedb_answer = 0;
|
||||
/* check if we are enabled, and skip if so */
|
||||
if(!ie->enabled) {
|
||||
/* pass request to next module */
|
||||
@@ -703,7 +748,7 @@ cachedb_handle_query(struct module_qstate* qstate,
|
||||
|
||||
/* lookup inside unbound's internal cache.
|
||||
* This does not look for expired entries. */
|
||||
if(cachedb_intcache_lookup(qstate)) {
|
||||
if(cachedb_intcache_lookup(qstate, ie)) {
|
||||
if(verbosity >= VERB_ALGO) {
|
||||
if(qstate->return_msg->rep)
|
||||
log_dns_msg("cachedb internal cache lookup",
|
||||
@@ -740,6 +785,7 @@ cachedb_handle_query(struct module_qstate* qstate,
|
||||
qstate->ext_state[id] = module_wait_module;
|
||||
return;
|
||||
}
|
||||
qstate->is_cachedb_answer = 1;
|
||||
/* we are done with the query */
|
||||
qstate->ext_state[id] = module_finished;
|
||||
return;
|
||||
@@ -762,12 +808,18 @@ static void
|
||||
cachedb_handle_response(struct module_qstate* qstate,
|
||||
struct cachedb_qstate* ATTR_UNUSED(iq), struct cachedb_env* ie, int id)
|
||||
{
|
||||
qstate->is_cachedb_answer = 0;
|
||||
/* check if we are not enabled or instructed to not cache, and skip */
|
||||
if(!ie->enabled || qstate->no_cache_store) {
|
||||
/* we are done with the query */
|
||||
qstate->ext_state[id] = module_finished;
|
||||
return;
|
||||
}
|
||||
if(qstate->env->cfg->cachedb_no_store) {
|
||||
/* do not store the item in the external cache */
|
||||
qstate->ext_state[id] = module_finished;
|
||||
return;
|
||||
}
|
||||
|
||||
/* store the item into the backend cache */
|
||||
cachedb_extcache_store(qstate, ie);
|
||||
|
||||
+71
-25
@@ -56,19 +56,43 @@ struct redis_moddata {
|
||||
int numctxs; /* number of ctx entries */
|
||||
const char* server_host; /* server's IP address or host name */
|
||||
int server_port; /* server's TCP port */
|
||||
const char* server_path; /* server's unix path, or "", NULL if unused */
|
||||
const char* server_password; /* server's AUTH password, or "", NULL if unused */
|
||||
struct timeval timeout; /* timeout for connection setup and commands */
|
||||
int logical_db; /* the redis logical database to use */
|
||||
};
|
||||
|
||||
static redisReply* redis_command(struct module_env*, struct cachedb_env*,
|
||||
const char*, const uint8_t*, size_t);
|
||||
|
||||
static void
|
||||
moddata_clean(struct redis_moddata** moddata) {
|
||||
if(!moddata || !*moddata)
|
||||
return;
|
||||
if((*moddata)->ctxs) {
|
||||
int i;
|
||||
for(i = 0; i < (*moddata)->numctxs; i++) {
|
||||
if((*moddata)->ctxs[i])
|
||||
redisFree((*moddata)->ctxs[i]);
|
||||
}
|
||||
free((*moddata)->ctxs);
|
||||
}
|
||||
free(*moddata);
|
||||
*moddata = NULL;
|
||||
}
|
||||
|
||||
static redisContext*
|
||||
redis_connect(const struct redis_moddata* moddata)
|
||||
{
|
||||
redisContext* ctx;
|
||||
|
||||
ctx = redisConnectWithTimeout(moddata->server_host,
|
||||
moddata->server_port, moddata->timeout);
|
||||
if(moddata->server_path && moddata->server_path[0]!=0) {
|
||||
ctx = redisConnectUnixWithTimeout(moddata->server_path,
|
||||
moddata->timeout);
|
||||
} else {
|
||||
ctx = redisConnectWithTimeout(moddata->server_host,
|
||||
moddata->server_port, moddata->timeout);
|
||||
}
|
||||
if(!ctx || ctx->err) {
|
||||
const char *errstr = "out of memory";
|
||||
if(ctx)
|
||||
@@ -80,9 +104,31 @@ redis_connect(const struct redis_moddata* moddata)
|
||||
log_err("failed to set redis timeout");
|
||||
goto fail;
|
||||
}
|
||||
if(moddata->server_password && moddata->server_password[0]!=0) {
|
||||
redisReply* rep;
|
||||
rep = redisCommand(ctx, "AUTH %s", moddata->server_password);
|
||||
if(!rep || rep->type == REDIS_REPLY_ERROR) {
|
||||
log_err("failed to authenticate with password");
|
||||
freeReplyObject(rep);
|
||||
goto fail;
|
||||
}
|
||||
freeReplyObject(rep);
|
||||
}
|
||||
if(moddata->logical_db > 0) {
|
||||
redisReply* rep;
|
||||
rep = redisCommand(ctx, "SELECT %d", moddata->logical_db);
|
||||
if(!rep || rep->type == REDIS_REPLY_ERROR) {
|
||||
log_err("failed to set logical database (%d)",
|
||||
moddata->logical_db);
|
||||
freeReplyObject(rep);
|
||||
goto fail;
|
||||
}
|
||||
freeReplyObject(rep);
|
||||
}
|
||||
verbose(VERB_OPS, "Connection to Redis established");
|
||||
return ctx;
|
||||
|
||||
fail:
|
||||
fail:
|
||||
if(ctx)
|
||||
redisFree(ctx);
|
||||
return NULL;
|
||||
@@ -94,28 +140,36 @@ redis_init(struct module_env* env, struct cachedb_env* cachedb_env)
|
||||
int i;
|
||||
struct redis_moddata* moddata = NULL;
|
||||
|
||||
verbose(VERB_ALGO, "redis_init");
|
||||
verbose(VERB_OPS, "Redis initialization");
|
||||
|
||||
moddata = calloc(1, sizeof(struct redis_moddata));
|
||||
if(!moddata) {
|
||||
log_err("out of memory");
|
||||
return 0;
|
||||
goto fail;
|
||||
}
|
||||
moddata->numctxs = env->cfg->num_threads;
|
||||
moddata->ctxs = calloc(env->cfg->num_threads, sizeof(redisContext*));
|
||||
if(!moddata->ctxs) {
|
||||
log_err("out of memory");
|
||||
free(moddata);
|
||||
return 0;
|
||||
goto fail;
|
||||
}
|
||||
/* note: server_host is a shallow reference to configured string.
|
||||
* we don't have to free it in this module. */
|
||||
moddata->server_host = env->cfg->redis_server_host;
|
||||
moddata->server_port = env->cfg->redis_server_port;
|
||||
moddata->server_path = env->cfg->redis_server_path;
|
||||
moddata->server_password = env->cfg->redis_server_password;
|
||||
moddata->timeout.tv_sec = env->cfg->redis_timeout / 1000;
|
||||
moddata->timeout.tv_usec = (env->cfg->redis_timeout % 1000) * 1000;
|
||||
for(i = 0; i < moddata->numctxs; i++)
|
||||
moddata->ctxs[i] = redis_connect(moddata);
|
||||
moddata->logical_db = env->cfg->redis_logical_db;
|
||||
for(i = 0; i < moddata->numctxs; i++) {
|
||||
redisContext* ctx = redis_connect(moddata);
|
||||
if(!ctx) {
|
||||
log_err("redis_init: failed to init redis");
|
||||
goto fail;
|
||||
}
|
||||
moddata->ctxs[i] = ctx;
|
||||
}
|
||||
cachedb_env->backend_data = moddata;
|
||||
if(env->cfg->redis_expire_records) {
|
||||
redisReply* rep = NULL;
|
||||
@@ -128,7 +182,7 @@ redis_init(struct module_env* env, struct cachedb_env* cachedb_env)
|
||||
log_err("redis_init: failed to init redis, the "
|
||||
"redis-expire-records option requires the SETEX command "
|
||||
"(redis >= 2.0.0)");
|
||||
return 0;
|
||||
goto fail;
|
||||
}
|
||||
redis_reply_type = rep->type;
|
||||
freeReplyObject(rep);
|
||||
@@ -140,11 +194,14 @@ redis_init(struct module_env* env, struct cachedb_env* cachedb_env)
|
||||
log_err("redis_init: failed to init redis, the "
|
||||
"redis-expire-records option requires the SETEX command "
|
||||
"(redis >= 2.0.0)");
|
||||
return 0;
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
fail:
|
||||
moddata_clean(&moddata);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -154,19 +211,8 @@ redis_deinit(struct module_env* env, struct cachedb_env* cachedb_env)
|
||||
cachedb_env->backend_data;
|
||||
(void)env;
|
||||
|
||||
verbose(VERB_ALGO, "redis_deinit");
|
||||
|
||||
if(!moddata)
|
||||
return;
|
||||
if(moddata->ctxs) {
|
||||
int i;
|
||||
for(i = 0; i < moddata->numctxs; i++) {
|
||||
if(moddata->ctxs[i])
|
||||
redisFree(moddata->ctxs[i]);
|
||||
}
|
||||
free(moddata->ctxs);
|
||||
}
|
||||
free(moddata);
|
||||
verbose(VERB_OPS, "Redis deinitialization");
|
||||
moddata_clean(&moddata);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -47,7 +47,7 @@
|
||||
#define SHA512_Update SHA512Update
|
||||
#define SHA512_Final SHA512Final
|
||||
#else
|
||||
#include "openssl/sha.h"
|
||||
#include <openssl/sha.h>
|
||||
#endif
|
||||
|
||||
#include <sys/vfs.h>
|
||||
|
||||
+14
-11
@@ -364,6 +364,9 @@
|
||||
/* Define if we have LibreSSL */
|
||||
#undef HAVE_LIBRESSL
|
||||
|
||||
/* Define to 1 if you have the <linux/net_tstamp.h> header file. */
|
||||
#undef HAVE_LINUX_NET_TSTAMP_H
|
||||
|
||||
/* Define to 1 if you have the `localtime_r' function. */
|
||||
#undef HAVE_LOCALTIME_R
|
||||
|
||||
@@ -1068,39 +1071,39 @@
|
||||
|
||||
#if defined(OMITTED__D_GNU_SOURCE) && !defined(_GNU_SOURCE)
|
||||
#define _GNU_SOURCE 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(OMITTED__D_BSD_SOURCE) && !defined(_BSD_SOURCE)
|
||||
#define _BSD_SOURCE 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(OMITTED__D_DEFAULT_SOURCE) && !defined(_DEFAULT_SOURCE)
|
||||
#define _DEFAULT_SOURCE 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(OMITTED__D__EXTENSIONS__) && !defined(__EXTENSIONS__)
|
||||
#define __EXTENSIONS__ 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(OMITTED__D_POSIX_C_SOURCE_200112) && !defined(_POSIX_C_SOURCE)
|
||||
#define _POSIX_C_SOURCE 200112
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(OMITTED__D_XOPEN_SOURCE_600) && !defined(_XOPEN_SOURCE)
|
||||
#define _XOPEN_SOURCE 600
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(OMITTED__D_XOPEN_SOURCE_EXTENDED_1) && !defined(_XOPEN_SOURCE_EXTENDED)
|
||||
#define _XOPEN_SOURCE_EXTENDED 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(OMITTED__D_ALL_SOURCE) && !defined(_ALL_SOURCE)
|
||||
#define _ALL_SOURCE 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(OMITTED__D_LARGEFILE_SOURCE_1) && !defined(_LARGEFILE_SOURCE)
|
||||
#define _LARGEFILE_SOURCE 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
@@ -1184,7 +1187,7 @@
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
#ifdef HAVE_ATTR_FORMAT
|
||||
# define ATTR_FORMAT(archetype, string_index, first_to_check) \
|
||||
__attribute__ ((format (archetype, string_index, first_to_check)))
|
||||
@@ -1294,7 +1297,7 @@ void* reallocarray(void *ptr, size_t nmemb, size_t size);
|
||||
#ifdef HAVE_WINSOCK2_H
|
||||
#define FD_SET_T (u_int)
|
||||
#else
|
||||
#define FD_SET_T
|
||||
#define FD_SET_T
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
+70
-44
@@ -10,15 +10,15 @@ sinclude(dnscrypt/dnscrypt.m4)
|
||||
|
||||
# must be numbers. ac_defun because of later processing
|
||||
m4_define([VERSION_MAJOR],[1])
|
||||
m4_define([VERSION_MINOR],[17])
|
||||
m4_define([VERSION_MICRO],[1])
|
||||
m4_define([VERSION_MINOR],[19])
|
||||
m4_define([VERSION_MICRO],[2])
|
||||
AC_INIT([unbound],m4_defn([VERSION_MAJOR]).m4_defn([VERSION_MINOR]).m4_defn([VERSION_MICRO]),[unbound-bugs@nlnetlabs.nl or https://github.com/NLnetLabs/unbound/issues],[unbound])
|
||||
AC_SUBST(UNBOUND_VERSION_MAJOR, [VERSION_MAJOR])
|
||||
AC_SUBST(UNBOUND_VERSION_MINOR, [VERSION_MINOR])
|
||||
AC_SUBST(UNBOUND_VERSION_MICRO, [VERSION_MICRO])
|
||||
|
||||
LIBUNBOUND_CURRENT=9
|
||||
LIBUNBOUND_REVISION=21
|
||||
LIBUNBOUND_REVISION=25
|
||||
LIBUNBOUND_AGE=1
|
||||
# 1.0.0 had 0:12:0
|
||||
# 1.0.1 had 0:13:0
|
||||
@@ -107,6 +107,10 @@ LIBUNBOUND_AGE=1
|
||||
# 1.16.3 had 9:19:1
|
||||
# 1.17.0 had 9:20:1
|
||||
# 1.17.1 had 9:21:1
|
||||
# 1.18.0 had 9:22:1
|
||||
# 1.19.0 had 9:23:1
|
||||
# 1.19.1 had 9:24:1
|
||||
# 1.19.2 had 9:25:1
|
||||
|
||||
# Current -- the number of the binary API that we're implementing
|
||||
# Revision -- which iteration of the implementation of the binary
|
||||
@@ -156,7 +160,7 @@ esac
|
||||
|
||||
# are we on MinGW?
|
||||
if uname -s 2>&1 | grep MINGW >/dev/null; then on_mingw="yes"
|
||||
else
|
||||
else
|
||||
if echo $host | grep mingw >/dev/null; then on_mingw="yes"
|
||||
else on_mingw="no"; fi
|
||||
fi
|
||||
@@ -185,9 +189,9 @@ ub_conf_dir=`AS_DIRNAME(["$ub_conf_file"])`
|
||||
AC_SUBST(ub_conf_dir)
|
||||
|
||||
# Determine run, chroot directory and pidfile locations
|
||||
AC_ARG_WITH(run-dir,
|
||||
AS_HELP_STRING([--with-run-dir=path],[set default directory to chdir to (by default dir part of cfg file)]),
|
||||
UNBOUND_RUN_DIR="$withval",
|
||||
AC_ARG_WITH(run-dir,
|
||||
AS_HELP_STRING([--with-run-dir=path],[set default directory to chdir to (by default dir part of cfg file)]),
|
||||
UNBOUND_RUN_DIR="$withval",
|
||||
if test $on_mingw = no; then
|
||||
UNBOUND_RUN_DIR=`dirname "$ub_conf_file"`
|
||||
else
|
||||
@@ -198,9 +202,9 @@ AC_SUBST(UNBOUND_RUN_DIR)
|
||||
ACX_ESCAPE_BACKSLASH($UNBOUND_RUN_DIR, hdr_run)
|
||||
AC_DEFINE_UNQUOTED(RUN_DIR, ["$hdr_run"], [Directory to chdir to])
|
||||
|
||||
AC_ARG_WITH(chroot-dir,
|
||||
AS_HELP_STRING([--with-chroot-dir=path],[set default directory to chroot to (by default same as run-dir)]),
|
||||
UNBOUND_CHROOT_DIR="$withval",
|
||||
AC_ARG_WITH(chroot-dir,
|
||||
AS_HELP_STRING([--with-chroot-dir=path],[set default directory to chroot to (by default same as run-dir)]),
|
||||
UNBOUND_CHROOT_DIR="$withval",
|
||||
if test $on_mingw = no; then
|
||||
UNBOUND_CHROOT_DIR="$UNBOUND_RUN_DIR"
|
||||
else
|
||||
@@ -218,9 +222,9 @@ AC_ARG_WITH(share-dir,
|
||||
AC_SUBST(UNBOUND_SHARE_DIR)
|
||||
AC_DEFINE_UNQUOTED(SHARE_DIR, ["$UNBOUND_SHARE_DIR"], [Shared data])
|
||||
|
||||
AC_ARG_WITH(pidfile,
|
||||
AS_HELP_STRING([--with-pidfile=filename],[set default pathname to unbound pidfile (default run-dir/unbound.pid)]),
|
||||
UNBOUND_PIDFILE="$withval",
|
||||
AC_ARG_WITH(pidfile,
|
||||
AS_HELP_STRING([--with-pidfile=filename],[set default pathname to unbound pidfile (default run-dir/unbound.pid)]),
|
||||
UNBOUND_PIDFILE="$withval",
|
||||
if test $on_mingw = no; then
|
||||
UNBOUND_PIDFILE="$UNBOUND_RUN_DIR/unbound.pid"
|
||||
else
|
||||
@@ -231,9 +235,9 @@ AC_SUBST(UNBOUND_PIDFILE)
|
||||
ACX_ESCAPE_BACKSLASH($UNBOUND_PIDFILE, hdr_pid)
|
||||
AC_DEFINE_UNQUOTED(PIDFILE, ["$hdr_pid"], [default pidfile location])
|
||||
|
||||
AC_ARG_WITH(rootkey-file,
|
||||
AS_HELP_STRING([--with-rootkey-file=filename],[set default pathname to root key file (default run-dir/root.key). This file is read and written.]),
|
||||
UNBOUND_ROOTKEY_FILE="$withval",
|
||||
AC_ARG_WITH(rootkey-file,
|
||||
AS_HELP_STRING([--with-rootkey-file=filename],[set default pathname to root key file (default run-dir/root.key). This file is read and written.]),
|
||||
UNBOUND_ROOTKEY_FILE="$withval",
|
||||
if test $on_mingw = no; then
|
||||
UNBOUND_ROOTKEY_FILE="$UNBOUND_RUN_DIR/root.key"
|
||||
else
|
||||
@@ -244,9 +248,9 @@ AC_SUBST(UNBOUND_ROOTKEY_FILE)
|
||||
ACX_ESCAPE_BACKSLASH($UNBOUND_ROOTKEY_FILE, hdr_rkey)
|
||||
AC_DEFINE_UNQUOTED(ROOT_ANCHOR_FILE, ["$hdr_rkey"], [default rootkey location])
|
||||
|
||||
AC_ARG_WITH(rootcert-file,
|
||||
AS_HELP_STRING([--with-rootcert-file=filename],[set default pathname to root update certificate file (default run-dir/icannbundle.pem). This file need not exist if you are content with the builtin.]),
|
||||
UNBOUND_ROOTCERT_FILE="$withval",
|
||||
AC_ARG_WITH(rootcert-file,
|
||||
AS_HELP_STRING([--with-rootcert-file=filename],[set default pathname to root update certificate file (default run-dir/icannbundle.pem). This file need not exist if you are content with the builtin.]),
|
||||
UNBOUND_ROOTCERT_FILE="$withval",
|
||||
if test $on_mingw = no; then
|
||||
UNBOUND_ROOTCERT_FILE="$UNBOUND_RUN_DIR/icannbundle.pem"
|
||||
else
|
||||
@@ -257,9 +261,9 @@ AC_SUBST(UNBOUND_ROOTCERT_FILE)
|
||||
ACX_ESCAPE_BACKSLASH($UNBOUND_ROOTCERT_FILE, hdr_rpem)
|
||||
AC_DEFINE_UNQUOTED(ROOT_CERT_FILE, ["$hdr_rpem"], [default rootcert location])
|
||||
|
||||
AC_ARG_WITH(username,
|
||||
AS_HELP_STRING([--with-username=user],[set default user that unbound changes to (default user is unbound)]),
|
||||
UNBOUND_USERNAME="$withval",
|
||||
AC_ARG_WITH(username,
|
||||
AS_HELP_STRING([--with-username=user],[set default user that unbound changes to (default user is unbound)]),
|
||||
UNBOUND_USERNAME="$withval",
|
||||
UNBOUND_USERNAME="unbound")
|
||||
AC_SUBST(UNBOUND_USERNAME)
|
||||
AC_DEFINE_UNQUOTED(UB_USERNAME, ["$UNBOUND_USERNAME"], [default username])
|
||||
@@ -278,14 +282,14 @@ ACX_CHECK_COMPILER_FLAG(g, [CFLAGS="$CFLAGS -g"])
|
||||
ACX_CHECK_COMPILER_FLAG(O2, [CFLAGS="$CFLAGS -O2"])
|
||||
default_cflags=yes
|
||||
fi
|
||||
AC_PROG_CC
|
||||
m4_version_prereq([2.70], [AC_PROG_CC], [AC_PROG_CC_STDC])
|
||||
ACX_DEPFLAG
|
||||
ACX_DETERMINE_EXT_FLAGS_UNBOUND
|
||||
|
||||
# debug mode flags warnings
|
||||
AC_ARG_ENABLE(checking, AS_HELP_STRING([--enable-checking],[Enable warnings, asserts, makefile-dependencies]))
|
||||
AC_ARG_ENABLE(debug, AS_HELP_STRING([--enable-debug],[same as enable-checking]))
|
||||
if test "$enable_debug" = "yes"; then debug_enabled="$enable_debug";
|
||||
if test "$enable_debug" = "yes"; then debug_enabled="$enable_debug";
|
||||
else debug_enabled="$enable_checking"; fi
|
||||
AC_SUBST(debug_enabled)
|
||||
case "$debug_enabled" in
|
||||
@@ -388,7 +392,17 @@ fi
|
||||
if test "$LEX" != "" -a "$LEX" != ":"; then
|
||||
ACX_YYLEX_OPTION
|
||||
fi
|
||||
if test "$LEX" = "" -o "$LEX" = ":"; then
|
||||
if test ! -f util/configlexer.c; then
|
||||
AC_MSG_ERROR([no lex and no util/configlexer.c: need flex and bison to compile from source repository.])
|
||||
fi
|
||||
fi
|
||||
AC_PROG_YACC
|
||||
if test "$YACC" = "" -o "$YACC" = ":"; then
|
||||
if test ! -f util/configparser.c; then
|
||||
AC_MSG_ERROR([no yacc and no util/configparser.c: need flex and bison to compile from source repository.])
|
||||
fi
|
||||
fi
|
||||
AC_CHECK_PROG(doxygen, doxygen, doxygen)
|
||||
AC_CHECK_TOOL(STRIP, strip)
|
||||
ACX_LIBTOOL_C_ONLY
|
||||
@@ -453,6 +467,9 @@ AC_CHECK_HEADERS([netioapi.h],,, [AC_INCLUDES_DEFAULT
|
||||
#endif
|
||||
])
|
||||
|
||||
# Check for Linux timestamping headers
|
||||
AC_CHECK_HEADERS([linux/net_tstamp.h],,, [AC_INCLUDES_DEFAULT])
|
||||
|
||||
# check for types.
|
||||
# Using own tests for int64* because autoconf builtin only give 32bit.
|
||||
AC_CHECK_TYPE(int8_t, signed char)
|
||||
@@ -511,7 +528,8 @@ res = strptime("2010-07-15T00:00:00+00:00", "%t%Y%t-%t%m%t-%t%d%tT%t%H%t:%t%M%t:
|
||||
if (!res) return 2;
|
||||
res = strptime("20070207111842", "%Y%m%d%H%M%S", &tm);
|
||||
if (!res) return 1; return 0; }
|
||||
]])] , [eval "ac_cv_c_strptime_works=yes"], [eval "ac_cv_c_strptime_works=no"])
|
||||
]])] , [eval "ac_cv_c_strptime_works=yes"], [eval "ac_cv_c_strptime_works=no"],
|
||||
[eval "ac_cv_c_strptime_works=maybe"])
|
||||
else
|
||||
eval "ac_cv_c_strptime_works=maybe"
|
||||
fi
|
||||
@@ -548,11 +566,11 @@ sinclude(systemd.m4)
|
||||
# Include systemd.m4 - end
|
||||
|
||||
# set memory allocation checking if requested
|
||||
AC_ARG_ENABLE(alloc-checks, AS_HELP_STRING([--enable-alloc-checks],[ enable to memory allocation statistics, for debug purposes ]),
|
||||
AC_ARG_ENABLE(alloc-checks, AS_HELP_STRING([--enable-alloc-checks],[ enable to memory allocation statistics, for debug purposes ]),
|
||||
, )
|
||||
AC_ARG_ENABLE(alloc-lite, AS_HELP_STRING([--enable-alloc-lite],[ enable for lightweight alloc assertions, for debug purposes ]),
|
||||
AC_ARG_ENABLE(alloc-lite, AS_HELP_STRING([--enable-alloc-lite],[ enable for lightweight alloc assertions, for debug purposes ]),
|
||||
, )
|
||||
AC_ARG_ENABLE(alloc-nonregional, AS_HELP_STRING([--enable-alloc-nonregional],[ enable nonregional allocs, slow but exposes regional allocations to other memory purifiers, for debug purposes ]),
|
||||
AC_ARG_ENABLE(alloc-nonregional, AS_HELP_STRING([--enable-alloc-nonregional],[ enable nonregional allocs, slow but exposes regional allocations to other memory purifiers, for debug purposes ]),
|
||||
, )
|
||||
if test x_$enable_alloc_nonregional = x_yes; then
|
||||
AC_DEFINE(UNBOUND_ALLOC_NONREGIONAL, 1, [use malloc not regions, for debug use])
|
||||
@@ -585,7 +603,7 @@ if test "$on_mingw" = "yes"; then
|
||||
])],
|
||||
AC_MSG_RESULT(yes)
|
||||
AC_DEFINE(HAVE_WINDOWS_THREADS, 1, [Using Windows threads])
|
||||
,
|
||||
,
|
||||
AC_MSG_RESULT(no)
|
||||
)
|
||||
|
||||
@@ -596,7 +614,7 @@ else
|
||||
# check this first, so that the pthread lib does not get linked in via
|
||||
# libssl or libpython, and thus distorts the tests, and we end up using
|
||||
# the non-threadsafe C libraries.
|
||||
AC_ARG_WITH(pthreads, AS_HELP_STRING([--with-pthreads],[use pthreads library, or --without-pthreads to disable threading support.]),
|
||||
AC_ARG_WITH(pthreads, AS_HELP_STRING([--with-pthreads],[use pthreads library, or --without-pthreads to disable threading support.]),
|
||||
[ ],[ withval="yes" ])
|
||||
ub_have_pthreads=no
|
||||
if test x_$withval != x_no; then
|
||||
@@ -623,7 +641,7 @@ int main(void) {return 0;}
|
||||
# first compile
|
||||
echo "$CC $CFLAGS -c conftest.c -o conftest.o" >&AS_MESSAGE_LOG_FD
|
||||
$CC $CFLAGS -c conftest.c -o conftest.o 2>&AS_MESSAGE_LOG_FD >&AS_MESSAGE_LOG_FD
|
||||
if test $? = 0; then
|
||||
if test $? = 0; then
|
||||
# then link
|
||||
echo "$CC $CFLAGS -Werror $LDFLAGS $LIBS -o conftest contest.o" >&AS_MESSAGE_LOG_FD
|
||||
$CC $CFLAGS -Werror $LDFLAGS $LIBS -o conftest conftest.o 2>&AS_MESSAGE_LOG_FD >&AS_MESSAGE_LOG_FD
|
||||
@@ -644,7 +662,7 @@ int main(void) {return 0;}
|
||||
])
|
||||
fi
|
||||
|
||||
# check solaris thread library
|
||||
# check solaris thread library
|
||||
AC_ARG_WITH(solaris-threads, AS_HELP_STRING([--with-solaris-threads],[use solaris native thread library.]), [ ],[ withval="no" ])
|
||||
ub_have_sol_threads=no
|
||||
if test x_$withval != x_no; then
|
||||
@@ -658,8 +676,8 @@ if test x_$withval != x_no; then
|
||||
ACX_CHECK_COMPILER_FLAG(mt, [CFLAGS="$CFLAGS -mt"],
|
||||
[CFLAGS="$CFLAGS -D_REENTRANT"])
|
||||
ub_have_sol_threads=yes
|
||||
] , [
|
||||
AC_MSG_ERROR([no solaris threads found.])
|
||||
] , [
|
||||
AC_MSG_ERROR([no solaris threads found.])
|
||||
])
|
||||
fi
|
||||
fi
|
||||
@@ -734,7 +752,14 @@ if test x_$ub_test_python != x_no; then
|
||||
ac_save_LIBS="$LIBS" dnl otherwise AC_PYTHON_DEVEL thrashes $LIBS
|
||||
AC_PYTHON_DEVEL
|
||||
if test ! -z "$PYTHON_VERSION"; then
|
||||
if test `$PYTHON -c "print('$PYTHON_VERSION' >= '2.4.0')"` = "False"; then
|
||||
badversion="no"
|
||||
if test "$PYTHON_VERSION_MAJOR" -lt 2; then
|
||||
badversion="yes"
|
||||
fi
|
||||
if test "$PYTHON_VERSION_MAJOR" -eq 2 -a "$PYTHON_VERSION_MINOR" -lt 4; then
|
||||
badversion="yes"
|
||||
fi
|
||||
if test "$badversion" = "yes"; then
|
||||
AC_MSG_ERROR([Python version >= 2.4.0 is required])
|
||||
fi
|
||||
|
||||
@@ -1085,7 +1110,7 @@ int load_gost_id(void)
|
||||
EVP_PKEY_asn1_get0_info(&gost_id, NULL, NULL, NULL, NULL, meth);
|
||||
return gost_id;
|
||||
}
|
||||
int main(void) {
|
||||
int main(void) {
|
||||
EVP_MD_CTX* ctx;
|
||||
const EVP_MD* md;
|
||||
unsigned char digest[64]; /* its a 256-bit digest, so uses 32 bytes */
|
||||
@@ -1116,7 +1141,8 @@ int main(void) {
|
||||
return 6;
|
||||
return 0;
|
||||
}
|
||||
]])] , [eval "ac_cv_c_gost_works=yes"], [eval "ac_cv_c_gost_works=no"])
|
||||
]])] , [eval "ac_cv_c_gost_works=yes"], [eval "ac_cv_c_gost_works=no"],
|
||||
[eval "ac_cv_c_gost_works=maybe"])
|
||||
CFLAGS="$BAKCFLAGS"
|
||||
else
|
||||
eval "ac_cv_c_gost_works=maybe"
|
||||
@@ -1529,7 +1555,7 @@ if test x_$enable_fully_static = x_yes; then
|
||||
fi
|
||||
|
||||
# set lock checking if requested
|
||||
AC_ARG_ENABLE(lock_checks, AS_HELP_STRING([--enable-lock-checks],[ enable to check lock and unlock calls, for debug purposes ]),
|
||||
AC_ARG_ENABLE(lock_checks, AS_HELP_STRING([--enable-lock-checks],[ enable to check lock and unlock calls, for debug purposes ]),
|
||||
, )
|
||||
if test x_$enable_lock_checks = x_yes; then
|
||||
AC_DEFINE(ENABLE_LOCK_CHECKS, 1, [Define if you want to use debug lock checking (slow).])
|
||||
@@ -1693,7 +1719,7 @@ int main(void) { return !(snprintf(NULL, 0, "test") == 4); }
|
||||
AC_MSG_RESULT(no)
|
||||
AC_DEFINE([SNPRINTF_RET_BROKEN], [], [define if (v)snprintf does not return length needed, (but length used)])
|
||||
AC_LIBOBJ(snprintf)
|
||||
])
|
||||
], [AC_MSG_RESULT(maybe)])
|
||||
fi
|
||||
fi
|
||||
AC_REPLACE_FUNCS(strlcat)
|
||||
@@ -1923,7 +1949,7 @@ case "$enable_explicit_port_randomisation" in
|
||||
esac
|
||||
|
||||
if echo "$host" | $GREP -i -e linux >/dev/null; then
|
||||
AC_ARG_ENABLE(linux-ip-local-port-range, AC_HELP_STRING([--enable-linux-ip-local-port-range], [Define this to enable use of /proc/sys/net/ipv4/ip_local_port_range as a default outgoing port range. This is only for the libunbound on Linux and does not affect unbound resolving daemon itself. This may severely limit the number of available outgoing ports and thus decrease randomness. Define this only when the target system restricts (e.g. some of SELinux enabled distributions) the use of non-ephemeral ports.]))
|
||||
AC_ARG_ENABLE(linux-ip-local-port-range, AS_HELP_STRING([--enable-linux-ip-local-port-range], [Define this to enable use of /proc/sys/net/ipv4/ip_local_port_range as a default outgoing port range. This is only for the libunbound on Linux and does not affect unbound resolving daemon itself. This may severely limit the number of available outgoing ports and thus decrease randomness. Define this only when the target system restricts (e.g. some of SELinux enabled distributions) the use of non-ephemeral ports.]))
|
||||
case "$enable_linux_ip_local_port_range" in
|
||||
yes)
|
||||
AC_DEFINE([USE_LINUX_IP_LOCAL_PORT_RANGE], [1], [Define this to enable use of /proc/sys/net/ipv4/ip_local_port_range as a default outgoing port range. This is only for the libunbound on Linux and does not affect unbound resolving daemon itself. This may severely limit the number of available outgoing ports and thus decrease randomness. Define this only when the target system restricts (e.g. some of SELinux enabled distributions) the use of non-ephemeral ports.])
|
||||
@@ -1980,11 +2006,11 @@ AC_ARG_WITH(libunbound-only, AS_HELP_STRING([--with-libunbound-only],[do not bui
|
||||
fi
|
||||
])
|
||||
if test $ALLTARGET = "alltargets"; then
|
||||
if test $USE_NSS = "yes"; then
|
||||
AC_MSG_ERROR([--with-nss can only be used in combination with --with-libunbound-only.])
|
||||
if test $USE_NSS = "yes"; then
|
||||
AC_MSG_ERROR([--with-nss can only be used in combination with --with-libunbound-only.])
|
||||
fi
|
||||
if test $USE_NETTLE = "yes"; then
|
||||
AC_MSG_ERROR([--with-nettle can only be used in combination with --with-libunbound-only.])
|
||||
AC_MSG_ERROR([--with-nettle can only be used in combination with --with-libunbound-only.])
|
||||
fi
|
||||
fi
|
||||
|
||||
@@ -1995,7 +2021,7 @@ ACX_STRIP_EXT_FLAGS
|
||||
if test -n "$LATE_LDFLAGS"; then
|
||||
LDFLAGS="$LATE_LDFLAGS $LDFLAGS"
|
||||
fi
|
||||
# remove start spaces
|
||||
# remove start spaces
|
||||
LDFLAGS=`echo "$LDFLAGS"|sed -e 's/^ *//'`
|
||||
LIBS=`echo "$LIBS"|sed -e 's/^ *//'`
|
||||
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
FROM gcc:latest
|
||||
WORKDIR /usr/src/unbound
|
||||
RUN apt-get update
|
||||
# install semantic parser & lexical analyzer
|
||||
RUN apt-get install -y bison flex
|
||||
# install packages used in tests
|
||||
RUN apt-get install -y ldnsutils dnsutils xxd splint doxygen netcat
|
||||
RUN apt-get update && apt-get install -y bison flex ldnsutils dnsutils xxd splint doxygen netcat-openbsd
|
||||
# accept short rsa keys, which are used in tests
|
||||
RUN sed -i 's/SECLEVEL=2/SECLEVEL=1/g' /usr/lib/ssl/openssl.cnf
|
||||
|
||||
|
||||
@@ -55,3 +55,6 @@ distribution but may be helpful.
|
||||
contributed by Andreas Schulze.
|
||||
* metrics.awk: awk script that can convert unbound-control stats to
|
||||
Prometheus metrics format output.
|
||||
* unbound.init_yocto: An init script to start and stop the server. Put it
|
||||
in /etc/init.d/unbound to use it. It is for the Yocto Project, in
|
||||
embedded systems, contributed by beni-sandu.
|
||||
|
||||
@@ -105,9 +105,9 @@ index 2482a1f4..bd5ba243 100644
|
||||
--- a/iterator/iter_utils.c
|
||||
+++ b/iterator/iter_utils.c
|
||||
@@ -177,6 +177,7 @@ iter_apply_cfg(struct iter_env* iter_env, struct config_file* cfg)
|
||||
iter_env->supports_ipv6 = cfg->do_ip6;
|
||||
iter_env->supports_ipv4 = cfg->do_ip4;
|
||||
iter_env->outbound_msg_retry = cfg->outbound_msg_retry;
|
||||
iter_env->max_sent_count = cfg->max_sent_count;
|
||||
iter_env->max_query_restarts = cfg->max_query_restarts;
|
||||
+ iter_env->aaaa_filter = cfg->aaaa_filter;
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,139 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# unbound This shell script takes care of starting and stopping
|
||||
# unbound (DNS server).
|
||||
#
|
||||
# chkconfig: - 14 86
|
||||
# description: unbound is a Domain Name Server (DNS) \
|
||||
# that is used to resolve host names to IP addresses.
|
||||
|
||||
### BEGIN INIT INFO
|
||||
# Provides: $named unbound
|
||||
# Required-Start: $network $local_fs
|
||||
# Required-Stop: $network $local_fs
|
||||
# Should-Start: $syslog
|
||||
# Should-Stop: $syslog
|
||||
# Short-Description: unbound recursive Domain Name Server.
|
||||
# Description: unbound is a Domain Name Server (DNS)
|
||||
# that is used to resolve host names to IP addresses.
|
||||
### END INIT INFO
|
||||
|
||||
# Source function library.
|
||||
. /etc/init.d/functions
|
||||
|
||||
exec="/usr/sbin/unbound"
|
||||
prog="unbound"
|
||||
config="/etc/unbound/unbound.conf"
|
||||
pidfile="/var/unbound/unbound.pid"
|
||||
rootdir="/var/unbound"
|
||||
|
||||
[ -e /etc/sysconfig/$prog ] && . /etc/sysconfig/$prog
|
||||
|
||||
lockfile=/var/lock/subsys/$prog
|
||||
|
||||
start() {
|
||||
[ -x $exec ] || exit 5
|
||||
[ -f $config ] || exit 6
|
||||
echo -n $"Starting $prog: "
|
||||
|
||||
# setup root jail
|
||||
if [ -s /etc/localtime ]; then
|
||||
[ -d ${rootdir}/etc ] || mkdir -p ${rootdir}/etc ;
|
||||
if [ ! -e ${rootdir}/etc/localtime ] || ! /usr/bin/cmp -s /etc/localtime ${rootdir}/etc/localtime; then
|
||||
cp -fp /etc/localtime ${rootdir}/etc/localtime
|
||||
fi;
|
||||
fi;
|
||||
if [ -s /etc/resolv.conf ]; then
|
||||
[ -d ${rootdir}/etc ] || mkdir -p ${rootdir}/etc ;
|
||||
if [ ! -e ${rootdir}/etc/resolv.conf ] || ! /usr/bin/cmp -s /etc/resolv.conf ${rootdir}/etc/resolv.conf; then
|
||||
cp -fp /etc/resolv.conf ${rootdir}/etc/resolv.conf
|
||||
fi;
|
||||
fi;
|
||||
if ! egrep -q '^/[^[:space:]]+[[:space:]]+'${rootdir}'/dev/log' /proc/mounts; then
|
||||
[ -d ${rootdir}/dev ] || mkdir -p ${rootdir}/dev ;
|
||||
[ -e ${rootdir}/dev/log ] || touch ${rootdir}/dev/log
|
||||
mount --bind -n /dev/log ${rootdir}/dev/log >/dev/null 2>&1;
|
||||
fi;
|
||||
if ! egrep -q '^/[^[:space:]]+[[:space:]]+'${rootdir}'/dev/random' /proc/mounts; then
|
||||
[ -d ${rootdir}/dev ] || mkdir -p ${rootdir}/dev ;
|
||||
[ -e ${rootdir}/dev/random ] || touch ${rootdir}/dev/random
|
||||
mount --bind -n /dev/random ${rootdir}/dev/random >/dev/null 2>&1;
|
||||
fi;
|
||||
|
||||
# if not running, start it up here
|
||||
daemonize $exec
|
||||
retval=$?
|
||||
echo
|
||||
[ $retval -eq 0 ] && touch $lockfile
|
||||
return $retval
|
||||
}
|
||||
|
||||
stop() {
|
||||
echo -n $"Stopping $prog: "
|
||||
# stop it here, often "killproc $prog"
|
||||
killproc $prog
|
||||
retval=$?
|
||||
echo
|
||||
[ $retval -eq 0 ] && rm -f $lockfile
|
||||
if egrep -q '^/[^[:space:]]+[[:space:]]+'${rootdir}'/dev/log' /proc/mounts; then
|
||||
umount ${rootdir}/dev/log >/dev/null 2>&1
|
||||
fi;
|
||||
if egrep -q '^/[^[:space:]]+[[:space:]]+'${rootdir}'/dev/random' /proc/mounts; then
|
||||
umount ${rootdir}/dev/random >/dev/null 2>&1
|
||||
fi;
|
||||
return $retval
|
||||
}
|
||||
|
||||
restart() {
|
||||
stop
|
||||
start
|
||||
}
|
||||
|
||||
reload() {
|
||||
kill -HUP `cat $pidfile`
|
||||
}
|
||||
|
||||
force_reload() {
|
||||
restart
|
||||
}
|
||||
|
||||
rh_status() {
|
||||
# run checks to determine if the service is running or use generic status
|
||||
status $prog
|
||||
}
|
||||
|
||||
rh_status_q() {
|
||||
rh_status -p $pidfile >/dev/null 2>&1
|
||||
}
|
||||
|
||||
case "$1" in
|
||||
start)
|
||||
rh_status_q && exit 0
|
||||
$1
|
||||
;;
|
||||
stop)
|
||||
rh_status_q || exit 0
|
||||
$1
|
||||
;;
|
||||
restart)
|
||||
$1
|
||||
;;
|
||||
reload)
|
||||
rh_status_q || exit 7
|
||||
$1
|
||||
;;
|
||||
force-reload)
|
||||
force_reload
|
||||
;;
|
||||
status)
|
||||
rh_status
|
||||
;;
|
||||
condrestart|try-restart)
|
||||
rh_status_q || exit 0
|
||||
restart
|
||||
;;
|
||||
*)
|
||||
echo $"Usage: $0 {start|stop|status|restart|condrestart|try-restart|reload|force-reload}"
|
||||
exit 2
|
||||
esac
|
||||
exit $?
|
||||
@@ -42,9 +42,8 @@
|
||||
[Unit]
|
||||
Description=Validating, recursive, and caching DNS resolver
|
||||
Documentation=man:unbound(8)
|
||||
After=network-online.target
|
||||
Before=nss-lookup.target
|
||||
Wants=network-online.target nss-lookup.target
|
||||
After=network.target
|
||||
Before=network-online.target nss-lookup.target
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
|
||||
@@ -109,6 +109,8 @@ parse_acl_access(const char* str, enum acl_access* control)
|
||||
*control = acl_allow_snoop;
|
||||
else if(strcmp(str, "allow_setrd") == 0)
|
||||
*control = acl_allow_setrd;
|
||||
else if (strcmp(str, "allow_cookie") == 0)
|
||||
*control = acl_allow_cookie;
|
||||
else {
|
||||
log_err("access control type %s unknown", str);
|
||||
return 0;
|
||||
|
||||
+6
-2
@@ -64,8 +64,12 @@ enum acl_access {
|
||||
acl_allow,
|
||||
/** allow full access for all queries, recursion and cache snooping */
|
||||
acl_allow_snoop,
|
||||
/** allow full access for recursion queries and set RD flag regardless of request */
|
||||
acl_allow_setrd
|
||||
/** allow full access for recursion queries and set RD flag regardless
|
||||
* of request */
|
||||
acl_allow_setrd,
|
||||
/** allow full access for recursion (+RD) queries if valid cookie
|
||||
* present or stateful transport */
|
||||
acl_allow_cookie
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
+25
-12
@@ -166,8 +166,7 @@ dump_msg_ref(RES* ssl, struct ub_packed_rrset_key* k)
|
||||
|
||||
/** dump message entry */
|
||||
static int
|
||||
dump_msg(RES* ssl, struct query_info* k, struct reply_info* d,
|
||||
time_t now)
|
||||
dump_msg(RES* ssl, struct query_info* k, struct reply_info* d, time_t now)
|
||||
{
|
||||
size_t i;
|
||||
char* nm, *tp, *cl;
|
||||
@@ -192,13 +191,15 @@ dump_msg(RES* ssl, struct query_info* k, struct reply_info* d,
|
||||
}
|
||||
|
||||
/* meta line */
|
||||
if(!ssl_printf(ssl, "msg %s %s %s %d %d " ARG_LL "d %d %u %u %u\n",
|
||||
if(!ssl_printf(ssl, "msg %s %s %s %d %d " ARG_LL "d %d %u %u %u %d %s\n",
|
||||
nm, cl, tp,
|
||||
(int)d->flags, (int)d->qdcount,
|
||||
(long long)(d->ttl-now), (int)d->security,
|
||||
(unsigned)d->an_numrrsets,
|
||||
(unsigned)d->an_numrrsets,
|
||||
(unsigned)d->ns_numrrsets,
|
||||
(unsigned)d->ar_numrrsets)) {
|
||||
(unsigned)d->ar_numrrsets,
|
||||
(int)d->reason_bogus,
|
||||
d->reason_bogus_str?d->reason_bogus_str:"")) {
|
||||
free(nm);
|
||||
free(tp);
|
||||
free(cl);
|
||||
@@ -387,7 +388,7 @@ move_into_cache(struct ub_packed_rrset_key* k,
|
||||
struct rrset_ref ref;
|
||||
uint8_t* p;
|
||||
|
||||
ak = alloc_special_obtain(&worker->alloc);
|
||||
ak = alloc_special_obtain(worker->alloc);
|
||||
if(!ak) {
|
||||
log_warn("error out of memory");
|
||||
return 0;
|
||||
@@ -398,7 +399,7 @@ move_into_cache(struct ub_packed_rrset_key* k,
|
||||
ak->rk.dname = (uint8_t*)memdup(k->rk.dname, k->rk.dname_len);
|
||||
if(!ak->rk.dname) {
|
||||
log_warn("error out of memory");
|
||||
ub_packed_rrset_parsedelete(ak, &worker->alloc);
|
||||
ub_packed_rrset_parsedelete(ak, worker->alloc);
|
||||
return 0;
|
||||
}
|
||||
s = sizeof(*ad) + (sizeof(size_t) + sizeof(uint8_t*) +
|
||||
@@ -408,7 +409,7 @@ move_into_cache(struct ub_packed_rrset_key* k,
|
||||
ad = (struct packed_rrset_data*)malloc(s);
|
||||
if(!ad) {
|
||||
log_warn("error out of memory");
|
||||
ub_packed_rrset_parsedelete(ak, &worker->alloc);
|
||||
ub_packed_rrset_parsedelete(ak, worker->alloc);
|
||||
return 0;
|
||||
}
|
||||
p = (uint8_t*)ad;
|
||||
@@ -431,7 +432,8 @@ move_into_cache(struct ub_packed_rrset_key* k,
|
||||
ref.key = ak;
|
||||
ref.id = ak->id;
|
||||
(void)rrset_cache_update(worker->env.rrset_cache, &ref,
|
||||
&worker->alloc, *worker->env.now);
|
||||
worker->alloc, *worker->env.now);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -632,6 +634,9 @@ load_msg(RES* ssl, sldns_buffer* buf, struct worker* worker)
|
||||
long long ttl;
|
||||
size_t i;
|
||||
int go_on = 1;
|
||||
int ede;
|
||||
int consumed = 0;
|
||||
char* ede_str = NULL;
|
||||
|
||||
regional_free_all(region);
|
||||
|
||||
@@ -646,11 +651,16 @@ load_msg(RES* ssl, sldns_buffer* buf, struct worker* worker)
|
||||
}
|
||||
|
||||
/* read remainder of line */
|
||||
if(sscanf(s, " %u %u " ARG_LL "d %u %u %u %u", &flags, &qdcount, &ttl,
|
||||
&security, &an, &ns, &ar) != 7) {
|
||||
/* note the last space before any possible EDE text */
|
||||
if(sscanf(s, " %u %u " ARG_LL "d %u %u %u %u %d %n", &flags, &qdcount, &ttl,
|
||||
&security, &an, &ns, &ar, &ede, &consumed) != 8) {
|
||||
log_warn("error cannot parse numbers: %s", s);
|
||||
return 0;
|
||||
}
|
||||
/* there may be EDE text after the numbers */
|
||||
if(consumed > 0 && (size_t)consumed < strlen(s))
|
||||
ede_str = s + consumed;
|
||||
memset(&rep, 0, sizeof(rep));
|
||||
rep.flags = (uint16_t)flags;
|
||||
rep.qdcount = (uint16_t)qdcount;
|
||||
rep.ttl = (time_t)ttl;
|
||||
@@ -665,6 +675,8 @@ load_msg(RES* ssl, sldns_buffer* buf, struct worker* worker)
|
||||
rep.ns_numrrsets = (size_t)ns;
|
||||
rep.ar_numrrsets = (size_t)ar;
|
||||
rep.rrset_count = (size_t)an+(size_t)ns+(size_t)ar;
|
||||
rep.reason_bogus = (sldns_ede_code)ede;
|
||||
rep.reason_bogus_str = ede_str?(char*)regional_strdup(region, ede_str):NULL;
|
||||
rep.rrsets = (struct ub_packed_rrset_key**)regional_alloc_zero(
|
||||
region, sizeof(struct ub_packed_rrset_key*)*rep.rrset_count);
|
||||
|
||||
@@ -859,7 +871,8 @@ int print_deleg_lookup(RES* ssl, struct worker* worker, uint8_t* nm,
|
||||
/* go up? */
|
||||
if(iter_dp_is_useless(&qinfo, BIT_RD, dp,
|
||||
(worker->env.cfg->do_ip4 && worker->back->num_ip4 != 0),
|
||||
(worker->env.cfg->do_ip6 && worker->back->num_ip6 != 0))) {
|
||||
(worker->env.cfg->do_ip6 && worker->back->num_ip6 != 0),
|
||||
worker->env.cfg->do_nat64)) {
|
||||
print_dp_main(ssl, dp, msg);
|
||||
print_dp_details(ssl, worker, dp);
|
||||
if(!ssl_printf(ssl, "cache delegation was "
|
||||
|
||||
+87
-4
@@ -488,6 +488,27 @@ static int daemon_get_shufport(struct daemon* daemon, int* shufport)
|
||||
return avail;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear and delete per-worker alloc caches, and free memory maintained in
|
||||
* superalloc.
|
||||
* The rrset and message caches must be empty at the time of call.
|
||||
* @param daemon: the daemon that maintains the alloc caches to be cleared.
|
||||
*/
|
||||
static void
|
||||
daemon_clear_allocs(struct daemon* daemon)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i=0; i<daemon->num; i++) {
|
||||
alloc_clear(daemon->worker_allocs[i]);
|
||||
free(daemon->worker_allocs[i]);
|
||||
}
|
||||
free(daemon->worker_allocs);
|
||||
daemon->worker_allocs = NULL;
|
||||
|
||||
alloc_clear_special(&daemon->superalloc);
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocate empty worker structures. With backptr and thread-number,
|
||||
* from 0..numthread initialised. Used as user arguments to new threads.
|
||||
@@ -540,6 +561,21 @@ daemon_create_workers(struct daemon* daemon)
|
||||
/* the above is not ports/numthr, due to rounding */
|
||||
fatal_exit("could not create worker");
|
||||
}
|
||||
/* create per-worker alloc caches if not reusing existing ones. */
|
||||
if(!daemon->worker_allocs) {
|
||||
daemon->worker_allocs = (struct alloc_cache**)calloc(
|
||||
(size_t)daemon->num, sizeof(struct alloc_cache*));
|
||||
if(!daemon->worker_allocs)
|
||||
fatal_exit("could not allocate worker allocs");
|
||||
for(i=0; i<daemon->num; i++) {
|
||||
struct alloc_cache* alloc = calloc(1,
|
||||
sizeof(struct alloc_cache));
|
||||
if (!alloc)
|
||||
fatal_exit("could not allocate worker alloc");
|
||||
alloc_init(alloc, &daemon->superalloc, i);
|
||||
daemon->worker_allocs[i] = alloc;
|
||||
}
|
||||
}
|
||||
free(shufport);
|
||||
}
|
||||
|
||||
@@ -771,6 +807,7 @@ daemon_fork(struct daemon* daemon)
|
||||
/* Shutdown SHM */
|
||||
shm_main_shutdown(daemon);
|
||||
|
||||
daemon->reuse_cache = daemon->workers[0]->reuse_cache;
|
||||
daemon->need_to_exit = daemon->workers[0]->need_to_exit;
|
||||
}
|
||||
|
||||
@@ -785,9 +822,16 @@ daemon_cleanup(struct daemon* daemon)
|
||||
log_thread_set(NULL);
|
||||
/* clean up caches because
|
||||
* a) RRset IDs will be recycled after a reload, causing collisions
|
||||
* b) validation config can change, thus rrset, msg, keycache clear */
|
||||
slabhash_clear(&daemon->env->rrset_cache->table);
|
||||
slabhash_clear(daemon->env->msg_cache);
|
||||
* b) validation config can change, thus rrset, msg, keycache clear
|
||||
*
|
||||
* If we are trying to keep the cache as long as possible, we should
|
||||
* defer the cleanup until we know whether the new configuration allows
|
||||
* the reuse. (If we're exiting, cleanup should be done here). */
|
||||
if(!daemon->reuse_cache || daemon->need_to_exit) {
|
||||
slabhash_clear(&daemon->env->rrset_cache->table);
|
||||
slabhash_clear(daemon->env->msg_cache);
|
||||
}
|
||||
daemon->old_num = daemon->num; /* save the current num */
|
||||
local_zones_delete(daemon->local_zones);
|
||||
daemon->local_zones = NULL;
|
||||
respip_set_delete(daemon->respip_set);
|
||||
@@ -802,8 +846,13 @@ daemon_cleanup(struct daemon* daemon)
|
||||
worker_delete(daemon->workers[i]);
|
||||
free(daemon->workers);
|
||||
daemon->workers = NULL;
|
||||
/* Unless we're trying to keep the cache, worker alloc_caches should be
|
||||
* cleared and freed here. We do this after deleting workers to
|
||||
* guarantee that the alloc caches are valid throughout the lifetime
|
||||
* of workers. */
|
||||
if(!daemon->reuse_cache || daemon->need_to_exit)
|
||||
daemon_clear_allocs(daemon);
|
||||
daemon->num = 0;
|
||||
alloc_clear_special(&daemon->superalloc);
|
||||
#ifdef USE_DNSTAP
|
||||
dt_delete(daemon->dtenv);
|
||||
daemon->dtenv = NULL;
|
||||
@@ -900,8 +949,42 @@ daemon_delete(struct daemon* daemon)
|
||||
|
||||
void daemon_apply_cfg(struct daemon* daemon, struct config_file* cfg)
|
||||
{
|
||||
int new_num = cfg->num_threads?cfg->num_threads:1;
|
||||
|
||||
daemon->cfg = cfg;
|
||||
config_apply(cfg);
|
||||
|
||||
/* If this is a reload and we deferred the decision on whether to
|
||||
* reuse the alloc, RRset, and message caches, then check to see if
|
||||
* it's safe to keep the caches:
|
||||
* - changing the number of threads is obviously incompatible with
|
||||
* keeping the per-thread alloc caches. It also means we have to
|
||||
* clear RRset and message caches. (note that 'new_num' may be
|
||||
* adjusted in daemon_create_workers, but for our purpose we can
|
||||
* simply compare it with 'old_num'; if they are equal here,
|
||||
* 'new_num' won't be adjusted to a different value than 'old_num').
|
||||
* - changing RRset cache size effectively clears any remaining cache
|
||||
* entries. We could keep their keys in alloc caches, but it would
|
||||
* be more consistent with the sense of the change to clear allocs
|
||||
* and free memory. To do so we also have to clear message cache.
|
||||
* - only changing message cache size does not necessarily affect
|
||||
* RRset or alloc cache. But almost all new subsequent queries will
|
||||
* require recursive resolution anyway, so it doesn't help much to
|
||||
* just keep RRset and alloc caches. For simplicity we clear/free
|
||||
* the other two, too. */
|
||||
if(daemon->worker_allocs &&
|
||||
(new_num != daemon->old_num ||
|
||||
!slabhash_is_size(daemon->env->msg_cache, cfg->msg_cache_size,
|
||||
cfg->msg_cache_slabs) ||
|
||||
!slabhash_is_size(&daemon->env->rrset_cache->table,
|
||||
cfg->rrset_cache_size, cfg->rrset_cache_slabs)))
|
||||
{
|
||||
log_warn("cannot reuse caches due to critical config change");
|
||||
slabhash_clear(&daemon->env->rrset_cache->table);
|
||||
slabhash_clear(daemon->env->msg_cache);
|
||||
daemon_clear_allocs(daemon);
|
||||
}
|
||||
|
||||
if(!slabhash_is_size(daemon->env->msg_cache, cfg->msg_cache_size,
|
||||
cfg->msg_cache_slabs)) {
|
||||
slabhash_delete(daemon->env->msg_cache);
|
||||
|
||||
@@ -99,8 +99,12 @@ struct daemon {
|
||||
void* listen_sslctx, *connect_sslctx;
|
||||
/** num threads allocated */
|
||||
int num;
|
||||
/** num threads allocated in the previous config or 0 at first */
|
||||
int old_num;
|
||||
/** the worker entries */
|
||||
struct worker** workers;
|
||||
/** per-worker allocation cache */
|
||||
struct alloc_cache **worker_allocs;
|
||||
/** do we need to exit unbound (or is it only a reload?) */
|
||||
int need_to_exit;
|
||||
/** master random table ; used for port div between threads on reload*/
|
||||
@@ -140,6 +144,8 @@ struct daemon {
|
||||
/** the dnscrypt environment */
|
||||
struct dnsc_env* dnscenv;
|
||||
#endif
|
||||
/** reuse existing cache on reload if other conditions allow it. */
|
||||
int reuse_cache;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
+138
-149
@@ -4,22 +4,22 @@
|
||||
* Copyright (c) 2008, 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
|
||||
@@ -38,7 +38,7 @@
|
||||
*
|
||||
* This file contains the remote control functionality for the daemon.
|
||||
* The remote control can be performed using either the commandline
|
||||
* unbound-control tool, or a TLS capable web browser.
|
||||
* unbound-control tool, or a TLS capable web browser.
|
||||
* The channel is secured using TLSv1, and certificates.
|
||||
* Both the server and the client(control tool) have their own keys.
|
||||
*/
|
||||
@@ -87,6 +87,7 @@
|
||||
#include "sldns/parseutil.h"
|
||||
#include "sldns/wire2str.h"
|
||||
#include "sldns/sbuffer.h"
|
||||
#include "util/timeval_func.h"
|
||||
|
||||
#ifdef HAVE_SYS_TYPES_H
|
||||
# include <sys/types.h>
|
||||
@@ -105,49 +106,6 @@
|
||||
|
||||
/** what to put on statistics lines between var and value, ": " or "=" */
|
||||
#define SQ "="
|
||||
/** if true, inhibits a lot of =0 lines from the stats output */
|
||||
static const int inhibit_zero = 1;
|
||||
|
||||
/** subtract timers and the values do not overflow or become negative */
|
||||
static void
|
||||
timeval_subtract(struct timeval* d, const struct timeval* end,
|
||||
const struct timeval* start)
|
||||
{
|
||||
#ifndef S_SPLINT_S
|
||||
time_t end_usec = end->tv_usec;
|
||||
d->tv_sec = end->tv_sec - start->tv_sec;
|
||||
if(end_usec < start->tv_usec) {
|
||||
end_usec += 1000000;
|
||||
d->tv_sec--;
|
||||
}
|
||||
d->tv_usec = end_usec - start->tv_usec;
|
||||
#endif
|
||||
}
|
||||
|
||||
/** divide sum of timers to get average */
|
||||
static void
|
||||
timeval_divide(struct timeval* avg, const struct timeval* sum, long long d)
|
||||
{
|
||||
#ifndef S_SPLINT_S
|
||||
size_t leftover;
|
||||
if(d <= 0) {
|
||||
avg->tv_sec = 0;
|
||||
avg->tv_usec = 0;
|
||||
return;
|
||||
}
|
||||
avg->tv_sec = sum->tv_sec / d;
|
||||
avg->tv_usec = sum->tv_usec / d;
|
||||
/* handle fraction from seconds divide */
|
||||
leftover = sum->tv_sec - avg->tv_sec*d;
|
||||
if(leftover <= 0)
|
||||
leftover = 0;
|
||||
avg->tv_usec += (((long long)leftover)*((long long)1000000))/d;
|
||||
if(avg->tv_sec < 0)
|
||||
avg->tv_sec = 0;
|
||||
if(avg->tv_usec < 0)
|
||||
avg->tv_usec = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
static int
|
||||
remote_setup_ctx(struct daemon_remote* rc, struct config_file* cfg)
|
||||
@@ -203,7 +161,7 @@ remote_setup_ctx(struct daemon_remote* rc, struct config_file* cfg)
|
||||
struct daemon_remote*
|
||||
daemon_remote_create(struct config_file* cfg)
|
||||
{
|
||||
struct daemon_remote* rc = (struct daemon_remote*)calloc(1,
|
||||
struct daemon_remote* rc = (struct daemon_remote*)calloc(1,
|
||||
sizeof(*rc));
|
||||
if(!rc) {
|
||||
log_err("out of memory in daemon_remote_create");
|
||||
@@ -412,7 +370,7 @@ accept_open(struct daemon_remote* rc, int fd)
|
||||
n->next = rc->accept_list;
|
||||
rc->accept_list = n;
|
||||
/* open commpt */
|
||||
n->com = comm_point_create_raw(rc->worker->base, fd, 0,
|
||||
n->com = comm_point_create_raw(rc->worker->base, fd, 0,
|
||||
&remote_accept_callback, rc);
|
||||
if(!n->com)
|
||||
return 0;
|
||||
@@ -421,7 +379,7 @@ accept_open(struct daemon_remote* rc, int fd)
|
||||
return 1;
|
||||
}
|
||||
|
||||
int daemon_remote_open_accept(struct daemon_remote* rc,
|
||||
int daemon_remote_open_accept(struct daemon_remote* rc,
|
||||
struct listen_port* ports, struct worker* worker)
|
||||
{
|
||||
struct listen_port* p;
|
||||
@@ -439,7 +397,7 @@ void daemon_remote_stop_accept(struct daemon_remote* rc)
|
||||
{
|
||||
struct listen_list* p;
|
||||
for(p=rc->accept_list; p; p=p->next) {
|
||||
comm_point_stop_listening(p->com);
|
||||
comm_point_stop_listening(p->com);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -447,11 +405,11 @@ void daemon_remote_start_accept(struct daemon_remote* rc)
|
||||
{
|
||||
struct listen_list* p;
|
||||
for(p=rc->accept_list; p; p=p->next) {
|
||||
comm_point_start_listening(p->com, -1, -1);
|
||||
comm_point_start_listening(p->com, -1, -1);
|
||||
}
|
||||
}
|
||||
|
||||
int remote_accept_callback(struct comm_point* c, void* arg, int err,
|
||||
int remote_accept_callback(struct comm_point* c, void* arg, int err,
|
||||
struct comm_reply* ATTR_UNUSED(rep))
|
||||
{
|
||||
struct daemon_remote* rc = (struct daemon_remote*)arg;
|
||||
@@ -483,7 +441,7 @@ int remote_accept_callback(struct comm_point* c, void* arg, int err,
|
||||
}
|
||||
n->fd = newfd;
|
||||
/* start in reading state */
|
||||
n->c = comm_point_create_raw(rc->worker->base, newfd, 0,
|
||||
n->c = comm_point_create_raw(rc->worker->base, newfd, 0,
|
||||
&remote_control_callback, n);
|
||||
if(!n->c) {
|
||||
log_err("out of memory");
|
||||
@@ -523,7 +481,7 @@ int remote_accept_callback(struct comm_point* c, void* arg, int err,
|
||||
rc->busy_list = n;
|
||||
rc->active ++;
|
||||
|
||||
/* perform the first nonblocking read already, for windows,
|
||||
/* perform the first nonblocking read already, for windows,
|
||||
* so it can return wouldblock. could be faster too. */
|
||||
(void)remote_control_callback(n->c, n, NETEVENT_NOERROR, NULL);
|
||||
return 0;
|
||||
@@ -560,17 +518,18 @@ int
|
||||
ssl_print_text(RES* res, const char* text)
|
||||
{
|
||||
int r;
|
||||
if(!res)
|
||||
if(!res)
|
||||
return 0;
|
||||
if(res->ssl) {
|
||||
ERR_clear_error();
|
||||
if((r=SSL_write(res->ssl, text, (int)strlen(text))) <= 0) {
|
||||
if(SSL_get_error(res->ssl, r) == SSL_ERROR_ZERO_RETURN) {
|
||||
int r2;
|
||||
if((r2=SSL_get_error(res->ssl, r)) == SSL_ERROR_ZERO_RETURN) {
|
||||
verbose(VERB_QUERY, "warning, in SSL_write, peer "
|
||||
"closed connection");
|
||||
return 0;
|
||||
}
|
||||
log_crypto_err("could not SSL_write");
|
||||
log_crypto_err_io("could not SSL_write", r2);
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
@@ -621,11 +580,12 @@ ssl_read_line(RES* res, char* buf, size_t max)
|
||||
if(res->ssl) {
|
||||
ERR_clear_error();
|
||||
if((r=SSL_read(res->ssl, buf+len, 1)) <= 0) {
|
||||
if(SSL_get_error(res->ssl, r) == SSL_ERROR_ZERO_RETURN) {
|
||||
int r2;
|
||||
if((r2=SSL_get_error(res->ssl, r)) == SSL_ERROR_ZERO_RETURN) {
|
||||
buf[len] = 0;
|
||||
return 1;
|
||||
}
|
||||
log_crypto_err("could not SSL_read");
|
||||
log_crypto_err_io("could not SSL_read", r2);
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
@@ -638,7 +598,7 @@ ssl_read_line(RES* res, char* buf, size_t max)
|
||||
}
|
||||
if(errno == EINTR || errno == EAGAIN)
|
||||
continue;
|
||||
log_err("could not recv: %s",
|
||||
if(rr < 0) log_err("could not recv: %s",
|
||||
sock_strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
@@ -662,7 +622,7 @@ static char*
|
||||
skipwhite(char* str)
|
||||
{
|
||||
/* EOS \0 is not a space */
|
||||
while( isspace((unsigned char)*str) )
|
||||
while( isspace((unsigned char)*str) )
|
||||
str++;
|
||||
return str;
|
||||
}
|
||||
@@ -684,8 +644,9 @@ do_stop(RES* ssl, struct worker* worker)
|
||||
|
||||
/** do the reload command */
|
||||
static void
|
||||
do_reload(RES* ssl, struct worker* worker)
|
||||
do_reload(RES* ssl, struct worker* worker, int reuse_cache)
|
||||
{
|
||||
worker->reuse_cache = reuse_cache;
|
||||
worker->need_to_exit = 0;
|
||||
comm_base_exit(worker->base);
|
||||
send_ok(ssl);
|
||||
@@ -709,20 +670,30 @@ static int
|
||||
print_stats(RES* ssl, const char* nm, struct ub_stats_info* s)
|
||||
{
|
||||
struct timeval sumwait, avg;
|
||||
if(!ssl_printf(ssl, "%s.num.queries"SQ"%lu\n", nm,
|
||||
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
|
||||
if(!ssl_printf(ssl, "%s.num.queries_cookie_valid"SQ"%lu\n", nm,
|
||||
(unsigned long)s->svr.num_queries_cookie_valid)) return 0;
|
||||
if(!ssl_printf(ssl, "%s.num.queries_cookie_client"SQ"%lu\n", nm,
|
||||
(unsigned long)s->svr.num_queries_cookie_client)) return 0;
|
||||
if(!ssl_printf(ssl, "%s.num.queries_cookie_invalid"SQ"%lu\n", nm,
|
||||
(unsigned long)s->svr.num_queries_cookie_invalid)) 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;
|
||||
if(!ssl_printf(ssl, "%s.num.cachemiss"SQ"%lu\n", nm,
|
||||
if(!ssl_printf(ssl, "%s.num.cachemiss"SQ"%lu\n", nm,
|
||||
(unsigned long)s->svr.num_queries_missed_cache)) return 0;
|
||||
if(!ssl_printf(ssl, "%s.num.prefetch"SQ"%lu\n", nm,
|
||||
if(!ssl_printf(ssl, "%s.num.prefetch"SQ"%lu\n", nm,
|
||||
(unsigned long)s->svr.num_queries_prefetch)) return 0;
|
||||
if(!ssl_printf(ssl, "%s.num.queries_timed_out"SQ"%lu\n", nm,
|
||||
(unsigned long)s->svr.num_queries_timed_out)) return 0;
|
||||
if(!ssl_printf(ssl, "%s.query.queue_time_us.max"SQ"%lu\n", nm,
|
||||
(unsigned long)s->svr.max_query_time_us)) return 0;
|
||||
if(!ssl_printf(ssl, "%s.num.expired"SQ"%lu\n", nm,
|
||||
(unsigned long)s->svr.ans_expired)) return 0;
|
||||
if(!ssl_printf(ssl, "%s.num.recursivereplies"SQ"%lu\n", nm,
|
||||
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,
|
||||
@@ -756,7 +727,7 @@ print_stats(RES* ssl, const char* nm, struct ub_stats_info* s)
|
||||
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,
|
||||
if(!ssl_printf(ssl, "%s.recursion.time.median"SQ"%g\n", nm,
|
||||
s->mesh_time_median)) return 0;
|
||||
if(!ssl_printf(ssl, "%s.tcpusage"SQ"%lu\n", nm,
|
||||
(unsigned long)s->svr.tcp_accept_usage)) return 0;
|
||||
@@ -781,7 +752,7 @@ print_longnum(RES* ssl, const char* desc, size_t x)
|
||||
/* more than a Gb */
|
||||
size_t front = x / (size_t)1000000;
|
||||
size_t back = x % (size_t)1000000;
|
||||
return ssl_printf(ssl, "%s%u%6.6u\n", desc,
|
||||
return ssl_printf(ssl, "%s%u%6.6u\n", desc,
|
||||
(unsigned)front, (unsigned)back);
|
||||
} else {
|
||||
return ssl_printf(ssl, "%s%lu\n", desc, (unsigned long)x);
|
||||
@@ -881,11 +852,11 @@ print_uptime(RES* ssl, struct worker* worker, int reset)
|
||||
timeval_subtract(&dt, &now, &worker->daemon->time_last_stat);
|
||||
if(reset)
|
||||
worker->daemon->time_last_stat = now;
|
||||
if(!ssl_printf(ssl, "time.now"SQ ARG_LL "d.%6.6d\n",
|
||||
if(!ssl_printf(ssl, "time.now"SQ ARG_LL "d.%6.6d\n",
|
||||
(long long)now.tv_sec, (unsigned)now.tv_usec)) return 0;
|
||||
if(!ssl_printf(ssl, "time.up"SQ ARG_LL "d.%6.6d\n",
|
||||
if(!ssl_printf(ssl, "time.up"SQ ARG_LL "d.%6.6d\n",
|
||||
(long long)up.tv_sec, (unsigned)up.tv_usec)) return 0;
|
||||
if(!ssl_printf(ssl, "time.elapsed"SQ ARG_LL "d.%6.6d\n",
|
||||
if(!ssl_printf(ssl, "time.elapsed"SQ ARG_LL "d.%6.6d\n",
|
||||
(long long)dt.tv_sec, (unsigned)dt.tv_usec)) return 0;
|
||||
return 1;
|
||||
}
|
||||
@@ -903,7 +874,7 @@ print_hist(RES* ssl, struct ub_stats_info* s)
|
||||
}
|
||||
timehist_import(hist, s->svr.hist, NUM_BUCKETS_HIST);
|
||||
for(i=0; i<hist->num; i++) {
|
||||
if(!ssl_printf(ssl,
|
||||
if(!ssl_printf(ssl,
|
||||
"histogram.%6.6d.%6.6d.to.%6.6d.%6.6d=%lu\n",
|
||||
(int)hist->buckets[i].lower.tv_sec,
|
||||
(int)hist->buckets[i].lower.tv_usec,
|
||||
@@ -920,7 +891,7 @@ print_hist(RES* ssl, struct ub_stats_info* s)
|
||||
|
||||
/** print extended stats */
|
||||
static int
|
||||
print_ext(RES* ssl, struct ub_stats_info* s)
|
||||
print_ext(RES* ssl, struct ub_stats_info* s, int inhibit_zero)
|
||||
{
|
||||
int i;
|
||||
char nm[32];
|
||||
@@ -946,11 +917,11 @@ print_ext(RES* ssl, struct ub_stats_info* s)
|
||||
} else {
|
||||
snprintf(nm, sizeof(nm), "TYPE%d", i);
|
||||
}
|
||||
if(!ssl_printf(ssl, "num.query.type.%s"SQ"%lu\n",
|
||||
if(!ssl_printf(ssl, "num.query.type.%s"SQ"%lu\n",
|
||||
nm, (unsigned long)s->svr.qtype[i])) return 0;
|
||||
}
|
||||
if(!inhibit_zero || s->svr.qtype_big) {
|
||||
if(!ssl_printf(ssl, "num.query.type.other"SQ"%lu\n",
|
||||
if(!ssl_printf(ssl, "num.query.type.other"SQ"%lu\n",
|
||||
(unsigned long)s->svr.qtype_big)) return 0;
|
||||
}
|
||||
/* CLASS */
|
||||
@@ -963,11 +934,11 @@ print_ext(RES* ssl, struct ub_stats_info* s)
|
||||
} else {
|
||||
snprintf(nm, sizeof(nm), "CLASS%d", i);
|
||||
}
|
||||
if(!ssl_printf(ssl, "num.query.class.%s"SQ"%lu\n",
|
||||
if(!ssl_printf(ssl, "num.query.class.%s"SQ"%lu\n",
|
||||
nm, (unsigned long)s->svr.qclass[i])) return 0;
|
||||
}
|
||||
if(!inhibit_zero || s->svr.qclass_big) {
|
||||
if(!ssl_printf(ssl, "num.query.class.other"SQ"%lu\n",
|
||||
if(!ssl_printf(ssl, "num.query.class.other"SQ"%lu\n",
|
||||
(unsigned long)s->svr.qclass_big)) return 0;
|
||||
}
|
||||
/* OPCODE */
|
||||
@@ -980,44 +951,44 @@ print_ext(RES* ssl, struct ub_stats_info* s)
|
||||
} else {
|
||||
snprintf(nm, sizeof(nm), "OPCODE%d", i);
|
||||
}
|
||||
if(!ssl_printf(ssl, "num.query.opcode.%s"SQ"%lu\n",
|
||||
if(!ssl_printf(ssl, "num.query.opcode.%s"SQ"%lu\n",
|
||||
nm, (unsigned long)s->svr.qopcode[i])) return 0;
|
||||
}
|
||||
/* transport */
|
||||
if(!ssl_printf(ssl, "num.query.tcp"SQ"%lu\n",
|
||||
if(!ssl_printf(ssl, "num.query.tcp"SQ"%lu\n",
|
||||
(unsigned long)s->svr.qtcp)) return 0;
|
||||
if(!ssl_printf(ssl, "num.query.tcpout"SQ"%lu\n",
|
||||
if(!ssl_printf(ssl, "num.query.tcpout"SQ"%lu\n",
|
||||
(unsigned long)s->svr.qtcp_outgoing)) return 0;
|
||||
if(!ssl_printf(ssl, "num.query.udpout"SQ"%lu\n",
|
||||
(unsigned long)s->svr.qudp_outgoing)) return 0;
|
||||
if(!ssl_printf(ssl, "num.query.tls"SQ"%lu\n",
|
||||
if(!ssl_printf(ssl, "num.query.tls"SQ"%lu\n",
|
||||
(unsigned long)s->svr.qtls)) return 0;
|
||||
if(!ssl_printf(ssl, "num.query.tls.resume"SQ"%lu\n",
|
||||
if(!ssl_printf(ssl, "num.query.tls.resume"SQ"%lu\n",
|
||||
(unsigned long)s->svr.qtls_resume)) return 0;
|
||||
if(!ssl_printf(ssl, "num.query.ipv6"SQ"%lu\n",
|
||||
if(!ssl_printf(ssl, "num.query.ipv6"SQ"%lu\n",
|
||||
(unsigned long)s->svr.qipv6)) return 0;
|
||||
if(!ssl_printf(ssl, "num.query.https"SQ"%lu\n",
|
||||
(unsigned long)s->svr.qhttps)) return 0;
|
||||
/* flags */
|
||||
if(!ssl_printf(ssl, "num.query.flags.QR"SQ"%lu\n",
|
||||
if(!ssl_printf(ssl, "num.query.flags.QR"SQ"%lu\n",
|
||||
(unsigned long)s->svr.qbit_QR)) return 0;
|
||||
if(!ssl_printf(ssl, "num.query.flags.AA"SQ"%lu\n",
|
||||
if(!ssl_printf(ssl, "num.query.flags.AA"SQ"%lu\n",
|
||||
(unsigned long)s->svr.qbit_AA)) return 0;
|
||||
if(!ssl_printf(ssl, "num.query.flags.TC"SQ"%lu\n",
|
||||
if(!ssl_printf(ssl, "num.query.flags.TC"SQ"%lu\n",
|
||||
(unsigned long)s->svr.qbit_TC)) return 0;
|
||||
if(!ssl_printf(ssl, "num.query.flags.RD"SQ"%lu\n",
|
||||
if(!ssl_printf(ssl, "num.query.flags.RD"SQ"%lu\n",
|
||||
(unsigned long)s->svr.qbit_RD)) return 0;
|
||||
if(!ssl_printf(ssl, "num.query.flags.RA"SQ"%lu\n",
|
||||
if(!ssl_printf(ssl, "num.query.flags.RA"SQ"%lu\n",
|
||||
(unsigned long)s->svr.qbit_RA)) return 0;
|
||||
if(!ssl_printf(ssl, "num.query.flags.Z"SQ"%lu\n",
|
||||
if(!ssl_printf(ssl, "num.query.flags.Z"SQ"%lu\n",
|
||||
(unsigned long)s->svr.qbit_Z)) return 0;
|
||||
if(!ssl_printf(ssl, "num.query.flags.AD"SQ"%lu\n",
|
||||
if(!ssl_printf(ssl, "num.query.flags.AD"SQ"%lu\n",
|
||||
(unsigned long)s->svr.qbit_AD)) return 0;
|
||||
if(!ssl_printf(ssl, "num.query.flags.CD"SQ"%lu\n",
|
||||
if(!ssl_printf(ssl, "num.query.flags.CD"SQ"%lu\n",
|
||||
(unsigned long)s->svr.qbit_CD)) return 0;
|
||||
if(!ssl_printf(ssl, "num.query.edns.present"SQ"%lu\n",
|
||||
if(!ssl_printf(ssl, "num.query.edns.present"SQ"%lu\n",
|
||||
(unsigned long)s->svr.qEDNS)) return 0;
|
||||
if(!ssl_printf(ssl, "num.query.edns.DO"SQ"%lu\n",
|
||||
if(!ssl_printf(ssl, "num.query.edns.DO"SQ"%lu\n",
|
||||
(unsigned long)s->svr.qEDNS_DO)) return 0;
|
||||
|
||||
/* RCODE */
|
||||
@@ -1031,31 +1002,31 @@ print_ext(RES* ssl, struct ub_stats_info* s)
|
||||
} else {
|
||||
snprintf(nm, sizeof(nm), "RCODE%d", i);
|
||||
}
|
||||
if(!ssl_printf(ssl, "num.answer.rcode.%s"SQ"%lu\n",
|
||||
if(!ssl_printf(ssl, "num.answer.rcode.%s"SQ"%lu\n",
|
||||
nm, (unsigned long)s->svr.ans_rcode[i])) return 0;
|
||||
}
|
||||
if(!inhibit_zero || s->svr.ans_rcode_nodata) {
|
||||
if(!ssl_printf(ssl, "num.answer.rcode.nodata"SQ"%lu\n",
|
||||
if(!ssl_printf(ssl, "num.answer.rcode.nodata"SQ"%lu\n",
|
||||
(unsigned long)s->svr.ans_rcode_nodata)) return 0;
|
||||
}
|
||||
/* iteration */
|
||||
if(!ssl_printf(ssl, "num.query.ratelimited"SQ"%lu\n",
|
||||
if(!ssl_printf(ssl, "num.query.ratelimited"SQ"%lu\n",
|
||||
(unsigned long)s->svr.queries_ratelimited)) return 0;
|
||||
/* validation */
|
||||
if(!ssl_printf(ssl, "num.answer.secure"SQ"%lu\n",
|
||||
if(!ssl_printf(ssl, "num.answer.secure"SQ"%lu\n",
|
||||
(unsigned long)s->svr.ans_secure)) return 0;
|
||||
if(!ssl_printf(ssl, "num.answer.bogus"SQ"%lu\n",
|
||||
if(!ssl_printf(ssl, "num.answer.bogus"SQ"%lu\n",
|
||||
(unsigned long)s->svr.ans_bogus)) return 0;
|
||||
if(!ssl_printf(ssl, "num.rrset.bogus"SQ"%lu\n",
|
||||
if(!ssl_printf(ssl, "num.rrset.bogus"SQ"%lu\n",
|
||||
(unsigned long)s->svr.rrset_bogus)) return 0;
|
||||
if(!ssl_printf(ssl, "num.query.aggressive.NOERROR"SQ"%lu\n",
|
||||
if(!ssl_printf(ssl, "num.query.aggressive.NOERROR"SQ"%lu\n",
|
||||
(unsigned long)s->svr.num_neg_cache_noerror)) return 0;
|
||||
if(!ssl_printf(ssl, "num.query.aggressive.NXDOMAIN"SQ"%lu\n",
|
||||
if(!ssl_printf(ssl, "num.query.aggressive.NXDOMAIN"SQ"%lu\n",
|
||||
(unsigned long)s->svr.num_neg_cache_nxdomain)) return 0;
|
||||
/* threat detection */
|
||||
if(!ssl_printf(ssl, "unwanted.queries"SQ"%lu\n",
|
||||
if(!ssl_printf(ssl, "unwanted.queries"SQ"%lu\n",
|
||||
(unsigned long)s->svr.unwanted_queries)) return 0;
|
||||
if(!ssl_printf(ssl, "unwanted.replies"SQ"%lu\n",
|
||||
if(!ssl_printf(ssl, "unwanted.replies"SQ"%lu\n",
|
||||
(unsigned long)s->svr.unwanted_replies)) return 0;
|
||||
/* cache counts */
|
||||
if(!ssl_printf(ssl, "msg.cache.count"SQ"%u\n",
|
||||
@@ -1066,6 +1037,11 @@ print_ext(RES* ssl, struct ub_stats_info* s)
|
||||
(unsigned)s->svr.infra_cache_count)) return 0;
|
||||
if(!ssl_printf(ssl, "key.cache.count"SQ"%u\n",
|
||||
(unsigned)s->svr.key_cache_count)) return 0;
|
||||
/* max collisions */
|
||||
if(!ssl_printf(ssl, "msg.cache.max_collisions"SQ"%u\n",
|
||||
(unsigned)s->svr.msg_cache_max_collisions)) return 0;
|
||||
if(!ssl_printf(ssl, "rrset.cache.max_collisions"SQ"%u\n",
|
||||
(unsigned)s->svr.rrset_cache_max_collisions)) return 0;
|
||||
/* applied RPZ actions */
|
||||
for(i=0; i<UB_STATS_RPZ_ACTION_NUM; i++) {
|
||||
if(i == RPZ_NO_OVERRIDE_ACTION)
|
||||
@@ -1096,6 +1072,10 @@ print_ext(RES* ssl, struct ub_stats_info* s)
|
||||
if(!ssl_printf(ssl, "num.query.subnet_cache"SQ"%lu\n",
|
||||
(unsigned long)s->svr.num_query_subnet_cache)) return 0;
|
||||
#endif /* CLIENT_SUBNET */
|
||||
#ifdef USE_CACHEDB
|
||||
if(!ssl_printf(ssl, "num.query.cachedb"SQ"%lu\n",
|
||||
(unsigned long)s->svr.num_query_cachedb)) return 0;
|
||||
#endif /* USE_CACHEDB */
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -1120,7 +1100,7 @@ do_stats(RES* ssl, struct worker* worker, int reset)
|
||||
}
|
||||
/* print the thread statistics */
|
||||
total.mesh_time_median /= (double)daemon->num;
|
||||
if(!print_stats(ssl, "total", &total))
|
||||
if(!print_stats(ssl, "total", &total))
|
||||
return;
|
||||
if(!print_uptime(ssl, worker, reset))
|
||||
return;
|
||||
@@ -1129,7 +1109,7 @@ do_stats(RES* ssl, struct worker* worker, int reset)
|
||||
return;
|
||||
if(!print_hist(ssl, &total))
|
||||
return;
|
||||
if(!print_ext(ssl, &total))
|
||||
if(!print_ext(ssl, &total, daemon->cfg->stat_inhibit_zero))
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -1209,7 +1189,7 @@ perform_zone_add(RES* ssl, struct local_zones* zones, char* arg)
|
||||
return 0;
|
||||
}
|
||||
lock_rw_wrlock(&zones->lock);
|
||||
if((z=local_zones_find(zones, nm, nmlen,
|
||||
if((z=local_zones_find(zones, nm, nmlen,
|
||||
nmlabs, LDNS_RR_CLASS_IN))) {
|
||||
/* already present in tree */
|
||||
lock_rw_wrlock(&z->lock);
|
||||
@@ -1219,7 +1199,7 @@ perform_zone_add(RES* ssl, struct local_zones* zones, char* arg)
|
||||
lock_rw_unlock(&zones->lock);
|
||||
return 1;
|
||||
}
|
||||
if(!local_zones_add_zone(zones, nm, nmlen,
|
||||
if(!local_zones_add_zone(zones, nm, nmlen,
|
||||
nmlabs, LDNS_RR_CLASS_IN, t)) {
|
||||
lock_rw_unlock(&zones->lock);
|
||||
ssl_printf(ssl, "error out of memory\n");
|
||||
@@ -1245,8 +1225,8 @@ do_zones_add(RES* ssl, struct local_zones* zones)
|
||||
char buf[2048];
|
||||
int num = 0;
|
||||
while(ssl_read_line(ssl, buf, sizeof(buf))) {
|
||||
if(buf[0] == 0x04 && buf[1] == 0)
|
||||
break; /* end of transmission */
|
||||
if(buf[0] == 0 || (buf[0] == 0x04 && buf[1] == 0))
|
||||
break; /* zero byte line or end of transmission */
|
||||
if(!perform_zone_add(ssl, zones, buf)) {
|
||||
if(!ssl_printf(ssl, "error for input line: %s\n", buf))
|
||||
return;
|
||||
@@ -1268,7 +1248,7 @@ perform_zone_remove(RES* ssl, struct local_zones* zones, char* arg)
|
||||
if(!parse_arg_name(ssl, arg, &nm, &nmlen, &nmlabs))
|
||||
return 0;
|
||||
lock_rw_wrlock(&zones->lock);
|
||||
if((z=local_zones_find(zones, nm, nmlen,
|
||||
if((z=local_zones_find(zones, nm, nmlen,
|
||||
nmlabs, LDNS_RR_CLASS_IN))) {
|
||||
/* present in tree */
|
||||
local_zones_del_zone(zones, z);
|
||||
@@ -1294,8 +1274,8 @@ do_zones_remove(RES* ssl, struct local_zones* zones)
|
||||
char buf[2048];
|
||||
int num = 0;
|
||||
while(ssl_read_line(ssl, buf, sizeof(buf))) {
|
||||
if(buf[0] == 0x04 && buf[1] == 0)
|
||||
break; /* end of transmission */
|
||||
if(buf[0] == 0 || (buf[0] == 0x04 && buf[1] == 0))
|
||||
break; /* zero byte line or end of transmission */
|
||||
if(!perform_zone_remove(ssl, zones, buf)) {
|
||||
if(!ssl_printf(ssl, "error for input line: %s\n", buf))
|
||||
return;
|
||||
@@ -1358,8 +1338,8 @@ do_datas_add(RES* ssl, struct local_zones* zones)
|
||||
char buf[2048];
|
||||
int num = 0, line = 0;
|
||||
while(ssl_read_line(ssl, buf, sizeof(buf))) {
|
||||
if(buf[0] == 0x04 && buf[1] == 0)
|
||||
break; /* end of transmission */
|
||||
if(buf[0] == 0 || (buf[0] == 0x04 && buf[1] == 0))
|
||||
break; /* zero byte line or end of transmission */
|
||||
line++;
|
||||
if(perform_data_add(ssl, zones, buf, line))
|
||||
num++;
|
||||
@@ -1398,8 +1378,8 @@ do_datas_remove(RES* ssl, struct local_zones* zones)
|
||||
char buf[2048];
|
||||
int num = 0;
|
||||
while(ssl_read_line(ssl, buf, sizeof(buf))) {
|
||||
if(buf[0] == 0x04 && buf[1] == 0)
|
||||
break; /* end of transmission */
|
||||
if(buf[0] == 0 || (buf[0] == 0x04 && buf[1] == 0))
|
||||
break; /* zero byte line or end of transmission */
|
||||
if(!perform_data_remove(ssl, zones, buf)) {
|
||||
if(!ssl_printf(ssl, "error for input line: %s\n", buf))
|
||||
return;
|
||||
@@ -1609,8 +1589,11 @@ do_flush_type(RES* ssl, struct worker* worker, char* arg)
|
||||
if(!parse_arg_name(ssl, arg, &nm, &nmlen, &nmlabs))
|
||||
return;
|
||||
t = sldns_get_rr_type_by_name(arg2);
|
||||
if(t == 0 && strcmp(arg2, "TYPE0") != 0) {
|
||||
return;
|
||||
}
|
||||
do_cache_remove(worker, nm, nmlen, t, LDNS_RR_CLASS_IN);
|
||||
|
||||
|
||||
free(nm);
|
||||
send_ok(ssl);
|
||||
}
|
||||
@@ -1720,7 +1703,7 @@ zone_del_rrset(struct lruhash_entry* e, void* arg)
|
||||
struct del_info* inf = (struct del_info*)arg;
|
||||
struct ub_packed_rrset_key* k = (struct ub_packed_rrset_key*)e->key;
|
||||
if(dname_subdomain_c(k->rk.dname, inf->name)) {
|
||||
struct packed_rrset_data* d =
|
||||
struct packed_rrset_data* d =
|
||||
(struct packed_rrset_data*)e->data;
|
||||
if(d->ttl > inf->expired) {
|
||||
d->ttl = inf->expired;
|
||||
@@ -1784,21 +1767,21 @@ do_flush_zone(RES* ssl, struct worker* worker, char* arg)
|
||||
inf.num_rrsets = 0;
|
||||
inf.num_msgs = 0;
|
||||
inf.num_keys = 0;
|
||||
slabhash_traverse(&worker->env.rrset_cache->table, 1,
|
||||
slabhash_traverse(&worker->env.rrset_cache->table, 1,
|
||||
&zone_del_rrset, &inf);
|
||||
|
||||
slabhash_traverse(worker->env.msg_cache, 1, &zone_del_msg, &inf);
|
||||
|
||||
/* and validator cache */
|
||||
if(worker->env.key_cache) {
|
||||
slabhash_traverse(worker->env.key_cache->slab, 1,
|
||||
slabhash_traverse(worker->env.key_cache->slab, 1,
|
||||
&zone_del_kcache, &inf);
|
||||
}
|
||||
|
||||
free(nm);
|
||||
|
||||
(void)ssl_printf(ssl, "ok removed %lu rrsets, %lu messages "
|
||||
"and %lu key entries\n", (unsigned long)inf.num_rrsets,
|
||||
"and %lu key entries\n", (unsigned long)inf.num_rrsets,
|
||||
(unsigned long)inf.num_msgs, (unsigned long)inf.num_keys);
|
||||
}
|
||||
|
||||
@@ -1853,19 +1836,19 @@ do_flush_bogus(RES* ssl, struct worker* worker)
|
||||
inf.num_rrsets = 0;
|
||||
inf.num_msgs = 0;
|
||||
inf.num_keys = 0;
|
||||
slabhash_traverse(&worker->env.rrset_cache->table, 1,
|
||||
slabhash_traverse(&worker->env.rrset_cache->table, 1,
|
||||
&bogus_del_rrset, &inf);
|
||||
|
||||
slabhash_traverse(worker->env.msg_cache, 1, &bogus_del_msg, &inf);
|
||||
|
||||
/* and validator cache */
|
||||
if(worker->env.key_cache) {
|
||||
slabhash_traverse(worker->env.key_cache->slab, 1,
|
||||
slabhash_traverse(worker->env.key_cache->slab, 1,
|
||||
&bogus_del_kcache, &inf);
|
||||
}
|
||||
|
||||
(void)ssl_printf(ssl, "ok removed %lu rrsets, %lu messages "
|
||||
"and %lu key entries\n", (unsigned long)inf.num_rrsets,
|
||||
"and %lu key entries\n", (unsigned long)inf.num_rrsets,
|
||||
(unsigned long)inf.num_msgs, (unsigned long)inf.num_keys);
|
||||
}
|
||||
|
||||
@@ -1928,19 +1911,19 @@ do_flush_negative(RES* ssl, struct worker* worker)
|
||||
inf.num_rrsets = 0;
|
||||
inf.num_msgs = 0;
|
||||
inf.num_keys = 0;
|
||||
slabhash_traverse(&worker->env.rrset_cache->table, 1,
|
||||
slabhash_traverse(&worker->env.rrset_cache->table, 1,
|
||||
&negative_del_rrset, &inf);
|
||||
|
||||
slabhash_traverse(worker->env.msg_cache, 1, &negative_del_msg, &inf);
|
||||
|
||||
/* and validator cache */
|
||||
if(worker->env.key_cache) {
|
||||
slabhash_traverse(worker->env.key_cache->slab, 1,
|
||||
slabhash_traverse(worker->env.key_cache->slab, 1,
|
||||
&negative_del_kcache, &inf);
|
||||
}
|
||||
|
||||
(void)ssl_printf(ssl, "ok removed %lu rrsets, %lu messages "
|
||||
"and %lu key entries\n", (unsigned long)inf.num_rrsets,
|
||||
"and %lu key entries\n", (unsigned long)inf.num_rrsets,
|
||||
(unsigned long)inf.num_msgs, (unsigned long)inf.num_keys);
|
||||
}
|
||||
|
||||
@@ -1963,7 +1946,9 @@ do_flush_name(RES* ssl, struct worker* w, char* arg)
|
||||
do_cache_remove(w, nm, nmlen, LDNS_RR_TYPE_PTR, LDNS_RR_CLASS_IN);
|
||||
do_cache_remove(w, nm, nmlen, LDNS_RR_TYPE_SRV, LDNS_RR_CLASS_IN);
|
||||
do_cache_remove(w, nm, nmlen, LDNS_RR_TYPE_NAPTR, LDNS_RR_CLASS_IN);
|
||||
|
||||
do_cache_remove(w, nm, nmlen, LDNS_RR_TYPE_SVCB, LDNS_RR_CLASS_IN);
|
||||
do_cache_remove(w, nm, nmlen, LDNS_RR_TYPE_HTTPS, LDNS_RR_CLASS_IN);
|
||||
|
||||
free(nm);
|
||||
send_ok(ssl);
|
||||
}
|
||||
@@ -2333,7 +2318,7 @@ do_status(RES* ssl, struct worker* worker)
|
||||
uptime = (time_t)time(NULL) - (time_t)worker->daemon->time_boot.tv_sec;
|
||||
if(!ssl_printf(ssl, "uptime: " ARG_LL "d seconds\n", (long long)uptime))
|
||||
return;
|
||||
if(!ssl_printf(ssl, "options:%s%s%s%s\n" ,
|
||||
if(!ssl_printf(ssl, "options:%s%s%s%s\n" ,
|
||||
(worker->daemon->reuseport?" reuseport":""),
|
||||
(worker->daemon->rc->accept_list?" control":""),
|
||||
(worker->daemon->rc->accept_list && worker->daemon->rc->use_cert?"(ssl)":""),
|
||||
@@ -2347,7 +2332,7 @@ do_status(RES* ssl, struct worker* worker)
|
||||
|
||||
/** get age for the mesh state */
|
||||
static void
|
||||
get_mesh_age(struct mesh_state* m, char* buf, size_t len,
|
||||
get_mesh_age(struct mesh_state* m, char* buf, size_t len,
|
||||
struct module_env* env)
|
||||
{
|
||||
if(m->reply_list) {
|
||||
@@ -2366,7 +2351,7 @@ get_mesh_age(struct mesh_state* m, char* buf, size_t len,
|
||||
|
||||
/** get status of a mesh state */
|
||||
static void
|
||||
get_mesh_status(struct mesh_area* mesh, struct mesh_state* m,
|
||||
get_mesh_status(struct mesh_area* mesh, struct mesh_state* m,
|
||||
char* buf, size_t len)
|
||||
{
|
||||
enum module_ext_state s = m->s.ext_state[m->s.curmod];
|
||||
@@ -2388,7 +2373,7 @@ get_mesh_status(struct mesh_area* mesh, struct mesh_state* m,
|
||||
snprintf(buf, len, " ");
|
||||
l = strlen(buf);
|
||||
buf += l; len -= l;
|
||||
addr_to_str(&e->qsent->addr, e->qsent->addrlen,
|
||||
addr_to_str(&e->qsent->addr, e->qsent->addrlen,
|
||||
buf, len);
|
||||
l = strlen(buf);
|
||||
buf += l; len -= l;
|
||||
@@ -2441,7 +2426,7 @@ do_dump_requestlist(RES* ssl, struct worker* worker)
|
||||
dname_str(m->s.qinfo.qname, buf);
|
||||
get_mesh_age(m, timebuf, sizeof(timebuf), &worker->env);
|
||||
get_mesh_status(mesh, m, statbuf, sizeof(statbuf));
|
||||
if(!ssl_printf(ssl, "%3d %4s %2s %s %s %s\n",
|
||||
if(!ssl_printf(ssl, "%3d %4s %2s %s %s %s\n",
|
||||
num, (t?t:"TYPE??"), (c?c:"CLASS??"), buf, timebuf,
|
||||
statbuf)) {
|
||||
free(t);
|
||||
@@ -2631,7 +2616,7 @@ do_auth_zone_transfer(RES* ssl, struct worker* worker, char* arg)
|
||||
free(nm);
|
||||
send_ok(ssl);
|
||||
}
|
||||
|
||||
|
||||
/** do the set_option command */
|
||||
static void
|
||||
do_set_option(RES* ssl, struct worker* worker, char* arg)
|
||||
@@ -2769,7 +2754,7 @@ do_list_local_zones(RES* ssl, struct local_zones* zones)
|
||||
RBTREE_FOR(z, struct local_zone*, &zones->ztree) {
|
||||
lock_rw_rdlock(&z->lock);
|
||||
dname_str(z->name, buf);
|
||||
if(!ssl_printf(ssl, "%s %s\n", buf,
|
||||
if(!ssl_printf(ssl, "%s %s\n", buf,
|
||||
local_zone_type2str(z->type))) {
|
||||
/* failure to print */
|
||||
lock_rw_unlock(&z->lock);
|
||||
@@ -2998,7 +2983,7 @@ static void
|
||||
distribute_cmd(struct daemon_remote* rc, RES* ssl, char* cmd)
|
||||
{
|
||||
int i;
|
||||
if(!cmd || !ssl)
|
||||
if(!cmd || !ssl)
|
||||
return;
|
||||
/* skip i=0 which is me */
|
||||
for(i=1; i<rc->worker->daemon->num; i++) {
|
||||
@@ -3021,7 +3006,7 @@ cmdcmp(char* p, const char* cmd, size_t len)
|
||||
|
||||
/** execute a remote control command */
|
||||
static void
|
||||
execute_cmd(struct daemon_remote* rc, RES* ssl, char* cmd,
|
||||
execute_cmd(struct daemon_remote* rc, RES* ssl, char* cmd,
|
||||
struct worker* worker)
|
||||
{
|
||||
char* p = skipwhite(cmd);
|
||||
@@ -3029,8 +3014,11 @@ execute_cmd(struct daemon_remote* rc, RES* ssl, char* cmd,
|
||||
if(cmdcmp(p, "stop", 4)) {
|
||||
do_stop(ssl, worker);
|
||||
return;
|
||||
} else if(cmdcmp(p, "reload_keep_cache", 17)) {
|
||||
do_reload(ssl, worker, 1);
|
||||
return;
|
||||
} else if(cmdcmp(p, "reload", 6)) {
|
||||
do_reload(ssl, worker);
|
||||
do_reload(ssl, worker, 0);
|
||||
return;
|
||||
} else if(cmdcmp(p, "stats_noreset", 13)) {
|
||||
do_stats(ssl, worker, 0);
|
||||
@@ -3202,7 +3190,7 @@ execute_cmd(struct daemon_remote* rc, RES* ssl, char* cmd,
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
void
|
||||
daemon_remote_exec(struct worker* worker)
|
||||
{
|
||||
/* read the cmd string */
|
||||
@@ -3236,9 +3224,10 @@ handle_req(struct daemon_remote* rc, struct rc_state* s, RES* res)
|
||||
if(res->ssl) {
|
||||
ERR_clear_error();
|
||||
if((r=SSL_read(res->ssl, magic, (int)sizeof(magic)-1)) <= 0) {
|
||||
if(SSL_get_error(res->ssl, r) == SSL_ERROR_ZERO_RETURN)
|
||||
int r2;
|
||||
if((r2=SSL_get_error(res->ssl, r)) == SSL_ERROR_ZERO_RETURN)
|
||||
return;
|
||||
log_crypto_err("could not SSL_read");
|
||||
log_crypto_err_io("could not SSL_read", r2);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
@@ -3305,13 +3294,13 @@ remote_handshake_later(struct daemon_remote* rc, struct rc_state* s,
|
||||
log_err("remote control connection closed prematurely");
|
||||
log_addr(VERB_OPS, "failed connection from",
|
||||
&s->c->repinfo.remote_addr, s->c->repinfo.remote_addrlen);
|
||||
log_crypto_err("remote control failed ssl");
|
||||
log_crypto_err_io("remote control failed ssl", r2);
|
||||
clean_point(rc, s);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int remote_control_callback(struct comm_point* c, void* arg, int err,
|
||||
int remote_control_callback(struct comm_point* c, void* arg, int err,
|
||||
struct comm_reply* ATTR_UNUSED(rep))
|
||||
{
|
||||
RES res;
|
||||
@@ -3319,7 +3308,7 @@ int remote_control_callback(struct comm_point* c, void* arg, int err,
|
||||
struct daemon_remote* rc = s->rc;
|
||||
int r;
|
||||
if(err != NETEVENT_NOERROR) {
|
||||
if(err==NETEVENT_TIMEOUT)
|
||||
if(err==NETEVENT_TIMEOUT)
|
||||
log_err("remote control timed out");
|
||||
clean_point(rc, s);
|
||||
return 0;
|
||||
|
||||
+1
-1
@@ -46,7 +46,7 @@
|
||||
#ifndef DAEMON_REMOTE_H
|
||||
#define DAEMON_REMOTE_H
|
||||
#ifdef HAVE_OPENSSL_SSL_H
|
||||
#include "openssl/ssl.h"
|
||||
#include <openssl/ssl.h>
|
||||
#endif
|
||||
struct config_file;
|
||||
struct listen_list;
|
||||
|
||||
+41
-12
@@ -4,22 +4,22 @@
|
||||
* Copyright (c) 2007, 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
|
||||
@@ -116,8 +116,8 @@ void server_stats_log(struct ub_server_stats* stats, struct worker* worker,
|
||||
log_info("server stats for thread %d: %u queries, "
|
||||
"%u answers from cache, %u recursions, %u prefetch, %u rejected by "
|
||||
"ip ratelimiting",
|
||||
threadnum, (unsigned)stats->num_queries,
|
||||
(unsigned)(stats->num_queries -
|
||||
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,
|
||||
@@ -279,7 +279,7 @@ server_stats_compile(struct worker* worker, struct ub_stats_info* s, int reset)
|
||||
s->svr.ans_rcode[i] += (long long)worker->env.mesh->ans_rcode[i];
|
||||
for(i=0; i<UB_STATS_RPZ_ACTION_NUM; i++)
|
||||
s->svr.rpz_action[i] += (long long)worker->env.mesh->rpz_action[i];
|
||||
timehist_export(worker->env.mesh->histogram, s->svr.hist,
|
||||
timehist_export(worker->env.mesh->histogram, s->svr.hist,
|
||||
NUM_BUCKETS_HIST);
|
||||
/* values from outside network */
|
||||
s->svr.unwanted_replies = (long long)worker->back->unwanted_replies;
|
||||
@@ -293,8 +293,10 @@ server_stats_compile(struct worker* worker, struct ub_stats_info* s, int reset)
|
||||
s->svr.queries_ratelimited = (long long)get_queries_ratelimit(worker, reset);
|
||||
|
||||
/* get cache sizes */
|
||||
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);
|
||||
get_slabhash_stats(worker->env.msg_cache,
|
||||
&s->svr.msg_cache_count, &s->svr.msg_cache_max_collisions);
|
||||
get_slabhash_stats(&worker->env.rrset_cache->table,
|
||||
&s->svr.rrset_cache_count, &s->svr.rrset_cache_max_collisions);
|
||||
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 = (long long)count_slabhash_entries(worker->env.key_cache->slab);
|
||||
@@ -354,6 +356,11 @@ server_stats_compile(struct worker* worker, struct ub_stats_info* s, int reset)
|
||||
s->svr.num_query_subnet = 0;
|
||||
s->svr.num_query_subnet_cache = 0;
|
||||
#endif
|
||||
#ifdef USE_CACHEDB
|
||||
s->svr.num_query_cachedb = (long long)worker->env.mesh->ans_cachedb;
|
||||
#else
|
||||
s->svr.num_query_cachedb = 0;
|
||||
#endif
|
||||
|
||||
/* get tcp accept usage */
|
||||
s->svr.tcp_accept_usage = 0;
|
||||
@@ -419,7 +426,7 @@ void server_stats_reply(struct worker* worker, int reset)
|
||||
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,
|
||||
if(!tube_write_msg(worker->daemon->workers[0]->cmd,
|
||||
(uint8_t*)&s, sizeof(s), 0))
|
||||
fatal_exit("could not write stat values over cmd channel");
|
||||
}
|
||||
@@ -428,8 +435,14 @@ 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_cookie_valid += a->svr.num_queries_cookie_valid;
|
||||
total->svr.num_queries_cookie_client += a->svr.num_queries_cookie_client;
|
||||
total->svr.num_queries_cookie_invalid += a->svr.num_queries_cookie_invalid;
|
||||
total->svr.num_queries_missed_cache += a->svr.num_queries_missed_cache;
|
||||
total->svr.num_queries_prefetch += a->svr.num_queries_prefetch;
|
||||
total->svr.num_queries_timed_out += a->svr.num_queries_timed_out;
|
||||
if (total->svr.max_query_time_us < a->svr.max_query_time_us)
|
||||
total->svr.max_query_time_us = a->svr.max_query_time_us;
|
||||
total->svr.sum_query_list_size += a->svr.sum_query_list_size;
|
||||
total->svr.ans_expired += a->svr.ans_expired;
|
||||
#ifdef USE_DNSCRYPT
|
||||
@@ -471,6 +484,9 @@ void server_stats_add(struct ub_stats_info* total, struct ub_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;
|
||||
#ifdef USE_CACHEDB
|
||||
total->svr.num_query_cachedb += a->svr.num_query_cachedb;
|
||||
#endif
|
||||
for(i=0; i<UB_STATS_QTYPE_NUM; i++)
|
||||
total->svr.qtype[i] += a->svr.qtype[i];
|
||||
for(i=0; i<UB_STATS_QCLASS_NUM; i++)
|
||||
@@ -514,7 +530,7 @@ void server_stats_insquery(struct ub_server_stats* stats, struct comm_point* c,
|
||||
if(c->ssl != NULL) {
|
||||
stats->qtls++;
|
||||
#ifdef HAVE_SSL
|
||||
if(SSL_session_reused(c->ssl))
|
||||
if(SSL_session_reused(c->ssl))
|
||||
stats->qtls_resume++;
|
||||
#endif
|
||||
if(c->type == comm_http)
|
||||
@@ -555,3 +571,16 @@ void server_stats_insrcode(struct ub_server_stats* stats, sldns_buffer* buf)
|
||||
stats->ans_rcode_nodata ++;
|
||||
}
|
||||
}
|
||||
|
||||
void server_stats_downstream_cookie(struct ub_server_stats* stats,
|
||||
struct edns_data* edns)
|
||||
{
|
||||
if(!(edns->edns_present && edns->cookie_present)) return;
|
||||
if(edns->cookie_valid) {
|
||||
stats->num_queries_cookie_valid++;
|
||||
} else if(edns->cookie_client) {
|
||||
stats->num_queries_cookie_client++;
|
||||
} else {
|
||||
stats->num_queries_cookie_invalid++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -126,4 +126,11 @@ void server_stats_insquery(struct ub_server_stats* stats, struct comm_point* c,
|
||||
*/
|
||||
void server_stats_insrcode(struct ub_server_stats* stats, struct sldns_buffer* buf);
|
||||
|
||||
/**
|
||||
* Add DNS Cookie stats for this query
|
||||
* @param stats: the stats
|
||||
* @param edns: edns record
|
||||
*/
|
||||
void server_stats_downstream_cookie(struct ub_server_stats* stats,
|
||||
struct edns_data* edns);
|
||||
#endif /* DAEMON_STATS_H */
|
||||
|
||||
+330
-168
File diff suppressed because it is too large
Load Diff
+3
-1
@@ -118,7 +118,7 @@ struct worker {
|
||||
/** do we need to restart or quit (on signal) */
|
||||
int need_to_exit;
|
||||
/** allocation cache for this thread */
|
||||
struct alloc_cache alloc;
|
||||
struct alloc_cache *alloc;
|
||||
/** per thread statistics */
|
||||
struct ub_server_stats stats;
|
||||
/** thread scratch regional */
|
||||
@@ -131,6 +131,8 @@ struct worker {
|
||||
/** dnstap environment, changed for this thread */
|
||||
struct dt_env dtenv;
|
||||
#endif
|
||||
/** reuse existing cache on reload if other conditions allow it. */
|
||||
int reuse_cache;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
+58
-43
@@ -59,7 +59,7 @@
|
||||
******************************************************************************/
|
||||
|
||||
/**
|
||||
* This is the default DNS64 prefix that is used whent he dns64 module is listed
|
||||
* This is the default DNS64 prefix that is used when the dns64 module is listed
|
||||
* in module-config but when the dns64-prefix variable is not present.
|
||||
*/
|
||||
static const char DEFAULT_DNS64_PREFIX[] = "64:ff9b::/96";
|
||||
@@ -573,28 +573,29 @@ static enum module_ext_state
|
||||
handle_event_pass(struct module_qstate* qstate, int id)
|
||||
{
|
||||
struct dns64_qstate* iq = (struct dns64_qstate*)qstate->minfo[id];
|
||||
if (iq && iq->state == DNS64_NEW_QUERY
|
||||
&& qstate->qinfo.qtype == LDNS_RR_TYPE_PTR
|
||||
&& qstate->qinfo.qname_len == 74
|
||||
&& !strcmp((char*)&qstate->qinfo.qname[64], "\03ip6\04arpa"))
|
||||
/* Handle PTR queries for IPv6 addresses. */
|
||||
return handle_ipv6_ptr(qstate, id);
|
||||
int synth_all_cfg = qstate->env->cfg->dns64_synthall;
|
||||
int synth_qname = 0;
|
||||
|
||||
if (qstate->env->cfg->dns64_synthall &&
|
||||
iq && iq->state == DNS64_NEW_QUERY
|
||||
&& qstate->qinfo.qtype == LDNS_RR_TYPE_AAAA)
|
||||
return generate_type_A_query(qstate, id);
|
||||
if(iq && iq->state == DNS64_NEW_QUERY
|
||||
&& qstate->qinfo.qtype == LDNS_RR_TYPE_PTR
|
||||
&& qstate->qinfo.qname_len == 74
|
||||
&& !strcmp((char*)&qstate->qinfo.qname[64], "\03ip6\04arpa")) {
|
||||
/* Handle PTR queries for IPv6 addresses. */
|
||||
return handle_ipv6_ptr(qstate, id);
|
||||
}
|
||||
|
||||
if(dns64_always_synth_for_qname(qstate, id) &&
|
||||
iq && iq->state == DNS64_NEW_QUERY
|
||||
&& !(qstate->query_flags & BIT_CD)
|
||||
&& qstate->qinfo.qtype == LDNS_RR_TYPE_AAAA) {
|
||||
verbose(VERB_ALGO, "dns64: ignore-aaaa and synthesize anyway");
|
||||
if(iq && iq->state == DNS64_NEW_QUERY &&
|
||||
qstate->qinfo.qtype == LDNS_RR_TYPE_AAAA &&
|
||||
(synth_all_cfg ||
|
||||
(synth_qname=(dns64_always_synth_for_qname(qstate, id)
|
||||
&& !(qstate->query_flags & BIT_CD))))) {
|
||||
if(synth_qname)
|
||||
verbose(VERB_ALGO, "dns64: ignore-aaaa and synthesize anyway");
|
||||
return generate_type_A_query(qstate, id);
|
||||
}
|
||||
|
||||
/* We are finished when our sub-query is finished. */
|
||||
if (iq && iq->state == DNS64_SUBQUERY_FINISHED)
|
||||
if(iq && iq->state == DNS64_SUBQUERY_FINISHED)
|
||||
return module_finished;
|
||||
|
||||
/* Otherwise, pass request to next module. */
|
||||
@@ -627,32 +628,37 @@ handle_event_moddone(struct module_qstate* qstate, int id)
|
||||
* synthesize in (sec 5.1.2 of RFC6147).
|
||||
* - A successful AAAA query with an answer.
|
||||
*/
|
||||
if((!iq || iq->state != DNS64_INTERNAL_QUERY)
|
||||
&& qstate->qinfo.qtype == LDNS_RR_TYPE_AAAA
|
||||
&& !(qstate->query_flags & BIT_CD)
|
||||
&& !(qstate->return_msg &&
|
||||
qstate->return_msg->rep &&
|
||||
reply_find_answer_rrset(&qstate->qinfo,
|
||||
qstate->return_msg->rep)))
|
||||
/* not internal, type AAAA, not CD, and no answer RRset,
|
||||
* So, this is a AAAA noerror/nodata answer */
|
||||
return generate_type_A_query(qstate, id);
|
||||
|
||||
if((!iq || iq->state != DNS64_INTERNAL_QUERY)
|
||||
&& qstate->qinfo.qtype == LDNS_RR_TYPE_AAAA
|
||||
&& !(qstate->query_flags & BIT_CD)
|
||||
&& dns64_always_synth_for_qname(qstate, id)) {
|
||||
/* if it is not internal, AAAA, not CD and listed domain,
|
||||
* generate from A record and ignore AAAA */
|
||||
verbose(VERB_ALGO, "dns64: ignore-aaaa and synthesize anyway");
|
||||
/* When an AAAA query completes check if we want to perform DNS64
|
||||
* synthesis. We skip queries with DNSSEC enabled (!CD) and
|
||||
* ones generated by us to retrive the A/PTR record to use for
|
||||
* synth. */
|
||||
int could_synth =
|
||||
qstate->qinfo.qtype == LDNS_RR_TYPE_AAAA &&
|
||||
(!iq || iq->state != DNS64_INTERNAL_QUERY) &&
|
||||
!(qstate->query_flags & BIT_CD);
|
||||
int has_data = /* whether query returned non-empty rrset */
|
||||
qstate->return_msg &&
|
||||
qstate->return_msg->rep &&
|
||||
reply_find_answer_rrset(&qstate->qinfo, qstate->return_msg->rep);
|
||||
int synth_qname = 0;
|
||||
|
||||
if(could_synth &&
|
||||
(!has_data ||
|
||||
(synth_qname=dns64_always_synth_for_qname(qstate, id)))) {
|
||||
if(synth_qname)
|
||||
verbose(VERB_ALGO, "dns64: ignore-aaaa and synthesize anyway");
|
||||
return generate_type_A_query(qstate, id);
|
||||
}
|
||||
|
||||
/* Store the response in cache. */
|
||||
if ( (!iq || !iq->started_no_cache_store) &&
|
||||
qstate->return_msg && qstate->return_msg->rep &&
|
||||
!dns_cache_store(qstate->env, &qstate->qinfo, qstate->return_msg->rep,
|
||||
0, 0, 0, NULL, qstate->query_flags, qstate->qstarttime))
|
||||
if( (!iq || !iq->started_no_cache_store) &&
|
||||
qstate->return_msg &&
|
||||
qstate->return_msg->rep &&
|
||||
!dns_cache_store(
|
||||
qstate->env, &qstate->qinfo, qstate->return_msg->rep,
|
||||
0, 0, 0, NULL,
|
||||
qstate->query_flags, qstate->qstarttime))
|
||||
log_err("out of memory");
|
||||
|
||||
/* do nothing */
|
||||
@@ -841,7 +847,7 @@ dns64_adjust_a(int id, struct module_qstate* super, struct module_qstate* qstate
|
||||
cp = construct_reply_info_base(super->region, rep->flags, rep->qdcount,
|
||||
rep->ttl, rep->prefetch_ttl, rep->serve_expired_ttl,
|
||||
rep->an_numrrsets, rep->ns_numrrsets, rep->ar_numrrsets,
|
||||
rep->rrset_count, rep->security);
|
||||
rep->rrset_count, rep->security, LDNS_EDE_NONE);
|
||||
if(!cp)
|
||||
return;
|
||||
|
||||
@@ -969,10 +975,19 @@ dns64_inform_super(struct module_qstate* qstate, int id,
|
||||
}
|
||||
super_dq->state = DNS64_SUBQUERY_FINISHED;
|
||||
|
||||
/* If there is no successful answer, we're done. */
|
||||
if (qstate->return_rcode != LDNS_RCODE_NOERROR
|
||||
|| !qstate->return_msg
|
||||
|| !qstate->return_msg->rep) {
|
||||
/* If there is no successful answer, we're done.
|
||||
* Guarantee that we have at least a NOERROR reply further on. */
|
||||
if(qstate->return_rcode != LDNS_RCODE_NOERROR
|
||||
|| !qstate->return_msg
|
||||
|| !qstate->return_msg->rep) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* When no A record is found for synthesis fall back to AAAA again. */
|
||||
if(qstate->qinfo.qtype == LDNS_RR_TYPE_A &&
|
||||
!reply_find_answer_rrset(&qstate->qinfo,
|
||||
qstate->return_msg->rep)) {
|
||||
super_dq->state = DNS64_INTERNAL_QUERY;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
+5
-2
@@ -388,12 +388,15 @@ dt_msg_send_client_query(struct dt_env *env,
|
||||
struct sockaddr_storage *qsock,
|
||||
struct sockaddr_storage *rsock,
|
||||
enum comm_point_type cptype,
|
||||
sldns_buffer *qmsg)
|
||||
sldns_buffer *qmsg,
|
||||
struct timeval* tstamp)
|
||||
{
|
||||
struct dt_msg dm;
|
||||
struct timeval qtime;
|
||||
|
||||
gettimeofday(&qtime, NULL);
|
||||
if(tstamp)
|
||||
memcpy(&qtime, tstamp, sizeof(qtime));
|
||||
else gettimeofday(&qtime, NULL);
|
||||
|
||||
/* type */
|
||||
dt_msg_init(env, &dm, DNSTAP__MESSAGE__TYPE__CLIENT_QUERY);
|
||||
|
||||
+3
-1
@@ -126,13 +126,15 @@ dt_delete(struct dt_env *env);
|
||||
* @param rsock: local (service) address/port.
|
||||
* @param cptype: comm_udp or comm_tcp.
|
||||
* @param qmsg: query message.
|
||||
* @param tstamp: timestamp or NULL if none provided.
|
||||
*/
|
||||
void
|
||||
dt_msg_send_client_query(struct dt_env *env,
|
||||
struct sockaddr_storage *qsock,
|
||||
struct sockaddr_storage *rsock,
|
||||
enum comm_point_type cptype,
|
||||
struct sldns_buffer *qmsg);
|
||||
struct sldns_buffer *qmsg,
|
||||
struct timeval* tstamp);
|
||||
|
||||
/**
|
||||
* Create and send a new dnstap "Message" event of type CLIENT_RESPONSE.
|
||||
|
||||
+1
-1
@@ -41,7 +41,7 @@ AC_DEFUN([dt_DNSTAP],
|
||||
fi
|
||||
])
|
||||
AC_SEARCH_LIBS([protobuf_c_message_pack], [protobuf-c], [],
|
||||
AC_MSG_ERROR([The protobuf-c library was not found. Please install protobuf-c!]))
|
||||
AC_MSG_ERROR([The protobuf-c library was not found. Please install the development libraries for protobuf-c!]))
|
||||
$2
|
||||
else
|
||||
$3
|
||||
|
||||
+4
-4
@@ -788,7 +788,7 @@ static int dtio_write_ssl(struct dt_io_thread* dtio, uint8_t* buf,
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
log_crypto_err("dnstap io, could not SSL_write");
|
||||
log_crypto_err_io("dnstap io, could not SSL_write", want);
|
||||
return -1;
|
||||
}
|
||||
return r;
|
||||
@@ -1029,7 +1029,7 @@ static int ssl_read_bytes(struct dt_io_thread* dtio, void* buf, size_t len)
|
||||
"other side");
|
||||
return 0;
|
||||
}
|
||||
log_crypto_err("could not SSL_read");
|
||||
log_crypto_err_io("could not SSL_read", want);
|
||||
verbose(VERB_DETAIL, "dnstap io: output closed by the "
|
||||
"other side");
|
||||
return 0;
|
||||
@@ -1431,8 +1431,8 @@ static int dtio_ssl_handshake(struct dt_io_thread* dtio,
|
||||
} else {
|
||||
unsigned long err = ERR_get_error();
|
||||
if(!squelch_err_ssl_handshake(err)) {
|
||||
log_crypto_err_code("dnstap io, ssl handshake failed",
|
||||
err);
|
||||
log_crypto_err_io_code("dnstap io, ssl handshake failed",
|
||||
want, err);
|
||||
verbose(VERB_OPS, "dnstap io, ssl handshake failed "
|
||||
"from %s", dtio->ip_str);
|
||||
}
|
||||
|
||||
@@ -61,6 +61,7 @@
|
||||
#include "services/listen_dnsport.h"
|
||||
#include "sldns/sbuffer.h"
|
||||
#include "sldns/wire2str.h"
|
||||
#include "sldns/pkthdr.h"
|
||||
#ifdef USE_DNSTAP
|
||||
#include <protobuf-c/protobuf-c.h>
|
||||
#include "dnstap/dnstap.pb-c.h"
|
||||
@@ -448,6 +449,7 @@ static char* q_of_msg(ProtobufCBinaryData message)
|
||||
char buf[300];
|
||||
/* header, name, type, class minimum to get the query tuple */
|
||||
if(message.len < 12 + 1 + 4 + 4) return NULL;
|
||||
if(LDNS_QDCOUNT(message.data) < 1) return NULL;
|
||||
if(sldns_wire2str_rrquestion_buf(message.data+12, message.len-12,
|
||||
buf, sizeof(buf)) != 0) {
|
||||
/* remove trailing newline, tabs to spaces */
|
||||
@@ -502,7 +504,7 @@ static char* tv_to_str(protobuf_c_boolean has_time_sec, uint64_t time_sec,
|
||||
time_t time_t_sec;
|
||||
memset(&tv, 0, sizeof(tv));
|
||||
if(has_time_sec) tv.tv_sec = time_sec;
|
||||
if(has_time_nsec) tv.tv_usec = time_nsec;
|
||||
if(has_time_nsec) tv.tv_usec = time_nsec/1000;
|
||||
|
||||
buf[0]=0;
|
||||
time_t_sec = tv.tv_sec;
|
||||
@@ -706,7 +708,7 @@ static ssize_t ssl_read_bytes(struct tap_data* data, void* buf, size_t len)
|
||||
(data->id?data->id:""));
|
||||
return 0;
|
||||
}
|
||||
log_crypto_err("could not SSL_read");
|
||||
log_crypto_err_io("could not SSL_read", want);
|
||||
if(verbosity) log_info("dnstap client stream closed from %s",
|
||||
(data->id?data->id:""));
|
||||
return 0;
|
||||
@@ -758,10 +760,11 @@ static int reply_with_accept(struct tap_data* data)
|
||||
fd_set_block(data->fd);
|
||||
if(data->ssl) {
|
||||
if((r=SSL_write(data->ssl, acceptframe, len)) <= 0) {
|
||||
if(SSL_get_error(data->ssl, r) == SSL_ERROR_ZERO_RETURN)
|
||||
int r2;
|
||||
if((r2=SSL_get_error(data->ssl, r)) == SSL_ERROR_ZERO_RETURN)
|
||||
log_err("SSL_write, peer closed connection");
|
||||
else
|
||||
log_err("could not SSL_write");
|
||||
log_crypto_err_io("could not SSL_write", r2);
|
||||
fd_set_nonblock(data->fd);
|
||||
free(acceptframe);
|
||||
return 0;
|
||||
@@ -789,7 +792,7 @@ static int reply_with_accept(struct tap_data* data)
|
||||
|
||||
/** reply with FINISH control frame to bidirectional client,
|
||||
* returns 0 on error */
|
||||
static int reply_with_finish(int fd)
|
||||
static int reply_with_finish(struct tap_data* data)
|
||||
{
|
||||
#ifdef USE_DNSTAP
|
||||
size_t len = 0;
|
||||
@@ -799,21 +802,35 @@ static int reply_with_finish(int fd)
|
||||
return 0;
|
||||
}
|
||||
|
||||
fd_set_block(fd);
|
||||
if(send(fd, finishframe, len, 0) == -1) {
|
||||
log_err("send failed: %s", sock_strerror(errno));
|
||||
fd_set_nonblock(fd);
|
||||
free(finishframe);
|
||||
return 0;
|
||||
fd_set_block(data->fd);
|
||||
if(data->ssl) {
|
||||
int r;
|
||||
if((r=SSL_write(data->ssl, finishframe, len)) <= 0) {
|
||||
int r2;
|
||||
if((r2=SSL_get_error(data->ssl, r)) == SSL_ERROR_ZERO_RETURN)
|
||||
log_err("SSL_write, peer closed connection");
|
||||
else
|
||||
log_crypto_err_io("could not SSL_write", r2);
|
||||
fd_set_nonblock(data->fd);
|
||||
free(finishframe);
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
if(send(data->fd, finishframe, len, 0) == -1) {
|
||||
log_err("send failed: %s", sock_strerror(errno));
|
||||
fd_set_nonblock(data->fd);
|
||||
free(finishframe);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if(verbosity) log_info("sent control frame(finish)");
|
||||
|
||||
fd_set_nonblock(fd);
|
||||
fd_set_nonblock(data->fd);
|
||||
free(finishframe);
|
||||
return 1;
|
||||
#else
|
||||
log_err("no dnstap compiled, no reply");
|
||||
(void)fd;
|
||||
(void)data;
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
@@ -933,7 +950,7 @@ static int tap_handshake(struct tap_data* data)
|
||||
#endif /* HAVE_SSL */
|
||||
|
||||
/** callback for dnstap listener */
|
||||
void dtio_tap_callback(int fd, short ATTR_UNUSED(bits), void* arg)
|
||||
void dtio_tap_callback(int ATTR_UNUSED(fd), short ATTR_UNUSED(bits), void* arg)
|
||||
{
|
||||
struct tap_data* data = (struct tap_data*)arg;
|
||||
if(verbosity>=3) log_info("tap callback");
|
||||
@@ -1016,7 +1033,7 @@ void dtio_tap_callback(int fd, short ATTR_UNUSED(bits), void* arg)
|
||||
}
|
||||
} else if(data->len >= 4 && sldns_read_uint32(data->frame) ==
|
||||
FSTRM_CONTROL_FRAME_STOP && data->is_bidirectional) {
|
||||
if(!reply_with_finish(fd)) {
|
||||
if(!reply_with_finish(data)) {
|
||||
tap_data_free(data);
|
||||
return;
|
||||
}
|
||||
|
||||
+536
-1
@@ -1,3 +1,538 @@
|
||||
2 November 2023: Wouter
|
||||
- Set version number to 1.19.0.
|
||||
- Tag for 1.19.0rc1 release.
|
||||
|
||||
1 November 2023: George
|
||||
- Mention flex and bison in README.md when building from repository
|
||||
source.
|
||||
|
||||
1 November 2023: Wouter
|
||||
- Fix SSL compile failure for definition in log_crypto_err_io_code_arg.
|
||||
- Fix SSL compile failure for other missing definitions in
|
||||
log_crypto_err_io_code_arg.
|
||||
- Fix compilation without openssl, remove unused function warning.
|
||||
|
||||
31 October 2023: George
|
||||
- Fix #941: dnscrypt doesn't work after upgrade to 1.18 with
|
||||
suggestion by dukeartem to also fix the udp_ancil with dnscrypt.
|
||||
|
||||
30 October 2023: George
|
||||
- Merge #930 from Stuart Henderson: add void to
|
||||
log_ident_revert_to_default declaration.
|
||||
|
||||
30 October 2023: Wouter
|
||||
- autoconf.
|
||||
|
||||
24 October 2023: George
|
||||
- Clearer configure text for missing protobuf-c development libraries.
|
||||
|
||||
20 October 2023: Wouter
|
||||
- Merge #951: Cachedb no store. The cachedb-no-store: yes option is
|
||||
used to stop cachedb from writing messages to the backend storage.
|
||||
It reads messages when data is available from the backend. The
|
||||
default is no.
|
||||
|
||||
19 October 2023: Wouter
|
||||
- Fix to print detailed errors when an SSL IO routine fails via
|
||||
SSL_get_error.
|
||||
|
||||
18 October 2023: George
|
||||
- Mailing list patches from Daniel Gröber for DNS64 fallback to plain
|
||||
AAAA when no A record exists for synthesis, and minor DNS64 code
|
||||
refactoring for better readability.
|
||||
- Fixes for the DNS64 patches.
|
||||
- Update the dns64_lookup.rpl test for the DNS64 fallback patch.
|
||||
- Merge #955 from buevsan: fix ipset wrong behavior.
|
||||
- Update testdata/ipset.tdir test for ipset fix.
|
||||
|
||||
17 October 2023: Wouter
|
||||
- Fix #954: Inconsistent RPZ handling for A record returned along with
|
||||
CNAME.
|
||||
|
||||
16 October 2023: George
|
||||
- Expose the script filename in the Python module environment 'mod_env'
|
||||
instead of the config_file structure which includes the linked list
|
||||
of scripts in a multi Python module setup; fixes #79.
|
||||
- Expose the configured listening and outgoing interfaces, if any, as
|
||||
a list of strings in the Python 'config_file' class instead of the
|
||||
current Swig object proxy; fixes #79.
|
||||
- For multi Python module setups, clean previously parsed module
|
||||
functions in __main__'s dictionary, if any, so that only current
|
||||
module functions are registered.
|
||||
|
||||
13 October 2023: George
|
||||
- Better fix for infinite loop when reading multiple lines of input on
|
||||
a broken remote control socket, by treating a zero byte line the
|
||||
same as transmission end. Addesses #947 and #948.
|
||||
|
||||
12 October 2023: Wouter
|
||||
- Merge #944: Disable EDNS DO.
|
||||
Disable the EDNS DO flag in upstream requests. This can be helpful
|
||||
for devices that cannot handle DNSSEC information. But it should not
|
||||
be enabled otherwise, because that would stop DNSSEC validation. The
|
||||
DNSSEC validation would not work for Unbound itself, and also not
|
||||
for downstream users. Default is no. The option
|
||||
is disable-edns-do: no
|
||||
|
||||
11 October 2023: George
|
||||
- Fix #850: [FR] Ability to use specific database in Redis, with new
|
||||
redis-logical-db configuration option.
|
||||
|
||||
11 October 2023: Wouter
|
||||
- Fix #949: "could not create control compt".
|
||||
- Fix that cachedb does not warn when serve-expired is disabled about
|
||||
use of serve-expired-reply-ttl and serve-expired-client-timeout.
|
||||
- Fix for #949: Fix pythonmod/ubmodule-tst.py for Python 3.x.
|
||||
|
||||
10 October 2023: George
|
||||
- Fix infinite loop when reading multiple lines of input on a broken
|
||||
remote control socket. Addesses #947 and #948.
|
||||
|
||||
9 October 2023: Wouter
|
||||
- Fix edns subnet so that queries with a source prefix of zero cause
|
||||
the recursor send no edns subnet option to the upstream.
|
||||
- Fix that printout of EDNS options shows the EDNS cookie option by
|
||||
name.
|
||||
|
||||
4 October 2023: Wouter
|
||||
- Fix #946: Forwarder returns servfail on upstream response noerror no
|
||||
data.
|
||||
|
||||
3 October 2023: George
|
||||
- Merge #881: Generalise the proxy protocol code.
|
||||
|
||||
2 October 2023: George
|
||||
- Fix misplaced comment.
|
||||
|
||||
22 September 2023: Wouter
|
||||
- Fix #942: 1.18.0 libunbound DNS regression when built without
|
||||
OpenSSL.
|
||||
|
||||
18 September 2023: Wouter
|
||||
- Fix rpz tcp-only action with rpz triggers nsdname and nsip.
|
||||
|
||||
15 September 2023: Wouter
|
||||
- Merge #936: Check for c99 with autoconf versions prior to 2.70.
|
||||
- Fix to remove two c99 notations.
|
||||
|
||||
14 September 2023: Wouter
|
||||
- Fix authority zone answers for obscured DNAMEs and delegations.
|
||||
|
||||
8 September 2023: Wouter
|
||||
- Fix send of udp retries when ENOBUFS is returned. It stops looping
|
||||
and also waits for the condition to go away. Reported by Florian
|
||||
Obser.
|
||||
|
||||
7 September 2023: Wouter
|
||||
- Fix to scrub resource records of type A and AAAA that have an
|
||||
inappropriate size. They are removed from responses.
|
||||
- Fix to move msgparse_rrset_remove_rr code to util/msgparse.c.
|
||||
- Fix to add EDE text when RRs have been removed due to length.
|
||||
- Fix to set ede match in unit test for rr length removal.
|
||||
- Fix to print EDE text in readable form in output logs.
|
||||
|
||||
6 September 2023: Wouter
|
||||
- Merge #931: Prevent warnings from -Wmissing-prototypes.
|
||||
|
||||
31 August 2023: Wouter
|
||||
- Fix autoconf 2.69 warnings in configure.
|
||||
- Fix #927: unbound 1.18.0 make test error. Fix make test without SHA1.
|
||||
|
||||
30 August 2023: Wouter
|
||||
- Fix for WKS call to getservbyname that creates allocation on exit
|
||||
in unit test by testing numbers first and testing from the services
|
||||
list later.
|
||||
|
||||
28 August 2023: Wouter
|
||||
- Fix for version generation race condition that ignored changes.
|
||||
|
||||
25 August 2023: Wouter
|
||||
- Fix compile error on NetBSD in util/netevent.h.
|
||||
|
||||
23 August 2023: Wouter
|
||||
- Tag for 1.18.0rc1 release. This became the 1.18.0 release on
|
||||
30 aug 2023, with the fix from 25 aug, fix compile on NetBSD
|
||||
included. The repository continues with version 1.18.1.
|
||||
|
||||
22 August 2023: Wouter
|
||||
- Set version number to 1.18.0.
|
||||
|
||||
21 August 2023: Wouter
|
||||
- Debug Windows ci workflow.
|
||||
- Fix windows ci workflow to install bison and flex.
|
||||
- Fix for #925: unbound.service: Main process exited, code=killed,
|
||||
status=11/SEGV. Fixes cachedb configuration handling.
|
||||
- Fix #923: processQueryResponse() THROWAWAY should be mindful of
|
||||
fail_reply.
|
||||
- Fix unit test for unbound-control to work when threads are disabled,
|
||||
and fix cache dump check.
|
||||
|
||||
18 August 2023: Wouter
|
||||
- Fix for iter_dec_attempts that could cause a hang, part of
|
||||
capsforid and qname minimisation, depending on the settings.
|
||||
- Fix uninitialized memory passed in padding bytes of cmsg to sendmsg.
|
||||
- Fix stat_values test to work with dig that enables DNS cookies.
|
||||
|
||||
17 August 2023: Wouter
|
||||
- Merge PR #762: Downstream DNS Server Cookies a la RFC7873 and
|
||||
RFC9018. Create server cookies for clients that send client cookies.
|
||||
This needs to be explicitly turned on in the config file with:
|
||||
`answer-cookie: yes`. A `cookie-secret:` can be configured for
|
||||
anycast setups. Without one, a random cookie secret is generated.
|
||||
The acl option `allow_cookie` allows queries with either a valid
|
||||
cookie or over a stateful transport. The statistics output has
|
||||
`queries_cookie_valid` and `queries_cookie_client` and
|
||||
`queries_cookie_invalid` information. The `ip\-ratelimit\-cookie:`
|
||||
value determines a rate limit for queries with cookies, if desired.
|
||||
- Fix regional_alloc_init for potential unaligned source of the copy.
|
||||
- Fix ip_ratelimit test to work with dig that enables DNS cookies.
|
||||
|
||||
2 August 2023: George
|
||||
- Move a cache reply callback in worker.c closer to the cache reply
|
||||
generation.
|
||||
|
||||
1 August 2023: George
|
||||
- Merge #911 from natalie-reece: Exclude EDE before other EDNS options
|
||||
when there isn't enough space.
|
||||
- For #911: Try to trim EXTRA-TEXT (and LDNS_EDE_OTHER options
|
||||
altogether) before giving up on attaching EDE options.
|
||||
- More braces and formatting for Fix for EDNS EDE size calculation to
|
||||
avoid future bugs.
|
||||
- Fix to use the now cached EDE, if any, for CD_bit queries.
|
||||
|
||||
1 August 2023: Wouter
|
||||
- Fix for EDNS EDE size calculation.
|
||||
|
||||
31 July 2023: George
|
||||
- Merge #790 from Tom Carpay: Add support for EDE caching in cachedb
|
||||
and subnetcache.
|
||||
|
||||
31 July 2023: Wouter
|
||||
- iana portlist update.
|
||||
|
||||
30 July 2023: George
|
||||
- Merge #759 from Tom Carpay: Add EDE (RFC8914) caching.
|
||||
|
||||
28 July 2023: George
|
||||
- Fix unused variable compile warning for kernel timestamps in
|
||||
netevent.c
|
||||
|
||||
21 July 2023: George
|
||||
- Merge #857 from eaglegai: fix potential memory leaks when errors
|
||||
happen.
|
||||
- For #857: fix mixed declarations and code.
|
||||
- Merge #118 from mibere: Changed verbosity level for Redis init &
|
||||
deinit.
|
||||
- Merge #390 from Frank Riley: Add missing callbacks to the python
|
||||
module.
|
||||
- Cleaner failure code for callback functions in interface.i.
|
||||
- Merge #889 from borisVanhoof: Free memory in error case + remove
|
||||
unused function.
|
||||
- For #889: use netcat-openbsd instead of netcat-traditional.
|
||||
- For #889: Account for num_detached_states before possible
|
||||
mesh_state_delete when erroring out.
|
||||
|
||||
20 July 2023: George
|
||||
- Merge #909 from headshog: Numeric truncation when parsing TYPEXX and
|
||||
CLASSXX representation.
|
||||
- For #909: Fix return values.
|
||||
- Merge #901 from Sergei Trofimovich: config: improve handling of
|
||||
unknown modules.
|
||||
|
||||
20 July 2023: Wouter
|
||||
- For #909: Fix RR class comparison.
|
||||
|
||||
14 July 2023: George
|
||||
- More clear description of the different auth-zone behaviors on the
|
||||
man page.
|
||||
|
||||
13 July 2023: George
|
||||
- Merge #880 from chipitsine: services/authzone.c: remove redundant
|
||||
check.
|
||||
|
||||
11 July 2023: George
|
||||
- Merge #664 from tilan7763: Add prefetch support for subnet cache
|
||||
entries.
|
||||
- For #664: Easier code flow for subnetcache prefetching.
|
||||
- For #664: Add testcase.
|
||||
- For #664: Rename subnet_prefetch tests to subnet_global_prefetch to
|
||||
differentiate from the new subnet prefetch support.
|
||||
|
||||
3 July 2023: George
|
||||
- Merge #739: Add SVCB dohpath support.
|
||||
- Code cleanup for sldns_str2wire_svcparam_key_lookup.
|
||||
- Merge #802: add validation EDEs to queries where the CD bit is set.
|
||||
- For #802: Cleanup comments and add RCODE check for CD bit test case.
|
||||
- Skip the 00-lint test. splint is not maintained; it either does not
|
||||
work or produces false positives. Static analysis is handled in the
|
||||
clang test.
|
||||
|
||||
3 July 2023: Wouter
|
||||
- Fix #906: warning: ‘Py_SetProgramName’ is deprecated.
|
||||
- Fix dereference of NULL variable warning in mesh_do_callback.
|
||||
|
||||
29 June 2023: George
|
||||
- More fixes for reference counting for python module and clean up
|
||||
failure code.
|
||||
- Merge #827 from rcmcdonald91: Eliminate unnecessary Python reloading
|
||||
which causes memory leaks.
|
||||
|
||||
29 June 2023: Wouter
|
||||
- Fix python modules with multiple scripts, by incrementing reference
|
||||
counts.
|
||||
|
||||
27 June 2023: George
|
||||
- Merge #892: Add cachedb hit stat. Introduces 'num.query.cachedb' as
|
||||
a new statistical counter.
|
||||
- Remove warning about unknown cast-function-type warning pragma.
|
||||
|
||||
22 June 2023: Wouter
|
||||
- Merge #903: contrib: add yocto compatible init script.
|
||||
|
||||
15 June 2023: Philip
|
||||
- Fix for issue #887 (Timeouts to forward servers on BSD based
|
||||
system with ASLR)
|
||||
- Probably fixes #516 (Stream reuse does not work on Windows) as well
|
||||
|
||||
14 June 2023: George
|
||||
- Properly handle all return values of worker_check_request during
|
||||
early EDE code.
|
||||
- Do not check the incoming request more than once.
|
||||
|
||||
12 June 2023: Wouter
|
||||
- Merge #896: Fix: #895: pythonmodule: add all site-packages
|
||||
directories to sys.path.
|
||||
- Fix #895: python + sysconfig gives ANOTHER path comparing to
|
||||
distutils.
|
||||
- Fix for uncertain unit test for doh buffer size events.
|
||||
|
||||
25 May 2023: Wouter
|
||||
- Fix unbound-dnstap-socket printout when no query is present.
|
||||
- Fix unbound-dnstap-socket time fraction conversion for printout.
|
||||
|
||||
19 May 2023: Wouter
|
||||
- Fix RPZ removal of client-ip, nsip, nsdname triggers from IXFR.
|
||||
- Fix to remove unused variables from RPZ clientip data structure.
|
||||
|
||||
16 May 2023: Wouter
|
||||
- Fix #888: [FR] Use kernel timestamps for dnstap.
|
||||
- Fix to print debug log for ancillary data with correct IP address.
|
||||
|
||||
11 May 2023: Wouter
|
||||
- Fix warning in windows compile, in set_recvtimestamp.
|
||||
|
||||
4 May 2023: Wouter
|
||||
- Fix #885: Error: util/configlexer.c: No such file or directory,
|
||||
adds error messages explaining to install flex and bison.
|
||||
- Fix to remove unused whitespace from acx_nlnetlabs.m4 and config.h.
|
||||
- Fix doxygen in addr_to_nat64 header definition.
|
||||
|
||||
1 May 2023: George
|
||||
- Merge #722 from David 'eqvinox' Lamparter: NAT64 support.
|
||||
- For #722: minor fixes, formatting, refactoring.
|
||||
|
||||
1 May 2023: Wouter
|
||||
- Fix RPZ IP responses with trigger rpz-drop on cache entries, that
|
||||
they are dropped.
|
||||
|
||||
26 April 2023: Philip
|
||||
- Fix issue #860: Bad interaction with 0 TTL records and serve-expired
|
||||
|
||||
26 April 2023: Wouter
|
||||
- Merge #882 from vvfedorenko: Features/dropqueuedpackets, with
|
||||
sock-queue-timeout option that drops packets that have been in the
|
||||
socket queue for too long. Added statistics num.queries_timed_out
|
||||
and query.queue_time_us.max that track the socket queue timeouts.
|
||||
- Fix for #882: small changes, date updated in Copyright for
|
||||
util/timeval_func.c and util/timeval_func.h. Man page entries and
|
||||
example entry.
|
||||
- Fix for #882: document variable to stop doxygen warning.
|
||||
|
||||
19 April 2023: Wouter
|
||||
- Fix for #878: Invalid IP address in unbound.conf causes Segmentation
|
||||
Fault on OpenBSD.
|
||||
|
||||
14 April 2023: Wouter
|
||||
- Merge #875: change obsolete txt URL in unbound-anchor.c to point
|
||||
to RFC 7958, and Fix #874.
|
||||
|
||||
13 April 2023: Wouter
|
||||
- Fix build badge, from failing travis link to github ci action link.
|
||||
|
||||
6 April 2023: Wouter
|
||||
- Fix for #870: Add test case for the qname minimisation and CNAME.
|
||||
|
||||
4 April 2023: Wouter
|
||||
- Fix #870: NXDOMAIN instead of NOERROR rcode when asked for existing
|
||||
CNAME record.
|
||||
|
||||
24 March 2023: Philip
|
||||
- Fix issue #676: Unencrypted query is sent when
|
||||
forward-tls-upstream: yes is used without tls-cert-bundle
|
||||
- Extra consistency check to make sure that when TLS is requested,
|
||||
either we set up a TLS connection or we return an error.
|
||||
|
||||
21 March 2023: Philip
|
||||
- Fix issue #851: reserved identifier violation
|
||||
|
||||
20 March 2023: Wouter
|
||||
- iana portlist update.
|
||||
|
||||
17 March 2023: George
|
||||
- Fix #812, fix #846, by using the SSL_OP_IGNORE_UNEXPECTED_EOF option
|
||||
to ignore the unexpected eof while reading in openssl >= 3.
|
||||
|
||||
16 March 2023: Wouter
|
||||
- Fix ssl.h include brackets, instead of quotes.
|
||||
|
||||
14 March 2023: Wouter
|
||||
- Fix unbound-dnstap-socket test program to reply the finish frame
|
||||
over a TLS connection correctly.
|
||||
|
||||
23 February 2023: Wouter
|
||||
- Fix for #852: Completion of error handling.
|
||||
|
||||
21 February 2023: Philip
|
||||
- Fix #825: Unexpected behavior with client-subnet-always-forward
|
||||
and serve-expired
|
||||
|
||||
10 February 2023: George
|
||||
- Clean up iterator/iterator.c::error_response_cache() and allow for
|
||||
better interaction with serve-expired, prefetch and cached error
|
||||
responses.
|
||||
|
||||
9 February 2023: George
|
||||
- Allow TTL refresh of expired error responses.
|
||||
- Add testcase for refreshing expired error responses.
|
||||
|
||||
9 February 2023: Wouter
|
||||
- Fix to ignore entirely empty responses, and try at another authority.
|
||||
This turns completely empty responses, a type of noerror/nodata into
|
||||
a servfail, but they do not conform to RFC2308, and the retry can
|
||||
fetch improved content.
|
||||
- Fix unit tests for spurious empty messages.
|
||||
- Fix consistency of unit test without roundrobin answers for the
|
||||
cnametooptout unit test.
|
||||
- Fix to git ignore the library symbol file that configure can create.
|
||||
|
||||
8 February 2023: Wouter
|
||||
- Fix #841: Unbound won't build with aaaa-filter-iterator.patch.
|
||||
|
||||
30 January 2023: George
|
||||
- Add duration variable for speed_local.test.
|
||||
|
||||
26 January 2023: Wouter
|
||||
- Fix acx_nlnetlabs.m4 for -Wstrict-prototypes.
|
||||
|
||||
23 January 2023: George
|
||||
- Fix #833: [FR] Ability to set the Redis password.
|
||||
|
||||
23 January 2023: Wouter
|
||||
- Fix #835: [FR] Ability to use Redis unix sockets.
|
||||
|
||||
20 January 2023: Wouter
|
||||
- Merge #819: Added new static zone type block_a to suppress all A
|
||||
queries for specific zones.
|
||||
|
||||
19 January 2023: Wouter
|
||||
- Set max-udp-size default to 1232. This is the same default value as
|
||||
the default value for edns-buffer-size. It restricts client edns
|
||||
buffer size choices, and makes unbound behave similar to other DNS
|
||||
resolvers. The new choice, down from 4096 means it is harder to get
|
||||
large responses from Unbound. Thanks to Xiang Li, from NISL Lab,
|
||||
Tsinghua University.
|
||||
- Add harden-unknown-additional option. It removes
|
||||
unknown records from the authority section and additional section.
|
||||
Thanks to Xiang Li, from NISL Lab, Tsinghua University.
|
||||
- Set default for harden-unknown-additional to no. So that it does
|
||||
not hamper future protocol developments.
|
||||
- Fix test for new default.
|
||||
|
||||
18 January 2023: Wouter
|
||||
- Fix not following cleared RD flags potentially enables amplification
|
||||
DDoS attacks, reported by Xiang Li and Wei Xu from NISL Lab,
|
||||
Tsinghua University. The fix stops query loops, by refusing to send
|
||||
RD=0 queries to a forwarder, they still get answered from cache.
|
||||
|
||||
13 January 2023: Wouter
|
||||
- Merge #826: Аdd a metric about the maximum number of collisions in
|
||||
lrushah.
|
||||
- Improve documentation for #826, describe the large collisions amount.
|
||||
|
||||
9 January 2023: Wouter
|
||||
- Fix python module install path detection.
|
||||
- Fix python version detection in configure.
|
||||
|
||||
6 January 2023: Wouter
|
||||
- Fix #823: Response change to NODATA for some ANY queries since
|
||||
1.12, tested on 1.16.1.
|
||||
- Fix wildcard in hyperlocal zone service degradation, reported
|
||||
by Sergey Kacheev. This fix is included in 1.17.1rc2.
|
||||
That became 1.17.1 on 12 Jan 2023, the code repo continues
|
||||
with 1.17.2. 1.17.1 excludes fix #823, it is included forwards.
|
||||
|
||||
5 January 2023: Wouter
|
||||
- Tag for 1.17.1 release.
|
||||
|
||||
2 January 2023: Wouter
|
||||
- Fix windows compile for libunbound subprocess reap comm point closes.
|
||||
- Update github workflows to use checkout v3.
|
||||
|
||||
14 December 2022: George
|
||||
- Merge #569 from JINMEI Tatuya: add keep-cache option to
|
||||
'unbound-control reload' to keep caches.
|
||||
|
||||
13 December 2022: George
|
||||
- Expose 'statistics-inhibit-zero' as a configuration option; the
|
||||
default value retains Unbound's behavior.
|
||||
- Expose 'max-sent-count' as a configuration option; the
|
||||
default value retains Unbound's behavior.
|
||||
- Merge #461 from Christian Allred: Add max-query-restarts option.
|
||||
Exposes an internal configuration but the default value retains
|
||||
Unbound's behavior.
|
||||
|
||||
13 December 2022: Wouter
|
||||
- Merge #808: Wrap Makefile script's directory variables in quotes.
|
||||
- Fix to wrap Makefile scripts directory in quotes for uninstall.
|
||||
|
||||
1 December 2022: Wouter
|
||||
- Fix #773: When used with systemd-networkd, unbound does not start
|
||||
until systemd-networkd-wait-online.service times out.
|
||||
|
||||
30 November 2022: George
|
||||
- Add SVCB and HTTPS to the types removed by 'unbound-control flush'.
|
||||
- Clear documentation for interactivity between the subnet module and
|
||||
the serve-expired and prefetch configuration options.
|
||||
|
||||
30 November 2022: Wouter
|
||||
- Fix #782: Segmentation fault in stats.c:404.
|
||||
|
||||
28 November 2022: Wouter
|
||||
- Fix for the ignore of tcp events for closed comm points, preserve
|
||||
the use after free protection features.
|
||||
|
||||
23 November 2022: Philip
|
||||
- Merge #720 from jonathangray: fix use after free when
|
||||
WSACreateEvent() fails.
|
||||
|
||||
22 November 2022: George
|
||||
- Ignore expired error responses.
|
||||
|
||||
11 November 2022: Wouter
|
||||
- Fix #779: [doc] Missing documention in ub_resolve_event() for
|
||||
callback parameter was_ratelimited.
|
||||
|
||||
9 November 2022: George
|
||||
- Complementary fix for distutils.sysconfig deprecation in Python 3.10
|
||||
to commit 62c5039ab9da42713e006e840b7578e01d66e7f2.
|
||||
|
||||
8 November 2022: Wouter
|
||||
- Fix to ignore tcp events for closed comm points.
|
||||
- Fix to make sure to not read again after a tcp comm point is closed.
|
||||
- Fix #775: libunbound: subprocess reap causes parent process reap
|
||||
to hang.
|
||||
- iana portlist update.
|
||||
|
||||
21 October 2022: George
|
||||
- Merge #767 from jonathangray: consistently use IPv4/IPv6 in
|
||||
unbound.conf.5.
|
||||
@@ -4364,7 +4899,7 @@
|
||||
- Fix that with openssl 1.1 control-use-cert: no uses less cpu, by
|
||||
using no encryption over the unix socket.
|
||||
|
||||
22 Novenber 2016: Ralph
|
||||
22 November 2016: Ralph
|
||||
- Make access-control-tag-data RDATA absolute. This makes the RDATA
|
||||
origin consistent between local-data and access-control-tag-data.
|
||||
- Fix NSEC ENT wildcard check. Matching wildcard does not have to be a
|
||||
|
||||
@@ -28,3 +28,23 @@ prefix. For example:
|
||||
;; ANSWER SECTION:
|
||||
jazz-v4.viagenie.ca. 86400 IN AAAA 64:ff9b::ce7b:1f02
|
||||
|
||||
|
||||
NAT64 support was added by David Lamparter in 2022; license(s) of the
|
||||
surrounding code apply. Note that NAT64 is closely related but functionally
|
||||
orthogonal to DNS64; it allows Unbound to send outgoing queries to IPv4-only
|
||||
servers over IPv6 through the configured NAT64 prefix. This allows running
|
||||
an Unbound instance on an IPv6-only host without breaking every single domain
|
||||
that only has IPv4 servers. Whether that Unbound instance also does DNS64 is
|
||||
an independent choice.
|
||||
|
||||
To enable NAT64 in Unbound, add to unbound.conf's "server" section:
|
||||
|
||||
do-nat64: yes
|
||||
|
||||
The NAT64 prefix defaults to the DNS64 prefix, which in turn defaults to the
|
||||
standard 64:FF9B::/96 prefix. You can reconfigure it with:
|
||||
|
||||
nat64-prefix: 64:FF9B::/96
|
||||
|
||||
To test NAT64 operation, pick a domain that only has IPv4 reachability for its
|
||||
nameservers and try resolving any names in that domain.
|
||||
|
||||
+52
-3
@@ -35,9 +35,14 @@ server:
|
||||
# statistics-cumulative: no
|
||||
|
||||
# enable extended statistics (query types, answer codes, status)
|
||||
# printed from unbound-control. default off, because of speed.
|
||||
# printed from unbound-control. Default off, because of speed.
|
||||
# extended-statistics: no
|
||||
|
||||
# Inhibits selected extended statistics (qtype, qclass, qopcode, rcode,
|
||||
# rpz-actions) from printing if their value is 0.
|
||||
# Default on.
|
||||
# statistics-inhibit-zero: yes
|
||||
|
||||
# number of threads to create. 1 disables threading.
|
||||
# num-threads: 1
|
||||
|
||||
@@ -138,8 +143,8 @@ server:
|
||||
# edns-buffer-size: 1232
|
||||
|
||||
# Maximum UDP response size (not applied to TCP response).
|
||||
# Suggested values are 512 to 4096. Default is 4096. 65536 disables it.
|
||||
# max-udp-size: 4096
|
||||
# Suggested values are 512 to 4096. Default is 1232. 65536 disables it.
|
||||
# max-udp-size: 1232
|
||||
|
||||
# max memory to use for stream(tcp and tls) waiting result buffers.
|
||||
# stream-wait-size: 4m
|
||||
@@ -173,6 +178,15 @@ server:
|
||||
# a throwaway response (also timeouts) is received.
|
||||
# outbound-msg-retry: 5
|
||||
|
||||
# Hard limit on the number of outgoing queries Unbound will make while
|
||||
# resolving a name, making sure large NS sets do not loop.
|
||||
# It resets on query restarts (e.g., CNAME) and referrals.
|
||||
# max-sent-count: 32
|
||||
|
||||
# Hard limit on the number of times Unbound is allowed to restart a
|
||||
# query upon encountering a CNAME record.
|
||||
# max-query-restarts: 11
|
||||
|
||||
# msec for waiting for an unknown server to reply. Increase if you
|
||||
# are behind a slow satellite link, to eg. 1128.
|
||||
# unknown-server-time-limit: 376
|
||||
@@ -229,6 +243,18 @@ server:
|
||||
# Enable IPv6, "yes" or "no".
|
||||
# do-ip6: yes
|
||||
|
||||
# If running unbound on an IPv6-only host, domains that only have
|
||||
# IPv4 servers would become unresolveable. If NAT64 is available in
|
||||
# the network, unbound can use NAT64 to reach these servers with
|
||||
# the following option. This is NOT needed for enabling DNS64 on a
|
||||
# system that has IPv4 connectivity.
|
||||
# Consider also enabling prefer-ip6 to prefer native IPv6 connections
|
||||
# to nameservers.
|
||||
# do-nat64: no
|
||||
|
||||
# NAT64 prefix. Defaults to using dns64-prefix value.
|
||||
# nat64-prefix: 64:ff9b::0/96
|
||||
|
||||
# Enable UDP, "yes" or "no".
|
||||
# do-udp: yes
|
||||
|
||||
@@ -260,6 +286,10 @@ server:
|
||||
# Timeout for EDNS TCP keepalive, in msec.
|
||||
# edns-tcp-keepalive-timeout: 120000
|
||||
|
||||
# UDP queries that have waited in the socket buffer for a long time
|
||||
# can be dropped. Default is 0, disabled. In seconds, such as 3.
|
||||
# sock-queue-timeout: 0
|
||||
|
||||
# Use systemd socket activation for UDP, TCP, and control sockets.
|
||||
# use-systemd: no
|
||||
|
||||
@@ -489,6 +519,10 @@ server:
|
||||
# to validate the zone.
|
||||
# harden-algo-downgrade: no
|
||||
|
||||
# Harden against unknown records in the authority section and the
|
||||
# additional section.
|
||||
# harden-unknown-additional: no
|
||||
|
||||
# Sent minimum amount of information to upstream servers to enhance
|
||||
# privacy. Only sent minimum required labels of the QNAME and set QTYPE
|
||||
# to A when possible.
|
||||
@@ -649,6 +683,11 @@ server:
|
||||
# that set CD but cannot validate themselves.
|
||||
# ignore-cd-flag: no
|
||||
|
||||
# Disable the DO flag in outgoing requests. It is helpful for upstream
|
||||
# devices that cannot handle DNSSEC information. But do not enable it
|
||||
# otherwise, because it would stop DNSSEC validation.
|
||||
# disable-edns-do: no
|
||||
|
||||
# Serve expired responses from cache, with serve-expired-reply-ttl in
|
||||
# the response, and then attempt to fetch the data afresh.
|
||||
# serve-expired: no
|
||||
@@ -796,6 +835,8 @@ server:
|
||||
# o always_transparent, always_refuse, always_nxdomain, always_nodata,
|
||||
# always_deny resolve in that way but ignore local data for
|
||||
# that name
|
||||
# o block_a resolves all records normally but returns
|
||||
# NODATA for A queries and ignores local data for that name
|
||||
# o always_null returns 0.0.0.0 or ::0 for any name in the zone.
|
||||
# o noview breaks out of that view towards global local-zones.
|
||||
#
|
||||
@@ -1185,6 +1226,8 @@ remote-control:
|
||||
# backend: "testframe"
|
||||
# # secret seed string to calculate hashed keys
|
||||
# secret-seed: "default"
|
||||
# # if the backend should be read from, but not written to.
|
||||
# cachedb-no-store: no
|
||||
#
|
||||
# # For "redis" backend:
|
||||
# # (to enable, use --with-libhiredis to configure before compiling)
|
||||
@@ -1192,10 +1235,16 @@ remote-control:
|
||||
# redis-server-host: 127.0.0.1
|
||||
# # redis server's TCP port
|
||||
# redis-server-port: 6379
|
||||
# # if the server uses a unix socket, set its path, or "" when not used.
|
||||
# # redis-server-path: "/var/lib/redis/redis-server.sock"
|
||||
# # if the server uses an AUTH password, specify here, or "" when not used.
|
||||
# # redis-server-password: ""
|
||||
# # timeout (in ms) for communication with the redis server
|
||||
# redis-timeout: 100
|
||||
# # set timeout on redis records based on DNS response TTL
|
||||
# redis-expire-records: no
|
||||
# # redis logical database to use, 0 is the default database.
|
||||
# redis-logical-db: 0
|
||||
|
||||
# IPSet
|
||||
# Add specify domain into set via ipset.
|
||||
|
||||
@@ -54,6 +54,12 @@ Stop the server. The server daemon exits.
|
||||
.B reload
|
||||
Reload the server. This flushes the cache and reads the config file fresh.
|
||||
.TP
|
||||
.B reload_keep_cache
|
||||
Reload the server but try to keep the RRset and message cache if
|
||||
(re)configuration allows for it.
|
||||
That means the caches sizes and the number of threads must not change between
|
||||
reloads.
|
||||
.TP
|
||||
.B verbosity \fInumber
|
||||
Change verbosity value for logging. Same values as \fBverbosity\fR keyword in
|
||||
\fIunbound.conf\fR(5). This new setting lasts until the server is issued
|
||||
@@ -130,7 +136,7 @@ name specified.
|
||||
.TP
|
||||
.B flush \fIname
|
||||
Remove the name from the cache. Removes the types
|
||||
A, AAAA, NS, SOA, CNAME, DNAME, MX, PTR, SRV and NAPTR.
|
||||
A, AAAA, NS, SOA, CNAME, DNAME, MX, PTR, SRV, NAPTR, SVCB and HTTPS.
|
||||
Because that is fast to do. Other record types can be removed using
|
||||
.B flush_type
|
||||
or
|
||||
@@ -363,6 +369,15 @@ number of queries received by thread
|
||||
.I threadX.num.queries_ip_ratelimited
|
||||
number of queries rate limited by thread
|
||||
.TP
|
||||
.I threadX.num.queries_cookie_valid
|
||||
number of queries with a valid DNS Cookie by thread
|
||||
.TP
|
||||
.I threadX.num.queries_cookie_client
|
||||
number of queries with a client part only DNS Cookie by thread
|
||||
.TP
|
||||
.I threadX.num.queries_cookie_invalid
|
||||
number of queries with an invalid DNS Cookie by thread
|
||||
.TP
|
||||
.I threadX.num.cachehits
|
||||
number of queries that were successfully answered using a cache lookup
|
||||
.TP
|
||||
@@ -392,6 +407,14 @@ as a cache response was sent.
|
||||
.I threadX.num.expired
|
||||
number of replies that served an expired cache entry.
|
||||
.TP
|
||||
.I threadX.num.queries_timed_out
|
||||
number of queries that are dropped because they waited in the UDP socket buffer
|
||||
for too long.
|
||||
.TP
|
||||
.I threadX.query.queue_time_us.max
|
||||
The maximum wait time for packets in the socket buffer, in microseconds. This
|
||||
is only reported when sock-queue-timeout is enabled.
|
||||
.TP
|
||||
.I threadX.num.recursivereplies
|
||||
The number of replies sent to queries that needed recursive processing. Could be smaller than threadX.num.cachemiss if due to timeouts no replies were sent for some queries.
|
||||
.TP
|
||||
@@ -432,6 +455,18 @@ buffers are full.
|
||||
.I total.num.queries
|
||||
summed over threads.
|
||||
.TP
|
||||
.I total.num.queries_ip_ratelimited
|
||||
summed over threads.
|
||||
.TP
|
||||
.I total.num.queries_cookie_valid
|
||||
summed over threads.
|
||||
.TP
|
||||
.I total.num.queries_cookie_client
|
||||
summed over threads.
|
||||
.TP
|
||||
.I total.num.queries_cookie_invalid
|
||||
summed over threads.
|
||||
.TP
|
||||
.I total.num.cachehits
|
||||
summed over threads.
|
||||
.TP
|
||||
@@ -456,6 +491,12 @@ summed over threads.
|
||||
.I total.num.expired
|
||||
summed over threads.
|
||||
.TP
|
||||
.I total.num.queries_timed_out
|
||||
summed over threads.
|
||||
.TP
|
||||
.I total.query.queue_time_us.max
|
||||
the maximum of the thread values.
|
||||
.TP
|
||||
.I total.num.recursivereplies
|
||||
summed over threads.
|
||||
.TP
|
||||
@@ -591,7 +632,7 @@ ratelimiting.
|
||||
.TP
|
||||
.I num.query.dnscrypt.shared_secret.cachemiss
|
||||
The number of dnscrypt queries that did not find a shared secret in the cache.
|
||||
The can be use to compute the shared secret hitrate.
|
||||
This can be used to compute the shared secret hitrate.
|
||||
.TP
|
||||
.I num.query.dnscrypt.replay
|
||||
The number of dnscrypt queries that found a nonce hit in the nonce cache and
|
||||
@@ -647,6 +688,18 @@ timing and protocol support information.
|
||||
The number of items in the key cache. These are DNSSEC keys, one item
|
||||
per delegation point, and their validation status.
|
||||
.TP
|
||||
.I msg.cache.max_collisions
|
||||
The maximum number of hash table collisions in the msg cache. This is the
|
||||
number of hashes that are identical when a new element is inserted in the
|
||||
hash table. If the value is very large, like hundreds, something is wrong
|
||||
with the performance of the hash table, hash values are incorrect or malicious.
|
||||
.TP
|
||||
.I rrset.cache.max_collisions
|
||||
The maximum number of hash table collisions in the rrset cache. This is the
|
||||
number of hashes that are identical when a new element is inserted in the
|
||||
hash table. If the value is very large, like hundreds, something is wrong
|
||||
with the performance of the hash table, hash values are incorrect or malicious.
|
||||
.TP
|
||||
.I dnscrypt_shared_secret.cache.count
|
||||
The number of items in the shared secret cache. These are precomputed shared
|
||||
secrets for a given client public key/server secret key pair. Shared secrets
|
||||
@@ -686,7 +739,12 @@ Number of queries that got an answer that contained EDNS client subnet data.
|
||||
.I num.query.subnet_cache
|
||||
Number of queries answered from the edns client subnet cache. These are
|
||||
counted as cachemiss by the main counters, but hit the client subnet
|
||||
specific cache, after getting processed by the edns client subnet module.
|
||||
specific cache after getting processed by the edns client subnet module.
|
||||
.TP
|
||||
.I num.query.cachedb
|
||||
Number of queries answered from the external cache of cachedb.
|
||||
These are counted as cachemiss by the main counters, but hit the cachedb
|
||||
external cache after getting processed by the cachedb module.
|
||||
.TP
|
||||
.I num.rpz.action.<rpz_action>
|
||||
Number of queries answered using configured RPZ policy, per RPZ action type.
|
||||
|
||||
+183
-20
@@ -112,6 +112,14 @@ If enabled, extended statistics are printed from \fIunbound\-control\fR(8).
|
||||
Default is off, because keeping track of more statistics takes time. The
|
||||
counters are listed in \fIunbound\-control\fR(8).
|
||||
.TP
|
||||
.B statistics\-inhibit\-zero: \fI<yes or no>
|
||||
If enabled, selected extended statistics with a value of 0 are inhibited from
|
||||
printing with \fIunbound\-control\fR(8).
|
||||
These are query types, query classes, query opcodes, answer rcodes
|
||||
(except NOERROR, FORMERR, SERVFAIL, NXDOMAIN, NOTIMPL, REFUSED) and
|
||||
RPZ actions.
|
||||
Default is on.
|
||||
.TP
|
||||
.B num\-threads: \fI<number>
|
||||
The number of threads to create to serve clients. Use 1 for no threading.
|
||||
.TP
|
||||
@@ -225,7 +233,8 @@ number).
|
||||
.B max\-udp\-size: \fI<number>
|
||||
Maximum UDP response size (not applied to TCP response). 65536 disables the
|
||||
udp response size maximum, and uses the choice from the client, always.
|
||||
Suggested values are 512 to 4096. Default is 4096.
|
||||
Suggested values are 512 to 4096. Default is 1232. The default value is the
|
||||
same as the default for edns\-buffer\-size.
|
||||
.TP
|
||||
.B stream\-wait\-size: \fI<number>
|
||||
Number of bytes size maximum to use for waiting stream buffers. Default is
|
||||
@@ -496,6 +505,14 @@ configured, and finally to 0 if the number of free buffers falls below
|
||||
A minimum actual timeout of 200 milliseconds is observed regardless of the
|
||||
advertised timeout.
|
||||
.TP
|
||||
.B sock\-queue\-timeout: \fI<sec>\fR
|
||||
UDP queries that have waited in the socket buffer for a long time can be
|
||||
dropped. Default is 0, disabled. The time is set in seconds, 3 could be a
|
||||
good value to ignore old queries that likely the client does not need a reply
|
||||
for any more. This could happen if the host has not been able to service
|
||||
the queries for a while, i.e. Unbound is not running, and then is enabled
|
||||
again. It uses timestamp socket options.
|
||||
.TP
|
||||
.B tcp\-upstream: \fI<yes or no>
|
||||
Enable or disable whether the upstream queries use TCP only for transport.
|
||||
Default is no. Useful in tunneling scenarios. If set to no you can specify
|
||||
@@ -684,17 +701,17 @@ This option is experimental at this time.
|
||||
.B access\-control: \fI<IP netblock> <action>
|
||||
The netblock is given as an IP4 or IP6 address with /size appended for a
|
||||
classless network block. The action can be \fIdeny\fR, \fIrefuse\fR,
|
||||
\fIallow\fR, \fIallow_setrd\fR, \fIallow_snoop\fR, \fIdeny_non_local\fR or
|
||||
\fIrefuse_non_local\fR.
|
||||
\fIallow\fR, \fIallow_setrd\fR, \fIallow_snoop\fR, \fIallow_cookie\fR,
|
||||
\fIdeny_non_local\fR or \fIrefuse_non_local\fR.
|
||||
The most specific netblock match is used, if none match \fIrefuse\fR is used.
|
||||
The order of the access\-control statements therefore does not matter.
|
||||
.IP
|
||||
The action \fIdeny\fR stops queries from hosts from that netblock.
|
||||
The \fIdeny\fR action stops queries from hosts from that netblock.
|
||||
.IP
|
||||
The action \fIrefuse\fR stops queries too, but sends a DNS rcode REFUSED
|
||||
The \fIrefuse\fR action stops queries too, but sends a DNS rcode REFUSED
|
||||
error message back.
|
||||
.IP
|
||||
The action \fIallow\fR gives access to clients from that netblock.
|
||||
The \fIallow\fR action gives access to clients from that netblock.
|
||||
It gives only access for recursion clients (which is
|
||||
what almost all clients need). Nonrecursive queries are refused.
|
||||
.IP
|
||||
@@ -714,13 +731,27 @@ may be useful if another DNS server must forward requests for specific
|
||||
zones to a resolver DNS server, but only supports stub domains and
|
||||
sends queries to the resolver DNS server with the RD bit cleared.
|
||||
.IP
|
||||
The action \fIallow_snoop\fR gives nonrecursive access too. This give
|
||||
The \fIallow_snoop\fR action gives nonrecursive access too. This give
|
||||
both recursive and non recursive access. The name \fIallow_snoop\fR refers
|
||||
to cache snooping, a technique to use nonrecursive queries to examine
|
||||
the cache contents (for malicious acts). However, nonrecursive queries can
|
||||
also be a valuable debugging tool (when you want to examine the cache
|
||||
contents). In that case use \fIallow_snoop\fR for your administration host.
|
||||
.IP
|
||||
The \fIallow_cookie\fR action allows access to UDP queries that contain a
|
||||
valid DNS Cookie as specified in RFC 7873 and RFC 9018, when the
|
||||
\fBanswer\-cookie\fR option is enabled.
|
||||
UDP queries containing only a DNS Client Cookie and no Server Cookie, or an
|
||||
invalid DNS Cookie, will receive a BADCOOKIE response including a newly
|
||||
generated DNS Cookie, allowing clients to retry with that DNS Cookie.
|
||||
The \fIallow_cookie\fR action will also accept requests over stateful
|
||||
transports, regardless of the presence of an DNS Cookie and regardless of the
|
||||
\fBanswer\-cookie\fR setting.
|
||||
If \fBip\-ratelimit\fR is used, clients with a valid DNS Cookie will bypass the
|
||||
ratelimit.
|
||||
If a ratelimit for such clients is still needed, \fBip\-ratelimit\-cookie\fR
|
||||
can be used instead.
|
||||
.IP
|
||||
By default only localhost is \fIallow\fRed, the rest is \fIrefuse\fRd.
|
||||
The default is \fIrefuse\fRd, because that is protocol\-friendly. The DNS
|
||||
protocol is not designed to handle dropped packets due to policy, and
|
||||
@@ -1011,6 +1042,12 @@ validate the zone. Default is no. Zone signers must produce zones
|
||||
that allow this feature to work, but sometimes they do not, and turning
|
||||
this option off avoids that validation failure.
|
||||
.TP
|
||||
.B harden\-unknown\-additional: \fI<yes or no>
|
||||
Harden against unknown records in the authority section and additional
|
||||
section. Default is no. If no, such records are copied from the upstream
|
||||
and presented to the client together with the answer. If yes, it could
|
||||
hamper future protocol developments that want to add records.
|
||||
.TP
|
||||
.B use\-caps\-for\-id: \fI<yes or no>
|
||||
Use 0x20\-encoded random bits in the query to foil spoof attempts.
|
||||
This perturbs the lowercase and uppercase of query names sent to
|
||||
@@ -1265,6 +1302,20 @@ servers that set the CD flag but cannot validate DNSSEC themselves are
|
||||
the clients, and then Unbound provides them with DNSSEC protection.
|
||||
The default value is "no".
|
||||
.TP
|
||||
.B disable\-edns\-do: \fI<yes or no>
|
||||
Disable the EDNS DO flag in upstream requests.
|
||||
It breaks DNSSEC validation for Unbound's clients.
|
||||
This results in the upstream name servers to not include DNSSEC records in
|
||||
their replies and could be helpful for devices that cannot handle DNSSEC
|
||||
information.
|
||||
When the option is enabled, clients that set the DO flag receive no EDNS
|
||||
record in the response to indicate the lack of support to them.
|
||||
If this option is enabled but Unbound is already configured for DNSSEC
|
||||
validation (i.e., the validator module is enabled; default) this option is
|
||||
implicitly turned off with a warning as to not break DNSSEC validation in
|
||||
Unbound.
|
||||
Default is no.
|
||||
.TP
|
||||
.B serve\-expired: \fI<yes or no>
|
||||
If enabled, Unbound attempts to serve old responses from cache with a
|
||||
TTL of \fBserve\-expired\-reply\-ttl\fR in the response without waiting for the
|
||||
@@ -1383,10 +1434,10 @@ address space are not validated. This is usually required whenever
|
||||
Configure a local zone. The type determines the answer to give if
|
||||
there is no match from local\-data. The types are deny, refuse, static,
|
||||
transparent, redirect, nodefault, typetransparent, inform, inform_deny,
|
||||
inform_redirect, always_transparent, always_refuse, always_nxdomain, always_null, noview,
|
||||
and are explained below. After that the default settings are listed. Use
|
||||
local\-data: to enter data into the local zone. Answers for local zones
|
||||
are authoritative DNS answers. By default the zones are class IN.
|
||||
inform_redirect, always_transparent, block_a, always_refuse, always_nxdomain,
|
||||
always_null, noview, and are explained below. After that the default settings
|
||||
are listed. Use local\-data: to enter data into the local zone. Answers for
|
||||
local zones are authoritative DNS answers. By default the zones are class IN.
|
||||
.IP
|
||||
If you need more complicated authoritative data, with referrals, wildcards,
|
||||
CNAME/DNAME support, or DNSSEC authoritative service, setup a stub\-zone for
|
||||
@@ -1461,6 +1512,12 @@ Ie. answer queries with fixed data and also log the machines that ask.
|
||||
\h'5'\fIalways_transparent\fR
|
||||
Like transparent, but ignores local data and resolves normally.
|
||||
.TP 10
|
||||
\h'5'\fIblock_a\fR
|
||||
Like transparent, but ignores local data and resolves normally all query
|
||||
types excluding A. For A queries it unconditionally returns NODATA.
|
||||
Useful in cases when there is a need to explicitly force all apps to use
|
||||
IPv6 protocol and avoid any queries to IPv4.
|
||||
.TP 10
|
||||
\h'5'\fIalways_refuse\fR
|
||||
Like refuse, but ignores local data and refuses the query.
|
||||
.TP 10
|
||||
@@ -1777,11 +1834,27 @@ A value of 0 will disable ratelimiting for domain names that end in this name.
|
||||
.TP 5
|
||||
.B ip\-ratelimit: \fI<number or 0>
|
||||
Enable global ratelimiting of queries accepted per IP address.
|
||||
If 0, the default, it is disabled. This option is experimental at this time.
|
||||
This option is experimental at this time.
|
||||
The ratelimit is in queries per second that are allowed. More queries are
|
||||
completely dropped and will not receive a reply, SERVFAIL or otherwise.
|
||||
IP ratelimiting happens before looking in the cache. This may be useful for
|
||||
mitigating amplification attacks.
|
||||
Default is 0 (disabled).
|
||||
.TP 5
|
||||
.B ip\-ratelimit\-cookie: \fI<number or 0>
|
||||
Enable global ratelimiting of queries accepted per IP address with a valid DNS
|
||||
Cookie.
|
||||
This option is experimental at this time.
|
||||
The ratelimit is in queries per second that are allowed.
|
||||
More queries are completely dropped and will not receive a reply, SERVFAIL or
|
||||
otherwise.
|
||||
IP ratelimiting happens before looking in the cache.
|
||||
This option could be useful in combination with \fIallow_cookie\fR in an
|
||||
attempt to mitigate other amplification attacks than UDP reflections (e.g.,
|
||||
attacks targeting Unbound itself) which are already handled with DNS Cookies.
|
||||
If used, the value is suggested to be higher than \fBip\-ratelimit\fR e.g.,
|
||||
tenfold.
|
||||
Default is 0 (disabled).
|
||||
.TP 5
|
||||
.B ip\-ratelimit\-size: \fI<memory size>
|
||||
Give the size of the data structure in which the current ongoing rates are
|
||||
@@ -1820,6 +1893,21 @@ If a forward/stub zone is used, this is the number of retries per nameserver in
|
||||
the zone.
|
||||
Default is 5.
|
||||
.TP 5
|
||||
.B max\-sent\-count: \fI<number>
|
||||
Hard limit on the number of outgoing queries Unbound will make while resolving
|
||||
a name, making sure large NS sets do not loop.
|
||||
Results in SERVFAIL when reached.
|
||||
It resets on query restarts (e.g., CNAME) and referrals.
|
||||
Default is 32.
|
||||
.TP 5
|
||||
.B max\-query\-restarts: \fI<number>
|
||||
Hard limit on the number of times Unbound is allowed to restart a query upon
|
||||
encountering a CNAME record.
|
||||
Results in SERVFAIL when reached.
|
||||
Changing this value needs caution as it can allow long CNAME chains to be
|
||||
accepted, where Unbound needs to verify (resolve) each link individually.
|
||||
Default is 11.
|
||||
.TP 5
|
||||
.B fast\-server\-permil: \fI<number>
|
||||
Specify how many times out of 1000 to pick from the set of fastest servers.
|
||||
0 turns the feature off. A value of 900 would pick from the fastest
|
||||
@@ -1835,6 +1923,18 @@ Set the number of servers that should be used for fast server selection. Only
|
||||
use the fastest specified number of servers with the fast\-server\-permil
|
||||
option, that turns this on or off. The default is to use the fastest 3 servers.
|
||||
.TP 5
|
||||
.B answer\-cookie: \fI<yes or no>
|
||||
If enabled, Unbound will answer to requests containing DNS Cookies as
|
||||
specified in RFC 7873 and RFC 9018.
|
||||
Default is no.
|
||||
.TP 5
|
||||
.B cookie\-secret: \fI<128 bit hex string>
|
||||
Server's secret for DNS Cookie generation.
|
||||
Useful to explicitly set for servers in an anycast deployment that need to
|
||||
share the secret in order to verify each other's Server Cookies.
|
||||
An example hex string would be "000102030405060708090a0b0c0d0e0f".
|
||||
Default is a 128 bits random secret generated at startup time.
|
||||
.TP 5
|
||||
.B edns\-client\-string: \fI<IP netblock> <string>
|
||||
Include an EDNS0 option containing configured ascii string in queries with
|
||||
destination address matching the configured IP netblock. This configuration
|
||||
@@ -1853,7 +1953,7 @@ errors. Default is "no".
|
||||
When the \fBval-log-level\fR option is also set to \fB2\fR, responses with
|
||||
Extended DNS Errors concerning DNSSEC failures that are not served from cache,
|
||||
will also contain a descriptive text message about the reason for the failure.
|
||||
.TP
|
||||
.TP 5
|
||||
.B ede\-serve\-expired: \fI<yes or no>
|
||||
If enabled, Unbound will attach an Extended DNS Error (RFC8914) Code 3 - Stale
|
||||
Answer as EDNS0 option to the expired response. Note that this will not attach
|
||||
@@ -2068,13 +2168,32 @@ useful when you want immediate changes to be visible.
|
||||
Authority zones are configured with \fBauth\-zone:\fR, and each one must
|
||||
have a \fBname:\fR. There can be multiple ones, by listing multiple auth\-zone clauses, each with a different name, pertaining to that part of the namespace.
|
||||
The authority zone with the name closest to the name looked up is used.
|
||||
Authority zones are processed after \fBlocal\-zones\fR and before
|
||||
cache (\fBfor\-downstream:\fR \fIyes\fR), and when used in this manner
|
||||
make Unbound respond like an authority server. Authority zones are also
|
||||
processed after cache, just before going to the network to fetch
|
||||
information for recursion (\fBfor\-upstream:\fR \fIyes\fR), and when used
|
||||
in this manner provide a local copy of an authority server that speeds up
|
||||
lookups of that data.
|
||||
Authority zones can be processed on two distinct, non-exclusive, configurable
|
||||
stages.
|
||||
.LP
|
||||
With \fBfor\-downstream:\fR \fIyes\fR (default), authority zones are processed
|
||||
after \fBlocal\-zones\fR and before cache.
|
||||
When used in this manner, Unbound responds like an authority server with no
|
||||
further processing other than returning an answer from the zone contents.
|
||||
A notable example, in this case, is CNAME records which are returned verbatim
|
||||
to downstream clients without further resolution.
|
||||
.LP
|
||||
With \fBfor\-upstream:\fR \fIyes\fR (default), authority zones are processed
|
||||
after the cache lookup, just before going to the network to fetch
|
||||
information for recursion.
|
||||
When used in this manner they provide a local copy of an authority server
|
||||
that speeds up lookups for that data during resolving.
|
||||
.LP
|
||||
If both options are enabled (default), client queries for an authority zone are
|
||||
answered authoritatively from Unbound, while internal queries that require data
|
||||
from the authority zone consult the local zone data instead of going to the
|
||||
network.
|
||||
.LP
|
||||
An interesting configuration is \fBfor\-downstream:\fR \fIno\fR,
|
||||
\fBfor\-upstream:\fR \fIyes\fR that allows for hyperlocal behavior where both
|
||||
client and internal queries consult the local zone data while resolving.
|
||||
In this case, the aforementioned CNAME example will result in a thoroughly
|
||||
resolved answer.
|
||||
.LP
|
||||
Authority zones can be read from zonefile. And can be kept updated via
|
||||
AXFR and IXFR. After update the zonefile is rewritten. The update mechanism
|
||||
@@ -2268,6 +2387,21 @@ List domain for which the AAAA records are ignored and the A record is
|
||||
used by dns64 processing instead. Can be entered multiple times, list a
|
||||
new domain for which it applies, one per line. Applies also to names
|
||||
underneath the name given.
|
||||
.SS "NAT64 Operation"
|
||||
.LP
|
||||
NAT64 operation allows using a NAT64 prefix for outbound requests to IPv4-only
|
||||
servers. It is controlled by two options in the \fBserver:\fR section:
|
||||
.TP
|
||||
.B do\-nat64: \fI<yes or no>\fR
|
||||
Use NAT64 to reach IPv4-only servers.
|
||||
Consider also enabling \fBprefer\-ip6\fR to prefer native IPv6 connections to
|
||||
nameservers.
|
||||
Default no.
|
||||
.TP
|
||||
.B nat64\-prefix: \fI<IPv6 prefix>\fR
|
||||
Use a specific NAT64 prefix to reach IPv4-only servers. Defaults to using
|
||||
the prefix configured in \fBdns64\-prefix\fR, which in turn defaults to
|
||||
64:ff9b::/96. The prefix length must be one of /32, /40, /48, /56, /64 or /96.
|
||||
.SS "DNSCrypt Options"
|
||||
.LP
|
||||
The
|
||||
@@ -2358,6 +2492,9 @@ The maximum size of the ECS cache is controlled by 'msg-cache-size' in the
|
||||
configuration file. On top of that, for each query only 100 different subnets
|
||||
are allowed to be stored for each address family. Exceeding that number, older
|
||||
entries will be purged from cache.
|
||||
.LP
|
||||
This module does not interact with the \fBserve\-expired*\fR and
|
||||
\fBprefetch:\fR options.
|
||||
.TP
|
||||
.B send\-client\-subnet: \fI<IP address>\fR
|
||||
Send client source address to this authority. Append /num to indicate a
|
||||
@@ -2544,6 +2681,11 @@ operationally.
|
||||
If the backend database is shared by multiple Unbound instances,
|
||||
all instances must use the same secret seed.
|
||||
This option defaults to "default".
|
||||
.TP
|
||||
.B cachedb-no-store: \fI<yes or no>\fR
|
||||
If the backend should be read from, but not written to. This makes this
|
||||
instance not store dns messages in the backend. But if data is available it
|
||||
is retrieved. The default is no.
|
||||
.P
|
||||
The following
|
||||
.B cachedb
|
||||
@@ -2560,6 +2702,16 @@ This option defaults to "127.0.0.1".
|
||||
The TCP port number of the Redis server.
|
||||
This option defaults to 6379.
|
||||
.TP
|
||||
.B redis-server-path: \fI<unix socket path>\fR
|
||||
The unix socket path to connect to the redis server. Off by default, and it
|
||||
can be set to "" to turn this off. Unix sockets may have better throughput
|
||||
than the IP address option.
|
||||
.TP
|
||||
.B redis-server-password: \fI"<password>"\fR
|
||||
The Redis AUTH password to use for the redis server.
|
||||
Only relevant if Redis is configured for client password authorisation.
|
||||
Off by default, and it can be set to "" to turn this off.
|
||||
.TP
|
||||
.B redis-timeout: \fI<msec>\fR
|
||||
The period until when Unbound waits for a response from the Redis sever.
|
||||
If this timeout expires Unbound closes the connection, treats it as
|
||||
@@ -2574,6 +2726,17 @@ Unbound is configured with \fBserve-expired\fR and \fBserve-expired-ttl\fR is 0,
|
||||
this option is internally reverted to "no". Redis SETEX support is required
|
||||
for this option (Redis >= 2.0.0).
|
||||
This option defaults to no.
|
||||
.TP
|
||||
.B redis-logical-db: \fI<logical database index>
|
||||
The logical database in Redis to use.
|
||||
These are databases in the same Redis instance sharing the same configuration
|
||||
and persisted in the same RDB/AOF file.
|
||||
If unsure about using this option, Redis documentation
|
||||
(https://redis.io/commands/select/) suggests not to use a single Redis instance
|
||||
for multiple unrelated applications.
|
||||
The default database in Redis is 0 while other logical databases need to be
|
||||
explicitly SELECT'ed upon connecting.
|
||||
This option defaults to 0.
|
||||
.SS DNSTAP Logging Options
|
||||
DNSTAP support, when compiled in by using \fB\-\-enable\-dnstap\fR, is enabled
|
||||
in the \fBdnstap:\fR section.
|
||||
|
||||
@@ -75,6 +75,7 @@ int dynlibmod_init(struct module_env* env, int id) {
|
||||
struct config_strlist* cfg_item = env->cfg->dynlib_file;
|
||||
struct dynlibmod_env* de = (struct dynlibmod_env*)calloc(1, sizeof(struct dynlibmod_env));
|
||||
__DYNMOD dynamic_library;
|
||||
int i;
|
||||
if (!de)
|
||||
{
|
||||
log_err("dynlibmod[%d]: malloc failure", dynlib_mod_idx);
|
||||
@@ -84,7 +85,7 @@ int dynlibmod_init(struct module_env* env, int id) {
|
||||
env->modinfo[id] = (void*) de;
|
||||
|
||||
de->fname = NULL;
|
||||
for(int i = dynlib_mod_idx;
|
||||
for(i = dynlib_mod_idx;
|
||||
i != 0 && cfg_item != NULL;
|
||||
i--, cfg_item = cfg_item->next) {}
|
||||
|
||||
|
||||
+58
-10
@@ -156,6 +156,7 @@ int ecs_whitelist_check(struct query_info* qinfo,
|
||||
qstate->no_cache_store = 0;
|
||||
}
|
||||
|
||||
sq->subnet_sent_no_subnet = 0;
|
||||
if(sq->ecs_server_out.subnet_validdata && ((sq->subnet_downstream &&
|
||||
qstate->env->cfg->client_subnet_always_forward) ||
|
||||
ecs_is_whitelisted(sn_env->whitelist,
|
||||
@@ -166,6 +167,14 @@ int ecs_whitelist_check(struct query_info* qinfo,
|
||||
* set. */
|
||||
if(!edns_opt_list_find(qstate->edns_opts_back_out,
|
||||
qstate->env->cfg->client_subnet_opcode)) {
|
||||
/* if the client is not wanting an EDNS subnet option,
|
||||
* omit it and store that we omitted it but actually
|
||||
* are doing EDNS subnet to the server. */
|
||||
if(sq->ecs_server_out.subnet_source_mask == 0) {
|
||||
sq->subnet_sent_no_subnet = 1;
|
||||
sq->subnet_sent = 0;
|
||||
return 1;
|
||||
}
|
||||
subnet_ecs_opt_list_append(&sq->ecs_server_out,
|
||||
&qstate->edns_opts_back_out, qstate, region);
|
||||
}
|
||||
@@ -204,6 +213,17 @@ subnetmod_init(struct module_env *env, int id)
|
||||
}
|
||||
alloc_init(&sn_env->alloc, NULL, 0);
|
||||
env->modinfo[id] = (void*)sn_env;
|
||||
|
||||
/* Warn that serve-expired and prefetch do not work with the subnet
|
||||
* module cache. */
|
||||
if(env->cfg->serve_expired)
|
||||
log_warn(
|
||||
"subnetcache: serve-expired is set but not working "
|
||||
"for data originating from the subnet module cache.");
|
||||
if(env->cfg->prefetch)
|
||||
log_warn(
|
||||
"subnetcache: prefetch is set but not working "
|
||||
"for data originating from the subnet module cache.");
|
||||
/* Copy msg_cache settings */
|
||||
sn_env->subnet_msg_cache = slabhash_create(env->cfg->msg_cache_slabs,
|
||||
HASH_DEFAULT_STARTARRAY, env->cfg->msg_cache_size,
|
||||
@@ -341,7 +361,7 @@ update_cache(struct module_qstate *qstate, int 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,
|
||||
struct lruhash_entry* lru_entry = slabhash_lookup(subnet_msg_cache, h,
|
||||
&qstate->qinfo, 1);
|
||||
int need_to_insert = (lru_entry == NULL);
|
||||
if (!lru_entry) {
|
||||
@@ -385,7 +405,7 @@ update_cache(struct module_qstate *qstate, int id)
|
||||
log_err("subnetcache: cache insertion failed");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/* store RRsets */
|
||||
for(i=0; i<rep->rrset_count; i++) {
|
||||
rep->ref[i].key = rep->rrsets[i];
|
||||
@@ -410,7 +430,7 @@ update_cache(struct module_qstate *qstate, int id)
|
||||
|
||||
/** 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)
|
||||
lookup_and_reply(struct module_qstate *qstate, int id, struct subnet_qstate *sq, int prefetch)
|
||||
{
|
||||
struct lruhash_entry *e;
|
||||
struct module_env *env = qstate->env;
|
||||
@@ -462,6 +482,10 @@ lookup_and_reply(struct module_qstate *qstate, int id, struct subnet_qstate *sq)
|
||||
INET6_SIZE);
|
||||
sq->ecs_client_out.subnet_validdata = 1;
|
||||
}
|
||||
|
||||
if (prefetch && *qstate->env->now >= ((struct reply_info *)node->elem)->prefetch_ttl) {
|
||||
qstate->need_refetch = 1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -498,18 +522,18 @@ eval_response(struct module_qstate *qstate, int id, struct subnet_qstate *sq)
|
||||
* module_finished */
|
||||
return module_finished;
|
||||
}
|
||||
|
||||
|
||||
/* We have not asked for subnet data */
|
||||
if (!sq->subnet_sent) {
|
||||
if (!sq->subnet_sent && !sq->subnet_sent_no_subnet) {
|
||||
if (s_in->subnet_validdata)
|
||||
verbose(VERB_QUERY, "subnetcache: 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) {
|
||||
if (!s_in->subnet_validdata && !sq->subnet_sent_no_subnet) {
|
||||
/* The authority indicated no support for edns subnet. As a
|
||||
* consequence the answer ended up in the regular cache. It
|
||||
* is still useful to put it in the edns subnet cache for
|
||||
@@ -524,11 +548,23 @@ eval_response(struct module_qstate *qstate, int id, struct subnet_qstate *sq)
|
||||
cp_edns_bad_response(c_out, c_in);
|
||||
return module_finished;
|
||||
}
|
||||
|
||||
|
||||
/* Purposefully there was no sent subnet, and there is consequently
|
||||
* no subnet in the answer. If there was, use the subnet in the answer
|
||||
* anyway. But if there is not, treat it as a prefix 0 answer. */
|
||||
if(sq->subnet_sent_no_subnet && !s_in->subnet_validdata) {
|
||||
/* Fill in 0.0.0.0/0 scope 0, or ::0/0 scope 0, for caching. */
|
||||
s_in->subnet_addr_fam = s_out->subnet_addr_fam;
|
||||
s_in->subnet_source_mask = 0;
|
||||
s_in->subnet_scope_mask = 0;
|
||||
memset(s_in->subnet_addr, 0, INET6_SIZE);
|
||||
s_in->subnet_validdata = 1;
|
||||
}
|
||||
|
||||
/* 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 ||
|
||||
@@ -541,6 +577,7 @@ eval_response(struct module_qstate *qstate, int id, struct subnet_qstate *sq)
|
||||
(void)edns_opt_list_remove(&qstate->edns_opts_back_out,
|
||||
qstate->env->cfg->client_subnet_opcode);
|
||||
sq->subnet_sent = 0;
|
||||
sq->subnet_sent_no_subnet = 0;
|
||||
return module_restart_next;
|
||||
}
|
||||
|
||||
@@ -661,6 +698,7 @@ ecs_query_response(struct module_qstate* qstate, struct dns_msg* response,
|
||||
edns_opt_list_remove(&qstate->edns_opts_back_out,
|
||||
qstate->env->cfg->client_subnet_opcode);
|
||||
sq->subnet_sent = 0;
|
||||
sq->subnet_sent_no_subnet = 0;
|
||||
memset(&sq->ecs_server_out, 0, sizeof(sq->ecs_server_out));
|
||||
} else if (!sq->track_max_scope &&
|
||||
FLAGS_GET_RCODE(response->rep->flags) == LDNS_RCODE_NOERROR &&
|
||||
@@ -722,6 +760,9 @@ ecs_edns_back_parsed(struct module_qstate* qstate, int id,
|
||||
sq->ecs_server_in.subnet_scope_mask >
|
||||
sq->max_scope))
|
||||
sq->max_scope = sq->ecs_server_in.subnet_scope_mask;
|
||||
} else if(sq->subnet_sent_no_subnet) {
|
||||
/* The answer can be stored as scope 0, not in global cache. */
|
||||
qstate->no_cache_store = 1;
|
||||
}
|
||||
|
||||
return 1;
|
||||
@@ -768,6 +809,11 @@ subnetmod_operate(struct module_qstate *qstate, enum module_ev event,
|
||||
&qstate->mesh_info->reply_list->query_reply.client_addr,
|
||||
&sq->ecs_client_in, qstate->env->cfg);
|
||||
}
|
||||
else if(qstate->client_addr.ss_family != AF_UNSPEC) {
|
||||
subnet_option_from_ss(
|
||||
&qstate->client_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
|
||||
@@ -791,7 +837,9 @@ subnetmod_operate(struct module_qstate *qstate, enum module_ev event,
|
||||
|
||||
if(!sq->started_no_cache_lookup && !qstate->blacklist) {
|
||||
lock_rw_wrlock(&sne->biglock);
|
||||
if(lookup_and_reply(qstate, id, sq)) {
|
||||
if(qstate->mesh_info->reply_list &&
|
||||
lookup_and_reply(qstate, id, sq,
|
||||
qstate->env->cfg->prefetch)) {
|
||||
sne->num_msg_cache++;
|
||||
lock_rw_unlock(&sne->biglock);
|
||||
verbose(VERB_QUERY, "subnetcache: answered from cache");
|
||||
|
||||
@@ -85,6 +85,13 @@ struct subnet_qstate {
|
||||
struct ecs_data ecs_server_out;
|
||||
int subnet_downstream;
|
||||
int subnet_sent;
|
||||
/**
|
||||
* If there was no subnet sent because the client used source prefix
|
||||
* length 0 for omitting the information. Then the answer is cached
|
||||
* like subnet was a /0 scope. Like the subnet_sent flag, but when
|
||||
* the EDNS subnet option is omitted because the client asked.
|
||||
*/
|
||||
int subnet_sent_no_subnet;
|
||||
/** keep track of longest received scope, set after receiving CNAME for
|
||||
* incoming QNAME. */
|
||||
int track_max_scope;
|
||||
|
||||
+2
-2
@@ -158,10 +158,10 @@ ipset_check_zones_for_rrset(struct module_env *env, struct ipset_env *ie,
|
||||
qs = NULL;
|
||||
plen = strlen(p->str);
|
||||
|
||||
if (dlen >= plen) {
|
||||
if (dlen == plen || (dlen > plen && dname[dlen - plen - 1] == '.' )) {
|
||||
ds = dname + (dlen - plen);
|
||||
}
|
||||
if (qlen >= plen) {
|
||||
if (qlen == plen || (qlen > plen && qname[qlen - plen - 1] == '.' )) {
|
||||
qs = qname + (qlen - plen);
|
||||
}
|
||||
if ((ds && strncasecmp(p->str, ds, plen) == 0)
|
||||
|
||||
@@ -321,6 +321,45 @@ void delegpt_log(enum verbosity_value v, struct delegpt* dp)
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
delegpt_addr_on_result_list(struct delegpt* dp, struct delegpt_addr* find)
|
||||
{
|
||||
struct delegpt_addr* a = dp->result_list;
|
||||
while(a) {
|
||||
if(a == find)
|
||||
return 1;
|
||||
a = a->next_result;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
delegpt_usable_list_remove_addr(struct delegpt* dp, struct delegpt_addr* del)
|
||||
{
|
||||
struct delegpt_addr* usa = dp->usable_list, *prev = NULL;
|
||||
while(usa) {
|
||||
if(usa == del) {
|
||||
/* snip off the usable list */
|
||||
if(prev)
|
||||
prev->next_usable = usa->next_usable;
|
||||
else dp->usable_list = usa->next_usable;
|
||||
return;
|
||||
}
|
||||
prev = usa;
|
||||
usa = usa->next_usable;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
delegpt_add_to_result_list(struct delegpt* dp, struct delegpt_addr* a)
|
||||
{
|
||||
if(delegpt_addr_on_result_list(dp, a))
|
||||
return;
|
||||
delegpt_usable_list_remove_addr(dp, a);
|
||||
a->next_result = dp->result_list;
|
||||
dp->result_list = a;
|
||||
}
|
||||
|
||||
void
|
||||
delegpt_add_unused_targets(struct delegpt* dp)
|
||||
{
|
||||
|
||||
@@ -457,4 +457,29 @@ int delegpt_add_target_mlc(struct delegpt* dp, uint8_t* name, size_t namelen,
|
||||
/** get memory in use by dp */
|
||||
size_t delegpt_get_mem(struct delegpt* dp);
|
||||
|
||||
/**
|
||||
* See if the addr is on the result list.
|
||||
* @param dp: delegation point.
|
||||
* @param find: the pointer is searched for on the result list.
|
||||
* @return 1 if found, 0 if not found.
|
||||
*/
|
||||
int delegpt_addr_on_result_list(struct delegpt* dp, struct delegpt_addr* find);
|
||||
|
||||
/**
|
||||
* Remove the addr from the usable list.
|
||||
* @param dp: the delegation point.
|
||||
* @param del: the addr to remove from the list, the pointer is searched for.
|
||||
*/
|
||||
void delegpt_usable_list_remove_addr(struct delegpt* dp,
|
||||
struct delegpt_addr* del);
|
||||
|
||||
/**
|
||||
* Add the delegpt_addr back to the result list, if it is not already on
|
||||
* the result list. Also removes it from the usable list.
|
||||
* @param dp: delegation point.
|
||||
* @param a: addr to add, nothing happens if it is already on the result list.
|
||||
* It is removed from the usable list.
|
||||
*/
|
||||
void delegpt_add_to_result_list(struct delegpt* dp, struct delegpt_addr* a);
|
||||
|
||||
#endif /* ITERATOR_ITER_DELEGPT_H */
|
||||
|
||||
+2
-24
@@ -207,28 +207,6 @@ size_t priv_get_mem(struct iter_priv* priv)
|
||||
return sizeof(*priv) + regional_get_mem(priv->region);
|
||||
}
|
||||
|
||||
/** remove RR from msgparse RRset, return true if rrset is entirely bad */
|
||||
static int
|
||||
remove_rr(const char* str, sldns_buffer* pkt, struct rrset_parse* rrset,
|
||||
struct rr_parse* prev, struct rr_parse** rr, struct sockaddr_storage* addr, socklen_t addrlen)
|
||||
{
|
||||
if(verbosity >= VERB_QUERY && rrset->dname_len <= LDNS_MAX_DOMAINLEN && str) {
|
||||
uint8_t buf[LDNS_MAX_DOMAINLEN+1];
|
||||
dname_pkt_copy(pkt, buf, rrset->dname);
|
||||
log_name_addr(VERB_QUERY, str, buf, addr, addrlen);
|
||||
}
|
||||
if(prev)
|
||||
prev->next = (*rr)->next;
|
||||
else rrset->rr_first = (*rr)->next;
|
||||
if(rrset->rr_last == *rr)
|
||||
rrset->rr_last = prev;
|
||||
rrset->rr_count --;
|
||||
rrset->size -= (*rr)->size;
|
||||
/* rr struct still exists, but is unlinked, so that in the for loop
|
||||
* the rr->next works fine to continue. */
|
||||
return rrset->rr_count == 0;
|
||||
}
|
||||
|
||||
int priv_rrset_bad(struct iter_priv* priv, sldns_buffer* pkt,
|
||||
struct rrset_parse* rrset)
|
||||
{
|
||||
@@ -261,7 +239,7 @@ int priv_rrset_bad(struct iter_priv* priv, sldns_buffer* pkt,
|
||||
INET_SIZE);
|
||||
memmove(&addr, &sa, len);
|
||||
if(priv_lookup_addr(priv, &addr, len)) {
|
||||
if(remove_rr("sanitize: removing public name with private address", pkt, rrset, prev, &rr, &addr, len))
|
||||
if(msgparse_rrset_remove_rr("sanitize: removing public name with private address", pkt, rrset, prev, rr, &addr, len))
|
||||
return 1;
|
||||
continue;
|
||||
}
|
||||
@@ -284,7 +262,7 @@ int priv_rrset_bad(struct iter_priv* priv, sldns_buffer* pkt,
|
||||
INET6_SIZE);
|
||||
memmove(&addr, &sa, len);
|
||||
if(priv_lookup_addr(priv, &addr, len)) {
|
||||
if(remove_rr("sanitize: removing public name with private address", pkt, rrset, prev, &rr, &addr, len))
|
||||
if(msgparse_rrset_remove_rr("sanitize: removing public name with private address", pkt, rrset, prev, rr, &addr, len))
|
||||
return 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -42,6 +42,7 @@
|
||||
#include "config.h"
|
||||
#include "iterator/iter_resptype.h"
|
||||
#include "iterator/iter_delegpt.h"
|
||||
#include "iterator/iterator.h"
|
||||
#include "services/cache/dns.h"
|
||||
#include "util/net_help.h"
|
||||
#include "util/data/dname.h"
|
||||
@@ -105,7 +106,8 @@ response_type_from_cache(struct dns_msg* msg,
|
||||
|
||||
enum response_type
|
||||
response_type_from_server(int rdset,
|
||||
struct dns_msg* msg, struct query_info* request, struct delegpt* dp)
|
||||
struct dns_msg* msg, struct query_info* request, struct delegpt* dp,
|
||||
int* empty_nodata_found)
|
||||
{
|
||||
uint8_t* origzone = (uint8_t*)"\000"; /* the default */
|
||||
struct ub_packed_rrset_key* s;
|
||||
@@ -284,6 +286,22 @@ response_type_from_server(int rdset,
|
||||
|
||||
/* If we've gotten this far, this is NOERROR/NODATA (which could
|
||||
* be an entirely empty message) */
|
||||
/* For entirely empty messages, try again, at first, then accept
|
||||
* it it happens more. A regular noerror/nodata response has a soa
|
||||
* negative ttl value in the authority section. This makes it try
|
||||
* again at another authority. And decides between storing a 5 second
|
||||
* empty message or a 5 second servfail response. */
|
||||
if(msg->rep->an_numrrsets == 0 && msg->rep->ns_numrrsets == 0 &&
|
||||
msg->rep->ar_numrrsets == 0) {
|
||||
if(empty_nodata_found) {
|
||||
/* detect as throwaway at first, but accept later. */
|
||||
(*empty_nodata_found)++;
|
||||
if(*empty_nodata_found < EMPTY_NODATA_RETRY_COUNT)
|
||||
return RESPONSE_TYPE_THROWAWAY;
|
||||
return RESPONSE_TYPE_ANSWER;
|
||||
}
|
||||
return RESPONSE_TYPE_ANSWER;
|
||||
}
|
||||
/* check if recursive answer; saying it has empty cache */
|
||||
if( (msg->rep->flags&BIT_RA) && !(msg->rep->flags&BIT_AA) && !rdset)
|
||||
return RESPONSE_TYPE_REC_LAME;
|
||||
|
||||
@@ -119,9 +119,11 @@ enum response_type response_type_from_cache(struct dns_msg* msg,
|
||||
* @param request: the request that generated the response.
|
||||
* @param dp: The delegation point that was being queried
|
||||
* when the response was returned.
|
||||
* @param empty_nodata_found: flag to keep track of empty nodata detection.
|
||||
* @return the response type (CNAME or ANSWER).
|
||||
*/
|
||||
enum response_type response_type_from_server(int rdset,
|
||||
struct dns_msg* msg, struct query_info* request, struct delegpt* dp);
|
||||
struct dns_msg* msg, struct query_info* request, struct delegpt* dp,
|
||||
int* empty_nodata_found);
|
||||
|
||||
#endif /* ITERATOR_ITER_RESPTYPE_H */
|
||||
|
||||
+104
-6
@@ -346,6 +346,26 @@ soa_in_auth(struct msg_parse* msg)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Check if type is allowed in the authority section */
|
||||
static int
|
||||
type_allowed_in_authority_section(uint16_t tp)
|
||||
{
|
||||
if(tp == LDNS_RR_TYPE_SOA || tp == LDNS_RR_TYPE_NS ||
|
||||
tp == LDNS_RR_TYPE_DS || tp == LDNS_RR_TYPE_NSEC ||
|
||||
tp == LDNS_RR_TYPE_NSEC3)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Check if type is allowed in the additional section */
|
||||
static int
|
||||
type_allowed_in_additional_section(uint16_t tp)
|
||||
{
|
||||
if(tp == LDNS_RR_TYPE_A || tp == LDNS_RR_TYPE_AAAA)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* This routine normalizes a response. This includes removing "irrelevant"
|
||||
* records from the answer and additional sections and (re)synthesizing
|
||||
@@ -355,11 +375,13 @@ soa_in_auth(struct msg_parse* msg)
|
||||
* @param msg: msg to normalize.
|
||||
* @param qinfo: original query.
|
||||
* @param region: where to allocate synthesized CNAMEs.
|
||||
* @param env: module env with config options.
|
||||
* @return 0 on error.
|
||||
*/
|
||||
static int
|
||||
scrub_normalize(sldns_buffer* pkt, struct msg_parse* msg,
|
||||
struct query_info* qinfo, struct regional* region)
|
||||
struct query_info* qinfo, struct regional* region,
|
||||
struct module_env* env)
|
||||
{
|
||||
uint8_t* sname = qinfo->qname;
|
||||
size_t snamelen = qinfo->qname_len;
|
||||
@@ -511,6 +533,7 @@ scrub_normalize(sldns_buffer* pkt, struct msg_parse* msg,
|
||||
|
||||
/* Mark additional names from AUTHORITY */
|
||||
while(rrset && rrset->section == LDNS_SECTION_AUTHORITY) {
|
||||
/* protect internals of recursor by making sure to del these */
|
||||
if(rrset->type==LDNS_RR_TYPE_DNAME ||
|
||||
rrset->type==LDNS_RR_TYPE_CNAME ||
|
||||
rrset->type==LDNS_RR_TYPE_A ||
|
||||
@@ -519,6 +542,13 @@ scrub_normalize(sldns_buffer* pkt, struct msg_parse* msg,
|
||||
"RRset:", pkt, msg, prev, &rrset);
|
||||
continue;
|
||||
}
|
||||
/* Allowed list of types in the authority section */
|
||||
if(env->cfg->harden_unknown_additional &&
|
||||
!type_allowed_in_authority_section(rrset->type)) {
|
||||
remove_rrset("normalize: removing irrelevant "
|
||||
"RRset:", pkt, msg, prev, &rrset);
|
||||
continue;
|
||||
}
|
||||
/* only one NS set allowed in authority section */
|
||||
if(rrset->type==LDNS_RR_TYPE_NS) {
|
||||
/* NS set must be pertinent to the query */
|
||||
@@ -576,7 +606,6 @@ scrub_normalize(sldns_buffer* pkt, struct msg_parse* msg,
|
||||
* found in ANSWER and AUTHORITY. */
|
||||
/* These records have not been marked OK previously */
|
||||
while(rrset && rrset->section == LDNS_SECTION_ADDITIONAL) {
|
||||
/* FIXME: what about other types? */
|
||||
if(rrset->type==LDNS_RR_TYPE_A ||
|
||||
rrset->type==LDNS_RR_TYPE_AAAA)
|
||||
{
|
||||
@@ -589,6 +618,7 @@ scrub_normalize(sldns_buffer* pkt, struct msg_parse* msg,
|
||||
continue;
|
||||
}
|
||||
}
|
||||
/* protect internals of recursor by making sure to del these */
|
||||
if(rrset->type==LDNS_RR_TYPE_DNAME ||
|
||||
rrset->type==LDNS_RR_TYPE_CNAME ||
|
||||
rrset->type==LDNS_RR_TYPE_NS) {
|
||||
@@ -596,6 +626,13 @@ scrub_normalize(sldns_buffer* pkt, struct msg_parse* msg,
|
||||
"RRset:", pkt, msg, prev, &rrset);
|
||||
continue;
|
||||
}
|
||||
/* Allowed list of types in the additional section */
|
||||
if(env->cfg->harden_unknown_additional &&
|
||||
!type_allowed_in_additional_section(rrset->type)) {
|
||||
remove_rrset("normalize: removing irrelevant "
|
||||
"RRset:", pkt, msg, prev, &rrset);
|
||||
continue;
|
||||
}
|
||||
prev = rrset;
|
||||
rrset = rrset->rrset_all_next;
|
||||
}
|
||||
@@ -679,6 +716,56 @@ static int sanitize_nsec_is_overreach(sldns_buffer* pkt,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Remove individual RRs, if the length is wrong. Returns true if the RRset
|
||||
* has been removed. */
|
||||
static int
|
||||
scrub_sanitize_rr_length(sldns_buffer* pkt, struct msg_parse* msg,
|
||||
struct rrset_parse* prev, struct rrset_parse** rrset, int* added_ede,
|
||||
struct module_qstate* qstate)
|
||||
{
|
||||
struct rr_parse* rr, *rr_prev = NULL;
|
||||
for(rr = (*rrset)->rr_first; rr; rr = rr->next) {
|
||||
|
||||
/* Sanity check for length of records
|
||||
* An A record should be 6 bytes only
|
||||
* (2 bytes for length and 4 for IPv4 addr)*/
|
||||
if((*rrset)->type == LDNS_RR_TYPE_A && rr->size != 6 ) {
|
||||
if(!*added_ede) {
|
||||
*added_ede = 1;
|
||||
errinf_ede(qstate, "sanitize: records of inappropriate length have been removed.",
|
||||
LDNS_EDE_OTHER);
|
||||
}
|
||||
if(msgparse_rrset_remove_rr("sanitize: removing type A RR of inappropriate length:",
|
||||
pkt, *rrset, rr_prev, rr, NULL, 0)) {
|
||||
remove_rrset("sanitize: removing type A RRset of inappropriate length:",
|
||||
pkt, msg, prev, rrset);
|
||||
return 1;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Sanity check for length of records
|
||||
* An AAAA record should be 18 bytes only
|
||||
* (2 bytes for length and 16 for IPv6 addr)*/
|
||||
if((*rrset)->type == LDNS_RR_TYPE_AAAA && rr->size != 18 ) {
|
||||
if(!*added_ede) {
|
||||
*added_ede = 1;
|
||||
errinf_ede(qstate, "sanitize: records of inappropriate length have been removed.",
|
||||
LDNS_EDE_OTHER);
|
||||
}
|
||||
if(msgparse_rrset_remove_rr("sanitize: removing type AAAA RR of inappropriate length:",
|
||||
pkt, *rrset, rr_prev, rr, NULL, 0)) {
|
||||
remove_rrset("sanitize: removing type AAAA RRset of inappropriate length:",
|
||||
pkt, msg, prev, rrset);
|
||||
return 1;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
rr_prev = rr;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a response event, remove suspect RRsets from the response.
|
||||
* "Suspect" rrsets are potentially poison. Note that this routine expects
|
||||
@@ -691,15 +778,17 @@ static int sanitize_nsec_is_overreach(sldns_buffer* pkt,
|
||||
* @param zonename: name of server zone.
|
||||
* @param env: module environment with config and cache.
|
||||
* @param ie: iterator environment with private address data.
|
||||
* @param qstate: for setting errinf for EDE error messages.
|
||||
* @return 0 on error.
|
||||
*/
|
||||
static int
|
||||
scrub_sanitize(sldns_buffer* pkt, struct msg_parse* msg,
|
||||
struct query_info* qinfo, uint8_t* zonename, struct module_env* env,
|
||||
struct iter_env* ie)
|
||||
struct iter_env* ie, struct module_qstate* qstate)
|
||||
{
|
||||
int del_addi = 0; /* if additional-holding rrsets are deleted, we
|
||||
do not trust the normalized additional-A-AAAA any more */
|
||||
int added_rrlen_ede = 0;
|
||||
struct rrset_parse* rrset, *prev;
|
||||
prev = NULL;
|
||||
rrset = msg->rrset_first;
|
||||
@@ -744,6 +833,14 @@ scrub_sanitize(sldns_buffer* pkt, struct msg_parse* msg,
|
||||
rrset = msg->rrset_first;
|
||||
while(rrset) {
|
||||
|
||||
/* Sanity check for length of records */
|
||||
if(rrset->type == LDNS_RR_TYPE_A ||
|
||||
rrset->type == LDNS_RR_TYPE_AAAA) {
|
||||
if(scrub_sanitize_rr_length(pkt, msg, prev, &rrset,
|
||||
&added_rrlen_ede, qstate))
|
||||
continue;
|
||||
}
|
||||
|
||||
/* remove private addresses */
|
||||
if( (rrset->type == LDNS_RR_TYPE_A ||
|
||||
rrset->type == LDNS_RR_TYPE_AAAA)) {
|
||||
@@ -817,7 +914,8 @@ scrub_sanitize(sldns_buffer* pkt, struct msg_parse* msg,
|
||||
int
|
||||
scrub_message(sldns_buffer* pkt, struct msg_parse* msg,
|
||||
struct query_info* qinfo, uint8_t* zonename, struct regional* region,
|
||||
struct module_env* env, struct iter_env* ie)
|
||||
struct module_env* env, struct module_qstate* qstate,
|
||||
struct iter_env* ie)
|
||||
{
|
||||
/* basic sanity checks */
|
||||
log_nametypeclass(VERB_ALGO, "scrub for", zonename, LDNS_RR_TYPE_NS,
|
||||
@@ -846,10 +944,10 @@ scrub_message(sldns_buffer* pkt, struct msg_parse* msg,
|
||||
}
|
||||
|
||||
/* normalize the response, this cleans up the additional. */
|
||||
if(!scrub_normalize(pkt, msg, qinfo, region))
|
||||
if(!scrub_normalize(pkt, msg, qinfo, region, env))
|
||||
return 0;
|
||||
/* delete all out-of-zone information */
|
||||
if(!scrub_sanitize(pkt, msg, qinfo, zonename, env, ie))
|
||||
if(!scrub_sanitize(pkt, msg, qinfo, zonename, env, ie, qstate))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -48,6 +48,7 @@ struct query_info;
|
||||
struct regional;
|
||||
struct module_env;
|
||||
struct iter_env;
|
||||
struct module_qstate;
|
||||
|
||||
/**
|
||||
* Cleanup the passed dns message.
|
||||
@@ -59,11 +60,13 @@ struct iter_env;
|
||||
* Used to determine out of bailiwick information.
|
||||
* @param regional: where to allocate (new) parts of the message.
|
||||
* @param env: module environment with config settings and cache.
|
||||
* @param qstate: for setting errinf for EDE error messages.
|
||||
* @param ie: iterator module environment data.
|
||||
* @return: false if the message is total waste. true if scrubbed with success.
|
||||
*/
|
||||
int scrub_message(struct sldns_buffer* pkt, struct msg_parse* msg,
|
||||
struct query_info* qinfo, uint8_t* zonename, struct regional* regional,
|
||||
struct module_env* env, struct iter_env* ie);
|
||||
struct module_env* env, struct module_qstate* qstate,
|
||||
struct iter_env* ie);
|
||||
|
||||
#endif /* ITERATOR_ITER_SCRUB_H */
|
||||
|
||||
+41
-4
@@ -71,6 +71,11 @@
|
||||
/** time when nameserver glue is said to be 'recent' */
|
||||
#define SUSPICION_RECENT_EXPIRY 86400
|
||||
|
||||
/** if NAT64 is enabled and no NAT64 prefix is configured, first fall back to
|
||||
* DNS64 prefix. If that is not configured, fall back to this default value.
|
||||
*/
|
||||
static const char DEFAULT_NAT64_PREFIX[] = "64:ff9b::/96";
|
||||
|
||||
/** fillup fetch policy array */
|
||||
static void
|
||||
fetch_fill(struct iter_env* ie, const char* str)
|
||||
@@ -142,6 +147,7 @@ caps_white_apply_cfg(rbtree_type* ntree, struct config_file* cfg)
|
||||
int
|
||||
iter_apply_cfg(struct iter_env* iter_env, struct config_file* cfg)
|
||||
{
|
||||
const char *nat64_prefix;
|
||||
int i;
|
||||
/* target fetch policy */
|
||||
if(!read_fetch_policy(iter_env, cfg->target_fetch_policy))
|
||||
@@ -172,9 +178,35 @@ iter_apply_cfg(struct iter_env* iter_env, struct config_file* cfg)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
nat64_prefix = cfg->nat64_prefix;
|
||||
if(!nat64_prefix)
|
||||
nat64_prefix = cfg->dns64_prefix;
|
||||
if(!nat64_prefix)
|
||||
nat64_prefix = DEFAULT_NAT64_PREFIX;
|
||||
if(!netblockstrtoaddr(nat64_prefix, 0, &iter_env->nat64_prefix_addr,
|
||||
&iter_env->nat64_prefix_addrlen,
|
||||
&iter_env->nat64_prefix_net)) {
|
||||
log_err("cannot parse nat64-prefix netblock: %s", nat64_prefix);
|
||||
return 0;
|
||||
}
|
||||
if(!addr_is_ip6(&iter_env->nat64_prefix_addr,
|
||||
iter_env->nat64_prefix_addrlen)) {
|
||||
log_err("nat64-prefix is not IPv6: %s", cfg->nat64_prefix);
|
||||
return 0;
|
||||
}
|
||||
if(!prefixnet_is_nat64(iter_env->nat64_prefix_net)) {
|
||||
log_err("nat64-prefix length it not 32, 40, 48, 56, 64 or 96: %s",
|
||||
nat64_prefix);
|
||||
return 0;
|
||||
}
|
||||
|
||||
iter_env->supports_ipv6 = cfg->do_ip6;
|
||||
iter_env->supports_ipv4 = cfg->do_ip4;
|
||||
iter_env->use_nat64 = cfg->do_nat64;
|
||||
iter_env->outbound_msg_retry = cfg->outbound_msg_retry;
|
||||
iter_env->max_sent_count = cfg->max_sent_count;
|
||||
iter_env->max_query_restarts = cfg->max_query_restarts;
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -238,7 +270,8 @@ iter_filter_unsuitable(struct iter_env* iter_env, struct module_env* env,
|
||||
if(!iter_env->supports_ipv6 && addr_is_ip6(&a->addr, a->addrlen)) {
|
||||
return -1; /* there is no ip6 available */
|
||||
}
|
||||
if(!iter_env->supports_ipv4 && !addr_is_ip6(&a->addr, a->addrlen)) {
|
||||
if(!iter_env->supports_ipv4 && !iter_env->use_nat64 &&
|
||||
!addr_is_ip6(&a->addr, a->addrlen)) {
|
||||
return -1; /* there is no ip4 available */
|
||||
}
|
||||
/* check lameness - need zone , class info */
|
||||
@@ -745,10 +778,15 @@ iter_mark_pside_cycle_targets(struct module_qstate* qstate, struct delegpt* dp)
|
||||
|
||||
int
|
||||
iter_dp_is_useless(struct query_info* qinfo, uint16_t qflags,
|
||||
struct delegpt* dp, int supports_ipv4, int supports_ipv6)
|
||||
struct delegpt* dp, int supports_ipv4, int supports_ipv6,
|
||||
int use_nat64)
|
||||
{
|
||||
struct delegpt_ns* ns;
|
||||
struct delegpt_addr* a;
|
||||
|
||||
if(supports_ipv6 && use_nat64)
|
||||
supports_ipv4 = 1;
|
||||
|
||||
/* check:
|
||||
* o RD qflag is on.
|
||||
* o no addresses are provided.
|
||||
@@ -1308,8 +1346,7 @@ void iter_dec_attempts(struct delegpt* dp, int d, int outbound_msg_retry)
|
||||
for(a=dp->target_list; a; a = a->next_target) {
|
||||
if(a->attempts >= outbound_msg_retry) {
|
||||
/* add back to result list */
|
||||
a->next_result = dp->result_list;
|
||||
dp->result_list = a;
|
||||
delegpt_add_to_result_list(dp, a);
|
||||
}
|
||||
if(a->attempts > d)
|
||||
a->attempts -= d;
|
||||
|
||||
@@ -189,10 +189,13 @@ void iter_mark_pside_cycle_targets(struct module_qstate* qstate,
|
||||
* if not, then the IPv4 addresses are useless.
|
||||
* @param supports_ipv6: if we support ipv6 for lookups to the target.
|
||||
* if not, then the IPv6 addresses are useless.
|
||||
* @param use_nat64: if we support NAT64 for lookups to the target.
|
||||
* if yes, IPv4 addresses are useful even if we don't support IPv4.
|
||||
* @return true if dp is useless.
|
||||
*/
|
||||
int iter_dp_is_useless(struct query_info* qinfo, uint16_t qflags,
|
||||
struct delegpt* dp, int supports_ipv4, int supports_ipv6);
|
||||
int iter_dp_is_useless(struct query_info* qinfo, uint16_t qflags,
|
||||
struct delegpt* dp, int supports_ipv4, int supports_ipv6,
|
||||
int use_nat64);
|
||||
|
||||
/**
|
||||
* See if qname has DNSSEC needs. This is true if there is a trust anchor above
|
||||
|
||||
+235
-104
@@ -255,7 +255,7 @@ error_supers(struct module_qstate* qstate, int id, struct module_qstate* super)
|
||||
log_err("out of memory adding missing");
|
||||
}
|
||||
delegpt_mark_neg(dpns, qstate->qinfo.qtype);
|
||||
if((dpns->got4 == 2 || !ie->supports_ipv4) &&
|
||||
if((dpns->got4 == 2 || (!ie->supports_ipv4 && !ie->use_nat64)) &&
|
||||
(dpns->got6 == 2 || !ie->supports_ipv6)) {
|
||||
dpns->resolved = 1; /* mark as failed */
|
||||
target_count_increase_nx(super_iq, 1);
|
||||
@@ -302,81 +302,65 @@ error_response(struct module_qstate* qstate, int id, int rcode)
|
||||
static int
|
||||
error_response_cache(struct module_qstate* qstate, int id, int rcode)
|
||||
{
|
||||
if(!qstate->no_cache_store) {
|
||||
/* store in cache */
|
||||
struct reply_info err;
|
||||
if(qstate->prefetch_leeway > NORR_TTL) {
|
||||
verbose(VERB_ALGO, "error response for prefetch in cache");
|
||||
/* attempt to adjust the cache entry prefetch */
|
||||
if(dns_cache_prefetch_adjust(qstate->env, &qstate->qinfo,
|
||||
NORR_TTL, qstate->query_flags))
|
||||
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,
|
||||
qstate->env->cfg->serve_expired_ttl_reset))
|
||||
!= NULL) {
|
||||
if(qstate->env->cfg->serve_expired_ttl_reset) {
|
||||
struct reply_info* rep =
|
||||
(struct reply_info*)msg->entry.data;
|
||||
if(rep && *qstate->env->now +
|
||||
qstate->env->cfg->serve_expired_ttl >
|
||||
rep->serve_expired_ttl) {
|
||||
rep->serve_expired_ttl =
|
||||
*qstate->env->now +
|
||||
qstate->env->cfg->serve_expired_ttl;
|
||||
}
|
||||
}
|
||||
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) */
|
||||
} else {
|
||||
/* don't overwrite existing (non-expired) data in
|
||||
* cache with a 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, *qstate->env->now, 0))
|
||||
!= NULL) {
|
||||
struct reply_info* rep = (struct reply_info*)
|
||||
msg->entry.data;
|
||||
if(FLAGS_GET_RCODE(rep->flags) ==
|
||||
LDNS_RCODE_NOERROR ||
|
||||
FLAGS_GET_RCODE(rep->flags) ==
|
||||
LDNS_RCODE_NXDOMAIN) {
|
||||
/* we have a good entry,
|
||||
* don't overwrite */
|
||||
lock_rw_unlock(&msg->entry.lock);
|
||||
return error_response(qstate, id, rcode);
|
||||
}
|
||||
lock_rw_unlock(&msg->entry.lock);
|
||||
}
|
||||
|
||||
}
|
||||
memset(&err, 0, sizeof(err));
|
||||
err.flags = (uint16_t)(BIT_QR | BIT_RA);
|
||||
FLAGS_SET_RCODE(err.flags, rcode);
|
||||
err.qdcount = 1;
|
||||
err.ttl = NORR_TTL;
|
||||
err.prefetch_ttl = PREFETCH_TTL_CALC(err.ttl);
|
||||
err.serve_expired_ttl = NORR_TTL;
|
||||
/* do not waste time trying to validate this servfail */
|
||||
err.security = sec_status_indeterminate;
|
||||
verbose(VERB_ALGO, "store error response in message cache");
|
||||
iter_dns_store(qstate->env, &qstate->qinfo, &err, 0, 0, 0, NULL,
|
||||
qstate->query_flags, qstate->qstarttime);
|
||||
struct reply_info err;
|
||||
struct msgreply_entry* msg;
|
||||
if(qstate->no_cache_store) {
|
||||
return error_response(qstate, id, rcode);
|
||||
}
|
||||
if(qstate->prefetch_leeway > NORR_TTL) {
|
||||
verbose(VERB_ALGO, "error response for prefetch in cache");
|
||||
/* attempt to adjust the cache entry prefetch */
|
||||
if(dns_cache_prefetch_adjust(qstate->env, &qstate->qinfo,
|
||||
NORR_TTL, qstate->query_flags))
|
||||
return error_response(qstate, id, rcode);
|
||||
/* if that fails (not in cache), fall through to store err */
|
||||
}
|
||||
if((msg=msg_cache_lookup(qstate->env,
|
||||
qstate->qinfo.qname, qstate->qinfo.qname_len,
|
||||
qstate->qinfo.qtype, qstate->qinfo.qclass,
|
||||
qstate->query_flags, 0,
|
||||
qstate->env->cfg->serve_expired_ttl_reset)) != NULL) {
|
||||
struct reply_info* rep = (struct reply_info*)msg->entry.data;
|
||||
if(qstate->env->cfg->serve_expired &&
|
||||
qstate->env->cfg->serve_expired_ttl_reset && rep &&
|
||||
*qstate->env->now + qstate->env->cfg->serve_expired_ttl
|
||||
> rep->serve_expired_ttl) {
|
||||
verbose(VERB_ALGO, "reset serve-expired-ttl for "
|
||||
"response in cache");
|
||||
rep->serve_expired_ttl = *qstate->env->now +
|
||||
qstate->env->cfg->serve_expired_ttl;
|
||||
}
|
||||
if(rep && (FLAGS_GET_RCODE(rep->flags) ==
|
||||
LDNS_RCODE_NOERROR ||
|
||||
FLAGS_GET_RCODE(rep->flags) ==
|
||||
LDNS_RCODE_NXDOMAIN ||
|
||||
FLAGS_GET_RCODE(rep->flags) ==
|
||||
LDNS_RCODE_YXDOMAIN) &&
|
||||
(qstate->env->cfg->serve_expired ||
|
||||
*qstate->env->now <= rep->ttl)) {
|
||||
/* we have a good entry, don't overwrite */
|
||||
lock_rw_unlock(&msg->entry.lock);
|
||||
return error_response(qstate, id, rcode);
|
||||
}
|
||||
lock_rw_unlock(&msg->entry.lock);
|
||||
/* nothing interesting is cached (already error response or
|
||||
* expired good record when we don't serve expired), so this
|
||||
* servfail cache entry is useful (stops waste of time on this
|
||||
* servfail NORR_TTL) */
|
||||
}
|
||||
/* store in cache */
|
||||
memset(&err, 0, sizeof(err));
|
||||
err.flags = (uint16_t)(BIT_QR | BIT_RA);
|
||||
FLAGS_SET_RCODE(err.flags, rcode);
|
||||
err.qdcount = 1;
|
||||
err.ttl = NORR_TTL;
|
||||
err.prefetch_ttl = PREFETCH_TTL_CALC(err.ttl);
|
||||
err.serve_expired_ttl = NORR_TTL;
|
||||
/* do not waste time trying to validate this servfail */
|
||||
err.security = sec_status_indeterminate;
|
||||
verbose(VERB_ALGO, "store error response in message cache");
|
||||
iter_dns_store(qstate->env, &qstate->qinfo, &err, 0, 0, 0, NULL,
|
||||
qstate->query_flags, qstate->qstarttime);
|
||||
return error_response(qstate, id, rcode);
|
||||
}
|
||||
|
||||
@@ -590,6 +574,54 @@ handle_cname_response(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** fill fail address for later recovery */
|
||||
static void
|
||||
fill_fail_addr(struct iter_qstate* iq, struct sockaddr_storage* addr,
|
||||
socklen_t addrlen)
|
||||
{
|
||||
if(addrlen == 0) {
|
||||
iq->fail_addr_type = 0;
|
||||
return;
|
||||
}
|
||||
if(((struct sockaddr_in*)addr)->sin_family == AF_INET) {
|
||||
iq->fail_addr_type = 4;
|
||||
memcpy(&iq->fail_addr.in,
|
||||
&((struct sockaddr_in*)addr)->sin_addr,
|
||||
sizeof(iq->fail_addr.in));
|
||||
}
|
||||
#ifdef AF_INET6
|
||||
else if(((struct sockaddr_in*)addr)->sin_family == AF_INET6) {
|
||||
iq->fail_addr_type = 6;
|
||||
memcpy(&iq->fail_addr.in6,
|
||||
&((struct sockaddr_in6*)addr)->sin6_addr,
|
||||
sizeof(iq->fail_addr.in6));
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
iq->fail_addr_type = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/** print fail addr to string */
|
||||
static void
|
||||
print_fail_addr(struct iter_qstate* iq, char* buf, size_t len)
|
||||
{
|
||||
if(iq->fail_addr_type == 4) {
|
||||
if(inet_ntop(AF_INET, &iq->fail_addr.in, buf,
|
||||
(socklen_t)len) == 0)
|
||||
(void)strlcpy(buf, "(inet_ntop error)", len);
|
||||
}
|
||||
#ifdef AF_INET6
|
||||
else if(iq->fail_addr_type == 6) {
|
||||
if(inet_ntop(AF_INET6, &iq->fail_addr.in6, buf,
|
||||
(socklen_t)len) == 0)
|
||||
(void)strlcpy(buf, "(inet_ntop error)", len);
|
||||
}
|
||||
#endif
|
||||
else
|
||||
(void)strlcpy(buf, "", len);
|
||||
}
|
||||
|
||||
/** add response specific error information for log servfail */
|
||||
static void
|
||||
errinf_reply(struct module_qstate* qstate, struct iter_qstate* iq)
|
||||
@@ -597,16 +629,14 @@ errinf_reply(struct module_qstate* qstate, struct iter_qstate* iq)
|
||||
if(qstate->env->cfg->val_log_level < 2 && !qstate->env->cfg->log_servfail)
|
||||
return;
|
||||
if((qstate->reply && qstate->reply->remote_addrlen != 0) ||
|
||||
(iq->fail_reply && iq->fail_reply->remote_addrlen != 0)) {
|
||||
(iq->fail_addr_type != 0)) {
|
||||
char from[256], frm[512];
|
||||
if(qstate->reply && qstate->reply->remote_addrlen != 0)
|
||||
addr_to_str(&qstate->reply->remote_addr,
|
||||
qstate->reply->remote_addrlen, from,
|
||||
sizeof(from));
|
||||
else
|
||||
addr_to_str(&iq->fail_reply->remote_addr,
|
||||
iq->fail_reply->remote_addrlen, from,
|
||||
sizeof(from));
|
||||
print_fail_addr(iq, from, sizeof(from));
|
||||
snprintf(frm, sizeof(frm), "from %s", from);
|
||||
errinf(qstate, frm);
|
||||
}
|
||||
@@ -1137,7 +1167,7 @@ generate_a_aaaa_check(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
* Generate a NS check request to obtain authoritative information
|
||||
* on an NS rrset.
|
||||
*
|
||||
* @param qstate: the qtstate that triggered the need to prime.
|
||||
* @param qstate: the qstate that triggered the need to prime.
|
||||
* @param iq: iterator query state.
|
||||
* @param id: module id.
|
||||
*/
|
||||
@@ -1314,7 +1344,7 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
|
||||
/* We enforce a maximum number of query restarts. This is primarily a
|
||||
* cheap way to prevent CNAME loops. */
|
||||
if(iq->query_restart_count > MAX_RESTART_COUNT) {
|
||||
if(iq->query_restart_count > ie->max_query_restarts) {
|
||||
verbose(VERB_QUERY, "request has exceeded the maximum number"
|
||||
" of query restarts with %d", iq->query_restart_count);
|
||||
errinf(qstate, "request has exceeded the maximum number "
|
||||
@@ -1419,6 +1449,39 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
}
|
||||
iq->qchase.qname = sname;
|
||||
iq->qchase.qname_len = slen;
|
||||
if(qstate->env->auth_zones) {
|
||||
/* apply rpz qname triggers after cname */
|
||||
struct dns_msg* forged_response =
|
||||
rpz_callback_from_iterator_cname(qstate, iq);
|
||||
while(forged_response && reply_find_rrset_section_an(
|
||||
forged_response->rep, iq->qchase.qname,
|
||||
iq->qchase.qname_len, LDNS_RR_TYPE_CNAME,
|
||||
iq->qchase.qclass)) {
|
||||
/* another cname to follow */
|
||||
if(!handle_cname_response(qstate, iq, forged_response,
|
||||
&sname, &slen)) {
|
||||
errinf(qstate, "malloc failure, CNAME info");
|
||||
return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
|
||||
}
|
||||
iq->qchase.qname = sname;
|
||||
iq->qchase.qname_len = slen;
|
||||
forged_response =
|
||||
rpz_callback_from_iterator_cname(qstate, iq);
|
||||
}
|
||||
if(forged_response != NULL) {
|
||||
qstate->ext_state[id] = module_finished;
|
||||
qstate->return_rcode = LDNS_RCODE_NOERROR;
|
||||
qstate->return_msg = forged_response;
|
||||
iq->response = forged_response;
|
||||
next_state(iq, FINISHED_STATE);
|
||||
if(!iter_prepend(iq, qstate->return_msg, qstate->region)) {
|
||||
log_err("rpz: after cached cname, prepend rrsets: out of memory");
|
||||
return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
|
||||
}
|
||||
qstate->return_msg->qinfo = qstate->qinfo;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
/* This *is* a query restart, even if it is a cheap
|
||||
* one. */
|
||||
iq->dp = NULL;
|
||||
@@ -1451,6 +1514,19 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
errinf(qstate, "malloc failure for forward zone");
|
||||
return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
|
||||
}
|
||||
if((qstate->query_flags&BIT_RD)==0) {
|
||||
/* If the server accepts RD=0 queries and forwards
|
||||
* with RD=1, then if the server is listed as an NS
|
||||
* entry, it starts query loops. Stop that loop by
|
||||
* disallowing the query. The RD=0 was previously used
|
||||
* to check the cache with allow_snoop. For stubs,
|
||||
* the iterator pass would have primed the stub and
|
||||
* then cached information can be used for further
|
||||
* queries. */
|
||||
verbose(VERB_ALGO, "cannot forward RD=0 query, to stop query loops");
|
||||
errinf(qstate, "cannot forward RD=0 query");
|
||||
return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
|
||||
}
|
||||
iq->refetch_glue = 0;
|
||||
iq->minimisation_state = DONOT_MINIMISE_STATE;
|
||||
/* the request has been forwarded.
|
||||
@@ -1560,18 +1636,19 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
|
||||
/* see if this dp not useless.
|
||||
* It is useless if:
|
||||
* o all NS items are required glue.
|
||||
* o all NS items are required glue.
|
||||
* or the query is for NS item that is required glue.
|
||||
* o no addresses are provided.
|
||||
* o RD qflag is on.
|
||||
* Instead, go up one level, and try to get even further
|
||||
* If the root was useless, use safety belt information.
|
||||
* If the root was useless, use safety belt information.
|
||||
* Only check cache returns, because replies for servers
|
||||
* could be useless but lead to loops (bumping into the
|
||||
* same server reply) if useless-checked.
|
||||
*/
|
||||
if(iter_dp_is_useless(&qstate->qinfo, qstate->query_flags,
|
||||
iq->dp, ie->supports_ipv4, ie->supports_ipv6)) {
|
||||
if(iter_dp_is_useless(&qstate->qinfo, qstate->query_flags,
|
||||
iq->dp, ie->supports_ipv4, ie->supports_ipv6,
|
||||
ie->use_nat64)) {
|
||||
struct delegpt* retdp = NULL;
|
||||
if(!can_have_last_resort(qstate->env, iq->dp->name, iq->dp->namelen, iq->qchase.qclass, &retdp)) {
|
||||
if(retdp) {
|
||||
@@ -1932,7 +2009,7 @@ query_for_targets(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
break;
|
||||
}
|
||||
/* Send the A request. */
|
||||
if(ie->supports_ipv4 &&
|
||||
if((ie->supports_ipv4 || ie->use_nat64) &&
|
||||
((ns->lame && !ns->done_pside4) ||
|
||||
(!ns->lame && !ns->got4))) {
|
||||
if(!generate_target_query(qstate, iq, id,
|
||||
@@ -2085,14 +2162,14 @@ processLastResort(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
/* 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)) &&
|
||||
((ie->supports_ipv4 || ie->use_nat64) && !ns->done_pside4)) &&
|
||||
!can_have_last_resort(qstate->env, ns->name, ns->namelen,
|
||||
iq->qchase.qclass, NULL)) {
|
||||
log_nametypeclass(VERB_ALGO, "cannot pside lookup ns "
|
||||
"because it is also a stub/forward,",
|
||||
ns->name, LDNS_RR_TYPE_NS, iq->qchase.qclass);
|
||||
if(ie->supports_ipv6) ns->done_pside6 = 1;
|
||||
if(ie->supports_ipv4) ns->done_pside4 = 1;
|
||||
if(ie->supports_ipv4 || ie->use_nat64) ns->done_pside4 = 1;
|
||||
continue;
|
||||
}
|
||||
/* query for parent-side A and AAAA for nameservers */
|
||||
@@ -2117,7 +2194,7 @@ processLastResort(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if(ie->supports_ipv4 && !ns->done_pside4) {
|
||||
if((ie->supports_ipv4 || ie->use_nat64) && !ns->done_pside4) {
|
||||
/* Send the A request. */
|
||||
if(!generate_parentside_target_query(qstate, iq, id,
|
||||
ns->name, ns->namelen,
|
||||
@@ -2259,6 +2336,8 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
int tf_policy;
|
||||
struct delegpt_addr* target;
|
||||
struct outbound_entry* outq;
|
||||
struct sockaddr_storage real_addr;
|
||||
socklen_t real_addrlen;
|
||||
int auth_fallback = 0;
|
||||
uint8_t* qout_orig = NULL;
|
||||
size_t qout_orig_len = 0;
|
||||
@@ -2282,7 +2361,7 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
errinf(qstate, "exceeded the maximum of referrals");
|
||||
return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
|
||||
}
|
||||
if(iq->sent_count > MAX_SENT_COUNT) {
|
||||
if(iq->sent_count > ie->max_sent_count) {
|
||||
verbose(VERB_QUERY, "request has exceeded the maximum "
|
||||
"number of sends with %d", iq->sent_count);
|
||||
errinf(qstate, "exceeded the maximum number of sends");
|
||||
@@ -2384,7 +2463,7 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
}
|
||||
if(!ie->supports_ipv6)
|
||||
delegpt_no_ipv6(iq->dp);
|
||||
if(!ie->supports_ipv4)
|
||||
if(!ie->supports_ipv4 && !ie->use_nat64)
|
||||
delegpt_no_ipv4(iq->dp);
|
||||
delegpt_log(VERB_ALGO, iq->dp);
|
||||
|
||||
@@ -2629,7 +2708,7 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
* the original query is one that matched too, so we have
|
||||
* caps_server+1 number of matching queries now */
|
||||
if(iq->caps_server+1 >= naddr*3 ||
|
||||
iq->caps_server*2+2 >= MAX_SENT_COUNT) {
|
||||
iq->caps_server*2+2 >= (size_t)ie->max_sent_count) {
|
||||
/* *2 on sentcount check because ipv6 may fail */
|
||||
/* we're done, process the response */
|
||||
verbose(VERB_ALGO, "0x20 fallback had %d responses "
|
||||
@@ -2805,23 +2884,36 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
/* We have a valid target. */
|
||||
if(verbosity >= VERB_QUERY) {
|
||||
log_query_info(VERB_QUERY, "sending query:", &iq->qinfo_out);
|
||||
log_name_addr(VERB_QUERY, "sending to target:", iq->dp->name,
|
||||
log_name_addr(VERB_QUERY, "sending to target:", iq->dp->name,
|
||||
&target->addr, target->addrlen);
|
||||
verbose(VERB_ALGO, "dnssec status: %s%s",
|
||||
iq->dnssec_expected?"expected": "not expected",
|
||||
iq->dnssec_lame_query?" but lame_query anyway": "");
|
||||
}
|
||||
|
||||
real_addr = target->addr;
|
||||
real_addrlen = target->addrlen;
|
||||
|
||||
if(ie->use_nat64 && target->addr.ss_family == AF_INET) {
|
||||
addr_to_nat64(&target->addr, &ie->nat64_prefix_addr,
|
||||
ie->nat64_prefix_addrlen, ie->nat64_prefix_net,
|
||||
&real_addr, &real_addrlen);
|
||||
log_name_addr(VERB_QUERY, "applied NAT64:",
|
||||
iq->dp->name, &real_addr, real_addrlen);
|
||||
}
|
||||
|
||||
fptr_ok(fptr_whitelist_modenv_send_query(qstate->env->send_query));
|
||||
outq = (*qstate->env->send_query)(&iq->qinfo_out,
|
||||
iq->chase_flags | (iq->chase_to_rd?BIT_RD:0),
|
||||
/* unset CD if to forwarder(RD set) and not dnssec retry
|
||||
* (blacklist nonempty) and no trust-anchors are configured
|
||||
* above the qname or on the first attempt when dnssec is on */
|
||||
EDNS_DO| ((iq->chase_to_rd||(iq->chase_flags&BIT_RD)!=0)&&
|
||||
(qstate->env->cfg->disable_edns_do?0:EDNS_DO)|
|
||||
((iq->chase_to_rd||(iq->chase_flags&BIT_RD)!=0)&&
|
||||
!qstate->blacklist&&(!iter_qname_indicates_dnssec(qstate->env,
|
||||
&iq->qinfo_out)||target->attempts==1)?0:BIT_CD),
|
||||
iq->dnssec_expected, iq->caps_fallback || is_caps_whitelisted(
|
||||
ie, iq), sq_check_ratelimit, &target->addr, target->addrlen,
|
||||
ie, iq), sq_check_ratelimit, &real_addr, real_addrlen,
|
||||
iq->dp->name, iq->dp->namelen,
|
||||
(iq->dp->tcp_upstream || qstate->env->cfg->tcp_upstream),
|
||||
(iq->dp->ssl_upstream || qstate->env->cfg->ssl_upstream),
|
||||
@@ -2838,7 +2930,7 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
|
||||
}
|
||||
log_addr(VERB_QUERY, "error sending query to auth server",
|
||||
&target->addr, target->addrlen);
|
||||
&real_addr, real_addrlen);
|
||||
if(qstate->env->cfg->qname_minimisation)
|
||||
iq->minimisation_state = SKIP_MINIMISE_STATE;
|
||||
return next_state(iq, QUERYTARGETS_STATE);
|
||||
@@ -2882,7 +2974,7 @@ static int
|
||||
processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
struct iter_env* ie, int id)
|
||||
{
|
||||
int dnsseclame = 0;
|
||||
int dnsseclame = 0, origtypecname = 0, orig_empty_nodata_found;
|
||||
enum response_type type;
|
||||
|
||||
iq->num_current_queries--;
|
||||
@@ -2902,12 +2994,25 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
return next_state(iq, QUERYTARGETS_STATE);
|
||||
}
|
||||
iq->timeout_count = 0;
|
||||
orig_empty_nodata_found = iq->empty_nodata_found;
|
||||
type = response_type_from_server(
|
||||
(int)((iq->chase_flags&BIT_RD) || iq->chase_to_rd),
|
||||
iq->response, &iq->qinfo_out, iq->dp);
|
||||
iq->response, &iq->qinfo_out, iq->dp, &iq->empty_nodata_found);
|
||||
iq->chase_to_rd = 0;
|
||||
/* remove TC flag, if this is erroneously set by TCP upstream */
|
||||
iq->response->rep->flags &= ~BIT_TC;
|
||||
if(orig_empty_nodata_found != iq->empty_nodata_found &&
|
||||
iq->empty_nodata_found < EMPTY_NODATA_RETRY_COUNT) {
|
||||
/* try to search at another server */
|
||||
if(qstate->reply) {
|
||||
struct delegpt_addr* a = delegpt_find_addr(
|
||||
iq->dp, &qstate->reply->remote_addr,
|
||||
qstate->reply->remote_addrlen);
|
||||
/* make selection disprefer it */
|
||||
if(a) a->lame = 1;
|
||||
}
|
||||
return next_state(iq, QUERYTARGETS_STATE);
|
||||
}
|
||||
if(type == RESPONSE_TYPE_REFERRAL && (iq->chase_flags&BIT_RD) &&
|
||||
!iq->auth_zone_response) {
|
||||
/* When forwarding (RD bit is set), we handle referrals
|
||||
@@ -2965,6 +3070,8 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
/* YXDOMAIN is a permanent error, no need to retry */
|
||||
type = RESPONSE_TYPE_ANSWER;
|
||||
}
|
||||
if(type == RESPONSE_TYPE_CNAME)
|
||||
origtypecname = 1;
|
||||
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;
|
||||
@@ -3050,11 +3157,14 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
iq->minimisation_state = DONOT_MINIMISE_STATE;
|
||||
}
|
||||
if(FLAGS_GET_RCODE(iq->response->rep->flags) ==
|
||||
LDNS_RCODE_NXDOMAIN) {
|
||||
LDNS_RCODE_NXDOMAIN && !origtypecname) {
|
||||
/* Stop resolving when NXDOMAIN is DNSSEC
|
||||
* signed. Based on assumption that nameservers
|
||||
* serving signed zones do not return NXDOMAIN
|
||||
* for empty-non-terminals. */
|
||||
/* If this response is actually a CNAME type,
|
||||
* the nxdomain rcode may not be for the qname,
|
||||
* and so it is not the final response. */
|
||||
if(iq->dnssec_expected)
|
||||
return final_state(iq);
|
||||
/* Make subrequest to validate intermediate
|
||||
@@ -3182,7 +3292,7 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
(*qstate->env->detach_subs)(qstate);
|
||||
iq->num_target_queries = 0;
|
||||
iq->response = NULL;
|
||||
iq->fail_reply = NULL;
|
||||
iq->fail_addr_type = 0;
|
||||
verbose(VERB_ALGO, "cleared outbound list for next round");
|
||||
return next_state(iq, QUERYTARGETS_STATE);
|
||||
} else if(type == RESPONSE_TYPE_CNAME) {
|
||||
@@ -3438,7 +3548,7 @@ processPrimeResponse(struct module_qstate* qstate, int id)
|
||||
iq->response->rep->flags &= ~(BIT_RD|BIT_RA); /* ignore rec-lame */
|
||||
type = response_type_from_server(
|
||||
(int)((iq->chase_flags&BIT_RD) || iq->chase_to_rd),
|
||||
iq->response, &iq->qchase, iq->dp);
|
||||
iq->response, &iq->qchase, iq->dp, NULL);
|
||||
if(type == RESPONSE_TYPE_ANSWER) {
|
||||
qstate->return_rcode = LDNS_RCODE_NOERROR;
|
||||
qstate->return_msg = iq->response;
|
||||
@@ -3564,7 +3674,7 @@ processTargetResponse(struct module_qstate* qstate, int id,
|
||||
} else {
|
||||
verbose(VERB_ALGO, "iterator TargetResponse failed");
|
||||
delegpt_mark_neg(dpns, qstate->qinfo.qtype);
|
||||
if((dpns->got4 == 2 || !ie->supports_ipv4) &&
|
||||
if((dpns->got4 == 2 || (!ie->supports_ipv4 && !ie->use_nat64)) &&
|
||||
(dpns->got6 == 2 || !ie->supports_ipv6)) {
|
||||
dpns->resolved = 1; /* fail the target */
|
||||
/* do not count cached answers */
|
||||
@@ -3809,6 +3919,26 @@ processFinished(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
/* make sure QR flag is on */
|
||||
iq->response->rep->flags |= BIT_QR;
|
||||
|
||||
/* explicitly set the EDE string to NULL */
|
||||
iq->response->rep->reason_bogus_str = NULL;
|
||||
if((qstate->env->cfg->val_log_level >= 2 ||
|
||||
qstate->env->cfg->log_servfail) && qstate->errinf &&
|
||||
!qstate->env->cfg->val_log_squelch) {
|
||||
char* err_str = errinf_to_str_misc(qstate);
|
||||
if(err_str) {
|
||||
size_t err_str_len = strlen(err_str);
|
||||
verbose(VERB_ALGO, "iterator EDE: %s", err_str);
|
||||
/* allocate space and store the error
|
||||
* string */
|
||||
iq->response->rep->reason_bogus_str = regional_alloc(
|
||||
qstate->region,
|
||||
sizeof(char) * (err_str_len+1));
|
||||
memcpy(iq->response->rep->reason_bogus_str,
|
||||
err_str, err_str_len+1);
|
||||
}
|
||||
free(err_str);
|
||||
}
|
||||
|
||||
/* we have finished processing this query */
|
||||
qstate->ext_state[id] = module_finished;
|
||||
|
||||
@@ -3987,7 +4117,8 @@ process_response(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
}
|
||||
|
||||
/* parse message */
|
||||
iq->fail_reply = qstate->reply;
|
||||
fill_fail_addr(iq, &qstate->reply->remote_addr,
|
||||
qstate->reply->remote_addrlen);
|
||||
prs = (struct msg_parse*)regional_alloc(qstate->env->scratch,
|
||||
sizeof(struct msg_parse));
|
||||
if(!prs) {
|
||||
@@ -4031,7 +4162,7 @@ process_response(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
|
||||
/* normalize and sanitize: easy to delete items from linked lists */
|
||||
if(!scrub_message(pkt, prs, &iq->qinfo_out, iq->dp->name,
|
||||
qstate->env->scratch, qstate->env, ie)) {
|
||||
qstate->env->scratch, qstate->env, qstate, ie)) {
|
||||
/* if 0x20 enabled, start fallback, but we have no message */
|
||||
if(event == module_event_capsfail && !iq->caps_fallback) {
|
||||
iq->caps_fallback = 1;
|
||||
|
||||
+34
-7
@@ -63,13 +63,8 @@ struct rbtree_type;
|
||||
/** max number of nxdomains allowed for target lookups for a query and
|
||||
* its subqueries when fallback has kicked in */
|
||||
#define MAX_TARGET_NX_FALLBACK (MAX_TARGET_NX*2)
|
||||
/** max number of query restarts. Determines max number of CNAME chain. */
|
||||
#define MAX_RESTART_COUNT 11
|
||||
/** max number of referrals. Makes sure resolver does not run away */
|
||||
#define MAX_REFERRAL_COUNT 130
|
||||
/** max number of queries-sent-out. Make sure large NS set does not loop.
|
||||
* Resets on query restarts (e.g., CNAMES) and referrals. */
|
||||
#define MAX_SENT_COUNT 32
|
||||
/** max number of queries for which to perform dnsseclameness detection,
|
||||
* (rrsigs missing detection) after that, just pick up that response */
|
||||
#define DNSSEC_LAME_DETECT_COUNT 4
|
||||
@@ -106,9 +101,11 @@ extern int BLACKLIST_PENALTY;
|
||||
* Chosen so that the UNKNOWN_SERVER_NICENESS falls within the band of a
|
||||
* fast server, this causes server exploration as a side benefit. msec. */
|
||||
#define RTT_BAND 400
|
||||
/** Number of retries for empty nodata packets before it is accepted. */
|
||||
#define EMPTY_NODATA_RETRY_COUNT 2
|
||||
|
||||
/**
|
||||
* Global state for the iterator.
|
||||
* Global state for the iterator.
|
||||
*/
|
||||
struct iter_env {
|
||||
/** A flag to indicate whether or not we have an IPv6 route */
|
||||
@@ -117,6 +114,18 @@ struct iter_env {
|
||||
/** A flag to indicate whether or not we have an IPv4 route */
|
||||
int supports_ipv4;
|
||||
|
||||
/** A flag to locally apply NAT64 to make IPv4 addrs into IPv6 */
|
||||
int use_nat64;
|
||||
|
||||
/** NAT64 prefix address, cf. dns64_env->prefix_addr */
|
||||
struct sockaddr_storage nat64_prefix_addr;
|
||||
|
||||
/** sizeof(sockaddr_in6) */
|
||||
socklen_t nat64_prefix_addrlen;
|
||||
|
||||
/** CIDR mask length of NAT64 prefix */
|
||||
int nat64_prefix_net;
|
||||
|
||||
/** A set of inetaddrs that should never be queried. */
|
||||
struct iter_donotq* donotq;
|
||||
|
||||
@@ -146,6 +155,12 @@ struct iter_env {
|
||||
|
||||
/** number of retries on outgoing queries */
|
||||
int outbound_msg_retry;
|
||||
|
||||
/** number of queries_sent */
|
||||
int max_sent_count;
|
||||
|
||||
/** max number of query restarts to limit length of CNAME chain */
|
||||
int max_query_restarts;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -402,6 +417,11 @@ struct iter_qstate {
|
||||
*/
|
||||
int refetch_glue;
|
||||
|
||||
/**
|
||||
* This flag detects that a completely empty nodata was received,
|
||||
* already so that it is accepted later. */
|
||||
int empty_nodata_found;
|
||||
|
||||
/** list of pending queries to authoritative servers. */
|
||||
struct outbound_list outlist;
|
||||
|
||||
@@ -438,7 +458,14 @@ struct iter_qstate {
|
||||
/** true if there have been parse failures of reply packets */
|
||||
int parse_failures;
|
||||
/** a failure printout address for last received answer */
|
||||
struct comm_reply* fail_reply;
|
||||
union {
|
||||
struct in_addr in;
|
||||
#ifdef AF_INET6
|
||||
struct in6_addr in6;
|
||||
#endif
|
||||
} fail_addr;
|
||||
/** which fail_addr, 0 is nothing, 4 or 6 */
|
||||
int fail_addr_type;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -70,6 +70,7 @@ context_finalize(struct ub_ctx* ctx)
|
||||
} else {
|
||||
log_init(cfg->logfile, cfg->use_syslog, NULL);
|
||||
}
|
||||
ctx->pipe_pid = getpid();
|
||||
cfg_apply_local_port_policy(cfg, 65536);
|
||||
config_apply(cfg);
|
||||
if(!modstack_setup(&ctx->mods, cfg->module_conf, ctx->env))
|
||||
|
||||
@@ -89,6 +89,12 @@ struct ub_ctx {
|
||||
pid_t bg_pid;
|
||||
/** tid of bg worker thread */
|
||||
ub_thread_type bg_tid;
|
||||
/** pid when pipes are created. This was the process when the
|
||||
* setup was called. Helps with clean up, so we can tell after a fork
|
||||
* which side of the fork the delete is on. */
|
||||
pid_t pipe_pid;
|
||||
/** when threaded, the worker that exists in the created thread. */
|
||||
struct libworker* thread_worker;
|
||||
|
||||
/** do threading (instead of forking) for async resolution */
|
||||
int dothread;
|
||||
|
||||
+38
-1
@@ -305,11 +305,31 @@ ub_ctx_delete(struct ub_ctx* ctx)
|
||||
int do_stop = 1;
|
||||
if(!ctx) return;
|
||||
|
||||
/* if the delete is called but it has forked, and before the fork
|
||||
* the context was finalized, then the bg worker is not stopped
|
||||
* from here. There is one worker, but two contexts that refer to
|
||||
* it and only one should clean up, the one with getpid == pipe_pid.*/
|
||||
if(ctx->created_bg && ctx->pipe_pid != getpid()) {
|
||||
do_stop = 0;
|
||||
#ifndef USE_WINSOCK
|
||||
/* Stop events from getting deregistered, if the backend is
|
||||
* epoll, the epoll fd is the same as the other process.
|
||||
* That process should deregister them. */
|
||||
if(ctx->qq_pipe->listen_com)
|
||||
ctx->qq_pipe->listen_com->event_added = 0;
|
||||
if(ctx->qq_pipe->res_com)
|
||||
ctx->qq_pipe->res_com->event_added = 0;
|
||||
if(ctx->rr_pipe->listen_com)
|
||||
ctx->rr_pipe->listen_com->event_added = 0;
|
||||
if(ctx->rr_pipe->res_com)
|
||||
ctx->rr_pipe->res_com->event_added = 0;
|
||||
#endif
|
||||
}
|
||||
/* see if bg thread is created and if threads have been killed */
|
||||
/* no locks, because those may be held by terminated threads */
|
||||
/* for processes the read pipe is closed and we see that on read */
|
||||
#ifdef HAVE_PTHREAD
|
||||
if(ctx->created_bg && ctx->dothread) {
|
||||
if(ctx->created_bg && ctx->dothread && do_stop) {
|
||||
if(pthread_kill(ctx->bg_tid, 0) == ESRCH) {
|
||||
/* thread has been killed */
|
||||
do_stop = 0;
|
||||
@@ -318,6 +338,23 @@ ub_ctx_delete(struct ub_ctx* ctx)
|
||||
#endif /* HAVE_PTHREAD */
|
||||
if(do_stop)
|
||||
ub_stop_bg(ctx);
|
||||
if(ctx->created_bg && ctx->pipe_pid != getpid() && ctx->thread_worker) {
|
||||
/* This delete is happening from a different process. Delete
|
||||
* the thread worker from this process memory space. The
|
||||
* thread is not there to do so, so it is freed here. */
|
||||
struct ub_event_base* evbase = comm_base_internal(
|
||||
ctx->thread_worker->base);
|
||||
libworker_delete_event(ctx->thread_worker);
|
||||
ctx->thread_worker = NULL;
|
||||
#ifdef USE_MINI_EVENT
|
||||
ub_event_base_free(evbase);
|
||||
#else
|
||||
/* cannot event_base_free, because the epoll_fd cleanup
|
||||
* in libevent could stop the original event_base in the
|
||||
* other process from working. */
|
||||
free(evbase);
|
||||
#endif
|
||||
}
|
||||
libworker_delete_event(ctx->event_worker);
|
||||
|
||||
modstack_desetup(&ctx->mods, ctx->env);
|
||||
|
||||
+13
-8
@@ -62,6 +62,7 @@
|
||||
#include "util/random.h"
|
||||
#include "util/config_file.h"
|
||||
#include "util/netevent.h"
|
||||
#include "util/proxy_protocol.h"
|
||||
#include "util/storage/lookup3.h"
|
||||
#include "util/storage/slabhash.h"
|
||||
#include "util/net_help.h"
|
||||
@@ -168,15 +169,15 @@ libworker_setup(struct ub_ctx* ctx, int is_bg, struct ub_event_base* eb)
|
||||
hints_delete(w->env->hints);
|
||||
w->env->hints = NULL;
|
||||
}
|
||||
if(cfg->ssl_upstream || (cfg->tls_cert_bundle && cfg->tls_cert_bundle[0]) || cfg->tls_win_cert) {
|
||||
w->sslctx = connect_sslctx_create(NULL, NULL,
|
||||
cfg->tls_cert_bundle, cfg->tls_win_cert);
|
||||
if(!w->sslctx) {
|
||||
/* to make the setup fail after unlock */
|
||||
hints_delete(w->env->hints);
|
||||
w->env->hints = NULL;
|
||||
}
|
||||
#ifdef HAVE_SSL
|
||||
w->sslctx = connect_sslctx_create(NULL, NULL,
|
||||
cfg->tls_cert_bundle, cfg->tls_win_cert);
|
||||
if(!w->sslctx) {
|
||||
/* to make the setup fail after unlock */
|
||||
hints_delete(w->env->hints);
|
||||
w->env->hints = NULL;
|
||||
}
|
||||
#endif
|
||||
if(!w->is_bg || w->is_bg_thread) {
|
||||
lock_basic_unlock(&ctx->cfglock);
|
||||
}
|
||||
@@ -265,6 +266,7 @@ libworker_setup(struct ub_ctx* ctx, int is_bg, struct ub_event_base* eb)
|
||||
w->env->kill_sub = &mesh_state_delete;
|
||||
w->env->detect_cycle = &mesh_detect_cycle;
|
||||
comm_base_timept(w->base, &w->env->now, &w->env->now_tv);
|
||||
pp_init(&sldns_write_uint16, &sldns_write_uint32);
|
||||
return w;
|
||||
}
|
||||
|
||||
@@ -395,6 +397,7 @@ int libworker_bg(struct ub_ctx* ctx)
|
||||
w = libworker_setup(ctx, 1, NULL);
|
||||
if(!w) return UB_NOMEM;
|
||||
w->is_bg_thread = 1;
|
||||
ctx->thread_worker = w;
|
||||
#ifdef ENABLE_LOCK_CHECKS
|
||||
w->thread_num = 1; /* for nicer DEBUG checklocks */
|
||||
#endif
|
||||
@@ -604,6 +607,8 @@ setup_qinfo_edns(struct libworker* w, struct ctx_query* q,
|
||||
edns->opt_list_out = NULL;
|
||||
edns->opt_list_inplace_cb_out = NULL;
|
||||
edns->padding_block_size = 0;
|
||||
edns->cookie_present = 0;
|
||||
edns->cookie_valid = 0;
|
||||
if(sldns_buffer_capacity(w->back->udp_buff) < 65535)
|
||||
edns->udp_size = (uint16_t)sldns_buffer_capacity(
|
||||
w->back->udp_buff);
|
||||
|
||||
@@ -36,6 +36,9 @@
|
||||
%begin %{
|
||||
/* store state of warning output, restored at later pop */
|
||||
#pragma GCC diagnostic push
|
||||
/* ignore warnings for pragma below, where for older GCC it can produce a
|
||||
warning if the cast-function-type warning is absent. */
|
||||
#pragma GCC diagnostic ignored "-Wpragmas"
|
||||
/* ignore gcc8 METH_NOARGS function cast warnings for swig function pointers */
|
||||
#pragma GCC diagnostic ignored "-Wcast-function-type"
|
||||
%}
|
||||
@@ -860,6 +863,9 @@ Result: ['74.125.43.147', '74.125.43.99', '74.125.43.103', '74.125.43.104']
|
||||
%inline %{
|
||||
//SWIG will see the ub_ctx as a class
|
||||
struct ub_ctx {
|
||||
/* Dummy member, so the struct is not empty, MSVC complains about
|
||||
* that. */
|
||||
int dummy;
|
||||
};
|
||||
%}
|
||||
|
||||
|
||||
@@ -52,8 +52,8 @@
|
||||
* unbound was compiled with, otherwise it wouldn't work, the event and
|
||||
* event_base structures would be different.
|
||||
*/
|
||||
#ifndef _UB_UNBOUND_EVENT_H
|
||||
#define _UB_UNBOUND_EVENT_H
|
||||
#ifndef UB_UNBOUND_EVENT_H
|
||||
#define UB_UNBOUND_EVENT_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@@ -230,7 +230,7 @@ int ub_ctx_set_event(struct ub_ctx* ctx, struct event_base* base);
|
||||
* @param callback: this is called on completion of the resolution.
|
||||
* It is called as:
|
||||
* void callback(void* mydata, int rcode, void* packet, int packet_len,
|
||||
* int sec, char* why_bogus)
|
||||
* int sec, char* why_bogus, int was_ratelimited)
|
||||
* with mydata: the same as passed here, you may pass NULL,
|
||||
* with rcode: 0 on no error, nonzero for mostly SERVFAIL situations,
|
||||
* this is a DNS rcode.
|
||||
@@ -241,6 +241,7 @@ int ub_ctx_set_event(struct ub_ctx* ctx, struct event_base* base);
|
||||
* with packet_len: length in bytes of the packet buffer.
|
||||
* with sec: 0 if insecure, 1 if bogus, 2 if DNSSEC secure.
|
||||
* with why_bogus: text string explaining why it is bogus (or NULL).
|
||||
* with was_ratelimited: if the query was ratelimited.
|
||||
* These point to buffers inside unbound; do not deallocate the packet or
|
||||
* error string.
|
||||
*
|
||||
@@ -261,4 +262,4 @@ int ub_resolve_event(struct ub_ctx* ctx, const char* name, int rrtype,
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _UB_UNBOUND_H */
|
||||
#endif /* UB_UNBOUND_EVENT_H */
|
||||
|
||||
+66
-50
@@ -4,22 +4,22 @@
|
||||
* Copyright (c) 2007, 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
|
||||
@@ -36,7 +36,7 @@
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* This file contains functions to resolve DNS queries and
|
||||
* This file contains functions to resolve DNS queries and
|
||||
* validate the answers. Synchronously and asynchronously.
|
||||
*
|
||||
* Several ways to use this interface from an application wishing
|
||||
@@ -65,7 +65,7 @@
|
||||
* ... or process() calls my_callback() with results.
|
||||
*
|
||||
* ... if the application has nothing more to do, wait for answer
|
||||
* ub_wait(ctx);
|
||||
* ub_wait(ctx);
|
||||
*
|
||||
* Application threaded. Blocking.
|
||||
* Blocking, same as above. The current thread does the work.
|
||||
@@ -83,7 +83,7 @@
|
||||
* CRYPTO_set_id_callback and CRYPTO_set_locking_callback.
|
||||
*
|
||||
* If no threading is compiled in, the above async example uses fork(2) to
|
||||
* create a process to perform the work. The forked process exits when the
|
||||
* create a process to perform the work. The forked process exits when the
|
||||
* calling process exits, or ctx_delete() is called.
|
||||
* Otherwise, for asynchronous with threading, a worker thread is created.
|
||||
*
|
||||
@@ -94,8 +94,8 @@
|
||||
* The second calls another worker thread (or process) to perform the work.
|
||||
* And no buffers need to be set up, but a context-switch happens.
|
||||
*/
|
||||
#ifndef _UB_UNBOUND_H
|
||||
#define _UB_UNBOUND_H
|
||||
#ifndef UB_UNBOUND_H
|
||||
#define UB_UNBOUND_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@@ -128,10 +128,10 @@ struct ub_result {
|
||||
/** the class asked for */
|
||||
int qclass;
|
||||
|
||||
/**
|
||||
* a list of network order DNS rdata items, terminated with a
|
||||
/**
|
||||
* a list of network order DNS rdata items, terminated with a
|
||||
* NULL pointer, so that data[0] is the first result entry,
|
||||
* data[1] the second, and the last entry is NULL.
|
||||
* data[1] the second, and the last entry is NULL.
|
||||
* If there was no data, data[0] is NULL.
|
||||
*/
|
||||
char** data;
|
||||
@@ -139,8 +139,8 @@ struct ub_result {
|
||||
/** the length in bytes of the data items, len[i] for data[i] */
|
||||
int* len;
|
||||
|
||||
/**
|
||||
* canonical name for the result (the final cname).
|
||||
/**
|
||||
* canonical name for the result (the final cname).
|
||||
* zero terminated string.
|
||||
* May be NULL if no canonical name exists.
|
||||
*/
|
||||
@@ -165,9 +165,9 @@ struct ub_result {
|
||||
*/
|
||||
int havedata;
|
||||
|
||||
/**
|
||||
/**
|
||||
* If there was no data, and the domain did not exist, this is true.
|
||||
* If it is false, and there was no data, then the domain name
|
||||
* If it is false, and there was no data, then the domain name
|
||||
* is purported to exist, but the requested data type is not available.
|
||||
*/
|
||||
int nxdomain;
|
||||
@@ -182,19 +182,19 @@ struct ub_result {
|
||||
*/
|
||||
int secure;
|
||||
|
||||
/**
|
||||
* If the result was not secure (secure==0), and this result is due
|
||||
/**
|
||||
* If the result was not secure (secure==0), and this result is due
|
||||
* to a security failure, bogus is true.
|
||||
* This means the data has been actively tampered with, signatures
|
||||
* failed, expected signatures were not present, timestamps on
|
||||
* failed, expected signatures were not present, timestamps on
|
||||
* signatures were out of date and so on.
|
||||
*
|
||||
* If !secure and !bogus, this can happen if the data is not secure
|
||||
* because security is disabled for that domain name.
|
||||
* If !secure and !bogus, this can happen if the data is not secure
|
||||
* because security is disabled for that domain name.
|
||||
* This means the data is from a domain where data is not signed.
|
||||
*/
|
||||
int bogus;
|
||||
|
||||
|
||||
/**
|
||||
* If the result is bogus this contains a string (zero terminated)
|
||||
* that describes the failure. There may be other errors as well
|
||||
@@ -222,7 +222,7 @@ struct ub_result {
|
||||
* The readable function definition looks like:
|
||||
* void my_callback(void* my_arg, int err, struct ub_result* result);
|
||||
* It is called with
|
||||
* void* my_arg: your pointer to a (struct of) data of your choice,
|
||||
* void* my_arg: your pointer to a (struct of) data of your choice,
|
||||
* or NULL.
|
||||
* int err: if 0 all is OK, otherwise an error occurred and no results
|
||||
* are forthcoming.
|
||||
@@ -301,8 +301,8 @@ int ub_ctx_set_option(struct ub_ctx* ctx, const char* opt, const char* val);
|
||||
* This is a power-users interface that lets you specify all sorts
|
||||
* of options.
|
||||
* @param str: the string is malloced and returned here. NULL on error.
|
||||
* The caller must free() the string. In cases with multiple
|
||||
* entries (auto-trust-anchor-file), a newline delimited list is
|
||||
* The caller must free() the string. In cases with multiple
|
||||
* entries (auto-trust-anchor-file), a newline delimited list is
|
||||
* returned in the string.
|
||||
* @return 0 if OK else an error code (malloc failure, syntax error).
|
||||
*/
|
||||
@@ -321,10 +321,10 @@ int ub_ctx_get_option(struct ub_ctx* ctx, const char* opt, char** str);
|
||||
int ub_ctx_config(struct ub_ctx* ctx, const char* fname);
|
||||
|
||||
/**
|
||||
* Set machine to forward DNS queries to, the caching resolver to use.
|
||||
* IP4 or IP6 address. Forwards all DNS requests to that machine, which
|
||||
* is expected to run a recursive resolver. If the proxy is not
|
||||
* DNSSEC-capable, validation may fail. Can be called several times, in
|
||||
* Set machine to forward DNS queries to, the caching resolver to use.
|
||||
* IP4 or IP6 address. Forwards all DNS requests to that machine, which
|
||||
* is expected to run a recursive resolver. If the proxy is not
|
||||
* DNSSEC-capable, validation may fail. Can be called several times, in
|
||||
* that case the addresses are used as backup servers.
|
||||
*
|
||||
* To read the list of nameservers from /etc/resolv.conf (from DHCP or so),
|
||||
@@ -389,7 +389,7 @@ int ub_ctx_resolvconf(struct ub_ctx* ctx, const char* fname);
|
||||
|
||||
/**
|
||||
* Read list of hosts from the filename given.
|
||||
* Usually "/etc/hosts".
|
||||
* Usually "/etc/hosts".
|
||||
* These addresses are not flagged as DNSSEC secure when queried for.
|
||||
*
|
||||
* @param ctx: context.
|
||||
@@ -403,7 +403,7 @@ int ub_ctx_hosts(struct ub_ctx* ctx, const char* fname);
|
||||
/**
|
||||
* Add a trust anchor to the given context.
|
||||
* The trust anchor is a string, on one line, that holds a valid DNSKEY or
|
||||
* DS RR.
|
||||
* DS RR.
|
||||
* @param ctx: context.
|
||||
* At this time it is only possible to add trusted keys before the
|
||||
* first resolve is done.
|
||||
@@ -465,7 +465,7 @@ int ub_ctx_debugout(struct ub_ctx* ctx, void* out);
|
||||
* Set debug verbosity for the context
|
||||
* Output is directed to stderr.
|
||||
* @param ctx: context.
|
||||
* @param d: debug level, 0 is off, 1 is very minimal, 2 is detailed,
|
||||
* @param d: debug level, 0 is off, 1 is very minimal, 2 is detailed,
|
||||
* and 3 is lots.
|
||||
* @return 0 if OK, else error.
|
||||
*/
|
||||
@@ -474,10 +474,10 @@ int ub_ctx_debuglevel(struct ub_ctx* ctx, int d);
|
||||
/**
|
||||
* Set a context behaviour for asynchronous action.
|
||||
* @param ctx: context.
|
||||
* @param dothread: if true, enables threading and a call to resolve_async()
|
||||
* @param dothread: if true, enables threading and a call to resolve_async()
|
||||
* creates a thread to handle work in the background.
|
||||
* If false, a process is forked to handle work in the background.
|
||||
* Changes to this setting after async() calls have been made have
|
||||
* Changes to this setting after async() calls have been made have
|
||||
* no effect (delete and re-create the context to change).
|
||||
* @return 0 if OK, else error.
|
||||
*/
|
||||
@@ -495,7 +495,7 @@ int ub_poll(struct ub_ctx* ctx);
|
||||
|
||||
/**
|
||||
* Wait for a context to finish with results. Calls ub_process() after
|
||||
* the wait for you. After the wait, there are no more outstanding
|
||||
* the wait for you. After the wait, there are no more outstanding
|
||||
* asynchronous queries.
|
||||
* @param ctx: context.
|
||||
* @return: 0 if OK, else error.
|
||||
@@ -530,11 +530,11 @@ int ub_process(struct ub_ctx* ctx);
|
||||
* @param rrtype: type of RR in host order, 1 is A (address).
|
||||
* @param rrclass: class of RR in host order, 1 is IN (for internet).
|
||||
* @param result: the result data is returned in a newly allocated result
|
||||
* structure. May be NULL on return, return value is set to an error
|
||||
* structure. May be NULL on return, return value is set to an error
|
||||
* in that case (out of memory).
|
||||
* @return 0 if OK, else error.
|
||||
*/
|
||||
int ub_resolve(struct ub_ctx* ctx, const char* name, int rrtype,
|
||||
int ub_resolve(struct ub_ctx* ctx, const char* name, int rrtype,
|
||||
int rrclass, struct ub_result** result);
|
||||
|
||||
/**
|
||||
@@ -561,11 +561,11 @@ int ub_resolve(struct ub_ctx* ctx, const char* name, int rrtype,
|
||||
* If an error happens during processing, your callback will be called
|
||||
* with error set to a nonzero value (and result==NULL).
|
||||
* @param async_id: if you pass a non-NULL value, an identifier number is
|
||||
* returned for the query as it is in progress. It can be used to
|
||||
* returned for the query as it is in progress. It can be used to
|
||||
* cancel the query.
|
||||
* @return 0 if OK, else error.
|
||||
*/
|
||||
int ub_resolve_async(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_type callback, int* async_id);
|
||||
|
||||
/**
|
||||
@@ -589,7 +589,7 @@ int ub_cancel(struct ub_ctx* ctx, int async_id);
|
||||
*/
|
||||
void ub_resolve_free(struct ub_result* result);
|
||||
|
||||
/**
|
||||
/**
|
||||
* Convert error value to a human readable string.
|
||||
* @param err: error code from one of the libunbound functions.
|
||||
* The error codes are from the type enum ub_ctx_err.
|
||||
@@ -605,7 +605,7 @@ const char* ub_strerror(int err);
|
||||
int ub_ctx_print_local_zones(struct ub_ctx* ctx);
|
||||
|
||||
/**
|
||||
* Add a new zone with the zonetype to the local authority info of the
|
||||
* Add a new zone with the zonetype to the local authority info of the
|
||||
* library.
|
||||
* @param ctx: context. Is finalized by the routine.
|
||||
* @param zone_name: name of the zone in text, "example.com"
|
||||
@@ -613,7 +613,7 @@ int ub_ctx_print_local_zones(struct ub_ctx* ctx);
|
||||
* @param zone_type: type of the zone (like for unbound.conf) in text.
|
||||
* @return 0 if OK, else error.
|
||||
*/
|
||||
int ub_ctx_zone_add(struct ub_ctx* ctx, const char *zone_name,
|
||||
int ub_ctx_zone_add(struct ub_ctx* ctx, const char *zone_name,
|
||||
const char *zone_type);
|
||||
|
||||
/**
|
||||
@@ -649,7 +649,7 @@ 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)
|
||||
*/
|
||||
@@ -695,13 +695,22 @@ struct ub_server_stats {
|
||||
long long num_queries;
|
||||
/** number of queries that have been dropped/ratelimited by ip. */
|
||||
long long num_queries_ip_ratelimited;
|
||||
/** number of queries with a valid DNS Cookie. */
|
||||
long long num_queries_cookie_valid;
|
||||
/** number of queries with only the client part of the DNS Cookie. */
|
||||
long long num_queries_cookie_client;
|
||||
/** number of queries with invalid DNS Cookie. */
|
||||
long long num_queries_cookie_invalid;
|
||||
/** 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;
|
||||
|
||||
/** number of queries which are too late to process */
|
||||
long long num_queries_timed_out;
|
||||
/** the longest wait time in the queue */
|
||||
long long max_query_time_us;
|
||||
/**
|
||||
* Sum of the querylistsize of the worker for
|
||||
* Sum of the querylistsize of the worker for
|
||||
* every query that missed cache. To calculate average.
|
||||
*/
|
||||
long long sum_query_list_size;
|
||||
@@ -773,12 +782,12 @@ struct ub_server_stats {
|
||||
long long tcp_accept_usage;
|
||||
/** expired answers served from cache */
|
||||
long long ans_expired;
|
||||
/** histogram data exported to array
|
||||
/** 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 */
|
||||
@@ -788,6 +797,11 @@ struct ub_server_stats {
|
||||
/** number of key cache entries */
|
||||
long long key_cache_count;
|
||||
|
||||
/** maximum number of collisions in the msg cache */
|
||||
long long msg_cache_max_collisions;
|
||||
/** maximum number of collisions in the rrset cache */
|
||||
long long rrset_cache_max_collisions;
|
||||
|
||||
/** number of queries that used dnscrypt */
|
||||
long long num_query_dnscrypt_crypted;
|
||||
/** number of queries that queried dnscrypt certificates */
|
||||
@@ -819,6 +833,8 @@ struct ub_server_stats {
|
||||
/** number of queries answered from edns-subnet specific data, and
|
||||
* the answer was from the edns-subnet cache. */
|
||||
long long num_query_subnet_cache;
|
||||
/** number of queries served from cachedb */
|
||||
long long num_query_cachedb;
|
||||
/** number of bytes in the stream wait buffers */
|
||||
long long mem_stream_wait;
|
||||
/** number of bytes in the HTTP2 query buffers */
|
||||
@@ -831,7 +847,7 @@ struct ub_server_stats {
|
||||
long long rpz_action[UB_STATS_RPZ_ACTION_NUM];
|
||||
};
|
||||
|
||||
/**
|
||||
/**
|
||||
* Statistics to send over the control pipe when asked
|
||||
* This struct is made to be memcopied, sent in binary.
|
||||
* shm mapped with (number+1) at num_threads+1, with first as total
|
||||
@@ -860,4 +876,4 @@ struct ub_stats_info {
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _UB_UNBOUND_H */
|
||||
#endif /* UB_UNBOUND_H */
|
||||
|
||||
+4
-4
@@ -358,8 +358,8 @@ if [ "$DOWIN" = "yes" ]; then
|
||||
replace_version "configure.ac" "$version" "$version2"
|
||||
version="$version2"
|
||||
info "Rebuilding configure script (autoconf) snapshot."
|
||||
autoconf || error_cleanup "Autoconf failed."
|
||||
autoheader || error_cleanup "Autoheader failed."
|
||||
autoconf -f || error_cleanup "Autoconf failed."
|
||||
autoheader -f || error_cleanup "Autoheader failed."
|
||||
rm -r autom4te* || echo "ignored"
|
||||
fi
|
||||
|
||||
@@ -511,7 +511,7 @@ if [ `uname -s | grep -i -c darwin` -ne 0 ]; then
|
||||
fi
|
||||
|
||||
info "Building configure script (autoreconf)."
|
||||
autoreconf || error_cleanup "Autoconf failed."
|
||||
autoreconf -f || error_cleanup "Autoconf failed."
|
||||
|
||||
rm -r autom4te* || error_cleanup "Failed to remove autoconf cache directory."
|
||||
|
||||
@@ -556,7 +556,7 @@ fi
|
||||
|
||||
if [ "$RECONFIGURE" = "yes" ]; then
|
||||
info "Rebuilding configure script (autoconf) snapshot."
|
||||
autoreconf || error_cleanup "Autoconf failed."
|
||||
autoreconf -f || error_cleanup "Autoconf failed."
|
||||
rm -r autom4te* || error_cleanup "Failed to remove autoconf cache directory."
|
||||
fi
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
def init(id, cfg):
|
||||
log_info("pythonmod: init called, module id is %d port: %d script: %s" % (id, cfg.port, cfg.python_script))
|
||||
log_info("pythonmod: init called, module id is %d port: %d script: %s" % (id, cfg.port, mod_env['script']))
|
||||
return True
|
||||
|
||||
def init_standard(id, env):
|
||||
log_info("pythonmod: init called, module id is %d port: %d script: %s" % (id, env.cfg.port, env.cfg.python_script))
|
||||
log_info("pythonmod: init called, module id is %d port: %d script: %s" % (id, env.cfg.port, mod_env['script']))
|
||||
return True
|
||||
|
||||
def deinit(id):
|
||||
|
||||
@@ -50,7 +50,7 @@ Script file must contain four compulsory functions:
|
||||
::
|
||||
|
||||
def init(id, cfg):
|
||||
log_info("pythonmod: init called, module id is %d port: %d script: %s" % (id, cfg.port, cfg.python_script))
|
||||
log_info("pythonmod: init called, module id is %d port: %d script: %s" % (id, cfg.port, mod_env['script']))
|
||||
return True
|
||||
|
||||
|
||||
@@ -69,7 +69,7 @@ Script file must contain four compulsory functions:
|
||||
::
|
||||
|
||||
def init_standard(id, env):
|
||||
log_info("pythonmod: init called, module id is %d port: %d script: %s" % (id, env.cfg.port, env.cfg.python_script))
|
||||
log_info("pythonmod: init called, module id is %d port: %d script: %s" % (id, env.cfg.port, mod_env['script']))
|
||||
return True
|
||||
|
||||
|
||||
|
||||
@@ -129,7 +129,7 @@ config_file
|
||||
|
||||
.. attribute:: ifs
|
||||
|
||||
Interface description strings (IP addresses).
|
||||
List of interface description strings (IP addresses).
|
||||
|
||||
.. attribute:: num_out_ifs
|
||||
|
||||
@@ -138,7 +138,7 @@ config_file
|
||||
|
||||
.. attribute:: out_ifs
|
||||
|
||||
Outgoing interface description strings (IP addresses).
|
||||
List of outgoing interface description strings (IP addresses).
|
||||
|
||||
.. attribute:: root_hints
|
||||
|
||||
@@ -339,4 +339,5 @@ config_file
|
||||
|
||||
.. attribute:: python_script
|
||||
|
||||
Python script file.
|
||||
Linked list of Python script files.
|
||||
Deprecated; `mod_env['script']` should be used instead.
|
||||
|
||||
@@ -6,8 +6,11 @@ Global variables
|
||||
|
||||
.. envvar:: mod_env
|
||||
|
||||
Module environment, contains data pointer for module-specific data.
|
||||
See :class:`pythonmod_env`.
|
||||
Module environment, it is the 'data' pointer for module-specific data
|
||||
in :class:`pythonmod_env`.
|
||||
It is initialized as a dictionary with the 'script' key pointing to the
|
||||
module's python script.
|
||||
It can be further populated during runtime for module-specific data.
|
||||
|
||||
|
||||
Predefined constants
|
||||
|
||||
@@ -80,7 +80,7 @@ def init_standard(id, env):
|
||||
..note:: The previously accessible configuration options can now be found in
|
||||
env.cfg.
|
||||
"""
|
||||
log_info("python: inited script {}".format(env.cfg.python_script))
|
||||
log_info("python: inited script {}".format(mod_env['script']))
|
||||
|
||||
# Register EDNS option 65001 as a known EDNS option.
|
||||
if not register_edns_option(env, 65001, bypass_cache_stage=True,
|
||||
|
||||
@@ -34,6 +34,9 @@
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
'''
|
||||
|
||||
import os
|
||||
|
||||
#Try:
|
||||
# - dig @localhost nlnetlabs.nl +ednsopt=65002:
|
||||
# This query *could* be answered from cache. If so, unbound will reply
|
||||
@@ -242,6 +245,36 @@ def inplace_query_callback(qinfo, flags, qstate, addr, zone, region, **kwargs):
|
||||
return True
|
||||
|
||||
|
||||
def inplace_query_response_callback(qstate, response, **kwargs):
|
||||
"""
|
||||
Function that will be registered as an inplace callback function.
|
||||
It will be called after receiving a reply from a backend server.
|
||||
|
||||
:param qstate: module qstate. opt_lists are available here;
|
||||
:param response: struct dns_msg. The reply received from the backend server;
|
||||
:param **kwargs: Dictionary that may contain parameters added in a future
|
||||
release.
|
||||
"""
|
||||
log_dns_msg(
|
||||
"python: incoming reply from {}{}".format(qstate.reply.addr, os.linesep),
|
||||
response.qinfo, response.rep
|
||||
)
|
||||
return True
|
||||
|
||||
|
||||
def inplace_edns_back_parsed_call(qstate, **kwargs):
|
||||
"""
|
||||
Function that will be registered as an inplace callback function.
|
||||
It will be called after EDNS is parsed on a reply from a backend server..
|
||||
|
||||
:param qstate: module qstate. opt_lists are available here;
|
||||
:param **kwargs: Dictionary that may contain parameters added in a future
|
||||
release.
|
||||
"""
|
||||
log_info("python: edns parsed")
|
||||
return True
|
||||
|
||||
|
||||
def init_standard(id, env):
|
||||
"""
|
||||
New version of the init function.
|
||||
@@ -254,7 +287,7 @@ def init_standard(id, env):
|
||||
env.cfg.
|
||||
|
||||
"""
|
||||
log_info("python: inited script {}".format(env.cfg.python_script))
|
||||
log_info("python: inited script {}".format(mod_env['script']))
|
||||
|
||||
# Register the inplace_reply_callback function as an inplace callback
|
||||
# function when answering a resolved query.
|
||||
@@ -281,6 +314,16 @@ def init_standard(id, env):
|
||||
if not register_inplace_cb_query(inplace_query_callback, env, id):
|
||||
return False
|
||||
|
||||
# Register the inplace_edns_back_parsed_call function as an inplace callback
|
||||
# for when a reply is received from a backend server.
|
||||
if not register_inplace_cb_query_response(inplace_query_response_callback, env, id):
|
||||
return False
|
||||
|
||||
# Register the inplace_edns_back_parsed_call function as an inplace callback
|
||||
# for when EDNS is parsed on a reply from a backend server.
|
||||
if not register_inplace_cb_edns_back_parsed_call(inplace_edns_back_parsed_call, env, id):
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
|
||||
|
||||
@@ -87,7 +87,7 @@ def logDnsMsg(qstate):
|
||||
print "-"*100
|
||||
|
||||
def init(id, cfg):
|
||||
log_info("pythonmod: init called, module id is %d port: %d script: %s" % (id, cfg.port, cfg.python_script))
|
||||
log_info("pythonmod: init called, module id is %d port: %d script: %s" % (id, cfg.port, mod_env['script']))
|
||||
return True
|
||||
|
||||
def deinit(id):
|
||||
|
||||
+187
-39
@@ -86,6 +86,20 @@
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
/* converts an array of strings (char**) to a List of strings */
|
||||
PyObject* CharArrayAsStringList(char** array, int len) {
|
||||
PyObject* list;
|
||||
int i;
|
||||
|
||||
if(!array||len==0) return PyList_New(0);
|
||||
|
||||
list = PyList_New(len);
|
||||
for (i=0; i < len; i++) {
|
||||
PyList_SET_ITEM(list, i, PyString_FromString(array[i]));
|
||||
}
|
||||
return list;
|
||||
}
|
||||
%}
|
||||
|
||||
/* ************************************************************************************ *
|
||||
@@ -952,6 +966,9 @@ struct config_str2list {
|
||||
/* ************************************************************************************ *
|
||||
Structure config_file
|
||||
* ************************************************************************************ */
|
||||
%ignore config_file::ifs;
|
||||
%ignore config_file::out_ifs;
|
||||
%ignore config_file::python_script;
|
||||
struct config_file {
|
||||
int verbosity;
|
||||
int stat_interval;
|
||||
@@ -1035,6 +1052,25 @@ struct config_file {
|
||||
struct config_strlist* python_script;
|
||||
};
|
||||
|
||||
%inline %{
|
||||
PyObject* _get_ifs_tuple(struct config_file* cfg) {
|
||||
return CharArrayAsStringList(cfg->ifs, cfg->num_ifs);
|
||||
}
|
||||
PyObject* _get_ifs_out_tuple(struct config_file* cfg) {
|
||||
return CharArrayAsStringList(cfg->out_ifs, cfg->num_out_ifs);
|
||||
}
|
||||
%}
|
||||
|
||||
%extend config_file {
|
||||
%pythoncode %{
|
||||
ifs = property(_unboundmodule._get_ifs_tuple)
|
||||
out_ifs = property(_unboundmodule._get_ifs_out_tuple)
|
||||
|
||||
def _deprecated_python_script(self): return "cfg.python_script is deprecated, you can use `mod_env['script']` instead."
|
||||
python_script = property(_deprecated_python_script)
|
||||
%}
|
||||
}
|
||||
|
||||
/* ************************************************************************************ *
|
||||
ASN: Adding structures related to forwards_lookup and dns_cache_find_delegation
|
||||
* ************************************************************************************ */
|
||||
@@ -1378,7 +1414,7 @@ struct delegpt* dns_cache_find_delegation(struct module_env* env,
|
||||
struct regional* region, struct dns_msg** msg, uint32_t timenow,
|
||||
int noexpiredabove, uint8_t* expiretop, size_t expiretoplen);
|
||||
int iter_dp_is_useless(struct query_info* qinfo, uint16_t qflags,
|
||||
struct delegpt* dp, int supports_ipv4, int supports_ipv6);
|
||||
struct delegpt* dp, int supports_ipv4, int supports_ipv6, int use_nat64);
|
||||
struct iter_hints_stub* hints_lookup_stub(struct iter_hints* hints,
|
||||
uint8_t* qname, uint16_t qclass, struct delegpt* dp);
|
||||
|
||||
@@ -1409,7 +1445,8 @@ struct delegpt* find_delegation(struct module_qstate* qstate, char *nm, size_t n
|
||||
if(!dp)
|
||||
return NULL;
|
||||
if(iter_dp_is_useless(&qinfo, BIT_RD, dp,
|
||||
qstate->env->cfg->do_ip4, qstate->env->cfg->do_ip6)) {
|
||||
qstate->env->cfg->do_ip4, qstate->env->cfg->do_ip6,
|
||||
qstate->env->cfg->do_nat64)) {
|
||||
if (dname_is_root((uint8_t*)nm))
|
||||
return NULL;
|
||||
nm = (char*)dp->name;
|
||||
@@ -1550,13 +1587,15 @@ int edns_opt_list_append(struct edns_option** list, uint16_t code, size_t len,
|
||||
struct comm_reply* repinfo, struct regional* region,
|
||||
struct timeval* start_time, int id, void* python_callback)
|
||||
{
|
||||
PyObject *func, *py_edns, *py_qstate, *py_opt_list_out, *py_qinfo;
|
||||
PyObject *py_rep, *py_repinfo, *py_region;
|
||||
PyObject *func = NULL, *py_edns = NULL, *py_qstate = NULL;
|
||||
PyObject *py_opt_list_out = NULL, *py_qinfo = NULL;
|
||||
PyObject *py_rep = NULL, *py_repinfo = NULL, *py_region = NULL;
|
||||
PyObject *py_args = NULL, *py_kwargs = NULL, *result = NULL;
|
||||
int res = 0;
|
||||
double py_start_time = ((double)start_time->tv_sec) + ((double)start_time->tv_usec) / 1.0e6;
|
||||
|
||||
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,
|
||||
@@ -1567,20 +1606,24 @@ int edns_opt_list_append(struct edns_option** list, uint16_t code, size_t len,
|
||||
py_rep = SWIG_NewPointerObj((void*) rep, SWIGTYPE_p_reply_info, 0);
|
||||
py_repinfo = SWIG_NewPointerObj((void*) repinfo, SWIGTYPE_p_comm_reply, 0);
|
||||
py_region = SWIG_NewPointerObj((void*) region, SWIGTYPE_p_regional, 0);
|
||||
if(py_qinfo && py_qstate && py_rep && py_edns && py_opt_list_out
|
||||
&& py_region && py_repinfo) {
|
||||
py_args = Py_BuildValue("(OOOiOOO)", py_qinfo, py_qstate, py_rep,
|
||||
rcode, py_edns, py_opt_list_out, py_region);
|
||||
py_kwargs = Py_BuildValue("{s:O,s:d}", "repinfo", py_repinfo, "start_time",
|
||||
py_start_time);
|
||||
if(py_args && py_kwargs) {
|
||||
result = PyObject_Call(func, py_args, py_kwargs);
|
||||
} else {
|
||||
log_err("pythonmod: malloc failure in python_inplace_cb_reply_generic");
|
||||
}
|
||||
} else {
|
||||
log_err("pythonmod: malloc failure in python_inplace_cb_reply_generic");
|
||||
if(!(py_qinfo && py_qstate && py_rep && py_edns && py_opt_list_out
|
||||
&& py_region && py_repinfo)) {
|
||||
log_err("pythonmod: swig pointer failure in python_inplace_cb_reply_generic");
|
||||
goto out;
|
||||
}
|
||||
py_args = Py_BuildValue("(OOOiOOO)", py_qinfo, py_qstate, py_rep,
|
||||
rcode, py_edns, py_opt_list_out, py_region);
|
||||
py_kwargs = Py_BuildValue("{s:O,s:d}", "repinfo", py_repinfo, "start_time",
|
||||
py_start_time);
|
||||
if(!(py_args && py_kwargs)) {
|
||||
log_err("pythonmod: BuildValue failure in python_inplace_cb_reply_generic");
|
||||
goto out;
|
||||
}
|
||||
result = PyObject_Call(func, py_args, py_kwargs);
|
||||
if (result) {
|
||||
res = PyInt_AsLong(result);
|
||||
}
|
||||
out:
|
||||
Py_XDECREF(py_edns);
|
||||
Py_XDECREF(py_qstate);
|
||||
Py_XDECREF(py_opt_list_out);
|
||||
@@ -1590,9 +1633,6 @@ int edns_opt_list_append(struct edns_option** list, uint16_t code, size_t len,
|
||||
Py_XDECREF(py_region);
|
||||
Py_XDECREF(py_args);
|
||||
Py_XDECREF(py_kwargs);
|
||||
if (result) {
|
||||
res = PyInt_AsLong(result);
|
||||
}
|
||||
Py_XDECREF(result);
|
||||
PyGILState_Release(gstate);
|
||||
return res;
|
||||
@@ -1640,29 +1680,34 @@ int edns_opt_list_append(struct edns_option** list, uint16_t code, size_t len,
|
||||
int res = 0;
|
||||
PyObject *func = python_callback;
|
||||
PyObject *py_args = NULL, *py_kwargs = NULL, *result = NULL;
|
||||
PyObject *py_qinfo = NULL;
|
||||
PyObject *py_qstate = NULL;
|
||||
PyObject *py_addr = NULL;
|
||||
PyObject *py_zone = NULL;
|
||||
PyObject *py_region = NULL;
|
||||
|
||||
PyGILState_STATE gstate = PyGILState_Ensure();
|
||||
|
||||
PyObject *py_qinfo = SWIG_NewPointerObj((void*) qinfo, SWIGTYPE_p_query_info, 0);
|
||||
PyObject *py_qstate = SWIG_NewPointerObj((void*) qstate, SWIGTYPE_p_module_qstate, 0);
|
||||
PyObject *py_addr = SWIG_NewPointerObj((void *) addr, SWIGTYPE_p_sockaddr_storage, 0);
|
||||
PyObject *py_zone = PyBytes_FromStringAndSize((const char *)zone, zonelen);
|
||||
PyObject *py_region = SWIG_NewPointerObj((void*) region, SWIGTYPE_p_regional, 0);
|
||||
if(py_qinfo && py_qstate && py_addr && py_zone && py_region) {
|
||||
py_args = Py_BuildValue("(OiOOOO)", py_qinfo, flags, py_qstate, py_addr, py_zone, py_region);
|
||||
py_kwargs = Py_BuildValue("{}");
|
||||
if(py_args && py_kwargs) {
|
||||
result = PyObject_Call(func, py_args, py_kwargs);
|
||||
if (result) {
|
||||
res = PyInt_AsLong(result);
|
||||
}
|
||||
} else {
|
||||
log_err("pythonmod: malloc failure in python_inplace_cb_query_generic");
|
||||
}
|
||||
} else {
|
||||
log_err("pythonmod: malloc failure in python_inplace_cb_query_generic");
|
||||
py_qinfo = SWIG_NewPointerObj((void*) qinfo, SWIGTYPE_p_query_info, 0);
|
||||
py_qstate = SWIG_NewPointerObj((void*) qstate, SWIGTYPE_p_module_qstate, 0);
|
||||
py_addr = SWIG_NewPointerObj((void *) addr, SWIGTYPE_p_sockaddr_storage, 0);
|
||||
py_zone = PyBytes_FromStringAndSize((const char *)zone, zonelen);
|
||||
py_region = SWIG_NewPointerObj((void*) region, SWIGTYPE_p_regional, 0);
|
||||
if(!(py_qinfo && py_qstate && py_addr && py_zone && py_region)) {
|
||||
log_err("pythonmod: swig pointer failure in python_inplace_cb_query_generic");
|
||||
goto out;
|
||||
}
|
||||
|
||||
py_args = Py_BuildValue("(OiOOOO)", py_qinfo, flags, py_qstate, py_addr, py_zone, py_region);
|
||||
py_kwargs = Py_BuildValue("{}");
|
||||
if(!(py_args && py_kwargs)) {
|
||||
log_err("pythonmod: BuildValue failure in python_inplace_cb_query_generic");
|
||||
goto out;
|
||||
}
|
||||
result = PyObject_Call(func, py_args, py_kwargs);
|
||||
if (result) {
|
||||
res = PyInt_AsLong(result);
|
||||
}
|
||||
out:
|
||||
Py_XDECREF(py_qinfo);
|
||||
Py_XDECREF(py_qstate);
|
||||
Py_XDECREF(py_addr);
|
||||
@@ -1686,6 +1731,105 @@ int edns_opt_list_append(struct edns_option** list, uint16_t code, size_t len,
|
||||
if (ret) Py_INCREF(py_cb);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int python_inplace_cb_query_response(struct module_qstate* qstate,
|
||||
struct dns_msg* response, int id, void* python_callback)
|
||||
{
|
||||
int res = 0;
|
||||
PyObject *func = python_callback;
|
||||
PyObject *py_qstate = NULL;
|
||||
PyObject *py_response = NULL;
|
||||
PyObject *py_args = NULL;
|
||||
PyObject *py_kwargs = NULL;
|
||||
PyObject *result = NULL;
|
||||
|
||||
PyGILState_STATE gstate = PyGILState_Ensure();
|
||||
|
||||
py_qstate = SWIG_NewPointerObj((void*) qstate, SWIGTYPE_p_module_qstate, 0);
|
||||
py_response = SWIG_NewPointerObj((void*) response, SWIGTYPE_p_dns_msg, 0);
|
||||
if(!(py_qstate && py_response)) {
|
||||
log_err("pythonmod: swig pointer failure in python_inplace_cb_query_response");
|
||||
goto out;
|
||||
}
|
||||
py_args = Py_BuildValue("(OO)", py_qstate, py_response);
|
||||
py_kwargs = Py_BuildValue("{}");
|
||||
if(!(py_args && py_kwargs)) {
|
||||
log_err("pythonmod: BuildValue failure in python_inplace_cb_query_response");
|
||||
goto out;
|
||||
}
|
||||
result = PyObject_Call(func, py_args, py_kwargs);
|
||||
if (result) {
|
||||
res = PyInt_AsLong(result);
|
||||
}
|
||||
out:
|
||||
Py_XDECREF(py_qstate);
|
||||
Py_XDECREF(py_response);
|
||||
|
||||
Py_XDECREF(py_args);
|
||||
Py_XDECREF(py_kwargs);
|
||||
Py_XDECREF(result);
|
||||
|
||||
PyGILState_Release(gstate);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static int register_inplace_cb_query_response(PyObject* py_cb,
|
||||
struct module_env* env, int id)
|
||||
{
|
||||
int ret = inplace_cb_register(python_inplace_cb_query_response,
|
||||
inplace_cb_query_response, (void*) py_cb, env, id);
|
||||
if (ret) Py_INCREF(py_cb);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int python_inplace_cb_edns_back_parsed_call(struct module_qstate* qstate,
|
||||
int id, void* python_callback)
|
||||
{
|
||||
int res = 0;
|
||||
PyObject *func = python_callback;
|
||||
PyObject *py_qstate = NULL;
|
||||
PyObject *py_args = NULL;
|
||||
PyObject *py_kwargs = NULL;
|
||||
PyObject *result = NULL;
|
||||
|
||||
PyGILState_STATE gstate = PyGILState_Ensure();
|
||||
|
||||
py_qstate = SWIG_NewPointerObj((void*) qstate, SWIGTYPE_p_module_qstate, 0);
|
||||
if(!py_qstate) {
|
||||
log_err("pythonmod: swig pointer failure in python_inplace_cb_edns_back_parsed_call");
|
||||
goto out;
|
||||
}
|
||||
py_args = Py_BuildValue("(O)", py_qstate);
|
||||
py_kwargs = Py_BuildValue("{}");
|
||||
if(!(py_args && py_kwargs)) {
|
||||
log_err("pythonmod: BuildValue failure in python_inplace_cb_edns_back_parsed_call");
|
||||
goto out;
|
||||
}
|
||||
result = PyObject_Call(func, py_args, py_kwargs);
|
||||
if (result) {
|
||||
res = PyInt_AsLong(result);
|
||||
}
|
||||
out:
|
||||
Py_XDECREF(py_qstate);
|
||||
|
||||
Py_XDECREF(py_args);
|
||||
Py_XDECREF(py_kwargs);
|
||||
Py_XDECREF(result);
|
||||
|
||||
PyGILState_Release(gstate);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static int register_inplace_cb_edns_back_parsed_call(PyObject* py_cb,
|
||||
struct module_env* env, int id)
|
||||
{
|
||||
int ret = inplace_cb_register(python_inplace_cb_edns_back_parsed_call,
|
||||
inplace_cb_edns_back_parsed, (void*) py_cb, env, id);
|
||||
if (ret) Py_INCREF(py_cb);
|
||||
return ret;
|
||||
}
|
||||
%}
|
||||
/* C declarations */
|
||||
int inplace_cb_register(void* cb, enum inplace_cb_list_type type, void* cbarg,
|
||||
@@ -1702,3 +1846,7 @@ static int register_inplace_cb_reply_servfail(PyObject* py_cb,
|
||||
struct module_env* env, int id);
|
||||
static int register_inplace_cb_query(PyObject *py_cb,
|
||||
struct module_env* env, int id);
|
||||
static int register_inplace_cb_query_response(PyObject *py_cb,
|
||||
struct module_env* env, int id);
|
||||
static int register_inplace_cb_edns_back_parsed_call(PyObject *py_cb,
|
||||
struct module_env* env, int id);
|
||||
|
||||
+182
-41
@@ -112,6 +112,34 @@ struct pythonmod_qstate {
|
||||
PyObject* data;
|
||||
};
|
||||
|
||||
/* The dict from __main__ could have remnants from a previous script
|
||||
* invocation, in a multi python module setup. Usually this is fine since newer
|
||||
* scripts will update their values. The obvious erroneous case is when mixing
|
||||
* python scripts that make use of both 'init' and 'init_standard'. This
|
||||
* results in 'init_standard' to persist on following scripts that don't use it
|
||||
* (thus not replacing it). This is also problematic in case where a script
|
||||
* does not define a required function but a previously loaded script did. The
|
||||
* current solution is to make sure to clean offensive remnants that influence
|
||||
* further parsing of the individual scripts.
|
||||
*/
|
||||
static void
|
||||
clean_python_function_objects(PyObject* dict) {
|
||||
const char* function_names[] = {
|
||||
"init",
|
||||
"init_standard",
|
||||
"deinit",
|
||||
"operate",
|
||||
"inform_super"
|
||||
};
|
||||
size_t i;
|
||||
|
||||
for(i=0; i<sizeof(function_names)/sizeof(function_names[0]); i++) {
|
||||
if(PyDict_GetItemString(dict, function_names[i]) != NULL) {
|
||||
PyDict_DelItemString(dict, function_names[i]);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/* Generated */
|
||||
#ifndef S_SPLINT_S
|
||||
#include "pythonmod/interface.h"
|
||||
@@ -252,13 +280,24 @@ cleanup:
|
||||
Py_XDECREF(exc_tb);
|
||||
}
|
||||
|
||||
/* we only want to unwind Python once at exit */
|
||||
static void
|
||||
pythonmod_atexit(void)
|
||||
{
|
||||
log_assert(py_mod_count == 0);
|
||||
log_assert(mainthr != NULL);
|
||||
|
||||
PyEval_RestoreThread(mainthr);
|
||||
Py_Finalize();
|
||||
}
|
||||
|
||||
int pythonmod_init(struct module_env* env, int id)
|
||||
{
|
||||
int py_mod_idx = py_mod_count++;
|
||||
|
||||
|
||||
/* Initialize module */
|
||||
FILE* script_py = NULL;
|
||||
PyObject* py_init_arg, *res;
|
||||
PyObject* py_init_arg = NULL, *res = NULL, *fname = NULL;
|
||||
PyGILState_STATE gil;
|
||||
int init_standard = 1, i = 0;
|
||||
#if PY_MAJOR_VERSION < 3
|
||||
@@ -292,47 +331,98 @@ int pythonmod_init(struct module_env* env, int id)
|
||||
/* Initialize Python libraries */
|
||||
if (py_mod_count==1 && !Py_IsInitialized())
|
||||
{
|
||||
#if PY_VERSION_HEX >= 0x03080000
|
||||
PyStatus status;
|
||||
PyPreConfig preconfig;
|
||||
PyConfig config;
|
||||
#endif
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
wchar_t progname[8];
|
||||
mbstowcs(progname, "unbound", 8);
|
||||
#else
|
||||
char *progname = "unbound";
|
||||
#endif
|
||||
#if PY_VERSION_HEX < 0x03080000
|
||||
Py_SetProgramName(progname);
|
||||
#else
|
||||
/* Python must be preinitialized, before the PyImport_AppendInittab
|
||||
* call. */
|
||||
PyPreConfig_InitPythonConfig(&preconfig);
|
||||
status = Py_PreInitialize(&preconfig);
|
||||
if(PyStatus_Exception(status)) {
|
||||
log_err("python exception in Py_PreInitialize: %s%s%s",
|
||||
(status.func?status.func:""), (status.func?": ":""),
|
||||
(status.err_msg?status.err_msg:""));
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
Py_NoSiteFlag = 1;
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
PyImport_AppendInittab(SWIG_name, (void*)SWIG_init);
|
||||
#endif
|
||||
#if PY_VERSION_HEX < 0x03080000
|
||||
Py_Initialize();
|
||||
#else
|
||||
PyConfig_InitPythonConfig(&config);
|
||||
status = PyConfig_SetString(&config, &config.program_name, progname);
|
||||
if(PyStatus_Exception(status)) {
|
||||
log_err("python exception in PyConfig_SetString(.. program_name ..): %s%s%s",
|
||||
(status.func?status.func:""), (status.func?": ":""),
|
||||
(status.err_msg?status.err_msg:""));
|
||||
PyConfig_Clear(&config);
|
||||
return 0;
|
||||
}
|
||||
config.site_import = 0;
|
||||
status = Py_InitializeFromConfig(&config);
|
||||
if(PyStatus_Exception(status)) {
|
||||
log_err("python exception in Py_InitializeFromConfig: %s%s%s",
|
||||
(status.func?status.func:""), (status.func?": ":""),
|
||||
(status.err_msg?status.err_msg:""));
|
||||
PyConfig_Clear(&config);
|
||||
return 0;
|
||||
}
|
||||
PyConfig_Clear(&config);
|
||||
#endif
|
||||
#if PY_MAJOR_VERSION <= 2 || (PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION <= 6)
|
||||
/* initthreads only for python 3.6 and older */
|
||||
PyEval_InitThreads();
|
||||
#endif
|
||||
SWIG_init();
|
||||
mainthr = PyEval_SaveThread();
|
||||
|
||||
/* register callback to unwind Python at exit */
|
||||
atexit(pythonmod_atexit);
|
||||
}
|
||||
|
||||
gil = PyGILState_Ensure();
|
||||
|
||||
if (py_mod_count==1) {
|
||||
/* Initialize Python */
|
||||
PyRun_SimpleString("import sys \n");
|
||||
if(PyRun_SimpleString("import sys \n") < 0 ) {
|
||||
log_err("pythonmod: cannot initialize core module: unboundmodule.py");
|
||||
goto python_init_fail;
|
||||
}
|
||||
PyRun_SimpleString("sys.path.append('.') \n");
|
||||
PyRun_SimpleString("sys.path.append('"RUN_DIR"') \n");
|
||||
PyRun_SimpleString("sys.path.append('"SHARE_DIR"') \n");
|
||||
if(env->cfg->directory && env->cfg->directory[0]) {
|
||||
char wdir[1524];
|
||||
snprintf(wdir, sizeof(wdir), "sys.path.append('%s') \n",
|
||||
env->cfg->directory);
|
||||
PyRun_SimpleString(wdir);
|
||||
}
|
||||
PyRun_SimpleString("sys.path.append('"RUN_DIR"') \n");
|
||||
PyRun_SimpleString("sys.path.append('"SHARE_DIR"') \n");
|
||||
PyRun_SimpleString("import distutils.sysconfig \n");
|
||||
PyRun_SimpleString("sys.path.append(distutils.sysconfig.get_python_lib(1,0)) \n");
|
||||
if (PyRun_SimpleString("from unboundmodule import *\n") < 0)
|
||||
if(PyRun_SimpleString("import site\n") < 0) {
|
||||
log_err("pythonmod: cannot initialize core module: unboundmodule.py");
|
||||
goto python_init_fail;
|
||||
}
|
||||
if(PyRun_SimpleString("sys.path.extend(site.getsitepackages())\n") < 0) {
|
||||
log_err("pythonmod: cannot initialize core module: unboundmodule.py");
|
||||
goto python_init_fail;
|
||||
}
|
||||
if(PyRun_SimpleString("from unboundmodule import *\n") < 0)
|
||||
{
|
||||
log_err("pythonmod: cannot initialize core module: unboundmodule.py");
|
||||
PyGILState_Release(gil);
|
||||
return 0;
|
||||
goto python_init_fail;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -348,18 +438,32 @@ int pythonmod_init(struct module_env* env, int id)
|
||||
if (script_py == NULL)
|
||||
{
|
||||
log_err("pythonmod: can't open file %s for reading", pe->fname);
|
||||
PyGILState_Release(gil);
|
||||
return 0;
|
||||
goto python_init_fail;
|
||||
}
|
||||
|
||||
/* Load file */
|
||||
pe->module = PyImport_AddModule("__main__");
|
||||
Py_XINCREF(pe->module);
|
||||
pe->dict = PyModule_GetDict(pe->module);
|
||||
pe->data = PyDict_New();
|
||||
Py_XINCREF(pe->data);
|
||||
PyModule_AddObject(pe->module, "mod_env", pe->data);
|
||||
Py_XINCREF(pe->dict);
|
||||
clean_python_function_objects(pe->dict);
|
||||
|
||||
/* TODO: deallocation of pe->... if an error occurs */
|
||||
pe->data = PyDict_New();
|
||||
/* add the script filename to the global "mod_env" for trivial access */
|
||||
fname = PyString_FromString(pe->fname);
|
||||
if(PyDict_SetItemString(pe->data, "script", fname) < 0) {
|
||||
log_err("pythonmod: could not add item to dictionary");
|
||||
Py_XDECREF(fname);
|
||||
goto python_init_fail;
|
||||
}
|
||||
Py_XDECREF(fname);
|
||||
Py_XINCREF(pe->data); /* reference will be stolen below */
|
||||
if(PyModule_AddObject(pe->module, "mod_env", pe->data) < 0) {
|
||||
log_err("pythonmod: could not add mod_env object");
|
||||
Py_XDECREF(pe->data); /* 2 times, here and on python_init_fail; */
|
||||
/* on failure the reference is not stolen */
|
||||
goto python_init_fail;
|
||||
}
|
||||
|
||||
if (PyRun_SimpleFile(script_py, pe->fname) < 0) {
|
||||
#if PY_MAJOR_VERSION <= 2 || (PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION < 9)
|
||||
@@ -390,18 +494,30 @@ int pythonmod_init(struct module_env* env, int id)
|
||||
fstr = malloc(flen+1);
|
||||
if(!fstr) {
|
||||
log_err("malloc failure to print parse error");
|
||||
PyGILState_Release(gil);
|
||||
|
||||
/* close the file */
|
||||
#if PY_MAJOR_VERSION < 3
|
||||
Py_XDECREF(PyFileObject);
|
||||
#else
|
||||
fclose(script_py);
|
||||
return 0;
|
||||
#endif
|
||||
|
||||
goto python_init_fail;
|
||||
}
|
||||
fseek(script_py, 0, SEEK_SET);
|
||||
if(fread(fstr, flen, 1, script_py) < 1) {
|
||||
log_err("file read failed to print parse error: %s: %s",
|
||||
pe->fname, strerror(errno));
|
||||
PyGILState_Release(gil);
|
||||
fclose(script_py);
|
||||
free(fstr);
|
||||
return 0;
|
||||
|
||||
/* close the file */
|
||||
#if PY_MAJOR_VERSION < 3
|
||||
Py_XDECREF(PyFileObject);
|
||||
#else
|
||||
fclose(script_py);
|
||||
#endif
|
||||
|
||||
goto python_init_fail;
|
||||
}
|
||||
fstr[flen] = 0;
|
||||
/* we compile the string, but do not run it, to stop side-effects */
|
||||
@@ -409,17 +525,26 @@ int pythonmod_init(struct module_env* env, int id)
|
||||
* that we are expecting */
|
||||
(void)Py_CompileString(fstr, pe->fname, Py_file_input);
|
||||
#endif
|
||||
|
||||
log_py_err();
|
||||
PyGILState_Release(gil);
|
||||
|
||||
/* close the file */
|
||||
#if PY_MAJOR_VERSION < 3
|
||||
Py_XDECREF(PyFileObject);
|
||||
#else
|
||||
fclose(script_py);
|
||||
#endif
|
||||
|
||||
#if PY_MAJOR_VERSION <= 2 || (PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION < 9)
|
||||
/* no cleanup needed for python before 3.9 */
|
||||
#else
|
||||
/* cleanup for python 3.9 and newer */
|
||||
free(fstr);
|
||||
#endif
|
||||
return 0;
|
||||
goto python_init_fail;
|
||||
}
|
||||
|
||||
/* close the file */
|
||||
#if PY_MAJOR_VERSION < 3
|
||||
Py_XDECREF(PyFileObject);
|
||||
#else
|
||||
@@ -432,28 +557,28 @@ int pythonmod_init(struct module_env* env, int id)
|
||||
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;
|
||||
goto python_init_fail;
|
||||
}
|
||||
}
|
||||
Py_XINCREF(pe->func_init);
|
||||
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;
|
||||
goto python_init_fail;
|
||||
}
|
||||
Py_XINCREF(pe->func_deinit);
|
||||
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;
|
||||
goto python_init_fail;
|
||||
}
|
||||
Py_XINCREF(pe->func_operate);
|
||||
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);
|
||||
return 0;
|
||||
goto python_init_fail;
|
||||
}
|
||||
Py_XINCREF(pe->func_inform);
|
||||
|
||||
if (init_standard)
|
||||
{
|
||||
@@ -469,21 +594,31 @@ int pythonmod_init(struct module_env* env, int id)
|
||||
{
|
||||
log_err("pythonmod: Exception occurred in function init");
|
||||
log_py_err();
|
||||
Py_XDECREF(res);
|
||||
Py_XDECREF(py_init_arg);
|
||||
PyGILState_Release(gil);
|
||||
return 0;
|
||||
goto python_init_fail;
|
||||
}
|
||||
|
||||
Py_XDECREF(res);
|
||||
Py_XDECREF(py_init_arg);
|
||||
PyGILState_Release(gil);
|
||||
|
||||
return 1;
|
||||
|
||||
python_init_fail:
|
||||
Py_XDECREF(pe->module);
|
||||
Py_XDECREF(pe->dict);
|
||||
Py_XDECREF(pe->data);
|
||||
Py_XDECREF(pe->func_init);
|
||||
Py_XDECREF(pe->func_deinit);
|
||||
Py_XDECREF(pe->func_operate);
|
||||
Py_XDECREF(pe->func_inform);
|
||||
Py_XDECREF(res);
|
||||
Py_XDECREF(py_init_arg);
|
||||
PyGILState_Release(gil);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void pythonmod_deinit(struct module_env* env, int id)
|
||||
{
|
||||
int cbtype;
|
||||
struct pythonmod_env* pe = env->modinfo[id];
|
||||
if(pe == NULL)
|
||||
return;
|
||||
@@ -503,18 +638,24 @@ void pythonmod_deinit(struct module_env* env, int id)
|
||||
/* Free result if any */
|
||||
Py_XDECREF(res);
|
||||
/* Free shared data if any */
|
||||
Py_XDECREF(pe->module);
|
||||
Py_XDECREF(pe->dict);
|
||||
Py_XDECREF(pe->data);
|
||||
Py_XDECREF(pe->func_init);
|
||||
Py_XDECREF(pe->func_deinit);
|
||||
Py_XDECREF(pe->func_inform);
|
||||
Py_XDECREF(pe->func_operate);
|
||||
PyGILState_Release(gil);
|
||||
|
||||
if(--py_mod_count==0) {
|
||||
PyEval_RestoreThread(mainthr);
|
||||
Py_Finalize();
|
||||
mainthr = NULL;
|
||||
}
|
||||
py_mod_count--;
|
||||
}
|
||||
pe->fname = NULL;
|
||||
free(pe);
|
||||
|
||||
/* iterate over all possible callback types and clean up each in turn */
|
||||
for (cbtype = 0; cbtype < inplace_cb_types_total; cbtype++)
|
||||
inplace_cb_delete(env, cbtype, id);
|
||||
|
||||
/* Module is deallocated in Python */
|
||||
env->modinfo[id] = NULL;
|
||||
}
|
||||
|
||||
@@ -82,4 +82,12 @@ int python_inplace_cb_query_generic(
|
||||
uint8_t* zone, size_t zonelen, struct regional* region, int id,
|
||||
void* python_callback);
|
||||
|
||||
/** Declared here for fptr_wlist access. The definition is in interface.i. */
|
||||
int python_inplace_cb_query_response(struct module_qstate* qstate,
|
||||
struct dns_msg* response, int id, void* python_callback);
|
||||
|
||||
/** Declared here for fptr_wlist access. The definition is in interface.i. */
|
||||
int python_inplace_cb_edns_back_parsed_call(struct module_qstate* qstate,
|
||||
int id, void* python_callback);
|
||||
|
||||
#endif /* PYTHONMOD_H */
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
import os
|
||||
|
||||
def init(id, cfg):
|
||||
log_info("pythonmod: init called, module id is %d port: %d script: %s" % (id, cfg.port, cfg.python_script))
|
||||
log_info("pythonmod: init called, module id is %d port: %d script: %s" % (id, cfg.port, mod_env['script']))
|
||||
return True
|
||||
|
||||
def deinit(id):
|
||||
|
||||
+21
-18
@@ -33,7 +33,7 @@
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
'''
|
||||
def init(id, cfg):
|
||||
log_info("pythonmod: init called, module id is %d port: %d script: %s" % (id, cfg.port, cfg.python_script))
|
||||
log_info("pythonmod: init called, module id is %d port: %d script: %s" % (id, cfg.port, mod_env['script']))
|
||||
return True
|
||||
|
||||
def deinit(id):
|
||||
@@ -55,12 +55,15 @@ def setTTL(qstate, ttl):
|
||||
|
||||
def dataHex(data, prefix=""):
|
||||
res = ""
|
||||
for i in range(0, (len(data)+15)/16):
|
||||
for i in range(0, int((len(data)+15)/16)):
|
||||
res += "%s0x%02X | " % (prefix, i*16)
|
||||
d = map(lambda x:ord(x), data[i*16:i*16+17])
|
||||
if type(data[0]) == type(1):
|
||||
d = map(lambda x:int(x), data[i*16:i*16+17])
|
||||
else:
|
||||
d = map(lambda x:ord(x), data[i*16:i*16+17])
|
||||
for ch in d:
|
||||
res += "%02X " % ch
|
||||
for i in range(0,17-len(d)):
|
||||
for i in range(0,17-len(data[i*16:i*16+17])):
|
||||
res += " "
|
||||
res += "| "
|
||||
for ch in d:
|
||||
@@ -72,31 +75,31 @@ def dataHex(data, prefix=""):
|
||||
return res
|
||||
|
||||
def printReturnMsg(qstate):
|
||||
print "Return MSG rep :: flags: %04X, QDcount: %d, Security:%d, TTL=%d" % (qstate.return_msg.rep.flags, qstate.return_msg.rep.qdcount,qstate.return_msg.rep.security, qstate.return_msg.rep.ttl)
|
||||
print " qinfo :: qname:",qstate.return_msg.qinfo.qname_list, qstate.return_msg.qinfo.qname_str, "type:",qstate.return_msg.qinfo.qtype_str, "class:",qstate.return_msg.qinfo.qclass_str
|
||||
print("Return MSG rep :: flags: %04X, QDcount: %d, Security:%d, TTL=%d" % (qstate.return_msg.rep.flags, qstate.return_msg.rep.qdcount,qstate.return_msg.rep.security, qstate.return_msg.rep.ttl))
|
||||
print(" qinfo :: qname:",qstate.return_msg.qinfo.qname_list, qstate.return_msg.qinfo.qname_str, "type:",qstate.return_msg.qinfo.qtype_str, "class:",qstate.return_msg.qinfo.qclass_str)
|
||||
if (qstate.return_msg.rep):
|
||||
print "RRSets:",qstate.return_msg.rep.rrset_count
|
||||
print("RRSets:",qstate.return_msg.rep.rrset_count)
|
||||
prevkey = None
|
||||
for i in range(0,qstate.return_msg.rep.rrset_count):
|
||||
r = qstate.return_msg.rep.rrsets[i]
|
||||
rk = r.rk
|
||||
print i,":",rk.dname_list, rk.dname_str, "flags: %04X" % rk.flags,
|
||||
print "type:",rk.type_str,"(%d)" % ntohs(rk.type), "class:",rk.rrset_class_str,"(%d)" % ntohs(rk.rrset_class)
|
||||
print(i,":",rk.dname_list, rk.dname_str, "flags: %04X" % rk.flags)
|
||||
print("type:",rk.type_str,"(%d)" % ntohs(rk.type), "class:",rk.rrset_class_str,"(%d)" % ntohs(rk.rrset_class))
|
||||
|
||||
d = r.entry.data
|
||||
print " RRDatas:",d.count+d.rrsig_count
|
||||
print(" RRDatas:",d.count+d.rrsig_count)
|
||||
for j in range(0,d.count+d.rrsig_count):
|
||||
print " ",j,":","TTL=",d.rr_ttl[j],"RR data:"
|
||||
print dataHex(d.rr_data[j]," ")
|
||||
print(" ",j,":","TTL=",d.rr_ttl[j],"RR data:")
|
||||
print(dataHex(d.rr_data[j]," "))
|
||||
|
||||
def operate(id, event, qstate, qdata):
|
||||
log_info("pythonmod: operate called, id: %d, event:%s" % (id, strmodulevent(event)))
|
||||
#print "pythonmod: per query data", qdata
|
||||
#print("pythonmod: per query data", qdata)
|
||||
|
||||
print "Query:", ''.join(map(lambda x:chr(max(32,ord(x))),qstate.qinfo.qname)), qstate.qinfo.qname_list,
|
||||
print "Type:",qstate.qinfo.qtype_str,"(%d)" % qstate.qinfo.qtype,
|
||||
print "Class:",qstate.qinfo.qclass_str,"(%d)" % qstate.qinfo.qclass
|
||||
print
|
||||
print("Query:", qstate.qinfo.qname, qstate.qinfo.qname_list, qstate.qinfo.qname_str)
|
||||
print("Type:",qstate.qinfo.qtype_str,"(%d)" % qstate.qinfo.qtype)
|
||||
print("Class:",qstate.qinfo.qclass_str,"(%d)" % qstate.qinfo.qclass)
|
||||
print("")
|
||||
|
||||
# TEST:
|
||||
# > dig @127.0.0.1 www.seznam.cz A
|
||||
@@ -118,7 +121,7 @@ def operate(id, event, qstate, qdata):
|
||||
invalidateQueryInCache(qstate, qstate.return_msg.qinfo)
|
||||
|
||||
if (qstate.return_msg.rep.authoritative):
|
||||
print "X"*300
|
||||
print("X"*300)
|
||||
|
||||
setTTL(qstate, 10) #do cache nastavime TTL na 10
|
||||
if not storeQueryInCache(qstate, qstate.return_msg.qinfo, qstate.return_msg.rep, 0):
|
||||
|
||||
+17
-8
@@ -1306,8 +1306,8 @@ az_remove_rr(struct auth_zone* z, uint8_t* rr, size_t rr_len,
|
||||
auth_data_delete(node);
|
||||
}
|
||||
if(z->rpz) {
|
||||
rpz_remove_rr(z->rpz, z->namelen, dname, dname_len, rr_type,
|
||||
rr_class, rdata, rdatalen);
|
||||
rpz_remove_rr(z->rpz, z->name, z->namelen, dname, dname_len,
|
||||
rr_type, rr_class, rdata, rdatalen);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
@@ -2475,6 +2475,7 @@ az_find_ce(struct auth_zone* z, struct query_info* qinfo,
|
||||
struct auth_rrset** rrset)
|
||||
{
|
||||
struct auth_data* n = node;
|
||||
struct auth_rrset* lookrrset;
|
||||
*ce = NULL;
|
||||
*rrset = NULL;
|
||||
if(!node_exact) {
|
||||
@@ -2497,21 +2498,23 @@ az_find_ce(struct auth_zone* z, struct query_info* qinfo,
|
||||
/* see if the current candidate has issues */
|
||||
/* not zone apex and has type NS */
|
||||
if(n->namelen != z->namelen &&
|
||||
(*rrset=az_domain_rrset(n, LDNS_RR_TYPE_NS)) &&
|
||||
(lookrrset=az_domain_rrset(n, LDNS_RR_TYPE_NS)) &&
|
||||
/* delegate here, but DS at exact the dp has notype */
|
||||
(qinfo->qtype != LDNS_RR_TYPE_DS ||
|
||||
n->namelen != qinfo->qname_len)) {
|
||||
/* referral */
|
||||
/* this is ce and the lowernode is nonexisting */
|
||||
*ce = n;
|
||||
return 0;
|
||||
*rrset = lookrrset;
|
||||
node_exact = 0;
|
||||
}
|
||||
/* not equal to qname and has type DNAME */
|
||||
if(n->namelen != qinfo->qname_len &&
|
||||
(*rrset=az_domain_rrset(n, LDNS_RR_TYPE_DNAME))) {
|
||||
(lookrrset=az_domain_rrset(n, LDNS_RR_TYPE_DNAME))) {
|
||||
/* this is ce and the lowernode is nonexisting */
|
||||
*ce = n;
|
||||
return 0;
|
||||
*rrset = lookrrset;
|
||||
node_exact = 0;
|
||||
}
|
||||
|
||||
if(*ce == NULL && !domain_has_only_nsec3(n)) {
|
||||
@@ -2756,6 +2759,7 @@ az_change_dnames(struct dns_msg* msg, uint8_t* oldname, uint8_t* newname,
|
||||
== 0) {
|
||||
msg->rep->rrsets[i]->rk.dname = newname;
|
||||
msg->rep->rrsets[i]->rk.dname_len = newlen;
|
||||
msg->rep->rrsets[i]->entry.hash = rrset_key_hash(&msg->rep->rrsets[i]->rk);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5419,6 +5423,8 @@ xfr_transfer_lookup_host(struct auth_xfer* xfr, struct module_env* env)
|
||||
edns.opt_list_out = NULL;
|
||||
edns.opt_list_inplace_cb_out = NULL;
|
||||
edns.padding_block_size = 0;
|
||||
edns.cookie_present = 0;
|
||||
edns.cookie_valid = 0;
|
||||
if(sldns_buffer_capacity(buf) < 65535)
|
||||
edns.udp_size = (uint16_t)sldns_buffer_capacity(buf);
|
||||
else edns.udp_size = 65535;
|
||||
@@ -6612,6 +6618,8 @@ xfr_probe_lookup_host(struct auth_xfer* xfr, struct module_env* env)
|
||||
edns.opt_list_out = NULL;
|
||||
edns.opt_list_inplace_cb_out = NULL;
|
||||
edns.padding_block_size = 0;
|
||||
edns.cookie_present = 0;
|
||||
edns.cookie_valid = 0;
|
||||
if(sldns_buffer_capacity(buf) < 65535)
|
||||
edns.udp_size = (uint16_t)sldns_buffer_capacity(buf);
|
||||
else edns.udp_size = 65535;
|
||||
@@ -7509,7 +7517,7 @@ static void add_rrlist_rrsigs_into_data(struct packed_rrset_data* data,
|
||||
size_t j;
|
||||
if(!rrlist[i])
|
||||
continue;
|
||||
if(rrlist[i] && rrlist[i]->type == LDNS_RR_TYPE_ZONEMD &&
|
||||
if(rrlist[i]->type == LDNS_RR_TYPE_ZONEMD &&
|
||||
query_dname_compare(z->name, node->name)==0) {
|
||||
/* omit RRSIGs over type ZONEMD at apex */
|
||||
continue;
|
||||
@@ -7766,6 +7774,7 @@ static int zonemd_dnssec_verify_rrset(struct auth_zone* z,
|
||||
enum sec_status sec;
|
||||
struct val_env* ve;
|
||||
int m;
|
||||
int verified = 0;
|
||||
m = modstack_find(mods, "validator");
|
||||
if(m == -1) {
|
||||
auth_zone_log(z->name, VERB_ALGO, "zonemd dnssec verify: have "
|
||||
@@ -7789,7 +7798,7 @@ static int zonemd_dnssec_verify_rrset(struct auth_zone* z,
|
||||
"zonemd: verify %s RRset with DNSKEY", typestr);
|
||||
}
|
||||
sec = dnskeyset_verify_rrset(env, ve, &pk, dnskey, sigalg, why_bogus, NULL,
|
||||
LDNS_SECTION_ANSWER, NULL);
|
||||
LDNS_SECTION_ANSWER, NULL, &verified);
|
||||
if(sec == sec_status_secure) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
Vendored
+48
-32
@@ -132,31 +132,6 @@ msg_cache_remove(struct module_env* env, uint8_t* qname, size_t qnamelen,
|
||||
slabhash_remove(env->msg_cache, h, &k);
|
||||
}
|
||||
|
||||
/** remove servfail msg cache entry */
|
||||
static void
|
||||
msg_del_servfail(struct module_env* env, struct query_info* qinfo,
|
||||
uint32_t flags)
|
||||
{
|
||||
struct msgreply_entry* e;
|
||||
/* see if the entry is servfail, and then remove it, so that
|
||||
* lookups move from the cacheresponse stage to the recursionresponse
|
||||
* stage */
|
||||
e = msg_cache_lookup(env, qinfo->qname, qinfo->qname_len,
|
||||
qinfo->qtype, qinfo->qclass, flags, 0, 0);
|
||||
if(!e) return;
|
||||
/* we don't check for the ttl here, also expired servfail entries
|
||||
* are removed. If the user uses serve-expired, they would still be
|
||||
* used to answer from cache */
|
||||
if(FLAGS_GET_RCODE(((struct reply_info*)e->entry.data)->flags)
|
||||
!= LDNS_RCODE_SERVFAIL) {
|
||||
lock_rw_unlock(&e->entry.lock);
|
||||
return;
|
||||
}
|
||||
lock_rw_unlock(&e->entry.lock);
|
||||
msg_cache_remove(env, qinfo->qname, qinfo->qname_len, qinfo->qtype,
|
||||
qinfo->qclass, flags);
|
||||
}
|
||||
|
||||
void
|
||||
dns_cache_store_msg(struct module_env* env, struct query_info* qinfo,
|
||||
hashvalue_type hash, struct reply_info* rep, time_t leeway, int pside,
|
||||
@@ -182,13 +157,20 @@ dns_cache_store_msg(struct module_env* env, struct query_info* qinfo,
|
||||
/* we do not store the message, but we did store the RRs,
|
||||
* which could be useful for delegation information */
|
||||
verbose(VERB_ALGO, "TTL 0: dropped msg from cache");
|
||||
free(rep);
|
||||
/* if the message is SERVFAIL in cache, remove that SERVFAIL,
|
||||
reply_info_delete(rep, NULL);
|
||||
/* if the message is in the cache, remove that msg,
|
||||
* so that the TTL 0 response can be returned for future
|
||||
* responses (i.e. don't get answered by the servfail from
|
||||
* responses (i.e. don't get answered from
|
||||
* cache, but instead go to recursion to get this TTL0
|
||||
* response). */
|
||||
msg_del_servfail(env, qinfo, flags);
|
||||
* response).
|
||||
* Possible messages that could be in the cache:
|
||||
* - SERVFAIL
|
||||
* - NXDOMAIN
|
||||
* - NODATA
|
||||
* - an older record that is expired
|
||||
* - an older record that did not yet expire */
|
||||
msg_cache_remove(env, qinfo->qname, qinfo->qname_len,
|
||||
qinfo->qtype, qinfo->qclass, flags);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -610,6 +592,7 @@ gen_dns_msg(struct regional* region, struct query_info* q, size_t num)
|
||||
if(!msg->rep)
|
||||
return NULL;
|
||||
msg->rep->reason_bogus = LDNS_EDE_NONE;
|
||||
msg->rep->reason_bogus_str = NULL;
|
||||
if(num > RR_COUNT_MAX)
|
||||
return NULL; /* integer overflow protection */
|
||||
msg->rep->rrsets = (struct ub_packed_rrset_key**)
|
||||
@@ -636,6 +619,14 @@ tomsg(struct module_env* env, struct query_info* q, struct reply_info* r,
|
||||
r->serve_expired_ttl < now) {
|
||||
return NULL;
|
||||
}
|
||||
/* Ignore expired failure answers */
|
||||
if(FLAGS_GET_RCODE(r->flags) !=
|
||||
LDNS_RCODE_NOERROR &&
|
||||
FLAGS_GET_RCODE(r->flags) !=
|
||||
LDNS_RCODE_NXDOMAIN &&
|
||||
FLAGS_GET_RCODE(r->flags) !=
|
||||
LDNS_RCODE_YXDOMAIN)
|
||||
return 0;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
@@ -664,6 +655,10 @@ tomsg(struct module_env* env, struct query_info* q, struct reply_info* r,
|
||||
msg->rep->rrset_count = r->rrset_count;
|
||||
msg->rep->authoritative = r->authoritative;
|
||||
msg->rep->reason_bogus = r->reason_bogus;
|
||||
if(r->reason_bogus_str) {
|
||||
msg->rep->reason_bogus_str = regional_strdup(region, r->reason_bogus_str);
|
||||
}
|
||||
|
||||
if(!rrset_array_lock(r->ref, r->rrset_count, now_control)) {
|
||||
return NULL;
|
||||
}
|
||||
@@ -695,6 +690,28 @@ tomsg(struct module_env* env, struct query_info* q, struct reply_info* r,
|
||||
return msg;
|
||||
}
|
||||
|
||||
struct dns_msg*
|
||||
dns_msg_deepcopy_region(struct dns_msg* origin, struct regional* region)
|
||||
{
|
||||
size_t i;
|
||||
struct dns_msg* res = NULL;
|
||||
res = gen_dns_msg(region, &origin->qinfo, origin->rep->rrset_count);
|
||||
if(!res) return NULL;
|
||||
*res->rep = *origin->rep;
|
||||
if(origin->rep->reason_bogus_str) {
|
||||
res->rep->reason_bogus_str = regional_strdup(region,
|
||||
origin->rep->reason_bogus_str);
|
||||
}
|
||||
for(i=0; i<res->rep->rrset_count; i++) {
|
||||
res->rep->rrsets[i] = packed_rrset_copy_region(
|
||||
origin->rep->rrsets[i], region, 0);
|
||||
if(!res->rep->rrsets[i]) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/** synthesize RRset-only response from cached RRset item */
|
||||
static struct dns_msg*
|
||||
rrset_msg(struct ub_packed_rrset_key* rrset, struct regional* region,
|
||||
@@ -1067,7 +1084,6 @@ dns_cache_store(struct module_env* env, struct query_info* msgqinf,
|
||||
/* ttl must be relative ;i.e. 0..86400 not time(0)+86400.
|
||||
* the env->now is added to message and RRsets in this routine. */
|
||||
/* the leeway is used to invalidate other rrsets earlier */
|
||||
|
||||
if(is_referral) {
|
||||
/* store rrsets */
|
||||
struct rrset_ref ref;
|
||||
@@ -1084,7 +1100,7 @@ dns_cache_store(struct module_env* env, struct query_info* msgqinf,
|
||||
((ntohs(ref.key->rk.type)==LDNS_RR_TYPE_NS
|
||||
&& !pside) ? qstarttime:*env->now + leeway));
|
||||
}
|
||||
free(rep);
|
||||
reply_info_delete(rep, NULL);
|
||||
return 1;
|
||||
} else {
|
||||
/* store msg, and rrsets */
|
||||
|
||||
Vendored
+9
@@ -164,6 +164,15 @@ struct dns_msg* tomsg(struct module_env* env, struct query_info* q,
|
||||
struct reply_info* r, struct regional* region, time_t now,
|
||||
int allow_expired, struct regional* scratch);
|
||||
|
||||
/**
|
||||
* Deep copy a dns_msg to a region.
|
||||
* @param origin: the dns_msg to copy.
|
||||
* @param region: the region to copy all the data to.
|
||||
* @return the new dns_msg or NULL on malloc error.
|
||||
*/
|
||||
struct dns_msg* dns_msg_deepcopy_region(struct dns_msg* origin,
|
||||
struct regional* region);
|
||||
|
||||
/**
|
||||
* Find cached message
|
||||
* @param env: module environment with the DNS cache.
|
||||
|
||||
Vendored
+49
-26
@@ -67,6 +67,11 @@ int infra_dp_ratelimit = 0;
|
||||
* in queries per second. */
|
||||
int infra_ip_ratelimit = 0;
|
||||
|
||||
/** ratelimit value for client ip addresses,
|
||||
* in queries per second.
|
||||
* For clients with a valid DNS Cookie. */
|
||||
int infra_ip_ratelimit_cookie = 0;
|
||||
|
||||
size_t
|
||||
infra_sizefunc(void* k, void* ATTR_UNUSED(d))
|
||||
{
|
||||
@@ -1051,9 +1056,50 @@ infra_get_mem(struct infra_cache* infra)
|
||||
return s;
|
||||
}
|
||||
|
||||
/* Returns 1 if the limit has not been exceeded, 0 otherwise. */
|
||||
static int
|
||||
check_ip_ratelimit(struct sockaddr_storage* addr, socklen_t addrlen,
|
||||
struct sldns_buffer* buffer, int premax, int max, int has_cookie)
|
||||
{
|
||||
int limit;
|
||||
|
||||
if(has_cookie) limit = infra_ip_ratelimit_cookie;
|
||||
else limit = infra_ip_ratelimit;
|
||||
|
||||
/* Disabled */
|
||||
if(limit == 0) return 1;
|
||||
|
||||
if(premax <= limit && max > limit) {
|
||||
char client_ip[128], qnm[LDNS_MAX_DOMAINLEN+1+12+12];
|
||||
addr_to_str(addr, addrlen, client_ip, sizeof(client_ip));
|
||||
qnm[0]=0;
|
||||
if(sldns_buffer_limit(buffer)>LDNS_HEADER_SIZE &&
|
||||
LDNS_QDCOUNT(sldns_buffer_begin(buffer))!=0) {
|
||||
(void)sldns_wire2str_rrquestion_buf(
|
||||
sldns_buffer_at(buffer, LDNS_HEADER_SIZE),
|
||||
sldns_buffer_limit(buffer)-LDNS_HEADER_SIZE,
|
||||
qnm, sizeof(qnm));
|
||||
if(strlen(qnm)>0 && qnm[strlen(qnm)-1]=='\n')
|
||||
qnm[strlen(qnm)-1] = 0; /*remove newline*/
|
||||
if(strchr(qnm, '\t'))
|
||||
*strchr(qnm, '\t') = ' ';
|
||||
if(strchr(qnm, '\t'))
|
||||
*strchr(qnm, '\t') = ' ';
|
||||
verbose(VERB_OPS, "ip_ratelimit exceeded %s %d%s %s",
|
||||
client_ip, limit,
|
||||
has_cookie?"(cookie)":"", qnm);
|
||||
} else {
|
||||
verbose(VERB_OPS, "ip_ratelimit exceeded %s %d%s (no query name)",
|
||||
client_ip, limit,
|
||||
has_cookie?"(cookie)":"");
|
||||
}
|
||||
}
|
||||
return (max <= limit);
|
||||
}
|
||||
|
||||
int infra_ip_ratelimit_inc(struct infra_cache* infra,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen, time_t timenow,
|
||||
int backoff, struct sldns_buffer* buffer)
|
||||
int has_cookie, int backoff, struct sldns_buffer* buffer)
|
||||
{
|
||||
int max;
|
||||
struct lruhash_entry* entry;
|
||||
@@ -1070,31 +1116,8 @@ int infra_ip_ratelimit_inc(struct infra_cache* infra,
|
||||
(*cur)++;
|
||||
max = infra_rate_max(entry->data, timenow, backoff);
|
||||
lock_rw_unlock(&entry->lock);
|
||||
|
||||
if(premax <= infra_ip_ratelimit && max > infra_ip_ratelimit) {
|
||||
char client_ip[128], qnm[LDNS_MAX_DOMAINLEN+1+12+12];
|
||||
addr_to_str(addr, addrlen, client_ip, sizeof(client_ip));
|
||||
qnm[0]=0;
|
||||
if(sldns_buffer_limit(buffer)>LDNS_HEADER_SIZE &&
|
||||
LDNS_QDCOUNT(sldns_buffer_begin(buffer))!=0) {
|
||||
(void)sldns_wire2str_rrquestion_buf(
|
||||
sldns_buffer_at(buffer, LDNS_HEADER_SIZE),
|
||||
sldns_buffer_limit(buffer)-LDNS_HEADER_SIZE,
|
||||
qnm, sizeof(qnm));
|
||||
if(strlen(qnm)>0 && qnm[strlen(qnm)-1]=='\n')
|
||||
qnm[strlen(qnm)-1] = 0; /*remove newline*/
|
||||
if(strchr(qnm, '\t'))
|
||||
*strchr(qnm, '\t') = ' ';
|
||||
if(strchr(qnm, '\t'))
|
||||
*strchr(qnm, '\t') = ' ';
|
||||
verbose(VERB_OPS, "ip_ratelimit exceeded %s %d %s",
|
||||
client_ip, infra_ip_ratelimit, qnm);
|
||||
} else {
|
||||
verbose(VERB_OPS, "ip_ratelimit exceeded %s %d (no query name)",
|
||||
client_ip, infra_ip_ratelimit);
|
||||
}
|
||||
}
|
||||
return (max <= infra_ip_ratelimit);
|
||||
return check_ip_ratelimit(addr, addrlen, buffer, premax, max,
|
||||
has_cookie);
|
||||
}
|
||||
|
||||
/* create */
|
||||
|
||||
Vendored
+4
-1
@@ -153,6 +153,8 @@ struct rate_key {
|
||||
|
||||
/** ip ratelimit, 0 is off */
|
||||
extern int infra_ip_ratelimit;
|
||||
/** ip ratelimit for DNS Cookie clients, 0 is off */
|
||||
extern int infra_ip_ratelimit_cookie;
|
||||
|
||||
/**
|
||||
* key for ip_ratelimit lookups, a source IP.
|
||||
@@ -419,13 +421,14 @@ int infra_find_ratelimit(struct infra_cache* infra, uint8_t* name,
|
||||
* @param addr: client address
|
||||
* @param addrlen: client address length
|
||||
* @param timenow: what time it is now.
|
||||
* @param has_cookie: if the request came with a DNS Cookie.
|
||||
* @param backoff: if backoff is enabled.
|
||||
* @param buffer: with query for logging.
|
||||
* @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 sockaddr_storage* addr, socklen_t addrlen, time_t timenow,
|
||||
int backoff, struct sldns_buffer* buffer);
|
||||
int has_cookie, int backoff, struct sldns_buffer* buffer);
|
||||
|
||||
/**
|
||||
* Get memory used by the infra cache.
|
||||
|
||||
+103
-58
@@ -4,22 +4,22 @@
|
||||
* Copyright (c) 2007, 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
|
||||
@@ -79,9 +79,11 @@
|
||||
#ifdef HAVE_NET_IF_H
|
||||
#include <net/if.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_LINUX_NET_TSTAMP_H
|
||||
#include <linux/net_tstamp.h>
|
||||
#endif
|
||||
/** number of queued TCP connections for listen() */
|
||||
#define TCP_BACKLOG 256
|
||||
#define TCP_BACKLOG 256
|
||||
|
||||
#ifndef THREADS_DISABLED
|
||||
/** lock on the counter of stream buffer memory */
|
||||
@@ -187,7 +189,7 @@ systemd_get_activated(int family, int socktype, int listen,
|
||||
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;
|
||||
@@ -253,7 +255,7 @@ create_udp_sock(int family, int socktype, struct sockaddr* addr,
|
||||
return -1;
|
||||
}
|
||||
#else
|
||||
if(WSAGetLastError() == WSAEAFNOSUPPORT ||
|
||||
if(WSAGetLastError() == WSAEAFNOSUPPORT ||
|
||||
WSAGetLastError() == WSAEPROTONOSUPPORT) {
|
||||
*noproto = 1;
|
||||
return -1;
|
||||
@@ -270,7 +272,7 @@ create_udp_sock(int family, int socktype, struct sockaddr* addr,
|
||||
#endif
|
||||
if(listen) {
|
||||
#ifdef SO_REUSEADDR
|
||||
if(setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (void*)&on,
|
||||
if(setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (void*)&on,
|
||||
(socklen_t)sizeof(on)) < 0) {
|
||||
log_err("setsockopt(.. SO_REUSEADDR ..) failed: %s",
|
||||
sock_strerror(errno));
|
||||
@@ -368,9 +370,9 @@ create_udp_sock(int family, int socktype, struct sockaddr* addr,
|
||||
socklen_t slen = (socklen_t)sizeof(got);
|
||||
# ifdef SO_RCVBUFFORCE
|
||||
/* Linux specific: try to use root permission to override
|
||||
* system limits on rcvbuf. The limit is stored in
|
||||
* system limits on rcvbuf. The limit is stored in
|
||||
* /proc/sys/net/core/rmem_max or sysctl net.core.rmem_max */
|
||||
if(setsockopt(s, SOL_SOCKET, SO_RCVBUFFORCE, (void*)&rcv,
|
||||
if(setsockopt(s, SOL_SOCKET, SO_RCVBUFFORCE, (void*)&rcv,
|
||||
(socklen_t)sizeof(rcv)) < 0) {
|
||||
if(errno != EPERM) {
|
||||
log_err("setsockopt(..., SO_RCVBUFFORCE, "
|
||||
@@ -381,7 +383,7 @@ create_udp_sock(int family, int socktype, struct sockaddr* addr,
|
||||
return -1;
|
||||
}
|
||||
# endif /* SO_RCVBUFFORCE */
|
||||
if(setsockopt(s, SOL_SOCKET, SO_RCVBUF, (void*)&rcv,
|
||||
if(setsockopt(s, SOL_SOCKET, SO_RCVBUF, (void*)&rcv,
|
||||
(socklen_t)sizeof(rcv)) < 0) {
|
||||
log_err("setsockopt(..., SO_RCVBUF, "
|
||||
"...) failed: %s", sock_strerror(errno));
|
||||
@@ -392,7 +394,7 @@ create_udp_sock(int family, int socktype, struct sockaddr* addr,
|
||||
}
|
||||
/* check if we got the right thing or if system
|
||||
* reduced to some system max. Warn if so */
|
||||
if(getsockopt(s, SOL_SOCKET, SO_RCVBUF, (void*)&got,
|
||||
if(getsockopt(s, SOL_SOCKET, SO_RCVBUF, (void*)&got,
|
||||
&slen) >= 0 && got < rcv/2) {
|
||||
log_warn("so-rcvbuf %u was not granted. "
|
||||
"Got %u. To fix: start with "
|
||||
@@ -413,9 +415,9 @@ create_udp_sock(int family, int socktype, struct sockaddr* addr,
|
||||
socklen_t slen = (socklen_t)sizeof(got);
|
||||
# ifdef SO_SNDBUFFORCE
|
||||
/* Linux specific: try to use root permission to override
|
||||
* system limits on sndbuf. The limit is stored in
|
||||
* system limits on sndbuf. The limit is stored in
|
||||
* /proc/sys/net/core/wmem_max or sysctl net.core.wmem_max */
|
||||
if(setsockopt(s, SOL_SOCKET, SO_SNDBUFFORCE, (void*)&snd,
|
||||
if(setsockopt(s, SOL_SOCKET, SO_SNDBUFFORCE, (void*)&snd,
|
||||
(socklen_t)sizeof(snd)) < 0) {
|
||||
if(errno != EPERM) {
|
||||
log_err("setsockopt(..., SO_SNDBUFFORCE, "
|
||||
@@ -426,7 +428,7 @@ create_udp_sock(int family, int socktype, struct sockaddr* addr,
|
||||
return -1;
|
||||
}
|
||||
# endif /* SO_SNDBUFFORCE */
|
||||
if(setsockopt(s, SOL_SOCKET, SO_SNDBUF, (void*)&snd,
|
||||
if(setsockopt(s, SOL_SOCKET, SO_SNDBUF, (void*)&snd,
|
||||
(socklen_t)sizeof(snd)) < 0) {
|
||||
log_err("setsockopt(..., SO_SNDBUF, "
|
||||
"...) failed: %s", sock_strerror(errno));
|
||||
@@ -437,7 +439,7 @@ create_udp_sock(int family, int socktype, struct sockaddr* addr,
|
||||
}
|
||||
/* check if we got the right thing or if system
|
||||
* reduced to some system max. Warn if so */
|
||||
if(getsockopt(s, SOL_SOCKET, SO_SNDBUF, (void*)&got,
|
||||
if(getsockopt(s, SOL_SOCKET, SO_SNDBUF, (void*)&got,
|
||||
&slen) >= 0 && got < snd/2) {
|
||||
log_warn("so-sndbuf %u was not granted. "
|
||||
"Got %u. To fix: start with "
|
||||
@@ -469,7 +471,7 @@ create_udp_sock(int family, int socktype, struct sockaddr* addr,
|
||||
# endif
|
||||
) {
|
||||
int val=(v6only==2)?0:1;
|
||||
if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY,
|
||||
if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY,
|
||||
(void*)&val, (socklen_t)sizeof(val)) < 0) {
|
||||
log_err("setsockopt(..., IPV6_V6ONLY"
|
||||
", ...) failed: %s", sock_strerror(errno));
|
||||
@@ -576,7 +578,7 @@ create_udp_sock(int family, int socktype, struct sockaddr* addr,
|
||||
int action;
|
||||
# if defined(IP_PMTUDISC_OMIT)
|
||||
action = IP_PMTUDISC_OMIT;
|
||||
if (setsockopt(s, IPPROTO_IP, IP_MTU_DISCOVER,
|
||||
if (setsockopt(s, IPPROTO_IP, IP_MTU_DISCOVER,
|
||||
&action, (socklen_t)sizeof(action)) < 0) {
|
||||
|
||||
if (errno != EINVAL) {
|
||||
@@ -609,7 +611,7 @@ create_udp_sock(int family, int socktype, struct sockaddr* addr,
|
||||
/* the IP_DONTFRAG option if defined in the 11.0 OSX headers,
|
||||
* but does not work on that version, so we exclude it */
|
||||
int off = 0;
|
||||
if (setsockopt(s, IPPROTO_IP, IP_DONTFRAG,
|
||||
if (setsockopt(s, IPPROTO_IP, IP_DONTFRAG,
|
||||
&off, (socklen_t)sizeof(off)) < 0) {
|
||||
log_err("setsockopt(..., IP_DONTFRAG, ...) failed: %s",
|
||||
strerror(errno));
|
||||
@@ -647,7 +649,7 @@ create_udp_sock(int family, int socktype, struct sockaddr* addr,
|
||||
if(WSAGetLastError() != WSAEADDRINUSE &&
|
||||
WSAGetLastError() != WSAEADDRNOTAVAIL &&
|
||||
!(WSAGetLastError() == WSAEACCES && verbosity < 4 && !listen)) {
|
||||
log_err_addr("can't bind socket",
|
||||
log_err_addr("can't bind socket",
|
||||
wsa_strerror(WSAGetLastError()),
|
||||
(struct sockaddr_storage*)addr, addrlen);
|
||||
}
|
||||
@@ -749,7 +751,7 @@ create_tcp_accept_sock(struct addrinfo *addr, int v6only, int* noproto,
|
||||
}
|
||||
#endif
|
||||
#ifdef SO_REUSEADDR
|
||||
if(setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (void*)&on,
|
||||
if(setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (void*)&on,
|
||||
(socklen_t)sizeof(on)) < 0) {
|
||||
log_err("setsockopt(.. SO_REUSEADDR ..) failed: %s",
|
||||
sock_strerror(errno));
|
||||
@@ -793,7 +795,7 @@ create_tcp_accept_sock(struct addrinfo *addr, int v6only, int* noproto,
|
||||
&& !got_fd_from_systemd
|
||||
# endif
|
||||
) {
|
||||
if(setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY,
|
||||
if(setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY,
|
||||
(void*)&on, (socklen_t)sizeof(on)) < 0) {
|
||||
log_err("setsockopt(..., IPV6_V6ONLY, ...) failed: %s",
|
||||
sock_strerror(errno));
|
||||
@@ -845,7 +847,7 @@ create_tcp_accept_sock(struct addrinfo *addr, int v6only, int* noproto,
|
||||
addr->ai_addrlen);
|
||||
}
|
||||
#else
|
||||
log_err_addr("can't bind socket",
|
||||
log_err_addr("can't bind socket",
|
||||
wsa_strerror(WSAGetLastError()),
|
||||
(struct sockaddr_storage*)addr->ai_addr,
|
||||
addr->ai_addrlen);
|
||||
@@ -873,7 +875,7 @@ create_tcp_accept_sock(struct addrinfo *addr, int v6only, int* noproto,
|
||||
/* 5 is recommended on linux */
|
||||
qlen = 5;
|
||||
#endif
|
||||
if ((setsockopt(s, IPPROTO_TCP, TCP_FASTOPEN, &qlen,
|
||||
if ((setsockopt(s, IPPROTO_TCP, TCP_FASTOPEN, &qlen,
|
||||
sizeof(qlen))) == -1 ) {
|
||||
#ifdef ENOPROTOOPT
|
||||
/* squelch ENOPROTOOPT: freebsd server mode with kernel support
|
||||
@@ -999,7 +1001,7 @@ err:
|
||||
* Create socket from getaddrinfo results
|
||||
*/
|
||||
static int
|
||||
make_sock(int stype, const char* ifname, const char* port,
|
||||
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 nodelay, int freebind,
|
||||
int use_systemd, int dscp, struct unbound_socket* ub_sock)
|
||||
@@ -1015,10 +1017,10 @@ make_sock(int stype, const char* ifname, const char* port,
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
log_err("node %s:%s getaddrinfo: %s %s",
|
||||
log_err("node %s:%s getaddrinfo: %s %s",
|
||||
ifname?ifname:"default", port, gai_strerror(r),
|
||||
#ifdef EAI_SYSTEM
|
||||
r==EAI_SYSTEM?(char*)strerror(errno):""
|
||||
(r==EAI_SYSTEM?(char*)strerror(errno):"")
|
||||
#else
|
||||
""
|
||||
#endif
|
||||
@@ -1055,7 +1057,7 @@ make_sock(int stype, const char* ifname, const char* port,
|
||||
|
||||
/** make socket and first see if ifname contains port override info */
|
||||
static int
|
||||
make_sock_port(int stype, const char* ifname, const char* port,
|
||||
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 nodelay, int freebind,
|
||||
int use_systemd, int dscp, struct unbound_socket* ub_sock)
|
||||
@@ -1114,9 +1116,28 @@ port_insert(struct listen_port** list, int s, enum listen_type ftype,
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** set fd to receive software timestamps */
|
||||
static int
|
||||
set_recvtimestamp(int s)
|
||||
{
|
||||
#ifdef HAVE_LINUX_NET_TSTAMP_H
|
||||
int opt = SOF_TIMESTAMPING_RX_SOFTWARE | SOF_TIMESTAMPING_SOFTWARE;
|
||||
if (setsockopt(s, SOL_SOCKET, SO_TIMESTAMPNS, (void*)&opt, (socklen_t)sizeof(opt)) < 0) {
|
||||
log_err("setsockopt(..., SO_TIMESTAMPNS, ...) failed: %s",
|
||||
strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
#else
|
||||
log_err("packets timestamping is not supported on this platform");
|
||||
(void)s;
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
/** set fd to receive source address packet info */
|
||||
static int
|
||||
set_recvpktinfo(int s, int family)
|
||||
set_recvpktinfo(int s, int family)
|
||||
{
|
||||
#if defined(IPV6_RECVPKTINFO) || defined(IPV6_PKTINFO) || (defined(IP_RECVDSTADDR) && defined(IP_SENDSRCADDR)) || defined(IP_PKTINFO)
|
||||
int on = 1;
|
||||
@@ -1214,6 +1235,9 @@ if_is_ssl(const char* ifname, const char* port, int ssl_port,
|
||||
* @param use_systemd: if true, fetch sockets from systemd.
|
||||
* @param dnscrypt_port: dnscrypt service port number
|
||||
* @param dscp: DSCP to use.
|
||||
* @param sock_queue_timeout: the sock_queue_timeout from config. Seconds to
|
||||
* wait to discard if UDP packets have waited for long in the socket
|
||||
* buffer.
|
||||
* @return: returns false on error.
|
||||
*/
|
||||
static int
|
||||
@@ -1223,7 +1247,8 @@ ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp,
|
||||
struct config_strlist* tls_additional_port, int https_port,
|
||||
struct config_strlist* proxy_protocol_port,
|
||||
int* reuseport, int transparent, int tcp_mss, int freebind,
|
||||
int http2_nodelay, int use_systemd, int dnscrypt_port, int dscp)
|
||||
int http2_nodelay, int use_systemd, int dnscrypt_port, int dscp,
|
||||
int sock_queue_timeout)
|
||||
{
|
||||
int s, noip6=0;
|
||||
int is_https = if_is_https(ifname, port, https_port);
|
||||
@@ -1252,7 +1277,8 @@ ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp,
|
||||
if((s = make_sock_port(SOCK_DGRAM, ifname, port, hints, 1,
|
||||
&noip6, rcv, snd, reuseport, transparent,
|
||||
tcp_mss, nodelay, freebind, use_systemd, dscp, ub_sock)) == -1) {
|
||||
freeaddrinfo(ub_sock->addr);
|
||||
if(ub_sock->addr)
|
||||
freeaddrinfo(ub_sock->addr);
|
||||
free(ub_sock);
|
||||
if(noip6) {
|
||||
log_warn("IPv6 protocol not available");
|
||||
@@ -1263,15 +1289,20 @@ ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp,
|
||||
/* getting source addr packet info is highly non-portable */
|
||||
if(!set_recvpktinfo(s, hints->ai_family)) {
|
||||
sock_close(s);
|
||||
freeaddrinfo(ub_sock->addr);
|
||||
if(ub_sock->addr)
|
||||
freeaddrinfo(ub_sock->addr);
|
||||
free(ub_sock);
|
||||
return 0;
|
||||
}
|
||||
if (sock_queue_timeout && !set_recvtimestamp(s)) {
|
||||
log_warn("socket timestamping is not available");
|
||||
}
|
||||
if(!port_insert(list, s, is_dnscrypt
|
||||
?listen_type_udpancil_dnscrypt:listen_type_udpancil,
|
||||
is_pp2, ub_sock)) {
|
||||
sock_close(s);
|
||||
freeaddrinfo(ub_sock->addr);
|
||||
if(ub_sock->addr)
|
||||
freeaddrinfo(ub_sock->addr);
|
||||
free(ub_sock);
|
||||
return 0;
|
||||
}
|
||||
@@ -1283,7 +1314,8 @@ ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp,
|
||||
if((s = make_sock_port(SOCK_DGRAM, ifname, port, hints, 1,
|
||||
&noip6, rcv, snd, reuseport, transparent,
|
||||
tcp_mss, nodelay, freebind, use_systemd, dscp, ub_sock)) == -1) {
|
||||
freeaddrinfo(ub_sock->addr);
|
||||
if(ub_sock->addr)
|
||||
freeaddrinfo(ub_sock->addr);
|
||||
free(ub_sock);
|
||||
if(noip6) {
|
||||
log_warn("IPv6 protocol not available");
|
||||
@@ -1291,11 +1323,17 @@ ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp,
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
if (sock_queue_timeout && !set_recvtimestamp(s)) {
|
||||
log_warn("socket timestamping is not available");
|
||||
}
|
||||
if(!port_insert(list, s, is_dnscrypt
|
||||
?listen_type_udp_dnscrypt:listen_type_udp,
|
||||
?listen_type_udp_dnscrypt :
|
||||
(sock_queue_timeout ?
|
||||
listen_type_udpancil:listen_type_udp),
|
||||
is_pp2, ub_sock)) {
|
||||
sock_close(s);
|
||||
freeaddrinfo(ub_sock->addr);
|
||||
if(ub_sock->addr)
|
||||
freeaddrinfo(ub_sock->addr);
|
||||
free(ub_sock);
|
||||
return 0;
|
||||
}
|
||||
@@ -1318,7 +1356,8 @@ ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp,
|
||||
if((s = make_sock_port(SOCK_STREAM, ifname, port, hints, 1,
|
||||
&noip6, 0, 0, reuseport, transparent, tcp_mss, nodelay,
|
||||
freebind, use_systemd, dscp, ub_sock)) == -1) {
|
||||
freeaddrinfo(ub_sock->addr);
|
||||
if(ub_sock->addr)
|
||||
freeaddrinfo(ub_sock->addr);
|
||||
free(ub_sock);
|
||||
if(noip6) {
|
||||
/*log_warn("IPv6 protocol not available");*/
|
||||
@@ -1330,7 +1369,8 @@ ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp,
|
||||
verbose(VERB_ALGO, "setup TCP for SSL service");
|
||||
if(!port_insert(list, s, port_type, is_pp2, ub_sock)) {
|
||||
sock_close(s);
|
||||
freeaddrinfo(ub_sock->addr);
|
||||
if(ub_sock->addr)
|
||||
freeaddrinfo(ub_sock->addr);
|
||||
free(ub_sock);
|
||||
return 0;
|
||||
}
|
||||
@@ -1338,7 +1378,7 @@ ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp,
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* Add items to commpoint list in front.
|
||||
* @param c: commpoint to add.
|
||||
* @param front: listen struct.
|
||||
@@ -1389,7 +1429,7 @@ void listen_desetup_locks(void)
|
||||
}
|
||||
}
|
||||
|
||||
struct listen_dnsport*
|
||||
struct listen_dnsport*
|
||||
listen_create(struct comm_base* base, struct listen_port* ports,
|
||||
size_t bufsize, int tcp_accept_count, int tcp_idle_timeout,
|
||||
int harden_large_queries, uint32_t http_max_streams,
|
||||
@@ -1460,9 +1500,13 @@ listen_create(struct comm_base* base, struct listen_port* ports,
|
||||
}
|
||||
} else if(ports->ftype == listen_type_udpancil ||
|
||||
ports->ftype == listen_type_udpancil_dnscrypt) {
|
||||
#if defined(AF_INET6) && defined(IPV6_PKTINFO) && defined(HAVE_RECVMSG)
|
||||
cp = comm_point_create_udp_ancil(base, ports->fd,
|
||||
front->udp_buff, ports->pp2_enabled, cb,
|
||||
cb_arg, ports->socket);
|
||||
#else
|
||||
log_warn("This system does not support UDP ancilliary data.");
|
||||
#endif
|
||||
}
|
||||
if(!cp) {
|
||||
log_err("can't create commpoint");
|
||||
@@ -1525,10 +1569,10 @@ listen_list_delete(struct listen_list* list)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
void
|
||||
listen_delete(struct listen_dnsport* front)
|
||||
{
|
||||
if(!front)
|
||||
if(!front)
|
||||
return;
|
||||
listen_list_delete(front->cps);
|
||||
#ifdef USE_DNSCRYPT
|
||||
@@ -1802,7 +1846,7 @@ listening_ports_open(struct config_file* cfg, char** ifs, int num_ifs,
|
||||
reuseport, cfg->ip_transparent,
|
||||
cfg->tcp_mss, cfg->ip_freebind,
|
||||
cfg->http_nodelay, cfg->use_systemd,
|
||||
cfg->dnscrypt_port, cfg->ip_dscp)) {
|
||||
cfg->dnscrypt_port, cfg->ip_dscp, cfg->sock_queue_timeout)) {
|
||||
listening_ports_free(list);
|
||||
return NULL;
|
||||
}
|
||||
@@ -1819,7 +1863,7 @@ listening_ports_open(struct config_file* cfg, char** ifs, int num_ifs,
|
||||
reuseport, cfg->ip_transparent,
|
||||
cfg->tcp_mss, cfg->ip_freebind,
|
||||
cfg->http_nodelay, cfg->use_systemd,
|
||||
cfg->dnscrypt_port, cfg->ip_dscp)) {
|
||||
cfg->dnscrypt_port, cfg->ip_dscp, cfg->sock_queue_timeout)) {
|
||||
listening_ports_free(list);
|
||||
return NULL;
|
||||
}
|
||||
@@ -1838,7 +1882,7 @@ listening_ports_open(struct config_file* cfg, char** ifs, int num_ifs,
|
||||
reuseport, cfg->ip_transparent,
|
||||
cfg->tcp_mss, cfg->ip_freebind,
|
||||
cfg->http_nodelay, cfg->use_systemd,
|
||||
cfg->dnscrypt_port, cfg->ip_dscp)) {
|
||||
cfg->dnscrypt_port, cfg->ip_dscp, cfg->sock_queue_timeout)) {
|
||||
listening_ports_free(list);
|
||||
return NULL;
|
||||
}
|
||||
@@ -1854,7 +1898,7 @@ listening_ports_open(struct config_file* cfg, char** ifs, int num_ifs,
|
||||
reuseport, cfg->ip_transparent,
|
||||
cfg->tcp_mss, cfg->ip_freebind,
|
||||
cfg->http_nodelay, cfg->use_systemd,
|
||||
cfg->dnscrypt_port, cfg->ip_dscp)) {
|
||||
cfg->dnscrypt_port, cfg->ip_dscp, cfg->sock_queue_timeout)) {
|
||||
listening_ports_free(list);
|
||||
return NULL;
|
||||
}
|
||||
@@ -1872,7 +1916,7 @@ listening_ports_open(struct config_file* cfg, char** ifs, int num_ifs,
|
||||
reuseport, cfg->ip_transparent,
|
||||
cfg->tcp_mss, cfg->ip_freebind,
|
||||
cfg->http_nodelay, cfg->use_systemd,
|
||||
cfg->dnscrypt_port, cfg->ip_dscp)) {
|
||||
cfg->dnscrypt_port, cfg->ip_dscp, cfg->sock_queue_timeout)) {
|
||||
listening_ports_free(list);
|
||||
return NULL;
|
||||
}
|
||||
@@ -1888,7 +1932,7 @@ listening_ports_open(struct config_file* cfg, char** ifs, int num_ifs,
|
||||
reuseport, cfg->ip_transparent,
|
||||
cfg->tcp_mss, cfg->ip_freebind,
|
||||
cfg->http_nodelay, cfg->use_systemd,
|
||||
cfg->dnscrypt_port, cfg->ip_dscp)) {
|
||||
cfg->dnscrypt_port, cfg->ip_dscp, cfg->sock_queue_timeout)) {
|
||||
listening_ports_free(list);
|
||||
return NULL;
|
||||
}
|
||||
@@ -1908,7 +1952,8 @@ void listening_ports_free(struct listen_port* list)
|
||||
}
|
||||
/* rc_ports don't have ub_socket */
|
||||
if(list->socket) {
|
||||
freeaddrinfo(list->socket->addr);
|
||||
if(list->socket->addr)
|
||||
freeaddrinfo(list->socket->addr);
|
||||
free(list->socket);
|
||||
}
|
||||
free(list);
|
||||
@@ -1919,8 +1964,8 @@ 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) +
|
||||
size_t s = sizeof(*listen) + sizeof(*listen->base) +
|
||||
sizeof(*listen->udp_buff) +
|
||||
sldns_buffer_capacity(listen->udp_buff);
|
||||
#ifdef USE_DNSCRYPT
|
||||
s += sizeof(*listen->dnscrypt_udp_buff);
|
||||
@@ -2001,7 +2046,7 @@ void tcp_req_info_clear(struct tcp_req_info* req)
|
||||
}
|
||||
req->open_req_list = NULL;
|
||||
req->num_open_req = 0;
|
||||
|
||||
|
||||
/* free pending writable result packets */
|
||||
item = req->done_req_list;
|
||||
while(item) {
|
||||
@@ -2060,7 +2105,7 @@ tcp_req_info_setup_listen(struct tcp_req_info* req)
|
||||
wr = 1;
|
||||
if(!req->read_is_closed)
|
||||
rd = 1;
|
||||
|
||||
|
||||
if(wr) {
|
||||
req->cp->tcp_is_reading = 0;
|
||||
comm_point_stop_listening(req->cp);
|
||||
@@ -2196,7 +2241,7 @@ tcp_req_info_handle_readdone(struct tcp_req_info* req)
|
||||
}
|
||||
req->in_worker_handle = 0;
|
||||
/* it should be waiting in the mesh for recursion.
|
||||
* If mesh failed to add a new entry and called commpoint_drop_reply.
|
||||
* If mesh failed to add a new entry and called commpoint_drop_reply.
|
||||
* Then the mesh state has been cleared. */
|
||||
if(req->is_drop) {
|
||||
/* the reply has been dropped, stream has been closed. */
|
||||
@@ -2256,7 +2301,7 @@ tcp_req_info_add_result(struct tcp_req_info* req, uint8_t* buf, size_t len)
|
||||
last = req->done_req_list;
|
||||
while(last && last->next)
|
||||
last = last->next;
|
||||
|
||||
|
||||
/* create new element */
|
||||
item = (struct tcp_req_done_item*)malloc(sizeof(*item));
|
||||
if(!item) {
|
||||
@@ -2615,7 +2660,7 @@ static int http2_query_read_done(struct http2_session* h2_session,
|
||||
"buffer already assigned to stream");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/* the c->buffer might be used by mesh_send_reply and no be cleard
|
||||
* need to be cleared before use */
|
||||
sldns_buffer_clear(h2_session->c->buffer);
|
||||
|
||||
+18
-2
@@ -1308,6 +1308,7 @@ local_encode(struct query_info* qinfo, struct module_env* env,
|
||||
else rep.ns_numrrsets = 1;
|
||||
rep.rrset_count = 1;
|
||||
rep.rrsets = &rrset;
|
||||
rep.reason_bogus = LDNS_EDE_NONE;
|
||||
udpsize = edns->udp_size;
|
||||
edns->edns_version = EDNS_ADVERTISED_VERSION;
|
||||
edns->udp_size = EDNS_ADVERTISED_SIZE;
|
||||
@@ -1603,7 +1604,7 @@ local_zone_does_not_cover(struct local_zone* z, struct query_info* qinfo,
|
||||
struct local_data key;
|
||||
struct local_data* ld = NULL;
|
||||
struct local_rrset* lr = NULL;
|
||||
if(z->type == local_zone_always_transparent)
|
||||
if(z->type == local_zone_always_transparent || z->type == local_zone_block_a)
|
||||
return 1;
|
||||
if(z->type != local_zone_transparent
|
||||
&& z->type != local_zone_typetransparent
|
||||
@@ -1679,6 +1680,16 @@ local_zones_zone_answer(struct local_zone* z, struct module_env* env,
|
||||
} else if(lz_type == local_zone_typetransparent
|
||||
|| lz_type == local_zone_always_transparent) {
|
||||
/* no NODATA or NXDOMAINS for this zone type */
|
||||
return 0;
|
||||
} else if(lz_type == local_zone_block_a) {
|
||||
/* Return NODATA for all A queries */
|
||||
if(qinfo->qtype == LDNS_RR_TYPE_A) {
|
||||
local_error_encode(qinfo, env, edns, repinfo, buf, temp,
|
||||
LDNS_RCODE_NOERROR, (LDNS_RCODE_NOERROR|BIT_AA),
|
||||
LDNS_EDE_NONE, NULL);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
} else if(lz_type == local_zone_always_null) {
|
||||
/* 0.0.0.0 or ::0 or noerror/nodata for this zone type,
|
||||
@@ -1846,7 +1857,8 @@ local_zones_answer(struct local_zones* zones, struct module_env* env,
|
||||
if(z && (lzt == local_zone_transparent ||
|
||||
lzt == local_zone_typetransparent ||
|
||||
lzt == local_zone_inform ||
|
||||
lzt == local_zone_always_transparent) &&
|
||||
lzt == local_zone_always_transparent ||
|
||||
lzt == local_zone_block_a) &&
|
||||
local_zone_does_not_cover(z, qinfo, labs)) {
|
||||
lock_rw_unlock(&z->lock);
|
||||
z = NULL;
|
||||
@@ -1894,6 +1906,7 @@ local_zones_answer(struct local_zones* zones, struct module_env* env,
|
||||
|
||||
if(lzt != local_zone_always_refuse
|
||||
&& lzt != local_zone_always_transparent
|
||||
&& lzt != local_zone_block_a
|
||||
&& lzt != local_zone_always_nxdomain
|
||||
&& lzt != local_zone_always_nodata
|
||||
&& lzt != local_zone_always_deny
|
||||
@@ -1924,6 +1937,7 @@ const char* local_zone_type2str(enum localzone_type t)
|
||||
case local_zone_inform_deny: return "inform_deny";
|
||||
case local_zone_inform_redirect: return "inform_redirect";
|
||||
case local_zone_always_transparent: return "always_transparent";
|
||||
case local_zone_block_a: return "block_a";
|
||||
case local_zone_always_refuse: return "always_refuse";
|
||||
case local_zone_always_nxdomain: return "always_nxdomain";
|
||||
case local_zone_always_nodata: return "always_nodata";
|
||||
@@ -1958,6 +1972,8 @@ int local_zone_str2type(const char* type, enum localzone_type* t)
|
||||
*t = local_zone_inform_redirect;
|
||||
else if(strcmp(type, "always_transparent") == 0)
|
||||
*t = local_zone_always_transparent;
|
||||
else if(strcmp(type, "block_a") == 0)
|
||||
*t = local_zone_block_a;
|
||||
else if(strcmp(type, "always_refuse") == 0)
|
||||
*t = local_zone_always_refuse;
|
||||
else if(strcmp(type, "always_nxdomain") == 0)
|
||||
|
||||
@@ -88,6 +88,8 @@ enum localzone_type {
|
||||
local_zone_inform_redirect,
|
||||
/** resolve normally, even when there is local data */
|
||||
local_zone_always_transparent,
|
||||
/** resolve normally, even when there is local data but return NODATA for A queries */
|
||||
local_zone_block_a,
|
||||
/** answer with error, even when there is local data */
|
||||
local_zone_always_refuse,
|
||||
/** answer with nxdomain, even when there is local data */
|
||||
|
||||
+190
-204
@@ -4,22 +4,22 @@
|
||||
* Copyright (c) 2007, 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
|
||||
@@ -63,82 +63,13 @@
|
||||
#include "util/data/dname.h"
|
||||
#include "respip/respip.h"
|
||||
#include "services/listen_dnsport.h"
|
||||
#include "util/timeval_func.h"
|
||||
|
||||
#ifdef CLIENT_SUBNET
|
||||
#include "edns-subnet/subnetmod.h"
|
||||
#include "edns-subnet/edns-subnet.h"
|
||||
#endif
|
||||
|
||||
/** subtract timers and the values do not overflow or become negative */
|
||||
static void
|
||||
timeval_subtract(struct timeval* d, const struct timeval* end, const struct timeval* start)
|
||||
{
|
||||
#ifndef S_SPLINT_S
|
||||
time_t end_usec = end->tv_usec;
|
||||
d->tv_sec = end->tv_sec - start->tv_sec;
|
||||
if(end_usec < start->tv_usec) {
|
||||
end_usec += 1000000;
|
||||
d->tv_sec--;
|
||||
}
|
||||
d->tv_usec = end_usec - start->tv_usec;
|
||||
#endif
|
||||
}
|
||||
|
||||
/** add timers and the values do not overflow or become negative */
|
||||
static void
|
||||
timeval_add(struct timeval* d, const struct timeval* add)
|
||||
{
|
||||
#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++;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/** divide sum of timers to get average */
|
||||
static void
|
||||
timeval_divide(struct timeval* avg, const struct timeval* sum, size_t d)
|
||||
{
|
||||
#ifndef S_SPLINT_S
|
||||
size_t leftover;
|
||||
if(d <= 0) {
|
||||
avg->tv_sec = 0;
|
||||
avg->tv_usec = 0;
|
||||
return;
|
||||
}
|
||||
avg->tv_sec = sum->tv_sec / d;
|
||||
avg->tv_usec = sum->tv_usec / d;
|
||||
/* handle fraction from seconds divide */
|
||||
leftover = sum->tv_sec - avg->tv_sec*d;
|
||||
if(leftover <= 0)
|
||||
leftover = 0;
|
||||
avg->tv_usec += (((long long)leftover)*((long long)1000000))/d;
|
||||
if(avg->tv_sec < 0)
|
||||
avg->tv_sec = 0;
|
||||
if(avg->tv_usec < 0)
|
||||
avg->tv_usec = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
/** histogram compare of time values */
|
||||
static int
|
||||
timeval_smaller(const struct timeval* x, const struct timeval* y)
|
||||
{
|
||||
#ifndef S_SPLINT_S
|
||||
if(x->tv_sec < y->tv_sec)
|
||||
return 1;
|
||||
else if(x->tv_sec == y->tv_sec) {
|
||||
if(x->tv_usec <= y->tv_usec)
|
||||
return 1;
|
||||
else return 0;
|
||||
}
|
||||
else return 0;
|
||||
#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
|
||||
@@ -249,7 +180,7 @@ mesh_state_ref_compare(const void* ap, const void* bp)
|
||||
return mesh_state_compare(a->s, b->s);
|
||||
}
|
||||
|
||||
struct mesh_area*
|
||||
struct mesh_area*
|
||||
mesh_create(struct module_stack* stack, struct module_env* env)
|
||||
{
|
||||
struct mesh_area* mesh = calloc(1, sizeof(struct mesh_area));
|
||||
@@ -275,6 +206,7 @@ mesh_create(struct module_stack* stack, struct module_env* env)
|
||||
mesh->stats_jostled = 0;
|
||||
mesh->stats_dropped = 0;
|
||||
mesh->ans_expired = 0;
|
||||
mesh->ans_cachedb = 0;
|
||||
mesh->max_reply_states = env->cfg->num_queries_per_thread;
|
||||
mesh->max_forever_states = (mesh->max_reply_states+1)/2;
|
||||
#ifndef S_SPLINT_S
|
||||
@@ -298,7 +230,7 @@ mesh_delete_helper(rbnode_type* n)
|
||||
* traversal and rbtree rebalancing do not work together */
|
||||
}
|
||||
|
||||
void
|
||||
void
|
||||
mesh_delete(struct mesh_area* mesh)
|
||||
{
|
||||
if(!mesh)
|
||||
@@ -341,7 +273,7 @@ int mesh_make_new_space(struct mesh_area* mesh, sldns_buffer* qbuf)
|
||||
if(m && m->reply_list && m->list_select == mesh_jostle_list) {
|
||||
/* how old is it? */
|
||||
struct timeval age;
|
||||
timeval_subtract(&age, mesh->env->now_tv,
|
||||
timeval_subtract(&age, mesh->env->now_tv,
|
||||
&m->reply_list->start_time);
|
||||
if(timeval_smaller(&mesh->jostle_max, &age)) {
|
||||
/* its a goner */
|
||||
@@ -517,6 +449,8 @@ void mesh_new_client(struct mesh_area* mesh, struct query_info* qinfo,
|
||||
comm_point_send_reply(rep);
|
||||
return;
|
||||
}
|
||||
/* set detached (it is now) */
|
||||
mesh->num_detached_states++;
|
||||
if(unique)
|
||||
mesh_state_make_unique(s);
|
||||
s->s.rpz_passthru = rpz_passthru;
|
||||
@@ -525,13 +459,14 @@ void mesh_new_client(struct mesh_area* mesh, struct query_info* qinfo,
|
||||
s->s.edns_opts_front_in = edns_opt_copy_region(edns->opt_list_in,
|
||||
s->s.region);
|
||||
if(!s->s.edns_opts_front_in) {
|
||||
log_err("mesh_state_create: out of memory; SERVFAIL");
|
||||
log_err("edns_opt_copy_region: out of memory; SERVFAIL");
|
||||
if(!inplace_cb_reply_servfail_call(mesh->env, qinfo, NULL,
|
||||
NULL, LDNS_RCODE_SERVFAIL, edns, rep, mesh->env->scratch, mesh->env->now_tv))
|
||||
edns->opt_list_inplace_cb_out = NULL;
|
||||
error_encode(r_buffer, LDNS_RCODE_SERVFAIL,
|
||||
qinfo, qid, qflags, edns);
|
||||
comm_point_send_reply(rep);
|
||||
mesh_state_delete(&s->s);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -543,8 +478,6 @@ void mesh_new_client(struct mesh_area* mesh, struct query_info* qinfo,
|
||||
#endif
|
||||
rbtree_insert(&mesh->all, &s->node);
|
||||
log_assert(n != NULL);
|
||||
/* set detached (it is now) */
|
||||
mesh->num_detached_states++;
|
||||
added = 1;
|
||||
}
|
||||
if(!s->reply_list && !s->cb_list) {
|
||||
@@ -585,11 +518,11 @@ void mesh_new_client(struct mesh_area* mesh, struct query_info* qinfo,
|
||||
/* move to either the forever or the jostle_list */
|
||||
if(mesh->num_forever_states < mesh->max_forever_states) {
|
||||
mesh->num_forever_states ++;
|
||||
mesh_list_insert(s, &mesh->forever_first,
|
||||
mesh_list_insert(s, &mesh->forever_first,
|
||||
&mesh->forever_last);
|
||||
s->list_select = mesh_forever_list;
|
||||
} else {
|
||||
mesh_list_insert(s, &mesh->jostle_first,
|
||||
mesh_list_insert(s, &mesh->jostle_first,
|
||||
&mesh->jostle_last);
|
||||
s->list_select = mesh_jostle_list;
|
||||
}
|
||||
@@ -610,9 +543,9 @@ servfail_mem:
|
||||
return;
|
||||
}
|
||||
|
||||
int
|
||||
int
|
||||
mesh_new_callback(struct mesh_area* mesh, struct query_info* qinfo,
|
||||
uint16_t qflags, struct edns_data* edns, sldns_buffer* buf,
|
||||
uint16_t qflags, struct edns_data* edns, sldns_buffer* buf,
|
||||
uint16_t qid, mesh_cb_func_type cb, void* cb_arg, int rpz_passthru)
|
||||
{
|
||||
struct mesh_state* s = NULL;
|
||||
@@ -637,6 +570,8 @@ mesh_new_callback(struct mesh_area* mesh, struct query_info* qinfo,
|
||||
if(!s) {
|
||||
return 0;
|
||||
}
|
||||
/* set detached (it is now) */
|
||||
mesh->num_detached_states++;
|
||||
if(unique)
|
||||
mesh_state_make_unique(s);
|
||||
s->s.rpz_passthru = rpz_passthru;
|
||||
@@ -644,6 +579,7 @@ mesh_new_callback(struct mesh_area* mesh, struct query_info* qinfo,
|
||||
s->s.edns_opts_front_in = edns_opt_copy_region(edns->opt_list_in,
|
||||
s->s.region);
|
||||
if(!s->s.edns_opts_front_in) {
|
||||
mesh_state_delete(&s->s);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -654,8 +590,6 @@ mesh_new_callback(struct mesh_area* mesh, struct query_info* qinfo,
|
||||
#endif
|
||||
rbtree_insert(&mesh->all, &s->node);
|
||||
log_assert(n != NULL);
|
||||
/* set detached (it is now) */
|
||||
mesh->num_detached_states++;
|
||||
added = 1;
|
||||
}
|
||||
if(!s->reply_list && !s->cb_list) {
|
||||
@@ -672,6 +606,8 @@ mesh_new_callback(struct mesh_area* mesh, struct query_info* qinfo,
|
||||
}
|
||||
/* add serve expired timer if not already there */
|
||||
if(timeout && !mesh_serve_expired_init(s, timeout)) {
|
||||
if(added)
|
||||
mesh_state_delete(&s->s);
|
||||
return 0;
|
||||
}
|
||||
/* update statistics */
|
||||
@@ -773,7 +709,7 @@ static void mesh_schedule_prefetch(struct mesh_area* mesh,
|
||||
* attached its own ECS data. */
|
||||
static void mesh_schedule_prefetch_subnet(struct mesh_area* mesh,
|
||||
struct query_info* qinfo, uint16_t qflags, time_t leeway, int run,
|
||||
int rpz_passthru, struct comm_reply* rep, struct edns_option* edns_list)
|
||||
int rpz_passthru, struct sockaddr_storage* addr, struct edns_option* edns_list)
|
||||
{
|
||||
struct mesh_state* s = NULL;
|
||||
struct edns_option* opt = NULL;
|
||||
@@ -803,20 +739,10 @@ static void mesh_schedule_prefetch_subnet(struct mesh_area* mesh,
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
/* Fake the ECS data from the client's IP */
|
||||
struct ecs_data ecs;
|
||||
memset(&ecs, 0, sizeof(ecs));
|
||||
subnet_option_from_ss(&rep->client_addr, &ecs, mesh->env->cfg);
|
||||
if(ecs.subnet_validdata == 0) {
|
||||
log_err("prefetch_subnet subnet_option_from_ss: invalid data");
|
||||
return;
|
||||
}
|
||||
subnet_ecs_opt_list_append(&ecs, &s->s.edns_opts_front_in,
|
||||
&s->s, s->s.region);
|
||||
if(!s->s.edns_opts_front_in) {
|
||||
log_err("prefetch_subnet subnet_ecs_opt_list_append: out of memory");
|
||||
return;
|
||||
}
|
||||
/* Store the client's address. Later in the subnet module,
|
||||
* it is decided whether to include an ECS option or not.
|
||||
*/
|
||||
s->s.client_addr = *addr;
|
||||
}
|
||||
#ifdef UNBOUND_DEBUG
|
||||
n =
|
||||
@@ -863,14 +789,14 @@ static void mesh_schedule_prefetch_subnet(struct mesh_area* mesh,
|
||||
|
||||
void mesh_new_prefetch(struct mesh_area* mesh, struct query_info* qinfo,
|
||||
uint16_t qflags, time_t leeway, int rpz_passthru,
|
||||
struct comm_reply* rep, struct edns_option* opt_list)
|
||||
struct sockaddr_storage* addr, struct edns_option* opt_list)
|
||||
{
|
||||
(void)addr;
|
||||
(void)opt_list;
|
||||
(void)rep;
|
||||
#ifdef CLIENT_SUBNET
|
||||
if(rep)
|
||||
if(addr)
|
||||
mesh_schedule_prefetch_subnet(mesh, qinfo, qflags, leeway, 1,
|
||||
rpz_passthru, rep, opt_list);
|
||||
rpz_passthru, addr, opt_list);
|
||||
else
|
||||
#endif
|
||||
mesh_schedule_prefetch(mesh, qinfo, qflags, leeway, 1,
|
||||
@@ -900,7 +826,7 @@ mesh_state_create(struct module_env* env, struct query_info* qinfo,
|
||||
int i;
|
||||
if(!region)
|
||||
return NULL;
|
||||
mstate = (struct mesh_state*)regional_alloc(region,
|
||||
mstate = (struct mesh_state*)regional_alloc(region,
|
||||
sizeof(struct mesh_state));
|
||||
if(!mstate) {
|
||||
alloc_reg_release(env->alloc, region);
|
||||
@@ -970,19 +896,13 @@ mesh_state_create(struct module_env* env, struct query_info* qinfo,
|
||||
return mstate;
|
||||
}
|
||||
|
||||
int
|
||||
mesh_state_is_unique(struct mesh_state* mstate)
|
||||
{
|
||||
return mstate->unique != NULL;
|
||||
}
|
||||
|
||||
void
|
||||
mesh_state_make_unique(struct mesh_state* mstate)
|
||||
{
|
||||
mstate->unique = mstate;
|
||||
}
|
||||
|
||||
void
|
||||
void
|
||||
mesh_state_cleanup(struct mesh_state* mstate)
|
||||
{
|
||||
struct mesh_area* mesh;
|
||||
@@ -1028,7 +948,7 @@ mesh_state_cleanup(struct mesh_state* mstate)
|
||||
alloc_reg_release(mstate->s.env->alloc, mstate->s.region);
|
||||
}
|
||||
|
||||
void
|
||||
void
|
||||
mesh_state_delete(struct module_qstate* qstate)
|
||||
{
|
||||
struct mesh_area* mesh;
|
||||
@@ -1041,10 +961,10 @@ mesh_state_delete(struct module_qstate* qstate)
|
||||
mesh_detach_subs(&mstate->s);
|
||||
if(mstate->list_select == mesh_forever_list) {
|
||||
mesh->num_forever_states --;
|
||||
mesh_list_remove(mstate, &mesh->forever_first,
|
||||
mesh_list_remove(mstate, &mesh->forever_first,
|
||||
&mesh->forever_last);
|
||||
} else if(mstate->list_select == mesh_jostle_list) {
|
||||
mesh_list_remove(mstate, &mesh->jostle_first,
|
||||
mesh_list_remove(mstate, &mesh->jostle_first,
|
||||
&mesh->jostle_last);
|
||||
}
|
||||
if(!mstate->reply_list && !mstate->cb_list
|
||||
@@ -1116,7 +1036,7 @@ void mesh_detach_subs(struct module_qstate* qstate)
|
||||
if(!ref->s->reply_list && !ref->s->cb_list
|
||||
&& ref->s->super_set.count == 0) {
|
||||
mesh->num_detached_states++;
|
||||
log_assert(mesh->num_detached_states +
|
||||
log_assert(mesh->num_detached_states +
|
||||
mesh->num_reply_states <= mesh->all.count);
|
||||
}
|
||||
}
|
||||
@@ -1181,7 +1101,7 @@ int mesh_attach_sub(struct module_qstate* qstate, struct query_info* qinfo,
|
||||
if(!mesh_state_attachment(qstate->mesh_info, sub))
|
||||
return 0;
|
||||
/* if it was a duplicate attachment, the count was not zero before */
|
||||
if(!sub->reply_list && !sub->cb_list && was_detached &&
|
||||
if(!sub->reply_list && !sub->cb_list && was_detached &&
|
||||
sub->super_set.count == 1) {
|
||||
/* it used to be detached, before this one got added */
|
||||
log_assert(mesh->num_detached_states > 0);
|
||||
@@ -1251,7 +1171,7 @@ mesh_do_callback(struct mesh_state* m, int rcode, struct reply_info* rep,
|
||||
else secure = 0;
|
||||
if(!rep && rcode == LDNS_RCODE_NOERROR)
|
||||
rcode = LDNS_RCODE_SERVFAIL;
|
||||
if(!rcode && (rep->security == sec_status_bogus ||
|
||||
if(!rcode && rep && (rep->security == sec_status_bogus ||
|
||||
rep->security == sec_status_secure_sentinel_fail)) {
|
||||
if(!(reason = errinf_to_str_bogus(&m->s)))
|
||||
rcode = LDNS_RCODE_SERVFAIL;
|
||||
@@ -1277,13 +1197,15 @@ mesh_do_callback(struct mesh_state* m, int rcode, struct reply_info* rep,
|
||||
r->edns.udp_size = EDNS_ADVERTISED_SIZE;
|
||||
r->edns.ext_rcode = 0;
|
||||
r->edns.bits &= EDNS_DO;
|
||||
if(m->s.env->cfg->disable_edns_do && (r->edns.bits&EDNS_DO))
|
||||
r->edns.edns_present = 0;
|
||||
|
||||
if(!inplace_cb_reply_call(m->s.env, &m->s.qinfo, &m->s, rep,
|
||||
LDNS_RCODE_NOERROR, &r->edns, NULL, m->s.region, start_time) ||
|
||||
!reply_info_answer_encode(&m->s.qinfo, rep, r->qid,
|
||||
r->qflags, r->buf, 0, 1,
|
||||
m->s.env->scratch, udp_size, &r->edns,
|
||||
(int)(r->edns.bits & EDNS_DO), secure))
|
||||
!reply_info_answer_encode(&m->s.qinfo, rep, r->qid,
|
||||
r->qflags, r->buf, 0, 1,
|
||||
m->s.env->scratch, udp_size, &r->edns,
|
||||
(int)(r->edns.bits & EDNS_DO), secure))
|
||||
{
|
||||
fptr_ok(fptr_whitelist_mesh_cb(r->cb));
|
||||
(*r->cb)(r->cb_arg, LDNS_RCODE_SERVFAIL, r->buf,
|
||||
@@ -1291,7 +1213,8 @@ mesh_do_callback(struct mesh_state* m, int rcode, struct reply_info* rep,
|
||||
} else {
|
||||
fptr_ok(fptr_whitelist_mesh_cb(r->cb));
|
||||
(*r->cb)(r->cb_arg, LDNS_RCODE_NOERROR, r->buf,
|
||||
rep->security, reason, was_ratelimited);
|
||||
(rep?rep->security:sec_status_unchecked),
|
||||
reason, was_ratelimited);
|
||||
}
|
||||
}
|
||||
free(reason);
|
||||
@@ -1303,18 +1226,45 @@ static inline int
|
||||
mesh_is_rpz_respip_tcponly_action(struct mesh_state const* m)
|
||||
{
|
||||
struct respip_action_info const* respip_info = m->s.respip_action_info;
|
||||
return respip_info == NULL
|
||||
return (respip_info == NULL
|
||||
? 0
|
||||
: (respip_info->rpz_used
|
||||
&& !respip_info->rpz_disabled
|
||||
&& respip_info->action == respip_truncate);
|
||||
&& respip_info->action == respip_truncate))
|
||||
|| m->s.tcp_required;
|
||||
}
|
||||
|
||||
static inline int
|
||||
mesh_is_udp(struct mesh_reply const* r) {
|
||||
mesh_is_udp(struct mesh_reply const* r)
|
||||
{
|
||||
return r->query_reply.c->type == comm_udp;
|
||||
}
|
||||
|
||||
static inline void
|
||||
mesh_find_and_attach_ede_and_reason(struct mesh_state* m,
|
||||
struct reply_info* rep, struct mesh_reply* r)
|
||||
{
|
||||
/* OLD note:
|
||||
* During validation the EDE code can be received via two
|
||||
* code paths. One code path fills the reply_info EDE, and
|
||||
* the other fills it in the errinf_strlist. These paths
|
||||
* intersect at some points, but where is opaque due to
|
||||
* the complexity of the validator. At the time of writing
|
||||
* we make the choice to prefer the EDE from errinf_strlist
|
||||
* but a compelling reason to do otherwise is just as valid
|
||||
* NEW note:
|
||||
* The compelling reason is that with caching support, the value
|
||||
* in the reply_info is cached.
|
||||
* The reason members of the reply_info struct should be
|
||||
* updated as they are already cached. No reason to
|
||||
* try and find the EDE information in errinf anymore.
|
||||
*/
|
||||
if(rep->reason_bogus != LDNS_EDE_NONE) {
|
||||
edns_opt_list_append_ede(&r->edns.opt_list_out,
|
||||
m->s.region, rep->reason_bogus, rep->reason_bogus_str);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Send reply to mesh reply entry
|
||||
* @param m: mesh state to send it for.
|
||||
@@ -1346,7 +1296,7 @@ mesh_send_reply(struct mesh_state* m, int rcode, struct reply_info* rep,
|
||||
|
||||
/* examine security status */
|
||||
if(m->s.env->need_to_validate && (!(r->qflags&BIT_CD) ||
|
||||
m->s.env->cfg->ignore_cd) && rep &&
|
||||
m->s.env->cfg->ignore_cd) && rep &&
|
||||
(rep->security <= sec_status_bogus ||
|
||||
rep->security == sec_status_secure_sentinel_fail)) {
|
||||
rcode = LDNS_RCODE_SERVFAIL;
|
||||
@@ -1401,40 +1351,17 @@ mesh_send_reply(struct mesh_state* m, int rcode, struct reply_info* rep,
|
||||
if(!inplace_cb_reply_servfail_call(m->s.env, &m->s.qinfo, &m->s,
|
||||
rep, rcode, &r->edns, &r->query_reply, m->s.region, &r->start_time))
|
||||
r->edns.opt_list_inplace_cb_out = NULL;
|
||||
} else {
|
||||
} else {
|
||||
if(!inplace_cb_reply_call(m->s.env, &m->s.qinfo, &m->s, rep, rcode,
|
||||
&r->edns, &r->query_reply, m->s.region, &r->start_time))
|
||||
r->edns.opt_list_inplace_cb_out = NULL;
|
||||
}
|
||||
/* Send along EDE BOGUS EDNS0 option when answer is bogus */
|
||||
if(m->s.env->cfg->ede && rcode == LDNS_RCODE_SERVFAIL &&
|
||||
m->s.env->need_to_validate && (!(r->qflags&BIT_CD) ||
|
||||
m->s.env->cfg->ignore_cd) && rep &&
|
||||
(rep->security <= sec_status_bogus ||
|
||||
rep->security == sec_status_secure_sentinel_fail)) {
|
||||
char *reason = m->s.env->cfg->val_log_level >= 2
|
||||
? errinf_to_str_bogus(&m->s) : NULL;
|
||||
|
||||
/* During validation the EDE code can be received via two
|
||||
* code paths. One code path fills the reply_info EDE, and
|
||||
* the other fills it in the errinf_strlist. These paths
|
||||
* intersect at some points, but where is opaque due to
|
||||
* the complexity of the validator. At the time of writing
|
||||
* we make the choice to prefer the EDE from errinf_strlist
|
||||
* but a compelling reason to do otherwise is just as valid
|
||||
*/
|
||||
sldns_ede_code reason_bogus = errinf_to_reason_bogus(&m->s);
|
||||
if ((reason_bogus == LDNS_EDE_DNSSEC_BOGUS &&
|
||||
rep->reason_bogus != LDNS_EDE_NONE) ||
|
||||
reason_bogus == LDNS_EDE_NONE) {
|
||||
reason_bogus = rep->reason_bogus;
|
||||
}
|
||||
|
||||
if(reason_bogus != LDNS_EDE_NONE) {
|
||||
edns_opt_list_append_ede(&r->edns.opt_list_out,
|
||||
m->s.region, reason_bogus, reason);
|
||||
}
|
||||
free(reason);
|
||||
/* Send along EDE EDNS0 option when SERVFAILing; usually
|
||||
* DNSSEC validation failures */
|
||||
/* Since we are SERVFAILing here, CD bit and rep->security
|
||||
* is already handled. */
|
||||
if(m->s.env->cfg->ede && rep) {
|
||||
mesh_find_and_attach_ede_and_reason(m, rep, r);
|
||||
}
|
||||
error_encode(r_buffer, rcode, &m->s.qinfo, r->qid,
|
||||
r->qflags, &r->edns);
|
||||
@@ -1447,14 +1374,26 @@ mesh_send_reply(struct mesh_state* m, int rcode, struct reply_info* rep,
|
||||
r->edns.udp_size = EDNS_ADVERTISED_SIZE;
|
||||
r->edns.ext_rcode = 0;
|
||||
r->edns.bits &= EDNS_DO;
|
||||
if(m->s.env->cfg->disable_edns_do && (r->edns.bits&EDNS_DO))
|
||||
r->edns.edns_present = 0;
|
||||
m->s.qinfo.qname = r->qname;
|
||||
m->s.qinfo.local_alias = r->local_alias;
|
||||
|
||||
/* Attach EDE without SERVFAIL if the validation failed.
|
||||
* Need to explicitly check for rep->security otherwise failed
|
||||
* validation paths may attach to a secure answer. */
|
||||
if(m->s.env->cfg->ede && rep &&
|
||||
(rep->security <= sec_status_bogus ||
|
||||
rep->security == sec_status_secure_sentinel_fail)) {
|
||||
mesh_find_and_attach_ede_and_reason(m, rep, r);
|
||||
}
|
||||
|
||||
if(!inplace_cb_reply_call(m->s.env, &m->s.qinfo, &m->s, rep,
|
||||
LDNS_RCODE_NOERROR, &r->edns, &r->query_reply, m->s.region, &r->start_time) ||
|
||||
!reply_info_answer_encode(&m->s.qinfo, rep, r->qid,
|
||||
!reply_info_answer_encode(&m->s.qinfo, rep, r->qid,
|
||||
r->qflags, r_buffer, 0, 1, m->s.env->scratch,
|
||||
udp_size, &r->edns, (int)(r->edns.bits & EDNS_DO),
|
||||
secure))
|
||||
secure))
|
||||
{
|
||||
if(!inplace_cb_reply_servfail_call(m->s.env, &m->s.qinfo, &m->s,
|
||||
rep, LDNS_RCODE_SERVFAIL, &r->edns, &r->query_reply, m->s.region, &r->start_time))
|
||||
@@ -1503,6 +1442,7 @@ void mesh_query_done(struct mesh_state* mstate)
|
||||
struct reply_info* rep = (mstate->s.return_msg?
|
||||
mstate->s.return_msg->rep:NULL);
|
||||
struct timeval tv = {0, 0};
|
||||
int i = 0;
|
||||
/* No need for the serve expired timer anymore; we are going to reply. */
|
||||
if(mstate->s.serve_expired_data) {
|
||||
comm_timer_delete(mstate->s.serve_expired_data->timer);
|
||||
@@ -1522,6 +1462,7 @@ void mesh_query_done(struct mesh_state* mstate)
|
||||
}
|
||||
}
|
||||
for(r = mstate->reply_list; r; r = r->next) {
|
||||
i++;
|
||||
tv = r->start_time;
|
||||
|
||||
/* if a response-ip address block has been stored the
|
||||
@@ -1533,16 +1474,6 @@ void mesh_query_done(struct mesh_state* mstate)
|
||||
mstate->s.qinfo.qclass, r->local_alias,
|
||||
&r->query_reply.client_addr,
|
||||
r->query_reply.client_addrlen);
|
||||
if(mstate->s.env->cfg->stat_extended &&
|
||||
mstate->s.respip_action_info->rpz_used) {
|
||||
if(mstate->s.respip_action_info->rpz_disabled)
|
||||
mstate->s.env->mesh->rpz_action[RPZ_DISABLED_ACTION]++;
|
||||
if(mstate->s.respip_action_info->rpz_cname_override)
|
||||
mstate->s.env->mesh->rpz_action[RPZ_CNAME_OVERRIDE_ACTION]++;
|
||||
else
|
||||
mstate->s.env->mesh->rpz_action[respip_action_to_rpz_action(
|
||||
mstate->s.respip_action_info->action)]++;
|
||||
}
|
||||
}
|
||||
|
||||
/* if this query is determined to be dropped during the
|
||||
@@ -1573,6 +1504,27 @@ void mesh_query_done(struct mesh_state* mstate)
|
||||
prev_buffer = r_buffer;
|
||||
}
|
||||
}
|
||||
/* Account for each reply sent. */
|
||||
if(i > 0 && mstate->s.respip_action_info &&
|
||||
mstate->s.respip_action_info->addrinfo &&
|
||||
mstate->s.env->cfg->stat_extended &&
|
||||
mstate->s.respip_action_info->rpz_used) {
|
||||
if(mstate->s.respip_action_info->rpz_disabled)
|
||||
mstate->s.env->mesh->rpz_action[RPZ_DISABLED_ACTION] += i;
|
||||
if(mstate->s.respip_action_info->rpz_cname_override)
|
||||
mstate->s.env->mesh->rpz_action[RPZ_CNAME_OVERRIDE_ACTION] += i;
|
||||
else
|
||||
mstate->s.env->mesh->rpz_action[respip_action_to_rpz_action(
|
||||
mstate->s.respip_action_info->action)] += i;
|
||||
}
|
||||
if(!mstate->s.is_drop && i > 0) {
|
||||
if(mstate->s.env->cfg->stat_extended
|
||||
&& mstate->s.is_cachedb_answer) {
|
||||
mstate->s.env->mesh->ans_cachedb += i;
|
||||
}
|
||||
}
|
||||
|
||||
/* Mesh area accounting */
|
||||
if(mstate->reply_list) {
|
||||
mstate->reply_list = NULL;
|
||||
if(!mstate->reply_list && !mstate->cb_list) {
|
||||
@@ -1585,6 +1537,7 @@ void mesh_query_done(struct mesh_state* mstate)
|
||||
mstate->s.env->mesh->num_detached_states++;
|
||||
}
|
||||
mstate->replies_sent = 1;
|
||||
|
||||
while((c = mstate->cb_list) != NULL) {
|
||||
/* take this cb off the list; so that the list can be
|
||||
* changed, eg. by adds from the callback routine */
|
||||
@@ -1611,7 +1564,7 @@ void mesh_walk_supers(struct mesh_area* mesh, struct mesh_state* mstate)
|
||||
/* callback the function to inform super of result */
|
||||
fptr_ok(fptr_whitelist_mod_inform_super(
|
||||
mesh->mods.mod[ref->s->s.curmod]->inform_super));
|
||||
(*mesh->mods.mod[ref->s->s.curmod]->inform_super)(&mstate->s,
|
||||
(*mesh->mods.mod[ref->s->s.curmod]->inform_super)(&mstate->s,
|
||||
ref->s->s.curmod, &ref->s->s);
|
||||
/* copy state that is always relevant to super */
|
||||
copy_state_to_super(&mstate->s, ref->s->s.curmod, &ref->s->s);
|
||||
@@ -1635,7 +1588,7 @@ struct mesh_state* mesh_area_find(struct mesh_area* mesh,
|
||||
* desire aggregation).*/
|
||||
key.unique = NULL;
|
||||
key.s.client_info = cinfo;
|
||||
|
||||
|
||||
result = (struct mesh_state*)rbtree_search(&mesh->all, &key);
|
||||
return result;
|
||||
}
|
||||
@@ -1644,7 +1597,7 @@ int mesh_state_add_cb(struct mesh_state* s, struct edns_data* edns,
|
||||
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,
|
||||
struct mesh_cb* r = regional_alloc(s->s.region,
|
||||
sizeof(struct mesh_cb));
|
||||
if(!r)
|
||||
return 0;
|
||||
@@ -1776,7 +1729,7 @@ mesh_copy_qinfo(struct mesh_state* mstate, struct query_info** qinfop,
|
||||
* Handles module finished.
|
||||
* @param mesh: the mesh area.
|
||||
* @param mstate: currently active mesh state.
|
||||
* Deleted if finished, calls _done and _supers to
|
||||
* Deleted if finished, calls _done and _supers to
|
||||
* send replies to clients and inform other mesh states.
|
||||
* This in turn may create additional runnable mesh states.
|
||||
* @param s: state at which the current module exited.
|
||||
@@ -1810,7 +1763,7 @@ mesh_continue(struct mesh_area* mesh, struct mesh_state* mstate,
|
||||
}
|
||||
if(s == module_restart_next) {
|
||||
int curmod = mstate->s.curmod;
|
||||
for(; mstate->s.curmod < mesh->mods.num;
|
||||
for(; mstate->s.curmod < mesh->mods.num;
|
||||
mstate->s.curmod++) {
|
||||
fptr_ok(fptr_whitelist_mod_clear(
|
||||
mesh->mods.mod[mstate->s.curmod]->clear));
|
||||
@@ -1842,9 +1795,21 @@ mesh_continue(struct mesh_area* mesh, struct mesh_state* mstate,
|
||||
if(s == module_finished) {
|
||||
if(mstate->s.curmod == 0) {
|
||||
struct query_info* qinfo = NULL;
|
||||
struct edns_option* opt_list = NULL;
|
||||
struct sockaddr_storage addr;
|
||||
uint16_t qflags;
|
||||
int rpz_p = 0;
|
||||
|
||||
#ifdef CLIENT_SUBNET
|
||||
struct edns_option* ecs;
|
||||
if(mstate->s.need_refetch && mstate->reply_list &&
|
||||
modstack_find(&mesh->mods, "subnetcache") != -1 &&
|
||||
mstate->s.env->unique_mesh) {
|
||||
addr = mstate->reply_list->query_reply.client_addr;
|
||||
} else
|
||||
#endif
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
|
||||
mesh_query_done(mstate);
|
||||
mesh_walk_supers(mesh, mstate);
|
||||
|
||||
@@ -1854,13 +1819,28 @@ mesh_continue(struct mesh_area* mesh, struct mesh_state* mstate,
|
||||
* we need to make a copy of the query info here. */
|
||||
if(mstate->s.need_refetch) {
|
||||
mesh_copy_qinfo(mstate, &qinfo, &qflags);
|
||||
#ifdef CLIENT_SUBNET
|
||||
/* Make also a copy of the ecs option if any */
|
||||
if((ecs = edns_opt_list_find(
|
||||
mstate->s.edns_opts_front_in,
|
||||
mstate->s.env->cfg->client_subnet_opcode)) != NULL) {
|
||||
(void)edns_opt_list_append(&opt_list,
|
||||
ecs->opt_code, ecs->opt_len,
|
||||
ecs->opt_data,
|
||||
mstate->s.env->scratch);
|
||||
}
|
||||
#endif
|
||||
rpz_p = mstate->s.rpz_passthru;
|
||||
}
|
||||
|
||||
mesh_state_delete(&mstate->s);
|
||||
if(qinfo) {
|
||||
mesh_schedule_prefetch(mesh, qinfo, qflags,
|
||||
0, 1, rpz_p);
|
||||
mesh_state_delete(&mstate->s);
|
||||
mesh_new_prefetch(mesh, qinfo, qflags, 0,
|
||||
rpz_p,
|
||||
addr.ss_family!=AF_UNSPEC?&addr:NULL,
|
||||
opt_list);
|
||||
} else {
|
||||
mesh_state_delete(&mstate->s);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -1888,7 +1868,7 @@ void mesh_run(struct mesh_area* mesh, struct mesh_state* mstate,
|
||||
mstate->s.reply = NULL;
|
||||
regional_free_all(mstate->s.env->scratch);
|
||||
s = mstate->s.ext_state[mstate->s.curmod];
|
||||
verbose(VERB_ALGO, "mesh_run: %s module exit state is %s",
|
||||
verbose(VERB_ALGO, "mesh_run: %s module exit state is %s",
|
||||
mesh->mods.mod[mstate->s.curmod]->name, strextstate(s));
|
||||
e = NULL;
|
||||
if(mesh_continue(mesh, mstate, s, &ev))
|
||||
@@ -1908,14 +1888,14 @@ void mesh_run(struct mesh_area* mesh, struct mesh_state* mstate,
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
void
|
||||
mesh_log_list(struct mesh_area* mesh)
|
||||
{
|
||||
char buf[30];
|
||||
struct mesh_state* m;
|
||||
int num = 0;
|
||||
RBTREE_FOR(m, struct mesh_state*, &mesh->all) {
|
||||
snprintf(buf, sizeof(buf), "%d%s%s%s%s%s%s mod%d %s%s",
|
||||
snprintf(buf, sizeof(buf), "%d%s%s%s%s%s%s mod%d %s%s",
|
||||
num++, (m->s.is_priming)?"p":"", /* prime */
|
||||
(m->s.is_valrec)?"v":"", /* prime */
|
||||
(m->s.query_flags&BIT_RD)?"RD":"",
|
||||
@@ -1924,18 +1904,18 @@ mesh_log_list(struct mesh_area* mesh)
|
||||
(m->sub_set.count!=0)?"c":"", /* children */
|
||||
m->s.curmod, (m->reply_list)?"rep":"", /*hasreply*/
|
||||
(m->cb_list)?"cb":"" /* callbacks */
|
||||
);
|
||||
);
|
||||
log_query_info(VERB_ALGO, buf, &m->s.qinfo);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
void
|
||||
mesh_stats(struct mesh_area* mesh, const char* str)
|
||||
{
|
||||
verbose(VERB_DETAIL, "%s %u recursion states (%u with reply, "
|
||||
"%u detached), %u waiting replies, %u recursion replies "
|
||||
"sent, %d replies dropped, %d states jostled out",
|
||||
str, (unsigned)mesh->all.count,
|
||||
"sent, %d replies dropped, %d states jostled out",
|
||||
str, (unsigned)mesh->all.count,
|
||||
(unsigned)mesh->num_reply_states,
|
||||
(unsigned)mesh->num_detached_states,
|
||||
(unsigned)mesh->num_reply_addrs,
|
||||
@@ -1944,7 +1924,7 @@ mesh_stats(struct mesh_area* mesh, const char* str)
|
||||
(unsigned)mesh->stats_jostled);
|
||||
if(mesh->replies_sent > 0) {
|
||||
struct timeval avg;
|
||||
timeval_divide(&avg, &mesh->replies_sum_wait,
|
||||
timeval_divide(&avg, &mesh->replies_sum_wait,
|
||||
mesh->replies_sent);
|
||||
log_info("average recursion processing time "
|
||||
ARG_LL "d.%6.6d sec",
|
||||
@@ -1954,7 +1934,7 @@ mesh_stats(struct mesh_area* mesh, const char* str)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
void
|
||||
mesh_stats_clear(struct mesh_area* mesh)
|
||||
{
|
||||
if(!mesh)
|
||||
@@ -1968,12 +1948,13 @@ mesh_stats_clear(struct mesh_area* mesh)
|
||||
mesh->ans_secure = 0;
|
||||
mesh->ans_bogus = 0;
|
||||
mesh->ans_expired = 0;
|
||||
mesh->ans_cachedb = 0;
|
||||
memset(&mesh->ans_rcode[0], 0, sizeof(size_t)*UB_STATS_RCODE_NUM);
|
||||
memset(&mesh->rpz_action[0], 0, sizeof(size_t)*UB_STATS_RPZ_ACTION_NUM);
|
||||
mesh->ans_nodata = 0;
|
||||
}
|
||||
|
||||
size_t
|
||||
size_t
|
||||
mesh_get_mem(struct mesh_area* mesh)
|
||||
{
|
||||
struct mesh_state* m;
|
||||
@@ -1987,7 +1968,7 @@ mesh_get_mem(struct mesh_area* mesh)
|
||||
return s;
|
||||
}
|
||||
|
||||
int
|
||||
int
|
||||
mesh_detect_cycle(struct module_qstate* qstate, struct query_info* qinfo,
|
||||
uint16_t flags, int prime, int valrec)
|
||||
{
|
||||
@@ -2104,6 +2085,7 @@ mesh_serve_expired_callback(void* arg)
|
||||
struct timeval tv = {0, 0};
|
||||
int must_validate = (!(qstate->query_flags&BIT_CD)
|
||||
|| qstate->env->cfg->ignore_cd) && qstate->env->need_to_validate;
|
||||
int i = 0;
|
||||
if(!qstate->serve_expired_data) return;
|
||||
verbose(VERB_ALGO, "Serve expired: Trying to reply with expired data");
|
||||
comm_timer_delete(qstate->serve_expired_data->timer);
|
||||
@@ -2175,6 +2157,7 @@ mesh_serve_expired_callback(void* arg)
|
||||
log_dns_msg("Serve expired lookup", &qstate->qinfo, msg->rep);
|
||||
|
||||
for(r = mstate->reply_list; r; r = r->next) {
|
||||
i++;
|
||||
tv = r->start_time;
|
||||
|
||||
/* If address info is returned, it means the action should be an
|
||||
@@ -2184,16 +2167,6 @@ mesh_serve_expired_callback(void* arg)
|
||||
qstate->qinfo.qtype, qstate->qinfo.qclass,
|
||||
r->local_alias, &r->query_reply.client_addr,
|
||||
r->query_reply.client_addrlen);
|
||||
|
||||
if(qstate->env->cfg->stat_extended && actinfo.rpz_used) {
|
||||
if(actinfo.rpz_disabled)
|
||||
qstate->env->mesh->rpz_action[RPZ_DISABLED_ACTION]++;
|
||||
if(actinfo.rpz_cname_override)
|
||||
qstate->env->mesh->rpz_action[RPZ_CNAME_OVERRIDE_ACTION]++;
|
||||
else
|
||||
qstate->env->mesh->rpz_action[
|
||||
respip_action_to_rpz_action(actinfo.action)]++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Add EDE Stale Answer (RCF8914). Ignore global ede as this is
|
||||
@@ -2213,11 +2186,23 @@ mesh_serve_expired_callback(void* arg)
|
||||
tcp_req_info_remove_mesh_state(r->query_reply.c->tcp_req_info, mstate);
|
||||
prev = r;
|
||||
prev_buffer = r_buffer;
|
||||
|
||||
/* Account for each reply sent. */
|
||||
mesh->ans_expired++;
|
||||
|
||||
}
|
||||
/* Account for each reply sent. */
|
||||
if(i > 0) {
|
||||
mesh->ans_expired += i;
|
||||
if(actinfo.addrinfo && qstate->env->cfg->stat_extended &&
|
||||
actinfo.rpz_used) {
|
||||
if(actinfo.rpz_disabled)
|
||||
qstate->env->mesh->rpz_action[RPZ_DISABLED_ACTION] += i;
|
||||
if(actinfo.rpz_cname_override)
|
||||
qstate->env->mesh->rpz_action[RPZ_CNAME_OVERRIDE_ACTION] += i;
|
||||
else
|
||||
qstate->env->mesh->rpz_action[
|
||||
respip_action_to_rpz_action(actinfo.action)] += i;
|
||||
}
|
||||
}
|
||||
|
||||
/* Mesh area accounting */
|
||||
if(mstate->reply_list) {
|
||||
mstate->reply_list = NULL;
|
||||
if(!mstate->reply_list && !mstate->cb_list) {
|
||||
@@ -2228,6 +2213,7 @@ mesh_serve_expired_callback(void* arg)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
while((c = mstate->cb_list) != NULL) {
|
||||
/* take this cb off the list; so that the list can be
|
||||
* changed, eg. by adds from the callback routine */
|
||||
|
||||
+4
-10
@@ -114,6 +114,8 @@ struct mesh_area {
|
||||
size_t stats_dropped;
|
||||
/** stats, number of expired replies sent */
|
||||
size_t ans_expired;
|
||||
/** stats, number of cached replies from cachedb */
|
||||
size_t ans_cachedb;
|
||||
/** number of replies sent */
|
||||
size_t replies_sent;
|
||||
/** sum of waiting times for the replies */
|
||||
@@ -335,13 +337,13 @@ int mesh_new_callback(struct mesh_area* mesh, struct query_info* qinfo,
|
||||
* @param leeway: TTL leeway what to expire earlier for this update.
|
||||
* @param rpz_passthru: if true, the rpz passthru was previously found and
|
||||
* further rpz processing is stopped.
|
||||
* @param rep: comm_reply for the client; to be used when subnet is enabled.
|
||||
* @param addr: sockaddr_storage for the client; to be used with subnet.
|
||||
* @param opt_list: edns opt_list from the client; to be used when subnet is
|
||||
* enabled.
|
||||
*/
|
||||
void mesh_new_prefetch(struct mesh_area* mesh, struct query_info* qinfo,
|
||||
uint16_t qflags, time_t leeway, int rpz_passthru,
|
||||
struct comm_reply* rep, struct edns_option* opt_list);
|
||||
struct sockaddr_storage* addr, struct edns_option* opt_list);
|
||||
|
||||
/**
|
||||
* Handle new event from the wire. A serviced query has returned.
|
||||
@@ -478,14 +480,6 @@ 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.
|
||||
* A unique mesh state uses it's unique member to point to itself, else NULL.
|
||||
* @param mstate: mesh state to check.
|
||||
* @return true if the mesh state is unique, false otherwise.
|
||||
*/
|
||||
int mesh_state_is_unique(struct mesh_state* mstate);
|
||||
|
||||
/**
|
||||
* Make a mesh state unique.
|
||||
* A unique mesh state uses it's unique member to point to itself.
|
||||
|
||||
+7
-3
@@ -120,12 +120,16 @@ modstack_config(struct module_stack* stack, const char* module_conf)
|
||||
stack->mod[i] = module_factory(&module_conf);
|
||||
if(!stack->mod[i]) {
|
||||
char md[256];
|
||||
char * s = md;
|
||||
snprintf(md, sizeof(md), "%s", module_conf);
|
||||
if(strchr(md, ' ')) *(strchr(md, ' ')) = 0;
|
||||
if(strchr(md, '\t')) *(strchr(md, '\t')) = 0;
|
||||
/* Leading spaces are present on errors. */
|
||||
while (*s && isspace((unsigned char)*s))
|
||||
s++;
|
||||
if(strchr(s, ' ')) *(strchr(s, ' ')) = 0;
|
||||
if(strchr(s, '\t')) *(strchr(s, '\t')) = 0;
|
||||
log_err("Unknown value in module-config, module: '%s'."
|
||||
" This module is not present (not compiled in),"
|
||||
" See the list of linked modules with unbound -V", md);
|
||||
" See the list of linked modules with unbound -V", s);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -550,9 +550,28 @@ reuse_tcp_find(struct outside_network* outnet, struct sockaddr_storage* addr,
|
||||
log_assert(&key_p.reuse != (struct reuse_tcp*)result);
|
||||
log_assert(&key_p != ((struct reuse_tcp*)result)->pending);
|
||||
}
|
||||
|
||||
/* It is possible that we search for something before the first element
|
||||
* in the tree. Replace a null pointer with the first element.
|
||||
*/
|
||||
if (!result) {
|
||||
verbose(VERB_CLIENT, "reuse_tcp_find: taking first");
|
||||
result = rbtree_first(&outnet->tcp_reuse);
|
||||
}
|
||||
|
||||
/* not found, return null */
|
||||
if(!result || result == RBTREE_NULL)
|
||||
return NULL;
|
||||
|
||||
/* It is possible that we got the previous address, but that the
|
||||
* address we are looking for is in the tree. If the address we got
|
||||
* is less than the address we are looking, then take the next entry.
|
||||
*/
|
||||
if (reuse_cmp_addrportssl(result->key, &key_p.reuse) < 0) {
|
||||
verbose(VERB_CLIENT, "reuse_tcp_find: key too low");
|
||||
result = rbtree_next(result);
|
||||
}
|
||||
|
||||
verbose(VERB_CLIENT, "reuse_tcp_find check inexact match");
|
||||
/* inexact match, find one of possibly several connections to the
|
||||
* same destination address, with the correct port, ssl, and
|
||||
@@ -620,6 +639,15 @@ outnet_tcp_take_into_use(struct waiting_tcp* w)
|
||||
log_assert(w->addrlen > 0);
|
||||
pend->c->tcp_do_toggle_rw = 0;
|
||||
pend->c->tcp_do_close = 0;
|
||||
|
||||
/* Consistency check, if we have ssl_upstream but no sslctx, then
|
||||
* log an error and return failure.
|
||||
*/
|
||||
if (w->ssl_upstream && !w->outnet->sslctx) {
|
||||
log_err("SSL upstream requested but no SSL context");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* open socket */
|
||||
s = outnet_get_tcp_fd(&w->addr, w->addrlen, w->outnet->tcp_mss, w->outnet->ip_dscp);
|
||||
|
||||
|
||||
+208
-32
@@ -1188,6 +1188,22 @@ rpz_find_zone(struct local_zones* zones, uint8_t* qname, size_t qname_len, uint1
|
||||
return z;
|
||||
}
|
||||
|
||||
/** Find entry for RR type in the list of rrsets for the clientip. */
|
||||
static struct local_rrset*
|
||||
rpz_find_synthesized_rrset(uint16_t qtype,
|
||||
struct clientip_synthesized_rr* data)
|
||||
{
|
||||
struct local_rrset* cursor = data->data;
|
||||
while( cursor != NULL) {
|
||||
struct packed_rrset_key* packed_rrset = &cursor->rrset->rk;
|
||||
if(htons(qtype) == packed_rrset->type) {
|
||||
return cursor;
|
||||
}
|
||||
cursor = cursor->next;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove RR from RPZ's local-data
|
||||
* @param z: local-zone for RPZ, holding write lock
|
||||
@@ -1270,15 +1286,15 @@ rpz_rrset_delete_rr(struct resp_addr* raddr, uint16_t rr_type, uint8_t* rdata,
|
||||
|
||||
}
|
||||
|
||||
/** Remove RR from RPZ's local-zone */
|
||||
/** Remove RR from rpz localzones structure */
|
||||
static void
|
||||
rpz_remove_qname_trigger(struct rpz* r, uint8_t* dname, size_t dnamelen,
|
||||
enum rpz_action a, uint16_t rr_type, uint16_t rr_class,
|
||||
uint8_t* rdatawl, size_t rdatalen)
|
||||
rpz_remove_local_zones_trigger(struct local_zones* zones, uint8_t* dname,
|
||||
size_t dnamelen, enum rpz_action a, uint16_t rr_type,
|
||||
uint16_t rr_class, uint8_t* rdatawl, size_t rdatalen)
|
||||
{
|
||||
struct local_zone* z;
|
||||
int delete_zone = 1;
|
||||
z = rpz_find_zone(r->local_zones, dname, dnamelen, rr_class,
|
||||
z = rpz_find_zone(zones, dname, dnamelen, rr_class,
|
||||
1 /* only exact */, 1 /* wr lock */, 1 /* keep lock*/);
|
||||
if(!z) {
|
||||
verbose(VERB_ALGO, "rpz: cannot remove RR from IXFR, "
|
||||
@@ -1290,15 +1306,24 @@ rpz_remove_qname_trigger(struct rpz* r, uint8_t* dname, size_t dnamelen,
|
||||
dnamelen, rr_type, rdatawl, rdatalen);
|
||||
else if(a != localzone_type_to_rpz_action(z->type)) {
|
||||
lock_rw_unlock(&z->lock);
|
||||
lock_rw_unlock(&r->local_zones->lock);
|
||||
lock_rw_unlock(&zones->lock);
|
||||
return;
|
||||
}
|
||||
lock_rw_unlock(&z->lock);
|
||||
if(delete_zone) {
|
||||
local_zones_del_zone(r->local_zones, z);
|
||||
local_zones_del_zone(zones, z);
|
||||
}
|
||||
lock_rw_unlock(&r->local_zones->lock);
|
||||
return;
|
||||
lock_rw_unlock(&zones->lock);
|
||||
}
|
||||
|
||||
/** Remove RR from RPZ's local-zone */
|
||||
static void
|
||||
rpz_remove_qname_trigger(struct rpz* r, uint8_t* dname, size_t dnamelen,
|
||||
enum rpz_action a, uint16_t rr_type, uint16_t rr_class,
|
||||
uint8_t* rdatawl, size_t rdatalen)
|
||||
{
|
||||
rpz_remove_local_zones_trigger(r->local_zones, dname, dnamelen,
|
||||
a, rr_type, rr_class, rdatawl, rdatalen);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1335,15 +1360,159 @@ rpz_remove_response_ip_trigger(struct rpz* r, uint8_t* dname, size_t dnamelen,
|
||||
lock_rw_unlock(&r->respip_set->lock);
|
||||
}
|
||||
|
||||
/** find and remove type from list of local_rrset entries*/
|
||||
static void
|
||||
del_local_rrset_from_list(struct local_rrset** list_head, uint16_t dtype)
|
||||
{
|
||||
struct local_rrset* prev=NULL, *p=*list_head;
|
||||
while(p && ntohs(p->rrset->rk.type) != dtype) {
|
||||
prev = p;
|
||||
p = p->next;
|
||||
}
|
||||
if(!p)
|
||||
return; /* rrset type not found */
|
||||
/* unlink it */
|
||||
if(prev) prev->next = p->next;
|
||||
else *list_head = p->next;
|
||||
/* no memory recycling for zone deletions ... */
|
||||
}
|
||||
|
||||
/** Delete client-ip trigger RR from its RRset and perhaps also the rrset
|
||||
* from the linked list. Returns if the local data is empty and the node can
|
||||
* be deleted too, or not. */
|
||||
static int rpz_remove_clientip_rr(struct clientip_synthesized_rr* node,
|
||||
uint16_t rr_type, uint8_t* rdatawl, size_t rdatalen)
|
||||
{
|
||||
struct local_rrset* rrset;
|
||||
struct packed_rrset_data* d;
|
||||
size_t index;
|
||||
rrset = rpz_find_synthesized_rrset(rr_type, node);
|
||||
if(rrset == NULL)
|
||||
return 0; /* type not found, ignore */
|
||||
d = (struct packed_rrset_data*)rrset->rrset->entry.data;
|
||||
if(!packed_rrset_find_rr(d, rdatawl, rdatalen, &index))
|
||||
return 0; /* RR not found, ignore */
|
||||
if(d->count == 1) {
|
||||
/* regional alloc'd */
|
||||
/* delete the type entry from the list */
|
||||
del_local_rrset_from_list(&node->data, rr_type);
|
||||
/* if the list is empty, the node can be removed too */
|
||||
if(node->data == NULL)
|
||||
return 1;
|
||||
} else if (d->count > 1) {
|
||||
if(!local_rrset_remove_rr(d, index))
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** remove trigger RR from clientip_syntheized set tree. */
|
||||
static void
|
||||
rpz_clientip_remove_trigger_rr(struct clientip_synthesized_rrset* set,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen, int net,
|
||||
enum rpz_action a, uint16_t rr_type, uint8_t* rdatawl, size_t rdatalen)
|
||||
{
|
||||
struct clientip_synthesized_rr* node;
|
||||
int delete_node = 1;
|
||||
|
||||
lock_rw_wrlock(&set->lock);
|
||||
node = (struct clientip_synthesized_rr*)addr_tree_find(&set->entries,
|
||||
addr, addrlen, net);
|
||||
if(node == NULL) {
|
||||
/* netblock not found */
|
||||
verbose(VERB_ALGO, "rpz: cannot remove RR from IXFR, "
|
||||
"RPZ address, netblock not found");
|
||||
lock_rw_unlock(&set->lock);
|
||||
return;
|
||||
}
|
||||
lock_rw_wrlock(&node->lock);
|
||||
if(a == RPZ_LOCAL_DATA_ACTION) {
|
||||
/* remove RR, signal whether entry can be removed */
|
||||
delete_node = rpz_remove_clientip_rr(node, rr_type, rdatawl,
|
||||
rdatalen);
|
||||
} else if(a != node->action) {
|
||||
/* ignore the RR with different action specification */
|
||||
delete_node = 0;
|
||||
}
|
||||
if(delete_node) {
|
||||
rbtree_delete(&set->entries, node->node.node.key);
|
||||
}
|
||||
lock_rw_unlock(&set->lock);
|
||||
lock_rw_unlock(&node->lock);
|
||||
if(delete_node) {
|
||||
lock_rw_destroy(&node->lock);
|
||||
}
|
||||
}
|
||||
|
||||
/** Remove clientip trigger RR from RPZ. */
|
||||
static void
|
||||
rpz_remove_clientip_trigger(struct rpz* r, uint8_t* dname, size_t dnamelen,
|
||||
enum rpz_action a, uint16_t rr_type, uint8_t* rdatawl, size_t rdatalen)
|
||||
{
|
||||
struct sockaddr_storage addr;
|
||||
socklen_t addrlen;
|
||||
int net, af;
|
||||
if(a == RPZ_INVALID_ACTION)
|
||||
return;
|
||||
if(!netblockdnametoaddr(dname, dnamelen, &addr, &addrlen, &net, &af))
|
||||
return;
|
||||
rpz_clientip_remove_trigger_rr(r->client_set, &addr, addrlen, net,
|
||||
a, rr_type, rdatawl, rdatalen);
|
||||
}
|
||||
|
||||
/** Remove nsip trigger RR from RPZ. */
|
||||
static void
|
||||
rpz_remove_nsip_trigger(struct rpz* r, uint8_t* dname, size_t dnamelen,
|
||||
enum rpz_action a, uint16_t rr_type, uint8_t* rdatawl, size_t rdatalen)
|
||||
{
|
||||
struct sockaddr_storage addr;
|
||||
socklen_t addrlen;
|
||||
int net, af;
|
||||
if(a == RPZ_INVALID_ACTION)
|
||||
return;
|
||||
if(!netblockdnametoaddr(dname, dnamelen, &addr, &addrlen, &net, &af))
|
||||
return;
|
||||
rpz_clientip_remove_trigger_rr(r->ns_set, &addr, addrlen, net,
|
||||
a, rr_type, rdatawl, rdatalen);
|
||||
}
|
||||
|
||||
/** Remove nsdname trigger RR from RPZ. */
|
||||
static void
|
||||
rpz_remove_nsdname_trigger(struct rpz* r, uint8_t* dname, size_t dnamelen,
|
||||
enum rpz_action a, uint16_t rr_type, uint16_t rr_class,
|
||||
uint8_t* rdatawl, size_t rdatalen)
|
||||
{
|
||||
uint8_t* dname_stripped = NULL;
|
||||
size_t dnamelen_stripped = 0;
|
||||
if(a == RPZ_INVALID_ACTION)
|
||||
return;
|
||||
if(!rpz_strip_nsdname_suffix(dname, dnamelen, &dname_stripped,
|
||||
&dnamelen_stripped))
|
||||
return;
|
||||
rpz_remove_local_zones_trigger(r->nsdname_zones, dname_stripped,
|
||||
dnamelen_stripped, a, rr_type, rr_class, rdatawl, rdatalen);
|
||||
free(dname_stripped);
|
||||
}
|
||||
|
||||
void
|
||||
rpz_remove_rr(struct rpz* r, size_t aznamelen, uint8_t* dname, size_t dnamelen,
|
||||
uint16_t rr_type, uint16_t rr_class, uint8_t* rdatawl, size_t rdatalen)
|
||||
rpz_remove_rr(struct rpz* r, uint8_t* azname, size_t aznamelen, uint8_t* dname,
|
||||
size_t dnamelen, uint16_t rr_type, uint16_t rr_class, uint8_t* rdatawl,
|
||||
size_t rdatalen)
|
||||
{
|
||||
size_t policydnamelen;
|
||||
enum rpz_trigger t;
|
||||
enum rpz_action a;
|
||||
uint8_t* policydname;
|
||||
|
||||
if(rpz_type_ignored(rr_type)) {
|
||||
/* this rpz action is not valid, eg. this is the SOA or NS RR */
|
||||
return;
|
||||
}
|
||||
if(!dname_subdomain_c(dname, azname)) {
|
||||
/* not subdomain of the RPZ zone. */
|
||||
return;
|
||||
}
|
||||
|
||||
if(!(policydname = calloc(1, LDNS_MAX_DOMAINLEN + 1)))
|
||||
return;
|
||||
|
||||
@@ -1358,13 +1527,28 @@ rpz_remove_rr(struct rpz* r, size_t aznamelen, uint8_t* dname, size_t dnamelen,
|
||||
return;
|
||||
}
|
||||
t = rpz_dname_to_trigger(policydname, policydnamelen);
|
||||
if(t == RPZ_INVALID_TRIGGER) {
|
||||
/* skipping invalid trigger */
|
||||
free(policydname);
|
||||
return;
|
||||
}
|
||||
if(t == RPZ_QNAME_TRIGGER) {
|
||||
rpz_remove_qname_trigger(r, policydname, policydnamelen, a,
|
||||
rr_type, rr_class, rdatawl, rdatalen);
|
||||
} else if(t == RPZ_RESPONSE_IP_TRIGGER) {
|
||||
rpz_remove_response_ip_trigger(r, policydname, policydnamelen,
|
||||
a, rr_type, rdatawl, rdatalen);
|
||||
} else if(t == RPZ_CLIENT_IP_TRIGGER) {
|
||||
rpz_remove_clientip_trigger(r, policydname, policydnamelen, a,
|
||||
rr_type, rdatawl, rdatalen);
|
||||
} else if(t == RPZ_NSIP_TRIGGER) {
|
||||
rpz_remove_nsip_trigger(r, policydname, policydnamelen, a,
|
||||
rr_type, rdatawl, rdatalen);
|
||||
} else if(t == RPZ_NSDNAME_TRIGGER) {
|
||||
rpz_remove_nsdname_trigger(r, policydname, policydnamelen, a,
|
||||
rr_type, rr_class, rdatawl, rdatalen);
|
||||
}
|
||||
/* else it was an unsupported trigger, also skipped. */
|
||||
free(policydname);
|
||||
}
|
||||
|
||||
@@ -1563,21 +1747,6 @@ rpz_local_encode(struct module_env* env, struct query_info* qinfo,
|
||||
return 1;
|
||||
}
|
||||
|
||||
static struct local_rrset*
|
||||
rpz_find_synthesized_rrset(uint16_t qtype,
|
||||
struct clientip_synthesized_rr* data)
|
||||
{
|
||||
struct local_rrset* cursor = data->data;
|
||||
while( cursor != NULL) {
|
||||
struct packed_rrset_key* packed_rrset = &cursor->rrset->rk;
|
||||
if(htons(qtype) == packed_rrset->type) {
|
||||
return cursor;
|
||||
}
|
||||
cursor = cursor->next;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/** allocate SOA record ubrrsetkey in region */
|
||||
static struct ub_packed_rrset_key*
|
||||
make_soa_ubrrset(struct auth_zone* auth_zone, struct auth_rrset* soa,
|
||||
@@ -1713,7 +1882,8 @@ rpz_synthesize_nodata(struct rpz* ATTR_UNUSED(r), struct module_qstate* ms,
|
||||
0, /* ns */
|
||||
0, /* ar */
|
||||
0, /* total */
|
||||
sec_status_insecure);
|
||||
sec_status_insecure,
|
||||
LDNS_EDE_NONE);
|
||||
if(msg->rep)
|
||||
msg->rep->authoritative = 1;
|
||||
if(!rpz_add_soa(msg->rep, ms, az))
|
||||
@@ -1742,7 +1912,8 @@ rpz_synthesize_nxdomain(struct rpz* r, struct module_qstate* ms,
|
||||
0, /* ns */
|
||||
0, /* ar */
|
||||
0, /* total */
|
||||
sec_status_insecure);
|
||||
sec_status_insecure,
|
||||
LDNS_EDE_NONE);
|
||||
if(msg->rep)
|
||||
msg->rep->authoritative = 1;
|
||||
if(!rpz_add_soa(msg->rep, ms, az))
|
||||
@@ -1772,7 +1943,8 @@ rpz_synthesize_localdata_from_rrset(struct rpz* ATTR_UNUSED(r), struct module_qs
|
||||
0, /* ns */
|
||||
0, /* ar */
|
||||
1, /* total */
|
||||
sec_status_insecure);
|
||||
sec_status_insecure,
|
||||
LDNS_EDE_NONE);
|
||||
if(new_reply_info == NULL) {
|
||||
log_err("out of memory");
|
||||
return NULL;
|
||||
@@ -1990,7 +2162,7 @@ rpz_apply_nsip_trigger(struct module_qstate* ms, struct rpz* r,
|
||||
case RPZ_TCP_ONLY_ACTION:
|
||||
/* basically a passthru here but the tcp-only will be
|
||||
* honored before the query gets sent. */
|
||||
ms->respip_action_info->action = respip_truncate;
|
||||
ms->tcp_required = 1;
|
||||
ret = NULL;
|
||||
break;
|
||||
case RPZ_DROP_ACTION:
|
||||
@@ -2045,7 +2217,7 @@ rpz_apply_nsdname_trigger(struct module_qstate* ms, struct rpz* r,
|
||||
case RPZ_TCP_ONLY_ACTION:
|
||||
/* basically a passthru here but the tcp-only will be
|
||||
* honored before the query gets sent. */
|
||||
ms->respip_action_info->action = respip_truncate;
|
||||
ms->tcp_required = 1;
|
||||
ret = NULL;
|
||||
break;
|
||||
case RPZ_DROP_ACTION:
|
||||
@@ -2256,7 +2428,7 @@ struct dns_msg* rpz_callback_from_iterator_cname(struct module_qstate* ms,
|
||||
case RPZ_TCP_ONLY_ACTION:
|
||||
/* basically a passthru here but the tcp-only will be
|
||||
* honored before the query gets sent. */
|
||||
ms->respip_action_info->action = respip_truncate;
|
||||
ms->tcp_required = 1;
|
||||
ret = NULL;
|
||||
break;
|
||||
case RPZ_DROP_ACTION:
|
||||
@@ -2276,6 +2448,10 @@ struct dns_msg* rpz_callback_from_iterator_cname(struct module_qstate* ms,
|
||||
rpz_action_to_string(localzone_type_to_rpz_action(lzt)));
|
||||
ret = NULL;
|
||||
}
|
||||
if(r->log)
|
||||
log_rpz_apply("qname", (z?z->name:NULL), NULL,
|
||||
localzone_type_to_rpz_action(lzt),
|
||||
&is->qchase, NULL, ms, r->log_name);
|
||||
lock_rw_unlock(&z->lock);
|
||||
lock_rw_unlock(&a->lock);
|
||||
return ret;
|
||||
|
||||
+7
-9
@@ -84,10 +84,11 @@ enum rpz_action {
|
||||
RPZ_CNAME_OVERRIDE_ACTION, /* RPZ CNAME action override*/
|
||||
};
|
||||
|
||||
struct clientip_synthesized_rrset{
|
||||
struct clientip_synthesized_rrset {
|
||||
struct regional* region;
|
||||
struct rbtree_type entries;
|
||||
lock_rw_type lock; /* lock on the respip tree */
|
||||
/** lock on the entries tree */
|
||||
lock_rw_type lock;
|
||||
};
|
||||
|
||||
struct clientip_synthesized_rr {
|
||||
@@ -95,10 +96,6 @@ struct clientip_synthesized_rr {
|
||||
struct addr_tree_node node;
|
||||
/** lock on the node item */
|
||||
lock_rw_type lock;
|
||||
/** tag bitlist */
|
||||
uint8_t* taglist;
|
||||
/** length of the taglist (in bytes) */
|
||||
size_t taglen;
|
||||
/** action for this address span */
|
||||
enum rpz_action action;
|
||||
/** "local data" for this node */
|
||||
@@ -152,6 +149,7 @@ int rpz_insert_rr(struct rpz* r, uint8_t* azname, size_t aznamelen, uint8_t* dna
|
||||
/**
|
||||
* Delete policy matching RR, used for IXFR.
|
||||
* @param r: the rpz to add the policy to.
|
||||
* @param azname: dname of the auth-zone
|
||||
* @param aznamelen: the length of the auth-zone name
|
||||
* @param dname: dname of the RR
|
||||
* @param dnamelen: length of the dname
|
||||
@@ -160,9 +158,9 @@ int rpz_insert_rr(struct rpz* r, uint8_t* azname, size_t aznamelen, uint8_t* dna
|
||||
* @param rdatawl: rdata of the RR, prepended with the rdata size
|
||||
* @param rdatalen: length if the RR, including the prepended rdata size
|
||||
*/
|
||||
void rpz_remove_rr(struct rpz* r, size_t aznamelen, uint8_t* dname,
|
||||
size_t dnamelen, uint16_t rr_type, uint16_t rr_class, uint8_t* rdatawl,
|
||||
size_t rdatalen);
|
||||
void rpz_remove_rr(struct rpz* r, uint8_t* azname, size_t aznamelen,
|
||||
uint8_t* dname, size_t dnamelen, uint16_t rr_type, uint16_t rr_class,
|
||||
uint8_t* rdatawl, size_t rdatalen);
|
||||
|
||||
/**
|
||||
* Walk over the RPZ zones to find and apply a QNAME trigger policy.
|
||||
|
||||
+10
-2
@@ -702,7 +702,11 @@ sldns_get_rr_type_by_name(const char *name)
|
||||
|
||||
/* TYPEXX representation */
|
||||
if (strlen(name) > 4 && strncasecmp(name, "TYPE", 4) == 0) {
|
||||
return atoi(name + 4);
|
||||
unsigned int a = atoi(name + 4);
|
||||
if (a > LDNS_RR_TYPE_LAST) {
|
||||
return (enum sldns_enum_rr_type)0;
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
/* Normal types */
|
||||
@@ -740,7 +744,11 @@ sldns_get_rr_class_by_name(const char *name)
|
||||
|
||||
/* CLASSXX representation */
|
||||
if (strlen(name) > 5 && strncasecmp(name, "CLASS", 5) == 0) {
|
||||
return atoi(name + 5);
|
||||
unsigned int a = atoi(name + 5);
|
||||
if (a > LDNS_RR_CLASS_LAST) {
|
||||
return (enum sldns_enum_rr_class)0;
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
/* Normal types */
|
||||
|
||||
+8
-3
@@ -196,8 +196,8 @@ enum sldns_enum_rr_type
|
||||
LDNS_RR_TYPE_OPENPGPKEY = 61, /* RFC 7929 */
|
||||
LDNS_RR_TYPE_CSYNC = 62, /* RFC 7477 */
|
||||
LDNS_RR_TYPE_ZONEMD = 63, /* draft-ietf-dnsop-dns-zone-digest-12 */
|
||||
LDNS_RR_TYPE_SVCB = 64, /* draft-ietf-dnsop-svcb-https-04 */
|
||||
LDNS_RR_TYPE_HTTPS = 65, /* draft-ietf-dnsop-svcb-https-04 */
|
||||
LDNS_RR_TYPE_SVCB = 64, /* draft-ietf-dnsop-svcb-https-04 */
|
||||
LDNS_RR_TYPE_HTTPS = 65, /* draft-ietf-dnsop-svcb-https-04 */
|
||||
|
||||
LDNS_RR_TYPE_SPF = 99, /* RFC 4408 */
|
||||
|
||||
@@ -433,10 +433,12 @@ enum sldns_enum_edns_option
|
||||
LDNS_EDNS_DHU = 6, /* RFC6975 */
|
||||
LDNS_EDNS_N3U = 7, /* RFC6975 */
|
||||
LDNS_EDNS_CLIENT_SUBNET = 8, /* RFC7871 */
|
||||
LDNS_EDNS_COOKIE = 10, /* RFC7873 */
|
||||
LDNS_EDNS_KEEPALIVE = 11, /* draft-ietf-dnsop-edns-tcp-keepalive*/
|
||||
LDNS_EDNS_PADDING = 12, /* RFC7830 */
|
||||
LDNS_EDNS_EDE = 15, /* RFC8914 */
|
||||
LDNS_EDNS_CLIENT_TAG = 16 /* draft-bellis-dnsop-edns-tags-01 */
|
||||
LDNS_EDNS_CLIENT_TAG = 16, /* draft-bellis-dnsop-edns-tags-01 */
|
||||
LDNS_EDNS_UNBOUND_CACHEDB_TESTFRAME_TEST = 65534
|
||||
};
|
||||
typedef enum sldns_enum_edns_option sldns_edns_option;
|
||||
|
||||
@@ -482,6 +484,9 @@ typedef enum sldns_enum_ede_code sldns_ede_code;
|
||||
#define LDNS_TSIG_ERROR_BADNAME 20
|
||||
#define LDNS_TSIG_ERROR_BADALG 21
|
||||
|
||||
/** DNS Cookie extended rcode */
|
||||
#define LDNS_EXT_RCODE_BADCOOKIE 23
|
||||
|
||||
/**
|
||||
* Contains all information about resource record types.
|
||||
*
|
||||
|
||||
+75
-40
@@ -357,7 +357,7 @@ rrinternal_get_delims(sldns_rdf_type rdftype, size_t r_cnt, size_t r_max)
|
||||
break;
|
||||
default : break;
|
||||
}
|
||||
return "\n\t ";
|
||||
return "\n\t ";
|
||||
}
|
||||
|
||||
/* Syntactic sugar for sldns_rr_new_frm_str_internal */
|
||||
@@ -448,7 +448,7 @@ rrinternal_parse_unknown(sldns_buffer* strbuf, char* token, size_t token_len,
|
||||
sldns_buffer_position(strbuf));
|
||||
}
|
||||
hex_data_size = (size_t)atoi(token);
|
||||
if(hex_data_size > LDNS_MAX_RDFLEN ||
|
||||
if(hex_data_size > LDNS_MAX_RDFLEN ||
|
||||
*rr_cur_len + hex_data_size > *rr_len) {
|
||||
return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL,
|
||||
sldns_buffer_position(strbuf));
|
||||
@@ -567,7 +567,7 @@ sldns_parse_rdf_token(sldns_buffer* strbuf, char* token, size_t token_len,
|
||||
/* check if not quoted yet, and we have encountered quotes */
|
||||
if(!*quoted && sldns_rdf_type_maybe_quoted(rdftype) &&
|
||||
slen >= 2 &&
|
||||
(token[0] == '"' || token[0] == '\'') &&
|
||||
(token[0] == '"' || token[0] == '\'') &&
|
||||
(token[slen-1] == '"' || token[slen-1] == '\'')) {
|
||||
/* move token two smaller (quotes) with endnull */
|
||||
memmove(token, token+1, slen-2);
|
||||
@@ -698,7 +698,7 @@ static int sldns_str2wire_check_svcbparams(uint8_t* rdata, uint16_t rdata_len)
|
||||
mandatory = svcparams[i];
|
||||
}
|
||||
|
||||
/* 4. verify that all the SvcParamKeys in mandatory are present */
|
||||
/* Verify that all the SvcParamKeys in mandatory are present */
|
||||
if(mandatory) {
|
||||
/* Divide by sizeof(uint16_t)*/
|
||||
uint16_t mandatory_nkeys = sldns_read_uint16(mandatory + 2) / sizeof(uint16_t);
|
||||
@@ -785,7 +785,7 @@ rrinternal_parse_rdata(sldns_buffer* strbuf, char* token, size_t token_len,
|
||||
token[2]=='\t')) {
|
||||
was_unknown_rr_format = 1;
|
||||
if((status=rrinternal_parse_unknown(strbuf, token,
|
||||
token_len, rr, rr_len, &rr_cur_len,
|
||||
token_len, rr, rr_len, &rr_cur_len,
|
||||
pre_data_pos)) != 0)
|
||||
return status;
|
||||
} else if(token_strlen > 0 || quoted) {
|
||||
@@ -844,7 +844,7 @@ rrinternal_parse_rdata(sldns_buffer* strbuf, char* token, size_t token_len,
|
||||
if (rr_type == LDNS_RR_TYPE_SVCB || rr_type == LDNS_RR_TYPE_HTTPS) {
|
||||
size_t rdata_len = rr_cur_len - dname_len - 10;
|
||||
uint8_t *rdata = rr+dname_len + 10;
|
||||
|
||||
|
||||
/* skip 1st rdata field SvcPriority (uint16_t) */
|
||||
if (rdata_len < sizeof(uint16_t))
|
||||
return LDNS_WIREPARSE_ERR_OK;
|
||||
@@ -1123,36 +1123,40 @@ sldns_str2wire_svcparam_key_lookup(const char *key, size_t key_len)
|
||||
return key_value;
|
||||
|
||||
} else switch (key_len) {
|
||||
case sizeof("mandatory")-1:
|
||||
if (!strncmp(key, "mandatory", sizeof("mandatory")-1))
|
||||
return SVCB_KEY_MANDATORY;
|
||||
if (!strncmp(key, "echconfig", sizeof("echconfig")-1))
|
||||
return SVCB_KEY_ECH; /* allow "echconfig" as well as "ech" */
|
||||
case 3:
|
||||
if (!strncmp(key, "ech", key_len))
|
||||
return SVCB_KEY_ECH;
|
||||
break;
|
||||
|
||||
case sizeof("alpn")-1:
|
||||
if (!strncmp(key, "alpn", sizeof("alpn")-1))
|
||||
case 4:
|
||||
if (!strncmp(key, "alpn", key_len))
|
||||
return SVCB_KEY_ALPN;
|
||||
if (!strncmp(key, "port", sizeof("port")-1))
|
||||
if (!strncmp(key, "port", key_len))
|
||||
return SVCB_KEY_PORT;
|
||||
break;
|
||||
|
||||
case sizeof("no-default-alpn")-1:
|
||||
if (!strncmp( key , "no-default-alpn"
|
||||
, sizeof("no-default-alpn")-1))
|
||||
return SVCB_KEY_NO_DEFAULT_ALPN;
|
||||
case 7:
|
||||
if (!strncmp(key, "dohpath", key_len))
|
||||
return SVCB_KEY_DOHPATH;
|
||||
break;
|
||||
|
||||
case sizeof("ipv4hint")-1:
|
||||
if (!strncmp(key, "ipv4hint", sizeof("ipv4hint")-1))
|
||||
case 8:
|
||||
if (!strncmp(key, "ipv4hint", key_len))
|
||||
return SVCB_KEY_IPV4HINT;
|
||||
if (!strncmp(key, "ipv6hint", sizeof("ipv6hint")-1))
|
||||
if (!strncmp(key, "ipv6hint", key_len))
|
||||
return SVCB_KEY_IPV6HINT;
|
||||
break;
|
||||
|
||||
case sizeof("ech")-1:
|
||||
if (!strncmp(key, "ech", sizeof("ech")-1))
|
||||
return SVCB_KEY_ECH;
|
||||
case 9:
|
||||
if (!strncmp(key, "mandatory", key_len))
|
||||
return SVCB_KEY_MANDATORY;
|
||||
if (!strncmp(key, "echconfig", key_len))
|
||||
return SVCB_KEY_ECH; /* allow "echconfig" as well as "ech" */
|
||||
break;
|
||||
|
||||
case 15:
|
||||
if (!strncmp(key, "no-default-alpn", key_len))
|
||||
return SVCB_KEY_NO_DEFAULT_ALPN;
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -1477,7 +1481,7 @@ sldns_str2wire_svcbparam_alpn_value(const char* val,
|
||||
size_t str_len;
|
||||
size_t dst_len;
|
||||
size_t val_len;
|
||||
|
||||
|
||||
val_len = strlen(val);
|
||||
|
||||
if (val_len > sizeof(unescaped_dst)) {
|
||||
@@ -1511,7 +1515,34 @@ sldns_str2wire_svcbparam_alpn_value(const char* val,
|
||||
sldns_write_uint16(rd + 2, dst_len);
|
||||
memcpy(rd + 4, unescaped_dst, dst_len);
|
||||
*rd_len = 4 + dst_len;
|
||||
|
||||
|
||||
return LDNS_WIREPARSE_ERR_OK;
|
||||
}
|
||||
|
||||
static int
|
||||
sldns_str2wire_svcbparam_dohpath_value(const char* val,
|
||||
uint8_t* rd, size_t* rd_len)
|
||||
{
|
||||
size_t val_len;
|
||||
|
||||
/* RFC6570#section-2.1
|
||||
* "The characters outside of expressions in a URI Template string are
|
||||
* intended to be copied literally"
|
||||
* Practically this means we do not have to look for "double escapes"
|
||||
* like in the alpn value list.
|
||||
*/
|
||||
|
||||
val_len = strlen(val);
|
||||
|
||||
if (*rd_len < 4 + val_len) {
|
||||
return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL;
|
||||
}
|
||||
|
||||
sldns_write_uint16(rd, SVCB_KEY_DOHPATH);
|
||||
sldns_write_uint16(rd + 2, val_len);
|
||||
memcpy(rd + 4, val, val_len);
|
||||
*rd_len = 4 + val_len;
|
||||
|
||||
return LDNS_WIREPARSE_ERR_OK;
|
||||
}
|
||||
|
||||
@@ -1535,6 +1566,7 @@ sldns_str2wire_svcparam_value(const char *key, size_t key_len,
|
||||
case SVCB_KEY_PORT:
|
||||
case SVCB_KEY_IPV4HINT:
|
||||
case SVCB_KEY_IPV6HINT:
|
||||
case SVCB_KEY_DOHPATH:
|
||||
return LDNS_WIREPARSE_ERR_SVCB_MISSING_PARAM;
|
||||
#endif
|
||||
default:
|
||||
@@ -1566,6 +1598,8 @@ sldns_str2wire_svcparam_value(const char *key, size_t key_len,
|
||||
return sldns_str2wire_svcbparam_ech_value(val, rd, rd_len);
|
||||
case SVCB_KEY_ALPN:
|
||||
return sldns_str2wire_svcbparam_alpn_value(val, rd, rd_len);
|
||||
case SVCB_KEY_DOHPATH:
|
||||
return sldns_str2wire_svcbparam_dohpath_value(val, rd, rd_len);
|
||||
default:
|
||||
str_len = strlen(val);
|
||||
if (*rd_len < 4 + str_len)
|
||||
@@ -1593,7 +1627,7 @@ static int sldns_str2wire_svcparam_buf(const char* str, uint8_t* rd, size_t* rd_
|
||||
/* case: key=value */
|
||||
if (eq_pos != NULL && eq_pos[1]) {
|
||||
val_in = eq_pos + 1;
|
||||
|
||||
|
||||
/* unescape characters and "" blocks */
|
||||
if (*val_in == '"') {
|
||||
val_in++;
|
||||
@@ -1610,11 +1644,11 @@ static int sldns_str2wire_svcparam_buf(const char* str, uint8_t* rd, size_t* rd_
|
||||
}
|
||||
*val_out = 0;
|
||||
|
||||
return sldns_str2wire_svcparam_value(str, eq_pos - str,
|
||||
unescaped_val[0] ? unescaped_val : NULL, rd, rd_len);
|
||||
return sldns_str2wire_svcparam_value(str, eq_pos - str,
|
||||
unescaped_val[0] ? unescaped_val : NULL, rd, rd_len);
|
||||
}
|
||||
/* case: key= */
|
||||
else if (eq_pos != NULL && !(eq_pos[1])) {
|
||||
else if (eq_pos != NULL && !(eq_pos[1])) {
|
||||
return sldns_str2wire_svcparam_value(str, eq_pos - str, NULL, rd, rd_len);
|
||||
}
|
||||
/* case: key */
|
||||
@@ -2425,12 +2459,13 @@ int sldns_str2wire_wks_buf(const char* str, uint8_t* rd, size_t* len)
|
||||
(void)strlcpy(proto_str, token, sizeof(proto_str));
|
||||
} else {
|
||||
int serv_port;
|
||||
struct servent *serv = getservbyname(token, proto_str);
|
||||
if(serv) serv_port=(int)ntohs((uint16_t)serv->s_port);
|
||||
if(atoi(token) != 0) serv_port=atoi(token);
|
||||
else if(strcmp(token, "0") == 0) serv_port=0;
|
||||
else if(strcasecmp(token, "domain")==0) serv_port=53;
|
||||
else {
|
||||
serv_port = atoi(token);
|
||||
if(serv_port == 0 && strcmp(token, "0") != 0) {
|
||||
struct servent *serv = getservbyname(token, proto_str);
|
||||
if(serv) serv_port=(int)ntohs((uint16_t)serv->s_port);
|
||||
else {
|
||||
#ifdef HAVE_ENDSERVENT
|
||||
endservent();
|
||||
#endif
|
||||
@@ -2440,16 +2475,16 @@ int sldns_str2wire_wks_buf(const char* str, uint8_t* rd, size_t* len)
|
||||
return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX,
|
||||
sldns_buffer_position(&strbuf));
|
||||
}
|
||||
if(serv_port < 0 || serv_port > 65535) {
|
||||
}
|
||||
if(serv_port < 0 || serv_port > 65535) {
|
||||
#ifdef HAVE_ENDSERVENT
|
||||
endservent();
|
||||
endservent();
|
||||
#endif
|
||||
#ifdef HAVE_ENDPROTOENT
|
||||
endprotoent();
|
||||
endprotoent();
|
||||
#endif
|
||||
return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX,
|
||||
sldns_buffer_position(&strbuf));
|
||||
}
|
||||
return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX,
|
||||
sldns_buffer_position(&strbuf));
|
||||
}
|
||||
if(rd_len < 1+serv_port/8+1) {
|
||||
/* bitmap is larger, init new bytes at 0 */
|
||||
|
||||
+3
-1
@@ -38,7 +38,8 @@ struct sldns_struct_lookup_table;
|
||||
#define SVCB_KEY_IPV4HINT 4
|
||||
#define SVCB_KEY_ECH 5
|
||||
#define SVCB_KEY_IPV6HINT 6
|
||||
#define SVCPARAMKEY_COUNT 7
|
||||
#define SVCB_KEY_DOHPATH 7
|
||||
#define SVCPARAMKEY_COUNT 8
|
||||
|
||||
#define MAX_NUMBER_OF_SVCPARAMS 64
|
||||
|
||||
@@ -236,6 +237,7 @@ uint8_t* sldns_wirerr_get_rdatawl(uint8_t* rr, size_t len, size_t dname_len);
|
||||
#define LDNS_WIREPARSE_ERR_SVCB_NO_DEFAULT_ALPN_VALUE 385
|
||||
#define LDNS_WIREPARSE_ERR_SVCPARAM_BROKEN_RDATA 386
|
||||
|
||||
|
||||
/**
|
||||
* Get reference to a constant string for the (parse) error.
|
||||
* @param e: error return value
|
||||
|
||||
+93
-8
@@ -159,7 +159,7 @@ static sldns_lookup_table sldns_wireparse_errors_data[] = {
|
||||
"Mandatory SvcParamKey is missing"},
|
||||
{ LDNS_WIREPARSE_ERR_SVCB_MANDATORY_DUPLICATE_KEY,
|
||||
"Keys in SvcParam mandatory MUST be unique" },
|
||||
{ LDNS_WIREPARSE_ERR_SVCB_MANDATORY_IN_MANDATORY,
|
||||
{ LDNS_WIREPARSE_ERR_SVCB_MANDATORY_IN_MANDATORY,
|
||||
"mandatory MUST not be included as mandatory parameter" },
|
||||
{ LDNS_WIREPARSE_ERR_SVCB_PORT_VALUE_SYNTAX,
|
||||
"Could not parse port SvcParamValue" },
|
||||
@@ -192,6 +192,7 @@ static sldns_lookup_table sldns_edns_options_data[] = {
|
||||
{ 6, "DHU" },
|
||||
{ 7, "N3U" },
|
||||
{ 8, "edns-client-subnet" },
|
||||
{ 10, "COOKIE" },
|
||||
{ 11, "edns-tcp-keepalive"},
|
||||
{ 12, "Padding" },
|
||||
{ 15, "EDE"},
|
||||
@@ -199,6 +200,38 @@ static sldns_lookup_table sldns_edns_options_data[] = {
|
||||
};
|
||||
sldns_lookup_table* sldns_edns_options = sldns_edns_options_data;
|
||||
|
||||
/* From RFC8914 5.2 Table 3, the "Extended DNS Error Codes" registry. */
|
||||
static sldns_lookup_table sldns_edns_ede_codes_data[] = {
|
||||
{ LDNS_EDE_NONE, "None" },
|
||||
{ LDNS_EDE_OTHER, "Other Error" },
|
||||
{ LDNS_EDE_UNSUPPORTED_DNSKEY_ALG, "Unsupported DNSKEY Algorithm" },
|
||||
{ LDNS_EDE_UNSUPPORTED_DS_DIGEST, "Unsupported DS Digest Type" },
|
||||
{ LDNS_EDE_STALE_ANSWER, "Stale Answer" },
|
||||
{ LDNS_EDE_FORGED_ANSWER, "Forged Answer" },
|
||||
{ LDNS_EDE_DNSSEC_INDETERMINATE, "DNSSEC Indeterminate" },
|
||||
{ LDNS_EDE_DNSSEC_BOGUS, "DNSSEC Bogus" },
|
||||
{ LDNS_EDE_SIGNATURE_EXPIRED, "Signature Expired" },
|
||||
{ LDNS_EDE_SIGNATURE_NOT_YET_VALID, "Signature Not Yet Valid" },
|
||||
{ LDNS_EDE_DNSKEY_MISSING, "DNSKEY Missing" },
|
||||
{ LDNS_EDE_RRSIGS_MISSING, "RRSIGs Missing" },
|
||||
{ LDNS_EDE_NO_ZONE_KEY_BIT_SET, "No Zone Key Bit Set" },
|
||||
{ LDNS_EDE_NSEC_MISSING, "NSEC Missing" },
|
||||
{ LDNS_EDE_CACHED_ERROR, "Cached Error" },
|
||||
{ LDNS_EDE_NOT_READY, "Not Ready" },
|
||||
{ LDNS_EDE_BLOCKED, "Blocked" },
|
||||
{ LDNS_EDE_CENSORED, "Censored" },
|
||||
{ LDNS_EDE_FILTERED, "Filtered" },
|
||||
{ LDNS_EDE_PROHIBITED, "Prohibited" },
|
||||
{ LDNS_EDE_STALE_NXDOMAIN_ANSWER, "Stale NXDOMAIN Answer" },
|
||||
{ LDNS_EDE_NOT_AUTHORITATIVE, "Not Authoritative" },
|
||||
{ LDNS_EDE_NOT_SUPPORTED, "Not Supported" },
|
||||
{ LDNS_EDE_NO_REACHABLE_AUTHORITY, "No Reachable Authority" },
|
||||
{ LDNS_EDE_NETWORK_ERROR, "Network Error" },
|
||||
{ LDNS_EDE_INVALID_DATA, "Invalid Data" },
|
||||
{ 0, NULL}
|
||||
};
|
||||
sldns_lookup_table* sldns_edns_ede_codes = sldns_edns_ede_codes_data;
|
||||
|
||||
static sldns_lookup_table sldns_tsig_errors_data[] = {
|
||||
{ LDNS_TSIG_ERROR_NOERROR, "NOERROR" },
|
||||
{ LDNS_RCODE_FORMERR, "FORMERR" },
|
||||
@@ -224,7 +257,7 @@ sldns_lookup_table* sldns_tsig_errors = sldns_tsig_errors_data;
|
||||
/* draft-ietf-dnsop-svcb-https-06: 6. Initial SvcParamKeys */
|
||||
const char *svcparamkey_strs[] = {
|
||||
"mandatory", "alpn", "no-default-alpn", "port",
|
||||
"ipv4hint", "ech", "ipv6hint"
|
||||
"ipv4hint", "ech", "ipv6hint", "dohpath"
|
||||
};
|
||||
|
||||
char* sldns_wire2str_pkt(uint8_t* data, size_t len)
|
||||
@@ -487,7 +520,7 @@ int sldns_wire2str_rr_scan(uint8_t** d, size_t* dlen, char** s, size_t* slen,
|
||||
uint8_t* rr = *d;
|
||||
size_t rrlen = *dlen, dname_off, rdlen, ordlen;
|
||||
uint16_t rrtype = 0;
|
||||
|
||||
|
||||
if(*dlen >= 3 && (*d)[0]==0 &&
|
||||
sldns_read_uint16((*d)+1)==LDNS_RR_TYPE_OPT) {
|
||||
/* perform EDNS OPT processing */
|
||||
@@ -1119,7 +1152,7 @@ static int sldns_wire2str_svcparam_alpn2str(char** s,
|
||||
w += sldns_str_print(s, slen, "%s", ",");
|
||||
}
|
||||
w += sldns_str_print(s, slen, "\"");
|
||||
|
||||
|
||||
return w;
|
||||
}
|
||||
|
||||
@@ -1139,7 +1172,7 @@ static int sldns_wire2str_svcparam_ech2str(char** s,
|
||||
(*s) += size;
|
||||
(*slen) -= size;
|
||||
|
||||
w += sldns_str_print(s, slen, "\"");
|
||||
w += sldns_str_print(s, slen, "\"");
|
||||
|
||||
return w + size;
|
||||
}
|
||||
@@ -1162,7 +1195,7 @@ int sldns_wire2str_svcparam_scan(uint8_t** d, size_t* dlen, char** s, size_t* sl
|
||||
|
||||
/* verify that we have data_len data */
|
||||
if (data_len > *dlen)
|
||||
return -1;
|
||||
return -1;
|
||||
|
||||
written_chars += sldns_print_svcparamkey(s, slen, svcparamkey);
|
||||
if (!data_len) {
|
||||
@@ -1174,6 +1207,7 @@ int sldns_wire2str_svcparam_scan(uint8_t** d, size_t* dlen, char** s, size_t* sl
|
||||
case SVCB_KEY_IPV4HINT:
|
||||
case SVCB_KEY_IPV6HINT:
|
||||
case SVCB_KEY_MANDATORY:
|
||||
case SVCB_KEY_DOHPATH:
|
||||
return -1;
|
||||
default:
|
||||
return written_chars;
|
||||
@@ -1201,6 +1235,8 @@ int sldns_wire2str_svcparam_scan(uint8_t** d, size_t* dlen, char** s, size_t* sl
|
||||
case SVCB_KEY_ECH:
|
||||
r = sldns_wire2str_svcparam_ech2str(s, slen, data_len, *d);
|
||||
break;
|
||||
case SVCB_KEY_DOHPATH:
|
||||
/* fallthrough */
|
||||
default:
|
||||
r = sldns_str_print(s, slen, "=\"");
|
||||
|
||||
@@ -1222,7 +1258,7 @@ int sldns_wire2str_svcparam_scan(uint8_t** d, size_t* dlen, char** s, size_t* sl
|
||||
}
|
||||
if (r <= 0)
|
||||
return -1; /* wireformat error */
|
||||
|
||||
|
||||
written_chars += r;
|
||||
*d += data_len;
|
||||
*dlen -= data_len;
|
||||
@@ -1551,7 +1587,7 @@ int sldns_wire2str_nsec_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
|
||||
unsigned i, bit, window, block_len;
|
||||
uint16_t t;
|
||||
int w = 0;
|
||||
|
||||
|
||||
/* check for errors */
|
||||
while(pl) {
|
||||
if(pl < 2) return -1;
|
||||
@@ -2231,6 +2267,52 @@ static int sldns_wire2str_edns_keepalive_print(char** s, size_t* sl,
|
||||
return w;
|
||||
}
|
||||
|
||||
int sldns_wire2str_edns_ede_print(char** s, size_t* sl,
|
||||
uint8_t* data, size_t len)
|
||||
{
|
||||
uint16_t ede_code;
|
||||
int w = 0;
|
||||
sldns_lookup_table *lt;
|
||||
size_t i;
|
||||
int printable;
|
||||
|
||||
if(len < 2) {
|
||||
w += sldns_str_print(s, sl, "malformed ede ");
|
||||
w += print_hex_buf(s, sl, data, len);
|
||||
return w;
|
||||
}
|
||||
|
||||
ede_code = sldns_read_uint16(data);
|
||||
lt = sldns_lookup_by_id(sldns_edns_ede_codes, (int)ede_code);
|
||||
if(lt && lt->name)
|
||||
w += sldns_str_print(s, sl, "%s", lt->name);
|
||||
else w += sldns_str_print(s, sl, "%d", (int)ede_code);
|
||||
|
||||
if(len == 2)
|
||||
return w;
|
||||
|
||||
w += sldns_str_print(s, sl, " ");
|
||||
|
||||
/* If it looks like text, show it as text. */
|
||||
printable=1;
|
||||
for(i=2; i<len; i++) {
|
||||
if(isprint((unsigned char)data[i]) || data[i] == '\t')
|
||||
continue;
|
||||
printable = 0;
|
||||
break;
|
||||
}
|
||||
if(printable) {
|
||||
w += sldns_str_print(s, sl, "\"");
|
||||
for(i=2; i<len; i++) {
|
||||
w += str_char_print(s, sl, data[i]);
|
||||
}
|
||||
w += sldns_str_print(s, sl, "\"");
|
||||
} else {
|
||||
w += print_hex_buf(s, sl, data+2, len-2);
|
||||
}
|
||||
return w;
|
||||
}
|
||||
|
||||
int sldns_wire2str_edns_option_print(char** s, size_t* sl,
|
||||
uint16_t option_code, uint8_t* optdata, size_t optlen)
|
||||
{
|
||||
@@ -2265,6 +2347,9 @@ int sldns_wire2str_edns_option_print(char** s, size_t* sl,
|
||||
case LDNS_EDNS_PADDING:
|
||||
w += print_hex_buf(s, sl, optdata, optlen);
|
||||
break;
|
||||
case LDNS_EDNS_EDE:
|
||||
w += sldns_wire2str_edns_ede_print(s, sl, optdata, optlen);
|
||||
break;
|
||||
default:
|
||||
/* unknown option code */
|
||||
w += print_hex_buf(s, sl, optdata, optlen);
|
||||
|
||||
@@ -36,6 +36,8 @@ extern struct sldns_struct_lookup_table* sldns_opcodes;
|
||||
extern struct sldns_struct_lookup_table* sldns_edns_flags;
|
||||
/** EDNS option codes */
|
||||
extern struct sldns_struct_lookup_table* sldns_edns_options;
|
||||
/** EDNS EDE codes */
|
||||
extern struct sldns_struct_lookup_table* sldns_edns_ede_codes;
|
||||
/** error string from wireparse */
|
||||
extern struct sldns_struct_lookup_table* sldns_wireparse_errors;
|
||||
/** tsig errors are the rcodes with extra (higher) values */
|
||||
@@ -1020,6 +1022,17 @@ int sldns_wire2str_edns_n3u_print(char** str, size_t* str_len,
|
||||
int sldns_wire2str_edns_subnet_print(char** str, size_t* str_len,
|
||||
uint8_t* option_data, size_t option_len);
|
||||
|
||||
/**
|
||||
* Print EDNS EDE option data to string. User buffers, moves string pointers.
|
||||
* @param str: string buffer.
|
||||
* @param str_len: length of string buffer.
|
||||
* @param option_data: buffer with EDNS option code data.
|
||||
* @param option_len: length of the data for this option.
|
||||
* @return number of characters (except null) needed to print.
|
||||
*/
|
||||
int sldns_wire2str_edns_ede_print(char** str, size_t* str_len,
|
||||
uint8_t* option_data, size_t option_len);
|
||||
|
||||
/**
|
||||
* Print an EDNS option as OPT: VALUE. User buffers, moves string pointers.
|
||||
* @param str: string buffer.
|
||||
|
||||
@@ -1589,8 +1589,7 @@ xml_parse_setup(XML_Parser parser, struct xml_data* data, time_t now)
|
||||
|
||||
/**
|
||||
* Perform XML parsing of the root-anchors file
|
||||
* Its format description can be read here
|
||||
* https://data.iana.org/root-anchors/draft-icann-dnssec-trust-anchor.txt
|
||||
* Its format description can be found in RFC 7958.
|
||||
* It uses libexpat.
|
||||
* @param xml: BIO with xml data.
|
||||
* @param now: the current time for checking DS validity periods.
|
||||
|
||||
@@ -707,6 +707,23 @@ morechecks(struct config_file* cfg)
|
||||
cfg->auto_trust_anchor_file_list, cfg->chrootdir, cfg);
|
||||
check_chroot_filelist_wild("trusted-keys-file",
|
||||
cfg->trusted_keys_file_list, cfg->chrootdir, cfg);
|
||||
if(cfg->disable_edns_do && strstr(cfg->module_conf, "validator")
|
||||
&& (cfg->trust_anchor_file_list
|
||||
|| cfg->trust_anchor_list
|
||||
|| cfg->auto_trust_anchor_file_list
|
||||
|| cfg->trusted_keys_file_list)) {
|
||||
char* key = NULL;
|
||||
if(cfg->auto_trust_anchor_file_list)
|
||||
key = cfg->auto_trust_anchor_file_list->str;
|
||||
if(!key && cfg->trust_anchor_file_list)
|
||||
key = cfg->trust_anchor_file_list->str;
|
||||
if(!key && cfg->trust_anchor_list)
|
||||
key = cfg->trust_anchor_list->str;
|
||||
if(!key && cfg->trusted_keys_file_list)
|
||||
key = cfg->trusted_keys_file_list->str;
|
||||
if(!key) key = "";
|
||||
fatal_exit("disable-edns-do does not allow DNSSEC to work, but the validator module uses a trust anchor %s, turn off disable-edns-do or disable validation", key);
|
||||
}
|
||||
#ifdef USE_IPSECMOD
|
||||
if(cfg->ipsecmod_enabled && strstr(cfg->module_conf, "ipsecmod")) {
|
||||
/* only check hook if enabled */
|
||||
@@ -714,7 +731,7 @@ morechecks(struct config_file* cfg)
|
||||
cfg->chrootdir, cfg);
|
||||
}
|
||||
#endif
|
||||
/* remove chroot setting so that modules are not stripping pathnames*/
|
||||
/* remove chroot setting so that modules are not stripping pathnames */
|
||||
free(cfg->chrootdir);
|
||||
cfg->chrootdir = NULL;
|
||||
|
||||
|
||||
+30
-36
@@ -4,22 +4,22 @@
|
||||
* Copyright (c) 2008, 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
|
||||
@@ -59,6 +59,7 @@
|
||||
#include "util/locks.h"
|
||||
#include "util/net_help.h"
|
||||
#include "util/shm_side/shm_main.h"
|
||||
#include "util/timeval_func.h"
|
||||
#include "daemon/stats.h"
|
||||
#include "sldns/wire2str.h"
|
||||
#include "sldns/pkthdr.h"
|
||||
@@ -102,6 +103,12 @@ usage(void)
|
||||
printf(" stop stops the server\n");
|
||||
printf(" reload reloads the server\n");
|
||||
printf(" (this flushes data, stats, requestlist)\n");
|
||||
printf(" reload_keep_cache reloads the server but tries to\n");
|
||||
printf(" keep the RRset and message cache\n");
|
||||
printf(" if (re)configuration allows for it.\n");
|
||||
printf(" That means the caches sizes and\n");
|
||||
printf(" the number of threads must not\n");
|
||||
printf(" change between reloads.\n");
|
||||
printf(" stats print statistics\n");
|
||||
printf(" stats_noreset peek at statistics\n");
|
||||
#ifdef HAVE_SHMGET
|
||||
@@ -180,33 +187,6 @@ usage(void)
|
||||
#ifdef HAVE_SHMGET
|
||||
/** what to put on statistics lines between var and value, ": " or "=" */
|
||||
#define SQ "="
|
||||
/** if true, inhibits a lot of =0 lines from the stats output */
|
||||
static const int inhibit_zero = 1;
|
||||
/** divide sum of timers to get average */
|
||||
static void
|
||||
timeval_divide(struct timeval* avg, const struct timeval* sum, long long d)
|
||||
{
|
||||
#ifndef S_SPLINT_S
|
||||
size_t leftover;
|
||||
if(d <= 0) {
|
||||
avg->tv_sec = 0;
|
||||
avg->tv_usec = 0;
|
||||
return;
|
||||
}
|
||||
avg->tv_sec = sum->tv_sec / d;
|
||||
avg->tv_usec = sum->tv_usec / d;
|
||||
/* handle fraction from seconds divide */
|
||||
leftover = sum->tv_sec - avg->tv_sec*d;
|
||||
if(leftover <= 0)
|
||||
leftover = 0;
|
||||
avg->tv_usec += (((long long)leftover)*((long long)1000000))/d;
|
||||
if(avg->tv_sec < 0)
|
||||
avg->tv_sec = 0;
|
||||
if(avg->tv_usec < 0)
|
||||
avg->tv_usec = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
/** print unsigned long stats value */
|
||||
#define PR_UL_NM(str, var) printf("%s."str SQ"%lu\n", nm, (unsigned long)(var));
|
||||
#define PR_UL(str, var) printf(str SQ"%lu\n", (unsigned long)(var));
|
||||
@@ -222,12 +202,20 @@ static void pr_stats(const char* nm, struct ub_stats_info* s)
|
||||
{
|
||||
struct timeval sumwait, avg;
|
||||
PR_UL_NM("num.queries", s->svr.num_queries);
|
||||
PR_UL_NM("num.queries_ip_ratelimited",
|
||||
PR_UL_NM("num.queries_ip_ratelimited",
|
||||
s->svr.num_queries_ip_ratelimited);
|
||||
PR_UL_NM("num.queries_cookie_valid",
|
||||
s->svr.num_queries_cookie_valid);
|
||||
PR_UL_NM("num.queries_cookie_client",
|
||||
s->svr.num_queries_cookie_client);
|
||||
PR_UL_NM("num.queries_cookie_invalid",
|
||||
s->svr.num_queries_cookie_invalid);
|
||||
PR_UL_NM("num.cachehits",
|
||||
s->svr.num_queries - s->svr.num_queries_missed_cache);
|
||||
PR_UL_NM("num.cachemiss", s->svr.num_queries_missed_cache);
|
||||
PR_UL_NM("num.prefetch", s->svr.num_queries_prefetch);
|
||||
PR_UL_NM("num.queries_timed_out", s->svr.num_queries_timed_out);
|
||||
PR_UL_NM("query.queue_time_us.max", s->svr.max_query_time_us);
|
||||
PR_UL_NM("num.expired", s->svr.ans_expired);
|
||||
PR_UL_NM("num.recursivereplies", s->mesh_replies_sent);
|
||||
#ifdef USE_DNSCRYPT
|
||||
@@ -316,7 +304,7 @@ static void print_hist(struct ub_stats_info* s)
|
||||
}
|
||||
|
||||
/** print extended */
|
||||
static void print_extended(struct ub_stats_info* s)
|
||||
static void print_extended(struct ub_stats_info* s, int inhibit_zero)
|
||||
{
|
||||
int i;
|
||||
char nm[16];
|
||||
@@ -399,6 +387,9 @@ static void print_extended(struct ub_stats_info* s)
|
||||
PR_UL("rrset.cache.count", s->svr.rrset_cache_count);
|
||||
PR_UL("infra.cache.count", s->svr.infra_cache_count);
|
||||
PR_UL("key.cache.count", s->svr.key_cache_count);
|
||||
/* max collisions */
|
||||
PR_UL("msg.cache.max_collisions", s->svr.msg_cache_max_collisions);
|
||||
PR_UL("rrset.cache.max_collisions", s->svr.rrset_cache_max_collisions);
|
||||
/* applied RPZ actions */
|
||||
for(i=0; i<UB_STATS_RPZ_ACTION_NUM; i++) {
|
||||
if(i == RPZ_NO_OVERRIDE_ACTION)
|
||||
@@ -422,6 +413,9 @@ static void print_extended(struct ub_stats_info* s)
|
||||
PR_UL("num.query.subnet", s->svr.num_query_subnet);
|
||||
PR_UL("num.query.subnet_cache", s->svr.num_query_subnet_cache);
|
||||
#endif
|
||||
#ifdef USE_CACHEDB
|
||||
PR_UL("num.query.cachedb", s->svr.num_query_cachedb);
|
||||
#endif
|
||||
}
|
||||
|
||||
/** print statistics out of memory structures */
|
||||
@@ -439,7 +433,7 @@ static void do_stats_shm(struct config_file* cfg, struct ub_stats_info* stats,
|
||||
if(cfg->stat_extended) {
|
||||
print_mem(shm_stat, &stats[0]);
|
||||
print_hist(stats);
|
||||
print_extended(stats);
|
||||
print_extended(stats, cfg->stat_inhibit_zero);
|
||||
}
|
||||
}
|
||||
#endif /* HAVE_SHMGET */
|
||||
@@ -985,7 +979,7 @@ int main(int argc, char* argv[])
|
||||
fatal_exit("could not exec unbound: %s",
|
||||
strerror(ENOSYS));
|
||||
#else
|
||||
if(execlp("unbound", "unbound", "-c", cfgfile,
|
||||
if(execlp("unbound", "unbound", "-c", cfgfile,
|
||||
(char*)NULL) < 0) {
|
||||
fatal_exit("could not exec unbound: %s",
|
||||
strerror(errno));
|
||||
|
||||
@@ -482,6 +482,7 @@ int main(int argc, char* argv[])
|
||||
case '?':
|
||||
case 'h':
|
||||
default:
|
||||
ub_ctx_delete(ctx);
|
||||
usage();
|
||||
}
|
||||
}
|
||||
@@ -495,8 +496,10 @@ int main(int argc, char* argv[])
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
if(argc != 1)
|
||||
if(argc != 1) {
|
||||
ub_ctx_delete(ctx);
|
||||
usage();
|
||||
}
|
||||
|
||||
#ifdef HAVE_SSL
|
||||
#ifdef HAVE_ERR_LOAD_CRYPTO_STRINGS
|
||||
|
||||
+11
-4
@@ -226,9 +226,16 @@ make_query(char* qname, char* qtype, char* qclass)
|
||||
printf("cannot parse query name: '%s'\n", qname);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
qinfo.qtype = sldns_get_rr_type_by_name(qtype);
|
||||
if(qinfo.qtype == 0 && strcmp(qtype, "TYPE0") != 0) {
|
||||
printf("cannot parse query type: '%s'\n", qtype);
|
||||
exit(1);
|
||||
}
|
||||
qinfo.qclass = sldns_get_rr_class_by_name(qclass);
|
||||
if(qinfo.qclass == 0 && strcmp(qclass, "CLASS0") != 0) {
|
||||
printf("cannot parse query class: '%s'\n", qclass);
|
||||
exit(1);
|
||||
}
|
||||
qinfo.local_alias = NULL;
|
||||
|
||||
qinfo_query_encode(buf, &qinfo); /* flips buffer */
|
||||
@@ -279,7 +286,7 @@ static ssize_t http2_recv_cb(nghttp2_session* ATTR_UNUSED(session),
|
||||
if(want == SSL_ERROR_ZERO_RETURN) {
|
||||
return NGHTTP2_ERR_EOF;
|
||||
}
|
||||
log_crypto_err("could not SSL_read");
|
||||
log_crypto_err_io("could not SSL_read", want);
|
||||
return NGHTTP2_ERR_EOF;
|
||||
}
|
||||
return r;
|
||||
@@ -310,7 +317,7 @@ static ssize_t http2_send_cb(nghttp2_session* ATTR_UNUSED(session),
|
||||
if(want == SSL_ERROR_ZERO_RETURN) {
|
||||
return NGHTTP2_ERR_CALLBACK_FAILURE;
|
||||
}
|
||||
log_crypto_err("could not SSL_write");
|
||||
log_crypto_err_io("could not SSL_write", want);
|
||||
return NGHTTP2_ERR_CALLBACK_FAILURE;
|
||||
}
|
||||
return r;
|
||||
@@ -519,7 +526,7 @@ run(struct http2_session* h2_session, int port, int no_tls, int count, char** q)
|
||||
r = SSL_get_error(ssl, r);
|
||||
if(r != SSL_ERROR_WANT_READ &&
|
||||
r != SSL_ERROR_WANT_WRITE) {
|
||||
log_crypto_err("could not ssl_handshake");
|
||||
log_crypto_err_io("could not ssl_handshake", r);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user