mirror of
https://github.com/NLnetLabs/unbound.git
synced 2026-08-17 21:25:50 +02:00
Compare commits
228
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
30c13d0351 | ||
|
|
d6e8ac1289 | ||
|
|
16ee7cf944 | ||
|
|
38026a21ee | ||
|
|
4f06e658d1 | ||
|
|
fca3ae0535 | ||
|
|
66b3abc803 | ||
|
|
922c5c3ab3 | ||
|
|
f9d740dfdc | ||
|
|
5eb1382fc0 | ||
|
|
e94e140f49 | ||
|
|
db6505eb8b | ||
|
|
a616437338 | ||
|
|
eb390dd038 | ||
|
|
4074a5b2ba | ||
|
|
a7e618b9c2 | ||
|
|
349721a39d | ||
|
|
ed71f72baa | ||
|
|
0e5d26807d | ||
|
|
90243a694a | ||
|
|
7fb6f9d613 | ||
|
|
7fb05c01c2 | ||
|
|
cb5a019d9f | ||
|
|
53ecdb25ef | ||
|
|
9939d5cdb0 | ||
|
|
5f91d5f74c | ||
|
|
c2ca679f5c | ||
|
|
ba18abcd35 | ||
|
|
a7704ad49f | ||
|
|
8b38fe5ab6 | ||
|
|
fcdb0bbf91 | ||
|
|
b738b354bd | ||
|
|
1c58ce0791 | ||
|
|
a7106fc58d | ||
|
|
17f95ffac1 | ||
|
|
0ca76b05e0 | ||
|
|
218f5cfc92 | ||
|
|
914cef75f9 | ||
|
|
f76365754e | ||
|
|
aa77d02336 | ||
|
|
23273d76a5 | ||
|
|
94a84d3387 | ||
|
|
d91c857e22 | ||
|
|
d03e4b1884 | ||
|
|
376f2ade2a | ||
|
|
0eabc8d0f1 | ||
|
|
a42fb99508 | ||
|
|
eccf52e39d | ||
|
|
30b9cb5f81 | ||
|
|
b0d20e2d28 | ||
|
|
13afde2cad | ||
|
|
71bb60e586 | ||
|
|
5c84bb573f | ||
|
|
d9f1dae540 | ||
|
|
a3d750b7d8 | ||
|
|
c371be3f9f | ||
|
|
c5c5486261 | ||
|
|
1894c0a150 | ||
|
|
edb20a2ad2 | ||
|
|
bcf162abd7 | ||
|
|
5e1f35b59b | ||
|
|
72828ff81c | ||
|
|
01cea4d5be | ||
|
|
35dbbcb2f5 | ||
|
|
911509fd59 | ||
|
|
b48958c983 | ||
|
|
cc55beefc8 | ||
|
|
a2bf32bb4e | ||
|
|
d9b863ed76 | ||
|
|
073c7301eb | ||
|
|
f822042cd0 | ||
|
|
5f58ced71e | ||
|
|
207ae97ff9 | ||
|
|
9a0de14aa1 | ||
|
|
048c193243 | ||
|
|
d62fff2c7c | ||
|
|
3f839cebc3 | ||
|
|
e4483bbbd1 | ||
|
|
8672b34fca | ||
|
|
1d428f2d54 | ||
|
|
9882a395ab | ||
|
|
394588818f | ||
|
|
f52b2a6ea2 | ||
|
|
b2fec3be11 | ||
|
|
f4881bd81a | ||
|
|
c3b5bff311 | ||
|
|
62a0e03801 | ||
|
|
716f3df385 | ||
|
|
7e4f7ec5be | ||
|
|
7559d26c93 | ||
|
|
eb36c880de | ||
|
|
fff9f62a1e | ||
|
|
e57e537c85 | ||
|
|
71d821fde9 | ||
|
|
df5ab5624d | ||
|
|
eb08dc617a | ||
|
|
ded4c82ced | ||
|
|
e82a691efe | ||
|
|
61d7250b96 | ||
|
|
b4a9c8bb05 | ||
|
|
be92752368 | ||
|
|
1512945c79 | ||
|
|
9de159b96b | ||
|
|
bd2e66de1e | ||
|
|
9770e855d2 | ||
|
|
c124f67f33 | ||
|
|
c55490c1e6 | ||
|
|
f46acec35f | ||
|
|
1cd2fb3b9d | ||
|
|
06fb30d0a0 | ||
|
|
9e3c50ec9e | ||
|
|
eefdbb341f | ||
|
|
e75da7d954 | ||
|
|
9a3a1bc221 | ||
|
|
c1e9d7be7f | ||
|
|
2c72a4970b | ||
|
|
4cf7fae50c | ||
|
|
a2ac980737 | ||
|
|
733d5f7161 | ||
|
|
fe288a9b06 | ||
|
|
fd1a1d5fa0 | ||
|
|
3c4b87636a | ||
|
|
36d8c6e778 | ||
|
|
60fd77b8f9 | ||
|
|
d5e91d181b | ||
|
|
7985d17b57 | ||
|
|
46cfbf313d | ||
|
|
533c3b0514 | ||
|
|
5f3f214da5 | ||
|
|
11b8157a98 | ||
|
|
1c24cd79cc | ||
|
|
d34fb3ed77 | ||
|
|
c37833c943 | ||
|
|
8a6a4bd7f3 | ||
|
|
d23523e528 | ||
|
|
75967e7f5e | ||
|
|
f5580f0a63 | ||
|
|
0e2b2743d8 | ||
|
|
018be1d089 | ||
|
|
9a63db344e | ||
|
|
0076736fc4 | ||
|
|
f8e45ed696 | ||
|
|
2a28c7389c | ||
|
|
114edf2c38 | ||
|
|
e0c93e300b | ||
|
|
bd1813b126 | ||
|
|
1b7e14dc39 | ||
|
|
8b7782e8fc | ||
|
|
e0201435a4 | ||
|
|
66fb3ff670 | ||
|
|
36461ea73d | ||
|
|
5679c8b1df | ||
|
|
a4d8c0c43b | ||
|
|
3d89c26d32 | ||
|
|
dcf7afd722 | ||
|
|
e67171612b | ||
|
|
a1b25f0296 | ||
|
|
490585bf29 | ||
|
|
b7c61d7cc2 | ||
|
|
01883fb017 | ||
|
|
5bb3b9cc83 | ||
|
|
3a1b79f6a1 | ||
|
|
84eeb9b97c | ||
|
|
d88eeb4c32 | ||
|
|
2e398d51ba | ||
|
|
24ebca7df6 | ||
|
|
7f4a61e6fc | ||
|
|
db719d404f | ||
|
|
a35a0c49da | ||
|
|
5e9b6296b7 | ||
|
|
606e262fdd | ||
|
|
819764663b | ||
|
|
6bf2b2ac56 | ||
|
|
5767b0933f | ||
|
|
24e0f0ab7e | ||
|
|
d3fdbba877 | ||
|
|
c36ce2a390 | ||
|
|
7ecff4113c | ||
|
|
99824bc0e6 | ||
|
|
9f09c36401 | ||
|
|
a887284703 | ||
|
|
fb198b96f1 | ||
|
|
30bf996f39 | ||
|
|
52154e658a | ||
|
|
c06d3646a9 | ||
|
|
42d421a305 | ||
|
|
b5951ce1fa | ||
|
|
6b37309705 | ||
|
|
dc274fef9b | ||
|
|
db1167c8b3 | ||
|
|
1e0cf1e86b | ||
|
|
348df52e05 | ||
|
|
6b3266aaf8 | ||
|
|
4f52461e81 | ||
|
|
06d5031d22 | ||
|
|
12119e2d3e | ||
|
|
19d53d5663 | ||
|
|
04e6f9e03b | ||
|
|
3d350fa73d | ||
|
|
015b2b0daf | ||
|
|
5fa84d50bf | ||
|
|
79e4c57851 | ||
|
|
5abdd09095 | ||
|
|
158c1defe3 | ||
|
|
b4519012dc | ||
|
|
ed883238fd | ||
|
|
0f2f6025e7 | ||
|
|
3cbf554e3b | ||
|
|
ad21dbd1c2 | ||
|
|
50cf55bdac | ||
|
|
6106528a50 | ||
|
|
befa7d8cd8 | ||
|
|
92be76fb89 | ||
|
|
9a6b6765cc | ||
|
|
03b511b1a2 | ||
|
|
6af28bed08 | ||
|
|
f094f4ea3c | ||
|
|
c717debace | ||
|
|
7d4d21764a | ||
|
|
83e6977f06 | ||
|
|
671e11552c | ||
|
|
c4541e634b | ||
|
|
30da725e67 | ||
|
|
8de5ae3552 | ||
|
|
5bea29b01c | ||
|
|
89c9eafa44 | ||
|
|
3512eaec48 | ||
|
|
f9bd35dcfa |
@@ -31,12 +31,12 @@ jobs:
|
||||
clang_analysis: "yes"
|
||||
- name: OS X
|
||||
os: macos-latest
|
||||
install_expat: "yes"
|
||||
install_expat: "no"
|
||||
config: "--enable-debug --disable-flto --with-ssl=/opt/homebrew/opt/openssl --with-libexpat=/opt/homebrew/opt/expat"
|
||||
make_test: "yes"
|
||||
- name: Clang on OS X
|
||||
os: macos-latest
|
||||
install_expat: "yes"
|
||||
install_expat: "no"
|
||||
config: "CC=clang --enable-debug --disable-flto --with-ssl=/opt/homebrew/opt/openssl --with-libexpat=/opt/homebrew/opt/expat --disable-static"
|
||||
make_test: "yes"
|
||||
clang_analysis: "yes"
|
||||
@@ -161,13 +161,44 @@ jobs:
|
||||
test_windows: "yes"
|
||||
config: "no"
|
||||
make: "no"
|
||||
- name: FreeBSD
|
||||
os: ubuntu-latest
|
||||
config: "no"
|
||||
make: "no"
|
||||
with_cross_platform_action: "yes"
|
||||
cross_platform_os: "freebsd"
|
||||
cross_platform_arch: "x86-64"
|
||||
cross_platform_version: "14.1"
|
||||
cross_platform_config: "--enable-debug --disable-flto --with-libevent --disable-static"
|
||||
- name: OpenBSD
|
||||
os: ubuntu-latest
|
||||
config: "no"
|
||||
make: "no"
|
||||
with_cross_platform_action: "yes"
|
||||
cross_platform_os: "openbsd"
|
||||
cross_platform_arch: "x86-64"
|
||||
cross_platform_version: "7.5"
|
||||
cross_platform_config: "--enable-debug --disable-flto --with-libevent --disable-static"
|
||||
- name: NetBSD
|
||||
os: ubuntu-latest
|
||||
config: "no"
|
||||
make: "no"
|
||||
with_cross_platform_action: "yes"
|
||||
cross_platform_os: "netbsd"
|
||||
cross_platform_arch: "x86-64"
|
||||
cross_platform_version: "10.0"
|
||||
cross_platform_config: "--enable-debug --disable-flto --with-libevent --disable-static"
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: false
|
||||
persist-credentials: false
|
||||
- name: test_windows
|
||||
if: ${{ matrix.test_windows == 'yes' }}
|
||||
env:
|
||||
LIBEXPAT_FNAME: expat-2.7.0
|
||||
LIBEXPAT_VERSION_DIR: R_2_7_0
|
||||
shell: bash
|
||||
run: |
|
||||
export unboundpath=`pwd`
|
||||
@@ -210,9 +241,9 @@ jobs:
|
||||
cd ..
|
||||
mkdir expat
|
||||
echo "curl expat"
|
||||
curl -L -k -s -S -o expat-2.2.10.tar.gz https://github.com/libexpat/libexpat/releases/download/R_2_2_10/expat-2.2.10.tar.gz
|
||||
tar xzf expat-2.2.10.tar.gz
|
||||
cd expat-2.2.10
|
||||
curl -L -k -s -S -o $LIBEXPAT_FNAME.tar.gz https://github.com/libexpat/libexpat/releases/download/$LIBEXPAT_VERSION_DIR/$LIBEXPAT_FNAME.tar.gz
|
||||
tar xzf $LIBEXPAT_FNAME.tar.gz
|
||||
cd $LIBEXPAT_FNAME
|
||||
echo "./configure SHELL=/usr/bin/bash CONFIG_SHELL=/usr/bin/bash --prefix=\"$prepath/expat\" --exec-prefix=\"$prepath/expat\" --bindir=\"$prepath/expat/bin\" --includedir=\"$prepath/expat/include\" --mandir=\"$prepath/expat/man\" --libdir=\"$prepath/expat/lib\""
|
||||
./configure SHELL=/usr/bin/bash CONFIG_SHELL=/usr/bin/bash --prefix="$prepath/expat" --exec-prefix="$prepath/expat" --bindir="$prepath/expat/bin" --includedir="$prepath/expat/include" --mandir="$prepath/expat/man" --libdir="$prepath/expat/lib"
|
||||
# fixup SHELL is treated specially, but SHELZZ is not by make.
|
||||
@@ -331,6 +362,33 @@ jobs:
|
||||
echo "::group::make install"
|
||||
make install
|
||||
echo "::endgroup::"
|
||||
- name: cross-platform-action on ${{ matrix.cross_platform_os }} ${{ matrix.cross_platform_version }}
|
||||
if: ${{ matrix.with_cross_platform_action == 'yes' }}
|
||||
uses: cross-platform-actions/action@v0.25.0
|
||||
env:
|
||||
CROSS_PLATFORM_OS: ${{ matrix.cross_platform_os }}
|
||||
with:
|
||||
environment_variables: CROSS_PLATFORM_OS
|
||||
operating_system: ${{ matrix.cross_platform_os }}
|
||||
architecture: ${{ matrix.cross_platform_arch }}
|
||||
version: ${{ matrix.cross_platform_version }}
|
||||
shell: bash
|
||||
memory: 4G
|
||||
cpu_count: 2
|
||||
run: |
|
||||
set -e -x
|
||||
if test "$CROSS_PLATFORM_OS" = "freebsd"; then sudo pkg install -y openssl libevent expat; fi
|
||||
if test "$CROSS_PLATFORM_OS" = "openbsd"; then sudo pkg_add libevent; fi
|
||||
if test "$CROSS_PLATFORM_OS" = "netbsd"; then sudo pkgin -y install libevent; fi
|
||||
echo "::group::configure"
|
||||
./configure ${{ matrix.cross_platform_config }}
|
||||
echo "::endgroup::"
|
||||
echo "::group::make"
|
||||
make
|
||||
echo "::endgroup::"
|
||||
echo "::group::make test"
|
||||
make test
|
||||
echo "::endgroup::"
|
||||
- name: install libevent
|
||||
if: ${{ matrix.install_libevent == 'yes' }}
|
||||
run: sudo apt-get install libevent-dev
|
||||
|
||||
@@ -13,6 +13,8 @@ jobs:
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: configure
|
||||
run: ./configure --enable-debug
|
||||
- name: make
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
/asynclook
|
||||
/delayer
|
||||
/dohclient
|
||||
/doqclient
|
||||
/lock-verify
|
||||
/memstats
|
||||
/perf
|
||||
|
||||
+28
-10
@@ -179,11 +179,11 @@ testcode/unitlruhash.c testcode/unitmain.c testcode/unitmsgparse.c \
|
||||
testcode/unitneg.c testcode/unitregional.c testcode/unitslabhash.c \
|
||||
testcode/unitverify.c testcode/readhex.c testcode/testpkts.c testcode/unitldns.c \
|
||||
testcode/unitecs.c testcode/unitauth.c testcode/unitzonemd.c \
|
||||
testcode/unittcpreuse.c
|
||||
testcode/unittcpreuse.c testcode/unitdoq.c testcode/unitinfra.c
|
||||
UNITTEST_OBJ=unitanchor.lo unitdname.lo unitlruhash.lo unitmain.lo \
|
||||
unitmsgparse.lo unitneg.lo unitregional.lo unitslabhash.lo unitverify.lo \
|
||||
readhex.lo testpkts.lo unitldns.lo unitecs.lo unitauth.lo unitzonemd.lo \
|
||||
unittcpreuse.lo
|
||||
unittcpreuse.lo unitdoq.lo unitinfra.lo
|
||||
UNITTEST_OBJ_LINK=$(UNITTEST_OBJ) worker_cb.lo $(COMMON_OBJ) $(SLDNS_OBJ) \
|
||||
$(COMPAT_OBJ)
|
||||
DAEMON_SRC=daemon/acl_list.c daemon/cachedump.c daemon/daemon.c \
|
||||
@@ -242,6 +242,10 @@ DOHCLIENT_SRC=testcode/dohclient.c
|
||||
DOHCLIENT_OBJ=dohclient.lo
|
||||
DOHCLIENT_OBJ_LINK=$(DOHCLIENT_OBJ) worker_cb.lo $(COMMON_OBJ) $(COMPAT_OBJ) \
|
||||
$(SLDNS_OBJ)
|
||||
DOQCLIENT_SRC=testcode/doqclient.c
|
||||
DOQCLIENT_OBJ=doqclient.lo
|
||||
DOQCLIENT_OBJ_LINK=$(DOQCLIENT_OBJ) $(COMMON_OBJ) $(COMPAT_OBJ) \
|
||||
$(SLDNS_OBJ)
|
||||
PERF_SRC=testcode/perf.c
|
||||
PERF_OBJ=perf.lo
|
||||
PERF_OBJ_LINK=$(PERF_OBJ) worker_cb.lo $(COMMON_OBJ) $(COMPAT_OBJ) $(SLDNS_OBJ)
|
||||
@@ -288,7 +292,7 @@ ALL_SRC=$(COMMON_SRC) $(UNITTEST_SRC) $(DAEMON_SRC) \
|
||||
$(CONTROL_SRC) $(UBANCHOR_SRC) $(PETAL_SRC) $(DNSTAP_SOCKET_SRC)\
|
||||
$(PYTHONMOD_SRC) $(PYUNBOUND_SRC) $(WIN_DAEMON_THE_SRC) \
|
||||
$(SVCINST_SRC) $(SVCUNINST_SRC) $(ANCHORUPD_SRC) $(SLDNS_SRC) \
|
||||
$(DOHCLIENT_SRC) $(READZONE_SRC)
|
||||
$(DOHCLIENT_SRC) $(DOQCLIENT_SRC) $(READZONE_SRC)
|
||||
|
||||
ALL_OBJ=$(COMMON_OBJ) $(UNITTEST_OBJ) $(DAEMON_OBJ) \
|
||||
$(TESTBOUND_OBJ) $(LOCKVERIFY_OBJ) $(PKTVIEW_OBJ) \
|
||||
@@ -297,7 +301,7 @@ ALL_OBJ=$(COMMON_OBJ) $(UNITTEST_OBJ) $(DAEMON_OBJ) \
|
||||
$(CONTROL_OBJ) $(UBANCHOR_OBJ) $(PETAL_OBJ) $(DNSTAP_SOCKET_OBJ)\
|
||||
$(COMPAT_OBJ) $(PYUNBOUND_OBJ) \
|
||||
$(SVCINST_OBJ) $(SVCUNINST_OBJ) $(ANCHORUPD_OBJ) $(SLDNS_OBJ) \
|
||||
$(DOHCLIENT_OBJ) $(READZONE_OBJ)
|
||||
$(DOHCLIENT_OBJ) $(DOQCLIENT_OBJ) $(READZONE_OBJ)
|
||||
|
||||
COMPILE=$(LIBTOOL) --tag=CC --mode=compile $(CC) $(CPPFLAGS) $(CFLAGS) @PTHREAD_CFLAGS_ONLY@
|
||||
LINK=$(LIBTOOL) --tag=CC --mode=link $(CC) $(staticexe) $(RUNTIME_PATH) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS)
|
||||
@@ -334,7 +338,7 @@ rsrc_unbound_checkconf.o: $(srcdir)/winrc/rsrc_unbound_checkconf.rc config.h
|
||||
TEST_BIN=asynclook$(EXEEXT) delayer$(EXEEXT) \
|
||||
lock-verify$(EXEEXT) memstats$(EXEEXT) perf$(EXEEXT) \
|
||||
petal$(EXEEXT) pktview$(EXEEXT) streamtcp$(EXEEXT) \
|
||||
$(DNSTAP_SOCKET_TESTBIN) dohclient$(EXEEXT) \
|
||||
$(DNSTAP_SOCKET_TESTBIN) dohclient$(EXEEXT) doqclient$(EXEEXT) \
|
||||
testbound$(EXEEXT) unittest$(EXEEXT) readzone$(EXEEXT)
|
||||
tests: all $(TEST_BIN)
|
||||
|
||||
@@ -416,6 +420,9 @@ streamtcp$(EXEEXT): $(STREAMTCP_OBJ_LINK)
|
||||
dohclient$(EXEEXT): $(DOHCLIENT_OBJ_LINK)
|
||||
$(LINK) -o $@ $(DOHCLIENT_OBJ_LINK) $(SSLLIB) $(LIBS)
|
||||
|
||||
doqclient$(EXEEXT): $(DOQCLIENT_OBJ_LINK)
|
||||
$(LINK) -o $@ $(DOQCLIENT_OBJ_LINK) $(SSLLIB) $(LIBS)
|
||||
|
||||
perf$(EXEEXT): $(PERF_OBJ_LINK)
|
||||
$(LINK) -o $@ $(PERF_OBJ_LINK) $(SSLLIB) $(LIBS)
|
||||
|
||||
@@ -502,10 +509,15 @@ util/configlexer.c: $(srcdir)/util/configlexer.lex util/configparser.h
|
||||
fi
|
||||
@if test ! -f $@; then echo "No $@ : need flex and bison to compile from source repository"; exit 1; fi
|
||||
|
||||
util/configparser.c util/configparser.h: $(srcdir)/util/configparser.y
|
||||
# Builds both util/configparser.c and util/configparser.h.
|
||||
# To avoid double-building we split one target out.
|
||||
util/configparser.c: $(srcdir)/util/configparser.y
|
||||
@-if test ! -d util; then $(INSTALL) -d util; fi
|
||||
$(YACC) -d -o util/configparser.c $(srcdir)/util/configparser.y
|
||||
|
||||
util/configparser.h: util/configparser.c
|
||||
touch $@
|
||||
|
||||
clean:
|
||||
rm -f *.o *.d *.lo *~ tags
|
||||
rm -f unbound$(EXEEXT) unbound-checkconf$(EXEEXT) unbound-host$(EXEEXT) unbound-control$(EXEEXT) unbound-anchor$(EXEEXT) unbound-control-setup libunbound.la unbound.h
|
||||
@@ -703,6 +715,8 @@ depend:
|
||||
|
||||
# build rules
|
||||
ipset.lo ipset.o: $(srcdir)/ipset/ipset.c
|
||||
doqclient.lo doqclient.o: $(srcdir)/testcode/doqclient.c
|
||||
unitdoq.lo unitdoq.o: $(srcdir)/testcode/unitdoq.c
|
||||
|
||||
# Dependencies
|
||||
dns.lo dns.o: $(srcdir)/services/cache/dns.c config.h $(srcdir)/iterator/iter_delegpt.h $(srcdir)/util/log.h \
|
||||
@@ -867,7 +881,7 @@ view.lo view.o: $(srcdir)/services/view.c config.h $(srcdir)/services/view.h $(s
|
||||
$(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/services/localzone.h $(srcdir)/util/storage/dnstree.h \
|
||||
$(srcdir)/util/module.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/data/msgreply.h \
|
||||
$(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h \
|
||||
$(srcdir)/sldns/rrdef.h $(srcdir)/sldns/sbuffer.h $(srcdir)/util/config_file.h
|
||||
$(srcdir)/sldns/rrdef.h $(srcdir)/sldns/sbuffer.h $(srcdir)/util/config_file.h $(srcdir)/respip/respip.h
|
||||
rpz.lo rpz.o: $(srcdir)/services/rpz.c config.h $(srcdir)/services/rpz.h $(srcdir)/services/localzone.h \
|
||||
$(srcdir)/util/rbtree.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/storage/dnstree.h \
|
||||
$(srcdir)/util/module.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/data/msgreply.h \
|
||||
@@ -963,7 +977,7 @@ fptr_wlist.lo fptr_wlist.o: $(srcdir)/util/fptr_wlist.c config.h $(srcdir)/util/
|
||||
$(srcdir)/validator/val_nsec3.h $(srcdir)/validator/val_sigcrypt.h $(srcdir)/validator/val_kentry.h \
|
||||
$(srcdir)/validator/val_neg.h $(srcdir)/validator/autotrust.h $(srcdir)/libunbound/libworker.h \
|
||||
$(srcdir)/libunbound/context.h $(srcdir)/util/alloc.h $(srcdir)/libunbound/unbound-event.h \
|
||||
$(srcdir)/libunbound/worker.h
|
||||
$(srcdir)/libunbound/worker.h $(srcdir)/daemon/remote.h
|
||||
locks.lo locks.o: $(srcdir)/util/locks.c config.h $(srcdir)/util/locks.h $(srcdir)/util/log.h
|
||||
log.lo log.o: $(srcdir)/util/log.c config.h $(srcdir)/util/log.h $(srcdir)/util/locks.h $(srcdir)/sldns/sbuffer.h
|
||||
mini_event.lo mini_event.o: $(srcdir)/util/mini_event.c config.h $(srcdir)/util/mini_event.h $(srcdir)/util/rbtree.h \
|
||||
@@ -1050,7 +1064,7 @@ tube.lo tube.o: $(srcdir)/util/tube.c config.h $(srcdir)/util/tube.h $(srcdir)/u
|
||||
$(srcdir)/libunbound/unbound.h $(srcdir)/respip/respip.h $(srcdir)/util/ub_event.h
|
||||
ub_event.lo ub_event.o: $(srcdir)/util/ub_event.c config.h $(srcdir)/util/ub_event.h $(srcdir)/util/log.h \
|
||||
$(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
|
||||
$(srcdir)/util/tube.h $(srcdir)/util/mini_event.h $(srcdir)/util/rbtree.h
|
||||
$(srcdir)/util/tube.h $(srcdir)/util/mini_event.h $(srcdir)/util/rbtree.h $(srcdir)/daemon/remote.h
|
||||
ub_event_pluggable.lo ub_event_pluggable.o: $(srcdir)/util/ub_event_pluggable.c config.h $(srcdir)/util/ub_event.h \
|
||||
$(srcdir)/libunbound/unbound-event.h $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
|
||||
$(srcdir)/util/log.h $(srcdir)/util/fptr_wlist.h \
|
||||
@@ -1247,6 +1261,7 @@ unitzonemd.lo unitzonemd.o: $(srcdir)/testcode/unitzonemd.c config.h $(srcdir)/u
|
||||
$(srcdir)/validator/val_anchor.h
|
||||
unittcpreuse.lo unittcpreuse.o: $(srcdir)/testcode/unittcpreuse.c config.h $(srcdir)/services/outside_network.h \
|
||||
$(srcdir)/util/random.h
|
||||
unitinfra.lo unitinfra.o: $(srcdir)/testcode/unitinfra.c config.h $(srcdir)/util/config_file.h $(srcdir)/util/net_help.h $(srcdir)/iterator/iterator.h
|
||||
acl_list.lo acl_list.o: $(srcdir)/daemon/acl_list.c config.h $(srcdir)/daemon/acl_list.h \
|
||||
$(srcdir)/util/storage/dnstree.h $(srcdir)/util/rbtree.h $(srcdir)/services/view.h $(srcdir)/util/locks.h \
|
||||
$(srcdir)/util/log.h $(srcdir)/util/regional.h $(srcdir)/util/config_file.h $(srcdir)/util/net_help.h \
|
||||
@@ -1298,7 +1313,10 @@ remote.lo remote.o: $(srcdir)/daemon/remote.c config.h $(srcdir)/daemon/remote.h
|
||||
$(srcdir)/validator/val_anchor.h $(srcdir)/iterator/iterator.h $(srcdir)/services/outbound_list.h \
|
||||
$(srcdir)/iterator/iter_fwd.h $(srcdir)/iterator/iter_hints.h $(srcdir)/iterator/iter_delegpt.h \
|
||||
$(srcdir)/services/outside_network.h $(srcdir)/sldns/str2wire.h $(srcdir)/sldns/parseutil.h \
|
||||
$(srcdir)/sldns/wire2str.h
|
||||
$(srcdir)/sldns/wire2str.h $(srcdir)/util/edns.h \
|
||||
$(srcdir)/util/locks.h $(srcdir)/util/ub_event.h \
|
||||
$(srcdir)/util/tcp_conn_limit.h $(srcdir)/util/edns.h $(srcdir)/validator/val_neg.h \
|
||||
$(srcdir)/iterator/iter_utils.h $(srcdir)/iterator/iter_donotq.h $(srcdir)/iterator/iter_priv.h
|
||||
stats.lo stats.o: $(srcdir)/daemon/stats.c config.h $(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h \
|
||||
$(srcdir)/libunbound/unbound.h $(srcdir)/daemon/worker.h $(srcdir)/libunbound/worker.h $(srcdir)/sldns/sbuffer.h \
|
||||
$(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
# ===========================================================================
|
||||
# https://www.gnu.org/software/autoconf-archive/ax_build_date_epoch.html
|
||||
# ===========================================================================
|
||||
#
|
||||
# SYNOPSIS
|
||||
#
|
||||
# AX_BUILD_DATE_EPOCH(VARIABLE[, FORMAT[, ACTION-IF-FAIL]])
|
||||
#
|
||||
# DESCRIPTION
|
||||
#
|
||||
# Sets VARIABLE to a string representing the current time. It is
|
||||
# formatted according to FORMAT if specified, otherwise it is formatted as
|
||||
# the number of seconds (excluding leap seconds) since the UNIX epoch (01
|
||||
# Jan 1970 00:00:00 UTC).
|
||||
#
|
||||
# If the SOURCE_DATE_EPOCH environment variable is set, it uses the value
|
||||
# of that variable instead of the current time. See
|
||||
# https://reproducible-builds.org/specs/source-date-epoch). If
|
||||
# SOURCE_DATE_EPOCH is set but cannot be properly interpreted as a UNIX
|
||||
# timestamp, then execute ACTION-IF-FAIL if specified, otherwise error.
|
||||
#
|
||||
# VARIABLE is AC_SUBST-ed.
|
||||
#
|
||||
# LICENSE
|
||||
#
|
||||
# Copyright (c) 2016 Eric Bavier <bavier@member.fsf.org>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License as published by the
|
||||
# Free Software Foundation, either version 3 of the License, or (at your
|
||||
# option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
||||
# Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along
|
||||
# with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
#
|
||||
# As a special exception, the respective Autoconf Macro's copyright owner
|
||||
# gives unlimited permission to copy, distribute and modify the configure
|
||||
# scripts that are the output of Autoconf when processing the Macro. You
|
||||
# need not follow the terms of the GNU General Public License when using
|
||||
# or distributing such scripts, even though portions of the text of the
|
||||
# Macro appear in them. The GNU General Public License (GPL) does govern
|
||||
# all other use of the material that constitutes the Autoconf Macro.
|
||||
#
|
||||
# This special exception to the GPL applies to versions of the Autoconf
|
||||
# Macro released by the Autoconf Archive. When you make and distribute a
|
||||
# modified version of the Autoconf Macro, you may extend this special
|
||||
# exception to the GPL to apply to your modified version as well.
|
||||
|
||||
#serial 2
|
||||
|
||||
AC_DEFUN([AX_BUILD_DATE_EPOCH],
|
||||
[dnl
|
||||
AC_MSG_CHECKING([for build time])
|
||||
ax_date_fmt="m4_default($2,%s)"
|
||||
AS_IF([test x"$SOURCE_DATE_EPOCH" = x],
|
||||
[$1=`date "+$ax_date_fmt"`],
|
||||
[ax_build_date=`date -u -d "@$SOURCE_DATE_EPOCH" "+$ax_date_fmt" 2>/dev/null \
|
||||
|| date -u -r "$SOURCE_DATE_EPOCH" "+$ax_date_fmt" 2>/dev/null`
|
||||
AS_IF([test x"$ax_build_date" = x],
|
||||
[m4_ifval([$3],
|
||||
[$3],
|
||||
[AC_MSG_ERROR([malformed SOURCE_DATE_EPOCH])])],
|
||||
[$1=$ax_build_date])])
|
||||
AC_MSG_RESULT([$$1])
|
||||
])dnl AX_BUILD_DATE_EPOCH
|
||||
+7
-3
@@ -47,6 +47,7 @@
|
||||
#include "util/regional.h"
|
||||
#include "util/net_help.h"
|
||||
#include "util/config_file.h"
|
||||
#include "util/data/dname.h"
|
||||
#include "util/data/msgreply.h"
|
||||
#include "util/data/msgencode.h"
|
||||
#include "services/cache/dns.h"
|
||||
@@ -341,6 +342,7 @@ calc_hash(struct query_info* qinfo, struct module_env* env, char* buf,
|
||||
/* copy the hash info into the clear buffer */
|
||||
if(clen + qinfo->qname_len < sizeof(clear)) {
|
||||
memmove(clear+clen, qinfo->qname, qinfo->qname_len);
|
||||
query_dname_tolower(clear+clen);
|
||||
clen += qinfo->qname_len;
|
||||
}
|
||||
if(clen + 4 < sizeof(clear)) {
|
||||
@@ -621,6 +623,9 @@ parse_data(struct module_qstate* qstate, struct sldns_buffer* buf,
|
||||
}
|
||||
verbose(VERB_ALGO, "cachedb msg adjusted down by %d", (int)adjust);
|
||||
adjust_msg_ttl(qstate->return_msg, adjust);
|
||||
if(qstate->env->cfg->aggressive_nsec) {
|
||||
limit_nsec_ttl(qstate->return_msg);
|
||||
}
|
||||
|
||||
/* Similar to the unbound worker, if serve-expired is enabled and
|
||||
* the msg would be considered to be expired, mark the state so a
|
||||
@@ -752,7 +757,8 @@ cachedb_intcache_store(struct module_qstate* qstate, int msg_expired)
|
||||
}
|
||||
(void)dns_cache_store(qstate->env, &qstate->qinfo,
|
||||
qstate->return_msg->rep, 0, qstate->prefetch_leeway, 0,
|
||||
qstate->region, store_flags, qstate->qstarttime);
|
||||
qstate->region, store_flags, qstate->qstarttime,
|
||||
qstate->is_valrec);
|
||||
if(serve_expired && msg_expired) {
|
||||
if(qstate->env->cfg->serve_expired_client_timeout) {
|
||||
/* No expired response from the query state, the
|
||||
@@ -828,8 +834,6 @@ cachedb_handle_query(struct module_qstate* qstate,
|
||||
/* In case we have expired data but there is a client timer for expired
|
||||
* answers, pass execution to next module in order to try updating the
|
||||
* data first.
|
||||
* TODO: this needs revisit. The expired data stored from cachedb has
|
||||
* 0 TTL which is picked up by iterator later when looking in the cache.
|
||||
*/
|
||||
if(qstate->env->cfg->serve_expired && msg_expired) {
|
||||
qstate->return_msg = NULL;
|
||||
|
||||
+203
-64
@@ -52,18 +52,38 @@
|
||||
#include "hiredis/hiredis.h"
|
||||
|
||||
struct redis_moddata {
|
||||
redisContext** ctxs; /* thread-specific redis contexts */
|
||||
int numctxs; /* number of ctx entries */
|
||||
const char* server_host; /* server's IP address or host name */
|
||||
int server_port; /* server's TCP port */
|
||||
const char* server_path; /* server's unix path, or "", NULL if unused */
|
||||
const char* server_password; /* server's AUTH password, or "", NULL if unused */
|
||||
struct timeval timeout; /* timeout for connection setup and commands */
|
||||
int logical_db; /* the redis logical database to use */
|
||||
/* thread-specific redis contexts */
|
||||
redisContext** ctxs;
|
||||
redisContext** replica_ctxs;
|
||||
/* number of ctx entries */
|
||||
int numctxs;
|
||||
/* server's IP address or host name */
|
||||
const char* server_host;
|
||||
const char* replica_server_host;
|
||||
/* server's TCP port */
|
||||
int server_port;
|
||||
int replica_server_port;
|
||||
/* server's unix path, or "", NULL if unused */
|
||||
const char* server_path;
|
||||
const char* replica_server_path;
|
||||
/* server's AUTH password, or "", NULL if unused */
|
||||
const char* server_password;
|
||||
const char* replica_server_password;
|
||||
/* timeout for commands */
|
||||
struct timeval command_timeout;
|
||||
struct timeval replica_command_timeout;
|
||||
/* timeout for connection setup */
|
||||
struct timeval connect_timeout;
|
||||
struct timeval replica_connect_timeout;
|
||||
/* the redis logical database to use */
|
||||
int logical_db;
|
||||
int replica_logical_db;
|
||||
/* if the SET with EX command is supported */
|
||||
int set_with_ex_available;
|
||||
};
|
||||
|
||||
static redisReply* redis_command(struct module_env*, struct cachedb_env*,
|
||||
const char*, const uint8_t*, size_t);
|
||||
const char*, const uint8_t*, size_t, int);
|
||||
|
||||
static void
|
||||
moddata_clean(struct redis_moddata** moddata) {
|
||||
@@ -77,21 +97,30 @@ moddata_clean(struct redis_moddata** moddata) {
|
||||
}
|
||||
free((*moddata)->ctxs);
|
||||
}
|
||||
if((*moddata)->replica_ctxs) {
|
||||
int i;
|
||||
for(i = 0; i < (*moddata)->numctxs; i++) {
|
||||
if((*moddata)->replica_ctxs[i])
|
||||
redisFree((*moddata)->replica_ctxs[i]);
|
||||
}
|
||||
free((*moddata)->replica_ctxs);
|
||||
}
|
||||
free(*moddata);
|
||||
*moddata = NULL;
|
||||
}
|
||||
|
||||
static redisContext*
|
||||
redis_connect(const struct redis_moddata* moddata)
|
||||
redis_connect(const char* host, int port, const char* path,
|
||||
const char* password, int logical_db,
|
||||
const struct timeval connect_timeout,
|
||||
const struct timeval command_timeout)
|
||||
{
|
||||
redisContext* ctx;
|
||||
|
||||
if(moddata->server_path && moddata->server_path[0]!=0) {
|
||||
ctx = redisConnectUnixWithTimeout(moddata->server_path,
|
||||
moddata->timeout);
|
||||
if(path && path[0]!=0) {
|
||||
ctx = redisConnectUnixWithTimeout(path, connect_timeout);
|
||||
} else {
|
||||
ctx = redisConnectWithTimeout(moddata->server_host,
|
||||
moddata->server_port, moddata->timeout);
|
||||
ctx = redisConnectWithTimeout(host, port, connect_timeout);
|
||||
}
|
||||
if(!ctx || ctx->err) {
|
||||
const char *errstr = "out of memory";
|
||||
@@ -100,13 +129,13 @@ redis_connect(const struct redis_moddata* moddata)
|
||||
log_err("failed to connect to redis server: %s", errstr);
|
||||
goto fail;
|
||||
}
|
||||
if(redisSetTimeout(ctx, moddata->timeout) != REDIS_OK) {
|
||||
log_err("failed to set redis timeout");
|
||||
if(redisSetTimeout(ctx, command_timeout) != REDIS_OK) {
|
||||
log_err("failed to set redis timeout, %s", ctx->errstr);
|
||||
goto fail;
|
||||
}
|
||||
if(moddata->server_password && moddata->server_password[0]!=0) {
|
||||
if(password && password[0]!=0) {
|
||||
redisReply* rep;
|
||||
rep = redisCommand(ctx, "AUTH %s", moddata->server_password);
|
||||
rep = redisCommand(ctx, "AUTH %s", password);
|
||||
if(!rep || rep->type == REDIS_REPLY_ERROR) {
|
||||
log_err("failed to authenticate with password");
|
||||
freeReplyObject(rep);
|
||||
@@ -114,18 +143,25 @@ redis_connect(const struct redis_moddata* moddata)
|
||||
}
|
||||
freeReplyObject(rep);
|
||||
}
|
||||
if(moddata->logical_db > 0) {
|
||||
if(logical_db > 0) {
|
||||
redisReply* rep;
|
||||
rep = redisCommand(ctx, "SELECT %d", moddata->logical_db);
|
||||
rep = redisCommand(ctx, "SELECT %d", logical_db);
|
||||
if(!rep || rep->type == REDIS_REPLY_ERROR) {
|
||||
log_err("failed to set logical database (%d)",
|
||||
moddata->logical_db);
|
||||
logical_db);
|
||||
freeReplyObject(rep);
|
||||
goto fail;
|
||||
}
|
||||
freeReplyObject(rep);
|
||||
}
|
||||
verbose(VERB_OPS, "Connection to Redis established");
|
||||
if(verbosity >= VERB_OPS) {
|
||||
char port_str[6+1];
|
||||
port_str[0] = ' ';
|
||||
(void)snprintf(port_str+1, sizeof(port_str)-1, "%d", port);
|
||||
verbose(VERB_OPS, "Connection to Redis established (%s%s)",
|
||||
path&&path[0]!=0?path:host,
|
||||
path&&path[0]!=0?"":port_str);
|
||||
}
|
||||
return ctx;
|
||||
|
||||
fail:
|
||||
@@ -134,6 +170,14 @@ fail:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
set_timeout(struct timeval* timeout, int value, int explicit_value)
|
||||
{
|
||||
int v = explicit_value != 0 ? explicit_value : value;
|
||||
timeout->tv_sec = v / 1000;
|
||||
timeout->tv_usec = (v % 1000) * 1000;
|
||||
}
|
||||
|
||||
static int
|
||||
redis_init(struct module_env* env, struct cachedb_env* cachedb_env)
|
||||
{
|
||||
@@ -148,41 +192,98 @@ redis_init(struct module_env* env, struct cachedb_env* cachedb_env)
|
||||
goto fail;
|
||||
}
|
||||
moddata->numctxs = env->cfg->num_threads;
|
||||
/* note: server_host and similar string configuration options are
|
||||
* shallow references to configured strings; we don't have to free them
|
||||
* in this module. */
|
||||
moddata->server_host = env->cfg->redis_server_host;
|
||||
moddata->replica_server_host = env->cfg->redis_replica_server_host;
|
||||
|
||||
moddata->server_port = env->cfg->redis_server_port;
|
||||
moddata->replica_server_port = env->cfg->redis_replica_server_port;
|
||||
|
||||
moddata->server_path = env->cfg->redis_server_path;
|
||||
moddata->replica_server_path = env->cfg->redis_replica_server_path;
|
||||
|
||||
moddata->server_password = env->cfg->redis_server_password;
|
||||
moddata->replica_server_password = env->cfg->redis_replica_server_password;
|
||||
|
||||
set_timeout(&moddata->command_timeout,
|
||||
env->cfg->redis_timeout,
|
||||
env->cfg->redis_command_timeout);
|
||||
set_timeout(&moddata->replica_command_timeout,
|
||||
env->cfg->redis_replica_timeout,
|
||||
env->cfg->redis_replica_command_timeout);
|
||||
set_timeout(&moddata->connect_timeout,
|
||||
env->cfg->redis_timeout,
|
||||
env->cfg->redis_connect_timeout);
|
||||
set_timeout(&moddata->replica_connect_timeout,
|
||||
env->cfg->redis_replica_timeout,
|
||||
env->cfg->redis_replica_connect_timeout);
|
||||
|
||||
moddata->logical_db = env->cfg->redis_logical_db;
|
||||
moddata->replica_logical_db = env->cfg->redis_replica_logical_db;
|
||||
|
||||
moddata->ctxs = calloc(env->cfg->num_threads, sizeof(redisContext*));
|
||||
if(!moddata->ctxs) {
|
||||
log_err("out of memory");
|
||||
goto fail;
|
||||
}
|
||||
/* note: server_host is a shallow reference to configured string.
|
||||
* we don't have to free it in this module. */
|
||||
moddata->server_host = env->cfg->redis_server_host;
|
||||
moddata->server_port = env->cfg->redis_server_port;
|
||||
moddata->server_path = env->cfg->redis_server_path;
|
||||
moddata->server_password = env->cfg->redis_server_password;
|
||||
moddata->timeout.tv_sec = env->cfg->redis_timeout / 1000;
|
||||
moddata->timeout.tv_usec = (env->cfg->redis_timeout % 1000) * 1000;
|
||||
moddata->logical_db = env->cfg->redis_logical_db;
|
||||
for(i = 0; i < moddata->numctxs; i++) {
|
||||
redisContext* ctx = redis_connect(moddata);
|
||||
if(!ctx) {
|
||||
log_err("redis_init: failed to init redis");
|
||||
if((moddata->replica_server_host && moddata->replica_server_host[0]!=0)
|
||||
|| (moddata->replica_server_path && moddata->replica_server_path[0]!=0)) {
|
||||
/* There is a replica configured, allocate ctxs */
|
||||
moddata->replica_ctxs = calloc(env->cfg->num_threads, sizeof(redisContext*));
|
||||
if(!moddata->replica_ctxs) {
|
||||
log_err("out of memory");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
for(i = 0; i < moddata->numctxs; i++) {
|
||||
redisContext* ctx = redis_connect(
|
||||
moddata->server_host,
|
||||
moddata->server_port,
|
||||
moddata->server_path,
|
||||
moddata->server_password,
|
||||
moddata->logical_db,
|
||||
moddata->connect_timeout,
|
||||
moddata->command_timeout);
|
||||
if(!ctx) {
|
||||
log_err("redis_init: failed to init redis "
|
||||
"(for thread %d)", i);
|
||||
/* And continue, the context can be established
|
||||
* later, just like after a disconnect. */
|
||||
}
|
||||
moddata->ctxs[i] = ctx;
|
||||
}
|
||||
if(moddata->replica_ctxs) {
|
||||
for(i = 0; i < moddata->numctxs; i++) {
|
||||
redisContext* ctx = redis_connect(
|
||||
moddata->replica_server_host,
|
||||
moddata->replica_server_port,
|
||||
moddata->replica_server_path,
|
||||
moddata->replica_server_password,
|
||||
moddata->replica_logical_db,
|
||||
moddata->replica_connect_timeout,
|
||||
moddata->replica_command_timeout);
|
||||
if(!ctx) {
|
||||
log_err("redis_init: failed to init redis "
|
||||
"replica (for thread %d)", i);
|
||||
/* And continue, the context can be established
|
||||
* later, just like after a disconnect. */
|
||||
}
|
||||
moddata->replica_ctxs[i] = ctx;
|
||||
}
|
||||
}
|
||||
cachedb_env->backend_data = moddata;
|
||||
if(env->cfg->redis_expire_records) {
|
||||
if(env->cfg->redis_expire_records &&
|
||||
moddata->ctxs[env->alloc->thread_num] != NULL) {
|
||||
redisReply* rep = NULL;
|
||||
int redis_reply_type = 0;
|
||||
/** check if setex command is supported */
|
||||
/** check if set with ex command is supported */
|
||||
rep = redis_command(env, cachedb_env,
|
||||
"SETEX __UNBOUND_REDIS_CHECK__ 1 none", NULL, 0);
|
||||
"SET __UNBOUND_REDIS_CHECK__ none EX 1", NULL, 0, 1);
|
||||
if(!rep) {
|
||||
/** init failed, no response from redis server*/
|
||||
log_err("redis_init: failed to init redis, the "
|
||||
"redis-expire-records option requires the SETEX command "
|
||||
"(redis >= 2.0.0)");
|
||||
goto fail;
|
||||
goto set_with_ex_fail;
|
||||
}
|
||||
redis_reply_type = rep->type;
|
||||
freeReplyObject(rep);
|
||||
@@ -190,15 +291,18 @@ redis_init(struct module_env* env, struct cachedb_env* cachedb_env)
|
||||
case REDIS_REPLY_STATUS:
|
||||
break;
|
||||
default:
|
||||
/** init failed, setex command not supported */
|
||||
log_err("redis_init: failed to init redis, the "
|
||||
"redis-expire-records option requires the SETEX command "
|
||||
"(redis >= 2.0.0)");
|
||||
goto fail;
|
||||
/** init failed, set_with_ex command not supported */
|
||||
goto set_with_ex_fail;
|
||||
}
|
||||
moddata->set_with_ex_available = 1;
|
||||
}
|
||||
return 1;
|
||||
|
||||
set_with_ex_fail:
|
||||
log_err("redis_init: failure during redis_init, the "
|
||||
"redis-expire-records option requires the SET with EX command "
|
||||
"(redis >= 2.6.2)");
|
||||
return 1;
|
||||
fail:
|
||||
moddata_clean(&moddata);
|
||||
return 0;
|
||||
@@ -229,9 +333,9 @@ redis_deinit(struct module_env* env, struct cachedb_env* cachedb_env)
|
||||
*/
|
||||
static redisReply*
|
||||
redis_command(struct module_env* env, struct cachedb_env* cachedb_env,
|
||||
const char* command, const uint8_t* data, size_t data_len)
|
||||
const char* command, const uint8_t* data, size_t data_len, int write)
|
||||
{
|
||||
redisContext* ctx;
|
||||
redisContext* ctx, **ctx_selector;
|
||||
redisReply* rep;
|
||||
struct redis_moddata* d = (struct redis_moddata*)
|
||||
cachedb_env->backend_data;
|
||||
@@ -242,17 +346,38 @@ redis_command(struct module_env* env, struct cachedb_env* cachedb_env,
|
||||
* assumption throughout the unbound architecture, so we simply assert
|
||||
* it. */
|
||||
log_assert(env->alloc->thread_num < d->numctxs);
|
||||
ctx = d->ctxs[env->alloc->thread_num];
|
||||
|
||||
ctx_selector = !write && d->replica_ctxs
|
||||
?d->replica_ctxs
|
||||
:d->ctxs;
|
||||
ctx = ctx_selector[env->alloc->thread_num];
|
||||
|
||||
/* If we've not established a connection to the server or we've closed
|
||||
* it on a failure, try to re-establish a new one. Failures will be
|
||||
* logged in redis_connect(). */
|
||||
if(!ctx) {
|
||||
ctx = redis_connect(d);
|
||||
d->ctxs[env->alloc->thread_num] = ctx;
|
||||
if(!write && d->replica_ctxs) {
|
||||
ctx = redis_connect(
|
||||
d->replica_server_host,
|
||||
d->replica_server_port,
|
||||
d->replica_server_path,
|
||||
d->replica_server_password,
|
||||
d->replica_logical_db,
|
||||
d->replica_connect_timeout,
|
||||
d->replica_command_timeout);
|
||||
} else {
|
||||
ctx = redis_connect(
|
||||
d->server_host,
|
||||
d->server_port,
|
||||
d->server_path,
|
||||
d->server_password,
|
||||
d->logical_db,
|
||||
d->connect_timeout,
|
||||
d->command_timeout);
|
||||
}
|
||||
ctx_selector[env->alloc->thread_num] = ctx;
|
||||
}
|
||||
if(!ctx)
|
||||
return NULL;
|
||||
if(!ctx) return NULL;
|
||||
|
||||
/* Send the command and get a reply, synchronously. */
|
||||
rep = (redisReply*)redisCommand(ctx, command, data, data_len);
|
||||
@@ -262,7 +387,7 @@ redis_command(struct module_env* env, struct cachedb_env* cachedb_env,
|
||||
log_err("redis_command: failed to receive a reply, "
|
||||
"closing connection: %s", ctx->errstr);
|
||||
redisFree(ctx);
|
||||
d->ctxs[env->alloc->thread_num] = NULL;
|
||||
ctx_selector[env->alloc->thread_num] = NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -292,7 +417,7 @@ redis_lookup(struct module_env* env, struct cachedb_env* cachedb_env,
|
||||
return 0;
|
||||
}
|
||||
|
||||
rep = redis_command(env, cachedb_env, cmdbuf, NULL, 0);
|
||||
rep = redis_command(env, cachedb_env, cmdbuf, NULL, 0, 0);
|
||||
if(!rep)
|
||||
return 0;
|
||||
switch(rep->type) {
|
||||
@@ -329,11 +454,16 @@ redis_store(struct module_env* env, struct cachedb_env* cachedb_env,
|
||||
{
|
||||
redisReply* rep;
|
||||
int n;
|
||||
int set_ttl = (env->cfg->redis_expire_records &&
|
||||
struct redis_moddata* moddata = (struct redis_moddata*)
|
||||
cachedb_env->backend_data;
|
||||
int set_ttl = (moddata->set_with_ex_available &&
|
||||
env->cfg->redis_expire_records &&
|
||||
(!env->cfg->serve_expired || env->cfg->serve_expired_ttl > 0));
|
||||
/* Supported commands:
|
||||
* - "SET " + key + " %b"
|
||||
* - "SETEX " + key + " " + ttl + " %b"
|
||||
* - "SET " + key + " %b EX " + ttl
|
||||
* older redis 2.0.0 was "SETEX " + key + " " + ttl + " %b"
|
||||
* - "EXPIRE " + key + " 0"
|
||||
*/
|
||||
char cmdbuf[6+(CACHEDB_HASHSIZE/8)*2+11+3+1];
|
||||
|
||||
@@ -341,14 +471,22 @@ redis_store(struct module_env* env, struct cachedb_env* cachedb_env,
|
||||
verbose(VERB_ALGO, "redis_store %s (%d bytes)", key, (int)data_len);
|
||||
/* build command to set to a binary safe string */
|
||||
n = snprintf(cmdbuf, sizeof(cmdbuf), "SET %s %%b", key);
|
||||
} else if(ttl == 0) {
|
||||
/* use the EXPIRE command, SET with EX 0 is an invalid time. */
|
||||
/* Replies with REDIS_REPLY_INTEGER of 1. */
|
||||
verbose(VERB_ALGO, "redis_store expire %s (%d bytes)",
|
||||
key, (int)data_len);
|
||||
n = snprintf(cmdbuf, sizeof(cmdbuf), "EXPIRE %s 0", key);
|
||||
data = NULL;
|
||||
data_len = 0;
|
||||
} else {
|
||||
/* add expired ttl time to redis ttl to avoid premature eviction of key */
|
||||
ttl += env->cfg->serve_expired_ttl;
|
||||
verbose(VERB_ALGO, "redis_store %s (%d bytes) with ttl %u",
|
||||
key, (int)data_len, (uint32_t)ttl);
|
||||
key, (int)data_len, (unsigned)(uint32_t)ttl);
|
||||
/* build command to set to a binary safe string */
|
||||
n = snprintf(cmdbuf, sizeof(cmdbuf), "SETEX %s %u %%b", key,
|
||||
(uint32_t)ttl);
|
||||
n = snprintf(cmdbuf, sizeof(cmdbuf), "SET %s %%b EX %u", key,
|
||||
(unsigned)(uint32_t)ttl);
|
||||
}
|
||||
|
||||
|
||||
@@ -357,11 +495,12 @@ redis_store(struct module_env* env, struct cachedb_env* cachedb_env,
|
||||
return;
|
||||
}
|
||||
|
||||
rep = redis_command(env, cachedb_env, cmdbuf, data, data_len);
|
||||
rep = redis_command(env, cachedb_env, cmdbuf, data, data_len, 1);
|
||||
if(rep) {
|
||||
verbose(VERB_ALGO, "redis_store set completed");
|
||||
if(rep->type != REDIS_REPLY_STATUS &&
|
||||
rep->type != REDIS_REPLY_ERROR) {
|
||||
rep->type != REDIS_REPLY_ERROR &&
|
||||
rep->type != REDIS_REPLY_INTEGER) {
|
||||
log_err("redis_store: unexpected type of reply (%d)",
|
||||
rep->type);
|
||||
}
|
||||
|
||||
@@ -5,12 +5,8 @@
|
||||
#undef malloc
|
||||
#include <sys/types.h>
|
||||
|
||||
#ifndef USE_WINSOCK
|
||||
void *malloc ();
|
||||
#else
|
||||
/* provide a prototype */
|
||||
void *malloc (size_t n);
|
||||
#endif
|
||||
|
||||
/* Allocate an N-byte block of memory from the heap.
|
||||
If N is zero, allocate a 1-byte block. */
|
||||
|
||||
+109
@@ -1,5 +1,8 @@
|
||||
/* config.h.in. Generated from configure.ac by autoheader. */
|
||||
|
||||
/* apply the fallthrough attribute. */
|
||||
#undef ATTR_FALLTHROUGH
|
||||
|
||||
/* apply the noreturn attribute to a function that exits the program */
|
||||
#undef ATTR_NORETURN
|
||||
|
||||
@@ -57,6 +60,9 @@
|
||||
/* Define to 1 if you have the <arpa/inet.h> header file. */
|
||||
#undef HAVE_ARPA_INET_H
|
||||
|
||||
/* Whether the C compiler accepts the "fallthrough" attribute */
|
||||
#undef HAVE_ATTR_FALLTHROUGH
|
||||
|
||||
/* Whether the C compiler accepts the "format" attribute */
|
||||
#undef HAVE_ATTR_FORMAT
|
||||
|
||||
@@ -123,6 +129,14 @@
|
||||
and to 0 if you don't. */
|
||||
#undef HAVE_DECL_NGHTTP2_SESSION_SERVER_NEW
|
||||
|
||||
/* Define to 1 if you have the declaration of `ngtcp2_conn_server_new', and to
|
||||
0 if you don't. */
|
||||
#undef HAVE_DECL_NGTCP2_CONN_SERVER_NEW
|
||||
|
||||
/* Define to 1 if you have the declaration of `ngtcp2_crypto_encrypt_cb', and
|
||||
to 0 if you don't. */
|
||||
#undef HAVE_DECL_NGTCP2_CRYPTO_ENCRYPT_CB
|
||||
|
||||
/* Define to 1 if you have the declaration of `NID_ED25519', and to 0 if you
|
||||
don't. */
|
||||
#undef HAVE_DECL_NID_ED25519
|
||||
@@ -364,6 +378,9 @@
|
||||
/* Define if we have LibreSSL */
|
||||
#undef HAVE_LIBRESSL
|
||||
|
||||
/* If we have atomic_store */
|
||||
#undef HAVE_LINK_ATOMIC_STORE
|
||||
|
||||
/* Define to 1 if you have the <linux/net_tstamp.h> header file. */
|
||||
#undef HAVE_LINUX_NET_TSTAMP_H
|
||||
|
||||
@@ -415,6 +432,65 @@
|
||||
/* Define to 1 if you have the <nghttp2/nghttp2.h> header file. */
|
||||
#undef HAVE_NGHTTP2_NGHTTP2_H
|
||||
|
||||
/* Define this to use ngtcp2. */
|
||||
#undef HAVE_NGTCP2
|
||||
|
||||
/* Define to 1 if you have the `ngtcp2_ccerr_default' function. */
|
||||
#undef HAVE_NGTCP2_CCERR_DEFAULT
|
||||
|
||||
/* Define to 1 if you have the `ngtcp2_conn_encode_0rtt_transport_params'
|
||||
function. */
|
||||
#undef HAVE_NGTCP2_CONN_ENCODE_0RTT_TRANSPORT_PARAMS
|
||||
|
||||
/* Define to 1 if you have the `ngtcp2_conn_get_max_local_streams_uni'
|
||||
function. */
|
||||
#undef HAVE_NGTCP2_CONN_GET_MAX_LOCAL_STREAMS_UNI
|
||||
|
||||
/* Define to 1 if you have the `ngtcp2_conn_get_num_scid' function. */
|
||||
#undef HAVE_NGTCP2_CONN_GET_NUM_SCID
|
||||
|
||||
/* Define to 1 if you have the `ngtcp2_conn_in_closing_period' function. */
|
||||
#undef HAVE_NGTCP2_CONN_IN_CLOSING_PERIOD
|
||||
|
||||
/* Define to 1 if you have the `ngtcp2_conn_in_draining_period' function. */
|
||||
#undef HAVE_NGTCP2_CONN_IN_DRAINING_PERIOD
|
||||
|
||||
/* Define if ngtcp2_conn_shutdown_stream has 4 arguments. */
|
||||
#undef HAVE_NGTCP2_CONN_SHUTDOWN_STREAM4
|
||||
|
||||
/* Define to 1 if you have the `ngtcp2_conn_tls_early_data_rejected' function.
|
||||
*/
|
||||
#undef HAVE_NGTCP2_CONN_TLS_EARLY_DATA_REJECTED
|
||||
|
||||
/* Define to 1 if you have the `ngtcp2_crypto_encrypt_cb' function. */
|
||||
#undef HAVE_NGTCP2_CRYPTO_ENCRYPT_CB
|
||||
|
||||
/* Define to 1 if you have the
|
||||
`ngtcp2_crypto_quictls_configure_client_context' function. */
|
||||
#undef HAVE_NGTCP2_CRYPTO_QUICTLS_CONFIGURE_CLIENT_CONTEXT
|
||||
|
||||
/* Define to 1 if you have the
|
||||
`ngtcp2_crypto_quictls_configure_server_context' function. */
|
||||
#undef HAVE_NGTCP2_CRYPTO_QUICTLS_CONFIGURE_SERVER_CONTEXT
|
||||
|
||||
/* Define to 1 if you have the
|
||||
`ngtcp2_crypto_quictls_from_ossl_encryption_level' function. */
|
||||
#undef HAVE_NGTCP2_CRYPTO_QUICTLS_FROM_OSSL_ENCRYPTION_LEVEL
|
||||
|
||||
/* Define to 1 if the system has the type `ngtcp2_encryption_level'. */
|
||||
#undef HAVE_NGTCP2_ENCRYPTION_LEVEL
|
||||
|
||||
/* Define to 1 if you have the <ngtcp2/ngtcp2_crypto_openssl.h> header file.
|
||||
*/
|
||||
#undef HAVE_NGTCP2_NGTCP2_CRYPTO_OPENSSL_H
|
||||
|
||||
/* Define to 1 if you have the <ngtcp2/ngtcp2_crypto_quictls.h> header file.
|
||||
*/
|
||||
#undef HAVE_NGTCP2_NGTCP2_CRYPTO_QUICTLS_H
|
||||
|
||||
/* Define to 1 if you have the <ngtcp2/ngtcp2.h> header file. */
|
||||
#undef HAVE_NGTCP2_NGTCP2_H
|
||||
|
||||
/* Use libnss for crypto */
|
||||
#undef HAVE_NSS
|
||||
|
||||
@@ -581,12 +657,18 @@
|
||||
/* Define to 1 if you have the `SSL_get1_peer_certificate' function. */
|
||||
#undef HAVE_SSL_GET1_PEER_CERTIFICATE
|
||||
|
||||
/* Define to 1 if you have the `SSL_is_quic' function. */
|
||||
#undef HAVE_SSL_IS_QUIC
|
||||
|
||||
/* Define to 1 if you have the `SSL_set1_host' function. */
|
||||
#undef HAVE_SSL_SET1_HOST
|
||||
|
||||
/* Define to 1 if you have the <stdarg.h> header file. */
|
||||
#undef HAVE_STDARG_H
|
||||
|
||||
/* Define to 1 if you have the <stdatomic.h> header file. */
|
||||
#undef HAVE_STDATOMIC_H
|
||||
|
||||
/* Define to 1 if you have the <stdbool.h> header file. */
|
||||
#undef HAVE_STDBOOL_H
|
||||
|
||||
@@ -623,6 +705,23 @@
|
||||
/* Define to 1 if `ipi_spec_dst' is a member of `struct in_pktinfo'. */
|
||||
#undef HAVE_STRUCT_IN_PKTINFO_IPI_SPEC_DST
|
||||
|
||||
/* Define to 1 if `tokenlen' is a member of `struct ngtcp2_pkt_hd'. */
|
||||
#undef HAVE_STRUCT_NGTCP2_PKT_HD_TOKENLEN
|
||||
|
||||
/* Define to 1 if `max_tx_udp_payload_size' is a member of `struct
|
||||
ngtcp2_settings'. */
|
||||
#undef HAVE_STRUCT_NGTCP2_SETTINGS_MAX_TX_UDP_PAYLOAD_SIZE
|
||||
|
||||
/* Define to 1 if `tokenlen' is a member of `struct ngtcp2_settings'. */
|
||||
#undef HAVE_STRUCT_NGTCP2_SETTINGS_TOKENLEN
|
||||
|
||||
/* Define to 1 if `original_dcid_present' is a member of `struct
|
||||
ngtcp2_transport_params'. */
|
||||
#undef HAVE_STRUCT_NGTCP2_TRANSPORT_PARAMS_ORIGINAL_DCID_PRESENT
|
||||
|
||||
/* Define to 1 if the system has the type `struct ngtcp2_version_cid'. */
|
||||
#undef HAVE_STRUCT_NGTCP2_VERSION_CID
|
||||
|
||||
/* Define to 1 if `sun_len' is a member of `struct sockaddr_un'. */
|
||||
#undef HAVE_STRUCT_SOCKADDR_UN_SUN_LEN
|
||||
|
||||
@@ -1490,6 +1589,10 @@ struct sockaddr_storage;
|
||||
# define calloc(n,s) unbound_stat_calloc_log(n, s, __FILE__, __LINE__, __func__)
|
||||
# define free(p) unbound_stat_free_log(p, __FILE__, __LINE__, __func__)
|
||||
# define realloc(p,s) unbound_stat_realloc_log(p, s, __FILE__, __LINE__, __func__)
|
||||
# define strdup(s) unbound_stat_strdup_log(s, __FILE__, __LINE__, __func__)
|
||||
#ifdef HAVE_REALLOCARRAY
|
||||
# define reallocarray(p,n,s) unbound_stat_reallocarray_log(p, n, s, __FILE__, __LINE__, __func__)
|
||||
#endif
|
||||
void *unbound_stat_malloc(size_t size);
|
||||
void *unbound_stat_calloc(size_t nmemb, size_t size);
|
||||
void unbound_stat_free(void *ptr);
|
||||
@@ -1502,6 +1605,10 @@ void unbound_stat_free_log(void *ptr, const char* file, int line,
|
||||
const char* func);
|
||||
void *unbound_stat_realloc_log(void *ptr, size_t size, const char* file,
|
||||
int line, const char* func);
|
||||
void *unbound_stat_reallocarray_log(void *ptr, size_t nmemb, size_t size,
|
||||
const char* file, int line, const char* func);
|
||||
char *unbound_stat_strdup_log(const char *s, const char* file, int line,
|
||||
const char* func);
|
||||
#elif defined(UNBOUND_ALLOC_LITE)
|
||||
# include "util/alloc.h"
|
||||
#endif /* UNBOUND_ALLOC_LITE and UNBOUND_ALLOC_STATS */
|
||||
@@ -1512,6 +1619,8 @@ void *unbound_stat_realloc_log(void *ptr, size_t size, const char* file,
|
||||
#define UNBOUND_DNS_OVER_TLS_PORT 853
|
||||
/** default port for DNS over HTTPS traffic. */
|
||||
#define UNBOUND_DNS_OVER_HTTPS_PORT 443
|
||||
/** default port for DNS over QUIC traffic. */
|
||||
#define UNBOUND_DNS_OVER_QUIC_PORT 853
|
||||
/** default port for unbound control traffic, registered port with IANA,
|
||||
ub-dns-control 8953/tcp unbound dns nameserver control */
|
||||
#define UNBOUND_CONTROL_PORT 8953
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#! /bin/sh
|
||||
# Guess values for system-dependent variables and create Makefiles.
|
||||
# Generated by GNU Autoconf 2.71 for unbound 1.20.1.
|
||||
# Generated by GNU Autoconf 2.71 for unbound 1.23.0.
|
||||
#
|
||||
# Report bugs to <unbound-bugs@nlnetlabs.nl or https://github.com/NLnetLabs/unbound/issues>.
|
||||
#
|
||||
@@ -622,8 +622,8 @@ MAKEFLAGS=
|
||||
# Identity of this package.
|
||||
PACKAGE_NAME='unbound'
|
||||
PACKAGE_TARNAME='unbound'
|
||||
PACKAGE_VERSION='1.20.1'
|
||||
PACKAGE_STRING='unbound 1.20.1'
|
||||
PACKAGE_VERSION='1.23.0'
|
||||
PACKAGE_STRING='unbound 1.23.0'
|
||||
PACKAGE_BUGREPORT='unbound-bugs@nlnetlabs.nl or https://github.com/NLnetLabs/unbound/issues'
|
||||
PACKAGE_URL=''
|
||||
|
||||
@@ -712,6 +712,7 @@ SSLLIB
|
||||
HAVE_SSL
|
||||
PC_CRYPTO_DEPENDENCY
|
||||
CONFIG_DATE
|
||||
SOURCE_DATE_EPOCH
|
||||
GCC_DOCKER_LINTFLAGS
|
||||
NETBSD_LINTFLAGS
|
||||
PYUNBOUND_UNINSTALL
|
||||
@@ -921,6 +922,7 @@ with_libevent
|
||||
with_libexpat
|
||||
with_libhiredis
|
||||
with_libnghttp2
|
||||
with_libngtcp2
|
||||
enable_static_exe
|
||||
enable_fully_static
|
||||
enable_lock_checks
|
||||
@@ -958,6 +960,7 @@ SYSTEMD_LIBS
|
||||
SYSTEMD_DAEMON_CFLAGS
|
||||
SYSTEMD_DAEMON_LIBS
|
||||
PYTHON_VERSION
|
||||
SOURCE_DATE_EPOCH
|
||||
PROTOBUFC_CFLAGS
|
||||
PROTOBUFC_LIBS'
|
||||
|
||||
@@ -1508,7 +1511,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.20.1 to adapt to many kinds of systems.
|
||||
\`configure' configures unbound 1.23.0 to adapt to many kinds of systems.
|
||||
|
||||
Usage: $0 [OPTION]... [VAR=VALUE]...
|
||||
|
||||
@@ -1574,7 +1577,7 @@ fi
|
||||
|
||||
if test -n "$ac_init_help"; then
|
||||
case $ac_init_help in
|
||||
short | recursive ) echo "Configuration of unbound 1.20.1:";;
|
||||
short | recursive ) echo "Configuration of unbound 1.23.0:";;
|
||||
esac
|
||||
cat <<\_ACEOF
|
||||
|
||||
@@ -1709,6 +1712,7 @@ Optional Packages:
|
||||
--with-libexpat=path specify explicit path for libexpat.
|
||||
--with-libhiredis=path specify explicit path for libhiredis.
|
||||
--with-libnghttp2=path specify explicit path for libnghttp2.
|
||||
--with-libngtcp2=path specify explicit path for libngtcp2, for QUIC.
|
||||
--with-dnstap-socket-path=pathname
|
||||
set default dnstap socket path
|
||||
--with-protobuf-c=path Path where protobuf-c is installed, for dnstap
|
||||
@@ -1750,6 +1754,10 @@ Some influential environment variables:
|
||||
The installed Python version to use, for example '2.3'. This
|
||||
string will be appended to the Python interpreter canonical
|
||||
name.
|
||||
SOURCE_DATE_EPOCH
|
||||
If it is set, it uses the value of that variable instead of the
|
||||
current time as the build timestamp. The format is a unix
|
||||
timestamp. This enables reproducible build output.
|
||||
PROTOBUFC_CFLAGS
|
||||
C compiler flags for PROTOBUFC, overriding pkg-config
|
||||
PROTOBUFC_LIBS
|
||||
@@ -1822,7 +1830,7 @@ fi
|
||||
test -n "$ac_init_help" && exit $ac_status
|
||||
if $ac_init_version; then
|
||||
cat <<\_ACEOF
|
||||
unbound configure 1.20.1
|
||||
unbound configure 1.23.0
|
||||
generated by GNU Autoconf 2.71
|
||||
|
||||
Copyright (C) 2021 Free Software Foundation, Inc.
|
||||
@@ -2479,7 +2487,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.20.1, which was
|
||||
It was created by unbound $as_me 1.23.0, which was
|
||||
generated by GNU Autoconf 2.71. Invocation command line was
|
||||
|
||||
$ $0$ac_configure_args_raw
|
||||
@@ -3241,13 +3249,13 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
|
||||
|
||||
UNBOUND_VERSION_MAJOR=1
|
||||
|
||||
UNBOUND_VERSION_MINOR=20
|
||||
UNBOUND_VERSION_MINOR=23
|
||||
|
||||
UNBOUND_VERSION_MICRO=1
|
||||
UNBOUND_VERSION_MICRO=0
|
||||
|
||||
|
||||
LIBUNBOUND_CURRENT=9
|
||||
LIBUNBOUND_REVISION=28
|
||||
LIBUNBOUND_REVISION=31
|
||||
LIBUNBOUND_AGE=1
|
||||
# 1.0.0 had 0:12:0
|
||||
# 1.0.1 had 0:13:0
|
||||
@@ -3342,7 +3350,10 @@ LIBUNBOUND_AGE=1
|
||||
# 1.19.2 had 9:25:1
|
||||
# 1.19.3 had 9:26:1
|
||||
# 1.20.0 had 9:27:1
|
||||
# 1.20.1 had 9:28:1
|
||||
# 1.21.0 had 9:28:1
|
||||
# 1.21.1 had 9:29:1
|
||||
# 1.22.0 had 9:30:1
|
||||
# 1.23.0 had 9:31:1
|
||||
|
||||
# Current -- the number of the binary API that we're implementing
|
||||
# Revision -- which iteration of the implementation of the binary
|
||||
@@ -6976,6 +6987,10 @@ printf "%s\n" "#define HAVE_ATTR_WEAK 1" >>confdefs.h
|
||||
|
||||
printf "%s\n" "#define ATTR_WEAK __attribute__((weak))" >>confdefs.h
|
||||
|
||||
else
|
||||
|
||||
printf "%s\n" "#define ATTR_WEAK /**/" >>confdefs.h
|
||||
|
||||
fi
|
||||
|
||||
|
||||
@@ -7023,6 +7038,79 @@ printf "%s\n" "#define HAVE_ATTR_NORETURN 1" >>confdefs.h
|
||||
|
||||
printf "%s\n" "#define ATTR_NORETURN __attribute__((__noreturn__))" >>confdefs.h
|
||||
|
||||
else
|
||||
|
||||
printf "%s\n" "#define ATTR_NORETURN /**/" >>confdefs.h
|
||||
|
||||
fi
|
||||
|
||||
|
||||
|
||||
|
||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the C compiler (${CC-cc}) accepts the \"fallthrough\" attribute" >&5
|
||||
printf %s "checking whether the C compiler (${CC-cc}) accepts the \"fallthrough\" attribute... " >&6; }
|
||||
BAKCFLAGS="$CFLAGS"
|
||||
CFLAGS="$CFLAGS -Werror"
|
||||
if test ${ac_cv_c_fallthrough_attribute+y}
|
||||
then :
|
||||
printf %s "(cached) " >&6
|
||||
else $as_nop
|
||||
ac_cv_c_fallthrough_attribute=no
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
#include <stdio.h>
|
||||
void f(int x) {
|
||||
int y = 0;
|
||||
switch(x) {
|
||||
case 1:
|
||||
y = 1;
|
||||
__attribute__((fallthrough));
|
||||
/* fallthrough */
|
||||
case 2:
|
||||
y++;
|
||||
break;
|
||||
case 3:
|
||||
y = 3;
|
||||
break;
|
||||
}
|
||||
printf("%d", y);
|
||||
}
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
|
||||
f(1);
|
||||
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
if ac_fn_c_try_compile "$LINENO"
|
||||
then :
|
||||
ac_cv_c_fallthrough_attribute="yes"
|
||||
else $as_nop
|
||||
ac_cv_c_fallthrough_attribute="no"
|
||||
fi
|
||||
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
|
||||
|
||||
fi
|
||||
|
||||
CFLAGS="$BAKCFLAGS"
|
||||
|
||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_fallthrough_attribute" >&5
|
||||
printf "%s\n" "$ac_cv_c_fallthrough_attribute" >&6; }
|
||||
if test $ac_cv_c_fallthrough_attribute = yes; then
|
||||
|
||||
printf "%s\n" "#define HAVE_ATTR_FALLTHROUGH 1" >>confdefs.h
|
||||
|
||||
|
||||
printf "%s\n" "#define ATTR_FALLTHROUGH __attribute__((fallthrough));" >>confdefs.h
|
||||
|
||||
else
|
||||
|
||||
printf "%s\n" "#define ATTR_FALLTHROUGH /**/" >>confdefs.h
|
||||
|
||||
fi
|
||||
|
||||
|
||||
@@ -16012,6 +16100,14 @@ then :
|
||||
|
||||
fi
|
||||
|
||||
ac_fn_c_check_header_compile "$LINENO" "stdatomic.h" "ac_cv_header_stdatomic_h" "$ac_includes_default
|
||||
"
|
||||
if test "x$ac_cv_header_stdatomic_h" = xyes
|
||||
then :
|
||||
printf "%s\n" "#define HAVE_STDATOMIC_H 1" >>confdefs.h
|
||||
|
||||
fi
|
||||
|
||||
|
||||
# check for types.
|
||||
# Using own tests for int64* because autoconf builtin only give 32bit.
|
||||
@@ -19812,7 +19908,26 @@ if test "`uname`" = "Linux"; then
|
||||
GCC_DOCKER_LINTFLAGS='-syntax'
|
||||
|
||||
fi
|
||||
CONFIG_DATE=`date +%Y%m%d`
|
||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for build time" >&5
|
||||
printf %s "checking for build time... " >&6; }
|
||||
ax_date_fmt="%Y%m%d"
|
||||
if test x"$SOURCE_DATE_EPOCH" = x
|
||||
then :
|
||||
CONFIG_DATE=`date "+$ax_date_fmt"`
|
||||
else $as_nop
|
||||
ax_build_date=`date -u -d "@$SOURCE_DATE_EPOCH" "+$ax_date_fmt" 2>/dev/null \
|
||||
|| date -u -r "$SOURCE_DATE_EPOCH" "+$ax_date_fmt" 2>/dev/null`
|
||||
if test x"$ax_build_date" = x
|
||||
then :
|
||||
as_fn_error $? "malformed SOURCE_DATE_EPOCH" "$LINENO" 5
|
||||
else $as_nop
|
||||
CONFIG_DATE=$ax_build_date
|
||||
fi
|
||||
fi
|
||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CONFIG_DATE" >&5
|
||||
printf "%s\n" "$CONFIG_DATE" >&6; }
|
||||
|
||||
|
||||
|
||||
|
||||
# Checks for libraries.
|
||||
@@ -22126,6 +22241,353 @@ printf "%s\n" "#define HAVE_DECL_NGHTTP2_SESSION_SERVER_NEW $ac_have_decl" >>con
|
||||
|
||||
fi
|
||||
|
||||
# ngtcp2
|
||||
|
||||
# Check whether --with-libngtcp2 was given.
|
||||
if test ${with_libngtcp2+y}
|
||||
then :
|
||||
withval=$with_libngtcp2;
|
||||
else $as_nop
|
||||
withval="no"
|
||||
fi
|
||||
|
||||
found_libngtcp2="no"
|
||||
if test x_$withval = x_yes -o x_$withval != x_no; then
|
||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for libngtcp2" >&5
|
||||
printf %s "checking for libngtcp2... " >&6; }
|
||||
if test x_$withval = x_ -o x_$withval = x_yes; then
|
||||
withval="/usr/local /opt/local /usr/lib /usr/pkg /usr/sfw /usr"
|
||||
fi
|
||||
for dir in $withval ; do
|
||||
if test -f "$dir/include/ngtcp2/ngtcp2.h"; then
|
||||
found_libngtcp2="yes"
|
||||
if test "$dir" != "/usr"; then
|
||||
CPPFLAGS="$CPPFLAGS -I$dir/include"
|
||||
LDFLAGS="$LDFLAGS -L$dir/lib"
|
||||
fi
|
||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: found in $dir" >&5
|
||||
printf "%s\n" "found in $dir" >&6; }
|
||||
|
||||
printf "%s\n" "#define HAVE_NGTCP2 1" >>confdefs.h
|
||||
|
||||
LIBS="$LIBS -lngtcp2"
|
||||
break;
|
||||
fi
|
||||
done
|
||||
if test x_$found_libngtcp2 != x_yes; then
|
||||
as_fn_error $? "Could not find libngtcp2, ngtcp2.h" "$LINENO" 5
|
||||
fi
|
||||
ac_fn_c_check_header_compile "$LINENO" "ngtcp2/ngtcp2.h" "ac_cv_header_ngtcp2_ngtcp2_h" "$ac_includes_default
|
||||
"
|
||||
if test "x$ac_cv_header_ngtcp2_ngtcp2_h" = xyes
|
||||
then :
|
||||
printf "%s\n" "#define HAVE_NGTCP2_NGTCP2_H 1" >>confdefs.h
|
||||
|
||||
fi
|
||||
ac_fn_c_check_header_compile "$LINENO" "ngtcp2/ngtcp2_crypto_openssl.h" "ac_cv_header_ngtcp2_ngtcp2_crypto_openssl_h" "$ac_includes_default
|
||||
"
|
||||
if test "x$ac_cv_header_ngtcp2_ngtcp2_crypto_openssl_h" = xyes
|
||||
then :
|
||||
printf "%s\n" "#define HAVE_NGTCP2_NGTCP2_CRYPTO_OPENSSL_H 1" >>confdefs.h
|
||||
|
||||
fi
|
||||
ac_fn_c_check_header_compile "$LINENO" "ngtcp2/ngtcp2_crypto_quictls.h" "ac_cv_header_ngtcp2_ngtcp2_crypto_quictls_h" "$ac_includes_default
|
||||
"
|
||||
if test "x$ac_cv_header_ngtcp2_ngtcp2_crypto_quictls_h" = xyes
|
||||
then :
|
||||
printf "%s\n" "#define HAVE_NGTCP2_NGTCP2_CRYPTO_QUICTLS_H 1" >>confdefs.h
|
||||
|
||||
fi
|
||||
|
||||
ac_fn_check_decl "$LINENO" "ngtcp2_conn_server_new" "ac_cv_have_decl_ngtcp2_conn_server_new" "$ac_includes_default
|
||||
#include <ngtcp2/ngtcp2.h>
|
||||
|
||||
" "$ac_c_undeclared_builtin_options" "CFLAGS"
|
||||
if test "x$ac_cv_have_decl_ngtcp2_conn_server_new" = xyes
|
||||
then :
|
||||
ac_have_decl=1
|
||||
else $as_nop
|
||||
ac_have_decl=0
|
||||
fi
|
||||
printf "%s\n" "#define HAVE_DECL_NGTCP2_CONN_SERVER_NEW $ac_have_decl" >>confdefs.h
|
||||
|
||||
ac_fn_check_decl "$LINENO" "ngtcp2_crypto_encrypt_cb" "ac_cv_have_decl_ngtcp2_crypto_encrypt_cb" "$ac_includes_default
|
||||
#include <ngtcp2/ngtcp2_crypto.h>
|
||||
|
||||
" "$ac_c_undeclared_builtin_options" "CFLAGS"
|
||||
if test "x$ac_cv_have_decl_ngtcp2_crypto_encrypt_cb" = xyes
|
||||
then :
|
||||
ac_have_decl=1
|
||||
else $as_nop
|
||||
ac_have_decl=0
|
||||
fi
|
||||
printf "%s\n" "#define HAVE_DECL_NGTCP2_CRYPTO_ENCRYPT_CB $ac_have_decl" >>confdefs.h
|
||||
|
||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ngtcp2_crypto_encrypt_cb in -lngtcp2_crypto_openssl" >&5
|
||||
printf %s "checking for ngtcp2_crypto_encrypt_cb in -lngtcp2_crypto_openssl... " >&6; }
|
||||
if test ${ac_cv_lib_ngtcp2_crypto_openssl_ngtcp2_crypto_encrypt_cb+y}
|
||||
then :
|
||||
printf %s "(cached) " >&6
|
||||
else $as_nop
|
||||
ac_check_lib_save_LIBS=$LIBS
|
||||
LIBS="-lngtcp2_crypto_openssl $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. */
|
||||
char ngtcp2_crypto_encrypt_cb ();
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
return ngtcp2_crypto_encrypt_cb ();
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
if ac_fn_c_try_link "$LINENO"
|
||||
then :
|
||||
ac_cv_lib_ngtcp2_crypto_openssl_ngtcp2_crypto_encrypt_cb=yes
|
||||
else $as_nop
|
||||
ac_cv_lib_ngtcp2_crypto_openssl_ngtcp2_crypto_encrypt_cb=no
|
||||
fi
|
||||
rm -f core conftest.err conftest.$ac_objext conftest.beam \
|
||||
conftest$ac_exeext conftest.$ac_ext
|
||||
LIBS=$ac_check_lib_save_LIBS
|
||||
fi
|
||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ngtcp2_crypto_openssl_ngtcp2_crypto_encrypt_cb" >&5
|
||||
printf "%s\n" "$ac_cv_lib_ngtcp2_crypto_openssl_ngtcp2_crypto_encrypt_cb" >&6; }
|
||||
if test "x$ac_cv_lib_ngtcp2_crypto_openssl_ngtcp2_crypto_encrypt_cb" = xyes
|
||||
then :
|
||||
LIBS="$LIBS -lngtcp2_crypto_openssl"
|
||||
fi
|
||||
|
||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ngtcp2_crypto_encrypt_cb in -lngtcp2_crypto_quictls" >&5
|
||||
printf %s "checking for ngtcp2_crypto_encrypt_cb in -lngtcp2_crypto_quictls... " >&6; }
|
||||
if test ${ac_cv_lib_ngtcp2_crypto_quictls_ngtcp2_crypto_encrypt_cb+y}
|
||||
then :
|
||||
printf %s "(cached) " >&6
|
||||
else $as_nop
|
||||
ac_check_lib_save_LIBS=$LIBS
|
||||
LIBS="-lngtcp2_crypto_quictls $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. */
|
||||
char ngtcp2_crypto_encrypt_cb ();
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
return ngtcp2_crypto_encrypt_cb ();
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
if ac_fn_c_try_link "$LINENO"
|
||||
then :
|
||||
ac_cv_lib_ngtcp2_crypto_quictls_ngtcp2_crypto_encrypt_cb=yes
|
||||
else $as_nop
|
||||
ac_cv_lib_ngtcp2_crypto_quictls_ngtcp2_crypto_encrypt_cb=no
|
||||
fi
|
||||
rm -f core conftest.err conftest.$ac_objext conftest.beam \
|
||||
conftest$ac_exeext conftest.$ac_ext
|
||||
LIBS=$ac_check_lib_save_LIBS
|
||||
fi
|
||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ngtcp2_crypto_quictls_ngtcp2_crypto_encrypt_cb" >&5
|
||||
printf "%s\n" "$ac_cv_lib_ngtcp2_crypto_quictls_ngtcp2_crypto_encrypt_cb" >&6; }
|
||||
if test "x$ac_cv_lib_ngtcp2_crypto_quictls_ngtcp2_crypto_encrypt_cb" = xyes
|
||||
then :
|
||||
LIBS="$LIBS -lngtcp2_crypto_quictls"
|
||||
fi
|
||||
|
||||
ac_fn_c_check_func "$LINENO" "ngtcp2_crypto_encrypt_cb" "ac_cv_func_ngtcp2_crypto_encrypt_cb"
|
||||
if test "x$ac_cv_func_ngtcp2_crypto_encrypt_cb" = xyes
|
||||
then :
|
||||
printf "%s\n" "#define HAVE_NGTCP2_CRYPTO_ENCRYPT_CB 1" >>confdefs.h
|
||||
|
||||
fi
|
||||
ac_fn_c_check_func "$LINENO" "ngtcp2_ccerr_default" "ac_cv_func_ngtcp2_ccerr_default"
|
||||
if test "x$ac_cv_func_ngtcp2_ccerr_default" = xyes
|
||||
then :
|
||||
printf "%s\n" "#define HAVE_NGTCP2_CCERR_DEFAULT 1" >>confdefs.h
|
||||
|
||||
fi
|
||||
ac_fn_c_check_func "$LINENO" "ngtcp2_conn_in_closing_period" "ac_cv_func_ngtcp2_conn_in_closing_period"
|
||||
if test "x$ac_cv_func_ngtcp2_conn_in_closing_period" = xyes
|
||||
then :
|
||||
printf "%s\n" "#define HAVE_NGTCP2_CONN_IN_CLOSING_PERIOD 1" >>confdefs.h
|
||||
|
||||
fi
|
||||
ac_fn_c_check_func "$LINENO" "ngtcp2_conn_in_draining_period" "ac_cv_func_ngtcp2_conn_in_draining_period"
|
||||
if test "x$ac_cv_func_ngtcp2_conn_in_draining_period" = xyes
|
||||
then :
|
||||
printf "%s\n" "#define HAVE_NGTCP2_CONN_IN_DRAINING_PERIOD 1" >>confdefs.h
|
||||
|
||||
fi
|
||||
ac_fn_c_check_func "$LINENO" "ngtcp2_conn_get_max_local_streams_uni" "ac_cv_func_ngtcp2_conn_get_max_local_streams_uni"
|
||||
if test "x$ac_cv_func_ngtcp2_conn_get_max_local_streams_uni" = xyes
|
||||
then :
|
||||
printf "%s\n" "#define HAVE_NGTCP2_CONN_GET_MAX_LOCAL_STREAMS_UNI 1" >>confdefs.h
|
||||
|
||||
fi
|
||||
ac_fn_c_check_func "$LINENO" "ngtcp2_crypto_quictls_from_ossl_encryption_level" "ac_cv_func_ngtcp2_crypto_quictls_from_ossl_encryption_level"
|
||||
if test "x$ac_cv_func_ngtcp2_crypto_quictls_from_ossl_encryption_level" = xyes
|
||||
then :
|
||||
printf "%s\n" "#define HAVE_NGTCP2_CRYPTO_QUICTLS_FROM_OSSL_ENCRYPTION_LEVEL 1" >>confdefs.h
|
||||
|
||||
fi
|
||||
ac_fn_c_check_func "$LINENO" "ngtcp2_crypto_quictls_configure_server_context" "ac_cv_func_ngtcp2_crypto_quictls_configure_server_context"
|
||||
if test "x$ac_cv_func_ngtcp2_crypto_quictls_configure_server_context" = xyes
|
||||
then :
|
||||
printf "%s\n" "#define HAVE_NGTCP2_CRYPTO_QUICTLS_CONFIGURE_SERVER_CONTEXT 1" >>confdefs.h
|
||||
|
||||
fi
|
||||
ac_fn_c_check_func "$LINENO" "ngtcp2_crypto_quictls_configure_client_context" "ac_cv_func_ngtcp2_crypto_quictls_configure_client_context"
|
||||
if test "x$ac_cv_func_ngtcp2_crypto_quictls_configure_client_context" = xyes
|
||||
then :
|
||||
printf "%s\n" "#define HAVE_NGTCP2_CRYPTO_QUICTLS_CONFIGURE_CLIENT_CONTEXT 1" >>confdefs.h
|
||||
|
||||
fi
|
||||
ac_fn_c_check_func "$LINENO" "ngtcp2_conn_get_num_scid" "ac_cv_func_ngtcp2_conn_get_num_scid"
|
||||
if test "x$ac_cv_func_ngtcp2_conn_get_num_scid" = xyes
|
||||
then :
|
||||
printf "%s\n" "#define HAVE_NGTCP2_CONN_GET_NUM_SCID 1" >>confdefs.h
|
||||
|
||||
fi
|
||||
ac_fn_c_check_func "$LINENO" "ngtcp2_conn_tls_early_data_rejected" "ac_cv_func_ngtcp2_conn_tls_early_data_rejected"
|
||||
if test "x$ac_cv_func_ngtcp2_conn_tls_early_data_rejected" = xyes
|
||||
then :
|
||||
printf "%s\n" "#define HAVE_NGTCP2_CONN_TLS_EARLY_DATA_REJECTED 1" >>confdefs.h
|
||||
|
||||
fi
|
||||
ac_fn_c_check_func "$LINENO" "ngtcp2_conn_encode_0rtt_transport_params" "ac_cv_func_ngtcp2_conn_encode_0rtt_transport_params"
|
||||
if test "x$ac_cv_func_ngtcp2_conn_encode_0rtt_transport_params" = xyes
|
||||
then :
|
||||
printf "%s\n" "#define HAVE_NGTCP2_CONN_ENCODE_0RTT_TRANSPORT_PARAMS 1" >>confdefs.h
|
||||
|
||||
fi
|
||||
|
||||
|
||||
for ac_func in SSL_is_quic
|
||||
do :
|
||||
ac_fn_c_check_func "$LINENO" "SSL_is_quic" "ac_cv_func_SSL_is_quic"
|
||||
if test "x$ac_cv_func_SSL_is_quic" = xyes
|
||||
then :
|
||||
printf "%s\n" "#define HAVE_SSL_IS_QUIC 1" >>confdefs.h
|
||||
|
||||
else $as_nop
|
||||
as_fn_error $? "No QUIC support detected in OpenSSL. Need OpenSSL version with QUIC support to enable DNS over QUIC with libngtcp2." "$LINENO" 5
|
||||
fi
|
||||
|
||||
done
|
||||
ac_fn_c_check_type "$LINENO" "struct ngtcp2_version_cid" "ac_cv_type_struct_ngtcp2_version_cid" "$ac_includes_default
|
||||
#include <ngtcp2/ngtcp2.h>
|
||||
|
||||
"
|
||||
if test "x$ac_cv_type_struct_ngtcp2_version_cid" = xyes
|
||||
then :
|
||||
|
||||
printf "%s\n" "#define HAVE_STRUCT_NGTCP2_VERSION_CID 1" >>confdefs.h
|
||||
|
||||
|
||||
fi
|
||||
ac_fn_c_check_type "$LINENO" "ngtcp2_encryption_level" "ac_cv_type_ngtcp2_encryption_level" "$ac_includes_default
|
||||
#include <ngtcp2/ngtcp2.h>
|
||||
|
||||
"
|
||||
if test "x$ac_cv_type_ngtcp2_encryption_level" = xyes
|
||||
then :
|
||||
|
||||
printf "%s\n" "#define HAVE_NGTCP2_ENCRYPTION_LEVEL 1" >>confdefs.h
|
||||
|
||||
|
||||
fi
|
||||
|
||||
ac_fn_c_check_member "$LINENO" "struct ngtcp2_pkt_hd" "tokenlen" "ac_cv_member_struct_ngtcp2_pkt_hd_tokenlen" "$ac_includes_default
|
||||
#include <ngtcp2/ngtcp2.h>
|
||||
|
||||
"
|
||||
if test "x$ac_cv_member_struct_ngtcp2_pkt_hd_tokenlen" = xyes
|
||||
then :
|
||||
|
||||
printf "%s\n" "#define HAVE_STRUCT_NGTCP2_PKT_HD_TOKENLEN 1" >>confdefs.h
|
||||
|
||||
|
||||
fi
|
||||
ac_fn_c_check_member "$LINENO" "struct ngtcp2_settings" "tokenlen" "ac_cv_member_struct_ngtcp2_settings_tokenlen" "$ac_includes_default
|
||||
#include <ngtcp2/ngtcp2.h>
|
||||
|
||||
"
|
||||
if test "x$ac_cv_member_struct_ngtcp2_settings_tokenlen" = xyes
|
||||
then :
|
||||
|
||||
printf "%s\n" "#define HAVE_STRUCT_NGTCP2_SETTINGS_TOKENLEN 1" >>confdefs.h
|
||||
|
||||
|
||||
fi
|
||||
ac_fn_c_check_member "$LINENO" "struct ngtcp2_settings" "max_tx_udp_payload_size" "ac_cv_member_struct_ngtcp2_settings_max_tx_udp_payload_size" "$ac_includes_default
|
||||
#include <ngtcp2/ngtcp2.h>
|
||||
|
||||
"
|
||||
if test "x$ac_cv_member_struct_ngtcp2_settings_max_tx_udp_payload_size" = xyes
|
||||
then :
|
||||
|
||||
printf "%s\n" "#define HAVE_STRUCT_NGTCP2_SETTINGS_MAX_TX_UDP_PAYLOAD_SIZE 1" >>confdefs.h
|
||||
|
||||
|
||||
fi
|
||||
ac_fn_c_check_member "$LINENO" "struct ngtcp2_transport_params" "original_dcid_present" "ac_cv_member_struct_ngtcp2_transport_params_original_dcid_present" "$ac_includes_default
|
||||
#include <ngtcp2/ngtcp2.h>
|
||||
|
||||
"
|
||||
if test "x$ac_cv_member_struct_ngtcp2_transport_params_original_dcid_present" = xyes
|
||||
then :
|
||||
|
||||
printf "%s\n" "#define HAVE_STRUCT_NGTCP2_TRANSPORT_PARAMS_ORIGINAL_DCID_PRESENT 1" >>confdefs.h
|
||||
|
||||
|
||||
fi
|
||||
|
||||
|
||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether ngtcp2_conn_shutdown_stream has 4 arguments" >&5
|
||||
printf %s "checking whether ngtcp2_conn_shutdown_stream has 4 arguments... " >&6; }
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
$ac_includes_default
|
||||
#include <ngtcp2/ngtcp2.h>
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
|
||||
(void)ngtcp2_conn_shutdown_stream(NULL, 0, 0, 0);
|
||||
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
if ac_fn_c_try_compile "$LINENO"
|
||||
then :
|
||||
|
||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
|
||||
printf "%s\n" "yes" >&6; }
|
||||
|
||||
printf "%s\n" "#define HAVE_NGTCP2_CONN_SHUTDOWN_STREAM4 1" >>confdefs.h
|
||||
|
||||
|
||||
else $as_nop
|
||||
|
||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
printf "%s\n" "no" >&6; }
|
||||
|
||||
fi
|
||||
rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
|
||||
|
||||
fi
|
||||
|
||||
# set static linking for uninstalled libraries if requested
|
||||
|
||||
staticexe=""
|
||||
@@ -23068,6 +23530,48 @@ if echo $host_os | grep darwin8 > /dev/null; then
|
||||
printf "%s\n" "#define DARWIN_BROKEN_SETREUID 1" >>confdefs.h
|
||||
|
||||
fi
|
||||
|
||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for atomic_store" >&5
|
||||
printf %s "checking for atomic_store... " >&6; }
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
$ac_includes_default
|
||||
#ifdef HAVE_STDATOMIC_H
|
||||
#include <stdatomic.h>
|
||||
#endif
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
|
||||
int newvar = 5, var = 0;
|
||||
atomic_store((_Atomic int*)&var, newvar);
|
||||
newvar = 0;
|
||||
/* condition to use the variables. */
|
||||
if(var == newvar) return 1;
|
||||
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
if ac_fn_c_try_link "$LINENO"
|
||||
then :
|
||||
|
||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
|
||||
printf "%s\n" "yes" >&6; }
|
||||
|
||||
printf "%s\n" "#define HAVE_LINK_ATOMIC_STORE 1" >>confdefs.h
|
||||
|
||||
|
||||
else $as_nop
|
||||
|
||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
printf "%s\n" "no" >&6; }
|
||||
|
||||
fi
|
||||
rm -f core conftest.err conftest.$ac_objext conftest.beam \
|
||||
conftest$ac_exeext conftest.$ac_ext
|
||||
|
||||
ac_fn_check_decl "$LINENO" "inet_pton" "ac_cv_have_decl_inet_pton" "
|
||||
$ac_includes_default
|
||||
#ifdef HAVE_NETINET_IN_H
|
||||
@@ -23709,10 +24213,12 @@ if test x_$enable_lock_checks = x_yes; then
|
||||
UBSYMS="-export-symbols clubsyms.def"
|
||||
cp ${srcdir}/libunbound/ubsyms.def clubsyms.def
|
||||
echo lock_protect >> clubsyms.def
|
||||
echo lock_protect_place >> clubsyms.def
|
||||
echo lock_unprotect >> clubsyms.def
|
||||
echo lock_get_mem >> clubsyms.def
|
||||
echo checklock_start >> clubsyms.def
|
||||
echo checklock_stop >> clubsyms.def
|
||||
echo checklock_set_output_name >> clubsyms.def
|
||||
echo checklock_lock >> clubsyms.def
|
||||
echo checklock_unlock >> clubsyms.def
|
||||
echo checklock_init >> clubsyms.def
|
||||
@@ -24567,9 +25073,27 @@ printf "%s\n" "#define MAXSYSLOGMSGLEN 10240" >>confdefs.h
|
||||
|
||||
|
||||
|
||||
version=1.20.1
|
||||
version=1.23.0
|
||||
|
||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for build time" >&5
|
||||
printf %s "checking for build time... " >&6; }
|
||||
ax_date_fmt="%b %e, %Y"
|
||||
if test x"$SOURCE_DATE_EPOCH" = x
|
||||
then :
|
||||
date=`date "+$ax_date_fmt"`
|
||||
else $as_nop
|
||||
ax_build_date=`date -u -d "@$SOURCE_DATE_EPOCH" "+$ax_date_fmt" 2>/dev/null \
|
||||
|| date -u -r "$SOURCE_DATE_EPOCH" "+$ax_date_fmt" 2>/dev/null`
|
||||
if test x"$ax_build_date" = x
|
||||
then :
|
||||
as_fn_error $? "malformed SOURCE_DATE_EPOCH" "$LINENO" 5
|
||||
else $as_nop
|
||||
date=$ax_build_date
|
||||
fi
|
||||
fi
|
||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $date" >&5
|
||||
printf "%s\n" "$date" >&6; }
|
||||
|
||||
date=`date +'%b %e, %Y'`
|
||||
|
||||
|
||||
ac_config_files="$ac_config_files Makefile doc/example.conf doc/libunbound.3 doc/unbound.8 doc/unbound-anchor.8 doc/unbound-checkconf.8 doc/unbound.conf.5 doc/unbound-control.8 doc/unbound-host.1 smallapp/unbound-control-setup.sh dnstap/dnstap_config.h dnscrypt/dnscrypt_config.h contrib/libunbound.pc contrib/unbound.socket contrib/unbound.service contrib/unbound_portable.service"
|
||||
@@ -25079,7 +25603,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.20.1, which was
|
||||
This file was extended by unbound $as_me 1.23.0, which was
|
||||
generated by GNU Autoconf 2.71. Invocation command line was
|
||||
|
||||
CONFIG_FILES = $CONFIG_FILES
|
||||
@@ -25147,7 +25671,7 @@ ac_cs_config_escaped=`printf "%s\n" "$ac_cs_config" | sed "s/^ //; s/'/'\\\\\\\\
|
||||
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
|
||||
ac_cs_config='$ac_cs_config_escaped'
|
||||
ac_cs_version="\\
|
||||
unbound config.status 1.20.1
|
||||
unbound config.status 1.23.0
|
||||
configured by $0, generated by GNU Autoconf 2.71,
|
||||
with options \\"\$ac_cs_config\\"
|
||||
|
||||
|
||||
+147
-6
@@ -2,6 +2,7 @@
|
||||
# Process this file with autoconf to produce a configure script.
|
||||
AC_PREREQ([2.56])
|
||||
sinclude(acx_nlnetlabs.m4)
|
||||
sinclude(ax_build_date_epoch.m4)
|
||||
sinclude(ax_pthread.m4)
|
||||
sinclude(acx_python.m4)
|
||||
sinclude(ax_pkg_swig.m4)
|
||||
@@ -10,15 +11,15 @@ sinclude(dnscrypt/dnscrypt.m4)
|
||||
|
||||
# must be numbers. ac_defun because of later processing
|
||||
m4_define([VERSION_MAJOR],[1])
|
||||
m4_define([VERSION_MINOR],[20])
|
||||
m4_define([VERSION_MICRO],[1])
|
||||
m4_define([VERSION_MINOR],[23])
|
||||
m4_define([VERSION_MICRO],[0])
|
||||
AC_INIT([unbound],m4_defn([VERSION_MAJOR]).m4_defn([VERSION_MINOR]).m4_defn([VERSION_MICRO]),[unbound-bugs@nlnetlabs.nl or https://github.com/NLnetLabs/unbound/issues],[unbound])
|
||||
AC_SUBST(UNBOUND_VERSION_MAJOR, [VERSION_MAJOR])
|
||||
AC_SUBST(UNBOUND_VERSION_MINOR, [VERSION_MINOR])
|
||||
AC_SUBST(UNBOUND_VERSION_MICRO, [VERSION_MICRO])
|
||||
|
||||
LIBUNBOUND_CURRENT=9
|
||||
LIBUNBOUND_REVISION=28
|
||||
LIBUNBOUND_REVISION=31
|
||||
LIBUNBOUND_AGE=1
|
||||
# 1.0.0 had 0:12:0
|
||||
# 1.0.1 had 0:13:0
|
||||
@@ -113,7 +114,10 @@ LIBUNBOUND_AGE=1
|
||||
# 1.19.2 had 9:25:1
|
||||
# 1.19.3 had 9:26:1
|
||||
# 1.20.0 had 9:27:1
|
||||
# 1.20.1 had 9:28:1
|
||||
# 1.21.0 had 9:28:1
|
||||
# 1.21.1 had 9:29:1
|
||||
# 1.22.0 had 9:30:1
|
||||
# 1.23.0 had 9:31:1
|
||||
|
||||
# Current -- the number of the binary API that we're implementing
|
||||
# Revision -- which iteration of the implementation of the binary
|
||||
@@ -339,6 +343,8 @@ AC_MSG_RESULT($ac_cv_c_weak_attribute)
|
||||
if test $ac_cv_c_weak_attribute = yes; then
|
||||
AC_DEFINE(HAVE_ATTR_WEAK, 1, [Whether the C compiler accepts the "weak" attribute])
|
||||
AC_DEFINE(ATTR_WEAK, [__attribute__((weak))], [apply the weak attribute to a symbol])
|
||||
else
|
||||
AC_DEFINE(ATTR_WEAK,[], [apply the weak attribute to a symbol])
|
||||
fi
|
||||
])dnl End of CHECK_WEAK_ATTRIBUTE
|
||||
|
||||
@@ -360,11 +366,54 @@ AC_MSG_RESULT($ac_cv_c_noreturn_attribute)
|
||||
if test $ac_cv_c_noreturn_attribute = yes; then
|
||||
AC_DEFINE(HAVE_ATTR_NORETURN, 1, [Whether the C compiler accepts the "noreturn" attribute])
|
||||
AC_DEFINE(ATTR_NORETURN, [__attribute__((__noreturn__))], [apply the noreturn attribute to a function that exits the program])
|
||||
else
|
||||
AC_DEFINE(ATTR_NORETURN,[], [apply the noreturn attribute to a function that exits the program])
|
||||
fi
|
||||
])dnl End of CHECK_NORETURN_ATTRIBUTE
|
||||
|
||||
CHECK_NORETURN_ATTRIBUTE
|
||||
|
||||
AC_DEFUN([CHECK_FALLTHROUGH_ATTRIBUTE],
|
||||
[AC_REQUIRE([AC_PROG_CC])
|
||||
AC_MSG_CHECKING(whether the C compiler (${CC-cc}) accepts the "fallthrough" attribute)
|
||||
BAKCFLAGS="$CFLAGS"
|
||||
CFLAGS="$CFLAGS -Werror"
|
||||
AC_CACHE_VAL(ac_cv_c_fallthrough_attribute,
|
||||
[ac_cv_c_fallthrough_attribute=no
|
||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include <stdio.h>
|
||||
void f(int x) {
|
||||
int y = 0;
|
||||
switch(x) {
|
||||
case 1:
|
||||
y = 1;
|
||||
__attribute__((fallthrough));
|
||||
/* fallthrough */
|
||||
case 2:
|
||||
y++;
|
||||
break;
|
||||
case 3:
|
||||
y = 3;
|
||||
break;
|
||||
}
|
||||
printf("%d", y);
|
||||
}
|
||||
]], [[
|
||||
f(1);
|
||||
]])],[ac_cv_c_fallthrough_attribute="yes"],[ac_cv_c_fallthrough_attribute="no"])
|
||||
])
|
||||
CFLAGS="$BAKCFLAGS"
|
||||
|
||||
AC_MSG_RESULT($ac_cv_c_fallthrough_attribute)
|
||||
if test $ac_cv_c_fallthrough_attribute = yes; then
|
||||
AC_DEFINE(HAVE_ATTR_FALLTHROUGH, 1, [Whether the C compiler accepts the "fallthrough" attribute])
|
||||
AC_DEFINE(ATTR_FALLTHROUGH, [__attribute__((fallthrough));], [apply the fallthrough attribute.])
|
||||
else
|
||||
AC_DEFINE(ATTR_FALLTHROUGH,[], [apply the fallthrough attribute.])
|
||||
fi
|
||||
])dnl End of CHECK_FALLTHROUGH_ATTRIBUTE
|
||||
|
||||
CHECK_FALLTHROUGH_ATTRIBUTE
|
||||
|
||||
if test "$srcdir" != "."; then
|
||||
CPPFLAGS="$CPPFLAGS -I$srcdir"
|
||||
fi
|
||||
@@ -475,6 +524,7 @@ AC_CHECK_HEADERS([netioapi.h],,, [AC_INCLUDES_DEFAULT
|
||||
|
||||
# Check for Linux timestamping headers
|
||||
AC_CHECK_HEADERS([linux/net_tstamp.h],,, [AC_INCLUDES_DEFAULT])
|
||||
AC_CHECK_HEADERS([stdatomic.h],,, [AC_INCLUDES_DEFAULT])
|
||||
|
||||
# check for types.
|
||||
# Using own tests for int64* because autoconf builtin only give 32bit.
|
||||
@@ -860,7 +910,8 @@ if test "`uname`" = "Linux"; then
|
||||
GCC_DOCKER_LINTFLAGS='-syntax'
|
||||
AC_SUBST(GCC_DOCKER_LINTFLAGS)
|
||||
fi
|
||||
CONFIG_DATE=`date +%Y%m%d`
|
||||
AX_BUILD_DATE_EPOCH(CONFIG_DATE, [%Y%m%d])
|
||||
AC_ARG_VAR(SOURCE_DATE_EPOCH, [If it is set, it uses the value of that variable instead of the current time as the build timestamp. The format is a unix timestamp. This enables reproducible build output.])
|
||||
AC_SUBST(CONFIG_DATE)
|
||||
|
||||
# Checks for libraries.
|
||||
@@ -1532,6 +1583,64 @@ if test x_$withval = x_yes -o x_$withval != x_no; then
|
||||
])
|
||||
fi
|
||||
|
||||
# ngtcp2
|
||||
AC_ARG_WITH(libngtcp2, AS_HELP_STRING([--with-libngtcp2=path],[specify explicit path for libngtcp2, for QUIC.]),
|
||||
[ ],[ withval="no" ])
|
||||
found_libngtcp2="no"
|
||||
if test x_$withval = x_yes -o x_$withval != x_no; then
|
||||
AC_MSG_CHECKING(for libngtcp2)
|
||||
if test x_$withval = x_ -o x_$withval = x_yes; then
|
||||
withval="/usr/local /opt/local /usr/lib /usr/pkg /usr/sfw /usr"
|
||||
fi
|
||||
for dir in $withval ; do
|
||||
if test -f "$dir/include/ngtcp2/ngtcp2.h"; then
|
||||
found_libngtcp2="yes"
|
||||
dnl assume /usr is in default path.
|
||||
if test "$dir" != "/usr"; then
|
||||
CPPFLAGS="$CPPFLAGS -I$dir/include"
|
||||
LDFLAGS="$LDFLAGS -L$dir/lib"
|
||||
fi
|
||||
AC_MSG_RESULT(found in $dir)
|
||||
AC_DEFINE([HAVE_NGTCP2], [1], [Define this to use ngtcp2.])
|
||||
LIBS="$LIBS -lngtcp2"
|
||||
break;
|
||||
fi
|
||||
done
|
||||
if test x_$found_libngtcp2 != x_yes; then
|
||||
AC_MSG_ERROR([Could not find libngtcp2, ngtcp2.h])
|
||||
fi
|
||||
AC_CHECK_HEADERS([ngtcp2/ngtcp2.h ngtcp2/ngtcp2_crypto_openssl.h ngtcp2/ngtcp2_crypto_quictls.h],,, [AC_INCLUDES_DEFAULT])
|
||||
AC_CHECK_DECLS([ngtcp2_conn_server_new], [], [], [AC_INCLUDES_DEFAULT
|
||||
#include <ngtcp2/ngtcp2.h>
|
||||
])
|
||||
AC_CHECK_DECLS([ngtcp2_crypto_encrypt_cb], [], [], [AC_INCLUDES_DEFAULT
|
||||
#include <ngtcp2/ngtcp2_crypto.h>
|
||||
])
|
||||
AC_CHECK_LIB([ngtcp2_crypto_openssl], [ngtcp2_crypto_encrypt_cb], [ LIBS="$LIBS -lngtcp2_crypto_openssl" ])
|
||||
AC_CHECK_LIB([ngtcp2_crypto_quictls], [ngtcp2_crypto_encrypt_cb], [ LIBS="$LIBS -lngtcp2_crypto_quictls" ])
|
||||
AC_CHECK_FUNCS([ngtcp2_crypto_encrypt_cb ngtcp2_ccerr_default ngtcp2_conn_in_closing_period ngtcp2_conn_in_draining_period ngtcp2_conn_get_max_local_streams_uni ngtcp2_crypto_quictls_from_ossl_encryption_level ngtcp2_crypto_quictls_configure_server_context ngtcp2_crypto_quictls_configure_client_context ngtcp2_conn_get_num_scid ngtcp2_conn_tls_early_data_rejected ngtcp2_conn_encode_0rtt_transport_params])
|
||||
AC_CHECK_FUNCS([SSL_is_quic], [], [AC_MSG_ERROR([No QUIC support detected in OpenSSL. Need OpenSSL version with QUIC support to enable DNS over QUIC with libngtcp2.])])
|
||||
AC_CHECK_TYPES([struct ngtcp2_version_cid, ngtcp2_encryption_level],,,[AC_INCLUDES_DEFAULT
|
||||
#include <ngtcp2/ngtcp2.h>
|
||||
])
|
||||
AC_CHECK_MEMBERS([struct ngtcp2_pkt_hd.tokenlen, struct ngtcp2_settings.tokenlen, struct ngtcp2_settings.max_tx_udp_payload_size, struct ngtcp2_transport_params.original_dcid_present],,,[AC_INCLUDES_DEFAULT
|
||||
#include <ngtcp2/ngtcp2.h>
|
||||
])
|
||||
|
||||
AC_MSG_CHECKING([whether ngtcp2_conn_shutdown_stream has 4 arguments])
|
||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([AC_INCLUDES_DEFAULT
|
||||
#include <ngtcp2/ngtcp2.h>
|
||||
],[
|
||||
(void)ngtcp2_conn_shutdown_stream(NULL, 0, 0, 0);
|
||||
])],[
|
||||
AC_MSG_RESULT(yes)
|
||||
AC_DEFINE(HAVE_NGTCP2_CONN_SHUTDOWN_STREAM4, 1, [Define if ngtcp2_conn_shutdown_stream has 4 arguments.])
|
||||
],[
|
||||
AC_MSG_RESULT(no)
|
||||
])
|
||||
|
||||
fi
|
||||
|
||||
# set static linking for uninstalled libraries if requested
|
||||
AC_SUBST(staticexe)
|
||||
staticexe=""
|
||||
@@ -1709,6 +1818,25 @@ AC_CHECK_FUNCS([setresgid],,[AC_CHECK_FUNCS([setregid])])
|
||||
if echo $host_os | grep darwin8 > /dev/null; then
|
||||
AC_DEFINE(DARWIN_BROKEN_SETREUID, 1, [Define this if on macOSX10.4-darwin8 and setreuid and setregid do not work])
|
||||
fi
|
||||
|
||||
AC_MSG_CHECKING([for atomic_store])
|
||||
AC_LINK_IFELSE([AC_LANG_PROGRAM(AC_INCLUDES_DEFAULT [[
|
||||
#ifdef HAVE_STDATOMIC_H
|
||||
#include <stdatomic.h>
|
||||
#endif
|
||||
]], [[
|
||||
int newvar = 5, var = 0;
|
||||
atomic_store((_Atomic int*)&var, newvar);
|
||||
newvar = 0;
|
||||
/* condition to use the variables. */
|
||||
if(var == newvar) return 1;
|
||||
]])], [
|
||||
AC_MSG_RESULT(yes)
|
||||
AC_DEFINE(HAVE_LINK_ATOMIC_STORE, 1, [If we have atomic_store])
|
||||
], [
|
||||
AC_MSG_RESULT([no])
|
||||
])
|
||||
|
||||
AC_CHECK_DECLS([inet_pton,inet_ntop], [], [], [
|
||||
AC_INCLUDES_DEFAULT
|
||||
#ifdef HAVE_NETINET_IN_H
|
||||
@@ -1847,10 +1975,12 @@ if test x_$enable_lock_checks = x_yes; then
|
||||
UBSYMS="-export-symbols clubsyms.def"
|
||||
cp ${srcdir}/libunbound/ubsyms.def clubsyms.def
|
||||
echo lock_protect >> clubsyms.def
|
||||
echo lock_protect_place >> clubsyms.def
|
||||
echo lock_unprotect >> clubsyms.def
|
||||
echo lock_get_mem >> clubsyms.def
|
||||
echo checklock_start >> clubsyms.def
|
||||
echo checklock_stop >> clubsyms.def
|
||||
echo checklock_set_output_name >> clubsyms.def
|
||||
echo checklock_lock >> clubsyms.def
|
||||
echo checklock_unlock >> clubsyms.def
|
||||
echo checklock_init >> clubsyms.def
|
||||
@@ -2284,6 +2414,10 @@ struct sockaddr_storage;
|
||||
# define calloc(n,s) unbound_stat_calloc_log(n, s, __FILE__, __LINE__, __func__)
|
||||
# define free(p) unbound_stat_free_log(p, __FILE__, __LINE__, __func__)
|
||||
# define realloc(p,s) unbound_stat_realloc_log(p, s, __FILE__, __LINE__, __func__)
|
||||
# define strdup(s) unbound_stat_strdup_log(s, __FILE__, __LINE__, __func__)
|
||||
#ifdef HAVE_REALLOCARRAY
|
||||
# define reallocarray(p,n,s) unbound_stat_reallocarray_log(p, n, s, __FILE__, __LINE__, __func__)
|
||||
#endif
|
||||
void *unbound_stat_malloc(size_t size);
|
||||
void *unbound_stat_calloc(size_t nmemb, size_t size);
|
||||
void unbound_stat_free(void *ptr);
|
||||
@@ -2296,6 +2430,10 @@ void unbound_stat_free_log(void *ptr, const char* file, int line,
|
||||
const char* func);
|
||||
void *unbound_stat_realloc_log(void *ptr, size_t size, const char* file,
|
||||
int line, const char* func);
|
||||
void *unbound_stat_reallocarray_log(void *ptr, size_t nmemb, size_t size,
|
||||
const char* file, int line, const char* func);
|
||||
char *unbound_stat_strdup_log(const char *s, const char* file, int line,
|
||||
const char* func);
|
||||
#elif defined(UNBOUND_ALLOC_LITE)
|
||||
# include "util/alloc.h"
|
||||
#endif /* UNBOUND_ALLOC_LITE and UNBOUND_ALLOC_STATS */
|
||||
@@ -2306,6 +2444,8 @@ void *unbound_stat_realloc_log(void *ptr, size_t size, const char* file,
|
||||
#define UNBOUND_DNS_OVER_TLS_PORT 853
|
||||
/** default port for DNS over HTTPS traffic. */
|
||||
#define UNBOUND_DNS_OVER_HTTPS_PORT 443
|
||||
/** default port for DNS over QUIC traffic. */
|
||||
#define UNBOUND_DNS_OVER_QUIC_PORT 853
|
||||
/** default port for unbound control traffic, registered port with IANA,
|
||||
ub-dns-control 8953/tcp unbound dns nameserver control */
|
||||
#define UNBOUND_CONTROL_PORT 8953
|
||||
@@ -2317,7 +2457,8 @@ void *unbound_stat_realloc_log(void *ptr, size_t size, const char* file,
|
||||
dnl if we build from source tree, the man pages need @date@ and @version@
|
||||
dnl if this is a distro tarball, that was already done by makedist.sh
|
||||
AC_SUBST(version, [VERSION_MAJOR.VERSION_MINOR.VERSION_MICRO])
|
||||
AC_SUBST(date, [`date +'%b %e, %Y'`])
|
||||
AX_BUILD_DATE_EPOCH(date, [[%b %e, %Y]])
|
||||
AC_SUBST(date)
|
||||
|
||||
AC_CONFIG_FILES([Makefile doc/example.conf doc/libunbound.3 doc/unbound.8 doc/unbound-anchor.8 doc/unbound-checkconf.8 doc/unbound.conf.5 doc/unbound-control.8 doc/unbound-host.1 smallapp/unbound-control-setup.sh dnstap/dnstap_config.h dnscrypt/dnscrypt_config.h contrib/libunbound.pc contrib/unbound.socket contrib/unbound.service contrib/unbound_portable.service])
|
||||
AC_CONFIG_HEADERS([config.h])
|
||||
|
||||
@@ -236,7 +236,7 @@ index 54006940..768fe202 100644
|
||||
+ /* see if the failure did get (parent-lame) info */
|
||||
+ if(!cache_fill_missing(super->env,
|
||||
+ super_iq->qchase.qclass, super->region,
|
||||
+ super_iq->dp))
|
||||
+ super_iq->dp, 0))
|
||||
+ log_err("ASN-AAAA-filter: out of memory adding missing");
|
||||
+ dpns->resolved = 1; /* mark as failed */
|
||||
+ }
|
||||
|
||||
@@ -1,21 +1,24 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
LIBEXPAT_FNAME=expat-2.7.0
|
||||
LIBEXPAT_VERSION_DIR=R_2_7_0
|
||||
|
||||
echo "Downloading Expat"
|
||||
if ! curl -L -k -s -o expat-2.2.9.tar.gz https://github.com/libexpat/libexpat/releases/download/R_2_2_9/expat-2.2.9.tar.gz;
|
||||
if ! curl -L -k -s -o $LIBEXPAT_FNAME.tar.gz https://github.com/libexpat/libexpat/releases/download/$LIBEXPAT_VERSION_DIR/$LIBEXPAT_FNAME.tar.gz;
|
||||
then
|
||||
echo "Failed to download Expat"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Unpacking Expat"
|
||||
rm -rf ./expat-2.2.9
|
||||
if ! tar -xf expat-2.2.9.tar.gz;
|
||||
rm -rf ./$LIBEXPAT_FNAME
|
||||
if ! tar -xf $LIBEXPAT_FNAME.tar.gz;
|
||||
then
|
||||
echo "Failed to unpack Expat"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
cd expat-2.2.9 || exit 1
|
||||
cd $LIBEXPAT_FNAME || exit 1
|
||||
|
||||
echo "Configuring Expat"
|
||||
if ! ./configure --build="$AUTOTOOLS_BUILD" --host="$AUTOTOOLS_HOST" --prefix="$ANDROID_PREFIX"; then
|
||||
|
||||
@@ -1,28 +1,32 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
LIBEXPAT_FNAME=expat-2.7.0
|
||||
LIBEXPAT_VERSION_DIR=R_2_7_0
|
||||
|
||||
echo "Downloading Expat"
|
||||
if ! curl -L -k -s -o expat-2.2.9.tar.gz https://github.com/libexpat/libexpat/releases/download/R_2_2_9/expat-2.2.9.tar.gz;
|
||||
if ! curl -L -k -s -o $LIBEXPAT_FNAME.tar.gz https://github.com/libexpat/libexpat/releases/download/$LIBEXPAT_VERSION_DIR/$LIBEXPAT_FNAME.tar.gz;
|
||||
then
|
||||
echo "Failed to download Expat"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Unpacking Expat"
|
||||
rm -rf ./expat-2.2.9
|
||||
if ! tar -xf expat-2.2.9.tar.gz;
|
||||
rm -rf ./$LIBEXPAT_FNAME
|
||||
if ! tar -xf $LIBEXPAT_FNAME.tar.gz;
|
||||
then
|
||||
echo "Failed to unpack Expat"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
cd expat-2.2.9 || exit 1
|
||||
cd $LIBEXPAT_FNAME || exit 1
|
||||
|
||||
export PKG_CONFIG_PATH="$IOS_PREFIX/lib/pkgconfig"
|
||||
|
||||
echo "Configuring Expat"
|
||||
if ! ./configure \
|
||||
--build="$AUTOTOOLS_BUILD" --host="$AUTOTOOLS_HOST" \
|
||||
--prefix="$IOS_PREFIX" ; then
|
||||
if ! ./configure --without-tests \
|
||||
--build="$AUTOTOOLS_BUILD" --host="$AUTOTOOLS_HOST" \
|
||||
--prefix="$IOS_PREFIX" ;
|
||||
then
|
||||
echo "Error: Failed to configure Expat"
|
||||
cat config.log
|
||||
exit 1
|
||||
|
||||
+17
-13
@@ -221,7 +221,9 @@ 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);
|
||||
struct acl_addr* node = acl_find_or_create(acl_interface, addr, addrlen, control);
|
||||
node->is_interface = 1;
|
||||
return node;
|
||||
}
|
||||
|
||||
/** apply acl_tag string */
|
||||
@@ -551,17 +553,6 @@ acl_list_apply_cfg(struct acl_list* acl, struct config_file* cfg,
|
||||
return 1;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
@@ -816,10 +807,23 @@ log_acl_action(const char* action, struct sockaddr_storage* addr,
|
||||
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,
|
||||
"%s/%d %s%s", action, a, (int)port, n,
|
||||
acladdr->node.net,
|
||||
acladdr->is_interface?"(ACL on interface IP) ":"",
|
||||
acl_access_to_str(acl));
|
||||
} else {
|
||||
verbose(VERB_ALGO, "%s query from %s port %d", action, a,
|
||||
(int)port);
|
||||
}
|
||||
}
|
||||
|
||||
void acl_list_swap_tree(struct acl_list* acl, struct acl_list* data)
|
||||
{
|
||||
/* swap tree and region */
|
||||
rbtree_type oldtree = acl->tree;
|
||||
struct regional* oldregion = acl->region;
|
||||
acl->tree = data->tree;
|
||||
acl->region = data->region;
|
||||
data->tree = oldtree;
|
||||
data->region = oldregion;
|
||||
}
|
||||
|
||||
+10
-3
@@ -107,6 +107,8 @@ struct acl_addr {
|
||||
struct config_strlist** tag_datas;
|
||||
/** size of the tag_datas array */
|
||||
size_t tag_datas_size;
|
||||
/* If the acl node is for an interface */
|
||||
int is_interface;
|
||||
/* view element, NULL if none */
|
||||
struct view* view;
|
||||
};
|
||||
@@ -147,9 +149,6 @@ acl_interface_insert(struct acl_list* acl_interface,
|
||||
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.
|
||||
@@ -202,4 +201,12 @@ const char* acl_access_to_str(enum acl_access acl);
|
||||
void log_acl_action(const char* action, struct sockaddr_storage* addr,
|
||||
socklen_t addrlen, enum acl_access acl, struct acl_addr* acladdr);
|
||||
|
||||
/**
|
||||
* Swap internal tree with preallocated entries.
|
||||
* @param acl: the acl structure.
|
||||
* @param data: the data structure used to take elements from. This contains
|
||||
* the old elements on return.
|
||||
*/
|
||||
void acl_list_swap_tree(struct acl_list* acl, struct acl_list* data);
|
||||
|
||||
#endif /* DAEMON_ACL_LIST_H */
|
||||
|
||||
+2
-2
@@ -692,7 +692,7 @@ load_msg(RES* ssl, sldns_buffer* buf, struct worker* worker)
|
||||
return 1; /* skip this one, not all references satisfied */
|
||||
|
||||
if(!dns_cache_store(&worker->env, &qinf, &rep, 0, 0, 0, NULL, flags,
|
||||
*worker->env.now)) {
|
||||
*worker->env.now, 1)) {
|
||||
log_warn("error out of memory");
|
||||
return 0;
|
||||
}
|
||||
@@ -836,7 +836,7 @@ int print_deleg_lookup(RES* ssl, struct worker* worker, uint8_t* nm,
|
||||
struct delegpt* dp;
|
||||
struct dns_msg* msg;
|
||||
struct regional* region = worker->scratchpad;
|
||||
char b[260];
|
||||
char b[LDNS_MAX_DOMAINLEN];
|
||||
struct query_info qinfo;
|
||||
struct iter_hints_stub* stub;
|
||||
int nolock = 0;
|
||||
|
||||
+44
-17
@@ -323,8 +323,7 @@ daemon_init(void)
|
||||
return daemon;
|
||||
}
|
||||
|
||||
static int setup_acl_for_ports(struct acl_list* list,
|
||||
struct listen_port* port_list)
|
||||
int setup_acl_for_ports(struct acl_list* list, struct listen_port* port_list)
|
||||
{
|
||||
struct acl_addr* acl_node;
|
||||
for(; port_list; port_list=port_list->next) {
|
||||
@@ -557,6 +556,12 @@ daemon_create_workers(struct daemon* daemon)
|
||||
fatal_exit("out of memory during daemon init");
|
||||
numport = daemon_get_shufport(daemon, shufport);
|
||||
verbose(VERB_ALGO, "total of %d outgoing ports available", numport);
|
||||
|
||||
#ifdef HAVE_NGTCP2
|
||||
daemon->doq_table = doq_table_create(daemon->cfg, daemon->rand);
|
||||
if(!daemon->doq_table)
|
||||
fatal_exit("could not create doq_table: out of memory");
|
||||
#endif
|
||||
|
||||
daemon->num = (daemon->cfg->num_threads?daemon->cfg->num_threads:1);
|
||||
if(daemon->reuseport && (int)daemon->num < (int)daemon->num_ports) {
|
||||
@@ -711,16 +716,16 @@ daemon_fork(struct daemon* daemon)
|
||||
#endif
|
||||
|
||||
log_assert(daemon);
|
||||
if(!(daemon->views = views_create()))
|
||||
if(!(daemon->env->views = views_create()))
|
||||
fatal_exit("Could not create views: out of memory");
|
||||
/* create individual views and their localzone/data trees */
|
||||
if(!views_apply_cfg(daemon->views, daemon->cfg))
|
||||
if(!views_apply_cfg(daemon->env->views, daemon->cfg))
|
||||
fatal_exit("Could not set up views");
|
||||
|
||||
if(!acl_list_apply_cfg(daemon->acl, daemon->cfg, daemon->views))
|
||||
if(!acl_list_apply_cfg(daemon->acl, daemon->cfg, daemon->env->views))
|
||||
fatal_exit("Could not setup access control list");
|
||||
if(!acl_interface_apply_cfg(daemon->acl_interface, daemon->cfg,
|
||||
daemon->views))
|
||||
daemon->env->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");
|
||||
@@ -735,6 +740,14 @@ daemon_fork(struct daemon* daemon)
|
||||
"dnscrypt support");
|
||||
#endif
|
||||
}
|
||||
if(daemon->cfg->cookie_secret_file &&
|
||||
daemon->cfg->cookie_secret_file[0]) {
|
||||
if(!(daemon->cookie_secrets = cookie_secrets_create()))
|
||||
fatal_exit("Could not create cookie_secrets: out of memory");
|
||||
if(!cookie_secrets_apply_cfg(daemon->cookie_secrets,
|
||||
daemon->cfg->cookie_secret_file))
|
||||
fatal_exit("Could not setup cookie_secrets");
|
||||
}
|
||||
/* create global local_zones */
|
||||
if(!(daemon->local_zones = local_zones_create()))
|
||||
fatal_exit("Could not create local zones: out of memory");
|
||||
@@ -748,15 +761,15 @@ daemon_fork(struct daemon* daemon)
|
||||
fatal_exit("Could not set root or stub hints");
|
||||
|
||||
/* process raw response-ip configuration data */
|
||||
if(!(daemon->respip_set = respip_set_create()))
|
||||
if(!(daemon->env->respip_set = respip_set_create()))
|
||||
fatal_exit("Could not create response IP set");
|
||||
if(!respip_global_apply_cfg(daemon->respip_set, daemon->cfg))
|
||||
if(!respip_global_apply_cfg(daemon->env->respip_set, daemon->cfg))
|
||||
fatal_exit("Could not set up response IP set");
|
||||
if(!respip_views_apply_cfg(daemon->views, daemon->cfg,
|
||||
if(!respip_views_apply_cfg(daemon->env->views, daemon->cfg,
|
||||
&have_view_respip_cfg))
|
||||
fatal_exit("Could not set up per-view response IP sets");
|
||||
daemon->use_response_ip = !respip_set_is_empty(daemon->respip_set) ||
|
||||
have_view_respip_cfg;
|
||||
daemon->use_response_ip = !respip_set_is_empty(
|
||||
daemon->env->respip_set) || have_view_respip_cfg;
|
||||
|
||||
/* setup modules */
|
||||
daemon_setup_modules(daemon);
|
||||
@@ -872,14 +885,18 @@ daemon_cleanup(struct daemon* daemon)
|
||||
daemon->env->hints = NULL;
|
||||
local_zones_delete(daemon->local_zones);
|
||||
daemon->local_zones = NULL;
|
||||
respip_set_delete(daemon->respip_set);
|
||||
daemon->respip_set = NULL;
|
||||
views_delete(daemon->views);
|
||||
daemon->views = NULL;
|
||||
respip_set_delete(daemon->env->respip_set);
|
||||
daemon->env->respip_set = NULL;
|
||||
views_delete(daemon->env->views);
|
||||
daemon->env->views = NULL;
|
||||
if(daemon->env->auth_zones)
|
||||
auth_zones_cleanup(daemon->env->auth_zones);
|
||||
/* key cache is cleared by module deinit during next daemon_fork() */
|
||||
daemon_remote_clear(daemon->rc);
|
||||
if(daemon->fast_reload_thread)
|
||||
fast_reload_thread_stop(daemon->fast_reload_thread);
|
||||
if(daemon->fast_reload_printq_list)
|
||||
fast_reload_printq_list_delete(daemon->fast_reload_printq_list);
|
||||
for(i=0; i<daemon->num; i++)
|
||||
worker_delete(daemon->workers[i]);
|
||||
free(daemon->workers);
|
||||
@@ -898,6 +915,10 @@ daemon_cleanup(struct daemon* daemon)
|
||||
#ifdef USE_DNSCRYPT
|
||||
dnsc_delete(daemon->dnscenv);
|
||||
daemon->dnscenv = NULL;
|
||||
#endif
|
||||
#ifdef HAVE_NGTCP2
|
||||
doq_table_delete(daemon->doq_table);
|
||||
daemon->doq_table = NULL;
|
||||
#endif
|
||||
daemon->cfg = NULL;
|
||||
}
|
||||
@@ -929,14 +950,20 @@ daemon_delete(struct daemon* daemon)
|
||||
acl_list_delete(daemon->acl);
|
||||
acl_list_delete(daemon->acl_interface);
|
||||
tcl_list_delete(daemon->tcl);
|
||||
cookie_secrets_delete(daemon->cookie_secrets);
|
||||
listen_desetup_locks();
|
||||
free(daemon->chroot);
|
||||
free(daemon->pidfile);
|
||||
free(daemon->cfgfile);
|
||||
free(daemon->env);
|
||||
#ifdef HAVE_SSL
|
||||
listen_sslctx_delete_ticket_keys();
|
||||
SSL_CTX_free((SSL_CTX*)daemon->listen_sslctx);
|
||||
SSL_CTX_free((SSL_CTX*)daemon->connect_sslctx);
|
||||
SSL_CTX_free((SSL_CTX*)daemon->listen_dot_sslctx);
|
||||
SSL_CTX_free((SSL_CTX*)daemon->listen_doh_sslctx);
|
||||
SSL_CTX_free((SSL_CTX*)daemon->connect_dot_sslctx);
|
||||
#endif
|
||||
#ifdef HAVE_NGTCP2
|
||||
SSL_CTX_free((SSL_CTX*)daemon->listen_quic_sslctx);
|
||||
#endif
|
||||
free(daemon);
|
||||
/* lex cleanup */
|
||||
|
||||
+35
-6
@@ -58,6 +58,10 @@ struct ub_randstate;
|
||||
struct daemon_remote;
|
||||
struct respip_set;
|
||||
struct shm_main_info;
|
||||
struct doq_table;
|
||||
struct cookie_secrets;
|
||||
struct fast_reload_thread;
|
||||
struct fast_reload_printq;
|
||||
|
||||
#include "dnstap/dnstap_config.h"
|
||||
#ifdef USE_DNSTAP
|
||||
@@ -95,8 +99,14 @@ struct daemon {
|
||||
struct listen_port* rc_ports;
|
||||
/** remote control connections management (for first worker) */
|
||||
struct daemon_remote* rc;
|
||||
/** ssl context for listening to dnstcp over ssl, and connecting ssl */
|
||||
void* listen_sslctx, *connect_sslctx;
|
||||
/** ssl context for listening to dnstcp over ssl */
|
||||
void* listen_dot_sslctx;
|
||||
/** ssl context for connecting to dnstcp over ssl */
|
||||
void* connect_dot_sslctx;
|
||||
/** ssl context for listening to DoH */
|
||||
void* listen_doh_sslctx;
|
||||
/** ssl context for listening to quic */
|
||||
void* listen_quic_sslctx;
|
||||
/** num threads allocated */
|
||||
int num;
|
||||
/** num threads allocated in the previous config or 0 at first */
|
||||
@@ -129,15 +139,11 @@ struct daemon {
|
||||
struct timeval time_last_stat;
|
||||
/** time when daemon started */
|
||||
struct timeval time_boot;
|
||||
/** views structure containing view tree */
|
||||
struct views* views;
|
||||
#ifdef USE_DNSTAP
|
||||
/** the dnstap environment master value, copied and changed by threads*/
|
||||
struct dt_env* dtenv;
|
||||
#endif
|
||||
struct shm_main_info* shm_info;
|
||||
/** response-ip set with associated actions and tags. */
|
||||
struct respip_set* respip_set;
|
||||
/** some response-ip tags or actions are configured if true */
|
||||
int use_response_ip;
|
||||
/** some RPZ policies are configured */
|
||||
@@ -146,8 +152,23 @@ struct daemon {
|
||||
/** the dnscrypt environment */
|
||||
struct dnsc_env* dnscenv;
|
||||
#endif
|
||||
/** the doq connection table */
|
||||
struct doq_table* doq_table;
|
||||
/** reuse existing cache on reload if other conditions allow it. */
|
||||
int reuse_cache;
|
||||
/** the EDNS cookie secrets from the cookie-secret-file */
|
||||
struct cookie_secrets* cookie_secrets;
|
||||
/** the fast reload thread, or NULL */
|
||||
struct fast_reload_thread* fast_reload_thread;
|
||||
/** the fast reload printq list */
|
||||
struct fast_reload_printq* fast_reload_printq_list;
|
||||
/** the fast reload option to drop mesh queries, true if so. */
|
||||
int fast_reload_drop_mesh;
|
||||
/** for fast reload, if the tcl, tcp connection limits, has
|
||||
* changes for workers */
|
||||
int fast_reload_tcl_has_changes;
|
||||
/** config file name */
|
||||
char* cfgfile;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -200,4 +221,12 @@ void daemon_delete(struct daemon* daemon);
|
||||
*/
|
||||
void daemon_apply_cfg(struct daemon* daemon, struct config_file* cfg);
|
||||
|
||||
/**
|
||||
* Setup acl list to have entries for the port list.
|
||||
* @param list: the acl interface
|
||||
* @param port_list: list of open ports, or none.
|
||||
* @return false on failure
|
||||
*/
|
||||
int setup_acl_for_ports(struct acl_list* list, struct listen_port* port_list);
|
||||
|
||||
#endif /* DAEMON_H */
|
||||
|
||||
+4358
-32
File diff suppressed because it is too large
Load Diff
+167
@@ -48,6 +48,7 @@
|
||||
#ifdef HAVE_OPENSSL_SSL_H
|
||||
#include <openssl/ssl.h>
|
||||
#endif
|
||||
#include "util/locks.h"
|
||||
struct config_file;
|
||||
struct listen_list;
|
||||
struct listen_port;
|
||||
@@ -55,6 +56,7 @@ struct worker;
|
||||
struct comm_reply;
|
||||
struct comm_point;
|
||||
struct daemon_remote;
|
||||
struct config_strlist_head;
|
||||
|
||||
/** number of milliseconds timeout on incoming remote control handshake */
|
||||
#define REMOTE_CONTROL_TCP_TIMEOUT 120000
|
||||
@@ -118,6 +120,137 @@ struct remote_stream {
|
||||
};
|
||||
typedef struct remote_stream RES;
|
||||
|
||||
/**
|
||||
* Notification status. This is exchanged between the fast reload thread
|
||||
* and the server thread, over the commpair sockets.
|
||||
*/
|
||||
enum fast_reload_notification {
|
||||
/** nothing, not used */
|
||||
fast_reload_notification_none = 0,
|
||||
/** the fast reload thread is done */
|
||||
fast_reload_notification_done = 1,
|
||||
/** the fast reload thread is done but with an error, it failed */
|
||||
fast_reload_notification_done_error = 2,
|
||||
/** the fast reload thread is told to exit by the server thread.
|
||||
* Sent on server quit while the reload is running. */
|
||||
fast_reload_notification_exit = 3,
|
||||
/** the fast reload thread has exited, after being told to exit */
|
||||
fast_reload_notification_exited = 4,
|
||||
/** the fast reload thread has information to print out */
|
||||
fast_reload_notification_printout = 5,
|
||||
/** stop as part of the reload the thread and other threads */
|
||||
fast_reload_notification_reload_stop = 6,
|
||||
/** ack the stop as part of the reload, and also ack start */
|
||||
fast_reload_notification_reload_ack = 7,
|
||||
/** resume from stop as part of the reload */
|
||||
fast_reload_notification_reload_start = 8,
|
||||
/** the fast reload thread wants the mainthread to poll workers,
|
||||
* after the reload, sent when nopause is used */
|
||||
fast_reload_notification_reload_nopause_poll = 9
|
||||
};
|
||||
|
||||
/**
|
||||
* Fast reload printout queue. Contains a list of strings, that need to be
|
||||
* printed over the file descriptor.
|
||||
*/
|
||||
struct fast_reload_printq {
|
||||
/** if this item is in a list, the previous and next */
|
||||
struct fast_reload_printq *prev, *next;
|
||||
/** if this item is in a list, it is true. */
|
||||
int in_list;
|
||||
/** list of strings to printout */
|
||||
struct config_strlist_head* to_print;
|
||||
/** the current item to print. It is malloced. NULL if none. */
|
||||
char* client_item;
|
||||
/** The length, strlen, of the client_item, that has to be sent. */
|
||||
int client_len;
|
||||
/** The number of bytes sent of client_item. */
|
||||
int client_byte_count;
|
||||
/** the comm point for the client connection, the remote control
|
||||
* client. */
|
||||
struct comm_point* client_cp;
|
||||
/** the remote control connection to print output to. */
|
||||
struct remote_stream remote;
|
||||
/** the worker that the event is added in */
|
||||
struct worker* worker;
|
||||
};
|
||||
|
||||
/**
|
||||
* Fast reload auth zone change. Keeps track if an auth zone was removed,
|
||||
* added or changed. This is needed because workers can have events for
|
||||
* dealing with auth zones, like transfers, and those have to be removed
|
||||
* too, not just the auth zone structure from the tree. */
|
||||
struct fast_reload_auth_change {
|
||||
/** next in the list of auth zone changes. */
|
||||
struct fast_reload_auth_change* next;
|
||||
/** the zone in the old config */
|
||||
struct auth_zone* old_z;
|
||||
/** the zone in the new config */
|
||||
struct auth_zone* new_z;
|
||||
/** if the zone was deleted */
|
||||
int is_deleted;
|
||||
/** if the zone was added */
|
||||
int is_added;
|
||||
/** if the zone has been changed */
|
||||
int is_changed;
|
||||
};
|
||||
|
||||
/**
|
||||
* Fast reload thread structure
|
||||
*/
|
||||
struct fast_reload_thread {
|
||||
/** the thread number for the dtio thread,
|
||||
* must be first to cast thread arg to int* in checklock code. */
|
||||
int threadnum;
|
||||
/** communication socket pair, that sends commands */
|
||||
int commpair[2];
|
||||
/** thread id, of the io thread */
|
||||
ub_thread_type tid;
|
||||
/** if the io processing has started */
|
||||
int started;
|
||||
/** if the thread has to quit */
|
||||
int need_to_quit;
|
||||
/** verbosity of the fast_reload command, the number of +v options */
|
||||
int fr_verb;
|
||||
/** option to not pause threads during reload */
|
||||
int fr_nopause;
|
||||
/** option to drop mesh queries */
|
||||
int fr_drop_mesh;
|
||||
|
||||
/** the event that listens on the remote service worker to the
|
||||
* commpair, it receives content from the fast reload thread. */
|
||||
void* service_event;
|
||||
/** if the event that listens on the remote service worker has
|
||||
* been added to the comm base. */
|
||||
int service_event_is_added;
|
||||
/** the service event can read a cmd, nonblocking, so it can
|
||||
* save the partial read cmd here */
|
||||
uint32_t service_read_cmd;
|
||||
/** the number of bytes in service_read_cmd */
|
||||
int service_read_cmd_count;
|
||||
/** the worker that the service_event is added in */
|
||||
struct worker* worker;
|
||||
|
||||
/** the printout of output to the remote client. */
|
||||
struct fast_reload_printq *printq;
|
||||
|
||||
/** lock on fr_output, to stop race when both remote control thread
|
||||
* and fast reload thread use fr_output list. */
|
||||
lock_basic_type fr_output_lock;
|
||||
/** list of strings, that the fast reload thread produces that have
|
||||
* to be printed. The remote control thread can pick them up with
|
||||
* the lock. */
|
||||
struct config_strlist_head* fr_output;
|
||||
|
||||
/** communication socket pair, to respond to the reload request */
|
||||
int commreload[2];
|
||||
|
||||
/** the list of auth zone changes. */
|
||||
struct fast_reload_auth_change* auth_zone_change_list;
|
||||
/** the old tree of auth zones, to lookup. */
|
||||
struct auth_zones* old_auth_zones;
|
||||
};
|
||||
|
||||
/**
|
||||
* Create new remote control state for the daemon.
|
||||
* @param cfg: config file with key file settings.
|
||||
@@ -203,4 +336,38 @@ int ssl_printf(RES* ssl, const char* format, ...)
|
||||
int ssl_read_line(RES* ssl, char* buf, size_t max);
|
||||
#endif /* HAVE_SSL */
|
||||
|
||||
/**
|
||||
* Start fast reload thread
|
||||
* @param ssl: the RES connection to print to.
|
||||
* @param worker: the remote servicing worker.
|
||||
* @param s: the rc_state that is servicing the remote control connection to
|
||||
* the remote control client. It needs to be moved away to stay connected
|
||||
* while the fast reload is running.
|
||||
* @param fr_verb: verbosity to print output at. 0 is nothing, 1 is some
|
||||
* and 2 is more detail.
|
||||
* @param fr_nopause: option to not pause threads during reload.
|
||||
* @param fr_drop_mesh: option to drop mesh queries.
|
||||
*/
|
||||
void fast_reload_thread_start(RES* ssl, struct worker* worker,
|
||||
struct rc_state* s, int fr_verb, int fr_nopause, int fr_drop_mesh);
|
||||
|
||||
/**
|
||||
* Stop fast reload thread
|
||||
* @param fast_reload_thread: the thread struct.
|
||||
*/
|
||||
void fast_reload_thread_stop(struct fast_reload_thread* fast_reload_thread);
|
||||
|
||||
/** fast reload thread commands to remote service thread event callback */
|
||||
void fast_reload_service_cb(int fd, short bits, void* arg);
|
||||
|
||||
/** fast reload callback for the remote control client connection */
|
||||
int fast_reload_client_callback(struct comm_point* c, void* arg, int err,
|
||||
struct comm_reply* rep);
|
||||
|
||||
/** fast reload printq delete list */
|
||||
void fast_reload_printq_list_delete(struct fast_reload_printq* list);
|
||||
|
||||
/** Pick up per worker changes after a fast reload. */
|
||||
void fast_reload_worker_pickup_changes(struct worker* worker);
|
||||
|
||||
#endif /* DAEMON_REMOTE_H */
|
||||
|
||||
+29
-17
@@ -281,6 +281,12 @@ server_stats_compile(struct worker* worker, struct ub_stats_info* s, int reset)
|
||||
s->svr.rpz_action[i] += (long long)worker->env.mesh->rpz_action[i];
|
||||
timehist_export(worker->env.mesh->histogram, s->svr.hist,
|
||||
NUM_BUCKETS_HIST);
|
||||
s->svr.num_queries_discard_timeout +=
|
||||
(long long)worker->env.mesh->num_queries_discard_timeout;
|
||||
s->svr.num_queries_wait_limit +=
|
||||
(long long)worker->env.mesh->num_queries_wait_limit;
|
||||
s->svr.num_dns_error_reports +=
|
||||
(long long)worker->env.mesh->num_dns_error_reports;
|
||||
/* 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;
|
||||
@@ -325,20 +331,8 @@ server_stats_compile(struct worker* worker, struct ub_stats_info* s, int reset)
|
||||
s->svr.num_query_dnscrypt_replay = 0;
|
||||
#endif /* USE_DNSCRYPT */
|
||||
if(worker->env.auth_zones) {
|
||||
if(reset && !worker->env.cfg->stat_cumulative) {
|
||||
lock_rw_wrlock(&worker->env.auth_zones->lock);
|
||||
} else {
|
||||
lock_rw_rdlock(&worker->env.auth_zones->lock);
|
||||
}
|
||||
s->svr.num_query_authzone_up = (long long)worker->env.
|
||||
auth_zones->num_query_up;
|
||||
s->svr.num_query_authzone_down = (long long)worker->env.
|
||||
auth_zones->num_query_down;
|
||||
if(reset && !worker->env.cfg->stat_cumulative) {
|
||||
worker->env.auth_zones->num_query_up = 0;
|
||||
worker->env.auth_zones->num_query_down = 0;
|
||||
}
|
||||
lock_rw_unlock(&worker->env.auth_zones->lock);
|
||||
s->svr.num_query_authzone_up += (long long)worker->env.mesh->num_query_authzone_up;
|
||||
s->svr.num_query_authzone_down += (long long)worker->env.mesh->num_query_authzone_down;
|
||||
}
|
||||
s->svr.mem_stream_wait =
|
||||
(long long)tcp_req_info_get_stream_buffer_size();
|
||||
@@ -346,6 +340,12 @@ server_stats_compile(struct worker* worker, struct ub_stats_info* s, int reset)
|
||||
(long long)http2_get_query_buffer_size();
|
||||
s->svr.mem_http2_response_buffer =
|
||||
(long long)http2_get_response_buffer_size();
|
||||
#ifdef HAVE_NGTCP2
|
||||
s->svr.mem_quic = (long long)doq_table_quic_size_get(
|
||||
worker->daemon->doq_table);
|
||||
#else
|
||||
s->svr.mem_quic = 0;
|
||||
#endif /* HAVE_NGTCP2 */
|
||||
|
||||
/* Set neg cache usage numbers */
|
||||
set_neg_cache_stats(worker, &s->svr, reset);
|
||||
@@ -445,9 +445,15 @@ void server_stats_add(struct ub_stats_info* total, struct ub_stats_info* a)
|
||||
total->svr.num_queries_cookie_valid += a->svr.num_queries_cookie_valid;
|
||||
total->svr.num_queries_cookie_client += a->svr.num_queries_cookie_client;
|
||||
total->svr.num_queries_cookie_invalid += a->svr.num_queries_cookie_invalid;
|
||||
total->svr.num_queries_discard_timeout +=
|
||||
a->svr.num_queries_discard_timeout;
|
||||
total->svr.num_queries_wait_limit += a->svr.num_queries_wait_limit;
|
||||
total->svr.num_dns_error_reports += a->svr.num_dns_error_reports;
|
||||
total->svr.num_queries_missed_cache += a->svr.num_queries_missed_cache;
|
||||
total->svr.num_queries_prefetch += a->svr.num_queries_prefetch;
|
||||
total->svr.num_queries_timed_out += a->svr.num_queries_timed_out;
|
||||
total->svr.num_query_authzone_up += a->svr.num_query_authzone_up;
|
||||
total->svr.num_query_authzone_down += a->svr.num_query_authzone_down;
|
||||
if (total->svr.max_query_time_us < a->svr.max_query_time_us)
|
||||
total->svr.max_query_time_us = a->svr.max_query_time_us;
|
||||
total->svr.sum_query_list_size += a->svr.sum_query_list_size;
|
||||
@@ -455,9 +461,9 @@ void server_stats_add(struct ub_stats_info* total, struct ub_stats_info* a)
|
||||
#ifdef USE_DNSCRYPT
|
||||
total->svr.num_query_dnscrypt_crypted += a->svr.num_query_dnscrypt_crypted;
|
||||
total->svr.num_query_dnscrypt_cert += a->svr.num_query_dnscrypt_cert;
|
||||
total->svr.num_query_dnscrypt_cleartext += \
|
||||
total->svr.num_query_dnscrypt_cleartext +=
|
||||
a->svr.num_query_dnscrypt_cleartext;
|
||||
total->svr.num_query_dnscrypt_crypted_malformed += \
|
||||
total->svr.num_query_dnscrypt_crypted_malformed +=
|
||||
a->svr.num_query_dnscrypt_crypted_malformed;
|
||||
#endif /* USE_DNSCRYPT */
|
||||
/* the max size reached is upped to higher of both */
|
||||
@@ -474,6 +480,7 @@ void server_stats_add(struct ub_stats_info* total, struct ub_stats_info* a)
|
||||
total->svr.qtls += a->svr.qtls;
|
||||
total->svr.qtls_resume += a->svr.qtls_resume;
|
||||
total->svr.qhttps += a->svr.qhttps;
|
||||
total->svr.qquic += a->svr.qquic;
|
||||
total->svr.qipv6 += a->svr.qipv6;
|
||||
total->svr.qbit_QR += a->svr.qbit_QR;
|
||||
total->svr.qbit_AA += a->svr.qbit_AA;
|
||||
@@ -533,7 +540,8 @@ void server_stats_insquery(struct ub_server_stats* stats, struct comm_point* c,
|
||||
else stats->qclass_big++;
|
||||
stats->qopcode[ LDNS_OPCODE_WIRE(sldns_buffer_begin(c->buffer)) ]++;
|
||||
if(c->type != comm_udp) {
|
||||
stats->qtcp++;
|
||||
if(c->type != comm_doq)
|
||||
stats->qtcp++;
|
||||
if(c->ssl != NULL) {
|
||||
stats->qtls++;
|
||||
#ifdef HAVE_SSL
|
||||
@@ -542,6 +550,10 @@ void server_stats_insquery(struct ub_server_stats* stats, struct comm_point* c,
|
||||
#endif
|
||||
if(c->type == comm_http)
|
||||
stats->qhttps++;
|
||||
#ifdef HAVE_NGTCP2
|
||||
else if(c->type == comm_doq)
|
||||
stats->qquic++;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
if(repinfo && addr_is_ip6(&repinfo->remote_addr, repinfo->remote_addrlen))
|
||||
|
||||
+62
-30
@@ -463,6 +463,64 @@ detach(void)
|
||||
#endif /* HAVE_DAEMON */
|
||||
}
|
||||
|
||||
/* setup a listening ssl context, fatal_exit() on any failure */
|
||||
static void
|
||||
setup_listen_sslctx(void** ctx, int is_dot, int is_doh, struct config_file* cfg)
|
||||
{
|
||||
#ifdef HAVE_SSL
|
||||
if(!(*ctx = listen_sslctx_create(
|
||||
cfg->ssl_service_key, cfg->ssl_service_pem, NULL,
|
||||
cfg->tls_ciphers, cfg->tls_ciphersuites,
|
||||
(cfg->tls_session_ticket_keys.first &&
|
||||
cfg->tls_session_ticket_keys.first->str[0] != 0),
|
||||
is_dot, is_doh))) {
|
||||
fatal_exit("could not set up listen SSL_CTX");
|
||||
}
|
||||
#else /* HAVE_SSL */
|
||||
(void)ctx;(void)is_dot;(void)is_doh;(void)cfg;
|
||||
#endif /* HAVE_SSL */
|
||||
}
|
||||
|
||||
/* setups the needed ssl contexts, fatal_exit() on any failure */
|
||||
static void
|
||||
setup_sslctxs(struct daemon* daemon, struct config_file* cfg)
|
||||
{
|
||||
#ifdef HAVE_SSL
|
||||
if(!(daemon->rc = daemon_remote_create(cfg)))
|
||||
fatal_exit("could not set up remote-control");
|
||||
if(cfg->ssl_service_key && cfg->ssl_service_key[0]) {
|
||||
/* setup the session keys; the callback to use them will be
|
||||
* attached to each sslctx separately */
|
||||
if(cfg->tls_session_ticket_keys.first &&
|
||||
cfg->tls_session_ticket_keys.first->str[0] != 0) {
|
||||
if(!listen_sslctx_setup_ticket_keys(
|
||||
cfg->tls_session_ticket_keys.first)) {
|
||||
fatal_exit("could not set session ticket SSL_CTX");
|
||||
}
|
||||
}
|
||||
(void)setup_listen_sslctx(&daemon->listen_dot_sslctx, 1, 0, cfg);
|
||||
#ifdef HAVE_NGHTTP2_NGHTTP2_H
|
||||
if(cfg_has_https(cfg)) {
|
||||
(void)setup_listen_sslctx(&daemon->listen_doh_sslctx, 0, 1, cfg);
|
||||
}
|
||||
#endif
|
||||
#ifdef HAVE_NGTCP2
|
||||
if(cfg_has_quic(cfg)) {
|
||||
if(!(daemon->listen_quic_sslctx = quic_sslctx_create(
|
||||
cfg->ssl_service_key, cfg->ssl_service_pem, NULL))) {
|
||||
fatal_exit("could not set up quic SSL_CTX");
|
||||
}
|
||||
}
|
||||
#endif /* HAVE_NGTCP2 */
|
||||
}
|
||||
if(!(daemon->connect_dot_sslctx = connect_sslctx_create(NULL, NULL,
|
||||
cfg->tls_cert_bundle, cfg->tls_win_cert)))
|
||||
fatal_exit("could not set up connect SSL_CTX");
|
||||
#else /* HAVE_SSL */
|
||||
(void)daemon;(void)cfg;
|
||||
#endif /* HAVE_SSL */
|
||||
}
|
||||
|
||||
/** daemonize, drop user privileges and chroot if needed */
|
||||
static void
|
||||
perform_setup(struct daemon* daemon, struct config_file* cfg, int debug_mode,
|
||||
@@ -489,36 +547,7 @@ perform_setup(struct daemon* daemon, struct config_file* cfg, int debug_mode,
|
||||
#endif
|
||||
|
||||
/* read ssl keys while superuser and outside chroot */
|
||||
#ifdef HAVE_SSL
|
||||
if(!(daemon->rc = daemon_remote_create(cfg)))
|
||||
fatal_exit("could not set up remote-control");
|
||||
if(cfg->ssl_service_key && cfg->ssl_service_key[0]) {
|
||||
if(!(daemon->listen_sslctx = listen_sslctx_create(
|
||||
cfg->ssl_service_key, cfg->ssl_service_pem, NULL)))
|
||||
fatal_exit("could not set up listen SSL_CTX");
|
||||
if(cfg->tls_ciphers && cfg->tls_ciphers[0]) {
|
||||
if (!SSL_CTX_set_cipher_list(daemon->listen_sslctx, cfg->tls_ciphers)) {
|
||||
fatal_exit("failed to set tls-cipher %s", cfg->tls_ciphers);
|
||||
}
|
||||
}
|
||||
#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
|
||||
if(cfg->tls_ciphersuites && cfg->tls_ciphersuites[0]) {
|
||||
if (!SSL_CTX_set_ciphersuites(daemon->listen_sslctx, cfg->tls_ciphersuites)) {
|
||||
fatal_exit("failed to set tls-ciphersuites %s", cfg->tls_ciphersuites);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if(cfg->tls_session_ticket_keys.first &&
|
||||
cfg->tls_session_ticket_keys.first->str[0] != 0) {
|
||||
if(!listen_sslctx_setup_ticket_keys(daemon->listen_sslctx, cfg->tls_session_ticket_keys.first)) {
|
||||
fatal_exit("could not set session ticket SSL_CTX");
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!(daemon->connect_sslctx = connect_sslctx_create(NULL, NULL,
|
||||
cfg->tls_cert_bundle, cfg->tls_win_cert)))
|
||||
fatal_exit("could not set up connect SSL_CTX");
|
||||
#endif
|
||||
(void)setup_sslctxs(daemon, cfg);
|
||||
|
||||
/* init syslog (as root) if needed, before daemonize, otherwise
|
||||
* a fork error could not be printed since daemonize closed stderr.*/
|
||||
@@ -681,6 +710,9 @@ perform_setup(struct daemon* daemon, struct config_file* cfg, int debug_mode,
|
||||
* it would succeed on SIGHUP as well */
|
||||
if(!cfg->use_syslog)
|
||||
log_init(cfg->logfile, cfg->use_syslog, cfg->chrootdir);
|
||||
daemon->cfgfile = strdup(*cfgfile);
|
||||
if(!daemon->cfgfile)
|
||||
fatal_exit("out of memory in daemon cfgfile strdup");
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+135
-28
@@ -160,9 +160,11 @@ worker_mem_report(struct worker* ATTR_UNUSED(worker),
|
||||
+ sizeof(worker->rndstate)
|
||||
+ regional_get_mem(worker->scratchpad)
|
||||
+ sizeof(*worker->env.scratch_buffer)
|
||||
+ sldns_buffer_capacity(worker->env.scratch_buffer)
|
||||
+ forwards_get_mem(worker->env.fwds)
|
||||
+ hints_get_mem(worker->env.hints);
|
||||
+ sldns_buffer_capacity(worker->env.scratch_buffer);
|
||||
if(worker->daemon->env->fwds)
|
||||
log_info("forwards=%u", (unsigned)forwards_get_mem(worker->env.fwds));
|
||||
if(worker->daemon->env->hints)
|
||||
log_info("hints=%u", (unsigned)hints_get_mem(worker->env.hints));
|
||||
if(worker->thread_num == 0)
|
||||
me += acl_list_get_mem(worker->daemon->acl);
|
||||
if(cur_serv) {
|
||||
@@ -369,6 +371,84 @@ worker_check_request(sldns_buffer* pkt, struct worker* worker,
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send fast-reload acknowledgement to the mainthread in one byte.
|
||||
* This signals that this worker has received the previous command.
|
||||
* The worker is waiting if that is after a reload_stop command.
|
||||
* Or the worker has briefly processed the event itself, and in doing so
|
||||
* released data pointers to old config, after a reload_poll command.
|
||||
*/
|
||||
static void
|
||||
worker_send_reload_ack(struct worker* worker)
|
||||
{
|
||||
/* If this is clipped to 8 bits because thread_num>255, then that
|
||||
* is not a problem, the receiver counts the number of bytes received.
|
||||
* The number is informative only. */
|
||||
uint8_t c = (uint8_t)worker->thread_num;
|
||||
ssize_t ret;
|
||||
while(1) {
|
||||
ret = send(worker->daemon->fast_reload_thread->commreload[1],
|
||||
(void*)&c, 1, 0);
|
||||
if(ret == -1) {
|
||||
if(
|
||||
#ifndef USE_WINSOCK
|
||||
errno == EINTR || errno == EAGAIN
|
||||
# ifdef EWOULDBLOCK
|
||||
|| errno == EWOULDBLOCK
|
||||
# endif
|
||||
#else
|
||||
WSAGetLastError() == WSAEINTR ||
|
||||
WSAGetLastError() == WSAEINPROGRESS ||
|
||||
WSAGetLastError() == WSAEWOULDBLOCK
|
||||
#endif
|
||||
)
|
||||
continue; /* Try again. */
|
||||
log_err("worker reload ack reply: send failed: %s",
|
||||
sock_strerror(errno));
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/** stop and wait to resume the worker */
|
||||
static void
|
||||
worker_stop_and_wait(struct worker* worker)
|
||||
{
|
||||
uint8_t* buf = NULL;
|
||||
uint32_t len = 0, cmd;
|
||||
worker_send_reload_ack(worker);
|
||||
/* wait for reload */
|
||||
if(!tube_read_msg(worker->cmd, &buf, &len, 0)) {
|
||||
log_err("worker reload read reply failed");
|
||||
return;
|
||||
}
|
||||
if(len != sizeof(uint32_t)) {
|
||||
log_err("worker reload reply, bad control msg length %d",
|
||||
(int)len);
|
||||
free(buf);
|
||||
return;
|
||||
}
|
||||
cmd = sldns_read_uint32(buf);
|
||||
free(buf);
|
||||
if(cmd == worker_cmd_quit) {
|
||||
/* quit anyway */
|
||||
verbose(VERB_ALGO, "reload reply, control cmd quit");
|
||||
comm_base_exit(worker->base);
|
||||
return;
|
||||
}
|
||||
if(cmd != worker_cmd_reload_start) {
|
||||
log_err("worker reload reply, wrong reply command");
|
||||
}
|
||||
if(worker->daemon->fast_reload_drop_mesh) {
|
||||
verbose(VERB_ALGO, "worker: drop mesh queries after reload");
|
||||
mesh_delete_all(worker->env.mesh);
|
||||
}
|
||||
fast_reload_worker_pickup_changes(worker);
|
||||
worker_send_reload_ack(worker);
|
||||
verbose(VERB_ALGO, "worker resume after reload");
|
||||
}
|
||||
|
||||
void
|
||||
worker_handle_control_cmd(struct tube* ATTR_UNUSED(tube), uint8_t* msg,
|
||||
size_t len, int error, void* arg)
|
||||
@@ -404,6 +484,15 @@ worker_handle_control_cmd(struct tube* ATTR_UNUSED(tube), uint8_t* msg,
|
||||
verbose(VERB_ALGO, "got control cmd remote");
|
||||
daemon_remote_exec(worker);
|
||||
break;
|
||||
case worker_cmd_reload_stop:
|
||||
verbose(VERB_ALGO, "got control cmd reload_stop");
|
||||
worker_stop_and_wait(worker);
|
||||
break;
|
||||
case worker_cmd_reload_poll:
|
||||
verbose(VERB_ALGO, "got control cmd reload_poll");
|
||||
fast_reload_worker_pickup_changes(worker);
|
||||
worker_send_reload_ack(worker);
|
||||
break;
|
||||
default:
|
||||
log_err("bad command %d", (int)cmd);
|
||||
break;
|
||||
@@ -598,7 +687,8 @@ 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, NULL))
|
||||
alias_rrset, 0, worker->scratchpad, az, NULL,
|
||||
worker->env.views, worker->env.respip_set))
|
||||
return 0;
|
||||
|
||||
/* xxx_deny actions mean dropping the reply, unless the original reply
|
||||
@@ -659,22 +749,18 @@ answer_from_cache(struct worker* worker, struct query_info* qinfo,
|
||||
if(rep->ttl < timenow) {
|
||||
/* Check if we need to serve expired now */
|
||||
if(worker->env.cfg->serve_expired &&
|
||||
!worker->env.cfg->serve_expired_client_timeout
|
||||
/* if serve-expired-client-timeout is set, serve
|
||||
* an expired record without attempting recursion
|
||||
* if the serve_expired_norec_ttl is set for the record
|
||||
* as we know that recursion is currently failing. */
|
||||
(!worker->env.cfg->serve_expired_client_timeout ||
|
||||
timenow < rep->serve_expired_norec_ttl)
|
||||
#ifdef USE_CACHEDB
|
||||
&& !(worker->env.cachedb_enabled &&
|
||||
worker->env.cfg->cachedb_check_when_serve_expired)
|
||||
#endif
|
||||
) {
|
||||
if(worker->env.cfg->serve_expired_ttl &&
|
||||
rep->serve_expired_ttl < timenow)
|
||||
return 0;
|
||||
/* Ignore expired failure answers */
|
||||
if(FLAGS_GET_RCODE(rep->flags) !=
|
||||
LDNS_RCODE_NOERROR &&
|
||||
FLAGS_GET_RCODE(rep->flags) !=
|
||||
LDNS_RCODE_NXDOMAIN &&
|
||||
FLAGS_GET_RCODE(rep->flags) !=
|
||||
LDNS_RCODE_YXDOMAIN)
|
||||
if(!reply_info_can_answer_expired(rep, timenow))
|
||||
return 0;
|
||||
if(!rrset_array_lock(rep->ref, rep->rrset_count, 0))
|
||||
return 0;
|
||||
@@ -763,7 +849,8 @@ answer_from_cache(struct worker* worker, struct query_info* qinfo,
|
||||
} else if(partial_rep &&
|
||||
!respip_merge_cname(partial_rep, qinfo, rep, cinfo,
|
||||
must_validate, &encode_rep, worker->scratchpad,
|
||||
worker->env.auth_zones)) {
|
||||
worker->env.auth_zones, worker->env.views,
|
||||
worker->env.respip_set)) {
|
||||
goto bail_out;
|
||||
}
|
||||
if(encode_rep != rep) {
|
||||
@@ -1084,7 +1171,7 @@ answer_notify(struct worker* w, struct query_info* qinfo,
|
||||
|
||||
if(verbosity >= VERB_DETAIL) {
|
||||
char buf[380];
|
||||
char zname[255+1];
|
||||
char zname[LDNS_MAX_DOMAINLEN];
|
||||
char sr[25];
|
||||
dname_str(qinfo->qname, zname);
|
||||
sr[0]=0;
|
||||
@@ -1415,7 +1502,7 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
|
||||
return 0;
|
||||
}
|
||||
if(c->dnscrypt && !repinfo->is_dnscrypted) {
|
||||
char buf[LDNS_MAX_DOMAINLEN+1];
|
||||
char buf[LDNS_MAX_DOMAINLEN];
|
||||
/* Check if this is unencrypted and asking for certs */
|
||||
worker_check_request(c->buffer, worker, &check_result);
|
||||
if(check_result.value != 0) {
|
||||
@@ -1571,7 +1658,8 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
|
||||
if((ret=parse_edns_from_query_pkt(
|
||||
c->buffer, &edns, worker->env.cfg, c, repinfo,
|
||||
(worker->env.now ? *worker->env.now : time(NULL)),
|
||||
worker->scratchpad)) != 0) {
|
||||
worker->scratchpad,
|
||||
worker->daemon->cookie_secrets)) != 0) {
|
||||
struct edns_data reply_edns;
|
||||
verbose(VERB_ALGO, "worker parse edns: formerror.");
|
||||
log_addr(VERB_CLIENT, "from", &repinfo->client_addr,
|
||||
@@ -1814,7 +1902,7 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
|
||||
cinfo_tmp.tag_datas = acladdr->tag_datas;
|
||||
cinfo_tmp.tag_datas_size = acladdr->tag_datas_size;
|
||||
cinfo_tmp.view = acladdr->view;
|
||||
cinfo_tmp.respip_set = worker->daemon->respip_set;
|
||||
cinfo_tmp.view_name = NULL;
|
||||
cinfo = &cinfo_tmp;
|
||||
}
|
||||
|
||||
@@ -1846,10 +1934,10 @@ lookup_cache:
|
||||
* its qname must be that used for cache
|
||||
* lookup. */
|
||||
if((worker->env.cfg->prefetch &&
|
||||
*worker->env.now >= rep->prefetch_ttl) ||
|
||||
rep->prefetch_ttl <= *worker->env.now) ||
|
||||
(worker->env.cfg->serve_expired &&
|
||||
*worker->env.now > rep->ttl)) {
|
||||
|
||||
rep->ttl < *worker->env.now &&
|
||||
!(*worker->env.now < rep->serve_expired_norec_ttl))) {
|
||||
time_t leeway = rep->ttl - *worker->env.now;
|
||||
if(rep->ttl < *worker->env.now)
|
||||
leeway = 0;
|
||||
@@ -1967,13 +2055,13 @@ send_reply_rc:
|
||||
&repinfo->client_addr, repinfo->client_addrlen,
|
||||
tv, 1, c->buffer,
|
||||
(worker->env.cfg->log_destaddr?(void*)repinfo->c->socket->addr:NULL),
|
||||
c->type);
|
||||
c->type, c->ssl);
|
||||
} else {
|
||||
log_reply_info(NO_VERBOSE, &qinfo,
|
||||
&repinfo->client_addr, repinfo->client_addrlen,
|
||||
tv, 1, c->buffer,
|
||||
(worker->env.cfg->log_destaddr?(void*)repinfo->c->socket->addr:NULL),
|
||||
c->type);
|
||||
c->type, c->ssl);
|
||||
}
|
||||
}
|
||||
#ifdef USE_DNSCRYPT
|
||||
@@ -2174,8 +2262,11 @@ worker_init(struct worker* worker, struct config_file *cfg,
|
||||
: cfg->tcp_idle_timeout,
|
||||
cfg->harden_large_queries, cfg->http_max_streams,
|
||||
cfg->http_endpoint, cfg->http_notls_downstream,
|
||||
worker->daemon->tcl, worker->daemon->listen_sslctx,
|
||||
dtenv, worker_handle_request, worker);
|
||||
worker->daemon->tcl, worker->daemon->listen_dot_sslctx,
|
||||
worker->daemon->listen_doh_sslctx,
|
||||
worker->daemon->listen_quic_sslctx,
|
||||
dtenv, worker->daemon->doq_table, worker->env.rnd,
|
||||
cfg, worker_handle_request, worker);
|
||||
if(!worker->front) {
|
||||
log_err("could not create listening sockets");
|
||||
worker_delete(worker);
|
||||
@@ -2190,7 +2281,7 @@ worker_init(struct worker* worker, struct config_file *cfg,
|
||||
cfg->unwanted_threshold, cfg->outgoing_tcp_mss,
|
||||
&worker_alloc_cleanup, worker,
|
||||
cfg->do_udp || cfg->udp_upstream_without_downstream,
|
||||
worker->daemon->connect_sslctx, cfg->delay_close,
|
||||
worker->daemon->connect_dot_sslctx, cfg->delay_close,
|
||||
cfg->tls_use_sni, dtenv, cfg->udp_connect,
|
||||
cfg->max_reuse_tcp_queries, cfg->tcp_reuse_timeout,
|
||||
cfg->tcp_auth_query_timeout);
|
||||
@@ -2509,3 +2600,19 @@ void dtio_mainfdcallback(int ATTR_UNUSED(fd), short ATTR_UNUSED(ev),
|
||||
log_assert(0);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_NGTCP2
|
||||
void doq_client_event_cb(int ATTR_UNUSED(fd), short ATTR_UNUSED(ev),
|
||||
void* ATTR_UNUSED(arg))
|
||||
{
|
||||
log_assert(0);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_NGTCP2
|
||||
void doq_client_timer_cb(int ATTR_UNUSED(fd), short ATTR_UNUSED(ev),
|
||||
void* ATTR_UNUSED(arg))
|
||||
{
|
||||
log_assert(0);
|
||||
}
|
||||
#endif
|
||||
|
||||
+7
-1
@@ -72,7 +72,13 @@ enum worker_commands {
|
||||
/** obtain statistics without statsclear */
|
||||
worker_cmd_stats_noreset,
|
||||
/** execute remote control command */
|
||||
worker_cmd_remote
|
||||
worker_cmd_remote,
|
||||
/** for fast-reload, perform stop */
|
||||
worker_cmd_reload_stop,
|
||||
/** for fast-reload, start again */
|
||||
worker_cmd_reload_start,
|
||||
/** for fast-reload, poll to make sure worker has released data */
|
||||
worker_cmd_reload_poll
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
+7
-3
@@ -657,8 +657,9 @@ handle_event_moddone(struct module_qstate* qstate, int id)
|
||||
qstate->return_msg->rep &&
|
||||
!dns_cache_store(
|
||||
qstate->env, &qstate->qinfo, qstate->return_msg->rep,
|
||||
0, 0, 0, NULL,
|
||||
qstate->query_flags, qstate->qstarttime))
|
||||
0, qstate->prefetch_leeway, 0, NULL,
|
||||
qstate->query_flags, qstate->qstarttime,
|
||||
qstate->is_valrec))
|
||||
log_err("out of memory");
|
||||
|
||||
/* do nothing */
|
||||
@@ -701,6 +702,7 @@ dns64_operate(struct module_qstate* qstate, enum module_ev event, int id,
|
||||
iq->state = DNS64_NEW_QUERY;
|
||||
iq->started_no_cache_store = qstate->no_cache_store;
|
||||
qstate->no_cache_store = 1;
|
||||
ATTR_FALLTHROUGH
|
||||
/* fallthrough */
|
||||
case module_event_pass:
|
||||
qstate->ext_state[id] = handle_event_pass(qstate, id);
|
||||
@@ -846,6 +848,7 @@ dns64_adjust_a(int id, struct module_qstate* super, struct module_qstate* qstate
|
||||
*/
|
||||
cp = construct_reply_info_base(super->region, rep->flags, rep->qdcount,
|
||||
rep->ttl, rep->prefetch_ttl, rep->serve_expired_ttl,
|
||||
rep->serve_expired_norec_ttl,
|
||||
rep->an_numrrsets, rep->ns_numrrsets, rep->ar_numrrsets,
|
||||
rep->rrset_count, rep->security, LDNS_EDE_NONE);
|
||||
if(!cp)
|
||||
@@ -1006,7 +1009,8 @@ 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, qstate->qstarttime))
|
||||
0, super->prefetch_leeway, 0, NULL, super->query_flags,
|
||||
qstate->qstarttime, qstate->is_valrec))
|
||||
log_err("out of memory");
|
||||
}
|
||||
|
||||
|
||||
+20
-8
@@ -192,8 +192,11 @@ static void
|
||||
dt_apply_identity(struct dt_env *env, struct config_file *cfg)
|
||||
{
|
||||
char buf[MAXHOSTNAMELEN+1];
|
||||
if (!cfg->dnstap_send_identity)
|
||||
if (!cfg->dnstap_send_identity) {
|
||||
free(env->identity);
|
||||
env->identity = NULL;
|
||||
return;
|
||||
}
|
||||
free(env->identity);
|
||||
if (cfg->dnstap_identity == NULL || cfg->dnstap_identity[0] == 0) {
|
||||
if (gethostname(buf, MAXHOSTNAMELEN) == 0) {
|
||||
@@ -215,8 +218,11 @@ dt_apply_identity(struct dt_env *env, struct config_file *cfg)
|
||||
static void
|
||||
dt_apply_version(struct dt_env *env, struct config_file *cfg)
|
||||
{
|
||||
if (!cfg->dnstap_send_version)
|
||||
if (!cfg->dnstap_send_version) {
|
||||
free(env->version);
|
||||
env->version = NULL;
|
||||
return;
|
||||
}
|
||||
free(env->version);
|
||||
if (cfg->dnstap_version == NULL || cfg->dnstap_version[0] == 0)
|
||||
env->version = strdup(PACKAGE_STRING);
|
||||
@@ -230,13 +236,8 @@ dt_apply_version(struct dt_env *env, struct config_file *cfg)
|
||||
}
|
||||
|
||||
void
|
||||
dt_apply_cfg(struct dt_env *env, struct config_file *cfg)
|
||||
dt_apply_logcfg(struct dt_env *env, struct config_file *cfg)
|
||||
{
|
||||
if (!cfg->dnstap)
|
||||
return;
|
||||
|
||||
dt_apply_identity(env, cfg);
|
||||
dt_apply_version(env, cfg);
|
||||
if ((env->log_resolver_query_messages = (unsigned int)
|
||||
cfg->dnstap_log_resolver_query_messages))
|
||||
{
|
||||
@@ -275,6 +276,17 @@ dt_apply_cfg(struct dt_env *env, struct config_file *cfg)
|
||||
lock_basic_unlock(&env->sample_lock);
|
||||
}
|
||||
|
||||
void
|
||||
dt_apply_cfg(struct dt_env *env, struct config_file *cfg)
|
||||
{
|
||||
if (!cfg->dnstap)
|
||||
return;
|
||||
|
||||
dt_apply_identity(env, cfg);
|
||||
dt_apply_version(env, cfg);
|
||||
dt_apply_logcfg(env, cfg);
|
||||
}
|
||||
|
||||
int
|
||||
dt_init(struct dt_env *env, struct comm_base* base)
|
||||
{
|
||||
|
||||
@@ -106,6 +106,13 @@ dt_create(struct config_file* cfg);
|
||||
void
|
||||
dt_apply_cfg(struct dt_env *env, struct config_file *cfg);
|
||||
|
||||
/**
|
||||
* Apply config settings for log enable for message types.
|
||||
* @param env: dnstap environment object.
|
||||
* @param cfg: new config settings.
|
||||
*/
|
||||
void dt_apply_logcfg(struct dt_env *env, struct config_file *cfg);
|
||||
|
||||
/**
|
||||
* Initialize per-worker state in dnstap environment object.
|
||||
* @param env: dnstap environment object to initialize, created with dt_create().
|
||||
|
||||
@@ -1510,8 +1510,10 @@ void dtio_output_cb(int ATTR_UNUSED(fd), short bits, void* arg)
|
||||
#endif
|
||||
|
||||
if((bits&UB_EV_READ || dtio->ssl_brief_write)) {
|
||||
#ifdef HAVE_SSL
|
||||
if(dtio->ssl_brief_write)
|
||||
(void)dtio_disable_brief_write(dtio);
|
||||
#endif
|
||||
if(dtio->ready_frame_sent && !dtio->accept_frame_received) {
|
||||
if(dtio_read_accept_frame(dtio) <= 0)
|
||||
return;
|
||||
|
||||
+104
-22
@@ -200,18 +200,25 @@ static void tap_data_list_try_to_free_tail(struct tap_data_list* list)
|
||||
}
|
||||
|
||||
/** delete the tap structure */
|
||||
static void tap_data_free(struct tap_data* data)
|
||||
static void tap_data_free(struct tap_data* data, int free_tail)
|
||||
{
|
||||
ub_event_del(data->ev);
|
||||
ub_event_free(data->ev);
|
||||
if(!data)
|
||||
return;
|
||||
if(data->ev) {
|
||||
ub_event_del(data->ev);
|
||||
ub_event_free(data->ev);
|
||||
}
|
||||
#ifdef HAVE_SSL
|
||||
SSL_free(data->ssl);
|
||||
#endif
|
||||
close(data->fd);
|
||||
sock_close(data->fd);
|
||||
free(data->id);
|
||||
free(data->frame);
|
||||
data->data_list->d = NULL;
|
||||
tap_data_list_try_to_free_tail(data->data_list);
|
||||
if(data->data_list) {
|
||||
data->data_list->d = NULL;
|
||||
if(free_tail)
|
||||
tap_data_list_try_to_free_tail(data->data_list);
|
||||
}
|
||||
free(data);
|
||||
}
|
||||
|
||||
@@ -237,7 +244,7 @@ static void tap_data_list_delete(struct tap_data_list* list)
|
||||
while(e) {
|
||||
next = e->next;
|
||||
if(e->d) {
|
||||
tap_data_free(e->d);
|
||||
tap_data_free(e->d, 0);
|
||||
e->d = NULL;
|
||||
}
|
||||
free(e);
|
||||
@@ -260,7 +267,7 @@ static void tap_socket_close(struct tap_socket* s)
|
||||
{
|
||||
if(!s) return;
|
||||
if(s->fd == -1) return;
|
||||
close(s->fd);
|
||||
sock_close(s->fd);
|
||||
s->fd = -1;
|
||||
}
|
||||
|
||||
@@ -339,7 +346,8 @@ static struct tap_socket* tap_socket_new_tlsaccept(char* ip,
|
||||
s->fd = -1;
|
||||
s->ev_cb = ev_cb;
|
||||
s->data = data;
|
||||
s->sslctx = listen_sslctx_create(server_key, server_cert, verifypem);
|
||||
s->sslctx = listen_sslctx_create(server_key, server_cert, verifypem,
|
||||
NULL, NULL, 0, 0, 0);
|
||||
if(!s->sslctx) {
|
||||
log_err("could not create ssl context");
|
||||
free(s->ip);
|
||||
@@ -822,7 +830,6 @@ static int reply_with_accept(struct tap_data* data)
|
||||
{
|
||||
#ifdef USE_DNSTAP
|
||||
/* len includes the escape and framelength */
|
||||
int r;
|
||||
size_t len = 0;
|
||||
void* acceptframe = fstrm_create_control_frame_accept(
|
||||
DNSTAP_CONTENT_TYPE, &len);
|
||||
@@ -833,6 +840,8 @@ static int reply_with_accept(struct tap_data* data)
|
||||
|
||||
fd_set_block(data->fd);
|
||||
if(data->ssl) {
|
||||
#ifdef HAVE_SSL
|
||||
int r;
|
||||
if((r=SSL_write(data->ssl, acceptframe, len)) <= 0) {
|
||||
int r2;
|
||||
if((r2=SSL_get_error(data->ssl, r)) == SSL_ERROR_ZERO_RETURN)
|
||||
@@ -843,6 +852,7 @@ static int reply_with_accept(struct tap_data* data)
|
||||
free(acceptframe);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
if(send(data->fd, acceptframe, len, 0) == -1) {
|
||||
log_err("send failed: %s", sock_strerror(errno));
|
||||
@@ -878,6 +888,7 @@ static int reply_with_finish(struct tap_data* data)
|
||||
|
||||
fd_set_block(data->fd);
|
||||
if(data->ssl) {
|
||||
#ifdef HAVE_SSL
|
||||
int r;
|
||||
if((r=SSL_write(data->ssl, finishframe, len)) <= 0) {
|
||||
int r2;
|
||||
@@ -889,6 +900,7 @@ static int reply_with_finish(struct tap_data* data)
|
||||
free(finishframe);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
if(send(data->fd, finishframe, len, 0) == -1) {
|
||||
log_err("send failed: %s", sock_strerror(errno));
|
||||
@@ -988,7 +1000,7 @@ static int tap_handshake(struct tap_data* data)
|
||||
return 0;
|
||||
} else if(r == 0) {
|
||||
/* closed */
|
||||
tap_data_free(data);
|
||||
tap_data_free(data, 1);
|
||||
return 0;
|
||||
} else if(want == SSL_ERROR_SYSCALL) {
|
||||
/* SYSCALL and errno==0 means closed uncleanly */
|
||||
@@ -1006,7 +1018,7 @@ static int tap_handshake(struct tap_data* data)
|
||||
if(!silent)
|
||||
log_err("SSL_handshake syscall: %s",
|
||||
strerror(errno));
|
||||
tap_data_free(data);
|
||||
tap_data_free(data, 1);
|
||||
return 0;
|
||||
} else {
|
||||
unsigned long err = ERR_get_error();
|
||||
@@ -1016,7 +1028,7 @@ static int tap_handshake(struct tap_data* data)
|
||||
verbose(VERB_OPS, "ssl handshake failed "
|
||||
"from %s", data->id);
|
||||
}
|
||||
tap_data_free(data);
|
||||
tap_data_free(data, 1);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -1024,7 +1036,7 @@ static int tap_handshake(struct tap_data* data)
|
||||
data->ssl_handshake_done = 1;
|
||||
if(!tap_check_peer(data)) {
|
||||
/* closed */
|
||||
tap_data_free(data);
|
||||
tap_data_free(data, 1);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
@@ -1050,7 +1062,7 @@ void dtio_tap_callback(int ATTR_UNUSED(fd), short ATTR_UNUSED(bits), void* arg)
|
||||
if(verbosity>=4) log_info("s recv %d", (int)ret);
|
||||
if(ret == 0) {
|
||||
/* closed or error */
|
||||
tap_data_free(data);
|
||||
tap_data_free(data, 1);
|
||||
return;
|
||||
} else if(ret == -1) {
|
||||
/* continue later */
|
||||
@@ -1072,7 +1084,7 @@ void dtio_tap_callback(int ATTR_UNUSED(fd), short ATTR_UNUSED(bits), void* arg)
|
||||
data->frame = calloc(1, data->len);
|
||||
if(!data->frame) {
|
||||
log_err("out of memory");
|
||||
tap_data_free(data);
|
||||
tap_data_free(data, 1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -1085,7 +1097,7 @@ void dtio_tap_callback(int ATTR_UNUSED(fd), short ATTR_UNUSED(bits), void* arg)
|
||||
if(verbosity>=4) log_info("f recv %d", (int)r);
|
||||
if(r == 0) {
|
||||
/* closed or error */
|
||||
tap_data_free(data);
|
||||
tap_data_free(data, 1);
|
||||
return;
|
||||
} else if(r == -1) {
|
||||
/* continue later */
|
||||
@@ -1110,13 +1122,13 @@ void dtio_tap_callback(int ATTR_UNUSED(fd), short ATTR_UNUSED(bits), void* arg)
|
||||
data->is_bidirectional = 1;
|
||||
if(verbosity) log_info("bidirectional stream");
|
||||
if(!reply_with_accept(data)) {
|
||||
tap_data_free(data);
|
||||
tap_data_free(data, 1);
|
||||
return;
|
||||
}
|
||||
} else if(data->len >= 4 && sldns_read_uint32(data->frame) ==
|
||||
FSTRM_CONTROL_FRAME_STOP && data->is_bidirectional) {
|
||||
if(!reply_with_finish(data)) {
|
||||
tap_data_free(data);
|
||||
tap_data_free(data, 1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -1140,7 +1152,9 @@ void dtio_mainfdcallback(int fd, short ATTR_UNUSED(bits), void* arg)
|
||||
char* id = NULL;
|
||||
struct sockaddr_storage addr;
|
||||
socklen_t addrlen = (socklen_t)sizeof(addr);
|
||||
int s = accept(fd, (struct sockaddr*)&addr, &addrlen);
|
||||
int s;
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
s = accept(fd, (struct sockaddr*)&addr, &addrlen);
|
||||
if(s == -1) {
|
||||
#ifndef USE_WINSOCK
|
||||
/* EINTR is signal interrupt. others are closed connection. */
|
||||
@@ -1396,6 +1410,41 @@ static int internal_unittest()
|
||||
/* clean up */
|
||||
tap_data_list_delete(socket->data_list);
|
||||
free(socket);
|
||||
|
||||
/* Start again. Add two elements */
|
||||
socket = calloc(1, sizeof(*socket));
|
||||
log_assert(socket);
|
||||
for(i=0; i<2; i++) {
|
||||
datas[i] = calloc(1, sizeof(struct tap_data));
|
||||
log_assert(datas[i]);
|
||||
log_assert(tap_data_list_insert(&socket->data_list, datas[i]));
|
||||
}
|
||||
/* sanity base check */
|
||||
list = socket->data_list;
|
||||
for(i=0; list; i++) list = list->next;
|
||||
log_assert(i==2);
|
||||
|
||||
/* Free the last data, tail cannot be erased */
|
||||
list = socket->data_list;
|
||||
while(list->next) list = list->next;
|
||||
free(list->d);
|
||||
list->d = NULL;
|
||||
tap_data_list_try_to_free_tail(list);
|
||||
list = socket->data_list;
|
||||
for(i=0; list; i++) list = list->next;
|
||||
log_assert(i==2);
|
||||
|
||||
/* clean up */
|
||||
tap_data_list_delete(socket->data_list);
|
||||
free(socket);
|
||||
|
||||
if(log_get_lock()) {
|
||||
lock_basic_destroy((lock_basic_type*)log_get_lock());
|
||||
}
|
||||
checklock_stop();
|
||||
#ifdef USE_WINSOCK
|
||||
WSACleanup();
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1497,8 +1546,8 @@ int main(int argc, char** argv)
|
||||
usage(argv);
|
||||
}
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
/* argc -= optind; not using further arguments */
|
||||
/* argv += optind; not using further arguments */
|
||||
|
||||
if(usessl) {
|
||||
#ifdef HAVE_SSL
|
||||
@@ -1527,6 +1576,9 @@ int main(int argc, char** argv)
|
||||
config_delstrlist(tcp_list.first);
|
||||
config_delstrlist(tls_list.first);
|
||||
|
||||
if(log_get_lock()) {
|
||||
lock_basic_destroy((lock_basic_type*)log_get_lock());
|
||||
}
|
||||
checklock_stop();
|
||||
#ifdef USE_WINSOCK
|
||||
WSACleanup();
|
||||
@@ -1734,3 +1786,33 @@ void remote_get_opt_ssl(char* ATTR_UNUSED(str), void* ATTR_UNUSED(arg))
|
||||
{
|
||||
log_assert(0);
|
||||
}
|
||||
|
||||
void fast_reload_service_cb(int ATTR_UNUSED(fd), short ATTR_UNUSED(ev),
|
||||
void* ATTR_UNUSED(arg))
|
||||
{
|
||||
log_assert(0);
|
||||
}
|
||||
|
||||
int fast_reload_client_callback(struct comm_point* ATTR_UNUSED(c),
|
||||
void* ATTR_UNUSED(arg), int ATTR_UNUSED(error),
|
||||
struct comm_reply* ATTR_UNUSED(repinfo))
|
||||
{
|
||||
log_assert(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef HAVE_NGTCP2
|
||||
void doq_client_event_cb(int ATTR_UNUSED(fd), short ATTR_UNUSED(ev),
|
||||
void* ATTR_UNUSED(arg))
|
||||
{
|
||||
log_assert(0);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_NGTCP2
|
||||
void doq_client_timer_cb(int ATTR_UNUSED(fd), short ATTR_UNUSED(ev),
|
||||
void* ATTR_UNUSED(arg))
|
||||
{
|
||||
log_assert(0);
|
||||
}
|
||||
#endif
|
||||
|
||||
+486
@@ -1,3 +1,489 @@
|
||||
11 April 2025: Yorgos
|
||||
- Merge #1265: Fix WSAPoll.
|
||||
|
||||
10 April 2025: Wouter
|
||||
- Fix for print of connection type in log-replies for dot and doh.
|
||||
|
||||
9 April 2025: Wouter
|
||||
- Fix to detect if atomic_store links in configure.
|
||||
- Fix #1264: unbound 1.22.0 leaks memory when doing DoH.
|
||||
|
||||
8 April 2025: Wouter
|
||||
- Tag for 1.23.0rc1.
|
||||
- Fix fast_reload to print chroot with config file name.
|
||||
|
||||
7 April 2025: Yorgos
|
||||
- Merge #902: DNS Error Reporting (RFC 9567). Introduces new
|
||||
configuration option 'dns-error-reporting' and new statistics for
|
||||
'num.dns_error_reports'.
|
||||
|
||||
4 April 2025: Wouter
|
||||
- Fix mesh_copy_client_info to omit null contents from copy.
|
||||
- Fix comment name in the rpz nsdname test.
|
||||
- Fix nettle compile for warnings and ticket keys.
|
||||
- Fix redis_replica test for unused option defaults and log printout.
|
||||
- Fix test to speed up common.sh script kill_pid.
|
||||
- Fix to update common.sh for speed of kill_pid.
|
||||
|
||||
4 April 2025: Yorgos
|
||||
- Merge #1019: Redis read-only replica support.
|
||||
Introduces new 'redis-replica-*' options for the Redis cache backend.
|
||||
|
||||
3 April 2025: Wouter
|
||||
- Fix #1263: Exempt loopback addresses from wait-limit.
|
||||
- Fix wait-limit-netblock and wait-limit-cookie-netblock config parse
|
||||
to allow two arguments.
|
||||
- Fix ub_event and include dnstap and win_svc headers.
|
||||
- Fix test for stat_values for wait limit defaults for localhost.
|
||||
- Fix parameter unused warning in net_help.c.
|
||||
|
||||
2 April 2025: Yorgos
|
||||
- Merge #1262 from markyang92, fix build with
|
||||
'gcc-15 -Wbuiltin-declaration-mismatch' error in compat/malloc.c.
|
||||
- For #1262, ifdef is no longer needed.
|
||||
|
||||
2 April 2025: Wouter
|
||||
- Fix unbound-control test so it counts the new flush_negative output,
|
||||
also answers the _ta probe from testns and prints command output
|
||||
and skip a thread specific test when no threads are available.
|
||||
- Fix that ub_event has the facility to deal with callbacks for
|
||||
fast reload, doq, windows-stop and dnstap.
|
||||
- Fix fast reload test to check if pid exists before acting on it.
|
||||
|
||||
1 April 2025: Wouter
|
||||
- Fix escape more characters when printing an RR type with an unquoted
|
||||
string.
|
||||
- Enable the auth_tls.tdir and auth_tls_failcert.tdir tests.
|
||||
|
||||
31 March 2025: Wouter
|
||||
- iana portlist update.
|
||||
- Merge #1042: Fast Reload. The unbound-control fast_reload is added.
|
||||
It reads changed config in a thread, then only briefly pauses the
|
||||
service threads, that keep running. DNS service is only interrupted
|
||||
briefly, less than a second.
|
||||
- Skip the unit tests for auth_tls.tdir and auth_tls_failcert.tdir.
|
||||
|
||||
27 March 2025: Wouter
|
||||
- Fix unit test dname log printout typecast.
|
||||
- Fix for ci test, expat is installed on the osx image.
|
||||
|
||||
26 March 2025: Yorgos
|
||||
- Fix #1255: Multiple pinnings to vulnerable copies of libexpat.
|
||||
- For #1255, for ios use an older expat version that does not require
|
||||
C++11 language features.
|
||||
- For #1255, for ios disable building tests that require C++11.
|
||||
- For #1255, for ios try the latest expat version again.
|
||||
|
||||
24 March 2025: Wouter
|
||||
- Fix #1254: `send failed: Socket is not connected` and
|
||||
`remote address is 0.0.0.0 port 53`.
|
||||
|
||||
21 March 2025: Wouter
|
||||
- Fix #1253: Cache entries fail to be removed from Redis cachedb
|
||||
backend with unbound-control flush* +c.
|
||||
- Fix for #1253: Fix for redis cachedb backend to expect an integer
|
||||
reply for the EXPIRE command.
|
||||
|
||||
20 March 2025: Wouter
|
||||
- Fix print of RR type NSAP-PTR, it is an unquoted string.
|
||||
|
||||
18 March 2025: Wouter
|
||||
- Fix #1251: WSAPoll first argument cannot be NULL.
|
||||
- Fix for windows compile create ssl contexts.
|
||||
|
||||
17 March 2025: Wouter
|
||||
- Fix representation of types GPOS and RESINFO, add rdf type for
|
||||
unquoted str.
|
||||
|
||||
16 March 2025: Yorgos
|
||||
- Fix 'unbound-control flush_negative' when reporting removed data;
|
||||
reported by David 'eqvinox' Lamparter.
|
||||
|
||||
28 February 2025: Wouter
|
||||
- Merge #1238: Prefer SOURCE_DATE_EPOCH over actual time.
|
||||
Add --help output description for the SOURCE_DATE_EPOCH variable.
|
||||
|
||||
25 February 2025: Wouter
|
||||
- Merge #1243: Do not shadow tm on line 236.
|
||||
|
||||
24 February 2025: Yorgos
|
||||
- Fix hash calculation for cachedb to ignore case. Previously, cached
|
||||
records there were only relevant for same case queries (if not
|
||||
already in Unbound's internal cache).
|
||||
|
||||
19 February 2025: Yorgos
|
||||
- Fix static analysis report about unhandled EOF on error conditions
|
||||
when reading anchor key files.
|
||||
- Merge #1241: Fix infra-keep-probing for low infra-cache-max-rtt
|
||||
values.
|
||||
|
||||
17 February 2025: Yorgos
|
||||
- Consider reconfigurations when calculating the still_useful_timeout
|
||||
for servers in the infrastructure cache.
|
||||
|
||||
30 January 2025: Wouter
|
||||
- Fix #986: Resolving sas.com with dnssec-validation fails though
|
||||
signed delegations seem to be (mostly) correct.
|
||||
|
||||
29 January 2025: Yorgos
|
||||
- Make the default value of module-config "validator iterator"
|
||||
regardless of compilation options. --enable-subnet would implicitly
|
||||
change the value to enable the subnetcache module by default in the
|
||||
past.
|
||||
|
||||
24 January 2025: Yorgos
|
||||
- Merge #1220 from Petr Menšík, Add unbound members group access to
|
||||
control key.
|
||||
|
||||
21 January 2025: Yorgos
|
||||
- Use the same interface listening port discovery code for all needed
|
||||
protocols.
|
||||
- Port to string only when needed before getaddrinfo().
|
||||
- Do not open unencrypted channels next to encrypted ones on the same
|
||||
port.
|
||||
- Merge #1224 from Theo Buehler: Do not use DSA API unless USE_DSA is
|
||||
set.
|
||||
|
||||
21 January 2025: Wouter
|
||||
- Fix compile of interface check code when dnscrypt or quic is
|
||||
disabled.
|
||||
- Fix encoding of RR type ATMA.
|
||||
- Fix to check length in ATMA string to wire.
|
||||
- Merge #1229: check before use daemon->shm_info.
|
||||
|
||||
20 January 2025: Yorgos
|
||||
- Merge #1222: Unique DoT and DoH SSL contexts to allow for different
|
||||
ALPN.
|
||||
- Create the quic SSL listening context only when needed.
|
||||
|
||||
15 January 2025: Yorgos
|
||||
- Merge #1221: Consider auth zones when checking for forwarders.
|
||||
|
||||
14 January 2025: Yorgos
|
||||
- Add resolver.arpa and service.arpa to the default locally served
|
||||
zones.
|
||||
|
||||
13 January 2025: Yorgos
|
||||
- Fix #1213: Misleading error message on default access control causing
|
||||
refuse.
|
||||
|
||||
10 January 2025: Yorgos
|
||||
- Merge #1214: Use TCP_NODELAY on TLS sockets to speed up the TLS
|
||||
handshake.
|
||||
|
||||
31 December 2024: Yorgos
|
||||
- Merge #1174: Serve expired cache update fixes. Fixes a regression bug
|
||||
with serve-expired that appeared in 1.22.0 and would not allow the
|
||||
iterator to update the cache with not-yet-validated entries resulting
|
||||
in increased outgoing traffic.
|
||||
|
||||
20 December 2024: Yorgos
|
||||
- For #1207: [FR] Support for RESINFO RRType 261 (RFC9606), add
|
||||
LDNS_RR_TYPE_RESINFO similar to LDNS_RR_TYPE_TXT.
|
||||
|
||||
13 December 2024: Yorgos
|
||||
- Merge #1204: ci: set persist-credentials: false for actions/checkout
|
||||
per zizmor suggestion.
|
||||
|
||||
3 December 2024: Yorgos
|
||||
- Merge #1189: Fix the dname_str method to cause conversion errors
|
||||
when the domain name length is 255.
|
||||
- Merge #1197: dname_str() fixes.
|
||||
- For #1175, the default value of serve-expired-ttl is set to 86400
|
||||
(1 day) as suggested by RFC8767.
|
||||
- Merge #1198: Fix log-servfail with serve expired and no useful cache
|
||||
contents.
|
||||
- Safeguard alias loop while looking in the cache for expired answers.
|
||||
- Merge #1187: Create the SSL_CTX for QUIC before chroot and privilege
|
||||
drop.
|
||||
- Fix typo in log_servfail.tdir test.
|
||||
|
||||
22 November 2024: Yorgos
|
||||
- Fix #1175: serve-expired does not adhere to secure-by-default
|
||||
principle. The default value of serve-expired-client-timeout
|
||||
is set to 1800 as suggested by RFC8767.
|
||||
- For #1175, update serve-expired tests.
|
||||
|
||||
20 November 2024: Yorgos
|
||||
- Fix comparison to help static analyzer.
|
||||
|
||||
19 November 2024: Yorgos
|
||||
- Merge #1169 from Sergey Kacheev, fix: lock-free counters for
|
||||
auth_zone up/down queries.
|
||||
|
||||
15 November 2024: Wouter
|
||||
- Fix #1183: the data being used is released in method
|
||||
nsec3_hash_test_entry.
|
||||
- Fix for #1183: release nsec3 hashes per test file.
|
||||
|
||||
8 November 2024: Yorgos
|
||||
- More descriptive text for 'harden-algo-downgrade'.
|
||||
- Complete fix for max-global-quota to 200.
|
||||
|
||||
6 November 2024: Yorgos
|
||||
- Increase the default of max-global-quota to 200 from 128 after
|
||||
operational feedback. Still keeping the possible amplification
|
||||
factor (CAMP related issues) in the hundreds.
|
||||
|
||||
5 November 2024: Wouter
|
||||
- Fix for the serve expired DNSSEC information fix, it would not allow
|
||||
current delegation information be updated in cache. The fix allows
|
||||
current delegation and validation recursion information to be
|
||||
updated, but as a consequence no longer has certain expired
|
||||
information around for later dnssec valid expired responses.
|
||||
- Fix to log redis timeout error string on failure.
|
||||
|
||||
5 November 2024: Yorgos
|
||||
- Fix SETEX check during Redis (re)initialization.
|
||||
|
||||
4 November 2024: Wouter
|
||||
- Fix redis that during a reload it does not fail if the redis
|
||||
server does not connect or does not respond. It still logs the
|
||||
errors and if the server is up checks expiration features.
|
||||
- Merge #1167: Makefile.in: fix occasional parallel build failures
|
||||
around bison rule.
|
||||
|
||||
1 November 2024: Yorgos
|
||||
- Merge #1159: Stats for discard-timeout and wait-limit.
|
||||
- Add test case for #1159.
|
||||
- Some clean up for stat_values.test.
|
||||
- Merge #1170 from Melroy van den Berg, Fix chroot manpage
|
||||
description.
|
||||
- Merge #1157 from Liang Zhu, Fix heap corruption when calling
|
||||
ub_ctx_delete in Windows.
|
||||
|
||||
25 October 2024: Yorgos
|
||||
- Fix #1163: Typos in unbound.conf documentation.
|
||||
|
||||
17 October 2024: Wouter
|
||||
- Tag for 1.22.0 release. This did not contain the 1154 fix
|
||||
from 16 oct. The code repository continues with
|
||||
version 1.22.1 in development.
|
||||
|
||||
16 October 2024: Yorgos
|
||||
- Fix for dnsoverquic and dnstap to use the correct dnstap
|
||||
environment.
|
||||
|
||||
16 October 2024: Wouter
|
||||
- Fix for dnstap with dnscrypt and dnstap without dnsoverquic.
|
||||
- Fix #1154: Tag Incorrectly Applying for Other Interfaces
|
||||
Using the Same IP. This fix is not for 1.22.0.
|
||||
|
||||
14 October 2024: Wouter
|
||||
- Fix to display warning if quic-port is set but dnsoverquic is not
|
||||
enabled when compiled.
|
||||
- Fix dnsoverquic to extend the number of streams when one is closed.
|
||||
|
||||
11 October 2024: Wouter
|
||||
- Fix to disable detection of quic configured ports when quic is
|
||||
not compiled in.
|
||||
- Fix harden-unverified-glue for AAAA cache_fill_missing lookups.
|
||||
- Fix contrib/aaaa-filter-iterator.patch for change in call
|
||||
signature for cache_fill_missing.
|
||||
|
||||
10 October 2024: Wouter
|
||||
- Fix cookie_file test sporadic fails for time change during
|
||||
the test.
|
||||
- Fix add reallocarray to alloc stats unit test, and disable
|
||||
override of strdup in unbound-host, and the result of config
|
||||
get option is freed properly.
|
||||
- Tag for 1.22.0rc1.
|
||||
|
||||
9 October 2024: Wouter
|
||||
- Merge #871: DNS over QUIC. This adds `quic-port: 853` and
|
||||
`quic-size: 8m` that enable dnsoverquic, and the counters
|
||||
`num.query.quic` and `mem.quic` in the statistics output.
|
||||
The feature needs to be enabled by compiling with libngtcp2,
|
||||
with `--with-libngtcp2=path` and libngtcp2 needs openssl+quic,
|
||||
pass that with `--with-ssl=path` to compile unbound as well.
|
||||
- Fix to limit NSEC TTL for messages from cachedb. Fix to limit the
|
||||
prefetch ttl for messages after a CNAME with short TTL.
|
||||
- Fix for dnstap compile of doqclient with doq disabled.
|
||||
|
||||
8 October 2024: Wouter
|
||||
- Fix #1149: unbound-control-setup hangs sometimes depending on
|
||||
the openssl version.
|
||||
- Fix #1128: Cannot override tcp-upstream and tls-upstream with
|
||||
forward-tcp-upstream and forward-tls-upstream.
|
||||
|
||||
3 October 2024: Yorgos
|
||||
- Fix CVE-2024-8508, unbounded name compression could lead to denial
|
||||
of service.
|
||||
- This fix was part of 1.21.1, a security point release on 1.21.0.
|
||||
The code repository continues with this fix and the version number
|
||||
1.22.0.
|
||||
|
||||
30 September 2024: Wouter
|
||||
- Fix negative cache NSEC3 parameter compares for zero length NSEC3
|
||||
salt.
|
||||
- Fix unbound dnstap socket test program analyzer warnings about
|
||||
unused variable assignments and variable initialization.
|
||||
|
||||
25 September 2024: Wouter
|
||||
- Fix #1144: [FR] log timestamps in ISO8601 format with timezone.
|
||||
This adds the option `log-time-iso: yes` that logs in ISO8601
|
||||
format.
|
||||
|
||||
24 September 2024: Yorgos
|
||||
- Attempt to further fix doh_downstream_buffer_size.tdir flakiness.
|
||||
- More clear text for prefetch and minimal-responses in the
|
||||
unbound.conf man page.
|
||||
- Merge #1143: Fix cache update when serve expired is used. Expired
|
||||
records are favored over resolution and validation failures when
|
||||
serve-expired is used.
|
||||
|
||||
23 September 2024: Wouter
|
||||
- Fix dns64 with prefetch that the prefetch is stored in cache.
|
||||
|
||||
23 September 2024: Yorgos
|
||||
- Fix doxygen warnings by commenting out CLANG_ASSISTED_PARSING,
|
||||
CLANG_ADD_INC_PATHS, CLANG_OPTIONS and CLANG_DATABASE_PATH; they were
|
||||
already disabled.
|
||||
|
||||
17 September 2024: Wouter
|
||||
- Add redis-command-timeout: 20 and redis-connect-timeout: 200,
|
||||
that can set the timeout separately for commands and the
|
||||
connection set up to the redis server. If they are not
|
||||
specified, the redis-timeout value is used.
|
||||
|
||||
16 September 2024: Wouter
|
||||
- Merge #1140: Fix spelling mistake in comments.
|
||||
|
||||
11 September 2024: Yorgos
|
||||
- Fix and add comments in testdata/val_negcache_ttl.rpl.
|
||||
|
||||
10 September 2024: Wouter
|
||||
- Fix to limit NSEC and NSEC3 TTL when aggressive nsec is
|
||||
enabled (RFC9077).
|
||||
- Add unit test for ttl limit for aggressive nsec.
|
||||
|
||||
6 September 2024: Yorgos
|
||||
- Fix alloc-size and calloc-transposed-args compiler warnings.
|
||||
- Fix comment to not trigger doxygen unknown command.
|
||||
|
||||
5 September 2024: Wouter
|
||||
- Fix config file read for dnstap-sample-rate.
|
||||
|
||||
2 September 2024: Wouter
|
||||
- Merge #1135: Add new IANA trust anchor.
|
||||
|
||||
30 August 2024: Wouter
|
||||
- Merge #1132: b.root renumbering.
|
||||
- Fix for #1132, adjusted unit test for change in the test file.
|
||||
- Fix for #1132, comment about adjusted copy of reference check.
|
||||
|
||||
29 August 2024: Wouter
|
||||
- Unit test for auth zone transfer TLS, and TLS failure.
|
||||
- Fix to print port number in logs for auth zone transfer activities.
|
||||
|
||||
28 August 2024: Wouter
|
||||
- Fix that when rpz is applied the message does not get picked up by
|
||||
the validator. That stops validation failures for the message.
|
||||
- Fix that stub-zone and forward-zone clauses do not exhaust memory
|
||||
for long content.
|
||||
|
||||
27 August 2024: Wouter
|
||||
- Fix #1130: Loads of logs: "validation failure: key for validation
|
||||
<domain>. is marked as invalid because of a previous" for
|
||||
non-DNSSEC signed zone.
|
||||
|
||||
23 August 2024: Wouter
|
||||
- Merge patch to fix for glue that is outside of zone, with
|
||||
`harden-unverified-glue`, from Karthik Umashankar (Microsoft).
|
||||
Enabling this option protects the Unbound resolver against bad
|
||||
glue, that is unverified out of zone glue, by resolving them.
|
||||
It uses the records as last resort if there is no other working
|
||||
glue.
|
||||
- Fix #1127: error: "memory exhausted" when defining more than 9994
|
||||
local-zones.
|
||||
- Fix documentation for cache_fill_missing function.
|
||||
|
||||
21 August 2024: Wouter
|
||||
- Add cross platform freebsd, openbsd and netbsd to github ci.
|
||||
- Fix for char signedness warnings on NetBSD.
|
||||
|
||||
20 August 2024: Wouter
|
||||
- Add iter-scrub-ns, iter-scrub-cname and max-global-quota
|
||||
configuration options.
|
||||
|
||||
19 August 2024: Wouter
|
||||
- Fix #1126: unbound-control-setup hangs while testing for openssl
|
||||
presence starting from version 1.21.0.
|
||||
|
||||
9 August 2024: Wouter
|
||||
- Fix spelling for the cache-min-negative-ttl entry in the
|
||||
example.conf.
|
||||
- Tag for release 1.21.0, the repository continues with 1.21.1
|
||||
in development.
|
||||
|
||||
8 August 2024: Wouter
|
||||
- Fix CAMP issues with global quota. Thanks to Huayi Duan, Marco
|
||||
Bearzi, Jodok Vieli, and Cagin Tanir from NetSec group, ETH Zurich.
|
||||
- Fix CacheFlush issues with limit on NS RRs. Thanks to Yehuda Afek,
|
||||
Anat Bremler-Barr, Shoham Danino and Yuval Shavitt (Tel-Aviv
|
||||
University and Reichman University).
|
||||
- Set version number to 1.21.0 for release. This has tag 1.21.0rc1.
|
||||
- Fix that for windows the module startup is called and sets up
|
||||
the module-config.
|
||||
|
||||
2 August 2024: Wouter
|
||||
- Fix that alloc stats has strdup checks, it stops debuggers from
|
||||
complaining about mismatch at free time.
|
||||
- Fix testbound for alloc stats strdup in util/alloc.c.
|
||||
- Merge #1090: Cookie secret file. Adds
|
||||
`cookie-secret-file: "unbound_cookiesecrets.txt"` option to store
|
||||
cookie secrets for EDNS COOKIE secret rollover. The remote control
|
||||
add_cookie_secret, activate_cookie_secret and drop_cookie_secret
|
||||
commands can be used for rollover, the command print_cookie_secrets
|
||||
shows the values in use.
|
||||
- Fix that alloc stats for forwards and hints are printed, and when
|
||||
alloc stats is enabled, the unit test for unbound control waits for
|
||||
reloads to complete.
|
||||
|
||||
1 August 2024: Wouter
|
||||
- Fix dnstap test program, cleans up to have clean memory on exit,
|
||||
for tap_data_free, does not delete NULL items. Also it does not try
|
||||
to free the tail, specifically in the free of the list since that
|
||||
picked up the next item in the list for its loop causing invalid
|
||||
free. Added internal unit test to unbound-dnstap-socket for that.
|
||||
- Fix that the worker mem report with alloc stats does not attempt
|
||||
to print memory use of forwards and hints if they have been
|
||||
deleted already.
|
||||
|
||||
31 July 2024: Wouter
|
||||
- Fix for #1114: Fix that cache fill for forward-host names is
|
||||
performed, so that with nonzero target-fetch-policy it fetches
|
||||
forwarder addresses and uses them from cache. Also updated that
|
||||
delegation point cache fill routines use CDflag for AAAA message
|
||||
lookups, so that its negative lookup stops a recursion since the
|
||||
cache uses the bit for disambiguation for dns64 but the recursion
|
||||
uses CDflag for the AAAA target lookups, so the check correctly
|
||||
stops a useless recursion by its cache lookup.
|
||||
|
||||
30 July 2024: Wouter
|
||||
- Fix to document parameters of auth_zone_verify_zonemd_with_key.
|
||||
|
||||
25 July 2024: Wouter
|
||||
- Add root key 38696 from 2024 for DNSSEC validation. It is added
|
||||
to the default root keys in unbound-anchor. The content can be
|
||||
inspected with `unbound-anchor -l`.
|
||||
|
||||
23 July 2024: Yorgos
|
||||
- Fix #1106: ratelimit-below-domain logs the wrong FROM address.
|
||||
- Cleanup ede.tdir test.
|
||||
- For #935 and #1104, clarify RPZ order and semantics.
|
||||
|
||||
23 July 2024: Wouter
|
||||
- Merge #1110: Make fallthrough explicit for libworker.c.
|
||||
- For #1110: Test for fallthrough attribute in configure and add
|
||||
fallthrough attribute annotations.
|
||||
- Fix compile when the compiler does not support the noreturn
|
||||
attribute.
|
||||
- Fix to have empty definition when not supported for weak attribute.
|
||||
- Fix uninitialized variable warning in create_tcp_accept_sock.
|
||||
- Fix link of dnstap without openssl.
|
||||
- Fix link of unbound-dnstap-socket without openssl.
|
||||
|
||||
19 July 2024: Wouter
|
||||
- Add dnstap-sample-rate that logs only 1/N messages, for high volume
|
||||
server environments. Thanks Dan Luther.
|
||||
|
||||
+72
-12
@@ -187,6 +187,15 @@ server:
|
||||
# query upon encountering a CNAME record.
|
||||
# max-query-restarts: 11
|
||||
|
||||
# Limit on number of NS records in NS RRset for incoming packets.
|
||||
# iter-scrub-ns: 20
|
||||
|
||||
# Limit on number of CNAME, DNAME records for incoming packets.
|
||||
# iter-scrub-cname: 11
|
||||
|
||||
# Limit on upstream queries for an incoming query and its recursion.
|
||||
# max-global-quota: 200
|
||||
|
||||
# msec for waiting for an unknown server to reply. Increase if you
|
||||
# are behind a slow satellite link, to eg. 1128.
|
||||
# unknown-server-time-limit: 376
|
||||
@@ -206,6 +215,12 @@ server:
|
||||
# Apart from the default, the wait limit with cookie can be adjusted.
|
||||
# wait-limit-cookie-netblock: 192.0.2.0/24 50000
|
||||
|
||||
# Defaults for loopback, it has no wait limit.
|
||||
# wait-limit-netblock: 127.0.0.0/8 -1
|
||||
# wait-limit-netblock: ::1/128 -1
|
||||
# wait-limit-cookie-netblock: 127.0.0.0/8 -1
|
||||
# wait-limit-cookie-netblock: ::1/128 -1
|
||||
|
||||
# the amount of memory to use for the RRset cache.
|
||||
# plain value in bytes or you can append k, m or G. default is "4Mb".
|
||||
# rrset-cache-size: 4m
|
||||
@@ -228,7 +243,7 @@ server:
|
||||
|
||||
# the time to live (TTL) value lower bound, in seconds. Default 0.
|
||||
# For negative responses in the cache. If disabled, default,
|
||||
# cache-min-tll applies if configured.
|
||||
# cache-min-ttl applies if configured.
|
||||
# cache-min-negative-ttl: 0
|
||||
|
||||
# the time to live (TTL) value for cached roundtrip times, lameness and
|
||||
@@ -452,6 +467,10 @@ server:
|
||||
# print UTC timestamp in ascii to logfile, default is epoch in seconds.
|
||||
# log-time-ascii: no
|
||||
|
||||
# log timestamp in ISO8601 format if also log-time-ascii is enabled.
|
||||
# (y-m-dTh:m:s.msec[+-]tzhours:tzminutes)
|
||||
# log-time-iso: no
|
||||
|
||||
# print one line with time, IP, name, type, class for every query.
|
||||
# log-queries: no
|
||||
|
||||
@@ -524,6 +543,9 @@ server:
|
||||
# Harden against out of zone rrsets, to avoid spoofing attempts.
|
||||
# harden-glue: yes
|
||||
|
||||
# Harden against unverified (outside-zone, including sibling zone) glue rrsets
|
||||
# harden-unverified-glue: no
|
||||
|
||||
# Harden against receiving dnssec-stripped data. If you turn it
|
||||
# off, failing to validate dnskey data for a trustanchor will
|
||||
# trigger insecure mode for that zone (like without a trustanchor).
|
||||
@@ -540,8 +562,9 @@ server:
|
||||
# harden-referral-path: no
|
||||
|
||||
# Harden against algorithm downgrade when multiple algorithms are
|
||||
# advertised in the DS record. If no, allows the weakest algorithm
|
||||
# to validate the zone.
|
||||
# advertised in the DS record. If no, allows any algorithm
|
||||
# to validate the zone which is the standard behavior for validators.
|
||||
# Check the manpage for detailed information.
|
||||
# harden-algo-downgrade: no
|
||||
|
||||
# Harden against unknown records in the authority section and the
|
||||
@@ -714,12 +737,13 @@ server:
|
||||
# disable-edns-do: no
|
||||
|
||||
# Serve expired responses from cache, with serve-expired-reply-ttl in
|
||||
# the response, and then attempt to fetch the data afresh.
|
||||
# the response. By default it first tries to refresh an expired answer.
|
||||
# Can be configured with serve-expired-client-timeout.
|
||||
# serve-expired: no
|
||||
#
|
||||
# Limit serving of expired responses to configured seconds after
|
||||
# expiration. 0 disables the limit.
|
||||
# serve-expired-ttl: 0
|
||||
# serve-expired-ttl: 86400
|
||||
#
|
||||
# Set the TTL of expired records to the serve-expired-ttl value after a
|
||||
# failed attempt to retrieve the record from upstream. This makes sure
|
||||
@@ -732,10 +756,9 @@ server:
|
||||
#
|
||||
# Time in milliseconds before replying to the client with expired data.
|
||||
# This essentially enables the serve-stale behavior as specified in
|
||||
# RFC 8767 that first tries to resolve before
|
||||
# immediately responding with expired data. 0 disables this behavior.
|
||||
# A recommended value is 1800.
|
||||
# serve-expired-client-timeout: 0
|
||||
# RFC 8767 that first tries to resolve before immediately responding
|
||||
# with expired data. 0 disables this behavior.
|
||||
# serve-expired-client-timeout: 1800
|
||||
|
||||
# Return the original TTL as received from the upstream name server rather
|
||||
# than the decrementing TTL as stored in the cache. Enabling this feature
|
||||
@@ -794,6 +817,8 @@ server:
|
||||
# local-zone: "127.in-addr.arpa." nodefault
|
||||
# local-zone: "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa." nodefault
|
||||
# local-zone: "home.arpa." nodefault
|
||||
# local-zone: "resolver.arpa." nodefault
|
||||
# local-zone: "service.arpa." nodefault
|
||||
# local-zone: "onion." nodefault
|
||||
# local-zone: "test." nodefault
|
||||
# local-zone: "invalid." nodefault
|
||||
@@ -904,6 +929,7 @@ server:
|
||||
# tls-service-pem: "path/to/publiccertfile.pem"
|
||||
# tls-port: 853
|
||||
# https-port: 443
|
||||
# quic-port: 853
|
||||
|
||||
# cipher setting for TLSv1.2
|
||||
# tls-ciphers: "DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256"
|
||||
@@ -968,6 +994,9 @@ server:
|
||||
# Disable TLS for DNS-over-HTTP downstream service.
|
||||
# http-notls-downstream: no
|
||||
|
||||
# Maximum number of bytes used for QUIC buffers.
|
||||
# quic-size: 8m
|
||||
|
||||
# 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.
|
||||
@@ -1044,6 +1073,11 @@ server:
|
||||
# example value "000102030405060708090a0b0c0d0e0f".
|
||||
# cookie-secret: <128 bit random hex string>
|
||||
|
||||
# File with cookie secrets, the 'cookie-secret:' option is ignored
|
||||
# and the file can be managed to have staging and active secrets
|
||||
# with remote control commands. Disabled with "". Default is "".
|
||||
# cookie-secret-file: "/usr/local/etc/unbound_cookiesecrets.txt"
|
||||
|
||||
# Enable to attach Extended DNS Error codes (RFC8914) to responses.
|
||||
# ede: no
|
||||
|
||||
@@ -1052,6 +1086,11 @@ server:
|
||||
# Note that the ede option above needs to be enabled for this to work.
|
||||
# ede-serve-expired: no
|
||||
|
||||
# Enable DNS Error Reporting (RFC9567).
|
||||
# qname-minimisation is advised to be turned on as well to increase
|
||||
# privacy on the outgoing reports.
|
||||
# dns-error-reporting: no
|
||||
|
||||
# Specific options for ipsecmod. Unbound needs to be configured with
|
||||
# --enable-ipsecmod for these to take effect.
|
||||
#
|
||||
@@ -1279,15 +1318,35 @@ remote-control:
|
||||
# # redis server's TCP port
|
||||
# redis-server-port: 6379
|
||||
# # if the server uses a unix socket, set its path, or "" when not used.
|
||||
# # redis-server-path: "/var/lib/redis/redis-server.sock"
|
||||
# redis-server-path: "/var/lib/redis/redis-server.sock"
|
||||
# # if the server uses an AUTH password, specify here, or "" when not used.
|
||||
# # redis-server-password: ""
|
||||
# redis-server-password: ""
|
||||
# # timeout (in ms) for communication with the redis server
|
||||
# redis-timeout: 100
|
||||
# # timeout (in ms) for commands, if 0, uses redis-timeout.
|
||||
# redis-command-timeout: 0
|
||||
# # timeout (in ms) for connection set up, if 0, uses redis-timeout.
|
||||
# redis-connect-timeout: 0
|
||||
# # set timeout on redis records based on DNS response TTL
|
||||
# redis-expire-records: no
|
||||
# # redis logical database to use, 0 is the default database.
|
||||
# redis-logical-db: 0
|
||||
# # redis replica server's IP address or host name
|
||||
# redis-replica-server-host: 127.0.0.1
|
||||
# # redis replica server's TCP port
|
||||
# redis-replica-server-port: 6379
|
||||
# # if the replica server uses a unix socket, set its path, or "" when not used.
|
||||
# redis-replica-server-path: "/var/lib/redis/redis-server.sock"
|
||||
# # if the replica server uses an AUTH password, specify here, or "" when not used.
|
||||
# redis-replica-server-password: ""
|
||||
# # timeout (in ms) for communication with the redis replica server
|
||||
# redis-replica-timeout: 100
|
||||
# # timeout (in ms) for redis replica commands, if 0, uses redis-replica-timeout.
|
||||
# redis-replica-command-timeout: 0
|
||||
# # timeout (in ms) for redis replica connection set up, if 0, uses redis-replica-timeout.
|
||||
# redis-replica-connect-timeout: 0
|
||||
# # redis logical database to use for the replica server, 0 is the default database.
|
||||
# redis-replica-logical-db: 0
|
||||
|
||||
# IPSet
|
||||
# Add specify domain into set via ipset.
|
||||
@@ -1339,7 +1398,8 @@ remote-control:
|
||||
# dnstap-log-forwarder-response-messages: no
|
||||
|
||||
# Response Policy Zones
|
||||
# RPZ policies. Applied in order of configuration. QNAME, Response IP
|
||||
# RPZ policies. Applied in order of configuration. Any match from an earlier
|
||||
# RPZ zone will terminate the RPZ lookup. QNAME, Response IP
|
||||
# Address, nsdname, nsip and clientip triggers are supported. Supported
|
||||
# actions are: NXDOMAIN, NODATA, PASSTHRU, DROP, Local Data, tcp-only
|
||||
# and drop. Policies can be loaded from a file, or using zone
|
||||
|
||||
@@ -60,6 +60,155 @@ Reload the server but try to keep the RRset and message cache if
|
||||
That means the caches sizes and the number of threads must not change between
|
||||
reloads.
|
||||
.TP
|
||||
.B fast_reload \fR[\fI+dpv\fR]
|
||||
Reload the server, but keep downtime to a minimum, so that user queries
|
||||
keep seeing service. This needs the code compiled with threads. The config
|
||||
is loaded in a thread, and prepared, then it briefly pauses the existing
|
||||
server and updates config options. The intent is that the pause does not
|
||||
impact the service of user queries. The cache is kept. Also user queries
|
||||
worked on are kept and continue, but with the new config options.
|
||||
.IP
|
||||
This command is experimental at this time.
|
||||
.IP
|
||||
The amount of temporal memory needed during a fast_reload is twice the
|
||||
amount needed for configuration.
|
||||
This is because Unbound temporarily needs to store both current configuration
|
||||
values and new ones while trying to fast_reload.
|
||||
Zones loaded from disk (authority zones and RPZ zones) are included in such
|
||||
memory needs.
|
||||
.IP
|
||||
Options that can be changed are for
|
||||
forwards,
|
||||
stubs,
|
||||
views,
|
||||
authority zones,
|
||||
RPZ zones and
|
||||
local zones.
|
||||
.IP
|
||||
Also
|
||||
access-control and similar options,
|
||||
interface-action and similar options and
|
||||
tcp-connection-limit.
|
||||
It can reload some
|
||||
define-tag
|
||||
changes, more on that below.
|
||||
Further options include
|
||||
insecure-lan-zones,
|
||||
domain-insecure,
|
||||
trust-anchor-file,
|
||||
trust-anchor,
|
||||
trusted-keys-file,
|
||||
auto-trust-anchor-file,
|
||||
edns-client-string,
|
||||
ipset,
|
||||
log-identity,
|
||||
infra-cache-numhosts,
|
||||
msg-cache-size,
|
||||
rrset-cache-size,
|
||||
key-cache-size,
|
||||
ratelimit-size,
|
||||
neg-cache-size,
|
||||
num-queries-per-thread,
|
||||
jostle-timeout,
|
||||
use-caps-for-id,
|
||||
unwanted-reply-threshold,
|
||||
tls-use-sni,
|
||||
outgoing-tcp-mss,
|
||||
ip-dscp,
|
||||
max-reuse-tcp-queries,
|
||||
tcp-reuse-timeout,
|
||||
tcp-auth-query-timeout,
|
||||
delay-close.
|
||||
.IP
|
||||
It does not work with
|
||||
interface and
|
||||
outgoing-interface changes,
|
||||
also not with
|
||||
remote control,
|
||||
outgoing-port-permit,
|
||||
outgoing-port-avoid,
|
||||
msg-buffer-size,
|
||||
any **\*-slabs** options and
|
||||
statistics-interval changes.
|
||||
.IP
|
||||
For dnstap these options can be changed:
|
||||
dnstap-log-resolver-query-messages,
|
||||
dnstap-log-resolver-response-messages,
|
||||
dnstap-log-client-query-messages,
|
||||
dnstap-log-client-response-messages,
|
||||
dnstap-log-forwarder-query-messages and
|
||||
dnstap-log-forwarder-response-messages.
|
||||
.IP
|
||||
It does not work with these options:
|
||||
dnstap-enable,
|
||||
dnstap-bidirectional,
|
||||
dnstap-socket-path,
|
||||
dnstap-ip,
|
||||
dnstap-tls,
|
||||
dnstap-tls-server-name,
|
||||
dnstap-tls-cert-bundle,
|
||||
dnstap-tls-client-key-file and
|
||||
dnstap-tls-client-cert-file.
|
||||
.IP
|
||||
The options
|
||||
dnstap-send-identity,
|
||||
dnstap-send-version,
|
||||
dnstap-identity, and
|
||||
dnstap-version can be loaded
|
||||
when ``+p`` is not used.
|
||||
.IP
|
||||
The '+v' option makes the output verbose which includes the time it took to do
|
||||
the reload.
|
||||
With '+vv' it is more verbose which includes the amount of memory that was
|
||||
allocated temporarily to perform the reload; this amount of memory can be big
|
||||
if the config has large contents.
|
||||
In the timing output the 'reload' time is the time during which the server was
|
||||
paused.
|
||||
.IP
|
||||
The '+p' option makes the reload not pause threads, they keep running.
|
||||
Locks are acquired, but items are updated in sequence, so it is possible
|
||||
for threads to see an inconsistent state with some options from the old
|
||||
and some options from the new config, such as cache TTL parameters from the
|
||||
old config and forwards from the new config. The stubs and forwards are
|
||||
updated at the same time, so that they are viewed consistently, either old
|
||||
or new values together. The option makes the reload time take eg. 3
|
||||
microseconds instead of 0.3 milliseconds during which the worker threads are
|
||||
interrupted. So, the interruption is much shorter, at the expense of some
|
||||
inconsistency. After the reload itself, every worker thread is briefly
|
||||
contacted to make them release resources, this makes the delete timing
|
||||
a little longer, and takes up time from the remote control servicing
|
||||
worker thread.
|
||||
.IP
|
||||
With the nopause option, the reload does not work to reload some options,
|
||||
that fast reload works on without the nopause option: val-bogus-ttl,
|
||||
val-override-date, val-sig-skew-min, val-sig-skew-max, val-max-restart,
|
||||
val-nsec3-keysize-iterations, target-fetch-policy, outbound-msg-retry,
|
||||
max-sent-count, max-query-restarts, do-not-query-address,
|
||||
do-not-query-localhost, private-address, private-domain, caps-exempt,
|
||||
nat64-prefix, do-nat64, infra-host-ttl, infra-keep-probing, ratelimit,
|
||||
ip-ratelimit, ip-ratelimit-cookie, wait-limit-netblock,
|
||||
wait-limit-cookie-netblock, ratelimit-below-domain, ratelimit-for-domain.
|
||||
.IP
|
||||
The '+d' option makes the reload drop queries that the worker threads are
|
||||
working on. This is like flush_requestlist. Without it the queries are kept
|
||||
so that users keep getting answers for those queries that are currently
|
||||
processed. The drop makes it so that queries during the life time of the
|
||||
query processing see only old, or only new config options.
|
||||
.IP
|
||||
When there are changes to the config tags, from the \fBdefine\-tag\fR option,
|
||||
then the '+d' option is implicitly turned on with a warning printout, and
|
||||
queries are dropped.
|
||||
This is to stop references to the old tag information, by the old
|
||||
queries. If the number of tags is increased in the newly loaded config, by
|
||||
adding tags at the end, then the implicit '+d' option is not needed.
|
||||
.IP
|
||||
For response ip, that is actions associated with IP addresses, and perhaps
|
||||
intersected with access control tag and action information, those settings
|
||||
are stored with a query when it comes in based on its source IP address.
|
||||
The old information is kept with the query until the queries are done.
|
||||
This is gone when those queries are resolved and finished, or it is possible
|
||||
to flush the requestlist with '+d'.
|
||||
.TP
|
||||
.B verbosity \fInumber
|
||||
Change verbosity value for logging. Same values as \fBverbosity\fR keyword in
|
||||
\fIunbound.conf\fR(5). This new setting lasts until the server is issued
|
||||
@@ -350,6 +499,41 @@ Remove a list of \fIlocal_data\fR for given view from stdin. Like local_datas_re
|
||||
.TP
|
||||
.B view_local_datas \fIview\fR
|
||||
Add a list of \fIlocal_data\fR for given view from stdin. Like local_datas.
|
||||
.TP
|
||||
.B add_cookie_secret <secret>
|
||||
Add or replace a cookie secret persistently. <secret> needs to be an 128 bit
|
||||
hex string.
|
||||
.IP
|
||||
Cookie secrets can be either \fIactive\fR or \fIstaging\fR. \fIActive\fR cookie
|
||||
secrets are used to create DNS Cookies, but verification of a DNS Cookie
|
||||
succeeds with any of the \fIactive\fR or \fIstaging\fR cookie secrets. The
|
||||
state of the current cookie secrets can be printed with the
|
||||
\fBprint_cookie_secrets\fR command.
|
||||
.IP
|
||||
When there are no cookie secrets configured yet, the <secret> is added as
|
||||
\fIactive\fR. If there is already an \fIactive\fR cookie secret, the <secret>
|
||||
is added as \fIstaging\fR or replacing an existing \fIstaging\fR secret.
|
||||
.IP
|
||||
To "roll" a cookie secret used in an anycast set. The new secret has to be
|
||||
added as staging secret to \fBall\fR nodes in the anycast set. When \fBall\fR
|
||||
nodes can verify DNS Cookies with the new secret, the new secret can be
|
||||
activated with the \fBactivate_cookie_secret\fR command. After \fBall\fR nodes
|
||||
have the new secret \fIactive\fR for at least one hour, the previous secret can
|
||||
be dropped with the \fBdrop_cookie_secret\fR command.
|
||||
.IP
|
||||
Persistence is accomplished by writing to a file which if configured with the
|
||||
\fBcookie\-secret\-file\fR option in the server section of the config file.
|
||||
This is disabled by default, "".
|
||||
.TP
|
||||
.B drop_cookie_secret
|
||||
Drop the \fIstaging\fR cookie secret.
|
||||
.TP
|
||||
.B activate_cookie_secret
|
||||
Make the current \fIstaging\fR cookie secret \fIactive\fR, and the current
|
||||
\fIactive\fR cookie secret \fIstaging\fR.
|
||||
.TP
|
||||
.B print_cookie_secrets
|
||||
Show the current configured cookie secrets with their status.
|
||||
.SH "EXIT CODE"
|
||||
The unbound\-control program exits with status code 1 on error, 0 on success.
|
||||
.SH "SET UP"
|
||||
@@ -387,6 +571,12 @@ number of queries with a client part only DNS Cookie by thread
|
||||
.I threadX.num.queries_cookie_invalid
|
||||
number of queries with an invalid DNS Cookie by thread
|
||||
.TP
|
||||
.I threadX.num.queries_discard_timeout
|
||||
number of queries removed due to discard-timeout by thread
|
||||
.TP
|
||||
.I threadX.num.queries_wait_limit
|
||||
number of queries removed due to wait-limit by thread
|
||||
.TP
|
||||
.I threadX.num.cachehits
|
||||
number of queries that were successfully answered using a cache lookup
|
||||
.TP
|
||||
@@ -406,6 +596,9 @@ request for certificates.
|
||||
.I threadX.num.dnscrypt.malformed
|
||||
number of request that were neither cleartext, not valid dnscrypt messages.
|
||||
.TP
|
||||
.I threadX.num.dns_error_reports
|
||||
number of DNS Error Reports generated by thread
|
||||
.TP
|
||||
.I threadX.num.prefetch
|
||||
number of cache prefetches performed. This number is included in
|
||||
cachehits, as the original query had the unprefetched answer from cache,
|
||||
@@ -476,6 +669,12 @@ summed over threads.
|
||||
.I total.num.queries_cookie_invalid
|
||||
summed over threads.
|
||||
.TP
|
||||
.I total.num.queries_discard_timeout
|
||||
summed over threads.
|
||||
.TP
|
||||
.I total.num.queries_wait_limit
|
||||
summed over threads.
|
||||
.TP
|
||||
.I total.num.cachehits
|
||||
summed over threads.
|
||||
.TP
|
||||
@@ -494,6 +693,9 @@ summed over threads.
|
||||
.I total.num.dnscrypt.malformed
|
||||
summed over threads.
|
||||
.TP
|
||||
.I total.num.dns_error_reports
|
||||
summed over threads.
|
||||
.TP
|
||||
.I total.num.prefetch
|
||||
summed over threads.
|
||||
.TP
|
||||
@@ -571,6 +773,10 @@ queries waiting for request stream completion.
|
||||
Memory in bytes used by the HTTP/2 response buffers. Containing DNS responses
|
||||
waiting to be written back to the clients.
|
||||
.TP
|
||||
.I mem.quic
|
||||
Memory in bytes used by QUIC. Containing connection information, stream
|
||||
information, queries read and responses written back to the clients.
|
||||
.TP
|
||||
.I histogram.<sec>.<usec>.to.<sec>.<usec>
|
||||
Shows a histogram, summed over all threads. Every element counts the
|
||||
recursive queries whose reply time fit between the lower and upper bound.
|
||||
@@ -619,6 +825,10 @@ 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.quic
|
||||
Number of queries that were made using QUIC towards the Unbound server.
|
||||
These are also counted in num.query.tls, because TLS is used for these queries.
|
||||
.TP
|
||||
.I num.query.ipv6
|
||||
Number of queries that were made using IPv6 towards the Unbound server.
|
||||
.TP
|
||||
|
||||
+236
-62
@@ -326,11 +326,15 @@ The wait limit for the netblock. If not given the wait\-limit value is
|
||||
used. The most specific netblock is used to determine the limit. Useful for
|
||||
overriding the default for a specific, group or individual, server.
|
||||
The value -1 disables wait limits for the netblock.
|
||||
By default the loopback has a wait limit netblock of -1, it is not limited,
|
||||
because it is separated from the rest of network for spoofed packets.
|
||||
The loopback addresses 127.0.0.0/8 and ::1/128 are default at -1.
|
||||
.TP
|
||||
.B wait\-limit\-cookie\-netblock: \fI<netblock> <number>
|
||||
The wait limit for the netblock, when the query has a DNS cookie.
|
||||
If not given, the wait\-limit\-cookie value is used.
|
||||
The value -1 disables wait limits for the netblock.
|
||||
The loopback addresses 127.0.0.0/8 and ::1/128 are default at -1.
|
||||
.TP
|
||||
.B so\-rcvbuf: \fI<number>
|
||||
If not 0, then set the SO_RCVBUF socket option to get more buffer
|
||||
@@ -566,6 +570,9 @@ 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.
|
||||
If the tls\-upstream option is enabled, it is for all the forwards and stubs,
|
||||
where the forward\-tls\-upstream and stub\-tls\-upstream options are ignored,
|
||||
as if they had been set to yes.
|
||||
.TP
|
||||
.B ssl\-upstream: \fI<yes or no>
|
||||
Alternate syntax for \fBtls\-upstream\fR. If both are present in the config
|
||||
@@ -713,9 +720,21 @@ 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.
|
||||
There is no support for PROXYv2 on a DoH, DoQ or DNSCrypt listening interface.
|
||||
Can list multiple, each on a new statement.
|
||||
.TP
|
||||
.B quic\-port: \fI<number>
|
||||
The port number on which to provide DNS-over-QUIC service, default 853, only
|
||||
interfaces configured with that port number as @number get the QUIC service.
|
||||
The interface uses QUIC for the UDP traffic on that port number.
|
||||
.TP
|
||||
.B quic\-size: \fI<size in bytes>
|
||||
Maximum number of bytes for all QUIC buffers and data combined. Default is 8
|
||||
megabytes. A plain number is in bytes, append 'k', 'm' or 'g' for kilobytes,
|
||||
megabytes or gigabytes (1024*1024 bytes in a megabyte). New connections receive
|
||||
connection refused when the limit is exceeded. New streams are reset when the
|
||||
limit is exceeded.
|
||||
.TP
|
||||
.B use\-systemd: \fI<yes or no>
|
||||
Enable or disable systemd socket activation.
|
||||
Default is no.
|
||||
@@ -887,9 +906,8 @@ outside of the chroot directory.
|
||||
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
|
||||
enabled and the default is "@UNBOUND_CHROOT_DIR@". If you give "" no
|
||||
chroot is performed.
|
||||
If given a chroot is done to the given directory. The chroot is by default
|
||||
set to "@UNBOUND_CHROOT_DIR@". If you give "" no chroot is performed.
|
||||
.TP
|
||||
.B username: \fI<name>
|
||||
If given, after binding the port the user privileges are dropped. Default is
|
||||
@@ -936,6 +954,10 @@ Sets logfile lines to use a timestamp in UTC ascii. Default is no, which
|
||||
prints the seconds since 1970 in brackets. No effect if using syslog, in
|
||||
that case syslog formats the timestamp printed into the log files.
|
||||
.TP
|
||||
.B log\-time\-iso:\fR <yes or no>
|
||||
Log time in ISO8601 format, if \fBlog\-time\-ascii:\fR yes is also set.
|
||||
Default is no.
|
||||
.TP
|
||||
.B log\-queries: \fI<yes or no>
|
||||
Prints one line per query to the log, with the log timestamp and IP address,
|
||||
name, type and class. Default is no. Note that it takes time to print these
|
||||
@@ -1037,17 +1059,22 @@ closer to that of BIND 9, while setting "\-1 \-1 \-1 \-1 \-1" gives behaviour
|
||||
rumoured to be closer to that of BIND 8.
|
||||
.TP
|
||||
.B harden\-short\-bufsize: \fI<yes or no>
|
||||
Very small EDNS buffer sizes from queries are ignored. Default is on, as
|
||||
Very small EDNS buffer sizes from queries are ignored. Default is yes, as
|
||||
described in the standard.
|
||||
.TP
|
||||
.B harden\-large\-queries: \fI<yes or no>
|
||||
Very large queries are ignored. Default is off, since it is legal protocol
|
||||
Very large queries are ignored. Default is no, since it is legal protocol
|
||||
wise to send these, and could be necessary for operation if TSIG or EDNS
|
||||
payload is very large.
|
||||
.TP
|
||||
.B harden\-glue: \fI<yes or no>
|
||||
Will trust glue only if it is within the servers authority. Default is yes.
|
||||
.TP
|
||||
.B harden\-unverified\-glue: \fI<yes or no>
|
||||
Will trust only in-zone glue. Will try to resolve all out of zone
|
||||
(\fI<unverfied>) glue. Will fallback to the original glue if unable to resolve.
|
||||
Default is no.
|
||||
.TP
|
||||
.B harden\-dnssec\-stripped: \fI<yes or no>
|
||||
Require DNSSEC data for trust\-anchored zones, if such data is absent,
|
||||
the zone becomes bogus. If turned off, and no DNSSEC data is received
|
||||
@@ -1083,10 +1110,23 @@ to increase the max depth that is checked to.
|
||||
.TP
|
||||
.B harden\-algo\-downgrade: \fI<yes or no>
|
||||
Harden against algorithm downgrade when multiple algorithms are
|
||||
advertised in the DS record. If no, allows the weakest algorithm to
|
||||
validate the zone. Default is no. Zone signers must produce zones
|
||||
that allow this feature to work, but sometimes they do not, and turning
|
||||
this option off avoids that validation failure.
|
||||
advertised in the DS record.
|
||||
This works by first choosing only the strongest DS digest type as per RFC 4509
|
||||
(Unbound treats the highest algorithm as the strongest) and then
|
||||
expecting signatures from all the advertised signing algorithms from the chosen
|
||||
DS(es) to be present.
|
||||
If no, allows any one supported algorithm to validate the zone, even if other advertised algorithms are broken.
|
||||
Default is no.
|
||||
RFC 6840 mandates that zone signers must produce zones signed with all
|
||||
advertised algorithms, but sometimes they do not.
|
||||
RFC 6840 also clarifies that this requirement is not for validators and
|
||||
validators should accept any single valid path.
|
||||
It should thus be explicitly noted that this option violates RFC 6840 for
|
||||
DNSSEC validation and should only be used to perform a signature
|
||||
completeness test to support troubleshooting.
|
||||
Using this option may break DNSSEC resolution with non-RFC6840-conforming
|
||||
signers and/or in multi-signer configurations that don't send all the
|
||||
advertised signatures.
|
||||
.TP
|
||||
.B harden\-unknown\-additional: \fI<yes or no>
|
||||
Harden against unknown records in the authority section and additional
|
||||
@@ -1107,7 +1147,7 @@ queries. For domains that do not support 0x20 and also fail with fallback
|
||||
because they keep sending different answers, like some load balancers.
|
||||
Can be given multiple times, for different domains.
|
||||
.TP
|
||||
.B caps\-whitelist: \fI<yes or no>
|
||||
.B caps\-whitelist: \fI<domain>
|
||||
Alternate syntax for \fBcaps\-exempt\fR.
|
||||
.TP
|
||||
.B qname\-minimisation: \fI<yes or no>
|
||||
@@ -1171,10 +1211,11 @@ IP6 ::1 and IP4 127.0.0.1/8. If no, then localhost can be used to send
|
||||
queries to. Default is yes.
|
||||
.TP
|
||||
.B prefetch: \fI<yes or no>
|
||||
If yes, message cache elements are prefetched before they expire to
|
||||
keep the cache up to date. Default is no. Turning it on gives about
|
||||
10 percent more traffic and load on the machine, but popular items do
|
||||
not expire from the cache.
|
||||
If yes, cache hits on message cache elements that are on their last 10 percent
|
||||
of their TTL value trigger a prefetch to keep the cache up to date.
|
||||
Default is no.
|
||||
Turning it on gives about 10 percent more traffic and load on the machine, but
|
||||
popular items do not expire from the cache.
|
||||
.TP
|
||||
.B prefetch\-key: \fI<yes or no>
|
||||
If yes, fetch the DNSKEYs earlier in the validation process, when a DS
|
||||
@@ -1194,12 +1235,13 @@ from the query ID, for speed and thread safety). Default is yes.
|
||||
.B minimal-responses: \fI<yes or no>
|
||||
If yes, Unbound does not insert authority/additional sections into response
|
||||
messages when those sections are not required. This reduces response
|
||||
size significantly, and may avoid TCP fallback for some responses.
|
||||
This may cause a slight speedup. The default is yes, even though the DNS
|
||||
size significantly, and may avoid TCP fallback for some responses which may
|
||||
cause a slight speedup. The default is yes, even though the DNS
|
||||
protocol RFCs mandate these sections, and the additional content could
|
||||
be of use and save roundtrips for clients. Because they are not used,
|
||||
and the saved roundtrips are easier saved with prefetch, whilst this is
|
||||
faster.
|
||||
save roundtrips for clients that use the additional content.
|
||||
However these sections are hardly used by clients.
|
||||
Enabling prefetch can benefit clients that need the additional content
|
||||
by trying to keep that content fresh in the cache.
|
||||
.TP
|
||||
.B disable-dnssec-lame-check: \fI<yes or no>
|
||||
If true, disables the DNSSEC lameness check in the iterator. This check
|
||||
@@ -1222,9 +1264,6 @@ Adding \fIrespip\fR to the front will cause RPZ processing to be done on
|
||||
all queries.
|
||||
The default is "\fIvalidator iterator\fR".
|
||||
.IP
|
||||
When the server is built with
|
||||
EDNS client subnet support the default is "\fIsubnetcache validator
|
||||
iterator\fR".
|
||||
Most modules that need to be listed here have to be listed at the beginning
|
||||
of the line. The subnetcachedb module has to be listed just before
|
||||
the iterator.
|
||||
@@ -1364,15 +1403,17 @@ Default is no.
|
||||
.TP
|
||||
.B serve\-expired: \fI<yes or no>
|
||||
If enabled, Unbound attempts to serve old responses from cache with a
|
||||
TTL of \fBserve\-expired\-reply\-ttl\fR in the response without waiting for the
|
||||
actual resolution to finish. The actual resolution answer ends up in the cache
|
||||
later on. Default is "no".
|
||||
TTL of \fBserve\-expired\-reply\-ttl\fR in the response.
|
||||
By default the expired answer will be used after a resolution attempt errored
|
||||
out or is taking more than serve\-expired\-client\-timeout to resolve.
|
||||
Default is "no".
|
||||
.TP
|
||||
.B serve\-expired\-ttl: \fI<seconds>
|
||||
Limit serving of expired responses to configured seconds after expiration. 0
|
||||
disables the limit. This option only applies when \fBserve\-expired\fR is
|
||||
enabled. A suggested value per RFC 8767 is between
|
||||
86400 (1 day) and 259200 (3 days). The default is 0.
|
||||
Limit serving of expired responses to configured seconds after expiration.
|
||||
0 disables the limit.
|
||||
This option only applies when \fBserve\-expired\fR is enabled.
|
||||
A suggested value per RFC 8767 is between 86400 (1 day) and 259200 (3 days).
|
||||
The default is 86400.
|
||||
.TP
|
||||
.B serve\-expired\-ttl\-reset: \fI<yes or no>
|
||||
Set the TTL of expired records to the \fBserve\-expired\-ttl\fR value after a
|
||||
@@ -1386,12 +1427,14 @@ TTL value to use when replying with expired data. If
|
||||
use 30 as the value (RFC 8767). The default is 30.
|
||||
.TP
|
||||
.B serve\-expired\-client\-timeout: \fI<msec>
|
||||
Time in milliseconds before replying to the client with expired data. This
|
||||
essentially enables the serve-stale behavior as specified in
|
||||
Time in milliseconds before replying to the client with expired data.
|
||||
This essentially enables the serve-stale behavior as specified in
|
||||
RFC 8767 that first tries to resolve before immediately
|
||||
responding with expired data. A recommended value per
|
||||
RFC 8767 is 1800. Setting this to 0 will disable this
|
||||
behavior. Default is 0.
|
||||
responding with expired data.
|
||||
Setting this to 0 will disable this behavior and instead serve the expired
|
||||
record immediately from the cache before attempting to refresh it via
|
||||
resolution.
|
||||
Default is 1800.
|
||||
.TP
|
||||
.B serve\-original\-ttl: \fI<yes or no>
|
||||
If enabled, Unbound will always return the original TTL as received from
|
||||
@@ -1596,6 +1639,7 @@ given zone. Use \fInodefault\fR if you use exactly that zone, if you want to
|
||||
use a subzone, use \fItransparent\fR.
|
||||
.P
|
||||
The default zones are localhost, reverse 127.0.0.1 and ::1, the home.arpa,
|
||||
the resolver.arpa, the service.arpa,
|
||||
the onion, test, invalid and the AS112 zones. The AS112 zones are reverse
|
||||
DNS zones for private use and reserved IP addresses for which the servers
|
||||
on the internet cannot provide correct answers. They are configured by
|
||||
@@ -1651,6 +1695,24 @@ local\-data: "home.arpa. 10800 IN
|
||||
SOA localhost. nobody.invalid. 1 3600 1200 604800 10800"
|
||||
.fi
|
||||
.TP 10
|
||||
\h'5'\fIresolver.arpa (RFC 9462)\fR
|
||||
Default content:
|
||||
.nf
|
||||
local\-zone: "resolver.arpa." static
|
||||
local\-data: "resolver.arpa. 10800 IN NS localhost."
|
||||
local\-data: "resolver.arpa. 10800 IN
|
||||
SOA localhost. nobody.invalid. 1 3600 1200 604800 10800"
|
||||
.fi
|
||||
.TP 10
|
||||
\h'5'\fIservice.arpa (draft-ietf-dnssd-srp-25)\fR
|
||||
Default content:
|
||||
.nf
|
||||
local\-zone: "service.arpa." static
|
||||
local\-data: "service.arpa. 10800 IN NS localhost."
|
||||
local\-data: "service.arpa. 10800 IN
|
||||
SOA localhost. nobody.invalid. 1 3600 1200 604800 10800"
|
||||
.fi
|
||||
.TP 10
|
||||
\h'5'\fIonion (RFC 7686)\fR
|
||||
Default content:
|
||||
.nf
|
||||
@@ -1957,6 +2019,23 @@ Changing this value needs caution as it can allow long CNAME chains to be
|
||||
accepted, where Unbound needs to verify (resolve) each link individually.
|
||||
Default is 11.
|
||||
.TP 5
|
||||
.B iter\-scrub\-ns: \fI<number>
|
||||
Limit on the number of NS records allowed in an rrset of type NS, from the
|
||||
iterator scrubber. This protects the internals of the resolver from overly
|
||||
large NS sets. Default is 20.
|
||||
.TP 5
|
||||
.B iter\-scrub\-cname: \fI<number>
|
||||
Limit on the number of CNAME, DNAME records in an answer, from the iterator
|
||||
scrubber. This protects the internals of the resolver from overly long
|
||||
indirection chains. Clips off the remainder of the reply packet at that point.
|
||||
Default is 11.
|
||||
.TP 5
|
||||
.B max\-global\-quota: \fI<number>
|
||||
Limit on the number of upstream queries sent out for an incoming query and
|
||||
its subqueries from recursion. It is not reset during the resolution. When
|
||||
it is exceeded the query is failed and the lookup process stops.
|
||||
Default is 200.
|
||||
.TP 5
|
||||
.B fast\-server\-permil: \fI<number>
|
||||
Specify how many times out of 1000 to pick from the set of fastest servers.
|
||||
0 turns the feature off. A value of 900 would pick from the fastest
|
||||
@@ -1983,6 +2062,20 @@ Useful to explicitly set for servers in an anycast deployment that need to
|
||||
share the secret in order to verify each other's Server Cookies.
|
||||
An example hex string would be "000102030405060708090a0b0c0d0e0f".
|
||||
Default is a 128 bits random secret generated at startup time.
|
||||
This option is ignored if a \fBcookie\-secret\-file\fR is
|
||||
present. In that case the secrets from that file are used in DNS Cookie
|
||||
calculations.
|
||||
.TP 5
|
||||
.B cookie\-secret\-file: \fI<filename>
|
||||
File from which the secrets are read used in DNS Cookie calculations. When this
|
||||
file exists, the secrets in this file are used and the secret specified by the
|
||||
\fBcookie-secret\fR option is ignored.
|
||||
Enable it by setting a filename, like "/usr/local/etc/unbound_cookiesecrets.txt".
|
||||
The content of this file must be manipulated with the \fBadd_cookie_secret\fR,
|
||||
\fBdrop_cookie_secret\fR and \fBactivate_cookie_secret\fR commands to the
|
||||
\fIunbound\-control\fR(8) tool. Please see that manpage on how to perform a
|
||||
safe cookie secret rollover.
|
||||
Default is "" (disabled).
|
||||
.TP 5
|
||||
.B edns\-client\-string: \fI<IP netblock> <string>
|
||||
Include an EDNS0 option containing configured ascii string in queries with
|
||||
@@ -1996,17 +2089,30 @@ 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".
|
||||
These EDEs provide additional information with a response mainly for, but not
|
||||
limited to, DNS and DNSSEC errors.
|
||||
|
||||
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.
|
||||
Extended DNS Errors concerning DNSSEC failures will also contain a descriptive
|
||||
text message about the reason for the failure.
|
||||
Default is "no".
|
||||
.TP 5
|
||||
.B ede\-serve\-expired: \fI<yes or no>
|
||||
If enabled, Unbound will attach an Extended DNS Error (RFC8914) Code 3 - Stale
|
||||
Answer as EDNS0 option to the expired response. Note that this will not attach
|
||||
the EDE code without setting the global \fBede\fR option to "yes" as well.
|
||||
Answer as EDNS0 option to the expired response.
|
||||
The \fBede\fR option needs to be enabled as well for this to work.
|
||||
Default is "no".
|
||||
.TP 5
|
||||
.B dns\-error\-reporting: \fI<yes or no>
|
||||
If enabled, Unbound will send DNS Error Reports (RFC9567).
|
||||
The name servers need to express support by attaching the Report-Channel EDNS0
|
||||
option on their replies specifying the reporting agent for the zone.
|
||||
Any errors encountered during resolution that would result in Unbound
|
||||
generating an Extended DNS Error (RFC8914) will be reported to the zone's
|
||||
reporting agent.
|
||||
The \fBede\fR option does not need to be enabled for this to work.
|
||||
It is advised that the \fBqname\-minimisation\fR option is also enabled to
|
||||
increase privacy on the outgoing reports.
|
||||
Default is "no".
|
||||
.SS "Remote Control Options"
|
||||
In the
|
||||
@@ -2419,8 +2525,8 @@ The dynamic library file to load. Repeat this option for every dynlib module
|
||||
instance added to the \fBmodule\-config:\fR option.
|
||||
.SS "DNS64 Module Options"
|
||||
.LP
|
||||
The dns64 module must be configured in the \fBmodule\-config:\fR "dns64
|
||||
validator iterator" directive and be compiled into the daemon to be
|
||||
The dns64 module must be configured in the \fBmodule\-config:\fR directive
|
||||
e.g., "dns64 validator iterator" and be compiled into the daemon to be
|
||||
enabled. These settings go in the \fBserver:\fR section.
|
||||
.TP
|
||||
.B dns64\-prefix: \fI<IPv6 prefix>\fR
|
||||
@@ -2520,8 +2626,8 @@ in the dnscrypt nonce cache. Close to the number of cpus is
|
||||
a fairly good setting.
|
||||
.SS "EDNS Client Subnet Module Options"
|
||||
.LP
|
||||
The ECS module must be configured in the \fBmodule\-config:\fR "subnetcache
|
||||
validator iterator" directive and be compiled into the daemon to be
|
||||
The ECS module must be configured in the \fBmodule\-config:\fR directive e.g.,
|
||||
"subnetcache validator iterator" and be compiled into the daemon to be
|
||||
enabled. These settings go in the \fBserver:\fR section.
|
||||
.LP
|
||||
If the destination address is allowed in the configuration Unbound will add the
|
||||
@@ -2542,6 +2648,15 @@ configuration file. On top of that, for each query only 100 different subnets
|
||||
are allowed to be stored for each address family. Exceeding that number, older
|
||||
entries will be purged from cache.
|
||||
.LP
|
||||
Note that due to the nature of how EDNS Client Subnet works, by segregating the
|
||||
client IP space in order to try and have tailored responses for prefixes of
|
||||
unknown sizes, resolution and cache response performance are impacted as a
|
||||
result.
|
||||
Usage of the subnetcache module should only be enabled in installations that
|
||||
require such functionality where the resolver and the clients belong to
|
||||
different networks.
|
||||
An example of that is an open resolver installation.
|
||||
.LP
|
||||
This module does not interact with the \fBserve\-expired*\fR and
|
||||
\fBprefetch:\fR options.
|
||||
.TP
|
||||
@@ -2592,8 +2707,8 @@ Specifies the maximum number of subnets ECS answers kept in the ECS radix tree.
|
||||
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 Unbound by using
|
||||
The IPsec module must be configured in the \fBmodule\-config:\fR directive
|
||||
e.g., "ipsecmod validator iterator" and be compiled into Unbound by using
|
||||
\fB\-\-enable\-ipsecmod\fR to be enabled.
|
||||
These settings go in the \fBserver:\fR section.
|
||||
.LP
|
||||
@@ -2658,12 +2773,12 @@ Allow the ipsecmod functionality for the domain so that the module logic will be
|
||||
executed. Can be given multiple times, for different domains. If the option is
|
||||
not specified, all domains are treated as being allowed (default).
|
||||
.TP
|
||||
.B ipsecmod\-whitelist: \fI<yes or no>
|
||||
.B ipsecmod\-whitelist: \fI<domain>
|
||||
Alternate syntax for \fBipsecmod\-allow\fR.
|
||||
.SS "Cache DB Module Options"
|
||||
.LP
|
||||
The Cache DB module must be configured in the \fBmodule\-config:\fR
|
||||
"validator cachedb iterator" directive and be compiled into the daemon
|
||||
The Cache DB module must be configured in the \fBmodule\-config:\fR directive
|
||||
e.g., "validator cachedb iterator" and be compiled into the daemon
|
||||
with \fB\-\-enable\-cachedb\fR.
|
||||
If this module is enabled and configured, the specified backend database
|
||||
works as a second level cache:
|
||||
@@ -2758,12 +2873,12 @@ The TCP port number of the Redis server.
|
||||
This option defaults to 6379.
|
||||
.TP
|
||||
.B redis-server-path: \fI<unix socket path>\fR
|
||||
The unix socket path to connect to the redis server. Off by default, and it
|
||||
The unix socket path to connect to the Redis server. Off by default, and it
|
||||
can be set to "" to turn this off. Unix sockets may have better throughput
|
||||
than the IP address option.
|
||||
.TP
|
||||
.B redis-server-password: \fI"<password>"\fR
|
||||
The Redis AUTH password to use for the redis server.
|
||||
The Redis AUTH password to use for the Redis server.
|
||||
Only relevant if Redis is configured for client password authorisation.
|
||||
Off by default, and it can be set to "" to turn this off.
|
||||
.TP
|
||||
@@ -2774,6 +2889,16 @@ if the Redis server does not have the requested data, and will try to
|
||||
re-establish a new connection later.
|
||||
This option defaults to 100 milliseconds.
|
||||
.TP
|
||||
.B redis-command-timeout: \fI<msec>\fR
|
||||
The timeout to use for Redis commands, in milliseconds.
|
||||
If 0, it uses the \fBredis\-timeout\fR value.
|
||||
The default is 0.
|
||||
.TP
|
||||
.B redis-connect-timeout: \fI<msec>\fR
|
||||
The timeout to use for Redis connection set up, in milliseconds.
|
||||
If 0, it uses the \fBredis\-timeout\fR value.
|
||||
The default is 0.
|
||||
.TP
|
||||
.B redis-expire-records: \fI<yes or no>
|
||||
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
|
||||
@@ -2792,6 +2917,52 @@ for multiple unrelated applications.
|
||||
The default database in Redis is 0 while other logical databases need to be
|
||||
explicitly SELECT'ed upon connecting.
|
||||
This option defaults to 0.
|
||||
.TP
|
||||
.B redis-replica-server-host: \fI<server address or name>\fR
|
||||
The IP (either v6 or v4) address or domain name of the Redis replica server.
|
||||
In general an IP address should be specified as otherwise Unbound will have to
|
||||
resolve the name of the server every time it establishes a connection
|
||||
to the server.
|
||||
This server is treated as a read-only replica server
|
||||
(https://redis.io/docs/management/replication/#read-only-replica).
|
||||
If specified, all Redis read commands will go to this replica server, while
|
||||
the write commands will go to the \fBredis-server-host\fR.
|
||||
This option defaults to "" (disabled).
|
||||
.TP
|
||||
.B redis-replica-server-port: \fI<port number>\fR
|
||||
The TCP port number of the Redis replica server.
|
||||
This option defaults to 6379.
|
||||
.TP
|
||||
.B redis-replica-server-path: \fI<unix socket path>\fR
|
||||
The unix socket path to connect to the Redis server. Off by default, and it
|
||||
can be set to "" to turn this off. Unix sockets may have better throughput
|
||||
than the IP address option.
|
||||
.TP
|
||||
.B redis-replica-server-password: \fI"<password>"\fR
|
||||
The Redis AUTH password to use for the Redis replica server.
|
||||
Only relevant if Redis is configured for client password authorisation.
|
||||
Off by default, and it can be set to "" to turn this off.
|
||||
.TP
|
||||
.B redis-replica-timeout: \fI<msec>\fR
|
||||
The period until when Unbound waits for a response from the Redis replica sever.
|
||||
If this timeout expires Unbound closes the connection, treats it as
|
||||
if the Redis replica server does not have the requested data, and will try to
|
||||
re-establish a new connection later.
|
||||
This option defaults to 100 milliseconds.
|
||||
.TP
|
||||
.B redis-replica-command-timeout: \fI<msec>\fR
|
||||
The timeout to use for Redis replica commands, in milliseconds.
|
||||
If 0, it uses the \fBredis\-replica\-timeout\fR value.
|
||||
The default is 0.
|
||||
.TP
|
||||
.B redis-replica-connect-timeout: \fI<msec>\fR
|
||||
The timeout to use for Redis replica connection set up, in milliseconds.
|
||||
If 0, it uses the \fBredis\-replica\-timeout\fR value.
|
||||
The default is 0.
|
||||
.TP
|
||||
.B redis-replica-logical-db: \fI<logical database index>
|
||||
Same as \fBredis-logical-db\fR but for the Redis replica server.
|
||||
This option defaults to 0.
|
||||
.SS DNSTAP Logging Options
|
||||
DNSTAP support, when compiled in by using \fB\-\-enable\-dnstap\fR, is enabled
|
||||
in the \fBdnstap:\fR section.
|
||||
@@ -2883,9 +3054,11 @@ Enable to log forwarder response messages. Default is no.
|
||||
.SS Response Policy Zone Options
|
||||
.LP
|
||||
Response Policy Zones are configured with \fBrpz:\fR, and each one must have a
|
||||
\fBname:\fR. There can be multiple ones, by listing multiple rpz clauses, each
|
||||
with a different name. RPZ clauses are applied in order of configuration. The
|
||||
\fBrespip\fR module needs to be added to the \fBmodule-config\fR, e.g.:
|
||||
\fBname:\fR. There can be multiple ones, by listing multiple RPZ clauses, each
|
||||
with a different name. RPZ clauses are applied in order of configuration and
|
||||
any match from an earlier RPZ zone will terminate the RPZ lookup. Note that a
|
||||
PASSTHRU action is still considered a match.
|
||||
The \fBrespip\fR module needs to be added to the \fBmodule-config\fR, e.g.:
|
||||
\fBmodule-config: "respip validator iterator"\fR.
|
||||
.P
|
||||
QNAME, Response IP Address, nsdname, nsip and clientip triggers are supported.
|
||||
@@ -2893,12 +3066,13 @@ Supported actions are: NXDOMAIN, NODATA, PASSTHRU, DROP, Local Data, tcp\-only
|
||||
and drop. RPZ QNAME triggers are applied after \fBlocal\-zones\fR and
|
||||
before \fBauth\-zones\fR.
|
||||
.P
|
||||
The rpz zone is formatted with a SOA start record as usual. The items in
|
||||
the zone are entries, that specify what to act on (the trigger) and what to
|
||||
do (the action). The trigger to act on is recorded in the name, the action
|
||||
to do is recorded as the resource record. The names all end in the zone
|
||||
name, so you could type the trigger names without a trailing dot in the
|
||||
zonefile.
|
||||
The RPZ zone is a regular DNS zone formatted with a SOA start record as usual.
|
||||
The items in the zone are entries, that specify what to act on (the trigger)
|
||||
and what to do (the action).
|
||||
The trigger to act on is recorded in the name, the action to do is recorded as
|
||||
the resource record.
|
||||
The names all end in the zone name, so you could type the trigger names without
|
||||
a trailing dot in the zonefile.
|
||||
.P
|
||||
An example RPZ record, that answers example.com with NXDOMAIN
|
||||
.nf
|
||||
@@ -2998,7 +3172,7 @@ externally blocked. Default is 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.
|
||||
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
|
||||
|
||||
+4
-4
@@ -1226,7 +1226,7 @@ VERBATIM_HEADERS = NO
|
||||
# generated with the -Duse_libclang=ON option for CMake.
|
||||
# The default value is: NO.
|
||||
|
||||
CLANG_ASSISTED_PARSING = NO
|
||||
#CLANG_ASSISTED_PARSING = NO
|
||||
|
||||
# If the CLANG_ASSISTED_PARSING tag is set to YES and the CLANG_ADD_INC_PATHS
|
||||
# tag is set to YES then doxygen will add the directory of each input to the
|
||||
@@ -1234,7 +1234,7 @@ CLANG_ASSISTED_PARSING = NO
|
||||
# The default value is: YES.
|
||||
# This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES.
|
||||
|
||||
CLANG_ADD_INC_PATHS = YES
|
||||
#CLANG_ADD_INC_PATHS = YES
|
||||
|
||||
# If clang assisted parsing is enabled you can provide the compiler with command
|
||||
# line options that you would normally use when invoking the compiler. Note that
|
||||
@@ -1242,7 +1242,7 @@ CLANG_ADD_INC_PATHS = YES
|
||||
# specified with INPUT and INCLUDE_PATH.
|
||||
# This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES.
|
||||
|
||||
CLANG_OPTIONS =
|
||||
#CLANG_OPTIONS =
|
||||
|
||||
# If clang assisted parsing is enabled you can provide the clang parser with the
|
||||
# path to the directory containing a file called compile_commands.json. This
|
||||
@@ -1255,7 +1255,7 @@ CLANG_OPTIONS =
|
||||
# Note: The availability of this option depends on whether or not doxygen was
|
||||
# generated with the -Duse_libclang=ON option for CMake.
|
||||
|
||||
CLANG_DATABASE_PATH =
|
||||
#CLANG_DATABASE_PATH =
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the alphabetical class index
|
||||
|
||||
+2
-1
@@ -456,7 +456,8 @@ 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, qstate->qstarttime)) {
|
||||
0, qstate->region, qstate->query_flags, qstate->qstarttime,
|
||||
qstate->is_valrec)) {
|
||||
log_err("ipsecmod: out of memory caching record");
|
||||
}
|
||||
qstate->ext_state[id] = module_finished;
|
||||
|
||||
@@ -278,7 +278,7 @@ delegpt_count_addr(struct delegpt* dp, size_t* numaddr, size_t* numres,
|
||||
|
||||
void delegpt_log(enum verbosity_value v, struct delegpt* dp)
|
||||
{
|
||||
char buf[LDNS_MAX_DOMAINLEN+1];
|
||||
char buf[LDNS_MAX_DOMAINLEN];
|
||||
struct delegpt_ns* ns;
|
||||
struct delegpt_addr* a;
|
||||
size_t missing=0, numns=0, numaddr=0, numres=0, numavail=0;
|
||||
|
||||
+51
-1
@@ -129,7 +129,7 @@ forwards_insert_data(struct iter_forwards* fwd, uint16_t c, uint8_t* nm,
|
||||
node->namelabs = nmlabs;
|
||||
node->dp = dp;
|
||||
if(!rbtree_insert(fwd->tree, &node->node)) {
|
||||
char buf[257];
|
||||
char buf[LDNS_MAX_DOMAINLEN];
|
||||
dname_str(nm, buf);
|
||||
log_err("duplicate forward zone %s ignored.", buf);
|
||||
delegpt_free_mlc(dp);
|
||||
@@ -331,6 +331,30 @@ make_stub_holes(struct iter_forwards* fwd, struct config_file* cfg)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** make NULL entries for auths */
|
||||
static int
|
||||
make_auth_holes(struct iter_forwards* fwd, struct config_file* cfg)
|
||||
{
|
||||
struct config_auth* a;
|
||||
uint8_t* dname;
|
||||
size_t dname_len;
|
||||
for(a = cfg->auths; a; a = a->next) {
|
||||
if(!a->name) continue;
|
||||
dname = sldns_str2wire_dname(a->name, &dname_len);
|
||||
if(!dname) {
|
||||
log_err("cannot parse auth name '%s'", a->name);
|
||||
return 0;
|
||||
}
|
||||
if(!fwd_add_stub_hole(fwd, LDNS_RR_CLASS_IN, dname)) {
|
||||
free(dname);
|
||||
log_err("out of memory");
|
||||
return 0;
|
||||
}
|
||||
free(dname);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
forwards_apply_cfg(struct iter_forwards* fwd, struct config_file* cfg)
|
||||
{
|
||||
@@ -353,6 +377,16 @@ forwards_apply_cfg(struct iter_forwards* fwd, struct config_file* cfg)
|
||||
lock_rw_unlock(&fwd->lock);
|
||||
return 0;
|
||||
}
|
||||
/* TODO: Now we punch holes for auth zones as well so that in
|
||||
* iterator:forward_request() we see the configured
|
||||
* delegation point, but code flow/naming is hard to follow.
|
||||
* Consider having a single tree with configured
|
||||
* delegation points for all categories
|
||||
* (stubs, forwards, auths). */
|
||||
if(!make_auth_holes(fwd, cfg)) {
|
||||
lock_rw_unlock(&fwd->lock);
|
||||
return 0;
|
||||
}
|
||||
fwd_init_parents(fwd);
|
||||
lock_rw_unlock(&fwd->lock);
|
||||
return 1;
|
||||
@@ -590,3 +624,19 @@ forwards_delete_stub_hole(struct iter_forwards* fwd, uint16_t c,
|
||||
fwd_init_parents(fwd);
|
||||
if(!nolock) { lock_rw_unlock(&fwd->lock); }
|
||||
}
|
||||
|
||||
void
|
||||
forwards_swap_tree(struct iter_forwards* fwd, struct iter_forwards* data)
|
||||
{
|
||||
rbtree_type* oldtree = fwd->tree;
|
||||
if(oldtree) {
|
||||
lock_unprotect(&fwd->lock, oldtree);
|
||||
}
|
||||
if(data->tree) {
|
||||
lock_unprotect(&data->lock, data->tree);
|
||||
}
|
||||
fwd->tree = data->tree;
|
||||
data->tree = oldtree;
|
||||
lock_protect(&fwd->lock, fwd->tree, sizeof(*fwd->tree));
|
||||
lock_protect(&data->lock, data->tree, sizeof(*data->tree));
|
||||
}
|
||||
|
||||
@@ -234,4 +234,13 @@ int forwards_add_stub_hole(struct iter_forwards* fwd, uint16_t c,
|
||||
void forwards_delete_stub_hole(struct iter_forwards* fwd, uint16_t c,
|
||||
uint8_t* nm, int nolock);
|
||||
|
||||
/**
|
||||
* Swap internal tree with preallocated entries. Caller should manage
|
||||
* the locks.
|
||||
* @param fwd: the forward data structure.
|
||||
* @param data: the data structure used to take elements from. This contains
|
||||
* the old elements on return.
|
||||
*/
|
||||
void forwards_swap_tree(struct iter_forwards* fwd, struct iter_forwards* data);
|
||||
|
||||
#endif /* ITERATOR_ITER_FWD_H */
|
||||
|
||||
+12
-1
@@ -181,7 +181,7 @@ hints_insert(struct iter_hints* hints, uint16_t c, struct delegpt* dp,
|
||||
node->noprime = (uint8_t)noprime;
|
||||
if(!name_tree_insert(&hints->tree, &node->node, dp->name, dp->namelen,
|
||||
dp->namelabs, c)) {
|
||||
char buf[257];
|
||||
char buf[LDNS_MAX_DOMAINLEN];
|
||||
dname_str(dp->name, buf);
|
||||
log_err("second hints for zone %s ignored.", buf);
|
||||
delegpt_free_mlc(dp);
|
||||
@@ -611,3 +611,14 @@ hints_delete_stub(struct iter_hints* hints, uint16_t c, uint8_t* nm,
|
||||
name_tree_init_parents(&hints->tree);
|
||||
if(!nolock) { lock_rw_unlock(&hints->lock); }
|
||||
}
|
||||
|
||||
void
|
||||
hints_swap_tree(struct iter_hints* hints, struct iter_hints* data)
|
||||
{
|
||||
rbnode_type* oldroot = hints->tree.root;
|
||||
size_t oldcount = hints->tree.count;
|
||||
hints->tree.root = data->tree.root;
|
||||
hints->tree.count = data->tree.count;
|
||||
data->tree.root = oldroot;
|
||||
data->tree.count = oldcount;
|
||||
}
|
||||
|
||||
@@ -198,4 +198,13 @@ int hints_add_stub(struct iter_hints* hints, uint16_t c, struct delegpt* dp,
|
||||
void hints_delete_stub(struct iter_hints* hints, uint16_t c,
|
||||
uint8_t* nm, int nolock);
|
||||
|
||||
/**
|
||||
* Swap internal tree with preallocated entries. Caller should manage
|
||||
* the locks.
|
||||
* @param hints: the hints data structure.
|
||||
* @param data: the data structure used to take elements from. This contains
|
||||
* the old elements on return.
|
||||
*/
|
||||
void hints_swap_tree(struct iter_hints* hints, struct iter_hints* data);
|
||||
|
||||
#endif /* ITERATOR_ITER_HINTS_H */
|
||||
|
||||
@@ -367,6 +367,47 @@ type_allowed_in_additional_section(uint16_t tp)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Shorten RRset */
|
||||
static void
|
||||
shorten_rrset(sldns_buffer* pkt, struct rrset_parse* rrset, int count)
|
||||
{
|
||||
/* The too large NS RRset is shortened. This is so that too large
|
||||
* content does not overwhelm the cache. It may make the rrset
|
||||
* bogus if it was signed, and then the domain is not resolved any
|
||||
* more, that is okay, the NS RRset was too large. During a referral
|
||||
* it can be shortened and then the first part of the list could
|
||||
* be used to resolve. The scrub continues to disallow glue for the
|
||||
* removed nameserver RRs and removes that too. Because the glue
|
||||
* is not marked as okay, since the RRs have been removed here. */
|
||||
int i;
|
||||
struct rr_parse* rr = rrset->rr_first, *prev = NULL;
|
||||
if(!rr)
|
||||
return;
|
||||
for(i=0; i<count; i++) {
|
||||
prev = rr;
|
||||
rr = rr->next;
|
||||
if(!rr)
|
||||
return; /* The RRset is already short. */
|
||||
}
|
||||
if(verbosity >= VERB_QUERY
|
||||
&& rrset->dname_len <= LDNS_MAX_DOMAINLEN) {
|
||||
uint8_t buf[LDNS_MAX_DOMAINLEN+1];
|
||||
dname_pkt_copy(pkt, buf, rrset->dname);
|
||||
log_nametypeclass(VERB_QUERY, "normalize: shorten RRset:", buf,
|
||||
rrset->type, ntohs(rrset->rrset_class));
|
||||
}
|
||||
/* remove further rrs */
|
||||
rrset->rr_last = prev;
|
||||
rrset->rr_count = count;
|
||||
while(rr) {
|
||||
rrset->size -= rr->size;
|
||||
rr = rr->next;
|
||||
}
|
||||
if(rrset->rr_last)
|
||||
rrset->rr_last->next = NULL;
|
||||
else rrset->rr_first = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* This routine normalizes a response. This includes removing "irrelevant"
|
||||
* records from the answer and additional sections and (re)synthesizing
|
||||
@@ -387,6 +428,7 @@ scrub_normalize(sldns_buffer* pkt, struct msg_parse* msg,
|
||||
uint8_t* sname = qinfo->qname;
|
||||
size_t snamelen = qinfo->qname_len;
|
||||
struct rrset_parse* rrset, *prev, *nsset=NULL;
|
||||
int cname_length = 0; /* number of CNAMEs, or DNAMEs */
|
||||
|
||||
if(FLAGS_GET_RCODE(msg->flags) != LDNS_RCODE_NOERROR &&
|
||||
FLAGS_GET_RCODE(msg->flags) != LDNS_RCODE_NXDOMAIN)
|
||||
@@ -401,6 +443,16 @@ scrub_normalize(sldns_buffer* pkt, struct msg_parse* msg,
|
||||
prev = NULL;
|
||||
rrset = msg->rrset_first;
|
||||
while(rrset && rrset->section == LDNS_SECTION_ANSWER) {
|
||||
if(cname_length > env->cfg->iter_scrub_cname) {
|
||||
/* Too many CNAMEs, or DNAMEs, from the authority
|
||||
* server, scrub down the length to something
|
||||
* shorter. This deletes everything after the limit
|
||||
* is reached. The iterator is going to look up
|
||||
* the content one by one anyway. */
|
||||
remove_rrset("normalize: removing because too many cnames:",
|
||||
pkt, msg, prev, &rrset);
|
||||
continue;
|
||||
}
|
||||
if(rrset->type == LDNS_RR_TYPE_DNAME &&
|
||||
pkt_strict_sub(pkt, sname, rrset->dname)) {
|
||||
/* check if next rrset is correct CNAME. else,
|
||||
@@ -420,6 +472,7 @@ scrub_normalize(sldns_buffer* pkt, struct msg_parse* msg,
|
||||
"too long");
|
||||
return 0;
|
||||
}
|
||||
cname_length++;
|
||||
if(nx && nx->type == LDNS_RR_TYPE_CNAME &&
|
||||
dname_pkt_compare(pkt, sname, nx->dname) == 0) {
|
||||
/* check next cname */
|
||||
@@ -460,6 +513,7 @@ scrub_normalize(sldns_buffer* pkt, struct msg_parse* msg,
|
||||
if(rrset->type == LDNS_RR_TYPE_CNAME) {
|
||||
struct rrset_parse* nx = rrset->rrset_all_next;
|
||||
uint8_t* oldsname = sname;
|
||||
cname_length++;
|
||||
/* see if the next one is a DNAME, if so, swap them */
|
||||
if(nx && nx->section == LDNS_SECTION_ANSWER &&
|
||||
nx->type == LDNS_RR_TYPE_DNAME &&
|
||||
@@ -507,6 +561,10 @@ scrub_normalize(sldns_buffer* pkt, struct msg_parse* msg,
|
||||
LDNS_SECTION_ANSWER &&
|
||||
dname_pkt_compare(pkt, oldsname,
|
||||
rrset->dname) == 0) {
|
||||
if(rrset->type == LDNS_RR_TYPE_NS &&
|
||||
rrset->rr_count > env->cfg->iter_scrub_ns) {
|
||||
shorten_rrset(pkt, rrset, env->cfg->iter_scrub_ns);
|
||||
}
|
||||
prev = rrset;
|
||||
rrset = rrset->rrset_all_next;
|
||||
}
|
||||
@@ -522,6 +580,11 @@ scrub_normalize(sldns_buffer* pkt, struct msg_parse* msg,
|
||||
continue;
|
||||
}
|
||||
|
||||
if(rrset->type == LDNS_RR_TYPE_NS &&
|
||||
rrset->rr_count > env->cfg->iter_scrub_ns) {
|
||||
shorten_rrset(pkt, rrset, env->cfg->iter_scrub_ns);
|
||||
}
|
||||
|
||||
/* Mark the additional names from relevant rrset as OK. */
|
||||
/* only for RRsets that match the query name, other ones
|
||||
* will be removed by sanitize, so no additional for them */
|
||||
@@ -578,6 +641,25 @@ scrub_normalize(sldns_buffer* pkt, struct msg_parse* msg,
|
||||
"RRset:", pkt, msg, prev, &rrset);
|
||||
continue;
|
||||
}
|
||||
if(rrset->rr_count > env->cfg->iter_scrub_ns) {
|
||||
/* If this is not a referral, and the NS RRset
|
||||
* is signed, then remove it entirely, so
|
||||
* that when it becomes bogus it does not
|
||||
* make the message that is otherwise fine
|
||||
* into a bogus message. */
|
||||
if(!(msg->an_rrsets == 0 &&
|
||||
FLAGS_GET_RCODE(msg->flags) ==
|
||||
LDNS_RCODE_NOERROR &&
|
||||
!soa_in_auth(msg) &&
|
||||
!(msg->flags & BIT_AA)) &&
|
||||
rrset->rrsig_count != 0) {
|
||||
remove_rrset("normalize: removing too large NS "
|
||||
"RRset:", pkt, msg, prev, &rrset);
|
||||
continue;
|
||||
} else {
|
||||
shorten_rrset(pkt, rrset, env->cfg->iter_scrub_ns);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* if this is type DS and we query for type DS we just got
|
||||
* a referral answer for our type DS query, fix packet */
|
||||
@@ -789,6 +871,7 @@ scrub_sanitize(sldns_buffer* pkt, struct msg_parse* msg,
|
||||
{
|
||||
int del_addi = 0; /* if additional-holding rrsets are deleted, we
|
||||
do not trust the normalized additional-A-AAAA any more */
|
||||
uint8_t* ns_rrset_dname = NULL;
|
||||
int added_rrlen_ede = 0;
|
||||
struct rrset_parse* rrset, *prev;
|
||||
prev = NULL;
|
||||
@@ -894,6 +977,16 @@ scrub_sanitize(sldns_buffer* pkt, struct msg_parse* msg,
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if(rrset->type == LDNS_RR_TYPE_NS &&
|
||||
(rrset->section == LDNS_SECTION_AUTHORITY ||
|
||||
rrset->section == LDNS_SECTION_ANSWER)) {
|
||||
/* If the type is NS, and we're in the
|
||||
* answer or authority section, then
|
||||
* store the dname so we can check
|
||||
* against the glue records
|
||||
* further down */
|
||||
ns_rrset_dname = rrset->dname;
|
||||
}
|
||||
if(del_addi && rrset->section == LDNS_SECTION_ADDITIONAL) {
|
||||
remove_rrset("sanitize: removing potential "
|
||||
"poison reference RRset:", pkt, msg, prev, &rrset);
|
||||
@@ -906,6 +999,26 @@ scrub_sanitize(sldns_buffer* pkt, struct msg_parse* msg,
|
||||
"RRset:", pkt, msg, prev, &rrset);
|
||||
continue;
|
||||
}
|
||||
if(env->cfg->harden_unverified_glue && ns_rrset_dname &&
|
||||
rrset->section == LDNS_SECTION_ADDITIONAL &&
|
||||
(rrset->type == LDNS_RR_TYPE_A || rrset->type == LDNS_RR_TYPE_AAAA) &&
|
||||
!pkt_strict_sub(pkt, rrset->dname, ns_rrset_dname)) {
|
||||
/* We're in the additional section, looking
|
||||
* at an A/AAAA rrset, have a previous
|
||||
* delegation point and we notice that
|
||||
* the glue records are NOT for strict
|
||||
* subdomains of the delegation. So set a
|
||||
* flag, recompute the hash for the rrset
|
||||
* and write the A/AAAA record to cache.
|
||||
* It'll be retrieved if we can't separately
|
||||
* resolve the glue */
|
||||
rrset->flags = PACKED_RRSET_UNVERIFIED_GLUE;
|
||||
rrset->hash = pkt_hash_rrset(pkt, rrset->dname, rrset->type, rrset->rrset_class, rrset->flags);
|
||||
store_rrset(pkt, msg, env, rrset);
|
||||
remove_rrset("sanitize: storing potential "
|
||||
"unverified glue reference RRset:", pkt, msg, prev, &rrset);
|
||||
continue;
|
||||
}
|
||||
prev = rrset;
|
||||
rrset = rrset->rrset_all_next;
|
||||
}
|
||||
|
||||
+146
-49
@@ -77,41 +77,73 @@
|
||||
static const char DEFAULT_NAT64_PREFIX[] = "64:ff9b::/96";
|
||||
|
||||
/** fillup fetch policy array */
|
||||
static void
|
||||
fetch_fill(struct iter_env* ie, const char* str)
|
||||
static int
|
||||
fetch_fill(int* target_fetch_policy, int max_dependency_depth, const char* str)
|
||||
{
|
||||
char* s = (char*)str, *e;
|
||||
int i;
|
||||
for(i=0; i<ie->max_dependency_depth+1; i++) {
|
||||
ie->target_fetch_policy[i] = strtol(s, &e, 10);
|
||||
if(s == e)
|
||||
fatal_exit("cannot parse fetch policy number %s", s);
|
||||
for(i=0; i<max_dependency_depth+1; i++) {
|
||||
target_fetch_policy[i] = strtol(s, &e, 10);
|
||||
if(s == e) {
|
||||
log_err("cannot parse fetch policy number %s", s);
|
||||
return 0;
|
||||
}
|
||||
s = e;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** Read config string that represents the target fetch policy */
|
||||
static int
|
||||
read_fetch_policy(struct iter_env* ie, const char* str)
|
||||
int
|
||||
read_fetch_policy(int** target_fetch_policy, int* max_dependency_depth,
|
||||
const char* str)
|
||||
{
|
||||
int count = cfg_count_numbers(str);
|
||||
if(count < 1) {
|
||||
log_err("Cannot parse target fetch policy: \"%s\"", str);
|
||||
return 0;
|
||||
}
|
||||
ie->max_dependency_depth = count - 1;
|
||||
ie->target_fetch_policy = (int*)calloc(
|
||||
(size_t)ie->max_dependency_depth+1, sizeof(int));
|
||||
if(!ie->target_fetch_policy) {
|
||||
*max_dependency_depth = count - 1;
|
||||
*target_fetch_policy = (int*)calloc(
|
||||
(size_t)(*max_dependency_depth)+1, sizeof(int));
|
||||
if(!*target_fetch_policy) {
|
||||
log_err("alloc fetch policy: out of memory");
|
||||
return 0;
|
||||
}
|
||||
fetch_fill(ie, str);
|
||||
if(!fetch_fill(*target_fetch_policy, *max_dependency_depth, str))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** apply config caps whitelist items to name tree */
|
||||
static int
|
||||
struct rbtree_type*
|
||||
caps_white_create(void)
|
||||
{
|
||||
struct rbtree_type* caps_white = rbtree_create(name_tree_compare);
|
||||
if(!caps_white)
|
||||
log_err("out of memory");
|
||||
return caps_white;
|
||||
}
|
||||
|
||||
/** delete caps_whitelist element */
|
||||
static void
|
||||
caps_free(struct rbnode_type* n, void* ATTR_UNUSED(d))
|
||||
{
|
||||
if(n) {
|
||||
free(((struct name_tree_node*)n)->name);
|
||||
free(n);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
caps_white_delete(struct rbtree_type* caps_white)
|
||||
{
|
||||
if(!caps_white)
|
||||
return;
|
||||
traverse_postorder(caps_white, caps_free, NULL);
|
||||
free(caps_white);
|
||||
}
|
||||
|
||||
int
|
||||
caps_white_apply_cfg(rbtree_type* ntree, struct config_file* cfg)
|
||||
{
|
||||
struct config_strlist* p;
|
||||
@@ -145,12 +177,41 @@ caps_white_apply_cfg(rbtree_type* ntree, struct config_file* cfg)
|
||||
}
|
||||
|
||||
int
|
||||
iter_apply_cfg(struct iter_env* iter_env, struct config_file* cfg)
|
||||
nat64_apply_cfg(struct iter_nat64* nat64, struct config_file* cfg)
|
||||
{
|
||||
const char *nat64_prefix;
|
||||
|
||||
nat64_prefix = cfg->nat64_prefix;
|
||||
if(!nat64_prefix)
|
||||
nat64_prefix = cfg->dns64_prefix;
|
||||
if(!nat64_prefix)
|
||||
nat64_prefix = DEFAULT_NAT64_PREFIX;
|
||||
if(!netblockstrtoaddr(nat64_prefix, 0, &nat64->nat64_prefix_addr,
|
||||
&nat64->nat64_prefix_addrlen, &nat64->nat64_prefix_net)) {
|
||||
log_err("cannot parse nat64-prefix netblock: %s", nat64_prefix);
|
||||
return 0;
|
||||
}
|
||||
if(!addr_is_ip6(&nat64->nat64_prefix_addr,
|
||||
nat64->nat64_prefix_addrlen)) {
|
||||
log_err("nat64-prefix is not IPv6: %s", cfg->nat64_prefix);
|
||||
return 0;
|
||||
}
|
||||
if(!prefixnet_is_nat64(nat64->nat64_prefix_net)) {
|
||||
log_err("nat64-prefix length it not 32, 40, 48, 56, 64 or 96: %s",
|
||||
nat64_prefix);
|
||||
return 0;
|
||||
}
|
||||
nat64->use_nat64 = cfg->do_nat64;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
iter_apply_cfg(struct iter_env* iter_env, struct config_file* cfg)
|
||||
{
|
||||
int i;
|
||||
/* target fetch policy */
|
||||
if(!read_fetch_policy(iter_env, cfg->target_fetch_policy))
|
||||
if(!read_fetch_policy(&iter_env->target_fetch_policy,
|
||||
&iter_env->max_dependency_depth, cfg->target_fetch_policy))
|
||||
return 0;
|
||||
for(i=0; i<iter_env->max_dependency_depth+1; i++)
|
||||
verbose(VERB_QUERY, "target fetch policy for level %d is %d",
|
||||
@@ -170,7 +231,7 @@ iter_apply_cfg(struct iter_env* iter_env, struct config_file* cfg)
|
||||
}
|
||||
if(cfg->caps_whitelist) {
|
||||
if(!iter_env->caps_white)
|
||||
iter_env->caps_white = rbtree_create(name_tree_compare);
|
||||
iter_env->caps_white = caps_white_create();
|
||||
if(!iter_env->caps_white || !caps_white_apply_cfg(
|
||||
iter_env->caps_white, cfg)) {
|
||||
log_err("Could not set capsforid whitelist");
|
||||
@@ -179,31 +240,13 @@ iter_apply_cfg(struct iter_env* iter_env, struct config_file* cfg)
|
||||
|
||||
}
|
||||
|
||||
nat64_prefix = cfg->nat64_prefix;
|
||||
if(!nat64_prefix)
|
||||
nat64_prefix = cfg->dns64_prefix;
|
||||
if(!nat64_prefix)
|
||||
nat64_prefix = DEFAULT_NAT64_PREFIX;
|
||||
if(!netblockstrtoaddr(nat64_prefix, 0, &iter_env->nat64_prefix_addr,
|
||||
&iter_env->nat64_prefix_addrlen,
|
||||
&iter_env->nat64_prefix_net)) {
|
||||
log_err("cannot parse nat64-prefix netblock: %s", nat64_prefix);
|
||||
return 0;
|
||||
}
|
||||
if(!addr_is_ip6(&iter_env->nat64_prefix_addr,
|
||||
iter_env->nat64_prefix_addrlen)) {
|
||||
log_err("nat64-prefix is not IPv6: %s", cfg->nat64_prefix);
|
||||
return 0;
|
||||
}
|
||||
if(!prefixnet_is_nat64(iter_env->nat64_prefix_net)) {
|
||||
log_err("nat64-prefix length it not 32, 40, 48, 56, 64 or 96: %s",
|
||||
nat64_prefix);
|
||||
if(!nat64_apply_cfg(&iter_env->nat64, cfg)) {
|
||||
log_err("Could not setup nat64");
|
||||
return 0;
|
||||
}
|
||||
|
||||
iter_env->supports_ipv6 = cfg->do_ip6;
|
||||
iter_env->supports_ipv4 = cfg->do_ip4;
|
||||
iter_env->use_nat64 = cfg->do_nat64;
|
||||
iter_env->outbound_msg_retry = cfg->outbound_msg_retry;
|
||||
iter_env->max_sent_count = cfg->max_sent_count;
|
||||
iter_env->max_query_restarts = cfg->max_query_restarts;
|
||||
@@ -270,7 +313,7 @@ iter_filter_unsuitable(struct iter_env* iter_env, struct module_env* env,
|
||||
if(!iter_env->supports_ipv6 && addr_is_ip6(&a->addr, a->addrlen)) {
|
||||
return -1; /* there is no ip6 available */
|
||||
}
|
||||
if(!iter_env->supports_ipv4 && !iter_env->use_nat64 &&
|
||||
if(!iter_env->supports_ipv4 && !iter_env->nat64.use_nat64 &&
|
||||
!addr_is_ip6(&a->addr, a->addrlen)) {
|
||||
return -1; /* there is no ip4 available */
|
||||
}
|
||||
@@ -693,10 +736,11 @@ 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, time_t qstarttime)
|
||||
struct regional* region, uint16_t flags, time_t qstarttime,
|
||||
int is_valrec)
|
||||
{
|
||||
if(!dns_cache_store(env, msgqinf, msgrep, is_referral, leeway,
|
||||
pside, region, flags, qstarttime))
|
||||
pside, region, flags, qstarttime, is_valrec))
|
||||
log_err("out of memory: cannot store data in cache");
|
||||
}
|
||||
|
||||
@@ -1488,14 +1532,15 @@ iter_stub_fwd_no_cache(struct module_qstate *qstate, struct query_info *qinf,
|
||||
|
||||
/* check stub */
|
||||
if (stub != NULL && stub->dp != NULL) {
|
||||
enum verbosity_value level = VERB_ALGO;
|
||||
int stub_no_cache = stub->dp->no_cache;
|
||||
lock_rw_unlock(&qstate->env->fwds->lock);
|
||||
if(stub_no_cache) {
|
||||
char qname[255+1];
|
||||
char dpname[255+1];
|
||||
if(verbosity >= level && stub_no_cache) {
|
||||
char qname[LDNS_MAX_DOMAINLEN];
|
||||
char dpname[LDNS_MAX_DOMAINLEN];
|
||||
dname_str(qinf->qname, qname);
|
||||
dname_str(stub->dp->name, dpname);
|
||||
verbose(VERB_ALGO, "stub for %s %s has no_cache", qname, dpname);
|
||||
verbose(level, "stub for %s %s has no_cache", qname, dpname);
|
||||
}
|
||||
if(retdpname) {
|
||||
if(stub->dp->namelen > dpname_storage_len) {
|
||||
@@ -1516,14 +1561,15 @@ iter_stub_fwd_no_cache(struct module_qstate *qstate, struct query_info *qinf,
|
||||
|
||||
/* Check for forward. */
|
||||
if (dp) {
|
||||
enum verbosity_value level = VERB_ALGO;
|
||||
int dp_no_cache = dp->no_cache;
|
||||
lock_rw_unlock(&qstate->env->hints->lock);
|
||||
if(dp_no_cache) {
|
||||
char qname[255+1];
|
||||
char dpname[255+1];
|
||||
if(verbosity >= level && dp_no_cache) {
|
||||
char qname[LDNS_MAX_DOMAINLEN];
|
||||
char dpname[LDNS_MAX_DOMAINLEN];
|
||||
dname_str(qinf->qname, qname);
|
||||
dname_str(dp->name, dpname);
|
||||
verbose(VERB_ALGO, "forward for %s %s has no_cache", qname, dpname);
|
||||
verbose(level, "forward for %s %s has no_cache", qname, dpname);
|
||||
}
|
||||
if(retdpname) {
|
||||
if(dp->namelen > dpname_storage_len) {
|
||||
@@ -1564,3 +1610,54 @@ void iterator_set_ip46_support(struct module_stack* mods,
|
||||
if(outnet->num_ip6 == 0)
|
||||
ie->supports_ipv6 = 0;
|
||||
}
|
||||
|
||||
void
|
||||
limit_nsec_ttl(struct dns_msg* msg)
|
||||
{
|
||||
/* Limit NSEC and NSEC3 TTL in response, RFC9077 */
|
||||
size_t i;
|
||||
int found = 0;
|
||||
time_t soa_ttl = 0;
|
||||
/* Limit the NSEC and NSEC3 TTL values to the SOA TTL and SOA minimum
|
||||
* TTL. That has already been applied to the SOA record ttl. */
|
||||
for(i=0; i<msg->rep->rrset_count; i++) {
|
||||
struct ub_packed_rrset_key* s = msg->rep->rrsets[i];
|
||||
if(ntohs(s->rk.type) == LDNS_RR_TYPE_SOA) {
|
||||
struct packed_rrset_data* soadata = (struct packed_rrset_data*)s->entry.data;
|
||||
found = 1;
|
||||
soa_ttl = soadata->ttl;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!found)
|
||||
return;
|
||||
for(i=0; i<msg->rep->rrset_count; i++) {
|
||||
struct ub_packed_rrset_key* s = msg->rep->rrsets[i];
|
||||
if(ntohs(s->rk.type) == LDNS_RR_TYPE_NSEC ||
|
||||
ntohs(s->rk.type) == LDNS_RR_TYPE_NSEC3) {
|
||||
struct packed_rrset_data* data = (struct packed_rrset_data*)s->entry.data;
|
||||
/* Limit the negative TTL. */
|
||||
if(data->ttl > soa_ttl) {
|
||||
if(verbosity >= VERB_ALGO) {
|
||||
char buf[256];
|
||||
snprintf(buf, sizeof(buf),
|
||||
"limiting TTL %d of %s record to the SOA TTL of %d for",
|
||||
(int)data->ttl, ((ntohs(s->rk.type) == LDNS_RR_TYPE_NSEC)?"NSEC":"NSEC3"), (int)soa_ttl);
|
||||
log_nametypeclass(VERB_ALGO, buf,
|
||||
s->rk.dname, ntohs(s->rk.type),
|
||||
ntohs(s->rk.rrset_class));
|
||||
}
|
||||
data->ttl = soa_ttl;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
iter_make_minimal(struct reply_info* rep)
|
||||
{
|
||||
size_t rem = rep->ns_numrrsets + rep->ar_numrrsets;
|
||||
rep->ns_numrrsets = 0;
|
||||
rep->ar_numrrsets = 0;
|
||||
rep->rrset_count -= rem;
|
||||
}
|
||||
|
||||
+55
-1
@@ -61,6 +61,7 @@ struct sock_list;
|
||||
struct ub_packed_rrset_key;
|
||||
struct module_stack;
|
||||
struct outside_network;
|
||||
struct iter_nat64;
|
||||
|
||||
/* max number of lookups in the cache for target nameserver names.
|
||||
* This stops, for large delegations, N*N lookups in the cache. */
|
||||
@@ -142,6 +143,7 @@ struct dns_msg* dns_copy_msg(struct dns_msg* from, struct regional* regional);
|
||||
* @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.
|
||||
* @param is_valrec: if the query is validation recursion and does not get
|
||||
* 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.
|
||||
@@ -150,7 +152,8 @@ 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, time_t qstarttime);
|
||||
struct regional* region, uint16_t flags, time_t qstarttime,
|
||||
int is_valrec);
|
||||
|
||||
/**
|
||||
* Select randomly with n/m probability.
|
||||
@@ -428,4 +431,55 @@ int iter_stub_fwd_no_cache(struct module_qstate *qstate,
|
||||
void iterator_set_ip46_support(struct module_stack* mods,
|
||||
struct module_env* env, struct outside_network* outnet);
|
||||
|
||||
/**
|
||||
* Read config string that represents the target fetch policy.
|
||||
* @param target_fetch_policy: alloced on return.
|
||||
* @param max_dependency_depth: set on return.
|
||||
* @param str: the config string
|
||||
* @return false on failure.
|
||||
*/
|
||||
int read_fetch_policy(int** target_fetch_policy, int* max_dependency_depth,
|
||||
const char* str);
|
||||
|
||||
/**
|
||||
* Create caps exempt data structure.
|
||||
* @return NULL on failure.
|
||||
*/
|
||||
struct rbtree_type* caps_white_create(void);
|
||||
|
||||
/**
|
||||
* Delete caps exempt data structure.
|
||||
* @param caps_white: caps exempt tree.
|
||||
*/
|
||||
void caps_white_delete(struct rbtree_type* caps_white);
|
||||
|
||||
/**
|
||||
* Apply config caps whitelist items to name tree
|
||||
* @param ntree: caps exempt tree.
|
||||
* @param cfg: config with options.
|
||||
*/
|
||||
int caps_white_apply_cfg(struct rbtree_type* ntree, struct config_file* cfg);
|
||||
|
||||
/**
|
||||
* Apply config for nat64
|
||||
* @param nat64: the nat64 state.
|
||||
* @param cfg: config with options.
|
||||
* @return false on failure.
|
||||
*/
|
||||
int nat64_apply_cfg(struct iter_nat64* nat64, struct config_file* cfg);
|
||||
|
||||
/**
|
||||
* Limit NSEC and NSEC3 TTL in response, RFC9077
|
||||
* @param msg: dns message, the SOA record ttl is used to restrict ttls
|
||||
* of NSEC and NSEC3 RRsets. If no SOA record, nothing happens.
|
||||
*/
|
||||
void limit_nsec_ttl(struct dns_msg* msg);
|
||||
|
||||
/**
|
||||
* Make the response minimal. Removed authority and additional section,
|
||||
* that works when there is an answer in the answer section.
|
||||
* @param rep: reply to modify.
|
||||
*/
|
||||
void iter_make_minimal(struct reply_info* rep);
|
||||
|
||||
#endif /* ITERATOR_ITER_UTILS_H */
|
||||
|
||||
+103
-53
@@ -70,12 +70,16 @@
|
||||
#include "sldns/parseutil.h"
|
||||
#include "sldns/sbuffer.h"
|
||||
|
||||
/* number of packets */
|
||||
int MAX_GLOBAL_QUOTA = 200;
|
||||
/* 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);
|
||||
/** Timeout when only a single probe query per IP is allowed. */
|
||||
int PROBE_MAXRTO = PROBE_MAXRTO_DEFAULT; /* in msec */
|
||||
|
||||
static void target_count_increase_nx(struct iter_qstate* iq, int num);
|
||||
|
||||
@@ -103,16 +107,6 @@ iter_init(struct module_env* env, int id)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** delete caps_whitelist element */
|
||||
static void
|
||||
caps_free(struct rbnode_type* n, void* ATTR_UNUSED(d))
|
||||
{
|
||||
if(n) {
|
||||
free(((struct name_tree_node*)n)->name);
|
||||
free(n);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
iter_deinit(struct module_env* env, int id)
|
||||
{
|
||||
@@ -124,10 +118,7 @@ iter_deinit(struct module_env* env, int id)
|
||||
free(iter_env->target_fetch_policy);
|
||||
priv_delete(iter_env->priv);
|
||||
donotq_delete(iter_env->donotq);
|
||||
if(iter_env->caps_white) {
|
||||
traverse_postorder(iter_env->caps_white, caps_free, NULL);
|
||||
free(iter_env->caps_white);
|
||||
}
|
||||
caps_white_delete(iter_env->caps_white);
|
||||
free(iter_env);
|
||||
env->modinfo[id] = NULL;
|
||||
}
|
||||
@@ -252,11 +243,11 @@ error_supers(struct module_qstate* qstate, int id, struct module_qstate* super)
|
||||
} else {
|
||||
/* see if the failure did get (parent-lame) info */
|
||||
if(!cache_fill_missing(super->env, super_iq->qchase.qclass,
|
||||
super->region, super_iq->dp))
|
||||
super->region, super_iq->dp, 0))
|
||||
log_err("out of memory adding missing");
|
||||
}
|
||||
delegpt_mark_neg(dpns, qstate->qinfo.qtype);
|
||||
if((dpns->got4 == 2 || (!ie->supports_ipv4 && !ie->use_nat64)) &&
|
||||
if((dpns->got4 == 2 || (!ie->supports_ipv4 && !ie->nat64.use_nat64)) &&
|
||||
(dpns->got6 == 2 || !ie->supports_ipv6)) {
|
||||
dpns->resolved = 1; /* mark as failed */
|
||||
target_count_increase_nx(super_iq, 1);
|
||||
@@ -320,16 +311,21 @@ error_response_cache(struct module_qstate* qstate, int id, int rcode)
|
||||
qstate->qinfo.qname, qstate->qinfo.qname_len,
|
||||
qstate->qinfo.qtype, qstate->qinfo.qclass,
|
||||
qstate->query_flags, 0,
|
||||
qstate->env->cfg->serve_expired_ttl_reset)) != NULL) {
|
||||
qstate->env->cfg->serve_expired)) != NULL) {
|
||||
struct reply_info* rep = (struct reply_info*)msg->entry.data;
|
||||
if(qstate->env->cfg->serve_expired &&
|
||||
qstate->env->cfg->serve_expired_ttl_reset && rep &&
|
||||
*qstate->env->now + qstate->env->cfg->serve_expired_ttl
|
||||
> rep->serve_expired_ttl) {
|
||||
verbose(VERB_ALGO, "reset serve-expired-ttl for "
|
||||
if(qstate->env->cfg->serve_expired && rep) {
|
||||
if(qstate->env->cfg->serve_expired_ttl_reset &&
|
||||
*qstate->env->now + qstate->env->cfg->serve_expired_ttl
|
||||
> rep->serve_expired_ttl) {
|
||||
verbose(VERB_ALGO, "reset serve-expired-ttl for "
|
||||
"response in cache");
|
||||
rep->serve_expired_ttl = *qstate->env->now +
|
||||
qstate->env->cfg->serve_expired_ttl;
|
||||
}
|
||||
verbose(VERB_ALGO, "set serve-expired-norec-ttl for "
|
||||
"response in cache");
|
||||
rep->serve_expired_ttl = *qstate->env->now +
|
||||
qstate->env->cfg->serve_expired_ttl;
|
||||
rep->serve_expired_norec_ttl = NORR_TTL +
|
||||
*qstate->env->now;
|
||||
}
|
||||
if(rep && (FLAGS_GET_RCODE(rep->flags) ==
|
||||
LDNS_RCODE_NOERROR ||
|
||||
@@ -361,7 +357,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->qstarttime);
|
||||
qstate->query_flags, qstate->qstarttime, qstate->is_valrec);
|
||||
return error_response(qstate, id, rcode);
|
||||
}
|
||||
|
||||
@@ -407,8 +403,11 @@ iter_prepend(struct iter_qstate* iq, struct dns_msg* msg,
|
||||
num_an = 0;
|
||||
for(p = iq->an_prepend_list; p; p = p->next) {
|
||||
sets[num_an++] = p->rrset;
|
||||
if(ub_packed_rrset_ttl(p->rrset) < msg->rep->ttl)
|
||||
if(ub_packed_rrset_ttl(p->rrset) < msg->rep->ttl) {
|
||||
msg->rep->ttl = ub_packed_rrset_ttl(p->rrset);
|
||||
msg->rep->prefetch_ttl = PREFETCH_TTL_CALC(msg->rep->ttl);
|
||||
msg->rep->serve_expired_ttl = msg->rep->ttl + SERVE_EXPIRED_TTL;
|
||||
}
|
||||
}
|
||||
memcpy(sets+num_an, msg->rep->rrsets, msg->rep->an_numrrsets *
|
||||
sizeof(struct ub_packed_rrset_key*));
|
||||
@@ -421,8 +420,11 @@ iter_prepend(struct iter_qstate* iq, struct dns_msg* msg,
|
||||
msg->rep->ns_numrrsets, p->rrset))
|
||||
continue;
|
||||
sets[msg->rep->an_numrrsets + num_an + num_ns++] = p->rrset;
|
||||
if(ub_packed_rrset_ttl(p->rrset) < msg->rep->ttl)
|
||||
if(ub_packed_rrset_ttl(p->rrset) < msg->rep->ttl) {
|
||||
msg->rep->ttl = ub_packed_rrset_ttl(p->rrset);
|
||||
msg->rep->prefetch_ttl = PREFETCH_TTL_CALC(msg->rep->ttl);
|
||||
msg->rep->serve_expired_ttl = msg->rep->ttl + SERVE_EXPIRED_TTL;
|
||||
}
|
||||
}
|
||||
memcpy(sets + num_an + msg->rep->an_numrrsets + num_ns,
|
||||
msg->rep->rrsets + msg->rep->an_numrrsets,
|
||||
@@ -760,6 +762,14 @@ target_count_increase_nx(struct iter_qstate* iq, int num)
|
||||
iq->target_count[TARGET_COUNT_NX] += num;
|
||||
}
|
||||
|
||||
static void
|
||||
target_count_increase_global_quota(struct iter_qstate* iq, int num)
|
||||
{
|
||||
target_count_create(iq);
|
||||
if(iq->target_count)
|
||||
iq->target_count[TARGET_COUNT_GLOBAL_QUOTA] += num;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a subrequest.
|
||||
* Generate a local request event. Local events are tied to this module, and
|
||||
@@ -1071,7 +1081,7 @@ auth_zone_delegpt(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
/* cache is blacklisted and fallback, and we
|
||||
* already have an auth_zone dp */
|
||||
if(verbosity>=VERB_ALGO) {
|
||||
char buf[255+1];
|
||||
char buf[LDNS_MAX_DOMAINLEN];
|
||||
dname_str(z->name, buf);
|
||||
verbose(VERB_ALGO, "auth_zone %s "
|
||||
"fallback because cache blacklisted",
|
||||
@@ -1088,7 +1098,7 @@ auth_zone_delegpt(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
* validation failure, and the zone allows
|
||||
* fallback to the internet, query there. */
|
||||
if(verbosity>=VERB_ALGO) {
|
||||
char buf[255+1];
|
||||
char buf[LDNS_MAX_DOMAINLEN];
|
||||
dname_str(z->name, buf);
|
||||
verbose(VERB_ALGO, "auth_zone %s "
|
||||
"fallback because cache blacklisted",
|
||||
@@ -1560,6 +1570,11 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
errinf(qstate, "malloc failure for forward zone");
|
||||
return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
|
||||
}
|
||||
if(!cache_fill_missing(qstate->env, iq->qchase.qclass,
|
||||
qstate->region, iq->dp, 0)) {
|
||||
errinf(qstate, "malloc failure, copy extra info into delegation point");
|
||||
return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
|
||||
}
|
||||
if((qstate->query_flags&BIT_RD)==0) {
|
||||
/* If the server accepts RD=0 queries and forwards
|
||||
* with RD=1, then if the server is listed as an NS
|
||||
@@ -1697,7 +1712,7 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
*/
|
||||
if(iter_dp_is_useless(&qstate->qinfo, qstate->query_flags,
|
||||
iq->dp, ie->supports_ipv4, ie->supports_ipv6,
|
||||
ie->use_nat64)) {
|
||||
ie->nat64.use_nat64)) {
|
||||
int have_dp = 0;
|
||||
if(!can_have_last_resort(qstate->env, iq->dp->name, iq->dp->namelen, iq->qchase.qclass, &have_dp, &iq->dp, qstate->region)) {
|
||||
if(have_dp) {
|
||||
@@ -2007,7 +2022,7 @@ query_for_targets(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
return 1;
|
||||
if(iq->depth > 0 && iq->target_count &&
|
||||
iq->target_count[TARGET_COUNT_QUERIES] > MAX_TARGET_COUNT) {
|
||||
char s[LDNS_MAX_DOMAINLEN+1];
|
||||
char s[LDNS_MAX_DOMAINLEN];
|
||||
dname_str(qstate->qinfo.qname, s);
|
||||
verbose(VERB_QUERY, "request %s has exceeded the maximum "
|
||||
"number of glue fetches %d", s,
|
||||
@@ -2015,7 +2030,7 @@ query_for_targets(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
return 2;
|
||||
}
|
||||
if(iq->dp_target_count > MAX_DP_TARGET_COUNT) {
|
||||
char s[LDNS_MAX_DOMAINLEN+1];
|
||||
char s[LDNS_MAX_DOMAINLEN];
|
||||
dname_str(qstate->qinfo.qname, s);
|
||||
verbose(VERB_QUERY, "request %s has exceeded the maximum "
|
||||
"number of glue fetches %d to a single delegation point",
|
||||
@@ -2061,7 +2076,7 @@ query_for_targets(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
if(mesh_jostle_exceeded(qstate->env->mesh)) {
|
||||
/* If no ip4 query is possible, that makes
|
||||
* this ns resolved. */
|
||||
if(!((ie->supports_ipv4 || ie->use_nat64) &&
|
||||
if(!((ie->supports_ipv4 || ie->nat64.use_nat64) &&
|
||||
((ns->lame && !ns->done_pside4) ||
|
||||
(!ns->lame && !ns->got4)))) {
|
||||
ns->resolved = 1;
|
||||
@@ -2070,7 +2085,7 @@ query_for_targets(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
}
|
||||
}
|
||||
/* Send the A request. */
|
||||
if((ie->supports_ipv4 || ie->use_nat64) &&
|
||||
if((ie->supports_ipv4 || ie->nat64.use_nat64) &&
|
||||
((ns->lame && !ns->done_pside4) ||
|
||||
(!ns->lame && !ns->got4))) {
|
||||
if(!generate_target_query(qstate, iq, id,
|
||||
@@ -2137,6 +2152,15 @@ processLastResort(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
verbose(VERB_QUERY, "configured stub or forward servers failed -- returning SERVFAIL");
|
||||
return error_response_cache(qstate, id, LDNS_RCODE_SERVFAIL);
|
||||
}
|
||||
if(qstate->env->cfg->harden_unverified_glue) {
|
||||
if(!cache_fill_missing(qstate->env, iq->qchase.qclass,
|
||||
qstate->region, iq->dp, PACKED_RRSET_UNVERIFIED_GLUE))
|
||||
log_err("out of memory in cache_fill_missing");
|
||||
if(iq->dp->usable_list) {
|
||||
verbose(VERB_ALGO, "try unverified glue from cache");
|
||||
return next_state(iq, QUERYTARGETS_STATE);
|
||||
}
|
||||
}
|
||||
if(!iq->dp->has_parent_side_NS && dname_is_root(iq->dp->name)) {
|
||||
struct delegpt* dp;
|
||||
int nolock = 0;
|
||||
@@ -2179,7 +2203,7 @@ processLastResort(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
}
|
||||
/* see if that makes new names available */
|
||||
if(!cache_fill_missing(qstate->env, iq->qchase.qclass,
|
||||
qstate->region, iq->dp))
|
||||
qstate->region, iq->dp, 0))
|
||||
log_err("out of memory in cache_fill_missing");
|
||||
if(iq->dp->usable_list) {
|
||||
verbose(VERB_ALGO, "try parent-side-name, w. glue from cache");
|
||||
@@ -2217,7 +2241,7 @@ processLastResort(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
}
|
||||
if(iq->depth > 0 && iq->target_count &&
|
||||
iq->target_count[TARGET_COUNT_QUERIES] > MAX_TARGET_COUNT) {
|
||||
char s[LDNS_MAX_DOMAINLEN+1];
|
||||
char s[LDNS_MAX_DOMAINLEN];
|
||||
dname_str(qstate->qinfo.qname, s);
|
||||
verbose(VERB_QUERY, "request %s has exceeded the maximum "
|
||||
"number of glue fetches %d", s,
|
||||
@@ -2233,14 +2257,14 @@ processLastResort(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
/* if this nameserver is at a delegation point, but that
|
||||
* delegation point is a stub and we cannot go higher, skip*/
|
||||
if( ((ie->supports_ipv6 && !ns->done_pside6) ||
|
||||
((ie->supports_ipv4 || ie->use_nat64) && !ns->done_pside4)) &&
|
||||
((ie->supports_ipv4 || ie->nat64.use_nat64) && !ns->done_pside4)) &&
|
||||
!can_have_last_resort(qstate->env, ns->name, ns->namelen,
|
||||
iq->qchase.qclass, NULL, NULL, NULL)) {
|
||||
log_nametypeclass(VERB_ALGO, "cannot pside lookup ns "
|
||||
"because it is also a stub/forward,",
|
||||
ns->name, LDNS_RR_TYPE_NS, iq->qchase.qclass);
|
||||
if(ie->supports_ipv6) ns->done_pside6 = 1;
|
||||
if(ie->supports_ipv4 || ie->use_nat64) ns->done_pside4 = 1;
|
||||
if(ie->supports_ipv4 || ie->nat64.use_nat64) ns->done_pside4 = 1;
|
||||
continue;
|
||||
}
|
||||
/* query for parent-side A and AAAA for nameservers */
|
||||
@@ -2265,7 +2289,7 @@ processLastResort(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if((ie->supports_ipv4 || ie->use_nat64) && !ns->done_pside4) {
|
||||
if((ie->supports_ipv4 || ie->nat64.use_nat64) && !ns->done_pside4) {
|
||||
/* Send the A request. */
|
||||
if(!generate_parentside_target_query(qstate, iq, id,
|
||||
ns->name, ns->namelen,
|
||||
@@ -2534,7 +2558,7 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
}
|
||||
if(!ie->supports_ipv6)
|
||||
delegpt_no_ipv6(iq->dp);
|
||||
if(!ie->supports_ipv4 && !ie->use_nat64)
|
||||
if(!ie->supports_ipv4 && !ie->nat64.use_nat64)
|
||||
delegpt_no_ipv4(iq->dp);
|
||||
delegpt_log(VERB_ALGO, iq->dp);
|
||||
|
||||
@@ -2706,9 +2730,7 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
if((iq->chase_flags&BIT_RD) && !(iq->response->rep->flags&BIT_AA)) {
|
||||
verbose(VERB_ALGO, "forwarder, ignoring referral from auth zone");
|
||||
} else {
|
||||
lock_rw_wrlock(&qstate->env->auth_zones->lock);
|
||||
qstate->env->auth_zones->num_query_up++;
|
||||
lock_rw_unlock(&qstate->env->auth_zones->lock);
|
||||
qstate->env->mesh->num_query_authzone_up++;
|
||||
iq->num_current_queries++;
|
||||
iq->chase_to_rd = 0;
|
||||
iq->dnssec_lame_query = 0;
|
||||
@@ -3008,6 +3030,17 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
}
|
||||
}
|
||||
|
||||
target_count_increase_global_quota(iq, 1);
|
||||
if(iq->target_count && iq->target_count[TARGET_COUNT_GLOBAL_QUOTA]
|
||||
> MAX_GLOBAL_QUOTA) {
|
||||
char s[LDNS_MAX_DOMAINLEN];
|
||||
dname_str(qstate->qinfo.qname, s);
|
||||
verbose(VERB_QUERY, "request %s has exceeded the maximum "
|
||||
"global quota on number of upstream queries %d", s,
|
||||
iq->target_count[TARGET_COUNT_GLOBAL_QUOTA]);
|
||||
return error_response_cache(qstate, id, LDNS_RCODE_SERVFAIL);
|
||||
}
|
||||
|
||||
/* 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);
|
||||
@@ -3024,9 +3057,9 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
real_addr = target->addr;
|
||||
real_addrlen = target->addrlen;
|
||||
|
||||
if(ie->use_nat64 && target->addr.ss_family == AF_INET) {
|
||||
addr_to_nat64(&target->addr, &ie->nat64_prefix_addr,
|
||||
ie->nat64_prefix_addrlen, ie->nat64_prefix_net,
|
||||
if(ie->nat64.use_nat64 && target->addr.ss_family == AF_INET) {
|
||||
addr_to_nat64(&target->addr, &ie->nat64.nat64_prefix_addr,
|
||||
ie->nat64.nat64_prefix_addrlen, ie->nat64.nat64_prefix_net,
|
||||
&real_addr, &real_addrlen);
|
||||
log_name_addr(VERB_QUERY, "applied NAT64:",
|
||||
iq->dp->name, &real_addr, real_addrlen);
|
||||
@@ -3250,6 +3283,16 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
iq->num_target_queries = 0;
|
||||
return processDSNSFind(qstate, iq, id);
|
||||
}
|
||||
if(iq->qchase.qtype == LDNS_RR_TYPE_DNSKEY && SERVE_EXPIRED
|
||||
&& qstate->is_valrec &&
|
||||
reply_find_answer_rrset(&iq->qchase, iq->response->rep) != NULL) {
|
||||
/* clean out the authority section, if any, so it
|
||||
* does not overwrite dnssec valid data in the
|
||||
* validation recursion lookup. */
|
||||
verbose(VERB_ALGO, "make DNSKEY minimal for serve "
|
||||
"expired");
|
||||
iter_make_minimal(iq->response->rep);
|
||||
}
|
||||
if(!qstate->no_cache_store)
|
||||
iter_dns_store(qstate->env, &iq->response->qinfo,
|
||||
iq->response->rep,
|
||||
@@ -3257,7 +3300,7 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
qstate->prefetch_leeway,
|
||||
iq->dp&&iq->dp->has_parent_side_NS,
|
||||
qstate->region, qstate->query_flags,
|
||||
qstate->qstarttime);
|
||||
qstate->qstarttime, qstate->is_valrec);
|
||||
/* close down outstanding requests to be discarded */
|
||||
outbound_list_clear(&iq->outlist);
|
||||
iq->num_current_queries = 0;
|
||||
@@ -3351,7 +3394,7 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
/* no prefetch-leeway, since its not the answer */
|
||||
iter_dns_store(qstate->env, &iq->response->qinfo,
|
||||
iq->response->rep, 1, 0, 0, NULL, 0,
|
||||
qstate->qstarttime);
|
||||
qstate->qstarttime, qstate->is_valrec);
|
||||
if(iq->store_parent_NS)
|
||||
iter_store_parentside_NS(qstate->env,
|
||||
iq->response->rep);
|
||||
@@ -3400,7 +3443,7 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
old_dp->name, old_dp->namelen);
|
||||
}
|
||||
if(!cache_fill_missing(qstate->env, iq->qchase.qclass,
|
||||
qstate->region, iq->dp)) {
|
||||
qstate->region, iq->dp, 0)) {
|
||||
errinf(qstate, "malloc failure, copy extra info into delegation point");
|
||||
return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
|
||||
}
|
||||
@@ -3481,7 +3524,8 @@ 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->qstarttime);
|
||||
qstate->query_flags, qstate->qstarttime,
|
||||
qstate->is_valrec);
|
||||
/* set the current request's qname to the new value. */
|
||||
iq->qchase.qname = sname;
|
||||
iq->qchase.qname_len = snamelen;
|
||||
@@ -3825,7 +3869,7 @@ processTargetResponse(struct module_qstate* qstate, int id,
|
||||
} else {
|
||||
verbose(VERB_ALGO, "iterator TargetResponse failed");
|
||||
delegpt_mark_neg(dpns, qstate->qinfo.qtype);
|
||||
if((dpns->got4 == 2 || (!ie->supports_ipv4 && !ie->use_nat64)) &&
|
||||
if((dpns->got4 == 2 || (!ie->supports_ipv4 && !ie->nat64.use_nat64)) &&
|
||||
(dpns->got6 == 2 || !ie->supports_ipv6)) {
|
||||
dpns->resolved = 1; /* fail the target */
|
||||
/* do not count cached answers */
|
||||
@@ -3969,6 +4013,8 @@ processClassResponse(struct module_qstate* qstate, int id,
|
||||
to->rep->prefetch_ttl = from->rep->prefetch_ttl;
|
||||
if(from->rep->serve_expired_ttl < to->rep->serve_expired_ttl)
|
||||
to->rep->serve_expired_ttl = from->rep->serve_expired_ttl;
|
||||
if(from->rep->serve_expired_norec_ttl < to->rep->serve_expired_norec_ttl)
|
||||
to->rep->serve_expired_norec_ttl = from->rep->serve_expired_norec_ttl;
|
||||
}
|
||||
/* are we done? */
|
||||
foriq->num_current_queries --;
|
||||
@@ -4106,7 +4152,7 @@ processFinished(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
iq->response->rep, 0, qstate->prefetch_leeway,
|
||||
iq->dp&&iq->dp->has_parent_side_NS,
|
||||
qstate->region, qstate->query_flags,
|
||||
qstate->qstarttime);
|
||||
qstate->qstarttime, qstate->is_valrec);
|
||||
}
|
||||
}
|
||||
qstate->return_rcode = LDNS_RCODE_NOERROR;
|
||||
@@ -4286,6 +4332,7 @@ process_response(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
}
|
||||
|
||||
/* Copy the edns options we may got from the back end */
|
||||
qstate->edns_opts_back_in = NULL;
|
||||
if(edns.opt_list_in) {
|
||||
qstate->edns_opts_back_in = edns_opt_copy_region(edns.opt_list_in,
|
||||
qstate->region);
|
||||
@@ -4331,7 +4378,10 @@ process_response(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
if(verbosity >= VERB_ALGO)
|
||||
log_dns_msg("incoming scrubbed packet:", &iq->response->qinfo,
|
||||
iq->response->rep);
|
||||
|
||||
|
||||
if(qstate->env->cfg->aggressive_nsec) {
|
||||
limit_nsec_ttl(iq->response);
|
||||
}
|
||||
if(event == module_event_capsfail || iq->caps_fallback) {
|
||||
if(qstate->env->cfg->qname_minimisation &&
|
||||
iq->minimisation_state != DONOT_MINIMISE_STATE) {
|
||||
|
||||
+22
-10
@@ -46,8 +46,6 @@
|
||||
#include "util/data/msgreply.h"
|
||||
#include "util/module.h"
|
||||
struct delegpt;
|
||||
struct iter_hints;
|
||||
struct iter_forwards;
|
||||
struct iter_donotq;
|
||||
struct iter_prep_list;
|
||||
struct iter_priv;
|
||||
@@ -55,6 +53,9 @@ struct rbtree_type;
|
||||
|
||||
/** max number of targets spawned for a query and its subqueries */
|
||||
#define MAX_TARGET_COUNT 64
|
||||
/** max number of upstream queries for a query and its subqueries, it is
|
||||
* never reset. */
|
||||
extern int MAX_GLOBAL_QUOTA;
|
||||
/** max number of target lookups per qstate, per delegation point */
|
||||
#define MAX_DP_TARGET_COUNT 16
|
||||
/** max number of nxdomains allowed for target lookups for a query and
|
||||
@@ -105,15 +106,9 @@ extern int BLACKLIST_PENALTY;
|
||||
#define EMPTY_NODATA_RETRY_COUNT 2
|
||||
|
||||
/**
|
||||
* Global state for the iterator.
|
||||
* Iterator global state for nat64.
|
||||
*/
|
||||
struct iter_env {
|
||||
/** A flag to indicate whether or not we have an IPv6 route */
|
||||
int supports_ipv6;
|
||||
|
||||
/** A flag to indicate whether or not we have an IPv4 route */
|
||||
int supports_ipv4;
|
||||
|
||||
struct iter_nat64 {
|
||||
/** A flag to locally apply NAT64 to make IPv4 addrs into IPv6 */
|
||||
int use_nat64;
|
||||
|
||||
@@ -125,6 +120,20 @@ struct iter_env {
|
||||
|
||||
/** CIDR mask length of NAT64 prefix */
|
||||
int nat64_prefix_net;
|
||||
};
|
||||
|
||||
/**
|
||||
* Global state for the iterator.
|
||||
*/
|
||||
struct iter_env {
|
||||
/** A flag to indicate whether or not we have an IPv6 route */
|
||||
int supports_ipv6;
|
||||
|
||||
/** A flag to indicate whether or not we have an IPv4 route */
|
||||
int supports_ipv4;
|
||||
|
||||
/** State for nat64 */
|
||||
struct iter_nat64 nat64;
|
||||
|
||||
/** A set of inetaddrs that should never be queried. */
|
||||
struct iter_donotq* donotq;
|
||||
@@ -248,6 +257,9 @@ enum target_count_variables {
|
||||
TARGET_COUNT_QUERIES,
|
||||
/** Number of nxdomain responses encountered. */
|
||||
TARGET_COUNT_NX,
|
||||
/** Global quota on number of queries to upstream servers per
|
||||
* client request, that is never reset. */
|
||||
TARGET_COUNT_GLOBAL_QUOTA,
|
||||
|
||||
/** This should stay last here, it is used for the allocation */
|
||||
TARGET_COUNT_MAX,
|
||||
|
||||
@@ -395,7 +395,7 @@ context_serialize_cancel(struct ctx_query* q, uint32_t* len)
|
||||
/* format of cancel:
|
||||
* o uint32 cmd
|
||||
* o uint32 async-id */
|
||||
uint8_t* p = (uint8_t*)reallocarray(NULL, sizeof(uint32_t), 2);
|
||||
uint8_t* p = (uint8_t*)reallocarray(NULL, 2, sizeof(uint32_t));
|
||||
if(!p) return NULL;
|
||||
*len = 2*sizeof(uint32_t);
|
||||
sldns_write_uint32(p, UB_LIBCMD_CANCEL);
|
||||
|
||||
+32
-1
@@ -292,6 +292,7 @@ libworker_do_cmd(struct libworker* w, uint8_t* msg, uint32_t len)
|
||||
log_err("unknown command for bg worker %d",
|
||||
(int)context_serial_getcmd(msg, len));
|
||||
/* and fall through to quit */
|
||||
ATTR_FALLTHROUGH
|
||||
/* fallthrough */
|
||||
case UB_LIBCMD_QUIT:
|
||||
free(msg);
|
||||
@@ -422,7 +423,7 @@ int libworker_bg(struct ub_ctx* ctx)
|
||||
static int
|
||||
fill_canon(struct ub_result* res, uint8_t* s)
|
||||
{
|
||||
char buf[255+2];
|
||||
char buf[LDNS_MAX_DOMAINLEN];
|
||||
dname_str(s, buf);
|
||||
res->canonname = strdup(buf);
|
||||
return res->canonname != 0;
|
||||
@@ -1057,3 +1058,33 @@ void dtio_mainfdcallback(int ATTR_UNUSED(fd), short ATTR_UNUSED(ev),
|
||||
log_assert(0);
|
||||
}
|
||||
#endif
|
||||
|
||||
void fast_reload_service_cb(int ATTR_UNUSED(fd), short ATTR_UNUSED(ev),
|
||||
void* ATTR_UNUSED(arg))
|
||||
{
|
||||
log_assert(0);
|
||||
}
|
||||
|
||||
int fast_reload_client_callback(struct comm_point* ATTR_UNUSED(c),
|
||||
void* ATTR_UNUSED(arg), int ATTR_UNUSED(error),
|
||||
struct comm_reply* ATTR_UNUSED(repinfo))
|
||||
{
|
||||
log_assert(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef HAVE_NGTCP2
|
||||
void doq_client_event_cb(int ATTR_UNUSED(fd), short ATTR_UNUSED(ev),
|
||||
void* ATTR_UNUSED(arg))
|
||||
{
|
||||
log_assert(0);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_NGTCP2
|
||||
void doq_client_timer_cb(int ATTR_UNUSED(fd), short ATTR_UNUSED(ev),
|
||||
void* ATTR_UNUSED(arg))
|
||||
{
|
||||
log_assert(0);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -30,6 +30,7 @@ def dnssecParse(domain, rrType=RR_TYPE_A):
|
||||
resolver = ub_ctx()
|
||||
resolver.add_ta(". IN DS 19036 8 2 49AAC11D7B6F6446702E54A1607371607A1A41855200FD2CE1CDDE32F24E8FB5")
|
||||
resolver.add_ta(". IN DS 20326 8 2 E06D44B80B8F1D39A95C0B0D7C65D08458E880409BBC683457104237C7F8EC8D")
|
||||
resolver.add_ta(". IN DS 38696 8 2 683D2D0ACB8C9B712A1948B27F741219298D0A450D612C483AF444A4C0FB2B16")
|
||||
|
||||
dnssecParse("nic.cz")
|
||||
dnssecParse("nonexistent-domain-blablabla.cz")
|
||||
|
||||
@@ -845,6 +845,16 @@ struct ub_server_stats {
|
||||
long long qtls_resume;
|
||||
/** RPZ action stats */
|
||||
long long rpz_action[UB_STATS_RPZ_ACTION_NUM];
|
||||
/** number of bytes in QUIC buffers */
|
||||
long long mem_quic;
|
||||
/** number of queries over (DNS over) QUIC */
|
||||
long long qquic;
|
||||
/** number of queries removed due to discard-timeout */
|
||||
long long num_queries_discard_timeout;
|
||||
/** number of queries removed due to wait-limit */
|
||||
long long num_queries_wait_limit;
|
||||
/** number of dns error reports generated */
|
||||
long long num_dns_error_reports;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -176,6 +176,10 @@ config_file
|
||||
|
||||
Harden against spoofed glue (out of zone data).
|
||||
|
||||
.. attribute:: harden_unverified_glue
|
||||
|
||||
Harden against unverified glue.
|
||||
|
||||
.. attribute:: harden_dnssec_stripped
|
||||
|
||||
Harden against receiving no DNSSEC data for trust anchor.
|
||||
|
||||
@@ -204,7 +204,7 @@ struct query_info {
|
||||
|
||||
%inline %{
|
||||
PyObject* dnameAsStr(PyObject* dname) {
|
||||
char buf[LDNS_MAX_DOMAINLEN+1];
|
||||
char buf[LDNS_MAX_DOMAINLEN];
|
||||
buf[0] = '\0';
|
||||
dname_str((uint8_t*)PyBytes_AsString(dname), buf);
|
||||
return PyString_FromString(buf);
|
||||
@@ -1009,6 +1009,7 @@ struct config_file {
|
||||
int harden_short_bufsize;
|
||||
int harden_large_queries;
|
||||
int harden_glue;
|
||||
int harden_unverified_glue;
|
||||
int harden_dnssec_stripped;
|
||||
int harden_referral_path;
|
||||
int use_caps_bits_for_id;
|
||||
|
||||
@@ -73,7 +73,7 @@ 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->qstarttime);
|
||||
qstate->qstarttime, qstate->is_valrec);
|
||||
}
|
||||
|
||||
/* Invalidate the message associated with query_info stored in message cache */
|
||||
|
||||
+64
-10
@@ -105,6 +105,7 @@ respip_sockaddr_find_or_create(struct respip_set* set, struct sockaddr_storage*
|
||||
socklen_t addrlen, int net, int create, const char* ipstr)
|
||||
{
|
||||
struct resp_addr* node;
|
||||
log_assert(set);
|
||||
node = (struct resp_addr*)addr_tree_find(&set->ip_tree, addr, addrlen, net);
|
||||
if(!node && create) {
|
||||
node = regional_alloc_zero(set->region, sizeof(*node));
|
||||
@@ -128,6 +129,7 @@ void
|
||||
respip_sockaddr_delete(struct respip_set* set, struct resp_addr* node)
|
||||
{
|
||||
struct resp_addr* prev;
|
||||
log_assert(set);
|
||||
prev = (struct resp_addr*)rbtree_previous((struct rbnode_type*)node);
|
||||
lock_rw_destroy(&node->lock);
|
||||
(void)rbtree_delete(&set->ip_tree, node);
|
||||
@@ -146,6 +148,7 @@ respip_find_or_create(struct respip_set* set, const char* ipstr, int create)
|
||||
struct sockaddr_storage addr;
|
||||
int net;
|
||||
socklen_t addrlen;
|
||||
log_assert(set);
|
||||
|
||||
if(!netblockstrtoaddr(ipstr, 0, &addr, &addrlen, &net)) {
|
||||
log_err("cannot parse netblock: '%s'", ipstr);
|
||||
@@ -160,6 +163,7 @@ respip_tag_cfg(struct respip_set* set, const char* ipstr,
|
||||
const uint8_t* taglist, size_t taglen)
|
||||
{
|
||||
struct resp_addr* node;
|
||||
log_assert(set);
|
||||
|
||||
if(!(node=respip_find_or_create(set, ipstr, 1)))
|
||||
return 0;
|
||||
@@ -183,6 +187,7 @@ respip_action_cfg(struct respip_set* set, const char* ipstr,
|
||||
{
|
||||
struct resp_addr* node;
|
||||
enum respip_action action;
|
||||
log_assert(set);
|
||||
|
||||
if(!(node=respip_find_or_create(set, ipstr, 1)))
|
||||
return 0;
|
||||
@@ -325,6 +330,7 @@ static int
|
||||
respip_data_cfg(struct respip_set* set, const char* ipstr, const char* rrstr)
|
||||
{
|
||||
struct resp_addr* node;
|
||||
log_assert(set);
|
||||
|
||||
node=respip_find_or_create(set, ipstr, 0);
|
||||
if(!node || node->action == respip_none) {
|
||||
@@ -344,6 +350,7 @@ respip_set_apply_cfg(struct respip_set* set, char* const* tagname, int num_tags,
|
||||
struct config_strbytelist* p;
|
||||
struct config_str2list* pa;
|
||||
struct config_str2list* pd;
|
||||
log_assert(set);
|
||||
|
||||
set->tagname = tagname;
|
||||
set->num_tags = num_tags;
|
||||
@@ -609,6 +616,7 @@ respip_addr_lookup(const struct reply_info *rep, struct respip_set* rs,
|
||||
struct resp_addr* ra;
|
||||
struct sockaddr_storage ss;
|
||||
socklen_t addrlen;
|
||||
log_assert(rs);
|
||||
|
||||
lock_rw_rdlock(&rs->lock);
|
||||
for(i=0; i<rep->an_numrrsets; i++) {
|
||||
@@ -867,7 +875,8 @@ 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, int* rpz_passthru)
|
||||
struct regional* region, struct auth_zones* az, int* rpz_passthru,
|
||||
struct views* views, struct respip_set* ipset)
|
||||
{
|
||||
const uint8_t* ctaglist;
|
||||
size_t ctaglen;
|
||||
@@ -876,7 +885,6 @@ respip_rewrite_reply(const struct query_info* qinfo,
|
||||
struct config_strlist** tag_datas;
|
||||
size_t tag_datas_size;
|
||||
struct view* view = NULL;
|
||||
struct respip_set* ipset = NULL;
|
||||
size_t rrset_id = 0, rr_id = 0;
|
||||
enum respip_action action = respip_none;
|
||||
int tag = -1;
|
||||
@@ -899,8 +907,20 @@ respip_rewrite_reply(const struct query_info* qinfo,
|
||||
tag_actions_size = cinfo->tag_actions_size;
|
||||
tag_datas = cinfo->tag_datas;
|
||||
tag_datas_size = cinfo->tag_datas_size;
|
||||
view = cinfo->view;
|
||||
ipset = cinfo->respip_set;
|
||||
if(cinfo->view) {
|
||||
view = cinfo->view;
|
||||
lock_rw_rdlock(&view->lock);
|
||||
} else if(cinfo->view_name) {
|
||||
view = views_find_view(views, cinfo->view_name, 0);
|
||||
if(!view) {
|
||||
/* If the view no longer exists, the rewrite can not
|
||||
* be processed further. */
|
||||
verbose(VERB_ALGO, "respip: failed because view %s no "
|
||||
"longer exists", cinfo->view_name);
|
||||
return 0;
|
||||
}
|
||||
/* The view is rdlocked by views_find_view. */
|
||||
}
|
||||
|
||||
log_assert(ipset);
|
||||
|
||||
@@ -915,7 +935,6 @@ respip_rewrite_reply(const struct query_info* qinfo,
|
||||
* Note also that we assume 'view' is valid in this function, which
|
||||
* should be safe (see unbound bug #1191) */
|
||||
if(view) {
|
||||
lock_rw_rdlock(&view->lock);
|
||||
if(view->respip_set) {
|
||||
if((raddr = respip_addr_lookup(rep,
|
||||
view->respip_set, &rrset_id, &rr_id))) {
|
||||
@@ -961,7 +980,7 @@ respip_rewrite_reply(const struct query_info* qinfo,
|
||||
struct sockaddr_storage ss;
|
||||
socklen_t ss_len = 0;
|
||||
char nm[256], ip[256];
|
||||
char qn[255+1];
|
||||
char qn[LDNS_MAX_DOMAINLEN];
|
||||
if(!rdata2sockaddr(rep->rrsets[rrset_id]->entry.data, ntohs(rep->rrsets[rrset_id]->rk.type), rr_id, &ss, &ss_len))
|
||||
snprintf(ip, sizeof(ip), "invalidRRdata");
|
||||
else
|
||||
@@ -1101,7 +1120,8 @@ respip_operate(struct module_qstate* qstate, enum module_ev event, int id,
|
||||
qstate->client_info, qstate->return_msg->rep,
|
||||
&new_rep, &actinfo, &alias_rrset, 0,
|
||||
qstate->region, qstate->env->auth_zones,
|
||||
&qstate->rpz_passthru)) {
|
||||
&qstate->rpz_passthru, qstate->env->views,
|
||||
qstate->env->respip_set)) {
|
||||
goto servfail;
|
||||
}
|
||||
if(actinfo.action != respip_none) {
|
||||
@@ -1149,7 +1169,8 @@ respip_merge_cname(struct reply_info* base_rep,
|
||||
const struct query_info* qinfo, const struct reply_info* tgt_rep,
|
||||
const struct respip_client_info* cinfo, int must_validate,
|
||||
struct reply_info** new_repp, struct regional* region,
|
||||
struct auth_zones* az)
|
||||
struct auth_zones* az, struct views* views,
|
||||
struct respip_set* respip_set)
|
||||
{
|
||||
struct reply_info* new_rep;
|
||||
struct reply_info* tmp_rep = NULL; /* just a placeholder */
|
||||
@@ -1176,7 +1197,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, NULL))
|
||||
&alias_rrset, 1, region, az, NULL, views, respip_set))
|
||||
return 0;
|
||||
if(actinfo.action != respip_none) {
|
||||
log_info("CNAME target of redirect response-ip action would "
|
||||
@@ -1229,7 +1250,8 @@ respip_inform_super(struct module_qstate* qstate, int id,
|
||||
if(!respip_merge_cname(super->return_msg->rep, &qstate->qinfo,
|
||||
qstate->return_msg->rep, super->client_info,
|
||||
super->env->need_to_validate, &new_rep, super->region,
|
||||
qstate->env->auth_zones))
|
||||
qstate->env->auth_zones, qstate->env->views,
|
||||
qstate->env->respip_set))
|
||||
goto fail;
|
||||
super->return_msg->rep = new_rep;
|
||||
return;
|
||||
@@ -1326,3 +1348,35 @@ respip_inform_print(struct respip_action_info* respip_actinfo, uint8_t* qname,
|
||||
(actionstr) ? actionstr : "inform", srcip, port);
|
||||
log_nametypeclass(NO_VERBOSE, txt, qname, qtype, qclass);
|
||||
}
|
||||
|
||||
size_t respip_set_get_mem(struct respip_set* set)
|
||||
{
|
||||
size_t m;
|
||||
if(!set) return 0;
|
||||
m = sizeof(*set);
|
||||
lock_rw_rdlock(&set->lock);
|
||||
m += regional_get_mem(set->region);
|
||||
lock_rw_unlock(&set->lock);
|
||||
return m;
|
||||
}
|
||||
|
||||
void
|
||||
respip_set_swap_tree(struct respip_set* respip_set,
|
||||
struct respip_set* data)
|
||||
{
|
||||
rbnode_type* oldroot = respip_set->ip_tree.root;
|
||||
size_t oldcount = respip_set->ip_tree.count;
|
||||
struct regional* oldregion = respip_set->region;
|
||||
char* const* oldtagname = respip_set->tagname;
|
||||
int oldnum_tags = respip_set->num_tags;
|
||||
respip_set->ip_tree.root = data->ip_tree.root;
|
||||
respip_set->ip_tree.count = data->ip_tree.count;
|
||||
respip_set->region = data->region;
|
||||
respip_set->tagname = data->tagname;
|
||||
respip_set->num_tags = data->num_tags;
|
||||
data->ip_tree.root = oldroot;
|
||||
data->ip_tree.count = oldcount;
|
||||
data->region = oldregion;
|
||||
data->tagname = oldtagname;
|
||||
data->num_tags = oldnum_tags;
|
||||
}
|
||||
|
||||
+28
-5
@@ -23,7 +23,8 @@
|
||||
struct respip_set {
|
||||
struct regional* region;
|
||||
struct rbtree_type ip_tree;
|
||||
lock_rw_type lock; /* lock on the respip tree */
|
||||
lock_rw_type lock; /* lock on the respip tree. It is ordered
|
||||
after views and before hints, stubs and local zones. */
|
||||
char* const* tagname; /* shallow copy of tag names, for logging */
|
||||
int num_tags; /* number of tagname entries */
|
||||
};
|
||||
@@ -59,7 +60,6 @@ struct respip_addr_info;
|
||||
* This is essentially a subset of acl_addr (except for respip_set) but
|
||||
* defined as a separate structure to avoid dependency on the daemon-specific
|
||||
* structure.
|
||||
* respip_set is supposed to refer to the response-ip set for the global view.
|
||||
*/
|
||||
struct respip_client_info {
|
||||
uint8_t* taglist;
|
||||
@@ -68,8 +68,12 @@ struct respip_client_info {
|
||||
size_t tag_actions_size;
|
||||
struct config_strlist** tag_datas;
|
||||
size_t tag_datas_size;
|
||||
/** The view for the action, during cache callback that is by
|
||||
* pointer. */
|
||||
struct view* view;
|
||||
struct respip_set* respip_set;
|
||||
/** If from module query state, the view pointer is NULL, but the
|
||||
* name is stored in reference to the view. */
|
||||
char* view_name;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -149,13 +153,16 @@ int respip_views_apply_cfg(struct views* vs, struct config_file* cfg,
|
||||
* on error.
|
||||
* @param region: allocator to build *new_repp.
|
||||
* @param az: auth zones containing RPZ information.
|
||||
* @param views: views tree to lookup view used.
|
||||
* @param respip_set: the respip set for the global view.
|
||||
* @return 1 on success, 0 on error.
|
||||
*/
|
||||
int respip_merge_cname(struct reply_info* base_rep,
|
||||
const struct query_info* qinfo, const struct reply_info* tgt_rep,
|
||||
const struct respip_client_info* cinfo, int must_validate,
|
||||
struct reply_info** new_repp, struct regional* region,
|
||||
struct auth_zones* az);
|
||||
struct auth_zones* az, struct views* views,
|
||||
struct respip_set* respip_set);
|
||||
|
||||
/**
|
||||
* See if any IP-based action should apply to any IP address of AAAA/A answer
|
||||
@@ -178,6 +185,8 @@ int respip_merge_cname(struct reply_info* base_rep,
|
||||
* @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.
|
||||
* @param views: views tree to lookup view used.
|
||||
* @param ipset: the respip set for the global view.
|
||||
* @return 1 on success, 0 on error.
|
||||
*/
|
||||
int respip_rewrite_reply(const struct query_info* qinfo,
|
||||
@@ -186,7 +195,7 @@ int respip_rewrite_reply(const struct query_info* qinfo,
|
||||
struct respip_action_info* actinfo,
|
||||
struct ub_packed_rrset_key** alias_rrset,
|
||||
int search_only, struct regional* region, struct auth_zones* az,
|
||||
int* rpz_passthru);
|
||||
int* rpz_passthru, struct views* views, struct respip_set* ipset);
|
||||
|
||||
/**
|
||||
* Get the response-ip function block.
|
||||
@@ -302,4 +311,18 @@ respip_sockaddr_delete(struct respip_set* set, struct resp_addr* node);
|
||||
|
||||
struct ub_packed_rrset_key*
|
||||
respip_copy_rrset(const struct ub_packed_rrset_key* key, struct regional* region);
|
||||
|
||||
/** Get memory usage of respip set tree. The routine locks and unlocks the
|
||||
* set for reading. */
|
||||
size_t respip_set_get_mem(struct respip_set* set);
|
||||
|
||||
/**
|
||||
* Swap internal tree with preallocated entries. Caller should manage
|
||||
* the locks.
|
||||
* @param respip_set: response ip tree
|
||||
* @param data: preallocated information.
|
||||
*/
|
||||
void respip_set_swap_tree(struct respip_set* respip_set,
|
||||
struct respip_set* data);
|
||||
|
||||
#endif /* RESPIP_RESPIP_H */
|
||||
|
||||
+248
-67
@@ -1578,7 +1578,7 @@ auth_zone_read_zonefile(struct auth_zone* z, struct config_file* cfg)
|
||||
cfg->chrootdir, strlen(cfg->chrootdir)) == 0)
|
||||
zfilename += strlen(cfg->chrootdir);
|
||||
if(verbosity >= VERB_ALGO) {
|
||||
char nm[255+1];
|
||||
char nm[LDNS_MAX_DOMAINLEN];
|
||||
dname_str(z->name, nm);
|
||||
verbose(VERB_ALGO, "read zonefile %s for %s", zfilename, nm);
|
||||
}
|
||||
@@ -1942,7 +1942,7 @@ static int auth_zone_zonemd_check_hash(struct auth_zone* z,
|
||||
unsupported_reason = *reason;
|
||||
/* continue to check for valid ZONEMD */
|
||||
if(verbosity >= VERB_ALGO) {
|
||||
char zstr[255+1];
|
||||
char zstr[LDNS_MAX_DOMAINLEN];
|
||||
dname_str(z->name, zstr);
|
||||
verbose(VERB_ALGO, "auth-zone %s ZONEMD %d %d is unsupported: %s", zstr, (int)scheme, (int)hashalgo, *reason);
|
||||
}
|
||||
@@ -1950,7 +1950,7 @@ static int auth_zone_zonemd_check_hash(struct auth_zone* z,
|
||||
continue;
|
||||
}
|
||||
if(verbosity >= VERB_ALGO) {
|
||||
char zstr[255+1];
|
||||
char zstr[LDNS_MAX_DOMAINLEN];
|
||||
dname_str(z->name, zstr);
|
||||
if(!*reason)
|
||||
verbose(VERB_ALGO, "auth-zone %s ZONEMD hash is correct", zstr);
|
||||
@@ -1973,7 +1973,7 @@ static int auth_zone_zonemd_check_hash(struct auth_zone* z,
|
||||
if(!*reason)
|
||||
*reason = "no ZONEMD records found";
|
||||
if(verbosity >= VERB_ALGO) {
|
||||
char zstr[255+1];
|
||||
char zstr[LDNS_MAX_DOMAINLEN];
|
||||
dname_str(z->name, zstr);
|
||||
verbose(VERB_ALGO, "auth-zone %s ZONEMD failed: %s", zstr, *reason);
|
||||
}
|
||||
@@ -2317,9 +2317,6 @@ auth_free_masters(struct auth_master* list)
|
||||
}
|
||||
}
|
||||
|
||||
/** delete auth xfer structure
|
||||
* @param xfr: delete this xfer and its tasks.
|
||||
*/
|
||||
void
|
||||
auth_xfer_delete(struct auth_xfer* xfr)
|
||||
{
|
||||
@@ -3610,9 +3607,7 @@ int auth_zones_answer(struct auth_zones* az, struct module_env* env,
|
||||
return 0;
|
||||
}
|
||||
lock_rw_unlock(&z->lock);
|
||||
lock_rw_wrlock(&az->lock);
|
||||
az->num_query_down++;
|
||||
lock_rw_unlock(&az->lock);
|
||||
env->mesh->num_query_authzone_down++;
|
||||
auth_error_encode(qinfo, env, edns, repinfo, buf, temp,
|
||||
LDNS_RCODE_SERVFAIL);
|
||||
return 1;
|
||||
@@ -3625,9 +3620,7 @@ int auth_zones_answer(struct auth_zones* az, struct module_env* env,
|
||||
/* fallback to regular answering (recursive) */
|
||||
return 0;
|
||||
}
|
||||
lock_rw_wrlock(&az->lock);
|
||||
az->num_query_down++;
|
||||
lock_rw_unlock(&az->lock);
|
||||
env->mesh->num_query_authzone_down++;
|
||||
|
||||
/* encode answer */
|
||||
if(!r)
|
||||
@@ -3684,6 +3677,29 @@ auth_zone_parse_notify_serial(sldns_buffer* pkt, uint32_t *serial)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** print addr to str, and if not 53, append "@port_number", for logs. */
|
||||
static void addr_port_to_str(struct sockaddr_storage* addr, socklen_t addrlen,
|
||||
char* buf, size_t len)
|
||||
{
|
||||
uint16_t port = 0;
|
||||
if(addr_is_ip6(addr, addrlen)) {
|
||||
struct sockaddr_in6* sa = (struct sockaddr_in6*)addr;
|
||||
port = ntohs((uint16_t)sa->sin6_port);
|
||||
} else {
|
||||
struct sockaddr_in* sa = (struct sockaddr_in*)addr;
|
||||
port = ntohs((uint16_t)sa->sin_port);
|
||||
}
|
||||
if(port == UNBOUND_DNS_PORT) {
|
||||
/* If it is port 53, print it plainly. */
|
||||
addr_to_str(addr, addrlen, buf, len);
|
||||
} else {
|
||||
char a[256];
|
||||
a[0]=0;
|
||||
addr_to_str(addr, addrlen, a, sizeof(a));
|
||||
snprintf(buf, len, "%s@%d", a, (int)port);
|
||||
}
|
||||
}
|
||||
|
||||
/** see if addr appears in the list */
|
||||
static int
|
||||
addr_in_list(struct auth_addr* list, struct sockaddr_storage* addr,
|
||||
@@ -4780,8 +4796,8 @@ log_rrlist_position(const char* label, struct auth_chunk* rr_chunk,
|
||||
{
|
||||
sldns_buffer pkt;
|
||||
size_t dlen;
|
||||
uint8_t buf[256];
|
||||
char str[256];
|
||||
uint8_t buf[LDNS_MAX_DOMAINLEN];
|
||||
char str[LDNS_MAX_DOMAINLEN];
|
||||
char typestr[32];
|
||||
sldns_buffer_init_frm_data(&pkt, rr_chunk->data, rr_chunk->len);
|
||||
sldns_buffer_set_position(&pkt, (size_t)(rr_dname -
|
||||
@@ -5208,7 +5224,7 @@ xfr_write_after_update(struct auth_xfer* xfr, struct module_env* env)
|
||||
cfg->chrootdir, strlen(cfg->chrootdir)) == 0)
|
||||
zfilename += strlen(cfg->chrootdir);
|
||||
if(verbosity >= VERB_ALGO) {
|
||||
char nm[255+1];
|
||||
char nm[LDNS_MAX_DOMAINLEN];
|
||||
dname_str(z->name, nm);
|
||||
verbose(VERB_ALGO, "write zonefile %s for %s", zfilename, nm);
|
||||
}
|
||||
@@ -5325,7 +5341,7 @@ xfr_process_chunk_list(struct auth_xfer* xfr, struct module_env* env,
|
||||
/* holding z lock */
|
||||
auth_zone_verify_zonemd(z, env, &env->mesh->mods, NULL, 0, 0);
|
||||
if(z->zone_expired) {
|
||||
char zname[256];
|
||||
char zname[LDNS_MAX_DOMAINLEN];
|
||||
/* ZONEMD must have failed */
|
||||
/* reacquire locks, so we hold xfr lock on exit of routine,
|
||||
* and both xfr and z again after releasing xfr for potential
|
||||
@@ -5357,7 +5373,7 @@ xfr_process_chunk_list(struct auth_xfer* xfr, struct module_env* env,
|
||||
lock_rw_unlock(&z->lock);
|
||||
|
||||
if(verbosity >= VERB_QUERY && xfr->have_zone) {
|
||||
char zname[256];
|
||||
char zname[LDNS_MAX_DOMAINLEN];
|
||||
dname_str(xfr->name, zname);
|
||||
verbose(VERB_QUERY, "auth zone %s updated to serial %u", zname,
|
||||
(unsigned)xfr->serial);
|
||||
@@ -5419,7 +5435,7 @@ xfr_transfer_lookup_host(struct auth_xfer* xfr, struct module_env* env)
|
||||
qinfo.local_alias = NULL;
|
||||
if(verbosity >= VERB_ALGO) {
|
||||
char buf1[512];
|
||||
char buf2[LDNS_MAX_DOMAINLEN+1];
|
||||
char buf2[LDNS_MAX_DOMAINLEN];
|
||||
dname_str(xfr->name, buf2);
|
||||
snprintf(buf1, sizeof(buf1), "auth zone %s: master lookup"
|
||||
" for task_transfer", buf2);
|
||||
@@ -5475,7 +5491,7 @@ xfr_transfer_init_fetch(struct auth_xfer* xfr, struct module_env* env)
|
||||
/* the ones that are not in addr format are supposed
|
||||
* to be looked up. The lookup has failed however,
|
||||
* so skip them */
|
||||
char zname[255+1];
|
||||
char zname[LDNS_MAX_DOMAINLEN];
|
||||
dname_str(xfr->name, zname);
|
||||
log_err("%s: failed lookup, cannot transfer from master %s",
|
||||
zname, master->host);
|
||||
@@ -5514,18 +5530,18 @@ xfr_transfer_init_fetch(struct auth_xfer* xfr, struct module_env* env)
|
||||
&addr, addrlen, -1, master->ssl, master->host,
|
||||
master->file, env->cfg);
|
||||
if(!xfr->task_transfer->cp) {
|
||||
char zname[255+1], as[256];
|
||||
char zname[LDNS_MAX_DOMAINLEN], as[256];
|
||||
dname_str(xfr->name, zname);
|
||||
addr_to_str(&addr, addrlen, as, sizeof(as));
|
||||
addr_port_to_str(&addr, addrlen, as, sizeof(as));
|
||||
verbose(VERB_ALGO, "cannot create http cp "
|
||||
"connection for %s to %s", zname, as);
|
||||
return 0;
|
||||
}
|
||||
comm_timer_set(xfr->task_transfer->timer, &t);
|
||||
if(verbosity >= VERB_ALGO) {
|
||||
char zname[255+1], as[256];
|
||||
char zname[LDNS_MAX_DOMAINLEN], as[256];
|
||||
dname_str(xfr->name, zname);
|
||||
addr_to_str(&addr, addrlen, as, sizeof(as));
|
||||
addr_port_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 */
|
||||
@@ -5546,18 +5562,18 @@ xfr_transfer_init_fetch(struct auth_xfer* xfr, struct module_env* env)
|
||||
env->scratch_buffer, -1,
|
||||
auth_name != NULL, auth_name);
|
||||
if(!xfr->task_transfer->cp) {
|
||||
char zname[255+1], as[256];
|
||||
char zname[LDNS_MAX_DOMAINLEN], as[256];
|
||||
dname_str(xfr->name, zname);
|
||||
addr_to_str(&addr, addrlen, as, sizeof(as));
|
||||
addr_port_to_str(&addr, addrlen, as, sizeof(as));
|
||||
verbose(VERB_ALGO, "cannot create tcp cp connection for "
|
||||
"xfr %s to %s", zname, as);
|
||||
return 0;
|
||||
}
|
||||
comm_timer_set(xfr->task_transfer->timer, &t);
|
||||
if(verbosity >= VERB_ALGO) {
|
||||
char zname[255+1], as[256];
|
||||
char zname[LDNS_MAX_DOMAINLEN], as[256];
|
||||
dname_str(xfr->name, zname);
|
||||
addr_to_str(&addr, addrlen, as, sizeof(as));
|
||||
addr_port_to_str(&addr, addrlen, as, sizeof(as));
|
||||
verbose(VERB_ALGO, "auth zone %s transfer next %s fetch from %s started", zname,
|
||||
(xfr->task_transfer->on_ixfr?"IXFR":"AXFR"), as);
|
||||
}
|
||||
@@ -5579,7 +5595,7 @@ xfr_transfer_nexttarget_or_end(struct auth_xfer* xfr, struct module_env* env)
|
||||
* and that calls the callback just like a full
|
||||
* lookup and lookup failures also call callback */
|
||||
if(verbosity >= VERB_ALGO) {
|
||||
char zname[255+1];
|
||||
char zname[LDNS_MAX_DOMAINLEN];
|
||||
dname_str(xfr->name, zname);
|
||||
verbose(VERB_ALGO, "auth zone %s transfer next target lookup", zname);
|
||||
}
|
||||
@@ -5602,7 +5618,7 @@ xfr_transfer_nexttarget_or_end(struct auth_xfer* xfr, struct module_env* env)
|
||||
xfr_transfer_nextmaster(xfr);
|
||||
}
|
||||
if(verbosity >= VERB_ALGO) {
|
||||
char zname[255+1];
|
||||
char zname[LDNS_MAX_DOMAINLEN];
|
||||
dname_str(xfr->name, zname);
|
||||
verbose(VERB_ALGO, "auth zone %s transfer failed, wait", zname);
|
||||
}
|
||||
@@ -5660,7 +5676,7 @@ xfr_master_add_addrs(struct auth_master* m, struct ub_packed_rrset_key* rrset,
|
||||
}
|
||||
if(verbosity >= VERB_ALGO) {
|
||||
char s[64];
|
||||
addr_to_str(&a->addr, a->addrlen, s, sizeof(s));
|
||||
addr_port_to_str(&a->addr, a->addrlen, s, sizeof(s));
|
||||
verbose(VERB_ALGO, "auth host %s lookup %s",
|
||||
m->host, s);
|
||||
}
|
||||
@@ -5705,14 +5721,14 @@ void auth_xfer_transfer_lookup_callback(void* arg, int rcode, sldns_buffer* buf,
|
||||
lookup_target, answer, wanted_qtype);
|
||||
} else {
|
||||
if(verbosity >= VERB_ALGO) {
|
||||
char zname[255+1];
|
||||
char zname[LDNS_MAX_DOMAINLEN];
|
||||
dname_str(xfr->name, zname);
|
||||
verbose(VERB_ALGO, "auth zone %s host %s type %s transfer lookup has nodata", zname, xfr->task_transfer->lookup_target->host, (xfr->task_transfer->lookup_aaaa?"AAAA":"A"));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if(verbosity >= VERB_ALGO) {
|
||||
char zname[255+1];
|
||||
char zname[LDNS_MAX_DOMAINLEN];
|
||||
dname_str(xfr->name, zname);
|
||||
verbose(VERB_ALGO, "auth zone %s host %s type %s transfer lookup has no answer", zname, xfr->task_transfer->lookup_target->host, (xfr->task_transfer->lookup_aaaa?"AAAA":"A"));
|
||||
}
|
||||
@@ -5720,7 +5736,7 @@ void auth_xfer_transfer_lookup_callback(void* arg, int rcode, sldns_buffer* buf,
|
||||
regional_free_all(temp);
|
||||
} else {
|
||||
if(verbosity >= VERB_ALGO) {
|
||||
char zname[255+1];
|
||||
char zname[LDNS_MAX_DOMAINLEN];
|
||||
dname_str(xfr->name, zname);
|
||||
verbose(VERB_ALGO, "auth zone %s host %s type %s transfer lookup failed", zname, xfr->task_transfer->lookup_target->host, (xfr->task_transfer->lookup_aaaa?"AAAA":"A"));
|
||||
}
|
||||
@@ -6362,7 +6378,7 @@ xfr_probe_send_probe(struct auth_xfer* xfr, struct module_env* env,
|
||||
/* the ones that are not in addr format are supposed
|
||||
* to be looked up. The lookup has failed however,
|
||||
* so skip them */
|
||||
char zname[255+1];
|
||||
char zname[LDNS_MAX_DOMAINLEN];
|
||||
dname_str(xfr->name, zname);
|
||||
log_err("%s: failed lookup, cannot probe to master %s",
|
||||
zname, master->host);
|
||||
@@ -6404,9 +6420,9 @@ xfr_probe_send_probe(struct auth_xfer* xfr, struct module_env* env,
|
||||
xfr->task_probe->cp = outnet_comm_point_for_udp(env->outnet,
|
||||
auth_xfer_probe_udp_callback, xfr, &addr, addrlen);
|
||||
if(!xfr->task_probe->cp) {
|
||||
char zname[255+1], as[256];
|
||||
char zname[LDNS_MAX_DOMAINLEN], as[256];
|
||||
dname_str(xfr->name, zname);
|
||||
addr_to_str(&addr, addrlen, as, sizeof(as));
|
||||
addr_port_to_str(&addr, addrlen, as, sizeof(as));
|
||||
verbose(VERB_ALGO, "cannot create udp cp for "
|
||||
"probe %s to %s", zname, as);
|
||||
return 0;
|
||||
@@ -6424,17 +6440,17 @@ xfr_probe_send_probe(struct auth_xfer* xfr, struct module_env* env,
|
||||
/* send udp packet */
|
||||
if(!comm_point_send_udp_msg(xfr->task_probe->cp, env->scratch_buffer,
|
||||
(struct sockaddr*)&addr, addrlen, 0)) {
|
||||
char zname[255+1], as[256];
|
||||
char zname[LDNS_MAX_DOMAINLEN], as[256];
|
||||
dname_str(xfr->name, zname);
|
||||
addr_to_str(&addr, addrlen, as, sizeof(as));
|
||||
addr_port_to_str(&addr, addrlen, as, sizeof(as));
|
||||
verbose(VERB_ALGO, "failed to send soa probe for %s to %s",
|
||||
zname, as);
|
||||
return 0;
|
||||
}
|
||||
if(verbosity >= VERB_ALGO) {
|
||||
char zname[255+1], as[256];
|
||||
char zname[LDNS_MAX_DOMAINLEN], as[256];
|
||||
dname_str(xfr->name, zname);
|
||||
addr_to_str(&addr, addrlen, as, sizeof(as));
|
||||
addr_port_to_str(&addr, addrlen, as, sizeof(as));
|
||||
verbose(VERB_ALGO, "auth zone %s soa probe sent to %s", zname,
|
||||
as);
|
||||
}
|
||||
@@ -6463,7 +6479,7 @@ auth_xfer_probe_timer_callback(void* arg)
|
||||
}
|
||||
|
||||
if(verbosity >= VERB_ALGO) {
|
||||
char zname[255+1];
|
||||
char zname[LDNS_MAX_DOMAINLEN];
|
||||
dname_str(xfr->name, zname);
|
||||
verbose(VERB_ALGO, "auth zone %s soa probe timeout", zname);
|
||||
}
|
||||
@@ -6511,7 +6527,7 @@ auth_xfer_probe_udp_callback(struct comm_point* c, void* arg, int err,
|
||||
&serial)) {
|
||||
/* successful lookup */
|
||||
if(verbosity >= VERB_ALGO) {
|
||||
char buf[256];
|
||||
char buf[LDNS_MAX_DOMAINLEN];
|
||||
dname_str(xfr->name, buf);
|
||||
verbose(VERB_ALGO, "auth zone %s: soa probe "
|
||||
"serial is %u", buf, (unsigned)serial);
|
||||
@@ -6550,14 +6566,14 @@ auth_xfer_probe_udp_callback(struct comm_point* c, void* arg, int err,
|
||||
}
|
||||
} else {
|
||||
if(verbosity >= VERB_ALGO) {
|
||||
char buf[256];
|
||||
char buf[LDNS_MAX_DOMAINLEN];
|
||||
dname_str(xfr->name, buf);
|
||||
verbose(VERB_ALGO, "auth zone %s: bad reply to soa probe", buf);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if(verbosity >= VERB_ALGO) {
|
||||
char buf[256];
|
||||
char buf[LDNS_MAX_DOMAINLEN];
|
||||
dname_str(xfr->name, buf);
|
||||
verbose(VERB_ALGO, "auth zone %s: soa probe failed", buf);
|
||||
}
|
||||
@@ -6614,7 +6630,7 @@ xfr_probe_lookup_host(struct auth_xfer* xfr, struct module_env* env)
|
||||
qinfo.local_alias = NULL;
|
||||
if(verbosity >= VERB_ALGO) {
|
||||
char buf1[512];
|
||||
char buf2[LDNS_MAX_DOMAINLEN+1];
|
||||
char buf2[LDNS_MAX_DOMAINLEN];
|
||||
dname_str(xfr->name, buf2);
|
||||
snprintf(buf1, sizeof(buf1), "auth zone %s: master lookup"
|
||||
" for task_probe", buf2);
|
||||
@@ -6660,7 +6676,7 @@ xfr_probe_send_or_end(struct auth_xfer* xfr, struct module_env* env)
|
||||
* and that calls the callback just like a full
|
||||
* lookup and lookup failures also call callback */
|
||||
if(verbosity >= VERB_ALGO) {
|
||||
char zname[255+1];
|
||||
char zname[LDNS_MAX_DOMAINLEN];
|
||||
dname_str(xfr->name, zname);
|
||||
verbose(VERB_ALGO, "auth zone %s probe next target lookup", zname);
|
||||
}
|
||||
@@ -6673,7 +6689,7 @@ xfr_probe_send_or_end(struct auth_xfer* xfr, struct module_env* env)
|
||||
* allow_notify addrs */
|
||||
probe_copy_masters_for_allow_notify(xfr);
|
||||
if(verbosity >= VERB_ALGO) {
|
||||
char zname[255+1];
|
||||
char zname[LDNS_MAX_DOMAINLEN];
|
||||
dname_str(xfr->name, zname);
|
||||
verbose(VERB_ALGO, "auth zone %s probe: notify addrs updated", zname);
|
||||
}
|
||||
@@ -6681,7 +6697,7 @@ xfr_probe_send_or_end(struct auth_xfer* xfr, struct module_env* env)
|
||||
/* only wanted lookups for copy, stop probe and start wait */
|
||||
xfr->task_probe->only_lookup = 0;
|
||||
if(verbosity >= VERB_ALGO) {
|
||||
char zname[255+1];
|
||||
char zname[LDNS_MAX_DOMAINLEN];
|
||||
dname_str(xfr->name, zname);
|
||||
verbose(VERB_ALGO, "auth zone %s probe: finished only_lookup", zname);
|
||||
}
|
||||
@@ -6707,7 +6723,7 @@ xfr_probe_send_or_end(struct auth_xfer* xfr, struct module_env* env)
|
||||
if(xfr->task_probe->have_new_lease) {
|
||||
/* if zone not updated, start the wait timer again */
|
||||
if(verbosity >= VERB_ALGO) {
|
||||
char zname[255+1];
|
||||
char zname[LDNS_MAX_DOMAINLEN];
|
||||
dname_str(xfr->name, zname);
|
||||
verbose(VERB_ALGO, "auth_zone %s unchanged, new lease, wait", zname);
|
||||
}
|
||||
@@ -6718,7 +6734,7 @@ xfr_probe_send_or_end(struct auth_xfer* xfr, struct module_env* env)
|
||||
xfr_set_timeout(xfr, env, 0, 0);
|
||||
} else {
|
||||
if(verbosity >= VERB_ALGO) {
|
||||
char zname[255+1];
|
||||
char zname[LDNS_MAX_DOMAINLEN];
|
||||
dname_str(xfr->name, zname);
|
||||
verbose(VERB_ALGO, "auth zone %s soa probe failed, wait to retry", zname);
|
||||
}
|
||||
@@ -6768,14 +6784,14 @@ void auth_xfer_probe_lookup_callback(void* arg, int rcode, sldns_buffer* buf,
|
||||
lookup_target, answer, wanted_qtype);
|
||||
} else {
|
||||
if(verbosity >= VERB_ALGO) {
|
||||
char zname[255+1];
|
||||
char zname[LDNS_MAX_DOMAINLEN];
|
||||
dname_str(xfr->name, zname);
|
||||
verbose(VERB_ALGO, "auth zone %s host %s type %s probe lookup has nodata", zname, xfr->task_probe->lookup_target->host, (xfr->task_probe->lookup_aaaa?"AAAA":"A"));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if(verbosity >= VERB_ALGO) {
|
||||
char zname[255+1];
|
||||
char zname[LDNS_MAX_DOMAINLEN];
|
||||
dname_str(xfr->name, zname);
|
||||
verbose(VERB_ALGO, "auth zone %s host %s type %s probe lookup has no address", zname, xfr->task_probe->lookup_target->host, (xfr->task_probe->lookup_aaaa?"AAAA":"A"));
|
||||
}
|
||||
@@ -6783,7 +6799,7 @@ void auth_xfer_probe_lookup_callback(void* arg, int rcode, sldns_buffer* buf,
|
||||
regional_free_all(temp);
|
||||
} else {
|
||||
if(verbosity >= VERB_ALGO) {
|
||||
char zname[255+1];
|
||||
char zname[LDNS_MAX_DOMAINLEN];
|
||||
dname_str(xfr->name, zname);
|
||||
verbose(VERB_ALGO, "auth zone %s host %s type %s probe lookup failed", zname, xfr->task_probe->lookup_target->host, (xfr->task_probe->lookup_aaaa?"AAAA":"A"));
|
||||
}
|
||||
@@ -6957,7 +6973,7 @@ xfr_set_timeout(struct auth_xfer* xfr, struct module_env* env,
|
||||
if(!xfr->task_nextprobe->timer) {
|
||||
/* failed to malloc memory. likely zone transfer
|
||||
* also fails for that. skip the timeout */
|
||||
char zname[255+1];
|
||||
char zname[LDNS_MAX_DOMAINLEN];
|
||||
dname_str(xfr->name, zname);
|
||||
log_err("cannot allocate timer, no refresh for %s",
|
||||
zname);
|
||||
@@ -6978,7 +6994,7 @@ xfr_set_timeout(struct auth_xfer* xfr, struct module_env* env,
|
||||
xfr->task_probe->only_lookup = 1;
|
||||
}
|
||||
if(verbosity >= VERB_ALGO) {
|
||||
char zname[255+1];
|
||||
char zname[LDNS_MAX_DOMAINLEN];
|
||||
dname_str(xfr->name, zname);
|
||||
verbose(VERB_ALGO, "auth zone %s timeout in %d seconds",
|
||||
zname, (int)tv.tv_sec);
|
||||
@@ -6987,6 +7003,18 @@ xfr_set_timeout(struct auth_xfer* xfr, struct module_env* env,
|
||||
comm_timer_set(xfr->task_nextprobe->timer, &tv);
|
||||
}
|
||||
|
||||
void auth_xfer_pickup_initial_zone(struct auth_xfer* x, struct module_env* env)
|
||||
{
|
||||
/* set lease_time, because we now have timestamp in env,
|
||||
* (not earlier during startup and apply_cfg), and this
|
||||
* notes the start time when the data was acquired */
|
||||
if(x->have_zone)
|
||||
x->lease_time = *env->now;
|
||||
if(x->task_nextprobe && x->task_nextprobe->worker == NULL) {
|
||||
xfr_set_timeout(x, env, 0, 1);
|
||||
}
|
||||
}
|
||||
|
||||
/** initial pick up of worker timeouts, ties events to worker event loop */
|
||||
void
|
||||
auth_xfer_pickup_initial(struct auth_zones* az, struct module_env* env)
|
||||
@@ -6995,14 +7023,7 @@ auth_xfer_pickup_initial(struct auth_zones* az, struct module_env* env)
|
||||
lock_rw_wrlock(&az->lock);
|
||||
RBTREE_FOR(x, struct auth_xfer*, &az->xtree) {
|
||||
lock_basic_lock(&x->lock);
|
||||
/* set lease_time, because we now have timestamp in env,
|
||||
* (not earlier during startup and apply_cfg), and this
|
||||
* notes the start time when the data was acquired */
|
||||
if(x->have_zone)
|
||||
x->lease_time = *env->now;
|
||||
if(x->task_nextprobe && x->task_nextprobe->worker == NULL) {
|
||||
xfr_set_timeout(x, env, 0, 1);
|
||||
}
|
||||
auth_xfer_pickup_initial_zone(x, env);
|
||||
lock_basic_unlock(&x->lock);
|
||||
}
|
||||
lock_rw_unlock(&az->lock);
|
||||
@@ -7765,7 +7786,7 @@ static void auth_zone_log(uint8_t* name, enum verbosity_value level,
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
if(verbosity >= level) {
|
||||
char str[255+1];
|
||||
char str[LDNS_MAX_DOMAINLEN];
|
||||
char msg[MAXSYSLOGMSGLEN];
|
||||
dname_str(name, str);
|
||||
vsnprintf(msg, sizeof(msg), format, args);
|
||||
@@ -7967,7 +7988,7 @@ static int zonemd_check_dnssec_soazonemd(struct auth_zone* z,
|
||||
static void auth_zone_zonemd_fail(struct auth_zone* z, struct module_env* env,
|
||||
char* reason, char* why_bogus, char** result)
|
||||
{
|
||||
char zstr[255+1];
|
||||
char zstr[LDNS_MAX_DOMAINLEN];
|
||||
/* if fail: log reason, and depending on config also take action
|
||||
* and drop the zone, eg. it is gone from memory, set zone_expired */
|
||||
dname_str(z->name, zstr);
|
||||
@@ -8112,6 +8133,8 @@ auth_zone_verify_zonemd_with_key(struct auth_zone* z, struct module_env* env,
|
||||
* @param why_bogus: if the routine fails, returns the failure reason.
|
||||
* @param keystorage: where to store the ub_packed_rrset_key that is created
|
||||
* on success. A pointer to it is returned on success.
|
||||
* @param reasonbuf: buffer to use for fail reason string print.
|
||||
* @param reasonlen: length of reasonbuf.
|
||||
* @return the dnskey RRset, reference to zone data and keystorage, or
|
||||
* NULL on failure.
|
||||
*/
|
||||
@@ -8411,7 +8434,7 @@ zonemd_lookup_dnskey(struct auth_zone* z, struct module_env* env)
|
||||
qinfo.local_alias = NULL;
|
||||
if(verbosity >= VERB_ALGO) {
|
||||
char buf1[512];
|
||||
char buf2[LDNS_MAX_DOMAINLEN+1];
|
||||
char buf2[LDNS_MAX_DOMAINLEN];
|
||||
dname_str(z->name, buf2);
|
||||
snprintf(buf1, sizeof(buf1), "auth zone %s: lookup %s "
|
||||
"for zonemd verification", buf2,
|
||||
@@ -8559,3 +8582,161 @@ void auth_zones_pickup_zonemd_verify(struct auth_zones* az,
|
||||
}
|
||||
lock_rw_unlock(&az->lock);
|
||||
}
|
||||
|
||||
/** Get memory usage of auth rrset */
|
||||
static size_t
|
||||
auth_rrset_get_mem(struct auth_rrset* rrset)
|
||||
{
|
||||
size_t m = sizeof(*rrset) + packed_rrset_sizeof(rrset->data);
|
||||
return m;
|
||||
}
|
||||
|
||||
/** Get memory usage of auth data */
|
||||
static size_t
|
||||
auth_data_get_mem(struct auth_data* node)
|
||||
{
|
||||
size_t m = sizeof(*node) + node->namelen;
|
||||
struct auth_rrset* rrset;
|
||||
for(rrset = node->rrsets; rrset; rrset = rrset->next) {
|
||||
m += auth_rrset_get_mem(rrset);
|
||||
}
|
||||
return m;
|
||||
}
|
||||
|
||||
/** Get memory usage of auth zone */
|
||||
static size_t
|
||||
auth_zone_get_mem(struct auth_zone* z)
|
||||
{
|
||||
size_t m = sizeof(*z) + z->namelen;
|
||||
struct auth_data* node;
|
||||
if(z->zonefile)
|
||||
m += strlen(z->zonefile)+1;
|
||||
RBTREE_FOR(node, struct auth_data*, &z->data) {
|
||||
m += auth_data_get_mem(node);
|
||||
}
|
||||
if(z->rpz)
|
||||
m += rpz_get_mem(z->rpz);
|
||||
return m;
|
||||
}
|
||||
|
||||
/** Get memory usage of list of auth addr */
|
||||
static size_t
|
||||
auth_addrs_get_mem(struct auth_addr* list)
|
||||
{
|
||||
size_t m = 0;
|
||||
struct auth_addr* a;
|
||||
for(a = list; a; a = a->next) {
|
||||
m += sizeof(*a);
|
||||
}
|
||||
return m;
|
||||
}
|
||||
|
||||
/** Get memory usage of list of primaries for auth xfer */
|
||||
static size_t
|
||||
auth_primaries_get_mem(struct auth_master* list)
|
||||
{
|
||||
size_t m = 0;
|
||||
struct auth_master* n;
|
||||
for(n = list; n; n = n->next) {
|
||||
m += sizeof(*n);
|
||||
m += auth_addrs_get_mem(n->list);
|
||||
if(n->host)
|
||||
m += strlen(n->host)+1;
|
||||
if(n->file)
|
||||
m += strlen(n->file)+1;
|
||||
}
|
||||
return m;
|
||||
}
|
||||
|
||||
/** Get memory usage or list of auth chunks */
|
||||
static size_t
|
||||
auth_chunks_get_mem(struct auth_chunk* list)
|
||||
{
|
||||
size_t m = 0;
|
||||
struct auth_chunk* chunk;
|
||||
for(chunk = list; chunk; chunk = chunk->next) {
|
||||
m += sizeof(*chunk) + chunk->len;
|
||||
}
|
||||
return m;
|
||||
}
|
||||
|
||||
/** Get memory usage of auth xfer */
|
||||
static size_t
|
||||
auth_xfer_get_mem(struct auth_xfer* xfr)
|
||||
{
|
||||
size_t m = sizeof(*xfr) + xfr->namelen;
|
||||
|
||||
/* auth_nextprobe */
|
||||
m += comm_timer_get_mem(xfr->task_nextprobe->timer);
|
||||
|
||||
/* auth_probe */
|
||||
m += auth_primaries_get_mem(xfr->task_probe->masters);
|
||||
m += comm_point_get_mem(xfr->task_probe->cp);
|
||||
m += comm_timer_get_mem(xfr->task_probe->timer);
|
||||
|
||||
/* auth_transfer */
|
||||
m += auth_chunks_get_mem(xfr->task_transfer->chunks_first);
|
||||
m += auth_primaries_get_mem(xfr->task_transfer->masters);
|
||||
m += comm_point_get_mem(xfr->task_transfer->cp);
|
||||
m += comm_timer_get_mem(xfr->task_transfer->timer);
|
||||
|
||||
/* allow_notify_list */
|
||||
m += auth_primaries_get_mem(xfr->allow_notify_list);
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
/** Get memory usage of auth zones ztree */
|
||||
static size_t
|
||||
az_ztree_get_mem(struct auth_zones* az)
|
||||
{
|
||||
size_t m = 0;
|
||||
struct auth_zone* z;
|
||||
RBTREE_FOR(z, struct auth_zone*, &az->ztree) {
|
||||
lock_rw_rdlock(&z->lock);
|
||||
m += auth_zone_get_mem(z);
|
||||
lock_rw_unlock(&z->lock);
|
||||
}
|
||||
return m;
|
||||
}
|
||||
|
||||
/** Get memory usage of auth zones xtree */
|
||||
static size_t
|
||||
az_xtree_get_mem(struct auth_zones* az)
|
||||
{
|
||||
size_t m = 0;
|
||||
struct auth_xfer* xfr;
|
||||
RBTREE_FOR(xfr, struct auth_xfer*, &az->xtree) {
|
||||
lock_basic_lock(&xfr->lock);
|
||||
m += auth_xfer_get_mem(xfr);
|
||||
lock_basic_unlock(&xfr->lock);
|
||||
}
|
||||
return m;
|
||||
}
|
||||
|
||||
size_t auth_zones_get_mem(struct auth_zones* zones)
|
||||
{
|
||||
size_t m;
|
||||
if(!zones) return 0;
|
||||
m = sizeof(*zones);
|
||||
lock_rw_rdlock(&zones->rpz_lock);
|
||||
lock_rw_rdlock(&zones->lock);
|
||||
m += az_ztree_get_mem(zones);
|
||||
m += az_xtree_get_mem(zones);
|
||||
lock_rw_unlock(&zones->lock);
|
||||
lock_rw_unlock(&zones->rpz_lock);
|
||||
return m;
|
||||
}
|
||||
|
||||
void xfr_disown_tasks(struct auth_xfer* xfr, struct worker* worker)
|
||||
{
|
||||
if(xfr->task_nextprobe->worker == worker) {
|
||||
xfr_nextprobe_disown(xfr);
|
||||
}
|
||||
if(xfr->task_probe->worker == worker) {
|
||||
xfr_probe_disown(xfr);
|
||||
}
|
||||
if(xfr->task_transfer->worker == worker) {
|
||||
xfr_transfer_disown(xfr);
|
||||
}
|
||||
}
|
||||
|
||||
+34
-6
@@ -70,7 +70,8 @@ struct auth_chunk;
|
||||
* Authoritative zones, shared.
|
||||
*/
|
||||
struct auth_zones {
|
||||
/** lock on the authzone trees */
|
||||
/** lock on the authzone trees. It is locked after views, respip,
|
||||
* local_zones and before fwds and stubs. */
|
||||
lock_rw_type lock;
|
||||
/** rbtree of struct auth_zone */
|
||||
rbtree_type ztree;
|
||||
@@ -78,10 +79,6 @@ struct auth_zones {
|
||||
rbtree_type xtree;
|
||||
/** do we have downstream enabled */
|
||||
int have_downstream;
|
||||
/** number of queries upstream */
|
||||
size_t num_query_up;
|
||||
/** number of queries downstream */
|
||||
size_t num_query_down;
|
||||
/** first auth zone containing rpz item in linked list */
|
||||
struct auth_zone* rpz_first;
|
||||
/** rw lock for rpz linked list, needed when iterating or editing linked
|
||||
@@ -211,7 +208,9 @@ struct auth_xfer {
|
||||
* one of the tasks.
|
||||
* Once it has the task assigned to it, the worker can access the
|
||||
* other elements of the task structure without a lock, because that
|
||||
* is necessary for the eventloop and callbacks from that. */
|
||||
* is necessary for the eventloop and callbacks from that.
|
||||
* The auth_zone->lock is locked before this lock.
|
||||
*/
|
||||
lock_basic_type lock;
|
||||
|
||||
/** zone name, in uncompressed wireformat */
|
||||
@@ -787,4 +786,33 @@ void auth_zonemd_dnskey_lookup_callback(void* arg, int rcode,
|
||||
void auth_zones_pickup_zonemd_verify(struct auth_zones* az,
|
||||
struct module_env* env);
|
||||
|
||||
/** Get memory usage for auth zones. The routine locks and unlocks
|
||||
* for reading. */
|
||||
size_t auth_zones_get_mem(struct auth_zones* zones);
|
||||
|
||||
/**
|
||||
* Initial pick up of the auth zone nextprobe timeout and that turns
|
||||
* into further zone transfer work, if any. Also sets the lease time.
|
||||
* @param x: xfer structure, locked by caller.
|
||||
* @param env: environment of the worker that picks up the task.
|
||||
*/
|
||||
void auth_xfer_pickup_initial_zone(struct auth_xfer* x,
|
||||
struct module_env* env);
|
||||
|
||||
/**
|
||||
* Delete auth xfer structure
|
||||
* @param xfr: delete this xfer and its tasks.
|
||||
*/
|
||||
void auth_xfer_delete(struct auth_xfer* xfr);
|
||||
|
||||
/**
|
||||
* Disown tasks from the xfr that belong to this worker.
|
||||
* Only tasks for the worker in question, the comm point and timer
|
||||
* delete functions need to run in the thread of that worker to be
|
||||
* able to delete the callback from the event base.
|
||||
* @param xfr: xfr structure
|
||||
* @param worker: the worker for which to stop tasks.
|
||||
*/
|
||||
void xfr_disown_tasks(struct auth_xfer* xfr, struct worker* worker);
|
||||
|
||||
#endif /* SERVICES_AUTHZONE_H */
|
||||
|
||||
Vendored
+93
-22
@@ -88,7 +88,7 @@ store_rrsets(struct module_env* env, struct reply_info* rep, time_t now,
|
||||
/* update ref if it was in the cache */
|
||||
switch(rrset_cache_update(env->rrset_cache, &rep->ref[i],
|
||||
env->alloc, ((ntohs(rep->ref[i].key->rk.type)==
|
||||
LDNS_RR_TYPE_NS && !pside)?qstarttime:now + leeway))) {
|
||||
LDNS_RR_TYPE_NS && !pside)?qstarttime:now) + leeway)) {
|
||||
case 0: /* ref unchanged, item inserted */
|
||||
break;
|
||||
case 2: /* ref updated, cache is superior */
|
||||
@@ -110,6 +110,7 @@ store_rrsets(struct module_env* env, struct reply_info* rep, time_t now,
|
||||
/* no break: also copy key item */
|
||||
/* the line below is matched by gcc regex and silences
|
||||
* the fallthrough warning */
|
||||
ATTR_FALLTHROUGH
|
||||
/* fallthrough */
|
||||
case 1: /* ref updated, item inserted */
|
||||
rep->rrsets[i] = rep->ref[i].key;
|
||||
@@ -161,7 +162,7 @@ dns_cache_store_msg(struct module_env* env, struct query_info* qinfo,
|
||||
size_t i;
|
||||
|
||||
/* store RRsets */
|
||||
for(i=0; i<rep->rrset_count; i++) {
|
||||
for(i=0; i<rep->rrset_count; i++) {
|
||||
rep->ref[i].key = rep->rrsets[i];
|
||||
rep->ref[i].id = rep->rrsets[i]->id;
|
||||
}
|
||||
@@ -196,6 +197,7 @@ dns_cache_store_msg(struct module_env* env, struct query_info* qinfo,
|
||||
reply_info_sortref(rep);
|
||||
if(!(e = query_info_entrysetup(qinfo, rep, hash))) {
|
||||
log_err("store_msg: malloc failed");
|
||||
reply_info_delete(rep, NULL);
|
||||
return;
|
||||
}
|
||||
slabhash_insert(env->msg_cache, hash, &e->entry, rep, env->alloc);
|
||||
@@ -345,6 +347,13 @@ find_add_addrs(struct module_env* env, uint16_t qclass,
|
||||
* not use dns64 translation */
|
||||
neg = msg_cache_lookup(env, ns->name, ns->namelen,
|
||||
LDNS_RR_TYPE_AAAA, qclass, 0, now, 0);
|
||||
/* Because recursion for lookup uses BIT_CD, check
|
||||
* for that so it stops the recursion lookup, if a
|
||||
* negative answer is cached. Because the cache uses
|
||||
* the CD flag for type AAAA. */
|
||||
if(!neg)
|
||||
neg = msg_cache_lookup(env, ns->name, ns->namelen,
|
||||
LDNS_RR_TYPE_AAAA, qclass, BIT_CD, now, 0);
|
||||
if(neg) {
|
||||
delegpt_add_neg_msg(dp, neg);
|
||||
lock_rw_unlock(&neg->entry.lock);
|
||||
@@ -357,7 +366,7 @@ find_add_addrs(struct module_env* env, uint16_t qclass,
|
||||
/** find and add A and AAAA records for missing nameservers in delegpt */
|
||||
int
|
||||
cache_fill_missing(struct module_env* env, uint16_t qclass,
|
||||
struct regional* region, struct delegpt* dp)
|
||||
struct regional* region, struct delegpt* dp, uint32_t flags)
|
||||
{
|
||||
struct delegpt_ns* ns;
|
||||
struct msgreply_entry* neg;
|
||||
@@ -368,7 +377,7 @@ cache_fill_missing(struct module_env* env, uint16_t qclass,
|
||||
continue;
|
||||
ns->cache_lookup_count++;
|
||||
akey = rrset_cache_lookup(env->rrset_cache, ns->name,
|
||||
ns->namelen, LDNS_RR_TYPE_A, qclass, 0, now, 0);
|
||||
ns->namelen, LDNS_RR_TYPE_A, qclass, flags, now, 0);
|
||||
if(akey) {
|
||||
if(!delegpt_add_rrset_A(dp, region, akey, ns->lame,
|
||||
NULL)) {
|
||||
@@ -389,7 +398,7 @@ cache_fill_missing(struct module_env* env, uint16_t qclass,
|
||||
}
|
||||
}
|
||||
akey = rrset_cache_lookup(env->rrset_cache, ns->name,
|
||||
ns->namelen, LDNS_RR_TYPE_AAAA, qclass, 0, now, 0);
|
||||
ns->namelen, LDNS_RR_TYPE_AAAA, qclass, flags, now, 0);
|
||||
if(akey) {
|
||||
if(!delegpt_add_rrset_AAAA(dp, region, akey, ns->lame,
|
||||
NULL)) {
|
||||
@@ -404,6 +413,13 @@ cache_fill_missing(struct module_env* env, uint16_t qclass,
|
||||
* not use dns64 translation */
|
||||
neg = msg_cache_lookup(env, ns->name, ns->namelen,
|
||||
LDNS_RR_TYPE_AAAA, qclass, 0, now, 0);
|
||||
/* Because recursion for lookup uses BIT_CD, check
|
||||
* for that so it stops the recursion lookup, if a
|
||||
* negative answer is cached. Because the cache uses
|
||||
* the CD flag for type AAAA. */
|
||||
if(!neg)
|
||||
neg = msg_cache_lookup(env, ns->name, ns->namelen,
|
||||
LDNS_RR_TYPE_AAAA, qclass, BIT_CD, now, 0);
|
||||
if(neg) {
|
||||
delegpt_add_neg_msg(dp, neg);
|
||||
lock_rw_unlock(&neg->entry.lock);
|
||||
@@ -592,22 +608,8 @@ tomsg(struct module_env* env, struct query_info* q, struct reply_info* r,
|
||||
time_t now_control = now;
|
||||
if(now > r->ttl) {
|
||||
/* Check if we are allowed to serve expired */
|
||||
if(allow_expired) {
|
||||
if(env->cfg->serve_expired_ttl &&
|
||||
r->serve_expired_ttl < now) {
|
||||
return NULL;
|
||||
}
|
||||
/* Ignore expired failure answers */
|
||||
if(FLAGS_GET_RCODE(r->flags) !=
|
||||
LDNS_RCODE_NOERROR &&
|
||||
FLAGS_GET_RCODE(r->flags) !=
|
||||
LDNS_RCODE_NXDOMAIN &&
|
||||
FLAGS_GET_RCODE(r->flags) !=
|
||||
LDNS_RCODE_YXDOMAIN)
|
||||
return 0;
|
||||
} else {
|
||||
if(!allow_expired || !reply_info_can_answer_expired(r, now))
|
||||
return NULL;
|
||||
}
|
||||
/* Change the current time so we can pass the below TTL checks when
|
||||
* serving expired data. */
|
||||
now_control = r->ttl - env->cfg->serve_expired_reply_ttl;
|
||||
@@ -626,6 +628,7 @@ tomsg(struct module_env* env, struct query_info* q, struct reply_info* r,
|
||||
else
|
||||
msg->rep->prefetch_ttl = PREFETCH_TTL_CALC(msg->rep->ttl);
|
||||
msg->rep->serve_expired_ttl = msg->rep->ttl + SERVE_EXPIRED_TTL;
|
||||
msg->rep->serve_expired_norec_ttl = 0;
|
||||
msg->rep->security = r->security;
|
||||
msg->rep->an_numrrsets = r->an_numrrsets;
|
||||
msg->rep->ns_numrrsets = r->ns_numrrsets;
|
||||
@@ -709,6 +712,7 @@ rrset_msg(struct ub_packed_rrset_key* rrset, struct regional* region,
|
||||
msg->rep->ttl = d->ttl - now;
|
||||
msg->rep->prefetch_ttl = PREFETCH_TTL_CALC(msg->rep->ttl);
|
||||
msg->rep->serve_expired_ttl = msg->rep->ttl + SERVE_EXPIRED_TTL;
|
||||
msg->rep->serve_expired_norec_ttl = 0;
|
||||
msg->rep->security = sec_status_unchecked;
|
||||
msg->rep->an_numrrsets = 1;
|
||||
msg->rep->ns_numrrsets = 0;
|
||||
@@ -748,6 +752,7 @@ synth_dname_msg(struct ub_packed_rrset_key* rrset, struct regional* region,
|
||||
msg->rep->ttl = d->ttl - now;
|
||||
msg->rep->prefetch_ttl = PREFETCH_TTL_CALC(msg->rep->ttl);
|
||||
msg->rep->serve_expired_ttl = msg->rep->ttl + SERVE_EXPIRED_TTL;
|
||||
msg->rep->serve_expired_norec_ttl = 0;
|
||||
msg->rep->security = sec_status_unchecked;
|
||||
msg->rep->an_numrrsets = 1;
|
||||
msg->rep->ns_numrrsets = 0;
|
||||
@@ -1051,10 +1056,76 @@ 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, time_t qstarttime)
|
||||
struct reply_info* msgrep, int is_referral, time_t leeway, int pside,
|
||||
struct regional* region, uint32_t flags, time_t qstarttime,
|
||||
int is_valrec)
|
||||
{
|
||||
struct reply_info* rep = NULL;
|
||||
if(SERVE_EXPIRED) {
|
||||
/* We are serving expired records. Before caching, check if a
|
||||
* useful expired record exists. */
|
||||
struct msgreply_entry* e = msg_cache_lookup(env,
|
||||
msgqinf->qname, msgqinf->qname_len, msgqinf->qtype,
|
||||
msgqinf->qclass, flags, 0, 1);
|
||||
if(e) {
|
||||
struct reply_info* cached = e->entry.data;
|
||||
if(cached->ttl < *env->now
|
||||
&& reply_info_could_use_expired(cached, *env->now)
|
||||
/* If we are validating make sure only
|
||||
* validating modules can update such messages.
|
||||
* In that case don't cache it and let a
|
||||
* subsequent module handle the caching. For
|
||||
* example, the iterator should not replace an
|
||||
* expired secure answer with a fresh unchecked
|
||||
* one and let the validator manage caching. */
|
||||
&& cached->security != sec_status_bogus
|
||||
&& (env->need_to_validate &&
|
||||
msgrep->security == sec_status_unchecked)
|
||||
/* Exceptions to that rule are:
|
||||
* o recursions that don't need validation but
|
||||
* need to update the cache for coherence
|
||||
* (delegation information while iterating,
|
||||
* DNSKEY and DS lookups from validator)
|
||||
* o explicit RRSIG queries that are not
|
||||
* validated. */
|
||||
&& !is_valrec
|
||||
&& msgqinf->qtype != LDNS_RR_TYPE_RRSIG) {
|
||||
if((int)FLAGS_GET_RCODE(msgrep->flags) !=
|
||||
LDNS_RCODE_NOERROR &&
|
||||
(int)FLAGS_GET_RCODE(msgrep->flags) !=
|
||||
LDNS_RCODE_NXDOMAIN) {
|
||||
/* The current response has an
|
||||
* erroneous rcode. Adjust norec time
|
||||
* so that additional lookups are not
|
||||
* performed for some time. */
|
||||
verbose(VERB_ALGO, "set "
|
||||
"serve-expired-norec-ttl for "
|
||||
"response in cache");
|
||||
cached->serve_expired_norec_ttl =
|
||||
NORR_TTL + *env->now;
|
||||
if(env->cfg->serve_expired_ttl_reset &&
|
||||
cached->serve_expired_ttl
|
||||
< *env->now +
|
||||
env->cfg->serve_expired_ttl) {
|
||||
/* Reset serve-expired-ttl for
|
||||
* valid response in cache. */
|
||||
verbose(VERB_ALGO, "reset "
|
||||
"serve-expired-ttl "
|
||||
"for response in cache");
|
||||
cached->serve_expired_ttl =
|
||||
*env->now +
|
||||
env->cfg->serve_expired_ttl;
|
||||
}
|
||||
}
|
||||
verbose(VERB_ALGO, "a validated expired entry "
|
||||
"could be overwritten, skip caching "
|
||||
"the new message at this stage");
|
||||
lock_rw_unlock(&e->entry.lock);
|
||||
return 1;
|
||||
}
|
||||
lock_rw_unlock(&e->entry.lock);
|
||||
}
|
||||
}
|
||||
/* alloc, malloc properly (not in region, like msg is) */
|
||||
rep = reply_info_copy(msgrep, env->alloc, NULL);
|
||||
if(!rep)
|
||||
|
||||
Vendored
+6
-2
@@ -90,11 +90,14 @@ struct dns_msg {
|
||||
* (See DNSCACHE_STORE_xxx flags).
|
||||
* @param qstarttime: time when the query was started, and thus when the
|
||||
* delegations were looked up.
|
||||
* @param is_valrec: if the query is validation recursion and does not get
|
||||
* dnssec validation itself.
|
||||
* @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, time_t qstarttime);
|
||||
struct regional* region, uint32_t flags, time_t qstarttime,
|
||||
int is_valrec);
|
||||
|
||||
/**
|
||||
* Store message in the cache. Stores in message cache and rrset cache.
|
||||
@@ -202,10 +205,11 @@ struct dns_msg* dns_cache_lookup(struct module_env* env,
|
||||
* @param qclass: which class to look in.
|
||||
* @param region: where to store new dp info.
|
||||
* @param dp: delegation point to fill missing entries.
|
||||
* @param flags: rrset flags, or 0.
|
||||
* @return false on alloc failure.
|
||||
*/
|
||||
int cache_fill_missing(struct module_env* env, uint16_t qclass,
|
||||
struct regional* region, struct delegpt* dp);
|
||||
struct regional* region, struct delegpt* dp, uint32_t flags);
|
||||
|
||||
/**
|
||||
* Utility, create new, unpacked data structure for cache response.
|
||||
|
||||
Vendored
+105
-65
@@ -52,24 +52,6 @@
|
||||
#include "util/config_file.h"
|
||||
#include "iterator/iterator.h"
|
||||
|
||||
/** Timeout when only a single probe query per IP is allowed. */
|
||||
#define PROBE_MAXRTO 12000 /* in msec */
|
||||
|
||||
/** number of timeouts for a type when the domain can be blocked ;
|
||||
* even if another type has completely rtt maxed it, the different type
|
||||
* can do this number of packets (until those all timeout too) */
|
||||
#define TIMEOUT_COUNT_MAX 3
|
||||
|
||||
/** Minus 1000 because that is outside of the RTTBAND, so
|
||||
* blacklisted servers stay blacklisted if this is chosen.
|
||||
* If USEFUL_SERVER_TOP_TIMEOUT is below 1000 (configured via RTT_MAX_TIMEOUT,
|
||||
* infra-cache-max-rtt) change it to just above the RTT_BAND. */
|
||||
#define STILL_USEFUL_TIMEOUT ( \
|
||||
USEFUL_SERVER_TOP_TIMEOUT < 1000 || \
|
||||
USEFUL_SERVER_TOP_TIMEOUT - 1000 <= RTT_BAND \
|
||||
?RTT_BAND + 1 \
|
||||
:USEFUL_SERVER_TOP_TIMEOUT - 1000)
|
||||
|
||||
/** ratelimit value for delegation point */
|
||||
int infra_dp_ratelimit = 0;
|
||||
|
||||
@@ -82,6 +64,20 @@ int infra_ip_ratelimit = 0;
|
||||
* For clients with a valid DNS Cookie. */
|
||||
int infra_ip_ratelimit_cookie = 0;
|
||||
|
||||
/** Minus 1000 because that is outside of the RTTBAND, so
|
||||
* blacklisted servers stay blacklisted if this is chosen.
|
||||
* If USEFUL_SERVER_TOP_TIMEOUT is below 1000 (configured via RTT_MAX_TIMEOUT,
|
||||
* infra-cache-max-rtt) change it to just above the RTT_BAND. */
|
||||
int
|
||||
still_useful_timeout()
|
||||
{
|
||||
return
|
||||
USEFUL_SERVER_TOP_TIMEOUT < 1000 ||
|
||||
USEFUL_SERVER_TOP_TIMEOUT - 1000 <= RTT_BAND
|
||||
?RTT_BAND + 1
|
||||
:USEFUL_SERVER_TOP_TIMEOUT - 1000;
|
||||
}
|
||||
|
||||
size_t
|
||||
infra_sizefunc(void* k, void* ATTR_UNUSED(d))
|
||||
{
|
||||
@@ -165,7 +161,7 @@ rate_deldatafunc(void* d, void* ATTR_UNUSED(arg))
|
||||
|
||||
/** find or create element in domainlimit tree */
|
||||
static struct domain_limit_data* domain_limit_findcreate(
|
||||
struct infra_cache* infra, char* name)
|
||||
struct rbtree_type* domain_limits, char* name)
|
||||
{
|
||||
uint8_t* nm;
|
||||
int labs;
|
||||
@@ -181,8 +177,8 @@ static struct domain_limit_data* domain_limit_findcreate(
|
||||
labs = dname_count_labels(nm);
|
||||
|
||||
/* can we find it? */
|
||||
d = (struct domain_limit_data*)name_tree_find(&infra->domain_limits,
|
||||
nm, nmlen, labs, LDNS_RR_CLASS_IN);
|
||||
d = (struct domain_limit_data*)name_tree_find(domain_limits, nm,
|
||||
nmlen, labs, LDNS_RR_CLASS_IN);
|
||||
if(d) {
|
||||
free(nm);
|
||||
return d;
|
||||
@@ -201,8 +197,8 @@ static struct domain_limit_data* domain_limit_findcreate(
|
||||
d->node.dclass = LDNS_RR_CLASS_IN;
|
||||
d->lim = -1;
|
||||
d->below = -1;
|
||||
if(!name_tree_insert(&infra->domain_limits, &d->node, nm, nmlen,
|
||||
labs, LDNS_RR_CLASS_IN)) {
|
||||
if(!name_tree_insert(domain_limits, &d->node, nm, nmlen, labs,
|
||||
LDNS_RR_CLASS_IN)) {
|
||||
log_err("duplicate element in domainlimit tree");
|
||||
free(nm);
|
||||
free(d);
|
||||
@@ -212,19 +208,19 @@ static struct domain_limit_data* domain_limit_findcreate(
|
||||
}
|
||||
|
||||
/** insert rate limit configuration into lookup tree */
|
||||
static int infra_ratelimit_cfg_insert(struct infra_cache* infra,
|
||||
static int infra_ratelimit_cfg_insert(struct rbtree_type* domain_limits,
|
||||
struct config_file* cfg)
|
||||
{
|
||||
struct config_str2list* p;
|
||||
struct domain_limit_data* d;
|
||||
for(p = cfg->ratelimit_for_domain; p; p = p->next) {
|
||||
d = domain_limit_findcreate(infra, p->str);
|
||||
d = domain_limit_findcreate(domain_limits, p->str);
|
||||
if(!d)
|
||||
return 0;
|
||||
d->lim = atoi(p->str2);
|
||||
}
|
||||
for(p = cfg->ratelimit_below_domain; p; p = p->next) {
|
||||
d = domain_limit_findcreate(infra, p->str);
|
||||
d = domain_limit_findcreate(domain_limits, p->str);
|
||||
if(!d)
|
||||
return 0;
|
||||
d->below = atoi(p->str2);
|
||||
@@ -232,24 +228,21 @@ static int infra_ratelimit_cfg_insert(struct infra_cache* infra,
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** setup domain limits tree (0 on failure) */
|
||||
static int
|
||||
setup_domain_limits(struct infra_cache* infra, struct config_file* cfg)
|
||||
int
|
||||
setup_domain_limits(struct rbtree_type* domain_limits, struct config_file* cfg)
|
||||
{
|
||||
name_tree_init(&infra->domain_limits);
|
||||
if(!infra_ratelimit_cfg_insert(infra, cfg)) {
|
||||
name_tree_init(domain_limits);
|
||||
if(!infra_ratelimit_cfg_insert(domain_limits, cfg)) {
|
||||
return 0;
|
||||
}
|
||||
name_tree_init_parents(&infra->domain_limits);
|
||||
name_tree_init_parents(domain_limits);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** find or create element in wait limit netblock tree */
|
||||
static struct wait_limit_netblock_info*
|
||||
wait_limit_netblock_findcreate(struct infra_cache* infra, char* str,
|
||||
int cookie)
|
||||
wait_limit_netblock_findcreate(struct rbtree_type* tree, char* str)
|
||||
{
|
||||
rbtree_type* tree;
|
||||
struct sockaddr_storage addr;
|
||||
int net;
|
||||
socklen_t addrlen;
|
||||
@@ -261,10 +254,6 @@ wait_limit_netblock_findcreate(struct infra_cache* infra, char* str,
|
||||
}
|
||||
|
||||
/* can we find it? */
|
||||
if(cookie)
|
||||
tree = &infra->wait_limits_cookie_netblock;
|
||||
else
|
||||
tree = &infra->wait_limits_netblock;
|
||||
d = (struct wait_limit_netblock_info*)addr_tree_find(tree, &addr,
|
||||
addrlen, net);
|
||||
if(d)
|
||||
@@ -286,19 +275,21 @@ wait_limit_netblock_findcreate(struct infra_cache* infra, char* str,
|
||||
|
||||
/** insert wait limit information into lookup tree */
|
||||
static int
|
||||
infra_wait_limit_netblock_insert(struct infra_cache* infra,
|
||||
struct config_file* cfg)
|
||||
infra_wait_limit_netblock_insert(rbtree_type* wait_limits_netblock,
|
||||
rbtree_type* wait_limits_cookie_netblock, struct config_file* cfg)
|
||||
{
|
||||
struct config_str2list* p;
|
||||
struct wait_limit_netblock_info* d;
|
||||
for(p = cfg->wait_limit_netblock; p; p = p->next) {
|
||||
d = wait_limit_netblock_findcreate(infra, p->str, 0);
|
||||
d = wait_limit_netblock_findcreate(wait_limits_netblock,
|
||||
p->str);
|
||||
if(!d)
|
||||
return 0;
|
||||
d->limit = atoi(p->str2);
|
||||
}
|
||||
for(p = cfg->wait_limit_cookie_netblock; p; p = p->next) {
|
||||
d = wait_limit_netblock_findcreate(infra, p->str, 1);
|
||||
d = wait_limit_netblock_findcreate(wait_limits_cookie_netblock,
|
||||
p->str);
|
||||
if(!d)
|
||||
return 0;
|
||||
d->limit = atoi(p->str2);
|
||||
@@ -306,16 +297,48 @@ infra_wait_limit_netblock_insert(struct infra_cache* infra,
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** setup wait limits tree (0 on failure) */
|
||||
/** Add a default wait limit netblock */
|
||||
static int
|
||||
setup_wait_limits(struct infra_cache* infra, struct config_file* cfg)
|
||||
wait_limit_netblock_default(struct rbtree_type* tree, char* str, int limit)
|
||||
{
|
||||
addr_tree_init(&infra->wait_limits_netblock);
|
||||
addr_tree_init(&infra->wait_limits_cookie_netblock);
|
||||
if(!infra_wait_limit_netblock_insert(infra, cfg))
|
||||
struct wait_limit_netblock_info* d;
|
||||
d = wait_limit_netblock_findcreate(tree, str);
|
||||
if(!d)
|
||||
return 0;
|
||||
addr_tree_init_parents(&infra->wait_limits_netblock);
|
||||
addr_tree_init_parents(&infra->wait_limits_cookie_netblock);
|
||||
d->limit = limit;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
setup_wait_limits(rbtree_type* wait_limits_netblock,
|
||||
rbtree_type* wait_limits_cookie_netblock, struct config_file* cfg)
|
||||
{
|
||||
addr_tree_init(wait_limits_netblock);
|
||||
addr_tree_init(wait_limits_cookie_netblock);
|
||||
|
||||
/* Insert defaults */
|
||||
/* The loopback address is separated from the rest of the network. */
|
||||
/* wait-limit-netblock: 127.0.0.0/8 -1 */
|
||||
if(!wait_limit_netblock_default(wait_limits_netblock, "127.0.0.0/8",
|
||||
-1))
|
||||
return 0;
|
||||
/* wait-limit-netblock: ::1/128 -1 */
|
||||
if(!wait_limit_netblock_default(wait_limits_netblock, "::1/128", -1))
|
||||
return 0;
|
||||
/* wait-limit-cookie-netblock: 127.0.0.0/8 -1 */
|
||||
if(!wait_limit_netblock_default(wait_limits_cookie_netblock,
|
||||
"127.0.0.0/8", -1))
|
||||
return 0;
|
||||
/* wait-limit-cookie-netblock: ::1/128 -1 */
|
||||
if(!wait_limit_netblock_default(wait_limits_cookie_netblock,
|
||||
"::1/128", -1))
|
||||
return 0;
|
||||
|
||||
if(!infra_wait_limit_netblock_insert(wait_limits_netblock,
|
||||
wait_limits_cookie_netblock, cfg))
|
||||
return 0;
|
||||
addr_tree_init_parents(wait_limits_netblock);
|
||||
addr_tree_init_parents(wait_limits_cookie_netblock);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -348,11 +371,12 @@ infra_create(struct config_file* cfg)
|
||||
return NULL;
|
||||
}
|
||||
/* insert config data into ratelimits */
|
||||
if(!setup_domain_limits(infra, cfg)) {
|
||||
if(!setup_domain_limits(&infra->domain_limits, cfg)) {
|
||||
infra_delete(infra);
|
||||
return NULL;
|
||||
}
|
||||
if(!setup_wait_limits(infra, cfg)) {
|
||||
if(!setup_wait_limits(&infra->wait_limits_netblock,
|
||||
&infra->wait_limits_cookie_netblock, cfg)) {
|
||||
infra_delete(infra);
|
||||
return NULL;
|
||||
}
|
||||
@@ -377,12 +401,29 @@ static void domain_limit_free(rbnode_type* n, void* ATTR_UNUSED(arg))
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
domain_limits_free(struct rbtree_type* domain_limits)
|
||||
{
|
||||
if(!domain_limits)
|
||||
return;
|
||||
traverse_postorder(domain_limits, domain_limit_free, NULL);
|
||||
}
|
||||
|
||||
/** delete wait_limit_netblock_info entries */
|
||||
static void wait_limit_netblock_del(rbnode_type* n, void* ATTR_UNUSED(arg))
|
||||
{
|
||||
free(n);
|
||||
}
|
||||
|
||||
void
|
||||
wait_limits_free(struct rbtree_type* wait_limits_tree)
|
||||
{
|
||||
if(!wait_limits_tree)
|
||||
return;
|
||||
traverse_postorder(wait_limits_tree, wait_limit_netblock_del,
|
||||
NULL);
|
||||
}
|
||||
|
||||
void
|
||||
infra_delete(struct infra_cache* infra)
|
||||
{
|
||||
@@ -390,12 +431,10 @@ infra_delete(struct infra_cache* infra)
|
||||
return;
|
||||
slabhash_delete(infra->hosts);
|
||||
slabhash_delete(infra->domain_rates);
|
||||
traverse_postorder(&infra->domain_limits, domain_limit_free, NULL);
|
||||
domain_limits_free(&infra->domain_limits);
|
||||
slabhash_delete(infra->client_ip_rates);
|
||||
traverse_postorder(&infra->wait_limits_netblock,
|
||||
wait_limit_netblock_del, NULL);
|
||||
traverse_postorder(&infra->wait_limits_cookie_netblock,
|
||||
wait_limit_netblock_del, NULL);
|
||||
wait_limits_free(&infra->wait_limits_netblock);
|
||||
wait_limits_free(&infra->wait_limits_cookie_netblock);
|
||||
free(infra);
|
||||
}
|
||||
|
||||
@@ -426,7 +465,7 @@ infra_adjust(struct infra_cache* infra, struct config_file* cfg)
|
||||
/* reapply domain limits */
|
||||
traverse_postorder(&infra->domain_limits, domain_limit_free,
|
||||
NULL);
|
||||
if(!setup_domain_limits(infra, cfg)) {
|
||||
if(!setup_domain_limits(&infra->domain_limits, cfg)) {
|
||||
infra_delete(infra);
|
||||
return NULL;
|
||||
}
|
||||
@@ -668,7 +707,7 @@ infra_update_tcp_works(struct infra_cache* infra,
|
||||
if(data->rtt.rto >= RTT_MAX_TIMEOUT)
|
||||
/* do not disqualify this server altogether, it is better
|
||||
* than nothing */
|
||||
data->rtt.rto = STILL_USEFUL_TIMEOUT;
|
||||
data->rtt.rto = still_useful_timeout();
|
||||
lock_rw_unlock(&e->lock);
|
||||
}
|
||||
|
||||
@@ -808,7 +847,7 @@ infra_get_lame_rtt(struct infra_cache* infra,
|
||||
&& infra->infra_keep_probing) {
|
||||
/* single probe, keep probing */
|
||||
if(*rtt >= USEFUL_SERVER_TOP_TIMEOUT)
|
||||
*rtt = STILL_USEFUL_TIMEOUT;
|
||||
*rtt = still_useful_timeout();
|
||||
} else if(host->rtt.rto >= PROBE_MAXRTO && timenow < host->probedelay
|
||||
&& rtt_notimeout(&host->rtt)*4 <= host->rtt.rto) {
|
||||
/* single probe for this domain, and we are not probing */
|
||||
@@ -816,15 +855,15 @@ infra_get_lame_rtt(struct infra_cache* infra,
|
||||
if(qtype == LDNS_RR_TYPE_A) {
|
||||
if(host->timeout_A >= TIMEOUT_COUNT_MAX)
|
||||
*rtt = USEFUL_SERVER_TOP_TIMEOUT;
|
||||
else *rtt = STILL_USEFUL_TIMEOUT;
|
||||
else *rtt = still_useful_timeout();
|
||||
} else if(qtype == LDNS_RR_TYPE_AAAA) {
|
||||
if(host->timeout_AAAA >= TIMEOUT_COUNT_MAX)
|
||||
*rtt = USEFUL_SERVER_TOP_TIMEOUT;
|
||||
else *rtt = STILL_USEFUL_TIMEOUT;
|
||||
else *rtt = still_useful_timeout();
|
||||
} else {
|
||||
if(host->timeout_other >= TIMEOUT_COUNT_MAX)
|
||||
*rtt = USEFUL_SERVER_TOP_TIMEOUT;
|
||||
else *rtt = STILL_USEFUL_TIMEOUT;
|
||||
else *rtt = still_useful_timeout();
|
||||
}
|
||||
}
|
||||
/* expired entry */
|
||||
@@ -832,7 +871,7 @@ infra_get_lame_rtt(struct infra_cache* infra,
|
||||
/* see if this can be a re-probe of an unresponsive server */
|
||||
if(host->rtt.rto >= USEFUL_SERVER_TOP_TIMEOUT) {
|
||||
lock_rw_unlock(&e->lock);
|
||||
*rtt = STILL_USEFUL_TIMEOUT;
|
||||
*rtt = still_useful_timeout();
|
||||
*lame = 0;
|
||||
*dnsseclame = 0;
|
||||
*reclame = 0;
|
||||
@@ -1081,7 +1120,8 @@ int infra_ratelimit_inc(struct infra_cache* infra, uint8_t* name,
|
||||
lock_rw_unlock(&entry->lock);
|
||||
|
||||
if(premax <= lim && max > lim) {
|
||||
char buf[257], qnm[257], ts[12], cs[12], ip[128];
|
||||
char buf[LDNS_MAX_DOMAINLEN], qnm[LDNS_MAX_DOMAINLEN];
|
||||
char ts[12], cs[12], ip[128];
|
||||
dname_str(name, buf);
|
||||
dname_str(qinfo->qname, qnm);
|
||||
sldns_wire2str_type_buf(qinfo->qtype, ts, sizeof(ts));
|
||||
|
||||
Vendored
+31
@@ -52,6 +52,19 @@
|
||||
struct slabhash;
|
||||
struct config_file;
|
||||
|
||||
/** number of timeouts for a type when the domain can be blocked ;
|
||||
* even if another type has completely rtt maxed it, the different type
|
||||
* can do this number of packets (until those all timeout too) */
|
||||
#define TIMEOUT_COUNT_MAX 3
|
||||
|
||||
|
||||
/** Timeout when only a single probe query per IP is allowed.
|
||||
* Any RTO above this number is considered a probe.
|
||||
* It is synchronized (caped) with USEFUL_SERVER_TOP_TIMEOUT so that probing
|
||||
* keeps working even if that configurable number drops below the default
|
||||
* 12000 ms of probing. */
|
||||
extern int PROBE_MAXRTO;
|
||||
|
||||
/**
|
||||
* Host information kept for every server, per zone.
|
||||
*/
|
||||
@@ -502,4 +515,22 @@ void infra_wait_limit_inc(struct infra_cache* infra, struct comm_reply* rep,
|
||||
void infra_wait_limit_dec(struct infra_cache* infra, struct comm_reply* rep,
|
||||
struct config_file* cfg);
|
||||
|
||||
/** setup wait limits tree (0 on failure) */
|
||||
int setup_wait_limits(struct rbtree_type* wait_limits_netblock,
|
||||
struct rbtree_type* wait_limits_cookie_netblock,
|
||||
struct config_file* cfg);
|
||||
|
||||
/** Free the wait limits and wait cookie limits tree. */
|
||||
void wait_limits_free(struct rbtree_type* wait_limits_tree);
|
||||
|
||||
/** setup domain limits tree (0 on failure) */
|
||||
int setup_domain_limits(struct rbtree_type* domain_limits,
|
||||
struct config_file* cfg);
|
||||
|
||||
/** Free the domain limits tree. */
|
||||
void domain_limits_free(struct rbtree_type* domain_limits);
|
||||
|
||||
/** exported for unit test */
|
||||
int still_useful_timeout();
|
||||
|
||||
#endif /* SERVICES_CACHE_INFRA_H */
|
||||
|
||||
Vendored
+5
-5
@@ -128,8 +128,8 @@ need_to_update_rrset(void* nd, void* cd, time_t timenow, int equal, int ns)
|
||||
{
|
||||
struct packed_rrset_data* newd = (struct packed_rrset_data*)nd;
|
||||
struct packed_rrset_data* cached = (struct packed_rrset_data*)cd;
|
||||
/* o if new data is expired, current data is better */
|
||||
if( newd->ttl < timenow && cached->ttl >= timenow)
|
||||
/* o if new data is expired, cached data is better */
|
||||
if( newd->ttl < timenow && timenow <= cached->ttl)
|
||||
return 0;
|
||||
/* o store if rrset has been validated
|
||||
* everything better than bogus data
|
||||
@@ -140,9 +140,9 @@ need_to_update_rrset(void* nd, void* cd, time_t timenow, int equal, int ns)
|
||||
if( cached->security == sec_status_bogus &&
|
||||
newd->security != sec_status_bogus && !equal)
|
||||
return 1;
|
||||
/* o if current RRset is more trustworthy - insert it */
|
||||
/* o if new RRset is more trustworthy - insert it */
|
||||
if( newd->trust > cached->trust ) {
|
||||
/* if the cached rrset is bogus, and this one equal,
|
||||
/* if the cached rrset is bogus, and new is equal,
|
||||
* do not update the TTL - let it expire. */
|
||||
if(equal && cached->ttl >= timenow &&
|
||||
cached->security == sec_status_bogus)
|
||||
@@ -155,7 +155,7 @@ need_to_update_rrset(void* nd, void* cd, time_t timenow, int equal, int ns)
|
||||
/* o same trust, but different in data - insert it */
|
||||
if( newd->trust == cached->trust && !equal ) {
|
||||
/* if this is type NS, do not 'stick' to owner that changes
|
||||
* the NS RRset, but use the old TTL for the new data, and
|
||||
* the NS RRset, but use the cached TTL for the new data, and
|
||||
* update to fetch the latest data. ttl is not expired, because
|
||||
* that check was before this one. */
|
||||
if(ns) {
|
||||
|
||||
+2541
-84
File diff suppressed because it is too large
Load Diff
+409
-5
@@ -43,10 +43,16 @@
|
||||
#define LISTEN_DNSPORT_H
|
||||
|
||||
#include "util/netevent.h"
|
||||
#include "util/rbtree.h"
|
||||
#include "util/locks.h"
|
||||
#include "daemon/acl_list.h"
|
||||
#ifdef HAVE_NGHTTP2_NGHTTP2_H
|
||||
#include <nghttp2/nghttp2.h>
|
||||
#endif
|
||||
#ifdef HAVE_NGTCP2
|
||||
#include <ngtcp2/ngtcp2.h>
|
||||
#include <ngtcp2/ngtcp2_crypto.h>
|
||||
#endif
|
||||
struct listen_list;
|
||||
struct config_file;
|
||||
struct addrinfo;
|
||||
@@ -100,7 +106,9 @@ enum listen_type {
|
||||
/** udp ipv6 (v4mapped) for use with ancillary data + dnscrypt*/
|
||||
listen_type_udpancil_dnscrypt,
|
||||
/** HTTP(2) over TLS over TCP */
|
||||
listen_type_http
|
||||
listen_type_http,
|
||||
/** DNS over QUIC */
|
||||
listen_type_doq
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -186,8 +194,13 @@ int resolve_interface_names(char** ifs, int num_ifs,
|
||||
* @param http_endpoint: HTTP endpoint to service queries on
|
||||
* @param http_notls: no TLS for http downstream
|
||||
* @param tcp_conn_limit: TCP connection limit info.
|
||||
* @param sslctx: nonNULL if ssl context.
|
||||
* @param dot_sslctx: nonNULL if dot ssl context.
|
||||
* @param doh_sslctx: nonNULL if doh ssl context.
|
||||
* @param quic_sslctx: nonNULL if quic ssl context.
|
||||
* @param dtenv: nonNULL if dnstap enabled.
|
||||
* @param doq_table: the doq connection table, with shared information.
|
||||
* @param rnd: random state.
|
||||
* @param cfg: config file struct.
|
||||
* @param cb: callback function when a request arrives. It is passed
|
||||
* the packet and user argument. Return true to send a reply.
|
||||
* @param cb_arg: user data argument for callback function.
|
||||
@@ -198,8 +211,11 @@ listen_create(struct comm_base* base, struct listen_port* ports,
|
||||
size_t bufsize, int tcp_accept_count, int tcp_idle_timeout,
|
||||
int harden_large_queries, uint32_t http_max_streams,
|
||||
char* http_endpoint, int http_notls, struct tcl_list* tcp_conn_limit,
|
||||
void* sslctx, struct dt_env* dtenv, comm_point_callback_type* cb,
|
||||
void *cb_arg);
|
||||
void* dot_sslctx, void* doh_sslctx, void* quic_sslctx,
|
||||
struct dt_env* dtenv,
|
||||
struct doq_table* doq_table,
|
||||
struct ub_randstate* rnd,struct config_file* cfg,
|
||||
comm_point_callback_type* cb, void *cb_arg);
|
||||
|
||||
/**
|
||||
* delete the listening structure
|
||||
@@ -278,11 +294,12 @@ int create_udp_sock(int family, int socktype, struct sockaddr* addr,
|
||||
* @param freebind: set IP_FREEBIND socket option.
|
||||
* @param use_systemd: if true, fetch sockets from systemd.
|
||||
* @param dscp: DSCP to use.
|
||||
* @param additional: additional log information for the socket type.
|
||||
* @return: the socket. -1 on error.
|
||||
*/
|
||||
int create_tcp_accept_sock(struct addrinfo *addr, int v6only, int* noproto,
|
||||
int* reuseport, int transparent, int mss, int nodelay, int freebind,
|
||||
int use_systemd, int dscp);
|
||||
int use_systemd, int dscp, const char* additional);
|
||||
|
||||
/**
|
||||
* Create and bind local listening socket
|
||||
@@ -452,6 +469,383 @@ int http2_submit_dns_response(struct http2_session* h2_session);
|
||||
int http2_submit_dns_response(void* v);
|
||||
#endif /* HAVE_NGHTTP2 */
|
||||
|
||||
#ifdef HAVE_NGTCP2
|
||||
struct doq_conid;
|
||||
struct doq_server_socket;
|
||||
|
||||
/**
|
||||
* DoQ shared connection table. This is the connections for the host.
|
||||
* And some config parameter values for connections. The host has to
|
||||
* respond on that ip,port for those connections, so they are shared
|
||||
* between threads.
|
||||
*/
|
||||
struct doq_table {
|
||||
/** the lock on the tree and config elements. insert and deletion,
|
||||
* also lookup in the tree needs to hold the lock. */
|
||||
lock_rw_type lock;
|
||||
/** rbtree of doq_conn, the connections to different destination
|
||||
* addresses, and can be found by dcid. */
|
||||
struct rbtree_type* conn_tree;
|
||||
/** lock for the conid tree, needed for the conid tree and also
|
||||
* the conid elements */
|
||||
lock_rw_type conid_lock;
|
||||
/** rbtree of doq_conid, connections can be found by their
|
||||
* connection ids. Lookup by connection id, finds doq_conn. */
|
||||
struct rbtree_type* conid_tree;
|
||||
/** the server scid length */
|
||||
int sv_scidlen;
|
||||
/** the static secret for the server */
|
||||
uint8_t* static_secret;
|
||||
/** length of the static secret */
|
||||
size_t static_secret_len;
|
||||
/** the idle timeout in nanoseconds */
|
||||
uint64_t idle_timeout;
|
||||
/** the list of write interested connections, hold the doq_table.lock
|
||||
* to change them */
|
||||
struct doq_conn* write_list_first, *write_list_last;
|
||||
/** rbtree of doq_timer. */
|
||||
struct rbtree_type* timer_tree;
|
||||
/** lock on the current_size counter. */
|
||||
lock_basic_type size_lock;
|
||||
/** current use, in bytes, of QUIC buffers.
|
||||
* The doq_conn ngtcp2_conn structure, SSL structure and conid structs
|
||||
* are not counted. */
|
||||
size_t current_size;
|
||||
};
|
||||
|
||||
/**
|
||||
* create SSL context for QUIC
|
||||
* @param key: private key file.
|
||||
* @param pem: public key cert.
|
||||
* @param verifypem: if nonNULL, verifylocation file.
|
||||
* return SSL_CTX* or NULL on failure (logged).
|
||||
*/
|
||||
void* quic_sslctx_create(char* key, char* pem, char* verifypem);
|
||||
|
||||
/** create doq table */
|
||||
struct doq_table* doq_table_create(struct config_file* cfg,
|
||||
struct ub_randstate* rnd);
|
||||
|
||||
/** delete doq table */
|
||||
void doq_table_delete(struct doq_table* table);
|
||||
|
||||
/**
|
||||
* Timer information for doq timer.
|
||||
*/
|
||||
struct doq_timer {
|
||||
/** The rbnode in the tree sorted by timeout value. Key this struct. */
|
||||
struct rbnode_type node;
|
||||
/** The timeout value. Absolute time value. */
|
||||
struct timeval time;
|
||||
/** If the timer is in the time tree, with the node. */
|
||||
int timer_in_tree;
|
||||
/** If there are more timers with the exact same timeout value,
|
||||
* they form a set of timers. The rbnode timer has a link to the list
|
||||
* with the other timers in the set. The rbnode timer is not a
|
||||
* member of the list with the other timers. The other timers are not
|
||||
* linked into the tree. */
|
||||
struct doq_timer* setlist_first, *setlist_last;
|
||||
/** If the timer is on the setlist. */
|
||||
int timer_in_list;
|
||||
/** If in the setlist, the next and prev element. */
|
||||
struct doq_timer* setlist_next, *setlist_prev;
|
||||
/** The connection that is timeouted. */
|
||||
struct doq_conn* conn;
|
||||
/** The worker that is waiting for the timeout event.
|
||||
* Set for the rbnode tree linked element. If a worker is waiting
|
||||
* for the event. If NULL, no worker is waiting for this timeout. */
|
||||
struct doq_server_socket* worker_doq_socket;
|
||||
};
|
||||
|
||||
/**
|
||||
* Key information that makes a doq_conn node in the tree lookup.
|
||||
*/
|
||||
struct doq_conn_key {
|
||||
/** the remote endpoint and local endpoint and ifindex */
|
||||
struct doq_pkt_addr paddr;
|
||||
/** the doq connection dcid */
|
||||
uint8_t* dcid;
|
||||
/** length of dcid */
|
||||
size_t dcidlen;
|
||||
};
|
||||
|
||||
/**
|
||||
* DoQ connection, for DNS over QUIC. One connection to a remote endpoint
|
||||
* with a number of streams in it. Every stream is like a tcp stream with
|
||||
* a uint16_t length, query read, and a uint16_t length and answer written.
|
||||
*/
|
||||
struct doq_conn {
|
||||
/** rbtree node, key is addresses and dcid */
|
||||
struct rbnode_type node;
|
||||
/** lock on the connection */
|
||||
lock_basic_type lock;
|
||||
/** the key information, with dcid and address endpoint */
|
||||
struct doq_conn_key key;
|
||||
/** the doq server socket for inside callbacks */
|
||||
struct doq_server_socket* doq_socket;
|
||||
/** the doq table this connection is part of */
|
||||
struct doq_table* table;
|
||||
/** if the connection is about to be deleted. */
|
||||
uint8_t is_deleted;
|
||||
/** the version, the client chosen version of QUIC */
|
||||
uint32_t version;
|
||||
/** the ngtcp2 connection, a server connection */
|
||||
struct ngtcp2_conn* conn;
|
||||
/** the connection ids that are associated with this doq_conn.
|
||||
* There can be a number, that can change. They are linked here,
|
||||
* so that upon removal, the list of actually associated conid
|
||||
* elements can be removed as well. */
|
||||
struct doq_conid* conid_list;
|
||||
/** the ngtcp2 last error for the connection */
|
||||
#ifdef HAVE_NGTCP2_CCERR_DEFAULT
|
||||
struct ngtcp2_ccerr ccerr;
|
||||
#else
|
||||
struct ngtcp2_connection_close_error last_error;
|
||||
#endif
|
||||
/** the recent tls alert error code */
|
||||
uint8_t tls_alert;
|
||||
/** the ssl context, SSL* */
|
||||
void* ssl;
|
||||
#ifdef HAVE_NGTCP2_CRYPTO_QUICTLS_CONFIGURE_SERVER_CONTEXT
|
||||
/** the connection reference for ngtcp2_conn and userdata in ssl */
|
||||
struct ngtcp2_crypto_conn_ref conn_ref;
|
||||
#endif
|
||||
/** closure packet, if any */
|
||||
uint8_t* close_pkt;
|
||||
/** length of closure packet. */
|
||||
size_t close_pkt_len;
|
||||
/** closure ecn */
|
||||
uint32_t close_ecn;
|
||||
/** the streams for this connection, of type doq_stream */
|
||||
struct rbtree_type stream_tree;
|
||||
/** the streams that want write, they have something to write.
|
||||
* The list is ordered, the last have to wait for the first to
|
||||
* get their data written. */
|
||||
struct doq_stream* stream_write_first, *stream_write_last;
|
||||
/** the conn has write interest if true, no write interest if false. */
|
||||
uint8_t write_interest;
|
||||
/** if the conn is on the connection write list */
|
||||
uint8_t on_write_list;
|
||||
/** the connection write list prev and next, if on the write list */
|
||||
struct doq_conn* write_prev, *write_next;
|
||||
/** The timer for the connection. If unused, it is not in the tree
|
||||
* and not in the list. It is alloced here, so that it is prealloced.
|
||||
* It has to be set after every read and write on the connection, so
|
||||
* this improves performance, but also the allocation does not fail. */
|
||||
struct doq_timer timer;
|
||||
};
|
||||
|
||||
/**
|
||||
* Connection ID and the doq_conn that is that connection. A connection
|
||||
* has an original dcid, and then more connection ids associated.
|
||||
*/
|
||||
struct doq_conid {
|
||||
/** rbtree node, key is the connection id. */
|
||||
struct rbnode_type node;
|
||||
/** the next and prev in the list of conids for the doq_conn */
|
||||
struct doq_conid* next, *prev;
|
||||
/** key to the doq_conn that is the connection */
|
||||
struct doq_conn_key key;
|
||||
/** the connection id, byte string */
|
||||
uint8_t* cid;
|
||||
/** the length of cid */
|
||||
size_t cidlen;
|
||||
};
|
||||
|
||||
/**
|
||||
* DoQ stream, for DNS over QUIC.
|
||||
*/
|
||||
struct doq_stream {
|
||||
/** the rbtree node for the stream, key is the stream_id */
|
||||
rbnode_type node;
|
||||
/** the stream id */
|
||||
int64_t stream_id;
|
||||
/** if the stream is closed */
|
||||
uint8_t is_closed;
|
||||
/** if the query is complete */
|
||||
uint8_t is_query_complete;
|
||||
/** the number of bytes read on the stream, up to querylen+2. */
|
||||
size_t nread;
|
||||
/** the length of the input query bytes */
|
||||
size_t inlen;
|
||||
/** the input bytes */
|
||||
uint8_t* in;
|
||||
/** does the stream have an answer to send */
|
||||
uint8_t is_answer_available;
|
||||
/** the answer bytes sent, up to outlen+2. */
|
||||
size_t nwrite;
|
||||
/** the length of the output answer bytes */
|
||||
size_t outlen;
|
||||
/** the output length in network wireformat */
|
||||
uint16_t outlen_wire;
|
||||
/** the output packet bytes */
|
||||
uint8_t* out;
|
||||
/** if the stream is on the write list */
|
||||
uint8_t on_write_list;
|
||||
/** the prev and next on the write list, if on the list */
|
||||
struct doq_stream* write_prev, *write_next;
|
||||
};
|
||||
|
||||
/** doq application error code that is sent when a stream is closed */
|
||||
#define DOQ_APP_ERROR_CODE 1
|
||||
|
||||
/**
|
||||
* Create the doq connection.
|
||||
* @param c: the comm point for the listening doq socket.
|
||||
* @param paddr: with remote and local address and ifindex for the
|
||||
* connection destination. This is where packets are sent.
|
||||
* @param dcid: the dcid, Destination Connection ID.
|
||||
* @param dcidlen: length of dcid.
|
||||
* @param version: client chosen version.
|
||||
* @return new doq connection or NULL on allocation failure.
|
||||
*/
|
||||
struct doq_conn* doq_conn_create(struct comm_point* c,
|
||||
struct doq_pkt_addr* paddr, const uint8_t* dcid, size_t dcidlen,
|
||||
uint32_t version);
|
||||
|
||||
/**
|
||||
* Delete the doq connection structure.
|
||||
* @param conn: to delete.
|
||||
* @param table: with memory size.
|
||||
*/
|
||||
void doq_conn_delete(struct doq_conn* conn, struct doq_table* table);
|
||||
|
||||
/** compare function of doq_conn */
|
||||
int doq_conn_cmp(const void* key1, const void* key2);
|
||||
|
||||
/** compare function of doq_conid */
|
||||
int doq_conid_cmp(const void* key1, const void* key2);
|
||||
|
||||
/** compare function of doq_timer */
|
||||
int doq_timer_cmp(const void* key1, const void* key2);
|
||||
|
||||
/** compare function of doq_stream */
|
||||
int doq_stream_cmp(const void* key1, const void* key2);
|
||||
|
||||
/** setup the doq connection callbacks, and settings. */
|
||||
int doq_conn_setup(struct doq_conn* conn, uint8_t* scid, size_t scidlen,
|
||||
uint8_t* ocid, size_t ocidlen, const uint8_t* token, size_t tokenlen);
|
||||
|
||||
/** fill a buffer with random data */
|
||||
void doq_fill_rand(struct ub_randstate* rnd, uint8_t* buf, size_t len);
|
||||
|
||||
/** delete a doq_conid */
|
||||
void doq_conid_delete(struct doq_conid* conid);
|
||||
|
||||
/** add a connection id to the doq_conn.
|
||||
* caller must hold doq_table.conid_lock. */
|
||||
int doq_conn_associate_conid(struct doq_conn* conn, uint8_t* data,
|
||||
size_t datalen);
|
||||
|
||||
/** remove a connection id from the doq_conn.
|
||||
* caller must hold doq_table.conid_lock. */
|
||||
void doq_conn_dissociate_conid(struct doq_conn* conn, const uint8_t* data,
|
||||
size_t datalen);
|
||||
|
||||
/** initial setup to link current connection ids to the doq_conn */
|
||||
int doq_conn_setup_conids(struct doq_conn* conn);
|
||||
|
||||
/** remove the connection ids from the doq_conn.
|
||||
* caller must hold doq_table.conid_lock. */
|
||||
void doq_conn_clear_conids(struct doq_conn* conn);
|
||||
|
||||
/** find a conid in the doq_conn connection.
|
||||
* caller must hold table.conid_lock. */
|
||||
struct doq_conid* doq_conid_find(struct doq_table* doq_table,
|
||||
const uint8_t* data, size_t datalen);
|
||||
|
||||
/** receive a packet for a connection */
|
||||
int doq_conn_recv(struct comm_point* c, struct doq_pkt_addr* paddr,
|
||||
struct doq_conn* conn, struct ngtcp2_pkt_info* pi, int* err_retry,
|
||||
int* err_drop);
|
||||
|
||||
/** send packets for a connection */
|
||||
int doq_conn_write_streams(struct comm_point* c, struct doq_conn* conn,
|
||||
int* err_drop);
|
||||
|
||||
/** send the close packet for the connection, perhaps again. */
|
||||
int doq_conn_send_close(struct comm_point* c, struct doq_conn* conn);
|
||||
|
||||
/** delete doq stream */
|
||||
void doq_stream_delete(struct doq_stream* stream);
|
||||
|
||||
/** doq read a connection key from repinfo. It is not malloced, but points
|
||||
* into the repinfo for the dcid. */
|
||||
void doq_conn_key_from_repinfo(struct doq_conn_key* key,
|
||||
struct comm_reply* repinfo);
|
||||
|
||||
/** doq find a stream in the connection */
|
||||
struct doq_stream* doq_stream_find(struct doq_conn* conn, int64_t stream_id);
|
||||
|
||||
/** doq shutdown the stream. */
|
||||
int doq_stream_close(struct doq_conn* conn, struct doq_stream* stream,
|
||||
int send_shutdown);
|
||||
|
||||
/** send reply for a connection */
|
||||
int doq_stream_send_reply(struct doq_conn* conn, struct doq_stream* stream,
|
||||
struct sldns_buffer* buf);
|
||||
|
||||
/** the connection has write interest, wants to write packets */
|
||||
void doq_conn_write_enable(struct doq_conn* conn);
|
||||
|
||||
/** the connection has no write interest, does not want to write packets */
|
||||
void doq_conn_write_disable(struct doq_conn* conn);
|
||||
|
||||
/** set the connection on or off the write list, depending on write interest */
|
||||
void doq_conn_set_write_list(struct doq_table* table, struct doq_conn* conn);
|
||||
|
||||
/** doq remove the connection from the write list */
|
||||
void doq_conn_write_list_remove(struct doq_table* table,
|
||||
struct doq_conn* conn);
|
||||
|
||||
/** doq get the first conn from the write list, if any, popped from list.
|
||||
* Locks the conn that is returned. */
|
||||
struct doq_conn* doq_table_pop_first(struct doq_table* table);
|
||||
|
||||
/**
|
||||
* doq check if the timer for the conn needs to be changed.
|
||||
* @param conn: connection, caller must hold lock on it.
|
||||
* @param tv: time value, absolute time, returned.
|
||||
* @return true if timer needs to be set to tv, false if no change is needed
|
||||
* to the timer. The timer is already set to the right time in that case.
|
||||
*/
|
||||
int doq_conn_check_timer(struct doq_conn* conn, struct timeval* tv);
|
||||
|
||||
/** doq remove timer from tree */
|
||||
void doq_timer_tree_remove(struct doq_table* table, struct doq_timer* timer);
|
||||
|
||||
/** doq remove timer from list */
|
||||
void doq_timer_list_remove(struct doq_table* table, struct doq_timer* timer);
|
||||
|
||||
/** doq unset the timer if it was set. */
|
||||
void doq_timer_unset(struct doq_table* table, struct doq_timer* timer);
|
||||
|
||||
/** doq set the timer and add it. */
|
||||
void doq_timer_set(struct doq_table* table, struct doq_timer* timer,
|
||||
struct doq_server_socket* worker_doq_socket, struct timeval* tv);
|
||||
|
||||
/** doq find a timeout in the timer tree */
|
||||
struct doq_timer* doq_timer_find_time(struct doq_table* table,
|
||||
struct timeval* tv);
|
||||
|
||||
/** doq handle timeout for a connection. Pass conn locked. Returns false for
|
||||
* deletion. */
|
||||
int doq_conn_handle_timeout(struct doq_conn* conn);
|
||||
|
||||
/** doq add size to the current quic buffer counter */
|
||||
void doq_table_quic_size_add(struct doq_table* table, size_t add);
|
||||
|
||||
/** doq subtract size from the current quic buffer counter */
|
||||
void doq_table_quic_size_subtract(struct doq_table* table, size_t subtract);
|
||||
|
||||
/** doq check if mem is available for quic. */
|
||||
int doq_table_quic_size_available(struct doq_table* table,
|
||||
struct config_file* cfg, size_t mem);
|
||||
|
||||
/** doq get the quic size value */
|
||||
size_t doq_table_quic_size_get(struct doq_table* table);
|
||||
#endif /* HAVE_NGTCP2 */
|
||||
|
||||
char* set_ip_dscp(int socket, int addrfamily, int ds);
|
||||
|
||||
/** for debug and profiling purposes only
|
||||
@@ -459,4 +853,14 @@ char* set_ip_dscp(int socket, int addrfamily, int ds);
|
||||
*/
|
||||
void verbose_print_unbound_socket(struct unbound_socket* ub_sock);
|
||||
|
||||
/** event callback for testcode/doqclient */
|
||||
void doq_client_event_cb(int fd, short event, void* arg);
|
||||
|
||||
/** timer event callback for testcode/doqclient */
|
||||
void doq_client_timer_cb(int fd, short event, void* arg);
|
||||
|
||||
#ifdef HAVE_NGTCP2
|
||||
/** get a timestamp in nanoseconds */
|
||||
ngtcp2_tstamp doq_get_timestamp_nanosec(void);
|
||||
#endif
|
||||
#endif /* LISTEN_DNSPORT_H */
|
||||
|
||||
+46
-4
@@ -223,7 +223,7 @@ lz_enter_zone_dname(struct local_zones* zones, uint8_t* nm, size_t len,
|
||||
lock_rw_wrlock(&z->lock);
|
||||
if(!rbtree_insert(&zones->ztree, &z->node)) {
|
||||
struct local_zone* oldz;
|
||||
char str[256];
|
||||
char str[LDNS_MAX_DOMAINLEN];
|
||||
dname_str(nm, str);
|
||||
log_warn("duplicate local-zone %s", str);
|
||||
lock_rw_unlock(&z->lock);
|
||||
@@ -943,6 +943,16 @@ int local_zone_enter_defaults(struct local_zones* zones, struct config_file* cfg
|
||||
log_err("out of memory adding default zone");
|
||||
return 0;
|
||||
}
|
||||
/* resolver.arpa. zone (RFC 9462) */
|
||||
if(!add_empty_default(zones, cfg, "resolver.arpa.")) {
|
||||
log_err("out of memory adding default zone");
|
||||
return 0;
|
||||
}
|
||||
/* service.arpa. zone (draft-ietf-dnssd-srp-25) */
|
||||
if(!add_empty_default(zones, cfg, "service.arpa.")) {
|
||||
log_err("out of memory adding default zone");
|
||||
return 0;
|
||||
}
|
||||
/* onion. zone (RFC 7686) */
|
||||
if(!add_empty_default(zones, cfg, "onion.")) {
|
||||
log_err("out of memory adding default zone");
|
||||
@@ -1765,7 +1775,7 @@ lz_inform_print(struct local_zone* z, struct query_info* qinfo,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen)
|
||||
{
|
||||
char ip[128], txt[512];
|
||||
char zname[LDNS_MAX_DOMAINLEN+1];
|
||||
char zname[LDNS_MAX_DOMAINLEN];
|
||||
uint16_t port = ntohs(((struct sockaddr_in*)addr)->sin_port);
|
||||
dname_str(z->name, zname);
|
||||
addr_to_str(addr, addrlen, ip, sizeof(ip));
|
||||
@@ -1875,7 +1885,7 @@ local_zones_answer(struct local_zones* zones, struct module_env* env,
|
||||
return 0;
|
||||
}
|
||||
if(z && verbosity >= VERB_ALGO) {
|
||||
char zname[255+1];
|
||||
char zname[LDNS_MAX_DOMAINLEN];
|
||||
dname_str(z->name, zname);
|
||||
verbose(VERB_ALGO, "using localzone %s %s from view %s",
|
||||
zname, local_zone_type2str(lzt), view->name);
|
||||
@@ -1897,7 +1907,7 @@ local_zones_answer(struct local_zones* zones, struct module_env* env,
|
||||
z->override_tree, &tag, tagname, num_tags);
|
||||
lock_rw_unlock(&zones->lock);
|
||||
if(z && verbosity >= VERB_ALGO) {
|
||||
char zname[255+1];
|
||||
char zname[LDNS_MAX_DOMAINLEN];
|
||||
dname_str(z->name, zname);
|
||||
verbose(VERB_ALGO, "using localzone %s %s", zname,
|
||||
local_zone_type2str(lzt));
|
||||
@@ -2210,3 +2220,35 @@ void local_zones_del_data(struct local_zones* zones,
|
||||
|
||||
lock_rw_unlock(&z->lock);
|
||||
}
|
||||
|
||||
/** Get memory usage for local_zone */
|
||||
static size_t
|
||||
local_zone_get_mem(struct local_zone* z)
|
||||
{
|
||||
size_t m = sizeof(*z);
|
||||
lock_rw_rdlock(&z->lock);
|
||||
m += z->namelen + z->taglen + regional_get_mem(z->region);
|
||||
lock_rw_unlock(&z->lock);
|
||||
return m;
|
||||
}
|
||||
|
||||
size_t local_zones_get_mem(struct local_zones* zones)
|
||||
{
|
||||
struct local_zone* z;
|
||||
size_t m;
|
||||
if(!zones) return 0;
|
||||
m = sizeof(*zones);
|
||||
lock_rw_rdlock(&zones->lock);
|
||||
RBTREE_FOR(z, struct local_zone*, &zones->ztree) {
|
||||
m += local_zone_get_mem(z);
|
||||
}
|
||||
lock_rw_unlock(&zones->lock);
|
||||
return m;
|
||||
}
|
||||
|
||||
void local_zones_swap_tree(struct local_zones* zones, struct local_zones* data)
|
||||
{
|
||||
rbtree_type oldtree = zones->ztree;
|
||||
zones->ztree = data->ztree;
|
||||
data->ztree = oldtree;
|
||||
}
|
||||
|
||||
@@ -642,6 +642,20 @@ local_zone_enter_rr(struct local_zone* z, uint8_t* nm, size_t nmlen,
|
||||
struct local_data*
|
||||
local_zone_find_data(struct local_zone* z, uint8_t* nm, size_t nmlen, int nmlabs);
|
||||
|
||||
/** Get memory usage for local_zones tree. The routine locks and unlocks
|
||||
* the tree for reading. */
|
||||
size_t local_zones_get_mem(struct local_zones* zones);
|
||||
|
||||
/**
|
||||
* Swap internal tree with preallocated entries. Caller should manage
|
||||
* the locks.
|
||||
* @param zones: the local zones structure.
|
||||
* @param data: the data structure used to take elements from. This contains
|
||||
* the old elements on return.
|
||||
*/
|
||||
void local_zones_swap_tree(struct local_zones* zones,
|
||||
struct local_zones* data);
|
||||
|
||||
/** Enter a new zone; returns with WRlock
|
||||
* Made public for unit testing
|
||||
* @param zones: the local zones tree
|
||||
|
||||
+291
-25
@@ -77,6 +77,20 @@
|
||||
#include <netdb.h>
|
||||
#endif
|
||||
|
||||
/** Compare two views by name */
|
||||
static int
|
||||
view_name_compare(const char* v_a, const char* v_b)
|
||||
{
|
||||
if(v_a == NULL && v_b == NULL)
|
||||
return 0;
|
||||
/* The NULL name is smaller than if the name is set. */
|
||||
if(v_a == NULL)
|
||||
return -1;
|
||||
if(v_b == NULL)
|
||||
return 1;
|
||||
return strcmp(v_a, v_b);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare two response-ip client info entries for the purpose of mesh state
|
||||
* compare. It returns 0 if ci_a and ci_b are considered equal; otherwise
|
||||
@@ -132,12 +146,14 @@ client_info_compare(const struct respip_client_info* ci_a,
|
||||
}
|
||||
if(ci_a->tag_datas != ci_b->tag_datas)
|
||||
return ci_a->tag_datas < ci_b->tag_datas ? -1 : 1;
|
||||
if(ci_a->view != ci_b->view)
|
||||
return ci_a->view < ci_b->view ? -1 : 1;
|
||||
/* For the unbound daemon these should be non-NULL and identical,
|
||||
* but we check that just in case. */
|
||||
if(ci_a->respip_set != ci_b->respip_set)
|
||||
return ci_a->respip_set < ci_b->respip_set ? -1 : 1;
|
||||
if(ci_a->view || ci_a->view_name || ci_b->view || ci_b->view_name) {
|
||||
/* Compare the views by name. */
|
||||
cmp = view_name_compare(
|
||||
(ci_a->view?ci_a->view->name:ci_a->view_name),
|
||||
(ci_b->view?ci_b->view->name:ci_b->view_name));
|
||||
if(cmp != 0)
|
||||
return cmp;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -214,6 +230,9 @@ mesh_create(struct module_stack* stack, struct module_env* env)
|
||||
mesh->stats_dropped = 0;
|
||||
mesh->ans_expired = 0;
|
||||
mesh->ans_cachedb = 0;
|
||||
mesh->num_queries_discard_timeout = 0;
|
||||
mesh->num_queries_wait_limit = 0;
|
||||
mesh->num_dns_error_reports = 0;
|
||||
mesh->max_reply_states = env->cfg->num_queries_per_thread;
|
||||
mesh->max_forever_states = (mesh->max_reply_states+1)/2;
|
||||
#ifndef S_SPLINT_S
|
||||
@@ -311,7 +330,7 @@ int mesh_make_new_space(struct mesh_area* mesh, sldns_buffer* qbuf)
|
||||
|
||||
struct dns_msg*
|
||||
mesh_serve_expired_lookup(struct module_qstate* qstate,
|
||||
struct query_info* lookup_qinfo)
|
||||
struct query_info* lookup_qinfo, int* is_expired)
|
||||
{
|
||||
hashvalue_type h;
|
||||
struct lruhash_entry* e;
|
||||
@@ -321,6 +340,7 @@ mesh_serve_expired_lookup(struct module_qstate* qstate,
|
||||
time_t timenow = *qstate->env->now;
|
||||
int must_validate = (!(qstate->query_flags&BIT_CD)
|
||||
|| qstate->env->cfg->ignore_cd) && qstate->env->need_to_validate;
|
||||
*is_expired = 0;
|
||||
/* Lookup cache */
|
||||
h = query_info_hash(lookup_qinfo, qstate->query_flags);
|
||||
e = slabhash_lookup(qstate->env->msg_cache, h, lookup_qinfo, 0);
|
||||
@@ -328,6 +348,7 @@ mesh_serve_expired_lookup(struct module_qstate* qstate,
|
||||
|
||||
key = (struct msgreply_entry*)e->key;
|
||||
data = (struct reply_info*)e->data;
|
||||
if(data->ttl < timenow) *is_expired = 1;
|
||||
msg = tomsg(qstate->env, &key->key, data, qstate->region, timenow,
|
||||
qstate->env->cfg->serve_expired, qstate->env->scratch);
|
||||
if(!msg)
|
||||
@@ -422,7 +443,7 @@ void mesh_new_client(struct mesh_area* mesh, struct query_info* qinfo,
|
||||
verbose(VERB_ALGO, "Too many queries waiting from the IP. "
|
||||
"dropping incoming query.");
|
||||
comm_point_drop_reply(rep);
|
||||
mesh->stats_dropped++;
|
||||
mesh->num_queries_wait_limit++;
|
||||
return;
|
||||
}
|
||||
if(!unique)
|
||||
@@ -866,6 +887,78 @@ void mesh_report_reply(struct mesh_area* mesh, struct outbound_entry* e,
|
||||
mesh_run(mesh, e->qstate->mesh_info, event, e);
|
||||
}
|
||||
|
||||
/** copy strlist to region */
|
||||
static struct config_strlist*
|
||||
cfg_region_strlist_copy(struct regional* region, struct config_strlist* list)
|
||||
{
|
||||
struct config_strlist* result = NULL, *last = NULL, *s = list;
|
||||
while(s) {
|
||||
struct config_strlist* n = regional_alloc_zero(region,
|
||||
sizeof(*n));
|
||||
if(!n)
|
||||
return NULL;
|
||||
n->str = regional_strdup(region, s->str);
|
||||
if(!n->str)
|
||||
return NULL;
|
||||
if(last)
|
||||
last->next = n;
|
||||
else result = n;
|
||||
last = n;
|
||||
s = s->next;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/** Copy the client info to the query region. */
|
||||
static struct respip_client_info*
|
||||
mesh_copy_client_info(struct regional* region, struct respip_client_info* cinfo)
|
||||
{
|
||||
size_t i;
|
||||
struct respip_client_info* client_info;
|
||||
client_info = regional_alloc_init(region, cinfo, sizeof(*cinfo));
|
||||
if(!client_info)
|
||||
return NULL;
|
||||
/* Copy the client_info so that if the configuration changes,
|
||||
* then the data stays valid. */
|
||||
if(cinfo->taglist) {
|
||||
client_info->taglist = regional_alloc_init(region, cinfo->taglist,
|
||||
cinfo->taglen);
|
||||
if(!client_info->taglist)
|
||||
return NULL;
|
||||
}
|
||||
if(cinfo->tag_actions) {
|
||||
client_info->tag_actions = regional_alloc_init(region, cinfo->tag_actions,
|
||||
cinfo->tag_actions_size);
|
||||
if(!client_info->tag_actions)
|
||||
return NULL;
|
||||
}
|
||||
if(cinfo->tag_datas) {
|
||||
client_info->tag_datas = regional_alloc_zero(region,
|
||||
sizeof(struct config_strlist*)*cinfo->tag_datas_size);
|
||||
if(!client_info->tag_datas)
|
||||
return NULL;
|
||||
for(i=0; i<cinfo->tag_datas_size; i++) {
|
||||
if(cinfo->tag_datas[i]) {
|
||||
client_info->tag_datas[i] = cfg_region_strlist_copy(
|
||||
region, cinfo->tag_datas[i]);
|
||||
if(!client_info->tag_datas[i])
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(cinfo->view) {
|
||||
/* Do not copy the view pointer but store a name instead.
|
||||
* The name is looked up later when done, this means that
|
||||
* the view tree can be changed, by reloads. */
|
||||
client_info->view = NULL;
|
||||
client_info->view_name = regional_strdup(region,
|
||||
cinfo->view->name);
|
||||
if(!client_info->view_name)
|
||||
return NULL;
|
||||
}
|
||||
return client_info;
|
||||
}
|
||||
|
||||
struct mesh_state*
|
||||
mesh_state_create(struct module_env* env, struct query_info* qinfo,
|
||||
struct respip_client_info* cinfo, uint16_t qflags, int prime,
|
||||
@@ -906,8 +999,7 @@ mesh_state_create(struct module_env* env, struct query_info* qinfo,
|
||||
return NULL;
|
||||
}
|
||||
if(cinfo) {
|
||||
mstate->s.client_info = regional_alloc_init(region, cinfo,
|
||||
sizeof(*cinfo));
|
||||
mstate->s.client_info = mesh_copy_client_info(region, cinfo);
|
||||
if(!mstate->s.client_info) {
|
||||
alloc_reg_release(env->alloc, region);
|
||||
return NULL;
|
||||
@@ -1487,10 +1579,121 @@ mesh_send_reply(struct mesh_state* m, int rcode, struct reply_info* rep,
|
||||
&r->query_reply.client_addr,
|
||||
r->query_reply.client_addrlen, duration, 0, r_buffer,
|
||||
(m->s.env->cfg->log_destaddr?(void*)r->query_reply.c->socket->addr:NULL),
|
||||
r->query_reply.c->type);
|
||||
r->query_reply.c->type, r->query_reply.c->ssl);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the DNS Error Report (RFC9567).
|
||||
* If there is an EDE attached for this reply and there was a Report-Channel
|
||||
* EDNS0 option from the upstream, fire up a report query.
|
||||
* @param qstate: module qstate.
|
||||
* @param rep: prepared reply to be sent.
|
||||
*/
|
||||
static void dns_error_reporting(struct module_qstate* qstate,
|
||||
struct reply_info* rep)
|
||||
{
|
||||
struct query_info qinfo;
|
||||
struct mesh_state* sub;
|
||||
struct module_qstate* newq;
|
||||
uint8_t buf[LDNS_MAX_DOMAINLEN];
|
||||
size_t count = 0;
|
||||
int written;
|
||||
size_t expected_length;
|
||||
struct edns_option* opt;
|
||||
sldns_ede_code reason_bogus = LDNS_EDE_NONE;
|
||||
sldns_rr_type qtype = qstate->qinfo.qtype;
|
||||
uint8_t* qname = qstate->qinfo.qname;
|
||||
size_t qname_len = qstate->qinfo.qname_len-1; /* skip the trailing \0 */
|
||||
uint8_t* agent_domain;
|
||||
size_t agent_domain_len;
|
||||
|
||||
/* We need a valid reporting agent;
|
||||
* this is based on qstate->edns_opts_back_in that will probably have
|
||||
* the latest reporting agent we found while iterating */
|
||||
opt = edns_opt_list_find(qstate->edns_opts_back_in,
|
||||
LDNS_EDNS_REPORT_CHANNEL);
|
||||
if(!opt) return;
|
||||
agent_domain_len = opt->opt_len;
|
||||
agent_domain = opt->opt_data;
|
||||
if(dname_valid(agent_domain, agent_domain_len) < 3) {
|
||||
/* The agent domain needs to be a valid dname that is not the
|
||||
* root; from RFC9567. */
|
||||
return;
|
||||
}
|
||||
|
||||
/* Get the EDE generated from the mesh state, these are mostly
|
||||
* validator errors. If other errors are produced in the future (e.g.,
|
||||
* RPZ) we would not want them to result in error reports. */
|
||||
reason_bogus = errinf_to_reason_bogus(qstate);
|
||||
if(rep && ((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 ||
|
||||
/* other, does not make sense without the text that comes
|
||||
* with it */
|
||||
reason_bogus == LDNS_EDE_OTHER) return;
|
||||
|
||||
/* Synthesize the error report query in the format:
|
||||
* "_er.$qtype.$qname.$ede._er.$reporting-agent-domain" */
|
||||
/* First check if the static length parts fit in the buffer.
|
||||
* That is everything except for qtype and ede that need to be
|
||||
* converted to decimal and checked further on. */
|
||||
expected_length = 4/*_er*/+qname_len+4/*_er*/+agent_domain_len;
|
||||
if(expected_length > LDNS_MAX_DOMAINLEN) goto skip;
|
||||
|
||||
memmove(buf+count, "\3_er", 4);
|
||||
count += 4;
|
||||
|
||||
written = snprintf((char*)buf+count, LDNS_MAX_DOMAINLEN-count,
|
||||
"X%d", qtype);
|
||||
expected_length += written;
|
||||
/* Skip on error, truncation or long expected length */
|
||||
if(written < 0 || (size_t)written >= LDNS_MAX_DOMAINLEN-count ||
|
||||
expected_length > LDNS_MAX_DOMAINLEN ) goto skip;
|
||||
/* Put in the label length */
|
||||
*(buf+count) = (char)(written - 1);
|
||||
count += written;
|
||||
|
||||
memmove(buf+count, qname, qname_len);
|
||||
count += qname_len;
|
||||
|
||||
written = snprintf((char*)buf+count, LDNS_MAX_DOMAINLEN-count,
|
||||
"X%d", reason_bogus);
|
||||
expected_length += written;
|
||||
/* Skip on error, truncation or long expected length */
|
||||
if(written < 0 || (size_t)written >= LDNS_MAX_DOMAINLEN-count ||
|
||||
expected_length > LDNS_MAX_DOMAINLEN ) goto skip;
|
||||
*(buf+count) = (char)(written - 1);
|
||||
count += written;
|
||||
|
||||
memmove(buf+count, "\3_er", 4);
|
||||
count += 4;
|
||||
|
||||
/* Copy the agent domain */
|
||||
memmove(buf+count, agent_domain, agent_domain_len);
|
||||
count += agent_domain_len;
|
||||
|
||||
qinfo.qname = buf;
|
||||
qinfo.qname_len = count;
|
||||
qinfo.qtype = LDNS_RR_TYPE_TXT;
|
||||
qinfo.qclass = qstate->qinfo.qclass;
|
||||
qinfo.local_alias = NULL;
|
||||
|
||||
log_query_info(VERB_ALGO, "DNS Error Reporting: generating report "
|
||||
"query for", &qinfo);
|
||||
if(mesh_add_sub(qstate, &qinfo, BIT_RD, 0, 0, &newq, &sub)) {
|
||||
qstate->env->mesh->num_dns_error_reports++;
|
||||
}
|
||||
return;
|
||||
skip:
|
||||
verbose(VERB_ALGO, "DNS Error Reporting: report query qname too long; "
|
||||
"skip");
|
||||
return;
|
||||
}
|
||||
|
||||
void mesh_query_done(struct mesh_state* mstate)
|
||||
{
|
||||
struct mesh_reply* r;
|
||||
@@ -1508,8 +1711,10 @@ void mesh_query_done(struct mesh_state* mstate)
|
||||
}
|
||||
if(mstate->s.return_rcode == LDNS_RCODE_SERVFAIL ||
|
||||
(rep && FLAGS_GET_RCODE(rep->flags) == LDNS_RCODE_SERVFAIL)) {
|
||||
/* we are SERVFAILing; check for expired answer here */
|
||||
mesh_serve_expired_callback(mstate);
|
||||
if(mstate->s.env->cfg->serve_expired) {
|
||||
/* we are SERVFAILing; check for expired answer here */
|
||||
mesh_respond_serve_expired(mstate);
|
||||
}
|
||||
if((mstate->reply_list || mstate->cb_list)
|
||||
&& mstate->s.env->cfg->log_servfail
|
||||
&& !mstate->s.env->cfg->val_log_squelch) {
|
||||
@@ -1517,6 +1722,10 @@ void mesh_query_done(struct mesh_state* mstate)
|
||||
if(err) { log_err("%s", err); }
|
||||
}
|
||||
}
|
||||
|
||||
if(mstate->reply_list && mstate->s.env->cfg->dns_error_reporting)
|
||||
dns_error_reporting(&mstate->s, rep);
|
||||
|
||||
for(r = mstate->reply_list; r; r = r->next) {
|
||||
struct timeval old;
|
||||
timeval_subtract(&old, mstate->s.env->now_tv, &r->start_time);
|
||||
@@ -1538,7 +1747,7 @@ void mesh_query_done(struct mesh_state* mstate)
|
||||
http2_stream_remove_mesh_state(r->h2_stream);
|
||||
comm_point_drop_reply(&r->query_reply);
|
||||
mstate->reply_list = reply_list;
|
||||
mstate->s.env->mesh->stats_dropped++;
|
||||
mstate->s.env->mesh->num_queries_discard_timeout++;
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -1680,6 +1889,25 @@ struct mesh_state* mesh_area_find(struct mesh_area* mesh,
|
||||
return result;
|
||||
}
|
||||
|
||||
/** remove mesh state callback */
|
||||
int mesh_state_del_cb(struct mesh_state* s, mesh_cb_func_type cb, void* cb_arg)
|
||||
{
|
||||
struct mesh_cb* r, *prev = NULL;
|
||||
r = s->cb_list;
|
||||
while(r) {
|
||||
if(r->cb == cb && r->cb_arg == cb_arg) {
|
||||
/* Delete this entry. */
|
||||
/* It was allocated in the s.region, so no free. */
|
||||
if(prev) prev->next = r->next;
|
||||
else s->cb_list = r->next;
|
||||
return 1;
|
||||
}
|
||||
prev = r;
|
||||
r = r->next;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mesh_state_add_cb(struct mesh_state* s, struct edns_data* edns,
|
||||
sldns_buffer* buf, mesh_cb_func_type cb, void* cb_arg,
|
||||
uint16_t qid, uint16_t qflags)
|
||||
@@ -2027,6 +2255,8 @@ mesh_stats_clear(struct mesh_area* mesh)
|
||||
{
|
||||
if(!mesh)
|
||||
return;
|
||||
mesh->num_query_authzone_up = 0;
|
||||
mesh->num_query_authzone_down = 0;
|
||||
mesh->replies_sent = 0;
|
||||
mesh->replies_sum_wait.tv_sec = 0;
|
||||
mesh->replies_sum_wait.tv_usec = 0;
|
||||
@@ -2040,6 +2270,9 @@ mesh_stats_clear(struct mesh_area* mesh)
|
||||
memset(&mesh->ans_rcode[0], 0, sizeof(size_t)*UB_STATS_RCODE_NUM);
|
||||
memset(&mesh->rpz_action[0], 0, sizeof(size_t)*UB_STATS_RPZ_ACTION_NUM);
|
||||
mesh->ans_nodata = 0;
|
||||
mesh->num_queries_discard_timeout = 0;
|
||||
mesh->num_queries_wait_limit = 0;
|
||||
mesh->num_dns_error_reports = 0;
|
||||
}
|
||||
|
||||
size_t
|
||||
@@ -2141,7 +2374,8 @@ 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, NULL))
|
||||
alias_rrset, 0, qstate->region, az, NULL, qstate->env->views,
|
||||
qstate->env->respip_set))
|
||||
return 0;
|
||||
|
||||
/* xxx_deny actions mean dropping the reply, unless the original reply
|
||||
@@ -2175,7 +2409,8 @@ mesh_serve_expired_callback(void* arg)
|
||||
struct timeval tv = {0, 0};
|
||||
int must_validate = (!(qstate->query_flags&BIT_CD)
|
||||
|| qstate->env->cfg->ignore_cd) && qstate->env->need_to_validate;
|
||||
int i = 0;
|
||||
int i = 0, for_count;
|
||||
int is_expired;
|
||||
if(!qstate->serve_expired_data) return;
|
||||
verbose(VERB_ALGO, "Serve expired: Trying to reply with expired data");
|
||||
comm_timer_delete(qstate->serve_expired_data->timer);
|
||||
@@ -2187,15 +2422,21 @@ mesh_serve_expired_callback(void* arg)
|
||||
"Serve expired: Not allowed to look into cache for stale");
|
||||
return;
|
||||
}
|
||||
/* The following while is used instead of the `goto lookup_cache`
|
||||
* like in the worker. */
|
||||
while(1) {
|
||||
/* The following for is used instead of the `goto lookup_cache`
|
||||
* like in the worker. This loop should get max 2 passes if we need to
|
||||
* do any aliasing. */
|
||||
for(for_count = 0; for_count < 2; for_count++) {
|
||||
fptr_ok(fptr_whitelist_serve_expired_lookup(
|
||||
qstate->serve_expired_data->get_cached_answer));
|
||||
msg = (*qstate->serve_expired_data->get_cached_answer)(qstate,
|
||||
lookup_qinfo);
|
||||
if(!msg)
|
||||
lookup_qinfo, &is_expired);
|
||||
if(!msg || (FLAGS_GET_RCODE(msg->rep->flags) != LDNS_RCODE_NOERROR
|
||||
&& FLAGS_GET_RCODE(msg->rep->flags) != LDNS_RCODE_NXDOMAIN
|
||||
&& FLAGS_GET_RCODE(msg->rep->flags) != LDNS_RCODE_YXDOMAIN)) {
|
||||
/* We don't care for cached failure answers at this
|
||||
* stage. */
|
||||
return;
|
||||
}
|
||||
/* Reset these in case we pass a second time from here. */
|
||||
encode_rep = msg->rep;
|
||||
memset(&actinfo, 0, sizeof(actinfo));
|
||||
@@ -2209,7 +2450,8 @@ mesh_serve_expired_callback(void* arg)
|
||||
} else if(partial_rep &&
|
||||
!respip_merge_cname(partial_rep, &qstate->qinfo, msg->rep,
|
||||
qstate->client_info, must_validate, &encode_rep, qstate->region,
|
||||
qstate->env->auth_zones)) {
|
||||
qstate->env->auth_zones, qstate->env->views,
|
||||
qstate->env->respip_set)) {
|
||||
return;
|
||||
}
|
||||
if(!encode_rep || alias_rrset) {
|
||||
@@ -2267,7 +2509,7 @@ mesh_serve_expired_callback(void* arg)
|
||||
http2_stream_remove_mesh_state(r->h2_stream);
|
||||
comm_point_drop_reply(&r->query_reply);
|
||||
mstate->reply_list = reply_list;
|
||||
mstate->s.env->mesh->stats_dropped++;
|
||||
mstate->s.env->mesh->num_queries_discard_timeout++;
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -2285,8 +2527,10 @@ 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) {
|
||||
if(r->edns.edns_present &&
|
||||
qstate->env->cfg->ede_serve_expired &&
|
||||
qstate->env->cfg->ede &&
|
||||
is_expired) {
|
||||
edns_opt_list_append_ede(&r->edns.opt_list_out,
|
||||
mstate->s.region, LDNS_EDE_STALE_ANSWER, NULL);
|
||||
}
|
||||
@@ -2361,3 +2605,25 @@ int mesh_jostle_exceeded(struct mesh_area* mesh)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void mesh_remove_callback(struct mesh_area* mesh, struct query_info* qinfo,
|
||||
uint16_t qflags, mesh_cb_func_type cb, void* cb_arg)
|
||||
{
|
||||
struct mesh_state* s = NULL;
|
||||
s = mesh_area_find(mesh, NULL, qinfo, qflags&(BIT_RD|BIT_CD), 0, 0);
|
||||
if(!s) return;
|
||||
if(!mesh_state_del_cb(s, cb, cb_arg)) return;
|
||||
|
||||
/* It was in the list and removed. */
|
||||
log_assert(mesh->num_reply_addrs > 0);
|
||||
mesh->num_reply_addrs--;
|
||||
if(!s->reply_list && !s->cb_list) {
|
||||
/* was a reply state, not anymore */
|
||||
log_assert(mesh->num_reply_states > 0);
|
||||
mesh->num_reply_states--;
|
||||
}
|
||||
if(!s->reply_list && !s->cb_list &&
|
||||
s->super_set.count == 0) {
|
||||
mesh->num_detached_states++;
|
||||
}
|
||||
}
|
||||
|
||||
+26
-1
@@ -90,6 +90,11 @@ struct mesh_area {
|
||||
/** rbtree of all current queries (mesh_state.node)*/
|
||||
rbtree_type all;
|
||||
|
||||
/** number of queries for unbound's auth_zones, upstream query */
|
||||
size_t num_query_authzone_up;
|
||||
/** number of queries for unbound's auth_zones, downstream answers */
|
||||
size_t num_query_authzone_down;
|
||||
|
||||
/** count of the total number of mesh_reply entries */
|
||||
size_t num_reply_addrs;
|
||||
/** count of the number of mesh_states that have mesh_replies
|
||||
@@ -132,6 +137,12 @@ struct mesh_area {
|
||||
size_t ans_nodata;
|
||||
/** (extended stats) type of applied RPZ action */
|
||||
size_t rpz_action[UB_STATS_RPZ_ACTION_NUM];
|
||||
/** stats, number of queries removed due to discard-timeout */
|
||||
size_t num_queries_discard_timeout;
|
||||
/** stats, number of queries removed due to wait-limit */
|
||||
size_t num_queries_wait_limit;
|
||||
/** stats, number of dns error reports generated */
|
||||
size_t num_dns_error_reports;
|
||||
|
||||
/** backup of query if other operations recurse and need the
|
||||
* network buffers */
|
||||
@@ -673,11 +684,12 @@ void mesh_serve_expired_callback(void* arg);
|
||||
* the same behavior as when replying from cache.
|
||||
* @param qstate: the module qstate.
|
||||
* @param lookup_qinfo: the query info to look for in the cache.
|
||||
* @param is_expired: set if the cached answer is expired.
|
||||
* @return dns_msg if a cached answer was found, otherwise NULL.
|
||||
*/
|
||||
struct dns_msg*
|
||||
mesh_serve_expired_lookup(struct module_qstate* qstate,
|
||||
struct query_info* lookup_qinfo);
|
||||
struct query_info* lookup_qinfo, int* is_expired);
|
||||
|
||||
/**
|
||||
* See if the mesh has space for more queries. You can allocate queries
|
||||
@@ -696,4 +708,17 @@ int mesh_jostle_exceeded(struct mesh_area* mesh);
|
||||
*/
|
||||
void mesh_respond_serve_expired(struct mesh_state* mstate);
|
||||
|
||||
/**
|
||||
* Remove callback from mesh. Removes the callback from the state.
|
||||
* The state itself is left to run. Searches for the pointer values.
|
||||
*
|
||||
* @param mesh: the mesh.
|
||||
* @param qinfo: query from client.
|
||||
* @param qflags: flags from client query.
|
||||
* @param cb: callback function.
|
||||
* @param cb_arg: callback user arg.
|
||||
*/
|
||||
void mesh_remove_callback(struct mesh_area* mesh, struct query_info* qinfo,
|
||||
uint16_t qflags, mesh_cb_func_type cb, void* cb_arg);
|
||||
|
||||
#endif /* SERVICES_MESH_H */
|
||||
|
||||
+1
-1
@@ -265,7 +265,7 @@ modstack_call_init(struct module_stack* stack, const char* module_conf,
|
||||
int i, changed = 0;
|
||||
env->need_to_validate = 0; /* set by module init below */
|
||||
for(i=0; i<stack->num; i++) {
|
||||
while(*module_conf && isspace(*module_conf))
|
||||
while(*module_conf && isspace((unsigned char)*module_conf))
|
||||
module_conf++;
|
||||
if(strncmp(stack->mod[i]->name, module_conf,
|
||||
strlen(stack->mod[i]->name))) {
|
||||
|
||||
@@ -262,12 +262,14 @@ pick_outgoing_tcp(struct pending_tcp* pend, struct waiting_tcp* w, int s)
|
||||
/** 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, int tcp_mss, int dscp)
|
||||
outnet_get_tcp_fd(struct sockaddr_storage* addr, socklen_t addrlen,
|
||||
int tcp_mss, int dscp, int nodelay)
|
||||
{
|
||||
int s;
|
||||
int af;
|
||||
char* err;
|
||||
#if defined(SO_REUSEADDR) || defined(IP_BIND_ADDRESS_NO_PORT)
|
||||
#if defined(SO_REUSEADDR) || defined(IP_BIND_ADDRESS_NO_PORT) \
|
||||
|| defined(TCP_NODELAY)
|
||||
int on = 1;
|
||||
#endif
|
||||
#ifdef INET6
|
||||
@@ -320,6 +322,18 @@ outnet_get_tcp_fd(struct sockaddr_storage* addr, socklen_t addrlen, int tcp_mss,
|
||||
" setsockopt(.. IP_BIND_ADDRESS_NO_PORT ..) failed");
|
||||
}
|
||||
#endif /* IP_BIND_ADDRESS_NO_PORT */
|
||||
if(nodelay) {
|
||||
#if defined(IPPROTO_TCP) && defined(TCP_NODELAY)
|
||||
if(setsockopt(s, IPPROTO_TCP, TCP_NODELAY, (void*)&on,
|
||||
(socklen_t)sizeof(on)) < 0) {
|
||||
verbose(VERB_ALGO, "outgoing tcp:"
|
||||
" setsockopt(.. TCP_NODELAY ..) failed");
|
||||
}
|
||||
#else
|
||||
verbose(VERB_ALGO, "outgoing tcp:"
|
||||
" setsockopt(.. TCP_NODELAY ..) unsupported");
|
||||
#endif /* defined(IPPROTO_TCP) && defined(TCP_NODELAY) */
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
@@ -649,7 +663,8 @@ outnet_tcp_take_into_use(struct waiting_tcp* w)
|
||||
}
|
||||
|
||||
/* open socket */
|
||||
s = outnet_get_tcp_fd(&w->addr, w->addrlen, w->outnet->tcp_mss, w->outnet->ip_dscp);
|
||||
s = outnet_get_tcp_fd(&w->addr, w->addrlen, w->outnet->tcp_mss,
|
||||
w->outnet->ip_dscp, w->ssl_upstream);
|
||||
|
||||
if(s == -1)
|
||||
return 0;
|
||||
@@ -1054,7 +1069,7 @@ reuse_move_writewait_away(struct outside_network* outnet,
|
||||
if(verbosity >= VERB_CLIENT && pend->query->pkt_len > 12+2+2 &&
|
||||
LDNS_QDCOUNT(pend->query->pkt) > 0 &&
|
||||
dname_valid(pend->query->pkt+12, pend->query->pkt_len-12)) {
|
||||
char buf[LDNS_MAX_DOMAINLEN+1];
|
||||
char buf[LDNS_MAX_DOMAINLEN];
|
||||
dname_str(pend->query->pkt+12, buf);
|
||||
verbose(VERB_CLIENT, "reuse_move_writewait_away current %s %d bytes were written",
|
||||
buf, (int)pend->c->tcp_write_byte_count);
|
||||
@@ -1079,7 +1094,7 @@ reuse_move_writewait_away(struct outside_network* outnet,
|
||||
if(verbosity >= VERB_CLIENT && w->pkt_len > 12+2+2 &&
|
||||
LDNS_QDCOUNT(w->pkt) > 0 &&
|
||||
dname_valid(w->pkt+12, w->pkt_len-12)) {
|
||||
char buf[LDNS_MAX_DOMAINLEN+1];
|
||||
char buf[LDNS_MAX_DOMAINLEN];
|
||||
dname_str(w->pkt+12, buf);
|
||||
verbose(VERB_CLIENT, "reuse_move_writewait_away item %s", buf);
|
||||
}
|
||||
@@ -2825,7 +2840,7 @@ serviced_perturb_qname(struct ub_randstate* rnd, uint8_t* qbuf, size_t len)
|
||||
lablen = *d++;
|
||||
}
|
||||
if(verbosity >= VERB_ALGO) {
|
||||
char buf[LDNS_MAX_DOMAINLEN+1];
|
||||
char buf[LDNS_MAX_DOMAINLEN];
|
||||
dname_str(qbuf+10, buf);
|
||||
verbose(VERB_ALGO, "qname perturbed to %s", buf);
|
||||
}
|
||||
@@ -3466,7 +3481,10 @@ outnet_serviced_query(struct outside_network* outnet,
|
||||
timenow = *env->now;
|
||||
if(!infra_ratelimit_inc(env->infra_cache, zone,
|
||||
zonelen, timenow, env->cfg->ratelimit_backoff,
|
||||
&qstate->qinfo, qstate->reply)) {
|
||||
&qstate->qinfo,
|
||||
qstate->mesh_info->reply_list
|
||||
?&qstate->mesh_info->reply_list->query_reply
|
||||
:NULL)) {
|
||||
/* Can we pass through with slip factor? */
|
||||
if(env->cfg->ratelimit_factor == 0 ||
|
||||
ub_random_max(env->rnd,
|
||||
@@ -3715,7 +3733,8 @@ outnet_comm_point_for_tcp(struct outside_network* outnet,
|
||||
sldns_buffer* query, int timeout, int ssl, char* host)
|
||||
{
|
||||
struct comm_point* cp;
|
||||
int fd = outnet_get_tcp_fd(to_addr, to_addrlen, outnet->tcp_mss, outnet->ip_dscp);
|
||||
int fd = outnet_get_tcp_fd(to_addr, to_addrlen, outnet->tcp_mss,
|
||||
outnet->ip_dscp, ssl);
|
||||
if(fd == -1) {
|
||||
return 0;
|
||||
}
|
||||
@@ -3790,7 +3809,8 @@ outnet_comm_point_for_http(struct outside_network* outnet,
|
||||
{
|
||||
/* cp calls cb with err=NETEVENT_DONE when transfer is done */
|
||||
struct comm_point* cp;
|
||||
int fd = outnet_get_tcp_fd(to_addr, to_addrlen, outnet->tcp_mss, outnet->ip_dscp);
|
||||
int fd = outnet_get_tcp_fd(to_addr, to_addrlen, outnet->tcp_mss,
|
||||
outnet->ip_dscp, ssl);
|
||||
if(fd == -1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -743,9 +743,11 @@ void reuse_write_wait_remove(struct reuse_tcp* reuse, struct waiting_tcp* w);
|
||||
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. */
|
||||
* tcp_mss is 0 or maxseg size to set for TCP packets,
|
||||
* nodelay (TCP_NODELAY) should be set for TLS connections to speed up the TLS
|
||||
* handshake.*/
|
||||
int outnet_get_tcp_fd(struct sockaddr_storage* addr, socklen_t addrlen,
|
||||
int tcp_mss, int dscp);
|
||||
int tcp_mss, int dscp, int nodelay);
|
||||
|
||||
/**
|
||||
* Create udp commpoint suitable for sending packets to the destination.
|
||||
|
||||
+73
-13
@@ -242,10 +242,14 @@ rpz_action_to_localzone_type(enum rpz_action a)
|
||||
case RPZ_NODATA_ACTION: return local_zone_always_nodata;
|
||||
case RPZ_DROP_ACTION: return local_zone_always_deny;
|
||||
case RPZ_PASSTHRU_ACTION: return local_zone_always_transparent;
|
||||
case RPZ_LOCAL_DATA_ACTION: /* fallthrough */
|
||||
case RPZ_LOCAL_DATA_ACTION:
|
||||
ATTR_FALLTHROUGH
|
||||
/* fallthrough */
|
||||
case RPZ_CNAME_OVERRIDE_ACTION: return local_zone_redirect;
|
||||
case RPZ_TCP_ONLY_ACTION: return local_zone_truncate;
|
||||
case RPZ_INVALID_ACTION: /* fallthrough */
|
||||
case RPZ_INVALID_ACTION:
|
||||
ATTR_FALLTHROUGH
|
||||
/* fallthrough */
|
||||
default: return local_zone_invalid;
|
||||
}
|
||||
}
|
||||
@@ -258,10 +262,14 @@ rpz_action_to_respip_action(enum rpz_action a)
|
||||
case RPZ_NODATA_ACTION: return respip_always_nodata;
|
||||
case RPZ_DROP_ACTION: return respip_always_deny;
|
||||
case RPZ_PASSTHRU_ACTION: return respip_always_transparent;
|
||||
case RPZ_LOCAL_DATA_ACTION: /* fallthrough */
|
||||
case RPZ_LOCAL_DATA_ACTION:
|
||||
ATTR_FALLTHROUGH
|
||||
/* fallthrough */
|
||||
case RPZ_CNAME_OVERRIDE_ACTION: return respip_redirect;
|
||||
case RPZ_TCP_ONLY_ACTION: return respip_truncate;
|
||||
case RPZ_INVALID_ACTION: /* fallthrough */
|
||||
case RPZ_INVALID_ACTION:
|
||||
ATTR_FALLTHROUGH
|
||||
/* fallthrough */
|
||||
default: return respip_invalid;
|
||||
}
|
||||
}
|
||||
@@ -276,7 +284,9 @@ localzone_type_to_rpz_action(enum localzone_type lzt)
|
||||
case local_zone_always_transparent: return RPZ_PASSTHRU_ACTION;
|
||||
case local_zone_redirect: return RPZ_LOCAL_DATA_ACTION;
|
||||
case local_zone_truncate: return RPZ_TCP_ONLY_ACTION;
|
||||
case local_zone_invalid: /* fallthrough */
|
||||
case local_zone_invalid:
|
||||
ATTR_FALLTHROUGH
|
||||
/* fallthrough */
|
||||
default: return RPZ_INVALID_ACTION;
|
||||
}
|
||||
}
|
||||
@@ -291,7 +301,9 @@ respip_action_to_rpz_action(enum respip_action a)
|
||||
case respip_always_transparent: return RPZ_PASSTHRU_ACTION;
|
||||
case respip_redirect: return RPZ_LOCAL_DATA_ACTION;
|
||||
case respip_truncate: return RPZ_TCP_ONLY_ACTION;
|
||||
case respip_invalid: /* fallthrough */
|
||||
case respip_invalid:
|
||||
ATTR_FALLTHROUGH
|
||||
/* fallthrough */
|
||||
default: return RPZ_INVALID_ACTION;
|
||||
}
|
||||
}
|
||||
@@ -654,7 +666,7 @@ rpz_insert_local_zones_trigger(struct local_zones* lz, uint8_t* dname,
|
||||
int newzone = 0;
|
||||
|
||||
if(a == RPZ_INVALID_ACTION) {
|
||||
char str[255+1];
|
||||
char str[LDNS_MAX_DOMAINLEN];
|
||||
if(rrtype == LDNS_RR_TYPE_SOA || rrtype == LDNS_RR_TYPE_NS ||
|
||||
rrtype == LDNS_RR_TYPE_DNAME ||
|
||||
rrtype == LDNS_RR_TYPE_DNSKEY ||
|
||||
@@ -727,7 +739,7 @@ rpz_insert_local_zones_trigger(struct local_zones* lz, uint8_t* dname,
|
||||
static void
|
||||
rpz_log_dname(char const* msg, uint8_t* dname, size_t dname_len)
|
||||
{
|
||||
char buf[LDNS_MAX_DOMAINLEN+1];
|
||||
char buf[LDNS_MAX_DOMAINLEN];
|
||||
(void)dname_len;
|
||||
dname_str(dname, buf);
|
||||
verbose(VERB_ALGO, "rpz: %s: <%s>", msg, buf);
|
||||
@@ -1050,7 +1062,7 @@ rpz_insert_response_ip_trigger(struct rpz* r, uint8_t* dname, size_t dnamelen,
|
||||
|
||||
if(a == RPZ_INVALID_ACTION ||
|
||||
rpz_action_to_respip_action(a) == respip_invalid) {
|
||||
char str[255+1];
|
||||
char str[LDNS_MAX_DOMAINLEN];
|
||||
dname_str(dname, str);
|
||||
verbose(VERB_ALGO, "rpz: respip trigger, %s skipping unsupported action: %s",
|
||||
str, rpz_action_to_string(a));
|
||||
@@ -1621,7 +1633,7 @@ log_rpz_apply(char* trigger, uint8_t* dname, struct addr_tree_node* addrnode,
|
||||
struct comm_reply* repinfo, struct module_qstate* ms, char* log_name)
|
||||
{
|
||||
char ip[128], txt[512], portstr[32];
|
||||
char dnamestr[LDNS_MAX_DOMAINLEN+1];
|
||||
char dnamestr[LDNS_MAX_DOMAINLEN];
|
||||
uint16_t port = 0;
|
||||
if(dname) {
|
||||
dname_str(dname, dnamestr);
|
||||
@@ -1957,6 +1969,7 @@ rpz_synthesize_nodata(struct rpz* ATTR_UNUSED(r), struct module_qstate* ms,
|
||||
0, /* ttl */
|
||||
0, /* prettl */
|
||||
0, /* expttl */
|
||||
0, /* norecttl */
|
||||
0, /* an */
|
||||
0, /* ns */
|
||||
0, /* ar */
|
||||
@@ -1987,6 +2000,7 @@ rpz_synthesize_nxdomain(struct rpz* r, struct module_qstate* ms,
|
||||
0, /* ttl */
|
||||
0, /* prettl */
|
||||
0, /* expttl */
|
||||
0, /* norecttl */
|
||||
0, /* an */
|
||||
0, /* ns */
|
||||
0, /* ar */
|
||||
@@ -2019,6 +2033,7 @@ rpz_synthesize_localdata_from_rrset(struct rpz* ATTR_UNUSED(r), struct module_qs
|
||||
0, /* ttl */
|
||||
0, /* prettl */
|
||||
0, /* expttl */
|
||||
0, /* norecttl */
|
||||
1, /* an */
|
||||
0, /* ns */
|
||||
0, /* ar */
|
||||
@@ -2164,6 +2179,7 @@ rpz_synthesize_cname_override_msg(struct rpz* r, struct module_qstate* ms,
|
||||
0, /* ttl */
|
||||
0, /* prettl */
|
||||
0, /* expttl */
|
||||
0, /* norecttl */
|
||||
1, /* an */
|
||||
0, /* ns */
|
||||
0, /* ar */
|
||||
@@ -2276,15 +2292,18 @@ rpz_apply_nsip_trigger(struct module_qstate* ms, struct query_info* qchase,
|
||||
if(action == RPZ_LOCAL_DATA_ACTION && raddr->data == NULL) {
|
||||
verbose(VERB_ALGO, "rpz: bug: nsip local data action but no local data");
|
||||
ret = rpz_synthesize_nodata(r, ms, qchase, az);
|
||||
ms->rpz_applied = 1;
|
||||
goto done;
|
||||
}
|
||||
|
||||
switch(action) {
|
||||
case RPZ_NXDOMAIN_ACTION:
|
||||
ret = rpz_synthesize_nxdomain(r, ms, qchase, az);
|
||||
ms->rpz_applied = 1;
|
||||
break;
|
||||
case RPZ_NODATA_ACTION:
|
||||
ret = rpz_synthesize_nodata(r, ms, qchase, az);
|
||||
ms->rpz_applied = 1;
|
||||
break;
|
||||
case RPZ_TCP_ONLY_ACTION:
|
||||
/* basically a passthru here but the tcp-only will be
|
||||
@@ -2294,11 +2313,13 @@ rpz_apply_nsip_trigger(struct module_qstate* ms, struct query_info* qchase,
|
||||
break;
|
||||
case RPZ_DROP_ACTION:
|
||||
ret = rpz_synthesize_nodata(r, ms, qchase, az);
|
||||
ms->rpz_applied = 1;
|
||||
ms->is_drop = 1;
|
||||
break;
|
||||
case RPZ_LOCAL_DATA_ACTION:
|
||||
ret = rpz_synthesize_nsip_localdata(r, ms, qchase, raddr, az);
|
||||
if(ret == NULL) { ret = rpz_synthesize_nodata(r, ms, qchase, az); }
|
||||
ms->rpz_applied = 1;
|
||||
break;
|
||||
case RPZ_PASSTHRU_ACTION:
|
||||
ret = NULL;
|
||||
@@ -2306,6 +2327,7 @@ rpz_apply_nsip_trigger(struct module_qstate* ms, struct query_info* qchase,
|
||||
break;
|
||||
case RPZ_CNAME_OVERRIDE_ACTION:
|
||||
ret = rpz_synthesize_cname_override_msg(r, ms, qchase);
|
||||
ms->rpz_applied = 1;
|
||||
break;
|
||||
default:
|
||||
verbose(VERB_ALGO, "rpz: nsip: bug: unhandled or invalid action: '%s'",
|
||||
@@ -2340,9 +2362,11 @@ rpz_apply_nsdname_trigger(struct module_qstate* ms, struct query_info* qchase,
|
||||
switch(action) {
|
||||
case RPZ_NXDOMAIN_ACTION:
|
||||
ret = rpz_synthesize_nxdomain(r, ms, qchase, az);
|
||||
ms->rpz_applied = 1;
|
||||
break;
|
||||
case RPZ_NODATA_ACTION:
|
||||
ret = rpz_synthesize_nodata(r, ms, qchase, az);
|
||||
ms->rpz_applied = 1;
|
||||
break;
|
||||
case RPZ_TCP_ONLY_ACTION:
|
||||
/* basically a passthru here but the tcp-only will be
|
||||
@@ -2352,11 +2376,13 @@ rpz_apply_nsdname_trigger(struct module_qstate* ms, struct query_info* qchase,
|
||||
break;
|
||||
case RPZ_DROP_ACTION:
|
||||
ret = rpz_synthesize_nodata(r, ms, qchase, az);
|
||||
ms->rpz_applied = 1;
|
||||
ms->is_drop = 1;
|
||||
break;
|
||||
case RPZ_LOCAL_DATA_ACTION:
|
||||
ret = rpz_synthesize_nsdname_localdata(r, ms, qchase, z, match, az);
|
||||
if(ret == NULL) { ret = rpz_synthesize_nodata(r, ms, qchase, az); }
|
||||
ms->rpz_applied = 1;
|
||||
break;
|
||||
case RPZ_PASSTHRU_ACTION:
|
||||
ret = NULL;
|
||||
@@ -2364,6 +2390,7 @@ rpz_apply_nsdname_trigger(struct module_qstate* ms, struct query_info* qchase,
|
||||
break;
|
||||
case RPZ_CNAME_OVERRIDE_ACTION:
|
||||
ret = rpz_synthesize_cname_override_msg(r, ms, qchase);
|
||||
ms->rpz_applied = 1;
|
||||
break;
|
||||
default:
|
||||
verbose(VERB_ALGO, "rpz: nsdname: bug: unhandled or invalid action: '%s'",
|
||||
@@ -2400,7 +2427,8 @@ rpz_delegation_point_zone_lookup(struct delegpt* dp, struct local_zones* zones,
|
||||
match->dname = nameserver->name;
|
||||
match->dname_len = nameserver->namelen;
|
||||
if(verbosity >= VERB_ALGO) {
|
||||
char nm[255+1], zn[255+1];
|
||||
char nm[LDNS_MAX_DOMAINLEN];
|
||||
char zn[LDNS_MAX_DOMAINLEN];
|
||||
dname_str(match->dname, nm);
|
||||
dname_str(z->name, zn);
|
||||
if(strcmp(nm, zn) != 0)
|
||||
@@ -2554,7 +2582,7 @@ struct dns_msg* rpz_callback_from_iterator_cname(struct module_qstate* ms,
|
||||
}
|
||||
|
||||
if(verbosity >= VERB_ALGO) {
|
||||
char nm[255+1], zn[255+1];
|
||||
char nm[LDNS_MAX_DOMAINLEN], zn[LDNS_MAX_DOMAINLEN];
|
||||
dname_str(is->qchase.qname, nm);
|
||||
dname_str(z->name, zn);
|
||||
if(strcmp(zn, nm) != 0)
|
||||
@@ -2567,9 +2595,11 @@ struct dns_msg* rpz_callback_from_iterator_cname(struct module_qstate* ms,
|
||||
switch(localzone_type_to_rpz_action(lzt)) {
|
||||
case RPZ_NXDOMAIN_ACTION:
|
||||
ret = rpz_synthesize_nxdomain(r, ms, &is->qchase, a);
|
||||
ms->rpz_applied = 1;
|
||||
break;
|
||||
case RPZ_NODATA_ACTION:
|
||||
ret = rpz_synthesize_nodata(r, ms, &is->qchase, a);
|
||||
ms->rpz_applied = 1;
|
||||
break;
|
||||
case RPZ_TCP_ONLY_ACTION:
|
||||
/* basically a passthru here but the tcp-only will be
|
||||
@@ -2579,11 +2609,13 @@ struct dns_msg* rpz_callback_from_iterator_cname(struct module_qstate* ms,
|
||||
break;
|
||||
case RPZ_DROP_ACTION:
|
||||
ret = rpz_synthesize_nodata(r, ms, &is->qchase, a);
|
||||
ms->rpz_applied = 1;
|
||||
ms->is_drop = 1;
|
||||
break;
|
||||
case RPZ_LOCAL_DATA_ACTION:
|
||||
ret = rpz_synthesize_qname_localdata_msg(r, ms, &is->qchase, z, a);
|
||||
if(ret == NULL) { ret = rpz_synthesize_nodata(r, ms, &is->qchase, a); }
|
||||
ms->rpz_applied = 1;
|
||||
break;
|
||||
case RPZ_PASSTHRU_ACTION:
|
||||
ret = NULL;
|
||||
@@ -2727,7 +2759,7 @@ rpz_callback_from_worker_request(struct auth_zones* az, struct module_env* env,
|
||||
}
|
||||
|
||||
if(verbosity >= VERB_ALGO) {
|
||||
char nm[255+1], zn[255+1];
|
||||
char nm[LDNS_MAX_DOMAINLEN], zn[LDNS_MAX_DOMAINLEN];
|
||||
dname_str(qinfo->qname, nm);
|
||||
dname_str(z->name, zn);
|
||||
if(strcmp(zn, nm) != 0)
|
||||
@@ -2760,3 +2792,31 @@ void rpz_disable(struct rpz* r)
|
||||
return;
|
||||
r->disabled = 1;
|
||||
}
|
||||
|
||||
/** Get memory usage for clientip_synthesized_rrset. Ignores memory usage
|
||||
* of locks. */
|
||||
static size_t
|
||||
rpz_clientip_synthesized_set_get_mem(struct clientip_synthesized_rrset* set)
|
||||
{
|
||||
size_t m = sizeof(*set);
|
||||
lock_rw_rdlock(&set->lock);
|
||||
m += regional_get_mem(set->region);
|
||||
lock_rw_unlock(&set->lock);
|
||||
return m;
|
||||
}
|
||||
|
||||
size_t rpz_get_mem(struct rpz* r)
|
||||
{
|
||||
size_t m = sizeof(*r);
|
||||
if(r->taglist)
|
||||
m += r->taglistlen;
|
||||
if(r->log_name)
|
||||
m += strlen(r->log_name) + 1;
|
||||
m += regional_get_mem(r->region);
|
||||
m += local_zones_get_mem(r->local_zones);
|
||||
m += local_zones_get_mem(r->nsdname_zones);
|
||||
m += respip_set_get_mem(r->respip_set);
|
||||
m += rpz_clientip_synthesized_set_get_mem(r->client_set);
|
||||
m += rpz_clientip_synthesized_set_get_mem(r->ns_set);
|
||||
return m;
|
||||
}
|
||||
|
||||
@@ -269,4 +269,11 @@ void rpz_enable(struct rpz* r);
|
||||
*/
|
||||
void rpz_disable(struct rpz* r);
|
||||
|
||||
/**
|
||||
* Get memory usage of rpz. Caller must manage locks.
|
||||
* @param r: RPZ struct.
|
||||
* @return memory usage.
|
||||
*/
|
||||
size_t rpz_get_mem(struct rpz* r);
|
||||
|
||||
#endif /* SERVICES_RPZ_H */
|
||||
|
||||
+36
-5
@@ -43,6 +43,7 @@
|
||||
#include "services/view.h"
|
||||
#include "services/localzone.h"
|
||||
#include "util/config_file.h"
|
||||
#include "respip/respip.h"
|
||||
|
||||
int
|
||||
view_cmp(const void* v1, const void* v2)
|
||||
@@ -66,11 +67,6 @@ views_create(void)
|
||||
return v;
|
||||
}
|
||||
|
||||
/* \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
|
||||
view_delete(struct view* v)
|
||||
{
|
||||
@@ -247,3 +243,38 @@ void views_print(struct views* v)
|
||||
/* TODO implement print */
|
||||
(void)v;
|
||||
}
|
||||
|
||||
size_t views_get_mem(struct views* vs)
|
||||
{
|
||||
struct view* v;
|
||||
size_t m;
|
||||
if(!vs) return 0;
|
||||
m = sizeof(struct views);
|
||||
lock_rw_rdlock(&vs->lock);
|
||||
RBTREE_FOR(v, struct view*, &vs->vtree) {
|
||||
m += view_get_mem(v);
|
||||
}
|
||||
lock_rw_unlock(&vs->lock);
|
||||
return m;
|
||||
}
|
||||
|
||||
size_t view_get_mem(struct view* v)
|
||||
{
|
||||
size_t m = sizeof(*v);
|
||||
lock_rw_rdlock(&v->lock);
|
||||
m += getmem_str(v->name);
|
||||
m += local_zones_get_mem(v->local_zones);
|
||||
m += respip_set_get_mem(v->respip_set);
|
||||
lock_rw_unlock(&v->lock);
|
||||
return m;
|
||||
}
|
||||
|
||||
void views_swap_tree(struct views* vs, struct views* data)
|
||||
{
|
||||
rbnode_type* oldroot = vs->vtree.root;
|
||||
size_t oldcount = vs->vtree.count;
|
||||
vs->vtree.root = data->vtree.root;
|
||||
vs->vtree.count = data->vtree.count;
|
||||
data->vtree.root = oldroot;
|
||||
data->vtree.count = oldcount;
|
||||
}
|
||||
|
||||
+25
-1
@@ -54,7 +54,8 @@ struct respip_set;
|
||||
* Views storage, shared.
|
||||
*/
|
||||
struct views {
|
||||
/** lock on the view tree */
|
||||
/** lock on the view tree. When locking order, the views lock
|
||||
* is before the forwards,hints,anchors,localzones lock. */
|
||||
lock_rw_type lock;
|
||||
/** rbtree of struct view */
|
||||
rbtree_type vtree;
|
||||
@@ -135,4 +136,27 @@ void views_print(struct views* v);
|
||||
*/
|
||||
struct view* views_find_view(struct views* vs, const char* name, int write);
|
||||
|
||||
/**
|
||||
* Calculate memory usage of views.
|
||||
* @param vs: the views tree. The routine locks and unlocks the structure
|
||||
* for reading.
|
||||
* @return memory in bytes.
|
||||
*/
|
||||
size_t views_get_mem(struct views* vs);
|
||||
|
||||
/**
|
||||
* Calculate memory usage of view.
|
||||
* @param v: the view. The routine locks and unlocks the structure for reading.
|
||||
* @return memory in bytes.
|
||||
*/
|
||||
size_t view_get_mem(struct view* v);
|
||||
|
||||
/**
|
||||
* Swap internal tree with preallocated entries. Caller should manage
|
||||
* the locks.
|
||||
* @param vs: views tree
|
||||
* @param data: preallocated information.
|
||||
*/
|
||||
void views_swap_tree(struct views* vs, struct views* data);
|
||||
|
||||
#endif /* SERVICES_VIEW_H */
|
||||
|
||||
@@ -195,6 +195,7 @@ void sldns_key_EVP_unload_gost(void)
|
||||
}
|
||||
#endif /* USE_GOST */
|
||||
|
||||
#ifdef USE_DSA
|
||||
/* Retrieve params as BIGNUM from raw buffer */
|
||||
static int
|
||||
sldns_key_dsa_buf_bignum(unsigned char* key, size_t len, BIGNUM** p,
|
||||
@@ -370,6 +371,7 @@ EVP_PKEY *sldns_key_dsa2pkey_raw(unsigned char* key, size_t len)
|
||||
return evp_key;
|
||||
#endif
|
||||
}
|
||||
#endif /* USE_DSA */
|
||||
|
||||
/* Retrieve params as BIGNUM from raw buffer, n is modulus, e is exponent */
|
||||
static int
|
||||
|
||||
@@ -436,11 +436,13 @@ sldns_b32_ntop_base(const uint8_t* src, size_t src_sz, char* dst, size_t dst_sz,
|
||||
|
||||
/* ........ ........ ....4444 4....... ........ */
|
||||
c = src[3] >> 7 ;
|
||||
ATTR_FALLTHROUGH
|
||||
/* fallthrough */
|
||||
case 3: dst[4] = b32[(src[2] & 0x0f) << 1 | c];
|
||||
|
||||
/* ........ .......3 3333.... ........ ........ */
|
||||
c = src[2] >> 4 ;
|
||||
ATTR_FALLTHROUGH
|
||||
/* fallthrough */
|
||||
case 2: dst[3] = b32[(src[1] & 0x01) << 4 | c];
|
||||
|
||||
@@ -449,6 +451,7 @@ sldns_b32_ntop_base(const uint8_t* src, size_t src_sz, char* dst, size_t dst_sz,
|
||||
|
||||
/* .....111 11...... ........ ........ ........ */
|
||||
c = src[1] >> 6 ;
|
||||
ATTR_FALLTHROUGH
|
||||
/* fallthrough */
|
||||
case 1: dst[1] = b32[(src[0] & 0x07) << 2 | c];
|
||||
|
||||
@@ -460,11 +463,14 @@ sldns_b32_ntop_base(const uint8_t* src, size_t src_sz, char* dst, size_t dst_sz,
|
||||
switch (src_sz) {
|
||||
case 1: dst[2] = '=';
|
||||
dst[3] = '=';
|
||||
ATTR_FALLTHROUGH
|
||||
/* fallthrough */
|
||||
case 2: dst[4] = '=';
|
||||
ATTR_FALLTHROUGH
|
||||
/* fallthrough */
|
||||
case 3: dst[5] = '=';
|
||||
dst[6] = '=';
|
||||
ATTR_FALLTHROUGH
|
||||
/* fallthrough */
|
||||
case 4: dst[7] = '=';
|
||||
}
|
||||
@@ -577,17 +583,20 @@ sldns_b32_pton_base(const char* src, size_t src_sz, uint8_t* dst, size_t dst_sz,
|
||||
/* ........ ........ ........ .55555.. ........ */
|
||||
/* ........ ........ ....4444 4....... ........ */
|
||||
dst[3] = buf[4] << 7 | buf[5] << 2 | buf[6] >> 3;
|
||||
ATTR_FALLTHROUGH
|
||||
/* fallthrough */
|
||||
|
||||
case 5: /* ........ ........ ....4444 4....... ........ */
|
||||
/* ........ .......3 3333.... ........ ........ */
|
||||
dst[2] = buf[3] << 4 | buf[4] >> 1;
|
||||
ATTR_FALLTHROUGH
|
||||
/* fallthrough */
|
||||
|
||||
case 4: /* ........ .......3 3333.... ........ ........ */
|
||||
/* ........ ..22222. ........ ........ ........ */
|
||||
/* .....111 11...... ........ ........ ........ */
|
||||
dst[1] = buf[1] << 6 | buf[2] << 1 | buf[3] >> 4;
|
||||
ATTR_FALLTHROUGH
|
||||
/* fallthrough */
|
||||
|
||||
case 2: /* .....111 11...... ........ ........ ........ */
|
||||
|
||||
+8
-2
@@ -72,7 +72,7 @@ static const sldns_rdf_type type_nsap_wireformat[] = {
|
||||
LDNS_RDF_TYPE_NSAP
|
||||
};
|
||||
static const sldns_rdf_type type_nsap_ptr_wireformat[] = {
|
||||
LDNS_RDF_TYPE_STR
|
||||
LDNS_RDF_TYPE_UNQUOTED
|
||||
};
|
||||
static const sldns_rdf_type type_sig_wireformat[] = {
|
||||
LDNS_RDF_TYPE_TYPE, LDNS_RDF_TYPE_ALG, LDNS_RDF_TYPE_INT8, LDNS_RDF_TYPE_INT32,
|
||||
@@ -86,7 +86,7 @@ static const sldns_rdf_type type_px_wireformat[] = {
|
||||
LDNS_RDF_TYPE_INT16, LDNS_RDF_TYPE_DNAME, LDNS_RDF_TYPE_DNAME
|
||||
};
|
||||
static const sldns_rdf_type type_gpos_wireformat[] = {
|
||||
LDNS_RDF_TYPE_STR, LDNS_RDF_TYPE_STR, LDNS_RDF_TYPE_STR
|
||||
LDNS_RDF_TYPE_UNQUOTED, LDNS_RDF_TYPE_UNQUOTED, LDNS_RDF_TYPE_UNQUOTED
|
||||
};
|
||||
static const sldns_rdf_type type_aaaa_wireformat[] = { LDNS_RDF_TYPE_AAAA };
|
||||
static const sldns_rdf_type type_loc_wireformat[] = { LDNS_RDF_TYPE_LOC };
|
||||
@@ -617,6 +617,12 @@ static sldns_rr_descriptor rdata_field_descriptors[] = {
|
||||
{(enum sldns_enum_rr_type)0, "TYPE258", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
|
||||
#endif
|
||||
|
||||
{(enum sldns_enum_rr_type)0, "TYPE259", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
|
||||
{(enum sldns_enum_rr_type)0, "TYPE260", 1, 1, type_0_wireformat, LDNS_RDF_TYPE_NONE, LDNS_RR_NO_COMPRESS, 0 },
|
||||
|
||||
/* 261 */
|
||||
{LDNS_RR_TYPE_RESINFO, "RESINFO", 1, 0, NULL, LDNS_RDF_TYPE_UNQUOTED, LDNS_RR_NO_COMPRESS, 0 },
|
||||
|
||||
/* split in array, no longer contiguous */
|
||||
|
||||
#ifdef DRAFT_RRTYPES
|
||||
|
||||
@@ -229,6 +229,8 @@ enum sldns_enum_rr_type
|
||||
LDNS_RR_TYPE_CAA = 257, /* RFC 6844 */
|
||||
LDNS_RR_TYPE_AVC = 258,
|
||||
|
||||
LDNS_RR_TYPE_RESINFO = 261, /* RFC 9606 */
|
||||
|
||||
/** DNSSEC Trust Authorities */
|
||||
LDNS_RR_TYPE_TA = 32768,
|
||||
/* RFC 4431, 5074, DNSSEC Lookaside Validation */
|
||||
@@ -341,6 +343,9 @@ enum sldns_enum_rdf_type
|
||||
/** 8 * 8 bit hex numbers separated by dashes. For EUI64. */
|
||||
LDNS_RDF_TYPE_EUI64,
|
||||
|
||||
/** Character string without quotes. */
|
||||
LDNS_RDF_TYPE_UNQUOTED,
|
||||
|
||||
/** A non-zero sequence of US-ASCII letters and numbers in lower case.
|
||||
* For CAA.
|
||||
*/
|
||||
@@ -438,6 +443,7 @@ enum sldns_enum_edns_option
|
||||
LDNS_EDNS_PADDING = 12, /* RFC7830 */
|
||||
LDNS_EDNS_EDE = 15, /* RFC8914 */
|
||||
LDNS_EDNS_CLIENT_TAG = 16, /* draft-bellis-dnsop-edns-tags-01 */
|
||||
LDNS_EDNS_REPORT_CHANNEL = 18, /* RFC9567 */
|
||||
LDNS_EDNS_UNBOUND_CACHEDB_TESTFRAME_TEST = 65534
|
||||
};
|
||||
typedef enum sldns_enum_edns_option sldns_edns_option;
|
||||
|
||||
+46
-8
@@ -365,7 +365,8 @@ static int
|
||||
sldns_rdf_type_maybe_quoted(sldns_rdf_type rdf_type)
|
||||
{
|
||||
return rdf_type == LDNS_RDF_TYPE_STR ||
|
||||
rdf_type == LDNS_RDF_TYPE_LONG_STR;
|
||||
rdf_type == LDNS_RDF_TYPE_LONG_STR ||
|
||||
rdf_type == LDNS_RDF_TYPE_UNQUOTED;
|
||||
}
|
||||
|
||||
/** see if rdata is quoted */
|
||||
@@ -1719,6 +1720,8 @@ int sldns_str2wire_rdf_buf(const char* str, uint8_t* rd, size_t* len,
|
||||
return sldns_str2wire_eui48_buf(str, rd, len);
|
||||
case LDNS_RDF_TYPE_EUI64:
|
||||
return sldns_str2wire_eui64_buf(str, rd, len);
|
||||
case LDNS_RDF_TYPE_UNQUOTED:
|
||||
return sldns_str2wire_unquoted_buf(str, rd, len);
|
||||
case LDNS_RDF_TYPE_TAG:
|
||||
return sldns_str2wire_tag_buf(str, rd, len);
|
||||
case LDNS_RDF_TYPE_LONG_STR:
|
||||
@@ -2554,12 +2557,42 @@ int sldns_str2wire_atma_buf(const char* str, uint8_t* rd, size_t* len)
|
||||
{
|
||||
const char* s = str;
|
||||
size_t slen = strlen(str);
|
||||
size_t dlen = 0; /* number of hexdigits parsed */
|
||||
size_t dlen = 0; /* number of hexdigits parsed for hex,
|
||||
digits for E.164 */
|
||||
|
||||
/* just a hex string with optional dots? */
|
||||
/* notimpl e.164 format */
|
||||
if(slen > LDNS_MAX_RDFLEN*2)
|
||||
return LDNS_WIREPARSE_ERR_LABEL_OVERFLOW;
|
||||
if(*len < 1)
|
||||
return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL;
|
||||
if(*s == 0) {
|
||||
/* empty string */
|
||||
rd[0] = 0;
|
||||
*len = 1;
|
||||
return LDNS_WIREPARSE_ERR_OK;
|
||||
}
|
||||
if(s[0] == '+') {
|
||||
rd[0] = 1; /* E.164 format */
|
||||
/* digits '0'..'9', with skipped dots. */
|
||||
s++;
|
||||
while(*s) {
|
||||
if(isspace((unsigned char)*s) || *s == '.') {
|
||||
s++;
|
||||
continue;
|
||||
}
|
||||
if(*s < '0' || *s > '9')
|
||||
return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX, s-str);
|
||||
if(*len < dlen + 2)
|
||||
return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL,
|
||||
s-str);
|
||||
rd[dlen+1] = *s++;
|
||||
dlen++;
|
||||
}
|
||||
*len = dlen+1;
|
||||
return LDNS_WIREPARSE_ERR_OK;
|
||||
}
|
||||
|
||||
rd[0] = 0; /* AESA format */
|
||||
/* hex, with skipped dots. */
|
||||
while(*s) {
|
||||
if(isspace((unsigned char)*s) || *s == '.') {
|
||||
s++;
|
||||
@@ -2567,17 +2600,17 @@ int sldns_str2wire_atma_buf(const char* str, uint8_t* rd, size_t* len)
|
||||
}
|
||||
if(!isxdigit((unsigned char)*s))
|
||||
return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_HEX, s-str);
|
||||
if(*len < dlen/2 + 1)
|
||||
if(*len < dlen/2 + 2)
|
||||
return RET_ERR(LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL,
|
||||
s-str);
|
||||
if((dlen&1)==0)
|
||||
rd[dlen/2] = (uint8_t)sldns_hexdigit_to_int(*s++) * 16;
|
||||
else rd[dlen/2] += sldns_hexdigit_to_int(*s++);
|
||||
rd[dlen/2 + 1] = (uint8_t)sldns_hexdigit_to_int(*s++) * 16;
|
||||
else rd[dlen/2 + 1] += sldns_hexdigit_to_int(*s++);
|
||||
dlen++;
|
||||
}
|
||||
if((dlen&1)!=0)
|
||||
return RET_ERR(LDNS_WIREPARSE_ERR_SYNTAX_HEX, s-str);
|
||||
*len = dlen/2;
|
||||
*len = dlen/2 + 1;
|
||||
return LDNS_WIREPARSE_ERR_OK;
|
||||
}
|
||||
|
||||
@@ -2746,6 +2779,11 @@ int sldns_str2wire_eui64_buf(const char* str, uint8_t* rd, size_t* len)
|
||||
return LDNS_WIREPARSE_ERR_OK;
|
||||
}
|
||||
|
||||
int sldns_str2wire_unquoted_buf(const char* str, uint8_t* rd, size_t* len)
|
||||
{
|
||||
return sldns_str2wire_str_buf(str, rd, len);
|
||||
}
|
||||
|
||||
int sldns_str2wire_tag_buf(const char* str, uint8_t* rd, size_t* len)
|
||||
{
|
||||
size_t slen = strlen(str);
|
||||
|
||||
@@ -551,6 +551,15 @@ int sldns_str2wire_eui48_buf(const char* str, uint8_t* rd, size_t* len);
|
||||
*/
|
||||
int sldns_str2wire_eui64_buf(const char* str, uint8_t* rd, size_t* len);
|
||||
|
||||
/**
|
||||
* Convert rdf of type LDNS_RDF_TYPE_UNQUOTED from string to wireformat.
|
||||
* @param str: the text to convert for this rdata element.
|
||||
* @param rd: rdata buffer for the wireformat.
|
||||
* @param len: length of rd buffer on input, used length on output.
|
||||
* @return 0 on success, error on failure.
|
||||
*/
|
||||
int sldns_str2wire_unquoted_buf(const char* str, uint8_t* rd, size_t* len);
|
||||
|
||||
/**
|
||||
* Convert rdf of type LDNS_RDF_TYPE_TAG from string to wireformat.
|
||||
* @param str: the text to convert for this rdata element.
|
||||
|
||||
+50
-1
@@ -1241,6 +1241,7 @@ int sldns_wire2str_svcparam_scan(uint8_t** d, size_t* dlen, char** s, size_t* sl
|
||||
r = sldns_wire2str_svcparam_ech2str(s, slen, data_len, *d);
|
||||
break;
|
||||
case SVCB_KEY_DOHPATH:
|
||||
ATTR_FALLTHROUGH
|
||||
/* fallthrough */
|
||||
default:
|
||||
r = sldns_str_print(s, slen, "=\"");
|
||||
@@ -1343,6 +1344,8 @@ int sldns_wire2str_rdf_scan(uint8_t** d, size_t* dlen, char** s, size_t* slen,
|
||||
return sldns_wire2str_eui48_scan(d, dlen, s, slen);
|
||||
case LDNS_RDF_TYPE_EUI64:
|
||||
return sldns_wire2str_eui64_scan(d, dlen, s, slen);
|
||||
case LDNS_RDF_TYPE_UNQUOTED:
|
||||
return sldns_wire2str_unquoted_scan(d, dlen, s, slen);
|
||||
case LDNS_RDF_TYPE_TAG:
|
||||
return sldns_wire2str_tag_scan(d, dlen, s, slen);
|
||||
case LDNS_RDF_TYPE_LONG_STR:
|
||||
@@ -1869,7 +1872,33 @@ int sldns_wire2str_nsap_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
|
||||
|
||||
int sldns_wire2str_atma_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
|
||||
{
|
||||
return print_remainder_hex("", d, dl, s, sl);
|
||||
uint8_t format;
|
||||
int w = 0;
|
||||
size_t i;
|
||||
|
||||
if(*dl < 1) return -1;
|
||||
format = (*d)[0];
|
||||
(*d)+=1;
|
||||
(*dl)-=1;
|
||||
|
||||
if(format == 0) {
|
||||
/* AESA format (ATM End System Address). */
|
||||
return print_remainder_hex("", d, dl, s, sl);
|
||||
} else if(format == 1) {
|
||||
/* E.164 format. */
|
||||
w += sldns_str_print(s, sl, "+");
|
||||
for(i=0; i<*dl; i++) {
|
||||
if((*d)[i] < '0' || (*d)[0] > '9')
|
||||
return -1;
|
||||
w += sldns_str_print(s, sl, "%c", (*d)[i]);
|
||||
}
|
||||
(*d) += *dl;
|
||||
(*dl) = 0;
|
||||
} else {
|
||||
/* Unknown format. */
|
||||
return -1;
|
||||
}
|
||||
return w;
|
||||
}
|
||||
|
||||
/* internal scan routine that can modify arguments on failure */
|
||||
@@ -2020,6 +2049,26 @@ int sldns_wire2str_eui64_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
|
||||
return w;
|
||||
}
|
||||
|
||||
int sldns_wire2str_unquoted_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
|
||||
{
|
||||
int w = 0;
|
||||
size_t i, len;
|
||||
if(*dl < 1) return -1;
|
||||
len = **d;
|
||||
if(*dl < 1+len) return -1;
|
||||
(*d)++;
|
||||
(*dl)--;
|
||||
for(i=0; i<len; i++) {
|
||||
if(isspace((unsigned char)(*d)[i]) || (*d)[i] == '(' ||
|
||||
(*d)[i] == ')' || (*d)[i] == '\'')
|
||||
w += sldns_str_print(s, sl, "\\%c", (char)(*d)[i]);
|
||||
else w += str_char_print(s, sl, (*d)[i]);
|
||||
}
|
||||
(*d)+=len;
|
||||
(*dl)-=len;
|
||||
return w;
|
||||
}
|
||||
|
||||
int sldns_wire2str_tag_scan(uint8_t** d, size_t* dl, char** s, size_t* sl)
|
||||
{
|
||||
size_t i, n;
|
||||
|
||||
@@ -919,6 +919,19 @@ int sldns_wire2str_eui48_scan(uint8_t** data, size_t* data_len, char** str,
|
||||
int sldns_wire2str_eui64_scan(uint8_t** data, size_t* data_len, char** str,
|
||||
size_t* str_len);
|
||||
|
||||
/**
|
||||
* Scan wireformat UNQUOTED field to string, with user buffers.
|
||||
* It shifts the arguments to move along (see sldns_wire2str_pkt_scan).
|
||||
* @param data: wireformat data.
|
||||
* @param data_len: length of data buffer.
|
||||
* @param str: string buffer.
|
||||
* @param str_len: length of string buffer.
|
||||
* @return number of characters (except null) needed to print.
|
||||
* Can return -1 on failure.
|
||||
*/
|
||||
int sldns_wire2str_unquoted_scan(uint8_t** data, size_t* data_len, char** str,
|
||||
size_t* str_len);
|
||||
|
||||
/**
|
||||
* Scan wireformat TAG field to string, with user buffers.
|
||||
* It shifts the arguments to move along (see sldns_wire2str_pkt_scan).
|
||||
|
||||
@@ -183,7 +183,9 @@ static const char DS_TRUST_ANCHOR[] =
|
||||
/* The anchors must start on a new line with ". IN DS and end with \n"[;]
|
||||
* because the makedist script greps on the source here */
|
||||
/* anchor 20326 is from 2017 */
|
||||
". IN DS 20326 8 2 E06D44B80B8F1D39A95C0B0D7C65D08458E880409BBC683457104237C7F8EC8D\n";
|
||||
". IN DS 20326 8 2 E06D44B80B8F1D39A95C0B0D7C65D08458E880409BBC683457104237C7F8EC8D\n"
|
||||
/* anchor 38696 is from 2024 */
|
||||
". IN DS 38696 8 2 683D2D0ACB8C9B712A1948B27F741219298D0A450D612C483AF444A4C0FB2B16\n";
|
||||
|
||||
/** verbosity for this application */
|
||||
static int verb = 0;
|
||||
|
||||
@@ -342,8 +342,6 @@ 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**));
|
||||
@@ -366,15 +364,19 @@ interfacechecks(struct config_file* cfg)
|
||||
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,
|
||||
if(if_is_pp2(resif[i][0], cfg->port, cfg->proxy_protocol_port)) {
|
||||
if(if_is_dnscrypt(resif[i][0], cfg->port,
|
||||
cfg->dnscrypt_port)) {
|
||||
fatal_exit("PROXYv2 and DNSCrypt combination not "
|
||||
"supported!");
|
||||
} else if(if_is_https(resif[i][0], portbuf,
|
||||
} else if(if_is_https(resif[i][0], cfg->port,
|
||||
cfg->https_port)) {
|
||||
fatal_exit("PROXYv2 and DoH combination not "
|
||||
"supported!");
|
||||
} else if(if_is_quic(resif[i][0], cfg->port,
|
||||
cfg->quic_port)) {
|
||||
fatal_exit("PROXYv2 and DoQ combination not "
|
||||
"supported!");
|
||||
}
|
||||
}
|
||||
/* search for duplicates in the returned addresses */
|
||||
|
||||
@@ -104,7 +104,7 @@ while getopts 'd:hr' arg; do
|
||||
done
|
||||
shift $((OPTIND - 1))
|
||||
|
||||
if ! openssl >/dev/null 2>&1; then
|
||||
if ! openssl version </dev/null >/dev/null 2>&1; then
|
||||
echo "$0 requires openssl to be installed for keys/certificates generation." >&2
|
||||
exit 1
|
||||
fi
|
||||
@@ -204,7 +204,8 @@ fi
|
||||
# remove unused permissions
|
||||
chmod o-rw \
|
||||
"$SVR_BASE.pem" \
|
||||
"$SVR_BASE.key" \
|
||||
"$SVR_BASE.key"
|
||||
chmod g+r,o-rw \
|
||||
"$CTL_BASE.pem" \
|
||||
"$CTL_BASE.key"
|
||||
|
||||
|
||||
@@ -109,6 +109,16 @@ usage(void)
|
||||
printf(" That means the caches sizes and\n");
|
||||
printf(" the number of threads must not\n");
|
||||
printf(" change between reloads.\n");
|
||||
printf(" fast_reload [+dpv] reloads the server but only briefly stops\n");
|
||||
printf(" server processing, keeps cache, and changes\n");
|
||||
printf(" most options; check unbound-control(8).\n");
|
||||
printf(" +d drops running queries to keep consistency\n");
|
||||
printf(" on changed options while reloading.\n");
|
||||
printf(" +p does not pause threads for even faster\n");
|
||||
printf(" reload but less options are supported\n");
|
||||
printf(" ; check unbound-control(8).\n");
|
||||
printf(" +v verbose output, it will include duration needed.\n");
|
||||
printf(" +vv more verbose output, it will include memory needed.\n");
|
||||
printf(" stats print statistics\n");
|
||||
printf(" stats_noreset peek at statistics\n");
|
||||
#ifdef HAVE_SHMGET
|
||||
@@ -186,6 +196,10 @@ usage(void)
|
||||
printf(" rpz_enable zone Enable the RPZ zone if it had previously\n");
|
||||
printf(" been disabled\n");
|
||||
printf(" rpz_disable zone Disable the RPZ zone\n");
|
||||
printf(" add_cookie_secret <secret> add (or replace) a new cookie secret <secret>\n");
|
||||
printf(" drop_cookie_secret drop a staging cookie secret\n");
|
||||
printf(" activate_cookie_secret make a staging cookie secret active\n");
|
||||
printf(" print_cookie_secrets show all cookie secrets with their status\n");
|
||||
printf("Version %s\n", PACKAGE_VERSION);
|
||||
printf("BSD licensed, see LICENSE in source package for details.\n");
|
||||
printf("Report bugs to %s\n", PACKAGE_BUGREPORT);
|
||||
@@ -218,6 +232,9 @@ static void pr_stats(const char* nm, struct ub_stats_info* s)
|
||||
s->svr.num_queries_cookie_client);
|
||||
PR_UL_NM("num.queries_cookie_invalid",
|
||||
s->svr.num_queries_cookie_invalid);
|
||||
PR_UL_NM("num.queries_discard_timeout",
|
||||
s->svr.num_queries_discard_timeout);
|
||||
PR_UL_NM("num.queries_wait_limit", s->svr.num_queries_wait_limit);
|
||||
PR_UL_NM("num.cachehits",
|
||||
s->svr.num_queries - s->svr.num_queries_missed_cache);
|
||||
PR_UL_NM("num.cachemiss", s->svr.num_queries_missed_cache);
|
||||
@@ -227,12 +244,13 @@ static void pr_stats(const char* nm, struct ub_stats_info* s)
|
||||
PR_UL_NM("num.expired", s->svr.ans_expired);
|
||||
PR_UL_NM("num.recursivereplies", s->mesh_replies_sent);
|
||||
#ifdef USE_DNSCRYPT
|
||||
PR_UL_NM("num.dnscrypt.crypted", s->svr.num_query_dnscrypt_crypted);
|
||||
PR_UL_NM("num.dnscrypt.cert", s->svr.num_query_dnscrypt_cert);
|
||||
PR_UL_NM("num.dnscrypt.cleartext", s->svr.num_query_dnscrypt_cleartext);
|
||||
PR_UL_NM("num.dnscrypt.malformed",
|
||||
s->svr.num_query_dnscrypt_crypted_malformed);
|
||||
PR_UL_NM("num.dnscrypt.crypted", s->svr.num_query_dnscrypt_crypted);
|
||||
PR_UL_NM("num.dnscrypt.cert", s->svr.num_query_dnscrypt_cert);
|
||||
PR_UL_NM("num.dnscrypt.cleartext", s->svr.num_query_dnscrypt_cleartext);
|
||||
PR_UL_NM("num.dnscrypt.malformed",
|
||||
s->svr.num_query_dnscrypt_crypted_malformed);
|
||||
#endif /* USE_DNSCRYPT */
|
||||
PR_UL_NM("num.dns_error_reports", s->svr.num_dns_error_reports);
|
||||
printf("%s.requestlist.avg"SQ"%g\n", nm,
|
||||
(s->svr.num_queries_missed_cache+s->svr.num_queries_prefetch)?
|
||||
(double)s->svr.sum_query_list_size/
|
||||
@@ -289,6 +307,9 @@ static void print_mem(struct ub_shm_stat_info* shm_stat,
|
||||
PR_LL("mem.streamwait", s->svr.mem_stream_wait);
|
||||
PR_LL("mem.http.query_buffer", s->svr.mem_http2_query_buffer);
|
||||
PR_LL("mem.http.response_buffer", s->svr.mem_http2_response_buffer);
|
||||
#ifdef HAVE_NGTCP2
|
||||
PR_LL("mem.quic", s->svr.mem_quic);
|
||||
#endif
|
||||
}
|
||||
|
||||
/** print histogram */
|
||||
@@ -355,6 +376,9 @@ static void print_extended(struct ub_stats_info* s, int inhibit_zero)
|
||||
PR_UL("num.query.tls_resume", s->svr.qtls_resume);
|
||||
PR_UL("num.query.ipv6", s->svr.qipv6);
|
||||
PR_UL("num.query.https", s->svr.qhttps);
|
||||
#ifdef HAVE_NGTCP2
|
||||
PR_UL("num.query.quic", s->svr.qquic);
|
||||
#endif
|
||||
|
||||
/* flags */
|
||||
PR_UL("num.query.flags.QR", s->svr.qbit_QR);
|
||||
|
||||
@@ -50,6 +50,8 @@
|
||||
#undef calloc
|
||||
#undef free
|
||||
#undef realloc
|
||||
#undef reallocarray
|
||||
#undef strdup
|
||||
#endif
|
||||
#ifdef UNBOUND_ALLOC_LITE
|
||||
#undef malloc
|
||||
@@ -492,7 +494,11 @@ int main(int argc, char* argv[])
|
||||
if(strcmp(use_syslog, "yes") == 0) /* disable use-syslog */
|
||||
check_ub_res(ub_ctx_set_option(ctx,
|
||||
"use-syslog:", "no"));
|
||||
#ifdef UNBOUND_ALLOC_STATS
|
||||
unbound_stat_free_log(use_syslog, __FILE__, __LINE__, __func__);
|
||||
#else
|
||||
free(use_syslog);
|
||||
#endif
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
@@ -255,3 +255,33 @@ void dtio_mainfdcallback(int ATTR_UNUSED(fd), short ATTR_UNUSED(ev),
|
||||
log_assert(0);
|
||||
}
|
||||
#endif
|
||||
|
||||
void fast_reload_service_cb(int ATTR_UNUSED(fd), short ATTR_UNUSED(ev),
|
||||
void* ATTR_UNUSED(arg))
|
||||
{
|
||||
log_assert(0);
|
||||
}
|
||||
|
||||
int fast_reload_client_callback(struct comm_point* ATTR_UNUSED(c),
|
||||
void* ATTR_UNUSED(arg), int ATTR_UNUSED(error),
|
||||
struct comm_reply* ATTR_UNUSED(repinfo))
|
||||
{
|
||||
log_assert(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef HAVE_NGTCP2
|
||||
void doq_client_event_cb(int ATTR_UNUSED(fd), short ATTR_UNUSED(ev),
|
||||
void* ATTR_UNUSED(arg))
|
||||
{
|
||||
log_assert(0);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_NGTCP2
|
||||
void doq_client_timer_cb(int ATTR_UNUSED(fd), short ATTR_UNUSED(ev),
|
||||
void* ATTR_UNUSED(arg))
|
||||
{
|
||||
log_assert(0);
|
||||
}
|
||||
#endif
|
||||
|
||||
+36
-6
@@ -64,10 +64,15 @@ static int key_deleted = 0;
|
||||
static ub_thread_key_type thr_debug_key;
|
||||
/** the list of threads, so all threads can be examined. NULL if unused. */
|
||||
static struct thr_check* thread_infos[THRDEBUG_MAX_THREADS];
|
||||
/** stored maximum lock number for threads, when a thread is restarted the
|
||||
* number is kept track of, because the new locks get new id numbers. */
|
||||
static int thread_lockcount[THRDEBUG_MAX_THREADS];
|
||||
/** do we check locking order */
|
||||
int check_locking_order = 1;
|
||||
/** the pid of this runset, reasonably unique. */
|
||||
static pid_t check_lock_pid;
|
||||
/** the name of the output file */
|
||||
static const char* output_name = "ublocktrace";
|
||||
/**
|
||||
* Should checklocks print a trace of the lock and unlock calls.
|
||||
* It uses fprintf for that because the log function uses a lock and that
|
||||
@@ -142,7 +147,8 @@ acquire_locklock(struct checked_lock* lock,
|
||||
|
||||
/** add protected region */
|
||||
void
|
||||
lock_protect(void *p, void* area, size_t size)
|
||||
lock_protect_place(void* p, void* area, size_t size, const char* def_func,
|
||||
const char* def_file, int def_line, const char* def_area)
|
||||
{
|
||||
struct checked_lock* lock = *(struct checked_lock**)p;
|
||||
struct protected_area* e = (struct protected_area*)malloc(
|
||||
@@ -151,6 +157,10 @@ lock_protect(void *p, void* area, size_t size)
|
||||
fatal_exit("lock_protect: out of memory");
|
||||
e->region = area;
|
||||
e->size = size;
|
||||
e->def_func = def_func;
|
||||
e->def_file = def_file;
|
||||
e->def_line = def_line;
|
||||
e->def_area = def_area;
|
||||
e->hold = malloc(size);
|
||||
if(!e->hold)
|
||||
fatal_exit("lock_protect: out of memory");
|
||||
@@ -203,6 +213,9 @@ prot_check(struct checked_lock* lock,
|
||||
if(memcmp(p->hold, p->region, p->size) != 0) {
|
||||
log_hex("memory prev", p->hold, p->size);
|
||||
log_hex("memory here", p->region, p->size);
|
||||
log_err("lock_protect on %s %s:%d %s failed",
|
||||
p->def_func, p->def_file, p->def_line,
|
||||
p->def_area);
|
||||
lock_error(lock, func, file, line,
|
||||
"protected area modified");
|
||||
}
|
||||
@@ -675,17 +688,33 @@ checklock_unlock(enum check_lock_type type, struct checked_lock* lock,
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
checklock_set_output_name(const char* name)
|
||||
{
|
||||
output_name = name;
|
||||
}
|
||||
|
||||
/** open order info debug file, thr->num must be valid */
|
||||
static void
|
||||
open_lockorder(struct thr_check* thr)
|
||||
{
|
||||
char buf[24];
|
||||
time_t t;
|
||||
snprintf(buf, sizeof(buf), "ublocktrace.%d", thr->num);
|
||||
thr->order_info = fopen(buf, "w");
|
||||
if(!thr->order_info)
|
||||
fatal_exit("could not open %s: %s", buf, strerror(errno));
|
||||
thr->locks_created = 0;
|
||||
snprintf(buf, sizeof(buf), "%s.%d", output_name, thr->num);
|
||||
thr->locks_created = thread_lockcount[thr->num];
|
||||
if(thr->locks_created == 0) {
|
||||
thr->order_info = fopen(buf, "w");
|
||||
if(!thr->order_info)
|
||||
fatal_exit("could not open %s: %s", buf, strerror(errno));
|
||||
} else {
|
||||
/* There is already a file to append on with the previous
|
||||
* thread information. */
|
||||
thr->order_info = fopen(buf, "a");
|
||||
if(!thr->order_info)
|
||||
fatal_exit("could not open for append %s: %s", buf, strerror(errno));
|
||||
return;
|
||||
}
|
||||
|
||||
t = time(NULL);
|
||||
/* write: <time_stamp> <runpid> <thread_num> */
|
||||
if(fwrite(&t, sizeof(t), 1, thr->order_info) != 1 ||
|
||||
@@ -712,6 +741,7 @@ static void* checklock_main(void* arg)
|
||||
if(check_locking_order)
|
||||
open_lockorder(thr);
|
||||
ret = thr->func(thr->arg);
|
||||
thread_lockcount[thr->num] = thr->locks_created;
|
||||
thread_infos[thr->num] = NULL;
|
||||
if(check_locking_order)
|
||||
fclose(thr->order_info);
|
||||
|
||||
+23
-1
@@ -90,6 +90,14 @@ struct protected_area {
|
||||
void* hold;
|
||||
/** next protected area in list */
|
||||
struct protected_area* next;
|
||||
/** the place where the lock_protect is made, at init. */
|
||||
const char* def_func;
|
||||
/** the file where the lock_protect is made */
|
||||
const char* def_file;
|
||||
/** the line number where the lock_protect is made */
|
||||
int def_line;
|
||||
/** the text string for the area that is protected, at init call. */
|
||||
const char* def_area;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -181,12 +189,19 @@ struct checked_lock {
|
||||
* It demangles the lock itself (struct checked_lock**).
|
||||
* @param area: ptr to mem.
|
||||
* @param size: length of area.
|
||||
* @param def_func: function where the lock_protect() line is.
|
||||
* @param def_file: file where the lock_protect() line is.
|
||||
* @param def_line: line where the lock_protect() line is.
|
||||
* @param def_area: area string
|
||||
* You can call it multiple times with the same lock to give several areas.
|
||||
* Call it when you are done initializing the area, since it will be copied
|
||||
* at this time and protected right away against unauthorised changes until
|
||||
* the next lock() call is done.
|
||||
*/
|
||||
void lock_protect(void* lock, void* area, size_t size);
|
||||
void lock_protect_place(void* lock, void* area, size_t size,
|
||||
const char* def_func, const char* def_file, int def_line,
|
||||
const char* def_area);
|
||||
#define lock_protect(lock, area, size) lock_protect_place(lock, area, size, __func__, __FILE__, __LINE__, #area)
|
||||
|
||||
/**
|
||||
* Remove protected area from lock.
|
||||
@@ -203,6 +218,13 @@ void lock_unprotect(void* lock, void* area);
|
||||
*/
|
||||
size_t lock_get_mem(void* lock);
|
||||
|
||||
/**
|
||||
* Set the output name, prefix, of the lock check output file(s).
|
||||
* Call it before the checklock_start or thread creation. Pass a fixed string.
|
||||
* @param name: string to use for output data file names.
|
||||
*/
|
||||
void checklock_set_output_name(const char* name);
|
||||
|
||||
/**
|
||||
* Initialise checklock. Sets up internal debug structures.
|
||||
*/
|
||||
|
||||
@@ -17,6 +17,7 @@ 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'
|
||||
NEED_REDIS_SERVER='redis_replica.tdir'
|
||||
|
||||
# test if dig and ldns-testns are available.
|
||||
test_tool_avail "dig"
|
||||
@@ -52,6 +53,7 @@ for test in `ls -d *.tdir`; do
|
||||
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"
|
||||
skip_if_in_list $test "$NEED_REDIS_SERVER" "redis-server"
|
||||
|
||||
if echo $NEED_IPV6 | grep $test >/dev/null; then
|
||||
if test "$HAVE_IPV6" = no; then
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
+34
-3
@@ -938,7 +938,12 @@ listen_create(struct comm_base* base, struct listen_port* ATTR_UNUSED(ports),
|
||||
char* ATTR_UNUSED(http_endpoint),
|
||||
int ATTR_UNUSED(http_notls),
|
||||
struct tcl_list* ATTR_UNUSED(tcp_conn_limit),
|
||||
void* ATTR_UNUSED(sslctx), struct dt_env* ATTR_UNUSED(dtenv),
|
||||
void* ATTR_UNUSED(dot_sslctx), void* ATTR_UNUSED(doh_sslctx),
|
||||
void* ATTR_UNUSED(quic_ssl),
|
||||
struct dt_env* ATTR_UNUSED(dtenv),
|
||||
struct doq_table* ATTR_UNUSED(table),
|
||||
struct ub_randstate* ATTR_UNUSED(rnd),
|
||||
struct config_file* ATTR_UNUSED(cfg),
|
||||
comm_point_callback_type* cb, void *cb_arg)
|
||||
{
|
||||
struct replay_runtime* runtime = (struct replay_runtime*)base;
|
||||
@@ -1259,7 +1264,7 @@ struct serviced_query* outnet_serviced_query(struct outside_network* outnet,
|
||||
struct replay_runtime* runtime = (struct replay_runtime*)outnet->base;
|
||||
struct fake_pending* pend = (struct fake_pending*)calloc(1,
|
||||
sizeof(struct fake_pending));
|
||||
char z[256];
|
||||
char z[LDNS_MAX_DOMAINLEN];
|
||||
log_assert(pend);
|
||||
log_nametypeclass(VERB_OPS, "pending serviced query",
|
||||
qinfo->qname, qinfo->qtype, qinfo->qclass);
|
||||
@@ -1479,6 +1484,11 @@ size_t comm_point_get_mem(struct comm_point* ATTR_UNUSED(c))
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t comm_timer_get_mem(struct comm_timer* ATTR_UNUSED(timer))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t serviced_get_mem(struct serviced_query* ATTR_UNUSED(c))
|
||||
{
|
||||
return 0;
|
||||
@@ -1934,7 +1944,8 @@ int comm_point_send_udp_msg(struct comm_point *c, sldns_buffer* packet,
|
||||
}
|
||||
|
||||
int outnet_get_tcp_fd(struct sockaddr_storage* ATTR_UNUSED(addr),
|
||||
socklen_t ATTR_UNUSED(addrlen), int ATTR_UNUSED(tcp_mss), int ATTR_UNUSED(dscp))
|
||||
socklen_t ATTR_UNUSED(addrlen), int ATTR_UNUSED(tcp_mss),
|
||||
int ATTR_UNUSED(dscp), int ATTR_UNUSED(nodelay))
|
||||
{
|
||||
log_assert(0);
|
||||
return -1;
|
||||
@@ -1988,4 +1999,24 @@ void http2_stream_remove_mesh_state(struct http2_stream* ATTR_UNUSED(h2_stream))
|
||||
{
|
||||
}
|
||||
|
||||
void fast_reload_service_cb(int ATTR_UNUSED(fd), short ATTR_UNUSED(event),
|
||||
void* ATTR_UNUSED(arg))
|
||||
{
|
||||
log_assert(0);
|
||||
}
|
||||
|
||||
void fast_reload_thread_stop(
|
||||
struct fast_reload_thread* ATTR_UNUSED(fast_reload_thread))
|
||||
{
|
||||
/* nothing */
|
||||
}
|
||||
|
||||
int fast_reload_client_callback(struct comm_point* ATTR_UNUSED(c),
|
||||
void* ATTR_UNUSED(arg), int ATTR_UNUSED(error),
|
||||
struct comm_reply* ATTR_UNUSED(repinfo))
|
||||
{
|
||||
log_assert(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*********** End of Dummy routines ***********/
|
||||
|
||||
+3
-3
@@ -220,7 +220,7 @@ perfsetup(struct perfinfo* info)
|
||||
#endif
|
||||
signal(SIGTERM, perf_sigh) == SIG_ERR)
|
||||
fatal_exit("could not bind to signal");
|
||||
info->io = (struct perfio*)calloc(sizeof(struct perfio), info->io_num);
|
||||
info->io = (struct perfio*)calloc(info->io_num, sizeof(struct perfio));
|
||||
if(!info->io) fatal_exit("out of memory");
|
||||
#ifndef S_SPLINT_S
|
||||
FD_ZERO(&info->rset);
|
||||
@@ -501,8 +501,8 @@ qlist_grow_capacity(struct perfinfo* info)
|
||||
{
|
||||
size_t newcap = (size_t)((info->qlist_capacity==0)?16:
|
||||
info->qlist_capacity*2);
|
||||
uint8_t** d = (uint8_t**)calloc(sizeof(uint8_t*), newcap);
|
||||
size_t* l = (size_t*)calloc(sizeof(size_t), newcap);
|
||||
uint8_t** d = (uint8_t**)calloc(newcap, sizeof(uint8_t*));
|
||||
size_t* l = (size_t*)calloc(newcap, sizeof(size_t));
|
||||
if(!d || !l) fatal_exit("out of memory");
|
||||
if(info->qlist_data && info->qlist_capacity)
|
||||
memcpy(d, info->qlist_data, sizeof(uint8_t*)*
|
||||
|
||||
+67
-18
@@ -72,23 +72,6 @@ int daemon_main(int argc, char* argv[]);
|
||||
/** config files (removed at exit) */
|
||||
static struct config_strlist* cfgfiles = NULL;
|
||||
|
||||
#ifdef UNBOUND_ALLOC_STATS
|
||||
# define strdup(s) unbound_stat_strdup_log(s, __FILE__, __LINE__, __func__)
|
||||
char* unbound_stat_strdup_log(char* s, const char* file, int line,
|
||||
const char* func);
|
||||
char* unbound_stat_strdup_log(char* s, const char* file, int line,
|
||||
const char* func) {
|
||||
char* result;
|
||||
size_t len;
|
||||
if(!s) return NULL;
|
||||
len = strlen(s);
|
||||
log_info("%s:%d %s strdup(%u)", file, line, func, (unsigned)len+1);
|
||||
result = unbound_stat_malloc(len+1);
|
||||
memmove(result, s, len+1);
|
||||
return result;
|
||||
}
|
||||
#endif /* UNBOUND_ALLOC_STATS */
|
||||
|
||||
/** give commandline usage for testbound. */
|
||||
static void
|
||||
testbound_usage(void)
|
||||
@@ -519,7 +502,7 @@ struct listen_port* daemon_remote_open_ports(struct config_file*
|
||||
|
||||
struct daemon_remote* daemon_remote_create(struct config_file* ATTR_UNUSED(cfg))
|
||||
{
|
||||
return (struct daemon_remote*)calloc(1,1);
|
||||
return (struct daemon_remote*)calloc(1, sizeof(struct daemon_remote));
|
||||
}
|
||||
|
||||
void daemon_remote_delete(struct daemon_remote* rc)
|
||||
@@ -617,3 +600,69 @@ void listen_desetup_locks(void)
|
||||
{
|
||||
/* nothing */
|
||||
}
|
||||
|
||||
void fast_reload_printq_list_delete(
|
||||
struct fast_reload_printq* ATTR_UNUSED(list))
|
||||
{
|
||||
/* nothing */
|
||||
}
|
||||
|
||||
void fast_reload_worker_pickup_changes(struct worker* ATTR_UNUSED(worker))
|
||||
{
|
||||
/* nothing */
|
||||
}
|
||||
|
||||
#ifdef HAVE_NGTCP2
|
||||
void* quic_sslctx_create(char* ATTR_UNUSED(key), char* ATTR_UNUSED(pem),
|
||||
char* ATTR_UNUSED(verifypem))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void comm_point_doq_callback(int ATTR_UNUSED(fd), short ATTR_UNUSED(event),
|
||||
void* ATTR_UNUSED(arg))
|
||||
{
|
||||
/* nothing */
|
||||
}
|
||||
|
||||
int doq_conn_cmp(const void* ATTR_UNUSED(key1), const void* ATTR_UNUSED(key2))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int doq_conid_cmp(const void* ATTR_UNUSED(key1), const void* ATTR_UNUSED(key2))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int doq_timer_cmp(const void* ATTR_UNUSED(key1), const void* ATTR_UNUSED(key2))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int doq_stream_cmp(const void* ATTR_UNUSED(key1), const void* ATTR_UNUSED(key2))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct doq_table* doq_table_create(struct config_file* ATTR_UNUSED(cfg),
|
||||
struct ub_randstate* ATTR_UNUSED(rnd))
|
||||
{
|
||||
return calloc(1, sizeof(struct doq_table));
|
||||
}
|
||||
|
||||
void doq_table_delete(struct doq_table* table)
|
||||
{
|
||||
free(table);
|
||||
}
|
||||
|
||||
void doq_timer_cb(void* ATTR_UNUSED(arg))
|
||||
{
|
||||
/* nothing */
|
||||
}
|
||||
|
||||
size_t doq_table_quic_size_get(struct doq_table* ATTR_UNUSED(table))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include <ctype.h>
|
||||
#include "util/log.h"
|
||||
#include "testcode/unitmain.h"
|
||||
#include "util/data/dname.h"
|
||||
@@ -858,6 +859,151 @@ dname_setup_bufs(sldns_buffer* loopbuf, sldns_buffer* boundbuf)
|
||||
sldns_buffer_flip(boundbuf);
|
||||
}
|
||||
|
||||
static void
|
||||
dname_test_str(sldns_buffer* buff)
|
||||
{
|
||||
char result[LDNS_MAX_DOMAINLEN], expect[LDNS_MAX_DOMAINLEN], *e;
|
||||
size_t i;
|
||||
unit_show_func("util/data/dname.c", "dname_str");
|
||||
|
||||
/* root ; expected OK */
|
||||
sldns_buffer_clear(buff);
|
||||
sldns_buffer_write(buff, "\000", 1);
|
||||
sldns_buffer_flip(buff);
|
||||
unit_assert( sldns_buffer_limit(buff) == 1 );
|
||||
unit_assert( pkt_dname_len(buff) == 1 );
|
||||
dname_str(sldns_buffer_begin(buff), result);
|
||||
unit_assert( strcmp( ".", result) == 0 );
|
||||
|
||||
/* LDNS_MAX_DOMAINLEN - 1 ; expected OK */
|
||||
sldns_buffer_clear(buff);
|
||||
sldns_buffer_write(buff,
|
||||
"\077abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890" /* 64 up to here */
|
||||
"\077abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890" /* 128 up to here */
|
||||
"\077abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890" /* 192 up to here */
|
||||
"\074abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567" /* 253 up to here */
|
||||
"\000" /* 254 up to here */
|
||||
, 254);
|
||||
sldns_buffer_flip(buff);
|
||||
unit_assert( sldns_buffer_limit(buff) == 254 );
|
||||
unit_assert( pkt_dname_len(buff) == 254 );
|
||||
dname_str(sldns_buffer_begin(buff), result);
|
||||
unit_assert( strcmp(
|
||||
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890."
|
||||
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890."
|
||||
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890."
|
||||
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567"
|
||||
".", result) == 0 );
|
||||
|
||||
/* LDNS_MAX_DOMAINLEN ; expected OK */
|
||||
sldns_buffer_clear(buff);
|
||||
sldns_buffer_write(buff,
|
||||
"\077abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890" /* 64 up to here */
|
||||
"\077abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890" /* 128 up to here */
|
||||
"\077abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890" /* 192 up to here */
|
||||
"\075abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ012345678" /* 254 up to here */
|
||||
"\000" /* 255 up to here */
|
||||
, 255);
|
||||
sldns_buffer_flip(buff);
|
||||
unit_assert( sldns_buffer_limit(buff) == 255 );
|
||||
unit_assert( pkt_dname_len(buff) == 255 );
|
||||
dname_str(sldns_buffer_begin(buff), result);
|
||||
unit_assert( strcmp(
|
||||
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890."
|
||||
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890."
|
||||
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890."
|
||||
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ012345678"
|
||||
".", result) == 0 );
|
||||
|
||||
/* LDNS_MAX_DOMAINLEN + 1 ; expected to fail, output uses '&' on the latest label */
|
||||
sldns_buffer_clear(buff);
|
||||
sldns_buffer_write(buff,
|
||||
"\077abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890" /* 64 up to here */
|
||||
"\077abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890" /* 128 up to here */
|
||||
"\077abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890" /* 192 up to here */
|
||||
"\076abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" /* 255 up to here */
|
||||
"\000" /* 256 up to here */
|
||||
, 256);
|
||||
sldns_buffer_flip(buff);
|
||||
unit_assert( sldns_buffer_limit(buff) == 256 );
|
||||
unit_assert( pkt_dname_len(buff) == 0 );
|
||||
dname_str(sldns_buffer_begin(buff), result);
|
||||
unit_assert( strcmp(
|
||||
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890."
|
||||
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890."
|
||||
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890."
|
||||
"&", result) == 0 );
|
||||
|
||||
/* LDNS_MAX_LABELLEN + 1 ; expected to fail, output uses '#' on the offending label */
|
||||
sldns_buffer_clear(buff);
|
||||
sldns_buffer_write(buff,
|
||||
"\077abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890" /* 64 up to here */
|
||||
"\100abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890a" /* 129 up to here */
|
||||
"\000" /* 130 up to here */
|
||||
, 130);
|
||||
sldns_buffer_flip(buff);
|
||||
unit_assert( sldns_buffer_limit(buff) == 130 );
|
||||
unit_assert( pkt_dname_len(buff) == 0 );
|
||||
dname_str(sldns_buffer_begin(buff), result);
|
||||
unit_assert( strcmp(
|
||||
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890."
|
||||
"#", result) == 0 );
|
||||
|
||||
/* LDNS_MAX_DOMAINLEN with single labels; expected OK */
|
||||
sldns_buffer_clear(buff);
|
||||
for(i=0; i<=252; i+=2)
|
||||
sldns_buffer_write(buff, "\001a", 2);
|
||||
sldns_buffer_write_u8(buff, 0);
|
||||
sldns_buffer_flip(buff);
|
||||
unit_assert( sldns_buffer_limit(buff) == 255 );
|
||||
unit_assert( pkt_dname_len(buff) == 255 );
|
||||
dname_str(sldns_buffer_begin(buff), result);
|
||||
e = expect;
|
||||
for(i=0; i<=252; i+=2) {
|
||||
*e++ = 'a';
|
||||
*e++ = '.';
|
||||
}
|
||||
*e = '\0';
|
||||
unit_assert( strcmp(expect, result) == 0 );
|
||||
|
||||
/* LDNS_MAX_DOMAINLEN + 1 with single labels; expected to fail, output uses '&' on the latest label */
|
||||
sldns_buffer_clear(buff);
|
||||
for(i=0; i<=250; i+=2)
|
||||
sldns_buffer_write(buff, "\001a", 2);
|
||||
sldns_buffer_write(buff, "\002ab", 3);
|
||||
sldns_buffer_write_u8(buff, 0);
|
||||
sldns_buffer_flip(buff);
|
||||
unit_assert( sldns_buffer_limit(buff) == 256 );
|
||||
unit_assert( pkt_dname_len(buff) == 0 );
|
||||
dname_str(sldns_buffer_begin(buff), result);
|
||||
e = expect;
|
||||
for(i=0; i<=250; i+=2) {
|
||||
*e++ = 'a';
|
||||
*e++ = '.';
|
||||
}
|
||||
*e++ = '&';
|
||||
*e = '\0';
|
||||
unit_assert( strcmp(expect, result) == 0 );
|
||||
|
||||
/* Only alphas, numericals and '-', '_' and '*' are allowed in the output */
|
||||
for(i=1; i<=255; i++) {
|
||||
if(isalnum(i) || i == '-' || i == '_' || i == '*')
|
||||
continue;
|
||||
sldns_buffer_clear(buff);
|
||||
sldns_buffer_write_u8(buff, 1);
|
||||
sldns_buffer_write_u8(buff, (uint8_t)i);
|
||||
sldns_buffer_write_u8(buff, 0);
|
||||
sldns_buffer_flip(buff);
|
||||
unit_assert( sldns_buffer_limit(buff) == 3 );
|
||||
unit_assert( pkt_dname_len(buff) == 3);
|
||||
dname_str(sldns_buffer_begin(buff), result);
|
||||
if(strcmp( "?.", result) != 0 ) {
|
||||
log_err("ASCII value '0x%lX' allowed in string output", (unsigned long)i);
|
||||
unit_assert(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void dname_test(void)
|
||||
{
|
||||
sldns_buffer* loopbuf = sldns_buffer_new(14);
|
||||
@@ -884,6 +1030,7 @@ void dname_test(void)
|
||||
dname_test_topdomain();
|
||||
dname_test_valid();
|
||||
dname_test_has_label();
|
||||
dname_test_str(buff);
|
||||
sldns_buffer_free(buff);
|
||||
sldns_buffer_free(loopbuf);
|
||||
sldns_buffer_free(boundbuf);
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* testcode/unitdoq.c - unit test for doq routines.
|
||||
*
|
||||
* Copyright (c) 2022, NLnet Labs. All rights reserved.
|
||||
*
|
||||
* This software is open source.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* Neither the name of the NLNET LABS nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
* Calls doq related unit tests. Exits with code 1 on a failure.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifdef HAVE_NGTCP2
|
||||
|
||||
#include "util/netevent.h"
|
||||
#include "services/listen_dnsport.h"
|
||||
#include "testcode/unitmain.h"
|
||||
|
||||
/** check the size of a connection for doq */
|
||||
static void
|
||||
doq_size_conn_check()
|
||||
{
|
||||
/* Printout the size of one doq connection, in memory usage.
|
||||
* A connection with a couple cids, of type doq_conid, and
|
||||
* it has one stream, and that has a query and an answer. */
|
||||
size_t answer_size = 233; /* size of www.nlnetlabs.nl minimal answer
|
||||
with dnssec and one A record. The unsigned answer is 176 with
|
||||
additional data, 61 bytes minimal response one A record. */
|
||||
size_t query_size = 45; /* size of query for www.nlnetlabs.nl, with
|
||||
an EDNS record with DO flag. */
|
||||
size_t conn_size = sizeof(struct doq_conn);
|
||||
size_t conid_size = sizeof(struct doq_conid);
|
||||
size_t stream_size = sizeof(struct doq_stream);
|
||||
|
||||
conn_size += 16; /* DCID len in the conn key */
|
||||
conn_size += 0; /* the size of the ngtcp2_conn */
|
||||
conn_size += 0; /* the size of the SSL record */
|
||||
conn_size += 0; /* size of the close pkt,
|
||||
but we do not count it here. Only if the conn gets closed. */
|
||||
conid_size += 16; /* the dcid of the conn key */
|
||||
conid_size += 16; /* the cid */
|
||||
stream_size += query_size; /* size of in buffer */
|
||||
stream_size += answer_size; /* size of out buffer */
|
||||
printf("doq connection size %u bytes\n", (unsigned)(conn_size +
|
||||
conid_size*3 + stream_size));
|
||||
}
|
||||
|
||||
void doq_test(void)
|
||||
{
|
||||
unit_show_feature("doq");
|
||||
doq_size_conn_check();
|
||||
}
|
||||
#endif /* HAVE_NGTCP2 */
|
||||
@@ -0,0 +1,209 @@
|
||||
/*
|
||||
* testcode/unitinfra.c - unit test for infra cache.
|
||||
*
|
||||
* Copyright (c) 2025, NLnet Labs. All rights reserved.
|
||||
*
|
||||
* This software is open source.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* Neither the name of the NLNET LABS nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
/**
|
||||
* \file
|
||||
* Tests the infra functionality.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "testcode/unitmain.h"
|
||||
#include "iterator/iterator.h"
|
||||
#include "services/cache/infra.h"
|
||||
#include "util/config_file.h"
|
||||
#include "util/net_help.h"
|
||||
|
||||
/* lookup and get key and data structs easily */
|
||||
static struct infra_data* infra_lookup_host(struct infra_cache* infra,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* zone,
|
||||
size_t zonelen, int wr, time_t now, struct infra_key** k)
|
||||
{
|
||||
struct infra_data* d;
|
||||
struct lruhash_entry* e = infra_lookup_nottl(infra, addr, addrlen,
|
||||
zone, zonelen, wr);
|
||||
if(!e) return NULL;
|
||||
d = (struct infra_data*)e->data;
|
||||
if(d->ttl < now) {
|
||||
lock_rw_unlock(&e->lock);
|
||||
return NULL;
|
||||
}
|
||||
*k = (struct infra_key*)e->key;
|
||||
return d;
|
||||
}
|
||||
|
||||
static void test_keep_probing(struct infra_cache* slab,
|
||||
struct config_file* cfg, struct sockaddr_storage one, socklen_t onelen,
|
||||
uint8_t* zone, size_t zonelen, time_t *now, int keep_probing,
|
||||
int rtt_max_timeout)
|
||||
{
|
||||
uint8_t edns_lame;
|
||||
int vs, to, lame, dnsseclame, reclame, probedelay;
|
||||
struct infra_key* k;
|
||||
struct infra_data* d;
|
||||
|
||||
/* configure */
|
||||
cfg->infra_cache_max_rtt = rtt_max_timeout;
|
||||
config_apply_max_rtt(rtt_max_timeout);
|
||||
slab->infra_keep_probing = keep_probing;
|
||||
|
||||
/* expired previous entry */
|
||||
*now += cfg->host_ttl + 10;
|
||||
unit_assert( infra_host(slab, &one, onelen, zone, zonelen,
|
||||
*now, &vs, &edns_lame, &to) );
|
||||
|
||||
/* simulate timeouts until the USEFUL_SERVER_TOP_TIMEOUT is reached */
|
||||
while(to < USEFUL_SERVER_TOP_TIMEOUT) {
|
||||
unit_assert( infra_rtt_update(slab, &one, onelen, zone, zonelen,
|
||||
LDNS_RR_TYPE_A, -1, to, *now) );
|
||||
unit_assert( infra_host(slab, &one, onelen, zone, zonelen,
|
||||
*now, &vs, &edns_lame, &to) );
|
||||
unit_assert( vs == 0 && to <= USEFUL_SERVER_TOP_TIMEOUT && edns_lame == 0 );
|
||||
}
|
||||
unit_assert( vs == 0 && to == USEFUL_SERVER_TOP_TIMEOUT && edns_lame == 0 );
|
||||
|
||||
/* don't let the record expire */
|
||||
unit_assert( (d=infra_lookup_host(slab, &one, onelen, zone, zonelen, 0, *now, &k)) );
|
||||
unit_assert( d->timeout_A >= TIMEOUT_COUNT_MAX );
|
||||
unit_assert( d->probedelay > 0 );
|
||||
probedelay = d->probedelay;
|
||||
lock_rw_unlock(&k->entry.lock);
|
||||
cfg->host_ttl = cfg->host_ttl + *now < probedelay
|
||||
?cfg->host_ttl :probedelay + 10;
|
||||
|
||||
/* advance time and check that probing is as expected; we already had a
|
||||
* lot of A timeouts (checked above). */
|
||||
*now = probedelay;
|
||||
unit_assert( infra_get_lame_rtt(slab, &one, onelen, zone, zonelen,
|
||||
LDNS_RR_TYPE_A, &lame, &dnsseclame, &reclame, &to, *now) );
|
||||
unit_assert( lame == 0 && dnsseclame == 0 && reclame == 0
|
||||
&& to == keep_probing ?still_useful_timeout() :USEFUL_SERVER_TOP_TIMEOUT);
|
||||
}
|
||||
|
||||
/** test host cache */
|
||||
void infra_test(void)
|
||||
{
|
||||
struct sockaddr_storage one;
|
||||
socklen_t onelen;
|
||||
uint8_t* zone = (uint8_t*)"\007example\003com\000";
|
||||
size_t zonelen = 13;
|
||||
struct infra_cache* slab;
|
||||
struct config_file* cfg = config_create();
|
||||
time_t now = 0;
|
||||
uint8_t edns_lame;
|
||||
int vs, to;
|
||||
struct infra_key* k;
|
||||
struct infra_data* d;
|
||||
int init = UNKNOWN_SERVER_NICENESS;
|
||||
int default_max_rtt = USEFUL_SERVER_TOP_TIMEOUT;
|
||||
|
||||
unit_show_feature("infra cache");
|
||||
unit_assert(ipstrtoaddr("127.0.0.1", 53, &one, &onelen));
|
||||
|
||||
slab = infra_create(cfg);
|
||||
/* insert new record */
|
||||
unit_assert( infra_host(slab, &one, onelen, zone, zonelen, now,
|
||||
&vs, &edns_lame, &to) );
|
||||
unit_assert( vs == 0 && to == init && edns_lame == 0 );
|
||||
|
||||
/* simulate no answer */
|
||||
unit_assert( infra_rtt_update(slab, &one, onelen, zone, zonelen, LDNS_RR_TYPE_A, -1, init, now) );
|
||||
unit_assert( infra_host(slab, &one, onelen, zone, zonelen,
|
||||
now, &vs, &edns_lame, &to) );
|
||||
unit_assert( vs == 0 && to == init*2 && edns_lame == 0 );
|
||||
|
||||
/* simulate EDNS lame */
|
||||
unit_assert( infra_edns_update(slab, &one, onelen, zone, zonelen, -1, now) );
|
||||
unit_assert( infra_host(slab, &one, onelen, zone, zonelen,
|
||||
now, &vs, &edns_lame, &to) );
|
||||
unit_assert( vs == -1 && to == init*2 && edns_lame == 1);
|
||||
|
||||
/* simulate cache expiry */
|
||||
now += cfg->host_ttl + 10;
|
||||
unit_assert( infra_host(slab, &one, onelen, zone, zonelen,
|
||||
now, &vs, &edns_lame, &to) );
|
||||
unit_assert( vs == 0 && to == init && edns_lame == 0 );
|
||||
|
||||
/* simulate no lame answer */
|
||||
unit_assert( infra_set_lame(slab, &one, onelen,
|
||||
zone, zonelen, now, 0, 0, LDNS_RR_TYPE_A) );
|
||||
unit_assert( (d=infra_lookup_host(slab, &one, onelen, zone, zonelen, 0, now, &k)) );
|
||||
unit_assert( d->ttl == now+cfg->host_ttl );
|
||||
unit_assert( d->edns_version == 0 );
|
||||
unit_assert(!d->isdnsseclame && !d->rec_lame && d->lame_type_A &&
|
||||
!d->lame_other);
|
||||
lock_rw_unlock(&k->entry.lock);
|
||||
|
||||
/* test merge of data */
|
||||
unit_assert( infra_set_lame(slab, &one, onelen,
|
||||
zone, zonelen, now, 0, 0, LDNS_RR_TYPE_AAAA) );
|
||||
unit_assert( (d=infra_lookup_host(slab, &one, onelen, zone, zonelen, 0, now, &k)) );
|
||||
unit_assert(!d->isdnsseclame && !d->rec_lame && d->lame_type_A &&
|
||||
d->lame_other);
|
||||
lock_rw_unlock(&k->entry.lock);
|
||||
|
||||
/* test that noEDNS cannot overwrite known-yesEDNS */
|
||||
now += cfg->host_ttl + 10;
|
||||
unit_assert( infra_host(slab, &one, onelen, zone, zonelen,
|
||||
now, &vs, &edns_lame, &to) );
|
||||
unit_assert( vs == 0 && to == init && edns_lame == 0 );
|
||||
|
||||
unit_assert( infra_edns_update(slab, &one, onelen, zone, zonelen, 0, now) );
|
||||
unit_assert( infra_host(slab, &one, onelen, zone, zonelen,
|
||||
now, &vs, &edns_lame, &to) );
|
||||
unit_assert( vs == 0 && to == init && edns_lame == 1 );
|
||||
|
||||
unit_assert( infra_edns_update(slab, &one, onelen, zone, zonelen, -1, now) );
|
||||
unit_assert( infra_host(slab, &one, onelen, zone, zonelen,
|
||||
now, &vs, &edns_lame, &to) );
|
||||
unit_assert( vs == 0 && to == init && edns_lame == 1 );
|
||||
|
||||
unit_show_feature("infra cache probing (keep-probing off, default infra-cache-max-rtt)");
|
||||
test_keep_probing(slab, cfg, one, onelen, zone, zonelen, &now, 0, default_max_rtt);
|
||||
|
||||
unit_show_feature("infra cache probing (keep-probing on, default infra-cache-max-rtt)");
|
||||
test_keep_probing(slab, cfg, one, onelen, zone, zonelen, &now, 1, default_max_rtt);
|
||||
|
||||
unit_show_feature("infra cache probing (keep-probing off, low infra-cache-max-rtt)");
|
||||
test_keep_probing(slab, cfg, one, onelen, zone, zonelen, &now, 0, 3000);
|
||||
|
||||
unit_show_feature("infra cache probing (keep-probing on, low infra-cache-max-rtt)");
|
||||
test_keep_probing(slab, cfg, one, onelen, zone, zonelen, &now, 1, 3000);
|
||||
|
||||
/* Re-apply defaults for other unit tests that follow */
|
||||
config_apply_max_rtt(default_max_rtt);
|
||||
|
||||
infra_delete(slab);
|
||||
config_delete(cfg);
|
||||
}
|
||||
+6
-2
@@ -172,10 +172,14 @@ rr_test_file(const char* input, const char* check)
|
||||
if(txt_in[0] == 0 || txt_in[0] == '\n' || txt_in[0] == ';')
|
||||
continue;
|
||||
/* read check lines */
|
||||
if(!fgets(wire_chk, (int)bufs, chf))
|
||||
if(!fgets(wire_chk, (int)bufs, chf)) {
|
||||
printf("%s too short\n", check);
|
||||
if(!fgets(txt_chk, (int)bufs, chf))
|
||||
unit_assert(0);
|
||||
}
|
||||
if(!fgets(txt_chk, (int)bufs, chf)) {
|
||||
printf("%s too short\n", check);
|
||||
unit_assert(0);
|
||||
}
|
||||
chlineno += 2;
|
||||
if(vbmp) printf("%s:%d %s", check, chlineno-1, wire_chk);
|
||||
if(vbmp) printf("%s:%d %s", check, chlineno, txt_chk);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user