mirror of
https://github.com/NLnetLabs/unbound.git
synced 2026-08-17 21:25:50 +02:00
Compare commits
373
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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 | ||
|
|
2695eb9d1a | ||
|
|
20184483df | ||
|
|
adb4aeb609 | ||
|
|
70c2b587fc | ||
|
|
a50ddd7ab9 | ||
|
|
4a04ba813a | ||
|
|
1aa2c318e7 | ||
|
|
e1ec3cf893 | ||
|
|
8058dc9127 | ||
|
|
144f29638c | ||
|
|
7081b0340f | ||
|
|
263096d1f6 | ||
|
|
e577ab105e | ||
|
|
04540f82e5 | ||
|
|
2e6ddd6032 | ||
|
|
a197aac2f6 | ||
|
|
648ad4db6f | ||
|
|
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 | ||
|
|
f531faf163 | ||
|
|
c0c9acccfd | ||
|
|
17e5dd6131 | ||
|
|
e9107907e5 | ||
|
|
ba8642aeb7 | ||
|
|
5ffa4d7232 | ||
|
|
2571d00535 | ||
|
|
f9a563d495 | ||
|
|
08dcae0dab | ||
|
|
5ac1bc13cb | ||
|
|
f5e1ef650d | ||
|
|
d25e0cd9b0 | ||
|
|
4f27799456 | ||
|
|
97d1cff315 | ||
|
|
a4631a3ecf | ||
|
|
2569b12b9c | ||
|
|
bf1cce6f9b | ||
|
|
b043bc5eb4 | ||
|
|
d122617dd4 | ||
|
|
6b8181acb7 | ||
|
|
f609a45354 | ||
|
|
60db1111c0 | ||
|
|
40b2b3a6f3 | ||
|
|
f1d263a318 | ||
|
|
f0614a57f8 | ||
|
|
bf7a2884fb | ||
|
|
c0eaadfc42 | ||
|
|
22e43aa631 | ||
|
|
c4e51a4cfe | ||
|
|
7d96a7e3fe | ||
|
|
9842fbf760 | ||
|
|
a102fb1df8 | ||
|
|
bd2c202674 | ||
|
|
75f3fbdd65 | ||
|
|
71f23ef354 | ||
|
|
5b98816751 | ||
|
|
0b176750bd | ||
|
|
f0989fc754 | ||
|
|
c9f90def0a | ||
|
|
57c4f28f20 | ||
|
|
d731fa2e21 | ||
|
|
e93c75a5d4 | ||
|
|
8e18f11965 | ||
|
|
e3871ca907 | ||
|
|
dcfcde2ec8 | ||
|
|
137719522a | ||
|
|
bd3c5702a7 | ||
|
|
f68e252345 | ||
|
|
1e5158045f | ||
|
|
99e12ae4b5 | ||
|
|
5f3b460586 | ||
|
|
9b1647ebae | ||
|
|
307805b64f | ||
|
|
f02d6bddd1 | ||
|
|
eb02170338 | ||
|
|
d301bfe4a2 | ||
|
|
fc123303ac | ||
|
|
aec33b3d63 | ||
|
|
7e9fd2114b | ||
|
|
c30bdff939 | ||
|
|
cfc656294e | ||
|
|
007db2c327 | ||
|
|
5bbaf78c3f | ||
|
|
57230d7f22 | ||
|
|
5f309d0018 | ||
|
|
d66e1cccf8 | ||
|
|
2450b4653a | ||
|
|
eb3378396f | ||
|
|
1f5cc25974 | ||
|
|
ec5812a748 | ||
|
|
10a5a5880a | ||
|
|
2fa1c17cd9 | ||
|
|
b642c5fe1f | ||
|
|
f3fa363443 | ||
|
|
e6f878ee71 | ||
|
|
8d939691a3 | ||
|
|
b465e0cfc0 | ||
|
|
73b3b32062 | ||
|
|
6e31d1f5be | ||
|
|
14fe4669e7 | ||
|
|
dc6c04b243 | ||
|
|
ef57f8bd51 | ||
|
|
fbe8e3b0b2 | ||
|
|
1c164ab442 | ||
|
|
e738ec31ca | ||
|
|
07b073ddb3 | ||
|
|
0f08cc6d55 | ||
|
|
7d3c6f1c43 | ||
|
|
cd22fdc28d | ||
|
|
5ae48f85c0 | ||
|
|
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
|
||||
|
||||
+29
-22
@@ -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/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 \
|
||||
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
|
||||
@@ -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,9 @@ 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 \
|
||||
$(srcdir)/util/data/dname.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/module.h \
|
||||
$(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgparse.h \
|
||||
@@ -1004,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 \
|
||||
@@ -1184,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 \
|
||||
@@ -1319,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 \
|
||||
@@ -1341,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 \
|
||||
@@ -1355,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 \
|
||||
@@ -1407,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 \
|
||||
@@ -1415,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 \
|
||||
@@ -1512,7 +1519,7 @@ asynclook.lo asynclook.o: $(srcdir)/testcode/asynclook.c config.h $(srcdir)/libu
|
||||
$(srcdir)/services/modstack.h $(srcdir)/libunbound/unbound-event.h $(srcdir)/util/data/packed_rrset.h \
|
||||
$(srcdir)/util/storage/lruhash.h $(srcdir)/sldns/rrdef.h
|
||||
streamtcp.lo streamtcp.o: $(srcdir)/testcode/streamtcp.c config.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \
|
||||
$(srcdir)/util/net_help.h $(srcdir)/util/data/msgencode.h $(srcdir)/util/data/msgparse.h \
|
||||
$(srcdir)/util/net_help.h $(srcdir)/util/proxy_protocol.h $(srcdir)/util/data/msgencode.h $(srcdir)/util/data/msgparse.h \
|
||||
$(srcdir)/util/storage/lruhash.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/data/msgreply.h \
|
||||
$(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/dname.h $(srcdir)/sldns/sbuffer.h \
|
||||
$(srcdir)/sldns/str2wire.h $(srcdir)/sldns/wire2str.h
|
||||
|
||||
@@ -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
|
||||
|
||||
+23
-17
@@ -2,7 +2,10 @@
|
||||
# Copyright 2009, Wouter Wijngaards, NLnet Labs.
|
||||
# BSD licensed.
|
||||
#
|
||||
# Version 43
|
||||
# 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
|
||||
# and ssldir_lib output directories.
|
||||
@@ -186,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
|
||||
@@ -232,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
|
||||
@@ -271,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;
|
||||
@@ -308,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;
|
||||
@@ -334,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;
|
||||
}
|
||||
@@ -344,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;
|
||||
@@ -355,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;
|
||||
@@ -369,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;
|
||||
@@ -384,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;
|
||||
@@ -412,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;
|
||||
@@ -474,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)))
|
||||
@@ -833,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;
|
||||
}
|
||||
@@ -858,7 +861,7 @@ char* (*f) () = getaddrinfo;
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
int main() {
|
||||
int main(void) {
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
@@ -922,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
|
||||
@@ -963,6 +966,9 @@ AC_LANG_SOURCE([[
|
||||
#ifdef HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_SELECT_H
|
||||
#include <sys/select.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_SOCKET_H
|
||||
#include <sys/socket.h>
|
||||
#endif
|
||||
@@ -1313,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
|
||||
])
|
||||
|
||||
@@ -1351,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
|
||||
|
||||
+67
-11
@@ -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,
|
||||
@@ -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;
|
||||
}
|
||||
@@ -390,6 +397,15 @@ prep_data(struct module_qstate* qstate, struct sldns_buffer* buf)
|
||||
|
||||
if(!qstate->return_msg || !qstate->return_msg->rep)
|
||||
return 0;
|
||||
/* do not store failures like SERVFAIL in the cachedb, this avoids
|
||||
* overwriting expired, valid, content with broken content. */
|
||||
if(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;
|
||||
/* We don't store the reply if its TTL is 0 unless serve-expired is
|
||||
* enabled. Such a reply won't be reusable and simply be a waste for
|
||||
* the backend. It's also compatible with the default behavior of
|
||||
@@ -397,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);
|
||||
@@ -493,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);
|
||||
@@ -530,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 */
|
||||
@@ -542,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);
|
||||
@@ -615,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 */
|
||||
@@ -678,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 */
|
||||
@@ -694,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",
|
||||
@@ -731,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;
|
||||
@@ -753,6 +808,7 @@ 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 */
|
||||
|
||||
+24
-4
@@ -56,6 +56,8 @@ 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 */
|
||||
};
|
||||
|
||||
@@ -67,8 +69,13 @@ 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,6 +87,17 @@ 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);
|
||||
}
|
||||
verbose(VERB_OPS, "Connection to Redis established");
|
||||
return ctx;
|
||||
|
||||
fail:
|
||||
@@ -94,7 +112,7 @@ 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) {
|
||||
@@ -112,6 +130,8 @@ redis_init(struct module_env* env, struct cachedb_env* cachedb_env)
|
||||
* 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++)
|
||||
@@ -154,7 +174,7 @@ redis_deinit(struct module_env* env, struct cachedb_env* cachedb_env)
|
||||
cachedb_env->backend_data;
|
||||
(void)env;
|
||||
|
||||
verbose(VERB_ALGO, "redis_deinit");
|
||||
verbose(VERB_OPS, "Redis deinitialization");
|
||||
|
||||
if(!moddata)
|
||||
return;
|
||||
|
||||
+7
-1
@@ -57,6 +57,8 @@
|
||||
#define BLOCKSZ 64
|
||||
#define RSBUFSZ (16*BLOCKSZ)
|
||||
|
||||
#define REKEY_BASE (1024*1024) /* NB. should be a power of 2 */
|
||||
|
||||
/* Marked MAP_INHERIT_ZERO, so zero'd out in fork children. */
|
||||
static struct {
|
||||
size_t rs_have; /* valid bytes at end of rs_buf */
|
||||
@@ -179,6 +181,7 @@ static void
|
||||
_rs_stir(void)
|
||||
{
|
||||
u_char rnd[KEYSZ + IVSZ];
|
||||
uint32_t rekey_fuzz = 0;
|
||||
|
||||
if (getentropy(rnd, sizeof rnd) == -1) {
|
||||
if(errno != ENOSYS ||
|
||||
@@ -201,7 +204,10 @@ _rs_stir(void)
|
||||
rs->rs_have = 0;
|
||||
memset(rsx->rs_buf, 0, sizeof(rsx->rs_buf));
|
||||
|
||||
rs->rs_count = 1600000;
|
||||
/* rekey interval should not be predictable */
|
||||
chacha_encrypt_bytes(&rsx->rs_chacha, (uint8_t *)&rekey_fuzz,
|
||||
(uint8_t *)&rekey_fuzz, sizeof(rekey_fuzz));
|
||||
rs->rs_count = REKEY_BASE + (rekey_fuzz % REKEY_BASE);
|
||||
}
|
||||
|
||||
static inline void
|
||||
|
||||
@@ -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>
|
||||
|
||||
+29
-11
@@ -298,6 +298,9 @@
|
||||
/* Define to 1 if you have the `getrlimit' function. */
|
||||
#undef HAVE_GETRLIMIT
|
||||
|
||||
/* Define to 1 if you have the `gettid' function. */
|
||||
#undef HAVE_GETTID
|
||||
|
||||
/* Define to 1 if you have the `glob' function. */
|
||||
#undef HAVE_GLOB
|
||||
|
||||
@@ -361,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
|
||||
|
||||
@@ -457,6 +463,12 @@
|
||||
/* Define to 1 if you have the `OSSL_PARAM_BLD_new' function. */
|
||||
#undef HAVE_OSSL_PARAM_BLD_NEW
|
||||
|
||||
/* Define to 1 if you have the `poll' function. */
|
||||
#undef HAVE_POLL
|
||||
|
||||
/* Define to 1 if you have the <poll.h> header file. */
|
||||
#undef HAVE_POLL_H
|
||||
|
||||
/* Define if you have POSIX threads libraries and header files. */
|
||||
#undef HAVE_PTHREAD
|
||||
|
||||
@@ -800,12 +812,18 @@
|
||||
/* Shared data */
|
||||
#undef SHARE_DIR
|
||||
|
||||
/* The size of `pthread_t', as computed by sizeof. */
|
||||
#undef SIZEOF_PTHREAD_T
|
||||
|
||||
/* The size of `size_t', as computed by sizeof. */
|
||||
#undef SIZEOF_SIZE_T
|
||||
|
||||
/* The size of `time_t', as computed by sizeof. */
|
||||
#undef SIZEOF_TIME_T
|
||||
|
||||
/* The size of `unsigned long', as computed by sizeof. */
|
||||
#undef SIZEOF_UNSIGNED_LONG
|
||||
|
||||
/* define if (v)snprintf does not return length needed, (but length used) */
|
||||
#undef SNPRINTF_RET_BROKEN
|
||||
|
||||
@@ -1053,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
|
||||
|
||||
|
||||
|
||||
@@ -1169,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)))
|
||||
@@ -1279,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
|
||||
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#! /bin/sh
|
||||
# Guess values for system-dependent variables and create Makefiles.
|
||||
# Generated by GNU Autoconf 2.69 for unbound 1.16.2.
|
||||
# Generated by GNU Autoconf 2.69 for unbound 1.18.0.
|
||||
#
|
||||
# Report bugs to <unbound-bugs@nlnetlabs.nl or https://github.com/NLnetLabs/unbound/issues>.
|
||||
#
|
||||
@@ -591,8 +591,8 @@ MAKEFLAGS=
|
||||
# Identity of this package.
|
||||
PACKAGE_NAME='unbound'
|
||||
PACKAGE_TARNAME='unbound'
|
||||
PACKAGE_VERSION='1.16.2'
|
||||
PACKAGE_STRING='unbound 1.16.2'
|
||||
PACKAGE_VERSION='1.18.0'
|
||||
PACKAGE_STRING='unbound 1.18.0'
|
||||
PACKAGE_BUGREPORT='unbound-bugs@nlnetlabs.nl or https://github.com/NLnetLabs/unbound/issues'
|
||||
PACKAGE_URL=''
|
||||
|
||||
@@ -1477,7 +1477,7 @@ if test "$ac_init_help" = "long"; then
|
||||
# Omit some internal or obsolete options to make the list less imposing.
|
||||
# This message is too long to be a string in the A/UX 3.1 sh.
|
||||
cat <<_ACEOF
|
||||
\`configure' configures unbound 1.16.2 to adapt to many kinds of systems.
|
||||
\`configure' configures unbound 1.18.0 to adapt to many kinds of systems.
|
||||
|
||||
Usage: $0 [OPTION]... [VAR=VALUE]...
|
||||
|
||||
@@ -1543,7 +1543,7 @@ fi
|
||||
|
||||
if test -n "$ac_init_help"; then
|
||||
case $ac_init_help in
|
||||
short | recursive ) echo "Configuration of unbound 1.16.2:";;
|
||||
short | recursive ) echo "Configuration of unbound 1.18.0:";;
|
||||
esac
|
||||
cat <<\_ACEOF
|
||||
|
||||
@@ -1785,7 +1785,7 @@ fi
|
||||
test -n "$ac_init_help" && exit $ac_status
|
||||
if $ac_init_version; then
|
||||
cat <<\_ACEOF
|
||||
unbound configure 1.16.2
|
||||
unbound configure 1.18.0
|
||||
generated by GNU Autoconf 2.69
|
||||
|
||||
Copyright (C) 2012 Free Software Foundation, Inc.
|
||||
@@ -2494,7 +2494,7 @@ cat >config.log <<_ACEOF
|
||||
This file contains any messages produced by compilers while
|
||||
running configure, to aid debugging if configure makes a mistake.
|
||||
|
||||
It was created by unbound $as_me 1.16.2, which was
|
||||
It was created by unbound $as_me 1.18.0, which was
|
||||
generated by GNU Autoconf 2.69. Invocation command line was
|
||||
|
||||
$ $0 $@
|
||||
@@ -2844,13 +2844,13 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
|
||||
|
||||
UNBOUND_VERSION_MAJOR=1
|
||||
|
||||
UNBOUND_VERSION_MINOR=16
|
||||
UNBOUND_VERSION_MINOR=18
|
||||
|
||||
UNBOUND_VERSION_MICRO=2
|
||||
UNBOUND_VERSION_MICRO=0
|
||||
|
||||
|
||||
LIBUNBOUND_CURRENT=9
|
||||
LIBUNBOUND_REVISION=18
|
||||
LIBUNBOUND_REVISION=22
|
||||
LIBUNBOUND_AGE=1
|
||||
# 1.0.0 had 0:12:0
|
||||
# 1.0.1 had 0:13:0
|
||||
@@ -2936,6 +2936,10 @@ LIBUNBOUND_AGE=1
|
||||
# 1.16.0 had 9:16:1
|
||||
# 1.16.1 had 9:17:1
|
||||
# 1.16.2 had 9:18: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
|
||||
|
||||
# Current -- the number of the binary API that we're implementing
|
||||
# Revision -- which iteration of the implementation of the binary
|
||||
@@ -5142,7 +5146,7 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $CC dependency flag" >&5
|
||||
$as_echo_n "checking $CC dependency flag... " >&6; }
|
||||
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
|
||||
@@ -5324,7 +5328,7 @@ echo '
|
||||
#include <getopt.h>
|
||||
#endif
|
||||
|
||||
int test() {
|
||||
int test(void) {
|
||||
int a;
|
||||
char **opts = NULL;
|
||||
struct timeval tv;
|
||||
@@ -5345,7 +5349,7 @@ int test() {
|
||||
return a;
|
||||
}
|
||||
' > 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
|
||||
@@ -5415,7 +5419,7 @@ echo '
|
||||
#include <getopt.h>
|
||||
#endif
|
||||
|
||||
int test() {
|
||||
int test(void) {
|
||||
int a;
|
||||
char **opts = NULL;
|
||||
struct timeval tv;
|
||||
@@ -5436,7 +5440,7 @@ int test() {
|
||||
return a;
|
||||
}
|
||||
' > 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
|
||||
@@ -5495,12 +5499,12 @@ else
|
||||
echo '
|
||||
#include <stdbool.h>
|
||||
#include <ctype.h>
|
||||
int test() {
|
||||
int test(void) {
|
||||
int a = 0;
|
||||
return a;
|
||||
}
|
||||
' > 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
|
||||
@@ -5559,13 +5563,13 @@ else
|
||||
echo '
|
||||
#include <ctype.h>
|
||||
|
||||
int test() {
|
||||
int test(void) {
|
||||
int a;
|
||||
a = isascii(32);
|
||||
return a;
|
||||
}
|
||||
' > 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
|
||||
@@ -5624,13 +5628,13 @@ else
|
||||
echo '
|
||||
#include <netinet/in.h>
|
||||
|
||||
int test() {
|
||||
int test(void) {
|
||||
struct in6_pktinfo inf;
|
||||
int a = (int)sizeof(inf);
|
||||
return a;
|
||||
}
|
||||
' > 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
|
||||
@@ -5692,13 +5696,13 @@ else
|
||||
echo '
|
||||
#include <unistd.h>
|
||||
|
||||
int test() {
|
||||
int test(void) {
|
||||
int a = setresgid(0,0,0);
|
||||
a = setresuid(0,0,0);
|
||||
return a;
|
||||
}
|
||||
' > 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
|
||||
@@ -5761,7 +5765,7 @@ echo '
|
||||
#endif
|
||||
#include <netdb.h>
|
||||
|
||||
int test() {
|
||||
int test(void) {
|
||||
int a = 0;
|
||||
char *t;
|
||||
time_t time = 0;
|
||||
@@ -5774,7 +5778,7 @@ int test() {
|
||||
return a;
|
||||
}
|
||||
' > 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
|
||||
@@ -5843,7 +5847,7 @@ echo '
|
||||
#include <getopt.h>
|
||||
#endif
|
||||
|
||||
int test() {
|
||||
int test(void) {
|
||||
int a;
|
||||
char **opts = NULL;
|
||||
struct timeval tv;
|
||||
@@ -5856,7 +5860,7 @@ int test() {
|
||||
return a;
|
||||
}
|
||||
' > 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
|
||||
@@ -6607,6 +6611,11 @@ $as_echo "no" >&6; };
|
||||
fi
|
||||
|
||||
fi
|
||||
if test "$LEX" = "" -o "$LEX" = ":"; then
|
||||
if test ! -f util/configlexer.c; then
|
||||
as_fn_error $? "no lex and no util/configlexer.c: need flex and bison to compile from source repository." "$LINENO" 5
|
||||
fi
|
||||
fi
|
||||
for ac_prog in 'bison -y' byacc
|
||||
do
|
||||
# Extract the first word of "$ac_prog", so it can be a program name with args.
|
||||
@@ -6650,6 +6659,11 @@ fi
|
||||
done
|
||||
test -n "$YACC" || YACC="yacc"
|
||||
|
||||
if test "$YACC" = "" -o "$YACC" = ":"; then
|
||||
if test ! -f util/configparser.c; then
|
||||
as_fn_error $? "no yacc and no util/configparser.c: need flex and bison to compile from source repository." "$LINENO" 5
|
||||
fi
|
||||
fi
|
||||
# Extract the first word of "doxygen", so it can be a program name with args.
|
||||
set dummy doxygen; ac_word=$2
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
|
||||
@@ -14771,7 +14785,7 @@ fi
|
||||
fi
|
||||
|
||||
# Checks for header files.
|
||||
for ac_header in stdarg.h stdbool.h netinet/in.h netinet/tcp.h sys/param.h sys/select.h sys/socket.h sys/un.h sys/uio.h sys/resource.h arpa/inet.h syslog.h netdb.h sys/wait.h pwd.h glob.h grp.h login_cap.h winsock2.h ws2tcpip.h endian.h sys/endian.h libkern/OSByteOrder.h sys/ipc.h sys/shm.h ifaddrs.h
|
||||
for ac_header in stdarg.h stdbool.h netinet/in.h netinet/tcp.h sys/param.h sys/select.h sys/socket.h sys/un.h sys/uio.h sys/resource.h arpa/inet.h syslog.h netdb.h sys/wait.h pwd.h glob.h grp.h login_cap.h winsock2.h ws2tcpip.h endian.h sys/endian.h libkern/OSByteOrder.h sys/ipc.h sys/shm.h ifaddrs.h poll.h
|
||||
do :
|
||||
as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
|
||||
ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default
|
||||
@@ -14874,6 +14888,21 @@ fi
|
||||
done
|
||||
|
||||
|
||||
# Check for Linux timestamping headers
|
||||
for ac_header in linux/net_tstamp.h
|
||||
do :
|
||||
ac_fn_c_check_header_compile "$LINENO" "linux/net_tstamp.h" "ac_cv_header_linux_net_tstamp_h" "$ac_includes_default
|
||||
"
|
||||
if test "x$ac_cv_header_linux_net_tstamp_h" = xyes; then :
|
||||
cat >>confdefs.h <<_ACEOF
|
||||
#define HAVE_LINUX_NET_TSTAMP_H 1
|
||||
_ACEOF
|
||||
|
||||
fi
|
||||
|
||||
done
|
||||
|
||||
|
||||
# check for types.
|
||||
# Using own tests for int64* because autoconf builtin only give 32bit.
|
||||
ac_fn_c_check_type "$LINENO" "int8_t" "ac_cv_type_int8_t" "$ac_includes_default"
|
||||
@@ -15951,12 +15980,12 @@ else
|
||||
|
||||
echo '
|
||||
#include <stdio.h>
|
||||
int test() {
|
||||
int test(void) {
|
||||
int a = fseeko(stdin, 0, 0);
|
||||
return a;
|
||||
}
|
||||
' > 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
|
||||
@@ -16030,6 +16059,9 @@ else
|
||||
#ifdef HAVE_SYS_TYPES_H
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_SELECT_H
|
||||
#include <sys/select.h>
|
||||
#endif
|
||||
#ifdef HAVE_SYS_SOCKET_H
|
||||
#include <sys/socket.h>
|
||||
#endif
|
||||
@@ -17100,6 +17132,72 @@ _ACEOF
|
||||
|
||||
fi
|
||||
|
||||
# The cast to long int works around a bug in the HP C Compiler
|
||||
# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
|
||||
# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
|
||||
# This bug is HP SR number 8606223364.
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of unsigned long" >&5
|
||||
$as_echo_n "checking size of unsigned long... " >&6; }
|
||||
if ${ac_cv_sizeof_unsigned_long+:} false; then :
|
||||
$as_echo_n "(cached) " >&6
|
||||
else
|
||||
if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (unsigned long))" "ac_cv_sizeof_unsigned_long" "$ac_includes_default"; then :
|
||||
|
||||
else
|
||||
if test "$ac_cv_type_unsigned_long" = yes; then
|
||||
{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
|
||||
$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
|
||||
as_fn_error 77 "cannot compute sizeof (unsigned long)
|
||||
See \`config.log' for more details" "$LINENO" 5; }
|
||||
else
|
||||
ac_cv_sizeof_unsigned_long=0
|
||||
fi
|
||||
fi
|
||||
|
||||
fi
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_unsigned_long" >&5
|
||||
$as_echo "$ac_cv_sizeof_unsigned_long" >&6; }
|
||||
|
||||
|
||||
|
||||
cat >>confdefs.h <<_ACEOF
|
||||
#define SIZEOF_UNSIGNED_LONG $ac_cv_sizeof_unsigned_long
|
||||
_ACEOF
|
||||
|
||||
|
||||
# The cast to long int works around a bug in the HP C Compiler
|
||||
# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
|
||||
# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
|
||||
# This bug is HP SR number 8606223364.
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of pthread_t" >&5
|
||||
$as_echo_n "checking size of pthread_t... " >&6; }
|
||||
if ${ac_cv_sizeof_pthread_t+:} false; then :
|
||||
$as_echo_n "(cached) " >&6
|
||||
else
|
||||
if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (pthread_t))" "ac_cv_sizeof_pthread_t" "$ac_includes_default"; then :
|
||||
|
||||
else
|
||||
if test "$ac_cv_type_pthread_t" = yes; then
|
||||
{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
|
||||
$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
|
||||
as_fn_error 77 "cannot compute sizeof (pthread_t)
|
||||
See \`config.log' for more details" "$LINENO" 5; }
|
||||
else
|
||||
ac_cv_sizeof_pthread_t=0
|
||||
fi
|
||||
fi
|
||||
|
||||
fi
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_pthread_t" >&5
|
||||
$as_echo "$ac_cv_sizeof_pthread_t" >&6; }
|
||||
|
||||
|
||||
|
||||
cat >>confdefs.h <<_ACEOF
|
||||
#define SIZEOF_PTHREAD_T $ac_cv_sizeof_pthread_t
|
||||
_ACEOF
|
||||
|
||||
|
||||
|
||||
if echo "$CFLAGS" | $GREP -e "-pthread" >/dev/null; then
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if -pthread unused during linking" >&5
|
||||
@@ -17469,39 +17567,68 @@ fi
|
||||
PYTHON_VERSION=`$PYTHON -c "import sys; \
|
||||
print(sys.version.split()[0])"`
|
||||
fi
|
||||
# calculate the version number components.
|
||||
|
||||
# Check if you have sysconfig
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for the sysconfig Python module" >&5
|
||||
$as_echo_n "checking for the sysconfig Python module... " >&6; }
|
||||
if ac_sysconfig_result=`$PYTHON -c "import sysconfig" 2>&1`; then
|
||||
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
|
||||
|
||||
|
||||
# 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=""
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for the $m Python module" >&5
|
||||
$as_echo_n "checking for the $m Python module... " >&6; }
|
||||
if ac_modulecheck_result1=`$PYTHON -c "import $m" 2>&1`; then
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
|
||||
$as_echo "yes" >&6; }
|
||||
sysconfig_module="sysconfig"
|
||||
# if yes, use sysconfig, because distutils is deprecated.
|
||||
sysconfig_module="$m"
|
||||
else
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
$as_echo "no" >&6; }
|
||||
# if no, try to use distutils
|
||||
fi
|
||||
|
||||
#
|
||||
# Check if you have distutils, else fail
|
||||
#
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for the distutils Python package" >&5
|
||||
$as_echo_n "checking for the distutils Python package... " >&6; }
|
||||
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
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for the $m2 Python module" >&5
|
||||
$as_echo_n "checking for the $m2 Python module... " >&6; }
|
||||
if ac_modulecheck_result2=`$PYTHON -c "import $m2" 2>&1`; then
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
|
||||
$as_echo "yes" >&6; }
|
||||
sysconfig_module="$m2"
|
||||
else
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
$as_echo "no" >&6; }
|
||||
as_fn_error $? "cannot import Python module \"distutils\".
|
||||
Please check your Python installation. The error was:
|
||||
$ac_distutils_result" "$LINENO" 5
|
||||
as_fn_error $? "cannot import Python module \"$m\", or \"$m2\".
|
||||
Please check your Python installation. The errors are:
|
||||
$m
|
||||
$ac_modulecheck_result1
|
||||
$m2
|
||||
$ac_modulecheck_result2" "$LINENO" 5
|
||||
PYTHON_VERSION=""
|
||||
fi
|
||||
|
||||
sysconfig_module="distutils.sysconfig"
|
||||
fi
|
||||
if test "$sysconfig_module" = "distutils"; then sysconfig_module="distutils.sysconfig"; fi
|
||||
|
||||
#
|
||||
# Check for Python include path
|
||||
@@ -17633,7 +17760,14 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
|
||||
#
|
||||
|
||||
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
|
||||
as_fn_error $? "Python version >= 2.4.0 is required" "$LINENO" 5
|
||||
fi
|
||||
|
||||
@@ -20102,7 +20236,7 @@ char* (*f) () = getaddrinfo;
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
int main() {
|
||||
int main(void) {
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
@@ -20376,7 +20510,7 @@ echo '
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
' >conftest.c
|
||||
echo 'void f(){ (void)daemon(0, 0); }' >>conftest.c
|
||||
echo 'void f(void){ (void)daemon(0, 0); }' >>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
|
||||
@@ -20590,7 +20724,7 @@ if test "$ac_res" != no; then :
|
||||
|
||||
fi
|
||||
|
||||
for ac_func in tzset sigprocmask fcntl getpwnam endpwent getrlimit setrlimit setsid chroot kill chown sleep usleep random srandom recvmsg sendmsg writev socketpair glob initgroups strftime localtime_r setusercontext _beginthreadex endservent endprotoent fsync shmget accept4 getifaddrs if_nametoindex
|
||||
for ac_func in tzset sigprocmask fcntl getpwnam endpwent getrlimit setrlimit setsid chroot kill chown sleep usleep random srandom recvmsg sendmsg writev socketpair glob initgroups strftime localtime_r setusercontext _beginthreadex endservent endprotoent fsync shmget accept4 getifaddrs if_nametoindex poll gettid
|
||||
do :
|
||||
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
|
||||
ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
|
||||
@@ -22014,7 +22148,7 @@ _ACEOF
|
||||
|
||||
|
||||
|
||||
version=1.16.2
|
||||
version=1.18.0
|
||||
|
||||
date=`date +'%b %e, %Y'`
|
||||
|
||||
@@ -22533,7 +22667,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
|
||||
# report actual input values of CONFIG_FILES etc. instead of their
|
||||
# values after options handling.
|
||||
ac_log="
|
||||
This file was extended by unbound $as_me 1.16.2, which was
|
||||
This file was extended by unbound $as_me 1.18.0, which was
|
||||
generated by GNU Autoconf 2.69. Invocation command line was
|
||||
|
||||
CONFIG_FILES = $CONFIG_FILES
|
||||
@@ -22599,7 +22733,7 @@ _ACEOF
|
||||
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
|
||||
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
|
||||
ac_cs_version="\\
|
||||
unbound config.status 1.16.2
|
||||
unbound config.status 1.18.0
|
||||
configured by $0, generated by GNU Autoconf 2.69,
|
||||
with options \\"\$ac_cs_config\\"
|
||||
|
||||
|
||||
+67
-41
@@ -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],[16])
|
||||
m4_define([VERSION_MICRO],[2])
|
||||
m4_define([VERSION_MINOR],[18])
|
||||
m4_define([VERSION_MICRO],[0])
|
||||
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=18
|
||||
LIBUNBOUND_REVISION=22
|
||||
LIBUNBOUND_AGE=1
|
||||
# 1.0.0 had 0:12:0
|
||||
# 1.0.1 had 0:13:0
|
||||
@@ -104,6 +104,10 @@ LIBUNBOUND_AGE=1
|
||||
# 1.16.0 had 9:16:1
|
||||
# 1.16.1 had 9:17:1
|
||||
# 1.16.2 had 9:18: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
|
||||
|
||||
# Current -- the number of the binary API that we're implementing
|
||||
# Revision -- which iteration of the implementation of the binary
|
||||
@@ -153,7 +157,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
|
||||
@@ -182,9 +186,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
|
||||
@@ -195,9 +199,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
|
||||
@@ -215,9 +219,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
|
||||
@@ -228,9 +232,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
|
||||
@@ -241,9 +245,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
|
||||
@@ -254,9 +258,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])
|
||||
@@ -282,7 +286,7 @@ 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
|
||||
@@ -385,7 +389,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
|
||||
@@ -396,7 +410,7 @@ PKG_PROG_PKG_CONFIG
|
||||
fi
|
||||
|
||||
# Checks for header files.
|
||||
AC_CHECK_HEADERS([stdarg.h stdbool.h netinet/in.h netinet/tcp.h sys/param.h sys/select.h sys/socket.h sys/un.h sys/uio.h sys/resource.h arpa/inet.h syslog.h netdb.h sys/wait.h pwd.h glob.h grp.h login_cap.h winsock2.h ws2tcpip.h endian.h sys/endian.h libkern/OSByteOrder.h sys/ipc.h sys/shm.h ifaddrs.h],,, [AC_INCLUDES_DEFAULT])
|
||||
AC_CHECK_HEADERS([stdarg.h stdbool.h netinet/in.h netinet/tcp.h sys/param.h sys/select.h sys/socket.h sys/un.h sys/uio.h sys/resource.h arpa/inet.h syslog.h netdb.h sys/wait.h pwd.h glob.h grp.h login_cap.h winsock2.h ws2tcpip.h endian.h sys/endian.h libkern/OSByteOrder.h sys/ipc.h sys/shm.h ifaddrs.h poll.h],,, [AC_INCLUDES_DEFAULT])
|
||||
# net/if.h portability for Darwin see:
|
||||
# https://www.gnu.org/software/autoconf/manual/autoconf-2.69/html_node/Header-Portability.html
|
||||
AC_CHECK_HEADERS([net/if.h],,, [
|
||||
@@ -450,6 +464,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)
|
||||
@@ -545,11 +562,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])
|
||||
@@ -582,7 +599,7 @@ if test "$on_mingw" = "yes"; then
|
||||
])],
|
||||
AC_MSG_RESULT(yes)
|
||||
AC_DEFINE(HAVE_WINDOWS_THREADS, 1, [Using Windows threads])
|
||||
,
|
||||
,
|
||||
AC_MSG_RESULT(no)
|
||||
)
|
||||
|
||||
@@ -593,7 +610,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
|
||||
@@ -606,6 +623,8 @@ if test x_$withval != x_no; then
|
||||
CC="$PTHREAD_CC"
|
||||
ub_have_pthreads=yes
|
||||
AC_CHECK_TYPES([pthread_spinlock_t, pthread_rwlock_t],,,[#include <pthread.h>])
|
||||
AC_CHECK_SIZEOF([unsigned long])
|
||||
AC_CHECK_SIZEOF(pthread_t)
|
||||
|
||||
if echo "$CFLAGS" | $GREP -e "-pthread" >/dev/null; then
|
||||
AC_MSG_CHECKING([if -pthread unused during linking])
|
||||
@@ -618,7 +637,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
|
||||
@@ -639,7 +658,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
|
||||
@@ -653,8 +672,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
|
||||
@@ -729,7 +748,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
|
||||
|
||||
@@ -1080,7 +1106,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 */
|
||||
@@ -1524,7 +1550,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).])
|
||||
@@ -1643,7 +1669,7 @@ AC_LINK_IFELSE([AC_LANG_PROGRAM([
|
||||
AC_MSG_RESULT(no))
|
||||
|
||||
AC_SEARCH_LIBS([setusercontext], [util])
|
||||
AC_CHECK_FUNCS([tzset sigprocmask fcntl getpwnam endpwent getrlimit setrlimit setsid chroot kill chown sleep usleep random srandom recvmsg sendmsg writev socketpair glob initgroups strftime localtime_r setusercontext _beginthreadex endservent endprotoent fsync shmget accept4 getifaddrs if_nametoindex])
|
||||
AC_CHECK_FUNCS([tzset sigprocmask fcntl getpwnam endpwent getrlimit setrlimit setsid chroot kill chown sleep usleep random srandom recvmsg sendmsg writev socketpair glob initgroups strftime localtime_r setusercontext _beginthreadex endservent endprotoent fsync shmget accept4 getifaddrs if_nametoindex poll gettid])
|
||||
AC_CHECK_FUNCS([setresuid],,[AC_CHECK_FUNCS([setreuid])])
|
||||
AC_CHECK_FUNCS([setresgid],,[AC_CHECK_FUNCS([setregid])])
|
||||
|
||||
@@ -1975,11 +2001,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
|
||||
|
||||
@@ -1990,7 +2016,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
|
||||
|
||||
+389
-88
@@ -46,9 +46,10 @@
|
||||
#include "util/config_file.h"
|
||||
#include "util/net_help.h"
|
||||
#include "services/localzone.h"
|
||||
#include "services/listen_dnsport.h"
|
||||
#include "sldns/str2wire.h"
|
||||
|
||||
struct acl_list*
|
||||
struct acl_list*
|
||||
acl_list_create(void)
|
||||
{
|
||||
struct acl_list* acl = (struct acl_list*)calloc(1,
|
||||
@@ -63,10 +64,10 @@ acl_list_create(void)
|
||||
return acl;
|
||||
}
|
||||
|
||||
void
|
||||
void
|
||||
acl_list_delete(struct acl_list* acl)
|
||||
{
|
||||
if(!acl)
|
||||
if(!acl)
|
||||
return;
|
||||
regional_destroy(acl->region);
|
||||
free(acl);
|
||||
@@ -74,8 +75,8 @@ acl_list_delete(struct acl_list* acl)
|
||||
|
||||
/** insert new address into acl_list structure */
|
||||
static struct acl_addr*
|
||||
acl_list_insert(struct acl_list* acl, struct sockaddr_storage* addr,
|
||||
socklen_t addrlen, int net, enum acl_access control,
|
||||
acl_list_insert(struct acl_list* acl, struct sockaddr_storage* addr,
|
||||
socklen_t addrlen, int net, enum acl_access control,
|
||||
int complain_duplicates)
|
||||
{
|
||||
struct acl_addr* node = regional_alloc_zero(acl->region,
|
||||
@@ -90,6 +91,33 @@ acl_list_insert(struct acl_list* acl, struct sockaddr_storage* addr,
|
||||
return node;
|
||||
}
|
||||
|
||||
/** parse str to acl_access enum */
|
||||
static int
|
||||
parse_acl_access(const char* str, enum acl_access* control)
|
||||
{
|
||||
if(strcmp(str, "allow") == 0)
|
||||
*control = acl_allow;
|
||||
else if(strcmp(str, "deny") == 0)
|
||||
*control = acl_deny;
|
||||
else if(strcmp(str, "refuse") == 0)
|
||||
*control = acl_refuse;
|
||||
else if(strcmp(str, "deny_non_local") == 0)
|
||||
*control = acl_deny_non_local;
|
||||
else if(strcmp(str, "refuse_non_local") == 0)
|
||||
*control = acl_refuse_non_local;
|
||||
else if(strcmp(str, "allow_snoop") == 0)
|
||||
*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;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** apply acl_list string */
|
||||
static int
|
||||
acl_list_str_cfg(struct acl_list* acl, const char* str, const char* s2,
|
||||
@@ -99,29 +127,14 @@ acl_list_str_cfg(struct acl_list* acl, const char* str, const char* s2,
|
||||
int net;
|
||||
socklen_t addrlen;
|
||||
enum acl_access control;
|
||||
if(strcmp(s2, "allow") == 0)
|
||||
control = acl_allow;
|
||||
else if(strcmp(s2, "deny") == 0)
|
||||
control = acl_deny;
|
||||
else if(strcmp(s2, "refuse") == 0)
|
||||
control = acl_refuse;
|
||||
else if(strcmp(s2, "deny_non_local") == 0)
|
||||
control = acl_deny_non_local;
|
||||
else if(strcmp(s2, "refuse_non_local") == 0)
|
||||
control = acl_refuse_non_local;
|
||||
else if(strcmp(s2, "allow_snoop") == 0)
|
||||
control = acl_allow_snoop;
|
||||
else if(strcmp(s2, "allow_setrd") == 0)
|
||||
control = acl_allow_setrd;
|
||||
else {
|
||||
log_err("access control type %s unknown", str);
|
||||
if(!parse_acl_access(s2, &control)) {
|
||||
return 0;
|
||||
}
|
||||
if(!netblockstrtoaddr(str, UNBOUND_DNS_PORT, &addr, &addrlen, &net)) {
|
||||
log_err("cannot parse access control: %s %s", str, s2);
|
||||
return 0;
|
||||
}
|
||||
if(!acl_list_insert(acl, &addr, addrlen, net, control,
|
||||
if(!acl_list_insert(acl, &addr, addrlen, net, control,
|
||||
complain_duplicates)) {
|
||||
log_err("out of memory");
|
||||
return 0;
|
||||
@@ -131,19 +144,27 @@ acl_list_str_cfg(struct acl_list* acl, const char* str, const char* s2,
|
||||
|
||||
/** find or create node (NULL on parse or error) */
|
||||
static struct acl_addr*
|
||||
acl_find_or_create(struct acl_list* acl, const char* str)
|
||||
acl_find_or_create_str2addr(struct acl_list* acl, const char* str,
|
||||
int is_interface, int port)
|
||||
{
|
||||
struct acl_addr* node;
|
||||
struct sockaddr_storage addr;
|
||||
int net;
|
||||
socklen_t addrlen;
|
||||
if(!netblockstrtoaddr(str, UNBOUND_DNS_PORT, &addr, &addrlen, &net)) {
|
||||
log_err("cannot parse netblock: %s", str);
|
||||
return NULL;
|
||||
int net = (str_is_ip6(str)?128:32);
|
||||
if(is_interface) {
|
||||
if(!extstrtoaddr(str, &addr, &addrlen, port)) {
|
||||
log_err("cannot parse interface: %s", str);
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
if(!netblockstrtoaddr(str, UNBOUND_DNS_PORT, &addr, &addrlen, &net)) {
|
||||
log_err("cannot parse netblock: %s", str);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
/* find or create node */
|
||||
if(!(node=(struct acl_addr*)addr_tree_find(&acl->tree, &addr,
|
||||
addrlen, net))) {
|
||||
addrlen, net)) && !is_interface) {
|
||||
/* create node, type 'allow' since otherwise tags are
|
||||
* pointless, can override with specific access-control: cfg */
|
||||
if(!(node=(struct acl_addr*)acl_list_insert(acl, &addr,
|
||||
@@ -155,14 +176,65 @@ acl_find_or_create(struct acl_list* acl, const char* str)
|
||||
return node;
|
||||
}
|
||||
|
||||
/** find or create node (NULL on error) */
|
||||
static struct acl_addr*
|
||||
acl_find_or_create(struct acl_list* acl, struct sockaddr_storage* addr,
|
||||
socklen_t addrlen, enum acl_access control)
|
||||
{
|
||||
struct acl_addr* node;
|
||||
int net = (addr_is_ip6(addr, addrlen)?128:32);
|
||||
/* find or create node */
|
||||
if(!(node=(struct acl_addr*)addr_tree_find(&acl->tree, addr,
|
||||
addrlen, net))) {
|
||||
/* create node;
|
||||
* can override with specific access-control: cfg */
|
||||
if(!(node=(struct acl_addr*)acl_list_insert(acl, addr,
|
||||
addrlen, net, control, 1))) {
|
||||
log_err("out of memory");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
/** apply acl_interface string */
|
||||
static int
|
||||
acl_interface_str_cfg(struct acl_list* acl_interface, const char* iface,
|
||||
const char* s2, int port)
|
||||
{
|
||||
struct acl_addr* node;
|
||||
enum acl_access control;
|
||||
if(!parse_acl_access(s2, &control)) {
|
||||
return 0;
|
||||
}
|
||||
if(!(node=acl_find_or_create_str2addr(acl_interface, iface, 1, port))) {
|
||||
log_err("cannot update ACL on non-configured interface: %s %d",
|
||||
iface, port);
|
||||
return 0;
|
||||
}
|
||||
node->control = control;
|
||||
return 1;
|
||||
}
|
||||
|
||||
struct acl_addr*
|
||||
acl_interface_insert(struct acl_list* acl_interface,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen,
|
||||
enum acl_access control)
|
||||
{
|
||||
return acl_find_or_create(acl_interface, addr, addrlen, control);
|
||||
}
|
||||
|
||||
/** apply acl_tag string */
|
||||
static int
|
||||
acl_list_tags_cfg(struct acl_list* acl, const char* str, uint8_t* bitmap,
|
||||
size_t bitmaplen)
|
||||
size_t bitmaplen, int is_interface, int port)
|
||||
{
|
||||
struct acl_addr* node;
|
||||
if(!(node=acl_find_or_create(acl, str)))
|
||||
if(!(node=acl_find_or_create_str2addr(acl, str, is_interface, port))) {
|
||||
if(is_interface)
|
||||
log_err("non-configured interface: %s", str);
|
||||
return 0;
|
||||
}
|
||||
node->taglen = bitmaplen;
|
||||
node->taglist = regional_alloc_init(acl->region, bitmap, bitmaplen);
|
||||
if(!node->taglist) {
|
||||
@@ -175,11 +247,14 @@ acl_list_tags_cfg(struct acl_list* acl, const char* str, uint8_t* bitmap,
|
||||
/** apply acl_view string */
|
||||
static int
|
||||
acl_list_view_cfg(struct acl_list* acl, const char* str, const char* str2,
|
||||
struct views* vs)
|
||||
struct views* vs, int is_interface, int port)
|
||||
{
|
||||
struct acl_addr* node;
|
||||
if(!(node=acl_find_or_create(acl, str)))
|
||||
if(!(node=acl_find_or_create_str2addr(acl, str, is_interface, port))) {
|
||||
if(is_interface)
|
||||
log_err("non-configured interface: %s", str);
|
||||
return 0;
|
||||
}
|
||||
node->view = views_find_view(vs, str2, 0 /* get read lock*/);
|
||||
if(!node->view) {
|
||||
log_err("no view with name: %s", str2);
|
||||
@@ -192,13 +267,17 @@ acl_list_view_cfg(struct acl_list* acl, const char* str, const char* str2,
|
||||
/** apply acl_tag_action string */
|
||||
static int
|
||||
acl_list_tag_action_cfg(struct acl_list* acl, struct config_file* cfg,
|
||||
const char* str, const char* tag, const char* action)
|
||||
const char* str, const char* tag, const char* action,
|
||||
int is_interface, int port)
|
||||
{
|
||||
struct acl_addr* node;
|
||||
int tagid;
|
||||
enum localzone_type t;
|
||||
if(!(node=acl_find_or_create(acl, str)))
|
||||
if(!(node=acl_find_or_create_str2addr(acl, str, is_interface, port))) {
|
||||
if(is_interface)
|
||||
log_err("non-configured interface: %s", str);
|
||||
return 0;
|
||||
}
|
||||
/* allocate array if not yet */
|
||||
if(!node->tag_actions) {
|
||||
node->tag_actions = (uint8_t*)regional_alloc_zero(acl->region,
|
||||
@@ -281,13 +360,17 @@ check_data(const char* data, const struct config_strlist* head)
|
||||
/** apply acl_tag_data string */
|
||||
static int
|
||||
acl_list_tag_data_cfg(struct acl_list* acl, struct config_file* cfg,
|
||||
const char* str, const char* tag, const char* data)
|
||||
const char* str, const char* tag, const char* data,
|
||||
int is_interface, int port)
|
||||
{
|
||||
struct acl_addr* node;
|
||||
int tagid;
|
||||
char* dupdata;
|
||||
if(!(node=acl_find_or_create(acl, str)))
|
||||
if(!(node=acl_find_or_create_str2addr(acl, str, is_interface, port))) {
|
||||
if(is_interface)
|
||||
log_err("non-configured interface: %s", str);
|
||||
return 0;
|
||||
}
|
||||
/* allocate array if not yet */
|
||||
if(!node->tag_datas) {
|
||||
node->tag_datas = (struct config_strlist**)regional_alloc_zero(
|
||||
@@ -329,11 +412,11 @@ acl_list_tag_data_cfg(struct acl_list* acl, struct config_file* cfg,
|
||||
}
|
||||
|
||||
/** read acl_list config */
|
||||
static int
|
||||
read_acl_list(struct acl_list* acl, struct config_file* cfg)
|
||||
static int
|
||||
read_acl_list(struct acl_list* acl, struct config_str2list* acls)
|
||||
{
|
||||
struct config_str2list* p;
|
||||
for(p = cfg->acls; p; p = p->next) {
|
||||
for(p = acls; p; p = p->next) {
|
||||
log_assert(p->str && p->str2);
|
||||
if(!acl_list_str_cfg(acl, p->str, p->str2, 1))
|
||||
return 0;
|
||||
@@ -341,15 +424,38 @@ read_acl_list(struct acl_list* acl, struct config_file* cfg)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** read acl tags config */
|
||||
static int
|
||||
read_acl_tags(struct acl_list* acl, struct config_file* cfg)
|
||||
/** read acl view config */
|
||||
static int
|
||||
read_acl_view(struct acl_list* acl, struct config_str2list** acl_view,
|
||||
struct views* v)
|
||||
{
|
||||
struct config_strbytelist* np, *p = cfg->acl_tags;
|
||||
cfg->acl_tags = NULL;
|
||||
struct config_str2list* np, *p = *acl_view;
|
||||
*acl_view = NULL;
|
||||
while(p) {
|
||||
log_assert(p->str && p->str2);
|
||||
if(!acl_list_tags_cfg(acl, p->str, p->str2, p->str2len)) {
|
||||
if(!acl_list_view_cfg(acl, p->str, p->str2, v, 0, 0)) {
|
||||
config_deldblstrlist(p);
|
||||
return 0;
|
||||
}
|
||||
/* free the items as we go to free up memory */
|
||||
np = p->next;
|
||||
free(p->str);
|
||||
free(p->str2);
|
||||
free(p);
|
||||
p = np;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** read acl tags config */
|
||||
static int
|
||||
read_acl_tags(struct acl_list* acl, struct config_strbytelist** acl_tags)
|
||||
{
|
||||
struct config_strbytelist* np, *p = *acl_tags;
|
||||
*acl_tags = NULL;
|
||||
while(p) {
|
||||
log_assert(p->str && p->str2);
|
||||
if(!acl_list_tags_cfg(acl, p->str, p->str2, p->str2len, 0, 0)) {
|
||||
config_del_strbytelist(p);
|
||||
return 0;
|
||||
}
|
||||
@@ -363,38 +469,18 @@ read_acl_tags(struct acl_list* acl, struct config_file* cfg)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** read acl view config */
|
||||
static int
|
||||
read_acl_view(struct acl_list* acl, struct config_file* cfg, struct views* v)
|
||||
{
|
||||
struct config_str2list* np, *p = cfg->acl_view;
|
||||
cfg->acl_view = NULL;
|
||||
while(p) {
|
||||
log_assert(p->str && p->str2);
|
||||
if(!acl_list_view_cfg(acl, p->str, p->str2, v)) {
|
||||
return 0;
|
||||
}
|
||||
/* free the items as we go to free up memory */
|
||||
np = p->next;
|
||||
free(p->str);
|
||||
free(p->str2);
|
||||
free(p);
|
||||
p = np;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** read acl tag actions config */
|
||||
static int
|
||||
read_acl_tag_actions(struct acl_list* acl, struct config_file* cfg)
|
||||
static int
|
||||
read_acl_tag_actions(struct acl_list* acl, struct config_file* cfg,
|
||||
struct config_str3list** acl_tag_actions)
|
||||
{
|
||||
struct config_str3list* p, *np;
|
||||
p = cfg->acl_tag_actions;
|
||||
cfg->acl_tag_actions = NULL;
|
||||
p = *acl_tag_actions;
|
||||
*acl_tag_actions = NULL;
|
||||
while(p) {
|
||||
log_assert(p->str && p->str2 && p->str3);
|
||||
if(!acl_list_tag_action_cfg(acl, cfg, p->str, p->str2,
|
||||
p->str3)) {
|
||||
p->str3, 0, 0)) {
|
||||
config_deltrplstrlist(p);
|
||||
return 0;
|
||||
}
|
||||
@@ -410,15 +496,17 @@ read_acl_tag_actions(struct acl_list* acl, struct config_file* cfg)
|
||||
}
|
||||
|
||||
/** read acl tag datas config */
|
||||
static int
|
||||
read_acl_tag_datas(struct acl_list* acl, struct config_file* cfg)
|
||||
static int
|
||||
read_acl_tag_datas(struct acl_list* acl, struct config_file* cfg,
|
||||
struct config_str3list** acl_tag_datas)
|
||||
{
|
||||
struct config_str3list* p, *np;
|
||||
p = cfg->acl_tag_datas;
|
||||
cfg->acl_tag_datas = NULL;
|
||||
p = *acl_tag_datas;
|
||||
*acl_tag_datas = NULL;
|
||||
while(p) {
|
||||
log_assert(p->str && p->str2 && p->str3);
|
||||
if(!acl_list_tag_data_cfg(acl, cfg, p->str, p->str2, p->str3)) {
|
||||
if(!acl_list_tag_data_cfg(acl, cfg, p->str, p->str2, p->str3,
|
||||
0, 0)) {
|
||||
config_deltrplstrlist(p);
|
||||
return 0;
|
||||
}
|
||||
@@ -433,30 +521,27 @@ read_acl_tag_datas(struct acl_list* acl, struct config_file* cfg)
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
int
|
||||
acl_list_apply_cfg(struct acl_list* acl, struct config_file* cfg,
|
||||
struct views* v)
|
||||
{
|
||||
regional_free_all(acl->region);
|
||||
addr_tree_init(&acl->tree);
|
||||
if(!read_acl_list(acl, cfg))
|
||||
if(!read_acl_list(acl, cfg->acls))
|
||||
return 0;
|
||||
if(!read_acl_view(acl, cfg, v))
|
||||
if(!read_acl_view(acl, &cfg->acl_view, v))
|
||||
return 0;
|
||||
if(!read_acl_tags(acl, cfg))
|
||||
if(!read_acl_tags(acl, &cfg->acl_tags))
|
||||
return 0;
|
||||
if(!read_acl_tag_actions(acl, cfg))
|
||||
if(!read_acl_tag_actions(acl, cfg, &cfg->acl_tag_actions))
|
||||
return 0;
|
||||
if(!read_acl_tag_datas(acl, cfg))
|
||||
if(!read_acl_tag_datas(acl, cfg, &cfg->acl_tag_datas))
|
||||
return 0;
|
||||
/* insert defaults, with '0' to ignore them if they are duplicates */
|
||||
if(!acl_list_str_cfg(acl, "0.0.0.0/0", "refuse", 0))
|
||||
return 0;
|
||||
/* the 'refuse' defaults for /0 are now done per interface instead */
|
||||
if(!acl_list_str_cfg(acl, "127.0.0.0/8", "allow", 0))
|
||||
return 0;
|
||||
if(cfg->do_ip6) {
|
||||
if(!acl_list_str_cfg(acl, "::0/0", "refuse", 0))
|
||||
return 0;
|
||||
if(!acl_list_str_cfg(acl, "::1", "allow", 0))
|
||||
return 0;
|
||||
if(!acl_list_str_cfg(acl, "::ffff:127.0.0.1", "allow", 0))
|
||||
@@ -466,7 +551,223 @@ acl_list_apply_cfg(struct acl_list* acl, struct config_file* cfg,
|
||||
return 1;
|
||||
}
|
||||
|
||||
enum acl_access
|
||||
int
|
||||
acl_interface_compare(const void* k1, const void* k2)
|
||||
{
|
||||
struct addr_tree_node* n1 = (struct addr_tree_node*)k1;
|
||||
struct addr_tree_node* n2 = (struct addr_tree_node*)k2;
|
||||
return sockaddr_cmp(&n1->addr, n1->addrlen, &n2->addr,
|
||||
n2->addrlen);
|
||||
/* We don't care about comparing node->net. All addresses in the
|
||||
* acl_interface tree have either 32 (ipv4) or 128 (ipv6). */
|
||||
}
|
||||
|
||||
void
|
||||
acl_interface_init(struct acl_list* acl_interface)
|
||||
{
|
||||
regional_free_all(acl_interface->region);
|
||||
/* We want comparison in the tree to include only address and port.
|
||||
* We don't care about comparing node->net. All addresses in the
|
||||
* acl_interface->tree should have either 32 (ipv4) or 128 (ipv6).
|
||||
* Initialise with the appropriate compare function but keep treating
|
||||
* it as an addr_tree. */
|
||||
addr_tree_addrport_init(&acl_interface->tree);
|
||||
}
|
||||
|
||||
static int
|
||||
read_acl_interface_action(struct acl_list* acl_interface,
|
||||
struct config_str2list* acls, int port)
|
||||
{
|
||||
struct config_str2list* p;
|
||||
for(p = acls; p; p = p->next) {
|
||||
char** resif = NULL;
|
||||
int num_resif = 0;
|
||||
int i;
|
||||
log_assert(p->str && p->str2);
|
||||
if(!resolve_interface_names(&p->str, 1, NULL, &resif, &num_resif))
|
||||
return 0;
|
||||
for(i = 0; i<num_resif; i++) {
|
||||
if(!acl_interface_str_cfg(acl_interface, resif[i], p->str2, port)){
|
||||
config_del_strarray(resif, num_resif);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
config_del_strarray(resif, num_resif);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** read acl view config for interface */
|
||||
static int
|
||||
read_acl_interface_view(struct acl_list* acl_interface,
|
||||
struct config_str2list** acl_view,
|
||||
struct views* v, int port)
|
||||
{
|
||||
struct config_str2list* np, *p = *acl_view;
|
||||
*acl_view = NULL;
|
||||
while(p) {
|
||||
char** resif = NULL;
|
||||
int num_resif = 0;
|
||||
int i;
|
||||
log_assert(p->str && p->str2);
|
||||
if(!resolve_interface_names(&p->str, 1, NULL, &resif, &num_resif)) {
|
||||
config_deldblstrlist(p);
|
||||
return 0;
|
||||
}
|
||||
for(i = 0; i<num_resif; i++) {
|
||||
if(!acl_list_view_cfg(acl_interface, resif[i], p->str2,
|
||||
v, 1, port)) {
|
||||
config_del_strarray(resif, num_resif);
|
||||
config_deldblstrlist(p);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
config_del_strarray(resif, num_resif);
|
||||
/* free the items as we go to free up memory */
|
||||
np = p->next;
|
||||
free(p->str);
|
||||
free(p->str2);
|
||||
free(p);
|
||||
p = np;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** read acl tags config for interface */
|
||||
static int
|
||||
read_acl_interface_tags(struct acl_list* acl_interface,
|
||||
struct config_strbytelist** acl_tags, int port)
|
||||
{
|
||||
struct config_strbytelist* np, *p = *acl_tags;
|
||||
*acl_tags = NULL;
|
||||
while(p) {
|
||||
char** resif = NULL;
|
||||
int num_resif = 0;
|
||||
int i;
|
||||
log_assert(p->str && p->str2);
|
||||
if(!resolve_interface_names(&p->str, 1, NULL, &resif, &num_resif)) {
|
||||
config_del_strbytelist(p);
|
||||
return 0;
|
||||
}
|
||||
for(i = 0; i<num_resif; i++) {
|
||||
if(!acl_list_tags_cfg(acl_interface, resif[i], p->str2,
|
||||
p->str2len, 1, port)) {
|
||||
config_del_strbytelist(p);
|
||||
config_del_strarray(resif, num_resif);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
config_del_strarray(resif, num_resif);
|
||||
/* free the items as we go to free up memory */
|
||||
np = p->next;
|
||||
free(p->str);
|
||||
free(p->str2);
|
||||
free(p);
|
||||
p = np;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** read acl tag actions config for interface*/
|
||||
static int
|
||||
read_acl_interface_tag_actions(struct acl_list* acl_interface,
|
||||
struct config_file* cfg,
|
||||
struct config_str3list** acl_tag_actions, int port)
|
||||
{
|
||||
struct config_str3list* p, *np;
|
||||
p = *acl_tag_actions;
|
||||
*acl_tag_actions = NULL;
|
||||
while(p) {
|
||||
char** resif = NULL;
|
||||
int num_resif = 0;
|
||||
int i;
|
||||
log_assert(p->str && p->str2 && p->str3);
|
||||
if(!resolve_interface_names(&p->str, 1, NULL, &resif, &num_resif)) {
|
||||
config_deltrplstrlist(p);
|
||||
return 0;
|
||||
}
|
||||
for(i = 0; i<num_resif; i++) {
|
||||
if(!acl_list_tag_action_cfg(acl_interface, cfg,
|
||||
resif[i], p->str2, p->str3, 1, port)) {
|
||||
config_deltrplstrlist(p);
|
||||
config_del_strarray(resif, num_resif);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
config_del_strarray(resif, num_resif);
|
||||
/* free the items as we go to free up memory */
|
||||
np = p->next;
|
||||
free(p->str);
|
||||
free(p->str2);
|
||||
free(p->str3);
|
||||
free(p);
|
||||
p = np;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** read acl tag datas config for interface */
|
||||
static int
|
||||
read_acl_interface_tag_datas(struct acl_list* acl_interface,
|
||||
struct config_file* cfg,
|
||||
struct config_str3list** acl_tag_datas, int port)
|
||||
{
|
||||
struct config_str3list* p, *np;
|
||||
p = *acl_tag_datas;
|
||||
*acl_tag_datas = NULL;
|
||||
while(p) {
|
||||
char** resif = NULL;
|
||||
int num_resif = 0;
|
||||
int i;
|
||||
log_assert(p->str && p->str2 && p->str3);
|
||||
if(!resolve_interface_names(&p->str, 1, NULL, &resif, &num_resif)) {
|
||||
config_deltrplstrlist(p);
|
||||
return 0;
|
||||
}
|
||||
for(i = 0; i<num_resif; i++) {
|
||||
if(!acl_list_tag_data_cfg(acl_interface, cfg,
|
||||
resif[i], p->str2, p->str3, 1, port)) {
|
||||
config_deltrplstrlist(p);
|
||||
config_del_strarray(resif, num_resif);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
config_del_strarray(resif, num_resif);
|
||||
/* free the items as we go to free up memory */
|
||||
np = p->next;
|
||||
free(p->str);
|
||||
free(p->str2);
|
||||
free(p->str3);
|
||||
free(p);
|
||||
p = np;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
acl_interface_apply_cfg(struct acl_list* acl_interface, struct config_file* cfg,
|
||||
struct views* v)
|
||||
{
|
||||
if(!read_acl_interface_action(acl_interface, cfg->interface_actions,
|
||||
cfg->port))
|
||||
return 0;
|
||||
if(!read_acl_interface_view(acl_interface, &cfg->interface_view, v,
|
||||
cfg->port))
|
||||
return 0;
|
||||
if(!read_acl_interface_tags(acl_interface, &cfg->interface_tags,
|
||||
cfg->port))
|
||||
return 0;
|
||||
if(!read_acl_interface_tag_actions(acl_interface, cfg,
|
||||
&cfg->interface_tag_actions, cfg->port))
|
||||
return 0;
|
||||
if(!read_acl_interface_tag_datas(acl_interface, cfg,
|
||||
&cfg->interface_tag_datas, cfg->port))
|
||||
return 0;
|
||||
addr_tree_init_parents(&acl_interface->tree);
|
||||
return 1;
|
||||
}
|
||||
|
||||
enum acl_access
|
||||
acl_get_control(struct acl_addr* acl)
|
||||
{
|
||||
if(acl) return acl->control;
|
||||
@@ -481,7 +782,7 @@ acl_addr_lookup(struct acl_list* acl, struct sockaddr_storage* addr,
|
||||
addr, addrlen);
|
||||
}
|
||||
|
||||
size_t
|
||||
size_t
|
||||
acl_list_get_mem(struct acl_list* acl)
|
||||
{
|
||||
if(!acl) return 0;
|
||||
|
||||
+42
-5
@@ -36,7 +36,7 @@
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* This file keeps track of the list of clients that are allowed to
|
||||
* This file keeps track of the list of clients that are allowed to
|
||||
* access the server.
|
||||
*/
|
||||
|
||||
@@ -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
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -74,7 +78,7 @@ enum acl_access {
|
||||
struct acl_list {
|
||||
/** regional for allocation */
|
||||
struct regional* region;
|
||||
/**
|
||||
/**
|
||||
* Tree of the addresses that are allowed/blocked.
|
||||
* contents of type acl_addr.
|
||||
*/
|
||||
@@ -108,7 +112,7 @@ struct acl_addr {
|
||||
};
|
||||
|
||||
/**
|
||||
* Create acl structure
|
||||
* Create acl structure
|
||||
* @return new structure or NULL on error.
|
||||
*/
|
||||
struct acl_list* acl_list_create(void);
|
||||
@@ -119,6 +123,20 @@ struct acl_list* acl_list_create(void);
|
||||
*/
|
||||
void acl_list_delete(struct acl_list* acl);
|
||||
|
||||
/**
|
||||
* Insert interface in the acl_list. This should happen when the listening
|
||||
* interface is setup.
|
||||
* @param acl_interface: acl_list to insert to.
|
||||
* @param addr: interface IP.
|
||||
* @param addrlen: length of the interface IP.
|
||||
* @param control: acl_access.
|
||||
* @return new structure or NULL on error.
|
||||
*/
|
||||
struct acl_addr*
|
||||
acl_interface_insert(struct acl_list* acl_interface,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen,
|
||||
enum acl_access control);
|
||||
|
||||
/**
|
||||
* Process access control config.
|
||||
* @param acl: where to store.
|
||||
@@ -129,6 +147,25 @@ void acl_list_delete(struct acl_list* acl);
|
||||
int acl_list_apply_cfg(struct acl_list* acl, struct config_file* cfg,
|
||||
struct views* v);
|
||||
|
||||
/** compare ACL interface "addr_tree" nodes (+port) */
|
||||
int acl_interface_compare(const void* k1, const void* k2);
|
||||
|
||||
/**
|
||||
* Initialise (also clean) the acl_interface struct.
|
||||
* @param acl_interface: where to store.
|
||||
*/
|
||||
void acl_interface_init(struct acl_list* acl_interface);
|
||||
|
||||
/**
|
||||
* Process interface control config.
|
||||
* @param acl_interface: where to store.
|
||||
* @param cfg: config options.
|
||||
* @param v: views structure
|
||||
* @return 0 on error.
|
||||
*/
|
||||
int acl_interface_apply_cfg(struct acl_list* acl_interface, struct config_file* cfg,
|
||||
struct views* v);
|
||||
|
||||
/**
|
||||
* Lookup access control status for acl structure.
|
||||
* @param acl: structure for acl storage.
|
||||
|
||||
+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 "
|
||||
|
||||
+147
-5
@@ -96,6 +96,9 @@
|
||||
#ifdef HAVE_SYSTEMD
|
||||
#include <systemd/sd-daemon.h>
|
||||
#endif
|
||||
#ifdef HAVE_NETDB_H
|
||||
#include <netdb.h>
|
||||
#endif
|
||||
|
||||
/** How many quit requests happened. */
|
||||
static int sig_record_quit = 0;
|
||||
@@ -271,8 +274,17 @@ daemon_init(void)
|
||||
free(daemon);
|
||||
return NULL;
|
||||
}
|
||||
daemon->acl_interface = acl_list_create();
|
||||
if(!daemon->acl_interface) {
|
||||
acl_list_delete(daemon->acl);
|
||||
edns_known_options_delete(daemon->env);
|
||||
free(daemon->env);
|
||||
free(daemon);
|
||||
return NULL;
|
||||
}
|
||||
daemon->tcl = tcl_list_create();
|
||||
if(!daemon->tcl) {
|
||||
acl_list_delete(daemon->acl_interface);
|
||||
acl_list_delete(daemon->acl);
|
||||
edns_known_options_delete(daemon->env);
|
||||
free(daemon->env);
|
||||
@@ -284,6 +296,7 @@ daemon_init(void)
|
||||
log_err("gettimeofday: %s", strerror(errno));
|
||||
daemon->time_last_stat = daemon->time_boot;
|
||||
if((daemon->env->auth_zones = auth_zones_create()) == 0) {
|
||||
acl_list_delete(daemon->acl_interface);
|
||||
acl_list_delete(daemon->acl);
|
||||
tcl_list_delete(daemon->tcl);
|
||||
edns_known_options_delete(daemon->env);
|
||||
@@ -293,6 +306,7 @@ daemon_init(void)
|
||||
}
|
||||
if(!(daemon->env->edns_strings = edns_strings_create())) {
|
||||
auth_zones_delete(daemon->env->auth_zones);
|
||||
acl_list_delete(daemon->acl_interface);
|
||||
acl_list_delete(daemon->acl);
|
||||
tcl_list_delete(daemon->tcl);
|
||||
edns_known_options_delete(daemon->env);
|
||||
@@ -303,6 +317,29 @@ daemon_init(void)
|
||||
return daemon;
|
||||
}
|
||||
|
||||
static int setup_acl_for_ports(struct acl_list* list,
|
||||
struct listen_port* port_list)
|
||||
{
|
||||
struct acl_addr* acl_node;
|
||||
struct addrinfo* addr;
|
||||
for(; port_list; port_list=port_list->next) {
|
||||
if(!port_list->socket) {
|
||||
/* This is mainly for testbound where port_list is
|
||||
* empty. */
|
||||
continue;
|
||||
}
|
||||
addr = port_list->socket->addr;
|
||||
if(!(acl_node = acl_interface_insert(list,
|
||||
(struct sockaddr_storage*)addr->ai_addr,
|
||||
(socklen_t)addr->ai_addrlen,
|
||||
acl_refuse))) {
|
||||
return 0;
|
||||
}
|
||||
port_list->socket->acl = acl_node;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
daemon_open_shared_ports(struct daemon* daemon)
|
||||
{
|
||||
@@ -320,6 +357,8 @@ daemon_open_shared_ports(struct daemon* daemon)
|
||||
free(daemon->ports);
|
||||
daemon->ports = NULL;
|
||||
}
|
||||
/* clean acl_interface */
|
||||
acl_interface_init(daemon->acl_interface);
|
||||
if(!resolve_interface_names(daemon->cfg->ifs,
|
||||
daemon->cfg->num_ifs, NULL, &resif, &num_resif))
|
||||
return 0;
|
||||
@@ -329,7 +368,8 @@ daemon_open_shared_ports(struct daemon* daemon)
|
||||
daemon->reuseport = 1;
|
||||
#endif
|
||||
/* try to use reuseport */
|
||||
p0 = listening_ports_open(daemon->cfg, resif, num_resif, &daemon->reuseport);
|
||||
p0 = listening_ports_open(daemon->cfg, resif, num_resif,
|
||||
&daemon->reuseport);
|
||||
if(!p0) {
|
||||
listening_ports_free(p0);
|
||||
config_del_strarray(resif, num_resif);
|
||||
@@ -350,6 +390,12 @@ daemon_open_shared_ports(struct daemon* daemon)
|
||||
return 0;
|
||||
}
|
||||
daemon->ports[0] = p0;
|
||||
if(!setup_acl_for_ports(daemon->acl_interface,
|
||||
daemon->ports[0])) {
|
||||
listening_ports_free(p0);
|
||||
config_del_strarray(resif, num_resif);
|
||||
return 0;
|
||||
}
|
||||
if(daemon->reuseport) {
|
||||
/* continue to use reuseport */
|
||||
for(i=1; i<daemon->num_ports; i++) {
|
||||
@@ -365,6 +411,15 @@ daemon_open_shared_ports(struct daemon* daemon)
|
||||
config_del_strarray(resif, num_resif);
|
||||
return 0;
|
||||
}
|
||||
if(!setup_acl_for_ports(daemon->acl_interface,
|
||||
daemon->ports[i])) {
|
||||
for(i=0; i<daemon->num_ports; i++)
|
||||
listening_ports_free(daemon->ports[i]);
|
||||
free(daemon->ports);
|
||||
daemon->ports = NULL;
|
||||
config_del_strarray(resif, num_resif);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
config_del_strarray(resif, num_resif);
|
||||
@@ -433,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.
|
||||
@@ -485,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);
|
||||
}
|
||||
|
||||
@@ -604,6 +695,9 @@ daemon_fork(struct daemon* daemon)
|
||||
|
||||
if(!acl_list_apply_cfg(daemon->acl, daemon->cfg, daemon->views))
|
||||
fatal_exit("Could not setup access control list");
|
||||
if(!acl_interface_apply_cfg(daemon->acl_interface, daemon->cfg,
|
||||
daemon->views))
|
||||
fatal_exit("Could not setup interface control list");
|
||||
if(!tcl_list_apply_cfg(daemon->tcl, daemon->cfg))
|
||||
fatal_exit("Could not setup TCP connection limits");
|
||||
if(daemon->cfg->dnscrypt) {
|
||||
@@ -713,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;
|
||||
}
|
||||
|
||||
@@ -727,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);
|
||||
@@ -744,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;
|
||||
@@ -780,6 +887,7 @@ daemon_delete(struct daemon* daemon)
|
||||
ub_randfree(daemon->rand);
|
||||
alloc_clear(&daemon->superalloc);
|
||||
acl_list_delete(daemon->acl);
|
||||
acl_list_delete(daemon->acl_interface);
|
||||
tcl_list_delete(daemon->tcl);
|
||||
listen_desetup_locks();
|
||||
free(daemon->chroot);
|
||||
@@ -841,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*/
|
||||
@@ -113,6 +117,8 @@ struct daemon {
|
||||
struct module_stack mods;
|
||||
/** access control, which client IPs are allowed to connect */
|
||||
struct acl_list* acl;
|
||||
/** access control, which interfaces are allowed to connect */
|
||||
struct acl_list* acl_interface;
|
||||
/** TCP connection limit, limit connections from client IPs */
|
||||
struct tcl_list* tcl;
|
||||
/** local authority zones */
|
||||
@@ -138,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;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
+122
-136
@@ -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");
|
||||
@@ -494,8 +452,8 @@ int remote_accept_callback(struct comm_point* c, void* arg, int err,
|
||||
n->c->do_not_close = 0;
|
||||
comm_point_stop_listening(n->c);
|
||||
comm_point_start_listening(n->c, -1, REMOTE_CONTROL_TCP_TIMEOUT);
|
||||
memcpy(&n->c->repinfo.addr, &addr, addrlen);
|
||||
n->c->repinfo.addrlen = addrlen;
|
||||
memcpy(&n->c->repinfo.remote_addr, &addr, addrlen);
|
||||
n->c->repinfo.remote_addrlen = addrlen;
|
||||
if(rc->use_cert) {
|
||||
n->shake_state = rc_hs_read;
|
||||
n->ssl = SSL_new(rc->ctx);
|
||||
@@ -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,7 +518,7 @@ int
|
||||
ssl_print_text(RES* res, const char* text)
|
||||
{
|
||||
int r;
|
||||
if(!res)
|
||||
if(!res)
|
||||
return 0;
|
||||
if(res->ssl) {
|
||||
ERR_clear_error();
|
||||
@@ -662,7 +620,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 +642,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 +668,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 +725,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 +750,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 +850,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 +872,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 +889,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 +915,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 +932,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 +949,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 +1000,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 +1035,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 +1070,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 +1098,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 +1107,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 +1187,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 +1197,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");
|
||||
@@ -1268,7 +1246,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);
|
||||
@@ -1609,8 +1587,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 +1701,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 +1765,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 +1834,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 +1909,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 +1944,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 +2316,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 +2330,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 +2349,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 +2371,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 +2424,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 +2614,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 +2752,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 +2981,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 +3004,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 +3012,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 +3188,7 @@ execute_cmd(struct daemon_remote* rc, RES* ssl, char* cmd,
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
void
|
||||
daemon_remote_exec(struct worker* worker)
|
||||
{
|
||||
/* read the cmd string */
|
||||
@@ -3304,14 +3290,14 @@ remote_handshake_later(struct daemon_remote* rc, struct rc_state* s,
|
||||
if(r == 0)
|
||||
log_err("remote control connection closed prematurely");
|
||||
log_addr(VERB_OPS, "failed connection from",
|
||||
&s->c->repinfo.addr, s->c->repinfo.addrlen);
|
||||
&s->c->repinfo.remote_addr, s->c->repinfo.remote_addrlen);
|
||||
log_crypto_err("remote control failed ssl");
|
||||
clean_point(rc, s);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int remote_control_callback(struct comm_point* c, void* arg, int err,
|
||||
int remote_control_callback(struct comm_point* c, void* arg, int err,
|
||||
struct comm_reply* ATTR_UNUSED(rep))
|
||||
{
|
||||
RES res;
|
||||
@@ -3319,7 +3305,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;
|
||||
|
||||
+67
-13
@@ -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
|
||||
@@ -70,6 +70,9 @@
|
||||
#include <openssl/ssl.h>
|
||||
#endif
|
||||
|
||||
/** How long to wait for threads to transmit statistics, in msec. */
|
||||
#define STATS_THREAD_WAIT 60000
|
||||
|
||||
/** add timers and the values do not overflow or become negative */
|
||||
static void
|
||||
stats_timeval_add(long long* d_sec, long long* d_usec, long long add_sec, long long add_usec)
|
||||
@@ -113,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,
|
||||
@@ -276,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;
|
||||
@@ -290,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);
|
||||
@@ -351,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;
|
||||
@@ -380,6 +390,28 @@ void server_stats_obtain(struct worker* worker, struct worker* who,
|
||||
worker_send_cmd(who, worker_cmd_stats);
|
||||
else worker_send_cmd(who, worker_cmd_stats_noreset);
|
||||
verbose(VERB_ALGO, "wait for stats reply");
|
||||
if(tube_wait_timeout(worker->cmd, STATS_THREAD_WAIT) == 0) {
|
||||
verbose(VERB_OPS, "no response from thread %d"
|
||||
#ifdef HAVE_GETTID
|
||||
" LWP %u"
|
||||
#endif
|
||||
#if defined(HAVE_PTHREAD) && defined(SIZEOF_PTHREAD_T) && defined(SIZEOF_UNSIGNED_LONG)
|
||||
# if SIZEOF_PTHREAD_T == SIZEOF_UNSIGNED_LONG
|
||||
" pthread 0x%lx"
|
||||
# endif
|
||||
#endif
|
||||
,
|
||||
who->thread_num
|
||||
#ifdef HAVE_GETTID
|
||||
, (unsigned)who->thread_tid
|
||||
#endif
|
||||
#if defined(HAVE_PTHREAD) && defined(SIZEOF_PTHREAD_T) && defined(SIZEOF_UNSIGNED_LONG)
|
||||
# if SIZEOF_PTHREAD_T == SIZEOF_UNSIGNED_LONG
|
||||
, (unsigned long)*((unsigned long*)&who->thr_id)
|
||||
# endif
|
||||
#endif
|
||||
);
|
||||
}
|
||||
if(!tube_read_msg(worker->cmd, &reply, &len, 0))
|
||||
fatal_exit("failed to read stats over cmd channel");
|
||||
if(len != (uint32_t)sizeof(*s))
|
||||
@@ -394,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");
|
||||
}
|
||||
@@ -403,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
|
||||
@@ -446,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++)
|
||||
@@ -489,14 +530,14 @@ 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)
|
||||
stats->qhttps++;
|
||||
}
|
||||
}
|
||||
if(repinfo && addr_is_ip6(&repinfo->addr, repinfo->addrlen))
|
||||
if(repinfo && addr_is_ip6(&repinfo->remote_addr, repinfo->remote_addrlen))
|
||||
stats->qipv6++;
|
||||
if( (flags&BIT_QR) )
|
||||
stats->qbit_QR++;
|
||||
@@ -530,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 */
|
||||
|
||||
+400
-208
File diff suppressed because it is too large
Load Diff
+7
-1
@@ -86,6 +86,10 @@ struct worker {
|
||||
struct daemon* daemon;
|
||||
/** thread id */
|
||||
ub_thread_type thr_id;
|
||||
#ifdef HAVE_GETTID
|
||||
/** thread tid, the LWP id. */
|
||||
pid_t thread_tid;
|
||||
#endif
|
||||
/** pipe, for commands for this worker */
|
||||
struct tube* cmd;
|
||||
/** the event base this worker works with */
|
||||
@@ -114,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 */
|
||||
@@ -127,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;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
+2
-2
@@ -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";
|
||||
@@ -841,7 +841,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;
|
||||
|
||||
|
||||
+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.
|
||||
|
||||
+2
-2
@@ -954,7 +954,7 @@ static int dtio_write_more(struct dt_io_thread* dtio)
|
||||
* -1: continue, >0: number of bytes read into buffer */
|
||||
static ssize_t receive_bytes(struct dt_io_thread* dtio, void* buf, size_t len) {
|
||||
ssize_t r;
|
||||
r = recv(dtio->fd, (void*)buf, len, 0);
|
||||
r = recv(dtio->fd, (void*)buf, len, MSG_DONTWAIT);
|
||||
if(r == -1) {
|
||||
char* to = dtio->socket_path;
|
||||
if(!to) to = dtio->ip_str;
|
||||
@@ -1960,7 +1960,7 @@ static int dtio_open_output_tcp(struct dt_io_thread* dtio)
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
addrlen = (socklen_t)sizeof(addr);
|
||||
|
||||
if(!extstrtoaddr(dtio->ip_str, &addr, &addrlen)) {
|
||||
if(!extstrtoaddr(dtio->ip_str, &addr, &addrlen, UNBOUND_DNS_PORT)) {
|
||||
log_err("could not parse IP '%s'", dtio->ip_str);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
@@ -272,7 +273,7 @@ static int make_tcp_accept(char* ip)
|
||||
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
len = (socklen_t)sizeof(addr);
|
||||
if(!extstrtoaddr(ip, &addr, &len)) {
|
||||
if(!extstrtoaddr(ip, &addr, &len, UNBOUND_DNS_PORT)) {
|
||||
log_err("could not parse IP '%s'", ip);
|
||||
return -1;
|
||||
}
|
||||
@@ -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;
|
||||
@@ -617,7 +619,7 @@ static void log_data_frame(uint8_t* pkt, size_t len)
|
||||
static ssize_t receive_bytes(struct tap_data* data, int fd, void* buf,
|
||||
size_t len)
|
||||
{
|
||||
ssize_t ret = recv(fd, buf, len, 0);
|
||||
ssize_t ret = recv(fd, buf, len, MSG_DONTWAIT);
|
||||
if(ret == 0) {
|
||||
/* closed */
|
||||
if(verbosity) log_info("dnstap client stream closed from %s",
|
||||
@@ -789,7 +791,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 +801,34 @@ 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) {
|
||||
if(SSL_get_error(data->ssl, r) == SSL_ERROR_ZERO_RETURN)
|
||||
log_err("SSL_write, peer closed connection");
|
||||
else
|
||||
log_err("could not SSL_write");
|
||||
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 +948,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 +1031,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;
|
||||
}
|
||||
|
||||
+519
@@ -1,6 +1,525 @@
|
||||
25 August 2023: Wouter
|
||||
- Fix compile error on NetBSD in util/netevent.h.
|
||||
|
||||
23 August 2023: Wouter
|
||||
- Tag for 1.18.0rc1 release.
|
||||
|
||||
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.
|
||||
|
||||
21 October 2022: Wouter
|
||||
- Fix that cachedb does not store failures in the external cache.
|
||||
|
||||
18 October 2022: George
|
||||
- Clarify the use of MAX_SENT_COUNT in the iterator code.
|
||||
|
||||
17 October 2022: Wouter
|
||||
- testcode/dohclient sets log identity to its name.
|
||||
|
||||
14 October 2022: Wouter
|
||||
- Merge #768 from fobser: Arithmetic on a pointer to void is a GNU
|
||||
extension.
|
||||
- In unit test, print python script name list correctly.
|
||||
|
||||
13 October 2022: Wouter
|
||||
- Tag for 1.17.0 release. The code repository continues with 1.17.1.
|
||||
|
||||
11 October 2022: George
|
||||
- Fix PROXYv2 header read for TCP connections when no proxied addresses
|
||||
are provided.
|
||||
|
||||
7 October 2022: Wouter
|
||||
- Tag for 1.17.0rc1 release.
|
||||
|
||||
7 October 2022: George
|
||||
- Fix to stop possible loops in the tcp reuse code (write_wait list
|
||||
and tcp_wait list). Based on analysis and patch from Prad Seniappan
|
||||
and Karthik Umashankar.
|
||||
- Fix unit test to properly test the reuse_write_wait_pop function.
|
||||
|
||||
6 October 2022: Wouter
|
||||
- Fix to stop responses with TC flag from resulting in partial
|
||||
responses. It retries to fetch the data elsewhere, or fails the
|
||||
query and in depth fix removes the TC flag from the cached item.
|
||||
- Fix proxy length debug output printout typecasts.
|
||||
|
||||
5 October 2022: Wouter
|
||||
- Fix dnscrypt compile for proxy protocol code changes.
|
||||
|
||||
5 October 2022: George
|
||||
- Use DEBUG_TDIR from environment in mini_tdir.sh for debugging.
|
||||
- Fix string comparison in mini_tdir.sh.
|
||||
- Make ede.tdir test more predictable by using static data.
|
||||
- Fix checkconf test for dnscrypt and proxy port.
|
||||
|
||||
4 October 2022: George
|
||||
- Merge #764: Leniency for target discovery when under load (for
|
||||
NRDelegation changes).
|
||||
|
||||
4 October 2022: Wouter
|
||||
- Fix static analysis report to remove dead code from the
|
||||
rpz_callback_from_iterator_module function.
|
||||
- Fix to clean up after the acl_interface unit test.
|
||||
|
||||
3 October 2022: George
|
||||
- Merge #760: PROXYv2 downstream support. (New proxy-protocol-port
|
||||
configuration option).
|
||||
|
||||
3 October 2022: Wouter
|
||||
- Fix to remove erroneous TC flag from TCP upstream.
|
||||
- Fix test tdir skip report printout.
|
||||
- Fix windows compile, the identifier interface is defined in headers.
|
||||
- Fix to close errno block in comm_point_tcp_handle_read outside of
|
||||
ifdef.
|
||||
|
||||
26 September 2022: George
|
||||
- Better output for skipped tdir tests.
|
||||
|
||||
21 September 2022: Wouter
|
||||
- Patch for CVE-2022-3204 Non-Responsive Delegation Attack.
|
||||
- This patch was released in 1.16.3, the code repository continues
|
||||
with the previous features and fixes for 1.17.0.
|
||||
- Fix doxygen warning in respip.h.
|
||||
|
||||
20 September 2022: George
|
||||
- Convert tdir tests to use the new skip_test functionality.
|
||||
- Remove unused testcode/mini_tpkg.sh file.
|
||||
|
||||
16 September 2022: George
|
||||
- Merge #753: ACL per interface. (New interface-* configuration
|
||||
options).
|
||||
|
||||
2 September 2022: Wouter
|
||||
- Remove include that was there for debug purposes.
|
||||
- Fix to check pthread_t size after pthread has been detected.
|
||||
|
||||
1 September 2022: Wouter
|
||||
- Fix to update config tests to fix checking if nonblocking sockets
|
||||
work on OpenBSD.
|
||||
- Slow down log frequency of write wait failures.
|
||||
- Fix to set out of file descriptor warning to operational verbosity.
|
||||
- Fix to log a verbose message at operational notice level if a
|
||||
thread is not responding, to stats requests. It is logged with
|
||||
thread identifiers.
|
||||
|
||||
31 August 2022: Wouter
|
||||
- Fix to avoid process wide fcntl calls mixed with nonblocking
|
||||
operations after a blocked write.
|
||||
- Patch from Vadim Fedorenko that adds MSG_DONTWAIT to receive
|
||||
operations, so that instruction reordering does not cause mistakenly
|
||||
blocking socket operations.
|
||||
- Fix to wait for blocked write on UDP sockets, with a timeout if it
|
||||
takes too long the packet is dropped.
|
||||
- Fix for wait for udp send to stop when packet is successfully sent.
|
||||
|
||||
22 August 2022: Wouter
|
||||
- Fix #741: systemd socket activation fails on IPv6.
|
||||
|
||||
12 August 2022: Wouter
|
||||
- Fix to log accept error ENFILE and EMFILE errno, but slowly, once
|
||||
per 10 seconds. Also log accept failures when no slow down is used.
|
||||
|
||||
5 August 2022: Wouter
|
||||
- Fix #734 [FR] enable unbound-checkconf to detect more (basic)
|
||||
errors.
|
||||
|
||||
4 August 2022: Wouter
|
||||
- Fix ratelimit inconsistency, for ip-ratelimits the value is the
|
||||
amount allowed, like for ratelimits.
|
||||
|
||||
2 August 2022: Wouter
|
||||
- Fix edns subnet so that scope 0 answers only match sourcemask 0
|
||||
queries for answers from cache if from a query with sourcemask 0.
|
||||
- Fix unittest for edns subnet change.
|
||||
- Merge #730 from luisdallos: Fix startup failure on Windows 8.1 due
|
||||
to unsupported IPV6_USER_MTU socket option being set.
|
||||
|
||||
1 August 2022: Wouter
|
||||
- Fix the novel ghost domain issues CVE-2022-30698 and CVE-2022-30699.
|
||||
- Tests for ghost domain fixes.
|
||||
- Tag for 1.16.2 release. The code repo continues with 1.16.3.
|
||||
- Fix #728: alloc_reg_obtain() core dump. Stop double
|
||||
alloc_reg_release when serviced_create fails.
|
||||
|
||||
19 July 2022: George
|
||||
- Update documentation for 'outbound-msg-retry:'.
|
||||
|
||||
@@ -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.
|
||||
|
||||
+104
-8
@@ -17,7 +17,7 @@ server:
|
||||
# whitespace is not necessary, but looks cleaner.
|
||||
|
||||
# verbosity number, 0 is least verbose. 1 is default.
|
||||
verbosity: 1
|
||||
# verbosity: 1
|
||||
|
||||
# print statistics to the log (for every thread) every N seconds.
|
||||
# Set to "" or 0 to disable. Default is disabled.
|
||||
@@ -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
|
||||
|
||||
@@ -50,6 +55,7 @@ server:
|
||||
# interface: 192.0.2.154
|
||||
# interface: 192.0.2.154@5003
|
||||
# interface: 2001:DB8::5
|
||||
# interface: eth0@5003
|
||||
|
||||
# enable this feature to copy the source address of queries to reply.
|
||||
# Socket options are not supported on all platforms. experimental.
|
||||
@@ -137,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
|
||||
@@ -172,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
|
||||
@@ -217,7 +232,8 @@ server:
|
||||
# the maximum number of hosts that are cached (roundtrip, EDNS, lame).
|
||||
# infra-cache-numhosts: 10000
|
||||
|
||||
# define a number of tags here, use with local-zone, access-control.
|
||||
# define a number of tags here, use with local-zone, access-control,
|
||||
# interface-*.
|
||||
# repeat the define-tag statement to add additional tags.
|
||||
# define-tag: "tag1 tag2 tag3"
|
||||
|
||||
@@ -227,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
|
||||
|
||||
@@ -258,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
|
||||
|
||||
@@ -273,9 +305,7 @@ server:
|
||||
# allow_snoop (recursive and nonrecursive ok)
|
||||
# deny_non_local (drop queries unless can be answered from local-data)
|
||||
# refuse_non_local (like deny_non_local but polite error reply).
|
||||
# access-control: 0.0.0.0/0 refuse
|
||||
# access-control: 127.0.0.0/8 allow
|
||||
# access-control: ::0/0 refuse
|
||||
# access-control: ::1 allow
|
||||
# access-control: ::ffff:127.0.0.1 allow
|
||||
|
||||
@@ -284,7 +314,7 @@ server:
|
||||
# are tagged with one of these tags.
|
||||
# access-control-tag: 192.0.2.0/24 "tag2 tag3"
|
||||
|
||||
# set action for particular tag for given access control element
|
||||
# set action for particular tag for given access control element.
|
||||
# if you have multiple tag values, the tag used to lookup the action
|
||||
# is the first tag match between access-control-tag and local-zone-tag
|
||||
# where "first" comes from the order of the define-tag values.
|
||||
@@ -296,6 +326,58 @@ server:
|
||||
# Set view for access control element
|
||||
# access-control-view: 192.0.2.0/24 viewname
|
||||
|
||||
# Similar to 'access-control:' but for interfaces.
|
||||
# Control which listening interfaces are allowed to accept (recursive)
|
||||
# queries for this server.
|
||||
# The specified interfaces should be the same as the ones specified in
|
||||
# 'interface:' followed by the action.
|
||||
# The actions are the same as 'access-control:' above.
|
||||
# By default all the interfaces configured are refused.
|
||||
# Note: any 'access-control*:' setting overrides all 'interface-*:'
|
||||
# settings for targeted clients.
|
||||
# interface-action: 192.0.2.153 allow
|
||||
# interface-action: 192.0.2.154 allow
|
||||
# interface-action: 192.0.2.154@5003 allow
|
||||
# interface-action: 2001:DB8::5 allow
|
||||
# interface-action: eth0@5003 allow
|
||||
|
||||
# Similar to 'access-control-tag:' but for interfaces.
|
||||
# Tag interfaces with a list of tags (in "" with spaces between).
|
||||
# Interfaces using these tags use localzones that are tagged with one
|
||||
# of these tags.
|
||||
# The specified interfaces should be the same as the ones specified in
|
||||
# 'interface:' followed by the list of tags.
|
||||
# Note: any 'access-control*:' setting overrides all 'interface-*:'
|
||||
# settings for targeted clients.
|
||||
# interface-tag: eth0@5003 "tag2 tag3"
|
||||
|
||||
# Similar to 'access-control-tag-action:' but for interfaces.
|
||||
# Set action for particular tag for a given interface element.
|
||||
# If you have multiple tag values, the tag used to lookup the action
|
||||
# is the first tag match between interface-tag and local-zone-tag
|
||||
# where "first" comes from the order of the define-tag values.
|
||||
# The specified interfaces should be the same as the ones specified in
|
||||
# 'interface:' followed by the tag and action.
|
||||
# Note: any 'access-control*:' setting overrides all 'interface-*:'
|
||||
# settings for targeted clients.
|
||||
# interface-tag-action: eth0@5003 tag3 refuse
|
||||
|
||||
# Similar to 'access-control-tag-data:' but for interfaces.
|
||||
# Set redirect data for a particular tag for an interface element.
|
||||
# The specified interfaces should be the same as the ones specified in
|
||||
# 'interface:' followed by the tag and the redirect data.
|
||||
# Note: any 'access-control*:' setting overrides all 'interface-*:'
|
||||
# settings for targeted clients.
|
||||
# interface-tag-data: eth0@5003 tag2 "A 127.0.0.1"
|
||||
|
||||
# Similar to 'access-control-view:' but for interfaces.
|
||||
# Set view for an interface element.
|
||||
# The specified interfaces should be the same as the ones specified in
|
||||
# 'interface:' followed by the view name.
|
||||
# Note: any 'access-control*:' setting overrides all 'interface-*:'
|
||||
# settings for targeted clients.
|
||||
# interface-view: eth0@5003 viewname
|
||||
|
||||
# if given, a chroot(2) is done to the given directory.
|
||||
# i.e. you can chroot to the working directory, for example,
|
||||
# for extra security, but make sure all files are in that directory.
|
||||
@@ -437,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.
|
||||
@@ -744,6 +830,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.
|
||||
#
|
||||
@@ -850,6 +938,10 @@ server:
|
||||
# Disable TLS for DNS-over-HTTP downstream service.
|
||||
# http-notls-downstream: no
|
||||
|
||||
# The interfaces that use these listed port numbers will support and
|
||||
# expect PROXYv2. For UDP and TCP/TLS interfaces.
|
||||
# proxy-protocol-port: portno for each of the port numbers.
|
||||
|
||||
# DNS64 prefix. Must be specified when DNS64 is use.
|
||||
# Enable dns64 in module-config. Used to synthesize IPv6 from IPv4.
|
||||
# dns64-prefix: 64:ff9b::0/96
|
||||
@@ -1136,6 +1228,10 @@ 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
|
||||
|
||||
@@ -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.
|
||||
|
||||
+213
-27
@@ -112,13 +112,21 @@ 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
|
||||
.B port: \fI<port number>
|
||||
The port number, default 53, on which the server responds to queries.
|
||||
.TP
|
||||
.B interface: \fI<ip address[@port]>
|
||||
.B interface: \fI<ip address or interface name [@port]>
|
||||
Interface to use to connect to the network. This interface is listened to
|
||||
for queries from clients, and answers to clients are given from it.
|
||||
Can be given multiple times to work on several interfaces. If none are
|
||||
@@ -129,7 +137,7 @@ A port number can be specified with @port (without spaces between
|
||||
interface and port number), if not specified the default port (from
|
||||
\fBport\fR) is used.
|
||||
.TP
|
||||
.B ip\-address: \fI<ip address[@port]>
|
||||
.B ip\-address: \fI<ip address or interface name [@port]>
|
||||
Same as interface: (for ease of compatibility with nsd.conf).
|
||||
.TP
|
||||
.B interface\-automatic: \fI<yes or no>
|
||||
@@ -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
|
||||
@@ -349,7 +358,7 @@ ip\-transparent option is also available.
|
||||
The value of the Differentiated Services Codepoint (DSCP) in the
|
||||
differentiated services field (DS) of the outgoing IP packet headers.
|
||||
The field replaces the outdated IPv4 Type-Of-Service field and the
|
||||
IPV6 traffic class field.
|
||||
IPv6 traffic class field.
|
||||
.TP
|
||||
.B rrset\-cache\-size: \fI<number>
|
||||
Number of bytes size of the RRset cache. Default is 4 megabytes.
|
||||
@@ -416,7 +425,7 @@ Enable or disable whether ip4 queries are answered or issued. Default is yes.
|
||||
Enable or disable whether ip6 queries are answered or issued. Default is yes.
|
||||
If disabled, queries are not answered on IPv6, and queries are not sent on
|
||||
IPv6 to the internet nameservers. With this option you can disable the
|
||||
ipv6 transport for sending DNS traffic, it does not impact the contents of
|
||||
IPv6 transport for sending DNS traffic, it does not impact the contents of
|
||||
the DNS traffic, which may have ip4 and ip6 addresses in it.
|
||||
.TP
|
||||
.B prefer\-ip4: \fI<yes or no>
|
||||
@@ -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
|
||||
@@ -656,6 +673,17 @@ Ignored if the option is not available. Default is yes.
|
||||
Disable use of TLS for the downstream DNS-over-HTTP connections. Useful for
|
||||
local back end servers. Default is no.
|
||||
.TP
|
||||
.B proxy\-protocol\-port: \fI<portnr>
|
||||
List port numbers as proxy\-protocol\-port, and when interfaces are defined,
|
||||
eg. with the @port suffix, as this port number, they support and expect PROXYv2.
|
||||
In this case the proxy address will only be used for the network communication
|
||||
and initial ACL (check if the proxy itself is denied/refused by configuration).
|
||||
The proxied address (if any) will then be used as the true client address and
|
||||
will be used where applicable for logging, ACL, DNSTAP, RPZ and IP ratelimiting.
|
||||
PROXYv2 is supported for UDP and TCP/TLS listening interfaces.
|
||||
There is no support for PROXYv2 on a DoH or DNSCrypt listening interface.
|
||||
Can list multiple, each on a new statement.
|
||||
.TP
|
||||
.B use\-systemd: \fI<yes or no>
|
||||
Enable or disable systemd socket activation.
|
||||
Default is no.
|
||||
@@ -673,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.
|
||||
The most specific netblock match is used, if none match \fIdeny\fR is used.
|
||||
\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
|
||||
@@ -703,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
|
||||
@@ -741,6 +783,46 @@ Set redirect data for particular tag for given access control element.
|
||||
.B access\-control\-view: \fI<IP netblock> <view name>
|
||||
Set view for given access control element.
|
||||
.TP
|
||||
.B interface\-action: \fI<ip address or interface name [@port]> <action>
|
||||
Similar to \fBaccess\-control:\fR but for interfaces.
|
||||
.IP
|
||||
The action is the same as the ones defined under \fBaccess\-control:\fR.
|
||||
Interfaces are \fIrefuse\fRd by default.
|
||||
By default only localhost (the IP netblock, not the loopback interface) is
|
||||
\fIallow\fRed through the default \fBaccess\-control:\fR behavior.
|
||||
.IP
|
||||
Note that the interface needs to be already specified with \fBinterface:\fR
|
||||
and that any \fBaccess-control*:\fR setting overrides all \fBinterface-*:\fR
|
||||
settings for targeted clients.
|
||||
.TP
|
||||
.B interface\-tag: \fI<ip address or interface name [@port]> <"list of tags">
|
||||
Similar to \fBaccess\-control-tag:\fR but for interfaces.
|
||||
.IP
|
||||
Note that the interface needs to be already specified with \fBinterface:\fR
|
||||
and that any \fBaccess-control*:\fR setting overrides all \fBinterface-*:\fR
|
||||
settings for targeted clients.
|
||||
.TP
|
||||
.B interface\-tag\-action: \fI<ip address or interface name [@port]> <tag> <action>
|
||||
Similar to \fBaccess\-control-tag-action:\fR but for interfaces.
|
||||
.IP
|
||||
Note that the interface needs to be already specified with \fBinterface:\fR
|
||||
and that any \fBaccess-control*:\fR setting overrides all \fBinterface-*:\fR
|
||||
settings for targeted clients.
|
||||
.TP
|
||||
.B interface\-tag\-data: \fI<ip address or interface name [@port]> <tag> <"resource record string">
|
||||
Similar to \fBaccess\-control-tag-data:\fR but for interfaces.
|
||||
.IP
|
||||
Note that the interface needs to be already specified with \fBinterface:\fR
|
||||
and that any \fBaccess-control*:\fR setting overrides all \fBinterface-*:\fR
|
||||
settings for targeted clients.
|
||||
.TP
|
||||
.B interface\-view: \fI<ip address or interface name [@port]> <view name>
|
||||
Similar to \fBaccess\-control-view:\fR but for interfaces.
|
||||
.IP
|
||||
Note that the interface needs to be already specified with \fBinterface:\fR
|
||||
and that any \fBaccess-control*:\fR setting overrides all \fBinterface-*:\fR
|
||||
settings for targeted clients.
|
||||
.TP
|
||||
.B chroot: \fI<directory>
|
||||
If chroot is enabled, you should pass the configfile (from the
|
||||
commandline) as a full path from the original root. After the
|
||||
@@ -960,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
|
||||
@@ -1332,10 +1420,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
|
||||
@@ -1410,6 +1498,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
|
||||
@@ -1620,7 +1714,7 @@ This specifies the action data for \fIresponse-ip\fR with action being
|
||||
to redirect as specified by "\fIresource record string\fR". "Resource
|
||||
record string" is similar to that of \fIaccess-control-tag-action\fR,
|
||||
but it must be of either AAAA, A or CNAME types.
|
||||
If the IP-netblock is an IPv6/IPV4 prefix, the record
|
||||
If the IP-netblock is an IPv6/IPv4 prefix, the record
|
||||
must be AAAA/A respectively, unless it is a CNAME (which can be used
|
||||
for both versions of IP netblocks). If it is CNAME there must not be
|
||||
more than one \fIresponse-ip-data\fR for the same IP-netblock.
|
||||
@@ -1726,11 +1820,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
|
||||
@@ -1769,6 +1879,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
|
||||
@@ -1784,6 +1909,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
|
||||
@@ -1802,7 +1939,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
|
||||
@@ -1823,9 +1960,11 @@ section for options. To setup the correct self\-signed certificates use the
|
||||
The option is used to enable remote control, default is "no".
|
||||
If turned off, the server does not listen for control commands.
|
||||
.TP 5
|
||||
.B control\-interface: \fI<ip address or path>
|
||||
.B control\-interface: \fI<ip address or interface name or path>
|
||||
Give IPv4 or IPv6 addresses or local socket path to listen on for
|
||||
control commands.
|
||||
If an interface name is used instead of an ip address, the list of ip addresses
|
||||
on that interface are used.
|
||||
By default localhost (127.0.0.1 and ::1) is listened to.
|
||||
Use 0.0.0.0 and ::0 to listen to all interfaces.
|
||||
If you change this and permissions have been dropped, you must restart
|
||||
@@ -2015,13 +2154,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
|
||||
@@ -2215,6 +2373,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
|
||||
@@ -2305,6 +2478,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
|
||||
@@ -2507,6 +2683,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
|
||||
|
||||
@@ -97,6 +97,7 @@ node_create(struct addrtree *tree, void *elem, addrlen_t scope,
|
||||
tree->node_count++;
|
||||
node->scope = scope;
|
||||
node->ttl = ttl;
|
||||
node->only_match_scope_zero = 0;
|
||||
node->edge[0] = NULL;
|
||||
node->edge[1] = NULL;
|
||||
node->parent_edge = NULL;
|
||||
@@ -155,6 +156,7 @@ clean_node(struct addrtree *tree, struct addrnode *node)
|
||||
if (!node->elem) return;
|
||||
tree->size_bytes -= tree->sizefunc(node->elem);
|
||||
tree->delfunc(tree->env, node->elem);
|
||||
node->only_match_scope_zero = 0;
|
||||
node->elem = NULL;
|
||||
}
|
||||
|
||||
@@ -358,7 +360,7 @@ issub(const addrkey_t *s1, addrlen_t l1,
|
||||
void
|
||||
addrtree_insert(struct addrtree *tree, const addrkey_t *addr,
|
||||
addrlen_t sourcemask, addrlen_t scope, void *elem, time_t ttl,
|
||||
time_t now)
|
||||
time_t now, int only_match_scope_zero)
|
||||
{
|
||||
struct addrnode *newnode, *node;
|
||||
struct addredge *edge;
|
||||
@@ -381,6 +383,7 @@ addrtree_insert(struct addrtree *tree, const addrkey_t *addr,
|
||||
/* update this node's scope and data */
|
||||
clean_node(tree, node);
|
||||
node->ttl = ttl;
|
||||
node->only_match_scope_zero = only_match_scope_zero;
|
||||
node->elem = elem;
|
||||
node->scope = scope;
|
||||
tree->size_bytes += tree->sizefunc(elem);
|
||||
@@ -447,6 +450,7 @@ addrtree_insert(struct addrtree *tree, const addrkey_t *addr,
|
||||
newnode->elem = elem;
|
||||
newnode->scope = scope;
|
||||
newnode->ttl = ttl;
|
||||
newnode->only_match_scope_zero = only_match_scope_zero;
|
||||
}
|
||||
|
||||
tree->size_bytes += node_size(tree, newnode);
|
||||
@@ -483,7 +487,8 @@ addrtree_find(struct addrtree *tree, const addrkey_t *addr,
|
||||
/* Current node more specific then question. */
|
||||
log_assert(depth <= sourcemask);
|
||||
/* does this node have data? if yes, see if we have a match */
|
||||
if (node->elem && node->ttl >= now) {
|
||||
if (node->elem && node->ttl >= now &&
|
||||
!(sourcemask != 0 && node->only_match_scope_zero)) {
|
||||
/* saved at wrong depth */;
|
||||
log_assert(node->scope >= depth);
|
||||
if (depth == node->scope ||
|
||||
|
||||
@@ -95,6 +95,10 @@ struct addrnode {
|
||||
time_t ttl;
|
||||
/** Number of significant bits in address. */
|
||||
addrlen_t scope;
|
||||
/** Only use the element for queries for subnet/0. Set if the query
|
||||
* for /0 was answered with scope 0. For query /x answer scope 0,
|
||||
* they can match anything and this is false. */
|
||||
int only_match_scope_zero;
|
||||
/** A node can have 0-2 edges, set to NULL for unused */
|
||||
struct addredge *edge[2];
|
||||
/** edge between this node and parent */
|
||||
@@ -157,11 +161,12 @@ void addrtree_delete(struct addrtree *tree);
|
||||
* @param scope: Number of significant bits in addr.
|
||||
* @param elem: data to store in the tree.
|
||||
* @param ttl: elem is valid up to this time, seconds.
|
||||
* @param only_match_scope_zero: set for when query /0 has scope /0 answer.
|
||||
* @param now: Current time in seconds.
|
||||
*/
|
||||
void addrtree_insert(struct addrtree *tree, const addrkey_t *addr,
|
||||
addrlen_t sourcemask, addrlen_t scope, void *elem, time_t ttl,
|
||||
time_t now);
|
||||
time_t now, int only_match_scope_zero);
|
||||
|
||||
/**
|
||||
* Find a node containing an element in the tree.
|
||||
|
||||
+71
-10
@@ -55,6 +55,7 @@
|
||||
#include "util/config_file.h"
|
||||
#include "util/data/msgreply.h"
|
||||
#include "sldns/sbuffer.h"
|
||||
#include "sldns/wire2str.h"
|
||||
#include "iterator/iter_utils.h"
|
||||
|
||||
/** externally called */
|
||||
@@ -203,6 +204,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,
|
||||
@@ -331,6 +343,7 @@ update_cache(struct module_qstate *qstate, int id)
|
||||
struct slabhash *subnet_msg_cache = sne->subnet_msg_cache;
|
||||
struct ecs_data *edns = &sq->ecs_client_in;
|
||||
size_t i;
|
||||
int only_match_scope_zero;
|
||||
|
||||
/* We already calculated hash upon lookup (lookup_and_reply) if we were
|
||||
* allowed to look in the ECS cache */
|
||||
@@ -339,7 +352,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) {
|
||||
@@ -383,7 +396,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];
|
||||
@@ -392,9 +405,12 @@ update_cache(struct module_qstate *qstate, int id)
|
||||
reply_info_set_ttls(rep, *qstate->env->now);
|
||||
rep->flags |= (BIT_RA | BIT_QR); /* fix flags to be sensible for */
|
||||
rep->flags &= ~(BIT_AA | BIT_CD);/* a reply based on the cache */
|
||||
if(edns->subnet_source_mask == 0 && edns->subnet_scope_mask == 0)
|
||||
only_match_scope_zero = 1;
|
||||
else only_match_scope_zero = 0;
|
||||
addrtree_insert(tree, (addrkey_t*)edns->subnet_addr,
|
||||
edns->subnet_source_mask, sq->max_scope, rep,
|
||||
rep->ttl, *qstate->env->now);
|
||||
rep->ttl, *qstate->env->now, only_match_scope_zero);
|
||||
|
||||
lock_rw_unlock(&lru_entry->lock);
|
||||
if (need_to_insert) {
|
||||
@@ -405,7 +421,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;
|
||||
@@ -457,6 +473,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;
|
||||
}
|
||||
|
||||
@@ -493,7 +513,7 @@ 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 (s_in->subnet_validdata)
|
||||
@@ -502,7 +522,7 @@ eval_response(struct module_qstate *qstate, int id, struct subnet_qstate *sq)
|
||||
cp_edns_bad_response(c_out, c_in);
|
||||
return module_finished;
|
||||
}
|
||||
|
||||
|
||||
/* subnet sent but nothing came back */
|
||||
if (!s_in->subnet_validdata) {
|
||||
/* The authority indicated no support for edns subnet. As a
|
||||
@@ -519,11 +539,11 @@ eval_response(struct module_qstate *qstate, int id, struct subnet_qstate *sq)
|
||||
cp_edns_bad_response(c_out, c_in);
|
||||
return module_finished;
|
||||
}
|
||||
|
||||
|
||||
/* Being here means we have asked for and got a subnet specific
|
||||
* answer. Also, the answer from the authority is not yet cached
|
||||
* anywhere. */
|
||||
|
||||
|
||||
/* can we accept response? */
|
||||
if(s_out->subnet_addr_fam != s_in->subnet_addr_fam ||
|
||||
s_out->subnet_source_mask != s_in->subnet_source_mask ||
|
||||
@@ -674,6 +694,24 @@ ecs_query_response(struct module_qstate* qstate, struct dns_msg* response,
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** verbose print edns subnet option in pretty print */
|
||||
static void
|
||||
subnet_log_print(const char* s, struct edns_option* ecs_opt)
|
||||
{
|
||||
if(verbosity >= VERB_ALGO) {
|
||||
char buf[256];
|
||||
char* str = buf;
|
||||
size_t str_len = sizeof(buf);
|
||||
if(!ecs_opt) {
|
||||
verbose(VERB_ALGO, "%s (null)", s);
|
||||
return;
|
||||
}
|
||||
(void)sldns_wire2str_edns_subnet_print(&str, &str_len,
|
||||
ecs_opt->opt_data, ecs_opt->opt_len);
|
||||
verbose(VERB_ALGO, "%s %s", s, buf);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
ecs_edns_back_parsed(struct module_qstate* qstate, int id,
|
||||
void* ATTR_UNUSED(cbargs))
|
||||
@@ -688,6 +726,7 @@ ecs_edns_back_parsed(struct module_qstate* qstate, int id,
|
||||
qstate->env->cfg->client_subnet_opcode)) &&
|
||||
parse_subnet_option(ecs_opt, &sq->ecs_server_in) &&
|
||||
sq->subnet_sent && sq->ecs_server_in.subnet_validdata) {
|
||||
subnet_log_print("answer has edns subnet", ecs_opt);
|
||||
/* Only skip global cache store if we sent an ECS option
|
||||
* and received one back. Answers from non-whitelisted
|
||||
* servers will end up in global cache. Answers for
|
||||
@@ -736,11 +775,17 @@ subnetmod_operate(struct module_qstate *qstate, enum module_ev event,
|
||||
qstate->ext_state[id] = module_finished;
|
||||
return;
|
||||
}
|
||||
subnet_log_print("query has edns subnet", ecs_opt);
|
||||
sq->subnet_downstream = 1;
|
||||
}
|
||||
else if(qstate->mesh_info->reply_list) {
|
||||
subnet_option_from_ss(
|
||||
&qstate->mesh_info->reply_list->query_reply.addr,
|
||||
&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);
|
||||
}
|
||||
|
||||
@@ -766,7 +811,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");
|
||||
@@ -775,6 +822,13 @@ subnetmod_operate(struct module_qstate *qstate, enum module_ev event,
|
||||
subnet_ecs_opt_list_append(&sq->ecs_client_out,
|
||||
&qstate->edns_opts_front_out, qstate,
|
||||
qstate->region);
|
||||
if(verbosity >= VERB_ALGO) {
|
||||
subnet_log_print("reply has edns subnet",
|
||||
edns_opt_list_find(
|
||||
qstate->edns_opts_front_out,
|
||||
qstate->env->cfg->
|
||||
client_subnet_opcode));
|
||||
}
|
||||
return;
|
||||
}
|
||||
lock_rw_unlock(&sne->biglock);
|
||||
@@ -823,6 +877,13 @@ subnetmod_operate(struct module_qstate *qstate, enum module_ev event,
|
||||
subnet_ecs_opt_list_append(&sq->ecs_client_out,
|
||||
&qstate->edns_opts_front_out, qstate,
|
||||
qstate->region);
|
||||
if(verbosity >= VERB_ALGO) {
|
||||
subnet_log_print("reply has edns subnet",
|
||||
edns_opt_list_find(
|
||||
qstate->edns_opts_front_out,
|
||||
qstate->env->cfg->
|
||||
client_subnet_opcode));
|
||||
}
|
||||
}
|
||||
qstate->no_cache_store = sq->started_no_cache_store;
|
||||
qstate->no_cache_lookup = sq->started_no_cache_lookup;
|
||||
|
||||
@@ -78,6 +78,7 @@ struct delegpt* delegpt_copy(struct delegpt* dp, struct regional* region)
|
||||
if(!delegpt_add_ns(copy, region, ns->name, ns->lame,
|
||||
ns->tls_auth_name, ns->port))
|
||||
return NULL;
|
||||
copy->nslist->cache_lookup_count = ns->cache_lookup_count;
|
||||
copy->nslist->resolved = ns->resolved;
|
||||
copy->nslist->got4 = ns->got4;
|
||||
copy->nslist->got6 = ns->got6;
|
||||
@@ -121,6 +122,7 @@ delegpt_add_ns(struct delegpt* dp, struct regional* region, uint8_t* name,
|
||||
ns->namelen = len;
|
||||
dp->nslist = ns;
|
||||
ns->name = regional_alloc_init(region, name, ns->namelen);
|
||||
ns->cache_lookup_count = 0;
|
||||
ns->resolved = 0;
|
||||
ns->got4 = 0;
|
||||
ns->got6 = 0;
|
||||
@@ -319,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)
|
||||
{
|
||||
@@ -620,6 +661,7 @@ int delegpt_add_ns_mlc(struct delegpt* dp, uint8_t* name, uint8_t lame,
|
||||
}
|
||||
ns->next = dp->nslist;
|
||||
dp->nslist = ns;
|
||||
ns->cache_lookup_count = 0;
|
||||
ns->resolved = 0;
|
||||
ns->got4 = 0;
|
||||
ns->got6 = 0;
|
||||
|
||||
@@ -101,6 +101,8 @@ struct delegpt_ns {
|
||||
uint8_t* name;
|
||||
/** length of name */
|
||||
size_t namelen;
|
||||
/** number of cache lookups for the name */
|
||||
int cache_lookup_count;
|
||||
/**
|
||||
* If the name has been resolved. false if not queried for yet.
|
||||
* true if the A, AAAA queries have been generated.
|
||||
@@ -455,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 */
|
||||
|
||||
@@ -100,7 +100,7 @@ ah(struct delegpt* dp, const char* sv, const char* ip)
|
||||
return 0;
|
||||
}
|
||||
if(!delegpt_add_ns_mlc(dp, dname, 0, NULL, UNBOUND_DNS_PORT) ||
|
||||
!extstrtoaddr(ip, &addr, &addrlen) ||
|
||||
!extstrtoaddr(ip, &addr, &addrlen, UNBOUND_DNS_PORT) ||
|
||||
!delegpt_add_target_mlc(dp, dname, dname_len,
|
||||
&addr, addrlen, 0, 0)) {
|
||||
free(dname);
|
||||
|
||||
@@ -113,7 +113,11 @@ response_type_from_server(int rdset,
|
||||
|
||||
if(!msg || !request)
|
||||
return RESPONSE_TYPE_THROWAWAY;
|
||||
|
||||
/* If the TC flag is set, the response is incomplete. Too large to
|
||||
* fit even in TCP or so. Discard it, it cannot be retrieved here. */
|
||||
if((msg->rep->flags & BIT_TC))
|
||||
return RESPONSE_TYPE_THROWAWAY;
|
||||
|
||||
/* If the message is NXDOMAIN, then it answers the question. */
|
||||
if(FLAGS_GET_RCODE(msg->rep->flags) == LDNS_RCODE_NXDOMAIN) {
|
||||
/* make sure its not recursive when we don't want it to */
|
||||
@@ -280,6 +284,13 @@ response_type_from_server(int rdset,
|
||||
|
||||
/* If we've gotten this far, this is NOERROR/NODATA (which could
|
||||
* be an entirely empty message) */
|
||||
/* but ignore entirely empty messages, noerror/nodata has a soa
|
||||
* negative ttl value in the authority section, this makes it try
|
||||
* again at another authority. And turns it from a 5 second empty
|
||||
* message into a 5 second servfail response. */
|
||||
if(msg->rep->an_numrrsets == 0 && msg->rep->ns_numrrsets == 0 &&
|
||||
msg->rep->ar_numrrsets == 0)
|
||||
return RESPONSE_TYPE_THROWAWAY;
|
||||
/* 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;
|
||||
|
||||
+40
-3
@@ -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;
|
||||
}
|
||||
@@ -846,7 +883,7 @@ 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))
|
||||
|
||||
+44
-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.
|
||||
@@ -1209,6 +1247,9 @@ int iter_lookup_parent_glue_from_cache(struct module_env* env,
|
||||
struct delegpt_ns* ns;
|
||||
size_t num = delegpt_count_targets(dp);
|
||||
for(ns = dp->nslist; ns; ns = ns->next) {
|
||||
if(ns->cache_lookup_count > ITERATOR_NAME_CACHELOOKUP_MAX_PSIDE)
|
||||
continue;
|
||||
ns->cache_lookup_count++;
|
||||
/* get cached parentside A */
|
||||
akey = rrset_cache_lookup(env->rrset_cache, ns->name,
|
||||
ns->namelen, LDNS_RR_TYPE_A, qinfo->qclass,
|
||||
@@ -1305,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;
|
||||
|
||||
+14
-2
@@ -62,6 +62,15 @@ struct ub_packed_rrset_key;
|
||||
struct module_stack;
|
||||
struct outside_network;
|
||||
|
||||
/* max number of lookups in the cache for target nameserver names.
|
||||
* This stops, for large delegations, N*N lookups in the cache. */
|
||||
#define ITERATOR_NAME_CACHELOOKUP_MAX 3
|
||||
/* max number of lookups in the cache for parentside glue for nameserver names
|
||||
* This stops, for larger delegations, N*N lookups in the cache.
|
||||
* It is a little larger than the nonpside max, so it allows a couple extra
|
||||
* lookups of parent side glue. */
|
||||
#define ITERATOR_NAME_CACHELOOKUP_MAX_PSIDE 5
|
||||
|
||||
/**
|
||||
* Process config options and set iterator module state.
|
||||
* Sets default values if no config is found.
|
||||
@@ -180,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
|
||||
|
||||
+263
-124
@@ -255,9 +255,9 @@ 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);
|
||||
dpns->resolved = 1; /* mark as failed */
|
||||
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,21 +574,69 @@ 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)
|
||||
{
|
||||
if(qstate->env->cfg->val_log_level < 2 && !qstate->env->cfg->log_servfail)
|
||||
return;
|
||||
if((qstate->reply && qstate->reply->addrlen != 0) ||
|
||||
(iq->fail_reply && iq->fail_reply->addrlen != 0)) {
|
||||
if((qstate->reply && qstate->reply->remote_addrlen != 0) ||
|
||||
(iq->fail_addr_type != 0)) {
|
||||
char from[256], frm[512];
|
||||
if(qstate->reply && qstate->reply->addrlen != 0)
|
||||
addr_to_str(&qstate->reply->addr, qstate->reply->addrlen,
|
||||
from, sizeof(from));
|
||||
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->addr, iq->fail_reply->addrlen,
|
||||
from, sizeof(from));
|
||||
print_fail_addr(iq, from, sizeof(from));
|
||||
snprintf(frm, sizeof(frm), "from %s", from);
|
||||
errinf(qstate, frm);
|
||||
}
|
||||
@@ -1135,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.
|
||||
*/
|
||||
@@ -1218,6 +1250,15 @@ generate_dnskey_prefetch(struct module_qstate* qstate,
|
||||
(qstate->query_flags&BIT_RD) && !(qstate->query_flags&BIT_CD)){
|
||||
return;
|
||||
}
|
||||
/* we do not generate this prefetch when the query list is full,
|
||||
* the query is fetched, if needed, when the validator wants it.
|
||||
* At that time the validator waits for it, after spawning it.
|
||||
* This means there is one state that uses cpu and a socket, the
|
||||
* spawned while this one waits, and not several at the same time,
|
||||
* if we had created the lookup here. And this helps to keep
|
||||
* the total load down, but the query still succeeds to resolve. */
|
||||
if(mesh_jostle_exceeded(qstate->env->mesh))
|
||||
return;
|
||||
|
||||
/* if the DNSKEY is in the cache this lookup will stop quickly */
|
||||
log_nametypeclass(VERB_ALGO, "schedule dnskey prefetch",
|
||||
@@ -1303,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 "
|
||||
@@ -1440,6 +1481,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.
|
||||
@@ -1549,18 +1603,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) {
|
||||
@@ -1911,9 +1966,17 @@ query_for_targets(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
return 0;
|
||||
}
|
||||
query_count++;
|
||||
/* If the mesh query list is full, exit the loop here.
|
||||
* This makes the routine spawn one query at a time,
|
||||
* and this means there is no query state load
|
||||
* increase, because the spawned state uses cpu and a
|
||||
* socket while this state waits for that spawned
|
||||
* state. Next time we can look up further targets */
|
||||
if(mesh_jostle_exceeded(qstate->env->mesh))
|
||||
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,
|
||||
@@ -1925,6 +1988,9 @@ query_for_targets(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
return 0;
|
||||
}
|
||||
query_count++;
|
||||
/* If the mesh query list is full, exit the loop. */
|
||||
if(mesh_jostle_exceeded(qstate->env->mesh))
|
||||
break;
|
||||
}
|
||||
|
||||
/* mark this target as in progress. */
|
||||
@@ -2063,14 +2129,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 */
|
||||
@@ -2085,8 +2151,17 @@ processLastResort(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
}
|
||||
ns->done_pside6 = 1;
|
||||
query_count++;
|
||||
if(mesh_jostle_exceeded(qstate->env->mesh)) {
|
||||
/* Wait for the lookup; do not spawn multiple
|
||||
* lookups at a time. */
|
||||
verbose(VERB_ALGO, "try parent-side glue lookup");
|
||||
iq->num_target_queries += query_count;
|
||||
target_count_increase(iq, query_count);
|
||||
qstate->ext_state[id] = module_wait_subquery;
|
||||
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,
|
||||
@@ -2228,11 +2303,14 @@ 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;
|
||||
int sq_check_ratelimit = 1;
|
||||
int sq_was_ratelimited = 0;
|
||||
int can_do_promisc = 0;
|
||||
|
||||
/* NOTE: a request will encounter this state for each target it
|
||||
* needs to send a query to. That is, at least one per referral,
|
||||
@@ -2244,14 +2322,13 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
iq->num_current_queries, iq->sent_count);
|
||||
|
||||
/* Make sure that we haven't run away */
|
||||
/* FIXME: is this check even necessary? */
|
||||
if(iq->referral_count > MAX_REFERRAL_COUNT) {
|
||||
verbose(VERB_QUERY, "request has exceeded the maximum "
|
||||
"number of referrrals with %d", iq->referral_count);
|
||||
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");
|
||||
@@ -2353,7 +2430,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);
|
||||
|
||||
@@ -2561,6 +2638,11 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
&& iq->num_target_queries == 0
|
||||
&& (!iq->target_count || iq->target_count[TARGET_COUNT_NX]==0)
|
||||
&& iq->sent_count < TARGET_FETCH_STOP) {
|
||||
can_do_promisc = 1;
|
||||
}
|
||||
/* if the mesh query list is full, then do not waste cpu and sockets to
|
||||
* fetch promiscuous targets. They can be looked up when needed. */
|
||||
if(can_do_promisc && !mesh_jostle_exceeded(qstate->env->mesh)) {
|
||||
tf_policy = ie->target_fetch_policy[iq->depth];
|
||||
}
|
||||
|
||||
@@ -2593,7 +2675,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 "
|
||||
@@ -2732,18 +2814,61 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* We have a target. We could have created promiscuous target
|
||||
* queries but we are currently under pressure (mesh_jostle_exceeded).
|
||||
* If we are configured to allow promiscuous target queries and haven't
|
||||
* gone out to the network for a target query for this delegation, then
|
||||
* it is possible to slip in a promiscuous one with a 1/10 chance. */
|
||||
if(can_do_promisc && tf_policy == 0 && iq->depth == 0
|
||||
&& iq->depth < ie->max_dependency_depth
|
||||
&& ie->target_fetch_policy[iq->depth] != 0
|
||||
&& iq->dp_target_count == 0
|
||||
&& !ub_random_max(qstate->env->rnd, 10)) {
|
||||
int extra = 0;
|
||||
verbose(VERB_ALGO, "available target exists in cache but "
|
||||
"attempt to get extra 1 target");
|
||||
(void)query_for_targets(qstate, iq, ie, id, 1, &extra);
|
||||
/* errors ignored, these targets are not strictly necessary for
|
||||
* this result, we do not have to reply with SERVFAIL */
|
||||
if(extra > 0) {
|
||||
iq->num_target_queries += extra;
|
||||
target_count_increase(iq, extra);
|
||||
check_waiting_queries(iq, qstate, id);
|
||||
/* undo qname minimise step because we'll get back here
|
||||
* to do it again */
|
||||
if(qout_orig && iq->minimise_count > 0) {
|
||||
iq->minimise_count--;
|
||||
iq->qinfo_out.qname = qout_orig;
|
||||
iq->qinfo_out.qname_len = qout_orig_len;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Do not check ratelimit for forwarding queries or if we already got a
|
||||
* pass. */
|
||||
sq_check_ratelimit = (!(iq->chase_flags & BIT_RD) && !iq->ratelimit_ok);
|
||||
/* 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),
|
||||
@@ -2754,7 +2879,7 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
!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),
|
||||
@@ -2771,7 +2896,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);
|
||||
@@ -2815,7 +2940,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;
|
||||
enum response_type type;
|
||||
|
||||
iq->num_current_queries--;
|
||||
@@ -2839,6 +2964,8 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
(int)((iq->chase_flags&BIT_RD) || iq->chase_to_rd),
|
||||
iq->response, &iq->qinfo_out, iq->dp);
|
||||
iq->chase_to_rd = 0;
|
||||
/* remove TC flag, if this is erroneously set by TCP upstream */
|
||||
iq->response->rep->flags &= ~BIT_TC;
|
||||
if(type == RESPONSE_TYPE_REFERRAL && (iq->chase_flags&BIT_RD) &&
|
||||
!iq->auth_zone_response) {
|
||||
/* When forwarding (RD bit is set), we handle referrals
|
||||
@@ -2862,8 +2989,8 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
* use dnssec-lame-bypass if it needs to query there.*/
|
||||
if(qstate->reply) {
|
||||
struct delegpt_addr* a = delegpt_find_addr(
|
||||
iq->dp, &qstate->reply->addr,
|
||||
qstate->reply->addrlen);
|
||||
iq->dp, &qstate->reply->remote_addr,
|
||||
qstate->reply->remote_addrlen);
|
||||
if(a) a->dnsseclame = 1;
|
||||
}
|
||||
/* test the answer is from the zone we expected,
|
||||
@@ -2896,6 +3023,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;
|
||||
@@ -2959,9 +3088,9 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
(*qstate->env->detach_subs)(qstate);
|
||||
iq->num_target_queries = 0;
|
||||
if(qstate->reply)
|
||||
sock_list_insert(&qstate->reply_origin,
|
||||
&qstate->reply->addr, qstate->reply->addrlen,
|
||||
qstate->region);
|
||||
sock_list_insert(&qstate->reply_origin,
|
||||
&qstate->reply->remote_addr,
|
||||
qstate->reply->remote_addrlen, qstate->region);
|
||||
if(iq->minimisation_state != DONOT_MINIMISE_STATE
|
||||
&& !(iq->chase_flags & BIT_RD)) {
|
||||
if(FLAGS_GET_RCODE(iq->response->rep->flags) !=
|
||||
@@ -2981,11 +3110,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
|
||||
@@ -3113,7 +3245,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) {
|
||||
@@ -3216,9 +3348,9 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
(*qstate->env->detach_subs)(qstate);
|
||||
iq->num_target_queries = 0;
|
||||
if(qstate->reply)
|
||||
sock_list_insert(&qstate->reply_origin,
|
||||
&qstate->reply->addr, qstate->reply->addrlen,
|
||||
qstate->region);
|
||||
sock_list_insert(&qstate->reply_origin,
|
||||
&qstate->reply->remote_addr,
|
||||
qstate->reply->remote_addrlen, qstate->region);
|
||||
verbose(VERB_ALGO, "cleared outbound list for query restart");
|
||||
/* go to INIT_REQUEST_STATE for new qname. */
|
||||
return next_state(iq, INIT_REQUEST_STATE);
|
||||
@@ -3232,9 +3364,10 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
} else if(qstate->reply) {
|
||||
/* need addr for lameness cache, but we may have
|
||||
* gotten this from cache, so test to be sure */
|
||||
if(!infra_set_lame(qstate->env->infra_cache,
|
||||
&qstate->reply->addr, qstate->reply->addrlen,
|
||||
iq->dp->name, iq->dp->namelen,
|
||||
if(!infra_set_lame(qstate->env->infra_cache,
|
||||
&qstate->reply->remote_addr,
|
||||
qstate->reply->remote_addrlen,
|
||||
iq->dp->name, iq->dp->namelen,
|
||||
*qstate->env->now, dnsseclame, 0,
|
||||
iq->qchase.qtype))
|
||||
log_err("mark host lame: out of memory");
|
||||
@@ -3251,8 +3384,9 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
* gotten this from cache, so test to be sure */
|
||||
verbose(VERB_DETAIL, "mark as REC_LAME");
|
||||
if(!infra_set_lame(qstate->env->infra_cache,
|
||||
&qstate->reply->addr, qstate->reply->addrlen,
|
||||
iq->dp->name, iq->dp->namelen,
|
||||
&qstate->reply->remote_addr,
|
||||
qstate->reply->remote_addrlen,
|
||||
iq->dp->name, iq->dp->namelen,
|
||||
*qstate->env->now, 0, 1, iq->qchase.qtype))
|
||||
log_err("mark host lame: out of memory");
|
||||
}
|
||||
@@ -3493,12 +3627,13 @@ processTargetResponse(struct module_qstate* qstate, int id,
|
||||
} else {
|
||||
verbose(VERB_ALGO, "iterator TargetResponse failed");
|
||||
delegpt_mark_neg(dpns, qstate->qinfo.qtype);
|
||||
dpns->resolved = 1; /* fail the target */
|
||||
if((dpns->got4 == 2 || !ie->supports_ipv4) &&
|
||||
(dpns->got6 == 2 || !ie->supports_ipv6) &&
|
||||
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 */
|
||||
(qstate->reply_origin && qstate->reply_origin->len != 0)) {
|
||||
target_count_increase_nx(foriq, 1);
|
||||
if(qstate->reply_origin && qstate->reply_origin->len != 0) {
|
||||
target_count_increase_nx(foriq, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3737,6 +3872,9 @@ 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;
|
||||
|
||||
/* we have finished processing this query */
|
||||
qstate->ext_state[id] = module_finished;
|
||||
|
||||
@@ -3915,7 +4053,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) {
|
||||
@@ -3980,8 +4119,8 @@ process_response(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
if(!iq->response)
|
||||
goto handle_it;
|
||||
log_query_info(VERB_DETAIL, "response for", &qstate->qinfo);
|
||||
log_name_addr(VERB_DETAIL, "reply from", iq->dp->name,
|
||||
&qstate->reply->addr, qstate->reply->addrlen);
|
||||
log_name_addr(VERB_DETAIL, "reply from", iq->dp->name,
|
||||
&qstate->reply->remote_addr, qstate->reply->remote_addrlen);
|
||||
if(verbosity >= VERB_ALGO)
|
||||
log_dns_msg("incoming scrubbed packet:", &iq->response->qinfo,
|
||||
iq->response->rep);
|
||||
|
||||
+28
-7
@@ -63,12 +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 */
|
||||
#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
|
||||
@@ -107,7 +103,7 @@ extern int BLACKLIST_PENALTY;
|
||||
#define RTT_BAND 400
|
||||
|
||||
/**
|
||||
* 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 */
|
||||
@@ -116,6 +112,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;
|
||||
|
||||
@@ -145,6 +153,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;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -324,7 +338,7 @@ struct iter_qstate {
|
||||
/** the number of times this query has been restarted. */
|
||||
int query_restart_count;
|
||||
|
||||
/** the number of times this query as followed a referral. */
|
||||
/** the number of times this query has followed a referral. */
|
||||
int referral_count;
|
||||
|
||||
/** number of queries fired off */
|
||||
@@ -437,7 +451,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;
|
||||
|
||||
+40
-3
@@ -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);
|
||||
@@ -951,7 +988,7 @@ ub_ctx_set_fwd(struct ub_ctx* ctx, const char* addr)
|
||||
lock_basic_unlock(&ctx->cfglock);
|
||||
|
||||
/* check syntax for addr */
|
||||
if(!extstrtoaddr(addr, &storage, &stlen)) {
|
||||
if(!extstrtoaddr(addr, &storage, &stlen, UNBOUND_DNS_PORT)) {
|
||||
errno=EINVAL;
|
||||
return UB_SYNTAX;
|
||||
}
|
||||
@@ -1031,7 +1068,7 @@ int ub_ctx_set_stub(struct ub_ctx* ctx, const char* zone, const char* addr,
|
||||
if(addr) {
|
||||
struct sockaddr_storage storage;
|
||||
socklen_t stlen;
|
||||
if(!extstrtoaddr(addr, &storage, &stlen)) {
|
||||
if(!extstrtoaddr(addr, &storage, &stlen, UNBOUND_DNS_PORT)) {
|
||||
errno=EINVAL;
|
||||
return UB_SYNTAX;
|
||||
}
|
||||
|
||||
@@ -168,14 +168,12 @@ 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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
if(!w->is_bg || w->is_bg_thread) {
|
||||
lock_basic_unlock(&ctx->cfglock);
|
||||
@@ -395,6 +393,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 +603,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"
|
||||
%}
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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.
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
+153
-41
@@ -609,9 +609,9 @@ struct mesh_reply {
|
||||
struct comm_reply query_reply;
|
||||
};
|
||||
|
||||
%rename(_addr) comm_reply::addr;
|
||||
%rename(_addr) comm_reply::client_addr;
|
||||
struct comm_reply {
|
||||
struct sockaddr_storage addr;
|
||||
struct sockaddr_storage client_addr;
|
||||
};
|
||||
|
||||
%extend comm_reply {
|
||||
@@ -1378,7 +1378,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 +1409,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 +1551,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 +1570,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 +1597,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 +1644,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 +1695,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 +1810,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);
|
||||
|
||||
+144
-41
@@ -252,13 +252,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;
|
||||
PyGILState_STATE gil;
|
||||
int init_standard = 1, i = 0;
|
||||
#if PY_MAJOR_VERSION < 3
|
||||
@@ -292,47 +303,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 +410,22 @@ 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);
|
||||
Py_XINCREF(pe->dict);
|
||||
pe->data = PyDict_New();
|
||||
Py_XINCREF(pe->data);
|
||||
PyModule_AddObject(pe->module, "mod_env", pe->data);
|
||||
|
||||
/* TODO: deallocation of pe->... if an error occurs */
|
||||
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 +456,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 +487,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 +519,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 +556,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 +600,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 */
|
||||
|
||||
@@ -172,14 +172,14 @@ int createResponse(struct module_qstate* qstate, sldns_buffer* pkt)
|
||||
}
|
||||
|
||||
|
||||
/* Convert reply->addr to string */
|
||||
/* Convert reply->client_addr to string */
|
||||
void reply_addr2str(struct comm_reply* reply, char* dest, int maxlen)
|
||||
{
|
||||
int af = (int)((struct sockaddr_in*) &(reply->addr))->sin_family;
|
||||
void* sinaddr = &((struct sockaddr_in*) &(reply->addr))->sin_addr;
|
||||
int af = (int)((struct sockaddr_in*) &(reply->client_addr))->sin_family;
|
||||
void* sinaddr = &((struct sockaddr_in*) &(reply->client_addr))->sin_addr;
|
||||
|
||||
if(af == AF_INET6)
|
||||
sinaddr = &((struct sockaddr_in6*)&(reply->addr))->sin6_addr;
|
||||
sinaddr = &((struct sockaddr_in6*)&(reply->client_addr))->sin6_addr;
|
||||
dest[0] = 0;
|
||||
if (inet_ntop(af, sinaddr, dest, (socklen_t)maxlen) == 0)
|
||||
return;
|
||||
|
||||
+5
-5
@@ -1290,7 +1290,7 @@ respip_set_is_empty(const struct respip_set* set)
|
||||
void
|
||||
respip_inform_print(struct respip_action_info* respip_actinfo, uint8_t* qname,
|
||||
uint16_t qtype, uint16_t qclass, struct local_rrset* local_alias,
|
||||
struct comm_reply* repinfo)
|
||||
struct sockaddr_storage* addr, socklen_t addrlen)
|
||||
{
|
||||
char srcip[128], respip[128], txt[512];
|
||||
unsigned port;
|
||||
@@ -1300,10 +1300,10 @@ respip_inform_print(struct respip_action_info* respip_actinfo, uint8_t* qname,
|
||||
|
||||
if(local_alias)
|
||||
qname = local_alias->rrset->rk.dname;
|
||||
port = (unsigned)((repinfo->addr.ss_family == AF_INET) ?
|
||||
ntohs(((struct sockaddr_in*)&repinfo->addr)->sin_port) :
|
||||
ntohs(((struct sockaddr_in6*)&repinfo->addr)->sin6_port));
|
||||
addr_to_str(&repinfo->addr, repinfo->addrlen, srcip, sizeof(srcip));
|
||||
port = (unsigned)((addr->ss_family == AF_INET) ?
|
||||
ntohs(((struct sockaddr_in*)addr)->sin_port) :
|
||||
ntohs(((struct sockaddr_in6*)addr)->sin6_port));
|
||||
addr_to_str(addr, addrlen, srcip, sizeof(srcip));
|
||||
addr_to_str(&respip_addr->addr, respip_addr->addrlen,
|
||||
respip, sizeof(respip));
|
||||
if(respip_actinfo->rpz_log) {
|
||||
|
||||
+4
-2
@@ -251,11 +251,13 @@ int respip_set_is_empty(const struct respip_set* set);
|
||||
* @param local_alias: set to a local alias if the query matches an alias in
|
||||
* a local zone. In this case its owner name will be considered the actual
|
||||
* query name.
|
||||
* @param repinfo: reply info containing the client's source address and port.
|
||||
* @param addr: the client's source address and port.
|
||||
* @param addrlen: the client's source address length.
|
||||
*/
|
||||
void respip_inform_print(struct respip_action_info* respip_actinfo,
|
||||
uint8_t* qname, uint16_t qtype, uint16_t qclass,
|
||||
struct local_rrset* local_alias, struct comm_reply* repinfo);
|
||||
struct local_rrset* local_alias, struct sockaddr_storage* addr,
|
||||
socklen_t addrlen);
|
||||
|
||||
/**
|
||||
* Find resp_addr in tree, create and add to tree if it does not exist.
|
||||
|
||||
+11
-6
@@ -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;
|
||||
}
|
||||
@@ -2756,6 +2756,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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3699,7 +3700,7 @@ addr_matches_master(struct auth_master* master, struct sockaddr_storage* addr,
|
||||
/* compare address (but not port number, that is the destination
|
||||
* port of the master, the port number of the received notify is
|
||||
* allowed to by any port on that master) */
|
||||
if(extstrtoaddr(master->host, &a, &alen) &&
|
||||
if(extstrtoaddr(master->host, &a, &alen, UNBOUND_DNS_PORT) &&
|
||||
sockaddr_cmp_addr(addr, addrlen, &a, alen)==0) {
|
||||
*fromhost = master;
|
||||
return 1;
|
||||
@@ -5381,7 +5382,7 @@ xfr_transfer_lookup_host(struct auth_xfer* xfr, struct module_env* env)
|
||||
struct edns_data edns;
|
||||
sldns_buffer* buf = env->scratch_buffer;
|
||||
if(!master) return 0;
|
||||
if(extstrtoaddr(master->host, &addr, &addrlen)) {
|
||||
if(extstrtoaddr(master->host, &addr, &addrlen, UNBOUND_DNS_PORT)) {
|
||||
/* not needed, host is in IP addr format */
|
||||
return 0;
|
||||
}
|
||||
@@ -5419,6 +5420,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;
|
||||
@@ -6572,7 +6575,7 @@ xfr_probe_lookup_host(struct auth_xfer* xfr, struct module_env* env)
|
||||
struct edns_data edns;
|
||||
sldns_buffer* buf = env->scratch_buffer;
|
||||
if(!master) return 0;
|
||||
if(extstrtoaddr(master->host, &addr, &addrlen)) {
|
||||
if(extstrtoaddr(master->host, &addr, &addrlen, UNBOUND_DNS_PORT)) {
|
||||
/* not needed, host is in IP addr format */
|
||||
return 0;
|
||||
}
|
||||
@@ -6612,6 +6615,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 +7514,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;
|
||||
|
||||
Vendored
+29
-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;
|
||||
}
|
||||
|
||||
@@ -404,6 +386,9 @@ cache_fill_missing(struct module_env* env, uint16_t qclass,
|
||||
struct ub_packed_rrset_key* akey;
|
||||
time_t now = *env->now;
|
||||
for(ns = dp->nslist; ns; ns = ns->next) {
|
||||
if(ns->cache_lookup_count > ITERATOR_NAME_CACHELOOKUP_MAX)
|
||||
continue;
|
||||
ns->cache_lookup_count++;
|
||||
akey = rrset_cache_lookup(env->rrset_cache, ns->name,
|
||||
ns->namelen, LDNS_RR_TYPE_A, qclass, 0, now, 0);
|
||||
if(akey) {
|
||||
@@ -607,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**)
|
||||
@@ -633,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;
|
||||
}
|
||||
@@ -661,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;
|
||||
}
|
||||
@@ -1064,7 +1062,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;
|
||||
@@ -1081,7 +1078,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
+63
-43
@@ -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))
|
||||
{
|
||||
@@ -834,14 +839,13 @@ static struct lruhash_entry* infra_find_ratedata(struct infra_cache* infra,
|
||||
|
||||
/** find data item in array for ip addresses */
|
||||
static struct lruhash_entry* infra_find_ip_ratedata(struct infra_cache* infra,
|
||||
struct comm_reply* repinfo, int wr)
|
||||
struct sockaddr_storage* addr, socklen_t addrlen, int wr)
|
||||
{
|
||||
struct ip_rate_key key;
|
||||
hashvalue_type h = hash_addr(&(repinfo->addr),
|
||||
repinfo->addrlen, 0);
|
||||
hashvalue_type h = hash_addr(addr, addrlen, 0);
|
||||
memset(&key, 0, sizeof(key));
|
||||
key.addr = repinfo->addr;
|
||||
key.addrlen = repinfo->addrlen;
|
||||
key.addr = *addr;
|
||||
key.addrlen = addrlen;
|
||||
key.entry.hash = h;
|
||||
return slabhash_lookup(infra->client_ip_rates, h, &key, wr);
|
||||
}
|
||||
@@ -876,10 +880,9 @@ static void infra_create_ratedata(struct infra_cache* infra,
|
||||
|
||||
/** create rate data item for ip address */
|
||||
static void infra_ip_create_ratedata(struct infra_cache* infra,
|
||||
struct comm_reply* repinfo, time_t timenow)
|
||||
struct sockaddr_storage* addr, socklen_t addrlen, time_t timenow)
|
||||
{
|
||||
hashvalue_type h = hash_addr(&(repinfo->addr),
|
||||
repinfo->addrlen, 0);
|
||||
hashvalue_type h = hash_addr(addr, addrlen, 0);
|
||||
struct ip_rate_key* k = (struct ip_rate_key*)calloc(1, sizeof(*k));
|
||||
struct ip_rate_data* d = (struct ip_rate_data*)calloc(1, sizeof(*d));
|
||||
if(!k || !d) {
|
||||
@@ -887,8 +890,8 @@ static void infra_ip_create_ratedata(struct infra_cache* infra,
|
||||
free(d);
|
||||
return; /* alloc failure */
|
||||
}
|
||||
k->addr = repinfo->addr;
|
||||
k->addrlen = repinfo->addrlen;
|
||||
k->addr = *addr;
|
||||
k->addrlen = addrlen;
|
||||
lock_rw_init(&k->entry.lock);
|
||||
k->entry.hash = h;
|
||||
k->entry.key = k;
|
||||
@@ -985,8 +988,8 @@ int infra_ratelimit_inc(struct infra_cache* infra, uint8_t* name,
|
||||
sldns_wire2str_class_buf(qinfo->qclass, cs, sizeof(cs));
|
||||
ip[0]=0;
|
||||
if(replylist) {
|
||||
addr_to_str((struct sockaddr_storage *)&replylist->addr,
|
||||
replylist->addrlen, ip, sizeof(ip));
|
||||
addr_to_str((struct sockaddr_storage *)&replylist->remote_addr,
|
||||
replylist->remote_addrlen, ip, sizeof(ip));
|
||||
verbose(VERB_OPS, "ratelimit exceeded %s %d query %s %s %s from %s", buf, lim, qnm, cs, ts, ip);
|
||||
} else {
|
||||
verbose(VERB_OPS, "ratelimit exceeded %s %d query %s %s %s", buf, lim, qnm, cs, ts);
|
||||
@@ -1040,7 +1043,7 @@ int infra_ratelimit_exceeded(struct infra_cache* infra, uint8_t* name,
|
||||
max = infra_rate_max(entry->data, timenow, backoff);
|
||||
lock_rw_unlock(&entry->lock);
|
||||
|
||||
return (max >= lim);
|
||||
return (max > lim);
|
||||
}
|
||||
|
||||
size_t
|
||||
@@ -1053,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 comm_reply* repinfo, time_t timenow, int backoff,
|
||||
struct sldns_buffer* buffer)
|
||||
struct sockaddr_storage* addr, socklen_t addrlen, time_t timenow,
|
||||
int has_cookie, int backoff, struct sldns_buffer* buffer)
|
||||
{
|
||||
int max;
|
||||
struct lruhash_entry* entry;
|
||||
@@ -1065,42 +1109,18 @@ int infra_ip_ratelimit_inc(struct infra_cache* infra,
|
||||
return 1;
|
||||
}
|
||||
/* find or insert ratedata */
|
||||
entry = infra_find_ip_ratedata(infra, repinfo, 1);
|
||||
entry = infra_find_ip_ratedata(infra, addr, addrlen, 1);
|
||||
if(entry) {
|
||||
int premax = infra_rate_max(entry->data, timenow, backoff);
|
||||
int* cur = infra_rate_give_second(entry->data, timenow);
|
||||
(*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((struct sockaddr_storage *)&repinfo->addr,
|
||||
repinfo->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 */
|
||||
infra_ip_create_ratedata(infra, repinfo, timenow);
|
||||
infra_ip_create_ratedata(infra, addr, addrlen, timenow);
|
||||
return 1;
|
||||
}
|
||||
|
||||
Vendored
+7
-3
@@ -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.
|
||||
@@ -416,15 +418,17 @@ int infra_find_ratelimit(struct infra_cache* infra, uint8_t* name,
|
||||
/** Update query ratelimit hash and decide
|
||||
* whether or not a query should be dropped.
|
||||
* @param infra: infra cache
|
||||
* @param repinfo: information about client
|
||||
* @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 comm_reply* repinfo, time_t timenow, int backoff,
|
||||
struct sldns_buffer* buffer);
|
||||
struct sockaddr_storage* addr, socklen_t addrlen, time_t timenow,
|
||||
int has_cookie, int backoff, struct sldns_buffer* buffer);
|
||||
|
||||
/**
|
||||
* Get memory used by the infra cache.
|
||||
|
||||
+184
-103
@@ -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 */
|
||||
@@ -124,12 +126,12 @@ verbose_print_addr(struct addrinfo *addr)
|
||||
(void)strlcpy(buf, "(null)", sizeof(buf));
|
||||
}
|
||||
buf[sizeof(buf)-1] = 0;
|
||||
verbose(VERB_ALGO, "creating %s%s socket %s %d",
|
||||
verbose(VERB_ALGO, "creating %s%s socket %s %d",
|
||||
addr->ai_socktype==SOCK_DGRAM?"udp":
|
||||
addr->ai_socktype==SOCK_STREAM?"tcp":"otherproto",
|
||||
addr->ai_family==AF_INET?"4":
|
||||
addr->ai_family==AF_INET6?"6":
|
||||
"_otherfam", buf,
|
||||
"_otherfam", buf,
|
||||
ntohs(((struct sockaddr_in*)addr->ai_addr)->sin_port));
|
||||
}
|
||||
}
|
||||
@@ -140,7 +142,9 @@ verbose_print_unbound_socket(struct unbound_socket* ub_sock)
|
||||
if(verbosity >= VERB_ALGO) {
|
||||
log_info("listing of unbound_socket structure:");
|
||||
verbose_print_addr(ub_sock->addr);
|
||||
log_info("s is: %d, fam is: %s", ub_sock->s, ub_sock->fam == AF_INET?"AF_INET":"AF_INET6");
|
||||
log_info("s is: %d, fam is: %s, acl: %s", ub_sock->s,
|
||||
ub_sock->fam == AF_INET?"AF_INET":"AF_INET6",
|
||||
ub_sock->acl?"yes":"no");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -185,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;
|
||||
@@ -251,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;
|
||||
@@ -268,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));
|
||||
@@ -366,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, "
|
||||
@@ -379,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));
|
||||
@@ -390,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 "
|
||||
@@ -411,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, "
|
||||
@@ -424,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));
|
||||
@@ -435,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 "
|
||||
@@ -458,9 +462,16 @@ create_udp_sock(int family, int socktype, struct sockaddr* addr,
|
||||
int action;
|
||||
# endif
|
||||
# if defined(IPV6_V6ONLY)
|
||||
if(v6only) {
|
||||
if(v6only
|
||||
# ifdef HAVE_SYSTEMD
|
||||
/* Systemd wants to control if the socket is v6 only
|
||||
* or both, with BindIPv6Only=default, ipv6-only or
|
||||
* both in systemd.socket, so it is not set here. */
|
||||
&& !got_fd_from_systemd
|
||||
# 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));
|
||||
@@ -511,12 +522,14 @@ create_udp_sock(int family, int socktype, struct sockaddr* addr,
|
||||
* instead which is writable; IPV6_MTU is readonly there. */
|
||||
if (setsockopt(s, IPPROTO_IPV6, IPV6_USER_MTU,
|
||||
(void*)&mtu, (socklen_t)sizeof(mtu)) < 0) {
|
||||
log_err("setsockopt(..., IPV6_USER_MTU, ...) failed: %s",
|
||||
wsa_strerror(WSAGetLastError()));
|
||||
sock_close(s);
|
||||
*noproto = 0;
|
||||
*inuse = 0;
|
||||
return -1;
|
||||
if (WSAGetLastError() != WSAENOPROTOOPT) {
|
||||
log_err("setsockopt(..., IPV6_USER_MTU, ...) failed: %s",
|
||||
wsa_strerror(WSAGetLastError()));
|
||||
sock_close(s);
|
||||
*noproto = 0;
|
||||
*inuse = 0;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
# endif /* USE_WINSOCK */
|
||||
# endif /* IPv6 MTU */
|
||||
@@ -565,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) {
|
||||
@@ -598,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));
|
||||
@@ -636,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);
|
||||
}
|
||||
@@ -738,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));
|
||||
@@ -774,8 +787,15 @@ create_tcp_accept_sock(struct addrinfo *addr, int v6only, int* noproto,
|
||||
(void)reuseport;
|
||||
#endif /* defined(SO_REUSEPORT) */
|
||||
#if defined(IPV6_V6ONLY)
|
||||
if(addr->ai_family == AF_INET6 && v6only) {
|
||||
if(setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY,
|
||||
if(addr->ai_family == AF_INET6 && v6only
|
||||
# ifdef HAVE_SYSTEMD
|
||||
/* Systemd wants to control if the socket is v6 only
|
||||
* or both, with BindIPv6Only=default, ipv6-only or
|
||||
* both in systemd.socket, so it is not set here. */
|
||||
&& !got_fd_from_systemd
|
||||
# endif
|
||||
) {
|
||||
if(setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY,
|
||||
(void*)&on, (socklen_t)sizeof(on)) < 0) {
|
||||
log_err("setsockopt(..., IPV6_V6ONLY, ...) failed: %s",
|
||||
sock_strerror(errno));
|
||||
@@ -827,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);
|
||||
@@ -855,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
|
||||
@@ -981,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)
|
||||
@@ -997,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
|
||||
@@ -1030,13 +1050,14 @@ make_sock(int stype, const char* ifname, const char* port,
|
||||
ub_sock->addr = res;
|
||||
ub_sock->s = s;
|
||||
ub_sock->fam = hints->ai_family;
|
||||
ub_sock->acl = NULL;
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
/** 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)
|
||||
@@ -1074,11 +1095,13 @@ make_sock_port(int stype, const char* ifname, const char* port,
|
||||
* @param list: list head. changed.
|
||||
* @param s: fd.
|
||||
* @param ftype: if fd is UDP.
|
||||
* @param pp2_enabled: if PROXYv2 is enabled for this port.
|
||||
* @param ub_sock: socket with address.
|
||||
* @return false on failure. list in unchanged then.
|
||||
*/
|
||||
static int
|
||||
port_insert(struct listen_port** list, int s, enum listen_type ftype, struct unbound_socket* ub_sock)
|
||||
port_insert(struct listen_port** list, int s, enum listen_type ftype,
|
||||
int pp2_enabled, struct unbound_socket* ub_sock)
|
||||
{
|
||||
struct listen_port* item = (struct listen_port*)malloc(
|
||||
sizeof(struct listen_port));
|
||||
@@ -1087,14 +1110,34 @@ port_insert(struct listen_port** list, int s, enum listen_type ftype, struct unb
|
||||
item->next = *list;
|
||||
item->fd = s;
|
||||
item->ftype = ftype;
|
||||
item->pp2_enabled = pp2_enabled;
|
||||
item->socket = ub_sock;
|
||||
*list = item;
|
||||
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;
|
||||
@@ -1182,6 +1225,7 @@ if_is_ssl(const char* ifname, const char* port, int ssl_port,
|
||||
* @param ssl_port: ssl service port number
|
||||
* @param tls_additional_port: list of additional ssl service port numbers.
|
||||
* @param https_port: DoH service port number
|
||||
* @param proxy_protocol_port: list of PROXYv2 port numbers.
|
||||
* @param reuseport: try to set SO_REUSEPORT if nonNULL and true.
|
||||
* set to false on exit if reuseport failed due to no kernel support.
|
||||
* @param transparent: set IP_TRANSPARENT socket option.
|
||||
@@ -1191,40 +1235,50 @@ 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
|
||||
ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp,
|
||||
ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp,
|
||||
struct addrinfo *hints, const char* port, struct listen_port** list,
|
||||
size_t rcv, size_t snd, int ssl_port,
|
||||
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);
|
||||
int is_dnscrypt = if_is_dnscrypt(ifname, port, dnscrypt_port);
|
||||
int is_pp2 = if_is_pp2(ifname, port, proxy_protocol_port);
|
||||
int nodelay = is_https && http2_nodelay;
|
||||
struct unbound_socket* ub_sock;
|
||||
#ifdef USE_DNSCRYPT
|
||||
int is_dnscrypt = ((strchr(ifname, '@') &&
|
||||
atoi(strchr(ifname, '@')+1) == dnscrypt_port) ||
|
||||
(!strchr(ifname, '@') && atoi(port) == dnscrypt_port));
|
||||
#else
|
||||
int is_dnscrypt = 0;
|
||||
(void)dnscrypt_port;
|
||||
#endif
|
||||
|
||||
if(!do_udp && !do_tcp)
|
||||
return 0;
|
||||
|
||||
if(is_pp2) {
|
||||
if(is_dnscrypt) {
|
||||
fatal_exit("PROXYv2 and DNSCrypt combination not "
|
||||
"supported!");
|
||||
} else if(is_https) {
|
||||
fatal_exit("PROXYv2 and DoH combination not "
|
||||
"supported!");
|
||||
}
|
||||
}
|
||||
|
||||
if(do_auto) {
|
||||
ub_sock = calloc(1, sizeof(struct unbound_socket));
|
||||
if(!ub_sock)
|
||||
return 0;
|
||||
if((s = make_sock_port(SOCK_DGRAM, ifname, port, hints, 1,
|
||||
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");
|
||||
@@ -1235,14 +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(!port_insert(list, s,
|
||||
is_dnscrypt?listen_type_udpancil_dnscrypt:listen_type_udpancil, ub_sock)) {
|
||||
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;
|
||||
}
|
||||
@@ -1251,10 +1311,11 @@ ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp,
|
||||
if(!ub_sock)
|
||||
return 0;
|
||||
/* regular udp socket */
|
||||
if((s = make_sock_port(SOCK_DGRAM, ifname, port, hints, 1,
|
||||
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");
|
||||
@@ -1262,10 +1323,15 @@ ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp,
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
if(!port_insert(list, s,
|
||||
is_dnscrypt?listen_type_udp_dnscrypt:listen_type_udp, ub_sock)) {
|
||||
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,
|
||||
is_pp2, ub_sock)) {
|
||||
sock_close(s);
|
||||
freeaddrinfo(ub_sock->addr);
|
||||
if(ub_sock->addr)
|
||||
freeaddrinfo(ub_sock->addr);
|
||||
free(ub_sock);
|
||||
return 0;
|
||||
}
|
||||
@@ -1285,10 +1351,11 @@ ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp,
|
||||
port_type = listen_type_tcp_dnscrypt;
|
||||
else
|
||||
port_type = listen_type_tcp;
|
||||
if((s = make_sock_port(SOCK_STREAM, ifname, port, hints, 1,
|
||||
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");*/
|
||||
@@ -1298,9 +1365,10 @@ ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp,
|
||||
}
|
||||
if(is_ssl)
|
||||
verbose(VERB_ALGO, "setup TCP for SSL service");
|
||||
if(!port_insert(list, s, port_type, ub_sock)) {
|
||||
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;
|
||||
}
|
||||
@@ -1308,7 +1376,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.
|
||||
@@ -1359,7 +1427,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,
|
||||
@@ -1387,14 +1455,16 @@ listen_create(struct comm_base* base, struct listen_port* ports,
|
||||
if(ports->ftype == listen_type_udp ||
|
||||
ports->ftype == listen_type_udp_dnscrypt) {
|
||||
cp = comm_point_create_udp(base, ports->fd,
|
||||
front->udp_buff, cb, cb_arg, ports->socket);
|
||||
front->udp_buff, ports->pp2_enabled, cb,
|
||||
cb_arg, ports->socket);
|
||||
} else if(ports->ftype == listen_type_tcp ||
|
||||
ports->ftype == listen_type_tcp_dnscrypt) {
|
||||
cp = comm_point_create_tcp(base, ports->fd,
|
||||
tcp_accept_count, tcp_idle_timeout,
|
||||
harden_large_queries, 0, NULL,
|
||||
tcp_conn_limit, bufsize, front->udp_buff,
|
||||
ports->ftype, cb, cb_arg, ports->socket);
|
||||
ports->ftype, ports->pp2_enabled, cb, cb_arg,
|
||||
ports->socket);
|
||||
} else if(ports->ftype == listen_type_ssl ||
|
||||
ports->ftype == listen_type_http) {
|
||||
cp = comm_point_create_tcp(base, ports->fd,
|
||||
@@ -1402,7 +1472,8 @@ listen_create(struct comm_base* base, struct listen_port* ports,
|
||||
harden_large_queries,
|
||||
http_max_streams, http_endpoint,
|
||||
tcp_conn_limit, bufsize, front->udp_buff,
|
||||
ports->ftype, cb, cb_arg, ports->socket);
|
||||
ports->ftype, ports->pp2_enabled, cb, cb_arg,
|
||||
ports->socket);
|
||||
if(ports->ftype == listen_type_http) {
|
||||
if(!sslctx && !http_notls) {
|
||||
log_warn("HTTPS port configured, but "
|
||||
@@ -1428,7 +1499,8 @@ listen_create(struct comm_base* base, struct listen_port* ports,
|
||||
} else if(ports->ftype == listen_type_udpancil ||
|
||||
ports->ftype == listen_type_udpancil_dnscrypt) {
|
||||
cp = comm_point_create_udp_ancil(base, ports->fd,
|
||||
front->udp_buff, cb, cb_arg, ports->socket);
|
||||
front->udp_buff, ports->pp2_enabled, cb,
|
||||
cb_arg, ports->socket);
|
||||
}
|
||||
if(!cp) {
|
||||
log_err("can't create commpoint");
|
||||
@@ -1491,10 +1563,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
|
||||
@@ -1700,7 +1772,7 @@ int resolve_interface_names(char** ifs, int num_ifs,
|
||||
#endif /* HAVE_GETIFADDRS */
|
||||
}
|
||||
|
||||
struct listen_port*
|
||||
struct listen_port*
|
||||
listening_ports_open(struct config_file* cfg, char** ifs, int num_ifs,
|
||||
int* reuseport)
|
||||
{
|
||||
@@ -1763,10 +1835,12 @@ listening_ports_open(struct config_file* cfg, char** ifs, int num_ifs,
|
||||
&hints, portbuf, &list,
|
||||
cfg->so_rcvbuf, cfg->so_sndbuf,
|
||||
cfg->ssl_port, cfg->tls_additional_port,
|
||||
cfg->https_port, reuseport, cfg->ip_transparent,
|
||||
cfg->https_port,
|
||||
cfg->proxy_protocol_port,
|
||||
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;
|
||||
}
|
||||
@@ -1778,10 +1852,12 @@ listening_ports_open(struct config_file* cfg, char** ifs, int num_ifs,
|
||||
&hints, portbuf, &list,
|
||||
cfg->so_rcvbuf, cfg->so_sndbuf,
|
||||
cfg->ssl_port, cfg->tls_additional_port,
|
||||
cfg->https_port, reuseport, cfg->ip_transparent,
|
||||
cfg->https_port,
|
||||
cfg->proxy_protocol_port,
|
||||
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;
|
||||
}
|
||||
@@ -1791,30 +1867,32 @@ listening_ports_open(struct config_file* cfg, char** ifs, int num_ifs,
|
||||
}
|
||||
if(do_ip6) {
|
||||
hints.ai_family = AF_INET6;
|
||||
if(!ports_create_if(do_auto?"::0":"::1",
|
||||
do_auto, cfg->do_udp, do_tcp,
|
||||
if(!ports_create_if(do_auto?"::0":"::1",
|
||||
do_auto, cfg->do_udp, do_tcp,
|
||||
&hints, portbuf, &list,
|
||||
cfg->so_rcvbuf, cfg->so_sndbuf,
|
||||
cfg->ssl_port, cfg->tls_additional_port,
|
||||
cfg->https_port, reuseport, cfg->ip_transparent,
|
||||
cfg->https_port, cfg->proxy_protocol_port,
|
||||
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;
|
||||
}
|
||||
}
|
||||
if(do_ip4) {
|
||||
hints.ai_family = AF_INET;
|
||||
if(!ports_create_if(do_auto?"0.0.0.0":"127.0.0.1",
|
||||
do_auto, cfg->do_udp, do_tcp,
|
||||
if(!ports_create_if(do_auto?"0.0.0.0":"127.0.0.1",
|
||||
do_auto, cfg->do_udp, do_tcp,
|
||||
&hints, portbuf, &list,
|
||||
cfg->so_rcvbuf, cfg->so_sndbuf,
|
||||
cfg->ssl_port, cfg->tls_additional_port,
|
||||
cfg->https_port, reuseport, cfg->ip_transparent,
|
||||
cfg->https_port, cfg->proxy_protocol_port,
|
||||
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;
|
||||
}
|
||||
@@ -1825,13 +1903,14 @@ listening_ports_open(struct config_file* cfg, char** ifs, int num_ifs,
|
||||
continue;
|
||||
hints.ai_family = AF_INET6;
|
||||
if(!ports_create_if(ifs[i], 0, cfg->do_udp,
|
||||
do_tcp, &hints, portbuf, &list,
|
||||
do_tcp, &hints, portbuf, &list,
|
||||
cfg->so_rcvbuf, cfg->so_sndbuf,
|
||||
cfg->ssl_port, cfg->tls_additional_port,
|
||||
cfg->https_port, reuseport, cfg->ip_transparent,
|
||||
cfg->https_port, cfg->proxy_protocol_port,
|
||||
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;
|
||||
}
|
||||
@@ -1840,13 +1919,14 @@ listening_ports_open(struct config_file* cfg, char** ifs, int num_ifs,
|
||||
continue;
|
||||
hints.ai_family = AF_INET;
|
||||
if(!ports_create_if(ifs[i], 0, cfg->do_udp,
|
||||
do_tcp, &hints, portbuf, &list,
|
||||
do_tcp, &hints, portbuf, &list,
|
||||
cfg->so_rcvbuf, cfg->so_sndbuf,
|
||||
cfg->ssl_port, cfg->tls_additional_port,
|
||||
cfg->https_port, reuseport, cfg->ip_transparent,
|
||||
cfg->https_port, cfg->proxy_protocol_port,
|
||||
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;
|
||||
}
|
||||
@@ -1866,7 +1946,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);
|
||||
@@ -1877,8 +1958,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);
|
||||
@@ -1959,7 +2040,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) {
|
||||
@@ -2018,7 +2099,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);
|
||||
@@ -2154,7 +2235,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. */
|
||||
@@ -2214,7 +2295,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) {
|
||||
@@ -2573,7 +2654,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);
|
||||
|
||||
@@ -43,6 +43,7 @@
|
||||
#define LISTEN_DNSPORT_H
|
||||
|
||||
#include "util/netevent.h"
|
||||
#include "daemon/acl_list.h"
|
||||
#ifdef HAVE_NGHTTP2_NGHTTP2_H
|
||||
#include <nghttp2/nghttp2.h>
|
||||
#endif
|
||||
@@ -107,11 +108,13 @@ enum listen_type {
|
||||
*/
|
||||
struct unbound_socket {
|
||||
/** socket-address structure */
|
||||
struct addrinfo * addr;
|
||||
struct addrinfo* addr;
|
||||
/** socket descriptor returned by socket() syscall */
|
||||
int s;
|
||||
int s;
|
||||
/** address family (AF_INET/IF_INET6) */
|
||||
int fam;
|
||||
int fam;
|
||||
/** ACL on the socket (listening interface) */
|
||||
struct acl_addr* acl;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -125,7 +128,10 @@ struct listen_port {
|
||||
int fd;
|
||||
/** type of file descriptor, udp or tcp */
|
||||
enum listen_type ftype;
|
||||
/** fill in unbpound_socket structure for every opened socket at Unbound startup */
|
||||
/** if the port should support PROXYv2 */
|
||||
int pp2_enabled;
|
||||
/** fill in unbound_socket structure for every opened socket at
|
||||
* Unbound startup */
|
||||
struct unbound_socket* socket;
|
||||
};
|
||||
|
||||
|
||||
+25
-7
@@ -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,
|
||||
@@ -1744,13 +1755,13 @@ local_zones_zone_answer(struct local_zone* z, struct module_env* env,
|
||||
/** print log information for an inform zone query */
|
||||
static void
|
||||
lz_inform_print(struct local_zone* z, struct query_info* qinfo,
|
||||
struct comm_reply* repinfo)
|
||||
struct sockaddr_storage* addr, socklen_t addrlen)
|
||||
{
|
||||
char ip[128], txt[512];
|
||||
char zname[LDNS_MAX_DOMAINLEN+1];
|
||||
uint16_t port = ntohs(((struct sockaddr_in*)&repinfo->addr)->sin_port);
|
||||
uint16_t port = ntohs(((struct sockaddr_in*)addr)->sin_port);
|
||||
dname_str(z->name, zname);
|
||||
addr_to_str(&repinfo->addr, repinfo->addrlen, ip, sizeof(ip));
|
||||
addr_to_str(addr, addrlen, ip, sizeof(ip));
|
||||
snprintf(txt, sizeof(txt), "%s %s %s@%u", zname, local_zone_type2str(z->type), ip,
|
||||
(unsigned)port);
|
||||
log_nametypeclass(NO_VERBOSE, txt, qinfo->qname, qinfo->qtype, qinfo->qclass);
|
||||
@@ -1765,7 +1776,8 @@ lz_type(uint8_t *taglist, size_t taglen, uint8_t *taglist2, size_t taglen2,
|
||||
struct local_zone_override* lzo;
|
||||
if(repinfo && override_tree) {
|
||||
lzo = (struct local_zone_override*)addr_tree_lookup(
|
||||
override_tree, &repinfo->addr, repinfo->addrlen);
|
||||
override_tree, &repinfo->client_addr,
|
||||
repinfo->client_addrlen);
|
||||
if(lzo && lzo->type) {
|
||||
verbose(VERB_ALGO, "local zone override to type %s",
|
||||
local_zone_type2str(lzo->type));
|
||||
@@ -1845,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;
|
||||
@@ -1888,10 +1901,12 @@ local_zones_answer(struct local_zones* zones, struct module_env* env,
|
||||
lzt == local_zone_inform_deny ||
|
||||
lzt == local_zone_inform_redirect)
|
||||
&& repinfo)
|
||||
lz_inform_print(z, qinfo, repinfo);
|
||||
lz_inform_print(z, qinfo, &repinfo->client_addr,
|
||||
repinfo->client_addrlen);
|
||||
|
||||
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
|
||||
@@ -1922,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";
|
||||
@@ -1956,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 */
|
||||
|
||||
+197
-206
@@ -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->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;
|
||||
@@ -1280,10 +1200,10 @@ mesh_do_callback(struct mesh_state* m, int rcode, struct reply_info* rep,
|
||||
|
||||
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 +1211,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);
|
||||
@@ -1311,10 +1232,36 @@ mesh_is_rpz_respip_tcponly_action(struct mesh_state const* m)
|
||||
}
|
||||
|
||||
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 +1293,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 +1348,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);
|
||||
@@ -1449,12 +1373,22 @@ mesh_send_reply(struct mesh_state* m, int rcode, struct reply_info* rep,
|
||||
r->edns.bits &= EDNS_DO;
|
||||
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))
|
||||
@@ -1488,8 +1422,9 @@ mesh_send_reply(struct mesh_state* m, int rcode, struct reply_info* rep,
|
||||
}
|
||||
/* Log reply sent */
|
||||
if(m->s.env->cfg->log_replies) {
|
||||
log_reply_info(NO_VERBOSE, &m->s.qinfo, &r->query_reply.addr,
|
||||
r->query_reply.addrlen, duration, 0, r_buffer);
|
||||
log_reply_info(NO_VERBOSE, &m->s.qinfo,
|
||||
&r->query_reply.client_addr,
|
||||
r->query_reply.client_addrlen, duration, 0, r_buffer);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1502,6 +1437,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);
|
||||
@@ -1521,6 +1457,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
|
||||
@@ -1530,17 +1467,8 @@ void mesh_query_done(struct mesh_state* mstate)
|
||||
respip_inform_print(mstate->s.respip_action_info,
|
||||
r->qname, mstate->s.qinfo.qtype,
|
||||
mstate->s.qinfo.qclass, r->local_alias,
|
||||
&r->query_reply);
|
||||
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)]++;
|
||||
}
|
||||
&r->query_reply.client_addr,
|
||||
r->query_reply.client_addrlen);
|
||||
}
|
||||
|
||||
/* if this query is determined to be dropped during the
|
||||
@@ -1571,6 +1499,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) {
|
||||
@@ -1583,6 +1532,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 */
|
||||
@@ -1609,7 +1559,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);
|
||||
@@ -1633,7 +1583,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;
|
||||
}
|
||||
@@ -1642,7 +1592,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;
|
||||
@@ -1774,7 +1724,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.
|
||||
@@ -1808,7 +1758,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));
|
||||
@@ -1840,9 +1790,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);
|
||||
|
||||
@@ -1852,13 +1814,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;
|
||||
}
|
||||
@@ -1886,7 +1863,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))
|
||||
@@ -1906,14 +1883,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":"",
|
||||
@@ -1922,18 +1899,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,
|
||||
@@ -1942,7 +1919,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",
|
||||
@@ -1952,7 +1929,7 @@ mesh_stats(struct mesh_area* mesh, const char* str)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
void
|
||||
mesh_stats_clear(struct mesh_area* mesh)
|
||||
{
|
||||
if(!mesh)
|
||||
@@ -1966,12 +1943,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;
|
||||
@@ -1985,7 +1963,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)
|
||||
{
|
||||
@@ -2102,6 +2080,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);
|
||||
@@ -2173,6 +2152,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
|
||||
@@ -2180,17 +2160,8 @@ mesh_serve_expired_callback(void* arg)
|
||||
if(actinfo.addrinfo) {
|
||||
respip_inform_print(&actinfo, r->qname,
|
||||
qstate->qinfo.qtype, qstate->qinfo.qclass,
|
||||
r->local_alias, &r->query_reply);
|
||||
|
||||
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)]++;
|
||||
}
|
||||
r->local_alias, &r->query_reply.client_addr,
|
||||
r->query_reply.client_addrlen);
|
||||
}
|
||||
|
||||
/* Add EDE Stale Answer (RCF8914). Ignore global ede as this is
|
||||
@@ -2210,11 +2181,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) {
|
||||
@@ -2225,6 +2208,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 */
|
||||
@@ -2240,3 +2224,10 @@ mesh_serve_expired_callback(void* arg)
|
||||
mesh_do_callback(mstate, LDNS_RCODE_NOERROR, msg->rep, c, &tv);
|
||||
}
|
||||
}
|
||||
|
||||
int mesh_jostle_exceeded(struct mesh_area* mesh)
|
||||
{
|
||||
if(mesh->all.count < mesh->max_reply_states)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
+15
-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.
|
||||
@@ -685,4 +679,15 @@ struct dns_msg*
|
||||
mesh_serve_expired_lookup(struct module_qstate* qstate,
|
||||
struct query_info* lookup_qinfo);
|
||||
|
||||
/**
|
||||
* See if the mesh has space for more queries. You can allocate queries
|
||||
* anyway, but this checks for the allocated space.
|
||||
* @param mesh: mesh area.
|
||||
* @return true if the query list is full.
|
||||
* It checks the number of all queries, not just number of reply states,
|
||||
* that have a client address. So that spawned queries count too,
|
||||
* that were created by the iterator, or other modules.
|
||||
*/
|
||||
int mesh_jostle_exceeded(struct mesh_area* mesh);
|
||||
|
||||
#endif /* SERVICES_MESH_H */
|
||||
|
||||
+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;
|
||||
}
|
||||
}
|
||||
|
||||
+116
-74
@@ -86,10 +86,6 @@ static void serviced_tcp_initiate(struct serviced_query* sq, sldns_buffer* buff)
|
||||
static int randomize_and_send_udp(struct pending* pend, sldns_buffer* packet,
|
||||
int timeout);
|
||||
|
||||
/** remove waiting tcp from the outnet waiting list */
|
||||
static void waiting_list_remove(struct outside_network* outnet,
|
||||
struct waiting_tcp* w);
|
||||
|
||||
/** select a DNS ID for a TCP stream */
|
||||
static uint16_t tcp_select_id(struct outside_network* outnet,
|
||||
struct reuse_tcp* reuse);
|
||||
@@ -372,7 +368,8 @@ log_reuse_tcp(enum verbosity_value v, const char* msg, struct reuse_tcp* reuse)
|
||||
}
|
||||
|
||||
/** pop the first element from the writewait list */
|
||||
static struct waiting_tcp* reuse_write_wait_pop(struct reuse_tcp* reuse)
|
||||
struct waiting_tcp*
|
||||
reuse_write_wait_pop(struct reuse_tcp* reuse)
|
||||
{
|
||||
struct waiting_tcp* w = reuse->write_wait_first;
|
||||
if(!w)
|
||||
@@ -390,8 +387,8 @@ static struct waiting_tcp* reuse_write_wait_pop(struct reuse_tcp* reuse)
|
||||
}
|
||||
|
||||
/** remove the element from the writewait list */
|
||||
static void reuse_write_wait_remove(struct reuse_tcp* reuse,
|
||||
struct waiting_tcp* w)
|
||||
void
|
||||
reuse_write_wait_remove(struct reuse_tcp* reuse, struct waiting_tcp* w)
|
||||
{
|
||||
log_assert(w);
|
||||
log_assert(w->write_wait_queued);
|
||||
@@ -415,8 +412,8 @@ static void reuse_write_wait_remove(struct reuse_tcp* reuse,
|
||||
}
|
||||
|
||||
/** push the element after the last on the writewait list */
|
||||
static void reuse_write_wait_push_back(struct reuse_tcp* reuse,
|
||||
struct waiting_tcp* w)
|
||||
void
|
||||
reuse_write_wait_push_back(struct reuse_tcp* reuse, struct waiting_tcp* w)
|
||||
{
|
||||
if(!w) return;
|
||||
log_assert(!w->write_wait_queued);
|
||||
@@ -427,7 +424,9 @@ static void reuse_write_wait_push_back(struct reuse_tcp* reuse,
|
||||
w->write_wait_prev = reuse->write_wait_last;
|
||||
} else {
|
||||
reuse->write_wait_first = w;
|
||||
w->write_wait_prev = NULL;
|
||||
}
|
||||
w->write_wait_next = NULL;
|
||||
reuse->write_wait_last = w;
|
||||
w->write_wait_queued = 1;
|
||||
}
|
||||
@@ -552,8 +551,27 @@ reuse_tcp_find(struct outside_network* outnet, struct sockaddr_storage* addr,
|
||||
log_assert(&key_p != ((struct reuse_tcp*)result)->pending);
|
||||
}
|
||||
/* not found, return null */
|
||||
|
||||
/* 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);
|
||||
}
|
||||
|
||||
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
|
||||
@@ -621,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);
|
||||
|
||||
@@ -721,12 +748,12 @@ outnet_tcp_take_into_use(struct waiting_tcp* w)
|
||||
pend->next_free = NULL;
|
||||
pend->query = w;
|
||||
pend->reuse.outnet = w->outnet;
|
||||
pend->c->repinfo.addrlen = w->addrlen;
|
||||
pend->c->repinfo.remote_addrlen = w->addrlen;
|
||||
pend->c->tcp_more_read_again = &pend->reuse.cp_more_read_again;
|
||||
pend->c->tcp_more_write_again = &pend->reuse.cp_more_write_again;
|
||||
pend->reuse.cp_more_read_again = 0;
|
||||
pend->reuse.cp_more_write_again = 0;
|
||||
memcpy(&pend->c->repinfo.addr, &w->addr, w->addrlen);
|
||||
memcpy(&pend->c->repinfo.remote_addr, &w->addr, w->addrlen);
|
||||
pend->reuse.pending = pend;
|
||||
|
||||
/* Remove from tree in case the is_ssl will be different and causes the
|
||||
@@ -810,20 +837,50 @@ reuse_tcp_lru_snip(struct outside_network* outnet)
|
||||
return reuse;
|
||||
}
|
||||
|
||||
/** call callback on waiting_tcp, if not NULL */
|
||||
static void
|
||||
waiting_tcp_callback(struct waiting_tcp* w, struct comm_point* c, int error,
|
||||
struct comm_reply* reply_info)
|
||||
/** remove waiting tcp from the outnet waiting list */
|
||||
void
|
||||
outnet_waiting_tcp_list_remove(struct outside_network* outnet, struct waiting_tcp* w)
|
||||
{
|
||||
if(w && w->cb) {
|
||||
fptr_ok(fptr_whitelist_pending_tcp(w->cb));
|
||||
(void)(*w->cb)(c, w->cb_arg, error, reply_info);
|
||||
struct waiting_tcp* p = outnet->tcp_wait_first, *prev = NULL;
|
||||
w->on_tcp_waiting_list = 0;
|
||||
while(p) {
|
||||
if(p == w) {
|
||||
/* remove w */
|
||||
if(prev)
|
||||
prev->next_waiting = w->next_waiting;
|
||||
else outnet->tcp_wait_first = w->next_waiting;
|
||||
if(outnet->tcp_wait_last == w)
|
||||
outnet->tcp_wait_last = prev;
|
||||
w->next_waiting = NULL;
|
||||
return;
|
||||
}
|
||||
prev = p;
|
||||
p = p->next_waiting;
|
||||
}
|
||||
/* outnet_waiting_tcp_list_remove is currently called only with items
|
||||
* that are already in the waiting list. */
|
||||
log_assert(0);
|
||||
}
|
||||
|
||||
/** pop the first waiting tcp from the outnet waiting list */
|
||||
struct waiting_tcp*
|
||||
outnet_waiting_tcp_list_pop(struct outside_network* outnet)
|
||||
{
|
||||
struct waiting_tcp* w = outnet->tcp_wait_first;
|
||||
if(!outnet->tcp_wait_first) return NULL;
|
||||
log_assert(w->on_tcp_waiting_list);
|
||||
outnet->tcp_wait_first = w->next_waiting;
|
||||
if(outnet->tcp_wait_last == w)
|
||||
outnet->tcp_wait_last = NULL;
|
||||
w->on_tcp_waiting_list = 0;
|
||||
w->next_waiting = NULL;
|
||||
return w;
|
||||
}
|
||||
|
||||
/** add waiting_tcp element to the outnet tcp waiting list */
|
||||
static void
|
||||
outnet_add_tcp_waiting(struct outside_network* outnet, struct waiting_tcp* w)
|
||||
void
|
||||
outnet_waiting_tcp_list_add(struct outside_network* outnet,
|
||||
struct waiting_tcp* w, int set_timer)
|
||||
{
|
||||
struct timeval tv;
|
||||
log_assert(!w->on_tcp_waiting_list);
|
||||
@@ -835,16 +892,18 @@ outnet_add_tcp_waiting(struct outside_network* outnet, struct waiting_tcp* w)
|
||||
else outnet->tcp_wait_first = w;
|
||||
outnet->tcp_wait_last = w;
|
||||
w->on_tcp_waiting_list = 1;
|
||||
if(set_timer) {
|
||||
#ifndef S_SPLINT_S
|
||||
tv.tv_sec = w->timeout/1000;
|
||||
tv.tv_usec = (w->timeout%1000)*1000;
|
||||
tv.tv_sec = w->timeout/1000;
|
||||
tv.tv_usec = (w->timeout%1000)*1000;
|
||||
#endif
|
||||
comm_timer_set(w->timer, &tv);
|
||||
comm_timer_set(w->timer, &tv);
|
||||
}
|
||||
}
|
||||
|
||||
/** add waiting_tcp element as first to the outnet tcp waiting list */
|
||||
static void
|
||||
outnet_add_tcp_waiting_first(struct outside_network* outnet,
|
||||
void
|
||||
outnet_waiting_tcp_list_add_first(struct outside_network* outnet,
|
||||
struct waiting_tcp* w, int reset_timer)
|
||||
{
|
||||
struct timeval tv;
|
||||
@@ -869,6 +928,17 @@ outnet_add_tcp_waiting_first(struct outside_network* outnet,
|
||||
(outnet->tcp_reuse_first && outnet->tcp_reuse_last));
|
||||
}
|
||||
|
||||
/** call callback on waiting_tcp, if not NULL */
|
||||
static void
|
||||
waiting_tcp_callback(struct waiting_tcp* w, struct comm_point* c, int error,
|
||||
struct comm_reply* reply_info)
|
||||
{
|
||||
if(w && w->cb) {
|
||||
fptr_ok(fptr_whitelist_pending_tcp(w->cb));
|
||||
(void)(*w->cb)(c, w->cb_arg, error, reply_info);
|
||||
}
|
||||
}
|
||||
|
||||
/** see if buffers can be used to service TCP queries */
|
||||
static void
|
||||
use_free_buffer(struct outside_network* outnet)
|
||||
@@ -879,15 +949,10 @@ use_free_buffer(struct outside_network* outnet)
|
||||
struct pending_tcp* pend_tcp = NULL;
|
||||
#endif
|
||||
struct reuse_tcp* reuse = NULL;
|
||||
w = outnet->tcp_wait_first;
|
||||
log_assert(w->on_tcp_waiting_list);
|
||||
outnet->tcp_wait_first = w->next_waiting;
|
||||
if(outnet->tcp_wait_last == w)
|
||||
outnet->tcp_wait_last = NULL;
|
||||
w = outnet_waiting_tcp_list_pop(outnet);
|
||||
log_assert(
|
||||
(!outnet->tcp_reuse_first && !outnet->tcp_reuse_last) ||
|
||||
(outnet->tcp_reuse_first && outnet->tcp_reuse_last));
|
||||
w->on_tcp_waiting_list = 0;
|
||||
reuse = reuse_tcp_find(outnet, &w->addr, w->addrlen,
|
||||
w->ssl_upstream);
|
||||
/* re-select an ID when moving to a new TCP buffer */
|
||||
@@ -934,7 +999,7 @@ use_free_buffer(struct outside_network* outnet)
|
||||
#endif
|
||||
} else {
|
||||
/* no reuse and no free buffer, put back at the start */
|
||||
outnet_add_tcp_waiting_first(outnet, w, 0);
|
||||
outnet_waiting_tcp_list_add_first(outnet, w, 0);
|
||||
break;
|
||||
}
|
||||
#ifdef USE_DNSTAP
|
||||
@@ -1008,7 +1073,7 @@ reuse_move_writewait_away(struct outside_network* outnet,
|
||||
* fail the query */
|
||||
w->error_count ++;
|
||||
reuse_tree_by_id_delete(&pend->reuse, w);
|
||||
outnet_add_tcp_waiting(outnet, w);
|
||||
outnet_waiting_tcp_list_add(outnet, w, 1);
|
||||
}
|
||||
while((w = reuse_write_wait_pop(&pend->reuse)) != NULL) {
|
||||
if(verbosity >= VERB_CLIENT && w->pkt_len > 12+2+2 &&
|
||||
@@ -1019,7 +1084,7 @@ reuse_move_writewait_away(struct outside_network* outnet,
|
||||
verbose(VERB_CLIENT, "reuse_move_writewait_away item %s", buf);
|
||||
}
|
||||
reuse_tree_by_id_delete(&pend->reuse, w);
|
||||
outnet_add_tcp_waiting(outnet, w);
|
||||
outnet_waiting_tcp_list_add(outnet, w, 1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1417,11 +1482,11 @@ outnet_udp_cb(struct comm_point* c, void* arg, int error,
|
||||
|
||||
/* setup lookup key */
|
||||
key.id = (unsigned)LDNS_ID_WIRE(sldns_buffer_begin(c->buffer));
|
||||
memcpy(&key.addr, &reply_info->addr, reply_info->addrlen);
|
||||
key.addrlen = reply_info->addrlen;
|
||||
memcpy(&key.addr, &reply_info->remote_addr, reply_info->remote_addrlen);
|
||||
key.addrlen = reply_info->remote_addrlen;
|
||||
verbose(VERB_ALGO, "Incoming reply id = %4.4x", key.id);
|
||||
log_addr(VERB_ALGO, "Incoming reply addr =",
|
||||
&reply_info->addr, reply_info->addrlen);
|
||||
&reply_info->remote_addr, reply_info->remote_addrlen);
|
||||
|
||||
/* find it, see if this thing is a valid query response */
|
||||
verbose(VERB_ALGO, "lookup size is %d entries", (int)outnet->pending->count);
|
||||
@@ -1690,7 +1755,7 @@ outside_network_create(struct comm_base *base, size_t bufsize,
|
||||
return NULL;
|
||||
}
|
||||
pc->cp = comm_point_create_udp(outnet->base, -1,
|
||||
outnet->udp_buff, outnet_udp_cb, outnet, NULL);
|
||||
outnet->udp_buff, 0, outnet_udp_cb, outnet, NULL);
|
||||
if(!pc->cp) {
|
||||
log_err("malloc failed");
|
||||
free(pc);
|
||||
@@ -2237,7 +2302,7 @@ outnet_tcptimer(void* arg)
|
||||
verbose(VERB_CLIENT, "outnet_tcptimer");
|
||||
if(w->on_tcp_waiting_list) {
|
||||
/* it is on the waiting list */
|
||||
waiting_list_remove(outnet, w);
|
||||
outnet_waiting_tcp_list_remove(outnet, w);
|
||||
waiting_tcp_callback(w, NULL, NETEVENT_TIMEOUT, NULL);
|
||||
waiting_tcp_delete(w);
|
||||
} else {
|
||||
@@ -2464,7 +2529,7 @@ pending_tcp_query(struct serviced_query* sq, sldns_buffer* packet,
|
||||
#ifdef USE_DNSTAP
|
||||
w->sq = sq;
|
||||
#endif
|
||||
outnet_add_tcp_waiting(sq->outnet, w);
|
||||
outnet_waiting_tcp_list_add(sq->outnet, w, 1);
|
||||
}
|
||||
return w;
|
||||
}
|
||||
@@ -2545,8 +2610,10 @@ serviced_create(struct outside_network* outnet, sldns_buffer* buff, int dnssec,
|
||||
#ifdef UNBOUND_DEBUG
|
||||
rbnode_type* ins;
|
||||
#endif
|
||||
if(!sq)
|
||||
if(!sq) {
|
||||
alloc_reg_release(alloc, region);
|
||||
return NULL;
|
||||
}
|
||||
sq->node.key = sq;
|
||||
sq->alloc = alloc;
|
||||
sq->region = region;
|
||||
@@ -2610,30 +2677,6 @@ serviced_create(struct outside_network* outnet, sldns_buffer* buff, int dnssec,
|
||||
return sq;
|
||||
}
|
||||
|
||||
/** remove waiting tcp from the outnet waiting list */
|
||||
static void
|
||||
waiting_list_remove(struct outside_network* outnet, struct waiting_tcp* w)
|
||||
{
|
||||
struct waiting_tcp* p = outnet->tcp_wait_first, *prev = NULL;
|
||||
w->on_tcp_waiting_list = 0;
|
||||
while(p) {
|
||||
if(p == w) {
|
||||
/* remove w */
|
||||
if(prev)
|
||||
prev->next_waiting = w->next_waiting;
|
||||
else outnet->tcp_wait_first = w->next_waiting;
|
||||
if(outnet->tcp_wait_last == w)
|
||||
outnet->tcp_wait_last = prev;
|
||||
return;
|
||||
}
|
||||
prev = p;
|
||||
p = p->next_waiting;
|
||||
}
|
||||
/* waiting_list_remove is currently called only with items that are
|
||||
* already in the waiting list. */
|
||||
log_assert(0);
|
||||
}
|
||||
|
||||
/** reuse tcp stream, remove serviced query from stream,
|
||||
* return true if the stream is kept, false if it is to be closed */
|
||||
static int
|
||||
@@ -2728,7 +2771,7 @@ serviced_delete(struct serviced_query* sq)
|
||||
sq->pending = NULL;
|
||||
} else {
|
||||
verbose(VERB_CLIENT, "serviced_delete: tcpwait");
|
||||
waiting_list_remove(sq->outnet, w);
|
||||
outnet_waiting_tcp_list_remove(sq->outnet, w);
|
||||
if(!w->in_cb_and_decommission)
|
||||
waiting_tcp_delete(w);
|
||||
}
|
||||
@@ -3101,8 +3144,8 @@ serviced_tcp_callback(struct comm_point* c, void* arg, int error,
|
||||
rep = &r2;
|
||||
r2.c = c;
|
||||
}
|
||||
memcpy(&rep->addr, &sq->addr, sq->addrlen);
|
||||
rep->addrlen = sq->addrlen;
|
||||
memcpy(&rep->remote_addr, &sq->addr, sq->addrlen);
|
||||
rep->remote_addrlen = sq->addrlen;
|
||||
serviced_callbacks(sq, error, c, rep);
|
||||
return 0;
|
||||
}
|
||||
@@ -3432,7 +3475,6 @@ outnet_serviced_query(struct outside_network* outnet,
|
||||
infra_ratelimit_dec(env->infra_cache,
|
||||
zone, zonelen, timenow);
|
||||
}
|
||||
alloc_reg_release(env->alloc, region);
|
||||
return NULL;
|
||||
}
|
||||
if(!(cb = (struct service_callback*)regional_alloc(
|
||||
@@ -3581,7 +3623,7 @@ outnet_comm_point_for_udp(struct outside_network* outnet,
|
||||
if(fd == -1) {
|
||||
return NULL;
|
||||
}
|
||||
cp = comm_point_create_udp(outnet->base, fd, outnet->udp_buff,
|
||||
cp = comm_point_create_udp(outnet->base, fd, outnet->udp_buff, 0,
|
||||
cb, cb_arg, NULL);
|
||||
if(!cp) {
|
||||
log_err("malloc failure");
|
||||
@@ -3669,8 +3711,8 @@ outnet_comm_point_for_tcp(struct outside_network* outnet,
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
cp->repinfo.addrlen = to_addrlen;
|
||||
memcpy(&cp->repinfo.addr, to_addr, to_addrlen);
|
||||
cp->repinfo.remote_addrlen = to_addrlen;
|
||||
memcpy(&cp->repinfo.remote_addr, to_addr, to_addrlen);
|
||||
|
||||
/* setup for SSL (if needed) */
|
||||
if(ssl) {
|
||||
@@ -3745,8 +3787,8 @@ outnet_comm_point_for_http(struct outside_network* outnet,
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
cp->repinfo.addrlen = to_addrlen;
|
||||
memcpy(&cp->repinfo.addr, to_addr, to_addrlen);
|
||||
cp->repinfo.remote_addrlen = to_addrlen;
|
||||
memcpy(&cp->repinfo.remote_addr, to_addr, to_addrlen);
|
||||
|
||||
/* setup for SSL (if needed) */
|
||||
if(ssl) {
|
||||
|
||||
@@ -718,6 +718,30 @@ struct reuse_tcp* reuse_tcp_lru_snip(struct outside_network* outnet);
|
||||
/** delete readwait waiting_tcp elements, deletes the elements in the list */
|
||||
void reuse_del_readwait(rbtree_type* tree_by_id);
|
||||
|
||||
/** remove waiting tcp from the outnet waiting list */
|
||||
void outnet_waiting_tcp_list_remove(struct outside_network* outnet,
|
||||
struct waiting_tcp* w);
|
||||
|
||||
/** pop the first waiting tcp from the outnet waiting list */
|
||||
struct waiting_tcp* outnet_waiting_tcp_list_pop(struct outside_network* outnet);
|
||||
|
||||
/** add waiting_tcp element to the outnet tcp waiting list */
|
||||
void outnet_waiting_tcp_list_add(struct outside_network* outnet,
|
||||
struct waiting_tcp* w, int set_timer);
|
||||
|
||||
/** add waiting_tcp element as first to the outnet tcp waiting list */
|
||||
void outnet_waiting_tcp_list_add_first(struct outside_network* outnet,
|
||||
struct waiting_tcp* w, int reset_timer);
|
||||
|
||||
/** pop the first element from the writewait list */
|
||||
struct waiting_tcp* reuse_write_wait_pop(struct reuse_tcp* reuse);
|
||||
|
||||
/** remove the element from the writewait list */
|
||||
void reuse_write_wait_remove(struct reuse_tcp* reuse, struct waiting_tcp* w);
|
||||
|
||||
/** push the element after the last on the writewait list */
|
||||
void reuse_write_wait_push_back(struct reuse_tcp* reuse, struct waiting_tcp* w);
|
||||
|
||||
/** get TCP file descriptor for address, returns -1 on failure,
|
||||
* tcp_mss is 0 or maxseg size to set for TCP packets. */
|
||||
int outnet_get_tcp_fd(struct sockaddr_storage* addr, socklen_t addrlen,
|
||||
|
||||
+216
-42
@@ -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);
|
||||
}
|
||||
|
||||
@@ -1392,11 +1576,13 @@ log_rpz_apply(char* trigger, uint8_t* dname, struct addr_tree_node* addrnode,
|
||||
dnamestr[0]=0;
|
||||
}
|
||||
if(repinfo) {
|
||||
addr_to_str(&repinfo->addr, repinfo->addrlen, ip, sizeof(ip));
|
||||
port = ntohs(((struct sockaddr_in*)&repinfo->addr)->sin_port);
|
||||
addr_to_str(&repinfo->client_addr, repinfo->client_addrlen, ip, sizeof(ip));
|
||||
port = ntohs(((struct sockaddr_in*)&repinfo->client_addr)->sin_port);
|
||||
} else if(ms && ms->mesh_info && ms->mesh_info->reply_list) {
|
||||
addr_to_str(&ms->mesh_info->reply_list->query_reply.addr, ms->mesh_info->reply_list->query_reply.addrlen, ip, sizeof(ip));
|
||||
port = ntohs(((struct sockaddr_in*)&ms->mesh_info->reply_list->query_reply.addr)->sin_port);
|
||||
addr_to_str(&ms->mesh_info->reply_list->query_reply.client_addr,
|
||||
ms->mesh_info->reply_list->query_reply.client_addrlen,
|
||||
ip, sizeof(ip));
|
||||
port = ntohs(((struct sockaddr_in*)&ms->mesh_info->reply_list->query_reply.client_addr)->sin_port);
|
||||
} else {
|
||||
ip[0]=0;
|
||||
port = 0;
|
||||
@@ -1468,7 +1654,9 @@ rpz_resolve_client_action_and_zone(struct auth_zones* az, struct query_info* qin
|
||||
}
|
||||
z = rpz_find_zone(r->local_zones, qinfo->qname, qinfo->qname_len,
|
||||
qinfo->qclass, 0, 0, 0);
|
||||
node = rpz_ipbased_trigger_lookup(r->client_set, &repinfo->addr, repinfo->addrlen, "clientip");
|
||||
node = rpz_ipbased_trigger_lookup(r->client_set,
|
||||
&repinfo->client_addr, repinfo->client_addrlen,
|
||||
"clientip");
|
||||
if((z || node) && r->action_override == RPZ_DISABLED_ACTION) {
|
||||
if(r->log)
|
||||
log_rpz_apply((node?"clientip":"qname"),
|
||||
@@ -1559,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,
|
||||
@@ -1709,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))
|
||||
@@ -1738,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))
|
||||
@@ -1768,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;
|
||||
@@ -2164,18 +2340,16 @@ rpz_callback_from_iterator_module(struct module_qstate* ms, struct iter_qstate*
|
||||
|
||||
lock_rw_unlock(&az->rpz_lock);
|
||||
|
||||
if(raddr == NULL && z == NULL) { return NULL; }
|
||||
else if(raddr != NULL) {
|
||||
if(raddr == NULL && z == NULL)
|
||||
return NULL;
|
||||
|
||||
if(raddr != NULL) {
|
||||
if(z) {
|
||||
lock_rw_unlock(&z->lock);
|
||||
}
|
||||
return rpz_apply_nsip_trigger(ms, r, raddr, a);
|
||||
} else if(z != NULL) {
|
||||
if(raddr) {
|
||||
lock_rw_unlock(&raddr->lock);
|
||||
}
|
||||
return rpz_apply_nsdname_trigger(ms, r, z, &match, a);
|
||||
} else { return NULL; }
|
||||
}
|
||||
return rpz_apply_nsdname_trigger(ms, r, z, &match, a);
|
||||
}
|
||||
|
||||
struct dns_msg* rpz_callback_from_iterator_cname(struct module_qstate* ms,
|
||||
|
||||
+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.
|
||||
|
||||
+3
-2
@@ -66,8 +66,9 @@ views_create(void)
|
||||
return v;
|
||||
}
|
||||
|
||||
/** This prototype is defined in in respip.h, but we want to avoid
|
||||
* unnecessary dependencies */
|
||||
/* \noop (ignore this comment for doxygen)
|
||||
* This prototype is defined in in respip.h, but we want to avoid
|
||||
* unnecessary dependencies */
|
||||
void respip_set_delete(struct respip_set *set);
|
||||
|
||||
void
|
||||
|
||||
+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.
|
||||
*
|
||||
|
||||
+64
-30
@@ -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 */
|
||||
|
||||
+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
|
||||
|
||||
+11
-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" },
|
||||
@@ -224,7 +224,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 +487,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 +1119,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 +1139,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 +1162,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 +1174,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 +1202,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 +1225,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 +1554,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;
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -316,7 +316,7 @@ warn_hosts(const char* typ, struct config_stub* list)
|
||||
struct config_strlist* h;
|
||||
for(s=list; s; s=s->next) {
|
||||
for(h=s->hosts; h; h=h->next) {
|
||||
if(extstrtoaddr(h->str, &a, &alen)) {
|
||||
if(extstrtoaddr(h->str, &a, &alen, UNBOUND_DNS_PORT)) {
|
||||
fprintf(stderr, "unbound-checkconf: warning:"
|
||||
" %s %s: \"%s\" is an IP%s address, "
|
||||
"and when looked up as a host name "
|
||||
@@ -338,6 +338,8 @@ interfacechecks(struct config_file* cfg)
|
||||
int i, j, i2, j2;
|
||||
char*** resif = NULL;
|
||||
int* num_resif = NULL;
|
||||
char portbuf[32];
|
||||
snprintf(portbuf, sizeof(portbuf), "%d", cfg->port);
|
||||
|
||||
if(cfg->num_ifs != 0) {
|
||||
resif = (char***)calloc(cfg->num_ifs, sizeof(char**));
|
||||
@@ -359,9 +361,21 @@ interfacechecks(struct config_file* cfg)
|
||||
fatal_exit("could not resolve interface names, for %s",
|
||||
cfg->ifs[i]);
|
||||
}
|
||||
/* check for port combinations that are not supported */
|
||||
if(if_is_pp2(resif[i][0], portbuf, cfg->proxy_protocol_port)) {
|
||||
if(if_is_dnscrypt(resif[i][0], portbuf,
|
||||
cfg->dnscrypt_port)) {
|
||||
fatal_exit("PROXYv2 and DNSCrypt combination not "
|
||||
"supported!");
|
||||
} else if(if_is_https(resif[i][0], portbuf,
|
||||
cfg->https_port)) {
|
||||
fatal_exit("PROXYv2 and DoH combination not "
|
||||
"supported!");
|
||||
}
|
||||
}
|
||||
/* search for duplicates in the returned addresses */
|
||||
for(j=0; j<num_resif[i]; j++) {
|
||||
if(!extstrtoaddr(resif[i][j], &a, &alen)) {
|
||||
if(!extstrtoaddr(resif[i][j], &a, &alen, cfg->port)) {
|
||||
if(strcmp(cfg->ifs[i], resif[i][j]) != 0)
|
||||
fatal_exit("cannot parse interface address '%s' from the interface specified as '%s'",
|
||||
resif[i][j], cfg->ifs[i]);
|
||||
@@ -700,7 +714,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;
|
||||
|
||||
|
||||
+32
-38
@@ -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 */
|
||||
@@ -601,7 +595,7 @@ contact_server(const char* svr, struct config_file* cfg, int statuscmd)
|
||||
struct sockaddr_storage addr2;
|
||||
socklen_t addrlen2;
|
||||
if(extstrtoaddr(cfg->control_ifs.first->str, &addr2,
|
||||
&addrlen2)) {
|
||||
&addrlen2, UNBOUND_DNS_PORT)) {
|
||||
svr = cfg->control_ifs.first->str;
|
||||
} else {
|
||||
if(!resolve_interface_names(NULL, 0,
|
||||
@@ -629,7 +623,7 @@ contact_server(const char* svr, struct config_file* cfg, int statuscmd)
|
||||
svr = "::1";
|
||||
}
|
||||
if(strchr(svr, '@')) {
|
||||
if(!extstrtoaddr(svr, &addr, &addrlen))
|
||||
if(!extstrtoaddr(svr, &addr, &addrlen, UNBOUND_DNS_PORT))
|
||||
fatal_exit("could not parse IP@port: %s", svr);
|
||||
#ifdef HAVE_SYS_UN_H
|
||||
} else if(svr[0] == '/') {
|
||||
@@ -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
|
||||
|
||||
+1
-1
@@ -974,7 +974,7 @@ service(const char* bind_str, int bindport, const char* serv_str,
|
||||
dl_tv_add(&reuse, &delay);
|
||||
if(reuse.tv_sec == 0)
|
||||
reuse.tv_sec = 1;
|
||||
if(!extstrtoaddr(serv_str, &srv_addr, &srv_len)) {
|
||||
if(!extstrtoaddr(serv_str, &srv_addr, &srv_len, UNBOUND_DNS_PORT)) {
|
||||
printf("cannot parse forward address: %s\n", serv_str);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ NEED_WHOAMI='07-confroot.tdir'
|
||||
NEED_IPV6='fwd_ancil.tdir fwd_tcp_tc6.tdir stub_udp6.tdir edns_cache.tdir'
|
||||
NEED_NOMINGW='tcp_sigpipe.tdir 07-confroot.tdir 08-host-lib.tdir fwd_ancil.tdir'
|
||||
NEED_DNSCRYPT_PROXY='dnscrypt_queries.tdir dnscrypt_queries_chacha.tdir'
|
||||
NEED_UNSHARE='acl_interface.tdir proxy_protocol.tdir'
|
||||
|
||||
# test if dig and ldns-testns are available.
|
||||
test_tool_avail "dig"
|
||||
@@ -50,6 +51,7 @@ for test in `ls -d *.tdir`; do
|
||||
skip_if_in_list $test "$NEED_NC" "nc"
|
||||
skip_if_in_list $test "$NEED_WHOAMI" "whoami"
|
||||
skip_if_in_list $test "$NEED_DNSCRYPT_PROXY" "dnscrypt-proxy"
|
||||
skip_if_in_list $test "$NEED_UNSHARE" "unshare"
|
||||
|
||||
if echo $NEED_IPV6 | grep $test >/dev/null; then
|
||||
if test "$HAVE_IPV6" = no; then
|
||||
|
||||
@@ -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 */
|
||||
@@ -573,6 +580,7 @@ int main(int argc, char** argv)
|
||||
#endif
|
||||
checklock_start();
|
||||
log_init(0, 0, 0);
|
||||
log_ident_set("dohclient");
|
||||
|
||||
h2_session = http2_session_create();
|
||||
if(!h2_session) fatal_exit("out of memory");
|
||||
|
||||
+92
-100
@@ -2,24 +2,24 @@
|
||||
* testcode/fake_event.c - fake event handling that replays existing scenario.
|
||||
*
|
||||
* 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
|
||||
@@ -65,6 +65,7 @@
|
||||
#include "sldns/wire2str.h"
|
||||
#include "sldns/str2wire.h"
|
||||
#include "daemon/remote.h"
|
||||
#include "util/timeval_func.h"
|
||||
#include <signal.h>
|
||||
struct worker;
|
||||
struct daemon_remote;
|
||||
@@ -95,21 +96,7 @@ struct fake_commpoint {
|
||||
/** Global variable: the scenario. Saved here for when event_init is done. */
|
||||
static struct replay_scenario* saved_scenario = NULL;
|
||||
|
||||
/** 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
|
||||
}
|
||||
|
||||
void
|
||||
void
|
||||
fake_temp_file(const char* adj, const char* id, char* buf, size_t len)
|
||||
{
|
||||
#ifdef USE_WINSOCK
|
||||
@@ -121,13 +108,13 @@ fake_temp_file(const char* adj, const char* id, char* buf, size_t len)
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
void
|
||||
fake_event_init(struct replay_scenario* scen)
|
||||
{
|
||||
saved_scenario = scen;
|
||||
}
|
||||
|
||||
void
|
||||
void
|
||||
fake_event_cleanup(void)
|
||||
{
|
||||
replay_scenario_delete(saved_scenario);
|
||||
@@ -172,7 +159,7 @@ repevt_string(enum replay_event_type t)
|
||||
}
|
||||
|
||||
/** delete a fake pending */
|
||||
static void
|
||||
static void
|
||||
delete_fake_pending(struct fake_pending* pend)
|
||||
{
|
||||
if(!pend)
|
||||
@@ -200,8 +187,8 @@ delete_replay_answer(struct replay_answer* a)
|
||||
/**
|
||||
* return: true if pending query matches the now event.
|
||||
*/
|
||||
static int
|
||||
pending_matches_current(struct replay_runtime* runtime,
|
||||
static int
|
||||
pending_matches_current(struct replay_runtime* runtime,
|
||||
struct entry** entry, struct fake_pending **pend)
|
||||
{
|
||||
struct fake_pending* p;
|
||||
@@ -233,7 +220,7 @@ pending_matches_current(struct replay_runtime* runtime,
|
||||
* @return: true if a match is found.
|
||||
*/
|
||||
static int
|
||||
pending_find_match(struct replay_runtime* runtime, struct entry** entry,
|
||||
pending_find_match(struct replay_runtime* runtime, struct entry** entry,
|
||||
struct fake_pending* pend)
|
||||
{
|
||||
int timenow = runtime->now->time_step;
|
||||
@@ -245,7 +232,7 @@ pending_find_match(struct replay_runtime* runtime, struct entry** entry,
|
||||
(*entry = find_match(p->match, pend->pkt, pend->pkt_len,
|
||||
pend->transport))) {
|
||||
log_info("matched query time %d in range [%d, %d] "
|
||||
"with entry line %d", timenow,
|
||||
"with entry line %d", timenow,
|
||||
p->start_step, p->end_step, (*entry)->lineno);
|
||||
if(p->addrlen != 0)
|
||||
log_addr(0, "matched ip", &p->addr, p->addrlen);
|
||||
@@ -266,8 +253,8 @@ pending_find_match(struct replay_runtime* runtime, struct entry** entry,
|
||||
* @param pend: if true, the outgoing message that matches is returned.
|
||||
* @return: true if pending query matches the now event.
|
||||
*/
|
||||
static int
|
||||
pending_matches_range(struct replay_runtime* runtime,
|
||||
static int
|
||||
pending_matches_range(struct replay_runtime* runtime,
|
||||
struct entry** entry, struct fake_pending** pend)
|
||||
{
|
||||
struct fake_pending* p = runtime->pending_list;
|
||||
@@ -384,8 +371,8 @@ answer_callback_from_entry(struct replay_runtime* runtime,
|
||||
fill_buffer_with_reply(c.buffer, entry, pend->pkt, pend->pkt_len,
|
||||
pend->tcp_pkt_counter);
|
||||
repinfo.c = &c;
|
||||
repinfo.addrlen = pend->addrlen;
|
||||
memcpy(&repinfo.addr, &pend->addr, pend->addrlen);
|
||||
repinfo.remote_addrlen = pend->addrlen;
|
||||
memcpy(&repinfo.remote_addr, &pend->addr, pend->addrlen);
|
||||
if(!pend->serviced) {
|
||||
if(entry && entry->reply_list->next &&
|
||||
pend->tcp_pkt_counter < count_reply_packets(entry)) {
|
||||
@@ -405,9 +392,9 @@ answer_callback_from_entry(struct replay_runtime* runtime,
|
||||
static void
|
||||
answer_check_it(struct replay_runtime* runtime)
|
||||
{
|
||||
struct replay_answer* ans = runtime->answer_list,
|
||||
struct replay_answer* ans = runtime->answer_list,
|
||||
*prev = NULL;
|
||||
log_assert(runtime && runtime->now &&
|
||||
log_assert(runtime && runtime->now &&
|
||||
runtime->now->evt_type == repevt_front_reply);
|
||||
while(ans) {
|
||||
enum transport_type tr = transport_tcp;
|
||||
@@ -415,12 +402,12 @@ answer_check_it(struct replay_runtime* runtime)
|
||||
tr = transport_udp;
|
||||
if((runtime->now->addrlen == 0 || sockaddr_cmp(
|
||||
&runtime->now->addr, runtime->now->addrlen,
|
||||
&ans->repinfo.addr, ans->repinfo.addrlen) == 0) &&
|
||||
&ans->repinfo.remote_addr, ans->repinfo.remote_addrlen) == 0) &&
|
||||
find_match(runtime->now->match, ans->pkt,
|
||||
ans->pkt_len, tr)) {
|
||||
log_info("testbound matched event entry from line %d",
|
||||
runtime->now->match->lineno);
|
||||
log_info("testbound: do STEP %d %s",
|
||||
log_info("testbound: do STEP %d %s",
|
||||
runtime->now->time_step,
|
||||
repevt_string(runtime->now->evt_type));
|
||||
if(prev)
|
||||
@@ -453,10 +440,12 @@ fake_front_query(struct replay_runtime* runtime, struct replay_moment *todo)
|
||||
repinfo.c = (struct comm_point*)calloc(1, sizeof(struct comm_point));
|
||||
if(!repinfo.c)
|
||||
fatal_exit("out of memory in fake_front_query");
|
||||
repinfo.addrlen = (socklen_t)sizeof(struct sockaddr_in);
|
||||
repinfo.remote_addrlen = (socklen_t)sizeof(struct sockaddr_in);
|
||||
if(todo->addrlen != 0) {
|
||||
repinfo.addrlen = todo->addrlen;
|
||||
memcpy(&repinfo.addr, &todo->addr, todo->addrlen);
|
||||
repinfo.remote_addrlen = todo->addrlen;
|
||||
memcpy(&repinfo.remote_addr, &todo->addr, todo->addrlen);
|
||||
repinfo.client_addrlen = todo->addrlen;
|
||||
memcpy(&repinfo.client_addr, &todo->addr, todo->addrlen);
|
||||
}
|
||||
repinfo.c->fd = -1;
|
||||
repinfo.c->ev = (struct internal_event*)runtime;
|
||||
@@ -472,7 +461,7 @@ fake_front_query(struct replay_runtime* runtime, struct replay_moment *todo)
|
||||
log_pkt("query pkt", todo->match->reply_list->reply_pkt,
|
||||
todo->match->reply_list->reply_len);
|
||||
/* call the callback for incoming queries */
|
||||
if((*runtime->callback_query)(repinfo.c, runtime->cb_arg,
|
||||
if((*runtime->callback_query)(repinfo.c, runtime->cb_arg,
|
||||
NETEVENT_NOERROR, &repinfo)) {
|
||||
/* send immediate reply */
|
||||
comm_point_send_reply(&repinfo);
|
||||
@@ -485,7 +474,7 @@ fake_front_query(struct replay_runtime* runtime, struct replay_moment *todo)
|
||||
* Perform callback for fake pending message.
|
||||
*/
|
||||
static void
|
||||
fake_pending_callback(struct replay_runtime* runtime,
|
||||
fake_pending_callback(struct replay_runtime* runtime,
|
||||
struct replay_moment* todo, int error)
|
||||
{
|
||||
struct fake_pending* p = runtime->pending_list;
|
||||
@@ -510,8 +499,8 @@ fake_pending_callback(struct replay_runtime* runtime,
|
||||
p->pkt_len, p->tcp_pkt_counter);
|
||||
}
|
||||
repinfo.c = &c;
|
||||
repinfo.addrlen = p->addrlen;
|
||||
memcpy(&repinfo.addr, &p->addr, p->addrlen);
|
||||
repinfo.remote_addrlen = p->addrlen;
|
||||
memcpy(&repinfo.remote_addr, &p->addr, p->addrlen);
|
||||
if(!p->serviced) {
|
||||
if(todo->match && todo->match->reply_list->next && !error &&
|
||||
p->tcp_pkt_counter < count_reply_packets(todo->match)) {
|
||||
@@ -564,7 +553,7 @@ time_passes(struct replay_runtime* runtime, struct replay_moment* mom)
|
||||
timeval_add(&runtime->now_tv, &tv);
|
||||
runtime->now_secs = (time_t)runtime->now_tv.tv_sec;
|
||||
#ifndef S_SPLINT_S
|
||||
log_info("elapsed %d.%6.6d now %d.%6.6d",
|
||||
log_info("elapsed %d.%6.6d now %d.%6.6d",
|
||||
(int)tv.tv_sec, (int)tv.tv_usec,
|
||||
(int)runtime->now_tv.tv_sec, (int)runtime->now_tv.tv_usec);
|
||||
#endif
|
||||
@@ -601,7 +590,7 @@ autotrust_check(struct replay_runtime* runtime, struct replay_moment* mom)
|
||||
}
|
||||
strip_end_white(line);
|
||||
expanded = macro_process(runtime->vars, runtime, p->str);
|
||||
if(!expanded)
|
||||
if(!expanded)
|
||||
fatal_exit("could not expand macro line %d", lineno);
|
||||
if(verbosity >= 7 && strcmp(p->str, expanded) != 0)
|
||||
log_info("expanded '%s' to '%s'", p->str, expanded);
|
||||
@@ -654,7 +643,7 @@ tempfile_check(struct replay_runtime* runtime, struct replay_moment* mom)
|
||||
}
|
||||
strip_end_white(line);
|
||||
expanded = macro_process(runtime->vars, runtime, p->str);
|
||||
if(!expanded)
|
||||
if(!expanded)
|
||||
fatal_exit("could not expand macro line %d", lineno);
|
||||
if(verbosity >= 7 && strcmp(p->str, expanded) != 0)
|
||||
log_info("expanded '%s' to '%s'", p->str, expanded);
|
||||
@@ -744,7 +733,7 @@ do_moment_and_advance(struct replay_runtime* runtime)
|
||||
advance_moment(runtime);
|
||||
return;
|
||||
}
|
||||
log_info("testbound: do STEP %d %s", runtime->now->time_step,
|
||||
log_info("testbound: do STEP %d %s", runtime->now->time_step,
|
||||
repevt_string(runtime->now->evt_type));
|
||||
switch(runtime->now->evt_type) {
|
||||
case repevt_nothing:
|
||||
@@ -759,7 +748,7 @@ do_moment_and_advance(struct replay_runtime* runtime)
|
||||
fake_front_query(runtime, mom);
|
||||
break;
|
||||
case repevt_front_reply:
|
||||
if(runtime->answer_list)
|
||||
if(runtime->answer_list)
|
||||
log_err("testbound: There are unmatched answers.");
|
||||
fatal_exit("testbound: query answer not matched");
|
||||
break;
|
||||
@@ -808,7 +797,7 @@ do_moment_and_advance(struct replay_runtime* runtime)
|
||||
advance_moment(runtime);
|
||||
break;
|
||||
default:
|
||||
fatal_exit("testbound: unknown event type %d",
|
||||
fatal_exit("testbound: unknown event type %d",
|
||||
runtime->now->evt_type);
|
||||
}
|
||||
}
|
||||
@@ -829,15 +818,15 @@ run_scenario(struct replay_runtime* runtime)
|
||||
/* else if precoded_range matches pending, do it */
|
||||
/* else do the current moment */
|
||||
if(pending_matches_current(runtime, &entry, &pending)) {
|
||||
log_info("testbound: do STEP %d CHECK_OUT_QUERY",
|
||||
log_info("testbound: do STEP %d CHECK_OUT_QUERY",
|
||||
runtime->now->time_step);
|
||||
advance_moment(runtime);
|
||||
if(entry->copy_id)
|
||||
answer_callback_from_entry(runtime, entry,
|
||||
answer_callback_from_entry(runtime, entry,
|
||||
pending);
|
||||
} else if(runtime->answer_list && runtime->now &&
|
||||
} else if(runtime->answer_list && runtime->now &&
|
||||
runtime->now->evt_type == repevt_front_reply) {
|
||||
answer_check_it(runtime);
|
||||
answer_check_it(runtime);
|
||||
advance_moment(runtime);
|
||||
} else if(pending_matches_range(runtime, &entry, &pending)) {
|
||||
answer_callback_from_entry(runtime, entry, pending);
|
||||
@@ -868,7 +857,7 @@ run_scenario(struct replay_runtime* runtime)
|
||||
|
||||
/*********** Dummy routines ***********/
|
||||
|
||||
struct listen_dnsport*
|
||||
struct listen_dnsport*
|
||||
listen_create(struct comm_base* base, struct listen_port* ATTR_UNUSED(ports),
|
||||
size_t bufsize, int ATTR_UNUSED(tcp_accept_count),
|
||||
int ATTR_UNUSED(tcp_idle_timeout),
|
||||
@@ -896,7 +885,7 @@ listen_create(struct comm_base* base, struct listen_port* ATTR_UNUSED(ports),
|
||||
return l;
|
||||
}
|
||||
|
||||
void
|
||||
void
|
||||
listen_delete(struct listen_dnsport* listen)
|
||||
{
|
||||
if(!listen)
|
||||
@@ -905,7 +894,7 @@ listen_delete(struct listen_dnsport* listen)
|
||||
free(listen);
|
||||
}
|
||||
|
||||
struct comm_base*
|
||||
struct comm_base*
|
||||
comm_base_create(int ATTR_UNUSED(sigs))
|
||||
{
|
||||
/* we return the runtime structure instead. */
|
||||
@@ -919,7 +908,7 @@ comm_base_create(int ATTR_UNUSED(sigs))
|
||||
return (struct comm_base*)runtime;
|
||||
}
|
||||
|
||||
void
|
||||
void
|
||||
comm_base_delete(struct comm_base* b)
|
||||
{
|
||||
struct replay_runtime* runtime = (struct replay_runtime*)b;
|
||||
@@ -959,7 +948,7 @@ comm_base_timept(struct comm_base* b, time_t** tt, struct timeval** tv)
|
||||
*tv = &runtime->now_tv;
|
||||
}
|
||||
|
||||
void
|
||||
void
|
||||
comm_base_dispatch(struct comm_base* b)
|
||||
{
|
||||
struct replay_runtime* runtime = (struct replay_runtime*)b;
|
||||
@@ -969,7 +958,7 @@ comm_base_dispatch(struct comm_base* b)
|
||||
else exit(0); /* OK exit when LIBEVENT_SIGNAL_PROBLEM exists */
|
||||
}
|
||||
|
||||
void
|
||||
void
|
||||
comm_base_exit(struct comm_base* b)
|
||||
{
|
||||
struct replay_runtime* runtime = (struct replay_runtime*)b;
|
||||
@@ -979,7 +968,7 @@ comm_base_exit(struct comm_base* b)
|
||||
}
|
||||
}
|
||||
|
||||
struct comm_signal*
|
||||
struct comm_signal*
|
||||
comm_signal_create(struct comm_base* base,
|
||||
void (*callback)(int, void*), void* cb_arg)
|
||||
{
|
||||
@@ -989,20 +978,20 @@ comm_signal_create(struct comm_base* base,
|
||||
return calloc(1, sizeof(struct comm_signal));
|
||||
}
|
||||
|
||||
int
|
||||
comm_signal_bind(struct comm_signal* ATTR_UNUSED(comsig), int
|
||||
int
|
||||
comm_signal_bind(struct comm_signal* ATTR_UNUSED(comsig), int
|
||||
ATTR_UNUSED(sig))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
void
|
||||
comm_signal_delete(struct comm_signal* comsig)
|
||||
{
|
||||
free(comsig);
|
||||
}
|
||||
|
||||
void
|
||||
void
|
||||
comm_point_send_reply(struct comm_reply* repinfo)
|
||||
{
|
||||
struct replay_answer* ans = (struct replay_answer*)calloc(1,
|
||||
@@ -1026,7 +1015,7 @@ comm_point_send_reply(struct comm_reply* repinfo)
|
||||
log_pkt("reply pkt: ", ans->pkt, ans->pkt_len);
|
||||
}
|
||||
|
||||
void
|
||||
void
|
||||
comm_point_drop_reply(struct comm_reply* repinfo)
|
||||
{
|
||||
log_info("comm_point_drop_reply fake");
|
||||
@@ -1036,14 +1025,14 @@ comm_point_drop_reply(struct comm_reply* repinfo)
|
||||
}
|
||||
}
|
||||
|
||||
struct outside_network*
|
||||
outside_network_create(struct comm_base* base, size_t bufsize,
|
||||
size_t ATTR_UNUSED(num_ports), char** ATTR_UNUSED(ifs),
|
||||
int ATTR_UNUSED(num_ifs), int ATTR_UNUSED(do_ip4),
|
||||
int ATTR_UNUSED(do_ip6), size_t ATTR_UNUSED(num_tcp),
|
||||
struct outside_network*
|
||||
outside_network_create(struct comm_base* base, size_t bufsize,
|
||||
size_t ATTR_UNUSED(num_ports), char** ATTR_UNUSED(ifs),
|
||||
int ATTR_UNUSED(num_ifs), int ATTR_UNUSED(do_ip4),
|
||||
int ATTR_UNUSED(do_ip6), size_t ATTR_UNUSED(num_tcp),
|
||||
int ATTR_UNUSED(dscp),
|
||||
struct infra_cache* infra,
|
||||
struct ub_randstate* ATTR_UNUSED(rnd),
|
||||
struct ub_randstate* ATTR_UNUSED(rnd),
|
||||
int ATTR_UNUSED(use_caps_for_id), int* ATTR_UNUSED(availports),
|
||||
int ATTR_UNUSED(numavailports), size_t ATTR_UNUSED(unwanted_threshold),
|
||||
int ATTR_UNUSED(outgoing_tcp_mss),
|
||||
@@ -1055,7 +1044,7 @@ outside_network_create(struct comm_base* base, size_t bufsize,
|
||||
int ATTR_UNUSED(tcp_auth_query_timeout))
|
||||
{
|
||||
struct replay_runtime* runtime = (struct replay_runtime*)base;
|
||||
struct outside_network* outnet = calloc(1,
|
||||
struct outside_network* outnet = calloc(1,
|
||||
sizeof(struct outside_network));
|
||||
(void)unwanted_action;
|
||||
if(!outnet)
|
||||
@@ -1070,7 +1059,7 @@ outside_network_create(struct comm_base* base, size_t bufsize,
|
||||
return outnet;
|
||||
}
|
||||
|
||||
void
|
||||
void
|
||||
outside_network_delete(struct outside_network* outnet)
|
||||
{
|
||||
if(!outnet)
|
||||
@@ -1079,12 +1068,12 @@ outside_network_delete(struct outside_network* outnet)
|
||||
free(outnet);
|
||||
}
|
||||
|
||||
void
|
||||
void
|
||||
outside_network_quit_prepare(struct outside_network* ATTR_UNUSED(outnet))
|
||||
{
|
||||
}
|
||||
|
||||
struct pending*
|
||||
struct pending*
|
||||
pending_udp_query(struct serviced_query* sq, sldns_buffer* packet,
|
||||
int timeout, comm_point_callback_type* callback, void* callback_arg)
|
||||
{
|
||||
@@ -1126,7 +1115,7 @@ pending_udp_query(struct serviced_query* sq, sldns_buffer* packet,
|
||||
repevt_string(runtime->now->evt_type));
|
||||
advance_moment(runtime);
|
||||
/* still create the pending, because we need it to callback */
|
||||
}
|
||||
}
|
||||
log_info("testbound: created fake pending");
|
||||
/* add to list */
|
||||
pend->next = runtime->pending_list;
|
||||
@@ -1176,7 +1165,7 @@ pending_tcp_query(struct serviced_query* sq, sldns_buffer* packet,
|
||||
repevt_string(runtime->now->evt_type));
|
||||
advance_moment(runtime);
|
||||
/* still create the pending, because we need it to callback */
|
||||
}
|
||||
}
|
||||
log_info("testbound: created fake pending");
|
||||
/* add to list */
|
||||
pend->next = runtime->pending_list;
|
||||
@@ -1200,10 +1189,10 @@ struct serviced_query* outnet_serviced_query(struct outside_network* outnet,
|
||||
sizeof(struct fake_pending));
|
||||
char z[256];
|
||||
log_assert(pend);
|
||||
log_nametypeclass(VERB_OPS, "pending serviced query",
|
||||
log_nametypeclass(VERB_OPS, "pending serviced query",
|
||||
qinfo->qname, qinfo->qtype, qinfo->qclass);
|
||||
dname_str(zone, z);
|
||||
verbose(VERB_OPS, "pending serviced query zone %s flags%s%s%s%s",
|
||||
verbose(VERB_OPS, "pending serviced query zone %s flags%s%s%s%s",
|
||||
z, (flags&BIT_RD)?" RD":"", (flags&BIT_CD)?" CD":"",
|
||||
(flags&~(BIT_RD|BIT_CD))?" MORE":"", (dnssec)?" DO":"");
|
||||
|
||||
@@ -1263,6 +1252,8 @@ struct serviced_query* outnet_serviced_query(struct outside_network* outnet,
|
||||
if(dnssec)
|
||||
edns.bits = EDNS_DO;
|
||||
edns.padding_block_size = 0;
|
||||
edns.cookie_present = 0;
|
||||
edns.cookie_valid = 0;
|
||||
edns.opt_list_in = NULL;
|
||||
edns.opt_list_out = per_upstream_opt_list;
|
||||
edns.opt_list_inplace_cb_out = NULL;
|
||||
@@ -1299,7 +1290,7 @@ struct serviced_query* outnet_serviced_query(struct outside_network* outnet,
|
||||
repevt_string(runtime->now->evt_type));
|
||||
advance_moment(runtime);
|
||||
/* still create the pending, because we need it to callback */
|
||||
}
|
||||
}
|
||||
log_info("testbound: created fake pending");
|
||||
/* add to list */
|
||||
pend->next = runtime->pending_list;
|
||||
@@ -1344,7 +1335,7 @@ struct listen_port* listening_ports_open(struct config_file* ATTR_UNUSED(cfg),
|
||||
char** ATTR_UNUSED(ifs), int ATTR_UNUSED(num_ifs),
|
||||
int* ATTR_UNUSED(reuseport))
|
||||
{
|
||||
return calloc(1, 1);
|
||||
return calloc(1, sizeof(struct listen_port));
|
||||
}
|
||||
|
||||
void listening_ports_free(struct listen_port* list)
|
||||
@@ -1354,7 +1345,7 @@ void listening_ports_free(struct listen_port* list)
|
||||
|
||||
struct comm_point* comm_point_create_local(struct comm_base* ATTR_UNUSED(base),
|
||||
int ATTR_UNUSED(fd), size_t ATTR_UNUSED(bufsize),
|
||||
comm_point_callback_type* ATTR_UNUSED(callback),
|
||||
comm_point_callback_type* ATTR_UNUSED(callback),
|
||||
void* ATTR_UNUSED(callback_arg))
|
||||
{
|
||||
struct fake_commpoint* fc = (struct fake_commpoint*)calloc(1,
|
||||
@@ -1366,7 +1357,7 @@ struct comm_point* comm_point_create_local(struct comm_base* ATTR_UNUSED(base),
|
||||
|
||||
struct comm_point* comm_point_create_raw(struct comm_base* ATTR_UNUSED(base),
|
||||
int ATTR_UNUSED(fd), int ATTR_UNUSED(writing),
|
||||
comm_point_callback_type* ATTR_UNUSED(callback),
|
||||
comm_point_callback_type* ATTR_UNUSED(callback),
|
||||
void* ATTR_UNUSED(callback_arg))
|
||||
{
|
||||
/* no pipe comm possible */
|
||||
@@ -1377,7 +1368,7 @@ struct comm_point* comm_point_create_raw(struct comm_base* ATTR_UNUSED(base),
|
||||
return (struct comm_point*)fc;
|
||||
}
|
||||
|
||||
void comm_point_start_listening(struct comm_point* ATTR_UNUSED(c),
|
||||
void comm_point_start_listening(struct comm_point* ATTR_UNUSED(c),
|
||||
int ATTR_UNUSED(newfd), int ATTR_UNUSED(sec))
|
||||
{
|
||||
/* no bg write pipe comm possible */
|
||||
@@ -1422,7 +1413,7 @@ size_t serviced_get_mem(struct serviced_query* ATTR_UNUSED(c))
|
||||
}
|
||||
|
||||
/* fake for fptr wlist */
|
||||
int outnet_udp_cb(struct comm_point* ATTR_UNUSED(c),
|
||||
int outnet_udp_cb(struct comm_point* ATTR_UNUSED(c),
|
||||
void* ATTR_UNUSED(arg), int ATTR_UNUSED(error),
|
||||
struct comm_reply *ATTR_UNUSED(reply_info))
|
||||
{
|
||||
@@ -1430,7 +1421,7 @@ int outnet_udp_cb(struct comm_point* ATTR_UNUSED(c),
|
||||
return 0;
|
||||
}
|
||||
|
||||
int outnet_tcp_cb(struct comm_point* ATTR_UNUSED(c),
|
||||
int outnet_tcp_cb(struct comm_point* ATTR_UNUSED(c),
|
||||
void* ATTR_UNUSED(arg), int ATTR_UNUSED(error),
|
||||
struct comm_reply *ATTR_UNUSED(reply_info))
|
||||
{
|
||||
@@ -1458,67 +1449,67 @@ void outnet_tcptimer(void* ATTR_UNUSED(arg))
|
||||
log_assert(0);
|
||||
}
|
||||
|
||||
void comm_point_udp_callback(int ATTR_UNUSED(fd), short ATTR_UNUSED(event),
|
||||
void comm_point_udp_callback(int ATTR_UNUSED(fd), short ATTR_UNUSED(event),
|
||||
void* ATTR_UNUSED(arg))
|
||||
{
|
||||
log_assert(0);
|
||||
}
|
||||
|
||||
void comm_point_udp_ancil_callback(int ATTR_UNUSED(fd),
|
||||
void comm_point_udp_ancil_callback(int ATTR_UNUSED(fd),
|
||||
short ATTR_UNUSED(event), void* ATTR_UNUSED(arg))
|
||||
{
|
||||
log_assert(0);
|
||||
}
|
||||
|
||||
void comm_point_tcp_accept_callback(int ATTR_UNUSED(fd),
|
||||
void comm_point_tcp_accept_callback(int ATTR_UNUSED(fd),
|
||||
short ATTR_UNUSED(event), void* ATTR_UNUSED(arg))
|
||||
{
|
||||
log_assert(0);
|
||||
}
|
||||
|
||||
void comm_point_tcp_handle_callback(int ATTR_UNUSED(fd),
|
||||
void comm_point_tcp_handle_callback(int ATTR_UNUSED(fd),
|
||||
short ATTR_UNUSED(event), void* ATTR_UNUSED(arg))
|
||||
{
|
||||
log_assert(0);
|
||||
}
|
||||
|
||||
void comm_timer_callback(int ATTR_UNUSED(fd),
|
||||
void comm_timer_callback(int ATTR_UNUSED(fd),
|
||||
short ATTR_UNUSED(event), void* ATTR_UNUSED(arg))
|
||||
{
|
||||
log_assert(0);
|
||||
}
|
||||
|
||||
void comm_signal_callback(int ATTR_UNUSED(fd),
|
||||
void comm_signal_callback(int ATTR_UNUSED(fd),
|
||||
short ATTR_UNUSED(event), void* ATTR_UNUSED(arg))
|
||||
{
|
||||
log_assert(0);
|
||||
}
|
||||
|
||||
void comm_point_http_handle_callback(int ATTR_UNUSED(fd),
|
||||
void comm_point_http_handle_callback(int ATTR_UNUSED(fd),
|
||||
short ATTR_UNUSED(event), void* ATTR_UNUSED(arg))
|
||||
{
|
||||
log_assert(0);
|
||||
}
|
||||
|
||||
void comm_point_local_handle_callback(int ATTR_UNUSED(fd),
|
||||
void comm_point_local_handle_callback(int ATTR_UNUSED(fd),
|
||||
short ATTR_UNUSED(event), void* ATTR_UNUSED(arg))
|
||||
{
|
||||
log_assert(0);
|
||||
}
|
||||
|
||||
void comm_point_raw_handle_callback(int ATTR_UNUSED(fd),
|
||||
void comm_point_raw_handle_callback(int ATTR_UNUSED(fd),
|
||||
short ATTR_UNUSED(event), void* ATTR_UNUSED(arg))
|
||||
{
|
||||
log_assert(0);
|
||||
}
|
||||
|
||||
void comm_base_handle_slow_accept(int ATTR_UNUSED(fd),
|
||||
void comm_base_handle_slow_accept(int ATTR_UNUSED(fd),
|
||||
short ATTR_UNUSED(event), void* ATTR_UNUSED(arg))
|
||||
{
|
||||
log_assert(0);
|
||||
}
|
||||
|
||||
int serviced_udp_callback(struct comm_point* ATTR_UNUSED(c),
|
||||
int serviced_udp_callback(struct comm_point* ATTR_UNUSED(c),
|
||||
void* ATTR_UNUSED(arg), int ATTR_UNUSED(error),
|
||||
struct comm_reply* ATTR_UNUSED(reply_info))
|
||||
{
|
||||
@@ -1526,7 +1517,7 @@ int serviced_udp_callback(struct comm_point* ATTR_UNUSED(c),
|
||||
return 0;
|
||||
}
|
||||
|
||||
int serviced_tcp_callback(struct comm_point* ATTR_UNUSED(c),
|
||||
int serviced_tcp_callback(struct comm_point* ATTR_UNUSED(c),
|
||||
void* ATTR_UNUSED(arg), int ATTR_UNUSED(error),
|
||||
struct comm_reply* ATTR_UNUSED(reply_info))
|
||||
{
|
||||
@@ -1559,7 +1550,7 @@ int reuse_id_cmp(const void* ATTR_UNUSED(a), const void* ATTR_UNUSED(b))
|
||||
}
|
||||
|
||||
/* timers in testbound for autotrust. statistics tested in tdir. */
|
||||
struct comm_timer* comm_timer_create(struct comm_base* base,
|
||||
struct comm_timer* comm_timer_create(struct comm_base* base,
|
||||
void (*cb)(void*), void* cb_arg)
|
||||
{
|
||||
struct replay_runtime* runtime = (struct replay_runtime*)base;
|
||||
@@ -1587,7 +1578,7 @@ void comm_timer_set(struct comm_timer* timer, struct timeval* tv)
|
||||
struct fake_timer* t = (struct fake_timer*)timer;
|
||||
t->enabled = 1;
|
||||
t->tv = *tv;
|
||||
log_info("fake timer set %d.%6.6d",
|
||||
log_info("fake timer set %d.%6.6d",
|
||||
(int)t->tv.tv_sec, (int)t->tv.tv_usec);
|
||||
timeval_add(&t->tv, &t->runtime->now_tv);
|
||||
}
|
||||
@@ -1663,6 +1654,7 @@ int create_udp_sock(int ATTR_UNUSED(family), int ATTR_UNUSED(socktype),
|
||||
|
||||
struct comm_point* comm_point_create_udp(struct comm_base *ATTR_UNUSED(base),
|
||||
int ATTR_UNUSED(fd), sldns_buffer* ATTR_UNUSED(buffer),
|
||||
int ATTR_UNUSED(pp2_enabled),
|
||||
comm_point_callback_type* ATTR_UNUSED(callback),
|
||||
void* ATTR_UNUSED(callback_arg),
|
||||
struct unbound_socket* ATTR_UNUSED(socket))
|
||||
|
||||
@@ -177,6 +177,8 @@ static int readup_str(char** str, FILE* in)
|
||||
}
|
||||
buf[len] = 0;
|
||||
*str = strdup(buf);
|
||||
if(!*str)
|
||||
fatal_exit("strdup failed: out of memory");
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
+27
-11
@@ -8,6 +8,7 @@ fi
|
||||
|
||||
# This will keep the temporary directory around and return 1 when the test failed.
|
||||
DEBUG=0
|
||||
test -n "$DEBUG_TDIR" && DEBUG=1
|
||||
|
||||
quiet=0
|
||||
if test "$1" = "-q"; then
|
||||
@@ -17,9 +18,9 @@ fi
|
||||
|
||||
if test "$1" = "clean"; then
|
||||
if test $quiet = 0; then
|
||||
echo "rm -f result.* .done* .tdir.var.master .tdir.var.test"
|
||||
echo "rm -f result.* .done* .skip* .tdir.var.master .tdir.var.test"
|
||||
fi
|
||||
rm -f result.* .done* .tdir.var.master .tdir.var.test
|
||||
rm -f result.* .done* .skip* .tdir.var.master .tdir.var.test
|
||||
exit 0
|
||||
fi
|
||||
if test "$1" = "fake"; then
|
||||
@@ -54,12 +55,15 @@ if test "$1" = "-f" && test "$2" = "report"; then
|
||||
echo "** PASSED ** $timelen $name: $desc"
|
||||
pass=`expr $pass + 1`
|
||||
fi
|
||||
elif test -f ".skip-$name"; then
|
||||
echo ".. SKIPPED.. $timelen $name: $desc"
|
||||
skip=`expr $skip + 1`
|
||||
else
|
||||
if test -f "result.$name"; then
|
||||
echo "!! FAILED !! $timelen $name: $desc"
|
||||
fail=`expr $fail + 1`
|
||||
else
|
||||
echo ".> SKIPPED<< $timelen $name: $desc"
|
||||
echo ".. SKIPPED.. $timelen $name: $desc"
|
||||
skip=`expr $skip + 1`
|
||||
fi
|
||||
fi
|
||||
@@ -81,11 +85,17 @@ if test "$1" = "report" || test "$2" = "report"; then
|
||||
if test $quiet = 0; then
|
||||
echo "** PASSED ** : $name"
|
||||
fi
|
||||
elif test -f ".skip-$name"; then
|
||||
if test $quiet = 0; then
|
||||
echo ".. SKIPPED.. : $name"
|
||||
fi
|
||||
else
|
||||
if test -f "result.$name"; then
|
||||
echo "!! FAILED !! : $name"
|
||||
else
|
||||
echo ">> SKIPPED<< : $name"
|
||||
if test $quiet = 0; then
|
||||
echo ".. SKIPPED.. : $name"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
done
|
||||
@@ -116,6 +126,7 @@ name=`basename $1 .tdir`
|
||||
dir=$name.$$
|
||||
result=result.$name
|
||||
done=.done-$name
|
||||
skip=.skip-$name
|
||||
success="no"
|
||||
if test -x "`which bash`"; then
|
||||
shell="bash"
|
||||
@@ -124,8 +135,8 @@ else
|
||||
fi
|
||||
|
||||
# check already done
|
||||
if test -f .done-$name; then
|
||||
echo "minitdir .done-$name exists. skip test."
|
||||
if test -f $done; then
|
||||
echo "minitdir $done exists. skip test."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
@@ -151,11 +162,16 @@ if test -f $name.pre; then
|
||||
fi
|
||||
echo "minitdir exe $name.pre" >> $result
|
||||
$shell $name.pre $args >> $result
|
||||
if test $? -ne 0; then
|
||||
exit_value=$?
|
||||
if test $exit_value -eq 3; then
|
||||
echo "$name: SKIPPED" >> $result
|
||||
echo "$name: SKIPPED" > ../$skip
|
||||
echo "$name: SKIPPED"
|
||||
elif test $exit_value -ne 0; then
|
||||
echo "Warning: $name.pre did not exit successfully"
|
||||
fi
|
||||
fi
|
||||
if test -f $name.test; then
|
||||
if test -f $name.test -a ! -f ../$skip; then
|
||||
if test $quiet = 0; then
|
||||
echo "minitdir exe $name.test"
|
||||
fi
|
||||
@@ -167,14 +183,14 @@ if test -f $name.test; then
|
||||
success="no"
|
||||
else
|
||||
echo "$name: PASSED" >> $result
|
||||
echo "$name: PASSED" > ../.done-$name
|
||||
echo "$name: PASSED" > ../$done
|
||||
if test $quiet = 0; then
|
||||
echo "$name: PASSED"
|
||||
fi
|
||||
success="yes"
|
||||
fi
|
||||
fi
|
||||
if test -f $name.post; then
|
||||
if test -f $name.post -a ! -f ../$skip; then
|
||||
if test $quiet = 0; then
|
||||
echo "minitdir exe $name.post"
|
||||
fi
|
||||
@@ -198,7 +214,7 @@ if test $DEBUG -eq 0; then
|
||||
rm -rf $dir
|
||||
fi
|
||||
else
|
||||
if test $success == "no"; then
|
||||
if test $success = "no"; then
|
||||
exit 1
|
||||
fi
|
||||
exit 0
|
||||
|
||||
@@ -1,128 +0,0 @@
|
||||
# tpkg that only exes the files.
|
||||
args="../.."
|
||||
if test "$1" = "-a"; then
|
||||
args=$2
|
||||
shift
|
||||
shift
|
||||
fi
|
||||
|
||||
if test "$1" = "clean"; then
|
||||
echo "rm -f result.* .done* .tpkg.var.master .tpkg.var.test"
|
||||
rm -f result.* .done* .tpkg.var.master .tpkg.var.test
|
||||
exit 0
|
||||
fi
|
||||
if test "$1" = "fake"; then
|
||||
echo "minitpkg fake $2"
|
||||
echo "fake" > .done-`basename $2 .tpkg`
|
||||
exit 0
|
||||
fi
|
||||
if test "$1" = "report" || test "$2" = "report"; then
|
||||
echo "Minitpkg Report"
|
||||
for result in *.tpkg; do
|
||||
name=`basename $result .tpkg`
|
||||
if test -f ".done-$name"; then
|
||||
if test "$1" != "-q"; then
|
||||
echo "** PASSED ** : $name"
|
||||
fi
|
||||
else
|
||||
if test -f "result.$name"; then
|
||||
echo "!! FAILED !! : $name"
|
||||
else
|
||||
echo ">> SKIPPED<< : $name"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if test "$1" != 'exe'; then
|
||||
# usage
|
||||
echo "mini tpkg. Reduced functionality for old shells."
|
||||
echo " tpkg exe <file>"
|
||||
echo " tpkg fake <file>"
|
||||
echo " tpkg clean"
|
||||
echo " tpkg [-q] report"
|
||||
exit 1
|
||||
fi
|
||||
shift
|
||||
|
||||
# do not execute if the disk is too full
|
||||
#DISKLIMIT=100000
|
||||
# This check is not portable (to Solaris 10).
|
||||
#avail=`df . | tail -1 | awk '{print $4}'`
|
||||
#if test "$avail" -lt "$DISKLIMIT"; then
|
||||
#echo "minitpkg: The disk is too full! Only $avail."
|
||||
#exit 1
|
||||
#fi
|
||||
|
||||
name=`basename $1 .tpkg`
|
||||
dir=$name.$$
|
||||
result=result.$name
|
||||
done=.done-$name
|
||||
success="no"
|
||||
if test -x "`which bash`"; then
|
||||
shell="bash"
|
||||
else
|
||||
shell="sh"
|
||||
fi
|
||||
|
||||
# check already done
|
||||
if test -f .done-$name; then
|
||||
echo "minitpkg .done-$name exists. skip test."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Extract
|
||||
echo "minitpkg extract $1 to $dir"
|
||||
mkdir $dir
|
||||
gzip -cd $name.tpkg | (cd $dir; tar xf -)
|
||||
cd $dir
|
||||
mv $name.dir/* .
|
||||
|
||||
# EXE
|
||||
echo "minitpkg exe $name" > $result
|
||||
grep "Description:" $name.dsc >> $result 2>&1
|
||||
echo "DateRunStart: "`date "+%s" 2>/dev/null` >> $result
|
||||
if test -f $name.pre; then
|
||||
echo "minitpkg exe $name.pre"
|
||||
echo "minitpkg exe $name.pre" >> $result
|
||||
$shell $name.pre $args >> $result
|
||||
if test $? -ne 0; then
|
||||
echo "Warning: $name.pre did not exit successfully"
|
||||
fi
|
||||
fi
|
||||
if test -f $name.test; then
|
||||
echo "minitpkg exe $name.test"
|
||||
echo "minitpkg exe $name.test" >> $result
|
||||
$shell $name.test $args >>$result 2>&1
|
||||
if test $? -ne 0; then
|
||||
echo "$name: FAILED" >> $result
|
||||
echo "$name: FAILED"
|
||||
success="no"
|
||||
else
|
||||
echo "$name: PASSED" >> $result
|
||||
echo "$name: PASSED" > ../.done-$name
|
||||
echo "$name: PASSED"
|
||||
success="yes"
|
||||
fi
|
||||
fi
|
||||
if test -f $name.post; then
|
||||
echo "minitpkg exe $name.post"
|
||||
echo "minitpkg exe $name.post" >> $result
|
||||
$shell $name.post $args >> $result
|
||||
if test $? -ne 0; then
|
||||
echo "Warning: $name.post did not exit successfully"
|
||||
fi
|
||||
fi
|
||||
echo "DateRunEnd: "`date "+%s" 2>/dev/null` >> $result
|
||||
|
||||
mv $result ..
|
||||
cd ..
|
||||
rm -rf $dir
|
||||
# compat for windows where deletion may not succeed initially (files locked
|
||||
# by processes that still have to exit).
|
||||
if test $? -eq 1; then
|
||||
echo "minitpkg waiting for processes to terminate"
|
||||
sleep 2 # some time to exit, and try again
|
||||
rm -rf $dir
|
||||
fi
|
||||
+9
-1
@@ -458,9 +458,17 @@ qlist_parse_line(sldns_buffer* buf, char* p)
|
||||
if(strcmp(tp, "IN") == 0 || strcmp(tp, "CH") == 0) {
|
||||
qinfo.qtype = sldns_get_rr_type_by_name(cl);
|
||||
qinfo.qclass = sldns_get_rr_class_by_name(tp);
|
||||
if((qinfo.qtype == 0 && strcmp(cl, "TYPE0") != 0) ||
|
||||
(qinfo.qclass == 0 && strcmp(tp, "CLASS0") != 0)) {
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
qinfo.qtype = sldns_get_rr_type_by_name(tp);
|
||||
qinfo.qclass = sldns_get_rr_class_by_name(cl);
|
||||
if((qinfo.qtype == 0 && strcmp(tp, "TYPE0") != 0) ||
|
||||
(qinfo.qclass == 0 && strcmp(cl, "CLASS0") != 0)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if(fl[0] == '+') rec = 1;
|
||||
else if(fl[0] == '-') rec = 0;
|
||||
@@ -618,7 +626,7 @@ int main(int argc, char* argv[])
|
||||
printf("error: pass server IP address on commandline.\n");
|
||||
usage(nm);
|
||||
}
|
||||
if(!extstrtoaddr(argv[0], &info.dest, &info.destlen)) {
|
||||
if(!extstrtoaddr(argv[0], &info.dest, &info.destlen, UNBOUND_DNS_PORT)) {
|
||||
printf("Could not parse ip: %s\n", argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
+42
-54
@@ -2,24 +2,24 @@
|
||||
* testcode/replay.c - store and use a replay of events for the DNS resolver.
|
||||
*
|
||||
* 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
|
||||
@@ -51,6 +51,7 @@
|
||||
#include "testcode/testpkts.h"
|
||||
#include "testcode/fake_event.h"
|
||||
#include "sldns/str2wire.h"
|
||||
#include "util/timeval_func.h"
|
||||
|
||||
/** max length of lines in file */
|
||||
#define MAX_LINE_LEN 10240
|
||||
@@ -59,35 +60,19 @@
|
||||
* Expand a macro
|
||||
* @param store: value storage
|
||||
* @param runtime: replay runtime for other stuff.
|
||||
* @param text: the macro text, after the ${, Updated to after the } when
|
||||
* @param text: the macro text, after the ${, Updated to after the } when
|
||||
* done (successfully).
|
||||
* @return expanded text, malloced. NULL on failure.
|
||||
*/
|
||||
static char* macro_expand(rbtree_type* store,
|
||||
static char* macro_expand(rbtree_type* store,
|
||||
struct replay_runtime* runtime, char** text);
|
||||
|
||||
/** 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
|
||||
}
|
||||
|
||||
/** parse keyword in string.
|
||||
/** parse keyword in string.
|
||||
* @param line: if found, the line is advanced to after the keyword.
|
||||
* @param keyword: string.
|
||||
* @return: true if found, false if not.
|
||||
* @return: true if found, false if not.
|
||||
*/
|
||||
static int
|
||||
static int
|
||||
parse_keyword(char** line, const char* keyword)
|
||||
{
|
||||
size_t len = (size_t)strlen(keyword);
|
||||
@@ -135,8 +120,8 @@ strip_end_white(char* p)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a range from file.
|
||||
/**
|
||||
* Read a range from file.
|
||||
* @param remain: Rest of line (after RANGE keyword).
|
||||
* @param in: file to read from.
|
||||
* @param name: name to print in errors.
|
||||
@@ -179,8 +164,9 @@ replay_range_read(char* remain, FILE* in, const char* name,
|
||||
while(isspace((unsigned char)*parse))
|
||||
parse++;
|
||||
strip_end_white(parse);
|
||||
if(!extstrtoaddr(parse, &rng->addr, &rng->addrlen)) {
|
||||
log_err("Line %d: could not read ADDRESS: %s",
|
||||
if(!extstrtoaddr(parse, &rng->addr, &rng->addrlen,
|
||||
UNBOUND_DNS_PORT)) {
|
||||
log_err("Line %d: could not read ADDRESS: %s",
|
||||
pstate->lineno, parse);
|
||||
free(rng);
|
||||
return NULL;
|
||||
@@ -254,8 +240,8 @@ read_assign_step(char* remain, struct replay_moment* mom)
|
||||
fatal_exit("out of memory");
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a replay moment 'STEP' from file.
|
||||
/**
|
||||
* Read a replay moment 'STEP' from file.
|
||||
* @param remain: Rest of line (after STEP keyword).
|
||||
* @param in: file to read from.
|
||||
* @param name: name to print in errors.
|
||||
@@ -287,7 +273,8 @@ replay_moment_read(char* remain, FILE* in, const char* name,
|
||||
} else if(parse_keyword(&remain, "QUERY")) {
|
||||
mom->evt_type = repevt_front_query;
|
||||
readentry = 1;
|
||||
if(!extstrtoaddr("127.0.0.1", &mom->addr, &mom->addrlen))
|
||||
if(!extstrtoaddr("127.0.0.1", &mom->addr, &mom->addrlen,
|
||||
UNBOUND_DNS_PORT))
|
||||
fatal_exit("internal error");
|
||||
} else if(parse_keyword(&remain, "CHECK_ANSWER")) {
|
||||
mom->evt_type = repevt_front_reply;
|
||||
@@ -354,7 +341,7 @@ replay_moment_read(char* remain, FILE* in, const char* name,
|
||||
m++;
|
||||
while(isspace((unsigned char)*m))
|
||||
m++;
|
||||
if(!extstrtoaddr(s, &mom->addr, &mom->addrlen))
|
||||
if(!extstrtoaddr(s, &mom->addr, &mom->addrlen, UNBOUND_DNS_PORT))
|
||||
fatal_exit("bad infra_rtt address %s", s);
|
||||
strip_end_white(m);
|
||||
mom->variable = strdup(remain);
|
||||
@@ -372,19 +359,20 @@ replay_moment_read(char* remain, FILE* in, const char* name,
|
||||
while(isspace((unsigned char)*remain))
|
||||
remain++;
|
||||
strip_end_white(remain);
|
||||
if(!extstrtoaddr(remain, &mom->addr, &mom->addrlen)) {
|
||||
log_err("line %d: could not parse ADDRESS: %s",
|
||||
if(!extstrtoaddr(remain, &mom->addr, &mom->addrlen,
|
||||
UNBOUND_DNS_PORT)) {
|
||||
log_err("line %d: could not parse ADDRESS: %s",
|
||||
pstate->lineno, remain);
|
||||
free(mom);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(parse_keyword(&remain, "ELAPSE")) {
|
||||
double sec;
|
||||
errno = 0;
|
||||
sec = strtod(remain, &remain);
|
||||
if(sec == 0. && errno != 0) {
|
||||
log_err("line %d: could not parse ELAPSE: %s (%s)",
|
||||
log_err("line %d: could not parse ELAPSE: %s (%s)",
|
||||
pstate->lineno, remain, strerror(errno));
|
||||
free(mom);
|
||||
return NULL;
|
||||
@@ -394,7 +382,7 @@ replay_moment_read(char* remain, FILE* in, const char* name,
|
||||
mom->elapse.tv_usec = (int)((sec - (double)mom->elapse.tv_sec)
|
||||
*1000000. + 0.5);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
if(readentry) {
|
||||
mom->match = read_entry(in, name, pstate, 1);
|
||||
@@ -430,7 +418,7 @@ make_scenario(char* line)
|
||||
return scen;
|
||||
}
|
||||
|
||||
struct replay_scenario*
|
||||
struct replay_scenario*
|
||||
replay_scenario_read(FILE* in, const char* name, int* lineno)
|
||||
{
|
||||
char line[MAX_LINE_LEN];
|
||||
@@ -448,7 +436,7 @@ replay_scenario_read(FILE* in, const char* name, int* lineno)
|
||||
(*lineno)++;
|
||||
while(isspace((unsigned char)*parse))
|
||||
parse++;
|
||||
if(!*parse)
|
||||
if(!*parse)
|
||||
continue; /* empty line */
|
||||
if(parse_keyword(&parse, ";"))
|
||||
continue; /* comment */
|
||||
@@ -459,11 +447,11 @@ replay_scenario_read(FILE* in, const char* name, int* lineno)
|
||||
if(!scen)
|
||||
fatal_exit("%d: could not make scen", *lineno);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if(!scen)
|
||||
fatal_exit("%d: expected SCENARIO", *lineno);
|
||||
if(parse_keyword(&parse, "RANGE_BEGIN")) {
|
||||
struct replay_range* newr = replay_range_read(parse,
|
||||
struct replay_range* newr = replay_range_read(parse,
|
||||
in, name, &pstate, line);
|
||||
if(!newr)
|
||||
fatal_exit("%d: bad range", pstate.lineno);
|
||||
@@ -471,12 +459,12 @@ replay_scenario_read(FILE* in, const char* name, int* lineno)
|
||||
newr->next_range = scen->range_list;
|
||||
scen->range_list = newr;
|
||||
} else if(parse_keyword(&parse, "STEP")) {
|
||||
struct replay_moment* mom = replay_moment_read(parse,
|
||||
struct replay_moment* mom = replay_moment_read(parse,
|
||||
in, name, &pstate);
|
||||
if(!mom)
|
||||
fatal_exit("%d: bad moment", pstate.lineno);
|
||||
*lineno = pstate.lineno;
|
||||
if(scen->mom_last &&
|
||||
if(scen->mom_last &&
|
||||
scen->mom_last->time_step >= mom->time_step)
|
||||
fatal_exit("%d: time goes backwards", *lineno);
|
||||
if(scen->mom_last)
|
||||
@@ -499,7 +487,7 @@ replay_scenario_read(FILE* in, const char* name, int* lineno)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
void
|
||||
replay_scenario_delete(struct replay_scenario* scen)
|
||||
{
|
||||
struct replay_moment* mom, *momn;
|
||||
@@ -627,7 +615,7 @@ do_macro_recursion(rbtree_type* store, struct replay_runtime* runtime,
|
||||
{
|
||||
char* after = at+2;
|
||||
char* expand = macro_expand(store, runtime, &after);
|
||||
if(!expand)
|
||||
if(!expand)
|
||||
return NULL; /* expansion failed */
|
||||
if(!do_buf_insert(at, remain, after, expand)) {
|
||||
free(expand);
|
||||
@@ -662,7 +650,7 @@ do_macro_variable(rbtree_type* store, char* buf, size_t remain)
|
||||
}
|
||||
/* terminator, we are working in macro_expand() buffer */
|
||||
sv = *at;
|
||||
*at = 0;
|
||||
*at = 0;
|
||||
v = macro_getvar(store, name);
|
||||
*at = sv;
|
||||
|
||||
@@ -813,7 +801,7 @@ macro_expand(rbtree_type* store, struct replay_runtime* runtime, char** text)
|
||||
time_t res = 0;
|
||||
if(runtime) {
|
||||
struct fake_timer* t = first_timer(runtime);
|
||||
if(t && (time_t)t->tv.tv_sec >= runtime->now_secs)
|
||||
if(t && (time_t)t->tv.tv_sec >= runtime->now_secs)
|
||||
res = (time_t)t->tv.tv_sec - runtime->now_secs;
|
||||
}
|
||||
snprintf(buf, sizeof(buf), ARG_LL "d", (long long)res);
|
||||
@@ -852,9 +840,9 @@ macro_expand(rbtree_type* store, struct replay_runtime* runtime, char** text)
|
||||
if(dofunc) {
|
||||
/* post process functions, buf has the argument(s) */
|
||||
if(strncmp(buf, "ctime", 5) == 0) {
|
||||
return do_macro_ctime(buf+6);
|
||||
return do_macro_ctime(buf+6);
|
||||
} else if(strncmp(buf, "range", 5) == 0) {
|
||||
return do_macro_range(buf+6);
|
||||
return do_macro_range(buf+6);
|
||||
}
|
||||
}
|
||||
return strdup(buf);
|
||||
@@ -888,7 +876,7 @@ macro_process(rbtree_type* store, struct replay_runtime* runtime, char* text)
|
||||
return strdup(buf);
|
||||
}
|
||||
|
||||
char*
|
||||
char*
|
||||
macro_lookup(rbtree_type* store, char* name)
|
||||
{
|
||||
struct replay_var* x = macro_getvar(store, name);
|
||||
@@ -904,7 +892,7 @@ void macro_print_debug(rbtree_type* store)
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
int
|
||||
macro_assign(rbtree_type* store, char* name, char* value)
|
||||
{
|
||||
struct replay_var* x = macro_getvar(store, name);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user