Compare commits

..
Author SHA1 Message Date
Willem Toorop c834ee635c Fix function signature for compiling test 2025-11-03 11:15:11 +01:00
Willem Toorop 7977ef28f5 distribute can send out responses tsig signed 2025-11-01 14:32:09 +01:00
Willem Toorop c86c267b8b Forgot to include util/allow_response_list.[ch] 2025-11-01 13:12:35 +01:00
Willem Toorop 3963af8d0b configurable ranges and tsig to allow responses
Configurable with the "allow-response:" option in the "server:" section.
Usage:
	allow-response: <IP netblock> <tsig key-name | NOKEY | BLOCKED>
2025-11-01 12:52:48 +01:00
Willem Toorop 3d6a4c7d6e Const string for tsig lookups 2025-10-31 15:45:34 +01:00
Willem Toorop 2217c9b96e Merge branch 'master' into update-with-branches/poisonlicious 2025-10-30 09:48:57 +01:00
Willem Toorop 6592c73d56 Merge branch 'xfr-tsig' into update-with-branches/poisonlicious 2025-10-30 09:45:11 +01:00
W.C.A. Wijngaards 8687d69131 Merge branch 'master' into xfr-tsig 2025-10-01 15:52:40 +02:00
W.C.A. Wijngaards c622a71a28 - xfr-tsig, flip buffer after tsig_sign_reply, but not for error_encode. 2025-10-01 15:52:15 +02:00
W.C.A. Wijngaards ecfc6a70ce - xfr-tsig, note tsig-key support for fast_reload. 2025-09-12 16:38:09 +02:00
W.C.A. Wijngaards a23c5347a7 - xfr-tsig, unit test shows zonefile that is created. 2025-09-12 15:43:45 +02:00
W.C.A. Wijngaards 1ae8be6847 - xfr-tsig, fast reload support for tsig keys. 2025-09-12 15:38:39 +02:00
W.C.A. Wijngaards f0268d3e83 - xfr-tsig, log TSIG key name with zone and notify information. Clear tsig
data before making a new one.
2025-09-12 14:58:49 +02:00
W.C.A. Wijngaards c904a3d375 - xfr-tsig, remove rpl unit test. 2025-09-12 11:23:29 +02:00
W.C.A. Wijngaards b451cc4af7 - xfr-tsig, add tdir test that performs tsig signed zone transfer. 2025-09-12 10:40:23 +02:00
W.C.A. Wijngaards f9713f9fe5 Merge branch 'master' into xfr-tsig 2025-09-12 09:27:23 +02:00
W.C.A. Wijngaards dfac72edfc - xfr-tsig, unit test use to make tsig for rpl. 2025-09-11 17:05:58 +02:00
W.C.A. Wijngaards 64e102aacb - xfr-tsig, fix notify tsig answer, fix parse edns allows TSIG,
unit test for auth zone with notify with tsig and notify answer with tsig.
2025-09-11 16:21:38 +02:00
W.C.A. Wijngaards bebd6c0f96 - xfr-tsig, use tsig_parse_verify_reply_xfr for zone transfers with TSIG. 2025-09-10 15:45:37 +02:00
W.C.A. Wijngaards 63aa70ab32 - xfr-tsig, unit test for tsig sign every couple packets, and verify that. 2025-09-10 15:26:57 +02:00
W.C.A. Wijngaards 7b59014ba3 - xfr-tsig, unit test with another trace of tsig every couple packets. 2025-09-09 16:24:55 +02:00
W.C.A. Wijngaards 156846e6c4 - xfr-tsig, unit test to verify tsig every couple packets. 2025-09-09 15:50:14 +02:00
W.C.A. Wijngaards aea2a821b9 - xfr-tsig, unit test for tsig-verify-reply-xfr, with output that works
with dig and NSD.
2025-09-09 15:40:51 +02:00
W.C.A. Wijngaards cacdfee755 Merge branch 'master' into xfr-tsig 2025-09-09 14:38:03 +02:00
W.C.A. Wijngaards e3c1981a6a - xfr-tsig, fix algorithm name write in xfr reply tsig and unit test
that works with output that works with dig and NSD.
2025-09-09 14:36:33 +02:00
W.C.A. Wijngaards e2efd17007 - xfr-tsig, unit test tsig-sign-reply-xfr implementation. 2025-09-05 16:45:15 +02:00
W.C.A. Wijngaards 4a2dc1df48 Merge branch 'master' into xfr-tsig 2025-09-05 15:00:31 +02:00
W.C.A. Wijngaards 5c79fd9a0b - xfr-tsig, tsig_parse_verify_reply_xfr and tsig_sign_reply_xfr. 2025-09-05 14:55:36 +02:00
W.C.A. Wijngaards 4a3a4f474f Merge branch 'master' into xfr-tsig 2025-08-27 16:30:03 +02:00
W.C.A. Wijngaards 708581579c - xfr-tsig, add test case with AXFR packet with TSIG. 2025-08-27 15:52:08 +02:00
W.C.A. Wijngaards af1d430759 - xfr-tsig, log rcode for received notifies. 2025-08-20 15:55:29 +02:00
W.C.A. Wijngaards da72734240 - xfr-tsig, tsig_get_mem function. 2025-08-19 16:46:12 +02:00
W.C.A. Wijngaards 54175a4180 Merge branch 'master' into xfr-tsig 2025-08-19 15:27:43 +02:00
W.C.A. Wijngaards 888d5ce9f9 - xfr-tsig, TSIG for SOA probe, notify, and on xfr first packet. 2025-08-19 15:27:16 +02:00
W.C.A. Wijngaards b1bb4a4592 - xfr-tsig, check that tsig keys exist at startup and in unbound-checkconf. 2025-07-31 17:02:55 +02:00
W.C.A. Wijngaards 3b88577dd1 Merge branch 'master' into xfr-tsig 2025-07-31 15:59:25 +02:00
W.C.A. Wijngaards 6634b8bcc5 - xfr-tsig, primary-tsig: addr tsig and allow-notify-tsig: addr tsig. 2025-07-31 14:43:43 +02:00
W.C.A. Wijngaards 3d7dfe2f36 - xfr-tsig, unit test for tsig_verify_reply for failed tsig. 2025-07-23 16:35:25 +02:00
W.C.A. Wijngaards baee7885bd Merge branch 'master' into xfr-tsig 2025-07-23 16:23:58 +02:00
W.C.A. Wijngaards e55b3a2a4c - xfr-tsig, unit test for tsig_verify_reply. 2025-07-23 16:16:41 +02:00
Willem Toorop b5a2de1292 allow-response: config option 2025-07-20 13:30:29 +02:00
Willem Toorop 5ed0840dc2 Poisonlicious PoC with new tsig code 2025-07-19 15:19:00 +02:00
Willem Toorop 9bbb34fc38 Link tsig.lo only once 2025-07-19 15:11:15 +02:00
Willem Toorop 433bb1c7bc Merge branch 'updated-with-master/xfr-tsig' into hackathon/poisonlicious-new-tsig-code 2025-07-19 15:02:30 +02:00
Willem Toorop f3b960e72b Merge branch 'master' into xfr-tsig-update 2025-07-19 14:42:44 +02:00
Willem Toorop 5bd31c9569 A typo and a reorder (without impact) 2025-07-19 14:35:38 +02:00
Willem Toorop 4f245e0e5b Merge branch 'master' into hackathon/poisonlicious-update 2025-07-19 14:23:50 +02:00
W.C.A. Wijngaards e4069e5619 Merge branch 'master' into xfr-tsig 2025-07-11 15:27:40 +02:00
W.C.A. Wijngaards a3ec9a974f - xfr-tsig, member comments for struct tsig_calc_state_crypto. 2025-07-11 15:18:11 +02:00
W.C.A. Wijngaards 479b954118 - xfr-tsig, implemented tsig_calc_state_crypto. 2025-07-11 10:08:48 +02:00
W.C.A. Wijngaards 0955238cd3 - xfr-tsig, tsig_verify_reply function. 2025-06-27 14:26:15 +02:00
W.C.A. Wijngaards 57dd6a971d - xfr-tsig, extra unit tests for tsig_sign_reply. 2025-06-27 11:29:41 +02:00
W.C.A. Wijngaards 6a831e3063 - xfr-tsig, more explanation in testcode/unittsig.c. 2025-06-27 11:03:25 +02:00
W.C.A. Wijngaards 3807bf00da - xfr-tsig, unit test for tsig_sign_reply. 2025-06-27 10:59:36 +02:00
W.C.A. Wijngaards 9022381be4 - xfr-tsig, more explanation in testcode/unittsig.c. 2025-06-27 09:29:57 +02:00
W.C.A. Wijngaards ca147a147d - xfr-tsig, unit test for tsig_sign_shared and tsig_verify_shared. 2025-06-27 09:24:51 +02:00
W.C.A. Wijngaards 5147e5aee9 - xfr-tsig, tsig_sign_shared function. 2025-06-27 08:52:32 +02:00
W.C.A. Wijngaards 6466513cc5 - xfr-tsig, unit test argument parse code. 2025-06-26 16:59:44 +02:00
W.C.A. Wijngaards 7a1a615fd3 - xfr-tsig, tsig_verify_shared function. 2025-06-26 15:11:25 +02:00
W.C.A. Wijngaards 81d774fb11 - xfr-tsig, tsig_sign_reply function. 2025-06-26 12:41:10 +02:00
W.C.A. Wijngaards 0254317e0d - xfr-tsig, fix unit test parse of tsig error code. 2025-06-25 14:52:16 +02:00
W.C.A. Wijngaards dc37849546 - xfr-tsig, test cases for BADTRUNC and not parseable. 2025-06-25 14:19:22 +02:00
W.C.A. Wijngaards 766666139b Merge branch 'master' into xfr-tsig 2025-06-25 14:05:06 +02:00
W.C.A. Wijngaards 86e78fcacc xfr-tsig, remove debug 2025-06-25 14:03:52 +02:00
W.C.A. Wijngaards 47a2d71fd3 - xfr-tsig, unit test cases for tsig errors. 2025-06-25 14:03:12 +02:00
W.C.A. Wijngaards 0719ef21fa - xfr-tsig, unit test for tsig_verify_query. 2025-06-25 12:06:15 +02:00
W.C.A. Wijngaards 6d5f22b56d - xfr-tsig, fix tsig_verify_query. 2025-06-25 10:21:42 +02:00
W.C.A. Wijngaards b5beb800c8 - xfr-tsig, tsig_find_rr function. 2025-06-24 16:51:41 +02:00
W.C.A. Wijngaards fe63b25441 - xfr-tsig, parse and verify query tsig. 2025-06-24 16:31:18 +02:00
W.C.A. Wijngaards 0afbb68b40 - xfr-tsig, other data content matches the other len when written. 2025-06-20 16:57:24 +02:00
W.C.A. Wijngaards 4562cd372c - xfr-tsig, whitespace. 2025-06-20 14:43:19 +02:00
W.C.A. Wijngaards 418ef3765d Merge branch 'master' into xfr-tsig 2025-06-20 14:33:02 +02:00
W.C.A. Wijngaards 29c8b3edba - xfr-tsig, unit tests for md5, sha1, sha224, sha256, sha384 and sha512. 2025-06-20 14:31:44 +02:00
W.C.A. Wijngaards 5214912555 Merge branch 'master' into xfr-tsig 2025-06-20 12:14:13 +02:00
W.C.A. Wijngaards f2c609b9a5 - xfr-tsig, unit test for tsig_sign_query. 2025-06-20 12:13:51 +02:00
W.C.A. Wijngaards aa22fd936e - xfr-tsig, test buffer size. 2025-06-18 17:01:35 +02:00
W.C.A. Wijngaards 4bbb74da39 - xfr-tsig, tsig test. 2025-06-18 16:41:10 +02:00
W.C.A. Wijngaards dd4ee42eb6 - xfr-tsig, tsig_sign_query. 2025-06-18 15:00:18 +02:00
W.C.A. Wijngaards 8b95785b8c - xfr-tsig, tsig functions. 2025-06-18 12:18:20 +02:00
W.C.A. Wijngaards bb4ddab77a Merge branch 'master' into xfr-tsig 2025-06-17 16:55:18 +02:00
W.C.A. Wijngaards 69354298fc - xfr-tsig, tsig_create and tsig_delete. 2025-06-17 16:54:52 +02:00
W.C.A. Wijngaards bbcf5d122a Merge branch 'master' into xfr-tsig 2025-06-16 17:00:12 +02:00
W.C.A. Wijngaards 497161f72f - xfr-tsig, tsig_verify return failure comment improved. 2025-06-16 16:59:53 +02:00
W.C.A. Wijngaards 31e8118b76 - xfr-tsig, man page and example config. 2025-06-13 16:32:36 +02:00
W.C.A. Wijngaards 8811bd4844 - xfr-tsig, tsig-key, with name, algorithm and secret options. 2025-06-13 12:12:49 +02:00
W.C.A. Wijngaards 0f02479dea - xfr-tsig, fix algorithm lookup. 2025-06-13 10:17:47 +02:00
W.C.A. Wijngaards 364edccebc - xfr-tsig, algorithm table. 2025-06-13 10:15:41 +02:00
W.C.A. Wijngaards 3d9242b3d3 - xfr-tsig, key table. 2025-06-12 16:05:10 +02:00
W.C.A. Wijngaards 3f378c962f - xfr-tsig, check rdata length in tsig verify. 2025-06-12 14:34:56 +02:00
W.C.A. Wijngaards 4ca37bcadf Merge branch 'master' into xfr-tsig 2025-06-12 12:17:13 +02:00
W.C.A. Wijngaards 19492da154 - xfr-tsig, check buffer remaining in tsig verify. 2025-06-12 11:50:11 +02:00
W.C.A. Wijngaards 182e580fe2 - xfr-tsig, fix warning in compile of declaration. 2025-06-12 09:57:23 +02:00
W.C.A. Wijngaards eefb417c09 - xfr-tsig, const for dname compare and fix warnings in compile. 2025-06-12 09:53:56 +02:00
W.C.A. Wijngaards 4fd0d84e66 - xfr-tsig, update header comment. 2025-06-12 09:49:20 +02:00
W.C.A. Wijngaards ea0973002f - xfr-tsig, constant time memcmp is used. 2025-06-12 09:34:07 +02:00
W.C.A. Wijngaards 8fcc4c98b6 Merge branch 'master' into xfr-tsig 2025-06-12 09:29:28 +02:00
W.C.A. Wijngaards 7edc1e0fc4 - xfr-tsig, import the tsig verify code from hackathon/poisonlicious branch. 2025-06-12 09:25:54 +02:00
Willem Toorop 3674e4813c A bit better TSIG handling 2025-03-25 16:46:42 +01:00
Willem Toorop 5d11af34dc Verification of incoming responses with TSIG
For now with a hardcoded TSIG key
2025-03-17 09:25:13 +01:00
Willem Toorop e29ee129a3 Fix CI 2025-03-16 10:17:53 +01:00
Willem Toorop 86526c75a3 Send responses just before they enter the cache
Configured with the `distribute:` option in the `server:` section in the config.
2025-03-16 09:21:11 +01:00
Willem Toorop d9d6dd31dc Store responses received on listen interface in cache 2025-03-15 16:22:29 +01:00
W.C.A. Wijngaards e6573fc337 - xfr-tsig, create util/tsig.c and util/tsig.h. 2023-04-14 14:05:15 +02:00
305 changed files with 11361 additions and 26093 deletions
+6 -8
View File
@@ -173,7 +173,7 @@ jobs:
cross_platform_config: "--enable-debug --disable-flto --with-libevent --disable-static"
steps:
- uses: actions/checkout@v7
- uses: actions/checkout@v4
with:
submodules: false
persist-credentials: false
@@ -189,8 +189,6 @@ jobs:
cd ..
export prepath=`pwd`
echo prepath=${prepath}
# parralel build option
export MINJ="-j4"
echo "choco install winflexbison3"
choco install winflexbison3
echo 'LEX="win_flex"'
@@ -213,8 +211,8 @@ jobs:
C:/msys64/usr/bin/perl ./Configure no-shared no-asm -DOPENSSL_NO_CAPIENG mingw64 --prefix="$prepath/openssl" PERL="C:/msys64/usr/bin/perl"
# make the libs only, build faster
echo "make build_libs"
#make $MINJ
make $MINJ build_libs
#make
make build_libs
mv Makefile Makefile.orig
# fixup \\ in the installtop to /.
echo "fixup INSTALLTOP"
@@ -246,7 +244,7 @@ jobs:
mv xmlwf/Makefile xmlwf/Makefile.orig
sed -e 's/SHELL/SHELLZZ/g' < xmlwf/Makefile.orig > xmlwf/Makefile
echo "make"
make $MINJ
make
echo "make install"
make install
cd ..
@@ -254,7 +252,7 @@ jobs:
cd unbound
echo "./configure --enable-debug --enable-static-exe --disable-flto \"--with-ssl=$prepath/openssl\" --with-libexpat=\"$prepath/expat\" --disable-shared"
./configure --enable-debug --enable-static-exe --disable-flto "--with-ssl=$prepath/openssl" --with-libexpat="$prepath/expat" --disable-shared
make $MINJ
make
# specific test output
#make testbound.exe; ./testbound.exe -s
#make testbound; ./testbound.exe -p testdata/acl.rpl -o -vvvv
@@ -349,7 +347,7 @@ jobs:
echo "::endgroup::"
- name: cross-platform-action on ${{ matrix.cross_platform_os }} ${{ matrix.cross_platform_version }}
if: ${{ matrix.with_cross_platform_action == 'yes' }}
uses: cross-platform-actions/action@v1.0.0
uses: cross-platform-actions/action@v0.25.0
env:
CROSS_PLATFORM_OS: ${{ matrix.cross_platform_os }}
with:
+1 -1
View File
@@ -12,7 +12,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- uses: actions/checkout@v4
with:
persist-credentials: false
- name: configure
+407 -556
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -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. Dont hesitate to
[create an issue on Github](https://github.com/NLnetLabs/unbound/issues/new)
or post a message on our [community forum](https://community.nlnetlabs.nl/).
or post a message on the [Unbound mailing list](https://lists.nlnetlabs.nl/mailman/listinfo/unbound-users).
You can learn more about Unbound by reading our
[documentation](https://unbound.docs.nlnetlabs.nl/).
Vendored
+202 -146
View File
@@ -1,6 +1,6 @@
# generated automatically by aclocal 1.16.2 -*- Autoconf -*-
# generated automatically by aclocal 1.16.5 -*- Autoconf -*-
# Copyright (C) 1996-2020 Free Software Foundation, Inc.
# Copyright (C) 1996-2021 Free Software Foundation, Inc.
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@@ -14,7 +14,8 @@
m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])])
# libtool.m4 - Configure libtool for the host system. -*-Autoconf-*-
#
# Copyright (C) 1996-2001, 2003-2015 Free Software Foundation, Inc.
# Copyright (C) 1996-2001, 2003-2019, 2021-2022 Free Software
# Foundation, Inc.
# Written by Gordon Matzigkeit, 1996
#
# This file is free software; the Free Software Foundation gives
@@ -45,7 +46,7 @@ m4_define([_LT_COPYING], [dnl
# along with this program. If not, see <http://www.gnu.org/licenses/>.
])
# serial 58 LT_INIT
# serial 59 LT_INIT
# LT_PREREQ(VERSION)
@@ -195,6 +196,7 @@ m4_require([_LT_FILEUTILS_DEFAULTS])dnl
m4_require([_LT_CHECK_SHELL_FEATURES])dnl
m4_require([_LT_PATH_CONVERSION_FUNCTIONS])dnl
m4_require([_LT_CMD_RELOAD])dnl
m4_require([_LT_DECL_FILECMD])dnl
m4_require([_LT_CHECK_MAGIC_METHOD])dnl
m4_require([_LT_CHECK_SHAREDLIB_FROM_LINKLIB])dnl
m4_require([_LT_CMD_OLD_ARCHIVE])dnl
@@ -233,8 +235,8 @@ esac
ofile=libtool
can_build_shared=yes
# All known linkers require a '.a' archive for static linking (except MSVC,
# which needs '.lib').
# All known linkers require a '.a' archive for static linking (except MSVC and
# ICC, which need '.lib').
libext=a
with_gnu_ld=$lt_cv_prog_gnu_ld
@@ -736,7 +738,6 @@ _LT_CONFIG_SAVE_COMMANDS([
cat <<_LT_EOF >> "$cfgfile"
#! $SHELL
# Generated automatically by $as_me ($PACKAGE) $VERSION
# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
# NOTE: Changes made to this file will be lost: look at ltmain.sh.
# Provide generalized library-building support services.
@@ -786,7 +787,7 @@ _LT_EOF
# if finds mixed CR/LF and LF-only lines. Since sed operates in
# text mode, it properly converts lines to CR/LF. This bash problem
# is reportedly fixed, but why not run on old versions too?
sed '$q' "$ltmain" >> "$cfgfile" \
$SED '$q' "$ltmain" >> "$cfgfile" \
|| (rm -f "$cfgfile"; exit 1)
mv -f "$cfgfile" "$ofile" ||
@@ -1048,8 +1049,8 @@ int forced_loaded() { return 2;}
_LT_EOF
echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&AS_MESSAGE_LOG_FD
$LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&AS_MESSAGE_LOG_FD
echo "$AR cru libconftest.a conftest.o" >&AS_MESSAGE_LOG_FD
$AR cru libconftest.a conftest.o 2>&AS_MESSAGE_LOG_FD
echo "$AR $AR_FLAGS libconftest.a conftest.o" >&AS_MESSAGE_LOG_FD
$AR $AR_FLAGS libconftest.a conftest.o 2>&AS_MESSAGE_LOG_FD
echo "$RANLIB libconftest.a" >&AS_MESSAGE_LOG_FD
$RANLIB libconftest.a 2>&AS_MESSAGE_LOG_FD
cat > conftest.c << _LT_EOF
@@ -1073,17 +1074,12 @@ _LT_EOF
_lt_dar_allow_undefined='$wl-undefined ${wl}suppress' ;;
darwin1.*)
_lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;;
darwin*) # darwin 5.x on
# if running on 10.5 or later, the deployment target defaults
# to the OS version, if on x86, and 10.4, the deployment
# target defaults to 10.4. Don't you love it?
case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in
10.0,*86*-darwin8*|10.0,*-darwin[[91]]*)
_lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;;
10.[[012]][[,.]]*)
_lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;;
10.*)
_lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;;
darwin*)
case $MACOSX_DEPLOYMENT_TARGET,$host in
10.[[012]],*|,*powerpc*-darwin[[5-8]]*)
_lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;;
*)
_lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;;
esac
;;
esac
@@ -1132,12 +1128,12 @@ m4_defun([_LT_DARWIN_LINKER_FEATURES],
output_verbose_link_cmd=func_echo_all
_LT_TAGVAR(archive_cmds, $1)="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dsymutil"
_LT_TAGVAR(module_cmds, $1)="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dsymutil"
_LT_TAGVAR(archive_expsym_cmds, $1)="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dar_export_syms$_lt_dsymutil"
_LT_TAGVAR(module_expsym_cmds, $1)="sed -e 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dar_export_syms$_lt_dsymutil"
_LT_TAGVAR(archive_expsym_cmds, $1)="$SED 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dar_export_syms$_lt_dsymutil"
_LT_TAGVAR(module_expsym_cmds, $1)="$SED -e 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dar_export_syms$_lt_dsymutil"
m4_if([$1], [CXX],
[ if test yes != "$lt_cv_apple_cc_single_mod"; then
_LT_TAGVAR(archive_cmds, $1)="\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dsymutil"
_LT_TAGVAR(archive_expsym_cmds, $1)="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dar_export_syms$_lt_dsymutil"
_LT_TAGVAR(archive_expsym_cmds, $1)="$SED 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dar_export_syms$_lt_dsymutil"
fi
],[])
else
@@ -1251,7 +1247,8 @@ _LT_DECL([], [ECHO], [1], [An echo program that protects backslashes])
# _LT_WITH_SYSROOT
# ----------------
AC_DEFUN([_LT_WITH_SYSROOT],
[AC_MSG_CHECKING([for sysroot])
[m4_require([_LT_DECL_SED])dnl
AC_MSG_CHECKING([for sysroot])
AC_ARG_WITH([sysroot],
[AS_HELP_STRING([--with-sysroot@<:@=DIR@:>@],
[Search for dependent libraries within DIR (or the compiler's sysroot
@@ -1268,7 +1265,7 @@ case $with_sysroot in #(
fi
;; #(
/*)
lt_sysroot=`echo "$with_sysroot" | sed -e "$sed_quote_subst"`
lt_sysroot=`echo "$with_sysroot" | $SED -e "$sed_quote_subst"`
;; #(
no|'')
;; #(
@@ -1298,7 +1295,7 @@ ia64-*-hpux*)
# options accordingly.
echo 'int i;' > conftest.$ac_ext
if AC_TRY_EVAL(ac_compile); then
case `/usr/bin/file conftest.$ac_objext` in
case `$FILECMD conftest.$ac_objext` in
*ELF-32*)
HPUX_IA64_MODE=32
;;
@@ -1315,7 +1312,7 @@ ia64-*-hpux*)
echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext
if AC_TRY_EVAL(ac_compile); then
if test yes = "$lt_cv_prog_gnu_ld"; then
case `/usr/bin/file conftest.$ac_objext` in
case `$FILECMD conftest.$ac_objext` in
*32-bit*)
LD="${LD-ld} -melf32bsmip"
;;
@@ -1327,7 +1324,7 @@ ia64-*-hpux*)
;;
esac
else
case `/usr/bin/file conftest.$ac_objext` in
case `$FILECMD conftest.$ac_objext` in
*32-bit*)
LD="${LD-ld} -32"
;;
@@ -1349,7 +1346,7 @@ mips64*-*linux*)
echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext
if AC_TRY_EVAL(ac_compile); then
emul=elf
case `/usr/bin/file conftest.$ac_objext` in
case `$FILECMD conftest.$ac_objext` in
*32-bit*)
emul="${emul}32"
;;
@@ -1357,7 +1354,7 @@ mips64*-*linux*)
emul="${emul}64"
;;
esac
case `/usr/bin/file conftest.$ac_objext` in
case `$FILECMD conftest.$ac_objext` in
*MSB*)
emul="${emul}btsmip"
;;
@@ -1365,7 +1362,7 @@ mips64*-*linux*)
emul="${emul}ltsmip"
;;
esac
case `/usr/bin/file conftest.$ac_objext` in
case `$FILECMD conftest.$ac_objext` in
*N32*)
emul="${emul}n32"
;;
@@ -1385,14 +1382,14 @@ s390*-*linux*|s390*-*tpf*|sparc*-*linux*)
# not appear in the list.
echo 'int i;' > conftest.$ac_ext
if AC_TRY_EVAL(ac_compile); then
case `/usr/bin/file conftest.o` in
case `$FILECMD conftest.o` in
*32-bit*)
case $host in
x86_64-*kfreebsd*-gnu)
LD="${LD-ld} -m elf_i386_fbsd"
;;
x86_64-*linux*)
case `/usr/bin/file conftest.o` in
case `$FILECMD conftest.o` in
*x86-64*)
LD="${LD-ld} -m elf32_x86_64"
;;
@@ -1460,7 +1457,7 @@ s390*-*linux*|s390*-*tpf*|sparc*-*linux*)
# options accordingly.
echo 'int i;' > conftest.$ac_ext
if AC_TRY_EVAL(ac_compile); then
case `/usr/bin/file conftest.o` in
case `$FILECMD conftest.o` in
*64-bit*)
case $lt_cv_prog_gnu_ld in
yes*)
@@ -1499,9 +1496,22 @@ need_locks=$enable_libtool_lock
m4_defun([_LT_PROG_AR],
[AC_CHECK_TOOLS(AR, [ar], false)
: ${AR=ar}
: ${AR_FLAGS=cru}
_LT_DECL([], [AR], [1], [The archiver])
_LT_DECL([], [AR_FLAGS], [1], [Flags to create an archive])
# Use ARFLAGS variable as AR's operation code to sync the variable naming with
# Automake. If both AR_FLAGS and ARFLAGS are specified, AR_FLAGS should have
# higher priority because thats what people were doing historically (setting
# ARFLAGS for automake and AR_FLAGS for libtool). FIXME: Make the AR_FLAGS
# variable obsoleted/removed.
test ${AR_FLAGS+y} || AR_FLAGS=${ARFLAGS-cr}
lt_ar_flags=$AR_FLAGS
_LT_DECL([], [lt_ar_flags], [0], [Flags to create an archive (by configure)])
# Make AR_FLAGS overridable by 'make ARFLAGS='. Don't try to run-time override
# by AR_FLAGS because that was never working and AR_FLAGS is about to die.
_LT_DECL([], [AR_FLAGS], [\@S|@{ARFLAGS-"\@S|@lt_ar_flags"}],
[Flags to create an archive])
AC_CACHE_CHECK([for archiver @FILE support], [lt_cv_ar_at_file],
[lt_cv_ar_at_file=no
@@ -1720,7 +1730,7 @@ AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl
lt_cv_sys_max_cmd_len=8192;
;;
bitrig* | darwin* | dragonfly* | freebsd* | netbsd* | openbsd*)
bitrig* | darwin* | dragonfly* | freebsd* | midnightbsd* | netbsd* | openbsd*)
# This has been around since 386BSD, at least. Likely further.
if test -x /sbin/sysctl; then
lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax`
@@ -1763,7 +1773,7 @@ AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl
sysv5* | sco5v6* | sysv4.2uw2*)
kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null`
if test -n "$kargmax"; then
lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[[ ]]//'`
lt_cv_sys_max_cmd_len=`echo $kargmax | $SED 's/.*[[ ]]//'`
else
lt_cv_sys_max_cmd_len=32768
fi
@@ -2213,26 +2223,35 @@ m4_defun([_LT_CMD_STRIPLIB],
striplib=
old_striplib=
AC_MSG_CHECKING([whether stripping libraries is possible])
if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then
test -z "$old_striplib" && old_striplib="$STRIP --strip-debug"
test -z "$striplib" && striplib="$STRIP --strip-unneeded"
AC_MSG_RESULT([yes])
if test -z "$STRIP"; then
AC_MSG_RESULT([no])
else
# FIXME - insert some real tests, host_os isn't really good enough
case $host_os in
darwin*)
if test -n "$STRIP"; then
if $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then
old_striplib="$STRIP --strip-debug"
striplib="$STRIP --strip-unneeded"
AC_MSG_RESULT([yes])
else
case $host_os in
darwin*)
# FIXME - insert some real tests, host_os isn't really good enough
striplib="$STRIP -x"
old_striplib="$STRIP -S"
AC_MSG_RESULT([yes])
else
;;
freebsd*)
if $STRIP -V 2>&1 | $GREP "elftoolchain" >/dev/null; then
old_striplib="$STRIP --strip-debug"
striplib="$STRIP --strip-unneeded"
AC_MSG_RESULT([yes])
else
AC_MSG_RESULT([no])
fi
;;
*)
AC_MSG_RESULT([no])
fi
;;
*)
AC_MSG_RESULT([no])
;;
esac
;;
esac
fi
fi
_LT_DECL([], [old_striplib], [1], [Commands to strip libraries])
_LT_DECL([], [striplib], [1])
@@ -2555,7 +2574,7 @@ cygwin* | mingw* | pw32* | cegcc*)
case $host_os in
cygwin*)
# Cygwin DLLs use 'cyg' prefix rather than 'lib'
soname_spec='`echo $libname | sed -e 's/^lib/cyg/'``echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext'
soname_spec='`echo $libname | $SED -e 's/^lib/cyg/'``echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext'
m4_if([$1], [],[
sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api"])
;;
@@ -2565,14 +2584,14 @@ m4_if([$1], [],[
;;
pw32*)
# pw32 DLLs use 'pw' prefix rather than 'lib'
library_names_spec='`echo $libname | sed -e 's/^lib/pw/'``echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext'
library_names_spec='`echo $libname | $SED -e 's/^lib/pw/'``echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext'
;;
esac
dynamic_linker='Win32 ld.exe'
;;
*,cl*)
# Native MSVC
*,cl* | *,icl*)
# Native MSVC or ICC
libname_spec='$name'
soname_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext'
library_names_spec='$libname.dll.lib'
@@ -2591,7 +2610,7 @@ m4_if([$1], [],[
done
IFS=$lt_save_ifs
# Convert to MSYS style.
sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([[a-zA-Z]]\\):| /\\1|g' -e 's|^ ||'`
sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's|\\\\|/|g' -e 's| \\([[a-zA-Z]]\\):| /\\1|g' -e 's|^ ||'`
;;
cygwin*)
# Convert to unix form, then to dos form, then back to unix form
@@ -2628,7 +2647,7 @@ m4_if([$1], [],[
;;
*)
# Assume MSVC wrapper
# Assume MSVC and ICC wrapper
library_names_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext $libname.lib'
dynamic_linker='Win32 ld.exe'
;;
@@ -2661,7 +2680,7 @@ dgux*)
shlibpath_var=LD_LIBRARY_PATH
;;
freebsd* | dragonfly*)
freebsd* | dragonfly* | midnightbsd*)
# DragonFly does not have aout. When/if they implement a new
# versioning mechanism, adjust this.
if test -x /usr/bin/objformat; then
@@ -2873,9 +2892,6 @@ linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
# before this can be enabled.
hardcode_into_libs=yes
# Add ABI-specific directories to the system library path.
sys_lib_dlsearch_path_spec="/lib64 /usr/lib64 /lib /usr/lib"
# Ideally, we could use ldconfig to report *all* directores which are
# searched for libraries, however this is still not possible. Aside from not
# being certain /sbin/ldconfig is available, command
@@ -2884,7 +2900,7 @@ linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
# appending ld.so.conf contents (and includes) to the search path.
if test -f /etc/ld.so.conf; then
lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \[$]2)); skip = 1; } { if (!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '`
sys_lib_dlsearch_path_spec="$sys_lib_dlsearch_path_spec $lt_ld_extra"
sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra"
fi
# We used to test for /lib/ld.so.1 and disable shared libraries on
@@ -2896,6 +2912,18 @@ linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
dynamic_linker='GNU/Linux ld.so'
;;
netbsdelf*-gnu)
version_type=linux
need_lib_prefix=no
need_version=no
library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
soname_spec='${libname}${release}${shared_ext}$major'
shlibpath_var=LD_LIBRARY_PATH
shlibpath_overrides_runpath=no
hardcode_into_libs=yes
dynamic_linker='NetBSD ld.elf_so'
;;
netbsd*)
version_type=sunos
need_lib_prefix=no
@@ -3463,7 +3491,7 @@ beos*)
bsdi[[45]]*)
lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib)'
lt_cv_file_magic_cmd='/usr/bin/file -L'
lt_cv_file_magic_cmd='$FILECMD -L'
lt_cv_file_magic_test_file=/shlib/libc.so
;;
@@ -3497,14 +3525,14 @@ darwin* | rhapsody*)
lt_cv_deplibs_check_method=pass_all
;;
freebsd* | dragonfly*)
freebsd* | dragonfly* | midnightbsd*)
if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then
case $host_cpu in
i*86 )
# Not sure whether the presence of OpenBSD here was a mistake.
# Let's accept both of them until this is cleared up.
lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[[3-9]]86 (compact )?demand paged shared library'
lt_cv_file_magic_cmd=/usr/bin/file
lt_cv_file_magic_cmd=$FILECMD
lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*`
;;
esac
@@ -3518,7 +3546,7 @@ haiku*)
;;
hpux10.20* | hpux11*)
lt_cv_file_magic_cmd=/usr/bin/file
lt_cv_file_magic_cmd=$FILECMD
case $host_cpu in
ia64*)
lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|ELF-[[0-9]][[0-9]]) shared object file - IA64'
@@ -3555,7 +3583,7 @@ linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*)
lt_cv_deplibs_check_method=pass_all
;;
netbsd*)
netbsd* | netbsdelf*-gnu)
if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then
lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$'
else
@@ -3565,7 +3593,7 @@ netbsd*)
newos6*)
lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (executable|dynamic lib)'
lt_cv_file_magic_cmd=/usr/bin/file
lt_cv_file_magic_cmd=$FILECMD
lt_cv_file_magic_test_file=/usr/lib/libnls.so
;;
@@ -3692,13 +3720,13 @@ else
mingw*) lt_bad_file=conftest.nm/nofile ;;
*) lt_bad_file=/dev/null ;;
esac
case `"$tmp_nm" -B $lt_bad_file 2>&1 | sed '1q'` in
case `"$tmp_nm" -B $lt_bad_file 2>&1 | $SED '1q'` in
*$lt_bad_file* | *'Invalid file or object type'*)
lt_cv_path_NM="$tmp_nm -B"
break 2
;;
*)
case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in
case `"$tmp_nm" -p /dev/null 2>&1 | $SED '1q'` in
*/dev/null*)
lt_cv_path_NM="$tmp_nm -p"
break 2
@@ -3724,7 +3752,7 @@ else
# Let the user override the test.
else
AC_CHECK_TOOLS(DUMPBIN, [dumpbin "link -dump"], :)
case `$DUMPBIN -symbols -headers /dev/null 2>&1 | sed '1q'` in
case `$DUMPBIN -symbols -headers /dev/null 2>&1 | $SED '1q'` in
*COFF*)
DUMPBIN="$DUMPBIN -symbols -headers"
;;
@@ -3964,7 +3992,7 @@ esac
if test "$lt_cv_nm_interface" = "MS dumpbin"; then
# Gets list of data symbols to import.
lt_cv_sys_global_symbol_to_import="sed -n -e 's/^I .* \(.*\)$/\1/p'"
lt_cv_sys_global_symbol_to_import="$SED -n -e 's/^I .* \(.*\)$/\1/p'"
# Adjust the below global symbol transforms to fixup imported variables.
lt_cdecl_hook=" -e 's/^I .* \(.*\)$/extern __declspec(dllimport) char \1;/p'"
lt_c_name_hook=" -e 's/^I .* \(.*\)$/ {\"\1\", (void *) 0},/p'"
@@ -3982,20 +4010,20 @@ fi
# Transform an extracted symbol line into a proper C declaration.
# Some systems (esp. on ia64) link data and code symbols differently,
# so use this general approach.
lt_cv_sys_global_symbol_to_cdecl="sed -n"\
lt_cv_sys_global_symbol_to_cdecl="$SED -n"\
$lt_cdecl_hook\
" -e 's/^T .* \(.*\)$/extern int \1();/p'"\
" -e 's/^$symcode$symcode* .* \(.*\)$/extern char \1;/p'"
# Transform an extracted symbol line into symbol name and symbol address
lt_cv_sys_global_symbol_to_c_name_address="sed -n"\
lt_cv_sys_global_symbol_to_c_name_address="$SED -n"\
$lt_c_name_hook\
" -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\
" -e 's/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/p'"
# Transform an extracted symbol line into symbol name with lib prefix and
# symbol address.
lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n"\
lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="$SED -n"\
$lt_c_name_lib_hook\
" -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\
" -e 's/^$symcode$symcode* .* \(lib.*\)$/ {\"\1\", (void *) \&\1},/p'"\
@@ -4019,7 +4047,7 @@ for ac_symprfx in "" "_"; do
if test "$lt_cv_nm_interface" = "MS dumpbin"; then
# Fake it for dumpbin and say T for any non-static function,
# D for any global variable and I for any imported variable.
# Also find C++ and __fastcall symbols from MSVC++,
# Also find C++ and __fastcall symbols from MSVC++ or ICC,
# which start with @ or ?.
lt_cv_sys_global_symbol_pipe="$AWK ['"\
" {last_section=section; section=\$ 3};"\
@@ -4037,9 +4065,9 @@ for ac_symprfx in "" "_"; do
" s[1]~prfx {split(s[1],t,\"@\"); print f,t[1],substr(t[1],length(prfx))}"\
" ' prfx=^$ac_symprfx]"
else
lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[[ ]]\($symcode$symcode*\)[[ ]][[ ]]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'"
lt_cv_sys_global_symbol_pipe="$SED -n -e 's/^.*[[ ]]\($symcode$symcode*\)[[ ]][[ ]]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'"
fi
lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | sed '/ __gnu_lto/d'"
lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | $SED '/ __gnu_lto/d'"
# Check to see that the pipe works correctly.
pipe_works=no
@@ -4061,7 +4089,8 @@ _LT_EOF
if AC_TRY_EVAL(ac_compile); then
# Now try to grab the symbols.
nlist=conftest.nm
if AC_TRY_EVAL(NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) && test -s "$nlist"; then
$ECHO "$as_me:$LINENO: $NM conftest.$ac_objext | $lt_cv_sys_global_symbol_pipe > $nlist" >&AS_MESSAGE_LOG_FD
if eval "$NM" conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist 2>&AS_MESSAGE_LOG_FD && test -s "$nlist"; then
# Try sorting and uniquifying the output.
if sort "$nlist" | uniq > "$nlist"T; then
mv -f "$nlist"T "$nlist"
@@ -4326,7 +4355,7 @@ m4_if([$1], [CXX], [
;;
esac
;;
freebsd* | dragonfly*)
freebsd* | dragonfly* | midnightbsd*)
# FreeBSD uses GNU C++
;;
hpux9* | hpux10* | hpux11*)
@@ -4409,7 +4438,7 @@ m4_if([$1], [CXX], [
_LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink'
;;
*)
case `$CC -V 2>&1 | sed 5q` in
case `$CC -V 2>&1 | $SED 5q` in
*Sun\ C*)
# Sun C++ 5.9
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
@@ -4433,7 +4462,7 @@ m4_if([$1], [CXX], [
;;
esac
;;
netbsd*)
netbsd* | netbsdelf*-gnu)
;;
*qnx* | *nto*)
# QNX uses GNU C++, but need to define -shared option too, otherwise
@@ -4701,6 +4730,12 @@ m4_if([$1], [CXX], [
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
_LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
;;
# flang / f18. f95 an alias for gfortran or flang on Debian
flang* | f18* | f95*)
_LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
_LT_TAGVAR(lt_prog_compiler_static, $1)='-static'
;;
# icc used to be incompatible with GCC.
# ICC 10 doesn't accept -KPIC any more.
icc* | ifort*)
@@ -4745,7 +4780,7 @@ m4_if([$1], [CXX], [
_LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink'
;;
*)
case `$CC -V 2>&1 | sed 5q` in
case `$CC -V 2>&1 | $SED 5q` in
*Sun\ Ceres\ Fortran* | *Sun*Fortran*\ [[1-7]].* | *Sun*Fortran*\ 8.[[0-3]]*)
# Sun Fortran 8.3 passes all unrecognized flags to the linker
_LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
@@ -4928,7 +4963,7 @@ m4_if([$1], [CXX], [
if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then
_LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols'
else
_LT_TAGVAR(export_symbols_cmds, $1)='`func_echo_all $NM | $SED -e '\''s/B\([[^B]]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && ([substr](\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols'
_LT_TAGVAR(export_symbols_cmds, $1)='`func_echo_all $NM | $SED -e '\''s/B\([[^B]]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "L") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && ([substr](\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols'
fi
;;
pw32*)
@@ -4936,7 +4971,7 @@ m4_if([$1], [CXX], [
;;
cygwin* | mingw* | cegcc*)
case $cc_basename in
cl*)
cl* | icl*)
_LT_TAGVAR(exclude_expsyms, $1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*'
;;
*)
@@ -4945,6 +4980,9 @@ m4_if([$1], [CXX], [
;;
esac
;;
linux* | k*bsd*-gnu | gnu*)
_LT_TAGVAR(link_all_deplibs, $1)=no
;;
*)
_LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
;;
@@ -4993,20 +5031,23 @@ dnl Note also adjust exclude_expsyms for C++ above.
case $host_os in
cygwin* | mingw* | pw32* | cegcc*)
# FIXME: the MSVC++ port hasn't been tested in a loooong time
# FIXME: the MSVC++ and ICC port hasn't been tested in a loooong time
# When not using gcc, we currently assume that we are using
# Microsoft Visual C++.
# Microsoft Visual C++ or Intel C++ Compiler.
if test yes != "$GCC"; then
with_gnu_ld=no
fi
;;
interix*)
# we just hope/assume this is gcc and not c89 (= MSVC++)
# we just hope/assume this is gcc and not c89 (= MSVC++ or ICC)
with_gnu_ld=yes
;;
openbsd* | bitrig*)
with_gnu_ld=no
;;
linux* | k*bsd*-gnu | gnu*)
_LT_TAGVAR(link_all_deplibs, $1)=no
;;
esac
_LT_TAGVAR(ld_shlibs, $1)=yes
@@ -5053,7 +5094,7 @@ dnl Note also adjust exclude_expsyms for C++ above.
_LT_TAGVAR(whole_archive_flag_spec, $1)=
fi
supports_anon_versioning=no
case `$LD -v | $SED -e 's/([^)]\+)\s\+//' 2>&1` in
case `$LD -v | $SED -e 's/([[^)]]\+)\s\+//' 2>&1` in
*GNU\ gold*) supports_anon_versioning=yes ;;
*\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.10.*) ;; # catch versions < 2.11
*\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ...
@@ -5165,6 +5206,7 @@ _LT_EOF
emximp -o $lib $output_objdir/$libname.def'
_LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def'
_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
_LT_TAGVAR(file_list_spec, $1)='@'
;;
interix[[3-9]]*)
@@ -5179,7 +5221,7 @@ _LT_EOF
# 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link
# time. Moving up from 0x10000000 also allows more sbrk(2) space.
_LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
_LT_TAGVAR(archive_expsym_cmds, $1)='sed "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
_LT_TAGVAR(archive_expsym_cmds, $1)='$SED "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
;;
gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu)
@@ -5222,7 +5264,7 @@ _LT_EOF
_LT_TAGVAR(compiler_needs_object, $1)=yes
;;
esac
case `$CC -V 2>&1 | sed 5q` in
case `$CC -V 2>&1 | $SED 5q` in
*Sun\ C*) # Sun C 5.9
_LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive'
_LT_TAGVAR(compiler_needs_object, $1)=yes
@@ -5234,13 +5276,14 @@ _LT_EOF
if test yes = "$supports_anon_versioning"; then
_LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~
cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
echo "local: *; };" >> $output_objdir/$libname.ver~
$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib'
fi
case $cc_basename in
tcc*)
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
_LT_TAGVAR(export_dynamic_flag_spec, $1)='-rdynamic'
;;
xlf* | bgf* | bgxlf* | mpixlf*)
@@ -5250,7 +5293,7 @@ _LT_EOF
_LT_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib'
if test yes = "$supports_anon_versioning"; then
_LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~
cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
echo "local: *; };" >> $output_objdir/$libname.ver~
$LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib'
fi
@@ -5261,7 +5304,7 @@ _LT_EOF
fi
;;
netbsd*)
netbsd* | netbsdelf*-gnu)
if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
_LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib'
wlarc=
@@ -5382,7 +5425,7 @@ _LT_EOF
if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then
_LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols'
else
_LT_TAGVAR(export_symbols_cmds, $1)='`func_echo_all $NM | $SED -e '\''s/B\([[^B]]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && ([substr](\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols'
_LT_TAGVAR(export_symbols_cmds, $1)='`func_echo_all $NM | $SED -e '\''s/B\([[^B]]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "L") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && ([substr](\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols'
fi
aix_use_runtimelinking=no
@@ -5565,12 +5608,12 @@ _LT_EOF
cygwin* | mingw* | pw32* | cegcc*)
# When not using gcc, we currently assume that we are using
# Microsoft Visual C++.
# Microsoft Visual C++ or Intel C++ Compiler.
# hardcode_libdir_flag_spec is actually meaningless, as there is
# no search path for DLLs.
case $cc_basename in
cl*)
# Native MSVC
cl* | icl*)
# Native MSVC or ICC
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' '
_LT_TAGVAR(allow_undefined_flag, $1)=unsupported
_LT_TAGVAR(always_export_symbols, $1)=yes
@@ -5611,7 +5654,7 @@ _LT_EOF
fi'
;;
*)
# Assume MSVC wrapper
# Assume MSVC and ICC wrapper
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' '
_LT_TAGVAR(allow_undefined_flag, $1)=unsupported
# Tell ltmain to make .lib files, not .a files.
@@ -5659,7 +5702,7 @@ _LT_EOF
;;
# FreeBSD 3 and greater uses gcc -shared to do shared libraries.
freebsd* | dragonfly*)
freebsd* | dragonfly* | midnightbsd*)
_LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
_LT_TAGVAR(hardcode_direct, $1)=yes
@@ -5782,6 +5825,7 @@ _LT_EOF
if test yes = "$lt_cv_irix_exported_symbol"; then
_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations $wl-exports_file $wl$export_symbols -o $lib'
fi
_LT_TAGVAR(link_all_deplibs, $1)=no
else
_LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib'
_LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -exports_file $export_symbols -o $lib'
@@ -5799,11 +5843,12 @@ _LT_EOF
# Fabrice Bellard et al's Tiny C Compiler
_LT_TAGVAR(ld_shlibs, $1)=yes
_LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir'
;;
esac
;;
netbsd*)
netbsd* | netbsdelf*-gnu)
if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then
_LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out
else
@@ -5870,6 +5915,7 @@ _LT_EOF
emximp -o $lib $output_objdir/$libname.def'
_LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def'
_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
_LT_TAGVAR(file_list_spec, $1)='@'
;;
osf3*)
@@ -6425,7 +6471,7 @@ if test yes != "$_lt_caught_CXX_error"; then
# Commands to make compiler produce verbose output that lists
# what "hidden" libraries, object files and flags are used when
# linking a shared library.
output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"'
output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP " \-L"'
else
GXX=no
@@ -6636,8 +6682,8 @@ if test yes != "$_lt_caught_CXX_error"; then
cygwin* | mingw* | pw32* | cegcc*)
case $GXX,$cc_basename in
,cl* | no,cl*)
# Native MSVC
,cl* | no,cl* | ,icl* | no,icl*)
# Native MSVC or ICC
# hardcode_libdir_flag_spec is actually meaningless, as there is
# no search path for DLLs.
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' '
@@ -6735,6 +6781,7 @@ if test yes != "$_lt_caught_CXX_error"; then
emximp -o $lib $output_objdir/$libname.def'
_LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def'
_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
_LT_TAGVAR(file_list_spec, $1)='@'
;;
dgux*)
@@ -6765,7 +6812,7 @@ if test yes != "$_lt_caught_CXX_error"; then
_LT_TAGVAR(archive_cmds_need_lc, $1)=no
;;
freebsd* | dragonfly*)
freebsd* | dragonfly* | midnightbsd*)
# FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF
# conventions
_LT_TAGVAR(ld_shlibs, $1)=yes
@@ -6800,7 +6847,7 @@ if test yes != "$_lt_caught_CXX_error"; then
# explicitly linking system object files so we need to strip them
# from the output so that they don't get included in the library
# dependencies.
output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP "\-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"'
output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP " \-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"'
;;
*)
if test yes = "$GXX"; then
@@ -6865,7 +6912,7 @@ if test yes != "$_lt_caught_CXX_error"; then
# explicitly linking system object files so we need to strip them
# from the output so that they don't get included in the library
# dependencies.
output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP "\-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"'
output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP " \-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"'
;;
*)
if test yes = "$GXX"; then
@@ -6902,7 +6949,7 @@ if test yes != "$_lt_caught_CXX_error"; then
# 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link
# time. Moving up from 0x10000000 also allows more sbrk(2) space.
_LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
_LT_TAGVAR(archive_expsym_cmds, $1)='sed "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
_LT_TAGVAR(archive_expsym_cmds, $1)='$SED "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib'
;;
irix5* | irix6*)
case $cc_basename in
@@ -7042,13 +7089,13 @@ if test yes != "$_lt_caught_CXX_error"; then
_LT_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib'
if test yes = "$supports_anon_versioning"; then
_LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~
cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
echo "local: *; };" >> $output_objdir/$libname.ver~
$CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib'
fi
;;
*)
case `$CC -V 2>&1 | sed 5q` in
case `$CC -V 2>&1 | $SED 5q` in
*Sun\ C*)
# Sun C++ 5.9
_LT_TAGVAR(no_undefined_flag, $1)=' -zdefs'
@@ -7204,7 +7251,7 @@ if test yes != "$_lt_caught_CXX_error"; then
# Commands to make compiler produce verbose output that lists
# what "hidden" libraries, object files and flags are used when
# linking a shared library.
output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"'
output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP " \-L"'
else
# FIXME: insert proper C++ library support
@@ -7288,7 +7335,7 @@ if test yes != "$_lt_caught_CXX_error"; then
# Commands to make compiler produce verbose output that lists
# what "hidden" libraries, object files and flags are used when
# linking a shared library.
output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"'
output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP " \-L"'
else
# g++ 2.7 appears to require '-G' NOT '-shared' on this
# platform.
@@ -7299,7 +7346,7 @@ if test yes != "$_lt_caught_CXX_error"; then
# Commands to make compiler produce verbose output that lists
# what "hidden" libraries, object files and flags are used when
# linking a shared library.
output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"'
output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP " \-L"'
fi
_LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $wl$libdir'
@@ -8186,6 +8233,14 @@ _LT_DECL([], [DLLTOOL], [1], [DLL creation program])
AC_SUBST([DLLTOOL])
])
# _LT_DECL_FILECMD
# ----------------
# Check for a file(cmd) program that can be used to detect file type and magic
m4_defun([_LT_DECL_FILECMD],
[AC_CHECK_TOOL([FILECMD], [file], [:])
_LT_DECL([], [FILECMD], [1], [A file(cmd) program that detects file types])
])# _LD_DECL_FILECMD
# _LT_DECL_SED
# ------------
# Check for a fully-functional sed program, that truncates
@@ -8365,8 +8420,8 @@ _LT_DECL([to_tool_file_cmd], [lt_cv_to_tool_file_cmd],
# Helper functions for option handling. -*- Autoconf -*-
#
# Copyright (C) 2004-2005, 2007-2009, 2011-2015 Free Software
# Foundation, Inc.
# Copyright (C) 2004-2005, 2007-2009, 2011-2019, 2021-2022 Free
# Software Foundation, Inc.
# Written by Gary V. Vaughan, 2004
#
# This file is free software; the Free Software Foundation gives
@@ -8797,7 +8852,7 @@ LT_OPTION_DEFINE([LTDL_INIT], [convenience],
# ltsugar.m4 -- libtool m4 base layer. -*-Autoconf-*-
#
# Copyright (C) 2004-2005, 2007-2008, 2011-2015 Free Software
# Copyright (C) 2004-2005, 2007-2008, 2011-2019, 2021-2022 Free Software
# Foundation, Inc.
# Written by Gary V. Vaughan, 2004
#
@@ -8922,7 +8977,8 @@ m4_define([lt_dict_filter],
# ltversion.m4 -- version numbers -*- Autoconf -*-
#
# Copyright (C) 2004, 2011-2015 Free Software Foundation, Inc.
# Copyright (C) 2004, 2011-2019, 2021-2022 Free Software Foundation,
# Inc.
# Written by Scott James Remnant, 2004
#
# This file is free software; the Free Software Foundation gives
@@ -8931,23 +8987,23 @@ m4_define([lt_dict_filter],
# @configure_input@
# serial 4179 ltversion.m4
# serial 4245 ltversion.m4
# This file is part of GNU Libtool
m4_define([LT_PACKAGE_VERSION], [2.4.6])
m4_define([LT_PACKAGE_REVISION], [2.4.6])
m4_define([LT_PACKAGE_VERSION], [2.4.7])
m4_define([LT_PACKAGE_REVISION], [2.4.7])
AC_DEFUN([LTVERSION_VERSION],
[macro_version='2.4.6'
macro_revision='2.4.6'
[macro_version='2.4.7'
macro_revision='2.4.7'
_LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?])
_LT_DECL(, macro_revision, 0)
])
# lt~obsolete.m4 -- aclocal satisfying obsolete definitions. -*-Autoconf-*-
#
# Copyright (C) 2004-2005, 2007, 2009, 2011-2015 Free Software
# Foundation, Inc.
# Copyright (C) 2004-2005, 2007, 2009, 2011-2019, 2021-2022 Free
# Software Foundation, Inc.
# Written by Scott James Remnant, 2004.
#
# This file is free software; the Free Software Foundation gives
@@ -9044,8 +9100,8 @@ m4_ifndef([_LT_PROG_F77], [AC_DEFUN([_LT_PROG_F77])])
m4_ifndef([_LT_PROG_FC], [AC_DEFUN([_LT_PROG_FC])])
m4_ifndef([_LT_PROG_CXX], [AC_DEFUN([_LT_PROG_CXX])])
# pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*-
# serial 11 (pkg-config-0.29.1)
# pkg.m4 - Macros to locate and use pkg-config. -*- Autoconf -*-
# serial 12 (pkg-config-0.29.2)
dnl Copyright © 2004 Scott James Remnant <scott@netsplit.com>.
dnl Copyright © 2012-2015 Dan Nicholson <dbn.lists@gmail.com>
@@ -9087,7 +9143,7 @@ dnl
dnl See the "Since" comment for each macro you use to see what version
dnl of the macros you require.
m4_defun([PKG_PREREQ],
[m4_define([PKG_MACROS_VERSION], [0.29.1])
[m4_define([PKG_MACROS_VERSION], [0.29.2])
m4_if(m4_version_compare(PKG_MACROS_VERSION, [$1]), -1,
[m4_fatal([pkg.m4 version $1 or higher is required but ]PKG_MACROS_VERSION[ found])])
])dnl PKG_PREREQ
@@ -9132,7 +9188,7 @@ dnl Check to see whether a particular set of modules exists. Similar to
dnl PKG_CHECK_MODULES(), but does not set variables or print errors.
dnl
dnl Please remember that m4 expands AC_REQUIRE([PKG_PROG_PKG_CONFIG])
dnl only at the first occurence in configure.ac, so if the first place
dnl only at the first occurrence in configure.ac, so if the first place
dnl it's called might be skipped (such as if it is within an "if", you
dnl have to call PKG_CHECK_EXISTS manually
AC_DEFUN([PKG_CHECK_EXISTS],
@@ -9188,7 +9244,7 @@ AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl
AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl
pkg_failed=no
AC_MSG_CHECKING([for $1])
AC_MSG_CHECKING([for $2])
_PKG_CONFIG([$1][_CFLAGS], [cflags], [$2])
_PKG_CONFIG([$1][_LIBS], [libs], [$2])
@@ -9198,17 +9254,17 @@ and $1[]_LIBS to avoid the need to call pkg-config.
See the pkg-config man page for more details.])
if test $pkg_failed = yes; then
AC_MSG_RESULT([no])
AC_MSG_RESULT([no])
_PKG_SHORT_ERRORS_SUPPORTED
if test $_pkg_short_errors_supported = yes; then
$1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$2" 2>&1`
else
$1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$2" 2>&1`
$1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$2" 2>&1`
else
$1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$2" 2>&1`
fi
# Put the nasty error message in config.log where it belongs
echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD
# Put the nasty error message in config.log where it belongs
echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD
m4_default([$4], [AC_MSG_ERROR(
m4_default([$4], [AC_MSG_ERROR(
[Package requirements ($2) were not met:
$$1_PKG_ERRORS
@@ -9219,8 +9275,8 @@ installed software in a non-standard prefix.
_PKG_TEXT])[]dnl
])
elif test $pkg_failed = untried; then
AC_MSG_RESULT([no])
m4_default([$4], [AC_MSG_FAILURE(
AC_MSG_RESULT([no])
m4_default([$4], [AC_MSG_FAILURE(
[The pkg-config script could not be found or is too old. Make sure it
is in your PATH or set the PKG_CONFIG environment variable to the full
path to pkg-config.
@@ -9230,10 +9286,10 @@ _PKG_TEXT
To get pkg-config, see <http://pkg-config.freedesktop.org/>.])[]dnl
])
else
$1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS
$1[]_LIBS=$pkg_cv_[]$1[]_LIBS
$1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS
$1[]_LIBS=$pkg_cv_[]$1[]_LIBS
AC_MSG_RESULT([yes])
$3
$3
fi[]dnl
])dnl PKG_CHECK_MODULES
@@ -9390,7 +9446,7 @@ AS_IF([test "$AS_TR_SH([with_]m4_tolower([$1]))" = "yes"],
# AM_CONDITIONAL -*- Autoconf -*-
# Copyright (C) 1997-2020 Free Software Foundation, Inc.
# Copyright (C) 1997-2021 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
@@ -9421,7 +9477,7 @@ AC_CONFIG_COMMANDS_PRE(
Usually this means the macro was only invoked conditionally.]])
fi])])
# Copyright (C) 2006-2020 Free Software Foundation, Inc.
# Copyright (C) 2006-2021 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
+1 -7
View File
@@ -2,9 +2,7 @@
# Copyright 2009, Wouter Wijngaards, NLnet Labs.
# BSD licensed.
#
# Version 51
# 2025-11-06 Fix ACX_CHECK_NONSTRING_ATTRIBUTE to reject clang, that prints
# a warning for 'unknown attribute' when nonstring is used.
# Version 50
# 2025-09-29 add ac_cv_func_malloc_0_nonnull as a cache value for the malloc(0)
# check by ACX_FUNC_MALLOC.
# 2025-09-29 add ACX_CHECK_NONSTRING_ATTRIBUTE, AHX_CONFIG_NONSTRING_ATTRIBUTE.
@@ -537,9 +535,6 @@ dnl result in HAVE_ATTR_NONSTRING.
dnl Make sure you include AHX_CONFIG_NONSTRING_ATTRIBUTE also.
AC_DEFUN([ACX_CHECK_NONSTRING_ATTRIBUTE],
[AC_REQUIRE([AC_PROG_CC])
AC_REQUIRE([ACX_CHECK_ERROR_FLAGS])
BAKCFLAGS="$CFLAGS"
CFLAGS="$CFLAGS $ERRFLAG"
AC_MSG_CHECKING(whether the C compiler (${CC-cc}) accepts the "nonstring" attribute)
AC_CACHE_VAL(ac_cv_c_nonstring_attribute,
[ac_cv_c_nonstring_attribute=no
@@ -551,7 +546,6 @@ struct test {
struct test t = { "1" };
(void) t;
]])],[ac_cv_c_nonstring_attribute="yes"],[ac_cv_c_nonstring_attribute="no"])
CFLAGS="$BAKCFLAGS"
])
dnl Setup ATTR_NONSTRING config.h parts.
+2 -17
View File
@@ -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 32
#serial 31
AU_ALIAS([ACX_PTHREAD], [AX_PTHREAD])
AC_DEFUN([AX_PTHREAD], [
@@ -249,22 +249,7 @@ AS_IF([test "x$ax_pthread_clang" = "xyes"],
# correctly enabled
case $host_os in
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*)
darwin* | hpux* | linux* | osf* | solaris*)
ax_pthread_check_macro="_REENTRANT"
;;
+4 -22
View File
@@ -401,12 +401,6 @@ 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)
@@ -760,10 +754,8 @@ cachedb_intcache_store(struct module_qstate* qstate, int msg_expired,
"(original ttl: %d)", (int)original_ttl);
/* The expired entry does not get checked by the validator
* and we need a validation value for it. */
/* By setting this to unchecked, bogus data is not returned
* as non-bogus. */
if(qstate->env->cfg->cachedb_check_when_serve_expired)
qstate->return_msg->rep->security = sec_status_unchecked;
qstate->return_msg->rep->security = sec_status_insecure;
}
(void)dns_cache_store(qstate->env, &qstate->qinfo,
qstate->return_msg->rep, 0, qstate->prefetch_leeway, 0,
@@ -811,11 +803,8 @@ cachedb_handle_query(struct module_qstate* qstate,
return;
}
if(qstate->blacklist || qstate->no_cache_lookup
|| iter_stub_fwd_no_cache(qstate, &qstate->qinfo, NULL, NULL,
NULL, 0)) {
/* cache is blacklisted or we are instructed from edns to not
* look or a forwarder/stub forbids it */
if(qstate->blacklist || qstate->no_cache_lookup) {
/* cache is blacklisted or we are instructed from edns to not look */
/* pass request to next module */
qstate->ext_state[id] = module_wait_module;
return;
@@ -869,11 +858,6 @@ 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 */
@@ -908,9 +892,7 @@ cachedb_handle_response(struct module_qstate* qstate,
{
qstate->is_cachedb_answer = 0;
/* check if we are not enabled or instructed to not cache, and skip */
if(!ie->enabled || qstate->no_cache_store
|| iter_stub_fwd_no_cache(qstate, &qstate->qinfo, NULL, NULL,
NULL, 0)) {
if(!ie->enabled || qstate->no_cache_store) {
/* we are done with the query */
qstate->ext_state[id] = module_finished;
return;
-7
View File
@@ -38,9 +38,6 @@
#ifndef UB_ON_WINDOWS
#include <sys/mman.h>
#endif
#ifdef __QNX__
#include "util/log.h"
#endif /* __QNX__ */
#define KEYSTREAM_ONLY
#include "chacha_private.h"
@@ -190,11 +187,7 @@ _rs_stir(void)
if(errno != ENOSYS ||
fallback_getentropy_urandom(rnd, sizeof rnd) == -1) {
#ifdef SIGKILL
#ifndef __QNX__
raise(SIGKILL);
#else /* !__QNX__ */
fatal_exit("failed to getentropy");
#endif /* __QNX__ */
#else
exit(9); /* windows */
#endif
+2 -2
View File
@@ -48,8 +48,8 @@ typedef struct
a = PLUS(a,b); d = ROTATE(XOR(d,a), 8); \
c = PLUS(c,d); b = ROTATE(XOR(b,c), 7);
static const char ATTR_NONSTRING(sigma[16]) = "expand 32-byte k";
static const char ATTR_NONSTRING(tau[16]) = "expand 16-byte k";
static const char sigma[16] = "expand 32-byte k";
static const char tau[16] = "expand 16-byte k";
static void
chacha_keysetup(chacha_ctx *x,const u8 *k,u32 kbits,u32 ATTR_UNUSED(ivbits))
-20
View File
@@ -29,9 +29,7 @@
#include <sys/param.h>
#include <sys/ioctl.h>
#include <sys/resource.h>
#ifndef __QNX__
#include <sys/syscall.h>
#endif /* !__QNX__ */
#ifdef SYS__sysctl
#include <linux/sysctl.h>
#endif
@@ -44,9 +42,7 @@
#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>
#ifndef __QNX__
#include <link.h>
#endif /* __QNX__ */
#include <termios.h>
#include <fcntl.h>
#include <signal.h>
@@ -64,14 +60,12 @@
#define SHA512_Final(r, c) sha512_digest(c, SHA512_DIGEST_SIZE, r)
#endif
#ifndef __QNX__
#include <linux/types.h>
#include <linux/random.h>
#ifdef HAVE_GETAUXVAL
#include <sys/auxv.h>
#endif
#include <sys/vfs.h>
#endif /* !__QNX__ */
#ifndef MAP_ANON
#define MAP_ANON MAP_ANONYMOUS
#endif
@@ -100,10 +94,8 @@ static int getentropy_urandom(void *buf, size_t len);
#ifdef SYS__sysctl
static int getentropy_sysctl(void *buf, size_t len);
#endif
#ifndef __QNX__
static int getentropy_fallback(void *buf, size_t len);
static int getentropy_phdr(struct dl_phdr_info *info, size_t size, void *data);
#endif /* !__QNX__ */
int
getentropy(void *buf, size_t len)
@@ -186,7 +178,6 @@ getentropy(void *buf, size_t len)
* sysctl ABI, or consider providing a new failsafe API which
* works in a chroot or when file descriptors are exhausted.
*/
#ifndef __QNX__
#undef FAIL_INSTEAD_OF_TRYING_FALLBACK
#ifdef FAIL_INSTEAD_OF_TRYING_FALLBACK
raise(SIGKILL);
@@ -194,9 +185,6 @@ getentropy(void *buf, size_t len)
ret = getentropy_fallback(buf, len);
if (ret != -1)
return (ret);
#else /* !__QNX__ */
fatal_exit("failed to read from /dev/urandom");
#endif /* __QNX__ */
errno = EIO;
return (ret);
@@ -226,11 +214,7 @@ getentropy_urandom(void *buf, size_t len)
{
struct stat st;
size_t i;
#ifndef __QNX__
int fd, cnt, flags;
#else /* !__QNX__ */
int fd, flags;
#endif /* __QNX__ */
int save_errno = errno;
start:
@@ -257,12 +241,10 @@ start:
close(fd);
goto nodevrandom;
}
#ifndef __QNX__
if (ioctl(fd, RNDGETENTCNT, &cnt) == -1) {
close(fd);
goto nodevrandom;
}
#endif /* !__QNX__ */
for (i = 0; i < len; ) {
size_t wanted = len - i;
ssize_t ret = read(fd, (char *)buf + i, wanted);
@@ -283,7 +265,6 @@ nodevrandom:
return (-1);
}
#ifndef __QNX__
#ifdef SYS__sysctl
static int
getentropy_sysctl(void *buf, size_t len)
@@ -556,4 +537,3 @@ getentropy_fallback(void *buf, size_t len)
errno = save_errno;
return (0); /* satisfied */
}
#endif /* !__QNX__ */
+382 -9
View File
@@ -20,25 +20,398 @@
* http://man.openbsd.org/getentropy.2
*/
/* 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 <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>
#include <errno.h>
#include <Security/SecRandom.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*)))
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) {
goto error;
errno = EIO;
return (-1);
}
if (SecRandomCopyBytes(kSecRandomDefault, len, buf) == errSecSuccess) {
return 0;
}
/*
* 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);
error:
errno = EIO;
return -1;
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 */
}
+4 -1
View File
@@ -42,7 +42,10 @@ static const int year_lengths[2] = {
};
static void
timesub(const time_t * const timep, const long offset, struct tm * const tmp)
timesub(timep, offset, tmp)
const time_t * const timep;
const long offset;
struct tm * const tmp;
{
long days;
long rem;
+10 -3
View File
@@ -59,7 +59,10 @@ static int inet_pton6 (const char *src, uint8_t *dst);
* Paul Vixie, 1996.
*/
int
inet_pton(int af, const char *src, void *dst)
inet_pton(af, src, dst)
int af;
const char *src;
void *dst;
{
switch (af) {
case AF_INET:
@@ -88,7 +91,9 @@ inet_pton(int af, const char *src, void *dst)
* Paul Vixie, 1996.
*/
static int
inet_pton4(const char *src, uint8_t *dst)
inet_pton4(src, dst)
const char *src;
uint8_t *dst;
{
static const char digits[] = "0123456789";
int saw_digit, octets, ch;
@@ -140,7 +145,9 @@ inet_pton4(const char *src, uint8_t *dst)
* Paul Vixie, 1996.
*/
static int
inet_pton6(const char *src, uint8_t *dst)
inet_pton6(src, dst)
const char *src;
uint8_t *dst;
{
static const char xdigits_l[] = "0123456789abcdef",
xdigits_u[] = "0123456789ABCDEF";
+9 -53
View File
@@ -31,9 +31,6 @@
/* 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
@@ -63,9 +60,6 @@
/* 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
@@ -146,10 +140,6 @@
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
@@ -266,6 +256,9 @@
/* Define to 1 if you have the `EVP_EncryptInit_ex' function. */
#undef HAVE_EVP_ENCRYPTINIT_EX
/* Define to 1 if you have the `EVP_MAC_CTX_new' function. */
#undef HAVE_EVP_MAC_CTX_NEW
/* Define to 1 if you have the `EVP_MAC_CTX_set_params' function. */
#undef HAVE_EVP_MAC_CTX_SET_PARAMS
@@ -299,12 +292,6 @@
/* 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
@@ -353,6 +340,9 @@
/* Define to 1 if you have the <hiredis/hiredis.h> header file. */
#undef HAVE_HIREDIS_HIREDIS_H
/* Define to 1 if you have the `HMAC_CTX_new' function. */
#undef HAVE_HMAC_CTX_NEW
/* Define to 1 if you have the `HMAC_Init_ex' function. */
#undef HAVE_HMAC_INIT_EX
@@ -529,9 +519,6 @@
/* 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
@@ -583,27 +570,12 @@
/* Define if you have POSIX threads libraries and header files. */
#undef HAVE_PTHREAD
/* Define to 1 if you have the <pthread_np.h> header file. */
#undef HAVE_PTHREAD_NP_H
/* Have PTHREAD_PRIO_INHERIT. */
#undef HAVE_PTHREAD_PRIO_INHERIT
/* Define to 1 if the system has the type `pthread_rwlock_t'. */
#undef HAVE_PTHREAD_RWLOCK_T
/* Define if pthread_setname_np has the common 2 arguments. */
#undef HAVE_PTHREAD_SETNAME_NP
/* Define if pthread_setname_np has only 1 argument. */
#undef HAVE_PTHREAD_SETNAME_NP1
/* Define if pthread_setname_np has 3 arguments. */
#undef HAVE_PTHREAD_SETNAME_NP3
/* Define if pthread_setname_np exists as pthread_set_name_np instead. */
#undef HAVE_PTHREAD_SET_NAME_NP
/* Define to 1 if the system has the type `pthread_spinlock_t'. */
#undef HAVE_PTHREAD_SPINLOCK_T
@@ -692,6 +664,9 @@
function. */
#undef HAVE_SSL_CTX_SET_TLSEXT_TICKET_KEY_EVP_CB
/* Define to 1 if you have the `SSL_CTX_set_tmp_ecdh' function. */
#undef HAVE_SSL_CTX_SET_TMP_ECDH
/* Define to 1 if you have the `SSL_get0_alpn_selected' function. */
#undef HAVE_SSL_GET0_ALPN_SELECTED
@@ -704,16 +679,9 @@
/* 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
@@ -776,12 +744,6 @@
/* Define to 1 if `sun_len' is a member of `struct sockaddr_un'. */
#undef HAVE_STRUCT_SOCKADDR_UN_SUN_LEN
/* Define to 1 if `st_mtimensec' is a member of `struct stat'. */
#undef HAVE_STRUCT_STAT_ST_MTIMENSEC
/* Define to 1 if `st_mtim.tv_nsec' is a member of `struct stat'. */
#undef HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC
/* Define if you have Swig libraries and header files. */
#undef HAVE_SWIG
@@ -878,12 +840,6 @@
/* 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
Vendored
+326 -504
View File
File diff suppressed because it is too large Load Diff
+8 -117
View File
@@ -11,15 +11,15 @@ sinclude(dnscrypt/dnscrypt.m4)
# must be numbers. ac_defun because of later processing
m4_define([VERSION_MAJOR],[1])
m4_define([VERSION_MINOR],[26])
m4_define([VERSION_MICRO],[0])
m4_define([VERSION_MINOR],[24])
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])
AC_SUBST(UNBOUND_VERSION_MINOR, [VERSION_MINOR])
AC_SUBST(UNBOUND_VERSION_MICRO, [VERSION_MICRO])
LIBUNBOUND_CURRENT=9
LIBUNBOUND_REVISION=39
LIBUNBOUND_REVISION=35
LIBUNBOUND_AGE=1
# 1.0.0 had 0:12:0
# 1.0.1 had 0:13:0
@@ -122,10 +122,6 @@ LIBUNBOUND_AGE=1
# 1.24.0 had 9:33:1
# 1.24.1 had 9:34:1
# 1.24.2 had 9:35: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
# Current -- the number of the binary API that we're implementing
# Revision -- which iteration of the implementation of the binary
@@ -365,14 +361,7 @@ AC_MSG_CHECKING(whether the C compiler (${CC-cc}) accepts the "noreturn" attribu
AC_CACHE_VAL(ac_cv_c_noreturn_attribute,
[ac_cv_c_noreturn_attribute=no
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include <stdio.h>
#ifdef STDC_HEADERS
# include <stdlib.h>
#else
# ifdef HAVE_STDLIB_H
# include <stdlib.h>
# endif
#endif
__attribute__((noreturn)) void f(int x) { printf("%d", x); exit(1); }
__attribute__((noreturn)) void f(int x) { printf("%d", x); }
]], [[
f(1);
]])],[ac_cv_c_noreturn_attribute="yes"],[ac_cv_c_noreturn_attribute="no"])
@@ -484,7 +473,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 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])
AC_CHECK_HEADERS([stdarg.h stdbool.h netinet/in.h netinet/tcp.h sys/param.h sys/select.h sys/socket.h sys/un.h sys/uio.h sys/resource.h arpa/inet.h syslog.h netdb.h sys/wait.h pwd.h glob.h grp.h login_cap.h winsock2.h ws2tcpip.h endian.h sys/endian.h libkern/OSByteOrder.h sys/ipc.h sys/shm.h ifaddrs.h poll.h],,, [AC_INCLUDES_DEFAULT])
# net/if.h portability for Darwin see:
# https://www.gnu.org/software/autoconf/manual/autoconf-2.69/html_node/Header-Portability.html
AC_CHECK_HEADERS([net/if.h],,, [
@@ -734,76 +723,6 @@ int main(void) {return 0;}
])
fi
if test x_$ub_have_pthreads != x_no; then
# Long checks to support pthread_setname_np().
# Some OSes have the extra non-portable functions in a specific
# header file.
AC_CHECK_HEADERS([pthread_np.h],,, [AC_INCLUDES_DEFAULT])
BAKCFLAGS="$CFLAGS"
CFLAGS="$CFLAGS -Werror"
# MacOS only has 1 argument, the name.
AC_MSG_CHECKING([whether pthread_setname_np has only 1 argument])
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([AC_INCLUDES_DEFAULT
#include <pthread.h>
#ifdef HAVE_PTHREAD_NP_H
#include <pthread_np.h>
#endif
],[
(void)pthread_setname_np("");
])],[
AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_PTHREAD_SETNAME_NP1, 1, [Define if pthread_setname_np has only 1 argument.])
],[
AC_MSG_RESULT(no)
])
# NetBSD has 3 arguments to allow for formatting of the name.
AC_MSG_CHECKING([whether pthread_setname_np has 3 arguments])
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([AC_INCLUDES_DEFAULT
#include <pthread.h>
#ifdef HAVE_PTHREAD_NP_H
#include <pthread_np.h>
#endif
],[
(void)pthread_setname_np(0, "", NULL);
])],[
AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_PTHREAD_SETNAME_NP3, 1, [Define if pthread_setname_np has 3 arguments.])
],[
AC_MSG_RESULT(no)
])
# Most OSes have the common 2 arguments, thread and name.
AC_MSG_CHECKING([whether pthread_setname_np has the common 2 arguments])
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([AC_INCLUDES_DEFAULT
#include <pthread.h>
#ifdef HAVE_PTHREAD_NP_H
#include <pthread_np.h>
#endif
],[
(void)pthread_setname_np(0, "");
])],[
AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_PTHREAD_SETNAME_NP, 1, [Define if pthread_setname_np has the common 2 arguments.])
],[
AC_MSG_RESULT(no)
])
# FreeBSD/OpenBSD use a slightly different function name.
AC_MSG_CHECKING([whether pthread_setname_np exists as pthread_set_name_np instead])
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([AC_INCLUDES_DEFAULT
#include <pthread.h>
#ifdef HAVE_PTHREAD_NP_H
#include <pthread_np.h>
#endif
],[
(void)pthread_set_name_np(0, "");
])],[
AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_PTHREAD_SET_NAME_NP, 1, [Define if pthread_setname_np exists as pthread_set_name_np instead.])
],[
AC_MSG_RESULT(no)
])
CFLAGS="$BAKCFLAGS"
fi
# check solaris thread library
AC_ARG_WITH(solaris-threads, AS_HELP_STRING([--with-solaris-threads],[use solaris native thread library.]), [ ],[ withval="no" ])
ub_have_sol_threads=no
@@ -1081,19 +1000,12 @@ 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 OPENSSL_cleanup])
AC_CHECK_FUNCS([OPENSSL_config EVP_sha1 EVP_sha256 EVP_sha512 FIPS_mode EVP_default_properties_is_fips_enabled EVP_MD_CTX_new OpenSSL_add_all_digests OPENSSL_init_crypto EVP_cleanup ENGINE_cleanup ERR_load_crypto_strings CRYPTO_cleanup_all_ex_data ERR_free_strings RAND_cleanup DSA_SIG_set0 EVP_dss1 EVP_DigestVerify EVP_aes_256_cbc EVP_EncryptInit_ex HMAC_Init_ex CRYPTO_THREADID_set_callback EVP_MAC_CTX_set_params OSSL_PARAM_BLD_new BIO_set_callback_ex SSL_CTX_set_tmp_ecdh HMAC_CTX_new EVP_MAC_CTX_new])
# 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 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
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])
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], [], [], [
@@ -1712,9 +1624,6 @@ 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" ])
@@ -1726,7 +1635,6 @@ 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
@@ -1748,22 +1656,6 @@ if test x_$withval = x_yes -o x_$withval != x_no; then
AC_MSG_RESULT(no)
])
AC_CHECK_DECL([CLOCK_MONOTONIC]
, []
, [AC_MSG_ERROR([ngtcp2 for QUIC needs at least CLOCK_MONOTONIC on the system])]
, [AC_INCLUDES_DEFAULT
#ifdef TIME_WITH_SYS_TIME
# include <sys/time.h>
# include <time.h>
#else
# ifdef HAVE_SYS_TIME_H
# include <sys/time.h>
# else
# include <time.h>
# endif
#endif
])
fi
# set static linking for uninstalled libraries if requested
@@ -1869,7 +1761,6 @@ if test $ac_cv_func_daemon = yes; then
])
fi
AC_CHECK_MEMBERS([struct stat.st_mtimensec, struct stat.st_mtim.tv_nsec])
AC_CHECK_MEMBERS([struct sockaddr_un.sun_len],,,[
AC_INCLUDES_DEFAULT
#ifdef HAVE_SYS_UN_H
@@ -1940,7 +1831,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 fnmatch 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 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])])
-2
View File
@@ -58,5 +58,3 @@ distribution but may be helpful.
* unbound.init_yocto: An init script to start and stop the server. Put it
in /etc/init.d/unbound to use it. It is for the Yocto Project, in
embedded systems, contributed by beni-sandu.
* gost12.patch: adds ECC-GOST12 support for the informational RFC9558.
Contributed by Igor V. Ruzanov.
-325
View File
@@ -1,325 +0,0 @@
diff --git a/sldns/keyraw.c b/sldns/keyraw.c
index 42a9262a3..cc6406a56 100644
--- a/sldns/keyraw.c
+++ b/sldns/keyraw.c
@@ -85,7 +85,7 @@ sldns_rr_dnskey_key_size_raw(const unsigned char* keydata,
}
break;
#ifdef USE_GOST
- case LDNS_ECC_GOST:
+ case LDNS_ECC_GOST12:
return 512;
#endif
#ifdef USE_ECDSA
@@ -146,7 +146,7 @@ sldns_key_EVP_load_gost_id(void)
if(gost_id) return gost_id;
/* see if configuration loaded gost implementation from other engine*/
- meth = EVP_PKEY_asn1_find_str(NULL, "gost2001", -1);
+ meth = EVP_PKEY_asn1_find_str(NULL, "gost2012_256", -1);
if(meth) {
EVP_PKEY_asn1_get0_info(&gost_id, NULL, NULL, NULL, NULL, meth);
return gost_id;
@@ -170,7 +170,7 @@ sldns_key_EVP_load_gost_id(void)
return 0;
}
- meth = EVP_PKEY_asn1_find_str(&e, "gost2001", -1);
+ meth = EVP_PKEY_asn1_find_str(&e, "gost2012_256", -1);
if(!meth) {
/* algo not found */
ENGINE_finish(e);
@@ -536,12 +536,17 @@ EVP_PKEY* sldns_key_rsa2pkey_raw(unsigned char* key, size_t len)
EVP_PKEY*
sldns_gost2pkey_raw(unsigned char* key, size_t keylen)
{
- /* prefix header for X509 encoding */
- uint8_t asn[37] = { 0x30, 0x63, 0x30, 0x1c, 0x06, 0x06, 0x2a, 0x85,
- 0x03, 0x02, 0x02, 0x13, 0x30, 0x12, 0x06, 0x07, 0x2a, 0x85,
- 0x03, 0x02, 0x02, 0x23, 0x01, 0x06, 0x07, 0x2a, 0x85, 0x03,
- 0x02, 0x02, 0x1e, 0x01, 0x03, 0x43, 0x00, 0x04, 0x40};
- unsigned char encoded[37+64];
+ /* prefix header for X509 encoding
+ *
+ * note: based on draft-makarenko-gost2012-dnssec-01 (pre-RFC9558 and it DOES work!)
+ * ASN1 header described in RFC9558 is not suitable due to d2i_PUBKEY() works with
+ * non-compressed public keys (two additional bytes 0x04, 0x40 at the end of header)
+ */
+ uint8_t asn[32] = { 0x30, 0x5e, 0x30, 0x17, 0x06, 0x08, 0x2a, 0x85,
+ 0x03, 0x07, 0x01, 0x01, 0x01, 0x01, 0x30, 0x0b,
+ 0x06, 0x09, 0x2a, 0x85, 0x03, 0x07, 0x01, 0x02,
+ 0x01, 0x01, 0x01, 0x03, 0x43, 0x00, 0x04, 0x40 };
+ unsigned char encoded[32+64];
const unsigned char* pp;
if(keylen != 64) {
/* key wrong size */
@@ -549,8 +554,8 @@ sldns_gost2pkey_raw(unsigned char* key, size_t keylen)
}
/* create evp_key */
- memmove(encoded, asn, 37);
- memmove(encoded+37, key, 64);
+ memmove(encoded, asn, 32);
+ memmove(encoded+32, key, 64);
pp = (unsigned char*)&encoded[0];
return d2i_PUBKEY(NULL, &pp, (int)sizeof(encoded));
diff --git a/sldns/rrdef.h b/sldns/rrdef.h
index bbc3d5b86..7d5f3c057 100644
--- a/sldns/rrdef.h
+++ b/sldns/rrdef.h
@@ -384,11 +384,12 @@ enum sldns_enum_algorithm
LDNS_RSASHA1_NSEC3 = 7,
LDNS_RSASHA256 = 8, /* RFC 5702 */
LDNS_RSASHA512 = 10, /* RFC 5702 */
- LDNS_ECC_GOST = 12, /* RFC 5933 */
+ LDNS_ECC_GOST = 12, /* RFC 5933, deprecated */
LDNS_ECDSAP256SHA256 = 13, /* RFC 6605 */
LDNS_ECDSAP384SHA384 = 14, /* RFC 6605 */
LDNS_ED25519 = 15, /* RFC 8080 */
LDNS_ED448 = 16, /* RFC 8080 */
+ LDNS_ECC_GOST12 = 23, /* RFC 9558 */
LDNS_INDIRECT = 252,
LDNS_PRIVATEDNS = 253,
LDNS_PRIVATEOID = 254
@@ -402,8 +403,9 @@ enum sldns_enum_hash
{
LDNS_SHA1 = 1, /* RFC 4034 */
LDNS_SHA256 = 2, /* RFC 4509 */
- LDNS_HASH_GOST = 3, /* RFC 5933 */
- LDNS_SHA384 = 4 /* RFC 6605 */
+ LDNS_HASH_GOST = 3, /* RFC 5933, deprecated */
+ LDNS_SHA384 = 4, /* RFC 6605 */
+ LDNS_HASH_GOST12 = 5 /* RFC 9558 */
};
typedef enum sldns_enum_hash sldns_hash;
diff --git a/sldns/wire2str.c b/sldns/wire2str.c
index 75b8f37b0..b4c4755e6 100644
--- a/sldns/wire2str.c
+++ b/sldns/wire2str.c
@@ -45,11 +45,12 @@ static sldns_lookup_table sldns_algorithms_data[] = {
{ LDNS_RSASHA1_NSEC3, "RSASHA1-NSEC3-SHA1" },
{ LDNS_RSASHA256, "RSASHA256"},
{ LDNS_RSASHA512, "RSASHA512"},
- { LDNS_ECC_GOST, "ECC-GOST"},
+ { LDNS_ECC_GOST, "ECC-GOST"}, /* deprecated */
{ LDNS_ECDSAP256SHA256, "ECDSAP256SHA256"},
{ LDNS_ECDSAP384SHA384, "ECDSAP384SHA384"},
{ LDNS_ED25519, "ED25519"},
{ LDNS_ED448, "ED448"},
+ { LDNS_ECC_GOST12, "ECC-GOST12"},
{ LDNS_INDIRECT, "INDIRECT" },
{ LDNS_PRIVATEDNS, "PRIVATEDNS" },
{ LDNS_PRIVATEOID, "PRIVATEOID" },
@@ -61,8 +62,9 @@ sldns_lookup_table* sldns_algorithms = sldns_algorithms_data;
static sldns_lookup_table sldns_hashes_data[] = {
{ LDNS_SHA1, "SHA1" },
{ LDNS_SHA256, "SHA256" },
- { LDNS_HASH_GOST, "HASH-GOST" },
+ { LDNS_HASH_GOST, "HASH-GOST" }, /* deprecated */
{ LDNS_SHA384, "SHA384" },
+ { LDNS_HASH_GOST12, "HASH-GOST12" },
{ 0, NULL }
};
sldns_lookup_table* sldns_hashes = sldns_hashes_data;
diff --git a/testcode/unitverify.c b/testcode/unitverify.c
index fcf2e2ffe..4a33e9f6a 100644
--- a/testcode/unitverify.c
+++ b/testcode/unitverify.c
@@ -696,7 +696,7 @@ verify_test(void)
#endif
#ifdef USE_GOST
if(sldns_key_EVP_load_gost_id())
- verifytest_file(SRCDIRSTR "/testdata/test_sigs.gost", "20090807060504");
+ verifytest_file(SRCDIRSTR "/testdata/test_sigs.gost12", "20251226060504");
else printf("Warning: skipped GOST, openssl does not provide gost.\n");
#endif
#ifdef USE_ECDSA
diff --git a/testdata/test_sigs.gost12 b/testdata/test_sigs.gost12
new file mode 100644
index 000000000..72a250cff
--- /dev/null
+++ b/testdata/test_sigs.gost12
@@ -0,0 +1,39 @@
+; Signature test file
+
+; first entry is a DNSKEY answer, with the DNSKEY rrset used for verification.
+; later entries are verified with it.
+
+; Test GOST signatures using algo number 23.
+
+ENTRY_BEGIN
+SECTION QUESTION
+nlnetlabs.nl. IN DNSKEY
+SECTION ANSWER
+nlnetlabs.nl. 3600 IN DNSKEY 256 3 23 cdOtkEcb6NhcdOpIbPYtWyWxdlUiKgtKQbYg3lIjtG7i3fYjUID9zyOgoQEiV9wuGCfrw5cNsnvNw+8HiVFK4g== ;{id = 12301 (zsk), size = 512b}
+ENTRY_END
+
+; entry to test
+ENTRY_BEGIN
+SECTION QUESTION
+open.nlnetlabs.nl. IN A
+SECTION ANSWER
+open.nlnetlabs.nl. 600 IN A 213.154.224.1
+open.nlnetlabs.nl. 600 IN RRSIG A 23 3 600 20260122084903 20251225084903 12301 nlnetlabs.nl. I12wYNs96DxMy26CWx296/sWMJAFg4nNXBo0sw7PnuMbJW5NFAmZYtFWhUdOWn4umaiodYOAmKG8Zg/OKvEtAQ==
+ENTRY_END
+
+ENTRY_BEGIN
+SECTION QUESTION
+open.nlnetlabs.nl. IN AAAA
+SECTION ANSWER
+open.nlnetlabs.nl. 600 IN AAAA 2001:7b8:206:1::1
+open.nlnetlabs.nl. 600 IN AAAA 2001:7b8:206:1::53
+open.nlnetlabs.nl. 600 IN RRSIG AAAA 23 3 600 20260122084903 20251225084903 12301 nlnetlabs.nl. J0jHa+CP8HM6UDa2+uYgaze2mfpJTh2hkZ2KwMTYb5sfL6iBmxxql0c/403Itk4fMfYBMGn7zfzDQ+CxnCgSWw==
+ENTRY_END
+
+ENTRY_BEGIN
+SECTION QUESTION
+open.nlnetlabs.nl. IN NSEC
+SECTION ANSWER
+open.nlnetlabs.nl. 86400 IN NSEC nlnetlabs.nl. A AAAA RRSIG NSEC
+open.nlnetlabs.nl. 86400 IN RRSIG NSEC 23 3 86400 20260122084903 20251225084903 12301 nlnetlabs.nl. INCLYe9vAaNYaYx5Ay3Q6QdX+wPW9sMRvVlGt/jUEGgCi+88QlV80CT1oHrhRI66I14Wk6NRAGZRNx1tUPSHSg==
+ENTRY_END
diff --git a/validator/val_secalgo.c b/validator/val_secalgo.c
index be8347b1b..4f621a309 100644
--- a/validator/val_secalgo.c
+++ b/validator/val_secalgo.c
@@ -246,10 +246,10 @@ ds_digest_size_supported(int algo)
return SHA256_DIGEST_LENGTH;
#endif
#ifdef USE_GOST
- case LDNS_HASH_GOST:
+ case LDNS_HASH_GOST12:
/* we support GOST if it can be loaded */
(void)sldns_key_EVP_load_gost_id();
- if(EVP_get_digestbyname("md_gost94"))
+ if(EVP_get_digestbyname("md_gost12_256"))
return 32;
else return 0;
#endif
@@ -265,9 +265,9 @@ ds_digest_size_supported(int algo)
#ifdef USE_GOST
/** Perform GOST hash */
static int
-do_gost94(unsigned char* data, size_t len, unsigned char* dest)
+do_gost12(unsigned char* data, size_t len, unsigned char* dest)
{
- const EVP_MD* md = EVP_get_digestbyname("md_gost94");
+ const EVP_MD* md = EVP_get_digestbyname("md_gost12_256");
if(!md)
return 0;
return sldns_digest_evp(data, (unsigned int)len, dest, md);
@@ -302,8 +302,8 @@ secalgo_ds_digest(int algo, unsigned char* buf, size_t len,
return 1;
#endif
#ifdef USE_GOST
- case LDNS_HASH_GOST:
- if(do_gost94(buf, len, res))
+ case LDNS_HASH_GOST12:
+ if(do_gost12(buf, len, res))
return 1;
break;
#endif
@@ -384,7 +384,7 @@ dnskey_algo_id_is_supported(int id)
#endif
#ifdef USE_GOST
- case LDNS_ECC_GOST:
+ case LDNS_ECC_GOST12:
/* we support GOST if it can be loaded */
return sldns_key_EVP_load_gost_id();
#endif
@@ -612,17 +612,17 @@ setup_key_digest(int algo, EVP_PKEY** evp_key, const EVP_MD** digest_type,
break;
#ifdef USE_GOST
- case LDNS_ECC_GOST:
+ case LDNS_ECC_GOST12:
*evp_key = sldns_gost2pkey_raw(key, keylen);
if(!*evp_key) {
verbose(VERB_QUERY, "verify: "
"sldns_gost2pkey_raw failed");
return 0;
}
- *digest_type = EVP_get_digestbyname("md_gost94");
+ *digest_type = EVP_get_digestbyname("md_gost12_256");
if(!*digest_type) {
verbose(VERB_QUERY, "verify: "
- "EVP_getdigest md_gost94 failed");
+ "EVP_getdigest md_gost12_256 failed");
return 0;
}
break;
@@ -964,7 +964,7 @@ ds_digest_size_supported(int algo)
return SHA384_LENGTH;
#endif
/* GOST not supported in NSS */
- case LDNS_HASH_GOST:
+ case LDNS_HASH_GOST12:
default: break;
}
return 0;
@@ -991,7 +991,7 @@ secalgo_ds_digest(int algo, unsigned char* buf, size_t len,
return HASH_HashBuf(HASH_AlgSHA384, res, buf, len)
== SECSuccess;
#endif
- case LDNS_HASH_GOST:
+ case LDNS_HASH_GOST12:
default:
verbose(VERB_QUERY, "unknown DS digest algorithm %d",
algo);
@@ -1031,7 +1031,7 @@ dnskey_algo_id_is_supported(int id)
case LDNS_ECDSAP384SHA384:
return PK11_TokenExists(CKM_ECDSA);
#endif
- case LDNS_ECC_GOST:
+ case LDNS_ECC_GOST12:
default:
return 0;
}
@@ -1352,7 +1352,7 @@ nss_setup_key_digest(int algo, SECKEYPublicKey** pubkey, HASH_HashType* htype,
/* no prefix for DSA verification */
break;
#endif /* USE_ECDSA */
- case LDNS_ECC_GOST:
+ case LDNS_ECC_GOST12:
default:
verbose(VERB_QUERY, "verify: unknown algorithm %d",
algo);
@@ -1675,7 +1675,7 @@ ds_digest_size_supported(int algo)
return SHA384_DIGEST_SIZE;
#endif
/* GOST not supported */
- case LDNS_HASH_GOST:
+ case LDNS_ECC_GOST12:
default:
break;
}
@@ -1700,7 +1700,7 @@ secalgo_ds_digest(int algo, unsigned char* buf, size_t len,
return _digest_nettle(SHA384_DIGEST_SIZE, buf, len, res);
#endif
- case LDNS_HASH_GOST:
+ case LDNS_ECC_GOST12:
default:
verbose(VERB_QUERY, "unknown DS digest algorithm %d",
algo);
@@ -1744,7 +1744,7 @@ dnskey_algo_id_is_supported(int id)
return 1;
#endif
case LDNS_RSAMD5: /* RFC 6725 deprecates RSAMD5 */
- case LDNS_ECC_GOST:
+ case LDNS_ECC_GOST12:
default:
return 0;
}
@@ -2103,7 +2103,7 @@ verify_canonrrset(sldns_buffer* buf, int algo, unsigned char* sigblock,
return sec_status_secure;
#endif
case LDNS_RSAMD5:
- case LDNS_ECC_GOST:
+ case LDNS_ECC_GOST12:
default:
*reason = "unable to verify signature, unknown algorithm";
return sec_status_bogus;
+2 -2
View File
@@ -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*4+2048];
char s[65535];
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(strcmp((char*)sldns_buffer_begin(buf), "BADRR") == 0) {
if(strncmp((char*)sldns_buffer_begin(buf), "BADRR\n", 6) == 0) {
*go_on = 0;
return 1;
}
+63 -340
View File
@@ -77,9 +77,9 @@
#include "util/storage/lookup3.h"
#include "util/storage/slabhash.h"
#include "util/tcp_conn_limit.h"
#include "util/allow_response_list.h"
#include "util/edns.h"
#include "services/listen_dnsport.h"
#include "services/outside_network.h"
#include "services/cache/rrset.h"
#include "services/cache/infra.h"
#include "services/localzone.h"
@@ -90,6 +90,7 @@
#include "util/random.h"
#include "util/tube.h"
#include "util/net_help.h"
#include "util/tsig.h"
#include "sldns/keyraw.h"
#include "respip/respip.h"
#include "iterator/iter_fwd.h"
@@ -200,267 +201,6 @@ signal_handling_playback(struct worker* wrk)
sig_record_reload = 0;
}
#ifdef HAVE_SSL
/* setup a listening ssl context, fatal_exit() on any failure */
static void
setup_listen_sslctx(void** ctx, int is_dot, int is_doh,
struct config_file* cfg, char* chroot)
{
char* key = cfg->ssl_service_key;
char* pem = cfg->ssl_service_pem;
if(chroot && strncmp(key, chroot, strlen(chroot)) == 0)
key += strlen(chroot);
if(chroot && pem && strncmp(pem, chroot, strlen(chroot)) == 0)
pem += strlen(chroot);
if(!(*ctx = listen_sslctx_create(key, pem, NULL,
cfg->tls_ciphers, cfg->tls_ciphersuites,
(cfg->tls_session_ticket_keys.first &&
cfg->tls_session_ticket_keys.first->str[0] != 0),
is_dot, is_doh, cfg->tls_protocols))) {
log_err("could not set up listen SSL_CTX");
*ctx = NULL;
}
}
#endif /* HAVE_SSL */
#ifdef HAVE_SSL
void* daemon_setup_listen_dot_sslctx(struct daemon* daemon,
struct config_file* cfg)
{
void* ctx;
(void)setup_listen_sslctx(&ctx, 1, 0, cfg, daemon->chroot);
return ctx;
}
#endif /* HAVE_SSL */
#ifdef HAVE_SSL
#ifdef HAVE_NGHTTP2_NGHTTP2_H
void* daemon_setup_listen_doh_sslctx(struct daemon* daemon,
struct config_file* cfg)
{
void* ctx;
(void)setup_listen_sslctx(&ctx, 0, 1, cfg, daemon->chroot);
return ctx;
}
#endif /* HAVE_NGHTTP2_NGHTTP2_H */
#endif /* HAVE_SSL */
#ifdef HAVE_SSL
#ifdef HAVE_NGTCP2
void* daemon_setup_listen_quic_sslctx(struct daemon* daemon,
struct config_file* cfg)
{
void* ctx;
char* chroot = daemon->chroot;
char* key = cfg->ssl_service_key;
char* pem = cfg->ssl_service_pem;
if(chroot && strncmp(key, chroot, strlen(chroot)) == 0)
key += strlen(chroot);
if(chroot && pem && strncmp(pem, chroot, strlen(chroot)) == 0)
pem += strlen(chroot);
if(!(ctx = quic_sslctx_create(key, pem, NULL))) {
log_err("could not set up quic SSL_CTX");
return NULL;
}
return ctx;
}
#endif /* HAVE_NGTCP2 */
#endif /* HAVE_SSL */
#ifdef HAVE_SSL
void* daemon_setup_connect_dot_sslctx(struct daemon* daemon,
struct config_file* cfg)
{
void* ctx;
char* bundle, *chroot = daemon->chroot;
bundle = cfg->tls_cert_bundle;
if(chroot && bundle && strncmp(bundle, chroot, strlen(chroot)) == 0)
bundle += strlen(chroot);
if(!(ctx = connect_sslctx_create(NULL, NULL, bundle,
cfg->tls_win_cert))) {
log_err("could not set up connect SSL_CTX");
return NULL;
}
return ctx;
}
#endif /* HAVE_SSL */
/* setups the needed ssl contexts, fatal_exit() on any failure */
void
daemon_setup_sslctxs(struct daemon* daemon, struct config_file* cfg)
{
#ifdef HAVE_SSL
char* chroot = daemon->chroot;
if(cfg->ssl_service_key && cfg->ssl_service_key[0]) {
char* key = cfg->ssl_service_key;
char* pem = cfg->ssl_service_pem;
if(chroot && strncmp(key, chroot, strlen(chroot)) == 0)
key += strlen(chroot);
if(chroot && pem && strncmp(pem, chroot, strlen(chroot)) == 0)
pem += strlen(chroot);
/* setup the session keys; the callback to use them will be
* attached to each sslctx separately */
if(cfg->tls_session_ticket_keys.first &&
cfg->tls_session_ticket_keys.first->str[0] != 0) {
if(!listen_sslctx_setup_ticket_keys(
cfg->tls_session_ticket_keys.first, chroot)) {
fatal_exit("could not set session ticket SSL_CTX");
}
}
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 */
/* Store the file name and mtime to detect changes later. */
daemon->ssl_service_key = strdup(cfg->ssl_service_key);
if(!daemon->ssl_service_key)
fatal_exit("could not setup ssl ctx: out of memory");
if(cfg->ssl_service_pem) {
daemon->ssl_service_pem = strdup(cfg->ssl_service_pem);
if(!daemon->ssl_service_pem)
fatal_exit("could not setup ssl ctx: out of memory");
} else {
daemon->ssl_service_pem = NULL;
}
if(!file_get_mtime(key,
&daemon->mtime_ssl_service_key,
&daemon->mtime_ns_ssl_service_key, NULL))
log_err("Could not stat(%s): %s",
key, strerror(errno));
if(pem) {
if(!file_get_mtime(pem,
&daemon->mtime_ssl_service_pem,
&daemon->mtime_ns_ssl_service_pem, NULL))
log_err("Could not stat(%s): %s",
pem, strerror(errno));
} else {
daemon->mtime_ssl_service_pem = 0;
daemon->mtime_ns_ssl_service_pem = 0;
}
}
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 */
}
/** Delete the ssl ctxs */
static void
daemon_delete_sslctxs(struct daemon* daemon)
{
#ifdef HAVE_SSL
listen_sslctx_delete_ticket_keys();
SSL_CTX_free((SSL_CTX*)daemon->listen_dot_sslctx);
daemon->listen_dot_sslctx = NULL;
SSL_CTX_free((SSL_CTX*)daemon->listen_doh_sslctx);
daemon->listen_doh_sslctx = NULL;
SSL_CTX_free((SSL_CTX*)daemon->connect_dot_sslctx);
daemon->connect_dot_sslctx = NULL;
free(daemon->ssl_service_key);
daemon->ssl_service_key = NULL;
free(daemon->ssl_service_pem);
daemon->ssl_service_pem = NULL;
#else
(void)daemon;
#endif
#ifdef HAVE_NGTCP2
SSL_CTX_free((SSL_CTX*)daemon->listen_quic_sslctx);
daemon->listen_quic_sslctx = NULL;
#endif
}
int
ssl_cert_changed(struct daemon* daemon, struct config_file* cfg)
{
time_t mtime = 0;
long ns = 0;
char* chroot = daemon->chroot;
char* key = cfg->ssl_service_key;
char* pem = cfg->ssl_service_pem;
log_assert(daemon->ssl_service_key && cfg->ssl_service_key);
if(chroot && strncmp(key, chroot, strlen(chroot)) == 0)
key += strlen(chroot);
if(chroot && pem && strncmp(pem, chroot, strlen(chroot)) == 0)
pem += strlen(chroot);
if(strcmp(daemon->ssl_service_key, cfg->ssl_service_key) != 0)
return 1;
if(daemon->ssl_service_pem && cfg->ssl_service_pem &&
strcmp(daemon->ssl_service_pem, cfg->ssl_service_pem) != 0)
return 1;
if(!file_get_mtime(key, &mtime, &ns, NULL)) {
log_err("Could not stat(%s): %s",
key, strerror(errno));
/* It has probably changed, but file read is likely going to
* fail. */
return 0;
}
if(mtime != daemon->mtime_ssl_service_key ||
ns != daemon->mtime_ns_ssl_service_key)
return 1;
if(pem) {
if(!file_get_mtime(pem, &mtime, &ns, NULL)) {
log_err("Could not stat(%s): %s",
pem, strerror(errno));
/* It has probably changed, but file read is likely going to
* fail. */
return 0;
}
if(mtime != daemon->mtime_ssl_service_pem ||
ns != daemon->mtime_ns_ssl_service_pem)
return 1;
}
return 0;
}
/** Reload the sslctxs if they have changed */
static void
daemon_reload_sslctxs(struct daemon* daemon)
{
#ifdef HAVE_SSL
if(daemon->cfg->ssl_service_key && daemon->cfg->ssl_service_key[0]) {
/* See if changed */
if(!daemon->ssl_service_key ||
ssl_cert_changed(daemon,daemon->cfg)) {
verbose(VERB_ALGO, "Reloading certificates");
daemon_delete_sslctxs(daemon);
daemon_setup_sslctxs(daemon, daemon->cfg);
}
} else {
/* See if sslctxs are removed from config. */
if(daemon->ssl_service_key) {
verbose(VERB_ALGO, "Removing certificates");
daemon_delete_sslctxs(daemon);
}
}
#else
(void)daemon;
#endif
}
struct daemon*
daemon_init(void)
{
@@ -497,11 +237,7 @@ daemon_init(void)
# else
OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS
| OPENSSL_INIT_ADD_ALL_DIGESTS
| OPENSSL_INIT_LOAD_CRYPTO_STRINGS
# if defined(OPENSSL_INIT_NO_LOAD_CONFIG) && defined(UB_ON_WINDOWS)
| OPENSSL_INIT_NO_LOAD_CONFIG
# endif
, NULL);
| OPENSSL_INIT_LOAD_CRYPTO_STRINGS, NULL);
# endif
# if HAVE_DECL_SSL_COMP_GET_COMPRESSION_METHODS
/* grab the COMP method ptr because openssl leaks it */
@@ -510,11 +246,7 @@ daemon_init(void)
# if OPENSSL_VERSION_NUMBER < 0x10100000 || !defined(HAVE_OPENSSL_INIT_SSL)
(void)SSL_library_init();
# else
(void)OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS
# if defined(OPENSSL_INIT_NO_LOAD_CONFIG) && defined(UB_ON_WINDOWS)
| OPENSSL_INIT_NO_LOAD_CONFIG
# endif
, NULL);
(void)OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS, NULL);
# endif
# if defined(HAVE_SSL) && defined(OPENSSL_THREADS) && !defined(THREADS_DISABLED)
if(!ub_openssl_lock_init())
@@ -567,6 +299,16 @@ daemon_init(void)
free(daemon);
return NULL;
}
daemon->arl = arl_list_create();
if(!daemon->arl) {
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;
}
listen_setup_locks();
if(gettimeofday(&daemon->time_boot, NULL) < 0)
log_err("gettimeofday: %s", strerror(errno));
@@ -575,6 +317,7 @@ daemon_init(void)
acl_list_delete(daemon->acl_interface);
acl_list_delete(daemon->acl);
tcl_list_delete(daemon->tcl);
arl_list_delete(daemon->arl);
edns_known_options_delete(daemon->env);
free(daemon->env);
free(daemon);
@@ -585,11 +328,24 @@ daemon_init(void)
acl_list_delete(daemon->acl_interface);
acl_list_delete(daemon->acl);
tcl_list_delete(daemon->tcl);
arl_list_delete(daemon->arl);
edns_known_options_delete(daemon->env);
free(daemon->env);
free(daemon);
return NULL;
}
if(!(daemon->env->tsig_key_table = tsig_key_table_create())) {
auth_zones_delete(daemon->env->auth_zones);
acl_list_delete(daemon->acl_interface);
acl_list_delete(daemon->acl);
tcl_list_delete(daemon->tcl);
arl_list_delete(daemon->arl);
edns_known_options_delete(daemon->env);
edns_strings_delete(daemon->env->edns_strings);
free(daemon->env);
free(daemon);
return NULL;
}
return daemon;
}
@@ -826,17 +582,11 @@ daemon_create_workers(struct daemon* daemon)
fatal_exit("out of memory during daemon init");
numport = daemon_get_shufport(daemon, shufport);
verbose(VERB_ALGO, "total of %d outgoing ports available", numport);
if(!(daemon->shared_ports = shared_ports_create(daemon->cfg->out_ifs,
daemon->cfg->num_out_ifs, daemon->cfg->do_ip4,
daemon->cfg->do_ip6, shufport, numport)))
fatal_exit("could not setup shared ports: out of memory");
#ifdef HAVE_NGTCP2
if (cfg_has_quic(daemon->cfg)) {
daemon->doq_table = doq_table_create(daemon->cfg, daemon->rand);
if(!daemon->doq_table)
fatal_exit("could not create doq_table: out of memory");
}
daemon->doq_table = doq_table_create(daemon->cfg, daemon->rand);
if(!daemon->doq_table)
fatal_exit("could not create doq_table: out of memory");
#endif
daemon->num = (daemon->cfg->num_threads?daemon->cfg->num_threads:1);
@@ -860,7 +610,10 @@ daemon_create_workers(struct daemon* daemon)
#endif
}
for(i=0; i<daemon->num; i++) {
if(!(daemon->workers[i] = worker_create(daemon, i)))
if(!(daemon->workers[i] = worker_create(daemon, i,
shufport+numport*i/daemon->num,
numport*(i+1)/daemon->num - numport*i/daemon->num)))
/* the above is not ports/numthr, due to rounding */
fatal_exit("could not create worker");
}
/* create per-worker alloc caches if not reusing existing ones. */
@@ -904,25 +657,6 @@ static void close_other_pipes(struct daemon* daemon, int thr)
}
#endif /* THREADS_DISABLED */
/**
* Function to set the thread local log ID.
* Either the internal thread number, or the LWP ID on Linux based on
* configuration.
*/
static void
set_log_thread_id(struct worker* worker, struct config_file* cfg)
{
(void)cfg;
log_assert(worker);
#if defined(HAVE_GETTID) && !defined(THREADS_DISABLED)
worker->thread_tid = gettid();
if(cfg->log_thread_id)
log_thread_set(&worker->thread_tid);
else
#endif
log_thread_set(&worker->thread_num);
}
/**
* Function to start one thread.
* @param arg: user argument.
@@ -933,15 +667,7 @@ thread_start(void* arg)
{
struct worker* worker = (struct worker*)arg;
int port_num = 0;
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);
/* 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);
}
log_thread_set(&worker->thread_num);
ub_thread_blocksigs();
#ifdef THREADS_DISABLED
/* close pipe ends used by main */
@@ -955,9 +681,8 @@ 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;
@@ -1017,7 +742,6 @@ daemon_fork(struct daemon* daemon)
#endif
log_assert(daemon);
daemon_reload_sslctxs(daemon);
if(!(daemon->env->views = views_create()))
fatal_exit("Could not create views: out of memory");
/* create individual views and their localzone/data trees */
@@ -1031,6 +755,8 @@ daemon_fork(struct daemon* daemon)
fatal_exit("Could not setup interface control list");
if(!tcl_list_apply_cfg(daemon->tcl, daemon->cfg))
fatal_exit("Could not setup TCP connection limits");
if(!arl_list_apply_cfg(daemon->arl, daemon->cfg))
fatal_exit("Could not setup allow response list");
if(daemon->cfg->dnscrypt) {
#ifdef USE_DNSCRYPT
daemon->dnscenv = dnsc_create();
@@ -1073,12 +799,17 @@ daemon_fork(struct daemon* daemon)
daemon->use_response_ip = !respip_set_is_empty(
daemon->env->respip_set) || have_view_respip_cfg;
/* setup tsig keys */
if(!tsig_key_table_apply_cfg(daemon->env->tsig_key_table, daemon->cfg))
fatal_exit("Could not set up TSIG keys");
/* setup modules */
daemon_setup_modules(daemon);
/* read auth zonefiles */
if(!auth_zones_apply_cfg(daemon->env->auth_zones, daemon->cfg, 1,
&daemon->use_rpz, daemon->env, &daemon->mods))
&daemon->use_rpz, daemon->env, &daemon->mods,
daemon->env->tsig_key_table))
fatal_exit("auth_zones could not be setup");
/* Set-up EDNS strings */
@@ -1103,25 +834,14 @@ daemon_fork(struct daemon* daemon)
fatal_exit("RPZ requires the respip module");
/* first create all the worker structures, so we can pass
* them to the newly created threads.
* them to the newly created threads.
*/
daemon_create_workers(daemon);
/* Set it for the first (main) worker since it does not take part in
* the thread_start() procedure.
*/
set_log_thread_id(daemon->workers[0], daemon->cfg);
/* If shm stats need an offset, calculate it */
if(daemon->cfg->shm_enable && daemon->cfg->stat_interval > 0) {
daemon->stat_time_specific = 1;
daemon->stat_time_offset =
((int)time(NULL))%daemon->cfg->stat_interval;
}
#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.
@@ -1134,9 +854,8 @@ 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]);
@@ -1180,6 +899,7 @@ 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
@@ -1221,8 +941,6 @@ daemon_cleanup(struct daemon* daemon)
if(!daemon->reuse_cache || daemon->need_to_exit)
daemon_clear_allocs(daemon);
daemon->num = 0;
shared_ports_delete(daemon->shared_ports);
daemon->shared_ports = NULL;
#ifdef USE_DNSTAP
dt_delete(daemon->dtenv);
daemon->dtenv = NULL;
@@ -1232,10 +950,8 @@ daemon_cleanup(struct daemon* daemon)
daemon->dnscenv = NULL;
#endif
#ifdef HAVE_NGTCP2
if (daemon->doq_table) {
doq_table_delete(daemon->doq_table);
daemon->doq_table = NULL;
}
doq_table_delete(daemon->doq_table);
daemon->doq_table = NULL;
#endif
daemon->cfg = NULL;
}
@@ -1261,19 +977,29 @@ daemon_delete(struct daemon* daemon)
edns_known_options_delete(daemon->env);
edns_strings_delete(daemon->env->edns_strings);
auth_zones_delete(daemon->env->auth_zones);
tsig_key_table_delete(daemon->env->tsig_key_table);
}
ub_randfree(daemon->rand);
alloc_clear(&daemon->superalloc);
acl_list_delete(daemon->acl);
acl_list_delete(daemon->acl_interface);
tcl_list_delete(daemon->tcl);
arl_list_delete(daemon->arl);
cookie_secrets_delete(daemon->cookie_secrets);
listen_desetup_locks();
free(daemon->chroot);
free(daemon->pidfile);
free(daemon->cfgfile);
free(daemon->env);
daemon_delete_sslctxs(daemon);
#ifdef HAVE_SSL
listen_sslctx_delete_ticket_keys();
SSL_CTX_free((SSL_CTX*)daemon->listen_dot_sslctx);
SSL_CTX_free((SSL_CTX*)daemon->listen_doh_sslctx);
SSL_CTX_free((SSL_CTX*)daemon->connect_dot_sslctx);
#endif
#ifdef HAVE_NGTCP2
SSL_CTX_free((SSL_CTX*)daemon->listen_quic_sslctx);
#endif
free(daemon);
/* lex cleanup */
ub_c_lex_destroy();
@@ -1285,7 +1011,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(*)(SSL_COMP*))CRYPTO_free);
sk_SSL_COMP_pop_free(comp_meth, (void(*)())CRYPTO_free);
# endif
# endif
# endif
@@ -1308,9 +1034,6 @@ 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
+2 -44
View File
@@ -62,7 +62,6 @@ struct doq_table;
struct cookie_secrets;
struct fast_reload_thread;
struct fast_reload_printq;
struct shared_ports;
#include "dnstap/dnstap_config.h"
#ifdef USE_DNSTAP
@@ -98,8 +97,6 @@ struct daemon {
int rc_port;
/** listening ports for remote control */
struct listen_port* rc_ports;
/** the shared ports structure, with random ports numbers. */
struct shared_ports* shared_ports;
/** remote control connections management (for first worker) */
struct daemon_remote* rc;
/** ssl context for listening to dnstcp over ssl */
@@ -110,18 +107,6 @@ struct daemon {
void* listen_doh_sslctx;
/** ssl context for listening to quic */
void* listen_quic_sslctx;
/** the file name that the ssl context is made with, private key. */
char* ssl_service_key;
/** the file name that the ssl context is made with, certificate. */
char* ssl_service_pem;
/** modification time for ssl_service_key, in sec and ns. Like
* in a struct timespec, but without that for portability. */
time_t mtime_ssl_service_key;
long mtime_ns_ssl_service_key;
/** modification time for ssl_service_pem, in sec and ns. Like
* in a struct timespec, but without that for portability. */
time_t mtime_ssl_service_pem;
long mtime_ns_ssl_service_pem;
/** num threads allocated */
int num;
/** num threads allocated in the previous config or 0 at first */
@@ -148,6 +133,8 @@ struct daemon {
struct acl_list* acl_interface;
/** TCP connection limit, limit connections from client IPs */
struct tcl_list* tcl;
/** allow response list, to cache responses send by client IPs */
struct arl_list* arl;
/** local authority zones */
struct local_zones* local_zones;
/** last time of statistics printout */
@@ -158,14 +145,7 @@ struct daemon {
/** the dnstap environment master value, copied and changed by threads*/
struct dt_env* dtenv;
#endif
/** The SHM info for shared memory stats. */
struct shm_main_info* shm_info;
/** if the timeout for statistics is attempted at specific offset.
* If it is true, the stat timeout is the interval+offset, and that
* picks (roughly) the same time offset every time period. */
int stat_time_specific;
/** if the timeout is specific, what offset in the period. */
int stat_time_offset;
/** some response-ip tags or actions are configured if true */
int use_response_ip;
/** some RPZ policies are configured */
@@ -251,26 +231,4 @@ void daemon_apply_cfg(struct daemon* daemon, struct config_file* cfg);
*/
int setup_acl_for_ports(struct acl_list* list, struct listen_port* port_list);
/* setups the needed ssl contexts, fatal_exit() on any failure */
void daemon_setup_sslctxs(struct daemon* daemon, struct config_file* cfg);
/** See if the SSL cert files have changed */
int ssl_cert_changed(struct daemon* daemon, struct config_file* cfg);
/** Setup the listening DoT SSL_CTX, returns the ssl ctx. */
void* daemon_setup_listen_dot_sslctx(struct daemon* daemon,
struct config_file* cfg);
/** Setup the listening DoH SSL_CTX, returns the ssl ctx. */
void* daemon_setup_listen_doh_sslctx(struct daemon* daemon,
struct config_file* cfg);
/** Setup the listening Quic SSL_CTX, returns the ssl ctx */
void* daemon_setup_listen_quic_sslctx(struct daemon* daemon,
struct config_file* cfg);
/** Setup the connect DoT SSL_CTX, returns the ssl ctx */
void* daemon_setup_connect_dot_sslctx(struct daemon* daemon,
struct config_file* cfg);
#endif /* DAEMON_H */
+68 -574
View File
@@ -97,7 +97,9 @@
#include "sldns/sbuffer.h"
#include "util/timeval_func.h"
#include "util/tcp_conn_limit.h"
#include "util/allow_response_list.h"
#include "util/edns.h"
#include "util/tsig.h"
#ifdef USE_CACHEDB
#include "cachedb/cachedb.h"
#endif
@@ -153,7 +155,7 @@ remote_setup_ctx(struct daemon_remote* rc, struct config_file* cfg)
log_crypto_err("could not SSL_CTX_new");
return 0;
}
if(!listen_sslctx_setup(rc->ctx, cfg->tls_protocols)) {
if(!listen_sslctx_setup(rc->ctx, cfg->tls_use_system_policy_versions)) {
return 0;
}
@@ -307,26 +309,6 @@ add_open(const char* ip, int nr, struct listen_port** list, int noproto_is_err,
#endif
}
} else {
const char* s = strchr(ip, '@');
char newif[128];
if(s) {
/* override port with ifspec@port */
int portnr;
if((size_t)(s-ip) >= sizeof(newif)) {
log_err("ifname too long: %s", ip);
return -1;
}
portnr = atoi(s+1);
if(portnr < 0 || 0 == portnr || portnr > 65535) {
log_err("invalid portnumber in control-interface: %s", ip);
return -1;
}
(void)strlcpy(newif, ip, sizeof(newif));
newif[s-ip] = 0;
ip = newif;
snprintf(port, sizeof(port), "%d", portnr);
port[sizeof(port)-1]=0;
}
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST;
if((r = getaddrinfo(ip, port, &hints, &res)) != 0 || !res) {
@@ -821,8 +803,6 @@ print_stats(RES* ssl, const char* nm, struct ub_stats_info* s)
(unsigned long)s->svr.num_queries_cookie_invalid)) return 0;
if(!ssl_printf(ssl, "%s.num.queries_discard_timeout"SQ"%lu\n", nm,
(unsigned long)s->svr.num_queries_discard_timeout)) return 0;
if(!ssl_printf(ssl, "%s.num.queries_replyaddr_limit"SQ"%lu\n", nm,
(unsigned long)s->svr.num_queries_replyaddr_limit)) return 0;
if(!ssl_printf(ssl, "%s.num.queries_wait_limit"SQ"%lu\n", nm,
(unsigned long)s->svr.num_queries_wait_limit)) return 0;
if(!ssl_printf(ssl, "%s.num.cachehits"SQ"%lu\n", nm,
@@ -867,8 +847,6 @@ print_stats(RES* ssl, const char* nm, struct ub_stats_info* s)
(unsigned long)s->mesh_num_states)) return 0;
if(!ssl_printf(ssl, "%s.requestlist.current.user"SQ"%lu\n", nm,
(unsigned long)s->mesh_num_reply_states)) return 0;
if(!ssl_printf(ssl, "%s.requestlist.current.replies"SQ"%lu\n", nm,
(unsigned long)s->mesh_num_reply_addrs)) return 0;
#ifndef S_SPLINT_S
sumwait.tv_sec = s->mesh_replies_sum_wait_sec;
sumwait.tv_usec = s->mesh_replies_sum_wait_usec;
@@ -1533,95 +1511,18 @@ 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 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));
uint8_t* nm;
int nmlabs;
size_t nmlen;
if(!parse_arg_name(ssl, arg, &nm, &nmlen, &nmlabs))
return 0;
}
/* handle the rr case */
if (!perform_data_remove_rr(ssl, zones, rr, len, dname_len, arg))
return 0;
local_zones_del_data(zones, nm,
nmlen, nmlabs, LDNS_RR_CLASS_IN);
free(nm);
return 1;
}
@@ -1735,14 +1636,6 @@ do_view_data_add(RES* ssl, struct worker* worker, char* arg)
ssl_printf(ssl,"error out of memory\n");
return;
}
if(!v->isfirst) {
/* Global local-zone is not used for this view,
* therefore add defaults to this view-specific
* local-zone. */
struct config_file lz_cfg;
memset(&lz_cfg, 0, sizeof(lz_cfg));
local_zone_enter_defaults(v->local_zones, &lz_cfg);
}
}
do_data_add(ssl, v->local_zones, arg2);
lock_rw_unlock(&v->lock);
@@ -1768,14 +1661,6 @@ do_view_datas_add(struct daemon_remote* rc, RES* ssl, struct worker* worker,
ssl_printf(ssl,"error out of memory\n");
return;
}
if(!v->isfirst) {
/* Global local-zone is not used for this view,
* therefore add defaults to this view-specific
* local-zone. */
struct config_file lz_cfg;
memset(&lz_cfg, 0, sizeof(lz_cfg));
local_zone_enter_defaults(v->local_zones, &lz_cfg);
}
}
/* put the view name in the command buf */
(void)snprintf(buf+strlen(buf), sizeof(buf)-strlen(buf), "%s ", arg);
@@ -2392,9 +2277,6 @@ 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++;
}
}
@@ -3318,10 +3200,6 @@ 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);
@@ -3333,7 +3211,6 @@ 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);
@@ -4754,26 +4631,6 @@ fr_init_time(struct timeval* time_start, struct timeval* time_read,
* are kept in here. They can then be deleted.
*/
struct fast_reload_construct {
/** ssl context for listening to dnstcp over ssl */
void* listen_dot_sslctx;
/** ssl context for connecting to dnstcp over ssl */
void* connect_dot_sslctx;
/** ssl context for listening to DoH */
void* listen_doh_sslctx;
/** ssl context for listening to quic */
void* listen_quic_sslctx;
/** the file name that the ssl context is made with, private key. */
char* ssl_service_key;
/** the file name that the ssl context is made with, certificate. */
char* ssl_service_pem;
/** modification time for ssl_service_key, in sec and ns. Like
* in a struct timespec, but without that for portability. */
time_t mtime_ssl_service_key;
long mtime_ns_ssl_service_key;
/** modification time for ssl_service_pem, in sec and ns. Like
* in a struct timespec, but without that for portability. */
time_t mtime_ssl_service_pem;
long mtime_ns_ssl_service_pem;
/** construct for views */
struct views* views;
/** construct for auth zones */
@@ -4790,6 +4647,10 @@ struct fast_reload_construct {
struct acl_list* acl_interface;
/** construct for tcp connection limit */
struct tcl_list* tcl;
/** construct for allow response list */
struct arl_list* arl;
/** tsig key table */
struct tsig_key_table* tsig_key_table;
/** construct for local zones */
struct local_zones* local_zones;
/** if there is response ip configuration in use */
@@ -5026,74 +4887,6 @@ 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)
@@ -5145,7 +4938,9 @@ fr_check_compat_cfg(struct fast_reload_thread* fr, struct config_file* newcfg)
FR_CHECK_CHANGED_CFG("http_notls_downstream", http_notls_downstream, changed_str);
FR_CHECK_CHANGED_CFG("https-port", https_port, changed_str);
FR_CHECK_CHANGED_CFG("tls-port", ssl_port, changed_str);
FR_CHECK_CHANGED_CFG_STR("tls-protocols", tls_protocols, changed_str);
FR_CHECK_CHANGED_CFG_STR("tls-service-key", ssl_service_key, changed_str);
FR_CHECK_CHANGED_CFG_STR("tls-service-pem", ssl_service_pem, changed_str);
FR_CHECK_CHANGED_CFG_STR("tls-cert-bundle", tls_cert_bundle, changed_str);
FR_CHECK_CHANGED_CFG_STRLIST("proxy-protocol-port", proxy_protocol_port, changed_str);
FR_CHECK_CHANGED_CFG_STRLIST("tls-additional-port", tls_additional_port, changed_str);
FR_CHECK_CHANGED_CFG_STR("interface-automatic-ports", if_automatic_ports, changed_str);
@@ -5242,6 +5037,8 @@ fr_construct_clear(struct fast_reload_construct* ct)
acl_list_delete(ct->acl);
acl_list_delete(ct->acl_interface);
tcl_list_delete(ct->tcl);
arl_list_delete(ct->arl);
tsig_key_table_delete(ct->tsig_key_table);
edns_strings_delete(ct->edns_strings);
anchors_delete(ct->anchors);
views_delete(ct->views);
@@ -5254,19 +5051,6 @@ fr_construct_clear(struct fast_reload_construct* ct)
wait_limits_free(&ct->wait_limits_netblock);
wait_limits_free(&ct->wait_limits_cookie_netblock);
domain_limits_free(&ct->domain_limits);
#ifdef HAVE_SSL
/* The SSL contexts can be SSL_CTX_free here. It is reference
* counted. So ongoing transfers with can continue.
* Once they are done, the context is freed. */
SSL_CTX_free((SSL_CTX*)ct->listen_dot_sslctx);
SSL_CTX_free((SSL_CTX*)ct->connect_dot_sslctx);
SSL_CTX_free((SSL_CTX*)ct->listen_doh_sslctx);
#endif /* HAVE_SSL */
#ifdef HAVE_NGTCP2
SSL_CTX_free((SSL_CTX*)ct->listen_quic_sslctx);
#endif
free(ct->ssl_service_key);
free(ct->ssl_service_pem);
/* Delete the log identity here so that the global value is not
* reset by config_delete. */
if(ct->oldcfg && ct->oldcfg->log_identity) {
@@ -5357,6 +5141,8 @@ getmem_config_auth(struct config_auth* p)
+ getmem_config_strlist(s->masters)
+ getmem_config_strlist(s->urls)
+ getmem_config_strlist(s->allow_notify)
+ getmem_config_str2list(s->masters_tsig)
+ getmem_config_str2list(s->allow_notify_tsig)
+ getmem_str(s->zonefile)
+ s->rpz_taglistlen
+ getmem_str(s->rpz_action_override)
@@ -5399,7 +5185,6 @@ config_file_getmem(struct config_file* cfg)
m += getmem_config_strlist(cfg->tls_session_ticket_keys.first);
m += getmem_str(cfg->tls_ciphers);
m += getmem_str(cfg->tls_ciphersuites);
m += getmem_str(cfg->tls_protocols);
m += getmem_str(cfg->http_endpoint);
m += (cfg->outgoing_avail_ports?65536*sizeof(int):0);
m += getmem_str(cfg->target_fetch_policy);
@@ -5452,6 +5237,7 @@ config_file_getmem(struct config_file* cfg)
m += getmem_config_str3list(cfg->acl_tag_datas);
m += getmem_config_str2list(cfg->acl_view);
m += getmem_config_str2list(cfg->interface_actions);
m += getmem_config_str2list(cfg->allow_response_list);
m += getmem_config_strbytelist(cfg->interface_tags);
m += getmem_config_str3list(cfg->interface_tag_actions);
m += getmem_config_str3list(cfg->interface_tag_datas);
@@ -5516,17 +5302,17 @@ fr_printmem(struct fast_reload_thread* fr,
size_t mem = 0;
if(fr_poll_for_quit(fr))
return 1;
mem += getmem_str(ct->ssl_service_key);
mem += getmem_str(ct->ssl_service_pem);
mem += views_get_mem(ct->views);
mem += respip_set_get_mem(ct->respip_set);
mem += auth_zones_get_mem(ct->auth_zones);
mem += forwards_get_mem(ct->fwds);
mem += hints_get_mem(ct->hints);
mem += tsig_key_table_get_mem(ct->tsig_key_table);
mem += local_zones_get_mem(ct->local_zones);
mem += acl_list_get_mem(ct->acl);
mem += acl_list_get_mem(ct->acl_interface);
mem += tcl_list_get_mem(ct->tcl);
mem += arl_list_get_mem(ct->arl);
mem += edns_strings_get_mem(ct->edns_strings);
mem += anchors_get_mem(ct->anchors);
mem += sizeof(*ct->oldcfg);
@@ -5611,6 +5397,12 @@ xfr_auth_master_equal(struct auth_master* m1, struct auth_master* m2)
return 0;
if(m1->port != m2->port)
return 0;
if((m1->tsig_key_name && !m2->tsig_key_name) || (!m1->tsig_key_name && m2->tsig_key_name))
return 0;
if(m1->tsig_key_name && m2->tsig_key_name && strcmp(m1->tsig_key_name, m2->tsig_key_name) != 0)
return 0;
return 1;
}
@@ -5630,23 +5422,6 @@ 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)
@@ -5735,31 +5510,8 @@ 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_config_equal(old_xfr, new_xfr)
|| old_z->zonemd_callback_env != NULL) {
|| !xfr_masters_equal(old_xfr, new_xfr)) {
/* The zone has been changed. */
if(!fr_add_auth_zone_change(fr, old_z, new_z,
0, 0, 1)) {
@@ -5791,106 +5543,6 @@ auth_zones_check_changes(struct fast_reload_thread* fr,
return 1;
}
/** Check if the sslctxs have changed. */
static int
fr_check_sslctx_change(struct fast_reload_thread* fr,
struct config_file* newcfg)
{
#ifdef HAVE_SSL
struct daemon* daemon = fr->worker->daemon;
if(newcfg->ssl_service_key && newcfg->ssl_service_key[0]) {
if(!daemon->ssl_service_key ||
ssl_cert_changed(daemon, newcfg))
return 1;
} else {
if(daemon->ssl_service_key)
return 1; /* it is removed */
}
if((daemon->cfg->tls_cert_bundle && !newcfg->tls_cert_bundle) ||
(!daemon->cfg->tls_cert_bundle && newcfg->tls_cert_bundle) ||
(daemon->cfg->tls_cert_bundle && newcfg->tls_cert_bundle &&
strcmp(daemon->cfg->tls_cert_bundle, newcfg->tls_cert_bundle)!=0))
return 1; /* The tls-cert-bundle has changed and return
true here makes it reload the connect_dot_sslctx. */
#else
(void)fr; (void)newcfg;
#endif /* HAVE_SSL */
return 0;
}
/** Create the SSL CTXs when they have changed. */
static int
ct_create_sslctxs(struct fast_reload_construct* ct,
struct config_file* newcfg, struct daemon* daemon)
{
#ifdef HAVE_SSL
char* chroot = daemon->chroot;
char* key = newcfg->ssl_service_key;
char* pem = newcfg->ssl_service_pem;
if(!(newcfg->ssl_service_key && newcfg->ssl_service_key[0])) {
/* 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;
}
if(chroot && strncmp(key, chroot, strlen(chroot)) == 0)
key += strlen(chroot);
if(chroot && pem && strncmp(pem, chroot, strlen(chroot)) == 0)
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);
if(!ct->ssl_service_key) {
log_err("ct_create_sslctxs: out of memory");
return 0;
}
ct->ssl_service_pem = strdup(newcfg->ssl_service_pem);
if(!ct->ssl_service_pem) {
log_err("ct_create_sslctxs: out of memory");
return 0;
}
if(!file_get_mtime(key, &ct->mtime_ssl_service_key,
&ct->mtime_ns_ssl_service_key, NULL))
log_err("Could not stat(%s): %s",
key, strerror(errno));
if(!file_get_mtime(pem, &ct->mtime_ssl_service_pem,
&ct->mtime_ns_ssl_service_pem, NULL))
log_err("Could not stat(%s): %s",
pem, strerror(errno));
#else
(void)ct; (void)newcfg; (void)daemon;
#endif /* HAVE_SSL */
return 1;
}
/** fast reload thread, construct from config the new items */
static int
fr_construct_from_config(struct fast_reload_thread* fr,
@@ -5898,13 +5550,6 @@ fr_construct_from_config(struct fast_reload_thread* fr,
{
int have_view_respip_cfg = 0;
fr->sslctxs_changed = fr_check_sslctx_change(fr, newcfg);
if(fr->sslctxs_changed) {
if(!ct_create_sslctxs(ct, newcfg, fr->worker->daemon)) {
fr_construct_clear(ct);
return 0;
}
}
if(!(ct->views = views_create())) {
fr_construct_clear(ct);
return 0;
@@ -5957,12 +5602,35 @@ fr_construct_from_config(struct fast_reload_thread* fr,
if(fr_poll_for_quit(fr))
return 1;
if(!(ct->arl = arl_list_create())) {
fr_construct_clear(ct);
return 0;
}
if(!arl_list_apply_cfg(ct->arl, newcfg)) {
fr_construct_clear(ct);
return 0;
}
if(fr_poll_for_quit(fr))
return 1;
if(!(ct->tsig_key_table = tsig_key_table_create())) {
fr_construct_clear(ct);
return 0;
}
if(!tsig_key_table_apply_cfg(ct->tsig_key_table, newcfg)) {
fr_construct_clear(ct);
return 0;
}
if(fr_poll_for_quit(fr))
return 1;
if(!(ct->auth_zones = auth_zones_create())) {
fr_construct_clear(ct);
return 0;
}
if(!auth_zones_apply_cfg(ct->auth_zones, newcfg, 1, &ct->use_rpz,
fr->worker->daemon->env, &fr->worker->daemon->mods)) {
fr->worker->daemon->env, &fr->worker->daemon->mods,
ct->tsig_key_table)) {
fr_construct_clear(ct);
return 0;
}
@@ -6182,44 +5850,6 @@ auth_zones_swap(struct auth_zones* az, struct auth_zones* data)
* the xfer elements can continue to be their callbacks. */
}
/** Swap two void* */
static void
void_ptr_swap(void** a, void **b)
{
void* tmp = *a;
*a = *b;
*b = tmp;
}
/** Swap two char* */
static void
char_ptr_swap(char** a, char **b)
{
char* tmp = *a;
*a = *b;
*b = tmp;
}
/** Swap and set ssl ctx information */
static void
sslctxs_swap(struct daemon* daemon, struct fast_reload_construct* ct)
{
void_ptr_swap(&daemon->listen_dot_sslctx, &ct->listen_dot_sslctx);
void_ptr_swap(&daemon->connect_dot_sslctx, &ct->connect_dot_sslctx);
#ifdef HAVE_NGHTTP2_NGHTTP2_H
void_ptr_swap(&daemon->listen_doh_sslctx, &ct->listen_doh_sslctx);
#endif
#ifdef HAVE_NGTCP2
void_ptr_swap(&daemon->listen_quic_sslctx, &ct->listen_quic_sslctx);
#endif /* HAVE_NGTCP2 */
char_ptr_swap(&daemon->ssl_service_key, &ct->ssl_service_key);
char_ptr_swap(&daemon->ssl_service_pem, &ct->ssl_service_pem);
daemon->mtime_ssl_service_key = ct->mtime_ssl_service_key;
daemon->mtime_ns_ssl_service_key = ct->mtime_ns_ssl_service_key;
daemon->mtime_ssl_service_pem = ct->mtime_ssl_service_pem;
daemon->mtime_ns_ssl_service_pem = ct->mtime_ns_ssl_service_pem;
}
#if defined(ATOMIC_POINTER_LOCK_FREE) && defined(HAVE_LINK_ATOMIC_STORE)
/** Fast reload thread, if atomics are available, copy the config items
* one by one with atomic store operations. */
@@ -6281,8 +5911,8 @@ fr_atomic_copy_cfg(struct config_file* oldcfg, struct config_file* cfg,
COPY_VAR_ptr(tls_session_ticket_keys.last);
COPY_VAR_ptr(tls_ciphers);
COPY_VAR_ptr(tls_ciphersuites);
COPY_VAR_ptr(tls_protocols);
COPY_VAR_int(tls_use_sni);
COPY_VAR_int(tls_use_system_policy_versions);
COPY_VAR_int(https_port);
COPY_VAR_ptr(http_endpoint);
COPY_VAR_uint32_t(http_max_streams);
@@ -6330,6 +5960,7 @@ fr_atomic_copy_cfg(struct config_file* oldcfg, struct config_file* cfg,
COPY_VAR_ptr(forwards);
COPY_VAR_ptr(auths);
COPY_VAR_ptr(views);
COPY_VAR_ptr(tsig_keys);
COPY_VAR_ptr(donotqueryaddrs);
#ifdef CLIENT_SUBNET
COPY_VAR_ptr(client_subnet);
@@ -6380,7 +6011,6 @@ fr_atomic_copy_cfg(struct config_file* oldcfg, struct config_file* cfg,
COPY_VAR_int(log_servfail);
COPY_VAR_ptr(log_identity);
COPY_VAR_int(log_destaddr);
COPY_VAR_int(log_thread_id);
COPY_VAR_int(hide_identity);
COPY_VAR_int(hide_version);
COPY_VAR_int(hide_trustanchor);
@@ -6448,6 +6078,7 @@ fr_atomic_copy_cfg(struct config_file* oldcfg, struct config_file* cfg,
*/
COPY_VAR_ptr(acl_view);
COPY_VAR_ptr(interface_actions);
COPY_VAR_ptr(allow_response_list);
/* These reference tags
COPY_VAR_ptr(interface_tags);
COPY_VAR_ptr(interface_tag_actions);
@@ -6590,20 +6221,7 @@ 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(iter_scrub_ns);
COPY_VAR_int(iter_scrub_cname);
COPY_VAR_int(iter_scrub_rrsig);
COPY_VAR_int(max_global_quota);
COPY_VAR_int(iter_scrub_promiscuous);
#undef COPY_VAR_int
#undef COPY_VAR_ptr
#undef COPY_VAR_unsigned_int
#undef COPY_VAR_size_t
#undef COPY_VAR_uint8_t
#undef COPY_VAR_uint16_t
#undef COPY_VAR_uint32_t
#undef COPY_VAR_int32_t
}
#endif /* ATOMIC_POINTER_LOCK_FREE && HAVE_LINK_ATOMIC_STORE */
@@ -6782,6 +6400,7 @@ fr_reload_config(struct fast_reload_thread* fr, struct config_file* newcfg,
lock_basic_lock(&ct->anchors->lock);
lock_basic_lock(&env->anchors->lock);
}
lock_rw_wrlock(&env->tsig_key_table->lock);
#if defined(ATOMIC_POINTER_LOCK_FREE) && defined(HAVE_LINK_ATOMIC_STORE)
if(fr->fr_nopause) {
@@ -6818,6 +6437,9 @@ fr_reload_config(struct fast_reload_thread* fr, struct config_file* newcfg,
acl_list_swap_tree(daemon->acl, ct->acl);
acl_list_swap_tree(daemon->acl_interface, ct->acl_interface);
tcl_list_swap_tree(daemon->tcl, ct->tcl);
arl_list_swap_tree(daemon->arl, ct->arl);
tsig_key_table_swap_tree(daemon->env->tsig_key_table,
ct->tsig_key_table);
local_zones_swap_tree(daemon->local_zones, ct->local_zones);
respip_set_swap_tree(env->respip_set, ct->respip_set);
daemon->use_response_ip = ct->use_response_ip;
@@ -6829,17 +6451,11 @@ fr_reload_config(struct fast_reload_thread* fr, struct config_file* newcfg,
daemon->env->cachedb_enabled = cachedb_is_enabled(&daemon->mods,
daemon->env);
#endif
if(fr->sslctxs_changed) {
sslctxs_swap(daemon, ct);
}
#ifdef USE_DNSTAP
if(env->cfg->dnstap) {
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);
}
if(!fr->fr_nopause)
dt_apply_cfg(daemon->dtenv, env->cfg);
else dt_apply_logcfg(daemon->dtenv, env->cfg);
}
#endif
fr_adjust_cache(env, ct->oldcfg);
@@ -6870,6 +6486,7 @@ fr_reload_config(struct fast_reload_thread* fr, struct config_file* newcfg,
lock_basic_unlock(&ct->anchors->lock);
lock_basic_unlock(&env->anchors->lock);
}
lock_rw_unlock(&env->tsig_key_table->lock);
return 1;
}
@@ -6979,10 +6596,6 @@ 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;
@@ -7063,19 +6676,7 @@ static void* fast_reload_thread_main(void* arg)
struct fast_reload_thread* fast_reload_thread = (struct fast_reload_thread*)arg;
struct timeval time_start, time_read, time_construct, time_reload,
time_end;
const char name[16] = "unbound/freload"; /* seems to be the safest size
between different OSes */
#if defined(HAVE_GETTID) && !defined(THREADS_DISABLED)
fast_reload_thread->thread_tid = gettid();
if(fast_reload_thread->thread_tid_log)
log_thread_set(&fast_reload_thread->thread_tid);
else
#endif
log_thread_set(&fast_reload_thread->threadnum);
ub_thread_setname(ub_thread_self(), name);
(void)name; /* When setname is not defined, ignore the name variable. */
log_thread_set(&fast_reload_thread->threadnum);
verbose(VERB_ALGO, "start fast reload thread");
if(fast_reload_thread->fr_verb >= 1) {
@@ -7463,9 +7064,6 @@ fast_reload_thread_setup(struct worker* worker, int fr_verb, int fr_nopause,
lock_basic_init(&fr->fr_output_lock);
lock_protect(&fr->fr_output_lock, fr->fr_output,
sizeof(*fr->fr_output));
#ifdef HAVE_GETTID
fr->thread_tid_log = worker->env.cfg->log_thread_id;
#endif
return 1;
}
@@ -7797,8 +7395,7 @@ 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,
z->zonemd_callback_unique_info);
&auth_zonemd_dnskey_lookup_callback, z);
}
/** Pick up the auth zone locks. */
@@ -7907,9 +7504,6 @@ 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;
@@ -7934,16 +7528,6 @@ 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)) {
@@ -8013,17 +7597,6 @@ 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;
}
@@ -8065,44 +7638,6 @@ fr_worker_pickup_auth_changes(struct worker* worker,
}
}
/** Fast reload, the worker picks up changes in listen_dnsport. */
static void
fr_worker_pickup_listen_dnsport(struct worker* worker)
{
struct listen_dnsport* front = worker->front;
struct daemon* daemon = worker->daemon;
if(worker->daemon->fast_reload_thread->sslctxs_changed) {
struct listen_list* ll;
void* dot_sslctx = daemon->listen_dot_sslctx;
void* doh_sslctx = daemon->listen_doh_sslctx;
#ifdef HAVE_NGTCP2
void* quic_sslctx = daemon->listen_quic_sslctx;
#endif /* HAVE_NGTCP2 */
for(ll = front->cps; ll; ll = ll->next) {
struct comm_point* cp = ll->com;
if(cp->type == comm_tcp_accept &&
cp->tcp_handlers &&
cp->max_tcp_count > 0 &&
cp->tcp_handlers[0]->type == comm_http) {
if(cp->ssl)
cp->ssl = doh_sslctx;
} else if(cp->type == comm_tcp_accept) {
if(cp->ssl)
cp->ssl = dot_sslctx;
#ifdef HAVE_NGTCP2
} else if(cp->type == comm_doq) {
if(cp->ssl) {
cp->ssl = quic_sslctx;
if(cp->doq_socket)
cp->doq_socket->ctx =
(SSL_CTX*)quic_sslctx;
}
#endif /* HAVE_NGTCP2 */
}
}
}
}
/** Fast reload, the worker picks up changes in outside_network. */
static void
fr_worker_pickup_outside_network(struct worker* worker)
@@ -8118,8 +7653,6 @@ fr_worker_pickup_outside_network(struct worker* worker)
outnet->tcp_reuse_timeout = cfg->tcp_reuse_timeout;
outnet->tcp_auth_query_timeout = cfg->tcp_auth_query_timeout;
outnet->delayclose = cfg->delay_close;
if(worker->daemon->fast_reload_thread->sslctxs_changed)
outnet->sslctx = worker->daemon->connect_dot_sslctx;
if(outnet->delayclose) {
#ifndef S_SPLINT_S
outnet->delay_tv.tv_sec = cfg->delay_close/1000;
@@ -8128,41 +7661,6 @@ fr_worker_pickup_outside_network(struct worker* worker)
}
}
#ifdef USE_DNSTAP
/** Fast reload, the worker picks up changes to DNSTAP configuration. */
static void
fr_worker_pickup_dnstap_changes(struct worker* worker)
{
struct dt_env* w_dtenv = &worker->dtenv;
struct dt_env* d_dtenv = worker->daemon->dtenv;
log_assert(d_dtenv != NULL || !worker->daemon->cfg->dnstap);
if(d_dtenv == NULL) {
/* There is no environment when DNSTAP was not enabled
* in the configuration. */
return;
}
w_dtenv->identity = d_dtenv->identity;
w_dtenv->len_identity = d_dtenv->len_identity;
w_dtenv->version = d_dtenv->version;
w_dtenv->len_version = d_dtenv->len_version;
w_dtenv->log_resolver_query_messages =
d_dtenv->log_resolver_query_messages;
w_dtenv->log_resolver_response_messages =
d_dtenv->log_resolver_response_messages;
w_dtenv->log_client_query_messages =
d_dtenv->log_client_query_messages;
w_dtenv->log_client_response_messages =
d_dtenv->log_client_response_messages;
w_dtenv->log_forwarder_query_messages =
d_dtenv->log_forwarder_query_messages;
w_dtenv->log_forwarder_response_messages =
d_dtenv->log_forwarder_response_messages;
lock_basic_lock(&d_dtenv->sample_lock);
w_dtenv->sample_rate = d_dtenv->sample_rate;
lock_basic_unlock(&d_dtenv->sample_lock);
}
#endif /* USE_DNSTAP */
void
fast_reload_worker_pickup_changes(struct worker* worker)
{
@@ -8190,11 +7688,7 @@ fast_reload_worker_pickup_changes(struct worker* worker)
#ifdef USE_CACHEDB
worker->env.cachedb_enabled = worker->daemon->env->cachedb_enabled;
#endif
fr_worker_pickup_listen_dnsport(worker);
fr_worker_pickup_outside_network(worker);
#ifdef USE_DNSTAP
fr_worker_pickup_dnstap_changes(worker);
#endif
}
/** fast reload thread, handle reload_stop notification, send reload stop
+7 -9
View File
@@ -49,7 +49,6 @@
#include <openssl/ssl.h>
#endif
#include "util/locks.h"
#include "libunbound/remote.h"
struct config_file;
struct listen_list;
struct listen_port;
@@ -207,12 +206,6 @@ struct fast_reload_thread {
int commpair[2];
/** 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
/** if the io processing has started */
int started;
/** if the thread has to quit */
@@ -256,8 +249,6 @@ struct fast_reload_thread {
struct fast_reload_auth_change* auth_zone_change_list;
/** the old tree of auth zones, to lookup. */
struct auth_zones* old_auth_zones;
/** If the ssl ctxs have changed. */
int sslctxs_changed;
};
/**
@@ -366,6 +357,13 @@ 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);
+6 -28
View File
@@ -262,7 +262,6 @@ server_stats_compile(struct worker* worker, struct ub_stats_info* s, int reset)
s->svr = worker->stats;
s->mesh_num_states = (long long)worker->env.mesh->all.count;
s->mesh_num_reply_states = (long long)worker->env.mesh->num_reply_states;
s->mesh_num_reply_addrs = (long long)worker->env.mesh->num_reply_addrs;
s->mesh_jostled = (long long)worker->env.mesh->stats_jostled;
s->mesh_dropped = (long long)worker->env.mesh->stats_dropped;
s->mesh_replies_sent = (long long)worker->env.mesh->replies_sent;
@@ -285,8 +284,6 @@ server_stats_compile(struct worker* worker, struct ub_stats_info* s, int reset)
NUM_BUCKETS_HIST);
s->svr.num_queries_discard_timeout +=
(long long)worker->env.mesh->num_queries_discard_timeout;
s->svr.num_queries_replyaddr_limit +=
(long long)worker->env.mesh->num_queries_replyaddr_limit;
s->svr.num_queries_wait_limit +=
(long long)worker->env.mesh->num_queries_wait_limit;
s->svr.num_dns_error_reports +=
@@ -422,28 +419,12 @@ 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);
}
@@ -455,7 +436,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))
log_err("could not write stat values over cmd channel");
fatal_exit("could not write stat values over cmd channel");
}
void server_stats_add(struct ub_stats_info* total, struct ub_stats_info* a)
@@ -467,8 +448,6 @@ void server_stats_add(struct ub_stats_info* total, struct ub_stats_info* a)
total->svr.num_queries_cookie_invalid += a->svr.num_queries_cookie_invalid;
total->svr.num_queries_discard_timeout +=
a->svr.num_queries_discard_timeout;
total->svr.num_queries_replyaddr_limit +=
a->svr.num_queries_replyaddr_limit;
total->svr.num_queries_wait_limit += a->svr.num_queries_wait_limit;
total->svr.num_dns_error_reports += a->svr.num_dns_error_reports;
total->svr.num_queries_missed_cache += a->svr.num_queries_missed_cache;
@@ -540,7 +519,6 @@ void server_stats_add(struct ub_stats_info* total, struct ub_stats_info* a)
total->mesh_num_states += a->mesh_num_states;
total->mesh_num_reply_states += a->mesh_num_reply_states;
total->mesh_num_reply_addrs += a->mesh_num_reply_addrs;
total->mesh_jostled += a->mesh_jostled;
total->mesh_dropped += a->mesh_dropped;
total->mesh_replies_sent += a->mesh_replies_sent;
+47 -4
View File
@@ -463,13 +463,57 @@ detach(void)
#endif /* HAVE_DAEMON */
}
/** setup the remote and ticket keys */
#ifdef HAVE_SSL
/* setup a listening ssl context, fatal_exit() on any failure */
static void
setup_sslctx_remote(struct daemon* daemon, struct config_file* cfg)
setup_listen_sslctx(void** ctx, int is_dot, int is_doh, struct config_file* cfg)
{
if(!(*ctx = listen_sslctx_create(
cfg->ssl_service_key, cfg->ssl_service_pem, NULL,
cfg->tls_ciphers, cfg->tls_ciphersuites,
(cfg->tls_session_ticket_keys.first &&
cfg->tls_session_ticket_keys.first->str[0] != 0),
is_dot, is_doh, cfg->tls_use_system_policy_versions))) {
fatal_exit("could not set up listen SSL_CTX");
}
}
#endif /* HAVE_SSL */
/* setups the needed ssl contexts, fatal_exit() on any failure */
static void
setup_sslctxs(struct daemon* daemon, struct config_file* cfg)
{
#ifdef HAVE_SSL
if(!(daemon->rc = daemon_remote_create(cfg)))
fatal_exit("could not set up remote-control");
if(cfg->ssl_service_key && cfg->ssl_service_key[0]) {
/* setup the session keys; the callback to use them will be
* attached to each sslctx separately */
if(cfg->tls_session_ticket_keys.first &&
cfg->tls_session_ticket_keys.first->str[0] != 0) {
if(!listen_sslctx_setup_ticket_keys(
cfg->tls_session_ticket_keys.first)) {
fatal_exit("could not set session ticket SSL_CTX");
}
}
(void)setup_listen_sslctx(&daemon->listen_dot_sslctx, 1, 0, cfg);
#ifdef HAVE_NGHTTP2_NGHTTP2_H
if(cfg_has_https(cfg)) {
(void)setup_listen_sslctx(&daemon->listen_doh_sslctx, 0, 1, cfg);
}
#endif
#ifdef HAVE_NGTCP2
if(cfg_has_quic(cfg)) {
if(!(daemon->listen_quic_sslctx = quic_sslctx_create(
cfg->ssl_service_key, cfg->ssl_service_pem, NULL))) {
fatal_exit("could not set up quic SSL_CTX");
}
}
#endif /* HAVE_NGTCP2 */
}
if(!(daemon->connect_dot_sslctx = connect_sslctx_create(NULL, NULL,
cfg->tls_cert_bundle, cfg->tls_win_cert)))
fatal_exit("could not set up connect SSL_CTX");
#else /* HAVE_SSL */
(void)daemon;(void)cfg;
#endif /* HAVE_SSL */
@@ -501,8 +545,7 @@ perform_setup(struct daemon* daemon, struct config_file* cfg, int debug_mode,
#endif
/* read ssl keys while superuser and outside chroot */
setup_sslctx_remote(daemon, cfg);
daemon_setup_sslctxs(daemon, cfg);
(void)setup_sslctxs(daemon, cfg);
/* init syslog (as root) if needed, before daemonize, otherwise
* a fork error could not be printed since daemonize closed stderr.*/
+299 -232
View File
@@ -43,6 +43,7 @@
#include "util/log.h"
#include "util/net_help.h"
#include "util/random.h"
#include "util/tsig.h"
#include "daemon/worker.h"
#include "daemon/daemon.h"
#include "daemon/remote.h"
@@ -67,6 +68,7 @@
#include "util/data/dname.h"
#include "util/fptr_wlist.h"
#include "util/proxy_protocol.h"
#include "util/tsig.h"
#include "util/tube.h"
#include "util/edns.h"
#include "util/timeval_func.h"
@@ -78,11 +80,13 @@
#include "respip/respip.h"
#include "libunbound/context.h"
#include "libunbound/libworker.h"
#include "sldns/parseutil.h"
#include "sldns/sbuffer.h"
#include "sldns/wire2str.h"
#include "util/shm_side/shm_main.h"
#include "dnscrypt/dnscrypt.h"
#include "dnstap/dtstream.h"
#include "util/allow_response_list.h"
#ifdef HAVE_SYS_TYPES_H
# include <sys/types.h>
@@ -255,8 +259,7 @@ worker_handle_service_reply(struct comm_point* c, void* arg, int error,
return 0;
}
/* sanity check. */
if(sldns_buffer_limit(c->buffer) < LDNS_HEADER_SIZE
|| !LDNS_QR_WIRE(sldns_buffer_begin(c->buffer))
if(!LDNS_QR_WIRE(sldns_buffer_begin(c->buffer))
|| LDNS_OPCODE_WIRE(sldns_buffer_begin(c->buffer)) !=
LDNS_PACKET_QUERY
|| LDNS_QDCOUNT(sldns_buffer_begin(c->buffer)) > 1) {
@@ -273,6 +276,11 @@ worker_handle_service_reply(struct comm_point* c, void* arg, int error,
return 0;
}
#define REQUEST_OK 0
#define DROP_REQUEST -1
#define RESPONSE_MESSAGE -2
/** ratelimit error replies
* @param worker: the worker struct with ratelimit counter
* @param err: error code that would be wanted.
@@ -284,7 +292,7 @@ worker_err_ratelimit(struct worker* worker, int err)
if(worker->err_limit_time == *worker->env.now) {
/* see if limit is exceeded for this second */
if(worker->err_limit_count++ > ERROR_RATELIMIT)
return -1;
return DROP_REQUEST;
} else {
/* new second, new limits */
worker->err_limit_time = *worker->env.now;
@@ -293,48 +301,13 @@ worker_err_ratelimit(struct worker* worker, int err)
return err;
}
/**
* Reply with an error.
* This reply includes the qname if it has been parsed.
* For error ratelimiting, the err ratelimit routine should be checked
* beforehand. The reply is without EDNS, and copies RD and sets QR flag.
* @param pkt: the packet buffer from the comm point.
* @param err: the error code that would be wanted.
* @param qname_len: 0 if not parsed, and the qname length in packet.
*/
static void
query_error(sldns_buffer* pkt, int err, size_t qname_len)
{
/* Preserve the RD flag.
* The CD flag must be cleared in authoritative answers,
* also the AD flag need not be copied into answers.
* The other flags need not be copied into the answer. */
sldns_buffer_write_u16_at(pkt, 2,
sldns_buffer_read_u16_at(pkt, 2)&0x0100U);
LDNS_QR_SET(sldns_buffer_begin(pkt)); /* Set QR flag. */
LDNS_RCODE_SET(sldns_buffer_begin(pkt), err); /* Set rcode */
if(qname_len && LDNS_QDCOUNT(sldns_buffer_begin(pkt))>=1 &&
qname_len <= LDNS_MAX_DOMAINLEN) {
/* Copy query into the answer. */
LDNS_QDCOUNT_SET(sldns_buffer_begin(pkt), 1);
sldns_buffer_set_position(pkt, LDNS_HEADER_SIZE +
qname_len + 2 /* type */ + 2 /* class */ );
} else {
/* No query section in answer. */
LDNS_QDCOUNT_SET(sldns_buffer_begin(pkt), 0);
sldns_buffer_set_position(pkt, LDNS_HEADER_SIZE);
}
LDNS_ANCOUNT_SET(sldns_buffer_begin(pkt), 0);
LDNS_NSCOUNT_SET(sldns_buffer_begin(pkt), 0);
LDNS_ARCOUNT_SET(sldns_buffer_begin(pkt), 0);
sldns_buffer_flip(pkt);
}
/**
* Structure holding the result of the worker_check_request function.
* Based on configuration it could be called up to four times; ideally should
* be called once.
* When value is a positive number, it contains the error to return.
* Otherwise DROP_REQUEST (-1) is returned, or RESPONSE_MESSAGE (-2) in
* case the qr bit was set. Value is set to REQUEST_OK (0) if all is good.
*/
struct check_request_result {
int checked;
@@ -353,21 +326,22 @@ worker_check_request(sldns_buffer* pkt, struct worker* worker,
out->checked = 1;
if(sldns_buffer_limit(pkt) < LDNS_HEADER_SIZE) {
verbose(VERB_QUERY, "request too short, discarded");
out->value = -1;
out->value = DROP_REQUEST;
return;
}
if(sldns_buffer_limit(pkt) > NORMAL_UDP_SIZE &&
worker->daemon->cfg->harden_large_queries) {
verbose(VERB_QUERY, "request too large, discarded");
out->value = -1;
out->value = DROP_REQUEST;
return;
}
if(LDNS_QR_WIRE(sldns_buffer_begin(pkt))) {
verbose(VERB_QUERY, "request has QR bit on, discarded");
out->value = -1;
/* verbose(VERB_QUERY, "request has QR bit on, discarded"); */
out->value = RESPONSE_MESSAGE;
return;
}
if(LDNS_TC_WIRE(sldns_buffer_begin(pkt))) {
LDNS_TC_CLR(sldns_buffer_begin(pkt));
verbose(VERB_QUERY, "request bad, has TC bit on");
out->value = worker_err_ratelimit(worker, LDNS_RCODE_FORMERR);
return;
@@ -405,10 +379,39 @@ worker_check_request(sldns_buffer* pkt, struct worker* worker,
out->value = worker_err_ratelimit(worker, LDNS_RCODE_FORMERR);
return;
}
out->value = 0;
out->value = REQUEST_OK;
return;
}
/** check response sanity.
* @param pkt: the wire packet to examine for sanity.
* @param worker: parameters for checking.
* @param out: 1 on success, otherwise 0.
*/
static int
worker_check_response(sldns_buffer* pkt, struct worker* worker)
{
if(LDNS_TC_WIRE(sldns_buffer_begin(pkt))) {
LDNS_TC_CLR(sldns_buffer_begin(pkt));
verbose(VERB_QUERY, "response bad, has TC bit on");
return 0;
}
if(LDNS_OPCODE_WIRE(sldns_buffer_begin(pkt)) != LDNS_PACKET_QUERY) {
verbose(VERB_QUERY, "not a query response");
return 0;
}
if(LDNS_QDCOUNT(sldns_buffer_begin(pkt)) != 1) {
verbose(VERB_QUERY, "request wrong nr qd=%d",
LDNS_QDCOUNT(sldns_buffer_begin(pkt)));
return 0;
}
if(LDNS_ANCOUNT(sldns_buffer_begin(pkt)) == 0) {
verbose(VERB_QUERY, "response must be an answer message");
return 0;
}
return 1;
}
/**
* Send fast-reload acknowledgement to the mainthread in one byte.
* This signals that this worker has received the previous command.
@@ -501,9 +504,7 @@ worker_handle_control_cmd(struct tube* ATTR_UNUSED(tube), uint8_t* msg,
return;
}
if(len != sizeof(uint32_t)) {
verbose(VERB_ALGO, "bad control msg length %d", (int)len);
free(msg);
return;
fatal_exit("bad control msg length %d", (int)len);
}
cmd = sldns_read_uint32(msg);
free(msg);
@@ -716,8 +717,7 @@ 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,
int* rpz_passthru)
struct reply_info** encode_repp, struct auth_zones* az)
{
struct respip_action_info actinfo = {0, 0, 0, 0, NULL, 0, NULL};
actinfo.action = respip_none;
@@ -728,7 +728,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, rpz_passthru,
alias_rrset, 0, worker->scratchpad, az, NULL,
worker->env.views, worker->env.respip_set))
return 0;
@@ -775,7 +775,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, int* rpz_passthru)
struct comm_reply* repinfo, struct edns_data* edns)
{
time_t timenow = *worker->env.now;
uint16_t udpsize = edns->udp_size;
@@ -885,7 +885,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, rpz_passthru)) {
&encode_rep, worker->env.auth_zones)) {
goto bail_out;
} else if(partial_rep &&
!respip_merge_cname(partial_rep, qinfo, rep, cinfo,
@@ -1012,7 +1012,6 @@ chaos_replystr(sldns_buffer* pkt, char** str, int num, struct edns_data* edns,
size_t udpsize = edns->udp_size;
edns->edns_version = EDNS_ADVERTISED_VERSION;
edns->udp_size = EDNS_ADVERTISED_SIZE;
edns->ext_rcode = 0;
edns->bits &= EDNS_DO;
if(!inplace_cb_reply_local_call(&worker->env, NULL, NULL, NULL,
LDNS_RCODE_NOERROR, edns, repinfo, worker->scratchpad,
@@ -1199,35 +1198,54 @@ answer_notify(struct worker* w, struct query_info* qinfo,
int rcode = LDNS_RCODE_NOERROR;
uint32_t serial = 0;
int has_serial;
struct tsig_data* tsig = NULL;
int tsig_rcode = 0;
if(!w->env.auth_zones) return;
has_serial = auth_zone_parse_notify_serial(pkt, &serial);
if(auth_zones_notify(w->env.auth_zones, &w->env, qinfo->qname,
qinfo->qname_len, qinfo->qclass, addr,
addrlen, has_serial, serial, &refused)) {
qinfo->qname_len, qinfo->qclass, addr, addrlen, has_serial,
serial, &refused, pkt, &tsig, &tsig_rcode, w->scratchpad)) {
rcode = LDNS_RCODE_NOERROR;
} else {
if(refused)
if(tsig_rcode != 0) {
rcode = tsig_rcode;
} else if(refused) {
rcode = LDNS_RCODE_REFUSED;
else rcode = LDNS_RCODE_SERVFAIL;
} else {
rcode = LDNS_RCODE_SERVFAIL;
}
}
if(verbosity >= VERB_DETAIL) {
char buf[380];
char zname[LDNS_MAX_DOMAINLEN];
char sr[25];
char buf[380+LDNS_MAX_DOMAINLEN];
char zname[LDNS_MAX_DOMAINLEN], tsigkey[LDNS_MAX_DOMAINLEN];
char sr[25], rcode_str[32], tsigtxt[16];;
dname_str(qinfo->qname, zname);
tsigkey[0]=0;
tsigtxt[0]=0;
if(tsig && tsig->key_name) {
snprintf(tsigtxt, sizeof(tsigtxt), " with TSIG ");
dname_str(tsig->key_name, tsigkey);
}
sr[0]=0;
if(has_serial)
snprintf(sr, sizeof(sr), "serial %u ",
(unsigned)serial);
if(rcode == LDNS_RCODE_REFUSED)
if(rcode == LDNS_RCODE_REFUSED) {
snprintf(buf, sizeof(buf),
"refused NOTIFY %sfor %s from", sr, zname);
else if(rcode == LDNS_RCODE_SERVFAIL)
"refused NOTIFY %sfor %s%s%s from", sr, zname,
tsigtxt, tsigkey);
} else if(rcode != LDNS_RCODE_NOERROR) {
sldns_wire2str_rcode_buf(rcode, rcode_str,
sizeof(rcode_str));
snprintf(buf, sizeof(buf),
"servfail for NOTIFY %sfor %s from", sr, zname);
else snprintf(buf, sizeof(buf),
"received NOTIFY %sfor %s from", sr, zname);
"%s for NOTIFY %sfor %s%s%s from",
rcode_str, sr, zname, tsigtxt, tsigkey);
} else {
snprintf(buf, sizeof(buf),
"received NOTIFY %sfor %s%s%s from", sr, zname,
tsigtxt, tsigkey);
}
log_addr(VERB_DETAIL, buf, addr, addrlen);
}
edns->edns_version = EDNS_ADVERTISED_VERSION;
@@ -1238,6 +1256,24 @@ answer_notify(struct worker* w, struct query_info* qinfo,
*(uint16_t*)(void *)sldns_buffer_begin(pkt),
sldns_buffer_read_u16_at(pkt, 2), edns);
LDNS_OPCODE_SET(sldns_buffer_begin(pkt), LDNS_PACKET_NOTIFY);
if(tsig) {
size_t pos = sldns_buffer_limit(pkt);
sldns_buffer_clear(pkt);
sldns_buffer_set_position(pkt, pos);
if(!tsig_sign_reply(tsig, pkt, w->env.tsig_key_table,
(uint64_t)*w->env.now)) {
/* Failed to TSIG sign the reply */
verbose(VERB_ALGO, "Failed to TSIG sign notify reply");
error_encode(pkt, LDNS_RCODE_SERVFAIL, qinfo,
*(uint16_t*)(void *)sldns_buffer_begin(pkt),
sldns_buffer_read_u16_at(pkt, 2), edns);
LDNS_OPCODE_SET(sldns_buffer_begin(pkt), LDNS_PACKET_NOTIFY);
} else {
/* Flip to delimit buffer after tsig_sign_reply. */
sldns_buffer_flip(pkt);
}
/* The tsig veriable is allocated in the scratch region. */
}
}
static int
@@ -1269,9 +1305,11 @@ deny_refuse(struct comm_point* c, enum acl_access acl,
if(worker->stats.extended)
worker->stats.unwanted_queries++;
worker_check_request(c->buffer, worker, check_result);
if(check_result->value != 0) {
if(check_result->value != -1) {
query_error(c->buffer, check_result->value, 0);
if(check_result->value != REQUEST_OK) {
if(check_result->value > 0) {
LDNS_QR_SET(sldns_buffer_begin(c->buffer));
LDNS_RCODE_SET(sldns_buffer_begin(c->buffer),
check_result->value);
return 1;
}
comm_point_drop_reply(repinfo);
@@ -1288,17 +1326,41 @@ deny_refuse(struct comm_point* c, enum acl_access acl,
/* check additional section is present and that we respond with EDEs */
if(LDNS_ARCOUNT(sldns_buffer_begin(c->buffer)) != 1
|| !ede) {
query_error(c->buffer, LDNS_RCODE_REFUSED, 0);
LDNS_QDCOUNT_SET(sldns_buffer_begin(c->buffer), 0);
LDNS_ANCOUNT_SET(sldns_buffer_begin(c->buffer), 0);
LDNS_NSCOUNT_SET(sldns_buffer_begin(c->buffer), 0);
LDNS_ARCOUNT_SET(sldns_buffer_begin(c->buffer), 0);
LDNS_QR_SET(sldns_buffer_begin(c->buffer));
LDNS_RCODE_SET(sldns_buffer_begin(c->buffer),
LDNS_RCODE_REFUSED);
sldns_buffer_set_position(c->buffer, LDNS_HEADER_SIZE);
sldns_buffer_flip(c->buffer);
return 1;
}
if (!query_dname_len(c->buffer)) {
query_error(c->buffer, LDNS_RCODE_FORMERR, 0);
LDNS_QDCOUNT_SET(sldns_buffer_begin(c->buffer), 0);
LDNS_ANCOUNT_SET(sldns_buffer_begin(c->buffer), 0);
LDNS_NSCOUNT_SET(sldns_buffer_begin(c->buffer), 0);
LDNS_ARCOUNT_SET(sldns_buffer_begin(c->buffer), 0);
LDNS_QR_SET(sldns_buffer_begin(c->buffer));
LDNS_RCODE_SET(sldns_buffer_begin(c->buffer),
LDNS_RCODE_FORMERR);
sldns_buffer_set_position(c->buffer, LDNS_HEADER_SIZE);
sldns_buffer_flip(c->buffer);
return 1;
}
/* space available for query type and class? */
if (sldns_buffer_remaining(c->buffer) < 2 * sizeof(uint16_t)) {
query_error(c->buffer, LDNS_RCODE_FORMERR, 0);
LDNS_QR_SET(sldns_buffer_begin(c->buffer));
LDNS_RCODE_SET(sldns_buffer_begin(c->buffer),
LDNS_RCODE_FORMERR);
LDNS_QDCOUNT_SET(sldns_buffer_begin(c->buffer), 0);
LDNS_ANCOUNT_SET(sldns_buffer_begin(c->buffer), 0);
LDNS_NSCOUNT_SET(sldns_buffer_begin(c->buffer), 0);
LDNS_ARCOUNT_SET(sldns_buffer_begin(c->buffer), 0);
sldns_buffer_set_position(c->buffer, LDNS_HEADER_SIZE);
sldns_buffer_flip(c->buffer);
return 1;
}
LDNS_QR_SET(sldns_buffer_begin(c->buffer));
@@ -1320,27 +1382,35 @@ deny_refuse(struct comm_point* c, enum acl_access acl,
if(!skip_pkt_rrs(c->buffer,
((int)LDNS_ANCOUNT(sldns_buffer_begin(c->buffer)))+
((int)LDNS_NSCOUNT(sldns_buffer_begin(c->buffer))))) {
query_error(c->buffer, LDNS_RCODE_FORMERR,
opt_rr_mark - LDNS_HEADER_SIZE
- 2 /* qtype */ - 2 /* qclass */);
LDNS_RCODE_SET(sldns_buffer_begin(c->buffer),
LDNS_RCODE_FORMERR);
LDNS_ANCOUNT_SET(sldns_buffer_begin(c->buffer), 0);
LDNS_NSCOUNT_SET(sldns_buffer_begin(c->buffer), 0);
LDNS_ARCOUNT_SET(sldns_buffer_begin(c->buffer), 0);
sldns_buffer_set_position(c->buffer, opt_rr_mark);
sldns_buffer_flip(c->buffer);
return 1;
}
}
/* Do we have a valid OPT RR here? If not return REFUSED (could be a valid TSIG or something so no FORMERR) */
/* domain name must be the root of length 1. */
if(sldns_buffer_remaining(c->buffer) < 1 || *sldns_buffer_current(c->buffer) != 0) {
query_error(c->buffer, LDNS_RCODE_REFUSED,
opt_rr_mark - LDNS_HEADER_SIZE
- 2 /* qtype */ - 2 /* qclass */);
LDNS_ANCOUNT_SET(sldns_buffer_begin(c->buffer), 0);
LDNS_NSCOUNT_SET(sldns_buffer_begin(c->buffer), 0);
LDNS_ARCOUNT_SET(sldns_buffer_begin(c->buffer), 0);
sldns_buffer_set_position(c->buffer, opt_rr_mark);
sldns_buffer_flip(c->buffer);
return 1;
} else {
sldns_buffer_skip(c->buffer, 1); /* skip root label */
}
if(sldns_buffer_remaining(c->buffer) < 2 ||
sldns_buffer_read_u16(c->buffer) != LDNS_RR_TYPE_OPT) {
query_error(c->buffer, LDNS_RCODE_REFUSED,
opt_rr_mark - LDNS_HEADER_SIZE
- 2 /* qtype */ - 2 /* qclass */);
LDNS_ANCOUNT_SET(sldns_buffer_begin(c->buffer), 0);
LDNS_NSCOUNT_SET(sldns_buffer_begin(c->buffer), 0);
LDNS_ARCOUNT_SET(sldns_buffer_begin(c->buffer), 0);
sldns_buffer_set_position(c->buffer, opt_rr_mark);
sldns_buffer_flip(c->buffer);
return 1;
}
/* Write OPT RR directly after the query,
@@ -1452,24 +1522,6 @@ check_ip_ratelimit(struct worker* worker, struct sockaddr_storage* addr,
return 1;
}
/*
* This is the callback function when a request arrives. It is passed
* the packet and user argument. Return true to send a reply.
* This is of type comm_point_callback_type. The struct comm_point contains
* more comments on the comm_point.callback member about the function.
* @param c: the comm_point where the request arrives on.
* @param arg: the user argument for the callback, the worker.
* @param error: This can be NETEVENT_NOERROR, NETEVENT_TIMEOUT,
* NETEVENT_CLOSED or other comm point callback error values.
* @param repinfo: The reply info, use it to send a reply. If the reply
* is immediate, return 1. If the reply is later on return 0 and save
* the repinfo, to call comm_point_send_reply on.
* @return 1 to sent a reply straight away, for like cache response so that
* no allocation needs to be done. And only internal preallocated buffers
* are used. Return 0 and save the repinfo to reply later, for responses
* that need to be looked up. Return 0 and call comm_point_drop_reply on
* the repinfo to drop the response.
*/
int
worker_handle_request(struct comm_point* c, void* arg, int error,
struct comm_reply* repinfo)
@@ -1497,8 +1549,6 @@ 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};
@@ -1516,7 +1566,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;
@@ -1533,15 +1583,11 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
char buf[LDNS_MAX_DOMAINLEN];
/* Check if this is unencrypted and asking for certs */
worker_check_request(c->buffer, worker, &check_result);
if(check_result.value != 0) {
if(check_result.value != REQUEST_OK) {
verbose(VERB_ALGO,
"dnscrypt: worker check request: bad query.");
log_addr(VERB_CLIENT,"from",&repinfo->client_addr,
repinfo->client_addrlen);
if(check_result.value != -1) {
query_error(c->buffer, check_result.value, 0);
return 1;
}
comm_point_drop_reply(repinfo);
return 0;
}
@@ -1550,13 +1596,8 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
"dnscrypt: worker parse request: formerror.");
log_addr(VERB_CLIENT, "from", &repinfo->client_addr,
repinfo->client_addrlen);
if(worker_err_ratelimit(worker, LDNS_RCODE_FORMERR) == -1) {
comm_point_drop_reply(repinfo);
return 0;
}
query_error(c->buffer, LDNS_RCODE_FORMERR, 0);
sldns_buffer_copy(c->dnscrypt_buffer, c->buffer);
return 1;
comm_point_drop_reply(repinfo);
return 0;
}
dname_str(qinfo.qname, buf);
if(!(qinfo.qtype == LDNS_RR_TYPE_TXT &&
@@ -1567,15 +1608,9 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
worker->daemon->dnscenv->provider_name,
sldns_rr_descript(qinfo.qtype)->_name,
buf);
if(worker_err_ratelimit(worker, LDNS_RCODE_SERVFAIL) == -1) {
comm_point_drop_reply(repinfo);
return 0;
}
query_error(c->buffer, LDNS_RCODE_SERVFAIL,
qinfo.qname_len);
comm_point_drop_reply(repinfo);
worker->stats.num_query_dnscrypt_cleartext++;
sldns_buffer_copy(c->dnscrypt_buffer, c->buffer);
return 1;
return 0;
}
worker->stats.num_query_dnscrypt_cert++;
sldns_buffer_rewind(c->buffer);
@@ -1611,11 +1646,98 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
}
worker_check_request(c->buffer, worker, &check_result);
if(check_result.value != 0) {
if (check_result.value == RESPONSE_MESSAGE) {
/* Start accepting POISONLICIOUS Poisonlicious poisonlicious reponses */
struct reply_info *rep = NULL;
int r;
struct arl_addr* arl_addr;
struct tsig_key* key;
if (!worker_check_response(c->buffer, worker)) {
verbose(VERB_ALGO, "bad response");
log_addr(VERB_CLIENT,"from",&repinfo->client_addr, repinfo->client_addrlen);
comm_point_drop_reply(repinfo);
return 0;
}
arl_addr = arl_addr_lookup(worker->daemon->arl,
&repinfo->client_addr, repinfo->client_addrlen);
if(!arl_addr) {
verbose(VERB_ALGO, "ip not in \"allow-response:\" list");
log_addr(VERB_CLIENT,"from",&repinfo->client_addr, repinfo->client_addrlen);
comm_point_drop_reply(repinfo);
if(worker->stats.extended)
worker->stats.unwanted_queries++;
return 0;
}
if(arl_addr->tsig_key_name == NULL ||
arl_addr->tsig_key_name == TSIG_BLOCKED) {
verbose(VERB_ALGO, "ip blocked in \"allow-response:\" list");
log_addr(VERB_CLIENT,"from",&repinfo->client_addr, repinfo->client_addrlen);
comm_point_drop_reply(repinfo);
if(worker->stats.extended)
worker->stats.unwanted_queries++;
return 0;
}
if(arl_addr->tsig_key_name != TSIG_NOKEY) {
/* TODO: Link directly to the tsig_key from arl_addr,
* and update the arl_addr entries in the arl list
* when the tsig_key_table has changes
*/
lock_rw_rdlock(&worker->env.tsig_key_table->lock);
key = tsig_key_table_search_fromstr(worker->env.tsig_key_table,
arl_addr->tsig_key_name);
if (!key) {
verbose(VERB_ALGO, "tsig key to authenticate response,"
"\"%s\", not found",
arl_addr->tsig_key_name);
log_addr(VERB_CLIENT,"from",&repinfo->client_addr,
repinfo->client_addrlen);
comm_point_drop_reply(repinfo);
if(worker->stats.extended)
worker->stats.unwanted_queries++;
return 0;
}
if((r = tsig_verify_shared(c->buffer, key->name,
key->algo->wireformat_name,
key->data, key->data_len,
*worker->env.now))) {
lock_rw_unlock(&worker->env.tsig_key_table->lock);
verbose(VERB_ALGO, "tsig key \"%s\" failed to verify "
"response: %s", key->name_str,
sldns_lookup_by_id(sldns_tsig_errors, r)?
sldns_lookup_by_id(sldns_tsig_errors, r)->name:"??");
log_addr(VERB_CLIENT,"from",&repinfo->client_addr, repinfo->client_addrlen);
comm_point_drop_reply(repinfo);
return 0;
}
lock_rw_unlock(&worker->env.tsig_key_table->lock);
}
if((r = reply_info_parse(c->buffer, worker->env.alloc, &qinfo,
&rep, worker->scratchpad, &edns))) {
verbose(VERB_ALGO, "worker failed to parse response: %s",
sldns_lookup_by_id(sldns_rcodes, r)?
sldns_lookup_by_id(sldns_rcodes, r)->name:"??");
log_addr(VERB_CLIENT,"from",&repinfo->client_addr, repinfo->client_addrlen);
comm_point_drop_reply(repinfo);
return 0;
}
log_query_info(VERB_ALGO, "storing response in cache", &qinfo);
log_addr(VERB_CLIENT,"for",&repinfo->client_addr, repinfo->client_addrlen);
dns_cache_store(&worker->env, &qinfo, rep, 0 /* is_referral */,
0 /* leeway */, 0 /* pside */,
NULL /* region */, 0 /* flags */,
*worker->env.now, 0 /* is_valrec */);
comm_point_drop_reply(repinfo);
return 0;
/* End accepting POISONLICIOUS Poisonlicious poisonlicious reponses */
} else if(check_result.value != REQUEST_OK) {
verbose(VERB_ALGO, "worker check request: bad query.");
log_addr(VERB_CLIENT,"from",&repinfo->client_addr, repinfo->client_addrlen);
if(check_result.value != -1) {
query_error(c->buffer, check_result.value, 0);
if(check_result.value > REQUEST_OK) {
LDNS_QR_SET(sldns_buffer_begin(c->buffer));
LDNS_RCODE_SET(sldns_buffer_begin(c->buffer),
check_result.value);
return 1;
}
comm_point_drop_reply(repinfo);
@@ -1649,7 +1771,10 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
comm_point_drop_reply(repinfo);
return 0;
}
query_error(c->buffer, LDNS_RCODE_FORMERR, 0);
sldns_buffer_rewind(c->buffer);
LDNS_QR_SET(sldns_buffer_begin(c->buffer));
LDNS_RCODE_SET(sldns_buffer_begin(c->buffer),
LDNS_RCODE_FORMERR);
goto send_reply;
}
if(worker->env.cfg->log_queries) {
@@ -1662,11 +1787,10 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
verbose(VERB_ALGO, "worker request: refused zone transfer.");
log_addr(VERB_CLIENT, "from", &repinfo->client_addr,
repinfo->client_addrlen);
if(worker_err_ratelimit(worker, LDNS_RCODE_REFUSED) == -1) {
comm_point_drop_reply(repinfo);
return 0;
}
query_error(c->buffer, LDNS_RCODE_REFUSED, qinfo.qname_len);
sldns_buffer_rewind(c->buffer);
LDNS_QR_SET(sldns_buffer_begin(c->buffer));
LDNS_RCODE_SET(sldns_buffer_begin(c->buffer),
LDNS_RCODE_REFUSED);
if(worker->stats.extended) {
worker->stats.qtype[qinfo.qtype]++;
}
@@ -1685,7 +1809,10 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
comm_point_drop_reply(repinfo);
return 0;
}
query_error(c->buffer, LDNS_RCODE_FORMERR, qinfo.qname_len);
sldns_buffer_rewind(c->buffer);
LDNS_QR_SET(sldns_buffer_begin(c->buffer));
LDNS_RCODE_SET(sldns_buffer_begin(c->buffer),
LDNS_RCODE_FORMERR);
if(worker->stats.extended) {
worker->stats.qtype[qinfo.qtype]++;
}
@@ -1693,17 +1820,13 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
}
if((ret=parse_edns_from_query_pkt(
c->buffer, &edns, worker->env.cfg, c, repinfo,
*worker->env.now, worker->scratchpad,
(worker->env.now ? *worker->env.now : time(NULL)),
worker->scratchpad,
worker->daemon->cookie_secrets)) != 0) {
struct edns_data reply_edns;
verbose(VERB_ALGO, "worker parse edns: formerror.");
log_addr(VERB_CLIENT, "from", &repinfo->client_addr,
repinfo->client_addrlen);
if(worker_err_ratelimit(worker, ret) == -1) {
comm_point_drop_reply(repinfo);
regional_free_all(worker->scratchpad);
return 0;
}
memset(&reply_edns, 0, sizeof(reply_edns));
reply_edns.edns_present = 1;
error_encode(c->buffer, ret, &qinfo,
@@ -1720,11 +1843,6 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
verbose(VERB_ALGO, "query with bad edns version.");
log_addr(VERB_CLIENT, "from", &repinfo->client_addr,
repinfo->client_addrlen);
if(worker_err_ratelimit(worker, EDNS_RCODE_BADVERS) == -1) {
comm_point_drop_reply(repinfo);
regional_free_all(worker->scratchpad);
return 0;
}
extended_error_encode(c->buffer, EDNS_RCODE_BADVERS, &qinfo,
*(uint16_t*)(void *)sldns_buffer_begin(c->buffer),
sldns_buffer_read_u16_at(c->buffer, 2), 0, &edns);
@@ -1770,11 +1888,6 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
else if(edns.cookie_present) {
/* Cookie present, but not valid: Cookie was bad! */
if(worker_err_ratelimit(worker, LDNS_EXT_RCODE_BADCOOKIE) == -1) {
comm_point_drop_reply(repinfo);
regional_free_all(worker->scratchpad);
return 0;
}
extended_error_encode(c->buffer,
LDNS_EXT_RCODE_BADCOOKIE, &qinfo,
*(uint16_t*)(void *)
@@ -1789,11 +1902,6 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
"need cookie or stateful transport");
log_addr(VERB_ALGO, "from",&repinfo->remote_addr
, repinfo->remote_addrlen);
if(worker_err_ratelimit(worker, LDNS_RCODE_REFUSED) == -1) {
comm_point_drop_reply(repinfo);
regional_free_all(worker->scratchpad);
return 0;
}
EDNS_OPT_LIST_APPEND_EDE(&edns.opt_list_out,
worker->scratchpad, LDNS_EDE_OTHER,
"DNS Cookie needed for UDP replies");
@@ -1820,14 +1928,14 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
verbose(VERB_ALGO, "worker request: edns is too small.");
log_addr(VERB_CLIENT, "from", &repinfo->client_addr,
repinfo->client_addrlen);
if(worker_err_ratelimit(worker, LDNS_RCODE_SERVFAIL) == -1) {
comm_point_drop_reply(repinfo);
regional_free_all(worker->scratchpad);
return 0;
}
/* A small error without qname, and TC flag on. */
query_error(c->buffer, LDNS_RCODE_SERVFAIL, 0);
LDNS_QR_SET(sldns_buffer_begin(c->buffer));
LDNS_TC_SET(sldns_buffer_begin(c->buffer));
LDNS_RCODE_SET(sldns_buffer_begin(c->buffer),
LDNS_RCODE_SERVFAIL);
sldns_buffer_set_position(c->buffer, LDNS_HEADER_SIZE);
sldns_buffer_write_at(c->buffer, 4,
(uint8_t*)"\0\0\0\0\0\0\0\0", 8);
sldns_buffer_flip(c->buffer);
regional_free_all(worker->scratchpad);
goto send_reply;
}
@@ -1835,13 +1943,7 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
server_stats_insquery(&worker->stats, c, qinfo.qtype,
qinfo.qclass, &edns, repinfo);
if(c->type != comm_udp)
#ifdef USE_DNSCRYPT
edns.udp_size = (c->dnscrypt && repinfo->is_dnscrypted)
? sldns_buffer_capacity(c->buffer) - DNSCRYPT_REPLY_HEADER_SIZE
: 65535;
#else
edns.udp_size = 65535; /* max size for TCP replies */
#endif
if(qinfo.qclass == LDNS_RR_CLASS_CH && answer_chaos(worker, &qinfo,
&edns, repinfo, c->buffer)) {
regional_free_all(worker->scratchpad);
@@ -1918,15 +2020,6 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
* ACLs allow the snooping. */
if(!(LDNS_RD_WIRE(sldns_buffer_begin(c->buffer))) &&
acl != acl_allow_snoop ) {
log_addr(VERB_ALGO, "refused nonrec (cache snoop) query from",
&repinfo->client_addr, repinfo->client_addrlen);
/* This ratelimited error query is accounted in the stats,
* as an incoming query. */
if(worker_err_ratelimit(worker, LDNS_RCODE_REFUSED) == -1) {
comm_point_drop_reply(repinfo);
regional_free_all(worker->scratchpad);
return 0;
}
if(worker->env.cfg->ede) {
EDNS_OPT_LIST_APPEND_EDE(&edns.opt_list_out,
worker->scratchpad, LDNS_EDE_NOT_AUTHORITATIVE, "");
@@ -1935,17 +2028,15 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
*(uint16_t*)(void *)sldns_buffer_begin(c->buffer),
sldns_buffer_read_u16_at(c->buffer, 2), &edns);
regional_free_all(worker->scratchpad);
log_addr(VERB_ALGO, "refused nonrec (cache snoop) query from",
&repinfo->client_addr, repinfo->client_addrlen);
goto send_reply;
}
/* 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);
@@ -1993,7 +2084,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, &rpz_passthru)) {
&edns)) {
/* prefetch it if the prefetch TTL expired.
* Note that if there is more than one pass
* its qname must be that used for cache
@@ -2111,10 +2202,11 @@ send_reply_rc:
{
struct timeval tv;
memset(&tv, 0, sizeof(tv));
if(alias_orig_qname) {
if(qinfo.local_alias && qinfo.local_alias->rrset &&
qinfo.local_alias->rrset->rk.dname) {
/* log original qname, before the local alias was
* used to resolve that CNAME to something else */
qinfo.qname = alias_orig_qname;
qinfo.qname = qinfo.local_alias->rrset->rk.dname;
log_reply_info(NO_VERBOSE, &qinfo,
&repinfo->client_addr, repinfo->client_addrlen,
tv, 1, c->buffer,
@@ -2129,7 +2221,7 @@ send_reply_rc:
}
}
#ifdef USE_DNSCRYPT
if(!dnsc_handle_uncurved_request(repinfo, c->buffer)) {
if(!dnsc_handle_uncurved_request(repinfo)) {
return 0;
}
#endif
@@ -2177,37 +2269,10 @@ worker_restart_timer(struct worker* worker)
{
if(worker->env.cfg->stat_interval > 0) {
struct timeval tv;
if(worker->daemon->stat_time_specific) {
struct timeval dest, now;
int interval = worker->env.cfg->stat_interval;
int offset = worker->daemon->stat_time_offset;
int nows, spec;
if(gettimeofday(&now, NULL) < 0)
log_err("gettimeofday: %s", strerror(errno));
#ifndef S_SPLINT_S
nows = (int)now.tv_sec;
/* The next time is on the timer interval, at the
* specific offset, time value % interval = offset. */
/* It relies on the integer division below to drop the
* remainder in order to calculate the expected
* result. */
spec = ((nows-offset)/interval+1)*interval+offset;
/* This is instead of an assertion, and should not
* be needed. So assert(spec > nows), tv is going to
* be positive. */
if(spec<=nows) spec += interval;
dest.tv_sec = spec;
dest.tv_usec = 0;
tv.tv_sec = worker->env.cfg->stat_interval;
tv.tv_usec = 0;
#endif
/* Subtract in timeval, so the fractions of a second
* are rounded to the whole specific time. */
timeval_subtract(&tv, &dest, &now);
} else {
#ifndef S_SPLINT_S
tv.tv_sec = worker->env.cfg->stat_interval;
tv.tv_usec = 0;
#endif
}
comm_timer_set(worker->stat_timer, &tv);
}
}
@@ -2242,16 +2307,23 @@ void worker_probe_timer_cb(void* arg)
}
struct worker*
worker_create(struct daemon* daemon, int id)
worker_create(struct daemon* daemon, int id, int* ports, int n)
{
unsigned int seed;
struct worker* worker = (struct worker*)calloc(1,
sizeof(struct worker));
if(!worker)
return NULL;
worker->numports = n;
worker->ports = (int*)memdup(ports, sizeof(int)*n);
if(!worker->ports) {
free(worker);
return NULL;
}
worker->daemon = daemon;
worker->thread_num = id;
if(!(worker->cmd = tube_create())) {
free(worker->ports);
free(worker);
return NULL;
}
@@ -2259,6 +2331,7 @@ worker_create(struct daemon* daemon, int id)
if(!(worker->rndstate = ub_initstate(daemon->rand))) {
log_err("could not init random numbers.");
tube_delete(worker->cmd);
free(worker->ports);
free(worker);
return NULL;
}
@@ -2274,6 +2347,9 @@ worker_init(struct worker* worker, struct config_file *cfg,
struct dt_env* dtenv = &worker->dtenv;
#else
void* dtenv = NULL;
#endif
#ifdef HAVE_GETTID
worker->thread_tid = gettid();
#endif
worker->need_to_exit = 0;
worker->base = comm_base_create(do_sigs);
@@ -2357,14 +2433,15 @@ worker_init(struct worker* worker, struct config_file *cfg,
cfg->out_ifs, cfg->num_out_ifs, cfg->do_ip4, cfg->do_ip6,
cfg->do_tcp?cfg->outgoing_num_tcp:0, cfg->ip_dscp,
worker->daemon->env->infra_cache, worker->rndstate,
cfg->use_caps_bits_for_id,
cfg->use_caps_bits_for_id, worker->ports, worker->numports,
cfg->unwanted_threshold, cfg->outgoing_tcp_mss,
&worker_alloc_cleanup, worker,
cfg->do_udp || cfg->udp_upstream_without_downstream,
worker->daemon->connect_dot_sslctx, cfg->delay_close,
cfg->tls_use_sni, dtenv, cfg->udp_connect,
cfg->max_reuse_tcp_queries, cfg->tcp_reuse_timeout,
cfg->tcp_auth_query_timeout, worker->daemon->shared_ports);
cfg->tcp_auth_query_timeout, (const char**)cfg->dist,
(const char**)cfg->dist_tsig, cfg->num_dist);
if(!worker->back) {
log_err("could not create outgoing sockets");
worker_delete(worker);
@@ -2383,8 +2460,6 @@ 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
@@ -2517,6 +2592,7 @@ worker_delete(struct worker* worker)
tube_delete(worker->cmd);
comm_timer_delete(worker->stat_timer);
comm_timer_delete(worker->env.probe_timer);
free(worker->ports);
if(worker->thread_num == 0) {
#ifdef UB_ON_WINDOWS
wsvc_desetup_worker(worker);
@@ -2537,8 +2613,6 @@ 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);
}
@@ -2547,8 +2621,7 @@ 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,
int* ratelimit_incremented)
struct module_qstate* q, int* was_ratelimited)
{
struct worker* worker = q->env->worker;
struct outbound_entry* e = (struct outbound_entry*)regional_alloc(
@@ -2560,7 +2633,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, ratelimit_incremented);
was_ratelimited);
if(!e->qsent) {
return NULL;
}
@@ -2609,8 +2682,7 @@ 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),
int* ATTR_UNUSED(ratelimit_incremented))
struct module_qstate* ATTR_UNUSED(q), int* ATTR_UNUSED(was_ratelimited))
{
log_assert(0);
return 0;
@@ -2652,11 +2724,6 @@ void libworker_event_done_cb(void* ATTR_UNUSED(arg), int ATTR_UNUSED(rcode),
log_assert(0);
}
void libworker_alloc_cleanup(void* ATTR_UNUSED(arg))
{
log_assert(0);
}
int context_query_cmp(const void* ATTR_UNUSED(a), const void* ATTR_UNUSED(b))
{
log_assert(0);
+7 -1
View File
@@ -104,6 +104,10 @@ struct worker {
struct listen_dnsport* front;
/** the backside outside network interface to the auth servers */
struct outside_network* back;
/** ports to be used by this worker. */
int* ports;
/** number of ports for this worker */
int numports;
/** the signal handler */
struct comm_signal* comsig;
/** commpoint to listen to commands. */
@@ -142,9 +146,11 @@ struct worker {
* with backpointers only. Use worker_init on it later.
* @param daemon: the daemon that this worker thread is part of.
* @param id: the thread number from 0.. numthreads-1.
* @param ports: the ports it is allowed to use, array.
* @param n: the number of ports.
* @return: the new worker or NULL on alloc failure.
*/
struct worker* worker_create(struct daemon* daemon, int id);
struct worker* worker_create(struct daemon* daemon, int id, int* ports, int n);
/**
* Initialize worker.
+15 -67
View File
@@ -366,23 +366,22 @@ static int
dns64_apply_cfg(struct dns64_env* dns64_env, struct config_file* cfg)
{
struct config_strlist* s;
const char* dns64_prefix = cfg->dns64_prefix ?
cfg->dns64_prefix : DEFAULT_DNS64_PREFIX;
verbose(VERB_ALGO, "dns64-prefix: %s", dns64_prefix);
if (!netblockstrtoaddr(dns64_prefix, 0, &dns64_env->prefix_addr,
verbose(VERB_ALGO, "dns64-prefix: %s", cfg->dns64_prefix);
if (!netblockstrtoaddr(cfg->dns64_prefix ? cfg->dns64_prefix :
DEFAULT_DNS64_PREFIX, 0, &dns64_env->prefix_addr,
&dns64_env->prefix_addrlen, &dns64_env->prefix_net)) {
log_err("cannot parse dns64-prefix netblock: %s", dns64_prefix);
log_err("cannot parse dns64-prefix netblock: %s", cfg->dns64_prefix);
return 0;
}
if (!addr_is_ip6(&dns64_env->prefix_addr, dns64_env->prefix_addrlen)) {
log_err("dns64_prefix is not IPv6: %s", dns64_prefix);
log_err("dns64_prefix is not IPv6: %s", cfg->dns64_prefix);
return 0;
}
if (dns64_env->prefix_net != 32 && dns64_env->prefix_net != 40 &&
dns64_env->prefix_net != 48 && dns64_env->prefix_net != 56 &&
dns64_env->prefix_net != 64 && dns64_env->prefix_net != 96 ) {
log_err("dns64-prefix length is not 32, 40, 48, 56, 64 or 96: %s",
dns64_prefix);
log_err("dns64-prefix length it not 32, 40, 48, 56, 64 or 96: %s",
cfg->dns64_prefix);
return 0;
}
for(s = cfg->dns64_ignore_aaaa; s; s = s->next) {
@@ -643,12 +642,6 @@ 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 ||
@@ -660,11 +653,8 @@ 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,
@@ -726,15 +716,8 @@ 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) {
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;
}
}
if(iq && iq->state != DNS64_INTERNAL_QUERY)
qstate->no_cache_store = iq->started_no_cache_store;
}
}
@@ -841,7 +824,6 @@ 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");
@@ -857,7 +839,6 @@ 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;
@@ -870,14 +851,11 @@ 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(allocated_return_msg) super->return_msg = NULL;
if(!cp)
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;
}
@@ -892,10 +870,8 @@ 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(allocated_return_msg) super->return_msg = NULL;
if(!dd)
return;
}
/* Delete negative AAAA record from cache stored by
* the iterator module */
rrset_cache_remove(super->env->rrset_cache, dk->rk.dname,
@@ -912,19 +888,15 @@ 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(allocated_return_msg) super->return_msg = NULL;
if(!dk->rk.dname)
return;
}
s = packed_rrset_sizeof(fd);
dd = (struct packed_rrset_data*)regional_alloc_init(
super->region, fd, s);
if(!dd) {
if(allocated_return_msg) super->return_msg = NULL;
if(!dd)
return;
}
}
packed_rrset_ptr_fixup(dd);
@@ -955,10 +927,8 @@ 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))) {
super->return_msg = NULL;
NULL, super->region)))
return;
}
/*
* Adjust the domain name of the answer RR set so that it matches the
@@ -1027,21 +997,6 @@ 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) {
@@ -1050,16 +1005,9 @@ 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->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 &&
if ( (!super_dq || !super_dq->started_no_cache_store) &&
!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))
+5 -32
View File
@@ -361,7 +361,7 @@ dnscrypt_server_uncurve(struct dnsc_env* env,
len -= DNSCRYPT_QUERY_HEADER_SIZE;
while (len>0 && *sldns_buffer_at(buffer, --len) == 0)
while (*sldns_buffer_at(buffer, --len) == 0)
;
if (*sldns_buffer_at(buffer, len) != 0x80) {
@@ -474,18 +474,10 @@ dnscrypt_server_curve(const dnsccert *cert,
uint8_t *const buf = sldns_buffer_begin(buffer);
size_t len = sldns_buffer_limit(buffer);
if(len + DNSCRYPT_REPLY_HEADER_SIZE > sldns_buffer_capacity(buffer))
return -1;
sldns_buffer_clear(buffer);
if(udp){
if (max_len > max_reply_size)
max_len = max_reply_size;
}
if(max_len > sldns_buffer_capacity(buffer))
max_len = sldns_buffer_capacity(buffer);
if(max_len > 65535)
max_len = 65535;
memcpy(nonce, client_nonce, crypto_box_HALF_NONCEBYTES);
@@ -528,7 +520,6 @@ dnscrypt_server_curve(const dnsccert *cert,
DNSCRYPT_MAGIC_HEADER_LEN,
nonce,
crypto_box_NONCEBYTES);
sldns_buffer_flip(buffer);
sldns_buffer_set_limit(buffer, len + DNSCRYPT_REPLY_HEADER_SIZE);
return 0;
}
@@ -672,8 +663,6 @@ dnsc_find_cert(struct dnsc_env* dnscenv, struct sldns_buffer* buffer)
}
dnscrypt_header = (struct dnscrypt_query_header *)sldns_buffer_begin(buffer);
for (i = 0U; i < dnscenv->signed_certs_count; i++) {
if(!certs[i].keypair)
continue;
if (memcmp(certs[i].magic_query, dnscrypt_header->magic_query,
DNSCRYPT_MAGIC_HEADER_LEN) == 0) {
return &certs[i];
@@ -815,7 +804,6 @@ dnsc_parse_keys(struct dnsc_env *env, struct config_file *cfg)
sizeof *env->keypairs);
env->certs = sodium_allocarray(env->signed_certs_count,
sizeof *env->certs);
memset(env->certs, 0, env->signed_certs_count * sizeof(*env->certs));
cert_id = 0U;
keypair_id = 0U;
@@ -842,14 +830,7 @@ 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;
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++];
dnsccert *current_cert = &env->certs[cert_id++];
found_cert = 1;
current_cert->keypair = current_keypair;
memcpy(current_cert->magic_query,
@@ -931,13 +912,12 @@ dnsc_handle_curved_request(struct dnsc_env* dnscenv,
}
int
dnsc_handle_uncurved_request(struct comm_reply *repinfo,
struct sldns_buffer* buffer)
dnsc_handle_uncurved_request(struct comm_reply *repinfo)
{
if(!repinfo->c->dnscrypt) {
return 1;
}
sldns_buffer_copy(repinfo->c->dnscrypt_buffer, buffer);
sldns_buffer_copy(repinfo->c->dnscrypt_buffer, repinfo->c->buffer);
if(!repinfo->is_dnscrypted) {
return 1;
}
@@ -983,19 +963,12 @@ dnsc_create(void)
int
dnsc_apply_cfg(struct dnsc_env *env, struct config_file *cfg)
{
int nkeys;
if(dnsc_parse_certs(env, cfg) <= 0) {
fatal_exit("dnsc_apply_cfg: no cert file loaded");
}
nkeys = dnsc_parse_keys(env, cfg);
if(nkeys <= 0) {
if(dnsc_parse_keys(env, cfg) <= 0) {
fatal_exit("dnsc_apply_cfg: no key file loaded");
}
if((size_t)nkeys < env->signed_certs_count) {
fatal_exit("dnsc_apply_cfg: %u dnscrypt-provider-cert file(s) have no "
"matching dnscrypt-secret-key",
(unsigned)(env->signed_certs_count - (size_t)nkeys));
}
randombytes_buf(env->hash_key, sizeof env->hash_key);
env->provider_name = cfg->dnscrypt_provider;
+1 -2
View File
@@ -128,8 +128,7 @@ int dnsc_handle_curved_request(struct dnsc_env* dnscenv,
* \return 0 in case of failure.
*/
int dnsc_handle_uncurved_request(struct comm_reply *repinfo,
struct sldns_buffer* buffer);
int dnsc_handle_uncurved_request(struct comm_reply *repinfo);
/**
* Computes the size of the shared secret cache entry.
+17 -36
View File
@@ -176,29 +176,26 @@ dt_create(struct config_file* cfg)
env->dtio = dt_io_thread_create();
if(!env->dtio) {
log_err("malloc failure");
dt_delete(env);
free(env);
return NULL;
}
if(!dt_io_thread_apply_cfg(env->dtio, cfg)) {
dt_delete(env);
return NULL;
}
if(!dt_apply_cfg(env, cfg)) {
dt_delete(env);
dt_io_thread_delete(env->dtio);
free(env);
return NULL;
}
dt_apply_cfg(env, cfg);
return env;
}
static int
static void
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;
env->len_identity = 0;
return 1;
return;
}
free(env->identity);
if (cfg->dnstap_identity == NULL || cfg->dnstap_identity[0] == 0) {
@@ -206,49 +203,36 @@ dt_apply_identity(struct dt_env *env, struct config_file *cfg)
buf[MAXHOSTNAMELEN] = 0;
env->identity = strdup(buf);
} else {
log_err("dt_apply_identity: gethostname() failed: %s",
strerror(errno));
env->identity = NULL;
env->len_identity = 0;
return 0;
fatal_exit("dt_apply_identity: gethostname() failed");
}
} else {
env->identity = strdup(cfg->dnstap_identity);
}
if (env->identity == NULL) {
log_err("dt_apply_identity: strdup() failed");
env->len_identity = 0;
return 0;
}
if (env->identity == NULL)
fatal_exit("dt_apply_identity: strdup() failed");
env->len_identity = (unsigned int)strlen(env->identity);
verbose(VERB_OPS, "dnstap identity field set to \"%s\"",
env->identity);
return 1;
}
static int
static void
dt_apply_version(struct dt_env *env, struct config_file *cfg)
{
if (!cfg->dnstap_send_version) {
free(env->version);
env->version = NULL;
env->len_version = 0;
return 1;
return;
}
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) {
log_err("dt_apply_version: strdup() failed");
env->len_version = 0;
return 0;
}
if (env->version == NULL)
fatal_exit("dt_apply_version: strdup() failed");
env->len_version = (unsigned int)strlen(env->version);
verbose(VERB_OPS, "dnstap version field set to \"%s\"",
env->version);
return 1;
}
void
@@ -292,18 +276,15 @@ dt_apply_logcfg(struct dt_env *env, struct config_file *cfg)
lock_basic_unlock(&env->sample_lock);
}
int
void
dt_apply_cfg(struct dt_env *env, struct config_file *cfg)
{
if (!cfg->dnstap)
return 1;
return;
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
View File
@@ -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.
*/
int dt_apply_cfg(struct dt_env *env, struct config_file *cfg);
void
dt_apply_cfg(struct dt_env *env, struct config_file *cfg);
/**
* Apply config settings for log enable for message types.
+1 -15
View File
@@ -448,9 +448,6 @@ int dt_io_thread_apply_cfg(struct dt_io_thread* dtio, struct config_file *cfg)
dtio->tls_use_sni = cfg->tls_use_sni;
#endif /* HAVE_SSL */
}
#ifdef HAVE_GETTID
dtio->thread_tid_log = cfg->log_thread_id;
#endif
return 1;
}
@@ -2133,18 +2130,7 @@ static void* dnstap_io(void* arg)
struct dt_io_thread* dtio = (struct dt_io_thread*)arg;
time_t secs = 0;
struct timeval now;
const char name[16] = "unbound/dnstap"; /* seems to be the safest size
between different OSes */
#if defined(HAVE_GETTID) && !defined(THREADS_DISABLED)
dtio->thread_tid = gettid();
if(dtio->thread_tid_log)
log_thread_set(&dtio->thread_tid);
else
#endif
log_thread_set(&dtio->threadnum);
ub_thread_setname(ub_thread_self(), name);
log_thread_set(&dtio->threadnum);
/* setup */
verbose(VERB_ALGO, "start dnstap io thread");
-6
View File
@@ -131,12 +131,6 @@ struct dt_io_thread {
struct dt_io_list_item* io_list_iter;
/** 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
/** if the io processing has started */
int started;
/** ssl context for the io thread, for tls connections. type SSL_CTX* */
+11 -28
View File
@@ -330,7 +330,7 @@ static struct tap_socket* tap_socket_new_tcpaccept(char* ip,
/** create new socket (unconnected, not base-added), or NULL malloc fail */
static struct tap_socket* tap_socket_new_tlsaccept(char* ip,
void (*ev_cb)(int, short, void*), void* data, char* server_key,
char* server_cert, char* verifypem, char* tls_protocols)
char* server_cert, char* verifypem)
{
struct tap_socket* s = calloc(1, sizeof(*s));
if(!s) {
@@ -347,7 +347,7 @@ static struct tap_socket* tap_socket_new_tlsaccept(char* ip,
s->ev_cb = ev_cb;
s->data = data;
s->sslctx = listen_sslctx_create(server_key, server_cert, verifypem,
NULL, NULL, 0, 0, 0, tls_protocols);
NULL, NULL, 0, 0, 0, 0);
if(!s->sslctx) {
log_err("could not create ssl context");
free(s->ip);
@@ -1261,13 +1261,13 @@ static void setup_tcp_list(struct main_tap_data* maindata,
/** setup tls accept sockets */
static void setup_tls_list(struct main_tap_data* maindata,
struct config_strlist_head* tls_list, char* server_key,
char* server_cert, char* verifypem, char* tls_protocols)
char* server_cert, char* verifypem)
{
struct config_strlist* item;
for(item = tls_list->first; item; item = item->next) {
struct tap_socket* s;
s = tap_socket_new_tlsaccept(item->str, &dtio_mainfdcallback,
maindata, server_key, server_cert, verifypem, tls_protocols);
maindata, server_key, server_cert, verifypem);
if(!s) fatal_exit("out of memory");
if(!tap_socket_list_insert(&maindata->acceptlist, s))
fatal_exit("out of memory");
@@ -1300,7 +1300,7 @@ static void
setup_and_run(struct config_strlist_head* local_list,
struct config_strlist_head* tcp_list,
struct config_strlist_head* tls_list, char* server_key,
char* server_cert, char* verifypem, char* tls_protocols)
char* server_cert, char* verifypem)
{
time_t secs = 0;
struct timeval now;
@@ -1326,7 +1326,7 @@ setup_and_run(struct config_strlist_head* local_list,
setup_local_list(maindata, local_list);
setup_tcp_list(maindata, tcp_list);
setup_tls_list(maindata, tls_list, server_key, server_cert,
verifypem, tls_protocols);
verifypem);
if(!tap_socket_list_addevs(maindata->acceptlist, base))
fatal_exit("could not setup accept events");
if(verbosity) log_info("start of service");
@@ -1462,8 +1462,6 @@ int main(int argc, char** argv)
struct config_strlist_head tcp_list;
struct config_strlist_head tls_list;
char* server_key = NULL, *server_cert = NULL, *verifypem = NULL;
char* tls_protocols = "TLSv1.2 TLSv1.3";
#ifdef USE_WINSOCK
WSADATA wsa_data;
if(WSAStartup(MAKEWORD(2,2), &wsa_data) != 0) {
@@ -1563,25 +1561,17 @@ int main(int argc, char** argv)
#else
OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS
| OPENSSL_INIT_ADD_ALL_DIGESTS
| OPENSSL_INIT_LOAD_CRYPTO_STRINGS
# if defined(OPENSSL_INIT_NO_LOAD_CONFIG) && defined(UB_ON_WINDOWS)
| OPENSSL_INIT_NO_LOAD_CONFIG
# endif
, NULL);
| OPENSSL_INIT_LOAD_CRYPTO_STRINGS, NULL);
#endif
#if OPENSSL_VERSION_NUMBER < 0x10100000 || !defined(HAVE_OPENSSL_INIT_SSL)
(void)SSL_library_init();
#else
(void)OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS
# if defined(OPENSSL_INIT_NO_LOAD_CONFIG) && defined(UB_ON_WINDOWS)
| OPENSSL_INIT_NO_LOAD_CONFIG
# endif
, NULL);
(void)OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS, NULL);
#endif
#endif /* HAVE_SSL */
}
setup_and_run(&local_list, &tcp_list, &tls_list, server_key,
server_cert, verifypem, tls_protocols);
server_cert, verifypem);
config_delstrlist(local_list.first);
config_delstrlist(tcp_list.first);
config_delstrlist(tls_list.first);
@@ -1659,8 +1649,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(ratelimit_incremented))
struct module_qstate* ATTR_UNUSED(q), int* ATTR_UNUSED(was_ratelimited))
{
log_assert(0);
return 0;
@@ -1694,8 +1683,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(ratelimit_incremented))
struct module_qstate* ATTR_UNUSED(q), int* ATTR_UNUSED(was_ratelimited))
{
log_assert(0);
return 0;
@@ -1737,11 +1725,6 @@ void libworker_event_done_cb(void* ATTR_UNUSED(arg), int ATTR_UNUSED(rcode),
log_assert(0);
}
void libworker_alloc_cleanup(void* ATTR_UNUSED(arg))
{
log_assert(0);
}
int context_query_cmp(const void* ATTR_UNUSED(a), const void* ATTR_UNUSED(b))
{
log_assert(0);
-981
View File
@@ -1,984 +1,3 @@
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.
- Fix CVE-2026-42944, Heap overflow and crash with multiple nsid,
cookie, padding EDNS options. Thanks to Qifan Zhang, Palo Alto
Networks, for the report.
- Fix CVE-2026-42959, Crash during DNSSEC validation of malicious
content. Thanks to Qifan Zhang, Palo Alto Networks, for the report.
- Fix CVE-2026-32792, Packet of death with DNSCrypt. Thanks to Andrew
Griffiths from 'calif.io' for the report.
- Fix CVE-2026-40622, "Ghost domain name" variant. Thanks to Qifan
Zhang, Palo Alto Networks, for the report.
- Fix CVE-2026-41292, Parsing a long list of incoming EDNS options
degrades performance. Thanks to GitHub user 'N0zoM1z0', also Qifan
Zhang from Palo Alto Networks, for the report.
- Fix CVE-2026-42534, Jostle logic bypass degrades resolution
performance. Thanks to Qifan Zhang, Palo Alto Networks, for the
report.
- Fix CVE-2026-42923, Degradation of service with unbounded NSEC3
hash calculations. Thanks to Qifan Zhang, Palo Alto Networks, for
the report.
- Fix CVE-2026-42960, Possible cache poisoning attack while following
delegation. Thanks to TaoFei Guo from Peking University, Yang Luo
and JianJun Chen, Tsinghua University, for the report.
- Fix CVE-2026-44390, Unbounded name compression in certain cases
causes degradation of service. Thanks to Qifan Zhang, Palo Alto
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
doq_repinfo_retrieve_localaddr().
- For #1441: Fix type of ipv6 addr struct.
21 April 2026: Wouter
- Add test case for malformed SVCB records. Thanks to
Qifan Zhang, Palo Alto Networks for the additional test.
- Fix for the Jiggle Attack. The server is fixed to answer
with errors for error cases, and does not stay silent.
In addition, the error replies do not contain parts of the
incoming query. This is more conformant, stops reflection
and stops it as a covert channel. Thanks to Yuqi Qiu and
Xiang Li, Nankai University (AOSP Lab) for the report.
In addition, thanks to Qifan Zhang, Palo Alto Networks, for
noting the fingerprinting possibility, that is also fixed
with this.
- Fix EDNS extended RCODE reflection. This fixes that
the server does not echo extended rcode values after class
chaos queries. Thanks to Qifan Zhang, Palo Alto Networks
for the report.
- Fix for iterator RCODE handling of YXDOMAIN. This fixes
that the server only accepts YXDOMAIN answers that contain
a DNAME record. This stops bad answers, and checks that
the authoritative server gives correct replies.
Thanks to Qifan Zhang, Palo Alto Networks for the report.
- Fix for missing bounds check for decompressing dnames
for downloaded authority zones. This fixes that the server
could end up with malformed zone content after receiving
truncated packet contents from an AXFR. In addition, the
domain names in the SOA rdata are checked before the
authority code picks up the zone serial.
Thanks to Halil Oktay for the report.
- Fix that upstream TLS connections are not reused as TLS
connections for a different name, at the same IP. This
checks that the tls name is correct when reusing the
upstream connections. Thanks to TaoFei Guo from Peking
University and JianJun Chen from Tsinghua University for
the report.
- Fix that signatures are not allowed with revoked dnskeys.
Thanks to Qifan Zhang, Palo Alto Networks for the report.
- Fix that a DNAME with an unsigned CNAME is checked for
the correct match. This stops that for certain zone
configurations an unchecked unsigned CNAME could get
secure status. Thanks to Qifan Zhang, Palo Alto Networks
for the report.
- Fix handling of wildcard CNAMEs in the chain of trust.
An improper wildcard in the chain of trust would send
the retries to the wrong upstream. Also it could label
the step in the chain of trust as secure, when it was not.
Thanks to Qifan Zhang, Palo Alto Networks for the report.
- Set version number to 1.25.0 of code repository.
- Fix doxygen comment syntax.
20 April 2026: Wouter
- Fix compile warnings for thread setname routine, and test compile.
- Fix unused variable warning when compiled without ssl.
- Fix test with https zone for libressl.
17 April 2026: Wouter
- Fix setup of ssl context copy of the tls service pem option,
from a clang analyzer warning.
- Fix setup of ssl context copy, to check for the tls service
pem option for stat calls.
- Fix to compile the shm code when there is no shmget.
- Update github ci to use actions/checkout@v6.
- Update github ci cross platform to use
cross-platform-actions/action@v1.0.0.
- Fix github ci to speed up with parralel build, for windows ci.
- Fix compat/chacha_private sigma and tau definitions to use
nonstring attribute.
- Fix compat/gmtime_r old style definition syntax.
- Fix to increase size of the buffer for the win_svc reportev log
function.
- Fix ttl comparisons in rdata_copy for 32bit signed or unsigned.
- Fix subnet store of servfail to not leak memory.
- Update generated man pages.
- Update generated configure, with autoconf.
- Fix pthread_setname detection to fail on warnings.
17 April 2026: Yorgos
- Merge #1400: Support pthread_setname_np. Adds support for
pthread_setname_np and variants to set the name on spawned threads
for easier debugging/monitoring.
16 April 2026: Yorgos
- Merge #1406: Introduce new 'tls-protocols' configuration option.
- Introduce new 'tls-protocols' configuration option that specifies
which of the supported TLS protocols will be used.
This change invalidates some previous changes:
- TLSv1.2 is again enabled by default, but can be selectively turned
off if desired (related to #1303).
- The biefly introduced (not yet released) 'tls-use-system-versions'
configuration option, that addressed #1346, is reverted in favor of
'tls-protocols'.
- The briefly introduced (not yet released) '--enable-system-tls'
configure option, related to #1401, is no longer needed with the new
option and the current default.
- Fix cleaning up DoH session. The same query can be on multiple
streams in a session.
16 April 2026: Wouter
- Fix configure, autoconf for #1406.
15 April 2026: Wouter
- Fix RFC7766 compliance when client sends EOF over TCP. It stops
pending replies and closes. Thanks to Yuxiao Wu, Tsinghua
University for the report.
- Fix to shorten RRSIG count in scrubber, this protects against
an overly large number of RRSIGs. It can be configured with
`iter-scrub-rrsig: 8`, it has default 8. Thanks to Yuxiao Wu,
Tsinghua University for the report.
14 April 2026: Wouter
- Fix #1017: memory corruption related core dumps.
When alloc_reg_obtain has an empty list, return a new allocation.
- Fix clang analyzer warning for subnetmod, when return_msg is
NULL for update cache, like when it stores servfail status.
- iana portlist updated.
13 April 2026: Yorgos
- Update the documentation of 'max-query-restarts' in the man page.
10 April 2026: Wouter
- Fix for EDNS client subnet so that it does not store SERVFAIL in
the global cache after a failed lookup, such as timeouts. A failure
entry is stored in the subnet cache, for the query name, for a
couple of seconds. Queries can continue to use the subnet cache
during that time.
7 April 2026: Yorgos
- Fix unused variable warning.
30 March 2026: Wouter
- Merge #1408: Fix shared memory stats with threads.
27 March 2026: Wouter
- Fix to allow the control-interface config to use ip@port notation.
- Fix test code to allow empty hex answer packets from testbound.
- Fix defense in depth for service callback with empty packet.
24 March 2026: Wouter
- Fix to check for invalid http content length and chunk size,
and to check the RR rdata field lengths when decompressing and
inserting RRs from an authority zone transfer. This stops
large memory use and heap buffer-overflow read errors. Thanks
to Haruto Kimura (Stella) for the report.
20 March 2026: Wouter
- Fix for testcode pktview to check buffer size and log errors.
13 March 2026: Yorgos
- Fix to ignore out-of-zone DNAME records for CNAME synthesis. Thanks
to Yuxiao Wu, Yiyi Wang, Zhang Chao, Baojun Liu, and Haixin Duan from
Tsinghua University.
13 March 2026: Wouter
- Fix #278: DoT: complete unbound restart required on certificate
renew. Fix so that a reload checks if the files have changed, and
if so, reload the contexts. Also for DoH, DoQ and outgoing DoT.
- iana portlist updated.
- For #278: fast_reload can reload tls-service-key, tls-service-pem
and tls-cert-bundle changes. It checks the modification time of
the tls-service-key and tls-service-pem files for update.
- Fix detection of http listening port in fast_reload.
- Fix to add tls-service-key to memory printout for fast_reload.
9 March 2026: Wouter
- Fix compile failure in unbound-checkconf for older gcc compiler.
- Merge #1418: Apply cache TTL policy to DNAME and synthesized
CNAME on wire path.
6 March 2026: Wouter
- Merge #1415: Add lock unlock for view in memory error handling.
6 March 2026: Yorgos
- Document the suggestion for a higher value for 'outgoing-range';
helps when the request list is full.
- Warn for unused 'nodefault' local-zone configuration in
unbound-checkconf (related to #1416).
5 March 2026: Wouter
- Fix for DNS Rebinding Bypass via SVCB/HTTPS Records in Unbound.
Thanks to Kunta Chu, School of Software, Tsinghua University,
Taofei Guo, Peking University, and Jianjun Chen, Institute for
Network Sciences and Cyberspace, Tsinghua University for the
report. The private-address option is fixed to also elide
SVCB and HTTPS records that match the filter.
- Update generated man pages.
4 March 2026: Yorgos
- For #1411: Introduce a failing case in the rpl test so that it only
passes with the fix in place.
3 March 2026: Wouter
- Merge #1411: Allow synthesized DNAME TTL=0 to be served from cache
within grace period. The responses are served from cache within
a 1-second grace period. Reduces recursion when authoritative
servers return DNAME with TTL=0 (RFC 2308). Response
still returns TTL=0 to clients. Adds a test for it.
- For #1411: Fix that the lookup for DNAME uses flag. Fix assertion
in expired calc debug routine.
27 February 2026: Wouter
- Merge #1409: Documentation CNAME in redirect-type local-zone.
- Update generated man pages.
25 February 2026: Wouter
- Fix validator to set unchecked when validation recursion
requests are passed. The edns subnet module checks if validation
is needed for a cache response, and set the validator to protect
the cache with validation for non-subnet lookups.
23 February 2026: Wouter
- Fix to have cachedb not return expired bogus data as non-bogus.
- Fix to make the cachedb_val_expired.crpl succeed.
23 February 2026: Yorgos
- Fix to disallow cache lookup/store in external cachedb when a
forwarder/stub forbids it with the no-cache option.
- Fixed some typos reported in #1395 by rezky_nightky.
17 February 2026: Wouter
- Fix to remove unused conditional from cookie timestamp at
worker env.
- For #1405: local-zone always_refuse also blocks queries of type DS.
16 February 2026: Yorgos
- Fix #1404: Priming the root key fails after loading ipfire.org RPZ
zones. Fixed by including the ZONEMD RRtype in the list of types to
ignore for RPZ zones. Analysis and patch provided by ummeegge.
16 February 2026: Wouter
- Fix that cachedb aggressive negative responses have the RA flag set.
11 February 2026: Wouter
- Fix #1403: Inconsistency between do-nat64 and do-not-query-address
during retries.
9 February 2026: Wouter
- Merge #1401: Add a new build-time option for system TLS.
The --enable-system-tls flag enables the
tls-use-system-policy-versions setting by default.
- Update generated man pages.
6 February 2026: Yorgos
- Fix #1389: [FR] replacement with ECC-GOST12 according to RFC9558.
Patch contributed by Igor V. Ruzanov, available in
contrib/gost12.patch.
4 February 2026: Wouter
- Fix local privilege escalation on Windows. Thanks to Hao Huang and
CrisprXiang with Fudan University for the report. The OpenSSL
init calls are set to not load the openssl.cnf file when compiled
for Windows.
3 February 2026: Yorgos
- Eagerly remove .skip mark files in between mini_tdir.sh runs in case
there has been a change on the environment.
27 January 2026: Wouter
- Add test for allow-notify with a host name.
26 January 2026: Wouter
- Fix that allow-notify entries with hostnames are copied after IPv4
and IPv6 lookup.
- Fix to not skip allow-notify hostname lookups when there are only
urls.
23 January 2026: Yorgos
- Merge #1396: Log Linux thread ID.
- On Linux systems log the system-wide unique thread ID instead of
Unbound's internal thread counter.
- Introduce the 'log-thread-id' configuration option to manage logging
the system-wide Linux thread ID for easier debugging with system
tools.
- Update generated man pages.
22 January 2026: Wouter
- Fix that fast reload copies the iter_scrub_ns, iter_scrub_cname
and max_global_quota options.
- Fix http test tool petal to not print errors when there is no
error.
21 January 2026: Wouter
- Merge #1388: QNX Porting support for unbound.
19 January 2026: Wouter
- Merge #1392: Include "V" (version) option in synopsis.
15 January 2026: Wouter
- Fix documentation for requestlist.overwritten and
requestlist.exceeded, it explains which query was dropped.
8 January 2026: Wouter
- Merge #1381: Do not initialize quic_table unless it is enabled.
6 January 2026: Wouter
- Fix edns subnet, that scope zero queries, when there is a
subquery without subnet, and the forward-no-cache or
stub-no-cache option is set, it is not stored in cache due to
the forward or stub option.
6 January 2026: Yorgos
- Merge #1391 from Götz Görisch: Fix documentation to adhere to
RFC5952.
31 December 2025: Yorgos
- Update the unbound-anchor man page to note write permissions of the
generated file if it is to be used with Unbound's
auto-trust-anchor-file option.
- Use the same EDE removal logic when encoding errors as when encoding
replies.
30 December 2025: Yorgos
- Mark "THROWAWAY" and "(DNSSEC) LAME" responses clearly as Unbound's
categorization in the log output.
24 December 2025: Yorgos
- More specific wording in the unbound.conf man page for stub-first
and forward-first options.
3 December 2025: Wouter
- Fix http2 drop handling to clear the postpone_drop state so that
other streams on the http2 session are not affected by a drop,
and can clean up properly if also dropped. Fix http2 send reply
so that when there is a send failure is does not recurse into
the mesh functions and also does not drop the connection due to
the condition of one stream.
2 December 2025: Wouter
- Fix to remove http2 stream mesh state when mesh new request is
dropping the new request.
1 December 2025: Wouter
- Fix to add EDNS CO flag to testbound and debug message log.
- Fix header comment about EDE reference in validator/val_sigcrypt.h.
28 November 2025: Yorgos
- For #1375, there is no DNSTAP environment if it wasn't configured.
26 November 2025: Yorgos
- Tag for 1.24.2 release.
The repository continues with version 1.24.3.
13 November 2025: Wouter
- Merge #1374: Mesh reply counters.
This adds the statistics num.queries.replyaddr_limit and
requestlist.current.replies.
- Merge #1375: Copy DNSTAP changes from daemon to workers after
fast_reload.
12 November 2025: Wouter
- Fix that when discard timeout drops packet, they are accounted as
less reply addresses in use in the mesh area.
- iana portlist updated.
6 November 2025: Wouter
- Fix add comment to worker_handle_request function that explain it.
- Fix configure test for noreturn attribute so it compiles without
warning.
- Fix configure test for nonstring attribute so that it does not
accept when the compiler prints a warning about an unknown
attribute.
4 November 2025: Wouter
- Fix dns64 log output to log the default instead of a null string.
1 November 2025: Yorgos
- Fix #1366: Infra cache does not work correctly for NAT64, by
moving the NAT64 synthesis from the iterator when selecting a target
address, to the delegation point itself when adding target
addresses.
27 October 2025: Yorgos
- Merge #1331 from Jitka Plesníková: Replace deprecated $function by
new $action, for SWIG.
+3 -3
View File
@@ -13,7 +13,7 @@ If you're not using DNSSEC then you may remove "validator".
2. The "dns64-prefix" directive indicates your DNS64 prefix. For example:
dns64-prefix: 64:ff9b::/96
dns64-prefix: 64:FF9B::/96
The prefix must be a /96 or shorter.
@@ -42,9 +42,9 @@ To enable NAT64 in Unbound, add to unbound.conf's "server" section:
do-nat64: yes
The NAT64 prefix defaults to the DNS64 prefix, which in turn defaults to the
standard 64:ff9b::/96 prefix. You can reconfigure it with:
standard 64:FF9B::/96 prefix. You can reconfigure it with:
nat64-prefix: 64:ff9b::/96
nat64-prefix: 64:FF9B::/96
To test NAT64 operation, pick a domain that only has IPv4 reachability for its
nameservers and try resolving any names in that domain.
+29 -28
View File
@@ -54,7 +54,7 @@ server:
# interface: 192.0.2.153
# interface: 192.0.2.154
# interface: 192.0.2.154@5003
# interface: 2001:db8::5
# interface: 2001:DB8::5
# interface: eth0@5003
# enable this feature to copy the source address of queries to reply.
@@ -72,12 +72,12 @@ server:
# server from by ip-address. If none, the default (all) interface
# is used. Specify every interface on a 'outgoing-interface:' line.
# outgoing-interface: 192.0.2.153
# outgoing-interface: 2001:db8::5
# outgoing-interface: 2001:db8::6
# outgoing-interface: 2001:DB8::5
# outgoing-interface: 2001:DB8::6
# Specify a netblock to use remainder 64 bits as random bits for
# upstream queries. Uses freebind option (Linux).
# outgoing-interface: 2001:db8::/64
# outgoing-interface: 2001:DB8::/64
# Also (Linux:) ip -6 addr add 2001:db8::/64 dev lo
# And: ip -6 route add local 2001:db8::/64 dev lo
# And set prefer-ip6: yes to use the ip6 randomness from a netblock.
@@ -193,9 +193,6 @@ server:
# Limit on number of CNAME, DNAME records for incoming packets.
# iter-scrub-cname: 11
# Limit on number of RRSIGs for an RRset for incoming packets.
# iter-scrub-rrsig: 8
# Limit on upstream queries for an incoming query and its recursion.
# max-global-quota: 200
@@ -382,7 +379,7 @@ server:
# interface-action: 192.0.2.153 allow
# interface-action: 192.0.2.154 allow
# interface-action: 192.0.2.154@5003 allow
# interface-action: 2001:db8::5 allow
# interface-action: 2001:DB8::5 allow
# interface-action: eth0@5003 allow
# Similar to 'access-control-tag:' but for interfaces.
@@ -499,10 +496,6 @@ server:
# print log lines that say why queries return SERVFAIL to clients.
# log-servfail: no
# log system-wide Linux thread ID, insted of Unbound's internal thread
# counter. Only on Linux and only when threads are available.
# log-thread-id: no
# the pid file. Can be an absolute path outside of chroot/work dir.
# pidfile: "@UNBOUND_PIDFILE@"
@@ -665,7 +658,7 @@ server:
# or, just before the iterator).
# module-config: "validator iterator"
# File with trusted keys, kept up-to-date using RFC5011 probes,
# File with trusted keys, kept uptodate using RFC5011 probes,
# initial file like trust-anchor-file, then it stores metadata.
# Use several entries, one per domain name, to track multiple zones.
#
@@ -725,7 +718,7 @@ server:
# val-max-restart: 5
# Should additional section of secure message also be kept clean of
# non-secure data. Useful to shield the users of this validator from
# unsecure 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
@@ -899,10 +892,6 @@ 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.
#
@@ -972,12 +961,16 @@ server:
# tls-ciphersuites: "TLS_AES_128_GCM_SHA256:TLS_AES_128_CCM_8_SHA256:TLS_AES_128_CCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256"
# Use the SNI extension for TLS connections. Default is yes.
# Changing the value requires a restart.
# Changing the value requires a reload.
# tls-use-sni: yes
# TLS protocols.
# Changing the value requires a restart.
# tls-protocols: "TLSv1.2 TLSv1.3"
# Allow general-purpose version-flexible TLS server configuration that
# may be further restricted by the system's policy.
# Use only if you want to support legacy TLS client connections.
# Default is no and Unbound will only use the latest available TLS
# version.
# Changing the value requires a reload.
# tls-use-system-policy-versions: no
# Add the secret file for TLS Session Ticket.
# Secret file must be 80 bytes of random data.
@@ -1262,7 +1255,8 @@ remote-control:
# authoritatively. zonefile: reads from file (and writes to it if you also
# download it), primary: fetches with AXFR and IXFR, or url to zonefile.
# With allow-notify: you can give additional (apart from primaries and urls)
# sources of notifies.
# sources of notifies. primary-tsig: and allow-notify-tsig: use addr keyname,
# with the name of the TSIG key to use, declared as a tsig-key:.
# auth-zone:
# name: "."
# primary: 170.247.170.2 # b.root-servers.net
@@ -1291,9 +1285,6 @@ 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.
@@ -1447,6 +1438,7 @@ remote-control:
# and drop. Policies can be loaded from a file, or using zone
# transfer, or using HTTP. The respip module needs to be added
# to the module-config, e.g.: module-config: "respip validator iterator".
# Can also use primary-tsig: and allow-notify-tsig:
# rpz:
# name: "rpz.example.com"
# zonefile: "rpz.example.com"
@@ -1460,5 +1452,14 @@ remote-control:
# rpz-signal-nxdomain-ra: no
# for-downstream: no
# tags: "example"
# max-transfer-size: 0
# max-transfer-time: 0
# TSIG keys
# tsig-key:
# # The key name is sent to the other party, it must be the same
# name: "keyname"
# # algorithm hmac-md5, or sha1, sha256, sha224, sha384, sha512
# algorithm: sha256
# # secret material, must be the same as the other party uses.
# # base64 encoded random number.
# # e.g. from dd if=/dev/random of=/dev/stdout count=1 bs=32 | base64
# secret: "K2tf3TRjvQkVCmJF3/Z9vA=="
+1 -1
View File
@@ -416,6 +416,6 @@ on a function return with file read failure.
.SH AUTHOR
Unbound developers are mentioned in the CREDITS file in the distribution.
.SH COPYRIGHT
1999-2026, NLnet Labs
1999-2025, NLnet Labs
.\" Generated by docutils manpage writer.
.
+4 -13
View File
@@ -39,17 +39,9 @@ unbound-anchor \- Unbound @version@ anchor utility.
validation.
The program fetches the trust anchor with the method from \fI\%RFC 7958\fP when
regular \fI\%RFC 5011\fP update fails to bring it up to date.
It can be run from the commandline, or run as part of startup scripts before
you start the \fI\%unbound(8)\fP DNS server.
.sp
Note that if you want to use \fI\%RFC 5011\fP with Unbound (i.e., the
\fI\%auto\-trust\-anchor\-file\fP option) so
that trust anchor information is automatically tracked by Unbound during
operation, the user that Unbound runs under (by default \(aqunbound\(aq) must have
write permissions to the file and the directory the file lives in (for creating
temporary files).
In this case you would probably want to run this program as the designated
Unbound user.
It can be run (as root) from the commandline, or run as part of startup
scripts.
Before you start the \fI\%unbound(8)\fP DNS server.
.sp
Suggested usage:
.INDENT 0.0
@@ -60,7 +52,6 @@ Suggested usage:
# in the init scripts.
# provide or update the root anchor (if necessary)
unbound\-anchor \-a \(dq@UNBOUND_ROOTKEY_FILE@\(dq
# Please note usage of this root anchor is at your own risk
# and under the terms of our LICENSE (see source).
#
@@ -304,6 +295,6 @@ Signature on the root key information.
.SH AUTHOR
Unbound developers are mentioned in the CREDITS file in the distribution.
.SH COPYRIGHT
1999-2026, NLnet Labs
1999-2025, NLnet Labs
.\" Generated by docutils manpage writer.
.
+3 -12
View File
@@ -51,17 +51,9 @@ Description
validation.
The program fetches the trust anchor with the method from :rfc:`7958` when
regular :rfc:`5011` update fails to bring it up to date.
It can be run from the commandline, or run as part of startup scripts before
you start the :doc:`unbound(8)</manpages/unbound>` DNS server.
Note that if you want to use :rfc:`5011` with Unbound (i.e., the
:ref:`auto-trust-anchor-file<unbound.conf.auto-trust-anchor-file>` option) so
that trust anchor information is automatically tracked by Unbound during
operation, the user that Unbound runs under (by default 'unbound') must have
write permissions to the file and the directory the file lives in (for creating
temporary files).
In this case you would probably want to run this program as the designated
Unbound user.
It can be run (as root) from the commandline, or run as part of startup
scripts.
Before you start the :doc:`unbound(8)</manpages/unbound>` DNS server.
Suggested usage:
@@ -70,7 +62,6 @@ Suggested usage:
# in the init scripts.
# provide or update the root anchor (if necessary)
unbound-anchor -a "@UNBOUND_ROOTKEY_FILE@"
# Please note usage of this root anchor is at your own risk
# and under the terms of our LICENSE (see source).
#
+1 -1
View File
@@ -88,6 +88,6 @@ Unbound configuration file.
.SH AUTHOR
Unbound developers are mentioned in the CREDITS file in the distribution.
.SH COPYRIGHT
1999-2026, NLnet Labs
1999-2025, NLnet Labs
.\" Generated by docutils manpage writer.
.
+1 -42
View File
@@ -168,8 +168,6 @@ ipset,
\fI\%tcp\-auth\-query\-timeout\fP,
\fI\%delay\-close\fP\&.
\fI\%iter\-scrub\-promiscuous\fP\&.
\fI\%tls\-service\-key\fP\&.
\fI\%tls\-service\-pem\fP\&.
.sp
It does not work with
\fI\%interface\fP and
@@ -354,8 +352,6 @@ 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
@@ -884,11 +880,6 @@ number of queries removed due to discard\-timeout by thread
.UNINDENT
.INDENT 0.0
.TP
.B threadX.num.queries_replyaddr_limit
number of queries removed due to replyaddr limits by thread
.UNINDENT
.INDENT 0.0
.TP
.B threadX.num.queries_wait_limit
number of queries removed due to wait\-limit by thread
.UNINDENT
@@ -982,10 +973,6 @@ Number of requests in the request list that were overwritten by newer
entries.
This happens if there is a flood of queries that recursive processing and
the server has a hard time.
The counter is increased when during the flood the
\fI\%jostle\-timeout\fP
allows a query to be removed in favor of a new incoming query.
The older query is then dropped to make space.
.UNINDENT
.INDENT 0.0
.TP
@@ -993,12 +980,6 @@ The older query is then dropped to make space.
Queries that were dropped because the request list was full.
This happens if a flood of queries need recursive processing, and the
server can not keep up.
The counter is increased when during the flood there is no space
to be made with the jostle out of an older query, and the new query
is dropped.
Since no older queries are removed, see
\fI\%jostle\-timeout\fP setting, there
is no space for the new query.
.UNINDENT
.INDENT 0.0
.TP
@@ -1013,13 +994,6 @@ Current size of the request list, only the requests from client queries.
.UNINDENT
.INDENT 0.0
.TP
.B threadX.requestlist.current.replies
Current count of the number of reply entries waiting on request list
entries. Because a request list entry can send results to multiple reply
addresses, this number may be larger than the size of the request list.
.UNINDENT
.INDENT 0.0
.TP
.B threadX.recursion.time.avg
Average time it took to answer queries that needed recursive processing.
Note that queries that were answered from the cache are not in this average.
@@ -1074,11 +1048,6 @@ summed over threads.
.UNINDENT
.INDENT 0.0
.TP
.B total.num.queries_replyaddr_limit
summed over threads.
.UNINDENT
.INDENT 0.0
.TP
.B total.num.queries_wait_limit
summed over threads.
.UNINDENT
@@ -1169,16 +1138,6 @@ summed over threads.
.UNINDENT
.INDENT 0.0
.TP
.B total.requestlist.current.user
summed over threads.
.UNINDENT
.INDENT 0.0
.TP
.B total.requestlist.current.replies
summed over threads.
.UNINDENT
.INDENT 0.0
.TP
.B total.recursion.time.median
averaged over threads.
.UNINDENT
@@ -1584,6 +1543,6 @@ directory with private keys (\fBunbound_server.key\fP and
.SH AUTHOR
Unbound developers are mentioned in the CREDITS file in the distribution.
.SH COPYRIGHT
1999-2026, NLnet Labs
1999-2025, NLnet Labs
.\" Generated by docutils manpage writer.
.
+1 -36
View File
@@ -150,6 +150,7 @@ There are several commands that the server understands.
:ref:`trusted-keys-file<unbound.conf.trusted-keys-file>`,
:ref:`auto-trust-anchor-file<unbound.conf.auto-trust-anchor-file>`,
:ref:`edns-client-string<unbound.conf.edns-client-string>`,
:ref:`tsig-key<unbound.conf.tsig-key>`,
ipset,
:ref:`log-identity<unbound.conf.log-identity>`,
:ref:`infra-cache-numhosts<unbound.conf.infra-cache-numhosts>`,
@@ -170,8 +171,6 @@ There are several commands that the server understands.
:ref:`tcp-auth-query-timeout<unbound.conf.tcp-auth-query-timeout>`,
:ref:`delay-close<unbound.conf.delay-close>`.
:ref:`iter-scrub-promiscuous<unbound.conf.iter-scrub-promiscuous>`.
:ref:`tls-service-key<unbound.conf.tls-service-key>`.
:ref:`tls-service-pem<unbound.conf.tls-service-pem>`.
It does not work with
:ref:`interface<unbound.conf.interface>` and
@@ -347,8 +346,6 @@ 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@@
@@ -819,10 +816,6 @@ number of statistic counters:
number of queries removed due to discard-timeout by thread
@@UAHL@unbound-control.stats@threadX.num.queries_replyaddr_limit@@
number of queries removed due to replyaddr limits by thread
@@UAHL@unbound-control.stats@threadX.num.queries_wait_limit@@
number of queries removed due to wait-limit by thread
@@ -901,22 +894,12 @@ number of statistic counters:
entries.
This happens if there is a flood of queries that recursive processing and
the server has a hard time.
The counter is increased when during the flood the
:ref:`jostle-timeout<unbound.conf.jostle-timeout>`
allows a query to be removed in favor of a new incoming query.
The older query is then dropped to make space.
@@UAHL@unbound-control.stats@threadX.requestlist.exceeded@@
Queries that were dropped because the request list was full.
This happens if a flood of queries need recursive processing, and the
server can not keep up.
The counter is increased when during the flood there is no space
to be made with the jostle out of an older query, and the new query
is dropped.
Since no older queries are removed, see
:ref:`jostle-timeout<unbound.conf.jostle-timeout>` setting, there
is no space for the new query.
@@UAHL@unbound-control.stats@threadX.requestlist.current.all@@
@@ -928,12 +911,6 @@ number of statistic counters:
Current size of the request list, only the requests from client queries.
@@UAHL@unbound-control.stats@threadX.requestlist.current.replies@@
Current count of the number of reply entries waiting on request list
entries. Because a request list entry can send results to multiple reply
addresses, this number may be larger than the size of the request list.
@@UAHL@unbound-control.stats@threadX.recursion.time.avg@@
Average time it took to answer queries that needed recursive processing.
Note that queries that were answered from the cache are not in this average.
@@ -979,10 +956,6 @@ number of statistic counters:
summed over threads.
@@UAHL@unbound-control.stats@total.num.queries_replyaddr_limit@@
summed over threads.
@@UAHL@unbound-control.stats@total.num.queries_wait_limit@@
summed over threads.
@@ -1055,14 +1028,6 @@ number of statistic counters:
summed over threads.
@@UAHL@unbound-control.stats@total.requestlist.current.user@@
summed over threads.
@@UAHL@unbound-control.stats@total.requestlist.current.replies@@
summed over threads.
@@UAHL@unbound-control.stats@total.recursion.time.median@@
averaged over threads.
+1 -1
View File
@@ -185,6 +185,6 @@ encountered a fatal error.
.SH AUTHOR
Unbound developers are mentioned in the CREDITS file in the distribution.
.SH COPYRIGHT
1999-2026, NLnet Labs
1999-2025, NLnet Labs
.\" Generated by docutils manpage writer.
.
+2 -2
View File
@@ -32,7 +32,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
unbound \- Unbound DNS validating resolver @version@.
.SH SYNOPSIS
.sp
\fBunbound\fP [\fB\-hdpVv\fP] [\fB\-c <cfgfile>\fP]
\fBunbound\fP [\fB\-hdpv\fP] [\fB\-c <cfgfile>\fP]
.SH DESCRIPTION
.sp
\fBunbound\fP is a caching DNS resolver.
@@ -118,6 +118,6 @@ Show the version number and build options, and exit.
.SH AUTHOR
Unbound developers are mentioned in the CREDITS file in the distribution.
.SH COPYRIGHT
1999-2026, NLnet Labs
1999-2025, NLnet Labs
.\" Generated by docutils manpage writer.
.
+32 -225
View File
@@ -102,7 +102,7 @@ server:
interface: 0.0.0.0
interface: ::0
access\-control: 10.0.0.0/8 allow
access\-control: 2001:db8::/64 allow
access\-control: 2001:DB8::/64 allow
.ft P
.fi
.UNINDENT
@@ -382,10 +382,6 @@ Default depends on compile options.
Larger numbers need extra resources from the operating system.
For performance a very large value is best, use libevent to make this
possible.
Should be higher (preferably double) than the value of
\fI\%num\-queries\-per\-thread\fP to
account for cases where the request list is full and avoid file descriptor
starvation.
.sp
Default: 4096 (libevent) / 960 (minievent) / 48 (windows)
.UNINDENT
@@ -691,7 +687,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 responses.
UDP port 53 outgoing queries.
This for very busy servers handles spikes in answer traffic, otherwise:
.INDENT 7.0
.INDENT 3.5
@@ -1139,13 +1135,9 @@ The file must contain the private key for the TLS session, the public
certificate is in the \fI\%tls\-service\-pem\fP
file and it must also be specified if
\fI\%tls\-service\-key\fP is specified.
If the key is stored with root permissions or outside of chroot, then
a change or enabling or disabling requires a restart (a reload is not
enough).
But if the key file (and tls\-service\-pem file) are accessible, then they
are read in on reload, and fast_reload.
The server checks the modification time of the file (and the filename)
to see if the file has changed for reload.
Enabling or disabling this service requires a restart (a reload is not
enough), because the key is read while root permissions are held and before
chroot (if any).
The ports enabled implicitly or explicitly via
\fI\%tls\-port\fP and
\fI\%https\-port\fP do not provide normal DNS TCP
@@ -1298,7 +1290,7 @@ Enable or disable sending the SNI extension on TLS connections.
\fBNOTE:\fP
.INDENT 7.0
.INDENT 3.5
Changing the value requires a restart.
Changing the value requires a reload.
.UNINDENT
.UNINDENT
.sp
@@ -1306,19 +1298,30 @@ Default: yes
.UNINDENT
.INDENT 0.0
.TP
.B tls\-protocols: \fI\(dq<list of protocols>\(dq\fP
Specify the allowed TLS protocol versions to use, in no particular order.
Possible values are \fBTLSv1.2\fP and \fBTLSv1.3\fP\&.
Enclose list of protocols in quotes (\fB\(dq\(dq\fP) and put spaces between them.
.B tls\-use\-system\-policy\-versions: \fI<yes or no>\fP
Enable or disable general\-puspose version\-flexible TLS server configuration
when serving TLS.
This will allow the whole list of available TLS versions provided by the
crypto library, which may have been further restricted by the system\(aqs
crypto policy.
.sp
By default Unbound only uses the latest available TLS version.
.sp
\fBCAUTION:\fP
.INDENT 7.0
.INDENT 3.5
Use only if you want to support legacy TLS client connections.
.UNINDENT
.UNINDENT
.sp
\fBNOTE:\fP
.INDENT 7.0
.INDENT 3.5
Changing the value requires a restart.
Changing the value requires a reload.
.UNINDENT
.UNINDENT
.sp
Default: \(dqTLSv1.2 TLSv1.3\(dq
Default: no
.UNINDENT
.INDENT 0.0
.TP
@@ -1447,9 +1450,6 @@ The port number on which to provide DNS\-over\-QUIC service.
Only interfaces configured with that port number as @number get the QUIC
service.
The interface uses QUIC for the UDP traffic on that port number.
If it is set to 0, the server does not init QUIC code, and QUIC is
disabled.
This is similar to if QUIC is not in use, but then explicitly.
.sp
Default: 853
.UNINDENT
@@ -1927,16 +1927,6 @@ Default: no
.UNINDENT
.INDENT 0.0
.TP
.B log\-thread\-id: \fI<yes or no>\fP
(Only on Linux and only when threads are available)
Logs the system\-wide Linux thread ID instead of Unbound\(aqs internal thread
counter.
Can be useful when debugging with system tools.
.sp
Default: no
.UNINDENT
.INDENT 0.0
.TP
.B pidfile: \fI<filename>\fP
The process id is written to the file.
Default is \fB\(dq@UNBOUND_PIDFILE@\(dq\fP\&.
@@ -2269,11 +2259,6 @@ This protects against so\-called DNS Rebinding, where a user browser is
turned into a network proxy, allowing remote access through the browser to
other parts of your private network.
.sp
The option removes resource records of types A, AAAA, SVCB and HTTPS
that match the filter.
Inside the SVCB and HTTPS records, the svcparams of type ipv4hint
and ipv6hint are checked for matches.
.sp
Some names can be allowed to contain your private addresses, by default all
the \fI\%local\-data\fP that you configured is
allowed to, and you can specify additional names using
@@ -2312,13 +2297,6 @@ 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
@@ -2369,8 +2347,6 @@ 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
@@ -2919,9 +2895,6 @@ 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,
@@ -3024,39 +2997,6 @@ local\-data: \(dqexample.com. A 127.0.0.1\(dq
queries for \fBwww.example.com\fP and \fBwww.foo.example.com\fP are
redirected, so that users with web browsers cannot access sites with
suffix example.com.
.sp
A \fBCNAME\fP record can also be provided via local\-data:
.INDENT 7.0
.INDENT 3.5
.sp
.nf
.ft C
local\-zone: \(dqexample.com.\(dq redirect
local\-data: \(dqexample.com. CNAME www.example.org.\(dq
.ft P
.fi
.UNINDENT
.UNINDENT
.sp
In that case, the \fBCNAME\fP is resolved and the answer
includes resolved target records as well.
The \fBCNAME\fP record has to be with the zone name of the local\-zone,
and there can be one CNAME, not more.
The \fBCNAME\fP record has to be at the zone apex of the
\fBredirect\fP zone, then it is used for redirection.
The resolution proceeds with upstream DNS resolution, and
that does not include the lookup in local zones.
So the record is not able to point in local zones, but it
can point to upstream DNS answers.
.sp
\fBCNAME\fP resolution is supported only in type \fBredirect\fP
local\-zone, and in type \fBinform_redirect\fP local\-zone.
.sp
As different from \fBCNAME\fP records that are used elsewhere, in
the \fBredirect\fP type local\-zone, it is supported that in the target
of the record a wildcard label gets expanded to the query name, with
for example: \fBexample.com. CNAME *.foo.net.\fP gets expanded
to \fBwww.example.com. CNAME www.example.com.foo.net.\fP\&.
.UNINDENT
.INDENT 7.0
.TP
@@ -3112,38 +3052,9 @@ 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.
This type also blocks queries of type DS for the zone name.
That can break the DNSSEC chain of trust, but it is refused anyway.
The block for type DS assists in more completely blocking the zone.
.UNINDENT
.INDENT 7.0
.TP
@@ -3466,7 +3377,7 @@ zone section below.
Configure local data shorthand for a PTR record with the reversed IPv4 or
IPv6 address and the host name.
For example \fB\(dq192.0.2.4 www.example.com\(dq\fP\&.
TTL can be inserted like this: \fB\(dq2001:db8::4 7200 www.example.com\(dq\fP
TTL can be inserted like this: \fB\(dq2001:DB8::4 7200 www.example.com\(dq\fP
.UNINDENT
.INDENT 0.0
.TP
@@ -3605,18 +3516,6 @@ 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
@@ -3819,10 +3718,6 @@ Default: 32
Hard limit on the number of times Unbound is allowed to restart a query
upon encountering a CNAME record.
Results in SERVFAIL when reached.
This applies to chained CNAME records but not sporadic CNAME records that
could be encountered in the lifetime of the query\(aqs resolution effort.
When a CNAME chain concludes, the counter keeping track of this limit is
reset.
Changing this value needs caution as it can allow long CNAME chains to be
accepted, where Unbound needs to verify (resolve) each link individually.
.sp
@@ -3850,16 +3745,6 @@ Default: 11
.UNINDENT
.INDENT 0.0
.TP
.B iter\-scrub\-rrsig: \fI<number>\fP
Limit on the number of RRSIGs allowed for an RRset, from the iterator
scrubber.
This protects against an overly large number of RRSIGs.
Clips off the remainder of the RRSIG list at that point.
.sp
Default: 8
.UNINDENT
.INDENT 0.0
.TP
.B max\-global\-quota: \fI<number>\fP
Limit on the number of upstream queries sent out for an incoming query and
its subqueries from recursion.
@@ -4041,7 +3926,7 @@ Default: no
.UNINDENT
.INDENT 0.0
.TP
.B control\-interface: \fI<IP address or interface name[@port] or path>\fP
.B control\-interface: \fI<IP address or interface name or path>\fP
Give IPv4 or IPv6 addresses or local socket path to listen on for control
commands.
If an interface name is used instead of an IP address, the list of IP
@@ -4250,9 +4135,6 @@ Default: no
If enabled, a query is attempted without this stub section if it fails.
The data could not be retrieved and would have caused SERVFAIL because the
servers are unreachable, instead it is tried without this stub section.
This can lead to using less specific configured forward/stub/auth zones if
any, or end up to otherwise normal recursive resolution for that particular
query.
.sp
Default: no
.UNINDENT
@@ -4373,11 +4255,9 @@ The cert must also match a CA from the
.INDENT 0.0
.TP
.B forward\-first: \fI<yes or no>\fP
If a forwarded query is met with a SERVFAIL error and this option is
enabled Unbound will fall back to less specific resolution.
This can lead to using less specific configured forward/stub/auth zones if
any, or end up to otherwise normal recursive resolution for that particular
query.
If a forwarded query is met with a SERVFAIL error, and this option is
enabled, Unbound will fall back to normal recursive resolution for this
query as if no query forwarding had been specified.
.sp
Default: no
.UNINDENT
@@ -4490,15 +4370,9 @@ does not support AXFR/IXFR for the zone, but if you used
\fI\%url\fP to download the zonefile as a text file
from a webserver that would work.
.sp
\fBCAUTION:\fP
.INDENT 7.0
.INDENT 3.5
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.
.UNINDENT
.UNINDENT
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.
.UNINDENT
.INDENT 0.0
.TP
@@ -4644,32 +4518,6 @@ 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.
@@ -4884,17 +4732,6 @@ Default: no
Use a specific NAT64 prefix to reach IPv4\-only servers.
The prefix length must be one of /32, /40, /48, /56, /64 or /96.
.sp
The NAT64 prefix is allowed by the
\fI\%do\-not\-query\-address\fP option,
so that there is a clear outcome of addresses in both; the NAT64 prefix
is allowed.
The IPv4 address could be filtered by the
\fI\%do\-not\-query\-address\fP option,
if needed.
Allowing the NAT64 prefix is useful when using do\-not\-query\-address
for a cluster of machines that is IPv6\-only and uses NAT64, but does
not have internet access.
.sp
Default: 64:ff9b::/96 (same as \fI\%dns64\-prefix\fP)
.UNINDENT
.SH DNSCRYPT OPTIONS
@@ -5882,10 +5719,6 @@ 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
@@ -6008,32 +5841,6 @@ 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.
@@ -6100,6 +5907,6 @@ Default is to log to \fIsyslog(3)\fP\&.
.SH AUTHOR
Unbound developers are mentioned in the CREDITS file in the distribution.
.SH COPYRIGHT
1999-2026, NLnet Labs
1999-2025, NLnet Labs
.\" Generated by docutils manpage writer.
.
+74 -190
View File
@@ -102,7 +102,7 @@ all the options.
interface: 0.0.0.0
interface: ::0
access-control: 10.0.0.0/8 allow
access-control: 2001:db8::/64 allow
access-control: 2001:DB8::/64 allow
.. _unbound.conf.clauses:
@@ -366,10 +366,6 @@ These options are part of the ``server:`` section.
Larger numbers need extra resources from the operating system.
For performance a very large value is best, use libevent to make this
possible.
Should be higher (preferably double) than the value of
:ref:`num-queries-per-thread<unbound.conf.num-queries-per-thread>` to
account for cases where the request list is full and avoid file descriptor
starvation.
Default: 4096 (libevent) / 960 (minievent) / 48 (windows)
@@ -642,7 +638,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 responses.
UDP port 53 outgoing queries.
This for very busy servers handles spikes in answer traffic, otherwise:
.. code-block:: text
@@ -1048,13 +1044,9 @@ These options are part of the ``server:`` section.
certificate is in the :ref:`tls-service-pem<unbound.conf.tls-service-pem>`
file and it must also be specified if
:ref:`tls-service-key<unbound.conf.tls-service-key>` is specified.
If the key is stored with root permissions or outside of chroot, then
a change or enabling or disabling requires a restart (a reload is not
enough).
But if the key file (and tls-service-pem file) are accessible, then they
are read in on reload, and fast_reload.
The server checks the modification time of the file (and the filename)
to see if the file has changed for reload.
Enabling or disabling this service requires a restart (a reload is not
enough), because the key is read while root permissions are held and before
chroot (if any).
The ports enabled implicitly or explicitly via
:ref:`tls-port<unbound.conf.tls-port>` and
:ref:`https-port<unbound.conf.https-port>` do not provide normal DNS TCP
@@ -1180,19 +1172,25 @@ These options are part of the ``server:`` section.
@@UAHL@unbound.conf@tls-use-sni@@: *<yes or no>*
Enable or disable sending the SNI extension on TLS connections.
.. note:: Changing the value requires a restart.
.. note:: Changing the value requires a reload.
Default: yes
@@UAHL@unbound.conf@tls-protocols@@: *"<list of protocols>"*
Specify the allowed TLS protocol versions to use, in no particular order.
Possible values are ``TLSv1.2`` and ``TLSv1.3``.
Enclose list of protocols in quotes (``""``) and put spaces between them.
@@UAHL@unbound.conf@tls-use-system-policy-versions@@: *<yes or no>*
Enable or disable general-puspose version-flexible TLS server configuration
when serving TLS.
This will allow the whole list of available TLS versions provided by the
crypto library, which may have been further restricted by the system's
crypto policy.
.. note:: Changing the value requires a restart.
By default Unbound only uses the latest available TLS version.
Default: "TLSv1.2 TLSv1.3"
.. caution:: Use only if you want to support legacy TLS client connections.
.. note:: Changing the value requires a reload.
Default: no
@@UAHL@unbound.conf@pad-responses@@: *<yes or no>*
@@ -1308,9 +1306,6 @@ These options are part of the ``server:`` section.
Only interfaces configured with that port number as @number get the QUIC
service.
The interface uses QUIC for the UDP traffic on that port number.
If it is set to 0, the server does not init QUIC code, and QUIC is
disabled.
This is similar to if QUIC is not in use, but then explicitly.
Default: 853
@@ -1719,15 +1714,6 @@ These options are part of the ``server:`` section.
Default: no
@@UAHL@unbound.conf@log-thread-id@@: *<yes or no>*
(Only on Linux and only when threads are available)
Logs the system-wide Linux thread ID instead of Unbound's internal thread
counter.
Can be useful when debugging with system tools.
Default: no
@@UAHL@unbound.conf@pidfile@@: *<filename>*
The process id is written to the file.
Default is :file:`"@UNBOUND_PIDFILE@"`.
@@ -2014,11 +2000,6 @@ These options are part of the ``server:`` section.
turned into a network proxy, allowing remote access through the browser to
other parts of your private network.
The option removes resource records of types A, AAAA, SVCB and HTTPS
that match the filter.
Inside the SVCB and HTTPS records, the svcparams of type ipv4hint
and ipv6hint are checked for matches.
Some names can be allowed to contain your private addresses, by default all
the :ref:`local-data<unbound.conf.local-data>` that you configured is
allowed to, and you can specify additional names using
@@ -2055,13 +2036,6 @@ These options are part of the ``server:`` section.
flushing away any poison.
A value of 10 million is suggested.
It is useful to add 0.0.0.0/8 and '::' to the
:ref:`do-not-query-address<unbound.conf.do-not-query-address>` list.
Otherwise they may be answered, from localhost, and the different source
makes an unwanted reply that unnecessarily ticks up.
The :ref:`do-not-query-localhost<unbound.conf.do-not-query-localhost>`
option includes them, the zero subnets, when it is enabled.
Default: 0 (disabled)
@@ -2107,8 +2081,6 @@ 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
@@ -2592,9 +2564,6 @@ 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>`,
@@ -2681,33 +2650,6 @@ These options are part of the ``server:`` section.
redirected, so that users with web browsers cannot access sites with
suffix example.com.
A ``CNAME`` record can also be provided via local-data:
.. code-block:: text
local-zone: "example.com." redirect
local-data: "example.com. CNAME www.example.org."
In that case, the ``CNAME`` is resolved and the answer
includes resolved target records as well.
The ``CNAME`` record has to be with the zone name of the local-zone,
and there can be one CNAME, not more.
The ``CNAME`` record has to be at the zone apex of the
``redirect`` zone, then it is used for redirection.
The resolution proceeds with upstream DNS resolution, and
that does not include the lookup in local zones.
So the record is not able to point in local zones, but it
can point to upstream DNS answers.
``CNAME`` resolution is supported only in type ``redirect``
local-zone, and in type ``inform_redirect`` local-zone.
As different from ``CNAME`` records that are used elsewhere, in
the ``redirect`` type local-zone, it is supported that in the target
of the record a wildcard label gets expanded to the query name, with
for example: ``example.com. CNAME *.foo.net.`` gets expanded
to ``www.example.com. CNAME www.example.com.foo.net.``.
@@UAHL@unbound.conf.local-zone.type@inform@@
The query is answered normally, same as
:ref:`transparent<unbound.conf.local-zone.type.transparent>`.
@@ -2744,32 +2686,9 @@ 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.
This type also blocks queries of type DS for the zone name.
That can break the DNSSEC chain of trust, but it is refused anyway.
The block for type DS assists in more completely blocking the zone.
@@UAHL@unbound.conf.local-zone.type@always_nxdomain@@
Like :ref:`static<unbound.conf.local-zone.type.static>`, but ignores
@@ -2977,7 +2896,7 @@ These options are part of the ``server:`` section.
Configure local data shorthand for a PTR record with the reversed IPv4 or
IPv6 address and the host name.
For example ``"192.0.2.4 www.example.com"``.
TTL can be inserted like this: ``"2001:db8::4 7200 www.example.com"``
TTL can be inserted like this: ``"2001:DB8::4 7200 www.example.com"``
@@UAHL@unbound.conf@local-zone-tag@@: *<zone> <"list of tags">*
@@ -3110,18 +3029,6 @@ 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
@@ -3304,10 +3211,6 @@ These options are part of the ``server:`` section.
Hard limit on the number of times Unbound is allowed to restart a query
upon encountering a CNAME record.
Results in SERVFAIL when reached.
This applies to chained CNAME records but not sporadic CNAME records that
could be encountered in the lifetime of the query's resolution effort.
When a CNAME chain concludes, the counter keeping track of this limit is
reset.
Changing this value needs caution as it can allow long CNAME chains to be
accepted, where Unbound needs to verify (resolve) each link individually.
@@ -3332,15 +3235,6 @@ These options are part of the ``server:`` section.
Default: 11
@@UAHL@unbound.conf@iter-scrub-rrsig@@: *<number>*
Limit on the number of RRSIGs allowed for an RRset, from the iterator
scrubber.
This protects against an overly large number of RRSIGs.
Clips off the remainder of the RRSIG list at that point.
Default: 8
@@UAHL@unbound.conf@max-global-quota@@: *<number>*
Limit on the number of upstream queries sent out for an incoming query and
its subqueries from recursion.
@@ -3505,7 +3399,7 @@ To setup the correct self-signed certificates use the
Default: no
@@UAHL@unbound.conf.remote@control-interface@@: *<IP address or interface name[@port] or path>*
@@UAHL@unbound.conf.remote@control-interface@@: *<IP address or interface name or path>*
Give IPv4 or IPv6 addresses or local socket path to listen on for control
commands.
If an interface name is used instead of an IP address, the list of IP
@@ -3693,9 +3587,6 @@ The :ref:`local-zone: nodefault<unbound.conf.local-zone.type.nodefault>` (or
If enabled, a query is attempted without this stub section if it fails.
The data could not be retrieved and would have caused SERVFAIL because the
servers are unreachable, instead it is tried without this stub section.
This can lead to using less specific configured forward/stub/auth zones if
any, or end up to otherwise normal recursive resolution for that particular
query.
Default: no
@@ -3808,11 +3699,9 @@ cache).
@@UAHL@unbound.conf.forward@forward-first@@: *<yes or no>*
If a forwarded query is met with a SERVFAIL error and this option is
enabled Unbound will fall back to less specific resolution.
This can lead to using less specific configured forward/stub/auth zones if
any, or end up to otherwise normal recursive resolution for that particular
query.
If a forwarded query is met with a SERVFAIL error, and this option is
enabled, Unbound will fall back to normal recursive resolution for this
query as if no query forwarding had been specified.
Default: no
@@ -3934,6 +3823,12 @@ fallback activates to fetch from the upstream instead of the SERVFAIL.
Alternate syntax for :ref:`primary<unbound.conf.auth.primary>`.
@@UAHL@unbound.conf.auth@primary-tsig@@: *<IP address or host name>* *<tsig key>*
Similar to :ref:`primary<unbound.conf.auth.primary>` and the tsig key
is used for TSIG.
The key name is from a :ref:`tsig-key<unbound.conf.tsig-key>` entry.
@@UAHL@unbound.conf.auth@url@@: *<URL to zone file>*
Where to download a zonefile for the zone.
With HTTP or HTTPS.
@@ -3980,6 +3875,12 @@ fallback activates to fetch from the upstream instead of the SERVFAIL.
default.
@@UAHL@unbound.conf.auth@allow-notify-tsig@@: *<IP address or host name or netblockIP/prefix>* *<tsig key>*
Similar to :ref:`allow-notify<unbound.conf.auth.allow-notify>` and the
tsig key is used for TSIG.
The key name is from a :ref:`tsig-key<unbound.conf.tsig-key>` entry.
@@UAHL@unbound.conf.auth@fallback-enabled@@: *<yes or no>*
If enabled, Unbound falls back to querying the internet as a resolver for
this zone when lookups fail.
@@ -4055,31 +3956,6 @@ 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
@@ -4280,17 +4156,6 @@ servers.
Use a specific NAT64 prefix to reach IPv4-only servers.
The prefix length must be one of /32, /40, /48, /56, /64 or /96.
The NAT64 prefix is allowed by the
:ref:`do-not-query-address<unbound.conf.do-not-query-address>` option,
so that there is a clear outcome of addresses in both; the NAT64 prefix
is allowed.
The IPv4 address could be filtered by the
:ref:`do-not-query-address<unbound.conf.do-not-query-address>` option,
if needed.
Allowing the NAT64 prefix is useful when using do-not-query-address
for a cluster of machines that is IPv6-only and uses NAT64, but does
not have internet access.
Default: 64:ff9b::/96 (same as :ref:`dns64-prefix<unbound.conf.dns64.dns64-prefix>`)
.. _unbound.conf.dnscrypt:
@@ -5160,15 +5025,17 @@ 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>`.
@@UAHL@unbound.conf.rpz@primary-tsig@@: *<IP address or host name>* *<tsig key>*
Similar to :ref:`primary<unbound.conf.rpz.primary>` and the tsig key
is used for TSIG.
The key name is from a :ref:`tsig-key<unbound.conf.tsig-key>` entry.
@@UAHL@unbound.conf.rpz@url@@: *<url to zonefile>*
Where to download a zonefile for the zone.
With HTTP or HTTPS.
@@ -5206,6 +5073,12 @@ answer queries with that content.
default.
@@UAHL@unbound.conf.rpz@allow-notify-tsig@@: *<IP address or host name or netblockIP/prefix>* *<tsig key>*
Similar to :ref:`allow-notify<unbound.conf.rpz.allow-notify>` and the
tsig key is used for TSIG.
The key name is from a :ref:`tsig-key<unbound.conf.tsig-key>` entry.
@@UAHL@unbound.conf.rpz@zonefile@@: *<filename>*
The filename where the zone is stored.
If not given then no zonefile is used.
@@ -5264,31 +5137,42 @@ answer queries with that content.
If no tags are specified the policies from this section will be applied for
all clients.
.. _unbound.conf.tsig-key:
@@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.
TSIG Key Options
^^^^^^^^^^^^^^^^^
Only consider for untrusted/misbehaving primaries that could hog resources
and bring down the resolver.
The **tsig-key:** clauses specify the TSIG keys that are used.
There can be multiple **tsig-key:** clauses, with each specifying a
different key.
Each key has a name, algorithm and secret key material.
Default: 0
TSIG keys are shared secrets.
Both sides of the connection share the secret information.
Also they must both use the same name for the key, and same algorithm.
With ``include: "key.conf"`` it is possible to put the declaration of the key
or some lines of it in an external file from the main configuration file.
It can also be used without such an include, with it the config statements
and key material can be put in separate files.
@@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.
@@UAHL@unbound.conf.tsig-key@name@@: *"<key name>"*
Name of the TSIG key.
The key name is transferred in DNS wireformat in the TSIG record, and
is used to reference the TSIG key from where it is configured to be used.
Only consider for untrusted/misbehaving primaries that could hog resources
and bring down the resolver.
Default: 0
@@UAHL@unbound.conf.tsig-key@algorithm@@: *<algorithm name>*
Name of the algorithm to use with this TSIG key.
This can be md5, sha1, sha224, sha256, sha384 or sha512.
@@UAHL@unbound.conf.tsig-key@secret@@: *"<base64 blob>"*
The secret contents is a base64 string.
A way to get random base64 bytes is e.g.
from ``dd if=/dev/random of=/dev/stdout count=1 bs=32 | base64``
Memory Control Example
----------------------
+1 -1
View File
@@ -42,7 +42,7 @@ unbound(8)
Synopsis
--------
**unbound** [``-hdpVv``] [``-c <cfgfile>``]
**unbound** [``-hdpv``] [``-c <cfgfile>``]
Description
-----------
-1
View File
@@ -459,7 +459,6 @@ 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);
+5 -102
View File
@@ -70,7 +70,6 @@ subnet_data_delete(void *d, void *ATTR_UNUSED(arg))
r = (struct subnet_msg_cache_data*)d;
addrtree_delete(r->tree4);
addrtree_delete(r->tree6);
free(r->reason_fail);
free(r);
}
@@ -85,8 +84,6 @@ msg_cache_sizefunc(void *k, void *d)
+ q->key.qname_len + lock_get_mem(&q->entry.lock);
s += addrtree_size(r->tree4);
s += addrtree_size(r->tree6);
if(r->reason_fail)
s += strlen(r->reason_fail)+1;
return s;
}
@@ -165,15 +162,8 @@ int ecs_whitelist_check(struct query_info* qinfo,
if(!ecs_is_whitelisted(sn_env->whitelist,
addr, addrlen, qinfo->qname, qinfo->qname_len,
qinfo->qclass)) {
/* The stub or forward can have no_cache set.*/
if(iter_stub_fwd_no_cache(qstate, &qstate->qinfo, NULL, NULL, NULL, 0)) {
verbose(VERB_ALGO, "subnet subquery is not stored globally, stuborfwd is no_cache");
} else {
verbose(VERB_ALGO, "subnet store subquery global, name and addr have no subnet treatment.%s",
(sq->started_no_cache_store?
" But the subnet module was started with no_cache_store for the super query, and that is still applied to this query":""));
qstate->no_cache_store = sq->started_no_cache_store;
}
verbose(VERB_ALGO, "subnet store subquery global, name and addr have no subnet treatment.");
qstate->no_cache_store = 0;
}
}
return 1;
@@ -203,18 +193,12 @@ int ecs_whitelist_check(struct query_info* qinfo,
if(sq->ecs_server_out.subnet_source_mask == 0) {
sq->subnet_sent_no_subnet = 1;
sq->subnet_sent = 0;
/* The result should end up in subnet cache,
* not in global cache. */
qstate->no_cache_store = 1;
return 1;
}
subnet_ecs_opt_list_append(&sq->ecs_server_out,
&qstate->edns_opts_back_out, qstate, region);
}
sq->subnet_sent = 1;
/* Do not store servfails in global cache, since the subnet
* option is sent out. */
qstate->no_cache_store = 1;
}
else {
/* Outgoing ECS option is set, but we don't want to sent it to
@@ -436,35 +420,6 @@ update_cache(struct module_qstate *qstate, int id)
}
/* lru_entry->lock is locked regardless of how we got here,
* either from the slabhash_lookup, or above in the new allocated */
if(!qstate->return_msg && qstate->error_response_cache) {
struct subnet_msg_cache_data *data =
(struct subnet_msg_cache_data*)lru_entry->data;
data->ttl_servfail = *qstate->env->now + NORR_TTL;
data->ede_fail = errinf_to_reason_bogus(qstate);
diff_size = (data->reason_fail?strlen(data->reason_fail)+1:0);
if(qstate->errinf) {
char* str = errinf_to_str_misc(qstate);
free(data->reason_fail);
data->reason_fail = NULL;
if(str)
data->reason_fail = strdup(str);
}
diff_size = (data->reason_fail?strlen(data->reason_fail)+1:0)
- diff_size;
lock_rw_unlock(&lru_entry->lock);
if (need_to_insert) {
slabhash_insert(subnet_msg_cache, h, lru_entry,
lru_entry->data, NULL);
} else {
slabhash_update_space_used(subnet_msg_cache, h, NULL,
diff_size);
}
return;
}
if(!qstate->return_msg) {
lock_rw_unlock(&lru_entry->lock);
return;
}
/* Step 2, find the correct tree */
if (!(tree = get_tree(lru_entry->data, edns, sne, qstate->env->cfg))) {
lock_rw_unlock(&lru_entry->lock);
@@ -508,21 +463,6 @@ update_cache(struct module_qstate *qstate, int id)
}
}
/** See if there is a stored servfail, returns true if so, and sets reply. */
static int
lookup_check_servfail(struct module_qstate *qstate,
struct subnet_msg_cache_data *data)
{
struct module_env *env = qstate->env;
if(!data)
return 0;
if(!data->ttl_servfail || TTL_IS_EXPIRED(data->ttl_servfail, *env->now))
return 0;
qstate->return_rcode = LDNS_RCODE_SERVFAIL;
errinf_ede(qstate, data->reason_fail, data->ede_fail);
return 1;
}
/** Lookup in cache and reply true iff reply is sent. */
static int
lookup_and_reply(struct module_qstate *qstate, int id, struct subnet_qstate *sq, int prefetch)
@@ -536,8 +476,6 @@ lookup_and_reply(struct module_qstate *qstate, int id, struct subnet_qstate *sq,
struct addrtree *tree;
struct addrnode *node;
uint8_t scope;
int must_validate = (!(qstate->query_flags&BIT_CD)
|| qstate->env->cfg->ignore_cd) && qstate->env->need_to_validate;
memset(&sq->ecs_client_out, 0, sizeof(sq->ecs_client_out));
@@ -551,20 +489,12 @@ lookup_and_reply(struct module_qstate *qstate, int id, struct subnet_qstate *sq,
tree = (ecs->subnet_addr_fam == EDNSSUBNET_ADDRFAM_IP4)?
data->tree4 : data->tree6;
if (!tree) { /* qinfo in cache but not for this family */
if(lookup_check_servfail(qstate, data)) {
lock_rw_unlock(&e->lock);
return 1;
}
lock_rw_unlock(&e->lock);
return 0;
}
node = addrtree_find(tree, (addrkey_t*)ecs->subnet_addr,
ecs->subnet_source_mask, *env->now);
if (!node) { /* plain old cache miss */
if(lookup_check_servfail(qstate, data)) {
lock_rw_unlock(&e->lock);
return 1;
}
lock_rw_unlock(&e->lock);
return 0;
}
@@ -573,24 +503,12 @@ lookup_and_reply(struct module_qstate *qstate, int id, struct subnet_qstate *sq,
(struct reply_info *)node->elem, qstate->region, *env->now, 0,
env->scratch);
scope = (uint8_t)node->scope;
lock_rw_unlock(&e->lock);
if (!qstate->return_msg) { /* Failed allocation or expired TTL */
if(lookup_check_servfail(qstate, data)) {
lock_rw_unlock(&e->lock);
return 1;
}
lock_rw_unlock(&e->lock);
return 0;
}
lock_rw_unlock(&e->lock);
if(qstate->return_msg->rep->security == sec_status_unchecked
&& must_validate) {
/* The message has to be validated first. */
verbose(VERB_ALGO, "subnet: unchecked cache entry needs "
"validation");
return 0;
}
if (sq->subnet_downstream) { /* relay to interested client */
sq->ecs_client_out.subnet_scope_mask = scope;
sq->ecs_client_out.subnet_addr_fam = ecs->subnet_addr_fam;
@@ -645,10 +563,7 @@ generate_sub_request(struct module_qstate *qstate, int id, struct subnet_qstate*
qflags |= BIT_RD;
if((qstate->query_flags & BIT_CD)!=0) {
qflags |= BIT_CD;
/* The valrec is left off. Leave out: valrec = 1;
* So that the cache is protected with DNSSEC validation.
* Just like the global cache. DNSSEC validation is performed
* regardless of the setting of the querier's CD flag. */
valrec = 1;
}
fptr_ok(fptr_whitelist_modenv_attach_sub(qstate->env->attach_sub));
@@ -665,7 +580,6 @@ generate_sub_request(struct module_qstate *qstate, int id, struct subnet_qstate*
}
subsq = (struct subnet_qstate*)subq->minfo[id];
subsq->is_subquery_nonsubnet = 1;
subsq->started_no_cache_store = sq->started_no_cache_store;
/* When the client asks 0.0.0.0/0 and the name is not treated
* as subnet, it is to be stored in the global cache.
@@ -718,12 +632,6 @@ eval_response(struct module_qstate *qstate, int id, struct subnet_qstate *sq)
/* already an answer and its not a message, but retain
* the actual rcode, instead of module_error, so send
* module_finished */
if(qstate->error_response_cache) {
verbose(VERB_ALGO, "subnet: store error response");
lock_rw_wrlock(&sne->biglock);
update_cache(qstate, id);
lock_rw_unlock(&sne->biglock);
}
return module_finished;
}
@@ -973,11 +881,9 @@ ecs_edns_back_parsed(struct module_qstate* qstate, int id,
sq->max_scope = sq->ecs_server_in.subnet_scope_mask;
} else if(sq->subnet_sent_no_subnet) {
/* The answer can be stored as scope 0, not in global cache. */
/* This was already set in ecs_whitelist_check */
qstate->no_cache_store = 1;
} else if(sq->subnet_sent) {
/* Need another query to be able to store in global cache. */
/* This was already set in ecs_whitelist_check */
qstate->no_cache_store = 1;
}
@@ -1015,7 +921,6 @@ 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;
@@ -1095,7 +1000,6 @@ 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;
@@ -1167,7 +1071,6 @@ 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;
if(verbosity >= VERB_ALGO) {
subnet_log_print("reply has edns subnet",
edns_opt_list_find(
-10
View File
@@ -69,18 +69,8 @@ struct subnet_env {
};
struct subnet_msg_cache_data {
/** Tree for nodes with IPv4 subnets. */
struct addrtree* tree4;
/** Tree for nodes with IPv6 subnets. */
struct addrtree* tree6;
/** If servfail is stored, for how long. Abs time in seconds.
* This protects against too much recusion on the item when
* resolution fails, for a couple of seconds. */
time_t ttl_servfail;
/** servfail ede */
sldns_ede_code ede_fail;
/** servfail reason */
char* reason_fail;
};
struct subnet_qstate {
-2
View File
@@ -100,8 +100,6 @@ 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);
+35 -85
View File
@@ -51,9 +51,6 @@
#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
@@ -63,11 +60,6 @@ ipsecmod_apply_cfg(struct ipsecmod_env* ipsecmod_env, struct config_file* cfg)
log_err("ipsecmod: missing ipsecmod-hook.");
return 0;
}
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;
}
if(cfg->ipsecmod_whitelist &&
!ipsecmod_whitelist_apply_cfg(ipsecmod_env, cfg))
return 0;
@@ -258,16 +250,27 @@ 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 qname_s[LDNS_MAX_DOMAINLEN*5+16], ttl_s[32], a_s[32768], k_s[32768];
char *s, *tempstring;
char str[65535], *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);
@@ -280,24 +283,17 @@ call_hook(struct module_qstate* qstate, struct ipsecmod_qstate* iq,
free(tempstring);
return 0;
}
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);
w += sldns_str_print(&s, &slen, "\"%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;
snprintf(ttl_s, sizeof(ttl_s), "%ld", (long)rrset_data->ttl);
w += sldns_str_print(&s, &slen, "\"%ld\"", (long)rrset_data->ttl);
/* Put space into the buffer. */
w += sldns_str_print(&s, &slen, " ");
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
@@ -308,15 +304,9 @@ call_hook(struct module_qstate* qstate, struct ipsecmod_qstate* iq,
return 0;
}
rrset_data = (struct packed_rrset_data*)rrset_key->entry.data;
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);
/* Copy the A/AAAA record(s) into the buffer. Start and end this section
* with a double quote. */
w += sldns_str_print(&s, &slen, "\"");
for(i=0; i<rrset_data->count; i++) {
if(i > 0) {
/* Put space into the buffer. */
@@ -332,7 +322,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: command addr argument too long");
log_err("ipsecmod: shell command too long");
return 0;
} else {
s += w_temp;
@@ -340,17 +330,12 @@ call_hook(struct module_qstate* qstate, struct ipsecmod_qstate* iq,
w += w_temp;
}
}
if(w >= (int)sizeof(a_s)) {
log_err("ipsecmod: command addr argument too long");
return 0;
}
w += sldns_str_print(&s, &slen, "\"");
/* Put space into the buffer. */
w += sldns_str_print(&s, &slen, " ");
/* Copy the IPSECKEY record(s) into the buffer. Start and end this section
* with a double quote. */
w = 0;
s = k_s;
slen = sizeof(k_s);
memset(s, 0, slen);
w += sldns_str_print(&s, &slen, "\"");
rrset_data = (struct packed_rrset_data*)iq->ipseckey_rrset->entry.data;
for(i=0; i<rrset_data->count; i++) {
if(i > 0) {
@@ -377,44 +362,15 @@ call_hook(struct module_qstate* qstate, struct ipsecmod_qstate* iq,
w += w_temp;
}
}
if(w >= (int)sizeof(k_s)) {
log_err("ipsecmod: command ipseckey argument too long");
w += sldns_str_print(&s, &slen, "\"");
if(w >= (int)sizeof(str)) {
log_err("ipsecmod: shell command too long");
return 0;
}
verbose(VERB_ALGO, "ipsecmod: shell command: '%s'", str);
/* ipsecmod-hook should return 0 on success. */
/* 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));
if(system(str) != 0)
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;
}
@@ -479,12 +435,6 @@ 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. */
+14 -17
View File
@@ -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];
char buffer[BUFF_LEN];
static char buffer[BUFF_LEN];
if (strlen(setname) >= IPSET_MAXNAMELEN) {
errno = ENAMETOOLONG;
@@ -208,6 +208,13 @@ 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;
}
}
@@ -219,15 +226,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)
{
char dname[LDNS_MAX_DOMAINLEN*4+16];
static char dname[BUFF_LEN];
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, sizeof(dname));
if (dlen == 0 || dlen >= (int)sizeof(dname)) {
dlen = sldns_wire2str_dname_buf(rrset->rk.dname, rrset->rk.dname_len, dname, BUFF_LEN);
if (dlen == 0) {
log_err("bad domain name");
return -1;
}
@@ -269,7 +276,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;
char qname[LDNS_MAX_DOMAINLEN*4+16];
static char qname[BUFF_LEN];
int qlen;
#ifdef HAVE_NET_PFVAR_H
@@ -285,8 +292,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, sizeof(qname));
if(qlen == 0 || qlen >= (int)sizeof(qname)) {
qname, BUFF_LEN);
if(qlen == 0) {
log_err("bad domain name");
return -1;
}
@@ -365,16 +372,6 @@ 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;
+24 -31
View File
@@ -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,9 +137,7 @@ delegpt_add_ns(struct delegpt* dp, struct regional* region, uint8_t* name,
} else {
ns->tls_auth_name = NULL;
}
ns->next = dp->nslist;
dp->nslist = ns;
return 1;
return ns->name != 0;
}
struct delegpt_ns*
@@ -225,7 +223,11 @@ 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;
@@ -239,10 +241,6 @@ 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;
}
@@ -400,33 +398,30 @@ 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, uint16_t qclass)
find_NS(struct reply_info* rep, size_t from, size_t to)
{
size_t i;
for(i=from; i<to; i++) {
if(ntohs(rep->rrsets[i]->rk.type) == LDNS_RR_TYPE_NS &&
ntohs(rep->rrsets[i]->rk.rrset_class) == qclass)
if(ntohs(rep->rrsets[i]->rk.type) == LDNS_RR_TYPE_NS)
return rep->rrsets[i];
}
return NULL;
}
struct delegpt*
delegpt_from_message(struct dns_msg* msg, struct regional* region, int port)
delegpt_from_message(struct dns_msg* msg, struct regional* region)
{
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->qinfo.qclass);
msg->rep->an_numrrsets+msg->rep->ns_numrrsets);
/* 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,
msg->qinfo.qclass);
ns_rrset = find_NS(msg->rep, 0, msg->rep->an_numrrsets);
/* If there was no NS rrset in the authority section, then this
* wasn't a referral message. (It might not actually be a
@@ -441,7 +436,7 @@ delegpt_from_message(struct dns_msg* msg, struct regional* region, int port)
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, port))
if(!delegpt_rrset_add_ns(dp, region, ns_rrset, 0))
return NULL;
/* add glue, A and AAAA in answer and additional section */
@@ -452,12 +447,10 @@ delegpt_from_message(struct dns_msg* msg, struct regional* region, int port)
i < (msg->rep->an_numrrsets+msg->rep->ns_numrrsets))
continue;
if(ntohs(s->rk.type) == LDNS_RR_TYPE_A &&
ntohs(s->rk.rrset_class) == msg->qinfo.qclass) {
if(ntohs(s->rk.type) == LDNS_RR_TYPE_A) {
if(!delegpt_add_rrset_A(dp, region, s, 0, NULL))
return NULL;
} else if(ntohs(s->rk.type) == LDNS_RR_TYPE_AAAA &&
ntohs(s->rk.rrset_class) == msg->qinfo.qclass) {
} else if(ntohs(s->rk.type) == LDNS_RR_TYPE_AAAA) {
if(!delegpt_add_rrset_AAAA(dp, region, s, 0, NULL))
return NULL;
}
@@ -467,7 +460,7 @@ delegpt_from_message(struct dns_msg* msg, struct regional* region, int port)
int
delegpt_rrset_add_ns(struct delegpt* dp, struct regional* region,
struct ub_packed_rrset_key* ns_rrset, uint8_t lame, int port)
struct ub_packed_rrset_key* ns_rrset, uint8_t lame)
{
struct packed_rrset_data* nsdata = (struct packed_rrset_data*)
ns_rrset->entry.data;
@@ -482,7 +475,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, (port==-1?UNBOUND_DNS_PORT:port)))
NULL, UNBOUND_DNS_PORT))
return 0;
}
return 1;
@@ -541,7 +534,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, -1);
return delegpt_rrset_add_ns(dp, region, rrset, lame);
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)
@@ -666,6 +659,8 @@ 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;
@@ -684,8 +679,6 @@ 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;
}
@@ -711,7 +704,11 @@ 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;
@@ -727,10 +724,6 @@ 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;
}
+2 -4
View File
@@ -221,11 +221,10 @@ 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, int port);
struct ub_packed_rrset_key* ns_rrset, uint8_t lame);
/**
* Add target address to the delegation point.
@@ -366,12 +365,11 @@ 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, int port);
struct regional* regional);
/**
* Mark negative return in delegation point for specific nameserver.
-12
View File
@@ -132,18 +132,6 @@ donotq_apply_cfg(struct iter_donotq* dq, struct config_file* cfg)
if(cfg->do_ip6) {
if(!donotq_str_cfg(dq, "::1"))
return 0;
if(!donotq_str_cfg(dq, "::ffff:127.0.0.0/104"))
return 0;
}
/* RFC 1122 3.2.1.3 / RFC 6890 / RFC 4291 2.5.2: not valid as
* destination; on Linux these route to the local host. */
if(!donotq_str_cfg(dq, "0.0.0.0/8"))
return 0;
if(cfg->do_ip6) {
if(!donotq_str_cfg(dq, "::"))
return 0;
if(!donotq_str_cfg(dq, "::ffff:0:0/96"))
return 0;
}
}
addr_tree_init_parents(&dq->tree);
+1 -167
View File
@@ -207,168 +207,6 @@ size_t priv_get_mem(struct iter_priv* priv)
return sizeof(*priv) + regional_get_mem(priv->region);
}
/**
* Check if svcparam ipv4hint contains a private address.
* @param priv: private address lookup struct.
* @param d: the data bytes.
* @param data_len: number of data bytes in the svcparam.
* @param addr: address to return the private address to log in to.
* It has space for IPv4 and IPv6 addresses.
* @param addrlen: length of the addr. Returns the correct size for the addr.
* @return true if the rdata contains a private address.
*/
static int svcb_ipv4hint_contains_priv_addr(struct iter_priv* priv,
uint8_t* d, uint16_t data_len, struct sockaddr_storage* addr,
socklen_t* addrlen)
{
struct sockaddr_in sa;
*addrlen = (socklen_t)sizeof(struct sockaddr_in);
memset(&sa, 0, sizeof(struct sockaddr_in));
sa.sin_family = AF_INET;
sa.sin_port = (in_port_t)htons(UNBOUND_DNS_PORT);
while(data_len >= LDNS_IP4ADDRLEN) {
memmove(&sa.sin_addr, d, LDNS_IP4ADDRLEN);
memmove(addr, &sa, *addrlen);
if(priv_lookup_addr(priv, addr, *addrlen))
return 1;
d += LDNS_IP4ADDRLEN;
data_len -= LDNS_IP4ADDRLEN;
}
/* if data_len != 0 here, then the svcparam is malformed. */
return 0;
}
/**
* Check if svcparam ipv6hint contains a private address.
* @param priv: private address lookup struct.
* @param d: the data bytes.
* @param data_len: number of data bytes in the svcparam.
* @param addr: address to return the private address to log in to.
* It has space for IPv4 and IPv6 addresses.
* @param addrlen: length of the addr. Returns the correct size for the addr.
* @return true if the rdata contains a private address.
*/
static int svcb_ipv6hint_contains_priv_addr(struct iter_priv* priv,
uint8_t* d, uint16_t data_len, struct sockaddr_storage* addr,
socklen_t* addrlen)
{
struct sockaddr_in6 sa;
*addrlen = (socklen_t)sizeof(struct sockaddr_in6);
memset(&sa, 0, sizeof(struct sockaddr_in6));
sa.sin6_family = AF_INET6;
sa.sin6_port = (in_port_t)htons(UNBOUND_DNS_PORT);
while(data_len >= LDNS_IP6ADDRLEN) {
memmove(&sa.sin6_addr, d, LDNS_IP6ADDRLEN);
memmove(addr, &sa, *addrlen);
if(priv_lookup_addr(priv, addr, *addrlen))
return 1;
d += LDNS_IP6ADDRLEN;
data_len -= LDNS_IP6ADDRLEN;
}
/* if data_len != 0 here, then the svcparam is malformed. */
return 0;
}
/**
* Check if type SVCB and HTTPS rdata contains a private address.
* @param priv: private address lookup struct.
* @param pkt: the packet.
* @param rr: the rr with rdata to check.
* @param addr: address to return the private address to log in to.
* @param addrlen: length of the addr. Initially the total size, on
* return the correct size for the addr.
* @return true if the rdata contains a private address.
*/
static int svcb_rr_contains_priv_addr(struct iter_priv* priv,
sldns_buffer* pkt, struct rr_parse* rr, struct sockaddr_storage* addr,
socklen_t* addrlen)
{
uint8_t* d = rr->ttl_data;
uint16_t svcparamkey, data_len, rdatalen;
size_t oldpos, dname_len, dname_start, dname_compr_len;
d += 4; /* skip TTL */
rdatalen = sldns_read_uint16(d); /* read rdata length */
d += 2;
if(rdatalen < 2 /* priority */ + 1 /* 1 length target */)
return 0; /* malformed, too short */
d += 2; /* skip priority */
rdatalen -= 2;
oldpos = sldns_buffer_position(pkt);
sldns_buffer_set_position(pkt, (size_t)(d - sldns_buffer_begin(pkt)));
dname_start = sldns_buffer_position(pkt);
dname_len = pkt_dname_len(pkt);
dname_compr_len = sldns_buffer_position(pkt) - dname_start;
sldns_buffer_set_position(pkt, oldpos);
if(dname_len == 0)
return 0; /* dname malformed */
if(dname_compr_len > rdatalen)
return 0; /* malformed */
d += dname_compr_len; /* skip target */
rdatalen -= dname_compr_len;
while(rdatalen >= 4) {
svcparamkey = sldns_read_uint16(d);
data_len = sldns_read_uint16(d+2);
d += 4;
rdatalen -= 4;
/* verify that we have data_len data */
if(data_len > rdatalen) {
/* It is malformed, but if there are addresses
* in there it can be rejected. */
data_len = rdatalen;
}
if(!data_len)
continue; /* no data for the svcparamkey */
if(svcparamkey == SVCB_KEY_IPV4HINT) {
if(svcb_ipv4hint_contains_priv_addr(priv, d, data_len,
addr, addrlen))
return 1;
} else if(svcparamkey == SVCB_KEY_IPV6HINT) {
if(svcb_ipv6hint_contains_priv_addr(priv, d, data_len,
addr, addrlen))
return 1;
}
d += data_len;
rdatalen -= data_len;
}
/* If rdatalen != 0 here, then the svcb rdata is malformed. */
return 0;
}
/**
* Check if the SVCB and HTTPS rrset is bad.
* @param priv: private address lookup struct.
* @param pkt: the packet.
* @param rrset: the rrset to check.
* @return 1 if the entire rrset has to be removed. 0 if not.
* It removes RRs if they have private addresses, and log that.
*/
static int priv_svcb_rrset_bad(struct iter_priv* priv, sldns_buffer* pkt,
struct rrset_parse* rrset)
{
struct rr_parse* rr, *prev = NULL;
struct sockaddr_storage addr;
socklen_t addrlen = (socklen_t)sizeof(addr);
for(rr = rrset->rr_first; rr; rr = rr->next) {
if(svcb_rr_contains_priv_addr(priv, pkt, rr, &addr,
&addrlen)) {
if(msgparse_rrset_remove_rr("sanitize: removing public name with private address", pkt, rrset, prev, rr, &addr, addrlen))
return 1;
continue;
}
prev = rr;
}
return 0;
}
int priv_rrset_bad(struct iter_priv* priv, sldns_buffer* pkt,
struct rrset_parse* rrset)
{
@@ -430,11 +268,7 @@ int priv_rrset_bad(struct iter_priv* priv, sldns_buffer* pkt,
}
prev = rr;
}
} else if(rrset->type == LDNS_RR_TYPE_SVCB ||
rrset->type == LDNS_RR_TYPE_HTTPS) {
if(priv_svcb_rrset_bad(priv, pkt, rrset))
return 1;
}
}
}
return 0;
}
+7 -18
View File
@@ -107,7 +107,7 @@ 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 msg_lame_empty, int msg_lame_referral)
int* empty_nodata_found)
{
uint8_t* origzone = (uint8_t*)"\000"; /* the default */
struct ub_packed_rrset_key* s;
@@ -122,10 +122,6 @@ 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)
@@ -147,10 +143,6 @@ 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) {
@@ -257,16 +249,13 @@ 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),
* 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 &&
* 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 &&
!(msg->rep->flags&BIT_AA) && !rdset)
return RESPONSE_TYPE_LAME;
return RESPONSE_TYPE_THROWAWAY;
return RESPONSE_TYPE_ANSWER;
}
/* If we are getting a referral upwards (or to
+1 -5
View File
@@ -120,14 +120,10 @@ enum response_type response_type_from_cache(struct dns_msg* msg,
* @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.
* @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 msg_lame_empty, int msg_lame_referral);
int* empty_nodata_found);
#endif /* ITERATOR_ITER_RESPTYPE_H */
+15 -178
View File
@@ -285,17 +285,6 @@ synth_cname_rrset(uint8_t** sname, size_t* snamelen, uint8_t* alias,
return NULL;
memmove(cn->rr_first->ttl_data, rrset->rr_first->ttl_data,
sizeof(uint32_t)); /* RFC6672: synth CNAME TTL == DNAME TTL */
/* Apply cache TTL policy so DNAME and synthesized CNAME stay equal
* and respect cache-min-ttl/cache-max-ttl (same as rdata_copy path). */
if(!SERVE_ORIGINAL_TTL) {
uint32_t ttl = sldns_read_uint32(cn->rr_first->ttl_data);
time_t ttl_t = (time_t)ttl;
if(ttl_t < MIN_TTL) ttl_t = MIN_TTL;
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);
}
sldns_write_uint16(cn->rr_first->ttl_data+4, aliaslen);
memmove(cn->rr_first->ttl_data+6, alias, aliaslen);
cn->rr_first->size = sizeof(uint16_t)+aliaslen;
@@ -316,20 +305,6 @@ 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)
@@ -408,8 +383,6 @@ 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;
@@ -435,43 +408,6 @@ shorten_rrset(sldns_buffer* pkt, struct rrset_parse* rrset, int count)
else rrset->rr_first = NULL;
}
/** Shorten RRSIGs list */
static void
shorten_rrsig(sldns_buffer* pkt, struct rrset_parse* rrset, int count)
{
/* The too large list of RRSIGs on the RRset is shortened.
* This is so that too large content does not overwhelm the cache.
* The validator does not validate more than a max number of
* RRSIGs as well. */
int i;
struct rr_parse* rr = rrset->rrsig_first, *prev = NULL;
if(!rr)
return;
for(i=0; i<count; i++) {
prev = rr;
rr = rr->next;
if(!rr)
return; /* The RRSIG list is already short. */
}
if(verbosity >= VERB_QUERY
&& rrset->dname_len <= LDNS_MAX_DOMAINLEN) {
uint8_t buf[LDNS_MAX_DOMAINLEN+1];
dname_pkt_copy(pkt, buf, rrset->dname);
log_nametypeclass(VERB_QUERY, "normalize: shorten RRSIGs:",
buf, rrset->type, ntohs(rrset->rrset_class));
}
/* remove further rrsigs */
rrset->rrsig_last = prev;
rrset->rrsig_count = count;
while(rr) {
rrset->size -= rr->size;
rr = rr->next;
}
if(rrset->rrsig_last)
rrset->rrsig_last->next = NULL;
else rrset->rrsig_first = NULL;
}
/**
* This routine normalizes a response. This includes removing "irrelevant"
* records from the answer and additional sections and (re)synthesizing
@@ -482,23 +418,20 @@ shorten_rrsig(sldns_buffer* pkt, struct rrset_parse* rrset, int count)
* @param qinfo: original query.
* @param region: where to allocate synthesized CNAMEs.
* @param env: module env with config options.
* @param zonename: name of server zone.
* @return 0 on error.
*/
static int
scrub_normalize(sldns_buffer* pkt, struct msg_parse* msg,
struct query_info* qinfo, struct regional* region,
struct module_env* env, uint8_t* zonename)
struct module_env* env)
{
uint8_t* sname = qinfo->qname;
size_t snamelen = qinfo->qname_len;
struct rrset_parse* rrset, *prev, *nsset=NULL;
int cname_length = 0; /* number of CNAMEs, or DNAMEs */
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 &&
FLAGS_GET_RCODE(msg->flags) != LDNS_RCODE_YXDOMAIN)
FLAGS_GET_RCODE(msg->flags) != LDNS_RCODE_NXDOMAIN)
return 1;
/* For the ANSWER section, remove all "irrelevant" records and add
@@ -510,8 +443,6 @@ scrub_normalize(sldns_buffer* pkt, struct msg_parse* msg,
prev = NULL;
rrset = msg->rrset_first;
while(rrset && rrset->section == LDNS_SECTION_ANSWER) {
if((int)rrset->rrsig_count > env->cfg->iter_scrub_rrsig)
shorten_rrsig(pkt, rrset, env->cfg->iter_scrub_rrsig);
if(cname_length > env->cfg->iter_scrub_cname) {
/* Too many CNAMEs, or DNAMEs, from the authority
* server, scrub down the length to something
@@ -522,9 +453,8 @@ scrub_normalize(sldns_buffer* pkt, struct msg_parse* msg,
pkt, msg, prev, &rrset);
continue;
}
if(rrset->type == LDNS_RR_TYPE_DNAME &&
pkt_strict_sub(pkt, sname, rrset->dname) &&
pkt_sub(pkt, rrset->dname, zonename)) {
if(rrset->type == LDNS_RR_TYPE_DNAME &&
pkt_strict_sub(pkt, sname, rrset->dname)) {
/* check if next rrset is correct CNAME. else,
* synthesize a CNAME */
struct rrset_parse* nx = rrset->rrset_all_next;
@@ -536,20 +466,10 @@ 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 "
"too long");
if(FLAGS_GET_RCODE(msg->flags) == LDNS_RCODE_YXDOMAIN) {
prev = rrset;
rrset = rrset->rrset_all_next;
continue;
}
return 0;
}
cname_length++;
@@ -575,6 +495,8 @@ scrub_normalize(sldns_buffer* pkt, struct msg_parse* msg,
log_err("out of memory synthesizing CNAME");
return 0;
}
/* FIXME: resolve the conflict between synthesized
* CNAME ttls and the cache. */
rrset = nx;
continue;
@@ -591,18 +513,12 @@ 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 &&
nx->type == LDNS_RR_TYPE_DNAME &&
nx->rr_count == 1 &&
pkt_strict_sub(pkt, sname, nx->dname) &&
pkt_sub(pkt, nx->dname, zonename)) {
pkt_strict_sub(pkt, sname, nx->dname)) {
/* there is a DNAME after this CNAME, it
* is in the ANSWER section, and the DNAME
* applies to the name we cover */
@@ -674,7 +590,6 @@ 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;
@@ -698,8 +613,6 @@ scrub_normalize(sldns_buffer* pkt, struct msg_parse* msg,
"RRset:", pkt, msg, prev, &rrset);
continue;
}
if((int)rrset->rrsig_count > env->cfg->iter_scrub_rrsig)
shorten_rrsig(pkt, rrset, env->cfg->iter_scrub_rrsig);
/* only one NS set allowed in authority section */
if(rrset->type==LDNS_RR_TYPE_NS) {
/* NS set must be pertinent to the query */
@@ -737,34 +650,6 @@ scrub_normalize(sldns_buffer* pkt, struct msg_parse* msg,
"RRset:", pkt, msg, prev, &rrset);
continue;
}
/* Also delete promiscuous NS for other RCODEs */
if(FLAGS_GET_RCODE(msg->flags) != LDNS_RCODE_NOERROR
&& env->cfg->iter_scrub_promiscuous) {
remove_rrset("normalize: removing promiscuous "
"RRset:", pkt, msg, prev, &rrset);
continue;
}
/* Also delete promiscuous NS for NOERROR with nodata
* for authoritative answers, not for delegations.
* NOERROR with an_rrsets!=0 already handled.
* Also NOERROR and soa_in_auth already handled.
* NOERROR with an_rrsets==0, and not a referral.
* referral is (NS not the zonename, noSOA).
*/
if(FLAGS_GET_RCODE(msg->flags) == LDNS_RCODE_NOERROR
&& msg->an_rrsets == 0
&& !(dname_pkt_compare(pkt, rrset->dname,
zonename) != 0 && !soa_in_auth(msg))
&& env->cfg->iter_scrub_promiscuous) {
remove_rrset("normalize: removing promiscuous "
"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 {
@@ -810,13 +695,7 @@ scrub_normalize(sldns_buffer* pkt, struct msg_parse* msg,
rrset->rrset_all_next = NULL;
return 1;
}
/* Only mark glue as allowed for type NS in the authority
* section. Other RR types do not get glue for them, it
* is allowed from the answer section, but not authority
* so that a message can not have address records cached
* as a side effect to the query. */
if(rrset->type==LDNS_RR_TYPE_NS)
mark_additional_rrset(pkt, msg, rrset);
mark_additional_rrset(pkt, msg, rrset);
prev = rrset;
rrset = rrset->rrset_all_next;
}
@@ -853,8 +732,6 @@ scrub_normalize(sldns_buffer* pkt, struct msg_parse* msg,
"RRset:", pkt, msg, prev, &rrset);
continue;
}
if((int)rrset->rrsig_count > env->cfg->iter_scrub_rrsig)
shorten_rrsig(pkt, rrset, env->cfg->iter_scrub_rrsig);
prev = rrset;
rrset = rrset->rrset_all_next;
}
@@ -1001,20 +878,12 @@ 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,
int pkt_before_NS, int* msg_lame_empty, int* msg_lame_referral,
int rdset)
struct iter_env* ie, struct module_qstate* qstate)
{
int del_addi = 0; /* if additional-holding rrsets are deleted, we
do not trust the normalized additional-A-AAAA any more */
@@ -1073,10 +942,8 @@ scrub_sanitize(sldns_buffer* pkt, struct msg_parse* msg,
}
/* remove private addresses */
if(rrset->type == LDNS_RR_TYPE_A ||
rrset->type == LDNS_RR_TYPE_AAAA ||
rrset->type == LDNS_RR_TYPE_SVCB ||
rrset->type == LDNS_RR_TYPE_HTTPS) {
if( (rrset->type == LDNS_RR_TYPE_A ||
rrset->type == LDNS_RR_TYPE_AAAA)) {
/* do not set servfail since this leads to too
* many drops of other people using rfc1918 space */
@@ -1171,21 +1038,6 @@ 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;
}
@@ -1193,15 +1045,11 @@ 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, int* msg_lame_empty, int* msg_lame_referral,
int rdset)
struct iter_env* ie)
{
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) )
@@ -1212,8 +1060,7 @@ scrub_message(sldns_buffer* pkt, struct msg_parse* msg,
/* this is not required for basic operation but is a forgery
* resistance (security) feature */
if((FLAGS_GET_RCODE(msg->flags) == LDNS_RCODE_NOERROR ||
FLAGS_GET_RCODE(msg->flags) == LDNS_RCODE_NXDOMAIN ||
FLAGS_GET_RCODE(msg->flags) == LDNS_RCODE_YXDOMAIN) &&
FLAGS_GET_RCODE(msg->flags) == LDNS_RCODE_NXDOMAIN) &&
msg->qdcount == 0)
return 0;
@@ -1226,21 +1073,11 @@ 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))
if(!scrub_normalize(pkt, msg, qinfo, region, env))
return 0;
/* delete all out-of-zone information */
if(!scrub_sanitize(pkt, msg, qinfo, zonename, env, ie, qstate,
pkt_before_NS, msg_lame_empty, msg_lame_referral, rdset))
if(!scrub_sanitize(pkt, msg, qinfo, zonename, env, ie, qstate))
return 0;
return 1;
}
+1 -6
View File
@@ -62,16 +62,11 @@ 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, int* msg_lame_empty, int* msg_lame_referral,
int rdset);
struct iter_env* ie);
#endif /* ITERATOR_ITER_SCRUB_H */
+5 -56
View File
@@ -253,9 +253,7 @@ iter_apply_cfg(struct iter_env* iter_env, struct config_file* cfg)
return 1;
}
/** filter out unsuitable targets.
* Applies NAT64 if needed as well by replacing the IPv4 with the synthesized
* IPv6 address.
/** filter out unsuitable targets
* @param iter_env: iterator environment with ipv6-support flag.
* @param env: module environment with infra cache.
* @param name: zone name
@@ -308,30 +306,9 @@ iter_filter_unsuitable(struct iter_env* iter_env, struct module_env* env,
if(a->bogus)
return -1; /* address of server is bogus */
if(donotq_lookup(iter_env->donotq, &a->addr, a->addrlen)) {
if(iter_env->nat64.use_nat64 &&
addr_is_ip6(&a->addr, a->addrlen) &&
a->addrlen == iter_env->nat64.nat64_prefix_addrlen &&
addr_in_common(&a->addr, 128,
&iter_env->nat64.nat64_prefix_addr,
iter_env->nat64.nat64_prefix_net,
iter_env->nat64.nat64_prefix_addrlen) ==
iter_env->nat64.nat64_prefix_net) {
/* The NAT64 is enabled, and address is IPv6, it is
* in the NAT64 prefix. It is allowed.
* So that in an IPv6-only cluster without internet
* access, that makes the NAT64 translation continue
* to work. The NAT64 prefix is allowed. */
/* Otherwise, after a timeout, the already NAT64
* translated address would be treated differently,
* and that causes confusion. */
log_addr(VERB_ALGO, "the addr is on the donotquery "
"list, but allowed because it is NAT64",
&a->addr, a->addrlen);
} else {
log_addr(VERB_ALGO, "skip addr on the donotquery list",
&a->addr, a->addrlen);
return -1; /* server is on the donotquery list */
}
log_addr(VERB_ALGO, "skip addr on the donotquery list",
&a->addr, a->addrlen);
return -1; /* server is on the donotquery list */
}
if(!iter_env->supports_ipv6 && addr_is_ip6(&a->addr, a->addrlen)) {
return -1; /* there is no ip6 available */
@@ -340,20 +317,6 @@ iter_filter_unsuitable(struct iter_env* iter_env, struct module_env* env,
!addr_is_ip6(&a->addr, a->addrlen)) {
return -1; /* there is no ip4 available */
}
if(iter_env->nat64.use_nat64 && !addr_is_ip6(&a->addr, a->addrlen)) {
struct sockaddr_storage real_addr;
socklen_t real_addrlen;
addr_to_nat64(&a->addr, &iter_env->nat64.nat64_prefix_addr,
iter_env->nat64.nat64_prefix_addrlen,
iter_env->nat64.nat64_prefix_net,
&real_addr, &real_addrlen);
log_name_addr(VERB_QUERY, "NAT64 apply: from: ",
name, &a->addr, a->addrlen);
log_name_addr(VERB_QUERY, "NAT64 apply: to: ",
name, &real_addr, real_addrlen);
a->addr = real_addr;
a->addrlen = real_addrlen;
}
/* check lameness - need zone , class info */
if(infra_get_lame_rtt(env->infra_cache, &a->addr, a->addrlen,
name, namelen, qtype, &lame, &dnsseclame, &reclame,
@@ -1313,8 +1276,7 @@ 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,
deleg_port_number(env))) {
if(!delegpt_rrset_add_ns(dp, region, akey, 1)) {
lock_rw_unlock(&akey->entry.lock);
return 0;
}
@@ -1549,11 +1511,6 @@ iter_stub_fwd_no_cache(struct module_qstate *qstate, struct query_info *qinf,
struct delegpt *dp;
int nolock = 1;
log_assert((retdpname && retdpnamelen
&& dpname_storage && dpname_storage_len > 0) ||
(retdpname == NULL && retdpnamelen == NULL
&& dpname_storage == NULL && dpname_storage_len == 0));
/* Check for stub. */
/* Lock both forwards and hints for atomic read. */
lock_rw_rdlock(&qstate->env->fwds->lock);
@@ -1704,11 +1661,3 @@ 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;
}
-4
View File
@@ -84,7 +84,6 @@ int iter_apply_cfg(struct iter_env* iter_env, struct config_file* cfg);
/**
* Select a valid, nice target to send query to.
* Sorting and removing unsuitable targets is combined.
* Adds records to the infra cache if not already there.
*
* @param iter_env: iterator module global state, with ip6 enabled and
* do-not-query-addresses.
@@ -483,7 +482,4 @@ 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);
#endif /* ITERATOR_ITER_UTILS_H */
+57 -131
View File
@@ -81,8 +81,7 @@ int BLACKLIST_PENALTY = (120000*4);
/** Timeout when only a single probe query per IP is allowed. */
int PROBE_MAXRTO = PROBE_MAXRTO_DEFAULT; /* in msec */
static void target_count_increase_nx(struct module_qstate* qstate,
struct iter_qstate* iq, int num);
static void target_count_increase_nx(struct iter_qstate* iq, int num);
int
iter_init(struct module_env* env, int id)
@@ -251,7 +250,7 @@ error_supers(struct module_qstate* qstate, int id, struct module_qstate* super)
if((dpns->got4 == 2 || (!ie->supports_ipv4 && !ie->nat64.use_nat64)) &&
(dpns->got6 == 2 || !ie->supports_ipv6)) {
dpns->resolved = 1; /* mark as failed */
target_count_increase_nx(super, super_iq, 1);
target_count_increase_nx(super_iq, 1);
}
}
if(qstate->qinfo.qtype == LDNS_RR_TYPE_NS) {
@@ -298,7 +297,6 @@ error_response_cache(struct module_qstate* qstate, int id, int rcode)
struct reply_info err;
struct msgreply_entry* msg;
if(qstate->no_cache_store) {
qstate->error_response_cache = 1;
return error_response(qstate, id, rcode);
}
if(qstate->prefetch_leeway > NORR_TTL) {
@@ -735,7 +733,7 @@ is_caps_whitelisted(struct iter_env* ie, struct iter_qstate* iq)
* created for the parent query.
*/
static void
target_count_create(struct module_qstate* qstate, struct iter_qstate* iq)
target_count_create(struct iter_qstate* iq)
{
if(!iq->target_count) {
iq->target_count = (int*)calloc(TARGET_COUNT_MAX, sizeof(int));
@@ -743,57 +741,33 @@ target_count_create(struct module_qstate* qstate, struct iter_qstate* iq)
if(iq->target_count) {
iq->target_count[TARGET_COUNT_REF] = 1;
iq->nxns_dp = (uint8_t**)calloc(1, sizeof(uint8_t*));
/* continue global quota from where it was. */
if(qstate->global_quota_reached >
iq->target_count[TARGET_COUNT_GLOBAL_QUOTA])
iq->target_count[TARGET_COUNT_GLOBAL_QUOTA] =
qstate->global_quota_reached;
}
}
}
static void
target_count_store(struct module_qstate* qstate, struct iter_qstate* iq)
target_count_increase(struct iter_qstate* iq, int num)
{
if(iq->target_count) {
/* By storing the global quota counter, it stays
* there to be picked up if the module is restarted,
* eg. due to a validator retry, and then the
* target_count_create routine picks it up. */
if(iq->target_count[TARGET_COUNT_GLOBAL_QUOTA] >
qstate->global_quota_reached)
qstate->global_quota_reached =
iq->target_count[TARGET_COUNT_GLOBAL_QUOTA];
}
}
static void
target_count_increase(struct module_qstate* qstate,
struct iter_qstate* iq, int num)
{
target_count_create(qstate, iq);
target_count_create(iq);
if(iq->target_count)
iq->target_count[TARGET_COUNT_QUERIES] += num;
iq->dp_target_count++;
}
static void
target_count_increase_nx(struct module_qstate* qstate,
struct iter_qstate* iq, int num)
target_count_increase_nx(struct iter_qstate* iq, int num)
{
target_count_create(qstate, iq);
target_count_create(iq);
if(iq->target_count)
iq->target_count[TARGET_COUNT_NX] += num;
}
static void
target_count_increase_global_quota(struct module_qstate* qstate,
struct iter_qstate* iq, int num)
target_count_increase_global_quota(struct iter_qstate* iq, int num)
{
target_count_create(qstate, iq);
target_count_create(iq);
if(iq->target_count)
iq->target_count[TARGET_COUNT_GLOBAL_QUOTA] += num;
target_count_store(qstate, iq);
}
/**
@@ -886,7 +860,7 @@ generate_sub_request(uint8_t* qname, size_t qnamelen, uint16_t qtype,
subiq = (struct iter_qstate*)subq->minfo[id];
memset(subiq, 0, sizeof(*subiq));
subiq->num_target_queries = 0;
target_count_create(qstate, iq);
target_count_create(iq);
subiq->target_count = iq->target_count;
if(iq->target_count) {
iq->target_count[TARGET_COUNT_REF] ++; /* extra reference */
@@ -1511,7 +1485,6 @@ 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
@@ -1531,7 +1504,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*/, dpname,
*qstate->env->now, 1/*add SOA*/, NULL,
qstate->env->cfg);
}
/* item taken from cache does not match our query name, thus
@@ -2260,7 +2233,7 @@ processLastResort(struct module_qstate* qstate, struct iter_qstate* iq,
return error_response_cache(qstate, id, LDNS_RCODE_SERVFAIL);
}
iq->num_target_queries += qs;
target_count_increase(qstate, iq, qs);
target_count_increase(iq, qs);
if(qs != 0) {
qstate->ext_state[id] = module_wait_subquery;
return 0; /* and wait for them */
@@ -2316,7 +2289,7 @@ processLastResort(struct module_qstate* qstate, struct iter_qstate* iq,
* lookups at a time. */
verbose(VERB_ALGO, "try parent-side glue lookup");
iq->num_target_queries += query_count;
target_count_increase(qstate, iq, query_count);
target_count_increase(iq, query_count);
qstate->ext_state[id] = module_wait_subquery;
return 0;
}
@@ -2336,7 +2309,7 @@ processLastResort(struct module_qstate* qstate, struct iter_qstate* iq,
if(query_count != 0) { /* suspend to await results */
verbose(VERB_ALGO, "try parent-side glue lookup");
iq->num_target_queries += query_count;
target_count_increase(qstate, iq, query_count);
target_count_increase(iq, query_count);
qstate->ext_state[id] = module_wait_subquery;
return 0;
}
@@ -2392,12 +2365,6 @@ 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
@@ -2469,6 +2436,8 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
int tf_policy;
struct delegpt_addr* target;
struct outbound_entry* outq;
struct sockaddr_storage real_addr;
socklen_t real_addrlen;
int auth_fallback = 0;
uint8_t* qout_orig = NULL;
size_t qout_orig_len = 0;
@@ -2820,7 +2789,7 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
return error_response_cache(qstate, id, LDNS_RCODE_SERVFAIL);
}
iq->num_target_queries += extra;
target_count_increase(qstate, iq, extra);
target_count_increase(iq, extra);
if(iq->num_target_queries > 0) {
/* wait to get all targets, we want to try em */
verbose(VERB_ALGO, "wait for all targets for fallback");
@@ -2871,7 +2840,7 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
/* errors ignored, these targets are not strictly necessary for
* this result, we do not have to reply with SERVFAIL */
iq->num_target_queries += extra;
target_count_increase(qstate, iq, extra);
target_count_increase(iq, extra);
}
/* Add the current set of unused targets to our queue. */
@@ -2994,7 +2963,7 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
LDNS_RCODE_SERVFAIL);
}
iq->num_target_queries += qs;
target_count_increase(qstate, iq, qs);
target_count_increase(iq, qs);
}
/* Since a target query might have been made, we
* need to check again. */
@@ -3054,7 +3023,7 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
* this result, we do not have to reply with SERVFAIL */
if(extra > 0) {
iq->num_target_queries += extra;
target_count_increase(qstate, iq, extra);
target_count_increase(iq, extra);
check_waiting_queries(iq, qstate, id);
/* undo qname minimise step because we'll get back here
* to do it again */
@@ -3067,7 +3036,7 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
}
}
target_count_increase_global_quota(qstate, iq, 1);
target_count_increase_global_quota(iq, 1);
if(iq->target_count && iq->target_count[TARGET_COUNT_GLOBAL_QUOTA]
> MAX_GLOBAL_QUOTA) {
char s[LDNS_MAX_DOMAINLEN];
@@ -3080,9 +3049,7 @@ 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));
iq->ratelimit_incremented = 0;
sq_check_ratelimit = (!(iq->chase_flags & BIT_RD) && !iq->ratelimit_ok);
/* We have a valid target. */
if(verbosity >= VERB_QUERY) {
log_query_info(VERB_QUERY, "sending query:", &iq->qinfo_out);
@@ -3093,6 +3060,17 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
iq->dnssec_lame_query?" but lame_query anyway": "");
}
real_addr = target->addr;
real_addrlen = target->addrlen;
if(ie->nat64.use_nat64 && target->addr.ss_family == AF_INET) {
addr_to_nat64(&target->addr, &ie->nat64.nat64_prefix_addr,
ie->nat64.nat64_prefix_addrlen, ie->nat64.nat64_prefix_net,
&real_addr, &real_addrlen);
log_name_addr(VERB_QUERY, "applied NAT64:",
iq->dp->name, &real_addr, real_addrlen);
}
fptr_ok(fptr_whitelist_modenv_send_query(qstate->env->send_query));
outq = (*qstate->env->send_query)(&iq->qinfo_out,
iq->chase_flags | (iq->chase_to_rd?BIT_RD:0),
@@ -3104,12 +3082,11 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
!qstate->blacklist&&(!iter_qname_indicates_dnssec(qstate->env,
&iq->qinfo_out)||target->attempts==1)?0:BIT_CD),
iq->dnssec_expected, iq->caps_fallback || is_caps_whitelisted(
ie, iq), sq_check_ratelimit, &target->addr, target->addrlen,
ie, iq), sq_check_ratelimit, &real_addr, real_addrlen,
iq->dp->name, iq->dp->namelen,
(iq->dp->tcp_upstream || qstate->env->cfg->tcp_upstream),
(iq->dp->ssl_upstream || qstate->env->cfg->ssl_upstream),
target->tls_auth_name, qstate, &sq_was_ratelimited,
&iq->ratelimit_incremented);
target->tls_auth_name, qstate, &sq_was_ratelimited);
if(!outq) {
if(sq_was_ratelimited) {
lock_basic_lock(&ie->queries_ratelimit_lock);
@@ -3122,7 +3099,7 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
return error_response_cache(qstate, id, LDNS_RCODE_SERVFAIL);
}
log_addr(VERB_QUERY, "error sending query to auth server",
&target->addr, target->addrlen);
&real_addr, real_addrlen);
if(qstate->env->cfg->qname_minimisation)
iq->minimisation_state = SKIP_MINIMISE_STATE;
return next_state(iq, QUERYTARGETS_STATE);
@@ -3147,6 +3124,7 @@ 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
@@ -3188,8 +3166,7 @@ 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->msg_lame_empty, iq->msg_lame_referral);
iq->response, &iq->qinfo_out, iq->dp, &iq->empty_nodata_found);
iq->chase_to_rd = 0;
/* remove TC flag, if this is erroneously set by TCP upstream */
iq->response->rep->flags &= ~BIT_TC;
@@ -3259,19 +3236,8 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
} else iter_scrub_ds(iq->response, NULL, NULL);
if(type == RESPONSE_TYPE_THROWAWAY &&
FLAGS_GET_RCODE(iq->response->rep->flags) == LDNS_RCODE_YXDOMAIN) {
/* YXDOMAIN is a permanent error for DNAME expansion overflow
* (RFC 6672 Section 2.2). Only accept if the response
* contains a DNAME record in the answer section; otherwise
* treat as invalid, to make sure the authoritative answer
* make sense. */
size_t i;
for(i=0; i<iq->response->rep->an_numrrsets; i++) {
if(ntohs(iq->response->rep->rrsets[i]->rk.type)
== LDNS_RR_TYPE_DNAME) {
type = RESPONSE_TYPE_ANSWER;
break;
}
}
/* YXDOMAIN is a permanent error, no need to retry */
type = RESPONSE_TYPE_ANSWER;
}
if(type == RESPONSE_TYPE_CNAME)
origtypecname = 1;
@@ -3467,14 +3433,7 @@ 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;
/* 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));
iq->dp = delegpt_from_message(iq->response, qstate->region);
if (qstate->env->cfg->qname_minimisation)
iq->minimisation_state = INIT_MINIMISE_STATE;
if(!iq->dp) {
@@ -3657,7 +3616,7 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
return next_state(iq, INIT_REQUEST_STATE);
} else if(type == RESPONSE_TYPE_LAME) {
/* Cache the LAMEness. */
verbose(VERB_DETAIL, "query response was categorized as %sLAME",
verbose(VERB_DETAIL, "query response was %sLAME",
dnsseclame?"DNSSEC ":"");
if(!dname_subdomain_c(iq->qchase.qname, iq->dp->name)) {
log_err("mark lame: mismatch in qname and dpname");
@@ -3696,7 +3655,7 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
* In this case, the event is just sent directly back to
* the QUERYTARGETS_STATE without resetting anything,
* because, clearly, the next target must be tried. */
verbose(VERB_DETAIL, "query response was categorized as THROWAWAY");
verbose(VERB_DETAIL, "query response was THROWAWAY");
} else {
log_warn("A query response came back with an unknown type: %d",
(int)type);
@@ -3751,8 +3710,7 @@ 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,
deleg_port_number(forq->env));
dp = delegpt_from_message(qstate->return_msg, forq->region);
if(!dp) {
/* if there is no convertible delegation point, then
* the ANSWER type was (presumably) a negative answer. */
@@ -3803,8 +3761,7 @@ 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->msg_lame_empty,
iq->msg_lame_referral);
iq->response, &iq->qchase, iq->dp, NULL);
if(type == RESPONSE_TYPE_ANSWER) {
qstate->return_rcode = LDNS_RCODE_NOERROR;
qstate->return_msg = iq->response;
@@ -3923,7 +3880,7 @@ processTargetResponse(struct module_qstate* qstate, int id,
/* no new addresses, increase the nxns counter, like
* this could be a list of wildcards with no new
* addresses */
target_count_increase_nx(qstate, foriq, 1);
target_count_increase_nx(foriq, 1);
}
verbose(VERB_ALGO, "added target response");
delegpt_log(VERB_ALGO, foriq->dp);
@@ -3935,7 +3892,7 @@ processTargetResponse(struct module_qstate* qstate, int id,
dpns->resolved = 1; /* fail the target */
/* do not count cached answers */
if(qstate->reply_origin && qstate->reply_origin->len != 0) {
target_count_increase_nx(qstate, foriq, 1);
target_count_increase_nx(foriq, 1);
}
}
}
@@ -3968,8 +3925,7 @@ processDSNSResponse(struct module_qstate* qstate, int id,
/* else, store as DP and continue at querytargets */
foriq->state = QUERYTARGETS_STATE;
foriq->dp = delegpt_from_message(qstate->return_msg, forq->region,
deleg_port_number(forq->env));
foriq->dp = delegpt_from_message(qstate->return_msg, forq->region);
if(!foriq->dp) {
log_err("out of memory in dsns dp alloc");
errinf(qstate, "malloc failure, in DS search");
@@ -4018,7 +3974,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 i, n = from->rep->rrset_count+to->rep->rrset_count;
size_t 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;
@@ -4040,49 +3996,24 @@ processClassResponse(struct module_qstate* qstate, int id,
memcpy(dest, to->rep->rrsets, to->rep->an_numrrsets
* sizeof(dest[0]));
dest += to->rep->an_numrrsets;
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;
}
}
memcpy(dest, from->rep->rrsets, from->rep->an_numrrsets
* sizeof(dest[0]));
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;
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;
}
}
memcpy(dest, from->rep->rrsets+from->rep->an_numrrsets,
from->rep->ns_numrrsets * sizeof(dest[0]));
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;
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;
}
}
memcpy(dest, from->rep->rrsets+from->rep->an_numrrsets+
from->rep->ns_numrrsets,
from->rep->ar_numrrsets * sizeof(dest[0]));
/* update counts */
to->rep->rrsets = d;
to->rep->an_numrrsets += from->rep->an_numrrsets;
@@ -4186,7 +4117,6 @@ processFinished(struct module_qstate* qstate, struct iter_qstate* iq,
iter_store_parentside_neg(qstate->env, &qstate->qinfo,
iq->deleg_msg?iq->deleg_msg->rep:
(iq->response?iq->response->rep:NULL));
target_count_store(qstate, iq);
if(!iq->response) {
verbose(VERB_ALGO, "No response is set, servfail");
errinf(qstate, "(no response found at query finish)");
@@ -4440,10 +4370,7 @@ 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,
&iq->msg_lame_empty, &iq->msg_lame_referral,
(int)((iq->chase_flags&BIT_RD) || iq->chase_to_rd)
)) {
qstate->env->scratch, qstate->env, qstate, ie)) {
/* if 0x20 enabled, start fallback, but we have no message */
if(event == module_event_capsfail && !iq->caps_fallback) {
iq->caps_fallback = 1;
@@ -4605,7 +4532,6 @@ iter_clear(struct module_qstate* qstate, int id)
iq = (struct iter_qstate*)qstate->minfo[id];
if(iq) {
outbound_list_clear(&iq->outlist);
target_count_store(qstate, iq);
if(iq->target_count && --iq->target_count[TARGET_COUNT_REF] == 0) {
free(iq->target_count);
if(*iq->nxns_dp) free(*iq->nxns_dp);
-18
View File
@@ -104,11 +104,6 @@ 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.
@@ -380,10 +375,6 @@ 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.
@@ -408,8 +399,6 @@ 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.
@@ -445,13 +434,6 @@ 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;
+4 -1
View File
@@ -52,6 +52,7 @@
#include "util/data/msgreply.h"
#include "util/storage/slabhash.h"
#include "util/edns.h"
#include "util/tsig.h"
#include "sldns/sbuffer.h"
#include "iterator/iter_fwd.h"
#include "iterator/iter_hints.h"
@@ -81,13 +82,15 @@ context_finalize(struct ub_ctx* ctx)
return UB_INITFAIL;
listen_setup_locks();
log_edns_known_options(VERB_ALGO, ctx->env);
if(!tsig_key_table_apply_cfg(ctx->env->tsig_key_table, cfg))
return UB_INITFAIL;
ctx->local_zones = local_zones_create();
if(!ctx->local_zones)
return UB_NOMEM;
if(!local_zones_apply_cfg(ctx->local_zones, cfg))
return UB_INITFAIL;
if(!auth_zones_apply_cfg(ctx->env->auth_zones, cfg, 1, &is_rpz,
ctx->env, &ctx->mods))
ctx->env, &ctx->mods, ctx->env->tsig_key_table))
return UB_INITFAIL;
if(!(ctx->env->fwds = forwards_create()) ||
!forwards_apply_cfg(ctx->env->fwds, cfg))
-2
View File
@@ -167,8 +167,6 @@ 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;
+14 -17
View File
@@ -59,6 +59,7 @@
#include "util/tube.h"
#include "util/ub_event.h"
#include "util/edns.h"
#include "util/tsig.h"
#include "services/modstack.h"
#include "services/localzone.h"
#include "services/cache/infra.h"
@@ -168,6 +169,18 @@ static struct ub_ctx* ub_ctx_create_nopipe(void)
errno = ENOMEM;
return NULL;
}
ctx->env->tsig_key_table = tsig_key_table_create();
if(!ctx->env->tsig_key_table) {
auth_zones_delete(ctx->env->auth_zones);
edns_known_options_delete(ctx->env);
edns_strings_delete(ctx->env->edns_strings);
config_delete(ctx->env->cfg);
free(ctx->env);
ub_randfree(ctx->seed_rnd);
free(ctx);
errno = ENOMEM;
return NULL;
}
ctx->env->alloc = &ctx->superalloc;
ctx->env->worker = NULL;
@@ -388,6 +401,7 @@ ub_ctx_delete(struct ub_ctx* ctx)
config_delete(ctx->env->cfg);
edns_known_options_delete(ctx->env);
edns_strings_delete(ctx->env->edns_strings);
tsig_key_table_delete(ctx->env->tsig_key_table);
forwards_delete(ctx->env->fwds);
hints_delete(ctx->env->hints);
auth_zones_delete(ctx->env->auth_zones);
@@ -571,8 +585,6 @@ 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);
}
@@ -580,8 +592,6 @@ 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);
}
@@ -676,8 +686,6 @@ 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);
@@ -706,8 +714,6 @@ 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) {
@@ -845,8 +851,6 @@ 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;
@@ -1477,15 +1481,8 @@ 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;
+10 -22
View File
@@ -105,7 +105,6 @@ libworker_delete_env(struct libworker* w)
SSL_CTX_free(w->sslctx);
#endif
outside_network_delete(w->back);
shared_ports_delete(w->shared_ports);
}
/** delete libworker struct */
@@ -220,25 +219,19 @@ libworker_setup(struct ub_ctx* ctx, int is_bg, struct ub_event_base* eb)
libworker_delete(w);
return NULL;
}
if(!(w->shared_ports = shared_ports_create(cfg->out_ifs,
cfg->num_out_ifs, cfg->do_ip4, cfg->do_ip6, ports, numports))) {
if(!w->is_bg || w->is_bg_thread) {
lock_basic_unlock(&ctx->cfglock);
}
libworker_delete(w);
return NULL;
}
w->back = outside_network_create(w->base, cfg->msg_buffer_size,
(size_t)cfg->outgoing_num_ports, cfg->out_ifs,
cfg->num_out_ifs, cfg->do_ip4, cfg->do_ip6,
cfg->do_tcp?cfg->outgoing_num_tcp:0, cfg->ip_dscp,
w->env->infra_cache, w->env->rnd, cfg->use_caps_bits_for_id,
cfg->unwanted_threshold,
ports, numports, cfg->unwanted_threshold,
cfg->outgoing_tcp_mss, &libworker_alloc_cleanup, w,
cfg->do_udp || cfg->udp_upstream_without_downstream, w->sslctx,
cfg->delay_close, cfg->tls_use_sni, NULL, cfg->udp_connect,
cfg->max_reuse_tcp_queries, cfg->tcp_reuse_timeout,
cfg->tcp_auth_query_timeout, w->shared_ports);
cfg->tcp_auth_query_timeout, (const char**)cfg->dist,
(const char**)cfg->dist_tsig,
cfg->num_dist);
w->env->outnet = w->back;
if(!w->is_bg || w->is_bg_thread) {
lock_basic_unlock(&ctx->cfglock);
@@ -651,8 +644,7 @@ int libworker_fg(struct ub_ctx* ctx, struct ctx_query* q)
}
/* process new query */
if(!mesh_new_callback(w->env->mesh, &qinfo, qflags, &edns,
w->back->udp_buff, qid, libworker_fg_done_cb, q, 0,
&q->unique_info)) {
w->back->udp_buff, qid, libworker_fg_done_cb, q, 0)) {
free(qinfo.qname);
return UB_NOMEM;
}
@@ -733,8 +725,7 @@ int libworker_attach_mesh(struct ub_ctx* ctx, struct ctx_query* q,
if(async_id)
*async_id = q->querynum;
if(!mesh_new_callback(w->env->mesh, &qinfo, qflags, &edns,
w->back->udp_buff, qid, libworker_event_done_cb, q, 0,
&q->unique_info)) {
w->back->udp_buff, qid, libworker_event_done_cb, q, 0)) {
free(qinfo.qname);
return UB_NOMEM;
}
@@ -872,8 +863,7 @@ handle_newq(struct libworker* w, uint8_t* buf, uint32_t len)
q->w = w;
/* process new query */
if(!mesh_new_callback(w->env->mesh, &qinfo, qflags, &edns,
w->back->udp_buff, qid, libworker_bg_done_cb, q, 0,
&q->unique_info)) {
w->back->udp_buff, qid, libworker_bg_done_cb, q, 0)) {
add_bg_result(w, q, NULL, UB_NOMEM, NULL, 0);
}
free(qinfo.qname);
@@ -891,8 +881,7 @@ 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,
int* ratelimit_incremented)
struct module_qstate* q, int* was_ratelimited)
{
struct libworker* w = (struct libworker*)q->env->worker;
struct outbound_entry* e = (struct outbound_entry*)regional_alloc(
@@ -904,7 +893,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, ratelimit_incremented);
was_ratelimited);
if(!e->qsent) {
return NULL;
}
@@ -989,8 +978,7 @@ 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),
int* ATTR_UNUSED(ratelimit_incremented))
struct module_qstate* ATTR_UNUSED(q), int* ATTR_UNUSED(was_ratelimited))
{
log_assert(0);
return 0;
-3
View File
@@ -60,7 +60,6 @@ struct tube;
struct sldns_buffer;
struct ub_event_base;
struct query_info;
struct shared_ports;
/**
* The library-worker status structure
@@ -85,8 +84,6 @@ struct libworker {
struct comm_base* base;
/** the backside outside network interface to the auth servers */
struct outside_network* back;
/** shared ports structure */
struct shared_ports* shared_ports;
/** random() table for this worker. */
struct ub_randstate* rndstate;
/** sslcontext for SSL wrapped DNS over TCP queries */
-65
View File
@@ -1,65 +0,0 @@
/*
* 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 */
-4
View File
@@ -853,8 +853,6 @@ struct ub_server_stats {
long long qquic;
/** number of queries removed due to discard-timeout */
long long num_queries_discard_timeout;
/** number of queries removed due to replyaddr limit */
long long num_queries_replyaddr_limit;
/** number of queries removed due to wait-limit */
long long num_queries_wait_limit;
/** number of dns error reports generated */
@@ -874,8 +872,6 @@ struct ub_stats_info {
long long mesh_num_states;
/** mesh stats: current number of reply (user) states */
long long mesh_num_reply_states;
/** mesh stats: current number of reply entries */
long long mesh_num_reply_addrs;
/** mesh stats: number of reply states overwritten with a new one */
long long mesh_jostled;
/** mesh stats: number of incoming queries dropped */
+11 -8
View File
@@ -70,8 +70,6 @@ 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.
*/
@@ -80,8 +78,7 @@ 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,
int* ratelimit_incremented);
struct module_qstate* q, int* was_ratelimited);
/** process incoming serviced query replies from the network */
int libworker_handle_service_reply(struct comm_point* c, void* arg, int error,
@@ -129,8 +126,6 @@ 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.
*/
@@ -139,8 +134,7 @@ 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,
int* ratelimit_incremented);
struct module_qstate* q, int* was_ratelimited);
/**
* process control messages from the main thread. Frees the control
@@ -177,4 +171,13 @@ 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 */
Regular → Executable
+602 -315
View File
File diff suppressed because it is too large Load Diff
-5
View File
@@ -466,13 +466,9 @@ 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"
@@ -489,7 +485,6 @@ 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"
+1 -2
View File
@@ -729,8 +729,7 @@ 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,
int* ratelimit_incremented);
char* tls_auth_name, struct module_qstate* q, int* was_ratelimited);
void (*detach_subs)(struct module_qstate* qstate);
int (*attach_sub)(struct module_qstate* qstate,
struct query_info* qinfo, struct respip_client_info* cinfo,
+1 -14
View File
@@ -487,23 +487,10 @@ 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);
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
flen = (size_t)ftell(script_py);
fstr = malloc(flen+1);
if(!fstr) {
log_err("malloc failure to print parse error");
+22 -42
View File
@@ -899,34 +899,27 @@ respip_rewrite_reply(const struct query_info* qinfo,
int rpz_cname_override = 0;
char* log_name = NULL;
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. */
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;
}
/* The view is rdlocked by views_find_view. */
}
log_assert(ipset);
@@ -980,9 +973,6 @@ respip_rewrite_reply(const struct query_info* qinfo,
lock_rw_unlock(&raddr->lock);
lock_rw_unlock(&a->lock);
lock_rw_unlock(&az->rpz_lock);
if(view) {
lock_rw_unlock(&view->lock);
}
return 0;
}
if(rpz_used) {
@@ -1121,13 +1111,7 @@ respip_operate(struct module_qstate* qstate, enum module_ev event, int id,
if((qstate->qinfo.qtype == LDNS_RR_TYPE_A ||
qstate->qinfo.qtype == LDNS_RR_TYPE_AAAA ||
qstate->qinfo.qtype == LDNS_RR_TYPE_ANY) &&
qstate->return_msg && qstate->return_msg->rep &&
!(qstate->env->need_to_validate &&
(!(qstate->query_flags & BIT_CD)
|| qstate->env->cfg->ignore_cd) &&
(qstate->return_msg->rep->security <= sec_status_bogus
|| qstate->return_msg->rep->security ==
sec_status_secure_sentinel_fail))) {
qstate->return_msg && qstate->return_msg->rep) {
struct reply_info* new_rep = qstate->return_msg->rep;
struct ub_packed_rrset_key* alias_rrset = NULL;
struct respip_action_info actinfo = {0, 0, 0, 0, NULL, 0, NULL};
@@ -1164,10 +1148,8 @@ 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)) {
errinf(qstate, "Could not generate CNAME request");
if(!generate_cname_request(qstate, alias_rrset))
goto servfail;
}
next_state = module_wait_subquery;
}
qstate->return_msg->rep = new_rep;
@@ -1181,7 +1163,6 @@ 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
@@ -1278,7 +1259,6 @@ 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;
+369 -423
View File
File diff suppressed because it is too large Load Diff
+21 -32
View File
@@ -55,6 +55,8 @@ struct query_info;
struct dns_msg;
struct edns_data;
struct module_env;
struct tsig_data;
struct tsig_key_table;
struct worker;
struct comm_point;
struct comm_timer;
@@ -144,8 +146,6 @@ 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;
/** zone has been deleted */
int zone_deleted;
/** deletelist pointer, unused normally except during delete */
@@ -155,10 +155,6 @@ 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;
};
/**
@@ -289,15 +285,6 @@ 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;
};
/**
@@ -346,8 +333,6 @@ 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),
@@ -378,6 +363,8 @@ struct auth_probe {
struct comm_timer* timer;
/** timeout in msec */
int timeout;
/** the tsig data for the packet */
struct tsig_data* tsig;
};
/**
@@ -396,18 +383,12 @@ 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;
/** 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;
@@ -453,6 +434,8 @@ struct auth_transfer {
/** timeout for the transfer.
* on the workers event base. */
struct comm_timer* timer;
/** the tsig data for the transfer */
struct tsig_data* tsig;
};
/** list of addresses */
@@ -484,6 +467,8 @@ struct auth_master {
int ssl;
/** the port number (for urls) */
int port;
/** the tsig key name (if any, or NULL) */
char* tsig_key_name;
/** if the host is a hostname, the list of resolved addrs, if any*/
struct auth_addr* list;
};
@@ -513,11 +498,13 @@ struct auth_zones* auth_zones_create(void);
* @param is_rpz: set to 1 if at least one RPZ zone is configured.
* @param env: environment for offline verification.
* @param mods: modules in environment.
* @param tsig_key_table: tsig key table to check if tsig keys exist.
* If NULL, no check is performed.
* @return false on failure.
*/
int auth_zones_apply_cfg(struct auth_zones* az, struct config_file* cfg,
int setup, int* is_rpz, struct module_env* env,
struct module_stack* mods);
struct module_stack* mods, struct tsig_key_table* tsig_key_table);
/** initial pick up of worker timeouts, ties events to worker event loop
* @param az: auth zones structure
@@ -642,13 +629,19 @@ int auth_zones_can_fallback(struct auth_zones* az, uint8_t* nm, size_t nmlen,
* @param has_serial: if true, the notify has a serial attached.
* @param serial: the serial number, if has_serial is true.
* @param refused: is set to true on failure to note refused access.
* @param pkt: the packet for TSIG verify.
* @param tsig: if TSIG, the structure is returned here, allocated in
* the worker scratch region.
* @param tsig_rcode: if not NOERROR it is the TSIG error code, TSIG failed.
* @param scratchpad: region to allocate tsig in.
* @return fail on failures (refused is false) and when access is
* denied (refused is true). True when processed.
*/
int auth_zones_notify(struct auth_zones* az, struct module_env* env,
uint8_t* nm, size_t nmlen, uint16_t dclass,
struct sockaddr_storage* addr, socklen_t addrlen, int has_serial,
uint32_t serial, int* refused);
uint32_t serial, int* refused, struct sldns_buffer* pkt,
struct tsig_data** tsig, int* tsig_rcode, struct regional* scratchpad);
/** process notify packet and read serial number from SOA.
* returns 0 if no soa record in the notify */
@@ -694,10 +687,12 @@ struct auth_xfer* auth_xfer_create(struct auth_zones* az, struct auth_zone* z);
* @param list: pointer to start of list. The malloced list is returned here.
* @param c: the config items to copy over.
* @param with_http: if true, http urls are also included, before the masters.
* @param tsig_key_table: if nonNULL, used to check that tsig keys exist in
* the key table.
* @return false on failure.
*/
int xfer_set_masters(struct auth_master** list, struct config_auth* c,
int with_http);
int with_http, struct tsig_key_table* tsig_key_table);
/** xfer nextprobe timeout callback, this is part of task_nextprobe */
void auth_xfer_timer(void* arg);
@@ -851,10 +846,4 @@ 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);
#endif /* SERVICES_AUTHZONE_H */
+9 -43
View File
@@ -43,7 +43,6 @@
#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"
@@ -233,15 +232,8 @@ find_closest_of_type(struct module_env* env, uint8_t* qname, size_t qnamelen,
/* snip off front part of qname until the type is found */
while(qnamelen > 0) {
rrset = rrset_cache_lookup(env->rrset_cache, qname,
qnamelen, searchtype, qclass, 0, now, 0);
if(!rrset && searchtype == LDNS_RR_TYPE_DNAME)
/* If not found, for type DNAME, try 0TTL stored,
* for its grace period. */
rrset = rrset_cache_lookup(env->rrset_cache, qname,
qnamelen, searchtype, qclass,
PACKED_RRSET_UPSTREAM_0TTL, now, 0);
if(rrset) {
if((rrset = rrset_cache_lookup(env->rrset_cache, qname,
qnamelen, searchtype, qclass, 0, now, 0))) {
uint8_t* origqname = qname;
size_t origqnamelen = qnamelen;
if(!noexpiredabove)
@@ -278,8 +270,6 @@ find_closest_of_type(struct module_env* env, uint8_t* qname, size_t qnamelen,
/* snip off front label */
lablen = *qname;
if(lablen == 0)
break;
qname += lablen + 1;
qnamelen -= lablen + 1;
}
@@ -587,12 +577,8 @@ dns_cache_find_delegation(struct module_env* env, uint8_t* qname,
return NULL;
}
}
if(!delegpt_rrset_add_ns(dp, region, nskey, 0,
deleg_port_number(env))) {
lock_rw_unlock(&nskey->entry.lock);
if(!delegpt_rrset_add_ns(dp, region, nskey, 0))
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)
@@ -719,16 +705,10 @@ struct dns_msg*
dns_msg_deepcopy_region(struct dns_msg* origin, struct regional* region)
{
size_t i;
struct ub_packed_rrset_key** saved_rrsets;
struct dns_msg* res = NULL;
size_t rep_alloc_size = sizeof(struct reply_info)
- sizeof(struct rrset_ref); /* this is the size of res->rep
allocated in gen_dns_msg() */
res = gen_dns_msg(region, &origin->qinfo, origin->rep->rrset_count);
if(!res) return NULL;
saved_rrsets = res->rep->rrsets; /* save rrsets alloc by gen_dns_msg */
memcpy(res->rep, origin->rep, rep_alloc_size);
res->rep->rrsets = saved_rrsets;
*res->rep = *origin->rep;
if(origin->rep->reason_bogus_str) {
res->rep->reason_bogus_str = regional_strdup(region,
origin->rep->reason_bogus_str);
@@ -786,20 +766,8 @@ synth_dname_msg(struct ub_packed_rrset_key* rrset, struct regional* region,
rrset->entry.data;
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;
}
if(TTL_IS_EXPIRED(d->ttl, now))
return NULL;
/* only allow validated (with DNSSEC) DNAMEs used from cache
* for insecure DNAMEs, query again. */
*sec_status = d->security;
@@ -811,7 +779,7 @@ synth_dname_msg(struct ub_packed_rrset_key* rrset, struct regional* region,
msg->rep->flags = BIT_QR; /* reply, no AA, no error */
msg->rep->authoritative = 0; /* reply stored in cache can't be authoritative */
msg->rep->qdcount = 1;
msg->rep->ttl = rr_ttl;
msg->rep->ttl = d->ttl - now;
msg->rep->prefetch_ttl = PREFETCH_TTL_CALC(msg->rep->ttl);
msg->rep->serve_expired_ttl = msg->rep->ttl + SERVE_EXPIRED_TTL;
msg->rep->serve_expired_norec_ttl = 0;
@@ -824,8 +792,6 @@ 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)
@@ -865,7 +831,7 @@ synth_dname_msg(struct ub_packed_rrset_key* rrset, struct regional* region,
if(!newd)
return NULL;
ck->entry.data = newd;
newd->ttl = rr_ttl; /* RFC6672: synth CNAME TTL == DNAME TTL */
newd->ttl = d->ttl - now; /* RFC6672: synth CNAME TTL == DNAME TTL */
newd->count = 1;
newd->rrsig_count = 0;
newd->trust = rrset_trust_ans_noAA;
@@ -1079,7 +1045,7 @@ dns_cache_lookup(struct module_env* env,
if(env->cfg->harden_below_nxdomain) {
while(!dname_is_root(k.qname)) {
if(dpname && dpnamelen
&& !dname_strict_subdomain_c(k.qname, dpname))
&& !dname_subdomain_c(k.qname, dpname))
break; /* no synth nxdomain above the stub */
dname_remove_label(&k.qname, &k.qname_len);
h = query_info_hash(&k, flags);
+10 -81
View File
@@ -50,7 +50,6 @@
#include "util/regional.h"
#include "util/alloc.h"
#include "util/net_help.h"
#include "validator/val_utils.h"
void
rrset_markdel(void* key)
@@ -127,8 +126,7 @@ rrset_cache_touch(struct rrset_cache* r, struct ub_packed_rrset_key* key,
/** see if rrset needs to be updated in the cache */
static int
need_to_update_rrset(void* nd, void* cd, time_t timenow, int equal, int ns,
int a_aaaa)
need_to_update_rrset(void* nd, void* cd, time_t timenow, int equal, int ns)
{
struct packed_rrset_data* newd = (struct packed_rrset_data*)nd;
struct packed_rrset_data* cached = (struct packed_rrset_data*)cd;
@@ -151,20 +149,6 @@ need_to_update_rrset(void* nd, void* cd, time_t timenow, int equal, int ns,
if(equal && !TTL_IS_EXPIRED(cached->ttl, timenow) &&
cached->security == sec_status_bogus)
return 0;
/* ghost-domain: never let an NS overwrite extend lifetime
* past the entry it replaces, regardless of trust. */
/* Also for A/AAAA and it is glue. */
if((ns ||
(a_aaaa && cached->trust==rrset_trust_add_noAA))
&& !TTL_IS_EXPIRED(cached->ttl, timenow) &&
newd->ttl > cached->ttl) {
size_t i;
if(a_aaaa) newd->trust=rrset_trust_add_noAA;
newd->ttl = cached->ttl;
for(i=0; i<(newd->count+newd->rrsig_count); i++)
if(newd->rr_ttl[i] > newd->ttl)
newd->rr_ttl[i] = newd->ttl;
}
return 1;
}
/* o item in cache has expired */
@@ -215,13 +199,6 @@ 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
@@ -236,8 +213,7 @@ rrset_cache_update(struct rrset_cache* r, struct rrset_ref* ref,
equal = rrsetdata_equal((struct packed_rrset_data*)k->entry.
data, (struct packed_rrset_data*)e->data);
if(!need_to_update_rrset(k->entry.data, e->data, timenow,
equal, (rrset_type==LDNS_RR_TYPE_NS),
(rrset_type==LDNS_RR_TYPE_A || rrset_type==LDNS_RR_TYPE_AAAA))) {
equal, (rrset_type==LDNS_RR_TYPE_NS))) {
/* cache is superior, return that value */
lock_rw_unlock(&e->lock);
ub_packed_rrset_parsedelete(k, alloc);
@@ -269,45 +245,12 @@ rrset_cache_update(struct rrset_cache* r, struct rrset_ref* ref,
return 0;
}
/** See if the name is a within signer authority */
static int
dname_subdomain_rrsig_signers(uint8_t* dname,
struct ub_packed_rrset_key* rrset)
{
struct packed_rrset_data* d = (struct packed_rrset_data*)
rrset->entry.data;
size_t i;
if(!d || !d->rrsig_count)
return 0;
for(i=0; i<d->rrsig_count; i++) {
uint8_t* sname = NULL;
size_t slen = 0;
rrsig_get_signer(d->rr_data[d->count+i], d->rr_len[d->count+i],
&sname, &slen);
if(!sname || !slen)
return 0; /* malformed */
if(!dname_subdomain_c(dname, sname))
return 0; /* not a subdomain */
}
return 1;
}
void rrset_cache_update_wildcard(struct rrset_cache* rrset_cache,
struct ub_packed_rrset_key* rrset, uint8_t* ce, size_t ce_len,
struct alloc_cache* alloc, time_t timenow)
{
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). */
if(!dname_subdomain_rrsig_signers(ce, rrset)) {
verbose(VERB_ALGO, "wildcard canonical parent outside signer authority");
return;
}
rrset = packed_rrset_copy_alloc(rrset, alloc, timenow);
if(!rrset) {
log_err("malloc failure in rrset_cache_update_wildcard");
@@ -319,16 +262,14 @@ void rrset_cache_update_wildcard(struct rrset_cache* rrset_cache,
wc_dname[1] = (uint8_t)'*';
memmove(wc_dname+2, ce, ce_len);
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);
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);
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;
@@ -337,10 +278,6 @@ void rrset_cache_update_wildcard(struct rrset_cache* rrset_cache,
(void)rrset_cache_update(rrset_cache, &ref, alloc, timenow);
}
/** Grace period in seconds for TTL=0 DNAME rrsets (RFC 2308: do not cache).
* Allows synthesis from cache within this window to reduce recursion load. */
#define DNAME_TTL0_GRACE_SECONDS 1
struct ub_packed_rrset_key*
rrset_cache_lookup(struct rrset_cache* r, uint8_t* qname, size_t qnamelen,
uint16_t qtype, uint16_t qclass, uint32_t flags, time_t timenow,
@@ -363,20 +300,12 @@ rrset_cache_lookup(struct rrset_cache* r, uint8_t* qname, size_t qnamelen,
/* check TTL */
struct packed_rrset_data* data =
(struct packed_rrset_data*)e->data;
struct ub_packed_rrset_key* k = (struct ub_packed_rrset_key*)e->key;
if(TTL_IS_EXPIRED(data->ttl, timenow)) {
/* Allow TTL=0 DNAME within grace period for synthesis */
if(qtype == LDNS_RR_TYPE_DNAME &&
(k->rk.flags & PACKED_RRSET_UPSTREAM_0TTL) &&
(timenow - data->ttl_add) <= DNAME_TTL0_GRACE_SECONDS) {
/* within grace: allow for synthesis */
} else {
lock_rw_unlock(&e->lock);
return NULL;
}
lock_rw_unlock(&e->lock);
return NULL;
}
/* we're done */
return k;
return (struct ub_packed_rrset_key*)e->key;
}
return NULL;
}
+101 -181
View File
@@ -42,6 +42,7 @@
#ifdef HAVE_SYS_TYPES_H
# include <sys/types.h>
#endif
#include <sys/time.h>
#include <limits.h>
#ifdef USE_TCP_FASTOPEN
#include <netinet/tcp.h>
@@ -1125,7 +1126,7 @@ make_sock_port(int stype, const char* ifname, int port,
int use_systemd, int dscp, struct unbound_socket* ub_sock,
const char* additional)
{
const char* s = strchr(ifname, '@');
char* s = strchr(ifname, '@');
if(s) {
/* override port with ifspec@port */
int port;
@@ -1563,7 +1564,7 @@ listen_create(struct comm_base* base, struct listen_port* ports,
cp = comm_point_create_udp(base, ports->fd,
front->udp_buff, ports->pp2_enabled, cb,
cb_arg, ports->socket);
} else if(ports->ftype == listen_type_doq && doq_table) {
} else if(ports->ftype == listen_type_doq) {
#ifndef HAVE_NGTCP2
log_warn("Unbound is not compiled with "
"ngtcp2. This is required to use DNS "
@@ -2166,8 +2167,7 @@ void tcp_req_info_clear(struct tcp_req_info* req)
open = req->open_req_list;
while(open) {
nopen = open->next;
mesh_state_remove_reply(open->mesh, open->mesh_state, req->cp,
NULL, NULL);
mesh_state_remove_reply(open->mesh, open->mesh_state, req->cp);
free(open);
open = nopen;
}
@@ -2300,8 +2300,21 @@ int
tcp_req_info_handle_read_close(struct tcp_req_info* req)
{
verbose(VERB_ALGO, "tcp channel read side closed %d", req->cp->fd);
/* RFC 7766 6.2.4 says to drop pending replies when client closes. */
return 0; /* drop connection */
/* reset byte count for (potential) partial read */
req->cp->tcp_byte_count = 0;
/* if we still have results to write, pick up next and write it */
if(req->num_done_req != 0) {
tcp_req_pickup_next_result(req);
tcp_req_info_setup_listen(req);
return 1;
}
/* if nothing to do, this closes the connection */
if(req->num_open_req == 0 && req->num_done_req == 0)
return 0;
/* otherwise, we must be waiting for dns resolve, wait with timeout */
req->read_is_closed = 1;
tcp_req_info_setup_listen(req);
return 1;
}
void
@@ -2871,7 +2884,6 @@ submit_http_error:
sldns_buffer_flip(h2_stream->qbuffer);
h2_session->postpone_drop = 1;
query_read_done = http2_query_read_done(h2_session, h2_stream);
h2_session->postpone_drop = 0;
if(query_read_done < 0)
return NGHTTP2_ERR_CALLBACK_FAILURE;
else if(!query_read_done) {
@@ -2881,9 +2893,11 @@ submit_http_error:
* failure will result in reclaiming (and closing)
* of comm point. */
verbose(VERB_QUERY, "http2 query dropped in worker cb");
h2_session->postpone_drop = 0;
return NGHTTP2_ERR_CALLBACK_FAILURE;
}
/* nothing to submit right now, query added to mesh. */
h2_session->postpone_drop = 0;
return 0;
}
if(!http2_submit_dns_response(h2_session)) {
@@ -3261,18 +3275,14 @@ nghttp2_session_callbacks* http2_req_callbacks_create(void)
struct doq_table*
doq_table_create(struct config_file* cfg, struct ub_randstate* rnd)
{
struct doq_table* table;
if (!cfg->quic_port)
return NULL;
table = calloc(1, sizeof(*table));
struct doq_table* table = calloc(1, sizeof(*table));
if(!table)
return NULL;
#ifdef USE_NGTCP2_CRYPTO_OSSL
/* Initialize the ossl crypto, it is harmless to call twice,
* and this is before use of doq connections. */
if(ngtcp2_crypto_ossl_init() != 0) {
log_err("ngtcp2_crypto_ossl_init failed");
log_err("ngtcp2_crypto_oss_init failed");
free(table);
return NULL;
}
@@ -3344,7 +3354,7 @@ conn_tree_del(rbnode_type* node, void* arg)
{
struct doq_table* table = (struct doq_table*)arg;
struct doq_conn* conn;
if(!node || !table)
if(!node)
return;
conn = (struct doq_conn*)node->key;
if(conn->timer.timer_in_list) {
@@ -3399,13 +3409,13 @@ doq_table_delete(struct doq_table* table)
}
struct doq_timer*
doq_timer_find_time(struct doq_table* table, ngtcp2_tstamp ts)
doq_timer_find_time(struct doq_table* table, struct timeval* tv)
{
struct doq_timer key;
struct rbnode_type* node;
log_assert(table != NULL);
memset(&key, 0, sizeof(key));
key.time_mono = ts;
key.time.tv_sec = tv->tv_sec;
key.time.tv_usec = tv->tv_usec;
node = rbtree_search(table->timer_tree, &key);
if(node)
return (struct doq_timer*)node->key;
@@ -3453,7 +3463,7 @@ doq_timer_list_remove(struct doq_table* table, struct doq_timer* timer)
if(!timer->timer_in_list)
return;
/* The item in the rbtree has the list start and end. */
rb_timer = doq_timer_find_time(table, timer->time_mono);
rb_timer = doq_timer_find_time(table, &timer->time);
if(rb_timer) {
if(timer->setlist_prev)
timer->setlist_prev->setlist_next = timer->setlist_next;
@@ -3499,8 +3509,7 @@ doq_timer_unset(struct doq_table* table, struct doq_timer* timer)
}
void doq_timer_set(struct doq_table* table, struct doq_timer* timer,
struct doq_server_socket* worker_doq_socket, struct timeval* tv,
ngtcp2_tstamp ts)
struct doq_server_socket* worker_doq_socket, struct timeval* tv)
{
struct doq_timer* rb_timer;
if(verbosity >= VERB_ALGO && timer->conn) {
@@ -3514,14 +3523,14 @@ void doq_timer_set(struct doq_table* table, struct doq_timer* timer,
(int)rel.tv_sec, (int)rel.tv_usec);
}
if(timer->timer_in_tree || timer->timer_in_list) {
if(timer->time_mono == ts)
if(timer->time.tv_sec == tv->tv_sec &&
timer->time.tv_usec == tv->tv_usec)
return; /* already set on that time */
doq_timer_unset(table, timer);
}
timer->time_real.tv_sec = tv->tv_sec;
timer->time_real.tv_usec = tv->tv_usec;
timer->time_mono = ts;
rb_timer = doq_timer_find_time(table, ts);
timer->time.tv_sec = tv->tv_sec;
timer->time.tv_usec = tv->tv_usec;
rb_timer = doq_timer_find_time(table, tv);
if(rb_timer) {
/* There is a timeout already with this value. Timer is
* added to the setlist. */
@@ -3597,29 +3606,15 @@ doq_conn_create(struct comm_point* c, struct doq_pkt_addr* paddr,
return conn;
}
/** The arguments for doq stream tree del. */
struct doq_stream_tree_del_args {
/** The doq table. */
struct doq_table* table;
/** The doq connection for the stream. */
struct doq_conn* conn;
};
/** delete stream tree node */
static void
stream_tree_del(rbnode_type* node, void* arg)
{
struct doq_stream_tree_del_args* args = (struct doq_stream_tree_del_args*)arg;
struct doq_table* table = args->table;
struct doq_table* table = (struct doq_table*)arg;
struct doq_stream* stream;
if(!node)
return;
stream = (struct doq_stream*)node;
if(stream->mesh_state) {
mesh_state_remove_reply(stream->mesh, stream->mesh_state,
args->conn->doq_socket->cp, NULL, stream);
stream->mesh_state = NULL;
}
if(stream->in)
doq_table_quic_size_subtract(table, stream->inlen);
if(stream->out)
@@ -3639,14 +3634,9 @@ 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. */
if(conn->ssl)
SSL_set_app_data(conn->ssl, NULL);
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));
args.table = table;
args.conn = conn;
traverse_postorder(&conn->stream_tree, stream_tree_del, &args);
traverse_postorder(&conn->stream_tree, stream_tree_del, table);
}
free(conn->key.dcid);
SSL_free(conn->ssl);
@@ -3719,9 +3709,13 @@ int doq_timer_cmp(const void* key1, const void* key2)
{
struct doq_timer* e = (struct doq_timer*)key1;
struct doq_timer* f = (struct doq_timer*)key2;
if(e->time_mono < f->time_mono)
if(e->time.tv_sec < f->time.tv_sec)
return -1;
if(e->time_mono > f->time_mono)
if(e->time.tv_sec > f->time.tv_sec)
return 1;
if(e->time.tv_usec < f->time.tv_usec)
return -1;
if(e->time.tv_usec > f->time.tv_usec)
return 1;
return 0;
}
@@ -3782,7 +3776,7 @@ doq_repinfo_retrieve_localaddr(struct comm_reply* repinfo,
memset(sa6, 0, *localaddrlen);
sa6->sin6_family = AF_INET6;
memmove(&sa6->sin6_addr, &repinfo->pktinfo.v6info.ipi6_addr,
sizeof(struct in6_addr));
*localaddrlen);
sa6->sin6_port = repinfo->doq_srcport;
#endif
} else {
@@ -3792,7 +3786,7 @@ doq_repinfo_retrieve_localaddr(struct comm_reply* repinfo,
memset(sa, 0, *localaddrlen);
sa->sin_family = AF_INET;
memmove(&sa->sin_addr, &repinfo->pktinfo.v4info.ipi_addr,
sizeof(struct in_addr));
*localaddrlen);
sa->sin_port = repinfo->doq_srcport;
#elif defined(IP_RECVDSTADDR)
struct sockaddr_in* sa = (struct sockaddr_in*)localaddr;
@@ -3955,11 +3949,6 @@ doq_stream_close(struct doq_conn* conn, struct doq_stream* stream,
if(stream->is_closed)
return 1;
stream->is_closed = 1;
if(stream->mesh_state) {
mesh_state_remove_reply(stream->mesh, stream->mesh_state,
conn->doq_socket->cp, NULL, stream);
stream->mesh_state = NULL;
}
doq_stream_off_write_list(conn, stream);
if(send_shutdown) {
verbose(VERB_ALGO, "doq: shutdown stream_id %d with app_error_code %d",
@@ -3989,8 +3978,7 @@ doq_stream_close(struct doq_conn* conn, struct doq_stream* stream,
/** doq stream pick up answer data from buffer */
static int
doq_stream_pickup_answer(struct doq_conn* conn, struct doq_stream* stream,
struct sldns_buffer* buf)
doq_stream_pickup_answer(struct doq_stream* stream, struct sldns_buffer* buf)
{
stream->is_answer_available = 1;
if(stream->out) {
@@ -4000,11 +3988,6 @@ doq_stream_pickup_answer(struct doq_conn* conn, struct doq_stream* stream,
}
stream->nwrite = 0;
stream->outlen = sldns_buffer_limit(buf);
if(!doq_table_quic_size_available(conn->doq_socket->table,
conn->doq_socket->cfg, stream->outlen)) {
verbose(VERB_ALGO, "doq stream: no space for reply length");
return 0;
}
/* For quic the output bytes have to stay allocated and available,
* for potential resends, until the remote end has acknowledged them.
* This includes the tcplen start uint16_t, in outlen_wire. */
@@ -4031,56 +4014,24 @@ doq_stream_send_reply(struct doq_conn* conn, struct doq_stream* stream,
if(stream->out)
doq_table_quic_size_subtract(conn->doq_socket->table,
stream->outlen);
if(!doq_stream_pickup_answer(conn, stream, buf))
if(!doq_stream_pickup_answer(stream, buf))
return 0;
doq_table_quic_size_add(conn->doq_socket->table, stream->outlen);
doq_stream_on_write_list(conn, stream);
doq_conn_write_enable(conn);
return 1;
}
#endif /* HAVE_NGTCP2 */
void
doq_stream_add_meshstate(struct doq_stream* stream,
struct mesh_area* mesh, struct mesh_state* m)
{
#ifdef HAVE_NGTCP2
stream->mesh = mesh;
stream->mesh_state = m;
#else
(void)stream; (void)mesh; (void)m;
#endif
}
void
doq_stream_remove_mesh_state(struct doq_stream* stream)
{
#ifdef HAVE_NGTCP2
if(!stream)
return;
stream->mesh_state = NULL;
#else
(void)stream;
#endif
}
#ifdef HAVE_NGTCP2
/** doq stream data length has completed, allocations can be done. False on
* allocation failure. */
static int
doq_stream_datalen_complete(struct doq_conn* conn, struct doq_stream* stream,
struct doq_table* table)
doq_stream_datalen_complete(struct doq_stream* stream, struct doq_table* table)
{
if(stream->inlen > 1024*1024) {
log_err("doq stream in length too large %d",
(int)stream->inlen);
return 0;
}
if(!doq_table_quic_size_available(table, conn->doq_socket->cfg,
stream->inlen)) {
verbose(VERB_ALGO, "doq stream: no space for query length");
return 0;
}
stream->in = calloc(1, stream->inlen);
if(!stream->in) {
log_err("doq could not read stream, calloc failed: "
@@ -4125,7 +4076,6 @@ doq_stream_data_complete(struct doq_conn* conn, struct doq_stream* stream)
return 0;
}
c->repinfo.doq_streamid = stream->stream_id;
c->repinfo.doq_stream = stream;
conn->doq_socket->current_conn = conn;
fptr_ok(fptr_whitelist_comm_point(c->callback));
if( (*c->callback)(c, c->cb_arg, NETEVENT_NOERROR, &c->repinfo)) {
@@ -4142,9 +4092,8 @@ doq_stream_data_complete(struct doq_conn* conn, struct doq_stream* stream)
/** doq receive data for a stream, more bytes of the incoming data */
static int
doq_stream_recv_data(struct doq_conn* conn, struct doq_stream* stream,
const uint8_t* data, size_t datalen, int* recv_done,
struct doq_table* table)
doq_stream_recv_data(struct doq_stream* stream, const uint8_t* data,
size_t datalen, int* recv_done, struct doq_table* table)
{
int got_data = 0;
/* read the tcplength uint16_t at the start */
@@ -4165,7 +4114,7 @@ doq_stream_recv_data(struct doq_conn* conn, struct doq_stream* stream,
if(stream->nread == 2) {
/* the initial length value is completed */
stream->inlen = ntohs(tcplen);
if(!doq_stream_datalen_complete(conn, stream, table))
if(!doq_stream_datalen_complete(stream, table))
return 0;
} else {
/* store for later */
@@ -4314,11 +4263,12 @@ doq_submit_new_token(struct doq_conn* conn)
ngtcp2_ssize tokenlen;
int ret;
const ngtcp2_path* path = ngtcp2_conn_get_path(conn->conn);
ngtcp2_tstamp ts = doq_get_timestamp_nanosec();
tokenlen = ngtcp2_crypto_generate_regular_token(token,
conn->doq_socket->static_secret,
conn->doq_socket->static_secret_len, path->remote.addr,
path->remote.addrlen, doq_get_timestamp_nanosec());
path->remote.addrlen, ts);
if(tokenlen < 0) {
log_err("doq ngtcp2_crypto_generate_regular_token failed");
return 1;
@@ -4381,7 +4331,8 @@ doq_stream_open_cb(ngtcp2_conn* ATTR_UNUSED(conn), int64_t stream_id,
verbose(VERB_ALGO, "doq: stream with this id already exists");
return 0;
}
if(!doq_table_quic_size_available(doq_conn->doq_socket->table,
if(stream_id != 0 && stream_id != 4 && /* allow one stream on a new connection */
!doq_table_quic_size_available(doq_conn->doq_socket->table,
doq_conn->doq_socket->cfg, sizeof(*stream)
+ 100 /* estimated query in */
+ 512 /* estimated response out */
@@ -4439,8 +4390,8 @@ doq_recv_stream_data_cb(ngtcp2_conn* ATTR_UNUSED(conn), uint32_t flags,
return 0;
}
if(datalen != 0) {
if(!doq_stream_recv_data(doq_conn, stream, data, datalen,
&recv_done, doq_conn->doq_socket->table))
if(!doq_stream_recv_data(stream, data, datalen, &recv_done,
doq_conn->doq_socket->table))
return NGTCP2_ERR_CALLBACK_FAILURE;
}
if((flags&NGTCP2_STREAM_DATA_FLAG_FIN)!=0) {
@@ -4509,29 +4460,6 @@ doq_stream_reset_cb(ngtcp2_conn* ATTR_UNUSED(conn), int64_t stream_id,
return 0;
}
/** ngtcp2 extend_max_stream_data function */
int doq_extend_max_stream_data_cb(ngtcp2_conn* ATTR_UNUSED(conn),
int64_t stream_id, uint64_t max_data, void* user_data,
void* ATTR_UNUSED(stream_user_data))
{
struct doq_conn* doq_conn = (struct doq_conn*)user_data;
struct doq_stream* stream;
verbose(VERB_ALGO, "doq extend_max_stream_data stream id %d "
"max_data %d ", (int)stream_id, (int)max_data);
if(max_data == 0)
return 0;
stream = doq_stream_find(doq_conn, stream_id);
if(!stream) {
verbose(VERB_ALGO, "doq: unknown stream %d", (int)stream_id);
return 0;
}
if(!stream->is_answer_available)
return 0;
doq_stream_on_write_list(doq_conn, stream);
doq_conn_write_enable(doq_conn);
return 0;
}
/** ngtcp2 acked_stream_data_offset callback function */
static int
doq_acked_stream_data_offset_cb(ngtcp2_conn* ATTR_UNUSED(conn),
@@ -4852,7 +4780,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 HAVE_SSL_SET_QUIC_TLS_EARLY_DATA_ENABLED
#ifdef USE_NGTCP2_CRYPTO_OSSL
SSL_set_quic_tls_early_data_enabled(ssl, 1);
#else
SSL_set_quic_early_data_enabled(ssl, 1);
@@ -4906,7 +4834,6 @@ doq_conn_setup(struct doq_conn* conn, uint8_t* scid, size_t scidlen,
callbacks.stream_open = doq_stream_open_cb;
callbacks.stream_close = doq_stream_close_cb;
callbacks.stream_reset = doq_stream_reset_cb;
callbacks.extend_max_stream_data = doq_extend_max_stream_data_cb;
callbacks.acked_stream_data_offset = doq_acked_stream_data_offset_cb;
callbacks.recv_stream_data = doq_recv_stream_data_cb;
@@ -4961,7 +4888,6 @@ 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, &params, 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));
@@ -4996,7 +4922,6 @@ doq_conid_find(struct doq_table* table, const uint8_t* data, size_t datalen)
key.node.key = &key;
key.cid = (void*)data;
key.cidlen = datalen;
log_assert(table != NULL);
node = rbtree_search(table->conid_tree, &key);
if(node)
return (struct doq_conid*)node->key;
@@ -5184,30 +5109,23 @@ doq_conn_clear_conids(struct doq_conn* conn)
ngtcp2_tstamp doq_get_timestamp_nanosec(void)
{
#ifdef CLOCK_REALTIME
struct timespec tp;
memset(&tp, 0, sizeof(tp));
#ifdef CLOCK_BOOTTIME
if(clock_gettime(CLOCK_BOOTTIME, &tp) == -1) {
#endif
if(clock_gettime(CLOCK_MONOTONIC, &tp) == -1) {
log_err("clock_gettime failed: %s", strerror(errno));
}
#ifdef CLOCK_BOOTTIME
/* Get a nanosecond time, that can be compared with the event base. */
if(clock_gettime(CLOCK_REALTIME, &tp) == -1) {
log_err("clock_gettime failed: %s", strerror(errno));
}
#endif
return ((uint64_t)tp.tv_sec)*((uint64_t)1000000000) +
((uint64_t)tp.tv_nsec);
}
static struct timeval doq_get_timevalue(void)
{
#else
struct timeval tv;
memset(&tv, 0, sizeof(tv));
if(gettimeofday(&tv, NULL) < 0) {
log_err("gettimeofday failed: %s", strerror(errno));
memset(&tv, 0, sizeof(tv));
}
return tv;
return ((uint64_t)tv.tv_sec)*((uint64_t)1000000000) +
((uint64_t)tv.tv_usec)*((uint64_t)1000);
#endif /* CLOCK_REALTIME */
}
/** doq start the closing period for the connection. */
@@ -5330,17 +5248,18 @@ doq_conn_recv(struct comm_point* c, struct doq_pkt_addr* paddr,
int* err_drop)
{
int ret;
ngtcp2_tstamp ts;
struct ngtcp2_path path;
memset(&path, 0, sizeof(path));
path.remote.addr = (struct sockaddr*)&paddr->addr;
path.remote.addrlen = paddr->addrlen;
path.local.addr = (struct sockaddr*)&paddr->localaddr;
path.local.addrlen = paddr->localaddrlen;
ts = doq_get_timestamp_nanosec();
ret = ngtcp2_conn_read_pkt(conn->conn, &path, pi,
sldns_buffer_begin(c->doq_socket->pkt_buf),
sldns_buffer_limit(c->doq_socket->pkt_buf),
doq_get_timestamp_nanosec());
sldns_buffer_limit(c->doq_socket->pkt_buf), ts);
if(ret != 0) {
if(err_retry)
*err_retry = 0;
@@ -5428,6 +5347,7 @@ doq_conn_write_streams(struct comm_point* c, struct doq_conn* conn,
{
struct doq_stream* stream = conn->stream_write_first;
ngtcp2_path_storage ps;
ngtcp2_tstamp ts = doq_get_timestamp_nanosec();
size_t num_packets = 0, max_packets = 65535;
ngtcp2_path_storage_zero(&ps);
@@ -5480,8 +5400,7 @@ doq_conn_write_streams(struct comm_point* c, struct doq_conn* conn,
ret = ngtcp2_conn_writev_stream(conn->conn, &ps.path, &pi,
sldns_buffer_begin(c->doq_socket->pkt_buf),
sldns_buffer_remaining(c->doq_socket->pkt_buf),
&ndatalen, flags, stream_id, datav, datav_count,
doq_get_timestamp_nanosec());
&ndatalen, flags, stream_id, datav, datav_count, ts);
if(ret < 0) {
if(ret == NGTCP2_ERR_WRITE_MORE) {
verbose(VERB_ALGO, "doq: write more, ndatalen %d", (int)ndatalen);
@@ -5496,20 +5415,26 @@ doq_conn_write_streams(struct comm_point* c, struct doq_conn* conn,
continue;
} else if(ret == NGTCP2_ERR_STREAM_DATA_BLOCKED) {
verbose(VERB_ALGO, "doq: ngtcp2_conn_writev_stream returned NGTCP2_ERR_STREAM_DATA_BLOCKED");
if(stream) {
doq_stream_off_write_list(conn, stream);
stream = stream->write_next;
continue;
} else {
break;
#ifdef HAVE_NGTCP2_CCERR_DEFAULT
ngtcp2_ccerr_set_application_error(
&conn->ccerr, -1, NULL, 0);
#else
ngtcp2_connection_close_error_set_application_error(&conn->last_error, -1, NULL, 0);
#endif
if(err_drop)
*err_drop = 0;
if(!doq_conn_close_error(c, conn)) {
if(err_drop)
*err_drop = 1;
}
return 0;
} else if(ret == NGTCP2_ERR_STREAM_SHUT_WR) {
verbose(VERB_ALGO, "doq: ngtcp2_conn_writev_stream returned NGTCP2_ERR_STREAM_SHUT_WR");
#ifdef HAVE_NGTCP2_CCERR_DEFAULT
ngtcp2_ccerr_set_application_error(
&conn->ccerr, DOQ_APP_ERROR_CODE, NULL, 0);
&conn->ccerr, -1, NULL, 0);
#else
ngtcp2_connection_close_error_set_application_error(&conn->last_error, DOQ_APP_ERROR_CODE, NULL, 0);
ngtcp2_connection_close_error_set_application_error(&conn->last_error, -1, NULL, 0);
#endif
if(err_drop)
*err_drop = 0;
@@ -5547,8 +5472,7 @@ doq_conn_write_streams(struct comm_point* c, struct doq_conn* conn,
if(ret == 0) {
/* congestion limited */
doq_conn_write_disable(conn);
ngtcp2_conn_update_pkt_tx_time(conn->conn,
doq_get_timestamp_nanosec());
ngtcp2_conn_update_pkt_tx_time(conn->conn, ts);
return 1;
}
sldns_buffer_set_position(c->doq_socket->pkt_buf, ret);
@@ -5562,7 +5486,7 @@ doq_conn_write_streams(struct comm_point* c, struct doq_conn* conn,
if(stream)
stream = stream->write_next;
}
ngtcp2_conn_update_pkt_tx_time(conn->conn, doq_get_timestamp_nanosec());
ngtcp2_conn_update_pkt_tx_time(conn->conn, ts);
return 1;
}
@@ -5639,35 +5563,32 @@ doq_table_pop_first(struct doq_table* table)
}
int
doq_conn_check_timer(struct doq_conn* conn, struct timeval* tv, ngtcp2_tstamp* ts)
doq_conn_check_timer(struct doq_conn* conn, struct timeval* tv)
{
ngtcp2_tstamp doq_expiry = ngtcp2_conn_get_expiry(conn->conn);
ngtcp2_tstamp doq_now = doq_get_timestamp_nanosec();
ngtcp2_tstamp expiry = ngtcp2_conn_get_expiry(conn->conn);
ngtcp2_tstamp now = doq_get_timestamp_nanosec();
ngtcp2_tstamp t;
struct timeval now = doq_get_timevalue();
if(doq_expiry <= doq_now || doq_expiry == UINT64_MAX) {
/* UINT64_MAX means there is no next expiry. */
if(expiry <= now) {
/* The timer has already expired, add with zero timeout.
* This should call the callback straight away. Calling it
* from the event callbacks is cleaner than calling it here,
* because then it is always called with the same locks and
* so on. This routine only has the conn.lock. */
t = doq_now;
memcpy(tv, &now, sizeof(*tv));
t = now;
} else {
t = doq_expiry;
memset(tv, 0, sizeof(*tv));
tv->tv_sec = (doq_expiry - doq_now) / NGTCP2_SECONDS;
tv->tv_usec = ((doq_expiry - doq_now) / NGTCP2_MICROSECONDS)%1000000;
timeval_add(tv, &now);
t = expiry;
}
*ts = t;
/* convert to timeval */
memset(tv, 0, sizeof(*tv));
tv->tv_sec = t / NGTCP2_SECONDS;
tv->tv_usec = (t / NGTCP2_MICROSECONDS)%1000000;
/* If we already have a timer, is it the right value? */
if(conn->timer.timer_in_tree || conn->timer.timer_in_list) {
if(conn->timer.time_mono == *ts)
if(conn->timer.time.tv_sec == tv->tv_sec &&
conn->timer.time.tv_usec == tv->tv_usec)
return 0;
}
return 1;
@@ -5688,12 +5609,13 @@ doq_conn_log_line(struct doq_conn* conn, char* s)
int
doq_conn_handle_timeout(struct doq_conn* conn)
{
ngtcp2_tstamp now = doq_get_timestamp_nanosec();
int rv;
if(verbosity >= VERB_ALGO)
doq_conn_log_line(conn, "timeout");
rv = ngtcp2_conn_handle_expiry(conn->conn, doq_get_timestamp_nanosec());
rv = ngtcp2_conn_handle_expiry(conn->conn, now);
if(rv != 0) {
verbose(VERB_ALGO, "ngtcp2_conn_handle_expiry failed: %s",
ngtcp2_strerror(rv));
@@ -5740,8 +5662,6 @@ doq_table_quic_size_available(struct doq_table* table,
struct config_file* cfg, size_t mem)
{
size_t cur;
if (!table)
return 0;
lock_basic_lock(&table->size_lock);
cur = table->current_size;
lock_basic_unlock(&table->size_lock);
+8 -29
View File
@@ -61,8 +61,6 @@ struct config_file;
struct addrinfo;
struct sldns_buffer;
struct tcl_list;
struct mesh_area;
struct mesh_state;
/**
* Listening for queries structure.
@@ -540,11 +538,8 @@ void doq_table_delete(struct doq_table* table);
struct doq_timer {
/** The rbnode in the tree sorted by timeout value. Key this struct. */
struct rbnode_type node;
/** The timeout value. Monotonic value used with ngtcp2.
* This time value is used for the tree operations. */
ngtcp2_tstamp time_mono;
/** The timeout value. Absolute time value. */
struct timeval time_real;
struct timeval time;
/** If the timer is in the time tree, with the node. */
int timer_in_tree;
/** If there are more timers with the exact same timeout value,
@@ -694,11 +689,6 @@ struct doq_stream {
uint8_t* out;
/** if the stream is on the write list */
uint8_t on_write_list;
/** The mesh area and mesh state, set when this stream's query was
* dispatched into the mesh; used to detach the reply on stream close */
struct mesh_area* mesh;
/** the mesh state for the query, is nonNULL when there is one. */
struct mesh_state* mesh_state;
/** the prev and next on the write list, if on the list */
struct doq_stream* write_prev, *write_next;
};
@@ -801,16 +791,7 @@ int doq_stream_close(struct doq_conn* conn, struct doq_stream* stream,
/** send reply for a connection */
int doq_stream_send_reply(struct doq_conn* conn, struct doq_stream* stream,
struct sldns_buffer* buf);
#endif /* HAVE_NGTCP2 */
/** add mesh state to doq stream */
void doq_stream_add_meshstate(struct doq_stream* stream,
struct mesh_area* mesh, struct mesh_state* m);
/** remove mesh state from doq stream */
void doq_stream_remove_mesh_state(struct doq_stream* stream);
#ifdef HAVE_NGTCP2
/** the connection has write interest, wants to write packets */
void doq_conn_write_enable(struct doq_conn* conn);
@@ -832,12 +813,10 @@ struct doq_conn* doq_table_pop_first(struct doq_table* table);
* doq check if the timer for the conn needs to be changed.
* @param conn: connection, caller must hold lock on it.
* @param tv: time value, absolute time, returned.
* @param ts: time stamp, absolute time, returned.
* @return true if timer needs to be set to tv, false if no change is needed
* to the timer. The timer is already set to the right time in that case.
*/
int doq_conn_check_timer(struct doq_conn* conn, struct timeval* tv,
ngtcp2_tstamp* ts);
int doq_conn_check_timer(struct doq_conn* conn, struct timeval* tv);
/** doq remove timer from tree */
void doq_timer_tree_remove(struct doq_table* table, struct doq_timer* timer);
@@ -850,12 +829,11 @@ void doq_timer_unset(struct doq_table* table, struct doq_timer* timer);
/** doq set the timer and add it. */
void doq_timer_set(struct doq_table* table, struct doq_timer* timer,
struct doq_server_socket* worker_doq_socket, struct timeval* tv,
ngtcp2_tstamp ts);
struct doq_server_socket* worker_doq_socket, struct timeval* tv);
/** doq find a timeout in the timer tree */
struct doq_timer* doq_timer_find_time(struct doq_table* table,
ngtcp2_tstamp ts);
struct timeval* tv);
/** doq handle timeout for a connection. Pass conn locked. Returns false for
* deletion. */
@@ -873,9 +851,6 @@ int doq_table_quic_size_available(struct doq_table* table,
/** doq get the quic size value */
size_t doq_table_quic_size_get(struct doq_table* table);
/** get a timestamp in nanoseconds */
ngtcp2_tstamp doq_get_timestamp_nanosec(void);
#endif /* HAVE_NGTCP2 */
char* set_ip_dscp(int socket, int addrfamily, int ds);
@@ -891,4 +866,8 @@ void doq_client_event_cb(int fd, short event, void* arg);
/** timer event callback for testcode/doqclient */
void doq_client_timer_cb(int fd, short event, void* arg);
#ifdef HAVE_NGTCP2
/** get a timestamp in nanoseconds */
ngtcp2_tstamp doq_get_timestamp_nanosec(void);
#endif
#endif /* LISTEN_DNSPORT_H */
+85 -161
View File
@@ -56,24 +56,6 @@
* with 16 bytes for an A record, a 64K packet has about 4000 max */
#define LOCALZONE_RRSET_COUNT_MAX 4096
static const char* default_zones_reverse_array[] = {
"127.in-addr.arpa.", /* reverse ip4 zone */
"1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa.", /* reverse ip6 zone */
0
};
const char** local_zones_default_reverse = default_zones_reverse_array;
static const char* default_zones_special_array[] = {
"test.", /* RFC 6761 */
"invalid.", /* RFC 6761 */
"onion.", /* RFC 7686 */
"home.arpa.", /* RFC 8375 */
"resolver.arpa.", /* RFC 9462 */
"service.arpa.", /* RFC 9665 */
0
};
const char** local_zones_default_special = default_zones_special_array;
/** print all RRsets in local zone */
static void
local_zone_out(struct local_zone* z)
@@ -386,6 +368,8 @@ 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) {
@@ -406,8 +390,6 @@ 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,10 +413,6 @@ 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;
}
@@ -450,10 +428,6 @@ 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;
}
@@ -676,12 +650,10 @@ lz_enter_rr_str(struct local_zones* zones, const char* rr)
}
labs = dname_count_size_labels(rr_name, &len);
lock_rw_rdlock(&zones->lock);
z = local_zones_lookup(zones, rr_name, len, labs, rr_class, rr_type, 1);
z = local_zones_lookup(zones, rr_name, len, labs, rr_class, rr_type);
if(!z) {
lock_rw_unlock(&zones->lock);
log_err("internal error: no zone for rr %s", rr);
free(rr_name);
return 0;
fatal_exit("internal error: no zone for rr %s", rr);
}
lock_rw_wrlock(&z->lock);
lock_rw_unlock(&zones->lock);
@@ -862,7 +834,7 @@ lz_nodefault(struct config_file* cfg, const char* name)
for(p = cfg->local_zones_nodefault; p; p = p->next) {
/* compare zone name, lowercase, compare without ending . */
if(strncasecmp(p->str, name, len) == 0 &&
if(strncasecmp(p->str, name, len) == 0 &&
(strlen(p->str) == len || (strlen(p->str)==len+1 &&
p->str[len] == '.')))
return 1;
@@ -870,45 +842,6 @@ lz_nodefault(struct config_file* cfg, const char* name)
return 0;
}
/** enter reverse default zone */
static int
add_reverse_default(struct local_zones* zones, struct config_file* cfg,
const char* name)
{
struct local_zone* z;
char str[1024]; /* known long enough */
if(lz_exists(zones, name) || lz_nodefault(cfg, name))
return 1; /* do not enter default content */
if(!(z=lz_enter_zone(zones, name, "static", LDNS_RR_CLASS_IN)))
return 0;
snprintf(str, sizeof(str), "%s 10800 IN SOA localhost. "
"nobody.invalid. 1 3600 1200 604800 10800", name);
if(!lz_enter_rr_into_zone(z, str)) {
lock_rw_unlock(&z->lock);
return 0;
}
snprintf(str, sizeof(str), "%s 10800 IN NS localhost. ", name);
if(!lz_enter_rr_into_zone(z, str)) {
lock_rw_unlock(&z->lock);
return 0;
}
if(strncasecmp("127.in-addr.arpa.", name, 17) == 0) {
if(!lz_enter_rr_into_zone(z,
"1.0.0.127.in-addr.arpa. 10800 IN PTR localhost.")) {
lock_rw_unlock(&z->lock);
return 0;
}
} else if(strncasecmp("1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa.", name, 73) == 0) {
snprintf(str, sizeof(str), "%s 10800 IN PTR localhost.", name);
if(!lz_enter_rr_into_zone(z, str)) {
lock_rw_unlock(&z->lock);
return 0;
}
}
lock_rw_unlock(&z->lock);
return 1;
}
/** enter (AS112) empty default zone */
static int
add_empty_default(struct local_zones* zones, struct config_file* cfg,
@@ -969,23 +902,72 @@ int local_zone_enter_defaults(struct local_zones* zones, struct config_file* cfg
}
lock_rw_unlock(&z->lock);
}
/* ip4 and ip6 reverse */
for(zstr = local_zones_default_reverse; *zstr; zstr++) {
if(!add_reverse_default(zones, cfg, *zstr)) {
/* reverse ip4 zone */
if(!lz_exists(zones, "127.in-addr.arpa.") &&
!lz_nodefault(cfg, "127.in-addr.arpa.")) {
if(!(z=lz_enter_zone(zones, "127.in-addr.arpa.", "static",
LDNS_RR_CLASS_IN)) ||
!lz_enter_rr_into_zone(z,
"127.in-addr.arpa. 10800 IN NS localhost.") ||
!lz_enter_rr_into_zone(z,
"127.in-addr.arpa. 10800 IN SOA localhost. "
"nobody.invalid. 1 3600 1200 604800 10800") ||
!lz_enter_rr_into_zone(z,
"1.0.0.127.in-addr.arpa. 10800 IN PTR localhost.")) {
log_err("out of memory adding default zone");
if(z) { lock_rw_unlock(&z->lock); }
return 0;
}
lock_rw_unlock(&z->lock);
}
/* special-use zones */
for(zstr = local_zones_default_special; *zstr; zstr++) {
if(!add_empty_default(zones, cfg, *zstr)) {
/* reverse ip6 zone */
if(!lz_exists(zones, "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa.") &&
!lz_nodefault(cfg, "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa.")) {
if(!(z=lz_enter_zone(zones, "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa.", "static",
LDNS_RR_CLASS_IN)) ||
!lz_enter_rr_into_zone(z,
"1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa. 10800 IN NS localhost.") ||
!lz_enter_rr_into_zone(z,
"1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa. 10800 IN SOA localhost. "
"nobody.invalid. 1 3600 1200 604800 10800") ||
!lz_enter_rr_into_zone(z,
"1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa. 10800 IN PTR localhost.")) {
log_err("out of memory adding default zone");
if(z) { lock_rw_unlock(&z->lock); }
return 0;
}
lock_rw_unlock(&z->lock);
}
/* home.arpa. zone (RFC 8375) */
if(!add_empty_default(zones, cfg, "home.arpa.")) {
log_err("out of memory adding default zone");
return 0;
}
/* resolver.arpa. zone (RFC 9462) */
if(!add_empty_default(zones, cfg, "resolver.arpa.")) {
log_err("out of memory adding default zone");
return 0;
}
/* service.arpa. zone (draft-ietf-dnssd-srp-25) */
if(!add_empty_default(zones, cfg, "service.arpa.")) {
log_err("out of memory adding default zone");
return 0;
}
/* onion. zone (RFC 7686) */
if(!add_empty_default(zones, cfg, "onion.")) {
log_err("out of memory adding default zone");
return 0;
}
/* test. zone (RFC 6761) */
if(!add_empty_default(zones, cfg, "test.")) {
log_err("out of memory adding default zone");
return 0;
}
/* invalid. zone (RFC 6761) */
if(!add_empty_default(zones, cfg, "invalid.")) {
log_err("out of memory adding default zone");
return 0;
}
/* block AS112 zones, unless asked not to */
if(!cfg->unblock_lan_zones) {
for(zstr = as112_zones; *zstr; zstr++) {
@@ -1080,15 +1062,14 @@ lz_setup_implicit(struct local_zones* zones, struct config_file* cfg)
labs = dname_count_size_labels(rr_name, &len);
lock_rw_rdlock(&zones->lock);
if(!local_zones_lookup(zones, rr_name, len, labs, rr_class,
rr_type, 1)) {
rr_type)) {
/* Check if there is a zone that this could go
* under but for different class; created zones are
* always for LDNS_RR_CLASS_IN. Create the zone with
* a different class but the same configured
* local_zone_type. */
struct local_zone* z = local_zones_lookup(zones,
rr_name, len, labs, LDNS_RR_CLASS_IN, rr_type,
1);
rr_name, len, labs, LDNS_RR_CLASS_IN, rr_type);
if(z) {
uint8_t* name = memdup(z->name, z->namelen);
size_t znamelen = z->namelen;
@@ -1250,48 +1231,28 @@ local_zones_apply_cfg(struct local_zones* zones, struct config_file* cfg)
struct local_zone*
local_zones_lookup(struct local_zones* zones,
uint8_t* name, size_t len, int labs, uint16_t dclass, uint16_t dtype,
int foradd)
uint8_t* name, size_t len, int labs, uint16_t dclass, uint16_t dtype)
{
return local_zones_tags_lookup(zones, name, len, labs,
dclass, dtype, NULL, 0, 1, foradd);
dclass, dtype, NULL, 0, 1);
}
struct local_zone*
local_zones_tags_lookup(struct local_zones* zones,
uint8_t* name, size_t len, int labs, uint16_t dclass, uint16_t dtype,
uint8_t* taglist, size_t taglen, int ignoretags, int foradd)
uint8_t* taglist, size_t taglen, int ignoretags)
{
rbnode_type* res = NULL;
struct local_zone *result;
struct local_zone key;
int m;
key.node.key = &key;
key.dclass = dclass;
/* for type DS use a zone higher when on a zonecut */
if(dtype == LDNS_RR_TYPE_DS && !dname_is_root(name)) {
/* If this is at a zone cut, of a local-zone, and it is
* of type always_refuse. Then also refuse the type DS
* for it. That could make it DNSSEC bogus, but it is
* REFUSED anyway. It stops CNAME type answers in the
* type DS lookup. */
key.name = name;
key.namelen = len;
key.namelabs = labs;
/* For additions and removals, use the ordinary rule,
* to remove a label for type DS to locate the parent zone.
* That is where the DS RR needs to be put. */
if(!foradd &&
(result=(struct local_zone*)rbtree_search(
&zones->ztree, &key)) != NULL &&
result->type == local_zone_always_refuse) {
/* The type DS does not go up one label. */
return result;
} else {
dname_remove_label(&name, &len);
labs--;
}
dname_remove_label(&name, &len);
labs--;
}
key.node.key = &key;
key.dclass = dclass;
key.name = name;
key.namelen = len;
key.namelabs = labs;
@@ -1510,10 +1471,8 @@ 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) {
qinfo->local_alias = NULL;
if(!qinfo->local_alias->rrset)
return 0; /* out of memory */
}
}
return result;
}
@@ -1579,17 +1538,13 @@ 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) {
qinfo->local_alias = NULL;
if(!qinfo->local_alias->rrset)
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) {
qinfo->local_alias = NULL;
if(!ctargetlen)
return 0; /* invalid cname */
}
if(dname_is_wild(ctarget)) {
/* synthesize cname target */
struct packed_rrset_data* d, *lr_d;
@@ -1618,10 +1573,8 @@ 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) {
qinfo->local_alias = NULL;
if(!d)
return 0; /* out of memory */
}
lr_d = (struct packed_rrset_data*)lr->rrset->entry.data;
qinfo->local_alias->rrset->entry.data = d;
d->ttl = lr_d->rr_ttl[0]; /* RFC6672-like behavior:
@@ -1668,7 +1621,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 || z->type == local_zone_block_aaaa)
if(z->type == local_zone_always_transparent || z->type == local_zone_block_a)
return 1;
if(z->type != local_zone_transparent
&& z->type != local_zone_typetransparent
@@ -1679,9 +1632,7 @@ 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
|| z->type == local_zone_block_a_wdata
|| z->type == local_zone_block_aaaa_wdata)
if(z->type == local_zone_transparent || z->type == local_zone_inform)
return (ld == NULL);
if(ld)
lr = local_data_find_type(ld, qinfo->qtype, 1);
@@ -1747,8 +1698,7 @@ 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 ||
lz_type == local_zone_block_a_wdata) {
} else if(lz_type == local_zone_block_a) {
/* Return NODATA for all A queries */
if(qinfo->qtype == LDNS_RR_TYPE_A) {
local_error_encode(qinfo, env, edns, repinfo, buf, temp,
@@ -1757,17 +1707,6 @@ 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,
@@ -1924,7 +1863,7 @@ local_zones_answer(struct local_zones* zones, struct module_env* env,
if(view->local_zones &&
(z = local_zones_lookup(view->local_zones,
qinfo->qname, qinfo->qname_len, labs,
qinfo->qclass, qinfo->qtype, 0))) {
qinfo->qclass, qinfo->qtype))) {
lock_rw_rdlock(&z->lock);
lzt = z->type;
}
@@ -1936,10 +1875,7 @@ 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_aaaa ||
lzt == local_zone_block_a_wdata ||
lzt == local_zone_block_aaaa_wdata) &&
lzt == local_zone_block_a) &&
local_zone_does_not_cover(z, qinfo, labs)) {
lock_rw_unlock(&z->lock);
z = NULL;
@@ -1961,7 +1897,7 @@ local_zones_answer(struct local_zones* zones, struct module_env* env,
lock_rw_rdlock(&zones->lock);
if(!(z = local_zones_tags_lookup(zones, qinfo->qname,
qinfo->qname_len, labs, qinfo->qclass, qinfo->qtype,
taglist, taglen, 0, 0))) {
taglist, taglen, 0))) {
lock_rw_unlock(&zones->lock);
return 0;
}
@@ -1988,7 +1924,6 @@ 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
@@ -2020,9 +1955,6 @@ 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";
@@ -2059,12 +1991,6 @@ 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)
@@ -2176,8 +2102,7 @@ local_zones_add_RR(struct local_zones* zones, const char* rr)
/* could first try readlock then get writelock if zone does not exist,
* but we do not add enough RRs (from multiple threads) to optimize */
lock_rw_wrlock(&zones->lock);
z = local_zones_lookup(zones, rr_name, len, labs, rr_class, rr_type,
1);
z = local_zones_lookup(zones, rr_name, len, labs, rr_class, rr_type);
if(!z) {
z = local_zones_add_zone(zones, rr_name, len, labs, rr_class,
local_zone_transparent);
@@ -2255,8 +2180,7 @@ void local_zones_del_data(struct local_zones* zones,
/* remove DS */
lock_rw_rdlock(&zones->lock);
z = local_zones_lookup(zones, name, len, labs, dclass, LDNS_RR_TYPE_DS,
1);
z = local_zones_lookup(zones, name, len, labs, dclass, LDNS_RR_TYPE_DS);
if(z) {
lock_rw_wrlock(&z->lock);
d = local_zone_find_data(z, name, len, labs);
@@ -2270,7 +2194,7 @@ void local_zones_del_data(struct local_zones* zones,
/* remove other types */
lock_rw_rdlock(&zones->lock);
z = local_zones_lookup(zones, name, len, labs, dclass, 0, 1);
z = local_zones_lookup(zones, name, len, labs, dclass, 0);
if(!z) {
/* no such zone, we're done */
lock_rw_unlock(&zones->lock);
+3 -17
View File
@@ -57,9 +57,6 @@ struct sldns_buffer;
struct comm_reply;
struct config_strlist;
extern const char** local_zones_default_special;
extern const char** local_zones_default_reverse;
/**
* Local zone type
* This type determines processing for queries that did not match
@@ -93,12 +90,6 @@ 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 */
@@ -271,13 +262,11 @@ void local_zone_delete(struct local_zone* z);
* @param taglen: length of taglist.
* @param ignoretags: lookup zone by name and class, regardless the
* local-zone's tags.
* @param foradd: if the lookup is for addition or removal of the type.
* Used for type DS. The lookup for answers turns this off.
* @return closest local_zone or NULL if no covering zone is found.
*/
struct local_zone* local_zones_tags_lookup(struct local_zones* zones,
uint8_t* name, size_t len, int labs, uint16_t dclass, uint16_t dtype,
uint8_t* taglist, size_t taglen, int ignoretags, int foradd);
uint8_t* taglist, size_t taglen, int ignoretags);
/**
* Lookup zone that contains the given name, class.
@@ -289,13 +278,10 @@ struct local_zone* local_zones_tags_lookup(struct local_zones* zones,
* @param dclass: class to lookup.
* @param dtype: type of the record, if type DS then a zone higher up is found
* pass 0 to just plain find a zone for a name.
* @param foradd: if the lookup is for addition or removal of the type.
* Used for type DS. The lookup for answers turns this off.
* @return closest local_zone or NULL if no covering zone is found.
*/
struct local_zone* local_zones_lookup(struct local_zones* zones,
uint8_t* name, size_t len, int labs, uint16_t dclass, uint16_t dtype,
int foradd);
uint8_t* name, size_t len, int labs, uint16_t dclass, uint16_t dtype);
/**
* Debug helper. Print all zones
@@ -579,7 +565,7 @@ enum respip_action {
respip_always_nxdomain = local_zone_always_nxdomain,
/** answer with nodata response */
respip_always_nodata = local_zone_always_nodata,
/** drop query */
/** answer with nodata response */
respip_always_deny = local_zone_always_deny,
/** RPZ: truncate answer in order to force switch to tcp */
respip_truncate = local_zone_truncate,
+135 -214
View File
@@ -45,6 +45,7 @@
#include "config.h"
#include "services/mesh.h"
#include "services/outbound_list.h"
#include "services/outside_network.h"
#include "services/cache/dns.h"
#include "services/cache/rrset.h"
#include "services/cache/infra.h"
@@ -58,6 +59,7 @@
#include "util/alloc.h"
#include "util/config_file.h"
#include "util/edns.h"
#include "sldns/parseutil.h"
#include "sldns/sbuffer.h"
#include "sldns/wire2str.h"
#include "services/localzone.h"
@@ -65,6 +67,8 @@
#include "respip/respip.h"
#include "services/listen_dnsport.h"
#include "util/timeval_func.h"
#include "util/allow_response_list.h"
#include "util/tsig.h"
#ifdef CLIENT_SUBNET
#include "edns-subnet/subnetmod.h"
@@ -231,7 +235,6 @@ mesh_create(struct module_stack* stack, struct module_env* env)
mesh->ans_expired = 0;
mesh->ans_cachedb = 0;
mesh->num_queries_discard_timeout = 0;
mesh->num_queries_replyaddr_limit = 0;
mesh->num_queries_wait_limit = 0;
mesh->num_dns_error_reports = 0;
mesh->max_reply_states = env->cfg->num_queries_per_thread;
@@ -297,14 +300,12 @@ int mesh_make_new_space(struct mesh_area* mesh, sldns_buffer* qbuf)
if(mesh->num_reply_states < mesh->max_reply_states)
return 1;
/* try to kick out a jostle-list item */
if(m && m->list_select == mesh_jostle_list) {
if(m && m->reply_list && m->list_select == mesh_jostle_list) {
/* how old is it? */
struct timeval age;
if(m->has_first_reply_time)
timeval_subtract(&age, mesh->env->now_tv,
&m->first_reply_time);
if(!m->has_first_reply_time ||
timeval_smaller(&mesh->jostle_max, &age)) {
timeval_subtract(&age, mesh->env->now_tv,
&m->reply_list->start_time);
if(timeval_smaller(&mesh->jostle_max, &age)) {
/* its a goner */
log_nametypeclass(VERB_ALGO, "query jostled out to "
"make space for a new one",
@@ -424,44 +425,6 @@ 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,
@@ -471,8 +434,7 @@ 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, added_reply_without_accounting = 0, added_tcp = 0;
struct mesh_reply* repadded = NULL;
int added = 0;
int timeout = mesh->env->cfg->serve_expired?
mesh->env->cfg->serve_expired_client_timeout:0;
struct sldns_buffer* r_buffer = rep->c->buffer;
@@ -504,10 +466,6 @@ void mesh_new_client(struct mesh_area* mesh, struct query_info* qinfo,
if(!mesh_make_new_space(mesh, rep->c->buffer)) {
verbose(VERB_ALGO, "Too many queries. dropping "
"incoming query.");
if(rep->c->use_h2)
http2_stream_remove_mesh_state(rep->c->h2_stream);
else if(rep->c->type == comm_doq && rep->doq_stream)
doq_stream_remove_mesh_state(rep->doq_stream);
comm_point_drop_reply(rep);
mesh->stats_dropped++;
return;
@@ -519,12 +477,8 @@ void mesh_new_client(struct mesh_area* mesh, struct query_info* qinfo,
if(mesh->num_reply_addrs > mesh->max_reply_states*16) {
verbose(VERB_ALGO, "Too many requests queued. "
"dropping incoming query.");
if(rep->c->use_h2)
http2_stream_remove_mesh_state(rep->c->h2_stream);
else if(rep->c->type == comm_doq && rep->doq_stream)
doq_stream_remove_mesh_state(rep->doq_stream);
comm_point_drop_reply(rep);
mesh->num_queries_replyaddr_limit++;
mesh->stats_dropped++;
return;
}
}
@@ -583,22 +537,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, &repadded)) {
if(!mesh_state_add_reply(s, edns, rep, qid, qflags, qinfo)) {
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) {
doq_stream_add_meshstate(rep->doq_stream, mesh, s);
}
/* add serve expired timer if required and not already there */
if(timeout && !mesh_serve_expired_init(s, timeout)) {
@@ -616,8 +566,6 @@ 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 */
@@ -654,14 +602,7 @@ servfail_mem:
qinfo, qid, qflags, edns);
if(rep->c->use_h2)
http2_stream_remove_mesh_state(rep->c->h2_stream);
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;
@@ -670,8 +611,7 @@ servfail_mem:
int
mesh_new_callback(struct mesh_area* mesh, struct query_info* qinfo,
uint16_t qflags, struct edns_data* edns, sldns_buffer* buf,
uint16_t qid, mesh_cb_func_type cb, void* cb_arg, int rpz_passthru,
void** unique_info)
uint16_t qid, mesh_cb_func_type cb, void* cb_arg, int rpz_passthru)
{
struct mesh_state* s = NULL;
int unique = unique_mesh_state(edns->opt_list_in, mesh->env);
@@ -680,7 +620,6 @@ 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);
@@ -726,14 +665,13 @@ 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, &add_cb)) {
if(!mesh_state_add_cb(s, edns, buf, cb, cb_arg, qid, qflags)) {
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;
@@ -744,7 +682,6 @@ 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;
@@ -760,8 +697,6 @@ 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;
@@ -965,9 +900,33 @@ void mesh_report_reply(struct mesh_area* mesh, struct outbound_entry* e,
mesh_run(mesh, e->qstate->mesh_info, event, e);
}
struct respip_client_info*
/** copy strlist to region */
static struct config_strlist*
cfg_region_strlist_copy(struct regional* region, struct config_strlist* list)
{
struct config_strlist* result = NULL, *last = NULL, *s = list;
while(s) {
struct config_strlist* n = regional_alloc_zero(region,
sizeof(*n));
if(!n)
return NULL;
n->str = regional_strdup(region, s->str);
if(!n->str)
return NULL;
if(last)
last->next = n;
else result = n;
last = n;
s = s->next;
}
return result;
}
/** Copy the client info to the query region. */
static struct respip_client_info*
mesh_copy_client_info(struct regional* region, struct respip_client_info* cinfo)
{
size_t i;
struct respip_client_info* client_info;
client_info = regional_alloc_init(region, cinfo, sizeof(*cinfo));
if(!client_info)
@@ -986,13 +945,20 @@ mesh_copy_client_info(struct regional* region, struct respip_client_info* cinfo)
if(!client_info->tag_actions)
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->tag_datas) {
client_info->tag_datas = regional_alloc_zero(region,
sizeof(struct config_strlist*)*cinfo->tag_datas_size);
if(!client_info->tag_datas)
return NULL;
for(i=0; i<cinfo->tag_datas_size; i++) {
if(cinfo->tag_datas[i]) {
client_info->tag_datas[i] = cfg_region_strlist_copy(
region, cinfo->tag_datas[i]);
if(!client_info->tag_datas[i])
return NULL;
}
}
}
if(cinfo->view) {
/* Do not copy the view pointer but store a name instead.
* The name is looked up later when done, this means that
@@ -1002,11 +968,6 @@ mesh_copy_client_info(struct regional* region, struct respip_client_info* cinfo)
cinfo->view->name);
if(!client_info->view_name)
return NULL;
} else if(cinfo->view_name) {
client_info->view_name = regional_strdup(region,
cinfo->view_name);
if(!client_info->view_name)
return NULL;
}
return client_info;
}
@@ -1074,7 +1035,6 @@ mesh_state_create(struct module_env* env, struct query_info* qinfo,
mstate->s.no_cache_store = 0;
mstate->s.need_refetch = 0;
mstate->s.was_ratelimited = 0;
mstate->s.error_response_cache = 0;
mstate->s.qstarttime = *env->now;
/* init modules */
@@ -1121,6 +1081,8 @@ mesh_state_cleanup(struct mesh_state* mstate)
for(; rep; rep=rep->next) {
infra_wait_limit_dec(mesh->env->infra_cache,
&rep->query_reply, mesh->env->cfg);
if(rep->query_reply.c->use_h2)
http2_stream_remove_mesh_state(rep->h2_stream);
comm_point_drop_reply(&rep->query_reply);
log_assert(mesh->num_reply_addrs > 0);
mesh->num_reply_addrs--;
@@ -1257,9 +1219,6 @@ 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
@@ -1515,10 +1474,6 @@ mesh_send_reply(struct mesh_state* m, int rcode, struct reply_info* rep,
* for HTTP/2 stream to refer to mesh state, in case
* connection gets cleanup before HTTP/2 stream close. */
r->h2_stream->mesh_state = NULL;
#ifdef HAVE_NGTCP2
} else if(r->query_reply.doq_stream) {
r->query_reply.doq_stream->mesh_state = NULL;
#endif
}
/* send the reply */
/* We don't reuse the encoded answer if:
@@ -1673,9 +1628,9 @@ static void dns_error_reporting(struct module_qstate* qstate,
opt = edns_opt_list_find(qstate->edns_opts_back_in,
LDNS_EDNS_REPORT_CHANNEL);
if(!opt) return;
agent_domain_len = opt->opt_len;
agent_domain = opt->opt_data;
agent_domain_len = dname_valid(agent_domain, opt->opt_len);
if(agent_domain_len < 3) {
if(dname_valid(agent_domain, agent_domain_len) < 3) {
/* The agent domain needs to be a valid dname that is not the
* root; from RFC9567. */
return;
@@ -1782,10 +1737,72 @@ void mesh_query_done(struct mesh_state* mstate)
}
}
if(mstate->reply_list && mstate->s.env->cfg->dns_error_reporting
&& (!rep || rep->security != sec_status_secure))
if(mstate->reply_list && mstate->s.env->cfg->dns_error_reporting)
dns_error_reporting(&mstate->s, rep);
if(mstate->reply_list && rep) {
uint8_t data[8192];
struct sldns_buffer dest;
int i;
sldns_buffer_init_frm_data(&dest, data, sizeof(data));
reply_info_answer_encode(&mstate->s.qinfo, rep, 0 /* id */,
0 /* qflags */, &dest, 0 /* current time */,
1 /* cached */, mstate->s.env->scratch,
sizeof(data) /* udpsize */, NULL /* edns */,
1 /* dnssec */, 0 /* secure */);
log_err("Answer to be send to %d other unbounds, size: %d",
mstate->s.env->outnet->num_dist,
(int)sldns_buffer_limit(&dest));
for(i = 0; i < mstate->s.env->outnet->num_dist; i++) {
struct tsig_key* key;
int r;
uint8_t data_signed[8192];
struct sldns_buffer dest_signed;
if(mstate->s.env->outnet->dist[i] == -1
|| mstate->s.env->outnet->dist_tsig[i] == NULL)
continue;
if(mstate->s.env->outnet->dist_tsig[i] == TSIG_NOKEY) {
send(mstate->s.env->outnet->dist[i],
data, sldns_buffer_limit(&dest), 0);
continue;
}
lock_rw_rdlock(&mstate->s.env->tsig_key_table->lock);
key = tsig_key_table_search_fromstr(
mstate->s.env->tsig_key_table,
mstate->s.env->outnet->dist_tsig[i]);
if(!key) {
lock_rw_unlock(
&mstate->s.env->tsig_key_table->lock);
log_err("tsig key \"%s\" not found when "
"distributing responses",
mstate->s.env->outnet->dist_tsig[i]);
continue;
}
sldns_buffer_init_frm_data(&dest_signed,
data_signed, sizeof(data_signed));
sldns_buffer_write(&dest_signed,
data, sldns_buffer_limit(&dest));
if((r = tsig_sign_shared(&dest_signed, key->name,
key->algo->wireformat_name,
key->data, key->data_len,
*mstate->s.env->now))) {
lock_rw_unlock(
&mstate->s.env->tsig_key_table->lock);
log_err("tsig key \"%s\" failed to sign"
"distributing response: %s",
key->name_str,
sldns_lookup_by_id(sldns_tsig_errors, r)?
sldns_lookup_by_id(sldns_tsig_errors, r)->name:"??");
continue;
}
lock_rw_unlock(&mstate->s.env->tsig_key_table->lock);
send(mstate->s.env->outnet->dist[i], data_signed,
sldns_buffer_position(&dest_signed), 0);
}
}
for(r = mstate->reply_list; r; r = r->next) {
if(mesh_is_udp(r)) {
/* For UDP queries, the old replies are discarded.
@@ -1813,12 +1830,8 @@ void mesh_query_done(struct mesh_state* mstate)
mstate->reply_list = NULL;
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++;
continue;
}
@@ -1852,13 +1865,9 @@ void mesh_query_done(struct mesh_state* mstate)
mstate->reply_list = NULL;
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 {
struct sldns_buffer* r_buffer = r->query_reply.c->buffer;
if(r->query_reply.c->tcp_req_info) {
@@ -1966,25 +1975,6 @@ 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)
{
@@ -2006,7 +1996,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, struct mesh_cb** result)
uint16_t qid, uint16_t qflags)
{
struct mesh_cb* r = regional_alloc(s->s.region,
sizeof(struct mesh_cb));
@@ -2030,14 +2020,13 @@ 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, struct mesh_reply** result)
const struct query_info* qinfo)
{
struct mesh_reply* r = regional_alloc(s->s.region,
sizeof(struct mesh_reply));
@@ -2057,10 +2046,6 @@ int mesh_state_add_reply(struct mesh_state* s, struct edns_data* edns,
r->qid = qid;
r->qflags = qflags;
r->start_time = *s->s.env->now_tv;
if(s->reply_list == NULL && !s->has_first_reply_time) {
s->first_reply_time = r->start_time;
s->has_first_reply_time = 1;
}
r->next = s->reply_list;
r->qname = regional_alloc_init(s->s.region, qinfo->qname,
s->s.qinfo.qname_len);
@@ -2069,8 +2054,6 @@ int mesh_state_add_reply(struct mesh_state* s, struct edns_data* edns,
if(rep->c->use_h2)
r->h2_stream = rep->c->h2_stream;
else r->h2_stream = NULL;
if(rep->c->type != comm_doq)
r->query_reply.doq_stream = NULL;
/* Data related to local alias stored in 'qinfo' (if any) is ephemeral
* and can be different for different original queries (even if the
@@ -2118,7 +2101,6 @@ 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;
}
@@ -2276,29 +2258,8 @@ 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));
@@ -2397,7 +2358,6 @@ mesh_stats_clear(struct mesh_area* mesh)
memset(&mesh->rpz_action[0], 0, sizeof(size_t)*UB_STATS_RPZ_ACTION_NUM);
mesh->ans_nodata = 0;
mesh->num_queries_discard_timeout = 0;
mesh->num_queries_replyaddr_limit = 0;
mesh->num_queries_wait_limit = 0;
mesh->num_dns_error_reports = 0;
}
@@ -2450,8 +2410,7 @@ 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 http2_stream* h2_stream,
struct doq_stream* doq_stream)
struct comm_point* cp)
{
struct mesh_reply* n, *prev = NULL;
n = m->reply_list;
@@ -2459,9 +2418,7 @@ void mesh_state_remove_reply(struct mesh_area* mesh, struct mesh_state* m,
* there is no accounting twice */
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)) {
if(n->query_reply.c == cp) {
/* unlink it */
if(prev) prev->next = n->next;
else m->reply_list = n->next;
@@ -2470,14 +2427,6 @@ void mesh_state_remove_reply(struct mesh_area* mesh, struct mesh_state* m,
mesh->num_reply_addrs--;
infra_wait_limit_dec(mesh->env->infra_cache,
&n->query_reply, mesh->env->cfg);
/* We may be removing more than one http2 stream (they
* share the same comm_point); make sure the streams
* don't point back. */
if(n->h2_stream) n->h2_stream->mesh_state = NULL;
#ifdef HAVE_NGTCP2
if(n->query_reply.doq_stream)
n->query_reply.doq_stream->mesh_state = NULL;
#endif
/* prev = prev; */
n = n->next;
@@ -2518,10 +2467,9 @@ apply_respip_action(struct module_qstate* qstate,
/* xxx_deny actions mean dropping the reply, unless the original reply
* was redirected to response-ip data. */
if(actinfo->action == respip_always_deny ||
((actinfo->action == respip_deny ||
if((actinfo->action == respip_deny ||
actinfo->action == respip_inform_deny) &&
*encode_repp == rep))
*encode_repp == rep)
*encode_repp = NULL;
return 1;
@@ -2586,15 +2534,12 @@ mesh_serve_expired_callback(void* arg)
qstate->client_info, &actinfo, msg->rep, &alias_rrset, &encode_rep,
qstate->env->auth_zones)) {
return;
} else if(partial_rep) {
if(!respip_merge_cname(partial_rep, &qstate->qinfo, msg->rep,
} else if(partial_rep &&
!respip_merge_cname(partial_rep, &qstate->qinfo, msg->rep,
qstate->client_info, must_validate, &encode_rep, qstate->region,
qstate->env->auth_zones, qstate->env->views,
qstate->env->respip_set)) {
return;
}
/* merge succeeded; final reply, no further alias pass */
partial_rep = NULL;
return;
}
if(!encode_rep || alias_rrset) {
if(!encode_rep) {
@@ -2605,7 +2550,6 @@ mesh_serve_expired_callback(void* arg)
partial_rep = encode_rep;
}
}
msg->rep = encode_rep;
/* We've found a partial reply ending with an
* alias. Replace the lookup qinfo for the
* alias target and lookup the cache again to
@@ -2632,10 +2576,9 @@ mesh_serve_expired_callback(void* arg)
log_dns_msg("Serve expired lookup", &qstate->qinfo, msg->rep);
for(r = mstate->reply_list; r; r = r->next) {
if(mesh_is_udp(r)) {
struct timeval old;
timeval_subtract(&old, mstate->s.env->now_tv, &r->start_time);
if(mstate->s.env->cfg->discard_timeout != 0 &&
struct timeval old;
timeval_subtract(&old, mstate->s.env->now_tv, &r->start_time);
if(mstate->s.env->cfg->discard_timeout != 0 &&
((int)old.tv_sec)*1000+((int)old.tv_usec)/1000 >
mstate->s.env->cfg->discard_timeout) {
/* Drop the reply, it is too old */
@@ -2651,15 +2594,10 @@ mesh_serve_expired_callback(void* arg)
mstate->reply_list = NULL;
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++;
continue;
}
}
i++;
@@ -2756,30 +2694,13 @@ 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, void* unique_info)
uint16_t qflags, mesh_cb_func_type cb, void* cb_arg)
{
struct mesh_state* s = NULL;
s = mesh_area_find(mesh, NULL, qinfo, qflags&(BIT_RD|BIT_CD), 0, 0);
if(s && 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;
if(!s) return;
if(!mesh_state_del_cb(s, cb, cb_arg)) return;
removed:
/* It was in the list and removed. */
log_assert(mesh->num_reply_addrs > 0);
mesh->num_reply_addrs--;
+5 -52
View File
@@ -69,13 +69,6 @@ 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
@@ -148,8 +141,6 @@ struct mesh_area {
size_t rpz_action[UB_STATS_RPZ_ACTION_NUM];
/** stats, number of queries removed due to discard-timeout */
size_t num_queries_discard_timeout;
/** stats, number of queries removed due to replyaddr limit */
size_t num_queries_replyaddr_limit;
/** stats, number of queries removed due to wait-limit */
size_t num_queries_wait_limit;
/** stats, number of dns error reports generated */
@@ -198,12 +189,6 @@ struct mesh_state {
struct module_qstate s;
/** the list of replies to clients for the results */
struct mesh_reply* reply_list;
/** if it has a first reply time */
int has_first_reply_time;
/** wall-clock time the first client reply was attached;
* used by mesh_make_new_space() so duplicate retransmits
* cannot reset jostle aging. */
struct timeval first_reply_time;
/** the list of callbacks for the results */
struct mesh_cb* cb_list;
/** set of superstates (that want this state's result)
@@ -349,14 +334,11 @@ 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,
void** unique_info);
uint16_t qid, mesh_cb_func_type cb, void* cb_arg, int rpz_passthru);
/**
* New prefetch message. Create new query state if needed.
@@ -553,23 +535,6 @@ 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.
@@ -589,12 +554,11 @@ 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, struct mesh_reply** result);
const struct query_info* qinfo);
/**
* Create new callback structure and attach it to a mesh state.
@@ -606,12 +570,11 @@ 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, struct mesh_cb** result);
uint16_t qid, uint16_t qflags);
/**
* Run the mesh. Run all runnable mesh states. Which can create new
@@ -712,14 +675,9 @@ 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 http2_stream* h2_stream,
struct doq_stream* doq_stream);
struct comm_point* cp);
/** 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.
@@ -766,13 +724,8 @@ 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, void* unique_info);
/** Copy the client info to the query region. */
struct respip_client_info* mesh_copy_client_info(struct regional* region,
struct respip_client_info* cinfo);
uint16_t qflags, mesh_cb_func_type cb, void* cb_arg);
#endif /* SERVICES_MESH_H */
+110 -440
View File
@@ -59,6 +59,7 @@
#include "util/random.h"
#include "util/fptr_wlist.h"
#include "util/edns.h"
#include "util/allow_response_list.h"
#include "sldns/sbuffer.h"
#include "dnstap/dnstap.h"
#ifdef HAVE_OPENSSL_SSL_H
@@ -160,19 +161,6 @@ reuse_cmp_addrportssl(const void* key1, const void* key2)
return 1;
if(!r1->is_ssl && r2->is_ssl)
return -1;
/* compare tls_auth_name if SSL-enabled */
if(r1->is_ssl) {
if(r1->tls_auth_name && !r2->tls_auth_name)
return 1;
if(!r1->tls_auth_name && r2->tls_auth_name)
return -1;
if(r1->tls_auth_name && r2->tls_auth_name) {
r = strcmp(r1->tls_auth_name, r2->tls_auth_name);
if(r != 0)
return r;
}
}
return 0;
}
@@ -208,7 +196,6 @@ static void
waiting_tcp_delete(struct waiting_tcp* w)
{
if(!w) return;
free(w->tls_auth_name);
if(w->timer)
comm_timer_delete(w->timer);
free(w);
@@ -545,7 +532,7 @@ reuse_tcp_insert(struct outside_network* outnet, struct pending_tcp* pend_tcp)
/** find reuse tcp stream to destination for query, or NULL if none */
static struct reuse_tcp*
reuse_tcp_find(struct outside_network* outnet, struct sockaddr_storage* addr,
socklen_t addrlen, int use_ssl, char* tls_auth_name)
socklen_t addrlen, int use_ssl)
{
struct waiting_tcp key_w;
struct pending_tcp key_p;
@@ -559,10 +546,8 @@ reuse_tcp_find(struct outside_network* outnet, struct sockaddr_storage* addr,
key_p.c = &c;
key_p.reuse.pending = &key_p;
key_p.reuse.node.key = &key_p.reuse;
if(use_ssl) {
if(use_ssl)
key_p.reuse.is_ssl = 1;
key_p.reuse.tls_auth_name = tls_auth_name;
}
if(addrlen > (socklen_t)sizeof(key_p.reuse.addr))
return NULL;
memmove(&key_p.reuse.addr, addr, addrlen);
@@ -662,7 +647,6 @@ static int
outnet_tcp_take_into_use(struct waiting_tcp* w)
{
struct pending_tcp* pend = w->outnet->tcp_free;
char* tls_auth_name = NULL;
int s;
log_assert(pend);
log_assert(w->pkt);
@@ -763,22 +747,7 @@ outnet_tcp_take_into_use(struct waiting_tcp* w)
comm_point_tcp_win_bio_cb(pend->c, pend->c->ssl);
#endif
pend->c->ssl_shake_state = comm_ssl_shake_write;
if(w->tls_auth_name) {
/* strdup the auth name, while not linked the list yet,
* in case of failure, easy cleanup. */
tls_auth_name = strdup(w->tls_auth_name);
if(!tls_auth_name) {
log_err("out of memory: alloc tls auth name");
pend->c->fd = s;
#ifdef HAVE_SSL
SSL_free(pend->c->ssl);
#endif
pend->c->ssl = NULL;
comm_point_close(pend->c);
return 0;
}
}
if(!set_auth_name_on_ssl(pend->c->ssl, tls_auth_name,
if(!set_auth_name_on_ssl(pend->c->ssl, w->tls_auth_name,
w->outnet->tls_use_sni)) {
pend->c->fd = s;
#ifdef HAVE_SSL
@@ -786,7 +755,6 @@ outnet_tcp_take_into_use(struct waiting_tcp* w)
#endif
pend->c->ssl = NULL;
comm_point_close(pend->c);
free(tls_auth_name);
return 0;
}
}
@@ -811,20 +779,9 @@ outnet_tcp_take_into_use(struct waiting_tcp* w)
if(pend->reuse.node.key)
reuse_tcp_remove_tree_list(w->outnet, &pend->reuse);
if(pend->c->ssl) {
if(pend->c->ssl)
pend->reuse.is_ssl = 1;
if(pend->reuse.tls_auth_name)
free(pend->reuse.tls_auth_name);
pend->reuse.tls_auth_name = tls_auth_name;
tls_auth_name = NULL;
} else {
pend->reuse.is_ssl = 0;
if(pend->reuse.tls_auth_name)
free(pend->reuse.tls_auth_name);
pend->reuse.tls_auth_name = NULL;
}
/* free tls auth name if nonNULL */
free(tls_auth_name);
else pend->reuse.is_ssl = 0;
/* insert in reuse by address tree if not already inserted there */
(void)reuse_tcp_insert(w->outnet, pend);
reuse_tree_by_id_insert(&pend->reuse, w);
@@ -1013,7 +970,7 @@ use_free_buffer(struct outside_network* outnet)
(!outnet->tcp_reuse_first && !outnet->tcp_reuse_last) ||
(outnet->tcp_reuse_first && outnet->tcp_reuse_last));
reuse = reuse_tcp_find(outnet, &w->addr, w->addrlen,
w->ssl_upstream, w->tls_auth_name);
w->ssl_upstream);
/* re-select an ID when moving to a new TCP buffer */
w->id = tcp_select_id(outnet, reuse);
LDNS_ID_SET(w->pkt, w->id);
@@ -1242,10 +1199,6 @@ decommission_pending_tcp(struct outside_network* outnet,
/* needs unlink from the reuse tree to get deleted */
reuse_tcp_remove_tree_list(outnet, &pend->reuse);
}
if(pend->reuse.tls_auth_name) {
free(pend->reuse.tls_auth_name);
pend->reuse.tls_auth_name = NULL;
}
/* free SSL structure after remove from outnet tcp reuse tree,
* because the c->ssl null or not is used for sorting in the tree */
if(pend->c->ssl) {
@@ -1481,7 +1434,7 @@ portcomm_loweruse(struct outside_network* outnet, struct port_comm* pc)
pif = pc->pif;
log_assert(pif->inuse > 0);
#ifndef DISABLE_EXPLICIT_PORT_RANDOMISATION
shared_ports_return_port(outnet->shared_ports, pif->shpif, pc->number);
pif->avail_ports[pif->avail_total - pif->inuse] = pc->number;
#endif
pif->inuse--;
pif->out[pc->index] = pif->out[pif->inuse];
@@ -1695,25 +1648,19 @@ create_pending_tcp(struct outside_network* outnet, size_t bufsize)
}
/** setup an outgoing interface, ready address */
static int setup_if(struct port_if* pif, const char* addrstr, size_t numfd,
struct shared_ports* shp)
static int setup_if(struct port_if* pif, const char* addrstr,
int* avail, int numavail, size_t numfd)
{
#ifndef DISABLE_EXPLICIT_PORT_RANDOMISATION
pif->avail_total = numavail;
pif->avail_ports = (int*)memdup(avail, (size_t)numavail*sizeof(int));
if(!pif->avail_ports)
return 0;
#endif
if(!ipstrtoaddr(addrstr, UNBOUND_DNS_PORT, &pif->addr, &pif->addrlen) &&
!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);
#else
(void)shp;
#endif
pif->maxout = (int)numfd;
pif->inuse = 0;
pif->out = (struct port_comm**)calloc(numfd,
@@ -1727,12 +1674,13 @@ struct outside_network*
outside_network_create(struct comm_base *base, size_t bufsize,
size_t num_ports, char** ifs, int num_ifs, int do_ip4,
int do_ip6, size_t num_tcp, int dscp, struct infra_cache* infra,
struct ub_randstate* rnd, int use_caps_for_id,
size_t unwanted_threshold, int tcp_mss,
struct ub_randstate* rnd, int use_caps_for_id, int* availports,
int numavailports, size_t unwanted_threshold, int tcp_mss,
void (*unwanted_action)(void*), void* unwanted_param, int do_udp,
void* sslctx, int delayclose, int tls_use_sni, struct dt_env* dtenv,
int udp_connect, int max_reuse_tcp_queries, int tcp_reuse_timeout,
int tcp_auth_query_timeout, struct shared_ports* shared_ports)
int tcp_auth_query_timeout, const char** dist, const char** dist_tsig,
int num_dist)
{
struct outside_network* outnet = (struct outside_network*)
calloc(1, sizeof(struct outside_network));
@@ -1767,7 +1715,6 @@ outside_network_create(struct comm_base *base, size_t bufsize,
outnet->do_udp = do_udp;
outnet->tcp_mss = tcp_mss;
outnet->ip_dscp = dscp;
outnet->shared_ports = shared_ports;
#ifndef S_SPLINT_S
if(delayclose) {
outnet->delayclose = 1;
@@ -1778,18 +1725,11 @@ outside_network_create(struct comm_base *base, size_t bufsize,
if(udp_connect) {
outnet->udp_connect = 1;
}
if(num_ports == 0) {
if(numavailports == 0 || num_ports == 0) {
log_err("no outgoing ports available");
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
@@ -1846,13 +1786,13 @@ outside_network_create(struct comm_base *base, size_t bufsize,
/* allocate interfaces */
if(num_ifs == 0) {
if(do_ip4 && !setup_if(&outnet->ip4_ifs[0], "0.0.0.0",
num_ports, outnet->shared_ports)) {
availports, numavailports, num_ports)) {
log_err("malloc failed");
outside_network_delete(outnet);
return NULL;
}
if(do_ip6 && !setup_if(&outnet->ip6_ifs[0], "::",
num_ports, outnet->shared_ports)) {
availports, numavailports, num_ports)) {
log_err("malloc failed");
outside_network_delete(outnet);
return NULL;
@@ -1863,7 +1803,7 @@ outside_network_create(struct comm_base *base, size_t bufsize,
for(i=0; i<num_ifs; i++) {
if(str_is_ip6(ifs[i]) && do_ip6) {
if(!setup_if(&outnet->ip6_ifs[done_6], ifs[i],
num_ports, outnet->shared_ports)){
availports, numavailports, num_ports)){
log_err("malloc failed");
outside_network_delete(outnet);
return NULL;
@@ -1872,7 +1812,7 @@ outside_network_create(struct comm_base *base, size_t bufsize,
}
if(!str_is_ip6(ifs[i]) && do_ip4) {
if(!setup_if(&outnet->ip4_ifs[done_4], ifs[i],
num_ports, outnet->shared_ports)){
availports, numavailports, num_ports)){
log_err("malloc failed");
outside_network_delete(outnet);
return NULL;
@@ -1881,6 +1821,32 @@ outside_network_create(struct comm_base *base, size_t bufsize,
}
}
}
if (!(outnet->num_dist = num_dist))
outnet->dist = NULL;
else if ((outnet->dist = calloc(num_dist, sizeof(int))) &&
(outnet->dist_tsig = calloc(num_dist, sizeof(const char*)))) {
int i;
for(i = 0; i < num_dist; i++) {
struct sockaddr_storage addr;
socklen_t addrlen;
int s = -1;
if(!extstrtoaddr(dist[i], &addr, &addrlen, UNBOUND_DNS_PORT)
|| (s = socket(addr.ss_family, SOCK_DGRAM, 0)) == -1
|| !fd_set_nonblock(s)
|| connect(s, (struct sockaddr*)&addr, addrlen)) {
if(s != -1)
close(s);
s = -1;
}
outnet->dist[i] = s;
outnet->dist_tsig[i] = dist_tsig[i] == NULL ? NULL
: strcmp(dist_tsig[i], TSIG_NOKEY)
? strdup(dist_tsig[i])
: TSIG_NOKEY;
}
}
return outnet;
}
@@ -1950,6 +1916,9 @@ outside_network_delete(struct outside_network* outnet)
comm_point_delete(pc->cp);
free(pc);
}
#ifndef DISABLE_EXPLICIT_PORT_RANDOMISATION
free(outnet->ip4_ifs[i].avail_ports);
#endif
free(outnet->ip4_ifs[i].out);
}
free(outnet->ip4_ifs);
@@ -1963,6 +1932,9 @@ outside_network_delete(struct outside_network* outnet)
comm_point_delete(pc->cp);
free(pc);
}
#ifndef DISABLE_EXPLICIT_PORT_RANDOMISATION
free(outnet->ip6_ifs[i].avail_ports);
#endif
free(outnet->ip6_ifs[i].out);
}
free(outnet->ip6_ifs);
@@ -1978,10 +1950,6 @@ outside_network_delete(struct outside_network* outnet)
* the tcp conn is working on */
decommission_pending_tcp(outnet, pend);
}
if(pend->reuse.tls_auth_name) {
free(pend->reuse.tls_auth_name);
pend->reuse.tls_auth_name = NULL;
}
comm_point_delete(outnet->tcp_conns[i]->c);
free(outnet->tcp_conns[i]);
outnet->tcp_conns[i] = NULL;
@@ -2009,6 +1977,8 @@ outside_network_delete(struct outside_network* outnet)
p = np;
}
}
if(outnet->num_dist > 0 && outnet->dist != NULL)
free(outnet->dist);
free(outnet);
}
@@ -2172,10 +2142,7 @@ static int
select_ifport(struct outside_network* outnet, struct pending* pend,
int num_if, struct port_if* ifs)
{
int my_if, fd, portno, inuse, tries=0;
#ifndef DISABLE_EXPLICIT_PORT_RANDOMISATION
int reused;
#endif
int my_if, my_port, fd, portno, inuse, tries=0;
struct port_if* pif;
/* randomly select interface and port */
if(num_if == 0) {
@@ -2189,35 +2156,37 @@ select_ifport(struct outside_network* outnet, struct pending* pend,
my_if = ub_random_max(outnet->rnd, num_if);
pif = &ifs[my_if];
#ifndef DISABLE_EXPLICIT_PORT_RANDOMISATION
if(!shared_ports_fetch_random(outnet->shared_ports,
pif->shpif, outnet->rnd, outnet->udp_connect,
pif->inuse, &portno, &reused)) {
tries++;
if(tries < MAX_PORT_RETRY)
continue;
log_err("failed to find an open port, drop msg");
return 0;
if(outnet->udp_connect) {
/* if we connect() we cannot reuse fds for a port */
if(pif->inuse >= pif->avail_total) {
tries++;
if(tries < MAX_PORT_RETRY)
continue;
log_err("failed to find an open port, drop msg");
return 0;
}
my_port = pif->inuse + ub_random_max(outnet->rnd,
pif->avail_total - pif->inuse);
} else {
my_port = ub_random_max(outnet->rnd, pif->avail_total);
if(my_port < pif->inuse) {
/* port already open */
pend->pc = pif->out[my_port];
verbose(VERB_ALGO, "using UDP if=%d port=%d",
my_if, pend->pc->number);
break;
}
}
if(reused) {
/* port already open */
log_assert(portno < pif->inuse);
pend->pc = pif->out[portno];
verbose(VERB_ALGO, "using UDP if=%d port=%d",
my_if, pend->pc->number);
break;
}
#else
portno = 0;
#endif
/* try to open new port, if fails, loop to try again */
log_assert(pif->inuse < pif->maxout);
portno = pif->avail_ports[my_port - pif->inuse];
#else
my_port = portno = 0;
#endif
fd = udp_sockport(&pif->addr, pif->addrlen, pif->pfxlen,
portno, &inuse, outnet->rnd, outnet->ip_dscp);
if(fd == -1 && !inuse) {
/* nonrecoverable error making socket */
#ifndef DISABLE_EXPLICIT_PORT_RANDOMISATION
shared_ports_return_port(outnet->shared_ports,
pif->shpif, portno);
#endif
return 0;
}
if(fd != -1) {
@@ -2234,11 +2203,6 @@ select_ifport(struct outside_network* outnet, struct pending* pend,
pend->addrlen);
}
sock_close(fd);
#ifndef DISABLE_EXPLICIT_PORT_RANDOMISATION
shared_ports_return_port(
outnet->shared_ports,
pif->shpif, portno);
#endif
return 0;
}
}
@@ -2256,14 +2220,14 @@ select_ifport(struct outside_network* outnet, struct pending* pend,
/* grab port in interface */
pif->out[pif->inuse] = pend->pc;
#ifndef DISABLE_EXPLICIT_PORT_RANDOMISATION
pif->avail_ports[my_port - pif->inuse] =
pif->avail_ports[pif->avail_total-pif->inuse-1];
#endif
pif->inuse++;
break;
}
/* failed, already in use */
#ifndef DISABLE_EXPLICIT_PORT_RANDOMISATION
shared_ports_return_port(outnet->shared_ports, pif->shpif,
portno);
#endif
verbose(VERB_QUERY, "port %d in use, trying another", portno);
tries++;
if(tries == MAX_PORT_RETRY) {
@@ -2513,7 +2477,7 @@ pending_tcp_query(struct serviced_query* sq, sldns_buffer* packet,
/* find out if a reused stream to the target exists */
/* if so, take it into use */
reuse = reuse_tcp_find(sq->outnet, &sq->addr, sq->addrlen,
sq->ssl_upstream, sq->tls_auth_name);
sq->ssl_upstream);
if(reuse) {
log_reuse_tcp(VERB_CLIENT, "pending_tcp_query: found reuse", reuse);
log_assert(reuse->pending);
@@ -2555,16 +2519,7 @@ pending_tcp_query(struct serviced_query* sq, sldns_buffer* packet,
w->cb = callback;
w->cb_arg = callback_arg;
w->ssl_upstream = sq->ssl_upstream;
if(sq->tls_auth_name) {
w->tls_auth_name = strdup(sq->tls_auth_name);
if(!w->tls_auth_name) {
comm_timer_delete(w->timer);
free(w);
return NULL;
}
} else {
w->tls_auth_name = NULL;
}
w->tls_auth_name = sq->tls_auth_name;
w->timeout = timeout;
w->id_node.key = NULL;
w->write_wait_prev = NULL;
@@ -3362,9 +3317,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 1472/1232 */
/* fallback to 1480/1280 */
sq->status = serviced_query_UDP_EDNS_FRAG;
log_name_addr(VERB_ALGO, "try edns1xx2", sq->qbuf+10,
log_name_addr(VERB_ALGO, "try edns1xx0", sq->qbuf+10,
&sq->addr, sq->addrlen);
if(!serviced_udp_send(sq, c->buffer)) {
serviced_callbacks(sq, NETEVENT_CLOSED, c, rep);
@@ -3501,8 +3456,7 @@ 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,
int* ratelimit_incremented)
sldns_buffer* buff, struct module_env* env, int* was_ratelimited)
{
struct serviced_query* sq;
struct service_callback* cb;
@@ -3574,7 +3528,6 @@ 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,
@@ -3656,16 +3609,13 @@ fd_for_dest(struct outside_network* outnet, struct sockaddr_storage* to_addr,
{
struct sockaddr_storage* addr;
socklen_t addrlen;
int i, try, dscp;
int i, try, pnum, dscp;
struct port_if* pif;
/* create fd */
dscp = outnet->ip_dscp;
for(try = 0; try<1000; try++) {
int port = 0;
#ifndef DISABLE_EXPLICIT_PORT_RANDOMISATION
int reused = 0;
#endif
int freebind = 0;
int noproto = 0;
int inuse = 0;
@@ -3694,18 +3644,16 @@ fd_for_dest(struct outside_network* outnet, struct sockaddr_storage* to_addr,
addr = &pif->addr;
addrlen = pif->addrlen;
#ifndef DISABLE_EXPLICIT_PORT_RANDOMISATION
if(!shared_ports_fetch_random(outnet->shared_ports,
pif->shpif, outnet->rnd, 0, pif->inuse,
&port, &reused)) {
/* try again, perhaps another interface. */
continue;
}
if(reused) {
log_assert(port < pif->inuse);
port = pif->out[port]->number;
pnum = ub_random_max(outnet->rnd, pif->avail_total);
if(pnum < pif->inuse) {
/* port already open */
port = pif->out[pnum]->number;
} else {
/* unused ports in start part of array */
port = pif->avail_ports[pnum - pif->inuse];
}
#else
port = 0;
pnum = port = 0;
#endif
if(addr_is_ip6(to_addr, to_addrlen)) {
struct sockaddr_in6 sa = *(struct sockaddr_in6*)addr;
@@ -3720,14 +3668,6 @@ fd_for_dest(struct outside_network* outnet, struct sockaddr_storage* to_addr,
(struct sockaddr*)addr, addrlen, 1, &inuse, &noproto,
0, 0, 0, NULL, 0, freebind, 0, dscp);
}
#ifndef DISABLE_EXPLICIT_PORT_RANDOMISATION
if(!reused) {
/* Return the port to the pool, since the caller does
* not keep track of it, also have done fd, and bind. */
shared_ports_return_port(outnet->shared_ports,
pif->shpif, port);
}
#endif
if(fd != -1) {
return fd;
}
@@ -3780,33 +3720,7 @@ 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_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)
#ifdef 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
@@ -3935,8 +3849,7 @@ 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,
sldns_buffer_capacity(outnet->udp_buff), cb, cb_arg,
cp = comm_point_create_http_out(outnet->base, 65552, cb, cb_arg,
outnet->udp_buff);
if(!cp) {
log_err("malloc failure");
@@ -3985,7 +3898,11 @@ if_get_mem(struct port_if* pif)
{
size_t s;
int i;
s = sizeof(*pif) + sizeof(struct port_comm*)*pif->maxout;
s = sizeof(*pif) +
#ifndef DISABLE_EXPLICIT_PORT_RANDOMISATION
sizeof(int)*pif->avail_total +
#endif
sizeof(struct port_comm*)*pif->maxout;
for(i=0; i<pif->inuse; i++)
s += sizeof(*pif->out[i]) +
comm_point_get_mem(pif->out[i]->cp);
@@ -4073,250 +3990,3 @@ serviced_get_mem(struct serviced_query* sq)
return s;
}
#ifndef DISABLE_EXPLICIT_PORT_RANDOMISATION
/** Setup shared port interface */
static int shared_ports_setup_if(struct shared_ports_if* shpif, char* str,
int* availports, int numavailports)
{
shpif->avail_ports = (int*)memdup(availports,
(size_t)numavailports*sizeof(int));
if(!shpif->avail_ports)
return 0;
shpif->avail_total = numavailports;
shpif->inuse = 0;
shpif->pfxlen = 0;
if(!ipstrtoaddr(str, UNBOUND_DNS_PORT, &shpif->addr, &shpif->addrlen) &&
!netblockstrtoaddr(str, UNBOUND_DNS_PORT, &shpif->addr,
&shpif->addrlen, &shpif->pfxlen))
return 0;
return 1;
}
#endif
#ifndef DISABLE_EXPLICIT_PORT_RANDOMISATION
/** Allocate shared ports interfaces */
static int shared_ports_alloc_ifs(struct shared_ports* shp, char** ifs,
int num_ifs, int do_ip4, int do_ip6, int* availports,
int numavailports)
{
#ifndef INET6
do_ip6 = 0;
#endif
calc_num46(ifs, num_ifs, do_ip4, do_ip6,
&shp->num_ip4, &shp->num_ip6);
if(shp->num_ip4 != 0) {
if(!(shp->ip4_ifs = (struct shared_ports_if*)calloc(
(size_t)shp->num_ip4,
sizeof(struct shared_ports_if))))
return 0;
}
if(shp->num_ip6 != 0) {
if(!(shp->ip6_ifs = (struct shared_ports_if*)calloc(
(size_t)shp->num_ip6,
sizeof(struct shared_ports_if))))
return 0;
}
if(num_ifs == 0) {
if(do_ip4 && !shared_ports_setup_if(&shp->ip4_ifs[0],
"0.0.0.0", availports, numavailports))
return 0;
if(do_ip6 && !shared_ports_setup_if(&shp->ip6_ifs[0],
"::", availports, numavailports))
return 0;
} else {
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 &&
(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 &&
(int)done_4 < shp->num_ip4) {
if(!shared_ports_setup_if(&shp->ip4_ifs[done_4],
ifs[i], availports, numavailports))
return 0;
done_4++;
}
}
}
return 1;
}
#endif
struct shared_ports* shared_ports_create(char** ifs, int num_ifs, int do_ip4,
int do_ip6, int* availports, int numavailports)
{
struct shared_ports* shp = calloc(1, sizeof(*shp));
if(!shp) {
log_err("malloc failed");
return NULL;
}
lock_basic_init(&shp->lock);
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;
#endif
return shp;
}
#ifndef DISABLE_EXPLICIT_PORT_RANDOMISATION
/** Delete shared ports interface structure */
static void shared_ports_if_delete(struct shared_ports_if* shpif)
{
if(!shpif)
return;
free(shpif->avail_ports);
}
#endif
void shared_ports_delete(struct shared_ports* shp)
{
#ifndef DISABLE_EXPLICIT_PORT_RANDOMISATION
int i;
#endif
if(!shp)
return;
lock_basic_destroy(&shp->lock);
#ifndef DISABLE_EXPLICIT_PORT_RANDOMISATION
for(i=0; i<shp->num_ip4; i++) {
shared_ports_if_delete(&shp->ip4_ifs[i]);
}
free(shp->ip4_ifs);
for(i=0; i<shp->num_ip6; i++) {
shared_ports_if_delete(&shp->ip6_ifs[i]);
}
free(shp->ip6_ifs);
#endif
free(shp);
}
struct shared_ports_if* shared_ports_find_if(struct shared_ports* shp,
struct sockaddr_storage* addr, socklen_t addrlen, int pfxlen)
{
#ifndef DISABLE_EXPLICIT_PORT_RANDOMISATION
struct shared_ports_if* ret, *ifs = NULL;
int i, num_ifs = 0;
lock_basic_lock(&shp->lock);
if(addr_is_ip6(addr, addrlen)) {
ifs = shp->ip6_ifs;
num_ifs = shp->num_ip6;
} else {
ifs = shp->ip4_ifs;
num_ifs = shp->num_ip4;
}
for(i=0; i<num_ifs; i++) {
if(sockaddr_cmp(addr, addrlen, &ifs[i].addr,
ifs[i].addrlen) == 0
&& pfxlen == ifs[i].pfxlen) {
ret = &ifs[i];
lock_basic_unlock(&shp->lock);
return ret;
}
}
lock_basic_unlock(&shp->lock);
return NULL;
#else
(void)shp; (void)addr; (void)addrlen; (void)pfxlen;
return NULL;
#endif
}
int shared_ports_fetch_random(struct shared_ports* shp,
struct shared_ports_if* shpif, struct ub_randstate* rnd,
int udp_connect, int reusenum, int* port, int* reused)
{
#ifndef DISABLE_EXPLICIT_PORT_RANDOMISATION
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. */
if(shpif->inuse >= shpif->avail_total) {
lock_basic_unlock(&shp->lock);
return 0;
}
my_port = ub_random_max(rnd,
shpif->avail_total - shpif->inuse);
} else {
/* select from free ports and open ports on this thread. */
if(shpif->inuse >= shpif->avail_total) {
lock_basic_unlock(&shp->lock);
if(reusenum == 0) {
return 0;
}
my_port = ub_random_max(rnd, reusenum);
*port = my_port;
*reused = 1;
return 1;
}
my_port = ub_random_max(rnd, shpif->avail_total - shpif->inuse
+ reusenum);
if(my_port < reusenum) {
/* port already open */
lock_basic_unlock(&shp->lock);
*port = my_port;
*reused = 1;
return 1;
}
my_port -= reusenum;
}
log_assert(shpif->inuse < shpif->avail_total);
log_assert(my_port >= 0 && my_port < shpif->avail_total);
portno = shpif->avail_ports[my_port];
shpif->avail_ports[my_port] =
shpif->avail_ports[shpif->avail_total-shpif->inuse-1];
shpif->inuse++;
lock_basic_unlock(&shp->lock);
*port = portno;
*reused = 0;
return 1;
#else
(void)shp; (void)shpif; (void)rnd; (void)udp_connect;
(void)reusenum;
*port = 0;
*reused = 0;
return 1;
#endif
}
void shared_ports_return_port(struct shared_ports* shp,
struct shared_ports_if* shpif, int port)
{
#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;
shpif->inuse--;
lock_basic_unlock(&shp->lock);
#else
(void)shp; (void)shpif; (void)port;
#endif
}
+20 -108
View File
@@ -48,10 +48,6 @@
#include "util/regional.h"
#include "util/netevent.h"
#include "dnstap/dnstap_config.h"
#ifdef __QNX__
/* For struct timeval */
#include <sys/time.h>
#endif /* __QNX__ */
struct pending;
struct pending_timeout;
struct ub_randstate;
@@ -70,8 +66,6 @@ struct module_env;
struct module_qstate;
struct query_info;
struct config_file;
struct shared_ports;
struct shared_ports_if;
/**
* Send queries to outside servers and wait for answers from servers.
@@ -121,9 +115,6 @@ struct outside_network {
int udp_connect;
/** number of udp packets sent. */
size_t num_udp_outgoing;
/** the shared ports structure, with random ports numbers.
* This is a reference to the member in the daemon structure. */
struct shared_ports* shared_ports;
/** array of outgoing IP4 interfaces */
struct port_if* ip4_ifs;
@@ -199,6 +190,12 @@ struct outside_network {
struct waiting_tcp* tcp_wait_first;
/** last of waiting query list */
struct waiting_tcp* tcp_wait_last;
/** number of IP addresses to send to be cached responses to */
int num_dist;
/** udp sockets to the addresses to send to be cached responses to */
int* dist;
/** names of TSIG keys with which to sign the outgoing responses */
const char** dist_tsig;
};
/**
@@ -216,8 +213,11 @@ struct port_if {
int pfxlen;
#ifndef DISABLE_EXPLICIT_PORT_RANDOMISATION
/** the shared port numbers for this interface. */
struct shared_ports_if* shpif;
/** the available ports array. These are unused.
* Only the first total-inuse part is filled. */
int* avail_ports;
/** the total number of available ports (size of the array) */
int avail_total;
#endif
/** array of the commpoints currently in use.
@@ -247,42 +247,6 @@ struct port_comm {
struct comm_point* cp;
};
/**
* Shared ports, the list of ports shared across threads
*/
struct shared_ports {
/** mutex on the ports */
lock_basic_type lock;
/** array of IP4 interfaces */
struct shared_ports_if* ip4_ifs;
/** number of outgoing IP4 interfaces */
int num_ip4;
/** array of IP6 interfaces */
struct shared_ports_if* ip6_ifs;
/** number of outgoing IP6 interfaces */
int num_ip6;
};
/**
* Shared ports for an interface.
*/
struct shared_ports_if {
/** address ready to allocate new socket (except port no). */
struct sockaddr_storage addr;
/** length of addr field */
socklen_t addrlen;
/** if a netblock, the prefix */
int pfxlen;
/** the available ports array. These are unused.
* Only the first total-inuse part is filled. */
int* avail_ports;
/** the total number of available ports (size of the array) */
int avail_total;
/** the number in use. */
int inuse;
};
/**
* Reuse TCP connection, still open can be used again.
*/
@@ -302,9 +266,6 @@ struct reuse_tcp {
socklen_t addrlen;
/** also key for tcp_reuse tree, if ssl is used */
int is_ssl;
/** If is_ssl is enabled, tls_auth_name is part of the key for
* tcp_reuse tree. If the string is NULL, it without a tls_auth_name */
char* tls_auth_name;
/** lru chain, so that the oldest can be removed to get a new
* connection when all are in (re)use. oldest is last in list.
* The lru only contains empty connections waiting for reuse,
@@ -457,7 +418,7 @@ struct waiting_tcp {
void* cb_arg;
/** if it uses ssl upstream */
int ssl_upstream;
/** owned copy of the tls_auth_name (malloced) */
/** ref to the tls_auth_name from the serviced_query */
char* tls_auth_name;
/** the packet was involved in an error, to stop looping errors */
int error_count;
@@ -538,7 +499,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 EDNS1472 (or 1232) */
/** send UDP query with EDNS1480 (or 1280) */
serviced_query_UDP_EDNS_FRAG
}
/** variable with current status */
@@ -589,6 +550,8 @@ struct serviced_query {
* @param infra: pointer to infra cached used for serviced queries.
* @param rnd: stored to create random numbers for serviced queries.
* @param use_caps_for_id: enable to use 0x20 bits to encode id randomness.
* @param availports: array of available ports.
* @param numavailports: number of available ports in array.
* @param unwanted_threshold: when to take defensive action.
* @param unwanted_action: the action to take.
* @param unwanted_param: user parameter to action.
@@ -603,18 +566,18 @@ struct serviced_query {
* @param max_reuse_tcp_queries: max number of queries on a reuse connection.
* @param tcp_reuse_timeout: timeout for REUSE entries in milliseconds.
* @param tcp_auth_query_timeout: timeout in milliseconds for TCP queries to auth servers.
* @param shared_ports: the shared_ports structure.
* @return: the new structure (with no pending answers) or NULL on error.
*/
struct outside_network* outside_network_create(struct comm_base* base,
size_t bufsize, size_t num_ports, char** ifs, int num_ifs,
int do_ip4, int do_ip6, size_t num_tcp, int dscp, struct infra_cache* infra,
struct ub_randstate* rnd, int use_caps_for_id,
size_t unwanted_threshold, int tcp_mss,
struct ub_randstate* rnd, int use_caps_for_id, int* availports,
int numavailports, size_t unwanted_threshold, int tcp_mss,
void (*unwanted_action)(void*), void* unwanted_param, int do_udp,
void* sslctx, int delayclose, int tls_use_sni, struct dt_env *dtenv,
int udp_connect, int max_reuse_tcp_queries, int tcp_reuse_timeout,
int tcp_auth_query_timeout, struct shared_ports* shared_ports);
int tcp_auth_query_timeout, const char** dist, const char** dist_tsig,
int num_dist);
/**
* Delete outside_network structure.
@@ -697,8 +660,6 @@ 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.
*/
@@ -708,8 +669,7 @@ 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,
int* ratelimit_incremented);
struct sldns_buffer* buff, struct module_env* env, int* was_ratelimited);
/**
* Remove service query callback.
@@ -859,54 +819,6 @@ struct comm_point* outnet_comm_point_for_http(struct outside_network* outnet,
/** connect tcp connection to addr, 0 on failure */
int outnet_tcp_connect(int s, struct sockaddr_storage* addr, socklen_t addrlen);
/**
* Create new shared ports structure.
* @param ifs: interface names (or NULL for default interface).
* These interfaces must be able to access all authoritative servers.
* @param num_ifs: number of names in array ifs.
* @param do_ip4: service IP4.
* @param do_ip6: service IP6.
* @param availports: array of available ports.
* @param numavailports: number of available ports in array.
* @return new, or NULL on failure.
*/
struct shared_ports* shared_ports_create(char** ifs, int num_ifs, int do_ip4,
int do_ip6, int* availports, int numavailports);
/**
* Delete shared ports structure.
* @param shp: shared ports structure.
*/
void shared_ports_delete(struct shared_ports* shp);
/** Find interface in shared ports. */
struct shared_ports_if* shared_ports_find_if(struct shared_ports* shp,
struct sockaddr_storage* addr, socklen_t addrlen, int pfxlen);
/**
* Get a shared port from the list of random ports.
* @param shp: shared ports structure.
* @param shpif: the shared ports interface.
* @param rnd: used to make random numbers.
* @param udp_connect: set to true if no reuse is possible.
* @param reusenum: number of ports that can be reused (already open).
* @param port: the port number is returned.
* @param reused: if the port numer is reused, returned.
* @return false on failure. That can mean no more free ports to use.
*/
int shared_ports_fetch_random(struct shared_ports* shp,
struct shared_ports_if* shpif, struct ub_randstate* rnd,
int udp_connect, int reusenum, int* port, int* reused);
/**
* Return a shared port to the list of random ports.
* @param shp: shared ports structure.
* @param shpif: the shared ports interface.
* @param port: port number to return to be used again.
*/
void shared_ports_return_port(struct shared_ports* shp,
struct shared_ports_if* shpif, int port);
/** callback for incoming udp answers from the network */
int outnet_udp_cb(struct comm_point* c, void* arg, int error,
struct comm_reply *reply_info);
+21 -40
View File
@@ -153,7 +153,6 @@ rpz_type_ignored(uint16_t rr_type)
case LDNS_RR_TYPE_SOA:
case LDNS_RR_TYPE_NS:
case LDNS_RR_TYPE_DNAME:
case LDNS_RR_TYPE_ZONEMD:
/* all DNSSEC-related RRs must be ignored */
case LDNS_RR_TYPE_DNSKEY:
case LDNS_RR_TYPE_DS:
@@ -721,22 +720,13 @@ 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");
if(!newzone)
free(dname);
free(dname);
lock_rw_unlock(&lz->lock);
return;
}
lock_rw_wrlock(&z->lock);
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;
}
local_zone_enter_rr(z, dname, dnamelen, dnamelabs, rrtype,
rrclass, ttl, rdata, rdata_len, rrstr);
lock_rw_unlock(&z->lock);
free(rrstr);
}
@@ -814,9 +804,8 @@ rpz_insert_nsdname_trigger(struct rpz* r, uint8_t* dname, size_t dnamelen,
uint8_t* dname_stripped = NULL;
size_t dnamelen_stripped = 0;
if(!rpz_strip_nsdname_suffix(dname, dnamelen, &dname_stripped,
&dnamelen_stripped))
return;
rpz_strip_nsdname_suffix(dname, dnamelen, &dname_stripped,
&dnamelen_stripped);
if(a == RPZ_INVALID_ACTION) {
verbose(VERB_ALGO, "rpz: skipping invalid action");
free(dname_stripped);
@@ -914,8 +903,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, uint16_t rrtype,
uint16_t rrclass)
rpz_clientip_new_rrset(struct regional* region,
struct clientip_synthesized_rr* raddr, uint16_t rrtype, uint16_t rrclass)
{
struct packed_rrset_data* pd;
struct local_rrset* rrset = (struct local_rrset*)
@@ -924,6 +913,8 @@ rpz_clientip_new_rrset(struct regional* region, uint16_t rrtype,
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) {
@@ -962,18 +953,12 @@ rpz_clientip_enter_rr(struct regional* region, struct clientip_synthesized_rr* r
return 0;
}
rrset = rpz_clientip_new_rrset(region, rrtype, rrclass);
if(rrset == NULL) {
rrset = rpz_clientip_new_rrset(region, raddr, rrtype, rrclass);
if(raddr->data == NULL) {
return 0;
}
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;
return rrset_insert_rr(region, rrset->rrset->entry.data, rdata, rdata_len, ttl, "");
}
static int
@@ -996,6 +981,7 @@ 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)) {
@@ -1005,7 +991,6 @@ rpz_clientip_insert_trigger_rr(struct clientip_synthesized_rrset* set, struct so
}
}
node->action = a;
lock_rw_unlock(&node->lock);
@@ -1991,9 +1976,8 @@ rpz_synthesize_nodata(struct rpz* ATTR_UNUSED(r), struct module_qstate* ms,
0, /* total */
sec_status_insecure,
LDNS_EDE_NONE);
if(!msg->rep)
return NULL;
msg->rep->authoritative = 1;
if(msg->rep)
msg->rep->authoritative = 1;
if(!rpz_add_soa(msg->rep, ms, az))
return NULL;
return msg;
@@ -2023,9 +2007,8 @@ rpz_synthesize_nxdomain(struct rpz* r, struct module_qstate* ms,
0, /* total */
sec_status_insecure,
LDNS_EDE_NONE);
if(!msg->rep)
return NULL;
msg->rep->authoritative = 1;
if(msg->rep)
msg->rep->authoritative = 1;
if(!rpz_add_soa(msg->rep, ms, az))
return NULL;
return msg;
@@ -2485,7 +2468,6 @@ rpz_callback_from_iterator_module(struct module_qstate* ms, struct iter_qstate*
{
struct auth_zones* az;
struct auth_zone* a;
struct dns_msg* ret = NULL;
struct clientip_synthesized_rr* raddr = NULL;
struct rpz* r = NULL;
struct local_zone* z = NULL;
@@ -2529,11 +2511,13 @@ rpz_callback_from_iterator_module(struct module_qstate* ms, struct iter_qstate*
z = rpz_delegation_point_zone_lookup(is->dp, r->nsdname_zones,
is->qchase.qclass, &match);
if(z != NULL) {
lock_rw_unlock(&a->lock);
break;
}
raddr = rpz_delegation_point_ipbased_trigger_lookup(r, is);
if(raddr != NULL) {
lock_rw_unlock(&a->lock);
break;
}
lock_rw_unlock(&a->lock);
@@ -2548,12 +2532,9 @@ rpz_callback_from_iterator_module(struct module_qstate* ms, struct iter_qstate*
if(z) {
lock_rw_unlock(&z->lock);
}
ret = rpz_apply_nsip_trigger(ms, &is->qchase, r, raddr, a);
} else {
ret = rpz_apply_nsdname_trigger(ms, &is->qchase, r, z, &match, a);
return rpz_apply_nsip_trigger(ms, &is->qchase, r, raddr, a);
}
lock_rw_unlock(&a->lock);
return ret;
return rpz_apply_nsdname_trigger(ms, &is->qchase, r, z, &match, a);
}
struct dns_msg* rpz_callback_from_iterator_cname(struct module_qstate* ms,
+2 -11
View File
@@ -67,28 +67,19 @@ 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);
offset = 3;
return (len - exp - 3)*8;
} else {
return 0;
}
} else {
exp = keydata[0];
offset = 1;
return (len-exp-1)*8;
}
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;
}
+1 -1
View File
@@ -486,7 +486,6 @@ enum sldns_enum_ede_code
typedef enum sldns_enum_ede_code sldns_ede_code;
#define LDNS_EDNS_MASK_DO_BIT 0x8000
#define LDNS_EDNS_MASK_CO_BIT 0x4000
/** TSIG and TKEY extended rcodes (16bit), 0-15 are the normal rcodes. */
#define LDNS_TSIG_ERROR_NOERROR 0
@@ -496,6 +495,7 @@ typedef enum sldns_enum_ede_code sldns_ede_code;
#define LDNS_TSIG_ERROR_BADMODE 19
#define LDNS_TSIG_ERROR_BADNAME 20
#define LDNS_TSIG_ERROR_BADALG 21
#define LDNS_TSIG_ERROR_BADTRUNC 22
/** DNS Cookie extended rcode */
#define LDNS_EXT_RCODE_BADCOOKIE 23
+38
View File
@@ -56,6 +56,18 @@ sldns_read_uint32(const void *src)
#endif
}
INLINE uint64_t
sldns_read_uint48(const void *src)
{
const uint8_t *p = (const uint8_t *) src;
return ( ((uint64_t) p[0] << 40)
| ((uint64_t) p[1] << 32)
| ((uint64_t) p[2] << 24)
| ((uint64_t) p[3] << 16)
| ((uint64_t) p[4] << 8)
| (uint64_t) p[5]);
}
/*
* Copy data allowing for unaligned accesses in network byte order
* (big endian).
@@ -693,6 +705,32 @@ sldns_buffer_read_u32(sldns_buffer *buffer)
return result;
}
/**
* returns the 6-byte integer value at the given position in the buffer
* \param[in] buffer the buffer
* \param[in] at position in the buffer
* \return 6 byte integer
*/
INLINE uint64_t
sldns_buffer_read_u48_at(sldns_buffer *buffer, size_t at)
{
assert(sldns_buffer_available_at(buffer, at, 6));
return sldns_read_uint48(buffer->_data + at);
}
/**
* returns the 6-byte integer value at the current position in the buffer
* \param[in] buffer the buffer
* \return 6 byte integer
*/
INLINE uint64_t
sldns_buffer_read_u48(sldns_buffer *buffer)
{
uint64_t result = sldns_buffer_read_u48_at(buffer, buffer->_position);
buffer->_position += 6;
return result;
}
/**
* returns the status of the buffer
* \param[in] buffer
+4 -6
View File
@@ -842,8 +842,7 @@ rrinternal_parse_rdata(sldns_buffer* strbuf, char* token, size_t token_len,
sldns_write_uint16(rr+dname_len+8, (uint16_t)(rr_cur_len-dname_len-10));
*rr_len = rr_cur_len;
/* SVCB/HTTPS handling */
if ((rr_type == LDNS_RR_TYPE_SVCB || rr_type == LDNS_RR_TYPE_HTTPS)
&& !was_unknown_rr_format) {
if (rr_type == LDNS_RR_TYPE_SVCB || rr_type == LDNS_RR_TYPE_HTTPS) {
size_t rdata_len = rr_cur_len - dname_len - 10;
uint8_t *rdata = rr+dname_len + 10;
@@ -1202,7 +1201,7 @@ sldns_str2wire_svcbparam_ipv4hint(const char* val, uint8_t* rd, size_t* rd_len)
{
size_t count;
char ip_str[INET_ADDRSTRLEN+1];
const char *next_ip_str;
char *next_ip_str;
size_t i;
for (i = 0, count = 1; val[i]; i++) {
@@ -1257,7 +1256,7 @@ sldns_str2wire_svcbparam_ipv6hint(const char* val, uint8_t* rd, size_t* rd_len)
{
size_t count;
char ip_str[INET6_ADDRSTRLEN+1];
const char *next_ip_str;
char *next_ip_str;
size_t i;
for (i = 0, count = 1; val[i]; i++) {
@@ -1318,7 +1317,7 @@ static int
sldns_str2wire_svcbparam_mandatory(const char* val, uint8_t* rd, size_t* rd_len)
{
size_t i, count, val_len;
const char* next_key;
char* next_key;
val_len = strlen(val);
@@ -1411,7 +1410,6 @@ 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;
}
+1 -2
View File
@@ -256,6 +256,7 @@ static sldns_lookup_table sldns_tsig_errors_data[] = {
{ LDNS_TSIG_ERROR_BADMODE, "BADMODE" },
{ LDNS_TSIG_ERROR_BADNAME, "BADNAME" },
{ LDNS_TSIG_ERROR_BADALG, "BADALG" },
{ LDNS_TSIG_ERROR_BADTRUNC, "BADTRUNC" },
{ 0, NULL }
};
sldns_lookup_table* sldns_tsig_errors = sldns_tsig_errors_data;
@@ -2486,8 +2487,6 @@ int sldns_wire2str_edns_scan(uint8_t** data, size_t* data_len, char** str,
w += sldns_str_print(str, str_len, " flags:");
if((edns_bits & LDNS_EDNS_MASK_DO_BIT))
w += sldns_str_print(str, str_len, " do");
if((edns_bits & LDNS_EDNS_MASK_CO_BIT))
w += sldns_str_print(str, str_len, " co");
/* the extended rcode is the value set, shifted four bits,
* and or'd with the original rcode */
if(ext_rcode) {
+13 -175
View File
@@ -156,7 +156,7 @@ char* wsa_strerror(int err);
#endif
static const char ICANN_UPDATE_CA[] =
/* The ICANN CA fetched at 29 May 2026. Valid to 20 Mar 2045 */
/* The ICANN CA fetched at 24 Sep 2010. Valid to 2028 */
"-----BEGIN CERTIFICATE-----\n"
"MIIDdzCCAl+gAwIBAgIBATANBgkqhkiG9w0BAQsFADBdMQ4wDAYDVQQKEwVJQ0FO\n"
"TjEmMCQGA1UECxMdSUNBTk4gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxFjAUBgNV\n"
@@ -177,40 +177,6 @@ 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[] =
@@ -1708,116 +1674,18 @@ 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))) {
# 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;
if(s->length > 0) {
val = s->data[0];
if(s->length > 1)
val |= s->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)
@@ -1837,9 +1705,6 @@ 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];
@@ -1852,29 +1717,17 @@ 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)) > 0)
NID_commonName, buf, (int)sizeof(buf)))
printf("commonName: %s\n", buf);
if(verb >= 3 && X509_NAME_get_text_by_NID(nm,
NID_pkcs9_emailAddress, buf, (int)sizeof(buf)) > 0)
NID_pkcs9_emailAddress, buf, (int)sizeof(buf)))
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) {
@@ -1888,23 +1741,16 @@ 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 !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,
if(!X509_NAME_get_text_by_NID(nm,
NID_pkcs9_emailAddress,
buf, (int)sizeof(buf)) <= 0) {
if(verb) printf("removed cert with no emailaddress\n");
buf, (int)sizeof(buf))) {
if(verb) printf("removed cert with no name\n");
continue; /* no name, no use */
}
if(strcmp(buf, p7signer) != 0) {
if(verb) printf("removed cert with wrong emailaddress\n");
if(verb) printf("removed cert with wrong name\n");
continue; /* wrong name, skip it */
}
#endif
}
/* check that the key usage allows digital signatures
@@ -2584,20 +2430,12 @@ int main(int argc, char* argv[])
#else
OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS
| OPENSSL_INIT_ADD_ALL_DIGESTS
| OPENSSL_INIT_LOAD_CRYPTO_STRINGS
# if defined(OPENSSL_INIT_NO_LOAD_CONFIG) && defined(UB_ON_WINDOWS)
| OPENSSL_INIT_NO_LOAD_CONFIG
# endif
, NULL);
| OPENSSL_INIT_LOAD_CRYPTO_STRINGS, NULL);
#endif
#if OPENSSL_VERSION_NUMBER < 0x10100000 || !defined(HAVE_OPENSSL_INIT_SSL)
(void)SSL_library_init();
#else
(void)OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS
# if defined(OPENSSL_INIT_NO_LOAD_CONFIG) && defined(UB_ON_WINDOWS)
| OPENSSL_INIT_NO_LOAD_CONFIG
# endif
, NULL);
(void)OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS, NULL);
#endif
if(dolist) do_list_builtin();

Some files were not shown because too many files have changed in this diff Show More