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
324 changed files with 11865 additions and 28771 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
+409 -560
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 -505
View File
File diff suppressed because it is too large Load Diff
+8 -118
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],[1])
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=40
LIBUNBOUND_REVISION=35
LIBUNBOUND_AGE=1
# 1.0.0 had 0:12:0
# 1.0.1 had 0:13:0
@@ -122,11 +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
# 1.26.1 had 9:40:1
# Current -- the number of the binary API that we're implementing
# Revision -- which iteration of the implementation of the binary
@@ -366,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"])
@@ -485,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],,, [
@@ -735,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
@@ -1082,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], [], [], [
@@ -1713,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" ])
@@ -1727,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
@@ -1749,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
@@ -1870,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
@@ -1941,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;
}
+54 -344
View File
@@ -77,20 +77,20 @@
#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"
#include "services/view.h"
#include "services/modstack.h"
#include "services/authzone.h"
#include "services/authload.h"
#include "util/module.h"
#include "util/random.h"
#include "util/tube.h"
#include "util/net_help.h"
#include "util/tsig.h"
#include "sldns/keyraw.h"
#include "respip/respip.h"
#include "iterator/iter_fwd.h"
@@ -201,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)
{
@@ -498,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 */
@@ -511,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())
@@ -568,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));
@@ -576,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);
@@ -586,18 +328,20 @@ 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->auth_load_info = auth_load_info_create())) {
edns_strings_delete(daemon->env->edns_strings);
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;
@@ -838,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);
@@ -872,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. */
@@ -916,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.
@@ -945,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 */
@@ -967,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;
@@ -1029,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 */
@@ -1043,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();
@@ -1085,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 */
@@ -1115,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.
@@ -1146,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]);
@@ -1192,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
@@ -1233,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;
@@ -1244,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;
}
@@ -1273,20 +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);
}
auth_load_info_delete(daemon->auth_load_info);
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();
@@ -1298,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
@@ -1321,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 -47
View File
@@ -62,8 +62,6 @@ struct doq_table;
struct cookie_secrets;
struct fast_reload_thread;
struct fast_reload_printq;
struct auth_load_general_info;
struct shared_ports;
#include "dnstap/dnstap_config.h"
#ifdef USE_DNSTAP
@@ -99,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 */
@@ -111,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 */
@@ -149,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 */
@@ -159,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 */
@@ -192,8 +171,6 @@ struct daemon {
int fast_reload_tcl_has_changes;
/** config file name */
char* cfgfile;
/** Auth load threads, the number of active threads. */
struct auth_load_general_info* auth_load_info;
};
/**
@@ -254,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 */
+440 -597
View File
File diff suppressed because it is too large Load Diff
+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);
-1026
View File
File diff suppressed because it is too large Load Diff
+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);
+37 -91
View File
@@ -51,28 +51,18 @@
#include "util/config_file.h"
#include "services/cache/dns.h"
#include "sldns/wire2str.h"
#ifdef HAVE_SYS_WAIT_H
#include <sys/wait.h>
#endif
/** Apply configuration to ipsecmod module 'global' state. */
static int
ipsecmod_apply_cfg(struct ipsecmod_env* ipsecmod_env, struct config_file* cfg)
{
if(cfg->ipsecmod_whitelist &&
!ipsecmod_whitelist_apply_cfg(ipsecmod_env, cfg))
return 0;
if(!cfg->ipsecmod_enabled)
return 1;
if(!cfg->ipsecmod_hook || (cfg->ipsecmod_hook && !cfg->ipsecmod_hook[0])) {
log_err("ipsecmod: missing ipsecmod-hook.");
return 0;
}
if(access(cfg->ipsecmod_hook, X_OK) != 0) {
log_err("ipsecmod: ipsecmod-hook '%s' is not an executable file: %s",
cfg->ipsecmod_hook, strerror(errno));
if(cfg->ipsecmod_whitelist &&
!ipsecmod_whitelist_apply_cfg(ipsecmod_env, cfg))
return 0;
}
return 1;
}
@@ -260,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);
@@ -282,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
@@ -310,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. */
@@ -334,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;
@@ -342,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) {
@@ -379,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;
}
@@ -481,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. */
@@ -628,8 +576,6 @@ ipsecmod_inform_super(struct module_qstate* qstate, int id,
verbose(VERB_ALGO, "super has no ipsecmod state");
return;
}
if(!siq->enabled)
return;
if(qstate->return_msg) {
struct ub_packed_rrset_key* rrset_key = reply_find_answer_rrset(
+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;
-49
View File
@@ -1,49 +0,0 @@
/*
* libunbound/authload.h - prototypes for auth load methods.
*
* Copyright (c) 2026, NLnet Labs. All rights reserved.
*
* This software is open source.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of the NLNET LABS nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* \file
*
* This file declares the methods that must be implemented to use the
* auth load service.
*/
#ifndef LIBUNBOUND_AUTHLOAD_H
#define LIBUNBOUND_AUTHLOAD_H
/** The worker routine that services the auth load connection. */
void worker_auth_load_service_cb(int fd, short bits, void* arg);
#endif /* LIBUNBOUND_AUTHLOAD_H */
+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
-8
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"
@@ -608,8 +603,6 @@ rm -rf .git .travis.yml .gitattributes .github .gitignore || error_cleanup "Fail
info "Adding libtool utils (libtoolize)."
libtoolize -c --install || libtoolize -c || error_cleanup "Libtoolize failed."
# Turn this off, if the git repo times out for lookups.
if test "updateconfigsub" = "false"; then
# https://www.gnu.org/software/gettext/manual/html_node/config_002eguess.html
info "Updating config.guess and config.sub"
wget -O config.guess 'https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD'
@@ -623,7 +616,6 @@ if [ `uname -s | grep -i -c darwin` -ne 0 ]; then
xattr -d com.apple.quarantine config.sub
fi
fi
fi
info "Building configure script (autoreconf)."
autoreconf -f || error_cleanup "Autoconf failed."
+15 -16
View File
@@ -79,7 +79,7 @@
i+(int)((unsigned int)name[i]) < len) {
memmove(buf, name + i + 1, (unsigned int)name[i]);
buf[(unsigned int)name[i]] = 0;
PyList_SetItem(list, cnt, PyUnicode_FromString(buf));
PyList_SetItem(list, cnt, PyString_FromString(buf));
}
i += ((unsigned int)name[i]) + 1;
cnt++;
@@ -96,7 +96,7 @@
list = PyList_New(len);
for (i=0; i < len; i++) {
PyList_SET_ITEM(list, i, PyUnicode_FromString(array[i]));
PyList_SET_ITEM(list, i, PyString_FromString(array[i]));
}
return list;
}
@@ -207,7 +207,7 @@ struct query_info {
char buf[LDNS_MAX_DOMAINLEN];
buf[0] = '\0';
dname_str((uint8_t*)PyBytes_AsString(dname), buf);
return PyUnicode_FromString(buf);
return PyString_FromString(buf);
}
%}
@@ -345,7 +345,7 @@ struct packed_rrset_data {
PyObject* _get_data_rr_len(struct packed_rrset_data* d, int idx) {
if ((d != NULL) && (idx >= 0) &&
((size_t)idx < (d->count+d->rrsig_count)))
return PyLong_FromLong(d->rr_len[idx]);
return PyInt_FromLong(d->rr_len[idx]);
return Py_None;
}
void _set_data_rr_ttl(struct packed_rrset_data* d, int idx, uint32_t ttl)
@@ -357,7 +357,7 @@ struct packed_rrset_data {
PyObject* _get_data_rr_ttl(struct packed_rrset_data* d, int idx) {
if ((d != NULL) && (idx >= 0) &&
((size_t)idx < (d->count+d->rrsig_count)))
return PyLong_FromLong(d->rr_ttl[idx]);
return PyInt_FromLong(d->rr_ttl[idx]);
return Py_None;
}
PyObject* _get_data_rr_data(struct packed_rrset_data* d, int idx) {
@@ -555,12 +555,12 @@ struct sockaddr_storage {};
if (ss->ss_family == AF_INET) {
const struct sockaddr_in *sa4 = (struct sockaddr_in *)ss;
return PyLong_FromLong(ntohs(sa4->sin_port));
return PyInt_FromLong(ntohs(sa4->sin_port));
}
if (ss->ss_family == AF_INET6) {
const struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)ss;
return PyLong_FromLong(ntohs(sa6->sin6_port));
return PyInt_FromLong(ntohs(sa6->sin6_port));
}
return Py_None;
@@ -574,7 +574,7 @@ struct sockaddr_storage {};
}
sa6 = (struct sockaddr_in6 *)ss;
return PyLong_FromLong(ntohl(sa6->sin6_flowinfo));
return PyInt_FromLong(ntohl(sa6->sin6_flowinfo));
}
PyObject *_sockaddr_storage_scope_id(const struct sockaddr_storage *ss) {
@@ -585,7 +585,7 @@ struct sockaddr_storage {};
}
sa6 = (struct sockaddr_in6 *)ss;
return PyLong_FromLong(ntohl(sa6->sin6_scope_id));
return PyInt_FromLong(ntohl(sa6->sin6_scope_id));
}
%}
@@ -661,7 +661,7 @@ struct edns_option {
%inline %{
PyObject* _edns_option_opt_code_get(struct edns_option* option) {
uint16_t opt_code = option->opt_code;
return PyLong_FromLong(opt_code);
return PyInt_FromLong(opt_code);
}
PyObject* _edns_option_opt_data_get(struct edns_option* option) {
@@ -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,
@@ -1627,7 +1626,7 @@ int edns_opt_list_append(struct edns_option** list, uint16_t code, size_t len,
}
result = PyObject_Call(func, py_args, py_kwargs);
if (result) {
res = PyLong_AsLong(result);
res = PyInt_AsLong(result);
}
out:
Py_XDECREF(py_edns);
@@ -1711,7 +1710,7 @@ out:
}
result = PyObject_Call(func, py_args, py_kwargs);
if (result) {
res = PyLong_AsLong(result);
res = PyInt_AsLong(result);
}
out:
Py_XDECREF(py_qinfo);
@@ -1765,7 +1764,7 @@ out:
}
result = PyObject_Call(func, py_args, py_kwargs);
if (result) {
res = PyLong_AsLong(result);
res = PyInt_AsLong(result);
}
out:
Py_XDECREF(py_qstate);
@@ -1814,7 +1813,7 @@ out:
}
result = PyObject_Call(func, py_args, py_kwargs);
if (result) {
res = PyLong_AsLong(result);
res = PyInt_AsLong(result);
}
out:
Py_XDECREF(py_qstate);
+5 -18
View File
@@ -246,14 +246,14 @@ log_py_err(void)
}
/* And it should be a string all ready to go - duplicate it. */
if (!PyBytes_Check(obResult) && !PyUnicode_Check(obResult)) {
if (!PyString_Check(obResult) && !PyUnicode_Check(obResult)) {
log_err("pythonmod: cannot print exception, "
"StringIO.getvalue() result did not String_Check"
" or Unicode_Check");
goto cleanup;
}
if(PyBytes_Check(obResult)) {
result = PyBytes_AsString(obResult);
if(PyString_Check(obResult)) {
result = PyString_AsString(obResult);
} else {
ascstr = PyUnicode_AsASCIIString(obResult);
result = PyBytes_AsString(ascstr);
@@ -450,7 +450,7 @@ int pythonmod_init(struct module_env* env, int id)
pe->data = PyDict_New();
/* add the script filename to the global "mod_env" for trivial access */
fname = PyUnicode_FromString(pe->fname);
fname = PyString_FromString(pe->fname);
if(PyDict_SetItemString(pe->data, "script", fname) < 0) {
log_err("pythonmod: could not add item to dictionary");
Py_XDECREF(fname);
@@ -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;
-921
View File
@@ -1,921 +0,0 @@
/*
* services/authload.c - authoritative zone load thread
*
* Copyright (c) 2026, NLnet Labs. All rights reserved.
*
* This software is open source.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of the NLNET LABS nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* \file
*
* This file contains the auth load thread. This loads authority zone
* and RPZ zone information in a thread, in a separate memory structure.
* When it is done, the information is swapped over to the running server.
*/
#include "config.h"
#include "services/authload.h"
#include "daemon/worker.h"
#include "daemon/daemon.h"
#include "services/authzone.h"
#include "libunbound/authload.h"
#include "util/net_help.h"
#include "util/log.h"
#include "util/ub_event.h"
#include "util/timeval_func.h"
#include "util/data/dname.h"
/** Get memory use of buffer. */
static size_t
buffer_get_mem(struct sldns_buffer* buf)
{
if(!buf) return 0;
return sizeof(*buf) + (buf->_data?buf->_capacity:0);
}
/** Auth load notification to string, for descriptive purposes. */
static const char*
auth_load_notification_to_string(enum auth_load_notification_type status)
{
switch(status) {
case auth_load_notification_exit:
return "auth_load_notification_exit";
default:
break;
}
return "unknown_auth_load_notification_value";
}
/** delete chunks */
static void
auth_chunk_list_delete(struct auth_chunk* first)
{
struct auth_chunk* c = first, *cn;
while(c) {
cn = c->next;
free(c->data);
free(c);
c = cn;
}
}
/** Delete auth load task item */
static void
auth_load_task_delete(struct auth_load_task* task)
{
if(!task)
return;
free(task->name);
free(task->host);
free(task->file);
auth_chunk_list_delete(task->chunks_first);
free(task);
}
/** Create new auth load task item */
static struct auth_load_task*
auth_load_task_create(void)
{
struct auth_load_task* task = (struct auth_load_task*)calloc(1,
sizeof(*task));
return task;
}
/** Pick up the work content of task transfer of auth xfr */
static int
auth_load_task_pickup_xfr(struct auth_load_task* task, struct auth_xfer* xfr)
{
task->name = memdup(xfr->name, xfr->namelen);
if(!task->name)
return 0;
task->namelen = xfr->namelen;
task->dclass = xfr->dclass;
if(xfr->task_transfer->master && xfr->task_transfer->master->host) {
task->host = strdup(xfr->task_transfer->master->host);
if(!task->host)
return 0;
}
if(xfr->task_transfer->master && xfr->task_transfer->master->file) {
task->file = strdup(xfr->task_transfer->master->file);
if(!task->file)
return 0;
}
if(xfr->task_transfer->master)
task->on_http = xfr->task_transfer->master->http;
task->on_ixfr = xfr->task_transfer->on_ixfr;
task->on_ixfr_is_axfr = xfr->task_transfer->on_ixfr_is_axfr;
task->serial = xfr->serial;
if(xfr->task_transfer->chunks_first) {
task->chunks_first = xfr->task_transfer->chunks_first;
task->chunks_last = xfr->task_transfer->chunks_last;
task->chunks_total = xfr->task_transfer->chunks_total;
/* The task now has the chunks. Remove them from the
* xfr structure. */
xfr->task_transfer->chunks_first = 0;
xfr->task_transfer->chunks_last = 0;
xfr->task_transfer->chunks_total = 0;
}
if(task->on_http)
task->task_type = AUTH_LOAD_TASK_HTTPCHUNKS;
else task->task_type = AUTH_LOAD_TASK_TRANSFER;
return 1;
}
/** Create xfr task */
static struct auth_load_task*
auth_load_task_create_xfr(struct auth_xfer* xfr, struct worker* worker)
{
struct auth_load_task* task = auth_load_task_create();
if(!task) {
log_err("out of memory");
return 0;
}
task->worker = worker;
if(!auth_load_task_pickup_xfr(task, xfr)) {
log_err("out of memory");
auth_load_task_delete(task);
return 0;
}
return task;
}
int
auth_load_thread_poll_for_quit(struct auth_load_thread* thr)
{
int inevent, loopexit = 0;
uint8_t cmd;
ssize_t ret;
if(!thr)
return 0;
if(thr->need_to_quit)
return 1;
/* Is there data? */
if(!sock_poll_timeout(thr->commpair[1], 0, 1, 0, &inevent)) {
log_err("auth_load_thread_poll_for_quit: poll failed");
return 0;
}
if(!inevent)
return 0;
/* Read the data */
while(1) {
if(++loopexit > 200) {
log_err("auth_load_thread_poll_for_quit: recv loops %s",
sock_strerror(errno));
return 0;
}
ret = recv(thr->commpair[1], ((char*)&cmd), sizeof(cmd), 0);
if(ret == -1) {
if(
#ifndef USE_WINSOCK
errno == EINTR || errno == EAGAIN
# ifdef EWOULDBLOCK
|| errno == EWOULDBLOCK
# endif
#else
WSAGetLastError() == WSAEINTR ||
WSAGetLastError() == WSAEINPROGRESS ||
WSAGetLastError() == WSAEWOULDBLOCK
#endif
)
continue; /* Try again. */
log_err("auth_load_thread_poll_for_quit: recv: %s",
sock_strerror(errno));
return 0;
} else if(ret == 0) {
log_err("auth_load_thread_poll_for_quit: recv: EOF");
return 0;
}
break;
}
if(cmd == auth_load_notification_exit) {
thr->need_to_quit = 1;
verbose(VERB_ALGO, "auth load: exit notification received");
return 1;
}
log_err("auth_load_thread_poll_for_quit: unknown notification status "
"received: %d %s", cmd, auth_load_notification_to_string(cmd));
return 0;
}
/** Signal the worker connected to an auth load thread the status */
static void
auth_load_thread_signal_worker(struct auth_load_thread* thr, int status)
{
int outevent, loopexit = 0;
ssize_t ret;
uint8_t to_send;
verbose(VERB_ALGO, "auth load thread: send status %d", status);
/* Make a blocking attempt to send. But meanwhile stay responsive,
* once in a while for quit commands. In case the server has to quit. */
/* see if there is incoming quit signals */
if(auth_load_thread_poll_for_quit(thr))
return;
to_send = (uint8_t)status;
while(1) {
if(++loopexit > 200) {
log_err("auth load thread: could not send status");
return;
}
/* wait for socket to become writable */
if(!sock_poll_timeout(thr->commpair[1],
200, /* msec wait before check for quit, and loop to
wait again. */
0, 1, &outevent)) {
log_err("auth load thread: poll failed");
return;
}
if(auth_load_thread_poll_for_quit(thr))
return;
if(!outevent)
continue;
ret = send(thr->commpair[1], &to_send, 1, 0);
if(ret == -1) {
if(
#ifndef USE_WINSOCK
errno == EINTR || errno == EAGAIN
# ifdef EWOULDBLOCK
|| errno == EWOULDBLOCK
# endif
#else
WSAGetLastError() == WSAEINTR ||
WSAGetLastError() == WSAEINPROGRESS ||
WSAGetLastError() == WSAEWOULDBLOCK
#endif
)
continue; /* Try again. */
log_err("auth load thread signal worker: send: %s",
sock_strerror(errno));
return;
} else if(ret < 1) {
continue;
}
break;
}
}
/** Create proxy auth zone structure, that is used to hold the data
* that is processed. */
static struct auth_zone*
auth_zone_create_proxy(uint8_t* nm, size_t nmlen, uint16_t dclass)
{
struct auth_zone* z = (struct auth_zone*)calloc(1, sizeof(*z));
if(!z) {
return NULL;
}
z->node.key = z;
z->dclass = dclass;
z->namelen = nmlen;
z->namelabs = dname_count_labels(nm);
z->name = memdup(nm, nmlen);
if(!z->name) {
free(z);
return NULL;
}
rbtree_init(&z->data, &auth_data_cmp);
return z;
}
/** Delete proxy auth zone structure */
static void
auth_zone_delete_proxy(struct auth_zone* z)
{
if(!z)
return;
traverse_postorder(&z->data, auth_data_del, NULL);
if(z->rpz)
rpz_delete(z->rpz);
free(z->name);
free(z);
}
/** Calculate memory use of the authload thread for this task.
* The size of the task struct, with the data chunks, and the proxy auth zone
* structure that is created while the other auth zone is used for queries,
* and other added memory.
*/
static void
auth_load_calc_mem(struct auth_load_task* task, struct auth_zone* z,
size_t other)
{
size_t m = 0;
if(verbosity < 8) {
task->mem_used = 0;
return;
}
m += other;
m += sizeof(*task);
m += task->namelen;
m += getmem_str(task->host);
m += getmem_str(task->file);
m += task->chunks_total;
m += auth_zone_get_mem(z);
task->mem_used = m;
}
/** Swap the final zone contents with the live zone */
static void
auth_load_swap_zone(struct auth_load_thread* thr, struct auth_zone* proxyz)
{
rbtree_type data;
struct rpz* rpz;
struct auth_zone* z;
lock_rw_rdlock(&thr->task->worker->env.auth_zones->lock);
z = auth_zone_find(thr->task->worker->env.auth_zones,
thr->task->name, thr->task->namelen, thr->task->dclass);
if(!z) {
lock_rw_unlock(&thr->task->worker->env.auth_zones->lock);
verbose(VERB_ALGO, "auth zone missing after auth load.");
return;
}
lock_rw_wrlock(&z->lock);
lock_rw_unlock(&thr->task->worker->env.auth_zones->lock);
data = proxyz->data;
proxyz->data = z->data;
z->data = data;
rpz = proxyz->rpz;
proxyz->rpz = z->rpz;
z->rpz = rpz;
lock_rw_unlock(&z->lock);
}
/** Process http transfer */
static int
auth_load_process_http(struct auth_load_thread* thr)
{
struct auth_load_task* task = thr->task;
struct sldns_buffer* scratch_buffer;
struct auth_zone* z;
size_t scratch_mem;
scratch_buffer = sldns_buffer_new(sldns_buffer_capacity(
thr->task->worker->env.scratch_buffer));
if(!scratch_buffer) {
log_err("out of memory");
return 0;
}
scratch_mem = buffer_get_mem(scratch_buffer);
z = auth_zone_create_proxy(task->name, task->namelen, task->dclass);
if(!z) {
log_err("out of memory");
sldns_buffer_free(scratch_buffer);
return 0;
}
if(auth_load_thread_poll_for_quit(thr)) {
sldns_buffer_free(scratch_buffer);
auth_zone_delete_proxy(z);
return 0;
}
xfr_http_preview(task->file, task->chunks_first);
if(!xfr_http_syntax_check(task->name, task->namelen, task->dclass,
task->host, task->file, task->chunks_first, scratch_buffer)) {
sldns_buffer_free(scratch_buffer);
auth_zone_delete_proxy(z);
return 0;
}
if(auth_load_thread_poll_for_quit(thr)) {
sldns_buffer_free(scratch_buffer);
auth_zone_delete_proxy(z);
return 0;
}
if(!xfr_apply_http(task->name, task->namelen, task->host, task->file,
task->chunks_first, z, scratch_buffer, thr)) {
sldns_buffer_free(scratch_buffer);
auth_zone_delete_proxy(z);
return 0;
}
sldns_buffer_free(scratch_buffer);
if(z->rpz)
rpz_finish_config(z->rpz);
if(auth_load_thread_poll_for_quit(thr)) {
auth_zone_delete_proxy(z);
return 0;
}
auth_load_calc_mem(task, z, scratch_mem);
auth_load_swap_zone(thr, z);
auth_zone_delete_proxy(z);
return 1;
}
/** Copy RRset and append it to the domain, update last pointer. */
static int
rrset_append_copy(struct auth_data* domain, struct auth_rrset* rrset,
struct auth_rrset** last)
{
struct auth_rrset* s = calloc(1, sizeof(*s));
if(!s)
return 0;
s->type = rrset->type;
s->data = (struct packed_rrset_data*)memdup(rrset->data,
packed_rrset_sizeof(rrset->data));
if(!s->data) {
free(s);
return 0;
}
packed_rrset_ptr_fixup(s->data);
if(!*last)
domain->rrsets = s;
else (*last)->next = s;
*last = s;
return 1;
}
/** Copy the existing zone for modification */
static int
auth_load_copy_into_zone(struct auth_load_thread* thr, struct auth_zone* proxyz)
{
int count = 0;
struct auth_zone* z;
struct auth_data* d;
lock_rw_rdlock(&thr->task->worker->env.auth_zones->lock);
z = auth_zone_find(thr->task->worker->env.auth_zones,
thr->task->name, thr->task->namelen, thr->task->dclass);
if(!z) {
lock_rw_unlock(&thr->task->worker->env.auth_zones->lock);
verbose(VERB_ALGO, "auth zone missing for copy for IXFR.");
return 0;
}
lock_rw_rdlock(&z->lock);
lock_rw_unlock(&thr->task->worker->env.auth_zones->lock);
/* Copy from z into proxyz. */
RBTREE_FOR(d, struct auth_data*, &z->data) {
struct auth_rrset* rrset, *last = NULL;
struct auth_data* proxy_d = az_domain_create(proxyz,
d->name, d->namelen);
if(!proxy_d) {
log_err("out of memory");
lock_rw_unlock(&z->lock);
return 0;
}
for(rrset = d->rrsets; rrset; rrset=rrset->next) {
if(!rrset_append_copy(proxy_d, rrset, &last)) {
log_err("out of memory");
lock_rw_unlock(&z->lock);
return 0;
}
if((count++)%10000 == 0) {
if(auth_load_thread_poll_for_quit(thr)) {
lock_rw_unlock(&z->lock);
return 0;
}
}
}
if((count++)%10000 == 0) {
if(auth_load_thread_poll_for_quit(thr)) {
lock_rw_unlock(&z->lock);
return 0;
}
}
}
lock_rw_unlock(&z->lock);
return 1;
}
/** Process ixfr transfer */
static int
auth_load_process_ixfr(struct auth_load_thread* thr)
{
struct auth_load_task* task = thr->task;
struct sldns_buffer* scratch_buffer;
struct auth_zone* z;
size_t scratch_mem;
scratch_buffer = sldns_buffer_new(sldns_buffer_capacity(
thr->task->worker->env.scratch_buffer));
if(!scratch_buffer) {
log_err("out of memory");
return 0;
}
scratch_mem = buffer_get_mem(scratch_buffer);
z = auth_zone_create_proxy(task->name, task->namelen, task->dclass);
if(!z) {
log_err("out of memory");
sldns_buffer_free(scratch_buffer);
return 0;
}
if(auth_load_thread_poll_for_quit(thr)) {
sldns_buffer_free(scratch_buffer);
auth_zone_delete_proxy(z);
return 0;
}
/* Copy the existing zone for modification, that uses a read lock.
* That then does not interrupt the service of threads. */
if(!auth_load_copy_into_zone(thr, z)) {
sldns_buffer_free(scratch_buffer);
auth_zone_delete_proxy(z);
return 0;
}
if(!xfr_apply_ixfr(task->chunks_first, task->serial, z,
scratch_buffer, thr)) {
sldns_buffer_free(scratch_buffer);
auth_zone_delete_proxy(z);
return 0;
}
sldns_buffer_free(scratch_buffer);
if(auth_load_thread_poll_for_quit(thr)) {
auth_zone_delete_proxy(z);
return 0;
}
auth_load_calc_mem(task, z, scratch_mem);
auth_load_swap_zone(thr, z);
auth_zone_delete_proxy(z);
return 1;
}
/** Process axfr transfer */
static int
auth_load_process_axfr(struct auth_load_thread* thr)
{
struct auth_load_task* task = thr->task;
struct sldns_buffer* scratch_buffer;
struct auth_zone* z;
size_t scratch_mem;
scratch_buffer = sldns_buffer_new(sldns_buffer_capacity(
thr->task->worker->env.scratch_buffer));
if(!scratch_buffer) {
log_err("out of memory");
return 0;
}
scratch_mem = buffer_get_mem(scratch_buffer);
z = auth_zone_create_proxy(task->name, task->namelen, task->dclass);
if(!z) {
log_err("out of memory");
sldns_buffer_free(scratch_buffer);
return 0;
}
if(auth_load_thread_poll_for_quit(thr)) {
sldns_buffer_free(scratch_buffer);
auth_zone_delete_proxy(z);
return 0;
}
if(!xfr_apply_axfr(task->chunks_first, z, scratch_buffer, thr)) {
sldns_buffer_free(scratch_buffer);
auth_zone_delete_proxy(z);
return 0;
}
sldns_buffer_free(scratch_buffer);
if(auth_load_thread_poll_for_quit(thr)) {
auth_zone_delete_proxy(z);
return 0;
}
auth_load_calc_mem(task, z, scratch_mem);
auth_load_swap_zone(thr, z);
auth_zone_delete_proxy(z);
return 1;
}
/** In the auth load thread, process the task */
static int
auth_load_thread_process(struct auth_load_thread* thr)
{
struct auth_load_task* task = thr->task;
struct timeval start, end;
if(gettimeofday(&start, NULL) < 0)
log_err("gettimeofday: %s", strerror(errno));
/* apply data */
if(task->on_http) {
if(!auth_load_process_http(thr))
return 0;
} else if(task->on_ixfr && !task->on_ixfr_is_axfr) {
if(!auth_load_process_ixfr(thr))
return 0;
} else {
if(!auth_load_process_axfr(thr))
return 0;
}
if(gettimeofday(&end, NULL) < 0)
log_err("gettimeofday: %s", strerror(errno));
timeval_subtract(&thr->task->time_taken, &end, &start);
return 1;
}
/** The auth load thread. The thread main function. */
static void*
auth_load_thread_main(void* arg)
{
struct auth_load_thread* thr = (struct auth_load_thread*)arg;
int s;
const char name[16] = "unbound/authld"; /* seems to be the safest size
between different OSes */
#if defined(HAVE_GETTID) && !defined(THREADS_DISABLED)
thr->thread_tid = gettid();
if(thr->thread_tid_log)
log_thread_set(&thr->thread_tid);
else
#endif
log_thread_set(&thr->threadnum);
ub_thread_setname(ub_thread_self(), name);
(void)name; /* When setname is not defined, ignore the name variable. */
verbose(VERB_ALGO, "start auth load thread");
s = auth_load_thread_process(thr);
/* The result is sent to the worker, that reaps the thread. */
auth_load_thread_signal_worker(thr, s);
verbose(VERB_ALGO, "stop auth load thread");
return NULL;
}
/** Delete auth load thread structure */
static void
auth_load_thread_delete(struct auth_load_thread* thr)
{
if(!thr)
return;
if(thr->service_event && thr->service_event_is_added) {
ub_event_del(thr->service_event);
thr->service_event_is_added = 0;
}
if(thr->service_event)
ub_event_free(thr->service_event);
if(thr->commpair[0] != -1)
sock_close(thr->commpair[0]);
if(thr->commpair[1] != -1)
sock_close(thr->commpair[1]);
auth_load_task_delete(thr->task);
free(thr);
}
/** Create auth load thread structure */
static struct auth_load_thread*
auth_load_thread_create(struct auth_load_task* task)
{
int numworkers;
struct auth_load_thread* thr = (struct auth_load_thread*)calloc(1,
sizeof(*thr));
if(!thr)
return NULL;
numworkers = task->worker->daemon->num;
/* This number is printed into the logs */
thr->threadnum = numworkers+3;
thr->task = task;
thr->commpair[0] = -1;
thr->commpair[1] = -1;
if(!create_socketpair(thr->commpair, task->worker->daemon->rand)) {
auth_load_thread_delete(thr);
return NULL;
}
#ifdef HAVE_GETTID
thr->thread_tid_log = task->worker->env.cfg->log_thread_id;
#endif
return thr;
}
/** The worker routine that services the auth load connection. */
void
worker_auth_load_service_cb(int ATTR_UNUSED(fd), short ATTR_UNUSED(bits),
void* arg)
{
struct auth_load_thread* thr = (struct auth_load_thread*)arg;
uint8_t recv_item;
ssize_t ret;
struct auth_xfer* xfr;
struct auth_chunk* chunk_list;
struct module_env* env = &thr->task->worker->env;
int ixfr_fail;
struct timeval time_taken;
size_t mem_used, chunks_total;
log_assert(thr->commpair[0] >= 0);
ret = recv(thr->commpair[0], &recv_item, 1, 0);
if(ret == -1) {
if(
#ifndef USE_WINSOCK
errno == EINTR || errno == EAGAIN
# ifdef EWOULDBLOCK
|| errno == EWOULDBLOCK
# endif
#else
WSAGetLastError() == WSAEINTR ||
WSAGetLastError() == WSAEINPROGRESS
#endif
)
return; /* Continue later. */
#ifdef USE_WINSOCK
if(WSAGetLastError() == WSAEWOULDBLOCK) {
ub_winsock_tcp_wouldblock(thr->service_event,
UB_EV_READ);
return; /* Continue later. */
}
#endif
log_err("read status from auth load thread, recv: %s",
sock_strerror(errno));
return;
} else if(ret == 0) {
verbose(VERB_ALGO, "closed connection from auth load thread");
/* handle this like an error */
recv_item = 0;
/* ret<1: No short read on 1 byte, to continue later on */
}
/* Deal with the result of auth load thread */
verbose(VERB_ALGO, "auth load status is %d", (int)recv_item);
verbose(VERB_ALGO, "join with auth load thread");
ub_thread_join(thr->tid);
verbose(VERB_ALGO, "joined with auth load thread");
lock_rw_rdlock(&thr->task->worker->env.auth_zones->lock);
xfr = auth_xfer_find(thr->task->worker->env.auth_zones,
thr->task->name, thr->task->namelen, thr->task->dclass);
if(!xfr) {
lock_rw_unlock(&thr->task->worker->env.auth_zones->lock);
verbose(VERB_ALGO, "auth load: xfr is gone");
auth_load_thread_delete(thr);
auth_load_info_release_thread(env);
return;
}
lock_basic_lock(&xfr->lock);
lock_rw_unlock(&thr->task->worker->env.auth_zones->lock);
ixfr_fail = thr->task->ixfr_fail;
time_taken = thr->task->time_taken;
mem_used = thr->task->mem_used;
chunks_total = thr->task->chunks_total;
if(thr->task->on_http) {
chunk_list = thr->task->chunks_first;
thr->task->chunks_first = NULL;
thr->task->chunks_last = NULL;
thr->task->chunks_total = 0;
} else {
chunk_list = NULL;
}
auth_load_thread_delete(thr);
auth_load_info_release_thread(env);
xfr_process_load_end_transfer(xfr, env, recv_item, ixfr_fail,
&time_taken, mem_used, chunks_total, chunk_list);
}
/** Attach worker to the auth load thread. */
static int
auth_load_thread_attach(struct auth_load_thread* thr, struct worker* worker)
{
/* Setup listener in worker, that connects via a pipe to the
* auth load thread.
* The listener has to be nonblocking, so the the remote servicing
* thread can continue to service DNS queries.
* The commpair[1] element can stay blocking, it is used by the
* auth load thread. The thread needs to wait at these times, when
* it has to check briefly it can use poll. */
verbose(VERB_ALGO, "auth_load_thread_attach");
fd_set_nonblock(thr->commpair[0]);
if(!comm_base_internal(worker->base)) {
verbose(VERB_ALGO, "auth load thread: no event base");
return 0;
}
thr->service_event = ub_event_new(comm_base_internal(worker->base),
thr->commpair[0], UB_EV_READ | UB_EV_PERSIST,
worker_auth_load_service_cb, thr);
if(!thr->service_event) {
log_err("out of memory");
return 0;
}
if(ub_event_add(thr->service_event, NULL) != 0) {
log_err("out of memory");
return 0;
}
thr->service_event_is_added = 1;
return 1;
}
/** Create and start the auth load thread, with the task */
static int
auth_load_start_thread(struct auth_load_task* task)
{
struct auth_load_thread* thr = auth_load_thread_create(task);
if(!thr) {
log_err("out of memory");
auth_load_task_delete(task);
return 0;
}
if(!auth_load_thread_attach(thr, task->worker)) {
log_err("out of memory");
auth_load_thread_delete(thr);
return 0;
}
/* Start auth load thread */
ub_thread_create(&thr->tid, auth_load_thread_main, thr);
return 1;
}
int auth_load_add_task_xfr(struct auth_xfer* xfr, struct worker* worker)
{
struct auth_load_task* task;
int can_run = 0;
verbose(VERB_ALGO, "auth load add task");
/* Check auth load count */
can_run = 1;
/* Create new thread */
task = auth_load_task_create_xfr(xfr, worker);
if(!task)
return 0;
if(can_run) {
verbose(VERB_ALGO, "auth load start thread");
if(!auth_load_start_thread(task))
return 0;
verbose(VERB_ALGO, "auth load thread started");
return 1;
}
/* Make wait item */
return 0;
}
struct auth_load_general_info* auth_load_info_create(void)
{
struct auth_load_general_info* auth_load_info =
(struct auth_load_general_info*)calloc(1,
sizeof(*auth_load_info));
if(!auth_load_info) {
log_err("malloc failure");
return NULL;
}
lock_basic_init(&auth_load_info->lock);
lock_protect(&auth_load_info->lock,
&auth_load_info->num_auth_load_threads,
sizeof(auth_load_info->num_auth_load_threads));
return auth_load_info;
}
void auth_load_info_delete(struct auth_load_general_info* auth_load_info)
{
if(!auth_load_info)
return;
lock_basic_destroy(&auth_load_info->lock);
free(auth_load_info);
}
int auth_load_info_grab_thread(struct module_env* env)
{
struct auth_load_general_info* auth_load_info =
env->worker->daemon->auth_load_info;
struct config_file* cfg = env->cfg;
int ret = 0;
lock_basic_lock(&auth_load_info->lock);
if(auth_load_info->num_auth_load_threads < cfg->auth_task_threads) {
ret = 1;
auth_load_info->num_auth_load_threads++;
}
lock_basic_unlock(&auth_load_info->lock);
return ret;
}
void auth_load_info_release_thread(struct module_env* env)
{
struct auth_load_general_info* auth_load_info =
env->worker->daemon->auth_load_info;
lock_basic_lock(&auth_load_info->lock);
if(auth_load_info->num_auth_load_threads == 0) {
verbose(VERB_ALGO, "release of auth load thread, but "
"num_auth_load_threads not > 0.");
} else {
auth_load_info->num_auth_load_threads--;
}
lock_basic_unlock(&auth_load_info->lock);
}
-203
View File
@@ -1,203 +0,0 @@
/*
* services/authload.h - authoritative zone load thread
*
* Copyright (c) 2026, NLnet Labs. All rights reserved.
*
* This software is open source.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of the NLNET LABS nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* \file
*
* This file contains the auth load thread. This loads authority zone
* and RPZ zone information in a thread, in a separate memory structure.
* When it is done, the information is swapped over to the running server.
*/
#ifndef SERVICES_AUTHLOAD_H
#define SERVICES_AUTHLOAD_H
#include "util/locks.h"
struct worker;
struct auth_xfer;
struct module_env;
struct auth_load_task;
/**
* General information for auth load threads. The number of active threads.
*/
struct auth_load_general_info {
/** lock on this structure */
lock_basic_type lock;
/** The number of active auth load threads. */
int num_auth_load_threads;
};
/**
* The types of notifications that the auth load thread sends around.
*/
enum auth_load_notification_type {
/** This is sent to make the auth load thread perform exit */
auth_load_notification_exit
};
/**
* The auth load thread. The thread runs to load authority zone information
* and RPZ information into memory. It loads into a copy. Then that is swapped
* over to the running server. This keeps the server responsive while the
* information is loaded.
*/
struct auth_load_thread {
/** the thread number for the thread,
* must be first to cast thread arg to int* in checklock code. */
int threadnum;
/** thread id, of the io thread */
ub_thread_type tid;
#ifdef HAVE_GETTID
/** thread tid, the LWP id */
pid_t thread_tid;
/** if logging should include the LWP id */
int thread_tid_log;
#endif
/** communication socket pair, that sends commands */
int commpair[2];
/** if the thread has to quit */
int need_to_quit;
/** the event that listens on the worker to commpair,
* it receives content from the auth load thread. */
void* service_event;
/** if the event that listens on the worker has
* been added to the comm base. */
int service_event_is_added;
/** the worker that the auth load is connected to */
struct worker* worker;
/** The task that the thread is working on */
struct auth_load_task* task;
};
/**
* The types of tasks that the auth load can perform.
*/
enum auth_load_task_type {
AUTH_LOAD_TASK_TRANSFER,
AUTH_LOAD_TASK_ZONEFILE_READ,
AUTH_LOAD_TASK_ZONEFILE_WRITE,
AUTH_LOAD_TASK_HTTPCHUNKS
};
/**
* The task for the auth load. The task can be to load a zone transfer, AXFR,
* IXFR, from zonefile, and from a http read, from chunks.
*/
struct auth_load_task {
/** The type of the task */
enum auth_load_task_type task_type;
/** The task is connected with this worker */
struct worker* worker;
/** The zone name */
uint8_t* name;
/** The zone namelen */
size_t namelen;
/** The zone class */
uint16_t dclass;
/** name of the host that the transfer comes from. */
char* host;
/** file part of the url that the transfer comes from, or NULL. */
char* file;
/** Set if the host is http transfer, if false it is AXFR or IXFR. */
int on_http;
/** Set if the transfer is doing IXFR */
int on_ixfr;
/** Set if the transfer is an IXFR but we detected an AXFR contents */
int on_ixfr_is_axfr;
/** Set if the ixfr failed. (So that there can be backoff to AXFR). */
int ixfr_fail;
/** current serial (from SOA), if we have no zone, 0
* This is for checking the IXFR result. */
uint32_t serial;
/** the data chunks, or NULL, to process. */
struct auth_chunk* chunks_first;
/** last data chunk */
struct auth_chunk* chunks_last;
/** size of data in data chunks. */
size_t chunks_total;
/** time taken for the task */
struct timeval time_taken;
/** memory used for the task */
size_t mem_used;
};
/**
* Add a new task to be performed by the auth load thread.
* It starts a thread, or makes a wait list item.
* @param xfr: zone transfer to start for.
* @param worker: worker that is connected to the task.
* @return false on failure.
*/
int auth_load_add_task_xfr(struct auth_xfer* xfr, struct worker* worker);
/** See if there is a quit signal, true if so. */
int auth_load_thread_poll_for_quit(struct auth_load_thread* thr);
/**
* Create auth load info structure.
* @return NULL on failure.
*/
struct auth_load_general_info* auth_load_info_create(void);
/**
* Delete auth load info structure.
* @param auth_load_info: to delete.
*/
void auth_load_info_delete(struct auth_load_general_info* auth_load_info);
/**
* Grab a new thread from the auth load count.
* @param env: with auth_load_info with the active thread count.
* and config file, with configured maximum.
* @return false on failure, like too many active, true if successful.
*/
int auth_load_info_grab_thread(struct module_env* env);
/**
* Release thread from auth load count. It is done.
* @param env: with auth_load_info with the active thread count.
*/
void auth_load_info_release_thread(struct module_env* env);
#endif /* SERVICES_AUTHLOAD_H */
+482 -789
View File
File diff suppressed because it is too large Load Diff
+21 -71
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;
@@ -65,7 +67,6 @@ struct auth_probe;
struct auth_transfer;
struct auth_master;
struct auth_chunk;
struct auth_load_thread;
/**
* Authoritative zones, shared.
@@ -145,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 */
@@ -156,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;
};
/**
@@ -290,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;
};
/**
@@ -347,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),
@@ -379,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;
};
/**
@@ -397,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;
@@ -454,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 */
@@ -485,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;
};
@@ -514,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
@@ -643,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 */
@@ -695,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);
@@ -852,48 +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);
/** Get memory usage of auth zone */
size_t auth_zone_get_mem(struct auth_zone* z);
/** create domain with the given name */
struct auth_data* az_domain_create(struct auth_zone* z, uint8_t* nm,
size_t nmlen);
/** helper traverse to delete zones */
void auth_data_del(rbnode_type* n, void* arg);
/** Handle the end of an auth load task. */
void xfr_process_load_end_transfer(struct auth_xfer* xfr,
struct module_env* env, uint8_t status, int ixfr_fail,
struct timeval* time_taken, size_t mem_used, size_t chunks_total,
struct auth_chunk* chunk_list);
/** Log preview of http transfer */
void xfr_http_preview(const char* file, struct auth_chunk* chunk_list);
/** Check syntax of first part of the http download */
int xfr_http_syntax_check(uint8_t* name, size_t namelen, uint16_t dclass,
const char* host, const char* file, struct auth_chunk* chunk_list,
struct sldns_buffer* scratch_buffer);
/** Apply http transfer to auth_zone */
int xfr_apply_http(uint8_t* name, size_t namelen, const char* host,
const char* file, struct auth_chunk* chunk_list, struct auth_zone* z,
struct sldns_buffer* scratch_buffer, struct auth_load_thread* thr);
/** Apply IXFR transfer to auth_zone */
int xfr_apply_ixfr(struct auth_chunk* chunk_list, uint32_t xfr_serial,
struct auth_zone* z, struct sldns_buffer* scratch_buffer,
struct auth_load_thread* thr);
/** Apply AXFR transfer to auth_zone */
int xfr_apply_axfr(struct auth_chunk* chunk_list, struct auth_zone* z,
struct sldns_buffer* scratch_buffer, struct auth_load_thread* thr);
#endif /* SERVICES_AUTHZONE_H */
+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;
}
+105 -203
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;
@@ -1341,33 +1342,13 @@ ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp,
if((is_doq) && !(is_https || is_ssl)) do_tcp = 0;
if(do_auto) {
enum listen_type auto_port_type;
ub_sock = calloc(1, sizeof(struct unbound_socket));
if(!ub_sock)
return 0;
if(is_dnscrypt) {
auto_port_type = listen_type_udpancil_dnscrypt;
add = "udpancil_dnscrypt";
} else if(is_doq) {
auto_port_type = listen_type_doq;
add = "doq";
if(if_listens_on(ifname, port, 53, NULL)) {
log_err("DNS over QUIC is strictly not "
"allowed on port 53 as per RFC 9250. "
"Port 53 is for DNS datagrams. Error "
"for interface '%s'.", ifname);
free(ub_sock->addr);
free(ub_sock);
return 0;
}
} else {
auto_port_type = listen_type_udpancil;
add = "udpancil";
}
if((s = make_sock_port(SOCK_DGRAM, ifname, port, hints, 1,
&noip6, rcv, snd, reuseport, transparent,
tcp_mss, nodelay, freebind, use_systemd, dscp, ub_sock,
add)) == -1) {
(is_dnscrypt?"udpancil_dnscrypt":"udpancil"))) == -1) {
free(ub_sock->addr);
free(ub_sock);
if(noip6) {
@@ -1386,7 +1367,9 @@ ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp,
if (sock_queue_timeout && !set_recvtimestamp(s)) {
log_warn("socket timestamping is not available");
}
if(!port_insert(list, s, auto_port_type, is_pp2, ub_sock)) {
if(!port_insert(list, s, is_dnscrypt
?listen_type_udpancil_dnscrypt:listen_type_udpancil,
is_pp2, ub_sock)) {
sock_close(s);
free(ub_sock->addr);
free(ub_sock);
@@ -1581,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 "
@@ -2184,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;
}
@@ -2318,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
@@ -2889,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) {
@@ -2899,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)) {
@@ -3279,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;
}
@@ -3362,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) {
@@ -3417,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;
@@ -3471,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;
@@ -3517,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) {
@@ -3532,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. */
@@ -3615,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)
@@ -3657,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);
@@ -3737,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;
}
@@ -3800,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 {
@@ -3810,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;
@@ -3973,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",
@@ -4007,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) {
@@ -4018,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. */
@@ -4049,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: "
@@ -4143,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)) {
@@ -4160,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 */
@@ -4183,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 */
@@ -4332,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;
@@ -4399,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 */
@@ -4457,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) {
@@ -4527,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),
@@ -4870,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);
@@ -4924,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;
@@ -4979,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));
@@ -5014,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;
@@ -5202,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. */
@@ -5348,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;
@@ -5446,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);
@@ -5498,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);
@@ -5514,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;
@@ -5565,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);
@@ -5580,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;
}
@@ -5657,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;
@@ -5706,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));
@@ -5758,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

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