mirror of
https://github.com/NLnetLabs/unbound.git
synced 2026-08-17 21:25:50 +02:00
Compare commits
296
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4014e2aec4 | ||
|
|
f3c9be889f | ||
|
|
cd3ebb7e72 | ||
|
|
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 | ||
|
|
5b98816751 | ||
|
|
e93c75a5d4 | ||
|
|
8e18f11965 | ||
|
|
e3871ca907 | ||
|
|
137719522a | ||
|
|
bd3c5702a7 | ||
|
|
f68e252345 | ||
|
|
1e5158045f | ||
|
|
99e12ae4b5 | ||
|
|
5f3b460586 | ||
|
|
9b1647ebae | ||
|
|
307805b64f | ||
|
|
f02d6bddd1 | ||
|
|
eb02170338 | ||
|
|
d301bfe4a2 | ||
|
|
fc123303ac | ||
|
|
aec33b3d63 | ||
|
|
7e9fd2114b | ||
|
|
c30bdff939 | ||
|
|
cfc656294e | ||
|
|
007db2c327 | ||
|
|
5bbaf78c3f | ||
|
|
57230d7f22 | ||
|
|
d66e1cccf8 | ||
|
|
2450b4653a | ||
|
|
eb3378396f | ||
|
|
1f5cc25974 | ||
|
|
ec5812a748 | ||
|
|
10a5a5880a | ||
|
|
2fa1c17cd9 | ||
|
|
e6f878ee71 | ||
|
|
dc6c04b243 | ||
|
|
ef57f8bd51 | ||
|
|
fbe8e3b0b2 | ||
|
|
1c164ab442 | ||
|
|
e738ec31ca | ||
|
|
07b073ddb3 | ||
|
|
0f08cc6d55 | ||
|
|
7d3c6f1c43 | ||
|
|
cd22fdc28d | ||
|
|
5ae48f85c0 | ||
|
|
cbed768b8f | ||
|
|
f6753a0f10 | ||
|
|
efdd70c7b5 | ||
|
|
f993ffbb07 | ||
|
|
ef9bb0213b | ||
|
|
309e23515e | ||
|
|
249efd4285 | ||
|
|
12cd495d55 | ||
|
|
33bd49af81 | ||
|
|
6e50c46102 | ||
|
|
88bf803297 | ||
|
|
9e4a17baaf | ||
|
|
2abd6f7d58 | ||
|
|
7696398231 | ||
|
|
886ffcc155 | ||
|
|
a45ced7739 | ||
|
|
125983558b | ||
|
|
903538c76e | ||
|
|
d447d60fc6 | ||
|
|
e5f66b4902 | ||
|
|
0f4c4c1163 | ||
|
|
eda0c0c194 | ||
|
|
309b1d368b | ||
|
|
c513119bba | ||
|
|
a30286502c | ||
|
|
317bab9f1d | ||
|
|
2fba248ebe | ||
|
|
e102aea751 | ||
|
|
24cb764d61 | ||
|
|
cb28bdcdb0 | ||
|
|
bcf7a8aed2 | ||
|
|
391dd86c3b | ||
|
|
b0ce31b4e4 | ||
|
|
2dbaba7d73 | ||
|
|
923eb7d474 | ||
|
|
58b21e4fca | ||
|
|
ef718f02e4 | ||
|
|
c8add463c4 | ||
|
|
203f606c38 | ||
|
|
e7badb9428 | ||
|
|
b816318106 | ||
|
|
1ceb031b58 | ||
|
|
352e1b28a1 | ||
|
|
80dbc7dd2c | ||
|
|
c8e7539313 | ||
|
|
12796d0af8 | ||
|
|
b057d2127a | ||
|
|
9177867d07 | ||
|
|
9e6b838d0b | ||
|
|
12552fddf0 | ||
|
|
3bade62c8a | ||
|
|
c806b5a2df | ||
|
|
7f67f7118c | ||
|
|
7c9177095f | ||
|
|
233cb5c218 | ||
|
|
e6a0afae73 | ||
|
|
90767fce98 | ||
|
|
187bc72633 | ||
|
|
78b4b12713 | ||
|
|
b8e111e379 | ||
|
|
0e1c266f86 | ||
|
|
c6ef39a22d | ||
|
|
459b73018f | ||
|
|
97b7224885 | ||
|
|
a3ab0921b0 | ||
|
|
16dd802c2e | ||
|
|
6dad2d2fc6 | ||
|
|
edc1d07718 | ||
|
|
2d61706171 | ||
|
|
11d077c826 | ||
|
|
d19d7b81ec | ||
|
|
714200ad0e | ||
|
|
c76420664a | ||
|
|
7e506bb477 | ||
|
|
f73e548934 | ||
|
|
e62b309959 | ||
|
|
2132e67b36 | ||
|
|
0abfddd279 | ||
|
|
ba4564b4ef | ||
|
|
daf316ea1b | ||
|
|
f0d91950ad | ||
|
|
917c30a46a | ||
|
|
77149fc2aa | ||
|
|
47ce372f13 | ||
|
|
0ce36e8289 | ||
|
|
b61b0af5d6 | ||
|
|
6a4ea692d4 | ||
|
|
74c6cf5ac6 | ||
|
|
33c8baaaba | ||
|
|
6cfcf21451 | ||
|
|
1289c53c1a | ||
|
|
d02e83ae2b | ||
|
|
8f2847ba69 | ||
|
|
730a03e9bd | ||
|
|
e4ca71e85b | ||
|
|
8f8a8a341a | ||
|
|
722391baf1 | ||
|
|
ee63ac8f9b | ||
|
|
1e23c4a376 | ||
|
|
c60bed8eef | ||
|
|
9484ddee2e | ||
|
|
402135b41a | ||
|
|
b0dbfa37f9 | ||
|
|
79f8fc1472 | ||
|
|
516f4f9cf4 | ||
|
|
62c5039ab9 | ||
|
|
b202b0874c | ||
|
|
debe5c665f | ||
|
|
f81420d77f | ||
|
|
b8e7dfa01e | ||
|
|
f7ca447368 | ||
|
|
a6880644aa | ||
|
|
0b8e6dafe5 | ||
|
|
99a3f5ee85 | ||
|
|
7749d98a14 | ||
|
|
8e8ccfe3c3 | ||
|
|
ad158ed5cc | ||
|
|
6e79237dc8 | ||
|
|
82adcfb971 | ||
|
|
6e64356175 | ||
|
|
e11cf2d964 | ||
|
|
c084c27b39 | ||
|
|
2c3225e6c7 | ||
|
|
4b772ed571 | ||
|
|
4f3df7ee86 | ||
|
|
c7be51a11b | ||
|
|
c4d8104db3 | ||
|
|
fbbb42c9d4 | ||
|
|
a746d9693a | ||
|
|
78aee89201 | ||
|
|
6de5310728 | ||
|
|
2b90181d3a | ||
|
|
91a5cc9a08 | ||
|
|
a0feea393a | ||
|
|
4c6b59fa47 | ||
|
|
ed4ce7b398 | ||
|
|
58ac43c754 | ||
|
|
5f724da8c5 | ||
|
|
c44fe07a07 | ||
|
|
c29b0e0a96 | ||
|
|
50a312b8da | ||
|
|
893fb4d54b | ||
|
|
6bad577781 | ||
|
|
2642319ea6 | ||
|
|
d123e1c919 | ||
|
|
c53171d942 | ||
|
|
e656be63f9 | ||
|
|
ee3c478239 | ||
|
|
b1feb9fb1e | ||
|
|
819008cf7e | ||
|
|
11f2e7e6ae | ||
|
|
414a37ed2b | ||
|
|
32c3bbd249 | ||
|
|
c6b413069d | ||
|
|
358e3a5963 | ||
|
|
25eae982de | ||
|
|
506d24c7a6 | ||
|
|
d81e1c999b | ||
|
|
a5e9221933 | ||
|
|
1199482372 | ||
|
|
b93aa79a05 | ||
|
|
7ddd456f02 | ||
|
|
814a234876 | ||
|
|
10d9804149 | ||
|
|
a60bbd12ed | ||
|
|
84df46289d | ||
|
|
52283194eb | ||
|
|
c8a6234aac | ||
|
|
3086335724 | ||
|
|
f857af873e | ||
|
|
888eb224a6 | ||
|
|
c49e87e1b7 | ||
|
|
d10562c823 | ||
|
|
54ea2948da | ||
|
|
ea47c08e70 | ||
|
|
79e755e1dd | ||
|
|
ddc3c754b0 | ||
|
|
5c85615515 | ||
|
|
f0c6d26155 | ||
|
|
4573629fc4 | ||
|
|
70f13e54bf | ||
|
|
12a1053dfa | ||
|
|
c3c0186658 | ||
|
|
8e76eb95a0 | ||
|
|
c7ae3ef156 | ||
|
|
2996040c6c | ||
|
|
3c8a79eed8 | ||
|
|
f00d96a21b | ||
|
|
773d1f2911 | ||
|
|
de1e91fc7f | ||
|
|
ff35659d5a | ||
|
|
a97604737b | ||
|
|
d52d94c6db | ||
|
|
370a855f08 | ||
|
|
c7f44b99e3 | ||
|
|
9bbbca5de9 | ||
|
|
33ef79d433 | ||
|
|
eccfe3e1f5 | ||
|
|
adcbb6ced7 | ||
|
|
c678c696a1 | ||
|
|
313bceb983 | ||
|
|
6b2e96430e | ||
|
|
ceef84e022 | ||
|
|
95644c9309 | ||
|
|
cbdc138df7 | ||
|
|
392c1f0f54 | ||
|
|
4e492725e1 | ||
|
|
65113ac775 | ||
|
|
983c716feb | ||
|
|
83c712ca60 | ||
|
|
2c1a5203a5 | ||
|
|
778b50f113 | ||
|
|
d29ab10a34 | ||
|
|
c6c54f9de4 | ||
|
|
c7afaef10c | ||
|
|
9d1eb66f19 | ||
|
|
ef076c0e15 | ||
|
|
56cf526c68 | ||
|
|
4efbee08b5 | ||
|
|
0b362e3a4d |
+20
-9
@@ -57,7 +57,7 @@ LEX=@LEX@
|
||||
STRIP=@STRIP@
|
||||
CC=@CC@
|
||||
CPPFLAGS=-I. @CPPFLAGS@
|
||||
PYTHON_CPPFLAGS=-I. @PYTHON_CPPFLAGS@
|
||||
PYTHON_CPPFLAGS=-I. -I$(srcdir) @PYTHON_CPPFLAGS@
|
||||
CFLAGS=-DSRCDIR=$(srcdir) @CFLAGS@
|
||||
LDFLAGS=@LDFLAGS@
|
||||
LIBS=@LIBS@
|
||||
@@ -130,7 +130,7 @@ 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/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/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 \
|
||||
@@ -148,7 +148,7 @@ 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 \
|
||||
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 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) \
|
||||
@@ -344,7 +344,16 @@ longcheck: longtest
|
||||
test: unittest$(EXEEXT) testbound$(EXEEXT)
|
||||
./unittest$(EXEEXT)
|
||||
./testbound$(EXEEXT) -s
|
||||
for x in $(srcdir)/testdata/*.rpl; do printf "%s" "$$x "; if ./testbound$(EXEEXT) -p $$x >/dev/null 2>&1; then echo OK; else echo failed; exit 1; fi done
|
||||
for x in $(srcdir)/testdata/*.rpl; do \
|
||||
output=`./testbound$(EXEEXT) -p $$x -o -vvvvv 2>&1`; \
|
||||
if test $$? -eq 0; then \
|
||||
printf "%s OK\n" "$$x "; \
|
||||
else \
|
||||
printf "%s\n" "$$output "; \
|
||||
printf "%s failed\n" "$$x "; \
|
||||
exit 1; \
|
||||
fi; \
|
||||
done
|
||||
@echo test OK
|
||||
|
||||
longtest: tests
|
||||
@@ -556,7 +565,7 @@ pythonmod-install:
|
||||
|
||||
pyunbound-install:
|
||||
$(INSTALL) -m 755 -d $(DESTDIR)$(PYTHON_SITE_PKG)
|
||||
$(INSTALL) -c -m 644 $(srcdir)/libunbound/python/unbound.py $(DESTDIR)$(PYTHON_SITE_PKG)/unbound.py
|
||||
$(INSTALL) -c -m 644 libunbound/python/unbound.py $(DESTDIR)$(PYTHON_SITE_PKG)/unbound.py
|
||||
$(LIBTOOL) --mode=install cp _unbound.la $(DESTDIR)$(PYTHON_SITE_PKG)
|
||||
$(LIBTOOL) --mode=finish $(DESTDIR)$(PYTHON_SITE_PKG)
|
||||
|
||||
@@ -583,6 +592,8 @@ install-lib: lib $(UNBOUND_EVENT_INSTALL)
|
||||
echo ".so man3/libunbound.3" > $(DESTDIR)$(mandir)/man3/$$mpage.3 ; \
|
||||
done
|
||||
$(LIBTOOL) --mode=install cp unbound.h $(DESTDIR)$(includedir)/unbound.h
|
||||
$(INSTALL) -m 755 -d $(DESTDIR)$(libdir)/pkgconfig
|
||||
$(INSTALL) -m 644 contrib/libunbound.pc $(DESTDIR)$(libdir)/pkgconfig
|
||||
$(LIBTOOL) --mode=install cp libunbound.la $(DESTDIR)$(libdir)
|
||||
$(LIBTOOL) --mode=finish $(DESTDIR)$(libdir)
|
||||
|
||||
@@ -592,8 +603,6 @@ install-all: all $(PYTHONMOD_INSTALL) $(PYUNBOUND_INSTALL) $(UNBOUND_EVENT_INSTA
|
||||
$(INSTALL) -m 755 -d $(DESTDIR)$(mandir)/man8
|
||||
$(INSTALL) -m 755 -d $(DESTDIR)$(mandir)/man5
|
||||
$(INSTALL) -m 755 -d $(DESTDIR)$(mandir)/man1
|
||||
$(INSTALL) -m 755 -d $(DESTDIR)$(libdir)/pkgconfig
|
||||
$(INSTALL) -m 644 contrib/libunbound.pc $(DESTDIR)$(libdir)/pkgconfig
|
||||
$(LIBTOOL) --mode=install cp -f unbound$(EXEEXT) $(DESTDIR)$(sbindir)/unbound$(EXEEXT)
|
||||
$(LIBTOOL) --mode=install cp -f unbound-checkconf$(EXEEXT) $(DESTDIR)$(sbindir)/unbound-checkconf$(EXEEXT)
|
||||
$(LIBTOOL) --mode=install cp -f unbound-control$(EXEEXT) $(DESTDIR)$(sbindir)/unbound-control$(EXEEXT)
|
||||
@@ -975,6 +984,8 @@ netevent.lo netevent.o: $(srcdir)/util/netevent.c config.h $(srcdir)/util/neteve
|
||||
$(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
|
||||
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 \
|
||||
@@ -1248,7 +1259,7 @@ cachedump.lo cachedump.o: $(srcdir)/daemon/cachedump.c config.h $(srcdir)/daemon
|
||||
$(srcdir)/util/regional.h $(srcdir)/util/net_help.h $(srcdir)/util/data/dname.h $(srcdir)/iterator/iterator.h \
|
||||
$(srcdir)/services/outbound_list.h $(srcdir)/iterator/iter_delegpt.h $(srcdir)/iterator/iter_utils.h \
|
||||
$(srcdir)/iterator/iter_resptype.h $(srcdir)/iterator/iter_fwd.h $(srcdir)/iterator/iter_hints.h \
|
||||
$(srcdir)/sldns/wire2str.h $(srcdir)/sldns/str2wire.h
|
||||
$(srcdir)/sldns/wire2str.h $(srcdir)/sldns/str2wire.h $(srcdir)/util/config_file.h $(srcdir)/services/outside_network.h
|
||||
daemon.lo daemon.o: $(srcdir)/daemon/daemon.c config.h $(srcdir)/daemon/daemon.h $(srcdir)/util/locks.h \
|
||||
$(srcdir)/util/log.h $(srcdir)/util/alloc.h $(srcdir)/services/modstack.h \
|
||||
$(srcdir)/daemon/worker.h $(srcdir)/libunbound/worker.h \
|
||||
@@ -1503,7 +1514,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
|
||||
|
||||
@@ -11,7 +11,7 @@ have any feedback, we would love to hear from you. Don’t hesitate to
|
||||
[create an issue on Github](https://github.com/NLnetLabs/unbound/issues/new)
|
||||
or post a message on the [Unbound mailing list](https://lists.nlnetlabs.nl/mailman/listinfo/unbound-users).
|
||||
You can learn more about Unbound by reading our
|
||||
[documentation](https://nlnetlabs.nl/documentation/unbound/).
|
||||
[documentation](https://unbound.docs.nlnetlabs.nl/).
|
||||
|
||||
## Compiling
|
||||
|
||||
@@ -33,7 +33,7 @@ support.
|
||||
|
||||
All of Unbound's configuration options are described in the man pages, which
|
||||
will be installed and are available on the Unbound
|
||||
[documentation page](https://nlnetlabs.nl/documentation/unbound/).
|
||||
[documentation page](https://unbound.docs.nlnetlabs.nl/).
|
||||
|
||||
An example configuration file is located in
|
||||
[doc/example.conf](https://github.com/NLnetLabs/unbound/blob/master/doc/example.conf.in).
|
||||
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
# Security Policy
|
||||
|
||||
## Supported Versions
|
||||
|
||||
NLnet Labs adheres to the straightforward, semantic versioning scheme that is
|
||||
commonly used in the software industry.
|
||||
|
||||
Support is provided in respect of the latest release, i.e. releases with the
|
||||
highest minor and patch version level. We do not backport security fixes to
|
||||
older (minor) versions. In the event a new major version is released (e.g. from
|
||||
3.2.18 to 4.0.0), support will also be provided on the latest minor version of
|
||||
the previous major version (3.2.18) for a period of one year from the release of
|
||||
the new major version (4.0.0).
|
||||
|
||||
In the event that, during this period, a new patch or minor version of the
|
||||
previous major version is released, then support on these versions will only be
|
||||
provided for the remainder of the one-year-period.
|
||||
|
||||
You can find detailed information on our software support policy here:
|
||||
|
||||
https://www.nlnetlabs.nl/support/software-support-policy/
|
||||
|
||||
## Reporting a Vulnerability
|
||||
|
||||
We take security very seriously. If you have discovered a security vulnerability
|
||||
in one of our projects and you would like to report it to us, you can send an
|
||||
encrypted message to our Security Entry Point.
|
||||
|
||||
Details are described here:
|
||||
|
||||
https://www.nlnetlabs.nl/security-report/
|
||||
+5
-1
@@ -2,7 +2,8 @@
|
||||
# Copyright 2009, Wouter Wijngaards, NLnet Labs.
|
||||
# BSD licensed.
|
||||
#
|
||||
# Version 43
|
||||
# Version 44
|
||||
# 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.
|
||||
@@ -963,6 +964,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
|
||||
|
||||
+40
-17
@@ -18,27 +18,45 @@ AC_DEFUN([AC_PYTHON_DEVEL],[
|
||||
print(sys.version.split()[[0]])"`
|
||||
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
|
||||
# Check if you have sysconfig
|
||||
AC_MSG_CHECKING([for the sysconfig Python module])
|
||||
if ac_sysconfig_result=`$PYTHON -c "import sysconfig" 2>&1`; then
|
||||
AC_MSG_RESULT([yes])
|
||||
else
|
||||
sysconfig_module="sysconfig"
|
||||
# if yes, use sysconfig, because distutils is deprecated.
|
||||
else
|
||||
AC_MSG_RESULT([no])
|
||||
AC_MSG_ERROR([cannot import Python module "distutils".
|
||||
Please check your Python installation. The error was:
|
||||
$ac_distutils_result])
|
||||
PYTHON_VERSION=""
|
||||
fi
|
||||
# if no, try to use distutils
|
||||
|
||||
#
|
||||
# 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
|
||||
AC_MSG_RESULT([yes])
|
||||
else
|
||||
AC_MSG_RESULT([no])
|
||||
AC_MSG_ERROR([cannot import Python module "distutils".
|
||||
Please check your Python installation. The error was:
|
||||
$ac_distutils_result])
|
||||
PYTHON_VERSION=""
|
||||
fi
|
||||
|
||||
sysconfig_module="distutils.sysconfig"
|
||||
fi
|
||||
|
||||
#
|
||||
# Check for Python include path
|
||||
#
|
||||
AC_MSG_CHECKING([for Python include path])
|
||||
if test -z "$PYTHON_CPPFLAGS"; then
|
||||
python_path=`$PYTHON -c "import distutils.sysconfig; \
|
||||
print(distutils.sysconfig.get_python_inc());"`
|
||||
if test "$sysconfig_module" = "sysconfig"; then
|
||||
python_path=`$PYTHON -c 'import sysconfig; \
|
||||
print(sysconfig.get_path("include"));'`
|
||||
else
|
||||
python_path=`$PYTHON -c "import distutils.sysconfig; \
|
||||
print(distutils.sysconfig.get_python_inc());"`
|
||||
fi
|
||||
if test -n "${python_path}"; then
|
||||
python_path="-I$python_path"
|
||||
fi
|
||||
@@ -52,14 +70,14 @@ $ac_distutils_result])
|
||||
#
|
||||
AC_MSG_CHECKING([for Python library path])
|
||||
if test -z "$PYTHON_LDFLAGS"; then
|
||||
PYTHON_LDFLAGS=`$PYTHON -c "from distutils.sysconfig import *; \
|
||||
PYTHON_LDFLAGS=`$PYTHON -c "from $sysconfig_module import *; \
|
||||
print('-L'+get_config_var('LIBDIR')+' -L'+get_config_var('LIBDEST')+' '+get_config_var('BLDLIBRARY'));"`
|
||||
fi
|
||||
AC_MSG_RESULT([$PYTHON_LDFLAGS])
|
||||
AC_SUBST([PYTHON_LDFLAGS])
|
||||
|
||||
if test -z "$PYTHON_LIBDIR"; then
|
||||
PYTHON_LIBDIR=`$PYTHON -c "from distutils.sysconfig import *; \
|
||||
PYTHON_LIBDIR=`$PYTHON -c "from $sysconfig_module import *; \
|
||||
print(get_config_var('LIBDIR'));"`
|
||||
fi
|
||||
|
||||
@@ -68,8 +86,13 @@ $ac_distutils_result])
|
||||
#
|
||||
AC_MSG_CHECKING([for Python site-packages path])
|
||||
if test -z "$PYTHON_SITE_PKG"; then
|
||||
PYTHON_SITE_PKG=`$PYTHON -c "import distutils.sysconfig; \
|
||||
print(distutils.sysconfig.get_python_lib(1,0));"`
|
||||
if test "$sysconfig_module" = "sysconfig"; then
|
||||
PYTHON_SITE_PKG=`$PYTHON -c 'import sysconfig; \
|
||||
print(sysconfig.get_path("platlib"));'`
|
||||
else
|
||||
PYTHON_SITE_PKG=`$PYTHON -c "import distutils.sysconfig; \
|
||||
print(distutils.sysconfig.get_python_lib(1,0));"`
|
||||
fi
|
||||
fi
|
||||
AC_MSG_RESULT([$PYTHON_SITE_PKG])
|
||||
AC_SUBST([PYTHON_SITE_PKG])
|
||||
|
||||
+10
-1
@@ -390,6 +390,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
|
||||
@@ -662,7 +671,7 @@ cachedb_intcache_store(struct module_qstate* qstate)
|
||||
return;
|
||||
(void)dns_cache_store(qstate->env, &qstate->qinfo,
|
||||
qstate->return_msg->rep, 0, qstate->prefetch_leeway, 0,
|
||||
qstate->region, store_flags);
|
||||
qstate->region, store_flags, qstate->qstarttime);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+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
|
||||
|
||||
+27
-1
@@ -222,6 +222,10 @@
|
||||
/* Define to 1 if you have the `EVP_cleanup' function. */
|
||||
#undef HAVE_EVP_CLEANUP
|
||||
|
||||
/* Define to 1 if you have the `EVP_default_properties_is_fips_enabled'
|
||||
function. */
|
||||
#undef HAVE_EVP_DEFAULT_PROPERTIES_IS_FIPS_ENABLED
|
||||
|
||||
/* Define to 1 if you have the `EVP_DigestVerify' function. */
|
||||
#undef HAVE_EVP_DIGESTVERIFY
|
||||
|
||||
@@ -294,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
|
||||
|
||||
@@ -381,6 +388,9 @@
|
||||
/* Define to 1 if you have the <netinet/tcp.h> header file. */
|
||||
#undef HAVE_NETINET_TCP_H
|
||||
|
||||
/* Define to 1 if you have the <netioapi.h> header file. */
|
||||
#undef HAVE_NETIOAPI_H
|
||||
|
||||
/* Use libnettle for crypto */
|
||||
#undef HAVE_NETTLE
|
||||
|
||||
@@ -450,6 +460,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
|
||||
|
||||
@@ -793,12 +809,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
|
||||
|
||||
@@ -968,6 +990,10 @@
|
||||
/* Define to 1 if you need to in order for `stat' and other things to work. */
|
||||
#undef _POSIX_SOURCE
|
||||
|
||||
/* defined to use gcc ansi snprintf and sscanf that understands %lld when
|
||||
compiled for windows. */
|
||||
#undef __USE_MINGW_ANSI_STDIO
|
||||
|
||||
/* Define to empty if `const' does not conform to ANSI C. */
|
||||
#undef const
|
||||
|
||||
@@ -1147,7 +1173,7 @@
|
||||
#include <ws2tcpip.h>
|
||||
#endif
|
||||
|
||||
#ifndef USE_WINSOCK
|
||||
#if !defined(USE_WINSOCK) || !defined(HAVE_SNPRINTF) || defined(SNPRINTF_RET_BROKEN) || defined(__USE_MINGW_ANSI_STDIO)
|
||||
#define ARG_LL "%ll"
|
||||
#else
|
||||
#define ARG_LL "%I64"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#! /bin/sh
|
||||
# Guess values for system-dependent variables and create Makefiles.
|
||||
# Generated by GNU Autoconf 2.69 for unbound 1.14.0.
|
||||
# Generated by GNU Autoconf 2.69 for unbound 1.17.1.
|
||||
#
|
||||
# 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.14.0'
|
||||
PACKAGE_STRING='unbound 1.14.0'
|
||||
PACKAGE_VERSION='1.17.1'
|
||||
PACKAGE_STRING='unbound 1.17.1'
|
||||
PACKAGE_BUGREPORT='unbound-bugs@nlnetlabs.nl or https://github.com/NLnetLabs/unbound/issues'
|
||||
PACKAGE_URL=''
|
||||
|
||||
@@ -813,6 +813,7 @@ infodir
|
||||
docdir
|
||||
oldincludedir
|
||||
includedir
|
||||
runstatedir
|
||||
localstatedir
|
||||
sharedstatedir
|
||||
sysconfdir
|
||||
@@ -964,6 +965,7 @@ datadir='${datarootdir}'
|
||||
sysconfdir='${prefix}/etc'
|
||||
sharedstatedir='${prefix}/com'
|
||||
localstatedir='${prefix}/var'
|
||||
runstatedir='${localstatedir}/run'
|
||||
includedir='${prefix}/include'
|
||||
oldincludedir='/usr/include'
|
||||
docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
|
||||
@@ -1216,6 +1218,15 @@ do
|
||||
| -silent | --silent | --silen | --sile | --sil)
|
||||
silent=yes ;;
|
||||
|
||||
-runstatedir | --runstatedir | --runstatedi | --runstated \
|
||||
| --runstate | --runstat | --runsta | --runst | --runs \
|
||||
| --run | --ru | --r)
|
||||
ac_prev=runstatedir ;;
|
||||
-runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \
|
||||
| --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \
|
||||
| --run=* | --ru=* | --r=*)
|
||||
runstatedir=$ac_optarg ;;
|
||||
|
||||
-sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
|
||||
ac_prev=sbindir ;;
|
||||
-sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
|
||||
@@ -1353,7 +1364,7 @@ fi
|
||||
for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \
|
||||
datadir sysconfdir sharedstatedir localstatedir includedir \
|
||||
oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
|
||||
libdir localedir mandir
|
||||
libdir localedir mandir runstatedir
|
||||
do
|
||||
eval ac_val=\$$ac_var
|
||||
# Remove trailing slashes.
|
||||
@@ -1466,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.14.0 to adapt to many kinds of systems.
|
||||
\`configure' configures unbound 1.17.1 to adapt to many kinds of systems.
|
||||
|
||||
Usage: $0 [OPTION]... [VAR=VALUE]...
|
||||
|
||||
@@ -1506,6 +1517,7 @@ Fine tuning of the installation directories:
|
||||
--sysconfdir=DIR read-only single-machine data [PREFIX/etc]
|
||||
--sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]
|
||||
--localstatedir=DIR modifiable single-machine data [PREFIX/var]
|
||||
--runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run]
|
||||
--libdir=DIR object code libraries [EPREFIX/lib]
|
||||
--includedir=DIR C header files [PREFIX/include]
|
||||
--oldincludedir=DIR C header files for non-gcc [/usr/include]
|
||||
@@ -1531,7 +1543,7 @@ fi
|
||||
|
||||
if test -n "$ac_init_help"; then
|
||||
case $ac_init_help in
|
||||
short | recursive ) echo "Configuration of unbound 1.14.0:";;
|
||||
short | recursive ) echo "Configuration of unbound 1.17.1:";;
|
||||
esac
|
||||
cat <<\_ACEOF
|
||||
|
||||
@@ -1773,7 +1785,7 @@ fi
|
||||
test -n "$ac_init_help" && exit $ac_status
|
||||
if $ac_init_version; then
|
||||
cat <<\_ACEOF
|
||||
unbound configure 1.14.0
|
||||
unbound configure 1.17.1
|
||||
generated by GNU Autoconf 2.69
|
||||
|
||||
Copyright (C) 2012 Free Software Foundation, Inc.
|
||||
@@ -2482,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.14.0, which was
|
||||
It was created by unbound $as_me 1.17.1, which was
|
||||
generated by GNU Autoconf 2.69. Invocation command line was
|
||||
|
||||
$ $0 $@
|
||||
@@ -2832,13 +2844,13 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
|
||||
|
||||
UNBOUND_VERSION_MAJOR=1
|
||||
|
||||
UNBOUND_VERSION_MINOR=14
|
||||
UNBOUND_VERSION_MINOR=17
|
||||
|
||||
UNBOUND_VERSION_MICRO=0
|
||||
UNBOUND_VERSION_MICRO=1
|
||||
|
||||
|
||||
LIBUNBOUND_CURRENT=9
|
||||
LIBUNBOUND_REVISION=14
|
||||
LIBUNBOUND_REVISION=21
|
||||
LIBUNBOUND_AGE=1
|
||||
# 1.0.0 had 0:12:0
|
||||
# 1.0.1 had 0:13:0
|
||||
@@ -2920,6 +2932,13 @@ LIBUNBOUND_AGE=1
|
||||
# 1.13.1 had 9:12:1
|
||||
# 1.13.2 had 9:13:1
|
||||
# 1.14.0 had 9:14:1
|
||||
# 1.15.0 had 9:15: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
|
||||
|
||||
# Current -- the number of the binary API that we're implementing
|
||||
# Revision -- which iteration of the implementation of the binary
|
||||
@@ -14755,7 +14774,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
|
||||
@@ -14812,6 +14831,51 @@ fi
|
||||
|
||||
done
|
||||
|
||||
for ac_header in netioapi.h
|
||||
do :
|
||||
ac_fn_c_check_header_compile "$LINENO" "netioapi.h" "ac_cv_header_netioapi_h" "$ac_includes_default
|
||||
#if HAVE_SYS_PARAM_H
|
||||
#include <sys/param.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SYS_SOCKET_H
|
||||
#include <sys/socket.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SYS_UIO_H
|
||||
#include <sys/uio.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_NETINET_IN_H
|
||||
#include <netinet/in.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_NETINET_TCP_H
|
||||
#include <netinet/tcp.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_ARPA_INET_H
|
||||
#include <arpa/inet.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_WINSOCK2_H
|
||||
#include <winsock2.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_WS2TCPIP_H
|
||||
#include <ws2tcpip.h>
|
||||
#endif
|
||||
|
||||
"
|
||||
if test "x$ac_cv_header_netioapi_h" = xyes; then :
|
||||
cat >>confdefs.h <<_ACEOF
|
||||
#define HAVE_NETIOAPI_H 1
|
||||
_ACEOF
|
||||
|
||||
fi
|
||||
|
||||
done
|
||||
|
||||
|
||||
# check for types.
|
||||
# Using own tests for int64* because autoconf builtin only give 32bit.
|
||||
@@ -15969,6 +16033,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
|
||||
@@ -17039,6 +17106,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
|
||||
@@ -17409,22 +17542,38 @@ fi
|
||||
print(sys.version.split()[0])"`
|
||||
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
|
||||
# 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
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
|
||||
$as_echo "yes" >&6; }
|
||||
else
|
||||
sysconfig_module="sysconfig"
|
||||
# if yes, use sysconfig, because distutils is deprecated.
|
||||
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
|
||||
PYTHON_VERSION=""
|
||||
fi
|
||||
# if no, try to use distutils
|
||||
|
||||
#
|
||||
# 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
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
|
||||
$as_echo "yes" >&6; }
|
||||
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
|
||||
PYTHON_VERSION=""
|
||||
fi
|
||||
|
||||
sysconfig_module="distutils.sysconfig"
|
||||
fi
|
||||
|
||||
#
|
||||
# Check for Python include path
|
||||
@@ -17432,8 +17581,13 @@ $ac_distutils_result" "$LINENO" 5
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for Python include path" >&5
|
||||
$as_echo_n "checking for Python include path... " >&6; }
|
||||
if test -z "$PYTHON_CPPFLAGS"; then
|
||||
python_path=`$PYTHON -c "import distutils.sysconfig; \
|
||||
print(distutils.sysconfig.get_python_inc());"`
|
||||
if test "$sysconfig_module" = "sysconfig"; then
|
||||
python_path=`$PYTHON -c 'import sysconfig; \
|
||||
print(sysconfig.get_path("include"));'`
|
||||
else
|
||||
python_path=`$PYTHON -c "import distutils.sysconfig; \
|
||||
print(distutils.sysconfig.get_python_inc());"`
|
||||
fi
|
||||
if test -n "${python_path}"; then
|
||||
python_path="-I$python_path"
|
||||
fi
|
||||
@@ -17449,7 +17603,7 @@ $as_echo "$PYTHON_CPPFLAGS" >&6; }
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for Python library path" >&5
|
||||
$as_echo_n "checking for Python library path... " >&6; }
|
||||
if test -z "$PYTHON_LDFLAGS"; then
|
||||
PYTHON_LDFLAGS=`$PYTHON -c "from distutils.sysconfig import *; \
|
||||
PYTHON_LDFLAGS=`$PYTHON -c "from $sysconfig_module import *; \
|
||||
print('-L'+get_config_var('LIBDIR')+' -L'+get_config_var('LIBDEST')+' '+get_config_var('BLDLIBRARY'));"`
|
||||
fi
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $PYTHON_LDFLAGS" >&5
|
||||
@@ -17457,7 +17611,7 @@ $as_echo "$PYTHON_LDFLAGS" >&6; }
|
||||
|
||||
|
||||
if test -z "$PYTHON_LIBDIR"; then
|
||||
PYTHON_LIBDIR=`$PYTHON -c "from distutils.sysconfig import *; \
|
||||
PYTHON_LIBDIR=`$PYTHON -c "from $sysconfig_module import *; \
|
||||
print(get_config_var('LIBDIR'));"`
|
||||
fi
|
||||
|
||||
@@ -17467,8 +17621,13 @@ $as_echo "$PYTHON_LDFLAGS" >&6; }
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for Python site-packages path" >&5
|
||||
$as_echo_n "checking for Python site-packages path... " >&6; }
|
||||
if test -z "$PYTHON_SITE_PKG"; then
|
||||
PYTHON_SITE_PKG=`$PYTHON -c "import distutils.sysconfig; \
|
||||
print(distutils.sysconfig.get_python_lib(1,0));"`
|
||||
if test "$sysconfig_module" = "sysconfig"; then
|
||||
PYTHON_SITE_PKG=`$PYTHON -c 'import sysconfig; \
|
||||
print(sysconfig.get_path("platlib"));'`
|
||||
else
|
||||
PYTHON_SITE_PKG=`$PYTHON -c "import distutils.sysconfig; \
|
||||
print(distutils.sysconfig.get_python_lib(1,0));"`
|
||||
fi
|
||||
fi
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $PYTHON_SITE_PKG" >&5
|
||||
$as_echo "$PYTHON_SITE_PKG" >&6; }
|
||||
@@ -17895,7 +18054,7 @@ if test "`uname`" = "NetBSD"; then
|
||||
|
||||
fi
|
||||
|
||||
if test "`uname -o`" = "GNU/Linux"; then
|
||||
if test "`uname`" = "Linux"; then
|
||||
# splint cannot parse modern c99 header files
|
||||
GCC_DOCKER_LINTFLAGS='-syntax'
|
||||
|
||||
@@ -18460,7 +18619,7 @@ fi
|
||||
|
||||
done
|
||||
|
||||
for ac_func in OPENSSL_config EVP_sha1 EVP_sha256 EVP_sha512 FIPS_mode EVP_MD_CTX_new OpenSSL_add_all_digests OPENSSL_init_crypto EVP_cleanup ENGINE_cleanup ERR_load_crypto_strings CRYPTO_cleanup_all_ex_data ERR_free_strings RAND_cleanup DSA_SIG_set0 EVP_dss1 EVP_DigestVerify EVP_aes_256_cbc EVP_EncryptInit_ex HMAC_Init_ex CRYPTO_THREADID_set_callback EVP_MAC_CTX_set_params OSSL_PARAM_BLD_new BIO_set_callback_ex
|
||||
for ac_func in OPENSSL_config EVP_sha1 EVP_sha256 EVP_sha512 FIPS_mode EVP_default_properties_is_fips_enabled EVP_MD_CTX_new OpenSSL_add_all_digests OPENSSL_init_crypto EVP_cleanup ENGINE_cleanup ERR_load_crypto_strings CRYPTO_cleanup_all_ex_data ERR_free_strings RAND_cleanup DSA_SIG_set0 EVP_dss1 EVP_DigestVerify EVP_aes_256_cbc EVP_EncryptInit_ex HMAC_Init_ex CRYPTO_THREADID_set_callback EVP_MAC_CTX_set_params OSSL_PARAM_BLD_new BIO_set_callback_ex
|
||||
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"
|
||||
@@ -19882,7 +20041,46 @@ if test x_$enable_static_exe = x_yes; then
|
||||
else
|
||||
LIBS="$LIBS -lgdi32"
|
||||
fi
|
||||
LIBS="$LIBS -lz"
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for compress in -lz" >&5
|
||||
$as_echo_n "checking for compress in -lz... " >&6; }
|
||||
if ${ac_cv_lib_z_compress+:} false; then :
|
||||
$as_echo_n "(cached) " >&6
|
||||
else
|
||||
ac_check_lib_save_LIBS=$LIBS
|
||||
LIBS="-lz $LIBS"
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
|
||||
/* Override any GCC internal prototype to avoid an error.
|
||||
Use char because int might match the return type of a GCC
|
||||
builtin and then its argument prototype would still apply. */
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
#endif
|
||||
char compress ();
|
||||
int
|
||||
main ()
|
||||
{
|
||||
return compress ();
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
if ac_fn_c_try_link "$LINENO"; then :
|
||||
ac_cv_lib_z_compress=yes
|
||||
else
|
||||
ac_cv_lib_z_compress=no
|
||||
fi
|
||||
rm -f core conftest.err conftest.$ac_objext \
|
||||
conftest$ac_exeext conftest.$ac_ext
|
||||
LIBS=$ac_check_lib_save_LIBS
|
||||
fi
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_z_compress" >&5
|
||||
$as_echo "$ac_cv_lib_z_compress" >&6; }
|
||||
if test "x$ac_cv_lib_z_compress" = xyes; then :
|
||||
LIBS="$LIBS -lz"
|
||||
fi
|
||||
|
||||
LIBS="$LIBS -l:libssp.a"
|
||||
fi
|
||||
fi
|
||||
@@ -19902,7 +20100,46 @@ if test x_$enable_fully_static = x_yes; then
|
||||
else
|
||||
LIBS="$LIBS -lgdi32"
|
||||
fi
|
||||
LIBS="$LIBS -lz"
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for compress in -lz" >&5
|
||||
$as_echo_n "checking for compress in -lz... " >&6; }
|
||||
if ${ac_cv_lib_z_compress+:} false; then :
|
||||
$as_echo_n "(cached) " >&6
|
||||
else
|
||||
ac_check_lib_save_LIBS=$LIBS
|
||||
LIBS="-lz $LIBS"
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
|
||||
/* Override any GCC internal prototype to avoid an error.
|
||||
Use char because int might match the return type of a GCC
|
||||
builtin and then its argument prototype would still apply. */
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
#endif
|
||||
char compress ();
|
||||
int
|
||||
main ()
|
||||
{
|
||||
return compress ();
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
if ac_fn_c_try_link "$LINENO"; then :
|
||||
ac_cv_lib_z_compress=yes
|
||||
else
|
||||
ac_cv_lib_z_compress=no
|
||||
fi
|
||||
rm -f core conftest.err conftest.$ac_objext \
|
||||
conftest$ac_exeext conftest.$ac_ext
|
||||
LIBS=$ac_check_lib_save_LIBS
|
||||
fi
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_z_compress" >&5
|
||||
$as_echo "$ac_cv_lib_z_compress" >&6; }
|
||||
if test "x$ac_cv_lib_z_compress" = xyes; then :
|
||||
LIBS="$LIBS -lz"
|
||||
fi
|
||||
|
||||
LIBS="$LIBS -l:libssp.a"
|
||||
fi
|
||||
fi
|
||||
@@ -20135,6 +20372,9 @@ fi
|
||||
|
||||
WIN_CHECKCONF_OBJ_LINK="rsrc_unbound_checkconf.o"
|
||||
|
||||
|
||||
$as_echo "#define __USE_MINGW_ANSI_STDIO 1" >>confdefs.h
|
||||
|
||||
fi
|
||||
if test $ac_cv_func_getaddrinfo = no; then
|
||||
case " $LIBOBJS " in
|
||||
@@ -20422,7 +20662,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"
|
||||
@@ -21632,10 +21872,16 @@ $as_echo_n "checking for libmnl... " >&6; }
|
||||
withval="/usr/local /opt/local /usr/lib /usr/pkg /usr/sfw /usr"
|
||||
fi
|
||||
for dir in $withval ; do
|
||||
if test -f "$dir/include/libmnl/libmnl.h"; then
|
||||
if test -f "$dir/include/libmnl/libmnl.h" -o -f "$dir/include/libmnl/libmnl/libmnl.h"; then
|
||||
found_libmnl="yes"
|
||||
if test "$dir" != "/usr"; then
|
||||
CPPFLAGS="$CPPFLAGS -I$dir/include"
|
||||
extralibmnl=""
|
||||
if test -f "$dir/include/libmnl/libmnl/libmnl.h"; then
|
||||
extralibmnl="/libmnl"
|
||||
fi
|
||||
if test "$dir" != "/usr" -o -n "$extralibmnl"; then
|
||||
CPPFLAGS="$CPPFLAGS -I$dir/include$extralibmnl"
|
||||
fi
|
||||
if test "$dir" != "/usr"; then
|
||||
LDFLAGS="$LDFLAGS -L$dir/lib"
|
||||
fi
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: found in $dir" >&5
|
||||
@@ -21840,7 +22086,7 @@ _ACEOF
|
||||
|
||||
|
||||
|
||||
version=1.14.0
|
||||
version=1.17.1
|
||||
|
||||
date=`date +'%b %e, %Y'`
|
||||
|
||||
@@ -22359,7 +22605,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.14.0, which was
|
||||
This file was extended by unbound $as_me 1.17.1, which was
|
||||
generated by GNU Autoconf 2.69. Invocation command line was
|
||||
|
||||
CONFIG_FILES = $CONFIG_FILES
|
||||
@@ -22425,7 +22671,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.14.0
|
||||
unbound config.status 1.17.1
|
||||
configured by $0, generated by GNU Autoconf 2.69,
|
||||
with options \\"\$ac_cs_config\\"
|
||||
|
||||
|
||||
+61
-12
@@ -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],[14])
|
||||
m4_define([VERSION_MICRO],[0])
|
||||
m4_define([VERSION_MINOR],[17])
|
||||
m4_define([VERSION_MICRO],[1])
|
||||
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=14
|
||||
LIBUNBOUND_REVISION=21
|
||||
LIBUNBOUND_AGE=1
|
||||
# 1.0.0 had 0:12:0
|
||||
# 1.0.1 had 0:13:0
|
||||
@@ -100,6 +100,13 @@ LIBUNBOUND_AGE=1
|
||||
# 1.13.1 had 9:12:1
|
||||
# 1.13.2 had 9:13:1
|
||||
# 1.14.0 had 9:14:1
|
||||
# 1.15.0 had 9:15: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
|
||||
|
||||
# Current -- the number of the binary API that we're implementing
|
||||
# Revision -- which iteration of the implementation of the binary
|
||||
@@ -392,7 +399,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],,, [
|
||||
@@ -412,6 +419,39 @@ AC_CHECK_HEADERS([net/if.h],,, [
|
||||
|
||||
# Check for Apple header. This uncovers TARGET_OS_IPHONE, TARGET_OS_TV or TARGET_OS_WATCH
|
||||
AC_CHECK_HEADERS([TargetConditionals.h],,, [AC_INCLUDES_DEFAULT])
|
||||
AC_CHECK_HEADERS([netioapi.h],,, [AC_INCLUDES_DEFAULT
|
||||
#if HAVE_SYS_PARAM_H
|
||||
#include <sys/param.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SYS_SOCKET_H
|
||||
#include <sys/socket.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SYS_UIO_H
|
||||
#include <sys/uio.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_NETINET_IN_H
|
||||
#include <netinet/in.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_NETINET_TCP_H
|
||||
#include <netinet/tcp.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_ARPA_INET_H
|
||||
#include <arpa/inet.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_WINSOCK2_H
|
||||
#include <winsock2.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_WS2TCPIP_H
|
||||
#include <ws2tcpip.h>
|
||||
#endif
|
||||
])
|
||||
|
||||
# check for types.
|
||||
# Using own tests for int64* because autoconf builtin only give 32bit.
|
||||
@@ -569,6 +609,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])
|
||||
@@ -782,7 +824,7 @@ if test "`uname`" = "NetBSD"; then
|
||||
AC_SUBST(NETBSD_LINTFLAGS)
|
||||
fi
|
||||
|
||||
if test "`uname -o`" = "GNU/Linux"; then
|
||||
if test "`uname`" = "Linux"; then
|
||||
# splint cannot parse modern c99 header files
|
||||
GCC_DOCKER_LINTFLAGS='-syntax'
|
||||
AC_SUBST(GCC_DOCKER_LINTFLAGS)
|
||||
@@ -871,7 +913,7 @@ else
|
||||
AC_MSG_RESULT([no])
|
||||
fi
|
||||
AC_CHECK_HEADERS([openssl/conf.h openssl/engine.h openssl/bn.h openssl/dh.h openssl/dsa.h openssl/rsa.h openssl/core_names.h openssl/param_build.h],,, [AC_INCLUDES_DEFAULT])
|
||||
AC_CHECK_FUNCS([OPENSSL_config EVP_sha1 EVP_sha256 EVP_sha512 FIPS_mode EVP_MD_CTX_new OpenSSL_add_all_digests OPENSSL_init_crypto EVP_cleanup ENGINE_cleanup ERR_load_crypto_strings CRYPTO_cleanup_all_ex_data ERR_free_strings RAND_cleanup DSA_SIG_set0 EVP_dss1 EVP_DigestVerify EVP_aes_256_cbc EVP_EncryptInit_ex HMAC_Init_ex CRYPTO_THREADID_set_callback EVP_MAC_CTX_set_params OSSL_PARAM_BLD_new BIO_set_callback_ex])
|
||||
AC_CHECK_FUNCS([OPENSSL_config EVP_sha1 EVP_sha256 EVP_sha512 FIPS_mode EVP_default_properties_is_fips_enabled EVP_MD_CTX_new OpenSSL_add_all_digests OPENSSL_init_crypto EVP_cleanup ENGINE_cleanup ERR_load_crypto_strings CRYPTO_cleanup_all_ex_data ERR_free_strings RAND_cleanup DSA_SIG_set0 EVP_dss1 EVP_DigestVerify EVP_aes_256_cbc EVP_EncryptInit_ex HMAC_Init_ex CRYPTO_THREADID_set_callback EVP_MAC_CTX_set_params OSSL_PARAM_BLD_new BIO_set_callback_ex])
|
||||
|
||||
# these check_funcs need -lssl
|
||||
BAKLIBS="$LIBS"
|
||||
@@ -1464,7 +1506,7 @@ if test x_$enable_static_exe = x_yes; then
|
||||
else
|
||||
LIBS="$LIBS -lgdi32"
|
||||
fi
|
||||
LIBS="$LIBS -lz"
|
||||
AC_CHECK_LIB([z], [compress], [ LIBS="$LIBS -lz" ])
|
||||
LIBS="$LIBS -l:libssp.a"
|
||||
fi
|
||||
fi
|
||||
@@ -1481,7 +1523,7 @@ if test x_$enable_fully_static = x_yes; then
|
||||
else
|
||||
LIBS="$LIBS -lgdi32"
|
||||
fi
|
||||
LIBS="$LIBS -lz"
|
||||
AC_CHECK_LIB([z], [compress], [ LIBS="$LIBS -lz" ])
|
||||
LIBS="$LIBS -l:libssp.a"
|
||||
fi
|
||||
fi
|
||||
@@ -1519,6 +1561,7 @@ if test "$USE_WINSOCK" = 1; then
|
||||
AC_SUBST(WIN_CONTROL_OBJ_LINK)
|
||||
WIN_CHECKCONF_OBJ_LINK="rsrc_unbound_checkconf.o"
|
||||
AC_SUBST(WIN_CHECKCONF_OBJ_LINK)
|
||||
AC_DEFINE(__USE_MINGW_ANSI_STDIO, 1, [defined to use gcc ansi snprintf and sscanf that understands %lld when compiled for windows.])
|
||||
fi
|
||||
if test $ac_cv_func_getaddrinfo = no; then
|
||||
AC_LIBOBJ([fake-rfc2553])
|
||||
@@ -1605,7 +1648,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])])
|
||||
|
||||
@@ -1844,11 +1887,17 @@ case "$enable_ipset" in
|
||||
withval="/usr/local /opt/local /usr/lib /usr/pkg /usr/sfw /usr"
|
||||
fi
|
||||
for dir in $withval ; do
|
||||
if test -f "$dir/include/libmnl/libmnl.h"; then
|
||||
if test -f "$dir/include/libmnl/libmnl.h" -o -f "$dir/include/libmnl/libmnl/libmnl.h"; then
|
||||
found_libmnl="yes"
|
||||
dnl assume /usr is in default path.
|
||||
extralibmnl=""
|
||||
if test -f "$dir/include/libmnl/libmnl/libmnl.h"; then
|
||||
extralibmnl="/libmnl"
|
||||
fi
|
||||
if test "$dir" != "/usr" -o -n "$extralibmnl"; then
|
||||
CPPFLAGS="$CPPFLAGS -I$dir/include$extralibmnl"
|
||||
fi
|
||||
if test "$dir" != "/usr"; then
|
||||
CPPFLAGS="$CPPFLAGS -I$dir/include"
|
||||
LDFLAGS="$LDFLAGS -L$dir/lib"
|
||||
fi
|
||||
AC_MSG_RESULT(found in $dir)
|
||||
@@ -2026,7 +2075,7 @@ dnl includes
|
||||
#include <ws2tcpip.h>
|
||||
#endif
|
||||
|
||||
#ifndef USE_WINSOCK
|
||||
#if !defined(USE_WINSOCK) || !defined(HAVE_SNPRINTF) || defined(SNPRINTF_RET_BROKEN) || defined(__USE_MINGW_ANSI_STDIO)
|
||||
#define ARG_LL "%ll"
|
||||
#else
|
||||
#define ARG_LL "%I64"
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
diff --git a/doc/unbound.conf.5.in b/doc/unbound.conf.5.in
|
||||
index f426ac5f..147fbfa9 100644
|
||||
index 5a75e319..c6c6dbe2 100644
|
||||
--- a/doc/unbound.conf.5.in
|
||||
+++ b/doc/unbound.conf.5.in
|
||||
@@ -872,6 +872,13 @@ potentially broken nameservers. A lot of domains will not be resolvable when
|
||||
@@ -970,6 +970,13 @@ potentially broken nameservers. A lot of domains will not be resolvable when
|
||||
this option in enabled. Only use if you know what you are doing.
|
||||
This option only has effect when qname-minimisation is enabled. Default is no.
|
||||
.TP
|
||||
@@ -17,10 +17,10 @@ index f426ac5f..147fbfa9 100644
|
||||
Aggressive NSEC uses the DNSSEC NSEC chain to synthesize NXDOMAIN
|
||||
and other denials, using information from previous NXDOMAINs answers.
|
||||
diff --git a/iterator/iter_scrub.c b/iterator/iter_scrub.c
|
||||
index aae934dd..55c55de0 100644
|
||||
index f093c1bf..e55a2246 100644
|
||||
--- a/iterator/iter_scrub.c
|
||||
+++ b/iterator/iter_scrub.c
|
||||
@@ -667,6 +667,32 @@ static int sanitize_nsec_is_overreach(struct rrset_parse* rrset,
|
||||
@@ -679,6 +679,32 @@ static int sanitize_nsec_is_overreach(sldns_buffer* pkt,
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -53,7 +53,7 @@ index aae934dd..55c55de0 100644
|
||||
/**
|
||||
* Given a response event, remove suspect RRsets from the response.
|
||||
* "Suspect" rrsets are potentially poison. Note that this routine expects
|
||||
@@ -686,6 +712,7 @@ scrub_sanitize(sldns_buffer* pkt, struct msg_parse* msg,
|
||||
@@ -698,6 +724,7 @@ scrub_sanitize(sldns_buffer* pkt, struct msg_parse* msg,
|
||||
struct query_info* qinfo, uint8_t* zonename, struct module_env* env,
|
||||
struct iter_env* ie)
|
||||
{
|
||||
@@ -61,7 +61,7 @@ index aae934dd..55c55de0 100644
|
||||
int del_addi = 0; /* if additional-holding rrsets are deleted, we
|
||||
do not trust the normalized additional-A-AAAA any more */
|
||||
struct rrset_parse* rrset, *prev;
|
||||
@@ -721,6 +748,13 @@ scrub_sanitize(sldns_buffer* pkt, struct msg_parse* msg,
|
||||
@@ -733,6 +760,13 @@ scrub_sanitize(sldns_buffer* pkt, struct msg_parse* msg,
|
||||
rrset = rrset->rrset_all_next;
|
||||
}
|
||||
|
||||
@@ -75,7 +75,7 @@ index aae934dd..55c55de0 100644
|
||||
/* At this point, we brutally remove ALL rrsets that aren't
|
||||
* children of the originating zone. The idea here is that,
|
||||
* as far as we know, the server that we contacted is ONLY
|
||||
@@ -732,6 +766,24 @@ scrub_sanitize(sldns_buffer* pkt, struct msg_parse* msg,
|
||||
@@ -744,6 +778,24 @@ scrub_sanitize(sldns_buffer* pkt, struct msg_parse* msg,
|
||||
rrset = msg->rrset_first;
|
||||
while(rrset) {
|
||||
|
||||
@@ -101,22 +101,22 @@ index aae934dd..55c55de0 100644
|
||||
if( (rrset->type == LDNS_RR_TYPE_A ||
|
||||
rrset->type == LDNS_RR_TYPE_AAAA)) {
|
||||
diff --git a/iterator/iter_utils.c b/iterator/iter_utils.c
|
||||
index 7bc67da6..e10f547a 100644
|
||||
index 2482a1f4..bd5ba243 100644
|
||||
--- a/iterator/iter_utils.c
|
||||
+++ b/iterator/iter_utils.c
|
||||
@@ -175,6 +175,7 @@ iter_apply_cfg(struct iter_env* iter_env, struct config_file* cfg)
|
||||
}
|
||||
@@ -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->aaaa_filter = cfg->aaaa_filter;
|
||||
return 1;
|
||||
}
|
||||
|
||||
diff --git a/iterator/iterator.c b/iterator/iterator.c
|
||||
index 23b07ea9..ca29b48c 100644
|
||||
index 54006940..768fe202 100644
|
||||
--- a/iterator/iterator.c
|
||||
+++ b/iterator/iterator.c
|
||||
@@ -2127,6 +2127,53 @@ processDSNSFind(struct module_qstate* qstate, struct iter_qstate* iq, int id)
|
||||
@@ -2155,6 +2155,53 @@ processDSNSFind(struct module_qstate* qstate, struct iter_qstate* iq, int id)
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -170,7 +170,7 @@ index 23b07ea9..ca29b48c 100644
|
||||
|
||||
/**
|
||||
* This is the request event state where the request will be sent to one of
|
||||
@@ -2186,6 +2233,13 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
@@ -2216,6 +2263,13 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
|
||||
}
|
||||
|
||||
@@ -184,7 +184,7 @@ index 23b07ea9..ca29b48c 100644
|
||||
/* Make sure we have a delegation point, otherwise priming failed
|
||||
* or another failure occurred */
|
||||
if(!iq->dp) {
|
||||
@@ -3574,6 +3628,61 @@ processFinished(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
@@ -3648,6 +3702,61 @@ processFinished(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -246,7 +246,7 @@ index 23b07ea9..ca29b48c 100644
|
||||
/*
|
||||
* Return priming query results to interested super querystates.
|
||||
*
|
||||
@@ -3593,6 +3702,9 @@ iter_inform_super(struct module_qstate* qstate, int id,
|
||||
@@ -3667,6 +3776,9 @@ iter_inform_super(struct module_qstate* qstate, int id,
|
||||
else if(super->qinfo.qtype == LDNS_RR_TYPE_DS && ((struct iter_qstate*)
|
||||
super->minfo[id])->state == DSNS_FIND_STATE)
|
||||
processDSNSResponse(qstate, id, super);
|
||||
@@ -256,7 +256,7 @@ index 23b07ea9..ca29b48c 100644
|
||||
else if(qstate->return_rcode != LDNS_RCODE_NOERROR)
|
||||
error_supers(qstate, id, super);
|
||||
else if(qstate->is_priming)
|
||||
@@ -3630,6 +3742,9 @@ iter_handle(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
@@ -3704,6 +3816,9 @@ iter_handle(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
case INIT_REQUEST_3_STATE:
|
||||
cont = processInitRequest3(qstate, iq, id);
|
||||
break;
|
||||
@@ -266,7 +266,7 @@ index 23b07ea9..ca29b48c 100644
|
||||
case QUERYTARGETS_STATE:
|
||||
cont = processQueryTargets(qstate, iq, ie, id);
|
||||
break;
|
||||
@@ -3961,6 +4076,8 @@ iter_state_to_string(enum iter_state state)
|
||||
@@ -4040,6 +4155,8 @@ iter_state_to_string(enum iter_state state)
|
||||
return "INIT REQUEST STATE (stage 2)";
|
||||
case INIT_REQUEST_3_STATE:
|
||||
return "INIT REQUEST STATE (stage 3)";
|
||||
@@ -275,7 +275,7 @@ index 23b07ea9..ca29b48c 100644
|
||||
case QUERYTARGETS_STATE :
|
||||
return "QUERY TARGETS STATE";
|
||||
case PRIME_RESP_STATE :
|
||||
@@ -3985,6 +4102,7 @@ iter_state_is_responsestate(enum iter_state s)
|
||||
@@ -4064,6 +4181,7 @@ iter_state_is_responsestate(enum iter_state s)
|
||||
case INIT_REQUEST_STATE :
|
||||
case INIT_REQUEST_2_STATE :
|
||||
case INIT_REQUEST_3_STATE :
|
||||
@@ -284,10 +284,10 @@ index 23b07ea9..ca29b48c 100644
|
||||
case COLLECT_CLASS_STATE :
|
||||
return 0;
|
||||
diff --git a/iterator/iterator.h b/iterator/iterator.h
|
||||
index 342ac207..731948d1 100644
|
||||
index 8b840528..a61c4195 100644
|
||||
--- a/iterator/iterator.h
|
||||
+++ b/iterator/iterator.h
|
||||
@@ -135,6 +135,9 @@ struct iter_env {
|
||||
@@ -133,6 +133,9 @@ struct iter_env {
|
||||
*/
|
||||
int* target_fetch_policy;
|
||||
|
||||
@@ -297,7 +297,7 @@ index 342ac207..731948d1 100644
|
||||
/** lock on ratelimit counter */
|
||||
lock_basic_type queries_ratelimit_lock;
|
||||
/** number of queries that have been ratelimited */
|
||||
@@ -186,6 +189,14 @@ enum iter_state {
|
||||
@@ -187,6 +190,14 @@ enum iter_state {
|
||||
*/
|
||||
INIT_REQUEST_3_STATE,
|
||||
|
||||
@@ -312,7 +312,7 @@ index 342ac207..731948d1 100644
|
||||
/**
|
||||
* Each time a delegation point changes for a given query or a
|
||||
* query times out and/or wakes up, this state is (re)visited.
|
||||
@@ -375,6 +386,13 @@ struct iter_qstate {
|
||||
@@ -376,6 +387,13 @@ struct iter_qstate {
|
||||
*/
|
||||
int refetch_glue;
|
||||
|
||||
@@ -327,10 +327,10 @@ index 342ac207..731948d1 100644
|
||||
struct outbound_list outlist;
|
||||
|
||||
diff --git a/pythonmod/interface.i b/pythonmod/interface.i
|
||||
index f08b575d..47f1bb2e 100644
|
||||
index 1ca8686a..d91b19ec 100644
|
||||
--- a/pythonmod/interface.i
|
||||
+++ b/pythonmod/interface.i
|
||||
@@ -975,6 +975,7 @@ struct config_file {
|
||||
@@ -995,6 +995,7 @@ struct config_file {
|
||||
int harden_dnssec_stripped;
|
||||
int harden_referral_path;
|
||||
int use_caps_bits_for_id;
|
||||
@@ -339,10 +339,10 @@ index f08b575d..47f1bb2e 100644
|
||||
struct config_strlist* private_domain;
|
||||
size_t unwanted_threshold;
|
||||
diff --git a/util/config_file.c b/util/config_file.c
|
||||
index 0ab8614a..729fb147 100644
|
||||
index 969d664b..8d94b008 100644
|
||||
--- a/util/config_file.c
|
||||
+++ b/util/config_file.c
|
||||
@@ -218,6 +218,7 @@ config_create(void)
|
||||
@@ -231,6 +231,7 @@ config_create(void)
|
||||
cfg->harden_referral_path = 0;
|
||||
cfg->harden_algo_downgrade = 0;
|
||||
cfg->use_caps_bits_for_id = 0;
|
||||
@@ -351,10 +351,10 @@ index 0ab8614a..729fb147 100644
|
||||
cfg->private_address = NULL;
|
||||
cfg->private_domain = NULL;
|
||||
diff --git a/util/config_file.h b/util/config_file.h
|
||||
index e61257a3..dabaa7bb 100644
|
||||
index c7c9a0a4..e3aa15b0 100644
|
||||
--- a/util/config_file.h
|
||||
+++ b/util/config_file.h
|
||||
@@ -260,6 +260,8 @@ struct config_file {
|
||||
@@ -285,6 +285,8 @@ struct config_file {
|
||||
int harden_algo_downgrade;
|
||||
/** use 0x20 bits in query as random ID bits */
|
||||
int use_caps_bits_for_id;
|
||||
@@ -364,38 +364,38 @@ index e61257a3..dabaa7bb 100644
|
||||
struct config_strlist* caps_whitelist;
|
||||
/** strip away these private addrs from answers, no DNS Rebinding */
|
||||
diff --git a/util/configlexer.lex b/util/configlexer.lex
|
||||
index 79a0edca..4eaec678 100644
|
||||
index 34a0e5dd..c890be2a 100644
|
||||
--- a/util/configlexer.lex
|
||||
+++ b/util/configlexer.lex
|
||||
@@ -304,6 +304,7 @@ harden-algo-downgrade{COLON} { YDVAR(1, VAR_HARDEN_ALGO_DOWNGRADE) }
|
||||
use-caps-for-id{COLON} { YDVAR(1, VAR_USE_CAPS_FOR_ID) }
|
||||
@@ -317,6 +317,7 @@ use-caps-for-id{COLON} { YDVAR(1, VAR_USE_CAPS_FOR_ID) }
|
||||
caps-whitelist{COLON} { YDVAR(1, VAR_CAPS_WHITELIST) }
|
||||
caps-exempt{COLON} { YDVAR(1, VAR_CAPS_WHITELIST) }
|
||||
unwanted-reply-threshold{COLON} { YDVAR(1, VAR_UNWANTED_REPLY_THRESHOLD) }
|
||||
+aaaa-filter{COLON} { YDVAR(1, VAR_AAAA_FILTER) }
|
||||
private-address{COLON} { YDVAR(1, VAR_PRIVATE_ADDRESS) }
|
||||
private-domain{COLON} { YDVAR(1, VAR_PRIVATE_DOMAIN) }
|
||||
prefetch-key{COLON} { YDVAR(1, VAR_PREFETCH_KEY) }
|
||||
diff --git a/util/configparser.y b/util/configparser.y
|
||||
index 1d0e8658..f284dd43 100644
|
||||
index d4f965f9..8cc237c6 100644
|
||||
--- a/util/configparser.y
|
||||
+++ b/util/configparser.y
|
||||
@@ -97,6 +97,7 @@ extern struct config_parser_state* cfg_parser;
|
||||
%token VAR_STATISTICS_CUMULATIVE VAR_OUTGOING_PORT_PERMIT
|
||||
%token VAR_STATISTICS_CUMULATIVE VAR_OUTGOING_PORT_PERMIT
|
||||
%token VAR_OUTGOING_PORT_AVOID VAR_DLV_ANCHOR_FILE VAR_DLV_ANCHOR
|
||||
%token VAR_NEG_CACHE_SIZE VAR_HARDEN_REFERRAL_PATH VAR_PRIVATE_ADDRESS
|
||||
+%token VAR_AAAA_FILTER
|
||||
%token VAR_PRIVATE_DOMAIN VAR_REMOTE_CONTROL VAR_CONTROL_ENABLE
|
||||
%token VAR_CONTROL_INTERFACE VAR_CONTROL_PORT VAR_SERVER_KEY_FILE
|
||||
%token VAR_SERVER_CERT_FILE VAR_CONTROL_KEY_FILE VAR_CONTROL_CERT_FILE
|
||||
@@ -233,6 +234,7 @@ content_server: server_num_threads | server_verbosity | server_port |
|
||||
@@ -247,6 +248,7 @@ content_server: server_num_threads | server_verbosity | server_port |
|
||||
server_dlv_anchor_file | server_dlv_anchor | server_neg_cache_size |
|
||||
server_harden_referral_path | server_private_address |
|
||||
server_private_domain | server_extended_statistics |
|
||||
server_private_domain | server_extended_statistics |
|
||||
+ server_aaaa_filter |
|
||||
server_local_data_ptr | server_jostle_timeout |
|
||||
server_unwanted_reply_threshold | server_log_time_ascii |
|
||||
server_domain_insecure | server_val_sig_skew_min |
|
||||
@@ -1563,6 +1565,15 @@ server_caps_whitelist: VAR_CAPS_WHITELIST STRING_ARG
|
||||
server_local_data_ptr | server_jostle_timeout |
|
||||
server_unwanted_reply_threshold | server_log_time_ascii |
|
||||
server_domain_insecure | server_val_sig_skew_min |
|
||||
@@ -1754,6 +1756,15 @@ server_caps_whitelist: VAR_CAPS_WHITELIST STRING_ARG
|
||||
yyerror("out of memory");
|
||||
}
|
||||
;
|
||||
|
||||
@@ -28,6 +28,7 @@ END {
|
||||
print "unbound_hits_queries{type=\"total.num.prefetch\"} " val["total.num.prefetch"];
|
||||
print "unbound_hits_queries{type=\"num.query.tcp\"} " val["num.query.tcp"];
|
||||
print "unbound_hits_queries{type=\"num.query.tcpout\"} " val["num.query.tcpout"];
|
||||
print "unbound_hits_queries{type=\"num.query.udpout\"} " val["num.query.udpout"];
|
||||
print "unbound_hits_queries{type=\"num.query.tls\"} " val["num.query.tls"];
|
||||
print "unbound_hits_queries{type=\"num.query.tls.resume\"} " val["num.query.tls.resume"];
|
||||
print "unbound_hits_queries{type=\"num.query.ipv6\"} " val["num.query.ipv6"];
|
||||
|
||||
@@ -253,6 +253,7 @@ if test "$1" = "config" ; then
|
||||
p_config "total.num.prefetch" "cache prefetch" "ABSOLUTE"
|
||||
p_config "num.query.tcp" "TCP queries" "ABSOLUTE"
|
||||
p_config "num.query.tcpout" "TCP out queries" "ABSOLUTE"
|
||||
p_config "num.query.udpout" "UDP out queries" "ABSOLUTE"
|
||||
p_config "num.query.tls" "TLS queries" "ABSOLUTE"
|
||||
p_config "num.query.tls.resume" "TLS resumes" "ABSOLUTE"
|
||||
p_config "num.query.ipv6" "IPv6 queries" "ABSOLUTE"
|
||||
@@ -452,7 +453,7 @@ hits)
|
||||
for x in `grep "^thread[0-9][0-9]*\.num\.queries=" $state |
|
||||
sed -e 's/=.*//'` total.num.queries \
|
||||
total.num.cachehits total.num.prefetch num.query.tcp \
|
||||
num.query.tcpout num.query.tls num.query.tls.resume \
|
||||
num.query.tcpout num.query.udpout num.query.tls num.query.tls.resume \
|
||||
num.query.ipv6 unwanted.queries \
|
||||
unwanted.replies; do
|
||||
if grep "^"$x"=" $state >/dev/null 2>&1; then
|
||||
|
||||
+422
-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,31 @@ 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 {
|
||||
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 +125,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 +142,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 +174,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 +245,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 +265,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 +358,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 +410,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 +422,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 +467,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 +494,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 +519,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 +549,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,9 +780,44 @@ 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;
|
||||
return sizeof(*acl) + regional_get_mem(acl->region);
|
||||
}
|
||||
|
||||
const char* acl_access_to_str(enum acl_access acl)
|
||||
{
|
||||
switch(acl) {
|
||||
case acl_deny: return "deny";
|
||||
case acl_refuse: return "refuse";
|
||||
case acl_deny_non_local: return "deny_non_local";
|
||||
case acl_refuse_non_local: return "refuse_non_local";
|
||||
case acl_allow: return "allow";
|
||||
case acl_allow_snoop: return "allow_snoop";
|
||||
case acl_allow_setrd: return "allow_setrd";
|
||||
default: break;
|
||||
}
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
void
|
||||
log_acl_action(const char* action, struct sockaddr_storage* addr,
|
||||
socklen_t addrlen, enum acl_access acl, struct acl_addr* acladdr)
|
||||
{
|
||||
char a[128], n[128];
|
||||
uint16_t port;
|
||||
addr_to_str(addr, addrlen, a, sizeof(a));
|
||||
port = ntohs(((struct sockaddr_in*)addr)->sin_port);
|
||||
if(acladdr) {
|
||||
addr_to_str(&acladdr->node.addr, acladdr->node.addrlen,
|
||||
n, sizeof(n));
|
||||
verbose(VERB_ALGO, "%s query from %s port %d because of "
|
||||
"%s/%d %s", action, a, (int)port, n, acladdr->node.net,
|
||||
acl_access_to_str(acl));
|
||||
} else {
|
||||
verbose(VERB_ALGO, "%s query from %s port %d", action, a,
|
||||
(int)port);
|
||||
}
|
||||
}
|
||||
|
||||
+47
-3
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -74,7 +74,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 +108,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 +119,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 +143,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.
|
||||
@@ -154,4 +187,15 @@ acl_addr_lookup(struct acl_list* acl, struct sockaddr_storage* addr,
|
||||
*/
|
||||
size_t acl_list_get_mem(struct acl_list* acl);
|
||||
|
||||
/*
|
||||
* Get string for acl access specification
|
||||
* @param acl: access type value
|
||||
* @return string
|
||||
*/
|
||||
const char* acl_access_to_str(enum acl_access acl);
|
||||
|
||||
/* log acl and addr for action */
|
||||
void log_acl_action(const char* action, struct sockaddr_storage* addr,
|
||||
socklen_t addrlen, enum acl_access acl, struct acl_addr* acladdr);
|
||||
|
||||
#endif /* DAEMON_ACL_LIST_H */
|
||||
|
||||
+8
-3
@@ -47,10 +47,12 @@
|
||||
#include "services/cache/rrset.h"
|
||||
#include "services/cache/dns.h"
|
||||
#include "services/cache/infra.h"
|
||||
#include "services/outside_network.h"
|
||||
#include "util/data/msgreply.h"
|
||||
#include "util/regional.h"
|
||||
#include "util/net_help.h"
|
||||
#include "util/data/dname.h"
|
||||
#include "util/config_file.h"
|
||||
#include "iterator/iterator.h"
|
||||
#include "iterator/iter_delegpt.h"
|
||||
#include "iterator/iter_utils.h"
|
||||
@@ -677,7 +679,8 @@ load_msg(RES* ssl, sldns_buffer* buf, struct worker* worker)
|
||||
if(!go_on)
|
||||
return 1; /* skip this one, not all references satisfied */
|
||||
|
||||
if(!dns_cache_store(&worker->env, &qinf, &rep, 0, 0, 0, NULL, flags)) {
|
||||
if(!dns_cache_store(&worker->env, &qinf, &rep, 0, 0, 0, NULL, flags,
|
||||
*worker->env.now)) {
|
||||
log_warn("error out of memory");
|
||||
return 0;
|
||||
}
|
||||
@@ -848,13 +851,15 @@ int print_deleg_lookup(RES* ssl, struct worker* worker, uint8_t* nm,
|
||||
while(1) {
|
||||
dp = dns_cache_find_delegation(&worker->env, nm, nmlen,
|
||||
qinfo.qtype, qinfo.qclass, region, &msg,
|
||||
*worker->env.now);
|
||||
*worker->env.now, 0, NULL, 0);
|
||||
if(!dp) {
|
||||
return ssl_printf(ssl, "no delegation from "
|
||||
"cache; goes to configured roots\n");
|
||||
}
|
||||
/* go up? */
|
||||
if(iter_dp_is_useless(&qinfo, BIT_RD, dp)) {
|
||||
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))) {
|
||||
print_dp_main(ssl, dp, msg);
|
||||
print_dp_details(ssl, worker, dp);
|
||||
if(!ssl_printf(ssl, "cache delegation was "
|
||||
|
||||
+61
-2
@@ -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);
|
||||
@@ -604,6 +659,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) {
|
||||
@@ -780,6 +838,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);
|
||||
@@ -795,7 +854,7 @@ daemon_delete(struct daemon* daemon)
|
||||
ub_c_lex_destroy();
|
||||
/* libcrypto cleanup */
|
||||
#ifdef HAVE_SSL
|
||||
# if defined(USE_GOST) && defined(HAVE_LDNS_KEY_EVP_UNLOAD_GOST)
|
||||
# if defined(USE_GOST)
|
||||
sldns_key_EVP_unload_gost();
|
||||
# endif
|
||||
# if HAVE_DECL_SSL_COMP_GET_COMPRESSION_METHODS && HAVE_DECL_SK_SSL_COMP_POP_FREE
|
||||
|
||||
@@ -113,6 +113,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 */
|
||||
|
||||
+33
-32
@@ -300,6 +300,7 @@ add_open(const char* ip, int nr, struct listen_port** list, int noproto_is_err,
|
||||
*/
|
||||
if(fd != -1) {
|
||||
#ifdef HAVE_CHOWN
|
||||
chmod(ip, (mode_t)(S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP));
|
||||
if (cfg->username && cfg->username[0] &&
|
||||
cfg_uid != (uid_t)-1) {
|
||||
if(chown(ip, cfg_uid, cfg_gid) == -1)
|
||||
@@ -307,7 +308,6 @@ add_open(const char* ip, int nr, struct listen_port** list, int noproto_is_err,
|
||||
(unsigned)cfg_uid, (unsigned)cfg_gid,
|
||||
ip, strerror(errno));
|
||||
}
|
||||
chmod(ip, (mode_t)(S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP));
|
||||
#else
|
||||
(void)cfg;
|
||||
#endif
|
||||
@@ -494,8 +494,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);
|
||||
@@ -988,6 +988,8 @@ print_ext(RES* ssl, struct ub_stats_info* s)
|
||||
(unsigned long)s->svr.qtcp)) return 0;
|
||||
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",
|
||||
(unsigned long)s->svr.qtls)) return 0;
|
||||
if(!ssl_printf(ssl, "num.query.tls.resume"SQ"%lu\n",
|
||||
@@ -2015,7 +2017,7 @@ print_root_fwds(RES* ssl, struct iter_forwards* fwds, uint8_t* root)
|
||||
|
||||
/** parse args into delegpt */
|
||||
static struct delegpt*
|
||||
parse_delegpt(RES* ssl, char* args, uint8_t* nm, int allow_names)
|
||||
parse_delegpt(RES* ssl, char* args, uint8_t* nm)
|
||||
{
|
||||
/* parse args and add in */
|
||||
char* p = args;
|
||||
@@ -2037,40 +2039,35 @@ parse_delegpt(RES* ssl, char* args, uint8_t* nm, int allow_names)
|
||||
}
|
||||
/* parse address */
|
||||
if(!authextstrtoaddr(todo, &addr, &addrlen, &auth_name)) {
|
||||
if(allow_names) {
|
||||
uint8_t* n = NULL;
|
||||
size_t ln;
|
||||
int lb;
|
||||
if(!parse_arg_name(ssl, todo, &n, &ln, &lb)) {
|
||||
(void)ssl_printf(ssl, "error cannot "
|
||||
"parse IP address or name "
|
||||
"'%s'\n", todo);
|
||||
delegpt_free_mlc(dp);
|
||||
return NULL;
|
||||
}
|
||||
if(!delegpt_add_ns_mlc(dp, n, 0)) {
|
||||
(void)ssl_printf(ssl, "error out of memory\n");
|
||||
free(n);
|
||||
delegpt_free_mlc(dp);
|
||||
return NULL;
|
||||
}
|
||||
free(n);
|
||||
|
||||
} else {
|
||||
uint8_t* dname= NULL;
|
||||
int port;
|
||||
dname = authextstrtodname(todo, &port, &auth_name);
|
||||
if(!dname) {
|
||||
(void)ssl_printf(ssl, "error cannot parse"
|
||||
" IP address '%s'\n", todo);
|
||||
" '%s'\n", todo);
|
||||
delegpt_free_mlc(dp);
|
||||
return NULL;
|
||||
}
|
||||
#if ! defined(HAVE_SSL_SET1_HOST) && ! defined(HAVE_X509_VERIFY_PARAM_SET1_HOST)
|
||||
if(auth_name)
|
||||
log_err("no name verification functionality in "
|
||||
"ssl library, ignored name for %s", todo);
|
||||
#endif
|
||||
if(!delegpt_add_ns_mlc(dp, dname, 0, auth_name, port)) {
|
||||
(void)ssl_printf(ssl, "error out of memory\n");
|
||||
free(dname);
|
||||
delegpt_free_mlc(dp);
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
#if ! defined(HAVE_SSL_SET1_HOST) && ! defined(HAVE_X509_VERIFY_PARAM_SET1_HOST)
|
||||
if(auth_name)
|
||||
log_err("no name verification functionality in "
|
||||
log_err("no name verification functionality in "
|
||||
"ssl library, ignored name for %s", todo);
|
||||
#endif
|
||||
/* add address */
|
||||
if(!delegpt_add_addr_mlc(dp, &addr, addrlen, 0, 0,
|
||||
auth_name)) {
|
||||
auth_name, -1)) {
|
||||
(void)ssl_printf(ssl, "error out of memory\n");
|
||||
delegpt_free_mlc(dp);
|
||||
return NULL;
|
||||
@@ -2103,7 +2100,7 @@ do_forward(RES* ssl, struct worker* worker, char* args)
|
||||
forwards_delete_zone(fwd, LDNS_RR_CLASS_IN, root);
|
||||
} else {
|
||||
struct delegpt* dp;
|
||||
if(!(dp = parse_delegpt(ssl, args, root, 0)))
|
||||
if(!(dp = parse_delegpt(ssl, args, root)))
|
||||
return;
|
||||
if(!forwards_add_zone(fwd, LDNS_RR_CLASS_IN, dp)) {
|
||||
(void)ssl_printf(ssl, "error out of memory\n");
|
||||
@@ -2149,7 +2146,7 @@ parse_fs_args(RES* ssl, char* args, uint8_t** nm, struct delegpt** dp,
|
||||
|
||||
/* parse dp */
|
||||
if(dp) {
|
||||
if(!(*dp = parse_delegpt(ssl, args, *nm, 1))) {
|
||||
if(!(*dp = parse_delegpt(ssl, args, *nm))) {
|
||||
free(*nm);
|
||||
return 0;
|
||||
}
|
||||
@@ -2865,6 +2862,8 @@ struct ratelimit_list_arg {
|
||||
int all;
|
||||
/** current time */
|
||||
time_t now;
|
||||
/** if backoff is enabled */
|
||||
int backoff;
|
||||
};
|
||||
|
||||
#define ip_ratelimit_list_arg ratelimit_list_arg
|
||||
@@ -2878,7 +2877,7 @@ rate_list(struct lruhash_entry* e, void* arg)
|
||||
struct rate_data* d = (struct rate_data*)e->data;
|
||||
char buf[257];
|
||||
int lim = infra_find_ratelimit(a->infra, k->name, k->namelen);
|
||||
int max = infra_rate_max(d, a->now);
|
||||
int max = infra_rate_max(d, a->now, a->backoff);
|
||||
if(a->all == 0) {
|
||||
if(max < lim)
|
||||
return;
|
||||
@@ -2896,7 +2895,7 @@ ip_rate_list(struct lruhash_entry* e, void* arg)
|
||||
struct ip_rate_key* k = (struct ip_rate_key*)e->key;
|
||||
struct ip_rate_data* d = (struct ip_rate_data*)e->data;
|
||||
int lim = infra_ip_ratelimit;
|
||||
int max = infra_rate_max(d, a->now);
|
||||
int max = infra_rate_max(d, a->now, a->backoff);
|
||||
if(a->all == 0) {
|
||||
if(max < lim)
|
||||
return;
|
||||
@@ -2914,6 +2913,7 @@ do_ratelimit_list(RES* ssl, struct worker* worker, char* arg)
|
||||
a.infra = worker->env.infra_cache;
|
||||
a.now = *worker->env.now;
|
||||
a.ssl = ssl;
|
||||
a.backoff = worker->env.cfg->ratelimit_backoff;
|
||||
arg = skipwhite(arg);
|
||||
if(strcmp(arg, "+a") == 0)
|
||||
a.all = 1;
|
||||
@@ -2932,6 +2932,7 @@ do_ip_ratelimit_list(RES* ssl, struct worker* worker, char* arg)
|
||||
a.infra = worker->env.infra_cache;
|
||||
a.now = *worker->env.now;
|
||||
a.ssl = ssl;
|
||||
a.backoff = worker->env.cfg->ip_ratelimit_backoff;
|
||||
arg = skipwhite(arg);
|
||||
if(strcmp(arg, "+a") == 0)
|
||||
a.all = 1;
|
||||
@@ -3303,7 +3304,7 @@ 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);
|
||||
}
|
||||
|
||||
+28
-1
@@ -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)
|
||||
@@ -281,6 +284,7 @@ server_stats_compile(struct worker* worker, struct ub_stats_info* s, int reset)
|
||||
/* values from outside network */
|
||||
s->svr.unwanted_replies = (long long)worker->back->unwanted_replies;
|
||||
s->svr.qtcp_outgoing = (long long)worker->back->num_tcp_outgoing;
|
||||
s->svr.qudp_outgoing = (long long)worker->back->num_udp_outgoing;
|
||||
|
||||
/* get and reset validator rrset bogus number */
|
||||
s->svr.rrset_bogus = (long long)get_rrset_bogus(worker, reset);
|
||||
@@ -379,6 +383,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))
|
||||
@@ -424,6 +450,7 @@ void server_stats_add(struct ub_stats_info* total, struct ub_stats_info* a)
|
||||
total->svr.qclass_big += a->svr.qclass_big;
|
||||
total->svr.qtcp += a->svr.qtcp;
|
||||
total->svr.qtcp_outgoing += a->svr.qtcp_outgoing;
|
||||
total->svr.qudp_outgoing += a->svr.qudp_outgoing;
|
||||
total->svr.qtls += a->svr.qtls;
|
||||
total->svr.qtls_resume += a->svr.qtls_resume;
|
||||
total->svr.qhttps += a->svr.qhttps;
|
||||
@@ -494,7 +521,7 @@ void server_stats_insquery(struct ub_server_stats* stats, struct comm_point* c,
|
||||
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++;
|
||||
|
||||
+357
-101
@@ -98,7 +98,7 @@
|
||||
/** ratelimit for error responses */
|
||||
#define ERROR_RATELIMIT 100 /* qps */
|
||||
|
||||
/**
|
||||
/**
|
||||
* seconds to add to prefetch leeway. This is a TTL that expires old rrsets
|
||||
* earlier than they should in order to put the new update into the cache.
|
||||
* This additional value is to make sure that if not all TTLs are equal in
|
||||
@@ -459,7 +459,7 @@ answer_norec_from_cache(struct worker* worker, struct query_info* qinfo,
|
||||
|
||||
dp = dns_cache_find_delegation(&worker->env, qinfo->qname,
|
||||
qinfo->qname_len, qinfo->qtype, qinfo->qclass,
|
||||
worker->scratchpad, &msg, timenow);
|
||||
worker->scratchpad, &msg, timenow, 0, NULL, 0);
|
||||
if(!dp) { /* no delegation, need to reprime */
|
||||
return 0;
|
||||
}
|
||||
@@ -484,6 +484,12 @@ answer_norec_from_cache(struct worker* worker, struct query_info* qinfo,
|
||||
msg->rep, LDNS_RCODE_SERVFAIL, edns, repinfo, worker->scratchpad,
|
||||
worker->env.now_tv))
|
||||
return 0;
|
||||
/* TODO store the reason for the bogus reply in cache
|
||||
* and implement in here instead of the hardcoded EDE */
|
||||
if (worker->env.cfg->ede) {
|
||||
EDNS_OPT_LIST_APPEND_EDE(&edns->opt_list_out,
|
||||
worker->scratchpad, LDNS_EDE_DNSSEC_BOGUS, "");
|
||||
}
|
||||
error_encode(repinfo->c->buffer, LDNS_RCODE_SERVFAIL,
|
||||
&msg->qinfo, id, flags, edns);
|
||||
if(worker->stats.extended) {
|
||||
@@ -541,7 +547,8 @@ answer_norec_from_cache(struct worker* worker, struct query_info* qinfo,
|
||||
static int
|
||||
apply_respip_action(struct worker* worker, const struct query_info* qinfo,
|
||||
struct respip_client_info* cinfo, struct reply_info* rep,
|
||||
struct comm_reply* repinfo, struct ub_packed_rrset_key** alias_rrset,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen,
|
||||
struct ub_packed_rrset_key** alias_rrset,
|
||||
struct reply_info** encode_repp, struct auth_zones* az)
|
||||
{
|
||||
struct respip_action_info actinfo = {0, 0, 0, 0, NULL, 0, NULL};
|
||||
@@ -553,7 +560,7 @@ apply_respip_action(struct worker* worker, const struct query_info* qinfo,
|
||||
return 1;
|
||||
|
||||
if(!respip_rewrite_reply(qinfo, cinfo, rep, encode_repp, &actinfo,
|
||||
alias_rrset, 0, worker->scratchpad, az))
|
||||
alias_rrset, 0, worker->scratchpad, az, NULL))
|
||||
return 0;
|
||||
|
||||
/* xxx_deny actions mean dropping the reply, unless the original reply
|
||||
@@ -568,7 +575,7 @@ apply_respip_action(struct worker* worker, const struct query_info* qinfo,
|
||||
if(actinfo.addrinfo) {
|
||||
respip_inform_print(&actinfo, qinfo->qname,
|
||||
qinfo->qtype, qinfo->qclass, qinfo->local_alias,
|
||||
repinfo);
|
||||
addr, addrlen);
|
||||
|
||||
if(worker->stats.extended && actinfo.rpz_used) {
|
||||
if(actinfo.rpz_disabled)
|
||||
@@ -654,6 +661,12 @@ answer_from_cache(struct worker* worker, struct query_info* qinfo,
|
||||
LDNS_RCODE_SERVFAIL, edns, repinfo, worker->scratchpad,
|
||||
worker->env.now_tv))
|
||||
goto bail_out;
|
||||
/* TODO store the reason for the bogus reply in cache
|
||||
* and implement in here instead of the hardcoded EDE */
|
||||
if (worker->env.cfg->ede) {
|
||||
EDNS_OPT_LIST_APPEND_EDE(&edns->opt_list_out,
|
||||
worker->scratchpad, LDNS_EDE_DNSSEC_BOGUS, "");
|
||||
}
|
||||
error_encode(repinfo->c->buffer, LDNS_RCODE_SERVFAIL,
|
||||
qinfo, id, flags, edns);
|
||||
rrset_array_unlock_touch(worker->env.rrset_cache,
|
||||
@@ -691,7 +704,7 @@ answer_from_cache(struct worker* worker, struct query_info* qinfo,
|
||||
*alias_rrset = NULL; /* avoid confusion if caller set it to non-NULL */
|
||||
if((worker->daemon->use_response_ip || worker->daemon->use_rpz) &&
|
||||
!partial_rep && !apply_respip_action(worker, qinfo, cinfo, rep,
|
||||
repinfo, alias_rrset,
|
||||
&repinfo->client_addr, repinfo->client_addrlen, alias_rrset,
|
||||
&encode_rep, worker->env.auth_zones)) {
|
||||
goto bail_out;
|
||||
} else if(partial_rep &&
|
||||
@@ -716,15 +729,25 @@ answer_from_cache(struct worker* worker, struct query_info* qinfo,
|
||||
if(!*partial_repp)
|
||||
goto bail_out;
|
||||
}
|
||||
} else if(!reply_info_answer_encode(qinfo, encode_rep, id, flags,
|
||||
repinfo->c->buffer, timenow, 1, worker->scratchpad,
|
||||
udpsize, edns, (int)(edns->bits & EDNS_DO), *is_secure_answer)) {
|
||||
if(!inplace_cb_reply_servfail_call(&worker->env, qinfo, NULL, NULL,
|
||||
LDNS_RCODE_SERVFAIL, edns, repinfo, worker->scratchpad,
|
||||
worker->env.now_tv))
|
||||
edns->opt_list_inplace_cb_out = NULL;
|
||||
error_encode(repinfo->c->buffer, LDNS_RCODE_SERVFAIL,
|
||||
qinfo, id, flags, edns);
|
||||
} else {
|
||||
/* We don't check the global ede as this is a warning, not
|
||||
* an error */
|
||||
if (*is_expired_answer == 1 &&
|
||||
worker->env.cfg->ede_serve_expired && worker->env.cfg->ede) {
|
||||
EDNS_OPT_LIST_APPEND_EDE(&edns->opt_list_out,
|
||||
worker->scratchpad, LDNS_EDE_STALE_ANSWER, "");
|
||||
}
|
||||
if(!reply_info_answer_encode(qinfo, encode_rep, id, flags,
|
||||
repinfo->c->buffer, timenow, 1, worker->scratchpad,
|
||||
udpsize, edns, (int)(edns->bits & EDNS_DO),
|
||||
*is_secure_answer)) {
|
||||
if(!inplace_cb_reply_servfail_call(&worker->env, qinfo,
|
||||
NULL, NULL, LDNS_RCODE_SERVFAIL, edns, repinfo,
|
||||
worker->scratchpad, worker->env.now_tv))
|
||||
edns->opt_list_inplace_cb_out = NULL;
|
||||
error_encode(repinfo->c->buffer, LDNS_RCODE_SERVFAIL,
|
||||
qinfo, id, flags, edns);
|
||||
}
|
||||
}
|
||||
/* cannot send the reply right now, because blocking network syscall
|
||||
* is bad while holding locks. */
|
||||
@@ -741,10 +764,12 @@ bail_out:
|
||||
|
||||
/** Reply to client and perform prefetch to keep cache up to date. */
|
||||
static void
|
||||
reply_and_prefetch(struct worker* worker, struct query_info* qinfo,
|
||||
uint16_t flags, struct comm_reply* repinfo, time_t leeway, int noreply)
|
||||
reply_and_prefetch(struct worker* worker, struct query_info* qinfo,
|
||||
uint16_t flags, struct comm_reply* repinfo, time_t leeway, int noreply,
|
||||
int rpz_passthru, struct edns_option* opt_list)
|
||||
{
|
||||
/* first send answer to client to keep its latency
|
||||
(void)opt_list;
|
||||
/* first send answer to client to keep its latency
|
||||
* as small as a cachereply */
|
||||
if(!noreply) {
|
||||
if(repinfo->c->tcp_req_info) {
|
||||
@@ -755,13 +780,23 @@ reply_and_prefetch(struct worker* worker, struct query_info* qinfo,
|
||||
comm_point_send_reply(repinfo);
|
||||
}
|
||||
server_stats_prefetch(&worker->stats, worker);
|
||||
|
||||
#ifdef CLIENT_SUBNET
|
||||
/* Check if the subnet module is enabled. In that case pass over the
|
||||
* comm_reply information for ECS generation later. The mesh states are
|
||||
* unique when subnet is enabled. */
|
||||
if(modstack_find(&worker->env.mesh->mods, "subnetcache") != -1
|
||||
&& worker->env.unique_mesh) {
|
||||
mesh_new_prefetch(worker->env.mesh, qinfo, flags, leeway +
|
||||
PREFETCH_EXPIRY_ADD, rpz_passthru, repinfo, opt_list);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
/* create the prefetch in the mesh as a normal lookup without
|
||||
* client addrs waiting, which has the cache blacklisted (to bypass
|
||||
* the cache and go to the network for the data). */
|
||||
/* this (potentially) runs the mesh for the new query */
|
||||
mesh_new_prefetch(worker->env.mesh, qinfo, flags, leeway +
|
||||
PREFETCH_EXPIRY_ADD);
|
||||
mesh_new_prefetch(worker->env.mesh, qinfo, flags, leeway +
|
||||
PREFETCH_EXPIRY_ADD, rpz_passthru, NULL, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -957,12 +992,14 @@ answer_chaos(struct worker* w, struct query_info* qinfo,
|
||||
* @param w: worker
|
||||
* @param qinfo: query info. Pointer into packet buffer.
|
||||
* @param edns: edns info from query.
|
||||
* @param repinfo: reply info with source address.
|
||||
* @param addr: client address.
|
||||
* @param addrlen: client address length.
|
||||
* @param pkt: packet buffer.
|
||||
*/
|
||||
static void
|
||||
answer_notify(struct worker* w, struct query_info* qinfo,
|
||||
struct edns_data* edns, sldns_buffer* pkt, struct comm_reply* repinfo)
|
||||
answer_notify(struct worker* w, struct query_info* qinfo,
|
||||
struct edns_data* edns, sldns_buffer* pkt,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen)
|
||||
{
|
||||
int refused = 0;
|
||||
int rcode = LDNS_RCODE_NOERROR;
|
||||
@@ -971,8 +1008,8 @@ answer_notify(struct worker* w, struct query_info* qinfo,
|
||||
if(!w->env.auth_zones) return;
|
||||
has_serial = auth_zone_parse_notify_serial(pkt, &serial);
|
||||
if(auth_zones_notify(w->env.auth_zones, &w->env, qinfo->qname,
|
||||
qinfo->qname_len, qinfo->qclass, &repinfo->addr,
|
||||
repinfo->addrlen, has_serial, serial, &refused)) {
|
||||
qinfo->qname_len, qinfo->qclass, addr,
|
||||
addrlen, has_serial, serial, &refused)) {
|
||||
rcode = LDNS_RCODE_NOERROR;
|
||||
} else {
|
||||
if(refused)
|
||||
@@ -997,7 +1034,7 @@ answer_notify(struct worker* w, struct query_info* qinfo,
|
||||
"servfail for NOTIFY %sfor %s from", sr, zname);
|
||||
else snprintf(buf, sizeof(buf),
|
||||
"received NOTIFY %sfor %s from", sr, zname);
|
||||
log_addr(VERB_DETAIL, buf, &repinfo->addr, repinfo->addrlen);
|
||||
log_addr(VERB_DETAIL, buf, addr, addrlen);
|
||||
}
|
||||
edns->edns_version = EDNS_ADVERTISED_VERSION;
|
||||
edns->udp_size = EDNS_ADVERTISED_SIZE;
|
||||
@@ -1012,52 +1049,214 @@ answer_notify(struct worker* w, struct query_info* qinfo,
|
||||
static int
|
||||
deny_refuse(struct comm_point* c, enum acl_access acl,
|
||||
enum acl_access deny, enum acl_access refuse,
|
||||
struct worker* worker, struct comm_reply* repinfo)
|
||||
struct worker* worker, struct comm_reply* repinfo,
|
||||
struct acl_addr* acladdr, int ede)
|
||||
{
|
||||
if(acl == deny) {
|
||||
if(verbosity >= VERB_ALGO) {
|
||||
log_acl_action("dropped", &repinfo->client_addr,
|
||||
repinfo->client_addrlen, acl, acladdr);
|
||||
log_buf(VERB_ALGO, "dropped", c->buffer);
|
||||
}
|
||||
comm_point_drop_reply(repinfo);
|
||||
if(worker->stats.extended)
|
||||
worker->stats.unwanted_queries++;
|
||||
return 0;
|
||||
} else if(acl == refuse) {
|
||||
log_addr(VERB_ALGO, "refused query from",
|
||||
&repinfo->addr, repinfo->addrlen);
|
||||
log_buf(VERB_ALGO, "refuse", c->buffer);
|
||||
size_t opt_rr_mark;
|
||||
|
||||
if(verbosity >= VERB_ALGO) {
|
||||
log_acl_action("refused", &repinfo->client_addr,
|
||||
repinfo->client_addrlen, acl, acladdr);
|
||||
log_buf(VERB_ALGO, "refuse", c->buffer);
|
||||
}
|
||||
|
||||
if(worker->stats.extended)
|
||||
worker->stats.unwanted_queries++;
|
||||
if(worker_check_request(c->buffer, worker) == -1) {
|
||||
comm_point_drop_reply(repinfo);
|
||||
return 0; /* discard this */
|
||||
}
|
||||
sldns_buffer_set_limit(c->buffer, LDNS_HEADER_SIZE);
|
||||
sldns_buffer_write_at(c->buffer, 4,
|
||||
(uint8_t*)"\0\0\0\0\0\0\0\0", 8);
|
||||
/* worker_check_request() above guarantees that the buffer contains at
|
||||
* least a header and that qdcount == 1
|
||||
*/
|
||||
log_assert(sldns_buffer_limit(c->buffer) >= LDNS_HEADER_SIZE
|
||||
&& LDNS_QDCOUNT(sldns_buffer_begin(c->buffer)) == 1);
|
||||
|
||||
sldns_buffer_skip(c->buffer, LDNS_HEADER_SIZE); /* skip header */
|
||||
|
||||
/* check additional section is present and that we respond with EDEs */
|
||||
if(LDNS_ARCOUNT(sldns_buffer_begin(c->buffer)) != 1
|
||||
|| !ede) {
|
||||
LDNS_QDCOUNT_SET(sldns_buffer_begin(c->buffer), 0);
|
||||
LDNS_ANCOUNT_SET(sldns_buffer_begin(c->buffer), 0);
|
||||
LDNS_NSCOUNT_SET(sldns_buffer_begin(c->buffer), 0);
|
||||
LDNS_ARCOUNT_SET(sldns_buffer_begin(c->buffer), 0);
|
||||
LDNS_QR_SET(sldns_buffer_begin(c->buffer));
|
||||
LDNS_RCODE_SET(sldns_buffer_begin(c->buffer),
|
||||
LDNS_RCODE_REFUSED);
|
||||
sldns_buffer_flip(c->buffer);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!query_dname_len(c->buffer)) {
|
||||
LDNS_QDCOUNT_SET(sldns_buffer_begin(c->buffer), 0);
|
||||
LDNS_ANCOUNT_SET(sldns_buffer_begin(c->buffer), 0);
|
||||
LDNS_NSCOUNT_SET(sldns_buffer_begin(c->buffer), 0);
|
||||
LDNS_ARCOUNT_SET(sldns_buffer_begin(c->buffer), 0);
|
||||
LDNS_QR_SET(sldns_buffer_begin(c->buffer));
|
||||
LDNS_RCODE_SET(sldns_buffer_begin(c->buffer),
|
||||
LDNS_RCODE_FORMERR);
|
||||
sldns_buffer_set_position(c->buffer, LDNS_HEADER_SIZE);
|
||||
sldns_buffer_flip(c->buffer);
|
||||
return 1;
|
||||
}
|
||||
/* space available for query type and class? */
|
||||
if (sldns_buffer_remaining(c->buffer) < 2 * sizeof(uint16_t)) {
|
||||
LDNS_QR_SET(sldns_buffer_begin(c->buffer));
|
||||
LDNS_RCODE_SET(sldns_buffer_begin(c->buffer),
|
||||
LDNS_RCODE_FORMERR);
|
||||
LDNS_QDCOUNT_SET(sldns_buffer_begin(c->buffer), 0);
|
||||
LDNS_ANCOUNT_SET(sldns_buffer_begin(c->buffer), 0);
|
||||
LDNS_NSCOUNT_SET(sldns_buffer_begin(c->buffer), 0);
|
||||
LDNS_ARCOUNT_SET(sldns_buffer_begin(c->buffer), 0);
|
||||
sldns_buffer_set_position(c->buffer, LDNS_HEADER_SIZE);
|
||||
sldns_buffer_flip(c->buffer);
|
||||
return 1;
|
||||
}
|
||||
LDNS_QR_SET(sldns_buffer_begin(c->buffer));
|
||||
LDNS_RCODE_SET(sldns_buffer_begin(c->buffer),
|
||||
LDNS_RCODE_REFUSED);
|
||||
sldns_buffer_set_position(c->buffer, LDNS_HEADER_SIZE);
|
||||
|
||||
sldns_buffer_skip(c->buffer, (ssize_t)sizeof(uint16_t)); /* skip qtype */
|
||||
|
||||
sldns_buffer_skip(c->buffer, (ssize_t)sizeof(uint16_t)); /* skip qclass */
|
||||
|
||||
/* The OPT RR to be returned should come directly after
|
||||
* the query, so mark this spot.
|
||||
*/
|
||||
opt_rr_mark = sldns_buffer_position(c->buffer);
|
||||
|
||||
/* Skip through the RR records */
|
||||
if(LDNS_ANCOUNT(sldns_buffer_begin(c->buffer)) != 0 ||
|
||||
LDNS_NSCOUNT(sldns_buffer_begin(c->buffer)) != 0) {
|
||||
if(!skip_pkt_rrs(c->buffer,
|
||||
((int)LDNS_ANCOUNT(sldns_buffer_begin(c->buffer)))+
|
||||
((int)LDNS_NSCOUNT(sldns_buffer_begin(c->buffer))))) {
|
||||
LDNS_RCODE_SET(sldns_buffer_begin(c->buffer),
|
||||
LDNS_RCODE_FORMERR);
|
||||
LDNS_ANCOUNT_SET(sldns_buffer_begin(c->buffer), 0);
|
||||
LDNS_NSCOUNT_SET(sldns_buffer_begin(c->buffer), 0);
|
||||
LDNS_ARCOUNT_SET(sldns_buffer_begin(c->buffer), 0);
|
||||
sldns_buffer_set_position(c->buffer, opt_rr_mark);
|
||||
sldns_buffer_flip(c->buffer);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
/* Do we have a valid OPT RR here? If not return REFUSED (could be a valid TSIG or something so no FORMERR) */
|
||||
/* domain name must be the root of length 1. */
|
||||
if(sldns_buffer_remaining(c->buffer) < 1 || *sldns_buffer_current(c->buffer) != 0) {
|
||||
LDNS_ANCOUNT_SET(sldns_buffer_begin(c->buffer), 0);
|
||||
LDNS_NSCOUNT_SET(sldns_buffer_begin(c->buffer), 0);
|
||||
LDNS_ARCOUNT_SET(sldns_buffer_begin(c->buffer), 0);
|
||||
sldns_buffer_set_position(c->buffer, opt_rr_mark);
|
||||
sldns_buffer_flip(c->buffer);
|
||||
return 1;
|
||||
} else {
|
||||
sldns_buffer_skip(c->buffer, 1); /* skip root label */
|
||||
}
|
||||
if(sldns_buffer_remaining(c->buffer) < 2 ||
|
||||
sldns_buffer_read_u16(c->buffer) != LDNS_RR_TYPE_OPT) {
|
||||
LDNS_ANCOUNT_SET(sldns_buffer_begin(c->buffer), 0);
|
||||
LDNS_NSCOUNT_SET(sldns_buffer_begin(c->buffer), 0);
|
||||
LDNS_ARCOUNT_SET(sldns_buffer_begin(c->buffer), 0);
|
||||
sldns_buffer_set_position(c->buffer, opt_rr_mark);
|
||||
sldns_buffer_flip(c->buffer);
|
||||
return 1;
|
||||
}
|
||||
/* Write OPT RR directly after the query,
|
||||
* so without the (possibly skipped) Answer and NS RRs
|
||||
*/
|
||||
LDNS_ANCOUNT_SET(sldns_buffer_begin(c->buffer), 0);
|
||||
LDNS_NSCOUNT_SET(sldns_buffer_begin(c->buffer), 0);
|
||||
sldns_buffer_clear(c->buffer); /* reset write limit */
|
||||
sldns_buffer_set_position(c->buffer, opt_rr_mark);
|
||||
|
||||
/* Check if OPT record can be written
|
||||
* 17 == root label (1) + RR type (2) + UDP Size (2)
|
||||
* + Fields (4) + rdata len (2) + EDE Option code (2)
|
||||
* + EDE Option length (2) + EDE info-code (2)
|
||||
*/
|
||||
if (sldns_buffer_available(c->buffer, 17) == 0) {
|
||||
LDNS_ARCOUNT_SET(sldns_buffer_begin(c->buffer), 0);
|
||||
sldns_buffer_flip(c->buffer);
|
||||
return 1;
|
||||
}
|
||||
|
||||
LDNS_ARCOUNT_SET(sldns_buffer_begin(c->buffer), 1);
|
||||
|
||||
/* root label */
|
||||
sldns_buffer_write_u8(c->buffer, 0);
|
||||
sldns_buffer_write_u16(c->buffer, LDNS_RR_TYPE_OPT);
|
||||
sldns_buffer_write_u16(c->buffer, EDNS_ADVERTISED_SIZE);
|
||||
|
||||
/* write OPT Record TTL Field */
|
||||
sldns_buffer_write_u32(c->buffer, 0);
|
||||
|
||||
/* write rdata len: EDE option + length + info-code */
|
||||
sldns_buffer_write_u16(c->buffer, 6);
|
||||
|
||||
/* write OPTIONS; add EDE option code */
|
||||
sldns_buffer_write_u16(c->buffer, LDNS_EDNS_EDE);
|
||||
|
||||
/* write single EDE option length (for just 1 info-code) */
|
||||
sldns_buffer_write_u16(c->buffer, 2);
|
||||
|
||||
/* write single EDE info-code */
|
||||
sldns_buffer_write_u16(c->buffer, LDNS_EDE_PROHIBITED);
|
||||
|
||||
sldns_buffer_flip(c->buffer);
|
||||
|
||||
verbose(VERB_ALGO, "attached EDE code: %d", LDNS_EDE_PROHIBITED);
|
||||
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
deny_refuse_all(struct comm_point* c, enum acl_access acl,
|
||||
struct worker* worker, struct comm_reply* repinfo)
|
||||
deny_refuse_all(struct comm_point* c, enum acl_access* acl,
|
||||
struct worker* worker, struct comm_reply* repinfo,
|
||||
struct acl_addr** acladdr, int ede, int check_proxy)
|
||||
{
|
||||
return deny_refuse(c, acl, acl_deny, acl_refuse, worker, repinfo);
|
||||
if(check_proxy) {
|
||||
*acladdr = acl_addr_lookup(worker->daemon->acl,
|
||||
&repinfo->remote_addr, repinfo->remote_addrlen);
|
||||
} else {
|
||||
*acladdr = acl_addr_lookup(worker->daemon->acl,
|
||||
&repinfo->client_addr, repinfo->client_addrlen);
|
||||
}
|
||||
/* If there is no ACL based on client IP use the interface ACL. */
|
||||
if(!(*acladdr) && c->socket) {
|
||||
*acladdr = c->socket->acl;
|
||||
}
|
||||
*acl = acl_get_control(*acladdr);
|
||||
return deny_refuse(c, *acl, acl_deny, acl_refuse, worker, repinfo,
|
||||
*acladdr, ede);
|
||||
}
|
||||
|
||||
static int
|
||||
deny_refuse_non_local(struct comm_point* c, enum acl_access acl,
|
||||
struct worker* worker, struct comm_reply* repinfo)
|
||||
struct worker* worker, struct comm_reply* repinfo,
|
||||
struct acl_addr* acladdr, int ede)
|
||||
{
|
||||
return deny_refuse(c, acl, acl_deny_non_local, acl_refuse_non_local, worker, repinfo);
|
||||
return deny_refuse(c, acl, acl_deny_non_local, acl_refuse_non_local,
|
||||
worker, repinfo, acladdr, ede);
|
||||
}
|
||||
|
||||
int
|
||||
int
|
||||
worker_handle_request(struct comm_point* c, void* arg, int error,
|
||||
struct comm_reply* repinfo)
|
||||
{
|
||||
@@ -1067,12 +1266,14 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
|
||||
struct lruhash_entry* e;
|
||||
struct query_info qinfo;
|
||||
struct edns_data edns;
|
||||
struct edns_option* original_edns_list = NULL;
|
||||
enum acl_access acl;
|
||||
struct acl_addr* acladdr;
|
||||
int rc = 0;
|
||||
int need_drop = 0;
|
||||
int is_expired_answer = 0;
|
||||
int is_secure_answer = 0;
|
||||
int rpz_passthru = 0;
|
||||
/* We might have to chase a CNAME chain internally, in which case
|
||||
* we'll have up to two replies and combine them to build a complete
|
||||
* answer. These variables control this case. */
|
||||
@@ -1100,16 +1301,16 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
|
||||
if(worker_check_request(c->buffer, worker) != 0) {
|
||||
verbose(VERB_ALGO,
|
||||
"dnscrypt: worker check request: bad query.");
|
||||
log_addr(VERB_CLIENT,"from",&repinfo->addr,
|
||||
repinfo->addrlen);
|
||||
log_addr(VERB_CLIENT,"from",&repinfo->client_addr,
|
||||
repinfo->client_addrlen);
|
||||
comm_point_drop_reply(repinfo);
|
||||
return 0;
|
||||
}
|
||||
if(!query_info_parse(&qinfo, c->buffer)) {
|
||||
verbose(VERB_ALGO,
|
||||
"dnscrypt: worker parse request: formerror.");
|
||||
log_addr(VERB_CLIENT, "from", &repinfo->addr,
|
||||
repinfo->addrlen);
|
||||
log_addr(VERB_CLIENT, "from", &repinfo->client_addr,
|
||||
repinfo->client_addrlen);
|
||||
comm_point_drop_reply(repinfo);
|
||||
return 0;
|
||||
}
|
||||
@@ -1137,23 +1338,30 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
|
||||
* sending src (client)/dst (local service) addresses over DNSTAP from incoming request handler
|
||||
*/
|
||||
if(worker->dtenv.log_client_query_messages) {
|
||||
log_addr(VERB_ALGO, "request from client", &repinfo->addr, repinfo->addrlen);
|
||||
log_addr(VERB_ALGO, "request from client", &repinfo->client_addr, repinfo->client_addrlen);
|
||||
log_addr(VERB_ALGO, "to local addr", (void*)repinfo->c->socket->addr->ai_addr, repinfo->c->socket->addr->ai_addrlen);
|
||||
dt_msg_send_client_query(&worker->dtenv, &repinfo->addr, (void*)repinfo->c->socket->addr->ai_addr, c->type, c->buffer);
|
||||
dt_msg_send_client_query(&worker->dtenv, &repinfo->client_addr, (void*)repinfo->c->socket->addr->ai_addr, c->type, c->buffer);
|
||||
}
|
||||
#endif
|
||||
acladdr = acl_addr_lookup(worker->daemon->acl, &repinfo->addr,
|
||||
repinfo->addrlen);
|
||||
acl = acl_get_control(acladdr);
|
||||
if((ret=deny_refuse_all(c, acl, worker, repinfo)) != -1)
|
||||
{
|
||||
/* Check deny/refuse ACLs */
|
||||
if(repinfo->is_proxied) {
|
||||
if((ret=deny_refuse_all(c, &acl, worker, repinfo, &acladdr,
|
||||
worker->env.cfg->ede, 1)) != -1) {
|
||||
if(ret == 1)
|
||||
goto send_reply;
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
if((ret=deny_refuse_all(c, &acl, worker, repinfo, &acladdr,
|
||||
worker->env.cfg->ede, 0)) != -1) {
|
||||
if(ret == 1)
|
||||
goto send_reply;
|
||||
return ret;
|
||||
}
|
||||
|
||||
if((ret=worker_check_request(c->buffer, worker)) != 0) {
|
||||
verbose(VERB_ALGO, "worker check request: bad query.");
|
||||
log_addr(VERB_CLIENT,"from",&repinfo->addr, repinfo->addrlen);
|
||||
log_addr(VERB_CLIENT,"from",&repinfo->client_addr, repinfo->client_addrlen);
|
||||
if(ret != -1) {
|
||||
LDNS_QR_SET(sldns_buffer_begin(c->buffer));
|
||||
LDNS_RCODE_SET(sldns_buffer_begin(c->buffer), ret);
|
||||
@@ -1165,19 +1373,24 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
|
||||
|
||||
worker->stats.num_queries++;
|
||||
|
||||
/* check if this query should be dropped based on source ip rate limiting */
|
||||
if(!infra_ip_ratelimit_inc(worker->env.infra_cache, repinfo,
|
||||
*worker->env.now, c->buffer)) {
|
||||
/* check if this query should be dropped based on source ip rate limiting
|
||||
* NOTE: we always check the repinfo->client_address. IP ratelimiting is
|
||||
* implicitly disabled for proxies. */
|
||||
if(!infra_ip_ratelimit_inc(worker->env.infra_cache,
|
||||
&repinfo->client_addr, repinfo->client_addrlen,
|
||||
*worker->env.now,
|
||||
worker->env.cfg->ip_ratelimit_backoff, c->buffer)) {
|
||||
/* See if we are passed through with slip factor */
|
||||
if(worker->env.cfg->ip_ratelimit_factor != 0 &&
|
||||
ub_random_max(worker->env.rnd,
|
||||
worker->env.cfg->ip_ratelimit_factor) == 0) {
|
||||
|
||||
worker->env.cfg->ip_ratelimit_factor) == 0) {
|
||||
char addrbuf[128];
|
||||
addr_to_str(&repinfo->addr, repinfo->addrlen,
|
||||
addrbuf, sizeof(addrbuf));
|
||||
verbose(VERB_QUERY, "ip_ratelimit allowed through for ip address %s because of slip in ip_ratelimit_factor",
|
||||
addrbuf);
|
||||
addr_to_str(&repinfo->client_addr,
|
||||
repinfo->client_addrlen, addrbuf,
|
||||
sizeof(addrbuf));
|
||||
verbose(VERB_QUERY, "ip_ratelimit allowed through for "
|
||||
"ip address %s because of slip in "
|
||||
"ip_ratelimit_factor", addrbuf);
|
||||
} else {
|
||||
worker->stats.num_queries_ip_ratelimited++;
|
||||
comm_point_drop_reply(repinfo);
|
||||
@@ -1188,7 +1401,8 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
|
||||
/* see if query is in the cache */
|
||||
if(!query_info_parse(&qinfo, c->buffer)) {
|
||||
verbose(VERB_ALGO, "worker parse request: formerror.");
|
||||
log_addr(VERB_CLIENT,"from",&repinfo->addr, repinfo->addrlen);
|
||||
log_addr(VERB_CLIENT, "from", &repinfo->client_addr,
|
||||
repinfo->client_addrlen);
|
||||
memset(&qinfo, 0, sizeof(qinfo)); /* zero qinfo.qname */
|
||||
if(worker_err_ratelimit(worker, LDNS_RCODE_FORMERR) == -1) {
|
||||
comm_point_drop_reply(repinfo);
|
||||
@@ -1202,13 +1416,14 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
|
||||
}
|
||||
if(worker->env.cfg->log_queries) {
|
||||
char ip[128];
|
||||
addr_to_str(&repinfo->addr, repinfo->addrlen, ip, sizeof(ip));
|
||||
addr_to_str(&repinfo->client_addr, repinfo->client_addrlen, ip, sizeof(ip));
|
||||
log_query_in(ip, qinfo.qname, qinfo.qtype, qinfo.qclass);
|
||||
}
|
||||
if(qinfo.qtype == LDNS_RR_TYPE_AXFR ||
|
||||
qinfo.qtype == LDNS_RR_TYPE_IXFR) {
|
||||
verbose(VERB_ALGO, "worker request: refused zone transfer.");
|
||||
log_addr(VERB_CLIENT,"from",&repinfo->addr, repinfo->addrlen);
|
||||
log_addr(VERB_CLIENT, "from", &repinfo->client_addr,
|
||||
repinfo->client_addrlen);
|
||||
sldns_buffer_rewind(c->buffer);
|
||||
LDNS_QR_SET(sldns_buffer_begin(c->buffer));
|
||||
LDNS_RCODE_SET(sldns_buffer_begin(c->buffer),
|
||||
@@ -1225,7 +1440,8 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
|
||||
qinfo.qtype == LDNS_RR_TYPE_MAILB ||
|
||||
(qinfo.qtype >= 128 && qinfo.qtype <= 248)) {
|
||||
verbose(VERB_ALGO, "worker request: formerror for meta-type.");
|
||||
log_addr(VERB_CLIENT,"from",&repinfo->addr, repinfo->addrlen);
|
||||
log_addr(VERB_CLIENT, "from", &repinfo->client_addr,
|
||||
repinfo->client_addrlen);
|
||||
if(worker_err_ratelimit(worker, LDNS_RCODE_FORMERR) == -1) {
|
||||
comm_point_drop_reply(repinfo);
|
||||
return 0;
|
||||
@@ -1243,7 +1459,8 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
|
||||
worker->scratchpad)) != 0) {
|
||||
struct edns_data reply_edns;
|
||||
verbose(VERB_ALGO, "worker parse edns: formerror.");
|
||||
log_addr(VERB_CLIENT,"from",&repinfo->addr, repinfo->addrlen);
|
||||
log_addr(VERB_CLIENT, "from", &repinfo->client_addr,
|
||||
repinfo->client_addrlen);
|
||||
memset(&reply_edns, 0, sizeof(reply_edns));
|
||||
reply_edns.edns_present = 1;
|
||||
reply_edns.udp_size = EDNS_ADVERTISED_SIZE;
|
||||
@@ -1265,7 +1482,8 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
|
||||
edns.opt_list_inplace_cb_out = NULL;
|
||||
edns.padding_block_size = 0;
|
||||
verbose(VERB_ALGO, "query with bad edns version.");
|
||||
log_addr(VERB_CLIENT,"from",&repinfo->addr, repinfo->addrlen);
|
||||
log_addr(VERB_CLIENT, "from", &repinfo->client_addr,
|
||||
repinfo->client_addrlen);
|
||||
error_encode(c->buffer, EDNS_RCODE_BADVERS&0xf, &qinfo,
|
||||
*(uint16_t*)(void *)sldns_buffer_begin(c->buffer),
|
||||
sldns_buffer_read_u16_at(c->buffer, 2), NULL);
|
||||
@@ -1279,7 +1497,8 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
|
||||
worker->daemon->cfg->harden_short_bufsize) {
|
||||
verbose(VERB_QUERY, "worker request: EDNS bufsize %d ignored",
|
||||
(int)edns.udp_size);
|
||||
log_addr(VERB_CLIENT,"from",&repinfo->addr, repinfo->addrlen);
|
||||
log_addr(VERB_CLIENT, "from", &repinfo->client_addr,
|
||||
repinfo->client_addrlen);
|
||||
edns.udp_size = NORMAL_UDP_SIZE;
|
||||
}
|
||||
}
|
||||
@@ -1288,12 +1507,14 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
|
||||
verbose(VERB_QUERY,
|
||||
"worker request: max UDP reply size modified"
|
||||
" (%d to max-udp-size)", (int)edns.udp_size);
|
||||
log_addr(VERB_CLIENT,"from",&repinfo->addr, repinfo->addrlen);
|
||||
log_addr(VERB_CLIENT, "from", &repinfo->client_addr,
|
||||
repinfo->client_addrlen);
|
||||
edns.udp_size = worker->daemon->cfg->max_udp_size;
|
||||
}
|
||||
if(edns.udp_size < LDNS_HEADER_SIZE) {
|
||||
verbose(VERB_ALGO, "worker request: edns is too small.");
|
||||
log_addr(VERB_CLIENT, "from", &repinfo->addr, repinfo->addrlen);
|
||||
log_addr(VERB_CLIENT, "from", &repinfo->client_addr,
|
||||
repinfo->client_addrlen);
|
||||
LDNS_QR_SET(sldns_buffer_begin(c->buffer));
|
||||
LDNS_TC_SET(sldns_buffer_begin(c->buffer));
|
||||
LDNS_RCODE_SET(sldns_buffer_begin(c->buffer),
|
||||
@@ -1317,7 +1538,8 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
|
||||
}
|
||||
if(LDNS_OPCODE_WIRE(sldns_buffer_begin(c->buffer)) ==
|
||||
LDNS_PACKET_NOTIFY) {
|
||||
answer_notify(worker, &qinfo, &edns, c->buffer, repinfo);
|
||||
answer_notify(worker, &qinfo, &edns, c->buffer,
|
||||
&repinfo->client_addr, repinfo->client_addrlen);
|
||||
regional_free_all(worker->scratchpad);
|
||||
goto send_reply;
|
||||
}
|
||||
@@ -1337,7 +1559,8 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
|
||||
if(worker->env.auth_zones &&
|
||||
rpz_callback_from_worker_request(worker->env.auth_zones,
|
||||
&worker->env, &qinfo, &edns, c->buffer, worker->scratchpad,
|
||||
repinfo, acladdr->taglist, acladdr->taglen, &worker->stats)) {
|
||||
repinfo, acladdr->taglist, acladdr->taglen, &worker->stats,
|
||||
&rpz_passthru)) {
|
||||
regional_free_all(worker->scratchpad);
|
||||
if(sldns_buffer_limit(c->buffer) == 0) {
|
||||
comm_point_drop_reply(repinfo);
|
||||
@@ -1363,7 +1586,8 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
|
||||
|
||||
/* We've looked in our local zones. If the answer isn't there, we
|
||||
* might need to bail out based on ACLs now. */
|
||||
if((ret=deny_refuse_non_local(c, acl, worker, repinfo)) != -1)
|
||||
if((ret=deny_refuse_non_local(c, acl, worker, repinfo, acladdr,
|
||||
worker->env.cfg->ede)) != -1)
|
||||
{
|
||||
regional_free_all(worker->scratchpad);
|
||||
if(ret == 1)
|
||||
@@ -1382,12 +1606,17 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
|
||||
* ACLs allow the snooping. */
|
||||
if(!(LDNS_RD_WIRE(sldns_buffer_begin(c->buffer))) &&
|
||||
acl != acl_allow_snoop ) {
|
||||
if (worker->env.cfg->ede) {
|
||||
EDNS_OPT_LIST_APPEND_EDE(&edns.opt_list_out,
|
||||
worker->scratchpad, LDNS_EDE_NOT_AUTHORITATIVE, "");
|
||||
}
|
||||
error_encode(c->buffer, LDNS_RCODE_REFUSED, &qinfo,
|
||||
*(uint16_t*)(void *)sldns_buffer_begin(c->buffer),
|
||||
sldns_buffer_read_u16_at(c->buffer, 2), NULL);
|
||||
sldns_buffer_read_u16_at(c->buffer, 2), &edns);
|
||||
regional_free_all(worker->scratchpad);
|
||||
log_addr(VERB_ALGO, "refused nonrec (cache snoop) query from",
|
||||
&repinfo->addr, repinfo->addrlen);
|
||||
&repinfo->client_addr, repinfo->client_addrlen);
|
||||
|
||||
goto send_reply;
|
||||
}
|
||||
|
||||
@@ -1428,6 +1657,11 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
|
||||
cinfo = &cinfo_tmp;
|
||||
}
|
||||
|
||||
/* Keep the original edns list around. The pointer could change if there is
|
||||
* a cached answer (through the inplace callback function there).
|
||||
* No need to actually copy the contents as they shouldn't change.
|
||||
* Used while prefetching and subnet is enabled. */
|
||||
original_edns_list = edns.opt_list_in;
|
||||
lookup_cache:
|
||||
/* Lookup the cache. In case we chase an intermediate CNAME chain
|
||||
* this is a two-pass operation, and lookup_qinfo is different for
|
||||
@@ -1438,10 +1672,11 @@ lookup_cache:
|
||||
is_secure_answer = 0;
|
||||
h = query_info_hash(lookup_qinfo, sldns_buffer_read_u16_at(c->buffer, 2));
|
||||
if((e=slabhash_lookup(worker->env.msg_cache, h, lookup_qinfo, 0))) {
|
||||
struct reply_info* rep = (struct reply_info*)e->data;
|
||||
/* answer from cache - we have acquired a readlock on it */
|
||||
if(answer_from_cache(worker, &qinfo,
|
||||
cinfo, &need_drop, &is_expired_answer, &is_secure_answer,
|
||||
&alias_rrset, &partial_rep, (struct reply_info*)e->data,
|
||||
if(answer_from_cache(worker, &qinfo, cinfo, &need_drop,
|
||||
&is_expired_answer, &is_secure_answer,
|
||||
&alias_rrset, &partial_rep, rep,
|
||||
*(uint16_t*)(void *)sldns_buffer_begin(c->buffer),
|
||||
sldns_buffer_read_u16_at(c->buffer, 2), repinfo,
|
||||
&edns)) {
|
||||
@@ -1449,21 +1684,22 @@ lookup_cache:
|
||||
* Note that if there is more than one pass
|
||||
* its qname must be that used for cache
|
||||
* lookup. */
|
||||
if((worker->env.cfg->prefetch && *worker->env.now >=
|
||||
((struct reply_info*)e->data)->prefetch_ttl) ||
|
||||
(worker->env.cfg->serve_expired &&
|
||||
*worker->env.now >= ((struct reply_info*)e->data)->ttl)) {
|
||||
if((worker->env.cfg->prefetch &&
|
||||
*worker->env.now >= rep->prefetch_ttl) ||
|
||||
(worker->env.cfg->serve_expired &&
|
||||
*worker->env.now > rep->ttl)) {
|
||||
|
||||
time_t leeway = ((struct reply_info*)e->
|
||||
data)->ttl - *worker->env.now;
|
||||
if(((struct reply_info*)e->data)->ttl
|
||||
< *worker->env.now)
|
||||
time_t leeway = rep->ttl - *worker->env.now;
|
||||
if(rep->ttl < *worker->env.now)
|
||||
leeway = 0;
|
||||
lock_rw_unlock(&e->lock);
|
||||
|
||||
reply_and_prefetch(worker, lookup_qinfo,
|
||||
sldns_buffer_read_u16_at(c->buffer, 2),
|
||||
repinfo, leeway,
|
||||
(partial_rep || need_drop));
|
||||
(partial_rep || need_drop),
|
||||
rpz_passthru,
|
||||
original_edns_list);
|
||||
if(!partial_rep) {
|
||||
rc = 0;
|
||||
regional_free_all(worker->scratchpad);
|
||||
@@ -1500,6 +1736,7 @@ lookup_cache:
|
||||
verbose(VERB_ALGO, "answer from the cache failed");
|
||||
lock_rw_unlock(&e->lock);
|
||||
}
|
||||
|
||||
if(!LDNS_RD_WIRE(sldns_buffer_begin(c->buffer))) {
|
||||
if(answer_norec_from_cache(worker, &qinfo,
|
||||
*(uint16_t*)(void *)sldns_buffer_begin(c->buffer),
|
||||
@@ -1518,15 +1755,16 @@ lookup_cache:
|
||||
if(verbosity >= VERB_CLIENT) {
|
||||
if(c->type == comm_udp)
|
||||
log_addr(VERB_CLIENT, "udp request from",
|
||||
&repinfo->addr, repinfo->addrlen);
|
||||
&repinfo->client_addr, repinfo->client_addrlen);
|
||||
else log_addr(VERB_CLIENT, "tcp request from",
|
||||
&repinfo->addr, repinfo->addrlen);
|
||||
&repinfo->client_addr, repinfo->client_addrlen);
|
||||
}
|
||||
|
||||
/* grab a work request structure for this new request */
|
||||
mesh_new_client(worker->env.mesh, &qinfo, cinfo,
|
||||
sldns_buffer_read_u16_at(c->buffer, 2),
|
||||
&edns, repinfo, *(uint16_t*)(void *)sldns_buffer_begin(c->buffer));
|
||||
&edns, repinfo, *(uint16_t*)(void *)sldns_buffer_begin(c->buffer),
|
||||
rpz_passthru);
|
||||
regional_free_all(worker->scratchpad);
|
||||
worker_mem_report(worker, NULL);
|
||||
return 0;
|
||||
@@ -1551,8 +1789,8 @@ send_reply_rc:
|
||||
*/
|
||||
if(worker->dtenv.log_client_response_messages) {
|
||||
log_addr(VERB_ALGO, "from local addr", (void*)repinfo->c->socket->addr->ai_addr, repinfo->c->socket->addr->ai_addrlen);
|
||||
log_addr(VERB_ALGO, "response to client", &repinfo->addr, repinfo->addrlen);
|
||||
dt_msg_send_client_response(&worker->dtenv, &repinfo->addr, (void*)repinfo->c->socket->addr->ai_addr, c->type, c->buffer);
|
||||
log_addr(VERB_ALGO, "response to client", &repinfo->client_addr, repinfo->client_addrlen);
|
||||
dt_msg_send_client_response(&worker->dtenv, &repinfo->client_addr, (void*)repinfo->c->socket->addr->ai_addr, c->type, c->buffer);
|
||||
}
|
||||
#endif
|
||||
if(worker->env.cfg->log_replies)
|
||||
@@ -1564,10 +1802,12 @@ send_reply_rc:
|
||||
/* log original qname, before the local alias was
|
||||
* used to resolve that CNAME to something else */
|
||||
qinfo.qname = qinfo.local_alias->rrset->rk.dname;
|
||||
log_reply_info(NO_VERBOSE, &qinfo, &repinfo->addr, repinfo->addrlen,
|
||||
log_reply_info(NO_VERBOSE, &qinfo,
|
||||
&repinfo->client_addr, repinfo->client_addrlen,
|
||||
tv, 1, c->buffer);
|
||||
} else {
|
||||
log_reply_info(NO_VERBOSE, &qinfo, &repinfo->addr, repinfo->addrlen,
|
||||
log_reply_info(NO_VERBOSE, &qinfo,
|
||||
&repinfo->client_addr, repinfo->client_addrlen,
|
||||
tv, 1, c->buffer);
|
||||
}
|
||||
}
|
||||
@@ -1590,6 +1830,9 @@ worker_sighandler(int sig, void* arg)
|
||||
case SIGHUP:
|
||||
comm_base_exit(worker->base);
|
||||
break;
|
||||
#endif
|
||||
#ifdef SIGBREAK
|
||||
case SIGBREAK:
|
||||
#endif
|
||||
case SIGINT:
|
||||
worker->need_to_exit = 1;
|
||||
@@ -1695,6 +1938,9 @@ worker_init(struct worker* worker, struct config_file *cfg,
|
||||
struct dt_env* dtenv = &worker->dtenv;
|
||||
#else
|
||||
void* dtenv = NULL;
|
||||
#endif
|
||||
#ifdef HAVE_GETTID
|
||||
worker->thread_tid = gettid();
|
||||
#endif
|
||||
worker->need_to_exit = 0;
|
||||
worker->base = comm_base_create(do_sigs);
|
||||
@@ -1708,6 +1954,9 @@ worker_init(struct worker* worker, struct config_file *cfg,
|
||||
if(do_sigs) {
|
||||
#ifdef SIGHUP
|
||||
ub_thread_sig_unblock(SIGHUP);
|
||||
#endif
|
||||
#ifdef SIGBREAK
|
||||
ub_thread_sig_unblock(SIGBREAK);
|
||||
#endif
|
||||
ub_thread_sig_unblock(SIGINT);
|
||||
#ifdef SIGQUIT
|
||||
@@ -1725,6 +1974,9 @@ worker_init(struct worker* worker, struct config_file *cfg,
|
||||
|| !comm_signal_bind(worker->comsig, SIGQUIT)
|
||||
#endif
|
||||
|| !comm_signal_bind(worker->comsig, SIGTERM)
|
||||
#ifdef SIGBREAK
|
||||
|| !comm_signal_bind(worker->comsig, SIGBREAK)
|
||||
#endif
|
||||
|| !comm_signal_bind(worker->comsig, SIGINT)) {
|
||||
log_err("could not create signal handlers");
|
||||
worker_delete(worker);
|
||||
@@ -1967,9 +2219,10 @@ worker_delete(struct worker* worker)
|
||||
|
||||
struct outbound_entry*
|
||||
worker_send_query(struct query_info* qinfo, uint16_t flags, int dnssec,
|
||||
int want_dnssec, int nocaps, struct sockaddr_storage* addr,
|
||||
socklen_t addrlen, uint8_t* zone, size_t zonelen, int tcp_upstream,
|
||||
int ssl_upstream, char* tls_auth_name, struct module_qstate* q)
|
||||
int want_dnssec, int nocaps, int check_ratelimit,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* zone,
|
||||
size_t zonelen, int tcp_upstream, int ssl_upstream, char* tls_auth_name,
|
||||
struct module_qstate* q, int* was_ratelimited)
|
||||
{
|
||||
struct worker* worker = q->env->worker;
|
||||
struct outbound_entry* e = (struct outbound_entry*)regional_alloc(
|
||||
@@ -1978,9 +2231,10 @@ worker_send_query(struct query_info* qinfo, uint16_t flags, int dnssec,
|
||||
return NULL;
|
||||
e->qstate = q;
|
||||
e->qsent = outnet_serviced_query(worker->back, qinfo, flags, dnssec,
|
||||
want_dnssec, nocaps, tcp_upstream,
|
||||
want_dnssec, nocaps, check_ratelimit, tcp_upstream,
|
||||
ssl_upstream, tls_auth_name, addr, addrlen, zone, zonelen, q,
|
||||
worker_handle_service_reply, e, worker->back->udp_buff, q->env);
|
||||
worker_handle_service_reply, e, worker->back->udp_buff, q->env,
|
||||
was_ratelimited);
|
||||
if(!e->qsent) {
|
||||
return NULL;
|
||||
}
|
||||
@@ -2001,6 +2255,7 @@ void worker_stats_clear(struct worker* worker)
|
||||
mesh_stats_clear(worker->env.mesh);
|
||||
worker->back->unwanted_replies = 0;
|
||||
worker->back->num_tcp_outgoing = 0;
|
||||
worker->back->num_udp_outgoing = 0;
|
||||
}
|
||||
|
||||
void worker_start_accept(void* arg)
|
||||
@@ -2024,10 +2279,11 @@ struct outbound_entry* libworker_send_query(
|
||||
struct query_info* ATTR_UNUSED(qinfo),
|
||||
uint16_t ATTR_UNUSED(flags), int ATTR_UNUSED(dnssec),
|
||||
int ATTR_UNUSED(want_dnssec), int ATTR_UNUSED(nocaps),
|
||||
int ATTR_UNUSED(check_ratelimit),
|
||||
struct sockaddr_storage* ATTR_UNUSED(addr), socklen_t ATTR_UNUSED(addrlen),
|
||||
uint8_t* ATTR_UNUSED(zone), size_t ATTR_UNUSED(zonelen), int ATTR_UNUSED(tcp_upstream),
|
||||
int ATTR_UNUSED(ssl_upstream), char* ATTR_UNUSED(tls_auth_name),
|
||||
struct module_qstate* ATTR_UNUSED(q))
|
||||
struct module_qstate* ATTR_UNUSED(q), int* ATTR_UNUSED(was_ratelimited))
|
||||
{
|
||||
log_assert(0);
|
||||
return 0;
|
||||
|
||||
@@ -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 */
|
||||
|
||||
+2
-2
@@ -652,7 +652,7 @@ handle_event_moddone(struct module_qstate* qstate, int id)
|
||||
if ( (!iq || !iq->started_no_cache_store) &&
|
||||
qstate->return_msg && qstate->return_msg->rep &&
|
||||
!dns_cache_store(qstate->env, &qstate->qinfo, qstate->return_msg->rep,
|
||||
0, 0, 0, NULL, qstate->query_flags))
|
||||
0, 0, 0, NULL, qstate->query_flags, qstate->qstarttime))
|
||||
log_err("out of memory");
|
||||
|
||||
/* do nothing */
|
||||
@@ -991,7 +991,7 @@ dns64_inform_super(struct module_qstate* qstate, int id,
|
||||
/* Store the generated response in cache. */
|
||||
if ( (!super_dq || !super_dq->started_no_cache_store) &&
|
||||
!dns_cache_store(super->env, &super->qinfo, super->return_msg->rep,
|
||||
0, 0, 0, NULL, super->query_flags))
|
||||
0, 0, 0, NULL, super->query_flags, qstate->qstarttime))
|
||||
log_err("out of memory");
|
||||
}
|
||||
|
||||
|
||||
+17
-12
@@ -188,9 +188,9 @@ mq_wakeup_cb(void* arg)
|
||||
|
||||
/** start timer to wakeup dtio because there is content in the queue */
|
||||
static void
|
||||
dt_msg_queue_start_timer(struct dt_msg_queue* mq)
|
||||
dt_msg_queue_start_timer(struct dt_msg_queue* mq, int wakeupnow)
|
||||
{
|
||||
struct timeval tv;
|
||||
struct timeval tv = {0};
|
||||
/* Start a timer to process messages to be logged.
|
||||
* If we woke up the dtio thread for every message, the wakeup
|
||||
* messages take up too much processing power. If the queue
|
||||
@@ -204,19 +204,26 @@ dt_msg_queue_start_timer(struct dt_msg_queue* mq)
|
||||
|
||||
/* do not start the timer if a timer already exists, perhaps
|
||||
* in another worker. So this variable is protected by a lock in
|
||||
* dtio */
|
||||
* dtio. */
|
||||
|
||||
/* If we need to wakeupnow, 0 the timer to force the callback. */
|
||||
lock_basic_lock(&mq->dtio->wakeup_timer_lock);
|
||||
if(mq->dtio->wakeup_timer_enabled) {
|
||||
if(wakeupnow) {
|
||||
comm_timer_set(mq->wakeup_timer, &tv);
|
||||
}
|
||||
lock_basic_unlock(&mq->dtio->wakeup_timer_lock);
|
||||
return;
|
||||
}
|
||||
mq->dtio->wakeup_timer_enabled = 1; /* we are going to start one */
|
||||
lock_basic_unlock(&mq->dtio->wakeup_timer_lock);
|
||||
|
||||
/* start the timer, in mq, in the event base of our worker */
|
||||
tv.tv_sec = 1;
|
||||
tv.tv_usec = 0;
|
||||
if(!wakeupnow) {
|
||||
tv.tv_sec = 1;
|
||||
tv.tv_usec = 0;
|
||||
}
|
||||
comm_timer_set(mq->wakeup_timer, &tv);
|
||||
lock_basic_unlock(&mq->dtio->wakeup_timer_lock);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -283,10 +290,8 @@ dt_msg_queue_submit(struct dt_msg_queue* mq, void* buf, size_t len)
|
||||
/* release lock */
|
||||
lock_basic_unlock(&mq->lock);
|
||||
|
||||
if(wakeupnow) {
|
||||
dtio_wakeup(mq->dtio);
|
||||
} else if(wakeupstarttimer) {
|
||||
dt_msg_queue_start_timer(mq);
|
||||
if(wakeupnow || wakeupstarttimer) {
|
||||
dt_msg_queue_start_timer(mq, wakeupnow);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -949,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;
|
||||
@@ -1955,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;
|
||||
}
|
||||
|
||||
@@ -272,7 +272,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;
|
||||
}
|
||||
@@ -617,7 +617,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",
|
||||
@@ -1413,11 +1413,12 @@ void worker_sighandler(int ATTR_UNUSED(sig), void* ATTR_UNUSED(arg))
|
||||
struct outbound_entry* worker_send_query(
|
||||
struct query_info* ATTR_UNUSED(qinfo), uint16_t ATTR_UNUSED(flags),
|
||||
int ATTR_UNUSED(dnssec), int ATTR_UNUSED(want_dnssec),
|
||||
int ATTR_UNUSED(nocaps), struct sockaddr_storage* ATTR_UNUSED(addr),
|
||||
int ATTR_UNUSED(nocaps), int ATTR_UNUSED(check_ratelimit),
|
||||
struct sockaddr_storage* ATTR_UNUSED(addr),
|
||||
socklen_t ATTR_UNUSED(addrlen), uint8_t* ATTR_UNUSED(zone),
|
||||
size_t ATTR_UNUSED(zonelen), int ATTR_UNUSED(tcp_upstream),
|
||||
int ATTR_UNUSED(ssl_upstream), char* ATTR_UNUSED(tls_auth_name),
|
||||
struct module_qstate* ATTR_UNUSED(q))
|
||||
struct module_qstate* ATTR_UNUSED(q), int* ATTR_UNUSED(was_ratelimited))
|
||||
{
|
||||
log_assert(0);
|
||||
return 0;
|
||||
@@ -1446,11 +1447,12 @@ worker_alloc_cleanup(void* ATTR_UNUSED(arg))
|
||||
struct outbound_entry* libworker_send_query(
|
||||
struct query_info* ATTR_UNUSED(qinfo), uint16_t ATTR_UNUSED(flags),
|
||||
int ATTR_UNUSED(dnssec), int ATTR_UNUSED(want_dnssec),
|
||||
int ATTR_UNUSED(nocaps), struct sockaddr_storage* ATTR_UNUSED(addr),
|
||||
int ATTR_UNUSED(nocaps), int ATTR_UNUSED(check_ratelimit),
|
||||
struct sockaddr_storage* ATTR_UNUSED(addr),
|
||||
socklen_t ATTR_UNUSED(addrlen), uint8_t* ATTR_UNUSED(zone),
|
||||
size_t ATTR_UNUSED(zonelen), int ATTR_UNUSED(tcp_upstream),
|
||||
int ATTR_UNUSED(ssl_upstream), char* ATTR_UNUSED(tls_auth_name),
|
||||
struct module_qstate* ATTR_UNUSED(q))
|
||||
struct module_qstate* ATTR_UNUSED(q), int* ATTR_UNUSED(was_ratelimited))
|
||||
{
|
||||
log_assert(0);
|
||||
return 0;
|
||||
|
||||
+514
@@ -1,5 +1,519 @@
|
||||
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:'.
|
||||
|
||||
19 July 2022: Wouter
|
||||
- Merge #718: Introduce infra-cache-max-rtt option to config max
|
||||
retransmit timeout.
|
||||
|
||||
15 July 2022: Wouter
|
||||
- Merge PR 714: Avoid treat normal hosts as unresponsive servers.
|
||||
And fixup the lock code.
|
||||
- iana portlist update.
|
||||
|
||||
12 July 2022: George
|
||||
- For windows crosscompile, fix setting the IPV6_MTU socket option
|
||||
equivalent (IPV6_USER_MTU); allows cross compiling with latest
|
||||
cross-compiler versions.
|
||||
|
||||
12 July 2022: Wouter
|
||||
- Fix dname count in sldns parse type descriptor for SVCB and HTTPS.
|
||||
|
||||
11 July 2022: Wouter
|
||||
- Fix verbose EDE error printout.
|
||||
|
||||
4 July 2022: George
|
||||
- Fix bug introduced in 'improve val_sigcrypt.c::algo_needs_missing for
|
||||
one loop pass'.
|
||||
- Merge PR #668 from Cristian Rodríguez: Set IP_BIND_ADDRESS_NO_PORT on
|
||||
outbound tcp sockets.
|
||||
|
||||
4 July 2022: Wouter
|
||||
- Tag for 1.16.1rc1 release. This became 1.16.1 on 11 July 2022.
|
||||
The code repo continues with version 1.16.2 under development.
|
||||
|
||||
3 July 2022: George
|
||||
- Merge PR #671 from Petr Menšík: Disable ED25519 and ED448 in FIPS
|
||||
mode on openssl3.
|
||||
- Merge PR #660 from Petr Menšík: Sha1 runtime insecure.
|
||||
- For #660: formatting, less verbose logging, add EDE information.
|
||||
- Fix for correct openssl error when adding windows CA certificates to
|
||||
the openssl trust store.
|
||||
- Improve val_sigcrypt.c::algo_needs_missing for one loop pass.
|
||||
- Reintroduce documentation and more EDE support for
|
||||
val_sigcrypt.c::dnskeyset_verify_rrset_sig.
|
||||
|
||||
1 July 2022: George
|
||||
- Merge PR #706: NXNS fallback.
|
||||
- From #706: Cached NXDOMAIN does not increase the target nx
|
||||
responses.
|
||||
- From #706: Don't generate parent side queries if we already
|
||||
have the lame records in cache.
|
||||
- From #706: When a lame address is the best choice, don't try to
|
||||
generate target queries when the missing targets are all lame.
|
||||
|
||||
29 June 2022: Wouter
|
||||
- iana portlist update.
|
||||
- Fix detection of libz on windows compile with static option.
|
||||
- Fix compile warning for windows compile.
|
||||
|
||||
29 June 2022: George
|
||||
- Add debug option to the mini_tdir.sh test code.
|
||||
- Fix #704: [FR] Statistics counter for number of outgoing UDP queries
|
||||
sent; introduces 'num.query.udpout' to the 'unbound-control stats'
|
||||
command.
|
||||
- Fix to not count cached NXDOMAIN for MAX_TARGET_NX.
|
||||
- Allow fallback to the parent side when MAX_TARGET_NX is reached.
|
||||
This will also allow MAX_TARGET_NX more NXDOMAINs.
|
||||
|
||||
28 June 2022: George
|
||||
- Show the output of the exact .rpl run that failed with 'make test'.
|
||||
- Fix for cached 0 TTL records to not trigger prefetching when
|
||||
serve-expired-client-timeout is set.
|
||||
|
||||
28 June 2022: Wouter
|
||||
- Fix test program dohclient close to use portability routine.
|
||||
|
||||
23 June 2022: Tom
|
||||
- Clarify -v flag manpage entry (#705)
|
||||
|
||||
22 June 2022: Philip
|
||||
- Fix #663: use after free issue with edns options.
|
||||
|
||||
21 June 2022: Philip
|
||||
- Fix for loading locally stored zones that have lines with blanks or
|
||||
blanks and comments.
|
||||
|
||||
20 June 2022: George
|
||||
- Remove unused LDNS function check for GOST Engine unloading.
|
||||
|
||||
14 June 2022: George
|
||||
- Merge PR #688: Rpz url notify issue.
|
||||
- Note in the unbound.conf text that NOTIFY is allowed from the url:
|
||||
addresses for auth and rpz zones.
|
||||
|
||||
3 June 2022: George
|
||||
- Fix for edns client subnet to respect not looking in its cache when
|
||||
instructed to do so (e.g., prefetch).
|
||||
|
||||
3 June 2022: Wouter
|
||||
- makedist.sh picks up 32bit libssp-0.dll when 32bit compile.
|
||||
|
||||
27 May 2022: Wouter
|
||||
- Fix #684: [FTBS] configure script error with libmnl on openSUSE 15.3 (and possibly other distributions)
|
||||
- Version is set to 1.16.0 for release. Release tag 1.16.0rc1. This
|
||||
became release 1.16.0 on 2 June 2022. The source code branch
|
||||
continues with version 1.16.1 under development.
|
||||
|
||||
20 May 2022: Wouter
|
||||
- Fix to silence test for ede error output to the console from the
|
||||
test setup script.
|
||||
- Fix ede test to not use default pidfile, and use local interface.
|
||||
- Fix some lint type warnings.
|
||||
|
||||
18 May 2022: George
|
||||
- Fix typos in config_set_option for the 'num-threads' and
|
||||
'ede-serve-expired' options.
|
||||
|
||||
15 May 2022: George
|
||||
- Fix #678: [FR] modify behaviour of unbound-control rpz_enable zone,
|
||||
by updating unbound-control's documentation.
|
||||
|
||||
12 May 2022: George
|
||||
- Fix #417: prefetch and ECS causing cache corruption when used
|
||||
together.
|
||||
|
||||
12 May 2022: Wouter
|
||||
- Merge #677: Allow using system certificates not only on Windows,
|
||||
from pemensik.
|
||||
- For #677: Added tls-system-cert to config parser and documentation.
|
||||
|
||||
11 May 2022: Wouter
|
||||
- Fix #673: DNS over TLS: error: SSL_handshake syscall: No route to
|
||||
host.
|
||||
|
||||
10 May 2022: George
|
||||
- Fix Python build in non-source directory; based on patch by
|
||||
Michael Tokarev.
|
||||
|
||||
6 May 2022: Tom
|
||||
- Merge PR #604: Add basic support for EDE (RFC8914).
|
||||
|
||||
28 April 2022: Wouter
|
||||
- Fix #670: SERVFAIL problems with unbound 1.15.0 running on
|
||||
OpenBSD 7.1.
|
||||
|
||||
8 April 2022: Wouter
|
||||
- Fix zonemd check to allow unsupported algorithms to load.
|
||||
If there are only unsupported algorithms, or unsupported schemes,
|
||||
and no failed or successful other ZONEMD records, or malformed
|
||||
or bad ZONEMD records, the unsupported records allow the zone load.
|
||||
- Fix zonemd unsupported algo check.
|
||||
- Fix zonemd unsupported algo check reason to not copy to next record,
|
||||
and check for success for debug printout.
|
||||
- Fix zonemd unsupported algo check to print unsupported reason before
|
||||
zeroing it.
|
||||
- Fix zonemd unsupported algo check to set reason to NULL before the
|
||||
check routine, but after malformed checks, to get the correct NULL
|
||||
output when the digest matches.
|
||||
|
||||
25 March 2022: Wouter
|
||||
- Fix spelling error in comment in sldns_str2wire_svcparam_key_lookup.
|
||||
|
||||
23 March 2022: Wouter
|
||||
- Fix #651: [FR] Better logging for refused queries.
|
||||
|
||||
18 March 2022: George
|
||||
- Merge PR #648 from eaglegai: fix -q doesn't work when use with
|
||||
'unbound-control stats_shm'.
|
||||
|
||||
17 March 2022: Wouter
|
||||
- Fix to describe auth-zone and other configuration at the local-zone
|
||||
configuration option, to allow for more broadly view of the options.
|
||||
|
||||
16 March 2022: Wouter
|
||||
- Fix to ensure uniform handling of spaces and tabs when parsing RRs.
|
||||
|
||||
9 March 2022: Wouter
|
||||
- Merge #644: Make `install-lib` make target install the pkg-config
|
||||
file.
|
||||
|
||||
7 March 2022: Wouter
|
||||
- Fix configure for python to use sysutils, because distutils is
|
||||
deprecated. It uses sysutils when available, distutils otherwise.
|
||||
|
||||
3 March 2022: Wouter
|
||||
- Fix #637: Integer Overflow in sldns_str2period function.
|
||||
- Fix for #637: fix integer overflow checks in sldns_str2period.
|
||||
|
||||
2 March 2022: George
|
||||
- Merge PR #632 from scottrw93: Match cnames in ipset.
|
||||
- Various fixes for #632: variable initialisation, convert the qinfo
|
||||
to str once, accept trailing dot in the local-zone ipset option.
|
||||
|
||||
2 March 2022: Wouter
|
||||
- Fix compile warnings for printf ll format on mingw compile.
|
||||
|
||||
1 March 2022: Wouter
|
||||
- Fix pythonmod for change in iter_dp_is_useless function prototype.
|
||||
|
||||
28 February 2022: George
|
||||
- Fix #630: Unify the RPZ log messages.
|
||||
- Merge #623 from rex4539: Fix typos.
|
||||
|
||||
28 February 2022: Wouter
|
||||
- Fix #633: Document unix domain socket support for unbound-control.
|
||||
- Fix for #633: updated fix with new text.
|
||||
- Fix edns client subnet to add the option based on the option list,
|
||||
so that it is not state dependent, after the state fix of #605 for
|
||||
double EDNS options.
|
||||
- Fix for edns client subnet option add fix in removal code, from review.
|
||||
|
||||
25 February 2022: Wouter
|
||||
- Fix to detect that no IPv6 support means that IPv6 addresses are
|
||||
useless for delegation point lookups.
|
||||
- update Makefile dependencies.
|
||||
- Fix check interface existence for support detection in remote lookup.
|
||||
|
||||
18 February 2022: Wouter
|
||||
- Fix that address not available is squelched from the logs for
|
||||
udp connect failures. It is visible on verbosity 4 and more.
|
||||
- Merge #631 from mollyim: Replace OpenSSL's ERR_PACK with
|
||||
ERR_GET_REASON.
|
||||
|
||||
16 February 2022: Wouter
|
||||
- Fix for #628: fix rpz-passthru for qname trigger by localzone type.
|
||||
|
||||
15 February 2022: Wouter
|
||||
- Fix #628: A rpz-passthru action is not ending RPZ zone processing.
|
||||
|
||||
11 February 2022: Wouter
|
||||
- Fix #624: Unable to stop Unbound in Windows console (does not
|
||||
respond to CTRL+C command).
|
||||
- Fix #618: enabling interface-automatic disables DNS-over-TLS.
|
||||
Adds the option to list interface-automatic-ports.
|
||||
- Remove debug info from #618 fix.
|
||||
|
||||
7 February 2022: Wouter
|
||||
- Fix that TCP interface does not use TLS when TLS is also configured.
|
||||
|
||||
4 February 2022: Wouter
|
||||
- Fix #412: cache invalidation issue with CNAME+A.
|
||||
|
||||
3 February 2022: Wouter
|
||||
- Fix for #611: Integer overflow in sldns_wire2str_pkt_scan.
|
||||
- Tag for 1.15.0rc1 created. That became 1.15.0 on 10 feb 2022.
|
||||
The repository continues with version 1.15.1.
|
||||
|
||||
2 February 2022: George
|
||||
- Merge PR #532 from Shchelk: Fix: buffer overflow bug.
|
||||
- Merge PR #616: Update ratelimit logic. It also introduces
|
||||
ratelimit-backoff and ip-ratelimit-backoff configuration options.
|
||||
- Change aggressive-nsec default to yes.
|
||||
- Merge PR #617: Update stub/forward-host notation to accept port and
|
||||
tls-auth-name.
|
||||
- Update stream_ssl.tdir test to also use the new forward-host
|
||||
notation.
|
||||
|
||||
2 February 2022: Wouter
|
||||
- Update version number in repo to 1.15.0 for upcoming release,
|
||||
since it changes the aggressive-nsec default and the ratelimit change.
|
||||
- Fix header comment for doxygen for authextstrtoaddr.
|
||||
- please clang analyzer for loop in test code.
|
||||
- Fix docker splint test to use more portable uname.
|
||||
- Update contrib/aaaa-filter-iterator.patch with diff for current
|
||||
software version.
|
||||
|
||||
1 February 2022: George
|
||||
- Merge PR #603 from fobser: Use OpenSSL 1.1 API to access DSA and RSA
|
||||
internals.
|
||||
|
||||
31 January 2022: George
|
||||
- Fix review comment for use-after-free when failing to send UDP out.
|
||||
|
||||
31 January 2022: Wouter
|
||||
- iana portlist update.
|
||||
|
||||
29 January 2022: George
|
||||
- Fix tls-* and ssl-* documented alternate syntax to also be available
|
||||
through remote-control and unbound-checkconf.
|
||||
- Better cleanup on failed DoT/DoH listening socket creation.
|
||||
|
||||
26 January 2022: George
|
||||
- Fix #599: [FR] RFC 9156 (obsoletes RFC 7816), by noting the new RFC
|
||||
document.
|
||||
|
||||
26 January 2022: Wouter
|
||||
- Test for NSID in SERVFAIL response due to DNSSEC bogus.
|
||||
|
||||
25 January 2022: George
|
||||
- Fix #588: Unbound 1.13.2 crashes due to p->pc is NULL in
|
||||
serviced_udp_callback.
|
||||
- Merge PR #612: TCP race condition.
|
||||
|
||||
25 January 2022: Wouter
|
||||
- Fix #610: Undefine-shift in sldns_str2wire_hip_buf.
|
||||
|
||||
19 January 2022: George
|
||||
- For dnstap, do not wakeupnow right there. Instead zero the timer to
|
||||
force the wakeup callback asap.
|
||||
|
||||
14 January 2022: George
|
||||
- Merge PR #605:
|
||||
- Fix EDNS to upstream where the same option could be attached
|
||||
more than once.
|
||||
- Add a region to serviced_query for allocations.
|
||||
|
||||
14 January 2022: Wouter
|
||||
- Add rpz: for-downstream: yesno option, where the RPZ zone is
|
||||
authoritatively answered for, so the RPZ zone contents can be
|
||||
checked with DNS queries directed at the RPZ zone.
|
||||
- For #602: Allow the module-config "subnetcache validator cachedb
|
||||
iterator".
|
||||
|
||||
11 January 2022: George
|
||||
- Fix prematurely terminated TCP queries when a reply has the same ID.
|
||||
|
||||
7 January 2022: Wouter
|
||||
- Merge #600 from pemensik: Change file mode before changing file
|
||||
owner.
|
||||
|
||||
5 January 2022: Wouter
|
||||
- Fix for #596: fix that rpz return message is returned and not just
|
||||
the rcode from the iterator return path. This fixes signal unset RA
|
||||
after a CNAME.
|
||||
- Fix unit tests for rpz now that the AA flag returns successfully from
|
||||
the iterator loop.
|
||||
- Fix for #596: add unit test for nsdname trigger and signal unset RA.
|
||||
- Fix for #596: add unit test for nsip trigger and signal unset RA.
|
||||
- Fix #598: Fix unbound-checkconf fatal error: module conf
|
||||
'respip dns64 validator iterator' is not known to work.
|
||||
- Fix for #596: Fix rpz-signal-nxdomain-ra to work for clientip
|
||||
triggered operation.
|
||||
|
||||
4 January 2022: Wouter
|
||||
- Fix #596: unset the RA bit when a query is blocked by an unbound
|
||||
RPZ nxdomain reply. The option rpz-signal-nxdomain-ra allows to
|
||||
signal that a domain is externally blocked to clients when it
|
||||
is blocked with NXDOMAIN by unsetting RA.
|
||||
- Fix to add test for rpz-signal-nxdomain-ra.
|
||||
- Fix #596: only unset RA when NXDOMAIN is signalled.
|
||||
- Fix that RPZ does not set RD flag on replies, it should be copied
|
||||
from the query.
|
||||
|
||||
22 December 2021: George
|
||||
- contrib/aaaa-filter-iterator.patch file renewed diff content to
|
||||
apply cleanly to the current coderepo for the current code version.
|
||||
|
||||
20 December 2021: George
|
||||
- Fix #591: Unbound-anchor manpage links to non-existent license file.
|
||||
|
||||
13 December 2021: George
|
||||
- Add missing configure flags for optional features in the
|
||||
documentation.
|
||||
- Fix Unbound capitalization in the documentation.
|
||||
|
||||
13 December 2021: Wouter
|
||||
- Fix to pick up other class local zone information before unlock.
|
||||
|
||||
10 December 2021: George
|
||||
- Allow local-data for classes other than IN to inherit a configured
|
||||
local-zone's type if possible, instead of defaulting to type
|
||||
transparent as per the implicit rule.
|
||||
|
||||
10 December 2021: Wouter
|
||||
- Add code similar to fix for ldns for tab between strings, for
|
||||
consistency, the test case was not broken.
|
||||
|
||||
6 December 2021: Wouter
|
||||
- Merge PR #581 from fobser: Fix -Wmissing-prototypes and -Wshadow
|
||||
warnings in rpz.
|
||||
- Fix validator debug output about DS support, print correct algorithm.
|
||||
|
||||
3 December 2021: Wouter
|
||||
- Fix compile warning for if_nametoindex on windows 64bit.
|
||||
|
||||
1 December 2021: Wouter
|
||||
- configure is set to 1.14.0, and release branch.
|
||||
This was released as version 1.14.0 on 9 Dec 2021, with the doxygen
|
||||
fix below included. The main branch continues as 1.14.1.
|
||||
- Fix doc/unbound.doxygen to remove obsolete tag warning.
|
||||
|
||||
1 December 2021: George
|
||||
|
||||
+121
-30
@@ -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.
|
||||
@@ -50,11 +50,16 @@ 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.
|
||||
# interface-automatic: no
|
||||
|
||||
# instead of the default port, open additional ports separated by
|
||||
# spaces when interface-automatic is enabled, by listing them here.
|
||||
# interface-automatic-ports: ""
|
||||
|
||||
# port to answer queries from
|
||||
# port: 53
|
||||
|
||||
@@ -82,13 +87,13 @@ server:
|
||||
# num-queries-per-thread, or, use as many as the OS will allow you.
|
||||
# outgoing-range: 4096
|
||||
|
||||
# permit unbound to use this port number or port range for
|
||||
# permit Unbound to use this port number or port range for
|
||||
# making outgoing queries, using an outgoing interface.
|
||||
# outgoing-port-permit: 32768
|
||||
|
||||
# deny unbound the use this of port number or port range for
|
||||
# deny Unbound the use this of port number or port range for
|
||||
# making outgoing queries, using an outgoing interface.
|
||||
# Use this to make sure unbound does not grab a UDP port that some
|
||||
# Use this to make sure Unbound does not grab a UDP port that some
|
||||
# other server on this computer needs. The default is to avoid
|
||||
# IANA-assigned port numbers.
|
||||
# If multiple outgoing-port-permit and outgoing-port-avoid options
|
||||
@@ -164,7 +169,8 @@ server:
|
||||
# perform connect for UDP sockets to mitigate ICMP side channel.
|
||||
# udp-connect: yes
|
||||
|
||||
# The number of retries when a non-positive response is received.
|
||||
# The number of retries, per upstream nameserver in a delegation, when
|
||||
# a throwaway response (also timeouts) is received.
|
||||
# outbound-msg-retry: 5
|
||||
|
||||
# msec for waiting for an unknown server to reply. Increase if you
|
||||
@@ -198,6 +204,9 @@ server:
|
||||
# minimum wait time for responses, increase if uplink is long. In msec.
|
||||
# infra-cache-min-rtt: 50
|
||||
|
||||
# maximum wait time for responses. In msec.
|
||||
# infra-cache-max-rtt: 120000
|
||||
|
||||
# enable to make server probe down hosts more frequently.
|
||||
# infra-keep-probing: no
|
||||
|
||||
@@ -209,7 +218,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"
|
||||
|
||||
@@ -254,7 +264,7 @@ server:
|
||||
# use-systemd: no
|
||||
|
||||
# Detach from the terminal, run in background, "yes" or "no".
|
||||
# Set the value to "no" when unbound runs as systemd service.
|
||||
# Set the value to "no" when Unbound runs as systemd service.
|
||||
# do-daemonize: yes
|
||||
|
||||
# control which clients are allowed to make (recursive) queries
|
||||
@@ -265,9 +275,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
|
||||
|
||||
@@ -276,7 +284,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.
|
||||
@@ -288,6 +296,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.
|
||||
@@ -307,7 +367,7 @@ server:
|
||||
# The pid file can be absolute and outside of the chroot, it is
|
||||
# written just prior to performing the chroot and dropping permissions.
|
||||
#
|
||||
# Additionally, unbound may need to access /dev/urandom (for entropy).
|
||||
# Additionally, Unbound may need to access /dev/urandom (for entropy).
|
||||
# How to do this is specific to your OS.
|
||||
#
|
||||
# If you give "" no chroot is performed. The path must not end in a /.
|
||||
@@ -442,7 +502,7 @@ server:
|
||||
|
||||
# Aggressive NSEC uses the DNSSEC NSEC chain to synthesize NXDOMAIN
|
||||
# and other denials, using information from previous NXDOMAINs answers.
|
||||
# aggressive-nsec: no
|
||||
# aggressive-nsec: yes
|
||||
|
||||
# Use 0x20-encoded random bits in the query to foil spoof attempts.
|
||||
# This feature is an experimental implementation of draft dns-0x20.
|
||||
@@ -517,7 +577,7 @@ server:
|
||||
# Use several entries, one per domain name, to track multiple zones.
|
||||
#
|
||||
# If you want to perform DNSSEC validation, run unbound-anchor before
|
||||
# you start unbound (i.e. in the system boot scripts).
|
||||
# you start Unbound (i.e. in the system boot scripts).
|
||||
# And then enable the auto-trust-anchor-file config item.
|
||||
# Please note usage of unbound-anchor root anchor is at your own risk
|
||||
# and under the terms of our LICENSE (see that file in the source).
|
||||
@@ -585,7 +645,7 @@ server:
|
||||
# val-permissive-mode: no
|
||||
|
||||
# Ignore the CD flag in incoming queries and refuse them bogus data.
|
||||
# Enable it if the only clients of unbound are legacy servers (w2008)
|
||||
# Enable it if the only clients of Unbound are legacy servers (w2008)
|
||||
# that set CD but cannot validate themselves.
|
||||
# ignore-cd-flag: no
|
||||
|
||||
@@ -615,7 +675,7 @@ server:
|
||||
|
||||
# Return the original TTL as received from the upstream name server rather
|
||||
# than the decrementing TTL as stored in the cache. Enabling this feature
|
||||
# does not impact cache expiry, it only changes the TTL unbound embeds in
|
||||
# does not impact cache expiry, it only changes the TTL Unbound embeds in
|
||||
# responses to queries. Note that enabling this feature implicitly disables
|
||||
# enforcement of the configured minimum and maximum TTL.
|
||||
# serve-original-ttl: no
|
||||
@@ -709,9 +769,9 @@ server:
|
||||
# Add example.com into ipset
|
||||
# local-zone: "example.com" ipset
|
||||
|
||||
# If unbound is running service for the local host then it is useful
|
||||
# If Unbound is running service for the local host then it is useful
|
||||
# to perform lan-wide lookups to the upstream, and unblock the
|
||||
# long list of local-zones above. If this unbound is a dns server
|
||||
# long list of local-zones above. If this Unbound is a dns server
|
||||
# for a network of computers, disabled is better and stops information
|
||||
# leakage of local lan information.
|
||||
# unblock-lan-zones: no
|
||||
@@ -811,6 +871,8 @@ server:
|
||||
|
||||
# Add system certs to the cert bundle, from the Windows Cert Store
|
||||
# tls-win-cert: no
|
||||
# and on other systems, the default openssl certificates
|
||||
# tls-system-cert: no
|
||||
|
||||
# Pad queries over TLS upstreams
|
||||
# pad-queries: yes
|
||||
@@ -840,6 +902,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
|
||||
@@ -860,6 +926,10 @@ server:
|
||||
# 0 blocks when ratelimited, otherwise let 1/xth traffic through
|
||||
# ratelimit-factor: 10
|
||||
|
||||
# Aggressive rate limit when the limit is reached and until demand has
|
||||
# decreased in a 2 second rate window.
|
||||
# ratelimit-backoff: no
|
||||
|
||||
# override the ratelimit for a specific domain name.
|
||||
# give this setting multiple times to have multiple overrides.
|
||||
# ratelimit-for-domain: example.com 1000
|
||||
@@ -880,6 +950,10 @@ server:
|
||||
# 0 blocks when ip is ratelimited, otherwise let 1/xth traffic through
|
||||
# ip-ratelimit-factor: 10
|
||||
|
||||
# Aggressive rate limit when the limit is reached and until demand has
|
||||
# decreased in a 2 second rate window.
|
||||
# ip-ratelimit-backoff: no
|
||||
|
||||
# Limit the number of connections simultaneous from a netblock
|
||||
# tcp-connection-limit: 192.0.2.0/24 12
|
||||
|
||||
@@ -889,7 +963,15 @@ server:
|
||||
# the number of servers that will be used in the fast server selection.
|
||||
# fast-server-num: 3
|
||||
|
||||
# Specific options for ipsecmod. unbound needs to be configured with
|
||||
# Enable to attach Extended DNS Error codes (RFC8914) to responses.
|
||||
# ede: no
|
||||
|
||||
# Enable to attach an Extended DNS Error (RFC8914) Code 3 - Stale
|
||||
# Answer as EDNS0 option to expired responses.
|
||||
# Note that the ede option above needs to be enabled for this to work.
|
||||
# ede-serve-expired: no
|
||||
|
||||
# Specific options for ipsecmod. Unbound needs to be configured with
|
||||
# --enable-ipsecmod for these to take effect.
|
||||
#
|
||||
# Enable or disable ipsecmod (it still needs to be defined in
|
||||
@@ -901,7 +983,7 @@ server:
|
||||
# listed in module-config (above).
|
||||
# ipsecmod-hook: "./my_executable"
|
||||
#
|
||||
# When enabled unbound will reply with SERVFAIL if the return value of
|
||||
# When enabled Unbound will reply with SERVFAIL if the return value of
|
||||
# the ipsecmod-hook is not 0.
|
||||
# ipsecmod-strict: no
|
||||
#
|
||||
@@ -966,10 +1048,10 @@ remote-control:
|
||||
# For local sockets this option is ignored, and TLS is not used.
|
||||
# control-use-cert: "yes"
|
||||
|
||||
# unbound server key file.
|
||||
# Unbound server key file.
|
||||
# server-key-file: "@UNBOUND_RUN_DIR@/unbound_server.key"
|
||||
|
||||
# unbound server certificate file.
|
||||
# Unbound server certificate file.
|
||||
# server-cert-file: "@UNBOUND_RUN_DIR@/unbound_server.pem"
|
||||
|
||||
# unbound-control key file.
|
||||
@@ -1023,8 +1105,8 @@ remote-control:
|
||||
# has a copy of the root for local usage. The second serves example.org
|
||||
# authoritatively. zonefile: reads from file (and writes to it if you also
|
||||
# download it), primary: fetches with AXFR and IXFR, or url to zonefile.
|
||||
# With allow-notify: you can give additional (apart from primaries) sources of
|
||||
# notifies.
|
||||
# With allow-notify: you can give additional (apart from primaries and urls)
|
||||
# sources of notifies.
|
||||
# auth-zone:
|
||||
# name: "."
|
||||
# primary: 199.9.14.201 # b.root-servers.net
|
||||
@@ -1072,8 +1154,9 @@ remote-control:
|
||||
# local-zone: "example.com" refuse
|
||||
|
||||
# DNSCrypt
|
||||
# To enable, use --enable-dnscrypt to configure before compiling.
|
||||
# Caveats:
|
||||
# 1. the keys/certs cannot be produced by unbound. You can use dnscrypt-wrapper
|
||||
# 1. the keys/certs cannot be produced by Unbound. You can use dnscrypt-wrapper
|
||||
# for this: https://github.com/cofyc/dnscrypt-wrapper/blob/master/README.md#usage
|
||||
# 2. dnscrypt channel attaches to an interface. you MUST set interfaces to
|
||||
# listen on `dnscrypt-port` with the follo0wing snippet:
|
||||
@@ -1092,7 +1175,9 @@ remote-control:
|
||||
# dnscrypt-provider-cert: /path/unbound-conf/keys2/1.cert
|
||||
|
||||
# CacheDB
|
||||
# Enable external backend DB as auxiliary cache. Specify the backend name
|
||||
# External backend DB as auxiliary cache.
|
||||
# To enable, use --enable-cachedb to configure before compiling.
|
||||
# Specify the backend name
|
||||
# (default is "testframe", which has no use other than for debugging and
|
||||
# testing) and backend-specific options. The 'cachedb' module must be
|
||||
# included in module-config, just before the iterator module.
|
||||
@@ -1102,6 +1187,7 @@ remote-control:
|
||||
# secret-seed: "default"
|
||||
#
|
||||
# # For "redis" backend:
|
||||
# # (to enable, use --with-libhiredis to configure before compiling)
|
||||
# # redis server's IP address or host name
|
||||
# redis-server-host: 127.0.0.1
|
||||
# # redis server's TCP port
|
||||
@@ -1113,7 +1199,9 @@ remote-control:
|
||||
|
||||
# IPSet
|
||||
# Add specify domain into set via ipset.
|
||||
# Note: To enable ipset unbound needs to run as root user.
|
||||
# To enable:
|
||||
# o use --enable-ipset to configure before compiling;
|
||||
# o Unbound then needs to run as root user.
|
||||
# ipset:
|
||||
# # set name for ip v4 addresses
|
||||
# name-v4: "list-v4"
|
||||
@@ -1121,9 +1209,10 @@ remote-control:
|
||||
# name-v6: "list-v6"
|
||||
#
|
||||
|
||||
# Dnstap logging support, if compiled in. To enable, set the dnstap-enable
|
||||
# to yes and also some of dnstap-log-..-messages to yes. And select an
|
||||
# upstream log destination, by socket path, TCP or TLS destination.
|
||||
# Dnstap logging support, if compiled in by using --enable-dnstap to configure.
|
||||
# To enable, set the dnstap-enable to yes and also some of
|
||||
# dnstap-log-..-messages to yes. And select an upstream log destination, by
|
||||
# socket path, TCP or TLS destination.
|
||||
# dnstap:
|
||||
# dnstap-enable: no
|
||||
# # if set to yes frame streams will be used in bidirectional mode
|
||||
@@ -1136,7 +1225,7 @@ remote-control:
|
||||
# dnstap-tls: yes
|
||||
# # name for authenticating the upstream server. or "" disabled.
|
||||
# dnstap-tls-server-name: ""
|
||||
# # if "", it uses the cert bundle from the main unbound config.
|
||||
# # if "", it uses the cert bundle from the main Unbound config.
|
||||
# dnstap-tls-cert-bundle: ""
|
||||
# # key file for client authentication, or "" disabled.
|
||||
# dnstap-tls-client-key-file: ""
|
||||
@@ -1172,4 +1261,6 @@ remote-control:
|
||||
# rpz-cname-override: www.example.org
|
||||
# rpz-log: yes
|
||||
# rpz-log-name: "example policy"
|
||||
# rpz-signal-nxdomain-ra: no
|
||||
# for-downstream: no
|
||||
# tags: "example"
|
||||
|
||||
@@ -41,7 +41,7 @@ update certificate files.
|
||||
.P
|
||||
It tests if the root anchor file works, and if not, and an update is possible,
|
||||
attempts to update the root anchor using the root update certificate.
|
||||
It performs a https fetch of root-anchors.xml and checks the results (RFC7958),
|
||||
It performs a https fetch of root-anchors.xml and checks the results (RFC7958),
|
||||
if all checks are successful, it updates the root anchor file. Otherwise
|
||||
the root anchor file is unchanged. It performs RFC5011 tracking if the
|
||||
DNSSEC information available via the DNS makes that possible.
|
||||
@@ -159,7 +159,7 @@ Or something more suitable for your operational environment.
|
||||
The root keys and update certificate included in this tool
|
||||
are provided for convenience and under the terms of our
|
||||
license (see the LICENSE file in the source distribution or
|
||||
http://unbound.nlnetlabs.nl/svn/trunk/LICENSE) and might be stale or
|
||||
https://github.com/NLnetLabs/unbound/blob/master/LICENSE) and might be stale or
|
||||
not suitable to your purpose.
|
||||
.P
|
||||
By running "unbound\-anchor \-l" the keys and certificate that are
|
||||
@@ -185,5 +185,5 @@ Source for the root key information.
|
||||
.I https://data.iana.org/root\-anchors/root\-anchors.p7s
|
||||
Signature on the root key information.
|
||||
.SH "SEE ALSO"
|
||||
\fIunbound.conf\fR(5),
|
||||
\fIunbound.conf\fR(5),
|
||||
\fIunbound\fR(8).
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
.\"
|
||||
.SH "NAME"
|
||||
unbound\-checkconf
|
||||
\- Check unbound configuration file for errors.
|
||||
\- Check Unbound configuration file for errors.
|
||||
.SH "SYNOPSIS"
|
||||
.B unbound\-checkconf
|
||||
.RB [ \-h ]
|
||||
@@ -21,8 +21,8 @@ unbound\-checkconf
|
||||
.B Unbound\-checkconf
|
||||
checks the configuration file for the
|
||||
\fIunbound\fR(8)
|
||||
DNS resolver for syntax and other errors.
|
||||
The config file syntax is described in
|
||||
DNS resolver for syntax and other errors.
|
||||
The config file syntax is described in
|
||||
\fIunbound.conf\fR(5).
|
||||
.P
|
||||
The available options are:
|
||||
@@ -34,19 +34,19 @@ Show the version and commandline option help.
|
||||
Print full pathname, with chroot applied to it. Use with the \-o option.
|
||||
.TP
|
||||
.B \-o\fI option
|
||||
If given, after checking the config file the value of this option is
|
||||
If given, after checking the config file the value of this option is
|
||||
printed to stdout. For "" (disabled) options an empty line is printed.
|
||||
.TP
|
||||
.I cfgfile
|
||||
The config file to read with settings for unbound. It is checked.
|
||||
The config file to read with settings for Unbound. It is checked.
|
||||
If omitted, the config file at the default location is checked.
|
||||
.SH "EXIT CODE"
|
||||
The unbound\-checkconf program exits with status code 1 on error,
|
||||
The unbound\-checkconf program exits with status code 1 on error,
|
||||
0 for a correct config file.
|
||||
.SH "FILES"
|
||||
.TP
|
||||
.I @ub_conf_file@
|
||||
unbound configuration file.
|
||||
Unbound configuration file.
|
||||
.SH "SEE ALSO"
|
||||
\fIunbound.conf\fR(5),
|
||||
\fIunbound.conf\fR(5),
|
||||
\fIunbound\fR(8).
|
||||
|
||||
+54
-48
@@ -14,15 +14,15 @@
|
||||
.SH "SYNOPSIS"
|
||||
.B unbound\-control
|
||||
.RB [ \-hq ]
|
||||
.RB [ \-c
|
||||
.RB [ \-c
|
||||
.IR cfgfile ]
|
||||
.RB [ \-s
|
||||
.RB [ \-s
|
||||
.IR server ]
|
||||
.IR command
|
||||
.SH "DESCRIPTION"
|
||||
.B Unbound\-control
|
||||
performs remote administration on the \fIunbound\fR(8) DNS server.
|
||||
It reads the configuration file, contacts the unbound server over SSL
|
||||
It reads the configuration file, contacts the Unbound server over SSL
|
||||
sends the command and displays the result.
|
||||
.P
|
||||
The available options are:
|
||||
@@ -44,8 +44,8 @@ quiet, if the option is given it does not print anything if it works ok.
|
||||
There are several commands that the server understands.
|
||||
.TP
|
||||
.B start
|
||||
Start the server. Simply execs \fIunbound\fR(8). The unbound executable
|
||||
is searched for in the \fBPATH\fR set in the environment. It is started
|
||||
Start the server. Simply execs \fIunbound\fR(8). The Unbound executable
|
||||
is searched for in the \fBPATH\fR set in the environment. It is started
|
||||
with the config file specified using \fI\-c\fR or the default config file.
|
||||
.TP
|
||||
.B stop
|
||||
@@ -65,8 +65,8 @@ daemon release the file it is logging to. If you are using syslog it will
|
||||
attempt to close and open the syslog (which may not work if chrooted).
|
||||
.TP
|
||||
.B stats
|
||||
Print statistics. Resets the internal counters to zero, this can be
|
||||
controlled using the \fBstatistics\-cumulative\fR config statement.
|
||||
Print statistics. Resets the internal counters to zero, this can be
|
||||
controlled using the \fBstatistics\-cumulative\fR config statement.
|
||||
Statistics are printed with one [name]: [value] per line.
|
||||
.TP
|
||||
.B stats_noreset
|
||||
@@ -74,7 +74,7 @@ Peek at statistics. Prints them like the \fBstats\fR command does, but does not
|
||||
reset the internal counters to zero.
|
||||
.TP
|
||||
.B status
|
||||
Display server status. Exit code 3 if not running (the connection to the
|
||||
Display server status. Exit code 3 if not running (the connection to the
|
||||
port is refused), 1 on error, 0 if running.
|
||||
.TP
|
||||
.B local_zone \fIname\fR \fItype
|
||||
@@ -88,14 +88,14 @@ it. If the zone does not exist, the command succeeds.
|
||||
.B local_data \fIRR data...
|
||||
Add new local data, the given resource record. Like \fBlocal\-data\fR
|
||||
config statement, except for when no covering zone exists. In that case
|
||||
this remote control command creates a transparent zone with the same
|
||||
this remote control command creates a transparent zone with the same
|
||||
name as this record.
|
||||
.TP
|
||||
.B local_data_remove \fIname
|
||||
Remove all RR data from local name. If the name already has no items,
|
||||
nothing happens. Often results in NXDOMAIN for the name (in a static zone),
|
||||
but if the name has become an empty nonterminal (there is still data in
|
||||
domain names below the removed name), NOERROR nodata answers are the
|
||||
but if the name has become an empty nonterminal (there is still data in
|
||||
domain names below the removed name), NOERROR nodata answers are the
|
||||
result for that name.
|
||||
.TP
|
||||
.B local_zones
|
||||
@@ -125,22 +125,22 @@ in old or wrong data returned to clients. Loading data into the cache
|
||||
in this way is supported in order to aid with debugging.
|
||||
.TP
|
||||
.B lookup \fIname
|
||||
Print to stdout the name servers that would be used to look up the
|
||||
Print to stdout the name servers that would be used to look up the
|
||||
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.
|
||||
Because that is fast to do. Other record types can be removed using
|
||||
.B flush_type
|
||||
or
|
||||
Because that is fast to do. Other record types can be removed using
|
||||
.B flush_type
|
||||
or
|
||||
.B flush_zone\fR.
|
||||
.TP
|
||||
.B flush_type \fIname\fR \fItype
|
||||
Remove the name, type information from the cache.
|
||||
.TP
|
||||
.B flush_zone \fIname
|
||||
Remove all information at or below the name from the cache.
|
||||
Remove all information at or below the name from the cache.
|
||||
The rrsets and key entries are removed so that new lookups will be performed.
|
||||
This needs to walk and inspect the entire cache, and is a slow operation.
|
||||
The entries are set to expired in the implementation of this command (so,
|
||||
@@ -187,7 +187,7 @@ therefore not flushed. The option must end with a ':' and whitespace
|
||||
must be between the option and the value. Some values may not have an
|
||||
effect if set this way, the new values are not written to the config file,
|
||||
not all options are supported. This is different from the set_option call
|
||||
in libunbound, where all values work because unbound has not been initialized.
|
||||
in libunbound, where all values work because Unbound has not been initialized.
|
||||
.IP
|
||||
The values that work are: statistics\-interval, statistics\-cumulative,
|
||||
do\-not\-query\-localhost, harden\-short\-bufsize, harden\-large\-queries,
|
||||
@@ -227,36 +227,36 @@ List the local data RRs in use. The resource records are printed.
|
||||
.TP
|
||||
.B insecure_add \fIzone
|
||||
Add a \fBdomain\-insecure\fR for the given zone, like the statement in unbound.conf.
|
||||
Adds to the running unbound without affecting the cache contents (which may
|
||||
Adds to the running Unbound without affecting the cache contents (which may
|
||||
still be bogus, use \fBflush_zone\fR to remove it), does not affect the config file.
|
||||
.TP
|
||||
.B insecure_remove \fIzone
|
||||
Removes domain\-insecure for the given zone.
|
||||
.TP
|
||||
.B forward_add \fR[\fI+i\fR] \fIzone addr ...
|
||||
Add a new forward zone to running unbound. With +i option also adds a
|
||||
Add a new forward zone to running Unbound. With +i option also adds a
|
||||
\fIdomain\-insecure\fR for the zone (so it can resolve insecurely if you have
|
||||
a DNSSEC root trust anchor configured for other names).
|
||||
The addr can be IP4, IP6 or nameserver names, like \fIforward-zone\fR config
|
||||
in unbound.conf.
|
||||
.TP
|
||||
.B forward_remove \fR[\fI+i\fR] \fIzone
|
||||
Remove a forward zone from running unbound. The +i also removes a
|
||||
Remove a forward zone from running Unbound. The +i also removes a
|
||||
\fIdomain\-insecure\fR for the zone.
|
||||
.TP
|
||||
.B stub_add \fR[\fI+ip\fR] \fIzone addr ...
|
||||
Add a new stub zone to running unbound. With +i option also adds a
|
||||
Add a new stub zone to running Unbound. With +i option also adds a
|
||||
\fIdomain\-insecure\fR for the zone. With +p the stub zone is set to prime,
|
||||
without it it is set to notprime. The addr can be IP4, IP6 or nameserver
|
||||
names, like the \fIstub-zone\fR config in unbound.conf.
|
||||
.TP
|
||||
.B stub_remove \fR[\fI+i\fR] \fIzone
|
||||
Remove a stub zone from running unbound. The +i also removes a
|
||||
Remove a stub zone from running Unbound. The +i also removes a
|
||||
\fIdomain\-insecure\fR for the zone.
|
||||
.TP
|
||||
.B forward \fR[\fIoff\fR | \fIaddr ...\fR ]
|
||||
Setup forwarding mode. Configures if the server should ask other upstream
|
||||
nameservers, should go to the internet root nameservers itself, or show
|
||||
nameservers, should go to the internet root nameservers itself, or show
|
||||
the current config. You could pass the nameservers after a DHCP update.
|
||||
.IP
|
||||
Without arguments the current list of addresses used to forward all queries
|
||||
@@ -289,20 +289,22 @@ just the ratelimited ips, with their estimated qps. The ratelimited
|
||||
ips are dropped before checking the cache.
|
||||
.TP
|
||||
.B list_auth_zones
|
||||
List the auth zones that are configured. Printed one per line with a
|
||||
status, indicating if the zone is expired and current serial number.
|
||||
List the auth zones that are configured. Printed one per line with a status,
|
||||
indicating if the zone is expired and current serial number. Configured RPZ
|
||||
zones are included.
|
||||
.TP
|
||||
.B auth_zone_reload \fIzone\fR
|
||||
Reload the auth zone from zonefile. The zonefile is read in overwriting
|
||||
the current contents of the zone in memory. This changes the auth zone
|
||||
contents itself, not the cache contents. Such cache contents exists if
|
||||
you set unbound to validate with for-upstream yes and that can be cleared
|
||||
with \fBflush_zone\fR \fIzone\fR.
|
||||
Reload the auth zone (or RPZ zone) from zonefile. The zonefile is read in
|
||||
overwriting the current contents of the zone in memory. This changes the auth
|
||||
zone contents itself, not the cache contents. Such cache contents exists if
|
||||
you set Unbound to validate with for-upstream yes and that can be cleared with
|
||||
\fBflush_zone\fR \fIzone\fR.
|
||||
.TP
|
||||
.B auth_zone_transfer \fIzone\fR
|
||||
Transfer the auth zone from master. The auth zone probe sequence is started,
|
||||
where the masters are probed to see if they have an updated zone (with the SOA
|
||||
serial check). And then the zone is transferred for a newer zone version.
|
||||
Transfer the auth zone (or RPZ zone) from master. The auth zone probe sequence
|
||||
is started, where the masters are probed to see if they have an updated zone
|
||||
(with the SOA serial check). And then the zone is transferred for a newer zone
|
||||
version.
|
||||
.TP
|
||||
.B rpz_enable \fIzone\fR
|
||||
Enable the RPZ zone if it had previously been disabled.
|
||||
@@ -336,7 +338,7 @@ Add a list of \fIlocal_data\fR for given view from stdin. Like local_datas.
|
||||
.SH "EXIT CODE"
|
||||
The unbound\-control program exits with status code 1 on error, 0 on success.
|
||||
.SH "SET UP"
|
||||
The setup requires a self\-signed certificate and private keys for both
|
||||
The setup requires a self\-signed certificate and private keys for both
|
||||
the server and client. The script \fIunbound\-control\-setup\fR generates
|
||||
these in the default run directory, or with \-d in another directory.
|
||||
If you change the access control permissions on the key files you can decide
|
||||
@@ -350,7 +352,7 @@ If you have not configured
|
||||
a username in unbound.conf, the keys need read permission for the user
|
||||
credentials under which the daemon is started.
|
||||
The script preserves private keys present in the directory.
|
||||
After running the script as root, turn on \fBcontrol\-enable\fR in
|
||||
After running the script as root, turn on \fBcontrol\-enable\fR in
|
||||
\fIunbound.conf\fR.
|
||||
.SH "STATISTIC COUNTERS"
|
||||
The \fIstats\fR command shows a number of statistic counters.
|
||||
@@ -417,8 +419,8 @@ Average time it took to answer queries that needed recursive processing. Note th
|
||||
.TP
|
||||
.I threadX.recursion.time.median
|
||||
The median of the time it took to answer queries that needed recursive
|
||||
processing. The median means that 50% of the user queries were answered in
|
||||
less than this time. Because of big outliers (usually queries to non
|
||||
processing. The median means that 50% of the user queries were answered in
|
||||
less than this time. Because of big outliers (usually queries to non
|
||||
responsive servers), the average can be bigger than the median. This median
|
||||
has been calculated by interpolation from a histogram.
|
||||
.TP
|
||||
@@ -544,32 +546,36 @@ The total number of queries over all threads with query opcode QUERY.
|
||||
Also printed for other opcodes, UPDATE, ...
|
||||
.TP
|
||||
.I num.query.tcp
|
||||
Number of queries that were made using TCP towards the unbound server.
|
||||
Number of queries that were made using TCP towards the Unbound server.
|
||||
.TP
|
||||
.I num.query.tcpout
|
||||
Number of queries that the unbound server made using TCP outgoing towards
|
||||
Number of queries that the Unbound server made using TCP outgoing towards
|
||||
other servers.
|
||||
.TP
|
||||
.I num.query.udpout
|
||||
Number of queries that the Unbound server made using UDP outgoing towards
|
||||
other servers.
|
||||
.TP
|
||||
.I num.query.tls
|
||||
Number of queries that were made using TLS towards the unbound server.
|
||||
Number of queries that were made using TLS towards the Unbound server.
|
||||
These are also counted in num.query.tcp, because TLS uses TCP.
|
||||
.TP
|
||||
.I num.query.tls.resume
|
||||
Number of TLS session resumptions, these are queries over TLS towards
|
||||
the unbound server where the client negotiated a TLS session resumption key.
|
||||
the Unbound server where the client negotiated a TLS session resumption key.
|
||||
.TP
|
||||
.I num.query.https
|
||||
Number of queries that were made using HTTPS towards the unbound server.
|
||||
Number of queries that were made using HTTPS towards the Unbound server.
|
||||
These are also counted in num.query.tcp and num.query.tls, because HTTPS
|
||||
uses TLS and TCP.
|
||||
.TP
|
||||
.I num.query.ipv6
|
||||
Number of queries that were made using IPv6 towards the unbound server.
|
||||
Number of queries that were made using IPv6 towards the Unbound server.
|
||||
.TP
|
||||
.I num.query.flags.RD
|
||||
The number of queries that had the RD flag set in the header.
|
||||
Also printed for flags QR, AA, TC, RA, Z, AD, CD.
|
||||
Note that queries with flags QR, AA or TC may have been rejected
|
||||
Note that queries with flags QR, AA or TC may have been rejected
|
||||
because of that.
|
||||
.TP
|
||||
.I num.query.edns.present
|
||||
@@ -603,7 +609,7 @@ These queries are also included in the num.answer.rcode.NOERROR number.
|
||||
Common for AAAA lookups when an A record exists, and no AAAA.
|
||||
.TP
|
||||
.I num.answer.secure
|
||||
Number of answers that were secure. The answer validated correctly.
|
||||
Number of answers that were secure. The answer validated correctly.
|
||||
The AD bit might have been set in some of these answers, where the client
|
||||
signalled (with DO or AD bit in the query) that they were ready to accept
|
||||
the AD bit in the answer.
|
||||
@@ -644,7 +650,7 @@ per delegation point, and their validation status.
|
||||
.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
|
||||
are CPU intensive and this cache allows unbound to avoid recomputing the
|
||||
are CPU intensive and this cache allows Unbound to avoid recomputing the
|
||||
shared secret when multiple dnscrypt queries are sent from the same client.
|
||||
.TP
|
||||
.I dnscrypt_nonce.cache.count
|
||||
@@ -689,11 +695,11 @@ disabled, and cname\-override.
|
||||
.SH "FILES"
|
||||
.TP
|
||||
.I @ub_conf_file@
|
||||
unbound configuration file.
|
||||
Unbound configuration file.
|
||||
.TP
|
||||
.I @UNBOUND_RUN_DIR@
|
||||
directory with private keys (unbound_server.key and unbound_control.key) and
|
||||
self\-signed certificates (unbound_server.pem and unbound_control.pem).
|
||||
.SH "SEE ALSO"
|
||||
\fIunbound.conf\fR(5),
|
||||
\fIunbound.conf\fR(5),
|
||||
\fIunbound\fR(8).
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
.RB [ \-C
|
||||
.IR configfile ]
|
||||
.RB [ \-vdhr46D ]
|
||||
.RB [ \-c
|
||||
.RB [ \-c
|
||||
.IR class ]
|
||||
.RB [ \-t
|
||||
.IR type ]
|
||||
@@ -28,12 +28,12 @@
|
||||
.I hostname
|
||||
.SH "DESCRIPTION"
|
||||
.B Unbound\-host
|
||||
uses the unbound validating resolver to query for the hostname and display
|
||||
results. With the \fB\-v\fR option it displays validation
|
||||
uses the Unbound validating resolver to query for the hostname and display
|
||||
results. With the \fB\-v\fR option it displays validation
|
||||
status: secure, insecure, bogus (security failure).
|
||||
.P
|
||||
By default it reads no configuration file whatsoever. It attempts to reach
|
||||
the internet root servers. With \fB\-C\fR an unbound config file and with
|
||||
the internet root servers. With \fB\-C\fR an Unbound config file and with
|
||||
\fB\-r\fR resolv.conf can be read.
|
||||
.P
|
||||
The available options are:
|
||||
@@ -73,7 +73,7 @@ For example \-y "example.com DS 31560 5 1 1CFED84787E6E19CCF9372C1187325972FE546
|
||||
.TP
|
||||
.B \-D
|
||||
Enables DNSSEC validation. Reads the root anchor from the default configured
|
||||
root anchor at the default location, \fI@UNBOUND_ROOTKEY_FILE@\fR.
|
||||
root anchor at the default location, \fI@UNBOUND_ROOTKEY_FILE@\fR.
|
||||
.TP
|
||||
.B \-f \fIkeyfile
|
||||
Reads keys from a file. Every line has a DS or DNSKEY record, in the format
|
||||
@@ -110,9 +110,9 @@ $ unbound\-host \-v \-y "example.com DS 31560 5 1 1CFED84787E6E19CCF9372C1187325
|
||||
.P
|
||||
$ unbound\-host \-v \-y "example.com DS 31560 5 1 1CFED84787E6E19CCF9372C1187325972FE546CD" 192.0.2.153
|
||||
.SH "EXIT CODE"
|
||||
The unbound\-host program exits with status code 1 on error,
|
||||
The unbound\-host program exits with status code 1 on error,
|
||||
0 on no error. The data may not be available on exit code 0, exit code 1
|
||||
means the lookup encountered a fatal error.
|
||||
.SH "SEE ALSO"
|
||||
\fIunbound.conf\fR(5),
|
||||
\fIunbound.conf\fR(5),
|
||||
\fIunbound\fR(8).
|
||||
|
||||
+3
-3
@@ -57,7 +57,7 @@ The available options are:
|
||||
Show the version number and commandline option help, and exit.
|
||||
.TP
|
||||
.B \-c\fI cfgfile
|
||||
Set the config file with settings for unbound to read instead of reading the
|
||||
Set the config file with settings for Unbound to read instead of reading the
|
||||
file at the default location, @ub_conf_file@. The syntax is
|
||||
described in \fIunbound.conf\fR(5).
|
||||
.TP
|
||||
@@ -70,12 +70,12 @@ or to syslog, but the log messages are printed to stderr all the time.
|
||||
.TP
|
||||
.B \-p
|
||||
Don't use a pidfile. This argument should only be used by supervision
|
||||
systems which can ensure that only one instance of unbound will run
|
||||
systems which can ensure that only one instance of Unbound will run
|
||||
concurrently.
|
||||
.TP
|
||||
.B \-v
|
||||
Increase verbosity. If given multiple times, more information is logged.
|
||||
This is in addition to the verbosity (if any) from the config file.
|
||||
This is added to the verbosity (if any) from the config file.
|
||||
.TP
|
||||
.B \-V
|
||||
Show the version number and build options, and exit.
|
||||
|
||||
+262
-118
@@ -104,7 +104,7 @@ requestlist statistics are printed for every interval (but can be 0).
|
||||
This is because the median calculation requires data to be present.
|
||||
.TP
|
||||
.B statistics\-cumulative: \fI<yes or no>
|
||||
If enabled, statistics are cumulative since starting unbound, without clearing
|
||||
If enabled, statistics are cumulative since starting Unbound, without clearing
|
||||
the statistics counters after logging the statistics. Default is no.
|
||||
.TP
|
||||
.B extended\-statistics: \fI<yes or no>
|
||||
@@ -118,7 +118,7 @@ The number of threads to create to serve clients. Use 1 for no threading.
|
||||
.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,17 +129,26 @@ 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>
|
||||
Listen on all addresses on all (current and future) interfaces, detect the
|
||||
source interface on UDP queries and copy them to replies. This is a lot like
|
||||
ip\-transparent, but this option services all interfaces whilst with
|
||||
ip\-transparent you can select which (future) interfaces unbound provides
|
||||
ip\-transparent you can select which (future) interfaces Unbound provides
|
||||
service on. This feature is experimental, and needs support in your OS for
|
||||
particular socket options. Default value is no.
|
||||
.TP
|
||||
.B interface\-automatic\-ports: \fI<string>
|
||||
List the port numbers that interface-automatic listens on. If empty, the
|
||||
default port is listened on. The port numbers are separated by spaces in the
|
||||
string. Default is "".
|
||||
.IP
|
||||
This can be used to have interface automatic to deal with the interface,
|
||||
and listen on the normal port number, by including it in the list, and
|
||||
also https or dns over tls port numbers by putting them in the list as well.
|
||||
.TP
|
||||
.B outgoing\-interface: \fI<ip address or ip6 netblock>
|
||||
Interface to use to connect to the network. This interface is used to send
|
||||
queries to authoritative servers and receive their replies. Can be given
|
||||
@@ -154,7 +163,7 @@ sent via a random outgoing interface to counter spoofing.
|
||||
If an IPv6 netblock is specified instead of an individual IPv6 address,
|
||||
outgoing UDP queries will use a randomised source address taken from the
|
||||
netblock to counter spoofing. Requires the IPv6 netblock to be routed to the
|
||||
host running unbound, and requires OS support for unprivileged non-local binds
|
||||
host running Unbound, and requires OS support for unprivileged non-local binds
|
||||
(currently only supported on Linux). Several netblocks may be specified with
|
||||
multiple
|
||||
.B outgoing\-interface:
|
||||
@@ -174,7 +183,7 @@ numbers need extra resources from the operating system. For performance a
|
||||
very large value is best, use libevent to make this possible.
|
||||
.TP
|
||||
.B outgoing\-port\-permit: \fI<port number or range>
|
||||
Permit unbound to open this port or range of ports for use to send queries.
|
||||
Permit Unbound to open this port or range of ports for use to send queries.
|
||||
A larger number of permitted outgoing ports increases resilience against
|
||||
spoofing attempts. Make sure these ports are not needed by other daemons.
|
||||
By default only ports above 1024 that have not been assigned by IANA are used.
|
||||
@@ -187,8 +196,8 @@ processing starts with the non IANA allocated ports above 1024 in the set
|
||||
of allowed ports.
|
||||
.TP
|
||||
.B outgoing\-port\-avoid: \fI<port number or range>
|
||||
Do not permit unbound to open this port or range of ports for use to send
|
||||
queries. Use this to make sure unbound does not grab a port that another
|
||||
Do not permit Unbound to open this port or range of ports for use to send
|
||||
queries. Use this to make sure Unbound does not grab a port that another
|
||||
daemon needs. The port is avoided on all outgoing interfaces, both IP4 and IP6.
|
||||
By default only ports above 1024 that have not been assigned by IANA are used.
|
||||
Give a port number or a range of the form "low\-high", without spaces.
|
||||
@@ -289,7 +298,7 @@ If not 0, then set the SO_RCVBUF socket option to get more buffer
|
||||
space on UDP port 53 incoming queries. So that short spikes on busy
|
||||
servers do not drop packets (see counter in netstat \-su). Default is
|
||||
0 (use system value). Otherwise, the number of bytes to ask for, try
|
||||
"4m" on a busy server. The OS caps it at a maximum, on linux unbound
|
||||
"4m" on a busy server. The OS caps it at a maximum, on linux Unbound
|
||||
needs root permission to bypass the limit, or the admin can use sysctl
|
||||
net.core.rmem_max. On BSD change kern.ipc.maxsockbuf in /etc/sysctl.conf.
|
||||
On OpenBSD change header and recompile kernel. On Solaris ndd \-set
|
||||
@@ -302,7 +311,7 @@ in answer traffic, otherwise 'send: resource temporarily unavailable'
|
||||
can get logged, the buffer overrun is also visible by netstat \-su.
|
||||
Default is 0 (use system value). Specify the number of bytes to ask
|
||||
for, try "4m" on a very busy server. The OS caps it at a maximum, on
|
||||
linux unbound needs root permission to bypass the limit, or the admin
|
||||
linux Unbound needs root permission to bypass the limit, or the admin
|
||||
can use sysctl net.core.wmem_max. On BSD, Solaris changes are similar
|
||||
to so\-rcvbuf.
|
||||
.TP
|
||||
@@ -319,18 +328,18 @@ At extreme load it could be better to turn it off to distribute the queries
|
||||
evenly, reported for Linux systems (4.4.x).
|
||||
.TP
|
||||
.B ip\-transparent: \fI<yes or no>
|
||||
If yes, then use IP_TRANSPARENT socket option on sockets where unbound
|
||||
If yes, then use IP_TRANSPARENT socket option on sockets where Unbound
|
||||
is listening for incoming traffic. Default no. Allows you to bind to
|
||||
non\-local interfaces. For example for non\-existent IP addresses that
|
||||
are going to exist later on, with host failover configuration. This is
|
||||
a lot like interface\-automatic, but that one services all interfaces
|
||||
and with this option you can select which (future) interfaces unbound
|
||||
provides service on. This option needs unbound to be started with root
|
||||
and with this option you can select which (future) interfaces Unbound
|
||||
provides service on. This option needs Unbound to be started with root
|
||||
permissions on some systems. The option uses IP_BINDANY on FreeBSD systems
|
||||
and SO_BINDANY on OpenBSD systems.
|
||||
.TP
|
||||
.B ip\-freebind: \fI<yes or no>
|
||||
If yes, then use IP_FREEBIND socket option on sockets where unbound
|
||||
If yes, then use IP_FREEBIND socket option on sockets where Unbound
|
||||
is listening to incoming traffic. Default no. Allows you to bind to
|
||||
IP addresses that are nonlocal or do not exist, like when the network
|
||||
interface or IP address is down. Exists only on Linux, where the similar
|
||||
@@ -340,7 +349,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.
|
||||
@@ -386,6 +395,10 @@ Lower limit for dynamic retransmit timeout calculation in infrastructure
|
||||
cache. Default is 50 milliseconds. Increase this value if using forwarders
|
||||
needing more time to do recursive name resolution.
|
||||
.TP
|
||||
.B infra\-cache\-max\-rtt: \fI<msec>
|
||||
Upper limit for dynamic retransmit timeout calculation in infrastructure
|
||||
cache. Default is 2 minutes.
|
||||
.TP
|
||||
.B infra\-keep\-probing: \fI<yes or no>
|
||||
If enabled the server keeps probing hosts that are down, in the one probe
|
||||
at a time regime. Default is no. Hosts that are down, eg. they did
|
||||
@@ -403,7 +416,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>
|
||||
@@ -499,10 +512,11 @@ Enabled or disable whether the upstream queries use TLS only for transport.
|
||||
Default is no. Useful in tunneling scenarios. The TLS contains plain DNS in
|
||||
TCP wireformat. The other server must support this (see
|
||||
\fBtls\-service\-key\fR).
|
||||
If you enable this, also configure a tls\-cert\-bundle or use tls\-win\-cert to
|
||||
load CA certs, otherwise the connections cannot be authenticated.
|
||||
This option enables TLS for all of them, but if you do not set this you can
|
||||
configure TLS specifically for some forward zones with forward\-tls\-upstream. And also with stub\-tls\-upstream.
|
||||
If you enable this, also configure a tls\-cert\-bundle or use tls\-win\-cert or
|
||||
tls\-system\-cert to load CA certs, otherwise the connections cannot be
|
||||
authenticated. This option enables TLS for all of them, but if you do not set
|
||||
this you can configure TLS specifically for some forward zones with
|
||||
forward\-tls\-upstream. And also with stub\-tls\-upstream.
|
||||
.TP
|
||||
.B ssl\-upstream: \fI<yes or no>
|
||||
Alternate syntax for \fBtls\-upstream\fR. If both are present in the config
|
||||
@@ -551,7 +565,12 @@ Alternate syntax for \fBtls\-cert\-bundle\fR.
|
||||
Add the system certificates to the cert bundle certificates for authentication.
|
||||
If no cert bundle, it uses only these certificates. Default is no.
|
||||
On windows this option uses the certificates from the cert store. Use
|
||||
the tls\-cert\-bundle option on other systems.
|
||||
the tls\-cert\-bundle option on other systems. On other systems, this option
|
||||
enables the system certificates.
|
||||
.TP
|
||||
.B tls\-system\-cert: \fI<yes or no>
|
||||
This the same setting as the tls\-win\-cert setting, under a different name.
|
||||
Because it is not windows specific.
|
||||
.TP
|
||||
.B tls\-additional\-port: \fI<portnr>
|
||||
List portnumbers as tls\-additional\-port, and when interfaces are defined,
|
||||
@@ -560,7 +579,7 @@ service. Can list multiple, each on a new statement.
|
||||
.TP
|
||||
.B tls-session-ticket-keys: \fI<file>
|
||||
If not "", lists files with 80 bytes of random contents that are used to
|
||||
perform TLS session resumption for clients using the unbound server.
|
||||
perform TLS session resumption for clients using the Unbound server.
|
||||
These files contain the secret key for the TLS session tickets.
|
||||
First key use to encrypt and decrypt TLS session tickets.
|
||||
Other keys use to decrypt only. With this you can roll over to new keys,
|
||||
@@ -637,13 +656,24 @@ 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.
|
||||
.TP
|
||||
.B do\-daemonize: \fI<yes or no>
|
||||
Enable or disable whether the unbound server forks into the background as
|
||||
a daemon. Set the value to \fIno\fR when unbound runs as systemd service.
|
||||
Enable or disable whether the Unbound server forks into the background as
|
||||
a daemon. Set the value to \fIno\fR when Unbound runs as systemd service.
|
||||
Default is yes.
|
||||
.TP
|
||||
.B tcp\-connection\-limit: \fI<IP netblock> <limit>
|
||||
@@ -656,7 +686,7 @@ 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.
|
||||
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.
|
||||
@@ -670,7 +700,7 @@ what almost all clients need). Nonrecursive queries are refused.
|
||||
.IP
|
||||
The \fIallow\fR action does allow nonrecursive queries to access the
|
||||
local\-data that is configured. The reason is that this does not involve
|
||||
the unbound server recursive lookup algorithm, and static data is served
|
||||
the Unbound server recursive lookup algorithm, and static data is served
|
||||
in the reply. This supports normal operations where nonrecursive queries
|
||||
are made for the authoritative data. For nonrecursive queries any replies
|
||||
from the dynamic cache are refused.
|
||||
@@ -722,6 +752,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
|
||||
@@ -742,7 +812,7 @@ to chroot and dropping permissions. This allows the pidfile to be
|
||||
Unbound is not able to remove the pidfile after termination when it is located
|
||||
outside of the chroot directory.
|
||||
.IP
|
||||
Additionally, unbound may need to access /dev/urandom (for entropy)
|
||||
Additionally, Unbound may need to access /dev/urandom (for entropy)
|
||||
from inside the chroot.
|
||||
.IP
|
||||
If given a chroot is done to the given directory. By default chroot is
|
||||
@@ -776,7 +846,7 @@ The logfile is reopened (for append) when the config file is reread, on
|
||||
SIGHUP.
|
||||
.TP
|
||||
.B use\-syslog: \fI<yes or no>
|
||||
Sets unbound to send log messages to the syslogd, using
|
||||
Sets Unbound to send log messages to the syslogd, using
|
||||
\fIsyslog\fR(3).
|
||||
The log facility LOG_DAEMON is used, with identity "unbound".
|
||||
The logfile setting is overridden when use\-syslog is turned on.
|
||||
@@ -786,7 +856,7 @@ The default is to log to syslog.
|
||||
If "" is given (default), then the name of the executable, usually "unbound"
|
||||
is used to report to the log. Enter a string to override it
|
||||
with that, which is useful on systems that run more than one instance of
|
||||
unbound, with different configurations, so that the logs can be easily
|
||||
Unbound, with different configurations, so that the logs can be easily
|
||||
distinguished against.
|
||||
.TP
|
||||
.B log\-time\-ascii: \fI<yes or no>
|
||||
@@ -874,12 +944,12 @@ with ascii_ prefix and then an ascii string.
|
||||
If enabled trustanchor.unbound queries are refused.
|
||||
.TP
|
||||
.B target\-fetch\-policy: \fI<"list of numbers">
|
||||
Set the target fetch policy used by unbound to determine if it should fetch
|
||||
Set the target fetch policy used by Unbound to determine if it should fetch
|
||||
nameserver target addresses opportunistically. The policy is described per
|
||||
dependency depth.
|
||||
.IP
|
||||
The number of values determines the maximum dependency depth
|
||||
that unbound will pursue in answering a query.
|
||||
that Unbound will pursue in answering a query.
|
||||
A value of \-1 means to fetch all targets opportunistically for that dependency
|
||||
depth. A value of 0 means to fetch on demand only. A positive value fetches
|
||||
that many targets opportunistically.
|
||||
@@ -973,7 +1043,7 @@ This option only has effect when qname-minimisation is enabled. Default is no.
|
||||
.B aggressive\-nsec: \fI<yes or no>
|
||||
Aggressive NSEC uses the DNSSEC NSEC chain to synthesize NXDOMAIN
|
||||
and other denials, using information from previous NXDOMAINs answers.
|
||||
Default is no. It helps to reduce the query rate towards targets that get
|
||||
Default is yes. It helps to reduce the query rate towards targets that get
|
||||
a very high nonexistent name lookup rate.
|
||||
.TP
|
||||
.B private\-address: \fI<IP address or subnet>
|
||||
@@ -1030,7 +1100,7 @@ a little more CPU. Also if the cache is set to 0, it is no use. Default is no.
|
||||
.TP
|
||||
.B deny\-any: \fI<yes or no>
|
||||
If yes, deny queries of type ANY with an empty response. Default is no.
|
||||
If disabled, unbound responds with a short list of resource records if some
|
||||
If disabled, Unbound responds with a short list of resource records if some
|
||||
can be found in the cache and makes the upstream type ANY query if there
|
||||
are none.
|
||||
.TP
|
||||
@@ -1090,7 +1160,7 @@ File with trust anchor for one zone, which is tracked with RFC5011 probes.
|
||||
The probes are run several times per month, thus the machine must be online
|
||||
frequently. The initial file can be one with contents as described in
|
||||
\fBtrust\-anchor\-file\fR. The file is written to when the anchor is updated,
|
||||
so the unbound user must have write permission. Write permission to the file,
|
||||
so the Unbound user must have write permission. Write permission to the file,
|
||||
but also to the directory it is in (to create a temporary file, which is
|
||||
necessary to deal with filesystem full events), it must also be inside the
|
||||
chroot (if that is used).
|
||||
@@ -1176,7 +1246,7 @@ the verbosity setting. Default is 0, off. At 1, for every user query
|
||||
that fails a line is printed to the logs. This way you can monitor what
|
||||
happens with validation. Use a diagnosis tool, such as dig or drill,
|
||||
to find out why validation is failing for these queries. At 2, not only
|
||||
the query that failed is printed but also the reason why unbound thought
|
||||
the query that failed is printed but also the reason why Unbound thought
|
||||
it was wrong and which server sent the faulty data.
|
||||
.TP
|
||||
.B val\-permissive\-mode: \fI<yes or no>
|
||||
@@ -1188,15 +1258,15 @@ is set in replies. Also logging is performed as for full validation.
|
||||
The default value is "no".
|
||||
.TP
|
||||
.B ignore\-cd\-flag: \fI<yes or no>
|
||||
Instruct unbound to ignore the CD flag from clients and refuse to
|
||||
Instruct Unbound to ignore the CD flag from clients and refuse to
|
||||
return bogus answers to them. Thus, the CD (Checking Disabled) flag
|
||||
does not disable checking any more. This is useful if legacy (w2008)
|
||||
servers that set the CD flag but cannot validate DNSSEC themselves are
|
||||
the clients, and then unbound provides them with DNSSEC protection.
|
||||
the clients, and then Unbound provides them with DNSSEC protection.
|
||||
The default value is "no".
|
||||
.TP
|
||||
.B serve\-expired: \fI<yes or no>
|
||||
If enabled, unbound attempts to serve old responses from cache with a
|
||||
If enabled, Unbound attempts to serve old responses from cache with a
|
||||
TTL of \fBserve\-expired\-reply\-ttl\fR in the response without waiting for the
|
||||
actual resolution to finish. The actual resolution answer ends up in the cache
|
||||
later on. Default is "no".
|
||||
@@ -1227,14 +1297,14 @@ RFC 8767 is 1800. Setting this to 0 will disable this
|
||||
behavior. Default is 0.
|
||||
.TP
|
||||
.B serve\-original\-ttl: \fI<yes or no>
|
||||
If enabled, unbound will always return the original TTL as received from
|
||||
If enabled, Unbound will always return the original TTL as received from
|
||||
the upstream name server rather than the decrementing TTL as
|
||||
stored in the cache. This feature may be useful if unbound serves as a
|
||||
front-end to a hidden authoritative name server. Enabling this feature does
|
||||
not impact cache expiry, it only changes the TTL unbound embeds in responses to
|
||||
stored in the cache. This feature may be useful if Unbound serves as a
|
||||
front-end to a hidden authoritative name server. Enabling this feature does
|
||||
not impact cache expiry, it only changes the TTL Unbound embeds in responses to
|
||||
queries. Note that enabling this feature implicitly disables enforcement of
|
||||
the configured minimum and maximum TTL, as it is assumed users who enable this
|
||||
feature do not want unbound to change the TTL obtained from an upstream server.
|
||||
the configured minimum and maximum TTL, as it is assumed users who enable this
|
||||
feature do not want Unbound to change the TTL obtained from an upstream server.
|
||||
Thus, the values set using \fBcache\-min\-ttl\fR and \fBcache\-max\-ttl\fR are
|
||||
ignored.
|
||||
Default is "no".
|
||||
@@ -1295,11 +1365,11 @@ or gigabytes (1024*1024 bytes in a megabyte).
|
||||
.TP
|
||||
.B unblock\-lan\-zones: \fI<yes or no>
|
||||
Default is disabled. If enabled, then for private address space,
|
||||
the reverse lookups are no longer filtered. This allows unbound when
|
||||
the reverse lookups are no longer filtered. This allows Unbound when
|
||||
running as dns service on a host where it provides service for that host,
|
||||
to put out all of the queries for the 'lan' upstream. When enabled,
|
||||
only localhost, 127.0.0.1 reverse and ::1 reverse zones are configured
|
||||
with default local zones. Disable the option when unbound is running
|
||||
with default local zones. Disable the option when Unbound is running
|
||||
as a (DHCP-) DNS network resolver for a group of machines, where such
|
||||
lookups should be filtered (RFC compliance), this also stops potential
|
||||
data leakage about the local network to the upstream DNS servers.
|
||||
@@ -1320,7 +1390,17 @@ 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
|
||||
it as detailed in the stub zone section below.
|
||||
it as detailed in the stub zone section below. A stub\-zone can be used to
|
||||
have unbound send queries to another server, an authoritative server, to
|
||||
fetch the information. With a forward\-zone, unbound sends queries to a server
|
||||
that is a recursive server to fetch the information. With an auth\-zone a
|
||||
zone can be loaded from file and used, it can be used like a local\-zone
|
||||
for users downstream, or the auth\-zone information can be used to fetch
|
||||
information from when resolving like it is an upstream server. The
|
||||
forward\-zone and auth\-zone options are described in their sections below.
|
||||
If you want to perform filtering of the information that the users can fetch,
|
||||
the local\-zone and local\-data statements allow for this, but also the
|
||||
rpz functionality can be used, described in the RPZ section.
|
||||
.TP 10
|
||||
\h'5'\fIdeny\fR
|
||||
Do not send an answer, drop the query.
|
||||
@@ -1403,7 +1483,7 @@ Breaks out of that view and moves towards the global local zones for answer
|
||||
to the query. If the view first is no, it'll resolve normally. If view first
|
||||
is enabled, it'll break perform that step and check the global answers.
|
||||
For when the view has view specific overrides but some zone has to be
|
||||
answered from global local zone contents.
|
||||
answered from global local zone contents.
|
||||
.TP 10
|
||||
\h'5'\fInodefault\fR
|
||||
Used to turn off default contents for AS112 zones. The other types
|
||||
@@ -1591,7 +1671,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.
|
||||
@@ -1647,8 +1727,9 @@ query names, but not spoofed reflection floods. Cached responses are not
|
||||
ratelimited by this setting. The zone of the query is determined by examining
|
||||
the nameservers for it, the zone name is used to keep track of the rate.
|
||||
For example, 1000 may be a suitable value to stop the server from being
|
||||
overloaded with random names, and keeps unbound from sending traffic to the
|
||||
nameservers for those zones.
|
||||
overloaded with random names, and keeps Unbound from sending traffic to the
|
||||
nameservers for those zones. Configured forwarders are excluded from
|
||||
ratelimiting.
|
||||
.TP 5
|
||||
.B ratelimit\-size: \fI<memory size>
|
||||
Give the size of the data structure in which the current ongoing rates are
|
||||
@@ -1670,6 +1751,15 @@ This can make ordinary queries complete (if repeatedly queried for),
|
||||
and enter the cache, whilst also mitigating the traffic flow by the
|
||||
factor given.
|
||||
.TP 5
|
||||
.B ratelimit\-backoff: \fI<yes or no>
|
||||
If enabled, the ratelimit is treated as a hard failure instead of the default
|
||||
maximum allowed constant rate. When the limit is reached, traffic is
|
||||
ratelimited and demand continues to be kept track of for a 2 second rate
|
||||
window. No traffic is allowed, except for ratelimit\-factor, until demand
|
||||
decreases below the configured ratelimit for a 2 second rate window. Useful to
|
||||
set ratelimit to a suspicious rate to aggressively limit unusually high
|
||||
traffic. Default is off.
|
||||
.TP 5
|
||||
.B ratelimit\-for\-domain: \fI<domain> <number qps or 0>
|
||||
Override the global ratelimit for an exact match domain name with the listed
|
||||
number. You can give this for any number of names. For example, for
|
||||
@@ -1686,7 +1776,7 @@ to use different settings for a top\-level\-domain and subdomains.
|
||||
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.
|
||||
Enable global ratelimiting of queries accepted per IP address.
|
||||
If 0, the default, it is disabled. 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.
|
||||
@@ -1713,10 +1803,22 @@ This can make ordinary queries complete (if repeatedly queried for),
|
||||
and enter the cache, whilst also mitigating the traffic flow by the
|
||||
factor given.
|
||||
.TP 5
|
||||
.B ip\-ratelimit\-backoff: \fI<yes or no>
|
||||
If enabled, the ratelimit is treated as a hard failure instead of the default
|
||||
maximum allowed constant rate. When the limit is reached, traffic is
|
||||
ratelimited and demand continues to be kept track of for a 2 second rate
|
||||
window. No traffic is allowed, except for ip\-ratelimit\-factor, until demand
|
||||
decreases below the configured ratelimit for a 2 second rate window. Useful to
|
||||
set ip\-ratelimit to a suspicious rate to aggressively limit unusually high
|
||||
traffic. Default is off.
|
||||
.TP 5
|
||||
.B outbound\-msg\-retry: \fI<number>
|
||||
The number of retries unbound will do in case of a non positive response is
|
||||
received. If a forward nameserver is used, this is the number of retries per
|
||||
forward nameserver in case of throwaway response.
|
||||
The number of retries, per upstream nameserver in a delegation, that Unbound
|
||||
will attempt in case a throwaway response is received.
|
||||
No response (timeout) contributes to the retry counter.
|
||||
If a forward/stub zone is used, this is the number of retries per nameserver in
|
||||
the zone.
|
||||
Default is 5.
|
||||
.TP 5
|
||||
.B fast\-server\-permil: \fI<number>
|
||||
Specify how many times out of 1000 to pick from the set of fastest servers.
|
||||
@@ -1742,12 +1844,27 @@ option can be used multiple times. The most specific match will be used.
|
||||
EDNS0 option code for the \fIedns\-client\-string\fR option, from 0 to 65535.
|
||||
A value from the `Reserved for Local/Experimental` range (65001-65534) should
|
||||
be used. Default is 65001.
|
||||
.TP 5
|
||||
.B ede: \fI<yes or no>
|
||||
If enabled, Unbound will respond with Extended DNS Error codes (RFC8914).
|
||||
These EDEs attach informative error messages to a response for various
|
||||
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
|
||||
.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
|
||||
the EDE code without setting the global \fBede\fR option to "yes" as well.
|
||||
Default is "no".
|
||||
.SS "Remote Control Options"
|
||||
In the
|
||||
.B remote\-control:
|
||||
clause are the declarations for the remote control facility. If this is
|
||||
enabled, the \fIunbound\-control\fR(8) utility can be used to send
|
||||
commands to the running unbound server. The server uses these clauses
|
||||
commands to the running Unbound server. The server uses these clauses
|
||||
to setup TLSv1 security for the connection. The
|
||||
\fIunbound\-control\fR(8) utility also reads the \fBremote\-control\fR
|
||||
section for options. To setup the correct self\-signed certificates use the
|
||||
@@ -1757,17 +1874,19 @@ 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
|
||||
the server for the change to take effect.
|
||||
.IP
|
||||
If you set it to an absolute path, a local socket is used. The local socket
|
||||
If you set it to an absolute path, a unix domain socket is used. This socket
|
||||
does not use the certificates and keys, so those files need not be present.
|
||||
To restrict access, unbound sets permissions on the file to the user and
|
||||
To restrict access, Unbound sets permissions on the file to the user and
|
||||
group that is configured, the access bits are set to allow the group members
|
||||
to access the control socket file. Put users that need to access the socket
|
||||
in the that group. To restrict access further, create a directory to put
|
||||
@@ -1787,12 +1906,12 @@ and the value of this option is ignored.
|
||||
.B server\-key\-file: \fI<private key file>
|
||||
Path to the server private key, by default unbound_server.key.
|
||||
This file is generated by the \fIunbound\-control\-setup\fR utility.
|
||||
This file is used by the unbound server, but not by \fIunbound\-control\fR.
|
||||
This file is used by the Unbound server, but not by \fIunbound\-control\fR.
|
||||
.TP 5
|
||||
.B server\-cert\-file: \fI<certificate file.pem>
|
||||
Path to the server self signed certificate, by default unbound_server.pem.
|
||||
This file is generated by the \fIunbound\-control\-setup\fR utility.
|
||||
This file is used by the unbound server, and also by \fIunbound\-control\fR.
|
||||
This file is used by the Unbound server, and also by \fIunbound\-control\fR.
|
||||
.TP 5
|
||||
.B control\-key\-file: \fI<private key file>
|
||||
Path to the control client private key, by default unbound_control.key.
|
||||
@@ -1810,24 +1929,24 @@ There may be multiple
|
||||
.B stub\-zone:
|
||||
clauses. Each with a name: and zero or more hostnames or IP addresses.
|
||||
For the stub zone this list of nameservers is used. Class IN is assumed.
|
||||
The servers should be authority servers, not recursors; unbound performs
|
||||
The servers should be authority servers, not recursors; Unbound performs
|
||||
the recursive processing itself for stub zones.
|
||||
.P
|
||||
The stub zone can be used to configure authoritative data to be used
|
||||
by the resolver that cannot be accessed using the public internet servers.
|
||||
This is useful for company\-local data or private zones. Setup an
|
||||
authoritative server on a different host (or different port). Enter a config
|
||||
entry for unbound with
|
||||
entry for Unbound with
|
||||
.B stub\-addr:
|
||||
<ip address of host[@port]>.
|
||||
The unbound resolver can then access the data, without referring to the
|
||||
The Unbound resolver can then access the data, without referring to the
|
||||
public internet for it.
|
||||
.P
|
||||
This setup allows DNSSEC signed zones to be served by that
|
||||
authoritative server, in which case a trusted key entry with the public key
|
||||
can be put in config, so that unbound can validate the data and set the AD
|
||||
can be put in config, so that Unbound can validate the data and set the AD
|
||||
bit on replies for the private zone (authoritative servers do not set the
|
||||
AD bit). This setup makes unbound capable of answering queries for the
|
||||
AD bit). This setup makes Unbound capable of answering queries for the
|
||||
private zone, and can even set the AD bit ('authentic'), but the AA
|
||||
('authoritative') bit is not set on these replies.
|
||||
.P
|
||||
@@ -1835,20 +1954,26 @@ Consider adding \fBserver:\fR statements for \fBdomain\-insecure:\fR and
|
||||
for \fBlocal\-zone:\fI name nodefault\fR for the zone if it is a locally
|
||||
served zone. The insecure clause stops DNSSEC from invalidating the
|
||||
zone. The local zone nodefault (or \fItransparent\fR) clause makes the
|
||||
(reverse\-) zone bypass unbound's filtering of RFC1918 zones.
|
||||
(reverse\-) zone bypass Unbound's filtering of RFC1918 zones.
|
||||
.TP
|
||||
.B name: \fI<domain name>
|
||||
Name of the stub zone. This is the full domain name of the zone.
|
||||
.TP
|
||||
.B stub\-host: \fI<domain name>
|
||||
Name of stub zone nameserver. Is itself resolved before it is used.
|
||||
To use a nondefault port for DNS communication append '@' with the port number.
|
||||
If tls is enabled, then you can append a '#' and a name, then it'll check the
|
||||
tls authentication certificates with that name. If you combine the '@'
|
||||
and '#', the '@' comes first. If only '#' is used the default port is the
|
||||
configured tls\-port.
|
||||
.TP
|
||||
.B stub\-addr: \fI<IP address>
|
||||
IP address of stub zone nameserver. Can be IP 4 or IP 6.
|
||||
To use a nondefault port for DNS communication append '@' with the port number.
|
||||
If tls is enabled, then you can append a '#' and a name, then it'll check
|
||||
the tls authentication certificates with that name. If you combine
|
||||
the '@' and '#', the '@' comes first.
|
||||
If tls is enabled, then you can append a '#' and a name, then it'll check the
|
||||
tls authentication certificates with that name. If you combine the '@'
|
||||
and '#', the '@' comes first. If only '#' is used the default port is the
|
||||
configured tls\-port.
|
||||
.TP
|
||||
.B stub\-prime: \fI<yes or no>
|
||||
This option is by default no. If enabled it performs NS set priming,
|
||||
@@ -1884,10 +2009,10 @@ clauses. Each with a \fBname:\fR and zero or more hostnames or IP
|
||||
addresses. For the forward zone this list of nameservers is used to
|
||||
forward the queries to. The servers listed as \fBforward\-host:\fR and
|
||||
\fBforward\-addr:\fR have to handle further recursion for the query. Thus,
|
||||
those servers are not authority servers, but are (just like unbound is)
|
||||
recursive servers too; unbound does not perform recursion itself for the
|
||||
those servers are not authority servers, but are (just like Unbound is)
|
||||
recursive servers too; Unbound does not perform recursion itself for the
|
||||
forward zone, it lets the remote server do it. Class IN is assumed.
|
||||
CNAMEs are chased by unbound itself, asking the remote server for every
|
||||
CNAMEs are chased by Unbound itself, asking the remote server for every
|
||||
name in the indirection chain, to protect the local cache from illegal
|
||||
indirect referenced items.
|
||||
A forward\-zone entry with name "." and a forward\-addr target will
|
||||
@@ -1899,13 +2024,19 @@ Name of the forward zone. This is the full domain name of the zone.
|
||||
.TP
|
||||
.B forward\-host: \fI<domain name>
|
||||
Name of server to forward to. Is itself resolved before it is used.
|
||||
To use a nondefault port for DNS communication append '@' with the port number.
|
||||
If tls is enabled, then you can append a '#' and a name, then it'll check the
|
||||
tls authentication certificates with that name. If you combine the '@'
|
||||
and '#', the '@' comes first. If only '#' is used the default port is the
|
||||
configured tls\-port.
|
||||
.TP
|
||||
.B forward\-addr: \fI<IP address>
|
||||
IP address of server to forward to. Can be IP 4 or IP 6.
|
||||
To use a nondefault port for DNS communication append '@' with the port number.
|
||||
If tls is enabled, then you can append a '#' and a name, then it'll check
|
||||
the tls authentication certificates with that name. If you combine
|
||||
the '@' and '#', the '@' comes first.
|
||||
If tls is enabled, then you can append a '#' and a name, then it'll check the
|
||||
tls authentication certificates with that name. If you combine the '@'
|
||||
and '#', the '@' comes first. If only '#' is used the default port is the
|
||||
configured tls\-port.
|
||||
.IP
|
||||
At high verbosity it logs the TLS certificate, with TLS enabled.
|
||||
If you leave out the '#' and auth name from the forward\-addr, any
|
||||
@@ -1913,7 +2044,7 @@ name is accepted. The cert must also match a CA from the tls\-cert\-bundle.
|
||||
.TP
|
||||
.B forward\-first: \fI<yes or no>
|
||||
If a forwarded query is met with a SERVFAIL error, and this option is
|
||||
enabled, unbound will fall back to normal recursive resolution for this
|
||||
enabled, Unbound will fall back to normal recursive resolution for this
|
||||
query as if no query forwarding had been specified. The default is "no".
|
||||
.TP
|
||||
.B forward\-tls\-upstream: \fI<yes or no>
|
||||
@@ -1939,7 +2070,7 @@ have a \fBname:\fR. There can be multiple ones, by listing multiple auth\-zone
|
||||
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
|
||||
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
|
||||
@@ -1996,29 +2127,29 @@ With allow\-notify you can specify additional sources of notifies.
|
||||
When notified, the server attempts to first probe and then zone transfer.
|
||||
If the notify is from a primary, it first attempts that primary. Otherwise
|
||||
other primaries are attempted. If there are no primaries, but only urls, the
|
||||
file is downloaded when notified. The primaries from primary: statements are
|
||||
allowed notify by default.
|
||||
file is downloaded when notified. The primaries from primary: and url:
|
||||
statements are allowed notify by default.
|
||||
.TP
|
||||
.B fallback\-enabled: \fI<yes or no>
|
||||
Default no. If enabled, unbound falls back to querying the internet as
|
||||
Default no. If enabled, Unbound falls back to querying the internet as
|
||||
a resolver for this zone when lookups fail. For example for DNSSEC
|
||||
validation failures.
|
||||
.TP
|
||||
.B for\-downstream: \fI<yes or no>
|
||||
Default yes. If enabled, unbound serves authority responses to
|
||||
downstream clients for this zone. This option makes unbound behave, for
|
||||
Default yes. If enabled, Unbound serves authority responses to
|
||||
downstream clients for this zone. This option makes Unbound behave, for
|
||||
the queries with names in this zone, like one of the authority servers for
|
||||
that zone. Turn it off if you want unbound to provide recursion for the
|
||||
that zone. Turn it off if you want Unbound to provide recursion for the
|
||||
zone but have a local copy of zone data. If for\-downstream is no and
|
||||
for\-upstream is yes, then unbound will DNSSEC validate the contents of the
|
||||
for\-upstream is yes, then Unbound will DNSSEC validate the contents of the
|
||||
zone before serving the zone contents to clients and store validation
|
||||
results in the cache.
|
||||
.TP
|
||||
.B for\-upstream: \fI<yes or no>
|
||||
Default yes. If enabled, unbound fetches data from this data collection
|
||||
Default yes. If enabled, Unbound fetches data from this data collection
|
||||
for answering recursion queries. Instead of sending queries over the internet
|
||||
to the authority servers for this zone, it'll fetch the data directly from
|
||||
the zone data. Turn it on when you want unbound to provide recursion for
|
||||
the zone data. Turn it on when you want Unbound to provide recursion for
|
||||
downstream clients, and use the zone data as a local copy to speed up lookups.
|
||||
.TP
|
||||
.B zonemd\-check: \fI<yes or no>
|
||||
@@ -2042,14 +2173,14 @@ a ZONEMD is always a failure, also for nonDNSSEC signed zones.
|
||||
.TP
|
||||
.B zonefile: \fI<filename>
|
||||
The filename where the zone is stored. If not given then no zonefile is used.
|
||||
If the file does not exist or is empty, unbound will attempt to fetch zone
|
||||
If the file does not exist or is empty, Unbound will attempt to fetch zone
|
||||
data (eg. from the primary servers).
|
||||
.SS "View Options"
|
||||
.LP
|
||||
There may be multiple
|
||||
.B view:
|
||||
clauses. Each with a \fBname:\fR and zero or more \fBlocal\-zone\fR and
|
||||
\fBlocal\-data\fR elements. Views can also contain view\-first,
|
||||
\fBlocal\-data\fR elements. Views can also contain view\-first,
|
||||
response\-ip, response\-ip\-data and local\-data\-ptr elements.
|
||||
View can be mapped to requests by specifying the
|
||||
view name in an \fBaccess\-control\-view\fR element. Options from matching
|
||||
@@ -2142,9 +2273,9 @@ underneath the name given.
|
||||
The
|
||||
.B dnscrypt:
|
||||
clause gives the settings of the dnscrypt channel. While those options are
|
||||
available, they are only meaningful if unbound was compiled with
|
||||
available, they are only meaningful if Unbound was compiled with
|
||||
\fB\-\-enable\-dnscrypt\fR.
|
||||
Currently certificate and secret/public keys cannot be generated by unbound.
|
||||
Currently certificate and secret/public keys cannot be generated by Unbound.
|
||||
You can use dnscrypt-wrapper to generate those: https://github.com/cofyc/\
|
||||
dnscrypt-wrapper/blob/master/README.md#usage
|
||||
.TP
|
||||
@@ -2263,7 +2394,7 @@ of 0 is always accepted. Default is 0.
|
||||
.TP
|
||||
.B min\-client\-subnet\-ipv4: \fI<number>\fR
|
||||
Specifies the minimum prefix length of the IPv4 source mask we are willing to
|
||||
accept in queries. Shorter source masks result in REFUSED answers. Source mask
|
||||
accept in queries. Shorter source masks result in REFUSED answers. Source mask
|
||||
of 0 is always accepted. Default is 0.
|
||||
.TP
|
||||
.B max\-ecs\-tree\-size\-ipv4: \fI<number>\fR
|
||||
@@ -2276,12 +2407,13 @@ This number applies for each qname/qclass/qtype tuple. Defaults to 100.
|
||||
.SS "Opportunistic IPsec Support Module Options"
|
||||
.LP
|
||||
The IPsec module must be configured in the \fBmodule\-config:\fR "ipsecmod
|
||||
validator iterator" directive and be compiled into the daemon to be
|
||||
enabled. These settings go in the \fBserver:\fR section.
|
||||
validator iterator" directive and be compiled into Unbound by using
|
||||
\fB\-\-enable\-ipsecmod\fR to be enabled.
|
||||
These settings go in the \fBserver:\fR section.
|
||||
.LP
|
||||
When unbound receives an A/AAAA query that is not in the cache and finds a
|
||||
When Unbound receives an A/AAAA query that is not in the cache and finds a
|
||||
valid answer, it will withhold returning the answer and instead will generate
|
||||
an IPSECKEY subquery for the same domain name. If an answer was found, unbound
|
||||
an IPSECKEY subquery for the same domain name. If an answer was found, Unbound
|
||||
will call an external hook passing the following arguments:
|
||||
.TP 10
|
||||
\h'5'\fIQNAME\fR
|
||||
@@ -2310,19 +2442,19 @@ relevant for opportunistic IPsec.
|
||||
.B ipsecmod-enabled: \fI<yes or no>\fR
|
||||
Specifies whether the IPsec module is enabled or not. The IPsec module still
|
||||
needs to be defined in the \fBmodule\-config:\fR directive. This option
|
||||
facilitates turning on/off the module without restarting/reloading unbound.
|
||||
facilitates turning on/off the module without restarting/reloading Unbound.
|
||||
Defaults to yes.
|
||||
.TP
|
||||
.B ipsecmod\-hook: \fI<filename>\fR
|
||||
Specifies the external hook that unbound will call with \fIsystem\fR(3). The
|
||||
Specifies the external hook that Unbound will call with \fIsystem\fR(3). The
|
||||
file can be specified as an absolute/relative path. The file needs the proper
|
||||
permissions to be able to be executed by the same user that runs unbound. It
|
||||
permissions to be able to be executed by the same user that runs Unbound. It
|
||||
must be present when the IPsec module is defined in the \fBmodule\-config:\fR
|
||||
directive.
|
||||
.TP
|
||||
.B ipsecmod-strict: \fI<yes or no>\fR
|
||||
If enabled unbound requires the external hook to return a success value of 0.
|
||||
Failing to do so unbound will reply with SERVFAIL. The A/AAAA answer will also
|
||||
If enabled Unbound requires the external hook to return a success value of 0.
|
||||
Failing to do so Unbound will reply with SERVFAIL. The A/AAAA answer will also
|
||||
not be cached. Defaults to no.
|
||||
.TP
|
||||
.B ipsecmod\-max-ttl: \fI<seconds>\fR
|
||||
@@ -2330,7 +2462,7 @@ Time to live maximum for A/AAAA cached records after calling the external hook.
|
||||
Defaults to 3600.
|
||||
.TP
|
||||
.B ipsecmod-ignore-bogus: \fI<yes or no>\fR
|
||||
Specifies the behaviour of unbound when the IPSECKEY answer is bogus. If set
|
||||
Specifies the behaviour of Unbound when the IPSECKEY answer is bogus. If set
|
||||
to yes, the hook will be called and the A/AAAA answer will be returned to the
|
||||
client. If set to no, the hook will not be called and the answer to the
|
||||
A/AAAA query will be SERVFAIL. Mainly used for testing. Defaults to no.
|
||||
@@ -2357,7 +2489,7 @@ If Unbound cannot even find an answer in the backend, it resolves the
|
||||
query as usual, and stores the answer in the backend.
|
||||
.P
|
||||
This module interacts with the \fBserve\-expired\-*\fR options and will reply
|
||||
with expired data if unbound is configured for that. Currently the use
|
||||
with expired data if Unbound is configured for that. Currently the use
|
||||
of \fBserve\-expired\-client\-timeout:\fR and
|
||||
\fBserve\-expired\-reply\-ttl:\fR is not consistent for data originating from
|
||||
the external cache as these will result in a reply with 0 TTL without trying to
|
||||
@@ -2436,16 +2568,17 @@ re-establish a new connection later.
|
||||
This option defaults to 100 milliseconds.
|
||||
.TP
|
||||
.B redis-expire-records: \fI<yes or no>
|
||||
If Redis record expiration is enabled. If yes, unbound sets timeout for Redis
|
||||
If Redis record expiration is enabled. If yes, Unbound sets timeout for Redis
|
||||
records so that Redis can evict keys that have expired automatically. If
|
||||
unbound is configured with \fBserve-expired\fR and \fBserve-expired-ttl\fR is 0,
|
||||
Unbound is configured with \fBserve-expired\fR and \fBserve-expired-ttl\fR is 0,
|
||||
this option is internally reverted to "no". Redis SETEX support is required
|
||||
for this option (Redis >= 2.0.0).
|
||||
This option defaults to no.
|
||||
.SS DNSTAP Logging Options
|
||||
DNSTAP support, when compiled in, is enabled in the \fBdnstap:\fR section.
|
||||
DNSTAP support, when compiled in by using \fB\-\-enable\-dnstap\fR, is enabled
|
||||
in the \fBdnstap:\fR section.
|
||||
This starts an extra thread (when compiled with threading) that writes
|
||||
the log information to the destination. If unbound is compiled without
|
||||
the log information to the destination. If Unbound is compiled without
|
||||
threading it does not spawn a thread, but connects per-process to the
|
||||
destination.
|
||||
.TP
|
||||
@@ -2503,19 +2636,19 @@ Default is "".
|
||||
.TP
|
||||
.B dnstap-log-resolver-query-messages: \fI<yes or no>
|
||||
Enable to log resolver query messages. Default is no.
|
||||
These are messages from unbound to upstream servers.
|
||||
These are messages from Unbound to upstream servers.
|
||||
.TP
|
||||
.B dnstap-log-resolver-response-messages: \fI<yes or no>
|
||||
Enable to log resolver response messages. Default is no.
|
||||
These are replies from upstream servers to unbound.
|
||||
These are replies from upstream servers to Unbound.
|
||||
.TP
|
||||
.B dnstap-log-client-query-messages: \fI<yes or no>
|
||||
Enable to log client query messages. Default is no.
|
||||
These are client queries to unbound.
|
||||
These are client queries to Unbound.
|
||||
.TP
|
||||
.B dnstap-log-client-response-messages: \fI<yes or no>
|
||||
Enable to log client response messages. Default is no.
|
||||
These are responses from unbound to clients.
|
||||
These are responses from Unbound to clients.
|
||||
.TP
|
||||
.B dnstap-log-forwarder-query-messages: \fI<yes or no>
|
||||
Enable to log forwarder query messages. Default is no.
|
||||
@@ -2609,12 +2742,12 @@ With allow\-notify you can specify additional sources of notifies.
|
||||
When notified, the server attempts to first probe and then zone transfer.
|
||||
If the notify is from a primary, it first attempts that primary. Otherwise
|
||||
other primaries are attempted. If there are no primaries, but only urls, the
|
||||
file is downloaded when notified. The primaries from primary: statements are
|
||||
allowed notify by default.
|
||||
file is downloaded when notified. The primaries from primary: and url:
|
||||
statements are allowed notify by default.
|
||||
.TP
|
||||
.B zonefile: \fI<filename>
|
||||
The filename where the zone is stored. If not given then no zonefile is used.
|
||||
If the file does not exist or is empty, unbound will attempt to fetch zone
|
||||
If the file does not exist or is empty, Unbound will attempt to fetch zone
|
||||
data (eg. from the primary servers).
|
||||
.TP
|
||||
.B rpz\-action\-override: \fI<action>
|
||||
@@ -2631,6 +2764,17 @@ Log all applied RPZ actions for this RPZ zone. Default is no.
|
||||
.B rpz\-log\-name: \fI<name>
|
||||
Specify a string to be part of the log line, for easy referencing.
|
||||
.TP
|
||||
.B rpz\-signal\-nxdomain\-ra: \fI<yes or no>
|
||||
Signal when a query is blocked by the RPZ with NXDOMAIN with an unset RA flag.
|
||||
This allows certain clients, like dnsmasq, to infer that the domain is
|
||||
externally blocked. Default is no.
|
||||
.TP
|
||||
.B for\-downstream: \fI<yes or no>
|
||||
If enabled the zone is authoritatively answered for and queries for the RPZ
|
||||
zone information are answered to downstream clients. This is useful for
|
||||
monitoring scripts, that can then access the SOA information to check if
|
||||
the rpz information is up to date. Default is no.
|
||||
.TP
|
||||
.B tags: \fI<list of tags>
|
||||
Limit the policies from this RPZ clause to clients with a matching tag. Tags
|
||||
need to be defined in \fBdefine\-tag\fR and can be assigned to client addresses
|
||||
@@ -2671,7 +2815,7 @@ server:
|
||||
.SH "FILES"
|
||||
.TP
|
||||
.I @UNBOUND_RUN_DIR@
|
||||
default unbound working directory.
|
||||
default Unbound working directory.
|
||||
.TP
|
||||
.I @UNBOUND_CHROOT_DIR@
|
||||
default
|
||||
@@ -2679,13 +2823,13 @@ default
|
||||
location.
|
||||
.TP
|
||||
.I @ub_conf_file@
|
||||
unbound configuration file.
|
||||
Unbound configuration file.
|
||||
.TP
|
||||
.I @UNBOUND_PIDFILE@
|
||||
default unbound pidfile with process ID of the running daemon.
|
||||
default Unbound pidfile with process ID of the running daemon.
|
||||
.TP
|
||||
.I unbound.log
|
||||
unbound log file. default is to log to
|
||||
Unbound log file. default is to log to
|
||||
\fIsyslog\fR(3).
|
||||
.SH "SEE ALSO"
|
||||
\fIunbound\fR(8),
|
||||
|
||||
@@ -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.
|
||||
|
||||
+87
-33
@@ -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 */
|
||||
@@ -93,13 +94,14 @@ subnet_new_qstate(struct module_qstate *qstate, int id)
|
||||
qstate->minfo[id] = sq;
|
||||
memset(sq, 0, sizeof(*sq));
|
||||
sq->started_no_cache_store = qstate->no_cache_store;
|
||||
sq->started_no_cache_lookup = qstate->no_cache_lookup;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** Add ecs struct to edns list, after parsing it to wire format. */
|
||||
static void
|
||||
ecs_opt_list_append(struct ecs_data* ecs, struct edns_option** list,
|
||||
struct module_qstate *qstate)
|
||||
void
|
||||
subnet_ecs_opt_list_append(struct ecs_data* ecs, struct edns_option** list,
|
||||
struct module_qstate *qstate, struct regional *region)
|
||||
{
|
||||
size_t sn_octs, sn_octs_remainder;
|
||||
sldns_buffer* buf = qstate->env->scratch_buffer;
|
||||
@@ -131,7 +133,7 @@ ecs_opt_list_append(struct ecs_data* ecs, struct edns_option** list,
|
||||
edns_opt_list_append(list,
|
||||
qstate->env->cfg->client_subnet_opcode,
|
||||
sn_octs + sn_octs_remainder + 4,
|
||||
sldns_buffer_begin(buf), qstate->region);
|
||||
sldns_buffer_begin(buf), region);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -139,7 +141,7 @@ int ecs_whitelist_check(struct query_info* qinfo,
|
||||
uint16_t ATTR_UNUSED(flags), struct module_qstate* qstate,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen,
|
||||
uint8_t* ATTR_UNUSED(zone), size_t ATTR_UNUSED(zonelen),
|
||||
struct regional* ATTR_UNUSED(region), int id, void* ATTR_UNUSED(cbargs))
|
||||
struct regional *region, int id, void* ATTR_UNUSED(cbargs))
|
||||
{
|
||||
struct subnet_qstate *sq;
|
||||
struct subnet_env *sn_env;
|
||||
@@ -162,17 +164,21 @@ int ecs_whitelist_check(struct query_info* qinfo,
|
||||
/* Address on whitelist or client query contains ECS option, we
|
||||
* want to sent out ECS. Only add option if it is not already
|
||||
* set. */
|
||||
if(!(sq->subnet_sent)) {
|
||||
ecs_opt_list_append(&sq->ecs_server_out,
|
||||
&qstate->edns_opts_back_out, qstate);
|
||||
sq->subnet_sent = 1;
|
||||
if(!edns_opt_list_find(qstate->edns_opts_back_out,
|
||||
qstate->env->cfg->client_subnet_opcode)) {
|
||||
subnet_ecs_opt_list_append(&sq->ecs_server_out,
|
||||
&qstate->edns_opts_back_out, qstate, region);
|
||||
}
|
||||
sq->subnet_sent = 1;
|
||||
}
|
||||
else if(sq->subnet_sent) {
|
||||
else {
|
||||
/* Outgoing ECS option is set, but we don't want to sent it to
|
||||
* this address, remove option. */
|
||||
edns_opt_list_remove(&qstate->edns_opts_back_out,
|
||||
qstate->env->cfg->client_subnet_opcode);
|
||||
if(edns_opt_list_find(qstate->edns_opts_back_out,
|
||||
qstate->env->cfg->client_subnet_opcode)) {
|
||||
edns_opt_list_remove(&qstate->edns_opts_back_out,
|
||||
qstate->env->cfg->client_subnet_opcode);
|
||||
}
|
||||
sq->subnet_sent = 0;
|
||||
}
|
||||
return 1;
|
||||
@@ -227,7 +233,7 @@ subnetmod_init(struct module_env *env, int id)
|
||||
env->unique_mesh = 1;
|
||||
if(!edns_register_option(env->cfg->client_subnet_opcode,
|
||||
env->cfg->client_subnet_always_forward /* bypass cache */,
|
||||
0 /* no aggregation */, env)) {
|
||||
1 /* no aggregation */, env)) {
|
||||
log_err("subnetcache: could not register opcode");
|
||||
ecs_whitelist_delete(sn_env->whitelist);
|
||||
slabhash_delete(sn_env->subnet_msg_cache);
|
||||
@@ -326,10 +332,13 @@ 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 */
|
||||
hashvalue_type h = qstate->minfo[id] ?
|
||||
((struct subnet_qstate*)qstate->minfo[id])->qinfo_hash :
|
||||
/* We already calculated hash upon lookup (lookup_and_reply) if we were
|
||||
* allowed to look in the ECS cache */
|
||||
hashvalue_type h = qstate->minfo[id] &&
|
||||
((struct subnet_qstate*)qstate->minfo[id])->qinfo_hash_calculated?
|
||||
((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,
|
||||
@@ -385,9 +394,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) {
|
||||
@@ -412,7 +424,10 @@ lookup_and_reply(struct module_qstate *qstate, int id, struct subnet_qstate *sq)
|
||||
|
||||
memset(&sq->ecs_client_out, 0, sizeof(sq->ecs_client_out));
|
||||
|
||||
if (sq) sq->qinfo_hash = h; /* Might be useful on cache miss */
|
||||
if (sq) {
|
||||
sq->qinfo_hash = h; /* Might be useful on cache miss */
|
||||
sq->qinfo_hash_calculated = 1;
|
||||
}
|
||||
e = slabhash_lookup(sne->subnet_msg_cache, h, &qstate->qinfo, 1);
|
||||
if (!e) return 0; /* qinfo not in cache */
|
||||
data = e->data;
|
||||
@@ -598,7 +613,7 @@ parse_subnet_option(struct edns_option* ecs_option, struct ecs_data* ecs)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void
|
||||
void
|
||||
subnet_option_from_ss(struct sockaddr_storage *ss, struct ecs_data* ecs,
|
||||
struct config_file* cfg)
|
||||
{
|
||||
@@ -664,6 +679,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))
|
||||
@@ -678,6 +711,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
|
||||
@@ -726,11 +760,12 @@ 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);
|
||||
}
|
||||
|
||||
@@ -754,18 +789,28 @@ subnetmod_operate(struct module_qstate *qstate, enum module_ev event,
|
||||
return;
|
||||
}
|
||||
|
||||
lock_rw_wrlock(&sne->biglock);
|
||||
if (lookup_and_reply(qstate, id, sq)) {
|
||||
sne->num_msg_cache++;
|
||||
lock_rw_unlock(&sne->biglock);
|
||||
verbose(VERB_QUERY, "subnetcache: answered from cache");
|
||||
qstate->ext_state[id] = module_finished;
|
||||
if(!sq->started_no_cache_lookup && !qstate->blacklist) {
|
||||
lock_rw_wrlock(&sne->biglock);
|
||||
if(lookup_and_reply(qstate, id, sq)) {
|
||||
sne->num_msg_cache++;
|
||||
lock_rw_unlock(&sne->biglock);
|
||||
verbose(VERB_QUERY, "subnetcache: answered from cache");
|
||||
qstate->ext_state[id] = module_finished;
|
||||
|
||||
ecs_opt_list_append(&sq->ecs_client_out,
|
||||
&qstate->edns_opts_front_out, qstate);
|
||||
return;
|
||||
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);
|
||||
}
|
||||
lock_rw_unlock(&sne->biglock);
|
||||
|
||||
sq->ecs_server_out.subnet_addr_fam =
|
||||
sq->ecs_client_in.subnet_addr_fam;
|
||||
@@ -783,7 +828,7 @@ subnetmod_operate(struct module_qstate *qstate, enum module_ev event,
|
||||
sq->ecs_server_out.subnet_source_mask =
|
||||
qstate->env->cfg->max_client_subnet_ipv6;
|
||||
/* Safe to copy completely, even if the source is limited by the
|
||||
* configuration. ecs_opt_list_append() will limit the address.
|
||||
* configuration. subnet_ecs_opt_list_append() will limit the address.
|
||||
* */
|
||||
memcpy(&sq->ecs_server_out.subnet_addr,
|
||||
sq->ecs_client_in.subnet_addr, INET6_SIZE);
|
||||
@@ -807,10 +852,19 @@ subnetmod_operate(struct module_qstate *qstate, enum module_ev event,
|
||||
qstate->ext_state[id] = eval_response(qstate, id, sq);
|
||||
if(qstate->ext_state[id] == module_finished &&
|
||||
qstate->return_msg) {
|
||||
ecs_opt_list_append(&sq->ecs_client_out,
|
||||
&qstate->edns_opts_front_out, qstate);
|
||||
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;
|
||||
return;
|
||||
}
|
||||
if(sq && outbound) {
|
||||
|
||||
@@ -76,6 +76,7 @@ struct subnet_msg_cache_data {
|
||||
struct subnet_qstate {
|
||||
/** We need the hash for both cache lookup and insert */
|
||||
hashvalue_type qinfo_hash;
|
||||
int qinfo_hash_calculated;
|
||||
/** ecs_data for client communication */
|
||||
struct ecs_data ecs_client_in;
|
||||
struct ecs_data ecs_client_out;
|
||||
@@ -92,6 +93,8 @@ struct subnet_qstate {
|
||||
uint8_t max_scope;
|
||||
/** has the subnet module been started with no_cache_store? */
|
||||
int started_no_cache_store;
|
||||
/** has the subnet module been started with no_cache_lookup? */
|
||||
int started_no_cache_lookup;
|
||||
};
|
||||
|
||||
void subnet_data_delete(void* d, void* ATTR_UNUSED(arg));
|
||||
@@ -143,4 +146,11 @@ int ecs_query_response(struct module_qstate* qstate, struct dns_msg* response,
|
||||
/** mark subnet msg to be deleted */
|
||||
void subnet_markdel(void* key);
|
||||
|
||||
/** Add ecs struct to edns list, after parsing it to wire format. */
|
||||
void subnet_ecs_opt_list_append(struct ecs_data* ecs, struct edns_option** list,
|
||||
struct module_qstate *qstate, struct regional *region);
|
||||
|
||||
/** Create ecs_data from the sockaddr_storage information. */
|
||||
void subnet_option_from_ss(struct sockaddr_storage *ss, struct ecs_data* ecs,
|
||||
struct config_file* cfg);
|
||||
#endif /* SUBNETMOD_H */
|
||||
|
||||
+1
-1
@@ -456,7 +456,7 @@ ipsecmod_handle_query(struct module_qstate* qstate,
|
||||
/* Store A/AAAA in cache. */
|
||||
if(!dns_cache_store(qstate->env, &qstate->qinfo,
|
||||
qstate->return_msg->rep, 0, qstate->prefetch_leeway,
|
||||
0, qstate->region, qstate->query_flags)) {
|
||||
0, qstate->region, qstate->query_flags, qstate->qstarttime)) {
|
||||
log_err("ipsecmod: out of memory caching record");
|
||||
}
|
||||
qstate->ext_state[id] = module_finished;
|
||||
|
||||
+37
-34
@@ -138,10 +138,10 @@ ipset_add_rrset_data(struct ipset_env *ie, struct mnl_socket *mnl,
|
||||
static int
|
||||
ipset_check_zones_for_rrset(struct module_env *env, struct ipset_env *ie,
|
||||
struct mnl_socket *mnl, struct ub_packed_rrset_key *rrset,
|
||||
const char *setname, int af)
|
||||
const char *qname, const int qlen, const char *setname, int af)
|
||||
{
|
||||
static char dname[BUFF_LEN];
|
||||
const char *s;
|
||||
const char *ds, *qs;
|
||||
int dlen, plen;
|
||||
|
||||
struct config_strlist *p;
|
||||
@@ -152,70 +152,73 @@ ipset_check_zones_for_rrset(struct module_env *env, struct ipset_env *ie,
|
||||
log_err("bad domain name");
|
||||
return -1;
|
||||
}
|
||||
if (dname[dlen - 1] == '.') {
|
||||
dlen--;
|
||||
}
|
||||
|
||||
for (p = env->cfg->local_zones_ipset; p; p = p->next) {
|
||||
ds = NULL;
|
||||
qs = NULL;
|
||||
plen = strlen(p->str);
|
||||
|
||||
if (dlen >= plen) {
|
||||
s = dname + (dlen - plen);
|
||||
|
||||
if (strncasecmp(p->str, s, plen) == 0) {
|
||||
d = (struct packed_rrset_data*)rrset->entry.data;
|
||||
ipset_add_rrset_data(ie, mnl, d, setname,
|
||||
af, dname);
|
||||
break;
|
||||
}
|
||||
ds = dname + (dlen - plen);
|
||||
}
|
||||
if (qlen >= plen) {
|
||||
qs = qname + (qlen - plen);
|
||||
}
|
||||
if ((ds && strncasecmp(p->str, ds, plen) == 0)
|
||||
|| (qs && strncasecmp(p->str, qs, plen) == 0)) {
|
||||
d = (struct packed_rrset_data*)rrset->entry.data;
|
||||
ipset_add_rrset_data(ie, mnl, d, setname,
|
||||
af, dname);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ipset_update(struct module_env *env, struct dns_msg *return_msg, struct ipset_env *ie) {
|
||||
static int ipset_update(struct module_env *env, struct dns_msg *return_msg,
|
||||
struct query_info qinfo, struct ipset_env *ie)
|
||||
{
|
||||
struct mnl_socket *mnl;
|
||||
|
||||
size_t i;
|
||||
|
||||
const char *setname;
|
||||
|
||||
struct ub_packed_rrset_key *rrset;
|
||||
|
||||
int af;
|
||||
|
||||
static char qname[BUFF_LEN];
|
||||
int qlen;
|
||||
|
||||
mnl = (struct mnl_socket *)ie->mnl;
|
||||
if (!mnl) {
|
||||
// retry to create mnl socket
|
||||
/* retry to create mnl socket */
|
||||
mnl = open_mnl_socket();
|
||||
if (!mnl) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
ie->mnl = mnl;
|
||||
}
|
||||
|
||||
for (i = 0; i < return_msg->rep->rrset_count; ++i) {
|
||||
qlen = sldns_wire2str_dname_buf(qinfo.qname, qinfo.qname_len,
|
||||
qname, BUFF_LEN);
|
||||
if(qlen == 0) {
|
||||
log_err("bad domain name");
|
||||
return -1;
|
||||
}
|
||||
|
||||
for(i = 0; i < return_msg->rep->rrset_count; i++) {
|
||||
setname = NULL;
|
||||
|
||||
rrset = return_msg->rep->rrsets[i];
|
||||
|
||||
if (rrset->rk.type == htons(LDNS_RR_TYPE_A)) {
|
||||
if(ntohs(rrset->rk.type) == LDNS_RR_TYPE_A &&
|
||||
ie->v4_enabled == 1) {
|
||||
af = AF_INET;
|
||||
if ((ie->v4_enabled == 1)) {
|
||||
setname = ie->name_v4;
|
||||
}
|
||||
} else {
|
||||
setname = ie->name_v4;
|
||||
} else if(ntohs(rrset->rk.type) == LDNS_RR_TYPE_AAAA &&
|
||||
ie->v6_enabled == 1) {
|
||||
af = AF_INET6;
|
||||
if ((ie->v6_enabled == 1)) {
|
||||
setname = ie->name_v6;
|
||||
}
|
||||
setname = ie->name_v6;
|
||||
}
|
||||
|
||||
if (setname) {
|
||||
if(ipset_check_zones_for_rrset(env, ie, mnl, rrset,
|
||||
setname, af) == -1)
|
||||
qname, qlen, setname, af) == -1)
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@@ -311,7 +314,7 @@ void ipset_operate(struct module_qstate *qstate, enum module_ev event, int id,
|
||||
|
||||
if (iq && (event == module_event_moddone)) {
|
||||
if (qstate->return_msg && qstate->return_msg->rep) {
|
||||
ipset_update(qstate->env, qstate->return_msg, ie);
|
||||
ipset_update(qstate->env, qstate->return_msg, qstate->qinfo, ie);
|
||||
}
|
||||
qstate->ext_state[id] = module_finished;
|
||||
return;
|
||||
|
||||
+71
-24
@@ -75,8 +75,10 @@ struct delegpt* delegpt_copy(struct delegpt* dp, struct regional* region)
|
||||
copy->ssl_upstream = dp->ssl_upstream;
|
||||
copy->tcp_upstream = dp->tcp_upstream;
|
||||
for(ns = dp->nslist; ns; ns = ns->next) {
|
||||
if(!delegpt_add_ns(copy, region, ns->name, ns->lame))
|
||||
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;
|
||||
@@ -84,8 +86,8 @@ struct delegpt* delegpt_copy(struct delegpt* dp, struct regional* region)
|
||||
copy->nslist->done_pside6 = ns->done_pside6;
|
||||
}
|
||||
for(a = dp->target_list; a; a = a->next_target) {
|
||||
if(!delegpt_add_addr(copy, region, &a->addr, a->addrlen,
|
||||
a->bogus, a->lame, a->tls_auth_name, NULL))
|
||||
if(!delegpt_add_addr(copy, region, &a->addr, a->addrlen,
|
||||
a->bogus, a->lame, a->tls_auth_name, -1, NULL))
|
||||
return NULL;
|
||||
}
|
||||
return copy;
|
||||
@@ -102,7 +104,7 @@ delegpt_set_name(struct delegpt* dp, struct regional* region, uint8_t* name)
|
||||
|
||||
int
|
||||
delegpt_add_ns(struct delegpt* dp, struct regional* region, uint8_t* name,
|
||||
uint8_t lame)
|
||||
uint8_t lame, char* tls_auth_name, int port)
|
||||
{
|
||||
struct delegpt_ns* ns;
|
||||
size_t len;
|
||||
@@ -120,12 +122,21 @@ 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;
|
||||
ns->lame = lame;
|
||||
ns->done_pside4 = 0;
|
||||
ns->done_pside6 = 0;
|
||||
ns->port = port;
|
||||
if(tls_auth_name) {
|
||||
ns->tls_auth_name = regional_strdup(region, tls_auth_name);
|
||||
if(!ns->tls_auth_name)
|
||||
return 0;
|
||||
} else {
|
||||
ns->tls_auth_name = NULL;
|
||||
}
|
||||
return ns->name != 0;
|
||||
}
|
||||
|
||||
@@ -159,9 +170,9 @@ delegpt_find_addr(struct delegpt* dp, struct sockaddr_storage* addr,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int
|
||||
delegpt_add_target(struct delegpt* dp, struct regional* region,
|
||||
uint8_t* name, size_t namelen, struct sockaddr_storage* addr,
|
||||
int
|
||||
delegpt_add_target(struct delegpt* dp, struct regional* region,
|
||||
uint8_t* name, size_t namelen, struct sockaddr_storage* addr,
|
||||
socklen_t addrlen, uint8_t bogus, uint8_t lame, int* additions)
|
||||
{
|
||||
struct delegpt_ns* ns = delegpt_find_ns(dp, name, namelen);
|
||||
@@ -176,18 +187,27 @@ delegpt_add_target(struct delegpt* dp, struct regional* region,
|
||||
else ns->got4 = 1;
|
||||
if(ns->got4 && ns->got6)
|
||||
ns->resolved = 1;
|
||||
} else {
|
||||
if(addr_is_ip6(addr, addrlen))
|
||||
ns->done_pside6 = 1;
|
||||
else ns->done_pside4 = 1;
|
||||
}
|
||||
return delegpt_add_addr(dp, region, addr, addrlen, bogus, lame, NULL,
|
||||
additions);
|
||||
log_assert(ns->port>0);
|
||||
return delegpt_add_addr(dp, region, addr, addrlen, bogus, lame,
|
||||
ns->tls_auth_name, ns->port, additions);
|
||||
}
|
||||
|
||||
int
|
||||
delegpt_add_addr(struct delegpt* dp, struct regional* region,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen, uint8_t bogus,
|
||||
uint8_t lame, char* tls_auth_name, int* additions)
|
||||
int
|
||||
delegpt_add_addr(struct delegpt* dp, struct regional* region,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen, uint8_t bogus,
|
||||
uint8_t lame, char* tls_auth_name, int port, int* additions)
|
||||
{
|
||||
struct delegpt_addr* a;
|
||||
log_assert(!dp->dp_type_mlc);
|
||||
if(port != -1) {
|
||||
log_assert(port>0);
|
||||
sockaddr_store_port(addr, addrlen, port);
|
||||
}
|
||||
/* check for duplicates */
|
||||
if((a = delegpt_find_addr(dp, addr, addrlen))) {
|
||||
if(bogus)
|
||||
@@ -324,13 +344,16 @@ delegpt_count_targets(struct delegpt* dp)
|
||||
}
|
||||
|
||||
size_t
|
||||
delegpt_count_missing_targets(struct delegpt* dp)
|
||||
delegpt_count_missing_targets(struct delegpt* dp, int* alllame)
|
||||
{
|
||||
struct delegpt_ns* ns;
|
||||
size_t n = 0;
|
||||
for(ns = dp->nslist; ns; ns = ns->next)
|
||||
if(!ns->resolved)
|
||||
n++;
|
||||
size_t n = 0, nlame = 0;
|
||||
for(ns = dp->nslist; ns; ns = ns->next) {
|
||||
if(ns->resolved) continue;
|
||||
n++;
|
||||
if(ns->lame) nlame++;
|
||||
}
|
||||
if(alllame && n == nlame) *alllame = 1;
|
||||
return n;
|
||||
}
|
||||
|
||||
@@ -412,7 +435,8 @@ delegpt_rrset_add_ns(struct delegpt* dp, struct regional* region,
|
||||
(size_t)sldns_read_uint16(nsdata->rr_data[i]))
|
||||
continue; /* bad format */
|
||||
/* add rdata of NS (= wirefmt dname), skip rdatalen bytes */
|
||||
if(!delegpt_add_ns(dp, region, nsdata->rr_data[i]+2, lame))
|
||||
if(!delegpt_add_ns(dp, region, nsdata->rr_data[i]+2, lame,
|
||||
NULL, UNBOUND_DNS_PORT))
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
@@ -429,7 +453,6 @@ delegpt_add_rrset_A(struct delegpt* dp, struct regional* region,
|
||||
log_assert(!dp->dp_type_mlc);
|
||||
memset(&sa, 0, len);
|
||||
sa.sin_family = AF_INET;
|
||||
sa.sin_port = (in_port_t)htons(UNBOUND_DNS_PORT);
|
||||
for(i=0; i<d->count; i++) {
|
||||
if(d->rr_len[i] != 2 + INET_SIZE)
|
||||
continue;
|
||||
@@ -453,7 +476,6 @@ delegpt_add_rrset_AAAA(struct delegpt* dp, struct regional* region,
|
||||
log_assert(!dp->dp_type_mlc);
|
||||
memset(&sa, 0, len);
|
||||
sa.sin6_family = AF_INET6;
|
||||
sa.sin6_port = (in_port_t)htons(UNBOUND_DNS_PORT);
|
||||
for(i=0; i<d->count; i++) {
|
||||
if(d->rr_len[i] != 2 + INET6_SIZE) /* rdatalen + len of IP6 */
|
||||
continue;
|
||||
@@ -555,6 +577,7 @@ void delegpt_free_mlc(struct delegpt* dp)
|
||||
while(n) {
|
||||
nn = n->next;
|
||||
free(n->name);
|
||||
free(n->tls_auth_name);
|
||||
free(n);
|
||||
n = nn;
|
||||
}
|
||||
@@ -577,7 +600,8 @@ int delegpt_set_name_mlc(struct delegpt* dp, uint8_t* name)
|
||||
return (dp->name != NULL);
|
||||
}
|
||||
|
||||
int delegpt_add_ns_mlc(struct delegpt* dp, uint8_t* name, uint8_t lame)
|
||||
int delegpt_add_ns_mlc(struct delegpt* dp, uint8_t* name, uint8_t lame,
|
||||
char* tls_auth_name, int port)
|
||||
{
|
||||
struct delegpt_ns* ns;
|
||||
size_t len;
|
||||
@@ -598,20 +622,37 @@ 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;
|
||||
ns->lame = (uint8_t)lame;
|
||||
ns->done_pside4 = 0;
|
||||
ns->done_pside6 = 0;
|
||||
ns->port = port;
|
||||
if(tls_auth_name) {
|
||||
ns->tls_auth_name = strdup(tls_auth_name);
|
||||
if(!ns->tls_auth_name) {
|
||||
free(ns->name);
|
||||
free(ns);
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
ns->tls_auth_name = NULL;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int delegpt_add_addr_mlc(struct delegpt* dp, struct sockaddr_storage* addr,
|
||||
socklen_t addrlen, uint8_t bogus, uint8_t lame, char* tls_auth_name)
|
||||
socklen_t addrlen, uint8_t bogus, uint8_t lame, char* tls_auth_name,
|
||||
int port)
|
||||
{
|
||||
struct delegpt_addr* a;
|
||||
log_assert(dp->dp_type_mlc);
|
||||
if(port != -1) {
|
||||
log_assert(port>0);
|
||||
sockaddr_store_port(addr, addrlen, port);
|
||||
}
|
||||
/* check for duplicates */
|
||||
if((a = delegpt_find_addr(dp, addr, addrlen))) {
|
||||
if(bogus)
|
||||
@@ -663,8 +704,14 @@ int delegpt_add_target_mlc(struct delegpt* dp, uint8_t* name, size_t namelen,
|
||||
else ns->got4 = 1;
|
||||
if(ns->got4 && ns->got6)
|
||||
ns->resolved = 1;
|
||||
} else {
|
||||
if(addr_is_ip6(addr, addrlen))
|
||||
ns->done_pside6 = 1;
|
||||
else ns->done_pside4 = 1;
|
||||
}
|
||||
return delegpt_add_addr_mlc(dp, addr, addrlen, bogus, lame, NULL);
|
||||
log_assert(ns->port>0);
|
||||
return delegpt_add_addr_mlc(dp, addr, addrlen, bogus, lame,
|
||||
ns->tls_auth_name, ns->port);
|
||||
}
|
||||
|
||||
size_t delegpt_get_mem(struct delegpt* dp)
|
||||
|
||||
+25
-8
@@ -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.
|
||||
@@ -126,6 +128,11 @@ struct delegpt_ns {
|
||||
* Also enabled if a parent-side cache entry exists, or a parent-side
|
||||
* negative-cache entry exists. */
|
||||
uint8_t done_pside6;
|
||||
/** the TLS authentication name, (if not NULL) to use. */
|
||||
char* tls_auth_name;
|
||||
/** the port to use; it should mostly be the default 53 but configured
|
||||
* upstreams can provide nondefault ports. */
|
||||
int port;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -191,10 +198,12 @@ int delegpt_set_name(struct delegpt* dp, struct regional* regional,
|
||||
* @param regional: where to allocate the info.
|
||||
* @param name: domain name in wire format.
|
||||
* @param lame: name is lame, disprefer it.
|
||||
* @param tls_auth_name: TLS authentication name (or NULL).
|
||||
* @param port: port to use for resolved addresses.
|
||||
* @return false on error.
|
||||
*/
|
||||
int delegpt_add_ns(struct delegpt* dp, struct regional* regional,
|
||||
uint8_t* name, uint8_t lame);
|
||||
int delegpt_add_ns(struct delegpt* dp, struct regional* regional,
|
||||
uint8_t* name, uint8_t lame, char* tls_auth_name, int port);
|
||||
|
||||
/**
|
||||
* Add NS rrset; calls add_ns repeatedly.
|
||||
@@ -271,12 +280,14 @@ int delegpt_add_rrset(struct delegpt* dp, struct regional* regional,
|
||||
* @param bogus: if address is bogus.
|
||||
* @param lame: if address is lame.
|
||||
* @param tls_auth_name: TLS authentication name (or NULL).
|
||||
* @param port: the port to use; if -1 the port is taken from addr.
|
||||
* @param additions: will be set to 1 if a new address is added
|
||||
* @return false on error.
|
||||
*/
|
||||
int delegpt_add_addr(struct delegpt* dp, struct regional* regional,
|
||||
int delegpt_add_addr(struct delegpt* dp, struct regional* regional,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen,
|
||||
uint8_t bogus, uint8_t lame, char* tls_auth_name, int* additions);
|
||||
uint8_t bogus, uint8_t lame, char* tls_auth_name, int port,
|
||||
int* additions);
|
||||
|
||||
/**
|
||||
* Find NS record in name list of delegation point.
|
||||
@@ -321,9 +332,10 @@ void delegpt_add_unused_targets(struct delegpt* dp);
|
||||
/**
|
||||
* Count number of missing targets. These are ns names with no resolved flag.
|
||||
* @param dp: delegation point.
|
||||
* @param alllame: if set, check if all the missing targets are lame.
|
||||
* @return number of missing targets (or 0).
|
||||
*/
|
||||
size_t delegpt_count_missing_targets(struct delegpt* dp);
|
||||
size_t delegpt_count_missing_targets(struct delegpt* dp, int* alllame);
|
||||
|
||||
/** count total number of targets in dp */
|
||||
size_t delegpt_count_targets(struct delegpt* dp);
|
||||
@@ -404,22 +416,27 @@ int delegpt_set_name_mlc(struct delegpt* dp, uint8_t* name);
|
||||
* @param dp: must have been created with delegpt_create_mlc.
|
||||
* @param name: the name to add.
|
||||
* @param lame: the name is lame, disprefer.
|
||||
* @param tls_auth_name: TLS authentication name (or NULL).
|
||||
* @param port: port to use for resolved addresses.
|
||||
* @return false on error.
|
||||
*/
|
||||
int delegpt_add_ns_mlc(struct delegpt* dp, uint8_t* name, uint8_t lame);
|
||||
int delegpt_add_ns_mlc(struct delegpt* dp, uint8_t* name, uint8_t lame,
|
||||
char* tls_auth_name, int port);
|
||||
|
||||
/**
|
||||
* add an address to a malloced delegation point.
|
||||
* @param dp: must have been created with delegpt_create_mlc.
|
||||
* @param dp: must have been created with delegpt_create_mlc.
|
||||
* @param addr: the address.
|
||||
* @param addrlen: the length of addr.
|
||||
* @param bogus: if address is bogus.
|
||||
* @param lame: if address is lame.
|
||||
* @param tls_auth_name: TLS authentication name (or NULL).
|
||||
* @param port: the port to use; if -1 the port is taken from addr.
|
||||
* @return false on error.
|
||||
*/
|
||||
int delegpt_add_addr_mlc(struct delegpt* dp, struct sockaddr_storage* addr,
|
||||
socklen_t addrlen, uint8_t bogus, uint8_t lame, char* tls_auth_name);
|
||||
socklen_t addrlen, uint8_t bogus, uint8_t lame, char* tls_auth_name,
|
||||
int port);
|
||||
|
||||
/**
|
||||
* Add target address to the delegation point.
|
||||
|
||||
+11
-5
@@ -200,21 +200,27 @@ read_fwds_name(struct config_stub* s)
|
||||
}
|
||||
|
||||
/** set fwd host names */
|
||||
static int
|
||||
static int
|
||||
read_fwds_host(struct config_stub* s, struct delegpt* dp)
|
||||
{
|
||||
struct config_strlist* p;
|
||||
uint8_t* dname;
|
||||
size_t dname_len;
|
||||
char* tls_auth_name;
|
||||
int port;
|
||||
for(p = s->hosts; p; p = p->next) {
|
||||
log_assert(p->str);
|
||||
dname = sldns_str2wire_dname(p->str, &dname_len);
|
||||
dname = authextstrtodname(p->str, &port, &tls_auth_name);
|
||||
if(!dname) {
|
||||
log_err("cannot parse forward %s server name: '%s'",
|
||||
s->name, p->str);
|
||||
return 0;
|
||||
}
|
||||
if(!delegpt_add_ns_mlc(dp, dname, 0)) {
|
||||
#if ! defined(HAVE_SSL_SET1_HOST) && ! defined(HAVE_X509_VERIFY_PARAM_SET1_HOST)
|
||||
if(tls_auth_name)
|
||||
log_err("no name verification functionality in "
|
||||
"ssl library, ignored name for %s", p->str);
|
||||
#endif
|
||||
if(!delegpt_add_ns_mlc(dp, dname, 0, tls_auth_name, port)) {
|
||||
free(dname);
|
||||
log_err("out of memory");
|
||||
return 0;
|
||||
@@ -245,7 +251,7 @@ read_fwds_addr(struct config_stub* s, struct delegpt* dp)
|
||||
"ssl library, ignored name for %s", p->str);
|
||||
#endif
|
||||
if(!delegpt_add_addr_mlc(dp, &addr, addrlen, 0, 0,
|
||||
tls_auth_name)) {
|
||||
tls_auth_name, -1)) {
|
||||
log_err("out of memory");
|
||||
return 0;
|
||||
}
|
||||
|
||||
+14
-8
@@ -99,8 +99,8 @@ ah(struct delegpt* dp, const char* sv, const char* ip)
|
||||
log_err("could not parse %s", sv);
|
||||
return 0;
|
||||
}
|
||||
if(!delegpt_add_ns_mlc(dp, dname, 0) ||
|
||||
!extstrtoaddr(ip, &addr, &addrlen) ||
|
||||
if(!delegpt_add_ns_mlc(dp, dname, 0, NULL, UNBOUND_DNS_PORT) ||
|
||||
!extstrtoaddr(ip, &addr, &addrlen, UNBOUND_DNS_PORT) ||
|
||||
!delegpt_add_target_mlc(dp, dname, dname_len,
|
||||
&addr, addrlen, 0, 0)) {
|
||||
free(dname);
|
||||
@@ -213,21 +213,27 @@ read_stubs_name(struct config_stub* s)
|
||||
}
|
||||
|
||||
/** set stub host names */
|
||||
static int
|
||||
static int
|
||||
read_stubs_host(struct config_stub* s, struct delegpt* dp)
|
||||
{
|
||||
struct config_strlist* p;
|
||||
size_t dname_len;
|
||||
uint8_t* dname;
|
||||
char* tls_auth_name;
|
||||
int port;
|
||||
for(p = s->hosts; p; p = p->next) {
|
||||
log_assert(p->str);
|
||||
dname = sldns_str2wire_dname(p->str, &dname_len);
|
||||
dname = authextstrtodname(p->str, &port, &tls_auth_name);
|
||||
if(!dname) {
|
||||
log_err("cannot parse stub %s nameserver name: '%s'",
|
||||
s->name, p->str);
|
||||
return 0;
|
||||
}
|
||||
if(!delegpt_add_ns_mlc(dp, dname, 0)) {
|
||||
#if ! defined(HAVE_SSL_SET1_HOST) && ! defined(HAVE_X509_VERIFY_PARAM_SET1_HOST)
|
||||
if(tls_auth_name)
|
||||
log_err("no name verification functionality in "
|
||||
"ssl library, ignored name for %s", p->str);
|
||||
#endif
|
||||
if(!delegpt_add_ns_mlc(dp, dname, 0, tls_auth_name, port)) {
|
||||
free(dname);
|
||||
log_err("out of memory");
|
||||
return 0;
|
||||
@@ -258,7 +264,7 @@ read_stubs_addr(struct config_stub* s, struct delegpt* dp)
|
||||
"ssl library, ignored name for %s", p->str);
|
||||
#endif
|
||||
if(!delegpt_add_addr_mlc(dp, &addr, addrlen, 0, 0,
|
||||
auth_name)) {
|
||||
auth_name, -1)) {
|
||||
log_err("out of memory");
|
||||
return 0;
|
||||
}
|
||||
@@ -338,7 +344,7 @@ read_root_hints(struct iter_hints* hints, char* fname)
|
||||
if(sldns_wirerr_get_type(rr, rr_len, dname_len)
|
||||
== LDNS_RR_TYPE_NS) {
|
||||
if(!delegpt_add_ns_mlc(dp, sldns_wirerr_get_rdata(rr,
|
||||
rr_len, dname_len), 0)) {
|
||||
rr_len, dname_len), 0, NULL, UNBOUND_DNS_PORT)) {
|
||||
log_err("out of memory reading root hints");
|
||||
goto stop_read;
|
||||
}
|
||||
|
||||
@@ -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 */
|
||||
|
||||
+28
-11
@@ -70,8 +70,6 @@
|
||||
|
||||
/** time when nameserver glue is said to be 'recent' */
|
||||
#define SUSPICION_RECENT_EXPIRY 86400
|
||||
/** penalty to validation failed blacklisted IPs */
|
||||
#define BLACKLIST_PENALTY (USEFUL_SERVER_TOP_TIMEOUT*4)
|
||||
|
||||
/** fillup fetch policy array */
|
||||
static void
|
||||
@@ -367,6 +365,7 @@ iter_filter_order(struct iter_env* iter_env, struct module_env* env,
|
||||
struct sock_list* blacklist, time_t prefetch)
|
||||
{
|
||||
int got_num = 0, low_rtt = 0, swap_to_front, rtt_band = RTT_BAND, nth;
|
||||
int alllame = 0;
|
||||
size_t num_results;
|
||||
struct delegpt_addr* a, *n, *prev=NULL;
|
||||
|
||||
@@ -376,7 +375,10 @@ iter_filter_order(struct iter_env* iter_env, struct module_env* env,
|
||||
if(got_num == 0)
|
||||
return 0;
|
||||
if(low_rtt >= USEFUL_SERVER_TOP_TIMEOUT &&
|
||||
(delegpt_count_missing_targets(dp) > 0 || open_target > 0)) {
|
||||
/* If all missing (or not fully resolved) targets are lame,
|
||||
* then use the remaining lame address. */
|
||||
((delegpt_count_missing_targets(dp, &alllame) > 0 && !alllame) ||
|
||||
open_target > 0)) {
|
||||
verbose(VERB_ALGO, "Bad choices, trying to get more choice");
|
||||
return 0; /* we want more choice. The best choice is a bad one.
|
||||
return 0 to force the caller to fetch more */
|
||||
@@ -657,10 +659,10 @@ dns_copy_msg(struct dns_msg* from, struct regional* region)
|
||||
void
|
||||
iter_dns_store(struct module_env* env, struct query_info* msgqinf,
|
||||
struct reply_info* msgrep, int is_referral, time_t leeway, int pside,
|
||||
struct regional* region, uint16_t flags)
|
||||
struct regional* region, uint16_t flags, time_t qstarttime)
|
||||
{
|
||||
if(!dns_cache_store(env, msgqinf, msgrep, is_referral, leeway,
|
||||
pside, region, flags))
|
||||
pside, region, flags, qstarttime))
|
||||
log_err("out of memory: cannot store data in cache");
|
||||
}
|
||||
|
||||
@@ -743,9 +745,10 @@ 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)
|
||||
struct delegpt* dp, int supports_ipv4, int supports_ipv6)
|
||||
{
|
||||
struct delegpt_ns* ns;
|
||||
struct delegpt_addr* a;
|
||||
/* check:
|
||||
* o RD qflag is on.
|
||||
* o no addresses are provided.
|
||||
@@ -758,13 +761,24 @@ iter_dp_is_useless(struct query_info* qinfo, uint16_t qflags,
|
||||
*/
|
||||
if(!(qflags&BIT_RD))
|
||||
return 0;
|
||||
/* either available or unused targets */
|
||||
if(dp->usable_list || dp->result_list)
|
||||
return 0;
|
||||
/* either available or unused targets,
|
||||
* if they exist, the dp is not useless. */
|
||||
for(a = dp->usable_list; a; a = a->next_usable) {
|
||||
if(!addr_is_ip6(&a->addr, a->addrlen) && supports_ipv4)
|
||||
return 0;
|
||||
else if(addr_is_ip6(&a->addr, a->addrlen) && supports_ipv6)
|
||||
return 0;
|
||||
}
|
||||
for(a = dp->result_list; a; a = a->next_result) {
|
||||
if(!addr_is_ip6(&a->addr, a->addrlen) && supports_ipv4)
|
||||
return 0;
|
||||
else if(addr_is_ip6(&a->addr, a->addrlen) && supports_ipv6)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* see if query is for one of the nameservers, which is glue */
|
||||
if( (qinfo->qtype == LDNS_RR_TYPE_A ||
|
||||
qinfo->qtype == LDNS_RR_TYPE_AAAA) &&
|
||||
if( ((qinfo->qtype == LDNS_RR_TYPE_A && supports_ipv4) ||
|
||||
(qinfo->qtype == LDNS_RR_TYPE_AAAA && supports_ipv6)) &&
|
||||
dname_subdomain_c(qinfo->qname, dp->name) &&
|
||||
delegpt_find_ns(dp, qinfo->qname, qinfo->qname_len))
|
||||
return 1;
|
||||
@@ -1195,6 +1209,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,
|
||||
|
||||
+16
-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.
|
||||
@@ -132,6 +141,7 @@ struct dns_msg* dns_copy_msg(struct dns_msg* from, struct regional* regional);
|
||||
* can be prefetch-updates.
|
||||
* @param region: to copy modified (cache is better) rrs back to.
|
||||
* @param flags: with BIT_CD for dns64 AAAA translated queries.
|
||||
* @param qstarttime: time of query start.
|
||||
* return void, because we are not interested in alloc errors,
|
||||
* the iterator and validator can operate on the results in their
|
||||
* scratch space (the qstate.region) and are not dependent on the cache.
|
||||
@@ -140,7 +150,7 @@ struct dns_msg* dns_copy_msg(struct dns_msg* from, struct regional* regional);
|
||||
*/
|
||||
void iter_dns_store(struct module_env* env, struct query_info* qinf,
|
||||
struct reply_info* rep, int is_referral, time_t leeway, int pside,
|
||||
struct regional* region, uint16_t flags);
|
||||
struct regional* region, uint16_t flags, time_t qstarttime);
|
||||
|
||||
/**
|
||||
* Select randomly with n/m probability.
|
||||
@@ -175,10 +185,14 @@ void iter_mark_pside_cycle_targets(struct module_qstate* qstate,
|
||||
* @param qinfo: query name and type
|
||||
* @param qflags: query flags with RD flag
|
||||
* @param dp: delegpt to check.
|
||||
* @param supports_ipv4: if we support ipv4 for lookups to the target.
|
||||
* 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.
|
||||
* @return true if dp is useless.
|
||||
*/
|
||||
int iter_dp_is_useless(struct query_info* qinfo, uint16_t qflags,
|
||||
struct delegpt* dp);
|
||||
struct delegpt* dp, int supports_ipv4, int supports_ipv6);
|
||||
|
||||
/**
|
||||
* See if qname has DNSSEC needs. This is true if there is a trust anchor above
|
||||
|
||||
+324
-168
@@ -71,6 +71,10 @@
|
||||
|
||||
/* in msec */
|
||||
int UNKNOWN_SERVER_NICENESS = 376;
|
||||
/* in msec */
|
||||
int USEFUL_SERVER_TOP_TIMEOUT = 120000;
|
||||
/* Equals USEFUL_SERVER_TOP_TIMEOUT*4 */
|
||||
int BLACKLIST_PENALTY = (120000*4);
|
||||
|
||||
static void target_count_increase_nx(struct iter_qstate* iq, int num);
|
||||
|
||||
@@ -251,10 +255,11 @@ 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) &&
|
||||
(dpns->got6 == 2 || !ie->supports_ipv6))
|
||||
(dpns->got6 == 2 || !ie->supports_ipv6)) {
|
||||
dpns->resolved = 1; /* mark as failed */
|
||||
target_count_increase_nx(super_iq, 1);
|
||||
}
|
||||
}
|
||||
if(qstate->qinfo.qtype == LDNS_RR_TYPE_NS) {
|
||||
/* prime failed to get delegation */
|
||||
@@ -370,7 +375,7 @@ error_response_cache(struct module_qstate* qstate, int id, int rcode)
|
||||
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->query_flags, qstate->qstarttime);
|
||||
}
|
||||
return error_response(qstate, id, rcode);
|
||||
}
|
||||
@@ -591,15 +596,17 @@ 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_reply && iq->fail_reply->remote_addrlen != 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));
|
||||
addr_to_str(&iq->fail_reply->remote_addr,
|
||||
iq->fail_reply->remote_addrlen, from,
|
||||
sizeof(from));
|
||||
snprintf(frm, sizeof(frm), "from %s", from);
|
||||
errinf(qstate, frm);
|
||||
}
|
||||
@@ -678,15 +685,20 @@ is_caps_whitelisted(struct iter_env* ie, struct iter_qstate* iq)
|
||||
iq->qchase.qclass) != NULL;
|
||||
}
|
||||
|
||||
/** create target count structure for this query */
|
||||
/**
|
||||
* Create target count structure for this query. This is always explicitly
|
||||
* created for the parent query.
|
||||
*/
|
||||
static void
|
||||
target_count_create(struct iter_qstate* iq)
|
||||
{
|
||||
if(!iq->target_count) {
|
||||
iq->target_count = (int*)calloc(3, sizeof(int));
|
||||
iq->target_count = (int*)calloc(TARGET_COUNT_MAX, sizeof(int));
|
||||
/* if calloc fails we simply do not track this number */
|
||||
if(iq->target_count)
|
||||
iq->target_count[0] = 1;
|
||||
if(iq->target_count) {
|
||||
iq->target_count[TARGET_COUNT_REF] = 1;
|
||||
iq->nxns_dp = (uint8_t**)calloc(1, sizeof(uint8_t*));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -695,7 +707,7 @@ target_count_increase(struct iter_qstate* iq, int num)
|
||||
{
|
||||
target_count_create(iq);
|
||||
if(iq->target_count)
|
||||
iq->target_count[1] += num;
|
||||
iq->target_count[TARGET_COUNT_QUERIES] += num;
|
||||
iq->dp_target_count++;
|
||||
}
|
||||
|
||||
@@ -704,7 +716,7 @@ target_count_increase_nx(struct iter_qstate* iq, int num)
|
||||
{
|
||||
target_count_create(iq);
|
||||
if(iq->target_count)
|
||||
iq->target_count[2] += num;
|
||||
iq->target_count[TARGET_COUNT_NX] += num;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -799,8 +811,10 @@ generate_sub_request(uint8_t* qname, size_t qnamelen, uint16_t qtype,
|
||||
subiq->num_target_queries = 0;
|
||||
target_count_create(iq);
|
||||
subiq->target_count = iq->target_count;
|
||||
if(iq->target_count)
|
||||
iq->target_count[0] ++; /* extra reference */
|
||||
if(iq->target_count) {
|
||||
iq->target_count[TARGET_COUNT_REF] ++; /* extra reference */
|
||||
subiq->nxns_dp = iq->nxns_dp;
|
||||
}
|
||||
subiq->dp_target_count = 0;
|
||||
subiq->num_current_queries = 0;
|
||||
subiq->depth = iq->depth+1;
|
||||
@@ -1206,6 +1220,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",
|
||||
@@ -1477,7 +1500,8 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
iq->dp = dns_cache_find_delegation(qstate->env, delname,
|
||||
delnamelen, iq->qchase.qtype, iq->qchase.qclass,
|
||||
qstate->region, &iq->deleg_msg,
|
||||
*qstate->env->now+qstate->prefetch_leeway);
|
||||
*qstate->env->now+qstate->prefetch_leeway, 1,
|
||||
dpname, dpnamelen);
|
||||
else iq->dp = NULL;
|
||||
|
||||
/* If the cache has returned nothing, then we have a
|
||||
@@ -1533,36 +1557,6 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
if(!iq->ratelimit_ok && qstate->prefetch_leeway)
|
||||
iq->ratelimit_ok = 1; /* allow prefetches, this keeps
|
||||
otherwise valid data in the cache */
|
||||
if(!iq->ratelimit_ok && infra_ratelimit_exceeded(
|
||||
qstate->env->infra_cache, iq->dp->name,
|
||||
iq->dp->namelen, *qstate->env->now)) {
|
||||
/* and increment the rate, so that the rate for time
|
||||
* now will also exceed the rate, keeping cache fresh */
|
||||
(void)infra_ratelimit_inc(qstate->env->infra_cache,
|
||||
iq->dp->name, iq->dp->namelen,
|
||||
*qstate->env->now, &qstate->qinfo,
|
||||
qstate->reply);
|
||||
/* see if we are passed through with slip factor */
|
||||
if(qstate->env->cfg->ratelimit_factor != 0 &&
|
||||
ub_random_max(qstate->env->rnd,
|
||||
qstate->env->cfg->ratelimit_factor) == 1) {
|
||||
iq->ratelimit_ok = 1;
|
||||
log_nametypeclass(VERB_ALGO, "ratelimit allowed through for "
|
||||
"delegation point", iq->dp->name,
|
||||
LDNS_RR_TYPE_NS, LDNS_RR_CLASS_IN);
|
||||
} else {
|
||||
lock_basic_lock(&ie->queries_ratelimit_lock);
|
||||
ie->num_queries_ratelimited++;
|
||||
lock_basic_unlock(&ie->queries_ratelimit_lock);
|
||||
log_nametypeclass(VERB_ALGO, "ratelimit exceeded with "
|
||||
"delegation point", iq->dp->name,
|
||||
LDNS_RR_TYPE_NS, LDNS_RR_CLASS_IN);
|
||||
qstate->was_ratelimited = 1;
|
||||
errinf(qstate, "query was ratelimited");
|
||||
errinf_dname(qstate, "for zone", iq->dp->name);
|
||||
return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
|
||||
}
|
||||
}
|
||||
|
||||
/* see if this dp not useless.
|
||||
* It is useless if:
|
||||
@@ -1577,7 +1571,7 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
* same server reply) if useless-checked.
|
||||
*/
|
||||
if(iter_dp_is_useless(&qstate->qinfo, qstate->query_flags,
|
||||
iq->dp)) {
|
||||
iq->dp, ie->supports_ipv4, ie->supports_ipv6)) {
|
||||
struct delegpt* retdp = NULL;
|
||||
if(!can_have_last_resort(qstate->env, iq->dp->name, iq->dp->namelen, iq->qchase.qclass, &retdp)) {
|
||||
if(retdp) {
|
||||
@@ -1799,7 +1793,8 @@ generate_parentside_target_query(struct module_qstate* qstate,
|
||||
subiq->dp = dns_cache_find_delegation(qstate->env,
|
||||
name, namelen, qtype, qclass, subq->region,
|
||||
&subiq->deleg_msg,
|
||||
*qstate->env->now+subq->prefetch_leeway);
|
||||
*qstate->env->now+subq->prefetch_leeway,
|
||||
1, NULL, 0);
|
||||
/* if no dp, then it's from root, refetch unneeded */
|
||||
if(subiq->dp) {
|
||||
subiq->dnssec_expected = iter_indicates_dnssec(
|
||||
@@ -1861,14 +1856,32 @@ query_for_targets(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
int missing;
|
||||
int toget = 0;
|
||||
|
||||
iter_mark_cycle_targets(qstate, iq->dp);
|
||||
missing = (int)delegpt_count_missing_targets(iq->dp, NULL);
|
||||
log_assert(maxtargets != 0); /* that would not be useful */
|
||||
|
||||
/* Generate target requests. Basically, any missing targets
|
||||
* are queried for here, regardless if it is necessary to do
|
||||
* so to continue processing. */
|
||||
if(maxtargets < 0 || maxtargets > missing)
|
||||
toget = missing;
|
||||
else toget = maxtargets;
|
||||
if(toget == 0) {
|
||||
*num = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* now that we are sure that a target query is going to be made,
|
||||
* check the limits. */
|
||||
if(iq->depth == ie->max_dependency_depth)
|
||||
return 0;
|
||||
if(iq->depth > 0 && iq->target_count &&
|
||||
iq->target_count[1] > MAX_TARGET_COUNT) {
|
||||
iq->target_count[TARGET_COUNT_QUERIES] > MAX_TARGET_COUNT) {
|
||||
char s[LDNS_MAX_DOMAINLEN+1];
|
||||
dname_str(qstate->qinfo.qname, s);
|
||||
verbose(VERB_QUERY, "request %s has exceeded the maximum "
|
||||
"number of glue fetches %d", s, iq->target_count[1]);
|
||||
"number of glue fetches %d", s,
|
||||
iq->target_count[TARGET_COUNT_QUERIES]);
|
||||
return 0;
|
||||
}
|
||||
if(iq->dp_target_count > MAX_DP_TARGET_COUNT) {
|
||||
@@ -1880,20 +1893,6 @@ query_for_targets(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
return 0;
|
||||
}
|
||||
|
||||
iter_mark_cycle_targets(qstate, iq->dp);
|
||||
missing = (int)delegpt_count_missing_targets(iq->dp);
|
||||
log_assert(maxtargets != 0); /* that would not be useful */
|
||||
|
||||
/* Generate target requests. Basically, any missing targets
|
||||
* are queried for here, regardless if it is necessary to do
|
||||
* so to continue processing. */
|
||||
if(maxtargets < 0 || maxtargets > missing)
|
||||
toget = missing;
|
||||
else toget = maxtargets;
|
||||
if(toget == 0) {
|
||||
*num = 0;
|
||||
return 1;
|
||||
}
|
||||
/* select 'toget' items from the total of 'missing' items */
|
||||
log_assert(toget <= missing);
|
||||
|
||||
@@ -1910,7 +1909,9 @@ query_for_targets(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
continue;
|
||||
}
|
||||
|
||||
if(ie->supports_ipv6 && !ns->got6) {
|
||||
if(ie->supports_ipv6 &&
|
||||
((ns->lame && !ns->done_pside6) ||
|
||||
(!ns->lame && !ns->got6))) {
|
||||
/* Send the AAAA request. */
|
||||
if(!generate_target_query(qstate, iq, id,
|
||||
ns->name, ns->namelen,
|
||||
@@ -1921,9 +1922,19 @@ 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 && !ns->got4) {
|
||||
if(ie->supports_ipv4 &&
|
||||
((ns->lame && !ns->done_pside4) ||
|
||||
(!ns->lame && !ns->got4))) {
|
||||
if(!generate_target_query(qstate, iq, id,
|
||||
ns->name, ns->namelen,
|
||||
LDNS_RR_TYPE_A, iq->qchase.qclass)) {
|
||||
@@ -1933,6 +1944,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. */
|
||||
@@ -1988,12 +2002,13 @@ processLastResort(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
iq->chase_flags &= ~BIT_RD; /* go to authorities */
|
||||
for(ns = p->nslist; ns; ns=ns->next) {
|
||||
(void)delegpt_add_ns(iq->dp, qstate->region,
|
||||
ns->name, ns->lame);
|
||||
ns->name, ns->lame, ns->tls_auth_name,
|
||||
ns->port);
|
||||
}
|
||||
for(a = p->target_list; a; a=a->next_target) {
|
||||
(void)delegpt_add_addr(iq->dp, qstate->region,
|
||||
&a->addr, a->addrlen, a->bogus,
|
||||
a->lame, a->tls_auth_name, NULL);
|
||||
a->lame, a->tls_auth_name, -1, NULL);
|
||||
}
|
||||
}
|
||||
iq->dp->has_parent_side_NS = 1;
|
||||
@@ -2032,7 +2047,7 @@ processLastResort(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
return next_state(iq, QUERYTARGETS_STATE);
|
||||
}
|
||||
/* query for an extra name added by the parent-NS record */
|
||||
if(delegpt_count_missing_targets(iq->dp) > 0) {
|
||||
if(delegpt_count_missing_targets(iq->dp, NULL) > 0) {
|
||||
int qs = 0;
|
||||
verbose(VERB_ALGO, "try parent-side target name");
|
||||
if(!query_for_targets(qstate, iq, ie, id, 1, &qs)) {
|
||||
@@ -2053,11 +2068,12 @@ processLastResort(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
return error_response_cache(qstate, id, LDNS_RCODE_SERVFAIL);
|
||||
}
|
||||
if(iq->depth > 0 && iq->target_count &&
|
||||
iq->target_count[1] > MAX_TARGET_COUNT) {
|
||||
iq->target_count[TARGET_COUNT_QUERIES] > MAX_TARGET_COUNT) {
|
||||
char s[LDNS_MAX_DOMAINLEN+1];
|
||||
dname_str(qstate->qinfo.qname, s);
|
||||
verbose(VERB_QUERY, "request %s has exceeded the maximum "
|
||||
"number of glue fetches %d", s, iq->target_count[1]);
|
||||
"number of glue fetches %d", s,
|
||||
iq->target_count[TARGET_COUNT_QUERIES]);
|
||||
errinf(qstate, "exceeded the maximum number of glue fetches");
|
||||
return error_response_cache(qstate, id, LDNS_RCODE_SERVFAIL);
|
||||
}
|
||||
@@ -2091,6 +2107,15 @@ 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) {
|
||||
/* Send the A request. */
|
||||
@@ -2184,6 +2209,32 @@ processDSNSFind(struct module_qstate* qstate, struct iter_qstate* iq, int id)
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if we wait responses for sent queries and update the iterator's
|
||||
* external state.
|
||||
*/
|
||||
static void
|
||||
check_waiting_queries(struct iter_qstate* iq, struct module_qstate* qstate,
|
||||
int id)
|
||||
{
|
||||
if(iq->num_target_queries>0 && iq->num_current_queries>0) {
|
||||
verbose(VERB_ALGO, "waiting for %d targets to "
|
||||
"resolve or %d outstanding queries to "
|
||||
"respond", iq->num_target_queries,
|
||||
iq->num_current_queries);
|
||||
qstate->ext_state[id] = module_wait_reply;
|
||||
} else if(iq->num_target_queries>0) {
|
||||
verbose(VERB_ALGO, "waiting for %d targets to "
|
||||
"resolve", iq->num_target_queries);
|
||||
qstate->ext_state[id] = module_wait_subquery;
|
||||
} else {
|
||||
verbose(VERB_ALGO, "waiting for %d "
|
||||
"outstanding queries to respond",
|
||||
iq->num_current_queries);
|
||||
qstate->ext_state[id] = module_wait_reply;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This is the request event state where the request will be sent to one of
|
||||
@@ -2211,9 +2262,12 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
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,
|
||||
/* NOTE: a request will encounter this state for each target it
|
||||
* needs to send a query to. That is, at least one per referral,
|
||||
* more if some targets timeout or return throwaway answers. */
|
||||
|
||||
log_query_info(VERB_QUERY, "processQueryTargets:", &qstate->qinfo);
|
||||
@@ -2222,7 +2276,6 @@ 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);
|
||||
@@ -2235,12 +2288,91 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
errinf(qstate, "exceeded the maximum number of sends");
|
||||
return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
|
||||
}
|
||||
if(iq->target_count && iq->target_count[2] > MAX_TARGET_NX) {
|
||||
verbose(VERB_QUERY, "request has exceeded the maximum "
|
||||
" number of nxdomain nameserver lookups with %d",
|
||||
iq->target_count[2]);
|
||||
errinf(qstate, "exceeded the maximum nameserver nxdomains");
|
||||
return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
|
||||
|
||||
/* Check if we reached MAX_TARGET_NX limit without a fallback activation. */
|
||||
if(iq->target_count && !*iq->nxns_dp &&
|
||||
iq->target_count[TARGET_COUNT_NX] > MAX_TARGET_NX) {
|
||||
struct delegpt_ns* ns;
|
||||
/* If we can wait for resolution, do so. */
|
||||
if(iq->num_target_queries>0 || iq->num_current_queries>0) {
|
||||
check_waiting_queries(iq, qstate, id);
|
||||
return 0;
|
||||
}
|
||||
verbose(VERB_ALGO, "request has exceeded the maximum "
|
||||
"number of nxdomain nameserver lookups (%d) with %d",
|
||||
MAX_TARGET_NX, iq->target_count[TARGET_COUNT_NX]);
|
||||
/* Check for dp because we require one below */
|
||||
if(!iq->dp) {
|
||||
verbose(VERB_QUERY, "Failed to get a delegation, "
|
||||
"giving up");
|
||||
errinf(qstate, "failed to get a delegation (eg. prime "
|
||||
"failure)");
|
||||
return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
|
||||
}
|
||||
/* We reached the limit but we already have parent side
|
||||
* information; stop resolution */
|
||||
if(iq->dp->has_parent_side_NS) {
|
||||
verbose(VERB_ALGO, "parent-side information is "
|
||||
"already present for the delegation point, no "
|
||||
"fallback possible");
|
||||
errinf(qstate, "exceeded the maximum nameserver nxdomains");
|
||||
return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
|
||||
}
|
||||
verbose(VERB_ALGO, "initiating parent-side fallback for "
|
||||
"nxdomain nameserver lookups");
|
||||
/* Mark all the current NSes as resolved to allow for parent
|
||||
* fallback */
|
||||
for(ns=iq->dp->nslist; ns; ns=ns->next) {
|
||||
ns->resolved = 1;
|
||||
}
|
||||
/* Note the delegation point that triggered the NXNS fallback;
|
||||
* no reason for shared queries to keep trying there.
|
||||
* This also marks the fallback activation. */
|
||||
*iq->nxns_dp = malloc(iq->dp->namelen);
|
||||
if(!*iq->nxns_dp) {
|
||||
verbose(VERB_ALGO, "out of memory while initiating "
|
||||
"fallback");
|
||||
errinf(qstate, "exceeded the maximum nameserver "
|
||||
"nxdomains (malloc)");
|
||||
return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
|
||||
}
|
||||
memcpy(*iq->nxns_dp, iq->dp->name, iq->dp->namelen);
|
||||
} else if(iq->target_count && *iq->nxns_dp) {
|
||||
/* Handle the NXNS fallback case. */
|
||||
/* If we can wait for resolution, do so. */
|
||||
if(iq->num_target_queries>0 || iq->num_current_queries>0) {
|
||||
check_waiting_queries(iq, qstate, id);
|
||||
return 0;
|
||||
}
|
||||
/* Check for dp because we require one below */
|
||||
if(!iq->dp) {
|
||||
verbose(VERB_QUERY, "Failed to get a delegation, "
|
||||
"giving up");
|
||||
errinf(qstate, "failed to get a delegation (eg. prime "
|
||||
"failure)");
|
||||
return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
|
||||
}
|
||||
|
||||
if(iq->target_count[TARGET_COUNT_NX] > MAX_TARGET_NX_FALLBACK) {
|
||||
verbose(VERB_ALGO, "request has exceeded the maximum "
|
||||
"number of fallback nxdomain nameserver "
|
||||
"lookups (%d) with %d", MAX_TARGET_NX_FALLBACK,
|
||||
iq->target_count[TARGET_COUNT_NX]);
|
||||
errinf(qstate, "exceeded the maximum nameserver nxdomains");
|
||||
return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
|
||||
}
|
||||
|
||||
if(!iq->dp->has_parent_side_NS) {
|
||||
struct delegpt_ns* ns;
|
||||
if(!dname_canonical_compare(*iq->nxns_dp, iq->dp->name)) {
|
||||
verbose(VERB_ALGO, "this delegation point "
|
||||
"initiated the fallback, marking the "
|
||||
"nslist as resolved");
|
||||
for(ns=iq->dp->nslist; ns; ns=ns->next) {
|
||||
ns->resolved = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Make sure we have a delegation point, otherwise priming failed
|
||||
@@ -2458,8 +2590,13 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
* that servfail is cached, which is not good as opportunism goes. */
|
||||
if(iq->depth < ie->max_dependency_depth
|
||||
&& iq->num_target_queries == 0
|
||||
&& (!iq->target_count || iq->target_count[2]==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];
|
||||
}
|
||||
|
||||
@@ -2534,12 +2671,12 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
struct dns_msg* forged_response = rpz_callback_from_iterator_module(qstate, iq);
|
||||
if(forged_response != NULL) {
|
||||
qstate->ext_state[id] = module_finished;
|
||||
qstate->return_rcode = FLAGS_GET_RCODE(forged_response->rep->flags);
|
||||
qstate->return_rcode = LDNS_RCODE_NOERROR;
|
||||
qstate->return_msg = forged_response;
|
||||
iq->response = forged_response;
|
||||
next_state(iq, FINISHED_STATE);
|
||||
if(!iter_prepend(iq, qstate->return_msg, qstate->region)) {
|
||||
log_err("rpz, prepend rrsets: out of memory");
|
||||
log_err("rpz: prepend rrsets: out of memory");
|
||||
return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
|
||||
}
|
||||
return 0;
|
||||
@@ -2547,9 +2684,9 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
}
|
||||
|
||||
/* Select the next usable target, filtering out unsuitable targets. */
|
||||
target = iter_server_selection(ie, qstate->env, iq->dp,
|
||||
target = iter_server_selection(ie, qstate->env, iq->dp,
|
||||
iq->dp->name, iq->dp->namelen, iq->qchase.qtype,
|
||||
&iq->dnssec_lame_query, &iq->chase_to_rd,
|
||||
&iq->dnssec_lame_query, &iq->chase_to_rd,
|
||||
iq->num_target_queries, qstate->blacklist,
|
||||
qstate->prefetch_leeway);
|
||||
|
||||
@@ -2568,7 +2705,7 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
/* If there is nothing to wait for, then we need
|
||||
* to distinguish between generating (a) new target
|
||||
* query, or failing. */
|
||||
if(delegpt_count_missing_targets(iq->dp) > 0) {
|
||||
if(delegpt_count_missing_targets(iq->dp, NULL) > 0) {
|
||||
int qs = 0;
|
||||
verbose(VERB_ALGO, "querying for next "
|
||||
"missing target");
|
||||
@@ -2580,7 +2717,7 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
LDNS_RCODE_SERVFAIL);
|
||||
}
|
||||
if(qs == 0 &&
|
||||
delegpt_count_missing_targets(iq->dp) == 0){
|
||||
delegpt_count_missing_targets(iq->dp, NULL) == 0){
|
||||
/* it looked like there were missing
|
||||
* targets, but they did not turn up.
|
||||
* Try the bad choices again (if any),
|
||||
@@ -2619,23 +2756,8 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
|
||||
/* otherwise, we have no current targets, so submerge
|
||||
* until one of the target or direct queries return. */
|
||||
if(iq->num_target_queries>0 && iq->num_current_queries>0) {
|
||||
verbose(VERB_ALGO, "no current targets -- waiting "
|
||||
"for %d targets to resolve or %d outstanding"
|
||||
" queries to respond", iq->num_target_queries,
|
||||
iq->num_current_queries);
|
||||
qstate->ext_state[id] = module_wait_reply;
|
||||
} else if(iq->num_target_queries>0) {
|
||||
verbose(VERB_ALGO, "no current targets -- waiting "
|
||||
"for %d targets to resolve.",
|
||||
iq->num_target_queries);
|
||||
qstate->ext_state[id] = module_wait_subquery;
|
||||
} else {
|
||||
verbose(VERB_ALGO, "no current targets -- waiting "
|
||||
"for %d outstanding queries to respond.",
|
||||
iq->num_current_queries);
|
||||
qstate->ext_state[id] = module_wait_reply;
|
||||
}
|
||||
verbose(VERB_ALGO, "no current targets");
|
||||
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) {
|
||||
@@ -2646,22 +2768,40 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* if not forwarding, check ratelimits per delegationpoint name */
|
||||
if(!(iq->chase_flags & BIT_RD) && !iq->ratelimit_ok) {
|
||||
if(!infra_ratelimit_inc(qstate->env->infra_cache, iq->dp->name,
|
||||
iq->dp->namelen, *qstate->env->now, &qstate->qinfo,
|
||||
qstate->reply)) {
|
||||
lock_basic_lock(&ie->queries_ratelimit_lock);
|
||||
ie->num_queries_ratelimited++;
|
||||
lock_basic_unlock(&ie->queries_ratelimit_lock);
|
||||
verbose(VERB_ALGO, "query exceeded ratelimits");
|
||||
qstate->was_ratelimited = 1;
|
||||
errinf_dname(qstate, "exceeded ratelimit for zone",
|
||||
iq->dp->name);
|
||||
return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
|
||||
/* 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);
|
||||
@@ -2673,25 +2813,32 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
}
|
||||
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),
|
||||
iq->chase_flags | (iq->chase_to_rd?BIT_RD:0),
|
||||
/* unset CD if to forwarder(RD set) and not dnssec retry
|
||||
* (blacklist nonempty) and no trust-anchors are configured
|
||||
* above the qname or on the first attempt when dnssec is on */
|
||||
EDNS_DO| ((iq->chase_to_rd||(iq->chase_flags&BIT_RD)!=0)&&
|
||||
!qstate->blacklist&&(!iter_qname_indicates_dnssec(qstate->env,
|
||||
&iq->qinfo_out)||target->attempts==1)?0:BIT_CD),
|
||||
&iq->qinfo_out)||target->attempts==1)?0:BIT_CD),
|
||||
iq->dnssec_expected, iq->caps_fallback || is_caps_whitelisted(
|
||||
ie, iq), &target->addr, target->addrlen,
|
||||
ie, iq), sq_check_ratelimit, &target->addr, target->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),
|
||||
target->tls_auth_name, qstate);
|
||||
target->tls_auth_name, qstate, &sq_was_ratelimited);
|
||||
if(!outq) {
|
||||
if(sq_was_ratelimited) {
|
||||
lock_basic_lock(&ie->queries_ratelimit_lock);
|
||||
ie->num_queries_ratelimited++;
|
||||
lock_basic_unlock(&ie->queries_ratelimit_lock);
|
||||
verbose(VERB_ALGO, "query exceeded ratelimits");
|
||||
qstate->was_ratelimited = 1;
|
||||
errinf_dname(qstate, "exceeded ratelimit for zone",
|
||||
iq->dp->name);
|
||||
return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
|
||||
}
|
||||
log_addr(VERB_QUERY, "error sending query to auth server",
|
||||
&target->addr, target->addrlen);
|
||||
if(!(iq->chase_flags & BIT_RD) && !iq->ratelimit_ok)
|
||||
infra_ratelimit_dec(qstate->env->infra_cache, iq->dp->name,
|
||||
iq->dp->namelen, *qstate->env->now);
|
||||
if(qstate->env->cfg->qname_minimisation)
|
||||
iq->minimisation_state = SKIP_MINIMISE_STATE;
|
||||
return next_state(iq, QUERYTARGETS_STATE);
|
||||
@@ -2759,6 +2906,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
|
||||
@@ -2782,8 +2931,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,
|
||||
@@ -2865,9 +3014,12 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
}
|
||||
if(!qstate->no_cache_store)
|
||||
iter_dns_store(qstate->env, &iq->response->qinfo,
|
||||
iq->response->rep, 0, qstate->prefetch_leeway,
|
||||
iq->response->rep,
|
||||
iq->qchase.qtype != iq->response->qinfo.qtype,
|
||||
qstate->prefetch_leeway,
|
||||
iq->dp&&iq->dp->has_parent_side_NS,
|
||||
qstate->region, qstate->query_flags);
|
||||
qstate->region, qstate->query_flags,
|
||||
qstate->qstarttime);
|
||||
/* close down outstanding requests to be discarded */
|
||||
outbound_list_clear(&iq->outlist);
|
||||
iq->num_current_queries = 0;
|
||||
@@ -2876,9 +3028,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) !=
|
||||
@@ -2935,14 +3087,6 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
* delegation point, and back to the QUERYTARGETS_STATE. */
|
||||
verbose(VERB_DETAIL, "query response was REFERRAL");
|
||||
|
||||
if(!(iq->chase_flags & BIT_RD) && !iq->ratelimit_ok) {
|
||||
/* we have a referral, no ratelimit, we can send
|
||||
* our queries to the given name */
|
||||
infra_ratelimit_dec(qstate->env->infra_cache,
|
||||
iq->dp->name, iq->dp->namelen,
|
||||
*qstate->env->now);
|
||||
}
|
||||
|
||||
/* if hardened, only store referral if we asked for it */
|
||||
if(!qstate->no_cache_store &&
|
||||
(!qstate->env->cfg->harden_referral_path ||
|
||||
@@ -2964,7 +3108,8 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
/* Store the referral under the current query */
|
||||
/* no prefetch-leeway, since its not the answer */
|
||||
iter_dns_store(qstate->env, &iq->response->qinfo,
|
||||
iq->response->rep, 1, 0, 0, NULL, 0);
|
||||
iq->response->rep, 1, 0, 0, NULL, 0,
|
||||
qstate->qstarttime);
|
||||
if(iq->store_parent_NS)
|
||||
iter_store_parentside_NS(qstate->env,
|
||||
iq->response->rep);
|
||||
@@ -3078,7 +3223,7 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
iter_dns_store(qstate->env, &iq->response->qinfo,
|
||||
iq->response->rep, 1, qstate->prefetch_leeway,
|
||||
iq->dp&&iq->dp->has_parent_side_NS, NULL,
|
||||
qstate->query_flags);
|
||||
qstate->query_flags, qstate->qstarttime);
|
||||
/* set the current request's qname to the new value. */
|
||||
iq->qchase.qname = sname;
|
||||
iq->qchase.qname_len = snamelen;
|
||||
@@ -3103,12 +3248,12 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
}
|
||||
if(forged_response != NULL) {
|
||||
qstate->ext_state[id] = module_finished;
|
||||
qstate->return_rcode = FLAGS_GET_RCODE(forged_response->rep->flags);
|
||||
qstate->return_rcode = LDNS_RCODE_NOERROR;
|
||||
qstate->return_msg = forged_response;
|
||||
iq->response = forged_response;
|
||||
next_state(iq, FINISHED_STATE);
|
||||
if(!iter_prepend(iq, qstate->return_msg, qstate->region)) {
|
||||
log_err("rpz after cname, prepend rrsets: out of memory");
|
||||
log_err("rpz: after cname, prepend rrsets: out of memory");
|
||||
return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
|
||||
}
|
||||
qstate->return_msg->qinfo = qstate->qinfo;
|
||||
@@ -3140,9 +3285,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);
|
||||
@@ -3156,9 +3301,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");
|
||||
@@ -3175,8 +3321,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");
|
||||
}
|
||||
@@ -3384,21 +3531,22 @@ processTargetResponse(struct module_qstate* qstate, int id,
|
||||
log_err("out of memory adding pside glue");
|
||||
}
|
||||
|
||||
/* This response is relevant to the current query, so we
|
||||
* add (attempt to add, anyway) this target(s) and reactivate
|
||||
* the original event.
|
||||
* NOTE: we could only look for the AnswerRRset if the
|
||||
/* This response is relevant to the current query, so we
|
||||
* add (attempt to add, anyway) this target(s) and reactivate
|
||||
* the original event.
|
||||
* NOTE: we could only look for the AnswerRRset if the
|
||||
* response type was ANSWER. */
|
||||
rrset = reply_find_answer_rrset(&iq->qchase, qstate->return_msg->rep);
|
||||
if(rrset) {
|
||||
int additions = 0;
|
||||
/* if CNAMEs have been followed - add new NS to delegpt. */
|
||||
/* BTW. RFC 1918 says NS should not have got CNAMEs. Robust. */
|
||||
if(!delegpt_find_ns(foriq->dp, rrset->rk.dname,
|
||||
if(!delegpt_find_ns(foriq->dp, rrset->rk.dname,
|
||||
rrset->rk.dname_len)) {
|
||||
/* if dpns->lame then set newcname ns lame too */
|
||||
if(!delegpt_add_ns(foriq->dp, forq->region,
|
||||
rrset->rk.dname, dpns->lame))
|
||||
if(!delegpt_add_ns(foriq->dp, forq->region,
|
||||
rrset->rk.dname, dpns->lame, dpns->tls_auth_name,
|
||||
dpns->port))
|
||||
log_err("out of memory adding cnamed-ns");
|
||||
}
|
||||
/* if dpns->lame then set the address(es) lame too */
|
||||
@@ -3416,10 +3564,14 @@ 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))
|
||||
target_count_increase_nx(foriq, 1);
|
||||
(dpns->got6 == 2 || !ie->supports_ipv6)) {
|
||||
dpns->resolved = 1; /* fail the target */
|
||||
/* do not count cached answers */
|
||||
if(qstate->reply_origin && qstate->reply_origin->len != 0) {
|
||||
target_count_increase_nx(foriq, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3680,7 +3832,8 @@ processFinished(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
iter_dns_store(qstate->env, &qstate->qinfo,
|
||||
iq->response->rep, 0, qstate->prefetch_leeway,
|
||||
iq->dp&&iq->dp->has_parent_side_NS,
|
||||
qstate->region, qstate->query_flags);
|
||||
qstate->region, qstate->query_flags,
|
||||
qstate->qstarttime);
|
||||
}
|
||||
}
|
||||
qstate->return_rcode = LDNS_RCODE_NOERROR;
|
||||
@@ -3899,8 +4052,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);
|
||||
@@ -4037,8 +4190,11 @@ iter_clear(struct module_qstate* qstate, int id)
|
||||
iq = (struct iter_qstate*)qstate->minfo[id];
|
||||
if(iq) {
|
||||
outbound_list_clear(&iq->outlist);
|
||||
if(iq->target_count && --iq->target_count[0] == 0)
|
||||
if(iq->target_count && --iq->target_count[TARGET_COUNT_REF] == 0) {
|
||||
free(iq->target_count);
|
||||
if(*iq->nxns_dp) free(*iq->nxns_dp);
|
||||
free(iq->nxns_dp);
|
||||
}
|
||||
iq->num_current_queries = 0;
|
||||
}
|
||||
qstate->minfo[id] = NULL;
|
||||
|
||||
+38
-12
@@ -60,11 +60,15 @@ struct rbtree_type;
|
||||
/** max number of nxdomains allowed for target lookups for a query and
|
||||
* its subqueries */
|
||||
#define MAX_TARGET_NX 5
|
||||
/** 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 */
|
||||
/** max number of queries-sent-out. Make sure large NS set does not loop.
|
||||
* Resets on query restarts (e.g., CNAMES) and referrals. */
|
||||
#define MAX_SENT_COUNT 32
|
||||
/** max number of queries for which to perform dnsseclameness detection,
|
||||
* (rrsigs missing detection) after that, just pick up that response */
|
||||
@@ -80,7 +84,7 @@ struct rbtree_type;
|
||||
/**
|
||||
* number of labels from QNAME that are always send individually when using
|
||||
* QNAME minimisation, even when the number of labels of the QNAME is bigger
|
||||
* tham MAX_MINIMISE_COUNT */
|
||||
* than MAX_MINIMISE_COUNT */
|
||||
#define MINIMISE_ONE_LAB 4
|
||||
#define MINIMISE_MULTIPLE_LABS (MAX_MINIMISE_COUNT - MINIMISE_ONE_LAB)
|
||||
/** at what query-sent-count to stop target fetch policy */
|
||||
@@ -91,15 +95,17 @@ struct rbtree_type;
|
||||
extern int UNKNOWN_SERVER_NICENESS;
|
||||
/** maximum timeout before a host is deemed unsuitable, in msec.
|
||||
* After host_ttl this will be timed out and the host will be tried again.
|
||||
* Equals RTT_MAX_TIMEOUT
|
||||
*/
|
||||
#define USEFUL_SERVER_TOP_TIMEOUT 120000
|
||||
* Equals RTT_MAX_TIMEOUT, and thus when RTT_MAX_TIMEOUT is overwritten by
|
||||
* config infra_cache_max_rtt, it will be overwritten as well. */
|
||||
extern int USEFUL_SERVER_TOP_TIMEOUT;
|
||||
/** penalty to validation failed blacklisted IPs
|
||||
* Equals USEFUL_SERVER_TOP_TIMEOUT*4, and thus when RTT_MAX_TIMEOUT is
|
||||
* overwritten by config infra_cache_max_rtt, it will be overwritten as well. */
|
||||
extern int BLACKLIST_PENALTY;
|
||||
/** RTT band, within this amount from the best, servers are chosen randomly.
|
||||
* Chosen so that the UNKNOWN_SERVER_NICENESS falls within the band of a
|
||||
* fast server, this causes server exploration as a side benefit. msec. */
|
||||
#define RTT_BAND 400
|
||||
/** Start value for blacklisting a host, 2*USEFUL_SERVER_TOP_TIMEOUT in sec */
|
||||
#define INFRA_BACKOFF_INITIAL 240
|
||||
|
||||
/**
|
||||
* Global state for the iterator.
|
||||
@@ -217,6 +223,21 @@ enum iter_state {
|
||||
FINISHED_STATE
|
||||
};
|
||||
|
||||
/**
|
||||
* Shared counters for queries.
|
||||
*/
|
||||
enum target_count_variables {
|
||||
/** Reference count for the shared iter_qstate->target_count. */
|
||||
TARGET_COUNT_REF = 0,
|
||||
/** Number of target queries spawned for the query and subqueries. */
|
||||
TARGET_COUNT_QUERIES,
|
||||
/** Number of nxdomain responses encountered. */
|
||||
TARGET_COUNT_NX,
|
||||
|
||||
/** This should stay last here, it is used for the allocation */
|
||||
TARGET_COUNT_MAX,
|
||||
};
|
||||
|
||||
/**
|
||||
* Per query state for the iterator module.
|
||||
*/
|
||||
@@ -304,21 +325,26 @@ 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 */
|
||||
int sent_count;
|
||||
|
||||
/** number of target queries spawned in [1], for this query and its
|
||||
* subqueries, the malloced-array is shared, [0] refcount.
|
||||
* in [2] the number of nxdomains is counted. */
|
||||
/** malloced-array shared with this query and its subqueries. It keeps
|
||||
* track of the defined enum target_count_variables counters. */
|
||||
int* target_count;
|
||||
|
||||
/** number of target lookups per delegation point. Reset to 0 after
|
||||
* receiving referral answer. Not shared with subqueries. */
|
||||
int dp_target_count;
|
||||
|
||||
/** Delegation point that triggered the NXNS fallback; shared with
|
||||
* this query and its subqueries, count-referenced by the reference
|
||||
* counter in target_count.
|
||||
* This also marks the fallback activation. */
|
||||
uint8_t** nxns_dp;
|
||||
|
||||
/** if true, already tested for ratelimiting and passed the test */
|
||||
int ratelimit_ok;
|
||||
|
||||
@@ -379,7 +405,7 @@ struct iter_qstate {
|
||||
/** list of pending queries to authoritative servers. */
|
||||
struct outbound_list outlist;
|
||||
|
||||
/** QNAME minimisation state, RFC7816 */
|
||||
/** QNAME minimisation state, RFC9156 */
|
||||
enum minimisation_state minimisation_state;
|
||||
|
||||
/** State for capsfail: QNAME minimisation state for comparisons. */
|
||||
|
||||
+36
-1
@@ -53,6 +53,7 @@
|
||||
#include "util/storage/slabhash.h"
|
||||
#include "util/edns.h"
|
||||
#include "sldns/sbuffer.h"
|
||||
#include "sldns/wire2str.h"
|
||||
|
||||
int
|
||||
context_finalize(struct ub_ctx* ctx)
|
||||
@@ -144,9 +145,17 @@ find_id(struct ub_ctx* ctx, int* id)
|
||||
|
||||
struct ctx_query*
|
||||
context_new(struct ub_ctx* ctx, const char* name, int rrtype, int rrclass,
|
||||
ub_callback_type cb, ub_event_callback_type cb_event, void* cbarg)
|
||||
ub_callback_type cb, ub_event_callback_type cb_event, void* cbarg,
|
||||
const uint8_t* qbuf, size_t qbuf_len)
|
||||
{
|
||||
struct ctx_query* q = (struct ctx_query*)calloc(1, sizeof(*q));
|
||||
char qname_str_buf[1024];
|
||||
char *qname_str = qname_str_buf;
|
||||
size_t qname_str_len = sizeof(qname_str_buf);
|
||||
uint8_t *qname;
|
||||
size_t qname_len;
|
||||
int comprloop;
|
||||
|
||||
if(!q) return NULL;
|
||||
lock_basic_lock(&ctx->cfglock);
|
||||
if(!find_id(ctx, &q->querynum)) {
|
||||
@@ -165,6 +174,32 @@ context_new(struct ub_ctx* ctx, const char* name, int rrtype, int rrclass,
|
||||
free(q);
|
||||
return NULL;
|
||||
}
|
||||
if(!name && qbuf) {
|
||||
if(qbuf_len < 12) {
|
||||
free(q->res);
|
||||
free(q);
|
||||
return NULL;
|
||||
}
|
||||
qname = (uint8_t* )qbuf + 12;
|
||||
qname_len = qbuf_len - 12;
|
||||
comprloop = 0;
|
||||
|
||||
/* get query name from the input buffer */
|
||||
sldns_wire2str_dname_scan(
|
||||
&qname, &qname_len,
|
||||
&qname_str, &qname_str_len,
|
||||
(uint8_t *)qbuf, qbuf_len,
|
||||
&comprloop);
|
||||
*qname_str = 0;
|
||||
name = qname_str_buf;
|
||||
if (qname_len < 4) {
|
||||
free(q->res);
|
||||
free(q);
|
||||
return NULL;
|
||||
}
|
||||
rrtype = sldns_read_uint16(qname);
|
||||
rrclass = sldns_read_uint16(qname + 2);
|
||||
}
|
||||
q->res->qname = strdup(name);
|
||||
if(!q->res->qname) {
|
||||
free(q->res);
|
||||
|
||||
@@ -171,6 +171,11 @@ struct ctx_query {
|
||||
/** store libworker that is handling this query */
|
||||
struct libworker* w;
|
||||
|
||||
/** raw query packet */
|
||||
const uint8_t *qbuf;
|
||||
/** length of raw query packet */
|
||||
size_t qbuf_len;
|
||||
|
||||
/** result structure, also contains original query, type, class.
|
||||
* malloced ptr ready to hand to the client. */
|
||||
struct ub_result* res;
|
||||
@@ -224,7 +229,7 @@ void context_query_delete(struct ctx_query* q);
|
||||
*/
|
||||
struct ctx_query* context_new(struct ub_ctx* ctx, const char* name, int rrtype,
|
||||
int rrclass, ub_callback_type cb, ub_event_callback_type cb_event,
|
||||
void* cbarg);
|
||||
void* cbarg, const uint8_t* qbuf, size_t qbuf_len);
|
||||
|
||||
/**
|
||||
* Get a new alloc. Creates a new one or uses a cached one.
|
||||
|
||||
+118
-5
@@ -714,7 +714,8 @@ ub_resolve(struct ub_ctx* ctx, const char* name, int rrtype,
|
||||
}
|
||||
/* create new ctx_query and attempt to add to the list */
|
||||
lock_basic_unlock(&ctx->cfglock);
|
||||
q = context_new(ctx, name, rrtype, rrclass, NULL, NULL, NULL);
|
||||
q = context_new(ctx, name, rrtype, rrclass,
|
||||
NULL, NULL, NULL, NULL, 0);
|
||||
if(!q)
|
||||
return UB_NOMEM;
|
||||
/* become a resolver thread for a bit */
|
||||
@@ -771,7 +772,8 @@ ub_resolve_event(struct ub_ctx* ctx, const char* name, int rrtype,
|
||||
ub_comm_base_now(ctx->event_worker->base);
|
||||
|
||||
/* create new ctx_query and attempt to add to the list */
|
||||
q = context_new(ctx, name, rrtype, rrclass, NULL, callback, mydata);
|
||||
q = context_new(ctx, name, rrtype, rrclass,
|
||||
NULL, callback, mydata, NULL, 0);
|
||||
if(!q)
|
||||
return UB_NOMEM;
|
||||
|
||||
@@ -816,7 +818,8 @@ ub_resolve_async(struct ub_ctx* ctx, const char* name, int rrtype,
|
||||
}
|
||||
|
||||
/* create new ctx_query and attempt to add to the list */
|
||||
q = context_new(ctx, name, rrtype, rrclass, callback, NULL, mydata);
|
||||
q = context_new(ctx, name, rrtype, rrclass,
|
||||
callback, NULL, mydata, NULL, 0);
|
||||
if(!q)
|
||||
return UB_NOMEM;
|
||||
|
||||
@@ -845,6 +848,116 @@ ub_resolve_async(struct ub_ctx* ctx, const char* name, int rrtype,
|
||||
return UB_NOERROR;
|
||||
}
|
||||
|
||||
int
|
||||
ub_send(struct ub_ctx* ctx, const char* packet, int length,
|
||||
struct ub_result** result)
|
||||
{
|
||||
struct ctx_query* q;
|
||||
int r;
|
||||
*result = NULL;
|
||||
|
||||
lock_basic_lock(&ctx->cfglock);
|
||||
if(!ctx->finalized) {
|
||||
r = context_finalize(ctx);
|
||||
if(r) {
|
||||
lock_basic_unlock(&ctx->cfglock);
|
||||
return r;
|
||||
}
|
||||
}
|
||||
/* create new ctx_query and attempt to add to the list */
|
||||
lock_basic_unlock(&ctx->cfglock);
|
||||
q = context_new(ctx, NULL, 0, 0,
|
||||
NULL, NULL, NULL, (const uint8_t *)packet, length);
|
||||
if(!q)
|
||||
return UB_NOMEM;
|
||||
/* become a resolver thread for a bit */
|
||||
|
||||
r = libworker_fg(ctx, q);
|
||||
if(r) {
|
||||
lock_basic_lock(&ctx->cfglock);
|
||||
(void)rbtree_delete(&ctx->queries, q->node.key);
|
||||
context_query_delete(q);
|
||||
lock_basic_unlock(&ctx->cfglock);
|
||||
return r;
|
||||
}
|
||||
q->res->answer_packet = q->msg;
|
||||
q->res->answer_len = (int)q->msg_len;
|
||||
q->msg = NULL;
|
||||
*result = q->res;
|
||||
q->res = NULL;
|
||||
|
||||
lock_basic_lock(&ctx->cfglock);
|
||||
(void)rbtree_delete(&ctx->queries, q->node.key);
|
||||
context_query_delete(q);
|
||||
lock_basic_unlock(&ctx->cfglock);
|
||||
return UB_NOERROR;
|
||||
}
|
||||
|
||||
int
|
||||
ub_send_async(struct ub_ctx* ctx, const char* packet, int length,
|
||||
void* mydata, ub_callback_type callback, int* async_id)
|
||||
{
|
||||
struct ctx_query* q;
|
||||
uint8_t* msg = NULL;
|
||||
uint32_t len = 0;
|
||||
|
||||
if(async_id)
|
||||
*async_id = 0;
|
||||
lock_basic_lock(&ctx->cfglock);
|
||||
if(!ctx->finalized) {
|
||||
int r = context_finalize(ctx);
|
||||
if(r) {
|
||||
lock_basic_unlock(&ctx->cfglock);
|
||||
return r;
|
||||
}
|
||||
}
|
||||
if(!ctx->created_bg) {
|
||||
int r;
|
||||
ctx->created_bg = 1;
|
||||
lock_basic_unlock(&ctx->cfglock);
|
||||
r = libworker_bg(ctx);
|
||||
if(r) {
|
||||
lock_basic_lock(&ctx->cfglock);
|
||||
ctx->created_bg = 0;
|
||||
lock_basic_unlock(&ctx->cfglock);
|
||||
return r;
|
||||
}
|
||||
} else {
|
||||
lock_basic_unlock(&ctx->cfglock);
|
||||
}
|
||||
|
||||
/* create new ctx_query and attempt to add to the list */
|
||||
q = context_new(ctx, NULL, 0, 0, callback, NULL,
|
||||
mydata, (const uint8_t*)packet, length);
|
||||
if(!q)
|
||||
return UB_NOMEM;
|
||||
|
||||
/* write over pipe to background worker */
|
||||
lock_basic_lock(&ctx->cfglock);
|
||||
msg = context_serialize_new_query(q, &len);
|
||||
if(!msg) {
|
||||
(void)rbtree_delete(&ctx->queries, q->node.key);
|
||||
ctx->num_async--;
|
||||
context_query_delete(q);
|
||||
lock_basic_unlock(&ctx->cfglock);
|
||||
return UB_NOMEM;
|
||||
}
|
||||
if(async_id)
|
||||
*async_id = q->querynum;
|
||||
lock_basic_unlock(&ctx->cfglock);
|
||||
|
||||
lock_basic_lock(&ctx->qqpipe_lock);
|
||||
if(!tube_write_msg(ctx->qq_pipe, msg, len, 0)) {
|
||||
lock_basic_unlock(&ctx->qqpipe_lock);
|
||||
free(msg);
|
||||
return UB_PIPE;
|
||||
}
|
||||
lock_basic_unlock(&ctx->qqpipe_lock);
|
||||
free(msg);
|
||||
return UB_NOERROR;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
ub_cancel(struct ub_ctx* ctx, int async_id)
|
||||
{
|
||||
@@ -951,7 +1064,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 +1144,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;
|
||||
}
|
||||
|
||||
+12
-7
@@ -596,6 +596,8 @@ setup_qinfo_edns(struct libworker* w, struct ctx_query* q,
|
||||
if(!qinfo->qname) {
|
||||
return 0;
|
||||
}
|
||||
qinfo->qbuf = q->qbuf;
|
||||
qinfo->qbuf_len = q->qbuf_len;
|
||||
edns->edns_present = 1;
|
||||
edns->ext_rcode = 0;
|
||||
edns->edns_version = 0;
|
||||
@@ -650,7 +652,7 @@ int libworker_fg(struct ub_ctx* ctx, struct ctx_query* q)
|
||||
}
|
||||
/* process new query */
|
||||
if(!mesh_new_callback(w->env->mesh, &qinfo, qflags, &edns,
|
||||
w->back->udp_buff, qid, libworker_fg_done_cb, q)) {
|
||||
w->back->udp_buff, qid, libworker_fg_done_cb, q, 0)) {
|
||||
free(qinfo.qname);
|
||||
return UB_NOMEM;
|
||||
}
|
||||
@@ -730,7 +732,7 @@ int libworker_attach_mesh(struct ub_ctx* ctx, struct ctx_query* q,
|
||||
if(async_id)
|
||||
*async_id = q->querynum;
|
||||
if(!mesh_new_callback(w->env->mesh, &qinfo, qflags, &edns,
|
||||
w->back->udp_buff, qid, libworker_event_done_cb, q)) {
|
||||
w->back->udp_buff, qid, libworker_event_done_cb, q, 0)) {
|
||||
free(qinfo.qname);
|
||||
return UB_NOMEM;
|
||||
}
|
||||
@@ -867,7 +869,7 @@ handle_newq(struct libworker* w, uint8_t* buf, uint32_t len)
|
||||
q->w = w;
|
||||
/* process new query */
|
||||
if(!mesh_new_callback(w->env->mesh, &qinfo, qflags, &edns,
|
||||
w->back->udp_buff, qid, libworker_bg_done_cb, q)) {
|
||||
w->back->udp_buff, qid, libworker_bg_done_cb, q, 0)) {
|
||||
add_bg_result(w, q, NULL, UB_NOMEM, NULL, 0);
|
||||
}
|
||||
free(qinfo.qname);
|
||||
@@ -882,9 +884,10 @@ void libworker_alloc_cleanup(void* arg)
|
||||
|
||||
struct outbound_entry* libworker_send_query(struct query_info* qinfo,
|
||||
uint16_t flags, int dnssec, int want_dnssec, int nocaps,
|
||||
int check_ratelimit,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* zone,
|
||||
size_t zonelen, int tcp_upstream, int ssl_upstream, char* tls_auth_name,
|
||||
struct module_qstate* q)
|
||||
struct module_qstate* q, int* was_ratelimited)
|
||||
{
|
||||
struct libworker* w = (struct libworker*)q->env->worker;
|
||||
struct outbound_entry* e = (struct outbound_entry*)regional_alloc(
|
||||
@@ -893,9 +896,10 @@ struct outbound_entry* libworker_send_query(struct query_info* qinfo,
|
||||
return NULL;
|
||||
e->qstate = q;
|
||||
e->qsent = outnet_serviced_query(w->back, qinfo, flags, dnssec,
|
||||
want_dnssec, nocaps, tcp_upstream, ssl_upstream,
|
||||
want_dnssec, nocaps, check_ratelimit, tcp_upstream, ssl_upstream,
|
||||
tls_auth_name, addr, addrlen, zone, zonelen, q,
|
||||
libworker_handle_service_reply, e, w->back->udp_buff, q->env);
|
||||
libworker_handle_service_reply, e, w->back->udp_buff, q->env,
|
||||
was_ratelimited);
|
||||
if(!e->qsent) {
|
||||
return NULL;
|
||||
}
|
||||
@@ -976,10 +980,11 @@ void worker_sighandler(int ATTR_UNUSED(sig), void* ATTR_UNUSED(arg))
|
||||
struct outbound_entry* worker_send_query(struct query_info* ATTR_UNUSED(qinfo),
|
||||
uint16_t ATTR_UNUSED(flags), int ATTR_UNUSED(dnssec),
|
||||
int ATTR_UNUSED(want_dnssec), int ATTR_UNUSED(nocaps),
|
||||
int ATTR_UNUSED(check_ratelimit),
|
||||
struct sockaddr_storage* ATTR_UNUSED(addr), socklen_t ATTR_UNUSED(addrlen),
|
||||
uint8_t* ATTR_UNUSED(zone), size_t ATTR_UNUSED(zonelen), int ATTR_UNUSED(tcp_upstream),
|
||||
int ATTR_UNUSED(ssl_upstream), char* ATTR_UNUSED(tls_auth_name),
|
||||
struct module_qstate* ATTR_UNUSED(q))
|
||||
struct module_qstate* ATTR_UNUSED(q), int* ATTR_UNUSED(was_ratelimited))
|
||||
{
|
||||
log_assert(0);
|
||||
return 0;
|
||||
|
||||
@@ -31,6 +31,8 @@ ub_resolve
|
||||
ub_resolve_async
|
||||
ub_resolve_event
|
||||
ub_resolve_free
|
||||
ub_send
|
||||
ub_send_async
|
||||
ub_strerror
|
||||
ub_version
|
||||
ub_wait
|
||||
|
||||
@@ -568,6 +568,50 @@ int ub_resolve(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);
|
||||
|
||||
/**
|
||||
* Transmit a wire-encoded query packet directly to a nameserver.
|
||||
* @param ctx: context.
|
||||
* The context is finalized, and can no longer accept config changes.
|
||||
* @param packet: wire-encoded query packet.
|
||||
* @param length: length of encoded query packet.
|
||||
* @param result: the reply packet, together with its validation status,
|
||||
* is returned in a newly allocated result structure.
|
||||
* May be NULL on return, in which case an error code is returned.
|
||||
* @return 0 if OK, else error.
|
||||
*/
|
||||
int ub_send(struct ub_ctx* ctx, const char* packet, int length,
|
||||
struct ub_result** result);
|
||||
|
||||
/**
|
||||
* Transmit a wire-encoded query packet directly to a nameserver.
|
||||
* Asynchronous, after a while, the callback will be called with your
|
||||
* data and the result.
|
||||
* @param ctx: context.
|
||||
* If no thread or process has been created yet to perform the
|
||||
* work in the background, it is created now.
|
||||
* The context is finalized, and can no longer accept config changes.
|
||||
* @param packet: wire-encoded query packet.
|
||||
* @param length: length of encoded query packet.
|
||||
* @param mydata: this data is your own data (you can pass NULL),
|
||||
* and is passed on to the callback function.
|
||||
* @param callback: this is called on completion of the resolution.
|
||||
* It is called as:
|
||||
* void callback(void* mydata, int err, struct ub_result* result)
|
||||
* with mydata: the same as passed here, you may pass NULL,
|
||||
* with err: is 0 when a result has been found.
|
||||
* with result: a newly allocated result structure.
|
||||
* The result may be NULL, in that case err is set.
|
||||
*
|
||||
* 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
|
||||
* cancel the query.
|
||||
* @return 0 if OK, else error.
|
||||
*/
|
||||
int ub_send_async(struct ub_ctx* ctx, const char* packet, int length,
|
||||
void* mydata, ub_callback_type callback, int* async_id);
|
||||
|
||||
/**
|
||||
* Cancel an async query in progress.
|
||||
* Its callback will not be called.
|
||||
@@ -725,6 +769,8 @@ struct ub_server_stats {
|
||||
long long qtcp;
|
||||
/** number of outgoing queries over TCP */
|
||||
long long qtcp_outgoing;
|
||||
/** number of outgoing queries over UDP */
|
||||
long long qudp_outgoing;
|
||||
/** number of queries over (DNS over) TLS */
|
||||
long long qtls;
|
||||
/** number of queries over (DNS over) HTTPS */
|
||||
|
||||
+10
-2
@@ -58,6 +58,7 @@ struct query_info;
|
||||
* @param dnssec: if set, EDNS record will have DO bit set.
|
||||
* @param want_dnssec: signatures needed.
|
||||
* @param nocaps: ignore capsforid(if in config), do not perturb qname.
|
||||
* @param check_ratelimit: if set, will check ratelimit before sending out.
|
||||
* @param addr: where to.
|
||||
* @param addrlen: length of addr.
|
||||
* @param zone: delegation point name.
|
||||
@@ -67,14 +68,17 @@ struct query_info;
|
||||
* @param tls_auth_name: if ssl_upstream, use this name with TLS
|
||||
* authentication.
|
||||
* @param q: which query state to reactivate upon return.
|
||||
* @param was_ratelimited: it will signal back if the query failed to pass the
|
||||
* ratelimit check.
|
||||
* @return: false on failure (memory or socket related). no query was
|
||||
* sent.
|
||||
*/
|
||||
struct outbound_entry* libworker_send_query(struct query_info* qinfo,
|
||||
uint16_t flags, int dnssec, int want_dnssec, int nocaps,
|
||||
int check_ratelimit,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* zone,
|
||||
size_t zonelen, int tcp_upstream, int ssl_upstream, char* tls_auth_name,
|
||||
struct module_qstate* q);
|
||||
struct module_qstate* q, int* was_ratelimited);
|
||||
|
||||
/** process incoming serviced query replies from the network */
|
||||
int libworker_handle_service_reply(struct comm_point* c, void* arg, int error,
|
||||
@@ -110,6 +114,7 @@ void worker_sighandler(int sig, void* arg);
|
||||
* @param dnssec: if set, EDNS record will have DO bit set.
|
||||
* @param want_dnssec: signatures needed.
|
||||
* @param nocaps: ignore capsforid(if in config), do not perturb qname.
|
||||
* @param check_ratelimit: if set, will check ratelimit before sending out.
|
||||
* @param addr: where to.
|
||||
* @param addrlen: length of addr.
|
||||
* @param zone: wireformat dname of the zone.
|
||||
@@ -119,14 +124,17 @@ void worker_sighandler(int sig, void* arg);
|
||||
* @param tls_auth_name: if ssl_upstream, use this name with TLS
|
||||
* authentication.
|
||||
* @param q: which query state to reactivate upon return.
|
||||
* @param was_ratelimited: it will signal back if the query failed to pass the
|
||||
* ratelimit check.
|
||||
* @return: false on failure (memory or socket related). no query was
|
||||
* sent.
|
||||
*/
|
||||
struct outbound_entry* worker_send_query(struct query_info* qinfo,
|
||||
uint16_t flags, int dnssec, int want_dnssec, int nocaps,
|
||||
int check_ratelimit,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* zone,
|
||||
size_t zonelen, int tcp_upstream, int ssl_upstream, char* tls_auth_name,
|
||||
struct module_qstate* q);
|
||||
struct module_qstate* q, int* was_ratelimited);
|
||||
|
||||
/**
|
||||
* process control messages from the main thread. Frees the control
|
||||
|
||||
+5
-3
@@ -268,10 +268,12 @@ if [ "$DOWIN" = "yes" ]; then
|
||||
# before 1.0.1i need --cross-compile-prefix=i686-w64-mingw32-
|
||||
if test "$mw64" = "mingw64"; then
|
||||
sslflags="no-asm -DOPENSSL_NO_CAPIENG mingw64"
|
||||
sspdll="/usr/x86_64-w64-mingw32/sys-root/mingw/bin/libssp-0.dll"
|
||||
else
|
||||
sslflags="no-asm -DOPENSSL_NO_CAPIENG mingw"
|
||||
sspdll="/usr/i686-w64-mingw32/sys-root/mingw/bin/libssp-0.dll"
|
||||
fi
|
||||
if test -f /usr/x86_64-w64-mingw32/sys-root/mingw/bin/libssp-0.dll; then
|
||||
if test -f "$sspdll"; then
|
||||
# stack protector lib needs to link in to make
|
||||
# -lws2_32 work in openssl link stage
|
||||
SSPLIB="-l:libssp.a"
|
||||
@@ -439,8 +441,8 @@ if [ "$DOWIN" = "yes" ]; then
|
||||
cp ../../sslsharedinstall/lib64/libssl.dll.a libunbound/.
|
||||
fi
|
||||
cp ../../unbound_shared/unbound.h ../../unbound_shared/.libs/libunbound*.dll ../../unbound_shared/.libs/libunbound.dll.a ../../unbound_shared/.libs/libunbound.a ../../unbound_shared/.libs/libunbound*.def ../../sslsharedinstall/bin/libcrypto*.dll ../../sslsharedinstall/bin/libssl*.dll ../../wxpinstall/bin/libexpat*.dll ../../wxpinstall/lib/libexpat.dll.a libunbound/.
|
||||
if test -f /usr/x86_64-w64-mingw32/sys-root/mingw/bin/libssp-0.dll; then
|
||||
cp /usr/x86_64-w64-mingw32/sys-root/mingw/bin/libssp-0.dll libunbound/.
|
||||
if test -f "$sspdll"; then
|
||||
cp "$sspdll" libunbound/.
|
||||
fi
|
||||
# zipfile
|
||||
zip -r ../$file LICENSE README.txt unbound.exe unbound-anchor.exe unbound-host.exe unbound-control.exe unbound-checkconf.exe unbound-service-install.exe unbound-service-remove.exe unbound-control-setup.cmd example.conf service.conf root.key unbound-website.url create_unbound_ad_servers.cmd warmup.cmd unbound_cache.cmd Changelog libunbound
|
||||
|
||||
@@ -60,7 +60,7 @@ EDNS options
|
||||
|
||||
.. function:: edns_opt_list_remove(list, code);
|
||||
|
||||
Remove an ENDS option code from the list.
|
||||
Remove an EDNS option code from the list.
|
||||
.. note:: All :class:`edns_option` with the code will be removed
|
||||
|
||||
:param list: linked list of :class:`edns_option`
|
||||
|
||||
@@ -77,7 +77,7 @@ module_qstate
|
||||
|
||||
.. attribute:: edns_opts_back_in_iter
|
||||
|
||||
Iterator for `ends_opts_back_in`.
|
||||
Iterator for `edns_opts_back_in`.
|
||||
|
||||
.. attribute:: edns_opts_front_out
|
||||
|
||||
|
||||
@@ -207,7 +207,7 @@ def inplace_servfail_callback(qinfo, qstate, rep, rcode, edns, opt_list_out,
|
||||
|
||||
"""
|
||||
log_info("python: called back while servfail.")
|
||||
# Append the example ENDS option
|
||||
# Append the example EDNS option
|
||||
b = bytearray.fromhex("")
|
||||
edns_opt_list_append(opt_list_out, 65003, b, region)
|
||||
|
||||
|
||||
+10
-7
@@ -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 {
|
||||
@@ -712,9 +712,10 @@ struct module_env {
|
||||
/* --- services --- */
|
||||
struct outbound_entry* (*send_query)(struct query_info* qinfo,
|
||||
uint16_t flags, int dnssec, int want_dnssec, int nocaps,
|
||||
int check_ratelimit,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen,
|
||||
uint8_t* zone, size_t zonelen, int tcp_upstream, int ssl_upstream,
|
||||
char* tls_auth_name, struct module_qstate* q);
|
||||
char* tls_auth_name, struct module_qstate* q, int* was_ratelimited);
|
||||
void (*detach_subs)(struct module_qstate* qstate);
|
||||
int (*attach_sub)(struct module_qstate* qstate,
|
||||
struct query_info* qinfo, uint16_t qflags, int prime,
|
||||
@@ -1374,9 +1375,10 @@ int set_return_msg(struct module_qstate* qstate,
|
||||
/* Functions which we will need to lookup delegations */
|
||||
struct delegpt* dns_cache_find_delegation(struct module_env* env,
|
||||
uint8_t* qname, size_t qnamelen, uint16_t qtype, uint16_t qclass,
|
||||
struct regional* region, struct dns_msg** msg, uint32_t timenow);
|
||||
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);
|
||||
struct delegpt* dp, int supports_ipv4, int supports_ipv6);
|
||||
struct iter_hints_stub* hints_lookup_stub(struct iter_hints* hints,
|
||||
uint8_t* qname, uint16_t qclass, struct delegpt* dp);
|
||||
|
||||
@@ -1403,10 +1405,11 @@ struct delegpt* find_delegation(struct module_qstate* qstate, char *nm, size_t n
|
||||
qinfo.qclass = LDNS_RR_CLASS_IN;
|
||||
|
||||
while(1) {
|
||||
dp = dns_cache_find_delegation(qstate->env, (uint8_t*)nm, nmlen, qinfo.qtype, qinfo.qclass, region, &msg, timenow);
|
||||
dp = dns_cache_find_delegation(qstate->env, (uint8_t*)nm, nmlen, qinfo.qtype, qinfo.qclass, region, &msg, timenow, 0, NULL, 0);
|
||||
if(!dp)
|
||||
return NULL;
|
||||
if(iter_dp_is_useless(&qinfo, BIT_RD, dp)) {
|
||||
if(iter_dp_is_useless(&qinfo, BIT_RD, dp,
|
||||
qstate->env->cfg->do_ip4, qstate->env->cfg->do_ip6)) {
|
||||
if (dname_is_root((uint8_t*)nm))
|
||||
return NULL;
|
||||
nm = (char*)dp->name;
|
||||
|
||||
@@ -72,7 +72,8 @@ int storeQueryInCache(struct module_qstate* qstate, struct query_info* qinfo,
|
||||
}
|
||||
|
||||
return dns_cache_store(qstate->env, qinfo, msgrep, is_referral,
|
||||
qstate->prefetch_leeway, 0, NULL, qstate->query_flags);
|
||||
qstate->prefetch_leeway, 0, NULL, qstate->query_flags,
|
||||
qstate->qstarttime);
|
||||
}
|
||||
|
||||
/* Invalidate the message associated with query_info stored in message cache */
|
||||
@@ -171,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;
|
||||
|
||||
+20
-13
@@ -833,8 +833,11 @@ static int
|
||||
respip_use_rpz(struct resp_addr* raddr, struct rpz* r,
|
||||
enum respip_action* action,
|
||||
struct ub_packed_rrset_key** data, int* rpz_log, char** log_name,
|
||||
int* rpz_cname_override, struct regional* region, int* is_rpz)
|
||||
int* rpz_cname_override, struct regional* region, int* is_rpz,
|
||||
int* rpz_passthru)
|
||||
{
|
||||
if(rpz_passthru && *rpz_passthru)
|
||||
return 0;
|
||||
if(r->action_override == RPZ_DISABLED_ACTION) {
|
||||
*is_rpz = 0;
|
||||
return 1;
|
||||
@@ -848,6 +851,9 @@ respip_use_rpz(struct resp_addr* raddr, struct rpz* r,
|
||||
*data = r->cname_override;
|
||||
*rpz_cname_override = 1;
|
||||
}
|
||||
if(*action == respip_always_transparent /* RPZ_PASSTHRU_ACTION */
|
||||
&& rpz_passthru)
|
||||
*rpz_passthru = 1;
|
||||
*rpz_log = r->log;
|
||||
if(r->log_name)
|
||||
if(!(*log_name = regional_strdup(region, r->log_name)))
|
||||
@@ -861,7 +867,7 @@ respip_rewrite_reply(const struct query_info* qinfo,
|
||||
const struct respip_client_info* cinfo, const struct reply_info* rep,
|
||||
struct reply_info** new_repp, struct respip_action_info* actinfo,
|
||||
struct ub_packed_rrset_key** alias_rrset, int search_only,
|
||||
struct regional* region, struct auth_zones* az)
|
||||
struct regional* region, struct auth_zones* az, int* rpz_passthru)
|
||||
{
|
||||
const uint8_t* ctaglist;
|
||||
size_t ctaglen;
|
||||
@@ -934,7 +940,7 @@ respip_rewrite_reply(const struct query_info* qinfo,
|
||||
ipset->tagname, ipset->num_tags);
|
||||
}
|
||||
lock_rw_rdlock(&az->rpz_lock);
|
||||
for(a = az->rpz_first; a && !raddr; a = a->rpz_az_next) {
|
||||
for(a = az->rpz_first; a && !raddr && !(rpz_passthru && *rpz_passthru); a = a->rpz_az_next) {
|
||||
lock_rw_rdlock(&a->lock);
|
||||
r = a->rpz;
|
||||
if(!r->taglist || taglist_intersect(r->taglist,
|
||||
@@ -943,7 +949,7 @@ respip_rewrite_reply(const struct query_info* qinfo,
|
||||
r->respip_set, &rrset_id, &rr_id))) {
|
||||
if(!respip_use_rpz(raddr, r, &action, &data,
|
||||
&rpz_log, &log_name, &rpz_cname_override,
|
||||
region, &rpz_used)) {
|
||||
region, &rpz_used, rpz_passthru)) {
|
||||
log_err("out of memory");
|
||||
lock_rw_unlock(&raddr->lock);
|
||||
lock_rw_unlock(&a->lock);
|
||||
@@ -964,7 +970,7 @@ respip_rewrite_reply(const struct query_info* qinfo,
|
||||
addr_to_str(&raddr->node.addr,
|
||||
raddr->node.addrlen,
|
||||
nm, sizeof(nm));
|
||||
verbose(VERB_ALGO, "respip: rpz response-ip trigger %s/%d on %s %s with action %s", nm, raddr->node.net, qn, ip, rpz_action_to_string(respip_action_to_rpz_action(action)));
|
||||
verbose(VERB_ALGO, "respip: rpz: response-ip trigger %s/%d on %s %s with action %s", nm, raddr->node.net, qn, ip, rpz_action_to_string(respip_action_to_rpz_action(action)));
|
||||
}
|
||||
/* break to make sure 'a' stays pointed
|
||||
* to used auth_zone, and keeps lock */
|
||||
@@ -1094,7 +1100,8 @@ respip_operate(struct module_qstate* qstate, enum module_ev event, int id,
|
||||
if(!respip_rewrite_reply(&qstate->qinfo,
|
||||
qstate->client_info, qstate->return_msg->rep,
|
||||
&new_rep, &actinfo, &alias_rrset, 0,
|
||||
qstate->region, qstate->env->auth_zones)) {
|
||||
qstate->region, qstate->env->auth_zones,
|
||||
&qstate->rpz_passthru)) {
|
||||
goto servfail;
|
||||
}
|
||||
if(actinfo.action != respip_none) {
|
||||
@@ -1169,7 +1176,7 @@ respip_merge_cname(struct reply_info* base_rep,
|
||||
|
||||
/* see if the target reply would be subject to a response-ip action. */
|
||||
if(!respip_rewrite_reply(qinfo, cinfo, tgt_rep, &tmp_rep, &actinfo,
|
||||
&alias_rrset, 1, region, az))
|
||||
&alias_rrset, 1, region, az, NULL))
|
||||
return 0;
|
||||
if(actinfo.action != respip_none) {
|
||||
log_info("CNAME target of redirect response-ip action would "
|
||||
@@ -1283,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;
|
||||
@@ -1293,15 +1300,15 @@ 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) {
|
||||
txtlen += snprintf(txt+txtlen, sizeof(txt)-txtlen, "%s",
|
||||
"RPZ applied ");
|
||||
"rpz: applied ");
|
||||
if(respip_actinfo->rpz_cname_override)
|
||||
actionstr = rpz_action_to_string(
|
||||
RPZ_CNAME_OVERRIDE_ACTION);
|
||||
|
||||
+8
-3
@@ -176,6 +176,8 @@ int respip_merge_cname(struct reply_info* base_rep,
|
||||
* will be set (or intact) accordingly but the modified reply won't be built.
|
||||
* @param az: auth zones containing RPZ information.
|
||||
* @param region: allocator to build *new_repp.
|
||||
* @param rpz_passthru: keeps track of query state can have passthru that
|
||||
* stops further rpz processing. Or NULL for cached answer processing.
|
||||
* @return 1 on success, 0 on error.
|
||||
*/
|
||||
int respip_rewrite_reply(const struct query_info* qinfo,
|
||||
@@ -183,7 +185,8 @@ int respip_rewrite_reply(const struct query_info* qinfo,
|
||||
const struct reply_info *rep, struct reply_info** new_repp,
|
||||
struct respip_action_info* actinfo,
|
||||
struct ub_packed_rrset_key** alias_rrset,
|
||||
int search_only, struct regional* region, struct auth_zones* az);
|
||||
int search_only, struct regional* region, struct auth_zones* az,
|
||||
int* rpz_passthru);
|
||||
|
||||
/**
|
||||
* Get the response-ip function block.
|
||||
@@ -248,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.
|
||||
|
||||
+89
-23
@@ -132,6 +132,7 @@ msg_create(struct regional* region, struct query_info* qinfo)
|
||||
return NULL;
|
||||
msg->rep->flags = (uint16_t)(BIT_QR | BIT_AA);
|
||||
msg->rep->authoritative = 1;
|
||||
msg->rep->reason_bogus = LDNS_EDE_NONE;
|
||||
msg->rep->qdcount = 1;
|
||||
/* rrsets is NULL, no rrsets yet */
|
||||
return msg;
|
||||
@@ -1882,6 +1883,8 @@ static int auth_zone_zonemd_check_hash(struct auth_zone* z,
|
||||
struct regional* region = NULL;
|
||||
struct sldns_buffer* buf = NULL;
|
||||
uint32_t soa_serial = 0;
|
||||
char* unsupported_reason = NULL;
|
||||
int only_unsupported = 1;
|
||||
region = env->scratch;
|
||||
regional_free_all(region);
|
||||
buf = env->scratch_buffer;
|
||||
@@ -1911,6 +1914,7 @@ static int auth_zone_zonemd_check_hash(struct auth_zone* z,
|
||||
&hashalgo, &hash, &hashlen)) {
|
||||
/* malformed RR */
|
||||
*reason = "ZONEMD rdata malformed";
|
||||
only_unsupported = 0;
|
||||
continue;
|
||||
}
|
||||
/* check for duplicates */
|
||||
@@ -1920,25 +1924,51 @@ static int auth_zone_zonemd_check_hash(struct auth_zone* z,
|
||||
* is not allowed. */
|
||||
*reason = "ZONEMD RRSet contains more than one RR "
|
||||
"with the same scheme and hash algorithm";
|
||||
only_unsupported = 0;
|
||||
continue;
|
||||
}
|
||||
regional_free_all(region);
|
||||
if(serial != soa_serial) {
|
||||
*reason = "ZONEMD serial is wrong";
|
||||
only_unsupported = 0;
|
||||
continue;
|
||||
}
|
||||
*reason = NULL;
|
||||
if(auth_zone_generate_zonemd_check(z, scheme, hashalgo,
|
||||
hash, hashlen, region, buf, reason)) {
|
||||
/* success */
|
||||
if(*reason) {
|
||||
if(!unsupported_reason)
|
||||
unsupported_reason = *reason;
|
||||
/* continue to check for valid ZONEMD */
|
||||
if(verbosity >= VERB_ALGO) {
|
||||
char zstr[255+1];
|
||||
dname_str(z->name, zstr);
|
||||
verbose(VERB_ALGO, "auth-zone %s ZONEMD %d %d is unsupported: %s", zstr, (int)scheme, (int)hashalgo, *reason);
|
||||
}
|
||||
*reason = NULL;
|
||||
continue;
|
||||
}
|
||||
if(verbosity >= VERB_ALGO) {
|
||||
char zstr[255+1];
|
||||
dname_str(z->name, zstr);
|
||||
verbose(VERB_ALGO, "auth-zone %s ZONEMD hash is correct", zstr);
|
||||
if(!*reason)
|
||||
verbose(VERB_ALGO, "auth-zone %s ZONEMD hash is correct", zstr);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
only_unsupported = 0;
|
||||
/* try next one */
|
||||
}
|
||||
/* have we seen no failures but only unsupported algo,
|
||||
* and one unsupported algorithm, or more. */
|
||||
if(only_unsupported && unsupported_reason) {
|
||||
/* only unsupported algorithms, with valid serial, not
|
||||
* malformed. Did not see supported algorithms, failed or
|
||||
* successful ones. */
|
||||
*reason = unsupported_reason;
|
||||
return 1;
|
||||
}
|
||||
/* fail, we may have reason */
|
||||
if(!*reason)
|
||||
*reason = "no ZONEMD records found";
|
||||
@@ -3669,7 +3699,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;
|
||||
@@ -3937,7 +3967,7 @@ probe_copy_masters_for_allow_notify(struct auth_xfer* xfr)
|
||||
struct auth_master* list = NULL, *last = NULL;
|
||||
struct auth_master* p;
|
||||
/* build up new list with copies */
|
||||
for(p = xfr->task_probe->masters; p; p=p->next) {
|
||||
for(p = xfr->task_transfer->masters; p; p=p->next) {
|
||||
struct auth_master* m = auth_master_copy(p);
|
||||
if(!m) {
|
||||
auth_free_masters(list);
|
||||
@@ -4456,7 +4486,7 @@ chunkline_get_line_collated(struct auth_chunk** chunk, size_t* chunk_pos,
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** process $ORIGIN for http */
|
||||
/** process $ORIGIN for http, 0 nothing, 1 done, 2 error */
|
||||
static int
|
||||
http_parse_origin(sldns_buffer* buf, struct sldns_file_parse_state* pstate)
|
||||
{
|
||||
@@ -4467,13 +4497,16 @@ http_parse_origin(sldns_buffer* buf, struct sldns_file_parse_state* pstate)
|
||||
pstate->origin_len = sizeof(pstate->origin);
|
||||
s = sldns_str2wire_dname_buf(sldns_strip_ws(line+8),
|
||||
pstate->origin, &pstate->origin_len);
|
||||
if(s) pstate->origin_len = 0;
|
||||
if(s) {
|
||||
pstate->origin_len = 0;
|
||||
return 2;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** process $TTL for http */
|
||||
/** process $TTL for http, 0 nothing, 1 done, 2 error */
|
||||
static int
|
||||
http_parse_ttl(sldns_buffer* buf, struct sldns_file_parse_state* pstate)
|
||||
{
|
||||
@@ -4481,8 +4514,12 @@ http_parse_ttl(sldns_buffer* buf, struct sldns_file_parse_state* pstate)
|
||||
if(strncmp(line, "$TTL", 4) == 0 &&
|
||||
isspace((unsigned char)line[4])) {
|
||||
const char* end = NULL;
|
||||
int overflow = 0;
|
||||
pstate->default_ttl = sldns_str2period(
|
||||
sldns_strip_ws(line+5), &end);
|
||||
sldns_strip_ws(line+5), &end, &overflow);
|
||||
if(overflow) {
|
||||
return 2;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
@@ -4493,15 +4530,20 @@ static int
|
||||
chunkline_non_comment_RR(struct auth_chunk** chunk, size_t* chunk_pos,
|
||||
sldns_buffer* buf, struct sldns_file_parse_state* pstate)
|
||||
{
|
||||
int ret;
|
||||
while(chunkline_get_line_collated(chunk, chunk_pos, buf)) {
|
||||
if(chunkline_is_comment_line_or_empty(buf)) {
|
||||
/* a comment, go to next line */
|
||||
continue;
|
||||
}
|
||||
if(http_parse_origin(buf, pstate)) {
|
||||
if((ret=http_parse_origin(buf, pstate))!=0) {
|
||||
if(ret == 2)
|
||||
return 0;
|
||||
continue; /* $ORIGIN has been handled */
|
||||
}
|
||||
if(http_parse_ttl(buf, pstate)) {
|
||||
if((ret=http_parse_ttl(buf, pstate))!=0) {
|
||||
if(ret == 2)
|
||||
return 0;
|
||||
continue; /* $TTL has been handled */
|
||||
}
|
||||
return 1;
|
||||
@@ -5007,6 +5049,7 @@ apply_http(struct auth_xfer* xfr, struct auth_zone* z,
|
||||
struct sldns_file_parse_state pstate;
|
||||
struct auth_chunk* chunk;
|
||||
size_t chunk_pos;
|
||||
int ret;
|
||||
memset(&pstate, 0, sizeof(pstate));
|
||||
pstate.default_ttl = 3600;
|
||||
if(xfr->namelen < sizeof(pstate.origin)) {
|
||||
@@ -5063,10 +5106,24 @@ apply_http(struct auth_xfer* xfr, struct auth_zone* z,
|
||||
continue;
|
||||
}
|
||||
/* parse line and add RR */
|
||||
if(http_parse_origin(scratch_buffer, &pstate)) {
|
||||
if((ret=http_parse_origin(scratch_buffer, &pstate))!=0) {
|
||||
if(ret == 2) {
|
||||
verbose(VERB_ALGO, "error parsing ORIGIN on line [%s:%d] %s",
|
||||
xfr->task_transfer->master->file,
|
||||
pstate.lineno,
|
||||
sldns_buffer_begin(scratch_buffer));
|
||||
return 0;
|
||||
}
|
||||
continue; /* $ORIGIN has been handled */
|
||||
}
|
||||
if(http_parse_ttl(scratch_buffer, &pstate)) {
|
||||
if((ret=http_parse_ttl(scratch_buffer, &pstate))!=0) {
|
||||
if(ret == 2) {
|
||||
verbose(VERB_ALGO, "error parsing TTL on line [%s:%d] %s",
|
||||
xfr->task_transfer->master->file,
|
||||
pstate.lineno,
|
||||
sldns_buffer_begin(scratch_buffer));
|
||||
return 0;
|
||||
}
|
||||
continue; /* $TTL has been handled */
|
||||
}
|
||||
if(!http_parse_add_rr(xfr, z, scratch_buffer, &pstate)) {
|
||||
@@ -5324,7 +5381,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;
|
||||
}
|
||||
@@ -5370,7 +5427,7 @@ xfr_transfer_lookup_host(struct auth_xfer* xfr, struct module_env* env)
|
||||
* called straight away */
|
||||
lock_basic_unlock(&xfr->lock);
|
||||
if(!mesh_new_callback(env->mesh, &qinfo, qflags, &edns, buf, 0,
|
||||
&auth_xfer_transfer_lookup_callback, xfr)) {
|
||||
&auth_xfer_transfer_lookup_callback, xfr, 0)) {
|
||||
lock_basic_lock(&xfr->lock);
|
||||
log_err("out of memory lookup up master %s", master->host);
|
||||
return 0;
|
||||
@@ -5455,6 +5512,8 @@ xfr_transfer_init_fetch(struct auth_xfer* xfr, struct module_env* env)
|
||||
addr_to_str(&addr, addrlen, as, sizeof(as));
|
||||
verbose(VERB_ALGO, "auth zone %s transfer next HTTP fetch from %s started", zname, as);
|
||||
}
|
||||
/* Create or refresh the list of allow_notify addrs */
|
||||
probe_copy_masters_for_allow_notify(xfr);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -6513,7 +6572,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;
|
||||
}
|
||||
@@ -6561,7 +6620,7 @@ xfr_probe_lookup_host(struct auth_xfer* xfr, struct module_env* env)
|
||||
* called straight away */
|
||||
lock_basic_unlock(&xfr->lock);
|
||||
if(!mesh_new_callback(env->mesh, &qinfo, qflags, &edns, buf, 0,
|
||||
&auth_xfer_probe_lookup_callback, xfr)) {
|
||||
&auth_xfer_probe_lookup_callback, xfr, 0)) {
|
||||
lock_basic_lock(&xfr->lock);
|
||||
log_err("out of memory lookup up master %s", master->host);
|
||||
return 0;
|
||||
@@ -7632,13 +7691,16 @@ int auth_zone_generate_zonemd_check(struct auth_zone* z, int scheme,
|
||||
{
|
||||
uint8_t gen[512];
|
||||
size_t genlen = 0;
|
||||
*reason = NULL;
|
||||
if(!zonemd_hashalgo_supported(hashalgo)) {
|
||||
/* allow it */
|
||||
*reason = "unsupported algorithm";
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
if(!zonemd_scheme_supported(scheme)) {
|
||||
/* allow it */
|
||||
*reason = "unsupported scheme";
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
if(hashlen < 12) {
|
||||
/* the ZONEMD draft requires digests to fail if too small */
|
||||
@@ -7726,7 +7788,7 @@ static int zonemd_dnssec_verify_rrset(struct auth_zone* z,
|
||||
auth_zone_log(z->name, VERB_ALGO,
|
||||
"zonemd: verify %s RRset with DNSKEY", typestr);
|
||||
}
|
||||
sec = dnskeyset_verify_rrset(env, ve, &pk, dnskey, sigalg, why_bogus,
|
||||
sec = dnskeyset_verify_rrset(env, ve, &pk, dnskey, sigalg, why_bogus, NULL,
|
||||
LDNS_SECTION_ANSWER, NULL);
|
||||
if(sec == sec_status_secure) {
|
||||
return 1;
|
||||
@@ -8003,9 +8065,13 @@ auth_zone_verify_zonemd_with_key(struct auth_zone* z, struct module_env* env,
|
||||
}
|
||||
|
||||
/* success! log the success */
|
||||
auth_zone_log(z->name, VERB_ALGO, "ZONEMD verification successful");
|
||||
if(reason)
|
||||
auth_zone_log(z->name, VERB_ALGO, "ZONEMD %s", reason);
|
||||
else auth_zone_log(z->name, VERB_ALGO, "ZONEMD verification successful");
|
||||
if(result) {
|
||||
*result = strdup("ZONEMD verification successful");
|
||||
if(reason)
|
||||
*result = strdup(reason);
|
||||
else *result = strdup("ZONEMD verification successful");
|
||||
if(!*result) log_err("out of memory");
|
||||
}
|
||||
}
|
||||
@@ -8065,7 +8131,7 @@ zonemd_get_dnskey_from_anchor(struct auth_zone* z, struct module_env* env,
|
||||
auth_zone_log(z->name, VERB_QUERY,
|
||||
"zonemd: verify DNSKEY RRset with trust anchor");
|
||||
sec = val_verify_DNSKEY_with_TA(env, ve, keystorage, anchor->ds_rrset,
|
||||
anchor->dnskey_rrset, NULL, why_bogus, NULL);
|
||||
anchor->dnskey_rrset, NULL, why_bogus, NULL, NULL);
|
||||
regional_free_all(env->scratch);
|
||||
if(sec == sec_status_secure) {
|
||||
/* success */
|
||||
@@ -8124,7 +8190,7 @@ auth_zone_verify_zonemd_key_with_ds(struct auth_zone* z,
|
||||
keystorage->rk.rrset_class = htons(z->dclass);
|
||||
auth_zone_log(z->name, VERB_QUERY, "zonemd: verify zone DNSKEY with DS");
|
||||
sec = val_verify_DNSKEY_with_DS(env, ve, keystorage, ds, sigalg,
|
||||
why_bogus, NULL);
|
||||
why_bogus, NULL, NULL);
|
||||
regional_free_all(env->scratch);
|
||||
if(sec == sec_status_secure) {
|
||||
/* success */
|
||||
@@ -8340,7 +8406,7 @@ zonemd_lookup_dnskey(struct auth_zone* z, struct module_env* env)
|
||||
/* the callback can be called straight away */
|
||||
lock_rw_unlock(&z->lock);
|
||||
if(!mesh_new_callback(env->mesh, &qinfo, qflags, &edns, buf, 0,
|
||||
&auth_zonemd_dnskey_lookup_callback, z)) {
|
||||
&auth_zonemd_dnskey_lookup_callback, z, 0)) {
|
||||
lock_rw_wrlock(&z->lock);
|
||||
log_err("out of memory lookup of %s for zonemd",
|
||||
(fetch_ds?"DS":"DNSKEY"));
|
||||
|
||||
@@ -747,6 +747,9 @@ int zonemd_scheme_supported(int scheme);
|
||||
* @param region: temp region for allocs during canonicalisation.
|
||||
* @param buf: temp buffer during canonicalisation.
|
||||
* @param reason: string returned with failure reason.
|
||||
* If the hash cannot be checked, but it is allowed, for unknown
|
||||
* algorithms, the routine returns success, and the reason is nonNULL,
|
||||
* with the allowance reason.
|
||||
* @return false on failure.
|
||||
*/
|
||||
int auth_zone_generate_zonemd_check(struct auth_zone* z, int scheme,
|
||||
|
||||
Vendored
+104
-15
@@ -68,11 +68,16 @@
|
||||
* in a prefetch situation to be updated (without becoming sticky).
|
||||
* @param qrep: update rrsets here if cache is better
|
||||
* @param region: for qrep allocs.
|
||||
* @param qstarttime: time when delegations were looked up, this is perhaps
|
||||
* earlier than the time in now. The time is used to determine if RRsets
|
||||
* of type NS have expired, so that they can only be updated using
|
||||
* lookups of delegation points that did not use them, since they had
|
||||
* expired then.
|
||||
*/
|
||||
static void
|
||||
store_rrsets(struct module_env* env, struct reply_info* rep, time_t now,
|
||||
time_t leeway, int pside, struct reply_info* qrep,
|
||||
struct regional* region)
|
||||
struct regional* region, time_t qstarttime)
|
||||
{
|
||||
size_t i;
|
||||
/* see if rrset already exists in cache, if not insert it. */
|
||||
@@ -81,8 +86,8 @@ store_rrsets(struct module_env* env, struct reply_info* rep, time_t now,
|
||||
rep->ref[i].id = rep->rrsets[i]->id;
|
||||
/* update ref if it was in the cache */
|
||||
switch(rrset_cache_update(env->rrset_cache, &rep->ref[i],
|
||||
env->alloc, now + ((ntohs(rep->ref[i].key->rk.type)==
|
||||
LDNS_RR_TYPE_NS && !pside)?0:leeway))) {
|
||||
env->alloc, ((ntohs(rep->ref[i].key->rk.type)==
|
||||
LDNS_RR_TYPE_NS && !pside)?qstarttime:now + leeway))) {
|
||||
case 0: /* ref unchanged, item inserted */
|
||||
break;
|
||||
case 2: /* ref updated, cache is superior */
|
||||
@@ -155,7 +160,8 @@ msg_del_servfail(struct module_env* env, struct query_info* qinfo,
|
||||
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,
|
||||
struct reply_info* qrep, uint32_t flags, struct regional* region)
|
||||
struct reply_info* qrep, uint32_t flags, struct regional* region,
|
||||
time_t qstarttime)
|
||||
{
|
||||
struct msgreply_entry* e;
|
||||
time_t ttl = rep->ttl;
|
||||
@@ -170,7 +176,8 @@ dns_cache_store_msg(struct module_env* env, struct query_info* qinfo,
|
||||
/* there was a reply_info_sortref(rep) here but it seems to be
|
||||
* unnecessary, because the cache gets locked per rrset. */
|
||||
reply_info_set_ttls(rep, *env->now);
|
||||
store_rrsets(env, rep, *env->now, leeway, pside, qrep, region);
|
||||
store_rrsets(env, rep, *env->now, leeway, pside, qrep, region,
|
||||
qstarttime);
|
||||
if(ttl == 0 && !(flags & DNSCACHE_STORE_ZEROTTL)) {
|
||||
/* we do not store the message, but we did store the RRs,
|
||||
* which could be useful for delegation information */
|
||||
@@ -194,10 +201,51 @@ dns_cache_store_msg(struct module_env* env, struct query_info* qinfo,
|
||||
slabhash_insert(env->msg_cache, hash, &e->entry, rep, env->alloc);
|
||||
}
|
||||
|
||||
/** see if an rrset is expired above the qname, return upper qname. */
|
||||
static int
|
||||
rrset_expired_above(struct module_env* env, uint8_t** qname, size_t* qnamelen,
|
||||
uint16_t searchtype, uint16_t qclass, time_t now, uint8_t* expiretop,
|
||||
size_t expiretoplen)
|
||||
{
|
||||
struct ub_packed_rrset_key *rrset;
|
||||
uint8_t lablen;
|
||||
|
||||
while(*qnamelen > 0) {
|
||||
/* look one label higher */
|
||||
lablen = **qname;
|
||||
*qname += lablen + 1;
|
||||
*qnamelen -= lablen + 1;
|
||||
if(*qnamelen <= 0)
|
||||
break;
|
||||
|
||||
/* looks up with a time of 0, to see expired entries */
|
||||
if((rrset = rrset_cache_lookup(env->rrset_cache, *qname,
|
||||
*qnamelen, searchtype, qclass, 0, 0, 0))) {
|
||||
struct packed_rrset_data* data =
|
||||
(struct packed_rrset_data*)rrset->entry.data;
|
||||
if(now > data->ttl) {
|
||||
/* it is expired, this is not wanted */
|
||||
lock_rw_unlock(&rrset->entry.lock);
|
||||
log_nametypeclass(VERB_ALGO, "this rrset is expired", *qname, searchtype, qclass);
|
||||
return 1;
|
||||
}
|
||||
/* it is not expired, continue looking */
|
||||
lock_rw_unlock(&rrset->entry.lock);
|
||||
}
|
||||
|
||||
/* do not look above the expiretop. */
|
||||
if(expiretop && *qnamelen == expiretoplen &&
|
||||
query_dname_compare(*qname, expiretop)==0)
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** find closest NS or DNAME and returns the rrset (locked) */
|
||||
static struct ub_packed_rrset_key*
|
||||
find_closest_of_type(struct module_env* env, uint8_t* qname, size_t qnamelen,
|
||||
uint16_t qclass, time_t now, uint16_t searchtype, int stripfront)
|
||||
uint16_t qclass, time_t now, uint16_t searchtype, int stripfront,
|
||||
int noexpiredabove, uint8_t* expiretop, size_t expiretoplen)
|
||||
{
|
||||
struct ub_packed_rrset_key *rrset;
|
||||
uint8_t lablen;
|
||||
@@ -212,8 +260,40 @@ find_closest_of_type(struct module_env* env, uint8_t* qname, size_t qnamelen,
|
||||
/* snip off front part of qname until the type is found */
|
||||
while(qnamelen > 0) {
|
||||
if((rrset = rrset_cache_lookup(env->rrset_cache, qname,
|
||||
qnamelen, searchtype, qclass, 0, now, 0)))
|
||||
return rrset;
|
||||
qnamelen, searchtype, qclass, 0, now, 0))) {
|
||||
uint8_t* origqname = qname;
|
||||
size_t origqnamelen = qnamelen;
|
||||
if(!noexpiredabove)
|
||||
return rrset;
|
||||
/* if expiretop set, do not look above it, but
|
||||
* qname is equal, so the just found result is also
|
||||
* the nonexpired above part. */
|
||||
if(expiretop && qnamelen == expiretoplen &&
|
||||
query_dname_compare(qname, expiretop)==0)
|
||||
return rrset;
|
||||
/* check for expiry, but we have to let go of the rrset
|
||||
* for the lock ordering */
|
||||
lock_rw_unlock(&rrset->entry.lock);
|
||||
/* the expired_above function always takes off one
|
||||
* label (if qnamelen>0) and returns the final qname
|
||||
* where it searched, so we can continue from there
|
||||
* turning the O N*N search into O N. */
|
||||
if(!rrset_expired_above(env, &qname, &qnamelen,
|
||||
searchtype, qclass, now, expiretop,
|
||||
expiretoplen)) {
|
||||
/* we want to return rrset, but it may be
|
||||
* gone from cache, if so, just loop like
|
||||
* it was not in the cache in the first place.
|
||||
*/
|
||||
if((rrset = rrset_cache_lookup(env->
|
||||
rrset_cache, origqname, origqnamelen,
|
||||
searchtype, qclass, 0, now, 0))) {
|
||||
return rrset;
|
||||
}
|
||||
}
|
||||
log_nametypeclass(VERB_ALGO, "ignoring rrset because expired rrsets exist above it", origqname, searchtype, qclass);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* snip off front label */
|
||||
lablen = *qname;
|
||||
@@ -324,6 +404,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) {
|
||||
@@ -428,6 +511,7 @@ dns_msg_create(uint8_t* qname, size_t qnamelen, uint16_t qtype,
|
||||
return NULL; /* integer overflow protection */
|
||||
msg->rep->flags = BIT_QR; /* with QR, no AA */
|
||||
msg->rep->qdcount = 1;
|
||||
msg->rep->reason_bogus = LDNS_EDE_NONE;
|
||||
msg->rep->rrsets = (struct ub_packed_rrset_key**)
|
||||
regional_alloc(region,
|
||||
capacity*sizeof(struct ub_packed_rrset_key*));
|
||||
@@ -461,7 +545,8 @@ dns_msg_ansadd(struct dns_msg* msg, struct regional* region,
|
||||
struct delegpt*
|
||||
dns_cache_find_delegation(struct module_env* env, uint8_t* qname,
|
||||
size_t qnamelen, uint16_t qtype, uint16_t qclass,
|
||||
struct regional* region, struct dns_msg** msg, time_t now)
|
||||
struct regional* region, struct dns_msg** msg, time_t now,
|
||||
int noexpiredabove, uint8_t* expiretop, size_t expiretoplen)
|
||||
{
|
||||
/* try to find closest NS rrset */
|
||||
struct ub_packed_rrset_key* nskey;
|
||||
@@ -469,7 +554,7 @@ dns_cache_find_delegation(struct module_env* env, uint8_t* qname,
|
||||
struct delegpt* dp;
|
||||
|
||||
nskey = find_closest_of_type(env, qname, qnamelen, qclass, now,
|
||||
LDNS_RR_TYPE_NS, 0);
|
||||
LDNS_RR_TYPE_NS, 0, noexpiredabove, expiretop, expiretoplen);
|
||||
if(!nskey) /* hope the caller has hints to prime or something */
|
||||
return NULL;
|
||||
nsdata = (struct packed_rrset_data*)nskey->entry.data;
|
||||
@@ -524,6 +609,7 @@ gen_dns_msg(struct regional* region, struct query_info* q, size_t num)
|
||||
sizeof(struct reply_info) - sizeof(struct rrset_ref));
|
||||
if(!msg->rep)
|
||||
return NULL;
|
||||
msg->rep->reason_bogus = LDNS_EDE_NONE;
|
||||
if(num > RR_COUNT_MAX)
|
||||
return NULL; /* integer overflow protection */
|
||||
msg->rep->rrsets = (struct ub_packed_rrset_key**)
|
||||
@@ -577,6 +663,7 @@ tomsg(struct module_env* env, struct query_info* q, struct reply_info* r,
|
||||
msg->rep->ar_numrrsets = r->ar_numrrsets;
|
||||
msg->rep->rrset_count = r->rrset_count;
|
||||
msg->rep->authoritative = r->authoritative;
|
||||
msg->rep->reason_bogus = r->reason_bogus;
|
||||
if(!rrset_array_lock(r->ref, r->rrset_count, now_control)) {
|
||||
return NULL;
|
||||
}
|
||||
@@ -632,6 +719,7 @@ rrset_msg(struct ub_packed_rrset_key* rrset, struct regional* region,
|
||||
msg->rep->ns_numrrsets = 0;
|
||||
msg->rep->ar_numrrsets = 0;
|
||||
msg->rep->rrset_count = 1;
|
||||
msg->rep->reason_bogus = LDNS_EDE_NONE;
|
||||
msg->rep->rrsets[0] = packed_rrset_copy_region(rrset, region, now);
|
||||
if(!msg->rep->rrsets[0]) /* copy CNAME */
|
||||
return NULL;
|
||||
@@ -670,6 +758,7 @@ synth_dname_msg(struct ub_packed_rrset_key* rrset, struct regional* region,
|
||||
msg->rep->ns_numrrsets = 0;
|
||||
msg->rep->ar_numrrsets = 0;
|
||||
msg->rep->rrset_count = 1;
|
||||
msg->rep->reason_bogus = LDNS_EDE_NONE;
|
||||
msg->rep->rrsets[0] = packed_rrset_copy_region(rrset, region, now);
|
||||
if(!msg->rep->rrsets[0]) /* copy DNAME */
|
||||
return NULL;
|
||||
@@ -835,7 +924,7 @@ dns_cache_lookup(struct module_env* env,
|
||||
* consistent with the DNAME */
|
||||
if(!no_partial &&
|
||||
(rrset=find_closest_of_type(env, qname, qnamelen, qclass, now,
|
||||
LDNS_RR_TYPE_DNAME, 1))) {
|
||||
LDNS_RR_TYPE_DNAME, 1, 0, NULL, 0))) {
|
||||
/* synthesize a DNAME+CNAME message based on this */
|
||||
enum sec_status sec_status = sec_status_unchecked;
|
||||
struct dns_msg* msg = synth_dname_msg(rrset, region, now, &k,
|
||||
@@ -968,7 +1057,7 @@ dns_cache_lookup(struct module_env* env,
|
||||
int
|
||||
dns_cache_store(struct module_env* env, struct query_info* msgqinf,
|
||||
struct reply_info* msgrep, int is_referral, time_t leeway, int pside,
|
||||
struct regional* region, uint32_t flags)
|
||||
struct regional* region, uint32_t flags, time_t qstarttime)
|
||||
{
|
||||
struct reply_info* rep = NULL;
|
||||
/* alloc, malloc properly (not in region, like msg is) */
|
||||
@@ -991,9 +1080,9 @@ dns_cache_store(struct module_env* env, struct query_info* msgqinf,
|
||||
/*ignore ret: it was in the cache, ref updated */
|
||||
/* no leeway for typeNS */
|
||||
(void)rrset_cache_update(env->rrset_cache, &ref,
|
||||
env->alloc, *env->now +
|
||||
env->alloc,
|
||||
((ntohs(ref.key->rk.type)==LDNS_RR_TYPE_NS
|
||||
&& !pside) ? 0:leeway));
|
||||
&& !pside) ? qstarttime:*env->now + leeway));
|
||||
}
|
||||
free(rep);
|
||||
return 1;
|
||||
@@ -1015,7 +1104,7 @@ dns_cache_store(struct module_env* env, struct query_info* msgqinf,
|
||||
rep->flags &= ~(BIT_AA | BIT_CD);
|
||||
h = query_info_hash(&qinf, (uint16_t)flags);
|
||||
dns_cache_store_msg(env, &qinf, h, rep, leeway, pside, msgrep,
|
||||
flags, region);
|
||||
flags, region, qstarttime);
|
||||
/* qname is used inside query_info_entrysetup, and set to
|
||||
* NULL. If it has not been used, free it. free(0) is safe. */
|
||||
free(qinf.qname);
|
||||
|
||||
Vendored
+15
-3
@@ -88,11 +88,13 @@ struct dns_msg {
|
||||
* @param flags: flags with BIT_CD for AAAA queries in dns64 translation.
|
||||
* The higher 16 bits are used internally to customize the cache policy.
|
||||
* (See DNSCACHE_STORE_xxx flags).
|
||||
* @param qstarttime: time when the query was started, and thus when the
|
||||
* delegations were looked up.
|
||||
* @return 0 on alloc error (out of memory).
|
||||
*/
|
||||
int dns_cache_store(struct module_env* env, struct query_info* qinf,
|
||||
struct reply_info* rep, int is_referral, time_t leeway, int pside,
|
||||
struct regional* region, uint32_t flags);
|
||||
struct regional* region, uint32_t flags, time_t qstarttime);
|
||||
|
||||
/**
|
||||
* Store message in the cache. Stores in message cache and rrset cache.
|
||||
@@ -112,11 +114,14 @@ int dns_cache_store(struct module_env* env, struct query_info* qinf,
|
||||
* can be updated to full TTL even in prefetch situations.
|
||||
* @param qrep: message that can be altered with better rrs from cache.
|
||||
* @param flags: customization flags for the cache policy.
|
||||
* @param qstarttime: time when the query was started, and thus when the
|
||||
* delegations were looked up.
|
||||
* @param region: to allocate into for qmsg.
|
||||
*/
|
||||
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,
|
||||
struct reply_info* qrep, uint32_t flags, struct regional* region);
|
||||
struct reply_info* qrep, uint32_t flags, struct regional* region,
|
||||
time_t qstarttime);
|
||||
|
||||
/**
|
||||
* Find a delegation from the cache.
|
||||
@@ -129,11 +134,18 @@ void dns_cache_store_msg(struct module_env* env, struct query_info* qinfo,
|
||||
* @param msg: if not NULL, delegation message is returned here, synthesized
|
||||
* from the cache.
|
||||
* @param timenow: the time now, for checking if TTL on cache entries is OK.
|
||||
* @param noexpiredabove: if set, no expired NS rrsets above the one found
|
||||
* are tolerated. It only returns delegations where the delegations above
|
||||
* it are valid.
|
||||
* @param expiretop: if not NULL, name where check for expiry ends for
|
||||
* noexpiredabove.
|
||||
* @param expiretoplen: length of expiretop dname.
|
||||
* @return new delegation or NULL on error or if not found in cache.
|
||||
*/
|
||||
struct delegpt* dns_cache_find_delegation(struct module_env* env,
|
||||
uint8_t* qname, size_t qnamelen, uint16_t qtype, uint16_t qclass,
|
||||
struct regional* region, struct dns_msg** msg, time_t timenow);
|
||||
struct regional* region, struct dns_msg** msg, time_t timenow,
|
||||
int noexpiredabove, uint8_t* expiretop, size_t expiretoplen);
|
||||
|
||||
/**
|
||||
* generate dns_msg from cached message
|
||||
|
||||
Vendored
+65
-40
@@ -721,13 +721,13 @@ infra_get_lame_rtt(struct infra_cache* infra,
|
||||
else *rtt = USEFUL_SERVER_TOP_TIMEOUT-1000;
|
||||
}
|
||||
}
|
||||
/* expired entry */
|
||||
if(timenow > host->ttl) {
|
||||
/* expired entry */
|
||||
|
||||
/* see if this can be a re-probe of an unresponsive server */
|
||||
/* minus 1000 because that is outside of the RTTBAND, so
|
||||
* blacklisted servers stay blacklisted if this is chosen */
|
||||
if(host->rtt.rto >= USEFUL_SERVER_TOP_TIMEOUT ||
|
||||
infra->infra_keep_probing) {
|
||||
if(host->rtt.rto >= USEFUL_SERVER_TOP_TIMEOUT) {
|
||||
lock_rw_unlock(&e->lock);
|
||||
*rtt = USEFUL_SERVER_TOP_TIMEOUT-1000;
|
||||
*lame = 0;
|
||||
@@ -834,14 +834,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 +875,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 +885,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;
|
||||
@@ -898,8 +896,9 @@ static void infra_ip_create_ratedata(struct infra_cache* infra,
|
||||
slabhash_insert(infra->client_ip_rates, h, &k->entry, d, NULL);
|
||||
}
|
||||
|
||||
/** find the second and return its rate counter, if none, remove oldest */
|
||||
static int* infra_rate_find_second(void* data, time_t t)
|
||||
/** Find the second and return its rate counter. If none and should_add, remove
|
||||
* oldest to accommodate. Else return none. */
|
||||
static int* infra_rate_find_second_or_none(void* data, time_t t, int should_add)
|
||||
{
|
||||
struct rate_data* d = (struct rate_data*)data;
|
||||
int i, oldest;
|
||||
@@ -907,6 +906,7 @@ static int* infra_rate_find_second(void* data, time_t t)
|
||||
if(d->timestamp[i] == t)
|
||||
return &(d->qps[i]);
|
||||
}
|
||||
if(!should_add) return NULL;
|
||||
/* remove oldest timestamp, and insert it at t with 0 qps */
|
||||
oldest = 0;
|
||||
for(i=0; i<RATE_WINDOW; i++) {
|
||||
@@ -918,21 +918,41 @@ static int* infra_rate_find_second(void* data, time_t t)
|
||||
return &(d->qps[oldest]);
|
||||
}
|
||||
|
||||
int infra_rate_max(void* data, time_t now)
|
||||
/** find the second and return its rate counter, if none, remove oldest to
|
||||
* accommodate */
|
||||
static int* infra_rate_give_second(void* data, time_t t)
|
||||
{
|
||||
return infra_rate_find_second_or_none(data, t, 1);
|
||||
}
|
||||
|
||||
/** find the second and return its rate counter only if it exists. Caller
|
||||
* should check for NULL return value */
|
||||
static int* infra_rate_get_second(void* data, time_t t)
|
||||
{
|
||||
return infra_rate_find_second_or_none(data, t, 0);
|
||||
}
|
||||
|
||||
int infra_rate_max(void* data, time_t now, int backoff)
|
||||
{
|
||||
struct rate_data* d = (struct rate_data*)data;
|
||||
int i, max = 0;
|
||||
for(i=0; i<RATE_WINDOW; i++) {
|
||||
if(now-d->timestamp[i] <= RATE_WINDOW) {
|
||||
if(d->qps[i] > max)
|
||||
if(backoff) {
|
||||
if(now-d->timestamp[i] <= RATE_WINDOW &&
|
||||
d->qps[i] > max) {
|
||||
max = d->qps[i];
|
||||
}
|
||||
} else {
|
||||
if(now == d->timestamp[i]) {
|
||||
return d->qps[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
return max;
|
||||
}
|
||||
|
||||
int infra_ratelimit_inc(struct infra_cache* infra, uint8_t* name,
|
||||
size_t namelen, time_t timenow, struct query_info* qinfo,
|
||||
size_t namelen, time_t timenow, int backoff, struct query_info* qinfo,
|
||||
struct comm_reply* replylist)
|
||||
{
|
||||
int lim, max;
|
||||
@@ -949,13 +969,13 @@ int infra_ratelimit_inc(struct infra_cache* infra, uint8_t* name,
|
||||
/* find or insert ratedata */
|
||||
entry = infra_find_ratedata(infra, name, namelen, 1);
|
||||
if(entry) {
|
||||
int premax = infra_rate_max(entry->data, timenow);
|
||||
int* cur = infra_rate_find_second(entry->data, timenow);
|
||||
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);
|
||||
max = infra_rate_max(entry->data, timenow, backoff);
|
||||
lock_rw_unlock(&entry->lock);
|
||||
|
||||
if(premax < lim && max >= lim) {
|
||||
if(premax <= lim && max > lim) {
|
||||
char buf[257], qnm[257], ts[12], cs[12], ip[128];
|
||||
dname_str(name, buf);
|
||||
dname_str(qinfo->qname, qnm);
|
||||
@@ -963,19 +983,19 @@ 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);
|
||||
}
|
||||
}
|
||||
return (max < lim);
|
||||
return (max <= lim);
|
||||
}
|
||||
|
||||
/* create */
|
||||
infra_create_ratedata(infra, name, namelen, timenow);
|
||||
return (1 < lim);
|
||||
return (1 <= lim);
|
||||
}
|
||||
|
||||
void infra_ratelimit_dec(struct infra_cache* infra, uint8_t* name,
|
||||
@@ -987,14 +1007,19 @@ void infra_ratelimit_dec(struct infra_cache* infra, uint8_t* name,
|
||||
return; /* not enabled */
|
||||
entry = infra_find_ratedata(infra, name, namelen, 1);
|
||||
if(!entry) return; /* not cached */
|
||||
cur = infra_rate_find_second(entry->data, timenow);
|
||||
cur = infra_rate_get_second(entry->data, timenow);
|
||||
if(cur == NULL) {
|
||||
/* our timenow is not available anymore; nothing to decrease */
|
||||
lock_rw_unlock(&entry->lock);
|
||||
return;
|
||||
}
|
||||
if((*cur) > 0)
|
||||
(*cur)--;
|
||||
lock_rw_unlock(&entry->lock);
|
||||
}
|
||||
|
||||
int infra_ratelimit_exceeded(struct infra_cache* infra, uint8_t* name,
|
||||
size_t namelen, time_t timenow)
|
||||
size_t namelen, time_t timenow, int backoff)
|
||||
{
|
||||
struct lruhash_entry* entry;
|
||||
int lim, max;
|
||||
@@ -1010,10 +1035,10 @@ int infra_ratelimit_exceeded(struct infra_cache* infra, uint8_t* name,
|
||||
entry = infra_find_ratedata(infra, name, namelen, 0);
|
||||
if(!entry)
|
||||
return 0; /* not cached */
|
||||
max = infra_rate_max(entry->data, timenow);
|
||||
max = infra_rate_max(entry->data, timenow, backoff);
|
||||
lock_rw_unlock(&entry->lock);
|
||||
|
||||
return (max >= lim);
|
||||
return (max > lim);
|
||||
}
|
||||
|
||||
size_t
|
||||
@@ -1027,7 +1052,8 @@ infra_get_mem(struct infra_cache* infra)
|
||||
}
|
||||
|
||||
int infra_ip_ratelimit_inc(struct infra_cache* infra,
|
||||
struct comm_reply* repinfo, time_t timenow, struct sldns_buffer* buffer)
|
||||
struct sockaddr_storage* addr, socklen_t addrlen, time_t timenow,
|
||||
int backoff, struct sldns_buffer* buffer)
|
||||
{
|
||||
int max;
|
||||
struct lruhash_entry* entry;
|
||||
@@ -1037,18 +1063,17 @@ 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);
|
||||
int* cur = infra_rate_find_second(entry->data, timenow);
|
||||
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);
|
||||
max = infra_rate_max(entry->data, timenow, backoff);
|
||||
lock_rw_unlock(&entry->lock);
|
||||
|
||||
if(premax < infra_ip_ratelimit && max >= infra_ip_ratelimit) {
|
||||
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));
|
||||
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) {
|
||||
@@ -1073,6 +1098,6 @@ int infra_ip_ratelimit_inc(struct infra_cache* infra,
|
||||
}
|
||||
|
||||
/* create */
|
||||
infra_ip_create_ratedata(infra, repinfo, timenow);
|
||||
infra_ip_create_ratedata(infra, addr, addrlen, timenow);
|
||||
return 1;
|
||||
}
|
||||
|
||||
Vendored
+12
-7
@@ -368,6 +368,7 @@ long long infra_get_host_rto(struct infra_cache* infra,
|
||||
* @param name: zone name
|
||||
* @param namelen: zone name length
|
||||
* @param timenow: what time it is now.
|
||||
* @param backoff: if backoff is enabled.
|
||||
* @param qinfo: for logging, query name.
|
||||
* @param replylist: for logging, querier's address (if any).
|
||||
* @return 1 if it could be incremented. 0 if the increment overshot the
|
||||
@@ -375,7 +376,7 @@ long long infra_get_host_rto(struct infra_cache* infra,
|
||||
* Failures like alloc failures are not returned (probably as 1).
|
||||
*/
|
||||
int infra_ratelimit_inc(struct infra_cache* infra, uint8_t* name,
|
||||
size_t namelen, time_t timenow, struct query_info* qinfo,
|
||||
size_t namelen, time_t timenow, int backoff, struct query_info* qinfo,
|
||||
struct comm_reply* replylist);
|
||||
|
||||
/**
|
||||
@@ -398,13 +399,15 @@ void infra_ratelimit_dec(struct infra_cache* infra, uint8_t* name,
|
||||
* @param name: zone name
|
||||
* @param namelen: zone name length
|
||||
* @param timenow: what time it is now.
|
||||
* @param backoff: if backoff is enabled.
|
||||
* @return true if exceeded.
|
||||
*/
|
||||
int infra_ratelimit_exceeded(struct infra_cache* infra, uint8_t* name,
|
||||
size_t namelen, time_t timenow);
|
||||
size_t namelen, time_t timenow, int backoff);
|
||||
|
||||
/** find the maximum rate stored, not too old. 0 if no information. */
|
||||
int infra_rate_max(void* data, time_t now);
|
||||
/** find the maximum rate stored. 0 if no information.
|
||||
* When backoff is enabled look for the maximum in the whole RATE_WINDOW. */
|
||||
int infra_rate_max(void* data, time_t now, int backoff);
|
||||
|
||||
/** find the ratelimit in qps for a domain. 0 if no limit for domain. */
|
||||
int infra_find_ratelimit(struct infra_cache* infra, uint8_t* name,
|
||||
@@ -413,14 +416,16 @@ 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 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,
|
||||
struct sldns_buffer* buffer);
|
||||
struct sockaddr_storage* addr, socklen_t addrlen, time_t timenow,
|
||||
int backoff, struct sldns_buffer* buffer);
|
||||
|
||||
/**
|
||||
* Get memory used by the infra cache.
|
||||
|
||||
+187
-62
@@ -47,6 +47,7 @@
|
||||
#ifdef USE_TCP_FASTOPEN
|
||||
#include <netinet/tcp.h>
|
||||
#endif
|
||||
#include <ctype.h>
|
||||
#include "services/listen_dnsport.h"
|
||||
#include "services/outside_network.h"
|
||||
#include "util/netevent.h"
|
||||
@@ -123,12 +124,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));
|
||||
}
|
||||
}
|
||||
@@ -139,7 +140,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");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -457,7 +460,14 @@ 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,
|
||||
(void*)&val, (socklen_t)sizeof(val)) < 0) {
|
||||
@@ -489,6 +499,7 @@ create_udp_sock(int family, int socktype, struct sockaddr* addr,
|
||||
return -1;
|
||||
}
|
||||
# elif defined(IPV6_MTU)
|
||||
# ifndef USE_WINSOCK
|
||||
/*
|
||||
* On Linux, to send no larger than 1280, the PMTUD is
|
||||
* disabled by default for datagrams anyway, so we set
|
||||
@@ -496,13 +507,29 @@ create_udp_sock(int family, int socktype, struct sockaddr* addr,
|
||||
*/
|
||||
if (setsockopt(s, IPPROTO_IPV6, IPV6_MTU,
|
||||
(void*)&mtu, (socklen_t)sizeof(mtu)) < 0) {
|
||||
log_err("setsockopt(..., IPV6_MTU, ...) failed: %s",
|
||||
log_err("setsockopt(..., IPV6_MTU, ...) failed: %s",
|
||||
sock_strerror(errno));
|
||||
sock_close(s);
|
||||
*noproto = 0;
|
||||
*inuse = 0;
|
||||
return -1;
|
||||
}
|
||||
# elif defined(IPV6_USER_MTU)
|
||||
/* As later versions of the mingw crosscompiler define
|
||||
* IPV6_MTU, do the same for windows but use IPV6_USER_MTU
|
||||
* instead which is writable; IPV6_MTU is readonly there. */
|
||||
if (setsockopt(s, IPPROTO_IPV6, IPV6_USER_MTU,
|
||||
(void*)&mtu, (socklen_t)sizeof(mtu)) < 0) {
|
||||
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 */
|
||||
# if defined(IPV6_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT)
|
||||
# if defined(IP_PMTUDISC_OMIT)
|
||||
@@ -758,7 +785,14 @@ 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(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",
|
||||
@@ -1014,6 +1048,7 @@ 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;
|
||||
}
|
||||
@@ -1058,11 +1093,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));
|
||||
@@ -1071,6 +1108,7 @@ 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;
|
||||
@@ -1157,7 +1195,7 @@ if_is_ssl(const char* ifname, const char* port, int ssl_port,
|
||||
* @param do_auto: use automatic interface detection.
|
||||
* If enabled, then ifname must be the wildcard name.
|
||||
* @param do_udp: if udp should be used.
|
||||
* @param do_tcp: if udp should be used.
|
||||
* @param do_tcp: if tcp should be used.
|
||||
* @param hints: for getaddrinfo. family and flags have to be set by caller.
|
||||
* @param port: Port number to use (as string).
|
||||
* @param list: list of open ports, appended to, changed to point to list head.
|
||||
@@ -1166,6 +1204,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.
|
||||
@@ -1178,34 +1217,39 @@ if_is_ssl(const char* ifname, const char* port, int ssl_port,
|
||||
* @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 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);
|
||||
@@ -1223,8 +1267,9 @@ ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp,
|
||||
free(ub_sock);
|
||||
return 0;
|
||||
}
|
||||
if(!port_insert(list, s,
|
||||
is_dnscrypt?listen_type_udpancil_dnscrypt:listen_type_udpancil, ub_sock)) {
|
||||
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);
|
||||
free(ub_sock);
|
||||
@@ -1235,7 +1280,7 @@ 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);
|
||||
@@ -1246,8 +1291,9 @@ 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(!port_insert(list, s, is_dnscrypt
|
||||
?listen_type_udp_dnscrypt:listen_type_udp,
|
||||
is_pp2, ub_sock)) {
|
||||
sock_close(s);
|
||||
freeaddrinfo(ub_sock->addr);
|
||||
free(ub_sock);
|
||||
@@ -1269,7 +1315,7 @@ 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);
|
||||
@@ -1282,7 +1328,7 @@ ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp,
|
||||
}
|
||||
if(is_ssl)
|
||||
verbose(VERB_ALGO, "setup TCP for SSL service");
|
||||
if(!port_insert(list, s, port_type, ub_sock)) {
|
||||
if(!port_insert(list, s, port_type, is_pp2, ub_sock)) {
|
||||
sock_close(s);
|
||||
freeaddrinfo(ub_sock->addr);
|
||||
free(ub_sock);
|
||||
@@ -1369,40 +1415,42 @@ listen_create(struct comm_base* base, struct listen_port* ports,
|
||||
while(ports) {
|
||||
struct comm_point* cp = NULL;
|
||||
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);
|
||||
else if(ports->ftype == listen_type_tcp ||
|
||||
ports->ftype == listen_type_tcp_dnscrypt)
|
||||
cp = comm_point_create_tcp(base, ports->fd,
|
||||
ports->ftype == listen_type_udp_dnscrypt) {
|
||||
cp = comm_point_create_udp(base, ports->fd,
|
||||
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);
|
||||
else if(ports->ftype == listen_type_ssl ||
|
||||
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,
|
||||
cp = comm_point_create_tcp(base, ports->fd,
|
||||
tcp_accept_count, tcp_idle_timeout,
|
||||
harden_large_queries,
|
||||
http_max_streams, http_endpoint,
|
||||
tcp_conn_limit, bufsize, front->udp_buff,
|
||||
ports->ftype, cb, cb_arg, ports->socket);
|
||||
if(http_notls && ports->ftype == listen_type_http)
|
||||
cp->ssl = NULL;
|
||||
else
|
||||
cp->ssl = sslctx;
|
||||
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 no TLS "
|
||||
"tls-service-key or tls-service-pem "
|
||||
"set");
|
||||
log_warn("HTTPS port configured, but "
|
||||
"no TLS tls-service-key or "
|
||||
"tls-service-pem set");
|
||||
}
|
||||
#ifndef HAVE_SSL_CTX_SET_ALPN_SELECT_CB
|
||||
if(!http_notls)
|
||||
log_warn("Unbound is not compiled with an "
|
||||
"OpenSSL version supporting ALPN "
|
||||
" (OpenSSL >= 1.0.2). This is required "
|
||||
"to use DNS-over-HTTPS");
|
||||
if(!http_notls) {
|
||||
log_warn("Unbound is not compiled "
|
||||
"with an OpenSSL version "
|
||||
"supporting ALPN "
|
||||
"(OpenSSL >= 1.0.2). This "
|
||||
"is required to use "
|
||||
"DNS-over-HTTPS");
|
||||
}
|
||||
#endif
|
||||
#ifndef HAVE_NGHTTP2_NGHTTP2_H
|
||||
log_warn("Unbound is not compiled with "
|
||||
@@ -1411,14 +1459,26 @@ listen_create(struct comm_base* base, struct listen_port* ports,
|
||||
#endif
|
||||
}
|
||||
} 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);
|
||||
ports->ftype == listen_type_udpancil_dnscrypt) {
|
||||
cp = comm_point_create_udp_ancil(base, ports->fd,
|
||||
front->udp_buff, ports->pp2_enabled, cb,
|
||||
cb_arg, ports->socket);
|
||||
}
|
||||
if(!cp) {
|
||||
log_err("can't create commpoint");
|
||||
log_err("can't create commpoint");
|
||||
listen_delete(front);
|
||||
return NULL;
|
||||
}
|
||||
if((http_notls && ports->ftype == listen_type_http) ||
|
||||
(ports->ftype == listen_type_tcp) ||
|
||||
(ports->ftype == listen_type_udp) ||
|
||||
(ports->ftype == listen_type_udpancil) ||
|
||||
(ports->ftype == listen_type_tcp_dnscrypt) ||
|
||||
(ports->ftype == listen_type_udp_dnscrypt) ||
|
||||
(ports->ftype == listen_type_udpancil_dnscrypt))
|
||||
cp->ssl = NULL;
|
||||
else
|
||||
cp->ssl = sslctx;
|
||||
cp->dtenv = dtenv;
|
||||
cp->do_not_close = 1;
|
||||
#ifdef USE_DNSCRYPT
|
||||
@@ -1674,7 +1734,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)
|
||||
{
|
||||
@@ -1706,14 +1766,76 @@ listening_ports_open(struct config_file* cfg, char** ifs, int num_ifs,
|
||||
}
|
||||
/* create ip4 and ip6 ports so that return addresses are nice. */
|
||||
if(do_auto || num_ifs == 0) {
|
||||
if(do_auto && cfg->if_automatic_ports &&
|
||||
cfg->if_automatic_ports[0]!=0) {
|
||||
char* now = cfg->if_automatic_ports;
|
||||
while(now && *now) {
|
||||
char* after;
|
||||
int extraport;
|
||||
while(isspace((unsigned char)*now))
|
||||
now++;
|
||||
if(!*now)
|
||||
break;
|
||||
after = now;
|
||||
extraport = (int)strtol(now, &after, 10);
|
||||
if(extraport < 0 || extraport > 65535) {
|
||||
log_err("interface-automatic-ports port number out of range, at position %d of '%s'", (int)(now-cfg->if_automatic_ports)+1, cfg->if_automatic_ports);
|
||||
listening_ports_free(list);
|
||||
return NULL;
|
||||
}
|
||||
if(extraport == 0 && now == after) {
|
||||
log_err("interface-automatic-ports could not be parsed, at position %d of '%s'", (int)(now-cfg->if_automatic_ports)+1, cfg->if_automatic_ports);
|
||||
listening_ports_free(list);
|
||||
return NULL;
|
||||
}
|
||||
now = after;
|
||||
snprintf(portbuf, sizeof(portbuf), "%d", extraport);
|
||||
if(do_ip6) {
|
||||
hints.ai_family = AF_INET6;
|
||||
if(!ports_create_if("::0",
|
||||
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,
|
||||
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)) {
|
||||
listening_ports_free(list);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
if(do_ip4) {
|
||||
hints.ai_family = AF_INET;
|
||||
if(!ports_create_if("0.0.0.0",
|
||||
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,
|
||||
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)) {
|
||||
listening_ports_free(list);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
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)) {
|
||||
@@ -1723,12 +1845,13 @@ listening_ports_open(struct config_file* cfg, char** ifs, int num_ifs,
|
||||
}
|
||||
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)) {
|
||||
@@ -1742,10 +1865,11 @@ 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)) {
|
||||
@@ -1757,10 +1881,11 @@ 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)) {
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
|
||||
+96
-44
@@ -56,6 +56,44 @@
|
||||
* with 16 bytes for an A record, a 64K packet has about 4000 max */
|
||||
#define LOCALZONE_RRSET_COUNT_MAX 4096
|
||||
|
||||
/** print all RRsets in local zone */
|
||||
static void
|
||||
local_zone_out(struct local_zone* z)
|
||||
{
|
||||
struct local_data* d;
|
||||
struct local_rrset* p;
|
||||
RBTREE_FOR(d, struct local_data*, &z->data) {
|
||||
for(p = d->rrsets; p; p = p->next) {
|
||||
log_nametypeclass(NO_VERBOSE, "rrset", d->name,
|
||||
ntohs(p->rrset->rk.type),
|
||||
ntohs(p->rrset->rk.rrset_class));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
local_zone_print(struct local_zone* z)
|
||||
{
|
||||
char buf[64];
|
||||
lock_rw_rdlock(&z->lock);
|
||||
snprintf(buf, sizeof(buf), "%s zone",
|
||||
local_zone_type2str(z->type));
|
||||
log_nametypeclass(NO_VERBOSE, buf, z->name, 0, z->dclass);
|
||||
local_zone_out(z);
|
||||
lock_rw_unlock(&z->lock);
|
||||
}
|
||||
|
||||
void local_zones_print(struct local_zones* zones)
|
||||
{
|
||||
struct local_zone* z;
|
||||
lock_rw_rdlock(&zones->lock);
|
||||
log_info("number of auth zones %u", (unsigned)zones->ztree.count);
|
||||
RBTREE_FOR(z, struct local_zone*, &zones->ztree) {
|
||||
local_zone_print(z);
|
||||
}
|
||||
lock_rw_unlock(&zones->lock);
|
||||
}
|
||||
|
||||
struct local_zones*
|
||||
local_zones_create(void)
|
||||
{
|
||||
@@ -1010,6 +1048,38 @@ lz_setup_implicit(struct local_zones* zones, struct config_file* cfg)
|
||||
lock_rw_rdlock(&zones->lock);
|
||||
if(!local_zones_lookup(zones, rr_name, len, labs, rr_class,
|
||||
rr_type)) {
|
||||
/* Check if there is a zone that this could go
|
||||
* under but for different class; created zones are
|
||||
* always for LDNS_RR_CLASS_IN. Create the zone with
|
||||
* a different class but the same configured
|
||||
* local_zone_type. */
|
||||
struct local_zone* z = local_zones_lookup(zones,
|
||||
rr_name, len, labs, LDNS_RR_CLASS_IN, rr_type);
|
||||
if(z) {
|
||||
uint8_t* name = memdup(z->name, z->namelen);
|
||||
size_t znamelen = z->namelen;
|
||||
int znamelabs = z->namelabs;
|
||||
enum localzone_type ztype = z->type;
|
||||
lock_rw_unlock(&zones->lock);
|
||||
if(!name) {
|
||||
log_err("out of memory");
|
||||
free(rr_name);
|
||||
return 0;
|
||||
}
|
||||
if(!(
|
||||
#ifndef THREADS_DISABLED
|
||||
z =
|
||||
#endif
|
||||
lz_enter_zone_dname(zones, name,
|
||||
znamelen, znamelabs,
|
||||
ztype, rr_class))) {
|
||||
free(rr_name);
|
||||
return 0;
|
||||
}
|
||||
lock_rw_unlock(&z->lock);
|
||||
free(rr_name);
|
||||
continue;
|
||||
}
|
||||
if(!have_name) {
|
||||
dclass = rr_class;
|
||||
nm = rr_name;
|
||||
@@ -1220,38 +1290,6 @@ local_zones_find_le(struct local_zones* zones,
|
||||
return (struct local_zone*)node;
|
||||
}
|
||||
|
||||
/** print all RRsets in local zone */
|
||||
static void
|
||||
local_zone_out(struct local_zone* z)
|
||||
{
|
||||
struct local_data* d;
|
||||
struct local_rrset* p;
|
||||
RBTREE_FOR(d, struct local_data*, &z->data) {
|
||||
for(p = d->rrsets; p; p = p->next) {
|
||||
log_nametypeclass(NO_VERBOSE, "rrset", d->name,
|
||||
ntohs(p->rrset->rk.type),
|
||||
ntohs(p->rrset->rk.rrset_class));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void local_zones_print(struct local_zones* zones)
|
||||
{
|
||||
struct local_zone* z;
|
||||
lock_rw_rdlock(&zones->lock);
|
||||
log_info("number of auth zones %u", (unsigned)zones->ztree.count);
|
||||
RBTREE_FOR(z, struct local_zone*, &zones->ztree) {
|
||||
char buf[64];
|
||||
lock_rw_rdlock(&z->lock);
|
||||
snprintf(buf, sizeof(buf), "%s zone",
|
||||
local_zone_type2str(z->type));
|
||||
log_nametypeclass(NO_VERBOSE, buf, z->name, 0, z->dclass);
|
||||
local_zone_out(z);
|
||||
lock_rw_unlock(&z->lock);
|
||||
}
|
||||
lock_rw_unlock(&zones->lock);
|
||||
}
|
||||
|
||||
/** encode answer consisting of 1 rrset */
|
||||
static int
|
||||
local_encode(struct query_info* qinfo, struct module_env* env,
|
||||
@@ -1290,7 +1328,8 @@ local_encode(struct query_info* qinfo, struct module_env* env,
|
||||
static void
|
||||
local_error_encode(struct query_info* qinfo, struct module_env* env,
|
||||
struct edns_data* edns, struct comm_reply* repinfo, sldns_buffer* buf,
|
||||
struct regional* temp, int rcode, int r)
|
||||
struct regional* temp, int rcode, int r, int ede_code,
|
||||
const char* ede_txt)
|
||||
{
|
||||
edns->edns_version = EDNS_ADVERTISED_VERSION;
|
||||
edns->udp_size = EDNS_ADVERTISED_SIZE;
|
||||
@@ -1300,6 +1339,12 @@ local_error_encode(struct query_info* qinfo, struct module_env* env,
|
||||
if(!inplace_cb_reply_local_call(env, qinfo, NULL, NULL,
|
||||
rcode, edns, repinfo, temp, env->now_tv))
|
||||
edns->opt_list_inplace_cb_out = NULL;
|
||||
|
||||
if(ede_code != LDNS_EDE_NONE && env->cfg->ede) {
|
||||
edns_opt_list_append_ede(&edns->opt_list_out, temp,
|
||||
ede_code, ede_txt);
|
||||
}
|
||||
|
||||
error_encode(buf, r, qinfo, *(uint16_t*)sldns_buffer_begin(buf),
|
||||
sldns_buffer_read_u16_at(buf, 2), edns);
|
||||
}
|
||||
@@ -1497,7 +1542,9 @@ local_data_answer(struct local_zone* z, struct module_env* env,
|
||||
qinfo->local_alias = NULL;
|
||||
local_error_encode(qinfo, env, edns, repinfo,
|
||||
buf, temp, LDNS_RCODE_YXDOMAIN,
|
||||
(LDNS_RCODE_YXDOMAIN|BIT_AA));
|
||||
(LDNS_RCODE_YXDOMAIN|BIT_AA),
|
||||
LDNS_EDE_OTHER,
|
||||
"DNAME expansion became too large");
|
||||
return 1;
|
||||
}
|
||||
memset(&qinfo->local_alias->rrset->entry, 0,
|
||||
@@ -1600,7 +1647,8 @@ local_zones_zone_answer(struct local_zone* z, struct module_env* env,
|
||||
} else if(lz_type == local_zone_refuse
|
||||
|| lz_type == local_zone_always_refuse) {
|
||||
local_error_encode(qinfo, env, edns, repinfo, buf, temp,
|
||||
LDNS_RCODE_REFUSED, (LDNS_RCODE_REFUSED|BIT_AA));
|
||||
LDNS_RCODE_REFUSED, (LDNS_RCODE_REFUSED|BIT_AA),
|
||||
LDNS_EDE_NONE, NULL);
|
||||
return 1;
|
||||
} else if(lz_type == local_zone_static ||
|
||||
lz_type == local_zone_redirect ||
|
||||
@@ -1625,8 +1673,8 @@ local_zones_zone_answer(struct local_zone* z, struct module_env* env,
|
||||
if(z != NULL && z->soa && z->soa_negative)
|
||||
return local_encode(qinfo, env, edns, repinfo, buf, temp,
|
||||
z->soa_negative, 0, rcode);
|
||||
local_error_encode(qinfo, env, edns, repinfo, buf, temp, rcode,
|
||||
(rcode|BIT_AA));
|
||||
local_error_encode(qinfo, env, edns, repinfo, buf, temp,
|
||||
rcode, (rcode|BIT_AA), LDNS_EDE_NONE, NULL);
|
||||
return 1;
|
||||
} else if(lz_type == local_zone_typetransparent
|
||||
|| lz_type == local_zone_always_transparent) {
|
||||
@@ -1667,9 +1715,10 @@ local_zones_zone_answer(struct local_zone* z, struct module_env* env,
|
||||
return local_encode(qinfo, env, edns, repinfo, buf, temp,
|
||||
&lrr, 1, LDNS_RCODE_NOERROR);
|
||||
} else {
|
||||
/* NODATA: No EDE needed */
|
||||
local_error_encode(qinfo, env, edns, repinfo, buf,
|
||||
temp, LDNS_RCODE_NOERROR,
|
||||
(LDNS_RCODE_NOERROR|BIT_AA));
|
||||
(LDNS_RCODE_NOERROR|BIT_AA), -1, NULL);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
@@ -1682,8 +1731,9 @@ local_zones_zone_answer(struct local_zone* z, struct module_env* env,
|
||||
if(z != NULL && z->soa && z->soa_negative)
|
||||
return local_encode(qinfo, env, edns, repinfo, buf, temp,
|
||||
z->soa_negative, 0, rcode);
|
||||
/* NODATA: No EDE needed */
|
||||
local_error_encode(qinfo, env, edns, repinfo, buf, temp, rcode,
|
||||
(rcode|BIT_AA));
|
||||
(rcode|BIT_AA), LDNS_EDE_NONE, NULL);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -1694,13 +1744,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);
|
||||
@@ -1715,7 +1765,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));
|
||||
@@ -1838,7 +1889,8 @@ 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
|
||||
|
||||
+186
-17
@@ -64,6 +64,11 @@
|
||||
#include "respip/respip.h"
|
||||
#include "services/listen_dnsport.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)
|
||||
@@ -458,7 +463,8 @@ mesh_serve_expired_init(struct mesh_state* mstate, int timeout)
|
||||
|
||||
void mesh_new_client(struct mesh_area* mesh, struct query_info* qinfo,
|
||||
struct respip_client_info* cinfo, uint16_t qflags,
|
||||
struct edns_data* edns, struct comm_reply* rep, uint16_t qid)
|
||||
struct edns_data* edns, struct comm_reply* rep, uint16_t qid,
|
||||
int rpz_passthru)
|
||||
{
|
||||
struct mesh_state* s = NULL;
|
||||
int unique = unique_mesh_state(edns->opt_list_in, mesh->env);
|
||||
@@ -513,6 +519,7 @@ void mesh_new_client(struct mesh_area* mesh, struct query_info* qinfo,
|
||||
}
|
||||
if(unique)
|
||||
mesh_state_make_unique(s);
|
||||
s->s.rpz_passthru = rpz_passthru;
|
||||
/* copy the edns options we got from the front */
|
||||
if(edns->opt_list_in) {
|
||||
s->s.edns_opts_front_in = edns_opt_copy_region(edns->opt_list_in,
|
||||
@@ -606,7 +613,7 @@ servfail_mem:
|
||||
int
|
||||
mesh_new_callback(struct mesh_area* mesh, struct query_info* qinfo,
|
||||
uint16_t qflags, struct edns_data* edns, sldns_buffer* buf,
|
||||
uint16_t qid, mesh_cb_func_type cb, void* cb_arg)
|
||||
uint16_t qid, mesh_cb_func_type cb, void* cb_arg, int rpz_passthru)
|
||||
{
|
||||
struct mesh_state* s = NULL;
|
||||
int unique = unique_mesh_state(edns->opt_list_in, mesh->env);
|
||||
@@ -632,6 +639,7 @@ mesh_new_callback(struct mesh_area* mesh, struct query_info* qinfo,
|
||||
}
|
||||
if(unique)
|
||||
mesh_state_make_unique(s);
|
||||
s->s.rpz_passthru = rpz_passthru;
|
||||
if(edns->opt_list_in) {
|
||||
s->s.edns_opts_front_in = edns_opt_copy_region(edns->opt_list_in,
|
||||
s->s.region);
|
||||
@@ -686,7 +694,8 @@ mesh_new_callback(struct mesh_area* mesh, struct query_info* qinfo,
|
||||
* 0 (false), in which case the new state is only made runnable so it
|
||||
* will not be run recursively on top of the current state. */
|
||||
static void mesh_schedule_prefetch(struct mesh_area* mesh,
|
||||
struct query_info* qinfo, uint16_t qflags, time_t leeway, int run)
|
||||
struct query_info* qinfo, uint16_t qflags, time_t leeway, int run,
|
||||
int rpz_passthru)
|
||||
{
|
||||
struct mesh_state* s = mesh_area_find(mesh, NULL, qinfo,
|
||||
qflags&(BIT_RD|BIT_CD), 0, 0);
|
||||
@@ -732,15 +741,16 @@ static void mesh_schedule_prefetch(struct mesh_area* mesh,
|
||||
/* 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;
|
||||
}
|
||||
}
|
||||
s->s.rpz_passthru = rpz_passthru;
|
||||
|
||||
if(!run) {
|
||||
#ifdef UNBOUND_DEBUG
|
||||
@@ -756,10 +766,115 @@ static void mesh_schedule_prefetch(struct mesh_area* mesh,
|
||||
mesh_run(mesh, s, module_event_new, NULL);
|
||||
}
|
||||
|
||||
void mesh_new_prefetch(struct mesh_area* mesh, struct query_info* qinfo,
|
||||
uint16_t qflags, time_t leeway)
|
||||
#ifdef CLIENT_SUBNET
|
||||
/* Same logic as mesh_schedule_prefetch but tailored to the subnet module logic
|
||||
* like passing along the comm_reply info. This will be faked into an EDNS
|
||||
* option for processing by the subnet module if the client has not already
|
||||
* 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)
|
||||
{
|
||||
mesh_schedule_prefetch(mesh, qinfo, qflags, leeway, 1);
|
||||
struct mesh_state* s = NULL;
|
||||
struct edns_option* opt = NULL;
|
||||
#ifdef UNBOUND_DEBUG
|
||||
struct rbnode_type* n;
|
||||
#endif
|
||||
if(!mesh_make_new_space(mesh, NULL)) {
|
||||
verbose(VERB_ALGO, "Too many queries. dropped prefetch.");
|
||||
mesh->stats_dropped ++;
|
||||
return;
|
||||
}
|
||||
|
||||
s = mesh_state_create(mesh->env, qinfo, NULL,
|
||||
qflags&(BIT_RD|BIT_CD), 0, 0);
|
||||
if(!s) {
|
||||
log_err("prefetch_subnet mesh_state_create: out of memory");
|
||||
return;
|
||||
}
|
||||
mesh_state_make_unique(s);
|
||||
|
||||
opt = edns_opt_list_find(edns_list, mesh->env->cfg->client_subnet_opcode);
|
||||
if(opt) {
|
||||
/* Use the client's ECS data */
|
||||
if(!edns_opt_list_append(&s->s.edns_opts_front_in, opt->opt_code,
|
||||
opt->opt_len, opt->opt_data, s->s.region)) {
|
||||
log_err("prefetch_subnet edns_opt_list_append: out of memory");
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
/* Fake the ECS data from the client's IP */
|
||||
struct ecs_data ecs;
|
||||
memset(&ecs, 0, sizeof(ecs));
|
||||
subnet_option_from_ss(&rep->client_addr, &ecs, mesh->env->cfg);
|
||||
if(ecs.subnet_validdata == 0) {
|
||||
log_err("prefetch_subnet subnet_option_from_ss: invalid data");
|
||||
return;
|
||||
}
|
||||
subnet_ecs_opt_list_append(&ecs, &s->s.edns_opts_front_in,
|
||||
&s->s, s->s.region);
|
||||
if(!s->s.edns_opts_front_in) {
|
||||
log_err("prefetch_subnet subnet_ecs_opt_list_append: out of memory");
|
||||
return;
|
||||
}
|
||||
}
|
||||
#ifdef UNBOUND_DEBUG
|
||||
n =
|
||||
#else
|
||||
(void)
|
||||
#endif
|
||||
rbtree_insert(&mesh->all, &s->node);
|
||||
log_assert(n != NULL);
|
||||
/* set detached (it is now) */
|
||||
mesh->num_detached_states++;
|
||||
/* make it ignore the cache */
|
||||
sock_list_insert(&s->s.blacklist, NULL, 0, s->s.region);
|
||||
s->s.prefetch_leeway = leeway;
|
||||
|
||||
if(s->list_select == mesh_no_list) {
|
||||
/* 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->forever_last);
|
||||
s->list_select = mesh_forever_list;
|
||||
} else {
|
||||
mesh_list_insert(s, &mesh->jostle_first,
|
||||
&mesh->jostle_last);
|
||||
s->list_select = mesh_jostle_list;
|
||||
}
|
||||
}
|
||||
s->s.rpz_passthru = rpz_passthru;
|
||||
|
||||
if(!run) {
|
||||
#ifdef UNBOUND_DEBUG
|
||||
n =
|
||||
#else
|
||||
(void)
|
||||
#endif
|
||||
rbtree_insert(&mesh->run, &s->run_node);
|
||||
log_assert(n != NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
mesh_run(mesh, s, module_event_new, NULL);
|
||||
}
|
||||
#endif /* CLIENT_SUBNET */
|
||||
|
||||
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)
|
||||
{
|
||||
(void)opt_list;
|
||||
(void)rep;
|
||||
#ifdef CLIENT_SUBNET
|
||||
if(rep)
|
||||
mesh_schedule_prefetch_subnet(mesh, qinfo, qflags, leeway, 1,
|
||||
rpz_passthru, rep, opt_list);
|
||||
else
|
||||
#endif
|
||||
mesh_schedule_prefetch(mesh, qinfo, qflags, leeway, 1,
|
||||
rpz_passthru);
|
||||
}
|
||||
|
||||
void mesh_report_reply(struct mesh_area* mesh, struct outbound_entry* e,
|
||||
@@ -839,6 +954,7 @@ mesh_state_create(struct module_env* env, struct query_info* qinfo,
|
||||
mstate->s.no_cache_store = 0;
|
||||
mstate->s.need_refetch = 0;
|
||||
mstate->s.was_ratelimited = 0;
|
||||
mstate->s.qstarttime = *env->now;
|
||||
|
||||
/* init modules */
|
||||
for(i=0; i<env->mesh->mods.num; i++) {
|
||||
@@ -1234,7 +1350,7 @@ mesh_send_reply(struct mesh_state* m, int rcode, struct reply_info* rep,
|
||||
(rep->security <= sec_status_bogus ||
|
||||
rep->security == sec_status_secure_sentinel_fail)) {
|
||||
rcode = LDNS_RCODE_SERVFAIL;
|
||||
if(m->s.env->cfg->stat_extended)
|
||||
if(m->s.env->cfg->stat_extended)
|
||||
m->s.env->mesh->ans_bogus++;
|
||||
}
|
||||
if(rep && rep->security == sec_status_secure)
|
||||
@@ -1290,6 +1406,36 @@ mesh_send_reply(struct mesh_state* m, int rcode, struct reply_info* rep,
|
||||
&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);
|
||||
}
|
||||
error_encode(r_buffer, rcode, &m->s.qinfo, r->qid,
|
||||
r->qflags, &r->edns);
|
||||
m->reply_list = NULL;
|
||||
@@ -1313,6 +1459,8 @@ 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, LDNS_RCODE_SERVFAIL, &r->edns, &r->query_reply, m->s.region, &r->start_time))
|
||||
r->edns.opt_list_inplace_cb_out = NULL;
|
||||
/* internal server error (probably malloc failure) so no
|
||||
* EDE (RFC8914) needed */
|
||||
error_encode(r_buffer, LDNS_RCODE_SERVFAIL,
|
||||
&m->s.qinfo, r->qid, r->qflags, &r->edns);
|
||||
}
|
||||
@@ -1340,8 +1488,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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1382,7 +1531,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);
|
||||
&r->query_reply.client_addr,
|
||||
r->query_reply.client_addrlen);
|
||||
if(mstate->s.env->cfg->stat_extended &&
|
||||
mstate->s.respip_action_info->rpz_used) {
|
||||
if(mstate->s.respip_action_info->rpz_disabled)
|
||||
@@ -1524,7 +1674,7 @@ int mesh_state_add_reply(struct mesh_state* s, struct edns_data* edns,
|
||||
struct comm_reply* rep, uint16_t qid, uint16_t qflags,
|
||||
const struct query_info* qinfo)
|
||||
{
|
||||
struct mesh_reply* r = regional_alloc(s->s.region,
|
||||
struct mesh_reply* r = regional_alloc(s->s.region,
|
||||
sizeof(struct mesh_reply));
|
||||
if(!r)
|
||||
return 0;
|
||||
@@ -1693,6 +1843,7 @@ mesh_continue(struct mesh_area* mesh, struct mesh_state* mstate,
|
||||
if(mstate->s.curmod == 0) {
|
||||
struct query_info* qinfo = NULL;
|
||||
uint16_t qflags;
|
||||
int rpz_p = 0;
|
||||
|
||||
mesh_query_done(mstate);
|
||||
mesh_walk_supers(mesh, mstate);
|
||||
@@ -1701,13 +1852,15 @@ mesh_continue(struct mesh_area* mesh, struct mesh_state* mstate,
|
||||
* from an external DNS server, we'll need to schedule
|
||||
* a prefetch after removing the current state, so
|
||||
* we need to make a copy of the query info here. */
|
||||
if(mstate->s.need_refetch)
|
||||
if(mstate->s.need_refetch) {
|
||||
mesh_copy_qinfo(mstate, &qinfo, &qflags);
|
||||
rpz_p = mstate->s.rpz_passthru;
|
||||
}
|
||||
|
||||
mesh_state_delete(&mstate->s);
|
||||
if(qinfo) {
|
||||
mesh_schedule_prefetch(mesh, qinfo, qflags,
|
||||
0, 1);
|
||||
0, 1, rpz_p);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -1917,7 +2070,7 @@ apply_respip_action(struct module_qstate* qstate,
|
||||
return 1;
|
||||
|
||||
if(!respip_rewrite_reply(qinfo, cinfo, rep, encode_repp, actinfo,
|
||||
alias_rrset, 0, qstate->region, az))
|
||||
alias_rrset, 0, qstate->region, az, NULL))
|
||||
return 0;
|
||||
|
||||
/* xxx_deny actions mean dropping the reply, unless the original reply
|
||||
@@ -2029,7 +2182,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);
|
||||
r->local_alias, &r->query_reply.client_addr,
|
||||
r->query_reply.client_addrlen);
|
||||
|
||||
if(qstate->env->cfg->stat_extended && actinfo.rpz_used) {
|
||||
if(actinfo.rpz_disabled)
|
||||
@@ -2042,6 +2196,14 @@ mesh_serve_expired_callback(void* arg)
|
||||
}
|
||||
}
|
||||
|
||||
/* Add EDE Stale Answer (RCF8914). Ignore global ede as this is
|
||||
* warning instead of an error */
|
||||
if (r->edns.edns_present && qstate->env->cfg->ede_serve_expired &&
|
||||
qstate->env->cfg->ede) {
|
||||
edns_opt_list_append_ede(&r->edns.opt_list_out,
|
||||
mstate->s.region, LDNS_EDE_STALE_ANSWER, NULL);
|
||||
}
|
||||
|
||||
r_buffer = r->query_reply.c->buffer;
|
||||
if(r->query_reply.c->tcp_req_info)
|
||||
r_buffer = r->query_reply.c->tcp_req_info->spool_buffer;
|
||||
@@ -2081,3 +2243,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;
|
||||
}
|
||||
|
||||
+25
-3
@@ -296,10 +296,13 @@ void mesh_delete(struct mesh_area* mesh);
|
||||
* @param edns: edns data from client query.
|
||||
* @param rep: where to reply to.
|
||||
* @param qid: query id to reply with.
|
||||
* @param rpz_passthru: if true, the rpz passthru was previously found and
|
||||
* further rpz processing is stopped.
|
||||
*/
|
||||
void mesh_new_client(struct mesh_area* mesh, struct query_info* qinfo,
|
||||
struct respip_client_info* cinfo, uint16_t qflags,
|
||||
struct edns_data* edns, struct comm_reply* rep, uint16_t qid);
|
||||
struct edns_data* edns, struct comm_reply* rep, uint16_t qid,
|
||||
int rpz_passthru);
|
||||
|
||||
/**
|
||||
* New query with callback. Create new query state if needed, and
|
||||
@@ -314,11 +317,13 @@ void mesh_new_client(struct mesh_area* mesh, struct query_info* qinfo,
|
||||
* @param qid: query id to reply with.
|
||||
* @param cb: callback function.
|
||||
* @param cb_arg: callback user arg.
|
||||
* @param rpz_passthru: if true, the rpz passthru was previously found and
|
||||
* further rpz processing is stopped.
|
||||
* @return 0 on error.
|
||||
*/
|
||||
int mesh_new_callback(struct mesh_area* mesh, struct query_info* qinfo,
|
||||
uint16_t qflags, struct edns_data* edns, struct sldns_buffer* buf,
|
||||
uint16_t qid, mesh_cb_func_type cb, void* cb_arg);
|
||||
uint16_t qid, mesh_cb_func_type cb, void* cb_arg, int rpz_passthru);
|
||||
|
||||
/**
|
||||
* New prefetch message. Create new query state if needed.
|
||||
@@ -328,9 +333,15 @@ int mesh_new_callback(struct mesh_area* mesh, struct query_info* qinfo,
|
||||
* @param qinfo: query from client.
|
||||
* @param qflags: flags from client query.
|
||||
* @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 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);
|
||||
uint16_t qflags, time_t leeway, int rpz_passthru,
|
||||
struct comm_reply* rep, struct edns_option* opt_list);
|
||||
|
||||
/**
|
||||
* Handle new event from the wire. A serviced query has returned.
|
||||
@@ -674,4 +685,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 */
|
||||
|
||||
+332
-161
@@ -86,14 +86,20 @@ 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);
|
||||
|
||||
/** Perform serviced query UDP sending operation */
|
||||
static int serviced_udp_send(struct serviced_query* sq, sldns_buffer* buff);
|
||||
|
||||
/** Send serviced query over TCP return false on initial failure */
|
||||
static int serviced_tcp_send(struct serviced_query* sq, sldns_buffer* buff);
|
||||
|
||||
/** call the callbacks for a serviced query */
|
||||
static void serviced_callbacks(struct serviced_query* sq, int error,
|
||||
struct comm_point* c, struct comm_reply* rep);
|
||||
|
||||
int
|
||||
pending_cmp(const void* key1, const void* key2)
|
||||
{
|
||||
@@ -261,7 +267,7 @@ outnet_get_tcp_fd(struct sockaddr_storage* addr, socklen_t addrlen, int tcp_mss,
|
||||
int s;
|
||||
int af;
|
||||
char* err;
|
||||
#ifdef SO_REUSEADDR
|
||||
#if defined(SO_REUSEADDR) || defined(IP_BIND_ADDRESS_NO_PORT)
|
||||
int on = 1;
|
||||
#endif
|
||||
#ifdef INET6
|
||||
@@ -307,7 +313,13 @@ outnet_get_tcp_fd(struct sockaddr_storage* addr, socklen_t addrlen, int tcp_mss,
|
||||
" setsockopt(TCP_MAXSEG) unsupported");
|
||||
#endif /* defined(IPPROTO_TCP) && defined(TCP_MAXSEG) */
|
||||
}
|
||||
|
||||
#ifdef IP_BIND_ADDRESS_NO_PORT
|
||||
if(setsockopt(s, IPPROTO_IP, IP_BIND_ADDRESS_NO_PORT, (void*)&on,
|
||||
(socklen_t)sizeof(on)) < 0) {
|
||||
verbose(VERB_ALGO, "outgoing tcp:"
|
||||
" setsockopt(.. IP_BIND_ADDRESS_NO_PORT ..) failed");
|
||||
}
|
||||
#endif /* IP_BIND_ADDRESS_NO_PORT */
|
||||
return s;
|
||||
}
|
||||
|
||||
@@ -356,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)
|
||||
@@ -374,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);
|
||||
@@ -399,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);
|
||||
@@ -411,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;
|
||||
}
|
||||
@@ -705,12 +720,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
|
||||
@@ -794,20 +809,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);
|
||||
@@ -819,16 +864,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;
|
||||
@@ -836,6 +883,7 @@ outnet_add_tcp_waiting_first(struct outside_network* outnet,
|
||||
if(w->on_tcp_waiting_list)
|
||||
return;
|
||||
w->next_waiting = outnet->tcp_wait_first;
|
||||
log_assert(w->next_waiting != w);
|
||||
if(!outnet->tcp_wait_last)
|
||||
outnet->tcp_wait_last = w;
|
||||
outnet->tcp_wait_first = w;
|
||||
@@ -852,6 +900,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)
|
||||
@@ -862,15 +921,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 */
|
||||
@@ -917,7 +971,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
|
||||
@@ -991,7 +1045,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 &&
|
||||
@@ -1002,7 +1056,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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1136,6 +1190,22 @@ static void reuse_cb_readwait_for_failure(rbtree_type* tree_by_id, int err)
|
||||
}
|
||||
}
|
||||
|
||||
/** mark the entry for being in the cb_and_decommission stage */
|
||||
static void mark_for_cb_and_decommission(rbnode_type* node,
|
||||
void* ATTR_UNUSED(arg))
|
||||
{
|
||||
struct waiting_tcp* w = (struct waiting_tcp*)node->key;
|
||||
/* Mark the waiting_tcp to signal later code (serviced_delete) that
|
||||
* this item is part of the backed up tree_by_id and will be deleted
|
||||
* later. */
|
||||
w->in_cb_and_decommission = 1;
|
||||
/* Mark the serviced_query for deletion so that later code through
|
||||
* callbacks (iter_clear .. outnet_serviced_query_stop) won't
|
||||
* prematurely delete it. */
|
||||
if(w->cb)
|
||||
((struct serviced_query*)w->cb_arg)->to_be_deleted = 1;
|
||||
}
|
||||
|
||||
/** perform callbacks for failure and also decommission pending tcp.
|
||||
* the callbacks remove references in sq->pending to the waiting_tcp
|
||||
* members of the tree_by_id in the pending tcp. The pending_tcp is
|
||||
@@ -1151,6 +1221,9 @@ static void reuse_cb_and_decommission(struct outside_network* outnet,
|
||||
pend->reuse.write_wait_first = NULL;
|
||||
pend->reuse.write_wait_last = NULL;
|
||||
decommission_pending_tcp(outnet, pend);
|
||||
if(store.root != NULL && store.root != RBTREE_NULL) {
|
||||
traverse_postorder(&store, &mark_for_cb_and_decommission, NULL);
|
||||
}
|
||||
reuse_cb_readwait_for_failure(&store, error);
|
||||
reuse_del_readwait(&store);
|
||||
}
|
||||
@@ -1248,6 +1321,12 @@ outnet_tcp_cb(struct comm_point* c, void* arg, int error,
|
||||
c->buffer));
|
||||
/* find the query the reply is for */
|
||||
w = reuse_tcp_by_id_find(&pend->reuse, id);
|
||||
/* Make sure that the reply we got is at least for a
|
||||
* sent query with the same ID; the waiting_tcp that
|
||||
* gets a reply is assumed to not be waiting to be
|
||||
* sent. */
|
||||
if(w && (w->on_tcp_waiting_list || w->write_wait_queued))
|
||||
w = NULL;
|
||||
}
|
||||
}
|
||||
if(error == NETEVENT_NOERROR && !w) {
|
||||
@@ -1265,6 +1344,8 @@ outnet_tcp_cb(struct comm_point* c, void* arg, int error,
|
||||
}
|
||||
}
|
||||
if(w) {
|
||||
log_assert(!w->on_tcp_waiting_list);
|
||||
log_assert(!w->write_wait_queued);
|
||||
reuse_tree_by_id_delete(&pend->reuse, w);
|
||||
verbose(VERB_CLIENT, "outnet tcp callback query err %d buflen %d",
|
||||
error, (int)sldns_buffer_limit(c->buffer));
|
||||
@@ -1324,7 +1405,7 @@ outnet_send_wait_udp(struct outside_network* outnet)
|
||||
{
|
||||
struct pending* pend;
|
||||
/* process waiting queries */
|
||||
while(outnet->udp_wait_first && outnet->unused_fds
|
||||
while(outnet->udp_wait_first && outnet->unused_fds
|
||||
&& !outnet->want_to_quit) {
|
||||
pend = outnet->udp_wait_first;
|
||||
outnet->udp_wait_first = pend->next_waiting;
|
||||
@@ -1333,8 +1414,10 @@ outnet_send_wait_udp(struct outside_network* outnet)
|
||||
sldns_buffer_write(outnet->udp_buff, pend->pkt, pend->pkt_len);
|
||||
sldns_buffer_flip(outnet->udp_buff);
|
||||
free(pend->pkt); /* freeing now makes get_mem correct */
|
||||
pend->pkt = NULL;
|
||||
pend->pkt = NULL;
|
||||
pend->pkt_len = 0;
|
||||
log_assert(!pend->sq->busy);
|
||||
pend->sq->busy = 1;
|
||||
if(!randomize_and_send_udp(pend, outnet->udp_buff,
|
||||
pend->timeout)) {
|
||||
/* callback error on pending */
|
||||
@@ -1344,6 +1427,8 @@ outnet_send_wait_udp(struct outside_network* outnet)
|
||||
NETEVENT_CLOSED, NULL);
|
||||
}
|
||||
pending_delete(outnet, pend);
|
||||
} else {
|
||||
pend->sq->busy = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1369,11 +1454,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);
|
||||
@@ -1454,7 +1539,6 @@ calc_num46(char** ifs, int num_ifs, int do_ip4, int do_ip6,
|
||||
(*num_ip4)++;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
@@ -1567,6 +1651,7 @@ outside_network_create(struct comm_base *base, size_t bufsize,
|
||||
outnet->tcp_reuse_timeout= tcp_reuse_timeout;
|
||||
outnet->tcp_auth_query_timeout = tcp_auth_query_timeout;
|
||||
outnet->num_tcp_outgoing = 0;
|
||||
outnet->num_udp_outgoing = 0;
|
||||
outnet->infra = infra;
|
||||
outnet->rnd = rnd;
|
||||
outnet->sslctx = sslctx;
|
||||
@@ -1642,7 +1727,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);
|
||||
@@ -1708,16 +1793,9 @@ static void
|
||||
serviced_node_del(rbnode_type* node, void* ATTR_UNUSED(arg))
|
||||
{
|
||||
struct serviced_query* sq = (struct serviced_query*)node;
|
||||
struct service_callback* p = sq->cblist, *np;
|
||||
free(sq->qbuf);
|
||||
free(sq->zone);
|
||||
free(sq->tls_auth_name);
|
||||
edns_opt_list_free(sq->opt_list);
|
||||
while(p) {
|
||||
np = p->next;
|
||||
free(p);
|
||||
p = np;
|
||||
}
|
||||
alloc_reg_release(sq->alloc, sq->region);
|
||||
if(sq->timer)
|
||||
comm_timer_delete(sq->timer);
|
||||
free(sq);
|
||||
}
|
||||
|
||||
@@ -1960,6 +2038,9 @@ static int udp_connect_needs_log(int err)
|
||||
# endif
|
||||
# ifdef ENETDOWN
|
||||
case ENETDOWN:
|
||||
# endif
|
||||
# ifdef EADDRNOTAVAIL
|
||||
case EADDRNOTAVAIL:
|
||||
# endif
|
||||
case EPERM:
|
||||
case EACCES:
|
||||
@@ -2105,6 +2186,7 @@ randomize_and_send_udp(struct pending* pend, sldns_buffer* packet, int timeout)
|
||||
portcomm_loweruse(outnet, pend->pc);
|
||||
return 0;
|
||||
}
|
||||
outnet->num_udp_outgoing++;
|
||||
|
||||
/* system calls to set timeout after sending UDP to make roundtrip
|
||||
smaller. */
|
||||
@@ -2174,10 +2256,13 @@ pending_udp_query(struct serviced_query* sq, struct sldns_buffer* packet,
|
||||
sq->outnet->udp_wait_last = pend;
|
||||
return pend;
|
||||
}
|
||||
log_assert(!sq->busy);
|
||||
sq->busy = 1;
|
||||
if(!randomize_and_send_udp(pend, packet, timeout)) {
|
||||
pending_delete(sq->outnet, pend);
|
||||
return NULL;
|
||||
}
|
||||
sq->busy = 0;
|
||||
return pend;
|
||||
}
|
||||
|
||||
@@ -2189,7 +2274,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 {
|
||||
@@ -2247,7 +2332,7 @@ reuse_tcp_select_id(struct reuse_tcp* reuse, struct outside_network* outnet)
|
||||
}
|
||||
|
||||
/* equally pick a random unused element from the tree that is
|
||||
* not in use. Pick a the n-th index of an ununused number,
|
||||
* not in use. Pick a the n-th index of an unused number,
|
||||
* then loop over the empty spaces in the tree and find it */
|
||||
log_assert(reuse->tree_by_id.count < 0xffff);
|
||||
select = ub_random_max(outnet->rnd, 0xffff - reuse->tree_by_id.count);
|
||||
@@ -2257,7 +2342,7 @@ reuse_tcp_select_id(struct reuse_tcp* reuse, struct outside_network* outnet)
|
||||
node = rbtree_first(&reuse->tree_by_id);
|
||||
log_assert(node && node != RBTREE_NULL); /* tree not empty */
|
||||
/* see if select is before first node */
|
||||
if(select < tree_by_id_get_id(node))
|
||||
if(select < (unsigned)tree_by_id_get_id(node))
|
||||
return select;
|
||||
count += tree_by_id_get_id(node);
|
||||
/* perhaps select is between nodes */
|
||||
@@ -2360,6 +2445,7 @@ pending_tcp_query(struct serviced_query* sq, sldns_buffer* packet,
|
||||
#ifdef USE_DNSTAP
|
||||
w->sq = NULL;
|
||||
#endif
|
||||
w->in_cb_and_decommission = 0;
|
||||
if(pend) {
|
||||
/* we have a buffer available right now */
|
||||
if(reuse) {
|
||||
@@ -2415,7 +2501,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;
|
||||
}
|
||||
@@ -2456,30 +2542,67 @@ lookup_serviced(struct outside_network* outnet, sldns_buffer* buff, int dnssec,
|
||||
return (struct serviced_query*)rbtree_search(outnet->serviced, &key);
|
||||
}
|
||||
|
||||
void
|
||||
serviced_timer_cb(void* arg)
|
||||
{
|
||||
struct serviced_query* sq = (struct serviced_query*)arg;
|
||||
struct outside_network* outnet = sq->outnet;
|
||||
verbose(VERB_ALGO, "serviced send timer");
|
||||
/* By the time this cb is called, if we don't have any registered
|
||||
* callbacks for this serviced_query anymore; do not send. */
|
||||
if(!sq->cblist)
|
||||
goto delete;
|
||||
/* perform first network action */
|
||||
if(outnet->do_udp && !(sq->tcp_upstream || sq->ssl_upstream)) {
|
||||
if(!serviced_udp_send(sq, outnet->udp_buff))
|
||||
goto delete;
|
||||
} else {
|
||||
if(!serviced_tcp_send(sq, outnet->udp_buff))
|
||||
goto delete;
|
||||
}
|
||||
/* Maybe by this time we don't have callbacks attached anymore. Don't
|
||||
* proactively try to delete; let it run and maybe another callback
|
||||
* will get attached by the time we get an answer. */
|
||||
return;
|
||||
delete:
|
||||
serviced_callbacks(sq, NETEVENT_CLOSED, NULL, NULL);
|
||||
}
|
||||
|
||||
/** Create new serviced entry */
|
||||
static struct serviced_query*
|
||||
serviced_create(struct outside_network* outnet, sldns_buffer* buff, int dnssec,
|
||||
int want_dnssec, int nocaps, int tcp_upstream, int ssl_upstream,
|
||||
char* tls_auth_name, struct sockaddr_storage* addr, socklen_t addrlen,
|
||||
uint8_t* zone, size_t zonelen, int qtype, struct edns_option* opt_list,
|
||||
size_t pad_queries_block_size)
|
||||
const uint8_t* raw_qbuf, size_t raw_qbuf_len,
|
||||
size_t pad_queries_block_size, struct alloc_cache* alloc,
|
||||
struct regional* region)
|
||||
{
|
||||
struct serviced_query* sq = (struct serviced_query*)malloc(sizeof(*sq));
|
||||
struct timeval t;
|
||||
#ifdef UNBOUND_DEBUG
|
||||
rbnode_type* ins;
|
||||
#endif
|
||||
if(!sq)
|
||||
if(!sq) {
|
||||
alloc_reg_release(alloc, region);
|
||||
return NULL;
|
||||
}
|
||||
sq->node.key = sq;
|
||||
sq->qbuf = memdup(sldns_buffer_begin(buff), sldns_buffer_limit(buff));
|
||||
sq->alloc = alloc;
|
||||
sq->region = region;
|
||||
sq->qbuf = regional_alloc_init(region, sldns_buffer_begin(buff),
|
||||
sldns_buffer_limit(buff));
|
||||
if(!sq->qbuf) {
|
||||
alloc_reg_release(alloc, region);
|
||||
free(sq);
|
||||
return NULL;
|
||||
}
|
||||
sq->qbuflen = sldns_buffer_limit(buff);
|
||||
sq->zone = memdup(zone, zonelen);
|
||||
sq->raw_qbuf = raw_qbuf;
|
||||
sq->raw_qbuf_len = raw_qbuf_len;
|
||||
sq->zone = regional_alloc_init(region, zone, zonelen);
|
||||
if(!sq->zone) {
|
||||
free(sq->qbuf);
|
||||
alloc_reg_release(alloc, region);
|
||||
free(sq);
|
||||
return NULL;
|
||||
}
|
||||
@@ -2491,10 +2614,9 @@ serviced_create(struct outside_network* outnet, sldns_buffer* buff, int dnssec,
|
||||
sq->tcp_upstream = tcp_upstream;
|
||||
sq->ssl_upstream = ssl_upstream;
|
||||
if(tls_auth_name) {
|
||||
sq->tls_auth_name = strdup(tls_auth_name);
|
||||
sq->tls_auth_name = regional_strdup(region, tls_auth_name);
|
||||
if(!sq->tls_auth_name) {
|
||||
free(sq->zone);
|
||||
free(sq->qbuf);
|
||||
alloc_reg_release(alloc, region);
|
||||
free(sq);
|
||||
return NULL;
|
||||
}
|
||||
@@ -2503,17 +2625,16 @@ serviced_create(struct outside_network* outnet, sldns_buffer* buff, int dnssec,
|
||||
}
|
||||
memcpy(&sq->addr, addr, addrlen);
|
||||
sq->addrlen = addrlen;
|
||||
sq->opt_list = NULL;
|
||||
if(opt_list) {
|
||||
sq->opt_list = edns_opt_copy_alloc(opt_list);
|
||||
if(!sq->opt_list) {
|
||||
free(sq->tls_auth_name);
|
||||
free(sq->zone);
|
||||
free(sq->qbuf);
|
||||
free(sq);
|
||||
return NULL;
|
||||
}
|
||||
sq->opt_list = opt_list;
|
||||
sq->busy = 0;
|
||||
sq->timer = comm_timer_create(outnet->base, serviced_timer_cb, sq);
|
||||
if(!sq->timer) {
|
||||
alloc_reg_release(alloc, region);
|
||||
free(sq);
|
||||
return NULL;
|
||||
}
|
||||
memset(&t, 0, sizeof(t));
|
||||
comm_timer_set(sq->timer, &t);
|
||||
sq->outnet = outnet;
|
||||
sq->cblist = NULL;
|
||||
sq->pending = NULL;
|
||||
@@ -2522,7 +2643,7 @@ serviced_create(struct outside_network* outnet, sldns_buffer* buff, int dnssec,
|
||||
sq->to_be_deleted = 0;
|
||||
sq->padding_block_size = pad_queries_block_size;
|
||||
#ifdef UNBOUND_DEBUG
|
||||
ins =
|
||||
ins =
|
||||
#else
|
||||
(void)
|
||||
#endif
|
||||
@@ -2531,30 +2652,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
|
||||
@@ -2620,29 +2717,38 @@ serviced_delete(struct serviced_query* sq)
|
||||
struct waiting_tcp* w = (struct waiting_tcp*)
|
||||
sq->pending;
|
||||
verbose(VERB_CLIENT, "serviced_delete: TCP");
|
||||
log_assert(!(w->write_wait_queued && w->on_tcp_waiting_list));
|
||||
/* if on stream-write-waiting list then
|
||||
* remove from waiting list and waiting_tcp_delete */
|
||||
if(w->write_wait_queued) {
|
||||
struct pending_tcp* pend =
|
||||
(struct pending_tcp*)w->next_waiting;
|
||||
verbose(VERB_CLIENT, "serviced_delete: writewait");
|
||||
reuse_tree_by_id_delete(&pend->reuse, w);
|
||||
if(!w->in_cb_and_decommission)
|
||||
reuse_tree_by_id_delete(&pend->reuse, w);
|
||||
reuse_write_wait_remove(&pend->reuse, w);
|
||||
waiting_tcp_delete(w);
|
||||
if(!w->in_cb_and_decommission)
|
||||
waiting_tcp_delete(w);
|
||||
} else if(!w->on_tcp_waiting_list) {
|
||||
struct pending_tcp* pend =
|
||||
(struct pending_tcp*)w->next_waiting;
|
||||
verbose(VERB_CLIENT, "serviced_delete: tcpreusekeep");
|
||||
/* w needs to stay on tree_by_id to not assign
|
||||
* the same ID; remove the callback since its
|
||||
* serviced_query will be gone. */
|
||||
w->cb = NULL;
|
||||
if(!reuse_tcp_remove_serviced_keep(w, sq)) {
|
||||
reuse_cb_and_decommission(sq->outnet,
|
||||
pend, NETEVENT_CLOSED);
|
||||
if(!w->in_cb_and_decommission)
|
||||
reuse_cb_and_decommission(sq->outnet,
|
||||
pend, NETEVENT_CLOSED);
|
||||
use_free_buffer(sq->outnet);
|
||||
}
|
||||
sq->pending = NULL;
|
||||
} else {
|
||||
verbose(VERB_CLIENT, "serviced_delete: tcpwait");
|
||||
waiting_list_remove(sq->outnet, w);
|
||||
waiting_tcp_delete(w);
|
||||
outnet_waiting_tcp_list_remove(sq->outnet, w);
|
||||
if(!w->in_cb_and_decommission)
|
||||
waiting_tcp_delete(w);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2697,6 +2803,13 @@ serviced_encode(struct serviced_query* sq, sldns_buffer* buff, int with_edns)
|
||||
if(sq->outnet->use_caps_for_id && !sq->nocaps) {
|
||||
serviced_perturb_qname(sq->outnet->rnd, sq->qbuf, sq->qbuflen);
|
||||
}
|
||||
if (sq->raw_qbuf) {
|
||||
/* use the raw packet from libunbound's ub_send */
|
||||
sldns_buffer_clear(buff);
|
||||
sldns_buffer_write(buff, sq->raw_qbuf, sq->raw_qbuf_len);
|
||||
sldns_buffer_flip(buff);
|
||||
return;
|
||||
}
|
||||
/* generate query */
|
||||
sldns_buffer_clear(buff);
|
||||
sldns_buffer_write_u16(buff, 0); /* id placeholder */
|
||||
@@ -2892,7 +3005,8 @@ serviced_callbacks(struct serviced_query* sq, int error, struct comm_point* c,
|
||||
* use secondary buffer to store the query.
|
||||
* This is a data copy, but faster than packet to server */
|
||||
backlen = sldns_buffer_limit(c->buffer);
|
||||
backup_p = memdup(sldns_buffer_begin(c->buffer), backlen);
|
||||
backup_p = regional_alloc_init(sq->region,
|
||||
sldns_buffer_begin(c->buffer), backlen);
|
||||
if(!backup_p) {
|
||||
log_err("malloc failure in serviced query callbacks");
|
||||
error = NETEVENT_CLOSED;
|
||||
@@ -2910,10 +3024,8 @@ serviced_callbacks(struct serviced_query* sq, int error, struct comm_point* c,
|
||||
}
|
||||
fptr_ok(fptr_whitelist_serviced_query(p->cb));
|
||||
(void)(*p->cb)(c, p->cb_arg, error, rep);
|
||||
free(p);
|
||||
}
|
||||
if(backup_p) {
|
||||
free(backup_p);
|
||||
sq->outnet->svcd_overhead = 0;
|
||||
}
|
||||
verbose(VERB_ALGO, "svcd callbacks end");
|
||||
@@ -2931,7 +3043,7 @@ serviced_tcp_callback(struct comm_point* c, void* arg, int error,
|
||||
struct waiting_tcp* w = (struct waiting_tcp*)sq->pending;
|
||||
struct pending_tcp* pend_tcp = NULL;
|
||||
struct port_if* pi = NULL;
|
||||
if(!w->on_tcp_waiting_list && w->next_waiting) {
|
||||
if(w && !w->on_tcp_waiting_list && w->next_waiting) {
|
||||
pend_tcp = (struct pending_tcp*)w->next_waiting;
|
||||
pi = pend_tcp->pi;
|
||||
}
|
||||
@@ -3014,8 +3126,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;
|
||||
}
|
||||
@@ -3027,8 +3139,11 @@ serviced_tcp_initiate(struct serviced_query* sq, sldns_buffer* buff)
|
||||
sq->status==serviced_query_TCP_EDNS?"EDNS":"");
|
||||
serviced_encode(sq, buff, sq->status == serviced_query_TCP_EDNS);
|
||||
sq->last_sent_time = *sq->outnet->now_tv;
|
||||
log_assert(!sq->busy);
|
||||
sq->busy = 1;
|
||||
sq->pending = pending_tcp_query(sq, buff, sq->outnet->tcp_auth_query_timeout,
|
||||
serviced_tcp_callback, sq);
|
||||
sq->busy = 0;
|
||||
if(!sq->pending) {
|
||||
/* delete from tree so that a retry by above layer does not
|
||||
* clash with this entry */
|
||||
@@ -3060,8 +3175,11 @@ serviced_tcp_send(struct serviced_query* sq, sldns_buffer* buff)
|
||||
} else {
|
||||
timeout = sq->outnet->tcp_auth_query_timeout;
|
||||
}
|
||||
log_assert(!sq->busy);
|
||||
sq->busy = 1;
|
||||
sq->pending = pending_tcp_query(sq, buff, timeout,
|
||||
serviced_tcp_callback, sq);
|
||||
sq->busy = 0;
|
||||
return sq->pending != NULL;
|
||||
}
|
||||
|
||||
@@ -3112,7 +3230,6 @@ serviced_udp_callback(struct comm_point* c, void* arg, int error,
|
||||
struct timeval now = *sq->outnet->now_tv;
|
||||
#ifdef USE_DNSTAP
|
||||
struct pending* p = (struct pending*)sq->pending;
|
||||
struct port_if* pi = p->pc->pif;
|
||||
#endif
|
||||
|
||||
sq->pending = NULL; /* removed after callback */
|
||||
@@ -3154,14 +3271,16 @@ serviced_udp_callback(struct comm_point* c, void* arg, int error,
|
||||
/*
|
||||
* sending src (local service)/dst (upstream) addresses over DNSTAP
|
||||
*/
|
||||
if(error == NETEVENT_NOERROR && outnet->dtenv &&
|
||||
(outnet->dtenv->log_resolver_response_messages ||
|
||||
outnet->dtenv->log_forwarder_response_messages)) {
|
||||
if(error == NETEVENT_NOERROR && outnet->dtenv && p->pc &&
|
||||
(outnet->dtenv->log_resolver_response_messages ||
|
||||
outnet->dtenv->log_forwarder_response_messages)) {
|
||||
log_addr(VERB_ALGO, "response from upstream", &sq->addr, sq->addrlen);
|
||||
log_addr(VERB_ALGO, "to local addr", &pi->addr, pi->addrlen);
|
||||
dt_msg_send_outside_response(outnet->dtenv, &sq->addr, &pi->addr, c->type,
|
||||
sq->zone, sq->zonelen, sq->qbuf, sq->qbuflen,
|
||||
&sq->last_sent_time, sq->outnet->now_tv, c->buffer);
|
||||
log_addr(VERB_ALGO, "to local addr", &p->pc->pif->addr,
|
||||
p->pc->pif->addrlen);
|
||||
dt_msg_send_outside_response(outnet->dtenv, &sq->addr,
|
||||
&p->pc->pif->addr, c->type, sq->zone, sq->zonelen,
|
||||
sq->qbuf, sq->qbuflen, &sq->last_sent_time,
|
||||
sq->outnet->now_tv, c->buffer);
|
||||
}
|
||||
#endif
|
||||
if( (sq->status == serviced_query_UDP_EDNS
|
||||
@@ -3251,64 +3370,117 @@ serviced_udp_callback(struct comm_point* c, void* arg, int error,
|
||||
struct serviced_query*
|
||||
outnet_serviced_query(struct outside_network* outnet,
|
||||
struct query_info* qinfo, uint16_t flags, int dnssec, int want_dnssec,
|
||||
int nocaps, int tcp_upstream, int ssl_upstream, char* tls_auth_name,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* zone,
|
||||
size_t zonelen, struct module_qstate* qstate,
|
||||
comm_point_callback_type* callback, void* callback_arg, sldns_buffer* buff,
|
||||
struct module_env* env)
|
||||
int nocaps, int check_ratelimit, int tcp_upstream, int ssl_upstream,
|
||||
char* tls_auth_name, struct sockaddr_storage* addr, socklen_t addrlen,
|
||||
uint8_t* zone, size_t zonelen, struct module_qstate* qstate,
|
||||
comm_point_callback_type* callback, void* callback_arg,
|
||||
sldns_buffer* buff, struct module_env* env, int* was_ratelimited)
|
||||
{
|
||||
struct serviced_query* sq;
|
||||
struct service_callback* cb;
|
||||
struct edns_string_addr* client_string_addr;
|
||||
struct regional* region;
|
||||
struct edns_option* backed_up_opt_list = qstate->edns_opts_back_out;
|
||||
struct edns_option* per_upstream_opt_list = NULL;
|
||||
time_t timenow = 0;
|
||||
|
||||
if(!inplace_cb_query_call(env, qinfo, flags, addr, addrlen, zone, zonelen,
|
||||
qstate, qstate->region))
|
||||
/* If we have an already populated EDNS option list make a copy since
|
||||
* we may now add upstream specific EDNS options. */
|
||||
/* Use a region that could be attached to a serviced_query, if it needs
|
||||
* to be created. If an existing one is found then this region will be
|
||||
* destroyed here. */
|
||||
region = alloc_reg_obtain(env->alloc);
|
||||
if(!region) return NULL;
|
||||
if(qstate->edns_opts_back_out) {
|
||||
per_upstream_opt_list = edns_opt_copy_region(
|
||||
qstate->edns_opts_back_out, region);
|
||||
if(!per_upstream_opt_list) {
|
||||
alloc_reg_release(env->alloc, region);
|
||||
return NULL;
|
||||
}
|
||||
qstate->edns_opts_back_out = per_upstream_opt_list;
|
||||
}
|
||||
|
||||
if(!inplace_cb_query_call(env, qinfo, flags, addr, addrlen, zone,
|
||||
zonelen, qstate, region)) {
|
||||
alloc_reg_release(env->alloc, region);
|
||||
return NULL;
|
||||
}
|
||||
/* Restore the option list; we can explicitly use the copied one from
|
||||
* now on. */
|
||||
per_upstream_opt_list = qstate->edns_opts_back_out;
|
||||
qstate->edns_opts_back_out = backed_up_opt_list;
|
||||
|
||||
if((client_string_addr = edns_string_addr_lookup(
|
||||
&env->edns_strings->client_strings, addr, addrlen))) {
|
||||
edns_opt_list_append(&qstate->edns_opts_back_out,
|
||||
edns_opt_list_append(&per_upstream_opt_list,
|
||||
env->edns_strings->client_string_opcode,
|
||||
client_string_addr->string_len,
|
||||
client_string_addr->string, qstate->region);
|
||||
client_string_addr->string, region);
|
||||
}
|
||||
|
||||
serviced_gen_query(buff, qinfo->qname, qinfo->qname_len, qinfo->qtype,
|
||||
qinfo->qclass, flags);
|
||||
sq = lookup_serviced(outnet, buff, dnssec, addr, addrlen,
|
||||
qstate->edns_opts_back_out);
|
||||
/* duplicate entries are included in the callback list, because
|
||||
* there is a counterpart registration by our caller that needs to
|
||||
* be doubly-removed (with callbacks perhaps). */
|
||||
if(!(cb = (struct service_callback*)malloc(sizeof(*cb))))
|
||||
return NULL;
|
||||
per_upstream_opt_list);
|
||||
if(!sq) {
|
||||
/* Check ratelimit only for new serviced_query */
|
||||
if(check_ratelimit) {
|
||||
timenow = *env->now;
|
||||
if(!infra_ratelimit_inc(env->infra_cache, zone,
|
||||
zonelen, timenow, env->cfg->ratelimit_backoff,
|
||||
&qstate->qinfo, qstate->reply)) {
|
||||
/* Can we pass through with slip factor? */
|
||||
if(env->cfg->ratelimit_factor == 0 ||
|
||||
ub_random_max(env->rnd,
|
||||
env->cfg->ratelimit_factor) != 1) {
|
||||
*was_ratelimited = 1;
|
||||
alloc_reg_release(env->alloc, region);
|
||||
return NULL;
|
||||
}
|
||||
log_nametypeclass(VERB_ALGO,
|
||||
"ratelimit allowed through for "
|
||||
"delegation point", zone,
|
||||
LDNS_RR_TYPE_NS, LDNS_RR_CLASS_IN);
|
||||
}
|
||||
}
|
||||
/* make new serviced query entry */
|
||||
sq = serviced_create(outnet, buff, dnssec, want_dnssec, nocaps,
|
||||
tcp_upstream, ssl_upstream, tls_auth_name, addr,
|
||||
addrlen, zone, zonelen, (int)qinfo->qtype,
|
||||
qstate->edns_opts_back_out,
|
||||
per_upstream_opt_list,
|
||||
qinfo->qbuf, qinfo->qbuf_len,
|
||||
( ssl_upstream && env->cfg->pad_queries
|
||||
? env->cfg->pad_queries_block_size : 0 ));
|
||||
? env->cfg->pad_queries_block_size : 0 ),
|
||||
env->alloc, region);
|
||||
if(!sq) {
|
||||
free(cb);
|
||||
if(check_ratelimit) {
|
||||
infra_ratelimit_dec(env->infra_cache,
|
||||
zone, zonelen, timenow);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
/* perform first network action */
|
||||
if(outnet->do_udp && !(tcp_upstream || ssl_upstream)) {
|
||||
if(!serviced_udp_send(sq, buff)) {
|
||||
(void)rbtree_delete(outnet->serviced, sq);
|
||||
serviced_node_del(&sq->node, NULL);
|
||||
free(cb);
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
if(!serviced_tcp_send(sq, buff)) {
|
||||
(void)rbtree_delete(outnet->serviced, sq);
|
||||
serviced_node_del(&sq->node, NULL);
|
||||
free(cb);
|
||||
return NULL;
|
||||
if(!(cb = (struct service_callback*)regional_alloc(
|
||||
sq->region, sizeof(*cb)))) {
|
||||
if(check_ratelimit) {
|
||||
infra_ratelimit_dec(env->infra_cache,
|
||||
zone, zonelen, timenow);
|
||||
}
|
||||
(void)rbtree_delete(outnet->serviced, sq);
|
||||
serviced_node_del(&sq->node, NULL);
|
||||
return NULL;
|
||||
}
|
||||
/* No network action at this point; it will be invoked with the
|
||||
* serviced_query timer instead to run outside of the mesh. */
|
||||
} else {
|
||||
/* We don't need this region anymore. */
|
||||
alloc_reg_release(env->alloc, region);
|
||||
/* duplicate entries are included in the callback list, because
|
||||
* there is a counterpart registration by our caller that needs
|
||||
* to be doubly-removed (with callbacks perhaps). */
|
||||
if(!(cb = (struct service_callback*)regional_alloc(
|
||||
sq->region, sizeof(*cb)))) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
/* add callback to list of callbacks */
|
||||
@@ -3328,7 +3500,6 @@ callback_list_remove(struct serviced_query* sq, void* cb_arg)
|
||||
if((*pp)->cb_arg == cb_arg) {
|
||||
struct service_callback* del = *pp;
|
||||
*pp = del->next;
|
||||
free(del);
|
||||
return;
|
||||
}
|
||||
pp = &(*pp)->next;
|
||||
@@ -3337,13 +3508,13 @@ callback_list_remove(struct serviced_query* sq, void* cb_arg)
|
||||
|
||||
void outnet_serviced_query_stop(struct serviced_query* sq, void* cb_arg)
|
||||
{
|
||||
if(!sq)
|
||||
if(!sq)
|
||||
return;
|
||||
callback_list_remove(sq, cb_arg);
|
||||
/* if callbacks() routine scheduled deletion, let it do that */
|
||||
if(!sq->cblist && !sq->to_be_deleted) {
|
||||
if(!sq->cblist && !sq->busy && !sq->to_be_deleted) {
|
||||
(void)rbtree_delete(sq->outnet->serviced, sq);
|
||||
serviced_delete(sq);
|
||||
serviced_delete(sq);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3435,7 +3606,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");
|
||||
@@ -3523,8 +3694,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) {
|
||||
@@ -3599,8 +3770,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) {
|
||||
|
||||
@@ -43,7 +43,9 @@
|
||||
#ifndef OUTSIDE_NETWORK_H
|
||||
#define OUTSIDE_NETWORK_H
|
||||
|
||||
#include "util/alloc.h"
|
||||
#include "util/rbtree.h"
|
||||
#include "util/regional.h"
|
||||
#include "util/netevent.h"
|
||||
#include "dnstap/dnstap_config.h"
|
||||
struct pending;
|
||||
@@ -111,6 +113,8 @@ struct outside_network {
|
||||
/** if we perform udp-connect, connect() for UDP socket to mitigate
|
||||
* ICMP side channel leakage */
|
||||
int udp_connect;
|
||||
/** number of udp packets sent. */
|
||||
size_t num_udp_outgoing;
|
||||
|
||||
/** array of outgoing IP4 interfaces */
|
||||
struct port_if* ip4_ifs;
|
||||
@@ -412,6 +416,8 @@ struct waiting_tcp {
|
||||
char* tls_auth_name;
|
||||
/** the packet was involved in an error, to stop looping errors */
|
||||
int error_count;
|
||||
/** if true, the item is at the cb_and_decommission stage */
|
||||
int in_cb_and_decommission;
|
||||
#ifdef USE_DNSTAP
|
||||
/** serviced query pointer for dnstap to get logging info, if nonNULL*/
|
||||
struct serviced_query* sq;
|
||||
@@ -450,6 +456,10 @@ struct serviced_query {
|
||||
uint8_t* qbuf;
|
||||
/** length of qbuf. */
|
||||
size_t qbuflen;
|
||||
/** raw_qbuf for sending precreated packets */
|
||||
const uint8_t *raw_qbuf;
|
||||
/** Precreated packet length */
|
||||
size_t raw_qbuf_len;
|
||||
/** If an EDNS section is included, the DO/CD bit will be turned on. */
|
||||
int dnssec;
|
||||
/** We want signatures, or else the answer is likely useless */
|
||||
@@ -512,6 +522,15 @@ struct serviced_query {
|
||||
void* pending;
|
||||
/** block size with which to pad encrypted queries (default: 128) */
|
||||
size_t padding_block_size;
|
||||
/** region for this serviced query. Will be cleared when this
|
||||
* serviced_query will be deleted */
|
||||
struct regional* region;
|
||||
/** allocation service for the region */
|
||||
struct alloc_cache* alloc;
|
||||
/** flash timer to start the net I/O as a separate event */
|
||||
struct comm_timer* timer;
|
||||
/** true if serviced_query is currently doing net I/O and may block */
|
||||
int busy;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -619,6 +638,7 @@ void pending_delete(struct outside_network* outnet, struct pending* p);
|
||||
* @param want_dnssec: signatures are needed, without EDNS the answer is
|
||||
* likely to be useless.
|
||||
* @param nocaps: ignore use_caps_for_id and use unperturbed qname.
|
||||
* @param check_ratelimit: if set, will check ratelimit before sending out.
|
||||
* @param tcp_upstream: use TCP for upstream queries.
|
||||
* @param ssl_upstream: use SSL for upstream queries.
|
||||
* @param tls_auth_name: when ssl_upstream is true, use this name to check
|
||||
@@ -635,16 +655,18 @@ void pending_delete(struct outside_network* outnet, struct pending* p);
|
||||
* @param callback_arg: user argument to callback function.
|
||||
* @param buff: scratch buffer to create query contents in. Empty on exit.
|
||||
* @param env: the module environment.
|
||||
* @param was_ratelimited: it will signal back if the query failed to pass the
|
||||
* ratelimit check.
|
||||
* @return 0 on error, or pointer to serviced query that is used to answer
|
||||
* this serviced query may be shared with other callbacks as well.
|
||||
*/
|
||||
struct serviced_query* outnet_serviced_query(struct outside_network* outnet,
|
||||
struct query_info* qinfo, uint16_t flags, int dnssec, int want_dnssec,
|
||||
int nocaps, int tcp_upstream, int ssl_upstream, char* tls_auth_name,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* zone,
|
||||
size_t zonelen, struct module_qstate* qstate,
|
||||
int nocaps, int check_ratelimit, int tcp_upstream, int ssl_upstream,
|
||||
char* tls_auth_name, struct sockaddr_storage* addr, socklen_t addrlen,
|
||||
uint8_t* zone, size_t zonelen, struct module_qstate* qstate,
|
||||
comm_point_callback_type* callback, void* callback_arg,
|
||||
struct sldns_buffer* buff, struct module_env* env);
|
||||
struct sldns_buffer* buff, struct module_env* env, int* was_ratelimited);
|
||||
|
||||
/**
|
||||
* Remove service query callback.
|
||||
@@ -700,6 +722,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,
|
||||
@@ -785,6 +831,9 @@ void pending_udp_timer_delay_cb(void *arg);
|
||||
/** callback for outgoing TCP timer event */
|
||||
void outnet_tcptimer(void* arg);
|
||||
|
||||
/** callback to send serviced queries */
|
||||
void serviced_timer_cb(void *arg);
|
||||
|
||||
/** callback for serviced query UDP answers */
|
||||
int serviced_udp_callback(struct comm_point* c, void* arg, int error,
|
||||
struct comm_reply* rep);
|
||||
|
||||
+70
-33
@@ -526,13 +526,13 @@ rpz_create(struct config_auth* p)
|
||||
size_t nmlen = sizeof(nm);
|
||||
|
||||
if(!p->rpz_cname) {
|
||||
log_err("RPZ override with cname action found, but no "
|
||||
log_err("rpz: override with cname action found, but no "
|
||||
"rpz-cname-override configured");
|
||||
goto err;
|
||||
}
|
||||
|
||||
if(sldns_str2wire_dname_buf(p->rpz_cname, nm, &nmlen) != 0) {
|
||||
log_err("cannot parse RPZ cname override: %s",
|
||||
log_err("rpz: cannot parse cname override: %s",
|
||||
p->rpz_cname);
|
||||
goto err;
|
||||
}
|
||||
@@ -542,6 +542,7 @@ rpz_create(struct config_auth* p)
|
||||
}
|
||||
}
|
||||
r->log = p->rpz_log;
|
||||
r->signal_nxdomain_ra = p->rpz_signal_nxdomain_ra;
|
||||
if(p->rpz_log_name) {
|
||||
if(!(r->log_name = strdup(p->rpz_log_name))) {
|
||||
log_err("malloc failure on RPZ log_name strdup");
|
||||
@@ -613,7 +614,7 @@ rpz_insert_local_zones_trigger(struct local_zones* lz, uint8_t* dname,
|
||||
return; /* no need to log these types as unsupported */
|
||||
}
|
||||
dname_str(dname, str);
|
||||
verbose(VERB_ALGO, "RPZ: qname trigger, %s skipping unsupported action: %s",
|
||||
verbose(VERB_ALGO, "rpz: qname trigger, %s skipping unsupported action: %s",
|
||||
str, rpz_action_to_string(a));
|
||||
free(dname);
|
||||
return;
|
||||
@@ -836,7 +837,7 @@ rpz_report_rrset_error(const char* msg, uint8_t* rr, size_t rr_len) {
|
||||
}
|
||||
|
||||
/* from localzone.c; difference is we don't have a dname */
|
||||
struct local_rrset*
|
||||
static struct local_rrset*
|
||||
rpz_clientip_new_rrset(struct regional* region,
|
||||
struct clientip_synthesized_rr* raddr, uint16_t rrtype, uint16_t rrclass)
|
||||
{
|
||||
@@ -998,7 +999,7 @@ rpz_insert_response_ip_trigger(struct rpz* r, uint8_t* dname, size_t dnamelen,
|
||||
rpz_action_to_respip_action(a) == respip_invalid) {
|
||||
char str[255+1];
|
||||
dname_str(dname, str);
|
||||
verbose(VERB_ALGO, "RPZ: respip trigger, %s skipping unsupported action: %s",
|
||||
verbose(VERB_ALGO, "rpz: respip trigger, %s skipping unsupported action: %s",
|
||||
str, rpz_action_to_string(a));
|
||||
return 0;
|
||||
}
|
||||
@@ -1384,18 +1385,20 @@ log_rpz_apply(char* trigger, uint8_t* dname, struct addr_tree_node* addrnode,
|
||||
if(dname) {
|
||||
dname_str(dname, dnamestr);
|
||||
} else if(addrnode) {
|
||||
char a[128];
|
||||
addr_to_str(&addrnode->addr, addrnode->addrlen, a, sizeof(a));
|
||||
snprintf(dnamestr, sizeof(dnamestr), "%s/%d", a, addrnode->net);
|
||||
char addrbuf[128];
|
||||
addr_to_str(&addrnode->addr, addrnode->addrlen, addrbuf, sizeof(addrbuf));
|
||||
snprintf(dnamestr, sizeof(dnamestr), "%s/%d", addrbuf, addrnode->net);
|
||||
} else {
|
||||
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;
|
||||
@@ -1467,7 +1470,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,7 +1564,9 @@ rpz_local_encode(struct module_env* env, struct query_info* qinfo,
|
||||
}
|
||||
|
||||
static struct local_rrset*
|
||||
rpz_find_synthesized_rrset(int qtype, struct clientip_synthesized_rr* data) {
|
||||
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;
|
||||
@@ -1697,7 +1704,7 @@ rpz_synthesize_nodata(struct rpz* ATTR_UNUSED(r), struct module_qstate* ms,
|
||||
if(msg == NULL) { return msg; }
|
||||
msg->qinfo = *qinfo;
|
||||
msg->rep = construct_reply_info_base(ms->region,
|
||||
LDNS_RCODE_NOERROR | BIT_RD | BIT_QR | BIT_AA | BIT_RA,
|
||||
LDNS_RCODE_NOERROR | BIT_QR | BIT_AA | BIT_RA,
|
||||
1, /* qd */
|
||||
0, /* ttl */
|
||||
0, /* prettl */
|
||||
@@ -1715,14 +1722,18 @@ rpz_synthesize_nodata(struct rpz* ATTR_UNUSED(r), struct module_qstate* ms,
|
||||
}
|
||||
|
||||
static inline struct dns_msg*
|
||||
rpz_synthesize_nxdomain(struct rpz* ATTR_UNUSED(r), struct module_qstate* ms,
|
||||
rpz_synthesize_nxdomain(struct rpz* r, struct module_qstate* ms,
|
||||
struct query_info* qinfo, struct auth_zone* az)
|
||||
{
|
||||
struct dns_msg* msg = rpz_dns_msg_new(ms->region);
|
||||
uint16_t flags;
|
||||
if(msg == NULL) { return msg; }
|
||||
msg->qinfo = *qinfo;
|
||||
flags = LDNS_RCODE_NXDOMAIN | BIT_QR | BIT_AA | BIT_RA;
|
||||
if(r->signal_nxdomain_ra)
|
||||
flags &= ~BIT_RA;
|
||||
msg->rep = construct_reply_info_base(ms->region,
|
||||
LDNS_RCODE_NXDOMAIN | BIT_RD | BIT_QR | BIT_AA | BIT_RA,
|
||||
flags,
|
||||
1, /* qd */
|
||||
0, /* ttl */
|
||||
0, /* prettl */
|
||||
@@ -1752,7 +1763,7 @@ rpz_synthesize_localdata_from_rrset(struct rpz* ATTR_UNUSED(r), struct module_qs
|
||||
if(msg == NULL) { return NULL; }
|
||||
|
||||
new_reply_info = construct_reply_info_base(ms->region,
|
||||
LDNS_RCODE_NOERROR | BIT_RD | BIT_QR | BIT_AA | BIT_RA,
|
||||
LDNS_RCODE_NOERROR | BIT_QR | BIT_AA | BIT_RA,
|
||||
1, /* qd */
|
||||
0, /* ttl */
|
||||
0, /* prettl */
|
||||
@@ -1922,6 +1933,9 @@ rpz_synthesize_qname_localdata(struct module_env* env, struct rpz* r,
|
||||
|
||||
ret = local_zones_zone_answer(z, env, qinfo, edns, repinfo, buf, temp,
|
||||
0 /* no local data used */, lzt);
|
||||
if(r->signal_nxdomain_ra && LDNS_RCODE_WIRE(sldns_buffer_begin(buf))
|
||||
== LDNS_RCODE_NXDOMAIN)
|
||||
LDNS_RA_CLR(sldns_buffer_begin(buf));
|
||||
if(r->log) {
|
||||
log_rpz_apply("qname", z->name, NULL, localzone_type_to_rpz_action(lzt),
|
||||
qinfo, repinfo, NULL, r->log_name);
|
||||
@@ -1930,7 +1944,7 @@ rpz_synthesize_qname_localdata(struct module_env* env, struct rpz* r,
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct clientip_synthesized_rr*
|
||||
static struct clientip_synthesized_rr*
|
||||
rpz_delegation_point_ipbased_trigger_lookup(struct rpz* rpz, struct iter_qstate* is)
|
||||
{
|
||||
struct delegpt_addr* cursor;
|
||||
@@ -1947,7 +1961,7 @@ rpz_delegation_point_ipbased_trigger_lookup(struct rpz* rpz, struct iter_qstate*
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct dns_msg*
|
||||
static struct dns_msg*
|
||||
rpz_apply_nsip_trigger(struct module_qstate* ms, struct rpz* r,
|
||||
struct clientip_synthesized_rr* raddr, struct auth_zone* az)
|
||||
{
|
||||
@@ -1989,6 +2003,7 @@ rpz_apply_nsip_trigger(struct module_qstate* ms, struct rpz* r,
|
||||
break;
|
||||
case RPZ_PASSTHRU_ACTION:
|
||||
ret = NULL;
|
||||
ms->rpz_passthru = 1;
|
||||
break;
|
||||
default:
|
||||
verbose(VERB_ALGO, "rpz: nsip: bug: unhandled or invalid action: '%s'",
|
||||
@@ -2006,7 +2021,7 @@ done:
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct dns_msg*
|
||||
static struct dns_msg*
|
||||
rpz_apply_nsdname_trigger(struct module_qstate* ms, struct rpz* r,
|
||||
struct local_zone* z, struct matched_delegation_point const* match,
|
||||
struct auth_zone* az)
|
||||
@@ -2043,6 +2058,7 @@ rpz_apply_nsdname_trigger(struct module_qstate* ms, struct rpz* r,
|
||||
break;
|
||||
case RPZ_PASSTHRU_ACTION:
|
||||
ret = NULL;
|
||||
ms->rpz_passthru = 1;
|
||||
break;
|
||||
default:
|
||||
verbose(VERB_ALGO, "rpz: nsip: bug: unhandled or invalid action: '%s'",
|
||||
@@ -2106,6 +2122,11 @@ rpz_callback_from_iterator_module(struct module_qstate* ms, struct iter_qstate*
|
||||
struct local_zone* z = NULL;
|
||||
struct matched_delegation_point match = {0};
|
||||
|
||||
if(ms->rpz_passthru) {
|
||||
verbose(VERB_ALGO, "query is rpz_passthru, no further processing");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(ms->env == NULL || ms->env->auth_zones == NULL) { return 0; }
|
||||
|
||||
az = ms->env->auth_zones;
|
||||
@@ -2147,18 +2168,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,
|
||||
@@ -2171,6 +2190,11 @@ struct dns_msg* rpz_callback_from_iterator_cname(struct module_qstate* ms,
|
||||
enum localzone_type lzt;
|
||||
struct dns_msg* ret = NULL;
|
||||
|
||||
if(ms->rpz_passthru) {
|
||||
verbose(VERB_ALGO, "query is rpz_passthru, no further processing");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(ms->env == NULL || ms->env->auth_zones == NULL) { return 0; }
|
||||
az = ms->env->auth_zones;
|
||||
|
||||
@@ -2245,6 +2269,7 @@ struct dns_msg* rpz_callback_from_iterator_cname(struct module_qstate* ms,
|
||||
break;
|
||||
case RPZ_PASSTHRU_ACTION:
|
||||
ret = NULL;
|
||||
ms->rpz_passthru = 1;
|
||||
break;
|
||||
default:
|
||||
verbose(VERB_ALGO, "rpz: qname trigger after cname: bug: unhandled or invalid action: '%s'",
|
||||
@@ -2262,7 +2287,8 @@ rpz_apply_maybe_clientip_trigger(struct auth_zones* az, struct module_env* env,
|
||||
uint8_t* taglist, size_t taglen, struct ub_server_stats* stats,
|
||||
sldns_buffer* buf, struct regional* temp,
|
||||
/* output parameters */
|
||||
struct local_zone** z_out, struct auth_zone** a_out, struct rpz** r_out)
|
||||
struct local_zone** z_out, struct auth_zone** a_out, struct rpz** r_out,
|
||||
int* passthru)
|
||||
{
|
||||
int ret = 0;
|
||||
enum rpz_action client_action;
|
||||
@@ -2270,7 +2296,9 @@ rpz_apply_maybe_clientip_trigger(struct auth_zones* az, struct module_env* env,
|
||||
az, qinfo, repinfo, taglist, taglen, stats, z_out, a_out, r_out);
|
||||
|
||||
client_action = ((node == NULL) ? RPZ_INVALID_ACTION : node->action);
|
||||
|
||||
if(client_action == RPZ_PASSTHRU_ACTION) {
|
||||
*passthru = 1;
|
||||
}
|
||||
if(*z_out == NULL || (client_action != RPZ_INVALID_ACTION &&
|
||||
client_action != RPZ_PASSTHRU_ACTION)) {
|
||||
if(client_action == RPZ_PASSTHRU_ACTION
|
||||
@@ -2295,6 +2323,10 @@ rpz_apply_maybe_clientip_trigger(struct auth_zones* az, struct module_env* env,
|
||||
local_zones_zone_answer(*z_out /*likely NULL, no zone*/, env, qinfo, edns,
|
||||
repinfo, buf, temp, 0 /* no local data used */,
|
||||
rpz_action_to_localzone_type(client_action));
|
||||
if(*r_out && (*r_out)->signal_nxdomain_ra &&
|
||||
LDNS_RCODE_WIRE(sldns_buffer_begin(buf))
|
||||
== LDNS_RCODE_NXDOMAIN)
|
||||
LDNS_RA_CLR(sldns_buffer_begin(buf));
|
||||
}
|
||||
ret = 1;
|
||||
goto done;
|
||||
@@ -2311,7 +2343,7 @@ int
|
||||
rpz_callback_from_worker_request(struct auth_zones* az, struct module_env* env,
|
||||
struct query_info* qinfo, struct edns_data* edns, sldns_buffer* buf,
|
||||
struct regional* temp, struct comm_reply* repinfo, uint8_t* taglist,
|
||||
size_t taglen, struct ub_server_stats* stats)
|
||||
size_t taglen, struct ub_server_stats* stats, int* passthru)
|
||||
{
|
||||
struct rpz* r = NULL;
|
||||
struct auth_zone* a = NULL;
|
||||
@@ -2320,7 +2352,8 @@ rpz_callback_from_worker_request(struct auth_zones* az, struct module_env* env,
|
||||
enum localzone_type lzt;
|
||||
|
||||
int clientip_trigger = rpz_apply_maybe_clientip_trigger(az, env, qinfo,
|
||||
edns, repinfo, taglist, taglen, stats, buf, temp, &z, &a, &r);
|
||||
edns, repinfo, taglist, taglen, stats, buf, temp, &z, &a, &r,
|
||||
passthru);
|
||||
if(clientip_trigger >= 0) {
|
||||
if(a) {
|
||||
lock_rw_unlock(&a->lock);
|
||||
@@ -2345,6 +2378,10 @@ rpz_callback_from_worker_request(struct auth_zones* az, struct module_env* env,
|
||||
} else {
|
||||
lzt = rpz_action_to_localzone_type(r->action_override);
|
||||
}
|
||||
if(r->action_override == RPZ_PASSTHRU_ACTION ||
|
||||
lzt == local_zone_always_transparent /* RPZ_PASSTHRU_ACTION */) {
|
||||
*passthru = 1;
|
||||
}
|
||||
|
||||
if(verbosity >= VERB_ALGO) {
|
||||
char nm[255+1], zn[255+1];
|
||||
|
||||
+5
-1
@@ -123,6 +123,8 @@ struct rpz {
|
||||
struct ub_packed_rrset_key* cname_override;
|
||||
int log;
|
||||
char* log_name;
|
||||
/** signal NXDOMAIN blocked with unset RA flag */
|
||||
int signal_nxdomain_ra;
|
||||
struct regional* region;
|
||||
int disabled;
|
||||
};
|
||||
@@ -174,12 +176,14 @@ void rpz_remove_rr(struct rpz* r, size_t aznamelen, uint8_t* dname,
|
||||
* @param taglist: taglist to lookup.
|
||||
* @param taglen: length of taglist.
|
||||
* @param stats: worker stats struct
|
||||
* @param passthru: returns if the query can passthru further rpz processing.
|
||||
* @return: 1 if client answer is ready, 0 to continue resolving
|
||||
*/
|
||||
int rpz_callback_from_worker_request(struct auth_zones* az, struct module_env* env,
|
||||
struct query_info* qinfo, struct edns_data* edns, sldns_buffer* buf,
|
||||
struct regional* temp, struct comm_reply* repinfo,
|
||||
uint8_t* taglist, size_t taglen, struct ub_server_stats* stats);
|
||||
uint8_t* taglist, size_t taglen, struct ub_server_stats* stats,
|
||||
int* passthru);
|
||||
|
||||
/**
|
||||
* Callback to process when the iterator module is about to send queries.
|
||||
|
||||
+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
|
||||
|
||||
+4
-2
@@ -250,7 +250,8 @@ sldns_key_buf2dsa_raw(unsigned char* key, size_t len)
|
||||
if(!(dsa = DSA_new())) {
|
||||
return NULL;
|
||||
}
|
||||
#if OPENSSL_VERSION_NUMBER < 0x10100000 || defined(HAVE_LIBRESSL)
|
||||
#if OPENSSL_VERSION_NUMBER < 0x10100000 || \
|
||||
(defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER < 0x02070000f)
|
||||
#ifndef S_SPLINT_S
|
||||
dsa->p = P;
|
||||
dsa->q = Q;
|
||||
@@ -428,7 +429,8 @@ sldns_key_buf2rsa_raw(unsigned char* key, size_t len)
|
||||
BN_free(modulus);
|
||||
return NULL;
|
||||
}
|
||||
#if OPENSSL_VERSION_NUMBER < 0x10100000 || defined(HAVE_LIBRESSL)
|
||||
#if OPENSSL_VERSION_NUMBER < 0x10100000 || \
|
||||
(defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER < 0x02070000f)
|
||||
#ifndef S_SPLINT_S
|
||||
rsa->n = modulus;
|
||||
rsa->e = exponent;
|
||||
|
||||
+47
-8
@@ -34,7 +34,7 @@ sldns_fget_token_l(FILE *f, char *token, const char *delim, size_t limit, int *l
|
||||
{
|
||||
int c, prev_c;
|
||||
int p; /* 0 -> no parentheses seen, >0 nr of ( seen */
|
||||
int com, quoted;
|
||||
int com, quoted, only_blank;
|
||||
char *t;
|
||||
size_t i;
|
||||
const char *d;
|
||||
@@ -53,6 +53,7 @@ sldns_fget_token_l(FILE *f, char *token, const char *delim, size_t limit, int *l
|
||||
com = 0;
|
||||
quoted = 0;
|
||||
prev_c = 0;
|
||||
only_blank = 1; /* Assume we got only <blank> until now */
|
||||
t = token;
|
||||
if (del[0] == '"') {
|
||||
quoted = 1;
|
||||
@@ -101,6 +102,22 @@ sldns_fget_token_l(FILE *f, char *token, const char *delim, size_t limit, int *l
|
||||
if (line_nr) {
|
||||
*line_nr = *line_nr + 1;
|
||||
}
|
||||
if (only_blank && i > 0) {
|
||||
/* Got only <blank> so far. Reset and try
|
||||
* again with the next line.
|
||||
*/
|
||||
i = 0;
|
||||
t = token;
|
||||
}
|
||||
if (p == 0) {
|
||||
/* If p != 0 then the next line is a continuation. So
|
||||
* we assume that the next line starts with a blank only
|
||||
* if it is actually a new line.
|
||||
*/
|
||||
only_blank = 1; /* Assume next line starts with
|
||||
* <blank>.
|
||||
*/
|
||||
}
|
||||
if (p == 0 && i > 0) {
|
||||
goto tokenread;
|
||||
} else {
|
||||
@@ -131,12 +148,29 @@ sldns_fget_token_l(FILE *f, char *token, const char *delim, size_t limit, int *l
|
||||
|
||||
/* check if we hit the delim */
|
||||
for (d = del; *d; d++) {
|
||||
if (c == *d && i > 0 && prev_c != '\\' && p == 0) {
|
||||
if (c == '\n' && line_nr) {
|
||||
*line_nr = *line_nr + 1;
|
||||
}
|
||||
goto tokenread;
|
||||
if (c == *d)
|
||||
break;
|
||||
}
|
||||
|
||||
if (c == *d && i > 0 && prev_c != '\\' && p == 0) {
|
||||
if (c == '\n' && line_nr) {
|
||||
*line_nr = *line_nr + 1;
|
||||
}
|
||||
if (only_blank) {
|
||||
/* Got only <blank> so far. Reset and
|
||||
* try again with the next line.
|
||||
*/
|
||||
i = 0;
|
||||
t = token;
|
||||
only_blank = 1;
|
||||
prev_c = c;
|
||||
continue;
|
||||
}
|
||||
goto tokenread;
|
||||
}
|
||||
if (c != ' ' && c != '\t') {
|
||||
/* Found something that is not <blank> */
|
||||
only_blank= 0;
|
||||
}
|
||||
if (c != '\0' && c != '\n') {
|
||||
i++;
|
||||
@@ -149,8 +183,13 @@ sldns_fget_token_l(FILE *f, char *token, const char *delim, size_t limit, int *l
|
||||
if (c != '\0' && c != '\n') {
|
||||
*t++ = c;
|
||||
}
|
||||
if (c == '\n' && line_nr) {
|
||||
*line_nr = *line_nr + 1;
|
||||
if (c == '\n') {
|
||||
if (line_nr) {
|
||||
*line_nr = *line_nr + 1;
|
||||
}
|
||||
only_blank = 1; /* Assume next line starts with
|
||||
* <blank>.
|
||||
*/
|
||||
}
|
||||
if (c == '\\' && prev_c == '\\')
|
||||
prev_c = 0;
|
||||
|
||||
+35
-1
@@ -209,11 +209,13 @@ sldns_hexdigit_to_int(char ch)
|
||||
}
|
||||
|
||||
uint32_t
|
||||
sldns_str2period(const char *nptr, const char **endptr)
|
||||
sldns_str2period(const char *nptr, const char **endptr, int* overflow)
|
||||
{
|
||||
int sign = 0;
|
||||
uint32_t i = 0;
|
||||
uint32_t seconds = 0;
|
||||
const uint32_t maxint = 0xffffffff;
|
||||
*overflow = 0;
|
||||
|
||||
for(*endptr = nptr; **endptr; (*endptr)++) {
|
||||
switch (**endptr) {
|
||||
@@ -236,26 +238,46 @@ sldns_str2period(const char *nptr, const char **endptr)
|
||||
break;
|
||||
case 's':
|
||||
case 'S':
|
||||
if(seconds > maxint-i) {
|
||||
*overflow = 1;
|
||||
return 0;
|
||||
}
|
||||
seconds += i;
|
||||
i = 0;
|
||||
break;
|
||||
case 'm':
|
||||
case 'M':
|
||||
if(i > maxint/60 || seconds > maxint-(i*60)) {
|
||||
*overflow = 1;
|
||||
return 0;
|
||||
}
|
||||
seconds += i * 60;
|
||||
i = 0;
|
||||
break;
|
||||
case 'h':
|
||||
case 'H':
|
||||
if(i > maxint/(60*60) || seconds > maxint-(i*60*60)) {
|
||||
*overflow = 1;
|
||||
return 0;
|
||||
}
|
||||
seconds += i * 60 * 60;
|
||||
i = 0;
|
||||
break;
|
||||
case 'd':
|
||||
case 'D':
|
||||
if(i > maxint/(60*60*24) || seconds > maxint-(i*60*60*24)) {
|
||||
*overflow = 1;
|
||||
return 0;
|
||||
}
|
||||
seconds += i * 60 * 60 * 24;
|
||||
i = 0;
|
||||
break;
|
||||
case 'w':
|
||||
case 'W':
|
||||
if(i > maxint/(60*60*24*7) || seconds > maxint-(i*60*60*24*7)) {
|
||||
*overflow = 1;
|
||||
return 0;
|
||||
}
|
||||
seconds += i * 60 * 60 * 24 * 7;
|
||||
i = 0;
|
||||
break;
|
||||
@@ -269,15 +291,27 @@ sldns_str2period(const char *nptr, const char **endptr)
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
if(i > maxint/10 || i*10 > maxint - (**endptr - '0')) {
|
||||
*overflow = 1;
|
||||
return 0;
|
||||
}
|
||||
i *= 10;
|
||||
i += (**endptr - '0');
|
||||
break;
|
||||
default:
|
||||
if(seconds > maxint-i) {
|
||||
*overflow = 1;
|
||||
return 0;
|
||||
}
|
||||
seconds += i;
|
||||
/* disregard signedness */
|
||||
return seconds;
|
||||
}
|
||||
}
|
||||
if(seconds > maxint-i) {
|
||||
*overflow = 1;
|
||||
return 0;
|
||||
}
|
||||
seconds += i;
|
||||
/* disregard signedness */
|
||||
return seconds;
|
||||
|
||||
+3
-1
@@ -74,9 +74,11 @@ struct tm * sldns_serial_arithmetics_gmtime_r(int32_t time, time_t now, struct t
|
||||
* converts a ttl value (like 5d2h) to a long.
|
||||
* \param[in] nptr the start of the string
|
||||
* \param[out] endptr points to the last char in case of error
|
||||
* \param[out] overflow returns if the string causes integer overflow error,
|
||||
* the number is too big, string of digits too long.
|
||||
* \return the convert duration value
|
||||
*/
|
||||
uint32_t sldns_str2period(const char *nptr, const char **endptr);
|
||||
uint32_t sldns_str2period(const char *nptr, const char **endptr, int* overflow);
|
||||
|
||||
/**
|
||||
* Returns the int value of the given (hex) digit
|
||||
|
||||
@@ -97,18 +97,22 @@ extern "C" {
|
||||
#define QDCOUNT(wirebuf) (ntohs(*(uint16_t *)(wirebuf+QDCOUNT_OFF)))
|
||||
*/
|
||||
#define LDNS_QDCOUNT(wirebuf) (sldns_read_uint16(wirebuf+LDNS_QDCOUNT_OFF))
|
||||
#define LDNS_QDCOUNT_SET(wirebuf, i) (sldns_write_uint16(wirebuf+LDNS_QDCOUNT_OFF, i))
|
||||
|
||||
/* Counter of the answer section */
|
||||
#define LDNS_ANCOUNT_OFF 6
|
||||
#define LDNS_ANCOUNT(wirebuf) (sldns_read_uint16(wirebuf+LDNS_ANCOUNT_OFF))
|
||||
#define LDNS_ANCOUNT_SET(wirebuf, i) (sldns_write_uint16(wirebuf+LDNS_ANCOUNT_OFF, i))
|
||||
|
||||
/* Counter of the authority section */
|
||||
#define LDNS_NSCOUNT_OFF 8
|
||||
#define LDNS_NSCOUNT(wirebuf) (sldns_read_uint16(wirebuf+LDNS_NSCOUNT_OFF))
|
||||
#define LDNS_NSCOUNT_SET(wirebuf, i) (sldns_write_uint16(wirebuf+LDNS_NSCOUNT_OFF, i))
|
||||
|
||||
/* Counter of the additional section */
|
||||
#define LDNS_ARCOUNT_OFF 10
|
||||
#define LDNS_ARCOUNT(wirebuf) (sldns_read_uint16(wirebuf+LDNS_ARCOUNT_OFF))
|
||||
#define LDNS_ARCOUNT_SET(wirebuf, i) (sldns_write_uint16(wirebuf+LDNS_ARCOUNT_OFF, i))
|
||||
|
||||
/**
|
||||
* The sections of a packet
|
||||
|
||||
+2
-2
@@ -381,9 +381,9 @@ static sldns_rr_descriptor rdata_field_descriptors[] = {
|
||||
/* 63 */
|
||||
{LDNS_RR_TYPE_ZONEMD, "ZONEMD", 4, 4, type_zonemd_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
|
||||
/* 64 */
|
||||
{LDNS_RR_TYPE_SVCB, "SVCB", 2, 2, type_svcb_wireformat, LDNS_RDF_TYPE_SVCPARAM, LDNS_RR_NO_COMPRESS, 0 },
|
||||
{LDNS_RR_TYPE_SVCB, "SVCB", 2, 2, type_svcb_wireformat, LDNS_RDF_TYPE_SVCPARAM, LDNS_RR_NO_COMPRESS, 1 },
|
||||
/* 65 */
|
||||
{LDNS_RR_TYPE_HTTPS, "HTTPS", 2, 2, type_svcb_wireformat, LDNS_RDF_TYPE_SVCPARAM, LDNS_RR_NO_COMPRESS, 0 },
|
||||
{LDNS_RR_TYPE_HTTPS, "HTTPS", 2, 2, type_svcb_wireformat, LDNS_RDF_TYPE_SVCPARAM, LDNS_RR_NO_COMPRESS, 1 },
|
||||
{(enum sldns_enum_rr_type)0, "TYPE66", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
|
||||
{(enum sldns_enum_rr_type)0, "TYPE67", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
|
||||
{(enum sldns_enum_rr_type)0, "TYPE68", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
|
||||
|
||||
@@ -435,10 +435,42 @@ enum sldns_enum_edns_option
|
||||
LDNS_EDNS_CLIENT_SUBNET = 8, /* RFC7871 */
|
||||
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 */
|
||||
};
|
||||
typedef enum sldns_enum_edns_option sldns_edns_option;
|
||||
|
||||
enum sldns_enum_ede_code
|
||||
{
|
||||
LDNS_EDE_NONE = -1, /* EDE undefined for internal use */
|
||||
LDNS_EDE_OTHER = 0,
|
||||
LDNS_EDE_UNSUPPORTED_DNSKEY_ALG = 1,
|
||||
LDNS_EDE_UNSUPPORTED_DS_DIGEST = 2,
|
||||
LDNS_EDE_STALE_ANSWER = 3,
|
||||
LDNS_EDE_FORGED_ANSWER = 4,
|
||||
LDNS_EDE_DNSSEC_INDETERMINATE = 5,
|
||||
LDNS_EDE_DNSSEC_BOGUS = 6,
|
||||
LDNS_EDE_SIGNATURE_EXPIRED = 7,
|
||||
LDNS_EDE_SIGNATURE_NOT_YET_VALID = 8,
|
||||
LDNS_EDE_DNSKEY_MISSING = 9,
|
||||
LDNS_EDE_RRSIGS_MISSING = 10,
|
||||
LDNS_EDE_NO_ZONE_KEY_BIT_SET = 11,
|
||||
LDNS_EDE_NSEC_MISSING = 12,
|
||||
LDNS_EDE_CACHED_ERROR = 13,
|
||||
LDNS_EDE_NOT_READY = 14,
|
||||
LDNS_EDE_BLOCKED = 15,
|
||||
LDNS_EDE_CENSORED = 16,
|
||||
LDNS_EDE_FILTERED = 17,
|
||||
LDNS_EDE_PROHIBITED = 18,
|
||||
LDNS_EDE_STALE_NXDOMAIN_ANSWER = 19,
|
||||
LDNS_EDE_NOT_AUTHORITATIVE = 20,
|
||||
LDNS_EDE_NOT_SUPPORTED = 21,
|
||||
LDNS_EDE_NO_REACHABLE_AUTHORITY = 22,
|
||||
LDNS_EDE_NETWORK_ERROR = 23,
|
||||
LDNS_EDE_INVALID_DATA = 24,
|
||||
};
|
||||
typedef enum sldns_enum_ede_code sldns_ede_code;
|
||||
|
||||
#define LDNS_EDNS_MASK_DO_BIT 0x8000
|
||||
|
||||
/** TSIG and TKEY extended rcodes (16bit), 0-15 are the normal rcodes. */
|
||||
|
||||
+35
-15
@@ -25,8 +25,10 @@
|
||||
#include <netdb.h>
|
||||
#endif
|
||||
|
||||
/** bits for the offset */
|
||||
#define RET_OFFSET_MASK (((unsigned)(~LDNS_WIREPARSE_MASK))>>LDNS_WIREPARSE_SHIFT)
|
||||
/** return an error */
|
||||
#define RET_ERR(e, off) ((int)((e)|((off)<<LDNS_WIREPARSE_SHIFT)))
|
||||
#define RET_ERR(e, off) ((int)(((e)&LDNS_WIREPARSE_MASK)|(((off)&RET_OFFSET_MASK)<<LDNS_WIREPARSE_SHIFT)))
|
||||
/** Move parse error but keep its ID */
|
||||
#define RET_ERR_SHIFT(e, move) RET_ERR(LDNS_WIREPARSE_ERROR(e), LDNS_WIREPARSE_OFFSET(e)+(move));
|
||||
|
||||
@@ -247,11 +249,16 @@ rrinternal_get_ttl(sldns_buffer* strbuf, char* token, size_t token_len,
|
||||
int* not_there, uint32_t* ttl, uint32_t default_ttl)
|
||||
{
|
||||
const char* endptr;
|
||||
int overflow;
|
||||
if(sldns_bget_token(strbuf, token, "\t\n ", token_len) == -1) {
|
||||
return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_TTL,
|
||||
sldns_buffer_position(strbuf));
|
||||
}
|
||||
*ttl = (uint32_t) sldns_str2period(token, &endptr);
|
||||
*ttl = (uint32_t) sldns_str2period(token, &endptr, &overflow);
|
||||
if(overflow) {
|
||||
return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_INTEGER_OVERFLOW,
|
||||
sldns_buffer_position(strbuf));
|
||||
}
|
||||
|
||||
if (strlen(token) > 0 && !isdigit((unsigned char)token[0])) {
|
||||
*not_there = 1;
|
||||
@@ -371,7 +378,8 @@ rrinternal_get_quoted(sldns_buffer* strbuf, const char** delimiters,
|
||||
|
||||
/* skip spaces */
|
||||
while(sldns_buffer_remaining(strbuf) > 0 &&
|
||||
*(sldns_buffer_current(strbuf)) == ' ') {
|
||||
(*(sldns_buffer_current(strbuf)) == ' ' ||
|
||||
*(sldns_buffer_current(strbuf)) == '\t')) {
|
||||
sldns_buffer_skip(strbuf, 1);
|
||||
}
|
||||
|
||||
@@ -543,9 +551,10 @@ sldns_parse_rdf_token(sldns_buffer* strbuf, char* token, size_t token_len,
|
||||
{
|
||||
size_t slen;
|
||||
|
||||
/* skip spaces */
|
||||
/* skip spaces and tabs */
|
||||
while(sldns_buffer_remaining(strbuf) > 0 && !*quoted &&
|
||||
*(sldns_buffer_current(strbuf)) == ' ') {
|
||||
(*(sldns_buffer_current(strbuf)) == ' ' ||
|
||||
*(sldns_buffer_current(strbuf)) == '\t')) {
|
||||
sldns_buffer_skip(strbuf, 1);
|
||||
}
|
||||
|
||||
@@ -601,7 +610,10 @@ sldns_affix_token(sldns_buffer* strbuf, char* token, size_t* token_len,
|
||||
size_t addstrlen = 0;
|
||||
|
||||
/* add space */
|
||||
if(addlen < 1) return 0;
|
||||
/* when addlen < 2, the token buffer is full considering the NULL byte
|
||||
* from strlen and will lead to buffer overflow with the second
|
||||
* assignment below. */
|
||||
if(addlen < 2) return 0;
|
||||
token[*token_strlen] = ' ';
|
||||
token[++(*token_strlen)] = 0;
|
||||
|
||||
@@ -664,10 +676,10 @@ static int sldns_str2wire_check_svcbparams(uint8_t* rdata, uint16_t rdata_len)
|
||||
,sldns_str2wire_svcparam_key_cmp);
|
||||
|
||||
|
||||
/* The code below revolves around sematic errors in the SVCParam set.
|
||||
/* The code below revolves around semantic errors in the SVCParam set.
|
||||
* So long as we do not distinguish between running Unbound as a primary
|
||||
* or as a secondary, we default to secondary behavior and we ignore the
|
||||
* sematic errors. */
|
||||
* semantic errors. */
|
||||
|
||||
#ifdef SVCB_SEMANTIC_ERRORS
|
||||
{
|
||||
@@ -769,7 +781,8 @@ rrinternal_parse_rdata(sldns_buffer* strbuf, char* token, size_t token_len,
|
||||
|
||||
/* unknown RR data */
|
||||
if(token_strlen>=2 && strncmp(token, "\\#", 2) == 0 &&
|
||||
!quoted && (token_strlen == 2 || token[2]==' ')) {
|
||||
!quoted && (token_strlen == 2 || token[2]==' ' ||
|
||||
token[2]=='\t')) {
|
||||
was_unknown_rr_format = 1;
|
||||
if((status=rrinternal_parse_unknown(strbuf, token,
|
||||
token_len, rr, rr_len, &rr_cur_len,
|
||||
@@ -1049,12 +1062,15 @@ int sldns_fp2wire_rr_buf(FILE* in, uint8_t* rr, size_t* len, size_t* dname_len,
|
||||
return s;
|
||||
} else if(strncmp(line, "$TTL", 4) == 0 && isspace((unsigned char)line[4])) {
|
||||
const char* end = NULL;
|
||||
int overflow = 0;
|
||||
strlcpy((char*)rr, line, *len);
|
||||
*len = 0;
|
||||
*dname_len = 0;
|
||||
if(!parse_state) return LDNS_WIREPARSE_ERR_OK;
|
||||
parse_state->default_ttl = sldns_str2period(
|
||||
sldns_strip_ws(line+5), &end);
|
||||
sldns_strip_ws(line+5), &end, &overflow);
|
||||
if(overflow)
|
||||
return LDNS_WIREPARSE_ERR_SYNTAX_INTEGER_OVERFLOW;
|
||||
} else if (strncmp(line, "$INCLUDE", 8) == 0) {
|
||||
strlcpy((char*)rr, line, *len);
|
||||
*len = 0;
|
||||
@@ -1111,7 +1127,7 @@ sldns_str2wire_svcparam_key_lookup(const char *key, size_t key_len)
|
||||
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" */
|
||||
return SVCB_KEY_ECH; /* allow "echconfig" as well as "ech" */
|
||||
break;
|
||||
|
||||
case sizeof("alpn")-1:
|
||||
@@ -1350,7 +1366,7 @@ sldns_str2wire_svcbparam_mandatory(const char* val, uint8_t* rd, size_t* rd_len)
|
||||
*/
|
||||
qsort((void *)(rd + 4), count, sizeof(uint16_t), sldns_network_uint16_cmp);
|
||||
|
||||
/* The code below revolves around sematic errors in the SVCParam set.
|
||||
/* The code below revolves around semantic errors in the SVCParam set.
|
||||
* So long as we do not distinguish between running Unbound as a primary
|
||||
* or as a secondary, we default to secondary behavior and we ignore the
|
||||
* semantic errors. */
|
||||
@@ -1582,12 +1598,12 @@ static int sldns_str2wire_svcparam_buf(const char* str, uint8_t* rd, size_t* rd_
|
||||
if (*val_in == '"') {
|
||||
val_in++;
|
||||
while (*val_in != '"'
|
||||
&& (unsigned)(val_out - unescaped_val + 1) < sizeof(unescaped_val)
|
||||
&& (size_t)(val_out - unescaped_val + 1) < sizeof(unescaped_val)
|
||||
&& sldns_parse_char( (uint8_t*) val_out, &val_in)) {
|
||||
val_out++;
|
||||
}
|
||||
} else {
|
||||
while ((unsigned)(val_out - unescaped_val + 1) < sizeof(unescaped_val)
|
||||
while ((size_t)(val_out - unescaped_val + 1) < sizeof(unescaped_val)
|
||||
&& sldns_parse_char( (uint8_t*) val_out, &val_in)) {
|
||||
val_out++;
|
||||
}
|
||||
@@ -2151,9 +2167,13 @@ int sldns_str2wire_tsigtime_buf(const char* str, uint8_t* rd, size_t* len)
|
||||
int sldns_str2wire_period_buf(const char* str, uint8_t* rd, size_t* len)
|
||||
{
|
||||
const char* end;
|
||||
uint32_t p = sldns_str2period(str, &end);
|
||||
int overflow;
|
||||
uint32_t p = sldns_str2period(str, &end, &overflow);
|
||||
if(*end != 0)
|
||||
return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_PERIOD, end-str);
|
||||
if(overflow)
|
||||
return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_INTEGER_OVERFLOW,
|
||||
end-str);
|
||||
if(*len < 4)
|
||||
return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL;
|
||||
sldns_write_uint32(rd, p);
|
||||
|
||||
+1
-1
@@ -187,7 +187,7 @@ uint8_t* sldns_wirerr_get_rdatawl(uint8_t* rr, size_t len, size_t dname_len);
|
||||
#define LDNS_WIREPARSE_MASK 0x0fff
|
||||
#define LDNS_WIREPARSE_SHIFT 12
|
||||
#define LDNS_WIREPARSE_ERROR(e) ((e)&LDNS_WIREPARSE_MASK)
|
||||
#define LDNS_WIREPARSE_OFFSET(e) (((e)&~LDNS_WIREPARSE_MASK)>>LDNS_WIREPARSE_SHIFT)
|
||||
#define LDNS_WIREPARSE_OFFSET(e) ((((unsigned)(e))&~LDNS_WIREPARSE_MASK)>>LDNS_WIREPARSE_SHIFT)
|
||||
/* use lookuptable to get error string, sldns_wireparse_errors */
|
||||
#define LDNS_WIREPARSE_ERR_OK 0
|
||||
#define LDNS_WIREPARSE_ERR_GENERAL 342
|
||||
|
||||
+13
-1
@@ -194,6 +194,7 @@ static sldns_lookup_table sldns_edns_options_data[] = {
|
||||
{ 8, "edns-client-subnet" },
|
||||
{ 11, "edns-tcp-keepalive"},
|
||||
{ 12, "Padding" },
|
||||
{ 15, "EDE"},
|
||||
{ 0, NULL}
|
||||
};
|
||||
sldns_lookup_table* sldns_edns_options = sldns_edns_options_data;
|
||||
@@ -817,6 +818,7 @@ int sldns_wire2str_dname_scan(uint8_t** d, size_t* dlen, char** s, size_t* slen,
|
||||
unsigned i, counter=0;
|
||||
unsigned maxcompr = MAX_COMPRESS_PTRS; /* loop detection, max compr ptrs */
|
||||
int in_buf = 1;
|
||||
size_t dname_len = 0;
|
||||
if(comprloop) {
|
||||
if(*comprloop != 0)
|
||||
maxcompr = 30; /* for like ipv6 reverse name, per label */
|
||||
@@ -872,6 +874,16 @@ int sldns_wire2str_dname_scan(uint8_t** d, size_t* dlen, char** s, size_t* slen,
|
||||
labellen = (uint8_t)*dlen;
|
||||
else if(!in_buf && pos+(size_t)labellen > pkt+pktlen)
|
||||
labellen = (uint8_t)(pkt + pktlen - pos);
|
||||
dname_len += ((size_t)labellen)+1;
|
||||
if(dname_len > LDNS_MAX_DOMAINLEN) {
|
||||
/* dname_len counts the uncompressed length we have
|
||||
* seen so far, and the domain name has become too
|
||||
* long, prevent the loop from printing overly long
|
||||
* content. */
|
||||
w += sldns_str_print(s, slen,
|
||||
"ErrorDomainNameTooLong");
|
||||
return w;
|
||||
}
|
||||
for(i=0; i<(unsigned)labellen; i++) {
|
||||
w += dname_char_print(s, slen, *pos++);
|
||||
}
|
||||
@@ -1059,7 +1071,7 @@ static int sldns_wire2str_svcparam_mandatory2str(char** s,
|
||||
assert(data_len > 0);
|
||||
|
||||
if (data_len % sizeof(uint16_t))
|
||||
return -1; // wireformat error, data_len must be multiple of shorts
|
||||
return -1; /* wireformat error, data_len must be multiple of shorts */
|
||||
w += sldns_str_print(s, slen, "=");
|
||||
w += sldns_print_svcparamkey(s, slen, sldns_read_uint16(data));
|
||||
data += 2;
|
||||
|
||||
@@ -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]);
|
||||
@@ -408,6 +422,28 @@ interfacechecks(struct config_file* cfg)
|
||||
}
|
||||
}
|
||||
|
||||
/** check interface-automatic-ports */
|
||||
static void
|
||||
ifautomaticportschecks(char* ifautomaticports)
|
||||
{
|
||||
char* now = ifautomaticports;
|
||||
while(now && *now) {
|
||||
char* after;
|
||||
int extraport;
|
||||
while(isspace((unsigned char)*now))
|
||||
now++;
|
||||
if(!*now)
|
||||
break;
|
||||
after = now;
|
||||
extraport = (int)strtol(now, &after, 10);
|
||||
if(extraport < 0 || extraport > 65535)
|
||||
fatal_exit("interface-automatic-ports: port out of range at position %d in '%s'", (int)(now-ifautomaticports)+1, ifautomaticports);
|
||||
if(extraport == 0 && now == after)
|
||||
fatal_exit("interface-automatic-ports: parse error at position %d in '%s'", (int)(now-ifautomaticports)+1, ifautomaticports);
|
||||
now = after;
|
||||
}
|
||||
}
|
||||
|
||||
/** check acl ips */
|
||||
static void
|
||||
aclchecks(struct config_file* cfg)
|
||||
@@ -608,6 +644,7 @@ morechecks(struct config_file* cfg)
|
||||
warn_hosts("stub-host", cfg->stubs);
|
||||
warn_hosts("forward-host", cfg->forwards);
|
||||
interfacechecks(cfg);
|
||||
ifautomaticportschecks(cfg->if_automatic_ports);
|
||||
aclchecks(cfg);
|
||||
tcpconnlimitchecks(cfg);
|
||||
|
||||
@@ -691,6 +728,8 @@ morechecks(struct config_file* cfg)
|
||||
&& strcmp(cfg->module_conf, "dns64 iterator") != 0
|
||||
&& strcmp(cfg->module_conf, "respip iterator") != 0
|
||||
&& strcmp(cfg->module_conf, "respip validator iterator") != 0
|
||||
&& strcmp(cfg->module_conf, "respip dns64 validator iterator") != 0
|
||||
&& strcmp(cfg->module_conf, "respip dns64 iterator") != 0
|
||||
#ifdef WITH_PYTHONMODULE
|
||||
&& strcmp(cfg->module_conf, "python iterator") != 0
|
||||
&& strcmp(cfg->module_conf, "python respip iterator") != 0
|
||||
@@ -785,6 +824,10 @@ morechecks(struct config_file* cfg)
|
||||
&& strcmp(cfg->module_conf, "validator python cachedb iterator") != 0
|
||||
&& strcmp(cfg->module_conf, "respip validator python cachedb iterator") != 0
|
||||
#endif
|
||||
#if defined(CLIENT_SUBNET) && defined(USE_CACHEDB)
|
||||
&& strcmp(cfg->module_conf, "respip subnetcache validator cachedb iterator") != 0
|
||||
&& strcmp(cfg->module_conf, "subnetcache validator cachedb iterator") != 0
|
||||
#endif
|
||||
#ifdef CLIENT_SUBNET
|
||||
&& strcmp(cfg->module_conf, "subnetcache iterator") != 0
|
||||
&& strcmp(cfg->module_conf, "respip subnetcache iterator") != 0
|
||||
|
||||
+20
-14
@@ -155,9 +155,9 @@ usage(void)
|
||||
printf(" ratelimit_list [+a] list ratelimited domains\n");
|
||||
printf(" ip_ratelimit_list [+a] list ratelimited ip addresses\n");
|
||||
printf(" +a list all, also not ratelimited\n");
|
||||
printf(" list_auth_zones list auth zones\n");
|
||||
printf(" auth_zone_reload zone reload auth zone from zonefile\n");
|
||||
printf(" auth_zone_transfer zone transfer auth zone from master\n");
|
||||
printf(" list_auth_zones list auth zones (includes RPZ zones)\n");
|
||||
printf(" auth_zone_reload zone reload auth zone (or RPZ zone) from zonefile\n");
|
||||
printf(" auth_zone_transfer zone transfer auth zone (or RPZ zone) from master\n");
|
||||
printf(" view_list_local_zones view list local-zones in view\n");
|
||||
printf(" view_list_local_data view list local-data RRs in view\n");
|
||||
printf(" view_local_zone view name type add local-zone in view\n");
|
||||
@@ -354,6 +354,7 @@ static void print_extended(struct ub_stats_info* s)
|
||||
/* transport */
|
||||
PR_UL("num.query.tcp", s->svr.qtcp);
|
||||
PR_UL("num.query.tcpout", s->svr.qtcp_outgoing);
|
||||
PR_UL("num.query.udpout", s->svr.qudp_outgoing);
|
||||
PR_UL("num.query.tls", s->svr.qtls);
|
||||
PR_UL("num.query.tls_resume", s->svr.qtls_resume);
|
||||
PR_UL("num.query.ipv6", s->svr.qipv6);
|
||||
@@ -444,7 +445,7 @@ static void do_stats_shm(struct config_file* cfg, struct ub_stats_info* stats,
|
||||
#endif /* HAVE_SHMGET */
|
||||
|
||||
/** print statistics from shm memory segment */
|
||||
static void print_stats_shm(const char* cfgfile)
|
||||
static void print_stats_shm(const char* cfgfile, int quiet)
|
||||
{
|
||||
#ifdef HAVE_SHMGET
|
||||
struct config_file* cfg;
|
||||
@@ -474,8 +475,11 @@ static void print_stats_shm(const char* cfgfile)
|
||||
fatal_exit("shmat(%d): %s", id_arr, strerror(errno));
|
||||
}
|
||||
|
||||
/* print the stats */
|
||||
do_stats_shm(cfg, stats, shm_stat);
|
||||
|
||||
if(!quiet) {
|
||||
/* print the stats */
|
||||
do_stats_shm(cfg, stats, shm_stat);
|
||||
}
|
||||
|
||||
/* shutdown */
|
||||
shmdt(shm_stat);
|
||||
@@ -483,6 +487,7 @@ static void print_stats_shm(const char* cfgfile)
|
||||
config_delete(cfg);
|
||||
#else
|
||||
(void)cfgfile;
|
||||
(void)quiet;
|
||||
#endif /* HAVE_SHMGET */
|
||||
}
|
||||
|
||||
@@ -499,7 +504,7 @@ static void ssl_path_err(const char* s, const char *path)
|
||||
{
|
||||
unsigned long err;
|
||||
err = ERR_peek_error();
|
||||
if (ERR_GET_LIB(err) == ERR_LIB_SYS) {
|
||||
if(ERR_GET_LIB(err) == ERR_LIB_SYS) {
|
||||
fprintf(stderr, "error: %s\n%s: %s\n",
|
||||
s, path, ERR_reason_error_string(err));
|
||||
exit(1);
|
||||
@@ -541,11 +546,11 @@ setup_ctx(struct config_file* cfg)
|
||||
#endif
|
||||
if(!SSL_CTX_use_certificate_chain_file(ctx,c_cert))
|
||||
ssl_path_err("Error setting up SSL_CTX client cert", c_cert);
|
||||
if (!SSL_CTX_use_PrivateKey_file(ctx,c_key,SSL_FILETYPE_PEM))
|
||||
if(!SSL_CTX_use_PrivateKey_file(ctx,c_key,SSL_FILETYPE_PEM))
|
||||
ssl_path_err("Error setting up SSL_CTX client key", c_key);
|
||||
if (!SSL_CTX_check_private_key(ctx))
|
||||
if(!SSL_CTX_check_private_key(ctx))
|
||||
ssl_err("Error setting up SSL_CTX client key");
|
||||
if (SSL_CTX_load_verify_locations(ctx, s_cert, NULL) != 1)
|
||||
if(SSL_CTX_load_verify_locations(ctx, s_cert, NULL) != 1)
|
||||
ssl_path_err("Error setting up SSL_CTX verify, server cert",
|
||||
s_cert);
|
||||
SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL);
|
||||
@@ -596,7 +601,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,
|
||||
@@ -624,7 +629,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] == '/') {
|
||||
@@ -880,8 +885,9 @@ go_cmd(SSL* ssl, int fd, int quiet, int argc, char* argv[])
|
||||
if(first_line && strncmp(buf, "error", 5) == 0) {
|
||||
printf("%s", buf);
|
||||
was_error = 1;
|
||||
} else if (!quiet)
|
||||
} else if(!quiet) {
|
||||
printf("%s", buf);
|
||||
}
|
||||
|
||||
first_line = 0;
|
||||
}
|
||||
@@ -987,7 +993,7 @@ int main(int argc, char* argv[])
|
||||
#endif
|
||||
}
|
||||
if(argc >= 1 && strcmp(argv[0], "stats_shm")==0) {
|
||||
print_stats_shm(cfgfile);
|
||||
print_stats_shm(cfgfile, quiet);
|
||||
return 0;
|
||||
}
|
||||
check_args_for_listcmd(argc, argv);
|
||||
|
||||
@@ -97,10 +97,12 @@ void worker_sighandler(int ATTR_UNUSED(sig), void* ATTR_UNUSED(arg))
|
||||
struct outbound_entry* worker_send_query(
|
||||
struct query_info* ATTR_UNUSED(qinfo), uint16_t ATTR_UNUSED(flags),
|
||||
int ATTR_UNUSED(dnssec), int ATTR_UNUSED(want_dnssec),
|
||||
int ATTR_UNUSED(nocaps), struct sockaddr_storage* ATTR_UNUSED(addr),
|
||||
int ATTR_UNUSED(nocaps), int ATTR_UNUSED(check_ratelimit),
|
||||
struct sockaddr_storage* ATTR_UNUSED(addr),
|
||||
socklen_t ATTR_UNUSED(addrlen), uint8_t* ATTR_UNUSED(zone),
|
||||
size_t ATTR_UNUSED(zonelen), int ATTR_UNUSED(tcp_upstream), int ATTR_UNUSED(ssl_upstream),
|
||||
char* ATTR_UNUSED(tls_auth_name), struct module_qstate* ATTR_UNUSED(q))
|
||||
char* ATTR_UNUSED(tls_auth_name), struct module_qstate* ATTR_UNUSED(q),
|
||||
int* ATTR_UNUSED(was_ratelimited))
|
||||
{
|
||||
log_assert(0);
|
||||
return 0;
|
||||
@@ -129,10 +131,12 @@ worker_alloc_cleanup(void* ATTR_UNUSED(arg))
|
||||
struct outbound_entry* libworker_send_query(
|
||||
struct query_info* ATTR_UNUSED(qinfo), uint16_t ATTR_UNUSED(flags),
|
||||
int ATTR_UNUSED(dnssec), int ATTR_UNUSED(want_dnssec),
|
||||
int ATTR_UNUSED(nocaps), struct sockaddr_storage* ATTR_UNUSED(addr),
|
||||
int ATTR_UNUSED(nocaps), int ATTR_UNUSED(check_ratelimit),
|
||||
struct sockaddr_storage* ATTR_UNUSED(addr),
|
||||
socklen_t ATTR_UNUSED(addrlen), uint8_t* ATTR_UNUSED(zone),
|
||||
size_t ATTR_UNUSED(zonelen), int ATTR_UNUSED(tcp_upstream), int ATTR_UNUSED(ssl_upstream),
|
||||
char* ATTR_UNUSED(tls_auth_name), struct module_qstate* ATTR_UNUSED(q))
|
||||
char* ATTR_UNUSED(tls_auth_name), struct module_qstate* ATTR_UNUSED(q),
|
||||
int* ATTR_UNUSED(was_ratelimited))
|
||||
{
|
||||
log_assert(0);
|
||||
return 0;
|
||||
|
||||
+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
|
||||
|
||||
@@ -551,7 +551,7 @@ run(struct http2_session* h2_session, int port, int no_tls, int count, char** q)
|
||||
if(ctx) {
|
||||
SSL_CTX_free(ctx);
|
||||
}
|
||||
close(fd);
|
||||
sock_close(fd);
|
||||
}
|
||||
|
||||
/** getopt global, in case header files fail to declare it. */
|
||||
@@ -573,6 +573,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");
|
||||
|
||||
+46
-19
@@ -384,8 +384,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)) {
|
||||
@@ -415,7 +415,7 @@ 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",
|
||||
@@ -453,10 +453,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;
|
||||
@@ -510,8 +512,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)) {
|
||||
@@ -1187,12 +1189,13 @@ pending_tcp_query(struct serviced_query* sq, sldns_buffer* packet,
|
||||
struct serviced_query* outnet_serviced_query(struct outside_network* outnet,
|
||||
struct query_info* qinfo, uint16_t flags, int dnssec,
|
||||
int ATTR_UNUSED(want_dnssec), int ATTR_UNUSED(nocaps),
|
||||
int ATTR_UNUSED(check_ratelimit),
|
||||
int ATTR_UNUSED(tcp_upstream), int ATTR_UNUSED(ssl_upstream),
|
||||
char* ATTR_UNUSED(tls_auth_name), struct sockaddr_storage* addr,
|
||||
socklen_t addrlen, uint8_t* zone, size_t zonelen,
|
||||
struct module_qstate* qstate, comm_point_callback_type* callback,
|
||||
void* callback_arg, sldns_buffer* ATTR_UNUSED(buff),
|
||||
struct module_env* env)
|
||||
struct module_env* env, int* ATTR_UNUSED(was_ratelimited))
|
||||
{
|
||||
struct replay_runtime* runtime = (struct replay_runtime*)outnet->base;
|
||||
struct fake_pending* pend = (struct fake_pending*)calloc(1,
|
||||
@@ -1222,11 +1225,37 @@ struct serviced_query* outnet_serviced_query(struct outside_network* outnet,
|
||||
if(1) {
|
||||
struct edns_data edns;
|
||||
struct edns_string_addr* client_string_addr;
|
||||
struct edns_option* backed_up_opt_list =
|
||||
qstate->edns_opts_back_out;
|
||||
struct edns_option* per_upstream_opt_list = NULL;
|
||||
/* If we have an already populated EDNS option list make a copy
|
||||
* since we may now add upstream specific EDNS options. */
|
||||
if(qstate->edns_opts_back_out) {
|
||||
per_upstream_opt_list = edns_opt_copy_region(
|
||||
qstate->edns_opts_back_out, qstate->region);
|
||||
if(!per_upstream_opt_list) {
|
||||
free(pend);
|
||||
fatal_exit("out of memory");
|
||||
}
|
||||
qstate->edns_opts_back_out = per_upstream_opt_list;
|
||||
}
|
||||
if(!inplace_cb_query_call(env, qinfo, flags, addr, addrlen,
|
||||
zone, zonelen, qstate, qstate->region)) {
|
||||
free(pend);
|
||||
return NULL;
|
||||
}
|
||||
/* Restore the option list; we can explicitly use the copied
|
||||
* one from now on. */
|
||||
per_upstream_opt_list = qstate->edns_opts_back_out;
|
||||
qstate->edns_opts_back_out = backed_up_opt_list;
|
||||
if((client_string_addr = edns_string_addr_lookup(
|
||||
&env->edns_strings->client_strings,
|
||||
addr, addrlen))) {
|
||||
edns_opt_list_append(&per_upstream_opt_list,
|
||||
env->edns_strings->client_string_opcode,
|
||||
client_string_addr->string_len,
|
||||
client_string_addr->string, qstate->region);
|
||||
}
|
||||
/* add edns */
|
||||
edns.edns_present = 1;
|
||||
edns.ext_rcode = 0;
|
||||
@@ -1236,16 +1265,8 @@ struct serviced_query* outnet_serviced_query(struct outside_network* outnet,
|
||||
if(dnssec)
|
||||
edns.bits = EDNS_DO;
|
||||
edns.padding_block_size = 0;
|
||||
if((client_string_addr = edns_string_addr_lookup(
|
||||
&env->edns_strings->client_strings,
|
||||
addr, addrlen))) {
|
||||
edns_opt_list_append(&qstate->edns_opts_back_out,
|
||||
env->edns_strings->client_string_opcode,
|
||||
client_string_addr->string_len,
|
||||
client_string_addr->string, qstate->region);
|
||||
}
|
||||
edns.opt_list_in = NULL;
|
||||
edns.opt_list_out = qstate->edns_opts_back_out;
|
||||
edns.opt_list_out = per_upstream_opt_list;
|
||||
edns.opt_list_inplace_cb_out = NULL;
|
||||
attach_edns_record(pend->buffer, &edns);
|
||||
}
|
||||
@@ -1325,7 +1346,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)
|
||||
@@ -1424,6 +1445,11 @@ void pending_udp_timer_cb(void *ATTR_UNUSED(arg))
|
||||
log_assert(0);
|
||||
}
|
||||
|
||||
void serviced_timer_cb(void *ATTR_UNUSED(arg))
|
||||
{
|
||||
log_assert(0);
|
||||
}
|
||||
|
||||
void pending_udp_timer_delay_cb(void *ATTR_UNUSED(arg))
|
||||
{
|
||||
log_assert(0);
|
||||
@@ -1639,6 +1665,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))
|
||||
|
||||
+43
-16
@@ -5,6 +5,11 @@ if test "$1" = "-a"; then
|
||||
shift
|
||||
shift
|
||||
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
|
||||
quiet=1
|
||||
@@ -13,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
|
||||
@@ -50,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
|
||||
@@ -77,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
|
||||
@@ -112,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"
|
||||
@@ -120,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
|
||||
|
||||
@@ -147,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
|
||||
@@ -163,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
|
||||
@@ -184,11 +204,18 @@ 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 "minitdir waiting for processes to terminate"
|
||||
sleep 2 # some time to exit, and try again
|
||||
if test $DEBUG -eq 0; then
|
||||
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 "minitdir waiting for processes to terminate"
|
||||
sleep 2 # some time to exit, and try again
|
||||
rm -rf $dir
|
||||
fi
|
||||
else
|
||||
if test $success = "no"; then
|
||||
exit 1
|
||||
fi
|
||||
exit 0
|
||||
fi
|
||||
|
||||
@@ -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
|
||||
+1
-1
@@ -618,7 +618,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);
|
||||
}
|
||||
|
||||
+1
-2
@@ -582,10 +582,9 @@ do_service(char* addr, int port, char* key, char* cert)
|
||||
{
|
||||
SSL_CTX* sslctx = setup_ctx(key, cert);
|
||||
int fd = setup_fd(addr, port);
|
||||
int go = 1;
|
||||
if(fd == -1) print_exit("could not setup sockets");
|
||||
if(verb) {printf("petal start\n"); fflush(stdout);}
|
||||
while(go) {
|
||||
while(1) {
|
||||
struct sockaddr_storage from;
|
||||
socklen_t flen = (socklen_t)sizeof(from);
|
||||
int s;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user