mirror of
https://github.com/NLnetLabs/unbound.git
synced 2026-10-14 12:35:11 +02:00
Compare commits
285
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cd0a585fbe | ||
|
|
d1ea227e94 | ||
|
|
18d8676e9c | ||
|
|
7c624d1dcd | ||
|
|
e23010c18e | ||
|
|
ddcbc291fe | ||
|
|
a119b1abc6 | ||
|
|
f62214e714 | ||
|
|
3d1aaae57a | ||
|
|
614dcbf675 | ||
|
|
add0065c43 | ||
|
|
3d53f08bd8 | ||
|
|
0dcd4cd2e8 | ||
|
|
b449d6f713 | ||
|
|
6932ae18f5 | ||
|
|
e2537840ba | ||
|
|
b425be8e10 | ||
|
|
bb408e503c | ||
|
|
8942d11bb3 | ||
|
|
cb027ae649 | ||
|
|
eafb027166 | ||
|
|
40d36cda61 | ||
|
|
8cf2202c52 | ||
|
|
f6fff9efcb | ||
|
|
97c001f9dd | ||
|
|
1e12bef540 | ||
|
|
b49f452f0a | ||
|
|
8820254637 | ||
|
|
5483a73856 | ||
|
|
0e2470450c | ||
|
|
65814ad6f3 | ||
|
|
97d6cc3643 | ||
|
|
e79365ec61 | ||
|
|
a7fc80d8c5 | ||
|
|
5d89e0c2a7 | ||
|
|
b45c8b4b53 | ||
|
|
a6586ced92 | ||
|
|
13b6717f17 | ||
|
|
0d4a6a63dd | ||
|
|
bd71e3b8a6 | ||
|
|
3a6ba0da81 | ||
|
|
3d65973d38 | ||
|
|
565651cd02 | ||
|
|
7914901915 | ||
|
|
eba3d35ad4 | ||
|
|
8c2e0fd6cc | ||
|
|
e619ead2db | ||
|
|
eb86d9bc50 | ||
|
|
3ad9b6aade | ||
|
|
5ccee67af2 | ||
|
|
b8577a9c04 | ||
|
|
18d9a5519e | ||
|
|
2df646e05f | ||
|
|
bdfa4d4c5d | ||
|
|
bd210d124b | ||
|
|
11900cc2b0 | ||
|
|
c04a5efb07 | ||
|
|
1060760650 | ||
|
|
f251a1157b | ||
|
|
292cf6526b | ||
|
|
ac935b9144 | ||
|
|
9dd370ba04 | ||
|
|
a6ccb2f74d | ||
|
|
32ff948a5b | ||
|
|
2ec2afd6b0 | ||
|
|
7fb79b0677 | ||
|
|
48d0aea60a | ||
|
|
17bbcac979 | ||
|
|
fd8ebbb19c | ||
|
|
2adbbea365 | ||
|
|
8ee0bca833 | ||
|
|
c58e6add2b | ||
|
|
156c00a727 | ||
|
|
d753f95956 | ||
|
|
93a56205cf | ||
|
|
709f622658 | ||
|
|
307fc6f062 | ||
|
|
8b33c5d7ff | ||
|
|
36bd52afb9 | ||
|
|
b7d13ff12b | ||
|
|
bdfcfb861f | ||
|
|
b444deffd2 | ||
|
|
ff28b7e5cf | ||
|
|
79b84bbc91 | ||
|
|
cbfc3b0342 | ||
|
|
a45da353d3 | ||
|
|
c21e3ee929 | ||
|
|
8a38bed262 | ||
|
|
7cc7a43ff6 | ||
|
|
9bd8df0149 | ||
|
|
8f7411057f | ||
|
|
ca1fe4f82a | ||
|
|
e183c2c506 | ||
|
|
52b18fc6f5 | ||
|
|
e6d00725c2 | ||
|
|
e597711824 | ||
|
|
e1e646c6fc | ||
|
|
fc3b5b4f63 | ||
|
|
1e904a3ce5 | ||
|
|
79e100a7fb | ||
|
|
a65d3d7283 | ||
|
|
3b8766aa43 | ||
|
|
c8b3c89a39 | ||
|
|
a05d460e66 | ||
|
|
5eb362a6c0 | ||
|
|
0735cb28d1 | ||
|
|
737c28e836 | ||
|
|
1bab2dfafa | ||
|
|
22e2c5b6d1 | ||
|
|
914dbfea4e | ||
|
|
cf5e6e89a5 | ||
|
|
4941edf275 | ||
|
|
b08723ef97 | ||
|
|
c163fbc505 | ||
|
|
eed3f1ab38 | ||
|
|
63501f51bb | ||
|
|
1ae2570bda | ||
|
|
9ad825b267 | ||
|
|
3d5e6c0692 | ||
|
|
23e19ca6fc | ||
|
|
9f757aa9f3 | ||
|
|
1df6c170ff | ||
|
|
7a95bedc26 | ||
|
|
ae685bc33d | ||
|
|
91ac449bcd | ||
|
|
25b2543e5e | ||
|
|
7133e0d32a | ||
|
|
fac7584830 | ||
|
|
87f9258fb4 | ||
|
|
a2fe5356b5 | ||
|
|
ad9b12a863 | ||
|
|
61ca4111a1 | ||
|
|
71a971d70c | ||
|
|
61d6c0e766 | ||
|
|
b4daa2d0fa | ||
|
|
425b701fb9 | ||
|
|
0a5cde80f1 | ||
|
|
58ede90fdb | ||
|
|
ba4f8478e6 | ||
|
|
374a18cc5b | ||
|
|
55ae8da032 | ||
|
|
6bd86df72e | ||
|
|
0efd3605cc | ||
|
|
a2f2f53ef9 | ||
|
|
b5a03093f6 | ||
|
|
8eba898135 | ||
|
|
56f66de89f | ||
|
|
2fbaee2255 | ||
|
|
f35561287a | ||
|
|
672b9659cf | ||
|
|
a122490461 | ||
|
|
7826b4f306 | ||
|
|
380994219f | ||
|
|
153accb8de | ||
|
|
7bb1c62263 | ||
|
|
1578b6e180 | ||
|
|
1978add0cd | ||
|
|
6cbcea3ac7 | ||
|
|
65e23d4b6f | ||
|
|
fbe41cdef9 | ||
|
|
01a95108b3 | ||
|
|
f75d11821f | ||
|
|
6aa5cfc903 | ||
|
|
f6931c794e | ||
|
|
4c5082ad05 | ||
|
|
5fb892a097 | ||
|
|
55e9532d16 | ||
|
|
fff6657cea | ||
|
|
45d1e75caf | ||
|
|
b806f16c8b | ||
|
|
8d3348c71b | ||
|
|
e2cc14681e | ||
|
|
5ae979bb6e | ||
|
|
8f2fbd66fc | ||
|
|
b5909d8d22 | ||
|
|
fa8e94f155 | ||
|
|
cb5683aeae | ||
|
|
c9715724ec | ||
|
|
78d9cfffd8 | ||
|
|
b47b1d048d | ||
|
|
740952fb82 | ||
|
|
5c550f4548 | ||
|
|
3d78cb8d9a | ||
|
|
1ab75c0043 | ||
|
|
bebc8d516b | ||
|
|
a7debe7ff6 | ||
|
|
215e3920ef | ||
|
|
aabf28aef5 | ||
|
|
aa09835c90 | ||
|
|
9b9e13b665 | ||
|
|
f72e11ef5b | ||
|
|
a45e54555d | ||
|
|
4693c00c9f | ||
|
|
8fe23e0297 | ||
|
|
8557788699 | ||
|
|
81a19ebeb3 | ||
|
|
299df5ec77 | ||
|
|
6f9b6db7be | ||
|
|
96f15b9160 | ||
|
|
159384c2a9 | ||
|
|
621fc91453 | ||
|
|
543c49f76c | ||
|
|
d0a760a587 | ||
|
|
f68cca4097 | ||
|
|
3129357874 | ||
|
|
fc09352df6 | ||
|
|
06da5d45a3 | ||
|
|
69524cadad | ||
|
|
98e95d80e6 | ||
|
|
2f8aa8a43a | ||
|
|
56e60e37ae | ||
|
|
8f5348ab47 | ||
|
|
c5d693b21c | ||
|
|
27e3ac55b9 | ||
|
|
7879218773 | ||
|
|
1354624ba4 | ||
|
|
153f8d5353 | ||
|
|
a1cecf7462 | ||
|
|
e2dac8a00a | ||
|
|
ecd41bef27 | ||
|
|
fd2131687a | ||
|
|
316b9ab4fc | ||
|
|
d45daaf313 | ||
|
|
db1c6d6557 | ||
|
|
e7a713a525 | ||
|
|
39e67508c9 | ||
|
|
3eab974ca2 | ||
|
|
b1d1dcb3b6 | ||
|
|
10cb62aca2 | ||
|
|
6da73aba38 | ||
|
|
1b1b9626ee | ||
|
|
8bc074043a | ||
|
|
04a6322aa4 | ||
|
|
5748f518d1 | ||
|
|
d05eff4d54 | ||
|
|
4544eaa4cc | ||
|
|
5d0770d0ad | ||
|
|
7f4beb846e | ||
|
|
8e8c04e1b9 | ||
|
|
bf0da2ed21 | ||
|
|
670ece06df | ||
|
|
9e41903be8 | ||
|
|
57f92cc97e | ||
|
|
c0741ccc68 | ||
|
|
fb2745024a | ||
|
|
0c15ddd133 | ||
|
|
b53504049c | ||
|
|
a5324e58eb | ||
|
|
963cd68535 | ||
|
|
047df73887 | ||
|
|
d2e1ea7d19 | ||
|
|
fbbe95ba5b | ||
|
|
758c649611 | ||
|
|
a23f95f620 | ||
|
|
5363570df0 | ||
|
|
368857a45b | ||
|
|
40b16d0565 | ||
|
|
08e901a1ac | ||
|
|
bc703c9129 | ||
|
|
9ce52de6c1 | ||
|
|
b3aa262477 | ||
|
|
25e112c674 | ||
|
|
0d2282d551 | ||
|
|
b5f21f4165 | ||
|
|
d357935f66 | ||
|
|
9d2e0f1c02 | ||
|
|
b46ff5c18e | ||
|
|
f597105800 | ||
|
|
3692517a41 | ||
|
|
a58bd6cb1e | ||
|
|
4bad944ae4 | ||
|
|
594182f109 | ||
|
|
53c261cb33 | ||
|
|
8703d9a5be | ||
|
|
aa9f1e68ff | ||
|
|
84a4f556b1 | ||
|
|
5b166dbf0a | ||
|
|
9e2233b821 | ||
|
|
13716dc8be | ||
|
|
8ada1bd88d | ||
|
|
9c80bb9fb0 | ||
|
|
33e2863862 | ||
|
|
027e23a11d | ||
|
|
62e8db1c6a | ||
|
|
581b2f31bc |
@@ -173,7 +173,7 @@ jobs:
|
||||
cross_platform_config: "--enable-debug --disable-flto --with-libevent --disable-static"
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v7
|
||||
with:
|
||||
submodules: false
|
||||
persist-credentials: false
|
||||
|
||||
@@ -12,7 +12,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v7
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: configure
|
||||
|
||||
-380
@@ -1,380 +0,0 @@
|
||||
language: c
|
||||
|
||||
git:
|
||||
depth: 5
|
||||
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- libssl-dev
|
||||
- libevent-dev
|
||||
- libexpat-dev
|
||||
- clang
|
||||
homebrew:
|
||||
packages:
|
||||
- openssl
|
||||
- libevent
|
||||
- expat
|
||||
# homebrew update takes 20min or hangs, so disable update
|
||||
#update: true
|
||||
|
||||
jobs:
|
||||
include:
|
||||
- os: linux
|
||||
name: GCC on Linux, Amd64
|
||||
compiler: gcc
|
||||
arch: amd64
|
||||
env:
|
||||
- CONFIG_OPTS="--enable-debug --disable-flto"
|
||||
- os: linux
|
||||
name: Clang on Linux, Amd64, clang-analysis
|
||||
compiler: clang
|
||||
arch: amd64
|
||||
env:
|
||||
- CONFIG_OPTS="--enable-debug --disable-flto"
|
||||
- TEST_ANALYZER=yes
|
||||
- os: osx
|
||||
osx_image: xcode12.2
|
||||
name: Clang on OS X, Amd64, clang-analysis
|
||||
compiler: clang
|
||||
arch: amd64
|
||||
env:
|
||||
- TEST_OSX=yes
|
||||
- CONFIG_OPTS="--enable-debug --disable-flto --with-ssl=/usr/local/opt/openssl --with-libexpat=/usr/local/opt/expat"
|
||||
- TEST_ANALYZER=yes
|
||||
- HOMEBREW_NO_AUTO_UPDATE=1
|
||||
- os: linux
|
||||
name: Libevent, GCC on Linux, Amd64
|
||||
compiler: gcc
|
||||
arch: amd64
|
||||
env:
|
||||
- TEST_LIBEVENT=yes
|
||||
- CONFIG_OPTS="--with-libevent"
|
||||
- os: linux
|
||||
name: Libevent, Clang on Linux, Amd64
|
||||
compiler: clang
|
||||
arch: amd64
|
||||
env:
|
||||
- TEST_LIBEVENT=yes
|
||||
- CONFIG_OPTS="--with-libevent"
|
||||
- os: osx
|
||||
osx_image: xcode12.2
|
||||
name: Libevent, Clang on OS X, Amd64
|
||||
compiler: clang
|
||||
arch: amd64
|
||||
env:
|
||||
- TEST_OSX=yes
|
||||
- TEST_LIBEVENT=yes
|
||||
- CONFIG_OPTS="--disable-flto --with-ssl=/usr/local/opt/openssl --with-libevent=/usr/local/opt/libevent --with-libexpat=/usr/local/opt/expat"
|
||||
- HOMEBREW_NO_AUTO_UPDATE=1
|
||||
- os: linux
|
||||
name: UBsan, GCC on Linux, Amd64
|
||||
compiler: gcc
|
||||
arch: amd64
|
||||
dist: bionic
|
||||
env:
|
||||
- TEST_UBSAN=yes
|
||||
- os: linux
|
||||
name: UBsan, Clang on Linux, Amd64
|
||||
compiler: clang
|
||||
arch: amd64
|
||||
dist: bionic
|
||||
env:
|
||||
- TEST_UBSAN=yes
|
||||
- os: linux
|
||||
name: Asan, GCC on Linux, Amd64
|
||||
compiler: gcc
|
||||
arch: amd64
|
||||
dist: bionic
|
||||
env:
|
||||
- TEST_ASAN=yes
|
||||
- os: linux
|
||||
name: Asan, Clang on Linux, Amd64
|
||||
compiler: clang
|
||||
arch: amd64
|
||||
dist: bionic
|
||||
env:
|
||||
- TEST_ASAN=yes
|
||||
- os: linux
|
||||
name: GCC on Linux, Aarch64
|
||||
compiler: gcc
|
||||
arch: arm64
|
||||
dist: bionic
|
||||
env:
|
||||
- CONFIG_OPTS="--enable-debug --disable-flto"
|
||||
- os: linux
|
||||
name: Clang on Linux, Aarch64
|
||||
compiler: clang
|
||||
arch: arm64
|
||||
dist: bionic
|
||||
env:
|
||||
- CONFIG_OPTS="--enable-debug --disable-flto"
|
||||
- os: linux
|
||||
name: GCC on Linux, PowerPC64
|
||||
compiler: gcc
|
||||
arch: ppc64le
|
||||
dist: bionic
|
||||
env:
|
||||
- CONFIG_OPTS="--enable-debug --disable-flto"
|
||||
- os: linux
|
||||
name: Clang on Linux, PowerPC64
|
||||
compiler: clang
|
||||
arch: ppc64le
|
||||
dist: bionic
|
||||
env:
|
||||
- CONFIG_OPTS="--enable-debug --disable-flto"
|
||||
- os: linux
|
||||
name: GCC on Linux, s390x
|
||||
compiler: gcc
|
||||
arch: s390x
|
||||
dist: bionic
|
||||
env:
|
||||
- CONFIG_OPTS="--enable-debug --disable-flto"
|
||||
- os: linux
|
||||
name: Clang on Linux, s390x
|
||||
compiler: clang
|
||||
arch: s390x
|
||||
dist: bionic
|
||||
env:
|
||||
- CONFIG_OPTS="--enable-debug --disable-flto"
|
||||
- os: osx
|
||||
osx_image: xcode12.2
|
||||
name: Apple iPhone on iOS, armv7
|
||||
compiler: clang
|
||||
env:
|
||||
- TEST_IOS=yes
|
||||
- AUTOTOOLS_HOST=armv7-apple-ios
|
||||
- OPENSSL_HOST=ios-cross
|
||||
- IOS_SDK=iPhoneOS
|
||||
- IOS_CPU=armv7s
|
||||
- IOS_PREFIX="$HOME/$IOS_SDK-$IOS_CPU"
|
||||
- HOMEBREW_NO_AUTO_UPDATE=1
|
||||
- os: osx
|
||||
osx_image: xcode12.2
|
||||
name: Apple iPhone on iOS, arm64
|
||||
compiler: clang
|
||||
env:
|
||||
- TEST_IOS=yes
|
||||
- AUTOTOOLS_HOST=aarch64-apple-ios
|
||||
- OPENSSL_HOST=ios64-cross
|
||||
- IOS_SDK=iPhoneOS
|
||||
- IOS_CPU=arm64
|
||||
- IOS_PREFIX="$HOME/$IOS_SDK-$IOS_CPU"
|
||||
- HOMEBREW_NO_AUTO_UPDATE=1
|
||||
- os: osx
|
||||
osx_image: xcode12.2
|
||||
name: Apple TV on iOS, arm64
|
||||
compiler: clang
|
||||
env:
|
||||
- TEST_IOS=yes
|
||||
- AUTOTOOLS_HOST=aarch64-apple-ios
|
||||
- OPENSSL_HOST=ios64-cross
|
||||
- IOS_SDK=AppleTVOS
|
||||
- IOS_CPU=arm64
|
||||
- IOS_PREFIX="$HOME/$IOS_SDK-$IOS_CPU"
|
||||
- HOMEBREW_NO_AUTO_UPDATE=1
|
||||
- os: osx
|
||||
osx_image: xcode12.2
|
||||
name: Apple Watch on iOS, armv7
|
||||
compiler: clang
|
||||
env:
|
||||
- TEST_IOS=yes
|
||||
- AUTOTOOLS_HOST=armv7-apple-ios
|
||||
- OPENSSL_HOST=ios-cross
|
||||
- IOS_SDK=WatchOS
|
||||
- IOS_CPU=armv7k
|
||||
- IOS_PREFIX="$HOME/$IOS_SDK-$IOS_CPU"
|
||||
- HOMEBREW_NO_AUTO_UPDATE=1
|
||||
- os: osx
|
||||
osx_image: xcode12.2
|
||||
name: iPhoneSimulator on OS X, i386
|
||||
env:
|
||||
- TEST_IOS=yes
|
||||
- AUTOTOOLS_HOST=i386-apple-ios
|
||||
- OPENSSL_HOST=iphoneos-cross
|
||||
- IOS_CPU=i386
|
||||
- IOS_SDK=iPhoneSimulator
|
||||
- IOS_PREFIX="$HOME/$IOS_SDK-$IOS_CPU"
|
||||
- HOMEBREW_NO_AUTO_UPDATE=1
|
||||
- os: osx
|
||||
osx_image: xcode12.2
|
||||
name: iPhoneSimulator on OS X, x86_64
|
||||
env:
|
||||
- TEST_IOS=yes
|
||||
- AUTOTOOLS_HOST=x86_64-apple-ios
|
||||
- OPENSSL_HOST=iphoneos-cross
|
||||
- IOS_CPU=x86_64
|
||||
- IOS_SDK=iPhoneSimulator
|
||||
- IOS_PREFIX="$HOME/$IOS_SDK-$IOS_CPU"
|
||||
- HOMEBREW_NO_AUTO_UPDATE=1
|
||||
- os: osx
|
||||
osx_image: xcode12.2
|
||||
name: AppleTVSimulator on OS X, x86_64
|
||||
env:
|
||||
- TEST_IOS=yes
|
||||
- AUTOTOOLS_HOST=x86_64-apple-ios
|
||||
- OPENSSL_HOST=iphoneos-cross
|
||||
- IOS_CPU=x86_64
|
||||
- IOS_SDK=AppleTVSimulator
|
||||
- IOS_PREFIX="$HOME/$IOS_SDK-$IOS_CPU"
|
||||
- HOMEBREW_NO_AUTO_UPDATE=1
|
||||
- os: osx
|
||||
osx_image: xcode12.2
|
||||
name: WatchSimulator on OS X, i386
|
||||
env:
|
||||
- TEST_IOS=yes
|
||||
- AUTOTOOLS_HOST=i386-apple-ios
|
||||
- OPENSSL_HOST=iphoneos-cross
|
||||
- IOS_CPU=i386
|
||||
- IOS_SDK=WatchSimulator
|
||||
- IOS_PREFIX="$HOME/$IOS_SDK-$IOS_CPU"
|
||||
- HOMEBREW_NO_AUTO_UPDATE=1
|
||||
- os: linux
|
||||
name: Android armv7a, Linux, Amd64
|
||||
compiler: clang
|
||||
arch: amd64
|
||||
dist: bionic
|
||||
env:
|
||||
- TEST_ANDROID=yes
|
||||
- AUTOTOOLS_HOST=armv7a-linux-androideabi
|
||||
- OPENSSL_HOST=android-arm
|
||||
- ANDROID_CPU=armv7a
|
||||
- ANDROID_API=23
|
||||
- ANDROID_PREFIX="$HOME/android$ANDROID_API-$ANDROID_CPU"
|
||||
- ANDROID_SDK_ROOT="$HOME/android-sdk"
|
||||
- ANDROID_NDK_ROOT="$HOME/android-ndk"
|
||||
- os: linux
|
||||
name: Android aarch64, Linux, Amd64
|
||||
compiler: clang
|
||||
arch: amd64
|
||||
dist: bionic
|
||||
env:
|
||||
- TEST_ANDROID=yes
|
||||
- AUTOTOOLS_HOST=aarch64-linux-android
|
||||
- OPENSSL_HOST=android-arm64
|
||||
- ANDROID_CPU=aarch64
|
||||
- ANDROID_API=23
|
||||
- ANDROID_PREFIX="$HOME/android$ANDROID_API-$ANDROID_CPU"
|
||||
- ANDROID_SDK_ROOT="$HOME/android-sdk"
|
||||
- ANDROID_NDK_ROOT="$HOME/android-ndk"
|
||||
- os: linux
|
||||
name: Android x86, Linux, Amd64
|
||||
compiler: clang
|
||||
arch: amd64
|
||||
dist: bionic
|
||||
env:
|
||||
- TEST_ANDROID=yes
|
||||
- AUTOTOOLS_HOST=i686-linux-android
|
||||
- OPENSSL_HOST=android-x86
|
||||
- ANDROID_CPU=x86
|
||||
- ANDROID_API=23
|
||||
- ANDROID_PREFIX="$HOME/android$ANDROID_API-$ANDROID_CPU"
|
||||
- ANDROID_SDK_ROOT="$HOME/android-sdk"
|
||||
- ANDROID_NDK_ROOT="$HOME/android-ndk"
|
||||
- os: linux
|
||||
name: Android x86_64, Linux, Amd64
|
||||
compiler: clang
|
||||
arch: amd64
|
||||
dist: bionic
|
||||
env:
|
||||
- TEST_ANDROID=yes
|
||||
- AUTOTOOLS_HOST=x86_64-linux-android
|
||||
- OPENSSL_HOST=android-x86_64
|
||||
- ANDROID_CPU=x86_64
|
||||
- ANDROID_API=23
|
||||
- ANDROID_PREFIX="$HOME/android$ANDROID_API-$ANDROID_CPU"
|
||||
- ANDROID_SDK_ROOT="$HOME/android-sdk"
|
||||
- ANDROID_NDK_ROOT="$HOME/android-ndk"
|
||||
|
||||
allow_failures:
|
||||
- os: osx
|
||||
name: Apple iPhone on iOS, armv7
|
||||
- os: osx
|
||||
name: Apple iPhone on iOS, arm64
|
||||
- os: osx
|
||||
name: Apple TV on iOS, arm64
|
||||
- os: osx
|
||||
name: Apple Watch on iOS, armv7
|
||||
- os: osx
|
||||
name: iPhoneSimulator on OS X, i386
|
||||
- os: osx
|
||||
name: iPhoneSimulator on OS X, x86_64
|
||||
- os: osx
|
||||
name: AppleTVSimulator on OS X, x86_64
|
||||
- os: osx
|
||||
name: WatchSimulator on OS X, i386
|
||||
- os: linux
|
||||
name: Android armv7a, Linux, Amd64
|
||||
- os: linux
|
||||
name: Android aarch64, Linux, Amd64
|
||||
- os: linux
|
||||
name: Android x86, Linux, Amd64
|
||||
- os: linux
|
||||
name: Android x86_64, Linux, Amd64
|
||||
|
||||
before_script:
|
||||
- |
|
||||
if [ "$TEST_ANDROID" = "yes" ]; then
|
||||
./contrib/android/install_tools.sh
|
||||
elif [ "$TEST_IOS" = "yes" ]; then
|
||||
./contrib/ios/install_tools.sh
|
||||
fi
|
||||
|
||||
# The Travis docs say to avoid calling exit in the script. It leads to
|
||||
# some code duplication to avoid failures in cross-compiles. Also see
|
||||
# https://docs.travis-ci.com/user/job-lifecycle/ in the Travis docs.
|
||||
script:
|
||||
- |
|
||||
export MAKE_TEST="yes"
|
||||
if [ "$TEST_UBSAN" = "yes" ]; then
|
||||
export CFLAGS="-DNDEBUG -g2 -O3 -fsanitize=undefined -fno-sanitize-recover=all"
|
||||
elif [ "$TEST_ASAN" = "yes" ]; then
|
||||
export CFLAGS="-DNDEBUG -g2 -O3 -fsanitize=address"
|
||||
fi
|
||||
- |
|
||||
if [ "$TEST_IOS" = "yes" ]; then
|
||||
export AUTOTOOLS_BUILD="$(./config.guess)"
|
||||
export PKG_CONFIG_PATH="$IOS_PREFIX/lib/pkgconfig"
|
||||
source ./contrib/ios/setenv_ios.sh
|
||||
./contrib/ios/install_openssl.sh
|
||||
./contrib/ios/install_expat.sh
|
||||
export CONFIG_OPTS="\
|
||||
--build=$AUTOTOOLS_BUILD --host=$AUTOTOOLS_HOST \
|
||||
--prefix=$IOS_PREFIX \
|
||||
--with-ssl=$IOS_PREFIX --disable-gost \
|
||||
--with-libexpat=$IOS_PREFIX "
|
||||
echo CONFIG_OPTS ${CONFIG_OPTS}
|
||||
export MAKE_TEST=no
|
||||
export TEST_INSTALL=yes
|
||||
fi
|
||||
- |
|
||||
if [ "$TEST_ANDROID" = "yes" ]; then
|
||||
export AUTOTOOLS_BUILD="$(./config.guess)"
|
||||
export PKG_CONFIG_PATH="$ANDROID_PREFIX/lib/pkgconfig"
|
||||
./contrib/android/install_ndk.sh
|
||||
source ./contrib/android/setenv_android.sh
|
||||
./contrib/android/install_openssl.sh
|
||||
./contrib/android/install_expat.sh
|
||||
export CONFIG_OPTS="\
|
||||
--build=$AUTOTOOLS_BUILD --host=$AUTOTOOLS_HOST \
|
||||
--prefix=$ANDROID_PREFIX \
|
||||
--with-ssl=$ANDROID_PREFIX --disable-gost \
|
||||
--with-libexpat=$ANDROID_PREFIX "
|
||||
echo CONFIG_OPTS ${CONFIG_OPTS}
|
||||
export MAKE_TEST=no
|
||||
export TEST_INSTALL=yes
|
||||
fi
|
||||
- ./configure ${CONFIG_OPTS}
|
||||
- make -j 2
|
||||
- |
|
||||
if [ "$MAKE_TEST" = "yes" ]; then
|
||||
make test
|
||||
fi
|
||||
- |
|
||||
if [ "$TEST_INSTALL" = "yes" ]; then
|
||||
make install
|
||||
fi
|
||||
- |
|
||||
if [ "$TEST_ANALYZER" = "yes" ]; then
|
||||
(cd testdata/clang-analysis.tdir; bash clang-analysis.test)
|
||||
fi
|
||||
+4
-2
@@ -125,7 +125,7 @@ services/localzone.c services/mesh.c services/modstack.c services/view.c \
|
||||
services/rpz.c util/rfc_1982.c \
|
||||
services/outbound_list.c services/outside_network.c util/alloc.c \
|
||||
util/config_file.c util/configlexer.c util/configparser.c \
|
||||
util/shm_side/shm_main.c services/authzone.c \
|
||||
util/shm_side/shm_main.c services/authzone.c services/authload.c \
|
||||
util/fptr_wlist.c util/locks.c util/log.c util/mini_event.c util/module.c \
|
||||
util/netevent.c util/net_help.c util/random.c util/rbtree.c util/regional.c \
|
||||
util/rtt.c util/siphash.c util/edns.c util/storage/dnstree.c util/storage/lookup3.c \
|
||||
@@ -152,7 +152,8 @@ autotrust.lo val_anchor.lo rpz.lo rfc_1982.lo proxy_protocol.lo \
|
||||
validator.lo val_kcache.lo val_kentry.lo val_neg.lo val_nsec3.lo val_nsec.lo \
|
||||
val_secalgo.lo val_sigcrypt.lo val_utils.lo dns64.lo $(CACHEDB_OBJ) authzone.lo \
|
||||
$(SUBNET_OBJ) $(PYTHONMOD_OBJ) $(CHECKLOCK_OBJ) $(DNSTAP_OBJ) $(DNSCRYPT_OBJ) \
|
||||
$(IPSECMOD_OBJ) $(IPSET_OBJ) $(DYNLIBMOD_OBJ) respip.lo timeval_func.lo
|
||||
$(IPSECMOD_OBJ) $(IPSET_OBJ) $(DYNLIBMOD_OBJ) respip.lo timeval_func.lo \
|
||||
authload.lo
|
||||
COMMON_OBJ_WITHOUT_UB_EVENT=$(COMMON_OBJ_WITHOUT_NETCALL) netevent.lo listen_dnsport.lo \
|
||||
outside_network.lo
|
||||
COMMON_OBJ=$(COMMON_OBJ_WITHOUT_UB_EVENT) ub_event.lo
|
||||
@@ -721,6 +722,7 @@ depend:
|
||||
ipset.lo ipset.o: $(srcdir)/ipset/ipset.c
|
||||
doqclient.lo doqclient.o: $(srcdir)/testcode/doqclient.c
|
||||
unitdoq.lo unitdoq.o: $(srcdir)/testcode/unitdoq.c
|
||||
authload.lo authload.o: $(srcdir)/services/authload.c
|
||||
|
||||
# Dependencies
|
||||
dns.lo dns.o: $(srcdir)/services/cache/dns.c config.h $(srcdir)/iterator/iter_delegpt.h $(srcdir)/util/log.h \
|
||||
|
||||
@@ -10,7 +10,7 @@ Unbound is a validating, recursive, caching DNS resolver. It is designed to be
|
||||
fast and lean and incorporates modern features based on open standards. If you
|
||||
have any feedback, we would love to hear from you. Don’t hesitate to
|
||||
[create an issue on Github](https://github.com/NLnetLabs/unbound/issues/new)
|
||||
or post a message on the [Unbound mailing list](https://lists.nlnetlabs.nl/mailman/listinfo/unbound-users).
|
||||
or post a message on our [community forum](https://community.nlnetlabs.nl/).
|
||||
You can learn more about Unbound by reading our
|
||||
[documentation](https://unbound.docs.nlnetlabs.nl/).
|
||||
|
||||
|
||||
+17
-2
@@ -87,7 +87,7 @@
|
||||
# modified version of the Autoconf Macro, you may extend this special
|
||||
# exception to the GPL to apply to your modified version as well.
|
||||
|
||||
#serial 31
|
||||
#serial 32
|
||||
|
||||
AU_ALIAS([ACX_PTHREAD], [AX_PTHREAD])
|
||||
AC_DEFUN([AX_PTHREAD], [
|
||||
@@ -249,7 +249,22 @@ AS_IF([test "x$ax_pthread_clang" = "xyes"],
|
||||
# correctly enabled
|
||||
|
||||
case $host_os in
|
||||
darwin* | hpux* | linux* | osf* | solaris*)
|
||||
solaris*)
|
||||
# Solaris 11.4 introduced XPG7 support and did away with the need for
|
||||
# _REENTRANT.
|
||||
|
||||
AC_EGREP_CPP([AX_PTHREAD_SOLARIS__REENTRANT],
|
||||
[
|
||||
# undef _XOPEN_SOURCE
|
||||
# include <sys/feature_tests.h>
|
||||
# if _XOPEN_VERSION < 700
|
||||
AX_PTHREAD_SOLARIS__REENTRANT
|
||||
# endif
|
||||
],
|
||||
[ax_pthread_check_macro="_REENTRANT"],
|
||||
[ax_pthread_check_macro="--"])
|
||||
;;
|
||||
darwin* | hpux* | linux* | osf*)
|
||||
ax_pthread_check_macro="_REENTRANT"
|
||||
;;
|
||||
|
||||
|
||||
@@ -401,6 +401,12 @@ prep_data(struct module_qstate* qstate, struct sldns_buffer* buf)
|
||||
FLAGS_GET_RCODE(qstate->return_msg->rep->flags) !=
|
||||
LDNS_RCODE_YXDOMAIN)
|
||||
return 0;
|
||||
/* Do not persist data the validator has not yet seen, or has rejected.
|
||||
* Otherwise an expired blob could maybe reach clients via
|
||||
* serve-expired. */
|
||||
if(qstate->env->need_to_validate &&
|
||||
qstate->return_msg->rep->security == sec_status_bogus)
|
||||
return 0;
|
||||
/* We don't store the reply if its TTL is 0. This is probably coming
|
||||
* from upstream and it is not meant to be stored. */
|
||||
if(qstate->return_msg->rep->ttl == 0)
|
||||
@@ -863,6 +869,11 @@ cachedb_handle_query(struct module_qstate* qstate,
|
||||
return;
|
||||
}
|
||||
/* No 0TTL answers escaping from external cache. */
|
||||
if(qstate->return_msg->rep->ttl == 0) {
|
||||
qstate->return_msg = NULL;
|
||||
qstate->ext_state[id] = module_wait_module;
|
||||
return;
|
||||
}
|
||||
log_assert(qstate->return_msg->rep->ttl > 0);
|
||||
qstate->is_cachedb_answer = 1;
|
||||
/* we are done with the query */
|
||||
|
||||
+9
-382
@@ -20,398 +20,25 @@
|
||||
* http://man.openbsd.org/getentropy.2
|
||||
*/
|
||||
|
||||
#include <TargetConditionals.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/resource.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/statvfs.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <termios.h>
|
||||
#include <fcntl.h>
|
||||
#include <signal.h>
|
||||
#include <string.h>
|
||||
/* Modified to use SecRandomCopyBytes. It is from macOS 10.7 (2011) and
|
||||
* iOS 2.0 (2008), and is the primary API for cryptographic random numbers. */
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <time.h>
|
||||
#include <mach/mach_time.h>
|
||||
#include <mach/mach_host.h>
|
||||
#include <mach/host_info.h>
|
||||
#if TARGET_OS_OSX
|
||||
#include <sys/socketvar.h>
|
||||
#include <sys/vmmeter.h>
|
||||
#endif
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/tcp.h>
|
||||
#if TARGET_OS_OSX
|
||||
#include <netinet/udp.h>
|
||||
#include <netinet/ip_var.h>
|
||||
#include <netinet/tcp_var.h>
|
||||
#include <netinet/udp_var.h>
|
||||
#endif
|
||||
#include <CommonCrypto/CommonDigest.h>
|
||||
#define SHA512_Update(a, b, c) (CC_SHA512_Update((a), (b), (c)))
|
||||
#define SHA512_Init(xxx) (CC_SHA512_Init((xxx)))
|
||||
#define SHA512_Final(xxx, yyy) (CC_SHA512_Final((xxx), (yyy)))
|
||||
#define SHA512_CTX CC_SHA512_CTX
|
||||
#define SHA512_DIGEST_LENGTH CC_SHA512_DIGEST_LENGTH
|
||||
|
||||
#define REPEAT 5
|
||||
#define min(a, b) (((a) < (b)) ? (a) : (b))
|
||||
|
||||
#define HX(a, b) \
|
||||
do { \
|
||||
if ((a)) \
|
||||
HD(errno); \
|
||||
else \
|
||||
HD(b); \
|
||||
} while (0)
|
||||
|
||||
#define HR(x, l) (SHA512_Update(&ctx, (char *)(x), (l)))
|
||||
#define HD(x) (SHA512_Update(&ctx, (char *)&(x), sizeof (x)))
|
||||
#define HF(x) (SHA512_Update(&ctx, (char *)&(x), sizeof (void*)))
|
||||
#include <Security/SecRandom.h>
|
||||
|
||||
int getentropy(void *buf, size_t len);
|
||||
|
||||
static int getentropy_urandom(void *buf, size_t len);
|
||||
static int getentropy_fallback(void *buf, size_t len);
|
||||
|
||||
int
|
||||
getentropy(void *buf, size_t len)
|
||||
{
|
||||
int ret = -1;
|
||||
|
||||
if (len > 256) {
|
||||
errno = EIO;
|
||||
return (-1);
|
||||
goto error;
|
||||
}
|
||||
|
||||
/*
|
||||
* Try to get entropy with /dev/urandom
|
||||
*
|
||||
* This can fail if the process is inside a chroot or if file
|
||||
* descriptors are exhausted.
|
||||
*/
|
||||
ret = getentropy_urandom(buf, len);
|
||||
if (ret != -1)
|
||||
return (ret);
|
||||
|
||||
/*
|
||||
* Entropy collection via /dev/urandom and sysctl have failed.
|
||||
*
|
||||
* No other API exists for collecting entropy, and we have
|
||||
* no failsafe way to get it on OSX that is not sensitive
|
||||
* to resource exhaustion.
|
||||
*
|
||||
* We have very few options:
|
||||
* - Even syslog_r is unsafe to call at this low level, so
|
||||
* there is no way to alert the user or program.
|
||||
* - Cannot call abort() because some systems have unsafe
|
||||
* corefiles.
|
||||
* - Could raise(SIGKILL) resulting in silent program termination.
|
||||
* - Return EIO, to hint that arc4random's stir function
|
||||
* should raise(SIGKILL)
|
||||
* - Do the best under the circumstances....
|
||||
*
|
||||
* This code path exists to bring light to the issue that OSX
|
||||
* does not provide a failsafe API for entropy collection.
|
||||
*
|
||||
* We hope this demonstrates that OSX should consider
|
||||
* providing a new failsafe API which works in a chroot or
|
||||
* when file descriptors are exhausted.
|
||||
*/
|
||||
#undef FAIL_INSTEAD_OF_TRYING_FALLBACK
|
||||
#ifdef FAIL_INSTEAD_OF_TRYING_FALLBACK
|
||||
raise(SIGKILL);
|
||||
#endif
|
||||
ret = getentropy_fallback(buf, len);
|
||||
if (ret != -1)
|
||||
return (ret);
|
||||
if (SecRandomCopyBytes(kSecRandomDefault, len, buf) == errSecSuccess) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
error:
|
||||
errno = EIO;
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static int
|
||||
getentropy_urandom(void *buf, size_t len)
|
||||
{
|
||||
struct stat st;
|
||||
size_t i;
|
||||
int fd, flags;
|
||||
int save_errno = errno;
|
||||
|
||||
start:
|
||||
|
||||
flags = O_RDONLY;
|
||||
#ifdef O_NOFOLLOW
|
||||
flags |= O_NOFOLLOW;
|
||||
#endif
|
||||
#ifdef O_CLOEXEC
|
||||
flags |= O_CLOEXEC;
|
||||
#endif
|
||||
fd = open("/dev/urandom", flags, 0);
|
||||
if (fd == -1) {
|
||||
if (errno == EINTR)
|
||||
goto start;
|
||||
goto nodevrandom;
|
||||
}
|
||||
#ifndef O_CLOEXEC
|
||||
fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
|
||||
#endif
|
||||
|
||||
/* Lightly verify that the device node looks sane */
|
||||
if (fstat(fd, &st) == -1 || !S_ISCHR(st.st_mode)) {
|
||||
close(fd);
|
||||
goto nodevrandom;
|
||||
}
|
||||
for (i = 0; i < len; ) {
|
||||
size_t wanted = len - i;
|
||||
ssize_t ret = read(fd, (char *)buf + i, wanted);
|
||||
|
||||
if (ret == -1) {
|
||||
if (errno == EAGAIN || errno == EINTR)
|
||||
continue;
|
||||
close(fd);
|
||||
goto nodevrandom;
|
||||
}
|
||||
i += ret;
|
||||
}
|
||||
close(fd);
|
||||
errno = save_errno;
|
||||
return (0); /* satisfied */
|
||||
nodevrandom:
|
||||
errno = EIO;
|
||||
return (-1);
|
||||
}
|
||||
|
||||
#if TARGET_OS_OSX
|
||||
static int tcpmib[] = { CTL_NET, AF_INET, IPPROTO_TCP, TCPCTL_STATS };
|
||||
static int udpmib[] = { CTL_NET, AF_INET, IPPROTO_UDP, UDPCTL_STATS };
|
||||
static int ipmib[] = { CTL_NET, AF_INET, IPPROTO_IP, IPCTL_STATS };
|
||||
#endif
|
||||
static int kmib[] = { CTL_KERN, KERN_USRSTACK };
|
||||
static int hwmib[] = { CTL_HW, HW_USERMEM };
|
||||
|
||||
static int
|
||||
getentropy_fallback(void *buf, size_t len)
|
||||
{
|
||||
uint8_t results[SHA512_DIGEST_LENGTH];
|
||||
int save_errno = errno, e, pgs = getpagesize(), faster = 0, repeat;
|
||||
static int cnt;
|
||||
struct timespec ts;
|
||||
struct timeval tv;
|
||||
struct rusage ru;
|
||||
sigset_t sigset;
|
||||
struct stat st;
|
||||
SHA512_CTX ctx;
|
||||
static pid_t lastpid;
|
||||
pid_t pid;
|
||||
size_t i, ii, m;
|
||||
char *p;
|
||||
#if TARGET_OS_OSX
|
||||
struct tcpstat tcpstat;
|
||||
struct udpstat udpstat;
|
||||
struct ipstat ipstat;
|
||||
#endif
|
||||
u_int64_t mach_time;
|
||||
unsigned int idata;
|
||||
void *addr;
|
||||
|
||||
pid = getpid();
|
||||
if (lastpid == pid) {
|
||||
faster = 1;
|
||||
repeat = 2;
|
||||
} else {
|
||||
faster = 0;
|
||||
lastpid = pid;
|
||||
repeat = REPEAT;
|
||||
}
|
||||
for (i = 0; i < len; ) {
|
||||
int j;
|
||||
SHA512_Init(&ctx);
|
||||
for (j = 0; j < repeat; j++) {
|
||||
HX((e = gettimeofday(&tv, NULL)) == -1, tv);
|
||||
if (e != -1) {
|
||||
cnt += (int)tv.tv_sec;
|
||||
cnt += (int)tv.tv_usec;
|
||||
}
|
||||
|
||||
mach_time = mach_absolute_time();
|
||||
HD(mach_time);
|
||||
|
||||
ii = sizeof(addr);
|
||||
HX(sysctl(kmib, sizeof(kmib) / sizeof(kmib[0]),
|
||||
&addr, &ii, NULL, 0) == -1, addr);
|
||||
|
||||
ii = sizeof(idata);
|
||||
HX(sysctl(hwmib, sizeof(hwmib) / sizeof(hwmib[0]),
|
||||
&idata, &ii, NULL, 0) == -1, idata);
|
||||
|
||||
#if TARGET_OS_OSX
|
||||
ii = sizeof(tcpstat);
|
||||
HX(sysctl(tcpmib, sizeof(tcpmib) / sizeof(tcpmib[0]),
|
||||
&tcpstat, &ii, NULL, 0) == -1, tcpstat);
|
||||
|
||||
ii = sizeof(udpstat);
|
||||
HX(sysctl(udpmib, sizeof(udpmib) / sizeof(udpmib[0]),
|
||||
&udpstat, &ii, NULL, 0) == -1, udpstat);
|
||||
|
||||
ii = sizeof(ipstat);
|
||||
HX(sysctl(ipmib, sizeof(ipmib) / sizeof(ipmib[0]),
|
||||
&ipstat, &ii, NULL, 0) == -1, ipstat);
|
||||
#endif
|
||||
|
||||
HX((pid = getpid()) == -1, pid);
|
||||
HX((pid = getsid(pid)) == -1, pid);
|
||||
HX((pid = getppid()) == -1, pid);
|
||||
HX((pid = getpgid(0)) == -1, pid);
|
||||
HX((e = getpriority(0, 0)) == -1, e);
|
||||
|
||||
if (!faster) {
|
||||
ts.tv_sec = 0;
|
||||
ts.tv_nsec = 1;
|
||||
(void) nanosleep(&ts, NULL);
|
||||
}
|
||||
|
||||
HX(sigpending(&sigset) == -1, sigset);
|
||||
HX(sigprocmask(SIG_BLOCK, NULL, &sigset) == -1,
|
||||
sigset);
|
||||
|
||||
HF(getentropy); /* an addr in this library */
|
||||
HF(printf); /* an addr in libc */
|
||||
p = (char *)&p;
|
||||
HD(p); /* an addr on stack */
|
||||
p = (char *)&errno;
|
||||
HD(p); /* the addr of errno */
|
||||
|
||||
if (i == 0) {
|
||||
struct sockaddr_storage ss;
|
||||
struct statvfs stvfs;
|
||||
struct termios tios;
|
||||
struct statfs stfs;
|
||||
socklen_t ssl;
|
||||
off_t off;
|
||||
|
||||
/*
|
||||
* Prime-sized mappings encourage fragmentation;
|
||||
* thus exposing some address entropy.
|
||||
*/
|
||||
struct mm {
|
||||
size_t npg;
|
||||
void *p;
|
||||
} mm[] = {
|
||||
{ 17, MAP_FAILED }, { 3, MAP_FAILED },
|
||||
{ 11, MAP_FAILED }, { 2, MAP_FAILED },
|
||||
{ 5, MAP_FAILED }, { 3, MAP_FAILED },
|
||||
{ 7, MAP_FAILED }, { 1, MAP_FAILED },
|
||||
{ 57, MAP_FAILED }, { 3, MAP_FAILED },
|
||||
{ 131, MAP_FAILED }, { 1, MAP_FAILED },
|
||||
};
|
||||
|
||||
for (m = 0; m < sizeof mm/sizeof(mm[0]); m++) {
|
||||
HX(mm[m].p = mmap(NULL,
|
||||
mm[m].npg * pgs,
|
||||
PROT_READ|PROT_WRITE,
|
||||
MAP_PRIVATE|MAP_ANON, -1,
|
||||
(off_t)0), mm[m].p);
|
||||
if (mm[m].p != MAP_FAILED) {
|
||||
size_t mo;
|
||||
|
||||
/* Touch some memory... */
|
||||
p = mm[m].p;
|
||||
mo = cnt %
|
||||
(mm[m].npg * pgs - 1);
|
||||
p[mo] = 1;
|
||||
cnt += (int)((long)(mm[m].p)
|
||||
/ pgs);
|
||||
}
|
||||
|
||||
/* Check cnts and times... */
|
||||
mach_time = mach_absolute_time();
|
||||
HD(mach_time);
|
||||
cnt += (int)mach_time;
|
||||
|
||||
HX((e = getrusage(RUSAGE_SELF,
|
||||
&ru)) == -1, ru);
|
||||
if (e != -1) {
|
||||
cnt += (int)ru.ru_utime.tv_sec;
|
||||
cnt += (int)ru.ru_utime.tv_usec;
|
||||
}
|
||||
}
|
||||
|
||||
for (m = 0; m < sizeof mm/sizeof(mm[0]); m++) {
|
||||
if (mm[m].p != MAP_FAILED)
|
||||
munmap(mm[m].p, mm[m].npg * pgs);
|
||||
mm[m].p = MAP_FAILED;
|
||||
}
|
||||
|
||||
HX(stat(".", &st) == -1, st);
|
||||
HX(statvfs(".", &stvfs) == -1, stvfs);
|
||||
HX(statfs(".", &stfs) == -1, stfs);
|
||||
|
||||
HX(stat("/", &st) == -1, st);
|
||||
HX(statvfs("/", &stvfs) == -1, stvfs);
|
||||
HX(statfs("/", &stfs) == -1, stfs);
|
||||
|
||||
HX((e = fstat(0, &st)) == -1, st);
|
||||
if (e == -1) {
|
||||
if (S_ISREG(st.st_mode) ||
|
||||
S_ISFIFO(st.st_mode) ||
|
||||
S_ISSOCK(st.st_mode)) {
|
||||
HX(fstatvfs(0, &stvfs) == -1,
|
||||
stvfs);
|
||||
HX(fstatfs(0, &stfs) == -1,
|
||||
stfs);
|
||||
HX((off = lseek(0, (off_t)0,
|
||||
SEEK_CUR)) < 0, off);
|
||||
}
|
||||
if (S_ISCHR(st.st_mode)) {
|
||||
HX(tcgetattr(0, &tios) == -1,
|
||||
tios);
|
||||
} else if (S_ISSOCK(st.st_mode)) {
|
||||
memset(&ss, 0, sizeof ss);
|
||||
ssl = sizeof(ss);
|
||||
HX(getpeername(0,
|
||||
(void *)&ss, &ssl) == -1,
|
||||
ss);
|
||||
}
|
||||
}
|
||||
|
||||
HX((e = getrusage(RUSAGE_CHILDREN,
|
||||
&ru)) == -1, ru);
|
||||
if (e != -1) {
|
||||
cnt += (int)ru.ru_utime.tv_sec;
|
||||
cnt += (int)ru.ru_utime.tv_usec;
|
||||
}
|
||||
} else {
|
||||
/* Subsequent hashes absorb previous result */
|
||||
HD(results);
|
||||
}
|
||||
|
||||
HX((e = gettimeofday(&tv, NULL)) == -1, tv);
|
||||
if (e != -1) {
|
||||
cnt += (int)tv.tv_sec;
|
||||
cnt += (int)tv.tv_usec;
|
||||
}
|
||||
|
||||
HD(cnt);
|
||||
}
|
||||
|
||||
SHA512_Final(results, &ctx);
|
||||
memcpy((char *)buf + i, results, min(sizeof(results), len - i));
|
||||
i += min(sizeof(results), len - i);
|
||||
}
|
||||
explicit_bzero(&ctx, sizeof ctx);
|
||||
explicit_bzero(results, sizeof results);
|
||||
errno = save_errno;
|
||||
return (0); /* satisfied */
|
||||
return -1;
|
||||
}
|
||||
|
||||
+3
-10
@@ -59,10 +59,7 @@ static int inet_pton6 (const char *src, uint8_t *dst);
|
||||
* Paul Vixie, 1996.
|
||||
*/
|
||||
int
|
||||
inet_pton(af, src, dst)
|
||||
int af;
|
||||
const char *src;
|
||||
void *dst;
|
||||
inet_pton(int af, const char *src, void *dst)
|
||||
{
|
||||
switch (af) {
|
||||
case AF_INET:
|
||||
@@ -91,9 +88,7 @@ inet_pton(af, src, dst)
|
||||
* Paul Vixie, 1996.
|
||||
*/
|
||||
static int
|
||||
inet_pton4(src, dst)
|
||||
const char *src;
|
||||
uint8_t *dst;
|
||||
inet_pton4(const char *src, uint8_t *dst)
|
||||
{
|
||||
static const char digits[] = "0123456789";
|
||||
int saw_digit, octets, ch;
|
||||
@@ -145,9 +140,7 @@ inet_pton4(src, dst)
|
||||
* Paul Vixie, 1996.
|
||||
*/
|
||||
static int
|
||||
inet_pton6(src, dst)
|
||||
const char *src;
|
||||
uint8_t *dst;
|
||||
inet_pton6(const char *src, uint8_t *dst)
|
||||
{
|
||||
static const char xdigits_l[] = "0123456789abcdef",
|
||||
xdigits_u[] = "0123456789ABCDEF";
|
||||
|
||||
+32
@@ -31,6 +31,9 @@
|
||||
/* Whether daemon is deprecated */
|
||||
#undef DEPRECATED_DAEMON
|
||||
|
||||
/* Whether X509_NAME_get_text_by_NID is deprecated */
|
||||
#undef DEPRECATED_X509_NAME_GET_TEXT_BY_NID
|
||||
|
||||
/* Deprecate RSA 1024 bit length, makes that an unsupported key */
|
||||
#undef DEPRECATE_RSA_1024
|
||||
|
||||
@@ -60,6 +63,9 @@
|
||||
/* Define to 1 if you have the <arpa/inet.h> header file. */
|
||||
#undef HAVE_ARPA_INET_H
|
||||
|
||||
/* Define to 1 if you have the `ASN1_STRING_get0_data' function. */
|
||||
#undef HAVE_ASN1_STRING_GET0_DATA
|
||||
|
||||
/* Whether the C compiler accepts the "fallthrough" attribute */
|
||||
#undef HAVE_ATTR_FALLTHROUGH
|
||||
|
||||
@@ -140,6 +146,10 @@
|
||||
to 0 if you don't. */
|
||||
#undef HAVE_DECL_NGTCP2_CRYPTO_ENCRYPT_CB
|
||||
|
||||
/* Define to 1 if you have the declaration of `ngtcp2_crypto_ossl_ctx_new',
|
||||
and to 0 if you don't. */
|
||||
#undef HAVE_DECL_NGTCP2_CRYPTO_OSSL_CTX_NEW
|
||||
|
||||
/* Define to 1 if you have the declaration of `NID_ED25519', and to 0 if you
|
||||
don't. */
|
||||
#undef HAVE_DECL_NID_ED25519
|
||||
@@ -289,6 +299,12 @@
|
||||
/* Define to 1 if you have the `FIPS_mode' function. */
|
||||
#undef HAVE_FIPS_MODE
|
||||
|
||||
/* Define to 1 if you have the `fnmatch' function. */
|
||||
#undef HAVE_FNMATCH
|
||||
|
||||
/* Define to 1 if you have the <fnmatch.h> header file. */
|
||||
#undef HAVE_FNMATCH_H
|
||||
|
||||
/* Define to 1 if you have the `fork' function. */
|
||||
#undef HAVE_FORK
|
||||
|
||||
@@ -513,6 +529,9 @@
|
||||
/* Define to 1 if you have the <openssl/bn.h> header file. */
|
||||
#undef HAVE_OPENSSL_BN_H
|
||||
|
||||
/* Define to 1 if you have the `OPENSSL_cleanup' function. */
|
||||
#undef HAVE_OPENSSL_CLEANUP
|
||||
|
||||
/* Define to 1 if you have the `OPENSSL_config' function. */
|
||||
#undef HAVE_OPENSSL_CONFIG
|
||||
|
||||
@@ -685,9 +704,16 @@
|
||||
/* 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_dnsname' function. */
|
||||
#undef HAVE_SSL_SET1_DNSNAME
|
||||
|
||||
/* Define to 1 if you have the `SSL_set1_host' function. */
|
||||
#undef HAVE_SSL_SET1_HOST
|
||||
|
||||
/* Define to 1 if you have the `SSL_set_quic_tls_early_data_enabled' function.
|
||||
*/
|
||||
#undef HAVE_SSL_SET_QUIC_TLS_EARLY_DATA_ENABLED
|
||||
|
||||
/* Define to 1 if you have the <stdarg.h> header file. */
|
||||
#undef HAVE_STDARG_H
|
||||
|
||||
@@ -852,6 +878,12 @@
|
||||
/* Define to 1 if you have the <ws2tcpip.h> header file. */
|
||||
#undef HAVE_WS2TCPIP_H
|
||||
|
||||
/* Define to 1 if you have the `X509_get_key_usage' function. */
|
||||
#undef HAVE_X509_GET_KEY_USAGE
|
||||
|
||||
/* Define to 1 if you have the `X509_NAME_get_text_by_NID' function. */
|
||||
#undef HAVE_X509_NAME_GET_TEXT_BY_NID
|
||||
|
||||
/* Define to 1 if you have the `X509_VERIFY_PARAM_set1_host' function. */
|
||||
#undef HAVE_X509_VERIFY_PARAM_SET1_HOST
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#! /bin/sh
|
||||
# Guess values for system-dependent variables and create Makefiles.
|
||||
# Generated by GNU Autoconf 2.71 for unbound 1.25.2.
|
||||
# Generated by GNU Autoconf 2.71 for unbound 1.26.2.
|
||||
#
|
||||
# Report bugs to <unbound-bugs@nlnetlabs.nl or https://github.com/NLnetLabs/unbound/issues>.
|
||||
#
|
||||
@@ -622,8 +622,8 @@ MAKEFLAGS=
|
||||
# Identity of this package.
|
||||
PACKAGE_NAME='unbound'
|
||||
PACKAGE_TARNAME='unbound'
|
||||
PACKAGE_VERSION='1.25.2'
|
||||
PACKAGE_STRING='unbound 1.25.2'
|
||||
PACKAGE_VERSION='1.26.2'
|
||||
PACKAGE_STRING='unbound 1.26.2'
|
||||
PACKAGE_BUGREPORT='unbound-bugs@nlnetlabs.nl or https://github.com/NLnetLabs/unbound/issues'
|
||||
PACKAGE_URL=''
|
||||
|
||||
@@ -1513,7 +1513,7 @@ if test "$ac_init_help" = "long"; then
|
||||
# Omit some internal or obsolete options to make the list less imposing.
|
||||
# This message is too long to be a string in the A/UX 3.1 sh.
|
||||
cat <<_ACEOF
|
||||
\`configure' configures unbound 1.25.2 to adapt to many kinds of systems.
|
||||
\`configure' configures unbound 1.26.2 to adapt to many kinds of systems.
|
||||
|
||||
Usage: $0 [OPTION]... [VAR=VALUE]...
|
||||
|
||||
@@ -1579,7 +1579,7 @@ fi
|
||||
|
||||
if test -n "$ac_init_help"; then
|
||||
case $ac_init_help in
|
||||
short | recursive ) echo "Configuration of unbound 1.25.2:";;
|
||||
short | recursive ) echo "Configuration of unbound 1.26.2:";;
|
||||
esac
|
||||
cat <<\_ACEOF
|
||||
|
||||
@@ -1832,7 +1832,7 @@ fi
|
||||
test -n "$ac_init_help" && exit $ac_status
|
||||
if $ac_init_version; then
|
||||
cat <<\_ACEOF
|
||||
unbound configure 1.25.2
|
||||
unbound configure 1.26.2
|
||||
generated by GNU Autoconf 2.71
|
||||
|
||||
Copyright (C) 2021 Free Software Foundation, Inc.
|
||||
@@ -2489,7 +2489,7 @@ cat >config.log <<_ACEOF
|
||||
This file contains any messages produced by compilers while
|
||||
running configure, to aid debugging if configure makes a mistake.
|
||||
|
||||
It was created by unbound $as_me 1.25.2, which was
|
||||
It was created by unbound $as_me 1.26.2, which was
|
||||
generated by GNU Autoconf 2.71. Invocation command line was
|
||||
|
||||
$ $0$ac_configure_args_raw
|
||||
@@ -3251,13 +3251,13 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
|
||||
|
||||
UNBOUND_VERSION_MAJOR=1
|
||||
|
||||
UNBOUND_VERSION_MINOR=25
|
||||
UNBOUND_VERSION_MINOR=26
|
||||
|
||||
UNBOUND_VERSION_MICRO=2
|
||||
|
||||
|
||||
LIBUNBOUND_CURRENT=9
|
||||
LIBUNBOUND_REVISION=38
|
||||
LIBUNBOUND_REVISION=41
|
||||
LIBUNBOUND_AGE=1
|
||||
# 1.0.0 had 0:12:0
|
||||
# 1.0.1 had 0:13:0
|
||||
@@ -3363,6 +3363,9 @@ LIBUNBOUND_AGE=1
|
||||
# 1.25.0 had 9:36:1
|
||||
# 1.25.1 had 9:37:1
|
||||
# 1.25.2 had 9:38:1
|
||||
# 1.26.0 had 9:39:1
|
||||
# 1.26.1 had 9:40:1
|
||||
# 1.26.2 had 9:41:1
|
||||
|
||||
# Current -- the number of the binary API that we're implementing
|
||||
# Revision -- which iteration of the implementation of the binary
|
||||
@@ -16005,6 +16008,13 @@ if test "x$ac_cv_header_glob_h" = xyes
|
||||
then :
|
||||
printf "%s\n" "#define HAVE_GLOB_H 1" >>confdefs.h
|
||||
|
||||
fi
|
||||
ac_fn_c_check_header_compile "$LINENO" "fnmatch.h" "ac_cv_header_fnmatch_h" "$ac_includes_default
|
||||
"
|
||||
if test "x$ac_cv_header_fnmatch_h" = xyes
|
||||
then :
|
||||
printf "%s\n" "#define HAVE_FNMATCH_H 1" >>confdefs.h
|
||||
|
||||
fi
|
||||
ac_fn_c_check_header_compile "$LINENO" "grp.h" "ac_cv_header_grp_h" "$ac_includes_default
|
||||
"
|
||||
@@ -18407,7 +18417,31 @@ fi
|
||||
# correctly enabled
|
||||
|
||||
case $host_os in
|
||||
darwin* | hpux* | linux* | osf* | solaris*)
|
||||
solaris*)
|
||||
# Solaris 11.4 introduced XPG7 support and did away with the need for
|
||||
# _REENTRANT.
|
||||
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
|
||||
# undef _XOPEN_SOURCE
|
||||
# include <sys/feature_tests.h>
|
||||
# if _XOPEN_VERSION < 700
|
||||
AX_PTHREAD_SOLARIS__REENTRANT
|
||||
# endif
|
||||
|
||||
_ACEOF
|
||||
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
|
||||
$EGREP "AX_PTHREAD_SOLARIS__REENTRANT" >/dev/null 2>&1
|
||||
then :
|
||||
ax_pthread_check_macro="_REENTRANT"
|
||||
else $as_nop
|
||||
ax_pthread_check_macro="--"
|
||||
fi
|
||||
rm -rf conftest*
|
||||
|
||||
;;
|
||||
darwin* | hpux* | linux* | osf*)
|
||||
ax_pthread_check_macro="_REENTRANT"
|
||||
;;
|
||||
|
||||
@@ -21061,6 +21095,12 @@ then :
|
||||
printf "%s\n" "#define HAVE_BIO_SET_CALLBACK_EX 1" >>confdefs.h
|
||||
|
||||
fi
|
||||
ac_fn_c_check_func "$LINENO" "OPENSSL_cleanup" "ac_cv_func_OPENSSL_cleanup"
|
||||
if test "x$ac_cv_func_OPENSSL_cleanup" = xyes
|
||||
then :
|
||||
printf "%s\n" "#define HAVE_OPENSSL_CLEANUP 1" >>confdefs.h
|
||||
|
||||
fi
|
||||
|
||||
|
||||
# these check_funcs need -lssl
|
||||
@@ -21089,6 +21129,24 @@ if test "x$ac_cv_func_SSL_get0_peername" = xyes
|
||||
then :
|
||||
printf "%s\n" "#define HAVE_SSL_GET0_PEERNAME 1" >>confdefs.h
|
||||
|
||||
fi
|
||||
ac_fn_c_check_func "$LINENO" "SSL_set1_dnsname" "ac_cv_func_SSL_set1_dnsname"
|
||||
if test "x$ac_cv_func_SSL_set1_dnsname" = xyes
|
||||
then :
|
||||
printf "%s\n" "#define HAVE_SSL_SET1_DNSNAME 1" >>confdefs.h
|
||||
|
||||
fi
|
||||
ac_fn_c_check_func "$LINENO" "X509_get_key_usage" "ac_cv_func_X509_get_key_usage"
|
||||
if test "x$ac_cv_func_X509_get_key_usage" = xyes
|
||||
then :
|
||||
printf "%s\n" "#define HAVE_X509_GET_KEY_USAGE 1" >>confdefs.h
|
||||
|
||||
fi
|
||||
ac_fn_c_check_func "$LINENO" "ASN1_STRING_get0_data" "ac_cv_func_ASN1_STRING_get0_data"
|
||||
if test "x$ac_cv_func_ASN1_STRING_get0_data" = xyes
|
||||
then :
|
||||
printf "%s\n" "#define HAVE_ASN1_STRING_GET0_DATA 1" >>confdefs.h
|
||||
|
||||
fi
|
||||
ac_fn_c_check_func "$LINENO" "X509_VERIFY_PARAM_set1_host" "ac_cv_func_X509_VERIFY_PARAM_set1_host"
|
||||
if test "x$ac_cv_func_X509_VERIFY_PARAM_set1_host" = xyes
|
||||
@@ -21133,6 +21191,54 @@ then :
|
||||
|
||||
fi
|
||||
|
||||
ac_fn_c_check_func "$LINENO" "X509_NAME_get_text_by_NID" "ac_cv_func_X509_NAME_get_text_by_NID"
|
||||
if test "x$ac_cv_func_X509_NAME_get_text_by_NID" = xyes
|
||||
then :
|
||||
printf "%s\n" "#define HAVE_X509_NAME_GET_TEXT_BY_NID 1" >>confdefs.h
|
||||
|
||||
fi
|
||||
|
||||
if test $ac_cv_func_X509_NAME_get_text_by_NID = yes; then
|
||||
|
||||
|
||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if X509_NAME_get_text_by_NID is deprecated" >&5
|
||||
printf %s "checking if X509_NAME_get_text_by_NID is deprecated... " >&6; }
|
||||
cache=`echo X509_NAME_get_text_by_NID | sed 'y%.=/+-%___p_%'`
|
||||
if eval test \${cv_cc_deprecated_$cache+y}
|
||||
then :
|
||||
printf %s "(cached) " >&6
|
||||
else $as_nop
|
||||
|
||||
echo '
|
||||
#include "openssl/x509.h"
|
||||
' >conftest.c
|
||||
echo 'void f(void){
|
||||
(void)X509_NAME_get_text_by_NID(NULL, 0, NULL, 0); }' >>conftest.c
|
||||
if test -z "`$CC $CPPFLAGS $CFLAGS -c conftest.c 2>&1 | grep -e deprecated -e unavailable`"; then
|
||||
eval "cv_cc_deprecated_$cache=no"
|
||||
else
|
||||
eval "cv_cc_deprecated_$cache=yes"
|
||||
fi
|
||||
rm -f conftest conftest.o conftest.c
|
||||
|
||||
fi
|
||||
|
||||
if eval "test \"`echo '$cv_cc_deprecated_'$cache`\" = yes"; then
|
||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
|
||||
printf "%s\n" "yes" >&6; }
|
||||
|
||||
printf "%s\n" "#define DEPRECATED_X509_NAME_GET_TEXT_BY_NID 1" >>confdefs.h
|
||||
|
||||
:
|
||||
|
||||
else
|
||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
printf "%s\n" "no" >&6; }
|
||||
:
|
||||
|
||||
fi
|
||||
|
||||
fi
|
||||
LIBS="$BAKLIBS"
|
||||
|
||||
ac_fn_check_decl "$LINENO" "SSL_COMP_get_compression_methods" "ac_cv_have_decl_SSL_COMP_get_compression_methods" "
|
||||
@@ -22639,6 +22745,24 @@ then :
|
||||
|
||||
printf "%s\n" "#define USE_NGTCP2_CRYPTO_OSSL 1" >>confdefs.h
|
||||
|
||||
ac_fn_check_decl "$LINENO" "ngtcp2_crypto_ossl_ctx_new" "ac_cv_have_decl_ngtcp2_crypto_ossl_ctx_new" "$ac_includes_default
|
||||
#include <ngtcp2/ngtcp2_crypto_ossl.h>
|
||||
|
||||
" "$ac_c_undeclared_builtin_options" "CFLAGS"
|
||||
if test "x$ac_cv_have_decl_ngtcp2_crypto_ossl_ctx_new" = xyes
|
||||
then :
|
||||
ac_have_decl=1
|
||||
else $as_nop
|
||||
ac_have_decl=0
|
||||
fi
|
||||
printf "%s\n" "#define HAVE_DECL_NGTCP2_CRYPTO_OSSL_CTX_NEW $ac_have_decl" >>confdefs.h
|
||||
if test $ac_have_decl = 1
|
||||
then :
|
||||
|
||||
else $as_nop
|
||||
as_fn_error $? "No declaration of ngtcp2_crypto_ossl_ctx_new in the ngtcp2_crypto_ossl header file. Perhaps the ngtcp2_crypto_ossl devel header files need to be installed." "$LINENO" 5
|
||||
fi
|
||||
|
||||
|
||||
else $as_nop
|
||||
|
||||
@@ -22818,6 +22942,13 @@ else $as_nop
|
||||
fi
|
||||
|
||||
done
|
||||
ac_fn_c_check_func "$LINENO" "SSL_set_quic_tls_early_data_enabled" "ac_cv_func_SSL_set_quic_tls_early_data_enabled"
|
||||
if test "x$ac_cv_func_SSL_set_quic_tls_early_data_enabled" = xyes
|
||||
then :
|
||||
printf "%s\n" "#define HAVE_SSL_SET_QUIC_TLS_EARLY_DATA_ENABLED 1" >>confdefs.h
|
||||
|
||||
fi
|
||||
|
||||
LIBS="$BAKLIBS"
|
||||
|
||||
ac_fn_c_check_type "$LINENO" "struct ngtcp2_version_cid" "ac_cv_type_struct_ngtcp2_version_cid" "$ac_includes_default
|
||||
@@ -23780,6 +23911,12 @@ if test "x$ac_cv_func_glob" = xyes
|
||||
then :
|
||||
printf "%s\n" "#define HAVE_GLOB 1" >>confdefs.h
|
||||
|
||||
fi
|
||||
ac_fn_c_check_func "$LINENO" "fnmatch" "ac_cv_func_fnmatch"
|
||||
if test "x$ac_cv_func_fnmatch" = xyes
|
||||
then :
|
||||
printf "%s\n" "#define HAVE_FNMATCH 1" >>confdefs.h
|
||||
|
||||
fi
|
||||
ac_fn_c_check_func "$LINENO" "initgroups" "ac_cv_func_initgroups"
|
||||
if test "x$ac_cv_func_initgroups" = xyes
|
||||
@@ -25576,7 +25713,7 @@ printf "%s\n" "#define MAXSYSLOGMSGLEN 10240" >>confdefs.h
|
||||
|
||||
|
||||
|
||||
version=1.25.2
|
||||
version=1.26.2
|
||||
|
||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for build time" >&5
|
||||
printf %s "checking for build time... " >&6; }
|
||||
@@ -26106,7 +26243,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
|
||||
# report actual input values of CONFIG_FILES etc. instead of their
|
||||
# values after options handling.
|
||||
ac_log="
|
||||
This file was extended by unbound $as_me 1.25.2, which was
|
||||
This file was extended by unbound $as_me 1.26.2, which was
|
||||
generated by GNU Autoconf 2.71. Invocation command line was
|
||||
|
||||
CONFIG_FILES = $CONFIG_FILES
|
||||
@@ -26174,7 +26311,7 @@ ac_cs_config_escaped=`printf "%s\n" "$ac_cs_config" | sed "s/^ //; s/'/'\\\\\\\\
|
||||
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
|
||||
ac_cs_config='$ac_cs_config_escaped'
|
||||
ac_cs_version="\\
|
||||
unbound config.status 1.25.2
|
||||
unbound config.status 1.26.2
|
||||
configured by $0, generated by GNU Autoconf 2.71,
|
||||
with options \\"\$ac_cs_config\\"
|
||||
|
||||
|
||||
+20
-6
@@ -11,7 +11,7 @@ sinclude(dnscrypt/dnscrypt.m4)
|
||||
|
||||
# must be numbers. ac_defun because of later processing
|
||||
m4_define([VERSION_MAJOR],[1])
|
||||
m4_define([VERSION_MINOR],[25])
|
||||
m4_define([VERSION_MINOR],[26])
|
||||
m4_define([VERSION_MICRO],[2])
|
||||
AC_INIT([unbound],m4_defn([VERSION_MAJOR]).m4_defn([VERSION_MINOR]).m4_defn([VERSION_MICRO]),[unbound-bugs@nlnetlabs.nl or https://github.com/NLnetLabs/unbound/issues],[unbound])
|
||||
AC_SUBST(UNBOUND_VERSION_MAJOR, [VERSION_MAJOR])
|
||||
@@ -19,7 +19,7 @@ AC_SUBST(UNBOUND_VERSION_MINOR, [VERSION_MINOR])
|
||||
AC_SUBST(UNBOUND_VERSION_MICRO, [VERSION_MICRO])
|
||||
|
||||
LIBUNBOUND_CURRENT=9
|
||||
LIBUNBOUND_REVISION=38
|
||||
LIBUNBOUND_REVISION=41
|
||||
LIBUNBOUND_AGE=1
|
||||
# 1.0.0 had 0:12:0
|
||||
# 1.0.1 had 0:13:0
|
||||
@@ -125,6 +125,9 @@ LIBUNBOUND_AGE=1
|
||||
# 1.25.0 had 9:36:1
|
||||
# 1.25.1 had 9:37:1
|
||||
# 1.25.2 had 9:38:1
|
||||
# 1.26.0 had 9:39:1
|
||||
# 1.26.1 had 9:40:1
|
||||
# 1.26.2 had 9:41:1
|
||||
|
||||
# Current -- the number of the binary API that we're implementing
|
||||
# Revision -- which iteration of the implementation of the binary
|
||||
@@ -483,7 +486,7 @@ PKG_PROG_PKG_CONFIG
|
||||
fi
|
||||
|
||||
# Checks for header files.
|
||||
AC_CHECK_HEADERS([stdarg.h stdbool.h netinet/in.h netinet/tcp.h sys/param.h sys/select.h sys/socket.h sys/un.h sys/uio.h sys/resource.h arpa/inet.h syslog.h netdb.h sys/wait.h pwd.h glob.h grp.h login_cap.h winsock2.h ws2tcpip.h endian.h sys/endian.h libkern/OSByteOrder.h sys/ipc.h sys/shm.h ifaddrs.h poll.h],,, [AC_INCLUDES_DEFAULT])
|
||||
AC_CHECK_HEADERS([stdarg.h stdbool.h netinet/in.h netinet/tcp.h sys/param.h sys/select.h sys/socket.h sys/un.h sys/uio.h sys/resource.h arpa/inet.h syslog.h netdb.h sys/wait.h pwd.h glob.h fnmatch.h grp.h login_cap.h winsock2.h ws2tcpip.h endian.h sys/endian.h libkern/OSByteOrder.h sys/ipc.h sys/shm.h ifaddrs.h poll.h],,, [AC_INCLUDES_DEFAULT])
|
||||
# net/if.h portability for Darwin see:
|
||||
# https://www.gnu.org/software/autoconf/manual/autoconf-2.69/html_node/Header-Portability.html
|
||||
AC_CHECK_HEADERS([net/if.h],,, [
|
||||
@@ -1080,12 +1083,19 @@ 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 OPENSSL_cleanup])
|
||||
|
||||
# these check_funcs need -lssl
|
||||
BAKLIBS="$LIBS"
|
||||
LIBS="-lssl $LIBS"
|
||||
AC_CHECK_FUNCS([OPENSSL_init_ssl SSL_CTX_set_security_level SSL_set1_host SSL_get0_peername X509_VERIFY_PARAM_set1_host SSL_CTX_set_ciphersuites SSL_CTX_set_tlsext_ticket_key_evp_cb SSL_CTX_set_alpn_select_cb SSL_get0_alpn_selected SSL_CTX_set_alpn_protos SSL_get1_peer_certificate])
|
||||
AC_CHECK_FUNCS([OPENSSL_init_ssl SSL_CTX_set_security_level SSL_set1_host SSL_get0_peername SSL_set1_dnsname X509_get_key_usage ASN1_STRING_get0_data X509_VERIFY_PARAM_set1_host SSL_CTX_set_ciphersuites SSL_CTX_set_tlsext_ticket_key_evp_cb SSL_CTX_set_alpn_select_cb SSL_get0_alpn_selected SSL_CTX_set_alpn_protos SSL_get1_peer_certificate])
|
||||
AC_CHECK_FUNCS([X509_NAME_get_text_by_NID])
|
||||
if test $ac_cv_func_X509_NAME_get_text_by_NID = yes; then
|
||||
ACX_FUNC_DEPRECATED([X509_NAME_get_text_by_NID], [
|
||||
(void)X509_NAME_get_text_by_NID(NULL, 0, NULL, 0);], [
|
||||
#include "openssl/x509.h"
|
||||
])
|
||||
fi
|
||||
LIBS="$BAKLIBS"
|
||||
|
||||
AC_CHECK_DECLS([SSL_COMP_get_compression_methods,sk_SSL_COMP_pop_free,SSL_CTX_set_ecdh_auto,SSL_CTX_set_tmp_ecdh], [], [], [
|
||||
@@ -1704,6 +1714,9 @@ if test x_$withval = x_yes -o x_$withval != x_no; then
|
||||
AC_CHECK_LIB([ngtcp2_crypto_ossl], [ngtcp2_crypto_encrypt_cb], [
|
||||
LIBS="$LIBS -lngtcp2_crypto_ossl"
|
||||
AC_DEFINE(USE_NGTCP2_CRYPTO_OSSL, 1, [Define this to use ngtcp2_crypto_ossl.])
|
||||
AC_CHECK_DECLS([ngtcp2_crypto_ossl_ctx_new], [], [AC_MSG_ERROR([No declaration of ngtcp2_crypto_ossl_ctx_new in the ngtcp2_crypto_ossl header file. Perhaps the ngtcp2_crypto_ossl devel header files need to be installed.])], [AC_INCLUDES_DEFAULT
|
||||
#include <ngtcp2/ngtcp2_crypto_ossl.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" ])
|
||||
@@ -1715,6 +1728,7 @@ if test x_$withval = x_yes -o x_$withval != x_no; then
|
||||
BAKLIBS="$LIBS"
|
||||
LIBS="-lssl $LIBS"
|
||||
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_FUNCS([SSL_set_quic_tls_early_data_enabled])
|
||||
LIBS="$BAKLIBS"
|
||||
|
||||
AC_CHECK_TYPES([struct ngtcp2_version_cid, ngtcp2_encryption_level],,,[AC_INCLUDES_DEFAULT
|
||||
@@ -1928,7 +1942,7 @@ AC_LINK_IFELSE([AC_LANG_PROGRAM([
|
||||
AC_MSG_RESULT(no))
|
||||
|
||||
AC_SEARCH_LIBS([setusercontext], [util])
|
||||
AC_CHECK_FUNCS([tzset sigprocmask fcntl getpwnam endpwent getrlimit setrlimit setsid chroot kill chown sleep usleep random srandom recvmsg sendmsg writev socketpair glob initgroups strftime localtime_r setusercontext _beginthreadex endservent endprotoent fsync shmget accept4 getifaddrs if_nametoindex poll gettid])
|
||||
AC_CHECK_FUNCS([tzset sigprocmask fcntl getpwnam endpwent getrlimit setrlimit setsid chroot kill chown sleep usleep random srandom recvmsg sendmsg writev socketpair glob fnmatch initgroups strftime localtime_r setusercontext _beginthreadex endservent endprotoent fsync shmget accept4 getifaddrs if_nametoindex poll gettid])
|
||||
AC_CHECK_FUNCS([setresuid],,[AC_CHECK_FUNCS([setreuid])])
|
||||
AC_CHECK_FUNCS([setresgid],,[AC_CHECK_FUNCS([setregid])])
|
||||
|
||||
|
||||
+3
-3
@@ -99,7 +99,7 @@ static void
|
||||
dump_rrset_line(struct config_strlist_head* txt, struct ub_packed_rrset_key* k,
|
||||
time_t now, size_t i)
|
||||
{
|
||||
char s[65535];
|
||||
char s[65535*4+2048];
|
||||
if(!packed_rr_to_string(k, i, now, s, sizeof(s))) {
|
||||
spool_txt_string(txt, "BADRR\n");
|
||||
return;
|
||||
@@ -455,7 +455,7 @@ load_rr(RES* ssl, sldns_buffer* buf, struct regional* region,
|
||||
/* read the line */
|
||||
if(!ssl_read_buf(ssl, buf))
|
||||
return 0;
|
||||
if(strncmp((char*)sldns_buffer_begin(buf), "BADRR\n", 6) == 0) {
|
||||
if(strcmp((char*)sldns_buffer_begin(buf), "BADRR") == 0) {
|
||||
*go_on = 0;
|
||||
return 1;
|
||||
}
|
||||
@@ -554,7 +554,7 @@ move_into_cache(struct ub_packed_rrset_key* k,
|
||||
|
||||
ref.key = ak;
|
||||
ref.id = ak->id;
|
||||
(void)rrset_cache_update(worker->env.rrset_cache, &ref,
|
||||
rrset_cache_update_unlock(worker->env.rrset_cache, &ref,
|
||||
worker->alloc, *worker->env.now);
|
||||
|
||||
return 1;
|
||||
|
||||
+43
-11
@@ -86,6 +86,7 @@
|
||||
#include "services/view.h"
|
||||
#include "services/modstack.h"
|
||||
#include "services/authzone.h"
|
||||
#include "services/authload.h"
|
||||
#include "util/module.h"
|
||||
#include "util/random.h"
|
||||
#include "util/tube.h"
|
||||
@@ -217,7 +218,8 @@ setup_listen_sslctx(void** ctx, int is_dot, int is_doh,
|
||||
(cfg->tls_session_ticket_keys.first &&
|
||||
cfg->tls_session_ticket_keys.first->str[0] != 0),
|
||||
is_dot, is_doh, cfg->tls_protocols))) {
|
||||
fatal_exit("could not set up listen SSL_CTX");
|
||||
log_err("could not set up listen SSL_CTX");
|
||||
*ctx = NULL;
|
||||
}
|
||||
}
|
||||
#endif /* HAVE_SSL */
|
||||
@@ -259,7 +261,8 @@ void* daemon_setup_listen_quic_sslctx(struct daemon* daemon,
|
||||
pem += strlen(chroot);
|
||||
|
||||
if(!(ctx = quic_sslctx_create(key, pem, NULL))) {
|
||||
fatal_exit("could not set up quic SSL_CTX");
|
||||
log_err("could not set up quic SSL_CTX");
|
||||
return NULL;
|
||||
}
|
||||
return ctx;
|
||||
}
|
||||
@@ -277,8 +280,10 @@ void* daemon_setup_connect_dot_sslctx(struct daemon* daemon,
|
||||
bundle += strlen(chroot);
|
||||
|
||||
if(!(ctx = connect_sslctx_create(NULL, NULL, bundle,
|
||||
cfg->tls_win_cert)))
|
||||
fatal_exit("could not set up connect SSL_CTX");
|
||||
cfg->tls_win_cert))) {
|
||||
log_err("could not set up connect SSL_CTX");
|
||||
return NULL;
|
||||
}
|
||||
return ctx;
|
||||
}
|
||||
#endif /* HAVE_SSL */
|
||||
@@ -308,16 +313,22 @@ daemon_setup_sslctxs(struct daemon* daemon, struct config_file* cfg)
|
||||
}
|
||||
daemon->listen_dot_sslctx = daemon_setup_listen_dot_sslctx(
|
||||
daemon, cfg);
|
||||
if(!daemon->listen_dot_sslctx)
|
||||
fatal_exit("Could not set up listen dot sslctx");
|
||||
#ifdef HAVE_NGHTTP2_NGHTTP2_H
|
||||
if(cfg_has_https(cfg)) {
|
||||
daemon->listen_doh_sslctx =
|
||||
daemon_setup_listen_doh_sslctx(daemon, cfg);
|
||||
if(!daemon->listen_doh_sslctx)
|
||||
fatal_exit("Could not set up listen doh sslctx");
|
||||
}
|
||||
#endif
|
||||
#ifdef HAVE_NGTCP2
|
||||
if(cfg_has_quic(cfg)) {
|
||||
daemon->listen_quic_sslctx =
|
||||
daemon_setup_listen_quic_sslctx(daemon, cfg);
|
||||
if(!daemon->listen_quic_sslctx)
|
||||
fatal_exit("Could not set up listen quic sslctx");
|
||||
}
|
||||
#endif /* HAVE_NGTCP2 */
|
||||
|
||||
@@ -350,6 +361,8 @@ daemon_setup_sslctxs(struct daemon* daemon, struct config_file* cfg)
|
||||
}
|
||||
daemon->connect_dot_sslctx = daemon_setup_connect_dot_sslctx(
|
||||
daemon, cfg);
|
||||
if(!daemon->connect_dot_sslctx)
|
||||
fatal_exit("could not setup connect dot sslctx");
|
||||
#else /* HAVE_SSL */
|
||||
(void)daemon;(void)cfg;
|
||||
#endif /* HAVE_SSL */
|
||||
@@ -578,6 +591,17 @@ daemon_init(void)
|
||||
free(daemon);
|
||||
return NULL;
|
||||
}
|
||||
if(!(daemon->auth_load_info = auth_load_info_create())) {
|
||||
edns_strings_delete(daemon->env->edns_strings);
|
||||
auth_zones_delete(daemon->env->auth_zones);
|
||||
acl_list_delete(daemon->acl_interface);
|
||||
acl_list_delete(daemon->acl);
|
||||
tcl_list_delete(daemon->tcl);
|
||||
edns_known_options_delete(daemon->env);
|
||||
free(daemon->env);
|
||||
free(daemon);
|
||||
return NULL;
|
||||
}
|
||||
return daemon;
|
||||
}
|
||||
|
||||
@@ -921,13 +945,14 @@ thread_start(void* arg)
|
||||
{
|
||||
struct worker* worker = (struct worker*)arg;
|
||||
int port_num = 0;
|
||||
log_assert(worker->thr_id);
|
||||
set_log_thread_id(worker, worker->daemon->cfg);
|
||||
{
|
||||
char name[16]; /* seems to be the safest size between
|
||||
different OSes */
|
||||
snprintf(name, sizeof(name), "unbound/%u", worker->thread_num);
|
||||
ub_thread_setname(worker->thr_id, name);
|
||||
/* worker->thr_id can be written to after the thread was made
|
||||
* by the creating thread, so this uses pthread_self. */
|
||||
ub_thread_setname(ub_thread_self(), name);
|
||||
}
|
||||
ub_thread_blocksigs();
|
||||
#ifdef THREADS_DISABLED
|
||||
@@ -942,8 +967,9 @@ thread_start(void* arg)
|
||||
port_num = 0;
|
||||
#endif
|
||||
if(!worker_init(worker, worker->daemon->cfg,
|
||||
worker->daemon->ports[port_num], 0))
|
||||
worker->daemon->ports[port_num], 0)) {
|
||||
fatal_exit("Could not initialize thread");
|
||||
}
|
||||
|
||||
worker_work(worker);
|
||||
return NULL;
|
||||
@@ -1105,8 +1131,9 @@ daemon_fork(struct daemon* daemon)
|
||||
|
||||
#if defined(HAVE_EV_LOOP) || defined(HAVE_EV_DEFAULT_LOOP)
|
||||
/* in libev the first inited base gets signals */
|
||||
if(!worker_init(daemon->workers[0], daemon->cfg, daemon->ports[0], 1))
|
||||
if(!worker_init(daemon->workers[0], daemon->cfg, daemon->ports[0], 1)) {
|
||||
fatal_exit("Could not initialize main thread");
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Now create the threads and init the workers.
|
||||
@@ -1119,8 +1146,9 @@ daemon_fork(struct daemon* daemon)
|
||||
*/
|
||||
#if !(defined(HAVE_EV_LOOP) || defined(HAVE_EV_DEFAULT_LOOP))
|
||||
/* libevent has the last inited base get signals (or any base) */
|
||||
if(!worker_init(daemon->workers[0], daemon->cfg, daemon->ports[0], 1))
|
||||
if(!worker_init(daemon->workers[0], daemon->cfg, daemon->ports[0], 1)) {
|
||||
fatal_exit("Could not initialize main thread");
|
||||
}
|
||||
#endif
|
||||
signal_handling_playback(daemon->workers[0]);
|
||||
|
||||
@@ -1148,6 +1176,7 @@ daemon_fork(struct daemon* daemon)
|
||||
|
||||
/* we exited! a signal happened! Stop other threads */
|
||||
daemon_stop_others(daemon);
|
||||
auth_load_stop_threads(daemon);
|
||||
|
||||
/* Shutdown SHM */
|
||||
shm_main_shutdown(daemon);
|
||||
@@ -1164,7 +1193,6 @@ daemon_cleanup(struct daemon* daemon)
|
||||
/* before stopping main worker, handle signals ourselves, so we
|
||||
don't die on multiple reload signals for example. */
|
||||
signal_handling_record();
|
||||
log_thread_set(NULL);
|
||||
/* clean up caches because
|
||||
* a) RRset IDs will be recycled after a reload, causing collisions
|
||||
* b) validation config can change, thus rrset, msg, keycache clear
|
||||
@@ -1247,6 +1275,7 @@ daemon_delete(struct daemon* daemon)
|
||||
edns_strings_delete(daemon->env->edns_strings);
|
||||
auth_zones_delete(daemon->env->auth_zones);
|
||||
}
|
||||
auth_load_info_delete(daemon->auth_load_info);
|
||||
ub_randfree(daemon->rand);
|
||||
alloc_clear(&daemon->superalloc);
|
||||
acl_list_delete(daemon->acl);
|
||||
@@ -1270,7 +1299,7 @@ daemon_delete(struct daemon* daemon)
|
||||
# if HAVE_DECL_SSL_COMP_GET_COMPRESSION_METHODS && HAVE_DECL_SK_SSL_COMP_POP_FREE
|
||||
# ifndef S_SPLINT_S
|
||||
# if OPENSSL_VERSION_NUMBER < 0x10100000
|
||||
sk_SSL_COMP_pop_free(comp_meth, (void(*)())CRYPTO_free);
|
||||
sk_SSL_COMP_pop_free(comp_meth, (void(*)(SSL_COMP*))CRYPTO_free);
|
||||
# endif
|
||||
# endif
|
||||
# endif
|
||||
@@ -1293,6 +1322,9 @@ daemon_delete(struct daemon* daemon)
|
||||
# if defined(HAVE_SSL) && defined(OPENSSL_THREADS) && !defined(THREADS_DISABLED)
|
||||
ub_openssl_lock_delete();
|
||||
# endif
|
||||
#ifdef HAVE_OPENSSL_CLEANUP
|
||||
OPENSSL_cleanup();
|
||||
#endif
|
||||
#ifndef HAVE_ARC4RANDOM
|
||||
_ARC4_LOCK_DESTROY();
|
||||
#endif
|
||||
|
||||
@@ -62,6 +62,7 @@ struct doq_table;
|
||||
struct cookie_secrets;
|
||||
struct fast_reload_thread;
|
||||
struct fast_reload_printq;
|
||||
struct auth_load_general_info;
|
||||
struct shared_ports;
|
||||
|
||||
#include "dnstap/dnstap_config.h"
|
||||
@@ -191,6 +192,8 @@ struct daemon {
|
||||
int fast_reload_tcl_has_changes;
|
||||
/** config file name */
|
||||
char* cfgfile;
|
||||
/** Auth load threads, the number of active threads. */
|
||||
struct auth_load_general_info* auth_load_info;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
+285
-386
@@ -73,6 +73,7 @@
|
||||
#include "services/mesh.h"
|
||||
#include "services/localzone.h"
|
||||
#include "services/authzone.h"
|
||||
#include "services/authload.h"
|
||||
#include "services/rpz.h"
|
||||
#include "util/storage/slabhash.h"
|
||||
#include "util/fptr_wlist.h"
|
||||
@@ -115,9 +116,6 @@
|
||||
#ifdef HAVE_NETDB_H
|
||||
#include <netdb.h>
|
||||
#endif
|
||||
#ifdef HAVE_POLL_H
|
||||
#include <poll.h>
|
||||
#endif
|
||||
|
||||
/* just for portability */
|
||||
#ifdef SQ
|
||||
@@ -307,7 +305,7 @@ add_open(const char* ip, int nr, struct listen_port** list, int noproto_is_err,
|
||||
#endif
|
||||
}
|
||||
} else {
|
||||
char* s = strchr(ip, '@');
|
||||
const char* s = strchr(ip, '@');
|
||||
char newif[128];
|
||||
if(s) {
|
||||
/* override port with ifspec@port */
|
||||
@@ -1533,18 +1531,95 @@ do_datas_add(struct daemon_remote* rc, RES* ssl, struct worker* worker)
|
||||
(void)ssl_printf(ssl, "added %d datas\n", num);
|
||||
}
|
||||
|
||||
static int
|
||||
perform_data_remove_rr(RES* ssl, struct local_zones* local_zones,
|
||||
uint8_t* rr, size_t len, size_t dname_len, char *arg)
|
||||
{
|
||||
uint16_t rr_class, rr_type;
|
||||
int labs;
|
||||
struct local_zone* z;
|
||||
struct local_data* ld;
|
||||
uint8_t *rdata;
|
||||
size_t rdata_len, index;
|
||||
struct packed_rrset_data* d;
|
||||
struct local_rrset* p;
|
||||
|
||||
rdata = sldns_wirerr_get_rdatawl(rr, len, dname_len);
|
||||
rdata_len = ((size_t)sldns_wirerr_get_rdatalen(rr, len, dname_len))+2;
|
||||
|
||||
labs = dname_count_labels(rr);
|
||||
|
||||
rr_class = sldns_wirerr_get_class(rr, len, dname_len);
|
||||
rr_type = sldns_wirerr_get_type(rr, len, dname_len);
|
||||
|
||||
z = local_zones_lookup(local_zones, rr, dname_len,
|
||||
labs, rr_class, rr_type, 1);
|
||||
if (!z) {
|
||||
ssl_printf(ssl, "error no zone for rr %s\n", arg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ld = local_zone_find_data(z, rr, dname_len, labs);
|
||||
if (!ld) {
|
||||
ssl_printf(ssl, "error no local data for rr %s\n", arg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
p = ld->rrsets;
|
||||
while (p && ntohs(p->rrset->rk.type) != rr_type) {
|
||||
p = p->next;
|
||||
}
|
||||
|
||||
if (!p) {
|
||||
ssl_printf(ssl, "error no rrset for rr %s\n", arg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
d = (struct packed_rrset_data*)p->rrset->entry.data;
|
||||
if (!packed_rrset_find_rr(d, rdata, rdata_len, &index)) {
|
||||
ssl_printf(ssl, "error rr %s not found in rrset\n", arg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!local_rrset_remove_rr(d, index)) {
|
||||
ssl_printf(ssl, "error unable to delete rr %s\n", arg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** Remove RR data */
|
||||
static int
|
||||
perform_data_remove(RES* ssl, struct local_zones* zones, char* arg)
|
||||
{
|
||||
uint8_t* nm;
|
||||
int nmlabs;
|
||||
size_t nmlen;
|
||||
if(!parse_arg_name(ssl, arg, &nm, &nmlen, &nmlabs))
|
||||
uint8_t rr[LDNS_RR_BUF_SIZE], *nm;
|
||||
size_t len = sizeof(rr);
|
||||
int status, nmlabs;
|
||||
size_t nmlen, dname_len;
|
||||
|
||||
/* try to parse as a rr first */
|
||||
status = sldns_str2wire_rr_buf(arg, rr, &len, &dname_len, 3600,
|
||||
NULL, 0, NULL, 0);
|
||||
|
||||
/* try to parse as a domain name second */
|
||||
if (status != 0) {
|
||||
if (parse_arg_name(ssl, arg, &nm, &nmlen, &nmlabs)) {
|
||||
local_zones_del_data(zones, nm,
|
||||
nmlen, nmlabs, LDNS_RR_CLASS_IN);
|
||||
free(nm);
|
||||
return 1;
|
||||
}
|
||||
ssl_printf(ssl, "error cannot parse rr %s at %d: %s\n", arg,
|
||||
LDNS_WIREPARSE_OFFSET(status),
|
||||
sldns_get_errorstr_parse(status));
|
||||
return 0;
|
||||
local_zones_del_data(zones, nm,
|
||||
nmlen, nmlabs, LDNS_RR_CLASS_IN);
|
||||
free(nm);
|
||||
}
|
||||
|
||||
/* handle the rr case */
|
||||
if (!perform_data_remove_rr(ssl, zones, rr, len, dname_len, arg))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -2315,6 +2390,9 @@ zone_del_rrset(struct lruhash_entry* e, void* arg)
|
||||
(struct packed_rrset_data*)e->data;
|
||||
if(d->ttl > inf->expired) {
|
||||
d->ttl = inf->expired;
|
||||
if(d->ttl_add > inf->expired)
|
||||
d->ttl_add = inf->expired; /* for 0TTL rrsets,
|
||||
means that d->ttl_add <= d->ttl */
|
||||
inf->num_rrsets++;
|
||||
}
|
||||
}
|
||||
@@ -2601,7 +2679,7 @@ static int
|
||||
ssl_print_name_dp(RES* ssl, const char* str, uint8_t* nm, uint16_t dclass,
|
||||
struct delegpt* dp)
|
||||
{
|
||||
char buf[LDNS_MAX_DOMAINLEN];
|
||||
char buf[LDNS_MAX_DOMAINLEN], portstr[128], tls_auth_name[256];
|
||||
struct delegpt_ns* ns;
|
||||
struct delegpt_addr* a;
|
||||
int f = 0;
|
||||
@@ -2616,13 +2694,32 @@ ssl_print_name_dp(RES* ssl, const char* str, uint8_t* nm, uint16_t dclass,
|
||||
}
|
||||
for(ns = dp->nslist; ns; ns = ns->next) {
|
||||
dname_str(ns->name, buf);
|
||||
if(!ssl_printf(ssl, "%s%s", (f?" ":""), buf))
|
||||
if(ns->port != UNBOUND_DNS_PORT)
|
||||
snprintf(portstr, sizeof(portstr), "@%d", ns->port);
|
||||
else portstr[0]=0;
|
||||
if(ns->tls_auth_name)
|
||||
snprintf(tls_auth_name, sizeof(tls_auth_name), "#%s",
|
||||
ns->tls_auth_name);
|
||||
else tls_auth_name[0]=0;
|
||||
if(!ssl_printf(ssl, "%s%s%s%s", (f?" ":""), buf, portstr,
|
||||
tls_auth_name))
|
||||
return 0;
|
||||
f = 1;
|
||||
}
|
||||
for(a = dp->target_list; a; a = a->next_target) {
|
||||
int port = (unsigned)((a->addr.ss_family == AF_INET) ?
|
||||
ntohs(((struct sockaddr_in*)&a->addr)->sin_port) :
|
||||
ntohs(((struct sockaddr_in6*)&a->addr)->sin6_port));
|
||||
addr_to_str(&a->addr, a->addrlen, buf, sizeof(buf));
|
||||
if(!ssl_printf(ssl, "%s%s", (f?" ":""), buf))
|
||||
if(port != UNBOUND_DNS_PORT)
|
||||
snprintf(portstr, sizeof(portstr), "@%d", port);
|
||||
else portstr[0]=0;
|
||||
if(a->tls_auth_name)
|
||||
snprintf(tls_auth_name, sizeof(tls_auth_name), "#%s",
|
||||
a->tls_auth_name);
|
||||
else tls_auth_name[0]=0;
|
||||
if(!ssl_printf(ssl, "%s%s%s%s", (f?" ":""), buf, portstr,
|
||||
tls_auth_name))
|
||||
return 0;
|
||||
f = 1;
|
||||
}
|
||||
@@ -3238,6 +3335,10 @@ do_auth_zone_reload(RES* ssl, struct worker* worker, char* arg)
|
||||
return;
|
||||
}
|
||||
if(!auth_zone_read_zonefile(z, worker->env.cfg)) {
|
||||
/* The old tree was already cleared. Do not answer from the
|
||||
* failed load. */
|
||||
z->zone_expired = 1;
|
||||
auth_zone_clear_data(z);
|
||||
lock_rw_unlock(&z->lock);
|
||||
if(xfr) {
|
||||
lock_basic_unlock(&xfr->lock);
|
||||
@@ -3249,6 +3350,7 @@ do_auth_zone_reload(RES* ssl, struct worker* worker, char* arg)
|
||||
z->zone_expired = 0;
|
||||
if(xfr) {
|
||||
xfr->zone_expired = 0;
|
||||
xfr->num_ixfrs = 0;
|
||||
if(!xfr_find_soa(z, xfr)) {
|
||||
if(z->data.count == 0) {
|
||||
lock_rw_unlock(&z->lock);
|
||||
@@ -4362,92 +4464,6 @@ int remote_control_callback(struct comm_point* c, void* arg, int err,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* This routine polls a socket for readiness.
|
||||
* @param fd: file descriptor, -1 uses no fd for a timer only.
|
||||
* @param timeout: time in msec to wait. 0 means nonblocking test,
|
||||
* -1 waits blocking for events.
|
||||
* @param pollin: check for input event.
|
||||
* @param pollout: check for output event.
|
||||
* @param event: output variable, set to true if the event happens.
|
||||
* It is false if there was an error or timeout.
|
||||
* @return false is system call failure, also logged.
|
||||
*/
|
||||
static int
|
||||
sock_poll_timeout(int fd, int timeout, int pollin, int pollout, int* event)
|
||||
{
|
||||
int loopcount = 0;
|
||||
/* Loop if the system call returns an errno to do so, like EINTR. */
|
||||
log_assert(pollin || pollout);
|
||||
while(1) {
|
||||
struct pollfd p, *fds;
|
||||
int nfds, ret;
|
||||
if(++loopcount > IPC_LOOP_MAX) {
|
||||
log_err("sock_poll_timeout: loop");
|
||||
if(event)
|
||||
*event = 0;
|
||||
return 0;
|
||||
}
|
||||
if(fd == -1) {
|
||||
fds = NULL;
|
||||
nfds = 0;
|
||||
} else {
|
||||
fds = &p;
|
||||
nfds = 1;
|
||||
memset(&p, 0, sizeof(p));
|
||||
p.fd = fd;
|
||||
#ifndef USE_WINSOCK
|
||||
p.events = POLLERR
|
||||
| POLLHUP
|
||||
;
|
||||
#endif
|
||||
if(pollin)
|
||||
p.events |= POLLIN;
|
||||
if(pollout)
|
||||
p.events |= POLLOUT;
|
||||
}
|
||||
#ifndef USE_WINSOCK
|
||||
ret = poll(fds, nfds, timeout);
|
||||
#else
|
||||
if(fds == NULL) {
|
||||
Sleep(timeout);
|
||||
ret = 0;
|
||||
} else {
|
||||
ret = WSAPoll(fds, nfds, timeout);
|
||||
}
|
||||
#endif
|
||||
if(ret == -1) {
|
||||
#ifndef USE_WINSOCK
|
||||
if(
|
||||
errno == EINTR || errno == EAGAIN
|
||||
# ifdef EWOULDBLOCK
|
||||
|| errno == EWOULDBLOCK
|
||||
# endif
|
||||
) continue; /* Try again. */
|
||||
#endif
|
||||
/* For WSAPoll we only get errors here:
|
||||
* o WSAENETDOWN
|
||||
* o WSAEFAULT
|
||||
* o WSAEINVAL
|
||||
* o WSAENOBUFS
|
||||
*/
|
||||
log_err("poll: %s", sock_strerror(errno));
|
||||
if(event)
|
||||
*event = 0;
|
||||
return 0;
|
||||
} else if(ret == 0) {
|
||||
/* Timeout */
|
||||
if(event)
|
||||
*event = 0;
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if(event)
|
||||
*event = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** fast reload convert fast reload notification status to string */
|
||||
static const char*
|
||||
fr_notification_to_string(enum fast_reload_notification status)
|
||||
@@ -4941,6 +4957,74 @@ fr_check_changed_cfg_str2list(struct config_str2list* cmp1,
|
||||
}
|
||||
}
|
||||
|
||||
/** fast reload thread, check if config str3list has changed. */
|
||||
#define FR_CHECK_CHANGED_CFG_STR3LIST(desc, var, buff) do { \
|
||||
fr_check_changed_cfg_str3list(cfg->var, newcfg->var, desc, buff,\
|
||||
sizeof(buff)); \
|
||||
} while(0);
|
||||
static void
|
||||
fr_check_changed_cfg_str3list(struct config_str3list* cmp1,
|
||||
struct config_str3list* cmp2, const char* desc, char* str, size_t len)
|
||||
{
|
||||
struct config_str3list* p1 = cmp1, *p2 = cmp2;
|
||||
while(p1 && p2) {
|
||||
if((!p1->str && p2->str) ||
|
||||
(p1->str && !p2->str) ||
|
||||
(p1->str && p2->str && strcmp(p1->str, p2->str) != 0)) {
|
||||
/* The str3list is different. */
|
||||
fr_add_incompatible_option(desc, str, len);
|
||||
return;
|
||||
}
|
||||
if((!p1->str2 && p2->str2) ||
|
||||
(p1->str2 && !p2->str2) ||
|
||||
(p1->str2 && p2->str2 &&
|
||||
strcmp(p1->str2, p2->str2) != 0)) {
|
||||
/* The str3list is different. */
|
||||
fr_add_incompatible_option(desc, str, len);
|
||||
return;
|
||||
}
|
||||
if((!p1->str3 && p2->str3) ||
|
||||
(p1->str3 && !p2->str3) ||
|
||||
(p1->str3 && p2->str3 &&
|
||||
strcmp(p1->str3, p2->str3) != 0)) {
|
||||
/* The str3list is different. */
|
||||
fr_add_incompatible_option(desc, str, len);
|
||||
return;
|
||||
}
|
||||
p1 = p1->next;
|
||||
p2 = p2->next;
|
||||
}
|
||||
if((!p1 && p2) || (p1 && !p2)) {
|
||||
fr_add_incompatible_option(desc, str, len);
|
||||
}
|
||||
}
|
||||
|
||||
/** fast reload thread, check tag datas. */
|
||||
static int
|
||||
fr_check_tag_datas(struct fast_reload_thread* fr, struct config_file* newcfg)
|
||||
{
|
||||
char changed_str[1024];
|
||||
struct config_file* cfg = fr->worker->env.cfg;
|
||||
changed_str[0]=0;
|
||||
|
||||
/* Check for tag_datas in acl_addr. */
|
||||
FR_CHECK_CHANGED_CFG_STR3LIST("interface-tag-data", interface_tag_datas, changed_str);
|
||||
FR_CHECK_CHANGED_CFG_STR3LIST("access-control-tag-data", acl_tag_datas, changed_str);
|
||||
|
||||
if(changed_str[0] != 0) {
|
||||
if(fr->fr_drop_mesh)
|
||||
return 1; /* already dropping queries */
|
||||
fr->fr_drop_mesh = 1;
|
||||
fr->worker->daemon->fast_reload_drop_mesh = fr->fr_drop_mesh;
|
||||
if(!fr_output_printf(fr, "recursion referenced data has changed, with: '%s"
|
||||
"', and the queries have to be dropped"
|
||||
", setting '+d'\n", changed_str))
|
||||
return 0;
|
||||
fr_send_notification(fr, fast_reload_notification_printout);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** fast reload thread, check compatible config items */
|
||||
static int
|
||||
fr_check_compat_cfg(struct fast_reload_thread* fr, struct config_file* newcfg)
|
||||
@@ -5477,6 +5561,23 @@ xfr_masterlist_equal(struct auth_master* list1, struct auth_master* list2)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** See if configuration has changed. */
|
||||
static int
|
||||
xfr_config_equal(struct auth_xfer* xfr1, struct auth_xfer* xfr2)
|
||||
{
|
||||
if(xfr1 == NULL && xfr2 == NULL)
|
||||
return 1;
|
||||
if(xfr1 == NULL && xfr2 != NULL)
|
||||
return 0;
|
||||
if(xfr1 != NULL && xfr2 == NULL)
|
||||
return 0;
|
||||
if(xfr1->max_transfer_size != xfr2->max_transfer_size)
|
||||
return 0;
|
||||
if(xfr1->max_transfer_time != xfr2->max_transfer_time)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** See if the list of masters has changed. */
|
||||
static int
|
||||
xfr_masters_equal(struct auth_xfer* xfr1, struct auth_xfer* xfr2)
|
||||
@@ -5565,8 +5666,31 @@ auth_zones_check_changes(struct fast_reload_thread* fr,
|
||||
&old_serial)!=0);
|
||||
have_new = (auth_zone_get_serial(new_z,
|
||||
&new_serial)!=0);
|
||||
/* A change in primaries, also means it is different
|
||||
* and the change makes it fire new transfers, from
|
||||
* the new primaries. */
|
||||
/* Treat as changed when the old zone has an
|
||||
* outstanding ZONEMD DS/DNSKEY mesh callback.
|
||||
* This will make the worker pickup change code
|
||||
* remove the mesh callback, before the old zone is
|
||||
* deleted. Also it makes a new zonemd lookup.
|
||||
* The new lookup is needed, because the new zone
|
||||
* entry needs to have a valid zonemd result,
|
||||
* and if that is bad, needs to be invalidated.
|
||||
* Also if there is a race event where the
|
||||
* outstanding callback makes the zone invalid,
|
||||
* before fast-reload completes, the change makes
|
||||
* the new zone entry have a new zonemd lookup,
|
||||
* to then invalidate that new zone.
|
||||
* There is also a brief operational window at
|
||||
* program start when a zonemd has to be looked
|
||||
* up on-line, where the zone is operational.
|
||||
* And this copies that for such a race event.
|
||||
*/
|
||||
if(have_old != have_new || old_serial != new_serial
|
||||
|| !xfr_masters_equal(old_xfr, new_xfr)) {
|
||||
|| !xfr_masters_equal(old_xfr, new_xfr)
|
||||
|| !xfr_config_equal(old_xfr, new_xfr)
|
||||
|| old_z->zonemd_callback_env != NULL) {
|
||||
/* The zone has been changed. */
|
||||
if(!fr_add_auth_zone_change(fr, old_z, new_z,
|
||||
0, 0, 1)) {
|
||||
@@ -5639,6 +5763,8 @@ ct_create_sslctxs(struct fast_reload_construct* ct,
|
||||
/* Leave listen ctxs and file str at NULL */
|
||||
ct->connect_dot_sslctx = daemon_setup_connect_dot_sslctx(
|
||||
daemon, newcfg);
|
||||
if(!ct->connect_dot_sslctx)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -5648,20 +5774,28 @@ ct_create_sslctxs(struct fast_reload_construct* ct,
|
||||
pem += strlen(chroot);
|
||||
|
||||
ct->listen_dot_sslctx = daemon_setup_listen_dot_sslctx(daemon, newcfg);
|
||||
if(!ct->listen_dot_sslctx)
|
||||
return 0;
|
||||
#ifdef HAVE_NGHTTP2_NGHTTP2_H
|
||||
if(cfg_has_https(newcfg)) {
|
||||
ct->listen_doh_sslctx = daemon_setup_listen_doh_sslctx(
|
||||
daemon, newcfg);
|
||||
if(!ct->listen_doh_sslctx)
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
#ifdef HAVE_NGTCP2
|
||||
if(cfg_has_quic(newcfg)) {
|
||||
ct->listen_quic_sslctx = daemon_setup_listen_quic_sslctx(
|
||||
daemon, newcfg);
|
||||
if(!ct->listen_quic_sslctx)
|
||||
return 0;
|
||||
}
|
||||
#endif /* HAVE_NGTCP2 */
|
||||
ct->connect_dot_sslctx = daemon_setup_connect_dot_sslctx(daemon,
|
||||
newcfg);
|
||||
if(!ct->connect_dot_sslctx)
|
||||
return 0;
|
||||
|
||||
/* Store mtime and names */
|
||||
ct->ssl_service_key = strdup(newcfg->ssl_service_key);
|
||||
@@ -6143,6 +6277,7 @@ fr_atomic_copy_cfg(struct config_file* oldcfg, struct config_file* cfg,
|
||||
COPY_VAR_ptr(acls);
|
||||
COPY_VAR_int(donotquery_localhost);
|
||||
COPY_VAR_ptr(tcp_connection_limits);
|
||||
COPY_VAR_int(auth_task_threads);
|
||||
COPY_VAR_int(harden_short_bufsize);
|
||||
COPY_VAR_int(harden_large_queries);
|
||||
COPY_VAR_int(harden_glue);
|
||||
@@ -6151,6 +6286,7 @@ fr_atomic_copy_cfg(struct config_file* oldcfg, struct config_file* cfg,
|
||||
COPY_VAR_int(harden_referral_path);
|
||||
COPY_VAR_int(harden_algo_downgrade);
|
||||
COPY_VAR_int(harden_unknown_additional);
|
||||
COPY_VAR_int(harden_cname_follow);
|
||||
COPY_VAR_int(use_caps_bits_for_id);
|
||||
COPY_VAR_ptr(caps_whitelist);
|
||||
COPY_VAR_ptr(private_address);
|
||||
@@ -6387,6 +6523,8 @@ fr_atomic_copy_cfg(struct config_file* oldcfg, struct config_file* cfg,
|
||||
COPY_VAR_ptr(ipset_name_v6);
|
||||
#endif
|
||||
COPY_VAR_int(ede);
|
||||
COPY_VAR_int(val_validation_attempts);
|
||||
COPY_VAR_int(val_hash_attempts);
|
||||
COPY_VAR_int(iter_scrub_ns);
|
||||
COPY_VAR_int(iter_scrub_cname);
|
||||
COPY_VAR_int(iter_scrub_rrsig);
|
||||
@@ -6631,9 +6769,12 @@ fr_reload_config(struct fast_reload_thread* fr, struct config_file* newcfg,
|
||||
}
|
||||
#ifdef USE_DNSTAP
|
||||
if(env->cfg->dnstap) {
|
||||
if(!fr->fr_nopause)
|
||||
dt_apply_cfg(daemon->dtenv, env->cfg);
|
||||
else dt_apply_logcfg(daemon->dtenv, env->cfg);
|
||||
if(!fr->fr_nopause) {
|
||||
if(!dt_apply_cfg(daemon->dtenv, env->cfg))
|
||||
log_warn("fast_reload: dnstap identity/version metadata not updated due to allocation failure");
|
||||
} else {
|
||||
dt_apply_logcfg(daemon->dtenv, env->cfg);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
fr_adjust_cache(env, ct->oldcfg);
|
||||
@@ -6773,6 +6914,10 @@ fr_load_config(struct fast_reload_thread* fr, struct timeval* time_read,
|
||||
config_delete(newcfg);
|
||||
return 0;
|
||||
}
|
||||
if(!fr_check_tag_datas(fr, newcfg)) {
|
||||
config_delete(newcfg);
|
||||
return 0;
|
||||
}
|
||||
if(!fr_check_compat_cfg(fr, newcfg)) {
|
||||
config_delete(newcfg);
|
||||
return 0;
|
||||
@@ -6864,7 +7009,7 @@ static void* fast_reload_thread_main(void* arg)
|
||||
#endif
|
||||
log_thread_set(&fast_reload_thread->threadnum);
|
||||
|
||||
ub_thread_setname(fast_reload_thread->tid, name);
|
||||
ub_thread_setname(ub_thread_self(), name);
|
||||
(void)name; /* When setname is not defined, ignore the name variable. */
|
||||
|
||||
verbose(VERB_ALGO, "start fast reload thread");
|
||||
@@ -6924,286 +7069,6 @@ done_error:
|
||||
}
|
||||
#endif /* !THREADS_DISABLED */
|
||||
|
||||
/** create a socketpair for bidirectional communication, false on failure */
|
||||
static int
|
||||
create_socketpair(int* pair, struct ub_randstate* rand)
|
||||
{
|
||||
#ifndef USE_WINSOCK
|
||||
if(socketpair(AF_UNIX, SOCK_STREAM, 0, pair) == -1) {
|
||||
log_err("socketpair: %s", strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
(void)rand;
|
||||
#else
|
||||
struct sockaddr_in addr, baddr, accaddr, connaddr;
|
||||
socklen_t baddrlen, accaddrlen, connaddrlen;
|
||||
uint8_t localhost[] = {127, 0, 0, 1};
|
||||
uint8_t nonce[16], recvnonce[16];
|
||||
size_t i;
|
||||
int lst, pollin_event, bcount, loopcount;
|
||||
int connect_poll_timeout = 200; /* msec to wait for connection */
|
||||
ssize_t ret;
|
||||
pair[0] = -1;
|
||||
pair[1] = -1;
|
||||
for(i=0; i<sizeof(nonce); i++) {
|
||||
nonce[i] = ub_random_max(rand, 256);
|
||||
}
|
||||
lst = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if(lst == -1) {
|
||||
log_err("create_socketpair: socket: %s", sock_strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_port = 0;
|
||||
memcpy(&addr.sin_addr, localhost, 4);
|
||||
if(bind(lst, (struct sockaddr*)&addr, (socklen_t)sizeof(addr))
|
||||
== -1) {
|
||||
log_err("create socketpair: bind: %s", sock_strerror(errno));
|
||||
sock_close(lst);
|
||||
return 0;
|
||||
}
|
||||
if(listen(lst, 12) == -1) {
|
||||
log_err("create socketpair: listen: %s", sock_strerror(errno));
|
||||
sock_close(lst);
|
||||
return 0;
|
||||
}
|
||||
|
||||
pair[1] = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if(pair[1] == -1) {
|
||||
log_err("create socketpair: socket: %s", sock_strerror(errno));
|
||||
sock_close(lst);
|
||||
return 0;
|
||||
}
|
||||
baddrlen = (socklen_t)sizeof(baddr);
|
||||
if(getsockname(lst, (struct sockaddr*)&baddr, &baddrlen) == -1) {
|
||||
log_err("create socketpair: getsockname: %s",
|
||||
sock_strerror(errno));
|
||||
sock_close(lst);
|
||||
sock_close(pair[1]);
|
||||
pair[1] = -1;
|
||||
return 0;
|
||||
}
|
||||
if(baddrlen > (socklen_t)sizeof(baddr)) {
|
||||
log_err("create socketpair: getsockname returned addr too big");
|
||||
sock_close(lst);
|
||||
sock_close(pair[1]);
|
||||
pair[1] = -1;
|
||||
return 0;
|
||||
}
|
||||
/* the socket is blocking */
|
||||
if(connect(pair[1], (struct sockaddr*)&baddr, baddrlen) == -1) {
|
||||
log_err("create socketpair: connect: %s",
|
||||
sock_strerror(errno));
|
||||
sock_close(lst);
|
||||
sock_close(pair[1]);
|
||||
pair[1] = -1;
|
||||
return 0;
|
||||
}
|
||||
if(!sock_poll_timeout(lst, connect_poll_timeout, 1, 0, &pollin_event)) {
|
||||
log_err("create socketpair: poll for accept failed: %s",
|
||||
sock_strerror(errno));
|
||||
sock_close(lst);
|
||||
sock_close(pair[1]);
|
||||
pair[1] = -1;
|
||||
return 0;
|
||||
}
|
||||
if(!pollin_event) {
|
||||
log_err("create socketpair: poll timeout for accept");
|
||||
sock_close(lst);
|
||||
sock_close(pair[1]);
|
||||
pair[1] = -1;
|
||||
return 0;
|
||||
}
|
||||
accaddrlen = (socklen_t)sizeof(accaddr);
|
||||
pair[0] = accept(lst, (struct sockaddr*)&accaddr, &accaddrlen);
|
||||
if(pair[0] == -1) {
|
||||
log_err("create socketpair: accept: %s", sock_strerror(errno));
|
||||
sock_close(lst);
|
||||
sock_close(pair[1]);
|
||||
pair[1] = -1;
|
||||
return 0;
|
||||
}
|
||||
if(accaddrlen > (socklen_t)sizeof(accaddr)) {
|
||||
log_err("create socketpair: accept returned addr too big");
|
||||
sock_close(lst);
|
||||
sock_close(pair[0]);
|
||||
sock_close(pair[1]);
|
||||
pair[0] = -1;
|
||||
pair[1] = -1;
|
||||
return 0;
|
||||
}
|
||||
if(accaddr.sin_family != AF_INET ||
|
||||
memcmp(localhost, &accaddr.sin_addr, 4) != 0) {
|
||||
log_err("create socketpair: accept from wrong address");
|
||||
sock_close(lst);
|
||||
sock_close(pair[0]);
|
||||
sock_close(pair[1]);
|
||||
pair[0] = -1;
|
||||
pair[1] = -1;
|
||||
return 0;
|
||||
}
|
||||
connaddrlen = (socklen_t)sizeof(connaddr);
|
||||
if(getsockname(pair[1], (struct sockaddr*)&connaddr, &connaddrlen)
|
||||
== -1) {
|
||||
log_err("create socketpair: getsockname connectedaddr: %s",
|
||||
sock_strerror(errno));
|
||||
sock_close(lst);
|
||||
sock_close(pair[0]);
|
||||
sock_close(pair[1]);
|
||||
pair[0] = -1;
|
||||
pair[1] = -1;
|
||||
return 0;
|
||||
}
|
||||
if(connaddrlen > (socklen_t)sizeof(connaddr)) {
|
||||
log_err("create socketpair: getsockname connectedaddr returned addr too big");
|
||||
sock_close(lst);
|
||||
sock_close(pair[0]);
|
||||
sock_close(pair[1]);
|
||||
pair[0] = -1;
|
||||
pair[1] = -1;
|
||||
return 0;
|
||||
}
|
||||
if(connaddr.sin_family != AF_INET ||
|
||||
memcmp(localhost, &connaddr.sin_addr, 4) != 0) {
|
||||
log_err("create socketpair: getsockname connectedaddr returned wrong address");
|
||||
sock_close(lst);
|
||||
sock_close(pair[0]);
|
||||
sock_close(pair[1]);
|
||||
pair[0] = -1;
|
||||
pair[1] = -1;
|
||||
return 0;
|
||||
}
|
||||
if(accaddr.sin_port != connaddr.sin_port) {
|
||||
log_err("create socketpair: accept from wrong port");
|
||||
sock_close(lst);
|
||||
sock_close(pair[0]);
|
||||
sock_close(pair[1]);
|
||||
pair[0] = -1;
|
||||
pair[1] = -1;
|
||||
return 0;
|
||||
}
|
||||
sock_close(lst);
|
||||
|
||||
loopcount = 0;
|
||||
bcount = 0;
|
||||
while(1) {
|
||||
if(++loopcount > IPC_LOOP_MAX) {
|
||||
log_err("create socketpair: send failed due to loop");
|
||||
sock_close(pair[0]);
|
||||
sock_close(pair[1]);
|
||||
pair[0] = -1;
|
||||
pair[1] = -1;
|
||||
return 0;
|
||||
}
|
||||
ret = send(pair[1], (void*)(nonce+bcount),
|
||||
sizeof(nonce)-bcount, 0);
|
||||
if(ret == -1) {
|
||||
if(
|
||||
#ifndef USE_WINSOCK
|
||||
errno == EINTR || errno == EAGAIN
|
||||
# ifdef EWOULDBLOCK
|
||||
|| errno == EWOULDBLOCK
|
||||
# endif
|
||||
#else
|
||||
WSAGetLastError() == WSAEINTR ||
|
||||
WSAGetLastError() == WSAEINPROGRESS ||
|
||||
WSAGetLastError() == WSAEWOULDBLOCK
|
||||
#endif
|
||||
)
|
||||
continue; /* Try again. */
|
||||
log_err("create socketpair: send: %s", sock_strerror(errno));
|
||||
sock_close(pair[0]);
|
||||
sock_close(pair[1]);
|
||||
pair[0] = -1;
|
||||
pair[1] = -1;
|
||||
return 0;
|
||||
} else if(ret+(ssize_t)bcount != sizeof(nonce)) {
|
||||
bcount += ret;
|
||||
if((size_t)bcount < sizeof(nonce))
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if(!sock_poll_timeout(pair[0], connect_poll_timeout, 1, 0, &pollin_event)) {
|
||||
log_err("create socketpair: poll failed: %s",
|
||||
sock_strerror(errno));
|
||||
sock_close(pair[0]);
|
||||
sock_close(pair[1]);
|
||||
pair[0] = -1;
|
||||
pair[1] = -1;
|
||||
return 0;
|
||||
}
|
||||
if(!pollin_event) {
|
||||
log_err("create socketpair: poll timeout for recv");
|
||||
sock_close(pair[0]);
|
||||
sock_close(pair[1]);
|
||||
pair[0] = -1;
|
||||
pair[1] = -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
loopcount = 0;
|
||||
bcount = 0;
|
||||
while(1) {
|
||||
if(++loopcount > IPC_LOOP_MAX) {
|
||||
log_err("create socketpair: recv failed due to loop");
|
||||
sock_close(pair[0]);
|
||||
sock_close(pair[1]);
|
||||
pair[0] = -1;
|
||||
pair[1] = -1;
|
||||
return 0;
|
||||
}
|
||||
ret = recv(pair[0], (void*)(recvnonce+bcount),
|
||||
sizeof(nonce)-bcount, 0);
|
||||
if(ret == -1) {
|
||||
if(
|
||||
#ifndef USE_WINSOCK
|
||||
errno == EINTR || errno == EAGAIN
|
||||
# ifdef EWOULDBLOCK
|
||||
|| errno == EWOULDBLOCK
|
||||
# endif
|
||||
#else
|
||||
WSAGetLastError() == WSAEINTR ||
|
||||
WSAGetLastError() == WSAEINPROGRESS ||
|
||||
WSAGetLastError() == WSAEWOULDBLOCK
|
||||
#endif
|
||||
)
|
||||
continue; /* Try again. */
|
||||
log_err("create socketpair: recv: %s", sock_strerror(errno));
|
||||
sock_close(pair[0]);
|
||||
sock_close(pair[1]);
|
||||
pair[0] = -1;
|
||||
pair[1] = -1;
|
||||
return 0;
|
||||
} else if(ret == 0) {
|
||||
log_err("create socketpair: stream closed");
|
||||
sock_close(pair[0]);
|
||||
sock_close(pair[1]);
|
||||
pair[0] = -1;
|
||||
pair[1] = -1;
|
||||
return 0;
|
||||
} else if(ret+(ssize_t)bcount != sizeof(nonce)) {
|
||||
bcount += ret;
|
||||
if((size_t)bcount < sizeof(nonce))
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if(memcmp(nonce, recvnonce, sizeof(nonce)) != 0) {
|
||||
log_err("create socketpair: recv wrong nonce");
|
||||
sock_close(pair[0]);
|
||||
sock_close(pair[1]);
|
||||
pair[0] = -1;
|
||||
pair[1] = -1;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** fast reload thread. setup the thread info */
|
||||
static int
|
||||
fast_reload_thread_setup(struct worker* worker, int fr_verb, int fr_nopause,
|
||||
@@ -7580,6 +7445,13 @@ auth_zone_zonemd_stop_lookup(struct auth_zone* z, struct mesh_area* mesh)
|
||||
{
|
||||
struct query_info qinfo;
|
||||
uint16_t qflags = BIT_RD;
|
||||
if(z->zonemd_transfer_active) {
|
||||
auth_load_info_release_transfer_in_progress(
|
||||
z->zonemd_callback_env);
|
||||
auth_load_schedule_waiting_pickup(z->zonemd_callback_env);
|
||||
z->zonemd_transfer_active = 0;
|
||||
}
|
||||
|
||||
qinfo.qname_len = z->namelen;
|
||||
qinfo.qname = z->name;
|
||||
qinfo.qclass = z->dclass;
|
||||
@@ -7587,7 +7459,8 @@ auth_zone_zonemd_stop_lookup(struct auth_zone* z, struct mesh_area* mesh)
|
||||
qinfo.local_alias = NULL;
|
||||
|
||||
mesh_remove_callback(mesh, &qinfo, qflags,
|
||||
&auth_zonemd_dnskey_lookup_callback, z);
|
||||
&auth_zonemd_dnskey_lookup_callback, z,
|
||||
z->zonemd_callback_unique_info);
|
||||
}
|
||||
|
||||
/** Pick up the auth zone locks. */
|
||||
@@ -7660,6 +7533,8 @@ fr_worker_auth_del(struct worker* worker, struct fast_reload_auth_change* item,
|
||||
released = 1;
|
||||
xfr_disown_tasks(xfr, worker);
|
||||
}
|
||||
auth_load_del_zone_tasks(worker, xfr->name, xfr->namelen,
|
||||
xfr->dclass);
|
||||
lock_basic_unlock(&xfr->lock);
|
||||
}
|
||||
|
||||
@@ -7696,6 +7571,9 @@ auth_xfr_pickup_config(struct auth_xfer* loadxfr, struct auth_xfer* xfr)
|
||||
log_assert(loadxfr->namelabs == xfr->namelabs);
|
||||
log_assert(loadxfr->dclass == xfr->dclass);
|
||||
|
||||
xfr->max_transfer_size = loadxfr->max_transfer_size;
|
||||
xfr->max_transfer_time = loadxfr->max_transfer_time;
|
||||
|
||||
/* The lists can be swapped in, the other xfr struct will be deleted
|
||||
* afterwards. */
|
||||
probe_masters = xfr->task_probe->masters;
|
||||
@@ -7720,6 +7598,16 @@ fr_worker_auth_add(struct worker* worker, struct fast_reload_auth_change* item,
|
||||
/* The xfr item needs to be created. The auth zones lock
|
||||
* is held to make this possible. */
|
||||
xfr = auth_xfer_create(worker->env.auth_zones, item->new_z);
|
||||
if(!xfr) {
|
||||
log_err("out of memory in fr_worker_auth_add");
|
||||
lock_rw_unlock(&item->new_z->lock);
|
||||
lock_rw_unlock(&worker->env.auth_zones->lock);
|
||||
lock_rw_unlock(&worker->daemon->fast_reload_thread->old_auth_zones->lock);
|
||||
if(loadxfr) {
|
||||
lock_basic_unlock(&loadxfr->lock);
|
||||
}
|
||||
return;
|
||||
}
|
||||
auth_xfr_pickup_config(loadxfr, xfr);
|
||||
/* Serial information is copied into the xfr struct. */
|
||||
if(!xfr_find_soa(item->new_z, xfr)) {
|
||||
@@ -7789,6 +7677,17 @@ fr_worker_auth_cha(struct worker* worker, struct fast_reload_auth_change* item)
|
||||
} else if(loadxfr && !xfr) {
|
||||
/* Create the xfr. */
|
||||
xfr = auth_xfer_create(worker->env.auth_zones, item->new_z);
|
||||
if(!xfr) {
|
||||
log_err("out of memory in fr_worker_auth_cha");
|
||||
lock_rw_unlock(&item->new_z->lock);
|
||||
lock_rw_unlock(&item->old_z->lock);
|
||||
lock_rw_unlock(&worker->daemon->fast_reload_thread->old_auth_zones->lock);
|
||||
lock_rw_unlock(&worker->env.auth_zones->lock);
|
||||
if(loadxfr) {
|
||||
lock_basic_unlock(&loadxfr->lock);
|
||||
}
|
||||
return;
|
||||
}
|
||||
auth_xfr_pickup_config(loadxfr, xfr);
|
||||
item->new_z->zone_is_slave = 1;
|
||||
}
|
||||
|
||||
+1
-7
@@ -49,6 +49,7 @@
|
||||
#include <openssl/ssl.h>
|
||||
#endif
|
||||
#include "util/locks.h"
|
||||
#include "libunbound/remote.h"
|
||||
struct config_file;
|
||||
struct listen_list;
|
||||
struct listen_port;
|
||||
@@ -365,13 +366,6 @@ void fast_reload_thread_start(RES* ssl, struct worker* worker,
|
||||
*/
|
||||
void fast_reload_thread_stop(struct fast_reload_thread* fast_reload_thread);
|
||||
|
||||
/** fast reload thread commands to remote service thread event callback */
|
||||
void fast_reload_service_cb(int fd, short bits, void* arg);
|
||||
|
||||
/** fast reload callback for the remote control client connection */
|
||||
int fast_reload_client_callback(struct comm_point* c, void* arg, int err,
|
||||
struct comm_reply* rep);
|
||||
|
||||
/** fast reload printq delete list */
|
||||
void fast_reload_printq_list_delete(struct fast_reload_printq* list);
|
||||
|
||||
|
||||
+22
-6
@@ -422,12 +422,28 @@ void server_stats_obtain(struct worker* worker, struct worker* who,
|
||||
# endif
|
||||
#endif
|
||||
);
|
||||
log_err("server_stats_obtain: no response from worker %d "
|
||||
"(stats timeout); returning zero stats for this worker",
|
||||
who->thread_num);
|
||||
/* A later reply from the worker, would be sizeof stats reply,
|
||||
* and the worker_handle_control_cmd routine discards if
|
||||
* it is not a 4byte command, when that is received here. */
|
||||
memset(s, 0, sizeof(*s));
|
||||
return;
|
||||
}
|
||||
if(!tube_read_msg(worker->cmd, &reply, &len, 0)) {
|
||||
log_err("server_stats_obtain: failed to read stats from worker "
|
||||
"(tube read error); returning zero stats for this worker");
|
||||
memset(s, 0, sizeof(*s));
|
||||
return;
|
||||
}
|
||||
if(len != (uint32_t)sizeof(*s)) {
|
||||
log_err("server_stats_obtain: wrong stats length %d (expected %d); "
|
||||
"discarding", (int)len, (int)sizeof(*s));
|
||||
free(reply);
|
||||
memset(s, 0, sizeof(*s));
|
||||
return;
|
||||
}
|
||||
if(!tube_read_msg(worker->cmd, &reply, &len, 0))
|
||||
fatal_exit("failed to read stats over cmd channel");
|
||||
if(len != (uint32_t)sizeof(*s))
|
||||
fatal_exit("stats on cmd channel wrong length %d %d",
|
||||
(int)len, (int)sizeof(*s));
|
||||
memcpy(s, reply, (size_t)len);
|
||||
free(reply);
|
||||
}
|
||||
@@ -439,7 +455,7 @@ void server_stats_reply(struct worker* worker, int reset)
|
||||
verbose(VERB_ALGO, "write stats replymsg");
|
||||
if(!tube_write_msg(worker->daemon->workers[0]->cmd,
|
||||
(uint8_t*)&s, sizeof(s), 0))
|
||||
fatal_exit("could not write stat values over cmd channel");
|
||||
log_err("could not write stat values over cmd channel");
|
||||
}
|
||||
|
||||
void server_stats_add(struct ub_stats_info* total, struct ub_stats_info* a)
|
||||
|
||||
+33
-16
@@ -59,6 +59,7 @@
|
||||
#include "services/cache/infra.h"
|
||||
#include "services/cache/dns.h"
|
||||
#include "services/authzone.h"
|
||||
#include "services/authload.h"
|
||||
#include "services/mesh.h"
|
||||
#include "services/localzone.h"
|
||||
#include "services/rpz.h"
|
||||
@@ -95,8 +96,6 @@
|
||||
#include "winrc/win_svc.h"
|
||||
#endif
|
||||
|
||||
/** Size of an UDP datagram */
|
||||
#define NORMAL_UDP_SIZE 512 /* bytes */
|
||||
/** ratelimit for error responses */
|
||||
#define ERROR_RATELIMIT 100 /* qps */
|
||||
|
||||
@@ -501,7 +500,9 @@ worker_handle_control_cmd(struct tube* ATTR_UNUSED(tube), uint8_t* msg,
|
||||
return;
|
||||
}
|
||||
if(len != sizeof(uint32_t)) {
|
||||
fatal_exit("bad control msg length %d", (int)len);
|
||||
verbose(VERB_ALGO, "bad control msg length %d", (int)len);
|
||||
free(msg);
|
||||
return;
|
||||
}
|
||||
cmd = sldns_read_uint32(msg);
|
||||
free(msg);
|
||||
@@ -714,7 +715,8 @@ apply_respip_action(struct worker* worker, const struct query_info* qinfo,
|
||||
struct respip_client_info* cinfo, struct reply_info* rep,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen,
|
||||
struct ub_packed_rrset_key** alias_rrset,
|
||||
struct reply_info** encode_repp, struct auth_zones* az)
|
||||
struct reply_info** encode_repp, struct auth_zones* az,
|
||||
int* rpz_passthru)
|
||||
{
|
||||
struct respip_action_info actinfo = {0, 0, 0, 0, NULL, 0, NULL};
|
||||
actinfo.action = respip_none;
|
||||
@@ -725,7 +727,7 @@ apply_respip_action(struct worker* worker, const struct query_info* qinfo,
|
||||
return 1;
|
||||
|
||||
if(!respip_rewrite_reply(qinfo, cinfo, rep, encode_repp, &actinfo,
|
||||
alias_rrset, 0, worker->scratchpad, az, NULL,
|
||||
alias_rrset, 0, worker->scratchpad, az, rpz_passthru,
|
||||
worker->env.views, worker->env.respip_set))
|
||||
return 0;
|
||||
|
||||
@@ -772,7 +774,7 @@ answer_from_cache(struct worker* worker, struct query_info* qinfo,
|
||||
int* is_secure_answer, struct ub_packed_rrset_key** alias_rrset,
|
||||
struct reply_info** partial_repp,
|
||||
struct reply_info* rep, uint16_t id, uint16_t flags,
|
||||
struct comm_reply* repinfo, struct edns_data* edns)
|
||||
struct comm_reply* repinfo, struct edns_data* edns, int* rpz_passthru)
|
||||
{
|
||||
time_t timenow = *worker->env.now;
|
||||
uint16_t udpsize = edns->udp_size;
|
||||
@@ -860,7 +862,7 @@ answer_from_cache(struct worker* worker, struct query_info* qinfo,
|
||||
"validation");
|
||||
goto bail_out; /* need to validate cache entry first */
|
||||
} else if(rep->security == sec_status_secure) {
|
||||
if(reply_all_rrsets_secure(rep)) {
|
||||
if(reply_an_ns_rrsets_secure(rep)) {
|
||||
*is_secure_answer = 1;
|
||||
} else {
|
||||
if(must_validate) {
|
||||
@@ -882,7 +884,7 @@ answer_from_cache(struct worker* worker, struct query_info* qinfo,
|
||||
if((worker->daemon->use_response_ip || worker->daemon->use_rpz) &&
|
||||
!partial_rep && !apply_respip_action(worker, qinfo, cinfo, rep,
|
||||
&repinfo->client_addr, repinfo->client_addrlen, alias_rrset,
|
||||
&encode_rep, worker->env.auth_zones)) {
|
||||
&encode_rep, worker->env.auth_zones, rpz_passthru)) {
|
||||
goto bail_out;
|
||||
} else if(partial_rep &&
|
||||
!respip_merge_cname(partial_rep, qinfo, rep, cinfo,
|
||||
@@ -1494,6 +1496,8 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
|
||||
struct reply_info* partial_rep = NULL;
|
||||
struct query_info* lookup_qinfo = &qinfo;
|
||||
struct query_info qinfo_tmp; /* placeholder for lookup_qinfo */
|
||||
uint8_t* alias_orig_qname = NULL; /* original qname for logs, if
|
||||
a local_alias is used to change the qname. */
|
||||
struct respip_client_info* cinfo = NULL, cinfo_tmp;
|
||||
struct timeval wait_time;
|
||||
struct check_request_result check_result = {0,0};
|
||||
@@ -1511,7 +1515,7 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
|
||||
if (worker->stats.max_query_time_us < wait_queue_time)
|
||||
worker->stats.max_query_time_us = wait_queue_time;
|
||||
if(wait_queue_time >
|
||||
(long long)(worker->env.cfg->sock_queue_timeout * 1000000)) {
|
||||
(long long)worker->env.cfg->sock_queue_timeout * 1000000) {
|
||||
/* count and drop queries that were sitting in the socket queue too long */
|
||||
worker->stats.num_queries_timed_out++;
|
||||
return 0;
|
||||
@@ -1701,6 +1705,8 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
|
||||
}
|
||||
memset(&reply_edns, 0, sizeof(reply_edns));
|
||||
reply_edns.edns_present = 1;
|
||||
reply_edns.edns_version = EDNS_ADVERTISED_VERSION;
|
||||
reply_edns.udp_size = EDNS_ADVERTISED_SIZE;
|
||||
error_encode(c->buffer, ret, &qinfo,
|
||||
*(uint16_t*)(void *)sldns_buffer_begin(c->buffer),
|
||||
sldns_buffer_read_u16_at(c->buffer, 2), &reply_edns);
|
||||
@@ -1936,6 +1942,11 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
|
||||
/* If we've found a local alias, replace the qname with the alias
|
||||
* target before resolving it. */
|
||||
if(qinfo.local_alias) {
|
||||
if(qinfo.local_alias->rrset &&
|
||||
qinfo.local_alias->rrset->rk.dname)
|
||||
/* Store the original qname, used for logs, since
|
||||
* local_alias can be removed by region_free_all. */
|
||||
alias_orig_qname = qinfo.local_alias->rrset->rk.dname;
|
||||
if(!local_alias_shallow_copy_qname(qinfo.local_alias, &qinfo.qname,
|
||||
&qinfo.qname_len)) {
|
||||
regional_free_all(worker->scratchpad);
|
||||
@@ -1983,7 +1994,7 @@ lookup_cache:
|
||||
&alias_rrset, &partial_rep, rep,
|
||||
*(uint16_t*)(void *)sldns_buffer_begin(c->buffer),
|
||||
sldns_buffer_read_u16_at(c->buffer, 2), repinfo,
|
||||
&edns)) {
|
||||
&edns, &rpz_passthru)) {
|
||||
/* prefetch it if the prefetch TTL expired.
|
||||
* Note that if there is more than one pass
|
||||
* its qname must be that used for cache
|
||||
@@ -2101,11 +2112,10 @@ send_reply_rc:
|
||||
{
|
||||
struct timeval tv;
|
||||
memset(&tv, 0, sizeof(tv));
|
||||
if(qinfo.local_alias && qinfo.local_alias->rrset &&
|
||||
qinfo.local_alias->rrset->rk.dname) {
|
||||
if(alias_orig_qname) {
|
||||
/* log original qname, before the local alias was
|
||||
* used to resolve that CNAME to something else */
|
||||
qinfo.qname = qinfo.local_alias->rrset->rk.dname;
|
||||
qinfo.qname = alias_orig_qname;
|
||||
log_reply_info(NO_VERBOSE, &qinfo,
|
||||
&repinfo->client_addr, repinfo->client_addrlen,
|
||||
tv, 1, c->buffer,
|
||||
@@ -2253,6 +2263,7 @@ worker_create(struct daemon* daemon, int id)
|
||||
free(worker);
|
||||
return NULL;
|
||||
}
|
||||
rbtree_init(&worker->auth_load_tree, auth_load_tree_cmp);
|
||||
explicit_bzero(&seed, sizeof(seed));
|
||||
return worker;
|
||||
}
|
||||
@@ -2374,6 +2385,8 @@ worker_init(struct worker* worker, struct config_file *cfg,
|
||||
worker_stat_timer_cb, worker);
|
||||
if(!worker->stat_timer) {
|
||||
log_err("could not create statistics timer");
|
||||
worker_delete(worker);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* we use the msg_buffer_size as a good estimate for what the
|
||||
@@ -2526,6 +2539,8 @@ worker_delete(struct worker* worker)
|
||||
/* don't touch worker->alloc, as it's maintained in daemon */
|
||||
regional_destroy(worker->env.scratch);
|
||||
regional_destroy(worker->scratchpad);
|
||||
/* The thread id can reference this worker's id value, so clear it. */
|
||||
log_thread_set(NULL);
|
||||
free(worker);
|
||||
}
|
||||
|
||||
@@ -2534,7 +2549,8 @@ worker_send_query(struct query_info* qinfo, uint16_t flags, int dnssec,
|
||||
int want_dnssec, int nocaps, int check_ratelimit,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* zone,
|
||||
size_t zonelen, int tcp_upstream, int ssl_upstream, char* tls_auth_name,
|
||||
struct module_qstate* q, int* was_ratelimited)
|
||||
struct module_qstate* q, int* was_ratelimited,
|
||||
int* ratelimit_incremented)
|
||||
{
|
||||
struct worker* worker = q->env->worker;
|
||||
struct outbound_entry* e = (struct outbound_entry*)regional_alloc(
|
||||
@@ -2546,7 +2562,7 @@ worker_send_query(struct query_info* qinfo, uint16_t flags, int dnssec,
|
||||
want_dnssec, nocaps, check_ratelimit, tcp_upstream,
|
||||
ssl_upstream, tls_auth_name, addr, addrlen, zone, zonelen, q,
|
||||
worker_handle_service_reply, e, worker->back->udp_buff, q->env,
|
||||
was_ratelimited);
|
||||
was_ratelimited, ratelimit_incremented);
|
||||
if(!e->qsent) {
|
||||
return NULL;
|
||||
}
|
||||
@@ -2595,7 +2611,8 @@ struct outbound_entry* libworker_send_query(
|
||||
struct sockaddr_storage* ATTR_UNUSED(addr), socklen_t ATTR_UNUSED(addrlen),
|
||||
uint8_t* ATTR_UNUSED(zone), size_t ATTR_UNUSED(zonelen), int ATTR_UNUSED(tcp_upstream),
|
||||
int ATTR_UNUSED(ssl_upstream), char* ATTR_UNUSED(tls_auth_name),
|
||||
struct module_qstate* ATTR_UNUSED(q), int* ATTR_UNUSED(was_ratelimited))
|
||||
struct module_qstate* ATTR_UNUSED(q), int* ATTR_UNUSED(was_ratelimited),
|
||||
int* ATTR_UNUSED(ratelimit_incremented))
|
||||
{
|
||||
log_assert(0);
|
||||
return 0;
|
||||
|
||||
@@ -47,6 +47,7 @@
|
||||
#include "util/netevent.h"
|
||||
#include "util/locks.h"
|
||||
#include "util/alloc.h"
|
||||
#include "util/rbtree.h"
|
||||
#include "util/data/msgreply.h"
|
||||
#include "util/data/msgparse.h"
|
||||
#include "daemon/stats.h"
|
||||
@@ -135,6 +136,8 @@ struct worker {
|
||||
#endif
|
||||
/** reuse existing cache on reload if other conditions allow it. */
|
||||
int reuse_cache;
|
||||
/** tree of auth load threads, attached to this worker. */
|
||||
rbtree_type auth_load_tree;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
+60
-8
@@ -643,6 +643,12 @@ handle_event_moddone(struct module_qstate* qstate, int id)
|
||||
qstate->return_msg->rep &&
|
||||
reply_find_answer_rrset(&qstate->qinfo, qstate->return_msg->rep);
|
||||
int synth_qname = 0;
|
||||
if(could_synth && !has_data && qstate->env->need_to_validate &&
|
||||
qstate->return_msg && qstate->return_msg->rep &&
|
||||
qstate->return_msg->rep->security == sec_status_bogus) {
|
||||
verbose(VERB_ALGO, "dns64: bogus AAAA reply not synthesized");
|
||||
could_synth = 0;
|
||||
}
|
||||
|
||||
if(could_synth &&
|
||||
(!has_data ||
|
||||
@@ -654,8 +660,11 @@ handle_event_moddone(struct module_qstate* qstate, int id)
|
||||
|
||||
/* Store the response in cache. */
|
||||
if( (!iq || !iq->started_no_cache_store) &&
|
||||
!qstate->rpz_applied && !qstate->rpz_passthru &&
|
||||
!qstate->is_subnet_answer &&
|
||||
qstate->return_msg &&
|
||||
qstate->return_msg->rep &&
|
||||
!qstate->fwd_stub_no_cache &&
|
||||
!dns_cache_store(
|
||||
qstate->env, &qstate->qinfo, qstate->return_msg->rep,
|
||||
0, qstate->prefetch_leeway, 0, NULL,
|
||||
@@ -717,8 +726,15 @@ dns64_operate(struct module_qstate* qstate, enum module_ev event, int id,
|
||||
}
|
||||
if(qstate->ext_state[id] == module_finished) {
|
||||
iq = (struct dns64_qstate*)qstate->minfo[id];
|
||||
if(iq && iq->state != DNS64_INTERNAL_QUERY)
|
||||
qstate->no_cache_store = iq->started_no_cache_store;
|
||||
if(iq && iq->state != DNS64_INTERNAL_QUERY) {
|
||||
if(qstate->fwd_stub_no_cache) {
|
||||
/* If the forward/stub has no cache, then
|
||||
* continue with the query with no cache. */
|
||||
qstate->no_cache_store = qstate->fwd_stub_no_cache;
|
||||
} else {
|
||||
qstate->no_cache_store = iq->started_no_cache_store;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -825,6 +841,7 @@ dns64_adjust_a(int id, struct module_qstate* super, struct module_qstate* qstate
|
||||
size_t i, s;
|
||||
struct packed_rrset_data* fd, *dd;
|
||||
struct ub_packed_rrset_key* fk, *dk;
|
||||
int allocated_return_msg = 0;
|
||||
|
||||
verbose(VERB_ALGO, "converting A answers to AAAA answers");
|
||||
|
||||
@@ -840,6 +857,7 @@ dns64_adjust_a(int id, struct module_qstate* super, struct module_qstate* qstate
|
||||
return;
|
||||
memset(super->return_msg, 0, sizeof(*super->return_msg));
|
||||
super->return_msg->qinfo = super->qinfo;
|
||||
allocated_return_msg = 1;
|
||||
}
|
||||
|
||||
rep = qstate->return_msg->rep;
|
||||
@@ -852,11 +870,14 @@ dns64_adjust_a(int id, struct module_qstate* super, struct module_qstate* qstate
|
||||
rep->serve_expired_norec_ttl,
|
||||
rep->an_numrrsets, rep->ns_numrrsets, rep->ar_numrrsets,
|
||||
rep->rrset_count, rep->security, LDNS_EDE_NONE);
|
||||
if(!cp)
|
||||
if(!cp) {
|
||||
if(allocated_return_msg) super->return_msg = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
/* allocate ub_key structures special or not */
|
||||
if(!reply_info_alloc_rrset_keys(cp, NULL, super->region)) {
|
||||
if(allocated_return_msg) super->return_msg = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -871,8 +892,10 @@ dns64_adjust_a(int id, struct module_qstate* super, struct module_qstate* qstate
|
||||
if(i<rep->an_numrrsets && fk->rk.type == htons(LDNS_RR_TYPE_A)) {
|
||||
/* also sets dk->entry.hash */
|
||||
dns64_synth_aaaa_data(fk, fd, dk, &dd, super->region, dns64_env);
|
||||
if(!dd)
|
||||
if(!dd) {
|
||||
if(allocated_return_msg) super->return_msg = NULL;
|
||||
return;
|
||||
}
|
||||
/* Delete negative AAAA record from cache stored by
|
||||
* the iterator module */
|
||||
rrset_cache_remove(super->env->rrset_cache, dk->rk.dname,
|
||||
@@ -889,15 +912,19 @@ dns64_adjust_a(int id, struct module_qstate* super, struct module_qstate* qstate
|
||||
dk->rk.dname = (uint8_t*)regional_alloc_init(super->region,
|
||||
fk->rk.dname, fk->rk.dname_len);
|
||||
|
||||
if(!dk->rk.dname)
|
||||
if(!dk->rk.dname) {
|
||||
if(allocated_return_msg) super->return_msg = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
s = packed_rrset_sizeof(fd);
|
||||
dd = (struct packed_rrset_data*)regional_alloc_init(
|
||||
super->region, fd, s);
|
||||
|
||||
if(!dd)
|
||||
if(!dd) {
|
||||
if(allocated_return_msg) super->return_msg = NULL;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
packed_rrset_ptr_fixup(dd);
|
||||
@@ -928,8 +955,10 @@ dns64_adjust_ptr(struct module_qstate* qstate, struct module_qstate* super)
|
||||
return;
|
||||
super->return_msg->qinfo = super->qinfo;
|
||||
if (!(super->return_msg->rep = reply_info_copy(qstate->return_msg->rep,
|
||||
NULL, super->region)))
|
||||
NULL, super->region))) {
|
||||
super->return_msg = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Adjust the domain name of the answer RR set so that it matches the
|
||||
@@ -939,6 +968,7 @@ dns64_adjust_ptr(struct module_qstate* qstate, struct module_qstate* super)
|
||||
if(answer) {
|
||||
answer->rk.dname = super->qinfo.qname;
|
||||
answer->rk.dname_len = super->qinfo.qname_len;
|
||||
answer->entry.hash = rrset_key_hash(&answer->rk);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -998,6 +1028,21 @@ dns64_inform_super(struct module_qstate* qstate, int id,
|
||||
/* Use return code from A query in response to client. */
|
||||
if (super->return_rcode != LDNS_RCODE_NOERROR)
|
||||
super->return_rcode = qstate->return_rcode;
|
||||
/* RPZ applied to the subquery need to then change (not cache)
|
||||
* the super query. With the super query not cached, it is
|
||||
* going to run the state machine modules on incoming queries,
|
||||
* that fetch the subquery (cache) response, and modify it
|
||||
* according to the rpz policy. That makes the synthesized
|
||||
* super query also adjusted by rpz policies. But loses cache
|
||||
* hits. Even though the subquery likely is answered from cache,
|
||||
* internally in its state machine process. */
|
||||
if(qstate->rpz_applied)
|
||||
super->rpz_applied = 1;
|
||||
if(qstate->rpz_passthru)
|
||||
super->rpz_passthru = 1;
|
||||
|
||||
/* Since the super qstate has a new response, its errinf is removed. */
|
||||
super->errinf = NULL;
|
||||
|
||||
/* Generate a response suitable for the original query. */
|
||||
if (qstate->qinfo.qtype == LDNS_RR_TYPE_A) {
|
||||
@@ -1006,9 +1051,16 @@ dns64_inform_super(struct module_qstate* qstate, int id,
|
||||
log_assert(qstate->qinfo.qtype == LDNS_RR_TYPE_PTR);
|
||||
dns64_adjust_ptr(qstate, super);
|
||||
}
|
||||
/* If the sub-query has no cache store, then also the super query. */
|
||||
if(qstate->fwd_stub_no_cache)
|
||||
super->fwd_stub_no_cache = 1;
|
||||
|
||||
/* Store the generated response in cache. */
|
||||
if ( (!super_dq || !super_dq->started_no_cache_store) &&
|
||||
if ( super->return_msg && super->return_msg->rep &&
|
||||
(!super_dq || !super_dq->started_no_cache_store) &&
|
||||
!qstate->fwd_stub_no_cache &&
|
||||
!super->rpz_applied && !super->rpz_passthru &&
|
||||
!super->is_subnet_answer &&
|
||||
!dns_cache_store(super->env, &super->qinfo, super->return_msg->rep,
|
||||
0, super->prefetch_leeway, 0, NULL, super->query_flags,
|
||||
qstate->qstarttime, qstate->is_valrec))
|
||||
|
||||
+8
-1
@@ -842,7 +842,14 @@ dnsc_parse_keys(struct dnsc_env *env, struct config_file *cfg)
|
||||
if(memcmp(current_keypair->crypt_publickey,
|
||||
env->signed_certs[c].server_publickey,
|
||||
crypto_box_PUBLICKEYBYTES) == 0) {
|
||||
dnsccert *current_cert = &env->certs[cert_id++];
|
||||
dnsccert* current_cert;
|
||||
if(cert_id >= env->signed_certs_count) {
|
||||
log_err("dnscrypt: secret key %s matches a cert that "
|
||||
"is already bound to another key (duplicate "
|
||||
"dnscrypt-secret-key?)", head->str);
|
||||
return -1;
|
||||
}
|
||||
current_cert = &env->certs[cert_id++];
|
||||
found_cert = 1;
|
||||
current_cert->keypair = current_keypair;
|
||||
memcpy(current_cert->magic_query,
|
||||
|
||||
+36
-17
@@ -176,26 +176,29 @@ dt_create(struct config_file* cfg)
|
||||
env->dtio = dt_io_thread_create();
|
||||
if(!env->dtio) {
|
||||
log_err("malloc failure");
|
||||
free(env);
|
||||
dt_delete(env);
|
||||
return NULL;
|
||||
}
|
||||
if(!dt_io_thread_apply_cfg(env->dtio, cfg)) {
|
||||
dt_io_thread_delete(env->dtio);
|
||||
free(env);
|
||||
dt_delete(env);
|
||||
return NULL;
|
||||
}
|
||||
if(!dt_apply_cfg(env, cfg)) {
|
||||
dt_delete(env);
|
||||
return NULL;
|
||||
}
|
||||
dt_apply_cfg(env, cfg);
|
||||
return env;
|
||||
}
|
||||
|
||||
static void
|
||||
static int
|
||||
dt_apply_identity(struct dt_env *env, struct config_file *cfg)
|
||||
{
|
||||
char buf[MAXHOSTNAMELEN+1];
|
||||
if (!cfg->dnstap_send_identity) {
|
||||
free(env->identity);
|
||||
env->identity = NULL;
|
||||
return;
|
||||
env->len_identity = 0;
|
||||
return 1;
|
||||
}
|
||||
free(env->identity);
|
||||
if (cfg->dnstap_identity == NULL || cfg->dnstap_identity[0] == 0) {
|
||||
@@ -203,36 +206,49 @@ dt_apply_identity(struct dt_env *env, struct config_file *cfg)
|
||||
buf[MAXHOSTNAMELEN] = 0;
|
||||
env->identity = strdup(buf);
|
||||
} else {
|
||||
fatal_exit("dt_apply_identity: gethostname() failed");
|
||||
log_err("dt_apply_identity: gethostname() failed: %s",
|
||||
strerror(errno));
|
||||
env->identity = NULL;
|
||||
env->len_identity = 0;
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
env->identity = strdup(cfg->dnstap_identity);
|
||||
}
|
||||
if (env->identity == NULL)
|
||||
fatal_exit("dt_apply_identity: strdup() failed");
|
||||
if (env->identity == NULL) {
|
||||
log_err("dt_apply_identity: strdup() failed");
|
||||
env->len_identity = 0;
|
||||
return 0;
|
||||
}
|
||||
env->len_identity = (unsigned int)strlen(env->identity);
|
||||
verbose(VERB_OPS, "dnstap identity field set to \"%s\"",
|
||||
env->identity);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void
|
||||
static int
|
||||
dt_apply_version(struct dt_env *env, struct config_file *cfg)
|
||||
{
|
||||
if (!cfg->dnstap_send_version) {
|
||||
free(env->version);
|
||||
env->version = NULL;
|
||||
return;
|
||||
env->len_version = 0;
|
||||
return 1;
|
||||
}
|
||||
free(env->version);
|
||||
if (cfg->dnstap_version == NULL || cfg->dnstap_version[0] == 0)
|
||||
env->version = strdup(PACKAGE_STRING);
|
||||
else
|
||||
env->version = strdup(cfg->dnstap_version);
|
||||
if (env->version == NULL)
|
||||
fatal_exit("dt_apply_version: strdup() failed");
|
||||
if (env->version == NULL) {
|
||||
log_err("dt_apply_version: strdup() failed");
|
||||
env->len_version = 0;
|
||||
return 0;
|
||||
}
|
||||
env->len_version = (unsigned int)strlen(env->version);
|
||||
verbose(VERB_OPS, "dnstap version field set to \"%s\"",
|
||||
env->version);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
@@ -276,15 +292,18 @@ dt_apply_logcfg(struct dt_env *env, struct config_file *cfg)
|
||||
lock_basic_unlock(&env->sample_lock);
|
||||
}
|
||||
|
||||
void
|
||||
int
|
||||
dt_apply_cfg(struct dt_env *env, struct config_file *cfg)
|
||||
{
|
||||
if (!cfg->dnstap)
|
||||
return;
|
||||
return 1;
|
||||
|
||||
dt_apply_identity(env, cfg);
|
||||
dt_apply_version(env, cfg);
|
||||
dt_apply_logcfg(env, cfg);
|
||||
if(!dt_apply_identity(env, cfg))
|
||||
return 0;
|
||||
if(!dt_apply_version(env, cfg))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
|
||||
+2
-2
@@ -102,9 +102,9 @@ dt_create(struct config_file* cfg);
|
||||
* Apply config settings.
|
||||
* @param env: dnstap environment object.
|
||||
* @param cfg: new config settings.
|
||||
* @return false on failure.
|
||||
*/
|
||||
void
|
||||
dt_apply_cfg(struct dt_env *env, struct config_file *cfg);
|
||||
int dt_apply_cfg(struct dt_env *env, struct config_file *cfg);
|
||||
|
||||
/**
|
||||
* Apply config settings for log enable for message types.
|
||||
|
||||
+1
-1
@@ -2144,7 +2144,7 @@ static void* dnstap_io(void* arg)
|
||||
#endif
|
||||
log_thread_set(&dtio->threadnum);
|
||||
|
||||
ub_thread_setname(dtio->tid, name);
|
||||
ub_thread_setname(ub_thread_self(), name);
|
||||
|
||||
/* setup */
|
||||
verbose(VERB_ALGO, "start dnstap io thread");
|
||||
|
||||
@@ -1659,7 +1659,8 @@ struct outbound_entry* worker_send_query(
|
||||
socklen_t ATTR_UNUSED(addrlen), uint8_t* ATTR_UNUSED(zone),
|
||||
size_t ATTR_UNUSED(zonelen), int ATTR_UNUSED(tcp_upstream),
|
||||
int ATTR_UNUSED(ssl_upstream), char* ATTR_UNUSED(tls_auth_name),
|
||||
struct module_qstate* ATTR_UNUSED(q), int* ATTR_UNUSED(was_ratelimited))
|
||||
struct module_qstate* ATTR_UNUSED(q), int* ATTR_UNUSED(was_ratelimited),
|
||||
int* ATTR_UNUSED(ratelimit_incremented))
|
||||
{
|
||||
log_assert(0);
|
||||
return 0;
|
||||
@@ -1693,7 +1694,8 @@ struct outbound_entry* libworker_send_query(
|
||||
socklen_t ATTR_UNUSED(addrlen), uint8_t* ATTR_UNUSED(zone),
|
||||
size_t ATTR_UNUSED(zonelen), int ATTR_UNUSED(tcp_upstream),
|
||||
int ATTR_UNUSED(ssl_upstream), char* ATTR_UNUSED(tls_auth_name),
|
||||
struct module_qstate* ATTR_UNUSED(q), int* ATTR_UNUSED(was_ratelimited))
|
||||
struct module_qstate* ATTR_UNUSED(q), int* ATTR_UNUSED(was_ratelimited),
|
||||
int* ATTR_UNUSED(ratelimit_incremented))
|
||||
{
|
||||
log_assert(0);
|
||||
return 0;
|
||||
|
||||
+763
@@ -1,3 +1,693 @@
|
||||
13 October 2026: Wouter
|
||||
- Fix dns64 synthesis and cache with subnet module enabled.
|
||||
The subnet module stopped a cache store, that caused later
|
||||
dns64 replies to have a nodata answer for the AAAA.
|
||||
|
||||
13 October 2026: Yorgos
|
||||
- Fix #1526: Root Server h.root-servers.net has been included for Zone
|
||||
Transfer Service by including it in the example configuration.
|
||||
|
||||
2 October 2026: Yorgos
|
||||
- Document libunbound's context lifetime during an async callback.
|
||||
Thanks to Omar Mousa for the suggestion.
|
||||
|
||||
28 September 2026: Wouter
|
||||
- Fix to log the errno for trust anchor write close fail.
|
||||
- Merge #1518 from nshopik: rrset: rehash copies after
|
||||
changing the key.
|
||||
- Fix to allow for large (64Kb) packets with testbound.
|
||||
|
||||
22 September 2026: Yorgos
|
||||
- Fix #1514: [FR] do-not-query-localhost is not including
|
||||
0.0.0.0/8 and ‘::’ in the man page.
|
||||
- Fix #1513: [FR] Size of harden-large-queries in the man page.
|
||||
- Move NORMAL_UDP_SIZE around.
|
||||
- Clarify man page text for harden-short-bufsize.
|
||||
- Update generated man pages.
|
||||
|
||||
21 September 2026: Yorgos
|
||||
- Merge #1510 from Andy Warner: Move unlink of temp file to before
|
||||
fatal exit.
|
||||
|
||||
16 September 2026: Wouter
|
||||
- Release of 1.26.1 with the following security fixes.
|
||||
- Fix CVE-2026-81642, Heap buffer overflow and possible Remote Code
|
||||
Execution when digesting DNSKEY. Thanks to Yuqi Qiu and Xiang Li
|
||||
from Nankai University, AOSP Lab for the report.
|
||||
- Fix CVE-2026-81634, Possible heap buffer overflow during DNSSEC
|
||||
canonicalization. Thanks to Vlatko Kosturjak with Marlink Cyber,
|
||||
for the report.
|
||||
- Fix CVE-2026-82717, CNAME synthesis could lead to heap corruption.
|
||||
Thanks to Ben Morris from Anthropic for the report.
|
||||
- Fix CVE-2026-77955, Possible ZONEMD verification bypass window.
|
||||
Thanks to Yuqi Qiu and Xiang Li from Nankai University, AOSP Lab,
|
||||
for the report. In addition, thanks to Qifan Zhang from Palo Alto
|
||||
Networks for also reporting this issue.
|
||||
- Fix CVE-2026-78227, Use-after-free in DoQ stream output buffer on
|
||||
reset re-transmission. Thanks to Yuqi Qiu and Xiang Li from Nankai
|
||||
University, AOSP Lab for the report.
|
||||
- Fix CVE-2026-80225, Possible degradation of service from continuous
|
||||
queries on the same TCP/DoT connection. Thanks to Qifan Zhang from
|
||||
Palo Alto Networks for the report.
|
||||
- Fix CVE-2026-82720, Use-after-free in DoH stream cleanup code path.
|
||||
Thanks to Yuqi Qiu and Xiang Li from Nankai University, AOSP Lab,
|
||||
for the report.
|
||||
- Fix CVE-2026-85501, Retrap: Novel Vulnerabilities to launch
|
||||
Algorithmic Complexity Attacks on DNSSEC. Thanks to Zuyao Xu and
|
||||
Xiang Li from Nankai University, AOSP Lab for the report. In
|
||||
addition, thanks to Qifan Zhang from Palo Alto Networks for a
|
||||
complimentary report.
|
||||
- Fix CVE-2026-77860, 'serve-expired' can bypass Unbound 'wait-limit'.
|
||||
Thanks to Xuanchao Xie, Lutong Chen, and Kaiping Xue from the
|
||||
University of Science and Technology of China (USTC) for the
|
||||
report.
|
||||
- The code repository continues with 1.26.2 under development,
|
||||
that includes the changes from before the 1.26.1 commits.
|
||||
- Unit test for CVE-2026-81642.
|
||||
- Unit test for CVE-2026-82717.
|
||||
- Unit test for CVE-2026-85501.
|
||||
|
||||
15 September 2026: Wouter
|
||||
- For #1507: TOCTOU race in store_rrsets() can return a
|
||||
CNAME chain whose target owns no address.
|
||||
|
||||
10 September 2026: Wouter
|
||||
- Fix to construct the delegation point during DS NS find
|
||||
as a child side delegation point if that was the response.
|
||||
Thanks to Qifan Zhang, Palo Alto Networks, for the report.
|
||||
- Fix to error on missing close parenthesis for zone file
|
||||
read and for url content read. Thanks to Qifan Zhang, Palo
|
||||
Alto Networks, for the report.
|
||||
|
||||
8 September 2026: Wouter
|
||||
- Fix to elevate the diagnostic for no matches for a wildcard
|
||||
trusted-keys-file, make it more descriptive, and more man
|
||||
page content for it. Thanks to Qifan Zhang, Palo Alto
|
||||
Networks, for the report.
|
||||
|
||||
4 September 2026: Wouter
|
||||
- Fix to make rpz_config leave the rpz with correct set up
|
||||
on failure. The struct is not half configured on exit.
|
||||
Thanks to Qifan Zhang, Palo Alto Networks, for the report.
|
||||
- Fix to not change the action override in rpz_config, before
|
||||
the cname override has succeeded.
|
||||
|
||||
3 September 2026: Wouter
|
||||
- Fix to match NSEC3 hash length to the NSEC3 algorithm,
|
||||
this stops negative cache overdeletion. It also contrains
|
||||
the hash label length and checks if the NSEC nextowner
|
||||
is valid. Thanks to Yuqi Qiu & Xiang Li (Nankai University,
|
||||
AOSP Lab).
|
||||
- Remove unused .travis.yml for ci integration.
|
||||
- Fix to reorder SVCB and HTTPS svcparams for unknown RR form
|
||||
zonefile input. If it can not be parsed it is leniently
|
||||
accepted, much like as a secondary it leniently accepts it.
|
||||
Thanks to Qifan Zhang, Palo Alto Networks, for the report.
|
||||
- Fix that when extended EDNS RCODE does not fit, at short
|
||||
udpsize, the reply is truncated with TC and fix for the
|
||||
rcode in that short reply to be a sensible rcode.
|
||||
Thanks to Qifan Zhang, Palo Alto Networks, for the report.
|
||||
- Fix that when a partial EDNS option is in a query, the
|
||||
response is a more RFC conformant FORMERR, since the EDNS
|
||||
option is malformed. Also fix to have an EDNS size for
|
||||
the reply error encoding for failed EDNS parse of the query.
|
||||
Thanks to Qifan Zhang, Palo Alto Networks, for the report.
|
||||
|
||||
2 September 2026: Wouter
|
||||
- Fix to not commit to have_zone at apply AXFR time for auth
|
||||
zone transfers, so that later failure rolls back to not.
|
||||
The have_zone value is set later when the SOA is retrieved.
|
||||
Also fix to clear the zone data when a transfer does not
|
||||
have a valid SOA record in the zone for it.
|
||||
Thanks to Qifan Zhang, Palo Alto Networks, for the report.
|
||||
|
||||
1 September 2026: Wouter
|
||||
- Fix to allow block_a and other local-zone types in a view.
|
||||
- Fix LOC RR parse to avoid double to uint32 cast overflow.
|
||||
Thanks to Qifan Zhang, Palo Alto Networks, for the report.
|
||||
|
||||
26 August 2026: Wouter
|
||||
- Fix notify for auth-zone during initial start up. It
|
||||
performs the transfer and not only lookup.
|
||||
|
||||
24 August 2026: Wouter
|
||||
- Fix #132: Add `harden-cname-follow: yes` config option, that
|
||||
can be used to disable cname scrubbing. That can be useful
|
||||
for when the traffic is on localhost only.
|
||||
|
||||
21 August 2026: Wouter
|
||||
- Fix to defend against double event deletion, that could cause
|
||||
event corruption and use after free, for comm_timer_disable.
|
||||
|
||||
11 August 2026: Wouter
|
||||
- Fix #1492 from zacek: Data race in log_init() on
|
||||
key_created/log_lock when calling ub_ctx_create()
|
||||
concurrently from multiple threads.
|
||||
- Fix stat_values.tdir test to have less test failures.
|
||||
|
||||
7 August 2026: Wouter
|
||||
- Fix #1489 from jplesnik: Replace removed Python 2 C API
|
||||
macros for SWIG 4.5.0 compatibility.
|
||||
|
||||
6 August 2026: Alex Khanin
|
||||
- Fix #1488: bounds check in packed_rr_to_string, it checked
|
||||
the assembled rr length against the output string length
|
||||
dest_len, instead of against the size of the rr buffer it
|
||||
writes into. Callers in cachedump.c and remote.c pass a
|
||||
dest_len larger than that buffer.
|
||||
- Unit test for packed_rr_to_string.
|
||||
|
||||
6 August 2026: Wouter
|
||||
- Fix #1485: the list_forwards command omits port numbers.
|
||||
The list_forwards and list_stubs commands for
|
||||
unbound-control print port and tls auth name.
|
||||
- Fix #1487: regression in 1.26.0, ipsecmod is now always
|
||||
partly enabled.
|
||||
|
||||
4 August 2026: Wouter
|
||||
- Fix to set makedist.sh to not wget config.sub and
|
||||
config.guess from git repo. The fetch times out, and the
|
||||
version from libtoolize is much more recent now than
|
||||
that it was when the wget was added.
|
||||
|
||||
31 July 2026: Wouter
|
||||
- For #1483: The failure reason when an NSEC NXDOMAIN is
|
||||
encountered when looking for an insecure delegation, is
|
||||
fixed to mention the NSEC records, instead of nonexistent
|
||||
NSEC3 records, that it attempted.
|
||||
|
||||
30 July 2026: Wouter
|
||||
- Fix #1482: DNS-over-QUIC doesn't work with simple config.
|
||||
That fixes interface-automatic for use with doq service.
|
||||
|
||||
28 July 2026: Wouter
|
||||
- Tag for 1.26.0rc1. The repo continues with version 1.26.1.
|
||||
This became 1.26.0 on 4 aug 2026.
|
||||
|
||||
24 July 2026: Wouter
|
||||
- Merge #1433 from jisakiel: Add new static zone type
|
||||
block_aaaa to suppress AAAA queries.
|
||||
- Unit test for block_a and block_aaaa.
|
||||
- Fix #1477: respip + dns64: dns64 uses A records modified by
|
||||
respip instead of original A records. Adds local-zone types
|
||||
block_a_wdata and block_aaaa_wdata, that are like block_a
|
||||
and block_aaaa, and uses local-data if present.
|
||||
- set code repository version to 1.26.0.
|
||||
- Update generated man pages.
|
||||
- Fix to allow test fake sha1 on systems with possible sha1
|
||||
support.
|
||||
- Fix to use sha256 for unbound-anchor unit test.
|
||||
- Fix unbound-anchor check for return value of
|
||||
X509_NAME_get_text_by_NID of the emailaddress.
|
||||
- Fix lock test protect for auth zone change.
|
||||
- Fix to lock shared_ports structure during initialisation.
|
||||
- Fix to lock anchor structure when file is set for it in
|
||||
parse of the header.
|
||||
- Merge #1480 from petrvaganoff: authzone: fix memory leak in
|
||||
xfer_set_masters() error path.
|
||||
- Fix unused variable warnings in shared_ports_fetch_random
|
||||
and shared_ports_return_port when compiled without threads.
|
||||
- Fix to guard access to shared ports interface array during
|
||||
set up, for analyzer.
|
||||
- Fix sign of comparison warning in shared ports setup.
|
||||
- Fix #1481: Fix to use tls-port after referral if
|
||||
tls-upstream is set.
|
||||
- Merge #1479 from psumbera: Fix pthread detection on
|
||||
Solaris 11.4.
|
||||
- Fix to call OPENSSL_cleanup on exit when that is defined.
|
||||
|
||||
23 July 2026: Wouter
|
||||
- Updated credits for Xuanchao Xie in 22 july changelog.
|
||||
- Merge #1478 from petrvaganoff: pythonmod: add check return
|
||||
value after ftell().
|
||||
- Fix that for NSEC3 proofs the NSEC3 zone, as the b32.name is
|
||||
checked to be the same as the signer name. Also RRSIGs are
|
||||
not considered valid when an NSEC3 is not b32.signerzone.
|
||||
Thanks to Qifan Zhang, Palo Alto Networks, for the report.
|
||||
- Fix that the aggressive negative cache does not insert NSEC
|
||||
records with overreaching next owner name. Also the result
|
||||
is not above the trust anchor's bailiwick. Also RRSIGS are
|
||||
not considered valid when an NSEC next owner name is not
|
||||
under the signer zone name. Thanks to Qifan Zhang, Palo
|
||||
Alto Networks, for the report.
|
||||
- Fix mesh cycle detection for configuration with respip CNAME
|
||||
loop and tagged clients. Thanks to Qifan Zhang, Palo Alto
|
||||
Networks, for the report.
|
||||
|
||||
22 July 2026: Wouter
|
||||
- Release tag for 1.25.2, with the security commits:
|
||||
- Fix CVE-2026-14586, Assertion in libngtcp2 when under pressure
|
||||
in high concurrency DNS-over-QUIC environments. Thanks to Kunta
|
||||
Chu, Kaihua Wang, and Jianjun Chen from Tsinghua University,
|
||||
for the report.
|
||||
- Fix CVE-2026-32665, Remote DNS-over-QUIC denial of
|
||||
service due to `quic-size` budget bypass. Thanks to N0zoM1z0
|
||||
(https://github.com/N0zoM1z0) for the report. In addition, thanks to
|
||||
Kunta Chu, Kaihua Wang, and Jianjun Chen from Tsinghua University,
|
||||
for also reporting this issue. In addition, thanks to Qifan Zhang,
|
||||
Palo Alto Networks, for also reporting this issue. In addition,
|
||||
thanks to Xuanchao Xie, Lutong Chen, and Kaiping Xue of the
|
||||
University of Science and Technology of China (USTC), for also
|
||||
reporting this issue.
|
||||
- Fix CVE-2026-40691, Packet of death for DNSCrypt over TCP. Thanks
|
||||
to Qifan Zhang, Palo Alto Networks, for the report. In addition,
|
||||
thanks to Trung Nguyen (@everping) of CyStack, for also reporting
|
||||
this issue.
|
||||
- Fix CVE-2026-41637, Degradation of resolution service from
|
||||
improperly accounted client-terminated DNS-over-QUIC queries. Thanks
|
||||
to Qifan Zhang, Palo Alto Networks, for the report.
|
||||
- Fix CVE-2026-42955, Extra fix for CVE-2026-40622 to also clamp
|
||||
the TTL of A/AAAA records disallowing a one-time 'ghost domain'
|
||||
delegation renewal via glue records. Thanks to Qifan Zhang, Palo
|
||||
Alto Networks, for the report.
|
||||
- Fix CVE-2026-44621, Libunbound applications configured with
|
||||
'unwanted-reply-threshold' could eventually be abruptly
|
||||
terminated. Thanks to Qifan Zhang, Palo Alto Networks, for the
|
||||
report.
|
||||
- Fix CVE-2026-44687, Off-by-one error in 'harden-below-nxdomain'
|
||||
logic can shadow a stub/forward zone by a legitimate parent's
|
||||
NXDOMAIN. Thanks to Qifan Zhang, Palo Alto Networks, for the report.
|
||||
- Fix CVE-2026-44690, Cross-zone wildcard cache poisoning via
|
||||
RRSIG.labels manipulation. Thanks to Qifan Zhang, Palo Alto
|
||||
Networks, for the report.
|
||||
- Fix CVE-2026-46582, A wildcard replay, as another piece of data,
|
||||
triggers poisoning in the serve expired reply path. Thanks to
|
||||
Qifan Zhang, Palo Alto Networks, for the report.
|
||||
- Fix CVE-2026-50045, 'max-global-quota' reset by DNSSEC validation
|
||||
restarts. Thanks to Kunjie Shang, University of Science and
|
||||
Technology of China, for the report.
|
||||
- Fix CVE-2026-50046, Possible heap use-after-free in an error path
|
||||
when a DoT forwarded query is jostled out. Thanks to Qifan Zhang,
|
||||
Palo Alto Networks, for the report.
|
||||
- Fix CVE-2026-50243, 'response-ip'/'rpz' can rewrite BOGUS answers
|
||||
instead of returning SERVFAIL. Thanks to Qifan Zhang, Palo Alto
|
||||
Networks, for the report.
|
||||
- Fix CVE-2026-50248, BOGUS configured primary hostname accepted for
|
||||
XFR in auth/rpz zones. Thanks to Qifan Zhang, Palo Alto Networks,
|
||||
for the report.
|
||||
- Fix CVE-2026-50251, Attacker supplied `0.0.0.0`/`::` glue triggers
|
||||
defensive full-cache flush. Thanks to Qifan Zhang, Palo Alto
|
||||
Networks, for the report.
|
||||
- Fix CVE-2026-50252, Possible cache poisoning attack by mapping
|
||||
source port population per thread. Thanks to Inbal Schussheim and
|
||||
Amit Klein, Hebrew University, for the report.
|
||||
- Fix CVE-2026-52863, Memory corruption could lead to crash and
|
||||
denial of service. Thanks to Qifan Zhang, Palo Alto Networks,
|
||||
for the report.
|
||||
- Fix CVE-2026-54478, DNS Cookie bypass when combined with
|
||||
proxy-protocol use. Thanks to Qifan Zhang, Palo Alto Networks,
|
||||
for the report.
|
||||
- Fix CVE-2026-55708, Privacy/configuration issue when adding local
|
||||
data in views through 'unbound-control'. Thanks to Qifan Zhang,
|
||||
Palo Alto Networks, for the report.
|
||||
- Fix CVE-2026-55717, 'serve-expired-client-timeout' and 'response-ip'
|
||||
CNAME redirect could lead to a crash. Thanks to Qifan Zhang, Palo
|
||||
Alto Networks, for the report. In addition, thanks to Xin Wang,
|
||||
Jiapeng Li, and Jiajia Liu, Northwestern Polytechnical University,
|
||||
for also reporting this issue.
|
||||
- Fix CVE-2026-55973, 'dns-error-reporting: yes' leads to stack buffer
|
||||
overflow. Thanks to Qifan Zhang, Palo Alto Networks, for the report.
|
||||
- Fix CVE-2026-55990, Packet of death for a DNSCrypt misconfigured
|
||||
Unbound. Thanks to Qifan Zhang, Palo Alto Networks, for the report.
|
||||
- Fix CVE-2026-55991, Remote DNS-over-QUIC (DoQ) flow-control
|
||||
assertion failure in libngtcp2. Thanks to Qifan Zhang, Palo Alto
|
||||
Networks, for the report. In addition, thanks to Xuanchao Xie,
|
||||
Lutong Chen, and Kaiping Xue of the University of Science and
|
||||
Technology of China (USTC), for also reporting this issue.
|
||||
- Fix CVE-2026-56416, Possible heap buffer overflow when validator
|
||||
canonicalizes RDATA that contains domain name. Thanks to Qifan
|
||||
Zhang, Palo Alto Networks, for the report.
|
||||
- Fix CVE-2026-56444, Degradation of resolution service when
|
||||
'discard-timeout' and 'serve-expired-client-timeout' are combined in
|
||||
unusual configuration. Thanks to Qifan Zhang, Palo Alto Networks,
|
||||
for the report. In addition, thanks to Xin Wang, Jiapeng Li,
|
||||
and Jiajia Liu, Northwestern Polytechnical University, for also
|
||||
reporting this issue. In addition, thanks to Haruki Oyama (Waseda
|
||||
University), for also reporting this issue.
|
||||
- Set the repository to 1.25.3, it continues with the previous
|
||||
changes.
|
||||
- Unit test for CVE-2026-42955.
|
||||
- Unit test for CVE-2026-44687.
|
||||
- Unit test for CVE-2026-44690.
|
||||
- Unit test for CVE-2026-46582.
|
||||
- Unit test for CVE-2026-50045.
|
||||
- Unit test for CVE-2026-50243.
|
||||
- Unit test for CVE-2026-50248.
|
||||
- Unit test for CVE-2026-55717.
|
||||
- Unit test for CVE-2026-55973.
|
||||
- Unit test for CVE-2026-56416.
|
||||
- Fix error in log printout in fix for CVE-2026-50248, when the
|
||||
primary name is bogus.
|
||||
- iana portlist update.
|
||||
|
||||
21 July 2026: Wouter
|
||||
- Merge #1476 from petrvaganoff: ipsecmod: fix possible deref
|
||||
on null after reply_find_answer_rrset().
|
||||
|
||||
20 July 2026: Wouter
|
||||
- Merge #1475 from petrvaganoff: ipsecmod: fix deref on null
|
||||
in ipsecmod-whitelist after OOM.
|
||||
- Fix #1474: DoQ responses are never padded - pad-responses
|
||||
does not apply to comm_doq (RFC 9250 §5.4 MUST).
|
||||
|
||||
9 July 2026: Wouter
|
||||
- Merge #1383 from jdek: Fix randomness generation on
|
||||
macOS/iOS under chroot.
|
||||
- Fix unit test for malformed svcb for test on Windows.
|
||||
|
||||
2 July 2026: Wouter
|
||||
- Merge #1087: Overload `local_data_remove` to support removing
|
||||
specific records.
|
||||
|
||||
30 June 2026: Wouter
|
||||
- Fix #1469: dohclient: DoH POST missing content-length → :status
|
||||
400 from strict resolvers (Cloudflare, Mullvad).
|
||||
- iana portlist updated.
|
||||
|
||||
26 June 2026: Wouter
|
||||
- Merge #1467: daemon: fix DEREF_AFTER_NULL.EX.COND on
|
||||
worker_init. This fixes error handling if the worker
|
||||
stat_timer allocation has an out of memory error. That
|
||||
makes the server not crash later, attempting to use it.
|
||||
|
||||
24 June 2026: Wouter
|
||||
- Merge #1465 from dag-erling: Add libunbound/remote.h. Add
|
||||
a shared header containing prototypes for functions that
|
||||
both ends of a remote control connection need to implement.
|
||||
|
||||
19 June 2026: Wouter
|
||||
- Fix for #1457: fix thread setname for thread start of
|
||||
dnstap, and fast_reload.
|
||||
- Fix to update github ci actions/checkout to v7.
|
||||
- Fix warning about file_string_matches in unbound-checkconf.
|
||||
|
||||
17 June 2026: Wouter
|
||||
- Fix that after fast_reload the disown of the auth zone
|
||||
transfer task cleans the chunk list. Also fix the
|
||||
auth_transfer_limit test to use a forwarder for each type
|
||||
of failure, so the one is not blocked by the other waiting.
|
||||
- Fix to remove debug from auth_transfer_limit test.
|
||||
- Fix that unbound-checkconf checks if an auth-zone download
|
||||
can overwrite another file, by filename collision.
|
||||
Thanks to Qifan Zhang, Palo Alto Networks, for the report.
|
||||
- Fix that malloc failure in auth-zone insert rr does
|
||||
not create an empty node and does not cause an infinite
|
||||
loop. Thanks to Qifan Zhang, Palo Alto Networks, for
|
||||
the report.
|
||||
- Fix that unbound-control auth_zone_reload stops the
|
||||
server answering from the zone after a failure to read.
|
||||
Thanks to Qifan Zhang, Palo Alto Networks, for the report.
|
||||
- Fix that malloc failure in dns64_inform_super does
|
||||
not set up a half-built reply for cache store, that could
|
||||
lead to a crash. Thanks to Qifan Zhang, Palo Alto Networks,
|
||||
for the report.
|
||||
- Fix that malloc failure for new_local_rrset for RPZ qname
|
||||
trigger RR insert does not crash. It does not link a
|
||||
partial RRset, and logs an error on failure, and cleans
|
||||
up the dname allocation. Thanks to Qifan Zhang, Palo Alto
|
||||
Networks, for the report.
|
||||
- Fix that malloc failure in doq connection setup, does
|
||||
not crash in doq connection delete later. Thanks to Qifan
|
||||
Zhang, Palo Alto Networks, for the report.
|
||||
- Fix that malloc failure for ngtcp2_conn_server_new
|
||||
cleans up reference that older ngtcp2 versions can leave.
|
||||
Thanks to Qifan Zhang, Palo Alto Networks, for the report.
|
||||
- Fix that on malloc failure during accept of TCP, the
|
||||
socket is not left to cause a read event loop. It uses
|
||||
slow-accept to delay accepting new connections, if
|
||||
that fails it drops the new connections. When the tcp
|
||||
connection usage is full, it waits for 50msec, to allow
|
||||
existing queries to be resolved. Thanks to Qifan Zhang,
|
||||
Palo Alto Networks, for the report.
|
||||
- Fix that malloc failure for rpz_strip_nsdname is
|
||||
checked and handled, so that it does not crash later.
|
||||
Thanks to Qifan Zhang, Palo Alto Networks, for the report.
|
||||
- Fix that malloc failure during edns subnet addrtree
|
||||
insert is checked, so it does not crash later. Thanks to
|
||||
Qifan Zhang, Palo Alto Networks, for the report.
|
||||
- Fix to check the return value of auth_xfer_create
|
||||
during fast_reload auth-zone add and change processing.
|
||||
Thanks to Qifan Zhang, Palo Alto Networks, for the report.
|
||||
- Fix to check for malloc failure in rpz response create,
|
||||
for nodata and nxdomain, so it does not crash later.
|
||||
Thanks to Qifan Zhang, Palo Alto Networks, for the report.
|
||||
- Fix that fast_reload does not terminate the server
|
||||
on malloc failure for dnstap, or if gethostname fails.
|
||||
Thanks to Qifan Zhang, Palo Alto Networks, for the report.
|
||||
- Fix after malloc failure for stats, then it drains the pipe
|
||||
so the internal messaging stays correct. Also it does
|
||||
not exit the server if stats pipe communication fails.
|
||||
Thanks to Qifan Zhang, Palo Alto Networks, for the report.
|
||||
- Fix that fast_reload does not terminate the server
|
||||
on config read failure after malloc failure. Thanks to
|
||||
Qifan Zhang, Palo Alto Networks, for the report.
|
||||
- Fix that fast_reload does not terminate the server if
|
||||
random init for DNS cookies fails. The data is only random
|
||||
generated if cookies are enabled, and the random data
|
||||
is necessary. Thanks to Qifan Zhang, Palo Alto Networks,
|
||||
for the report.
|
||||
|
||||
17 June 2026: Yorgos
|
||||
- Fix memory leak on DNAME 0TTL records.
|
||||
|
||||
16 June 2026: Wouter
|
||||
- Fix to disallow $INCLUDE for secondary zones. Start up
|
||||
of server continues if a secondary zone fails to load.
|
||||
Failed loads clear the zone data, so there is no partial
|
||||
zone. Thanks to Qifan Zhang, Palo Alto Networks, for
|
||||
the report.
|
||||
- Fix that when SVCB records cannot be written out, and
|
||||
are written in unknown format, that the zone read allows
|
||||
such unknown format SVCB records. Thanks to Qifan Zhang,
|
||||
Palo Alto Networks, for the report.
|
||||
- Fix that a half-written trust anchor file does not crash
|
||||
the server at runtime. It unlinks a wrong file from the list.
|
||||
Thanks to Qifan Zhang, Palo Alto Networks, for the report.
|
||||
- Fix that auth-zone, and RPZ zones, do not allow out-of-zone
|
||||
records. These are records that are not under the zone apex.
|
||||
The out-of-zone records are dropped from the zone contents.
|
||||
Thanks to Qifan Zhang, Palo Alto Networks, for the report.
|
||||
- Fix that dns64 does not ignore the `forward-no-cache` and
|
||||
`stub-no-cache` options. Thanks to Qifan Zhang, Palo Alto
|
||||
Networks, for the report.
|
||||
- Fix that a signed wildcard NSEC, is checked before use,
|
||||
so it does not allow insecure DS proofs inappropriately.
|
||||
Thanks to Qifan Zhang, Palo Alto Networks, for the report.
|
||||
- Fix that after malloc failure a half-built local_alias does
|
||||
not crash the server. Thanks to Qifan Zhang, Palo Alto
|
||||
Networks, for the report.
|
||||
- Fix that for a zonefile only zone, if that file does not
|
||||
exist on server start, the server continues to start with
|
||||
a warning log message. Thanks to Qifan Zhang, Palo Alto
|
||||
Networks, for the report.
|
||||
- Fix that after malloc failure in RPZ load a half built
|
||||
list does not crash later. The newly created RRset is
|
||||
linked after creation has succeeded. Thanks to Qifan Zhang,
|
||||
Palo Alto Networks, for the report.
|
||||
- Fix that dnscrypt configuration does not crash, due to
|
||||
inconsistency between secret and public keys. Also
|
||||
duplicate files are skipped. Thanks to Qifan Zhang, Palo
|
||||
Alto Networks, for the report.
|
||||
- Fix locking in libunbound ub_ctx_set_event call.
|
||||
Thanks to Qifan Zhang, Palo Alto Networks, for the report.
|
||||
- Fix that libunbound pipe functions fail with error after
|
||||
an event base is set. Thanks to Qifan Zhang, Palo Alto
|
||||
Networks, for the report.
|
||||
- Fix for neater solution to clear log thread id after
|
||||
worker init failure. Thanks to Qifan Zhang, Palo Alto
|
||||
Networks, for the report.
|
||||
- Fix incorrect cleanup after an allocation failure for
|
||||
a delegation point. Thanks to Qifan Zhang, Palo Alto
|
||||
Networks, for the report.
|
||||
- Fix that after malloc failure in find_tag_datas, the
|
||||
local_alias is cleaned up. Thanks to Qifan Zhang, Palo
|
||||
Alto Networks, for the report.
|
||||
- Fix that after shared memory cannot be created, from
|
||||
`shm-enable`, the server does not crash. Thanks to Qifan
|
||||
Zhang, Palo Alto Networks, for the report.
|
||||
- Fix incorrect cleanup after an allocation failure for
|
||||
a delegation point in a region. Thanks to Qifan Zhang,
|
||||
Palo Alto Networks, for the report.
|
||||
- Fix after malloc failure the rrset_insert_rr in
|
||||
localzone processing, during RPZ qname trigger processing,
|
||||
the RRset retains its previous data correcly. Thanks to
|
||||
Qifan Zhang, Palo Alto Networks, for the report.
|
||||
- Fix for #1462: Fix that auth primary host name lookup
|
||||
allows CNAMEs.
|
||||
|
||||
15 June 2026: Wouter
|
||||
- Fix to add `max-transfer-size` and `max-transfer-time` that
|
||||
limit auth-zone and rpz transfer amount and time taken.
|
||||
Default is disabled. This hardens against unbounded
|
||||
transfers. Thanks to Qifan Zhang, Palo Alto Networks,
|
||||
for the report.
|
||||
- Fix perform a full transfer every number of incremental
|
||||
transfers, to stop increasing memory usage, for rpz
|
||||
zones. Thanks to Qifan Zhang, Palo Alto Networks, for
|
||||
the report.
|
||||
- Fix assertion failure for long HTTP header that fills
|
||||
buffer. Thanks to Qifan Zhang, Palo Alto Networks, for
|
||||
the report.
|
||||
- Fix buffer overflow when configured with lower than
|
||||
default size and http transfer. Thanks to Qifan Zhang,
|
||||
Palo Alto Networks, for the report.
|
||||
- Fix that misconfigured `iter-scrub-ns: 0` causes request
|
||||
failures. Thanks to Qifan Zhang, Palo Alto Networks,
|
||||
for the report.
|
||||
- Fix that fast_reload when a zonemd verification lookup
|
||||
it in progress with subnet loaded, deregisters the
|
||||
callback. Thanks to Qifan Zhang, Palo Alto Networks,
|
||||
for the report.
|
||||
- Fix for fast_reload that removes an auth zone while its
|
||||
lookups are in progress, for a primary name. Also after the
|
||||
change, it no longer picks up the old results. Thanks to
|
||||
Qifan Zhang, Palo Alto Networks, for the report.
|
||||
- Fix integer overflow in infra-cache-max-rtt calculation.
|
||||
Thanks to Qifan Zhang, Palo Alto Networks, for the report.
|
||||
- Fix erroneous DNS error report values after bogus AAAA
|
||||
query caused error information that was not cleared by
|
||||
a successful A subquery. Thanks to Qifan Zhang, Palo Alto
|
||||
Networks, for the report.
|
||||
- Fix integer overflow for very high values of
|
||||
`sock-queue-timeout`. Thanks to Qifan Zhang, Palo Alto
|
||||
Networks, for the report.
|
||||
- Fix that fast_reload does not terminate the server for
|
||||
errors in config, for key files. Thanks to Qifan Zhang,
|
||||
Palo Alto Networks, for the report.
|
||||
- Fix log of an aliased qname, to not use freed region
|
||||
memory. Thanks to Qifan Zhang, Palo Alto Networks, for
|
||||
the report.
|
||||
- Fix DNAME synthesis from cache that keeps use of 0TTL
|
||||
entries in a sliding window. It did not surpass RRSIG
|
||||
expiry. Thanks to Qifan Zhang, Palo Alto Networks, for
|
||||
the report.
|
||||
- Fix misconfigured ipsecmod hook causing path name
|
||||
similarity with other file. The ipsecmod is changed for
|
||||
exec of the hook. The ipsecmod hook, if a script, has to
|
||||
start now with a line like `#!/bin/sh`. Thanks to Qifan
|
||||
Zhang, Palo Alto Networks, for the report.
|
||||
- Fix that dns64 bypasses rpz-passthru rule during
|
||||
synthesis. This restricted more than necessary. Thanks to
|
||||
Qifan Zhang, Palo Alto Networks, for the report.
|
||||
|
||||
12 June 2026: Wouter
|
||||
- Fix that for auth-zone and rpz zones the allow-notify
|
||||
addresses and netblocks are available from start, and
|
||||
fix the probe step skip.
|
||||
|
||||
11 June 2026: Wouter
|
||||
- Fix for #1306: configure detects specifically the call to
|
||||
SSL_set_quic_tls_early_data_enabled and
|
||||
SSL_set_quic_early_data_enabled, so the correct one is used.
|
||||
- Fix for #1306: configure checks if the ngtcp2_crypto_ossl
|
||||
header file is available, and prints an error otherwise.
|
||||
- Fix #1437: Fix compile with OpenSSL 4.0.1.
|
||||
- Fix compile for OpenSSL 1.0.2 and before in server cleanup.
|
||||
|
||||
10 June 2026: Wouter
|
||||
- Fix pythonmod script read for numeric overflow.
|
||||
- Fix warnings with gcc in compat/inet_pton.c.
|
||||
|
||||
9 June 2026: Wouter
|
||||
- Fix unit test for ecs to check for malloc success.
|
||||
|
||||
3 June 2026: Wouter
|
||||
- Fix that the processing of class responses does not have
|
||||
a heap use-after-free. That could happen if at least two
|
||||
distinct classes are configured for resolution. Thanks
|
||||
to Qifan Zhang, Palo Alto Networks for the report.
|
||||
In addition, thanks to Xin Wang, Jiapeng Li, and Jiajia
|
||||
Liu, Northwestern Polytechnical University, for also
|
||||
reporting this.
|
||||
- Fix negative cache to work with NSEC3 records without salt.
|
||||
Thanks to Xin Wang, Jiapeng Li, and Jiajia Liu, Northwestern
|
||||
Polytechnical University, for the report.
|
||||
- Fix parse of svcbparam ech, it had incorrect length. Thanks
|
||||
to Qifan Zhang, Palo Alto Networks for the report.
|
||||
- Fix that quotation and escaping works the same in auth-zone
|
||||
url content, as in the zonefile read. Thanks to Qifan Zhang,
|
||||
Palo Alto Networks for the report.
|
||||
- Fix ipset module to use larger domain name buffers, and
|
||||
check buffer lengths. Thanks to Qifan Zhang, Palo Alto
|
||||
Networks for the report.
|
||||
- Fix PROXYv2 header read and consume, it checks the header
|
||||
size. Thanks to Qifan Zhang, Palo Alto Networks for
|
||||
the report.
|
||||
- Fix negative cache NSEC3 nodata proof, to use the correct
|
||||
message size. Thanks to Qifan Zhang, Palo Alto Networks,
|
||||
for the report.
|
||||
- Fix fast_reload for when a ZONEMD lookup is in progress.
|
||||
Thanks to Qifan Zhang, Palo Alto Networks, for the report.
|
||||
- Fix that validation canonicalization of domain names
|
||||
in rdata checks for buffer bounds. Thanks to Qifan Zhang,
|
||||
Palo Alto Networks, for the report.
|
||||
- Fix that dump_cache has a larger buffer for records,
|
||||
and it checks that an owner name does not collide with BADRR
|
||||
on the input, and changes verbosity on the log of failure in
|
||||
rrset to string. Thanks to Qifan Zhang, Palo Alto Networks,
|
||||
for the report.
|
||||
- Fix that dns64 cleans up the allocated message if the adjust
|
||||
routines fail, and checks if there is a reply before cache
|
||||
store, also unbound checks if A and AAAA are malformed
|
||||
for auth-zones. Thanks to Qifan Zhang, Palo Alto Networks,
|
||||
for the report.
|
||||
|
||||
3 June 2026: Yorgos
|
||||
- Fix const as reported by newest compiler warnings.
|
||||
|
||||
29 May 2026: Wouter
|
||||
- Fix header_seen detection for trust anchor files, so that it
|
||||
detects the id line.
|
||||
- iana portlist updated.
|
||||
- Update icannbundle.pem certificates in unbound-anchor. It
|
||||
has the public keys for 2009 to 2029 and for 2025 to 2045.
|
||||
- Fix unit test to check for new icannbundle.pem.
|
||||
|
||||
28 May 2026: Wouter
|
||||
- Fix #1457: race condition causes segfault when starting
|
||||
threads.
|
||||
|
||||
27 May 2026: Wouter
|
||||
- Fix for autotrust state-file line overflow, that can give
|
||||
hold-down bypass. Thanks to Qifan Zhang, Palo Alto Networks,
|
||||
for the report.
|
||||
- Fix to limit the DSNS per-label walk in the iterator. Thanks
|
||||
to Qifan Zhang, Palo Alto Networks, for the report.
|
||||
- Fix that the ratelimit is decremented on successful
|
||||
referrals. Thanks to Qifan Zhang, Palo Alto Networks, for
|
||||
the report.
|
||||
- Fix that msgencode insert_query has the correct assertion,
|
||||
for a local_alias. Thanks to Qifan Zhang, Palo Alto Networks,
|
||||
for the report.
|
||||
- Fix to reset the tcp-timeout before applying a load based
|
||||
reduction. Thanks to Qifan Zhang, Palo Alto Networks, for the
|
||||
report.
|
||||
- Fix to decrement the per-netblock tcp connection limits, so
|
||||
it keeps usable. Thanks to Qifan Zhang, Palo Alto Networks,
|
||||
for the report.
|
||||
- Fix manual to document ratelimit, that it is for target
|
||||
nameservers for a domain, and keeps queries limited. Thanks
|
||||
to Qifan Zhang, Palo Alto Networks, for the report.
|
||||
- Fix, in depth, for respip rewrite of dns64 responses. Thanks
|
||||
to Qifan Zhang, Palo Alto Networks, for the report.
|
||||
- Fix that dns64 with subnetcache does not write ECS scoped
|
||||
answers to global cache. Thanks to Qifan Zhang, Palo Alto
|
||||
Networks, for the report.
|
||||
- Fix ipset module for name too long checks, race conditions
|
||||
on local name buffer, and for socket close race condition.
|
||||
Thanks to Qifan Zhang, Palo Alto Networks, for the report.
|
||||
- Fix that validator caps number of ANY RRsets it can
|
||||
validate, and the wait timer is shortened. Thanks to Qifan
|
||||
Zhang, Palo Alto Networks, for the report.
|
||||
- Fix analyzer warning in mesh_new_client.
|
||||
|
||||
26 May 2026: Wouter
|
||||
- Fix for mesh new client and mesh new callback to rollback the
|
||||
added address, tcp mesh state and callback when there is a failure
|
||||
to initialize. This fixes the mesh accounting of reply addresses.
|
||||
Thanks to Xin Wang, Jiapeng Li, and Jiajia Liu, Northwestern
|
||||
Polytechnical University, for the report
|
||||
|
||||
20 May 2026: Wouter
|
||||
- Fix CVE-2026-33278, Possible remote code execution during DNSSEC
|
||||
validation. Thanks to Qifan Zhang, Palo Alto Networks, for the report.
|
||||
@@ -27,6 +717,79 @@
|
||||
Networks, for the report.
|
||||
- Fix CVE-2026-44608, Use after free and crash in RPZ code. Thanks
|
||||
to Qifan Zhang, Palo Alto Networks, for the report.
|
||||
- Tag for 1.25.1 release, it contains the security fixes on 1.25.0.
|
||||
the code repository continues with in addition the previous fixes,
|
||||
for 1.25.2.
|
||||
- Unit test for CVE-2026-33278.
|
||||
- Unit test for CVE-2026-42944.
|
||||
- Unit test for CVE-2026-42959.
|
||||
- Unit test for CVE-2026-40622.
|
||||
- Unit test for CVE-2026-42960.
|
||||
- Fix in depth for serve-expired responses from cachedb, that it
|
||||
does not store bogus. Thanks to Qifan Zhang, Palo Alto Networks,
|
||||
for the report.
|
||||
- Fix lame server detection, for selfpointed glue records.
|
||||
Thanks to Shuhan Zhang, Dan Li, and Baojun Liu from Tsinghua
|
||||
University for the report.
|
||||
- Fix cleaning up DoH session. The same query can be on multiple
|
||||
streams in a session. Thanks to Qifan Zhang, Palo Alto Networks,
|
||||
for the report.
|
||||
- Fix for signed same-owner CNAME and ordinary RRset responses.
|
||||
Thanks to Xin Wang and Jiajia Liu, Northwestern Polytechnical
|
||||
University, for the report.
|
||||
|
||||
18 May 2026: Wouter
|
||||
- Fix for mixed class referrals, the resolver uses the query
|
||||
class. Thanks to Xin Wang and Jiajia Liu, Northwestern
|
||||
Polytechnical University, for the report.
|
||||
|
||||
15 May 2026: Wouter
|
||||
- Fix man page entry for so-sndbuf, it is for responses sent out.
|
||||
- Fix val_find_DS for robustness, to check the result of
|
||||
packet_rrset_copy_region before using it. Thanks to Xin Wang
|
||||
and Jiajia Liu, Northwestern Polytechnical University, for
|
||||
the report.
|
||||
- Fix that for dns64 answers, the AAAA query is checked to be
|
||||
DNSSEC validated, when DNSSEC is enabled. This improves
|
||||
the RFC6147 conformance of Unbound. Thanks to Xin Wang
|
||||
and Jiajia Liu, Northwestern Polytechnical University, for
|
||||
the report. In addition, thanks to Qifan Zhang, Palo Alto
|
||||
Networks, for reporting it.
|
||||
- Fix for allocation-failure hardening of rrset cache wildcard
|
||||
storage and canonical NSEC owner replacement. Thanks to Xin
|
||||
Wang and Jiajia Liu, Northwestern Polytechnical University,
|
||||
for the report.
|
||||
- Fix DNSSEC validation with libnettle for noncanonical RSA
|
||||
DNSKEYs with leading zeroes for n. Thanks to Xin Wang and
|
||||
Jiajia Liu, Northwestern Polytechnical University, for
|
||||
the report.
|
||||
- Fix DNSKEY size calculation for noncanonical RSA DNSKEYs
|
||||
with leading zeroes for n. Thanks to Xin Wang and Jiajia Liu,
|
||||
Northwestern Polytechnical University, for the report.
|
||||
|
||||
11 May 2026: Yorgos
|
||||
- Fix comment and verbose logging for EDNS fallback buffer size.
|
||||
|
||||
8 May 2026: Wouter
|
||||
- Fix to relax assertions after the TTL 0 handling change.
|
||||
This relaxes an assertion in cachedb (it fails instead),
|
||||
and for packet_rrset_copy_region.
|
||||
|
||||
7 May 2026: Wouter
|
||||
- Fix for Heap Out-of-Bounds Write via size_t-to-int Truncation
|
||||
in setup_if() - outside_network_create(). This fixes that
|
||||
large values for num_ports do not overflow and create
|
||||
invalid references after integer truncation. Thanks
|
||||
to Karnakar Reddy (@karnakarreddi) for the report.
|
||||
- Fix to clean up log ids after a failure to start a worker thread.
|
||||
|
||||
1 May 2026: Wouter
|
||||
- iana portlist updated.
|
||||
|
||||
29 April 2026: Wouter
|
||||
- tag for 1.25.0. The code repository continues with 1.25.1 in
|
||||
development.
|
||||
- Fix windows 64bit build for libssp dependency.
|
||||
|
||||
23 April 2026: Wouter
|
||||
- Merge #1441: Fix buffer overrun in
|
||||
|
||||
+23
-1
@@ -203,6 +203,12 @@ server:
|
||||
# protects against poison attempts.
|
||||
# iter-scrub-promiscuous: yes
|
||||
|
||||
# Limit on number of DNSSEC validation attempts for a query.
|
||||
# val-validation-attempts: 32
|
||||
|
||||
# Limit on number of DNSSEC hash attempts for a query.
|
||||
# val-hash-attempts: 32
|
||||
|
||||
# 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
|
||||
@@ -582,6 +588,9 @@ server:
|
||||
# additional section.
|
||||
# harden-unknown-additional: no
|
||||
|
||||
# Harden CNAME redirections by following them.
|
||||
# harden-cname-follow: yes
|
||||
|
||||
# Sent minimum amount of information to upstream servers to enhance
|
||||
# privacy. Only sent minimum required labels of the QNAME and set QTYPE
|
||||
# to A when possible.
|
||||
@@ -728,7 +737,7 @@ server:
|
||||
# non-secure data. Useful to shield the users of this validator from
|
||||
# potential bogus data in the additional section. All unsigned data
|
||||
# in the additional section is removed from secure messages.
|
||||
# val-clean-additional: yes
|
||||
# val-clean-additional: no
|
||||
|
||||
# Turn permissive mode on to permit bogus messages. Thus, messages
|
||||
# for which security checks failed will be returned to clients,
|
||||
@@ -899,6 +908,10 @@ server:
|
||||
# that name
|
||||
# o block_a resolves all records normally but returns
|
||||
# NODATA for A queries and ignores local data for that name
|
||||
# o block_aaaa similarly to block_a, resolves all records normally but
|
||||
# returns NODATA for AAAA queries and ignores local data for that name
|
||||
# o block_a_wdata like block_a but uses local data if present.
|
||||
# o block_aaaa_wdata like block_aaaa but uses local data if present.
|
||||
# o always_null returns 0.0.0.0 or ::0 for any name in the zone.
|
||||
# o noview breaks out of that view towards global local-zones.
|
||||
#
|
||||
@@ -1158,6 +1171,8 @@ server:
|
||||
# Timeout in milliseconds for TCP queries to auth servers.
|
||||
# tcp-auth-query-timeout: 3000
|
||||
|
||||
# Number of threads to use to load auth-zones (and RPZ). 0 disables.
|
||||
# auth-task-threads: 0
|
||||
|
||||
# Python config section. To enable:
|
||||
# o use --with-pythonmodule to configure before compiling.
|
||||
@@ -1266,6 +1281,7 @@ remote-control:
|
||||
# primary: 199.7.91.13 # d.root-servers.net
|
||||
# primary: 192.5.5.241 # f.root-servers.net
|
||||
# primary: 192.112.36.4 # g.root-servers.net
|
||||
# primary: 198.97.190.53 # h.root-servers.net
|
||||
# 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
|
||||
@@ -1274,6 +1290,7 @@ remote-control:
|
||||
# primary: 2001:500:2d::d # d.root-servers.net
|
||||
# primary: 2001:500:2f::f # f.root-servers.net
|
||||
# primary: 2001:500:12::d0d # g.root-servers.net
|
||||
# primary: 2001:500:1::53 # h.root-servers.net
|
||||
# primary: 2001:7fd::1 # k.root-servers.net
|
||||
# primary: 2620:0:2830:202::132 # xfr.cjr.dns.icann.org
|
||||
# primary: 2620:0:2d0:202::132 # xfr.lax.dns.icann.org
|
||||
@@ -1287,6 +1304,9 @@ remote-control:
|
||||
# zonemd-check: no
|
||||
# zonemd-reject-absence: no
|
||||
# zonefile: "example.org.zone"
|
||||
# max-transfer-size: 0
|
||||
# max-transfer-time: 0
|
||||
|
||||
|
||||
# Views
|
||||
# Create named views. Name must be unique.
|
||||
@@ -1453,3 +1473,5 @@ remote-control:
|
||||
# rpz-signal-nxdomain-ra: no
|
||||
# for-downstream: no
|
||||
# tags: "example"
|
||||
# max-transfer-size: 0
|
||||
# max-transfer-time: 0
|
||||
|
||||
@@ -331,6 +331,8 @@ void my_callback_function(void* my_arg, int err,
|
||||
The \fBasync_id\fP is returned so you can (at your option) decide to
|
||||
track it and cancel the request if needed.
|
||||
If you pass a NULL pointer the \fBasync_id\fP is not returned.
|
||||
The context, created via \fBub_ctx_create\fP, is in use during but also
|
||||
after the callback and it cannot be deleted during a callback.
|
||||
.TP
|
||||
.B ub_cancel
|
||||
Cancel an async query in progress.
|
||||
|
||||
@@ -408,6 +408,8 @@ Functions
|
||||
The **async_id** is returned so you can (at your option) decide to
|
||||
track it and cancel the request if needed.
|
||||
If you pass a NULL pointer the **async_id** is not returned.
|
||||
The context, created via **ub_ctx_create**, is in use during but also
|
||||
after the callback and it cannot be deleted during a callback.
|
||||
|
||||
ub_cancel
|
||||
Cancel an async query in progress.
|
||||
|
||||
@@ -354,6 +354,8 @@ If the name already has no items, nothing happens.
|
||||
Often results in NXDOMAIN for the name (in a static zone), but if the name
|
||||
has become an empty nonterminal (there is still data in domain names below
|
||||
the removed name), NOERROR nodata answers are the result for that name.
|
||||
With a specific RR instead of a domain name, that specific record is
|
||||
removed from the local data, and not all the RR data.
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
|
||||
@@ -347,6 +347,8 @@ There are several commands that the server understands.
|
||||
Often results in NXDOMAIN for the name (in a static zone), but if the name
|
||||
has become an empty nonterminal (there is still data in domain names below
|
||||
the removed name), NOERROR nodata answers are the result for that name.
|
||||
With a specific RR instead of a domain name, that specific record is
|
||||
removed from the local data, and not all the RR data.
|
||||
|
||||
|
||||
@@UAHL@unbound-control.commands@local_zones@@
|
||||
|
||||
+152
-4
@@ -691,7 +691,7 @@ Default: 0 (use system value)
|
||||
.TP
|
||||
.B so\-sndbuf: \fI<number>\fP
|
||||
If not 0, then set the SO_SNDBUF socket option to get more buffer space on
|
||||
UDP port 53 outgoing queries.
|
||||
UDP port 53 outgoing responses.
|
||||
This for very busy servers handles spikes in answer traffic, otherwise:
|
||||
.INDENT 7.0
|
||||
.INDENT 3.5
|
||||
@@ -2070,7 +2070,8 @@ Default: \(dq3 2 1 0 0\(dq
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B harden\-short\-bufsize: \fI<yes or no>\fP
|
||||
Very small EDNS buffer sizes from queries are ignored.
|
||||
Very small EDNS buffer sizes from queries are ignored and are instead
|
||||
set to the normal UDP packet size (512 bytes).
|
||||
.sp
|
||||
Default: yes (per \fI\%RFC 6891\fP)
|
||||
.UNINDENT
|
||||
@@ -2078,6 +2079,7 @@ Default: yes (per \fI\%RFC 6891\fP)
|
||||
.TP
|
||||
.B harden\-large\-queries: \fI<yes or no>\fP
|
||||
Very large queries are ignored.
|
||||
The cutoff value is chosen to be the normal UDP packet size (512 bytes).
|
||||
Default is no, since it is legal protocol wise to send these, and could be
|
||||
necessary for operation if TSIG or EDNS payload is very large.
|
||||
.sp
|
||||
@@ -2201,6 +2203,18 @@ Default: no
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B harden\-cname\-follow: \fI<yes or no>\fP
|
||||
Harden CNAME redirections by following them.
|
||||
If no, then upstream CNAME and DNAME redirections are allowed in a
|
||||
response without checking with further messages if those are valid.
|
||||
It can only really be disabled safely on localhost net or encrypted
|
||||
connectivity.
|
||||
Default is on to protect the cache integrity.
|
||||
.sp
|
||||
Default: yes
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B use\-caps\-for\-id: \fI<yes or no>\fP
|
||||
Use 0x20\-encoded random bits in the query to foil spoof attempts.
|
||||
This perturbs the lowercase and uppercase of query names sent to authority
|
||||
@@ -2312,6 +2326,13 @@ The defensive action is to clear the rrset and message caches, hopefully
|
||||
flushing away any poison.
|
||||
A value of 10 million is suggested.
|
||||
.sp
|
||||
It is useful to add 0.0.0.0/8 and \(aq::\(aq to the
|
||||
\fI\%do\-not\-query\-address\fP list.
|
||||
Otherwise they may be answered, from localhost, and the different source
|
||||
makes an unwanted reply that unnecessarily ticks up.
|
||||
The \fI\%do\-not\-query\-localhost\fP
|
||||
option includes them, the zero subnets, when it is enabled.
|
||||
.sp
|
||||
Default: 0 (disabled)
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
@@ -2329,7 +2350,10 @@ Default: (none)
|
||||
.B do\-not\-query\-localhost: \fI<yes or no>\fP
|
||||
If yes, localhost is added to the
|
||||
\fI\%do\-not\-query\-address\fP entries,
|
||||
both IPv6 \fB::1\fP and IPv4 \fB127.0.0.1/8\fP\&.
|
||||
both IPv4 \fB127.0.0.1/8\fP (also \fB::ffff:127.0.0.0/104\fP) and IPv6 \fB::1\fP\&.
|
||||
Additionally, the zero subnets \fB0.0.0.0/8\fP (also \fB::ffff:0:0/96\fP) and
|
||||
\fB::\fP are added to the list since on some systems they route to
|
||||
localhost as well.
|
||||
If no, then localhost can be used to send queries to.
|
||||
.sp
|
||||
Default: yes
|
||||
@@ -2362,6 +2386,8 @@ If yes, deny queries of type ANY with an empty response.
|
||||
If disabled, Unbound responds with a short list of resource records if some
|
||||
can be found in the cache and makes the upstream type ANY query if there
|
||||
are none.
|
||||
The option stops the DNSSEC validation from processing, possibly lengthy,
|
||||
ANY responses, when the option is enabled.
|
||||
.sp
|
||||
Default: no
|
||||
.UNINDENT
|
||||
@@ -2495,6 +2521,9 @@ Format is BIND\-9 style format, the \fBtrusted\-keys { name flag proto algo
|
||||
It is possible to use wildcards with this statement, the wildcard is
|
||||
expanded on start and on reload.
|
||||
.sp
|
||||
A wildcard that matches no files is not an error: the entry loads no
|
||||
trust anchors, and the condition is logged at operational verbosity.
|
||||
.sp
|
||||
Default: \(dq\(dq (no trusted keys file)
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
@@ -2604,7 +2633,7 @@ affected.
|
||||
Use this setting to protect the users that rely on this validator for
|
||||
authentication from potentially bad data in the additional section.
|
||||
.sp
|
||||
Default: yes
|
||||
Default: no
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
@@ -2910,6 +2939,9 @@ The types are
|
||||
\fI\%inform_redirect\fP,
|
||||
\fI\%always_transparent\fP,
|
||||
\fI\%block_a\fP,
|
||||
\fI\%block_aaaa\fP,
|
||||
\fI\%block_a_wdata\fP,
|
||||
\fI\%block_aaaa_wdata\fP,
|
||||
\fI\%always_refuse\fP,
|
||||
\fI\%always_nxdomain\fP,
|
||||
\fI\%always_null\fP,
|
||||
@@ -3100,6 +3132,32 @@ use IPv6 protocol and avoid any queries to IPv4.
|
||||
.UNINDENT
|
||||
.INDENT 7.0
|
||||
.TP
|
||||
.B block_aaaa
|
||||
Like \fI\%transparent\fP or
|
||||
\fI\%block_a\fP, but
|
||||
ignores local data and resolves normally all query types excluding AAAA.
|
||||
For AAAA queries it unconditionally returns NODATA.
|
||||
Useful in cases when there is a need to explicitly force all apps to
|
||||
use IPv4 protocol and avoid any queries to IPv6.
|
||||
.UNINDENT
|
||||
.INDENT 7.0
|
||||
.TP
|
||||
.B block_a_wdata
|
||||
Like \fI\%block_a\fP, but
|
||||
uses local data if present.
|
||||
If there is local data that is returned, and it acts like transparent.
|
||||
For A queries it returns NODATA.
|
||||
.UNINDENT
|
||||
.INDENT 7.0
|
||||
.TP
|
||||
.B block_aaaa_wdata
|
||||
Like \fI\%block_aaaa\fP, but
|
||||
uses local data if present.
|
||||
If there is local data that is returned, and it acts like transparent.
|
||||
For AAAA queries it returns NODATA.
|
||||
.UNINDENT
|
||||
.INDENT 7.0
|
||||
.TP
|
||||
.B always_refuse
|
||||
Like \fI\%refuse\fP, but ignores
|
||||
local data and refuses the query.
|
||||
@@ -3567,6 +3625,18 @@ For example, 1000 may be a suitable value to stop the server from being
|
||||
overloaded with random names, and keeps unbound from sending traffic to the
|
||||
nameservers for those zones.
|
||||
.sp
|
||||
It is intended to count the number of queries towards the nameservers
|
||||
for the zone, and keep those queries limited.
|
||||
When there is a delegation that needs a lot of lookups, those are
|
||||
charged in the counters for the destination, the target name, of
|
||||
the NS records.
|
||||
Since that is where the nameserver lookup queries are sent to.
|
||||
That keeps the target, the victim domain, from having many queries.
|
||||
With the \fI\%ratelimit\-factor\fP, some
|
||||
genuine queries that are also made to the target zone, can filter
|
||||
through, and then end up in cache, where the genuine answers have
|
||||
a chance to collect, keeping up service to some extent.
|
||||
.sp
|
||||
\fBNOTE:\fP
|
||||
.INDENT 7.0
|
||||
.INDENT 3.5
|
||||
@@ -3829,6 +3899,28 @@ Default: yes
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B val\-validation\-attempts: \fI<number>\fP
|
||||
Limit on the number of DNSSEC validation attempts for a query.
|
||||
This protects against too large numbers of cryptographic operations,
|
||||
like for a deep delegation chain.
|
||||
This counts attempts to validate RRSIGs.
|
||||
When it is exceeded, the query fails.
|
||||
.sp
|
||||
Default: 32
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B val\-hash\-attempts: \fI<number>\fP
|
||||
Limit on the number of DNSSEC hash attempts for a query.
|
||||
This protects against too large numbers of cryptographic operations,
|
||||
like for a deep delegation chain.
|
||||
This counts DS hash attempts to match DNSKEYs.
|
||||
When it is exceeded, the query fails.
|
||||
.sp
|
||||
Default: 32
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B fast\-server\-permil: \fI<number>\fP
|
||||
Specify how many times out of 1000 to pick from the set of fastest servers.
|
||||
0 turns the feature off.
|
||||
@@ -4594,6 +4686,32 @@ If not given then no zonefile is used.
|
||||
If the file does not exist or is empty, Unbound will attempt to fetch zone
|
||||
data (eg. from the primary servers).
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B max\-transfer\-size: \fI<number>\fP
|
||||
Number of bytes size of the maximum zone transfer size.
|
||||
Larger transfers, over AXFR, IXFR and HTTP, are not allowed.
|
||||
A plain number is in bytes, append \(aqk\(aq, \(aqm\(aq or \(aqg\(aq for kilobytes, megabytes
|
||||
or gigabytes (1024*1024 bytes in a megabyte).
|
||||
The value \fB0\fP disables the feature.
|
||||
.sp
|
||||
Only consider for untrusted/misbehaving primaries that could hog resources
|
||||
and bring down the resolver.
|
||||
.sp
|
||||
Default: 0
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B max\-transfer\-time: \fI<msec>\fP
|
||||
Maximum time in milliseconds that a zone transfer is allowed to take from
|
||||
the start.
|
||||
The value \fB0\fP disables the feature.
|
||||
.sp
|
||||
Only consider for untrusted/misbehaving primaries that could hog resources
|
||||
and bring down the resolver.
|
||||
.sp
|
||||
Default: 0
|
||||
.UNINDENT
|
||||
.SH VIEW OPTIONS
|
||||
.sp
|
||||
These options are part of the \fBview:\fP section.
|
||||
@@ -5806,6 +5924,10 @@ from a webserver that would work.
|
||||
If you specify the hostname, you cannot use the domain from the zonefile,
|
||||
because it may not have that when retrieving that data, instead use a plain
|
||||
IP address to avoid a circular dependency on retrieving that IP address.
|
||||
.sp
|
||||
Every number of IXFR transfers, a full AXFR is performed.
|
||||
This is to consolidate the rpz memory, that would otherwise grow.
|
||||
The fixed value is after 5 IXFR transfers.
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
@@ -5928,6 +6050,32 @@ Enclose list of tags in quotes (\fB\(dq\(dq\fP) and put spaces between tags.
|
||||
If no tags are specified the policies from this section will be applied for
|
||||
all clients.
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B max\-transfer\-size: \fI<number>\fP
|
||||
Number of bytes size of the maximum zone transfer size.
|
||||
Larger transfers, over AXFR, IXFR and HTTP, are not allowed.
|
||||
A plain number is in bytes, append \(aqk\(aq, \(aqm\(aq or \(aqg\(aq for kilobytes, megabytes
|
||||
or gigabytes (1024*1024 bytes in a megabyte).
|
||||
The value \fB0\fP disables the feature.
|
||||
.sp
|
||||
Only consider for untrusted/misbehaving primaries that could hog resources
|
||||
and bring down the resolver.
|
||||
.sp
|
||||
Default: 0
|
||||
.UNINDENT
|
||||
.INDENT 0.0
|
||||
.TP
|
||||
.B max\-transfer\-time: \fI<msec>\fP
|
||||
Maximum time in milliseconds that a zone transfer is allowed to take from
|
||||
the start.
|
||||
The value \fB0\fP disables the feature.
|
||||
.sp
|
||||
Only consider for untrusted/misbehaving primaries that could hog resources
|
||||
and bring down the resolver.
|
||||
.sp
|
||||
Default: 0
|
||||
.UNINDENT
|
||||
.SH MEMORY CONTROL EXAMPLE
|
||||
.sp
|
||||
In the example config settings below memory usage is reduced.
|
||||
|
||||
+152
-4
@@ -642,7 +642,7 @@ These options are part of the ``server:`` section.
|
||||
|
||||
@@UAHL@unbound.conf@so-sndbuf@@: *<number>*
|
||||
If not 0, then set the SO_SNDBUF socket option to get more buffer space on
|
||||
UDP port 53 outgoing queries.
|
||||
UDP port 53 outgoing responses.
|
||||
This for very busy servers handles spikes in answer traffic, otherwise:
|
||||
|
||||
.. code-block:: text
|
||||
@@ -1838,13 +1838,15 @@ These options are part of the ``server:`` section.
|
||||
|
||||
|
||||
@@UAHL@unbound.conf@harden-short-bufsize@@: *<yes or no>*
|
||||
Very small EDNS buffer sizes from queries are ignored.
|
||||
Very small EDNS buffer sizes from queries are ignored and are instead
|
||||
set to the normal UDP packet size (512 bytes).
|
||||
|
||||
Default: yes (per :rfc:`6891`)
|
||||
|
||||
|
||||
@@UAHL@unbound.conf@harden-large-queries@@: *<yes or no>*
|
||||
Very large queries are ignored.
|
||||
The cutoff value is chosen to be the normal UDP packet size (512 bytes).
|
||||
Default is no, since it is legal protocol wise to send these, and could be
|
||||
necessary for operation if TSIG or EDNS payload is very large.
|
||||
|
||||
@@ -1952,6 +1954,17 @@ These options are part of the ``server:`` section.
|
||||
Default: no
|
||||
|
||||
|
||||
@@UAHL@unbound.conf@harden-cname-follow@@: *<yes or no>*
|
||||
Harden CNAME redirections by following them.
|
||||
If no, then upstream CNAME and DNAME redirections are allowed in a
|
||||
response without checking with further messages if those are valid.
|
||||
It can only really be disabled safely on localhost net or encrypted
|
||||
connectivity.
|
||||
Default is on to protect the cache integrity.
|
||||
|
||||
Default: yes
|
||||
|
||||
|
||||
@@UAHL@unbound.conf@use-caps-for-id@@: *<yes or no>*
|
||||
Use 0x20-encoded random bits in the query to foil spoof attempts.
|
||||
This perturbs the lowercase and uppercase of query names sent to authority
|
||||
@@ -2077,7 +2090,10 @@ These options are part of the ``server:`` section.
|
||||
@@UAHL@unbound.conf@do-not-query-localhost@@: *<yes or no>*
|
||||
If yes, localhost is added to the
|
||||
:ref:`do-not-query-address<unbound.conf.do-not-query-address>` entries,
|
||||
both IPv6 ``::1`` and IPv4 ``127.0.0.1/8``.
|
||||
both IPv4 ``127.0.0.1/8`` (also ``::ffff:127.0.0.0/104``) and IPv6 ``::1``.
|
||||
Additionally, the zero subnets ``0.0.0.0/8`` (also ``::ffff:0:0/96``) and
|
||||
``::`` are added to the list since on some systems they route to
|
||||
localhost as well.
|
||||
If no, then localhost can be used to send queries to.
|
||||
|
||||
Default: yes
|
||||
@@ -2107,6 +2123,8 @@ These options are part of the ``server:`` section.
|
||||
If disabled, Unbound responds with a short list of resource records if some
|
||||
can be found in the cache and makes the upstream type ANY query if there
|
||||
are none.
|
||||
The option stops the DNSSEC validation from processing, possibly lengthy,
|
||||
ANY responses, when the option is enabled.
|
||||
|
||||
Default: no
|
||||
|
||||
@@ -2224,6 +2242,9 @@ These options are part of the ``server:`` section.
|
||||
It is possible to use wildcards with this statement, the wildcard is
|
||||
expanded on start and on reload.
|
||||
|
||||
A wildcard that matches no files is not an error: the entry loads no
|
||||
trust anchors, and the condition is logged at operational verbosity.
|
||||
|
||||
Default: "" (no trusted keys file)
|
||||
|
||||
|
||||
@@ -2318,7 +2339,7 @@ These options are part of the ``server:`` section.
|
||||
Use this setting to protect the users that rely on this validator for
|
||||
authentication from potentially bad data in the additional section.
|
||||
|
||||
Default: yes
|
||||
Default: no
|
||||
|
||||
|
||||
@@UAHL@unbound.conf@val-log-level@@: *<number>*
|
||||
@@ -2590,6 +2611,9 @@ These options are part of the ``server:`` section.
|
||||
:ref:`inform_redirect<unbound.conf.local-zone.type.inform_redirect>`,
|
||||
:ref:`always_transparent<unbound.conf.local-zone.type.always_transparent>`,
|
||||
:ref:`block_a<unbound.conf.local-zone.type.block_a>`,
|
||||
:ref:`block_aaaa<unbound.conf.local-zone.type.block_aaaa>`,
|
||||
:ref:`block_a_wdata<unbound.conf.local-zone.type.block_a_wdata>`,
|
||||
:ref:`block_aaaa_wdata<unbound.conf.local-zone.type.block_aaaa_wdata>`,
|
||||
:ref:`always_refuse<unbound.conf.local-zone.type.always_refuse>`,
|
||||
:ref:`always_nxdomain<unbound.conf.local-zone.type.always_nxdomain>`,
|
||||
:ref:`always_null<unbound.conf.local-zone.type.always_null>`,
|
||||
@@ -2739,6 +2763,26 @@ These options are part of the ``server:`` section.
|
||||
Useful in cases when there is a need to explicitly force all apps to
|
||||
use IPv6 protocol and avoid any queries to IPv4.
|
||||
|
||||
@@UAHL@unbound.conf.local-zone.type@block_aaaa@@
|
||||
Like :ref:`transparent<unbound.conf.local-zone.type.transparent>` or
|
||||
:ref:`block_a<unbound.conf.local-zone.type.block_a>`, but
|
||||
ignores local data and resolves normally all query types excluding AAAA.
|
||||
For AAAA queries it unconditionally returns NODATA.
|
||||
Useful in cases when there is a need to explicitly force all apps to
|
||||
use IPv4 protocol and avoid any queries to IPv6.
|
||||
|
||||
@@UAHL@unbound.conf.local-zone.type@block_a_wdata@@
|
||||
Like :ref:`block_a<unbound.conf.local-zone.type.block_a>`, but
|
||||
uses local data if present.
|
||||
If there is local data that is returned, and it acts like transparent.
|
||||
For A queries it returns NODATA.
|
||||
|
||||
@@UAHL@unbound.conf.local-zone.type@block_aaaa_wdata@@
|
||||
Like :ref:`block_aaaa<unbound.conf.local-zone.type.block_aaaa>`, but
|
||||
uses local data if present.
|
||||
If there is local data that is returned, and it acts like transparent.
|
||||
For AAAA queries it returns NODATA.
|
||||
|
||||
@@UAHL@unbound.conf.local-zone.type@always_refuse@@
|
||||
Like :ref:`refuse<unbound.conf.local-zone.type.refuse>`, but ignores
|
||||
local data and refuses the query.
|
||||
@@ -3085,6 +3129,18 @@ These options are part of the ``server:`` section.
|
||||
overloaded with random names, and keeps unbound from sending traffic to the
|
||||
nameservers for those zones.
|
||||
|
||||
It is intended to count the number of queries towards the nameservers
|
||||
for the zone, and keep those queries limited.
|
||||
When there is a delegation that needs a lot of lookups, those are
|
||||
charged in the counters for the destination, the target name, of
|
||||
the NS records.
|
||||
Since that is where the nameserver lookup queries are sent to.
|
||||
That keeps the target, the victim domain, from having many queries.
|
||||
With the :ref:`ratelimit-factor<unbound.conf.ratelimit-factor>`, some
|
||||
genuine queries that are also made to the target zone, can filter
|
||||
through, and then end up in cache, where the genuine answers have
|
||||
a chance to collect, keeping up service to some extent.
|
||||
|
||||
.. note:: Configured forwarders are excluded from ratelimiting.
|
||||
|
||||
Default: 0
|
||||
@@ -3321,6 +3377,26 @@ These options are part of the ``server:`` section.
|
||||
Default: yes
|
||||
|
||||
|
||||
@@UAHL@unbound.conf@val-validation-attempts@@: *<number>*
|
||||
Limit on the number of DNSSEC validation attempts for a query.
|
||||
This protects against too large numbers of cryptographic operations,
|
||||
like for a deep delegation chain.
|
||||
This counts attempts to validate RRSIGs.
|
||||
When it is exceeded, the query fails.
|
||||
|
||||
Default: 32
|
||||
|
||||
|
||||
@@UAHL@unbound.conf@val-hash-attempts@@: *<number>*
|
||||
Limit on the number of DNSSEC hash attempts for a query.
|
||||
This protects against too large numbers of cryptographic operations,
|
||||
like for a deep delegation chain.
|
||||
This counts DS hash attempts to match DNSKEYs.
|
||||
When it is exceeded, the query fails.
|
||||
|
||||
Default: 32
|
||||
|
||||
|
||||
@@UAHL@unbound.conf@fast-server-permil@@: *<number>*
|
||||
Specify how many times out of 1000 to pick from the set of fastest servers.
|
||||
0 turns the feature off.
|
||||
@@ -3444,6 +3520,24 @@ These options are part of the ``server:`` section.
|
||||
|
||||
Default: no
|
||||
|
||||
|
||||
@@UAHL@unbound.conf@auth-task-threads@@: *<number of threads>*
|
||||
If nonzero, the number of threads to start to process zone transfers
|
||||
for authority zones, and also RPZ zones.
|
||||
The zone transfer is processed in a thread, that does not interrupt
|
||||
the resolver.
|
||||
For RPZ zones that means the old RPZ zone continues to be used, while
|
||||
the task is processed.
|
||||
The thread allocates the new zone data, and this keeps another copy of
|
||||
the zone data in memory during processing.
|
||||
The result is swapped into the resolver when the thread is done.
|
||||
|
||||
The value 0 disables the threading, one of the worker threads performs
|
||||
the processing. Without threading enabled, use the value 0.
|
||||
|
||||
Default: 0
|
||||
|
||||
|
||||
.. _unbound.conf.remote:
|
||||
|
||||
Remote Control Options
|
||||
@@ -4018,6 +4112,31 @@ fallback activates to fetch from the upstream instead of the SERVFAIL.
|
||||
If the file does not exist or is empty, Unbound will attempt to fetch zone
|
||||
data (eg. from the primary servers).
|
||||
|
||||
|
||||
@@UAHL@unbound.conf.auth@max-transfer-size@@: *<number>*
|
||||
Number of bytes size of the maximum zone transfer size.
|
||||
Larger transfers, over AXFR, IXFR and HTTP, are not allowed.
|
||||
A plain number is in bytes, append 'k', 'm' or 'g' for kilobytes, megabytes
|
||||
or gigabytes (1024*1024 bytes in a megabyte).
|
||||
The value ``0`` disables the feature.
|
||||
|
||||
Only consider for untrusted/misbehaving primaries that could hog resources
|
||||
and bring down the resolver.
|
||||
|
||||
Default: 0
|
||||
|
||||
|
||||
@@UAHL@unbound.conf.auth@max-transfer-time@@: *<msec>*
|
||||
Maximum time in milliseconds that a zone transfer is allowed to take from
|
||||
the start.
|
||||
The value ``0`` disables the feature.
|
||||
|
||||
Only consider for untrusted/misbehaving primaries that could hog resources
|
||||
and bring down the resolver.
|
||||
|
||||
Default: 0
|
||||
|
||||
|
||||
.. _unbound.conf.view:
|
||||
|
||||
View Options
|
||||
@@ -5098,6 +5217,10 @@ answer queries with that content.
|
||||
because it may not have that when retrieving that data, instead use a plain
|
||||
IP address to avoid a circular dependency on retrieving that IP address.
|
||||
|
||||
Every number of IXFR transfers, a full AXFR is performed.
|
||||
This is to consolidate the rpz memory, that would otherwise grow.
|
||||
The fixed value is after 5 IXFR transfers.
|
||||
|
||||
|
||||
@@UAHL@unbound.conf.rpz@master@@: *<IP address or host name>*
|
||||
Alternate syntax for :ref:`primary<unbound.conf.rpz.primary>`.
|
||||
@@ -5198,6 +5321,31 @@ answer queries with that content.
|
||||
If no tags are specified the policies from this section will be applied for
|
||||
all clients.
|
||||
|
||||
|
||||
@@UAHL@unbound.conf.rpz@max-transfer-size@@: *<number>*
|
||||
Number of bytes size of the maximum zone transfer size.
|
||||
Larger transfers, over AXFR, IXFR and HTTP, are not allowed.
|
||||
A plain number is in bytes, append 'k', 'm' or 'g' for kilobytes, megabytes
|
||||
or gigabytes (1024*1024 bytes in a megabyte).
|
||||
The value ``0`` disables the feature.
|
||||
|
||||
Only consider for untrusted/misbehaving primaries that could hog resources
|
||||
and bring down the resolver.
|
||||
|
||||
Default: 0
|
||||
|
||||
|
||||
@@UAHL@unbound.conf.rpz@max-transfer-time@@: *<msec>*
|
||||
Maximum time in milliseconds that a zone transfer is allowed to take from
|
||||
the start.
|
||||
The value ``0`` disables the feature.
|
||||
|
||||
Only consider for untrusted/misbehaving primaries that could hog resources
|
||||
and bring down the resolver.
|
||||
|
||||
Default: 0
|
||||
|
||||
|
||||
Memory Control Example
|
||||
----------------------
|
||||
|
||||
|
||||
@@ -459,6 +459,7 @@ addrtree_insert(struct addrtree *tree, const addrkey_t *addr,
|
||||
/* Data is stored in other leafnode */
|
||||
node = newnode;
|
||||
newnode = node_create(tree, elem, scope, ttl);
|
||||
if (!newnode) return;
|
||||
if (!edge_create(newnode, addr, sourcemask, node,
|
||||
index^1)) {
|
||||
clean_node(tree, newnode);
|
||||
|
||||
@@ -1015,6 +1015,7 @@ subnetmod_operate(struct module_qstate *qstate, enum module_ev event,
|
||||
subnet_ecs_opt_list_append(&sq->ecs_client_out,
|
||||
&qstate->edns_opts_front_out, qstate,
|
||||
qstate->region);
|
||||
qstate->is_subnet_answer = 1;
|
||||
}
|
||||
sq->wait_subquery_done = 0;
|
||||
qstate->ext_state[id] = module_finished;
|
||||
@@ -1094,6 +1095,7 @@ subnetmod_operate(struct module_qstate *qstate, enum module_ev event,
|
||||
qstate->env->cfg->prefetch)) {
|
||||
sne->num_msg_cache++;
|
||||
lock_rw_unlock(&sne->biglock);
|
||||
qstate->is_subnet_answer = 1;
|
||||
verbose(VERB_QUERY, "subnetcache: answered from cache");
|
||||
qstate->ext_state[id] = module_finished;
|
||||
|
||||
@@ -1165,6 +1167,8 @@ subnetmod_operate(struct module_qstate *qstate, enum module_ev event,
|
||||
subnet_ecs_opt_list_append(&sq->ecs_client_out,
|
||||
&qstate->edns_opts_front_out, qstate,
|
||||
qstate->region);
|
||||
if(sq->subnet_sent || sq->subnet_sent_no_subnet)
|
||||
qstate->is_subnet_answer = 1;
|
||||
if(verbosity >= VERB_ALGO) {
|
||||
subnet_log_print("reply has edns subnet",
|
||||
edns_opt_list_find(
|
||||
|
||||
@@ -100,6 +100,8 @@ ipsecmod_whitelist_apply_cfg(struct ipsecmod_env* ie,
|
||||
struct config_file* cfg)
|
||||
{
|
||||
ie->whitelist = rbtree_create(name_tree_compare);
|
||||
if (!ie->whitelist)
|
||||
return 0;
|
||||
if(!read_whitelist(ie->whitelist, cfg))
|
||||
return 0;
|
||||
name_tree_init_parents(ie->whitelist);
|
||||
|
||||
+91
-37
@@ -51,18 +51,28 @@
|
||||
#include "util/config_file.h"
|
||||
#include "services/cache/dns.h"
|
||||
#include "sldns/wire2str.h"
|
||||
#ifdef HAVE_SYS_WAIT_H
|
||||
#include <sys/wait.h>
|
||||
#endif
|
||||
|
||||
/** Apply configuration to ipsecmod module 'global' state. */
|
||||
static int
|
||||
ipsecmod_apply_cfg(struct ipsecmod_env* ipsecmod_env, struct config_file* cfg)
|
||||
{
|
||||
if(cfg->ipsecmod_whitelist &&
|
||||
!ipsecmod_whitelist_apply_cfg(ipsecmod_env, cfg))
|
||||
return 0;
|
||||
if(!cfg->ipsecmod_enabled)
|
||||
return 1;
|
||||
if(!cfg->ipsecmod_hook || (cfg->ipsecmod_hook && !cfg->ipsecmod_hook[0])) {
|
||||
log_err("ipsecmod: missing ipsecmod-hook.");
|
||||
return 0;
|
||||
}
|
||||
if(cfg->ipsecmod_whitelist &&
|
||||
!ipsecmod_whitelist_apply_cfg(ipsecmod_env, cfg))
|
||||
if(access(cfg->ipsecmod_hook, X_OK) != 0) {
|
||||
log_err("ipsecmod: ipsecmod-hook '%s' is not an executable file: %s",
|
||||
cfg->ipsecmod_hook, strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -250,27 +260,16 @@ call_hook(struct module_qstate* qstate, struct ipsecmod_qstate* iq,
|
||||
struct ipsecmod_env* ATTR_UNUSED(ie))
|
||||
{
|
||||
size_t slen, tempdata_len, tempstring_len, i;
|
||||
char str[65535], *s, *tempstring;
|
||||
char qname_s[LDNS_MAX_DOMAINLEN*5+16], ttl_s[32], a_s[32768], k_s[32768];
|
||||
char *s, *tempstring;
|
||||
int w = 0, w_temp, qtype;
|
||||
struct ub_packed_rrset_key* rrset_key;
|
||||
struct packed_rrset_data* rrset_data;
|
||||
uint8_t *tempdata;
|
||||
pid_t pid;
|
||||
int st;
|
||||
char* argv[6];
|
||||
|
||||
/* Check if a shell is available */
|
||||
if(system(NULL) == 0) {
|
||||
log_err("ipsecmod: no shell available for ipsecmod-hook");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Zero the buffer. */
|
||||
s = str;
|
||||
slen = sizeof(str);
|
||||
memset(s, 0, slen);
|
||||
|
||||
/* Copy the hook into the buffer. */
|
||||
w += sldns_str_print(&s, &slen, "%s", qstate->env->cfg->ipsecmod_hook);
|
||||
/* Put space into the buffer. */
|
||||
w += sldns_str_print(&s, &slen, " ");
|
||||
/* Copy the qname into the buffer. */
|
||||
tempstring = sldns_wire2str_dname(qstate->qinfo.qname,
|
||||
qstate->qinfo.qname_len);
|
||||
@@ -283,17 +282,24 @@ call_hook(struct module_qstate* qstate, struct ipsecmod_qstate* iq,
|
||||
free(tempstring);
|
||||
return 0;
|
||||
}
|
||||
w += sldns_str_print(&s, &slen, "\"%s\"", tempstring);
|
||||
if(strlen(tempstring)+1 > sizeof(qname_s)) {
|
||||
log_err("ipsecmod: string too long");
|
||||
free(tempstring);
|
||||
return 0;
|
||||
}
|
||||
snprintf(qname_s, sizeof(qname_s), "%s", tempstring);
|
||||
free(tempstring);
|
||||
/* Put space into the buffer. */
|
||||
w += sldns_str_print(&s, &slen, " ");
|
||||
|
||||
/* Copy the IPSECKEY TTL into the buffer. */
|
||||
rrset_data = (struct packed_rrset_data*)iq->ipseckey_rrset->entry.data;
|
||||
w += sldns_str_print(&s, &slen, "\"%ld\"", (long)rrset_data->ttl);
|
||||
/* Put space into the buffer. */
|
||||
w += sldns_str_print(&s, &slen, " ");
|
||||
snprintf(ttl_s, sizeof(ttl_s), "%ld", (long)rrset_data->ttl);
|
||||
|
||||
rrset_key = reply_find_answer_rrset(&qstate->return_msg->qinfo,
|
||||
qstate->return_msg->rep);
|
||||
if(!rrset_key) {
|
||||
log_err("ipsecmod: could not find answer rrset for A/AAAA");
|
||||
return 0;
|
||||
}
|
||||
/* Double check that the records are indeed A/AAAA.
|
||||
* This should never happen as this function is only executed for A/AAAA
|
||||
* queries but make sure we don't pass anything other than A/AAAA to the
|
||||
@@ -304,9 +310,15 @@ call_hook(struct module_qstate* qstate, struct ipsecmod_qstate* iq,
|
||||
return 0;
|
||||
}
|
||||
rrset_data = (struct packed_rrset_data*)rrset_key->entry.data;
|
||||
/* Copy the A/AAAA record(s) into the buffer. Start and end this section
|
||||
* with a double quote. */
|
||||
w += sldns_str_print(&s, &slen, "\"");
|
||||
if(!rrset_data) {
|
||||
log_err("ipsecmod: Answer has no data");
|
||||
return 0;
|
||||
}
|
||||
/* Copy the A/AAAA record(s) into the buffer. */
|
||||
w = 0;
|
||||
s = a_s;
|
||||
slen = sizeof(a_s);
|
||||
memset(s, 0, slen);
|
||||
for(i=0; i<rrset_data->count; i++) {
|
||||
if(i > 0) {
|
||||
/* Put space into the buffer. */
|
||||
@@ -322,7 +334,7 @@ call_hook(struct module_qstate* qstate, struct ipsecmod_qstate* iq,
|
||||
} else if((size_t)w_temp >= slen) {
|
||||
s = NULL; /* We do not want str to point outside of buffer. */
|
||||
slen = 0;
|
||||
log_err("ipsecmod: shell command too long");
|
||||
log_err("ipsecmod: command addr argument too long");
|
||||
return 0;
|
||||
} else {
|
||||
s += w_temp;
|
||||
@@ -330,12 +342,17 @@ call_hook(struct module_qstate* qstate, struct ipsecmod_qstate* iq,
|
||||
w += w_temp;
|
||||
}
|
||||
}
|
||||
w += sldns_str_print(&s, &slen, "\"");
|
||||
/* Put space into the buffer. */
|
||||
w += sldns_str_print(&s, &slen, " ");
|
||||
if(w >= (int)sizeof(a_s)) {
|
||||
log_err("ipsecmod: command addr argument too long");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Copy the IPSECKEY record(s) into the buffer. Start and end this section
|
||||
* with a double quote. */
|
||||
w += sldns_str_print(&s, &slen, "\"");
|
||||
w = 0;
|
||||
s = k_s;
|
||||
slen = sizeof(k_s);
|
||||
memset(s, 0, slen);
|
||||
rrset_data = (struct packed_rrset_data*)iq->ipseckey_rrset->entry.data;
|
||||
for(i=0; i<rrset_data->count; i++) {
|
||||
if(i > 0) {
|
||||
@@ -362,15 +379,44 @@ call_hook(struct module_qstate* qstate, struct ipsecmod_qstate* iq,
|
||||
w += w_temp;
|
||||
}
|
||||
}
|
||||
w += sldns_str_print(&s, &slen, "\"");
|
||||
if(w >= (int)sizeof(str)) {
|
||||
log_err("ipsecmod: shell command too long");
|
||||
if(w >= (int)sizeof(k_s)) {
|
||||
log_err("ipsecmod: command ipseckey argument too long");
|
||||
return 0;
|
||||
}
|
||||
verbose(VERB_ALGO, "ipsecmod: shell command: '%s'", str);
|
||||
|
||||
/* ipsecmod-hook should return 0 on success. */
|
||||
if(system(str) != 0)
|
||||
/* exec the ipsecmod-hook */
|
||||
argv[0] = qstate->env->cfg->ipsecmod_hook;
|
||||
argv[1] = qname_s;
|
||||
argv[2] = ttl_s;
|
||||
argv[3] = a_s;
|
||||
argv[4] = k_s;
|
||||
argv[5] = NULL;
|
||||
verbose(VERB_ALGO, "ipsecmod: exec %s \"%s\" %s \"%s\" \"%s\"",
|
||||
argv[0], argv[1], argv[2], argv[3], argv[4]);
|
||||
if((pid = fork()) < 0) {
|
||||
log_err("ipsecmod: for exec, can not fork: %s",
|
||||
strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
if(pid == 0) {
|
||||
if(execv(argv[0], argv) < 0)
|
||||
fprintf(stderr, "ipsecmod: execv: %s\n",
|
||||
strerror(errno));
|
||||
_exit(127);
|
||||
}
|
||||
while(1) {
|
||||
if(waitpid(pid, &st, 0) < 0) {
|
||||
if(errno == EINTR)
|
||||
continue;
|
||||
log_err("ipsecmod: wait_pid: %s", strerror(errno));
|
||||
}
|
||||
break;
|
||||
}
|
||||
if(!(WIFEXITED(st) && WEXITSTATUS(st) == 0)) {
|
||||
/* the command failed */
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -435,6 +481,12 @@ ipsecmod_handle_query(struct module_qstate* qstate,
|
||||
* ipsecmod_max_ttl. */
|
||||
rrset_key = reply_find_answer_rrset(&qstate->return_msg->qinfo,
|
||||
qstate->return_msg->rep);
|
||||
if(!rrset_key) {
|
||||
log_err("ipsecmod: reply-find-answer failed");
|
||||
errinf(qstate, "ipsecmod: reply-find-answer failed");
|
||||
ipsecmod_error(qstate, id);
|
||||
return;
|
||||
}
|
||||
rrset_data = (struct packed_rrset_data*)rrset_key->entry.data;
|
||||
if(rrset_data->ttl > (time_t)qstate->env->cfg->ipsecmod_max_ttl) {
|
||||
/* Update TTL for rrset to fixed value. */
|
||||
@@ -576,6 +628,8 @@ ipsecmod_inform_super(struct module_qstate* qstate, int id,
|
||||
verbose(VERB_ALGO, "super has no ipsecmod state");
|
||||
return;
|
||||
}
|
||||
if(!siq->enabled)
|
||||
return;
|
||||
|
||||
if(qstate->return_msg) {
|
||||
struct ub_packed_rrset_key* rrset_key = reply_find_answer_rrset(
|
||||
|
||||
+17
-14
@@ -143,7 +143,7 @@ static int add_to_ipset(filter_dev dev, const char *setname, const void *ipaddr,
|
||||
struct nlmsghdr *nlh;
|
||||
struct nfgenmsg *nfg;
|
||||
struct nlattr *nested[2];
|
||||
static char buffer[BUFF_LEN];
|
||||
char buffer[BUFF_LEN];
|
||||
|
||||
if (strlen(setname) >= IPSET_MAXNAMELEN) {
|
||||
errno = ENAMETOOLONG;
|
||||
@@ -208,13 +208,6 @@ ipset_add_rrset_data(struct ipset_env *ie,
|
||||
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);
|
||||
|
||||
#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;
|
||||
}
|
||||
}
|
||||
@@ -226,15 +219,15 @@ ipset_check_zones_for_rrset(struct module_env *env, struct ipset_env *ie,
|
||||
struct ub_packed_rrset_key *rrset, const char *qname, int qlen,
|
||||
const char *setname, int af)
|
||||
{
|
||||
static char dname[BUFF_LEN];
|
||||
char dname[LDNS_MAX_DOMAINLEN*4+16];
|
||||
const char *ds, *qs;
|
||||
int dlen, plen;
|
||||
|
||||
struct config_strlist *p;
|
||||
struct packed_rrset_data *d;
|
||||
|
||||
dlen = sldns_wire2str_dname_buf(rrset->rk.dname, rrset->rk.dname_len, dname, BUFF_LEN);
|
||||
if (dlen == 0) {
|
||||
dlen = sldns_wire2str_dname_buf(rrset->rk.dname, rrset->rk.dname_len, dname, sizeof(dname));
|
||||
if (dlen == 0 || dlen >= (int)sizeof(dname)) {
|
||||
log_err("bad domain name");
|
||||
return -1;
|
||||
}
|
||||
@@ -276,7 +269,7 @@ static int ipset_update(struct module_env *env, struct dns_msg *return_msg,
|
||||
const char *setname;
|
||||
struct ub_packed_rrset_key *rrset;
|
||||
int af;
|
||||
static char qname[BUFF_LEN];
|
||||
char qname[LDNS_MAX_DOMAINLEN*4+16];
|
||||
int qlen;
|
||||
|
||||
#ifdef HAVE_NET_PFVAR_H
|
||||
@@ -292,8 +285,8 @@ static int ipset_update(struct module_env *env, struct dns_msg *return_msg,
|
||||
#endif
|
||||
|
||||
qlen = sldns_wire2str_dname_buf(qinfo.qname, qinfo.qname_len,
|
||||
qname, BUFF_LEN);
|
||||
if(qlen == 0) {
|
||||
qname, sizeof(qname));
|
||||
if(qlen == 0 || qlen >= (int)sizeof(qname)) {
|
||||
log_err("bad domain name");
|
||||
return -1;
|
||||
}
|
||||
@@ -372,6 +365,16 @@ int ipset_init(struct module_env* env, int id) {
|
||||
|
||||
ipset_env->name_v4 = env->cfg->ipset_name_v4;
|
||||
ipset_env->name_v6 = env->cfg->ipset_name_v6;
|
||||
#ifndef HAVE_NET_PFVAR_H
|
||||
if (ipset_env->name_v4 && strlen(ipset_env->name_v4) >= IPSET_MAXNAMELEN) {
|
||||
log_err("ipset: name-v4 exceeds IPSET_MAXNAMELEN (%d)", IPSET_MAXNAMELEN);
|
||||
return 0;
|
||||
}
|
||||
if (ipset_env->name_v6 && strlen(ipset_env->name_v6) >= IPSET_MAXNAMELEN) {
|
||||
log_err("ipset: name-v6 exceeds IPSET_MAXNAMELEN (%d)", IPSET_MAXNAMELEN);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
ipset_env->v4_enabled = !ipset_env->name_v4 || (strlen(ipset_env->name_v4) == 0) ? 0 : 1;
|
||||
ipset_env->v6_enabled = !ipset_env->name_v6 || (strlen(ipset_env->name_v6) == 0) ? 0 : 1;
|
||||
|
||||
+31
-24
@@ -118,10 +118,10 @@ delegpt_add_ns(struct delegpt* dp, struct regional* region, uint8_t* name,
|
||||
sizeof(struct delegpt_ns));
|
||||
if(!ns)
|
||||
return 0;
|
||||
ns->next = dp->nslist;
|
||||
ns->namelen = len;
|
||||
dp->nslist = ns;
|
||||
ns->name = regional_alloc_init(region, name, ns->namelen);
|
||||
if(!ns->name)
|
||||
return 0;
|
||||
ns->cache_lookup_count = 0;
|
||||
ns->resolved = 0;
|
||||
ns->got4 = 0;
|
||||
@@ -137,7 +137,9 @@ delegpt_add_ns(struct delegpt* dp, struct regional* region, uint8_t* name,
|
||||
} else {
|
||||
ns->tls_auth_name = NULL;
|
||||
}
|
||||
return ns->name != 0;
|
||||
ns->next = dp->nslist;
|
||||
dp->nslist = ns;
|
||||
return 1;
|
||||
}
|
||||
|
||||
struct delegpt_ns*
|
||||
@@ -223,11 +225,7 @@ delegpt_add_addr(struct delegpt* dp, struct regional* region,
|
||||
sizeof(struct delegpt_addr));
|
||||
if(!a)
|
||||
return 0;
|
||||
a->next_target = dp->target_list;
|
||||
dp->target_list = a;
|
||||
a->next_result = 0;
|
||||
a->next_usable = dp->usable_list;
|
||||
dp->usable_list = a;
|
||||
memcpy(&a->addr, addr, addrlen);
|
||||
a->addrlen = addrlen;
|
||||
a->attempts = 0;
|
||||
@@ -241,6 +239,10 @@ delegpt_add_addr(struct delegpt* dp, struct regional* region,
|
||||
} else {
|
||||
a->tls_auth_name = NULL;
|
||||
}
|
||||
a->next_target = dp->target_list;
|
||||
dp->target_list = a;
|
||||
a->next_usable = dp->usable_list;
|
||||
dp->usable_list = a;
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -398,30 +400,33 @@ delegpt_count_missing_targets(struct delegpt* dp, int* alllame)
|
||||
|
||||
/** find NS rrset in given list */
|
||||
static struct ub_packed_rrset_key*
|
||||
find_NS(struct reply_info* rep, size_t from, size_t to)
|
||||
find_NS(struct reply_info* rep, size_t from, size_t to, uint16_t qclass)
|
||||
{
|
||||
size_t i;
|
||||
for(i=from; i<to; i++) {
|
||||
if(ntohs(rep->rrsets[i]->rk.type) == LDNS_RR_TYPE_NS)
|
||||
if(ntohs(rep->rrsets[i]->rk.type) == LDNS_RR_TYPE_NS &&
|
||||
ntohs(rep->rrsets[i]->rk.rrset_class) == qclass)
|
||||
return rep->rrsets[i];
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct delegpt*
|
||||
delegpt_from_message(struct dns_msg* msg, struct regional* region)
|
||||
delegpt_from_message(struct dns_msg* msg, struct regional* region, int port)
|
||||
{
|
||||
struct ub_packed_rrset_key* ns_rrset = NULL;
|
||||
struct delegpt* dp;
|
||||
size_t i;
|
||||
/* look for NS records in the authority section... */
|
||||
ns_rrset = find_NS(msg->rep, msg->rep->an_numrrsets,
|
||||
msg->rep->an_numrrsets+msg->rep->ns_numrrsets);
|
||||
msg->rep->an_numrrsets+msg->rep->ns_numrrsets,
|
||||
msg->qinfo.qclass);
|
||||
|
||||
/* In some cases (even legitimate, perfectly legal cases), the
|
||||
* NS set for the "referral" might be in the answer section. */
|
||||
if(!ns_rrset)
|
||||
ns_rrset = find_NS(msg->rep, 0, msg->rep->an_numrrsets);
|
||||
ns_rrset = find_NS(msg->rep, 0, msg->rep->an_numrrsets,
|
||||
msg->qinfo.qclass);
|
||||
|
||||
/* If there was no NS rrset in the authority section, then this
|
||||
* wasn't a referral message. (It might not actually be a
|
||||
@@ -436,7 +441,7 @@ delegpt_from_message(struct dns_msg* msg, struct regional* region)
|
||||
dp->has_parent_side_NS = 1; /* created from message */
|
||||
if(!delegpt_set_name(dp, region, ns_rrset->rk.dname))
|
||||
return NULL;
|
||||
if(!delegpt_rrset_add_ns(dp, region, ns_rrset, 0))
|
||||
if(!delegpt_rrset_add_ns(dp, region, ns_rrset, 0, port))
|
||||
return NULL;
|
||||
|
||||
/* add glue, A and AAAA in answer and additional section */
|
||||
@@ -447,10 +452,12 @@ delegpt_from_message(struct dns_msg* msg, struct regional* region)
|
||||
i < (msg->rep->an_numrrsets+msg->rep->ns_numrrsets))
|
||||
continue;
|
||||
|
||||
if(ntohs(s->rk.type) == LDNS_RR_TYPE_A) {
|
||||
if(ntohs(s->rk.type) == LDNS_RR_TYPE_A &&
|
||||
ntohs(s->rk.rrset_class) == msg->qinfo.qclass) {
|
||||
if(!delegpt_add_rrset_A(dp, region, s, 0, NULL))
|
||||
return NULL;
|
||||
} else if(ntohs(s->rk.type) == LDNS_RR_TYPE_AAAA) {
|
||||
} else if(ntohs(s->rk.type) == LDNS_RR_TYPE_AAAA &&
|
||||
ntohs(s->rk.rrset_class) == msg->qinfo.qclass) {
|
||||
if(!delegpt_add_rrset_AAAA(dp, region, s, 0, NULL))
|
||||
return NULL;
|
||||
}
|
||||
@@ -460,7 +467,7 @@ delegpt_from_message(struct dns_msg* msg, struct regional* region)
|
||||
|
||||
int
|
||||
delegpt_rrset_add_ns(struct delegpt* dp, struct regional* region,
|
||||
struct ub_packed_rrset_key* ns_rrset, uint8_t lame)
|
||||
struct ub_packed_rrset_key* ns_rrset, uint8_t lame, int port)
|
||||
{
|
||||
struct packed_rrset_data* nsdata = (struct packed_rrset_data*)
|
||||
ns_rrset->entry.data;
|
||||
@@ -475,7 +482,7 @@ delegpt_rrset_add_ns(struct delegpt* dp, struct regional* region,
|
||||
continue; /* bad format */
|
||||
/* add rdata of NS (= wirefmt dname), skip rdatalen bytes */
|
||||
if(!delegpt_add_ns(dp, region, nsdata->rr_data[i]+2, lame,
|
||||
NULL, UNBOUND_DNS_PORT))
|
||||
NULL, (port==-1?UNBOUND_DNS_PORT:port)))
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
@@ -534,7 +541,7 @@ delegpt_add_rrset(struct delegpt* dp, struct regional* region,
|
||||
if(!rrset)
|
||||
return 1;
|
||||
if(ntohs(rrset->rk.type) == LDNS_RR_TYPE_NS)
|
||||
return delegpt_rrset_add_ns(dp, region, rrset, lame);
|
||||
return delegpt_rrset_add_ns(dp, region, rrset, lame, -1);
|
||||
else if(ntohs(rrset->rk.type) == LDNS_RR_TYPE_A)
|
||||
return delegpt_add_rrset_A(dp, region, rrset, lame, additions);
|
||||
else if(ntohs(rrset->rk.type) == LDNS_RR_TYPE_AAAA)
|
||||
@@ -659,8 +666,6 @@ int delegpt_add_ns_mlc(struct delegpt* dp, uint8_t* name, uint8_t lame,
|
||||
free(ns);
|
||||
return 0;
|
||||
}
|
||||
ns->next = dp->nslist;
|
||||
dp->nslist = ns;
|
||||
ns->cache_lookup_count = 0;
|
||||
ns->resolved = 0;
|
||||
ns->got4 = 0;
|
||||
@@ -679,6 +684,8 @@ int delegpt_add_ns_mlc(struct delegpt* dp, uint8_t* name, uint8_t lame,
|
||||
} else {
|
||||
ns->tls_auth_name = NULL;
|
||||
}
|
||||
ns->next = dp->nslist;
|
||||
dp->nslist = ns;
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -704,11 +711,7 @@ int delegpt_add_addr_mlc(struct delegpt* dp, struct sockaddr_storage* addr,
|
||||
a = (struct delegpt_addr*)malloc(sizeof(struct delegpt_addr));
|
||||
if(!a)
|
||||
return 0;
|
||||
a->next_target = dp->target_list;
|
||||
dp->target_list = a;
|
||||
a->next_result = 0;
|
||||
a->next_usable = dp->usable_list;
|
||||
dp->usable_list = a;
|
||||
memcpy(&a->addr, addr, addrlen);
|
||||
a->addrlen = addrlen;
|
||||
a->attempts = 0;
|
||||
@@ -724,6 +727,10 @@ int delegpt_add_addr_mlc(struct delegpt* dp, struct sockaddr_storage* addr,
|
||||
} else {
|
||||
a->tls_auth_name = NULL;
|
||||
}
|
||||
a->next_target = dp->target_list;
|
||||
dp->target_list = a;
|
||||
a->next_usable = dp->usable_list;
|
||||
dp->usable_list = a;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -221,10 +221,11 @@ int delegpt_add_ns(struct delegpt* dp, struct regional* regional,
|
||||
* @param regional: where to allocate the info.
|
||||
* @param ns_rrset: NS rrset.
|
||||
* @param lame: rrset is lame, disprefer it.
|
||||
* @param port: port or -1 if not set.
|
||||
* @return 0 on alloc error.
|
||||
*/
|
||||
int delegpt_rrset_add_ns(struct delegpt* dp, struct regional* regional,
|
||||
struct ub_packed_rrset_key* ns_rrset, uint8_t lame);
|
||||
struct ub_packed_rrset_key* ns_rrset, uint8_t lame, int port);
|
||||
|
||||
/**
|
||||
* Add target address to the delegation point.
|
||||
@@ -365,11 +366,12 @@ size_t delegpt_count_targets(struct delegpt* dp);
|
||||
*
|
||||
* @param msg: the dns message, referral.
|
||||
* @param regional: where to allocate delegation point.
|
||||
* @param port: if not -1 specifies a port number.
|
||||
* @return new delegation point or NULL on alloc error, or if the
|
||||
* message was not appropriate.
|
||||
*/
|
||||
struct delegpt* delegpt_from_message(struct dns_msg* msg,
|
||||
struct regional* regional);
|
||||
struct regional* regional, int port);
|
||||
|
||||
/**
|
||||
* Mark negative return in delegation point for specific nameserver.
|
||||
|
||||
@@ -46,6 +46,7 @@
|
||||
#include "services/cache/dns.h"
|
||||
#include "util/net_help.h"
|
||||
#include "util/data/dname.h"
|
||||
#include "util/config_file.h"
|
||||
#include "sldns/rrdef.h"
|
||||
#include "sldns/pkthdr.h"
|
||||
|
||||
@@ -107,7 +108,8 @@ response_type_from_cache(struct dns_msg* msg,
|
||||
enum response_type
|
||||
response_type_from_server(int rdset,
|
||||
struct dns_msg* msg, struct query_info* request, struct delegpt* dp,
|
||||
int* empty_nodata_found)
|
||||
int* empty_nodata_found, int msg_lame_empty, int msg_lame_referral,
|
||||
struct config_file* cfg)
|
||||
{
|
||||
uint8_t* origzone = (uint8_t*)"\000"; /* the default */
|
||||
struct ub_packed_rrset_key* s;
|
||||
@@ -122,10 +124,24 @@ response_type_from_server(int rdset,
|
||||
|
||||
/* If the message is NXDOMAIN, then it answers the question. */
|
||||
if(FLAGS_GET_RCODE(msg->rep->flags) == LDNS_RCODE_NXDOMAIN) {
|
||||
if(msg->rep->an_numrrsets == 0 &&
|
||||
msg->rep->ns_numrrsets == 0 &&
|
||||
msg_lame_empty)
|
||||
return RESPONSE_TYPE_LAME;
|
||||
/* make sure its not recursive when we don't want it to */
|
||||
if( (msg->rep->flags&BIT_RA) &&
|
||||
!(msg->rep->flags&BIT_AA) && !rdset)
|
||||
return RESPONSE_TYPE_REC_LAME;
|
||||
if(!cfg->harden_cname_follow /* follow CNAME chain */) {
|
||||
/* If the CNAME chain is allowed, see if there is a
|
||||
* SOA record, if so, the chain is complete to the
|
||||
* end of it, otherwise it could be a partial chain.*/
|
||||
for(i=msg->rep->an_numrrsets; i<msg->rep->an_numrrsets+msg->rep->ns_numrrsets; i++) {
|
||||
s = msg->rep->rrsets[i];
|
||||
if(ntohs(s->rk.type) == LDNS_RR_TYPE_SOA)
|
||||
return RESPONSE_TYPE_ANSWER;
|
||||
}
|
||||
}
|
||||
/* it could be a CNAME with NXDOMAIN rcode */
|
||||
for(i=0; i<msg->rep->an_numrrsets; i++) {
|
||||
s = msg->rep->rrsets[i];
|
||||
@@ -143,6 +159,10 @@ response_type_from_server(int rdset,
|
||||
if(FLAGS_GET_RCODE(msg->rep->flags) != LDNS_RCODE_NOERROR)
|
||||
return RESPONSE_TYPE_THROWAWAY;
|
||||
|
||||
if(msg->rep->an_numrrsets == 0 && msg->rep->ns_numrrsets == 0 &&
|
||||
msg_lame_empty)
|
||||
return RESPONSE_TYPE_LAME;
|
||||
|
||||
/* Note: TC bit has already been handled */
|
||||
|
||||
if(dp) {
|
||||
@@ -154,6 +174,7 @@ response_type_from_server(int rdset,
|
||||
if(msg->rep->an_numrrsets > 0) {
|
||||
uint8_t* mname = request->qname;
|
||||
size_t mname_len = request->qname_len;
|
||||
int sawanswer = 0;
|
||||
|
||||
/* Now look at the answer section first. 3 states: our
|
||||
* answer is there directly, our answer is there after
|
||||
@@ -189,6 +210,7 @@ response_type_from_server(int rdset,
|
||||
* the answer, we only provisionally say
|
||||
* 'ANSWER' -- it very well could be a
|
||||
* REFERRAL. */
|
||||
sawanswer = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -206,6 +228,10 @@ response_type_from_server(int rdset,
|
||||
* still got to here, then it is a CNAME response.
|
||||
* (This is regardless of the AA bit at this point) */
|
||||
if(mname != request->qname) {
|
||||
if(!cfg->harden_cname_follow /* allow CNAMEs */ &&
|
||||
sawanswer /* The last was not CNAME, and
|
||||
there is an answer RRset. */ )
|
||||
return RESPONSE_TYPE_ANSWER;
|
||||
return RESPONSE_TYPE_CNAME;
|
||||
}
|
||||
}
|
||||
@@ -249,13 +275,16 @@ response_type_from_server(int rdset,
|
||||
* which gives ns==zone delegation from cache
|
||||
* without AA bit as well, with nodata nosoa*/
|
||||
/* real answer must be +AA and SOA RFC(2308),
|
||||
* so this is wrong, and we SERVFAIL it if
|
||||
* this is the only possible reply, if it
|
||||
* is misdeployed the THROWAWAY makes us pick
|
||||
* the next server from the selection */
|
||||
if(msg->rep->an_numrrsets==0 &&
|
||||
* this is picked up as lame_referral by the
|
||||
* sanitize step, so it can spot if there
|
||||
* was data in the answer section before
|
||||
* removal. If such data is then removed we
|
||||
* do not want to turn that answer into lame.
|
||||
* But if it was not there, it can be lame. */
|
||||
if(msg_lame_referral &&
|
||||
msg->rep->an_numrrsets==0 &&
|
||||
!(msg->rep->flags&BIT_AA) && !rdset)
|
||||
return RESPONSE_TYPE_THROWAWAY;
|
||||
return RESPONSE_TYPE_LAME;
|
||||
return RESPONSE_TYPE_ANSWER;
|
||||
}
|
||||
/* If we are getting a referral upwards (or to
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
struct dns_msg;
|
||||
struct query_info;
|
||||
struct delegpt;
|
||||
struct config_file;
|
||||
|
||||
/**
|
||||
* The response type is used to interpret the response.
|
||||
@@ -115,15 +116,21 @@ enum response_type response_type_from_cache(struct dns_msg* msg,
|
||||
* detection, mostly).
|
||||
*
|
||||
* @param rdset: if RD bit was sent in query sent by unbound.
|
||||
* @param msg: the message from the cache.
|
||||
* @param msg: the message.
|
||||
* @param request: the request that generated the response.
|
||||
* @param dp: The delegation point that was being queried
|
||||
* when the response was returned.
|
||||
* @param empty_nodata_found: flag to keep track of empty nodata detection.
|
||||
* @param msg_lame_empty: The scrubber indicates that this empty message
|
||||
* is lame, before it became empty.
|
||||
* @param msg_lame_referral: returned true if the reply has a referral before
|
||||
* scrub.
|
||||
* @param cfg: config with options.
|
||||
* @return the response type (CNAME or ANSWER).
|
||||
*/
|
||||
enum response_type response_type_from_server(int rdset,
|
||||
struct dns_msg* msg, struct query_info* request, struct delegpt* dp,
|
||||
int* empty_nodata_found);
|
||||
int* empty_nodata_found, int msg_lame_empty, int msg_lame_referral,
|
||||
struct config_file* cfg);
|
||||
|
||||
#endif /* ITERATOR_ITER_RESPTYPE_H */
|
||||
|
||||
+120
-8
@@ -294,7 +294,14 @@ synth_cname_rrset(uint8_t** sname, size_t* snamelen, uint8_t* alias,
|
||||
if(ttl_t > MAX_TTL) ttl_t = MAX_TTL;
|
||||
ttl = (uint32_t)ttl_t;
|
||||
sldns_write_uint32(cn->rr_first->ttl_data, ttl);
|
||||
sldns_write_uint32(rrset->rr_first->ttl_data, ttl);
|
||||
/* Do NOT write the clamp back into the packet buffer:
|
||||
* parse_packet already sized every name from the original
|
||||
* bytes and rdata_copy re-walks them trusting those sizes;
|
||||
* mutating packet bytes between the walks breaks that
|
||||
* invariant (compression pointers can target these TTL
|
||||
* bytes). The DNAME rrset receives the same clamp at store
|
||||
* time in rdata_copy, so the DNAME and the synthesized
|
||||
* CNAME still carry equal TTLs in the cache. */
|
||||
}
|
||||
sldns_write_uint16(cn->rr_first->ttl_data+4, aliaslen);
|
||||
memmove(cn->rr_first->ttl_data+6, alias, aliaslen);
|
||||
@@ -316,6 +323,20 @@ synth_cname_rrset(uint8_t** sname, size_t* snamelen, uint8_t* alias,
|
||||
return cn;
|
||||
}
|
||||
|
||||
/** Check if the packet has type NS in answer or authority section */
|
||||
static int
|
||||
pkt_contains_ns(struct msg_parse* msg)
|
||||
{
|
||||
struct rrset_parse* rrset;
|
||||
for(rrset = msg->rrset_first; rrset; rrset = rrset->rrset_all_next) {
|
||||
if(rrset->type == LDNS_RR_TYPE_NS &&
|
||||
(rrset->section == LDNS_SECTION_ANSWER ||
|
||||
rrset->section == LDNS_SECTION_AUTHORITY))
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** check if DNAME applies to a name */
|
||||
static int
|
||||
pkt_strict_sub(sldns_buffer* pkt, uint8_t* sname, uint8_t* dr)
|
||||
@@ -394,6 +415,8 @@ shorten_rrset(sldns_buffer* pkt, struct rrset_parse* rrset, int count)
|
||||
struct rr_parse* rr = rrset->rr_first, *prev = NULL;
|
||||
if(!rr)
|
||||
return;
|
||||
if(count < 1)
|
||||
return; /* cannot leave a still-linked rrset_parse with rr_count == 0 */
|
||||
for(i=0; i<count; i++) {
|
||||
prev = rr;
|
||||
rr = rr->next;
|
||||
@@ -478,6 +501,7 @@ scrub_normalize(sldns_buffer* pkt, struct msg_parse* msg,
|
||||
size_t snamelen = qinfo->qname_len;
|
||||
struct rrset_parse* rrset, *prev, *nsset=NULL;
|
||||
int cname_length = 0; /* number of CNAMEs, or DNAMEs */
|
||||
int has_answer = 0; /* if answer section contains nonCNAME,nonDNAME */
|
||||
|
||||
if(FLAGS_GET_RCODE(msg->flags) != LDNS_RCODE_NOERROR &&
|
||||
FLAGS_GET_RCODE(msg->flags) != LDNS_RCODE_NXDOMAIN &&
|
||||
@@ -500,7 +524,7 @@ scrub_normalize(sldns_buffer* pkt, struct msg_parse* msg,
|
||||
* 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. */
|
||||
* the content one by one, if harden-cname-follow . */
|
||||
remove_rrset("normalize: removing because too many cnames:",
|
||||
pkt, msg, prev, &rrset);
|
||||
continue;
|
||||
@@ -519,6 +543,11 @@ scrub_normalize(sldns_buffer* pkt, struct msg_parse* msg,
|
||||
(unsigned)rrset->rr_count);
|
||||
return 0;
|
||||
}
|
||||
if(has_answer) {
|
||||
remove_rrset("normalize: removing DNAME redirection after answer:",
|
||||
pkt, msg, prev, &rrset);
|
||||
continue;
|
||||
}
|
||||
if(!synth_cname(sname, snamelen, rrset, alias,
|
||||
&aliaslen, pkt)) {
|
||||
verbose(VERB_ALGO, "synthesized CNAME "
|
||||
@@ -569,6 +598,11 @@ 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;
|
||||
if(has_answer) {
|
||||
remove_rrset("normalize: removing redirection after answer:",
|
||||
pkt, msg, prev, &rrset);
|
||||
continue;
|
||||
}
|
||||
cname_length++;
|
||||
/* see if the next one is a DNAME, if so, swap them */
|
||||
if(nx && nx->section == LDNS_SECTION_ANSWER &&
|
||||
@@ -621,6 +655,9 @@ scrub_normalize(sldns_buffer* pkt, struct msg_parse* msg,
|
||||
if(rrset->type == LDNS_RR_TYPE_NS &&
|
||||
rrset->rr_count > env->cfg->iter_scrub_ns) {
|
||||
shorten_rrset(pkt, rrset, env->cfg->iter_scrub_ns);
|
||||
} else if(rrset->type == LDNS_RR_TYPE_DS &&
|
||||
rrset->rr_count > env->cfg->iter_scrub_ns) {
|
||||
shorten_rrset(pkt, rrset, env->cfg->iter_scrub_ns);
|
||||
}
|
||||
prev = rrset;
|
||||
rrset = rrset->rrset_all_next;
|
||||
@@ -640,6 +677,9 @@ scrub_normalize(sldns_buffer* pkt, struct msg_parse* msg,
|
||||
if(rrset->type == LDNS_RR_TYPE_NS &&
|
||||
rrset->rr_count > env->cfg->iter_scrub_ns) {
|
||||
shorten_rrset(pkt, rrset, env->cfg->iter_scrub_ns);
|
||||
} else if(rrset->type == LDNS_RR_TYPE_DS &&
|
||||
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. */
|
||||
@@ -647,6 +687,7 @@ scrub_normalize(sldns_buffer* pkt, struct msg_parse* msg,
|
||||
* will be removed by sanitize, so no additional for them */
|
||||
if(dname_pkt_compare(pkt, qinfo->qname, rrset->dname) == 0)
|
||||
mark_additional_rrset(pkt, msg, rrset);
|
||||
has_answer = 1;
|
||||
|
||||
prev = rrset;
|
||||
rrset = rrset->rrset_all_next;
|
||||
@@ -732,6 +773,11 @@ scrub_normalize(sldns_buffer* pkt, struct msg_parse* msg,
|
||||
"RRset:", pkt, msg, prev, &rrset);
|
||||
continue;
|
||||
}
|
||||
if(ntohs(rrset->rrset_class) != qinfo->qclass) {
|
||||
remove_rrset("normalize: removing other class "
|
||||
"RRset:", pkt, msg, prev, &rrset);
|
||||
continue;
|
||||
}
|
||||
if(nsset == NULL) {
|
||||
nsset = rrset;
|
||||
} else {
|
||||
@@ -758,6 +804,11 @@ scrub_normalize(sldns_buffer* pkt, struct msg_parse* msg,
|
||||
shorten_rrset(pkt, rrset, env->cfg->iter_scrub_ns);
|
||||
}
|
||||
}
|
||||
} else if(rrset->type==LDNS_RR_TYPE_DS) {
|
||||
if(rrset->rr_count > env->cfg->iter_scrub_ns) {
|
||||
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 */
|
||||
@@ -860,8 +911,8 @@ store_rrset(sldns_buffer* pkt, struct msg_parse* msg, struct module_env* env,
|
||||
packed_rrset_ttl_add(d, now);
|
||||
ref.key = k;
|
||||
ref.id = k->id;
|
||||
/*ignore ret: it was in the cache, ref updated */
|
||||
(void)rrset_cache_update(env->rrset_cache, &ref, env->alloc, now);
|
||||
/* if it was in the cache, ref updated */
|
||||
rrset_cache_update_unlock(env->rrset_cache, &ref, env->alloc, now);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -968,18 +1019,28 @@ scrub_sanitize_rr_length(sldns_buffer* pkt, struct msg_parse* msg,
|
||||
* @param env: module environment with config and cache.
|
||||
* @param ie: iterator environment with private address data.
|
||||
* @param qstate: for setting errinf for EDE error messages.
|
||||
* @param pkt_before_NS: if the packet had type NS before scrub. If that
|
||||
* is removed now, that indicates this may have been lame.
|
||||
* @param msg_lame_empty: returned true if the empty packet is lame.
|
||||
* @param msg_lame_referral: returned true if the reply has a referral before
|
||||
* scrub.
|
||||
* @param rdset: if RD bit was sent in query sent by unbound.
|
||||
* @return 0 on error.
|
||||
*/
|
||||
static int
|
||||
scrub_sanitize(sldns_buffer* pkt, struct msg_parse* msg,
|
||||
struct query_info* qinfo, uint8_t* zonename, struct module_env* env,
|
||||
struct iter_env* ie, struct module_qstate* qstate)
|
||||
struct iter_env* ie, struct module_qstate* qstate,
|
||||
int pkt_before_NS, int* msg_lame_empty, int* msg_lame_referral,
|
||||
int rdset)
|
||||
{
|
||||
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;
|
||||
uint8_t* sname = qinfo->qname;
|
||||
size_t snamelen = qinfo->qname_len;
|
||||
prev = NULL;
|
||||
rrset = msg->rrset_first;
|
||||
|
||||
@@ -987,6 +1048,7 @@ scrub_sanitize(sldns_buffer* pkt, struct msg_parse* msg,
|
||||
* it can be used from the cache. After normalization, an initial
|
||||
* DNAME will have a correctly synthesized CNAME after it. */
|
||||
if(rrset && rrset->type == LDNS_RR_TYPE_DNAME &&
|
||||
env->cfg->harden_cname_follow /* CNAME chain is cut off, one DNAME is allowed here. */ &&
|
||||
rrset->section == LDNS_SECTION_ANSWER &&
|
||||
pkt_strict_sub(pkt, qinfo->qname, rrset->dname) &&
|
||||
pkt_sub(pkt, rrset->dname, zonename)) {
|
||||
@@ -1002,12 +1064,33 @@ scrub_sanitize(sldns_buffer* pkt, struct msg_parse* msg,
|
||||
* ANY queries get query name in answer section.
|
||||
* Remainders of CNAME chains are cut off and resolved by iterator. */
|
||||
while(rrset && rrset->section == LDNS_SECTION_ANSWER) {
|
||||
if(dname_pkt_compare(pkt, qinfo->qname, rrset->dname) != 0) {
|
||||
if(!env->cfg->harden_cname_follow /* CNAME chain is allowed to stay */ &&
|
||||
rrset->type == LDNS_RR_TYPE_DNAME &&
|
||||
pkt_strict_sub(pkt, sname, rrset->dname) &&
|
||||
pkt_sub(pkt, rrset->dname, zonename)) {
|
||||
/* This DNAME is allowed to stay, the synthesized
|
||||
* CNAME follows next. */
|
||||
prev = rrset;
|
||||
rrset = rrset->rrset_all_next;
|
||||
continue;
|
||||
}
|
||||
if(dname_pkt_compare(pkt, sname, rrset->dname) != 0) {
|
||||
if(has_additional(rrset->type)) del_addi = 1;
|
||||
remove_rrset("sanitize: removing extraneous answer "
|
||||
"RRset:", pkt, msg, prev, &rrset);
|
||||
continue;
|
||||
}
|
||||
if(!env->cfg->harden_cname_follow /* CNAME chain is allowed to stay */ &&
|
||||
qinfo->qtype != LDNS_RR_TYPE_ANY &&
|
||||
rrset->type == LDNS_RR_TYPE_CNAME &&
|
||||
dname_pkt_compare(pkt, sname, rrset->dname) == 0) {
|
||||
/* Follow the CNAME chain, and allow the elements
|
||||
* that match the CNAME chain. Also allow a DNAME
|
||||
* in front. */
|
||||
if(!parse_get_cname_target(rrset, &sname, &snamelen,
|
||||
pkt))
|
||||
return 0;
|
||||
}
|
||||
prev = rrset;
|
||||
rrset = rrset->rrset_all_next;
|
||||
}
|
||||
@@ -1130,6 +1213,21 @@ scrub_sanitize(sldns_buffer* pkt, struct msg_parse* msg,
|
||||
prev = rrset;
|
||||
rrset = rrset->rrset_all_next;
|
||||
}
|
||||
|
||||
/* If the packet is empty now, but it was not before. And there
|
||||
* was type NS in authority, then that indicates the answer is lame. */
|
||||
if(msg->rrset_first == NULL && pkt_before_NS) {
|
||||
*msg_lame_empty = 1;
|
||||
verbose(VERB_ALGO, "sanitize: empty message had referral to NS before, marked as lame");
|
||||
} else if(pkt_before_NS && msg->an_rrsets==0 &&
|
||||
!(msg->flags&BIT_AA) && !rdset) {
|
||||
/* If the packet is now a referral, not really a nodata,
|
||||
* then if it was also with an empty answer section before,
|
||||
* it is also lame. */
|
||||
*msg_lame_referral = 1;
|
||||
verbose(VERB_ALGO, "sanitize: message has referral not answer, marked as lame");
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -1137,11 +1235,15 @@ int
|
||||
scrub_message(sldns_buffer* pkt, struct msg_parse* msg,
|
||||
struct query_info* qinfo, uint8_t* zonename, struct regional* region,
|
||||
struct module_env* env, struct module_qstate* qstate,
|
||||
struct iter_env* ie)
|
||||
struct iter_env* ie, int* msg_lame_empty, int* msg_lame_referral,
|
||||
int rdset)
|
||||
{
|
||||
int pkt_before_NS;
|
||||
/* basic sanity checks */
|
||||
log_nametypeclass(VERB_ALGO, "scrub for", zonename, LDNS_RR_TYPE_NS,
|
||||
qinfo->qclass);
|
||||
*msg_lame_empty = 0;
|
||||
*msg_lame_referral = 0;
|
||||
if(msg->qdcount > 1)
|
||||
return 0;
|
||||
if( !(msg->flags&BIT_QR) )
|
||||
@@ -1166,11 +1268,21 @@ scrub_message(sldns_buffer* pkt, struct msg_parse* msg,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* If the packet contains type NS in authority before scrub,
|
||||
* like a self referral. With the answer section empty, it
|
||||
* was not AA, the query was not sent with RD, with NS in auth,
|
||||
* and no SOA in auth. For a negative answer, type SOA is present.
|
||||
* This detects certain lameness if after has removed that. */
|
||||
pkt_before_NS = msg->an_rrsets == 0 &&
|
||||
!(msg->flags&BIT_AA) && !rdset &&
|
||||
pkt_contains_ns(msg) && !soa_in_auth(msg);
|
||||
|
||||
/* normalize the response, this cleans up the additional. */
|
||||
if(!scrub_normalize(pkt, msg, qinfo, region, env, zonename))
|
||||
return 0;
|
||||
/* delete all out-of-zone information */
|
||||
if(!scrub_sanitize(pkt, msg, qinfo, zonename, env, ie, qstate))
|
||||
if(!scrub_sanitize(pkt, msg, qinfo, zonename, env, ie, qstate,
|
||||
pkt_before_NS, msg_lame_empty, msg_lame_referral, rdset))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -62,11 +62,16 @@ struct module_qstate;
|
||||
* @param env: module environment with config settings and cache.
|
||||
* @param qstate: for setting errinf for EDE error messages.
|
||||
* @param ie: iterator module environment data.
|
||||
* @param msg_lame_empty: returned true if the empty packet is lame.
|
||||
* @param msg_lame_referral: returned true if the reply has a referral before
|
||||
* scrub.
|
||||
* @param rdset: if RD bit was sent in query sent by unbound.
|
||||
* @return: false if the message is total waste. true if scrubbed with success.
|
||||
*/
|
||||
int scrub_message(struct sldns_buffer* pkt, struct msg_parse* msg,
|
||||
struct query_info* qinfo, uint8_t* zonename, struct regional* regional,
|
||||
struct module_env* env, struct module_qstate* qstate,
|
||||
struct iter_env* ie);
|
||||
struct iter_env* ie, int* msg_lame_empty, int* msg_lame_referral,
|
||||
int rdset);
|
||||
|
||||
#endif /* ITERATOR_ITER_SCRUB_H */
|
||||
|
||||
+37
-3
@@ -1215,8 +1215,8 @@ iter_store_parentside_rrset(struct module_env* env,
|
||||
rrset->entry.hash = rrset_key_hash(&rrset->rk);
|
||||
ref.key = rrset;
|
||||
ref.id = rrset->id;
|
||||
/* ignore ret: if it was in the cache, ref updated */
|
||||
(void)rrset_cache_update(env->rrset_cache, &ref, env->alloc, *env->now);
|
||||
/* if it was in the cache, ref updated */
|
||||
rrset_cache_update_unlock(env->rrset_cache, &ref, env->alloc, *env->now);
|
||||
}
|
||||
|
||||
/** fetch NS record from reply, if any */
|
||||
@@ -1313,7 +1313,8 @@ iter_lookup_parent_NS_from_cache(struct module_env* env, struct delegpt* dp,
|
||||
log_rrset_key(VERB_ALGO, "found parent-side NS in cache", akey);
|
||||
dp->has_parent_side_NS = 1;
|
||||
/* and mark the new names as lame */
|
||||
if(!delegpt_rrset_add_ns(dp, region, akey, 1)) {
|
||||
if(!delegpt_rrset_add_ns(dp, region, akey, 1,
|
||||
deleg_port_number(env))) {
|
||||
lock_rw_unlock(&akey->entry.lock);
|
||||
return 0;
|
||||
}
|
||||
@@ -1703,3 +1704,36 @@ iter_make_minimal(struct reply_info* rep)
|
||||
rep->ar_numrrsets = 0;
|
||||
rep->rrset_count -= rem;
|
||||
}
|
||||
|
||||
int
|
||||
deleg_port_number(struct module_env* env)
|
||||
{
|
||||
if(env->cfg->ssl_upstream)
|
||||
return env->cfg->ssl_port;
|
||||
return -1;
|
||||
}
|
||||
|
||||
void
|
||||
shorten_answer_cname(struct reply_info* rep, uint8_t* cutoff)
|
||||
{
|
||||
size_t i, found = 0, removenum;
|
||||
uint8_t* sname = NULL;
|
||||
size_t snamelen = 0;
|
||||
for(i=0; i<rep->an_numrrsets; i++) {
|
||||
if(query_dname_compare(rep->rrsets[i]->rk.dname, cutoff) == 0) {
|
||||
found = 1;
|
||||
removenum = i;
|
||||
break;
|
||||
}
|
||||
if(ntohs(rep->rrsets[i]->rk.type) == LDNS_RR_TYPE_CNAME) {
|
||||
get_cname_target(rep->rrsets[i], &sname, &snamelen);
|
||||
if(query_dname_compare(sname, cutoff) == 0) {
|
||||
found = 1;
|
||||
removenum = i+1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!found) return; /* not found */
|
||||
val_reply_remove_answers(rep, removenum, rep->an_numrrsets-removenum);
|
||||
}
|
||||
|
||||
@@ -483,4 +483,10 @@ void limit_nsec_ttl(struct dns_msg* msg);
|
||||
*/
|
||||
void iter_make_minimal(struct reply_info* rep);
|
||||
|
||||
/** See if we need a different port number */
|
||||
int deleg_port_number(struct module_env* env);
|
||||
|
||||
/** Shorten reply CNAME chain to cutoff, cutoff is excluded. */
|
||||
void shorten_answer_cname(struct reply_info* rep, uint8_t* cutoff);
|
||||
|
||||
#endif /* ITERATOR_ITER_UTILS_H */
|
||||
|
||||
+132
-21
@@ -1511,6 +1511,7 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
verbose(VERB_ALGO, "no-cache set, going to the network");
|
||||
qstate->no_cache_lookup = 1;
|
||||
qstate->no_cache_store = 1;
|
||||
qstate->fwd_stub_no_cache = 1;
|
||||
msg = NULL;
|
||||
} else if(qstate->blacklist) {
|
||||
/* if cache, or anything else, was blacklisted then
|
||||
@@ -1530,7 +1531,7 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
msg = val_neg_getmsg(qstate->env->neg_cache, &iq->qchase,
|
||||
qstate->region, qstate->env->rrset_cache,
|
||||
qstate->env->scratch_buffer,
|
||||
*qstate->env->now, 1/*add SOA*/, NULL,
|
||||
*qstate->env->now, 1/*add SOA*/, dpname,
|
||||
qstate->env->cfg);
|
||||
}
|
||||
/* item taken from cache does not match our query name, thus
|
||||
@@ -2391,6 +2392,12 @@ processDSNSFind(struct module_qstate* qstate, struct iter_qstate* iq, int id)
|
||||
|
||||
/* go up one (more) step, until we hit the dp, if so, end */
|
||||
dname_remove_label(&iq->dsns_point, &iq->dsns_point_len);
|
||||
if(++iq->dsns_count > MAX_DSNS_FIND_COUNT) {
|
||||
verbose(VERB_QUERY, "DS NS search exceeded %d labels",
|
||||
MAX_DSNS_FIND_COUNT);
|
||||
errinf(qstate, "DS NS search exceeded label limit");
|
||||
return error_response_cache(qstate, id, LDNS_RCODE_SERVFAIL);
|
||||
}
|
||||
if(query_dname_compare(iq->dsns_point, iq->dp->name) == 0) {
|
||||
/* there was no inbetween nameserver, use the old delegation
|
||||
* point again. And this time, because dsns_point is nonNULL
|
||||
@@ -3073,7 +3080,9 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
|
||||
/* Do not check ratelimit for forwarding queries or if we already got a
|
||||
* pass. */
|
||||
sq_check_ratelimit = (!(iq->chase_flags & BIT_RD) && !iq->ratelimit_ok);
|
||||
sq_check_ratelimit = ((!(iq->chase_flags & BIT_RD) &&
|
||||
!iq->ratelimit_ok));
|
||||
iq->ratelimit_incremented = 0;
|
||||
/* We have a valid target. */
|
||||
if(verbosity >= VERB_QUERY) {
|
||||
log_query_info(VERB_QUERY, "sending query:", &iq->qinfo_out);
|
||||
@@ -3099,7 +3108,8 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
iq->dp->name, iq->dp->namelen,
|
||||
(iq->dp->tcp_upstream || qstate->env->cfg->tcp_upstream),
|
||||
(iq->dp->ssl_upstream || qstate->env->cfg->ssl_upstream),
|
||||
target->tls_auth_name, qstate, &sq_was_ratelimited);
|
||||
target->tls_auth_name, qstate, &sq_was_ratelimited,
|
||||
&iq->ratelimit_incremented);
|
||||
if(!outq) {
|
||||
if(sq_was_ratelimited) {
|
||||
lock_basic_lock(&ie->queries_ratelimit_lock);
|
||||
@@ -3137,7 +3147,6 @@ find_NS(struct reply_info* rep, size_t from, size_t to)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Process the query response. All queries end up at this state first. This
|
||||
* process generally consists of analyzing the response and routing the
|
||||
@@ -3179,7 +3188,8 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
orig_empty_nodata_found = iq->empty_nodata_found;
|
||||
type = response_type_from_server(
|
||||
(int)((iq->chase_flags&BIT_RD) || iq->chase_to_rd),
|
||||
iq->response, &iq->qinfo_out, iq->dp, &iq->empty_nodata_found);
|
||||
iq->response, &iq->qinfo_out, iq->dp, &iq->empty_nodata_found,
|
||||
iq->msg_lame_empty, iq->msg_lame_referral, qstate->env->cfg);
|
||||
iq->chase_to_rd = 0;
|
||||
/* remove TC flag, if this is erroneously set by TCP upstream */
|
||||
iq->response->rep->flags &= ~BIT_TC;
|
||||
@@ -3292,6 +3302,47 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
* to send another query with a new qtype. */
|
||||
type = RESPONSE_TYPE_ANSWER;
|
||||
}
|
||||
if(type == RESPONSE_TYPE_ANSWER &&
|
||||
!qstate->env->cfg->harden_cname_follow /* cname chain from upstream is allowed */ &&
|
||||
qstate->env->auth_zones &&
|
||||
/* Check for CNAMEs in answer and RPZ after the CNAME. */
|
||||
reply_find_rrset_section_an(
|
||||
iq->response->rep, iq->qchase.qname,
|
||||
iq->qchase.qname_len, LDNS_RR_TYPE_CNAME,
|
||||
iq->qchase.qclass) != NULL) {
|
||||
/* If this is an answer with CNAMEs in front, and
|
||||
* RPZ wants to modify after CNAME(s), cut off, the
|
||||
* remainder, and treat as the CNAME response */
|
||||
size_t i;
|
||||
uint8_t* origname = iq->qchase.qname;
|
||||
size_t orignamelen = iq->qchase.qname_len;
|
||||
for(i=0; i<iq->response->rep->an_numrrsets; i++) {
|
||||
struct dns_msg* forged_response;
|
||||
if(ntohs(iq->response->rep->rrsets[i]->rk.type) ==
|
||||
LDNS_RR_TYPE_DNAME) {
|
||||
continue;
|
||||
}
|
||||
if(ntohs(iq->response->rep->rrsets[i]->rk.type) !=
|
||||
LDNS_RR_TYPE_CNAME) {
|
||||
break;
|
||||
}
|
||||
get_cname_target(iq->response->rep->rrsets[i],
|
||||
&iq->qchase.qname, &iq->qchase.qname_len);
|
||||
forged_response = rpz_callback_from_iterator_cname(qstate, iq);
|
||||
if(forged_response) {
|
||||
/* Cut off the answer section at this point.
|
||||
* RPZ is going to make an answer, in the
|
||||
* processInit after the CNAME(s) in front
|
||||
* are handled. */
|
||||
shorten_answer_cname(iq->response->rep,
|
||||
iq->qchase.qname);
|
||||
type = RESPONSE_TYPE_CNAME;
|
||||
break;
|
||||
}
|
||||
}
|
||||
iq->qchase.qname = origname;
|
||||
iq->qchase.qname_len = orignamelen;
|
||||
}
|
||||
|
||||
/* handle each of the type cases */
|
||||
if(type == RESPONSE_TYPE_ANSWER) {
|
||||
@@ -3457,7 +3508,14 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
iq->deleg_msg = iq->response;
|
||||
/* Keep current delegation point for label comparison */
|
||||
old_dp = iq->dp;
|
||||
iq->dp = delegpt_from_message(iq->response, qstate->region);
|
||||
/* A referral reply is "pleasant", refund the
|
||||
* parent dp's rate charge before descending to the child. */
|
||||
if(iq->ratelimit_incremented)
|
||||
infra_ratelimit_dec(qstate->env->infra_cache,
|
||||
old_dp->name, old_dp->namelen,
|
||||
*qstate->env->now);
|
||||
iq->dp = delegpt_from_message(iq->response, qstate->region,
|
||||
deleg_port_number(qstate->env));
|
||||
if (qstate->env->cfg->qname_minimisation)
|
||||
iq->minimisation_state = INIT_MINIMISE_STATE;
|
||||
if(!iq->dp) {
|
||||
@@ -3734,7 +3792,8 @@ prime_supers(struct module_qstate* qstate, int id, struct module_qstate* forq)
|
||||
log_assert(qstate->is_priming || foriq->wait_priming_stub);
|
||||
log_assert(qstate->return_rcode == LDNS_RCODE_NOERROR);
|
||||
/* Convert our response to a delegation point */
|
||||
dp = delegpt_from_message(qstate->return_msg, forq->region);
|
||||
dp = delegpt_from_message(qstate->return_msg, forq->region,
|
||||
deleg_port_number(forq->env));
|
||||
if(!dp) {
|
||||
/* if there is no convertible delegation point, then
|
||||
* the ANSWER type was (presumably) a negative answer. */
|
||||
@@ -3785,7 +3844,8 @@ processPrimeResponse(struct module_qstate* qstate, int id)
|
||||
iq->response->rep->flags &= ~(BIT_RD|BIT_RA); /* ignore rec-lame */
|
||||
type = response_type_from_server(
|
||||
(int)((iq->chase_flags&BIT_RD) || iq->chase_to_rd),
|
||||
iq->response, &iq->qchase, iq->dp, NULL);
|
||||
iq->response, &iq->qchase, iq->dp, NULL, iq->msg_lame_empty,
|
||||
iq->msg_lame_referral, qstate->env->cfg);
|
||||
if(type == RESPONSE_TYPE_ANSWER) {
|
||||
qstate->return_rcode = LDNS_RCODE_NOERROR;
|
||||
qstate->return_msg = iq->response;
|
||||
@@ -3935,26 +3995,49 @@ processDSNSResponse(struct module_qstate* qstate, int id,
|
||||
struct module_qstate* forq)
|
||||
{
|
||||
struct iter_qstate* foriq = (struct iter_qstate*)forq->minfo[id];
|
||||
int sec_an = 0, sec_ns = 0;
|
||||
|
||||
/* if the finished (iq->response) query has no NS set: continue
|
||||
* up to look for the right dp; nothing to change, do DPNSstate */
|
||||
if(qstate->return_rcode != LDNS_RCODE_NOERROR)
|
||||
return; /* seek further */
|
||||
/* find the NS RRset (without allowing CNAMEs) */
|
||||
if(!reply_find_rrset(qstate->return_msg->rep, qstate->qinfo.qname,
|
||||
qstate->qinfo.qname_len, LDNS_RR_TYPE_NS,
|
||||
qstate->qinfo.qclass)){
|
||||
/* Usually, the response has a NS in the answer section, since that
|
||||
* was the query type. And it is then the child side part of the NS
|
||||
* set. This child side part would be used if next up a delegation
|
||||
* point was constructed from cache, for example. But now it uses that
|
||||
* child side part for constructing a delegation point for the DS
|
||||
* lookup.
|
||||
* If that is not there, we can pick up the NS from the authority
|
||||
* section as well, like from a referral. */
|
||||
if(reply_find_rrset_section_an(qstate->return_msg->rep,
|
||||
qstate->qinfo.qname, qstate->qinfo.qname_len,
|
||||
LDNS_RR_TYPE_NS, qstate->qinfo.qclass))
|
||||
sec_an = 1;
|
||||
if(!sec_an && reply_find_rrset_section_ns(qstate->return_msg->rep,
|
||||
qstate->qinfo.qname, qstate->qinfo.qname_len,
|
||||
LDNS_RR_TYPE_NS, qstate->qinfo.qclass))
|
||||
sec_ns = 1;
|
||||
if(!sec_an && !sec_ns) {
|
||||
/* We probably hit an intermediate label, without a type NS
|
||||
* record there. To find the nameservers, it must go up more.*/
|
||||
return; /* seek further */
|
||||
}
|
||||
|
||||
/* else, store as DP and continue at querytargets */
|
||||
foriq->state = QUERYTARGETS_STATE;
|
||||
foriq->dp = delegpt_from_message(qstate->return_msg, forq->region);
|
||||
foriq->dp = delegpt_from_message(qstate->return_msg, forq->region,
|
||||
deleg_port_number(forq->env));
|
||||
if(!foriq->dp) {
|
||||
log_err("out of memory in dsns dp alloc");
|
||||
errinf(qstate, "malloc failure, in DS search");
|
||||
return; /* dp==NULL in QUERYTARGETS makes SERVFAIL */
|
||||
}
|
||||
if(sec_an) {
|
||||
/* The NS is in the answer section, this is not a parent side,
|
||||
* but a child side response for it. */
|
||||
foriq->dp->has_parent_side_NS = 0;
|
||||
}
|
||||
/* success, go query the querytargets in the new dp (and go down) */
|
||||
}
|
||||
|
||||
@@ -3998,7 +4081,7 @@ processClassResponse(struct module_qstate* qstate, int id,
|
||||
/* if there are records, copy RCODE */
|
||||
/* lower sec_state if this message is lower */
|
||||
if(from->rep->rrset_count != 0) {
|
||||
size_t n = from->rep->rrset_count+to->rep->rrset_count;
|
||||
size_t i, n = from->rep->rrset_count+to->rep->rrset_count;
|
||||
struct ub_packed_rrset_key** dest, **d;
|
||||
/* copy appropriate rcode */
|
||||
to->rep->flags = from->rep->flags;
|
||||
@@ -4020,24 +4103,49 @@ processClassResponse(struct module_qstate* qstate, int id,
|
||||
memcpy(dest, to->rep->rrsets, to->rep->an_numrrsets
|
||||
* sizeof(dest[0]));
|
||||
dest += to->rep->an_numrrsets;
|
||||
memcpy(dest, from->rep->rrsets, from->rep->an_numrrsets
|
||||
* sizeof(dest[0]));
|
||||
for(i=0; i<from->rep->an_numrrsets; i++) {
|
||||
dest[i] = packed_rrset_copy_region(
|
||||
from->rep->rrsets[i], forq->region, 0);
|
||||
if(!dest[i]) {
|
||||
log_err("malloc failed in collect ANY");
|
||||
foriq->state = FINISHED_STATE;
|
||||
return;
|
||||
}
|
||||
}
|
||||
dest += from->rep->an_numrrsets;
|
||||
/* copy NS */
|
||||
memcpy(dest, to->rep->rrsets+to->rep->an_numrrsets,
|
||||
to->rep->ns_numrrsets * sizeof(dest[0]));
|
||||
dest += to->rep->ns_numrrsets;
|
||||
memcpy(dest, from->rep->rrsets+from->rep->an_numrrsets,
|
||||
from->rep->ns_numrrsets * sizeof(dest[0]));
|
||||
for(i=0; i<from->rep->ns_numrrsets; i++) {
|
||||
dest[i] = packed_rrset_copy_region(
|
||||
from->rep->rrsets[
|
||||
from->rep->an_numrrsets+i],
|
||||
forq->region, 0);
|
||||
if(!dest[i]) {
|
||||
log_err("malloc failed in collect ANY");
|
||||
foriq->state = FINISHED_STATE;
|
||||
return;
|
||||
}
|
||||
}
|
||||
dest += from->rep->ns_numrrsets;
|
||||
/* copy AR */
|
||||
memcpy(dest, to->rep->rrsets+to->rep->an_numrrsets+
|
||||
to->rep->ns_numrrsets,
|
||||
to->rep->ar_numrrsets * sizeof(dest[0]));
|
||||
dest += to->rep->ar_numrrsets;
|
||||
memcpy(dest, from->rep->rrsets+from->rep->an_numrrsets+
|
||||
from->rep->ns_numrrsets,
|
||||
from->rep->ar_numrrsets * sizeof(dest[0]));
|
||||
for(i=0; i<from->rep->ar_numrrsets; i++) {
|
||||
dest[i] = packed_rrset_copy_region(
|
||||
from->rep->rrsets[
|
||||
from->rep->an_numrrsets+
|
||||
from->rep->ns_numrrsets+i],
|
||||
forq->region, 0);
|
||||
if(!dest[i]) {
|
||||
log_err("malloc failed in collect ANY");
|
||||
foriq->state = FINISHED_STATE;
|
||||
return;
|
||||
}
|
||||
}
|
||||
/* update counts */
|
||||
to->rep->rrsets = d;
|
||||
to->rep->an_numrrsets += from->rep->an_numrrsets;
|
||||
@@ -4395,7 +4503,10 @@ process_response(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||
|
||||
/* normalize and sanitize: easy to delete items from linked lists */
|
||||
if(!scrub_message(pkt, prs, &iq->qinfo_out, iq->dp->name,
|
||||
qstate->env->scratch, qstate->env, qstate, ie)) {
|
||||
qstate->env->scratch, qstate->env, qstate, ie,
|
||||
&iq->msg_lame_empty, &iq->msg_lame_referral,
|
||||
(int)((iq->chase_flags&BIT_RD) || iq->chase_to_rd)
|
||||
)) {
|
||||
/* if 0x20 enabled, start fallback, but we have no message */
|
||||
if(event == module_event_capsfail && !iq->caps_fallback) {
|
||||
iq->caps_fallback = 1;
|
||||
|
||||
@@ -104,6 +104,11 @@ extern int BLACKLIST_PENALTY;
|
||||
#define RTT_BAND 400
|
||||
/** Number of retries for empty nodata packets before it is accepted. */
|
||||
#define EMPTY_NODATA_RETRY_COUNT 2
|
||||
/** max label-strip iterations in DSNS_FIND_STATE (RFC 4035 4.2 parent-NS
|
||||
* search) before giving up; bounds upstream NS sends per client DS.
|
||||
* Means the max number of labels in grandchild to the grandparent zone that
|
||||
* are co-hosted. */
|
||||
#define MAX_DSNS_FIND_COUNT 20
|
||||
|
||||
/**
|
||||
* Iterator global state for nat64.
|
||||
@@ -375,6 +380,10 @@ struct iter_qstate {
|
||||
/** if true, already tested for ratelimiting and passed the test */
|
||||
int ratelimit_ok;
|
||||
|
||||
/** If the last query, that may be a referral, incremented the
|
||||
* ratelimit counter. */
|
||||
int ratelimit_incremented;
|
||||
|
||||
/**
|
||||
* The query must store NS records from referrals as parentside RRs
|
||||
* Enabled once it hits resolution problems, to throttle retries.
|
||||
@@ -399,6 +408,8 @@ struct iter_qstate {
|
||||
uint8_t* dsns_point;
|
||||
/** length of the dname in dsns_point */
|
||||
size_t dsns_point_len;
|
||||
/** number of label-strip iterations performed in DSNS_FIND_STATE */
|
||||
int dsns_count;
|
||||
|
||||
/**
|
||||
* expected dnssec information for this iteration step.
|
||||
@@ -434,6 +445,13 @@ struct iter_qstate {
|
||||
* already so that it is accepted later. */
|
||||
int empty_nodata_found;
|
||||
|
||||
/** Store if the answer was empty, but lame, before it became empty.*/
|
||||
int msg_lame_empty;
|
||||
|
||||
/** Store if the answer was a referral, to self, before scrub. So the
|
||||
* it is not some sort of answer. */
|
||||
int msg_lame_referral;
|
||||
|
||||
/** list of pending queries to authoritative servers. */
|
||||
struct outbound_list outlist;
|
||||
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* libunbound/authload.h - prototypes for auth load methods.
|
||||
*
|
||||
* Copyright (c) 2026, NLnet Labs. All rights reserved.
|
||||
*
|
||||
* This software is open source.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* Neither the name of the NLNET LABS nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* This file declares the methods that must be implemented to use the
|
||||
* auth load service.
|
||||
*/
|
||||
|
||||
#ifndef LIBUNBOUND_AUTHLOAD_H
|
||||
#define LIBUNBOUND_AUTHLOAD_H
|
||||
|
||||
/** The worker routine that services the auth load connection. */
|
||||
void worker_auth_load_service_cb(int fd, short bits, void* arg);
|
||||
|
||||
#endif /* LIBUNBOUND_AUTHLOAD_H */
|
||||
@@ -167,6 +167,8 @@ struct ctx_query {
|
||||
ub_event_callback_type cb_event;
|
||||
/** for async query, the callback user arg */
|
||||
void* cb_arg;
|
||||
/** for async query the unique info */
|
||||
void* unique_info;
|
||||
|
||||
/** answer message, result from resolver lookup. */
|
||||
uint8_t* msg;
|
||||
|
||||
@@ -571,6 +571,8 @@ ub_ctx_async(struct ub_ctx* ctx, int dothread)
|
||||
int
|
||||
ub_poll(struct ub_ctx* ctx)
|
||||
{
|
||||
if(!ctx || ctx->event_base)
|
||||
return UB_INITFAIL;
|
||||
/* no need to hold lock while testing for readability. */
|
||||
return tube_poll(ctx->rr_pipe);
|
||||
}
|
||||
@@ -578,6 +580,8 @@ ub_poll(struct ub_ctx* ctx)
|
||||
int
|
||||
ub_fd(struct ub_ctx* ctx)
|
||||
{
|
||||
if(!ctx || ctx->event_base)
|
||||
return -1;
|
||||
return tube_read_fd(ctx->rr_pipe);
|
||||
}
|
||||
|
||||
@@ -672,6 +676,8 @@ ub_process(struct ub_ctx* ctx)
|
||||
int r;
|
||||
uint8_t* msg;
|
||||
uint32_t len;
|
||||
if(!ctx || ctx->event_base)
|
||||
return UB_INITFAIL;
|
||||
while(1) {
|
||||
msg = NULL;
|
||||
lock_basic_lock(&ctx->rrpipe_lock);
|
||||
@@ -700,6 +706,8 @@ ub_wait(struct ub_ctx* ctx)
|
||||
int r;
|
||||
uint8_t* msg;
|
||||
uint32_t len;
|
||||
if(!ctx || ctx->event_base)
|
||||
return UB_INITFAIL;
|
||||
/* this is basically the same loop as _process(), but with changes.
|
||||
* holds the rrpipe lock and waits with tube_wait */
|
||||
while(1) {
|
||||
@@ -837,6 +845,8 @@ ub_resolve_async(struct ub_ctx* ctx, const char* name, int rrtype,
|
||||
struct ctx_query* q;
|
||||
uint8_t* msg = NULL;
|
||||
uint32_t len = 0;
|
||||
if(!ctx || ctx->event_base)
|
||||
return UB_INITFAIL;
|
||||
|
||||
if(async_id)
|
||||
*async_id = 0;
|
||||
@@ -1467,8 +1477,15 @@ ub_ctx_set_event(struct ub_ctx* ctx, struct event_base* base) {
|
||||
|
||||
lock_basic_lock(&ctx->cfglock);
|
||||
/* destroy the current worker - safe to pass in NULL */
|
||||
|
||||
/* Unlock the cfglock during libworker_delete_event, since it
|
||||
* calls context_release_alloc, that wants to lock cfglock again.
|
||||
* Since the event base is used from one thread, the one that
|
||||
* called this function, it is safe to do so. */
|
||||
lock_basic_unlock(&ctx->cfglock);
|
||||
libworker_delete_event(ctx->event_worker);
|
||||
ctx->event_worker = NULL;
|
||||
lock_basic_lock(&ctx->cfglock);
|
||||
new_base = ub_libevent_event_base(base);
|
||||
if (new_base)
|
||||
ctx->event_base = new_base;
|
||||
|
||||
+11
-6
@@ -651,7 +651,8 @@ int libworker_fg(struct ub_ctx* ctx, struct ctx_query* q)
|
||||
}
|
||||
/* process new query */
|
||||
if(!mesh_new_callback(w->env->mesh, &qinfo, qflags, &edns,
|
||||
w->back->udp_buff, qid, libworker_fg_done_cb, q, 0)) {
|
||||
w->back->udp_buff, qid, libworker_fg_done_cb, q, 0,
|
||||
&q->unique_info)) {
|
||||
free(qinfo.qname);
|
||||
return UB_NOMEM;
|
||||
}
|
||||
@@ -732,7 +733,8 @@ int libworker_attach_mesh(struct ub_ctx* ctx, struct ctx_query* q,
|
||||
if(async_id)
|
||||
*async_id = q->querynum;
|
||||
if(!mesh_new_callback(w->env->mesh, &qinfo, qflags, &edns,
|
||||
w->back->udp_buff, qid, libworker_event_done_cb, q, 0)) {
|
||||
w->back->udp_buff, qid, libworker_event_done_cb, q, 0,
|
||||
&q->unique_info)) {
|
||||
free(qinfo.qname);
|
||||
return UB_NOMEM;
|
||||
}
|
||||
@@ -870,7 +872,8 @@ handle_newq(struct libworker* w, uint8_t* buf, uint32_t len)
|
||||
q->w = w;
|
||||
/* process new query */
|
||||
if(!mesh_new_callback(w->env->mesh, &qinfo, qflags, &edns,
|
||||
w->back->udp_buff, qid, libworker_bg_done_cb, q, 0)) {
|
||||
w->back->udp_buff, qid, libworker_bg_done_cb, q, 0,
|
||||
&q->unique_info)) {
|
||||
add_bg_result(w, q, NULL, UB_NOMEM, NULL, 0);
|
||||
}
|
||||
free(qinfo.qname);
|
||||
@@ -888,7 +891,8 @@ struct outbound_entry* libworker_send_query(struct query_info* qinfo,
|
||||
int check_ratelimit,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* zone,
|
||||
size_t zonelen, int tcp_upstream, int ssl_upstream, char* tls_auth_name,
|
||||
struct module_qstate* q, int* was_ratelimited)
|
||||
struct module_qstate* q, int* was_ratelimited,
|
||||
int* ratelimit_incremented)
|
||||
{
|
||||
struct libworker* w = (struct libworker*)q->env->worker;
|
||||
struct outbound_entry* e = (struct outbound_entry*)regional_alloc(
|
||||
@@ -900,7 +904,7 @@ struct outbound_entry* libworker_send_query(struct query_info* qinfo,
|
||||
want_dnssec, nocaps, check_ratelimit, tcp_upstream, ssl_upstream,
|
||||
tls_auth_name, addr, addrlen, zone, zonelen, q,
|
||||
libworker_handle_service_reply, e, w->back->udp_buff, q->env,
|
||||
was_ratelimited);
|
||||
was_ratelimited, ratelimit_incremented);
|
||||
if(!e->qsent) {
|
||||
return NULL;
|
||||
}
|
||||
@@ -985,7 +989,8 @@ struct outbound_entry* worker_send_query(struct query_info* ATTR_UNUSED(qinfo),
|
||||
struct sockaddr_storage* ATTR_UNUSED(addr), socklen_t ATTR_UNUSED(addrlen),
|
||||
uint8_t* ATTR_UNUSED(zone), size_t ATTR_UNUSED(zonelen), int ATTR_UNUSED(tcp_upstream),
|
||||
int ATTR_UNUSED(ssl_upstream), char* ATTR_UNUSED(tls_auth_name),
|
||||
struct module_qstate* ATTR_UNUSED(q), int* ATTR_UNUSED(was_ratelimited))
|
||||
struct module_qstate* ATTR_UNUSED(q), int* ATTR_UNUSED(was_ratelimited),
|
||||
int* ATTR_UNUSED(ratelimit_incremented))
|
||||
{
|
||||
log_assert(0);
|
||||
return 0;
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* libunbound/remote.h - prototypes for remote control methods.
|
||||
*
|
||||
* Copyright (c) 2026, NLnet Labs. All rights reserved.
|
||||
*
|
||||
* This software is open source.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* Neither the name of the NLNET LABS nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* This file declares the methods that must be implemented to use the
|
||||
* remote control service.
|
||||
*/
|
||||
|
||||
#ifndef LIBUNBOUND_REMOTE_H
|
||||
#define LIBUNBOUND_REMOTE_H
|
||||
|
||||
struct comm_reply;
|
||||
struct comm_point;
|
||||
|
||||
/** fast reload thread commands to remote service thread event callback */
|
||||
void fast_reload_service_cb(int fd, short bits, void* arg);
|
||||
|
||||
/** fast reload callback for the remote control client connection */
|
||||
int fast_reload_client_callback(struct comm_point* c, void* arg, int err,
|
||||
struct comm_reply* rep);
|
||||
|
||||
/** handle remote control accept callbacks */
|
||||
int remote_accept_callback(struct comm_point*, void*, int, struct comm_reply*);
|
||||
|
||||
/** handle remote control data callbacks */
|
||||
int remote_control_callback(struct comm_point*, void*, int, struct comm_reply*);
|
||||
|
||||
/** routine to printout option values over SSL */
|
||||
void remote_get_opt_ssl(char* line, void* arg);
|
||||
|
||||
#endif /* LIBUNBOUND_REMOTE_H */
|
||||
+8
-11
@@ -70,6 +70,8 @@ struct query_info;
|
||||
* @param q: which query state to reactivate upon return.
|
||||
* @param was_ratelimited: it will signal back if the query failed to pass the
|
||||
* ratelimit check.
|
||||
* @param ratelimit_incremented: set to true if the ratelimit counter
|
||||
* was increased.
|
||||
* @return: false on failure (memory or socket related). no query was
|
||||
* sent.
|
||||
*/
|
||||
@@ -78,7 +80,8 @@ struct outbound_entry* libworker_send_query(struct query_info* qinfo,
|
||||
int check_ratelimit,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* zone,
|
||||
size_t zonelen, int tcp_upstream, int ssl_upstream, char* tls_auth_name,
|
||||
struct module_qstate* q, int* was_ratelimited);
|
||||
struct module_qstate* q, int* was_ratelimited,
|
||||
int* ratelimit_incremented);
|
||||
|
||||
/** process incoming serviced query replies from the network */
|
||||
int libworker_handle_service_reply(struct comm_point* c, void* arg, int error,
|
||||
@@ -126,6 +129,8 @@ void worker_sighandler(int sig, void* arg);
|
||||
* @param q: which query state to reactivate upon return.
|
||||
* @param was_ratelimited: it will signal back if the query failed to pass the
|
||||
* ratelimit check.
|
||||
* @param ratelimit_incremented: set to true if the ratelimit counter
|
||||
* was increased.
|
||||
* @return: false on failure (memory or socket related). no query was
|
||||
* sent.
|
||||
*/
|
||||
@@ -134,7 +139,8 @@ struct outbound_entry* worker_send_query(struct query_info* qinfo,
|
||||
int check_ratelimit,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* zone,
|
||||
size_t zonelen, int tcp_upstream, int ssl_upstream, char* tls_auth_name,
|
||||
struct module_qstate* q, int* was_ratelimited);
|
||||
struct module_qstate* q, int* was_ratelimited,
|
||||
int* ratelimit_incremented);
|
||||
|
||||
/**
|
||||
* process control messages from the main thread. Frees the control
|
||||
@@ -171,13 +177,4 @@ void worker_start_accept(void* arg);
|
||||
/** stop accept callback handler */
|
||||
void worker_stop_accept(void* arg);
|
||||
|
||||
/** handle remote control accept callbacks */
|
||||
int remote_accept_callback(struct comm_point*, void*, int, struct comm_reply*);
|
||||
|
||||
/** handle remote control data callbacks */
|
||||
int remote_control_callback(struct comm_point*, void*, int, struct comm_reply*);
|
||||
|
||||
/** routine to printout option values over SSL */
|
||||
void remote_get_opt_ssl(char* line, void* arg);
|
||||
|
||||
#endif /* LIBUNBOUND_WORKER_H */
|
||||
|
||||
+10
-2
@@ -409,7 +409,7 @@ if [ "$DOWIN" = "yes" ]; then
|
||||
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"
|
||||
cd unbound || error_cleanup "Unbound not exported correctly from git"
|
||||
rm -rf .git .travis.yml .gitattributes .github .gitignore || error_cleanup "Failed to remove .git tracking and ci information"
|
||||
rm -rf .git .gitattributes .github .gitignore || error_cleanup "Failed to remove .git tracking and ci information"
|
||||
|
||||
# on a re-configure the cache may no longer be valid...
|
||||
if test -f mingw32-config.cache; then rm mingw32-config.cache; fi
|
||||
@@ -466,9 +466,13 @@ if [ "$DOWIN" = "yes" ]; then
|
||||
|| error_cleanup "Could not configure"
|
||||
set +x
|
||||
else
|
||||
# Add -l:libssp:a to statically link libssp if possible.
|
||||
# Put it at the end of LIBS, to satisfy also linked in
|
||||
# dependencies.
|
||||
set -x
|
||||
$configure --enable-debug --enable-static-exe --disable-flto --disable-gost $* $cross_flag \
|
||||
|| error_cleanup "Could not configure"
|
||||
sed -i Makefile -e 's/^\(LIBS=.*\)$/\1 -l:libssp.a/'
|
||||
set +x
|
||||
fi
|
||||
info "Calling make"
|
||||
@@ -485,6 +489,7 @@ if [ "$DOWIN" = "yes" ]; then
|
||||
|| error_cleanup "Could not configure"
|
||||
set +x
|
||||
else
|
||||
# Do not add -l:libssp:a statically because it is a shared build.
|
||||
set -x
|
||||
$configure --enable-debug --disable-flto --disable-gost $* $shared_cross_flag \
|
||||
|| error_cleanup "Could not configure"
|
||||
@@ -598,11 +603,13 @@ 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"
|
||||
|
||||
cd unbound || error_cleanup "Unbound not exported correctly from git"
|
||||
rm -rf .git .travis.yml .gitattributes .github .gitignore || error_cleanup "Failed to remove .git tracking and ci information"
|
||||
rm -rf .git .gitattributes .github .gitignore || error_cleanup "Failed to remove .git tracking and ci information"
|
||||
|
||||
info "Adding libtool utils (libtoolize)."
|
||||
libtoolize -c --install || libtoolize -c || error_cleanup "Libtoolize failed."
|
||||
|
||||
# Turn this off, if the git repo times out for lookups.
|
||||
if test "updateconfigsub" = "false"; then
|
||||
# https://www.gnu.org/software/gettext/manual/html_node/config_002eguess.html
|
||||
info "Updating config.guess and config.sub"
|
||||
wget -O config.guess 'https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD'
|
||||
@@ -616,6 +623,7 @@ if [ `uname -s | grep -i -c darwin` -ne 0 ]; then
|
||||
xattr -d com.apple.quarantine config.sub
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
info "Building configure script (autoreconf)."
|
||||
autoreconf -f || error_cleanup "Autoconf failed."
|
||||
|
||||
+16
-15
@@ -79,7 +79,7 @@
|
||||
i+(int)((unsigned int)name[i]) < len) {
|
||||
memmove(buf, name + i + 1, (unsigned int)name[i]);
|
||||
buf[(unsigned int)name[i]] = 0;
|
||||
PyList_SetItem(list, cnt, PyString_FromString(buf));
|
||||
PyList_SetItem(list, cnt, PyUnicode_FromString(buf));
|
||||
}
|
||||
i += ((unsigned int)name[i]) + 1;
|
||||
cnt++;
|
||||
@@ -96,7 +96,7 @@
|
||||
|
||||
list = PyList_New(len);
|
||||
for (i=0; i < len; i++) {
|
||||
PyList_SET_ITEM(list, i, PyString_FromString(array[i]));
|
||||
PyList_SET_ITEM(list, i, PyUnicode_FromString(array[i]));
|
||||
}
|
||||
return list;
|
||||
}
|
||||
@@ -207,7 +207,7 @@ struct query_info {
|
||||
char buf[LDNS_MAX_DOMAINLEN];
|
||||
buf[0] = '\0';
|
||||
dname_str((uint8_t*)PyBytes_AsString(dname), buf);
|
||||
return PyString_FromString(buf);
|
||||
return PyUnicode_FromString(buf);
|
||||
}
|
||||
%}
|
||||
|
||||
@@ -345,7 +345,7 @@ struct packed_rrset_data {
|
||||
PyObject* _get_data_rr_len(struct packed_rrset_data* d, int idx) {
|
||||
if ((d != NULL) && (idx >= 0) &&
|
||||
((size_t)idx < (d->count+d->rrsig_count)))
|
||||
return PyInt_FromLong(d->rr_len[idx]);
|
||||
return PyLong_FromLong(d->rr_len[idx]);
|
||||
return Py_None;
|
||||
}
|
||||
void _set_data_rr_ttl(struct packed_rrset_data* d, int idx, uint32_t ttl)
|
||||
@@ -357,7 +357,7 @@ struct packed_rrset_data {
|
||||
PyObject* _get_data_rr_ttl(struct packed_rrset_data* d, int idx) {
|
||||
if ((d != NULL) && (idx >= 0) &&
|
||||
((size_t)idx < (d->count+d->rrsig_count)))
|
||||
return PyInt_FromLong(d->rr_ttl[idx]);
|
||||
return PyLong_FromLong(d->rr_ttl[idx]);
|
||||
return Py_None;
|
||||
}
|
||||
PyObject* _get_data_rr_data(struct packed_rrset_data* d, int idx) {
|
||||
@@ -555,12 +555,12 @@ struct sockaddr_storage {};
|
||||
|
||||
if (ss->ss_family == AF_INET) {
|
||||
const struct sockaddr_in *sa4 = (struct sockaddr_in *)ss;
|
||||
return PyInt_FromLong(ntohs(sa4->sin_port));
|
||||
return PyLong_FromLong(ntohs(sa4->sin_port));
|
||||
}
|
||||
|
||||
if (ss->ss_family == AF_INET6) {
|
||||
const struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)ss;
|
||||
return PyInt_FromLong(ntohs(sa6->sin6_port));
|
||||
return PyLong_FromLong(ntohs(sa6->sin6_port));
|
||||
}
|
||||
|
||||
return Py_None;
|
||||
@@ -574,7 +574,7 @@ struct sockaddr_storage {};
|
||||
}
|
||||
|
||||
sa6 = (struct sockaddr_in6 *)ss;
|
||||
return PyInt_FromLong(ntohl(sa6->sin6_flowinfo));
|
||||
return PyLong_FromLong(ntohl(sa6->sin6_flowinfo));
|
||||
}
|
||||
|
||||
PyObject *_sockaddr_storage_scope_id(const struct sockaddr_storage *ss) {
|
||||
@@ -585,7 +585,7 @@ struct sockaddr_storage {};
|
||||
}
|
||||
|
||||
sa6 = (struct sockaddr_in6 *)ss;
|
||||
return PyInt_FromLong(ntohl(sa6->sin6_scope_id));
|
||||
return PyLong_FromLong(ntohl(sa6->sin6_scope_id));
|
||||
}
|
||||
%}
|
||||
|
||||
@@ -661,7 +661,7 @@ struct edns_option {
|
||||
%inline %{
|
||||
PyObject* _edns_option_opt_code_get(struct edns_option* option) {
|
||||
uint16_t opt_code = option->opt_code;
|
||||
return PyInt_FromLong(opt_code);
|
||||
return PyLong_FromLong(opt_code);
|
||||
}
|
||||
|
||||
PyObject* _edns_option_opt_data_get(struct edns_option* option) {
|
||||
@@ -729,7 +729,8 @@ struct module_env {
|
||||
int check_ratelimit,
|
||||
struct sockaddr_storage* addr, socklen_t addrlen,
|
||||
uint8_t* zone, size_t zonelen, int tcp_upstream, int ssl_upstream,
|
||||
char* tls_auth_name, struct module_qstate* q, int* was_ratelimited);
|
||||
char* tls_auth_name, struct module_qstate* q, int* was_ratelimited,
|
||||
int* ratelimit_incremented);
|
||||
void (*detach_subs)(struct module_qstate* qstate);
|
||||
int (*attach_sub)(struct module_qstate* qstate,
|
||||
struct query_info* qinfo, struct respip_client_info* cinfo,
|
||||
@@ -1626,7 +1627,7 @@ int edns_opt_list_append(struct edns_option** list, uint16_t code, size_t len,
|
||||
}
|
||||
result = PyObject_Call(func, py_args, py_kwargs);
|
||||
if (result) {
|
||||
res = PyInt_AsLong(result);
|
||||
res = PyLong_AsLong(result);
|
||||
}
|
||||
out:
|
||||
Py_XDECREF(py_edns);
|
||||
@@ -1710,7 +1711,7 @@ out:
|
||||
}
|
||||
result = PyObject_Call(func, py_args, py_kwargs);
|
||||
if (result) {
|
||||
res = PyInt_AsLong(result);
|
||||
res = PyLong_AsLong(result);
|
||||
}
|
||||
out:
|
||||
Py_XDECREF(py_qinfo);
|
||||
@@ -1764,7 +1765,7 @@ out:
|
||||
}
|
||||
result = PyObject_Call(func, py_args, py_kwargs);
|
||||
if (result) {
|
||||
res = PyInt_AsLong(result);
|
||||
res = PyLong_AsLong(result);
|
||||
}
|
||||
out:
|
||||
Py_XDECREF(py_qstate);
|
||||
@@ -1813,7 +1814,7 @@ out:
|
||||
}
|
||||
result = PyObject_Call(func, py_args, py_kwargs);
|
||||
if (result) {
|
||||
res = PyInt_AsLong(result);
|
||||
res = PyLong_AsLong(result);
|
||||
}
|
||||
out:
|
||||
Py_XDECREF(py_qstate);
|
||||
|
||||
+18
-5
@@ -246,14 +246,14 @@ log_py_err(void)
|
||||
}
|
||||
|
||||
/* And it should be a string all ready to go - duplicate it. */
|
||||
if (!PyString_Check(obResult) && !PyUnicode_Check(obResult)) {
|
||||
if (!PyBytes_Check(obResult) && !PyUnicode_Check(obResult)) {
|
||||
log_err("pythonmod: cannot print exception, "
|
||||
"StringIO.getvalue() result did not String_Check"
|
||||
" or Unicode_Check");
|
||||
goto cleanup;
|
||||
}
|
||||
if(PyString_Check(obResult)) {
|
||||
result = PyString_AsString(obResult);
|
||||
if(PyBytes_Check(obResult)) {
|
||||
result = PyBytes_AsString(obResult);
|
||||
} else {
|
||||
ascstr = PyUnicode_AsASCIIString(obResult);
|
||||
result = PyBytes_AsString(ascstr);
|
||||
@@ -450,7 +450,7 @@ int pythonmod_init(struct module_env* env, int id)
|
||||
|
||||
pe->data = PyDict_New();
|
||||
/* add the script filename to the global "mod_env" for trivial access */
|
||||
fname = PyString_FromString(pe->fname);
|
||||
fname = PyUnicode_FromString(pe->fname);
|
||||
if(PyDict_SetItemString(pe->data, "script", fname) < 0) {
|
||||
log_err("pythonmod: could not add item to dictionary");
|
||||
Py_XDECREF(fname);
|
||||
@@ -487,10 +487,23 @@ int pythonmod_init(struct module_env* env, int id)
|
||||
/* for python 3.9 and newer */
|
||||
char* fstr = NULL;
|
||||
size_t flen = 0;
|
||||
long pos = 0;
|
||||
log_err("pythonmod: can't parse Python script %s", pe->fname);
|
||||
/* print the error to logs too, run it again */
|
||||
fseek(script_py, 0, SEEK_END);
|
||||
flen = (size_t)ftell(script_py);
|
||||
pos = ftell(script_py);
|
||||
if (pos == -1L) {
|
||||
log_err("ftell failed to print parse error: %s: %s",
|
||||
pe->fname, strerror(errno));
|
||||
goto fail_close_file;
|
||||
}
|
||||
flen = (size_t)pos;
|
||||
#ifdef SIZE_MAX
|
||||
if(flen > SIZE_MAX-2) {
|
||||
log_err("script file too large");
|
||||
goto fail_close_file;
|
||||
}
|
||||
#endif
|
||||
fstr = malloc(flen+1);
|
||||
if(!fstr) {
|
||||
log_err("malloc failure to print parse error");
|
||||
|
||||
+33
-21
@@ -734,6 +734,7 @@ respip_data_answer(enum respip_action action,
|
||||
if(!new_rep)
|
||||
return -1;
|
||||
rp->rk.flags |= PACKED_RRSET_FIXEDTTL; /* avoid adjusting TTL */
|
||||
rp->entry.hash = rrset_key_hash(&rp->rk);
|
||||
new_rep->rrsets[rrset_id] = rp;
|
||||
|
||||
*redirect_rrsetp = rp;
|
||||
@@ -899,27 +900,34 @@ respip_rewrite_reply(const struct query_info* qinfo,
|
||||
int rpz_cname_override = 0;
|
||||
char* log_name = NULL;
|
||||
|
||||
if(!cinfo)
|
||||
goto done;
|
||||
ctaglist = cinfo->taglist;
|
||||
ctaglen = cinfo->taglen;
|
||||
tag_actions = cinfo->tag_actions;
|
||||
tag_actions_size = cinfo->tag_actions_size;
|
||||
tag_datas = cinfo->tag_datas;
|
||||
tag_datas_size = cinfo->tag_datas_size;
|
||||
if(cinfo->view) {
|
||||
view = cinfo->view;
|
||||
lock_rw_rdlock(&view->lock);
|
||||
} else if(cinfo->view_name) {
|
||||
view = views_find_view(views, cinfo->view_name, 0);
|
||||
if(!view) {
|
||||
/* If the view no longer exists, the rewrite can not
|
||||
* be processed further. */
|
||||
verbose(VERB_ALGO, "respip: failed because view %s no "
|
||||
"longer exists", cinfo->view_name);
|
||||
return 0;
|
||||
if(!cinfo) {
|
||||
/* Internal mesh sub-query (e.g. dns64 A lookup): no
|
||||
* per-client view/tags, but global response-ip and RPZ
|
||||
* rpz-ip must still apply. */
|
||||
ctaglist = NULL; ctaglen = 0;
|
||||
tag_actions = NULL; tag_actions_size = 0;
|
||||
tag_datas = NULL; tag_datas_size = 0;
|
||||
} else {
|
||||
ctaglist = cinfo->taglist;
|
||||
ctaglen = cinfo->taglen;
|
||||
tag_actions = cinfo->tag_actions;
|
||||
tag_actions_size = cinfo->tag_actions_size;
|
||||
tag_datas = cinfo->tag_datas;
|
||||
tag_datas_size = cinfo->tag_datas_size;
|
||||
if(cinfo->view) {
|
||||
view = cinfo->view;
|
||||
lock_rw_rdlock(&view->lock);
|
||||
} else if(cinfo->view_name) {
|
||||
view = views_find_view(views, cinfo->view_name, 0);
|
||||
if(!view) {
|
||||
/* If the view no longer exists, the rewrite can not
|
||||
* be processed further. */
|
||||
verbose(VERB_ALGO, "respip: failed because view %s no "
|
||||
"longer exists", cinfo->view_name);
|
||||
return 0;
|
||||
}
|
||||
/* The view is rdlocked by views_find_view. */
|
||||
}
|
||||
/* The view is rdlocked by views_find_view. */
|
||||
}
|
||||
|
||||
log_assert(ipset);
|
||||
@@ -1157,8 +1165,10 @@ respip_operate(struct module_qstate* qstate, enum module_ev event, int id,
|
||||
* clients. */
|
||||
qstate->is_drop = 1;
|
||||
} else if(alias_rrset) {
|
||||
if(!generate_cname_request(qstate, alias_rrset))
|
||||
if(!generate_cname_request(qstate, alias_rrset)) {
|
||||
errinf(qstate, "Could not generate CNAME request");
|
||||
goto servfail;
|
||||
}
|
||||
next_state = module_wait_subquery;
|
||||
}
|
||||
qstate->return_msg->rep = new_rep;
|
||||
@@ -1172,6 +1182,7 @@ respip_operate(struct module_qstate* qstate, enum module_ev event, int id,
|
||||
servfail:
|
||||
qstate->return_rcode = LDNS_RCODE_SERVFAIL;
|
||||
qstate->return_msg = NULL;
|
||||
qstate->ext_state[id] = module_finished;
|
||||
}
|
||||
|
||||
int
|
||||
@@ -1268,6 +1279,7 @@ respip_inform_super(struct module_qstate* qstate, int id,
|
||||
return;
|
||||
|
||||
fail:
|
||||
errinf(super, "CNAME lookup failed");
|
||||
super->return_rcode = LDNS_RCODE_SERVFAIL;
|
||||
super->return_msg = NULL;
|
||||
return;
|
||||
|
||||
+1542
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,301 @@
|
||||
/*
|
||||
* services/authload.h - authoritative zone load thread
|
||||
*
|
||||
* Copyright (c) 2026, NLnet Labs. All rights reserved.
|
||||
*
|
||||
* This software is open source.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* Neither the name of the NLNET LABS nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* This file contains the auth load thread. This loads authority zone
|
||||
* and RPZ zone information in a thread, in a separate memory structure.
|
||||
* When it is done, the information is swapped over to the running server.
|
||||
*/
|
||||
|
||||
#ifndef SERVICES_AUTHLOAD_H
|
||||
#define SERVICES_AUTHLOAD_H
|
||||
#include "util/locks.h"
|
||||
#include "util/rbtree.h"
|
||||
struct worker;
|
||||
struct daemon;
|
||||
struct auth_xfer;
|
||||
struct module_env;
|
||||
struct auth_load_task;
|
||||
struct comm_timer;
|
||||
|
||||
/**
|
||||
* General information for auth load threads. The number of active threads.
|
||||
*/
|
||||
struct auth_load_general_info {
|
||||
/** lock on this structure. It is after the auth_zones lock, and
|
||||
* after the auth_xfer locks. */
|
||||
lock_basic_type lock;
|
||||
/** The number of active auth load threads. */
|
||||
int num_auth_load_threads;
|
||||
/** The number of active downloads, zone transfers in progress.
|
||||
* These are going to need an auth load thread when done. The counter
|
||||
* is decremented when the thread and transfer have completed. */
|
||||
int num_auth_transfers;
|
||||
/** The auth zone xfer transfer wait list */
|
||||
struct auth_xfer* wait_transfer_list;
|
||||
/** The last item of the wait_transfer list. */
|
||||
struct auth_xfer* wait_transfer_last;
|
||||
/** To resume from a waiting item, the callback, at zero timeout is
|
||||
* used. That breaks out of callbacks and handles the items there.
|
||||
* If the timer is set, this is true. */
|
||||
int resume_timer_enabled;
|
||||
/** The resume timer for the wait_transfer list. */
|
||||
struct comm_timer* resume_timer;
|
||||
/** The worker env for the resume timer. It is set in the event base
|
||||
* of that worker. */
|
||||
struct module_env* resume_env;
|
||||
};
|
||||
|
||||
/**
|
||||
* The types of notifications that the auth load thread sends around.
|
||||
*/
|
||||
enum auth_load_notification_type {
|
||||
/** This is sent to make the auth load thread perform exit */
|
||||
auth_load_notification_exit
|
||||
};
|
||||
|
||||
/**
|
||||
* The auth load thread. The thread runs to load authority zone information
|
||||
* and RPZ information into memory. It loads into a copy. Then that is swapped
|
||||
* over to the running server. This keeps the server responsive while the
|
||||
* information is loaded.
|
||||
*/
|
||||
struct auth_load_thread {
|
||||
/** the thread number for the thread,
|
||||
* must be first to cast thread arg to int* in checklock code. */
|
||||
int threadnum;
|
||||
/** thread id, of the io thread */
|
||||
ub_thread_type tid;
|
||||
#ifdef HAVE_GETTID
|
||||
/** thread tid, the LWP id */
|
||||
pid_t thread_tid;
|
||||
/** if logging should include the LWP id */
|
||||
int thread_tid_log;
|
||||
#endif
|
||||
|
||||
/** communication socket pair, that sends commands */
|
||||
int commpair[2];
|
||||
/** if the thread has to quit */
|
||||
int need_to_quit;
|
||||
/** the event that listens on the worker to commpair,
|
||||
* it receives content from the auth load thread. */
|
||||
void* service_event;
|
||||
/** if the event that listens on the worker has
|
||||
* been added to the comm base. */
|
||||
int service_event_is_added;
|
||||
|
||||
/** the worker that the auth load is connected to */
|
||||
struct worker* worker;
|
||||
/** if the thread is inserted in the tree at the worker. */
|
||||
int tree_inserted;
|
||||
/** the rbtree node for the worker tree of auth load threads. */
|
||||
rbnode_type node;
|
||||
|
||||
/** The task that the thread is working on */
|
||||
struct auth_load_task* task;
|
||||
};
|
||||
|
||||
/**
|
||||
* The types of tasks that the auth load can perform.
|
||||
*/
|
||||
enum auth_load_task_type {
|
||||
AUTH_LOAD_TASK_TRANSFER,
|
||||
AUTH_LOAD_TASK_ZONEFILE_READ,
|
||||
AUTH_LOAD_TASK_ZONEFILE_WRITE,
|
||||
AUTH_LOAD_TASK_HTTPCHUNKS
|
||||
};
|
||||
|
||||
/**
|
||||
* The task for the auth load. The task can be to load a zone transfer, AXFR,
|
||||
* IXFR, from zonefile, and from a http read, from chunks.
|
||||
*/
|
||||
struct auth_load_task {
|
||||
/** The type of the task */
|
||||
enum auth_load_task_type task_type;
|
||||
/** The task is connected with this worker */
|
||||
struct worker* worker;
|
||||
|
||||
/** The zone name */
|
||||
uint8_t* name;
|
||||
/** The zone namelen */
|
||||
size_t namelen;
|
||||
/** The zone class */
|
||||
uint16_t dclass;
|
||||
|
||||
/** name of the host that the transfer comes from. */
|
||||
char* host;
|
||||
/** file part of the url that the transfer comes from, or NULL. */
|
||||
char* file;
|
||||
/** Set if the host is http transfer, if false it is AXFR or IXFR. */
|
||||
int on_http;
|
||||
/** Set if the transfer is doing IXFR */
|
||||
int on_ixfr;
|
||||
/** Set if the transfer is an IXFR but we detected an AXFR contents */
|
||||
int on_ixfr_is_axfr;
|
||||
/** The zone is an rpz zone. */
|
||||
int is_rpz;
|
||||
|
||||
/** Set if the ixfr failed. (So that there can be backoff to AXFR). */
|
||||
int ixfr_fail;
|
||||
|
||||
/** current serial (from SOA), if we have no zone, 0
|
||||
* This is for checking the IXFR result. */
|
||||
uint32_t serial;
|
||||
|
||||
/** the data chunks, or NULL, to process. */
|
||||
struct auth_chunk* chunks_first;
|
||||
/** last data chunk */
|
||||
struct auth_chunk* chunks_last;
|
||||
/** size of data in data chunks. */
|
||||
size_t chunks_total;
|
||||
|
||||
/** time taken for the task */
|
||||
struct timeval time_taken;
|
||||
/** time taken for the reload part of the task */
|
||||
struct timeval time_reload;
|
||||
/** memory used for the task */
|
||||
size_t mem_used;
|
||||
};
|
||||
|
||||
/**
|
||||
* Add a new task to be performed by the auth load thread.
|
||||
* It starts a thread.
|
||||
* @param xfr: zone transfer to start for.
|
||||
* @param worker: worker that is connected to the task.
|
||||
* @return false on failure.
|
||||
*/
|
||||
int auth_load_add_task_xfr(struct auth_xfer* xfr, struct worker* worker);
|
||||
|
||||
/**
|
||||
* Add a new task to be performed by the auth load thread.
|
||||
* It starts a thread. This writes to zonefile.
|
||||
* @param name: name of zone, wireformat.
|
||||
* @param namelen: length of name.
|
||||
* @param dclass: class of the zone.
|
||||
* @param env: the module env.
|
||||
* @param chunk_list: for writes after http, the chunk list with data.
|
||||
* @return false on failure to create the thread.
|
||||
*/
|
||||
int auth_load_add_task_write(uint8_t* name, size_t namelen, uint16_t dclass,
|
||||
struct module_env* env, struct auth_chunk* chunk_list);
|
||||
|
||||
/** See if there is a quit signal, true if so. */
|
||||
int auth_load_thread_poll_for_quit(struct auth_load_thread* thr);
|
||||
|
||||
/**
|
||||
* Create auth load info structure.
|
||||
* @return NULL on failure.
|
||||
*/
|
||||
struct auth_load_general_info* auth_load_info_create(void);
|
||||
|
||||
/**
|
||||
* Delete auth load info structure.
|
||||
* @param auth_load_info: to delete.
|
||||
*/
|
||||
void auth_load_info_delete(struct auth_load_general_info* auth_load_info);
|
||||
|
||||
/**
|
||||
* Grab a new thread from the auth load count.
|
||||
* @param env: with auth_load_info with the active thread count.
|
||||
* and config file, with configured maximum.
|
||||
* @return false on failure, like too many active, true if successful.
|
||||
*/
|
||||
int auth_load_info_grab_thread(struct module_env* env);
|
||||
|
||||
/**
|
||||
* Release thread from auth load count. It is done.
|
||||
* @param env: with auth_load_info with the active thread count.
|
||||
*/
|
||||
void auth_load_info_release_thread(struct module_env* env);
|
||||
|
||||
/**
|
||||
* Grab a new transfer in progress, this is limited by the auth load count.
|
||||
* @param env: with auth_load_info with the active transfer number.
|
||||
* and config file, with configured maximum.
|
||||
* @return false on failure, like too many active, true if successful.
|
||||
*/
|
||||
int auth_load_info_grab_transfer_in_progress(struct module_env* env);
|
||||
|
||||
/**
|
||||
* Release transfer from active count. It is done.
|
||||
* @param env: with auth_load_info with the active transfer count.
|
||||
*/
|
||||
void auth_load_info_release_transfer_in_progress(struct module_env* env);
|
||||
|
||||
/**
|
||||
* Make transfer active in the in progress transfer count.
|
||||
* @param xfr: the xfr is in progress
|
||||
* @return false if not possible.
|
||||
*/
|
||||
int xfr_transfer_grab_active(struct auth_xfer* xfr);
|
||||
|
||||
/**
|
||||
* Release active transfer from in progress transfer count.
|
||||
* @param xfr: the xfr is no longer in progress.
|
||||
*/
|
||||
void xfr_transfer_release_active(struct auth_xfer* xfr);
|
||||
|
||||
/**
|
||||
* Add transfer to wait_transfer list. It can not become active right now.
|
||||
* @param xfr: the xfr is put on the wait_transfer list.
|
||||
*/
|
||||
void xfr_transfer_wait_active(struct auth_xfer* xfr);
|
||||
|
||||
/**
|
||||
* Remove xfr from wait_transfer list
|
||||
* @param xfr: the xfr is removed from the wait_transfer list.
|
||||
*/
|
||||
void xfr_transfer_remove_wait_transfer_list(struct auth_xfer* xfr);
|
||||
|
||||
/** The timer callback for the wait_transfer resume timer. */
|
||||
void auth_load_resume_timer_cb(void* arg);
|
||||
|
||||
/** Schedule pick up of waiting transfers. */
|
||||
void auth_load_schedule_waiting_pickup(struct module_env* env);
|
||||
|
||||
/** Compare auth load tree entries, in the worker auth load tree. */
|
||||
int auth_load_tree_cmp(const void* a, const void* b);
|
||||
|
||||
/** Delete tasks for the zone. The write and xfr tasks for that name, class
|
||||
* are sent a quit signal, and the thread is joined, as it exits. */
|
||||
void auth_load_del_zone_tasks(struct worker* worker, uint8_t* name,
|
||||
size_t namelen, uint16_t dclass);
|
||||
|
||||
/** Stop all the auth load threads. */
|
||||
void auth_load_stop_threads(struct daemon* daemon);
|
||||
|
||||
#endif /* SERVICES_AUTHLOAD_H */
|
||||
+1041
-253
File diff suppressed because it is too large
Load Diff
+99
-1
@@ -65,6 +65,7 @@ struct auth_probe;
|
||||
struct auth_transfer;
|
||||
struct auth_master;
|
||||
struct auth_chunk;
|
||||
struct auth_load_thread;
|
||||
|
||||
/**
|
||||
* Authoritative zones, shared.
|
||||
@@ -144,6 +145,14 @@ struct auth_zone {
|
||||
struct module_env* zonemd_callback_env;
|
||||
/** for the zonemd callback, the type of data looked up */
|
||||
uint16_t zonemd_callback_qtype;
|
||||
/** for the zonemd callback, the unique info */
|
||||
void* zonemd_callback_unique_info;
|
||||
/** if the zonemd callback should write to file */
|
||||
int zonemd_callback_perform_write;
|
||||
/** chunklist to write for chunked transfer. */
|
||||
struct auth_chunk* perform_write_chunk_list;
|
||||
/** The zonemd transfer is an active transfer (for auth load info) */
|
||||
int zonemd_transfer_active;
|
||||
/** zone has been deleted */
|
||||
int zone_deleted;
|
||||
/** deletelist pointer, unused normally except during delete */
|
||||
@@ -153,6 +162,10 @@ struct auth_zone {
|
||||
struct auth_zone* rpz_az_next;
|
||||
/** previous auth zone containing RPZ data, or NULL */
|
||||
struct auth_zone* rpz_az_prev;
|
||||
/** The maximum auth zone transfer size, in bytes. */
|
||||
size_t max_transfer_size;
|
||||
/** The maximum auth zone transfer time taken, in msec. */
|
||||
int max_transfer_time;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -283,6 +296,15 @@ struct auth_xfer {
|
||||
* this is renewed every SOA probe and transfer. On zone load
|
||||
* from zonefile it is also set (with probe set soon to check) */
|
||||
time_t lease_time;
|
||||
|
||||
/** The maximum auth zone transfer size, in bytes. */
|
||||
size_t max_transfer_size;
|
||||
/** The maximum auth zone transfer time taken, in msec. */
|
||||
int max_transfer_time;
|
||||
/** the zone is an rpz zone */
|
||||
int is_rpz;
|
||||
/** the number of IXFRs since the last full transfer. */
|
||||
int num_ixfrs;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -331,6 +353,8 @@ struct auth_probe {
|
||||
|
||||
/** for the hostname lookups, which master is current */
|
||||
struct auth_master* lookup_target;
|
||||
/** for the lookup, the callback unique info */
|
||||
void* lookup_unique_info;
|
||||
/** are we looking up A or AAAA, first A, then AAAA (if ip6 enabled) */
|
||||
int lookup_aaaa;
|
||||
/** we only want to do lookups for making config work (for notify),
|
||||
@@ -379,12 +403,27 @@ struct auth_transfer {
|
||||
struct auth_chunk* chunks_first;
|
||||
/** last element in chunks list (to append new data at the end) */
|
||||
struct auth_chunk* chunks_last;
|
||||
/** running total of bytes held in chunks_first..chunks_last */
|
||||
size_t chunks_total;
|
||||
/** start time of the transfer */
|
||||
struct timeval start_time;
|
||||
/** if the transfer is active and in the in progress count. */
|
||||
int active_transfer;
|
||||
/** if the transfer is on the wait_transfer list (it waits to
|
||||
* become active). */
|
||||
int on_wait_transfer_list;
|
||||
/** If on the wait_transfer list, the previous list item. */
|
||||
struct auth_xfer* wait_transfer_prev;
|
||||
/** If on the wait_transfer list, the next list item. */
|
||||
struct auth_xfer* wait_transfer_next;
|
||||
|
||||
/** list of upstream masters for this zone, from config */
|
||||
struct auth_master* masters;
|
||||
|
||||
/** for the hostname lookups, which master is current */
|
||||
struct auth_master* lookup_target;
|
||||
/** for the lookup, the callback unique info */
|
||||
void* lookup_unique_info;
|
||||
/** are we looking up A or AAAA, first A, then AAAA (if ip6 enabled) */
|
||||
int lookup_aaaa;
|
||||
|
||||
@@ -518,7 +557,15 @@ void auth_zones_delete(struct auth_zones* az);
|
||||
/**
|
||||
* Write auth zone data to file, in zonefile format.
|
||||
*/
|
||||
int auth_zone_write_file(struct auth_zone* z, const char* fname);
|
||||
int auth_zone_write_file(struct auth_zone* z, const char* fname,
|
||||
struct auth_load_thread* thr);
|
||||
|
||||
/** write to zonefile after zone has updated, reacquires z readlock.
|
||||
* The chunk list is freed on return.
|
||||
* If the zone is gone, chunk_list is freed (if non NULL). */
|
||||
void zone_write_after_update_reacq(uint8_t* name, size_t namelen,
|
||||
uint16_t dclass, struct module_env* env,
|
||||
struct auth_chunk* chunk_list, struct auth_load_thread* thr);
|
||||
|
||||
/**
|
||||
* Use auth zones to lookup the answer to a query.
|
||||
@@ -828,4 +875,55 @@ void auth_xfer_delete(struct auth_xfer* xfr);
|
||||
*/
|
||||
void xfr_disown_tasks(struct auth_xfer* xfr, struct worker* worker);
|
||||
|
||||
/** count number of open and closed parenthesis in a chunkline */
|
||||
int chunkline_count_parens(struct sldns_buffer* buf, size_t start);
|
||||
|
||||
/** Clear data in auth zone */
|
||||
void auth_zone_clear_data(struct auth_zone* z);
|
||||
|
||||
/** Get memory usage of auth zone */
|
||||
size_t auth_zone_get_mem(struct auth_zone* z);
|
||||
|
||||
/** create domain with the given name */
|
||||
struct auth_data* az_domain_create(struct auth_zone* z, uint8_t* nm,
|
||||
size_t nmlen);
|
||||
|
||||
/** helper traverse to delete zones */
|
||||
void auth_data_del(rbnode_type* n, void* arg);
|
||||
|
||||
/** Pick up xfr task from wait_transfer resumption. xfr is locked on entry,
|
||||
* unlocked at return. */
|
||||
void xfr_pick_up_transfer(struct auth_xfer* xfr, struct module_env* env);
|
||||
|
||||
/** Handle the end of an auth load task. */
|
||||
void xfr_process_load_end_transfer(struct auth_xfer* xfr,
|
||||
struct module_env* env, uint8_t status, int ixfr_fail,
|
||||
struct timeval* time_taken, struct timeval* time_reload,
|
||||
size_t mem_used, size_t chunks_total, struct auth_chunk* chunk_list);
|
||||
|
||||
/** Handle the end of an auth load task to write. */
|
||||
void auth_zone_process_load_end_write(struct module_env* env);
|
||||
|
||||
/** Log preview of http transfer */
|
||||
void xfr_http_preview(const char* file, struct auth_chunk* chunk_list);
|
||||
|
||||
/** Check syntax of first part of the http download */
|
||||
int xfr_http_syntax_check(uint8_t* name, size_t namelen, uint16_t dclass,
|
||||
const char* host, const char* file, struct auth_chunk* chunk_list,
|
||||
struct sldns_buffer* scratch_buffer);
|
||||
|
||||
/** Apply http transfer to auth_zone */
|
||||
int xfr_apply_http(uint8_t* name, size_t namelen, const char* host,
|
||||
const char* file, struct auth_chunk* chunk_list, struct auth_zone* z,
|
||||
struct sldns_buffer* scratch_buffer, struct auth_load_thread* thr);
|
||||
|
||||
/** Apply IXFR transfer to auth_zone */
|
||||
int xfr_apply_ixfr(struct auth_chunk* chunk_list, uint32_t xfr_serial,
|
||||
struct auth_zone* z, struct sldns_buffer* scratch_buffer,
|
||||
struct auth_load_thread* thr);
|
||||
|
||||
/** Apply AXFR transfer to auth_zone */
|
||||
int xfr_apply_axfr(struct auth_chunk* chunk_list, struct auth_zone* z,
|
||||
struct sldns_buffer* scratch_buffer, struct auth_load_thread* thr);
|
||||
|
||||
#endif /* SERVICES_AUTHZONE_H */
|
||||
|
||||
Vendored
+20
-5
@@ -43,6 +43,7 @@
|
||||
#include "iterator/iter_utils.h"
|
||||
#include "validator/val_nsec.h"
|
||||
#include "validator/val_utils.h"
|
||||
#include "iterator/iter_utils.h"
|
||||
#include "services/cache/dns.h"
|
||||
#include "services/cache/rrset.h"
|
||||
#include "util/data/msgparse.h"
|
||||
@@ -94,7 +95,8 @@ store_rrsets(struct module_env* env, struct reply_info* rep, time_t now,
|
||||
case 2: /* ref updated, cache is superior */
|
||||
if(region) {
|
||||
struct ub_packed_rrset_key* ck;
|
||||
lock_rw_rdlock(&rep->ref[i].key->entry.lock);
|
||||
/* the entry is already readlocked from the
|
||||
* check in rrset_cache_update. */
|
||||
/* if deleted rrset, do not copy it */
|
||||
if(rep->ref[i].key->id == 0 ||
|
||||
rep->ref[i].id != rep->ref[i].key->id)
|
||||
@@ -115,6 +117,8 @@ store_rrsets(struct module_env* env, struct reply_info* rep, time_t now,
|
||||
qrep->serve_expired_ttl = qrep->ttl + SERVE_EXPIRED_TTL;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
lock_rw_unlock(&rep->ref[i].key->entry.lock);
|
||||
}
|
||||
/* no break: also copy key item */
|
||||
/* the line below is matched by gcc regex and silences
|
||||
@@ -586,8 +590,12 @@ dns_cache_find_delegation(struct module_env* env, uint8_t* qname,
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
if(!delegpt_rrset_add_ns(dp, region, nskey, 0))
|
||||
if(!delegpt_rrset_add_ns(dp, region, nskey, 0,
|
||||
deleg_port_number(env))) {
|
||||
lock_rw_unlock(&nskey->entry.lock);
|
||||
log_err("find_delegation: addns out of memory");
|
||||
return NULL;
|
||||
}
|
||||
lock_rw_unlock(&nskey->entry.lock); /* first unlock before next lookup*/
|
||||
/* find and add DS/NSEC (if any) */
|
||||
if(msg)
|
||||
@@ -672,7 +680,7 @@ tomsg(struct module_env* env, struct query_info* q, struct reply_info* r,
|
||||
rrset_array_unlock(r->ref, r->rrset_count);
|
||||
return NULL;
|
||||
}
|
||||
if(r->security == sec_status_secure && !reply_all_rrsets_secure(r)) {
|
||||
if(r->security == sec_status_secure && !reply_an_ns_rrsets_secure(r)) {
|
||||
/* message rrsets have changed status, revalidate */
|
||||
rrset_array_unlock(r->ref, r->rrset_count);
|
||||
return NULL;
|
||||
@@ -782,11 +790,16 @@ synth_dname_msg(struct ub_packed_rrset_key* rrset, struct regional* region,
|
||||
uint8_t* newname, *dtarg = NULL;
|
||||
size_t newlen, dtarglen;
|
||||
time_t rr_ttl;
|
||||
int graceperiod = 0;
|
||||
if(TTL_IS_EXPIRED(d->ttl, now)) {
|
||||
/* Allow TTL=0 DNAME from upstream within grace period */
|
||||
if(!(rrset->rk.flags & PACKED_RRSET_UPSTREAM_0TTL))
|
||||
return NULL;
|
||||
rr_ttl = 0;
|
||||
/* Since PACKED_RRSET_UPSTREAM_0TTL set the flag that
|
||||
* the grace period has been applied, this stops the rrset
|
||||
* from getting stored back into the cache with a bigger TTL.*/
|
||||
graceperiod = 1;
|
||||
} else {
|
||||
rr_ttl = d->ttl - now;
|
||||
}
|
||||
@@ -814,6 +827,8 @@ synth_dname_msg(struct ub_packed_rrset_key* rrset, struct regional* region,
|
||||
msg->rep->rrsets[0] = packed_rrset_copy_region(rrset, region, now);
|
||||
if(!msg->rep->rrsets[0]) /* copy DNAME */
|
||||
return NULL;
|
||||
if(graceperiod)
|
||||
msg->rep->rrsets[0]->rk.flags |= PACKED_RRSET_0TTL_GRACE;
|
||||
/* synth CNAME rrset */
|
||||
get_cname_target(rrset, &dtarg, &dtarglen);
|
||||
if(!dtarg)
|
||||
@@ -1196,9 +1211,9 @@ dns_cache_store(struct module_env* env, struct query_info* msgqinf,
|
||||
rep->rrsets[i]->entry.data, *env->now);
|
||||
ref.key = rep->rrsets[i];
|
||||
ref.id = rep->rrsets[i]->id;
|
||||
/*ignore ret: it was in the cache, ref updated */
|
||||
/* if it was in the cache, ref updated */
|
||||
/* no leeway for typeNS */
|
||||
(void)rrset_cache_update(env->rrset_cache, &ref,
|
||||
rrset_cache_update_unlock(env->rrset_cache, &ref,
|
||||
env->alloc,
|
||||
((ntohs(ref.key->rk.type)==LDNS_RR_TYPE_NS
|
||||
&& !pside) ? qstarttime:*env->now + leeway));
|
||||
|
||||
Vendored
+32
-8
@@ -215,6 +215,13 @@ rrset_cache_update(struct rrset_cache* r, struct rrset_ref* ref,
|
||||
int equal = 0;
|
||||
log_assert(ref->id != 0 && k->id != 0);
|
||||
log_assert(k->rk.dname != NULL);
|
||||
if((k->rk.flags&PACKED_RRSET_0TTL_GRACE) !=0) {
|
||||
log_nametypeclass(VERB_ALGO, "rrset store of PACKED_RRSET_0TTL_GRACE rrset skipped", k->rk.dname, rrset_type, ntohs(k->rk.rrset_class));
|
||||
ub_packed_rrset_parsedelete(k, alloc);
|
||||
return 0; /* Do not store 0TTL items after apply of
|
||||
the grace ttl amount.
|
||||
This means the ref was not changed by the call. */
|
||||
}
|
||||
/* looks up item with a readlock - no editing! */
|
||||
if((e=slabhash_lookup(&r->table, h, k, 0)) != 0) {
|
||||
/* return id and key as they will be used in the cache
|
||||
@@ -232,9 +239,13 @@ rrset_cache_update(struct rrset_cache* r, struct rrset_ref* ref,
|
||||
equal, (rrset_type==LDNS_RR_TYPE_NS),
|
||||
(rrset_type==LDNS_RR_TYPE_A || rrset_type==LDNS_RR_TYPE_AAAA))) {
|
||||
/* cache is superior, return that value */
|
||||
if(equal) {
|
||||
ub_packed_rrset_parsedelete(k, alloc);
|
||||
/* return readlocked item. */
|
||||
return 2;
|
||||
}
|
||||
lock_rw_unlock(&e->lock);
|
||||
ub_packed_rrset_parsedelete(k, alloc);
|
||||
if(equal) return 2;
|
||||
return 1;
|
||||
}
|
||||
lock_rw_unlock(&e->lock);
|
||||
@@ -262,6 +273,15 @@ rrset_cache_update(struct rrset_cache* r, struct rrset_ref* ref,
|
||||
return 0;
|
||||
}
|
||||
|
||||
void rrset_cache_update_unlock(struct rrset_cache* r, struct rrset_ref* ref,
|
||||
struct alloc_cache* alloc, time_t timenow)
|
||||
{
|
||||
int ret = rrset_cache_update(r, ref, alloc, timenow);
|
||||
if(ret == 2) {
|
||||
lock_rw_unlock(&ref->key->entry.lock);
|
||||
}
|
||||
}
|
||||
|
||||
/** See if the name is a within signer authority */
|
||||
static int
|
||||
dname_subdomain_rrsig_signers(uint8_t* dname,
|
||||
@@ -291,6 +311,8 @@ void rrset_cache_update_wildcard(struct rrset_cache* rrset_cache,
|
||||
{
|
||||
struct rrset_ref ref;
|
||||
uint8_t wc_dname[LDNS_MAX_DOMAINLEN+3];
|
||||
uint8_t* new_dname;
|
||||
size_t new_dname_len;
|
||||
|
||||
/* See if the RRSIG signer name allows this wildcard,
|
||||
* the new rrset should fall within the zone of the RRSIG signer(s). */
|
||||
@@ -310,20 +332,22 @@ void rrset_cache_update_wildcard(struct rrset_cache* rrset_cache,
|
||||
wc_dname[1] = (uint8_t)'*';
|
||||
memmove(wc_dname+2, ce, ce_len);
|
||||
|
||||
free(rrset->rk.dname);
|
||||
rrset->rk.dname_len = ce_len + 2;
|
||||
rrset->rk.dname = (uint8_t*)memdup(wc_dname, rrset->rk.dname_len);
|
||||
if(!rrset->rk.dname) {
|
||||
alloc_special_release(alloc, rrset);
|
||||
new_dname_len = ce_len + 2;
|
||||
new_dname = (uint8_t*)memdup(wc_dname, new_dname_len);
|
||||
if(!new_dname) {
|
||||
ub_packed_rrset_parsedelete(rrset, alloc);
|
||||
log_err("memdup failure in rrset_cache_update_wildcard");
|
||||
return;
|
||||
}
|
||||
free(rrset->rk.dname);
|
||||
rrset->rk.dname = new_dname;
|
||||
rrset->rk.dname_len = new_dname_len;
|
||||
|
||||
rrset->entry.hash = rrset_key_hash(&rrset->rk);
|
||||
ref.key = rrset;
|
||||
ref.id = rrset->id;
|
||||
/* ignore ret: if it was in the cache, ref updated */
|
||||
(void)rrset_cache_update(rrset_cache, &ref, alloc, timenow);
|
||||
/* if it was in the cache, ref updated */
|
||||
rrset_cache_update_unlock(rrset_cache, &ref, alloc, timenow);
|
||||
}
|
||||
|
||||
/** Grace period in seconds for TTL=0 DNAME rrsets (RFC 2308: do not cache).
|
||||
|
||||
Vendored
+6
@@ -129,10 +129,16 @@ void rrset_cache_touch(struct rrset_cache* r, struct ub_packed_rrset_key* key,
|
||||
* 1: reference updated, item is inserted in cache.
|
||||
* 2: reference updated, item in cache is considered superior.
|
||||
* also the rdata is equal (but other parameters in cache are superior).
|
||||
* In case 2 the item is returned under a readlock. The caller must
|
||||
* unlock.
|
||||
*/
|
||||
int rrset_cache_update(struct rrset_cache* r, struct rrset_ref* ref,
|
||||
struct alloc_cache* alloc, time_t timenow);
|
||||
|
||||
/** The rrset_cache_update routine that unlocks at end */
|
||||
void rrset_cache_update_unlock(struct rrset_cache* r, struct rrset_ref* ref,
|
||||
struct alloc_cache* alloc, time_t timenow);
|
||||
|
||||
/**
|
||||
* Update or add an rrset in the rrset cache using a wildcard dname.
|
||||
* Generates wildcard dname by prepending the wildcard label to the closest
|
||||
|
||||
+42
-12
@@ -1125,7 +1125,7 @@ make_sock_port(int stype, const char* ifname, int port,
|
||||
int use_systemd, int dscp, struct unbound_socket* ub_sock,
|
||||
const char* additional)
|
||||
{
|
||||
char* s = strchr(ifname, '@');
|
||||
const char* s = strchr(ifname, '@');
|
||||
if(s) {
|
||||
/* override port with ifspec@port */
|
||||
int port;
|
||||
@@ -1341,13 +1341,33 @@ ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp,
|
||||
if((is_doq) && !(is_https || is_ssl)) do_tcp = 0;
|
||||
|
||||
if(do_auto) {
|
||||
enum listen_type auto_port_type;
|
||||
ub_sock = calloc(1, sizeof(struct unbound_socket));
|
||||
if(!ub_sock)
|
||||
return 0;
|
||||
if(is_dnscrypt) {
|
||||
auto_port_type = listen_type_udpancil_dnscrypt;
|
||||
add = "udpancil_dnscrypt";
|
||||
} else if(is_doq) {
|
||||
auto_port_type = listen_type_doq;
|
||||
add = "doq";
|
||||
if(if_listens_on(ifname, port, 53, NULL)) {
|
||||
log_err("DNS over QUIC is strictly not "
|
||||
"allowed on port 53 as per RFC 9250. "
|
||||
"Port 53 is for DNS datagrams. Error "
|
||||
"for interface '%s'.", ifname);
|
||||
free(ub_sock->addr);
|
||||
free(ub_sock);
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
auto_port_type = listen_type_udpancil;
|
||||
add = "udpancil";
|
||||
}
|
||||
if((s = make_sock_port(SOCK_DGRAM, ifname, port, hints, 1,
|
||||
&noip6, rcv, snd, reuseport, transparent,
|
||||
tcp_mss, nodelay, freebind, use_systemd, dscp, ub_sock,
|
||||
(is_dnscrypt?"udpancil_dnscrypt":"udpancil"))) == -1) {
|
||||
add)) == -1) {
|
||||
free(ub_sock->addr);
|
||||
free(ub_sock);
|
||||
if(noip6) {
|
||||
@@ -1366,9 +1386,7 @@ ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp,
|
||||
if (sock_queue_timeout && !set_recvtimestamp(s)) {
|
||||
log_warn("socket timestamping is not available");
|
||||
}
|
||||
if(!port_insert(list, s, is_dnscrypt
|
||||
?listen_type_udpancil_dnscrypt:listen_type_udpancil,
|
||||
is_pp2, ub_sock)) {
|
||||
if(!port_insert(list, s, auto_port_type, is_pp2, ub_sock)) {
|
||||
sock_close(s);
|
||||
free(ub_sock->addr);
|
||||
free(ub_sock);
|
||||
@@ -2133,7 +2151,7 @@ void listen_start_accept(struct listen_dnsport* listen)
|
||||
}
|
||||
|
||||
struct tcp_req_info*
|
||||
tcp_req_info_create(struct sldns_buffer* spoolbuf)
|
||||
tcp_req_info_create(struct comm_base* base, struct sldns_buffer* spoolbuf)
|
||||
{
|
||||
struct tcp_req_info* req = (struct tcp_req_info*)malloc(sizeof(*req));
|
||||
if(!req) {
|
||||
@@ -2141,6 +2159,12 @@ tcp_req_info_create(struct sldns_buffer* spoolbuf)
|
||||
return NULL;
|
||||
}
|
||||
memset(req, 0, sizeof(*req));
|
||||
req->read_again_timer = comm_timer_create(base, tcp_read_again_cb, req);
|
||||
if(!req->read_again_timer) {
|
||||
log_err("malloc failure");
|
||||
free(req);
|
||||
return NULL;
|
||||
}
|
||||
req->spool_buffer = spoolbuf;
|
||||
return req;
|
||||
}
|
||||
@@ -2150,6 +2174,7 @@ tcp_req_info_delete(struct tcp_req_info* req)
|
||||
{
|
||||
if(!req) return;
|
||||
tcp_req_info_clear(req);
|
||||
comm_timer_delete(req->read_again_timer);
|
||||
/* cp is pointer back to commpoint that owns this struct and
|
||||
* called delete on us */
|
||||
/* spool_buffer is shared udp buffer, not deleted here */
|
||||
@@ -2167,7 +2192,7 @@ void tcp_req_info_clear(struct tcp_req_info* req)
|
||||
while(open) {
|
||||
nopen = open->next;
|
||||
mesh_state_remove_reply(open->mesh, open->mesh_state, req->cp,
|
||||
NULL);
|
||||
NULL, NULL);
|
||||
free(open);
|
||||
open = nopen;
|
||||
}
|
||||
@@ -2189,6 +2214,9 @@ void tcp_req_info_clear(struct tcp_req_info* req)
|
||||
req->done_req_list = NULL;
|
||||
req->num_done_req = 0;
|
||||
req->read_is_closed = 0;
|
||||
|
||||
if(comm_timer_is_set(req->read_again_timer))
|
||||
comm_timer_disable(req->read_again_timer);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -3617,7 +3645,7 @@ stream_tree_del(rbnode_type* node, void* arg)
|
||||
stream = (struct doq_stream*)node;
|
||||
if(stream->mesh_state) {
|
||||
mesh_state_remove_reply(stream->mesh, stream->mesh_state,
|
||||
args->conn->doq_socket->cp, stream);
|
||||
args->conn->doq_socket->cp, NULL, stream);
|
||||
stream->mesh_state = NULL;
|
||||
}
|
||||
if(stream->in)
|
||||
@@ -3639,7 +3667,8 @@ doq_conn_delete(struct doq_conn* conn, struct doq_table* table)
|
||||
lock_rw_unlock(&conn->table->conid_lock);
|
||||
/* Remove the app data from ngtcp2 before SSL_free of conn->ssl,
|
||||
* because the ngtcp2 conn is deleted. */
|
||||
SSL_set_app_data(conn->ssl, NULL);
|
||||
if(conn->ssl)
|
||||
SSL_set_app_data(conn->ssl, NULL);
|
||||
if(conn->stream_tree.count != 0) {
|
||||
struct doq_stream_tree_del_args args;
|
||||
memset(&args, 0, sizeof(args));
|
||||
@@ -3956,7 +3985,7 @@ doq_stream_close(struct doq_conn* conn, struct doq_stream* stream,
|
||||
stream->is_closed = 1;
|
||||
if(stream->mesh_state) {
|
||||
mesh_state_remove_reply(stream->mesh, stream->mesh_state,
|
||||
conn->doq_socket->cp, stream);
|
||||
conn->doq_socket->cp, NULL, stream);
|
||||
stream->mesh_state = NULL;
|
||||
}
|
||||
doq_stream_off_write_list(conn, stream);
|
||||
@@ -4503,7 +4532,7 @@ doq_stream_reset_cb(ngtcp2_conn* ATTR_UNUSED(conn), int64_t stream_id,
|
||||
"unknown stream %d", (int)stream_id);
|
||||
return 0;
|
||||
}
|
||||
if(!doq_stream_close(doq_conn, stream, 0))
|
||||
if(!doq_stream_close(doq_conn, stream, 1))
|
||||
return NGTCP2_ERR_CALLBACK_FAILURE;
|
||||
return 0;
|
||||
}
|
||||
@@ -4851,7 +4880,7 @@ doq_ssl_server_setup(SSL_CTX* ctx, struct doq_conn* conn)
|
||||
SSL_set_app_data(ssl, conn);
|
||||
#endif
|
||||
SSL_set_accept_state(ssl);
|
||||
#ifdef USE_NGTCP2_CRYPTO_OSSL
|
||||
#ifdef HAVE_SSL_SET_QUIC_TLS_EARLY_DATA_ENABLED
|
||||
SSL_set_quic_tls_early_data_enabled(ssl, 1);
|
||||
#else
|
||||
SSL_set_quic_early_data_enabled(ssl, 1);
|
||||
@@ -4960,6 +4989,7 @@ doq_conn_setup(struct doq_conn* conn, uint8_t* scid, size_t scidlen,
|
||||
rv = ngtcp2_conn_server_new(&conn->conn, &scid_cid, &sv_scid, &path,
|
||||
conn->version, &callbacks, &settings, ¶ms, NULL, conn);
|
||||
if(rv != 0) {
|
||||
conn->conn = NULL;
|
||||
lock_rw_unlock(&conn->table->conid_lock);
|
||||
log_err("ngtcp2_conn_server_new failed: %s",
|
||||
ngtcp2_strerror(rv));
|
||||
|
||||
@@ -347,6 +347,10 @@ struct tcp_req_info {
|
||||
int num_done_req;
|
||||
/** list of pending writable result packets, malloced one at a time */
|
||||
struct tcp_req_done_item* done_req_list;
|
||||
/** the read again timer, when the number of pipelined TCP queries
|
||||
* is large, it waits, zero time, for a new event loop to service
|
||||
* the remainder of the TCP traffic on the fd. */
|
||||
struct comm_timer* read_again_timer;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -377,10 +381,12 @@ struct tcp_req_done_item {
|
||||
* Create tcp request info structure that keeps track of open
|
||||
* requests on the TCP channel that are resolved at the same time,
|
||||
* and the pending results that have to get written back to that client.
|
||||
* @param base: comm base for read again timer.
|
||||
* @param spoolbuf: shared buffer
|
||||
* @return new structure or NULL on alloc failure.
|
||||
*/
|
||||
struct tcp_req_info* tcp_req_info_create(struct sldns_buffer* spoolbuf);
|
||||
struct tcp_req_info* tcp_req_info_create(struct comm_base* base,
|
||||
struct sldns_buffer* spoolbuf);
|
||||
|
||||
/**
|
||||
* Delete tcp request structure. Called by owning commpoint.
|
||||
|
||||
+56
-11
@@ -386,8 +386,6 @@ new_local_rrset(struct regional* region, struct local_data* node,
|
||||
log_err("out of memory");
|
||||
return NULL;
|
||||
}
|
||||
rrset->next = node->rrsets;
|
||||
node->rrsets = rrset;
|
||||
rrset->rrset = (struct ub_packed_rrset_key*)
|
||||
regional_alloc_zero(region, sizeof(*rrset->rrset));
|
||||
if(!rrset->rrset) {
|
||||
@@ -408,6 +406,8 @@ new_local_rrset(struct regional* region, struct local_data* node,
|
||||
rrset->rrset->rk.dname_len = node->namelen;
|
||||
rrset->rrset->rk.type = htons(rrtype);
|
||||
rrset->rrset->rk.rrset_class = htons(rrclass);
|
||||
rrset->next = node->rrsets;
|
||||
node->rrsets = rrset;
|
||||
return rrset;
|
||||
}
|
||||
|
||||
@@ -431,6 +431,10 @@ rrset_insert_rr(struct regional* region, struct packed_rrset_data* pd,
|
||||
pd->rr_ttl = regional_alloc(region, sizeof(*pd->rr_ttl)*pd->count);
|
||||
pd->rr_data = regional_alloc(region, sizeof(*pd->rr_data)*pd->count);
|
||||
if(!pd->rr_len || !pd->rr_ttl || !pd->rr_data) {
|
||||
pd->count--;
|
||||
pd->rr_len = oldlen;
|
||||
pd->rr_ttl = oldttl;
|
||||
pd->rr_data = olddata;
|
||||
log_err("out of memory");
|
||||
return 0;
|
||||
}
|
||||
@@ -446,6 +450,10 @@ rrset_insert_rr(struct regional* region, struct packed_rrset_data* pd,
|
||||
pd->rr_ttl[0] = ttl;
|
||||
pd->rr_data[0] = regional_alloc_init(region, rdata, rdata_len);
|
||||
if(!pd->rr_data[0]) {
|
||||
pd->count--;
|
||||
pd->rr_len = oldlen;
|
||||
pd->rr_ttl = oldttl;
|
||||
pd->rr_data = olddata;
|
||||
log_err("out of memory");
|
||||
return 0;
|
||||
}
|
||||
@@ -671,7 +679,9 @@ lz_enter_rr_str(struct local_zones* zones, const char* rr)
|
||||
z = local_zones_lookup(zones, rr_name, len, labs, rr_class, rr_type, 1);
|
||||
if(!z) {
|
||||
lock_rw_unlock(&zones->lock);
|
||||
fatal_exit("internal error: no zone for rr %s", rr);
|
||||
log_err("internal error: no zone for rr %s", rr);
|
||||
free(rr_name);
|
||||
return 0;
|
||||
}
|
||||
lock_rw_wrlock(&z->lock);
|
||||
lock_rw_unlock(&zones->lock);
|
||||
@@ -1500,8 +1510,10 @@ find_tag_datas(struct query_info* qinfo, struct config_strlist* list,
|
||||
return 0; /* out of memory */
|
||||
qinfo->local_alias->rrset =
|
||||
regional_alloc_init(temp, r, sizeof(*r));
|
||||
if(!qinfo->local_alias->rrset)
|
||||
if(!qinfo->local_alias->rrset) {
|
||||
qinfo->local_alias = NULL;
|
||||
return 0; /* out of memory */
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -1567,13 +1579,17 @@ local_data_answer(struct local_zone* z, struct module_env* env,
|
||||
return 0; /* out of memory */
|
||||
qinfo->local_alias->rrset = regional_alloc_init(
|
||||
temp, lr->rrset, sizeof(*lr->rrset));
|
||||
if(!qinfo->local_alias->rrset)
|
||||
if(!qinfo->local_alias->rrset) {
|
||||
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;
|
||||
get_cname_target(lr->rrset, &ctarget, &ctargetlen);
|
||||
if(!ctargetlen)
|
||||
if(!ctargetlen) {
|
||||
qinfo->local_alias = NULL;
|
||||
return 0; /* invalid cname */
|
||||
}
|
||||
if(dname_is_wild(ctarget)) {
|
||||
/* synthesize cname target */
|
||||
struct packed_rrset_data* d, *lr_d;
|
||||
@@ -1602,8 +1618,10 @@ local_data_answer(struct local_zone* z, struct module_env* env,
|
||||
sizeof(struct packed_rrset_data) + sizeof(size_t) +
|
||||
sizeof(uint8_t*) + sizeof(time_t) + sizeof(uint16_t)
|
||||
+ newtargetlen);
|
||||
if(!d)
|
||||
if(!d) {
|
||||
qinfo->local_alias = NULL;
|
||||
return 0; /* out of memory */
|
||||
}
|
||||
lr_d = (struct packed_rrset_data*)lr->rrset->entry.data;
|
||||
qinfo->local_alias->rrset->entry.data = d;
|
||||
d->ttl = lr_d->rr_ttl[0]; /* RFC6672-like behavior:
|
||||
@@ -1650,7 +1668,7 @@ local_zone_does_not_cover(struct local_zone* z, struct query_info* qinfo,
|
||||
struct local_data key;
|
||||
struct local_data* ld = NULL;
|
||||
struct local_rrset* lr = NULL;
|
||||
if(z->type == local_zone_always_transparent || z->type == local_zone_block_a)
|
||||
if(z->type == local_zone_always_transparent || z->type == local_zone_block_a || z->type == local_zone_block_aaaa)
|
||||
return 1;
|
||||
if(z->type != local_zone_transparent
|
||||
&& z->type != local_zone_typetransparent
|
||||
@@ -1661,7 +1679,9 @@ local_zone_does_not_cover(struct local_zone* z, struct query_info* qinfo,
|
||||
key.namelen = qinfo->qname_len;
|
||||
key.namelabs = labs;
|
||||
ld = (struct local_data*)rbtree_search(&z->data, &key.node);
|
||||
if(z->type == local_zone_transparent || z->type == local_zone_inform)
|
||||
if(z->type == local_zone_transparent || z->type == local_zone_inform
|
||||
|| z->type == local_zone_block_a_wdata
|
||||
|| z->type == local_zone_block_aaaa_wdata)
|
||||
return (ld == NULL);
|
||||
if(ld)
|
||||
lr = local_data_find_type(ld, qinfo->qtype, 1);
|
||||
@@ -1727,7 +1747,8 @@ local_zones_zone_answer(struct local_zone* z, struct module_env* env,
|
||||
|| lz_type == local_zone_always_transparent) {
|
||||
/* no NODATA or NXDOMAINS for this zone type */
|
||||
return 0;
|
||||
} else if(lz_type == local_zone_block_a) {
|
||||
} else if(lz_type == local_zone_block_a ||
|
||||
lz_type == local_zone_block_a_wdata) {
|
||||
/* Return NODATA for all A queries */
|
||||
if(qinfo->qtype == LDNS_RR_TYPE_A) {
|
||||
local_error_encode(qinfo, env, edns, repinfo, buf, temp,
|
||||
@@ -1736,6 +1757,17 @@ local_zones_zone_answer(struct local_zone* z, struct module_env* env,
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
} else if(lz_type == local_zone_block_aaaa ||
|
||||
lz_type == local_zone_block_aaaa_wdata) {
|
||||
/* Return NODATA for all AAAA queries */
|
||||
if(qinfo->qtype == LDNS_RR_TYPE_AAAA) {
|
||||
local_error_encode(qinfo, env, edns, repinfo, buf, temp,
|
||||
LDNS_RCODE_NOERROR, (LDNS_RCODE_NOERROR|BIT_AA),
|
||||
LDNS_EDE_NONE, NULL);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
} else if(lz_type == local_zone_always_null) {
|
||||
/* 0.0.0.0 or ::0 or noerror/nodata for this zone type,
|
||||
@@ -1904,7 +1936,10 @@ local_zones_answer(struct local_zones* zones, struct module_env* env,
|
||||
lzt == local_zone_typetransparent ||
|
||||
lzt == local_zone_inform ||
|
||||
lzt == local_zone_always_transparent ||
|
||||
lzt == local_zone_block_a) &&
|
||||
lzt == local_zone_block_a ||
|
||||
lzt == local_zone_block_aaaa ||
|
||||
lzt == local_zone_block_a_wdata ||
|
||||
lzt == local_zone_block_aaaa_wdata) &&
|
||||
local_zone_does_not_cover(z, qinfo, labs)) {
|
||||
lock_rw_unlock(&z->lock);
|
||||
z = NULL;
|
||||
@@ -1953,6 +1988,7 @@ local_zones_answer(struct local_zones* zones, struct module_env* env,
|
||||
if(lzt != local_zone_always_refuse
|
||||
&& lzt != local_zone_always_transparent
|
||||
&& lzt != local_zone_block_a
|
||||
&& lzt != local_zone_block_aaaa
|
||||
&& lzt != local_zone_always_nxdomain
|
||||
&& lzt != local_zone_always_nodata
|
||||
&& lzt != local_zone_always_deny
|
||||
@@ -1984,6 +2020,9 @@ const char* local_zone_type2str(enum localzone_type t)
|
||||
case local_zone_inform_redirect: return "inform_redirect";
|
||||
case local_zone_always_transparent: return "always_transparent";
|
||||
case local_zone_block_a: return "block_a";
|
||||
case local_zone_block_aaaa: return "block_aaaa";
|
||||
case local_zone_block_a_wdata: return "block_a_wdata";
|
||||
case local_zone_block_aaaa_wdata: return "block_aaaa_wdata";
|
||||
case local_zone_always_refuse: return "always_refuse";
|
||||
case local_zone_always_nxdomain: return "always_nxdomain";
|
||||
case local_zone_always_nodata: return "always_nodata";
|
||||
@@ -2020,6 +2059,12 @@ int local_zone_str2type(const char* type, enum localzone_type* t)
|
||||
*t = local_zone_always_transparent;
|
||||
else if(strcmp(type, "block_a") == 0)
|
||||
*t = local_zone_block_a;
|
||||
else if(strcmp(type, "block_aaaa") == 0)
|
||||
*t = local_zone_block_aaaa;
|
||||
else if(strcmp(type, "block_a_wdata") == 0)
|
||||
*t = local_zone_block_a_wdata;
|
||||
else if(strcmp(type, "block_aaaa_wdata") == 0)
|
||||
*t = local_zone_block_aaaa_wdata;
|
||||
else if(strcmp(type, "always_refuse") == 0)
|
||||
*t = local_zone_always_refuse;
|
||||
else if(strcmp(type, "always_nxdomain") == 0)
|
||||
|
||||
@@ -93,6 +93,12 @@ enum localzone_type {
|
||||
local_zone_always_transparent,
|
||||
/** resolve normally, even when there is local data but return NODATA for A queries */
|
||||
local_zone_block_a,
|
||||
/** resolve normally, even when there is local data, but return NODATA for AAAA queries */
|
||||
local_zone_block_aaaa,
|
||||
/** resolve normally, use local data, else return NODATA for A queries */
|
||||
local_zone_block_a_wdata,
|
||||
/** resolve normally, use local data, else return NODATA for AAAA queries */
|
||||
local_zone_block_aaaa_wdata,
|
||||
/** answer with error, even when there is local data */
|
||||
local_zone_always_refuse,
|
||||
/** answer with nxdomain, even when there is local data */
|
||||
|
||||
+210
-131
@@ -373,7 +373,7 @@ mesh_serve_expired_lookup(struct module_qstate* qstate,
|
||||
"validation");
|
||||
goto bail_out; /* need to validate cache entry first */
|
||||
} else if(msg->rep->security == sec_status_secure &&
|
||||
!reply_all_rrsets_secure(msg->rep) && must_validate) {
|
||||
!reply_an_ns_rrsets_secure(msg->rep) && must_validate) {
|
||||
verbose(VERB_ALGO, "Serve expired: secure entry"
|
||||
" changed status");
|
||||
goto bail_out; /* rrset changed, re-verify */
|
||||
@@ -424,6 +424,44 @@ mesh_serve_expired_init(struct mesh_state* mstate, int timeout)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** remove a reply without accounting, rollback the add reply. */
|
||||
static void
|
||||
mesh_remove_reply_without_accounting(struct mesh_state* s,
|
||||
struct mesh_reply* todel)
|
||||
{
|
||||
struct mesh_reply* r, *prev = NULL;
|
||||
for(r = s->reply_list; r; r = r->next) {
|
||||
if(r == todel) {
|
||||
if(prev)
|
||||
prev->next = r->next;
|
||||
else s->reply_list = r->next;
|
||||
r->next = NULL;
|
||||
/* todel is allocated in region */
|
||||
return;
|
||||
}
|
||||
prev = r;
|
||||
}
|
||||
}
|
||||
|
||||
/** remove a callback without accounting, rollback the add reply. */
|
||||
static void
|
||||
mesh_remove_callback_without_accounting(struct mesh_state* s,
|
||||
struct mesh_cb* todel)
|
||||
{
|
||||
struct mesh_cb* r, *prev = NULL;
|
||||
for(r = s->cb_list; r; r = r->next) {
|
||||
if(r == todel) {
|
||||
if(prev)
|
||||
prev->next = r->next;
|
||||
else s->cb_list = r->next;
|
||||
r->next = NULL;
|
||||
/* todel is allocated in region */
|
||||
return;
|
||||
}
|
||||
prev = r;
|
||||
}
|
||||
}
|
||||
|
||||
void mesh_new_client(struct mesh_area* mesh, struct query_info* qinfo,
|
||||
struct respip_client_info* cinfo, uint16_t qflags,
|
||||
struct edns_data* edns, struct comm_reply* rep, uint16_t qid,
|
||||
@@ -433,7 +471,8 @@ void mesh_new_client(struct mesh_area* mesh, struct query_info* qinfo,
|
||||
int unique = unique_mesh_state(edns->opt_list_in, mesh->env);
|
||||
int was_detached = 0;
|
||||
int was_noreply = 0;
|
||||
int added = 0;
|
||||
int added = 0, added_reply_without_accounting = 0, added_tcp = 0;
|
||||
struct mesh_reply* repadded = NULL;
|
||||
int timeout = mesh->env->cfg->serve_expired?
|
||||
mesh->env->cfg->serve_expired_client_timeout:0;
|
||||
struct sldns_buffer* r_buffer = rep->c->buffer;
|
||||
@@ -544,16 +583,18 @@ void mesh_new_client(struct mesh_area* mesh, struct query_info* qinfo,
|
||||
}
|
||||
}
|
||||
/* add reply to s */
|
||||
if(!mesh_state_add_reply(s, edns, rep, qid, qflags, qinfo)) {
|
||||
if(!mesh_state_add_reply(s, edns, rep, qid, qflags, qinfo, &repadded)) {
|
||||
log_err("mesh_new_client: out of memory; SERVFAIL");
|
||||
goto servfail_mem;
|
||||
}
|
||||
added_reply_without_accounting = 1;
|
||||
if(rep->c->tcp_req_info) {
|
||||
if(!tcp_req_info_add_meshstate(rep->c->tcp_req_info, mesh, s)) {
|
||||
log_err("mesh_new_client: out of memory add tcpreqinfo");
|
||||
goto servfail_mem;
|
||||
}
|
||||
}
|
||||
added_tcp = 1;
|
||||
if(rep->c->use_h2) {
|
||||
http2_stream_add_meshstate(rep->c->h2_stream, mesh, s);
|
||||
} else if(rep->c->type == comm_doq && rep->doq_stream) {
|
||||
@@ -575,6 +616,8 @@ void mesh_new_client(struct mesh_area* mesh, struct query_info* qinfo,
|
||||
}
|
||||
}
|
||||
#endif
|
||||
/* Since the acccounting now happens,
|
||||
* added_reply_without_accounting = 0; but that is not used. */
|
||||
infra_wait_limit_inc(mesh->env->infra_cache, rep, *mesh->env->now,
|
||||
mesh->env->cfg);
|
||||
/* update statistics */
|
||||
@@ -614,6 +657,11 @@ servfail_mem:
|
||||
else if(rep->c->type == comm_doq && rep->doq_stream)
|
||||
doq_stream_remove_mesh_state(rep->doq_stream);
|
||||
comm_point_send_reply(rep);
|
||||
if(added_reply_without_accounting) {
|
||||
mesh_remove_reply_without_accounting(s, repadded);
|
||||
if(added_tcp && rep->c->tcp_req_info)
|
||||
tcp_req_info_remove_mesh_state(rep->c->tcp_req_info, s);
|
||||
}
|
||||
if(added)
|
||||
mesh_state_delete(&s->s);
|
||||
return;
|
||||
@@ -622,7 +670,8 @@ servfail_mem:
|
||||
int
|
||||
mesh_new_callback(struct mesh_area* mesh, struct query_info* qinfo,
|
||||
uint16_t qflags, struct edns_data* edns, sldns_buffer* buf,
|
||||
uint16_t qid, mesh_cb_func_type cb, void* cb_arg, int rpz_passthru)
|
||||
uint16_t qid, mesh_cb_func_type cb, void* cb_arg, int rpz_passthru,
|
||||
void** unique_info)
|
||||
{
|
||||
struct mesh_state* s = NULL;
|
||||
int unique = unique_mesh_state(edns->opt_list_in, mesh->env);
|
||||
@@ -631,6 +680,7 @@ mesh_new_callback(struct mesh_area* mesh, struct query_info* qinfo,
|
||||
int was_detached = 0;
|
||||
int was_noreply = 0;
|
||||
int added = 0;
|
||||
struct mesh_cb* add_cb = NULL;
|
||||
uint16_t mesh_flags = qflags&(BIT_RD|BIT_CD);
|
||||
if(!unique)
|
||||
s = mesh_area_find(mesh, NULL, qinfo, mesh_flags, 0, 0);
|
||||
@@ -676,13 +726,14 @@ mesh_new_callback(struct mesh_area* mesh, struct query_info* qinfo,
|
||||
}
|
||||
}
|
||||
/* add reply to s */
|
||||
if(!mesh_state_add_cb(s, edns, buf, cb, cb_arg, qid, qflags)) {
|
||||
if(!mesh_state_add_cb(s, edns, buf, cb, cb_arg, qid, qflags, &add_cb)) {
|
||||
if(added)
|
||||
mesh_state_delete(&s->s);
|
||||
return 0;
|
||||
}
|
||||
/* add serve expired timer if not already there */
|
||||
if(timeout && !mesh_serve_expired_init(s, timeout)) {
|
||||
mesh_remove_callback_without_accounting(s, add_cb);
|
||||
if(added)
|
||||
mesh_state_delete(&s->s);
|
||||
return 0;
|
||||
@@ -693,6 +744,7 @@ mesh_new_callback(struct mesh_area* mesh, struct query_info* qinfo,
|
||||
(mesh->env->cachedb_enabled &&
|
||||
mesh->env->cfg->cachedb_check_when_serve_expired)) {
|
||||
if(!mesh_serve_expired_init(s, -1)) {
|
||||
mesh_remove_callback_without_accounting(s, add_cb);
|
||||
if(added)
|
||||
mesh_state_delete(&s->s);
|
||||
return 0;
|
||||
@@ -708,6 +760,8 @@ mesh_new_callback(struct mesh_area* mesh, struct query_info* qinfo,
|
||||
mesh->num_reply_states ++;
|
||||
}
|
||||
mesh->num_reply_addrs++;
|
||||
if(unique_info)
|
||||
*unique_info = s->unique;
|
||||
if(added)
|
||||
mesh_run(mesh, s, module_event_new, NULL);
|
||||
return 1;
|
||||
@@ -911,32 +965,9 @@ void mesh_report_reply(struct mesh_area* mesh, struct outbound_entry* e,
|
||||
mesh_run(mesh, e->qstate->mesh_info, event, e);
|
||||
}
|
||||
|
||||
/** copy strlist to region */
|
||||
static struct config_strlist*
|
||||
cfg_region_strlist_copy(struct regional* region, struct config_strlist* list)
|
||||
{
|
||||
struct config_strlist* result = NULL, *last = NULL, *s = list;
|
||||
while(s) {
|
||||
struct config_strlist* n = regional_alloc_zero(region,
|
||||
sizeof(*n));
|
||||
if(!n)
|
||||
return NULL;
|
||||
n->str = regional_strdup(region, s->str);
|
||||
if(!n->str)
|
||||
return NULL;
|
||||
if(last)
|
||||
last->next = n;
|
||||
else result = n;
|
||||
last = n;
|
||||
s = s->next;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
struct respip_client_info*
|
||||
mesh_copy_client_info(struct regional* region, struct respip_client_info* cinfo)
|
||||
{
|
||||
size_t i;
|
||||
struct respip_client_info* client_info;
|
||||
client_info = regional_alloc_init(region, cinfo, sizeof(*cinfo));
|
||||
if(!client_info)
|
||||
@@ -955,20 +986,13 @@ mesh_copy_client_info(struct regional* region, struct respip_client_info* cinfo)
|
||||
if(!client_info->tag_actions)
|
||||
return NULL;
|
||||
}
|
||||
if(cinfo->tag_datas) {
|
||||
client_info->tag_datas = regional_alloc_zero(region,
|
||||
sizeof(struct config_strlist*)*cinfo->tag_datas_size);
|
||||
if(!client_info->tag_datas)
|
||||
return NULL;
|
||||
for(i=0; i<cinfo->tag_datas_size; i++) {
|
||||
if(cinfo->tag_datas[i]) {
|
||||
client_info->tag_datas[i] = cfg_region_strlist_copy(
|
||||
region, cinfo->tag_datas[i]);
|
||||
if(!client_info->tag_datas[i])
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* tag_datas is owned by the matched acl_addr in config_file; its
|
||||
* lifetime is until config reload, which tears down all mesh states
|
||||
* first. Keep the original pointer so client_info_compare()
|
||||
* can recognise two states from the same ACL entry. */
|
||||
/* fast reload insists on dropping the queries when interface-tag-data
|
||||
* or access-control-tag-data are changed. */
|
||||
/* client_info->tag_datas already copied by regional_alloc_init above */
|
||||
if(cinfo->view) {
|
||||
/* Do not copy the view pointer but store a name instead.
|
||||
* The name is looked up later when done, this means that
|
||||
@@ -1073,6 +1097,18 @@ mesh_state_make_unique(struct mesh_state* mstate)
|
||||
mstate->unique = mstate;
|
||||
}
|
||||
|
||||
/** pop a reply from the reply list, if there are any. */
|
||||
static struct mesh_reply*
|
||||
mesh_reply_list_pop_first(struct mesh_state* mstate)
|
||||
{
|
||||
if(mstate->reply_list) {
|
||||
struct mesh_reply* r = mstate->reply_list;
|
||||
mstate->reply_list = r->next;
|
||||
return r;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
mesh_state_cleanup(struct mesh_state* mstate)
|
||||
{
|
||||
@@ -1088,23 +1124,30 @@ mesh_state_cleanup(struct mesh_state* mstate)
|
||||
}
|
||||
/* drop unsent replies */
|
||||
if(!mstate->replies_sent) {
|
||||
struct mesh_reply* rep = mstate->reply_list;
|
||||
struct mesh_reply* rep;
|
||||
struct mesh_cb* cb;
|
||||
/* One http2 stream could bring down its comm_point along with
|
||||
* the other streams which could share the same query. Do all
|
||||
* the http2 stream bookkeeping upfront. */
|
||||
for(; rep; rep=rep->next) {
|
||||
if(rep->query_reply.c->use_h2)
|
||||
http2_stream_remove_mesh_state(rep->h2_stream);
|
||||
}
|
||||
rep = mstate->reply_list;
|
||||
/* in tcp_req_info, the mstates linked are removed, but
|
||||
* the reply_list is now NULL, so the remove-from-empty-list
|
||||
* takes no time and also it does not do the mesh accounting */
|
||||
mstate->reply_list = NULL;
|
||||
for(; rep; rep=rep->next) {
|
||||
/* Pop items from the list, that means there is no iterator.
|
||||
* And then items can be removed from the reply list, from
|
||||
* like comm_point_drop_reply and comm_point_close calls.
|
||||
* As the tcp_req_info and http2 code drops the entire
|
||||
* connection. That could delete mesh_reply items previous and
|
||||
* after the current state. The previous items are already
|
||||
* popped. And the next items can be altered, like to when a
|
||||
* connection has more replies on the reply list.
|
||||
* The current item is also popped so the code needs to
|
||||
* remove its references. */
|
||||
while((rep = mesh_reply_list_pop_first(mstate)) != NULL) {
|
||||
infra_wait_limit_dec(mesh->env->infra_cache,
|
||||
&rep->query_reply, mesh->env->cfg);
|
||||
if(rep->query_reply.c->tcp_req_info)
|
||||
tcp_req_info_remove_mesh_state(
|
||||
rep->query_reply.c->tcp_req_info,
|
||||
mstate);
|
||||
else if(rep->query_reply.c->use_h2)
|
||||
http2_stream_remove_mesh_state(rep->h2_stream);
|
||||
else if(rep->query_reply.doq_stream)
|
||||
doq_stream_remove_mesh_state(
|
||||
rep->query_reply.doq_stream);
|
||||
comm_point_drop_reply(&rep->query_reply);
|
||||
log_assert(mesh->num_reply_addrs > 0);
|
||||
mesh->num_reply_addrs--;
|
||||
@@ -1241,6 +1284,9 @@ int mesh_add_sub(struct module_qstate* qstate, struct query_info* qinfo,
|
||||
log_err("mesh_attach_sub: out of memory");
|
||||
return 0;
|
||||
}
|
||||
/* inherit RPZ passthru from the parent so respip on the sub
|
||||
* sees the same client-IP/qname PASSTHRU decision */
|
||||
(*sub)->s.rpz_passthru = qstate->rpz_passthru;
|
||||
#ifdef UNBOUND_DEBUG
|
||||
n =
|
||||
#else
|
||||
@@ -1465,12 +1511,6 @@ mesh_send_reply(struct mesh_state* m, int rcode, struct reply_info* rep,
|
||||
struct timeval end_time;
|
||||
struct timeval duration;
|
||||
int secure;
|
||||
/* briefly set the replylist to null in case the
|
||||
* meshsendreply calls tcpreqinfo sendreply that
|
||||
* comm_point_drops because of size, and then the
|
||||
* null stops the mesh state remove and thus
|
||||
* reply_list modification and accounting */
|
||||
struct mesh_reply* rlist = m->reply_list;
|
||||
|
||||
/* rpz: apply actions */
|
||||
rcode = mesh_is_udp(r) && mesh_is_rpz_respip_tcponly_action(m)
|
||||
@@ -1527,9 +1567,7 @@ mesh_send_reply(struct mesh_state* m, int rcode, struct reply_info* rep,
|
||||
sldns_buffer_write_at(r_buffer, 0, &r->qid, sizeof(uint16_t));
|
||||
sldns_buffer_write_at(r_buffer, 12, r->qname,
|
||||
m->s.qinfo.qname_len);
|
||||
m->reply_list = NULL;
|
||||
comm_point_send_reply(&r->query_reply);
|
||||
m->reply_list = rlist;
|
||||
} else if(rcode) {
|
||||
m->s.qinfo.qname = r->qname;
|
||||
m->s.qinfo.local_alias = r->local_alias;
|
||||
@@ -1551,9 +1589,7 @@ mesh_send_reply(struct mesh_state* m, int rcode, struct reply_info* rep,
|
||||
}
|
||||
error_encode(r_buffer, rcode, &m->s.qinfo, r->qid,
|
||||
r->qflags, &r->edns);
|
||||
m->reply_list = NULL;
|
||||
comm_point_send_reply(&r->query_reply);
|
||||
m->reply_list = rlist;
|
||||
} else {
|
||||
size_t udp_size = r->edns.udp_size;
|
||||
r->edns.edns_version = EDNS_ADVERTISED_VERSION;
|
||||
@@ -1589,9 +1625,7 @@ mesh_send_reply(struct mesh_state* m, int rcode, struct reply_info* rep,
|
||||
error_encode(r_buffer, LDNS_RCODE_SERVFAIL,
|
||||
&m->s.qinfo, r->qid, r->qflags, &r->edns);
|
||||
}
|
||||
m->reply_list = NULL;
|
||||
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);
|
||||
@@ -1743,6 +1777,7 @@ void mesh_query_done(struct mesh_state* mstate)
|
||||
struct reply_info* rep = (mstate->s.return_msg?
|
||||
mstate->s.return_msg->rep:NULL);
|
||||
struct timeval tv = {0, 0};
|
||||
struct mesh_area* mesh = mstate->s.env->mesh;
|
||||
int i = 0;
|
||||
/* No need for the serve expired timer anymore; we are going to reply. */
|
||||
if(mstate->s.serve_expired_data) {
|
||||
@@ -1763,10 +1798,22 @@ void mesh_query_done(struct mesh_state* mstate)
|
||||
}
|
||||
}
|
||||
|
||||
if(mstate->reply_list && mstate->s.env->cfg->dns_error_reporting)
|
||||
if(mstate->reply_list && mstate->s.env->cfg->dns_error_reporting
|
||||
&& (!rep || rep->security != sec_status_secure))
|
||||
dns_error_reporting(&mstate->s, rep);
|
||||
|
||||
for(r = mstate->reply_list; r; r = r->next) {
|
||||
while((r = mesh_reply_list_pop_first(mstate)) != NULL) {
|
||||
|
||||
/* it was not detached (because it had a reply list), could be now */
|
||||
if(!mstate->reply_list && !mstate->cb_list
|
||||
&& mstate->super_set.count == 0) {
|
||||
mesh->num_detached_states++;
|
||||
}
|
||||
/* if not replies any more in mstate, it is no longer a reply_state */
|
||||
if(!mstate->reply_list && !mstate->cb_list) {
|
||||
log_assert(mesh->num_reply_states > 0);
|
||||
mesh->num_reply_states--;
|
||||
}
|
||||
if(mesh_is_udp(r)) {
|
||||
/* For UDP queries, the old replies are discarded.
|
||||
* This stops a large volume of old replies from
|
||||
@@ -1781,22 +1828,18 @@ void mesh_query_done(struct mesh_state* mstate)
|
||||
((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)
|
||||
if(r->query_reply.c->tcp_req_info)
|
||||
tcp_req_info_remove_mesh_state(
|
||||
r->query_reply.c->tcp_req_info,
|
||||
mstate);
|
||||
else if(r->query_reply.c->use_h2)
|
||||
http2_stream_remove_mesh_state(r->h2_stream);
|
||||
else if(r->query_reply.doq_stream)
|
||||
doq_stream_remove_mesh_state(r->query_reply.doq_stream);
|
||||
comm_point_drop_reply(&r->query_reply);
|
||||
mstate->reply_list = reply_list;
|
||||
log_assert(mstate->s.env->mesh->num_reply_addrs > 0);
|
||||
mstate->s.env->mesh->num_reply_addrs--;
|
||||
mstate->s.env->mesh->num_queries_discard_timeout++;
|
||||
@@ -1821,22 +1864,17 @@ void mesh_query_done(struct mesh_state* mstate)
|
||||
/* if this query is determined to be dropped during the
|
||||
* mesh processing, this is the point to take that action. */
|
||||
if(mstate->s.is_drop) {
|
||||
/* 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;
|
||||
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) {
|
||||
if(r->query_reply.c->tcp_req_info) {
|
||||
tcp_req_info_remove_mesh_state(
|
||||
r->query_reply.c->tcp_req_info, mstate);
|
||||
} else if(r->query_reply.c->use_h2) {
|
||||
http2_stream_remove_mesh_state(r->h2_stream);
|
||||
} else if(r->query_reply.doq_stream) {
|
||||
doq_stream_remove_mesh_state(r->query_reply.doq_stream);
|
||||
}
|
||||
comm_point_drop_reply(&r->query_reply);
|
||||
mstate->reply_list = reply_list;
|
||||
log_assert(mstate->s.env->mesh->num_reply_addrs > 0);
|
||||
mstate->s.env->mesh->num_reply_addrs--;
|
||||
} else {
|
||||
@@ -1877,18 +1915,6 @@ void mesh_query_done(struct mesh_state* mstate)
|
||||
}
|
||||
}
|
||||
|
||||
/* Mesh area accounting */
|
||||
if(mstate->reply_list) {
|
||||
mstate->reply_list = NULL;
|
||||
if(!mstate->reply_list && !mstate->cb_list) {
|
||||
/* was a reply state, not anymore */
|
||||
log_assert(mstate->s.env->mesh->num_reply_states > 0);
|
||||
mstate->s.env->mesh->num_reply_states--;
|
||||
}
|
||||
if(!mstate->reply_list && !mstate->cb_list &&
|
||||
mstate->super_set.count == 0)
|
||||
mstate->s.env->mesh->num_detached_states++;
|
||||
}
|
||||
mstate->replies_sent = 1;
|
||||
|
||||
while((c = mstate->cb_list) != NULL) {
|
||||
@@ -1946,6 +1972,25 @@ struct mesh_state* mesh_area_find(struct mesh_area* mesh,
|
||||
return result;
|
||||
}
|
||||
|
||||
struct mesh_state* mesh_area_find_unique(struct mesh_area* mesh,
|
||||
struct respip_client_info* cinfo, struct query_info* qinfo,
|
||||
uint16_t qflags, int prime, int valrec, void* unique_info)
|
||||
{
|
||||
struct mesh_state key;
|
||||
struct mesh_state* result;
|
||||
|
||||
key.node.key = &key;
|
||||
key.s.is_priming = prime;
|
||||
key.s.is_valrec = valrec;
|
||||
key.s.qinfo = *qinfo;
|
||||
key.s.query_flags = qflags;
|
||||
key.unique = (struct mesh_state*)unique_info;
|
||||
key.s.client_info = cinfo;
|
||||
|
||||
result = (struct mesh_state*)rbtree_search(&mesh->all, &key);
|
||||
return result;
|
||||
}
|
||||
|
||||
/** remove mesh state callback */
|
||||
int mesh_state_del_cb(struct mesh_state* s, mesh_cb_func_type cb, void* cb_arg)
|
||||
{
|
||||
@@ -1967,7 +2012,7 @@ int mesh_state_del_cb(struct mesh_state* s, mesh_cb_func_type cb, void* cb_arg)
|
||||
|
||||
int mesh_state_add_cb(struct mesh_state* s, struct edns_data* edns,
|
||||
sldns_buffer* buf, mesh_cb_func_type cb, void* cb_arg,
|
||||
uint16_t qid, uint16_t qflags)
|
||||
uint16_t qid, uint16_t qflags, struct mesh_cb** result)
|
||||
{
|
||||
struct mesh_cb* r = regional_alloc(s->s.region,
|
||||
sizeof(struct mesh_cb));
|
||||
@@ -1991,13 +2036,14 @@ int mesh_state_add_cb(struct mesh_state* s, struct edns_data* edns,
|
||||
r->qflags = qflags;
|
||||
r->next = s->cb_list;
|
||||
s->cb_list = r;
|
||||
*result = r;
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
int mesh_state_add_reply(struct mesh_state* s, struct edns_data* edns,
|
||||
struct comm_reply* rep, uint16_t qid, uint16_t qflags,
|
||||
const struct query_info* qinfo)
|
||||
const struct query_info* qinfo, struct mesh_reply** result)
|
||||
{
|
||||
struct mesh_reply* r = regional_alloc(s->s.region,
|
||||
sizeof(struct mesh_reply));
|
||||
@@ -2078,6 +2124,7 @@ int mesh_state_add_reply(struct mesh_state* s, struct edns_data* edns,
|
||||
r->local_alias = NULL;
|
||||
|
||||
s->reply_list = r;
|
||||
*result = r;
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -2235,8 +2282,29 @@ void mesh_run(struct mesh_area* mesh, struct mesh_state* mstate,
|
||||
enum module_ev ev, struct outbound_entry* e)
|
||||
{
|
||||
enum module_ext_state s;
|
||||
int numrun = 0;
|
||||
verbose(VERB_ALGO, "mesh_run: start");
|
||||
while(mstate) {
|
||||
if(numrun++ > MESH_MAX_RUN_ITER) {
|
||||
/* These modules are too much to activate, stop them.*/
|
||||
log_err("Too many module run iterations, deleting");
|
||||
while(mstate) {
|
||||
/* notify supers */
|
||||
if(mstate->super_set.count > 0) {
|
||||
verbose(VERB_ALGO, "notify supers of failure");
|
||||
mstate->s.return_msg = NULL;
|
||||
mstate->s.return_rcode = LDNS_RCODE_SERVFAIL;
|
||||
mesh_walk_supers(mesh, mstate);
|
||||
}
|
||||
mesh_state_delete(&mstate->s);
|
||||
if(mesh->run.count > 0) {
|
||||
/* pop random element off the runnable tree */
|
||||
mstate = (struct mesh_state*)mesh->run.root->key;
|
||||
(void)rbtree_delete(&mesh->run, mstate);
|
||||
} else mstate = NULL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
/* run the module */
|
||||
fptr_ok(fptr_whitelist_mod_operate(
|
||||
mesh->mods.mod[mstate->s.curmod]->operate));
|
||||
@@ -2388,7 +2456,8 @@ void mesh_list_remove(struct mesh_state* m, struct mesh_state** fp,
|
||||
}
|
||||
|
||||
void mesh_state_remove_reply(struct mesh_area* mesh, struct mesh_state* m,
|
||||
struct comm_point* cp, struct doq_stream* doq_stream)
|
||||
struct comm_point* cp, struct http2_stream* h2_stream,
|
||||
struct doq_stream* doq_stream)
|
||||
{
|
||||
struct mesh_reply* n, *prev = NULL;
|
||||
n = m->reply_list;
|
||||
@@ -2397,6 +2466,7 @@ void mesh_state_remove_reply(struct mesh_area* mesh, struct mesh_state* m,
|
||||
if(!n) return; /* nothing to remove, also no accounting needed */
|
||||
while(n) {
|
||||
if(n->query_reply.c == cp
|
||||
&& (!h2_stream || n->h2_stream == h2_stream)
|
||||
&& (!doq_stream || n->query_reply.doq_stream == doq_stream)) {
|
||||
/* unlink it */
|
||||
if(prev) prev->next = n->next;
|
||||
@@ -2434,7 +2504,6 @@ void mesh_state_remove_reply(struct mesh_area* mesh, struct mesh_state* m,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
apply_respip_action(struct module_qstate* qstate,
|
||||
const struct query_info* qinfo, struct respip_client_info* cinfo,
|
||||
@@ -2567,7 +2636,18 @@ mesh_serve_expired_callback(void* arg)
|
||||
if(verbosity >= VERB_ALGO)
|
||||
log_dns_msg("Serve expired lookup", &qstate->qinfo, msg->rep);
|
||||
|
||||
for(r = mstate->reply_list; r; r = r->next) {
|
||||
while((r = mesh_reply_list_pop_first(mstate)) != NULL) {
|
||||
|
||||
/* it was not detached (because it had a reply list), could be now */
|
||||
if(!mstate->reply_list && !mstate->cb_list
|
||||
&& mstate->super_set.count == 0) {
|
||||
mesh->num_detached_states++;
|
||||
}
|
||||
/* if not replies any more in mstate, it is no longer a reply_state */
|
||||
if(!mstate->reply_list && !mstate->cb_list) {
|
||||
log_assert(mesh->num_reply_states > 0);
|
||||
mesh->num_reply_states--;
|
||||
}
|
||||
if(mesh_is_udp(r)) {
|
||||
struct timeval old;
|
||||
timeval_subtract(&old, mstate->s.env->now_tv, &r->start_time);
|
||||
@@ -2575,22 +2655,17 @@ mesh_serve_expired_callback(void* arg)
|
||||
((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)
|
||||
if(r->query_reply.c->tcp_req_info)
|
||||
tcp_req_info_remove_mesh_state(
|
||||
r->query_reply.c->tcp_req_info, mstate);
|
||||
else if(r->query_reply.c->use_h2)
|
||||
http2_stream_remove_mesh_state(r->h2_stream);
|
||||
else if(r->query_reply.doq_stream)
|
||||
doq_stream_remove_mesh_state(r->query_reply.doq_stream);
|
||||
comm_point_drop_reply(&r->query_reply);
|
||||
mstate->reply_list = reply_list;
|
||||
log_assert(mstate->s.env->mesh->num_reply_addrs > 0);
|
||||
mstate->s.env->mesh->num_reply_addrs--;
|
||||
mstate->s.env->mesh->num_queries_discard_timeout++;
|
||||
@@ -2628,8 +2703,7 @@ mesh_serve_expired_callback(void* arg)
|
||||
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);
|
||||
/* mesh_send_reply decremented wait_limit. */
|
||||
prev = r;
|
||||
prev_buffer = r_buffer;
|
||||
}
|
||||
@@ -2648,18 +2722,6 @@ mesh_serve_expired_callback(void* arg)
|
||||
}
|
||||
}
|
||||
|
||||
/* Mesh area accounting */
|
||||
if(mstate->reply_list) {
|
||||
mstate->reply_list = NULL;
|
||||
if(!mstate->reply_list && !mstate->cb_list) {
|
||||
log_assert(mesh->num_reply_states > 0);
|
||||
mesh->num_reply_states--;
|
||||
if(mstate->super_set.count == 0) {
|
||||
mesh->num_detached_states++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
while((c = mstate->cb_list) != NULL) {
|
||||
/* take this cb off the list; so that the list can be
|
||||
* changed, eg. by adds from the callback routine */
|
||||
@@ -2692,13 +2754,30 @@ int mesh_jostle_exceeded(struct mesh_area* mesh)
|
||||
}
|
||||
|
||||
void mesh_remove_callback(struct mesh_area* mesh, struct query_info* qinfo,
|
||||
uint16_t qflags, mesh_cb_func_type cb, void* cb_arg)
|
||||
uint16_t qflags, mesh_cb_func_type cb, void* cb_arg, void* unique_info)
|
||||
{
|
||||
struct mesh_state* s = NULL;
|
||||
s = mesh_area_find(mesh, NULL, qinfo, qflags&(BIT_RD|BIT_CD), 0, 0);
|
||||
if(!s) return;
|
||||
if(!mesh_state_del_cb(s, cb, cb_arg)) return;
|
||||
if(s && mesh_state_del_cb(s, cb, cb_arg))
|
||||
goto removed;
|
||||
if(unique_info) {
|
||||
s = mesh_area_find_unique(mesh, NULL, qinfo,
|
||||
qflags&(BIT_RD|BIT_CD), 0, 0, unique_info);
|
||||
if(s && mesh_state_del_cb(s, cb, cb_arg))
|
||||
goto removed;
|
||||
}
|
||||
/* mesh_area_find builds key.unique=NULL and cannot match a state
|
||||
* created with mesh_state_make_unique (e.g. subnetcache sets
|
||||
* env->unique_mesh). Fall back to a linear scan; cb+cb_arg is an
|
||||
* exact key (mesh_state_del_cb compares both).
|
||||
* This works for both lookups for zonemd and for hostname authzone. */
|
||||
RBTREE_FOR(s, struct mesh_state*, &mesh->all) {
|
||||
if(s->cb_list && mesh_state_del_cb(s, cb, cb_arg))
|
||||
goto removed;
|
||||
}
|
||||
return;
|
||||
|
||||
removed:
|
||||
/* It was in the list and removed. */
|
||||
log_assert(mesh->num_reply_addrs > 0);
|
||||
mesh->num_reply_addrs--;
|
||||
|
||||
+38
-5
@@ -69,6 +69,13 @@ struct respip_client_info;
|
||||
*/
|
||||
#define MESH_MAX_ACTIVATION 10000
|
||||
|
||||
/**
|
||||
* Maximum number of mesh state run items. These are different modules
|
||||
* activated during a mesh run. Any more is likely an infinite loop
|
||||
* in the module. It is then terminated, and states are deleted.
|
||||
*/
|
||||
#define MESH_MAX_RUN_ITER 10000
|
||||
|
||||
/**
|
||||
* Max number of references-to-references-to-references.. search size.
|
||||
* Any more is treated like 'too large', and the creation of a new
|
||||
@@ -342,11 +349,14 @@ void mesh_new_client(struct mesh_area* mesh, struct query_info* qinfo,
|
||||
* @param cb_arg: callback user arg.
|
||||
* @param rpz_passthru: if true, the rpz passthru was previously found and
|
||||
* further rpz processing is stopped.
|
||||
* @param unique_info: if nonnull, unique info is passed back to be used
|
||||
* for the callback remove call. It does not need to be deallocated.
|
||||
* @return 0 on error.
|
||||
*/
|
||||
int mesh_new_callback(struct mesh_area* mesh, struct query_info* qinfo,
|
||||
uint16_t qflags, struct edns_data* edns, struct sldns_buffer* buf,
|
||||
uint16_t qid, mesh_cb_func_type cb, void* cb_arg, int rpz_passthru);
|
||||
uint16_t qid, mesh_cb_func_type cb, void* cb_arg, int rpz_passthru,
|
||||
void** unique_info);
|
||||
|
||||
/**
|
||||
* New prefetch message. Create new query state if needed.
|
||||
@@ -543,6 +553,23 @@ struct mesh_state* mesh_area_find(struct mesh_area* mesh,
|
||||
struct respip_client_info* cinfo, struct query_info* qinfo,
|
||||
uint16_t qflags, int prime, int valrec);
|
||||
|
||||
/**
|
||||
* Find a unique mesh state in the mesh area. Pass relevant flags.
|
||||
*
|
||||
* @param mesh: the mesh area to look in.
|
||||
* @param cinfo: if non-NULL client specific info that may affect IP-based
|
||||
* actions that apply to the query result.
|
||||
* @param qinfo: what query
|
||||
* @param qflags: if RD / CD bit is set or not.
|
||||
* @param prime: if it is a priming query.
|
||||
* @param valrec: if it is a validation-recursion query.
|
||||
* @param unique_info: the unique info for the state. NULL can be passed.
|
||||
* @return: mesh state or NULL if not found.
|
||||
*/
|
||||
struct mesh_state* mesh_area_find_unique(struct mesh_area* mesh,
|
||||
struct respip_client_info* cinfo, struct query_info* qinfo,
|
||||
uint16_t qflags, int prime, int valrec, void* unique_info);
|
||||
|
||||
/**
|
||||
* Setup attachment super/sub relation between super and sub mesh state.
|
||||
* The relation must not be present when calling the function.
|
||||
@@ -562,11 +589,12 @@ int mesh_state_attachment(struct mesh_state* super, struct mesh_state* sub);
|
||||
* @param qid: ID of reply.
|
||||
* @param qflags: original query flags.
|
||||
* @param qinfo: original query info.
|
||||
* @param result: the allocated reply structure, for rollback.
|
||||
* @return: 0 on alloc error.
|
||||
*/
|
||||
int mesh_state_add_reply(struct mesh_state* s, struct edns_data* edns,
|
||||
struct comm_reply* rep, uint16_t qid, uint16_t qflags,
|
||||
const struct query_info* qinfo);
|
||||
const struct query_info* qinfo, struct mesh_reply** result);
|
||||
|
||||
/**
|
||||
* Create new callback structure and attach it to a mesh state.
|
||||
@@ -578,11 +606,12 @@ int mesh_state_add_reply(struct mesh_state* s, struct edns_data* edns,
|
||||
* @param cb_arg: callback user arg.
|
||||
* @param qid: ID of reply.
|
||||
* @param qflags: original query flags.
|
||||
* @param result: the allocated callback structure, for rollback.
|
||||
* @return: 0 on alloc error.
|
||||
*/
|
||||
int mesh_state_add_cb(struct mesh_state* s, struct edns_data* edns,
|
||||
struct sldns_buffer* buf, mesh_cb_func_type cb, void* cb_arg,
|
||||
uint16_t qid, uint16_t qflags);
|
||||
uint16_t qid, uint16_t qflags, struct mesh_cb** result);
|
||||
|
||||
/**
|
||||
* Run the mesh. Run all runnable mesh states. Which can create new
|
||||
@@ -683,11 +712,14 @@ void mesh_list_remove(struct mesh_state* m, struct mesh_state** fp,
|
||||
* @param mesh: to update the counters.
|
||||
* @param m: the mesh state.
|
||||
* @param cp: the comm_point to remove from the list.
|
||||
* @param h2_stream: if not NULL, it specifies the h2_stream to match
|
||||
* for the delete.
|
||||
* @param doq_stream: if not NULL, it specifies the doq_stream to match
|
||||
* for the delete.
|
||||
*/
|
||||
void mesh_state_remove_reply(struct mesh_area* mesh, struct mesh_state* m,
|
||||
struct comm_point* cp, struct doq_stream* doq_stream);
|
||||
struct comm_point* cp, struct http2_stream* h2_stream,
|
||||
struct doq_stream* doq_stream);
|
||||
|
||||
/** Callback for when the serve expired client timer has run out. Tries to
|
||||
* find an expired answer in the cache and reply that to the client.
|
||||
@@ -734,9 +766,10 @@ void mesh_respond_serve_expired(struct mesh_state* mstate);
|
||||
* @param qflags: flags from client query.
|
||||
* @param cb: callback function.
|
||||
* @param cb_arg: callback user arg.
|
||||
* @param unique_info: if not NULL, used to find a unique state for removal.
|
||||
*/
|
||||
void mesh_remove_callback(struct mesh_area* mesh, struct query_info* qinfo,
|
||||
uint16_t qflags, mesh_cb_func_type cb, void* cb_arg);
|
||||
uint16_t qflags, mesh_cb_func_type cb, void* cb_arg, void* unique_info);
|
||||
|
||||
/** Copy the client info to the query region. */
|
||||
struct respip_client_info* mesh_copy_client_info(struct regional* region,
|
||||
|
||||
@@ -1702,6 +1702,12 @@ static int setup_if(struct port_if* pif, const char* addrstr, size_t numfd,
|
||||
!netblockstrtoaddr(addrstr, UNBOUND_DNS_PORT,
|
||||
&pif->addr, &pif->addrlen, &pif->pfxlen))
|
||||
return 0;
|
||||
#ifdef INT_MAX
|
||||
if(numfd > (size_t)INT_MAX) {
|
||||
log_err("num_ports exceeds INT_MAX");
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
#ifndef DISABLE_EXPLICIT_PORT_RANDOMISATION
|
||||
pif->shpif = shared_ports_find_if(shp, &pif->addr, pif->addrlen,
|
||||
pif->pfxlen);
|
||||
@@ -1777,6 +1783,13 @@ outside_network_create(struct comm_base *base, size_t bufsize,
|
||||
outside_network_delete(outnet);
|
||||
return NULL;
|
||||
}
|
||||
#ifdef INT_MAX
|
||||
if(num_ports > (size_t)INT_MAX) {
|
||||
log_err("outgoing num_ports exceeds INT_MAX");
|
||||
outside_network_delete(outnet);
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
#ifndef INET6
|
||||
do_ip6 = 0;
|
||||
#endif
|
||||
@@ -3349,9 +3362,9 @@ serviced_udp_callback(struct comm_point* c, void* arg, int error,
|
||||
if(error == NETEVENT_TIMEOUT) {
|
||||
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 */
|
||||
/* fallback to 1472/1232 */
|
||||
sq->status = serviced_query_UDP_EDNS_FRAG;
|
||||
log_name_addr(VERB_ALGO, "try edns1xx0", sq->qbuf+10,
|
||||
log_name_addr(VERB_ALGO, "try edns1xx2", sq->qbuf+10,
|
||||
&sq->addr, sq->addrlen);
|
||||
if(!serviced_udp_send(sq, c->buffer)) {
|
||||
serviced_callbacks(sq, NETEVENT_CLOSED, c, rep);
|
||||
@@ -3488,7 +3501,8 @@ outnet_serviced_query(struct outside_network* outnet,
|
||||
char* tls_auth_name, struct sockaddr_storage* addr, socklen_t addrlen,
|
||||
uint8_t* zone, size_t zonelen, struct module_qstate* qstate,
|
||||
comm_point_callback_type* callback, void* callback_arg,
|
||||
sldns_buffer* buff, struct module_env* env, int* was_ratelimited)
|
||||
sldns_buffer* buff, struct module_env* env, int* was_ratelimited,
|
||||
int* ratelimit_incremented)
|
||||
{
|
||||
struct serviced_query* sq;
|
||||
struct service_callback* cb;
|
||||
@@ -3560,6 +3574,7 @@ outnet_serviced_query(struct outside_network* outnet,
|
||||
"delegation point", zone,
|
||||
LDNS_RR_TYPE_NS, LDNS_RR_CLASS_IN);
|
||||
}
|
||||
*ratelimit_incremented = 1;
|
||||
}
|
||||
/* make new serviced query entry */
|
||||
sq = serviced_create(outnet, buff, dnssec, want_dnssec, nocaps,
|
||||
@@ -3765,7 +3780,33 @@ setup_comm_ssl(struct comm_point* cp, struct outside_network* outnet,
|
||||
(void)SSL_set_tlsext_host_name(cp->ssl, host);
|
||||
}
|
||||
#endif
|
||||
#ifdef HAVE_SSL_SET1_HOST
|
||||
#ifdef HAVE_SSL_SET1_DNSNAME
|
||||
if((SSL_CTX_get_verify_mode(outnet->sslctx)&SSL_VERIFY_PEER)) {
|
||||
/* because we set SSL_VERIFY_PEER, in netevent in
|
||||
* ssl_handshake, it'll check if the certificate
|
||||
* verification has succeeded */
|
||||
/* SSL_VERIFY_PEER is set on the sslctx */
|
||||
/* and the certificates to verify with are loaded into
|
||||
* it with SSL_load_verify_locations or
|
||||
* SSL_CTX_set_default_verify_paths */
|
||||
/* setting the hostname makes openssl verify the
|
||||
* host name in the x509 certificate in the
|
||||
* SSL connection*/
|
||||
struct sockaddr_storage tmpaddr;
|
||||
socklen_t tmpaddrlen = (socklen_t)sizeof(tmpaddr);
|
||||
if(ipstrtoaddr(host, UNBOUND_DNS_PORT, &tmpaddr, &tmpaddrlen)) {
|
||||
if(!SSL_set1_ipaddr(cp->ssl, host)) {
|
||||
log_err("SSL_set1_ipaddr failed");
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
if(!SSL_set1_dnsname(cp->ssl, host)) {
|
||||
log_err("SSL_set1_dnsname failed");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
#elif defined(HAVE_SSL_SET1_HOST)
|
||||
if((SSL_CTX_get_verify_mode(outnet->sslctx)&SSL_VERIFY_PEER)) {
|
||||
/* because we set SSL_VERIFY_PEER, in netevent in
|
||||
* ssl_handshake, it'll check if the certificate
|
||||
@@ -3894,7 +3935,8 @@ outnet_comm_point_for_http(struct outside_network* outnet,
|
||||
/* outnet_tcp_connect has closed fd on error for us */
|
||||
return 0;
|
||||
}
|
||||
cp = comm_point_create_http_out(outnet->base, 65552, cb, cb_arg,
|
||||
cp = comm_point_create_http_out(outnet->base,
|
||||
sldns_buffer_capacity(outnet->udp_buff), cb, cb_arg,
|
||||
outnet->udp_buff);
|
||||
if(!cp) {
|
||||
log_err("malloc failure");
|
||||
@@ -4085,13 +4127,15 @@ static int shared_ports_alloc_ifs(struct shared_ports* shp, char** ifs,
|
||||
size_t done_4 = 0, done_6 = 0;
|
||||
int i;
|
||||
for(i=0; i<num_ifs; i++) {
|
||||
if(str_is_ip6(ifs[i]) && do_ip6) {
|
||||
if(str_is_ip6(ifs[i]) && do_ip6 &&
|
||||
(int)done_6 < shp->num_ip6) {
|
||||
if(!shared_ports_setup_if(&shp->ip6_ifs[done_6],
|
||||
ifs[i], availports, numavailports))
|
||||
return 0;
|
||||
done_6++;
|
||||
}
|
||||
if(!str_is_ip6(ifs[i]) && do_ip4) {
|
||||
if(!str_is_ip6(ifs[i]) && do_ip4 &&
|
||||
(int)done_4 < shp->num_ip4) {
|
||||
if(!shared_ports_setup_if(&shp->ip4_ifs[done_4],
|
||||
ifs[i], availports, numavailports))
|
||||
return 0;
|
||||
@@ -4112,16 +4156,21 @@ struct shared_ports* shared_ports_create(char** ifs, int num_ifs, int do_ip4,
|
||||
return NULL;
|
||||
}
|
||||
lock_basic_init(&shp->lock);
|
||||
lock_protect(&shp->lock, shp, sizeof(*shp));
|
||||
lock_protect(&shp->lock, &shp->ip4_ifs, sizeof(shp->ip4_ifs));
|
||||
lock_protect(&shp->lock, &shp->num_ip4, sizeof(shp->num_ip4));
|
||||
lock_protect(&shp->lock, &shp->ip6_ifs, sizeof(shp->ip6_ifs));
|
||||
lock_protect(&shp->lock, &shp->num_ip6, sizeof(shp->num_ip6));
|
||||
|
||||
#ifndef DISABLE_EXPLICIT_PORT_RANDOMISATION
|
||||
/* Allocate interfaces */
|
||||
lock_basic_lock(&shp->lock);
|
||||
if(!shared_ports_alloc_ifs(shp, ifs, num_ifs, do_ip4, do_ip6,
|
||||
availports, numavailports)) {
|
||||
log_err("malloc failed");
|
||||
shared_ports_delete(shp);
|
||||
return NULL;
|
||||
}
|
||||
lock_basic_unlock(&shp->lock);
|
||||
#else
|
||||
(void)ifs; (void)num_ifs; (void)do_ip4; (void)do_ip6;
|
||||
(void)availports; (void)numavailports;
|
||||
@@ -4199,6 +4248,9 @@ int shared_ports_fetch_random(struct shared_ports* shp,
|
||||
int portno = 0, my_port = 0;
|
||||
if(!shpif)
|
||||
return 0;
|
||||
# ifdef THREADS_DISABLED
|
||||
(void)shp;
|
||||
# endif
|
||||
lock_basic_lock(&shp->lock);
|
||||
if(udp_connect) {
|
||||
/* if we connect() we cannot reuse fds for a port. */
|
||||
@@ -4256,6 +4308,9 @@ void shared_ports_return_port(struct shared_ports* shp,
|
||||
#ifndef DISABLE_EXPLICIT_PORT_RANDOMISATION
|
||||
if(!shpif)
|
||||
return;
|
||||
# ifdef THREADS_DISABLED
|
||||
(void)shp;
|
||||
# endif
|
||||
lock_basic_lock(&shp->lock);
|
||||
log_assert(shpif->inuse > 0);
|
||||
shpif->avail_ports[shpif->avail_total - shpif->inuse] = port;
|
||||
|
||||
@@ -538,7 +538,7 @@ struct serviced_query {
|
||||
serviced_query_UDP_EDNS_fallback,
|
||||
/** probe to test TCP noEDNS0 (EDNS gives FORMERRorNOTIMP) */
|
||||
serviced_query_TCP_EDNS_fallback,
|
||||
/** send UDP query with EDNS1480 (or 1280) */
|
||||
/** send UDP query with EDNS1472 (or 1232) */
|
||||
serviced_query_UDP_EDNS_FRAG
|
||||
}
|
||||
/** variable with current status */
|
||||
@@ -697,6 +697,8 @@ void pending_delete(struct outside_network* outnet, struct pending* p);
|
||||
* @param env: the module environment.
|
||||
* @param was_ratelimited: it will signal back if the query failed to pass the
|
||||
* ratelimit check.
|
||||
* @param ratelimit_incremented: set to true if the ratelimit counter
|
||||
* was increased.
|
||||
* @return 0 on error, or pointer to serviced query that is used to answer
|
||||
* this serviced query may be shared with other callbacks as well.
|
||||
*/
|
||||
@@ -706,7 +708,8 @@ struct serviced_query* outnet_serviced_query(struct outside_network* outnet,
|
||||
char* tls_auth_name, struct sockaddr_storage* addr, socklen_t addrlen,
|
||||
uint8_t* zone, size_t zonelen, struct module_qstate* qstate,
|
||||
comm_point_callback_type* callback, void* callback_arg,
|
||||
struct sldns_buffer* buff, struct module_env* env, int* was_ratelimited);
|
||||
struct sldns_buffer* buff, struct module_env* env, int* was_ratelimited,
|
||||
int* ratelimit_incremented);
|
||||
|
||||
/**
|
||||
* Remove service query callback.
|
||||
|
||||
+112
-50
@@ -506,24 +506,37 @@ delete_cname_override(struct rpz* r)
|
||||
static int
|
||||
rpz_apply_cfg_elements(struct rpz* r, struct config_auth* p)
|
||||
{
|
||||
enum rpz_action action_override;
|
||||
if(p->rpz_taglist && p->rpz_taglistlen) {
|
||||
r->taglistlen = p->rpz_taglistlen;
|
||||
r->taglist = memdup(p->rpz_taglist, r->taglistlen);
|
||||
if(!r->taglist) {
|
||||
uint8_t* taglist = memdup(p->rpz_taglist, p->rpz_taglistlen);
|
||||
if(!taglist) {
|
||||
log_err("malloc failure on RPZ taglist alloc");
|
||||
return 0;
|
||||
}
|
||||
if(r->taglist)
|
||||
free(r->taglist);
|
||||
r->taglist = taglist;
|
||||
r->taglistlen = p->rpz_taglistlen;
|
||||
} else {
|
||||
/* free taglist, if any */
|
||||
if(r->taglist) {
|
||||
free(r->taglist);
|
||||
r->taglist = NULL;
|
||||
r->taglistlen = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if(p->rpz_action_override) {
|
||||
r->action_override = rpz_config_to_action(p->rpz_action_override);
|
||||
action_override = rpz_config_to_action(p->rpz_action_override);
|
||||
}
|
||||
else
|
||||
r->action_override = RPZ_NO_OVERRIDE_ACTION;
|
||||
action_override = RPZ_NO_OVERRIDE_ACTION;
|
||||
|
||||
if(r->action_override == RPZ_CNAME_OVERRIDE_ACTION) {
|
||||
if(action_override == RPZ_CNAME_OVERRIDE_ACTION) {
|
||||
uint8_t nm[LDNS_MAX_DOMAINLEN+1];
|
||||
size_t nmlen = sizeof(nm);
|
||||
struct regional* newr;
|
||||
struct ub_packed_rrset_key* cname_override;
|
||||
|
||||
if(!p->rpz_cname) {
|
||||
log_err("rpz: override with cname action found, but no "
|
||||
@@ -536,33 +549,50 @@ rpz_apply_cfg_elements(struct rpz* r, struct config_auth* p)
|
||||
p->rpz_cname);
|
||||
return 0;
|
||||
}
|
||||
r->cname_override = new_cname_override(r->region, nm, nmlen);
|
||||
if(!r->cname_override) {
|
||||
newr = regional_create_custom(sizeof(struct regional));
|
||||
if(!newr) {
|
||||
log_err("malloc failure on RPZ cname override region");
|
||||
return 0;
|
||||
}
|
||||
cname_override = new_cname_override(newr, nm, nmlen);
|
||||
if(!cname_override) {
|
||||
regional_destroy(newr);
|
||||
return 0;
|
||||
}
|
||||
regional_destroy(r->region);
|
||||
r->region = newr;
|
||||
r->cname_override = cname_override;
|
||||
} else {
|
||||
delete_cname_override(r);
|
||||
}
|
||||
r->action_override = action_override;
|
||||
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))) {
|
||||
char* log_name = strdup(p->rpz_log_name);
|
||||
if(!log_name) {
|
||||
log_err("malloc failure on RPZ log_name strdup");
|
||||
return 0;
|
||||
}
|
||||
if(r->log_name)
|
||||
free(r->log_name);
|
||||
r->log_name = log_name;
|
||||
} else {
|
||||
/* free logname, if any */
|
||||
if(r->log_name) {
|
||||
free(r->log_name);
|
||||
r->log_name = NULL;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
struct rpz*
|
||||
rpz_create(struct config_auth* p)
|
||||
rpz_create_empty(void)
|
||||
{
|
||||
struct rpz* r = calloc(1, sizeof(*r));
|
||||
if(!r)
|
||||
goto err;
|
||||
|
||||
r->region = regional_create_custom(sizeof(struct regional));
|
||||
if(!r->region) {
|
||||
goto err;
|
||||
}
|
||||
return NULL;
|
||||
|
||||
if(!(r->local_zones = local_zones_create())){
|
||||
goto err;
|
||||
@@ -586,6 +616,35 @@ rpz_create(struct config_auth* p)
|
||||
if(r->ns_set == NULL) {
|
||||
goto err;
|
||||
}
|
||||
return r;
|
||||
err:
|
||||
if(r) {
|
||||
if(r->local_zones)
|
||||
local_zones_delete(r->local_zones);
|
||||
if(r->nsdname_zones)
|
||||
local_zones_delete(r->nsdname_zones);
|
||||
if(r->respip_set)
|
||||
respip_set_delete(r->respip_set);
|
||||
if(r->client_set != NULL)
|
||||
rpz_clientip_synthesized_set_delete(r->client_set);
|
||||
if(r->ns_set != NULL)
|
||||
rpz_clientip_synthesized_set_delete(r->ns_set);
|
||||
free(r);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct rpz*
|
||||
rpz_create(struct config_auth* p)
|
||||
{
|
||||
struct rpz* r = rpz_create_empty();
|
||||
if(!r)
|
||||
goto err;
|
||||
|
||||
r->region = regional_create_custom(sizeof(struct regional));
|
||||
if(!r->region) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
if(!rpz_apply_cfg_elements(r, p))
|
||||
goto err;
|
||||
@@ -616,22 +675,6 @@ 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;
|
||||
@@ -721,13 +764,22 @@ rpz_insert_local_zones_trigger(struct local_zones* lz, uint8_t* dname,
|
||||
char* rrstr = sldns_wire2str_rr(rr, rr_len);
|
||||
if(rrstr == NULL) {
|
||||
log_err("malloc error while inserting rpz nsdname trigger");
|
||||
free(dname);
|
||||
if(!newzone)
|
||||
free(dname);
|
||||
lock_rw_unlock(&lz->lock);
|
||||
return;
|
||||
}
|
||||
lock_rw_wrlock(&z->lock);
|
||||
local_zone_enter_rr(z, dname, dnamelen, dnamelabs, rrtype,
|
||||
rrclass, ttl, rdata, rdata_len, rrstr);
|
||||
if(!local_zone_enter_rr(z, dname, dnamelen, dnamelabs, rrtype,
|
||||
rrclass, ttl, rdata, rdata_len, rrstr)) {
|
||||
log_err("rpz: could not enter local-data: %s", rrstr);
|
||||
if(!newzone)
|
||||
free(dname);
|
||||
lock_rw_unlock(&z->lock);
|
||||
lock_rw_unlock(&lz->lock);
|
||||
free(rrstr);
|
||||
return;
|
||||
}
|
||||
lock_rw_unlock(&z->lock);
|
||||
free(rrstr);
|
||||
}
|
||||
@@ -805,8 +857,9 @@ rpz_insert_nsdname_trigger(struct rpz* r, uint8_t* dname, size_t dnamelen,
|
||||
uint8_t* dname_stripped = NULL;
|
||||
size_t dnamelen_stripped = 0;
|
||||
|
||||
rpz_strip_nsdname_suffix(dname, dnamelen, &dname_stripped,
|
||||
&dnamelen_stripped);
|
||||
if(!rpz_strip_nsdname_suffix(dname, dnamelen, &dname_stripped,
|
||||
&dnamelen_stripped))
|
||||
return;
|
||||
if(a == RPZ_INVALID_ACTION) {
|
||||
verbose(VERB_ALGO, "rpz: skipping invalid action");
|
||||
free(dname_stripped);
|
||||
@@ -904,8 +957,8 @@ rpz_report_rrset_error(const char* msg, uint8_t* rr, size_t rr_len) {
|
||||
|
||||
/* from localzone.c; difference is we don't have a dname */
|
||||
static struct local_rrset*
|
||||
rpz_clientip_new_rrset(struct regional* region,
|
||||
struct clientip_synthesized_rr* raddr, uint16_t rrtype, uint16_t rrclass)
|
||||
rpz_clientip_new_rrset(struct regional* region, uint16_t rrtype,
|
||||
uint16_t rrclass)
|
||||
{
|
||||
struct packed_rrset_data* pd;
|
||||
struct local_rrset* rrset = (struct local_rrset*)
|
||||
@@ -914,8 +967,6 @@ rpz_clientip_new_rrset(struct regional* region,
|
||||
log_err("out of memory");
|
||||
return NULL;
|
||||
}
|
||||
rrset->next = raddr->data;
|
||||
raddr->data = rrset;
|
||||
rrset->rrset = (struct ub_packed_rrset_key*)
|
||||
regional_alloc_zero(region, sizeof(*rrset->rrset));
|
||||
if(rrset->rrset == NULL) {
|
||||
@@ -954,12 +1005,18 @@ rpz_clientip_enter_rr(struct regional* region, struct clientip_synthesized_rr* r
|
||||
return 0;
|
||||
}
|
||||
|
||||
rrset = rpz_clientip_new_rrset(region, raddr, rrtype, rrclass);
|
||||
if(raddr->data == NULL) {
|
||||
rrset = rpz_clientip_new_rrset(region, rrtype, rrclass);
|
||||
if(rrset == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return rrset_insert_rr(region, rrset->rrset->entry.data, rdata, rdata_len, ttl, "");
|
||||
if(!rrset_insert_rr(region, rrset->rrset->entry.data, rdata, rdata_len, ttl, ""))
|
||||
return 0;
|
||||
|
||||
/* Link in now that the allocations have succeeded. */
|
||||
rrset->next = raddr->data;
|
||||
raddr->data = rrset;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -982,7 +1039,6 @@ rpz_clientip_insert_trigger_rr(struct clientip_synthesized_rrset* set, struct so
|
||||
lock_rw_wrlock(&node->lock);
|
||||
lock_rw_unlock(&set->lock);
|
||||
|
||||
node->action = a;
|
||||
if(a == RPZ_LOCAL_DATA_ACTION) {
|
||||
if(!rpz_clientip_enter_rr(set->region, node, rrtype,
|
||||
rrclass, ttl, rdata, rdata_len)) {
|
||||
@@ -992,6 +1048,7 @@ rpz_clientip_insert_trigger_rr(struct clientip_synthesized_rrset* set, struct so
|
||||
}
|
||||
|
||||
}
|
||||
node->action = a;
|
||||
|
||||
lock_rw_unlock(&node->lock);
|
||||
|
||||
@@ -1977,8 +2034,9 @@ rpz_synthesize_nodata(struct rpz* ATTR_UNUSED(r), struct module_qstate* ms,
|
||||
0, /* total */
|
||||
sec_status_insecure,
|
||||
LDNS_EDE_NONE);
|
||||
if(msg->rep)
|
||||
msg->rep->authoritative = 1;
|
||||
if(!msg->rep)
|
||||
return NULL;
|
||||
msg->rep->authoritative = 1;
|
||||
if(!rpz_add_soa(msg->rep, ms, az))
|
||||
return NULL;
|
||||
return msg;
|
||||
@@ -2008,8 +2066,9 @@ rpz_synthesize_nxdomain(struct rpz* r, struct module_qstate* ms,
|
||||
0, /* total */
|
||||
sec_status_insecure,
|
||||
LDNS_EDE_NONE);
|
||||
if(msg->rep)
|
||||
msg->rep->authoritative = 1;
|
||||
if(!msg->rep)
|
||||
return NULL;
|
||||
msg->rep->authoritative = 1;
|
||||
if(!rpz_add_soa(msg->rep, ms, az))
|
||||
return NULL;
|
||||
return msg;
|
||||
@@ -2062,6 +2121,7 @@ rpz_synthesize_localdata_from_rrset(struct rpz* ATTR_UNUSED(r), struct module_qs
|
||||
* actual data. So that the actual network data and fake data
|
||||
* are kept track of separately. */
|
||||
rp->rk.flags |= PACKED_RRSET_RPZ;
|
||||
rp->entry.hash = rrset_key_hash(&rp->rk);
|
||||
new_reply_info->rrsets[0] = rp;
|
||||
msg->rep = new_reply_info;
|
||||
if(!rpz_add_soa(msg->rep, ms, az))
|
||||
@@ -2227,6 +2287,7 @@ rpz_synthesize_cname_override_msg(struct rpz* r, struct module_qstate* ms,
|
||||
* actual data. So that the actual network data and fake data
|
||||
* are kept track of separately. */
|
||||
rp->rk.flags |= PACKED_RRSET_RPZ;
|
||||
rp->entry.hash = rrset_key_hash(&rp->rk);
|
||||
new_reply_info->rrsets[0] = rp;
|
||||
|
||||
msg->rep = new_reply_info;
|
||||
@@ -2833,7 +2894,8 @@ size_t rpz_get_mem(struct rpz* r)
|
||||
m += r->taglistlen;
|
||||
if(r->log_name)
|
||||
m += strlen(r->log_name) + 1;
|
||||
m += regional_get_mem(r->region);
|
||||
if(r->region)
|
||||
m += regional_get_mem(r->region);
|
||||
m += local_zones_get_mem(r->local_zones);
|
||||
m += local_zones_get_mem(r->nsdname_zones);
|
||||
m += respip_set_get_mem(r->respip_set);
|
||||
|
||||
@@ -219,6 +219,9 @@ void rpz_delete(struct rpz* r);
|
||||
*/
|
||||
int rpz_clear(struct rpz* r);
|
||||
|
||||
/** Create empty RPZ structure, useful as a proxy for entering data. */
|
||||
struct rpz* rpz_create_empty(void);
|
||||
|
||||
/**
|
||||
* Create RPZ. RPZ must be added to linked list after creation.
|
||||
* @return: the newly created RPZ
|
||||
|
||||
+11
-2
@@ -67,19 +67,28 @@ sldns_rr_dnskey_key_size_raw(const unsigned char* keydata,
|
||||
case LDNS_RSASHA512:
|
||||
#endif
|
||||
if (len > 0) {
|
||||
size_t nlen, offset;
|
||||
if (keydata[0] == 0) {
|
||||
/* big exponent */
|
||||
if (len > 3) {
|
||||
memmove(&int16, keydata + 1, 2);
|
||||
exp = ntohs(int16);
|
||||
return (len - exp - 3)*8;
|
||||
offset = 3;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
exp = keydata[0];
|
||||
return (len-exp-1)*8;
|
||||
offset = 1;
|
||||
}
|
||||
if(exp+offset > len)
|
||||
return 0;
|
||||
nlen = len - exp - offset;
|
||||
/* prefixed zeroes mean a smaller value */
|
||||
while(nlen > 0 &&
|
||||
keydata[len-nlen] == 0)
|
||||
nlen--;
|
||||
return nlen*8;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -197,6 +197,8 @@ sldns_fget_token_l(FILE *f, char *token, const char *delim, size_t limit, int *l
|
||||
}
|
||||
*t = '\0';
|
||||
if (c == EOF) {
|
||||
if(p != 0 || quoted)
|
||||
return -1;
|
||||
return (ssize_t)i;
|
||||
}
|
||||
|
||||
|
||||
+27
-6
@@ -874,7 +874,14 @@ rrinternal_parse_rdata(sldns_buffer* strbuf, char* token, size_t token_len,
|
||||
|
||||
rdata_len -= 1;
|
||||
rdata += 1;
|
||||
return sldns_str2wire_check_svcbparams(rdata, rdata_len);
|
||||
status = sldns_str2wire_check_svcbparams(rdata, rdata_len);
|
||||
/* For RFC3597 generic-form input, preserve unprintable records.
|
||||
* Those could have appeared due to secondary zones, and also
|
||||
* unbound writing invalid-format records out in generic form.
|
||||
* If it can be parsed, it fixes the svcparam ordering. */
|
||||
if(was_unknown_rr_format && status != LDNS_WIREPARSE_ERR_OK)
|
||||
status = LDNS_WIREPARSE_ERR_OK;
|
||||
return status;
|
||||
|
||||
}
|
||||
return LDNS_WIREPARSE_ERR_OK;
|
||||
@@ -1201,7 +1208,7 @@ sldns_str2wire_svcbparam_ipv4hint(const char* val, uint8_t* rd, size_t* rd_len)
|
||||
{
|
||||
size_t count;
|
||||
char ip_str[INET_ADDRSTRLEN+1];
|
||||
char *next_ip_str;
|
||||
const char *next_ip_str;
|
||||
size_t i;
|
||||
|
||||
for (i = 0, count = 1; val[i]; i++) {
|
||||
@@ -1256,7 +1263,7 @@ sldns_str2wire_svcbparam_ipv6hint(const char* val, uint8_t* rd, size_t* rd_len)
|
||||
{
|
||||
size_t count;
|
||||
char ip_str[INET6_ADDRSTRLEN+1];
|
||||
char *next_ip_str;
|
||||
const char *next_ip_str;
|
||||
size_t i;
|
||||
|
||||
for (i = 0, count = 1; val[i]; i++) {
|
||||
@@ -1317,7 +1324,7 @@ static int
|
||||
sldns_str2wire_svcbparam_mandatory(const char* val, uint8_t* rd, size_t* rd_len)
|
||||
{
|
||||
size_t i, count, val_len;
|
||||
char* next_key;
|
||||
const char* next_key;
|
||||
|
||||
val_len = strlen(val);
|
||||
|
||||
@@ -1410,6 +1417,7 @@ sldns_str2wire_svcbparam_ech_value(const char* val, uint8_t* rd, size_t* rd_len)
|
||||
return LDNS_WIREPARSE_ERR_BUFFER_TOO_SMALL;
|
||||
sldns_write_uint16(rd, SVCB_KEY_ECH);
|
||||
sldns_write_uint16(rd + 2, 0);
|
||||
*rd_len = 4;
|
||||
|
||||
return LDNS_WIREPARSE_ERR_OK;
|
||||
}
|
||||
@@ -2302,6 +2310,8 @@ int sldns_str2wire_loc_buf(const char* str, uint8_t* rd, size_t* len)
|
||||
|
||||
if (isdigit((unsigned char) *my_str)) {
|
||||
s = strtod(my_str, &my_str);
|
||||
if(s > 60.0)
|
||||
return LDNS_WIREPARSE_ERR_SYNTAX;
|
||||
}
|
||||
|
||||
/* skip blanks before northerness */
|
||||
@@ -2360,6 +2370,8 @@ north:
|
||||
|
||||
if (isdigit((unsigned char) *my_str)) {
|
||||
s = strtod(my_str, &my_str);
|
||||
if(s > 60.0)
|
||||
return LDNS_WIREPARSE_ERR_SYNTAX;
|
||||
}
|
||||
|
||||
/* skip blanks before easterness */
|
||||
@@ -2392,8 +2404,17 @@ east:
|
||||
longitude = equator - longitude;
|
||||
}
|
||||
|
||||
altitude = (uint32_t)(strtod(my_str, &my_str)*100.0 +
|
||||
10000000.0 + 0.5);
|
||||
while (isblank((unsigned char) *my_str)) {
|
||||
my_str++;
|
||||
}
|
||||
|
||||
/* altitude */
|
||||
if(!(isdigit((unsigned char) *my_str) || *my_str == '-'))
|
||||
return LDNS_WIREPARSE_ERR_SYNTAX;
|
||||
s = strtod(my_str, &my_str);
|
||||
if(s < -100000.0 || s > 42849672.95)
|
||||
return LDNS_WIREPARSE_ERR_SYNTAX;
|
||||
altitude = (uint32_t)(s*100.0 + 10000000.0 + 0.5);
|
||||
if (*my_str == 'm' || *my_str == 'M') {
|
||||
my_str++;
|
||||
}
|
||||
|
||||
+165
-11
@@ -156,7 +156,7 @@ char* wsa_strerror(int err);
|
||||
#endif
|
||||
|
||||
static const char ICANN_UPDATE_CA[] =
|
||||
/* The ICANN CA fetched at 24 Sep 2010. Valid to 2028 */
|
||||
/* The ICANN CA fetched at 29 May 2026. Valid to 20 Mar 2045 */
|
||||
"-----BEGIN CERTIFICATE-----\n"
|
||||
"MIIDdzCCAl+gAwIBAgIBATANBgkqhkiG9w0BAQsFADBdMQ4wDAYDVQQKEwVJQ0FO\n"
|
||||
"TjEmMCQGA1UECxMdSUNBTk4gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxFjAUBgNV\n"
|
||||
@@ -177,6 +177,40 @@ static const char ICANN_UPDATE_CA[] =
|
||||
"15nu5JBSewrCkYqYYmaxyOC3WrVGfHZxVI7MpIFcGdvSb2a1uyuua8l0BKgk3ujF\n"
|
||||
"0/wsHNeP22qNyVO+XVBzrM8fk8BSUFuiT/6tZTYXRtEt5aKQZgXbKU5dUF3jT9qg\n"
|
||||
"j/Br5BZw3X/zd325TvnswzMC1+ljLzHnQGGk\n"
|
||||
"-----END CERTIFICATE-----\n"
|
||||
"\n"
|
||||
"-----BEGIN CERTIFICATE-----\n"
|
||||
"MIIFsTCCA5mgAwIBAgIUQFsYkgroBoe69HKQPy8/DQuiLwgwDQYJKoZIhvcNAQEN\n"
|
||||
"BQAwYDELMAkGA1UEBhMCVVMxDjAMBgNVBAoMBUlDQU5OMSYwJAYDVQQLDB1JQ0FO\n"
|
||||
"TiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEZMBcGA1UEAwwQSUNBTk4gUm9vdCBD\n"
|
||||
"QSB2MjAeFw0yNTAzMjAyMTA0MjZaFw00NTAzMjAyMTA0MjZaMGAxCzAJBgNVBAYT\n"
|
||||
"AlVTMQ4wDAYDVQQKDAVJQ0FOTjEmMCQGA1UECwwdSUNBTk4gQ2VydGlmaWNhdGlv\n"
|
||||
"biBBdXRob3JpdHkxGTAXBgNVBAMMEElDQU5OIFJvb3QgQ0EgdjIwggIiMA0GCSqG\n"
|
||||
"SIb3DQEBAQUAA4ICDwAwggIKAoICAQCepDjrubjR7en/uZWo7MAnzFIIvUPYEc7b\n"
|
||||
"+AlefdlEDQ1JEmpfrvt/4CX9lJ9ShIBR6zwrQeDvrj5XZ2kEjbJ8Nnc6sM/ojdyr\n"
|
||||
"5jSLqcDPH9fJg7jCW02KF8CtqWsnqcW6jjTIZcCWkg9lEixdF8QAjIEgJtZte+Yh\n"
|
||||
"XeyN0KD2EaO8U5Id0bLvMyphuO1OCGKzDtetcX8K7SvoshdJx3lPIlYzqXl0nVAY\n"
|
||||
"iCeNdeDzTNjEOHYJOP6dYoZI8nKRJltMkZcCCjBE2vQuSMY2w4pOlWk1skHjMWXj\n"
|
||||
"QsZzngXuNG56zialL0TPEDVWjWRjzOnruHUAs4KUY8Zs+Nt8JdSlXMi825PKoKpp\n"
|
||||
"ESs7/ZG1mPjVOYp7Z7ntrRjJFgnUBjWzVPOx4yHiJj1ur+OpqP18oP5YfqY+tKmz\n"
|
||||
"7vlfRGGOEd08a0XgZISDNKpMAovn5pRUHTWPCCjc28tns9ODPvr1cQi+QSwTv+v8\n"
|
||||
"wnA5etGrsead88Rv/ieaq5ikMJTRDfW4d9SY2uPcMGvfU6VdQLRhQkzEVTQNAJ1R\n"
|
||||
"i2lOoJbbjwnK+OU9OhST/OqdjJDJAhTAstdUnrr8WBU80xM75MIaaTjSBCvZ1wro\n"
|
||||
"pAi2hYb0tedTH6WarSW3MH9HcEoGGzs2GD3hDB0a2eCp+TdAs8Up944SjY7UV4Jx\n"
|
||||
"sOC7TxbmkQIDAQABo2MwYTAdBgNVHQ4EFgQU+1EuMRuOZ/ecsfYzNQ+yGZsxZrMw\n"
|
||||
"HwYDVR0jBBgwFoAU+1EuMRuOZ/ecsfYzNQ+yGZsxZrMwDwYDVR0TAQH/BAUwAwEB\n"
|
||||
"/zAOBgNVHQ8BAf8EBAMCAf4wDQYJKoZIhvcNAQENBQADggIBACz38SkKR1WsEZnX\n"
|
||||
"x1BKaS5/oQPw+7quDQCKGoD2Vz7CR7yQh4zQn/Hh0173vKvRWcwN2io0iLJ1ysv5\n"
|
||||
"jXBLeWZh3djiQlXP3iWp4s01SiUwmFssxi3SD1IT2jNosk1xcVWthle9zth7Y8Mp\n"
|
||||
"iUJYnHobP7tX7H2g+I8Rqw2sEX/yPSYMYcdH5a1xRMPOLHTyOaCgevRBBBtXkiAJ\n"
|
||||
"Ob9QKZTaFaXntPXBKNSGkVb2d+2qKyJMrwd0KNI+SVSoIgNDAxkNOdi9x6X6ETW2\n"
|
||||
"4aYFsytohFVkNUXx2eFYRim4yjnD8PHIvDQSofLfSAC5TOERtwUFd+Mw3/di+HCm\n"
|
||||
"50OJPyoxZLjWQCCfNUZzgZZOe+zT6lgBiV3KB0UuuAdq7jGUeH/328HJDi30BvNj\n"
|
||||
"+TNb9Hmpm+ZDguM+f8p7GxapX8AVNu/xErtl4msYiVJrr1qqV+qLLEMwIz0raujG\n"
|
||||
"FFDd6N43wgduffbU20pThry0Y7rku5+RZjUZe/T7ZL+NUKiqXAPufrkqVkjX/8T+\n"
|
||||
"wyNZz8KkiQwkJthojpppa79FDxn/A2M8tt+FQqIONAUPR2m5nurVgftQH0z5ZtDB\n"
|
||||
"YykUlkUiPOJNXoDOIkbpA7lW2wezeY4te+EiSeUZSE541N5QBwaItaonIZsIgn6C\n"
|
||||
"pMnwChV9468oRE20bdqq9+Go7g4E\n"
|
||||
"-----END CERTIFICATE-----\n";
|
||||
|
||||
static const char DS_TRUST_ANCHOR[] =
|
||||
@@ -1674,18 +1708,116 @@ static unsigned long
|
||||
get_usage_of_ex(X509* cert)
|
||||
{
|
||||
unsigned long val = 0;
|
||||
#ifdef HAVE_X509_GET_KEY_USAGE
|
||||
val = X509_get_key_usage(cert);
|
||||
if (val == UINT32_MAX)
|
||||
return 0;
|
||||
#else
|
||||
ASN1_BIT_STRING* s;
|
||||
if((s=X509_get_ext_d2i(cert, NID_key_usage, NULL, NULL))) {
|
||||
if(s->length > 0) {
|
||||
val = s->data[0];
|
||||
if(s->length > 1)
|
||||
val |= s->data[1] << 8;
|
||||
# ifdef HAVE_ASN1_STRING_GET0_DATA
|
||||
const unsigned char *data = ASN1_STRING_get0_data(s);
|
||||
# else
|
||||
const unsigned char *data = ASN1_STRING_data(s);
|
||||
# endif
|
||||
int len = ASN1_STRING_length(s);
|
||||
if(len > 0) {
|
||||
val = data[0];
|
||||
if(len > 1)
|
||||
val |= data[1] << 8;
|
||||
}
|
||||
ASN1_BIT_STRING_free(s);
|
||||
}
|
||||
#endif
|
||||
return val;
|
||||
}
|
||||
|
||||
#if !defined(HAVE_X509_NAME_GET_TEXT_BY_NID) || defined(DEPRECATED_X509_NAME_GET_TEXT_BY_NID)
|
||||
/** print verbose output about name extension data. */
|
||||
static void
|
||||
print_name_ext(
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x40000000
|
||||
const
|
||||
#endif
|
||||
X509_NAME* nm, int nid, const char* str)
|
||||
{
|
||||
int lastpos = -1;
|
||||
for(;;) {
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x40000000
|
||||
const
|
||||
#endif
|
||||
X509_NAME_ENTRY* ne;
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x40000000
|
||||
const
|
||||
#endif
|
||||
ASN1_STRING *asn;
|
||||
const unsigned char *data;
|
||||
char buf[1024];
|
||||
|
||||
lastpos = X509_NAME_get_index_by_NID(nm, nid, lastpos);
|
||||
if(lastpos == -1 || lastpos == -2)
|
||||
break;
|
||||
ne = X509_NAME_get_entry(nm, lastpos);
|
||||
if(!ne) continue;
|
||||
asn = X509_NAME_ENTRY_get_data(ne);
|
||||
if(!asn) continue;
|
||||
# ifdef HAVE_ASN1_STRING_GET0_DATA
|
||||
data = ASN1_STRING_get0_data(asn);
|
||||
# else
|
||||
data = ASN1_STRING_data(asn);
|
||||
# endif
|
||||
if(!data) continue;
|
||||
if(ASN1_STRING_length(asn) > (int)sizeof(buf)-1) continue;
|
||||
memcpy(buf, data, ASN1_STRING_length(asn));
|
||||
buf[ASN1_STRING_length(asn)]=0;
|
||||
printf("%s: %s\n", str, buf);
|
||||
}
|
||||
}
|
||||
#endif /* X509_NAME_GET_TEXT_BY_NID */
|
||||
|
||||
#if !defined(HAVE_X509_NAME_GET_TEXT_BY_NID) || defined(DEPRECATED_X509_NAME_GET_TEXT_BY_NID)
|
||||
/** see if the valid emailaddr is present. */
|
||||
static int
|
||||
has_valid_emailaddr(
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x40000000
|
||||
const
|
||||
#endif
|
||||
X509_NAME* nm, const char* p7signer)
|
||||
{
|
||||
int lastpos = -1;
|
||||
for(;;) {
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x40000000
|
||||
const
|
||||
#endif
|
||||
X509_NAME_ENTRY* ne;
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x40000000
|
||||
const
|
||||
#endif
|
||||
ASN1_STRING *asn;
|
||||
const unsigned char *data;
|
||||
|
||||
lastpos = X509_NAME_get_index_by_NID(nm,
|
||||
NID_pkcs9_emailAddress, lastpos);
|
||||
if(lastpos == -1 || lastpos == -2)
|
||||
break;
|
||||
ne = X509_NAME_get_entry(nm, lastpos);
|
||||
if(!ne) continue;
|
||||
asn = X509_NAME_ENTRY_get_data(ne);
|
||||
if(!asn) continue;
|
||||
# ifdef HAVE_ASN1_STRING_GET0_DATA
|
||||
data = ASN1_STRING_get0_data(asn);
|
||||
# else
|
||||
data = ASN1_STRING_data(asn);
|
||||
# endif
|
||||
if(!data) continue;
|
||||
if(ASN1_STRING_length(asn) == (int)strlen(p7signer) &&
|
||||
strncmp((char*)data, p7signer, strlen(p7signer)) == 0)
|
||||
return 1; /* match */
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif /* X509_NAME_GET_TEXT_BY_NID */
|
||||
|
||||
/** get valid signers from the list of signers in the signature */
|
||||
static STACK_OF(X509)*
|
||||
get_valid_signers(PKCS7* p7, const char* p7signer)
|
||||
@@ -1705,6 +1837,9 @@ get_valid_signers(PKCS7* p7, const char* p7signer)
|
||||
return NULL;
|
||||
}
|
||||
for(i=0; i<sk_X509_num(signers); i++) {
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x40000000
|
||||
const
|
||||
#endif
|
||||
X509_NAME* nm = X509_get_subject_name(
|
||||
sk_X509_value(signers, i));
|
||||
char buf[1024];
|
||||
@@ -1717,17 +1852,29 @@ get_valid_signers(PKCS7* p7, const char* p7signer)
|
||||
(int)sizeof(buf));
|
||||
printf("signer %d: Subject: %s\n", i,
|
||||
nmline?nmline:"no subject");
|
||||
#if !defined(HAVE_X509_NAME_GET_TEXT_BY_NID) || defined(DEPRECATED_X509_NAME_GET_TEXT_BY_NID)
|
||||
if(verb >= 3) {
|
||||
print_name_ext(nm, NID_commonName,
|
||||
"commonName");
|
||||
print_name_ext(nm, NID_pkcs9_emailAddress,
|
||||
"emailAddress");
|
||||
}
|
||||
#else
|
||||
if(verb >= 3 && X509_NAME_get_text_by_NID(nm,
|
||||
NID_commonName, buf, (int)sizeof(buf)))
|
||||
NID_commonName, buf, (int)sizeof(buf)) > 0)
|
||||
printf("commonName: %s\n", buf);
|
||||
if(verb >= 3 && X509_NAME_get_text_by_NID(nm,
|
||||
NID_pkcs9_emailAddress, buf, (int)sizeof(buf)))
|
||||
NID_pkcs9_emailAddress, buf, (int)sizeof(buf)) > 0)
|
||||
printf("emailAddress: %s\n", buf);
|
||||
#endif
|
||||
}
|
||||
if(verb) {
|
||||
int ku_loc = X509_get_ext_by_NID(
|
||||
sk_X509_value(signers, i), NID_key_usage, -1);
|
||||
if(verb >= 3 && ku_loc >= 0) {
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x40000000
|
||||
const
|
||||
#endif
|
||||
X509_EXTENSION *ex = X509_get_ext(
|
||||
sk_X509_value(signers, i), ku_loc);
|
||||
if(ex) {
|
||||
@@ -1741,16 +1888,23 @@ get_valid_signers(PKCS7* p7, const char* p7signer)
|
||||
/* there is no name to check, return all records */
|
||||
if(verb) printf("did not check commonName of signer\n");
|
||||
} else {
|
||||
if(!X509_NAME_get_text_by_NID(nm,
|
||||
#if !defined(HAVE_X509_NAME_GET_TEXT_BY_NID) || defined(DEPRECATED_X509_NAME_GET_TEXT_BY_NID)
|
||||
if(!has_valid_emailaddr(nm, p7signer)) {
|
||||
if(verb) printf("removed cert with wrong emailaddress\n");
|
||||
continue; /* wrong name, skip it */
|
||||
}
|
||||
#else
|
||||
if(X509_NAME_get_text_by_NID(nm,
|
||||
NID_pkcs9_emailAddress,
|
||||
buf, (int)sizeof(buf))) {
|
||||
if(verb) printf("removed cert with no name\n");
|
||||
buf, (int)sizeof(buf)) <= 0) {
|
||||
if(verb) printf("removed cert with no emailaddress\n");
|
||||
continue; /* no name, no use */
|
||||
}
|
||||
if(strcmp(buf, p7signer) != 0) {
|
||||
if(verb) printf("removed cert with wrong name\n");
|
||||
if(verb) printf("removed cert with wrong emailaddress\n");
|
||||
continue; /* wrong name, skip it */
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* check that the key usage allows digital signatures
|
||||
|
||||
@@ -73,6 +73,9 @@
|
||||
#ifdef HAVE_GLOB_H
|
||||
#include <glob.h>
|
||||
#endif
|
||||
#ifdef HAVE_FNMATCH_H
|
||||
#include <fnmatch.h>
|
||||
#endif
|
||||
#ifdef WITH_PYTHONMODULE
|
||||
#include "pythonmod/pythonmod.h"
|
||||
#endif
|
||||
@@ -728,6 +731,122 @@ check_modules_exist(const char* module_conf)
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef USE_IPSECMOD
|
||||
/** Compare filename with string, true if it matches the name. */
|
||||
static int
|
||||
file_string_matches(char* str, char* fname, struct config_file* cfg)
|
||||
{
|
||||
char* f;
|
||||
if(!str || str[0] == 0)
|
||||
return 0;
|
||||
/* compare name after chroot and working dir are applied */
|
||||
f = fname_after_chroot(str, cfg, 1);
|
||||
if(!f) fatal_exit("out of memory");
|
||||
if(strcmp(fname, f) == 0) {
|
||||
free(f);
|
||||
return 1;
|
||||
}
|
||||
free(f);
|
||||
return 0;
|
||||
}
|
||||
#endif /* USE_IPSECMOD */
|
||||
|
||||
/** Compare filename with list of files, true if list contains the name. */
|
||||
static int
|
||||
file_list_contains(struct config_strlist* list, char* fname,
|
||||
struct config_file* cfg)
|
||||
{
|
||||
struct config_strlist* s;
|
||||
char* f;
|
||||
for(s = list; s; s = s->next) {
|
||||
if(!s->str || s->str[0] == 0)
|
||||
continue; /* skip if no file name */
|
||||
/* compare names after chroot and working dir are applied */
|
||||
f = fname_after_chroot(s->str, cfg, 1);
|
||||
if(!f) fatal_exit("out of memory");
|
||||
if(strcmp(fname, f) == 0) {
|
||||
free(f);
|
||||
return 1;
|
||||
}
|
||||
free(f);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Compare filename with list of files, true if list contains the name,
|
||||
* with glob compare. */
|
||||
static int
|
||||
file_list_contains_wild(struct config_strlist* list, char* fname,
|
||||
struct config_file* cfg)
|
||||
{
|
||||
struct config_strlist* s;
|
||||
char* f;
|
||||
for(s = list; s; s = s->next) {
|
||||
if(!s->str || s->str[0] == 0)
|
||||
continue; /* skip if no file name */
|
||||
/* compare names after chroot and working dir are applied */
|
||||
f = fname_after_chroot(s->str, cfg, 1);
|
||||
if(!f) fatal_exit("out of memory");
|
||||
if(strcmp(fname, f) == 0) {
|
||||
free(f);
|
||||
return 1;
|
||||
}
|
||||
#ifdef HAVE_FNMATCH
|
||||
if(fnmatch(f, fname, 0) == 0) {
|
||||
log_err("trusted-keys-file: \"%s\" matches zonefile '%s'",
|
||||
s->str, fname);
|
||||
free(f);
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
free(f);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Check if the auth-zone/rpz zonefile: conflicts with other files,
|
||||
* so it would overwrite that file. Refuse it aliasing any read-side bootstrap
|
||||
* file. */
|
||||
static void
|
||||
check_file_clobber(struct config_file* cfg)
|
||||
{
|
||||
struct config_auth* p;
|
||||
char* zfile, *sourceopt = NULL;
|
||||
for(p = cfg->auths; p; p = p->next) {
|
||||
if(!p->name || p->name[0] == 0)
|
||||
continue; /* skip if no name */
|
||||
if(!p->zonefile || p->zonefile[0]==0)
|
||||
continue; /* no zone file */
|
||||
zfile = fname_after_chroot(p->zonefile, cfg, 1);
|
||||
if(!zfile) fatal_exit("out of memory");
|
||||
if(file_list_contains(cfg->auto_trust_anchor_file_list, zfile,
|
||||
cfg))
|
||||
sourceopt = "auto-trust-anchor-file";
|
||||
else if(file_list_contains(cfg->trust_anchor_file_list, zfile,
|
||||
cfg))
|
||||
sourceopt = "trust-anchor-file";
|
||||
else if(file_list_contains_wild(cfg->trusted_keys_file_list,
|
||||
zfile, cfg))
|
||||
sourceopt = "trusted-keys-file";
|
||||
else if(file_list_contains(cfg->root_hints, zfile, cfg))
|
||||
sourceopt = "root-hints";
|
||||
else if(file_list_contains(cfg->tls_session_ticket_keys.first,
|
||||
zfile, cfg))
|
||||
sourceopt = "tls-session-ticket-keys";
|
||||
#ifdef USE_IPSECMOD
|
||||
if(cfg->ipsecmod_enabled &&
|
||||
file_string_matches(cfg->ipsecmod_hook, zfile, cfg))
|
||||
sourceopt = "ipsecmod-hook";
|
||||
#endif
|
||||
if(sourceopt)
|
||||
fatal_exit("auth-zone '%s': zonefile \"%s\" "
|
||||
"is the same path as a %s option. "
|
||||
"The auth-zone transfer would overwrite it.",
|
||||
p->name, p->zonefile, sourceopt);
|
||||
free(zfile);
|
||||
}
|
||||
}
|
||||
|
||||
/** check configuration for errors */
|
||||
static void
|
||||
morechecks(struct config_file* cfg)
|
||||
@@ -822,6 +941,7 @@ morechecks(struct config_file* cfg)
|
||||
cfg->chrootdir, cfg);
|
||||
}
|
||||
#endif
|
||||
check_file_clobber(cfg);
|
||||
/* remove chroot setting so that modules are not stripping pathnames */
|
||||
free(cfg->chrootdir);
|
||||
cfg->chrootdir = NULL;
|
||||
|
||||
@@ -43,6 +43,7 @@
|
||||
#include "config.h"
|
||||
#include "libunbound/context.h"
|
||||
#include "libunbound/worker.h"
|
||||
#include "libunbound/remote.h"
|
||||
#include "util/fptr_wlist.h"
|
||||
#include "util/log.h"
|
||||
#include "services/mesh.h"
|
||||
@@ -102,7 +103,7 @@ struct outbound_entry* worker_send_query(
|
||||
socklen_t ATTR_UNUSED(addrlen), uint8_t* ATTR_UNUSED(zone),
|
||||
size_t ATTR_UNUSED(zonelen), int ATTR_UNUSED(tcp_upstream), int ATTR_UNUSED(ssl_upstream),
|
||||
char* ATTR_UNUSED(tls_auth_name), struct module_qstate* ATTR_UNUSED(q),
|
||||
int* ATTR_UNUSED(was_ratelimited))
|
||||
int* ATTR_UNUSED(was_ratelimited), int* ATTR_UNUSED(ratelimit_incremented))
|
||||
{
|
||||
log_assert(0);
|
||||
return 0;
|
||||
@@ -142,7 +143,7 @@ struct outbound_entry* libworker_send_query(
|
||||
socklen_t ATTR_UNUSED(addrlen), uint8_t* ATTR_UNUSED(zone),
|
||||
size_t ATTR_UNUSED(zonelen), int ATTR_UNUSED(tcp_upstream), int ATTR_UNUSED(ssl_upstream),
|
||||
char* ATTR_UNUSED(tls_auth_name), struct module_qstate* ATTR_UNUSED(q),
|
||||
int* ATTR_UNUSED(was_ratelimited))
|
||||
int* ATTR_UNUSED(was_ratelimited), int* ATTR_UNUSED(ratelimit_incremented))
|
||||
{
|
||||
log_assert(0);
|
||||
return 0;
|
||||
|
||||
+12
-3
@@ -146,7 +146,9 @@ submit_query(struct http2_session* h2_session, struct sldns_buffer* buf)
|
||||
{
|
||||
int32_t stream_id;
|
||||
struct http2_stream* h2_stream;
|
||||
nghttp2_nv headers[5];
|
||||
nghttp2_nv headers[6];
|
||||
size_t num_headers = 5;
|
||||
char clen[16];
|
||||
char* qb64;
|
||||
size_t qb64_size;
|
||||
size_t qb64_expected_size;
|
||||
@@ -194,9 +196,16 @@ submit_query(struct http2_session* h2_session, struct sldns_buffer* buf)
|
||||
headers[3].value = (uint8_t*)h2_session->authority;
|
||||
headers[4].name = (uint8_t*)"content-type";
|
||||
headers[4].value = (uint8_t*)h2_session->content_type;
|
||||
if(h2_session->post) {
|
||||
snprintf(clen, sizeof(clen), "%u",
|
||||
(unsigned)sldns_buffer_remaining(buf));
|
||||
headers[5].name = (uint8_t*)"content-length";
|
||||
headers[5].value = (uint8_t*)clen;
|
||||
num_headers = 6;
|
||||
}
|
||||
|
||||
printf("Request headers\n");
|
||||
for(i=0; i<sizeof(headers)/sizeof(headers[0]); i++) {
|
||||
for(i=0; i<num_headers; i++) {
|
||||
headers[i].namelen = strlen((char*)headers[i].name);
|
||||
headers[i].valuelen = strlen((char*)headers[i].value);
|
||||
headers[i].flags = NGHTTP2_NV_FLAG_NONE;
|
||||
@@ -204,7 +213,7 @@ submit_query(struct http2_session* h2_session, struct sldns_buffer* buf)
|
||||
}
|
||||
|
||||
stream_id = nghttp2_submit_request(h2_session->session, NULL, headers,
|
||||
sizeof(headers)/sizeof(headers[0]),
|
||||
num_headers,
|
||||
(h2_session->post) ? &data_prd : NULL, h2_stream);
|
||||
if(stream_id < 0) {
|
||||
printf("Failed to submit nghttp2 request");
|
||||
|
||||
+10
-5
@@ -1137,8 +1137,11 @@ static struct ngtcp2_conn* conn_client_setup(struct doq_client_data* data)
|
||||
client_chosen_version, &cbs, &settings, ¶ms,
|
||||
NULL, /* ngtcp2_mem allocator, use default */
|
||||
data /* callback argument */);
|
||||
if(!conn) fatal_exit("could not ngtcp2_conn_client_new: %s",
|
||||
ngtcp2_strerror(rv));
|
||||
if(rv!=0) {
|
||||
conn = NULL;
|
||||
fatal_exit("could not ngtcp2_conn_client_new: %s",
|
||||
ngtcp2_strerror(rv));
|
||||
}
|
||||
data->cc_algo = settings.cc_algo;
|
||||
return conn;
|
||||
}
|
||||
@@ -2098,7 +2101,7 @@ early_data_setup_session(struct doq_client_data* data)
|
||||
SSL_SESSION_free(session);
|
||||
return 0;
|
||||
}
|
||||
#ifdef USE_NGTCP2_CRYPTO_OSSL
|
||||
#ifdef HAVE_SSL_SET_QUIC_TLS_EARLY_DATA_ENABLED
|
||||
SSL_set_quic_tls_early_data_enabled(data->ssl, 1);
|
||||
#else
|
||||
SSL_set_quic_early_data_enabled(data->ssl, 1);
|
||||
@@ -2595,7 +2598,8 @@ struct outbound_entry* worker_send_query(
|
||||
socklen_t ATTR_UNUSED(addrlen), uint8_t* ATTR_UNUSED(zone),
|
||||
size_t ATTR_UNUSED(zonelen), int ATTR_UNUSED(tcp_upstream),
|
||||
int ATTR_UNUSED(ssl_upstream), char* ATTR_UNUSED(tls_auth_name),
|
||||
struct module_qstate* ATTR_UNUSED(q), int* ATTR_UNUSED(was_ratelimited))
|
||||
struct module_qstate* ATTR_UNUSED(q), int* ATTR_UNUSED(was_ratelimited),
|
||||
int* ATTR_UNUSED(ratelimit_incremented))
|
||||
{
|
||||
log_assert(0);
|
||||
return 0;
|
||||
@@ -2629,7 +2633,8 @@ struct outbound_entry* libworker_send_query(
|
||||
socklen_t ATTR_UNUSED(addrlen), uint8_t* ATTR_UNUSED(zone),
|
||||
size_t ATTR_UNUSED(zonelen), int ATTR_UNUSED(tcp_upstream),
|
||||
int ATTR_UNUSED(ssl_upstream), char* ATTR_UNUSED(tls_auth_name),
|
||||
struct module_qstate* ATTR_UNUSED(q), int* ATTR_UNUSED(was_ratelimited))
|
||||
struct module_qstate* ATTR_UNUSED(q), int* ATTR_UNUSED(was_ratelimited),
|
||||
int* ATTR_UNUSED(ratelimit_incremented))
|
||||
{
|
||||
log_assert(0);
|
||||
return 0;
|
||||
|
||||
@@ -1276,7 +1276,8 @@ struct serviced_query* outnet_serviced_query(struct outside_network* outnet,
|
||||
socklen_t addrlen, uint8_t* zone, size_t zonelen,
|
||||
struct module_qstate* qstate, comm_point_callback_type* callback,
|
||||
void* callback_arg, sldns_buffer* ATTR_UNUSED(buff),
|
||||
struct module_env* env, int* ATTR_UNUSED(was_ratelimited))
|
||||
struct module_env* env, int* ATTR_UNUSED(was_ratelimited),
|
||||
int* ATTR_UNUSED(ratelimit_incremented))
|
||||
{
|
||||
struct replay_runtime* runtime = (struct replay_runtime*)outnet->base;
|
||||
struct fake_pending* pend = (struct fake_pending*)calloc(1,
|
||||
|
||||
@@ -264,6 +264,9 @@ setup_config(FILE* in, int* lineno, int* pass_argc, char* pass_argv[])
|
||||
fprintf(cfg, " pidfile: \"\"\n");
|
||||
fprintf(cfg, " val-log-level: 2\n");
|
||||
fprintf(cfg, " log-servfail: yes\n");
|
||||
/* the extra thread needs pipe communication that is not available
|
||||
* from fake_event calls. So auth-task-threads: 0 disables them. */
|
||||
fprintf(cfg, " auth-task-threads: 0\n");
|
||||
fprintf(cfg, "remote-control: control-enable: no\n");
|
||||
while(fgets(line, MAX_LINE_LEN-1, in)) {
|
||||
parse = line;
|
||||
@@ -786,3 +789,13 @@ size_t doq_table_quic_size_get(struct doq_table* ATTR_UNUSED(table))
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
void tcp_read_again_cb(void* ATTR_UNUSED(arg))
|
||||
{
|
||||
/* nothing */
|
||||
}
|
||||
|
||||
void tcp_more_read_again_cb(void* ATTR_UNUSED(arg))
|
||||
{
|
||||
/* nothing */
|
||||
}
|
||||
|
||||
+7
-7
@@ -387,7 +387,7 @@ hex_buffer2wire(sldns_buffer *data_buffer)
|
||||
uint8_t *wire = (uint8_t*)malloc(MAX_PACKETLEN);
|
||||
if(!wire) error("out of memory");
|
||||
|
||||
hexbuf = (uint8_t*)malloc(MAX_PACKETLEN);
|
||||
hexbuf = (uint8_t*)malloc(MAX_PACKETLEN * 2);
|
||||
if(!hexbuf) error("out of memory");
|
||||
for (data_buf_pos = 0; data_buf_pos < sldns_buffer_position(data_buffer); data_buf_pos++) {
|
||||
c = (int) data_wire[data_buf_pos];
|
||||
@@ -402,7 +402,7 @@ hex_buffer2wire(sldns_buffer *data_buffer)
|
||||
(c >= 'a' && c <= 'f') ||
|
||||
(c >= 'A' && c <= 'F') )
|
||||
{
|
||||
if (hexbufpos >= MAX_PACKETLEN) {
|
||||
if (hexbufpos >= MAX_PACKETLEN * 2) {
|
||||
error("buffer overflow");
|
||||
free(hexbuf);
|
||||
return 0;
|
||||
@@ -422,7 +422,7 @@ hex_buffer2wire(sldns_buffer *data_buffer)
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
if (hexbufpos >= MAX_PACKETLEN) {
|
||||
if (hexbufpos >= MAX_PACKETLEN * 2) {
|
||||
error("buffer overflow");
|
||||
free(hexbuf);
|
||||
return 0;
|
||||
@@ -433,13 +433,13 @@ hex_buffer2wire(sldns_buffer *data_buffer)
|
||||
}
|
||||
}
|
||||
|
||||
if (hexbufpos >= MAX_PACKETLEN) {
|
||||
if (hexbufpos >= MAX_PACKETLEN * 2) {
|
||||
/*verbose("packet size reached\n");*/
|
||||
}
|
||||
|
||||
/* lenient mode: length must be multiple of 2 */
|
||||
if (hexbufpos % 2 != 0) {
|
||||
if (hexbufpos >= MAX_PACKETLEN) {
|
||||
if (hexbufpos >= MAX_PACKETLEN * 2) {
|
||||
error("buffer overflow");
|
||||
free(hexbuf);
|
||||
return 0;
|
||||
@@ -630,7 +630,7 @@ read_entry(FILE* in, const char* name, struct sldns_file_parse_state* pstate,
|
||||
add_section = LDNS_SECTION_ADDITIONAL;
|
||||
else error("%s line %d: bad section %s", name, pstate->lineno, parse);
|
||||
} else if(str_keyword(&parse, "HEX_ANSWER_BEGIN")) {
|
||||
hex_data_buffer = sldns_buffer_new(MAX_PACKETLEN);
|
||||
hex_data_buffer = sldns_buffer_new(MAX_PACKETLEN*2);
|
||||
reading_hex = 1;
|
||||
} else if(str_keyword(&parse, "HEX_ANSWER_END")) {
|
||||
if(!reading_hex) {
|
||||
@@ -643,7 +643,7 @@ read_entry(FILE* in, const char* name, struct sldns_file_parse_state* pstate,
|
||||
} else if(reading_hex) {
|
||||
sldns_buffer_printf(hex_data_buffer, "%s", line);
|
||||
} else if(str_keyword(&parse, "HEX_EDNSDATA_BEGIN")) {
|
||||
hex_ednsdata_buffer = sldns_buffer_new(MAX_PACKETLEN);
|
||||
hex_ednsdata_buffer = sldns_buffer_new(MAX_PACKETLEN*2);
|
||||
reading_hex_ednsdata = 1;
|
||||
} else if(str_keyword(&parse, "HEX_EDNSDATA_END")) {
|
||||
if (!reading_hex_ednsdata) {
|
||||
|
||||
+34
-1
@@ -735,7 +735,7 @@ check_read_exact(const char* name, const char* zone)
|
||||
z = authtest_addzone(az, name, fname);
|
||||
unit_assert(z);
|
||||
outf = create_tmp_file(NULL);
|
||||
if(!auth_zone_write_file(z, outf)) {
|
||||
if(!auth_zone_write_file(z, outf, NULL)) {
|
||||
fatal_exit("write file failed for %s", fname);
|
||||
}
|
||||
checkfile(fname, outf);
|
||||
@@ -1027,6 +1027,38 @@ authzone_query_test(void)
|
||||
check_queries("example.com", zone_example_com, example_com_queries);
|
||||
}
|
||||
|
||||
/** Test chunkline_count_parens output */
|
||||
static void
|
||||
authzone_chunkline_count_parens_test(void)
|
||||
{
|
||||
sldns_buffer* buf;
|
||||
if(vbmp) printf("Testing chunkline_count_parens\n");
|
||||
buf = sldns_buffer_new(1024);
|
||||
if(!buf) fatal_exit("out of memory");
|
||||
|
||||
/* Check that escaped characters are handled, '\x', and in quotes. */
|
||||
sldns_buffer_printf(buf, "TXT \"x\" \\(");
|
||||
unit_assert(chunkline_count_parens(buf, 0) == 0);
|
||||
|
||||
sldns_buffer_clear(buf);
|
||||
sldns_buffer_printf(buf, "TXT ';x' (");
|
||||
unit_assert(chunkline_count_parens(buf, 0) == 0);
|
||||
|
||||
sldns_buffer_clear(buf);
|
||||
sldns_buffer_printf(buf, "TXT \"a;b\" (");
|
||||
unit_assert(chunkline_count_parens(buf, 0) == 1);
|
||||
|
||||
sldns_buffer_clear(buf);
|
||||
sldns_buffer_printf(buf, "TXT \\) )");
|
||||
unit_assert(chunkline_count_parens(buf, 0) == -1);
|
||||
|
||||
sldns_buffer_clear(buf);
|
||||
sldns_buffer_printf(buf, "TXT \"a\\\\\" \"(\" ");
|
||||
unit_assert(chunkline_count_parens(buf, 0) == 0);
|
||||
|
||||
sldns_buffer_free(buf);
|
||||
}
|
||||
|
||||
/** test authzone code */
|
||||
void
|
||||
authzone_test(void)
|
||||
@@ -1036,4 +1068,5 @@ authzone_test(void)
|
||||
authzone_compare_serial();
|
||||
authzone_read_test();
|
||||
authzone_query_test();
|
||||
authzone_chunkline_count_parens_test();
|
||||
}
|
||||
|
||||
@@ -141,6 +141,7 @@ static addrlen_t randomkey(addrkey_t **k, int maxlen)
|
||||
int bits = rand() % maxlen;
|
||||
int bytes = bits/8 + (bits%8>0); /*ceil*/
|
||||
*k = (addrkey_t *) malloc(bytes * sizeof(addrkey_t));
|
||||
if(!*k) fatal_exit("out of memory");
|
||||
for (byte = 0; byte < bytes; byte++) {
|
||||
(*k)[byte] = (addrkey_t)(rand() & 0xFF);
|
||||
}
|
||||
|
||||
@@ -279,10 +279,24 @@ b64_test(void)
|
||||
unit_assert(result == -1);
|
||||
}
|
||||
|
||||
/** test SVCB ech svcparam */
|
||||
static void
|
||||
svcb_ech_test(void)
|
||||
{
|
||||
uint8_t rr[LDNS_RR_BUF_SIZE];
|
||||
size_t rr_len = sizeof(rr), dname_len = 0;
|
||||
int e = sldns_str2wire_rr_buf("x. 300 IN HTTPS 1 . ech=0",
|
||||
rr, &rr_len, &dname_len, 300, NULL, 0, NULL, 0);
|
||||
unit_assert(e == LDNS_WIREPARSE_ERR_OK);
|
||||
unit_assert(rr_len == dname_len + 10 /* type,class,ttl,rdatalen */ + 7 /* rdata */);
|
||||
unit_assert(sldns_read_uint16(rr + dname_len + 8 /* rdlen */) == 7);
|
||||
}
|
||||
|
||||
void
|
||||
ldns_test(void)
|
||||
{
|
||||
unit_show_feature("sldns");
|
||||
rr_tests();
|
||||
b64_test();
|
||||
svcb_ech_test();
|
||||
}
|
||||
|
||||
@@ -1337,6 +1337,89 @@ static void mesh_test(void)
|
||||
free(c1);
|
||||
}
|
||||
|
||||
#include "util/data/packed_rrset.h"
|
||||
#include "sldns/sbuffer.h"
|
||||
/** packed_rrset unit tests */
|
||||
static void packed_rrset_test(void)
|
||||
{
|
||||
/* packed_rr_to_string assembles the dname, type, class, ttl and
|
||||
* rdata of one rr into a buffer of 65535 bytes. Check that it
|
||||
* refuses an rr that does not fit in there, also when the caller
|
||||
* passes a dest_len that is larger than that, like the callers in
|
||||
* daemon/cachedump.c and daemon/remote.c do. Without the check it
|
||||
* writes past the end of the assembly buffer. */
|
||||
uint8_t smalldname[] = "\003www\007example\003com";
|
||||
uint8_t smallrdata[] = {0, 4, 1, 2, 3, 4};
|
||||
uint8_t maxdname[LDNS_MAX_DOMAINLEN];
|
||||
struct ub_packed_rrset_key rrk;
|
||||
struct packed_rrset_data d;
|
||||
uint8_t* rr_data[1];
|
||||
size_t rr_len[1];
|
||||
time_t rr_ttl[1];
|
||||
size_t dest_len = 65535*4+2048; /* the size daemon/cachedump.c uses */
|
||||
char* dest = (char*)malloc(dest_len);
|
||||
int i;
|
||||
|
||||
unit_show_func("util/data/packed_rrset.c", "packed_rr_to_string");
|
||||
if(!dest) fatal_exit("out of memory");
|
||||
memset(&rrk, 0, sizeof(rrk));
|
||||
memset(&d, 0, sizeof(d));
|
||||
rrk.entry.data = &d;
|
||||
rrk.rk.rrset_class = htons(LDNS_RR_CLASS_IN);
|
||||
d.count = 1;
|
||||
d.rr_len = rr_len;
|
||||
d.rr_ttl = rr_ttl;
|
||||
d.rr_data = rr_data;
|
||||
rr_ttl[0] = 3600;
|
||||
|
||||
/* an ordinary rr is printed, also with the large dest_len */
|
||||
rrk.rk.dname = smalldname;
|
||||
rrk.rk.dname_len = sizeof(smalldname);
|
||||
rrk.rk.type = htons(LDNS_RR_TYPE_A);
|
||||
rr_data[0] = smallrdata;
|
||||
rr_len[0] = sizeof(smallrdata);
|
||||
unit_assert(packed_rr_to_string(&rrk, 0, 0, dest, dest_len) == 1);
|
||||
unit_assert(strstr(dest, "1.2.3.4") != NULL);
|
||||
|
||||
/* a dname of the maximum length, 127 labels of one character */
|
||||
for(i=0; i<127; i++) {
|
||||
maxdname[i*2] = 1;
|
||||
maxdname[i*2+1] = (uint8_t)'a';
|
||||
}
|
||||
maxdname[254] = 0;
|
||||
rrk.rk.dname = maxdname;
|
||||
rrk.rk.dname_len = sizeof(maxdname);
|
||||
rrk.rk.type = htons(LDNS_RR_TYPE_TXT);
|
||||
|
||||
/* 255+2+2+4+65272 is exactly 65535, that still fits */
|
||||
rr_len[0] = 65535 - 255 - 8;
|
||||
rr_data[0] = (uint8_t*)calloc(1, rr_len[0]);
|
||||
if(!rr_data[0]) fatal_exit("out of memory");
|
||||
sldns_write_uint16(rr_data[0], (uint16_t)(rr_len[0]-2));
|
||||
unit_assert(packed_rr_to_string(&rrk, 0, 0, dest, dest_len) == 1);
|
||||
free(rr_data[0]);
|
||||
|
||||
/* one more byte of rdata does not fit and must be refused */
|
||||
rr_len[0] = 65535 - 255 - 8 + 1;
|
||||
rr_data[0] = (uint8_t*)calloc(1, rr_len[0]);
|
||||
if(!rr_data[0]) fatal_exit("out of memory");
|
||||
sldns_write_uint16(rr_data[0], (uint16_t)(rr_len[0]-2));
|
||||
unit_assert(packed_rr_to_string(&rrk, 0, 0, dest, dest_len) == 0);
|
||||
unit_assert(dest[0] == 0);
|
||||
free(rr_data[0]);
|
||||
|
||||
/* the largest rdata an rr can hold, well over the buffer */
|
||||
rr_len[0] = 2 + 65535;
|
||||
rr_data[0] = (uint8_t*)calloc(1, rr_len[0]);
|
||||
if(!rr_data[0]) fatal_exit("out of memory");
|
||||
sldns_write_uint16(rr_data[0], 65535);
|
||||
unit_assert(packed_rr_to_string(&rrk, 0, 0, dest, dest_len) == 0);
|
||||
unit_assert(dest[0] == 0);
|
||||
free(rr_data[0]);
|
||||
|
||||
free(dest);
|
||||
}
|
||||
|
||||
void unit_show_func(const char* file, const char* func)
|
||||
{
|
||||
printf("test %s:%s\n", file, func);
|
||||
@@ -1409,6 +1492,7 @@ main(int argc, char* argv[])
|
||||
zonemd_test();
|
||||
tcpreuse_test();
|
||||
msgparse_test();
|
||||
packed_rrset_test();
|
||||
edns_ede_answer_encode_test();
|
||||
localzone_test();
|
||||
mesh_test();
|
||||
@@ -1445,6 +1529,9 @@ main(int argc, char* argv[])
|
||||
# ifdef HAVE_RAND_CLEANUP
|
||||
RAND_cleanup();
|
||||
# endif
|
||||
#ifdef HAVE_OPENSSL_CLEANUP
|
||||
OPENSSL_cleanup();
|
||||
#endif
|
||||
#elif defined(HAVE_NSS)
|
||||
if(NSS_Shutdown() != SECSuccess)
|
||||
fatal_exit("could not shutdown NSS");
|
||||
|
||||
+143
-1
@@ -196,7 +196,7 @@ verifytest_rrset(struct module_env* env, struct val_env* ve,
|
||||
setup_sigalg(dnskey, sigalg); /* check all algorithms in the dnskey */
|
||||
/* ok to give null as qstate here, won't be used for answer section. */
|
||||
sec = dnskeyset_verify_rrset(env, ve, rrset, dnskey, sigalg, &reason,
|
||||
NULL, LDNS_SECTION_ANSWER, NULL, &verified, reasonbuf,
|
||||
NULL, LDNS_SECTION_ANSWER, NULL, NULL, &verified, reasonbuf,
|
||||
sizeof(reasonbuf));
|
||||
if(vsig) {
|
||||
printf("verify outcome is: %s %s\n", sec_status_to_string(sec),
|
||||
@@ -510,6 +510,146 @@ nsec3_hash_test(const char* fname)
|
||||
sldns_buffer_free(buf);
|
||||
}
|
||||
|
||||
/** Test the rrset_canonicalize_to_buffer function to see if the
|
||||
* size of canon_owner name is properly checked for. */
|
||||
static void
|
||||
canon_owner_buf_test(void)
|
||||
{
|
||||
struct regional* region;
|
||||
sldns_buffer* buf;
|
||||
struct ub_packed_rrset_key k;
|
||||
struct packed_rrset_data d;
|
||||
size_t rr_len[2];
|
||||
time_t rr_ttl[2];
|
||||
uint8_t* rr_data[2];
|
||||
int ret;
|
||||
unit_show_func("validator/val_sigcrypt.c",
|
||||
"rrset_canonicalize_to_buffer");
|
||||
region = regional_create();
|
||||
if(!region)
|
||||
fatal_exit("out of memory");
|
||||
/* Purposefully a very small buffer, to overflow it */
|
||||
buf = sldns_buffer_new(28);
|
||||
if(!buf)
|
||||
fatal_exit("out of memory");
|
||||
|
||||
/* An RRset to canonicalize. The buffer is made smaller, so
|
||||
* it can fail on bounds checks. */
|
||||
memset(&d, 0, sizeof(d));
|
||||
d.ttl = 3600;
|
||||
d.count = 1;
|
||||
d.rrsig_count = 1;
|
||||
d.rr_len = rr_len;
|
||||
d.rr_ttl = rr_ttl;
|
||||
d.rr_data = rr_data;
|
||||
rr_len[0] = 18;
|
||||
rr_len[1] = 36;
|
||||
rr_ttl[0] = 3600;
|
||||
rr_ttl[1] = 3600;
|
||||
rr_data[0] = (uint8_t*)"\x00\x10\x0Fzzaaaaaaaaaaaaa";
|
||||
rr_data[1] = (uint8_t*)"\x00\x24\x00\x06\x08\x3\x01\x02\x03\x04\x01\x02\x03\x04\x01\x02\x03\x04\x12\x34\x03zzz\x00zzaaaaaaaaaaa";
|
||||
|
||||
memset(&k, 0, sizeof(k));
|
||||
k.rk.dname = (uint8_t*) "\x0f" "aaaaaaaaaaaaaaa" "\x00";
|
||||
k.rk.dname_len = 17;
|
||||
k.rk.type = htons(LDNS_RR_TYPE_TXT);
|
||||
k.rk.rrset_class = htons(LDNS_RR_CLASS_IN);
|
||||
k.entry.data = &d;
|
||||
|
||||
/* There should be no buffer overflow, assertion failure, here */
|
||||
ret = rrset_canonicalize_to_buffer(region, buf, &k);
|
||||
unit_assert(ret == 0);
|
||||
|
||||
regional_destroy(region);
|
||||
sldns_buffer_free(buf);
|
||||
}
|
||||
|
||||
/** Test if ds_digest_match_dnskey that calls ds_create_dnskey_digest,
|
||||
* checks the buffer size. */
|
||||
static void
|
||||
dnskey_ds_digest_test(void)
|
||||
{
|
||||
struct regional* region;
|
||||
sldns_buffer* buf;
|
||||
struct module_env env;
|
||||
struct ub_packed_rrset_key k1, k2;
|
||||
struct packed_rrset_data d1, d2;
|
||||
size_t rr_len1[1], rr_len2[1];
|
||||
time_t rr_ttl1[1], rr_ttl2[1];
|
||||
uint8_t* rr_rdata1[1], *rr_rdata2[1];
|
||||
int ret;
|
||||
unit_show_func("validator/val_sigcrypt.c", "ds_digest_match_dnskey");
|
||||
region = regional_create();
|
||||
if(!region)
|
||||
fatal_exit("out of memory");
|
||||
/* Purposefully a very small buffer, to overflow it */
|
||||
buf = sldns_buffer_new(28);
|
||||
if(!buf)
|
||||
fatal_exit("out of memory");
|
||||
memset(&env, 0, sizeof(env));
|
||||
env.scratch = region;
|
||||
env.scratch_buffer = buf;
|
||||
|
||||
/* A DNSKEY and DS RRset to match together. The buffer is made
|
||||
* smaller, so it can fail on bounds checks. */
|
||||
memset(&d1, 0, sizeof(d1));
|
||||
d1.ttl = 3600;
|
||||
d1.count = 1;
|
||||
d1.rr_len = rr_len1;
|
||||
d1.rr_ttl = rr_ttl1;
|
||||
d1.rr_data = rr_rdata1;
|
||||
rr_len1[0] = 38;
|
||||
rr_ttl1[0] = 3600;
|
||||
/* DS rdata has: keytag (2bytes), algorithm (1byte),
|
||||
* digesttype (1byte), digest (remainder). */
|
||||
rr_rdata1[0] = (uint8_t*)"\x00\x24"
|
||||
"\x12\x34"
|
||||
"\x08" /* RSASHA256 */
|
||||
"\x02" /* SHA256 */
|
||||
"0123456789abcdef0123456789abcdef"; /* 32 bytes */
|
||||
;
|
||||
|
||||
memset(&k1, 0, sizeof(k1));
|
||||
k1.rk.dname = (uint8_t*) "\x03" "foo" "\x00";
|
||||
k1.rk.dname_len = 5;
|
||||
k1.rk.type = htons(LDNS_RR_TYPE_DS);
|
||||
k1.rk.rrset_class = htons(LDNS_RR_CLASS_IN);
|
||||
k1.entry.data = &d1;
|
||||
|
||||
memset(&d2, 0, sizeof(d2));
|
||||
d2.ttl = 3600;
|
||||
d2.count = 1;
|
||||
d2.rr_len = rr_len2;
|
||||
d2.rr_ttl = rr_ttl2;
|
||||
d2.rr_data = rr_rdata2;
|
||||
rr_len2[0] = 38;
|
||||
rr_ttl2[0] = 3600;
|
||||
/* DNSKEY rdata has: flags (2bytes), protocol (1byte),
|
||||
* algorithm (1byte), publickey (remainder). */
|
||||
rr_rdata2[0] = (uint8_t*)"\x00\x24"
|
||||
"\x01\x01" /* KSK */
|
||||
"\x03" /* DNSSEC_KEYPROTO */
|
||||
"\x08" /* RSASHA256 */
|
||||
"0123456789abcdef0123456789abcdef"; /* 32 bytes of content */
|
||||
;
|
||||
|
||||
memset(&k2, 0, sizeof(k2));
|
||||
k2.rk.dname = (uint8_t*) "\x03" "foo" "\x00";
|
||||
k2.rk.dname_len = 5;
|
||||
k2.rk.type = htons(LDNS_RR_TYPE_DNSKEY);
|
||||
k2.rk.rrset_class = htons(LDNS_RR_CLASS_IN);
|
||||
k2.entry.data = &d2;
|
||||
/* 36 byte rdata length for DNSKEY (38-2), and dname length of 5,
|
||||
* exceeds the (small) buffer size. */
|
||||
|
||||
/* There should be no buffer overflow, assertion failure, here */
|
||||
ret = ds_digest_match_dnskey(&env, &k2, 0, &k1, 0);
|
||||
unit_assert(ret == 0);
|
||||
|
||||
regional_destroy(region);
|
||||
sldns_buffer_free(buf);
|
||||
}
|
||||
|
||||
#define xstr(s) str(s)
|
||||
#define str(s) #s
|
||||
|
||||
@@ -724,4 +864,6 @@ verify_test(void)
|
||||
#endif
|
||||
nsectest();
|
||||
nsec3_hash_test(SRCDIRSTR "/testdata/test_nsec3_hash.1");
|
||||
dnskey_ds_digest_test();
|
||||
canon_owner_buf_test();
|
||||
}
|
||||
|
||||
@@ -85,6 +85,15 @@ for input in $PRE/testdata/*.rpl $PRE/testdata/*.crpl; do
|
||||
fi
|
||||
fi
|
||||
|
||||
# detect if ECDSA is needed
|
||||
if echo $cleaninput | grep ecdsa >/dev/null 2>&1; then
|
||||
if $PRE/testbound -e >/dev/null 2>&1; then
|
||||
: # ECDSA is supported
|
||||
else
|
||||
continue
|
||||
fi
|
||||
fi
|
||||
|
||||
# detect if CLIENT_SUBNET is needed
|
||||
if echo $cleaninput | grep subnet >/dev/null 2>&1; then
|
||||
if $PRE/testbound -c >/dev/null 2>&1; then
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
server:
|
||||
do-not-query-localhost: no
|
||||
fake-sha1: yes
|
||||
verbosity: 8
|
||||
forward-zone:
|
||||
name: "."
|
||||
forward-addr: "127.0.0.1@@TOPORT@"
|
||||
|
||||
+3
-1
@@ -35,11 +35,13 @@ function check_insecure() {
|
||||
# test with good start key, and must do 5011 (no URL possible)
|
||||
echo "*** TEST 1 ***"
|
||||
echo $DS > root.key
|
||||
$PRE/unbound-anchor -x "notexist.xml" -s "notexist.p7s" $OPTS
|
||||
cat root.key
|
||||
$PRE/unbound-anchor -x "notexist.xml" -s "notexist.p7s" $OPTS -vvvv
|
||||
if test $? != 0; then
|
||||
echo "Exitcode not OK"
|
||||
exit 1
|
||||
fi
|
||||
cat root.key
|
||||
check_works
|
||||
# save for test 5
|
||||
cp root.key root.key.probed
|
||||
|
||||
Binary file not shown.
Binary file not shown.
+201
@@ -0,0 +1,201 @@
|
||||
#!/bin/sh
|
||||
|
||||
# run in temp dir.
|
||||
# Then for petal, move into basedir.
|
||||
# For test_cert.key and test_cert.pem, rename the output files to that.
|
||||
# And run signit.sh for both signature files, by commenting infile and outfile.
|
||||
# for test_cert.pem it has emailAddress and keyUsage, but petal.pem does not
|
||||
# need that.
|
||||
|
||||
# settings:
|
||||
|
||||
# directory for files
|
||||
DESTDIR=.
|
||||
|
||||
# issuer and subject name for certificates
|
||||
SERVERNAME=petal
|
||||
CLIENTNAME=petal
|
||||
|
||||
# validity period for certificates
|
||||
DAYS=7200
|
||||
|
||||
# size of keys in bits
|
||||
BITS=3072
|
||||
|
||||
# hash algorithm
|
||||
HASH=sha256
|
||||
|
||||
# base name for unbound server keys
|
||||
SVR_BASE=petal
|
||||
|
||||
# base name for unbound-control keys
|
||||
CTL_BASE=petal
|
||||
|
||||
# flag to recreate generated certificates
|
||||
RECREATE=0
|
||||
|
||||
# we want -rw-r----- access (say you run this as root: grp=yes (server), all=no).
|
||||
umask 0027
|
||||
|
||||
# end of options
|
||||
|
||||
set -eu
|
||||
|
||||
cleanup() {
|
||||
echo "removing artifacts"
|
||||
|
||||
rm -rf \
|
||||
server.cnf \
|
||||
client.cnf \
|
||||
"${SVR_BASE}_trust.pem" \
|
||||
"${CTL_BASE}_trust.pem" \
|
||||
"${SVR_BASE}_trust.srl"
|
||||
}
|
||||
|
||||
fatal() {
|
||||
printf "fatal error: $*\n" >/dev/stderr
|
||||
exit 1
|
||||
}
|
||||
|
||||
usage() {
|
||||
cat <<EOF
|
||||
usage: $0 OPTIONS
|
||||
OPTIONS
|
||||
-d <dir> used directory to store keys and certificates (default: $DESTDIR)
|
||||
-h show help notice
|
||||
-r recreate certificates
|
||||
EOF
|
||||
}
|
||||
|
||||
OPTIND=1
|
||||
while getopts 'd:hr' arg; do
|
||||
case "$arg" in
|
||||
d) DESTDIR="$OPTARG" ;;
|
||||
h) usage; exit 1 ;;
|
||||
r) RECREATE=1 ;;
|
||||
?) fatal "'$arg' unknown option" ;;
|
||||
esac
|
||||
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"
|
||||
|
||||
trap cleanup INT
|
||||
|
||||
# ===
|
||||
# Generate server certificate
|
||||
# ===
|
||||
|
||||
# generate private key; do no recreate it if they already exist.
|
||||
if [ ! -f "$SVR_BASE.key" ]; then
|
||||
openssl genrsa -out "$SVR_BASE.key" "$BITS"
|
||||
fi
|
||||
|
||||
cat >server.cnf <<EOF
|
||||
[req]
|
||||
default_bits=$BITS
|
||||
default_md=$HASH
|
||||
prompt=no
|
||||
distinguished_name=req_distinguished_name
|
||||
x509_extensions=v3_ca
|
||||
[req_distinguished_name]
|
||||
commonName=$SERVERNAME
|
||||
emailAddress=$SERVERNAME
|
||||
[v3_ca]
|
||||
subjectKeyIdentifier=hash
|
||||
authorityKeyIdentifier=keyid:always,issuer:always
|
||||
basicConstraints=critical,CA:TRUE,pathlen:0
|
||||
subjectAltName=DNS:$SERVERNAME
|
||||
keyUsage = digitalSignature, keyCertSign
|
||||
EOF
|
||||
|
||||
[ -f server.cnf ] || fatal "cannot create openssl configuration"
|
||||
|
||||
if [ ! -f "$SVR_BASE.pem" -o $RECREATE -eq 1 ]; then
|
||||
openssl req \
|
||||
-new -x509 \
|
||||
-key "$SVR_BASE.key" \
|
||||
-config server.cnf \
|
||||
-days "$DAYS" \
|
||||
-out "$SVR_BASE.pem"
|
||||
|
||||
[ ! -f "SVR_BASE.pem" ] || fatal "cannot create server certificate"
|
||||
fi
|
||||
|
||||
# ===
|
||||
# Generate client certificate
|
||||
# ===
|
||||
|
||||
# generate private key; do no recreate it if they already exist.
|
||||
if [ ! -f "$CTL_BASE.key" ]; then
|
||||
openssl genrsa -out "$CTL_BASE.key" "$BITS"
|
||||
fi
|
||||
|
||||
cat >client.cnf <<EOF
|
||||
[req]
|
||||
default_bits=$BITS
|
||||
default_md=$HASH
|
||||
prompt=no
|
||||
distinguished_name=req_distinguished_name
|
||||
req_extensions=v3_req
|
||||
[req_distinguished_name]
|
||||
commonName=$CLIENTNAME
|
||||
[v3_req]
|
||||
basicConstraints=critical,CA:FALSE
|
||||
subjectAltName=DNS:$CLIENTNAME
|
||||
EOF
|
||||
|
||||
[ -f client.cnf ] || fatal "cannot create openssl configuration"
|
||||
|
||||
if [ ! -f "$CTL_BASE.pem" -o $RECREATE -eq 1 ]; then
|
||||
openssl x509 \
|
||||
-addtrust serverAuth \
|
||||
-in "$SVR_BASE.pem" \
|
||||
-out "${SVR_BASE}_trust.pem"
|
||||
|
||||
openssl req \
|
||||
-new \
|
||||
-config client.cnf \
|
||||
-key "$CTL_BASE.key" \
|
||||
| openssl x509 \
|
||||
-req \
|
||||
-days "$DAYS" \
|
||||
-CA "${SVR_BASE}_trust.pem" \
|
||||
-CAkey "$SVR_BASE.key" \
|
||||
-CAcreateserial \
|
||||
-$HASH \
|
||||
-extfile client.cnf \
|
||||
-extensions v3_req \
|
||||
-out "$CTL_BASE.pem"
|
||||
|
||||
[ ! -f "CTL_BASE.pem" ] || fatal "cannot create signed client certificate"
|
||||
fi
|
||||
|
||||
# remove unused permissions
|
||||
chmod o-rw \
|
||||
"$SVR_BASE.pem" \
|
||||
"$SVR_BASE.key"
|
||||
chmod g+r,o-rw \
|
||||
"$CTL_BASE.pem" \
|
||||
"$CTL_BASE.key"
|
||||
|
||||
cleanup
|
||||
|
||||
echo "Setup success. Certificates created. Enable in unbound.conf file to use"
|
||||
|
||||
# create trusted usage pem
|
||||
# openssl x509 -in $CTL_BASE.pem -addtrust clientAuth -out $CTL_BASE"_trust.pem"
|
||||
|
||||
# see details with openssl x509 -noout -text < $SVR_BASE.pem
|
||||
# echo "create $CTL_BASE""_browser.pfx (web client certificate)"
|
||||
# echo "create webbrowser PKCS#12 .PFX certificate file. In Firefox import in:"
|
||||
# echo "preferences - advanced - encryption - view certificates - your certs"
|
||||
# echo "empty password is used, simply click OK on the password dialog box."
|
||||
# openssl pkcs12 -export -in $CTL_BASE"_trust.pem" -inkey $CTL_BASE.key -name "unbound remote control client cert" -out $CTL_BASE"_browser.pfx" -password "pass:" || error "could not create browser certificate"
|
||||
|
||||
+40
-21
@@ -1,21 +1,40 @@
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIDfQIBAAKBwQC1xQ/Kca6zszZbcCtdOTIH2Uy2gOy/DfabMUU7TmNPm0dVE0NJ
|
||||
RuN+Rm304SonpwghfP2/ULZNnuDgpG03/32yI7k/VzG6iA4hiF7tT/KAAWC/+2l1
|
||||
QCsawCV2bSrFK0VhcZr7ALqXd8vkDaQ867K029ypjOQtAJ85qdO3mERy7TGtdUcu
|
||||
O6hLeVet419YeQ2F8cfNxn63d7bOzNGLPW5xwaCd3UcgD+Ib0k4xfFvbinvPQUeU
|
||||
J/i4YDWexFYSL+ECAwEAAQKBwCLXXQl+9O+5AEhSnd1Go1Jh0pSA7eBJOuXQcebG
|
||||
Rb7ykp+6C4G2NtDziwwPRNdI6wQQQ0sym18RfyVQHydGr78/nbiIbB3HCn5e92Mh
|
||||
mefzW6ow9Kvm2txLzGKA1lvoyRbNm81jnG/eygi3u7Nqd5PNv+4dHj2RkTlmxOeh
|
||||
qnDMVP5md8uZPv6lYNnrnIzvLCR5vnPNdVwn89AqzI85IcDZdy0R9ZX4NBbsDgAU
|
||||
6ig6uXuRXvSGiyJ/OUXSrnogaQJhAOjvkHUhVZQkPOxO90TNH4j0GdKKtbSWxIdz
|
||||
lKfuJeBAEqs0TL+C6vbS81Xw3W1alyDdUBk3rJMOBqW6Ryq5HNL+j5H+Jfsh7fvc
|
||||
Yle+5wHGci0P9zCFZCrY8It7n9XFIwJhAMfEi6oJa2G8waPJ1bQhxka82Tf9pnKM
|
||||
XCn/1BBOFjVIx5F842cpA+zp5a62GENTGYPQTTRBB/2/ZwnW5aIkrlg54AtmbqBZ
|
||||
Oh+2kJdJQD/tfoVmc5soUE2ScTHadK5RKwJhAN4w9kjkXS+MSZjX0kIMsBIBVkhh
|
||||
C+aREjJqa9ir7/Ey7RvmLXdYuCxtGLRXp7/R8+rjcK49Tx6O+IRJZe042mfhbq3C
|
||||
EhS1Tr86f4xXix9EXlDhs9bSxrOgcAN9Dv/opQJhAK7eBcPaav0rVfYh/8emqQHS
|
||||
3fJ9Pu6WnzbEksWTFS2ff9KDGCx9YspIFJ5TF/oXDAaumGZdZrlgirm6O1kr8tGY
|
||||
F97i04PZl1+bWAaWQH+1TUNI43m2WFUPE7coG2tb8QJgcddDg9VlXliZqgcETZfJ
|
||||
kJmYETxrcSn3ao6v116N8yxhEgUgjkmsCTiFgx36iDVnXwK6PIt+sIu8MC7eYNa3
|
||||
berrv/M21K0LRn20IWRxvUobG070weHCAgkko7fTWgr2
|
||||
-----END RSA PRIVATE KEY-----
|
||||
-----BEGIN PRIVATE KEY-----
|
||||
MIIG/gIBADANBgkqhkiG9w0BAQEFAASCBugwggbkAgEAAoIBgQDiNGqbEmyFI9QF
|
||||
EvWcU36irjzp1W+VMuMHGD5PDYy5ib1QIrUcUQPvWydV4er/6gnpv6VQ+dfOeVlr
|
||||
Acu73kdh+N0u5UgjIY9CJnoN12eEGjTrVFlHoA2Ur/TMbN3DW20Nbyi5LUJ8KrGl
|
||||
Yg8tPbLqGvfJsIYTspBEzgQcJg5ZTD3YA2ZESrbZe2sOunri0j1myv+EoTqB4nPb
|
||||
ShHx8i11IJpUoBEoHoSyMQgEgYJqbmqCHaTGJWNxHUUhI5MmTPEzyrG6T0B3v5Pb
|
||||
y1eFOyAU+I4SCs0fqHPg4DbPlNTe/MEBm2LQAVrUFjcFx+Cq75oOa9sVp6xvBmYN
|
||||
nMiwGgLJYjN7l0lhRQEtao6tEGQUYbmpKoLQJMsKs6bjs6HK5TXMzQUfHATirmjE
|
||||
C1Fcb/eKJ27HNiKS+uw2g9Tpu/af2qKl3ePNUioPbMYtgGhu5csD22heGeilNVtN
|
||||
8D47kU0SveXjokV476CecW0SZnN9rVrvd0IqtnU9fMoAQyZE6ScCAwEAAQKCAYAk
|
||||
0//fS3qbmp+0S8ftMbLWbaPBNly6X9SSnSHX4Q7eTkyiNWRjPdV0LNUUqHmIPORs
|
||||
SCV0L5kxJpSmVV6EMcZRbyEjt3StM5ONY5JPmphh65peDheTD73mTVd/yOG6IrJ4
|
||||
k3Z/35yJdrIBiRuLdBYjA00Aa1sI7fOLIDePFasUYtNWzgbia3+lnPBrL3U+ZJhW
|
||||
mgpL36wU5XeTZlXRnGpGPY6i5ISmkYFtOYpioWtIRL3WfVkMYZ31FpzgrlgQzknQ
|
||||
lrKN2g7/3q0uLlbasgCsAK50hL2f2xxzsALDCGFjDJbwdIZKfdoxRbgS0L7q7gj0
|
||||
SUK4fc1obR5qHc2lTuCSzPpionq022ElC0DChupiosyXN4GxNZ2Dwoln4Y5s2YXo
|
||||
+VTtyYbVEib15WbhHorvfg0QUO00Nwqu+LVTVUXueNre2n507fSiOhCIpbPUWDGz
|
||||
RoeRFEP0T9+mzQgXr56TAiYunIat1qVxXrwaSWSXEfInGUTkdRUC4rctv7KJ1nEC
|
||||
gcEA8jDTh1OLBG3/JkQxQNOoqFUFssPlJ+z3LcyaNT6bM5lH5Vwn3sGOFWOMLILD
|
||||
f/qbGG/1VPVfoCEY1NEkYsocOMtkLIJrIdtD5DOnWz1JJE7Zh2AoWWfIfXd9v5sh
|
||||
m1fB3SVa6D9JtGoDnKttMl25Tqf6YehVo35Axxar74k3kC/vuZrp/81iZscdRsyK
|
||||
kQh9fPXl4Oqw2cUYdx3L8UprLS4JguvR0zXvbukJ75DjLZELvjnxBbA1vdtyQz58
|
||||
2uk1AoHBAO8aP5h08kwTIJCXS6uyAJ0F8F/30srAtchSpzsC3YEEs/Z+43D7W1RR
|
||||
Obw4KhVjjmFeh83U8pdEuUEjv3ua52+uoUCqTywe+o180owiWsTDSXVtDHiUD7bu
|
||||
x+nRnpk3flZD28GHKLdWMmJvd8DzMgsa9fJIucMYT7xQHzxCW+4nhhBckX9LEH7i
|
||||
Jo6MaVuh8b6NuZXOBgU3cp20GTZ3SwRNkKOigctQVZT4A1Vf4ioLrVyhv/LVLBC+
|
||||
UvoIu82wawKBwQDakMXU8sgaj0ocNp5caqdigphJ5BACIBBR/LuOIZnezw3bJ3ez
|
||||
x+l51ATEhp33+SnOu/sjWO2bjULjjHrRzKP7fVJB+NDGFSMH5rW52W0Qnzggu96u
|
||||
EMMWt6d8K3wAvQnvka6gubzCXIo18V7yfTKmkWGcyhe/HElJYmR4H9VNAnXNgsh6
|
||||
Wdfb+QWqxxymFotpImD6wdIoNX8GwJU0hHyEoW9j/320ppAV/6k/0fmzPZrjaVbi
|
||||
U0uss0ZC+TmkNaECgcB9L6gGYYyOyiDts1k6LvtlOzvMc0uZPmau2J+YJPrmVxkG
|
||||
QQ9CE0iRD+oDowBdrH9aeYzu9sSA8Mlx0o6p38O21J625bSILDwQoj72gfI2PO0U
|
||||
HyE9bIABzmk7AbZhEA4Eiojffa2St/2vTh9MFcioydfln7Aq9mqg9O41taS+P1FQ
|
||||
9bZ0CFA9rphzYA61nEee9kMprPG3/3zyFt5whuru+NF261m7onb8hRHxvD8EtpJx
|
||||
AnsmX/gvWAbHxJTXr7sCgcEAp6QAysy0/sgRYvzBkqv05kz4xBqy2a4ZKjnMLEWY
|
||||
7MicZiQrkSsEjMNDy20rjXfZbhDJWGVjBOZ1QsYehKhGAIoORXID9B3aZ32m//VU
|
||||
IUxkLcrIPLPmfdzZvlRPnQc/TAZNe41BGBa4WlDwTFE9TdpVtTzjW1ac5yBN7sa+
|
||||
V7YbBSiOhP+NuqQFQM01aaZCmOetcj70B4SwJVzswhITS0O+7ZAvicGJiQKTUvUY
|
||||
ijWm+Luu3QYDc2HBMwUAmHT5
|
||||
-----END PRIVATE KEY-----
|
||||
|
||||
+23
-12
@@ -1,14 +1,25 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIICFzCCAUACCQDO660L5y5LGDANBgkqhkiG9w0BAQUFADAQMQ4wDAYDVQQDEwVw
|
||||
ZXRhbDAeFw0xMDA5MzAxMzQzMDFaFw0zMDA2MTcxMzQzMDFaMBAxDjAMBgNVBAMT
|
||||
BXBldGFsMIHfMA0GCSqGSIb3DQEBAQUAA4HNADCByQKBwQC1xQ/Kca6zszZbcCtd
|
||||
OTIH2Uy2gOy/DfabMUU7TmNPm0dVE0NJRuN+Rm304SonpwghfP2/ULZNnuDgpG03
|
||||
/32yI7k/VzG6iA4hiF7tT/KAAWC/+2l1QCsawCV2bSrFK0VhcZr7ALqXd8vkDaQ8
|
||||
67K029ypjOQtAJ85qdO3mERy7TGtdUcuO6hLeVet419YeQ2F8cfNxn63d7bOzNGL
|
||||
PW5xwaCd3UcgD+Ib0k4xfFvbinvPQUeUJ/i4YDWexFYSL+ECAwEAATANBgkqhkiG
|
||||
9w0BAQUFAAOBwQBBkX9KDP2RXbg+xPmdJ4P6CwvA5x1LZwC++ydVx4NlvT0pWicD
|
||||
ZUnXjcWAJlkeOuUBAqFG7WHTrXpUUAjmdqFVq2yFjteUYBdrFz0RDB2jM9feeKYO
|
||||
mTgxdZyT9a6humxCxt5VfgT02axLjm/2AqCyFPMbf4PASoJDln01AEuZLZ8Xl2gV
|
||||
bYHMnHTGoD1Hu6FNEzRgkMC6XT8X3YjHvzQhpc/qL5wEfEsinQGdX4twsuWbf8xd
|
||||
q7miNnkO8vd0maw=
|
||||
MIIERDCCAqygAwIBAgIUY5FZe4tAZd0ITNbceavVGLvEe2QwDQYJKoZIhvcNAQEL
|
||||
BQAwEDEOMAwGA1UEAwwFcGV0YWwwHhcNMjYwNzI0MDkwNTMyWhcNNDYwNDEwMDkw
|
||||
NTMyWjAQMQ4wDAYDVQQDDAVwZXRhbDCCAaIwDQYJKoZIhvcNAQEBBQADggGPADCC
|
||||
AYoCggGBAOI0apsSbIUj1AUS9ZxTfqKuPOnVb5Uy4wcYPk8NjLmJvVAitRxRA+9b
|
||||
J1Xh6v/qCem/pVD51855WWsBy7veR2H43S7lSCMhj0Imeg3XZ4QaNOtUWUegDZSv
|
||||
9Mxs3cNbbQ1vKLktQnwqsaViDy09suoa98mwhhOykETOBBwmDllMPdgDZkRKttl7
|
||||
aw66euLSPWbK/4ShOoHic9tKEfHyLXUgmlSgESgehLIxCASBgmpuaoIdpMYlY3Ed
|
||||
RSEjkyZM8TPKsbpPQHe/k9vLV4U7IBT4jhIKzR+oc+DgNs+U1N78wQGbYtABWtQW
|
||||
NwXH4Krvmg5r2xWnrG8GZg2cyLAaAsliM3uXSWFFAS1qjq0QZBRhuakqgtAkywqz
|
||||
puOzocrlNczNBR8cBOKuaMQLUVxv94onbsc2IpL67DaD1Om79p/aoqXd481SKg9s
|
||||
xi2AaG7lywPbaF4Z6KU1W03wPjuRTRK95eOiRXjvoJ5xbRJmc32tWu93Qiq2dT18
|
||||
ygBDJkTpJwIDAQABo4GVMIGSMB0GA1UdDgQWBBSLQ6cvFrU2JiedggRXjiUemV3h
|
||||
QzBLBgNVHSMERDBCgBSLQ6cvFrU2JiedggRXjiUemV3hQ6EUpBIwEDEOMAwGA1UE
|
||||
AwwFcGV0YWyCFGORWXuLQGXdCEzW3Hmr1Ri7xHtkMBIGA1UdEwEB/wQIMAYBAf8C
|
||||
AQAwEAYDVR0RBAkwB4IFcGV0YWwwDQYJKoZIhvcNAQELBQADggGBANj5PXClrk76
|
||||
UddT6aniB/VbErfu1MwfyYSGhE4y5VVJVyD+wHYECswdm2IIo/v/4I+4KWgAcGPk
|
||||
u+j1B2iXN8sQTe500+KMSRFfaxdbwlX42+oDKwRoz8pwMzETyZYQA4PAE5j2rnjb
|
||||
n9USomWzvwavo7GRE6VauBcSAekrNFDjPw43tElmr2TTz4lUFXlvBlQvcbloJ4OU
|
||||
60ek8d1erlsLXzAtf4kCFH1aiII0g0fA448gnIOIgT9LiV88smKNDPVqusw9TBd5
|
||||
/f1R8ETy7jcIJ9TU34dy6S39s4aUjWUAZMV1TIH3wJPDsE6+1yD5OC5b50akIwpJ
|
||||
jO9naDRvgaHIWxJRcREXd+H7IlybL+l+Qq4L4RX583cdL/rZEWdnESgbDq7EkEPn
|
||||
ZbpjdM4oNGUlXsrZw0/GFgzYlN2MBFiLht6y2iBbhFxPb2SM3Xx/M5YnsNLym+I/
|
||||
m9mck/aeeSEyJ2uIfFfVndfPfqmKxwvoPu0OCv/ppsi+xTvhE6B/UQ==
|
||||
-----END CERTIFICATE-----
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user