mirror of
https://github.com/NLnetLabs/unbound.git
synced 2026-08-17 21:25:50 +02:00
Compare commits
350
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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 | ||
|
|
3af4e44646 | ||
|
|
c3dd6a2dbd | ||
|
|
8fca3e7c5b | ||
|
|
8947c2c764 | ||
|
|
b1e3319a11 | ||
|
|
d52f501d90 | ||
|
|
7083d58c6b | ||
|
|
3adb9c8f92 | ||
|
|
51425b2388 | ||
|
|
d43760a8cd | ||
|
|
ea3e327006 | ||
|
|
be09350eca | ||
|
|
169acfc546 | ||
|
|
bed7cc2a90 | ||
|
|
02f4446833 | ||
|
|
c8a2289542 | ||
|
|
b53d90053e | ||
|
|
978b0696d3 | ||
|
|
ec5f86b4eb | ||
|
|
ec2f45c6fd | ||
|
|
6b319c97ee | ||
|
|
6eb3992c9e | ||
|
|
94a94fd8c8 | ||
|
|
36f9d1a2a9 | ||
|
|
d3a2264272 | ||
|
|
92b6c2a7b9 | ||
|
|
a335e601e4 | ||
|
|
a19009df1d | ||
|
|
96f8a94c19 | ||
|
|
2fe4e2ec3e | ||
|
|
e54928a628 | ||
|
|
538434186e | ||
|
|
65e7253d19 | ||
|
|
03ac902296 | ||
|
|
97ad1df343 | ||
|
|
2279cde8f7 | ||
|
|
ff653a7ef8 | ||
|
|
fd11cd9182 | ||
|
|
3953f827fb | ||
|
|
7fbc061846 | ||
|
|
70f73a33b3 | ||
|
|
b67fbb69e7 | ||
|
|
902c79608c | ||
|
|
08050dc939 | ||
|
|
9603924bb4 | ||
|
|
4c2da2b979 | ||
|
|
1974732d19 | ||
|
|
3cad5818a1 | ||
|
|
ad12109191 | ||
|
|
f611220eb8 | ||
|
|
86fe9cbce5 | ||
|
|
ac609fcbfc | ||
|
|
486985fbdf | ||
|
|
caab100207 | ||
|
|
4b30e88eec | ||
|
|
b6c7ea563f | ||
|
|
910d7cf446 | ||
|
|
cd485f2036 | ||
|
|
8ff1baf585 | ||
|
|
5fc4673901 | ||
|
|
faf3d358dc | ||
|
|
f5a2160ba3 | ||
|
|
0c0c36f015 | ||
|
|
47956de897 | ||
|
|
b30c869a59 | ||
|
|
6f030e9672 | ||
|
|
7107d3c9e7 | ||
|
|
fbdc06ebc4 | ||
|
|
d149e755fd | ||
|
|
86ee8ccd12 | ||
|
|
8d6a1ba811 | ||
|
|
9ccb8d5f20 | ||
|
|
8e43e2574c | ||
|
|
2e70506763 | ||
|
|
7f184c8ca8 | ||
|
|
da2b307aa3 | ||
|
|
739a88ceed | ||
|
|
3ff5c7a74d | ||
|
|
1048c4a28c | ||
|
|
7de009f99a | ||
|
|
95669855fb | ||
|
|
56e7cade28 | ||
|
|
c085a53268 | ||
|
|
49569b81aa | ||
|
|
4497e8a154 | ||
|
|
b9525c5fd4 | ||
|
|
c3206f4568 | ||
|
|
9abed3fc83 | ||
|
|
63a6b7b255 | ||
|
|
15dc8e8a3f | ||
|
|
cd4a017e96 | ||
|
|
82c0207fa6 | ||
|
|
7c5e765b3b | ||
|
|
f456d97a34 | ||
|
|
8b490b1540 | ||
|
|
b3951e5885 | ||
|
|
ced9762b14 | ||
|
|
9b9bba9f02 | ||
|
|
07859a9ef3 | ||
|
|
cb74467acb | ||
|
|
62dad42152 | ||
|
|
3ec74d1e3a | ||
|
|
52aff65e35 | ||
|
|
5994fb3db5 | ||
|
|
0dbcb45d28 | ||
|
|
d71f257215 | ||
|
|
b11d234f77 | ||
|
|
0d4c5aa421 | ||
|
|
9e60f93b84 | ||
|
|
9d63e8f093 | ||
|
|
4c40253df7 | ||
|
|
491b56d051 | ||
|
|
4d530920e0 | ||
|
|
08fb9a9209 | ||
|
|
04ff2672b5 | ||
|
|
d47849a26e | ||
|
|
63ee97d0fd | ||
|
|
bd74a32b79 | ||
|
|
b990be88ef | ||
|
|
cccf5e73c0 | ||
|
|
f3f85e5a11 | ||
|
|
d55511f1dd | ||
|
|
d98c7b9ae3 | ||
|
|
a30221c5bb | ||
|
|
411e843fc4 | ||
|
|
8575d5b35c | ||
|
|
ba16e41160 | ||
|
|
708d5229ae | ||
|
|
fb4a7d65d7 | ||
|
|
d7353e6e99 | ||
|
|
48113cfaba | ||
|
|
c0b5754ef7 | ||
|
|
f2fb498c69 | ||
|
|
91e8e0e511 | ||
|
|
dfff8d23cf | ||
|
|
103d9a68fa | ||
|
|
a814fe8c5f | ||
|
|
193401e754 | ||
|
|
e1aeabde44 | ||
|
|
6d1e61173b | ||
|
|
6f82b5be4a | ||
|
|
192f1b0e2b | ||
|
|
238a796e38 | ||
|
|
fe393ac355 | ||
|
|
3ea078baf6 | ||
|
|
eb3e1ae24f | ||
|
|
c2b20c585e | ||
|
|
07561964fc | ||
|
|
ce8c1ce5b0 | ||
|
|
ef60dcac31 | ||
|
|
73bd5a19aa | ||
|
|
fef974ca5c | ||
|
|
8dbf46913b | ||
|
|
e46b188fe8 | ||
|
|
e6b1f9a4c3 | ||
|
|
39cfc8c1c0 | ||
|
|
79e25e192c | ||
|
|
792089f523 | ||
|
|
34636caa2d | ||
|
|
2993437eaa | ||
|
|
0bcc8c0211 | ||
|
|
4b54d8e15e | ||
|
|
afe52595a9 | ||
|
|
4f417262e3 | ||
|
|
1db3b38104 | ||
|
|
bc47f50926 | ||
|
|
e36b5a099c | ||
|
|
025881d0e9 | ||
|
|
320d0a5f1b | ||
|
|
d382210fce | ||
|
|
7b62767e16 | ||
|
|
6568841bb0 | ||
|
|
e361f6b284 | ||
|
|
53766917ef | ||
|
|
2a255076f5 | ||
|
|
fb080e7853 | ||
|
|
0818841038 | ||
|
|
939baebfe7 | ||
|
|
326ba26522 | ||
|
|
ec0b510f1c | ||
|
|
be626f7c53 | ||
|
|
3096e4930e | ||
|
|
33bdf44a04 | ||
|
|
ccbe31c21f | ||
|
|
c6746499c1 | ||
|
|
e1229e375f | ||
|
|
be27499d39 | ||
|
|
56a2b564ef | ||
|
|
9a00877af9 | ||
|
|
54d86dd73b | ||
|
|
b496714caa | ||
|
|
3f5175584b | ||
|
|
11fff226f3 | ||
|
|
93490a0fc1 | ||
|
|
0585c3e5fd | ||
|
|
0b74f2a007 | ||
|
|
59d98b9ef6 | ||
|
|
3522451600 | ||
|
|
fe03bacd6c | ||
|
|
1f46d5945b | ||
|
|
585d73bf7c | ||
|
|
9e84cebfdb | ||
|
|
d1a2bd67da | ||
|
|
7708429d35 | ||
|
|
6045911d95 | ||
|
|
1b212aa073 | ||
|
|
4d48166835 | ||
|
|
437bac370a | ||
|
|
546062d3a3 | ||
|
|
576b93c99f | ||
|
|
180275c4e0 | ||
|
|
379e4b68f5 | ||
|
|
74b4d81992 | ||
|
|
fea8f0d5fd | ||
|
|
0e5dab5eaf | ||
|
|
c550bc154f | ||
|
|
40fcb91206 | ||
|
|
c8554ff48c | ||
|
|
3d95cef08c | ||
|
|
9cd724cf5e | ||
|
|
eb7eb5ce68 | ||
|
|
418eeb642c | ||
|
|
8ac56d004d | ||
|
|
52a76583c5 | ||
|
|
b1d02cc94f | ||
|
|
b9b488b6d3 | ||
|
|
9a2d0238a8 | ||
|
|
5cc21690eb | ||
|
|
f80f65d58c | ||
|
|
df284fbe65 | ||
|
|
b632ebf129 | ||
|
|
4b9cd8e81d | ||
|
|
6c82f4ae9b | ||
|
|
87644fa46b | ||
|
|
22dc376392 | ||
|
|
4ef1fb5a24 | ||
|
|
be6fd80a1c | ||
|
|
c48a467b8e | ||
|
|
557edbb84a | ||
|
|
0cfc6e6d95 | ||
|
|
2978106991 | ||
|
|
8517f49745 | ||
|
|
6c76b4e2f8 | ||
|
|
c91bd60051 | ||
|
|
a8739bad76 | ||
|
|
2b97442f2e | ||
|
|
5997355e22 | ||
|
|
d8bd9845cc | ||
|
|
3d1bc143af | ||
|
|
72a25f825c | ||
|
|
c4e0354876 | ||
|
|
389e820878 | ||
|
|
a2f0186427 | ||
|
|
58d670a258 | ||
|
|
ca88669435 | ||
|
|
15a9b0f2be | ||
|
|
197bf15402 | ||
|
|
0bae242cbf | ||
|
|
1d23e0c920 | ||
|
|
ad51795314 | ||
|
|
7d76e84953 | ||
|
|
c96e4ca121 |
@@ -32,12 +32,12 @@ jobs:
|
||||
- name: OS X
|
||||
os: macos-latest
|
||||
install_expat: "yes"
|
||||
config: "--enable-debug --disable-flto --with-ssl=/usr/local/opt/openssl --with-libexpat=/usr/local/opt/expat"
|
||||
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"
|
||||
config: "CC=clang --enable-debug --disable-flto --with-ssl=/usr/local/opt/openssl --with-libexpat=/usr/local/opt/expat --disable-static"
|
||||
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"
|
||||
- name: ubsan (gcc undefined behaviour sanitizer)
|
||||
@@ -161,9 +161,36 @@ 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@v3
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: false
|
||||
- name: test_windows
|
||||
@@ -181,21 +208,20 @@ jobs:
|
||||
export LEX="win_flex"
|
||||
echo 'YACC="win_bison -y"'
|
||||
export YACC="win_bison -y"
|
||||
#echo "curl cpanm"
|
||||
#curl -L -k -s -S -o cpanm https://cpanmin.us/
|
||||
#echo "perl cpanm Pod::Usage"
|
||||
#perl cpanm Pod::Usage
|
||||
mkdir openssl
|
||||
echo "curl openssl"
|
||||
curl -L -k -s -S -o openssl-1.1.1j.tar.gz https://www.openssl.org/source/openssl-1.1.1j.tar.gz
|
||||
tar xzf openssl-1.1.1j.tar.gz
|
||||
cd openssl-1.1.1j
|
||||
curl -L -k -s -S -o openssl-3.2.0.tar.gz https://www.openssl.org/source/openssl-3.2.0.tar.gz
|
||||
tar xzf openssl-3.2.0.tar.gz
|
||||
cd openssl-3.2.0
|
||||
# remove pod::Usage because we do not need -help or -man output
|
||||
# from the Configure script
|
||||
echo "Fixup ./Configure by removing use Pod::Usage require"
|
||||
sed -e 's/use Pod::Usage//' < Configure > Configure.fix
|
||||
echo "./Configure.fix no-shared no-asm -DOPENSSL_NO_CAPIENG mingw64 --prefix=\""$prepath/openssl\"""
|
||||
./Configure.fix no-shared no-asm -DOPENSSL_NO_CAPIENG mingw64 --prefix="$prepath/openssl"
|
||||
# from the Configure script, this fixes it for openssl 1.1.1
|
||||
#echo "Fixup ./Configure by removing use Pod::Usage require"
|
||||
#sed -e 's/use Pod::Usage//' < Configure > Configure.fix
|
||||
# ./Configure.fix no-shared no-asm -DOPENSSL_NO_CAPIENG mingw64 --prefix="$prepath/openssl"
|
||||
# pacman is used to install for msys2, with
|
||||
# C:/msys64/usr/bin/pacman -S perl
|
||||
echo "C:/msys64/usr/bin/perl ./Configure no-shared no-asm -DOPENSSL_NO_CAPIENG mingw64 --prefix=\""$prepath/openssl"\" PERL=\"C:/msys64/usr/bin/perl\""
|
||||
C:/msys64/usr/bin/perl ./Configure no-shared no-asm -DOPENSSL_NO_CAPIENG mingw64 --prefix="$prepath/openssl" PERL="C:/msys64/usr/bin/perl"
|
||||
# make the libs only, build faster
|
||||
echo "make build_libs"
|
||||
#make
|
||||
@@ -332,6 +358,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
|
||||
|
||||
@@ -12,7 +12,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- name: configure
|
||||
run: ./configure --enable-debug
|
||||
- name: make
|
||||
|
||||
@@ -10,6 +10,9 @@
|
||||
/config.status
|
||||
/dnstap/dnstap_config.h
|
||||
/dnscrypt/dnscrypt_config.h
|
||||
/util/configlexer.c
|
||||
/util/configparser.c
|
||||
/util/configparser.h
|
||||
/clubsyms.def
|
||||
/doc/example.conf
|
||||
/doc/libunbound.3
|
||||
@@ -33,6 +36,7 @@
|
||||
/asynclook
|
||||
/delayer
|
||||
/dohclient
|
||||
/doqclient
|
||||
/lock-verify
|
||||
/memstats
|
||||
/perf
|
||||
@@ -55,6 +59,7 @@
|
||||
/pythonmod/unboundmodule.py
|
||||
/testdata/result.*
|
||||
/testdata/.done-*
|
||||
/testdata/.skip-*
|
||||
/testdata/.perfstats.txt
|
||||
/doc/html
|
||||
/doc/xml
|
||||
|
||||
+26
-14
@@ -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
|
||||
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
|
||||
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)
|
||||
|
||||
@@ -439,7 +446,8 @@ unbound-control-setup: smallapp/unbound-control-setup.sh
|
||||
dnstap.lo dnstap.o: $(srcdir)/dnstap/dnstap.c config.h dnstap/dnstap_config.h \
|
||||
dnstap/dnstap.pb-c.c dnstap/dnstap.pb-c.h $(srcdir)/dnstap/dnstap.h \
|
||||
$(srcdir)/util/config_file.h $(srcdir)/util/log.h \
|
||||
$(srcdir)/util/netevent.h $(srcdir)/util/net_help.h
|
||||
$(srcdir)/util/netevent.h $(srcdir)/util/net_help.h \
|
||||
$(srcdir)/util/locks.h
|
||||
|
||||
dnstap/dnstap.pb-c.c dnstap/dnstap.pb-c.h: $(srcdir)/dnstap/dnstap.proto
|
||||
@-if test ! -d dnstap; then $(INSTALL) -d dnstap; fi
|
||||
@@ -702,6 +710,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 \
|
||||
@@ -1278,7 +1288,8 @@ daemon.lo daemon.o: $(srcdir)/daemon/daemon.c config.h $(srcdir)/daemon/daemon.h
|
||||
$(srcdir)/util/edns.h $(srcdir)/services/listen_dnsport.h $(srcdir)/services/cache/rrset.h \
|
||||
$(srcdir)/services/cache/infra.h $(srcdir)/util/rtt.h $(srcdir)/services/localzone.h \
|
||||
$(srcdir)/services/authzone.h $(srcdir)/services/mesh.h $(srcdir)/services/rpz.h $(srcdir)/respip/respip.h \
|
||||
$(srcdir)/util/random.h $(srcdir)/util/tube.h $(srcdir)/util/net_help.h $(srcdir)/sldns/keyraw.h
|
||||
$(srcdir)/util/random.h $(srcdir)/util/tube.h $(srcdir)/util/net_help.h $(srcdir)/sldns/keyraw.h \
|
||||
$(srcdir)/iterator/iter_fwd.h $(srcdir)/iterator/iter_hints.h
|
||||
remote.lo remote.o: $(srcdir)/daemon/remote.c config.h $(srcdir)/daemon/remote.h $(srcdir)/daemon/worker.h \
|
||||
$(srcdir)/libunbound/worker.h $(srcdir)/sldns/sbuffer.h $(srcdir)/util/data/packed_rrset.h \
|
||||
$(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/netevent.h \
|
||||
@@ -1296,7 +1307,7 @@ 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
|
||||
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 \
|
||||
@@ -1355,7 +1366,7 @@ testbound.lo testbound.o: $(srcdir)/testcode/testbound.c config.h $(srcdir)/test
|
||||
$(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/tube.h \
|
||||
$(srcdir)/services/mesh.h $(srcdir)/services/rpz.h $(srcdir)/services/localzone.h $(srcdir)/services/view.h \
|
||||
$(srcdir)/services/authzone.h $(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h $(srcdir)/libunbound/unbound.h \
|
||||
$(srcdir)/respip/respip.h $(srcdir)/util/net_help.h $(srcdir)/util/ub_event.h
|
||||
$(srcdir)/respip/respip.h $(srcdir)/util/net_help.h $(srcdir)/util/ub_event.h $(srcdir)/daemon/worker.h
|
||||
testpkts.lo testpkts.o: $(srcdir)/testcode/testpkts.c config.h $(srcdir)/testcode/testpkts.h \
|
||||
$(srcdir)/util/net_help.h $(srcdir)/util/log.h $(srcdir)/sldns/sbuffer.h $(srcdir)/sldns/rrdef.h $(srcdir)/sldns/pkthdr.h \
|
||||
$(srcdir)/sldns/str2wire.h $(srcdir)/sldns/wire2str.h
|
||||
@@ -1428,7 +1439,7 @@ fake_event.lo fake_event.o: $(srcdir)/testcode/fake_event.c config.h $(srcdir)/t
|
||||
$(srcdir)/util/tube.h $(srcdir)/services/mesh.h $(srcdir)/services/modstack.h $(srcdir)/services/rpz.h \
|
||||
$(srcdir)/services/localzone.h $(srcdir)/services/view.h $(srcdir)/sldns/sbuffer.h $(srcdir)/services/authzone.h \
|
||||
$(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h $(srcdir)/libunbound/unbound.h $(srcdir)/respip/respip.h \
|
||||
$(srcdir)/sldns/wire2str.h $(srcdir)/sldns/str2wire.h $(srcdir)/daemon/remote.h
|
||||
$(srcdir)/sldns/wire2str.h $(srcdir)/sldns/str2wire.h $(srcdir)/daemon/remote.h $(srcdir)/util/storage/slabhash.h $(srcdir)/daemon/daemon.h
|
||||
lock_verify.lo lock_verify.o: $(srcdir)/testcode/lock_verify.c config.h $(srcdir)/util/log.h $(srcdir)/util/rbtree.h \
|
||||
$(srcdir)/util/locks.h $(srcdir)/util/fptr_wlist.h $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
|
||||
$(srcdir)/util/storage/lruhash.h $(srcdir)/util/module.h \
|
||||
@@ -1484,7 +1495,8 @@ context.lo context.o: $(srcdir)/libunbound/context.c config.h $(srcdir)/libunbou
|
||||
$(srcdir)/util/storage/slabhash.h $(srcdir)/services/cache/infra.h $(srcdir)/util/rtt.h \
|
||||
$(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
|
||||
$(srcdir)/services/authzone.h $(srcdir)/services/mesh.h $(srcdir)/services/rpz.h $(srcdir)/daemon/stats.h \
|
||||
$(srcdir)/util/timehist.h $(srcdir)/respip/respip.h $(srcdir)/util/edns.h
|
||||
$(srcdir)/util/timehist.h $(srcdir)/respip/respip.h $(srcdir)/util/edns.h \
|
||||
$(srcdir)/iterator/iter_fwd.h $(srcdir)/iterator/iter_hints.h
|
||||
libunbound.lo libunbound.o: $(srcdir)/libunbound/libunbound.c $(srcdir)/libunbound/unbound.h \
|
||||
$(srcdir)/libunbound/unbound-event.h config.h $(srcdir)/libunbound/context.h $(srcdir)/util/locks.h \
|
||||
$(srcdir)/util/log.h $(srcdir)/util/alloc.h $(srcdir)/util/rbtree.h $(srcdir)/services/modstack.h \
|
||||
@@ -1496,7 +1508,8 @@ libunbound.lo libunbound.o: $(srcdir)/libunbound/libunbound.c $(srcdir)/libunbou
|
||||
$(srcdir)/sldns/sbuffer.h $(srcdir)/services/cache/infra.h $(srcdir)/util/rtt.h $(srcdir)/util/netevent.h \
|
||||
$(srcdir)/dnscrypt/dnscrypt.h $(srcdir)/services/cache/rrset.h \
|
||||
$(srcdir)/util/storage/slabhash.h $(srcdir)/services/authzone.h $(srcdir)/services/mesh.h \
|
||||
$(srcdir)/services/rpz.h $(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h $(srcdir)/respip/respip.h
|
||||
$(srcdir)/services/rpz.h $(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h $(srcdir)/respip/respip.h \
|
||||
$(srcdir)/iterator/iter_fwd.h $(srcdir)/iterator/iter_hints.h
|
||||
libworker.lo libworker.o: $(srcdir)/libunbound/libworker.c config.h $(srcdir)/libunbound/libworker.h \
|
||||
$(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \
|
||||
$(srcdir)/libunbound/context.h $(srcdir)/util/alloc.h $(srcdir)/util/rbtree.h $(srcdir)/services/modstack.h \
|
||||
@@ -1510,8 +1523,7 @@ libworker.lo libworker.o: $(srcdir)/libunbound/libworker.c config.h $(srcdir)/li
|
||||
$(srcdir)/services/cache/rrset.h $(srcdir)/util/storage/slabhash.h $(srcdir)/services/outbound_list.h \
|
||||
$(srcdir)/util/fptr_wlist.h $(srcdir)/util/tube.h $(srcdir)/util/regional.h $(srcdir)/util/random.h \
|
||||
$(srcdir)/util/storage/lookup3.h $(srcdir)/util/net_help.h $(srcdir)/util/data/dname.h \
|
||||
$(srcdir)/util/data/msgencode.h $(srcdir)/iterator/iter_fwd.h $(srcdir)/iterator/iter_hints.h \
|
||||
$(srcdir)/sldns/str2wire.h
|
||||
$(srcdir)/util/data/msgencode.h $(srcdir)/sldns/str2wire.h
|
||||
unbound-host.lo unbound-host.o: $(srcdir)/smallapp/unbound-host.c config.h $(srcdir)/libunbound/unbound.h \
|
||||
$(srcdir)/sldns/rrdef.h $(srcdir)/sldns/wire2str.h
|
||||
asynclook.lo asynclook.o: $(srcdir)/testcode/asynclook.c config.h $(srcdir)/libunbound/unbound.h \
|
||||
|
||||
+88
-33
@@ -2,7 +2,10 @@
|
||||
# Copyright 2009, Wouter Wijngaards, NLnet Labs.
|
||||
# BSD licensed.
|
||||
#
|
||||
# Version 46
|
||||
# Version 48
|
||||
# 2024-01-16 fix to add -l:libssp.a to -lcrypto link check.
|
||||
# and check for getaddrinfo with only header.
|
||||
# 2024-01-15 fix to add crypt32 to -lcrypto link check when checking for gdi32.
|
||||
# 2023-05-04 fix to remove unused whitespace.
|
||||
# 2023-01-26 fix -Wstrict-prototypes.
|
||||
# 2022-09-01 fix checking if nonblocking sockets work on OpenBSD.
|
||||
@@ -707,7 +710,7 @@ AC_DEFUN([ACX_SSL_CHECKS], [
|
||||
LIBSSL_LDFLAGS="$LIBSSL_LDFLAGS -L$ssldir_lib"
|
||||
ACX_RUNTIME_PATH_ADD([$ssldir_lib])
|
||||
fi
|
||||
|
||||
|
||||
AC_MSG_CHECKING([for EVP_sha256 in -lcrypto])
|
||||
LIBS="$LIBS -lcrypto"
|
||||
LIBSSL_LIBS="$LIBSSL_LIBS -lcrypto"
|
||||
@@ -732,40 +735,73 @@ AC_DEFUN([ACX_SSL_CHECKS], [
|
||||
]])],[
|
||||
AC_DEFINE([HAVE_EVP_SHA256], 1,
|
||||
[If you have EVP_sha256])
|
||||
AC_MSG_RESULT(yes)
|
||||
AC_MSG_RESULT(yes)
|
||||
],[
|
||||
AC_MSG_RESULT(no)
|
||||
LIBS="$BAKLIBS"
|
||||
LIBSSL_LIBS="$BAKSSLLIBS"
|
||||
LIBS="$LIBS -ldl"
|
||||
LIBSSL_LIBS="$LIBSSL_LIBS -ldl"
|
||||
AC_MSG_CHECKING([if -lcrypto needs -ldl])
|
||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[
|
||||
int EVP_sha256(void);
|
||||
(void)EVP_sha256();
|
||||
]])],[
|
||||
AC_DEFINE([HAVE_EVP_SHA256], 1,
|
||||
[If you have EVP_sha256])
|
||||
AC_MSG_RESULT(yes)
|
||||
],[
|
||||
AC_MSG_RESULT(no)
|
||||
LIBS="$BAKLIBS"
|
||||
LIBSSL_LIBS="$BAKSSLLIBS"
|
||||
LIBS="$LIBS -ldl -pthread"
|
||||
LIBSSL_LIBS="$LIBSSL_LIBS -ldl -pthread"
|
||||
AC_MSG_CHECKING([if -lcrypto needs -ldl -pthread])
|
||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[
|
||||
int EVP_sha256(void);
|
||||
(void)EVP_sha256();
|
||||
]])],[
|
||||
AC_DEFINE([HAVE_EVP_SHA256], 1,
|
||||
[If you have EVP_sha256])
|
||||
AC_MSG_RESULT(yes)
|
||||
],[
|
||||
AC_MSG_RESULT(no)
|
||||
AC_MSG_ERROR([OpenSSL found in $ssldir, but version 0.9.7 or higher is required])
|
||||
|
||||
LIBS="$LIBS -lgdi32 -lws2_32 -lcrypt32"
|
||||
LIBSSL_LIBS="$LIBSSL_LIBS -lgdi32 -lws2_32 -lcrypt32"
|
||||
AC_MSG_CHECKING([if -lcrypto needs -lgdi32 -lws2_32 -lcrypt32])
|
||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[
|
||||
int EVP_sha256(void);
|
||||
(void)EVP_sha256();
|
||||
]])],[
|
||||
AC_DEFINE([HAVE_EVP_SHA256], 1,
|
||||
[If you have EVP_sha256])
|
||||
AC_MSG_RESULT(yes)
|
||||
],[
|
||||
AC_MSG_RESULT(no)
|
||||
LIBS="$BAKLIBS"
|
||||
LIBSSL_LIBS="$BAKSSLLIBS"
|
||||
|
||||
LIBS="$LIBS -lgdi32 -lws2_32 -lcrypt32 -l:libssp.a"
|
||||
LIBSSL_LIBS="$LIBSSL_LIBS -lgdi32 -lws2_32 -lcrypt32 -l:libssp.a"
|
||||
AC_MSG_CHECKING([if -lcrypto needs -lgdi32 -lws2_32 -lcrypt32 -l:libssp.a])
|
||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[
|
||||
int EVP_sha256(void);
|
||||
(void)EVP_sha256();
|
||||
]])],[
|
||||
AC_DEFINE([HAVE_EVP_SHA256], 1,
|
||||
[If you have EVP_sha256])
|
||||
AC_MSG_RESULT(yes)
|
||||
],[
|
||||
AC_MSG_RESULT(no)
|
||||
LIBS="$BAKLIBS"
|
||||
LIBSSL_LIBS="$BAKSSLLIBS"
|
||||
|
||||
LIBS="$LIBS -ldl"
|
||||
LIBSSL_LIBS="$LIBSSL_LIBS -ldl"
|
||||
AC_MSG_CHECKING([if -lcrypto needs -ldl])
|
||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[
|
||||
int EVP_sha256(void);
|
||||
(void)EVP_sha256();
|
||||
]])],[
|
||||
AC_DEFINE([HAVE_EVP_SHA256], 1,
|
||||
[If you have EVP_sha256])
|
||||
AC_MSG_RESULT(yes)
|
||||
],[
|
||||
AC_MSG_RESULT(no)
|
||||
LIBS="$BAKLIBS"
|
||||
LIBSSL_LIBS="$BAKSSLLIBS"
|
||||
LIBS="$LIBS -ldl -pthread"
|
||||
LIBSSL_LIBS="$LIBSSL_LIBS -ldl -pthread"
|
||||
AC_MSG_CHECKING([if -lcrypto needs -ldl -pthread])
|
||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[
|
||||
int EVP_sha256(void);
|
||||
(void)EVP_sha256();
|
||||
]])],[
|
||||
AC_DEFINE([HAVE_EVP_SHA256], 1,
|
||||
[If you have EVP_sha256])
|
||||
AC_MSG_RESULT(yes)
|
||||
],[
|
||||
AC_MSG_RESULT(no)
|
||||
AC_MSG_ERROR([OpenSSL found in $ssldir, but version 0.9.7 or higher is required])
|
||||
])
|
||||
])
|
||||
])
|
||||
])
|
||||
])
|
||||
])
|
||||
])
|
||||
fi
|
||||
@@ -779,7 +815,7 @@ AC_CHECK_HEADERS([openssl/rand.h],,, [AC_INCLUDES_DEFAULT])
|
||||
|
||||
dnl Check for SSL, where SSL is mandatory
|
||||
dnl Adds --with-ssl option, searches for openssl and defines HAVE_SSL if found
|
||||
dnl Setup of CPPFLAGS, CFLAGS. Adds -lcrypto to LIBS.
|
||||
dnl Setup of CPPFLAGS, CFLAGS. Adds -lcrypto to LIBS.
|
||||
dnl Checks main header files of SSL.
|
||||
dnl
|
||||
AC_DEFUN([ACX_WITH_SSL],
|
||||
@@ -872,7 +908,7 @@ dnl see if on windows
|
||||
if test "$ac_cv_header_windows_h" = "yes"; then
|
||||
AC_DEFINE(USE_WINSOCK, 1, [Whether the windows socket API is used])
|
||||
USE_WINSOCK="1"
|
||||
if echo $LIBS | grep 'lws2_32' >/dev/null; then
|
||||
if echo "$LIBS" | grep 'lws2_32' >/dev/null; then
|
||||
:
|
||||
else
|
||||
LIBS="$LIBS -lws2_32"
|
||||
@@ -880,6 +916,24 @@ if test "$ac_cv_header_windows_h" = "yes"; then
|
||||
fi
|
||||
],
|
||||
dnl no quick getaddrinfo, try mingw32 and winsock2 library.
|
||||
dnl perhaps getaddrinfo needs only the include
|
||||
AC_LINK_IFELSE(
|
||||
[AC_LANG_PROGRAM(
|
||||
[
|
||||
#ifdef HAVE_WS2TCPIP_H
|
||||
#include <ws2tcpip.h>
|
||||
#endif
|
||||
],
|
||||
[
|
||||
(void)getaddrinfo(NULL, NULL, NULL, NULL);
|
||||
]
|
||||
)],
|
||||
[
|
||||
ac_cv_func_getaddrinfo="yes"
|
||||
AC_DEFINE(USE_WINSOCK, 1, [Whether the windows socket API is used])
|
||||
USE_WINSOCK="1"
|
||||
],
|
||||
|
||||
ORIGLIBS="$LIBS"
|
||||
LIBS="$LIBS -lws2_32"
|
||||
AC_LINK_IFELSE(
|
||||
@@ -904,6 +958,7 @@ ac_cv_func_getaddrinfo="no"
|
||||
LIBS="$ORIGLIBS"
|
||||
])
|
||||
)
|
||||
)
|
||||
|
||||
AC_MSG_RESULT($ac_cv_func_getaddrinfo)
|
||||
if test $ac_cv_func_getaddrinfo = yes; then
|
||||
|
||||
+1
-1
@@ -9,7 +9,7 @@ AC_DEFUN([AC_PYTHON_DEVEL],[
|
||||
|
||||
AC_PATH_PROG([PYTHON],[python[$PYTHON_VERSION]])
|
||||
if test -z "$PYTHON"; then
|
||||
AC_MSG_ERROR([Cannot find python$PYTHON_VERSION in your system path])
|
||||
AC_MSG_ERROR([Cannot find 'python$PYTHON_VERSION' in your system path. You can use the environment variable 'PYTHON_VERSION=version_number' for an explicit version.])
|
||||
PYTHON_VERSION=""
|
||||
fi
|
||||
|
||||
|
||||
@@ -1,39 +1,43 @@
|
||||
# ===========================================================================
|
||||
# http://autoconf-archive.cryp.to/ac_pkg_swig.html
|
||||
# https://www.gnu.org/software/autoconf-archive/ax_pkg_swig.html
|
||||
# ===========================================================================
|
||||
#
|
||||
# SYNOPSIS
|
||||
#
|
||||
# AC_PROG_SWIG([major.minor.micro])
|
||||
# AX_PKG_SWIG([major.minor.micro], [action-if-found], [action-if-not-found])
|
||||
#
|
||||
# DESCRIPTION
|
||||
#
|
||||
# This macro searches for a SWIG installation on your system. If found you
|
||||
# should call SWIG via $(SWIG). You can use the optional first argument to
|
||||
# check if the version of the available SWIG is greater than or equal to
|
||||
# the value of the argument. It should have the format: N[.N[.N]] (N is a
|
||||
# number between 0 and 999. Only the first N is mandatory.)
|
||||
# This macro searches for a SWIG installation on your system. If found,
|
||||
# then SWIG is AC_SUBST'd; if not found, then $SWIG is empty. If SWIG is
|
||||
# found, then SWIG_LIB is set to the SWIG library path, and AC_SUBST'd.
|
||||
#
|
||||
# If the version argument is given (e.g. 1.3.17), AC_PROG_SWIG checks that
|
||||
# the swig package is this version number or higher.
|
||||
# You can use the optional first argument to check if the version of the
|
||||
# available SWIG is greater than or equal to the value of the argument. It
|
||||
# should have the format: N[.N[.N]] (N is a number between 0 and 999. Only
|
||||
# the first N is mandatory.) If the version argument is given (e.g.
|
||||
# 1.3.17), AX_PKG_SWIG checks that the swig package is this version number
|
||||
# or higher.
|
||||
#
|
||||
# As usual, action-if-found is executed if SWIG is found, otherwise
|
||||
# action-if-not-found is executed.
|
||||
#
|
||||
# In configure.in, use as:
|
||||
#
|
||||
# AC_PROG_SWIG(1.3.17)
|
||||
# SWIG_ENABLE_CXX
|
||||
# SWIG_MULTI_MODULE_SUPPORT
|
||||
# SWIG_PYTHON
|
||||
# AX_PKG_SWIG(1.3.17, [], [ AC_MSG_ERROR([SWIG is required to build..]) ])
|
||||
# AX_SWIG_ENABLE_CXX
|
||||
# AX_SWIG_MULTI_MODULE_SUPPORT
|
||||
# AX_SWIG_PYTHON
|
||||
#
|
||||
# LAST MODIFICATION
|
||||
#
|
||||
# 2008-04-12
|
||||
#
|
||||
# COPYLEFT
|
||||
# LICENSE
|
||||
#
|
||||
# Copyright (c) 2008 Sebastian Huber <sebastian-huber@web.de>
|
||||
# Copyright (c) 2008 Alan W. Irwin <irwin@beluga.phys.uvic.ca>
|
||||
# Copyright (c) 2008 Alan W. Irwin
|
||||
# Copyright (c) 2008 Rafael Laboissiere <rafael@laboissiere.net>
|
||||
# Copyright (c) 2008 Andrew Collier <colliera@ukzn.ac.za>
|
||||
# Copyright (c) 2008 Andrew Collier
|
||||
# Copyright (c) 2011 Murray Cumming <murrayc@openismus.com>
|
||||
# Copyright (c) 2018 Reini Urban <rurban@cpan.org>
|
||||
# Copyright (c) 2021 Vincent Danjean <Vincent.Danjean@ens-lyon.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
|
||||
@@ -46,7 +50,7 @@
|
||||
# Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along
|
||||
# with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
# 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
|
||||
@@ -57,17 +61,21 @@
|
||||
# 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 Macro 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.
|
||||
# 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.
|
||||
|
||||
AC_DEFUN([AC_PROG_SWIG],[
|
||||
AC_PATH_PROG([SWIG],[swig])
|
||||
#serial 15
|
||||
|
||||
AC_DEFUN([AX_PKG_SWIG],[
|
||||
# Find path to the "swig" executable.
|
||||
AC_PATH_PROGS([SWIG],[swig swig3.0 swig2.0])
|
||||
if test -z "$SWIG" ; then
|
||||
AC_MSG_WARN([cannot find 'swig' program. You should look at http://www.swig.org])
|
||||
SWIG='echo "Error: SWIG is not installed. You should look at http://www.swig.org" ; false'
|
||||
elif test -n "$1" ; then
|
||||
AC_MSG_CHECKING([for SWIG version])
|
||||
m4_ifval([$3],[$3],[:])
|
||||
elif test -z "$1" ; then
|
||||
m4_ifval([$2],[$2],[:])
|
||||
else
|
||||
AC_MSG_CHECKING([SWIG version])
|
||||
[swig_version=`$SWIG -version 2>&1 | grep 'SWIG Version' | sed 's/.*\([0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\).*/\1/g'`]
|
||||
AC_MSG_RESULT([$swig_version])
|
||||
if test -n "$swig_version" ; then
|
||||
@@ -77,12 +85,12 @@ AC_DEFUN([AC_PROG_SWIG],[
|
||||
if test -z "$required_major" ; then
|
||||
[required_major=0]
|
||||
fi
|
||||
[required=`echo $required | sed 's/[0-9]*[^0-9]//'`]
|
||||
[required=`echo $required. | sed 's/[0-9]*[^0-9]//'`]
|
||||
[required_minor=`echo $required | sed 's/[^0-9].*//'`]
|
||||
if test -z "$required_minor" ; then
|
||||
[required_minor=0]
|
||||
fi
|
||||
[required=`echo $required | sed 's/[0-9]*[^0-9]//'`]
|
||||
[required=`echo $required. | sed 's/[0-9]*[^0-9]//'`]
|
||||
[required_patch=`echo $required | sed 's/[^0-9].*//'`]
|
||||
if test -z "$required_patch" ; then
|
||||
[required_patch=0]
|
||||
@@ -103,30 +111,28 @@ AC_DEFUN([AC_PROG_SWIG],[
|
||||
if test -z "$available_patch" ; then
|
||||
[available_patch=0]
|
||||
fi
|
||||
[badversion=0]
|
||||
if test $available_major -lt $required_major ; then
|
||||
[badversion=1]
|
||||
fi
|
||||
if test $available_major -eq $required_major \
|
||||
-a $available_minor -lt $required_minor ; then
|
||||
[badversion=1]
|
||||
fi
|
||||
if test $available_major -eq $required_major \
|
||||
-a $available_minor -eq $required_minor \
|
||||
-a $available_patch -lt $required_patch ; then
|
||||
[badversion=1]
|
||||
fi
|
||||
if test $badversion -eq 1 ; then
|
||||
AC_MSG_WARN([SWIG version >= $1 is required. You have $swig_version. You should look at http://www.swig.org])
|
||||
SWIG='echo "Error: SWIG version >= $1 is required. You have '"$swig_version"'. You should look at http://www.swig.org" ; false'
|
||||
# Convert the version tuple into a single number for easier comparison.
|
||||
# Using base 100 should be safe since SWIG internally uses BCD values
|
||||
# to encode its version number.
|
||||
required_swig_vernum=`expr $required_major \* 10000 \
|
||||
\+ $required_minor \* 100 \+ $required_patch`
|
||||
available_swig_vernum=`expr $available_major \* 10000 \
|
||||
\+ $available_minor \* 100 \+ $available_patch`
|
||||
|
||||
if test $available_swig_vernum -lt $required_swig_vernum; then
|
||||
AC_MSG_WARN([SWIG version >= $1 is required. You have $swig_version.])
|
||||
SWIG=''
|
||||
m4_ifval([$3],[$3],[])
|
||||
else
|
||||
AC_MSG_NOTICE([SWIG executable is '$SWIG'])
|
||||
SWIG_LIB=`$SWIG -swiglib`
|
||||
AC_MSG_NOTICE([SWIG library directory is '$SWIG_LIB'])
|
||||
AC_MSG_CHECKING([for SWIG library])
|
||||
SWIG_LIB=`$SWIG -swiglib | tr '\r\n' ' '`
|
||||
AC_MSG_RESULT([$SWIG_LIB])
|
||||
m4_ifval([$2],[$2],[])
|
||||
fi
|
||||
else
|
||||
AC_MSG_WARN([cannot determine SWIG version])
|
||||
SWIG='echo "Error: Cannot determine SWIG version. You should look at http://www.swig.org" ; false'
|
||||
SWIG=''
|
||||
m4_ifval([$3],[$3],[])
|
||||
fi
|
||||
fi
|
||||
AC_SUBST([SWIG_LIB])
|
||||
+317
-127
@@ -1,5 +1,5 @@
|
||||
# ===========================================================================
|
||||
# http://www.gnu.org/software/autoconf-archive/ax_pthread.html
|
||||
# https://www.gnu.org/software/autoconf-archive/ax_pthread.html
|
||||
# ===========================================================================
|
||||
#
|
||||
# SYNOPSIS
|
||||
@@ -14,24 +14,28 @@
|
||||
# flags that are needed. (The user can also force certain compiler
|
||||
# flags/libs to be tested by setting these environment variables.)
|
||||
#
|
||||
# Also sets PTHREAD_CC to any special C compiler that is needed for
|
||||
# multi-threaded programs (defaults to the value of CC otherwise). (This
|
||||
# is necessary on AIX to use the special cc_r compiler alias.)
|
||||
# Also sets PTHREAD_CC and PTHREAD_CXX to any special C compiler that is
|
||||
# needed for multi-threaded programs (defaults to the value of CC
|
||||
# respectively CXX otherwise). (This is necessary on e.g. AIX to use the
|
||||
# special cc_r/CC_r compiler alias.)
|
||||
#
|
||||
# NOTE: You are assumed to not only compile your program with these flags,
|
||||
# but also link it with them as well. e.g. you should link with
|
||||
# but also to link with them as well. For example, you might link with
|
||||
# $PTHREAD_CC $CFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS $LIBS
|
||||
# $PTHREAD_CXX $CXXFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS $LIBS
|
||||
#
|
||||
# If you are only building threads programs, you may wish to use these
|
||||
# If you are only building threaded programs, you may wish to use these
|
||||
# variables in your default LIBS, CFLAGS, and CC:
|
||||
#
|
||||
# LIBS="$PTHREAD_LIBS $LIBS"
|
||||
# CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
|
||||
# CXXFLAGS="$CXXFLAGS $PTHREAD_CFLAGS"
|
||||
# CC="$PTHREAD_CC"
|
||||
# CXX="$PTHREAD_CXX"
|
||||
#
|
||||
# In addition, if the PTHREAD_CREATE_JOINABLE thread-attribute constant
|
||||
# has a nonstandard name, defines PTHREAD_CREATE_JOINABLE to that name
|
||||
# (e.g. PTHREAD_CREATE_UNDETACHED on AIX).
|
||||
# has a nonstandard name, this macro defines PTHREAD_CREATE_JOINABLE to
|
||||
# that name (e.g. PTHREAD_CREATE_UNDETACHED on AIX).
|
||||
#
|
||||
# Also HAVE_PTHREAD_PRIO_INHERIT is defined if pthread is found and the
|
||||
# PTHREAD_PRIO_INHERIT symbol is defined when compiling with
|
||||
@@ -55,6 +59,7 @@
|
||||
#
|
||||
# Copyright (c) 2008 Steven G. Johnson <stevenj@alum.mit.edu>
|
||||
# Copyright (c) 2011 Daniel Richard G. <skunk@iSKUNK.ORG>
|
||||
# Copyright (c) 2019 Marc Stevens <marc.stevens@cwi.nl>
|
||||
#
|
||||
# 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
|
||||
@@ -67,7 +72,7 @@
|
||||
# Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along
|
||||
# with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
# 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
|
||||
@@ -82,35 +87,41 @@
|
||||
# modified version of the Autoconf Macro, you may extend this special
|
||||
# exception to the GPL to apply to your modified version as well.
|
||||
|
||||
#serial 21
|
||||
#serial 31
|
||||
|
||||
AU_ALIAS([ACX_PTHREAD], [AX_PTHREAD])
|
||||
AC_DEFUN([AX_PTHREAD], [
|
||||
AC_REQUIRE([AC_CANONICAL_HOST])
|
||||
AC_REQUIRE([AC_PROG_CC])
|
||||
AC_REQUIRE([AC_PROG_SED])
|
||||
AC_LANG_PUSH([C])
|
||||
ax_pthread_ok=no
|
||||
|
||||
# We used to check for pthread.h first, but this fails if pthread.h
|
||||
# requires special compiler flags (e.g. on True64 or Sequent).
|
||||
# requires special compiler flags (e.g. on Tru64 or Sequent).
|
||||
# It gets checked for in the link test anyway.
|
||||
|
||||
# First of all, check if the user has set any of the PTHREAD_LIBS,
|
||||
# etcetera environment variables, and if threads linking works using
|
||||
# them:
|
||||
if test x"$PTHREAD_LIBS$PTHREAD_CFLAGS" != x; then
|
||||
save_CFLAGS="$CFLAGS"
|
||||
if test "x$PTHREAD_CFLAGS$PTHREAD_LIBS" != "x"; then
|
||||
ax_pthread_save_CC="$CC"
|
||||
ax_pthread_save_CFLAGS="$CFLAGS"
|
||||
ax_pthread_save_LIBS="$LIBS"
|
||||
AS_IF([test "x$PTHREAD_CC" != "x"], [CC="$PTHREAD_CC"])
|
||||
AS_IF([test "x$PTHREAD_CXX" != "x"], [CXX="$PTHREAD_CXX"])
|
||||
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
|
||||
save_LIBS="$LIBS"
|
||||
LIBS="$PTHREAD_LIBS $LIBS"
|
||||
AC_MSG_CHECKING([for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS])
|
||||
AC_TRY_LINK_FUNC([pthread_join], [ax_pthread_ok=yes])
|
||||
AC_MSG_CHECKING([for pthread_join using $CC $PTHREAD_CFLAGS $PTHREAD_LIBS])
|
||||
AC_LINK_IFELSE([AC_LANG_CALL([], [pthread_join])], [ax_pthread_ok=yes])
|
||||
AC_MSG_RESULT([$ax_pthread_ok])
|
||||
if test x"$ax_pthread_ok" = xno; then
|
||||
if test "x$ax_pthread_ok" = "xno"; then
|
||||
PTHREAD_LIBS=""
|
||||
PTHREAD_CFLAGS=""
|
||||
fi
|
||||
LIBS="$save_LIBS"
|
||||
CFLAGS="$save_CFLAGS"
|
||||
CC="$ax_pthread_save_CC"
|
||||
CFLAGS="$ax_pthread_save_CFLAGS"
|
||||
LIBS="$ax_pthread_save_LIBS"
|
||||
fi
|
||||
|
||||
# We must check for the threads library under a number of different
|
||||
@@ -118,12 +129,14 @@ fi
|
||||
# (e.g. DEC) have both -lpthread and -lpthreads, where one of the
|
||||
# libraries is broken (non-POSIX).
|
||||
|
||||
# Create a list of thread flags to try. Items starting with a "-" are
|
||||
# C compiler flags, and other items are library names, except for "none"
|
||||
# which indicates that we try without any flags at all, and "pthread-config"
|
||||
# which is a program returning the flags for the Pth emulation library.
|
||||
# Create a list of thread flags to try. Items with a "," contain both
|
||||
# C compiler flags (before ",") and linker flags (after ","). Other items
|
||||
# starting with a "-" are C compiler flags, and remaining items are
|
||||
# library names, except for "none" which indicates that we try without
|
||||
# any flags at all, and "pthread-config" which is a program returning
|
||||
# the flags for the Pth emulation library.
|
||||
|
||||
ax_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config"
|
||||
ax_pthread_flags="pthreads none -Kthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config"
|
||||
|
||||
# The ordering *is* (sometimes) important. Some notes on the
|
||||
# individual items follow:
|
||||
@@ -132,82 +145,163 @@ ax_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -mt
|
||||
# none: in case threads are in libc; should be tried before -Kthread and
|
||||
# other compiler flags to prevent continual compiler warnings
|
||||
# -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h)
|
||||
# -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able)
|
||||
# lthread: LinuxThreads port on FreeBSD (also preferred to -pthread)
|
||||
# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads)
|
||||
# -pthreads: Solaris/gcc
|
||||
# -mthreads: Mingw32/gcc, Lynx/gcc
|
||||
# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads), Tru64
|
||||
# (Note: HP C rejects this with "bad form for `-t' option")
|
||||
# -pthreads: Solaris/gcc (Note: HP C also rejects)
|
||||
# -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it
|
||||
# doesn't hurt to check since this sometimes defines pthreads too;
|
||||
# also defines -D_REENTRANT)
|
||||
# ... -mt is also the pthreads flag for HP/aCC
|
||||
# doesn't hurt to check since this sometimes defines pthreads and
|
||||
# -D_REENTRANT too), HP C (must be checked before -lpthread, which
|
||||
# is present but should not be used directly; and before -mthreads,
|
||||
# because the compiler interprets this as "-mt" + "-hreads")
|
||||
# -mthreads: Mingw32/gcc, Lynx/gcc
|
||||
# pthread: Linux, etcetera
|
||||
# --thread-safe: KAI C++
|
||||
# pthread-config: use pthread-config program (for GNU Pth library)
|
||||
|
||||
case ${host_os} in
|
||||
case $host_os in
|
||||
|
||||
freebsd*)
|
||||
|
||||
# -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able)
|
||||
# lthread: LinuxThreads port on FreeBSD (also preferred to -pthread)
|
||||
|
||||
ax_pthread_flags="-kthread lthread $ax_pthread_flags"
|
||||
;;
|
||||
|
||||
hpux*)
|
||||
|
||||
# From the cc(1) man page: "[-mt] Sets various -D flags to enable
|
||||
# multi-threading and also sets -lpthread."
|
||||
|
||||
ax_pthread_flags="-mt -pthread pthread $ax_pthread_flags"
|
||||
;;
|
||||
|
||||
openedition*)
|
||||
|
||||
# IBM z/OS requires a feature-test macro to be defined in order to
|
||||
# enable POSIX threads at all, so give the user a hint if this is
|
||||
# not set. (We don't define these ourselves, as they can affect
|
||||
# other portions of the system API in unpredictable ways.)
|
||||
|
||||
AC_EGREP_CPP([AX_PTHREAD_ZOS_MISSING],
|
||||
[
|
||||
# if !defined(_OPEN_THREADS) && !defined(_UNIX03_THREADS)
|
||||
AX_PTHREAD_ZOS_MISSING
|
||||
# endif
|
||||
],
|
||||
[AC_MSG_WARN([IBM z/OS requires -D_OPEN_THREADS or -D_UNIX03_THREADS to enable pthreads support.])])
|
||||
;;
|
||||
|
||||
solaris*)
|
||||
|
||||
# On Solaris (at least, for some versions), libc contains stubbed
|
||||
# (non-functional) versions of the pthreads routines, so link-based
|
||||
# tests will erroneously succeed. (We need to link with -pthreads/-mt/
|
||||
# -lpthread.) (The stubs are missing pthread_cleanup_push, or rather
|
||||
# a function called by this macro, so we could check for that, but
|
||||
# who knows whether they'll stub that too in a future libc.) So,
|
||||
# we'll just look for -pthreads and -lpthread first:
|
||||
# tests will erroneously succeed. (N.B.: The stubs are missing
|
||||
# pthread_cleanup_push, or rather a function called by this macro,
|
||||
# so we could check for that, but who knows whether they'll stub
|
||||
# that too in a future libc.) So we'll check first for the
|
||||
# standard Solaris way of linking pthreads (-mt -lpthread).
|
||||
|
||||
ax_pthread_flags="-pthreads pthread -mt -pthread $ax_pthread_flags"
|
||||
;;
|
||||
|
||||
darwin*)
|
||||
ax_pthread_flags="-pthread $ax_pthread_flags"
|
||||
ax_pthread_flags="-mt,-lpthread pthread $ax_pthread_flags"
|
||||
;;
|
||||
esac
|
||||
|
||||
# Clang doesn't consider unrecognized options an error unless we specify
|
||||
# -Werror. We throw in some extra Clang-specific options to ensure that
|
||||
# this doesn't happen for GCC, which also accepts -Werror.
|
||||
# Are we compiling with Clang?
|
||||
|
||||
AC_MSG_CHECKING([if compiler needs -Werror to reject unknown flags])
|
||||
save_CFLAGS="$CFLAGS"
|
||||
ax_pthread_extra_flags="-Werror"
|
||||
CFLAGS="$CFLAGS $ax_pthread_extra_flags -Wunknown-warning-option -Wsizeof-array-argument"
|
||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([int foo(void);],[foo()])],
|
||||
[AC_MSG_RESULT([yes])],
|
||||
[ax_pthread_extra_flags=
|
||||
AC_MSG_RESULT([no])])
|
||||
CFLAGS="$save_CFLAGS"
|
||||
AC_CACHE_CHECK([whether $CC is Clang],
|
||||
[ax_cv_PTHREAD_CLANG],
|
||||
[ax_cv_PTHREAD_CLANG=no
|
||||
# Note that Autoconf sets GCC=yes for Clang as well as GCC
|
||||
if test "x$GCC" = "xyes"; then
|
||||
AC_EGREP_CPP([AX_PTHREAD_CC_IS_CLANG],
|
||||
[/* Note: Clang 2.7 lacks __clang_[a-z]+__ */
|
||||
# if defined(__clang__) && defined(__llvm__)
|
||||
AX_PTHREAD_CC_IS_CLANG
|
||||
# endif
|
||||
],
|
||||
[ax_cv_PTHREAD_CLANG=yes])
|
||||
fi
|
||||
])
|
||||
ax_pthread_clang="$ax_cv_PTHREAD_CLANG"
|
||||
|
||||
if test x"$ax_pthread_ok" = xno; then
|
||||
for flag in $ax_pthread_flags; do
|
||||
|
||||
case $flag in
|
||||
# GCC generally uses -pthread, or -pthreads on some platforms (e.g. SPARC)
|
||||
|
||||
# Note that for GCC and Clang -pthread generally implies -lpthread,
|
||||
# except when -nostdlib is passed.
|
||||
# This is problematic using libtool to build C++ shared libraries with pthread:
|
||||
# [1] https://gcc.gnu.org/bugzilla/show_bug.cgi?id=25460
|
||||
# [2] https://bugzilla.redhat.com/show_bug.cgi?id=661333
|
||||
# [3] https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=468555
|
||||
# To solve this, first try -pthread together with -lpthread for GCC
|
||||
|
||||
AS_IF([test "x$GCC" = "xyes"],
|
||||
[ax_pthread_flags="-pthread,-lpthread -pthread -pthreads $ax_pthread_flags"])
|
||||
|
||||
# Clang takes -pthread (never supported any other flag), but we'll try with -lpthread first
|
||||
|
||||
AS_IF([test "x$ax_pthread_clang" = "xyes"],
|
||||
[ax_pthread_flags="-pthread,-lpthread -pthread"])
|
||||
|
||||
|
||||
# The presence of a feature test macro requesting re-entrant function
|
||||
# definitions is, on some systems, a strong hint that pthreads support is
|
||||
# correctly enabled
|
||||
|
||||
case $host_os in
|
||||
darwin* | hpux* | linux* | osf* | solaris*)
|
||||
ax_pthread_check_macro="_REENTRANT"
|
||||
;;
|
||||
|
||||
aix*)
|
||||
ax_pthread_check_macro="_THREAD_SAFE"
|
||||
;;
|
||||
|
||||
*)
|
||||
ax_pthread_check_macro="--"
|
||||
;;
|
||||
esac
|
||||
AS_IF([test "x$ax_pthread_check_macro" = "x--"],
|
||||
[ax_pthread_check_cond=0],
|
||||
[ax_pthread_check_cond="!defined($ax_pthread_check_macro)"])
|
||||
|
||||
|
||||
if test "x$ax_pthread_ok" = "xno"; then
|
||||
for ax_pthread_try_flag in $ax_pthread_flags; do
|
||||
|
||||
case $ax_pthread_try_flag in
|
||||
none)
|
||||
AC_MSG_CHECKING([whether pthreads work without any flags])
|
||||
;;
|
||||
|
||||
*,*)
|
||||
PTHREAD_CFLAGS=`echo $ax_pthread_try_flag | sed "s/^\(.*\),\(.*\)$/\1/"`
|
||||
PTHREAD_LIBS=`echo $ax_pthread_try_flag | sed "s/^\(.*\),\(.*\)$/\2/"`
|
||||
AC_MSG_CHECKING([whether pthreads work with "$PTHREAD_CFLAGS" and "$PTHREAD_LIBS"])
|
||||
;;
|
||||
|
||||
-*)
|
||||
AC_MSG_CHECKING([whether pthreads work with $flag])
|
||||
PTHREAD_CFLAGS="$flag"
|
||||
AC_MSG_CHECKING([whether pthreads work with $ax_pthread_try_flag])
|
||||
PTHREAD_CFLAGS="$ax_pthread_try_flag"
|
||||
;;
|
||||
|
||||
pthread-config)
|
||||
AC_CHECK_PROG([ax_pthread_config], [pthread-config], [yes], [no])
|
||||
if test x"$ax_pthread_config" = xno; then continue; fi
|
||||
AS_IF([test "x$ax_pthread_config" = "xno"], [continue])
|
||||
PTHREAD_CFLAGS="`pthread-config --cflags`"
|
||||
PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`"
|
||||
;;
|
||||
|
||||
*)
|
||||
AC_MSG_CHECKING([for the pthreads library -l$flag])
|
||||
PTHREAD_LIBS="-l$flag"
|
||||
AC_MSG_CHECKING([for the pthreads library -l$ax_pthread_try_flag])
|
||||
PTHREAD_LIBS="-l$ax_pthread_try_flag"
|
||||
;;
|
||||
esac
|
||||
|
||||
save_LIBS="$LIBS"
|
||||
save_CFLAGS="$CFLAGS"
|
||||
ax_pthread_save_CFLAGS="$CFLAGS"
|
||||
ax_pthread_save_LIBS="$LIBS"
|
||||
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
|
||||
LIBS="$PTHREAD_LIBS $LIBS"
|
||||
CFLAGS="$CFLAGS $PTHREAD_CFLAGS $ax_pthread_extra_flags"
|
||||
|
||||
# Check for various functions. We must include pthread.h,
|
||||
# since some functions may be macros. (On the Sequent, we
|
||||
@@ -218,8 +312,18 @@ for flag in $ax_pthread_flags; do
|
||||
# pthread_cleanup_push because it is one of the few pthread
|
||||
# functions on Solaris that doesn't have a non-functional libc stub.
|
||||
# We try pthread_create on general principles.
|
||||
|
||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <pthread.h>
|
||||
static void routine(void *a) { *((int*)a) = 0; }
|
||||
# if $ax_pthread_check_cond
|
||||
# error "$ax_pthread_check_macro must be defined"
|
||||
# endif
|
||||
static void *some_global = NULL;
|
||||
static void routine(void *a)
|
||||
{
|
||||
/* To avoid any unused-parameter or
|
||||
unused-but-set-parameter warning. */
|
||||
some_global = a;
|
||||
}
|
||||
static void *start_routine(void *a) { return a; }],
|
||||
[pthread_t th; pthread_attr_t attr;
|
||||
pthread_create(&th, 0, start_routine, 0);
|
||||
@@ -227,101 +331,187 @@ for flag in $ax_pthread_flags; do
|
||||
pthread_attr_init(&attr);
|
||||
pthread_cleanup_push(routine, 0);
|
||||
pthread_cleanup_pop(0) /* ; */])],
|
||||
[ax_pthread_ok=yes],
|
||||
[])
|
||||
[ax_pthread_ok=yes],
|
||||
[])
|
||||
|
||||
LIBS="$save_LIBS"
|
||||
CFLAGS="$save_CFLAGS"
|
||||
CFLAGS="$ax_pthread_save_CFLAGS"
|
||||
LIBS="$ax_pthread_save_LIBS"
|
||||
|
||||
AC_MSG_RESULT([$ax_pthread_ok])
|
||||
if test "x$ax_pthread_ok" = xyes; then
|
||||
break;
|
||||
fi
|
||||
AS_IF([test "x$ax_pthread_ok" = "xyes"], [break])
|
||||
|
||||
PTHREAD_LIBS=""
|
||||
PTHREAD_CFLAGS=""
|
||||
done
|
||||
fi
|
||||
|
||||
|
||||
# Clang needs special handling, because older versions handle the -pthread
|
||||
# option in a rather... idiosyncratic way
|
||||
|
||||
if test "x$ax_pthread_clang" = "xyes"; then
|
||||
|
||||
# Clang takes -pthread; it has never supported any other flag
|
||||
|
||||
# (Note 1: This will need to be revisited if a system that Clang
|
||||
# supports has POSIX threads in a separate library. This tends not
|
||||
# to be the way of modern systems, but it's conceivable.)
|
||||
|
||||
# (Note 2: On some systems, notably Darwin, -pthread is not needed
|
||||
# to get POSIX threads support; the API is always present and
|
||||
# active. We could reasonably leave PTHREAD_CFLAGS empty. But
|
||||
# -pthread does define _REENTRANT, and while the Darwin headers
|
||||
# ignore this macro, third-party headers might not.)
|
||||
|
||||
# However, older versions of Clang make a point of warning the user
|
||||
# that, in an invocation where only linking and no compilation is
|
||||
# taking place, the -pthread option has no effect ("argument unused
|
||||
# during compilation"). They expect -pthread to be passed in only
|
||||
# when source code is being compiled.
|
||||
#
|
||||
# Problem is, this is at odds with the way Automake and most other
|
||||
# C build frameworks function, which is that the same flags used in
|
||||
# compilation (CFLAGS) are also used in linking. Many systems
|
||||
# supported by AX_PTHREAD require exactly this for POSIX threads
|
||||
# support, and in fact it is often not straightforward to specify a
|
||||
# flag that is used only in the compilation phase and not in
|
||||
# linking. Such a scenario is extremely rare in practice.
|
||||
#
|
||||
# Even though use of the -pthread flag in linking would only print
|
||||
# a warning, this can be a nuisance for well-run software projects
|
||||
# that build with -Werror. So if the active version of Clang has
|
||||
# this misfeature, we search for an option to squash it.
|
||||
|
||||
AC_CACHE_CHECK([whether Clang needs flag to prevent "argument unused" warning when linking with -pthread],
|
||||
[ax_cv_PTHREAD_CLANG_NO_WARN_FLAG],
|
||||
[ax_cv_PTHREAD_CLANG_NO_WARN_FLAG=unknown
|
||||
# Create an alternate version of $ac_link that compiles and
|
||||
# links in two steps (.c -> .o, .o -> exe) instead of one
|
||||
# (.c -> exe), because the warning occurs only in the second
|
||||
# step
|
||||
ax_pthread_save_ac_link="$ac_link"
|
||||
ax_pthread_sed='s/conftest\.\$ac_ext/conftest.$ac_objext/g'
|
||||
ax_pthread_link_step=`AS_ECHO(["$ac_link"]) | sed "$ax_pthread_sed"`
|
||||
ax_pthread_2step_ac_link="($ac_compile) && (echo ==== >&5) && ($ax_pthread_link_step)"
|
||||
ax_pthread_save_CFLAGS="$CFLAGS"
|
||||
for ax_pthread_try in '' -Qunused-arguments -Wno-unused-command-line-argument unknown; do
|
||||
AS_IF([test "x$ax_pthread_try" = "xunknown"], [break])
|
||||
CFLAGS="-Werror -Wunknown-warning-option $ax_pthread_try -pthread $ax_pthread_save_CFLAGS"
|
||||
ac_link="$ax_pthread_save_ac_link"
|
||||
AC_LINK_IFELSE([AC_LANG_SOURCE([[int main(void){return 0;}]])],
|
||||
[ac_link="$ax_pthread_2step_ac_link"
|
||||
AC_LINK_IFELSE([AC_LANG_SOURCE([[int main(void){return 0;}]])],
|
||||
[break])
|
||||
])
|
||||
done
|
||||
ac_link="$ax_pthread_save_ac_link"
|
||||
CFLAGS="$ax_pthread_save_CFLAGS"
|
||||
AS_IF([test "x$ax_pthread_try" = "x"], [ax_pthread_try=no])
|
||||
ax_cv_PTHREAD_CLANG_NO_WARN_FLAG="$ax_pthread_try"
|
||||
])
|
||||
|
||||
case "$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG" in
|
||||
no | unknown) ;;
|
||||
*) PTHREAD_CFLAGS="$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG $PTHREAD_CFLAGS" ;;
|
||||
esac
|
||||
|
||||
fi # $ax_pthread_clang = yes
|
||||
|
||||
|
||||
|
||||
# Various other checks:
|
||||
if test "x$ax_pthread_ok" = xyes; then
|
||||
save_LIBS="$LIBS"
|
||||
LIBS="$PTHREAD_LIBS $LIBS"
|
||||
save_CFLAGS="$CFLAGS"
|
||||
if test "x$ax_pthread_ok" = "xyes"; then
|
||||
ax_pthread_save_CFLAGS="$CFLAGS"
|
||||
ax_pthread_save_LIBS="$LIBS"
|
||||
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
|
||||
LIBS="$PTHREAD_LIBS $LIBS"
|
||||
|
||||
# Detect AIX lossage: JOINABLE attribute is called UNDETACHED.
|
||||
AC_MSG_CHECKING([for joinable pthread attribute])
|
||||
attr_name=unknown
|
||||
for attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do
|
||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <pthread.h>],
|
||||
[int attr = $attr; return attr /* ; */])],
|
||||
[attr_name=$attr; break],
|
||||
[])
|
||||
done
|
||||
AC_MSG_RESULT([$attr_name])
|
||||
if test "$attr_name" != PTHREAD_CREATE_JOINABLE; then
|
||||
AC_DEFINE_UNQUOTED([PTHREAD_CREATE_JOINABLE], [$attr_name],
|
||||
[Define to necessary symbol if this constant
|
||||
uses a non-standard name on your system.])
|
||||
fi
|
||||
AC_CACHE_CHECK([for joinable pthread attribute],
|
||||
[ax_cv_PTHREAD_JOINABLE_ATTR],
|
||||
[ax_cv_PTHREAD_JOINABLE_ATTR=unknown
|
||||
for ax_pthread_attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do
|
||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <pthread.h>],
|
||||
[int attr = $ax_pthread_attr; return attr /* ; */])],
|
||||
[ax_cv_PTHREAD_JOINABLE_ATTR=$ax_pthread_attr; break],
|
||||
[])
|
||||
done
|
||||
])
|
||||
AS_IF([test "x$ax_cv_PTHREAD_JOINABLE_ATTR" != "xunknown" && \
|
||||
test "x$ax_cv_PTHREAD_JOINABLE_ATTR" != "xPTHREAD_CREATE_JOINABLE" && \
|
||||
test "x$ax_pthread_joinable_attr_defined" != "xyes"],
|
||||
[AC_DEFINE_UNQUOTED([PTHREAD_CREATE_JOINABLE],
|
||||
[$ax_cv_PTHREAD_JOINABLE_ATTR],
|
||||
[Define to necessary symbol if this constant
|
||||
uses a non-standard name on your system.])
|
||||
ax_pthread_joinable_attr_defined=yes
|
||||
])
|
||||
|
||||
AC_MSG_CHECKING([if more special flags are required for pthreads])
|
||||
flag=no
|
||||
case ${host_os} in
|
||||
aix* | freebsd* | darwin*) flag="-D_THREAD_SAFE";;
|
||||
osf* | hpux*) flag="-D_REENTRANT";;
|
||||
solaris*)
|
||||
if test "$GCC" = "yes"; then
|
||||
flag="-D_REENTRANT"
|
||||
else
|
||||
# TODO: What about Clang on Solaris?
|
||||
flag="-mt -D_REENTRANT"
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
AC_MSG_RESULT([$flag])
|
||||
if test "x$flag" != xno; then
|
||||
PTHREAD_CFLAGS="$flag $PTHREAD_CFLAGS"
|
||||
fi
|
||||
AC_CACHE_CHECK([whether more special flags are required for pthreads],
|
||||
[ax_cv_PTHREAD_SPECIAL_FLAGS],
|
||||
[ax_cv_PTHREAD_SPECIAL_FLAGS=no
|
||||
case $host_os in
|
||||
solaris*)
|
||||
ax_cv_PTHREAD_SPECIAL_FLAGS="-D_POSIX_PTHREAD_SEMANTICS"
|
||||
;;
|
||||
esac
|
||||
])
|
||||
AS_IF([test "x$ax_cv_PTHREAD_SPECIAL_FLAGS" != "xno" && \
|
||||
test "x$ax_pthread_special_flags_added" != "xyes"],
|
||||
[PTHREAD_CFLAGS="$ax_cv_PTHREAD_SPECIAL_FLAGS $PTHREAD_CFLAGS"
|
||||
ax_pthread_special_flags_added=yes])
|
||||
|
||||
AC_CACHE_CHECK([for PTHREAD_PRIO_INHERIT],
|
||||
[ax_cv_PTHREAD_PRIO_INHERIT], [
|
||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <pthread.h>]],
|
||||
[[int i = PTHREAD_PRIO_INHERIT;]])],
|
||||
[ax_cv_PTHREAD_PRIO_INHERIT=yes],
|
||||
[ax_cv_PTHREAD_PRIO_INHERIT=no])
|
||||
[ax_cv_PTHREAD_PRIO_INHERIT],
|
||||
[AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <pthread.h>]],
|
||||
[[int i = PTHREAD_PRIO_INHERIT;
|
||||
return i;]])],
|
||||
[ax_cv_PTHREAD_PRIO_INHERIT=yes],
|
||||
[ax_cv_PTHREAD_PRIO_INHERIT=no])
|
||||
])
|
||||
AS_IF([test "x$ax_cv_PTHREAD_PRIO_INHERIT" = "xyes"],
|
||||
[AC_DEFINE([HAVE_PTHREAD_PRIO_INHERIT], [1], [Have PTHREAD_PRIO_INHERIT.])])
|
||||
AS_IF([test "x$ax_cv_PTHREAD_PRIO_INHERIT" = "xyes" && \
|
||||
test "x$ax_pthread_prio_inherit_defined" != "xyes"],
|
||||
[AC_DEFINE([HAVE_PTHREAD_PRIO_INHERIT], [1], [Have PTHREAD_PRIO_INHERIT.])
|
||||
ax_pthread_prio_inherit_defined=yes
|
||||
])
|
||||
|
||||
LIBS="$save_LIBS"
|
||||
CFLAGS="$save_CFLAGS"
|
||||
CFLAGS="$ax_pthread_save_CFLAGS"
|
||||
LIBS="$ax_pthread_save_LIBS"
|
||||
|
||||
# More AIX lossage: compile with *_r variant
|
||||
if test "x$GCC" != xyes; then
|
||||
if test "x$GCC" != "xyes"; then
|
||||
case $host_os in
|
||||
aix*)
|
||||
AS_CASE(["x/$CC"],
|
||||
[x*/c89|x*/c89_128|x*/c99|x*/c99_128|x*/cc|x*/cc128|x*/xlc|x*/xlc_v6|x*/xlc128|x*/xlc128_v6],
|
||||
[#handle absolute path differently from PATH based program lookup
|
||||
AS_CASE(["x$CC"],
|
||||
[x/*],
|
||||
[AS_IF([AS_EXECUTABLE_P([${CC}_r])],[PTHREAD_CC="${CC}_r"])],
|
||||
[AC_CHECK_PROGS([PTHREAD_CC],[${CC}_r],[$CC])])])
|
||||
[x*/c89|x*/c89_128|x*/c99|x*/c99_128|x*/cc|x*/cc128|x*/xlc|x*/xlc_v6|x*/xlc128|x*/xlc128_v6],
|
||||
[#handle absolute path differently from PATH based program lookup
|
||||
AS_CASE(["x$CC"],
|
||||
[x/*],
|
||||
[
|
||||
AS_IF([AS_EXECUTABLE_P([${CC}_r])],[PTHREAD_CC="${CC}_r"])
|
||||
AS_IF([test "x${CXX}" != "x"], [AS_IF([AS_EXECUTABLE_P([${CXX}_r])],[PTHREAD_CXX="${CXX}_r"])])
|
||||
],
|
||||
[
|
||||
AC_CHECK_PROGS([PTHREAD_CC],[${CC}_r],[$CC])
|
||||
AS_IF([test "x${CXX}" != "x"], [AC_CHECK_PROGS([PTHREAD_CXX],[${CXX}_r],[$CXX])])
|
||||
]
|
||||
)
|
||||
])
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
fi
|
||||
|
||||
test -n "$PTHREAD_CC" || PTHREAD_CC="$CC"
|
||||
test -n "$PTHREAD_CXX" || PTHREAD_CXX="$CXX"
|
||||
|
||||
AC_SUBST([PTHREAD_LIBS])
|
||||
AC_SUBST([PTHREAD_CFLAGS])
|
||||
AC_SUBST([PTHREAD_CC])
|
||||
AC_SUBST([PTHREAD_CXX])
|
||||
|
||||
# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND:
|
||||
if test x"$ax_pthread_ok" = xyes; then
|
||||
if test "x$ax_pthread_ok" = "xyes"; then
|
||||
ifelse([$1],,[AC_DEFINE([HAVE_PTHREAD],[1],[Define if you have POSIX threads libraries and header files.])],[$1])
|
||||
:
|
||||
else
|
||||
|
||||
+140
-33
@@ -50,6 +50,8 @@
|
||||
#include "util/data/msgreply.h"
|
||||
#include "util/data/msgencode.h"
|
||||
#include "services/cache/dns.h"
|
||||
#include "services/mesh.h"
|
||||
#include "services/modstack.h"
|
||||
#include "validator/val_neg.h"
|
||||
#include "validator/val_secalgo.h"
|
||||
#include "iterator/iter_utils.h"
|
||||
@@ -265,15 +267,6 @@ cachedb_init(struct module_env* env, int id)
|
||||
return 0;
|
||||
}
|
||||
cachedb_env->enabled = 1;
|
||||
if(env->cfg->serve_expired && env->cfg->serve_expired_reply_ttl)
|
||||
log_warn(
|
||||
"cachedb: serve-expired-reply-ttl is set but not working for data "
|
||||
"originating from the external cache; 0 TTL is used for those.");
|
||||
if(env->cfg->serve_expired && env->cfg->serve_expired_client_timeout)
|
||||
log_warn(
|
||||
"cachedb: serve-expired-client-timeout is set but not working for "
|
||||
"data originating from the external cache; expired data are used "
|
||||
"in the reply without first trying to refresh the data.");
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -329,30 +322,30 @@ error_response(struct module_qstate* qstate, int id, int rcode)
|
||||
|
||||
/**
|
||||
* Hash the query name, type, class and dbacess-secret into lookup buffer.
|
||||
* @param qstate: query state with query info
|
||||
* and env->cfg with secret.
|
||||
* @param qinfo: query info
|
||||
* @param env: with env->cfg with secret.
|
||||
* @param buf: returned buffer with hash to lookup
|
||||
* @param len: length of the buffer.
|
||||
*/
|
||||
static void
|
||||
calc_hash(struct module_qstate* qstate, char* buf, size_t len)
|
||||
calc_hash(struct query_info* qinfo, struct module_env* env, char* buf,
|
||||
size_t len)
|
||||
{
|
||||
uint8_t clear[1024];
|
||||
size_t clen = 0;
|
||||
uint8_t hash[CACHEDB_HASHSIZE/8];
|
||||
const char* hex = "0123456789ABCDEF";
|
||||
const char* secret = qstate->env->cfg->cachedb_secret;
|
||||
const char* secret = env->cfg->cachedb_secret;
|
||||
size_t i;
|
||||
|
||||
/* copy the hash info into the clear buffer */
|
||||
if(clen + qstate->qinfo.qname_len < sizeof(clear)) {
|
||||
memmove(clear+clen, qstate->qinfo.qname,
|
||||
qstate->qinfo.qname_len);
|
||||
clen += qstate->qinfo.qname_len;
|
||||
if(clen + qinfo->qname_len < sizeof(clear)) {
|
||||
memmove(clear+clen, qinfo->qname, qinfo->qname_len);
|
||||
clen += qinfo->qname_len;
|
||||
}
|
||||
if(clen + 4 < sizeof(clear)) {
|
||||
uint16_t t = htons(qstate->qinfo.qtype);
|
||||
uint16_t c = htons(qstate->qinfo.qclass);
|
||||
uint16_t t = htons(qinfo->qtype);
|
||||
uint16_t c = htons(qinfo->qclass);
|
||||
memmove(clear+clen, &t, 2);
|
||||
memmove(clear+clen+2, &c, 2);
|
||||
clen += 4;
|
||||
@@ -511,9 +504,38 @@ adjust_msg_ttl(struct dns_msg* msg, time_t adjust)
|
||||
}
|
||||
}
|
||||
|
||||
/* Set the TTL of the given RRset to fixed value. */
|
||||
static void
|
||||
packed_rrset_ttl_set(struct packed_rrset_data* data, time_t ttl)
|
||||
{
|
||||
size_t i;
|
||||
size_t total = data->count + data->rrsig_count;
|
||||
data->ttl = ttl;
|
||||
for(i=0; i<total; i++) {
|
||||
data->rr_ttl[i] = ttl;
|
||||
}
|
||||
data->ttl_add = 0;
|
||||
}
|
||||
|
||||
/* Set the TTL of a DNS message and its RRs by to a fixed value. */
|
||||
static void
|
||||
set_msg_ttl(struct dns_msg* msg, time_t ttl)
|
||||
{
|
||||
size_t i;
|
||||
msg->rep->ttl = ttl;
|
||||
msg->rep->prefetch_ttl = PREFETCH_TTL_CALC(msg->rep->ttl);
|
||||
msg->rep->serve_expired_ttl = msg->rep->ttl + SERVE_EXPIRED_TTL;
|
||||
|
||||
for(i=0; i<msg->rep->rrset_count; i++) {
|
||||
packed_rrset_ttl_set((struct packed_rrset_data*)msg->
|
||||
rep->rrsets[i]->entry.data, ttl);
|
||||
}
|
||||
}
|
||||
|
||||
/** convert dns message in buffer to return_msg */
|
||||
static int
|
||||
parse_data(struct module_qstate* qstate, struct sldns_buffer* buf)
|
||||
parse_data(struct module_qstate* qstate, struct sldns_buffer* buf,
|
||||
int* msg_expired)
|
||||
{
|
||||
struct msg_parse* prs;
|
||||
struct edns_data edns;
|
||||
@@ -583,6 +605,7 @@ parse_data(struct module_qstate* qstate, struct sldns_buffer* buf)
|
||||
adjust = *qstate->env->now - (time_t)timestamp;
|
||||
if(qstate->return_msg->rep->ttl < adjust) {
|
||||
verbose(VERB_ALGO, "cachedb msg expired");
|
||||
*msg_expired = 1;
|
||||
/* If serve-expired is enabled, we still use an expired message
|
||||
* setting the TTL to 0. */
|
||||
if(!qstate->env->cfg->serve_expired ||
|
||||
@@ -598,6 +621,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
|
||||
@@ -605,6 +631,7 @@ parse_data(struct module_qstate* qstate, struct sldns_buffer* buf)
|
||||
* 'now' should be redundant given how these values were calculated,
|
||||
* but we check it just in case as does good_expiry_and_qinfo(). */
|
||||
if(qstate->env->cfg->serve_expired &&
|
||||
!qstate->env->cfg->serve_expired_client_timeout &&
|
||||
(adjust == -1 || (time_t)expiry < *qstate->env->now)) {
|
||||
qstate->need_refetch = 1;
|
||||
}
|
||||
@@ -617,10 +644,11 @@ parse_data(struct module_qstate* qstate, struct sldns_buffer* buf)
|
||||
* return true if lookup was successful.
|
||||
*/
|
||||
static int
|
||||
cachedb_extcache_lookup(struct module_qstate* qstate, struct cachedb_env* ie)
|
||||
cachedb_extcache_lookup(struct module_qstate* qstate, struct cachedb_env* ie,
|
||||
int* msg_expired)
|
||||
{
|
||||
char key[(CACHEDB_HASHSIZE/8)*2+1];
|
||||
calc_hash(qstate, key, sizeof(key));
|
||||
calc_hash(&qstate->qinfo, qstate->env, key, sizeof(key));
|
||||
|
||||
/* call backend to fetch data for key into scratch buffer */
|
||||
if( !(*ie->backend->lookup)(qstate->env, ie, key,
|
||||
@@ -634,7 +662,7 @@ cachedb_extcache_lookup(struct module_qstate* qstate, struct cachedb_env* ie)
|
||||
}
|
||||
|
||||
/* parse dns message into return_msg */
|
||||
if( !parse_data(qstate, qstate->env->scratch_buffer) ) {
|
||||
if( !parse_data(qstate, qstate->env->scratch_buffer, msg_expired) ) {
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
@@ -647,7 +675,7 @@ static void
|
||||
cachedb_extcache_store(struct module_qstate* qstate, struct cachedb_env* ie)
|
||||
{
|
||||
char key[(CACHEDB_HASHSIZE/8)*2+1];
|
||||
calc_hash(qstate, key, sizeof(key));
|
||||
calc_hash(&qstate->qinfo, qstate->env, key, sizeof(key));
|
||||
|
||||
/* prepare data in scratch buffer */
|
||||
if(!prep_data(qstate, qstate->env->scratch_buffer))
|
||||
@@ -666,6 +694,7 @@ cachedb_extcache_store(struct module_qstate* qstate, struct cachedb_env* ie)
|
||||
static int
|
||||
cachedb_intcache_lookup(struct module_qstate* qstate, struct cachedb_env* cde)
|
||||
{
|
||||
uint8_t dpname_storage[LDNS_MAX_DOMAINLEN+1];
|
||||
uint8_t* dpname=NULL;
|
||||
size_t dpnamelen=0;
|
||||
struct dns_msg* msg;
|
||||
@@ -674,7 +703,7 @@ cachedb_intcache_lookup(struct module_qstate* qstate, struct cachedb_env* cde)
|
||||
return 0;
|
||||
}
|
||||
if(iter_stub_fwd_no_cache(qstate, &qstate->qinfo,
|
||||
&dpname, &dpnamelen))
|
||||
&dpname, &dpnamelen, dpname_storage, sizeof(dpname_storage)))
|
||||
return 0; /* no cache for these queries */
|
||||
msg = dns_cache_lookup(qstate->env, qstate->qinfo.qname,
|
||||
qstate->qinfo.qname_len, qstate->qinfo.qtype,
|
||||
@@ -705,17 +734,43 @@ cachedb_intcache_lookup(struct module_qstate* qstate, struct cachedb_env* cde)
|
||||
* Store query into the internal cache of unbound.
|
||||
*/
|
||||
static void
|
||||
cachedb_intcache_store(struct module_qstate* qstate)
|
||||
cachedb_intcache_store(struct module_qstate* qstate, int msg_expired)
|
||||
{
|
||||
uint32_t store_flags = qstate->query_flags;
|
||||
int serve_expired = qstate->env->cfg->serve_expired;
|
||||
|
||||
if(qstate->env->cfg->serve_expired)
|
||||
store_flags |= DNSCACHE_STORE_ZEROTTL;
|
||||
if(!qstate->return_msg)
|
||||
return;
|
||||
if(serve_expired && msg_expired) {
|
||||
/* Set TTLs to a value such that value + *env->now is
|
||||
* going to be now-3 seconds. Making it expired
|
||||
* in the cache. */
|
||||
set_msg_ttl(qstate->return_msg, (time_t)-3);
|
||||
/* The expired entry does not get checked by the validator
|
||||
* and we need a validation value for it. */
|
||||
if(qstate->env->cfg->cachedb_check_when_serve_expired)
|
||||
qstate->return_msg->rep->security = sec_status_insecure;
|
||||
}
|
||||
(void)dns_cache_store(qstate->env, &qstate->qinfo,
|
||||
qstate->return_msg->rep, 0, qstate->prefetch_leeway, 0,
|
||||
qstate->region, store_flags, qstate->qstarttime);
|
||||
if(serve_expired && msg_expired) {
|
||||
if(qstate->env->cfg->serve_expired_client_timeout) {
|
||||
/* No expired response from the query state, the
|
||||
* query resolution needs to continue and it can
|
||||
* pick up the expired result after the timer out
|
||||
* of cache. */
|
||||
return;
|
||||
}
|
||||
/* set TTLs to zero again */
|
||||
adjust_msg_ttl(qstate->return_msg, -1);
|
||||
/* Send serve expired responses based on the cachedb
|
||||
* returned message, that was just stored in the cache.
|
||||
* It can then continue to work on this query. */
|
||||
mesh_respond_serve_expired(qstate->mesh_info);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -731,6 +786,7 @@ cachedb_handle_query(struct module_qstate* qstate,
|
||||
struct cachedb_qstate* ATTR_UNUSED(iq),
|
||||
struct cachedb_env* ie, int id)
|
||||
{
|
||||
int msg_expired = 0;
|
||||
qstate->is_cachedb_answer = 0;
|
||||
/* check if we are enabled, and skip if so */
|
||||
if(!ie->enabled) {
|
||||
@@ -765,20 +821,26 @@ cachedb_handle_query(struct module_qstate* qstate,
|
||||
}
|
||||
|
||||
/* ask backend cache to see if we have data */
|
||||
if(cachedb_extcache_lookup(qstate, ie)) {
|
||||
if(cachedb_extcache_lookup(qstate, ie, &msg_expired)) {
|
||||
if(verbosity >= VERB_ALGO)
|
||||
log_dns_msg(ie->backend->name,
|
||||
&qstate->return_msg->qinfo,
|
||||
qstate->return_msg->rep);
|
||||
/* store this result in internal cache */
|
||||
cachedb_intcache_store(qstate);
|
||||
cachedb_intcache_store(qstate, msg_expired);
|
||||
/* 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.
|
||||
* Document that ext cachedb does not work properly with
|
||||
* serve_stale_reply_ttl yet. */
|
||||
*/
|
||||
if(qstate->env->cfg->serve_expired && msg_expired) {
|
||||
qstate->return_msg = NULL;
|
||||
qstate->ext_state[id] = module_wait_module;
|
||||
/* The expired reply is sent with
|
||||
* mesh_respond_serve_expired, and so
|
||||
* the need_refetch is not used. */
|
||||
qstate->need_refetch = 0;
|
||||
return;
|
||||
}
|
||||
if(qstate->need_refetch && qstate->serve_expired_data &&
|
||||
qstate->serve_expired_data->timer) {
|
||||
qstate->return_msg = NULL;
|
||||
@@ -791,6 +853,14 @@ cachedb_handle_query(struct module_qstate* qstate,
|
||||
return;
|
||||
}
|
||||
|
||||
if(qstate->serve_expired_data &&
|
||||
qstate->env->cfg->cachedb_check_when_serve_expired &&
|
||||
!qstate->env->cfg->serve_expired_client_timeout) {
|
||||
/* Reply with expired data if any to client, because cachedb
|
||||
* also has no useful, current data */
|
||||
mesh_respond_serve_expired(qstate->mesh_info);
|
||||
}
|
||||
|
||||
/* no cache fetches */
|
||||
/* pass request to next module */
|
||||
qstate->ext_state[id] = module_wait_module;
|
||||
@@ -914,7 +984,7 @@ cachedb_get_mem(struct module_env* env, int id)
|
||||
*/
|
||||
static struct module_func_block cachedb_block = {
|
||||
"cachedb",
|
||||
&cachedb_init, &cachedb_deinit, &cachedb_operate,
|
||||
NULL, NULL, &cachedb_init, &cachedb_deinit, &cachedb_operate,
|
||||
&cachedb_inform_super, &cachedb_clear, &cachedb_get_mem
|
||||
};
|
||||
|
||||
@@ -923,4 +993,41 @@ cachedb_get_funcblock(void)
|
||||
{
|
||||
return &cachedb_block;
|
||||
}
|
||||
|
||||
int
|
||||
cachedb_is_enabled(struct module_stack* mods, struct module_env* env)
|
||||
{
|
||||
struct cachedb_env* ie;
|
||||
int id = modstack_find(mods, "cachedb");
|
||||
if(id == -1)
|
||||
return 0;
|
||||
ie = (struct cachedb_env*)env->modinfo[id];
|
||||
if(ie && ie->enabled)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void cachedb_msg_remove(struct module_qstate* qstate)
|
||||
{
|
||||
cachedb_msg_remove_qinfo(qstate->env, &qstate->qinfo);
|
||||
}
|
||||
|
||||
void cachedb_msg_remove_qinfo(struct module_env* env, struct query_info* qinfo)
|
||||
{
|
||||
char key[(CACHEDB_HASHSIZE/8)*2+1];
|
||||
int id = modstack_find(env->modstack, "cachedb");
|
||||
struct cachedb_env* ie = (struct cachedb_env*)env->modinfo[id];
|
||||
|
||||
log_query_info(VERB_ALGO, "cachedb msg remove", qinfo);
|
||||
calc_hash(qinfo, env, key, sizeof(key));
|
||||
sldns_buffer_clear(env->scratch_buffer);
|
||||
sldns_buffer_write_u32(env->scratch_buffer, 0);
|
||||
sldns_buffer_flip(env->scratch_buffer);
|
||||
|
||||
/* call backend */
|
||||
(*ie->backend->store)(env, ie, key,
|
||||
sldns_buffer_begin(env->scratch_buffer),
|
||||
sldns_buffer_limit(env->scratch_buffer),
|
||||
0);
|
||||
}
|
||||
#endif /* USE_CACHEDB */
|
||||
|
||||
@@ -41,6 +41,7 @@
|
||||
*/
|
||||
#include "util/module.h"
|
||||
struct cachedb_backend;
|
||||
struct module_stack;
|
||||
|
||||
/**
|
||||
* The global variable environment contents for the cachedb
|
||||
@@ -110,3 +111,26 @@ size_t cachedb_get_mem(struct module_env* env, int id);
|
||||
*/
|
||||
struct module_func_block* cachedb_get_funcblock(void);
|
||||
|
||||
/**
|
||||
* See if the cachedb is enabled.
|
||||
* @param mods: module stack. It finds the cachedb module environment.
|
||||
* @param env: module environment.
|
||||
* @return true if exists and enabled.
|
||||
*/
|
||||
int cachedb_is_enabled(struct module_stack* mods, struct module_env* env);
|
||||
|
||||
/**
|
||||
* Remove a message from the global cache. Because edns subnet has a more
|
||||
* specific entry, and if not removed when everything expires, the global
|
||||
* entry is used, instead of a fresh lookup of the edns subnet entry.
|
||||
* @param qstate: query state.
|
||||
*/
|
||||
void cachedb_msg_remove(struct module_qstate* qstate);
|
||||
|
||||
/**
|
||||
* Remove message from the cachedb cache, by query info.
|
||||
* @param env: module environment to look up cachedb state.
|
||||
* @param qinfo: the message to remove.
|
||||
*/
|
||||
void cachedb_msg_remove_qinfo(struct module_env* env,
|
||||
struct query_info* qinfo);
|
||||
|
||||
+23
-6
@@ -58,7 +58,8 @@ struct redis_moddata {
|
||||
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 */
|
||||
struct timeval command_timeout; /* timeout for commands */
|
||||
struct timeval connect_timeout; /* timeout for connect */
|
||||
int logical_db; /* the redis logical database to use */
|
||||
};
|
||||
|
||||
@@ -88,10 +89,10 @@ redis_connect(const struct redis_moddata* moddata)
|
||||
|
||||
if(moddata->server_path && moddata->server_path[0]!=0) {
|
||||
ctx = redisConnectUnixWithTimeout(moddata->server_path,
|
||||
moddata->timeout);
|
||||
moddata->connect_timeout);
|
||||
} else {
|
||||
ctx = redisConnectWithTimeout(moddata->server_host,
|
||||
moddata->server_port, moddata->timeout);
|
||||
moddata->server_port, moddata->connect_timeout);
|
||||
}
|
||||
if(!ctx || ctx->err) {
|
||||
const char *errstr = "out of memory";
|
||||
@@ -100,7 +101,7 @@ 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) {
|
||||
if(redisSetTimeout(ctx, moddata->command_timeout) != REDIS_OK) {
|
||||
log_err("failed to set redis timeout");
|
||||
goto fail;
|
||||
}
|
||||
@@ -159,8 +160,24 @@ redis_init(struct module_env* env, struct cachedb_env* cachedb_env)
|
||||
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->command_timeout.tv_sec = env->cfg->redis_timeout / 1000;
|
||||
moddata->command_timeout.tv_usec =
|
||||
(env->cfg->redis_timeout % 1000) * 1000;
|
||||
moddata->connect_timeout.tv_sec = env->cfg->redis_timeout / 1000;
|
||||
moddata->connect_timeout.tv_usec =
|
||||
(env->cfg->redis_timeout % 1000) * 1000;
|
||||
if(env->cfg->redis_command_timeout != 0) {
|
||||
moddata->command_timeout.tv_sec =
|
||||
env->cfg->redis_command_timeout / 1000;
|
||||
moddata->command_timeout.tv_usec =
|
||||
(env->cfg->redis_command_timeout % 1000) * 1000;
|
||||
}
|
||||
if(env->cfg->redis_connect_timeout != 0) {
|
||||
moddata->connect_timeout.tv_sec =
|
||||
env->cfg->redis_connect_timeout / 1000;
|
||||
moddata->connect_timeout.tv_usec =
|
||||
(env->cfg->redis_connect_timeout % 1000) * 1000;
|
||||
}
|
||||
moddata->logical_db = env->cfg->redis_logical_db;
|
||||
for(i = 0; i < moddata->numctxs; i++) {
|
||||
redisContext* ctx = redis_connect(moddata);
|
||||
|
||||
Vendored
+704
-559
File diff suppressed because it is too large
Load Diff
+191
-23
@@ -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
|
||||
@@ -379,8 +393,8 @@
|
||||
/* Define to 1 if you have the `memmove' function. */
|
||||
#undef HAVE_MEMMOVE
|
||||
|
||||
/* Define to 1 if you have the <memory.h> header file. */
|
||||
#undef HAVE_MEMORY_H
|
||||
/* Define to 1 if you have the <minix/config.h> header file. */
|
||||
#undef HAVE_MINIX_CONFIG_H
|
||||
|
||||
/* Define to 1 if you have the <netdb.h> header file. */
|
||||
#undef HAVE_NETDB_H
|
||||
@@ -406,12 +420,74 @@
|
||||
/* Define to 1 if you have the <net/if.h> header file. */
|
||||
#undef HAVE_NET_IF_H
|
||||
|
||||
/* Define to 1 if you have the <net/pfvar.h> header file. */
|
||||
#undef HAVE_NET_PFVAR_H
|
||||
|
||||
/* Define this to use nghttp2 client. */
|
||||
#undef HAVE_NGHTTP2
|
||||
|
||||
/* 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
|
||||
|
||||
@@ -566,6 +642,9 @@
|
||||
function. */
|
||||
#undef HAVE_SSL_CTX_SET_TLSEXT_TICKET_KEY_EVP_CB
|
||||
|
||||
/* Define to 1 if you have the `SSL_CTX_set_tmp_ecdh' function. */
|
||||
#undef HAVE_SSL_CTX_SET_TMP_ECDH
|
||||
|
||||
/* Define to 1 if you have the `SSL_get0_alpn_selected' function. */
|
||||
#undef HAVE_SSL_GET0_ALPN_SELECTED
|
||||
|
||||
@@ -575,6 +654,9 @@
|
||||
/* 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
|
||||
|
||||
@@ -587,6 +669,9 @@
|
||||
/* Define to 1 if you have the <stdint.h> header file. */
|
||||
#undef HAVE_STDINT_H
|
||||
|
||||
/* Define to 1 if you have the <stdio.h> header file. */
|
||||
#undef HAVE_STDIO_H
|
||||
|
||||
/* Define to 1 if you have the <stdlib.h> header file. */
|
||||
#undef HAVE_STDLIB_H
|
||||
|
||||
@@ -614,6 +699,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
|
||||
|
||||
@@ -689,6 +791,9 @@
|
||||
/* Define to 1 if you have the <vfork.h> header file. */
|
||||
#undef HAVE_VFORK_H
|
||||
|
||||
/* Define to 1 if you have the <wchar.h> header file. */
|
||||
#undef HAVE_WCHAR_H
|
||||
|
||||
/* Define to 1 if you have the <windows.h> header file. */
|
||||
#undef HAVE_WINDOWS_H
|
||||
|
||||
@@ -830,7 +935,9 @@
|
||||
/* Define to 1 if libsodium supports sodium_set_misuse_handler */
|
||||
#undef SODIUM_MISUSE_HANDLER
|
||||
|
||||
/* Define to 1 if you have the ANSI C header files. */
|
||||
/* Define to 1 if all of the C90 standard headers exist (not just the ones
|
||||
required in a freestanding environment). This macro is provided for
|
||||
backward compatibility; new code need not use it. */
|
||||
#undef STDC_HEADERS
|
||||
|
||||
/* use default strptime. */
|
||||
@@ -926,21 +1033,87 @@
|
||||
#ifndef _ALL_SOURCE
|
||||
# undef _ALL_SOURCE
|
||||
#endif
|
||||
/* Enable general extensions on macOS. */
|
||||
#ifndef _DARWIN_C_SOURCE
|
||||
# undef _DARWIN_C_SOURCE
|
||||
#endif
|
||||
/* Enable general extensions on Solaris. */
|
||||
#ifndef __EXTENSIONS__
|
||||
# undef __EXTENSIONS__
|
||||
#endif
|
||||
/* Enable GNU extensions on systems that have them. */
|
||||
#ifndef _GNU_SOURCE
|
||||
# undef _GNU_SOURCE
|
||||
#endif
|
||||
/* Enable threading extensions on Solaris. */
|
||||
/* Enable X/Open compliant socket functions that do not require linking
|
||||
with -lxnet on HP-UX 11.11. */
|
||||
#ifndef _HPUX_ALT_XOPEN_SOCKET_API
|
||||
# undef _HPUX_ALT_XOPEN_SOCKET_API
|
||||
#endif
|
||||
/* Identify the host operating system as Minix.
|
||||
This macro does not affect the system headers' behavior.
|
||||
A future release of Autoconf may stop defining this macro. */
|
||||
#ifndef _MINIX
|
||||
# undef _MINIX
|
||||
#endif
|
||||
/* Enable general extensions on NetBSD.
|
||||
Enable NetBSD compatibility extensions on Minix. */
|
||||
#ifndef _NETBSD_SOURCE
|
||||
# undef _NETBSD_SOURCE
|
||||
#endif
|
||||
/* Enable OpenBSD compatibility extensions on NetBSD.
|
||||
Oddly enough, this does nothing on OpenBSD. */
|
||||
#ifndef _OPENBSD_SOURCE
|
||||
# undef _OPENBSD_SOURCE
|
||||
#endif
|
||||
/* Define to 1 if needed for POSIX-compatible behavior. */
|
||||
#ifndef _POSIX_SOURCE
|
||||
# undef _POSIX_SOURCE
|
||||
#endif
|
||||
/* Define to 2 if needed for POSIX-compatible behavior. */
|
||||
#ifndef _POSIX_1_SOURCE
|
||||
# undef _POSIX_1_SOURCE
|
||||
#endif
|
||||
/* Enable POSIX-compatible threading on Solaris. */
|
||||
#ifndef _POSIX_PTHREAD_SEMANTICS
|
||||
# undef _POSIX_PTHREAD_SEMANTICS
|
||||
#endif
|
||||
/* Enable extensions specified by ISO/IEC TS 18661-5:2014. */
|
||||
#ifndef __STDC_WANT_IEC_60559_ATTRIBS_EXT__
|
||||
# undef __STDC_WANT_IEC_60559_ATTRIBS_EXT__
|
||||
#endif
|
||||
/* Enable extensions specified by ISO/IEC TS 18661-1:2014. */
|
||||
#ifndef __STDC_WANT_IEC_60559_BFP_EXT__
|
||||
# undef __STDC_WANT_IEC_60559_BFP_EXT__
|
||||
#endif
|
||||
/* Enable extensions specified by ISO/IEC TS 18661-2:2015. */
|
||||
#ifndef __STDC_WANT_IEC_60559_DFP_EXT__
|
||||
# undef __STDC_WANT_IEC_60559_DFP_EXT__
|
||||
#endif
|
||||
/* Enable extensions specified by ISO/IEC TS 18661-4:2015. */
|
||||
#ifndef __STDC_WANT_IEC_60559_FUNCS_EXT__
|
||||
# undef __STDC_WANT_IEC_60559_FUNCS_EXT__
|
||||
#endif
|
||||
/* Enable extensions specified by ISO/IEC TS 18661-3:2015. */
|
||||
#ifndef __STDC_WANT_IEC_60559_TYPES_EXT__
|
||||
# undef __STDC_WANT_IEC_60559_TYPES_EXT__
|
||||
#endif
|
||||
/* Enable extensions specified by ISO/IEC TR 24731-2:2010. */
|
||||
#ifndef __STDC_WANT_LIB_EXT2__
|
||||
# undef __STDC_WANT_LIB_EXT2__
|
||||
#endif
|
||||
/* Enable extensions specified by ISO/IEC 24747:2009. */
|
||||
#ifndef __STDC_WANT_MATH_SPEC_FUNCS__
|
||||
# undef __STDC_WANT_MATH_SPEC_FUNCS__
|
||||
#endif
|
||||
/* Enable extensions on HP NonStop. */
|
||||
#ifndef _TANDEM_SOURCE
|
||||
# undef _TANDEM_SOURCE
|
||||
#endif
|
||||
/* Enable general extensions on Solaris. */
|
||||
#ifndef __EXTENSIONS__
|
||||
# undef __EXTENSIONS__
|
||||
/* Enable X/Open extensions. Define to 500 only if necessary
|
||||
to make mbstate_t available. */
|
||||
#ifndef _XOPEN_SOURCE
|
||||
# undef _XOPEN_SOURCE
|
||||
#endif
|
||||
|
||||
|
||||
@@ -966,11 +1139,6 @@
|
||||
`char[]'. */
|
||||
#undef YYTEXT_POINTER
|
||||
|
||||
/* Enable large inode numbers on Mac OS X 10.5. */
|
||||
#ifndef _DARWIN_USE_64_BIT_INODE
|
||||
# define _DARWIN_USE_64_BIT_INODE 1
|
||||
#endif
|
||||
|
||||
/* Number of bits in a file offset, on hosts where this is settable. */
|
||||
#undef _FILE_OFFSET_BITS
|
||||
|
||||
@@ -980,19 +1148,9 @@
|
||||
/* Define for large files, on AIX-style hosts. */
|
||||
#undef _LARGE_FILES
|
||||
|
||||
/* Define to 1 if on MINIX. */
|
||||
#undef _MINIX
|
||||
|
||||
/* Enable for compile on Minix */
|
||||
#undef _NETBSD_SOURCE
|
||||
|
||||
/* Define to 2 if the system does not provide POSIX.1 features except with
|
||||
this defined. */
|
||||
#undef _POSIX_1_SOURCE
|
||||
|
||||
/* Define to 1 if you need to in order for `stat' and other things to work. */
|
||||
#undef _POSIX_SOURCE
|
||||
|
||||
/* defined to use gcc ansi snprintf and sscanf that understands %lld when
|
||||
compiled for windows. */
|
||||
#undef __USE_MINGW_ANSI_STDIO
|
||||
@@ -1033,7 +1191,7 @@
|
||||
/* Define to `long int' if <sys/types.h> does not define. */
|
||||
#undef off_t
|
||||
|
||||
/* Define to `int' if <sys/types.h> does not define. */
|
||||
/* Define as a signed integer type capable of holding a process identifier. */
|
||||
#undef pid_t
|
||||
|
||||
/* Define to 'int' if not defined */
|
||||
@@ -1425,6 +1583,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);
|
||||
@@ -1437,6 +1599,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 */
|
||||
@@ -1447,6 +1613,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
|
||||
|
||||
Vendored
+503
-325
File diff suppressed because it is too large
Load Diff
+176
-24
@@ -4,13 +4,13 @@ AC_PREREQ([2.56])
|
||||
sinclude(acx_nlnetlabs.m4)
|
||||
sinclude(ax_pthread.m4)
|
||||
sinclude(acx_python.m4)
|
||||
sinclude(ac_pkg_swig.m4)
|
||||
sinclude(ax_pkg_swig.m4)
|
||||
sinclude(dnstap/dnstap.m4)
|
||||
sinclude(dnscrypt/dnscrypt.m4)
|
||||
|
||||
# must be numbers. ac_defun because of later processing
|
||||
m4_define([VERSION_MAJOR],[1])
|
||||
m4_define([VERSION_MINOR],[19])
|
||||
m4_define([VERSION_MINOR],[22])
|
||||
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])
|
||||
@@ -18,7 +18,7 @@ AC_SUBST(UNBOUND_VERSION_MINOR, [VERSION_MINOR])
|
||||
AC_SUBST(UNBOUND_VERSION_MICRO, [VERSION_MICRO])
|
||||
|
||||
LIBUNBOUND_CURRENT=9
|
||||
LIBUNBOUND_REVISION=23
|
||||
LIBUNBOUND_REVISION=30
|
||||
LIBUNBOUND_AGE=1
|
||||
# 1.0.0 had 0:12:0
|
||||
# 1.0.1 had 0:13:0
|
||||
@@ -109,6 +109,13 @@ LIBUNBOUND_AGE=1
|
||||
# 1.17.1 had 9:21:1
|
||||
# 1.18.0 had 9:22:1
|
||||
# 1.19.0 had 9:23:1
|
||||
# 1.19.1 had 9:24:1
|
||||
# 1.19.2 had 9:25:1
|
||||
# 1.19.3 had 9:26:1
|
||||
# 1.20.0 had 9:27:1
|
||||
# 1.21.0 had 9:28:1
|
||||
# 1.21.1 had 9:29:1
|
||||
# 1.22.0 had 9:30:1
|
||||
|
||||
# Current -- the number of the binary API that we're implementing
|
||||
# Revision -- which iteration of the implementation of the binary
|
||||
@@ -270,6 +277,9 @@ AC_DEFINE(WINVER, 0x0502, [the version of the windows API enabled])
|
||||
ACX_RSRC_VERSION(wnvs)
|
||||
AC_DEFINE_UNQUOTED(RSRC_PACKAGE_VERSION, [$wnvs], [version number for resource files])
|
||||
|
||||
# Check for 'grep -e' program, here, since ACX_CHECK_FLTO needs that.
|
||||
AC_PROG_GREP
|
||||
|
||||
# Checks for typedefs, structures, and compiler characteristics.
|
||||
AC_C_CONST
|
||||
AC_LANG([C])
|
||||
@@ -331,6 +341,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
|
||||
|
||||
@@ -352,11 +364,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
|
||||
@@ -406,7 +461,7 @@ AC_CHECK_TOOL(STRIP, strip)
|
||||
ACX_LIBTOOL_C_ONLY
|
||||
|
||||
# pkg-config is only needed for these options, do not require it otherwise
|
||||
if test "$enable_systemd" = "yes" -o "$with_pyunbound" = "yes" -o "$with_pythonmod" = "yes"; then
|
||||
if test "$enable_systemd" = "yes" -o "$enable_dnstap" = "yes" -o "$with_pyunbound" = "yes" -o "$with_pythonmod" = "yes"; then
|
||||
PKG_PROG_PKG_CONFIG
|
||||
fi
|
||||
|
||||
@@ -792,9 +847,9 @@ if test x_$ub_test_python != x_no; then
|
||||
ub_have_swig=no
|
||||
AC_ARG_ENABLE(swig-version-check, AS_HELP_STRING([--disable-swig-version-check],[Disable swig version check to build python modules with older swig even though that is unreliable]))
|
||||
if test "$enable_swig_version_check" = "yes"; then
|
||||
AC_PROG_SWIG(2.0.1)
|
||||
AX_PKG_SWIG(2.0.1)
|
||||
else
|
||||
AC_PROG_SWIG
|
||||
AX_PKG_SWIG
|
||||
fi
|
||||
AC_MSG_CHECKING(SWIG)
|
||||
if test ! -x "$SWIG"; then
|
||||
@@ -936,7 +991,7 @@ else
|
||||
AC_MSG_RESULT([no])
|
||||
fi
|
||||
AC_CHECK_HEADERS([openssl/conf.h openssl/engine.h openssl/bn.h openssl/dh.h openssl/dsa.h openssl/rsa.h openssl/core_names.h openssl/param_build.h],,, [AC_INCLUDES_DEFAULT])
|
||||
AC_CHECK_FUNCS([OPENSSL_config EVP_sha1 EVP_sha256 EVP_sha512 FIPS_mode EVP_default_properties_is_fips_enabled EVP_MD_CTX_new OpenSSL_add_all_digests OPENSSL_init_crypto EVP_cleanup ENGINE_cleanup ERR_load_crypto_strings CRYPTO_cleanup_all_ex_data ERR_free_strings RAND_cleanup DSA_SIG_set0 EVP_dss1 EVP_DigestVerify EVP_aes_256_cbc EVP_EncryptInit_ex HMAC_Init_ex CRYPTO_THREADID_set_callback EVP_MAC_CTX_set_params OSSL_PARAM_BLD_new BIO_set_callback_ex])
|
||||
AC_CHECK_FUNCS([OPENSSL_config EVP_sha1 EVP_sha256 EVP_sha512 FIPS_mode EVP_default_properties_is_fips_enabled EVP_MD_CTX_new OpenSSL_add_all_digests OPENSSL_init_crypto EVP_cleanup ENGINE_cleanup ERR_load_crypto_strings CRYPTO_cleanup_all_ex_data ERR_free_strings RAND_cleanup DSA_SIG_set0 EVP_dss1 EVP_DigestVerify EVP_aes_256_cbc EVP_EncryptInit_ex HMAC_Init_ex CRYPTO_THREADID_set_callback EVP_MAC_CTX_set_params OSSL_PARAM_BLD_new BIO_set_callback_ex SSL_CTX_set_tmp_ecdh])
|
||||
|
||||
# these check_funcs need -lssl
|
||||
BAKLIBS="$LIBS"
|
||||
@@ -1173,8 +1228,17 @@ case "$enable_ecdsa" in
|
||||
;;
|
||||
*)
|
||||
if test $USE_NSS = "no" -a $USE_NETTLE = "no"; then
|
||||
AC_CHECK_FUNC(ECDSA_sign, [], [AC_MSG_ERROR([OpenSSL does not support ECDSA: please upgrade or rerun with --disable-ecdsa])])
|
||||
AC_CHECK_FUNC(SHA384_Init, [], [AC_MSG_ERROR([OpenSSL does not support SHA384: please upgrade or rerun with --disable-ecdsa])])
|
||||
AC_CHECK_FUNC(EVP_PKEY_fromdata, [
|
||||
# with EVP_PKEY_fromdata, check if EC is not disabled
|
||||
AC_CHECK_DECL([OPENSSL_NO_EC], [AC_MSG_ERROR([OpenSSL does not support ECDSA: please upgrade or rerun with --disable-ecdsa])
|
||||
], [], [AC_INCLUDES_DEFAULT
|
||||
#include <openssl/evp.h>
|
||||
])
|
||||
], [
|
||||
# without EVP_PKEY_fromdata, older openssl, check for support
|
||||
AC_CHECK_FUNC(ECDSA_sign, [], [AC_MSG_ERROR([OpenSSL does not support ECDSA: please upgrade or rerun with --disable-ecdsa])])
|
||||
AC_CHECK_FUNC(SHA384_Init, [], [AC_MSG_ERROR([OpenSSL does not support SHA384: please upgrade or rerun with --disable-ecdsa])])
|
||||
])
|
||||
AC_CHECK_DECLS([NID_X9_62_prime256v1, NID_secp384r1], [], [AC_MSG_ERROR([OpenSSL does not support the ECDSA curves: please upgrade or rerun with --disable-ecdsa])], [AC_INCLUDES_DEFAULT
|
||||
#include <openssl/evp.h>
|
||||
])
|
||||
@@ -1515,6 +1579,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=""
|
||||
@@ -1525,13 +1647,17 @@ if test x_$enable_static_exe = x_yes; then
|
||||
if test "$on_mingw" = yes; then
|
||||
staticexe="-all-static"
|
||||
# for static compile, include gdi32 and zlib here.
|
||||
if echo $LIBS | grep 'lgdi32' >/dev/null; then
|
||||
if echo "$LIBS" | grep 'lgdi32' >/dev/null; then
|
||||
:
|
||||
else
|
||||
LIBS="$LIBS -lgdi32"
|
||||
fi
|
||||
AC_CHECK_LIB([z], [compress], [ LIBS="$LIBS -lz" ])
|
||||
LIBS="$LIBS -l:libssp.a"
|
||||
if echo "$LIBS" | grep -e "libssp.a" -e "lssp" >/dev/null; then
|
||||
:
|
||||
else
|
||||
LIBS="$LIBS -l:libssp.a"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
@@ -1548,7 +1674,11 @@ if test x_$enable_fully_static = x_yes; then
|
||||
LIBS="$LIBS -lgdi32"
|
||||
fi
|
||||
AC_CHECK_LIB([z], [compress], [ LIBS="$LIBS -lz" ])
|
||||
LIBS="$LIBS -l:libssp.a"
|
||||
if echo "$LIBS" | grep -e "libssp.a" -e "lssp" >/dev/null; then
|
||||
:
|
||||
else
|
||||
LIBS="$LIBS -l:libssp.a"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
@@ -1568,7 +1698,11 @@ if test "$USE_WINSOCK" = 1; then
|
||||
#include <windows.h>
|
||||
])
|
||||
AC_CHECK_TOOL(WINDRES, windres)
|
||||
LIBS="$LIBS -liphlpapi -lcrypt32"
|
||||
if echo "$LIBS" | grep crypt32 >/dev/null; then
|
||||
LIBS="$LIBS -liphlpapi"
|
||||
else
|
||||
LIBS="$LIBS -liphlpapi -lcrypt32"
|
||||
fi
|
||||
WINAPPS="unbound-service-install.exe unbound-service-remove.exe anchor-update.exe"
|
||||
AC_SUBST(WINAPPS)
|
||||
WIN_DAEMON_SRC="winrc/win_svc.c winrc/w_inst.c"
|
||||
@@ -1818,10 +1952,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
|
||||
@@ -1902,15 +2038,17 @@ case "$enable_ipset" in
|
||||
IPSET_OBJ="ipset.lo"
|
||||
AC_SUBST(IPSET_OBJ)
|
||||
|
||||
# mnl
|
||||
AC_ARG_WITH(libmnl, AS_HELP_STRING([--with-libmnl=path],[specify explicit path for libmnl.]),
|
||||
# BSD's pf
|
||||
AC_CHECK_HEADERS([net/pfvar.h], [], [
|
||||
# mnl
|
||||
AC_ARG_WITH(libmnl, AS_HELP_STRING([--with-libmnl=path],[specify explicit path for libmnl.]),
|
||||
[ ],[ withval="yes" ])
|
||||
found_libmnl="no"
|
||||
AC_MSG_CHECKING(for libmnl)
|
||||
if test x_$withval = x_ -o x_$withval = x_yes; then
|
||||
found_libmnl="no"
|
||||
AC_MSG_CHECKING(for libmnl)
|
||||
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
|
||||
fi
|
||||
for dir in $withval ; do
|
||||
if test -f "$dir/include/libmnl/libmnl.h" -o -f "$dir/include/libmnl/libmnl/libmnl.h"; then
|
||||
found_libmnl="yes"
|
||||
dnl assume /usr is in default path.
|
||||
@@ -1928,10 +2066,14 @@ case "$enable_ipset" in
|
||||
LIBS="$LIBS -lmnl"
|
||||
break;
|
||||
fi
|
||||
done
|
||||
if test x_$found_libmnl != x_yes; then
|
||||
AC_MSG_ERROR([Could not find libmnl, libmnl.h])
|
||||
fi
|
||||
done
|
||||
if test x_$found_libmnl != x_yes; then
|
||||
AC_MSG_ERROR([Could not find libmnl, libmnl.h])
|
||||
fi
|
||||
], [
|
||||
#include <netinet/in.h>
|
||||
#include <net/if.h>
|
||||
])
|
||||
;;
|
||||
no|*)
|
||||
# nothing
|
||||
@@ -2249,6 +2391,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);
|
||||
@@ -2261,6 +2407,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 */
|
||||
@@ -2271,6 +2421,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
|
||||
|
||||
@@ -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 */
|
||||
+ }
|
||||
|
||||
@@ -22,4 +22,13 @@ pidfile=${unbound_pidfile:-"/usr/local/etc/unbound/unbound.pid"}
|
||||
command_args=${unbound_flags:-"-c /usr/local/etc/unbound/unbound.conf"}
|
||||
extra_commands="reload"
|
||||
|
||||
if test "$1" = "stop" ; then
|
||||
run_rc_command "$1"
|
||||
ret=$?
|
||||
if test $ret -eq 0; then
|
||||
rm -f "$pidfile"
|
||||
fi
|
||||
exit $ret
|
||||
fi
|
||||
|
||||
run_rc_command "$1"
|
||||
|
||||
@@ -75,6 +75,7 @@ stop() {
|
||||
retval=$?
|
||||
echo
|
||||
[ $retval -eq 0 ] && rm -f $lockfile
|
||||
[ $retval -eq 0 ] && rm -f $pidfile
|
||||
if egrep -q '^/[^[:space:]]+[[:space:]]+'${rootdir}'/dev/log' /proc/mounts; then
|
||||
umount ${rootdir}/dev/log >/dev/null 2>&1
|
||||
fi;
|
||||
|
||||
@@ -58,6 +58,7 @@ stop() {
|
||||
killproc -p $pidfile unbound
|
||||
retval=$?
|
||||
[ $retval -eq 0 ] && rm -f $lockfile
|
||||
[ $retval -eq 0 ] && rm -f $pidfile
|
||||
for mountfile in /dev/log /dev/urandom /etc/localtime /etc/resolv.conf /var/run/unbound
|
||||
do
|
||||
if egrep -q '^/[^[:space:]]+[[:space:]]+'${rootdir}''${mountfile}'' /proc/mounts; then
|
||||
|
||||
@@ -75,6 +75,7 @@ stop() {
|
||||
retval=$?
|
||||
echo
|
||||
[ $retval -eq 0 ] && rm -f $lockfile
|
||||
[ $retval -eq 0 ] && rm -f $pidfile
|
||||
if egrep -q '^/[^[:space:]]+[[:space:]]+'${rootdir}'/dev/log' /proc/mounts; then
|
||||
umount ${rootdir}/dev/log >/dev/null 2>&1
|
||||
fi;
|
||||
|
||||
@@ -42,8 +42,8 @@
|
||||
[Unit]
|
||||
Description=Validating, recursive, and caching DNS resolver
|
||||
Documentation=man:unbound(8)
|
||||
After=network.target
|
||||
Before=network-online.target nss-lookup.target
|
||||
After=network-online.target
|
||||
Before=nss-lookup.target
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
|
||||
@@ -14,8 +14,8 @@
|
||||
[Unit]
|
||||
Description=Validating, recursive, and caching DNS resolver
|
||||
Documentation=man:unbound(8)
|
||||
After=network.target
|
||||
Before=network-online.target nss-lookup.target
|
||||
After=network-online.target
|
||||
Before=nss-lookup.target
|
||||
Wants=nss-lookup.target
|
||||
|
||||
[Install]
|
||||
|
||||
+16
-7
@@ -839,6 +839,7 @@ int print_deleg_lookup(RES* ssl, struct worker* worker, uint8_t* nm,
|
||||
char b[260];
|
||||
struct query_info qinfo;
|
||||
struct iter_hints_stub* stub;
|
||||
int nolock = 0;
|
||||
regional_free_all(region);
|
||||
qinfo.qname = nm;
|
||||
qinfo.qname_len = nmlen;
|
||||
@@ -850,13 +851,16 @@ int print_deleg_lookup(RES* ssl, struct worker* worker, uint8_t* nm,
|
||||
if(!ssl_printf(ssl, "The following name servers are used for lookup "
|
||||
"of %s\n", b))
|
||||
return 0;
|
||||
|
||||
dp = forwards_lookup(worker->env.fwds, nm, qinfo.qclass);
|
||||
|
||||
dp = forwards_lookup(worker->env.fwds, nm, qinfo.qclass, nolock);
|
||||
if(dp) {
|
||||
if(!ssl_printf(ssl, "forwarding request:\n"))
|
||||
if(!ssl_printf(ssl, "forwarding request:\n")) {
|
||||
lock_rw_unlock(&worker->env.fwds->lock);
|
||||
return 0;
|
||||
}
|
||||
print_dp_main(ssl, dp, NULL);
|
||||
print_dp_details(ssl, worker, dp);
|
||||
lock_rw_unlock(&worker->env.fwds->lock);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -892,21 +896,26 @@ int print_deleg_lookup(RES* ssl, struct worker* worker, uint8_t* nm,
|
||||
return 0;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
stub = hints_lookup_stub(worker->env.hints, nm, qinfo.qclass,
|
||||
dp);
|
||||
dp, nolock);
|
||||
if(stub) {
|
||||
if(stub->noprime) {
|
||||
if(!ssl_printf(ssl, "The noprime stub servers "
|
||||
"are used:\n"))
|
||||
"are used:\n")) {
|
||||
lock_rw_unlock(&worker->env.hints->lock);
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
if(!ssl_printf(ssl, "The stub is primed "
|
||||
"with servers:\n"))
|
||||
"with servers:\n")) {
|
||||
lock_rw_unlock(&worker->env.hints->lock);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
print_dp_main(ssl, stub->dp, NULL);
|
||||
print_dp_details(ssl, worker, stub->dp);
|
||||
lock_rw_unlock(&worker->env.hints->lock);
|
||||
} else {
|
||||
print_dp_main(ssl, dp, msg);
|
||||
print_dp_details(ssl, worker, dp);
|
||||
|
||||
+71
-12
@@ -91,6 +91,8 @@
|
||||
#include "util/net_help.h"
|
||||
#include "sldns/keyraw.h"
|
||||
#include "respip/respip.h"
|
||||
#include "iterator/iter_fwd.h"
|
||||
#include "iterator/iter_hints.h"
|
||||
#include <signal.h>
|
||||
|
||||
#ifdef HAVE_SYSTEMD
|
||||
@@ -99,6 +101,9 @@
|
||||
#ifdef HAVE_NETDB_H
|
||||
#include <netdb.h>
|
||||
#endif
|
||||
#ifdef USE_CACHEDB
|
||||
#include "cachedb/cachedb.h"
|
||||
#endif
|
||||
|
||||
/** How many quit requests happened. */
|
||||
static int sig_record_quit = 0;
|
||||
@@ -260,6 +265,7 @@ daemon_init(void)
|
||||
free(daemon);
|
||||
return NULL;
|
||||
}
|
||||
daemon->env->modstack = &daemon->mods;
|
||||
/* init edns_known_options */
|
||||
if(!edns_known_options_init(daemon->env)) {
|
||||
free(daemon->env);
|
||||
@@ -321,17 +327,15 @@ static int setup_acl_for_ports(struct acl_list* list,
|
||||
struct listen_port* port_list)
|
||||
{
|
||||
struct acl_addr* acl_node;
|
||||
struct addrinfo* addr;
|
||||
for(; port_list; port_list=port_list->next) {
|
||||
if(!port_list->socket) {
|
||||
/* This is mainly for testbound where port_list is
|
||||
* empty. */
|
||||
continue;
|
||||
}
|
||||
addr = port_list->socket->addr;
|
||||
if(!(acl_node = acl_interface_insert(list,
|
||||
(struct sockaddr_storage*)addr->ai_addr,
|
||||
(socklen_t)addr->ai_addrlen,
|
||||
(struct sockaddr_storage*)port_list->socket->addr,
|
||||
port_list->socket->addrlen,
|
||||
acl_refuse))) {
|
||||
return 0;
|
||||
}
|
||||
@@ -340,7 +344,7 @@ static int setup_acl_for_ports(struct acl_list* list,
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
int
|
||||
daemon_open_shared_ports(struct daemon* daemon)
|
||||
{
|
||||
log_assert(daemon);
|
||||
@@ -440,6 +444,19 @@ daemon_open_shared_ports(struct daemon* daemon)
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
daemon_privileged(struct daemon* daemon)
|
||||
{
|
||||
daemon->env->cfg = daemon->cfg;
|
||||
daemon->env->alloc = &daemon->superalloc;
|
||||
daemon->env->worker = NULL;
|
||||
if(!modstack_call_startup(&daemon->mods, daemon->cfg->module_conf,
|
||||
daemon->env)) {
|
||||
fatal_exit("failed to startup modules");
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup modules. setup module stack.
|
||||
* @param daemon: the daemon
|
||||
@@ -449,11 +466,15 @@ static void daemon_setup_modules(struct daemon* daemon)
|
||||
daemon->env->cfg = daemon->cfg;
|
||||
daemon->env->alloc = &daemon->superalloc;
|
||||
daemon->env->worker = NULL;
|
||||
daemon->env->need_to_validate = 0; /* set by module init below */
|
||||
if(!modstack_setup(&daemon->mods, daemon->cfg->module_conf,
|
||||
daemon->env)) {
|
||||
fatal_exit("failed to setup modules");
|
||||
if(daemon->mods_inited) {
|
||||
modstack_call_deinit(&daemon->mods, daemon->env);
|
||||
}
|
||||
daemon->env->need_to_validate = 0; /* set by module init below */
|
||||
if(!modstack_call_init(&daemon->mods, daemon->cfg->module_conf,
|
||||
daemon->env)) {
|
||||
fatal_exit("failed to init modules");
|
||||
}
|
||||
daemon->mods_inited = 1;
|
||||
log_edns_known_options(VERB_ALGO, daemon->env);
|
||||
}
|
||||
|
||||
@@ -499,7 +520,10 @@ daemon_clear_allocs(struct daemon* daemon)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i=0; i<daemon->num; i++) {
|
||||
/* daemon->num may be different during reloads (after configuration
|
||||
* read). Use old_num which has the correct value used to setup the
|
||||
* worker_allocs */
|
||||
for(i=0; i<daemon->old_num; i++) {
|
||||
alloc_clear(daemon->worker_allocs[i]);
|
||||
free(daemon->worker_allocs[i]);
|
||||
}
|
||||
@@ -533,6 +557,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,11 +741,25 @@ 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");
|
||||
if(!local_zones_apply_cfg(daemon->local_zones, daemon->cfg))
|
||||
fatal_exit("Could not set up local zones");
|
||||
if(!(daemon->env->fwds = forwards_create()) ||
|
||||
!forwards_apply_cfg(daemon->env->fwds, daemon->cfg))
|
||||
fatal_exit("Could not set forward zones");
|
||||
if(!(daemon->env->hints = hints_create()) ||
|
||||
!hints_apply_cfg(daemon->env->hints, daemon->cfg))
|
||||
fatal_exit("Could not set root or stub hints");
|
||||
|
||||
/* process raw response-ip configuration data */
|
||||
if(!(daemon->respip_set = respip_set_create()))
|
||||
@@ -740,6 +784,10 @@ daemon_fork(struct daemon* daemon)
|
||||
if(!edns_strings_apply_cfg(daemon->env->edns_strings, daemon->cfg))
|
||||
fatal_exit("Could not set up EDNS strings");
|
||||
|
||||
#ifdef USE_CACHEDB
|
||||
daemon->env->cachedb_enabled = cachedb_is_enabled(&daemon->mods,
|
||||
daemon->env);
|
||||
#endif
|
||||
/* response-ip-xxx options don't work as expected without the respip
|
||||
* module. To avoid run-time operational surprise we reject such
|
||||
* configuration. */
|
||||
@@ -832,6 +880,10 @@ daemon_cleanup(struct daemon* daemon)
|
||||
slabhash_clear(daemon->env->msg_cache);
|
||||
}
|
||||
daemon->old_num = daemon->num; /* save the current num */
|
||||
forwards_delete(daemon->env->fwds);
|
||||
daemon->env->fwds = NULL;
|
||||
hints_delete(daemon->env->hints);
|
||||
daemon->env->hints = NULL;
|
||||
local_zones_delete(daemon->local_zones);
|
||||
daemon->local_zones = NULL;
|
||||
respip_set_delete(daemon->respip_set);
|
||||
@@ -840,7 +892,7 @@ daemon_cleanup(struct daemon* daemon)
|
||||
daemon->views = NULL;
|
||||
if(daemon->env->auth_zones)
|
||||
auth_zones_cleanup(daemon->env->auth_zones);
|
||||
/* key cache is cleared by module desetup during next daemon_fork() */
|
||||
/* key cache is cleared by module deinit during next daemon_fork() */
|
||||
daemon_remote_clear(daemon->rc);
|
||||
for(i=0; i<daemon->num; i++)
|
||||
worker_delete(daemon->workers[i]);
|
||||
@@ -860,6 +912,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;
|
||||
}
|
||||
@@ -870,7 +926,9 @@ daemon_delete(struct daemon* daemon)
|
||||
size_t i;
|
||||
if(!daemon)
|
||||
return;
|
||||
modstack_desetup(&daemon->mods, daemon->env);
|
||||
modstack_call_deinit(&daemon->mods, daemon->env);
|
||||
modstack_call_destartup(&daemon->mods, daemon->env);
|
||||
modstack_free(&daemon->mods);
|
||||
daemon_remote_delete(daemon->rc);
|
||||
for(i = 0; i < daemon->num_ports; i++)
|
||||
listening_ports_free(daemon->ports[i]);
|
||||
@@ -889,6 +947,7 @@ 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);
|
||||
|
||||
@@ -58,6 +58,8 @@ struct ub_randstate;
|
||||
struct daemon_remote;
|
||||
struct respip_set;
|
||||
struct shm_main_info;
|
||||
struct doq_table;
|
||||
struct cookie_secrets;
|
||||
|
||||
#include "dnstap/dnstap_config.h"
|
||||
#ifdef USE_DNSTAP
|
||||
@@ -115,6 +117,8 @@ struct daemon {
|
||||
struct module_env* env;
|
||||
/** stack of module callbacks */
|
||||
struct module_stack mods;
|
||||
/** The module stack has been inited */
|
||||
int mods_inited;
|
||||
/** access control, which client IPs are allowed to connect */
|
||||
struct acl_list* acl;
|
||||
/** access control, which interfaces are allowed to connect */
|
||||
@@ -144,8 +148,12 @@ 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;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -162,6 +170,15 @@ struct daemon* daemon_init(void);
|
||||
*/
|
||||
int daemon_open_shared_ports(struct daemon* daemon);
|
||||
|
||||
/**
|
||||
* Do daemon setup that needs privileges
|
||||
* like opening privileged ports or opening device files.
|
||||
* The cfg member pointer must have been set for the daemon.
|
||||
* @param daemon: the daemon.
|
||||
* @return: false on error.
|
||||
*/
|
||||
int daemon_privileged(struct daemon* daemon);
|
||||
|
||||
/**
|
||||
* Fork workers and start service.
|
||||
* When the routine exits, it is no longer forked.
|
||||
|
||||
+562
-130
File diff suppressed because it is too large
Load Diff
+21
-2
@@ -346,6 +346,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);
|
||||
@@ -391,6 +397,13 @@ void server_stats_obtain(struct worker* worker, struct worker* who,
|
||||
else worker_send_cmd(who, worker_cmd_stats_noreset);
|
||||
verbose(VERB_ALGO, "wait for stats reply");
|
||||
if(tube_wait_timeout(worker->cmd, STATS_THREAD_WAIT) == 0) {
|
||||
#if defined(HAVE_PTHREAD) && defined(SIZEOF_PTHREAD_T) && defined(SIZEOF_UNSIGNED_LONG)
|
||||
# if SIZEOF_PTHREAD_T == SIZEOF_UNSIGNED_LONG
|
||||
unsigned long pthid = 0;
|
||||
if(verbosity >= VERB_OPS)
|
||||
memcpy(&pthid, &who->thr_id, sizeof(unsigned long));
|
||||
# endif
|
||||
#endif
|
||||
verbose(VERB_OPS, "no response from thread %d"
|
||||
#ifdef HAVE_GETTID
|
||||
" LWP %u"
|
||||
@@ -407,7 +420,7 @@ void server_stats_obtain(struct worker* worker, struct worker* who,
|
||||
#endif
|
||||
#if defined(HAVE_PTHREAD) && defined(SIZEOF_PTHREAD_T) && defined(SIZEOF_UNSIGNED_LONG)
|
||||
# if SIZEOF_PTHREAD_T == SIZEOF_UNSIGNED_LONG
|
||||
, (unsigned long)*((unsigned long*)&who->thr_id)
|
||||
, pthid
|
||||
# endif
|
||||
#endif
|
||||
);
|
||||
@@ -467,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;
|
||||
@@ -526,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
|
||||
@@ -535,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))
|
||||
|
||||
+23
-20
@@ -366,9 +366,8 @@ readpid (const char* file)
|
||||
/** write pid to file.
|
||||
* @param pidfile: file name of pid file.
|
||||
* @param pid: pid to write to file.
|
||||
* @return false on failure
|
||||
*/
|
||||
static int
|
||||
static void
|
||||
writepid (const char* pidfile, pid_t pid)
|
||||
{
|
||||
int fd;
|
||||
@@ -383,7 +382,7 @@ writepid (const char* pidfile, pid_t pid)
|
||||
, 0644)) == -1) {
|
||||
log_err("cannot open pidfile %s: %s",
|
||||
pidfile, strerror(errno));
|
||||
return 0;
|
||||
return;
|
||||
}
|
||||
while(count < strlen(pidbuf)) {
|
||||
ssize_t r = write(fd, pidbuf+count, strlen(pidbuf)-count);
|
||||
@@ -393,17 +392,16 @@ writepid (const char* pidfile, pid_t pid)
|
||||
log_err("cannot write to pidfile %s: %s",
|
||||
pidfile, strerror(errno));
|
||||
close(fd);
|
||||
return 0;
|
||||
return;
|
||||
} else if(r == 0) {
|
||||
log_err("cannot write any bytes to pidfile %s: "
|
||||
"write returns 0 bytes written", pidfile);
|
||||
close(fd);
|
||||
return 0;
|
||||
return;
|
||||
}
|
||||
count += r;
|
||||
}
|
||||
close(fd);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -475,7 +473,11 @@ perform_setup(struct daemon* daemon, struct config_file* cfg, int debug_mode,
|
||||
#endif
|
||||
#ifdef HAVE_GETPWNAM
|
||||
struct passwd *pwd = NULL;
|
||||
#endif
|
||||
|
||||
if(!daemon_privileged(daemon))
|
||||
fatal_exit("could not do privileged setup");
|
||||
#ifdef HAVE_GETPWNAM
|
||||
if(cfg->username && cfg->username[0]) {
|
||||
if((pwd = getpwnam(cfg->username)) == NULL)
|
||||
fatal_exit("user '%s' does not exist.", cfg->username);
|
||||
@@ -545,7 +547,15 @@ perform_setup(struct daemon* daemon, struct config_file* cfg, int debug_mode,
|
||||
cfg, 1);
|
||||
if(!daemon->pidfile)
|
||||
fatal_exit("pidfile alloc: out of memory");
|
||||
checkoldpid(daemon->pidfile, pidinchroot);
|
||||
/* Check old pid if there is no username configured.
|
||||
* With a username, the assumption is that the privilege
|
||||
* drop makes a pidfile not removed when the server stopped
|
||||
* last time. The server does not chown the pidfile for it,
|
||||
* because that creates privilege escape problems, with the
|
||||
* pidfile writable by unprivileged users, but used by
|
||||
* privileged users. */
|
||||
if(!(cfg->username && cfg->username[0]))
|
||||
checkoldpid(daemon->pidfile, pidinchroot);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -557,18 +567,7 @@ perform_setup(struct daemon* daemon, struct config_file* cfg, int debug_mode,
|
||||
/* write new pidfile (while still root, so can be outside chroot) */
|
||||
#ifdef HAVE_KILL
|
||||
if(cfg->pidfile && cfg->pidfile[0] && need_pidfile) {
|
||||
if(writepid(daemon->pidfile, getpid())) {
|
||||
if(cfg->username && cfg->username[0] && cfg_uid != (uid_t)-1 &&
|
||||
pidinchroot) {
|
||||
# ifdef HAVE_CHOWN
|
||||
if(chown(daemon->pidfile, cfg_uid, cfg_gid) == -1) {
|
||||
verbose(VERB_QUERY, "cannot chown %u.%u %s: %s",
|
||||
(unsigned)cfg_uid, (unsigned)cfg_gid,
|
||||
daemon->pidfile, strerror(errno));
|
||||
}
|
||||
# endif /* HAVE_CHOWN */
|
||||
}
|
||||
}
|
||||
writepid(daemon->pidfile, getpid());
|
||||
}
|
||||
#else
|
||||
(void)daemon;
|
||||
@@ -746,7 +745,11 @@ run_daemon(const char* cfgfile, int cmdline_verbose, int debug_mode, int need_pi
|
||||
if(daemon->pidfile) {
|
||||
int fd;
|
||||
/* truncate pidfile */
|
||||
fd = open(daemon->pidfile, O_WRONLY | O_TRUNC, 0644);
|
||||
fd = open(daemon->pidfile, O_WRONLY | O_TRUNC
|
||||
#ifdef O_NOFOLLOW
|
||||
| O_NOFOLLOW
|
||||
#endif
|
||||
, 0644);
|
||||
if(fd != -1)
|
||||
close(fd);
|
||||
/* delete pidfile */
|
||||
|
||||
+54
-48
@@ -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) {
|
||||
@@ -659,17 +661,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(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 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(!reply_info_can_answer_expired(rep, timenow))
|
||||
return 0;
|
||||
if(!rrset_array_lock(rep->ref, rep->rrset_count, 0))
|
||||
return 0;
|
||||
@@ -1151,7 +1154,7 @@ deny_refuse(struct comm_point* c, enum acl_access acl,
|
||||
log_assert(sldns_buffer_limit(c->buffer) >= LDNS_HEADER_SIZE
|
||||
&& LDNS_QDCOUNT(sldns_buffer_begin(c->buffer)) == 1);
|
||||
|
||||
sldns_buffer_skip(c->buffer, LDNS_HEADER_SIZE); /* skip header */
|
||||
sldns_buffer_set_position(c->buffer, LDNS_HEADER_SIZE); /* skip header */
|
||||
|
||||
/* check additional section is present and that we respond with EDEs */
|
||||
if(LDNS_ARCOUNT(sldns_buffer_begin(c->buffer)) != 1
|
||||
@@ -1163,6 +1166,7 @@ deny_refuse(struct comm_point* c, enum acl_access acl,
|
||||
LDNS_QR_SET(sldns_buffer_begin(c->buffer));
|
||||
LDNS_RCODE_SET(sldns_buffer_begin(c->buffer),
|
||||
LDNS_RCODE_REFUSED);
|
||||
sldns_buffer_set_position(c->buffer, LDNS_HEADER_SIZE);
|
||||
sldns_buffer_flip(c->buffer);
|
||||
return 1;
|
||||
}
|
||||
@@ -1326,15 +1330,6 @@ deny_refuse_non_local(struct comm_point* c, enum acl_access acl,
|
||||
worker, repinfo, acladdr, ede, check_result);
|
||||
}
|
||||
|
||||
/* Returns 1 if the ip rate limit check can happen before EDNS parsing,
|
||||
* else 0 */
|
||||
static int
|
||||
pre_edns_ip_ratelimit_check(enum acl_access acl)
|
||||
{
|
||||
if(acl == acl_allow_cookie) return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Check if the query is blocked by source IP rate limiting.
|
||||
* Returns 1 if it passes the check, 0 otherwise. */
|
||||
static int
|
||||
@@ -1462,8 +1457,8 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
|
||||
*/
|
||||
if(worker->dtenv.log_client_query_messages) {
|
||||
log_addr(VERB_ALGO, "request from client", &repinfo->client_addr, repinfo->client_addrlen);
|
||||
log_addr(VERB_ALGO, "to local addr", (void*)repinfo->c->socket->addr->ai_addr, repinfo->c->socket->addr->ai_addrlen);
|
||||
dt_msg_send_client_query(&worker->dtenv, &repinfo->client_addr, (void*)repinfo->c->socket->addr->ai_addr, c->type, c->buffer,
|
||||
log_addr(VERB_ALGO, "to local addr", (void*)repinfo->c->socket->addr, repinfo->c->socket->addrlen);
|
||||
dt_msg_send_client_query(&worker->dtenv, &repinfo->client_addr, (void*)repinfo->c->socket->addr, c->type, c->ssl, c->buffer,
|
||||
((worker->env.cfg->sock_queue_timeout && timeval_isset(&c->recv_tv))?&c->recv_tv:NULL));
|
||||
}
|
||||
#endif
|
||||
@@ -1498,7 +1493,9 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
|
||||
}
|
||||
|
||||
worker->stats.num_queries++;
|
||||
pre_edns_ip_ratelimit = pre_edns_ip_ratelimit_check(acl);
|
||||
pre_edns_ip_ratelimit = !worker->env.cfg->do_answer_cookie
|
||||
|| sldns_buffer_limit(c->buffer) < LDNS_HEADER_SIZE
|
||||
|| LDNS_ARCOUNT(sldns_buffer_begin(c->buffer)) == 0;
|
||||
|
||||
/* If the IP rate limiting check needs extra EDNS information (e.g.,
|
||||
* DNS Cookies) postpone the check until after EDNS is parsed. */
|
||||
@@ -1572,7 +1569,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,
|
||||
@@ -1949,10 +1947,10 @@ send_reply_rc:
|
||||
/*
|
||||
* sending src (client)/dst (local service) addresses over DNSTAP from send_reply code label (when we serviced local zone for ex.)
|
||||
*/
|
||||
if(worker->dtenv.log_client_response_messages) {
|
||||
log_addr(VERB_ALGO, "from local addr", (void*)repinfo->c->socket->addr->ai_addr, repinfo->c->socket->addr->ai_addrlen);
|
||||
if(worker->dtenv.log_client_response_messages && rc !=0) {
|
||||
log_addr(VERB_ALGO, "from local addr", (void*)repinfo->c->socket->addr, repinfo->c->socket->addrlen);
|
||||
log_addr(VERB_ALGO, "response to client", &repinfo->client_addr, repinfo->client_addrlen);
|
||||
dt_msg_send_client_response(&worker->dtenv, &repinfo->client_addr, (void*)repinfo->c->socket->addr->ai_addr, c->type, c->buffer);
|
||||
dt_msg_send_client_response(&worker->dtenv, &repinfo->client_addr, (void*)repinfo->c->socket->addr, c->type, c->ssl, c->buffer);
|
||||
}
|
||||
#endif
|
||||
if(worker->env.cfg->log_replies)
|
||||
@@ -1966,11 +1964,15 @@ send_reply_rc:
|
||||
qinfo.qname = qinfo.local_alias->rrset->rk.dname;
|
||||
log_reply_info(NO_VERBOSE, &qinfo,
|
||||
&repinfo->client_addr, repinfo->client_addrlen,
|
||||
tv, 1, c->buffer);
|
||||
tv, 1, c->buffer,
|
||||
(worker->env.cfg->log_destaddr?(void*)repinfo->c->socket->addr:NULL),
|
||||
c->type);
|
||||
} else {
|
||||
log_reply_info(NO_VERBOSE, &qinfo,
|
||||
&repinfo->client_addr, repinfo->client_addrlen,
|
||||
tv, 1, c->buffer);
|
||||
tv, 1, c->buffer,
|
||||
(worker->env.cfg->log_destaddr?(void*)repinfo->c->socket->addr:NULL),
|
||||
c->type);
|
||||
}
|
||||
}
|
||||
#ifdef USE_DNSCRYPT
|
||||
@@ -2172,7 +2174,9 @@ worker_init(struct worker* worker, struct config_file *cfg,
|
||||
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);
|
||||
dtenv, worker->daemon->doq_table, worker->env.rnd,
|
||||
cfg->ssl_service_key, cfg->ssl_service_pem, cfg,
|
||||
worker_handle_request, worker);
|
||||
if(!worker->front) {
|
||||
log_err("could not create listening sockets");
|
||||
worker_delete(worker);
|
||||
@@ -2263,18 +2267,6 @@ worker_init(struct worker* worker, struct config_file *cfg,
|
||||
worker_delete(worker);
|
||||
return 0;
|
||||
}
|
||||
if(!(worker->env.fwds = forwards_create()) ||
|
||||
!forwards_apply_cfg(worker->env.fwds, cfg)) {
|
||||
log_err("Could not set forward zones");
|
||||
worker_delete(worker);
|
||||
return 0;
|
||||
}
|
||||
if(!(worker->env.hints = hints_create()) ||
|
||||
!hints_apply_cfg(worker->env.hints, cfg)) {
|
||||
log_err("Could not set root or stub hints");
|
||||
worker_delete(worker);
|
||||
return 0;
|
||||
}
|
||||
/* one probe timer per process -- if we have 5011 anchors */
|
||||
if(autr_get_num_anchors(worker->env.anchors) > 0
|
||||
#ifndef THREADS_DISABLED
|
||||
@@ -2347,8 +2339,6 @@ worker_delete(struct worker* worker)
|
||||
outside_network_quit_prepare(worker->back);
|
||||
mesh_delete(worker->env.mesh);
|
||||
sldns_buffer_free(worker->env.scratch_buffer);
|
||||
forwards_delete(worker->env.fwds);
|
||||
hints_delete(worker->env.hints);
|
||||
listen_delete(worker->front);
|
||||
outside_network_delete(worker->back);
|
||||
comm_signal_delete(worker->comsig);
|
||||
@@ -2520,3 +2510,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
|
||||
|
||||
+6
-4
@@ -657,7 +657,7 @@ 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,
|
||||
0, qstate->prefetch_leeway, 0, NULL,
|
||||
qstate->query_flags, qstate->qstarttime))
|
||||
log_err("out of memory");
|
||||
|
||||
@@ -701,6 +701,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 +847,7 @@ dns64_adjust_a(int id, struct module_qstate* super, struct module_qstate* qstate
|
||||
*/
|
||||
cp = construct_reply_info_base(super->region, rep->flags, rep->qdcount,
|
||||
rep->ttl, rep->prefetch_ttl, rep->serve_expired_ttl,
|
||||
rep->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 +1008,7 @@ dns64_inform_super(struct module_qstate* qstate, int id,
|
||||
/* Store the generated response in cache. */
|
||||
if ( (!super_dq || !super_dq->started_no_cache_store) &&
|
||||
!dns_cache_store(super->env, &super->qinfo, super->return_msg->rep,
|
||||
0, 0, 0, NULL, super->query_flags, qstate->qstarttime))
|
||||
0, super->prefetch_leeway, 0, NULL, super->query_flags, qstate->qstarttime))
|
||||
log_err("out of memory");
|
||||
}
|
||||
|
||||
@@ -1044,8 +1046,8 @@ dns64_get_mem(struct module_env* env, int id)
|
||||
*/
|
||||
static struct module_func_block dns64_block = {
|
||||
"dns64",
|
||||
&dns64_init, &dns64_deinit, &dns64_operate, &dns64_inform_super,
|
||||
&dns64_clear, &dns64_get_mem
|
||||
NULL, NULL, &dns64_init, &dns64_deinit, &dns64_operate,
|
||||
&dns64_inform_super, &dns64_clear, &dns64_get_mem
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
+68
-9
@@ -86,6 +86,31 @@ dt_pack(const Dnstap__Dnstap *d, void **buf, size_t *sz)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** See if the message is sent due to dnstap sample rate */
|
||||
static int
|
||||
dt_sample_rate_limited(struct dt_env* env)
|
||||
{
|
||||
lock_basic_lock(&env->sample_lock);
|
||||
/* Sampling is every [n] packets. Where n==1, every packet is sent */
|
||||
if(env->sample_rate > 1) {
|
||||
int submit = 0;
|
||||
/* if sampling is engaged... */
|
||||
if (env->sample_rate_count > env->sample_rate) {
|
||||
/* once the count passes the limit */
|
||||
/* submit the message */
|
||||
submit = 1;
|
||||
/* and reset the count */
|
||||
env->sample_rate_count = 0;
|
||||
}
|
||||
/* increment count regardless */
|
||||
env->sample_rate_count++;
|
||||
lock_basic_unlock(&env->sample_lock);
|
||||
return !submit;
|
||||
}
|
||||
lock_basic_unlock(&env->sample_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
dt_send(const struct dt_env *env, void *buf, size_t len_buf)
|
||||
{
|
||||
@@ -146,6 +171,7 @@ dt_create(struct config_file* cfg)
|
||||
env = (struct dt_env *) calloc(1, sizeof(struct dt_env));
|
||||
if (!env)
|
||||
return NULL;
|
||||
lock_basic_init(&env->sample_lock);
|
||||
|
||||
env->dtio = dt_io_thread_create();
|
||||
if(!env->dtio) {
|
||||
@@ -241,6 +267,12 @@ dt_apply_cfg(struct dt_env *env, struct config_file *cfg)
|
||||
{
|
||||
verbose(VERB_OPS, "dnstap Message/FORWARDER_RESPONSE enabled");
|
||||
}
|
||||
lock_basic_lock(&env->sample_lock);
|
||||
if((env->sample_rate = (unsigned int)cfg->dnstap_sample_rate))
|
||||
{
|
||||
verbose(VERB_OPS, "dnstap SAMPLE_RATE enabled and set to \"%d\"", (int)env->sample_rate);
|
||||
}
|
||||
lock_basic_unlock(&env->sample_lock);
|
||||
}
|
||||
|
||||
int
|
||||
@@ -273,6 +305,7 @@ dt_delete(struct dt_env *env)
|
||||
if (!env)
|
||||
return;
|
||||
dt_io_thread_delete(env->dtio);
|
||||
lock_basic_destroy(&env->sample_lock);
|
||||
free(env->identity);
|
||||
free(env->version);
|
||||
free(env);
|
||||
@@ -305,6 +338,7 @@ dt_msg_fill_net(struct dt_msg *dm,
|
||||
struct sockaddr_storage *qs,
|
||||
struct sockaddr_storage *rs,
|
||||
enum comm_point_type cptype,
|
||||
void *cpssl,
|
||||
ProtobufCBinaryData *qaddr, protobuf_c_boolean *has_qaddr,
|
||||
uint32_t *qport, protobuf_c_boolean *has_qport,
|
||||
ProtobufCBinaryData *raddr, protobuf_c_boolean *has_raddr,
|
||||
@@ -371,13 +405,26 @@ dt_msg_fill_net(struct dt_msg *dm,
|
||||
*has_rport = 1;
|
||||
}
|
||||
|
||||
log_assert(cptype == comm_udp || cptype == comm_tcp);
|
||||
if (cptype == comm_udp) {
|
||||
/* socket_protocol */
|
||||
dm->m.socket_protocol = DNSTAP__SOCKET_PROTOCOL__UDP;
|
||||
dm->m.has_socket_protocol = 1;
|
||||
} else if (cptype == comm_tcp) {
|
||||
if (cpssl == NULL) {
|
||||
/* socket_protocol */
|
||||
dm->m.socket_protocol = DNSTAP__SOCKET_PROTOCOL__TCP;
|
||||
dm->m.has_socket_protocol = 1;
|
||||
} else {
|
||||
/* socket_protocol */
|
||||
dm->m.socket_protocol = DNSTAP__SOCKET_PROTOCOL__DOT;
|
||||
dm->m.has_socket_protocol = 1;
|
||||
}
|
||||
} else if (cptype == comm_http) {
|
||||
/* socket_protocol */
|
||||
dm->m.socket_protocol = DNSTAP__SOCKET_PROTOCOL__DOH;
|
||||
dm->m.has_socket_protocol = 1;
|
||||
} else {
|
||||
/* other socket protocol */
|
||||
dm->m.socket_protocol = DNSTAP__SOCKET_PROTOCOL__TCP;
|
||||
dm->m.has_socket_protocol = 1;
|
||||
}
|
||||
@@ -388,12 +435,16 @@ dt_msg_send_client_query(struct dt_env *env,
|
||||
struct sockaddr_storage *qsock,
|
||||
struct sockaddr_storage *rsock,
|
||||
enum comm_point_type cptype,
|
||||
void *cpssl,
|
||||
sldns_buffer *qmsg,
|
||||
struct timeval* tstamp)
|
||||
{
|
||||
struct dt_msg dm;
|
||||
struct timeval qtime;
|
||||
|
||||
if(dt_sample_rate_limited(env))
|
||||
return;
|
||||
|
||||
if(tstamp)
|
||||
memcpy(&qtime, tstamp, sizeof(qtime));
|
||||
else gettimeofday(&qtime, NULL);
|
||||
@@ -410,8 +461,7 @@ dt_msg_send_client_query(struct dt_env *env,
|
||||
dt_fill_buffer(qmsg, &dm.m.query_message, &dm.m.has_query_message);
|
||||
|
||||
/* socket_family, socket_protocol, query_address, query_port, response_address, response_port */
|
||||
log_assert(cptype == comm_udp || cptype == comm_tcp);
|
||||
dt_msg_fill_net(&dm, qsock, rsock, cptype,
|
||||
dt_msg_fill_net(&dm, qsock, rsock, cptype, cpssl,
|
||||
&dm.m.query_address, &dm.m.has_query_address,
|
||||
&dm.m.query_port, &dm.m.has_query_port,
|
||||
&dm.m.response_address, &dm.m.has_response_address,
|
||||
@@ -427,11 +477,15 @@ dt_msg_send_client_response(struct dt_env *env,
|
||||
struct sockaddr_storage *qsock,
|
||||
struct sockaddr_storage *rsock,
|
||||
enum comm_point_type cptype,
|
||||
void *cpssl,
|
||||
sldns_buffer *rmsg)
|
||||
{
|
||||
struct dt_msg dm;
|
||||
struct timeval rtime;
|
||||
|
||||
if(dt_sample_rate_limited(env))
|
||||
return;
|
||||
|
||||
gettimeofday(&rtime, NULL);
|
||||
|
||||
/* type */
|
||||
@@ -446,8 +500,7 @@ dt_msg_send_client_response(struct dt_env *env,
|
||||
dt_fill_buffer(rmsg, &dm.m.response_message, &dm.m.has_response_message);
|
||||
|
||||
/* socket_family, socket_protocol, query_address, query_port, response_address, response_port */
|
||||
log_assert(cptype == comm_udp || cptype == comm_tcp);
|
||||
dt_msg_fill_net(&dm, qsock, rsock, cptype,
|
||||
dt_msg_fill_net(&dm, qsock, rsock, cptype, cpssl,
|
||||
&dm.m.query_address, &dm.m.has_query_address,
|
||||
&dm.m.query_port, &dm.m.has_query_port,
|
||||
&dm.m.response_address, &dm.m.has_response_address,
|
||||
@@ -462,6 +515,7 @@ dt_msg_send_outside_query(struct dt_env *env,
|
||||
struct sockaddr_storage *rsock,
|
||||
struct sockaddr_storage *qsock,
|
||||
enum comm_point_type cptype,
|
||||
void *cpssl,
|
||||
uint8_t *zone, size_t zone_len,
|
||||
sldns_buffer *qmsg)
|
||||
{
|
||||
@@ -469,6 +523,9 @@ dt_msg_send_outside_query(struct dt_env *env,
|
||||
struct timeval qtime;
|
||||
uint16_t qflags;
|
||||
|
||||
if(dt_sample_rate_limited(env))
|
||||
return;
|
||||
|
||||
gettimeofday(&qtime, NULL);
|
||||
qflags = sldns_buffer_read_u16_at(qmsg, 2);
|
||||
|
||||
@@ -497,8 +554,7 @@ dt_msg_send_outside_query(struct dt_env *env,
|
||||
dt_fill_buffer(qmsg, &dm.m.query_message, &dm.m.has_query_message);
|
||||
|
||||
/* socket_family, socket_protocol, response_address, response_port, query_address, query_port */
|
||||
log_assert(cptype == comm_udp || cptype == comm_tcp);
|
||||
dt_msg_fill_net(&dm, rsock, qsock, cptype,
|
||||
dt_msg_fill_net(&dm, rsock, qsock, cptype, cpssl,
|
||||
&dm.m.response_address, &dm.m.has_response_address,
|
||||
&dm.m.response_port, &dm.m.has_response_port,
|
||||
&dm.m.query_address, &dm.m.has_query_address,
|
||||
@@ -513,6 +569,7 @@ dt_msg_send_outside_response(struct dt_env *env,
|
||||
struct sockaddr_storage *rsock,
|
||||
struct sockaddr_storage *qsock,
|
||||
enum comm_point_type cptype,
|
||||
void *cpssl,
|
||||
uint8_t *zone, size_t zone_len,
|
||||
uint8_t *qbuf, size_t qbuf_len,
|
||||
const struct timeval *qtime,
|
||||
@@ -522,6 +579,9 @@ dt_msg_send_outside_response(struct dt_env *env,
|
||||
struct dt_msg dm;
|
||||
uint16_t qflags;
|
||||
|
||||
if(dt_sample_rate_limited(env))
|
||||
return;
|
||||
|
||||
(void)qbuf_len; log_assert(qbuf_len >= sizeof(qflags));
|
||||
memcpy(&qflags, qbuf, sizeof(qflags));
|
||||
qflags = ntohs(qflags);
|
||||
@@ -556,8 +616,7 @@ dt_msg_send_outside_response(struct dt_env *env,
|
||||
dt_fill_buffer(rmsg, &dm.m.response_message, &dm.m.has_response_message);
|
||||
|
||||
/* socket_family, socket_protocol, response_address, response_port, query_address, query_port */
|
||||
log_assert(cptype == comm_udp || cptype == comm_tcp);
|
||||
dt_msg_fill_net(&dm, rsock, qsock, cptype,
|
||||
dt_msg_fill_net(&dm, rsock, qsock, cptype, cpssl,
|
||||
&dm.m.response_address, &dm.m.has_response_address,
|
||||
&dm.m.response_port, &dm.m.has_response_port,
|
||||
&dm.m.query_address, &dm.m.has_query_address,
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
|
||||
#ifdef USE_DNSTAP
|
||||
|
||||
#include "util/locks.h"
|
||||
struct config_file;
|
||||
struct sldns_buffer;
|
||||
struct dt_msg_queue;
|
||||
@@ -75,6 +76,13 @@ struct dt_env {
|
||||
unsigned log_forwarder_query_messages : 1;
|
||||
/** whether to log Message/FORWARDER_RESPONSE */
|
||||
unsigned log_forwarder_response_messages : 1;
|
||||
|
||||
/** lock on sample count */
|
||||
lock_basic_type sample_lock;
|
||||
/** rate limit value from config, samples 1/N messages */
|
||||
unsigned int sample_rate;
|
||||
/** rate limit counter */
|
||||
unsigned int sample_rate_count;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -133,6 +141,7 @@ dt_msg_send_client_query(struct dt_env *env,
|
||||
struct sockaddr_storage *qsock,
|
||||
struct sockaddr_storage *rsock,
|
||||
enum comm_point_type cptype,
|
||||
void *cpssl,
|
||||
struct sldns_buffer *qmsg,
|
||||
struct timeval* tstamp);
|
||||
|
||||
@@ -149,6 +158,7 @@ dt_msg_send_client_response(struct dt_env *env,
|
||||
struct sockaddr_storage *qsock,
|
||||
struct sockaddr_storage *rsock,
|
||||
enum comm_point_type cptype,
|
||||
void *cpssl,
|
||||
struct sldns_buffer *rmsg);
|
||||
|
||||
/**
|
||||
@@ -168,6 +178,7 @@ dt_msg_send_outside_query(struct dt_env *env,
|
||||
struct sockaddr_storage *rsock,
|
||||
struct sockaddr_storage *qsock,
|
||||
enum comm_point_type cptype,
|
||||
void *cpssl,
|
||||
uint8_t *zone, size_t zone_len,
|
||||
struct sldns_buffer *qmsg);
|
||||
|
||||
@@ -192,6 +203,7 @@ dt_msg_send_outside_response(struct dt_env *env,
|
||||
struct sockaddr_storage *rsock,
|
||||
struct sockaddr_storage *qsock,
|
||||
enum comm_point_type cptype,
|
||||
void *cpssl,
|
||||
uint8_t *zone, size_t zone_len,
|
||||
uint8_t *qbuf, size_t qbuf_len,
|
||||
const struct timeval *qtime,
|
||||
|
||||
+66
-38
@@ -5,45 +5,73 @@
|
||||
# Check for required dnstap libraries and add dnstap configure args.
|
||||
AC_DEFUN([dt_DNSTAP],
|
||||
[
|
||||
AC_ARG_ENABLE([dnstap],
|
||||
AS_HELP_STRING([--enable-dnstap],
|
||||
[Enable dnstap support (requires protobuf-c)]),
|
||||
[opt_dnstap=$enableval], [opt_dnstap=no])
|
||||
AC_ARG_ENABLE([dnstap],
|
||||
AS_HELP_STRING([--enable-dnstap],
|
||||
[Enable dnstap support (requires protobuf-c)]),
|
||||
[opt_dnstap=$enableval],
|
||||
[opt_dnstap=no])
|
||||
|
||||
AC_ARG_WITH([dnstap-socket-path],
|
||||
AS_HELP_STRING([--with-dnstap-socket-path=pathname],
|
||||
[set default dnstap socket path]),
|
||||
[opt_dnstap_socket_path=$withval], [opt_dnstap_socket_path="$1"])
|
||||
AC_ARG_WITH([dnstap-socket-path],
|
||||
AS_HELP_STRING([--with-dnstap-socket-path=pathname],
|
||||
[set default dnstap socket path]),
|
||||
[opt_dnstap_socket_path=$withval],
|
||||
[opt_dnstap_socket_path="$1"])
|
||||
|
||||
if test "x$opt_dnstap" != "xno"; then
|
||||
AC_PATH_PROG([PROTOC_C], [protoc-c])
|
||||
if test -z "$PROTOC_C"; then
|
||||
AC_MSG_ERROR([The protoc-c program was not found. Please install protobuf-c!])
|
||||
if test "x$opt_dnstap" != "xno"; then
|
||||
AC_PATH_PROG([PROTOC_C], [protoc-c])
|
||||
if test -z "$PROTOC_C"; then
|
||||
AC_MSG_ERROR([The protoc-c program was not found. Please install protobuf-c!])
|
||||
fi
|
||||
AC_ARG_WITH([protobuf-c],
|
||||
AS_HELP_STRING([--with-protobuf-c=path], [Path where protobuf-c is installed, for dnstap]),
|
||||
[
|
||||
# workaround for protobuf-c includes at old dir before protobuf-c-1.0.0
|
||||
if test -f $withval/include/google/protobuf-c/protobuf-c.h; then
|
||||
CFLAGS="$CFLAGS -I$withval/include/google"
|
||||
else
|
||||
CFLAGS="$CFLAGS -I$withval/include"
|
||||
fi
|
||||
LDFLAGS="$LDFLAGS -L$withval/lib"
|
||||
],
|
||||
[
|
||||
if test -n "$PKG_CONFIG"; then
|
||||
PKG_CHECK_MODULES([PROTOBUFC], [libprotobuf-c],
|
||||
[
|
||||
CFLAGS="$CFLAGS $PROTOBUFC_CFLAGS"
|
||||
LIBS="$LIBS $PROTOBUFC_LIBS"
|
||||
],
|
||||
[
|
||||
# pkg-config failed; try falling back to known values
|
||||
# workaround for protobuf-c includes at old dir before protobuf-c-1.0.0
|
||||
if test -f /usr/include/google/protobuf-c/protobuf-c.h; then
|
||||
CFLAGS="$CFLAGS -I/usr/include/google"
|
||||
else
|
||||
if test -f /usr/local/include/google/protobuf-c/protobuf-c.h; then
|
||||
CFLAGS="$CFLAGS -I/usr/local/include/google"
|
||||
LDFLAGS="$LDFLAGS -L/usr/local/lib"
|
||||
else
|
||||
AC_MSG_ERROR([The protobuf-c package was not found with pkg-config. Please install protobuf-c!])
|
||||
fi
|
||||
fi
|
||||
]
|
||||
)
|
||||
else
|
||||
# workaround for protobuf-c includes at old dir before protobuf-c-1.0.0
|
||||
if test -f /usr/include/google/protobuf-c/protobuf-c.h; then
|
||||
CFLAGS="$CFLAGS -I/usr/include/google"
|
||||
else
|
||||
if test -f /usr/local/include/google/protobuf-c/protobuf-c.h; then
|
||||
CFLAGS="$CFLAGS -I/usr/local/include/google"
|
||||
LDFLAGS="$LDFLAGS -L/usr/local/lib"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
]
|
||||
)
|
||||
AC_SEARCH_LIBS([protobuf_c_message_pack], [protobuf-c], [],
|
||||
AC_MSG_ERROR([The protobuf-c library was not found. Please install the development libraries for protobuf-c!]))
|
||||
$2
|
||||
else
|
||||
$3
|
||||
fi
|
||||
AC_ARG_WITH([protobuf-c], AS_HELP_STRING([--with-protobuf-c=path],
|
||||
[Path where protobuf-c is installed, for dnstap]), [
|
||||
# workaround for protobuf-c includes at old dir before protobuf-c-1.0.0
|
||||
if test -f $withval/include/google/protobuf-c/protobuf-c.h; then
|
||||
CFLAGS="$CFLAGS -I$withval/include/google"
|
||||
else
|
||||
CFLAGS="$CFLAGS -I$withval/include"
|
||||
fi
|
||||
LDFLAGS="$LDFLAGS -L$withval/lib"
|
||||
], [
|
||||
# workaround for protobuf-c includes at old dir before protobuf-c-1.0.0
|
||||
if test -f /usr/include/google/protobuf-c/protobuf-c.h; then
|
||||
CFLAGS="$CFLAGS -I/usr/include/google"
|
||||
else
|
||||
if test -f /usr/local/include/google/protobuf-c/protobuf-c.h; then
|
||||
CFLAGS="$CFLAGS -I/usr/local/include/google"
|
||||
LDFLAGS="$LDFLAGS -L/usr/local/lib"
|
||||
fi
|
||||
fi
|
||||
])
|
||||
AC_SEARCH_LIBS([protobuf_c_message_pack], [protobuf-c], [],
|
||||
AC_MSG_ERROR([The protobuf-c library was not found. Please install the development libraries for protobuf-c!]))
|
||||
$2
|
||||
else
|
||||
$3
|
||||
fi
|
||||
])
|
||||
|
||||
+75
-7
@@ -13,8 +13,8 @@
|
||||
// with this file. If not, see:
|
||||
//
|
||||
// <http://creativecommons.org/publicdomain/zero/1.0/>.
|
||||
syntax = "proto2";
|
||||
|
||||
syntax = "proto2";
|
||||
package dnstap;
|
||||
|
||||
// "Dnstap": this is the top-level dnstap type, which is a "union" type that
|
||||
@@ -56,11 +56,60 @@ enum SocketFamily {
|
||||
INET6 = 2; // IPv6 (RFC 2460)
|
||||
}
|
||||
|
||||
// SocketProtocol: the transport protocol of a socket. This specifies how to
|
||||
// interpret "transport port" fields.
|
||||
// SocketProtocol: the protocol used to transport a DNS message.
|
||||
enum SocketProtocol {
|
||||
UDP = 1; // User Datagram Protocol (RFC 768)
|
||||
TCP = 2; // Transmission Control Protocol (RFC 793)
|
||||
UDP = 1; // DNS over UDP transport (RFC 1035 section 4.2.1)
|
||||
TCP = 2; // DNS over TCP transport (RFC 1035 section 4.2.2)
|
||||
DOT = 3; // DNS over TLS (RFC 7858)
|
||||
DOH = 4; // DNS over HTTPS (RFC 8484)
|
||||
DNSCryptUDP = 5; // DNSCrypt over UDP (https://dnscrypt.info/protocol)
|
||||
DNSCryptTCP = 6; // DNSCrypt over TCP (https://dnscrypt.info/protocol)
|
||||
DOQ = 7; // DNS over QUIC (RFC 9250)
|
||||
}
|
||||
|
||||
// Policy: information about any name server operator policy
|
||||
// applied to the processing of a DNS message.
|
||||
message Policy {
|
||||
|
||||
// Match: what aspect of the message or message exchange
|
||||
// triggered the application of the Policy.
|
||||
enum Match {
|
||||
QNAME = 1; // Name in question section of query
|
||||
CLIENT_IP = 2; // Client IP address
|
||||
RESPONSE_IP = 3; // Address in A/AAAA RRSet
|
||||
NS_NAME = 4; // Authoritative name server, by name
|
||||
NS_IP = 5; // Authoritative name server, by IP address
|
||||
}
|
||||
|
||||
// The Action taken to implement the Policy.
|
||||
enum Action {
|
||||
NXDOMAIN = 1; // Respond with NXDOMAIN
|
||||
NODATA = 2; // Respond with empty answer section
|
||||
PASS = 3; // Do not alter the response (passthrough)
|
||||
DROP = 4; // Do not respond.
|
||||
TRUNCATE = 5; // Truncate UDP response, forcing TCP retry
|
||||
LOCAL_DATA = 6; // Respond with local data from policy
|
||||
}
|
||||
|
||||
// type: the type of policy applied, e.g. "RPZ" for a
|
||||
// policy from a Response Policy Zone.
|
||||
optional string type = 1;
|
||||
|
||||
// rule: the rule matched by the message.
|
||||
//
|
||||
// In a RPZ context, this is the owner name of the rule in
|
||||
// the Reponse Policy Zone in wire format.
|
||||
optional bytes rule = 2;
|
||||
|
||||
// action: the policy action taken in response to the
|
||||
// rule match.
|
||||
optional Action action = 3;
|
||||
|
||||
// match: the feature of the message exchange which matched the rule.
|
||||
optional Match match = 4;
|
||||
|
||||
// The matched value. Format depends on the matched feature .
|
||||
optional bytes value = 5;
|
||||
}
|
||||
|
||||
// Message: a wire-format (RFC 1035 section 4) DNS message and associated
|
||||
@@ -158,6 +207,24 @@ message Message {
|
||||
// STUB_RESPONSE is a DNS response message sent from a DNS server to a
|
||||
// stub resolver, from the perspective of the stub resolver.
|
||||
STUB_RESPONSE = 10;
|
||||
|
||||
// TOOL_QUERY is a DNS query message sent from a DNS software tool to a
|
||||
// DNS server, from the perspective of the tool.
|
||||
TOOL_QUERY = 11;
|
||||
|
||||
// TOOL_RESPONSE is a DNS response message received by a DNS software
|
||||
// tool from a DNS server, from the perspective of the tool.
|
||||
TOOL_RESPONSE = 12;
|
||||
|
||||
// UPDATE_QUERY is a Dynamic DNS Update request (RFC 2136) received
|
||||
// by an authoritative name server, from the perspective of the
|
||||
// authoritative name server.
|
||||
UPDATE_QUERY = 13;
|
||||
|
||||
// UPDATE_RESPONSE is a Dynamic DNS Update response (RFC 2136) sent
|
||||
// from an authoritative name server, from the perspective of the
|
||||
// authoritative name server.
|
||||
UPDATE_RESPONSE = 14;
|
||||
}
|
||||
|
||||
// One of the Type values described above.
|
||||
@@ -215,6 +282,9 @@ message Message {
|
||||
|
||||
// The responder's original wire-format DNS response message, verbatim.
|
||||
optional bytes response_message = 14;
|
||||
|
||||
// Operator policy applied to the processing of this message, if any.
|
||||
optional Policy policy = 15;
|
||||
}
|
||||
|
||||
// All fields except for 'type' in the Message schema are optional.
|
||||
@@ -236,7 +306,6 @@ message Message {
|
||||
|
||||
// RESOLVER_QUERY:
|
||||
// socket_family, socket_protocol
|
||||
// query_name, query_type, query_class
|
||||
// query_message
|
||||
// query_time_sec, query_time_nsec
|
||||
// query_zone
|
||||
@@ -244,7 +313,6 @@ message Message {
|
||||
|
||||
// RESOLVER_RESPONSE:
|
||||
// socket_family, socket_protocol
|
||||
// query_name, query_type, query_class
|
||||
// query_time_sec, query_time_nsec
|
||||
// query_zone
|
||||
// response_address, response_port
|
||||
|
||||
+45
-8
@@ -176,10 +176,7 @@ void
|
||||
mq_wakeup_cb(void* arg)
|
||||
{
|
||||
struct dt_msg_queue* mq = (struct dt_msg_queue*)arg;
|
||||
/* even if the dtio is already active, because perhaps much
|
||||
* traffic suddenly, we leave the timer running to save on
|
||||
* managing it, the once a second timer is less work then
|
||||
* starting and stopping the timer frequently */
|
||||
|
||||
lock_basic_lock(&mq->dtio->wakeup_timer_lock);
|
||||
mq->dtio->wakeup_timer_enabled = 0;
|
||||
lock_basic_unlock(&mq->dtio->wakeup_timer_lock);
|
||||
@@ -210,6 +207,8 @@ dt_msg_queue_start_timer(struct dt_msg_queue* mq, int wakeupnow)
|
||||
lock_basic_lock(&mq->dtio->wakeup_timer_lock);
|
||||
if(mq->dtio->wakeup_timer_enabled) {
|
||||
if(wakeupnow) {
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = 0;
|
||||
comm_timer_set(mq->wakeup_timer, &tv);
|
||||
}
|
||||
lock_basic_unlock(&mq->dtio->wakeup_timer_lock);
|
||||
@@ -221,8 +220,14 @@ dt_msg_queue_start_timer(struct dt_msg_queue* mq, int wakeupnow)
|
||||
if(!wakeupnow) {
|
||||
tv.tv_sec = 1;
|
||||
tv.tv_usec = 0;
|
||||
/* If it is already set, keep it running. */
|
||||
if(!comm_timer_is_set(mq->wakeup_timer))
|
||||
comm_timer_set(mq->wakeup_timer, &tv);
|
||||
} else {
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = 0;
|
||||
comm_timer_set(mq->wakeup_timer, &tv);
|
||||
}
|
||||
comm_timer_set(mq->wakeup_timer, &tv);
|
||||
lock_basic_unlock(&mq->dtio->wakeup_timer_lock);
|
||||
}
|
||||
|
||||
@@ -260,8 +265,9 @@ dt_msg_queue_submit(struct dt_msg_queue* mq, void* buf, size_t len)
|
||||
|
||||
/* acquire lock */
|
||||
lock_basic_lock(&mq->lock);
|
||||
/* if list was empty, start timer for (eventual) wakeup */
|
||||
if(mq->first == NULL)
|
||||
/* if list was empty, start timer for (eventual) wakeup,
|
||||
* or if dtio is not writing now an eventual wakeup is needed. */
|
||||
if(mq->first == NULL || !mq->dtio->event_added_is_write)
|
||||
wakeupstarttimer = 1;
|
||||
/* if list contains more than wakeupnum elements, wakeup now,
|
||||
* or if list is (going to be) almost full */
|
||||
@@ -1259,6 +1265,13 @@ static void dtio_sleep(struct dt_io_thread* dtio)
|
||||
/* unregister the event polling for write, because there is
|
||||
* nothing to be written */
|
||||
(void)dtio_add_output_event_read(dtio);
|
||||
|
||||
/* Set wakeuptimer enabled off; so that the next worker thread that
|
||||
* wants to log starts a timer if needed, since the writer thread
|
||||
* has gone to sleep. */
|
||||
lock_basic_lock(&dtio->wakeup_timer_lock);
|
||||
dtio->wakeup_timer_enabled = 0;
|
||||
lock_basic_unlock(&dtio->wakeup_timer_lock);
|
||||
}
|
||||
|
||||
#ifdef HAVE_SSL
|
||||
@@ -1322,7 +1335,11 @@ static int dtio_ssl_check_peer(struct dt_io_thread* dtio)
|
||||
if((SSL_get_verify_mode(dtio->ssl)&SSL_VERIFY_PEER)) {
|
||||
/* verification */
|
||||
if(SSL_get_verify_result(dtio->ssl) == X509_V_OK) {
|
||||
#ifdef HAVE_SSL_GET1_PEER_CERTIFICATE
|
||||
X509* x = SSL_get1_peer_certificate(dtio->ssl);
|
||||
#else
|
||||
X509* x = SSL_get_peer_certificate(dtio->ssl);
|
||||
#endif
|
||||
if(!x) {
|
||||
verbose(VERB_ALGO, "dnstap io, %s, SSL "
|
||||
"connection failed no certificate",
|
||||
@@ -1347,7 +1364,11 @@ static int dtio_ssl_check_peer(struct dt_io_thread* dtio)
|
||||
#endif
|
||||
X509_free(x);
|
||||
} else {
|
||||
#ifdef HAVE_SSL_GET1_PEER_CERTIFICATE
|
||||
X509* x = SSL_get1_peer_certificate(dtio->ssl);
|
||||
#else
|
||||
X509* x = SSL_get_peer_certificate(dtio->ssl);
|
||||
#endif
|
||||
if(x) {
|
||||
log_cert(VERB_ALGO, "dnstap io, peer "
|
||||
"certificate", x);
|
||||
@@ -1489,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;
|
||||
@@ -1513,8 +1536,22 @@ void dtio_output_cb(int ATTR_UNUSED(fd), short bits, void* arg)
|
||||
/* no messages on the first iteration,
|
||||
* the queues are all empty */
|
||||
dtio_sleep(dtio);
|
||||
/* After putting to sleep, see if
|
||||
* a message is in a message queue,
|
||||
* if so, resume service. Stops a
|
||||
* race condition where a thread could
|
||||
* have one message but the dtio
|
||||
* also just went to sleep. With the
|
||||
* message queued between the
|
||||
* dtio_find_msg and dtio_sleep
|
||||
* calls. */
|
||||
if(dtio_find_msg(dtio)) {
|
||||
if(!dtio_add_output_event_write(dtio))
|
||||
return;
|
||||
}
|
||||
}
|
||||
return; /* nothing to do */
|
||||
if(!dtio->cur_msg)
|
||||
return; /* nothing to do */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+269
-40
@@ -75,17 +75,18 @@
|
||||
static void usage(char* argv[])
|
||||
{
|
||||
printf("usage: %s [options]\n", argv[0]);
|
||||
printf(" Listen to dnstap messages\n");
|
||||
printf(" Listen to dnstap messages\n");
|
||||
printf("stdout has dnstap log, stderr has verbose server log\n");
|
||||
printf("-u <socketpath> listen to unix socket with this file name\n");
|
||||
printf("-s <serverip[@port]> listen for TCP on the IP and port\n");
|
||||
printf("-t <serverip[@port]> listen for TLS on IP and port\n");
|
||||
printf("-x <server.key> server key file for TLS service\n");
|
||||
printf("-y <server.pem> server cert file for TLS service\n");
|
||||
printf("-z <verify.pem> cert file to verify client connections\n");
|
||||
printf("-l long format for DNS printout\n");
|
||||
printf("-v more verbose log output\n");
|
||||
printf("-h this help text\n");
|
||||
printf("-u <socketpath> listen to unix socket with this file name\n");
|
||||
printf("-s <serverip[@port]> listen for TCP on the IP and port\n");
|
||||
printf("-t <serverip[@port]> listen for TLS on IP and port\n");
|
||||
printf("-x <server.key> server key file for TLS service\n");
|
||||
printf("-y <server.pem> server cert file for TLS service\n");
|
||||
printf("-z <verify.pem> cert file to verify client connections\n");
|
||||
printf("-l long format for DNS printout\n");
|
||||
printf("-v more verbose log output\n");
|
||||
printf("-c internal unit test and exit\n");
|
||||
printf("-h this help text\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@@ -102,6 +103,14 @@ struct main_tap_data {
|
||||
struct tap_socket_list* acceptlist;
|
||||
};
|
||||
|
||||
/* list of data */
|
||||
struct tap_data_list {
|
||||
/** next in list */
|
||||
struct tap_data_list* next;
|
||||
/** the data */
|
||||
struct tap_data* d;
|
||||
};
|
||||
|
||||
/** tap callback variables */
|
||||
struct tap_data {
|
||||
/** the fd */
|
||||
@@ -128,6 +137,10 @@ struct tap_data {
|
||||
uint8_t* frame;
|
||||
/** length of this frame */
|
||||
size_t len;
|
||||
/** back pointer to the tap_data_list entry;
|
||||
* used to NULL the forward pointer to this data
|
||||
* when this data is freed. */
|
||||
struct tap_data_list* data_list;
|
||||
};
|
||||
|
||||
/** list of sockets */
|
||||
@@ -156,8 +169,89 @@ struct tap_socket {
|
||||
char* ip;
|
||||
/** for a TLS socket, the tls context */
|
||||
SSL_CTX* sslctx;
|
||||
/** dumb way to deal with memory leaks:
|
||||
* tap_data was only freed on errors and not during exit leading to
|
||||
* false positives when testing for memory leaks. */
|
||||
struct tap_data_list* data_list;
|
||||
};
|
||||
|
||||
/** try to delete tail entries from the list if all of them have no data */
|
||||
static void tap_data_list_try_to_free_tail(struct tap_data_list* list)
|
||||
{
|
||||
struct tap_data_list* current = list;
|
||||
log_assert(!list->d);
|
||||
if(!list->next) /* we are the last, we can't remove ourselves */
|
||||
return;
|
||||
list = list->next;
|
||||
while(list) {
|
||||
if(list->d) /* a tail entry still has data; return */
|
||||
return;
|
||||
list = list->next;
|
||||
}
|
||||
/* keep the next */
|
||||
list = current->next;
|
||||
/* the tail will be removed; but not ourselves */
|
||||
current->next = NULL;
|
||||
while(list) {
|
||||
current = list;
|
||||
list = list->next;
|
||||
free(current);
|
||||
}
|
||||
}
|
||||
|
||||
/** delete the tap structure */
|
||||
static void tap_data_free(struct tap_data* data, int free_tail)
|
||||
{
|
||||
if(!data)
|
||||
return;
|
||||
if(data->ev) {
|
||||
ub_event_del(data->ev);
|
||||
ub_event_free(data->ev);
|
||||
}
|
||||
#ifdef HAVE_SSL
|
||||
SSL_free(data->ssl);
|
||||
#endif
|
||||
sock_close(data->fd);
|
||||
free(data->id);
|
||||
free(data->frame);
|
||||
if(data->data_list) {
|
||||
data->data_list->d = NULL;
|
||||
if(free_tail)
|
||||
tap_data_list_try_to_free_tail(data->data_list);
|
||||
}
|
||||
free(data);
|
||||
}
|
||||
|
||||
/** insert tap_data in the tap_data_list */
|
||||
static int tap_data_list_insert(struct tap_data_list** liststart,
|
||||
struct tap_data* d)
|
||||
{
|
||||
struct tap_data_list* entry = (struct tap_data_list*)
|
||||
malloc(sizeof(*entry));
|
||||
if(!entry)
|
||||
return 0;
|
||||
entry->next = *liststart;
|
||||
entry->d = d;
|
||||
d->data_list = entry;
|
||||
*liststart = entry;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** delete the tap_data_list and free any remaining tap_data */
|
||||
static void tap_data_list_delete(struct tap_data_list* list)
|
||||
{
|
||||
struct tap_data_list* e = list, *next;
|
||||
while(e) {
|
||||
next = e->next;
|
||||
if(e->d) {
|
||||
tap_data_free(e->d, 0);
|
||||
e->d = NULL;
|
||||
}
|
||||
free(e);
|
||||
e = next;
|
||||
}
|
||||
}
|
||||
|
||||
/** del the tap event */
|
||||
static void tap_socket_delev(struct tap_socket* s)
|
||||
{
|
||||
@@ -173,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;
|
||||
}
|
||||
|
||||
@@ -184,6 +278,7 @@ static void tap_socket_delete(struct tap_socket* s)
|
||||
#ifdef HAVE_SSL
|
||||
SSL_CTX_free(s->sslctx);
|
||||
#endif
|
||||
tap_data_list_delete(s->data_list);
|
||||
ub_event_free(s->ev);
|
||||
free(s->socketpath);
|
||||
free(s->ip);
|
||||
@@ -728,27 +823,12 @@ static ssize_t tap_receive(struct tap_data* data, void* buf, size_t len)
|
||||
return receive_bytes(data, data->fd, buf, len);
|
||||
}
|
||||
|
||||
/** delete the tap structure */
|
||||
static void tap_data_free(struct tap_data* data)
|
||||
{
|
||||
ub_event_del(data->ev);
|
||||
ub_event_free(data->ev);
|
||||
#ifdef HAVE_SSL
|
||||
SSL_free(data->ssl);
|
||||
#endif
|
||||
close(data->fd);
|
||||
free(data->id);
|
||||
free(data->frame);
|
||||
free(data);
|
||||
}
|
||||
|
||||
/** reply with ACCEPT control frame to bidirectional client,
|
||||
* returns 0 on error */
|
||||
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);
|
||||
@@ -759,6 +839,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)
|
||||
@@ -769,6 +851,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));
|
||||
@@ -804,6 +887,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;
|
||||
@@ -815,6 +899,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));
|
||||
@@ -842,7 +927,11 @@ static int tap_check_peer(struct tap_data* data)
|
||||
if((SSL_get_verify_mode(data->ssl)&SSL_VERIFY_PEER)) {
|
||||
/* verification */
|
||||
if(SSL_get_verify_result(data->ssl) == X509_V_OK) {
|
||||
#ifdef HAVE_SSL_GET1_PEER_CERTIFICATE
|
||||
X509* x = SSL_get1_peer_certificate(data->ssl);
|
||||
#else
|
||||
X509* x = SSL_get_peer_certificate(data->ssl);
|
||||
#endif
|
||||
if(!x) {
|
||||
if(verbosity) log_info("SSL connection %s"
|
||||
" failed no certificate", data->id);
|
||||
@@ -864,7 +953,11 @@ static int tap_check_peer(struct tap_data* data)
|
||||
#endif
|
||||
X509_free(x);
|
||||
} else {
|
||||
#ifdef HAVE_SSL_GET1_PEER_CERTIFICATE
|
||||
X509* x = SSL_get1_peer_certificate(data->ssl);
|
||||
#else
|
||||
X509* x = SSL_get_peer_certificate(data->ssl);
|
||||
#endif
|
||||
if(x) {
|
||||
if(verbosity)
|
||||
log_cert(VERB_ALGO, "peer certificate", x);
|
||||
@@ -906,7 +999,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 */
|
||||
@@ -924,7 +1017,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();
|
||||
@@ -934,7 +1027,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;
|
||||
}
|
||||
}
|
||||
@@ -942,7 +1035,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;
|
||||
@@ -968,7 +1061,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 */
|
||||
@@ -990,7 +1083,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;
|
||||
}
|
||||
}
|
||||
@@ -1003,7 +1096,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 */
|
||||
@@ -1028,13 +1121,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;
|
||||
}
|
||||
}
|
||||
@@ -1046,7 +1139,6 @@ void dtio_tap_callback(int ATTR_UNUSED(fd), short ATTR_UNUSED(bits), void* arg)
|
||||
data->len = 0;
|
||||
data->len_done = 0;
|
||||
data->data_done = 0;
|
||||
|
||||
}
|
||||
|
||||
/** callback for main listening file descriptor */
|
||||
@@ -1059,7 +1151,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. */
|
||||
@@ -1129,6 +1223,8 @@ void dtio_mainfdcallback(int fd, short ATTR_UNUSED(bits), void* arg)
|
||||
&dtio_tap_callback, data);
|
||||
if(!data->ev) fatal_exit("could not ub_event_new");
|
||||
if(ub_event_add(data->ev, NULL) != 0) fatal_exit("could not ub_event_add");
|
||||
if(!tap_data_list_insert(&tap_sock->data_list, data))
|
||||
fatal_exit("could not tap_data_list_insert");
|
||||
}
|
||||
|
||||
/** setup local accept sockets */
|
||||
@@ -1243,6 +1339,114 @@ setup_and_run(struct config_strlist_head* local_list,
|
||||
free(maindata);
|
||||
}
|
||||
|
||||
/* internal unit tests */
|
||||
static int internal_unittest()
|
||||
{
|
||||
/* unit test tap_data_list_try_to_free_tail() */
|
||||
#define unit_tap_datas_max 5
|
||||
struct tap_data* datas[unit_tap_datas_max];
|
||||
struct tap_data_list* list;
|
||||
struct tap_socket* socket = calloc(1, sizeof(*socket));
|
||||
size_t i = 0;
|
||||
log_assert(socket);
|
||||
log_assert(unit_tap_datas_max>2); /* needed for the test */
|
||||
for(i=0; i<unit_tap_datas_max; 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==unit_tap_datas_max);
|
||||
|
||||
/* 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==unit_tap_datas_max);
|
||||
|
||||
/* Free the third to last data, tail cannot be erased */
|
||||
list = socket->data_list;
|
||||
for(i=0; i<unit_tap_datas_max-3; i++) 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==unit_tap_datas_max);
|
||||
|
||||
/* Free the second to last data, try to remove tail from the third
|
||||
* again, tail (last 2) should be removed */
|
||||
list = socket->data_list;
|
||||
for(i=0; i<unit_tap_datas_max-2; i++) list = list->next;
|
||||
free(list->d);
|
||||
list->d = NULL;
|
||||
list = socket->data_list;
|
||||
while(list->d) list = list->next;
|
||||
tap_data_list_try_to_free_tail(list);
|
||||
list = socket->data_list;
|
||||
for(i=0; list; i++) list = list->next;
|
||||
log_assert(i==unit_tap_datas_max-2);
|
||||
|
||||
/* Free all the remaining data, try to remove tail from the start,
|
||||
* only the start should remain */
|
||||
list = socket->data_list;
|
||||
while(list) {
|
||||
free(list->d);
|
||||
list->d = NULL;
|
||||
list = list->next;
|
||||
}
|
||||
tap_data_list_try_to_free_tail(socket->data_list);
|
||||
list = socket->data_list;
|
||||
for(i=0; list; i++) list = list->next;
|
||||
log_assert(i==1);
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
/** getopt global, in case header files fail to declare it. */
|
||||
extern int optind;
|
||||
/** getopt global, in case header files fail to declare it. */
|
||||
@@ -1293,7 +1497,7 @@ int main(int argc, char** argv)
|
||||
#endif
|
||||
|
||||
/* command line options */
|
||||
while( (c=getopt(argc, argv, "hls:t:u:vx:y:z:")) != -1) {
|
||||
while( (c=getopt(argc, argv, "hcls:t:u:vx:y:z:")) != -1) {
|
||||
switch(c) {
|
||||
case 'u':
|
||||
if(!cfg_strlist_append(&local_list,
|
||||
@@ -1329,14 +1533,20 @@ int main(int argc, char** argv)
|
||||
case 'v':
|
||||
verbosity++;
|
||||
break;
|
||||
case 'c':
|
||||
#ifndef UNBOUND_DEBUG
|
||||
fatal_exit("-c option needs compilation with "
|
||||
"--enable-debug");
|
||||
#endif
|
||||
return internal_unittest();
|
||||
case 'h':
|
||||
case '?':
|
||||
default:
|
||||
usage(argv);
|
||||
}
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
/* argc -= optind; not using further arguments */
|
||||
/* argv += optind; not using further arguments */
|
||||
|
||||
if(usessl) {
|
||||
#ifdef HAVE_SSL
|
||||
@@ -1365,6 +1575,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();
|
||||
@@ -1572,3 +1785,19 @@ void remote_get_opt_ssl(char* ATTR_UNUSED(str), void* ATTR_UNUSED(arg))
|
||||
{
|
||||
log_assert(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
|
||||
|
||||
+732
-1
@@ -1,6 +1,737 @@
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
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.
|
||||
- Fix dnstap wakeup, a running wakeup timer is left to expire and not
|
||||
increased, a timer is started when the dtio thread is sleeping,
|
||||
the timer set disabled when the dtio thread goes to sleep, and
|
||||
after sleep the thread checks to see if there are messages to log
|
||||
immediately.
|
||||
|
||||
16 July 2024: Wouter
|
||||
- For #1103: Fix to drop mesh state reference for the http2 stream
|
||||
associated with the reply, not the currently active stream. And
|
||||
it does not remove it twice on a mesh_send_reply call. The reply
|
||||
h2_stream is NULL when not in use, for more initialisation.
|
||||
|
||||
15 July 2024: Wouter
|
||||
- For #1103: fix to also drop mesh state reference when the discard
|
||||
limit is reached, when there is an error making a new recursion
|
||||
state and when the connection is dropped with is_drop.
|
||||
|
||||
12 July 2024: Yorgos
|
||||
- Add RPZ tag tests in acl_interface.tdir.
|
||||
- For #1102: clearer text for using interface-* options for the
|
||||
loopback interface.
|
||||
|
||||
12 July 2024: Wouter
|
||||
- Fix #1103: unbound 1.20.0 segmentation fault with nghttp2.
|
||||
- For #1103: fix to also drop mesh state reference when a h2 reply is
|
||||
dropped.
|
||||
|
||||
10 July 2024: Wouter
|
||||
- For #773: In contrib/unbound.service.in set unbound to start after
|
||||
network-online.target. Also for contrib/unbound_portable.service.in.
|
||||
|
||||
9 July 2024: Yorgos
|
||||
- Update list of known EDE codes.
|
||||
|
||||
8 July 2024: Wouter
|
||||
- Fix that validation reason failure that uses string print uses
|
||||
separate buffer that is passed, from the scratch validation buffer.
|
||||
- Fixup algo_needs_reason string buffer length.
|
||||
- Fix shadowed error string variable in validator dnskey handling.
|
||||
|
||||
5 July 2024: Yorgos
|
||||
- Don't check for message TTL changes if the RRsets remain the same.
|
||||
|
||||
5 July 2024: Wouter
|
||||
- Fix for neater printout for error for missing DS response.
|
||||
- Fix neater printout.
|
||||
- Fix #1099: Unbound core dump on SIGSEGV.
|
||||
- Fix for #1099: Fix to check for deleted RRset when the contents
|
||||
is updated and fetched after it is stored, and also check for a
|
||||
changed RRset.
|
||||
|
||||
4 July 2024: Wouter
|
||||
- Fix to print details about the failure to lookup a DNSKEY record
|
||||
when validation fails due to the missing DNSKEY. Also for key prime
|
||||
and DS lookups.
|
||||
|
||||
3 July 2024: Yorgos
|
||||
- Fix for repeated use of a DNAME record: first overallocate and then
|
||||
move the exact size of the init value to avoid false positive heap
|
||||
overflow reads from address sanitizers.
|
||||
|
||||
3 July 2024: Wouter
|
||||
- Fix #144: Port ipset to BSD pf tables.
|
||||
- Add unit test skip files and bison and flex output to gitignore.
|
||||
- Fix to use modstack_init in zonemd unit test.
|
||||
- Fix to remove unneeded linebreak in fptr_wlist.c.
|
||||
- Fix compile warnings in fptr_wlist.c.
|
||||
|
||||
2 July 2024: Wouter
|
||||
- Fix to remove unused include from the readzone test program.
|
||||
- Fix unused variable warning in do_cache_remove.
|
||||
- Fix compile warning in worker pthread id printout.
|
||||
|
||||
17 June 2024: Wouter
|
||||
- Fix ip-ratelimit-cookie setting, it was not applied.
|
||||
|
||||
26 June 2024: Yorgos
|
||||
- Explicitly set the RD bit for the mesh query flags when prefetching.
|
||||
These queries have no waiting client but they need to be treated as
|
||||
recursive.
|
||||
|
||||
21 June 2024: Yorgos
|
||||
- Fix pkg-config availability check in dnstap/dnstap.m4 and
|
||||
systemd.m4.
|
||||
|
||||
19 June 2024: Yorgos
|
||||
- Fix #1092: Ubuntu 22.04 Jammy fails to compile unbound 1.20.0; by
|
||||
adding helpful text for the Python interpreter version and allowing
|
||||
the default pkg-config unavailability error message to be shown.
|
||||
|
||||
17 June 2024: Wouter
|
||||
- Fix #1091: Build fails with OpenSSL >= 3.0 built with
|
||||
OPENSSL_NO_DEPRECATED.
|
||||
|
||||
7 June 2024: Wouter
|
||||
- Add unit test for validation of repeated use of a DNAME record.
|
||||
|
||||
6 June 2024: Wouter
|
||||
- Fix memory leak in setup of dsa sig.
|
||||
- Fix typos for 'the the' in text.
|
||||
- Fix validation for repeated use of a DNAME record.
|
||||
|
||||
4 June 2024: Yorgos
|
||||
- Merge #1080: AddressSanitizer detection in tdir tests and memory leak
|
||||
fixes.
|
||||
- Fix memory leak when reload_keep_cache is used and num-threads
|
||||
changes.
|
||||
- Fix memory leak on exit for unbound-dnstap-socket; creates false
|
||||
negatives during testing.
|
||||
|
||||
3 June 2024: Wouter
|
||||
- Fix to squelch connection reset by peer errors from log. And fix
|
||||
that the tcp read errors are labeled as initial for the first calls.
|
||||
|
||||
30 May 2024: Wouter
|
||||
- Fix #1079: tags from tagged rpz zones are no longer honored after
|
||||
upgrade from 1.19.3 to 1.20.0.
|
||||
- Fix for #1079: fix RPZ taglist in iterator callback that no client
|
||||
info is like no taglist intersection.
|
||||
|
||||
29 May 2024: Wouter
|
||||
- Merge #1078: Only check old pid if no username.
|
||||
|
||||
27 May 2024: Wouter
|
||||
- Fix to enable that SERVFAIL is cached, for a short period, for more
|
||||
cases. In the cases where limits are exceeded.
|
||||
- Fix spelling of tcp-idle-timeout docs, from Michael Tokarev.
|
||||
|
||||
27 May 2024: Yorgos
|
||||
- Fix unused variable warning on compilation with no thread support.
|
||||
- unbound-control-setup: check openssl availability before doing
|
||||
anything, patch from Michael Tokarev.
|
||||
- Update patch to remove 'command' shell builtin and update error
|
||||
text.
|
||||
|
||||
24 May 2024: Wouter
|
||||
- Fix #1064: Unbound 1.20 Cachedb broken?
|
||||
|
||||
24 May 2024: Yorgos
|
||||
- Fix #1059: Intermittent DNS blocking failure with local-zone and
|
||||
always_nxdomain. Addition of local_zones dynamically via
|
||||
unbound-control was not finding the zone's parent correctly.
|
||||
|
||||
21 May 2024: Wouter
|
||||
- Merge #1073: fix null pointer dereference issue in function
|
||||
ub_ctx_set_fwd.
|
||||
- Fix to print a parse error when config is read with no name for
|
||||
a forward-zone, stub-zone or view.
|
||||
- Fix for parse end of forward-zone, stub-zone and view.
|
||||
- Fix for #1064: Fix that cachedb expired messages are considered
|
||||
insecure, and thus can be served to clients when dnssec is enabled.
|
||||
|
||||
17 May 2024: Yorgos
|
||||
- Merge #1069: Fix unbound-control stdin commands for multi-process
|
||||
Unbounds.
|
||||
- Fix unbound-control commands that read stdin in multi-process
|
||||
operation (local_zones_remove, local_zones, local_datas_remove,
|
||||
local_datas, view_local_datas_remove, view_local_datas). They will
|
||||
be properly distributed to all processes. dump_cache and load_cache
|
||||
are no longer supported in multi-process operation.
|
||||
- Remove testdata/remote-threaded.tdir. testdata/09-unbound-control.tdir
|
||||
now checks both single and multi process/thread operation.
|
||||
|
||||
16 May 2024: Yorgos
|
||||
- Merge #1070: Fix rtt assignement for low values of
|
||||
infra-cache-max-rtt.
|
||||
|
||||
16 May 2024: Wouter
|
||||
- Fix #1071: [FR] Clear both in-memory and cachedb module cache with
|
||||
`unbound-control flush*` commands.
|
||||
|
||||
15 May 2024: Yorgos
|
||||
- Add missing common functions to tdir tests.
|
||||
|
||||
10 May 2024: Wouter
|
||||
- Fix when the mesh jostle is exceeded that nameserver targets are
|
||||
marked as resolved, so that the lookup is not stuck on the
|
||||
requestlist.
|
||||
|
||||
8 May 2024: Wouter
|
||||
- Fix to squelch udp connect errors in the log at low verbosity about
|
||||
invalid argument for IPv6 link local addresses.
|
||||
|
||||
7 May 2024: Wouter
|
||||
- Merge #1062: Fix potential overflow bug while parsing port in
|
||||
function cfg_mark_ports.
|
||||
- Fix for #1062: declaration before statement, avoid print of null,
|
||||
and redundant check for array size.
|
||||
|
||||
1 May 2024: Wouter
|
||||
- Fix for the DNSBomb vulnerability CVE-2024-33655. Thanks to Xiang Li
|
||||
from the Network and Information Security Lab of Tsinghua University
|
||||
for reporting it.
|
||||
- Set version number to 1.20.0 for release. This became the release
|
||||
on 8 may 2024, the repository continues with version 1.20.1.
|
||||
|
||||
29 April 2024: Yorgos
|
||||
- Cleanup unnecessary strdup calls for EDE strings.
|
||||
|
||||
29 April 2024: Wouter
|
||||
- Fix doxygen comment for errinf_to_str_bogus.
|
||||
|
||||
26 April 2024: Wouter
|
||||
- Fix cachedb with serve-expired-client-timeout disabled. The edns
|
||||
subnet module deletes global cache and cachedb cache when it
|
||||
stores a result, and serve-expired is enabled, so that the global
|
||||
reply, that is older than the ecs reply, does not return after
|
||||
the ecs reply expires.
|
||||
- Add unit tests for cachedb and subnet cache expired data.
|
||||
- Man page entry for unbound-checkconf -q.
|
||||
|
||||
26 April 2024: Yorgos
|
||||
- Fix #876: [FR] can unbound-checkconf be silenced when configuration
|
||||
is valid?
|
||||
|
||||
25 April 2024: Wouter
|
||||
- Fix configure flto check error, by finding grep for it.
|
||||
- Merge #1041: Stub and Forward unshare. This has one structure
|
||||
for them and fixes #1038: fatal error: Could not initialize
|
||||
thread / error: reading root hints.
|
||||
- Fix to disable fragmentation on systems with IP_DONTFRAG,
|
||||
with a nonzero value for the socket option argument.
|
||||
- Fix doc unit test for out of directory build.
|
||||
|
||||
24 April 2024: Wouter
|
||||
- Fix ci workflow for macos for moved install locations.
|
||||
|
||||
23 April 2024: Yorgos
|
||||
- Merge #1053: Remove child delegations from cache when grandchild
|
||||
delegations are returned from parent.
|
||||
|
||||
22 April 2024: Wouter
|
||||
- Add checklock feature verbose_locking to trace locks and unlocks.
|
||||
- Fix edns subnet to sort rrset references when storing messages
|
||||
in the cache. This fixes a race condition in the rrset locks.
|
||||
|
||||
15 April 2024: Wouter
|
||||
- Fix #1048: Update ax_pkg_swig.m4 and ax_pthread.m4.
|
||||
- Fix configure, autoconf for #1048.
|
||||
|
||||
15 April 2024: Yorgos
|
||||
- Merge #1049 from Petr Menšík: Py_NoSiteFlag is not needed since
|
||||
Python 3.8
|
||||
|
||||
12 April 2024: Wouter
|
||||
- Fix cachedb for serve-expired with serve-expired-client-timeout.
|
||||
- Fixup unit test for cachedb server expired client timeout with
|
||||
a check if response if from upstream or from cachedb.
|
||||
- Fixup cachedb to not refetch when serve-expired-client-timeout is
|
||||
used.
|
||||
|
||||
10 April 2024: Wouter
|
||||
- Implement cachedb-check-when-serve-expired: yes option, default
|
||||
is enabled. When serve expired is enabled with cachedb, it first
|
||||
checks cachedb before serving the expired response.
|
||||
- Fixup compile without cachedb.
|
||||
- Add test for cachedb serve expired.
|
||||
- Extended test for cachedb serve expired.
|
||||
- Fix makefile dependencies for fake_event.c.
|
||||
- Fix cachedb for serve-expired with serve-expired-reply-ttl.
|
||||
- Fix to not reply serve expired unless enabled for cachedb.
|
||||
|
||||
9 April 2024: Yorgos
|
||||
- Merge #1043 from xiaoxiaoafeifei: Add loongarch support; updates
|
||||
config.guess(2024-01-01) and config.sub(2024-01-01), verified
|
||||
with upstream.
|
||||
|
||||
8 April 2024: Yorgos
|
||||
- Fix #595: unbound-anchor cannot deal with full disk; it will now
|
||||
first write out to a temp file before replacing the original one,
|
||||
like Unbound already does for auto-trust-anchor-file.
|
||||
|
||||
5 April 2024: Wouter
|
||||
- Fix comment syntax for view function views_find_view.
|
||||
|
||||
5 April 2024: Yorgos
|
||||
- Merge #1027: Introduce 'cache-min-negative-ttl' option.
|
||||
|
||||
3 April 2024: Wouter
|
||||
- Fix #1040: fix heap-buffer-overflow issue in function cfg_mark_ports
|
||||
of file util/config_file.c.
|
||||
- For #1040: adjust error text and disallow negative ports in other
|
||||
parts of cfg_mark_ports.
|
||||
|
||||
3 April 2024: Yorgos
|
||||
- Fix #1035: Potential Bug while parsing port from the "stub-host"
|
||||
string; also affected forward-zones and remote-control host
|
||||
directives.
|
||||
- Fix #369: dnstap showing extra responses; for client responses
|
||||
right from the cache when replying with expired data or
|
||||
prefetching.
|
||||
|
||||
28 March 2024: Wouter
|
||||
- Fix #1034: DoT forward-zone via unbound-control.
|
||||
- Fix for crypto related failures to have a better error string.
|
||||
|
||||
27 March 2024: Wouter
|
||||
- Fix name of unit test for subnet cache response.
|
||||
- Fix #1032: The size of subnet_msg_cache calculation mistake cause
|
||||
memory usage increased beyond expectations.
|
||||
- Fix for #1032, add safeguard to make table space positive.
|
||||
- Fix comment in lruhash space function.
|
||||
- Fix to add unit test for lruhash space that exercises the routines.
|
||||
- Fix that when the server truncates the pidfile, it does not follow
|
||||
symbolic links.
|
||||
- Fix that the server does not chown the pidfile.
|
||||
|
||||
25 March 2024: Yorgos
|
||||
- Merge #831 from Pierre4012: Improve Windows NSIS installer
|
||||
script (setup.nsi).
|
||||
- For #831: Format text, use exclamation icon and explicit label
|
||||
names.
|
||||
|
||||
19 March 2024: Wouter
|
||||
- Fix rpz so that rpz CNAME can apply after rpz CNAME. And fix that
|
||||
clientip and nsip can give a CNAME.
|
||||
- Fix localdata and rpz localdata to match CNAME only if no direct
|
||||
type match is available.
|
||||
|
||||
18 March 2024: Wouter
|
||||
- Fix that rpz CNAME content is limited to the max number of cnames.
|
||||
- Fix rpz, it follows iterator CNAMEs for nsip and nsdname and sets
|
||||
the reply query_info values, that is better for debug logging.
|
||||
- Fix rpz that copies the cname override completely to the temp
|
||||
region, so there are no references to the rpz region.
|
||||
- Add rpz unit test for nsip action override.
|
||||
- Fix rpz for qtype CNAME after nameserver trigger.
|
||||
|
||||
15 March 2024: Yorgos
|
||||
- Merge #1030: Persist the openssl and expat directories for repeated
|
||||
Windows builds.
|
||||
|
||||
15 March 2024: Wouter
|
||||
- Fix that addrinfo is not kept around but copied and freed, so that
|
||||
log-destaddr uses a copy of the information, much like NSD does.
|
||||
|
||||
13 March 2024: Wouter
|
||||
- Fix #1029: rpz trigger clientip and action rpz-passthru not working
|
||||
as expected.
|
||||
- Fix rpz that the rpz override is taken in case of clientip triggers.
|
||||
Fix that the clientip passthru action is logged. Fix that the
|
||||
clientip localdata action is logged. Fix rpz override action cname
|
||||
for the clientip trigger.
|
||||
- Fix to unify codepath for local alias for rpz cname action override.
|
||||
- Fix rpz for cname override action after nsdname and nsip triggers.
|
||||
|
||||
12 March 2024: Yorgos
|
||||
- Merge #1028: Clearer documentation for tcp-idle-timeout and
|
||||
edns-tcp-keepalive-timeout.
|
||||
|
||||
11 March 2024: Wouter
|
||||
- Fix #1021 Inconsistent Behavior with Changing rpz-cname-override
|
||||
and doing a unbound-control reload.
|
||||
|
||||
8 March 2024: Wouter
|
||||
- Fix unbound-control-setup.cmd to use 3072 bits so that certificates
|
||||
are long enough for newer OpenSSL versions. This fix is included
|
||||
in 1.19.3rc2.
|
||||
- Fix TTL of synthesized CNAME when a DNAME is used from cache. This
|
||||
fix is included in 1.19.3rc2.
|
||||
- Remove unused portion from iter_dname_ttl unit test.
|
||||
- Fix validator classification of qtype DNAME for positive and
|
||||
redirection answers, and fix validator signature routine for dealing
|
||||
with the synthesized CNAME for a DNAME without previously
|
||||
encountering it and also for when the qtype is DNAME.
|
||||
- Fix qname minimisation for reply with a DNAME for qtype CNAME that
|
||||
answers it.
|
||||
- Fix doc test so it ignores but outputs unsupported doxygen options.
|
||||
- Fix unbound-control-setup.cmd to have CA v3 basicConstraints,
|
||||
like unbound-control-setup.sh has. This fix is included in 1.19.3rc2.
|
||||
|
||||
8 March 2024: Yorgos
|
||||
- Update doc/unbound.doxygen with 'doxygen -u'. Fixes option
|
||||
deprecation warnings and updates with newer defaults.
|
||||
|
||||
7 March 2024: Wouter
|
||||
- Version set to 1.19.3 for release. After 1.19.2 point release with
|
||||
security fix for CVE-2024-1931, Denial of service when trimming
|
||||
EDE text on positive replies. The code repo includes the fix and
|
||||
is for version 1.19.3. The code repo continues for version 1.19.4,
|
||||
but 1.19.3 includes the fixes in 1.19.3rc2 as well.
|
||||
|
||||
5 March 2024: Wouter
|
||||
- Fix for #1022: Fix ede prohibited in access control refused answers.
|
||||
|
||||
4 March 2024: Wouter
|
||||
- Fix edns subnet replies for scope zero answers to not get stored
|
||||
in the global cache, and in cachedb, when the upstream replies
|
||||
without an EDNS record.
|
||||
|
||||
28 February 2024: Wouter
|
||||
- Move github workflows to use checkoutv4.
|
||||
|
||||
23 February 2024: Yorgos
|
||||
- Document the suspend argument for process_ds_response().
|
||||
|
||||
22 February 2024: Wouter
|
||||
- Fix trim of EDE text from large udp responses from spinning cpu.
|
||||
|
||||
20 February 2024: Yorgos
|
||||
- Merge #1010: Mention REFUSED has the TC bit set with unmatched
|
||||
allow_cookie acl in the manpage. It also fixes the code to match the
|
||||
documentation about clients with a valid cookie that bypass the
|
||||
ratelimit regardless of the allow_cookie acl.
|
||||
|
||||
13 February 2024: Wouter
|
||||
- Fix CVE-2023-50387, DNSSEC verification complexity can be exploited
|
||||
to exhaust CPU resources and stall DNS resolvers.
|
||||
- Fix CVE-2023-50868, NSEC3 closest encloser proof can exhaust CPU.
|
||||
- These fixes are part of the 1.19.1 release, that is a security
|
||||
point release on 1.19.0, the code repository continues with these
|
||||
fixes, with version number 1.19.2.
|
||||
|
||||
8 February 2024: Wouter
|
||||
- Fix documentation for access-control in the unbound.conf man page.
|
||||
|
||||
7 February 2024: Yorgos
|
||||
- Fix #1006: Can't find protobuf-c package since #999.
|
||||
|
||||
30 January 2024: Wouter
|
||||
- Merge #999: Search for protobuf-c with pkg-config.
|
||||
|
||||
23 January 2024: Yorgos
|
||||
- Update message TTL when using cached RRSETs. It could result in
|
||||
non-expired messages with expired RRSETs (non-usable messages by
|
||||
Unbound).
|
||||
|
||||
22 January 2024: Yorgos
|
||||
- Update error printout for duplicate trust anchors to include the
|
||||
trust anchor name (relates to #920).
|
||||
|
||||
22 January 2024: Wouter
|
||||
- Fix for #997: Print details for SSL certificate failure.
|
||||
|
||||
17 January 2024: Wouter
|
||||
- Update workflow for ports to use newer openssl on windows compile.
|
||||
- Fix warning for windres on resource files due to redefinition.
|
||||
|
||||
16 January 2024: Wouter
|
||||
- Fix to link with libssp for libcrypto and getaddrinfo check for
|
||||
only header. Also update crosscompile to remove ssp for 32bit.
|
||||
- Merge #993: Update b.root-servers.net also in example config file.
|
||||
|
||||
15 January 2024: Wouter
|
||||
- Fix to link with -lcrypt32 for OpenSSL 3.2.0 on Windows.
|
||||
|
||||
9 January 2024: Wouter
|
||||
- Merge #988: Fix NLnetLabs#981: dump_cache truncates large records.
|
||||
|
||||
5 January 2024: Wouter
|
||||
- Merge #987: skip edns frag retry if advertised udp payload size is
|
||||
not smaller.
|
||||
- Fix unit test for #987 change in udp1xxx retry packet send.
|
||||
|
||||
4 January 2024: Wouter
|
||||
- Remove unneeded newlines and improve indentation in remote control
|
||||
code.
|
||||
|
||||
3 January 2024: Wouter
|
||||
- Merge #980: DoH: reject non-h2 early. To fix #979: Improve errors
|
||||
for non-HTTP/2 DoH clients.
|
||||
- Merge #985: Add DoH and DoT to dnstap message.
|
||||
- Fix #983: Sha1 runtime insecure change was incomplete.
|
||||
|
||||
22 December 2023: Yorgos
|
||||
- Update example.conf with cookie options.
|
||||
|
||||
8 December 2023: Yorgos
|
||||
- Merge PR #973: Use the origin (DNAME) TTL for synthesized CNAMEs as
|
||||
per RFC 6672.
|
||||
|
||||
8 December 2023: Wouter
|
||||
- Fix root_zonemd unit test, it checks that the root ZONEMD verifies,
|
||||
now that the root has a valid ZONEMD.
|
||||
|
||||
7 December 2023: Wouter
|
||||
- Fix #974: doc: default number of outgoing ports without libevent.
|
||||
- Merge #975: Fixed some syntax errors in rpl files.
|
||||
|
||||
6 December 2023: Wouter
|
||||
- Fix to sync the tests script file common.sh.
|
||||
- iana portlist update.
|
||||
- Updated IPv4 and IPv6 address for b.root-servers.net in root hints.
|
||||
- Update test script file common.sh.
|
||||
- Fix tests to use new common.sh functions, wait_logfile and
|
||||
kill_from_pidfile.
|
||||
|
||||
5 December 2023: Wouter
|
||||
- Merge #971: fix 'WARNING: Message has 41 extra bytes at end'.
|
||||
- Fix #969: [FR] distinguish Do53, DoT and DoH in the logs.
|
||||
- Fix dnstap that assertion failed on logging other than UDP and TCP
|
||||
traffic. It lists it as TCP traffic.
|
||||
|
||||
27 November 2023: Yorgos
|
||||
- Merge #968: Replace the obsolescent fgrep with grep -F in tests.
|
||||
|
||||
27 November 2023: Wouter
|
||||
- Fix #964: config.h.in~ backup file in release tar balls.
|
||||
|
||||
24 November 2023: Yorgos
|
||||
- Use 127.0.0.1 explicitly in tests to avoid delays and errors on
|
||||
newer systems.
|
||||
|
||||
9 November 2023: Wouter
|
||||
- Fix unit test parse of origin syntax.
|
||||
|
||||
2 November 2023: Wouter
|
||||
- Set version number to 1.19.0.
|
||||
- Tag for 1.19.0rc1 release.
|
||||
- Tag for 1.19.0rc1 release. It became 1.19.0 release on 8 nov 2023.
|
||||
The repository continues with 1.19.1.
|
||||
|
||||
1 November 2023: George
|
||||
- Mention flex and bison in README.md when building from repository
|
||||
|
||||
+4
-5
@@ -19,11 +19,10 @@ The DNSTAP code has BSD license in dnstap/dnstap.c.
|
||||
* Make and install: ./configure; make; make install
|
||||
* --with-libevent=/path/to/libevent
|
||||
Can be set to either the system install or the build directory.
|
||||
--with-libevent=no (default) gives a builtin alternative
|
||||
implementation. libevent is useful when having many (thousands)
|
||||
of outgoing ports. This improves randomization and spoof
|
||||
resistance. For the default of 16 ports the builtin alternative
|
||||
works well and is a little faster.
|
||||
--with-libevent=no gives a builtin alternative implementation.
|
||||
Libevent is enabled by default, it is useful when having many
|
||||
(thousands) of outgoing ports. This improves randomization and spoof
|
||||
resistance. It also allows a higher number of outgoing queries.
|
||||
* --with-libexpat=/path/to/libexpat
|
||||
Can be set to the install directory of libexpat.
|
||||
* --without-pthreads
|
||||
|
||||
+79
-4
@@ -187,10 +187,34 @@ 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: 128
|
||||
|
||||
# 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
|
||||
|
||||
# msec before recursion replies are dropped. The work item continues.
|
||||
# discard-timeout: 1900
|
||||
|
||||
# Max number of replies waiting for recursion per IP address.
|
||||
# wait-limit: 1000
|
||||
|
||||
# Max replies waiting for recursion for IP address with cookie.
|
||||
# wait-limit-cookie: 10000
|
||||
|
||||
# Apart from the default, the wait limit can be set for a netblock.
|
||||
# wait-limit-netblock: 192.0.2.0/24 50000
|
||||
|
||||
# Apart from the default, the wait limit with cookie can be adjusted.
|
||||
# wait-limit-cookie-netblock: 192.0.2.0/24 50000
|
||||
|
||||
# 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
|
||||
@@ -211,6 +235,11 @@ server:
|
||||
# the time to live (TTL) value cap for negative responses in the cache
|
||||
# cache-max-negative-ttl: 3600
|
||||
|
||||
# the time to live (TTL) value lower bound, in seconds. Default 0.
|
||||
# For negative responses in the cache. If disabled, default,
|
||||
# cache-min-ttl applies if configured.
|
||||
# cache-min-negative-ttl: 0
|
||||
|
||||
# the time to live (TTL) value for cached roundtrip times, lameness and
|
||||
# EDNS version information for hosts. In seconds.
|
||||
# infra-host-ttl: 900
|
||||
@@ -283,7 +312,8 @@ server:
|
||||
# Enable EDNS TCP keepalive option.
|
||||
# edns-tcp-keepalive: no
|
||||
|
||||
# Timeout for EDNS TCP keepalive, in msec.
|
||||
# Timeout for EDNS TCP keepalive, in msec. Overrides tcp-idle-timeout
|
||||
# if edns-tcp-keepalive is set.
|
||||
# edns-tcp-keepalive-timeout: 120000
|
||||
|
||||
# UDP queries that have waited in the socket buffer for a long time
|
||||
@@ -303,6 +333,7 @@ server:
|
||||
# Choose deny (drop message), refuse (polite error reply),
|
||||
# allow (recursive ok), allow_setrd (recursive ok, rd bit is forced on),
|
||||
# allow_snoop (recursive and nonrecursive ok)
|
||||
# allow_cookie (allow UDP with valid cookie or stateful transport)
|
||||
# deny_non_local (drop queries unless can be answered from local-data)
|
||||
# refuse_non_local (like deny_non_local but polite error reply).
|
||||
# access-control: 127.0.0.0/8 allow
|
||||
@@ -430,6 +461,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
|
||||
|
||||
@@ -441,6 +476,9 @@ server:
|
||||
# filtering log-queries and log-replies from the log.
|
||||
# log-tag-queryreply: no
|
||||
|
||||
# log with destination address, port and type for log-replies.
|
||||
# log-destaddr: no
|
||||
|
||||
# log the local-zone actions, like local-zone type inform is enabled
|
||||
# also for the other local zone types.
|
||||
# log-local-actions: no
|
||||
@@ -499,6 +537,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).
|
||||
@@ -879,6 +920,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"
|
||||
@@ -943,6 +985,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.
|
||||
@@ -983,6 +1028,13 @@ server:
|
||||
# if 0(default) it is disabled, otherwise states qps allowed per ip address
|
||||
# ip-ratelimit: 0
|
||||
|
||||
# global query ratelimit for all ip addresses with a valid DNS Cookie.
|
||||
# feature is experimental.
|
||||
# if 0(default) it is disabled, otherwise states qps allowed per ip address
|
||||
# useful in combination with 'allow_cookie'.
|
||||
# If used, suggested to be higher than ip-ratelimit, tenfold.
|
||||
# ip-ratelimit-cookie: 0
|
||||
|
||||
# ip ratelimits are tracked in a cache, size in bytes of cache (or k,m).
|
||||
# ip-ratelimit-size: 4m
|
||||
# ip ratelimit cache slabs, reduces lock contention if equal to cpucount.
|
||||
@@ -1004,6 +1056,19 @@ server:
|
||||
# the number of servers that will be used in the fast server selection.
|
||||
# fast-server-num: 3
|
||||
|
||||
# reply to requests containing DNS Cookies as specified in RFC 7873 and RFC 9018.
|
||||
# answer-cookie: no
|
||||
|
||||
# secret for DNS Cookie generation.
|
||||
# useful for anycast deployments.
|
||||
# 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
|
||||
|
||||
@@ -1150,7 +1215,7 @@ remote-control:
|
||||
# sources of notifies.
|
||||
# auth-zone:
|
||||
# name: "."
|
||||
# primary: 199.9.14.201 # b.root-servers.net
|
||||
# primary: 170.247.170.2 # b.root-servers.net
|
||||
# primary: 192.33.4.12 # c.root-servers.net
|
||||
# primary: 199.7.91.13 # d.root-servers.net
|
||||
# primary: 192.5.5.241 # f.root-servers.net
|
||||
@@ -1158,7 +1223,7 @@ remote-control:
|
||||
# primary: 193.0.14.129 # k.root-servers.net
|
||||
# primary: 192.0.47.132 # xfr.cjr.dns.icann.org
|
||||
# primary: 192.0.32.132 # xfr.lax.dns.icann.org
|
||||
# primary: 2001:500:200::b # b.root-servers.net
|
||||
# primary: 2801:1b8:10::b # b.root-servers.net
|
||||
# primary: 2001:500:2::c # c.root-servers.net
|
||||
# primary: 2001:500:2d::d # d.root-servers.net
|
||||
# primary: 2001:500:2f::f # f.root-servers.net
|
||||
@@ -1228,6 +1293,9 @@ remote-control:
|
||||
# secret-seed: "default"
|
||||
# # if the backend should be read from, but not written to.
|
||||
# cachedb-no-store: no
|
||||
# # if the cachedb should be checked before a serve-expired response is
|
||||
# # given, when serve-expired is enabled.
|
||||
# cachedb-check-when-serve-expired: yes
|
||||
#
|
||||
# # For "redis" backend:
|
||||
# # (to enable, use --with-libhiredis to configure before compiling)
|
||||
@@ -1241,6 +1309,10 @@ remote-control:
|
||||
# # 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.
|
||||
@@ -1286,6 +1358,8 @@ remote-control:
|
||||
# dnstap-identity: ""
|
||||
# # if "" it uses the package version.
|
||||
# dnstap-version: ""
|
||||
# # log only 1/N messages, if 0 it is disabled. default 0.
|
||||
# dnstap-sample-rate: 0
|
||||
# dnstap-log-resolver-query-messages: no
|
||||
# dnstap-log-resolver-response-messages: no
|
||||
# dnstap-log-client-query-messages: no
|
||||
@@ -1294,7 +1368,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
|
||||
|
||||
@@ -14,6 +14,7 @@ unbound\-checkconf
|
||||
.B unbound\-checkconf
|
||||
.RB [ \-h ]
|
||||
.RB [ \-f ]
|
||||
.RB [ \-q ]
|
||||
.RB [ \-o
|
||||
.IR option ]
|
||||
.RI [ cfgfile ]
|
||||
@@ -37,6 +38,9 @@ Print full pathname, with chroot applied to it. Use with the \-o option.
|
||||
If given, after checking the config file the value of this option is
|
||||
printed to stdout. For "" (disabled) options an empty line is printed.
|
||||
.TP
|
||||
.B \-q
|
||||
Make the operation quiet, suppress output on success.
|
||||
.TP
|
||||
.I cfgfile
|
||||
The config file to read with settings for Unbound. It is checked.
|
||||
If omitted, the config file at the default location is checked.
|
||||
|
||||
+65
-13
@@ -121,31 +121,38 @@ Remove local data RRs read from stdin of unbound\-control. Input is one name per
|
||||
line. For bulk removals.
|
||||
.TP
|
||||
.B dump_cache
|
||||
The contents of the cache is printed in a text format to stdout. You can
|
||||
redirect it to a file to store the cache in a file.
|
||||
The content of the cache is printed in a text format to stdout.
|
||||
You can redirect it to a file to store the cache in a file.
|
||||
Not supported in remote Unbounds in multi-process operation.
|
||||
.TP
|
||||
.B load_cache
|
||||
The contents of the cache is loaded from stdin. Uses the same format as
|
||||
dump_cache uses. Loading the cache with old, or wrong data can result
|
||||
in old or wrong data returned to clients. Loading data into the cache
|
||||
in this way is supported in order to aid with debugging.
|
||||
The content of the cache is loaded from stdin.
|
||||
Uses the same format as dump_cache uses.
|
||||
Loading the cache with old, or wrong data can result in old or wrong data
|
||||
returned to clients.
|
||||
Loading data into the cache in this way is supported in order to aid with
|
||||
debugging.
|
||||
Not supported in remote Unbounds in multi-process operation.
|
||||
.TP
|
||||
.B lookup \fIname
|
||||
Print to stdout the name servers that would be used to look up the
|
||||
name specified.
|
||||
.TP
|
||||
.B flush \fIname
|
||||
.B flush \fR[\fI+c\fR] \fIname
|
||||
Remove the name from the cache. Removes the types
|
||||
A, AAAA, NS, SOA, CNAME, DNAME, MX, PTR, SRV, NAPTR, SVCB and HTTPS.
|
||||
Because that is fast to do. Other record types can be removed using
|
||||
.B flush_type
|
||||
or
|
||||
.B flush_zone\fR.
|
||||
.IP
|
||||
The '+c' option removes the items also from the cachedb cache. If
|
||||
cachedb is in use.
|
||||
.TP
|
||||
.B flush_type \fIname\fR \fItype
|
||||
.B flush_type \fR[\fI+c\fR] \fIname\fR \fItype
|
||||
Remove the name, type information from the cache.
|
||||
.TP
|
||||
.B flush_zone \fIname
|
||||
.B flush_zone \fR[\fI+c\fR] \fIname
|
||||
Remove all information at or below the name from the cache.
|
||||
The rrsets and key entries are removed so that new lookups will be performed.
|
||||
This needs to walk and inspect the entire cache, and is a slow operation.
|
||||
@@ -153,10 +160,10 @@ The entries are set to expired in the implementation of this command (so,
|
||||
with serve\-expired enabled, it'll serve that information but schedule a
|
||||
prefetch for new information).
|
||||
.TP
|
||||
.B flush_bogus
|
||||
.B flush_bogus \fR[\fI+c\fR]
|
||||
Remove all bogus data from the cache.
|
||||
.TP
|
||||
.B flush_negative
|
||||
.B flush_negative \fR[\fI+c\fR]
|
||||
Remove all negative data from the cache. This is nxdomain answers,
|
||||
nodata answers and servfail answers. Also removes bad key entries
|
||||
(which could be due to failed lookups) from the dnssec key cache, and
|
||||
@@ -239,22 +246,24 @@ still be bogus, use \fBflush_zone\fR to remove it), does not affect the config f
|
||||
.B insecure_remove \fIzone
|
||||
Removes domain\-insecure for the given zone.
|
||||
.TP
|
||||
.B forward_add \fR[\fI+i\fR] \fIzone addr ...
|
||||
.B forward_add \fR[\fI+it\fR] \fIzone addr ...
|
||||
Add a new forward zone to running Unbound. With +i option also adds a
|
||||
\fIdomain\-insecure\fR for the zone (so it can resolve insecurely if you have
|
||||
a DNSSEC root trust anchor configured for other names).
|
||||
The addr can be IP4, IP6 or nameserver names, like \fIforward-zone\fR config
|
||||
in unbound.conf.
|
||||
The +t option sets it to use tls upstream, like \fIforward\-tls\-upstream\fR: yes.
|
||||
.TP
|
||||
.B forward_remove \fR[\fI+i\fR] \fIzone
|
||||
Remove a forward zone from running Unbound. The +i also removes a
|
||||
\fIdomain\-insecure\fR for the zone.
|
||||
.TP
|
||||
.B stub_add \fR[\fI+ip\fR] \fIzone addr ...
|
||||
.B stub_add \fR[\fI+ipt\fR] \fIzone addr ...
|
||||
Add a new stub zone to running Unbound. With +i option also adds a
|
||||
\fIdomain\-insecure\fR for the zone. With +p the stub zone is set to prime,
|
||||
without it it is set to notprime. The addr can be IP4, IP6 or nameserver
|
||||
names, like the \fIstub-zone\fR config in unbound.conf.
|
||||
The +t option sets it to use tls upstream, like \fIstub\-tls\-upstream\fR: yes.
|
||||
.TP
|
||||
.B stub_remove \fR[\fI+i\fR] \fIzone
|
||||
Remove a stub zone from running Unbound. The +i also removes a
|
||||
@@ -341,6 +350,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"
|
||||
@@ -562,6 +606,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.
|
||||
@@ -610,6 +658,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
|
||||
|
||||
+173
-43
@@ -302,6 +302,36 @@ Increase this if you are behind a slow satellite link, to eg. 1128.
|
||||
That would then avoid re\-querying every initial query because it times out.
|
||||
Default is 376 msec.
|
||||
.TP
|
||||
.B discard\-timeout: \fI<msec>
|
||||
The wait time in msec where recursion requests are dropped. This is
|
||||
to stop a large number of replies from accumulating. They receive
|
||||
no reply, the work item continues to recurse. It is nice to be a bit
|
||||
larger than serve\-expired\-client\-timeout if that is enabled.
|
||||
A value of 1900 msec is suggested. The value 0 disables it.
|
||||
Default 1900 msec.
|
||||
.TP
|
||||
.B wait\-limit: \fI<number>
|
||||
The number of replies that can wait for recursion, for an IP address.
|
||||
This makes a ratelimit per IP address of waiting replies for recursion.
|
||||
It stops very large amounts of queries waiting to be returned to one
|
||||
destination. The value 0 disables wait limits. Default is 1000.
|
||||
.TP
|
||||
.B wait\-limit\-cookie: \fI<number>
|
||||
The number of replies that can wait for recursion, for an IP address
|
||||
that sent the query with a valid DNS cookie. Since the cookie validates
|
||||
the client address, the limit can be higher. Default is 10000.
|
||||
.TP
|
||||
.B wait\-limit\-netblock: \fI<netblock> <number>
|
||||
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.
|
||||
.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.
|
||||
.TP
|
||||
.B so\-rcvbuf: \fI<number>
|
||||
If not 0, then set the SO_RCVBUF socket option to get more buffer
|
||||
space on UDP port 53 incoming queries. So that short spikes on busy
|
||||
@@ -388,6 +418,15 @@ Time to live maximum for negative responses, these have a SOA in the
|
||||
authority section that is limited in time. Default is 3600.
|
||||
This applies to nxdomain and nodata answers.
|
||||
.TP
|
||||
.B cache\-min\-negative\-ttl: \fI<seconds>
|
||||
Time to live minimum for negative responses, these have a SOA in the
|
||||
authority section that is limited in time.
|
||||
Default is 0 (disabled).
|
||||
If this is disabled and \fBcache-min-ttl\fR is configured, it will take effect
|
||||
instead.
|
||||
In that case you can set this to 1 to honor the upstream TTL.
|
||||
This applies to nxdomain and nodata answers.
|
||||
.TP
|
||||
.B infra\-host\-ttl: \fI<seconds>
|
||||
Time to live for entries in the host cache. The host cache contains
|
||||
roundtrip timing, lameness and EDNS support information. Default is 900.
|
||||
@@ -472,6 +511,8 @@ configured value if the number of free buffers falls below 35% of the
|
||||
total number configured, and finally to 0 if the number of free buffers
|
||||
falls below 20% of the total number configured. A minimum timeout of
|
||||
200 milliseconds is observed regardless of the option value used.
|
||||
It will be overridden by \fBedns\-tcp\-keepalive\-timeout\fR if
|
||||
\fBedns\-tcp\-keepalive\fR is enabled.
|
||||
.TP
|
||||
.B tcp-reuse-timeout: \fI<msec>\fR
|
||||
The period Unbound will keep TCP persistent connections open to
|
||||
@@ -490,20 +531,11 @@ This option defaults to 3000 milliseconds.
|
||||
Enable or disable EDNS TCP Keepalive. Default is no.
|
||||
.TP
|
||||
.B edns-tcp-keepalive-timeout: \fI<msec>\fR
|
||||
The period Unbound will wait for a query on a TCP connection when
|
||||
EDNS TCP Keepalive is active. If this timeout expires Unbound closes
|
||||
the connection. If the client supports the EDNS TCP Keepalive option,
|
||||
Overrides \fBtcp\-idle\-timeout\fR when \fBedns\-tcp\-keepalive\fR is enabled.
|
||||
If the client supports the EDNS TCP Keepalive option,
|
||||
Unbound sends the timeout value to the client to encourage it to
|
||||
close the connection before the server times out.
|
||||
This option defaults to 120000 milliseconds.
|
||||
When the number of free incoming TCP buffers falls below 50% of
|
||||
the total number configured, the advertised timeout is progressively
|
||||
reduced to 1% of the configured value, then to 0.2% of the configured
|
||||
value if the number of free buffers falls below 35% of the total number
|
||||
configured, and finally to 0 if the number of free buffers falls below
|
||||
20% of the total number configured.
|
||||
A minimum actual timeout of 200 milliseconds is observed regardless of the
|
||||
advertised timeout.
|
||||
.TP
|
||||
.B sock\-queue\-timeout: \fI<sec>\fR
|
||||
UDP queries that have waited in the socket buffer for a long time can be
|
||||
@@ -534,6 +566,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
|
||||
@@ -684,6 +719,18 @@ PROXYv2 is supported for UDP and TCP/TLS listening interfaces.
|
||||
There is no support for PROXYv2 on a DoH or DNSCrypt listening interface.
|
||||
Can list multiple, each on a new statement.
|
||||
.TP
|
||||
.B 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.
|
||||
@@ -699,6 +746,12 @@ When at the limit, further connections are accepted but closed immediately.
|
||||
This option is experimental at this time.
|
||||
.TP
|
||||
.B access\-control: \fI<IP netblock> <action>
|
||||
Specify treatment of incoming queries from their originating IP address.
|
||||
Queries can be allowed to have access to this server that gives DNS
|
||||
answers, or refused, with other actions possible. The IP address range
|
||||
can be specified as a netblock, it is possible to give the statement
|
||||
several times in order to specify the treatment of different netblocks.
|
||||
.IP
|
||||
The netblock is given as an IP4 or IP6 address with /size appended for a
|
||||
classless network block. The action can be \fIdeny\fR, \fIrefuse\fR,
|
||||
\fIallow\fR, \fIallow_setrd\fR, \fIallow_snoop\fR, \fIallow_cookie\fR,
|
||||
@@ -738,7 +791,7 @@ the cache contents (for malicious acts). However, nonrecursive queries can
|
||||
also be a valuable debugging tool (when you want to examine the cache
|
||||
contents). In that case use \fIallow_snoop\fR for your administration host.
|
||||
.IP
|
||||
The \fIallow_cookie\fR action allows access to UDP queries that contain a
|
||||
The \fIallow_cookie\fR action allows access only to UDP queries that contain a
|
||||
valid DNS Cookie as specified in RFC 7873 and RFC 9018, when the
|
||||
\fBanswer\-cookie\fR option is enabled.
|
||||
UDP queries containing only a DNS Client Cookie and no Server Cookie, or an
|
||||
@@ -747,12 +800,11 @@ generated DNS Cookie, allowing clients to retry with that DNS Cookie.
|
||||
The \fIallow_cookie\fR action will also accept requests over stateful
|
||||
transports, regardless of the presence of an DNS Cookie and regardless of the
|
||||
\fBanswer\-cookie\fR setting.
|
||||
If \fBip\-ratelimit\fR is used, clients with a valid DNS Cookie will bypass the
|
||||
ratelimit.
|
||||
If a ratelimit for such clients is still needed, \fBip\-ratelimit\-cookie\fR
|
||||
can be used instead.
|
||||
UDP queries without a DNS Cookie receive REFUSED responses with the TC flag set,
|
||||
that may trigger fall back to TCP for those clients.
|
||||
.IP
|
||||
By default only localhost is \fIallow\fRed, the rest is \fIrefuse\fRd.
|
||||
By default only localhost (the 127.0.0.0/8 IP netblock, not the loopback
|
||||
interface) is implicitly \fIallow\fRed, the rest is \fIrefuse\fRd.
|
||||
The default is \fIrefuse\fRd, because that is protocol\-friendly. The DNS
|
||||
protocol is not designed to handle dropped packets due to policy, and
|
||||
dropping may result in (possibly excessive) retried queries.
|
||||
@@ -788,8 +840,12 @@ Similar to \fBaccess\-control:\fR but for interfaces.
|
||||
.IP
|
||||
The action is the same as the ones defined under \fBaccess\-control:\fR.
|
||||
Interfaces are \fIrefuse\fRd by default.
|
||||
By default only localhost (the IP netblock, not the loopback interface) is
|
||||
\fIallow\fRed through the default \fBaccess\-control:\fR behavior.
|
||||
By default only localhost (the 127.0.0.0/8 IP netblock, not the loopback
|
||||
interface) is implicitly \fIallow\fRed through the default
|
||||
\fBaccess\-control:\fR behavior.
|
||||
This also means that any attempt to use the \fBinterface-*:\fR options for the
|
||||
loopback interface will not work as they will be overridden by the implicit
|
||||
default "\fBaccess\-control:\fR 127.0.0.0/8 allow" option.
|
||||
.IP
|
||||
Note that the interface needs to be already specified with \fBinterface:\fR
|
||||
and that any \fBaccess-control*:\fR setting overrides all \fBinterface-*:\fR
|
||||
@@ -895,6 +951,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
|
||||
@@ -913,6 +973,11 @@ Prints the word 'query' and 'reply' with log\-queries and log\-replies.
|
||||
This makes filtering logs easier. The default is off (for backwards
|
||||
compatibility).
|
||||
.TP
|
||||
.B log\-destaddr: \fI<yes or no>
|
||||
Prints the destination address, port and type in the log\-replies output.
|
||||
This disambiguates what type of traffic, eg. udp or tcp, and to what local
|
||||
port the traffic was sent to.
|
||||
.TP
|
||||
.B log\-local\-actions: \fI<yes or no>
|
||||
Print log lines to inform about local zone actions. These lines are like the
|
||||
local\-zone type inform prints out, but they are also printed for the other
|
||||
@@ -1002,6 +1067,11 @@ payload is very large.
|
||||
.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
|
||||
@@ -1125,10 +1195,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
|
||||
@@ -1148,12 +1219,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
|
||||
@@ -1839,6 +1911,9 @@ The ratelimit is in queries per second that are allowed. More queries are
|
||||
completely dropped and will not receive a reply, SERVFAIL or otherwise.
|
||||
IP ratelimiting happens before looking in the cache. This may be useful for
|
||||
mitigating amplification attacks.
|
||||
Clients with a valid DNS Cookie will bypass the ratelimit.
|
||||
If a ratelimit for such clients is still needed, \fBip\-ratelimit\-cookie\fR
|
||||
can be used instead.
|
||||
Default is 0 (disabled).
|
||||
.TP 5
|
||||
.B ip\-ratelimit\-cookie: \fI<number or 0>
|
||||
@@ -1908,6 +1983,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 128.
|
||||
.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
|
||||
@@ -1934,6 +2026,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
|
||||
@@ -2626,11 +2732,7 @@ If Unbound cannot even find an answer in the backend, it resolves the
|
||||
query as usual, and stores the answer in the backend.
|
||||
.P
|
||||
This module interacts with the \fBserve\-expired\-*\fR options and will reply
|
||||
with expired data if Unbound is configured for that. Currently the use
|
||||
of \fBserve\-expired\-client\-timeout:\fR and
|
||||
\fBserve\-expired\-reply\-ttl:\fR is not consistent for data originating from
|
||||
the external cache as these will result in a reply with 0 TTL without trying to
|
||||
update the data first, ignoring the configured values.
|
||||
with expired data if Unbound is configured for that.
|
||||
.P
|
||||
If Unbound was built with
|
||||
\fB\-\-with\-libhiredis\fR
|
||||
@@ -2686,6 +2788,16 @@ This option defaults to "default".
|
||||
If the backend should be read from, but not written to. This makes this
|
||||
instance not store dns messages in the backend. But if data is available it
|
||||
is retrieved. The default is no.
|
||||
.TP
|
||||
.B cachedb-check-when-serve-expired: \fI<yes or no>\fR
|
||||
If enabled, the cachedb is checked before an expired response is returned.
|
||||
When \fBserve\-expired\fR is enabled, without \fBserve\-expired\-client\-timeout\fR, it then
|
||||
does not immediately respond with an expired response from cache, but instead
|
||||
first checks the cachedb for valid contents, and if so returns it. If the
|
||||
cachedb also has no valid contents, the serve expired response is sent.
|
||||
If also \fBserve\-expired\-client\-timeout\fR is enabled, the expired response
|
||||
is delayed until the timeout expires. Unless the lookup succeeds within the
|
||||
timeout. The default is yes.
|
||||
.P
|
||||
The following
|
||||
.B cachedb
|
||||
@@ -2719,6 +2831,14 @@ 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
|
||||
redis\-timeout 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 redis\-timeout 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
|
||||
@@ -2797,6 +2917,13 @@ Default is "".
|
||||
The version to send with messages, if "" the package version is used.
|
||||
Default is "".
|
||||
.TP
|
||||
.B dnstap-sample-rate: \fI<number>
|
||||
The sample rate for log of messages, it logs only 1/N messages. With 0 it
|
||||
is disabled. Default is 0. This is useful in a high volume environment,
|
||||
where log functionality would otherwise not be reliable. For example 10
|
||||
would spend only 1/10th time on logging, and 100 would only spend a
|
||||
hundredth of the time on logging.
|
||||
.TP
|
||||
.B dnstap-log-resolver-query-messages: \fI<yes or no>
|
||||
Enable to log resolver query messages. Default is no.
|
||||
These are messages from Unbound to upstream servers.
|
||||
@@ -2821,9 +2948,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.
|
||||
@@ -2831,12 +2960,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
|
||||
@@ -2936,7 +3066,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
|
||||
|
||||
+2007
-886
File diff suppressed because it is too large
Load Diff
@@ -297,8 +297,8 @@ inplace_cb_delete_wrapped(struct module_env* env, enum inplace_cb_list_type type
|
||||
*/
|
||||
static struct module_func_block dynlibmod_block = {
|
||||
"dynlib",
|
||||
&dynlibmod_init, &dynlibmod_deinit, &dynlibmod_operate, &dynlibmod_inform_super,
|
||||
&dynlibmod_clear, &dynlibmod_get_mem
|
||||
NULL, NULL, &dynlibmod_init, &dynlibmod_deinit, &dynlibmod_operate,
|
||||
&dynlibmod_inform_super, &dynlibmod_clear, &dynlibmod_get_mem
|
||||
};
|
||||
|
||||
struct module_func_block* dynlibmod_get_funcblock(void)
|
||||
|
||||
+38
-5
@@ -57,6 +57,9 @@
|
||||
#include "sldns/sbuffer.h"
|
||||
#include "sldns/wire2str.h"
|
||||
#include "iterator/iter_utils.h"
|
||||
#ifdef USE_CACHEDB
|
||||
#include "cachedb/cachedb.h"
|
||||
#endif
|
||||
|
||||
/** externally called */
|
||||
void
|
||||
@@ -152,7 +155,7 @@ int ecs_whitelist_check(struct query_info* qinfo,
|
||||
|
||||
/* Cache by default, might be disabled after parsing EDNS option
|
||||
* received from nameserver. */
|
||||
if(!iter_stub_fwd_no_cache(qstate, &qstate->qinfo, NULL, NULL)) {
|
||||
if(!iter_stub_fwd_no_cache(qstate, &qstate->qinfo, NULL, NULL, NULL, 0)) {
|
||||
qstate->no_cache_store = 0;
|
||||
}
|
||||
|
||||
@@ -310,9 +313,18 @@ delfunc(void *envptr, void *elemptr) {
|
||||
static size_t
|
||||
sizefunc(void *elemptr) {
|
||||
struct reply_info *elem = (struct reply_info *)elemptr;
|
||||
return sizeof (struct reply_info) - sizeof (struct rrset_ref)
|
||||
size_t s = sizeof (struct reply_info) - sizeof (struct rrset_ref)
|
||||
+ elem->rrset_count * sizeof (struct rrset_ref)
|
||||
+ elem->rrset_count * sizeof (struct ub_packed_rrset_key *);
|
||||
size_t i;
|
||||
for (i = 0; i < elem->rrset_count; i++) {
|
||||
struct ub_packed_rrset_key *key = elem->rrsets[i];
|
||||
struct packed_rrset_data *data = key->entry.data;
|
||||
s += ub_rrset_sizefunc(key, data);
|
||||
}
|
||||
if(elem->reason_bogus_str)
|
||||
s += strlen(elem->reason_bogus_str)+1;
|
||||
return s;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -352,7 +364,7 @@ update_cache(struct module_qstate *qstate, int id)
|
||||
struct slabhash *subnet_msg_cache = sne->subnet_msg_cache;
|
||||
struct ecs_data *edns = &sq->ecs_client_in;
|
||||
size_t i;
|
||||
int only_match_scope_zero;
|
||||
int only_match_scope_zero, diff_size;
|
||||
|
||||
/* We already calculated hash upon lookup (lookup_and_reply) if we were
|
||||
* allowed to look in the ECS cache */
|
||||
@@ -412,19 +424,25 @@ update_cache(struct module_qstate *qstate, int id)
|
||||
rep->ref[i].id = rep->rrsets[i]->id;
|
||||
}
|
||||
reply_info_set_ttls(rep, *qstate->env->now);
|
||||
reply_info_sortref(rep);
|
||||
rep->flags |= (BIT_RA | BIT_QR); /* fix flags to be sensible for */
|
||||
rep->flags &= ~(BIT_AA | BIT_CD);/* a reply based on the cache */
|
||||
if(edns->subnet_source_mask == 0 && edns->subnet_scope_mask == 0)
|
||||
only_match_scope_zero = 1;
|
||||
else only_match_scope_zero = 0;
|
||||
diff_size = (int)tree->size_bytes;
|
||||
addrtree_insert(tree, (addrkey_t*)edns->subnet_addr,
|
||||
edns->subnet_source_mask, sq->max_scope, rep,
|
||||
rep->ttl, *qstate->env->now, only_match_scope_zero);
|
||||
diff_size = (int)tree->size_bytes - diff_size;
|
||||
|
||||
lock_rw_unlock(&lru_entry->lock);
|
||||
if (need_to_insert) {
|
||||
slabhash_insert(subnet_msg_cache, h, lru_entry, lru_entry->data,
|
||||
NULL);
|
||||
} else {
|
||||
slabhash_update_space_used(subnet_msg_cache, h, NULL,
|
||||
diff_size);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -587,7 +605,21 @@ eval_response(struct module_qstate *qstate, int id, struct subnet_qstate *sq)
|
||||
}
|
||||
sne->num_msg_nocache++;
|
||||
lock_rw_unlock(&sne->biglock);
|
||||
|
||||
|
||||
/* If there is an expired answer in the global cache, remove that,
|
||||
* because expired answers would otherwise resurface once the ecs data
|
||||
* expires, giving once in a while global data responses for ecs
|
||||
* domains, with serve expired enabled. */
|
||||
if(qstate->env->cfg->serve_expired) {
|
||||
msg_cache_remove(qstate->env, qstate->qinfo.qname,
|
||||
qstate->qinfo.qname_len, qstate->qinfo.qtype,
|
||||
qstate->qinfo.qclass, 0);
|
||||
#ifdef USE_CACHEDB
|
||||
if(qstate->env->cachedb_enabled)
|
||||
cachedb_msg_remove(qstate);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (sq->subnet_downstream) {
|
||||
/* Client wants to see the answer, echo option back
|
||||
* and adjust the scope. */
|
||||
@@ -963,7 +995,8 @@ subnetmod_get_mem(struct module_env *env, int id)
|
||||
* The module function block
|
||||
*/
|
||||
static struct module_func_block subnetmod_block = {
|
||||
"subnetcache", &subnetmod_init, &subnetmod_deinit, &subnetmod_operate,
|
||||
"subnetcache",
|
||||
NULL, NULL, &subnetmod_init, &subnetmod_deinit, &subnetmod_operate,
|
||||
&subnetmod_inform_super, &subnetmod_clear, &subnetmod_get_mem
|
||||
};
|
||||
|
||||
|
||||
+1
-1
@@ -615,7 +615,7 @@ ipsecmod_get_mem(struct module_env* env, int id)
|
||||
*/
|
||||
static struct module_func_block ipsecmod_block = {
|
||||
"ipsecmod",
|
||||
&ipsecmod_init, &ipsecmod_deinit, &ipsecmod_operate,
|
||||
NULL, NULL, &ipsecmod_init, &ipsecmod_deinit, &ipsecmod_operate,
|
||||
&ipsecmod_inform_super, &ipsecmod_clear, &ipsecmod_get_mem
|
||||
};
|
||||
|
||||
|
||||
+162
-47
@@ -17,9 +17,19 @@
|
||||
#include "sldns/wire2str.h"
|
||||
#include "sldns/parseutil.h"
|
||||
|
||||
#ifdef HAVE_NET_PFVAR_H
|
||||
#include <fcntl.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <netinet/in.h>
|
||||
#include <net/if.h>
|
||||
#include <net/pfvar.h>
|
||||
typedef intptr_t filter_dev;
|
||||
#else
|
||||
#include <libmnl/libmnl.h>
|
||||
#include <linux/netfilter/nfnetlink.h>
|
||||
#include <linux/netfilter/ipset/ip_set.h>
|
||||
typedef struct mnl_socket * filter_dev;
|
||||
#endif
|
||||
|
||||
#define BUFF_LEN 256
|
||||
|
||||
@@ -41,24 +51,95 @@ static int error_response(struct module_qstate* qstate, int id, int rcode) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct mnl_socket * open_mnl_socket() {
|
||||
struct mnl_socket *mnl;
|
||||
#ifdef HAVE_NET_PFVAR_H
|
||||
static void * open_filter() {
|
||||
filter_dev dev;
|
||||
|
||||
mnl = mnl_socket_open(NETLINK_NETFILTER);
|
||||
if (!mnl) {
|
||||
dev = open("/dev/pf", O_RDWR);
|
||||
if (dev == -1) {
|
||||
log_err("open(\"/dev/pf\") failed: %s", strerror(errno));
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
return (void *)dev;
|
||||
}
|
||||
#else
|
||||
static void * open_filter() {
|
||||
filter_dev dev;
|
||||
|
||||
dev = mnl_socket_open(NETLINK_NETFILTER);
|
||||
if (!dev) {
|
||||
log_err("ipset: could not open netfilter.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (mnl_socket_bind(mnl, 0, MNL_SOCKET_AUTOPID) < 0) {
|
||||
mnl_socket_close(mnl);
|
||||
if (mnl_socket_bind(dev, 0, MNL_SOCKET_AUTOPID) < 0) {
|
||||
mnl_socket_close(dev);
|
||||
log_err("ipset: could not bind netfilter.");
|
||||
return NULL;
|
||||
}
|
||||
return mnl;
|
||||
return (void *)dev;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int add_to_ipset(struct mnl_socket *mnl, const char *setname, const void *ipaddr, int af) {
|
||||
#ifdef HAVE_NET_PFVAR_H
|
||||
static int add_to_ipset(filter_dev dev, const char *setname, const void *ipaddr, int af) {
|
||||
struct pfioc_table io;
|
||||
struct pfr_addr addr;
|
||||
const char *p;
|
||||
int i;
|
||||
|
||||
bzero(&io, sizeof(io));
|
||||
bzero(&addr, sizeof(addr));
|
||||
|
||||
p = strrchr(setname, '/');
|
||||
if (p) {
|
||||
i = p - setname;
|
||||
if (i >= PATH_MAX) {
|
||||
errno = ENAMETOOLONG;
|
||||
return -1;
|
||||
}
|
||||
memcpy(io.pfrio_table.pfrt_anchor, setname, i);
|
||||
if (i < PATH_MAX)
|
||||
io.pfrio_table.pfrt_anchor[i] = '\0';
|
||||
p++;
|
||||
}
|
||||
else
|
||||
p = setname;
|
||||
|
||||
if (strlen(p) >= PF_TABLE_NAME_SIZE) {
|
||||
errno = ENAMETOOLONG;
|
||||
return -1;
|
||||
}
|
||||
strlcpy(io.pfrio_table.pfrt_name, p, PF_TABLE_NAME_SIZE);
|
||||
|
||||
io.pfrio_buffer = &addr;
|
||||
io.pfrio_size = 1;
|
||||
io.pfrio_esize = sizeof(addr);
|
||||
|
||||
switch (af) {
|
||||
case AF_INET:
|
||||
addr.pfra_ip4addr = *(struct in_addr *)ipaddr;
|
||||
addr.pfra_net = 32;
|
||||
break;
|
||||
case AF_INET6:
|
||||
addr.pfra_ip6addr = *(struct in6_addr *)ipaddr;
|
||||
addr.pfra_net = 128;
|
||||
break;
|
||||
default:
|
||||
errno = EAFNOSUPPORT;
|
||||
return -1;
|
||||
}
|
||||
addr.pfra_af = af;
|
||||
|
||||
if (ioctl(dev, DIOCRADDADDRS, &io) == -1) {
|
||||
log_err("ioctl failed: %s", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
static int add_to_ipset(filter_dev dev, const char *setname, const void *ipaddr, int af) {
|
||||
struct nlmsghdr *nlh;
|
||||
struct nfgenmsg *nfg;
|
||||
struct nlattr *nested[2];
|
||||
@@ -91,14 +172,15 @@ static int add_to_ipset(struct mnl_socket *mnl, const char *setname, const void
|
||||
mnl_attr_nest_end(nlh, nested[1]);
|
||||
mnl_attr_nest_end(nlh, nested[0]);
|
||||
|
||||
if (mnl_socket_sendto(mnl, nlh, nlh->nlmsg_len) < 0) {
|
||||
if (mnl_socket_sendto(dev, nlh, nlh->nlmsg_len) < 0) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
ipset_add_rrset_data(struct ipset_env *ie, struct mnl_socket *mnl,
|
||||
ipset_add_rrset_data(struct ipset_env *ie,
|
||||
struct packed_rrset_data *d, const char* setname, int af,
|
||||
const char* dname)
|
||||
{
|
||||
@@ -123,12 +205,16 @@ ipset_add_rrset_data(struct ipset_env *ie, struct mnl_socket *mnl,
|
||||
snprintf(ip, sizeof(ip), "(inet_ntop_error)");
|
||||
verbose(VERB_QUERY, "ipset: add %s to %s for %s", ip, setname, dname);
|
||||
}
|
||||
ret = add_to_ipset(mnl, setname, rr_data + 2, af);
|
||||
ret = add_to_ipset((filter_dev)ie->dev, setname, rr_data + 2, af);
|
||||
if (ret < 0) {
|
||||
log_err("ipset: could not add %s into %s", dname, setname);
|
||||
|
||||
mnl_socket_close(mnl);
|
||||
ie->mnl = NULL;
|
||||
#if HAVE_NET_PFVAR_H
|
||||
/* don't close as we might not be able to open again due to dropped privs */
|
||||
#else
|
||||
mnl_socket_close((filter_dev)ie->dev);
|
||||
ie->dev = NULL;
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -137,8 +223,8 @@ ipset_add_rrset_data(struct ipset_env *ie, struct mnl_socket *mnl,
|
||||
|
||||
static int
|
||||
ipset_check_zones_for_rrset(struct module_env *env, struct ipset_env *ie,
|
||||
struct mnl_socket *mnl, struct ub_packed_rrset_key *rrset,
|
||||
const char *qname, const int qlen, const char *setname, int af)
|
||||
struct ub_packed_rrset_key *rrset, const char *qname, int qlen,
|
||||
const char *setname, int af)
|
||||
{
|
||||
static char dname[BUFF_LEN];
|
||||
const char *ds, *qs;
|
||||
@@ -152,11 +238,20 @@ ipset_check_zones_for_rrset(struct module_env *env, struct ipset_env *ie,
|
||||
log_err("bad domain name");
|
||||
return -1;
|
||||
}
|
||||
if (dname[dlen - 1] == '.') {
|
||||
dlen--;
|
||||
}
|
||||
if (qname[qlen - 1] == '.') {
|
||||
qlen--;
|
||||
}
|
||||
|
||||
for (p = env->cfg->local_zones_ipset; p; p = p->next) {
|
||||
ds = NULL;
|
||||
qs = NULL;
|
||||
plen = strlen(p->str);
|
||||
if (p->str[plen - 1] == '.') {
|
||||
plen--;
|
||||
}
|
||||
|
||||
if (dlen == plen || (dlen > plen && dname[dlen - plen - 1] == '.' )) {
|
||||
ds = dname + (dlen - plen);
|
||||
@@ -167,8 +262,7 @@ ipset_check_zones_for_rrset(struct module_env *env, struct ipset_env *ie,
|
||||
if ((ds && strncasecmp(p->str, ds, plen) == 0)
|
||||
|| (qs && strncasecmp(p->str, qs, plen) == 0)) {
|
||||
d = (struct packed_rrset_data*)rrset->entry.data;
|
||||
ipset_add_rrset_data(ie, mnl, d, setname,
|
||||
af, dname);
|
||||
ipset_add_rrset_data(ie, d, setname, af, dname);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -178,7 +272,6 @@ ipset_check_zones_for_rrset(struct module_env *env, struct ipset_env *ie,
|
||||
static int ipset_update(struct module_env *env, struct dns_msg *return_msg,
|
||||
struct query_info qinfo, struct ipset_env *ie)
|
||||
{
|
||||
struct mnl_socket *mnl;
|
||||
size_t i;
|
||||
const char *setname;
|
||||
struct ub_packed_rrset_key *rrset;
|
||||
@@ -186,15 +279,17 @@ static int ipset_update(struct module_env *env, struct dns_msg *return_msg,
|
||||
static char qname[BUFF_LEN];
|
||||
int qlen;
|
||||
|
||||
mnl = (struct mnl_socket *)ie->mnl;
|
||||
if (!mnl) {
|
||||
#ifdef HAVE_NET_PFVAR_H
|
||||
#else
|
||||
if (!ie->dev) {
|
||||
/* retry to create mnl socket */
|
||||
mnl = open_mnl_socket();
|
||||
if (!mnl) {
|
||||
ie->dev = open_filter();
|
||||
if (!ie->dev) {
|
||||
log_warn("ipset open_filter failed");
|
||||
return -1;
|
||||
}
|
||||
ie->mnl = mnl;
|
||||
}
|
||||
#endif
|
||||
|
||||
qlen = sldns_wire2str_dname_buf(qinfo.qname, qinfo.qname_len,
|
||||
qname, BUFF_LEN);
|
||||
@@ -217,8 +312,8 @@ static int ipset_update(struct module_env *env, struct dns_msg *return_msg,
|
||||
}
|
||||
|
||||
if (setname) {
|
||||
if(ipset_check_zones_for_rrset(env, ie, mnl, rrset,
|
||||
qname, qlen, setname, af) == -1)
|
||||
if(ipset_check_zones_for_rrset(env, ie, rrset, qname,
|
||||
qlen, setname, af) == -1)
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@@ -226,7 +321,7 @@ static int ipset_update(struct module_env *env, struct dns_msg *return_msg,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ipset_init(struct module_env* env, int id) {
|
||||
int ipset_startup(struct module_env* env, int id) {
|
||||
struct ipset_env *ipset_env;
|
||||
|
||||
ipset_env = (struct ipset_env *)calloc(1, sizeof(struct ipset_env));
|
||||
@@ -237,7 +332,43 @@ int ipset_init(struct module_env* env, int id) {
|
||||
|
||||
env->modinfo[id] = (void *)ipset_env;
|
||||
|
||||
ipset_env->mnl = NULL;
|
||||
#ifdef HAVE_NET_PFVAR_H
|
||||
ipset_env->dev = open_filter();
|
||||
if (!ipset_env->dev) {
|
||||
log_err("ipset open_filter failed");
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
ipset_env->dev = NULL;
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
void ipset_destartup(struct module_env* env, int id) {
|
||||
filter_dev dev;
|
||||
struct ipset_env *ipset_env;
|
||||
|
||||
if (!env || !env->modinfo[id]) {
|
||||
return;
|
||||
}
|
||||
ipset_env = (struct ipset_env*)env->modinfo[id];
|
||||
|
||||
dev = (filter_dev)ipset_env->dev;
|
||||
if (dev) {
|
||||
#if HAVE_NET_PFVAR_H
|
||||
close(dev);
|
||||
#else
|
||||
mnl_socket_close(dev);
|
||||
#endif
|
||||
ipset_env->dev = NULL;
|
||||
}
|
||||
|
||||
free(ipset_env);
|
||||
env->modinfo[id] = NULL;
|
||||
}
|
||||
|
||||
int ipset_init(struct module_env* env, int id) {
|
||||
struct ipset_env *ipset_env = env->modinfo[id];
|
||||
|
||||
ipset_env->name_v4 = env->cfg->ipset_name_v4;
|
||||
ipset_env->name_v6 = env->cfg->ipset_name_v6;
|
||||
@@ -253,24 +384,8 @@ int ipset_init(struct module_env* env, int id) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
void ipset_deinit(struct module_env *env, int id) {
|
||||
struct mnl_socket *mnl;
|
||||
struct ipset_env *ipset_env;
|
||||
|
||||
if (!env || !env->modinfo[id]) {
|
||||
return;
|
||||
}
|
||||
|
||||
ipset_env = (struct ipset_env *)env->modinfo[id];
|
||||
|
||||
mnl = (struct mnl_socket *)ipset_env->mnl;
|
||||
if (mnl) {
|
||||
mnl_socket_close(mnl);
|
||||
ipset_env->mnl = NULL;
|
||||
}
|
||||
|
||||
free(ipset_env);
|
||||
env->modinfo[id] = NULL;
|
||||
void ipset_deinit(struct module_env *ATTR_UNUSED(env), int ATTR_UNUSED(id)) {
|
||||
/* nothing */
|
||||
}
|
||||
|
||||
static int ipset_new(struct module_qstate* qstate, int id) {
|
||||
@@ -376,8 +491,8 @@ size_t ipset_get_mem(struct module_env *env, int id) {
|
||||
*/
|
||||
static struct module_func_block ipset_block = {
|
||||
"ipset",
|
||||
&ipset_init, &ipset_deinit, &ipset_operate,
|
||||
&ipset_inform_super, &ipset_clear, &ipset_get_mem
|
||||
&ipset_startup, &ipset_destartup, &ipset_init, &ipset_deinit,
|
||||
&ipset_operate, &ipset_inform_super, &ipset_clear, &ipset_get_mem
|
||||
};
|
||||
|
||||
struct module_func_block * ipset_get_funcblock(void) {
|
||||
|
||||
+5
-1
@@ -37,7 +37,7 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
struct ipset_env {
|
||||
void* mnl;
|
||||
void* dev;
|
||||
|
||||
int v4_enabled;
|
||||
int v6_enabled;
|
||||
@@ -50,6 +50,10 @@ struct ipset_qstate {
|
||||
int dummy;
|
||||
};
|
||||
|
||||
/** Startup the ipset module */
|
||||
int ipset_startup(struct module_env* env, int id);
|
||||
/** Destartup the ipset module */
|
||||
void ipset_destartup(struct module_env* env, int id);
|
||||
/** Init the ipset module */
|
||||
int ipset_init(struct module_env* env, int id);
|
||||
/** Deinit the ipset module */
|
||||
|
||||
+93
-27
@@ -71,6 +71,7 @@ forwards_create(void)
|
||||
sizeof(struct iter_forwards));
|
||||
if(!fwd)
|
||||
return NULL;
|
||||
lock_rw_init(&fwd->lock);
|
||||
return fwd;
|
||||
}
|
||||
|
||||
@@ -100,6 +101,7 @@ forwards_delete(struct iter_forwards* fwd)
|
||||
{
|
||||
if(!fwd)
|
||||
return;
|
||||
lock_rw_destroy(&fwd->lock);
|
||||
fwd_del_tree(fwd);
|
||||
free(fwd);
|
||||
}
|
||||
@@ -332,45 +334,64 @@ make_stub_holes(struct iter_forwards* fwd, struct config_file* cfg)
|
||||
int
|
||||
forwards_apply_cfg(struct iter_forwards* fwd, struct config_file* cfg)
|
||||
{
|
||||
if(fwd->tree) {
|
||||
lock_unprotect(&fwd->lock, fwd->tree);
|
||||
}
|
||||
fwd_del_tree(fwd);
|
||||
fwd->tree = rbtree_create(fwd_cmp);
|
||||
if(!fwd->tree)
|
||||
return 0;
|
||||
lock_protect(&fwd->lock, fwd->tree, sizeof(*fwd->tree));
|
||||
|
||||
lock_rw_wrlock(&fwd->lock);
|
||||
/* read forward zones */
|
||||
if(!read_forwards(fwd, cfg))
|
||||
if(!read_forwards(fwd, cfg)) {
|
||||
lock_rw_unlock(&fwd->lock);
|
||||
return 0;
|
||||
if(!make_stub_holes(fwd, cfg))
|
||||
}
|
||||
if(!make_stub_holes(fwd, cfg)) {
|
||||
lock_rw_unlock(&fwd->lock);
|
||||
return 0;
|
||||
}
|
||||
fwd_init_parents(fwd);
|
||||
lock_rw_unlock(&fwd->lock);
|
||||
return 1;
|
||||
}
|
||||
|
||||
struct delegpt*
|
||||
forwards_find(struct iter_forwards* fwd, uint8_t* qname, uint16_t qclass)
|
||||
forwards_find(struct iter_forwards* fwd, uint8_t* qname, uint16_t qclass,
|
||||
int nolock)
|
||||
{
|
||||
rbnode_type* res = NULL;
|
||||
struct iter_forward_zone* res;
|
||||
struct iter_forward_zone key;
|
||||
int has_dp;
|
||||
key.node.key = &key;
|
||||
key.dclass = qclass;
|
||||
key.name = qname;
|
||||
key.namelabs = dname_count_size_labels(qname, &key.namelen);
|
||||
res = rbtree_search(fwd->tree, &key);
|
||||
if(res) return ((struct iter_forward_zone*)res)->dp;
|
||||
return NULL;
|
||||
/* lock_() calls are macros that could be nothing, surround in {} */
|
||||
if(!nolock) { lock_rw_rdlock(&fwd->lock); }
|
||||
res = (struct iter_forward_zone*)rbtree_search(fwd->tree, &key);
|
||||
has_dp = res && res->dp;
|
||||
if(!has_dp && !nolock) { lock_rw_unlock(&fwd->lock); }
|
||||
return has_dp?res->dp:NULL;
|
||||
}
|
||||
|
||||
struct delegpt*
|
||||
forwards_lookup(struct iter_forwards* fwd, uint8_t* qname, uint16_t qclass)
|
||||
forwards_lookup(struct iter_forwards* fwd, uint8_t* qname, uint16_t qclass,
|
||||
int nolock)
|
||||
{
|
||||
/* lookup the forward zone in the tree */
|
||||
rbnode_type* res = NULL;
|
||||
struct iter_forward_zone *result;
|
||||
struct iter_forward_zone key;
|
||||
int has_dp;
|
||||
key.node.key = &key;
|
||||
key.dclass = qclass;
|
||||
key.name = qname;
|
||||
key.namelabs = dname_count_size_labels(qname, &key.namelen);
|
||||
/* lock_() calls are macros that could be nothing, surround in {} */
|
||||
if(!nolock) { lock_rw_rdlock(&fwd->lock); }
|
||||
if(rbtree_find_less_equal(fwd->tree, &key, &res)) {
|
||||
/* exact */
|
||||
result = (struct iter_forward_zone*)res;
|
||||
@@ -378,8 +399,10 @@ forwards_lookup(struct iter_forwards* fwd, uint8_t* qname, uint16_t qclass)
|
||||
/* smaller element (or no element) */
|
||||
int m;
|
||||
result = (struct iter_forward_zone*)res;
|
||||
if(!result || result->dclass != qclass)
|
||||
if(!result || result->dclass != qclass) {
|
||||
if(!nolock) { lock_rw_unlock(&fwd->lock); }
|
||||
return NULL;
|
||||
}
|
||||
/* count number of labels matched */
|
||||
(void)dname_lab_cmp(result->name, result->namelabs, key.name,
|
||||
key.namelabs, &m);
|
||||
@@ -389,20 +412,22 @@ forwards_lookup(struct iter_forwards* fwd, uint8_t* qname, uint16_t qclass)
|
||||
result = result->parent;
|
||||
}
|
||||
}
|
||||
if(result)
|
||||
return result->dp;
|
||||
return NULL;
|
||||
has_dp = result && result->dp;
|
||||
if(!has_dp && !nolock) { lock_rw_unlock(&fwd->lock); }
|
||||
return has_dp?result->dp:NULL;
|
||||
}
|
||||
|
||||
struct delegpt*
|
||||
forwards_lookup_root(struct iter_forwards* fwd, uint16_t qclass)
|
||||
forwards_lookup_root(struct iter_forwards* fwd, uint16_t qclass, int nolock)
|
||||
{
|
||||
uint8_t root = 0;
|
||||
return forwards_lookup(fwd, &root, qclass);
|
||||
return forwards_lookup(fwd, &root, qclass, nolock);
|
||||
}
|
||||
|
||||
int
|
||||
forwards_next_root(struct iter_forwards* fwd, uint16_t* dclass)
|
||||
/* Finds next root item in forwards lookup tree.
|
||||
* Caller needs to handle locking of the forwards structure. */
|
||||
static int
|
||||
next_root_locked(struct iter_forwards* fwd, uint16_t* dclass)
|
||||
{
|
||||
struct iter_forward_zone key;
|
||||
rbnode_type* n;
|
||||
@@ -419,7 +444,7 @@ forwards_next_root(struct iter_forwards* fwd, uint16_t* dclass)
|
||||
}
|
||||
/* root not first item? search for higher items */
|
||||
*dclass = p->dclass + 1;
|
||||
return forwards_next_root(fwd, dclass);
|
||||
return next_root_locked(fwd, dclass);
|
||||
}
|
||||
/* find class n in tree, we may get a direct hit, or if we don't
|
||||
* this is the last item of the previous class so rbtree_next() takes
|
||||
@@ -447,10 +472,21 @@ forwards_next_root(struct iter_forwards* fwd, uint16_t* dclass)
|
||||
}
|
||||
/* not a root node, return next higher item */
|
||||
*dclass = p->dclass+1;
|
||||
return forwards_next_root(fwd, dclass);
|
||||
return next_root_locked(fwd, dclass);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
forwards_next_root(struct iter_forwards* fwd, uint16_t* dclass, int nolock)
|
||||
{
|
||||
int ret;
|
||||
/* lock_() calls are macros that could be nothing, surround in {} */
|
||||
if(!nolock) { lock_rw_rdlock(&fwd->lock); }
|
||||
ret = next_root_locked(fwd, dclass);
|
||||
if(!nolock) { lock_rw_unlock(&fwd->lock); }
|
||||
return ret;
|
||||
}
|
||||
|
||||
size_t
|
||||
forwards_get_mem(struct iter_forwards* fwd)
|
||||
{
|
||||
@@ -458,10 +494,12 @@ forwards_get_mem(struct iter_forwards* fwd)
|
||||
size_t s;
|
||||
if(!fwd)
|
||||
return 0;
|
||||
lock_rw_rdlock(&fwd->lock);
|
||||
s = sizeof(*fwd) + sizeof(*fwd->tree);
|
||||
RBTREE_FOR(p, struct iter_forward_zone*, fwd->tree) {
|
||||
s += sizeof(*p) + p->namelen + delegpt_get_mem(p->dp);
|
||||
}
|
||||
lock_rw_unlock(&fwd->lock);
|
||||
return s;
|
||||
}
|
||||
|
||||
@@ -477,50 +515,78 @@ fwd_zone_find(struct iter_forwards* fwd, uint16_t c, uint8_t* nm)
|
||||
}
|
||||
|
||||
int
|
||||
forwards_add_zone(struct iter_forwards* fwd, uint16_t c, struct delegpt* dp)
|
||||
forwards_add_zone(struct iter_forwards* fwd, uint16_t c, struct delegpt* dp,
|
||||
int nolock)
|
||||
{
|
||||
struct iter_forward_zone *z;
|
||||
/* lock_() calls are macros that could be nothing, surround in {} */
|
||||
if(!nolock) { lock_rw_wrlock(&fwd->lock); }
|
||||
if((z=fwd_zone_find(fwd, c, dp->name)) != NULL) {
|
||||
(void)rbtree_delete(fwd->tree, &z->node);
|
||||
fwd_zone_free(z);
|
||||
}
|
||||
if(!forwards_insert(fwd, c, dp))
|
||||
if(!forwards_insert(fwd, c, dp)) {
|
||||
if(!nolock) { lock_rw_unlock(&fwd->lock); }
|
||||
return 0;
|
||||
}
|
||||
fwd_init_parents(fwd);
|
||||
if(!nolock) { lock_rw_unlock(&fwd->lock); }
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
forwards_delete_zone(struct iter_forwards* fwd, uint16_t c, uint8_t* nm)
|
||||
forwards_delete_zone(struct iter_forwards* fwd, uint16_t c, uint8_t* nm,
|
||||
int nolock)
|
||||
{
|
||||
struct iter_forward_zone *z;
|
||||
if(!(z=fwd_zone_find(fwd, c, nm)))
|
||||
/* lock_() calls are macros that could be nothing, surround in {} */
|
||||
if(!nolock) { lock_rw_wrlock(&fwd->lock); }
|
||||
if(!(z=fwd_zone_find(fwd, c, nm))) {
|
||||
if(!nolock) { lock_rw_unlock(&fwd->lock); }
|
||||
return; /* nothing to do */
|
||||
}
|
||||
(void)rbtree_delete(fwd->tree, &z->node);
|
||||
fwd_zone_free(z);
|
||||
fwd_init_parents(fwd);
|
||||
if(!nolock) { lock_rw_unlock(&fwd->lock); }
|
||||
}
|
||||
|
||||
int
|
||||
forwards_add_stub_hole(struct iter_forwards* fwd, uint16_t c, uint8_t* nm)
|
||||
forwards_add_stub_hole(struct iter_forwards* fwd, uint16_t c, uint8_t* nm,
|
||||
int nolock)
|
||||
{
|
||||
/* lock_() calls are macros that could be nothing, surround in {} */
|
||||
if(!nolock) { lock_rw_wrlock(&fwd->lock); }
|
||||
if(fwd_zone_find(fwd, c, nm) != NULL) {
|
||||
if(!nolock) { lock_rw_unlock(&fwd->lock); }
|
||||
return 1; /* already a stub zone there */
|
||||
}
|
||||
if(!fwd_add_stub_hole(fwd, c, nm)) {
|
||||
if(!nolock) { lock_rw_unlock(&fwd->lock); }
|
||||
return 0;
|
||||
}
|
||||
fwd_init_parents(fwd);
|
||||
if(!nolock) { lock_rw_unlock(&fwd->lock); }
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
forwards_delete_stub_hole(struct iter_forwards* fwd, uint16_t c, uint8_t* nm)
|
||||
forwards_delete_stub_hole(struct iter_forwards* fwd, uint16_t c,
|
||||
uint8_t* nm, int nolock)
|
||||
{
|
||||
struct iter_forward_zone *z;
|
||||
if(!(z=fwd_zone_find(fwd, c, nm)))
|
||||
/* lock_() calls are macros that could be nothing, surround in {} */
|
||||
if(!nolock) { lock_rw_wrlock(&fwd->lock); }
|
||||
if(!(z=fwd_zone_find(fwd, c, nm))) {
|
||||
if(!nolock) { lock_rw_unlock(&fwd->lock); }
|
||||
return; /* nothing to do */
|
||||
if(z->dp != NULL)
|
||||
}
|
||||
if(z->dp != NULL) {
|
||||
if(!nolock) { lock_rw_unlock(&fwd->lock); }
|
||||
return; /* not a stub hole */
|
||||
}
|
||||
(void)rbtree_delete(fwd->tree, &z->node);
|
||||
fwd_zone_free(z);
|
||||
fwd_init_parents(fwd);
|
||||
if(!nolock) { lock_rw_unlock(&fwd->lock); }
|
||||
}
|
||||
|
||||
|
||||
+49
-11
@@ -43,6 +43,7 @@
|
||||
#ifndef ITERATOR_ITER_FWD_H
|
||||
#define ITERATOR_ITER_FWD_H
|
||||
#include "util/rbtree.h"
|
||||
#include "util/locks.h"
|
||||
struct config_file;
|
||||
struct delegpt;
|
||||
|
||||
@@ -50,6 +51,11 @@ struct delegpt;
|
||||
* Iterator forward zones structure
|
||||
*/
|
||||
struct iter_forwards {
|
||||
/** lock on the forwards tree.
|
||||
* When grabbing both this lock and the anchors.lock, this lock
|
||||
* is grabbed first. When grabbing both this lock and the hints.lock
|
||||
* this lock is grabbed first. */
|
||||
lock_rw_type lock;
|
||||
/**
|
||||
* Zones are stored in this tree. Sort order is specially chosen.
|
||||
* first sorted on qclass. Then on dname in nsec-like order, so that
|
||||
@@ -106,47 +112,65 @@ int forwards_apply_cfg(struct iter_forwards* fwd, struct config_file* cfg);
|
||||
|
||||
/**
|
||||
* Find forward zone exactly by name
|
||||
* The return value is contents of the forwards structure.
|
||||
* Caller should lock and unlock a readlock on the forwards structure if nolock
|
||||
* is set.
|
||||
* Otherwise caller should unlock the readlock on the forwards structure if a
|
||||
* value was returned.
|
||||
* @param fwd: forward storage.
|
||||
* @param qname: The qname of the query.
|
||||
* @param qclass: The qclass of the query.
|
||||
* @param nolock: Skip locking, locking is handled by the caller.
|
||||
* @return: A delegation point or null.
|
||||
*/
|
||||
struct delegpt* forwards_find(struct iter_forwards* fwd, uint8_t* qname,
|
||||
uint16_t qclass);
|
||||
uint16_t qclass, int nolock);
|
||||
|
||||
/**
|
||||
* Find forward zone information
|
||||
* For this qname/qclass find forward zone information, returns delegation
|
||||
* point with server names and addresses, or NULL if no forwarding is needed.
|
||||
* The return value is contents of the forwards structure.
|
||||
* Caller should lock and unlock a readlock on the forwards structure if nolock
|
||||
* is set.
|
||||
* Otherwise caller should unlock the readlock on the forwards structure if a
|
||||
* value was returned.
|
||||
*
|
||||
* @param fwd: forward storage.
|
||||
* @param qname: The qname of the query.
|
||||
* @param qclass: The qclass of the query.
|
||||
* @param nolock: Skip locking, locking is handled by the caller.
|
||||
* @return: A delegation point if the query has to be forwarded to that list,
|
||||
* otherwise null.
|
||||
*/
|
||||
struct delegpt* forwards_lookup(struct iter_forwards* fwd,
|
||||
uint8_t* qname, uint16_t qclass);
|
||||
struct delegpt* forwards_lookup(struct iter_forwards* fwd,
|
||||
uint8_t* qname, uint16_t qclass, int nolock);
|
||||
|
||||
/**
|
||||
* Same as forwards_lookup, but for the root only
|
||||
* @param fwd: forward storage.
|
||||
* @param qclass: The qclass of the query.
|
||||
* @param nolock: Skip locking, locking is handled by the caller.
|
||||
* @return: A delegation point if root forward exists, otherwise null.
|
||||
*/
|
||||
struct delegpt* forwards_lookup_root(struct iter_forwards* fwd,
|
||||
uint16_t qclass);
|
||||
struct delegpt* forwards_lookup_root(struct iter_forwards* fwd,
|
||||
uint16_t qclass, int nolock);
|
||||
|
||||
/**
|
||||
* Find next root item in forwards lookup tree.
|
||||
* Handles its own locking unless nolock is set. In that case the caller
|
||||
* should lock and unlock a readlock on the forwards structure.
|
||||
* @param fwd: the forward storage
|
||||
* @param qclass: class to look at next, or higher.
|
||||
* @param nolock: Skip locking, locking is handled by the caller.
|
||||
* @return false if none found, or if true stored in qclass.
|
||||
*/
|
||||
int forwards_next_root(struct iter_forwards* fwd, uint16_t* qclass);
|
||||
int forwards_next_root(struct iter_forwards* fwd, uint16_t* qclass,
|
||||
int nolock);
|
||||
|
||||
/**
|
||||
* Get memory in use by forward storage
|
||||
* Locks and unlocks the structure.
|
||||
* @param fwd: forward storage.
|
||||
* @return bytes in use
|
||||
*/
|
||||
@@ -158,42 +182,56 @@ int fwd_cmp(const void* k1, const void* k2);
|
||||
/**
|
||||
* Add zone to forward structure. For external use since it recalcs
|
||||
* the tree parents.
|
||||
* Handles its own locking unless nolock is set. In that case the caller
|
||||
* should lock and unlock a writelock on the forwards structure.
|
||||
* @param fwd: the forward data structure
|
||||
* @param c: class of zone
|
||||
* @param dp: delegation point with name and target nameservers for new
|
||||
* forward zone. malloced.
|
||||
* @param nolock: Skip locking, locking is handled by the caller.
|
||||
* @return false on failure (out of memory);
|
||||
*/
|
||||
int forwards_add_zone(struct iter_forwards* fwd, uint16_t c,
|
||||
struct delegpt* dp);
|
||||
int forwards_add_zone(struct iter_forwards* fwd, uint16_t c,
|
||||
struct delegpt* dp, int nolock);
|
||||
|
||||
/**
|
||||
* Remove zone from forward structure. For external use since it
|
||||
* recalcs the tree parents.
|
||||
* Handles its own locking unless nolock is set. In that case the caller
|
||||
* should lock and unlock a writelock on the forwards structure.
|
||||
* @param fwd: the forward data structure
|
||||
* @param c: class of zone
|
||||
* @param nm: name of zone (in uncompressed wireformat).
|
||||
* @param nolock: Skip locking, locking is handled by the caller.
|
||||
*/
|
||||
void forwards_delete_zone(struct iter_forwards* fwd, uint16_t c, uint8_t* nm);
|
||||
void forwards_delete_zone(struct iter_forwards* fwd, uint16_t c,
|
||||
uint8_t* nm, int nolock);
|
||||
|
||||
/**
|
||||
* Add stub hole (empty entry in forward table, that makes resolution skip
|
||||
* a forward-zone because the stub zone should override the forward zone).
|
||||
* Does not add one if not necessary.
|
||||
* Handles its own locking unless nolock is set. In that case the caller
|
||||
* should lock and unlock a writelock on the forwards structure.
|
||||
* @param fwd: the forward data structure
|
||||
* @param c: class of zone
|
||||
* @param nm: name of zone (in uncompressed wireformat).
|
||||
* @param nolock: Skip locking, locking is handled by the caller.
|
||||
* @return false on failure (out of memory);
|
||||
*/
|
||||
int forwards_add_stub_hole(struct iter_forwards* fwd, uint16_t c, uint8_t* nm);
|
||||
int forwards_add_stub_hole(struct iter_forwards* fwd, uint16_t c,
|
||||
uint8_t* nm, int nolock);
|
||||
|
||||
/**
|
||||
* Remove stub hole, if one exists.
|
||||
* Handles its own locking unless nolock is set. In that case the caller
|
||||
* should lock and unlock a writelock on the forwards structure.
|
||||
* @param fwd: the forward data structure
|
||||
* @param c: class of zone
|
||||
* @param nm: name of zone (in uncompressed wireformat).
|
||||
* @param nolock: Skip locking, locking is handled by the caller.
|
||||
*/
|
||||
void forwards_delete_stub_hole(struct iter_forwards* fwd, uint16_t c,
|
||||
uint8_t* nm);
|
||||
uint8_t* nm, int nolock);
|
||||
|
||||
#endif /* ITERATOR_ITER_FWD_H */
|
||||
|
||||
+76
-26
@@ -57,6 +57,8 @@ hints_create(void)
|
||||
sizeof(struct iter_hints));
|
||||
if(!hints)
|
||||
return NULL;
|
||||
lock_rw_init(&hints->lock);
|
||||
lock_protect(&hints->lock, &hints->tree, sizeof(hints->tree));
|
||||
return hints;
|
||||
}
|
||||
|
||||
@@ -83,6 +85,7 @@ hints_delete(struct iter_hints* hints)
|
||||
{
|
||||
if(!hints)
|
||||
return;
|
||||
lock_rw_destroy(&hints->lock);
|
||||
hints_del_tree(hints);
|
||||
free(hints);
|
||||
}
|
||||
@@ -129,7 +132,7 @@ compile_time_root_prime(int do_ip4, int do_ip6)
|
||||
dp->has_parent_side_NS = 1;
|
||||
if(do_ip4) {
|
||||
if(!ah(dp, "A.ROOT-SERVERS.NET.", "198.41.0.4")) goto failed;
|
||||
if(!ah(dp, "B.ROOT-SERVERS.NET.", "199.9.14.201")) goto failed;
|
||||
if(!ah(dp, "B.ROOT-SERVERS.NET.", "170.247.170.2")) goto failed;
|
||||
if(!ah(dp, "C.ROOT-SERVERS.NET.", "192.33.4.12")) goto failed;
|
||||
if(!ah(dp, "D.ROOT-SERVERS.NET.", "199.7.91.13")) goto failed;
|
||||
if(!ah(dp, "E.ROOT-SERVERS.NET.", "192.203.230.10")) goto failed;
|
||||
@@ -144,7 +147,7 @@ compile_time_root_prime(int do_ip4, int do_ip6)
|
||||
}
|
||||
if(do_ip6) {
|
||||
if(!ah(dp, "A.ROOT-SERVERS.NET.", "2001:503:ba3e::2:30")) goto failed;
|
||||
if(!ah(dp, "B.ROOT-SERVERS.NET.", "2001:500:200::b")) goto failed;
|
||||
if(!ah(dp, "B.ROOT-SERVERS.NET.", "2801:1b8:10::b")) goto failed;
|
||||
if(!ah(dp, "C.ROOT-SERVERS.NET.", "2001:500:2::c")) goto failed;
|
||||
if(!ah(dp, "D.ROOT-SERVERS.NET.", "2001:500:2d::d")) goto failed;
|
||||
if(!ah(dp, "E.ROOT-SERVERS.NET.", "2001:500:a8::e")) goto failed;
|
||||
@@ -438,47 +441,70 @@ read_root_hints_list(struct iter_hints* hints, struct config_file* cfg)
|
||||
int
|
||||
hints_apply_cfg(struct iter_hints* hints, struct config_file* cfg)
|
||||
{
|
||||
int nolock = 1;
|
||||
lock_rw_wrlock(&hints->lock);
|
||||
hints_del_tree(hints);
|
||||
name_tree_init(&hints->tree);
|
||||
|
||||
|
||||
/* read root hints */
|
||||
if(!read_root_hints_list(hints, cfg))
|
||||
if(!read_root_hints_list(hints, cfg)) {
|
||||
lock_rw_unlock(&hints->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* read stub hints */
|
||||
if(!read_stubs(hints, cfg))
|
||||
if(!read_stubs(hints, cfg)) {
|
||||
lock_rw_unlock(&hints->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* use fallback compiletime root hints */
|
||||
if(!hints_lookup_root(hints, LDNS_RR_CLASS_IN)) {
|
||||
if(!hints_find_root(hints, LDNS_RR_CLASS_IN, nolock)) {
|
||||
struct delegpt* dp = compile_time_root_prime(cfg->do_ip4,
|
||||
cfg->do_ip6);
|
||||
verbose(VERB_ALGO, "no config, using builtin root hints.");
|
||||
if(!dp)
|
||||
if(!dp) {
|
||||
lock_rw_unlock(&hints->lock);
|
||||
return 0;
|
||||
if(!hints_insert(hints, LDNS_RR_CLASS_IN, dp, 0))
|
||||
}
|
||||
if(!hints_insert(hints, LDNS_RR_CLASS_IN, dp, 0)) {
|
||||
lock_rw_unlock(&hints->lock);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
name_tree_init_parents(&hints->tree);
|
||||
lock_rw_unlock(&hints->lock);
|
||||
return 1;
|
||||
}
|
||||
|
||||
struct delegpt*
|
||||
hints_lookup_root(struct iter_hints* hints, uint16_t qclass)
|
||||
struct delegpt*
|
||||
hints_find(struct iter_hints* hints, uint8_t* qname, uint16_t qclass,
|
||||
int nolock)
|
||||
{
|
||||
struct iter_hints_stub *stub;
|
||||
size_t len;
|
||||
int has_dp;
|
||||
int labs = dname_count_size_labels(qname, &len);
|
||||
/* lock_() calls are macros that could be nothing, surround in {} */
|
||||
if(!nolock) { lock_rw_rdlock(&hints->lock); }
|
||||
stub = (struct iter_hints_stub*)name_tree_find(&hints->tree,
|
||||
qname, len, labs, qclass);
|
||||
has_dp = stub && stub->dp;
|
||||
if(!has_dp && !nolock) { lock_rw_unlock(&hints->lock); }
|
||||
return has_dp?stub->dp:NULL;
|
||||
}
|
||||
|
||||
struct delegpt*
|
||||
hints_find_root(struct iter_hints* hints, uint16_t qclass, int nolock)
|
||||
{
|
||||
uint8_t rootlab = 0;
|
||||
struct iter_hints_stub *stub;
|
||||
stub = (struct iter_hints_stub*)name_tree_find(&hints->tree,
|
||||
&rootlab, 1, 1, qclass);
|
||||
if(!stub)
|
||||
return NULL;
|
||||
return stub->dp;
|
||||
return hints_find(hints, &rootlab, qclass, nolock);
|
||||
}
|
||||
|
||||
struct iter_hints_stub*
|
||||
hints_lookup_stub(struct iter_hints* hints, uint8_t* qname,
|
||||
uint16_t qclass, struct delegpt* cache_dp)
|
||||
hints_lookup_stub(struct iter_hints* hints, uint8_t* qname,
|
||||
uint16_t qclass, struct delegpt* cache_dp, int nolock)
|
||||
{
|
||||
size_t len;
|
||||
int labs;
|
||||
@@ -486,14 +512,20 @@ hints_lookup_stub(struct iter_hints* hints, uint8_t* qname,
|
||||
|
||||
/* first lookup the stub */
|
||||
labs = dname_count_size_labels(qname, &len);
|
||||
/* lock_() calls are macros that could be nothing, surround in {} */
|
||||
if(!nolock) { lock_rw_rdlock(&hints->lock); }
|
||||
r = (struct iter_hints_stub*)name_tree_lookup(&hints->tree, qname,
|
||||
len, labs, qclass);
|
||||
if(!r) return NULL;
|
||||
if(!r) {
|
||||
if(!nolock) { lock_rw_unlock(&hints->lock); }
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* If there is no cache (root prime situation) */
|
||||
if(cache_dp == NULL) {
|
||||
if(r->dp->namelabs != 1)
|
||||
return r; /* no cache dp, use any non-root stub */
|
||||
if(!nolock) { lock_rw_unlock(&hints->lock); }
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -510,12 +542,18 @@ hints_lookup_stub(struct iter_hints* hints, uint8_t* qname,
|
||||
if(dname_strict_subdomain(r->dp->name, r->dp->namelabs,
|
||||
cache_dp->name, cache_dp->namelabs))
|
||||
return r; /* need to prime this stub */
|
||||
if(!nolock) { lock_rw_unlock(&hints->lock); }
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int hints_next_root(struct iter_hints* hints, uint16_t* qclass)
|
||||
int hints_next_root(struct iter_hints* hints, uint16_t* qclass, int nolock)
|
||||
{
|
||||
return name_tree_next_root(&hints->tree, qclass);
|
||||
int ret;
|
||||
/* lock_() calls are macros that could be nothing, surround in {} */
|
||||
if(!nolock) { lock_rw_rdlock(&hints->lock); }
|
||||
ret = name_tree_next_root(&hints->tree, qclass);
|
||||
if(!nolock) { lock_rw_unlock(&hints->lock); }
|
||||
return ret;
|
||||
}
|
||||
|
||||
size_t
|
||||
@@ -524,40 +562,52 @@ hints_get_mem(struct iter_hints* hints)
|
||||
size_t s;
|
||||
struct iter_hints_stub* p;
|
||||
if(!hints) return 0;
|
||||
lock_rw_rdlock(&hints->lock);
|
||||
s = sizeof(*hints);
|
||||
RBTREE_FOR(p, struct iter_hints_stub*, &hints->tree) {
|
||||
s += sizeof(*p) + delegpt_get_mem(p->dp);
|
||||
}
|
||||
lock_rw_unlock(&hints->lock);
|
||||
return s;
|
||||
}
|
||||
|
||||
int
|
||||
hints_add_stub(struct iter_hints* hints, uint16_t c, struct delegpt* dp,
|
||||
int noprime)
|
||||
int noprime, int nolock)
|
||||
{
|
||||
struct iter_hints_stub *z;
|
||||
/* lock_() calls are macros that could be nothing, surround in {} */
|
||||
if(!nolock) { lock_rw_wrlock(&hints->lock); }
|
||||
if((z=(struct iter_hints_stub*)name_tree_find(&hints->tree,
|
||||
dp->name, dp->namelen, dp->namelabs, c)) != NULL) {
|
||||
(void)rbtree_delete(&hints->tree, &z->node);
|
||||
hints_stub_free(z);
|
||||
}
|
||||
if(!hints_insert(hints, c, dp, noprime))
|
||||
if(!hints_insert(hints, c, dp, noprime)) {
|
||||
if(!nolock) { lock_rw_unlock(&hints->lock); }
|
||||
return 0;
|
||||
}
|
||||
name_tree_init_parents(&hints->tree);
|
||||
if(!nolock) { lock_rw_unlock(&hints->lock); }
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
hints_delete_stub(struct iter_hints* hints, uint16_t c, uint8_t* nm)
|
||||
hints_delete_stub(struct iter_hints* hints, uint16_t c, uint8_t* nm,
|
||||
int nolock)
|
||||
{
|
||||
struct iter_hints_stub *z;
|
||||
size_t len;
|
||||
int labs = dname_count_size_labels(nm, &len);
|
||||
/* lock_() calls are macros that could be nothing, surround in {} */
|
||||
if(!nolock) { lock_rw_wrlock(&hints->lock); }
|
||||
if(!(z=(struct iter_hints_stub*)name_tree_find(&hints->tree,
|
||||
nm, len, labs, c)))
|
||||
nm, len, labs, c))) {
|
||||
if(!nolock) { lock_rw_unlock(&hints->lock); }
|
||||
return; /* nothing to do */
|
||||
}
|
||||
(void)rbtree_delete(&hints->tree, &z->node);
|
||||
hints_stub_free(z);
|
||||
name_tree_init_parents(&hints->tree);
|
||||
if(!nolock) { lock_rw_unlock(&hints->lock); }
|
||||
}
|
||||
|
||||
|
||||
+47
-7
@@ -43,6 +43,7 @@
|
||||
#ifndef ITERATOR_ITER_HINTS_H
|
||||
#define ITERATOR_ITER_HINTS_H
|
||||
#include "util/storage/dnstree.h"
|
||||
#include "util/locks.h"
|
||||
struct iter_env;
|
||||
struct config_file;
|
||||
struct delegpt;
|
||||
@@ -51,6 +52,10 @@ struct delegpt;
|
||||
* Iterator hints structure
|
||||
*/
|
||||
struct iter_hints {
|
||||
/** lock on the forwards tree.
|
||||
* When grabbing both this lock and the anchors.lock, this lock
|
||||
* is grabbed first. */
|
||||
lock_rw_type lock;
|
||||
/**
|
||||
* Hints are stored in this tree. Sort order is specially chosen.
|
||||
* first sorted on qclass. Then on dname in nsec-like order, so that
|
||||
@@ -95,42 +100,70 @@ void hints_delete(struct iter_hints* hints);
|
||||
int hints_apply_cfg(struct iter_hints* hints, struct config_file* cfg);
|
||||
|
||||
/**
|
||||
* Find root hints for the given class.
|
||||
* Find hints for the given class.
|
||||
* The return value is contents of the hints structure.
|
||||
* Caller should lock and unlock a readlock on the hints structure if nolock
|
||||
* is set.
|
||||
* Otherwise caller should unlock the readlock on the hints structure if a
|
||||
* value was returned.
|
||||
* @param hints: hint storage.
|
||||
* @param qname: the qname that generated the delegation point.
|
||||
* @param qclass: class for which root hints are requested. host order.
|
||||
* @param nolock: Skip locking, locking is handled by the caller.
|
||||
* @return: NULL if no hints, or a ptr to stored hints.
|
||||
*/
|
||||
struct delegpt* hints_lookup_root(struct iter_hints* hints, uint16_t qclass);
|
||||
struct delegpt* hints_find(struct iter_hints* hints, uint8_t* qname,
|
||||
uint16_t qclass, int nolock);
|
||||
|
||||
/**
|
||||
* Same as hints_lookup, but for the root only.
|
||||
* @param hints: hint storage.
|
||||
* @param qclass: class for which root hints are requested. host order.
|
||||
* @param nolock: Skip locking, locking is handled by the caller.
|
||||
* @return: NULL if no hints, or a ptr to stored hints.
|
||||
*/
|
||||
struct delegpt* hints_find_root(struct iter_hints* hints,
|
||||
uint16_t qclass, int nolock);
|
||||
|
||||
/**
|
||||
* Find next root hints (to cycle through all root hints).
|
||||
* Handles its own locking unless nolock is set. In that case the caller
|
||||
* should lock and unlock a readlock on the hints structure.
|
||||
* @param hints: hint storage
|
||||
* @param qclass: class for which root hints are sought.
|
||||
* 0 means give the first available root hints class.
|
||||
* x means, give class x or a higher class if any.
|
||||
* returns the found class in this variable.
|
||||
* @param nolock: Skip locking, locking is handled by the caller.
|
||||
* @return true if a root hint class is found.
|
||||
* false if not root hint class is found (qclass may have been changed).
|
||||
*/
|
||||
int hints_next_root(struct iter_hints* hints, uint16_t* qclass);
|
||||
int hints_next_root(struct iter_hints* hints, uint16_t* qclass, int nolock);
|
||||
|
||||
/**
|
||||
* Given a qname/qclass combination, and the delegation point from the cache
|
||||
* for this qname/qclass, determine if this combination indicates that a
|
||||
* stub hint exists and must be primed.
|
||||
* The return value is contents of the hints structure.
|
||||
* Caller should lock and unlock a readlock on the hints structure if nolock
|
||||
* is set.
|
||||
* Otherwise caller should unlock the readlock on the hints structure if a
|
||||
* value was returned.
|
||||
*
|
||||
* @param hints: hint storage.
|
||||
* @param qname: The qname that generated the delegation point.
|
||||
* @param qclass: The qclass that generated the delegation point.
|
||||
* @param dp: The cache generated delegation point.
|
||||
* @param nolock: Skip locking, locking is handled by the caller.
|
||||
* @return: A priming delegation point if there is a stub hint that must
|
||||
* be primed, otherwise null.
|
||||
*/
|
||||
struct iter_hints_stub* hints_lookup_stub(struct iter_hints* hints,
|
||||
uint8_t* qname, uint16_t qclass, struct delegpt* dp);
|
||||
struct iter_hints_stub* hints_lookup_stub(struct iter_hints* hints,
|
||||
uint8_t* qname, uint16_t qclass, struct delegpt* dp, int nolock);
|
||||
|
||||
/**
|
||||
* Get memory in use by hints
|
||||
* Locks and unlocks the structure.
|
||||
* @param hints: hint storage.
|
||||
* @return bytes in use
|
||||
*/
|
||||
@@ -139,23 +172,30 @@ size_t hints_get_mem(struct iter_hints* hints);
|
||||
/**
|
||||
* Add stub to hints structure. For external use since it recalcs
|
||||
* the tree parents.
|
||||
* Handles its own locking unless nolock is set. In that case the caller
|
||||
* should lock and unlock a writelock on the hints structure.
|
||||
* @param hints: the hints data structure
|
||||
* @param c: class of zone
|
||||
* @param dp: delegation point with name and target nameservers for new
|
||||
* hints stub. malloced.
|
||||
* @param noprime: set noprime option to true or false on new hint stub.
|
||||
* @param nolock: Skip locking, locking is handled by the caller.
|
||||
* @return false on failure (out of memory);
|
||||
*/
|
||||
int hints_add_stub(struct iter_hints* hints, uint16_t c, struct delegpt* dp,
|
||||
int noprime);
|
||||
int noprime, int nolock);
|
||||
|
||||
/**
|
||||
* Remove stub from hints structure. For external use since it
|
||||
* recalcs the tree parents.
|
||||
* Handles its own locking unless nolock is set. In that case the caller
|
||||
* should lock and unlock a writelock on the hints structure.
|
||||
* @param hints: the hints data structure
|
||||
* @param c: class of stub zone
|
||||
* @param nm: name of stub zone (in uncompressed wireformat).
|
||||
* @param nolock: Skip locking, locking is handled by the caller.
|
||||
*/
|
||||
void hints_delete_stub(struct iter_hints* hints, uint16_t c, uint8_t* nm);
|
||||
void hints_delete_stub(struct iter_hints* hints, uint16_t c,
|
||||
uint8_t* nm, int nolock);
|
||||
|
||||
#endif /* ITERATOR_ITER_HINTS_H */
|
||||
|
||||
+115
-1
@@ -283,7 +283,8 @@ synth_cname_rrset(uint8_t** sname, size_t* snamelen, uint8_t* alias,
|
||||
sizeof(uint32_t)+sizeof(uint16_t)+aliaslen);
|
||||
if(!cn->rr_first->ttl_data)
|
||||
return NULL;
|
||||
sldns_write_uint32(cn->rr_first->ttl_data, 0); /* TTL = 0 */
|
||||
memmove(cn->rr_first->ttl_data, rrset->rr_first->ttl_data,
|
||||
sizeof(uint32_t)); /* RFC6672: synth CNAME TTL == DNAME TTL */
|
||||
sldns_write_uint16(cn->rr_first->ttl_data+4, aliaslen);
|
||||
memmove(cn->rr_first->ttl_data+6, alias, aliaslen);
|
||||
cn->rr_first->size = sizeof(uint16_t)+aliaslen;
|
||||
@@ -366,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
|
||||
@@ -386,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)
|
||||
@@ -400,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,
|
||||
@@ -419,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 */
|
||||
@@ -459,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 &&
|
||||
@@ -506,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;
|
||||
}
|
||||
@@ -521,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 */
|
||||
@@ -577,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 */
|
||||
@@ -788,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;
|
||||
@@ -893,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);
|
||||
@@ -905,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;
|
||||
}
|
||||
|
||||
+95
-12
@@ -279,9 +279,10 @@ iter_filter_unsuitable(struct iter_env* iter_env, struct module_env* env,
|
||||
name, namelen, qtype, &lame, &dnsseclame, &reclame,
|
||||
&rtt, now)) {
|
||||
log_addr(VERB_ALGO, "servselect", &a->addr, a->addrlen);
|
||||
verbose(VERB_ALGO, " rtt=%d%s%s%s%s", rtt,
|
||||
verbose(VERB_ALGO, " rtt=%d%s%s%s%s%s", rtt,
|
||||
lame?" LAME":"",
|
||||
dnsseclame?" DNSSEC_LAME":"",
|
||||
a->dnsseclame?" ADDR_DNSSEC_LAME":"",
|
||||
reclame?" REC_LAME":"",
|
||||
a->lame?" ADDR_LAME":"");
|
||||
if(lame)
|
||||
@@ -1284,8 +1285,17 @@ iter_get_next_root(struct iter_hints* hints, struct iter_forwards* fwd,
|
||||
uint16_t* c)
|
||||
{
|
||||
uint16_t c1 = *c, c2 = *c;
|
||||
int r1 = hints_next_root(hints, &c1);
|
||||
int r2 = forwards_next_root(fwd, &c2);
|
||||
int r1, r2;
|
||||
int nolock = 1;
|
||||
|
||||
/* prelock both forwards and hints for atomic read. */
|
||||
lock_rw_rdlock(&fwd->lock);
|
||||
lock_rw_rdlock(&hints->lock);
|
||||
r1 = hints_next_root(hints, &c1, nolock);
|
||||
r2 = forwards_next_root(fwd, &c2, nolock);
|
||||
lock_rw_unlock(&fwd->lock);
|
||||
lock_rw_unlock(&hints->lock);
|
||||
|
||||
if(!r1 && !r2) /* got none, end of list */
|
||||
return 0;
|
||||
else if(!r1) /* got one, return that */
|
||||
@@ -1450,15 +1460,21 @@ int iter_dp_cangodown(struct query_info* qinfo, struct delegpt* dp)
|
||||
|
||||
int
|
||||
iter_stub_fwd_no_cache(struct module_qstate *qstate, struct query_info *qinf,
|
||||
uint8_t** retdpname, size_t* retdpnamelen)
|
||||
uint8_t** retdpname, size_t* retdpnamelen, uint8_t* dpname_storage,
|
||||
size_t dpname_storage_len)
|
||||
{
|
||||
struct iter_hints_stub *stub;
|
||||
struct delegpt *dp;
|
||||
int nolock = 1;
|
||||
|
||||
/* Check for stub. */
|
||||
/* Lock both forwards and hints for atomic read. */
|
||||
lock_rw_rdlock(&qstate->env->fwds->lock);
|
||||
lock_rw_rdlock(&qstate->env->hints->lock);
|
||||
stub = hints_lookup_stub(qstate->env->hints, qinf->qname,
|
||||
qinf->qclass, NULL);
|
||||
dp = forwards_lookup(qstate->env->fwds, qinf->qname, qinf->qclass);
|
||||
qinf->qclass, NULL, nolock);
|
||||
dp = forwards_lookup(qstate->env->fwds, qinf->qname, qinf->qclass,
|
||||
nolock);
|
||||
|
||||
/* see if forward or stub is more pertinent */
|
||||
if(stub && stub->dp && dp) {
|
||||
@@ -1472,7 +1488,9 @@ iter_stub_fwd_no_cache(struct module_qstate *qstate, struct query_info *qinf,
|
||||
|
||||
/* check stub */
|
||||
if (stub != NULL && stub->dp != NULL) {
|
||||
if(stub->dp->no_cache) {
|
||||
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];
|
||||
dname_str(qinf->qname, qname);
|
||||
@@ -1480,15 +1498,27 @@ iter_stub_fwd_no_cache(struct module_qstate *qstate, struct query_info *qinf,
|
||||
verbose(VERB_ALGO, "stub for %s %s has no_cache", qname, dpname);
|
||||
}
|
||||
if(retdpname) {
|
||||
*retdpname = stub->dp->name;
|
||||
if(stub->dp->namelen > dpname_storage_len) {
|
||||
verbose(VERB_ALGO, "no cache stub dpname too long");
|
||||
lock_rw_unlock(&qstate->env->hints->lock);
|
||||
*retdpname = NULL;
|
||||
*retdpnamelen = 0;
|
||||
return stub_no_cache;
|
||||
}
|
||||
memmove(dpname_storage, stub->dp->name,
|
||||
stub->dp->namelen);
|
||||
*retdpname = dpname_storage;
|
||||
*retdpnamelen = stub->dp->namelen;
|
||||
}
|
||||
return (stub->dp->no_cache);
|
||||
lock_rw_unlock(&qstate->env->hints->lock);
|
||||
return stub_no_cache;
|
||||
}
|
||||
|
||||
/* Check for forward. */
|
||||
if (dp) {
|
||||
if(dp->no_cache) {
|
||||
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];
|
||||
dname_str(qinf->qname, qname);
|
||||
@@ -1496,11 +1526,22 @@ iter_stub_fwd_no_cache(struct module_qstate *qstate, struct query_info *qinf,
|
||||
verbose(VERB_ALGO, "forward for %s %s has no_cache", qname, dpname);
|
||||
}
|
||||
if(retdpname) {
|
||||
*retdpname = dp->name;
|
||||
if(dp->namelen > dpname_storage_len) {
|
||||
verbose(VERB_ALGO, "no cache dpname too long");
|
||||
lock_rw_unlock(&qstate->env->fwds->lock);
|
||||
*retdpname = NULL;
|
||||
*retdpnamelen = 0;
|
||||
return dp_no_cache;
|
||||
}
|
||||
memmove(dpname_storage, dp->name, dp->namelen);
|
||||
*retdpname = dpname_storage;
|
||||
*retdpnamelen = dp->namelen;
|
||||
}
|
||||
return (dp->no_cache);
|
||||
lock_rw_unlock(&qstate->env->fwds->lock);
|
||||
return dp_no_cache;
|
||||
}
|
||||
lock_rw_unlock(&qstate->env->fwds->lock);
|
||||
lock_rw_unlock(&qstate->env->hints->lock);
|
||||
if(retdpname) {
|
||||
*retdpname = NULL;
|
||||
*retdpnamelen = 0;
|
||||
@@ -1523,3 +1564,45 @@ 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+12
-1
@@ -407,10 +407,14 @@ int iter_dp_cangodown(struct query_info* qinfo, struct delegpt* dp);
|
||||
* Used for NXDOMAIN checks, above that it is an nxdomain from a
|
||||
* different server and zone. You can pass NULL to not get it.
|
||||
* @param retdpnamelen: returns the length of the dpname.
|
||||
* @param dpname_storage: this is where the dpname buf is stored, if any.
|
||||
* So that caller can manage the buffer.
|
||||
* @param dpname_storage_len: size of dpname_storage buffer.
|
||||
* @return true if no_cache is set in stub or fwd.
|
||||
*/
|
||||
int iter_stub_fwd_no_cache(struct module_qstate *qstate,
|
||||
struct query_info *qinf, uint8_t** retdpname, size_t* retdpnamelen);
|
||||
struct query_info *qinf, uint8_t** retdpname, size_t* retdpnamelen,
|
||||
uint8_t* dpname_storage, size_t dpname_storage_len);
|
||||
|
||||
/**
|
||||
* Set support for IP4 and IP6 depending on outgoing interfaces
|
||||
@@ -424,4 +428,11 @@ 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);
|
||||
|
||||
/**
|
||||
* 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);
|
||||
|
||||
#endif /* ITERATOR_ITER_UTILS_H */
|
||||
|
||||
+338
-144
File diff suppressed because it is too large
Load Diff
@@ -55,6 +55,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
|
||||
@@ -248,6 +251,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,
|
||||
|
||||
+12
-2
@@ -53,6 +53,8 @@
|
||||
#include "util/storage/slabhash.h"
|
||||
#include "util/edns.h"
|
||||
#include "sldns/sbuffer.h"
|
||||
#include "iterator/iter_fwd.h"
|
||||
#include "iterator/iter_hints.h"
|
||||
|
||||
int
|
||||
context_finalize(struct ub_ctx* ctx)
|
||||
@@ -73,7 +75,9 @@ context_finalize(struct ub_ctx* ctx)
|
||||
ctx->pipe_pid = getpid();
|
||||
cfg_apply_local_port_policy(cfg, 65536);
|
||||
config_apply(cfg);
|
||||
if(!modstack_setup(&ctx->mods, cfg->module_conf, ctx->env))
|
||||
if(!modstack_call_startup(&ctx->mods, cfg->module_conf, ctx->env))
|
||||
return UB_INITFAIL;
|
||||
if(!modstack_call_init(&ctx->mods, cfg->module_conf, ctx->env))
|
||||
return UB_INITFAIL;
|
||||
listen_setup_locks();
|
||||
log_edns_known_options(VERB_ALGO, ctx->env);
|
||||
@@ -85,6 +89,12 @@ context_finalize(struct ub_ctx* ctx)
|
||||
if(!auth_zones_apply_cfg(ctx->env->auth_zones, cfg, 1, &is_rpz,
|
||||
ctx->env, &ctx->mods))
|
||||
return UB_INITFAIL;
|
||||
if(!(ctx->env->fwds = forwards_create()) ||
|
||||
!forwards_apply_cfg(ctx->env->fwds, cfg))
|
||||
return UB_INITFAIL;
|
||||
if(!(ctx->env->hints = hints_create()) ||
|
||||
!hints_apply_cfg(ctx->env->hints, cfg))
|
||||
return UB_INITFAIL;
|
||||
if(!edns_strings_apply_cfg(ctx->env->edns_strings, cfg))
|
||||
return UB_INITFAIL;
|
||||
if(!slabhash_is_size(ctx->env->msg_cache, cfg->msg_cache_size,
|
||||
@@ -385,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);
|
||||
|
||||
+19
-5
@@ -66,6 +66,8 @@
|
||||
#include "services/authzone.h"
|
||||
#include "services/listen_dnsport.h"
|
||||
#include "sldns/sbuffer.h"
|
||||
#include "iterator/iter_fwd.h"
|
||||
#include "iterator/iter_hints.h"
|
||||
#ifdef HAVE_PTHREAD
|
||||
#include <signal.h>
|
||||
#endif
|
||||
@@ -171,6 +173,7 @@ static struct ub_ctx* ub_ctx_create_nopipe(void)
|
||||
ctx->env->worker = NULL;
|
||||
ctx->env->need_to_validate = 0;
|
||||
modstack_init(&ctx->mods);
|
||||
ctx->env->modstack = &ctx->mods;
|
||||
rbtree_init(&ctx->queries, &context_query_cmp);
|
||||
return ctx;
|
||||
}
|
||||
@@ -185,7 +188,9 @@ ub_ctx_create(void)
|
||||
int e = errno;
|
||||
ub_randfree(ctx->seed_rnd);
|
||||
config_delete(ctx->env->cfg);
|
||||
modstack_desetup(&ctx->mods, ctx->env);
|
||||
modstack_call_deinit(&ctx->mods, ctx->env);
|
||||
modstack_call_destartup(&ctx->mods, ctx->env);
|
||||
modstack_free(&ctx->mods);
|
||||
listen_desetup_locks();
|
||||
edns_known_options_delete(ctx->env);
|
||||
edns_strings_delete(ctx->env->edns_strings);
|
||||
@@ -199,7 +204,9 @@ ub_ctx_create(void)
|
||||
tube_delete(ctx->qq_pipe);
|
||||
ub_randfree(ctx->seed_rnd);
|
||||
config_delete(ctx->env->cfg);
|
||||
modstack_desetup(&ctx->mods, ctx->env);
|
||||
modstack_call_deinit(&ctx->mods, ctx->env);
|
||||
modstack_call_destartup(&ctx->mods, ctx->env);
|
||||
modstack_free(&ctx->mods);
|
||||
listen_desetup_locks();
|
||||
edns_known_options_delete(ctx->env);
|
||||
edns_strings_delete(ctx->env->edns_strings);
|
||||
@@ -357,7 +364,9 @@ ub_ctx_delete(struct ub_ctx* ctx)
|
||||
}
|
||||
libworker_delete_event(ctx->event_worker);
|
||||
|
||||
modstack_desetup(&ctx->mods, ctx->env);
|
||||
modstack_call_deinit(&ctx->mods, ctx->env);
|
||||
modstack_call_destartup(&ctx->mods, ctx->env);
|
||||
modstack_free(&ctx->mods);
|
||||
a = ctx->alloc_list;
|
||||
while(a) {
|
||||
na = a->super;
|
||||
@@ -379,6 +388,8 @@ ub_ctx_delete(struct ub_ctx* ctx)
|
||||
config_delete(ctx->env->cfg);
|
||||
edns_known_options_delete(ctx->env);
|
||||
edns_strings_delete(ctx->env->edns_strings);
|
||||
forwards_delete(ctx->env->fwds);
|
||||
hints_delete(ctx->env->hints);
|
||||
auth_zones_delete(ctx->env->auth_zones);
|
||||
free(ctx->env);
|
||||
}
|
||||
@@ -976,7 +987,8 @@ ub_ctx_set_fwd(struct ub_ctx* ctx, const char* addr)
|
||||
if(!addr) {
|
||||
/* disable fwd mode - the root stub should be first. */
|
||||
if(ctx->env->cfg->forwards &&
|
||||
strcmp(ctx->env->cfg->forwards->name, ".") == 0) {
|
||||
(ctx->env->cfg->forwards->name &&
|
||||
strcmp(ctx->env->cfg->forwards->name, ".") == 0)) {
|
||||
s = ctx->env->cfg->forwards;
|
||||
ctx->env->cfg->forwards = s->next;
|
||||
s->next = NULL;
|
||||
@@ -996,7 +1008,8 @@ ub_ctx_set_fwd(struct ub_ctx* ctx, const char* addr)
|
||||
/* it parses, add root stub in front of list */
|
||||
lock_basic_lock(&ctx->cfglock);
|
||||
if(!ctx->env->cfg->forwards ||
|
||||
strcmp(ctx->env->cfg->forwards->name, ".") != 0) {
|
||||
(ctx->env->cfg->forwards->name &&
|
||||
strcmp(ctx->env->cfg->forwards->name, ".") != 0)) {
|
||||
s = calloc(1, sizeof(*s));
|
||||
if(!s) {
|
||||
lock_basic_unlock(&ctx->cfglock);
|
||||
@@ -1014,6 +1027,7 @@ ub_ctx_set_fwd(struct ub_ctx* ctx, const char* addr)
|
||||
ctx->env->cfg->forwards = s;
|
||||
} else {
|
||||
log_assert(ctx->env->cfg->forwards);
|
||||
log_assert(ctx->env->cfg->forwards->name);
|
||||
s = ctx->env->cfg->forwards;
|
||||
}
|
||||
dupl = strdup(addr);
|
||||
|
||||
+20
-18
@@ -70,8 +70,6 @@
|
||||
#include "util/data/msgreply.h"
|
||||
#include "util/data/msgencode.h"
|
||||
#include "util/tube.h"
|
||||
#include "iterator/iter_fwd.h"
|
||||
#include "iterator/iter_hints.h"
|
||||
#include "sldns/sbuffer.h"
|
||||
#include "sldns/str2wire.h"
|
||||
#ifdef USE_DNSTAP
|
||||
@@ -100,8 +98,6 @@ libworker_delete_env(struct libworker* w)
|
||||
!w->is_bg || w->is_bg_thread);
|
||||
sldns_buffer_free(w->env->scratch_buffer);
|
||||
regional_destroy(w->env->scratch);
|
||||
forwards_delete(w->env->fwds);
|
||||
hints_delete(w->env->hints);
|
||||
ub_randfree(w->env->rnd);
|
||||
free(w->env);
|
||||
}
|
||||
@@ -159,30 +155,19 @@ libworker_setup(struct ub_ctx* ctx, int is_bg, struct ub_event_base* eb)
|
||||
}
|
||||
w->env->scratch = regional_create_custom(cfg->msg_buffer_size);
|
||||
w->env->scratch_buffer = sldns_buffer_new(cfg->msg_buffer_size);
|
||||
w->env->fwds = forwards_create();
|
||||
if(w->env->fwds && !forwards_apply_cfg(w->env->fwds, cfg)) {
|
||||
forwards_delete(w->env->fwds);
|
||||
w->env->fwds = NULL;
|
||||
}
|
||||
w->env->hints = hints_create();
|
||||
if(w->env->hints && !hints_apply_cfg(w->env->hints, cfg)) {
|
||||
hints_delete(w->env->hints);
|
||||
w->env->hints = NULL;
|
||||
}
|
||||
#ifdef HAVE_SSL
|
||||
w->sslctx = connect_sslctx_create(NULL, NULL,
|
||||
cfg->tls_cert_bundle, cfg->tls_win_cert);
|
||||
if(!w->sslctx) {
|
||||
/* to make the setup fail after unlock */
|
||||
hints_delete(w->env->hints);
|
||||
w->env->hints = NULL;
|
||||
sldns_buffer_free(w->env->scratch_buffer);
|
||||
w->env->scratch_buffer = NULL;
|
||||
}
|
||||
#endif
|
||||
if(!w->is_bg || w->is_bg_thread) {
|
||||
lock_basic_unlock(&ctx->cfglock);
|
||||
}
|
||||
if(!w->env->scratch || !w->env->scratch_buffer || !w->env->fwds ||
|
||||
!w->env->hints) {
|
||||
if(!w->env->scratch || !w->env->scratch_buffer) {
|
||||
libworker_delete(w);
|
||||
return NULL;
|
||||
}
|
||||
@@ -307,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);
|
||||
@@ -1072,3 +1058,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
|
||||
|
||||
@@ -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,10 @@ 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;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
+143
-41
@@ -45,20 +45,24 @@ usage () {
|
||||
Usage $0: [-h] [-s] [-u git_url] [-b git_branch] [-w ...args...]
|
||||
Generate a distribution tar file for unbound.
|
||||
|
||||
-h This usage information.
|
||||
-s Build a snapshot distribution file. The current date is
|
||||
automatically appended to the current unbound version number.
|
||||
-rc <nr> Build a release candidate, the given string will be added
|
||||
to the version number
|
||||
(which will then be unbound-<version>rc<number>)
|
||||
-u git_url Retrieve the source from the specified repository url.
|
||||
Detected from the working copy if not specified.
|
||||
-b git_branch Retrieve the the specified branch or tag.
|
||||
Detected from the working copy if not specified.
|
||||
-h This usage information.
|
||||
-s Build a snapshot distribution file. The current date is
|
||||
automatically appended to the current unbound version number.
|
||||
-rc <nr> Build a release candidate, the given string will be added
|
||||
to the version number
|
||||
(which will then be unbound-<version>rc<number>)
|
||||
-u git_url Retrieve the source from the specified repository url.
|
||||
Detected from the working copy if not specified.
|
||||
-b git_branch Retrieve the specified branch or tag.
|
||||
Detected from the working copy if not specified.
|
||||
-wssl openssl.xx.tar.gz Also build openssl from tarball for windows dist.
|
||||
-wxp expat.xx.tar.gz Also build expat from tarball for windows dist.
|
||||
-w32 32bit windows compile.
|
||||
-w ... Build windows binary dist. last args passed to configure.
|
||||
-wdir directory Build openssl and expat in a persistent directory for
|
||||
windows dist. If builds are already in that directory
|
||||
they are used right away. Useful when debuggin windows
|
||||
builds.
|
||||
-w32 32bit windows compile.
|
||||
-w ... Build windows binary dist. last args passed to configure.
|
||||
EOF
|
||||
exit 1
|
||||
}
|
||||
@@ -143,6 +147,16 @@ create_temp_dir () {
|
||||
cd $temp_dir
|
||||
}
|
||||
|
||||
activate_windebug_dir () {
|
||||
info "Activating persistent directory for windows build."
|
||||
if test ! -d "$WINDIR"; then
|
||||
mkdir -p "$WINDIR"
|
||||
info "Created $WINDIR persistent directory."
|
||||
fi
|
||||
cd "$WINDIR"
|
||||
WINDIR="`pwd`"
|
||||
}
|
||||
|
||||
# pass filename as $1 arg.
|
||||
# creates file.sha1 and file.sha256
|
||||
storehash () {
|
||||
@@ -187,7 +201,9 @@ DOWIN="no"
|
||||
W64="yes"
|
||||
WINSSL=""
|
||||
WINEXPAT=""
|
||||
MINJ=""
|
||||
WINDIR=""
|
||||
# Use environment if set otherwise null
|
||||
MINJ="${MINJ:+$MINJ}"
|
||||
|
||||
# Parse the command line arguments.
|
||||
while [ "$1" ]; do
|
||||
@@ -214,6 +230,10 @@ while [ "$1" ]; do
|
||||
WINEXPAT="$2"
|
||||
shift
|
||||
;;
|
||||
"-wdir")
|
||||
WINDIR="$2"
|
||||
shift
|
||||
;;
|
||||
"-w32")
|
||||
W64="no"
|
||||
;;
|
||||
@@ -253,8 +273,27 @@ if [ "$DOWIN" = "yes" ]; then
|
||||
shared_cross_flag=""
|
||||
|
||||
check_git_repo
|
||||
create_temp_dir
|
||||
|
||||
if test -n "$WINDIR"; then
|
||||
activate_windebug_dir
|
||||
else
|
||||
create_temp_dir
|
||||
fi
|
||||
|
||||
if test -n "$WINSSL" \
|
||||
-a -n "$WINDIR" \
|
||||
-a -d "$WINDIR" \
|
||||
-a -d "${WINDIR}/sslinstall" \
|
||||
-a -d "${WINDIR}/openssl_shared" \
|
||||
-a -d "${WINDIR}/sslsharedinstall"; then
|
||||
info "Found already compiled openssl at $WINDIR/sslinstall; using that."
|
||||
WINSSL=""
|
||||
# Variables needed later on.
|
||||
sslinstall="${WINDIR}/sslinstall"
|
||||
cross_flag="$cross_flag --with-ssl=$sslinstall"
|
||||
sslsharedinstall="${WINDIR}/sslsharedinstall"
|
||||
shared_cross_flag="$shared_cross_flag --with-ssl=$sslsharedinstall"
|
||||
fi
|
||||
# crosscompile openssl for windows.
|
||||
if test -n "$WINSSL"; then
|
||||
info "Cross compile $WINSSL"
|
||||
@@ -267,10 +306,10 @@ if [ "$DOWIN" = "yes" ]; then
|
||||
# cross-compilation and it is not used anyway
|
||||
# before 1.0.1i need --cross-compile-prefix=i686-w64-mingw32-
|
||||
if test "$mw64" = "mingw64"; then
|
||||
sslflags="no-asm -DOPENSSL_NO_CAPIENG mingw64"
|
||||
sslflags="no-asm no-tests -DOPENSSL_NO_CAPIENG mingw64"
|
||||
sspdll="/usr/x86_64-w64-mingw32/sys-root/mingw/bin/libssp-0.dll"
|
||||
else
|
||||
sslflags="no-asm -DOPENSSL_NO_CAPIENG mingw"
|
||||
sslflags="no-asm no-tests -DOPENSSL_NO_CAPIENG mingw"
|
||||
sspdll="/usr/i686-w64-mingw32/sys-root/mingw/bin/libssp-0.dll"
|
||||
fi
|
||||
if test -f "$sspdll"; then
|
||||
@@ -282,9 +321,18 @@ if [ "$DOWIN" = "yes" ]; then
|
||||
SSPLIB=""
|
||||
fi
|
||||
info "winssl: Configure no-shared $sslflags"
|
||||
set -x # echo the configure command
|
||||
__CNF_LDLIBS=$SSPLIB CC=${warch}-w64-mingw32-gcc AR=${warch}-w64-mingw32-ar RANLIB=${warch}-w64-mingw32-ranlib WINDRES=${warch}-w64-mingw32-windres ./Configure --prefix="$sslinstall" no-shared $sslflags || error_cleanup "OpenSSL Configure failed"
|
||||
set +x
|
||||
if test "$W64" = "no"; then
|
||||
# Disable stack-protector for 32-bit windows builds.
|
||||
# mingw passes an LDFLAGS, so there is something
|
||||
# passed in the LDFLAGS to stop -lssp passed in it.
|
||||
set -x # echo the configure command
|
||||
__CNF_LDLIBS=$SSPLIB __CNF_LDFLAGS="-fno-stack-protector" CC=${warch}-w64-mingw32-gcc AR=${warch}-w64-mingw32-ar RANLIB=${warch}-w64-mingw32-ranlib WINDRES=${warch}-w64-mingw32-windres ./Configure --prefix="$sslinstall" no-shared $sslflags || error_cleanup "OpenSSL Configure failed"
|
||||
set +x
|
||||
else
|
||||
set -x # echo the configure command
|
||||
__CNF_LDLIBS=$SSPLIB CC=${warch}-w64-mingw32-gcc AR=${warch}-w64-mingw32-ar RANLIB=${warch}-w64-mingw32-ranlib WINDRES=${warch}-w64-mingw32-windres ./Configure --prefix="$sslinstall" no-shared $sslflags || error_cleanup "OpenSSL Configure failed"
|
||||
set +x
|
||||
fi
|
||||
info "winssl: make"
|
||||
make $MINJ || error_cleanup "OpenSSL crosscompile failed"
|
||||
# only install sw not docs, which take a long time.
|
||||
@@ -297,9 +345,15 @@ if [ "$DOWIN" = "yes" ]; then
|
||||
sslsharedinstall="`pwd`/sslsharedinstall"
|
||||
cd openssl_shared
|
||||
info "winssl: Configure shared $sslflags"
|
||||
set -x # echo the configure command
|
||||
__CNF_LDLIBS=$SSPLIB CC=${warch}-w64-mingw32-gcc AR=${warch}-w64-mingw32-ar RANLIB=${warch}-w64-mingw32-ranlib WINDRES=${warch}-w64-mingw32-windres ./Configure --prefix="$sslsharedinstall" shared $sslflags || error_cleanup "OpenSSL Configure failed"
|
||||
set +x
|
||||
if test "$W64" = "no"; then
|
||||
set -x # echo the configure command
|
||||
__CNF_LDLIBS=$SSPLIB __CNF_LDFLAGS="-fno-stack-protector" CC=${warch}-w64-mingw32-gcc AR=${warch}-w64-mingw32-ar RANLIB=${warch}-w64-mingw32-ranlib WINDRES=${warch}-w64-mingw32-windres ./Configure --prefix="$sslsharedinstall" shared $sslflags || error_cleanup "OpenSSL Configure failed"
|
||||
set +x
|
||||
else
|
||||
set -x # echo the configure command
|
||||
__CNF_LDLIBS=$SSPLIB CC=${warch}-w64-mingw32-gcc AR=${warch}-w64-mingw32-ar RANLIB=${warch}-w64-mingw32-ranlib WINDRES=${warch}-w64-mingw32-windres ./Configure --prefix="$sslsharedinstall" shared $sslflags || error_cleanup "OpenSSL Configure failed"
|
||||
set +x
|
||||
fi
|
||||
info "winssl: make"
|
||||
make $MINJ || error_cleanup "OpenSSL crosscompile failed"
|
||||
info "winssl: make install_sw"
|
||||
@@ -308,6 +362,17 @@ if [ "$DOWIN" = "yes" ]; then
|
||||
cd ..
|
||||
fi
|
||||
|
||||
if test -n "$WINEXPAT" \
|
||||
-a -n "$WINDIR" \
|
||||
-a -d "$WINDIR" \
|
||||
-a -d "${WINDIR}/wxpinstall"; then
|
||||
info "Found already compiled expat at $WINDIR/wxpinstall; using that."
|
||||
WINEXPAT=""
|
||||
# Variables needed later on.
|
||||
wxpinstall="${WINDIR}/wxpinstall"
|
||||
cross_flag="$cross_flag --with-libexpat=$wxpinstall"
|
||||
shared_cross_flag="$shared_cross_flag --with-libexpat=$wxpinstall"
|
||||
fi
|
||||
if test -n "$WINEXPAT"; then
|
||||
info "Cross compile $WINEXPAT"
|
||||
info "wxp: tar unpack"
|
||||
@@ -315,7 +380,16 @@ if [ "$DOWIN" = "yes" ]; then
|
||||
wxpinstall="`pwd`/wxpinstall"
|
||||
cd expat-* || error_cleanup "no expat-X dir in tarball"
|
||||
info "wxp: configure"
|
||||
$configure --prefix="$wxpinstall" --exec-prefix="$wxpinstall" --bindir="$wxpinstall/bin" --includedir="$wxpinstall/include" --mandir="$wxpinstall/man" --libdir="$wxpinstall/lib" || error_cleanup "libexpat configure failed"
|
||||
if test "$W64" = "no"; then
|
||||
# Disable stack-protector for 32-bit windows builds.
|
||||
set -x # echo the configure command
|
||||
$configure --prefix="$wxpinstall" --exec-prefix="$wxpinstall" --bindir="$wxpinstall/bin" --includedir="$wxpinstall/include" --mandir="$wxpinstall/man" --libdir="$wxpinstall/lib" LDFLAGS="-fno-stack-protector" || error_cleanup "libexpat configure failed"
|
||||
set +x
|
||||
else
|
||||
set -x # echo the configure command
|
||||
$configure --prefix="$wxpinstall" --exec-prefix="$wxpinstall" --bindir="$wxpinstall/bin" --includedir="$wxpinstall/include" --mandir="$wxpinstall/man" --libdir="$wxpinstall/lib" || error_cleanup "libexpat configure failed"
|
||||
set +x
|
||||
fi
|
||||
info "wxp: make"
|
||||
make $MINJ || error_cleanup "libexpat crosscompile failed"
|
||||
info "wxp: make install"
|
||||
@@ -325,8 +399,12 @@ if [ "$DOWIN" = "yes" ]; then
|
||||
cd ..
|
||||
fi
|
||||
|
||||
info "GITREPO is $GITREPO"
|
||||
info "GITBRANCH is $GITBRANCH"
|
||||
if test -n "$WINDIR"; then
|
||||
cd "$cwd"
|
||||
create_temp_dir
|
||||
fi
|
||||
info "GITREPO is $GITREPO"
|
||||
info "GITBRANCH is $GITBRANCH"
|
||||
info "Exporting source from git."
|
||||
info "git clone --depth=1 --no-tags -b $GITBRANCH $GITREPO unbound"
|
||||
git clone --depth=1 --no-tags -b $GITBRANCH $GITREPO unbound || error_cleanup "git clone failed"
|
||||
@@ -361,10 +439,14 @@ if [ "$DOWIN" = "yes" ]; then
|
||||
autoconf -f || error_cleanup "Autoconf failed."
|
||||
autoheader -f || error_cleanup "Autoheader failed."
|
||||
rm -r autom4te* || echo "ignored"
|
||||
rm -f config.h.in~ || echo "ignore absence of config.h.in~ file."
|
||||
fi
|
||||
|
||||
if test "`uname`" = "Linux"; then
|
||||
(cd ..; cp -r unbound unbound_shared)
|
||||
cd ..
|
||||
cp -r unbound unbound_shared
|
||||
unbound_shared="`pwd`/unbound_shared"
|
||||
cd unbound
|
||||
fi
|
||||
|
||||
# procedure for making unbound installer on mingw.
|
||||
@@ -378,13 +460,15 @@ if [ "$DOWIN" = "yes" ]; then
|
||||
fi
|
||||
if test "$W64" = "no"; then
|
||||
# Disable stack-protector for 32-bit windows builds.
|
||||
echo "$configure"' --enable-debug --enable-static-exe --disable-flto --disable-gost '"$* $cross_flag" "$file_flag" "$file2_flag" "$file3_flag" CFLAGS='-O2 -g -fno-stack-protector'
|
||||
$configure --enable-debug --enable-static-exe --disable-flto --disable-gost $* $cross_flag "$file_flag" "$file2_flag" "$file3_flag" CFLAGS='-O2 -g -fno-stack-protector'\
|
||||
set -x
|
||||
$configure --enable-debug --enable-static-exe --disable-flto --disable-gost $* $cross_flag "$file_flag" "$file2_flag" "$file3_flag" CFLAGS='-O2 -g -fno-stack-protector' LDFLAGS="-fno-stack-protector" \
|
||||
|| error_cleanup "Could not configure"
|
||||
set +x
|
||||
else
|
||||
echo "$configure"' --enable-debug --enable-static-exe --disable-flto --disable-gost '"$* $cross_flag"
|
||||
set -x
|
||||
$configure --enable-debug --enable-static-exe --disable-flto --disable-gost $* $cross_flag \
|
||||
|| error_cleanup "Could not configure"
|
||||
set +x
|
||||
fi
|
||||
info "Calling make"
|
||||
make $MINJ || error_cleanup "Could not make"
|
||||
@@ -392,16 +476,18 @@ if [ "$DOWIN" = "yes" ]; then
|
||||
|
||||
if test "`uname`" = "Linux"; then
|
||||
info "Make DLL"
|
||||
cd ../unbound_shared
|
||||
cd $unbound_shared
|
||||
if test "$W64" = "no"; then
|
||||
# Disable stack-protector for 32-bit windows builds.
|
||||
echo "$configure"' --enable-debug --disable-flto --disable-gost '"$* $shared_cross_flag" "$file_flag" "$file2_flag" "$file3_flag" CFLAGS='-O2 -g -fno-stack-protector'
|
||||
$configure --enable-debug --disable-flto --disable-gost $* $shared_cross_flag "$file_flag" "$file2_flag" "$file3_flag" CFLAGS='-O2 -g -fno-stack-protector'\
|
||||
set -x
|
||||
$configure --enable-debug --disable-flto --disable-gost $* $shared_cross_flag "$file_flag" "$file2_flag" "$file3_flag" CFLAGS='-O2 -g -fno-stack-protector' LDFLAGS="-fno-stack-protector" \
|
||||
|| error_cleanup "Could not configure"
|
||||
set +x
|
||||
else
|
||||
echo "$configure"' --enable-debug --disable-flto --disable-gost '"$* $shared_cross_flag"
|
||||
$configure --enable-debug --disable-flto --disable-gost $* $shared_cross_flag \
|
||||
set -x
|
||||
$configure --enable-debug --disable-flto --disable-gost $* $shared_cross_flag \
|
||||
|| error_cleanup "Could not configure"
|
||||
set +x
|
||||
fi
|
||||
info "Calling make for DLL"
|
||||
make $MINJ || error_cleanup "Could not make DLL"
|
||||
@@ -430,17 +516,26 @@ if [ "$DOWIN" = "yes" ]; then
|
||||
cp ../unbound.exe ../unbound-anchor.exe ../unbound-host.exe ../unbound-control.exe ../unbound-checkconf.exe ../unbound-service-install.exe ../unbound-service-remove.exe ../LICENSE ../winrc/unbound-control-setup.cmd ../winrc/unbound-website.url ../winrc/service.conf ../winrc/README.txt ../contrib/create_unbound_ad_servers.cmd ../contrib/warmup.cmd ../contrib/unbound_cache.cmd .
|
||||
mkdir libunbound
|
||||
# test to see if lib or lib64 (for openssl 3.0.0) needs to be used
|
||||
if test -f ../../sslsharedinstall/lib/libcrypto.dll.a; then
|
||||
cp ../../sslsharedinstall/lib/libcrypto.dll.a libunbound/.
|
||||
if test -f $sslsharedinstall/lib/libcrypto.dll.a; then
|
||||
cp $sslsharedinstall/lib/libcrypto.dll.a libunbound/.
|
||||
else
|
||||
cp ../../sslsharedinstall/lib64/libcrypto.dll.a libunbound/.
|
||||
cp $sslsharedinstall/lib64/libcrypto.dll.a libunbound/.
|
||||
fi
|
||||
if test -f ../../sslsharedinstall/lib/libssl.dll.a; then
|
||||
cp ../../sslsharedinstall/lib/libssl.dll.a libunbound/.
|
||||
if test -f $sslsharedinstall/lib/libssl.dll.a; then
|
||||
cp $sslsharedinstall/lib/libssl.dll.a libunbound/.
|
||||
else
|
||||
cp ../../sslsharedinstall/lib64/libssl.dll.a libunbound/.
|
||||
cp $sslsharedinstall/lib64/libssl.dll.a libunbound/.
|
||||
fi
|
||||
cp ../../unbound_shared/unbound.h ../../unbound_shared/.libs/libunbound*.dll ../../unbound_shared/.libs/libunbound.dll.a ../../unbound_shared/.libs/libunbound.a ../../unbound_shared/.libs/libunbound*.def ../../sslsharedinstall/bin/libcrypto*.dll ../../sslsharedinstall/bin/libssl*.dll ../../wxpinstall/bin/libexpat*.dll ../../wxpinstall/lib/libexpat.dll.a libunbound/.
|
||||
cp $unbound_shared/unbound.h \
|
||||
$unbound_shared/.libs/libunbound*.dll \
|
||||
$unbound_shared/.libs/libunbound.dll.a \
|
||||
$unbound_shared/.libs/libunbound.a \
|
||||
$unbound_shared/.libs/libunbound*.def \
|
||||
$sslsharedinstall/bin/libcrypto*.dll \
|
||||
$sslsharedinstall/bin/libssl*.dll \
|
||||
$wxpinstall/bin/libexpat*.dll \
|
||||
$wxpinstall/lib/libexpat.dll.a \
|
||||
libunbound/.
|
||||
if test -f "$sspdll"; then
|
||||
cp "$sspdll" libunbound/.
|
||||
fi
|
||||
@@ -470,6 +565,11 @@ if [ "$DOWIN" = "yes" ]; then
|
||||
storehash unbound-$version.zip
|
||||
ls -lG unbound_setup_$version.exe
|
||||
ls -lG unbound-$version.zip
|
||||
|
||||
echo "create signed versions with:"
|
||||
echo " gpg --armor --detach-sign --digest-algo SHA256 unbound_setup_$version.exe"
|
||||
echo " gpg --armor --detach-sign --digest-algo SHA256 unbound-$version.zip"
|
||||
|
||||
info "Done"
|
||||
exit 0
|
||||
fi
|
||||
@@ -514,6 +614,7 @@ info "Building configure script (autoreconf)."
|
||||
autoreconf -f || error_cleanup "Autoconf failed."
|
||||
|
||||
rm -r autom4te* || error_cleanup "Failed to remove autoconf cache directory."
|
||||
rm -f config.h.in~ || echo "ignore absence of config.h.in~ file."
|
||||
|
||||
info "Building lexer and parser."
|
||||
echo "#include \"config.h\"" > util/configlexer.c || error_cleanup "Failed to create configlexer"
|
||||
@@ -558,6 +659,7 @@ if [ "$RECONFIGURE" = "yes" ]; then
|
||||
info "Rebuilding configure script (autoconf) snapshot."
|
||||
autoreconf -f || error_cleanup "Autoconf failed."
|
||||
rm -r autom4te* || error_cleanup "Failed to remove autoconf cache directory."
|
||||
rm -f config.h.in~ || echo "ignore absence of config.h.in~ file."
|
||||
fi
|
||||
|
||||
replace_all doc/README
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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;
|
||||
@@ -1416,7 +1417,7 @@ struct delegpt* dns_cache_find_delegation(struct module_env* env,
|
||||
int iter_dp_is_useless(struct query_info* qinfo, uint16_t qflags,
|
||||
struct delegpt* dp, int supports_ipv4, int supports_ipv6, int use_nat64);
|
||||
struct iter_hints_stub* hints_lookup_stub(struct iter_hints* hints,
|
||||
uint8_t* qname, uint16_t qclass, struct delegpt* dp);
|
||||
uint8_t* qname, uint16_t qclass, struct delegpt* dp, int nolock);
|
||||
|
||||
/* Custom function to perform logic similar to the one in daemon/cachedump.c */
|
||||
struct delegpt* find_delegation(struct module_qstate* qstate, char *nm, size_t nmlen);
|
||||
@@ -1433,6 +1434,7 @@ struct delegpt* find_delegation(struct module_qstate* qstate, char *nm, size_t n
|
||||
struct query_info qinfo;
|
||||
struct iter_hints_stub* stub;
|
||||
uint32_t timenow = *qstate->env->now;
|
||||
int nolock = 0;
|
||||
|
||||
regional_free_all(region);
|
||||
qinfo.qname = (uint8_t*)nm;
|
||||
@@ -1455,9 +1457,12 @@ struct delegpt* find_delegation(struct module_qstate* qstate, char *nm, size_t n
|
||||
dname_str((uint8_t*)nm, b);
|
||||
continue;
|
||||
}
|
||||
stub = hints_lookup_stub(qstate->env->hints, qinfo.qname, qinfo.qclass, dp);
|
||||
stub = hints_lookup_stub(qstate->env->hints, qinfo.qname,
|
||||
qinfo.qclass, dp, nolock);
|
||||
if (stub) {
|
||||
return stub->dp;
|
||||
struct delegpt* stubdp = delegpt_copy(stub->dp, region);
|
||||
lock_rw_unlock(&qstate->env->hints->lock);
|
||||
return stubdp;
|
||||
} else {
|
||||
return dp;
|
||||
}
|
||||
|
||||
@@ -356,11 +356,11 @@ int pythonmod_init(struct module_env* env, int id)
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
Py_NoSiteFlag = 1;
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
PyImport_AppendInittab(SWIG_name, (void*)SWIG_init);
|
||||
#endif
|
||||
#if PY_VERSION_HEX < 0x03080000
|
||||
Py_NoSiteFlag = 1;
|
||||
Py_Initialize();
|
||||
#else
|
||||
PyConfig_InitPythonConfig(&config);
|
||||
@@ -777,8 +777,8 @@ size_t pythonmod_get_mem(struct module_env* env, int id)
|
||||
*/
|
||||
static struct module_func_block pythonmod_block = {
|
||||
"python",
|
||||
&pythonmod_init, &pythonmod_deinit, &pythonmod_operate, &pythonmod_inform_super,
|
||||
&pythonmod_clear, &pythonmod_get_mem
|
||||
NULL, NULL, &pythonmod_init, &pythonmod_deinit, &pythonmod_operate,
|
||||
&pythonmod_inform_super, &pythonmod_clear, &pythonmod_get_mem
|
||||
};
|
||||
|
||||
struct module_func_block* pythonmod_get_funcblock(void)
|
||||
|
||||
+2
-2
@@ -1259,8 +1259,8 @@ respip_get_mem(struct module_env* env, int id)
|
||||
*/
|
||||
static struct module_func_block respip_block = {
|
||||
"respip",
|
||||
&respip_init, &respip_deinit, &respip_operate, &respip_inform_super,
|
||||
&respip_clear, &respip_get_mem
|
||||
NULL, NULL, &respip_init, &respip_deinit, &respip_operate,
|
||||
&respip_inform_super, &respip_clear, &respip_get_mem
|
||||
};
|
||||
|
||||
struct module_func_block*
|
||||
|
||||
+74
-25
@@ -2152,6 +2152,16 @@ auth_zones_cfg(struct auth_zones* az, struct config_auth* c)
|
||||
if(az->rpz_first)
|
||||
az->rpz_first->rpz_az_prev = z;
|
||||
az->rpz_first = z;
|
||||
} else if(c->isrpz && z->rpz) {
|
||||
if(!rpz_config(z->rpz, c)) {
|
||||
log_err("Could not change rpz config");
|
||||
if(x) {
|
||||
lock_basic_unlock(&x->lock);
|
||||
}
|
||||
lock_rw_unlock(&z->lock);
|
||||
lock_rw_unlock(&az->rpz_lock);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if(c->isrpz) {
|
||||
lock_rw_unlock(&az->rpz_lock);
|
||||
@@ -2702,7 +2712,7 @@ create_synth_cname(uint8_t* qname, size_t qname_len, struct regional* region,
|
||||
if(!d)
|
||||
return 0; /* out of memory */
|
||||
(*cname)->entry.data = d;
|
||||
d->ttl = 0; /* 0 for synthesized CNAME TTL */
|
||||
d->ttl = dname->data->ttl; /* RFC6672: synth CNAME TTL == DNAME TTL */
|
||||
d->count = 1;
|
||||
d->rrsig_count = 0;
|
||||
d->trust = rrset_trust_ans_noAA;
|
||||
@@ -3674,6 +3684,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,
|
||||
@@ -5506,7 +5539,7 @@ xfr_transfer_init_fetch(struct auth_xfer* xfr, struct module_env* env)
|
||||
if(!xfr->task_transfer->cp) {
|
||||
char zname[255+1], 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;
|
||||
@@ -5515,7 +5548,7 @@ xfr_transfer_init_fetch(struct auth_xfer* xfr, struct module_env* env)
|
||||
if(verbosity >= VERB_ALGO) {
|
||||
char zname[255+1], 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 */
|
||||
@@ -5538,7 +5571,7 @@ xfr_transfer_init_fetch(struct auth_xfer* xfr, struct module_env* env)
|
||||
if(!xfr->task_transfer->cp) {
|
||||
char zname[255+1], 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;
|
||||
@@ -5547,7 +5580,7 @@ xfr_transfer_init_fetch(struct auth_xfer* xfr, struct module_env* env)
|
||||
if(verbosity >= VERB_ALGO) {
|
||||
char zname[255+1], 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);
|
||||
}
|
||||
@@ -5650,7 +5683,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);
|
||||
}
|
||||
@@ -6396,7 +6429,7 @@ xfr_probe_send_probe(struct auth_xfer* xfr, struct module_env* env,
|
||||
if(!xfr->task_probe->cp) {
|
||||
char zname[255+1], 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;
|
||||
@@ -6416,7 +6449,7 @@ xfr_probe_send_probe(struct auth_xfer* xfr, struct module_env* env,
|
||||
(struct sockaddr*)&addr, addrlen, 0)) {
|
||||
char zname[255+1], 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;
|
||||
@@ -6424,7 +6457,7 @@ xfr_probe_send_probe(struct auth_xfer* xfr, struct module_env* env,
|
||||
if(verbosity >= VERB_ALGO) {
|
||||
char zname[255+1], 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);
|
||||
}
|
||||
@@ -7768,7 +7801,8 @@ static void auth_zone_log(uint8_t* name, enum verbosity_value level,
|
||||
static int zonemd_dnssec_verify_rrset(struct auth_zone* z,
|
||||
struct module_env* env, struct module_stack* mods,
|
||||
struct ub_packed_rrset_key* dnskey, struct auth_data* node,
|
||||
struct auth_rrset* rrset, char** why_bogus, uint8_t* sigalg)
|
||||
struct auth_rrset* rrset, char** why_bogus, uint8_t* sigalg,
|
||||
char* reasonbuf, size_t reasonlen)
|
||||
{
|
||||
struct ub_packed_rrset_key pk;
|
||||
enum sec_status sec;
|
||||
@@ -7798,7 +7832,7 @@ static int zonemd_dnssec_verify_rrset(struct auth_zone* z,
|
||||
"zonemd: verify %s RRset with DNSKEY", typestr);
|
||||
}
|
||||
sec = dnskeyset_verify_rrset(env, ve, &pk, dnskey, sigalg, why_bogus, NULL,
|
||||
LDNS_SECTION_ANSWER, NULL, &verified);
|
||||
LDNS_SECTION_ANSWER, NULL, &verified, reasonbuf, reasonlen);
|
||||
if(sec == sec_status_secure) {
|
||||
return 1;
|
||||
}
|
||||
@@ -7841,7 +7875,8 @@ static int nsec3_of_param_has_type(struct auth_rrset* nsec3, int algo,
|
||||
static int zonemd_check_dnssec_absence(struct auth_zone* z,
|
||||
struct module_env* env, struct module_stack* mods,
|
||||
struct ub_packed_rrset_key* dnskey, struct auth_data* apex,
|
||||
char** reason, char** why_bogus, uint8_t* sigalg)
|
||||
char** reason, char** why_bogus, uint8_t* sigalg, char* reasonbuf,
|
||||
size_t reasonlen)
|
||||
{
|
||||
struct auth_rrset* nsec = NULL;
|
||||
if(!apex) {
|
||||
@@ -7853,7 +7888,7 @@ static int zonemd_check_dnssec_absence(struct auth_zone* z,
|
||||
struct ub_packed_rrset_key pk;
|
||||
/* dnssec verify the NSEC */
|
||||
if(!zonemd_dnssec_verify_rrset(z, env, mods, dnskey, apex,
|
||||
nsec, why_bogus, sigalg)) {
|
||||
nsec, why_bogus, sigalg, reasonbuf, reasonlen)) {
|
||||
*reason = "DNSSEC verify failed for NSEC RRset";
|
||||
return 0;
|
||||
}
|
||||
@@ -7896,7 +7931,7 @@ static int zonemd_check_dnssec_absence(struct auth_zone* z,
|
||||
}
|
||||
/* dnssec verify the NSEC3 */
|
||||
if(!zonemd_dnssec_verify_rrset(z, env, mods, dnskey, match,
|
||||
nsec3, why_bogus, sigalg)) {
|
||||
nsec3, why_bogus, sigalg, reasonbuf, reasonlen)) {
|
||||
*reason = "DNSSEC verify failed for NSEC3 RRset";
|
||||
return 0;
|
||||
}
|
||||
@@ -7918,7 +7953,7 @@ static int zonemd_check_dnssec_soazonemd(struct auth_zone* z,
|
||||
struct module_env* env, struct module_stack* mods,
|
||||
struct ub_packed_rrset_key* dnskey, struct auth_data* apex,
|
||||
struct auth_rrset* zonemd_rrset, char** reason, char** why_bogus,
|
||||
uint8_t* sigalg)
|
||||
uint8_t* sigalg, char* reasonbuf, size_t reasonlen)
|
||||
{
|
||||
struct auth_rrset* soa;
|
||||
if(!apex) {
|
||||
@@ -7931,12 +7966,12 @@ static int zonemd_check_dnssec_soazonemd(struct auth_zone* z,
|
||||
return 0;
|
||||
}
|
||||
if(!zonemd_dnssec_verify_rrset(z, env, mods, dnskey, apex, soa,
|
||||
why_bogus, sigalg)) {
|
||||
why_bogus, sigalg, reasonbuf, reasonlen)) {
|
||||
*reason = "DNSSEC verify failed for SOA RRset";
|
||||
return 0;
|
||||
}
|
||||
if(!zonemd_dnssec_verify_rrset(z, env, mods, dnskey, apex,
|
||||
zonemd_rrset, why_bogus, sigalg)) {
|
||||
zonemd_rrset, why_bogus, sigalg, reasonbuf, reasonlen)) {
|
||||
*reason = "DNSSEC verify failed for ZONEMD RRset";
|
||||
return 0;
|
||||
}
|
||||
@@ -8004,6 +8039,7 @@ auth_zone_verify_zonemd_with_key(struct auth_zone* z, struct module_env* env,
|
||||
struct module_stack* mods, struct ub_packed_rrset_key* dnskey,
|
||||
int is_insecure, char** result, uint8_t* sigalg)
|
||||
{
|
||||
char reasonbuf[256];
|
||||
char* reason = NULL, *why_bogus = NULL;
|
||||
struct auth_data* apex = NULL;
|
||||
struct auth_rrset* zonemd_rrset = NULL;
|
||||
@@ -8032,7 +8068,8 @@ auth_zone_verify_zonemd_with_key(struct auth_zone* z, struct module_env* env,
|
||||
} else if(!zonemd_rrset && dnskey && !is_insecure) {
|
||||
/* fetch, DNSSEC verify, and check NSEC/NSEC3 */
|
||||
if(!zonemd_check_dnssec_absence(z, env, mods, dnskey, apex,
|
||||
&reason, &why_bogus, sigalg)) {
|
||||
&reason, &why_bogus, sigalg, reasonbuf,
|
||||
sizeof(reasonbuf))) {
|
||||
auth_zone_zonemd_fail(z, env, reason, why_bogus, result);
|
||||
return;
|
||||
}
|
||||
@@ -8040,7 +8077,8 @@ auth_zone_verify_zonemd_with_key(struct auth_zone* z, struct module_env* env,
|
||||
} else if(zonemd_rrset && dnskey && !is_insecure) {
|
||||
/* check DNSSEC verify of SOA and ZONEMD */
|
||||
if(!zonemd_check_dnssec_soazonemd(z, env, mods, dnskey, apex,
|
||||
zonemd_rrset, &reason, &why_bogus, sigalg)) {
|
||||
zonemd_rrset, &reason, &why_bogus, sigalg, reasonbuf,
|
||||
sizeof(reasonbuf))) {
|
||||
auth_zone_zonemd_fail(z, env, reason, why_bogus, result);
|
||||
return;
|
||||
}
|
||||
@@ -8097,6 +8135,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.
|
||||
*/
|
||||
@@ -8104,7 +8144,8 @@ static struct ub_packed_rrset_key*
|
||||
zonemd_get_dnskey_from_anchor(struct auth_zone* z, struct module_env* env,
|
||||
struct module_stack* mods, struct trust_anchor* anchor,
|
||||
int* is_insecure, char** why_bogus,
|
||||
struct ub_packed_rrset_key* keystorage)
|
||||
struct ub_packed_rrset_key* keystorage, char* reasonbuf,
|
||||
size_t reasonlen)
|
||||
{
|
||||
struct auth_data* apex;
|
||||
struct auth_rrset* dnskey_rrset;
|
||||
@@ -8140,7 +8181,8 @@ zonemd_get_dnskey_from_anchor(struct auth_zone* z, struct module_env* env,
|
||||
auth_zone_log(z->name, VERB_QUERY,
|
||||
"zonemd: verify DNSKEY RRset with trust anchor");
|
||||
sec = val_verify_DNSKEY_with_TA(env, ve, keystorage, anchor->ds_rrset,
|
||||
anchor->dnskey_rrset, NULL, why_bogus, NULL, NULL);
|
||||
anchor->dnskey_rrset, NULL, why_bogus, NULL, NULL, reasonbuf,
|
||||
reasonlen);
|
||||
regional_free_all(env->scratch);
|
||||
if(sec == sec_status_secure) {
|
||||
/* success */
|
||||
@@ -8163,7 +8205,8 @@ static struct ub_packed_rrset_key*
|
||||
auth_zone_verify_zonemd_key_with_ds(struct auth_zone* z,
|
||||
struct module_env* env, struct module_stack* mods,
|
||||
struct ub_packed_rrset_key* ds, int* is_insecure, char** why_bogus,
|
||||
struct ub_packed_rrset_key* keystorage, uint8_t* sigalg)
|
||||
struct ub_packed_rrset_key* keystorage, uint8_t* sigalg,
|
||||
char* reasonbuf, size_t reasonlen)
|
||||
{
|
||||
struct auth_data* apex;
|
||||
struct auth_rrset* dnskey_rrset;
|
||||
@@ -8199,7 +8242,7 @@ auth_zone_verify_zonemd_key_with_ds(struct auth_zone* z,
|
||||
keystorage->rk.rrset_class = htons(z->dclass);
|
||||
auth_zone_log(z->name, VERB_QUERY, "zonemd: verify zone DNSKEY with DS");
|
||||
sec = val_verify_DNSKEY_with_DS(env, ve, keystorage, ds, sigalg,
|
||||
why_bogus, NULL, NULL);
|
||||
why_bogus, NULL, NULL, reasonbuf, reasonlen);
|
||||
regional_free_all(env->scratch);
|
||||
if(sec == sec_status_secure) {
|
||||
/* success */
|
||||
@@ -8225,6 +8268,7 @@ void auth_zonemd_dnskey_lookup_callback(void* arg, int rcode, sldns_buffer* buf,
|
||||
{
|
||||
struct auth_zone* z = (struct auth_zone*)arg;
|
||||
struct module_env* env;
|
||||
char reasonbuf[256];
|
||||
char* reason = NULL, *ds_bogus = NULL, *typestr="DNSKEY";
|
||||
struct ub_packed_rrset_key* dnskey = NULL, *ds = NULL;
|
||||
int is_insecure = 0, downprot;
|
||||
@@ -8336,7 +8380,8 @@ void auth_zonemd_dnskey_lookup_callback(void* arg, int rcode, sldns_buffer* buf,
|
||||
if(!reason && !is_insecure && !dnskey && ds) {
|
||||
dnskey = auth_zone_verify_zonemd_key_with_ds(z, env,
|
||||
&env->mesh->mods, ds, &is_insecure, &ds_bogus,
|
||||
&keystorage, downprot?sigalg:NULL);
|
||||
&keystorage, downprot?sigalg:NULL, reasonbuf,
|
||||
sizeof(reasonbuf));
|
||||
if(!dnskey && !is_insecure && !reason)
|
||||
reason = "DNSKEY verify with DS failed";
|
||||
}
|
||||
@@ -8344,6 +8389,7 @@ void auth_zonemd_dnskey_lookup_callback(void* arg, int rcode, sldns_buffer* buf,
|
||||
if(reason) {
|
||||
auth_zone_zonemd_fail(z, env, reason, ds_bogus, NULL);
|
||||
lock_rw_unlock(&z->lock);
|
||||
regional_free_all(env->scratch);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -8428,6 +8474,7 @@ zonemd_lookup_dnskey(struct auth_zone* z, struct module_env* env)
|
||||
void auth_zone_verify_zonemd(struct auth_zone* z, struct module_env* env,
|
||||
struct module_stack* mods, char** result, int offline, int only_online)
|
||||
{
|
||||
char reasonbuf[256];
|
||||
char* reason = NULL, *why_bogus = NULL;
|
||||
struct trust_anchor* anchor = NULL;
|
||||
struct ub_packed_rrset_key* dnskey = NULL;
|
||||
@@ -8462,7 +8509,8 @@ void auth_zone_verify_zonemd(struct auth_zone* z, struct module_env* env,
|
||||
}
|
||||
/* equal to trustanchor, no need for online lookups */
|
||||
dnskey = zonemd_get_dnskey_from_anchor(z, env, mods, anchor,
|
||||
&is_insecure, &why_bogus, &keystorage);
|
||||
&is_insecure, &why_bogus, &keystorage, reasonbuf,
|
||||
sizeof(reasonbuf));
|
||||
lock_basic_unlock(&anchor->lock);
|
||||
if(!dnskey && !reason && !is_insecure) {
|
||||
reason = "verify DNSKEY RRset with trust anchor failed";
|
||||
@@ -8488,6 +8536,7 @@ void auth_zone_verify_zonemd(struct auth_zone* z, struct module_env* env,
|
||||
|
||||
if(reason) {
|
||||
auth_zone_zonemd_fail(z, env, reason, why_bogus, result);
|
||||
regional_free_all(env->scratch);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
Vendored
+80
-68
@@ -80,6 +80,7 @@ store_rrsets(struct module_env* env, struct reply_info* rep, time_t now,
|
||||
struct regional* region, time_t qstarttime)
|
||||
{
|
||||
size_t i;
|
||||
time_t ttl, min_ttl = rep->ttl;
|
||||
/* see if rrset already exists in cache, if not insert it. */
|
||||
for(i=0; i<rep->rrset_count; i++) {
|
||||
rep->ref[i].key = rep->rrsets[i];
|
||||
@@ -87,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 */
|
||||
@@ -95,7 +96,8 @@ store_rrsets(struct module_env* env, struct reply_info* rep, time_t now,
|
||||
struct ub_packed_rrset_key* ck;
|
||||
lock_rw_rdlock(&rep->ref[i].key->entry.lock);
|
||||
/* if deleted rrset, do not copy it */
|
||||
if(rep->ref[i].key->id == 0)
|
||||
if(rep->ref[i].key->id == 0 ||
|
||||
rep->ref[i].id != rep->ref[i].key->id)
|
||||
ck = NULL;
|
||||
else ck = packed_rrset_copy_region(
|
||||
rep->ref[i].key, region, now);
|
||||
@@ -108,11 +110,28 @@ 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;
|
||||
/* ref was updated; make sure the message ttl is
|
||||
* updated to the minimum of the current rrsets. */
|
||||
lock_rw_rdlock(&rep->ref[i].key->entry.lock);
|
||||
/* if deleted, skip ttl update. */
|
||||
if(rep->ref[i].key->id != 0 &&
|
||||
rep->ref[i].id == rep->ref[i].key->id) {
|
||||
ttl = ((struct packed_rrset_data*)
|
||||
rep->rrsets[i]->entry.data)->ttl;
|
||||
if(ttl < min_ttl) min_ttl = ttl;
|
||||
}
|
||||
lock_rw_unlock(&rep->ref[i].key->entry.lock);
|
||||
}
|
||||
}
|
||||
if(min_ttl < rep->ttl) {
|
||||
rep->ttl = min_ttl;
|
||||
rep->prefetch_ttl = PREFETCH_TTL_CALC(rep->ttl);
|
||||
rep->serve_expired_ttl = rep->ttl + SERVE_EXPIRED_TTL;
|
||||
}
|
||||
}
|
||||
|
||||
/** delete message from message cache */
|
||||
@@ -143,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;
|
||||
}
|
||||
@@ -178,51 +197,12 @@ 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);
|
||||
}
|
||||
|
||||
/** see if an rrset is expired above the qname, return upper qname. */
|
||||
static int
|
||||
rrset_expired_above(struct module_env* env, uint8_t** qname, size_t* qnamelen,
|
||||
uint16_t searchtype, uint16_t qclass, time_t now, uint8_t* expiretop,
|
||||
size_t expiretoplen)
|
||||
{
|
||||
struct ub_packed_rrset_key *rrset;
|
||||
uint8_t lablen;
|
||||
|
||||
while(*qnamelen > 0) {
|
||||
/* look one label higher */
|
||||
lablen = **qname;
|
||||
*qname += lablen + 1;
|
||||
*qnamelen -= lablen + 1;
|
||||
if(*qnamelen <= 0)
|
||||
break;
|
||||
|
||||
/* looks up with a time of 0, to see expired entries */
|
||||
if((rrset = rrset_cache_lookup(env->rrset_cache, *qname,
|
||||
*qnamelen, searchtype, qclass, 0, 0, 0))) {
|
||||
struct packed_rrset_data* data =
|
||||
(struct packed_rrset_data*)rrset->entry.data;
|
||||
if(now > data->ttl) {
|
||||
/* it is expired, this is not wanted */
|
||||
lock_rw_unlock(&rrset->entry.lock);
|
||||
log_nametypeclass(VERB_ALGO, "this rrset is expired", *qname, searchtype, qclass);
|
||||
return 1;
|
||||
}
|
||||
/* it is not expired, continue looking */
|
||||
lock_rw_unlock(&rrset->entry.lock);
|
||||
}
|
||||
|
||||
/* do not look above the expiretop. */
|
||||
if(expiretop && *qnamelen == expiretoplen &&
|
||||
query_dname_compare(*qname, expiretop)==0)
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** find closest NS or DNAME and returns the rrset (locked) */
|
||||
static struct ub_packed_rrset_key*
|
||||
find_closest_of_type(struct module_env* env, uint8_t* qname, size_t qnamelen,
|
||||
@@ -256,12 +236,12 @@ find_closest_of_type(struct module_env* env, uint8_t* qname, size_t qnamelen,
|
||||
/* check for expiry, but we have to let go of the rrset
|
||||
* for the lock ordering */
|
||||
lock_rw_unlock(&rrset->entry.lock);
|
||||
/* the expired_above function always takes off one
|
||||
* label (if qnamelen>0) and returns the final qname
|
||||
* where it searched, so we can continue from there
|
||||
* turning the O N*N search into O N. */
|
||||
if(!rrset_expired_above(env, &qname, &qnamelen,
|
||||
searchtype, qclass, now, expiretop,
|
||||
/* the rrset_cache_expired_above function always takes
|
||||
* off one label (if qnamelen>0) and returns the final
|
||||
* qname where it searched, so we can continue from
|
||||
* there turning the O N*N search into O N. */
|
||||
if(!rrset_cache_expired_above(env->rrset_cache, &qname,
|
||||
&qnamelen, searchtype, qclass, now, expiretop,
|
||||
expiretoplen)) {
|
||||
/* we want to return rrset, but it may be
|
||||
* gone from cache, if so, just loop like
|
||||
@@ -367,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);
|
||||
@@ -379,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;
|
||||
@@ -390,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)) {
|
||||
@@ -411,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)) {
|
||||
@@ -426,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);
|
||||
@@ -614,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;
|
||||
@@ -648,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;
|
||||
@@ -731,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;
|
||||
@@ -770,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;
|
||||
@@ -818,7 +801,7 @@ synth_dname_msg(struct ub_packed_rrset_key* rrset, struct regional* region,
|
||||
if(!newd)
|
||||
return NULL;
|
||||
ck->entry.data = newd;
|
||||
newd->ttl = 0; /* 0 for synthesized CNAME TTL */
|
||||
newd->ttl = d->ttl - now; /* RFC6672: synth CNAME TTL == DNAME TTL */
|
||||
newd->count = 1;
|
||||
newd->rrsig_count = 0;
|
||||
newd->trust = rrset_trust_ans_noAA;
|
||||
@@ -1077,6 +1060,35 @@ dns_cache_store(struct module_env* env, struct query_info* msgqinf,
|
||||
struct regional* region, uint32_t flags, time_t qstarttime)
|
||||
{
|
||||
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, 0);
|
||||
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)) {
|
||||
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
+2
-1
@@ -202,10 +202,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
+186
-11
@@ -60,6 +60,16 @@
|
||||
* 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;
|
||||
|
||||
@@ -234,6 +244,81 @@ setup_domain_limits(struct infra_cache* infra, struct config_file* cfg)
|
||||
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)
|
||||
{
|
||||
rbtree_type* tree;
|
||||
struct sockaddr_storage addr;
|
||||
int net;
|
||||
socklen_t addrlen;
|
||||
struct wait_limit_netblock_info* d;
|
||||
|
||||
if(!netblockstrtoaddr(str, 0, &addr, &addrlen, &net)) {
|
||||
log_err("cannot parse wait limit netblock '%s'", str);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* 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)
|
||||
return d;
|
||||
|
||||
/* create it */
|
||||
d = (struct wait_limit_netblock_info*)calloc(1, sizeof(*d));
|
||||
if(!d)
|
||||
return NULL;
|
||||
d->limit = -1;
|
||||
if(!addr_tree_insert(tree, &d->node, &addr, addrlen, net)) {
|
||||
log_err("duplicate element in domainlimit tree");
|
||||
free(d);
|
||||
return NULL;
|
||||
}
|
||||
return d;
|
||||
}
|
||||
|
||||
|
||||
/** insert wait limit information into lookup tree */
|
||||
static int
|
||||
infra_wait_limit_netblock_insert(struct infra_cache* infra,
|
||||
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);
|
||||
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);
|
||||
if(!d)
|
||||
return 0;
|
||||
d->limit = atoi(p->str2);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** setup wait limits tree (0 on failure) */
|
||||
static int
|
||||
setup_wait_limits(struct infra_cache* infra, struct config_file* cfg)
|
||||
{
|
||||
addr_tree_init(&infra->wait_limits_netblock);
|
||||
addr_tree_init(&infra->wait_limits_cookie_netblock);
|
||||
if(!infra_wait_limit_netblock_insert(infra, cfg))
|
||||
return 0;
|
||||
addr_tree_init_parents(&infra->wait_limits_netblock);
|
||||
addr_tree_init_parents(&infra->wait_limits_cookie_netblock);
|
||||
return 1;
|
||||
}
|
||||
|
||||
struct infra_cache*
|
||||
infra_create(struct config_file* cfg)
|
||||
{
|
||||
@@ -267,7 +352,12 @@ infra_create(struct config_file* cfg)
|
||||
infra_delete(infra);
|
||||
return NULL;
|
||||
}
|
||||
if(!setup_wait_limits(infra, cfg)) {
|
||||
infra_delete(infra);
|
||||
return NULL;
|
||||
}
|
||||
infra_ip_ratelimit = cfg->ip_ratelimit;
|
||||
infra_ip_ratelimit_cookie = cfg->ip_ratelimit_cookie;
|
||||
infra->client_ip_rates = slabhash_create(cfg->ip_ratelimit_slabs,
|
||||
INFRA_HOST_STARTSIZE, cfg->ip_ratelimit_size, &ip_rate_sizefunc,
|
||||
&ip_rate_compfunc, &ip_rate_delkeyfunc, &ip_rate_deldatafunc, NULL);
|
||||
@@ -287,6 +377,12 @@ static void domain_limit_free(rbnode_type* n, void* ATTR_UNUSED(arg))
|
||||
}
|
||||
}
|
||||
|
||||
/** delete wait_limit_netblock_info entries */
|
||||
static void wait_limit_netblock_del(rbnode_type* n, void* ATTR_UNUSED(arg))
|
||||
{
|
||||
free(n);
|
||||
}
|
||||
|
||||
void
|
||||
infra_delete(struct infra_cache* infra)
|
||||
{
|
||||
@@ -296,6 +392,10 @@ infra_delete(struct infra_cache* infra)
|
||||
slabhash_delete(infra->domain_rates);
|
||||
traverse_postorder(&infra->domain_limits, domain_limit_free, NULL);
|
||||
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);
|
||||
free(infra);
|
||||
}
|
||||
|
||||
@@ -309,6 +409,7 @@ infra_adjust(struct infra_cache* infra, struct config_file* cfg)
|
||||
infra->infra_keep_probing = cfg->infra_keep_probing;
|
||||
infra_dp_ratelimit = cfg->ratelimit;
|
||||
infra_ip_ratelimit = cfg->ip_ratelimit;
|
||||
infra_ip_ratelimit_cookie = cfg->ip_ratelimit_cookie;
|
||||
maxmem = cfg->infra_cache_numhosts * (sizeof(struct infra_key)+
|
||||
sizeof(struct infra_data)+INFRA_BYTES_NAME);
|
||||
/* divide cachesize by slabs and multiply by slabs, because if the
|
||||
@@ -567,7 +668,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 = RTT_MAX_TIMEOUT-1000;
|
||||
data->rtt.rto = STILL_USEFUL_TIMEOUT;
|
||||
lock_rw_unlock(&e->lock);
|
||||
}
|
||||
|
||||
@@ -707,7 +808,7 @@ infra_get_lame_rtt(struct infra_cache* infra,
|
||||
&& infra->infra_keep_probing) {
|
||||
/* single probe, keep probing */
|
||||
if(*rtt >= USEFUL_SERVER_TOP_TIMEOUT)
|
||||
*rtt = USEFUL_SERVER_TOP_TIMEOUT-1000;
|
||||
*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 */
|
||||
@@ -715,26 +816,23 @@ 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 = USEFUL_SERVER_TOP_TIMEOUT-1000;
|
||||
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 = USEFUL_SERVER_TOP_TIMEOUT-1000;
|
||||
else *rtt = STILL_USEFUL_TIMEOUT;
|
||||
} else {
|
||||
if(host->timeout_other >= TIMEOUT_COUNT_MAX)
|
||||
*rtt = USEFUL_SERVER_TOP_TIMEOUT;
|
||||
else *rtt = USEFUL_SERVER_TOP_TIMEOUT-1000;
|
||||
else *rtt = STILL_USEFUL_TIMEOUT;
|
||||
}
|
||||
}
|
||||
/* expired entry */
|
||||
if(timenow > host->ttl) {
|
||||
|
||||
/* see if this can be a re-probe of an unresponsive server */
|
||||
/* minus 1000 because that is outside of the RTTBAND, so
|
||||
* blacklisted servers stay blacklisted if this is chosen */
|
||||
if(host->rtt.rto >= USEFUL_SERVER_TOP_TIMEOUT) {
|
||||
lock_rw_unlock(&e->lock);
|
||||
*rtt = USEFUL_SERVER_TOP_TIMEOUT-1000;
|
||||
*rtt = STILL_USEFUL_TIMEOUT;
|
||||
*lame = 0;
|
||||
*dnsseclame = 0;
|
||||
*reclame = 0;
|
||||
@@ -880,7 +978,8 @@ static void infra_create_ratedata(struct infra_cache* infra,
|
||||
|
||||
/** create rate data item for ip address */
|
||||
static void infra_ip_create_ratedata(struct infra_cache* infra,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen, time_t timenow)
|
||||
struct sockaddr_storage* addr, socklen_t addrlen, time_t timenow,
|
||||
int mesh_wait)
|
||||
{
|
||||
hashvalue_type h = hash_addr(addr, addrlen, 0);
|
||||
struct ip_rate_key* k = (struct ip_rate_key*)calloc(1, sizeof(*k));
|
||||
@@ -898,6 +997,7 @@ static void infra_ip_create_ratedata(struct infra_cache* infra,
|
||||
k->entry.data = d;
|
||||
d->qps[0] = 1;
|
||||
d->timestamp[0] = timenow;
|
||||
d->mesh_wait = mesh_wait;
|
||||
slabhash_insert(infra->client_ip_rates, h, &k->entry, d, NULL);
|
||||
}
|
||||
|
||||
@@ -1121,6 +1221,81 @@ int infra_ip_ratelimit_inc(struct infra_cache* infra,
|
||||
}
|
||||
|
||||
/* create */
|
||||
infra_ip_create_ratedata(infra, addr, addrlen, timenow);
|
||||
infra_ip_create_ratedata(infra, addr, addrlen, timenow, 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int infra_wait_limit_allowed(struct infra_cache* infra, struct comm_reply* rep,
|
||||
int cookie_valid, struct config_file* cfg)
|
||||
{
|
||||
struct lruhash_entry* entry;
|
||||
if(cfg->wait_limit == 0)
|
||||
return 1;
|
||||
|
||||
entry = infra_find_ip_ratedata(infra, &rep->client_addr,
|
||||
rep->client_addrlen, 0);
|
||||
if(entry) {
|
||||
rbtree_type* tree;
|
||||
struct wait_limit_netblock_info* w;
|
||||
struct rate_data* d = (struct rate_data*)entry->data;
|
||||
int mesh_wait = d->mesh_wait;
|
||||
lock_rw_unlock(&entry->lock);
|
||||
|
||||
/* have the wait amount, check how much is allowed */
|
||||
if(cookie_valid)
|
||||
tree = &infra->wait_limits_cookie_netblock;
|
||||
else tree = &infra->wait_limits_netblock;
|
||||
w = (struct wait_limit_netblock_info*)addr_tree_lookup(tree,
|
||||
&rep->client_addr, rep->client_addrlen);
|
||||
if(w) {
|
||||
if(w->limit != -1 && mesh_wait > w->limit)
|
||||
return 0;
|
||||
} else {
|
||||
/* if there is no IP netblock specific information,
|
||||
* use the configured value. */
|
||||
if(mesh_wait > (cookie_valid?cfg->wait_limit_cookie:
|
||||
cfg->wait_limit))
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
void infra_wait_limit_inc(struct infra_cache* infra, struct comm_reply* rep,
|
||||
time_t timenow, struct config_file* cfg)
|
||||
{
|
||||
struct lruhash_entry* entry;
|
||||
if(cfg->wait_limit == 0)
|
||||
return;
|
||||
|
||||
/* Find it */
|
||||
entry = infra_find_ip_ratedata(infra, &rep->client_addr,
|
||||
rep->client_addrlen, 1);
|
||||
if(entry) {
|
||||
struct rate_data* d = (struct rate_data*)entry->data;
|
||||
d->mesh_wait++;
|
||||
lock_rw_unlock(&entry->lock);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Create it */
|
||||
infra_ip_create_ratedata(infra, &rep->client_addr,
|
||||
rep->client_addrlen, timenow, 1);
|
||||
}
|
||||
|
||||
void infra_wait_limit_dec(struct infra_cache* infra, struct comm_reply* rep,
|
||||
struct config_file* cfg)
|
||||
{
|
||||
struct lruhash_entry* entry;
|
||||
if(cfg->wait_limit == 0)
|
||||
return;
|
||||
|
||||
entry = infra_find_ip_ratedata(infra, &rep->client_addr,
|
||||
rep->client_addrlen, 1);
|
||||
if(entry) {
|
||||
struct rate_data* d = (struct rate_data*)entry->data;
|
||||
if(d->mesh_wait > 0)
|
||||
d->mesh_wait--;
|
||||
lock_rw_unlock(&entry->lock);
|
||||
}
|
||||
}
|
||||
|
||||
Vendored
+29
-1
@@ -122,6 +122,10 @@ struct infra_cache {
|
||||
rbtree_type domain_limits;
|
||||
/** hash table with query rates per client ip: ip_rate_key, ip_rate_data */
|
||||
struct slabhash* client_ip_rates;
|
||||
/** tree of addr_tree_node, with wait_limit_netblock_info information */
|
||||
rbtree_type wait_limits_netblock;
|
||||
/** tree of addr_tree_node, with wait_limit_netblock_info information */
|
||||
rbtree_type wait_limits_cookie_netblock;
|
||||
};
|
||||
|
||||
/** ratelimit, unless overridden by domain_limits, 0 is off */
|
||||
@@ -184,10 +188,22 @@ struct rate_data {
|
||||
/** what the timestamp is of the qps array members, counter is
|
||||
* valid for that timestamp. Usually now and now-1. */
|
||||
time_t timestamp[RATE_WINDOW];
|
||||
/** the number of queries waiting in the mesh */
|
||||
int mesh_wait;
|
||||
};
|
||||
|
||||
#define ip_rate_data rate_data
|
||||
|
||||
/**
|
||||
* Data to store the configuration per netblock for the wait limit
|
||||
*/
|
||||
struct wait_limit_netblock_info {
|
||||
/** The addr tree node, this must be first. */
|
||||
struct addr_tree_node node;
|
||||
/** the limit on the amount */
|
||||
int limit;
|
||||
};
|
||||
|
||||
/** infra host cache default hash lookup size */
|
||||
#define INFRA_HOST_STARTSIZE 32
|
||||
/** bytes per zonename reserved in the hostcache, dnamelen(zonename.com.) */
|
||||
@@ -218,7 +234,7 @@ struct infra_cache* infra_adjust(struct infra_cache* infra,
|
||||
struct config_file* cfg);
|
||||
|
||||
/**
|
||||
* Plain find infra data function (used by the the other functions)
|
||||
* Plain find infra data function (used by the other functions)
|
||||
* @param infra: infrastructure cache.
|
||||
* @param addr: host address.
|
||||
* @param addrlen: length of addr.
|
||||
@@ -474,4 +490,16 @@ void ip_rate_delkeyfunc(void* d, void* arg);
|
||||
/* delete data */
|
||||
#define ip_rate_deldatafunc rate_deldatafunc
|
||||
|
||||
/** See if the IP address can have another reply in the wait limit */
|
||||
int infra_wait_limit_allowed(struct infra_cache* infra, struct comm_reply* rep,
|
||||
int cookie_valid, struct config_file* cfg);
|
||||
|
||||
/** Increment number of waiting replies for IP */
|
||||
void infra_wait_limit_inc(struct infra_cache* infra, struct comm_reply* rep,
|
||||
time_t timenow, struct config_file* cfg);
|
||||
|
||||
/** Decrement number of waiting replies for IP */
|
||||
void infra_wait_limit_dec(struct infra_cache* infra, struct comm_reply* rep,
|
||||
struct config_file* cfg);
|
||||
|
||||
#endif /* SERVICES_CACHE_INFRA_H */
|
||||
|
||||
Vendored
+90
-3
@@ -46,6 +46,7 @@
|
||||
#include "util/data/packed_rrset.h"
|
||||
#include "util/data/msgreply.h"
|
||||
#include "util/data/msgparse.h"
|
||||
#include "util/data/dname.h"
|
||||
#include "util/regional.h"
|
||||
#include "util/alloc.h"
|
||||
#include "util/net_help.h"
|
||||
@@ -127,6 +128,9 @@ 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, 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
|
||||
* secure is preferred */
|
||||
@@ -136,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)
|
||||
@@ -151,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) {
|
||||
@@ -440,6 +444,89 @@ rrset_check_sec_status(struct rrset_cache* r,
|
||||
lock_rw_unlock(&e->lock);
|
||||
}
|
||||
|
||||
void
|
||||
rrset_cache_remove_above(struct rrset_cache* r, uint8_t** qname, size_t*
|
||||
qnamelen, uint16_t searchtype, uint16_t qclass, time_t now, uint8_t*
|
||||
qnametop, size_t qnametoplen)
|
||||
{
|
||||
struct ub_packed_rrset_key *rrset;
|
||||
uint8_t lablen;
|
||||
|
||||
while(*qnamelen > 0) {
|
||||
/* look one label higher */
|
||||
lablen = **qname;
|
||||
*qname += lablen + 1;
|
||||
*qnamelen -= lablen + 1;
|
||||
if(*qnamelen <= 0)
|
||||
return;
|
||||
|
||||
/* stop at qnametop */
|
||||
if(qnametop && *qnamelen == qnametoplen &&
|
||||
query_dname_compare(*qname, qnametop)==0)
|
||||
return;
|
||||
|
||||
if(verbosity >= VERB_ALGO) {
|
||||
/* looks up with a time of 0, to see expired entries */
|
||||
if((rrset = rrset_cache_lookup(r, *qname,
|
||||
*qnamelen, searchtype, qclass, 0, 0, 0))) {
|
||||
struct packed_rrset_data* data =
|
||||
(struct packed_rrset_data*)rrset->entry.data;
|
||||
int expired = (now > data->ttl);
|
||||
lock_rw_unlock(&rrset->entry.lock);
|
||||
if(expired)
|
||||
log_nametypeclass(verbosity, "this "
|
||||
"(grand)parent rrset will be "
|
||||
"removed (expired)",
|
||||
*qname, searchtype, qclass);
|
||||
else log_nametypeclass(verbosity, "this "
|
||||
"(grand)parent rrset will be "
|
||||
"removed",
|
||||
*qname, searchtype, qclass);
|
||||
}
|
||||
}
|
||||
rrset_cache_remove(r, *qname, *qnamelen, searchtype, qclass, 0);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
rrset_cache_expired_above(struct rrset_cache* r, uint8_t** qname, size_t*
|
||||
qnamelen, uint16_t searchtype, uint16_t qclass, time_t now, uint8_t*
|
||||
qnametop, size_t qnametoplen)
|
||||
{
|
||||
struct ub_packed_rrset_key *rrset;
|
||||
uint8_t lablen;
|
||||
|
||||
while(*qnamelen > 0) {
|
||||
/* look one label higher */
|
||||
lablen = **qname;
|
||||
*qname += lablen + 1;
|
||||
*qnamelen -= lablen + 1;
|
||||
if(*qnamelen <= 0)
|
||||
break;
|
||||
|
||||
/* looks up with a time of 0, to see expired entries */
|
||||
if((rrset = rrset_cache_lookup(r, *qname,
|
||||
*qnamelen, searchtype, qclass, 0, 0, 0))) {
|
||||
struct packed_rrset_data* data =
|
||||
(struct packed_rrset_data*)rrset->entry.data;
|
||||
if(now > data->ttl) {
|
||||
/* it is expired, this is not wanted */
|
||||
lock_rw_unlock(&rrset->entry.lock);
|
||||
log_nametypeclass(VERB_ALGO, "this rrset is expired", *qname, searchtype, qclass);
|
||||
return 1;
|
||||
}
|
||||
/* it is not expired, continue looking */
|
||||
lock_rw_unlock(&rrset->entry.lock);
|
||||
}
|
||||
|
||||
/* do not look above the qnametop. */
|
||||
if(qnametop && *qnamelen == qnametoplen &&
|
||||
query_dname_compare(*qname, qnametop)==0)
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void rrset_cache_remove(struct rrset_cache* r, uint8_t* nm, size_t nmlen,
|
||||
uint16_t type, uint16_t dclass, uint32_t flags)
|
||||
{
|
||||
|
||||
Vendored
+31
@@ -231,6 +231,37 @@ void rrset_update_sec_status(struct rrset_cache* r,
|
||||
void rrset_check_sec_status(struct rrset_cache* r,
|
||||
struct ub_packed_rrset_key* rrset, time_t now);
|
||||
|
||||
/**
|
||||
* Removes rrsets above the qname, returns upper qname.
|
||||
* @param r: the rrset cache.
|
||||
* @param qname: the start qname, also used as the output.
|
||||
* @param qnamelen: length of qname, updated when it returns.
|
||||
* @param searchtype: qtype to search for.
|
||||
* @param qclass: qclass to search for.
|
||||
* @param now: current time.
|
||||
* @param qnametop: the top qname to stop removal (it is not removed).
|
||||
* @param qnametoplen: length of qnametop.
|
||||
*/
|
||||
void rrset_cache_remove_above(struct rrset_cache* r, uint8_t** qname,
|
||||
size_t* qnamelen, uint16_t searchtype, uint16_t qclass, time_t now,
|
||||
uint8_t* qnametop, size_t qnametoplen);
|
||||
|
||||
/**
|
||||
* Sees if an rrset is expired above the qname, returns upper qname.
|
||||
* @param r: the rrset cache.
|
||||
* @param qname: the start qname, also used as the output.
|
||||
* @param qnamelen: length of qname, updated when it returns.
|
||||
* @param searchtype: qtype to search for.
|
||||
* @param qclass: qclass to search for.
|
||||
* @param now: current time.
|
||||
* @param qnametop: the top qname, don't look farther than that.
|
||||
* @param qnametoplen: length of qnametop.
|
||||
* @return true if there is an expired rrset above, false otherwise.
|
||||
*/
|
||||
int rrset_cache_expired_above(struct rrset_cache* r, uint8_t** qname,
|
||||
size_t* qnamelen, uint16_t searchtype, uint16_t qclass, time_t now,
|
||||
uint8_t* qnametop, size_t qnametoplen);
|
||||
|
||||
/**
|
||||
* Remove an rrset from the cache, by name and type and flags
|
||||
* @param r: rrset cache
|
||||
|
||||
+2532
-55
File diff suppressed because it is too large
Load Diff
+406
-7
@@ -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,18 +106,22 @@ 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
|
||||
};
|
||||
|
||||
/*
|
||||
* socket properties (just like NSD nsd_socket structure definition)
|
||||
*/
|
||||
struct unbound_socket {
|
||||
/** socket-address structure */
|
||||
struct addrinfo* addr;
|
||||
/** the address of the socket */
|
||||
struct sockaddr* addr;
|
||||
/** length of the address */
|
||||
socklen_t addrlen;
|
||||
/** socket descriptor returned by socket() syscall */
|
||||
int s;
|
||||
/** address family (AF_INET/IF_INET6) */
|
||||
/** address family (AF_INET/AF_INET6) */
|
||||
int fam;
|
||||
/** ACL on the socket (listening interface) */
|
||||
struct acl_addr* acl;
|
||||
@@ -186,6 +196,11 @@ int resolve_interface_names(char** ifs, int num_ifs,
|
||||
* @param tcp_conn_limit: TCP connection limit info.
|
||||
* @param sslctx: nonNULL if ssl context.
|
||||
* @param dtenv: nonNULL if dnstap enabled.
|
||||
* @param doq_table: the doq connection table, with shared information.
|
||||
* @param rnd: random state.
|
||||
* @param ssl_service_key: the SSL service key file.
|
||||
* @param ssl_service_pem: the SSL service pem file.
|
||||
* @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.
|
||||
@@ -196,8 +211,10 @@ 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* sslctx, struct dt_env* dtenv, struct doq_table* doq_table,
|
||||
struct ub_randstate* rnd, const char* ssl_service_key,
|
||||
const char* ssl_service_pem, struct config_file* cfg,
|
||||
comm_point_callback_type* cb, void *cb_arg);
|
||||
|
||||
/**
|
||||
* delete the listening structure
|
||||
@@ -276,11 +293,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
|
||||
@@ -450,6 +468,377 @@ 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 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_socket server tls context */
|
||||
int doq_socket_setup_ctx(struct doq_server_socket* doq_socket);
|
||||
|
||||
/** 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
|
||||
@@ -457,4 +846,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 */
|
||||
|
||||
+49
-38
@@ -242,7 +242,7 @@ lz_enter_zone_dname(struct local_zones* zones, uint8_t* nm, size_t len,
|
||||
}
|
||||
|
||||
/** enter a new zone */
|
||||
static struct local_zone*
|
||||
struct local_zone*
|
||||
lz_enter_zone(struct local_zones* zones, const char* name, const char* type,
|
||||
uint16_t dclass)
|
||||
{
|
||||
@@ -330,14 +330,16 @@ get_rr_nameclass(const char* str, uint8_t** nm, uint16_t* dclass,
|
||||
static struct local_rrset*
|
||||
local_data_find_type(struct local_data* data, uint16_t type, int alias_ok)
|
||||
{
|
||||
struct local_rrset* p;
|
||||
struct local_rrset* p, *cname = NULL;
|
||||
type = htons(type);
|
||||
for(p = data->rrsets; p; p = p->next) {
|
||||
if(p->rrset->rk.type == type)
|
||||
return p;
|
||||
if(alias_ok && p->rrset->rk.type == htons(LDNS_RR_TYPE_CNAME))
|
||||
return p;
|
||||
cname = p;
|
||||
}
|
||||
if(alias_ok)
|
||||
return cname;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -981,40 +983,43 @@ lz_enter_overrides(struct local_zones* zones, struct config_file* cfg)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** setup parent pointers, so that a lookup can be done for closest match */
|
||||
static void
|
||||
init_parents(struct local_zones* zones)
|
||||
/* return closest parent in the tree, NULL if none */
|
||||
static struct local_zone* find_closest_parent(struct local_zone* curr,
|
||||
struct local_zone* prev)
|
||||
{
|
||||
struct local_zone* node, *prev = NULL, *p;
|
||||
int m;
|
||||
lock_rw_wrlock(&zones->lock);
|
||||
RBTREE_FOR(node, struct local_zone*, &zones->ztree) {
|
||||
lock_rw_wrlock(&node->lock);
|
||||
node->parent = NULL;
|
||||
if(!prev || prev->dclass != node->dclass) {
|
||||
prev = node;
|
||||
lock_rw_unlock(&node->lock);
|
||||
continue;
|
||||
}
|
||||
(void)dname_lab_cmp(prev->name, prev->namelabs, node->name,
|
||||
node->namelabs, &m); /* we know prev is smaller */
|
||||
/* sort order like: . com. bla.com. zwb.com. net. */
|
||||
/* find the previous, or parent-parent-parent */
|
||||
for(p = prev; p; p = p->parent)
|
||||
/* looking for name with few labels, a parent */
|
||||
if(p->namelabs <= m) {
|
||||
/* ==: since prev matched m, this is closest*/
|
||||
/* <: prev matches more, but is not a parent,
|
||||
* this one is a (grand)parent */
|
||||
node->parent = p;
|
||||
break;
|
||||
}
|
||||
prev = node;
|
||||
struct local_zone* p;
|
||||
int m;
|
||||
if(!prev || prev->dclass != curr->dclass) return NULL;
|
||||
(void)dname_lab_cmp(prev->name, prev->namelabs, curr->name,
|
||||
curr->namelabs, &m); /* we know prev is smaller */
|
||||
/* sort order like: . com. bla.com. zwb.com. net. */
|
||||
/* find the previous, or parent-parent-parent */
|
||||
for(p = prev; p; p = p->parent) {
|
||||
/* looking for name with few labels, a parent */
|
||||
if(p->namelabs <= m) {
|
||||
/* ==: since prev matched m, this is closest*/
|
||||
/* <: prev matches more, but is not a parent,
|
||||
* this one is a (grand)parent */
|
||||
return p;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/** setup parent pointers, so that a lookup can be done for closest match */
|
||||
void
|
||||
lz_init_parents(struct local_zones* zones)
|
||||
{
|
||||
struct local_zone* node, *prev = NULL;
|
||||
lock_rw_wrlock(&zones->lock);
|
||||
RBTREE_FOR(node, struct local_zone*, &zones->ztree) {
|
||||
lock_rw_wrlock(&node->lock);
|
||||
node->parent = find_closest_parent(node, prev);
|
||||
prev = node;
|
||||
if(node->override_tree)
|
||||
addr_tree_init_parents(node->override_tree);
|
||||
lock_rw_unlock(&node->lock);
|
||||
}
|
||||
}
|
||||
lock_rw_unlock(&zones->lock);
|
||||
}
|
||||
|
||||
@@ -1034,7 +1039,7 @@ lz_setup_implicit(struct local_zones* zones, struct config_file* cfg)
|
||||
int nmlabs = 0;
|
||||
int match = 0; /* number of labels match count */
|
||||
|
||||
init_parents(zones); /* to enable local_zones_lookup() */
|
||||
lz_init_parents(zones); /* to enable local_zones_lookup() */
|
||||
for(p = cfg->local_data; p; p = p->next) {
|
||||
uint8_t* rr_name;
|
||||
uint16_t rr_class, rr_type;
|
||||
@@ -1200,7 +1205,7 @@ local_zones_apply_cfg(struct local_zones* zones, struct config_file* cfg)
|
||||
}
|
||||
|
||||
/* setup parent ptrs for lookup during data entry */
|
||||
init_parents(zones);
|
||||
lz_init_parents(zones);
|
||||
/* insert local zone tags */
|
||||
if(!lz_enter_zone_tags(zones, cfg)) {
|
||||
return 0;
|
||||
@@ -1532,7 +1537,7 @@ local_data_answer(struct local_zone* z, struct module_env* env,
|
||||
return 0; /* invalid cname */
|
||||
if(dname_is_wild(ctarget)) {
|
||||
/* synthesize cname target */
|
||||
struct packed_rrset_data* d;
|
||||
struct packed_rrset_data* d, *lr_d;
|
||||
/* -3 for wildcard label and root label from qname */
|
||||
size_t newtargetlen = qinfo->qname_len + ctargetlen - 3;
|
||||
|
||||
@@ -1560,8 +1565,10 @@ local_data_answer(struct local_zone* z, struct module_env* env,
|
||||
+ newtargetlen);
|
||||
if(!d)
|
||||
return 0; /* out of memory */
|
||||
lr_d = (struct packed_rrset_data*)lr->rrset->entry.data;
|
||||
qinfo->local_alias->rrset->entry.data = d;
|
||||
d->ttl = 0; /* 0 for synthesized CNAME TTL */
|
||||
d->ttl = lr_d->rr_ttl[0]; /* RFC6672-like behavior:
|
||||
synth CNAME TTL uses original TTL*/
|
||||
d->count = 1;
|
||||
d->rrsig_count = 0;
|
||||
d->trust = rrset_trust_ans_noAA;
|
||||
@@ -2024,7 +2031,9 @@ struct local_zone* local_zones_add_zone(struct local_zones* zones,
|
||||
uint8_t* name, size_t len, int labs, uint16_t dclass,
|
||||
enum localzone_type tp)
|
||||
{
|
||||
int exact;
|
||||
/* create */
|
||||
struct local_zone *prev;
|
||||
struct local_zone* z = local_zone_create(name, len, labs, tp, dclass);
|
||||
if(!z) {
|
||||
free(name);
|
||||
@@ -2033,10 +2042,12 @@ struct local_zone* local_zones_add_zone(struct local_zones* zones,
|
||||
lock_rw_wrlock(&z->lock);
|
||||
|
||||
/* find the closest parent */
|
||||
z->parent = local_zones_find(zones, name, len, labs, dclass);
|
||||
prev = local_zones_find_le(zones, name, len, labs, dclass, &exact);
|
||||
if(!exact)
|
||||
z->parent = find_closest_parent(z, prev);
|
||||
|
||||
/* insert into the tree */
|
||||
if(!rbtree_insert(&zones->ztree, &z->node)) {
|
||||
if(exact||!rbtree_insert(&zones->ztree, &z->node)) {
|
||||
/* duplicate entry! */
|
||||
lock_rw_unlock(&z->lock);
|
||||
local_zone_delete(z);
|
||||
|
||||
@@ -641,4 +641,23 @@ 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);
|
||||
|
||||
/** Enter a new zone; returns with WRlock
|
||||
* Made public for unit testing
|
||||
* @param zones: the local zones tree
|
||||
* @param name: name of the zone
|
||||
* @param type: type of the zone
|
||||
* @param dclass: class of the zone
|
||||
* @return local_zone (or duplicate), NULL on parse and malloc failures
|
||||
*/
|
||||
struct local_zone*
|
||||
lz_enter_zone(struct local_zones* zones, const char* name, const char* type,
|
||||
uint16_t dclass);
|
||||
|
||||
/** Setup parent pointers, so that a lookup can be done for closest match
|
||||
* Made public for unit testing
|
||||
* @param zones: the local zones tree
|
||||
*/
|
||||
void
|
||||
lz_init_parents(struct local_zones* zones);
|
||||
#endif /* SERVICES_LOCALZONE_H */
|
||||
|
||||
+149
-19
@@ -47,6 +47,7 @@
|
||||
#include "services/outbound_list.h"
|
||||
#include "services/cache/dns.h"
|
||||
#include "services/cache/rrset.h"
|
||||
#include "services/cache/infra.h"
|
||||
#include "util/log.h"
|
||||
#include "util/net_help.h"
|
||||
#include "util/module.h"
|
||||
@@ -69,6 +70,12 @@
|
||||
#include "edns-subnet/subnetmod.h"
|
||||
#include "edns-subnet/edns-subnet.h"
|
||||
#endif
|
||||
#ifdef HAVE_SYS_TYPES_H
|
||||
# include <sys/types.h>
|
||||
#endif
|
||||
#ifdef HAVE_NETDB_H
|
||||
#include <netdb.h>
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Compare two response-ip client info entries for the purpose of mesh state
|
||||
@@ -304,7 +311,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;
|
||||
@@ -314,6 +321,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);
|
||||
@@ -321,6 +329,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)
|
||||
@@ -379,7 +388,7 @@ mesh_serve_expired_init(struct mesh_state* mstate, int timeout)
|
||||
&mesh_serve_expired_lookup;
|
||||
|
||||
/* In case this timer already popped, start it again */
|
||||
if(!mstate->s.serve_expired_data->timer) {
|
||||
if(!mstate->s.serve_expired_data->timer && timeout != -1) {
|
||||
mstate->s.serve_expired_data->timer = comm_timer_create(
|
||||
mstate->s.env->worker_base, mesh_serve_expired_callback, mstate);
|
||||
if(!mstate->s.serve_expired_data->timer)
|
||||
@@ -406,11 +415,20 @@ void mesh_new_client(struct mesh_area* mesh, struct query_info* qinfo,
|
||||
int timeout = mesh->env->cfg->serve_expired?
|
||||
mesh->env->cfg->serve_expired_client_timeout:0;
|
||||
struct sldns_buffer* r_buffer = rep->c->buffer;
|
||||
uint16_t mesh_flags = qflags&(BIT_RD|BIT_CD);
|
||||
if(rep->c->tcp_req_info) {
|
||||
r_buffer = rep->c->tcp_req_info->spool_buffer;
|
||||
}
|
||||
if(!infra_wait_limit_allowed(mesh->env->infra_cache, rep,
|
||||
edns->cookie_valid, mesh->env->cfg)) {
|
||||
verbose(VERB_ALGO, "Too many queries waiting from the IP. "
|
||||
"dropping incoming query.");
|
||||
comm_point_drop_reply(rep);
|
||||
mesh->stats_dropped++;
|
||||
return;
|
||||
}
|
||||
if(!unique)
|
||||
s = mesh_area_find(mesh, cinfo, qinfo, qflags&(BIT_RD|BIT_CD), 0, 0);
|
||||
s = mesh_area_find(mesh, cinfo, qinfo, mesh_flags, 0, 0);
|
||||
/* does this create a new reply state? */
|
||||
if(!s || s->list_select == mesh_no_list) {
|
||||
if(!mesh_make_new_space(mesh, rep->c->buffer)) {
|
||||
@@ -438,7 +456,7 @@ void mesh_new_client(struct mesh_area* mesh, struct query_info* qinfo,
|
||||
struct rbnode_type* n;
|
||||
#endif
|
||||
s = mesh_state_create(mesh->env, qinfo, cinfo,
|
||||
qflags&(BIT_RD|BIT_CD), 0, 0);
|
||||
mesh_flags, 0, 0);
|
||||
if(!s) {
|
||||
log_err("mesh_state_create: out of memory; SERVFAIL");
|
||||
if(!inplace_cb_reply_servfail_call(mesh->env, qinfo, NULL, NULL,
|
||||
@@ -505,6 +523,19 @@ void mesh_new_client(struct mesh_area* mesh, struct query_info* qinfo,
|
||||
log_err("mesh_new_client: out of memory initializing serve expired");
|
||||
goto servfail_mem;
|
||||
}
|
||||
#ifdef USE_CACHEDB
|
||||
if(!timeout && mesh->env->cfg->serve_expired &&
|
||||
!mesh->env->cfg->serve_expired_client_timeout &&
|
||||
(mesh->env->cachedb_enabled &&
|
||||
mesh->env->cfg->cachedb_check_when_serve_expired)) {
|
||||
if(!mesh_serve_expired_init(s, -1)) {
|
||||
log_err("mesh_new_client: out of memory initializing serve expired");
|
||||
goto servfail_mem;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
infra_wait_limit_inc(mesh->env->infra_cache, rep, *mesh->env->now,
|
||||
mesh->env->cfg);
|
||||
/* update statistics */
|
||||
if(was_detached) {
|
||||
log_assert(mesh->num_detached_states > 0);
|
||||
@@ -537,6 +568,8 @@ servfail_mem:
|
||||
edns->opt_list_inplace_cb_out = NULL;
|
||||
error_encode(r_buffer, LDNS_RCODE_SERVFAIL,
|
||||
qinfo, qid, qflags, edns);
|
||||
if(rep->c->use_h2)
|
||||
http2_stream_remove_mesh_state(rep->c->h2_stream);
|
||||
comm_point_send_reply(rep);
|
||||
if(added)
|
||||
mesh_state_delete(&s->s);
|
||||
@@ -555,8 +588,9 @@ mesh_new_callback(struct mesh_area* mesh, struct query_info* qinfo,
|
||||
int was_detached = 0;
|
||||
int was_noreply = 0;
|
||||
int added = 0;
|
||||
uint16_t mesh_flags = qflags&(BIT_RD|BIT_CD);
|
||||
if(!unique)
|
||||
s = mesh_area_find(mesh, NULL, qinfo, qflags&(BIT_RD|BIT_CD), 0, 0);
|
||||
s = mesh_area_find(mesh, NULL, qinfo, mesh_flags, 0, 0);
|
||||
|
||||
/* there are no limits on the number of callbacks */
|
||||
|
||||
@@ -566,7 +600,7 @@ mesh_new_callback(struct mesh_area* mesh, struct query_info* qinfo,
|
||||
struct rbnode_type* n;
|
||||
#endif
|
||||
s = mesh_state_create(mesh->env, qinfo, NULL,
|
||||
qflags&(BIT_RD|BIT_CD), 0, 0);
|
||||
mesh_flags, 0, 0);
|
||||
if(!s) {
|
||||
return 0;
|
||||
}
|
||||
@@ -610,6 +644,18 @@ mesh_new_callback(struct mesh_area* mesh, struct query_info* qinfo,
|
||||
mesh_state_delete(&s->s);
|
||||
return 0;
|
||||
}
|
||||
#ifdef USE_CACHEDB
|
||||
if(!timeout && mesh->env->cfg->serve_expired &&
|
||||
!mesh->env->cfg->serve_expired_client_timeout &&
|
||||
(mesh->env->cachedb_enabled &&
|
||||
mesh->env->cfg->cachedb_check_when_serve_expired)) {
|
||||
if(!mesh_serve_expired_init(s, -1)) {
|
||||
if(added)
|
||||
mesh_state_delete(&s->s);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
/* update statistics */
|
||||
if(was_detached) {
|
||||
log_assert(mesh->num_detached_states > 0);
|
||||
@@ -633,8 +679,12 @@ static void mesh_schedule_prefetch(struct mesh_area* mesh,
|
||||
struct query_info* qinfo, uint16_t qflags, time_t leeway, int run,
|
||||
int rpz_passthru)
|
||||
{
|
||||
/* Explicitly set the BIT_RD regardless of the client's flags. This is
|
||||
* for a prefetch query (no client attached) but it needs to be treated
|
||||
* as a recursion query. */
|
||||
uint16_t mesh_flags = BIT_RD|(qflags&BIT_CD);
|
||||
struct mesh_state* s = mesh_area_find(mesh, NULL, qinfo,
|
||||
qflags&(BIT_RD|BIT_CD), 0, 0);
|
||||
mesh_flags, 0, 0);
|
||||
#ifdef UNBOUND_DEBUG
|
||||
struct rbnode_type* n;
|
||||
#endif
|
||||
@@ -654,8 +704,7 @@ static void mesh_schedule_prefetch(struct mesh_area* mesh,
|
||||
return;
|
||||
}
|
||||
|
||||
s = mesh_state_create(mesh->env, qinfo, NULL,
|
||||
qflags&(BIT_RD|BIT_CD), 0, 0);
|
||||
s = mesh_state_create(mesh->env, qinfo, NULL, mesh_flags, 0, 0);
|
||||
if(!s) {
|
||||
log_err("prefetch mesh_state_create: out of memory");
|
||||
return;
|
||||
@@ -716,14 +765,17 @@ static void mesh_schedule_prefetch_subnet(struct mesh_area* mesh,
|
||||
#ifdef UNBOUND_DEBUG
|
||||
struct rbnode_type* n;
|
||||
#endif
|
||||
/* Explicitly set the BIT_RD regardless of the client's flags. This is
|
||||
* for a prefetch query (no client attached) but it needs to be treated
|
||||
* as a recursion query. */
|
||||
uint16_t mesh_flags = BIT_RD|(qflags&BIT_CD);
|
||||
if(!mesh_make_new_space(mesh, NULL)) {
|
||||
verbose(VERB_ALGO, "Too many queries. dropped prefetch.");
|
||||
mesh->stats_dropped ++;
|
||||
return;
|
||||
}
|
||||
|
||||
s = mesh_state_create(mesh->env, qinfo, NULL,
|
||||
qflags&(BIT_RD|BIT_CD), 0, 0);
|
||||
s = mesh_state_create(mesh->env, qinfo, NULL, mesh_flags, 0, 0);
|
||||
if(!s) {
|
||||
log_err("prefetch_subnet mesh_state_create: out of memory");
|
||||
return;
|
||||
@@ -924,6 +976,10 @@ mesh_state_cleanup(struct mesh_state* mstate)
|
||||
* takes no time and also it does not do the mesh accounting */
|
||||
mstate->reply_list = NULL;
|
||||
for(; rep; rep=rep->next) {
|
||||
infra_wait_limit_dec(mesh->env->infra_cache,
|
||||
&rep->query_reply, mesh->env->cfg);
|
||||
if(rep->query_reply.c->use_h2)
|
||||
http2_stream_remove_mesh_state(rep->h2_stream);
|
||||
comm_point_drop_reply(&rep->query_reply);
|
||||
log_assert(mesh->num_reply_addrs > 0);
|
||||
mesh->num_reply_addrs--;
|
||||
@@ -1173,7 +1229,7 @@ mesh_do_callback(struct mesh_state* m, int rcode, struct reply_info* rep,
|
||||
rcode = LDNS_RCODE_SERVFAIL;
|
||||
if(!rcode && rep && (rep->security == sec_status_bogus ||
|
||||
rep->security == sec_status_secure_sentinel_fail)) {
|
||||
if(!(reason = errinf_to_str_bogus(&m->s)))
|
||||
if(!(reason = errinf_to_str_bogus(&m->s, NULL)))
|
||||
rcode = LDNS_RCODE_SERVFAIL;
|
||||
}
|
||||
/* send the reply */
|
||||
@@ -1407,6 +1463,8 @@ mesh_send_reply(struct mesh_state* m, int rcode, struct reply_info* rep,
|
||||
comm_point_send_reply(&r->query_reply);
|
||||
m->reply_list = rlist;
|
||||
}
|
||||
infra_wait_limit_dec(m->s.env->infra_cache, &r->query_reply,
|
||||
m->s.env->cfg);
|
||||
/* account */
|
||||
log_assert(m->s.env->mesh->num_reply_addrs > 0);
|
||||
m->s.env->mesh->num_reply_addrs--;
|
||||
@@ -1429,7 +1487,9 @@ mesh_send_reply(struct mesh_state* m, int rcode, struct reply_info* rep,
|
||||
if(m->s.env->cfg->log_replies) {
|
||||
log_reply_info(NO_VERBOSE, &m->s.qinfo,
|
||||
&r->query_reply.client_addr,
|
||||
r->query_reply.client_addrlen, duration, 0, r_buffer);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1456,12 +1516,34 @@ void mesh_query_done(struct mesh_state* mstate)
|
||||
&& mstate->s.env->cfg->log_servfail
|
||||
&& !mstate->s.env->cfg->val_log_squelch) {
|
||||
char* err = errinf_to_str_servfail(&mstate->s);
|
||||
if(err)
|
||||
log_err("%s", err);
|
||||
free(err);
|
||||
if(err) { log_err("%s", err); }
|
||||
}
|
||||
}
|
||||
for(r = mstate->reply_list; r; r = r->next) {
|
||||
struct timeval old;
|
||||
timeval_subtract(&old, mstate->s.env->now_tv, &r->start_time);
|
||||
if(mstate->s.env->cfg->discard_timeout != 0 &&
|
||||
((int)old.tv_sec)*1000+((int)old.tv_usec)/1000 >
|
||||
mstate->s.env->cfg->discard_timeout) {
|
||||
/* Drop the reply, it is too old */
|
||||
/* briefly set the reply_list to NULL, so that the
|
||||
* tcp req info cleanup routine that calls the mesh
|
||||
* to deregister the meshstate for it is not done
|
||||
* because the list is NULL and also accounting is not
|
||||
* done there, but instead we do that here. */
|
||||
struct mesh_reply* reply_list = mstate->reply_list;
|
||||
verbose(VERB_ALGO, "drop reply, it is older than discard-timeout");
|
||||
infra_wait_limit_dec(mstate->s.env->infra_cache,
|
||||
&r->query_reply, mstate->s.env->cfg);
|
||||
mstate->reply_list = NULL;
|
||||
if(r->query_reply.c->use_h2)
|
||||
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++;
|
||||
continue;
|
||||
}
|
||||
|
||||
i++;
|
||||
tv = r->start_time;
|
||||
|
||||
@@ -1485,7 +1567,12 @@ void mesh_query_done(struct mesh_state* mstate)
|
||||
* because the list is NULL and also accounting is not
|
||||
* done there, but instead we do that here. */
|
||||
struct mesh_reply* reply_list = mstate->reply_list;
|
||||
infra_wait_limit_dec(mstate->s.env->infra_cache,
|
||||
&r->query_reply, mstate->s.env->cfg);
|
||||
mstate->reply_list = NULL;
|
||||
if(r->query_reply.c->use_h2) {
|
||||
http2_stream_remove_mesh_state(r->h2_stream);
|
||||
}
|
||||
comm_point_drop_reply(&r->query_reply);
|
||||
mstate->reply_list = reply_list;
|
||||
} else {
|
||||
@@ -1500,6 +1587,8 @@ void mesh_query_done(struct mesh_state* mstate)
|
||||
tcp_req_info_remove_mesh_state(r->query_reply.c->tcp_req_info, mstate);
|
||||
r_buffer = NULL;
|
||||
}
|
||||
/* mesh_send_reply removed mesh state from
|
||||
* http2_stream. */
|
||||
prev = r;
|
||||
prev_buffer = r_buffer;
|
||||
}
|
||||
@@ -1652,6 +1741,7 @@ int mesh_state_add_reply(struct mesh_state* s, struct edns_data* edns,
|
||||
return 0;
|
||||
if(rep->c->use_h2)
|
||||
r->h2_stream = rep->c->h2_stream;
|
||||
else r->h2_stream = NULL;
|
||||
|
||||
/* Data related to local alias stored in 'qinfo' (if any) is ephemeral
|
||||
* and can be different for different original queries (even if the
|
||||
@@ -2017,6 +2107,8 @@ void mesh_state_remove_reply(struct mesh_area* mesh, struct mesh_state* m,
|
||||
/* delete it, but allocated in m region */
|
||||
log_assert(mesh->num_reply_addrs > 0);
|
||||
mesh->num_reply_addrs--;
|
||||
infra_wait_limit_dec(mesh->env->infra_cache,
|
||||
&n->query_reply, mesh->env->cfg);
|
||||
|
||||
/* prev = prev; */
|
||||
n = n->next;
|
||||
@@ -2086,6 +2178,7 @@ mesh_serve_expired_callback(void* arg)
|
||||
int must_validate = (!(qstate->query_flags&BIT_CD)
|
||||
|| qstate->env->cfg->ignore_cd) && qstate->env->need_to_validate;
|
||||
int i = 0;
|
||||
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);
|
||||
@@ -2103,7 +2196,7 @@ mesh_serve_expired_callback(void* arg)
|
||||
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);
|
||||
lookup_qinfo, &is_expired);
|
||||
if(!msg)
|
||||
return;
|
||||
/* Reset these in case we pass a second time from here. */
|
||||
@@ -2157,6 +2250,30 @@ mesh_serve_expired_callback(void* arg)
|
||||
log_dns_msg("Serve expired lookup", &qstate->qinfo, msg->rep);
|
||||
|
||||
for(r = mstate->reply_list; r; r = r->next) {
|
||||
struct timeval old;
|
||||
timeval_subtract(&old, mstate->s.env->now_tv, &r->start_time);
|
||||
if(mstate->s.env->cfg->discard_timeout != 0 &&
|
||||
((int)old.tv_sec)*1000+((int)old.tv_usec)/1000 >
|
||||
mstate->s.env->cfg->discard_timeout) {
|
||||
/* Drop the reply, it is too old */
|
||||
/* briefly set the reply_list to NULL, so that the
|
||||
* tcp req info cleanup routine that calls the mesh
|
||||
* to deregister the meshstate for it is not done
|
||||
* because the list is NULL and also accounting is not
|
||||
* done there, but instead we do that here. */
|
||||
struct mesh_reply* reply_list = mstate->reply_list;
|
||||
verbose(VERB_ALGO, "drop reply, it is older than discard-timeout");
|
||||
infra_wait_limit_dec(mstate->s.env->infra_cache,
|
||||
&r->query_reply, mstate->s.env->cfg);
|
||||
mstate->reply_list = NULL;
|
||||
if(r->query_reply.c->use_h2)
|
||||
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++;
|
||||
continue;
|
||||
}
|
||||
|
||||
i++;
|
||||
tv = r->start_time;
|
||||
|
||||
@@ -2171,8 +2288,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);
|
||||
}
|
||||
@@ -2184,6 +2303,9 @@ mesh_serve_expired_callback(void* arg)
|
||||
r, r_buffer, prev, prev_buffer);
|
||||
if(r->query_reply.c->tcp_req_info)
|
||||
tcp_req_info_remove_mesh_state(r->query_reply.c->tcp_req_info, mstate);
|
||||
/* mesh_send_reply removed mesh state from http2_stream. */
|
||||
infra_wait_limit_dec(mstate->s.env->infra_cache,
|
||||
&r->query_reply, mstate->s.env->cfg);
|
||||
prev = r;
|
||||
prev_buffer = r_buffer;
|
||||
}
|
||||
@@ -2230,6 +2352,14 @@ mesh_serve_expired_callback(void* arg)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
mesh_respond_serve_expired(struct mesh_state* mstate)
|
||||
{
|
||||
if(!mstate->s.serve_expired_data)
|
||||
mesh_serve_expired_init(mstate, -1);
|
||||
mesh_serve_expired_callback(mstate);
|
||||
}
|
||||
|
||||
int mesh_jostle_exceeded(struct mesh_area* mesh)
|
||||
{
|
||||
if(mesh->all.count < mesh->max_reply_states)
|
||||
|
||||
+8
-1
@@ -673,11 +673,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
|
||||
@@ -690,4 +691,10 @@ mesh_serve_expired_lookup(struct module_qstate* qstate,
|
||||
*/
|
||||
int mesh_jostle_exceeded(struct mesh_area* mesh);
|
||||
|
||||
/**
|
||||
* Give the serve expired responses.
|
||||
* @param mstate: mesh state for query that has serve_expired_data.
|
||||
*/
|
||||
void mesh_respond_serve_expired(struct mesh_state* mstate);
|
||||
|
||||
#endif /* SERVICES_MESH_H */
|
||||
|
||||
+69
-9
@@ -95,6 +95,16 @@ modstack_init(struct module_stack* stack)
|
||||
stack->mod = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
modstack_free(struct module_stack* stack)
|
||||
{
|
||||
if(!stack)
|
||||
return;
|
||||
stack->num = 0;
|
||||
free(stack->mod);
|
||||
stack->mod = NULL;
|
||||
}
|
||||
|
||||
int
|
||||
modstack_config(struct module_stack* stack, const char* module_conf)
|
||||
{
|
||||
@@ -222,18 +232,59 @@ module_func_block* module_factory(const char** str)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int
|
||||
modstack_setup(struct module_stack* stack, const char* module_conf,
|
||||
int
|
||||
modstack_call_startup(struct module_stack* stack, const char* module_conf,
|
||||
struct module_env* env)
|
||||
{
|
||||
int i;
|
||||
if(stack->num != 0)
|
||||
modstack_desetup(stack, env);
|
||||
fatal_exit("unexpected already initialised modules");
|
||||
/* fixed setup of the modules */
|
||||
if(!modstack_config(stack, module_conf)) {
|
||||
return 0;
|
||||
}
|
||||
for(i=0; i<stack->num; i++) {
|
||||
if(stack->mod[i]->startup == NULL)
|
||||
continue;
|
||||
verbose(VERB_OPS, "startup module %d: %s",
|
||||
i, stack->mod[i]->name);
|
||||
fptr_ok(fptr_whitelist_mod_startup(stack->mod[i]->startup));
|
||||
if(!(*stack->mod[i]->startup)(env, i)) {
|
||||
log_err("module startup for module %s failed",
|
||||
stack->mod[i]->name);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
modstack_call_init(struct module_stack* stack, const char* module_conf,
|
||||
struct module_env* env)
|
||||
{
|
||||
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((unsigned char)*module_conf))
|
||||
module_conf++;
|
||||
if(strncmp(stack->mod[i]->name, module_conf,
|
||||
strlen(stack->mod[i]->name))) {
|
||||
if(stack->mod[i]->startup || stack->mod[i]->destartup) {
|
||||
log_err("changed module ordering during reload not supported, for module that needs startup");
|
||||
return 0;
|
||||
} else {
|
||||
changed = 1;
|
||||
}
|
||||
}
|
||||
module_conf += strlen(stack->mod[i]->name);
|
||||
}
|
||||
if(changed) {
|
||||
modstack_free(stack);
|
||||
if(!modstack_config(stack, module_conf)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
for(i=0; i<stack->num; i++) {
|
||||
verbose(VERB_OPS, "init module %d: %s",
|
||||
i, stack->mod[i]->name);
|
||||
@@ -247,20 +298,29 @@ modstack_setup(struct module_stack* stack, const char* module_conf,
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
modstack_desetup(struct module_stack* stack, struct module_env* env)
|
||||
void
|
||||
modstack_call_deinit(struct module_stack* stack, struct module_env* env)
|
||||
{
|
||||
int i;
|
||||
for(i=0; i<stack->num; i++) {
|
||||
fptr_ok(fptr_whitelist_mod_deinit(stack->mod[i]->deinit));
|
||||
(*stack->mod[i]->deinit)(env, i);
|
||||
}
|
||||
stack->num = 0;
|
||||
free(stack->mod);
|
||||
stack->mod = NULL;
|
||||
}
|
||||
|
||||
int
|
||||
void
|
||||
modstack_call_destartup(struct module_stack* stack, struct module_env* env)
|
||||
{
|
||||
int i;
|
||||
for(i=0; i<stack->num; i++) {
|
||||
if(stack->mod[i]->destartup == NULL)
|
||||
continue;
|
||||
fptr_ok(fptr_whitelist_mod_destartup(stack->mod[i]->destartup));
|
||||
(*stack->mod[i]->destartup)(env, i);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
modstack_find(struct module_stack* stack, const char* name)
|
||||
{
|
||||
int i;
|
||||
|
||||
+31
-7
@@ -60,6 +60,23 @@ struct module_stack {
|
||||
*/
|
||||
void modstack_init(struct module_stack* stack);
|
||||
|
||||
/**
|
||||
* Free the stack of modules
|
||||
* @param stack: stack that frees up memory.
|
||||
*/
|
||||
void modstack_free(struct module_stack* stack);
|
||||
|
||||
/**
|
||||
* Initialises modules and assignes ids. Calls module_startup().
|
||||
* @param stack: Expected empty, filled according to module_conf
|
||||
* @param module_conf: string what modules to initialize
|
||||
* @param env: module environment which is inited by the modules.
|
||||
* environment should have a superalloc, cfg,
|
||||
* @return on false a module init failed.
|
||||
*/
|
||||
int modstack_call_startup(struct module_stack* stack, const char* module_conf,
|
||||
struct module_env* env);
|
||||
|
||||
/**
|
||||
* Read config file module settings and set up the modfunc block
|
||||
* @param stack: the stack of modules (empty before call).
|
||||
@@ -83,24 +100,31 @@ struct module_func_block* module_factory(const char** str);
|
||||
const char** module_list_avail(void);
|
||||
|
||||
/**
|
||||
* Setup modules. Assigns ids and calls module_init.
|
||||
* @param stack: if not empty beforehand, it will be desetup()ed.
|
||||
* It is then modstack_configged().
|
||||
* @param module_conf: string what modules to insert.
|
||||
* Init modules. Calls module_init().
|
||||
* @param stack: It is modstack_setupped().
|
||||
* @param module_conf: module ordering to check against the ordering in stack.
|
||||
* fails on changed ordering.
|
||||
* @param env: module environment which is inited by the modules.
|
||||
* environment should have a superalloc, cfg,
|
||||
* env.need_to_validate is set by the modules.
|
||||
* @return on false a module init failed.
|
||||
*/
|
||||
int modstack_setup(struct module_stack* stack, const char* module_conf,
|
||||
int modstack_call_init(struct module_stack* stack, const char* module_conf,
|
||||
struct module_env* env);
|
||||
|
||||
/**
|
||||
* Desetup the modules, deinit, delete.
|
||||
* Deinit the modules.
|
||||
* @param stack: made empty.
|
||||
* @param env: module env for module deinit() calls.
|
||||
*/
|
||||
void modstack_desetup(struct module_stack* stack, struct module_env* env);
|
||||
void modstack_call_deinit(struct module_stack* stack, struct module_env* env);
|
||||
|
||||
/**
|
||||
* Destartup the modules, close, delete.
|
||||
* @param stack: made empty.
|
||||
* @param env: module env for module destartup() calls.
|
||||
*/
|
||||
void modstack_call_destartup(struct module_stack* stack, struct module_env* env);
|
||||
|
||||
/**
|
||||
* Find index of module by name.
|
||||
|
||||
+44
-22
@@ -1009,7 +1009,7 @@ use_free_buffer(struct outside_network* outnet)
|
||||
sldns_buffer tmp;
|
||||
sldns_buffer_init_frm_data(&tmp, w->pkt, w->pkt_len);
|
||||
dt_msg_send_outside_query(outnet->dtenv, &w->sq->addr,
|
||||
&pend_tcp->pi->addr, comm_tcp, w->sq->zone,
|
||||
&pend_tcp->pi->addr, comm_tcp, NULL, w->sq->zone,
|
||||
w->sq->zonelen, &tmp);
|
||||
}
|
||||
#endif
|
||||
@@ -2051,7 +2051,8 @@ select_id(struct outside_network* outnet, struct pending* pend,
|
||||
}
|
||||
|
||||
/** return true is UDP connect error needs to be logged */
|
||||
static int udp_connect_needs_log(int err)
|
||||
static int udp_connect_needs_log(int err, struct sockaddr_storage* addr,
|
||||
socklen_t addrlen)
|
||||
{
|
||||
switch(err) {
|
||||
case ECONNREFUSED:
|
||||
@@ -2075,6 +2076,15 @@ static int udp_connect_needs_log(int err)
|
||||
if(verbosity >= VERB_ALGO)
|
||||
return 1;
|
||||
return 0;
|
||||
case EINVAL:
|
||||
/* Stop 'Invalid argument for fe80::/10' addresses appearing
|
||||
* in the logs, at low verbosity. They cannot be sent to. */
|
||||
if(addr_is_ip6linklocal(addr, addrlen)) {
|
||||
if(verbosity >= VERB_ALGO)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -2141,7 +2151,8 @@ select_ifport(struct outside_network* outnet, struct pending* pend,
|
||||
/* connect() to the destination */
|
||||
if(connect(fd, (struct sockaddr*)&pend->addr,
|
||||
pend->addrlen) < 0) {
|
||||
if(udp_connect_needs_log(errno)) {
|
||||
if(udp_connect_needs_log(errno,
|
||||
&pend->addr, pend->addrlen)) {
|
||||
log_err_addr("udp connect failed",
|
||||
strerror(errno), &pend->addr,
|
||||
pend->addrlen);
|
||||
@@ -2237,7 +2248,7 @@ randomize_and_send_udp(struct pending* pend, sldns_buffer* packet, int timeout)
|
||||
outnet->dtenv->log_forwarder_query_messages)) {
|
||||
log_addr(VERB_ALGO, "from local addr", &pend->pc->pif->addr, pend->pc->pif->addrlen);
|
||||
log_addr(VERB_ALGO, "request to upstream", &pend->addr, pend->addrlen);
|
||||
dt_msg_send_outside_query(outnet->dtenv, &pend->addr, &pend->pc->pif->addr, comm_udp,
|
||||
dt_msg_send_outside_query(outnet->dtenv, &pend->addr, &pend->pc->pif->addr, comm_udp, NULL,
|
||||
pend->sq->zone, pend->sq->zonelen, packet);
|
||||
}
|
||||
#endif
|
||||
@@ -2517,7 +2528,7 @@ pending_tcp_query(struct serviced_query* sq, sldns_buffer* packet,
|
||||
sldns_buffer tmp;
|
||||
sldns_buffer_init_frm_data(&tmp, w->pkt, w->pkt_len);
|
||||
dt_msg_send_outside_query(sq->outnet->dtenv, &sq->addr,
|
||||
&pend->pi->addr, comm_tcp, sq->zone,
|
||||
&pend->pi->addr, comm_tcp, NULL, sq->zone,
|
||||
sq->zonelen, &tmp);
|
||||
}
|
||||
#endif
|
||||
@@ -2820,6 +2831,25 @@ serviced_perturb_qname(struct ub_randstate* rnd, uint8_t* qbuf, size_t len)
|
||||
}
|
||||
}
|
||||
|
||||
static uint16_t
|
||||
serviced_query_udp_size(struct serviced_query* sq, enum serviced_query_status status) {
|
||||
uint16_t udp_size;
|
||||
if(status == serviced_query_UDP_EDNS_FRAG) {
|
||||
if(addr_is_ip6(&sq->addr, sq->addrlen)) {
|
||||
if(EDNS_FRAG_SIZE_IP6 < EDNS_ADVERTISED_SIZE)
|
||||
udp_size = EDNS_FRAG_SIZE_IP6;
|
||||
else udp_size = EDNS_ADVERTISED_SIZE;
|
||||
} else {
|
||||
if(EDNS_FRAG_SIZE_IP4 < EDNS_ADVERTISED_SIZE)
|
||||
udp_size = EDNS_FRAG_SIZE_IP4;
|
||||
else udp_size = EDNS_ADVERTISED_SIZE;
|
||||
}
|
||||
} else {
|
||||
udp_size = EDNS_ADVERTISED_SIZE;
|
||||
}
|
||||
return udp_size;
|
||||
}
|
||||
|
||||
/** put serviced query into a buffer */
|
||||
static void
|
||||
serviced_encode(struct serviced_query* sq, sldns_buffer* buff, int with_edns)
|
||||
@@ -2843,19 +2873,7 @@ serviced_encode(struct serviced_query* sq, sldns_buffer* buff, int with_edns)
|
||||
edns.opt_list_in = NULL;
|
||||
edns.opt_list_out = sq->opt_list;
|
||||
edns.opt_list_inplace_cb_out = NULL;
|
||||
if(sq->status == serviced_query_UDP_EDNS_FRAG) {
|
||||
if(addr_is_ip6(&sq->addr, sq->addrlen)) {
|
||||
if(EDNS_FRAG_SIZE_IP6 < EDNS_ADVERTISED_SIZE)
|
||||
edns.udp_size = EDNS_FRAG_SIZE_IP6;
|
||||
else edns.udp_size = EDNS_ADVERTISED_SIZE;
|
||||
} else {
|
||||
if(EDNS_FRAG_SIZE_IP4 < EDNS_ADVERTISED_SIZE)
|
||||
edns.udp_size = EDNS_FRAG_SIZE_IP4;
|
||||
else edns.udp_size = EDNS_ADVERTISED_SIZE;
|
||||
}
|
||||
} else {
|
||||
edns.udp_size = EDNS_ADVERTISED_SIZE;
|
||||
}
|
||||
edns.udp_size = serviced_query_udp_size(sq, sq->status);
|
||||
edns.bits = 0;
|
||||
if(sq->dnssec & EDNS_DO)
|
||||
edns.bits = EDNS_DO;
|
||||
@@ -3083,7 +3101,7 @@ serviced_tcp_callback(struct comm_point* c, void* arg, int error,
|
||||
log_addr(VERB_ALGO, "response from upstream", &sq->addr, sq->addrlen);
|
||||
log_addr(VERB_ALGO, "to local addr", &pi->addr, pi->addrlen);
|
||||
dt_msg_send_outside_response(sq->outnet->dtenv, &sq->addr,
|
||||
&pi->addr, c->type, sq->zone, sq->zonelen, sq->qbuf,
|
||||
&pi->addr, c->type, c->ssl, sq->zone, sq->zonelen, sq->qbuf,
|
||||
sq->qbuflen, &sq->last_sent_time, sq->outnet->now_tv,
|
||||
c->buffer);
|
||||
}
|
||||
@@ -3252,7 +3270,8 @@ serviced_udp_callback(struct comm_point* c, void* arg, int error,
|
||||
|
||||
sq->pending = NULL; /* removed after callback */
|
||||
if(error == NETEVENT_TIMEOUT) {
|
||||
if(sq->status == serviced_query_UDP_EDNS && sq->last_rtt < 5000) {
|
||||
if(sq->status == serviced_query_UDP_EDNS && sq->last_rtt < 5000 &&
|
||||
(serviced_query_udp_size(sq, serviced_query_UDP_EDNS_FRAG) < serviced_query_udp_size(sq, serviced_query_UDP_EDNS))) {
|
||||
/* fallback to 1480/1280 */
|
||||
sq->status = serviced_query_UDP_EDNS_FRAG;
|
||||
log_name_addr(VERB_ALGO, "try edns1xx0", sq->qbuf+10,
|
||||
@@ -3296,7 +3315,7 @@ serviced_udp_callback(struct comm_point* c, void* arg, int error,
|
||||
log_addr(VERB_ALGO, "to local addr", &p->pc->pif->addr,
|
||||
p->pc->pif->addrlen);
|
||||
dt_msg_send_outside_response(outnet->dtenv, &sq->addr,
|
||||
&p->pc->pif->addr, c->type, sq->zone, sq->zonelen,
|
||||
&p->pc->pif->addr, c->type, c->ssl, sq->zone, sq->zonelen,
|
||||
sq->qbuf, sq->qbuflen, &sq->last_sent_time,
|
||||
sq->outnet->now_tv, c->buffer);
|
||||
}
|
||||
@@ -3447,7 +3466,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,
|
||||
|
||||
+300
-102
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -478,6 +490,67 @@ new_cname_override(struct regional* region, uint8_t* ct, size_t ctlen)
|
||||
return rrset;
|
||||
}
|
||||
|
||||
/** delete the cname override */
|
||||
static void
|
||||
delete_cname_override(struct rpz* r)
|
||||
{
|
||||
if(r->cname_override) {
|
||||
/* The cname override is what is allocated in the region. */
|
||||
regional_free_all(r->region);
|
||||
r->cname_override = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/** Apply rpz config elements to the rpz structure, false on failure. */
|
||||
static int
|
||||
rpz_apply_cfg_elements(struct rpz* r, struct config_auth* p)
|
||||
{
|
||||
if(p->rpz_taglist && p->rpz_taglistlen) {
|
||||
r->taglistlen = p->rpz_taglistlen;
|
||||
r->taglist = memdup(p->rpz_taglist, r->taglistlen);
|
||||
if(!r->taglist) {
|
||||
log_err("malloc failure on RPZ taglist alloc");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if(p->rpz_action_override) {
|
||||
r->action_override = rpz_config_to_action(p->rpz_action_override);
|
||||
}
|
||||
else
|
||||
r->action_override = RPZ_NO_OVERRIDE_ACTION;
|
||||
|
||||
if(r->action_override == RPZ_CNAME_OVERRIDE_ACTION) {
|
||||
uint8_t nm[LDNS_MAX_DOMAINLEN+1];
|
||||
size_t nmlen = sizeof(nm);
|
||||
|
||||
if(!p->rpz_cname) {
|
||||
log_err("rpz: override with cname action found, but no "
|
||||
"rpz-cname-override configured");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(sldns_str2wire_dname_buf(p->rpz_cname, nm, &nmlen) != 0) {
|
||||
log_err("rpz: cannot parse cname override: %s",
|
||||
p->rpz_cname);
|
||||
return 0;
|
||||
}
|
||||
r->cname_override = new_cname_override(r->region, nm, nmlen);
|
||||
if(!r->cname_override) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
r->log = p->rpz_log;
|
||||
r->signal_nxdomain_ra = p->rpz_signal_nxdomain_ra;
|
||||
if(p->rpz_log_name) {
|
||||
if(!(r->log_name = strdup(p->rpz_log_name))) {
|
||||
log_err("malloc failure on RPZ log_name strdup");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
struct rpz*
|
||||
rpz_create(struct config_auth* p)
|
||||
{
|
||||
@@ -513,42 +586,8 @@ rpz_create(struct config_auth* p)
|
||||
goto err;
|
||||
}
|
||||
|
||||
r->taglistlen = p->rpz_taglistlen;
|
||||
r->taglist = memdup(p->rpz_taglist, r->taglistlen);
|
||||
if(p->rpz_action_override) {
|
||||
r->action_override = rpz_config_to_action(p->rpz_action_override);
|
||||
}
|
||||
else
|
||||
r->action_override = RPZ_NO_OVERRIDE_ACTION;
|
||||
|
||||
if(r->action_override == RPZ_CNAME_OVERRIDE_ACTION) {
|
||||
uint8_t nm[LDNS_MAX_DOMAINLEN+1];
|
||||
size_t nmlen = sizeof(nm);
|
||||
|
||||
if(!p->rpz_cname) {
|
||||
log_err("rpz: override with cname action found, but no "
|
||||
"rpz-cname-override configured");
|
||||
goto err;
|
||||
}
|
||||
|
||||
if(sldns_str2wire_dname_buf(p->rpz_cname, nm, &nmlen) != 0) {
|
||||
log_err("rpz: cannot parse cname override: %s",
|
||||
p->rpz_cname);
|
||||
goto err;
|
||||
}
|
||||
r->cname_override = new_cname_override(r->region, nm, nmlen);
|
||||
if(!r->cname_override) {
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
r->log = p->rpz_log;
|
||||
r->signal_nxdomain_ra = p->rpz_signal_nxdomain_ra;
|
||||
if(p->rpz_log_name) {
|
||||
if(!(r->log_name = strdup(p->rpz_log_name))) {
|
||||
log_err("malloc failure on RPZ log_name strdup");
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
if(!rpz_apply_cfg_elements(r, p))
|
||||
goto err;
|
||||
return r;
|
||||
err:
|
||||
if(r) {
|
||||
@@ -571,6 +610,32 @@ err:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int
|
||||
rpz_config(struct rpz* r, struct config_auth* p)
|
||||
{
|
||||
/* If the zonefile changes, it is read later, after which
|
||||
* rpz_clear and rpz_finish_config is called. */
|
||||
|
||||
/* free taglist, if any */
|
||||
if(r->taglist) {
|
||||
free(r->taglist);
|
||||
r->taglist = NULL;
|
||||
r->taglistlen = 0;
|
||||
}
|
||||
|
||||
/* free logname, if any */
|
||||
if(r->log_name) {
|
||||
free(r->log_name);
|
||||
r->log_name = NULL;
|
||||
}
|
||||
|
||||
delete_cname_override(r);
|
||||
|
||||
if(!rpz_apply_cfg_elements(r, p))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove RPZ zone name from dname
|
||||
* Copy dname to newdname, without the originlen number of trailing bytes
|
||||
@@ -1191,16 +1256,20 @@ rpz_find_zone(struct local_zones* zones, uint8_t* qname, size_t qname_len, uint1
|
||||
/** Find entry for RR type in the list of rrsets for the clientip. */
|
||||
static struct local_rrset*
|
||||
rpz_find_synthesized_rrset(uint16_t qtype,
|
||||
struct clientip_synthesized_rr* data)
|
||||
struct clientip_synthesized_rr* data, int alias_ok)
|
||||
{
|
||||
struct local_rrset* cursor = data->data;
|
||||
struct local_rrset* cursor = data->data, *cname = NULL;
|
||||
while( cursor != NULL) {
|
||||
struct packed_rrset_key* packed_rrset = &cursor->rrset->rk;
|
||||
if(htons(qtype) == packed_rrset->type) {
|
||||
return cursor;
|
||||
}
|
||||
if(ntohs(packed_rrset->type) == LDNS_RR_TYPE_CNAME && alias_ok)
|
||||
cname = cursor;
|
||||
cursor = cursor->next;
|
||||
}
|
||||
if(alias_ok)
|
||||
return cname;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -1386,7 +1455,7 @@ static int rpz_remove_clientip_rr(struct clientip_synthesized_rr* node,
|
||||
struct local_rrset* rrset;
|
||||
struct packed_rrset_data* d;
|
||||
size_t index;
|
||||
rrset = rpz_find_synthesized_rrset(rr_type, node);
|
||||
rrset = rpz_find_synthesized_rrset(rr_type, node, 0);
|
||||
if(rrset == NULL)
|
||||
return 0; /* type not found, ignore */
|
||||
d = (struct packed_rrset_data*)rrset->rrset->entry.data;
|
||||
@@ -1789,7 +1858,7 @@ rpz_apply_clientip_localdata_action(struct clientip_synthesized_rr* raddr,
|
||||
}
|
||||
|
||||
/* check query type / rr type */
|
||||
rrset = rpz_find_synthesized_rrset(qinfo->qtype, raddr);
|
||||
rrset = rpz_find_synthesized_rrset(qinfo->qtype, raddr, 1);
|
||||
if(rrset == NULL) {
|
||||
verbose(VERB_ALGO, "rpz: unable to find local-data for query");
|
||||
rrset_count = 0;
|
||||
@@ -1823,6 +1892,28 @@ nodata:
|
||||
rrset_count, rcode, rsoa);
|
||||
}
|
||||
|
||||
/** Apply the cname override action, during worker request callback.
|
||||
* false on failure. */
|
||||
static int
|
||||
rpz_apply_cname_override_action(struct rpz* r,
|
||||
struct query_info* qinfo, struct regional* temp)
|
||||
{
|
||||
if(!r)
|
||||
return 0;
|
||||
qinfo->local_alias = regional_alloc_zero(temp,
|
||||
sizeof(struct local_rrset));
|
||||
if(qinfo->local_alias == NULL)
|
||||
return 0; /* out of memory */
|
||||
qinfo->local_alias->rrset = respip_copy_rrset(r->cname_override, temp);
|
||||
if(qinfo->local_alias->rrset == NULL) {
|
||||
qinfo->local_alias = NULL;
|
||||
return 0; /* out of memory */
|
||||
}
|
||||
qinfo->local_alias->rrset->rk.dname = qinfo->qname;
|
||||
qinfo->local_alias->rrset->rk.dname_len = qinfo->qname_len;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** add additional section SOA record to the reply.
|
||||
* Since this gets fed into the normal iterator answer creation, it
|
||||
* gets minimal-responses applied to it, that can remove the additional SOA
|
||||
@@ -1878,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 */
|
||||
@@ -1908,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 */
|
||||
@@ -1933,12 +2026,14 @@ rpz_synthesize_localdata_from_rrset(struct rpz* ATTR_UNUSED(r), struct module_qs
|
||||
msg = rpz_dns_msg_new(ms->region);
|
||||
if(msg == NULL) { return NULL; }
|
||||
|
||||
msg->qinfo = *qi;
|
||||
new_reply_info = construct_reply_info_base(ms->region,
|
||||
LDNS_RCODE_NOERROR | BIT_QR | BIT_AA | BIT_RA,
|
||||
1, /* qd */
|
||||
0, /* ttl */
|
||||
0, /* prettl */
|
||||
0, /* expttl */
|
||||
0, /* norecttl */
|
||||
1, /* an */
|
||||
0, /* ns */
|
||||
0, /* ar */
|
||||
@@ -1975,40 +2070,42 @@ rpz_synthesize_localdata_from_rrset(struct rpz* ATTR_UNUSED(r), struct module_qs
|
||||
|
||||
static inline struct dns_msg*
|
||||
rpz_synthesize_nsip_localdata(struct rpz* r, struct module_qstate* ms,
|
||||
struct clientip_synthesized_rr* data, struct auth_zone* az)
|
||||
struct query_info* qi, struct clientip_synthesized_rr* data,
|
||||
struct auth_zone* az)
|
||||
{
|
||||
struct query_info* qi = &ms->qinfo;
|
||||
struct local_rrset* rrset;
|
||||
|
||||
rrset = rpz_find_synthesized_rrset(qi->qtype, data);
|
||||
rrset = rpz_find_synthesized_rrset(qi->qtype, data, 1);
|
||||
if(rrset == NULL) {
|
||||
verbose(VERB_ALGO, "rpz: nsip: no matching local data found");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return rpz_synthesize_localdata_from_rrset(r, ms, &ms->qinfo, rrset, az);
|
||||
return rpz_synthesize_localdata_from_rrset(r, ms, qi, rrset, az);
|
||||
}
|
||||
|
||||
/* copy'n'paste from localzone.c */
|
||||
static struct local_rrset*
|
||||
local_data_find_type(struct local_data* data, uint16_t type, int alias_ok)
|
||||
{
|
||||
struct local_rrset* p;
|
||||
struct local_rrset* p, *cname = NULL;
|
||||
type = htons(type);
|
||||
for(p = data->rrsets; p; p = p->next) {
|
||||
if(p->rrset->rk.type == type)
|
||||
return p;
|
||||
if(alias_ok && p->rrset->rk.type == htons(LDNS_RR_TYPE_CNAME))
|
||||
return p;
|
||||
cname = p;
|
||||
}
|
||||
if(alias_ok)
|
||||
return cname;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* based on localzone.c:local_data_answer() */
|
||||
static inline struct dns_msg*
|
||||
rpz_synthesize_nsdname_localdata(struct rpz* r, struct module_qstate* ms,
|
||||
struct local_zone* z, struct matched_delegation_point const* match,
|
||||
struct auth_zone* az)
|
||||
struct query_info* qi, struct local_zone* z,
|
||||
struct matched_delegation_point const* match, struct auth_zone* az)
|
||||
{
|
||||
struct local_data key;
|
||||
struct local_data* ld;
|
||||
@@ -2029,13 +2126,13 @@ rpz_synthesize_nsdname_localdata(struct rpz* r, struct module_qstate* ms,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
rrset = local_data_find_type(ld, ms->qinfo.qtype, 1);
|
||||
rrset = local_data_find_type(ld, qi->qtype, 1);
|
||||
if(rrset == NULL) {
|
||||
verbose(VERB_ALGO, "rpz: nsdname: no matching local data found");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return rpz_synthesize_localdata_from_rrset(r, ms, &ms->qinfo, rrset, az);
|
||||
return rpz_synthesize_localdata_from_rrset(r, ms, qi, rrset, az);
|
||||
}
|
||||
|
||||
/* like local_data_answer for qname triggers after a cname */
|
||||
@@ -2052,17 +2149,71 @@ rpz_synthesize_qname_localdata_msg(struct rpz* r, struct module_qstate* ms,
|
||||
key.namelabs = dname_count_labels(qinfo->qname);
|
||||
ld = (struct local_data*)rbtree_search(&z->data, &key.node);
|
||||
if(ld == NULL) {
|
||||
verbose(VERB_ALGO, "rpz: qname after cname: name not found");
|
||||
verbose(VERB_ALGO, "rpz: qname: name not found");
|
||||
return NULL;
|
||||
}
|
||||
rrset = local_data_find_type(ld, qinfo->qtype, 1);
|
||||
if(rrset == NULL) {
|
||||
verbose(VERB_ALGO, "rpz: qname after cname: type not found");
|
||||
verbose(VERB_ALGO, "rpz: qname: type not found");
|
||||
return NULL;
|
||||
}
|
||||
return rpz_synthesize_localdata_from_rrset(r, ms, qinfo, rrset, az);
|
||||
}
|
||||
|
||||
/** Synthesize a CNAME message for RPZ action override */
|
||||
static struct dns_msg*
|
||||
rpz_synthesize_cname_override_msg(struct rpz* r, struct module_qstate* ms,
|
||||
struct query_info* qinfo)
|
||||
{
|
||||
struct dns_msg* msg = NULL;
|
||||
struct reply_info* new_reply_info;
|
||||
struct ub_packed_rrset_key* rp;
|
||||
|
||||
msg = rpz_dns_msg_new(ms->region);
|
||||
if(msg == NULL) { return NULL; }
|
||||
|
||||
msg->qinfo = *qinfo;
|
||||
new_reply_info = construct_reply_info_base(ms->region,
|
||||
LDNS_RCODE_NOERROR | BIT_QR | BIT_AA | BIT_RA,
|
||||
1, /* qd */
|
||||
0, /* ttl */
|
||||
0, /* prettl */
|
||||
0, /* expttl */
|
||||
0, /* norecttl */
|
||||
1, /* an */
|
||||
0, /* ns */
|
||||
0, /* ar */
|
||||
1, /* total */
|
||||
sec_status_insecure,
|
||||
LDNS_EDE_NONE);
|
||||
if(new_reply_info == NULL) {
|
||||
log_err("out of memory");
|
||||
return NULL;
|
||||
}
|
||||
new_reply_info->authoritative = 1;
|
||||
|
||||
rp = respip_copy_rrset(r->cname_override, ms->region);
|
||||
if(rp == NULL) {
|
||||
log_err("out of memory");
|
||||
return NULL;
|
||||
}
|
||||
rp->rk.dname = qinfo->qname;
|
||||
rp->rk.dname_len = qinfo->qname_len;
|
||||
/* this rrset is from the rpz data, or synthesized.
|
||||
* It is not actually from the network, so we flag it with this
|
||||
* flags as a fake RRset. If later the cache is used to look up
|
||||
* rrsets, then the fake ones are not returned (if you look without
|
||||
* the flag). For like CNAME lookups from the iterator or A, AAAA
|
||||
* lookups for nameserver targets, it would use the without flag
|
||||
* actual data. So that the actual network data and fake data
|
||||
* are kept track of separately. */
|
||||
rp->rk.flags |= PACKED_RRSET_RPZ;
|
||||
new_reply_info->rrsets[0] = rp;
|
||||
|
||||
msg->rep = new_reply_info;
|
||||
return msg;
|
||||
}
|
||||
|
||||
static int
|
||||
rpz_synthesize_qname_localdata(struct module_env* env, struct rpz* r,
|
||||
struct local_zone* z, enum localzone_type lzt, struct query_info* qinfo,
|
||||
@@ -2072,17 +2223,8 @@ rpz_synthesize_qname_localdata(struct module_env* env, struct rpz* r,
|
||||
struct local_data* ld = NULL;
|
||||
int ret = 0;
|
||||
if(r->action_override == RPZ_CNAME_OVERRIDE_ACTION) {
|
||||
qinfo->local_alias = regional_alloc_zero(temp, sizeof(struct local_rrset));
|
||||
if(qinfo->local_alias == NULL) {
|
||||
return 0; /* out of memory */
|
||||
}
|
||||
qinfo->local_alias->rrset = regional_alloc_init(temp, r->cname_override,
|
||||
sizeof(*r->cname_override));
|
||||
if(qinfo->local_alias->rrset == NULL) {
|
||||
return 0; /* out of memory */
|
||||
}
|
||||
qinfo->local_alias->rrset->rk.dname = qinfo->qname;
|
||||
qinfo->local_alias->rrset->rk.dname_len = qinfo->qname_len;
|
||||
if(!rpz_apply_cname_override_action(r, qinfo, temp))
|
||||
return 0;
|
||||
if(r->log) {
|
||||
log_rpz_apply("qname", z->name, NULL, RPZ_CNAME_OVERRIDE_ACTION,
|
||||
qinfo, repinfo, NULL, r->log_name);
|
||||
@@ -2134,8 +2276,9 @@ rpz_delegation_point_ipbased_trigger_lookup(struct rpz* rpz, struct iter_qstate*
|
||||
}
|
||||
|
||||
static struct dns_msg*
|
||||
rpz_apply_nsip_trigger(struct module_qstate* ms, struct rpz* r,
|
||||
struct clientip_synthesized_rr* raddr, struct auth_zone* az)
|
||||
rpz_apply_nsip_trigger(struct module_qstate* ms, struct query_info* qchase,
|
||||
struct rpz* r, struct clientip_synthesized_rr* raddr,
|
||||
struct auth_zone* az)
|
||||
{
|
||||
enum rpz_action action = raddr->action;
|
||||
struct dns_msg* ret = NULL;
|
||||
@@ -2148,16 +2291,19 @@ rpz_apply_nsip_trigger(struct module_qstate* ms, struct rpz* r,
|
||||
|
||||
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, &ms->qinfo, az);
|
||||
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, &ms->qinfo, az);
|
||||
ret = rpz_synthesize_nxdomain(r, ms, qchase, az);
|
||||
ms->rpz_applied = 1;
|
||||
break;
|
||||
case RPZ_NODATA_ACTION:
|
||||
ret = rpz_synthesize_nodata(r, ms, &ms->qinfo, az);
|
||||
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
|
||||
@@ -2166,17 +2312,23 @@ rpz_apply_nsip_trigger(struct module_qstate* ms, struct rpz* r,
|
||||
ret = NULL;
|
||||
break;
|
||||
case RPZ_DROP_ACTION:
|
||||
ret = rpz_synthesize_nodata(r, ms, &ms->qinfo, az);
|
||||
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, raddr, az);
|
||||
if(ret == NULL) { ret = rpz_synthesize_nodata(r, ms, &ms->qinfo, az); }
|
||||
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;
|
||||
ms->rpz_passthru = 1;
|
||||
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'",
|
||||
rpz_action_to_string(action));
|
||||
@@ -2194,9 +2346,9 @@ done:
|
||||
}
|
||||
|
||||
static struct dns_msg*
|
||||
rpz_apply_nsdname_trigger(struct module_qstate* ms, struct rpz* r,
|
||||
struct local_zone* z, struct matched_delegation_point const* match,
|
||||
struct auth_zone* az)
|
||||
rpz_apply_nsdname_trigger(struct module_qstate* ms, struct query_info* qchase,
|
||||
struct rpz* r, struct local_zone* z,
|
||||
struct matched_delegation_point const* match, struct auth_zone* az)
|
||||
{
|
||||
struct dns_msg* ret = NULL;
|
||||
enum rpz_action action = localzone_type_to_rpz_action(z->type);
|
||||
@@ -2209,10 +2361,12 @@ rpz_apply_nsdname_trigger(struct module_qstate* ms, struct rpz* r,
|
||||
|
||||
switch(action) {
|
||||
case RPZ_NXDOMAIN_ACTION:
|
||||
ret = rpz_synthesize_nxdomain(r, ms, &ms->qinfo, az);
|
||||
ret = rpz_synthesize_nxdomain(r, ms, qchase, az);
|
||||
ms->rpz_applied = 1;
|
||||
break;
|
||||
case RPZ_NODATA_ACTION:
|
||||
ret = rpz_synthesize_nodata(r, ms, &ms->qinfo, az);
|
||||
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
|
||||
@@ -2221,19 +2375,25 @@ rpz_apply_nsdname_trigger(struct module_qstate* ms, struct rpz* r,
|
||||
ret = NULL;
|
||||
break;
|
||||
case RPZ_DROP_ACTION:
|
||||
ret = rpz_synthesize_nodata(r, ms, &ms->qinfo, az);
|
||||
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, z, match, az);
|
||||
if(ret == NULL) { ret = rpz_synthesize_nodata(r, ms, &ms->qinfo, az); }
|
||||
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;
|
||||
ms->rpz_passthru = 1;
|
||||
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'",
|
||||
verbose(VERB_ALGO, "rpz: nsdname: bug: unhandled or invalid action: '%s'",
|
||||
rpz_action_to_string(action));
|
||||
ret = NULL;
|
||||
}
|
||||
@@ -2302,11 +2462,10 @@ rpz_callback_from_iterator_module(struct module_qstate* ms, struct iter_qstate*
|
||||
if(ms->env == NULL || ms->env->auth_zones == NULL) { return 0; }
|
||||
|
||||
az = ms->env->auth_zones;
|
||||
lock_rw_rdlock(&az->rpz_lock);
|
||||
|
||||
verbose(VERB_ALGO, "rpz: iterator module callback: have_rpz=%d", az->rpz_first != NULL);
|
||||
|
||||
lock_rw_rdlock(&az->rpz_lock);
|
||||
|
||||
/* precedence of RPZ works, loosely, like this:
|
||||
* CNAMEs in order of the CNAME chain. rpzs in the order they are
|
||||
* configured. In an RPZ: first client-IP addr, then QNAME, then
|
||||
@@ -2321,10 +2480,17 @@ rpz_callback_from_iterator_module(struct module_qstate* ms, struct iter_qstate*
|
||||
lock_rw_unlock(&a->lock);
|
||||
continue;
|
||||
}
|
||||
if(r->taglist && (!ms->client_info ||
|
||||
!taglist_intersect(r->taglist, r->taglistlen,
|
||||
ms->client_info->taglist,
|
||||
ms->client_info->taglen))) {
|
||||
lock_rw_unlock(&a->lock);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* the nsdname has precedence over the nsip triggers */
|
||||
z = rpz_delegation_point_zone_lookup(is->dp, r->nsdname_zones,
|
||||
ms->qinfo.qclass, &match);
|
||||
is->qchase.qclass, &match);
|
||||
if(z != NULL) {
|
||||
lock_rw_unlock(&a->lock);
|
||||
break;
|
||||
@@ -2347,9 +2513,9 @@ rpz_callback_from_iterator_module(struct module_qstate* ms, struct iter_qstate*
|
||||
if(z) {
|
||||
lock_rw_unlock(&z->lock);
|
||||
}
|
||||
return rpz_apply_nsip_trigger(ms, r, raddr, a);
|
||||
return rpz_apply_nsip_trigger(ms, &is->qchase, r, raddr, a);
|
||||
}
|
||||
return rpz_apply_nsdname_trigger(ms, r, z, &match, a);
|
||||
return rpz_apply_nsdname_trigger(ms, &is->qchase, r, z, &match, a);
|
||||
}
|
||||
|
||||
struct dns_msg* rpz_callback_from_iterator_cname(struct module_qstate* ms,
|
||||
@@ -2379,6 +2545,13 @@ struct dns_msg* rpz_callback_from_iterator_cname(struct module_qstate* ms,
|
||||
lock_rw_unlock(&a->lock);
|
||||
continue;
|
||||
}
|
||||
if(r->taglist && (!ms->client_info ||
|
||||
!taglist_intersect(r->taglist, r->taglistlen,
|
||||
ms->client_info->taglist,
|
||||
ms->client_info->taglen))) {
|
||||
lock_rw_unlock(&a->lock);
|
||||
continue;
|
||||
}
|
||||
z = rpz_find_zone(r->local_zones, is->qchase.qname,
|
||||
is->qchase.qname_len, is->qchase.qclass, 0, 0, 0);
|
||||
if(z && r->action_override == RPZ_DISABLED_ACTION) {
|
||||
@@ -2412,18 +2585,20 @@ struct dns_msg* rpz_callback_from_iterator_cname(struct module_qstate* ms,
|
||||
dname_str(is->qchase.qname, nm);
|
||||
dname_str(z->name, zn);
|
||||
if(strcmp(zn, nm) != 0)
|
||||
verbose(VERB_ALGO, "rpz: qname trigger after cname %s on %s, with action=%s",
|
||||
verbose(VERB_ALGO, "rpz: qname trigger %s on %s, with action=%s",
|
||||
zn, nm, rpz_action_to_string(localzone_type_to_rpz_action(lzt)));
|
||||
else
|
||||
verbose(VERB_ALGO, "rpz: qname trigger after cname %s, with action=%s",
|
||||
verbose(VERB_ALGO, "rpz: qname trigger %s, with action=%s",
|
||||
nm, rpz_action_to_string(localzone_type_to_rpz_action(lzt)));
|
||||
}
|
||||
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
|
||||
@@ -2433,18 +2608,20 @@ 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;
|
||||
ms->rpz_passthru = 1;
|
||||
break;
|
||||
default:
|
||||
verbose(VERB_ALGO, "rpz: qname trigger after cname: bug: unhandled or invalid action: '%s'",
|
||||
verbose(VERB_ALGO, "rpz: qname trigger: bug: unhandled or invalid action: '%s'",
|
||||
rpz_action_to_string(localzone_type_to_rpz_action(lzt)));
|
||||
ret = NULL;
|
||||
}
|
||||
@@ -2472,8 +2649,21 @@ rpz_apply_maybe_clientip_trigger(struct auth_zones* az, struct module_env* env,
|
||||
az, qinfo, repinfo, taglist, taglen, stats, z_out, a_out, r_out);
|
||||
|
||||
client_action = ((node == NULL) ? RPZ_INVALID_ACTION : node->action);
|
||||
if(node != NULL && *r_out &&
|
||||
(*r_out)->action_override != RPZ_NO_OVERRIDE_ACTION) {
|
||||
client_action = (*r_out)->action_override;
|
||||
}
|
||||
if(client_action == RPZ_PASSTHRU_ACTION) {
|
||||
if(*r_out && (*r_out)->log)
|
||||
log_rpz_apply(
|
||||
(node?"clientip":"qname"),
|
||||
((*z_out)?(*z_out)->name:NULL),
|
||||
(node?&node->node:NULL),
|
||||
client_action, qinfo, repinfo, NULL,
|
||||
(*r_out)->log_name);
|
||||
*passthru = 1;
|
||||
ret = 0;
|
||||
goto done;
|
||||
}
|
||||
if(*z_out == NULL || (client_action != RPZ_INVALID_ACTION &&
|
||||
client_action != RPZ_PASSTHRU_ACTION)) {
|
||||
@@ -2488,14 +2678,15 @@ rpz_apply_maybe_clientip_trigger(struct auth_zones* az, struct module_env* env,
|
||||
if(client_action == RPZ_LOCAL_DATA_ACTION) {
|
||||
rpz_apply_clientip_localdata_action(node, env, qinfo,
|
||||
edns, repinfo, buf, temp, *a_out);
|
||||
ret = 1;
|
||||
} else if(client_action == RPZ_CNAME_OVERRIDE_ACTION) {
|
||||
if(!rpz_apply_cname_override_action(*r_out, qinfo,
|
||||
temp)) {
|
||||
ret = 0;
|
||||
goto done;
|
||||
}
|
||||
ret = 0;
|
||||
} else {
|
||||
if(*r_out && (*r_out)->log)
|
||||
log_rpz_apply(
|
||||
(node?"clientip":"qname"),
|
||||
((*z_out)?(*z_out)->name:NULL),
|
||||
(node?&node->node:NULL),
|
||||
client_action, qinfo, repinfo, NULL,
|
||||
(*r_out)->log_name);
|
||||
local_zones_zone_answer(*z_out /*likely NULL, no zone*/, env, qinfo, edns,
|
||||
repinfo, buf, temp, 0 /* no local data used */,
|
||||
rpz_action_to_localzone_type(client_action));
|
||||
@@ -2503,8 +2694,15 @@ rpz_apply_maybe_clientip_trigger(struct auth_zones* az, struct module_env* env,
|
||||
LDNS_RCODE_WIRE(sldns_buffer_begin(buf))
|
||||
== LDNS_RCODE_NXDOMAIN)
|
||||
LDNS_RA_CLR(sldns_buffer_begin(buf));
|
||||
ret = 1;
|
||||
}
|
||||
ret = 1;
|
||||
if(*r_out && (*r_out)->log)
|
||||
log_rpz_apply(
|
||||
(node?"clientip":"qname"),
|
||||
((*z_out)?(*z_out)->name:NULL),
|
||||
(node?&node->node:NULL),
|
||||
client_action, qinfo, repinfo, NULL,
|
||||
(*r_out)->log_name);
|
||||
goto done;
|
||||
}
|
||||
ret = -1;
|
||||
|
||||
@@ -225,6 +225,14 @@ int rpz_clear(struct rpz* r);
|
||||
*/
|
||||
struct rpz* rpz_create(struct config_auth* p);
|
||||
|
||||
/**
|
||||
* Change config on rpz, after reload.
|
||||
* @param r: the rpz structure.
|
||||
* @param p: the config that was read.
|
||||
* @return false on failure.
|
||||
*/
|
||||
int rpz_config(struct rpz* r, struct config_auth* p);
|
||||
|
||||
/**
|
||||
* String for RPZ action enum
|
||||
* @param a: RPZ action to get string for
|
||||
|
||||
+2
-1
@@ -126,7 +126,8 @@ void view_delete(struct view* v);
|
||||
*/
|
||||
void views_print(struct views* v);
|
||||
|
||||
/* Find a view by name.
|
||||
/**
|
||||
* Find a view by name.
|
||||
* @param vs: views
|
||||
* @param name: name of the view we are looking for
|
||||
* @param write: 1 for obtaining write lock on found view, 0 for read lock
|
||||
|
||||
+3
-3
@@ -106,7 +106,7 @@ ssize_t sldns_bget_token(struct sldns_buffer *b, char *token, const char *delim,
|
||||
* \param[in] k_del keyword delimiter
|
||||
* \param[out] data the data found
|
||||
* \param[in] d_del the data delimiter
|
||||
* \param[in] data_limit maximum size the the data buffer
|
||||
* \param[in] data_limit maximum size the data buffer
|
||||
* \return the number of character read
|
||||
*/
|
||||
ssize_t sldns_fget_keyword_data(FILE *f, const char *keyword, const char *k_del, char *data, const char *d_del, size_t data_limit);
|
||||
@@ -119,7 +119,7 @@ ssize_t sldns_fget_keyword_data(FILE *f, const char *keyword, const char *k_del,
|
||||
* \param[in] k_del keyword delimiter
|
||||
* \param[out] data the data found
|
||||
* \param[in] d_del the data delimiter
|
||||
* \param[in] data_limit maximum size the the data buffer
|
||||
* \param[in] data_limit maximum size the data buffer
|
||||
* \param[in] line_nr pointer to an integer containing the current line number (for
|
||||
debugging purposes)
|
||||
* \return the number of character read
|
||||
@@ -134,7 +134,7 @@ ssize_t sldns_fget_keyword_data_l(FILE *f, const char *keyword, const char *k_de
|
||||
* \param[in] k_del keyword delimiter
|
||||
* \param[out] data the data found
|
||||
* \param[in] d_del the data delimiter
|
||||
* \param[in] data_limit maximum size the the data buffer
|
||||
* \param[in] data_limit maximum size the data buffer
|
||||
* \return the number of character read
|
||||
*/
|
||||
ssize_t sldns_bget_keyword_data(struct sldns_buffer *b, const char *keyword, const char *k_del, char *data, const char *d_del, size_t data_limit);
|
||||
|
||||
@@ -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...... ........ ........ ........ */
|
||||
|
||||
@@ -470,6 +470,11 @@ enum sldns_enum_ede_code
|
||||
LDNS_EDE_NO_REACHABLE_AUTHORITY = 22,
|
||||
LDNS_EDE_NETWORK_ERROR = 23,
|
||||
LDNS_EDE_INVALID_DATA = 24,
|
||||
LDNS_EDE_SIGNATURE_EXPIRED_BEFORE_VALID = 25,
|
||||
LDNS_EDE_TOO_EARLY = 26,
|
||||
LDNS_EDE_UNSUPPORTED_NSEC3_ITERATIONS = 27,
|
||||
LDNS_EDE_BADPROXYPOLICY = 28,
|
||||
LDNS_EDE_SYNTHESIZED = 29
|
||||
};
|
||||
typedef enum sldns_enum_ede_code sldns_ede_code;
|
||||
|
||||
|
||||
@@ -228,6 +228,11 @@ static sldns_lookup_table sldns_edns_ede_codes_data[] = {
|
||||
{ LDNS_EDE_NO_REACHABLE_AUTHORITY, "No Reachable Authority" },
|
||||
{ LDNS_EDE_NETWORK_ERROR, "Network Error" },
|
||||
{ LDNS_EDE_INVALID_DATA, "Invalid Data" },
|
||||
{ LDNS_EDE_SIGNATURE_EXPIRED_BEFORE_VALID, "Signature Expired Before Valid" },
|
||||
{ LDNS_EDE_TOO_EARLY, "Non-Replayable Transactions Received in 0-RTT Data" },
|
||||
{ LDNS_EDE_UNSUPPORTED_NSEC3_ITERATIONS, "Unsupported NSEC3 Iterations Value" },
|
||||
{ LDNS_EDE_BADPROXYPOLICY, "Unable to Conform to Policy" },
|
||||
{ LDNS_EDE_SYNTHESIZED, "Synthesized Answer" },
|
||||
{ 0, NULL}
|
||||
};
|
||||
sldns_lookup_table* sldns_edns_ede_codes = sldns_edns_ede_codes_data;
|
||||
@@ -1236,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, "=\"");
|
||||
|
||||
+55
-25
@@ -151,7 +151,7 @@
|
||||
#define HTTPS_PORT 443
|
||||
|
||||
#ifdef USE_WINSOCK
|
||||
/* sneakily reuse the the wsa_strerror function, on windows */
|
||||
/* sneakily reuse the wsa_strerror function, on windows */
|
||||
char* wsa_strerror(int err);
|
||||
#endif
|
||||
|
||||
@@ -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;
|
||||
@@ -805,7 +807,11 @@ TLS_initiate(SSL_CTX* sslctx, int fd, const char* urlname, int use_sni)
|
||||
}
|
||||
/* wants to be called again */
|
||||
}
|
||||
#ifdef HAVE_SSL_GET1_PEER_CERTIFICATE
|
||||
x = SSL_get1_peer_certificate(ssl);
|
||||
#else
|
||||
x = SSL_get_peer_certificate(ssl);
|
||||
#endif
|
||||
if(!x) {
|
||||
if(verb) printf("Server presented no peer certificate\n");
|
||||
SSL_free(ssl);
|
||||
@@ -1835,15 +1841,49 @@ verify_p7sig(BIO* data, BIO* p7s, STACK_OF(X509)* trust, const char* p7signer)
|
||||
return secure;
|
||||
}
|
||||
|
||||
/** open a temp file */
|
||||
static FILE*
|
||||
tempfile_open(char* tempf, size_t tempflen, const char* fname, const char* mode)
|
||||
{
|
||||
snprintf(tempf, tempflen, "%s~", fname);
|
||||
return fopen(tempf, mode);
|
||||
}
|
||||
|
||||
/** close an open temp file and replace the original with it */
|
||||
static void
|
||||
tempfile_close(FILE* fd, const char* tempf, const char* fname)
|
||||
{
|
||||
fflush(fd);
|
||||
#ifdef HAVE_FSYNC
|
||||
fsync(fileno(fd));
|
||||
#else
|
||||
FlushFileBuffers((HANDLE)_get_osfhandle(_fileno(fd)));
|
||||
#endif
|
||||
if(fclose(fd) != 0) {
|
||||
printf("could not complete write: %s: %s\n",
|
||||
tempf, strerror(errno));
|
||||
unlink(tempf);
|
||||
return;
|
||||
}
|
||||
/* success; overwrite actual file */
|
||||
#ifdef USE_WINSOCK
|
||||
(void)unlink(fname); /* windows does not replace file with rename() */
|
||||
#endif
|
||||
if(rename(tempf, fname) < 0) {
|
||||
printf("rename(%s to %s): %s", tempf, fname, strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
/** write unsigned root anchor file, a 5011 revoked tp */
|
||||
static void
|
||||
write_unsigned_root(const char* root_anchor_file)
|
||||
{
|
||||
FILE* out;
|
||||
time_t now = time(NULL);
|
||||
out = fopen(root_anchor_file, "w");
|
||||
char tempf[2048];
|
||||
out = tempfile_open(tempf, sizeof(tempf), root_anchor_file, "w");
|
||||
if(!out) {
|
||||
if(verb) printf("%s: %s\n", root_anchor_file, strerror(errno));
|
||||
if(verb) printf("%s: %s\n", tempf, strerror(errno));
|
||||
return;
|
||||
}
|
||||
if(fprintf(out, "; autotrust trust anchor file\n"
|
||||
@@ -1858,13 +1898,7 @@ write_unsigned_root(const char* root_anchor_file)
|
||||
root_anchor_file);
|
||||
if(verb && errno != 0) printf("%s\n", strerror(errno));
|
||||
}
|
||||
fflush(out);
|
||||
#ifdef HAVE_FSYNC
|
||||
fsync(fileno(out));
|
||||
#else
|
||||
FlushFileBuffers((HANDLE)_get_osfhandle(_fileno(out)));
|
||||
#endif
|
||||
fclose(out);
|
||||
tempfile_close(out, tempf, root_anchor_file);
|
||||
}
|
||||
|
||||
/** write root anchor file */
|
||||
@@ -1874,29 +1908,24 @@ write_root_anchor(const char* root_anchor_file, BIO* ds)
|
||||
char* pp = NULL;
|
||||
int len;
|
||||
FILE* out;
|
||||
char tempf[2048];
|
||||
(void)BIO_seek(ds, 0);
|
||||
len = BIO_get_mem_data(ds, &pp);
|
||||
if(!len || !pp) {
|
||||
if(verb) printf("out of memory\n");
|
||||
return;
|
||||
}
|
||||
out = fopen(root_anchor_file, "w");
|
||||
out = tempfile_open(tempf, sizeof(tempf), root_anchor_file, "w");
|
||||
if(!out) {
|
||||
if(verb) printf("%s: %s\n", root_anchor_file, strerror(errno));
|
||||
if(verb) printf("%s: %s\n", tempf, strerror(errno));
|
||||
return;
|
||||
}
|
||||
if(fwrite(pp, (size_t)len, 1, out) != 1) {
|
||||
if(verb) printf("failed to write all data to %s\n",
|
||||
root_anchor_file);
|
||||
tempf);
|
||||
if(verb && errno != 0) printf("%s\n", strerror(errno));
|
||||
}
|
||||
fflush(out);
|
||||
#ifdef HAVE_FSYNC
|
||||
fsync(fileno(out));
|
||||
#else
|
||||
FlushFileBuffers((HANDLE)_get_osfhandle(_fileno(out)));
|
||||
#endif
|
||||
fclose(out);
|
||||
tempfile_close(out, tempf, root_anchor_file);
|
||||
}
|
||||
|
||||
/** Perform the verification and update of the trustanchor file */
|
||||
@@ -2040,18 +2069,19 @@ try_read_anchor(const char* file)
|
||||
static void
|
||||
write_builtin_anchor(const char* file)
|
||||
{
|
||||
char tempf[2048];
|
||||
const char* builtin_root_anchor = get_builtin_ds();
|
||||
FILE* out = fopen(file, "w");
|
||||
FILE* out = tempfile_open(tempf, sizeof(tempf), file, "w");
|
||||
if(!out) {
|
||||
printf("could not write builtin anchor, to file %s: %s\n",
|
||||
file, strerror(errno));
|
||||
tempf, strerror(errno));
|
||||
return;
|
||||
}
|
||||
if(!fwrite(builtin_root_anchor, strlen(builtin_root_anchor), 1, out)) {
|
||||
printf("could not complete write builtin anchor, to file %s: %s\n",
|
||||
file, strerror(errno));
|
||||
tempf, strerror(errno));
|
||||
}
|
||||
fclose(out);
|
||||
tempfile_close(out, tempf, file);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -88,6 +88,7 @@ usage(void)
|
||||
printf("file if omitted %s is used.\n", CONFIGFILE);
|
||||
printf("-o option print value of option to stdout.\n");
|
||||
printf("-f output full pathname with chroot applied, eg. with -o pidfile.\n");
|
||||
printf("-q quiet (suppress output on success).\n");
|
||||
printf("-h show this usage help.\n");
|
||||
printf("Version %s\n", PACKAGE_VERSION);
|
||||
printf("BSD licensed, see LICENSE in source package for details.\n");
|
||||
@@ -139,10 +140,13 @@ check_mod(struct config_file* cfg, struct module_func_block* fb)
|
||||
fatal_exit("out of memory");
|
||||
if(!edns_known_options_init(&env))
|
||||
fatal_exit("out of memory");
|
||||
if(!(*fb->init)(&env, 0)) {
|
||||
fatal_exit("bad config for %s module", fb->name);
|
||||
}
|
||||
if(fb->startup && !(*fb->startup)(&env, 0))
|
||||
fatal_exit("bad config during startup for %s module", fb->name);
|
||||
if(!(*fb->init)(&env, 0))
|
||||
fatal_exit("bad config during init for %s module", fb->name);
|
||||
(*fb->deinit)(&env, 0);
|
||||
if(fb->destartup)
|
||||
(*fb->destartup)(&env, 0);
|
||||
sldns_buffer_free(env.scratch_buffer);
|
||||
regional_destroy(env.scratch);
|
||||
edns_known_options_delete(&env);
|
||||
@@ -965,7 +969,7 @@ check_auth(struct config_file* cfg)
|
||||
|
||||
/** check config file */
|
||||
static void
|
||||
checkconf(const char* cfgfile, const char* opt, int final)
|
||||
checkconf(const char* cfgfile, const char* opt, int final, int quiet)
|
||||
{
|
||||
char oldwd[4096];
|
||||
struct config_file* cfg = config_create();
|
||||
@@ -998,7 +1002,7 @@ checkconf(const char* cfgfile, const char* opt, int final)
|
||||
check_fwd(cfg);
|
||||
check_hints(cfg);
|
||||
check_auth(cfg);
|
||||
printf("unbound-checkconf: no errors in %s\n", cfgfile);
|
||||
if(!quiet) { printf("unbound-checkconf: no errors in %s\n", cfgfile); }
|
||||
config_delete(cfg);
|
||||
}
|
||||
|
||||
@@ -1012,6 +1016,7 @@ int main(int argc, char* argv[])
|
||||
{
|
||||
int c;
|
||||
int final = 0;
|
||||
int quiet = 0;
|
||||
const char* f;
|
||||
const char* opt = NULL;
|
||||
const char* cfgfile = CONFIGFILE;
|
||||
@@ -1024,7 +1029,7 @@ int main(int argc, char* argv[])
|
||||
cfgfile = CONFIGFILE;
|
||||
#endif /* USE_WINSOCK */
|
||||
/* parse the options */
|
||||
while( (c=getopt(argc, argv, "fho:")) != -1) {
|
||||
while( (c=getopt(argc, argv, "fhqo:")) != -1) {
|
||||
switch(c) {
|
||||
case 'f':
|
||||
final = 1;
|
||||
@@ -1032,6 +1037,9 @@ int main(int argc, char* argv[])
|
||||
case 'o':
|
||||
opt = optarg;
|
||||
break;
|
||||
case 'q':
|
||||
quiet = 1;
|
||||
break;
|
||||
case '?':
|
||||
case 'h':
|
||||
default:
|
||||
@@ -1045,7 +1053,7 @@ int main(int argc, char* argv[])
|
||||
if(argc == 1)
|
||||
f = argv[0];
|
||||
else f = cfgfile;
|
||||
checkconf(f, opt, final);
|
||||
checkconf(f, opt, final, quiet);
|
||||
checklock_stop();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -104,6 +104,10 @@ while getopts 'd:hr' arg; do
|
||||
done
|
||||
shift $((OPTIND - 1))
|
||||
|
||||
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
|
||||
|
||||
echo "setup in directory $DESTDIR"
|
||||
cd "$DESTDIR"
|
||||
|
||||
@@ -122,20 +122,27 @@ usage(void)
|
||||
printf(" local_data <RR data...> add local data, for example\n");
|
||||
printf(" local_data www.example.com A 192.0.2.1\n");
|
||||
printf(" local_data_remove <name> remove local RR data from name\n");
|
||||
printf(" local_zones, local_zones_remove, local_datas, local_datas_remove\n");
|
||||
printf(" same, but read list from stdin\n");
|
||||
printf(" local_zones,\n");
|
||||
printf(" local_zones_remove,\n");
|
||||
printf(" local_datas,\n");
|
||||
printf(" local_datas_remove same, but read list from stdin\n");
|
||||
printf(" (one entry per line).\n");
|
||||
printf(" dump_cache print cache to stdout\n");
|
||||
printf(" (not supported in remote unbounds in\n");
|
||||
printf(" multi-process operation)\n");
|
||||
printf(" load_cache load cache from stdin\n");
|
||||
printf(" (not supported in remote unbounds in\n");
|
||||
printf(" multi-process operation)\n");
|
||||
printf(" lookup <name> print nameservers for name\n");
|
||||
printf(" flush <name> flushes common types for name from cache\n");
|
||||
printf(" flush [+c] <name> flushes common types for name from cache\n");
|
||||
printf(" types: A, AAAA, MX, PTR, NS,\n");
|
||||
printf(" SOA, CNAME, DNAME, SRV, NAPTR\n");
|
||||
printf(" flush_type <name> <type> flush name, type from cache\n");
|
||||
printf(" flush_zone <name> flush everything at or under name\n");
|
||||
printf(" flush_type [+c] <name> <type> flush name, type from cache\n");
|
||||
printf(" +c remove from cachedb too\n");
|
||||
printf(" flush_zone [+c] <name> flush everything at or under name\n");
|
||||
printf(" from rr and dnssec caches\n");
|
||||
printf(" flush_bogus flush all bogus data\n");
|
||||
printf(" flush_negative flush all negative data\n");
|
||||
printf(" flush_bogus [+c] flush all bogus data\n");
|
||||
printf(" flush_negative [+c] flush all negative data\n");
|
||||
printf(" flush_stats flush statistics, make zero\n");
|
||||
printf(" flush_requestlist drop queries that are worked on\n");
|
||||
printf(" dump_requestlist show what is worked on by first thread\n");
|
||||
@@ -150,12 +157,13 @@ usage(void)
|
||||
printf(" list_local_data list local-data RRs in use\n");
|
||||
printf(" insecure_add zone add domain-insecure zone\n");
|
||||
printf(" insecure_remove zone remove domain-insecure zone\n");
|
||||
printf(" forward_add [+i] zone addr.. add forward-zone with servers\n");
|
||||
printf(" forward_add [+it] zone addr.. add forward-zone with servers\n");
|
||||
printf(" forward_remove [+i] zone remove forward zone\n");
|
||||
printf(" stub_add [+ip] zone addr.. add stub-zone with servers\n");
|
||||
printf(" stub_add [+ipt] zone addr.. add stub-zone with servers\n");
|
||||
printf(" stub_remove [+i] zone remove stub zone\n");
|
||||
printf(" +i also do dnssec insecure point\n");
|
||||
printf(" +p set stub to use priming\n");
|
||||
printf(" +t set to use tls upstream\n");
|
||||
printf(" forward [off | addr ...] without arg show forward setup\n");
|
||||
printf(" or off to turn off root forwarding\n");
|
||||
printf(" or give list of ip addresses\n");
|
||||
@@ -178,6 +186,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);
|
||||
@@ -281,6 +293,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 */
|
||||
@@ -347,6 +362,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);
|
||||
@@ -751,7 +769,11 @@ setup_ssl(SSL_CTX* ctx, int fd)
|
||||
/* check authenticity of server */
|
||||
if(SSL_get_verify_result(ssl) != X509_V_OK)
|
||||
ssl_err("SSL verification failed");
|
||||
#ifdef HAVE_SSL_GET1_PEER_CERTIFICATE
|
||||
x = SSL_get1_peer_certificate(ssl);
|
||||
#else
|
||||
x = SSL_get_peer_certificate(ssl);
|
||||
#endif
|
||||
if(!x)
|
||||
ssl_err("Server presented no peer certificate");
|
||||
X509_free(x);
|
||||
|
||||
@@ -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,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
|
||||
|
||||
+8
-6
@@ -2,17 +2,19 @@
|
||||
# Copyright 2015, Sami Kerola, CloudFlare.
|
||||
# BSD licensed.
|
||||
AC_ARG_ENABLE([systemd],
|
||||
[AS_HELP_STRING([--enable-systemd], [compile with systemd support])],
|
||||
[AS_HELP_STRING([--enable-systemd], [compile with systemd support (requires libsystemd, pkg-config)])],
|
||||
[], [enable_systemd=no])
|
||||
have_systemd=no
|
||||
AS_IF([test "x$enable_systemd" != xno], [
|
||||
ifdef([PKG_CHECK_MODULES], [
|
||||
if test -n "$PKG_CONFIG"; then
|
||||
dnl systemd v209 or newer
|
||||
PKG_CHECK_MODULES([SYSTEMD], [libsystemd], [have_systemd=yes], [have_systemd=no])
|
||||
have_systemd=no
|
||||
PKG_CHECK_MODULES([SYSTEMD], [libsystemd], [have_systemd=yes], [])
|
||||
dnl old systemd library
|
||||
AS_IF([test "x$have_systemd" != "xyes"], [
|
||||
have_systemd_daemon=no
|
||||
PKG_CHECK_MODULES([SYSTEMD_DAEMON], [libsystemd-daemon],
|
||||
[have_systemd_daemon=yes], [have_systemd_daemon=no])
|
||||
[have_systemd_daemon=yes], [])
|
||||
AS_IF([test "x$have_systemd_daemon" = "xyes"],
|
||||
[have_systemd=yes])
|
||||
])
|
||||
@@ -24,8 +26,8 @@ AS_IF([test "x$enable_systemd" != xno], [
|
||||
LIBS="$LIBS $SYSTEMD_LIBS"
|
||||
]
|
||||
)
|
||||
], [
|
||||
else
|
||||
AC_MSG_ERROR([systemd enabled but need pkg-config to configure for it])
|
||||
])
|
||||
fi
|
||||
])
|
||||
AM_CONDITIONAL([USE_SYSTEMD], [test "x$have_systemd" = xyes])
|
||||
|
||||
+42
-2
@@ -68,6 +68,19 @@ static struct thr_check* thread_infos[THRDEBUG_MAX_THREADS];
|
||||
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
|
||||
* would loop otherwise.
|
||||
*/
|
||||
static int verbose_locking = 0;
|
||||
/**
|
||||
* Assume lock 0 0 (create_thread, create_instance), is the log lock and
|
||||
* do not print for that. Otherwise the output is full of log lock accesses.
|
||||
*/
|
||||
static int verbose_locking_not_loglock = 1;
|
||||
|
||||
/** print all possible debug info on the state of the system */
|
||||
static void total_debug_info(void);
|
||||
@@ -131,7 +144,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(
|
||||
@@ -140,6 +154,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");
|
||||
@@ -192,6 +210,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");
|
||||
}
|
||||
@@ -508,6 +529,9 @@ checklock_rdlock(enum check_lock_type type, struct checked_lock* lock,
|
||||
if(key_deleted)
|
||||
return;
|
||||
|
||||
if(verbose_locking && !(verbose_locking_not_loglock &&
|
||||
lock->create_thread == 0 && lock->create_instance == 0))
|
||||
fprintf(stderr, "checklock_rdlock lock %d %d %s:%d at %s:%d\n", lock->create_thread, lock->create_instance, lock->create_file, lock->create_line, file, line);
|
||||
log_assert(type == check_lock_rwlock);
|
||||
checklock_lockit(type, lock, func, file, line,
|
||||
try_rd, timed_rd, &lock->u.rwlock, 0, 0);
|
||||
@@ -528,6 +552,9 @@ checklock_wrlock(enum check_lock_type type, struct checked_lock* lock,
|
||||
if(key_deleted)
|
||||
return;
|
||||
log_assert(type == check_lock_rwlock);
|
||||
if(verbose_locking && !(verbose_locking_not_loglock &&
|
||||
lock->create_thread == 0 && lock->create_instance == 0))
|
||||
fprintf(stderr, "checklock_wrlock lock %d %d %s:%d at %s:%d\n", lock->create_thread, lock->create_instance, lock->create_file, lock->create_line, file, line);
|
||||
checklock_lockit(type, lock, func, file, line,
|
||||
try_wr, timed_wr, &lock->u.rwlock, 0, 1);
|
||||
}
|
||||
@@ -565,6 +592,9 @@ checklock_lock(enum check_lock_type type, struct checked_lock* lock,
|
||||
if(key_deleted)
|
||||
return;
|
||||
log_assert(type != check_lock_rwlock);
|
||||
if(verbose_locking && !(verbose_locking_not_loglock &&
|
||||
lock->create_thread == 0 && lock->create_instance == 0))
|
||||
fprintf(stderr, "checklock_lock lock %d %d %s:%d at %s:%d\n", lock->create_thread, lock->create_instance, lock->create_file, lock->create_line, file, line);
|
||||
switch(type) {
|
||||
case check_lock_mutex:
|
||||
checklock_lockit(type, lock, func, file, line,
|
||||
@@ -602,6 +632,10 @@ checklock_unlock(enum check_lock_type type, struct checked_lock* lock,
|
||||
if(lock->hold_count <= 0)
|
||||
lock_error(lock, func, file, line, "too many unlocks");
|
||||
|
||||
if(verbose_locking && !(verbose_locking_not_loglock &&
|
||||
lock->create_thread == 0 && lock->create_instance == 0))
|
||||
fprintf(stderr, "checklock_unlock lock %d %d %s:%d at %s:%d\n", lock->create_thread, lock->create_instance, lock->create_file, lock->create_line, file, line);
|
||||
|
||||
/* store this point as last touched by */
|
||||
lock->holder = thr;
|
||||
lock->hold_count --;
|
||||
@@ -651,13 +685,19 @@ 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);
|
||||
snprintf(buf, sizeof(buf), "%s.%d", output_name, thr->num);
|
||||
thr->order_info = fopen(buf, "w");
|
||||
if(!thr->order_info)
|
||||
fatal_exit("could not open %s: %s", buf, strerror(errno));
|
||||
|
||||
+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.
|
||||
*/
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user