mirror of
https://github.com/NLnetLabs/unbound.git
synced 2026-10-18 14:27:18 +02:00
Compare commits
3
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4014e2aec4 | ||
|
|
f3c9be889f | ||
|
|
cd3ebb7e72 |
@@ -12,7 +12,6 @@ jobs:
|
|||||||
build:
|
build:
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
matrix:
|
||||||
include:
|
include:
|
||||||
- name: GCC on Linux
|
- name: GCC on Linux
|
||||||
@@ -33,12 +32,12 @@ jobs:
|
|||||||
- name: OS X
|
- name: OS X
|
||||||
os: macos-latest
|
os: macos-latest
|
||||||
install_expat: "yes"
|
install_expat: "yes"
|
||||||
config: "--enable-debug --disable-flto --with-ssl=/opt/homebrew/opt/openssl --with-libexpat=/opt/homebrew/opt/expat"
|
config: "--enable-debug --disable-flto --with-ssl=/usr/local/opt/openssl --with-libexpat=/usr/local/opt/expat"
|
||||||
make_test: "yes"
|
make_test: "yes"
|
||||||
- name: Clang on OS X
|
- name: Clang on OS X
|
||||||
os: macos-latest
|
os: macos-latest
|
||||||
install_expat: "yes"
|
install_expat: "yes"
|
||||||
config: "CC=clang --enable-debug --disable-flto --with-ssl=/opt/homebrew/opt/openssl --with-libexpat=/opt/homebrew/opt/expat --disable-static"
|
config: "CC=clang --enable-debug --disable-flto --with-ssl=/usr/local/opt/openssl --with-libexpat=/usr/local/opt/expat --disable-static"
|
||||||
make_test: "yes"
|
make_test: "yes"
|
||||||
clang_analysis: "yes"
|
clang_analysis: "yes"
|
||||||
- name: ubsan (gcc undefined behaviour sanitizer)
|
- name: ubsan (gcc undefined behaviour sanitizer)
|
||||||
@@ -49,6 +48,15 @@ jobs:
|
|||||||
os: ubuntu-latest
|
os: ubuntu-latest
|
||||||
config: 'CFLAGS="-DNDEBUG -g2 -O3 -fsanitize=address" --disable-flto --disable-static'
|
config: 'CFLAGS="-DNDEBUG -g2 -O3 -fsanitize=address" --disable-flto --disable-static'
|
||||||
make_test: "yes"
|
make_test: "yes"
|
||||||
|
- name: Apple iPhone on iOS, armv7
|
||||||
|
os: macos-latest
|
||||||
|
AUTOTOOLS_HOST: armv7-apple-ios
|
||||||
|
OPENSSL_HOST: ios-cross
|
||||||
|
IOS_SDK: iPhoneOS
|
||||||
|
IOS_CPU: armv7s
|
||||||
|
test_ios: "yes"
|
||||||
|
config: "no"
|
||||||
|
make: "no"
|
||||||
- name: Apple iPhone on iOS, arm64
|
- name: Apple iPhone on iOS, arm64
|
||||||
os: macos-latest
|
os: macos-latest
|
||||||
AUTOTOOLS_HOST: aarch64-apple-ios
|
AUTOTOOLS_HOST: aarch64-apple-ios
|
||||||
@@ -76,6 +84,15 @@ jobs:
|
|||||||
test_ios: "yes"
|
test_ios: "yes"
|
||||||
config: "no"
|
config: "no"
|
||||||
make: "no"
|
make: "no"
|
||||||
|
- name: iPhoneSimulator on OS X, i386
|
||||||
|
os: macos-latest
|
||||||
|
AUTOTOOLS_HOST: i386-apple-ios
|
||||||
|
OPENSSL_HOST: iphoneos-cross
|
||||||
|
IOS_SDK: iPhoneSimulator
|
||||||
|
IOS_CPU: i386
|
||||||
|
test_ios: "yes"
|
||||||
|
config: "no"
|
||||||
|
make: "no"
|
||||||
- name: iPhoneSimulator on OS X, x86_64
|
- name: iPhoneSimulator on OS X, x86_64
|
||||||
os: macos-latest
|
os: macos-latest
|
||||||
AUTOTOOLS_HOST: x86_64-apple-ios
|
AUTOTOOLS_HOST: x86_64-apple-ios
|
||||||
@@ -144,44 +161,13 @@ jobs:
|
|||||||
test_windows: "yes"
|
test_windows: "yes"
|
||||||
config: "no"
|
config: "no"
|
||||||
make: "no"
|
make: "no"
|
||||||
- name: FreeBSD
|
|
||||||
os: ubuntu-latest
|
|
||||||
config: "no"
|
|
||||||
make: "no"
|
|
||||||
with_cross_platform_action: "yes"
|
|
||||||
cross_platform_os: "freebsd"
|
|
||||||
cross_platform_arch: "x86-64"
|
|
||||||
cross_platform_version: "14.1"
|
|
||||||
cross_platform_config: "--enable-debug --disable-flto --with-libevent --disable-static"
|
|
||||||
- name: OpenBSD
|
|
||||||
os: ubuntu-latest
|
|
||||||
config: "no"
|
|
||||||
make: "no"
|
|
||||||
with_cross_platform_action: "yes"
|
|
||||||
cross_platform_os: "openbsd"
|
|
||||||
cross_platform_arch: "x86-64"
|
|
||||||
cross_platform_version: "7.5"
|
|
||||||
cross_platform_config: "--enable-debug --disable-flto --with-libevent --disable-static"
|
|
||||||
- name: NetBSD
|
|
||||||
os: ubuntu-latest
|
|
||||||
config: "no"
|
|
||||||
make: "no"
|
|
||||||
with_cross_platform_action: "yes"
|
|
||||||
cross_platform_os: "netbsd"
|
|
||||||
cross_platform_arch: "x86-64"
|
|
||||||
cross_platform_version: "10.0"
|
|
||||||
cross_platform_config: "--enable-debug --disable-flto --with-libevent --disable-static"
|
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v7
|
- uses: actions/checkout@v2
|
||||||
with:
|
with:
|
||||||
submodules: false
|
submodules: false
|
||||||
persist-credentials: false
|
|
||||||
- name: test_windows
|
- name: test_windows
|
||||||
if: ${{ matrix.test_windows == 'yes' }}
|
if: ${{ matrix.test_windows == 'yes' }}
|
||||||
env:
|
|
||||||
LIBEXPAT_FNAME: expat-2.7.0
|
|
||||||
LIBEXPAT_VERSION_DIR: R_2_7_0
|
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
export unboundpath=`pwd`
|
export unboundpath=`pwd`
|
||||||
@@ -189,32 +175,25 @@ jobs:
|
|||||||
cd ..
|
cd ..
|
||||||
export prepath=`pwd`
|
export prepath=`pwd`
|
||||||
echo prepath=${prepath}
|
echo prepath=${prepath}
|
||||||
# parralel build option
|
#echo "curl cpanm"
|
||||||
export MINJ="-j4"
|
#curl -L -k -s -S -o cpanm https://cpanmin.us/
|
||||||
echo "choco install winflexbison3"
|
#echo "perl cpanm Pod::Usage"
|
||||||
choco install winflexbison3
|
#perl cpanm Pod::Usage
|
||||||
echo 'LEX="win_flex"'
|
|
||||||
export LEX="win_flex"
|
|
||||||
echo 'YACC="win_bison -y"'
|
|
||||||
export YACC="win_bison -y"
|
|
||||||
mkdir openssl
|
mkdir openssl
|
||||||
echo "curl openssl"
|
echo "curl openssl"
|
||||||
curl -L -k -s -S -o openssl-3.2.0.tar.gz https://www.openssl.org/source/openssl-3.2.0.tar.gz
|
curl -L -k -s -S -o openssl-1.1.1j.tar.gz https://www.openssl.org/source/openssl-1.1.1j.tar.gz
|
||||||
tar xzf openssl-3.2.0.tar.gz
|
tar xzf openssl-1.1.1j.tar.gz
|
||||||
cd openssl-3.2.0
|
cd openssl-1.1.1j
|
||||||
# remove pod::Usage because we do not need -help or -man output
|
# remove pod::Usage because we do not need -help or -man output
|
||||||
# from the Configure script, this fixes it for openssl 1.1.1
|
# from the Configure script
|
||||||
#echo "Fixup ./Configure by removing use Pod::Usage require"
|
echo "Fixup ./Configure by removing use Pod::Usage require"
|
||||||
#sed -e 's/use Pod::Usage//' < Configure > Configure.fix
|
sed -e 's/use Pod::Usage//' < Configure > Configure.fix
|
||||||
# ./Configure.fix no-shared no-asm -DOPENSSL_NO_CAPIENG mingw64 --prefix="$prepath/openssl"
|
echo "./Configure.fix no-shared no-asm -DOPENSSL_NO_CAPIENG mingw64 --prefix=\""$prepath/openssl\"""
|
||||||
# pacman is used to install for msys2, with
|
./Configure.fix no-shared no-asm -DOPENSSL_NO_CAPIENG mingw64 --prefix="$prepath/openssl"
|
||||||
# C:/msys64/usr/bin/pacman -S perl
|
|
||||||
echo "C:/msys64/usr/bin/perl ./Configure no-shared no-asm -DOPENSSL_NO_CAPIENG mingw64 --prefix=\""$prepath/openssl"\" PERL=\"C:/msys64/usr/bin/perl\""
|
|
||||||
C:/msys64/usr/bin/perl ./Configure no-shared no-asm -DOPENSSL_NO_CAPIENG mingw64 --prefix="$prepath/openssl" PERL="C:/msys64/usr/bin/perl"
|
|
||||||
# make the libs only, build faster
|
# make the libs only, build faster
|
||||||
echo "make build_libs"
|
echo "make build_libs"
|
||||||
#make $MINJ
|
#make
|
||||||
make $MINJ build_libs
|
make build_libs
|
||||||
mv Makefile Makefile.orig
|
mv Makefile Makefile.orig
|
||||||
# fixup \\ in the installtop to /.
|
# fixup \\ in the installtop to /.
|
||||||
echo "fixup INSTALLTOP"
|
echo "fixup INSTALLTOP"
|
||||||
@@ -226,9 +205,9 @@ jobs:
|
|||||||
cd ..
|
cd ..
|
||||||
mkdir expat
|
mkdir expat
|
||||||
echo "curl expat"
|
echo "curl expat"
|
||||||
curl -L -k -s -S -o $LIBEXPAT_FNAME.tar.gz https://github.com/libexpat/libexpat/releases/download/$LIBEXPAT_VERSION_DIR/$LIBEXPAT_FNAME.tar.gz
|
curl -L -k -s -S -o expat-2.2.10.tar.gz https://github.com/libexpat/libexpat/releases/download/R_2_2_10/expat-2.2.10.tar.gz
|
||||||
tar xzf $LIBEXPAT_FNAME.tar.gz
|
tar xzf expat-2.2.10.tar.gz
|
||||||
cd $LIBEXPAT_FNAME
|
cd expat-2.2.10
|
||||||
echo "./configure SHELL=/usr/bin/bash CONFIG_SHELL=/usr/bin/bash --prefix=\"$prepath/expat\" --exec-prefix=\"$prepath/expat\" --bindir=\"$prepath/expat/bin\" --includedir=\"$prepath/expat/include\" --mandir=\"$prepath/expat/man\" --libdir=\"$prepath/expat/lib\""
|
echo "./configure SHELL=/usr/bin/bash CONFIG_SHELL=/usr/bin/bash --prefix=\"$prepath/expat\" --exec-prefix=\"$prepath/expat\" --bindir=\"$prepath/expat/bin\" --includedir=\"$prepath/expat/include\" --mandir=\"$prepath/expat/man\" --libdir=\"$prepath/expat/lib\""
|
||||||
./configure SHELL=/usr/bin/bash CONFIG_SHELL=/usr/bin/bash --prefix="$prepath/expat" --exec-prefix="$prepath/expat" --bindir="$prepath/expat/bin" --includedir="$prepath/expat/include" --mandir="$prepath/expat/man" --libdir="$prepath/expat/lib"
|
./configure SHELL=/usr/bin/bash CONFIG_SHELL=/usr/bin/bash --prefix="$prepath/expat" --exec-prefix="$prepath/expat" --bindir="$prepath/expat/bin" --includedir="$prepath/expat/include" --mandir="$prepath/expat/man" --libdir="$prepath/expat/lib"
|
||||||
# fixup SHELL is treated specially, but SHELZZ is not by make.
|
# fixup SHELL is treated specially, but SHELZZ is not by make.
|
||||||
@@ -246,7 +225,7 @@ jobs:
|
|||||||
mv xmlwf/Makefile xmlwf/Makefile.orig
|
mv xmlwf/Makefile xmlwf/Makefile.orig
|
||||||
sed -e 's/SHELL/SHELLZZ/g' < xmlwf/Makefile.orig > xmlwf/Makefile
|
sed -e 's/SHELL/SHELLZZ/g' < xmlwf/Makefile.orig > xmlwf/Makefile
|
||||||
echo "make"
|
echo "make"
|
||||||
make $MINJ
|
make
|
||||||
echo "make install"
|
echo "make install"
|
||||||
make install
|
make install
|
||||||
cd ..
|
cd ..
|
||||||
@@ -254,7 +233,7 @@ jobs:
|
|||||||
cd unbound
|
cd unbound
|
||||||
echo "./configure --enable-debug --enable-static-exe --disable-flto \"--with-ssl=$prepath/openssl\" --with-libexpat=\"$prepath/expat\" --disable-shared"
|
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
|
./configure --enable-debug --enable-static-exe --disable-flto "--with-ssl=$prepath/openssl" --with-libexpat="$prepath/expat" --disable-shared
|
||||||
make $MINJ
|
make
|
||||||
# specific test output
|
# specific test output
|
||||||
#make testbound.exe; ./testbound.exe -s
|
#make testbound.exe; ./testbound.exe -s
|
||||||
#make testbound; ./testbound.exe -p testdata/acl.rpl -o -vvvv
|
#make testbound; ./testbound.exe -p testdata/acl.rpl -o -vvvv
|
||||||
@@ -347,33 +326,6 @@ jobs:
|
|||||||
echo "::group::make install"
|
echo "::group::make install"
|
||||||
make install
|
make install
|
||||||
echo "::endgroup::"
|
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
|
|
||||||
env:
|
|
||||||
CROSS_PLATFORM_OS: ${{ matrix.cross_platform_os }}
|
|
||||||
with:
|
|
||||||
environment_variables: CROSS_PLATFORM_OS
|
|
||||||
operating_system: ${{ matrix.cross_platform_os }}
|
|
||||||
architecture: ${{ matrix.cross_platform_arch }}
|
|
||||||
version: ${{ matrix.cross_platform_version }}
|
|
||||||
shell: bash
|
|
||||||
memory: 4G
|
|
||||||
cpu_count: 2
|
|
||||||
run: |
|
|
||||||
set -e -x
|
|
||||||
if test "$CROSS_PLATFORM_OS" = "freebsd"; then sudo pkg install -y openssl libevent expat; fi
|
|
||||||
if test "$CROSS_PLATFORM_OS" = "openbsd"; then sudo pkg_add libevent; fi
|
|
||||||
if test "$CROSS_PLATFORM_OS" = "netbsd"; then sudo pkgin -y install libevent; fi
|
|
||||||
echo "::group::configure"
|
|
||||||
./configure ${{ matrix.cross_platform_config }}
|
|
||||||
echo "::endgroup::"
|
|
||||||
echo "::group::make"
|
|
||||||
make
|
|
||||||
echo "::endgroup::"
|
|
||||||
echo "::group::make test"
|
|
||||||
make test
|
|
||||||
echo "::endgroup::"
|
|
||||||
- name: install libevent
|
- name: install libevent
|
||||||
if: ${{ matrix.install_libevent == 'yes' }}
|
if: ${{ matrix.install_libevent == 'yes' }}
|
||||||
run: sudo apt-get install libevent-dev
|
run: sudo apt-get install libevent-dev
|
||||||
|
|||||||
@@ -12,9 +12,7 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v7
|
- uses: actions/checkout@v2
|
||||||
with:
|
|
||||||
persist-credentials: false
|
|
||||||
- name: configure
|
- name: configure
|
||||||
run: ./configure --enable-debug
|
run: ./configure --enable-debug
|
||||||
- name: make
|
- name: make
|
||||||
|
|||||||
@@ -10,10 +10,6 @@
|
|||||||
/config.status
|
/config.status
|
||||||
/dnstap/dnstap_config.h
|
/dnstap/dnstap_config.h
|
||||||
/dnscrypt/dnscrypt_config.h
|
/dnscrypt/dnscrypt_config.h
|
||||||
/util/configlexer.c
|
|
||||||
/util/configparser.c
|
|
||||||
/util/configparser.h
|
|
||||||
/clubsyms.def
|
|
||||||
/doc/example.conf
|
/doc/example.conf
|
||||||
/doc/libunbound.3
|
/doc/libunbound.3
|
||||||
/doc/unbound-anchor.8
|
/doc/unbound-anchor.8
|
||||||
@@ -36,7 +32,6 @@
|
|||||||
/asynclook
|
/asynclook
|
||||||
/delayer
|
/delayer
|
||||||
/dohclient
|
/dohclient
|
||||||
/doqclient
|
|
||||||
/lock-verify
|
/lock-verify
|
||||||
/memstats
|
/memstats
|
||||||
/perf
|
/perf
|
||||||
@@ -59,7 +54,6 @@
|
|||||||
/pythonmod/unboundmodule.py
|
/pythonmod/unboundmodule.py
|
||||||
/testdata/result.*
|
/testdata/result.*
|
||||||
/testdata/.done-*
|
/testdata/.done-*
|
||||||
/testdata/.skip-*
|
|
||||||
/testdata/.perfstats.txt
|
/testdata/.perfstats.txt
|
||||||
/doc/html
|
/doc/html
|
||||||
/doc/xml
|
/doc/xml
|
||||||
|
|||||||
+380
@@ -0,0 +1,380 @@
|
|||||||
|
language: c
|
||||||
|
|
||||||
|
git:
|
||||||
|
depth: 5
|
||||||
|
|
||||||
|
addons:
|
||||||
|
apt:
|
||||||
|
packages:
|
||||||
|
- libssl-dev
|
||||||
|
- libevent-dev
|
||||||
|
- libexpat-dev
|
||||||
|
- clang
|
||||||
|
homebrew:
|
||||||
|
packages:
|
||||||
|
- openssl
|
||||||
|
- libevent
|
||||||
|
- expat
|
||||||
|
# homebrew update takes 20min or hangs, so disable update
|
||||||
|
#update: true
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
include:
|
||||||
|
- os: linux
|
||||||
|
name: GCC on Linux, Amd64
|
||||||
|
compiler: gcc
|
||||||
|
arch: amd64
|
||||||
|
env:
|
||||||
|
- CONFIG_OPTS="--enable-debug --disable-flto"
|
||||||
|
- os: linux
|
||||||
|
name: Clang on Linux, Amd64, clang-analysis
|
||||||
|
compiler: clang
|
||||||
|
arch: amd64
|
||||||
|
env:
|
||||||
|
- CONFIG_OPTS="--enable-debug --disable-flto"
|
||||||
|
- TEST_ANALYZER=yes
|
||||||
|
- os: osx
|
||||||
|
osx_image: xcode12.2
|
||||||
|
name: Clang on OS X, Amd64, clang-analysis
|
||||||
|
compiler: clang
|
||||||
|
arch: amd64
|
||||||
|
env:
|
||||||
|
- TEST_OSX=yes
|
||||||
|
- CONFIG_OPTS="--enable-debug --disable-flto --with-ssl=/usr/local/opt/openssl --with-libexpat=/usr/local/opt/expat"
|
||||||
|
- TEST_ANALYZER=yes
|
||||||
|
- HOMEBREW_NO_AUTO_UPDATE=1
|
||||||
|
- os: linux
|
||||||
|
name: Libevent, GCC on Linux, Amd64
|
||||||
|
compiler: gcc
|
||||||
|
arch: amd64
|
||||||
|
env:
|
||||||
|
- TEST_LIBEVENT=yes
|
||||||
|
- CONFIG_OPTS="--with-libevent"
|
||||||
|
- os: linux
|
||||||
|
name: Libevent, Clang on Linux, Amd64
|
||||||
|
compiler: clang
|
||||||
|
arch: amd64
|
||||||
|
env:
|
||||||
|
- TEST_LIBEVENT=yes
|
||||||
|
- CONFIG_OPTS="--with-libevent"
|
||||||
|
- os: osx
|
||||||
|
osx_image: xcode12.2
|
||||||
|
name: Libevent, Clang on OS X, Amd64
|
||||||
|
compiler: clang
|
||||||
|
arch: amd64
|
||||||
|
env:
|
||||||
|
- TEST_OSX=yes
|
||||||
|
- TEST_LIBEVENT=yes
|
||||||
|
- CONFIG_OPTS="--disable-flto --with-ssl=/usr/local/opt/openssl --with-libevent=/usr/local/opt/libevent --with-libexpat=/usr/local/opt/expat"
|
||||||
|
- HOMEBREW_NO_AUTO_UPDATE=1
|
||||||
|
- os: linux
|
||||||
|
name: UBsan, GCC on Linux, Amd64
|
||||||
|
compiler: gcc
|
||||||
|
arch: amd64
|
||||||
|
dist: bionic
|
||||||
|
env:
|
||||||
|
- TEST_UBSAN=yes
|
||||||
|
- os: linux
|
||||||
|
name: UBsan, Clang on Linux, Amd64
|
||||||
|
compiler: clang
|
||||||
|
arch: amd64
|
||||||
|
dist: bionic
|
||||||
|
env:
|
||||||
|
- TEST_UBSAN=yes
|
||||||
|
- os: linux
|
||||||
|
name: Asan, GCC on Linux, Amd64
|
||||||
|
compiler: gcc
|
||||||
|
arch: amd64
|
||||||
|
dist: bionic
|
||||||
|
env:
|
||||||
|
- TEST_ASAN=yes
|
||||||
|
- os: linux
|
||||||
|
name: Asan, Clang on Linux, Amd64
|
||||||
|
compiler: clang
|
||||||
|
arch: amd64
|
||||||
|
dist: bionic
|
||||||
|
env:
|
||||||
|
- TEST_ASAN=yes
|
||||||
|
- os: linux
|
||||||
|
name: GCC on Linux, Aarch64
|
||||||
|
compiler: gcc
|
||||||
|
arch: arm64
|
||||||
|
dist: bionic
|
||||||
|
env:
|
||||||
|
- CONFIG_OPTS="--enable-debug --disable-flto"
|
||||||
|
- os: linux
|
||||||
|
name: Clang on Linux, Aarch64
|
||||||
|
compiler: clang
|
||||||
|
arch: arm64
|
||||||
|
dist: bionic
|
||||||
|
env:
|
||||||
|
- CONFIG_OPTS="--enable-debug --disable-flto"
|
||||||
|
- os: linux
|
||||||
|
name: GCC on Linux, PowerPC64
|
||||||
|
compiler: gcc
|
||||||
|
arch: ppc64le
|
||||||
|
dist: bionic
|
||||||
|
env:
|
||||||
|
- CONFIG_OPTS="--enable-debug --disable-flto"
|
||||||
|
- os: linux
|
||||||
|
name: Clang on Linux, PowerPC64
|
||||||
|
compiler: clang
|
||||||
|
arch: ppc64le
|
||||||
|
dist: bionic
|
||||||
|
env:
|
||||||
|
- CONFIG_OPTS="--enable-debug --disable-flto"
|
||||||
|
- os: linux
|
||||||
|
name: GCC on Linux, s390x
|
||||||
|
compiler: gcc
|
||||||
|
arch: s390x
|
||||||
|
dist: bionic
|
||||||
|
env:
|
||||||
|
- CONFIG_OPTS="--enable-debug --disable-flto"
|
||||||
|
- os: linux
|
||||||
|
name: Clang on Linux, s390x
|
||||||
|
compiler: clang
|
||||||
|
arch: s390x
|
||||||
|
dist: bionic
|
||||||
|
env:
|
||||||
|
- CONFIG_OPTS="--enable-debug --disable-flto"
|
||||||
|
- os: osx
|
||||||
|
osx_image: xcode12.2
|
||||||
|
name: Apple iPhone on iOS, armv7
|
||||||
|
compiler: clang
|
||||||
|
env:
|
||||||
|
- TEST_IOS=yes
|
||||||
|
- AUTOTOOLS_HOST=armv7-apple-ios
|
||||||
|
- OPENSSL_HOST=ios-cross
|
||||||
|
- IOS_SDK=iPhoneOS
|
||||||
|
- IOS_CPU=armv7s
|
||||||
|
- IOS_PREFIX="$HOME/$IOS_SDK-$IOS_CPU"
|
||||||
|
- HOMEBREW_NO_AUTO_UPDATE=1
|
||||||
|
- os: osx
|
||||||
|
osx_image: xcode12.2
|
||||||
|
name: Apple iPhone on iOS, arm64
|
||||||
|
compiler: clang
|
||||||
|
env:
|
||||||
|
- TEST_IOS=yes
|
||||||
|
- AUTOTOOLS_HOST=aarch64-apple-ios
|
||||||
|
- OPENSSL_HOST=ios64-cross
|
||||||
|
- IOS_SDK=iPhoneOS
|
||||||
|
- IOS_CPU=arm64
|
||||||
|
- IOS_PREFIX="$HOME/$IOS_SDK-$IOS_CPU"
|
||||||
|
- HOMEBREW_NO_AUTO_UPDATE=1
|
||||||
|
- os: osx
|
||||||
|
osx_image: xcode12.2
|
||||||
|
name: Apple TV on iOS, arm64
|
||||||
|
compiler: clang
|
||||||
|
env:
|
||||||
|
- TEST_IOS=yes
|
||||||
|
- AUTOTOOLS_HOST=aarch64-apple-ios
|
||||||
|
- OPENSSL_HOST=ios64-cross
|
||||||
|
- IOS_SDK=AppleTVOS
|
||||||
|
- IOS_CPU=arm64
|
||||||
|
- IOS_PREFIX="$HOME/$IOS_SDK-$IOS_CPU"
|
||||||
|
- HOMEBREW_NO_AUTO_UPDATE=1
|
||||||
|
- os: osx
|
||||||
|
osx_image: xcode12.2
|
||||||
|
name: Apple Watch on iOS, armv7
|
||||||
|
compiler: clang
|
||||||
|
env:
|
||||||
|
- TEST_IOS=yes
|
||||||
|
- AUTOTOOLS_HOST=armv7-apple-ios
|
||||||
|
- OPENSSL_HOST=ios-cross
|
||||||
|
- IOS_SDK=WatchOS
|
||||||
|
- IOS_CPU=armv7k
|
||||||
|
- IOS_PREFIX="$HOME/$IOS_SDK-$IOS_CPU"
|
||||||
|
- HOMEBREW_NO_AUTO_UPDATE=1
|
||||||
|
- os: osx
|
||||||
|
osx_image: xcode12.2
|
||||||
|
name: iPhoneSimulator on OS X, i386
|
||||||
|
env:
|
||||||
|
- TEST_IOS=yes
|
||||||
|
- AUTOTOOLS_HOST=i386-apple-ios
|
||||||
|
- OPENSSL_HOST=iphoneos-cross
|
||||||
|
- IOS_CPU=i386
|
||||||
|
- IOS_SDK=iPhoneSimulator
|
||||||
|
- IOS_PREFIX="$HOME/$IOS_SDK-$IOS_CPU"
|
||||||
|
- HOMEBREW_NO_AUTO_UPDATE=1
|
||||||
|
- os: osx
|
||||||
|
osx_image: xcode12.2
|
||||||
|
name: iPhoneSimulator on OS X, x86_64
|
||||||
|
env:
|
||||||
|
- TEST_IOS=yes
|
||||||
|
- AUTOTOOLS_HOST=x86_64-apple-ios
|
||||||
|
- OPENSSL_HOST=iphoneos-cross
|
||||||
|
- IOS_CPU=x86_64
|
||||||
|
- IOS_SDK=iPhoneSimulator
|
||||||
|
- IOS_PREFIX="$HOME/$IOS_SDK-$IOS_CPU"
|
||||||
|
- HOMEBREW_NO_AUTO_UPDATE=1
|
||||||
|
- os: osx
|
||||||
|
osx_image: xcode12.2
|
||||||
|
name: AppleTVSimulator on OS X, x86_64
|
||||||
|
env:
|
||||||
|
- TEST_IOS=yes
|
||||||
|
- AUTOTOOLS_HOST=x86_64-apple-ios
|
||||||
|
- OPENSSL_HOST=iphoneos-cross
|
||||||
|
- IOS_CPU=x86_64
|
||||||
|
- IOS_SDK=AppleTVSimulator
|
||||||
|
- IOS_PREFIX="$HOME/$IOS_SDK-$IOS_CPU"
|
||||||
|
- HOMEBREW_NO_AUTO_UPDATE=1
|
||||||
|
- os: osx
|
||||||
|
osx_image: xcode12.2
|
||||||
|
name: WatchSimulator on OS X, i386
|
||||||
|
env:
|
||||||
|
- TEST_IOS=yes
|
||||||
|
- AUTOTOOLS_HOST=i386-apple-ios
|
||||||
|
- OPENSSL_HOST=iphoneos-cross
|
||||||
|
- IOS_CPU=i386
|
||||||
|
- IOS_SDK=WatchSimulator
|
||||||
|
- IOS_PREFIX="$HOME/$IOS_SDK-$IOS_CPU"
|
||||||
|
- HOMEBREW_NO_AUTO_UPDATE=1
|
||||||
|
- os: linux
|
||||||
|
name: Android armv7a, Linux, Amd64
|
||||||
|
compiler: clang
|
||||||
|
arch: amd64
|
||||||
|
dist: bionic
|
||||||
|
env:
|
||||||
|
- TEST_ANDROID=yes
|
||||||
|
- AUTOTOOLS_HOST=armv7a-linux-androideabi
|
||||||
|
- OPENSSL_HOST=android-arm
|
||||||
|
- ANDROID_CPU=armv7a
|
||||||
|
- ANDROID_API=23
|
||||||
|
- ANDROID_PREFIX="$HOME/android$ANDROID_API-$ANDROID_CPU"
|
||||||
|
- ANDROID_SDK_ROOT="$HOME/android-sdk"
|
||||||
|
- ANDROID_NDK_ROOT="$HOME/android-ndk"
|
||||||
|
- os: linux
|
||||||
|
name: Android aarch64, Linux, Amd64
|
||||||
|
compiler: clang
|
||||||
|
arch: amd64
|
||||||
|
dist: bionic
|
||||||
|
env:
|
||||||
|
- TEST_ANDROID=yes
|
||||||
|
- AUTOTOOLS_HOST=aarch64-linux-android
|
||||||
|
- OPENSSL_HOST=android-arm64
|
||||||
|
- ANDROID_CPU=aarch64
|
||||||
|
- ANDROID_API=23
|
||||||
|
- ANDROID_PREFIX="$HOME/android$ANDROID_API-$ANDROID_CPU"
|
||||||
|
- ANDROID_SDK_ROOT="$HOME/android-sdk"
|
||||||
|
- ANDROID_NDK_ROOT="$HOME/android-ndk"
|
||||||
|
- os: linux
|
||||||
|
name: Android x86, Linux, Amd64
|
||||||
|
compiler: clang
|
||||||
|
arch: amd64
|
||||||
|
dist: bionic
|
||||||
|
env:
|
||||||
|
- TEST_ANDROID=yes
|
||||||
|
- AUTOTOOLS_HOST=i686-linux-android
|
||||||
|
- OPENSSL_HOST=android-x86
|
||||||
|
- ANDROID_CPU=x86
|
||||||
|
- ANDROID_API=23
|
||||||
|
- ANDROID_PREFIX="$HOME/android$ANDROID_API-$ANDROID_CPU"
|
||||||
|
- ANDROID_SDK_ROOT="$HOME/android-sdk"
|
||||||
|
- ANDROID_NDK_ROOT="$HOME/android-ndk"
|
||||||
|
- os: linux
|
||||||
|
name: Android x86_64, Linux, Amd64
|
||||||
|
compiler: clang
|
||||||
|
arch: amd64
|
||||||
|
dist: bionic
|
||||||
|
env:
|
||||||
|
- TEST_ANDROID=yes
|
||||||
|
- AUTOTOOLS_HOST=x86_64-linux-android
|
||||||
|
- OPENSSL_HOST=android-x86_64
|
||||||
|
- ANDROID_CPU=x86_64
|
||||||
|
- ANDROID_API=23
|
||||||
|
- ANDROID_PREFIX="$HOME/android$ANDROID_API-$ANDROID_CPU"
|
||||||
|
- ANDROID_SDK_ROOT="$HOME/android-sdk"
|
||||||
|
- ANDROID_NDK_ROOT="$HOME/android-ndk"
|
||||||
|
|
||||||
|
allow_failures:
|
||||||
|
- os: osx
|
||||||
|
name: Apple iPhone on iOS, armv7
|
||||||
|
- os: osx
|
||||||
|
name: Apple iPhone on iOS, arm64
|
||||||
|
- os: osx
|
||||||
|
name: Apple TV on iOS, arm64
|
||||||
|
- os: osx
|
||||||
|
name: Apple Watch on iOS, armv7
|
||||||
|
- os: osx
|
||||||
|
name: iPhoneSimulator on OS X, i386
|
||||||
|
- os: osx
|
||||||
|
name: iPhoneSimulator on OS X, x86_64
|
||||||
|
- os: osx
|
||||||
|
name: AppleTVSimulator on OS X, x86_64
|
||||||
|
- os: osx
|
||||||
|
name: WatchSimulator on OS X, i386
|
||||||
|
- os: linux
|
||||||
|
name: Android armv7a, Linux, Amd64
|
||||||
|
- os: linux
|
||||||
|
name: Android aarch64, Linux, Amd64
|
||||||
|
- os: linux
|
||||||
|
name: Android x86, Linux, Amd64
|
||||||
|
- os: linux
|
||||||
|
name: Android x86_64, Linux, Amd64
|
||||||
|
|
||||||
|
before_script:
|
||||||
|
- |
|
||||||
|
if [ "$TEST_ANDROID" = "yes" ]; then
|
||||||
|
./contrib/android/install_tools.sh
|
||||||
|
elif [ "$TEST_IOS" = "yes" ]; then
|
||||||
|
./contrib/ios/install_tools.sh
|
||||||
|
fi
|
||||||
|
|
||||||
|
# The Travis docs say to avoid calling exit in the script. It leads to
|
||||||
|
# some code duplication to avoid failures in cross-compiles. Also see
|
||||||
|
# https://docs.travis-ci.com/user/job-lifecycle/ in the Travis docs.
|
||||||
|
script:
|
||||||
|
- |
|
||||||
|
export MAKE_TEST="yes"
|
||||||
|
if [ "$TEST_UBSAN" = "yes" ]; then
|
||||||
|
export CFLAGS="-DNDEBUG -g2 -O3 -fsanitize=undefined -fno-sanitize-recover=all"
|
||||||
|
elif [ "$TEST_ASAN" = "yes" ]; then
|
||||||
|
export CFLAGS="-DNDEBUG -g2 -O3 -fsanitize=address"
|
||||||
|
fi
|
||||||
|
- |
|
||||||
|
if [ "$TEST_IOS" = "yes" ]; then
|
||||||
|
export AUTOTOOLS_BUILD="$(./config.guess)"
|
||||||
|
export PKG_CONFIG_PATH="$IOS_PREFIX/lib/pkgconfig"
|
||||||
|
source ./contrib/ios/setenv_ios.sh
|
||||||
|
./contrib/ios/install_openssl.sh
|
||||||
|
./contrib/ios/install_expat.sh
|
||||||
|
export CONFIG_OPTS="\
|
||||||
|
--build=$AUTOTOOLS_BUILD --host=$AUTOTOOLS_HOST \
|
||||||
|
--prefix=$IOS_PREFIX \
|
||||||
|
--with-ssl=$IOS_PREFIX --disable-gost \
|
||||||
|
--with-libexpat=$IOS_PREFIX "
|
||||||
|
echo CONFIG_OPTS ${CONFIG_OPTS}
|
||||||
|
export MAKE_TEST=no
|
||||||
|
export TEST_INSTALL=yes
|
||||||
|
fi
|
||||||
|
- |
|
||||||
|
if [ "$TEST_ANDROID" = "yes" ]; then
|
||||||
|
export AUTOTOOLS_BUILD="$(./config.guess)"
|
||||||
|
export PKG_CONFIG_PATH="$ANDROID_PREFIX/lib/pkgconfig"
|
||||||
|
./contrib/android/install_ndk.sh
|
||||||
|
source ./contrib/android/setenv_android.sh
|
||||||
|
./contrib/android/install_openssl.sh
|
||||||
|
./contrib/android/install_expat.sh
|
||||||
|
export CONFIG_OPTS="\
|
||||||
|
--build=$AUTOTOOLS_BUILD --host=$AUTOTOOLS_HOST \
|
||||||
|
--prefix=$ANDROID_PREFIX \
|
||||||
|
--with-ssl=$ANDROID_PREFIX --disable-gost \
|
||||||
|
--with-libexpat=$ANDROID_PREFIX "
|
||||||
|
echo CONFIG_OPTS ${CONFIG_OPTS}
|
||||||
|
export MAKE_TEST=no
|
||||||
|
export TEST_INSTALL=yes
|
||||||
|
fi
|
||||||
|
- ./configure ${CONFIG_OPTS}
|
||||||
|
- make -j 2
|
||||||
|
- |
|
||||||
|
if [ "$MAKE_TEST" = "yes" ]; then
|
||||||
|
make test
|
||||||
|
fi
|
||||||
|
- |
|
||||||
|
if [ "$TEST_INSTALL" = "yes" ]; then
|
||||||
|
make install
|
||||||
|
fi
|
||||||
|
- |
|
||||||
|
if [ "$TEST_ANALYZER" = "yes" ]; then
|
||||||
|
(cd testdata/clang-analysis.tdir; bash clang-analysis.test)
|
||||||
|
fi
|
||||||
+569
-849
File diff suppressed because it is too large
Load Diff
@@ -1,45 +1,39 @@
|
|||||||
# Unbound
|
# Unbound
|
||||||
|
|
||||||
[](https://github.com/NLnetLabs/unbound/actions)
|
[](https://travis-ci.org/NLnetLabs/unbound)
|
||||||
[](https://repology.org/project/unbound/versions)
|
[](https://repology.org/project/unbound/versions)
|
||||||
[](https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:unbound)
|
[](https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:unbound)
|
||||||
[](https://unbound.readthedocs.io/en/latest/?badge=latest)
|
[](https://unbound.readthedocs.io/en/latest/?badge=latest)
|
||||||
[](https://social.nlnetlabs.nl/@nlnetlabs)
|
|
||||||
|
|
||||||
Unbound is a validating, recursive, caching DNS resolver. It is designed to be
|
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
|
fast and lean and incorporates modern features based on open standards. If you
|
||||||
have any feedback, we would love to hear from you. Don’t hesitate to
|
have any feedback, we would love to hear from you. Don’t hesitate to
|
||||||
[create an issue on Github](https://github.com/NLnetLabs/unbound/issues/new)
|
[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
|
You can learn more about Unbound by reading our
|
||||||
[documentation](https://unbound.docs.nlnetlabs.nl/).
|
[documentation](https://unbound.docs.nlnetlabs.nl/).
|
||||||
|
|
||||||
## Compiling
|
## Compiling
|
||||||
|
|
||||||
Make sure you have the C toolchain, OpenSSL and its include files, and libexpat
|
Make sure you have the C toolchain, OpenSSL and its include files, and libexpat
|
||||||
installed.
|
installed. Unbound can be compiled and installed using:
|
||||||
If building from the repository source you also need flex and bison installed.
|
|
||||||
Unbound can be compiled and installed using:
|
|
||||||
|
|
||||||
```
|
```
|
||||||
./configure && make && make install
|
./configure && make && make install
|
||||||
```
|
```
|
||||||
|
|
||||||
You can use libevent if you want. libevent is useful when using many (e.g.,
|
You can use libevent if you want. libevent is useful when using many (10000)
|
||||||
10000) outgoing ports.
|
outgoing ports. By default max 256 ports are opened at the same time and the
|
||||||
Use the `--with-libevent` configure option to compile Unbound with libevent
|
builtin alternative is equally capable and a little faster.
|
||||||
|
|
||||||
|
Use the `--with-libevent=dir` configure option to compile Unbound with libevent
|
||||||
support.
|
support.
|
||||||
|
|
||||||
If not, the default builtin alternative opens max 256 ports at the same time
|
|
||||||
and is equally capable and a little faster.
|
|
||||||
|
|
||||||
|
|
||||||
## Unbound configuration
|
## Unbound configuration
|
||||||
|
|
||||||
All of Unbound's configuration options are described in the `unbound.conf(5)`
|
All of Unbound's configuration options are described in the man pages, which
|
||||||
man page, which will be installed and is also available on the Unbound
|
will be installed and are available on the Unbound
|
||||||
[documentation page](https://unbound.docs.nlnetlabs.nl/en/latest/manpages/unbound.conf.html)
|
[documentation page](https://unbound.docs.nlnetlabs.nl/).
|
||||||
for the latest version.
|
|
||||||
|
|
||||||
An example configuration file, with minimal documentation, is located in
|
An example configuration file is located in
|
||||||
[doc/example.conf](https://github.com/NLnetLabs/unbound/blob/master/doc/example.conf.in).
|
[doc/example.conf](https://github.com/NLnetLabs/unbound/blob/master/doc/example.conf.in).
|
||||||
|
|||||||
@@ -1,43 +1,39 @@
|
|||||||
# ===========================================================================
|
# ===========================================================================
|
||||||
# https://www.gnu.org/software/autoconf-archive/ax_pkg_swig.html
|
# http://autoconf-archive.cryp.to/ac_pkg_swig.html
|
||||||
# ===========================================================================
|
# ===========================================================================
|
||||||
#
|
#
|
||||||
# SYNOPSIS
|
# SYNOPSIS
|
||||||
#
|
#
|
||||||
# AX_PKG_SWIG([major.minor.micro], [action-if-found], [action-if-not-found])
|
# AC_PROG_SWIG([major.minor.micro])
|
||||||
#
|
#
|
||||||
# DESCRIPTION
|
# DESCRIPTION
|
||||||
#
|
#
|
||||||
# This macro searches for a SWIG installation on your system. If found,
|
# This macro searches for a SWIG installation on your system. If found you
|
||||||
# then SWIG is AC_SUBST'd; if not found, then $SWIG is empty. If SWIG is
|
# should call SWIG via $(SWIG). You can use the optional first argument to
|
||||||
# found, then SWIG_LIB is set to the SWIG library path, and AC_SUBST'd.
|
# check if the version of the available SWIG is greater than or equal to
|
||||||
|
# the value of the argument. It should have the format: N[.N[.N]] (N is a
|
||||||
|
# number between 0 and 999. Only the first N is mandatory.)
|
||||||
#
|
#
|
||||||
# You can use the optional first argument to check if the version of the
|
# If the version argument is given (e.g. 1.3.17), AC_PROG_SWIG checks that
|
||||||
# available SWIG is greater than or equal to the value of the argument. It
|
# the swig package is this version number or higher.
|
||||||
# should have the format: N[.N[.N]] (N is a number between 0 and 999. Only
|
|
||||||
# the first N is mandatory.) If the version argument is given (e.g.
|
|
||||||
# 1.3.17), AX_PKG_SWIG checks that the swig package is this version number
|
|
||||||
# or higher.
|
|
||||||
#
|
|
||||||
# As usual, action-if-found is executed if SWIG is found, otherwise
|
|
||||||
# action-if-not-found is executed.
|
|
||||||
#
|
#
|
||||||
# In configure.in, use as:
|
# In configure.in, use as:
|
||||||
#
|
#
|
||||||
# AX_PKG_SWIG(1.3.17, [], [ AC_MSG_ERROR([SWIG is required to build..]) ])
|
# AC_PROG_SWIG(1.3.17)
|
||||||
# AX_SWIG_ENABLE_CXX
|
# SWIG_ENABLE_CXX
|
||||||
# AX_SWIG_MULTI_MODULE_SUPPORT
|
# SWIG_MULTI_MODULE_SUPPORT
|
||||||
# AX_SWIG_PYTHON
|
# SWIG_PYTHON
|
||||||
#
|
#
|
||||||
# LICENSE
|
# LAST MODIFICATION
|
||||||
|
#
|
||||||
|
# 2008-04-12
|
||||||
|
#
|
||||||
|
# COPYLEFT
|
||||||
#
|
#
|
||||||
# Copyright (c) 2008 Sebastian Huber <sebastian-huber@web.de>
|
# Copyright (c) 2008 Sebastian Huber <sebastian-huber@web.de>
|
||||||
# Copyright (c) 2008 Alan W. Irwin
|
# Copyright (c) 2008 Alan W. Irwin <irwin@beluga.phys.uvic.ca>
|
||||||
# Copyright (c) 2008 Rafael Laboissiere <rafael@laboissiere.net>
|
# Copyright (c) 2008 Rafael Laboissiere <rafael@laboissiere.net>
|
||||||
# Copyright (c) 2008 Andrew Collier
|
# Copyright (c) 2008 Andrew Collier <colliera@ukzn.ac.za>
|
||||||
# Copyright (c) 2011 Murray Cumming <murrayc@openismus.com>
|
|
||||||
# Copyright (c) 2018 Reini Urban <rurban@cpan.org>
|
|
||||||
# Copyright (c) 2021 Vincent Danjean <Vincent.Danjean@ens-lyon.org>
|
|
||||||
#
|
#
|
||||||
# This program is free software; you can redistribute it and/or modify it
|
# This program is free software; you can redistribute it and/or modify it
|
||||||
# under the terms of the GNU General Public License as published by the
|
# under the terms of the GNU General Public License as published by the
|
||||||
@@ -50,7 +46,7 @@
|
|||||||
# Public License for more details.
|
# Public License for more details.
|
||||||
#
|
#
|
||||||
# You should have received a copy of the GNU General Public License along
|
# You should have received a copy of the GNU General Public License along
|
||||||
# with this program. If not, see <https://www.gnu.org/licenses/>.
|
# with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
#
|
#
|
||||||
# As a special exception, the respective Autoconf Macro's copyright owner
|
# As a special exception, the respective Autoconf Macro's copyright owner
|
||||||
# gives unlimited permission to copy, distribute and modify the configure
|
# gives unlimited permission to copy, distribute and modify the configure
|
||||||
@@ -61,21 +57,17 @@
|
|||||||
# all other use of the material that constitutes the Autoconf Macro.
|
# all other use of the material that constitutes the Autoconf Macro.
|
||||||
#
|
#
|
||||||
# This special exception to the GPL applies to versions of the Autoconf
|
# This special exception to the GPL applies to versions of the Autoconf
|
||||||
# Macro released by the Autoconf Archive. When you make and distribute a
|
# Macro released by the Autoconf Macro Archive. When you make and
|
||||||
# modified version of the Autoconf Macro, you may extend this special
|
# distribute a modified version of the Autoconf Macro, you may extend this
|
||||||
# exception to the GPL to apply to your modified version as well.
|
# special exception to the GPL to apply to your modified version as well.
|
||||||
|
|
||||||
#serial 15
|
AC_DEFUN([AC_PROG_SWIG],[
|
||||||
|
AC_PATH_PROG([SWIG],[swig])
|
||||||
AC_DEFUN([AX_PKG_SWIG],[
|
|
||||||
# Find path to the "swig" executable.
|
|
||||||
AC_PATH_PROGS([SWIG],[swig swig3.0 swig2.0])
|
|
||||||
if test -z "$SWIG" ; then
|
if test -z "$SWIG" ; then
|
||||||
m4_ifval([$3],[$3],[:])
|
AC_MSG_WARN([cannot find 'swig' program. You should look at http://www.swig.org])
|
||||||
elif test -z "$1" ; then
|
SWIG='echo "Error: SWIG is not installed. You should look at http://www.swig.org" ; false'
|
||||||
m4_ifval([$2],[$2],[:])
|
elif test -n "$1" ; then
|
||||||
else
|
AC_MSG_CHECKING([for SWIG version])
|
||||||
AC_MSG_CHECKING([SWIG version])
|
|
||||||
[swig_version=`$SWIG -version 2>&1 | grep 'SWIG Version' | sed 's/.*\([0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\).*/\1/g'`]
|
[swig_version=`$SWIG -version 2>&1 | grep 'SWIG Version' | sed 's/.*\([0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\).*/\1/g'`]
|
||||||
AC_MSG_RESULT([$swig_version])
|
AC_MSG_RESULT([$swig_version])
|
||||||
if test -n "$swig_version" ; then
|
if test -n "$swig_version" ; then
|
||||||
@@ -85,12 +77,12 @@ AC_DEFUN([AX_PKG_SWIG],[
|
|||||||
if test -z "$required_major" ; then
|
if test -z "$required_major" ; then
|
||||||
[required_major=0]
|
[required_major=0]
|
||||||
fi
|
fi
|
||||||
[required=`echo $required. | sed 's/[0-9]*[^0-9]//'`]
|
[required=`echo $required | sed 's/[0-9]*[^0-9]//'`]
|
||||||
[required_minor=`echo $required | sed 's/[^0-9].*//'`]
|
[required_minor=`echo $required | sed 's/[^0-9].*//'`]
|
||||||
if test -z "$required_minor" ; then
|
if test -z "$required_minor" ; then
|
||||||
[required_minor=0]
|
[required_minor=0]
|
||||||
fi
|
fi
|
||||||
[required=`echo $required. | sed 's/[0-9]*[^0-9]//'`]
|
[required=`echo $required | sed 's/[0-9]*[^0-9]//'`]
|
||||||
[required_patch=`echo $required | sed 's/[^0-9].*//'`]
|
[required_patch=`echo $required | sed 's/[^0-9].*//'`]
|
||||||
if test -z "$required_patch" ; then
|
if test -z "$required_patch" ; then
|
||||||
[required_patch=0]
|
[required_patch=0]
|
||||||
@@ -111,28 +103,30 @@ AC_DEFUN([AX_PKG_SWIG],[
|
|||||||
if test -z "$available_patch" ; then
|
if test -z "$available_patch" ; then
|
||||||
[available_patch=0]
|
[available_patch=0]
|
||||||
fi
|
fi
|
||||||
# Convert the version tuple into a single number for easier comparison.
|
[badversion=0]
|
||||||
# Using base 100 should be safe since SWIG internally uses BCD values
|
if test $available_major -lt $required_major ; then
|
||||||
# to encode its version number.
|
[badversion=1]
|
||||||
required_swig_vernum=`expr $required_major \* 10000 \
|
fi
|
||||||
\+ $required_minor \* 100 \+ $required_patch`
|
if test $available_major -eq $required_major \
|
||||||
available_swig_vernum=`expr $available_major \* 10000 \
|
-a $available_minor -lt $required_minor ; then
|
||||||
\+ $available_minor \* 100 \+ $available_patch`
|
[badversion=1]
|
||||||
|
fi
|
||||||
if test $available_swig_vernum -lt $required_swig_vernum; then
|
if test $available_major -eq $required_major \
|
||||||
AC_MSG_WARN([SWIG version >= $1 is required. You have $swig_version.])
|
-a $available_minor -eq $required_minor \
|
||||||
SWIG=''
|
-a $available_patch -lt $required_patch ; then
|
||||||
m4_ifval([$3],[$3],[])
|
[badversion=1]
|
||||||
|
fi
|
||||||
|
if test $badversion -eq 1 ; then
|
||||||
|
AC_MSG_WARN([SWIG version >= $1 is required. You have $swig_version. You should look at http://www.swig.org])
|
||||||
|
SWIG='echo "Error: SWIG version >= $1 is required. You have '"$swig_version"'. You should look at http://www.swig.org" ; false'
|
||||||
else
|
else
|
||||||
AC_MSG_CHECKING([for SWIG library])
|
AC_MSG_NOTICE([SWIG executable is '$SWIG'])
|
||||||
SWIG_LIB=`$SWIG -swiglib | tr '\r\n' ' '`
|
SWIG_LIB=`$SWIG -swiglib`
|
||||||
AC_MSG_RESULT([$SWIG_LIB])
|
AC_MSG_NOTICE([SWIG library directory is '$SWIG_LIB'])
|
||||||
m4_ifval([$2],[$2],[])
|
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
AC_MSG_WARN([cannot determine SWIG version])
|
AC_MSG_WARN([cannot determine SWIG version])
|
||||||
SWIG=''
|
SWIG='echo "Error: Cannot determine SWIG version. You should look at http://www.swig.org" ; false'
|
||||||
m4_ifval([$3],[$3],[])
|
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
AC_SUBST([SWIG_LIB])
|
AC_SUBST([SWIG_LIB])
|
||||||
+54
-164
@@ -2,17 +2,7 @@
|
|||||||
# Copyright 2009, Wouter Wijngaards, NLnet Labs.
|
# Copyright 2009, Wouter Wijngaards, NLnet Labs.
|
||||||
# BSD licensed.
|
# BSD licensed.
|
||||||
#
|
#
|
||||||
# Version 51
|
# Version 44
|
||||||
# 2025-11-06 Fix ACX_CHECK_NONSTRING_ATTRIBUTE to reject clang, that prints
|
|
||||||
# a warning for 'unknown attribute' when nonstring is used.
|
|
||||||
# 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.
|
|
||||||
# 2024-01-16 fix to add -l:libssp.a to -lcrypto link check.
|
|
||||||
# and check for getaddrinfo with only header.
|
|
||||||
# 2024-01-15 fix to add crypt32 to -lcrypto link check when checking for gdi32.
|
|
||||||
# 2023-05-04 fix to remove unused whitespace.
|
|
||||||
# 2023-01-26 fix -Wstrict-prototypes.
|
|
||||||
# 2022-09-01 fix checking if nonblocking sockets work on OpenBSD.
|
# 2022-09-01 fix checking if nonblocking sockets work on OpenBSD.
|
||||||
# 2021-08-17 fix sed script in ssldir split handling.
|
# 2021-08-17 fix sed script in ssldir split handling.
|
||||||
# 2021-08-17 fix for openssl to detect split version, with ssldir_include
|
# 2021-08-17 fix for openssl to detect split version, with ssldir_include
|
||||||
@@ -76,7 +66,6 @@
|
|||||||
# ACX_DEPFLAG - find cc dependency flags.
|
# ACX_DEPFLAG - find cc dependency flags.
|
||||||
# ACX_DETERMINE_EXT_FLAGS_UNBOUND - find out which flags enable BSD and POSIX.
|
# ACX_DETERMINE_EXT_FLAGS_UNBOUND - find out which flags enable BSD and POSIX.
|
||||||
# ACX_CHECK_FORMAT_ATTRIBUTE - find cc printf format syntax.
|
# ACX_CHECK_FORMAT_ATTRIBUTE - find cc printf format syntax.
|
||||||
# ACX_CHECK_NONSTRING_ATTRIBUTE - find cc nonstring attribute syntax.
|
|
||||||
# ACX_CHECK_UNUSED_ATTRIBUTE - find cc variable unused syntax.
|
# ACX_CHECK_UNUSED_ATTRIBUTE - find cc variable unused syntax.
|
||||||
# ACX_CHECK_FLTO - see if cc supports -flto and use it if so.
|
# ACX_CHECK_FLTO - see if cc supports -flto and use it if so.
|
||||||
# ACX_LIBTOOL_C_ONLY - create libtool for C only, improved.
|
# ACX_LIBTOOL_C_ONLY - create libtool for C only, improved.
|
||||||
@@ -98,7 +87,6 @@
|
|||||||
# ACX_FUNC_IOCTLSOCKET - find ioctlsocket, portably.
|
# ACX_FUNC_IOCTLSOCKET - find ioctlsocket, portably.
|
||||||
# ACX_FUNC_MALLOC - check malloc, define replacement .
|
# ACX_FUNC_MALLOC - check malloc, define replacement .
|
||||||
# AHX_CONFIG_FORMAT_ATTRIBUTE - config.h text for format.
|
# AHX_CONFIG_FORMAT_ATTRIBUTE - config.h text for format.
|
||||||
# AHX_CONFIG_NONSTRING_ATTRIBUTE - config.h text for nonstring.
|
|
||||||
# AHX_CONFIG_UNUSED_ATTRIBUTE - config.h text for unused.
|
# AHX_CONFIG_UNUSED_ATTRIBUTE - config.h text for unused.
|
||||||
# AHX_CONFIG_FSEEKO - define fseeko, ftello fallback.
|
# AHX_CONFIG_FSEEKO - define fseeko, ftello fallback.
|
||||||
# AHX_CONFIG_RAND_MAX - define RAND_MAX if needed.
|
# AHX_CONFIG_RAND_MAX - define RAND_MAX if needed.
|
||||||
@@ -199,7 +187,7 @@ dnl cache=`echo $1 | sed 'y%.=/+- %___p__%'`
|
|||||||
AC_CACHE_VAL(cv_prog_cc_flag_needed_$cache,
|
AC_CACHE_VAL(cv_prog_cc_flag_needed_$cache,
|
||||||
[
|
[
|
||||||
echo '$2' > conftest.c
|
echo '$2' > conftest.c
|
||||||
echo 'void f(void){}' >>conftest.c
|
echo 'void f(){}' >>conftest.c
|
||||||
if test -z "`$CC $CPPFLAGS $CFLAGS $ERRFLAG -c conftest.c 2>&1`"; then
|
if test -z "`$CC $CPPFLAGS $CFLAGS $ERRFLAG -c conftest.c 2>&1`"; then
|
||||||
eval "cv_prog_cc_flag_needed_$cache=no"
|
eval "cv_prog_cc_flag_needed_$cache=no"
|
||||||
else
|
else
|
||||||
@@ -245,7 +233,7 @@ dnl DEPFLAG: set to flag that generates dependencies.
|
|||||||
AC_DEFUN([ACX_DEPFLAG],
|
AC_DEFUN([ACX_DEPFLAG],
|
||||||
[
|
[
|
||||||
AC_MSG_CHECKING([$CC dependency flag])
|
AC_MSG_CHECKING([$CC dependency flag])
|
||||||
echo 'void f(void){}' >conftest.c
|
echo 'void f(){}' >conftest.c
|
||||||
if test "`$CC -MM conftest.c 2>&1`" = "conftest.o: conftest.c"; then
|
if test "`$CC -MM conftest.c 2>&1`" = "conftest.o: conftest.c"; then
|
||||||
DEPFLAG="-MM"
|
DEPFLAG="-MM"
|
||||||
else
|
else
|
||||||
@@ -284,7 +272,7 @@ ACX_CHECK_COMPILER_FLAG_NEEDED($C99FLAG -D__EXTENSIONS__ -D_BSD_SOURCE -D_DEFAUL
|
|||||||
#include <getopt.h>
|
#include <getopt.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int test(void) {
|
int test() {
|
||||||
int a;
|
int a;
|
||||||
char **opts = NULL;
|
char **opts = NULL;
|
||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
@@ -321,7 +309,7 @@ ACX_CHECK_COMPILER_FLAG_NEEDED($C99FLAG -D__EXTENSIONS__ -D_BSD_SOURCE -D_DEFAUL
|
|||||||
#include <getopt.h>
|
#include <getopt.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int test(void) {
|
int test() {
|
||||||
int a;
|
int a;
|
||||||
char **opts = NULL;
|
char **opts = NULL;
|
||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
@@ -347,7 +335,7 @@ ACX_CHECK_COMPILER_FLAG_NEEDED($C99FLAG,
|
|||||||
[
|
[
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
int test(void) {
|
int test() {
|
||||||
int a = 0;
|
int a = 0;
|
||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
@@ -357,7 +345,7 @@ ACX_CHECK_COMPILER_FLAG_NEEDED(-D_BSD_SOURCE -D_DEFAULT_SOURCE,
|
|||||||
[
|
[
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
|
||||||
int test(void) {
|
int test() {
|
||||||
int a;
|
int a;
|
||||||
a = isascii(32);
|
a = isascii(32);
|
||||||
return a;
|
return a;
|
||||||
@@ -368,7 +356,7 @@ ACX_CHECK_COMPILER_FLAG_NEEDED(-D_GNU_SOURCE,
|
|||||||
[
|
[
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
|
|
||||||
int test(void) {
|
int test() {
|
||||||
struct in6_pktinfo inf;
|
struct in6_pktinfo inf;
|
||||||
int a = (int)sizeof(inf);
|
int a = (int)sizeof(inf);
|
||||||
return a;
|
return a;
|
||||||
@@ -382,7 +370,7 @@ ACX_CHECK_COMPILER_FLAG_NEEDED(-D_GNU_SOURCE -D_FRSRESGID,
|
|||||||
[
|
[
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
int test(void) {
|
int test() {
|
||||||
int a = setresgid(0,0,0);
|
int a = setresgid(0,0,0);
|
||||||
a = setresuid(0,0,0);
|
a = setresuid(0,0,0);
|
||||||
return a;
|
return a;
|
||||||
@@ -397,7 +385,7 @@ ACX_CHECK_COMPILER_FLAG_NEEDED(-D_POSIX_C_SOURCE=200112,
|
|||||||
#endif
|
#endif
|
||||||
#include <netdb.h>
|
#include <netdb.h>
|
||||||
|
|
||||||
int test(void) {
|
int test() {
|
||||||
int a = 0;
|
int a = 0;
|
||||||
char *t;
|
char *t;
|
||||||
time_t time = 0;
|
time_t time = 0;
|
||||||
@@ -425,7 +413,7 @@ ACX_CHECK_COMPILER_FLAG_NEEDED(-D__EXTENSIONS__,
|
|||||||
#include <getopt.h>
|
#include <getopt.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int test(void) {
|
int test() {
|
||||||
int a;
|
int a;
|
||||||
char **opts = NULL;
|
char **opts = NULL;
|
||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
@@ -532,49 +520,6 @@ if test $ac_cv_c_unused_attribute = yes; then
|
|||||||
fi
|
fi
|
||||||
])dnl
|
])dnl
|
||||||
|
|
||||||
dnl Check how to mark function arguments as nonstring.
|
|
||||||
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
|
|
||||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <stdio.h>
|
|
||||||
struct test {
|
|
||||||
char __attribute__((nonstring)) s[1];
|
|
||||||
};
|
|
||||||
]], [[
|
|
||||||
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.
|
|
||||||
dnl make sure you call ACX_CHECK_NONSTRING_ATTRIBUTE also.
|
|
||||||
AC_DEFUN([AHX_CONFIG_NONSTRING_ATTRIBUTE],
|
|
||||||
[
|
|
||||||
#if defined(DOXYGEN)
|
|
||||||
# define ATTR_NONSTRING(x) x
|
|
||||||
#elif defined(__cplusplus)
|
|
||||||
# define ATTR_NONSTRING(x) __attribute__((nonstring)) x
|
|
||||||
#elif defined(HAVE_ATTR_NONSTRING)
|
|
||||||
# define ATTR_NONSTRING(x) __attribute__((nonstring)) x
|
|
||||||
#else /* !HAVE_ATTR_NONSTRING */
|
|
||||||
# define ATTR_NONSTRING(x) x
|
|
||||||
#endif /* !HAVE_ATTR_NONSTRING */
|
|
||||||
])
|
|
||||||
|
|
||||||
AC_MSG_RESULT($ac_cv_c_nonstring_attribute)
|
|
||||||
if test $ac_cv_c_nonstring_attribute = yes; then
|
|
||||||
AC_DEFINE(HAVE_ATTR_NONSTRING, 1, [Whether the C compiler accepts the "nonstring" attribute])
|
|
||||||
fi
|
|
||||||
])dnl
|
|
||||||
|
|
||||||
dnl Pre-fun for ACX_LIBTOOL_C_ONLY
|
dnl Pre-fun for ACX_LIBTOOL_C_ONLY
|
||||||
AC_DEFUN([ACX_LIBTOOL_C_PRE], [
|
AC_DEFUN([ACX_LIBTOOL_C_PRE], [
|
||||||
# skip these tests, we do not need them.
|
# skip these tests, we do not need them.
|
||||||
@@ -790,68 +735,35 @@ AC_DEFUN([ACX_SSL_CHECKS], [
|
|||||||
AC_MSG_RESULT(no)
|
AC_MSG_RESULT(no)
|
||||||
LIBS="$BAKLIBS"
|
LIBS="$BAKLIBS"
|
||||||
LIBSSL_LIBS="$BAKSSLLIBS"
|
LIBSSL_LIBS="$BAKSSLLIBS"
|
||||||
|
LIBS="$LIBS -ldl"
|
||||||
LIBS="$LIBS -lgdi32 -lws2_32 -lcrypt32"
|
LIBSSL_LIBS="$LIBSSL_LIBS -ldl"
|
||||||
LIBSSL_LIBS="$LIBSSL_LIBS -lgdi32 -lws2_32 -lcrypt32"
|
AC_MSG_CHECKING([if -lcrypto needs -ldl])
|
||||||
AC_MSG_CHECKING([if -lcrypto needs -lgdi32 -lws2_32 -lcrypt32])
|
AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[
|
||||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[
|
int EVP_sha256(void);
|
||||||
int EVP_sha256(void);
|
(void)EVP_sha256();
|
||||||
(void)EVP_sha256();
|
]])],[
|
||||||
]])],[
|
AC_DEFINE([HAVE_EVP_SHA256], 1,
|
||||||
AC_DEFINE([HAVE_EVP_SHA256], 1,
|
[If you have EVP_sha256])
|
||||||
[If you have EVP_sha256])
|
AC_MSG_RESULT(yes)
|
||||||
AC_MSG_RESULT(yes)
|
],[
|
||||||
],[
|
AC_MSG_RESULT(no)
|
||||||
AC_MSG_RESULT(no)
|
LIBS="$BAKLIBS"
|
||||||
LIBS="$BAKLIBS"
|
LIBSSL_LIBS="$BAKSSLLIBS"
|
||||||
LIBSSL_LIBS="$BAKSSLLIBS"
|
LIBS="$LIBS -ldl -pthread"
|
||||||
|
LIBSSL_LIBS="$LIBSSL_LIBS -ldl -pthread"
|
||||||
LIBS="$LIBS -lgdi32 -lws2_32 -lcrypt32 -l:libssp.a"
|
AC_MSG_CHECKING([if -lcrypto needs -ldl -pthread])
|
||||||
LIBSSL_LIBS="$LIBSSL_LIBS -lgdi32 -lws2_32 -lcrypt32 -l:libssp.a"
|
AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[
|
||||||
AC_MSG_CHECKING([if -lcrypto needs -lgdi32 -lws2_32 -lcrypt32 -l:libssp.a])
|
int EVP_sha256(void);
|
||||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[
|
(void)EVP_sha256();
|
||||||
int EVP_sha256(void);
|
]])],[
|
||||||
(void)EVP_sha256();
|
AC_DEFINE([HAVE_EVP_SHA256], 1,
|
||||||
]])],[
|
[If you have EVP_sha256])
|
||||||
AC_DEFINE([HAVE_EVP_SHA256], 1,
|
AC_MSG_RESULT(yes)
|
||||||
[If you have EVP_sha256])
|
],[
|
||||||
AC_MSG_RESULT(yes)
|
AC_MSG_RESULT(no)
|
||||||
],[
|
AC_MSG_ERROR([OpenSSL found in $ssldir, but version 0.9.7 or higher is required])
|
||||||
AC_MSG_RESULT(no)
|
|
||||||
LIBS="$BAKLIBS"
|
|
||||||
LIBSSL_LIBS="$BAKSSLLIBS"
|
|
||||||
|
|
||||||
LIBS="$LIBS -ldl"
|
|
||||||
LIBSSL_LIBS="$LIBSSL_LIBS -ldl"
|
|
||||||
AC_MSG_CHECKING([if -lcrypto needs -ldl])
|
|
||||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[
|
|
||||||
int EVP_sha256(void);
|
|
||||||
(void)EVP_sha256();
|
|
||||||
]])],[
|
|
||||||
AC_DEFINE([HAVE_EVP_SHA256], 1,
|
|
||||||
[If you have EVP_sha256])
|
|
||||||
AC_MSG_RESULT(yes)
|
|
||||||
],[
|
|
||||||
AC_MSG_RESULT(no)
|
|
||||||
LIBS="$BAKLIBS"
|
|
||||||
LIBSSL_LIBS="$BAKSSLLIBS"
|
|
||||||
LIBS="$LIBS -ldl -pthread"
|
|
||||||
LIBSSL_LIBS="$LIBSSL_LIBS -ldl -pthread"
|
|
||||||
AC_MSG_CHECKING([if -lcrypto needs -ldl -pthread])
|
|
||||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[
|
|
||||||
int EVP_sha256(void);
|
|
||||||
(void)EVP_sha256();
|
|
||||||
]])],[
|
|
||||||
AC_DEFINE([HAVE_EVP_SHA256], 1,
|
|
||||||
[If you have EVP_sha256])
|
|
||||||
AC_MSG_RESULT(yes)
|
|
||||||
],[
|
|
||||||
AC_MSG_RESULT(no)
|
|
||||||
AC_MSG_ERROR([OpenSSL found in $ssldir, but version 0.9.7 or higher is required])
|
|
||||||
])
|
|
||||||
])
|
|
||||||
])
|
])
|
||||||
])
|
])
|
||||||
])
|
])
|
||||||
])
|
])
|
||||||
fi
|
fi
|
||||||
@@ -922,7 +834,7 @@ dnl try to see if an additional _LARGEFILE_SOURCE 1 is needed to get fseeko
|
|||||||
ACX_CHECK_COMPILER_FLAG_NEEDED(-D_LARGEFILE_SOURCE=1,
|
ACX_CHECK_COMPILER_FLAG_NEEDED(-D_LARGEFILE_SOURCE=1,
|
||||||
[
|
[
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
int test(void) {
|
int test() {
|
||||||
int a = fseeko(stdin, 0, 0);
|
int a = fseeko(stdin, 0, 0);
|
||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
@@ -947,7 +859,7 @@ char* (*f) () = getaddrinfo;
|
|||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
int main(void) {
|
int main() {
|
||||||
;
|
;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -958,7 +870,7 @@ dnl see if on windows
|
|||||||
if test "$ac_cv_header_windows_h" = "yes"; then
|
if test "$ac_cv_header_windows_h" = "yes"; then
|
||||||
AC_DEFINE(USE_WINSOCK, 1, [Whether the windows socket API is used])
|
AC_DEFINE(USE_WINSOCK, 1, [Whether the windows socket API is used])
|
||||||
USE_WINSOCK="1"
|
USE_WINSOCK="1"
|
||||||
if echo "$LIBS" | grep 'lws2_32' >/dev/null; then
|
if echo $LIBS | grep 'lws2_32' >/dev/null; then
|
||||||
:
|
:
|
||||||
else
|
else
|
||||||
LIBS="$LIBS -lws2_32"
|
LIBS="$LIBS -lws2_32"
|
||||||
@@ -966,24 +878,6 @@ if test "$ac_cv_header_windows_h" = "yes"; then
|
|||||||
fi
|
fi
|
||||||
],
|
],
|
||||||
dnl no quick getaddrinfo, try mingw32 and winsock2 library.
|
dnl no quick getaddrinfo, try mingw32 and winsock2 library.
|
||||||
dnl perhaps getaddrinfo needs only the include
|
|
||||||
AC_LINK_IFELSE(
|
|
||||||
[AC_LANG_PROGRAM(
|
|
||||||
[
|
|
||||||
#ifdef HAVE_WS2TCPIP_H
|
|
||||||
#include <ws2tcpip.h>
|
|
||||||
#endif
|
|
||||||
],
|
|
||||||
[
|
|
||||||
(void)getaddrinfo(NULL, NULL, NULL, NULL);
|
|
||||||
]
|
|
||||||
)],
|
|
||||||
[
|
|
||||||
ac_cv_func_getaddrinfo="yes"
|
|
||||||
AC_DEFINE(USE_WINSOCK, 1, [Whether the windows socket API is used])
|
|
||||||
USE_WINSOCK="1"
|
|
||||||
],
|
|
||||||
|
|
||||||
ORIGLIBS="$LIBS"
|
ORIGLIBS="$LIBS"
|
||||||
LIBS="$LIBS -lws2_32"
|
LIBS="$LIBS -lws2_32"
|
||||||
AC_LINK_IFELSE(
|
AC_LINK_IFELSE(
|
||||||
@@ -1008,7 +902,6 @@ ac_cv_func_getaddrinfo="no"
|
|||||||
LIBS="$ORIGLIBS"
|
LIBS="$ORIGLIBS"
|
||||||
])
|
])
|
||||||
)
|
)
|
||||||
)
|
|
||||||
|
|
||||||
AC_MSG_RESULT($ac_cv_func_getaddrinfo)
|
AC_MSG_RESULT($ac_cv_func_getaddrinfo)
|
||||||
if test $ac_cv_func_getaddrinfo = yes; then
|
if test $ac_cv_func_getaddrinfo = yes; then
|
||||||
@@ -1030,7 +923,7 @@ cache=`echo $1 | sed 'y%.=/+-%___p_%'`
|
|||||||
AC_CACHE_VAL(cv_cc_deprecated_$cache,
|
AC_CACHE_VAL(cv_cc_deprecated_$cache,
|
||||||
[
|
[
|
||||||
echo '$3' >conftest.c
|
echo '$3' >conftest.c
|
||||||
echo 'void f(void){ $2 }' >>conftest.c
|
echo 'void f(){ $2 }' >>conftest.c
|
||||||
if test -z "`$CC $CPPFLAGS $CFLAGS -c conftest.c 2>&1 | grep -e deprecated -e unavailable`"; then
|
if test -z "`$CC $CPPFLAGS $CFLAGS -c conftest.c 2>&1 | grep -e deprecated -e unavailable`"; then
|
||||||
eval "cv_cc_deprecated_$cache=no"
|
eval "cv_cc_deprecated_$cache=no"
|
||||||
else
|
else
|
||||||
@@ -1240,9 +1133,8 @@ dnl detect malloc and provide malloc compat prototype.
|
|||||||
dnl $1: unique name for compat code
|
dnl $1: unique name for compat code
|
||||||
AC_DEFUN([ACX_FUNC_MALLOC],
|
AC_DEFUN([ACX_FUNC_MALLOC],
|
||||||
[
|
[
|
||||||
AC_CACHE_CHECK([for GNU libc compatible malloc],[ac_cv_func_malloc_0_nonnull],
|
AC_MSG_CHECKING([for GNU libc compatible malloc])
|
||||||
[
|
AC_RUN_IFELSE([AC_LANG_PROGRAM(
|
||||||
AC_RUN_IFELSE([AC_LANG_PROGRAM(
|
|
||||||
[[#if defined STDC_HEADERS || defined HAVE_STDLIB_H
|
[[#if defined STDC_HEADERS || defined HAVE_STDLIB_H
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#else
|
#else
|
||||||
@@ -1250,16 +1142,14 @@ char *malloc ();
|
|||||||
#endif
|
#endif
|
||||||
]], [ if(malloc(0) != 0) return 1;])
|
]], [ if(malloc(0) != 0) return 1;])
|
||||||
],
|
],
|
||||||
[ac_cv_func_malloc_0_nonnull=no],
|
[AC_MSG_RESULT([no])
|
||||||
[ac_cv_func_malloc_0_nonnull=yes],
|
AC_LIBOBJ(malloc)
|
||||||
[ac_cv_func_malloc_0_nonnull="no (crosscompile)"])
|
AC_DEFINE_UNQUOTED([malloc], [rpl_malloc_$1], [Define if replacement function should be used.])] ,
|
||||||
])
|
[AC_MSG_RESULT([yes])
|
||||||
AS_IF([test "$ac_cv_func_malloc_0_nonnull" = yes],
|
AC_DEFINE([HAVE_MALLOC], 1, [If have GNU libc compatible malloc])],
|
||||||
[AC_DEFINE([HAVE_MALLOC], 1, [If have GNU libc compatible malloc])],
|
[AC_MSG_RESULT([no (crosscompile)])
|
||||||
[
|
AC_LIBOBJ(malloc)
|
||||||
AC_LIBOBJ(malloc)
|
AC_DEFINE_UNQUOTED([malloc], [rpl_malloc_$1], [Define if replacement function should be used.])] )
|
||||||
AC_DEFINE_UNQUOTED([malloc], [rpl_malloc_$1], [Define if replacement function should be used.])
|
|
||||||
])
|
|
||||||
])
|
])
|
||||||
|
|
||||||
dnl Define fallback for fseeko and ftello if needed.
|
dnl Define fallback for fseeko and ftello if needed.
|
||||||
@@ -1465,7 +1355,7 @@ dnl $3: define value, 1
|
|||||||
AC_DEFUN([AHX_CONFIG_FLAG_OMITTED],
|
AC_DEFUN([AHX_CONFIG_FLAG_OMITTED],
|
||||||
[#if defined($1) && !defined($2)
|
[#if defined($1) && !defined($2)
|
||||||
#define $2 $3
|
#define $2 $3
|
||||||
[#]endif])
|
[#]endif ])
|
||||||
|
|
||||||
dnl Wrapper for AHX_CONFIG_FLAG_OMITTED for -D style flags
|
dnl Wrapper for AHX_CONFIG_FLAG_OMITTED for -D style flags
|
||||||
dnl $1: the -DNAME or -DNAME=value string.
|
dnl $1: the -DNAME or -DNAME=value string.
|
||||||
|
|||||||
+17
-46
@@ -9,7 +9,7 @@ AC_DEFUN([AC_PYTHON_DEVEL],[
|
|||||||
|
|
||||||
AC_PATH_PROG([PYTHON],[python[$PYTHON_VERSION]])
|
AC_PATH_PROG([PYTHON],[python[$PYTHON_VERSION]])
|
||||||
if test -z "$PYTHON"; then
|
if test -z "$PYTHON"; then
|
||||||
AC_MSG_ERROR([Cannot find 'python$PYTHON_VERSION' in your system path. You can use the environment variable 'PYTHON_VERSION=version_number' for an explicit version.])
|
AC_MSG_ERROR([Cannot find python$PYTHON_VERSION in your system path])
|
||||||
PYTHON_VERSION=""
|
PYTHON_VERSION=""
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -17,62 +17,33 @@ AC_DEFUN([AC_PYTHON_DEVEL],[
|
|||||||
PYTHON_VERSION=`$PYTHON -c "import sys; \
|
PYTHON_VERSION=`$PYTHON -c "import sys; \
|
||||||
print(sys.version.split()[[0]])"`
|
print(sys.version.split()[[0]])"`
|
||||||
fi
|
fi
|
||||||
# calculate the version number components.
|
|
||||||
[
|
|
||||||
v="$PYTHON_VERSION"
|
|
||||||
PYTHON_VERSION_MAJOR=`echo $v | sed 's/[^0-9].*//'`
|
|
||||||
if test -z "$PYTHON_VERSION_MAJOR"; then PYTHON_VERSION_MAJOR="0"; fi
|
|
||||||
v=`echo $v | sed -e 's/^[0-9]*$//' -e 's/[0-9]*[^0-9]//'`
|
|
||||||
PYTHON_VERSION_MINOR=`echo $v | sed 's/[^0-9].*//'`
|
|
||||||
if test -z "$PYTHON_VERSION_MINOR"; then PYTHON_VERSION_MINOR="0"; fi
|
|
||||||
v=`echo $v | sed -e 's/^[0-9]*$//' -e 's/[0-9]*[^0-9]//'`
|
|
||||||
PYTHON_VERSION_PATCH=`echo $v | sed 's/[^0-9].*//'`
|
|
||||||
if test -z "$PYTHON_VERSION_PATCH"; then PYTHON_VERSION_PATCH="0"; fi
|
|
||||||
]
|
|
||||||
|
|
||||||
# For some systems, sysconfig exists, but has the wrong paths,
|
# Check if you have sysconfig
|
||||||
# on Debian 10, for python 2.7 and 3.7. So, we check the version,
|
AC_MSG_CHECKING([for the sysconfig Python module])
|
||||||
# and for older versions try distutils.sysconfig first. For newer
|
if ac_sysconfig_result=`$PYTHON -c "import sysconfig" 2>&1`; then
|
||||||
# versions>=3.10, where distutils.sysconfig is deprecated, use
|
|
||||||
# sysconfig first and then attempt the other one.
|
|
||||||
py_distutils_first="no"
|
|
||||||
if test $PYTHON_VERSION_MAJOR -lt 3; then
|
|
||||||
py_distutils_first="yes"
|
|
||||||
fi
|
|
||||||
if test $PYTHON_VERSION_MAJOR -eq 3 -a $PYTHON_VERSION_MINOR -lt 10; then
|
|
||||||
py_distutils_first="yes"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Check if you have the first module
|
|
||||||
if test "$py_distutils_first" = "yes"; then m="distutils"; else m="sysconfig"; fi
|
|
||||||
sysconfig_module=""
|
|
||||||
AC_MSG_CHECKING([for the $m Python module])
|
|
||||||
if ac_modulecheck_result1=`$PYTHON -c "import $m" 2>&1`; then
|
|
||||||
AC_MSG_RESULT([yes])
|
AC_MSG_RESULT([yes])
|
||||||
sysconfig_module="$m"
|
sysconfig_module="sysconfig"
|
||||||
|
# if yes, use sysconfig, because distutils is deprecated.
|
||||||
else
|
else
|
||||||
AC_MSG_RESULT([no])
|
AC_MSG_RESULT([no])
|
||||||
fi
|
# if no, try to use distutils
|
||||||
|
|
||||||
# if not found, try the other one.
|
#
|
||||||
if test -z "$sysconfig_module"; then
|
# Check if you have distutils, else fail
|
||||||
if test "$py_distutils_first" = "yes"; then m2="sysconfig"; else m2="distutils"; fi
|
#
|
||||||
AC_MSG_CHECKING([for the $m2 Python module])
|
AC_MSG_CHECKING([for the distutils Python package])
|
||||||
if ac_modulecheck_result2=`$PYTHON -c "import $m2" 2>&1`; then
|
if ac_distutils_result=`$PYTHON -c "import distutils" 2>&1`; then
|
||||||
AC_MSG_RESULT([yes])
|
AC_MSG_RESULT([yes])
|
||||||
sysconfig_module="$m2"
|
|
||||||
else
|
else
|
||||||
AC_MSG_RESULT([no])
|
AC_MSG_RESULT([no])
|
||||||
AC_MSG_ERROR([cannot import Python module "$m", or "$m2".
|
AC_MSG_ERROR([cannot import Python module "distutils".
|
||||||
Please check your Python installation. The errors are:
|
Please check your Python installation. The error was:
|
||||||
$m
|
$ac_distutils_result])
|
||||||
$ac_modulecheck_result1
|
|
||||||
$m2
|
|
||||||
$ac_modulecheck_result2])
|
|
||||||
PYTHON_VERSION=""
|
PYTHON_VERSION=""
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
sysconfig_module="distutils.sysconfig"
|
||||||
fi
|
fi
|
||||||
if test "$sysconfig_module" = "distutils"; then sysconfig_module="distutils.sysconfig"; fi
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Check for Python include path
|
# Check for Python include path
|
||||||
|
|||||||
@@ -1,70 +0,0 @@
|
|||||||
# ===========================================================================
|
|
||||||
# https://www.gnu.org/software/autoconf-archive/ax_build_date_epoch.html
|
|
||||||
# ===========================================================================
|
|
||||||
#
|
|
||||||
# SYNOPSIS
|
|
||||||
#
|
|
||||||
# AX_BUILD_DATE_EPOCH(VARIABLE[, FORMAT[, ACTION-IF-FAIL]])
|
|
||||||
#
|
|
||||||
# DESCRIPTION
|
|
||||||
#
|
|
||||||
# Sets VARIABLE to a string representing the current time. It is
|
|
||||||
# formatted according to FORMAT if specified, otherwise it is formatted as
|
|
||||||
# the number of seconds (excluding leap seconds) since the UNIX epoch (01
|
|
||||||
# Jan 1970 00:00:00 UTC).
|
|
||||||
#
|
|
||||||
# If the SOURCE_DATE_EPOCH environment variable is set, it uses the value
|
|
||||||
# of that variable instead of the current time. See
|
|
||||||
# https://reproducible-builds.org/specs/source-date-epoch). If
|
|
||||||
# SOURCE_DATE_EPOCH is set but cannot be properly interpreted as a UNIX
|
|
||||||
# timestamp, then execute ACTION-IF-FAIL if specified, otherwise error.
|
|
||||||
#
|
|
||||||
# VARIABLE is AC_SUBST-ed.
|
|
||||||
#
|
|
||||||
# LICENSE
|
|
||||||
#
|
|
||||||
# Copyright (c) 2016 Eric Bavier <bavier@member.fsf.org>
|
|
||||||
#
|
|
||||||
# This program is free software: you can redistribute it and/or modify it
|
|
||||||
# under the terms of the GNU General Public License as published by the
|
|
||||||
# Free Software Foundation, either version 3 of the License, or (at your
|
|
||||||
# option) any later version.
|
|
||||||
#
|
|
||||||
# This program is distributed in the hope that it will be useful, but
|
|
||||||
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
|
||||||
# Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU General Public License along
|
|
||||||
# with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
#
|
|
||||||
# As a special exception, the respective Autoconf Macro's copyright owner
|
|
||||||
# gives unlimited permission to copy, distribute and modify the configure
|
|
||||||
# scripts that are the output of Autoconf when processing the Macro. You
|
|
||||||
# need not follow the terms of the GNU General Public License when using
|
|
||||||
# or distributing such scripts, even though portions of the text of the
|
|
||||||
# Macro appear in them. The GNU General Public License (GPL) does govern
|
|
||||||
# all other use of the material that constitutes the Autoconf Macro.
|
|
||||||
#
|
|
||||||
# This special exception to the GPL applies to versions of the Autoconf
|
|
||||||
# Macro released by the Autoconf Archive. When you make and distribute a
|
|
||||||
# modified version of the Autoconf Macro, you may extend this special
|
|
||||||
# exception to the GPL to apply to your modified version as well.
|
|
||||||
|
|
||||||
#serial 2
|
|
||||||
|
|
||||||
AC_DEFUN([AX_BUILD_DATE_EPOCH],
|
|
||||||
[dnl
|
|
||||||
AC_MSG_CHECKING([for build time])
|
|
||||||
ax_date_fmt="m4_default($2,%s)"
|
|
||||||
AS_IF([test x"$SOURCE_DATE_EPOCH" = x],
|
|
||||||
[$1=`date "+$ax_date_fmt"`],
|
|
||||||
[ax_build_date=`date -u -d "@$SOURCE_DATE_EPOCH" "+$ax_date_fmt" 2>/dev/null \
|
|
||||||
|| date -u -r "$SOURCE_DATE_EPOCH" "+$ax_date_fmt" 2>/dev/null`
|
|
||||||
AS_IF([test x"$ax_build_date" = x],
|
|
||||||
[m4_ifval([$3],
|
|
||||||
[$3],
|
|
||||||
[AC_MSG_ERROR([malformed SOURCE_DATE_EPOCH])])],
|
|
||||||
[$1=$ax_build_date])])
|
|
||||||
AC_MSG_RESULT([$$1])
|
|
||||||
])dnl AX_BUILD_DATE_EPOCH
|
|
||||||
+127
-332
@@ -1,5 +1,5 @@
|
|||||||
# ===========================================================================
|
# ===========================================================================
|
||||||
# https://www.gnu.org/software/autoconf-archive/ax_pthread.html
|
# http://www.gnu.org/software/autoconf-archive/ax_pthread.html
|
||||||
# ===========================================================================
|
# ===========================================================================
|
||||||
#
|
#
|
||||||
# SYNOPSIS
|
# SYNOPSIS
|
||||||
@@ -14,28 +14,24 @@
|
|||||||
# flags that are needed. (The user can also force certain compiler
|
# flags that are needed. (The user can also force certain compiler
|
||||||
# flags/libs to be tested by setting these environment variables.)
|
# flags/libs to be tested by setting these environment variables.)
|
||||||
#
|
#
|
||||||
# Also sets PTHREAD_CC and PTHREAD_CXX to any special C compiler that is
|
# Also sets PTHREAD_CC to any special C compiler that is needed for
|
||||||
# needed for multi-threaded programs (defaults to the value of CC
|
# multi-threaded programs (defaults to the value of CC otherwise). (This
|
||||||
# respectively CXX otherwise). (This is necessary on e.g. AIX to use the
|
# is necessary on AIX to use the special cc_r compiler alias.)
|
||||||
# special cc_r/CC_r compiler alias.)
|
|
||||||
#
|
#
|
||||||
# NOTE: You are assumed to not only compile your program with these flags,
|
# NOTE: You are assumed to not only compile your program with these flags,
|
||||||
# but also to link with them as well. For example, you might link with
|
# but also link it with them as well. e.g. you should link with
|
||||||
# $PTHREAD_CC $CFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS $LIBS
|
# $PTHREAD_CC $CFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS $LIBS
|
||||||
# $PTHREAD_CXX $CXXFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS $LIBS
|
|
||||||
#
|
#
|
||||||
# If you are only building threaded programs, you may wish to use these
|
# If you are only building threads programs, you may wish to use these
|
||||||
# variables in your default LIBS, CFLAGS, and CC:
|
# variables in your default LIBS, CFLAGS, and CC:
|
||||||
#
|
#
|
||||||
# LIBS="$PTHREAD_LIBS $LIBS"
|
# LIBS="$PTHREAD_LIBS $LIBS"
|
||||||
# CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
|
# CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
|
||||||
# CXXFLAGS="$CXXFLAGS $PTHREAD_CFLAGS"
|
|
||||||
# CC="$PTHREAD_CC"
|
# CC="$PTHREAD_CC"
|
||||||
# CXX="$PTHREAD_CXX"
|
|
||||||
#
|
#
|
||||||
# In addition, if the PTHREAD_CREATE_JOINABLE thread-attribute constant
|
# In addition, if the PTHREAD_CREATE_JOINABLE thread-attribute constant
|
||||||
# has a nonstandard name, this macro defines PTHREAD_CREATE_JOINABLE to
|
# has a nonstandard name, defines PTHREAD_CREATE_JOINABLE to that name
|
||||||
# that name (e.g. PTHREAD_CREATE_UNDETACHED on AIX).
|
# (e.g. PTHREAD_CREATE_UNDETACHED on AIX).
|
||||||
#
|
#
|
||||||
# Also HAVE_PTHREAD_PRIO_INHERIT is defined if pthread is found and the
|
# Also HAVE_PTHREAD_PRIO_INHERIT is defined if pthread is found and the
|
||||||
# PTHREAD_PRIO_INHERIT symbol is defined when compiling with
|
# PTHREAD_PRIO_INHERIT symbol is defined when compiling with
|
||||||
@@ -59,7 +55,6 @@
|
|||||||
#
|
#
|
||||||
# Copyright (c) 2008 Steven G. Johnson <stevenj@alum.mit.edu>
|
# Copyright (c) 2008 Steven G. Johnson <stevenj@alum.mit.edu>
|
||||||
# Copyright (c) 2011 Daniel Richard G. <skunk@iSKUNK.ORG>
|
# Copyright (c) 2011 Daniel Richard G. <skunk@iSKUNK.ORG>
|
||||||
# Copyright (c) 2019 Marc Stevens <marc.stevens@cwi.nl>
|
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it
|
# This program is free software: you can redistribute it and/or modify it
|
||||||
# under the terms of the GNU General Public License as published by the
|
# under the terms of the GNU General Public License as published by the
|
||||||
@@ -72,7 +67,7 @@
|
|||||||
# Public License for more details.
|
# Public License for more details.
|
||||||
#
|
#
|
||||||
# You should have received a copy of the GNU General Public License along
|
# You should have received a copy of the GNU General Public License along
|
||||||
# with this program. If not, see <https://www.gnu.org/licenses/>.
|
# with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
#
|
#
|
||||||
# As a special exception, the respective Autoconf Macro's copyright owner
|
# As a special exception, the respective Autoconf Macro's copyright owner
|
||||||
# gives unlimited permission to copy, distribute and modify the configure
|
# gives unlimited permission to copy, distribute and modify the configure
|
||||||
@@ -87,41 +82,35 @@
|
|||||||
# modified version of the Autoconf Macro, you may extend this special
|
# modified version of the Autoconf Macro, you may extend this special
|
||||||
# exception to the GPL to apply to your modified version as well.
|
# exception to the GPL to apply to your modified version as well.
|
||||||
|
|
||||||
#serial 32
|
#serial 21
|
||||||
|
|
||||||
AU_ALIAS([ACX_PTHREAD], [AX_PTHREAD])
|
AU_ALIAS([ACX_PTHREAD], [AX_PTHREAD])
|
||||||
AC_DEFUN([AX_PTHREAD], [
|
AC_DEFUN([AX_PTHREAD], [
|
||||||
AC_REQUIRE([AC_CANONICAL_HOST])
|
AC_REQUIRE([AC_CANONICAL_HOST])
|
||||||
AC_REQUIRE([AC_PROG_CC])
|
|
||||||
AC_REQUIRE([AC_PROG_SED])
|
|
||||||
AC_LANG_PUSH([C])
|
AC_LANG_PUSH([C])
|
||||||
ax_pthread_ok=no
|
ax_pthread_ok=no
|
||||||
|
|
||||||
# We used to check for pthread.h first, but this fails if pthread.h
|
# We used to check for pthread.h first, but this fails if pthread.h
|
||||||
# requires special compiler flags (e.g. on Tru64 or Sequent).
|
# requires special compiler flags (e.g. on True64 or Sequent).
|
||||||
# It gets checked for in the link test anyway.
|
# It gets checked for in the link test anyway.
|
||||||
|
|
||||||
# First of all, check if the user has set any of the PTHREAD_LIBS,
|
# First of all, check if the user has set any of the PTHREAD_LIBS,
|
||||||
# etcetera environment variables, and if threads linking works using
|
# etcetera environment variables, and if threads linking works using
|
||||||
# them:
|
# them:
|
||||||
if test "x$PTHREAD_CFLAGS$PTHREAD_LIBS" != "x"; then
|
if test x"$PTHREAD_LIBS$PTHREAD_CFLAGS" != x; then
|
||||||
ax_pthread_save_CC="$CC"
|
save_CFLAGS="$CFLAGS"
|
||||||
ax_pthread_save_CFLAGS="$CFLAGS"
|
|
||||||
ax_pthread_save_LIBS="$LIBS"
|
|
||||||
AS_IF([test "x$PTHREAD_CC" != "x"], [CC="$PTHREAD_CC"])
|
|
||||||
AS_IF([test "x$PTHREAD_CXX" != "x"], [CXX="$PTHREAD_CXX"])
|
|
||||||
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
|
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
|
||||||
|
save_LIBS="$LIBS"
|
||||||
LIBS="$PTHREAD_LIBS $LIBS"
|
LIBS="$PTHREAD_LIBS $LIBS"
|
||||||
AC_MSG_CHECKING([for pthread_join using $CC $PTHREAD_CFLAGS $PTHREAD_LIBS])
|
AC_MSG_CHECKING([for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS])
|
||||||
AC_LINK_IFELSE([AC_LANG_CALL([], [pthread_join])], [ax_pthread_ok=yes])
|
AC_TRY_LINK_FUNC([pthread_join], [ax_pthread_ok=yes])
|
||||||
AC_MSG_RESULT([$ax_pthread_ok])
|
AC_MSG_RESULT([$ax_pthread_ok])
|
||||||
if test "x$ax_pthread_ok" = "xno"; then
|
if test x"$ax_pthread_ok" = xno; then
|
||||||
PTHREAD_LIBS=""
|
PTHREAD_LIBS=""
|
||||||
PTHREAD_CFLAGS=""
|
PTHREAD_CFLAGS=""
|
||||||
fi
|
fi
|
||||||
CC="$ax_pthread_save_CC"
|
LIBS="$save_LIBS"
|
||||||
CFLAGS="$ax_pthread_save_CFLAGS"
|
CFLAGS="$save_CFLAGS"
|
||||||
LIBS="$ax_pthread_save_LIBS"
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# We must check for the threads library under a number of different
|
# We must check for the threads library under a number of different
|
||||||
@@ -129,14 +118,12 @@ fi
|
|||||||
# (e.g. DEC) have both -lpthread and -lpthreads, where one of the
|
# (e.g. DEC) have both -lpthread and -lpthreads, where one of the
|
||||||
# libraries is broken (non-POSIX).
|
# libraries is broken (non-POSIX).
|
||||||
|
|
||||||
# Create a list of thread flags to try. Items with a "," contain both
|
# Create a list of thread flags to try. Items starting with a "-" are
|
||||||
# C compiler flags (before ",") and linker flags (after ","). Other items
|
# C compiler flags, and other items are library names, except for "none"
|
||||||
# starting with a "-" are C compiler flags, and remaining items are
|
# which indicates that we try without any flags at all, and "pthread-config"
|
||||||
# library names, except for "none" which indicates that we try without
|
# which is a program returning the flags for the Pth emulation library.
|
||||||
# any flags at all, and "pthread-config" which is a program returning
|
|
||||||
# the flags for the Pth emulation library.
|
|
||||||
|
|
||||||
ax_pthread_flags="pthreads none -Kthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config"
|
ax_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config"
|
||||||
|
|
||||||
# The ordering *is* (sometimes) important. Some notes on the
|
# The ordering *is* (sometimes) important. Some notes on the
|
||||||
# individual items follow:
|
# individual items follow:
|
||||||
@@ -145,178 +132,82 @@ ax_pthread_flags="pthreads none -Kthread -pthread -pthreads -mthreads pthread --
|
|||||||
# none: in case threads are in libc; should be tried before -Kthread and
|
# none: in case threads are in libc; should be tried before -Kthread and
|
||||||
# other compiler flags to prevent continual compiler warnings
|
# other compiler flags to prevent continual compiler warnings
|
||||||
# -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h)
|
# -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h)
|
||||||
# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads), Tru64
|
# -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able)
|
||||||
# (Note: HP C rejects this with "bad form for `-t' option")
|
# lthread: LinuxThreads port on FreeBSD (also preferred to -pthread)
|
||||||
# -pthreads: Solaris/gcc (Note: HP C also rejects)
|
# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads)
|
||||||
# -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it
|
# -pthreads: Solaris/gcc
|
||||||
# doesn't hurt to check since this sometimes defines pthreads and
|
|
||||||
# -D_REENTRANT too), HP C (must be checked before -lpthread, which
|
|
||||||
# is present but should not be used directly; and before -mthreads,
|
|
||||||
# because the compiler interprets this as "-mt" + "-hreads")
|
|
||||||
# -mthreads: Mingw32/gcc, Lynx/gcc
|
# -mthreads: Mingw32/gcc, Lynx/gcc
|
||||||
|
# -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it
|
||||||
|
# doesn't hurt to check since this sometimes defines pthreads too;
|
||||||
|
# also defines -D_REENTRANT)
|
||||||
|
# ... -mt is also the pthreads flag for HP/aCC
|
||||||
# pthread: Linux, etcetera
|
# pthread: Linux, etcetera
|
||||||
# --thread-safe: KAI C++
|
# --thread-safe: KAI C++
|
||||||
# pthread-config: use pthread-config program (for GNU Pth library)
|
# pthread-config: use pthread-config program (for GNU Pth library)
|
||||||
|
|
||||||
case $host_os in
|
case ${host_os} in
|
||||||
|
|
||||||
freebsd*)
|
|
||||||
|
|
||||||
# -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able)
|
|
||||||
# lthread: LinuxThreads port on FreeBSD (also preferred to -pthread)
|
|
||||||
|
|
||||||
ax_pthread_flags="-kthread lthread $ax_pthread_flags"
|
|
||||||
;;
|
|
||||||
|
|
||||||
hpux*)
|
|
||||||
|
|
||||||
# From the cc(1) man page: "[-mt] Sets various -D flags to enable
|
|
||||||
# multi-threading and also sets -lpthread."
|
|
||||||
|
|
||||||
ax_pthread_flags="-mt -pthread pthread $ax_pthread_flags"
|
|
||||||
;;
|
|
||||||
|
|
||||||
openedition*)
|
|
||||||
|
|
||||||
# IBM z/OS requires a feature-test macro to be defined in order to
|
|
||||||
# enable POSIX threads at all, so give the user a hint if this is
|
|
||||||
# not set. (We don't define these ourselves, as they can affect
|
|
||||||
# other portions of the system API in unpredictable ways.)
|
|
||||||
|
|
||||||
AC_EGREP_CPP([AX_PTHREAD_ZOS_MISSING],
|
|
||||||
[
|
|
||||||
# if !defined(_OPEN_THREADS) && !defined(_UNIX03_THREADS)
|
|
||||||
AX_PTHREAD_ZOS_MISSING
|
|
||||||
# endif
|
|
||||||
],
|
|
||||||
[AC_MSG_WARN([IBM z/OS requires -D_OPEN_THREADS or -D_UNIX03_THREADS to enable pthreads support.])])
|
|
||||||
;;
|
|
||||||
|
|
||||||
solaris*)
|
solaris*)
|
||||||
|
|
||||||
# On Solaris (at least, for some versions), libc contains stubbed
|
# On Solaris (at least, for some versions), libc contains stubbed
|
||||||
# (non-functional) versions of the pthreads routines, so link-based
|
# (non-functional) versions of the pthreads routines, so link-based
|
||||||
# tests will erroneously succeed. (N.B.: The stubs are missing
|
# tests will erroneously succeed. (We need to link with -pthreads/-mt/
|
||||||
# pthread_cleanup_push, or rather a function called by this macro,
|
# -lpthread.) (The stubs are missing pthread_cleanup_push, or rather
|
||||||
# so we could check for that, but who knows whether they'll stub
|
# a function called by this macro, so we could check for that, but
|
||||||
# that too in a future libc.) So we'll check first for the
|
# who knows whether they'll stub that too in a future libc.) So,
|
||||||
# standard Solaris way of linking pthreads (-mt -lpthread).
|
# we'll just look for -pthreads and -lpthread first:
|
||||||
|
|
||||||
ax_pthread_flags="-mt,-lpthread pthread $ax_pthread_flags"
|
ax_pthread_flags="-pthreads pthread -mt -pthread $ax_pthread_flags"
|
||||||
|
;;
|
||||||
|
|
||||||
|
darwin*)
|
||||||
|
ax_pthread_flags="-pthread $ax_pthread_flags"
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
# Are we compiling with Clang?
|
# Clang doesn't consider unrecognized options an error unless we specify
|
||||||
|
# -Werror. We throw in some extra Clang-specific options to ensure that
|
||||||
|
# this doesn't happen for GCC, which also accepts -Werror.
|
||||||
|
|
||||||
AC_CACHE_CHECK([whether $CC is Clang],
|
AC_MSG_CHECKING([if compiler needs -Werror to reject unknown flags])
|
||||||
[ax_cv_PTHREAD_CLANG],
|
save_CFLAGS="$CFLAGS"
|
||||||
[ax_cv_PTHREAD_CLANG=no
|
ax_pthread_extra_flags="-Werror"
|
||||||
# Note that Autoconf sets GCC=yes for Clang as well as GCC
|
CFLAGS="$CFLAGS $ax_pthread_extra_flags -Wunknown-warning-option -Wsizeof-array-argument"
|
||||||
if test "x$GCC" = "xyes"; then
|
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([int foo(void);],[foo()])],
|
||||||
AC_EGREP_CPP([AX_PTHREAD_CC_IS_CLANG],
|
[AC_MSG_RESULT([yes])],
|
||||||
[/* Note: Clang 2.7 lacks __clang_[a-z]+__ */
|
[ax_pthread_extra_flags=
|
||||||
# if defined(__clang__) && defined(__llvm__)
|
AC_MSG_RESULT([no])])
|
||||||
AX_PTHREAD_CC_IS_CLANG
|
CFLAGS="$save_CFLAGS"
|
||||||
# endif
|
|
||||||
],
|
|
||||||
[ax_cv_PTHREAD_CLANG=yes])
|
|
||||||
fi
|
|
||||||
])
|
|
||||||
ax_pthread_clang="$ax_cv_PTHREAD_CLANG"
|
|
||||||
|
|
||||||
|
if test x"$ax_pthread_ok" = xno; then
|
||||||
|
for flag in $ax_pthread_flags; do
|
||||||
|
|
||||||
# GCC generally uses -pthread, or -pthreads on some platforms (e.g. SPARC)
|
case $flag in
|
||||||
|
|
||||||
# Note that for GCC and Clang -pthread generally implies -lpthread,
|
|
||||||
# except when -nostdlib is passed.
|
|
||||||
# This is problematic using libtool to build C++ shared libraries with pthread:
|
|
||||||
# [1] https://gcc.gnu.org/bugzilla/show_bug.cgi?id=25460
|
|
||||||
# [2] https://bugzilla.redhat.com/show_bug.cgi?id=661333
|
|
||||||
# [3] https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=468555
|
|
||||||
# To solve this, first try -pthread together with -lpthread for GCC
|
|
||||||
|
|
||||||
AS_IF([test "x$GCC" = "xyes"],
|
|
||||||
[ax_pthread_flags="-pthread,-lpthread -pthread -pthreads $ax_pthread_flags"])
|
|
||||||
|
|
||||||
# Clang takes -pthread (never supported any other flag), but we'll try with -lpthread first
|
|
||||||
|
|
||||||
AS_IF([test "x$ax_pthread_clang" = "xyes"],
|
|
||||||
[ax_pthread_flags="-pthread,-lpthread -pthread"])
|
|
||||||
|
|
||||||
|
|
||||||
# The presence of a feature test macro requesting re-entrant function
|
|
||||||
# definitions is, on some systems, a strong hint that pthreads support is
|
|
||||||
# correctly enabled
|
|
||||||
|
|
||||||
case $host_os in
|
|
||||||
solaris*)
|
|
||||||
# Solaris 11.4 introduced XPG7 support and did away with the need for
|
|
||||||
# _REENTRANT.
|
|
||||||
|
|
||||||
AC_EGREP_CPP([AX_PTHREAD_SOLARIS__REENTRANT],
|
|
||||||
[
|
|
||||||
# undef _XOPEN_SOURCE
|
|
||||||
# include <sys/feature_tests.h>
|
|
||||||
# if _XOPEN_VERSION < 700
|
|
||||||
AX_PTHREAD_SOLARIS__REENTRANT
|
|
||||||
# endif
|
|
||||||
],
|
|
||||||
[ax_pthread_check_macro="_REENTRANT"],
|
|
||||||
[ax_pthread_check_macro="--"])
|
|
||||||
;;
|
|
||||||
darwin* | hpux* | linux* | osf*)
|
|
||||||
ax_pthread_check_macro="_REENTRANT"
|
|
||||||
;;
|
|
||||||
|
|
||||||
aix*)
|
|
||||||
ax_pthread_check_macro="_THREAD_SAFE"
|
|
||||||
;;
|
|
||||||
|
|
||||||
*)
|
|
||||||
ax_pthread_check_macro="--"
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
AS_IF([test "x$ax_pthread_check_macro" = "x--"],
|
|
||||||
[ax_pthread_check_cond=0],
|
|
||||||
[ax_pthread_check_cond="!defined($ax_pthread_check_macro)"])
|
|
||||||
|
|
||||||
|
|
||||||
if test "x$ax_pthread_ok" = "xno"; then
|
|
||||||
for ax_pthread_try_flag in $ax_pthread_flags; do
|
|
||||||
|
|
||||||
case $ax_pthread_try_flag in
|
|
||||||
none)
|
none)
|
||||||
AC_MSG_CHECKING([whether pthreads work without any flags])
|
AC_MSG_CHECKING([whether pthreads work without any flags])
|
||||||
;;
|
;;
|
||||||
|
|
||||||
*,*)
|
|
||||||
PTHREAD_CFLAGS=`echo $ax_pthread_try_flag | sed "s/^\(.*\),\(.*\)$/\1/"`
|
|
||||||
PTHREAD_LIBS=`echo $ax_pthread_try_flag | sed "s/^\(.*\),\(.*\)$/\2/"`
|
|
||||||
AC_MSG_CHECKING([whether pthreads work with "$PTHREAD_CFLAGS" and "$PTHREAD_LIBS"])
|
|
||||||
;;
|
|
||||||
|
|
||||||
-*)
|
-*)
|
||||||
AC_MSG_CHECKING([whether pthreads work with $ax_pthread_try_flag])
|
AC_MSG_CHECKING([whether pthreads work with $flag])
|
||||||
PTHREAD_CFLAGS="$ax_pthread_try_flag"
|
PTHREAD_CFLAGS="$flag"
|
||||||
;;
|
;;
|
||||||
|
|
||||||
pthread-config)
|
pthread-config)
|
||||||
AC_CHECK_PROG([ax_pthread_config], [pthread-config], [yes], [no])
|
AC_CHECK_PROG([ax_pthread_config], [pthread-config], [yes], [no])
|
||||||
AS_IF([test "x$ax_pthread_config" = "xno"], [continue])
|
if test x"$ax_pthread_config" = xno; then continue; fi
|
||||||
PTHREAD_CFLAGS="`pthread-config --cflags`"
|
PTHREAD_CFLAGS="`pthread-config --cflags`"
|
||||||
PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`"
|
PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`"
|
||||||
;;
|
;;
|
||||||
|
|
||||||
*)
|
*)
|
||||||
AC_MSG_CHECKING([for the pthreads library -l$ax_pthread_try_flag])
|
AC_MSG_CHECKING([for the pthreads library -l$flag])
|
||||||
PTHREAD_LIBS="-l$ax_pthread_try_flag"
|
PTHREAD_LIBS="-l$flag"
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
ax_pthread_save_CFLAGS="$CFLAGS"
|
save_LIBS="$LIBS"
|
||||||
ax_pthread_save_LIBS="$LIBS"
|
save_CFLAGS="$CFLAGS"
|
||||||
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
|
|
||||||
LIBS="$PTHREAD_LIBS $LIBS"
|
LIBS="$PTHREAD_LIBS $LIBS"
|
||||||
|
CFLAGS="$CFLAGS $PTHREAD_CFLAGS $ax_pthread_extra_flags"
|
||||||
|
|
||||||
# Check for various functions. We must include pthread.h,
|
# Check for various functions. We must include pthread.h,
|
||||||
# since some functions may be macros. (On the Sequent, we
|
# since some functions may be macros. (On the Sequent, we
|
||||||
@@ -327,18 +218,8 @@ for ax_pthread_try_flag in $ax_pthread_flags; do
|
|||||||
# pthread_cleanup_push because it is one of the few pthread
|
# pthread_cleanup_push because it is one of the few pthread
|
||||||
# functions on Solaris that doesn't have a non-functional libc stub.
|
# functions on Solaris that doesn't have a non-functional libc stub.
|
||||||
# We try pthread_create on general principles.
|
# We try pthread_create on general principles.
|
||||||
|
|
||||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <pthread.h>
|
AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <pthread.h>
|
||||||
# if $ax_pthread_check_cond
|
static void routine(void *a) { *((int*)a) = 0; }
|
||||||
# error "$ax_pthread_check_macro must be defined"
|
|
||||||
# endif
|
|
||||||
static void *some_global = NULL;
|
|
||||||
static void routine(void *a)
|
|
||||||
{
|
|
||||||
/* To avoid any unused-parameter or
|
|
||||||
unused-but-set-parameter warning. */
|
|
||||||
some_global = a;
|
|
||||||
}
|
|
||||||
static void *start_routine(void *a) { return a; }],
|
static void *start_routine(void *a) { return a; }],
|
||||||
[pthread_t th; pthread_attr_t attr;
|
[pthread_t th; pthread_attr_t attr;
|
||||||
pthread_create(&th, 0, start_routine, 0);
|
pthread_create(&th, 0, start_routine, 0);
|
||||||
@@ -346,187 +227,101 @@ for ax_pthread_try_flag in $ax_pthread_flags; do
|
|||||||
pthread_attr_init(&attr);
|
pthread_attr_init(&attr);
|
||||||
pthread_cleanup_push(routine, 0);
|
pthread_cleanup_push(routine, 0);
|
||||||
pthread_cleanup_pop(0) /* ; */])],
|
pthread_cleanup_pop(0) /* ; */])],
|
||||||
[ax_pthread_ok=yes],
|
[ax_pthread_ok=yes],
|
||||||
[])
|
[])
|
||||||
|
|
||||||
CFLAGS="$ax_pthread_save_CFLAGS"
|
LIBS="$save_LIBS"
|
||||||
LIBS="$ax_pthread_save_LIBS"
|
CFLAGS="$save_CFLAGS"
|
||||||
|
|
||||||
AC_MSG_RESULT([$ax_pthread_ok])
|
AC_MSG_RESULT([$ax_pthread_ok])
|
||||||
AS_IF([test "x$ax_pthread_ok" = "xyes"], [break])
|
if test "x$ax_pthread_ok" = xyes; then
|
||||||
|
break;
|
||||||
|
fi
|
||||||
|
|
||||||
PTHREAD_LIBS=""
|
PTHREAD_LIBS=""
|
||||||
PTHREAD_CFLAGS=""
|
PTHREAD_CFLAGS=""
|
||||||
done
|
done
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
# Clang needs special handling, because older versions handle the -pthread
|
|
||||||
# option in a rather... idiosyncratic way
|
|
||||||
|
|
||||||
if test "x$ax_pthread_clang" = "xyes"; then
|
|
||||||
|
|
||||||
# Clang takes -pthread; it has never supported any other flag
|
|
||||||
|
|
||||||
# (Note 1: This will need to be revisited if a system that Clang
|
|
||||||
# supports has POSIX threads in a separate library. This tends not
|
|
||||||
# to be the way of modern systems, but it's conceivable.)
|
|
||||||
|
|
||||||
# (Note 2: On some systems, notably Darwin, -pthread is not needed
|
|
||||||
# to get POSIX threads support; the API is always present and
|
|
||||||
# active. We could reasonably leave PTHREAD_CFLAGS empty. But
|
|
||||||
# -pthread does define _REENTRANT, and while the Darwin headers
|
|
||||||
# ignore this macro, third-party headers might not.)
|
|
||||||
|
|
||||||
# However, older versions of Clang make a point of warning the user
|
|
||||||
# that, in an invocation where only linking and no compilation is
|
|
||||||
# taking place, the -pthread option has no effect ("argument unused
|
|
||||||
# during compilation"). They expect -pthread to be passed in only
|
|
||||||
# when source code is being compiled.
|
|
||||||
#
|
|
||||||
# Problem is, this is at odds with the way Automake and most other
|
|
||||||
# C build frameworks function, which is that the same flags used in
|
|
||||||
# compilation (CFLAGS) are also used in linking. Many systems
|
|
||||||
# supported by AX_PTHREAD require exactly this for POSIX threads
|
|
||||||
# support, and in fact it is often not straightforward to specify a
|
|
||||||
# flag that is used only in the compilation phase and not in
|
|
||||||
# linking. Such a scenario is extremely rare in practice.
|
|
||||||
#
|
|
||||||
# Even though use of the -pthread flag in linking would only print
|
|
||||||
# a warning, this can be a nuisance for well-run software projects
|
|
||||||
# that build with -Werror. So if the active version of Clang has
|
|
||||||
# this misfeature, we search for an option to squash it.
|
|
||||||
|
|
||||||
AC_CACHE_CHECK([whether Clang needs flag to prevent "argument unused" warning when linking with -pthread],
|
|
||||||
[ax_cv_PTHREAD_CLANG_NO_WARN_FLAG],
|
|
||||||
[ax_cv_PTHREAD_CLANG_NO_WARN_FLAG=unknown
|
|
||||||
# Create an alternate version of $ac_link that compiles and
|
|
||||||
# links in two steps (.c -> .o, .o -> exe) instead of one
|
|
||||||
# (.c -> exe), because the warning occurs only in the second
|
|
||||||
# step
|
|
||||||
ax_pthread_save_ac_link="$ac_link"
|
|
||||||
ax_pthread_sed='s/conftest\.\$ac_ext/conftest.$ac_objext/g'
|
|
||||||
ax_pthread_link_step=`AS_ECHO(["$ac_link"]) | sed "$ax_pthread_sed"`
|
|
||||||
ax_pthread_2step_ac_link="($ac_compile) && (echo ==== >&5) && ($ax_pthread_link_step)"
|
|
||||||
ax_pthread_save_CFLAGS="$CFLAGS"
|
|
||||||
for ax_pthread_try in '' -Qunused-arguments -Wno-unused-command-line-argument unknown; do
|
|
||||||
AS_IF([test "x$ax_pthread_try" = "xunknown"], [break])
|
|
||||||
CFLAGS="-Werror -Wunknown-warning-option $ax_pthread_try -pthread $ax_pthread_save_CFLAGS"
|
|
||||||
ac_link="$ax_pthread_save_ac_link"
|
|
||||||
AC_LINK_IFELSE([AC_LANG_SOURCE([[int main(void){return 0;}]])],
|
|
||||||
[ac_link="$ax_pthread_2step_ac_link"
|
|
||||||
AC_LINK_IFELSE([AC_LANG_SOURCE([[int main(void){return 0;}]])],
|
|
||||||
[break])
|
|
||||||
])
|
|
||||||
done
|
|
||||||
ac_link="$ax_pthread_save_ac_link"
|
|
||||||
CFLAGS="$ax_pthread_save_CFLAGS"
|
|
||||||
AS_IF([test "x$ax_pthread_try" = "x"], [ax_pthread_try=no])
|
|
||||||
ax_cv_PTHREAD_CLANG_NO_WARN_FLAG="$ax_pthread_try"
|
|
||||||
])
|
|
||||||
|
|
||||||
case "$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG" in
|
|
||||||
no | unknown) ;;
|
|
||||||
*) PTHREAD_CFLAGS="$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG $PTHREAD_CFLAGS" ;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
fi # $ax_pthread_clang = yes
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Various other checks:
|
# Various other checks:
|
||||||
if test "x$ax_pthread_ok" = "xyes"; then
|
if test "x$ax_pthread_ok" = xyes; then
|
||||||
ax_pthread_save_CFLAGS="$CFLAGS"
|
save_LIBS="$LIBS"
|
||||||
ax_pthread_save_LIBS="$LIBS"
|
|
||||||
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
|
|
||||||
LIBS="$PTHREAD_LIBS $LIBS"
|
LIBS="$PTHREAD_LIBS $LIBS"
|
||||||
|
save_CFLAGS="$CFLAGS"
|
||||||
|
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
|
||||||
|
|
||||||
# Detect AIX lossage: JOINABLE attribute is called UNDETACHED.
|
# Detect AIX lossage: JOINABLE attribute is called UNDETACHED.
|
||||||
AC_CACHE_CHECK([for joinable pthread attribute],
|
AC_MSG_CHECKING([for joinable pthread attribute])
|
||||||
[ax_cv_PTHREAD_JOINABLE_ATTR],
|
attr_name=unknown
|
||||||
[ax_cv_PTHREAD_JOINABLE_ATTR=unknown
|
for attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do
|
||||||
for ax_pthread_attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do
|
AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <pthread.h>],
|
||||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <pthread.h>],
|
[int attr = $attr; return attr /* ; */])],
|
||||||
[int attr = $ax_pthread_attr; return attr /* ; */])],
|
[attr_name=$attr; break],
|
||||||
[ax_cv_PTHREAD_JOINABLE_ATTR=$ax_pthread_attr; break],
|
[])
|
||||||
[])
|
done
|
||||||
done
|
AC_MSG_RESULT([$attr_name])
|
||||||
])
|
if test "$attr_name" != PTHREAD_CREATE_JOINABLE; then
|
||||||
AS_IF([test "x$ax_cv_PTHREAD_JOINABLE_ATTR" != "xunknown" && \
|
AC_DEFINE_UNQUOTED([PTHREAD_CREATE_JOINABLE], [$attr_name],
|
||||||
test "x$ax_cv_PTHREAD_JOINABLE_ATTR" != "xPTHREAD_CREATE_JOINABLE" && \
|
[Define to necessary symbol if this constant
|
||||||
test "x$ax_pthread_joinable_attr_defined" != "xyes"],
|
uses a non-standard name on your system.])
|
||||||
[AC_DEFINE_UNQUOTED([PTHREAD_CREATE_JOINABLE],
|
fi
|
||||||
[$ax_cv_PTHREAD_JOINABLE_ATTR],
|
|
||||||
[Define to necessary symbol if this constant
|
|
||||||
uses a non-standard name on your system.])
|
|
||||||
ax_pthread_joinable_attr_defined=yes
|
|
||||||
])
|
|
||||||
|
|
||||||
AC_CACHE_CHECK([whether more special flags are required for pthreads],
|
AC_MSG_CHECKING([if more special flags are required for pthreads])
|
||||||
[ax_cv_PTHREAD_SPECIAL_FLAGS],
|
flag=no
|
||||||
[ax_cv_PTHREAD_SPECIAL_FLAGS=no
|
case ${host_os} in
|
||||||
case $host_os in
|
aix* | freebsd* | darwin*) flag="-D_THREAD_SAFE";;
|
||||||
solaris*)
|
osf* | hpux*) flag="-D_REENTRANT";;
|
||||||
ax_cv_PTHREAD_SPECIAL_FLAGS="-D_POSIX_PTHREAD_SEMANTICS"
|
solaris*)
|
||||||
;;
|
if test "$GCC" = "yes"; then
|
||||||
esac
|
flag="-D_REENTRANT"
|
||||||
])
|
else
|
||||||
AS_IF([test "x$ax_cv_PTHREAD_SPECIAL_FLAGS" != "xno" && \
|
# TODO: What about Clang on Solaris?
|
||||||
test "x$ax_pthread_special_flags_added" != "xyes"],
|
flag="-mt -D_REENTRANT"
|
||||||
[PTHREAD_CFLAGS="$ax_cv_PTHREAD_SPECIAL_FLAGS $PTHREAD_CFLAGS"
|
fi
|
||||||
ax_pthread_special_flags_added=yes])
|
;;
|
||||||
|
esac
|
||||||
|
AC_MSG_RESULT([$flag])
|
||||||
|
if test "x$flag" != xno; then
|
||||||
|
PTHREAD_CFLAGS="$flag $PTHREAD_CFLAGS"
|
||||||
|
fi
|
||||||
|
|
||||||
AC_CACHE_CHECK([for PTHREAD_PRIO_INHERIT],
|
AC_CACHE_CHECK([for PTHREAD_PRIO_INHERIT],
|
||||||
[ax_cv_PTHREAD_PRIO_INHERIT],
|
[ax_cv_PTHREAD_PRIO_INHERIT], [
|
||||||
[AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <pthread.h>]],
|
AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <pthread.h>]],
|
||||||
[[int i = PTHREAD_PRIO_INHERIT;
|
[[int i = PTHREAD_PRIO_INHERIT;]])],
|
||||||
return i;]])],
|
[ax_cv_PTHREAD_PRIO_INHERIT=yes],
|
||||||
[ax_cv_PTHREAD_PRIO_INHERIT=yes],
|
[ax_cv_PTHREAD_PRIO_INHERIT=no])
|
||||||
[ax_cv_PTHREAD_PRIO_INHERIT=no])
|
|
||||||
])
|
])
|
||||||
AS_IF([test "x$ax_cv_PTHREAD_PRIO_INHERIT" = "xyes" && \
|
AS_IF([test "x$ax_cv_PTHREAD_PRIO_INHERIT" = "xyes"],
|
||||||
test "x$ax_pthread_prio_inherit_defined" != "xyes"],
|
[AC_DEFINE([HAVE_PTHREAD_PRIO_INHERIT], [1], [Have PTHREAD_PRIO_INHERIT.])])
|
||||||
[AC_DEFINE([HAVE_PTHREAD_PRIO_INHERIT], [1], [Have PTHREAD_PRIO_INHERIT.])
|
|
||||||
ax_pthread_prio_inherit_defined=yes
|
|
||||||
])
|
|
||||||
|
|
||||||
CFLAGS="$ax_pthread_save_CFLAGS"
|
LIBS="$save_LIBS"
|
||||||
LIBS="$ax_pthread_save_LIBS"
|
CFLAGS="$save_CFLAGS"
|
||||||
|
|
||||||
# More AIX lossage: compile with *_r variant
|
# More AIX lossage: compile with *_r variant
|
||||||
if test "x$GCC" != "xyes"; then
|
if test "x$GCC" != xyes; then
|
||||||
case $host_os in
|
case $host_os in
|
||||||
aix*)
|
aix*)
|
||||||
AS_CASE(["x/$CC"],
|
AS_CASE(["x/$CC"],
|
||||||
[x*/c89|x*/c89_128|x*/c99|x*/c99_128|x*/cc|x*/cc128|x*/xlc|x*/xlc_v6|x*/xlc128|x*/xlc128_v6],
|
[x*/c89|x*/c89_128|x*/c99|x*/c99_128|x*/cc|x*/cc128|x*/xlc|x*/xlc_v6|x*/xlc128|x*/xlc128_v6],
|
||||||
[#handle absolute path differently from PATH based program lookup
|
[#handle absolute path differently from PATH based program lookup
|
||||||
AS_CASE(["x$CC"],
|
AS_CASE(["x$CC"],
|
||||||
[x/*],
|
[x/*],
|
||||||
[
|
[AS_IF([AS_EXECUTABLE_P([${CC}_r])],[PTHREAD_CC="${CC}_r"])],
|
||||||
AS_IF([AS_EXECUTABLE_P([${CC}_r])],[PTHREAD_CC="${CC}_r"])
|
[AC_CHECK_PROGS([PTHREAD_CC],[${CC}_r],[$CC])])])
|
||||||
AS_IF([test "x${CXX}" != "x"], [AS_IF([AS_EXECUTABLE_P([${CXX}_r])],[PTHREAD_CXX="${CXX}_r"])])
|
|
||||||
],
|
|
||||||
[
|
|
||||||
AC_CHECK_PROGS([PTHREAD_CC],[${CC}_r],[$CC])
|
|
||||||
AS_IF([test "x${CXX}" != "x"], [AC_CHECK_PROGS([PTHREAD_CXX],[${CXX}_r],[$CXX])])
|
|
||||||
]
|
|
||||||
)
|
|
||||||
])
|
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
test -n "$PTHREAD_CC" || PTHREAD_CC="$CC"
|
test -n "$PTHREAD_CC" || PTHREAD_CC="$CC"
|
||||||
test -n "$PTHREAD_CXX" || PTHREAD_CXX="$CXX"
|
|
||||||
|
|
||||||
AC_SUBST([PTHREAD_LIBS])
|
AC_SUBST([PTHREAD_LIBS])
|
||||||
AC_SUBST([PTHREAD_CFLAGS])
|
AC_SUBST([PTHREAD_CFLAGS])
|
||||||
AC_SUBST([PTHREAD_CC])
|
AC_SUBST([PTHREAD_CC])
|
||||||
AC_SUBST([PTHREAD_CXX])
|
|
||||||
|
|
||||||
# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND:
|
# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND:
|
||||||
if test "x$ax_pthread_ok" = "xyes"; then
|
if test x"$ax_pthread_ok" = xyes; then
|
||||||
ifelse([$1],,[AC_DEFINE([HAVE_PTHREAD],[1],[Define if you have POSIX threads libraries and header files.])],[$1])
|
ifelse([$1],,[AC_DEFINE([HAVE_PTHREAD],[1],[Define if you have POSIX threads libraries and header files.])],[$1])
|
||||||
:
|
:
|
||||||
else
|
else
|
||||||
|
|||||||
+69
-258
@@ -47,12 +47,9 @@
|
|||||||
#include "util/regional.h"
|
#include "util/regional.h"
|
||||||
#include "util/net_help.h"
|
#include "util/net_help.h"
|
||||||
#include "util/config_file.h"
|
#include "util/config_file.h"
|
||||||
#include "util/data/dname.h"
|
|
||||||
#include "util/data/msgreply.h"
|
#include "util/data/msgreply.h"
|
||||||
#include "util/data/msgencode.h"
|
#include "util/data/msgencode.h"
|
||||||
#include "services/cache/dns.h"
|
#include "services/cache/dns.h"
|
||||||
#include "services/mesh.h"
|
|
||||||
#include "services/modstack.h"
|
|
||||||
#include "validator/val_neg.h"
|
#include "validator/val_neg.h"
|
||||||
#include "validator/val_secalgo.h"
|
#include "validator/val_secalgo.h"
|
||||||
#include "iterator/iter_utils.h"
|
#include "iterator/iter_utils.h"
|
||||||
@@ -105,6 +102,7 @@ static int
|
|||||||
testframe_init(struct module_env* env, struct cachedb_env* cachedb_env)
|
testframe_init(struct module_env* env, struct cachedb_env* cachedb_env)
|
||||||
{
|
{
|
||||||
struct testframe_moddata* d;
|
struct testframe_moddata* d;
|
||||||
|
(void)env;
|
||||||
verbose(VERB_ALGO, "testframe_init");
|
verbose(VERB_ALGO, "testframe_init");
|
||||||
d = (struct testframe_moddata*)calloc(1,
|
d = (struct testframe_moddata*)calloc(1,
|
||||||
sizeof(struct testframe_moddata));
|
sizeof(struct testframe_moddata));
|
||||||
@@ -113,15 +111,6 @@ testframe_init(struct module_env* env, struct cachedb_env* cachedb_env)
|
|||||||
log_err("out of memory");
|
log_err("out of memory");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
/* Register an EDNS option (65534) to bypass the worker cache lookup
|
|
||||||
* for testing */
|
|
||||||
if(!edns_register_option(LDNS_EDNS_UNBOUND_CACHEDB_TESTFRAME_TEST,
|
|
||||||
1 /* bypass cache */,
|
|
||||||
0 /* no aggregation */, env)) {
|
|
||||||
log_err("testframe_init, could not register test opcode");
|
|
||||||
free(d);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
lock_basic_init(&d->lock);
|
lock_basic_init(&d->lock);
|
||||||
lock_protect(&d->lock, d, sizeof(*d));
|
lock_protect(&d->lock, d, sizeof(*d));
|
||||||
return 1;
|
return 1;
|
||||||
@@ -229,8 +218,6 @@ static int
|
|||||||
cachedb_apply_cfg(struct cachedb_env* cachedb_env, struct config_file* cfg)
|
cachedb_apply_cfg(struct cachedb_env* cachedb_env, struct config_file* cfg)
|
||||||
{
|
{
|
||||||
const char* backend_str = cfg->cachedb_backend;
|
const char* backend_str = cfg->cachedb_backend;
|
||||||
if(!backend_str || *backend_str==0)
|
|
||||||
return 1;
|
|
||||||
cachedb_env->backend = cachedb_find_backend(backend_str);
|
cachedb_env->backend = cachedb_find_backend(backend_str);
|
||||||
if(!cachedb_env->backend) {
|
if(!cachedb_env->backend) {
|
||||||
log_err("cachedb: cannot find backend name '%s'", backend_str);
|
log_err("cachedb: cannot find backend name '%s'", backend_str);
|
||||||
@@ -268,6 +255,15 @@ cachedb_init(struct module_env* env, int id)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
cachedb_env->enabled = 1;
|
cachedb_env->enabled = 1;
|
||||||
|
if(env->cfg->serve_expired_reply_ttl)
|
||||||
|
log_warn(
|
||||||
|
"cachedb: serve-expired-reply-ttl is set but not working for data "
|
||||||
|
"originating from the external cache; 0 TLL is used for those.");
|
||||||
|
if(env->cfg->serve_expired_client_timeout)
|
||||||
|
log_warn(
|
||||||
|
"cachedb: serve-expired-client-timeout is set but not working for "
|
||||||
|
"data originating from the external cache; expired data are used "
|
||||||
|
"in the reply without first trying to refresh the data.");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -278,9 +274,12 @@ cachedb_deinit(struct module_env* env, int id)
|
|||||||
if(!env || !env->modinfo[id])
|
if(!env || !env->modinfo[id])
|
||||||
return;
|
return;
|
||||||
cachedb_env = (struct cachedb_env*)env->modinfo[id];
|
cachedb_env = (struct cachedb_env*)env->modinfo[id];
|
||||||
|
/* free contents */
|
||||||
|
/* TODO */
|
||||||
if(cachedb_env->enabled) {
|
if(cachedb_env->enabled) {
|
||||||
(*cachedb_env->backend->deinit)(env, cachedb_env);
|
(*cachedb_env->backend->deinit)(env, cachedb_env);
|
||||||
}
|
}
|
||||||
|
|
||||||
free(cachedb_env);
|
free(cachedb_env);
|
||||||
env->modinfo[id] = NULL;
|
env->modinfo[id] = NULL;
|
||||||
}
|
}
|
||||||
@@ -323,31 +322,30 @@ error_response(struct module_qstate* qstate, int id, int rcode)
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Hash the query name, type, class and dbacess-secret into lookup buffer.
|
* Hash the query name, type, class and dbacess-secret into lookup buffer.
|
||||||
* @param qinfo: query info
|
* @param qstate: query state with query info
|
||||||
* @param env: with env->cfg with secret.
|
* and env->cfg with secret.
|
||||||
* @param buf: returned buffer with hash to lookup
|
* @param buf: returned buffer with hash to lookup
|
||||||
* @param len: length of the buffer.
|
* @param len: length of the buffer.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
calc_hash(struct query_info* qinfo, struct module_env* env, char* buf,
|
calc_hash(struct module_qstate* qstate, char* buf, size_t len)
|
||||||
size_t len)
|
|
||||||
{
|
{
|
||||||
uint8_t clear[1024];
|
uint8_t clear[1024];
|
||||||
size_t clen = 0;
|
size_t clen = 0;
|
||||||
uint8_t hash[CACHEDB_HASHSIZE/8];
|
uint8_t hash[CACHEDB_HASHSIZE/8];
|
||||||
const char* hex = "0123456789ABCDEF";
|
const char* hex = "0123456789ABCDEF";
|
||||||
const char* secret = env->cfg->cachedb_secret;
|
const char* secret = qstate->env->cfg->cachedb_secret;
|
||||||
size_t i;
|
size_t i;
|
||||||
|
|
||||||
/* copy the hash info into the clear buffer */
|
/* copy the hash info into the clear buffer */
|
||||||
if(clen + qinfo->qname_len < sizeof(clear)) {
|
if(clen + qstate->qinfo.qname_len < sizeof(clear)) {
|
||||||
memmove(clear+clen, qinfo->qname, qinfo->qname_len);
|
memmove(clear+clen, qstate->qinfo.qname,
|
||||||
query_dname_tolower(clear+clen);
|
qstate->qinfo.qname_len);
|
||||||
clen += qinfo->qname_len;
|
clen += qstate->qinfo.qname_len;
|
||||||
}
|
}
|
||||||
if(clen + 4 < sizeof(clear)) {
|
if(clen + 4 < sizeof(clear)) {
|
||||||
uint16_t t = htons(qinfo->qtype);
|
uint16_t t = htons(qstate->qinfo.qtype);
|
||||||
uint16_t c = htons(qinfo->qclass);
|
uint16_t c = htons(qstate->qinfo.qclass);
|
||||||
memmove(clear+clen, &t, 2);
|
memmove(clear+clen, &t, 2);
|
||||||
memmove(clear+clen+2, &c, 2);
|
memmove(clear+clen+2, &c, 2);
|
||||||
clen += 4;
|
clen += 4;
|
||||||
@@ -401,24 +399,13 @@ prep_data(struct module_qstate* qstate, struct sldns_buffer* buf)
|
|||||||
FLAGS_GET_RCODE(qstate->return_msg->rep->flags) !=
|
FLAGS_GET_RCODE(qstate->return_msg->rep->flags) !=
|
||||||
LDNS_RCODE_YXDOMAIN)
|
LDNS_RCODE_YXDOMAIN)
|
||||||
return 0;
|
return 0;
|
||||||
/* Do not persist data the validator has not yet seen, or has rejected.
|
/* We don't store the reply if its TTL is 0 unless serve-expired is
|
||||||
* Otherwise an expired blob could maybe reach clients via
|
* enabled. Such a reply won't be reusable and simply be a waste for
|
||||||
* serve-expired. */
|
* the backend. It's also compatible with the default behavior of
|
||||||
if(qstate->env->need_to_validate &&
|
* dns_cache_store_msg(). */
|
||||||
qstate->return_msg->rep->security == sec_status_bogus)
|
if(qstate->return_msg->rep->ttl == 0 &&
|
||||||
|
!qstate->env->cfg->serve_expired)
|
||||||
return 0;
|
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)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
/* The EDE is added to the out-list so it is encoded in the cached message */
|
|
||||||
if (qstate->env->cfg->ede && qstate->return_msg->rep->reason_bogus != LDNS_EDE_NONE) {
|
|
||||||
edns_opt_list_append_ede(&edns.opt_list_out, qstate->env->scratch,
|
|
||||||
qstate->return_msg->rep->reason_bogus,
|
|
||||||
qstate->return_msg->rep->reason_bogus_str);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(verbosity >= VERB_ALGO)
|
if(verbosity >= VERB_ALGO)
|
||||||
log_dns_msg("cachedb encoding", &qstate->return_msg->qinfo,
|
log_dns_msg("cachedb encoding", &qstate->return_msg->qinfo,
|
||||||
qstate->return_msg->rep);
|
qstate->return_msg->rep);
|
||||||
@@ -463,7 +450,7 @@ good_expiry_and_qinfo(struct module_qstate* qstate, struct sldns_buffer* buf)
|
|||||||
* - serve_expired needs to be set
|
* - serve_expired needs to be set
|
||||||
* - if SERVE_EXPIRED_TTL is set make sure that the record is not older
|
* - if SERVE_EXPIRED_TTL is set make sure that the record is not older
|
||||||
* than that. */
|
* than that. */
|
||||||
if(TTL_IS_EXPIRED((time_t)expiry, *qstate->env->now) &&
|
if((time_t)expiry < *qstate->env->now &&
|
||||||
(!qstate->env->cfg->serve_expired ||
|
(!qstate->env->cfg->serve_expired ||
|
||||||
(SERVE_EXPIRED_TTL &&
|
(SERVE_EXPIRED_TTL &&
|
||||||
*qstate->env->now - (time_t)expiry > SERVE_EXPIRED_TTL)))
|
*qstate->env->now - (time_t)expiry > SERVE_EXPIRED_TTL)))
|
||||||
@@ -475,8 +462,7 @@ good_expiry_and_qinfo(struct module_qstate* qstate, struct sldns_buffer* buf)
|
|||||||
/* Adjust the TTL of the given RRset by 'subtract'. If 'subtract' is
|
/* Adjust the TTL of the given RRset by 'subtract'. If 'subtract' is
|
||||||
* negative, set the TTL to 0. */
|
* negative, set the TTL to 0. */
|
||||||
static void
|
static void
|
||||||
packed_rrset_ttl_subtract(struct packed_rrset_data* data, time_t subtract,
|
packed_rrset_ttl_subtract(struct packed_rrset_data* data, time_t subtract)
|
||||||
time_t timestamp)
|
|
||||||
{
|
{
|
||||||
size_t i;
|
size_t i;
|
||||||
size_t total = data->count + data->rrsig_count;
|
size_t total = data->count + data->rrsig_count;
|
||||||
@@ -488,13 +474,13 @@ packed_rrset_ttl_subtract(struct packed_rrset_data* data, time_t subtract,
|
|||||||
data->rr_ttl[i] -= subtract;
|
data->rr_ttl[i] -= subtract;
|
||||||
else data->rr_ttl[i] = 0;
|
else data->rr_ttl[i] = 0;
|
||||||
}
|
}
|
||||||
data->ttl_add = timestamp;
|
data->ttl_add = (subtract < data->ttl_add) ? (data->ttl_add - subtract) : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Adjust the TTL of a DNS message and its RRs by 'adjust'. If 'adjust' is
|
/* Adjust the TTL of a DNS message and its RRs by 'adjust'. If 'adjust' is
|
||||||
* negative, set the TTLs to 0. */
|
* negative, set the TTLs to 0. */
|
||||||
static void
|
static void
|
||||||
adjust_msg_ttl(struct dns_msg* msg, time_t adjust, time_t timestamp)
|
adjust_msg_ttl(struct dns_msg* msg, time_t adjust)
|
||||||
{
|
{
|
||||||
size_t i;
|
size_t i;
|
||||||
if(adjust >= 0 && msg->rep->ttl > adjust)
|
if(adjust >= 0 && msg->rep->ttl > adjust)
|
||||||
@@ -506,46 +492,16 @@ adjust_msg_ttl(struct dns_msg* msg, time_t adjust, time_t timestamp)
|
|||||||
|
|
||||||
for(i=0; i<msg->rep->rrset_count; i++) {
|
for(i=0; i<msg->rep->rrset_count; i++) {
|
||||||
packed_rrset_ttl_subtract((struct packed_rrset_data*)msg->
|
packed_rrset_ttl_subtract((struct packed_rrset_data*)msg->
|
||||||
rep->rrsets[i]->entry.data, adjust, timestamp);
|
rep->rrsets[i]->entry.data, adjust);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Set the TTL of the given RRset to fixed value. */
|
|
||||||
static void
|
|
||||||
packed_rrset_ttl_set(struct packed_rrset_data* data, time_t ttl, time_t timestamp)
|
|
||||||
{
|
|
||||||
size_t i;
|
|
||||||
size_t total = data->count + data->rrsig_count;
|
|
||||||
data->ttl = ttl;
|
|
||||||
for(i=0; i<total; i++) {
|
|
||||||
data->rr_ttl[i] = ttl;
|
|
||||||
}
|
|
||||||
data->ttl_add = timestamp;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Set the TTL of a DNS message and its RRs by to a fixed value. */
|
|
||||||
static void
|
|
||||||
set_msg_ttl(struct dns_msg* msg, time_t ttl, time_t timestamp)
|
|
||||||
{
|
|
||||||
size_t i;
|
|
||||||
msg->rep->ttl = ttl;
|
|
||||||
msg->rep->prefetch_ttl = PREFETCH_TTL_CALC(msg->rep->ttl);
|
|
||||||
msg->rep->serve_expired_ttl = msg->rep->ttl + SERVE_EXPIRED_TTL;
|
|
||||||
|
|
||||||
for(i=0; i<msg->rep->rrset_count; i++) {
|
|
||||||
packed_rrset_ttl_set((struct packed_rrset_data*)msg->
|
|
||||||
rep->rrsets[i]->entry.data, ttl, timestamp);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** convert dns message in buffer to return_msg */
|
/** convert dns message in buffer to return_msg */
|
||||||
static int
|
static int
|
||||||
parse_data(struct module_qstate* qstate, struct sldns_buffer* buf,
|
parse_data(struct module_qstate* qstate, struct sldns_buffer* buf)
|
||||||
int* msg_expired, time_t* msg_timestamp, time_t* msg_expiry)
|
|
||||||
{
|
{
|
||||||
struct msg_parse* prs;
|
struct msg_parse* prs;
|
||||||
struct edns_data edns;
|
struct edns_data edns;
|
||||||
struct edns_option* ede;
|
|
||||||
uint64_t timestamp, expiry;
|
uint64_t timestamp, expiry;
|
||||||
time_t adjust;
|
time_t adjust;
|
||||||
size_t lim = sldns_buffer_limit(buf);
|
size_t lim = sldns_buffer_limit(buf);
|
||||||
@@ -558,9 +514,6 @@ parse_data(struct module_qstate* qstate, struct sldns_buffer* buf,
|
|||||||
×tamp, sizeof(timestamp));
|
×tamp, sizeof(timestamp));
|
||||||
expiry = be64toh(expiry);
|
expiry = be64toh(expiry);
|
||||||
timestamp = be64toh(timestamp);
|
timestamp = be64toh(timestamp);
|
||||||
log_assert(timestamp <= expiry);
|
|
||||||
*msg_expiry = (time_t)expiry;
|
|
||||||
*msg_timestamp = (time_t)timestamp;
|
|
||||||
|
|
||||||
/* parse DNS packet */
|
/* parse DNS packet */
|
||||||
regional_free_all(qstate->env->scratch);
|
regional_free_all(qstate->env->scratch);
|
||||||
@@ -586,24 +539,6 @@ parse_data(struct module_qstate* qstate, struct sldns_buffer* buf,
|
|||||||
if(!qstate->return_msg)
|
if(!qstate->return_msg)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* We find the EDE in the in-list after parsing */
|
|
||||||
if(qstate->env->cfg->ede &&
|
|
||||||
(ede = edns_opt_list_find(edns.opt_list_in, LDNS_EDNS_EDE))) {
|
|
||||||
if(ede->opt_len >= 2) {
|
|
||||||
qstate->return_msg->rep->reason_bogus =
|
|
||||||
sldns_read_uint16(ede->opt_data);
|
|
||||||
}
|
|
||||||
/* allocate space and store the error string and it's size */
|
|
||||||
if(ede->opt_len > 2) {
|
|
||||||
size_t ede_len = ede->opt_len - 2;
|
|
||||||
qstate->return_msg->rep->reason_bogus_str = regional_alloc(
|
|
||||||
qstate->region, sizeof(char) * (ede_len+1));
|
|
||||||
memcpy(qstate->return_msg->rep->reason_bogus_str,
|
|
||||||
ede->opt_data+2, ede_len);
|
|
||||||
qstate->return_msg->rep->reason_bogus_str[ede_len] = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
qstate->return_rcode = LDNS_RCODE_NOERROR;
|
qstate->return_rcode = LDNS_RCODE_NOERROR;
|
||||||
|
|
||||||
/* see how much of the TTL expired, and remove it */
|
/* see how much of the TTL expired, and remove it */
|
||||||
@@ -612,32 +547,25 @@ parse_data(struct module_qstate* qstate, struct sldns_buffer* buf,
|
|||||||
return 1; /* message from the future (clock skew?) */
|
return 1; /* message from the future (clock skew?) */
|
||||||
}
|
}
|
||||||
adjust = *qstate->env->now - (time_t)timestamp;
|
adjust = *qstate->env->now - (time_t)timestamp;
|
||||||
if(TTL_IS_EXPIRED((time_t)expiry, *qstate->env->now)) {
|
if(qstate->return_msg->rep->ttl < adjust) {
|
||||||
verbose(VERB_ALGO, "cachedb msg expired");
|
verbose(VERB_ALGO, "cachedb msg expired");
|
||||||
*msg_expired = 1;
|
/* If serve-expired is enabled, we still use an expired message
|
||||||
if(!qstate->env->cfg->serve_expired ||
|
* setting the TTL to 0. */
|
||||||
(FLAGS_GET_RCODE(qstate->return_msg->rep->flags)
|
if(qstate->env->cfg->serve_expired)
|
||||||
!= LDNS_RCODE_NOERROR &&
|
adjust = -1;
|
||||||
FLAGS_GET_RCODE(qstate->return_msg->rep->flags)
|
else
|
||||||
!= LDNS_RCODE_NXDOMAIN &&
|
|
||||||
FLAGS_GET_RCODE(qstate->return_msg->rep->flags)
|
|
||||||
!= LDNS_RCODE_YXDOMAIN))
|
|
||||||
return 0; /* message expired */
|
return 0; /* message expired */
|
||||||
/* If serve-expired is enabled, we still use an expired message.
|
|
||||||
* Set the TTL to 0 now and it will be handled specially later
|
|
||||||
* when we need to store it internally. */
|
|
||||||
adjust = -1;
|
|
||||||
}
|
}
|
||||||
adjust_msg_ttl(qstate->return_msg, adjust, timestamp);
|
|
||||||
verbose(VERB_ALGO, "cachedb msg adjusted down by %d", (int)adjust);
|
verbose(VERB_ALGO, "cachedb msg adjusted down by %d", (int)adjust);
|
||||||
if(qstate->env->cfg->aggressive_nsec) {
|
adjust_msg_ttl(qstate->return_msg, adjust);
|
||||||
limit_nsec_ttl(qstate->return_msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Similar to the unbound worker, if serve-expired is enabled and
|
/* Similar to the unbound worker, if serve-expired is enabled and
|
||||||
* the msg would be considered to be expired, mark the state so a
|
* the msg would be considered to be expired, mark the state so a
|
||||||
* refetch will be scheduled. */
|
* refetch will be scheduled. The comparison between 'expiry' and
|
||||||
if(*msg_expired && !qstate->env->cfg->serve_expired_client_timeout) {
|
* 'now' should be redundant given how these values were calculated,
|
||||||
|
* but we check it just in case as does good_expiry_and_qinfo(). */
|
||||||
|
if(qstate->env->cfg->serve_expired &&
|
||||||
|
(adjust == -1 || (time_t)expiry < *qstate->env->now)) {
|
||||||
qstate->need_refetch = 1;
|
qstate->need_refetch = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -649,11 +577,10 @@ parse_data(struct module_qstate* qstate, struct sldns_buffer* buf,
|
|||||||
* return true if lookup was successful.
|
* return true if lookup was successful.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
cachedb_extcache_lookup(struct module_qstate* qstate, struct cachedb_env* ie,
|
cachedb_extcache_lookup(struct module_qstate* qstate, struct cachedb_env* ie)
|
||||||
int* msg_expired, time_t* msg_timestamp, time_t* msg_expiry)
|
|
||||||
{
|
{
|
||||||
char key[(CACHEDB_HASHSIZE/8)*2+1];
|
char key[(CACHEDB_HASHSIZE/8)*2+1];
|
||||||
calc_hash(&qstate->qinfo, qstate->env, key, sizeof(key));
|
calc_hash(qstate, key, sizeof(key));
|
||||||
|
|
||||||
/* call backend to fetch data for key into scratch buffer */
|
/* call backend to fetch data for key into scratch buffer */
|
||||||
if( !(*ie->backend->lookup)(qstate->env, ie, key,
|
if( !(*ie->backend->lookup)(qstate->env, ie, key,
|
||||||
@@ -667,8 +594,7 @@ cachedb_extcache_lookup(struct module_qstate* qstate, struct cachedb_env* ie,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* parse dns message into return_msg */
|
/* parse dns message into return_msg */
|
||||||
if( !parse_data(qstate, qstate->env->scratch_buffer, msg_expired,
|
if( !parse_data(qstate, qstate->env->scratch_buffer) ) {
|
||||||
msg_timestamp, msg_expiry) ) {
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
@@ -681,7 +607,7 @@ static void
|
|||||||
cachedb_extcache_store(struct module_qstate* qstate, struct cachedb_env* ie)
|
cachedb_extcache_store(struct module_qstate* qstate, struct cachedb_env* ie)
|
||||||
{
|
{
|
||||||
char key[(CACHEDB_HASHSIZE/8)*2+1];
|
char key[(CACHEDB_HASHSIZE/8)*2+1];
|
||||||
calc_hash(&qstate->qinfo, qstate->env, key, sizeof(key));
|
calc_hash(qstate, key, sizeof(key));
|
||||||
|
|
||||||
/* prepare data in scratch buffer */
|
/* prepare data in scratch buffer */
|
||||||
if(!prep_data(qstate, qstate->env->scratch_buffer))
|
if(!prep_data(qstate, qstate->env->scratch_buffer))
|
||||||
@@ -698,18 +624,13 @@ cachedb_extcache_store(struct module_qstate* qstate, struct cachedb_env* ie)
|
|||||||
* See if unbound's internal cache can answer the query
|
* See if unbound's internal cache can answer the query
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
cachedb_intcache_lookup(struct module_qstate* qstate, struct cachedb_env* cde)
|
cachedb_intcache_lookup(struct module_qstate* qstate)
|
||||||
{
|
{
|
||||||
uint8_t dpname_storage[LDNS_MAX_DOMAINLEN+1];
|
|
||||||
uint8_t* dpname=NULL;
|
uint8_t* dpname=NULL;
|
||||||
size_t dpnamelen=0;
|
size_t dpnamelen=0;
|
||||||
struct dns_msg* msg;
|
struct dns_msg* msg;
|
||||||
/* for testframe bypass this lookup */
|
|
||||||
if(cde->backend == &testframe_backend) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if(iter_stub_fwd_no_cache(qstate, &qstate->qinfo,
|
if(iter_stub_fwd_no_cache(qstate, &qstate->qinfo,
|
||||||
&dpname, &dpnamelen, dpname_storage, sizeof(dpname_storage)))
|
&dpname, &dpnamelen))
|
||||||
return 0; /* no cache for these queries */
|
return 0; /* no cache for these queries */
|
||||||
msg = dns_cache_lookup(qstate->env, qstate->qinfo.qname,
|
msg = dns_cache_lookup(qstate->env, qstate->qinfo.qname,
|
||||||
qstate->qinfo.qname_len, qstate->qinfo.qtype,
|
qstate->qinfo.qname_len, qstate->qinfo.qtype,
|
||||||
@@ -740,52 +661,17 @@ cachedb_intcache_lookup(struct module_qstate* qstate, struct cachedb_env* cde)
|
|||||||
* Store query into the internal cache of unbound.
|
* Store query into the internal cache of unbound.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
cachedb_intcache_store(struct module_qstate* qstate, int msg_expired,
|
cachedb_intcache_store(struct module_qstate* qstate)
|
||||||
time_t msg_timestamp, time_t msg_expiry)
|
|
||||||
{
|
{
|
||||||
uint32_t store_flags = qstate->query_flags;
|
uint32_t store_flags = qstate->query_flags;
|
||||||
int serve_expired = qstate->env->cfg->serve_expired;
|
|
||||||
|
if(qstate->env->cfg->serve_expired)
|
||||||
|
store_flags |= DNSCACHE_STORE_ZEROTTL;
|
||||||
if(!qstate->return_msg)
|
if(!qstate->return_msg)
|
||||||
return;
|
return;
|
||||||
if(serve_expired && msg_expired) {
|
|
||||||
time_t original_ttl = msg_expiry - msg_timestamp;
|
|
||||||
store_flags |= DNSCACHE_STORE_EXPIRED_MSG_CACHEDB;
|
|
||||||
/* Pass the original TTL of the expired message and signal with
|
|
||||||
* the DNSCACHE_STORE_EXPIRED_MSG_CACHEDB flag that
|
|
||||||
* dns_cache_store_msg() needs to set absolute expired TTLs
|
|
||||||
* based on the original message TTL.
|
|
||||||
* Results as expired message in the cache */
|
|
||||||
set_msg_ttl(qstate->return_msg, original_ttl, 0);
|
|
||||||
verbose(VERB_ALGO, "cachedb expired msg set to be expired now "
|
|
||||||
"(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;
|
|
||||||
}
|
|
||||||
(void)dns_cache_store(qstate->env, &qstate->qinfo,
|
(void)dns_cache_store(qstate->env, &qstate->qinfo,
|
||||||
qstate->return_msg->rep, 0, qstate->prefetch_leeway, 0,
|
qstate->return_msg->rep, 0, qstate->prefetch_leeway, 0,
|
||||||
qstate->region, store_flags, qstate->qstarttime,
|
qstate->region, store_flags, qstate->qstarttime);
|
||||||
qstate->is_valrec);
|
|
||||||
if(serve_expired && msg_expired) {
|
|
||||||
if(qstate->env->cfg->serve_expired_client_timeout) {
|
|
||||||
/* No expired response from the query state, the
|
|
||||||
* query resolution needs to continue and it can
|
|
||||||
* pick up the expired result after the timer out
|
|
||||||
* of cache. */
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
/* Send serve expired responses based on the cachedb
|
|
||||||
* returned message, that was just stored in the cache.
|
|
||||||
* It can then continue to work on this query. */
|
|
||||||
mesh_respond_serve_expired(qstate->mesh_info);
|
|
||||||
/* set TTLs as expired for this return_msg in case it is used
|
|
||||||
* later on */
|
|
||||||
set_msg_ttl(qstate->return_msg,
|
|
||||||
EXPIRED_REPLY_TTL_CALC(msg_expiry, msg_timestamp), 0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -801,9 +687,6 @@ cachedb_handle_query(struct module_qstate* qstate,
|
|||||||
struct cachedb_qstate* ATTR_UNUSED(iq),
|
struct cachedb_qstate* ATTR_UNUSED(iq),
|
||||||
struct cachedb_env* ie, int id)
|
struct cachedb_env* ie, int id)
|
||||||
{
|
{
|
||||||
int msg_expired = 0;
|
|
||||||
time_t msg_timestamp, msg_expiry;
|
|
||||||
qstate->is_cachedb_answer = 0;
|
|
||||||
/* check if we are enabled, and skip if so */
|
/* check if we are enabled, and skip if so */
|
||||||
if(!ie->enabled) {
|
if(!ie->enabled) {
|
||||||
/* pass request to next module */
|
/* pass request to next module */
|
||||||
@@ -811,11 +694,8 @@ cachedb_handle_query(struct module_qstate* qstate,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(qstate->blacklist || qstate->no_cache_lookup
|
if(qstate->blacklist || qstate->no_cache_lookup) {
|
||||||
|| iter_stub_fwd_no_cache(qstate, &qstate->qinfo, NULL, NULL,
|
/* cache is blacklisted or we are instructed from edns to not look */
|
||||||
NULL, 0)) {
|
|
||||||
/* cache is blacklisted or we are instructed from edns to not
|
|
||||||
* look or a forwarder/stub forbids it */
|
|
||||||
/* pass request to next module */
|
/* pass request to next module */
|
||||||
qstate->ext_state[id] = module_wait_module;
|
qstate->ext_state[id] = module_wait_module;
|
||||||
return;
|
return;
|
||||||
@@ -823,7 +703,7 @@ cachedb_handle_query(struct module_qstate* qstate,
|
|||||||
|
|
||||||
/* lookup inside unbound's internal cache.
|
/* lookup inside unbound's internal cache.
|
||||||
* This does not look for expired entries. */
|
* This does not look for expired entries. */
|
||||||
if(cachedb_intcache_lookup(qstate, ie)) {
|
if(cachedb_intcache_lookup(qstate)) {
|
||||||
if(verbosity >= VERB_ALGO) {
|
if(verbosity >= VERB_ALGO) {
|
||||||
if(qstate->return_msg->rep)
|
if(qstate->return_msg->rep)
|
||||||
log_dns_msg("cachedb internal cache lookup",
|
log_dns_msg("cachedb internal cache lookup",
|
||||||
@@ -840,55 +720,31 @@ cachedb_handle_query(struct module_qstate* qstate,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* ask backend cache to see if we have data */
|
/* ask backend cache to see if we have data */
|
||||||
if(cachedb_extcache_lookup(qstate, ie, &msg_expired, &msg_timestamp,
|
if(cachedb_extcache_lookup(qstate, ie)) {
|
||||||
&msg_expiry)) {
|
|
||||||
if(verbosity >= VERB_ALGO)
|
if(verbosity >= VERB_ALGO)
|
||||||
log_dns_msg(ie->backend->name,
|
log_dns_msg(ie->backend->name,
|
||||||
&qstate->return_msg->qinfo,
|
&qstate->return_msg->qinfo,
|
||||||
qstate->return_msg->rep);
|
qstate->return_msg->rep);
|
||||||
/* store this result in internal cache */
|
/* store this result in internal cache */
|
||||||
cachedb_intcache_store(qstate,
|
cachedb_intcache_store(qstate);
|
||||||
msg_expired, msg_timestamp, msg_expiry);
|
|
||||||
/* In case we have expired data but there is a client timer for expired
|
/* In case we have expired data but there is a client timer for expired
|
||||||
* answers, pass execution to next module in order to try updating the
|
* answers, pass execution to next module in order to try updating the
|
||||||
* data first.
|
* data first.
|
||||||
*/
|
* TODO: this needs revisit. The expired data stored from cachedb has
|
||||||
if(qstate->env->cfg->serve_expired && msg_expired) {
|
* 0 TTL which is picked up by iterator later when looking in the cache.
|
||||||
qstate->return_msg = NULL;
|
* Document that ext cachedb does not work properly with
|
||||||
qstate->ext_state[id] = module_wait_module;
|
* serve_stale_reply_ttl yet. */
|
||||||
/* The expired reply is sent with
|
|
||||||
* mesh_respond_serve_expired, and so
|
|
||||||
* the need_refetch is not used. */
|
|
||||||
qstate->need_refetch = 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if(qstate->need_refetch && qstate->serve_expired_data &&
|
if(qstate->need_refetch && qstate->serve_expired_data &&
|
||||||
qstate->serve_expired_data->timer) {
|
qstate->serve_expired_data->timer) {
|
||||||
qstate->return_msg = NULL;
|
qstate->return_msg = NULL;
|
||||||
qstate->ext_state[id] = module_wait_module;
|
qstate->ext_state[id] = module_wait_module;
|
||||||
return;
|
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 */
|
/* we are done with the query */
|
||||||
qstate->ext_state[id] = module_finished;
|
qstate->ext_state[id] = module_finished;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(qstate->serve_expired_data &&
|
|
||||||
qstate->env->cfg->cachedb_check_when_serve_expired &&
|
|
||||||
!qstate->env->cfg->serve_expired_client_timeout) {
|
|
||||||
/* Reply with expired data if any to client, because cachedb
|
|
||||||
* also has no useful, current data */
|
|
||||||
mesh_respond_serve_expired(qstate->mesh_info);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* no cache fetches */
|
/* no cache fetches */
|
||||||
/* pass request to next module */
|
/* pass request to next module */
|
||||||
qstate->ext_state[id] = module_wait_module;
|
qstate->ext_state[id] = module_wait_module;
|
||||||
@@ -906,20 +762,12 @@ static void
|
|||||||
cachedb_handle_response(struct module_qstate* qstate,
|
cachedb_handle_response(struct module_qstate* qstate,
|
||||||
struct cachedb_qstate* ATTR_UNUSED(iq), struct cachedb_env* ie, int id)
|
struct cachedb_qstate* ATTR_UNUSED(iq), struct cachedb_env* ie, int id)
|
||||||
{
|
{
|
||||||
qstate->is_cachedb_answer = 0;
|
|
||||||
/* check if we are not enabled or instructed to not cache, and skip */
|
/* check if we are not enabled or instructed to not cache, and skip */
|
||||||
if(!ie->enabled || qstate->no_cache_store
|
if(!ie->enabled || qstate->no_cache_store) {
|
||||||
|| iter_stub_fwd_no_cache(qstate, &qstate->qinfo, NULL, NULL,
|
|
||||||
NULL, 0)) {
|
|
||||||
/* we are done with the query */
|
/* we are done with the query */
|
||||||
qstate->ext_state[id] = module_finished;
|
qstate->ext_state[id] = module_finished;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(qstate->env->cfg->cachedb_no_store) {
|
|
||||||
/* do not store the item in the external cache */
|
|
||||||
qstate->ext_state[id] = module_finished;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* store the item into the backend cache */
|
/* store the item into the backend cache */
|
||||||
cachedb_extcache_store(qstate, ie);
|
cachedb_extcache_store(qstate, ie);
|
||||||
@@ -1014,7 +862,7 @@ cachedb_get_mem(struct module_env* env, int id)
|
|||||||
*/
|
*/
|
||||||
static struct module_func_block cachedb_block = {
|
static struct module_func_block cachedb_block = {
|
||||||
"cachedb",
|
"cachedb",
|
||||||
NULL, NULL, &cachedb_init, &cachedb_deinit, &cachedb_operate,
|
&cachedb_init, &cachedb_deinit, &cachedb_operate,
|
||||||
&cachedb_inform_super, &cachedb_clear, &cachedb_get_mem
|
&cachedb_inform_super, &cachedb_clear, &cachedb_get_mem
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1023,41 +871,4 @@ cachedb_get_funcblock(void)
|
|||||||
{
|
{
|
||||||
return &cachedb_block;
|
return &cachedb_block;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
|
||||||
cachedb_is_enabled(struct module_stack* mods, struct module_env* env)
|
|
||||||
{
|
|
||||||
struct cachedb_env* ie;
|
|
||||||
int id = modstack_find(mods, "cachedb");
|
|
||||||
if(id == -1)
|
|
||||||
return 0;
|
|
||||||
ie = (struct cachedb_env*)env->modinfo[id];
|
|
||||||
if(ie && ie->enabled)
|
|
||||||
return 1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void cachedb_msg_remove(struct module_qstate* qstate)
|
|
||||||
{
|
|
||||||
cachedb_msg_remove_qinfo(qstate->env, &qstate->qinfo);
|
|
||||||
}
|
|
||||||
|
|
||||||
void cachedb_msg_remove_qinfo(struct module_env* env, struct query_info* qinfo)
|
|
||||||
{
|
|
||||||
char key[(CACHEDB_HASHSIZE/8)*2+1];
|
|
||||||
int id = modstack_find(env->modstack, "cachedb");
|
|
||||||
struct cachedb_env* ie = (struct cachedb_env*)env->modinfo[id];
|
|
||||||
|
|
||||||
log_query_info(VERB_ALGO, "cachedb msg remove", qinfo);
|
|
||||||
calc_hash(qinfo, env, key, sizeof(key));
|
|
||||||
sldns_buffer_clear(env->scratch_buffer);
|
|
||||||
sldns_buffer_write_u32(env->scratch_buffer, 0);
|
|
||||||
sldns_buffer_flip(env->scratch_buffer);
|
|
||||||
|
|
||||||
/* call backend */
|
|
||||||
(*ie->backend->store)(env, ie, key,
|
|
||||||
sldns_buffer_begin(env->scratch_buffer),
|
|
||||||
sldns_buffer_limit(env->scratch_buffer),
|
|
||||||
0);
|
|
||||||
}
|
|
||||||
#endif /* USE_CACHEDB */
|
#endif /* USE_CACHEDB */
|
||||||
|
|||||||
@@ -41,7 +41,6 @@
|
|||||||
*/
|
*/
|
||||||
#include "util/module.h"
|
#include "util/module.h"
|
||||||
struct cachedb_backend;
|
struct cachedb_backend;
|
||||||
struct module_stack;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The global variable environment contents for the cachedb
|
* The global variable environment contents for the cachedb
|
||||||
@@ -111,26 +110,3 @@ size_t cachedb_get_mem(struct module_env* env, int id);
|
|||||||
*/
|
*/
|
||||||
struct module_func_block* cachedb_get_funcblock(void);
|
struct module_func_block* cachedb_get_funcblock(void);
|
||||||
|
|
||||||
/**
|
|
||||||
* See if the cachedb is enabled.
|
|
||||||
* @param mods: module stack. It finds the cachedb module environment.
|
|
||||||
* @param env: module environment.
|
|
||||||
* @return true if exists and enabled.
|
|
||||||
*/
|
|
||||||
int cachedb_is_enabled(struct module_stack* mods, struct module_env* env);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove a message from the global cache. Because edns subnet has a more
|
|
||||||
* specific entry, and if not removed when everything expires, the global
|
|
||||||
* entry is used, instead of a fresh lookup of the edns subnet entry.
|
|
||||||
* @param qstate: query state.
|
|
||||||
*/
|
|
||||||
void cachedb_msg_remove(struct module_qstate* qstate);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove message from the cachedb cache, by query info.
|
|
||||||
* @param env: module environment to look up cachedb state.
|
|
||||||
* @param qinfo: the message to remove.
|
|
||||||
*/
|
|
||||||
void cachedb_msg_remove_qinfo(struct module_env* env,
|
|
||||||
struct query_info* qinfo);
|
|
||||||
|
|||||||
+68
-375
@@ -46,341 +46,89 @@
|
|||||||
#include "cachedb/cachedb.h"
|
#include "cachedb/cachedb.h"
|
||||||
#include "util/alloc.h"
|
#include "util/alloc.h"
|
||||||
#include "util/config_file.h"
|
#include "util/config_file.h"
|
||||||
#include "util/locks.h"
|
|
||||||
#include "util/timeval_func.h"
|
|
||||||
#include "sldns/sbuffer.h"
|
#include "sldns/sbuffer.h"
|
||||||
|
|
||||||
#ifdef USE_REDIS
|
#ifdef USE_REDIS
|
||||||
#include "hiredis/hiredis.h"
|
#include "hiredis/hiredis.h"
|
||||||
|
|
||||||
struct redis_moddata {
|
struct redis_moddata {
|
||||||
/* thread-specific redis contexts */
|
redisContext** ctxs; /* thread-specific redis contexts */
|
||||||
redisContext** ctxs;
|
int numctxs; /* number of ctx entries */
|
||||||
redisContext** replica_ctxs;
|
const char* server_host; /* server's IP address or host name */
|
||||||
/* number of ctx entries */
|
int server_port; /* server's TCP port */
|
||||||
int numctxs;
|
struct timeval timeout; /* timeout for connection setup and commands */
|
||||||
/* server's IP address or host name */
|
|
||||||
const char* server_host;
|
|
||||||
const char* replica_server_host;
|
|
||||||
/* server's TCP port */
|
|
||||||
int server_port;
|
|
||||||
int replica_server_port;
|
|
||||||
/* server's unix path, or "", NULL if unused */
|
|
||||||
const char* server_path;
|
|
||||||
const char* replica_server_path;
|
|
||||||
/* server's AUTH password, or "", NULL if unused */
|
|
||||||
const char* server_password;
|
|
||||||
const char* replica_server_password;
|
|
||||||
/* timeout for commands */
|
|
||||||
struct timeval command_timeout;
|
|
||||||
struct timeval replica_command_timeout;
|
|
||||||
/* timeout for connection setup */
|
|
||||||
struct timeval connect_timeout;
|
|
||||||
struct timeval replica_connect_timeout;
|
|
||||||
/* the reconnect interval time. */
|
|
||||||
struct timeval reconnect_interval;
|
|
||||||
struct timeval replica_reconnect_interval;
|
|
||||||
/* reconnect attempts, 0 if connected, counts up failed reconnects. */
|
|
||||||
int reconnect_attempts;
|
|
||||||
int replica_reconnect_attempts;
|
|
||||||
/* Lock on reconnect_wait time. */
|
|
||||||
lock_basic_type wait_lock;
|
|
||||||
lock_basic_type replica_wait_lock;
|
|
||||||
/* reconnect wait time, wait until it has passed before reconnect. */
|
|
||||||
struct timeval reconnect_wait;
|
|
||||||
struct timeval replica_reconnect_wait;
|
|
||||||
/* the redis logical database to use */
|
|
||||||
int logical_db;
|
|
||||||
int replica_logical_db;
|
|
||||||
/* if the SET with EX command is supported */
|
|
||||||
int set_with_ex_available;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/** The limit on the number of redis connect attempts. After failure if
|
|
||||||
* the number is exceeded, the reconnects are throttled by the wait time. */
|
|
||||||
#define REDIS_RECONNECT_ATTEMPT_LIMIT 3
|
|
||||||
|
|
||||||
static redisReply* redis_command(struct module_env*, struct cachedb_env*,
|
static redisReply* redis_command(struct module_env*, struct cachedb_env*,
|
||||||
const char*, const uint8_t*, size_t, int);
|
const char*, const uint8_t*, size_t);
|
||||||
|
|
||||||
static void
|
|
||||||
moddata_clean(struct redis_moddata** moddata) {
|
|
||||||
if(!moddata || !*moddata)
|
|
||||||
return;
|
|
||||||
if((*moddata)->ctxs) {
|
|
||||||
int i;
|
|
||||||
for(i = 0; i < (*moddata)->numctxs; i++) {
|
|
||||||
if((*moddata)->ctxs[i])
|
|
||||||
redisFree((*moddata)->ctxs[i]);
|
|
||||||
}
|
|
||||||
free((*moddata)->ctxs);
|
|
||||||
}
|
|
||||||
if((*moddata)->replica_ctxs) {
|
|
||||||
int i;
|
|
||||||
for(i = 0; i < (*moddata)->numctxs; i++) {
|
|
||||||
if((*moddata)->replica_ctxs[i])
|
|
||||||
redisFree((*moddata)->replica_ctxs[i]);
|
|
||||||
}
|
|
||||||
free((*moddata)->replica_ctxs);
|
|
||||||
}
|
|
||||||
lock_basic_destroy(&(*moddata)->wait_lock);
|
|
||||||
lock_basic_destroy(&(*moddata)->replica_wait_lock);
|
|
||||||
free(*moddata);
|
|
||||||
*moddata = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static redisContext*
|
static redisContext*
|
||||||
redis_connect(const char* host, int port, const char* path,
|
redis_connect(const struct redis_moddata* moddata)
|
||||||
const char* password, int logical_db,
|
|
||||||
const struct timeval connect_timeout,
|
|
||||||
const struct timeval command_timeout,
|
|
||||||
const struct timeval* reconnect_interval,
|
|
||||||
int* reconnect_attempts,
|
|
||||||
struct timeval* reconnect_wait,
|
|
||||||
lock_basic_type* wait_lock,
|
|
||||||
struct timeval* now_tv,
|
|
||||||
const char* infostr)
|
|
||||||
{
|
{
|
||||||
struct timeval now_val;
|
|
||||||
redisContext* ctx;
|
redisContext* ctx;
|
||||||
#ifdef THREADS_DISABLED
|
|
||||||
/* Fix attribute unused warning.
|
|
||||||
* wait_lock is only used with lock_basic_* functions that are nop'ed
|
|
||||||
* when compiled without thread support. */
|
|
||||||
(void)wait_lock;
|
|
||||||
#endif /* THREADS_DISABLED */
|
|
||||||
|
|
||||||
/* See if the redis server is down, and reconnect has to wait. */
|
ctx = redisConnectWithTimeout(moddata->server_host,
|
||||||
if(*reconnect_attempts > REDIS_RECONNECT_ATTEMPT_LIMIT) {
|
moddata->server_port, moddata->timeout);
|
||||||
/* Acquire lock to look at timeval, the integer has atomic
|
|
||||||
* integrity. */
|
|
||||||
struct timeval wait_tv;
|
|
||||||
if(now_tv) {
|
|
||||||
now_val = *now_tv;
|
|
||||||
} else {
|
|
||||||
if(gettimeofday(&now_val, NULL) < 0)
|
|
||||||
log_err("redis: gettimeofday: %s",
|
|
||||||
strerror(errno));
|
|
||||||
}
|
|
||||||
lock_basic_lock(wait_lock);
|
|
||||||
wait_tv = *reconnect_wait;
|
|
||||||
lock_basic_unlock(wait_lock);
|
|
||||||
if(timeval_smaller(&now_val, &wait_tv)) {
|
|
||||||
verbose(VERB_ALGO, "redis %sdown, reconnect wait",
|
|
||||||
infostr);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(path && path[0]!=0) {
|
|
||||||
ctx = redisConnectUnixWithTimeout(path, connect_timeout);
|
|
||||||
} else {
|
|
||||||
ctx = redisConnectWithTimeout(host, port, connect_timeout);
|
|
||||||
}
|
|
||||||
if(!ctx || ctx->err) {
|
if(!ctx || ctx->err) {
|
||||||
const char *errstr = "out of memory";
|
const char *errstr = "out of memory";
|
||||||
if(ctx)
|
if(ctx)
|
||||||
errstr = ctx->errstr;
|
errstr = ctx->errstr;
|
||||||
log_err("failed to connect to redis %sserver: %s", infostr, errstr);
|
log_err("failed to connect to redis server: %s", errstr);
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
if(redisSetTimeout(ctx, command_timeout) != REDIS_OK) {
|
if(redisSetTimeout(ctx, moddata->timeout) != REDIS_OK) {
|
||||||
log_err("failed to set redis %stimeout, %s", infostr, ctx->errstr);
|
log_err("failed to set redis timeout");
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
if(password && password[0]!=0) {
|
|
||||||
redisReply* rep;
|
|
||||||
rep = redisCommand(ctx, "AUTH %s", password);
|
|
||||||
if(!rep || rep->type == REDIS_REPLY_ERROR) {
|
|
||||||
log_err("failed to authenticate %swith password", infostr);
|
|
||||||
freeReplyObject(rep);
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
freeReplyObject(rep);
|
|
||||||
}
|
|
||||||
if(logical_db > 0) {
|
|
||||||
redisReply* rep;
|
|
||||||
rep = redisCommand(ctx, "SELECT %d", logical_db);
|
|
||||||
if(!rep || rep->type == REDIS_REPLY_ERROR) {
|
|
||||||
log_err("failed %sto set logical database (%d)",
|
|
||||||
infostr, logical_db);
|
|
||||||
freeReplyObject(rep);
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
freeReplyObject(rep);
|
|
||||||
}
|
|
||||||
*reconnect_attempts = 0;
|
|
||||||
if(verbosity >= VERB_OPS) {
|
|
||||||
char port_str[6+1];
|
|
||||||
port_str[0] = ' ';
|
|
||||||
(void)snprintf(port_str+1, sizeof(port_str)-1, "%d", port);
|
|
||||||
verbose(VERB_OPS, "Connection to Redis %sestablished (%s%s)",
|
|
||||||
infostr,
|
|
||||||
path&&path[0]!=0?path:host,
|
|
||||||
path&&path[0]!=0?"":port_str);
|
|
||||||
}
|
|
||||||
return ctx;
|
return ctx;
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
if(ctx)
|
if(ctx)
|
||||||
redisFree(ctx);
|
redisFree(ctx);
|
||||||
(*reconnect_attempts)++;
|
|
||||||
if(*reconnect_attempts > REDIS_RECONNECT_ATTEMPT_LIMIT) {
|
|
||||||
/* Wait for the reconnect interval before trying again. */
|
|
||||||
struct timeval tv;
|
|
||||||
if(now_tv) {
|
|
||||||
now_val = *now_tv;
|
|
||||||
} else {
|
|
||||||
if(gettimeofday(&now_val, NULL) < 0)
|
|
||||||
log_err("redis: gettimeofday: %s",
|
|
||||||
strerror(errno));
|
|
||||||
}
|
|
||||||
tv = now_val;
|
|
||||||
timeval_add(&tv, reconnect_interval);
|
|
||||||
lock_basic_lock(wait_lock);
|
|
||||||
*reconnect_wait = tv;
|
|
||||||
lock_basic_unlock(wait_lock);
|
|
||||||
verbose(VERB_ALGO, "redis %sreconnect wait until %d.%6.6d",
|
|
||||||
infostr, (int)tv.tv_sec, (int)tv.tv_usec);
|
|
||||||
}
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
set_timeout(struct timeval* timeout, int value, int explicit_value)
|
|
||||||
{
|
|
||||||
int v = explicit_value != 0 ? explicit_value : value;
|
|
||||||
timeout->tv_sec = v / 1000;
|
|
||||||
timeout->tv_usec = (v % 1000) * 1000;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
redis_init(struct module_env* env, struct cachedb_env* cachedb_env)
|
redis_init(struct module_env* env, struct cachedb_env* cachedb_env)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
struct redis_moddata* moddata = NULL;
|
struct redis_moddata* moddata = NULL;
|
||||||
|
|
||||||
verbose(VERB_OPS, "Redis initialization");
|
verbose(VERB_ALGO, "redis_init");
|
||||||
|
|
||||||
moddata = calloc(1, sizeof(struct redis_moddata));
|
moddata = calloc(1, sizeof(struct redis_moddata));
|
||||||
if(!moddata) {
|
if(!moddata) {
|
||||||
log_err("out of memory");
|
log_err("out of memory");
|
||||||
goto fail;
|
return 0;
|
||||||
}
|
}
|
||||||
lock_basic_init(&moddata->wait_lock);
|
|
||||||
lock_protect(&moddata->wait_lock, &moddata->reconnect_wait,
|
|
||||||
sizeof(moddata->reconnect_wait));
|
|
||||||
lock_basic_init(&moddata->replica_wait_lock);
|
|
||||||
lock_protect(&moddata->replica_wait_lock,
|
|
||||||
&moddata->replica_reconnect_wait,
|
|
||||||
sizeof(moddata->replica_reconnect_wait));
|
|
||||||
moddata->numctxs = env->cfg->num_threads;
|
moddata->numctxs = env->cfg->num_threads;
|
||||||
/* note: server_host and similar string configuration options are
|
|
||||||
* shallow references to configured strings; we don't have to free them
|
|
||||||
* in this module. */
|
|
||||||
moddata->server_host = env->cfg->redis_server_host;
|
|
||||||
moddata->replica_server_host = env->cfg->redis_replica_server_host;
|
|
||||||
|
|
||||||
moddata->server_port = env->cfg->redis_server_port;
|
|
||||||
moddata->replica_server_port = env->cfg->redis_replica_server_port;
|
|
||||||
|
|
||||||
moddata->server_path = env->cfg->redis_server_path;
|
|
||||||
moddata->replica_server_path = env->cfg->redis_replica_server_path;
|
|
||||||
|
|
||||||
moddata->server_password = env->cfg->redis_server_password;
|
|
||||||
moddata->replica_server_password = env->cfg->redis_replica_server_password;
|
|
||||||
|
|
||||||
set_timeout(&moddata->command_timeout,
|
|
||||||
env->cfg->redis_timeout,
|
|
||||||
env->cfg->redis_command_timeout);
|
|
||||||
set_timeout(&moddata->replica_command_timeout,
|
|
||||||
env->cfg->redis_replica_timeout,
|
|
||||||
env->cfg->redis_replica_command_timeout);
|
|
||||||
set_timeout(&moddata->connect_timeout,
|
|
||||||
env->cfg->redis_timeout,
|
|
||||||
env->cfg->redis_connect_timeout);
|
|
||||||
set_timeout(&moddata->replica_connect_timeout,
|
|
||||||
env->cfg->redis_replica_timeout,
|
|
||||||
env->cfg->redis_replica_connect_timeout);
|
|
||||||
set_timeout(&moddata->reconnect_interval, 1000, 0);
|
|
||||||
set_timeout(&moddata->replica_reconnect_interval, 1000, 0);
|
|
||||||
|
|
||||||
moddata->logical_db = env->cfg->redis_logical_db;
|
|
||||||
moddata->replica_logical_db = env->cfg->redis_replica_logical_db;
|
|
||||||
|
|
||||||
moddata->ctxs = calloc(env->cfg->num_threads, sizeof(redisContext*));
|
moddata->ctxs = calloc(env->cfg->num_threads, sizeof(redisContext*));
|
||||||
if(!moddata->ctxs) {
|
if(!moddata->ctxs) {
|
||||||
log_err("out of memory");
|
log_err("out of memory");
|
||||||
goto fail;
|
free(moddata);
|
||||||
}
|
return 0;
|
||||||
if((moddata->replica_server_host && moddata->replica_server_host[0]!=0)
|
|
||||||
|| (moddata->replica_server_path && moddata->replica_server_path[0]!=0)) {
|
|
||||||
/* There is a replica configured, allocate ctxs */
|
|
||||||
moddata->replica_ctxs = calloc(env->cfg->num_threads, sizeof(redisContext*));
|
|
||||||
if(!moddata->replica_ctxs) {
|
|
||||||
log_err("out of memory");
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for(i = 0; i < moddata->numctxs; i++) {
|
|
||||||
redisContext* ctx = redis_connect(
|
|
||||||
moddata->server_host,
|
|
||||||
moddata->server_port,
|
|
||||||
moddata->server_path,
|
|
||||||
moddata->server_password,
|
|
||||||
moddata->logical_db,
|
|
||||||
moddata->connect_timeout,
|
|
||||||
moddata->command_timeout,
|
|
||||||
&moddata->reconnect_interval,
|
|
||||||
&moddata->reconnect_attempts,
|
|
||||||
&moddata->reconnect_wait,
|
|
||||||
&moddata->wait_lock,
|
|
||||||
env->now_tv,
|
|
||||||
"");
|
|
||||||
if(!ctx) {
|
|
||||||
log_err("redis_init: failed to init redis "
|
|
||||||
"(for thread %d)", i);
|
|
||||||
/* And continue, the context can be established
|
|
||||||
* later, just like after a disconnect. */
|
|
||||||
}
|
|
||||||
moddata->ctxs[i] = ctx;
|
|
||||||
}
|
|
||||||
if(moddata->replica_ctxs) {
|
|
||||||
for(i = 0; i < moddata->numctxs; i++) {
|
|
||||||
redisContext* ctx = redis_connect(
|
|
||||||
moddata->replica_server_host,
|
|
||||||
moddata->replica_server_port,
|
|
||||||
moddata->replica_server_path,
|
|
||||||
moddata->replica_server_password,
|
|
||||||
moddata->replica_logical_db,
|
|
||||||
moddata->replica_connect_timeout,
|
|
||||||
moddata->replica_command_timeout,
|
|
||||||
&moddata->replica_reconnect_interval,
|
|
||||||
&moddata->replica_reconnect_attempts,
|
|
||||||
&moddata->replica_reconnect_wait,
|
|
||||||
&moddata->replica_wait_lock,
|
|
||||||
env->now_tv,
|
|
||||||
"replica ");
|
|
||||||
if(!ctx) {
|
|
||||||
log_err("redis_init: failed to init redis "
|
|
||||||
"replica (for thread %d)", i);
|
|
||||||
/* And continue, the context can be established
|
|
||||||
* later, just like after a disconnect. */
|
|
||||||
}
|
|
||||||
moddata->replica_ctxs[i] = ctx;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
/* note: server_host is a shallow reference to configured string.
|
||||||
|
* we don't have to free it in this module. */
|
||||||
|
moddata->server_host = env->cfg->redis_server_host;
|
||||||
|
moddata->server_port = env->cfg->redis_server_port;
|
||||||
|
moddata->timeout.tv_sec = env->cfg->redis_timeout / 1000;
|
||||||
|
moddata->timeout.tv_usec = (env->cfg->redis_timeout % 1000) * 1000;
|
||||||
|
for(i = 0; i < moddata->numctxs; i++)
|
||||||
|
moddata->ctxs[i] = redis_connect(moddata);
|
||||||
cachedb_env->backend_data = moddata;
|
cachedb_env->backend_data = moddata;
|
||||||
if(env->cfg->redis_expire_records &&
|
if(env->cfg->redis_expire_records) {
|
||||||
moddata->ctxs[env->alloc->thread_num] != NULL) {
|
|
||||||
redisReply* rep = NULL;
|
redisReply* rep = NULL;
|
||||||
int redis_reply_type = 0;
|
int redis_reply_type = 0;
|
||||||
/** check if set with ex command is supported */
|
/** check if setex command is supported */
|
||||||
rep = redis_command(env, cachedb_env,
|
rep = redis_command(env, cachedb_env,
|
||||||
"SET __UNBOUND_REDIS_CHECK__ none EX 1", NULL, 0, 1);
|
"SETEX __UNBOUND_REDIS_CHECK__ 1 none", NULL, 0);
|
||||||
if(!rep) {
|
if(!rep) {
|
||||||
/** init failed, no response from redis server*/
|
/** init failed, no response from redis server*/
|
||||||
goto set_with_ex_fail;
|
log_err("redis_init: failed to init redis, the "
|
||||||
|
"redis-expire-records option requires the SETEX command "
|
||||||
|
"(redis >= 2.0.0)");
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
redis_reply_type = rep->type;
|
redis_reply_type = rep->type;
|
||||||
freeReplyObject(rep);
|
freeReplyObject(rep);
|
||||||
@@ -388,21 +136,15 @@ redis_init(struct module_env* env, struct cachedb_env* cachedb_env)
|
|||||||
case REDIS_REPLY_STATUS:
|
case REDIS_REPLY_STATUS:
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
/** init failed, set_with_ex command not supported */
|
/** init failed, setex command not supported */
|
||||||
goto set_with_ex_fail;
|
log_err("redis_init: failed to init redis, the "
|
||||||
|
"redis-expire-records option requires the SETEX command "
|
||||||
|
"(redis >= 2.0.0)");
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
moddata->set_with_ex_available = 1;
|
|
||||||
}
|
}
|
||||||
return 1;
|
|
||||||
|
|
||||||
set_with_ex_fail:
|
|
||||||
log_err("redis_init: failure during redis_init, the "
|
|
||||||
"redis-expire-records option requires the SET with EX command "
|
|
||||||
"(redis >= 2.6.12)");
|
|
||||||
return 1;
|
return 1;
|
||||||
fail:
|
|
||||||
moddata_clean(&moddata);
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -412,8 +154,19 @@ redis_deinit(struct module_env* env, struct cachedb_env* cachedb_env)
|
|||||||
cachedb_env->backend_data;
|
cachedb_env->backend_data;
|
||||||
(void)env;
|
(void)env;
|
||||||
|
|
||||||
verbose(VERB_OPS, "Redis deinitialization");
|
verbose(VERB_ALGO, "redis_deinit");
|
||||||
moddata_clean(&moddata);
|
|
||||||
|
if(!moddata)
|
||||||
|
return;
|
||||||
|
if(moddata->ctxs) {
|
||||||
|
int i;
|
||||||
|
for(i = 0; i < moddata->numctxs; i++) {
|
||||||
|
if(moddata->ctxs[i])
|
||||||
|
redisFree(moddata->ctxs[i]);
|
||||||
|
}
|
||||||
|
free(moddata->ctxs);
|
||||||
|
}
|
||||||
|
free(moddata);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -430,9 +183,9 @@ redis_deinit(struct module_env* env, struct cachedb_env* cachedb_env)
|
|||||||
*/
|
*/
|
||||||
static redisReply*
|
static redisReply*
|
||||||
redis_command(struct module_env* env, struct cachedb_env* cachedb_env,
|
redis_command(struct module_env* env, struct cachedb_env* cachedb_env,
|
||||||
const char* command, const uint8_t* data, size_t data_len, int write)
|
const char* command, const uint8_t* data, size_t data_len)
|
||||||
{
|
{
|
||||||
redisContext* ctx, **ctx_selector;
|
redisContext* ctx;
|
||||||
redisReply* rep;
|
redisReply* rep;
|
||||||
struct redis_moddata* d = (struct redis_moddata*)
|
struct redis_moddata* d = (struct redis_moddata*)
|
||||||
cachedb_env->backend_data;
|
cachedb_env->backend_data;
|
||||||
@@ -443,50 +196,17 @@ redis_command(struct module_env* env, struct cachedb_env* cachedb_env,
|
|||||||
* assumption throughout the unbound architecture, so we simply assert
|
* assumption throughout the unbound architecture, so we simply assert
|
||||||
* it. */
|
* it. */
|
||||||
log_assert(env->alloc->thread_num < d->numctxs);
|
log_assert(env->alloc->thread_num < d->numctxs);
|
||||||
|
ctx = d->ctxs[env->alloc->thread_num];
|
||||||
ctx_selector = !write && d->replica_ctxs
|
|
||||||
?d->replica_ctxs
|
|
||||||
:d->ctxs;
|
|
||||||
ctx = ctx_selector[env->alloc->thread_num];
|
|
||||||
|
|
||||||
/* If we've not established a connection to the server or we've closed
|
/* If we've not established a connection to the server or we've closed
|
||||||
* it on a failure, try to re-establish a new one. Failures will be
|
* it on a failure, try to re-establish a new one. Failures will be
|
||||||
* logged in redis_connect(). */
|
* logged in redis_connect(). */
|
||||||
if(!ctx) {
|
if(!ctx) {
|
||||||
if(!write && d->replica_ctxs) {
|
ctx = redis_connect(d);
|
||||||
ctx = redis_connect(
|
d->ctxs[env->alloc->thread_num] = ctx;
|
||||||
d->replica_server_host,
|
|
||||||
d->replica_server_port,
|
|
||||||
d->replica_server_path,
|
|
||||||
d->replica_server_password,
|
|
||||||
d->replica_logical_db,
|
|
||||||
d->replica_connect_timeout,
|
|
||||||
d->replica_command_timeout,
|
|
||||||
&d->replica_reconnect_interval,
|
|
||||||
&d->replica_reconnect_attempts,
|
|
||||||
&d->replica_reconnect_wait,
|
|
||||||
&d->replica_wait_lock,
|
|
||||||
env->now_tv,
|
|
||||||
"replica ");
|
|
||||||
} else {
|
|
||||||
ctx = redis_connect(
|
|
||||||
d->server_host,
|
|
||||||
d->server_port,
|
|
||||||
d->server_path,
|
|
||||||
d->server_password,
|
|
||||||
d->logical_db,
|
|
||||||
d->connect_timeout,
|
|
||||||
d->command_timeout,
|
|
||||||
&d->reconnect_interval,
|
|
||||||
&d->reconnect_attempts,
|
|
||||||
&d->reconnect_wait,
|
|
||||||
&d->wait_lock,
|
|
||||||
env->now_tv,
|
|
||||||
"");
|
|
||||||
}
|
|
||||||
ctx_selector[env->alloc->thread_num] = ctx;
|
|
||||||
}
|
}
|
||||||
if(!ctx) return NULL;
|
if(!ctx)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
/* Send the command and get a reply, synchronously. */
|
/* Send the command and get a reply, synchronously. */
|
||||||
rep = (redisReply*)redisCommand(ctx, command, data, data_len);
|
rep = (redisReply*)redisCommand(ctx, command, data, data_len);
|
||||||
@@ -496,7 +216,7 @@ redis_command(struct module_env* env, struct cachedb_env* cachedb_env,
|
|||||||
log_err("redis_command: failed to receive a reply, "
|
log_err("redis_command: failed to receive a reply, "
|
||||||
"closing connection: %s", ctx->errstr);
|
"closing connection: %s", ctx->errstr);
|
||||||
redisFree(ctx);
|
redisFree(ctx);
|
||||||
ctx_selector[env->alloc->thread_num] = NULL;
|
d->ctxs[env->alloc->thread_num] = NULL;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -514,14 +234,7 @@ redis_lookup(struct module_env* env, struct cachedb_env* cachedb_env,
|
|||||||
char* key, struct sldns_buffer* result_buffer)
|
char* key, struct sldns_buffer* result_buffer)
|
||||||
{
|
{
|
||||||
redisReply* rep;
|
redisReply* rep;
|
||||||
/* Supported commands:
|
char cmdbuf[4+(CACHEDB_HASHSIZE/8)*2+1]; /* "GET " + key */
|
||||||
* - "GET " + key
|
|
||||||
*/
|
|
||||||
#define REDIS_LOOKUP_MAX_BUF_LEN \
|
|
||||||
4 /* "GET " */ \
|
|
||||||
+(CACHEDB_HASHSIZE/8)*2 /* key hash */ \
|
|
||||||
+ 1 /* \0 */
|
|
||||||
char cmdbuf[REDIS_LOOKUP_MAX_BUF_LEN];
|
|
||||||
int n;
|
int n;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
@@ -533,7 +246,7 @@ redis_lookup(struct module_env* env, struct cachedb_env* cachedb_env,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
rep = redis_command(env, cachedb_env, cmdbuf, NULL, 0, 0);
|
rep = redis_command(env, cachedb_env, cmdbuf, NULL, 0);
|
||||||
if(!rep)
|
if(!rep)
|
||||||
return 0;
|
return 0;
|
||||||
switch(rep->type) {
|
switch(rep->type) {
|
||||||
@@ -570,45 +283,26 @@ redis_store(struct module_env* env, struct cachedb_env* cachedb_env,
|
|||||||
{
|
{
|
||||||
redisReply* rep;
|
redisReply* rep;
|
||||||
int n;
|
int n;
|
||||||
struct redis_moddata* moddata = (struct redis_moddata*)
|
int set_ttl = (env->cfg->redis_expire_records &&
|
||||||
cachedb_env->backend_data;
|
|
||||||
int set_ttl = (moddata->set_with_ex_available &&
|
|
||||||
env->cfg->redis_expire_records &&
|
|
||||||
(!env->cfg->serve_expired || env->cfg->serve_expired_ttl > 0));
|
(!env->cfg->serve_expired || env->cfg->serve_expired_ttl > 0));
|
||||||
/* Supported commands:
|
/* Supported commands:
|
||||||
* - "SET " + key + " %b"
|
* - "SET " + key + " %b"
|
||||||
* - "SET " + key + " %b EX " + ttl
|
* - "SETEX " + key + " " + ttl + " %b"
|
||||||
* older redis 2.0.0 was "SETEX " + key + " " + ttl + " %b"
|
|
||||||
* - "EXPIRE " + key + " 0"
|
|
||||||
*/
|
*/
|
||||||
#define REDIS_STORE_MAX_BUF_LEN \
|
char cmdbuf[6+(CACHEDB_HASHSIZE/8)*2+11+3+1];
|
||||||
7 /* "EXPIRE " */ \
|
|
||||||
+(CACHEDB_HASHSIZE/8)*2 /* key hash */ \
|
|
||||||
+ 7 /* " %b EX " */ \
|
|
||||||
+ 20 /* ttl (uint64_t) */ \
|
|
||||||
+ 1 /* \0 */
|
|
||||||
char cmdbuf[REDIS_STORE_MAX_BUF_LEN];
|
|
||||||
|
|
||||||
if (!set_ttl) {
|
if (!set_ttl) {
|
||||||
verbose(VERB_ALGO, "redis_store %s (%d bytes)", key, (int)data_len);
|
verbose(VERB_ALGO, "redis_store %s (%d bytes)", key, (int)data_len);
|
||||||
/* build command to set to a binary safe string */
|
/* build command to set to a binary safe string */
|
||||||
n = snprintf(cmdbuf, sizeof(cmdbuf), "SET %s %%b", key);
|
n = snprintf(cmdbuf, sizeof(cmdbuf), "SET %s %%b", key);
|
||||||
} else if(ttl == 0) {
|
|
||||||
/* use the EXPIRE command, SET with EX 0 is an invalid time. */
|
|
||||||
/* Replies with REDIS_REPLY_INTEGER of 1. */
|
|
||||||
verbose(VERB_ALGO, "redis_store expire %s (%d bytes)",
|
|
||||||
key, (int)data_len);
|
|
||||||
n = snprintf(cmdbuf, sizeof(cmdbuf), "EXPIRE %s 0", key);
|
|
||||||
data = NULL;
|
|
||||||
data_len = 0;
|
|
||||||
} else {
|
} else {
|
||||||
/* add expired ttl time to redis ttl to avoid premature eviction of key */
|
/* add expired ttl time to redis ttl to avoid premature eviction of key */
|
||||||
ttl += env->cfg->serve_expired_ttl;
|
ttl += env->cfg->serve_expired_ttl;
|
||||||
verbose(VERB_ALGO, "redis_store %s (%d bytes) with ttl %u",
|
verbose(VERB_ALGO, "redis_store %s (%d bytes) with ttl %u",
|
||||||
key, (int)data_len, (unsigned)(uint32_t)ttl);
|
key, (int)data_len, (uint32_t)ttl);
|
||||||
/* build command to set to a binary safe string */
|
/* build command to set to a binary safe string */
|
||||||
n = snprintf(cmdbuf, sizeof(cmdbuf), "SET %s %%b EX %u", key,
|
n = snprintf(cmdbuf, sizeof(cmdbuf), "SETEX %s %u %%b", key,
|
||||||
(unsigned)(uint32_t)ttl);
|
(uint32_t)ttl);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -617,12 +311,11 @@ redis_store(struct module_env* env, struct cachedb_env* cachedb_env,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
rep = redis_command(env, cachedb_env, cmdbuf, data, data_len, 1);
|
rep = redis_command(env, cachedb_env, cmdbuf, data, data_len);
|
||||||
if(rep) {
|
if(rep) {
|
||||||
verbose(VERB_ALGO, "redis_store set completed");
|
verbose(VERB_ALGO, "redis_store set completed");
|
||||||
if(rep->type != REDIS_REPLY_STATUS &&
|
if(rep->type != REDIS_REPLY_STATUS &&
|
||||||
rep->type != REDIS_REPLY_ERROR &&
|
rep->type != REDIS_REPLY_ERROR) {
|
||||||
rep->type != REDIS_REPLY_INTEGER) {
|
|
||||||
log_err("redis_store: unexpected type of reply (%d)",
|
log_err("redis_store: unexpected type of reply (%d)",
|
||||||
rep->type);
|
rep->type);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,9 +38,6 @@
|
|||||||
#ifndef UB_ON_WINDOWS
|
#ifndef UB_ON_WINDOWS
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
#endif
|
#endif
|
||||||
#ifdef __QNX__
|
|
||||||
#include "util/log.h"
|
|
||||||
#endif /* __QNX__ */
|
|
||||||
|
|
||||||
#define KEYSTREAM_ONLY
|
#define KEYSTREAM_ONLY
|
||||||
#include "chacha_private.h"
|
#include "chacha_private.h"
|
||||||
@@ -190,11 +187,7 @@ _rs_stir(void)
|
|||||||
if(errno != ENOSYS ||
|
if(errno != ENOSYS ||
|
||||||
fallback_getentropy_urandom(rnd, sizeof rnd) == -1) {
|
fallback_getentropy_urandom(rnd, sizeof rnd) == -1) {
|
||||||
#ifdef SIGKILL
|
#ifdef SIGKILL
|
||||||
#ifndef __QNX__
|
|
||||||
raise(SIGKILL);
|
raise(SIGKILL);
|
||||||
#else /* !__QNX__ */
|
|
||||||
fatal_exit("failed to getentropy");
|
|
||||||
#endif /* __QNX__ */
|
|
||||||
#else
|
#else
|
||||||
exit(9); /* windows */
|
exit(9); /* windows */
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -48,8 +48,8 @@ typedef struct
|
|||||||
a = PLUS(a,b); d = ROTATE(XOR(d,a), 8); \
|
a = PLUS(a,b); d = ROTATE(XOR(d,a), 8); \
|
||||||
c = PLUS(c,d); b = ROTATE(XOR(b,c), 7);
|
c = PLUS(c,d); b = ROTATE(XOR(b,c), 7);
|
||||||
|
|
||||||
static const char ATTR_NONSTRING(sigma[16]) = "expand 32-byte k";
|
static const char sigma[16] = "expand 32-byte k";
|
||||||
static const char ATTR_NONSTRING(tau[16]) = "expand 16-byte k";
|
static const char tau[16] = "expand 16-byte k";
|
||||||
|
|
||||||
static void
|
static void
|
||||||
chacha_keysetup(chacha_ctx *x,const u8 *k,u32 kbits,u32 ATTR_UNUSED(ivbits))
|
chacha_keysetup(chacha_ctx *x,const u8 *k,u32 kbits,u32 ATTR_UNUSED(ivbits))
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ int getnameinfo(const struct sockaddr *sa, size_t ATTR_UNUSED(salen), char *host
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (host != NULL) {
|
if (host != NULL) {
|
||||||
if ((flags & NI_NUMERICHOST)) {
|
if (flags & NI_NUMERICHOST) {
|
||||||
if (strlcpy(host, inet_ntoa(sin->sin_addr),
|
if (strlcpy(host, inet_ntoa(sin->sin_addr),
|
||||||
hostlen) >= hostlen)
|
hostlen) >= hostlen)
|
||||||
return (EAI_MEMORY);
|
return (EAI_MEMORY);
|
||||||
@@ -168,7 +168,7 @@ getaddrinfo(const char *hostname, const char *servname,
|
|||||||
port = 0;
|
port = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hints && (hints->ai_flags & AI_PASSIVE)) {
|
if (hints && hints->ai_flags & AI_PASSIVE) {
|
||||||
addr = htonl(0x00000000);
|
addr = htonl(0x00000000);
|
||||||
if (hostname && inet_aton(hostname, &in) != 0)
|
if (hostname && inet_aton(hostname, &in) != 0)
|
||||||
addr = in.s_addr;
|
addr = in.s_addr;
|
||||||
@@ -193,7 +193,7 @@ getaddrinfo(const char *hostname, const char *servname,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Don't try DNS if AI_NUMERICHOST is set */
|
/* Don't try DNS if AI_NUMERICHOST is set */
|
||||||
if (hints && (hints->ai_flags & AI_NUMERICHOST))
|
if (hints && hints->ai_flags & AI_NUMERICHOST)
|
||||||
return (EAI_NONAME);
|
return (EAI_NONAME);
|
||||||
|
|
||||||
hp = gethostbyname(hostname);
|
hp = gethostbyname(hostname);
|
||||||
|
|||||||
@@ -29,9 +29,7 @@
|
|||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
#include <sys/resource.h>
|
#include <sys/resource.h>
|
||||||
#ifndef __QNX__
|
|
||||||
#include <sys/syscall.h>
|
#include <sys/syscall.h>
|
||||||
#endif /* !__QNX__ */
|
|
||||||
#ifdef SYS__sysctl
|
#ifdef SYS__sysctl
|
||||||
#include <linux/sysctl.h>
|
#include <linux/sysctl.h>
|
||||||
#endif
|
#endif
|
||||||
@@ -44,9 +42,7 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#ifndef __QNX__
|
|
||||||
#include <link.h>
|
#include <link.h>
|
||||||
#endif /* __QNX__ */
|
|
||||||
#include <termios.h>
|
#include <termios.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
@@ -64,14 +60,12 @@
|
|||||||
#define SHA512_Final(r, c) sha512_digest(c, SHA512_DIGEST_SIZE, r)
|
#define SHA512_Final(r, c) sha512_digest(c, SHA512_DIGEST_SIZE, r)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef __QNX__
|
|
||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
#include <linux/random.h>
|
#include <linux/random.h>
|
||||||
#ifdef HAVE_GETAUXVAL
|
#ifdef HAVE_GETAUXVAL
|
||||||
#include <sys/auxv.h>
|
#include <sys/auxv.h>
|
||||||
#endif
|
#endif
|
||||||
#include <sys/vfs.h>
|
#include <sys/vfs.h>
|
||||||
#endif /* !__QNX__ */
|
|
||||||
#ifndef MAP_ANON
|
#ifndef MAP_ANON
|
||||||
#define MAP_ANON MAP_ANONYMOUS
|
#define MAP_ANON MAP_ANONYMOUS
|
||||||
#endif
|
#endif
|
||||||
@@ -100,10 +94,8 @@ static int getentropy_urandom(void *buf, size_t len);
|
|||||||
#ifdef SYS__sysctl
|
#ifdef SYS__sysctl
|
||||||
static int getentropy_sysctl(void *buf, size_t len);
|
static int getentropy_sysctl(void *buf, size_t len);
|
||||||
#endif
|
#endif
|
||||||
#ifndef __QNX__
|
|
||||||
static int getentropy_fallback(void *buf, size_t len);
|
static int getentropy_fallback(void *buf, size_t len);
|
||||||
static int getentropy_phdr(struct dl_phdr_info *info, size_t size, void *data);
|
static int getentropy_phdr(struct dl_phdr_info *info, size_t size, void *data);
|
||||||
#endif /* !__QNX__ */
|
|
||||||
|
|
||||||
int
|
int
|
||||||
getentropy(void *buf, size_t len)
|
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
|
* sysctl ABI, or consider providing a new failsafe API which
|
||||||
* works in a chroot or when file descriptors are exhausted.
|
* works in a chroot or when file descriptors are exhausted.
|
||||||
*/
|
*/
|
||||||
#ifndef __QNX__
|
|
||||||
#undef FAIL_INSTEAD_OF_TRYING_FALLBACK
|
#undef FAIL_INSTEAD_OF_TRYING_FALLBACK
|
||||||
#ifdef FAIL_INSTEAD_OF_TRYING_FALLBACK
|
#ifdef FAIL_INSTEAD_OF_TRYING_FALLBACK
|
||||||
raise(SIGKILL);
|
raise(SIGKILL);
|
||||||
@@ -194,9 +185,6 @@ getentropy(void *buf, size_t len)
|
|||||||
ret = getentropy_fallback(buf, len);
|
ret = getentropy_fallback(buf, len);
|
||||||
if (ret != -1)
|
if (ret != -1)
|
||||||
return (ret);
|
return (ret);
|
||||||
#else /* !__QNX__ */
|
|
||||||
fatal_exit("failed to read from /dev/urandom");
|
|
||||||
#endif /* __QNX__ */
|
|
||||||
|
|
||||||
errno = EIO;
|
errno = EIO;
|
||||||
return (ret);
|
return (ret);
|
||||||
@@ -226,11 +214,7 @@ getentropy_urandom(void *buf, size_t len)
|
|||||||
{
|
{
|
||||||
struct stat st;
|
struct stat st;
|
||||||
size_t i;
|
size_t i;
|
||||||
#ifndef __QNX__
|
|
||||||
int fd, cnt, flags;
|
int fd, cnt, flags;
|
||||||
#else /* !__QNX__ */
|
|
||||||
int fd, flags;
|
|
||||||
#endif /* __QNX__ */
|
|
||||||
int save_errno = errno;
|
int save_errno = errno;
|
||||||
|
|
||||||
start:
|
start:
|
||||||
@@ -257,12 +241,10 @@ start:
|
|||||||
close(fd);
|
close(fd);
|
||||||
goto nodevrandom;
|
goto nodevrandom;
|
||||||
}
|
}
|
||||||
#ifndef __QNX__
|
|
||||||
if (ioctl(fd, RNDGETENTCNT, &cnt) == -1) {
|
if (ioctl(fd, RNDGETENTCNT, &cnt) == -1) {
|
||||||
close(fd);
|
close(fd);
|
||||||
goto nodevrandom;
|
goto nodevrandom;
|
||||||
}
|
}
|
||||||
#endif /* !__QNX__ */
|
|
||||||
for (i = 0; i < len; ) {
|
for (i = 0; i < len; ) {
|
||||||
size_t wanted = len - i;
|
size_t wanted = len - i;
|
||||||
ssize_t ret = read(fd, (char *)buf + i, wanted);
|
ssize_t ret = read(fd, (char *)buf + i, wanted);
|
||||||
@@ -283,7 +265,6 @@ nodevrandom:
|
|||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef __QNX__
|
|
||||||
#ifdef SYS__sysctl
|
#ifdef SYS__sysctl
|
||||||
static int
|
static int
|
||||||
getentropy_sysctl(void *buf, size_t len)
|
getentropy_sysctl(void *buf, size_t len)
|
||||||
@@ -556,4 +537,3 @@ getentropy_fallback(void *buf, size_t len)
|
|||||||
errno = save_errno;
|
errno = save_errno;
|
||||||
return (0); /* satisfied */
|
return (0); /* satisfied */
|
||||||
}
|
}
|
||||||
#endif /* !__QNX__ */
|
|
||||||
|
|||||||
+382
-9
@@ -20,25 +20,398 @@
|
|||||||
* http://man.openbsd.org/getentropy.2
|
* http://man.openbsd.org/getentropy.2
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Modified to use SecRandomCopyBytes. It is from macOS 10.7 (2011) and
|
#include <TargetConditionals.h>
|
||||||
* iOS 2.0 (2008), and is the primary API for cryptographic random numbers. */
|
#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 <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);
|
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
|
int
|
||||||
getentropy(void *buf, size_t len)
|
getentropy(void *buf, size_t len)
|
||||||
{
|
{
|
||||||
|
int ret = -1;
|
||||||
|
|
||||||
if (len > 256) {
|
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;
|
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 */
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,7 +47,7 @@
|
|||||||
#define SHA512_Update SHA512Update
|
#define SHA512_Update SHA512Update
|
||||||
#define SHA512_Final SHA512Final
|
#define SHA512_Final SHA512Final
|
||||||
#else
|
#else
|
||||||
#include <openssl/sha.h>
|
#include "openssl/sha.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <sys/vfs.h>
|
#include <sys/vfs.h>
|
||||||
|
|||||||
+4
-1
@@ -42,7 +42,10 @@ static const int year_lengths[2] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static void
|
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 days;
|
||||||
long rem;
|
long rem;
|
||||||
|
|||||||
+10
-3
@@ -59,7 +59,10 @@ static int inet_pton6 (const char *src, uint8_t *dst);
|
|||||||
* Paul Vixie, 1996.
|
* Paul Vixie, 1996.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
inet_pton(int af, const char *src, void *dst)
|
inet_pton(af, src, dst)
|
||||||
|
int af;
|
||||||
|
const char *src;
|
||||||
|
void *dst;
|
||||||
{
|
{
|
||||||
switch (af) {
|
switch (af) {
|
||||||
case AF_INET:
|
case AF_INET:
|
||||||
@@ -88,7 +91,9 @@ inet_pton(int af, const char *src, void *dst)
|
|||||||
* Paul Vixie, 1996.
|
* Paul Vixie, 1996.
|
||||||
*/
|
*/
|
||||||
static int
|
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";
|
static const char digits[] = "0123456789";
|
||||||
int saw_digit, octets, ch;
|
int saw_digit, octets, ch;
|
||||||
@@ -140,7 +145,9 @@ inet_pton4(const char *src, uint8_t *dst)
|
|||||||
* Paul Vixie, 1996.
|
* Paul Vixie, 1996.
|
||||||
*/
|
*/
|
||||||
static int
|
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",
|
static const char xdigits_l[] = "0123456789abcdef",
|
||||||
xdigits_u[] = "0123456789ABCDEF";
|
xdigits_u[] = "0123456789ABCDEF";
|
||||||
|
|||||||
@@ -5,8 +5,12 @@
|
|||||||
#undef malloc
|
#undef malloc
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
#ifndef USE_WINSOCK
|
||||||
|
void *malloc ();
|
||||||
|
#else
|
||||||
/* provide a prototype */
|
/* provide a prototype */
|
||||||
void *malloc (size_t n);
|
void *malloc (size_t n);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Allocate an N-byte block of memory from the heap.
|
/* Allocate an N-byte block of memory from the heap.
|
||||||
If N is zero, allocate a 1-byte block. */
|
If N is zero, allocate a 1-byte block. */
|
||||||
|
|||||||
Vendored
+559
-704
File diff suppressed because it is too large
Load Diff
+23
-277
@@ -1,8 +1,5 @@
|
|||||||
/* config.h.in. Generated from configure.ac by autoheader. */
|
/* config.h.in. Generated from configure.ac by autoheader. */
|
||||||
|
|
||||||
/* apply the fallthrough attribute. */
|
|
||||||
#undef ATTR_FALLTHROUGH
|
|
||||||
|
|
||||||
/* apply the noreturn attribute to a function that exits the program */
|
/* apply the noreturn attribute to a function that exits the program */
|
||||||
#undef ATTR_NORETURN
|
#undef ATTR_NORETURN
|
||||||
|
|
||||||
@@ -31,9 +28,6 @@
|
|||||||
/* Whether daemon is deprecated */
|
/* Whether daemon is deprecated */
|
||||||
#undef DEPRECATED_DAEMON
|
#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 */
|
/* Deprecate RSA 1024 bit length, makes that an unsupported key */
|
||||||
#undef DEPRECATE_RSA_1024
|
#undef DEPRECATE_RSA_1024
|
||||||
|
|
||||||
@@ -63,18 +57,9 @@
|
|||||||
/* Define to 1 if you have the <arpa/inet.h> header file. */
|
/* Define to 1 if you have the <arpa/inet.h> header file. */
|
||||||
#undef HAVE_ARPA_INET_H
|
#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
|
|
||||||
|
|
||||||
/* Whether the C compiler accepts the "format" attribute */
|
/* Whether the C compiler accepts the "format" attribute */
|
||||||
#undef HAVE_ATTR_FORMAT
|
#undef HAVE_ATTR_FORMAT
|
||||||
|
|
||||||
/* Whether the C compiler accepts the "nonstring" attribute */
|
|
||||||
#undef HAVE_ATTR_NONSTRING
|
|
||||||
|
|
||||||
/* Whether the C compiler accepts the "noreturn" attribute */
|
/* Whether the C compiler accepts the "noreturn" attribute */
|
||||||
#undef HAVE_ATTR_NORETURN
|
#undef HAVE_ATTR_NORETURN
|
||||||
|
|
||||||
@@ -138,18 +123,6 @@
|
|||||||
and to 0 if you don't. */
|
and to 0 if you don't. */
|
||||||
#undef HAVE_DECL_NGHTTP2_SESSION_SERVER_NEW
|
#undef HAVE_DECL_NGHTTP2_SESSION_SERVER_NEW
|
||||||
|
|
||||||
/* Define to 1 if you have the declaration of `ngtcp2_conn_server_new', and to
|
|
||||||
0 if you don't. */
|
|
||||||
#undef HAVE_DECL_NGTCP2_CONN_SERVER_NEW
|
|
||||||
|
|
||||||
/* Define to 1 if you have the declaration of `ngtcp2_crypto_encrypt_cb', and
|
|
||||||
to 0 if you don't. */
|
|
||||||
#undef HAVE_DECL_NGTCP2_CRYPTO_ENCRYPT_CB
|
|
||||||
|
|
||||||
/* Define to 1 if you have the declaration of `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
|
/* Define to 1 if you have the declaration of `NID_ED25519', and to 0 if you
|
||||||
don't. */
|
don't. */
|
||||||
#undef HAVE_DECL_NID_ED25519
|
#undef HAVE_DECL_NID_ED25519
|
||||||
@@ -186,10 +159,6 @@
|
|||||||
0 if you don't. */
|
0 if you don't. */
|
||||||
#undef HAVE_DECL_SSL_CTX_SET_ECDH_AUTO
|
#undef HAVE_DECL_SSL_CTX_SET_ECDH_AUTO
|
||||||
|
|
||||||
/* Define to 1 if you have the declaration of `SSL_CTX_set_tmp_ecdh', and to 0
|
|
||||||
if you don't. */
|
|
||||||
#undef HAVE_DECL_SSL_CTX_SET_TMP_ECDH
|
|
||||||
|
|
||||||
/* Define to 1 if you have the declaration of `strlcat', and to 0 if you
|
/* Define to 1 if you have the declaration of `strlcat', and to 0 if you
|
||||||
don't. */
|
don't. */
|
||||||
#undef HAVE_DECL_STRLCAT
|
#undef HAVE_DECL_STRLCAT
|
||||||
@@ -299,12 +268,6 @@
|
|||||||
/* Define to 1 if you have the `FIPS_mode' function. */
|
/* Define to 1 if you have the `FIPS_mode' function. */
|
||||||
#undef HAVE_FIPS_MODE
|
#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. */
|
/* Define to 1 if you have the `fork' function. */
|
||||||
#undef HAVE_FORK
|
#undef HAVE_FORK
|
||||||
|
|
||||||
@@ -401,12 +364,6 @@
|
|||||||
/* Define if we have LibreSSL */
|
/* Define if we have LibreSSL */
|
||||||
#undef HAVE_LIBRESSL
|
#undef HAVE_LIBRESSL
|
||||||
|
|
||||||
/* If we have atomic_store */
|
|
||||||
#undef HAVE_LINK_ATOMIC_STORE
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <linux/net_tstamp.h> header file. */
|
|
||||||
#undef HAVE_LINUX_NET_TSTAMP_H
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `localtime_r' function. */
|
/* Define to 1 if you have the `localtime_r' function. */
|
||||||
#undef HAVE_LOCALTIME_R
|
#undef HAVE_LOCALTIME_R
|
||||||
|
|
||||||
@@ -419,8 +376,8 @@
|
|||||||
/* Define to 1 if you have the `memmove' function. */
|
/* Define to 1 if you have the `memmove' function. */
|
||||||
#undef HAVE_MEMMOVE
|
#undef HAVE_MEMMOVE
|
||||||
|
|
||||||
/* Define to 1 if you have the <minix/config.h> header file. */
|
/* Define to 1 if you have the <memory.h> header file. */
|
||||||
#undef HAVE_MINIX_CONFIG_H
|
#undef HAVE_MEMORY_H
|
||||||
|
|
||||||
/* Define to 1 if you have the <netdb.h> header file. */
|
/* Define to 1 if you have the <netdb.h> header file. */
|
||||||
#undef HAVE_NETDB_H
|
#undef HAVE_NETDB_H
|
||||||
@@ -446,80 +403,12 @@
|
|||||||
/* Define to 1 if you have the <net/if.h> header file. */
|
/* Define to 1 if you have the <net/if.h> header file. */
|
||||||
#undef HAVE_NET_IF_H
|
#undef HAVE_NET_IF_H
|
||||||
|
|
||||||
/* Define to 1 if you have the <net/pfvar.h> header file. */
|
|
||||||
#undef HAVE_NET_PFVAR_H
|
|
||||||
|
|
||||||
/* Define this to use nghttp2 client. */
|
/* Define this to use nghttp2 client. */
|
||||||
#undef HAVE_NGHTTP2
|
#undef HAVE_NGHTTP2
|
||||||
|
|
||||||
/* Define to 1 if you have the <nghttp2/nghttp2.h> header file. */
|
/* Define to 1 if you have the <nghttp2/nghttp2.h> header file. */
|
||||||
#undef HAVE_NGHTTP2_NGHTTP2_H
|
#undef HAVE_NGHTTP2_NGHTTP2_H
|
||||||
|
|
||||||
/* Define this to use ngtcp2. */
|
|
||||||
#undef HAVE_NGTCP2
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `ngtcp2_ccerr_default' function. */
|
|
||||||
#undef HAVE_NGTCP2_CCERR_DEFAULT
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `ngtcp2_conn_encode_0rtt_transport_params'
|
|
||||||
function. */
|
|
||||||
#undef HAVE_NGTCP2_CONN_ENCODE_0RTT_TRANSPORT_PARAMS
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `ngtcp2_conn_get_max_local_streams_uni'
|
|
||||||
function. */
|
|
||||||
#undef HAVE_NGTCP2_CONN_GET_MAX_LOCAL_STREAMS_UNI
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `ngtcp2_conn_get_num_scid' function. */
|
|
||||||
#undef HAVE_NGTCP2_CONN_GET_NUM_SCID
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `ngtcp2_conn_in_closing_period' function. */
|
|
||||||
#undef HAVE_NGTCP2_CONN_IN_CLOSING_PERIOD
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `ngtcp2_conn_in_draining_period' function. */
|
|
||||||
#undef HAVE_NGTCP2_CONN_IN_DRAINING_PERIOD
|
|
||||||
|
|
||||||
/* Define if ngtcp2_conn_shutdown_stream has 4 arguments. */
|
|
||||||
#undef HAVE_NGTCP2_CONN_SHUTDOWN_STREAM4
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `ngtcp2_conn_tls_early_data_rejected' function.
|
|
||||||
*/
|
|
||||||
#undef HAVE_NGTCP2_CONN_TLS_EARLY_DATA_REJECTED
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `ngtcp2_crypto_encrypt_cb' function. */
|
|
||||||
#undef HAVE_NGTCP2_CRYPTO_ENCRYPT_CB
|
|
||||||
|
|
||||||
/* Define to 1 if you have the
|
|
||||||
`ngtcp2_crypto_quictls_configure_client_context' function. */
|
|
||||||
#undef HAVE_NGTCP2_CRYPTO_QUICTLS_CONFIGURE_CLIENT_CONTEXT
|
|
||||||
|
|
||||||
/* Define to 1 if you have the
|
|
||||||
`ngtcp2_crypto_quictls_configure_server_context' function. */
|
|
||||||
#undef HAVE_NGTCP2_CRYPTO_QUICTLS_CONFIGURE_SERVER_CONTEXT
|
|
||||||
|
|
||||||
/* Define to 1 if you have the
|
|
||||||
`ngtcp2_crypto_quictls_from_ossl_encryption_level' function. */
|
|
||||||
#undef HAVE_NGTCP2_CRYPTO_QUICTLS_FROM_OSSL_ENCRYPTION_LEVEL
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `ngtcp2_crypto_quictls_init' function. */
|
|
||||||
#undef HAVE_NGTCP2_CRYPTO_QUICTLS_INIT
|
|
||||||
|
|
||||||
/* Define to 1 if the system has the type `ngtcp2_encryption_level'. */
|
|
||||||
#undef HAVE_NGTCP2_ENCRYPTION_LEVEL
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <ngtcp2/ngtcp2_crypto_openssl.h> header file.
|
|
||||||
*/
|
|
||||||
#undef HAVE_NGTCP2_NGTCP2_CRYPTO_OPENSSL_H
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <ngtcp2/ngtcp2_crypto_ossl.h> header file. */
|
|
||||||
#undef HAVE_NGTCP2_NGTCP2_CRYPTO_OSSL_H
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <ngtcp2/ngtcp2_crypto_quictls.h> header file.
|
|
||||||
*/
|
|
||||||
#undef HAVE_NGTCP2_NGTCP2_CRYPTO_QUICTLS_H
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <ngtcp2/ngtcp2.h> header file. */
|
|
||||||
#undef HAVE_NGTCP2_NGTCP2_H
|
|
||||||
|
|
||||||
/* Use libnss for crypto */
|
/* Use libnss for crypto */
|
||||||
#undef HAVE_NSS
|
#undef HAVE_NSS
|
||||||
|
|
||||||
@@ -529,9 +418,6 @@
|
|||||||
/* Define to 1 if you have the <openssl/bn.h> header file. */
|
/* Define to 1 if you have the <openssl/bn.h> header file. */
|
||||||
#undef HAVE_OPENSSL_BN_H
|
#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. */
|
/* Define to 1 if you have the `OPENSSL_config' function. */
|
||||||
#undef HAVE_OPENSSL_CONFIG
|
#undef HAVE_OPENSSL_CONFIG
|
||||||
|
|
||||||
@@ -583,27 +469,12 @@
|
|||||||
/* Define if you have POSIX threads libraries and header files. */
|
/* Define if you have POSIX threads libraries and header files. */
|
||||||
#undef HAVE_PTHREAD
|
#undef HAVE_PTHREAD
|
||||||
|
|
||||||
/* Define to 1 if you have the <pthread_np.h> header file. */
|
|
||||||
#undef HAVE_PTHREAD_NP_H
|
|
||||||
|
|
||||||
/* Have PTHREAD_PRIO_INHERIT. */
|
/* Have PTHREAD_PRIO_INHERIT. */
|
||||||
#undef HAVE_PTHREAD_PRIO_INHERIT
|
#undef HAVE_PTHREAD_PRIO_INHERIT
|
||||||
|
|
||||||
/* Define to 1 if the system has the type `pthread_rwlock_t'. */
|
/* Define to 1 if the system has the type `pthread_rwlock_t'. */
|
||||||
#undef HAVE_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'. */
|
/* Define to 1 if the system has the type `pthread_spinlock_t'. */
|
||||||
#undef HAVE_PTHREAD_SPINLOCK_T
|
#undef HAVE_PTHREAD_SPINLOCK_T
|
||||||
|
|
||||||
@@ -701,34 +572,18 @@
|
|||||||
/* Define to 1 if you have the `SSL_get1_peer_certificate' function. */
|
/* Define to 1 if you have the `SSL_get1_peer_certificate' function. */
|
||||||
#undef HAVE_SSL_GET1_PEER_CERTIFICATE
|
#undef HAVE_SSL_GET1_PEER_CERTIFICATE
|
||||||
|
|
||||||
/* Define to 1 if you have the `SSL_is_quic' function. */
|
|
||||||
#undef HAVE_SSL_IS_QUIC
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `SSL_set1_dnsname' function. */
|
|
||||||
#undef HAVE_SSL_SET1_DNSNAME
|
|
||||||
|
|
||||||
/* Define to 1 if you have the `SSL_set1_host' function. */
|
/* Define to 1 if you have the `SSL_set1_host' function. */
|
||||||
#undef HAVE_SSL_SET1_HOST
|
#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. */
|
/* Define to 1 if you have the <stdarg.h> header file. */
|
||||||
#undef HAVE_STDARG_H
|
#undef HAVE_STDARG_H
|
||||||
|
|
||||||
/* Define to 1 if you have the <stdatomic.h> header file. */
|
|
||||||
#undef HAVE_STDATOMIC_H
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <stdbool.h> header file. */
|
/* Define to 1 if you have the <stdbool.h> header file. */
|
||||||
#undef HAVE_STDBOOL_H
|
#undef HAVE_STDBOOL_H
|
||||||
|
|
||||||
/* Define to 1 if you have the <stdint.h> header file. */
|
/* Define to 1 if you have the <stdint.h> header file. */
|
||||||
#undef HAVE_STDINT_H
|
#undef HAVE_STDINT_H
|
||||||
|
|
||||||
/* Define to 1 if you have the <stdio.h> header file. */
|
|
||||||
#undef HAVE_STDIO_H
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <stdlib.h> header file. */
|
/* Define to 1 if you have the <stdlib.h> header file. */
|
||||||
#undef HAVE_STDLIB_H
|
#undef HAVE_STDLIB_H
|
||||||
|
|
||||||
@@ -756,32 +611,9 @@
|
|||||||
/* Define to 1 if `ipi_spec_dst' is a member of `struct in_pktinfo'. */
|
/* Define to 1 if `ipi_spec_dst' is a member of `struct in_pktinfo'. */
|
||||||
#undef HAVE_STRUCT_IN_PKTINFO_IPI_SPEC_DST
|
#undef HAVE_STRUCT_IN_PKTINFO_IPI_SPEC_DST
|
||||||
|
|
||||||
/* Define to 1 if `tokenlen' is a member of `struct ngtcp2_pkt_hd'. */
|
|
||||||
#undef HAVE_STRUCT_NGTCP2_PKT_HD_TOKENLEN
|
|
||||||
|
|
||||||
/* Define to 1 if `max_tx_udp_payload_size' is a member of `struct
|
|
||||||
ngtcp2_settings'. */
|
|
||||||
#undef HAVE_STRUCT_NGTCP2_SETTINGS_MAX_TX_UDP_PAYLOAD_SIZE
|
|
||||||
|
|
||||||
/* Define to 1 if `tokenlen' is a member of `struct ngtcp2_settings'. */
|
|
||||||
#undef HAVE_STRUCT_NGTCP2_SETTINGS_TOKENLEN
|
|
||||||
|
|
||||||
/* Define to 1 if `original_dcid_present' is a member of `struct
|
|
||||||
ngtcp2_transport_params'. */
|
|
||||||
#undef HAVE_STRUCT_NGTCP2_TRANSPORT_PARAMS_ORIGINAL_DCID_PRESENT
|
|
||||||
|
|
||||||
/* Define to 1 if the system has the type `struct ngtcp2_version_cid'. */
|
|
||||||
#undef HAVE_STRUCT_NGTCP2_VERSION_CID
|
|
||||||
|
|
||||||
/* Define to 1 if `sun_len' is a member of `struct sockaddr_un'. */
|
/* Define to 1 if `sun_len' is a member of `struct sockaddr_un'. */
|
||||||
#undef HAVE_STRUCT_SOCKADDR_UN_SUN_LEN
|
#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. */
|
/* Define if you have Swig libraries and header files. */
|
||||||
#undef HAVE_SWIG
|
#undef HAVE_SWIG
|
||||||
|
|
||||||
@@ -854,9 +686,6 @@
|
|||||||
/* Define to 1 if you have the <vfork.h> header file. */
|
/* Define to 1 if you have the <vfork.h> header file. */
|
||||||
#undef HAVE_VFORK_H
|
#undef HAVE_VFORK_H
|
||||||
|
|
||||||
/* Define to 1 if you have the <wchar.h> header file. */
|
|
||||||
#undef HAVE_WCHAR_H
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <windows.h> header file. */
|
/* Define to 1 if you have the <windows.h> header file. */
|
||||||
#undef HAVE_WINDOWS_H
|
#undef HAVE_WINDOWS_H
|
||||||
|
|
||||||
@@ -878,12 +707,6 @@
|
|||||||
/* Define to 1 if you have the <ws2tcpip.h> header file. */
|
/* Define to 1 if you have the <ws2tcpip.h> header file. */
|
||||||
#undef HAVE_WS2TCPIP_H
|
#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. */
|
/* Define to 1 if you have the `X509_VERIFY_PARAM_set1_host' function. */
|
||||||
#undef HAVE_X509_VERIFY_PARAM_SET1_HOST
|
#undef HAVE_X509_VERIFY_PARAM_SET1_HOST
|
||||||
|
|
||||||
@@ -1004,9 +827,7 @@
|
|||||||
/* Define to 1 if libsodium supports sodium_set_misuse_handler */
|
/* Define to 1 if libsodium supports sodium_set_misuse_handler */
|
||||||
#undef SODIUM_MISUSE_HANDLER
|
#undef SODIUM_MISUSE_HANDLER
|
||||||
|
|
||||||
/* Define to 1 if all of the C90 standard headers exist (not just the ones
|
/* Define to 1 if you have the ANSI C header files. */
|
||||||
required in a freestanding environment). This macro is provided for
|
|
||||||
backward compatibility; new code need not use it. */
|
|
||||||
#undef STDC_HEADERS
|
#undef STDC_HEADERS
|
||||||
|
|
||||||
/* use default strptime. */
|
/* use default strptime. */
|
||||||
@@ -1086,9 +907,6 @@
|
|||||||
/* Define this to enable client TCP Fast Open. */
|
/* Define this to enable client TCP Fast Open. */
|
||||||
#undef USE_MSG_FASTOPEN
|
#undef USE_MSG_FASTOPEN
|
||||||
|
|
||||||
/* Define this to use ngtcp2_crypto_ossl. */
|
|
||||||
#undef USE_NGTCP2_CRYPTO_OSSL
|
|
||||||
|
|
||||||
/* Define this to enable client TCP Fast Open. */
|
/* Define this to enable client TCP Fast Open. */
|
||||||
#undef USE_OSX_MSG_FASTOPEN
|
#undef USE_OSX_MSG_FASTOPEN
|
||||||
|
|
||||||
@@ -1105,87 +923,21 @@
|
|||||||
#ifndef _ALL_SOURCE
|
#ifndef _ALL_SOURCE
|
||||||
# undef _ALL_SOURCE
|
# undef _ALL_SOURCE
|
||||||
#endif
|
#endif
|
||||||
/* Enable general extensions on macOS. */
|
|
||||||
#ifndef _DARWIN_C_SOURCE
|
|
||||||
# undef _DARWIN_C_SOURCE
|
|
||||||
#endif
|
|
||||||
/* Enable general extensions on Solaris. */
|
|
||||||
#ifndef __EXTENSIONS__
|
|
||||||
# undef __EXTENSIONS__
|
|
||||||
#endif
|
|
||||||
/* Enable GNU extensions on systems that have them. */
|
/* Enable GNU extensions on systems that have them. */
|
||||||
#ifndef _GNU_SOURCE
|
#ifndef _GNU_SOURCE
|
||||||
# undef _GNU_SOURCE
|
# undef _GNU_SOURCE
|
||||||
#endif
|
#endif
|
||||||
/* Enable X/Open compliant socket functions that do not require linking
|
/* Enable threading extensions on Solaris. */
|
||||||
with -lxnet on HP-UX 11.11. */
|
|
||||||
#ifndef _HPUX_ALT_XOPEN_SOCKET_API
|
|
||||||
# undef _HPUX_ALT_XOPEN_SOCKET_API
|
|
||||||
#endif
|
|
||||||
/* Identify the host operating system as Minix.
|
|
||||||
This macro does not affect the system headers' behavior.
|
|
||||||
A future release of Autoconf may stop defining this macro. */
|
|
||||||
#ifndef _MINIX
|
|
||||||
# undef _MINIX
|
|
||||||
#endif
|
|
||||||
/* Enable general extensions on NetBSD.
|
|
||||||
Enable NetBSD compatibility extensions on Minix. */
|
|
||||||
#ifndef _NETBSD_SOURCE
|
|
||||||
# undef _NETBSD_SOURCE
|
|
||||||
#endif
|
|
||||||
/* Enable OpenBSD compatibility extensions on NetBSD.
|
|
||||||
Oddly enough, this does nothing on OpenBSD. */
|
|
||||||
#ifndef _OPENBSD_SOURCE
|
|
||||||
# undef _OPENBSD_SOURCE
|
|
||||||
#endif
|
|
||||||
/* Define to 1 if needed for POSIX-compatible behavior. */
|
|
||||||
#ifndef _POSIX_SOURCE
|
|
||||||
# undef _POSIX_SOURCE
|
|
||||||
#endif
|
|
||||||
/* Define to 2 if needed for POSIX-compatible behavior. */
|
|
||||||
#ifndef _POSIX_1_SOURCE
|
|
||||||
# undef _POSIX_1_SOURCE
|
|
||||||
#endif
|
|
||||||
/* Enable POSIX-compatible threading on Solaris. */
|
|
||||||
#ifndef _POSIX_PTHREAD_SEMANTICS
|
#ifndef _POSIX_PTHREAD_SEMANTICS
|
||||||
# undef _POSIX_PTHREAD_SEMANTICS
|
# undef _POSIX_PTHREAD_SEMANTICS
|
||||||
#endif
|
#endif
|
||||||
/* Enable extensions specified by ISO/IEC TS 18661-5:2014. */
|
|
||||||
#ifndef __STDC_WANT_IEC_60559_ATTRIBS_EXT__
|
|
||||||
# undef __STDC_WANT_IEC_60559_ATTRIBS_EXT__
|
|
||||||
#endif
|
|
||||||
/* Enable extensions specified by ISO/IEC TS 18661-1:2014. */
|
|
||||||
#ifndef __STDC_WANT_IEC_60559_BFP_EXT__
|
|
||||||
# undef __STDC_WANT_IEC_60559_BFP_EXT__
|
|
||||||
#endif
|
|
||||||
/* Enable extensions specified by ISO/IEC TS 18661-2:2015. */
|
|
||||||
#ifndef __STDC_WANT_IEC_60559_DFP_EXT__
|
|
||||||
# undef __STDC_WANT_IEC_60559_DFP_EXT__
|
|
||||||
#endif
|
|
||||||
/* Enable extensions specified by ISO/IEC TS 18661-4:2015. */
|
|
||||||
#ifndef __STDC_WANT_IEC_60559_FUNCS_EXT__
|
|
||||||
# undef __STDC_WANT_IEC_60559_FUNCS_EXT__
|
|
||||||
#endif
|
|
||||||
/* Enable extensions specified by ISO/IEC TS 18661-3:2015. */
|
|
||||||
#ifndef __STDC_WANT_IEC_60559_TYPES_EXT__
|
|
||||||
# undef __STDC_WANT_IEC_60559_TYPES_EXT__
|
|
||||||
#endif
|
|
||||||
/* Enable extensions specified by ISO/IEC TR 24731-2:2010. */
|
|
||||||
#ifndef __STDC_WANT_LIB_EXT2__
|
|
||||||
# undef __STDC_WANT_LIB_EXT2__
|
|
||||||
#endif
|
|
||||||
/* Enable extensions specified by ISO/IEC 24747:2009. */
|
|
||||||
#ifndef __STDC_WANT_MATH_SPEC_FUNCS__
|
|
||||||
# undef __STDC_WANT_MATH_SPEC_FUNCS__
|
|
||||||
#endif
|
|
||||||
/* Enable extensions on HP NonStop. */
|
/* Enable extensions on HP NonStop. */
|
||||||
#ifndef _TANDEM_SOURCE
|
#ifndef _TANDEM_SOURCE
|
||||||
# undef _TANDEM_SOURCE
|
# undef _TANDEM_SOURCE
|
||||||
#endif
|
#endif
|
||||||
/* Enable X/Open extensions. Define to 500 only if necessary
|
/* Enable general extensions on Solaris. */
|
||||||
to make mbstate_t available. */
|
#ifndef __EXTENSIONS__
|
||||||
#ifndef _XOPEN_SOURCE
|
# undef __EXTENSIONS__
|
||||||
# undef _XOPEN_SOURCE
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
@@ -1211,6 +963,11 @@
|
|||||||
`char[]'. */
|
`char[]'. */
|
||||||
#undef YYTEXT_POINTER
|
#undef YYTEXT_POINTER
|
||||||
|
|
||||||
|
/* Enable large inode numbers on Mac OS X 10.5. */
|
||||||
|
#ifndef _DARWIN_USE_64_BIT_INODE
|
||||||
|
# define _DARWIN_USE_64_BIT_INODE 1
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Number of bits in a file offset, on hosts where this is settable. */
|
/* Number of bits in a file offset, on hosts where this is settable. */
|
||||||
#undef _FILE_OFFSET_BITS
|
#undef _FILE_OFFSET_BITS
|
||||||
|
|
||||||
@@ -1220,9 +977,19 @@
|
|||||||
/* Define for large files, on AIX-style hosts. */
|
/* Define for large files, on AIX-style hosts. */
|
||||||
#undef _LARGE_FILES
|
#undef _LARGE_FILES
|
||||||
|
|
||||||
|
/* Define to 1 if on MINIX. */
|
||||||
|
#undef _MINIX
|
||||||
|
|
||||||
/* Enable for compile on Minix */
|
/* Enable for compile on Minix */
|
||||||
#undef _NETBSD_SOURCE
|
#undef _NETBSD_SOURCE
|
||||||
|
|
||||||
|
/* Define to 2 if the system does not provide POSIX.1 features except with
|
||||||
|
this defined. */
|
||||||
|
#undef _POSIX_1_SOURCE
|
||||||
|
|
||||||
|
/* Define to 1 if you need to in order for `stat' and other things to work. */
|
||||||
|
#undef _POSIX_SOURCE
|
||||||
|
|
||||||
/* defined to use gcc ansi snprintf and sscanf that understands %lld when
|
/* defined to use gcc ansi snprintf and sscanf that understands %lld when
|
||||||
compiled for windows. */
|
compiled for windows. */
|
||||||
#undef __USE_MINGW_ANSI_STDIO
|
#undef __USE_MINGW_ANSI_STDIO
|
||||||
@@ -1263,7 +1030,7 @@
|
|||||||
/* Define to `long int' if <sys/types.h> does not define. */
|
/* Define to `long int' if <sys/types.h> does not define. */
|
||||||
#undef off_t
|
#undef off_t
|
||||||
|
|
||||||
/* Define as a signed integer type capable of holding a process identifier. */
|
/* Define to `int' if <sys/types.h> does not define. */
|
||||||
#undef pid_t
|
#undef pid_t
|
||||||
|
|
||||||
/* Define to 'int' if not defined */
|
/* Define to 'int' if not defined */
|
||||||
@@ -1437,17 +1204,6 @@
|
|||||||
#endif /* !HAVE_ATTR_UNUSED */
|
#endif /* !HAVE_ATTR_UNUSED */
|
||||||
|
|
||||||
|
|
||||||
#if defined(DOXYGEN)
|
|
||||||
# define ATTR_NONSTRING(x) x
|
|
||||||
#elif defined(__cplusplus)
|
|
||||||
# define ATTR_NONSTRING(x) __attribute__((nonstring)) x
|
|
||||||
#elif defined(HAVE_ATTR_NONSTRING)
|
|
||||||
# define ATTR_NONSTRING(x) __attribute__((nonstring)) x
|
|
||||||
#else /* !HAVE_ATTR_NONSTRING */
|
|
||||||
# define ATTR_NONSTRING(x) x
|
|
||||||
#endif /* !HAVE_ATTR_NONSTRING */
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef HAVE_FSEEKO
|
#ifndef HAVE_FSEEKO
|
||||||
#define fseeko fseek
|
#define fseeko fseek
|
||||||
#define ftello ftell
|
#define ftello ftell
|
||||||
@@ -1666,10 +1422,6 @@ struct sockaddr_storage;
|
|||||||
# define calloc(n,s) unbound_stat_calloc_log(n, s, __FILE__, __LINE__, __func__)
|
# define calloc(n,s) unbound_stat_calloc_log(n, s, __FILE__, __LINE__, __func__)
|
||||||
# define free(p) unbound_stat_free_log(p, __FILE__, __LINE__, __func__)
|
# define free(p) unbound_stat_free_log(p, __FILE__, __LINE__, __func__)
|
||||||
# define realloc(p,s) unbound_stat_realloc_log(p, s, __FILE__, __LINE__, __func__)
|
# define realloc(p,s) unbound_stat_realloc_log(p, s, __FILE__, __LINE__, __func__)
|
||||||
# define strdup(s) unbound_stat_strdup_log(s, __FILE__, __LINE__, __func__)
|
|
||||||
#ifdef HAVE_REALLOCARRAY
|
|
||||||
# define reallocarray(p,n,s) unbound_stat_reallocarray_log(p, n, s, __FILE__, __LINE__, __func__)
|
|
||||||
#endif
|
|
||||||
void *unbound_stat_malloc(size_t size);
|
void *unbound_stat_malloc(size_t size);
|
||||||
void *unbound_stat_calloc(size_t nmemb, size_t size);
|
void *unbound_stat_calloc(size_t nmemb, size_t size);
|
||||||
void unbound_stat_free(void *ptr);
|
void unbound_stat_free(void *ptr);
|
||||||
@@ -1682,10 +1434,6 @@ void unbound_stat_free_log(void *ptr, const char* file, int line,
|
|||||||
const char* func);
|
const char* func);
|
||||||
void *unbound_stat_realloc_log(void *ptr, size_t size, const char* file,
|
void *unbound_stat_realloc_log(void *ptr, size_t size, const char* file,
|
||||||
int line, const char* func);
|
int line, const char* func);
|
||||||
void *unbound_stat_reallocarray_log(void *ptr, size_t nmemb, size_t size,
|
|
||||||
const char* file, int line, const char* func);
|
|
||||||
char *unbound_stat_strdup_log(const char *s, const char* file, int line,
|
|
||||||
const char* func);
|
|
||||||
#elif defined(UNBOUND_ALLOC_LITE)
|
#elif defined(UNBOUND_ALLOC_LITE)
|
||||||
# include "util/alloc.h"
|
# include "util/alloc.h"
|
||||||
#endif /* UNBOUND_ALLOC_LITE and UNBOUND_ALLOC_STATS */
|
#endif /* UNBOUND_ALLOC_LITE and UNBOUND_ALLOC_STATS */
|
||||||
@@ -1696,8 +1444,6 @@ char *unbound_stat_strdup_log(const char *s, const char* file, int line,
|
|||||||
#define UNBOUND_DNS_OVER_TLS_PORT 853
|
#define UNBOUND_DNS_OVER_TLS_PORT 853
|
||||||
/** default port for DNS over HTTPS traffic. */
|
/** default port for DNS over HTTPS traffic. */
|
||||||
#define UNBOUND_DNS_OVER_HTTPS_PORT 443
|
#define UNBOUND_DNS_OVER_HTTPS_PORT 443
|
||||||
/** default port for DNS over QUIC traffic. */
|
|
||||||
#define UNBOUND_DNS_OVER_QUIC_PORT 853
|
|
||||||
/** default port for unbound control traffic, registered port with IANA,
|
/** default port for unbound control traffic, registered port with IANA,
|
||||||
ub-dns-control 8953/tcp unbound dns nameserver control */
|
ub-dns-control 8953/tcp unbound dns nameserver control */
|
||||||
#define UNBOUND_CONTROL_PORT 8953
|
#define UNBOUND_CONTROL_PORT 8953
|
||||||
|
|||||||
Vendored
+325
-503
File diff suppressed because it is too large
Load Diff
+45
-378
@@ -2,24 +2,23 @@
|
|||||||
# Process this file with autoconf to produce a configure script.
|
# Process this file with autoconf to produce a configure script.
|
||||||
AC_PREREQ([2.56])
|
AC_PREREQ([2.56])
|
||||||
sinclude(acx_nlnetlabs.m4)
|
sinclude(acx_nlnetlabs.m4)
|
||||||
sinclude(ax_build_date_epoch.m4)
|
|
||||||
sinclude(ax_pthread.m4)
|
sinclude(ax_pthread.m4)
|
||||||
sinclude(acx_python.m4)
|
sinclude(acx_python.m4)
|
||||||
sinclude(ax_pkg_swig.m4)
|
sinclude(ac_pkg_swig.m4)
|
||||||
sinclude(dnstap/dnstap.m4)
|
sinclude(dnstap/dnstap.m4)
|
||||||
sinclude(dnscrypt/dnscrypt.m4)
|
sinclude(dnscrypt/dnscrypt.m4)
|
||||||
|
|
||||||
# must be numbers. ac_defun because of later processing
|
# must be numbers. ac_defun because of later processing
|
||||||
m4_define([VERSION_MAJOR],[1])
|
m4_define([VERSION_MAJOR],[1])
|
||||||
m4_define([VERSION_MINOR],[26])
|
m4_define([VERSION_MINOR],[17])
|
||||||
m4_define([VERSION_MICRO],[2])
|
m4_define([VERSION_MICRO],[1])
|
||||||
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_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_MAJOR, [VERSION_MAJOR])
|
||||||
AC_SUBST(UNBOUND_VERSION_MINOR, [VERSION_MINOR])
|
AC_SUBST(UNBOUND_VERSION_MINOR, [VERSION_MINOR])
|
||||||
AC_SUBST(UNBOUND_VERSION_MICRO, [VERSION_MICRO])
|
AC_SUBST(UNBOUND_VERSION_MICRO, [VERSION_MICRO])
|
||||||
|
|
||||||
LIBUNBOUND_CURRENT=9
|
LIBUNBOUND_CURRENT=9
|
||||||
LIBUNBOUND_REVISION=41
|
LIBUNBOUND_REVISION=21
|
||||||
LIBUNBOUND_AGE=1
|
LIBUNBOUND_AGE=1
|
||||||
# 1.0.0 had 0:12:0
|
# 1.0.0 had 0:12:0
|
||||||
# 1.0.1 had 0:13:0
|
# 1.0.1 had 0:13:0
|
||||||
@@ -108,26 +107,6 @@ LIBUNBOUND_AGE=1
|
|||||||
# 1.16.3 had 9:19:1
|
# 1.16.3 had 9:19:1
|
||||||
# 1.17.0 had 9:20:1
|
# 1.17.0 had 9:20:1
|
||||||
# 1.17.1 had 9:21:1
|
# 1.17.1 had 9:21:1
|
||||||
# 1.18.0 had 9:22:1
|
|
||||||
# 1.19.0 had 9:23:1
|
|
||||||
# 1.19.1 had 9:24:1
|
|
||||||
# 1.19.2 had 9:25:1
|
|
||||||
# 1.19.3 had 9:26:1
|
|
||||||
# 1.20.0 had 9:27:1
|
|
||||||
# 1.21.0 had 9:28:1
|
|
||||||
# 1.21.1 had 9:29:1
|
|
||||||
# 1.22.0 had 9:30:1
|
|
||||||
# 1.23.0 had 9:31:1
|
|
||||||
# 1.23.1 had 9:32: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
|
|
||||||
# 1.26.2 had 9:41:1
|
|
||||||
|
|
||||||
# Current -- the number of the binary API that we're implementing
|
# Current -- the number of the binary API that we're implementing
|
||||||
# Revision -- which iteration of the implementation of the binary
|
# Revision -- which iteration of the implementation of the binary
|
||||||
@@ -289,9 +268,6 @@ AC_DEFINE(WINVER, 0x0502, [the version of the windows API enabled])
|
|||||||
ACX_RSRC_VERSION(wnvs)
|
ACX_RSRC_VERSION(wnvs)
|
||||||
AC_DEFINE_UNQUOTED(RSRC_PACKAGE_VERSION, [$wnvs], [version number for resource files])
|
AC_DEFINE_UNQUOTED(RSRC_PACKAGE_VERSION, [$wnvs], [version number for resource files])
|
||||||
|
|
||||||
# Check for 'grep -e' program, here, since ACX_CHECK_FLTO needs that.
|
|
||||||
AC_PROG_GREP
|
|
||||||
|
|
||||||
# Checks for typedefs, structures, and compiler characteristics.
|
# Checks for typedefs, structures, and compiler characteristics.
|
||||||
AC_C_CONST
|
AC_C_CONST
|
||||||
AC_LANG([C])
|
AC_LANG([C])
|
||||||
@@ -302,7 +278,7 @@ ACX_CHECK_COMPILER_FLAG(g, [CFLAGS="$CFLAGS -g"])
|
|||||||
ACX_CHECK_COMPILER_FLAG(O2, [CFLAGS="$CFLAGS -O2"])
|
ACX_CHECK_COMPILER_FLAG(O2, [CFLAGS="$CFLAGS -O2"])
|
||||||
default_cflags=yes
|
default_cflags=yes
|
||||||
fi
|
fi
|
||||||
m4_version_prereq([2.70], [AC_PROG_CC], [AC_PROG_CC_STDC])
|
AC_PROG_CC
|
||||||
ACX_DEPFLAG
|
ACX_DEPFLAG
|
||||||
ACX_DETERMINE_EXT_FLAGS_UNBOUND
|
ACX_DETERMINE_EXT_FLAGS_UNBOUND
|
||||||
|
|
||||||
@@ -336,7 +312,6 @@ fi
|
|||||||
AC_C_INLINE
|
AC_C_INLINE
|
||||||
ACX_CHECK_FORMAT_ATTRIBUTE
|
ACX_CHECK_FORMAT_ATTRIBUTE
|
||||||
ACX_CHECK_UNUSED_ATTRIBUTE
|
ACX_CHECK_UNUSED_ATTRIBUTE
|
||||||
ACX_CHECK_NONSTRING_ATTRIBUTE
|
|
||||||
|
|
||||||
AC_DEFUN([CHECK_WEAK_ATTRIBUTE],
|
AC_DEFUN([CHECK_WEAK_ATTRIBUTE],
|
||||||
[AC_REQUIRE([AC_PROG_CC])
|
[AC_REQUIRE([AC_PROG_CC])
|
||||||
@@ -354,8 +329,6 @@ AC_MSG_RESULT($ac_cv_c_weak_attribute)
|
|||||||
if test $ac_cv_c_weak_attribute = yes; then
|
if test $ac_cv_c_weak_attribute = yes; then
|
||||||
AC_DEFINE(HAVE_ATTR_WEAK, 1, [Whether the C compiler accepts the "weak" attribute])
|
AC_DEFINE(HAVE_ATTR_WEAK, 1, [Whether the C compiler accepts the "weak" attribute])
|
||||||
AC_DEFINE(ATTR_WEAK, [__attribute__((weak))], [apply the weak attribute to a symbol])
|
AC_DEFINE(ATTR_WEAK, [__attribute__((weak))], [apply the weak attribute to a symbol])
|
||||||
else
|
|
||||||
AC_DEFINE(ATTR_WEAK,[], [apply the weak attribute to a symbol])
|
|
||||||
fi
|
fi
|
||||||
])dnl End of CHECK_WEAK_ATTRIBUTE
|
])dnl End of CHECK_WEAK_ATTRIBUTE
|
||||||
|
|
||||||
@@ -367,14 +340,7 @@ AC_MSG_CHECKING(whether the C compiler (${CC-cc}) accepts the "noreturn" attribu
|
|||||||
AC_CACHE_VAL(ac_cv_c_noreturn_attribute,
|
AC_CACHE_VAL(ac_cv_c_noreturn_attribute,
|
||||||
[ac_cv_c_noreturn_attribute=no
|
[ac_cv_c_noreturn_attribute=no
|
||||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include <stdio.h>
|
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include <stdio.h>
|
||||||
#ifdef STDC_HEADERS
|
__attribute__((noreturn)) void f(int x) { printf("%d", x); }
|
||||||
# include <stdlib.h>
|
|
||||||
#else
|
|
||||||
# ifdef HAVE_STDLIB_H
|
|
||||||
# include <stdlib.h>
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
__attribute__((noreturn)) void f(int x) { printf("%d", x); exit(1); }
|
|
||||||
]], [[
|
]], [[
|
||||||
f(1);
|
f(1);
|
||||||
]])],[ac_cv_c_noreturn_attribute="yes"],[ac_cv_c_noreturn_attribute="no"])
|
]])],[ac_cv_c_noreturn_attribute="yes"],[ac_cv_c_noreturn_attribute="no"])
|
||||||
@@ -384,54 +350,11 @@ AC_MSG_RESULT($ac_cv_c_noreturn_attribute)
|
|||||||
if test $ac_cv_c_noreturn_attribute = yes; then
|
if test $ac_cv_c_noreturn_attribute = yes; then
|
||||||
AC_DEFINE(HAVE_ATTR_NORETURN, 1, [Whether the C compiler accepts the "noreturn" attribute])
|
AC_DEFINE(HAVE_ATTR_NORETURN, 1, [Whether the C compiler accepts the "noreturn" attribute])
|
||||||
AC_DEFINE(ATTR_NORETURN, [__attribute__((__noreturn__))], [apply the noreturn attribute to a function that exits the program])
|
AC_DEFINE(ATTR_NORETURN, [__attribute__((__noreturn__))], [apply the noreturn attribute to a function that exits the program])
|
||||||
else
|
|
||||||
AC_DEFINE(ATTR_NORETURN,[], [apply the noreturn attribute to a function that exits the program])
|
|
||||||
fi
|
fi
|
||||||
])dnl End of CHECK_NORETURN_ATTRIBUTE
|
])dnl End of CHECK_NORETURN_ATTRIBUTE
|
||||||
|
|
||||||
CHECK_NORETURN_ATTRIBUTE
|
CHECK_NORETURN_ATTRIBUTE
|
||||||
|
|
||||||
AC_DEFUN([CHECK_FALLTHROUGH_ATTRIBUTE],
|
|
||||||
[AC_REQUIRE([AC_PROG_CC])
|
|
||||||
AC_MSG_CHECKING(whether the C compiler (${CC-cc}) accepts the "fallthrough" attribute)
|
|
||||||
BAKCFLAGS="$CFLAGS"
|
|
||||||
CFLAGS="$CFLAGS -Werror"
|
|
||||||
AC_CACHE_VAL(ac_cv_c_fallthrough_attribute,
|
|
||||||
[ac_cv_c_fallthrough_attribute=no
|
|
||||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include <stdio.h>
|
|
||||||
void f(int x) {
|
|
||||||
int y = 0;
|
|
||||||
switch(x) {
|
|
||||||
case 1:
|
|
||||||
y = 1;
|
|
||||||
__attribute__((fallthrough));
|
|
||||||
/* fallthrough */
|
|
||||||
case 2:
|
|
||||||
y++;
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
y = 3;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
printf("%d", y);
|
|
||||||
}
|
|
||||||
]], [[
|
|
||||||
f(1);
|
|
||||||
]])],[ac_cv_c_fallthrough_attribute="yes"],[ac_cv_c_fallthrough_attribute="no"])
|
|
||||||
])
|
|
||||||
CFLAGS="$BAKCFLAGS"
|
|
||||||
|
|
||||||
AC_MSG_RESULT($ac_cv_c_fallthrough_attribute)
|
|
||||||
if test $ac_cv_c_fallthrough_attribute = yes; then
|
|
||||||
AC_DEFINE(HAVE_ATTR_FALLTHROUGH, 1, [Whether the C compiler accepts the "fallthrough" attribute])
|
|
||||||
AC_DEFINE(ATTR_FALLTHROUGH, [__attribute__((fallthrough));], [apply the fallthrough attribute.])
|
|
||||||
else
|
|
||||||
AC_DEFINE(ATTR_FALLTHROUGH,[], [apply the fallthrough attribute.])
|
|
||||||
fi
|
|
||||||
])dnl End of CHECK_FALLTHROUGH_ATTRIBUTE
|
|
||||||
|
|
||||||
CHECK_FALLTHROUGH_ATTRIBUTE
|
|
||||||
|
|
||||||
if test "$srcdir" != "."; then
|
if test "$srcdir" != "."; then
|
||||||
CPPFLAGS="$CPPFLAGS -I$srcdir"
|
CPPFLAGS="$CPPFLAGS -I$srcdir"
|
||||||
fi
|
fi
|
||||||
@@ -465,28 +388,18 @@ fi
|
|||||||
if test "$LEX" != "" -a "$LEX" != ":"; then
|
if test "$LEX" != "" -a "$LEX" != ":"; then
|
||||||
ACX_YYLEX_OPTION
|
ACX_YYLEX_OPTION
|
||||||
fi
|
fi
|
||||||
if test "$LEX" = "" -o "$LEX" = ":"; then
|
|
||||||
if test ! -f util/configlexer.c; then
|
|
||||||
AC_MSG_ERROR([no lex and no util/configlexer.c: need flex and bison to compile from source repository.])
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
AC_PROG_YACC
|
AC_PROG_YACC
|
||||||
if test "$YACC" = "" -o "$YACC" = ":"; then
|
|
||||||
if test ! -f util/configparser.c; then
|
|
||||||
AC_MSG_ERROR([no yacc and no util/configparser.c: need flex and bison to compile from source repository.])
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
AC_CHECK_PROG(doxygen, doxygen, doxygen)
|
AC_CHECK_PROG(doxygen, doxygen, doxygen)
|
||||||
AC_CHECK_TOOL(STRIP, strip)
|
AC_CHECK_TOOL(STRIP, strip)
|
||||||
ACX_LIBTOOL_C_ONLY
|
ACX_LIBTOOL_C_ONLY
|
||||||
|
|
||||||
# pkg-config is only needed for these options, do not require it otherwise
|
# pkg-config is only needed for these options, do not require it otherwise
|
||||||
if test "$enable_systemd" = "yes" -o "$enable_dnstap" = "yes" -o "$with_pyunbound" = "yes" -o "$with_pythonmod" = "yes"; then
|
if test "$enable_systemd" = "yes" -o "$with_pyunbound" = "yes" -o "$with_pythonmod" = "yes"; then
|
||||||
PKG_PROG_PKG_CONFIG
|
PKG_PROG_PKG_CONFIG
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Checks for header files.
|
# 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:
|
# net/if.h portability for Darwin see:
|
||||||
# https://www.gnu.org/software/autoconf/manual/autoconf-2.69/html_node/Header-Portability.html
|
# https://www.gnu.org/software/autoconf/manual/autoconf-2.69/html_node/Header-Portability.html
|
||||||
AC_CHECK_HEADERS([net/if.h],,, [
|
AC_CHECK_HEADERS([net/if.h],,, [
|
||||||
@@ -540,10 +453,6 @@ AC_CHECK_HEADERS([netioapi.h],,, [AC_INCLUDES_DEFAULT
|
|||||||
#endif
|
#endif
|
||||||
])
|
])
|
||||||
|
|
||||||
# Check for Linux timestamping headers
|
|
||||||
AC_CHECK_HEADERS([linux/net_tstamp.h],,, [AC_INCLUDES_DEFAULT])
|
|
||||||
AC_CHECK_HEADERS([stdatomic.h],,, [AC_INCLUDES_DEFAULT])
|
|
||||||
|
|
||||||
# check for types.
|
# check for types.
|
||||||
# Using own tests for int64* because autoconf builtin only give 32bit.
|
# Using own tests for int64* because autoconf builtin only give 32bit.
|
||||||
AC_CHECK_TYPE(int8_t, signed char)
|
AC_CHECK_TYPE(int8_t, signed char)
|
||||||
@@ -602,8 +511,7 @@ res = strptime("2010-07-15T00:00:00+00:00", "%t%Y%t-%t%m%t-%t%d%tT%t%H%t:%t%M%t:
|
|||||||
if (!res) return 2;
|
if (!res) return 2;
|
||||||
res = strptime("20070207111842", "%Y%m%d%H%M%S", &tm);
|
res = strptime("20070207111842", "%Y%m%d%H%M%S", &tm);
|
||||||
if (!res) return 1; return 0; }
|
if (!res) return 1; return 0; }
|
||||||
]])] , [eval "ac_cv_c_strptime_works=yes"], [eval "ac_cv_c_strptime_works=no"],
|
]])] , [eval "ac_cv_c_strptime_works=yes"], [eval "ac_cv_c_strptime_works=no"])
|
||||||
[eval "ac_cv_c_strptime_works=maybe"])
|
|
||||||
else
|
else
|
||||||
eval "ac_cv_c_strptime_works=maybe"
|
eval "ac_cv_c_strptime_works=maybe"
|
||||||
fi
|
fi
|
||||||
@@ -649,19 +557,19 @@ AC_ARG_ENABLE(alloc-nonregional, AS_HELP_STRING([--enable-alloc-nonregional],[ e
|
|||||||
if test x_$enable_alloc_nonregional = x_yes; then
|
if test x_$enable_alloc_nonregional = x_yes; then
|
||||||
AC_DEFINE(UNBOUND_ALLOC_NONREGIONAL, 1, [use malloc not regions, for debug use])
|
AC_DEFINE(UNBOUND_ALLOC_NONREGIONAL, 1, [use malloc not regions, for debug use])
|
||||||
fi
|
fi
|
||||||
AS_IF([test x_$enable_alloc_checks = x_yes],[
|
if test x_$enable_alloc_checks = x_yes; then
|
||||||
AC_DEFINE(UNBOUND_ALLOC_STATS, 1, [use statistics for allocs and frees, for debug use])
|
AC_DEFINE(UNBOUND_ALLOC_STATS, 1, [use statistics for allocs and frees, for debug use])
|
||||||
SLDNS_ALLOCCHECK_EXTRA_OBJ="alloc.lo log.lo"
|
SLDNS_ALLOCCHECK_EXTRA_OBJ="alloc.lo log.lo"
|
||||||
AC_SUBST(SLDNS_ALLOCCHECK_EXTRA_OBJ)
|
AC_SUBST(SLDNS_ALLOCCHECK_EXTRA_OBJ)
|
||||||
ASYNCLOOK_ALLOCCHECK_EXTRA_OBJ="alloc.lo"
|
ASYNCLOOK_ALLOCCHECK_EXTRA_OBJ="alloc.lo"
|
||||||
AC_SUBST(ASYNCLOOK_ALLOCCHECK_EXTRA_OBJ)
|
AC_SUBST(ASYNCLOOK_ALLOCCHECK_EXTRA_OBJ)
|
||||||
],[
|
else
|
||||||
AS_IF([test x_$enable_alloc_lite = x_yes],[
|
if test x_$enable_alloc_lite = x_yes; then
|
||||||
AC_DEFINE(UNBOUND_ALLOC_LITE, 1, [use to enable lightweight alloc assertions, for debug use])
|
AC_DEFINE(UNBOUND_ALLOC_LITE, 1, [use to enable lightweight alloc assertions, for debug use])
|
||||||
],[
|
else
|
||||||
ACX_FUNC_MALLOC([unbound])
|
ACX_FUNC_MALLOC([unbound])
|
||||||
])
|
fi
|
||||||
])
|
fi
|
||||||
|
|
||||||
# check windows threads (we use them, not pthreads, on windows).
|
# check windows threads (we use them, not pthreads, on windows).
|
||||||
if test "$on_mingw" = "yes"; then
|
if test "$on_mingw" = "yes"; then
|
||||||
@@ -736,76 +644,6 @@ int main(void) {return 0;}
|
|||||||
])
|
])
|
||||||
fi
|
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
|
# check solaris thread library
|
||||||
AC_ARG_WITH(solaris-threads, AS_HELP_STRING([--with-solaris-threads],[use solaris native thread library.]), [ ],[ withval="no" ])
|
AC_ARG_WITH(solaris-threads, AS_HELP_STRING([--with-solaris-threads],[use solaris native thread library.]), [ ],[ withval="no" ])
|
||||||
ub_have_sol_threads=no
|
ub_have_sol_threads=no
|
||||||
@@ -896,14 +734,7 @@ if test x_$ub_test_python != x_no; then
|
|||||||
ac_save_LIBS="$LIBS" dnl otherwise AC_PYTHON_DEVEL thrashes $LIBS
|
ac_save_LIBS="$LIBS" dnl otherwise AC_PYTHON_DEVEL thrashes $LIBS
|
||||||
AC_PYTHON_DEVEL
|
AC_PYTHON_DEVEL
|
||||||
if test ! -z "$PYTHON_VERSION"; then
|
if test ! -z "$PYTHON_VERSION"; then
|
||||||
badversion="no"
|
if test `$PYTHON -c "print('$PYTHON_VERSION' >= '2.4.0')"` = "False"; then
|
||||||
if test "$PYTHON_VERSION_MAJOR" -lt 2; then
|
|
||||||
badversion="yes"
|
|
||||||
fi
|
|
||||||
if test "$PYTHON_VERSION_MAJOR" -eq 2 -a "$PYTHON_VERSION_MINOR" -lt 4; then
|
|
||||||
badversion="yes"
|
|
||||||
fi
|
|
||||||
if test "$badversion" = "yes"; then
|
|
||||||
AC_MSG_ERROR([Python version >= 2.4.0 is required])
|
AC_MSG_ERROR([Python version >= 2.4.0 is required])
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -938,9 +769,9 @@ if test x_$ub_test_python != x_no; then
|
|||||||
ub_have_swig=no
|
ub_have_swig=no
|
||||||
AC_ARG_ENABLE(swig-version-check, AS_HELP_STRING([--disable-swig-version-check],[Disable swig version check to build python modules with older swig even though that is unreliable]))
|
AC_ARG_ENABLE(swig-version-check, AS_HELP_STRING([--disable-swig-version-check],[Disable swig version check to build python modules with older swig even though that is unreliable]))
|
||||||
if test "$enable_swig_version_check" = "yes"; then
|
if test "$enable_swig_version_check" = "yes"; then
|
||||||
AX_PKG_SWIG(2.0.1)
|
AC_PROG_SWIG(2.0.1)
|
||||||
else
|
else
|
||||||
AX_PKG_SWIG
|
AC_PROG_SWIG
|
||||||
fi
|
fi
|
||||||
AC_MSG_CHECKING(SWIG)
|
AC_MSG_CHECKING(SWIG)
|
||||||
if test ! -x "$SWIG"; then
|
if test ! -x "$SWIG"; then
|
||||||
@@ -998,8 +829,7 @@ if test "`uname`" = "Linux"; then
|
|||||||
GCC_DOCKER_LINTFLAGS='-syntax'
|
GCC_DOCKER_LINTFLAGS='-syntax'
|
||||||
AC_SUBST(GCC_DOCKER_LINTFLAGS)
|
AC_SUBST(GCC_DOCKER_LINTFLAGS)
|
||||||
fi
|
fi
|
||||||
AX_BUILD_DATE_EPOCH(CONFIG_DATE, [%Y%m%d])
|
CONFIG_DATE=`date +%Y%m%d`
|
||||||
AC_ARG_VAR(SOURCE_DATE_EPOCH, [If it is set, it uses the value of that variable instead of the current time as the build timestamp. The format is a unix timestamp. This enables reproducible build output.])
|
|
||||||
AC_SUBST(CONFIG_DATE)
|
AC_SUBST(CONFIG_DATE)
|
||||||
|
|
||||||
# Checks for libraries.
|
# Checks for libraries.
|
||||||
@@ -1083,22 +913,15 @@ else
|
|||||||
AC_MSG_RESULT([no])
|
AC_MSG_RESULT([no])
|
||||||
fi
|
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_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])
|
||||||
|
|
||||||
# these check_funcs need -lssl
|
# these check_funcs need -lssl
|
||||||
BAKLIBS="$LIBS"
|
BAKLIBS="$LIBS"
|
||||||
LIBS="-lssl $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([OPENSSL_init_ssl SSL_CTX_set_security_level SSL_set1_host SSL_get0_peername X509_VERIFY_PARAM_set1_host SSL_CTX_set_ciphersuites SSL_CTX_set_tlsext_ticket_key_evp_cb SSL_CTX_set_alpn_select_cb SSL_get0_alpn_selected SSL_CTX_set_alpn_protos SSL_get1_peer_certificate])
|
||||||
AC_CHECK_FUNCS([X509_NAME_get_text_by_NID])
|
|
||||||
if test $ac_cv_func_X509_NAME_get_text_by_NID = yes; then
|
|
||||||
ACX_FUNC_DEPRECATED([X509_NAME_get_text_by_NID], [
|
|
||||||
(void)X509_NAME_get_text_by_NID(NULL, 0, NULL, 0);], [
|
|
||||||
#include "openssl/x509.h"
|
|
||||||
])
|
|
||||||
fi
|
|
||||||
LIBS="$BAKLIBS"
|
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], [], [], [
|
AC_CHECK_DECLS([SSL_COMP_get_compression_methods,sk_SSL_COMP_pop_free,SSL_CTX_set_ecdh_auto], [], [], [
|
||||||
AC_INCLUDES_DEFAULT
|
AC_INCLUDES_DEFAULT
|
||||||
#ifdef HAVE_OPENSSL_ERR_H
|
#ifdef HAVE_OPENSSL_ERR_H
|
||||||
#include <openssl/err.h>
|
#include <openssl/err.h>
|
||||||
@@ -1293,8 +1116,7 @@ int main(void) {
|
|||||||
return 6;
|
return 6;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
]])] , [eval "ac_cv_c_gost_works=yes"], [eval "ac_cv_c_gost_works=no"],
|
]])] , [eval "ac_cv_c_gost_works=yes"], [eval "ac_cv_c_gost_works=no"])
|
||||||
[eval "ac_cv_c_gost_works=maybe"])
|
|
||||||
CFLAGS="$BAKCFLAGS"
|
CFLAGS="$BAKCFLAGS"
|
||||||
else
|
else
|
||||||
eval "ac_cv_c_gost_works=maybe"
|
eval "ac_cv_c_gost_works=maybe"
|
||||||
@@ -1327,24 +1149,15 @@ case "$enable_ecdsa" in
|
|||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
if test $USE_NSS = "no" -a $USE_NETTLE = "no"; then
|
if test $USE_NSS = "no" -a $USE_NETTLE = "no"; then
|
||||||
AC_CHECK_FUNC(EVP_PKEY_fromdata, [
|
AC_CHECK_FUNC(ECDSA_sign, [], [AC_MSG_ERROR([OpenSSL does not support ECDSA: please upgrade or rerun with --disable-ecdsa])])
|
||||||
# with EVP_PKEY_fromdata, check if EC is not disabled
|
AC_CHECK_FUNC(SHA384_Init, [], [AC_MSG_ERROR([OpenSSL does not support SHA384: please upgrade or rerun with --disable-ecdsa])])
|
||||||
AC_CHECK_DECL([OPENSSL_NO_EC], [AC_MSG_ERROR([OpenSSL does not support ECDSA: please upgrade or rerun with --disable-ecdsa])
|
|
||||||
], [], [AC_INCLUDES_DEFAULT
|
|
||||||
#include <openssl/evp.h>
|
|
||||||
])
|
|
||||||
], [
|
|
||||||
# without EVP_PKEY_fromdata, older openssl, check for support
|
|
||||||
AC_CHECK_FUNC(ECDSA_sign, [], [AC_MSG_ERROR([OpenSSL does not support ECDSA: please upgrade or rerun with --disable-ecdsa])])
|
|
||||||
AC_CHECK_FUNC(SHA384_Init, [], [AC_MSG_ERROR([OpenSSL does not support SHA384: please upgrade or rerun with --disable-ecdsa])])
|
|
||||||
])
|
|
||||||
AC_CHECK_DECLS([NID_X9_62_prime256v1, NID_secp384r1], [], [AC_MSG_ERROR([OpenSSL does not support the ECDSA curves: please upgrade or rerun with --disable-ecdsa])], [AC_INCLUDES_DEFAULT
|
AC_CHECK_DECLS([NID_X9_62_prime256v1, NID_secp384r1], [], [AC_MSG_ERROR([OpenSSL does not support the ECDSA curves: please upgrade or rerun with --disable-ecdsa])], [AC_INCLUDES_DEFAULT
|
||||||
#include <openssl/evp.h>
|
#include <openssl/evp.h>
|
||||||
])
|
])
|
||||||
# see if OPENSSL 1.0.0 or later (has EVP MD and Verify independency)
|
# see if OPENSSL 1.0.0 or later (has EVP MD and Verify independency)
|
||||||
AC_MSG_CHECKING([if openssl supports SHA2 and ECDSA with EVP])
|
AC_MSG_CHECKING([if openssl supports SHA2 and ECDSA with EVP])
|
||||||
if grep OPENSSL_VERSION_TEXT $ssldir_include/openssl/opensslv.h | grep "OpenSSL" >/dev/null; then
|
if grep OPENSSL_VERSION_TEXT $ssldir_include/openssl/opensslv.h | grep "OpenSSL" >/dev/null; then
|
||||||
if grep OPENSSL_VERSION_TEXT $ssldir_include/openssl/opensslv.h | grep "OpenSSL 0\." >/dev/null; then
|
if grep OPENSSL_VERSION_NUMBER $ssldir_include/openssl/opensslv.h | grep 0x0 >/dev/null; then
|
||||||
AC_MSG_RESULT([no])
|
AC_MSG_RESULT([no])
|
||||||
AC_DEFINE_UNQUOTED([USE_ECDSA_EVP_WORKAROUND], [1], [Define this to enable an EVP workaround for older openssl])
|
AC_DEFINE_UNQUOTED([USE_ECDSA_EVP_WORKAROUND], [1], [Define this to enable an EVP workaround for older openssl])
|
||||||
else
|
else
|
||||||
@@ -1678,96 +1491,6 @@ if test x_$withval = x_yes -o x_$withval != x_no; then
|
|||||||
])
|
])
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# ngtcp2
|
|
||||||
AC_ARG_WITH(libngtcp2, AS_HELP_STRING([--with-libngtcp2=path],[specify explicit path for libngtcp2, for QUIC.]),
|
|
||||||
[ ],[ withval="no" ])
|
|
||||||
found_libngtcp2="no"
|
|
||||||
if test x_$withval = x_yes -o x_$withval != x_no; then
|
|
||||||
AC_MSG_CHECKING(for libngtcp2)
|
|
||||||
if test x_$withval = x_ -o x_$withval = x_yes; then
|
|
||||||
withval="/usr/local /opt/local /usr/lib /usr/pkg /usr/sfw /usr"
|
|
||||||
fi
|
|
||||||
for dir in $withval ; do
|
|
||||||
if test -f "$dir/include/ngtcp2/ngtcp2.h"; then
|
|
||||||
found_libngtcp2="yes"
|
|
||||||
dnl assume /usr is in default path.
|
|
||||||
if test "$dir" != "/usr"; then
|
|
||||||
CPPFLAGS="$CPPFLAGS -I$dir/include"
|
|
||||||
LDFLAGS="$LDFLAGS -L$dir/lib"
|
|
||||||
fi
|
|
||||||
AC_MSG_RESULT(found in $dir)
|
|
||||||
AC_DEFINE([HAVE_NGTCP2], [1], [Define this to use ngtcp2.])
|
|
||||||
LIBS="$LIBS -lngtcp2"
|
|
||||||
break;
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
if test x_$found_libngtcp2 != x_yes; then
|
|
||||||
AC_MSG_ERROR([Could not find libngtcp2, ngtcp2.h])
|
|
||||||
fi
|
|
||||||
AC_CHECK_HEADERS([ngtcp2/ngtcp2.h ngtcp2/ngtcp2_crypto_ossl.h ngtcp2/ngtcp2_crypto_openssl.h ngtcp2/ngtcp2_crypto_quictls.h],,, [AC_INCLUDES_DEFAULT])
|
|
||||||
AC_CHECK_DECLS([ngtcp2_conn_server_new], [], [], [AC_INCLUDES_DEFAULT
|
|
||||||
#include <ngtcp2/ngtcp2.h>
|
|
||||||
])
|
|
||||||
AC_CHECK_DECLS([ngtcp2_crypto_encrypt_cb], [], [], [AC_INCLUDES_DEFAULT
|
|
||||||
#include <ngtcp2/ngtcp2_crypto.h>
|
|
||||||
])
|
|
||||||
AC_CHECK_LIB([ngtcp2_crypto_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" ])
|
|
||||||
])
|
|
||||||
])
|
|
||||||
AC_CHECK_FUNCS([ngtcp2_crypto_encrypt_cb ngtcp2_ccerr_default ngtcp2_conn_in_closing_period ngtcp2_conn_in_draining_period ngtcp2_conn_get_max_local_streams_uni ngtcp2_crypto_quictls_from_ossl_encryption_level ngtcp2_crypto_quictls_configure_server_context ngtcp2_crypto_quictls_configure_client_context ngtcp2_crypto_quictls_init ngtcp2_conn_get_num_scid ngtcp2_conn_tls_early_data_rejected ngtcp2_conn_encode_0rtt_transport_params])
|
|
||||||
|
|
||||||
# these check_funcs need -lssl
|
|
||||||
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
|
|
||||||
#include <ngtcp2/ngtcp2.h>
|
|
||||||
])
|
|
||||||
AC_CHECK_MEMBERS([struct ngtcp2_pkt_hd.tokenlen, struct ngtcp2_settings.tokenlen, struct ngtcp2_settings.max_tx_udp_payload_size, struct ngtcp2_transport_params.original_dcid_present],,,[AC_INCLUDES_DEFAULT
|
|
||||||
#include <ngtcp2/ngtcp2.h>
|
|
||||||
])
|
|
||||||
|
|
||||||
AC_MSG_CHECKING([whether ngtcp2_conn_shutdown_stream has 4 arguments])
|
|
||||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([AC_INCLUDES_DEFAULT
|
|
||||||
#include <ngtcp2/ngtcp2.h>
|
|
||||||
],[
|
|
||||||
(void)ngtcp2_conn_shutdown_stream(NULL, 0, 0, 0);
|
|
||||||
])],[
|
|
||||||
AC_MSG_RESULT(yes)
|
|
||||||
AC_DEFINE(HAVE_NGTCP2_CONN_SHUTDOWN_STREAM4, 1, [Define if ngtcp2_conn_shutdown_stream has 4 arguments.])
|
|
||||||
],[
|
|
||||||
AC_MSG_RESULT(no)
|
|
||||||
])
|
|
||||||
|
|
||||||
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
|
# set static linking for uninstalled libraries if requested
|
||||||
AC_SUBST(staticexe)
|
AC_SUBST(staticexe)
|
||||||
staticexe=""
|
staticexe=""
|
||||||
@@ -1778,19 +1501,13 @@ if test x_$enable_static_exe = x_yes; then
|
|||||||
if test "$on_mingw" = yes; then
|
if test "$on_mingw" = yes; then
|
||||||
staticexe="-all-static"
|
staticexe="-all-static"
|
||||||
# for static compile, include gdi32 and zlib here.
|
# for static compile, include gdi32 and zlib here.
|
||||||
if echo "$LIBS" | grep 'lgdi32' >/dev/null; then
|
if echo $LIBS | grep 'lgdi32' >/dev/null; then
|
||||||
:
|
:
|
||||||
else
|
else
|
||||||
LIBS="$LIBS -lgdi32"
|
LIBS="$LIBS -lgdi32"
|
||||||
fi
|
fi
|
||||||
AC_CHECK_LIB([z], [compress], [ LIBS="$LIBS -lz" ])
|
AC_CHECK_LIB([z], [compress], [ LIBS="$LIBS -lz" ])
|
||||||
if echo "$host" | $GREP -i -e linux >/dev/null; then
|
LIBS="$LIBS -l:libssp.a"
|
||||||
if echo "$LIBS" | grep -e "libssp.a" -e "lssp" >/dev/null; then
|
|
||||||
:
|
|
||||||
else
|
|
||||||
LIBS="$LIBS -l:libssp.a"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -1807,13 +1524,7 @@ if test x_$enable_fully_static = x_yes; then
|
|||||||
LIBS="$LIBS -lgdi32"
|
LIBS="$LIBS -lgdi32"
|
||||||
fi
|
fi
|
||||||
AC_CHECK_LIB([z], [compress], [ LIBS="$LIBS -lz" ])
|
AC_CHECK_LIB([z], [compress], [ LIBS="$LIBS -lz" ])
|
||||||
if echo "$host" | $GREP -i -e linux >/dev/null; then
|
LIBS="$LIBS -l:libssp.a"
|
||||||
if echo "$LIBS" | grep -e "libssp.a" -e "lssp" >/dev/null; then
|
|
||||||
:
|
|
||||||
else
|
|
||||||
LIBS="$LIBS -l:libssp.a"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -1833,11 +1544,7 @@ if test "$USE_WINSOCK" = 1; then
|
|||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
])
|
])
|
||||||
AC_CHECK_TOOL(WINDRES, windres)
|
AC_CHECK_TOOL(WINDRES, windres)
|
||||||
if echo "$LIBS" | grep crypt32 >/dev/null; then
|
LIBS="$LIBS -liphlpapi -lcrypt32"
|
||||||
LIBS="$LIBS -liphlpapi"
|
|
||||||
else
|
|
||||||
LIBS="$LIBS -liphlpapi -lcrypt32"
|
|
||||||
fi
|
|
||||||
WINAPPS="unbound-service-install.exe unbound-service-remove.exe anchor-update.exe"
|
WINAPPS="unbound-service-install.exe unbound-service-remove.exe anchor-update.exe"
|
||||||
AC_SUBST(WINAPPS)
|
AC_SUBST(WINAPPS)
|
||||||
WIN_DAEMON_SRC="winrc/win_svc.c winrc/w_inst.c"
|
WIN_DAEMON_SRC="winrc/win_svc.c winrc/w_inst.c"
|
||||||
@@ -1871,7 +1578,6 @@ if test $ac_cv_func_daemon = yes; then
|
|||||||
])
|
])
|
||||||
fi
|
fi
|
||||||
|
|
||||||
AC_CHECK_MEMBERS([struct stat.st_mtimensec, struct stat.st_mtim.tv_nsec])
|
|
||||||
AC_CHECK_MEMBERS([struct sockaddr_un.sun_len],,,[
|
AC_CHECK_MEMBERS([struct sockaddr_un.sun_len],,,[
|
||||||
AC_INCLUDES_DEFAULT
|
AC_INCLUDES_DEFAULT
|
||||||
#ifdef HAVE_SYS_UN_H
|
#ifdef HAVE_SYS_UN_H
|
||||||
@@ -1942,7 +1648,7 @@ AC_LINK_IFELSE([AC_LANG_PROGRAM([
|
|||||||
AC_MSG_RESULT(no))
|
AC_MSG_RESULT(no))
|
||||||
|
|
||||||
AC_SEARCH_LIBS([setusercontext], [util])
|
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([setresuid],,[AC_CHECK_FUNCS([setreuid])])
|
||||||
AC_CHECK_FUNCS([setresgid],,[AC_CHECK_FUNCS([setregid])])
|
AC_CHECK_FUNCS([setresgid],,[AC_CHECK_FUNCS([setregid])])
|
||||||
|
|
||||||
@@ -1950,25 +1656,6 @@ AC_CHECK_FUNCS([setresgid],,[AC_CHECK_FUNCS([setregid])])
|
|||||||
if echo $host_os | grep darwin8 > /dev/null; then
|
if echo $host_os | grep darwin8 > /dev/null; then
|
||||||
AC_DEFINE(DARWIN_BROKEN_SETREUID, 1, [Define this if on macOSX10.4-darwin8 and setreuid and setregid do not work])
|
AC_DEFINE(DARWIN_BROKEN_SETREUID, 1, [Define this if on macOSX10.4-darwin8 and setreuid and setregid do not work])
|
||||||
fi
|
fi
|
||||||
|
|
||||||
AC_MSG_CHECKING([for atomic_store])
|
|
||||||
AC_LINK_IFELSE([AC_LANG_PROGRAM(AC_INCLUDES_DEFAULT [[
|
|
||||||
#ifdef HAVE_STDATOMIC_H
|
|
||||||
#include <stdatomic.h>
|
|
||||||
#endif
|
|
||||||
]], [[
|
|
||||||
int newvar = 5, var = 0;
|
|
||||||
atomic_store((_Atomic int*)&var, newvar);
|
|
||||||
newvar = 0;
|
|
||||||
/* condition to use the variables. */
|
|
||||||
if(var == newvar) return 1;
|
|
||||||
]])], [
|
|
||||||
AC_MSG_RESULT(yes)
|
|
||||||
AC_DEFINE(HAVE_LINK_ATOMIC_STORE, 1, [If we have atomic_store])
|
|
||||||
], [
|
|
||||||
AC_MSG_RESULT([no])
|
|
||||||
])
|
|
||||||
|
|
||||||
AC_CHECK_DECLS([inet_pton,inet_ntop], [], [], [
|
AC_CHECK_DECLS([inet_pton,inet_ntop], [], [], [
|
||||||
AC_INCLUDES_DEFAULT
|
AC_INCLUDES_DEFAULT
|
||||||
#ifdef HAVE_NETINET_IN_H
|
#ifdef HAVE_NETINET_IN_H
|
||||||
@@ -2006,7 +1693,7 @@ int main(void) { return !(snprintf(NULL, 0, "test") == 4); }
|
|||||||
AC_MSG_RESULT(no)
|
AC_MSG_RESULT(no)
|
||||||
AC_DEFINE([SNPRINTF_RET_BROKEN], [], [define if (v)snprintf does not return length needed, (but length used)])
|
AC_DEFINE([SNPRINTF_RET_BROKEN], [], [define if (v)snprintf does not return length needed, (but length used)])
|
||||||
AC_LIBOBJ(snprintf)
|
AC_LIBOBJ(snprintf)
|
||||||
], [AC_MSG_RESULT(maybe)])
|
])
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
AC_REPLACE_FUNCS(strlcat)
|
AC_REPLACE_FUNCS(strlcat)
|
||||||
@@ -2107,12 +1794,10 @@ if test x_$enable_lock_checks = x_yes; then
|
|||||||
UBSYMS="-export-symbols clubsyms.def"
|
UBSYMS="-export-symbols clubsyms.def"
|
||||||
cp ${srcdir}/libunbound/ubsyms.def clubsyms.def
|
cp ${srcdir}/libunbound/ubsyms.def clubsyms.def
|
||||||
echo lock_protect >> clubsyms.def
|
echo lock_protect >> clubsyms.def
|
||||||
echo lock_protect_place >> clubsyms.def
|
|
||||||
echo lock_unprotect >> clubsyms.def
|
echo lock_unprotect >> clubsyms.def
|
||||||
echo lock_get_mem >> clubsyms.def
|
echo lock_get_mem >> clubsyms.def
|
||||||
echo checklock_start >> clubsyms.def
|
echo checklock_start >> clubsyms.def
|
||||||
echo checklock_stop >> clubsyms.def
|
echo checklock_stop >> clubsyms.def
|
||||||
echo checklock_set_output_name >> clubsyms.def
|
|
||||||
echo checklock_lock >> clubsyms.def
|
echo checklock_lock >> clubsyms.def
|
||||||
echo checklock_unlock >> clubsyms.def
|
echo checklock_unlock >> clubsyms.def
|
||||||
echo checklock_init >> clubsyms.def
|
echo checklock_init >> clubsyms.def
|
||||||
@@ -2193,17 +1878,15 @@ case "$enable_ipset" in
|
|||||||
IPSET_OBJ="ipset.lo"
|
IPSET_OBJ="ipset.lo"
|
||||||
AC_SUBST(IPSET_OBJ)
|
AC_SUBST(IPSET_OBJ)
|
||||||
|
|
||||||
# BSD's pf
|
# mnl
|
||||||
AC_CHECK_HEADERS([net/pfvar.h], [], [
|
AC_ARG_WITH(libmnl, AS_HELP_STRING([--with-libmnl=path],[specify explicit path for libmnl.]),
|
||||||
# mnl
|
|
||||||
AC_ARG_WITH(libmnl, AS_HELP_STRING([--with-libmnl=path],[specify explicit path for libmnl.]),
|
|
||||||
[ ],[ withval="yes" ])
|
[ ],[ withval="yes" ])
|
||||||
found_libmnl="no"
|
found_libmnl="no"
|
||||||
AC_MSG_CHECKING(for libmnl)
|
AC_MSG_CHECKING(for libmnl)
|
||||||
if test x_$withval = x_ -o x_$withval = x_yes; then
|
if test x_$withval = x_ -o x_$withval = x_yes; then
|
||||||
withval="/usr/local /opt/local /usr/lib /usr/pkg /usr/sfw /usr"
|
withval="/usr/local /opt/local /usr/lib /usr/pkg /usr/sfw /usr"
|
||||||
fi
|
fi
|
||||||
for dir in $withval ; do
|
for dir in $withval ; do
|
||||||
if test -f "$dir/include/libmnl/libmnl.h" -o -f "$dir/include/libmnl/libmnl/libmnl.h"; then
|
if test -f "$dir/include/libmnl/libmnl.h" -o -f "$dir/include/libmnl/libmnl/libmnl.h"; then
|
||||||
found_libmnl="yes"
|
found_libmnl="yes"
|
||||||
dnl assume /usr is in default path.
|
dnl assume /usr is in default path.
|
||||||
@@ -2221,14 +1904,10 @@ case "$enable_ipset" in
|
|||||||
LIBS="$LIBS -lmnl"
|
LIBS="$LIBS -lmnl"
|
||||||
break;
|
break;
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
if test x_$found_libmnl != x_yes; then
|
if test x_$found_libmnl != x_yes; then
|
||||||
AC_MSG_ERROR([Could not find libmnl, libmnl.h])
|
AC_MSG_ERROR([Could not find libmnl, libmnl.h])
|
||||||
fi
|
fi
|
||||||
], [
|
|
||||||
#include <netinet/in.h>
|
|
||||||
#include <net/if.h>
|
|
||||||
])
|
|
||||||
;;
|
;;
|
||||||
no|*)
|
no|*)
|
||||||
# nothing
|
# nothing
|
||||||
@@ -2244,7 +1923,7 @@ case "$enable_explicit_port_randomisation" in
|
|||||||
esac
|
esac
|
||||||
|
|
||||||
if echo "$host" | $GREP -i -e linux >/dev/null; then
|
if echo "$host" | $GREP -i -e linux >/dev/null; then
|
||||||
AC_ARG_ENABLE(linux-ip-local-port-range, AS_HELP_STRING([--enable-linux-ip-local-port-range], [Define this to enable use of /proc/sys/net/ipv4/ip_local_port_range as a default outgoing port range. This is only for the libunbound on Linux and does not affect unbound resolving daemon itself. This may severely limit the number of available outgoing ports and thus decrease randomness. Define this only when the target system restricts (e.g. some of SELinux enabled distributions) the use of non-ephemeral ports.]))
|
AC_ARG_ENABLE(linux-ip-local-port-range, AC_HELP_STRING([--enable-linux-ip-local-port-range], [Define this to enable use of /proc/sys/net/ipv4/ip_local_port_range as a default outgoing port range. This is only for the libunbound on Linux and does not affect unbound resolving daemon itself. This may severely limit the number of available outgoing ports and thus decrease randomness. Define this only when the target system restricts (e.g. some of SELinux enabled distributions) the use of non-ephemeral ports.]))
|
||||||
case "$enable_linux_ip_local_port_range" in
|
case "$enable_linux_ip_local_port_range" in
|
||||||
yes)
|
yes)
|
||||||
AC_DEFINE([USE_LINUX_IP_LOCAL_PORT_RANGE], [1], [Define this to enable use of /proc/sys/net/ipv4/ip_local_port_range as a default outgoing port range. This is only for the libunbound on Linux and does not affect unbound resolving daemon itself. This may severely limit the number of available outgoing ports and thus decrease randomness. Define this only when the target system restricts (e.g. some of SELinux enabled distributions) the use of non-ephemeral ports.])
|
AC_DEFINE([USE_LINUX_IP_LOCAL_PORT_RANGE], [1], [Define this to enable use of /proc/sys/net/ipv4/ip_local_port_range as a default outgoing port range. This is only for the libunbound on Linux and does not affect unbound resolving daemon itself. This may severely limit the number of available outgoing ports and thus decrease randomness. Define this only when the target system restricts (e.g. some of SELinux enabled distributions) the use of non-ephemeral ports.])
|
||||||
@@ -2409,7 +2088,6 @@ dnl includes
|
|||||||
|
|
||||||
AHX_CONFIG_FORMAT_ATTRIBUTE
|
AHX_CONFIG_FORMAT_ATTRIBUTE
|
||||||
AHX_CONFIG_UNUSED_ATTRIBUTE
|
AHX_CONFIG_UNUSED_ATTRIBUTE
|
||||||
AHX_CONFIG_NONSTRING_ATTRIBUTE
|
|
||||||
AHX_CONFIG_FSEEKO
|
AHX_CONFIG_FSEEKO
|
||||||
AHX_CONFIG_MAXHOSTNAMELEN
|
AHX_CONFIG_MAXHOSTNAMELEN
|
||||||
#if !defined(HAVE_SNPRINTF) || defined(SNPRINTF_RET_BROKEN)
|
#if !defined(HAVE_SNPRINTF) || defined(SNPRINTF_RET_BROKEN)
|
||||||
@@ -2547,10 +2225,6 @@ struct sockaddr_storage;
|
|||||||
# define calloc(n,s) unbound_stat_calloc_log(n, s, __FILE__, __LINE__, __func__)
|
# define calloc(n,s) unbound_stat_calloc_log(n, s, __FILE__, __LINE__, __func__)
|
||||||
# define free(p) unbound_stat_free_log(p, __FILE__, __LINE__, __func__)
|
# define free(p) unbound_stat_free_log(p, __FILE__, __LINE__, __func__)
|
||||||
# define realloc(p,s) unbound_stat_realloc_log(p, s, __FILE__, __LINE__, __func__)
|
# define realloc(p,s) unbound_stat_realloc_log(p, s, __FILE__, __LINE__, __func__)
|
||||||
# define strdup(s) unbound_stat_strdup_log(s, __FILE__, __LINE__, __func__)
|
|
||||||
#ifdef HAVE_REALLOCARRAY
|
|
||||||
# define reallocarray(p,n,s) unbound_stat_reallocarray_log(p, n, s, __FILE__, __LINE__, __func__)
|
|
||||||
#endif
|
|
||||||
void *unbound_stat_malloc(size_t size);
|
void *unbound_stat_malloc(size_t size);
|
||||||
void *unbound_stat_calloc(size_t nmemb, size_t size);
|
void *unbound_stat_calloc(size_t nmemb, size_t size);
|
||||||
void unbound_stat_free(void *ptr);
|
void unbound_stat_free(void *ptr);
|
||||||
@@ -2563,10 +2237,6 @@ void unbound_stat_free_log(void *ptr, const char* file, int line,
|
|||||||
const char* func);
|
const char* func);
|
||||||
void *unbound_stat_realloc_log(void *ptr, size_t size, const char* file,
|
void *unbound_stat_realloc_log(void *ptr, size_t size, const char* file,
|
||||||
int line, const char* func);
|
int line, const char* func);
|
||||||
void *unbound_stat_reallocarray_log(void *ptr, size_t nmemb, size_t size,
|
|
||||||
const char* file, int line, const char* func);
|
|
||||||
char *unbound_stat_strdup_log(const char *s, const char* file, int line,
|
|
||||||
const char* func);
|
|
||||||
#elif defined(UNBOUND_ALLOC_LITE)
|
#elif defined(UNBOUND_ALLOC_LITE)
|
||||||
# include "util/alloc.h"
|
# include "util/alloc.h"
|
||||||
#endif /* UNBOUND_ALLOC_LITE and UNBOUND_ALLOC_STATS */
|
#endif /* UNBOUND_ALLOC_LITE and UNBOUND_ALLOC_STATS */
|
||||||
@@ -2577,8 +2247,6 @@ char *unbound_stat_strdup_log(const char *s, const char* file, int line,
|
|||||||
#define UNBOUND_DNS_OVER_TLS_PORT 853
|
#define UNBOUND_DNS_OVER_TLS_PORT 853
|
||||||
/** default port for DNS over HTTPS traffic. */
|
/** default port for DNS over HTTPS traffic. */
|
||||||
#define UNBOUND_DNS_OVER_HTTPS_PORT 443
|
#define UNBOUND_DNS_OVER_HTTPS_PORT 443
|
||||||
/** default port for DNS over QUIC traffic. */
|
|
||||||
#define UNBOUND_DNS_OVER_QUIC_PORT 853
|
|
||||||
/** default port for unbound control traffic, registered port with IANA,
|
/** default port for unbound control traffic, registered port with IANA,
|
||||||
ub-dns-control 8953/tcp unbound dns nameserver control */
|
ub-dns-control 8953/tcp unbound dns nameserver control */
|
||||||
#define UNBOUND_CONTROL_PORT 8953
|
#define UNBOUND_CONTROL_PORT 8953
|
||||||
@@ -2590,8 +2258,7 @@ char *unbound_stat_strdup_log(const char *s, const char* file, int line,
|
|||||||
dnl if we build from source tree, the man pages need @date@ and @version@
|
dnl if we build from source tree, the man pages need @date@ and @version@
|
||||||
dnl if this is a distro tarball, that was already done by makedist.sh
|
dnl if this is a distro tarball, that was already done by makedist.sh
|
||||||
AC_SUBST(version, [VERSION_MAJOR.VERSION_MINOR.VERSION_MICRO])
|
AC_SUBST(version, [VERSION_MAJOR.VERSION_MINOR.VERSION_MICRO])
|
||||||
AX_BUILD_DATE_EPOCH(date, [[%b %e, %Y]])
|
AC_SUBST(date, [`date +'%b %e, %Y'`])
|
||||||
AC_SUBST(date)
|
|
||||||
|
|
||||||
AC_CONFIG_FILES([Makefile doc/example.conf doc/libunbound.3 doc/unbound.8 doc/unbound-anchor.8 doc/unbound-checkconf.8 doc/unbound.conf.5 doc/unbound-control.8 doc/unbound-host.1 smallapp/unbound-control-setup.sh dnstap/dnstap_config.h dnscrypt/dnscrypt_config.h contrib/libunbound.pc contrib/unbound.socket contrib/unbound.service contrib/unbound_portable.service])
|
AC_CONFIG_FILES([Makefile doc/example.conf doc/libunbound.3 doc/unbound.8 doc/unbound-anchor.8 doc/unbound-checkconf.8 doc/unbound.conf.5 doc/unbound-control.8 doc/unbound-host.1 smallapp/unbound-control-setup.sh dnstap/dnstap_config.h dnscrypt/dnscrypt_config.h contrib/libunbound.pc contrib/unbound.socket contrib/unbound.service contrib/unbound_portable.service])
|
||||||
AC_CONFIG_HEADERS([config.h])
|
AC_CONFIG_HEADERS([config.h])
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
FROM gcc:latest
|
FROM gcc:latest
|
||||||
WORKDIR /usr/src/unbound
|
WORKDIR /usr/src/unbound
|
||||||
|
RUN apt-get update
|
||||||
# install semantic parser & lexical analyzer
|
# install semantic parser & lexical analyzer
|
||||||
|
RUN apt-get install -y bison flex
|
||||||
# install packages used in tests
|
# install packages used in tests
|
||||||
RUN apt-get update && apt-get install -y bison flex ldnsutils dnsutils xxd splint doxygen netcat-openbsd
|
RUN apt-get install -y ldnsutils dnsutils xxd splint doxygen netcat
|
||||||
# accept short rsa keys, which are used in tests
|
# accept short rsa keys, which are used in tests
|
||||||
RUN sed -i 's/SECLEVEL=2/SECLEVEL=1/g' /usr/lib/ssl/openssl.cnf
|
RUN sed -i 's/SECLEVEL=2/SECLEVEL=1/g' /usr/lib/ssl/openssl.cnf
|
||||||
|
|
||||||
|
|||||||
@@ -55,8 +55,3 @@ distribution but may be helpful.
|
|||||||
contributed by Andreas Schulze.
|
contributed by Andreas Schulze.
|
||||||
* metrics.awk: awk script that can convert unbound-control stats to
|
* metrics.awk: awk script that can convert unbound-control stats to
|
||||||
Prometheus metrics format output.
|
Prometheus metrics format output.
|
||||||
* 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.
|
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
diff --git a/doc/unbound.conf.5.in b/doc/unbound.conf.5.in
|
diff --git a/doc/unbound.conf.5.in b/doc/unbound.conf.5.in
|
||||||
index 172eb26c..2921c87f 100644
|
index 5a75e319..c6c6dbe2 100644
|
||||||
--- a/doc/unbound.conf.5.in
|
--- a/doc/unbound.conf.5.in
|
||||||
+++ b/doc/unbound.conf.5.in
|
+++ b/doc/unbound.conf.5.in
|
||||||
@@ -2146,6 +2146,13 @@ Default: no
|
@@ -970,6 +970,13 @@ potentially broken nameservers. A lot of domains will not be resolvable when
|
||||||
.UNINDENT
|
this option in enabled. Only use if you know what you are doing.
|
||||||
.INDENT 0.0
|
This option only has effect when qname-minimisation is enabled. Default is no.
|
||||||
.TP
|
.TP
|
||||||
+.B aaaa\-filter: \fI<yes or no>
|
+.B aaaa\-filter: \fI<yes or no>
|
||||||
+Activate behavior similar to BIND's AAAA-filter.
|
+Activate behavior similar to BIND's AAAA-filter.
|
||||||
@@ -13,14 +13,14 @@ index 172eb26c..2921c87f 100644
|
|||||||
+This also causes an additional A query to be sent for each AAAA query.
|
+This also causes an additional A query to be sent for each AAAA query.
|
||||||
+This breaks DNSSEC!
|
+This breaks DNSSEC!
|
||||||
+.TP
|
+.TP
|
||||||
.B aggressive\-nsec: \fI<yes or no>\fP
|
.B aggressive\-nsec: \fI<yes or no>
|
||||||
Aggressive NSEC uses the DNSSEC NSEC chain to synthesize NXDOMAIN and other
|
Aggressive NSEC uses the DNSSEC NSEC chain to synthesize NXDOMAIN
|
||||||
denials, using information from previous NXDOMAINs answers.
|
and other denials, using information from previous NXDOMAINs answers.
|
||||||
diff --git a/iterator/iter_scrub.c b/iterator/iter_scrub.c
|
diff --git a/iterator/iter_scrub.c b/iterator/iter_scrub.c
|
||||||
index 49a5f5da..fbe434fa 100644
|
index f093c1bf..e55a2246 100644
|
||||||
--- a/iterator/iter_scrub.c
|
--- a/iterator/iter_scrub.c
|
||||||
+++ b/iterator/iter_scrub.c
|
+++ b/iterator/iter_scrub.c
|
||||||
@@ -849,6 +849,32 @@ scrub_sanitize_rr_length(sldns_buffer* pkt, struct msg_parse* msg,
|
@@ -679,6 +679,32 @@ static int sanitize_nsec_is_overreach(sldns_buffer* pkt,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -53,15 +53,15 @@ index 49a5f5da..fbe434fa 100644
|
|||||||
/**
|
/**
|
||||||
* Given a response event, remove suspect RRsets from the response.
|
* Given a response event, remove suspect RRsets from the response.
|
||||||
* "Suspect" rrsets are potentially poison. Note that this routine expects
|
* "Suspect" rrsets are potentially poison. Note that this routine expects
|
||||||
@@ -869,6 +895,7 @@ scrub_sanitize(sldns_buffer* pkt, struct msg_parse* msg,
|
@@ -698,6 +724,7 @@ scrub_sanitize(sldns_buffer* pkt, struct msg_parse* msg,
|
||||||
struct query_info* qinfo, uint8_t* zonename, struct module_env* env,
|
struct query_info* qinfo, uint8_t* zonename, struct module_env* env,
|
||||||
struct iter_env* ie, struct module_qstate* qstate)
|
struct iter_env* ie)
|
||||||
{
|
{
|
||||||
+ int found_a_record = 0; /* ASN: do we have a A record? */
|
+ int found_a_record = 0; /* ASN: do we have a A record? */
|
||||||
int del_addi = 0; /* if additional-holding rrsets are deleted, we
|
int del_addi = 0; /* if additional-holding rrsets are deleted, we
|
||||||
do not trust the normalized additional-A-AAAA any more */
|
do not trust the normalized additional-A-AAAA any more */
|
||||||
uint8_t* ns_rrset_dname = NULL;
|
struct rrset_parse* rrset, *prev;
|
||||||
@@ -906,6 +933,13 @@ scrub_sanitize(sldns_buffer* pkt, struct msg_parse* msg,
|
@@ -733,6 +760,13 @@ scrub_sanitize(sldns_buffer* pkt, struct msg_parse* msg,
|
||||||
rrset = rrset->rrset_all_next;
|
rrset = rrset->rrset_all_next;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -75,9 +75,9 @@ index 49a5f5da..fbe434fa 100644
|
|||||||
/* At this point, we brutally remove ALL rrsets that aren't
|
/* At this point, we brutally remove ALL rrsets that aren't
|
||||||
* children of the originating zone. The idea here is that,
|
* children of the originating zone. The idea here is that,
|
||||||
* as far as we know, the server that we contacted is ONLY
|
* as far as we know, the server that we contacted is ONLY
|
||||||
@@ -925,6 +959,24 @@ scrub_sanitize(sldns_buffer* pkt, struct msg_parse* msg,
|
@@ -744,6 +778,24 @@ scrub_sanitize(sldns_buffer* pkt, struct msg_parse* msg,
|
||||||
continue;
|
rrset = msg->rrset_first;
|
||||||
}
|
while(rrset) {
|
||||||
|
|
||||||
+ /* ASN: For AAAA records only... */
|
+ /* ASN: For AAAA records only... */
|
||||||
+ if((ie->aaaa_filter) && (rrset->type == LDNS_RR_TYPE_AAAA)) {
|
+ if((ie->aaaa_filter) && (rrset->type == LDNS_RR_TYPE_AAAA)) {
|
||||||
@@ -101,24 +101,24 @@ index 49a5f5da..fbe434fa 100644
|
|||||||
if( (rrset->type == LDNS_RR_TYPE_A ||
|
if( (rrset->type == LDNS_RR_TYPE_A ||
|
||||||
rrset->type == LDNS_RR_TYPE_AAAA)) {
|
rrset->type == LDNS_RR_TYPE_AAAA)) {
|
||||||
diff --git a/iterator/iter_utils.c b/iterator/iter_utils.c
|
diff --git a/iterator/iter_utils.c b/iterator/iter_utils.c
|
||||||
index 1da21896..6583dd0e 100644
|
index 2482a1f4..bd5ba243 100644
|
||||||
--- a/iterator/iter_utils.c
|
--- a/iterator/iter_utils.c
|
||||||
+++ b/iterator/iter_utils.c
|
+++ b/iterator/iter_utils.c
|
||||||
@@ -250,6 +250,7 @@ iter_apply_cfg(struct iter_env* iter_env, struct config_file* cfg)
|
@@ -177,6 +177,7 @@ iter_apply_cfg(struct iter_env* iter_env, struct config_file* cfg)
|
||||||
|
iter_env->supports_ipv6 = cfg->do_ip6;
|
||||||
|
iter_env->supports_ipv4 = cfg->do_ip4;
|
||||||
iter_env->outbound_msg_retry = cfg->outbound_msg_retry;
|
iter_env->outbound_msg_retry = cfg->outbound_msg_retry;
|
||||||
iter_env->max_sent_count = cfg->max_sent_count;
|
|
||||||
iter_env->max_query_restarts = cfg->max_query_restarts;
|
|
||||||
+ iter_env->aaaa_filter = cfg->aaaa_filter;
|
+ iter_env->aaaa_filter = cfg->aaaa_filter;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
diff --git a/iterator/iterator.c b/iterator/iterator.c
|
diff --git a/iterator/iterator.c b/iterator/iterator.c
|
||||||
index 71e64655..735f4ca0 100644
|
index 54006940..768fe202 100644
|
||||||
--- a/iterator/iterator.c
|
--- a/iterator/iterator.c
|
||||||
+++ b/iterator/iterator.c
|
+++ b/iterator/iterator.c
|
||||||
@@ -2412,6 +2412,53 @@ check_waiting_queries(struct iter_qstate* iq, struct module_qstate* qstate,
|
@@ -2155,6 +2155,53 @@ processDSNSFind(struct module_qstate* qstate, struct iter_qstate* iq, int id)
|
||||||
qstate->ext_state[id] = module_wait_reply;
|
|
||||||
}
|
return 0;
|
||||||
}
|
}
|
||||||
+
|
+
|
||||||
+/**
|
+/**
|
||||||
@@ -170,8 +170,8 @@ index 71e64655..735f4ca0 100644
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* This is the request event state where the request will be sent to one of
|
* This is the request event state where the request will be sent to one of
|
||||||
@@ -2554,6 +2601,13 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
|
@@ -2216,6 +2263,13 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||||
}
|
return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
|
||||||
}
|
}
|
||||||
|
|
||||||
+ /* ASN: If we have a AAAA query, then also query for A records */
|
+ /* ASN: If we have a AAAA query, then also query for A records */
|
||||||
@@ -184,7 +184,7 @@ index 71e64655..735f4ca0 100644
|
|||||||
/* Make sure we have a delegation point, otherwise priming failed
|
/* Make sure we have a delegation point, otherwise priming failed
|
||||||
* or another failure occurred */
|
* or another failure occurred */
|
||||||
if(!iq->dp) {
|
if(!iq->dp) {
|
||||||
@@ -4178,6 +4232,61 @@ processFinished(struct module_qstate* qstate, struct iter_qstate* iq,
|
@@ -3648,6 +3702,61 @@ processFinished(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -236,7 +236,7 @@ index 71e64655..735f4ca0 100644
|
|||||||
+ /* see if the failure did get (parent-lame) info */
|
+ /* see if the failure did get (parent-lame) info */
|
||||||
+ if(!cache_fill_missing(super->env,
|
+ if(!cache_fill_missing(super->env,
|
||||||
+ super_iq->qchase.qclass, super->region,
|
+ super_iq->qchase.qclass, super->region,
|
||||||
+ super_iq->dp, 0))
|
+ super_iq->dp))
|
||||||
+ log_err("ASN-AAAA-filter: out of memory adding missing");
|
+ log_err("ASN-AAAA-filter: out of memory adding missing");
|
||||||
+ dpns->resolved = 1; /* mark as failed */
|
+ dpns->resolved = 1; /* mark as failed */
|
||||||
+ }
|
+ }
|
||||||
@@ -246,7 +246,7 @@ index 71e64655..735f4ca0 100644
|
|||||||
/*
|
/*
|
||||||
* Return priming query results to interested super querystates.
|
* Return priming query results to interested super querystates.
|
||||||
*
|
*
|
||||||
@@ -4197,6 +4306,9 @@ iter_inform_super(struct module_qstate* qstate, int id,
|
@@ -3667,6 +3776,9 @@ iter_inform_super(struct module_qstate* qstate, int id,
|
||||||
else if(super->qinfo.qtype == LDNS_RR_TYPE_DS && ((struct iter_qstate*)
|
else if(super->qinfo.qtype == LDNS_RR_TYPE_DS && ((struct iter_qstate*)
|
||||||
super->minfo[id])->state == DSNS_FIND_STATE)
|
super->minfo[id])->state == DSNS_FIND_STATE)
|
||||||
processDSNSResponse(qstate, id, super);
|
processDSNSResponse(qstate, id, super);
|
||||||
@@ -256,7 +256,7 @@ index 71e64655..735f4ca0 100644
|
|||||||
else if(qstate->return_rcode != LDNS_RCODE_NOERROR)
|
else if(qstate->return_rcode != LDNS_RCODE_NOERROR)
|
||||||
error_supers(qstate, id, super);
|
error_supers(qstate, id, super);
|
||||||
else if(qstate->is_priming)
|
else if(qstate->is_priming)
|
||||||
@@ -4234,6 +4346,9 @@ iter_handle(struct module_qstate* qstate, struct iter_qstate* iq,
|
@@ -3704,6 +3816,9 @@ iter_handle(struct module_qstate* qstate, struct iter_qstate* iq,
|
||||||
case INIT_REQUEST_3_STATE:
|
case INIT_REQUEST_3_STATE:
|
||||||
cont = processInitRequest3(qstate, iq, id);
|
cont = processInitRequest3(qstate, iq, id);
|
||||||
break;
|
break;
|
||||||
@@ -266,7 +266,7 @@ index 71e64655..735f4ca0 100644
|
|||||||
case QUERYTARGETS_STATE:
|
case QUERYTARGETS_STATE:
|
||||||
cont = processQueryTargets(qstate, iq, ie, id);
|
cont = processQueryTargets(qstate, iq, ie, id);
|
||||||
break;
|
break;
|
||||||
@@ -4578,6 +4693,8 @@ iter_state_to_string(enum iter_state state)
|
@@ -4040,6 +4155,8 @@ iter_state_to_string(enum iter_state state)
|
||||||
return "INIT REQUEST STATE (stage 2)";
|
return "INIT REQUEST STATE (stage 2)";
|
||||||
case INIT_REQUEST_3_STATE:
|
case INIT_REQUEST_3_STATE:
|
||||||
return "INIT REQUEST STATE (stage 3)";
|
return "INIT REQUEST STATE (stage 3)";
|
||||||
@@ -275,7 +275,7 @@ index 71e64655..735f4ca0 100644
|
|||||||
case QUERYTARGETS_STATE :
|
case QUERYTARGETS_STATE :
|
||||||
return "QUERY TARGETS STATE";
|
return "QUERY TARGETS STATE";
|
||||||
case PRIME_RESP_STATE :
|
case PRIME_RESP_STATE :
|
||||||
@@ -4602,6 +4719,7 @@ iter_state_is_responsestate(enum iter_state s)
|
@@ -4064,6 +4181,7 @@ iter_state_is_responsestate(enum iter_state s)
|
||||||
case INIT_REQUEST_STATE :
|
case INIT_REQUEST_STATE :
|
||||||
case INIT_REQUEST_2_STATE :
|
case INIT_REQUEST_2_STATE :
|
||||||
case INIT_REQUEST_3_STATE :
|
case INIT_REQUEST_3_STATE :
|
||||||
@@ -284,10 +284,10 @@ index 71e64655..735f4ca0 100644
|
|||||||
case COLLECT_CLASS_STATE :
|
case COLLECT_CLASS_STATE :
|
||||||
return 0;
|
return 0;
|
||||||
diff --git a/iterator/iterator.h b/iterator/iterator.h
|
diff --git a/iterator/iterator.h b/iterator/iterator.h
|
||||||
index ae4b4e45..a44f9d27 100644
|
index 8b840528..a61c4195 100644
|
||||||
--- a/iterator/iterator.h
|
--- a/iterator/iterator.h
|
||||||
+++ b/iterator/iterator.h
|
+++ b/iterator/iterator.h
|
||||||
@@ -157,6 +157,9 @@ struct iter_env {
|
@@ -133,6 +133,9 @@ struct iter_env {
|
||||||
*/
|
*/
|
||||||
int* target_fetch_policy;
|
int* target_fetch_policy;
|
||||||
|
|
||||||
@@ -297,7 +297,7 @@ index ae4b4e45..a44f9d27 100644
|
|||||||
/** lock on ratelimit counter */
|
/** lock on ratelimit counter */
|
||||||
lock_basic_type queries_ratelimit_lock;
|
lock_basic_type queries_ratelimit_lock;
|
||||||
/** number of queries that have been ratelimited */
|
/** number of queries that have been ratelimited */
|
||||||
@@ -217,6 +220,14 @@ enum iter_state {
|
@@ -187,6 +190,14 @@ enum iter_state {
|
||||||
*/
|
*/
|
||||||
INIT_REQUEST_3_STATE,
|
INIT_REQUEST_3_STATE,
|
||||||
|
|
||||||
@@ -312,9 +312,9 @@ index ae4b4e45..a44f9d27 100644
|
|||||||
/**
|
/**
|
||||||
* Each time a delegation point changes for a given query or a
|
* Each time a delegation point changes for a given query or a
|
||||||
* query times out and/or wakes up, this state is (re)visited.
|
* query times out and/or wakes up, this state is (re)visited.
|
||||||
@@ -434,6 +445,13 @@ struct iter_qstate {
|
@@ -376,6 +387,13 @@ struct iter_qstate {
|
||||||
* already so that it is accepted later. */
|
*/
|
||||||
int empty_nodata_found;
|
int refetch_glue;
|
||||||
|
|
||||||
+ /**
|
+ /**
|
||||||
+ * ASN: This is a flag that, if true, means that this query is
|
+ * ASN: This is a flag that, if true, means that this query is
|
||||||
@@ -327,10 +327,10 @@ index ae4b4e45..a44f9d27 100644
|
|||||||
struct outbound_list outlist;
|
struct outbound_list outlist;
|
||||||
|
|
||||||
diff --git a/pythonmod/interface.i b/pythonmod/interface.i
|
diff --git a/pythonmod/interface.i b/pythonmod/interface.i
|
||||||
index 2040fb9e..f073c3dc 100644
|
index 1ca8686a..d91b19ec 100644
|
||||||
--- a/pythonmod/interface.i
|
--- a/pythonmod/interface.i
|
||||||
+++ b/pythonmod/interface.i
|
+++ b/pythonmod/interface.i
|
||||||
@@ -1013,6 +1013,7 @@ struct config_file {
|
@@ -995,6 +995,7 @@ struct config_file {
|
||||||
int harden_dnssec_stripped;
|
int harden_dnssec_stripped;
|
||||||
int harden_referral_path;
|
int harden_referral_path;
|
||||||
int use_caps_bits_for_id;
|
int use_caps_bits_for_id;
|
||||||
@@ -339,23 +339,23 @@ index 2040fb9e..f073c3dc 100644
|
|||||||
struct config_strlist* private_domain;
|
struct config_strlist* private_domain;
|
||||||
size_t unwanted_threshold;
|
size_t unwanted_threshold;
|
||||||
diff --git a/util/config_file.c b/util/config_file.c
|
diff --git a/util/config_file.c b/util/config_file.c
|
||||||
index b1e767b3..5eb3c099 100644
|
index 969d664b..8d94b008 100644
|
||||||
--- a/util/config_file.c
|
--- a/util/config_file.c
|
||||||
+++ b/util/config_file.c
|
+++ b/util/config_file.c
|
||||||
@@ -247,6 +247,7 @@ config_create(void)
|
@@ -231,6 +231,7 @@ config_create(void)
|
||||||
|
cfg->harden_referral_path = 0;
|
||||||
cfg->harden_algo_downgrade = 0;
|
cfg->harden_algo_downgrade = 0;
|
||||||
cfg->harden_unknown_additional = 0;
|
|
||||||
cfg->use_caps_bits_for_id = 0;
|
cfg->use_caps_bits_for_id = 0;
|
||||||
+ cfg->aaaa_filter = 0; /* ASN: default is disabled */
|
+ cfg->aaaa_filter = 0; /* ASN: default is disabled */
|
||||||
cfg->caps_whitelist = NULL;
|
cfg->caps_whitelist = NULL;
|
||||||
cfg->private_address = NULL;
|
cfg->private_address = NULL;
|
||||||
cfg->private_domain = NULL;
|
cfg->private_domain = NULL;
|
||||||
diff --git a/util/config_file.h b/util/config_file.h
|
diff --git a/util/config_file.h b/util/config_file.h
|
||||||
index 44ac036b..1e59ab07 100644
|
index c7c9a0a4..e3aa15b0 100644
|
||||||
--- a/util/config_file.h
|
--- a/util/config_file.h
|
||||||
+++ b/util/config_file.h
|
+++ b/util/config_file.h
|
||||||
@@ -311,6 +311,8 @@ struct config_file {
|
@@ -285,6 +285,8 @@ struct config_file {
|
||||||
int harden_unknown_additional;
|
int harden_algo_downgrade;
|
||||||
/** use 0x20 bits in query as random ID bits */
|
/** use 0x20 bits in query as random ID bits */
|
||||||
int use_caps_bits_for_id;
|
int use_caps_bits_for_id;
|
||||||
+ /** ASN: enable AAAA filter? */
|
+ /** ASN: enable AAAA filter? */
|
||||||
@@ -364,10 +364,10 @@ index 44ac036b..1e59ab07 100644
|
|||||||
struct config_strlist* caps_whitelist;
|
struct config_strlist* caps_whitelist;
|
||||||
/** strip away these private addrs from answers, no DNS Rebinding */
|
/** strip away these private addrs from answers, no DNS Rebinding */
|
||||||
diff --git a/util/configlexer.lex b/util/configlexer.lex
|
diff --git a/util/configlexer.lex b/util/configlexer.lex
|
||||||
index bc258673..76aab170 100644
|
index 34a0e5dd..c890be2a 100644
|
||||||
--- a/util/configlexer.lex
|
--- a/util/configlexer.lex
|
||||||
+++ b/util/configlexer.lex
|
+++ b/util/configlexer.lex
|
||||||
@@ -327,6 +327,7 @@ use-caps-for-id{COLON} { YDVAR(1, VAR_USE_CAPS_FOR_ID) }
|
@@ -317,6 +317,7 @@ use-caps-for-id{COLON} { YDVAR(1, VAR_USE_CAPS_FOR_ID) }
|
||||||
caps-whitelist{COLON} { YDVAR(1, VAR_CAPS_WHITELIST) }
|
caps-whitelist{COLON} { YDVAR(1, VAR_CAPS_WHITELIST) }
|
||||||
caps-exempt{COLON} { YDVAR(1, VAR_CAPS_WHITELIST) }
|
caps-exempt{COLON} { YDVAR(1, VAR_CAPS_WHITELIST) }
|
||||||
unwanted-reply-threshold{COLON} { YDVAR(1, VAR_UNWANTED_REPLY_THRESHOLD) }
|
unwanted-reply-threshold{COLON} { YDVAR(1, VAR_UNWANTED_REPLY_THRESHOLD) }
|
||||||
@@ -376,10 +376,10 @@ index bc258673..76aab170 100644
|
|||||||
private-domain{COLON} { YDVAR(1, VAR_PRIVATE_DOMAIN) }
|
private-domain{COLON} { YDVAR(1, VAR_PRIVATE_DOMAIN) }
|
||||||
prefetch-key{COLON} { YDVAR(1, VAR_PREFETCH_KEY) }
|
prefetch-key{COLON} { YDVAR(1, VAR_PREFETCH_KEY) }
|
||||||
diff --git a/util/configparser.y b/util/configparser.y
|
diff --git a/util/configparser.y b/util/configparser.y
|
||||||
index 82e1d878..dc19bed5 100644
|
index d4f965f9..8cc237c6 100644
|
||||||
--- a/util/configparser.y
|
--- a/util/configparser.y
|
||||||
+++ b/util/configparser.y
|
+++ b/util/configparser.y
|
||||||
@@ -100,6 +100,7 @@ extern struct config_parser_state* cfg_parser;
|
@@ -97,6 +97,7 @@ extern struct config_parser_state* cfg_parser;
|
||||||
%token VAR_STATISTICS_CUMULATIVE VAR_OUTGOING_PORT_PERMIT
|
%token VAR_STATISTICS_CUMULATIVE VAR_OUTGOING_PORT_PERMIT
|
||||||
%token VAR_OUTGOING_PORT_AVOID VAR_DLV_ANCHOR_FILE VAR_DLV_ANCHOR
|
%token VAR_OUTGOING_PORT_AVOID VAR_DLV_ANCHOR_FILE VAR_DLV_ANCHOR
|
||||||
%token VAR_NEG_CACHE_SIZE VAR_HARDEN_REFERRAL_PATH VAR_PRIVATE_ADDRESS
|
%token VAR_NEG_CACHE_SIZE VAR_HARDEN_REFERRAL_PATH VAR_PRIVATE_ADDRESS
|
||||||
@@ -387,7 +387,7 @@ index 82e1d878..dc19bed5 100644
|
|||||||
%token VAR_PRIVATE_DOMAIN VAR_REMOTE_CONTROL VAR_CONTROL_ENABLE
|
%token VAR_PRIVATE_DOMAIN VAR_REMOTE_CONTROL VAR_CONTROL_ENABLE
|
||||||
%token VAR_CONTROL_INTERFACE VAR_CONTROL_PORT VAR_SERVER_KEY_FILE
|
%token VAR_CONTROL_INTERFACE VAR_CONTROL_PORT VAR_SERVER_KEY_FILE
|
||||||
%token VAR_SERVER_CERT_FILE VAR_CONTROL_KEY_FILE VAR_CONTROL_CERT_FILE
|
%token VAR_SERVER_CERT_FILE VAR_CONTROL_KEY_FILE VAR_CONTROL_CERT_FILE
|
||||||
@@ -276,6 +277,7 @@ content_server: server_num_threads | server_verbosity | server_port |
|
@@ -247,6 +248,7 @@ content_server: server_num_threads | server_verbosity | server_port |
|
||||||
server_dlv_anchor_file | server_dlv_anchor | server_neg_cache_size |
|
server_dlv_anchor_file | server_dlv_anchor | server_neg_cache_size |
|
||||||
server_harden_referral_path | server_private_address |
|
server_harden_referral_path | server_private_address |
|
||||||
server_private_domain | server_extended_statistics |
|
server_private_domain | server_extended_statistics |
|
||||||
@@ -395,7 +395,7 @@ index 82e1d878..dc19bed5 100644
|
|||||||
server_local_data_ptr | server_jostle_timeout |
|
server_local_data_ptr | server_jostle_timeout |
|
||||||
server_unwanted_reply_threshold | server_log_time_ascii |
|
server_unwanted_reply_threshold | server_log_time_ascii |
|
||||||
server_domain_insecure | server_val_sig_skew_min |
|
server_domain_insecure | server_val_sig_skew_min |
|
||||||
@@ -1932,6 +1934,15 @@ server_caps_whitelist: VAR_CAPS_WHITELIST STRING_ARG
|
@@ -1754,6 +1756,15 @@ server_caps_whitelist: VAR_CAPS_WHITELIST STRING_ARG
|
||||||
yyerror("out of memory");
|
yyerror("out of memory");
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|||||||
@@ -1,24 +1,21 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
LIBEXPAT_FNAME=expat-2.7.0
|
|
||||||
LIBEXPAT_VERSION_DIR=R_2_7_0
|
|
||||||
|
|
||||||
echo "Downloading Expat"
|
echo "Downloading Expat"
|
||||||
if ! curl -L -k -s -o $LIBEXPAT_FNAME.tar.gz https://github.com/libexpat/libexpat/releases/download/$LIBEXPAT_VERSION_DIR/$LIBEXPAT_FNAME.tar.gz;
|
if ! curl -L -k -s -o expat-2.2.9.tar.gz https://github.com/libexpat/libexpat/releases/download/R_2_2_9/expat-2.2.9.tar.gz;
|
||||||
then
|
then
|
||||||
echo "Failed to download Expat"
|
echo "Failed to download Expat"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "Unpacking Expat"
|
echo "Unpacking Expat"
|
||||||
rm -rf ./$LIBEXPAT_FNAME
|
rm -rf ./expat-2.2.9
|
||||||
if ! tar -xf $LIBEXPAT_FNAME.tar.gz;
|
if ! tar -xf expat-2.2.9.tar.gz;
|
||||||
then
|
then
|
||||||
echo "Failed to unpack Expat"
|
echo "Failed to unpack Expat"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
cd $LIBEXPAT_FNAME || exit 1
|
cd expat-2.2.9 || exit 1
|
||||||
|
|
||||||
echo "Configuring Expat"
|
echo "Configuring Expat"
|
||||||
if ! ./configure --build="$AUTOTOOLS_BUILD" --host="$AUTOTOOLS_HOST" --prefix="$ANDROID_PREFIX"; then
|
if ! ./configure --build="$AUTOTOOLS_BUILD" --host="$AUTOTOOLS_HOST" --prefix="$ANDROID_PREFIX"; then
|
||||||
|
|||||||
@@ -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;
|
|
||||||
@@ -1,32 +1,28 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
LIBEXPAT_FNAME=expat-2.7.0
|
|
||||||
LIBEXPAT_VERSION_DIR=R_2_7_0
|
|
||||||
|
|
||||||
echo "Downloading Expat"
|
echo "Downloading Expat"
|
||||||
if ! curl -L -k -s -o $LIBEXPAT_FNAME.tar.gz https://github.com/libexpat/libexpat/releases/download/$LIBEXPAT_VERSION_DIR/$LIBEXPAT_FNAME.tar.gz;
|
if ! curl -L -k -s -o expat-2.2.9.tar.gz https://github.com/libexpat/libexpat/releases/download/R_2_2_9/expat-2.2.9.tar.gz;
|
||||||
then
|
then
|
||||||
echo "Failed to download Expat"
|
echo "Failed to download Expat"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "Unpacking Expat"
|
echo "Unpacking Expat"
|
||||||
rm -rf ./$LIBEXPAT_FNAME
|
rm -rf ./expat-2.2.9
|
||||||
if ! tar -xf $LIBEXPAT_FNAME.tar.gz;
|
if ! tar -xf expat-2.2.9.tar.gz;
|
||||||
then
|
then
|
||||||
echo "Failed to unpack Expat"
|
echo "Failed to unpack Expat"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
cd $LIBEXPAT_FNAME || exit 1
|
cd expat-2.2.9 || exit 1
|
||||||
|
|
||||||
export PKG_CONFIG_PATH="$IOS_PREFIX/lib/pkgconfig"
|
export PKG_CONFIG_PATH="$IOS_PREFIX/lib/pkgconfig"
|
||||||
|
|
||||||
echo "Configuring Expat"
|
echo "Configuring Expat"
|
||||||
if ! ./configure --without-tests \
|
if ! ./configure \
|
||||||
--build="$AUTOTOOLS_BUILD" --host="$AUTOTOOLS_HOST" \
|
--build="$AUTOTOOLS_BUILD" --host="$AUTOTOOLS_HOST" \
|
||||||
--prefix="$IOS_PREFIX" ;
|
--prefix="$IOS_PREFIX" ; then
|
||||||
then
|
|
||||||
echo "Error: Failed to configure Expat"
|
echo "Error: Failed to configure Expat"
|
||||||
cat config.log
|
cat config.log
|
||||||
exit 1
|
exit 1
|
||||||
|
|||||||
@@ -1,22 +1,21 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
OPENSSL_VERSION=1.1.1d
|
|
||||||
|
|
||||||
echo "Downloading OpenSSL"
|
echo "Downloading OpenSSL"
|
||||||
if ! curl -L -k -s -o openssl-$OPENSSL_VERSION.tar.gz https://www.openssl.org/source/openssl-$OPENSSL_VERSION.tar.gz;
|
if ! curl -L -k -s -o openssl-1.1.1d.tar.gz https://www.openssl.org/source/openssl-1.1.1d.tar.gz;
|
||||||
then
|
then
|
||||||
echo "Failed to download OpenSSL"
|
echo "Failed to download OpenSSL"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "Unpacking OpenSSL"
|
echo "Unpacking OpenSSL"
|
||||||
rm -rf ./openssl-$OPENSSL_VERSION
|
rm -rf ./openssl-1.1.1d
|
||||||
if ! tar -xf openssl-$OPENSSL_VERSION.tar.gz;
|
if ! tar -xf openssl-1.1.1d.tar.gz;
|
||||||
then
|
then
|
||||||
echo "Failed to unpack OpenSSL"
|
echo "Failed to unpack OpenSSL"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
cd openssl-$OPENSSL_VERSION || exit 1
|
cd openssl-1.1.1d || exit 1
|
||||||
|
|
||||||
if ! cp ../contrib/ios/15-ios.conf Configurations/; then
|
if ! cp ../contrib/ios/15-ios.conf Configurations/; then
|
||||||
echo "Failed to copy OpenSSL ios config"
|
echo "Failed to copy OpenSSL ios config"
|
||||||
@@ -28,8 +27,7 @@ fi
|
|||||||
# Also see https://github.com/openssl/openssl/issues/7607.
|
# Also see https://github.com/openssl/openssl/issues/7607.
|
||||||
if ! patch -u -p0 < ../contrib/ios/openssl.patch; then
|
if ! patch -u -p0 < ../contrib/ios/openssl.patch; then
|
||||||
echo "Failed to patch OpenSSL"
|
echo "Failed to patch OpenSSL"
|
||||||
# the partial patch may be useful.
|
exit 1
|
||||||
#exit 1
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "Configuring OpenSSL"
|
echo "Configuring OpenSSL"
|
||||||
|
|||||||
@@ -175,7 +175,6 @@ fi
|
|||||||
# For example, remove 4.3, 6.2, and 6.1 if they are not installed. We go back to
|
# For example, remove 4.3, 6.2, and 6.1 if they are not installed. We go back to
|
||||||
# the 1.0 SDKs because Apple WatchOS uses low numbers, like 2.0 and 2.1.
|
# the 1.0 SDKs because Apple WatchOS uses low numbers, like 2.0 and 2.1.
|
||||||
XCODE_SDK=
|
XCODE_SDK=
|
||||||
if test -z "$SDK_VERSION"; then
|
|
||||||
for i in $(seq -f "%.1f" 30.0 -0.1 1.0)
|
for i in $(seq -f "%.1f" 30.0 -0.1 1.0)
|
||||||
do
|
do
|
||||||
if [ -d "$XCODE_DEVELOPER_SDK/Developer/SDKs/$IOS_SDK$i.sdk" ]; then
|
if [ -d "$XCODE_DEVELOPER_SDK/Developer/SDKs/$IOS_SDK$i.sdk" ]; then
|
||||||
@@ -183,10 +182,6 @@ do
|
|||||||
break
|
break
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
else
|
|
||||||
i="$SDK_VERSION"
|
|
||||||
XCODE_SDK="$IOS_SDK$i.sdk"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Error checking
|
# Error checking
|
||||||
if [ -z "$XCODE_SDK" ]; then
|
if [ -z "$XCODE_SDK" ]; then
|
||||||
|
|||||||
@@ -22,13 +22,4 @@ pidfile=${unbound_pidfile:-"/usr/local/etc/unbound/unbound.pid"}
|
|||||||
command_args=${unbound_flags:-"-c /usr/local/etc/unbound/unbound.conf"}
|
command_args=${unbound_flags:-"-c /usr/local/etc/unbound/unbound.conf"}
|
||||||
extra_commands="reload"
|
extra_commands="reload"
|
||||||
|
|
||||||
if test "$1" = "stop" ; then
|
|
||||||
run_rc_command "$1"
|
|
||||||
ret=$?
|
|
||||||
if test $ret -eq 0; then
|
|
||||||
rm -f "$pidfile"
|
|
||||||
fi
|
|
||||||
exit $ret
|
|
||||||
fi
|
|
||||||
|
|
||||||
run_rc_command "$1"
|
run_rc_command "$1"
|
||||||
|
|||||||
@@ -75,7 +75,6 @@ stop() {
|
|||||||
retval=$?
|
retval=$?
|
||||||
echo
|
echo
|
||||||
[ $retval -eq 0 ] && rm -f $lockfile
|
[ $retval -eq 0 ] && rm -f $lockfile
|
||||||
[ $retval -eq 0 ] && rm -f $pidfile
|
|
||||||
if egrep -q '^/[^[:space:]]+[[:space:]]+'${rootdir}'/dev/log' /proc/mounts; then
|
if egrep -q '^/[^[:space:]]+[[:space:]]+'${rootdir}'/dev/log' /proc/mounts; then
|
||||||
umount ${rootdir}/dev/log >/dev/null 2>&1
|
umount ${rootdir}/dev/log >/dev/null 2>&1
|
||||||
fi;
|
fi;
|
||||||
|
|||||||
@@ -58,7 +58,6 @@ stop() {
|
|||||||
killproc -p $pidfile unbound
|
killproc -p $pidfile unbound
|
||||||
retval=$?
|
retval=$?
|
||||||
[ $retval -eq 0 ] && rm -f $lockfile
|
[ $retval -eq 0 ] && rm -f $lockfile
|
||||||
[ $retval -eq 0 ] && rm -f $pidfile
|
|
||||||
for mountfile in /dev/log /dev/urandom /etc/localtime /etc/resolv.conf /var/run/unbound
|
for mountfile in /dev/log /dev/urandom /etc/localtime /etc/resolv.conf /var/run/unbound
|
||||||
do
|
do
|
||||||
if egrep -q '^/[^[:space:]]+[[:space:]]+'${rootdir}''${mountfile}'' /proc/mounts; then
|
if egrep -q '^/[^[:space:]]+[[:space:]]+'${rootdir}''${mountfile}'' /proc/mounts; then
|
||||||
|
|||||||
@@ -1,140 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
#
|
|
||||||
# unbound This shell script takes care of starting and stopping
|
|
||||||
# unbound (DNS server).
|
|
||||||
#
|
|
||||||
# chkconfig: - 14 86
|
|
||||||
# description: unbound is a Domain Name Server (DNS) \
|
|
||||||
# that is used to resolve host names to IP addresses.
|
|
||||||
|
|
||||||
### BEGIN INIT INFO
|
|
||||||
# Provides: $named unbound
|
|
||||||
# Required-Start: $network $local_fs
|
|
||||||
# Required-Stop: $network $local_fs
|
|
||||||
# Should-Start: $syslog
|
|
||||||
# Should-Stop: $syslog
|
|
||||||
# Short-Description: unbound recursive Domain Name Server.
|
|
||||||
# Description: unbound is a Domain Name Server (DNS)
|
|
||||||
# that is used to resolve host names to IP addresses.
|
|
||||||
### END INIT INFO
|
|
||||||
|
|
||||||
# Source function library.
|
|
||||||
. /etc/init.d/functions
|
|
||||||
|
|
||||||
exec="/usr/sbin/unbound"
|
|
||||||
prog="unbound"
|
|
||||||
config="/etc/unbound/unbound.conf"
|
|
||||||
pidfile="/var/unbound/unbound.pid"
|
|
||||||
rootdir="/var/unbound"
|
|
||||||
|
|
||||||
[ -e /etc/sysconfig/$prog ] && . /etc/sysconfig/$prog
|
|
||||||
|
|
||||||
lockfile=/var/lock/subsys/$prog
|
|
||||||
|
|
||||||
start() {
|
|
||||||
[ -x $exec ] || exit 5
|
|
||||||
[ -f $config ] || exit 6
|
|
||||||
echo -n $"Starting $prog: "
|
|
||||||
|
|
||||||
# setup root jail
|
|
||||||
if [ -s /etc/localtime ]; then
|
|
||||||
[ -d ${rootdir}/etc ] || mkdir -p ${rootdir}/etc ;
|
|
||||||
if [ ! -e ${rootdir}/etc/localtime ] || ! /usr/bin/cmp -s /etc/localtime ${rootdir}/etc/localtime; then
|
|
||||||
cp -fp /etc/localtime ${rootdir}/etc/localtime
|
|
||||||
fi;
|
|
||||||
fi;
|
|
||||||
if [ -s /etc/resolv.conf ]; then
|
|
||||||
[ -d ${rootdir}/etc ] || mkdir -p ${rootdir}/etc ;
|
|
||||||
if [ ! -e ${rootdir}/etc/resolv.conf ] || ! /usr/bin/cmp -s /etc/resolv.conf ${rootdir}/etc/resolv.conf; then
|
|
||||||
cp -fp /etc/resolv.conf ${rootdir}/etc/resolv.conf
|
|
||||||
fi;
|
|
||||||
fi;
|
|
||||||
if ! egrep -q '^/[^[:space:]]+[[:space:]]+'${rootdir}'/dev/log' /proc/mounts; then
|
|
||||||
[ -d ${rootdir}/dev ] || mkdir -p ${rootdir}/dev ;
|
|
||||||
[ -e ${rootdir}/dev/log ] || touch ${rootdir}/dev/log
|
|
||||||
mount --bind -n /dev/log ${rootdir}/dev/log >/dev/null 2>&1;
|
|
||||||
fi;
|
|
||||||
if ! egrep -q '^/[^[:space:]]+[[:space:]]+'${rootdir}'/dev/random' /proc/mounts; then
|
|
||||||
[ -d ${rootdir}/dev ] || mkdir -p ${rootdir}/dev ;
|
|
||||||
[ -e ${rootdir}/dev/random ] || touch ${rootdir}/dev/random
|
|
||||||
mount --bind -n /dev/random ${rootdir}/dev/random >/dev/null 2>&1;
|
|
||||||
fi;
|
|
||||||
|
|
||||||
# if not running, start it up here
|
|
||||||
daemonize $exec
|
|
||||||
retval=$?
|
|
||||||
echo
|
|
||||||
[ $retval -eq 0 ] && touch $lockfile
|
|
||||||
return $retval
|
|
||||||
}
|
|
||||||
|
|
||||||
stop() {
|
|
||||||
echo -n $"Stopping $prog: "
|
|
||||||
# stop it here, often "killproc $prog"
|
|
||||||
killproc $prog
|
|
||||||
retval=$?
|
|
||||||
echo
|
|
||||||
[ $retval -eq 0 ] && rm -f $lockfile
|
|
||||||
[ $retval -eq 0 ] && rm -f $pidfile
|
|
||||||
if egrep -q '^/[^[:space:]]+[[:space:]]+'${rootdir}'/dev/log' /proc/mounts; then
|
|
||||||
umount ${rootdir}/dev/log >/dev/null 2>&1
|
|
||||||
fi;
|
|
||||||
if egrep -q '^/[^[:space:]]+[[:space:]]+'${rootdir}'/dev/random' /proc/mounts; then
|
|
||||||
umount ${rootdir}/dev/random >/dev/null 2>&1
|
|
||||||
fi;
|
|
||||||
return $retval
|
|
||||||
}
|
|
||||||
|
|
||||||
restart() {
|
|
||||||
stop
|
|
||||||
start
|
|
||||||
}
|
|
||||||
|
|
||||||
reload() {
|
|
||||||
kill -HUP `cat $pidfile`
|
|
||||||
}
|
|
||||||
|
|
||||||
force_reload() {
|
|
||||||
restart
|
|
||||||
}
|
|
||||||
|
|
||||||
rh_status() {
|
|
||||||
# run checks to determine if the service is running or use generic status
|
|
||||||
status $prog
|
|
||||||
}
|
|
||||||
|
|
||||||
rh_status_q() {
|
|
||||||
rh_status -p $pidfile >/dev/null 2>&1
|
|
||||||
}
|
|
||||||
|
|
||||||
case "$1" in
|
|
||||||
start)
|
|
||||||
rh_status_q && exit 0
|
|
||||||
$1
|
|
||||||
;;
|
|
||||||
stop)
|
|
||||||
rh_status_q || exit 0
|
|
||||||
$1
|
|
||||||
;;
|
|
||||||
restart)
|
|
||||||
$1
|
|
||||||
;;
|
|
||||||
reload)
|
|
||||||
rh_status_q || exit 7
|
|
||||||
$1
|
|
||||||
;;
|
|
||||||
force-reload)
|
|
||||||
force_reload
|
|
||||||
;;
|
|
||||||
status)
|
|
||||||
rh_status
|
|
||||||
;;
|
|
||||||
condrestart|try-restart)
|
|
||||||
rh_status_q || exit 0
|
|
||||||
restart
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
echo $"Usage: $0 {start|stop|status|restart|condrestart|try-restart|reload|force-reload}"
|
|
||||||
exit 2
|
|
||||||
esac
|
|
||||||
exit $?
|
|
||||||
@@ -38,18 +38,13 @@
|
|||||||
; - `LockPersonality=yes` locks down the personality system call so that the
|
; - `LockPersonality=yes` locks down the personality system call so that the
|
||||||
; kernel execution domain may not be changed from the default.
|
; kernel execution domain may not be changed from the default.
|
||||||
;
|
;
|
||||||
; - With /etc/systemd/network/*.network a setting to make sure the network
|
|
||||||
; is not considered online too early, can reduce network unreachable
|
|
||||||
; errors on server start:
|
|
||||||
; [Link]
|
|
||||||
; RequiredForOnline=routable
|
|
||||||
;
|
;
|
||||||
[Unit]
|
[Unit]
|
||||||
Description=Validating, recursive, and caching DNS resolver
|
Description=Validating, recursive, and caching DNS resolver
|
||||||
Documentation=man:unbound(8)
|
Documentation=man:unbound(8)
|
||||||
After=network-online.target
|
After=network-online.target
|
||||||
Wants=network-online.target
|
|
||||||
Before=nss-lookup.target
|
Before=nss-lookup.target
|
||||||
|
Wants=network-online.target nss-lookup.target
|
||||||
|
|
||||||
[Install]
|
[Install]
|
||||||
WantedBy=multi-user.target
|
WantedBy=multi-user.target
|
||||||
@@ -59,7 +54,7 @@ ExecReload=+/bin/kill -HUP $MAINPID
|
|||||||
ExecStart=@UNBOUND_SBIN_DIR@/unbound -d -p
|
ExecStart=@UNBOUND_SBIN_DIR@/unbound -d -p
|
||||||
NotifyAccess=main
|
NotifyAccess=main
|
||||||
Type=notify
|
Type=notify
|
||||||
CapabilityBoundingSet=CAP_NET_BIND_SERVICE CAP_SETGID CAP_SETUID CAP_SYS_CHROOT CAP_SYS_RESOURCE CAP_NET_ADMIN
|
CapabilityBoundingSet=CAP_NET_BIND_SERVICE CAP_SETGID CAP_SETUID CAP_SYS_CHROOT CAP_SYS_RESOURCE CAP_NET_RAW
|
||||||
MemoryDenyWriteExecute=true
|
MemoryDenyWriteExecute=true
|
||||||
NoNewPrivileges=true
|
NoNewPrivileges=true
|
||||||
PrivateDevices=true
|
PrivateDevices=true
|
||||||
|
|||||||
@@ -14,8 +14,8 @@
|
|||||||
[Unit]
|
[Unit]
|
||||||
Description=Validating, recursive, and caching DNS resolver
|
Description=Validating, recursive, and caching DNS resolver
|
||||||
Documentation=man:unbound(8)
|
Documentation=man:unbound(8)
|
||||||
After=network-online.target
|
After=network.target
|
||||||
Before=nss-lookup.target
|
Before=network-online.target nss-lookup.target
|
||||||
Wants=nss-lookup.target
|
Wants=nss-lookup.target
|
||||||
|
|
||||||
[Install]
|
[Install]
|
||||||
@@ -26,7 +26,7 @@ ExecReload=+/bin/kill -HUP $MAINPID
|
|||||||
ExecStart=@UNBOUND_SBIN_DIR@/unbound -d -p
|
ExecStart=@UNBOUND_SBIN_DIR@/unbound -d -p
|
||||||
NotifyAccess=main
|
NotifyAccess=main
|
||||||
Type=notify
|
Type=notify
|
||||||
CapabilityBoundingSet=CAP_NET_BIND_SERVICE CAP_SETGID CAP_SETUID CAP_SYS_CHROOT CAP_SYS_RESOURCE CAP_NET_ADMIN
|
CapabilityBoundingSet=CAP_NET_BIND_SERVICE CAP_SETGID CAP_SETUID CAP_SYS_CHROOT CAP_SYS_RESOURCE CAP_NET_RAW
|
||||||
MemoryDenyWriteExecute=true
|
MemoryDenyWriteExecute=true
|
||||||
NoNewPrivileges=true
|
NoNewPrivileges=true
|
||||||
PrivateDevices=true
|
PrivateDevices=true
|
||||||
|
|||||||
+13
-19
@@ -109,8 +109,6 @@ parse_acl_access(const char* str, enum acl_access* control)
|
|||||||
*control = acl_allow_snoop;
|
*control = acl_allow_snoop;
|
||||||
else if(strcmp(str, "allow_setrd") == 0)
|
else if(strcmp(str, "allow_setrd") == 0)
|
||||||
*control = acl_allow_setrd;
|
*control = acl_allow_setrd;
|
||||||
else if (strcmp(str, "allow_cookie") == 0)
|
|
||||||
*control = acl_allow_cookie;
|
|
||||||
else {
|
else {
|
||||||
log_err("access control type %s unknown", str);
|
log_err("access control type %s unknown", str);
|
||||||
return 0;
|
return 0;
|
||||||
@@ -221,9 +219,7 @@ acl_interface_insert(struct acl_list* acl_interface,
|
|||||||
struct sockaddr_storage* addr, socklen_t addrlen,
|
struct sockaddr_storage* addr, socklen_t addrlen,
|
||||||
enum acl_access control)
|
enum acl_access control)
|
||||||
{
|
{
|
||||||
struct acl_addr* node = acl_find_or_create(acl_interface, addr, addrlen, control);
|
return acl_find_or_create(acl_interface, addr, addrlen, control);
|
||||||
node->is_interface = 1;
|
|
||||||
return node;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** apply acl_tag string */
|
/** apply acl_tag string */
|
||||||
@@ -553,6 +549,17 @@ acl_list_apply_cfg(struct acl_list* acl, struct config_file* cfg,
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
acl_interface_compare(const void* k1, const void* k2)
|
||||||
|
{
|
||||||
|
struct addr_tree_node* n1 = (struct addr_tree_node*)k1;
|
||||||
|
struct addr_tree_node* n2 = (struct addr_tree_node*)k2;
|
||||||
|
return sockaddr_cmp(&n1->addr, n1->addrlen, &n2->addr,
|
||||||
|
n2->addrlen);
|
||||||
|
/* We don't care about comparing node->net. All addresses in the
|
||||||
|
* acl_interface tree have either 32 (ipv4) or 128 (ipv6). */
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
acl_interface_init(struct acl_list* acl_interface)
|
acl_interface_init(struct acl_list* acl_interface)
|
||||||
{
|
{
|
||||||
@@ -807,23 +814,10 @@ log_acl_action(const char* action, struct sockaddr_storage* addr,
|
|||||||
addr_to_str(&acladdr->node.addr, acladdr->node.addrlen,
|
addr_to_str(&acladdr->node.addr, acladdr->node.addrlen,
|
||||||
n, sizeof(n));
|
n, sizeof(n));
|
||||||
verbose(VERB_ALGO, "%s query from %s port %d because of "
|
verbose(VERB_ALGO, "%s query from %s port %d because of "
|
||||||
"%s/%d %s%s", action, a, (int)port, n,
|
"%s/%d %s", action, a, (int)port, n, acladdr->node.net,
|
||||||
acladdr->node.net,
|
|
||||||
acladdr->is_interface?"(ACL on interface IP) ":"",
|
|
||||||
acl_access_to_str(acl));
|
acl_access_to_str(acl));
|
||||||
} else {
|
} else {
|
||||||
verbose(VERB_ALGO, "%s query from %s port %d", action, a,
|
verbose(VERB_ALGO, "%s query from %s port %d", action, a,
|
||||||
(int)port);
|
(int)port);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void acl_list_swap_tree(struct acl_list* acl, struct acl_list* data)
|
|
||||||
{
|
|
||||||
/* swap tree and region */
|
|
||||||
rbtree_type oldtree = acl->tree;
|
|
||||||
struct regional* oldregion = acl->region;
|
|
||||||
acl->tree = data->tree;
|
|
||||||
acl->region = data->region;
|
|
||||||
data->tree = oldtree;
|
|
||||||
data->region = oldregion;
|
|
||||||
}
|
|
||||||
|
|||||||
+5
-16
@@ -64,12 +64,8 @@ enum acl_access {
|
|||||||
acl_allow,
|
acl_allow,
|
||||||
/** allow full access for all queries, recursion and cache snooping */
|
/** allow full access for all queries, recursion and cache snooping */
|
||||||
acl_allow_snoop,
|
acl_allow_snoop,
|
||||||
/** allow full access for recursion queries and set RD flag regardless
|
/** allow full access for recursion queries and set RD flag regardless of request */
|
||||||
* of request */
|
acl_allow_setrd
|
||||||
acl_allow_setrd,
|
|
||||||
/** allow full access for recursion (+RD) queries if valid cookie
|
|
||||||
* present or stateful transport */
|
|
||||||
acl_allow_cookie
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -107,8 +103,6 @@ struct acl_addr {
|
|||||||
struct config_strlist** tag_datas;
|
struct config_strlist** tag_datas;
|
||||||
/** size of the tag_datas array */
|
/** size of the tag_datas array */
|
||||||
size_t tag_datas_size;
|
size_t tag_datas_size;
|
||||||
/* If the acl node is for an interface */
|
|
||||||
int is_interface;
|
|
||||||
/* view element, NULL if none */
|
/* view element, NULL if none */
|
||||||
struct view* view;
|
struct view* view;
|
||||||
};
|
};
|
||||||
@@ -149,6 +143,9 @@ acl_interface_insert(struct acl_list* acl_interface,
|
|||||||
int acl_list_apply_cfg(struct acl_list* acl, struct config_file* cfg,
|
int acl_list_apply_cfg(struct acl_list* acl, struct config_file* cfg,
|
||||||
struct views* v);
|
struct views* v);
|
||||||
|
|
||||||
|
/** compare ACL interface "addr_tree" nodes (+port) */
|
||||||
|
int acl_interface_compare(const void* k1, const void* k2);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialise (also clean) the acl_interface struct.
|
* Initialise (also clean) the acl_interface struct.
|
||||||
* @param acl_interface: where to store.
|
* @param acl_interface: where to store.
|
||||||
@@ -201,12 +198,4 @@ const char* acl_access_to_str(enum acl_access acl);
|
|||||||
void log_acl_action(const char* action, struct sockaddr_storage* addr,
|
void log_acl_action(const char* action, struct sockaddr_storage* addr,
|
||||||
socklen_t addrlen, enum acl_access acl, struct acl_addr* acladdr);
|
socklen_t addrlen, enum acl_access acl, struct acl_addr* acladdr);
|
||||||
|
|
||||||
/**
|
|
||||||
* Swap internal tree with preallocated entries.
|
|
||||||
* @param acl: the acl structure.
|
|
||||||
* @param data: the data structure used to take elements from. This contains
|
|
||||||
* the old elements on return.
|
|
||||||
*/
|
|
||||||
void acl_list_swap_tree(struct acl_list* acl, struct acl_list* data);
|
|
||||||
|
|
||||||
#endif /* DAEMON_ACL_LIST_H */
|
#endif /* DAEMON_ACL_LIST_H */
|
||||||
|
|||||||
+119
-270
@@ -62,231 +62,84 @@
|
|||||||
#include "sldns/wire2str.h"
|
#include "sldns/wire2str.h"
|
||||||
#include "sldns/str2wire.h"
|
#include "sldns/str2wire.h"
|
||||||
|
|
||||||
static void spool_txt_printf(struct config_strlist_head* txt,
|
|
||||||
const char* format, ...) ATTR_FORMAT(printf, 2, 3);
|
|
||||||
|
|
||||||
/** Append to strlist at end, and log error if out of memory. */
|
|
||||||
static void
|
|
||||||
spool_txt_string(struct config_strlist_head* txt, char* str)
|
|
||||||
{
|
|
||||||
if(!cfg_strlist_append(txt, strdup(str))) {
|
|
||||||
log_err("out of memory in spool text");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Spool txt to spool list. */
|
|
||||||
static void
|
|
||||||
spool_txt_vmsg(struct config_strlist_head* txt, const char* format,
|
|
||||||
va_list args)
|
|
||||||
{
|
|
||||||
char msg[65535];
|
|
||||||
vsnprintf(msg, sizeof(msg), format, args);
|
|
||||||
spool_txt_string(txt, msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Print item to spool list. On alloc failure the list is as before. */
|
|
||||||
static void
|
|
||||||
spool_txt_printf(struct config_strlist_head* txt, const char* format, ...)
|
|
||||||
{
|
|
||||||
va_list args;
|
|
||||||
va_start(args, format);
|
|
||||||
spool_txt_vmsg(txt, format, args);
|
|
||||||
va_end(args);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** dump one rrset zonefile line */
|
/** dump one rrset zonefile line */
|
||||||
static void
|
static int
|
||||||
dump_rrset_line(struct config_strlist_head* txt, struct ub_packed_rrset_key* k,
|
dump_rrset_line(RES* ssl, struct ub_packed_rrset_key* k, time_t now, size_t i)
|
||||||
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))) {
|
if(!packed_rr_to_string(k, i, now, s, sizeof(s))) {
|
||||||
spool_txt_string(txt, "BADRR\n");
|
return ssl_printf(ssl, "BADRR\n");
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
spool_txt_string(txt, s);
|
return ssl_printf(ssl, "%s", s);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** dump rrset key and data info */
|
/** dump rrset key and data info */
|
||||||
static void
|
static int
|
||||||
dump_rrset(struct config_strlist_head* txt, struct ub_packed_rrset_key* k,
|
dump_rrset(RES* ssl, struct ub_packed_rrset_key* k,
|
||||||
struct packed_rrset_data* d, time_t now)
|
struct packed_rrset_data* d, time_t now)
|
||||||
{
|
{
|
||||||
size_t i;
|
size_t i;
|
||||||
/* rd lock held by caller */
|
/* rd lock held by caller */
|
||||||
if(!k || !d) return;
|
if(!k || !d) return 1;
|
||||||
if(k->id == 0) return; /* deleted */
|
if(k->id == 0) return 1; /* deleted */
|
||||||
if(d->ttl < now) return; /* expired */
|
if(d->ttl < now) return 1; /* expired */
|
||||||
|
|
||||||
/* meta line */
|
/* meta line */
|
||||||
spool_txt_printf(txt, ";rrset%s " ARG_LL "d %u %u %d %d\n",
|
if(!ssl_printf(ssl, ";rrset%s " ARG_LL "d %u %u %d %d\n",
|
||||||
(k->rk.flags & PACKED_RRSET_NSEC_AT_APEX)?" nsec_apex":"",
|
(k->rk.flags & PACKED_RRSET_NSEC_AT_APEX)?" nsec_apex":"",
|
||||||
(long long)(d->ttl - now),
|
(long long)(d->ttl - now),
|
||||||
(unsigned)d->count, (unsigned)d->rrsig_count,
|
(unsigned)d->count, (unsigned)d->rrsig_count,
|
||||||
(int)d->trust, (int)d->security
|
(int)d->trust, (int)d->security
|
||||||
);
|
))
|
||||||
|
return 0;
|
||||||
for(i=0; i<d->count + d->rrsig_count; i++) {
|
for(i=0; i<d->count + d->rrsig_count; i++) {
|
||||||
dump_rrset_line(txt, k, now, i);
|
if(!dump_rrset_line(ssl, k, now, i))
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Spool strlist to the output. */
|
|
||||||
static int
|
|
||||||
spool_strlist(RES* ssl, struct config_strlist* list)
|
|
||||||
{
|
|
||||||
struct config_strlist* s;
|
|
||||||
for(s=list; s; s=s->next) {
|
|
||||||
if(!ssl_printf(ssl, "%s", s->str))
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** dump lruhash cache and call callback for every item. */
|
/** dump lruhash rrset cache */
|
||||||
static int
|
static int
|
||||||
dump_lruhash(struct lruhash* table,
|
dump_rrset_lruhash(RES* ssl, struct lruhash* h, time_t now)
|
||||||
void (*func)(struct lruhash_entry*, struct config_strlist_head*, void*),
|
|
||||||
RES* ssl, void* arg)
|
|
||||||
{
|
{
|
||||||
int just_started = 1;
|
struct lruhash_entry* e;
|
||||||
int not_done = 1;
|
/* lruhash already locked by caller */
|
||||||
hashvalue_type hash;
|
/* walk in order of lru; best first */
|
||||||
size_t num = 0; /* number of entries processed. */
|
for(e=h->lru_start; e; e = e->lru_next) {
|
||||||
size_t max = 2; /* number of entries after which it unlocks. */
|
lock_rw_rdlock(&e->lock);
|
||||||
struct config_strlist_head txt; /* Text strings spooled. */
|
if(!dump_rrset(ssl, (struct ub_packed_rrset_key*)e->key,
|
||||||
memset(&txt, 0, sizeof(txt));
|
(struct packed_rrset_data*)e->data, now)) {
|
||||||
|
lock_rw_unlock(&e->lock);
|
||||||
while(not_done) {
|
|
||||||
size_t i; /* hash bin. */
|
|
||||||
/* Process a number of items. */
|
|
||||||
num = 0;
|
|
||||||
lock_quick_lock(&table->lock);
|
|
||||||
if(just_started) {
|
|
||||||
i = 0;
|
|
||||||
} else {
|
|
||||||
i = hash&table->size_mask;
|
|
||||||
}
|
|
||||||
while(num < max) {
|
|
||||||
/* Process bin. */
|
|
||||||
int found = 0;
|
|
||||||
size_t num_bin = 0;
|
|
||||||
struct lruhash_bin* bin = &table->array[i];
|
|
||||||
struct lruhash_entry* e;
|
|
||||||
lock_quick_lock(&bin->lock);
|
|
||||||
for(e = bin->overflow_list; e; e = e->overflow_next) {
|
|
||||||
/* Entry e is locked by the func. */
|
|
||||||
func(e, &txt, arg);
|
|
||||||
num_bin++;
|
|
||||||
}
|
|
||||||
lock_quick_unlock(&bin->lock);
|
|
||||||
/* This addition of bin number of entries may take
|
|
||||||
* it over the max. */
|
|
||||||
num += num_bin;
|
|
||||||
|
|
||||||
/* Move to next bin. */
|
|
||||||
/* Find one with an entry, with a hash value, so we
|
|
||||||
* can continue from the hash value. The hash value
|
|
||||||
* can be indexed also if the array changes size. */
|
|
||||||
i++;
|
|
||||||
while(i < table->size) {
|
|
||||||
bin = &table->array[i];
|
|
||||||
lock_quick_lock(&bin->lock);
|
|
||||||
if(bin->overflow_list) {
|
|
||||||
hash = bin->overflow_list->hash;
|
|
||||||
lock_quick_unlock(&bin->lock);
|
|
||||||
found = 1;
|
|
||||||
just_started = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
lock_quick_unlock(&bin->lock);
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
if(!found) {
|
|
||||||
not_done = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
lock_quick_unlock(&table->lock);
|
|
||||||
/* Print the spooled items, that are collected while the
|
|
||||||
* locks are locked. The print happens while they are not
|
|
||||||
* locked. */
|
|
||||||
if(txt.first) {
|
|
||||||
if(!spool_strlist(ssl, txt.first)) {
|
|
||||||
config_delstrlist(txt.first);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
config_delstrlist(txt.first);
|
|
||||||
memset(&txt, 0, sizeof(txt));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* Print the final spooled items. */
|
|
||||||
if(txt.first) {
|
|
||||||
if(!spool_strlist(ssl, txt.first)) {
|
|
||||||
config_delstrlist(txt.first);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
config_delstrlist(txt.first);
|
lock_rw_unlock(&e->lock);
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** dump slabhash cache and call callback for every item. */
|
|
||||||
static int
|
|
||||||
dump_slabhash(struct slabhash* sh,
|
|
||||||
void (*func)(struct lruhash_entry*, struct config_strlist_head*, void*),
|
|
||||||
RES* ssl, void* arg)
|
|
||||||
{
|
|
||||||
/* Process a number of items at a time, then unlock the cache,
|
|
||||||
* so that ordinary processing can continue. Keep an iteration marker
|
|
||||||
* to continue the loop. That means the cache can change, items
|
|
||||||
* could be inserted and deleted. And, for example, the hash table
|
|
||||||
* can grow. */
|
|
||||||
size_t slab;
|
|
||||||
for(slab=0; slab<sh->size; slab++) {
|
|
||||||
if(!dump_lruhash(sh->array[slab], func, ssl, arg))
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Struct for dump information. */
|
|
||||||
struct dump_info {
|
|
||||||
/** The worker. */
|
|
||||||
struct worker* worker;
|
|
||||||
/** The printout connection. */
|
|
||||||
RES* ssl;
|
|
||||||
};
|
|
||||||
|
|
||||||
/** Dump the rrset cache entry */
|
|
||||||
static void
|
|
||||||
dump_rrset_entry(struct lruhash_entry* e, struct config_strlist_head* txt,
|
|
||||||
void* arg)
|
|
||||||
{
|
|
||||||
struct dump_info* dump_info = (struct dump_info*)arg;
|
|
||||||
lock_rw_rdlock(&e->lock);
|
|
||||||
dump_rrset(txt, (struct ub_packed_rrset_key*)e->key,
|
|
||||||
(struct packed_rrset_data*)e->data,
|
|
||||||
*dump_info->worker->env.now);
|
|
||||||
lock_rw_unlock(&e->lock);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** dump rrset cache */
|
/** dump rrset cache */
|
||||||
static int
|
static int
|
||||||
dump_rrset_cache(RES* ssl, struct worker* worker)
|
dump_rrset_cache(RES* ssl, struct worker* worker)
|
||||||
{
|
{
|
||||||
struct rrset_cache* r = worker->env.rrset_cache;
|
struct rrset_cache* r = worker->env.rrset_cache;
|
||||||
struct dump_info dump_info;
|
size_t slab;
|
||||||
dump_info.worker = worker;
|
|
||||||
dump_info.ssl = ssl;
|
|
||||||
if(!ssl_printf(ssl, "START_RRSET_CACHE\n")) return 0;
|
if(!ssl_printf(ssl, "START_RRSET_CACHE\n")) return 0;
|
||||||
if(!dump_slabhash(&r->table, &dump_rrset_entry, ssl, &dump_info))
|
for(slab=0; slab<r->table.size; slab++) {
|
||||||
return 0;
|
lock_quick_lock(&r->table.array[slab]->lock);
|
||||||
|
if(!dump_rrset_lruhash(ssl, r->table.array[slab],
|
||||||
|
*worker->env.now)) {
|
||||||
|
lock_quick_unlock(&r->table.array[slab]->lock);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
lock_quick_unlock(&r->table.array[slab]->lock);
|
||||||
|
}
|
||||||
return ssl_printf(ssl, "END_RRSET_CACHE\n");
|
return ssl_printf(ssl, "END_RRSET_CACHE\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
/** dump message to rrset reference */
|
/** dump message to rrset reference */
|
||||||
static void
|
static int
|
||||||
dump_msg_ref(struct config_strlist_head* txt, struct ub_packed_rrset_key* k)
|
dump_msg_ref(RES* ssl, struct ub_packed_rrset_key* k)
|
||||||
{
|
{
|
||||||
char* nm, *tp, *cl;
|
char* nm, *tp, *cl;
|
||||||
nm = sldns_wire2str_dname(k->rk.dname, k->rk.dname_len);
|
nm = sldns_wire2str_dname(k->rk.dname, k->rk.dname_len);
|
||||||
@@ -296,24 +149,30 @@ dump_msg_ref(struct config_strlist_head* txt, struct ub_packed_rrset_key* k)
|
|||||||
free(nm);
|
free(nm);
|
||||||
free(tp);
|
free(tp);
|
||||||
free(cl);
|
free(cl);
|
||||||
spool_txt_string(txt, "BADREF\n");
|
return ssl_printf(ssl, "BADREF\n");
|
||||||
return;
|
}
|
||||||
|
if(!ssl_printf(ssl, "%s %s %s %d\n", nm, cl, tp, (int)k->rk.flags)) {
|
||||||
|
free(nm);
|
||||||
|
free(tp);
|
||||||
|
free(cl);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
spool_txt_printf(txt, "%s %s %s %d\n", nm, cl, tp, (int)k->rk.flags);
|
|
||||||
free(nm);
|
free(nm);
|
||||||
free(tp);
|
free(tp);
|
||||||
free(cl);
|
free(cl);
|
||||||
|
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** dump message entry */
|
/** dump message entry */
|
||||||
static void
|
static int
|
||||||
dump_msg(struct config_strlist_head* txt, struct query_info* k,
|
dump_msg(RES* ssl, struct query_info* k, struct reply_info* d,
|
||||||
struct reply_info* d, time_t now)
|
time_t now)
|
||||||
{
|
{
|
||||||
size_t i;
|
size_t i;
|
||||||
char* nm, *tp, *cl;
|
char* nm, *tp, *cl;
|
||||||
if(!k || !d) return;
|
if(!k || !d) return 1;
|
||||||
if(d->ttl < now) return; /* expired */
|
if(d->ttl < now) return 1; /* expired */
|
||||||
|
|
||||||
nm = sldns_wire2str_dname(k->qname, k->qname_len);
|
nm = sldns_wire2str_dname(k->qname, k->qname_len);
|
||||||
tp = sldns_wire2str_type(k->qtype);
|
tp = sldns_wire2str_type(k->qtype);
|
||||||
@@ -322,35 +181,43 @@ dump_msg(struct config_strlist_head* txt, struct query_info* k,
|
|||||||
free(nm);
|
free(nm);
|
||||||
free(tp);
|
free(tp);
|
||||||
free(cl);
|
free(cl);
|
||||||
return; /* skip this entry */
|
return 1; /* skip this entry */
|
||||||
}
|
}
|
||||||
if(!rrset_array_lock(d->ref, d->rrset_count, now)) {
|
if(!rrset_array_lock(d->ref, d->rrset_count, now)) {
|
||||||
/* rrsets have timed out or do not exist */
|
/* rrsets have timed out or do not exist */
|
||||||
free(nm);
|
free(nm);
|
||||||
free(tp);
|
free(tp);
|
||||||
free(cl);
|
free(cl);
|
||||||
return; /* skip this entry */
|
return 1; /* skip this entry */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* meta line */
|
/* meta line */
|
||||||
spool_txt_printf(txt,
|
if(!ssl_printf(ssl, "msg %s %s %s %d %d " ARG_LL "d %d %u %u %u\n",
|
||||||
"msg %s %s %s %d %d " ARG_LL "d %d %u %u %u %d %s\n",
|
nm, cl, tp,
|
||||||
nm, cl, tp,
|
(int)d->flags, (int)d->qdcount,
|
||||||
(int)d->flags, (int)d->qdcount,
|
(long long)(d->ttl-now), (int)d->security,
|
||||||
(long long)(d->ttl-now), (int)d->security,
|
(unsigned)d->an_numrrsets,
|
||||||
(unsigned)d->an_numrrsets,
|
(unsigned)d->ns_numrrsets,
|
||||||
(unsigned)d->ns_numrrsets,
|
(unsigned)d->ar_numrrsets)) {
|
||||||
(unsigned)d->ar_numrrsets,
|
free(nm);
|
||||||
(int)d->reason_bogus,
|
free(tp);
|
||||||
d->reason_bogus_str?d->reason_bogus_str:"");
|
free(cl);
|
||||||
|
rrset_array_unlock(d->ref, d->rrset_count);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
free(nm);
|
free(nm);
|
||||||
free(tp);
|
free(tp);
|
||||||
free(cl);
|
free(cl);
|
||||||
|
|
||||||
for(i=0; i<d->rrset_count; i++) {
|
for(i=0; i<d->rrset_count; i++) {
|
||||||
dump_msg_ref(txt, d->rrsets[i]);
|
if(!dump_msg_ref(ssl, d->rrsets[i])) {
|
||||||
|
rrset_array_unlock(d->ref, d->rrset_count);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
rrset_array_unlock(d->ref, d->rrset_count);
|
rrset_array_unlock(d->ref, d->rrset_count);
|
||||||
|
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** copy msg to worker pad */
|
/** copy msg to worker pad */
|
||||||
@@ -379,40 +246,49 @@ copy_msg(struct regional* region, struct lruhash_entry* e,
|
|||||||
return (*k)->qname != NULL;
|
return (*k)->qname != NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Dump the msg entry. */
|
/** dump lruhash msg cache */
|
||||||
static void
|
static int
|
||||||
dump_msg_entry(struct lruhash_entry* e, struct config_strlist_head* txt,
|
dump_msg_lruhash(RES* ssl, struct worker* worker, struct lruhash* h)
|
||||||
void* arg)
|
|
||||||
{
|
{
|
||||||
struct dump_info* dump_info = (struct dump_info*)arg;
|
struct lruhash_entry* e;
|
||||||
struct query_info* k;
|
struct query_info* k;
|
||||||
struct reply_info* d;
|
struct reply_info* d;
|
||||||
|
|
||||||
regional_free_all(dump_info->worker->scratchpad);
|
/* lruhash already locked by caller */
|
||||||
/* Make copy of rrset in worker buffer. */
|
/* walk in order of lru; best first */
|
||||||
lock_rw_rdlock(&e->lock);
|
for(e=h->lru_start; e; e = e->lru_next) {
|
||||||
if(!copy_msg(dump_info->worker->scratchpad, e, &k, &d)) {
|
regional_free_all(worker->scratchpad);
|
||||||
|
lock_rw_rdlock(&e->lock);
|
||||||
|
/* make copy of rrset in worker buffer */
|
||||||
|
if(!copy_msg(worker->scratchpad, e, &k, &d)) {
|
||||||
|
lock_rw_unlock(&e->lock);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
lock_rw_unlock(&e->lock);
|
lock_rw_unlock(&e->lock);
|
||||||
log_err("out of memory in dump_msg_entry");
|
/* release lock so we can lookup the rrset references
|
||||||
return;
|
* in the rrset cache */
|
||||||
|
if(!dump_msg(ssl, k, d, *worker->env.now)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
lock_rw_unlock(&e->lock);
|
return 1;
|
||||||
/* Release lock so we can lookup the rrset references
|
|
||||||
* in the rrset cache. */
|
|
||||||
dump_msg(txt, k, d, *dump_info->worker->env.now);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** dump msg cache */
|
/** dump msg cache */
|
||||||
static int
|
static int
|
||||||
dump_msg_cache(RES* ssl, struct worker* worker)
|
dump_msg_cache(RES* ssl, struct worker* worker)
|
||||||
{
|
{
|
||||||
struct dump_info dump_info;
|
struct slabhash* sh = worker->env.msg_cache;
|
||||||
dump_info.worker = worker;
|
size_t slab;
|
||||||
dump_info.ssl = ssl;
|
|
||||||
if(!ssl_printf(ssl, "START_MSG_CACHE\n")) return 0;
|
if(!ssl_printf(ssl, "START_MSG_CACHE\n")) return 0;
|
||||||
if(!dump_slabhash(worker->env.msg_cache, &dump_msg_entry, ssl,
|
for(slab=0; slab<sh->size; slab++) {
|
||||||
&dump_info))
|
lock_quick_lock(&sh->array[slab]->lock);
|
||||||
return 0;
|
if(!dump_msg_lruhash(ssl, worker, sh->array[slab])) {
|
||||||
|
lock_quick_unlock(&sh->array[slab]->lock);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
lock_quick_unlock(&sh->array[slab]->lock);
|
||||||
|
}
|
||||||
return ssl_printf(ssl, "END_MSG_CACHE\n");
|
return ssl_printf(ssl, "END_MSG_CACHE\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -455,7 +331,7 @@ load_rr(RES* ssl, sldns_buffer* buf, struct regional* region,
|
|||||||
/* read the line */
|
/* read the line */
|
||||||
if(!ssl_read_buf(ssl, buf))
|
if(!ssl_read_buf(ssl, buf))
|
||||||
return 0;
|
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;
|
*go_on = 0;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -511,7 +387,7 @@ move_into_cache(struct ub_packed_rrset_key* k,
|
|||||||
struct rrset_ref ref;
|
struct rrset_ref ref;
|
||||||
uint8_t* p;
|
uint8_t* p;
|
||||||
|
|
||||||
ak = alloc_special_obtain(worker->alloc);
|
ak = alloc_special_obtain(&worker->alloc);
|
||||||
if(!ak) {
|
if(!ak) {
|
||||||
log_warn("error out of memory");
|
log_warn("error out of memory");
|
||||||
return 0;
|
return 0;
|
||||||
@@ -522,7 +398,7 @@ move_into_cache(struct ub_packed_rrset_key* k,
|
|||||||
ak->rk.dname = (uint8_t*)memdup(k->rk.dname, k->rk.dname_len);
|
ak->rk.dname = (uint8_t*)memdup(k->rk.dname, k->rk.dname_len);
|
||||||
if(!ak->rk.dname) {
|
if(!ak->rk.dname) {
|
||||||
log_warn("error out of memory");
|
log_warn("error out of memory");
|
||||||
ub_packed_rrset_parsedelete(ak, worker->alloc);
|
ub_packed_rrset_parsedelete(ak, &worker->alloc);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
s = sizeof(*ad) + (sizeof(size_t) + sizeof(uint8_t*) +
|
s = sizeof(*ad) + (sizeof(size_t) + sizeof(uint8_t*) +
|
||||||
@@ -532,7 +408,7 @@ move_into_cache(struct ub_packed_rrset_key* k,
|
|||||||
ad = (struct packed_rrset_data*)malloc(s);
|
ad = (struct packed_rrset_data*)malloc(s);
|
||||||
if(!ad) {
|
if(!ad) {
|
||||||
log_warn("error out of memory");
|
log_warn("error out of memory");
|
||||||
ub_packed_rrset_parsedelete(ak, worker->alloc);
|
ub_packed_rrset_parsedelete(ak, &worker->alloc);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
p = (uint8_t*)ad;
|
p = (uint8_t*)ad;
|
||||||
@@ -554,9 +430,8 @@ move_into_cache(struct ub_packed_rrset_key* k,
|
|||||||
|
|
||||||
ref.key = ak;
|
ref.key = ak;
|
||||||
ref.id = ak->id;
|
ref.id = ak->id;
|
||||||
rrset_cache_update_unlock(worker->env.rrset_cache, &ref,
|
(void)rrset_cache_update(worker->env.rrset_cache, &ref,
|
||||||
worker->alloc, *worker->env.now);
|
&worker->alloc, *worker->env.now);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -757,9 +632,6 @@ load_msg(RES* ssl, sldns_buffer* buf, struct worker* worker)
|
|||||||
long long ttl;
|
long long ttl;
|
||||||
size_t i;
|
size_t i;
|
||||||
int go_on = 1;
|
int go_on = 1;
|
||||||
int ede;
|
|
||||||
int consumed = 0;
|
|
||||||
char* ede_str = NULL;
|
|
||||||
|
|
||||||
regional_free_all(region);
|
regional_free_all(region);
|
||||||
|
|
||||||
@@ -774,16 +646,11 @@ load_msg(RES* ssl, sldns_buffer* buf, struct worker* worker)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* read remainder of line */
|
/* read remainder of line */
|
||||||
/* note the last space before any possible EDE text */
|
if(sscanf(s, " %u %u " ARG_LL "d %u %u %u %u", &flags, &qdcount, &ttl,
|
||||||
if(sscanf(s, " %u %u " ARG_LL "d %u %u %u %u %d %n", &flags, &qdcount, &ttl,
|
&security, &an, &ns, &ar) != 7) {
|
||||||
&security, &an, &ns, &ar, &ede, &consumed) != 8) {
|
|
||||||
log_warn("error cannot parse numbers: %s", s);
|
log_warn("error cannot parse numbers: %s", s);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
/* there may be EDE text after the numbers */
|
|
||||||
if(consumed > 0 && (size_t)consumed < strlen(s))
|
|
||||||
ede_str = s + consumed;
|
|
||||||
memset(&rep, 0, sizeof(rep));
|
|
||||||
rep.flags = (uint16_t)flags;
|
rep.flags = (uint16_t)flags;
|
||||||
rep.qdcount = (uint16_t)qdcount;
|
rep.qdcount = (uint16_t)qdcount;
|
||||||
rep.ttl = (time_t)ttl;
|
rep.ttl = (time_t)ttl;
|
||||||
@@ -798,8 +665,6 @@ load_msg(RES* ssl, sldns_buffer* buf, struct worker* worker)
|
|||||||
rep.ns_numrrsets = (size_t)ns;
|
rep.ns_numrrsets = (size_t)ns;
|
||||||
rep.ar_numrrsets = (size_t)ar;
|
rep.ar_numrrsets = (size_t)ar;
|
||||||
rep.rrset_count = (size_t)an+(size_t)ns+(size_t)ar;
|
rep.rrset_count = (size_t)an+(size_t)ns+(size_t)ar;
|
||||||
rep.reason_bogus = (sldns_ede_code)ede;
|
|
||||||
rep.reason_bogus_str = ede_str?(char*)regional_strdup(region, ede_str):NULL;
|
|
||||||
rep.rrsets = (struct ub_packed_rrset_key**)regional_alloc_zero(
|
rep.rrsets = (struct ub_packed_rrset_key**)regional_alloc_zero(
|
||||||
region, sizeof(struct ub_packed_rrset_key*)*rep.rrset_count);
|
region, sizeof(struct ub_packed_rrset_key*)*rep.rrset_count);
|
||||||
|
|
||||||
@@ -815,7 +680,7 @@ load_msg(RES* ssl, sldns_buffer* buf, struct worker* worker)
|
|||||||
return 1; /* skip this one, not all references satisfied */
|
return 1; /* skip this one, not all references satisfied */
|
||||||
|
|
||||||
if(!dns_cache_store(&worker->env, &qinf, &rep, 0, 0, 0, NULL, flags,
|
if(!dns_cache_store(&worker->env, &qinf, &rep, 0, 0, 0, NULL, flags,
|
||||||
*worker->env.now, 1)) {
|
*worker->env.now)) {
|
||||||
log_warn("error out of memory");
|
log_warn("error out of memory");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -934,18 +799,12 @@ print_dp_main(RES* ssl, struct delegpt* dp, struct dns_msg* msg)
|
|||||||
struct ub_packed_rrset_key* k = msg->rep->rrsets[i];
|
struct ub_packed_rrset_key* k = msg->rep->rrsets[i];
|
||||||
struct packed_rrset_data* d =
|
struct packed_rrset_data* d =
|
||||||
(struct packed_rrset_data*)k->entry.data;
|
(struct packed_rrset_data*)k->entry.data;
|
||||||
struct config_strlist_head txt;
|
|
||||||
memset(&txt, 0, sizeof(txt));
|
|
||||||
if(d->security == sec_status_bogus) {
|
if(d->security == sec_status_bogus) {
|
||||||
if(!ssl_printf(ssl, "Address is BOGUS:\n"))
|
if(!ssl_printf(ssl, "Address is BOGUS:\n"))
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
dump_rrset(&txt, k, d, 0);
|
if(!dump_rrset(ssl, k, d, 0))
|
||||||
if(!spool_strlist(ssl, txt.first)) {
|
|
||||||
config_delstrlist(txt.first);
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
config_delstrlist(txt.first);
|
|
||||||
}
|
}
|
||||||
delegpt_count_ns(dp, &n_ns, &n_miss);
|
delegpt_count_ns(dp, &n_ns, &n_miss);
|
||||||
delegpt_count_addr(dp, &n_addr, &n_res, &n_avail);
|
delegpt_count_addr(dp, &n_addr, &n_res, &n_avail);
|
||||||
@@ -965,10 +824,9 @@ int print_deleg_lookup(RES* ssl, struct worker* worker, uint8_t* nm,
|
|||||||
struct delegpt* dp;
|
struct delegpt* dp;
|
||||||
struct dns_msg* msg;
|
struct dns_msg* msg;
|
||||||
struct regional* region = worker->scratchpad;
|
struct regional* region = worker->scratchpad;
|
||||||
char b[LDNS_MAX_DOMAINLEN];
|
char b[260];
|
||||||
struct query_info qinfo;
|
struct query_info qinfo;
|
||||||
struct iter_hints_stub* stub;
|
struct iter_hints_stub* stub;
|
||||||
int nolock = 0;
|
|
||||||
regional_free_all(region);
|
regional_free_all(region);
|
||||||
qinfo.qname = nm;
|
qinfo.qname = nm;
|
||||||
qinfo.qname_len = nmlen;
|
qinfo.qname_len = nmlen;
|
||||||
@@ -981,15 +839,12 @@ int print_deleg_lookup(RES* ssl, struct worker* worker, uint8_t* nm,
|
|||||||
"of %s\n", b))
|
"of %s\n", b))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
dp = forwards_lookup(worker->env.fwds, nm, qinfo.qclass, nolock);
|
dp = forwards_lookup(worker->env.fwds, nm, qinfo.qclass);
|
||||||
if(dp) {
|
if(dp) {
|
||||||
if(!ssl_printf(ssl, "forwarding request:\n")) {
|
if(!ssl_printf(ssl, "forwarding request:\n"))
|
||||||
lock_rw_unlock(&worker->env.fwds->lock);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
|
||||||
print_dp_main(ssl, dp, NULL);
|
print_dp_main(ssl, dp, NULL);
|
||||||
print_dp_details(ssl, worker, dp);
|
print_dp_details(ssl, worker, dp);
|
||||||
lock_rw_unlock(&worker->env.fwds->lock);
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1004,8 +859,7 @@ int print_deleg_lookup(RES* ssl, struct worker* worker, uint8_t* nm,
|
|||||||
/* go up? */
|
/* go up? */
|
||||||
if(iter_dp_is_useless(&qinfo, BIT_RD, dp,
|
if(iter_dp_is_useless(&qinfo, BIT_RD, dp,
|
||||||
(worker->env.cfg->do_ip4 && worker->back->num_ip4 != 0),
|
(worker->env.cfg->do_ip4 && worker->back->num_ip4 != 0),
|
||||||
(worker->env.cfg->do_ip6 && worker->back->num_ip6 != 0),
|
(worker->env.cfg->do_ip6 && worker->back->num_ip6 != 0))) {
|
||||||
worker->env.cfg->do_nat64)) {
|
|
||||||
print_dp_main(ssl, dp, msg);
|
print_dp_main(ssl, dp, msg);
|
||||||
print_dp_details(ssl, worker, dp);
|
print_dp_details(ssl, worker, dp);
|
||||||
if(!ssl_printf(ssl, "cache delegation was "
|
if(!ssl_printf(ssl, "cache delegation was "
|
||||||
@@ -1027,24 +881,19 @@ int print_deleg_lookup(RES* ssl, struct worker* worker, uint8_t* nm,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
stub = hints_lookup_stub(worker->env.hints, nm, qinfo.qclass,
|
stub = hints_lookup_stub(worker->env.hints, nm, qinfo.qclass,
|
||||||
dp, nolock);
|
dp);
|
||||||
if(stub) {
|
if(stub) {
|
||||||
if(stub->noprime) {
|
if(stub->noprime) {
|
||||||
if(!ssl_printf(ssl, "The noprime stub servers "
|
if(!ssl_printf(ssl, "The noprime stub servers "
|
||||||
"are used:\n")) {
|
"are used:\n"))
|
||||||
lock_rw_unlock(&worker->env.hints->lock);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
if(!ssl_printf(ssl, "The stub is primed "
|
if(!ssl_printf(ssl, "The stub is primed "
|
||||||
"with servers:\n")) {
|
"with servers:\n"))
|
||||||
lock_rw_unlock(&worker->env.hints->lock);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
print_dp_main(ssl, stub->dp, NULL);
|
print_dp_main(ssl, stub->dp, NULL);
|
||||||
print_dp_details(ssl, worker, stub->dp);
|
print_dp_details(ssl, worker, stub->dp);
|
||||||
lock_rw_unlock(&worker->env.hints->lock);
|
|
||||||
} else {
|
} else {
|
||||||
print_dp_main(ssl, dp, msg);
|
print_dp_main(ssl, dp, msg);
|
||||||
print_dp_details(ssl, worker, dp);
|
print_dp_details(ssl, worker, dp);
|
||||||
|
|||||||
+44
-521
@@ -79,22 +79,18 @@
|
|||||||
#include "util/tcp_conn_limit.h"
|
#include "util/tcp_conn_limit.h"
|
||||||
#include "util/edns.h"
|
#include "util/edns.h"
|
||||||
#include "services/listen_dnsport.h"
|
#include "services/listen_dnsport.h"
|
||||||
#include "services/outside_network.h"
|
|
||||||
#include "services/cache/rrset.h"
|
#include "services/cache/rrset.h"
|
||||||
#include "services/cache/infra.h"
|
#include "services/cache/infra.h"
|
||||||
#include "services/localzone.h"
|
#include "services/localzone.h"
|
||||||
#include "services/view.h"
|
#include "services/view.h"
|
||||||
#include "services/modstack.h"
|
#include "services/modstack.h"
|
||||||
#include "services/authzone.h"
|
#include "services/authzone.h"
|
||||||
#include "services/authload.h"
|
|
||||||
#include "util/module.h"
|
#include "util/module.h"
|
||||||
#include "util/random.h"
|
#include "util/random.h"
|
||||||
#include "util/tube.h"
|
#include "util/tube.h"
|
||||||
#include "util/net_help.h"
|
#include "util/net_help.h"
|
||||||
#include "sldns/keyraw.h"
|
#include "sldns/keyraw.h"
|
||||||
#include "respip/respip.h"
|
#include "respip/respip.h"
|
||||||
#include "iterator/iter_fwd.h"
|
|
||||||
#include "iterator/iter_hints.h"
|
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
|
|
||||||
#ifdef HAVE_SYSTEMD
|
#ifdef HAVE_SYSTEMD
|
||||||
@@ -103,9 +99,6 @@
|
|||||||
#ifdef HAVE_NETDB_H
|
#ifdef HAVE_NETDB_H
|
||||||
#include <netdb.h>
|
#include <netdb.h>
|
||||||
#endif
|
#endif
|
||||||
#ifdef USE_CACHEDB
|
|
||||||
#include "cachedb/cachedb.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/** How many quit requests happened. */
|
/** How many quit requests happened. */
|
||||||
static int sig_record_quit = 0;
|
static int sig_record_quit = 0;
|
||||||
@@ -201,267 +194,6 @@ signal_handling_playback(struct worker* wrk)
|
|||||||
sig_record_reload = 0;
|
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*
|
struct daemon*
|
||||||
daemon_init(void)
|
daemon_init(void)
|
||||||
{
|
{
|
||||||
@@ -498,11 +230,7 @@ daemon_init(void)
|
|||||||
# else
|
# else
|
||||||
OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS
|
OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS
|
||||||
| OPENSSL_INIT_ADD_ALL_DIGESTS
|
| OPENSSL_INIT_ADD_ALL_DIGESTS
|
||||||
| OPENSSL_INIT_LOAD_CRYPTO_STRINGS
|
| OPENSSL_INIT_LOAD_CRYPTO_STRINGS, NULL);
|
||||||
# if defined(OPENSSL_INIT_NO_LOAD_CONFIG) && defined(UB_ON_WINDOWS)
|
|
||||||
| OPENSSL_INIT_NO_LOAD_CONFIG
|
|
||||||
# endif
|
|
||||||
, NULL);
|
|
||||||
# endif
|
# endif
|
||||||
# if HAVE_DECL_SSL_COMP_GET_COMPRESSION_METHODS
|
# if HAVE_DECL_SSL_COMP_GET_COMPRESSION_METHODS
|
||||||
/* grab the COMP method ptr because openssl leaks it */
|
/* grab the COMP method ptr because openssl leaks it */
|
||||||
@@ -511,11 +239,7 @@ daemon_init(void)
|
|||||||
# if OPENSSL_VERSION_NUMBER < 0x10100000 || !defined(HAVE_OPENSSL_INIT_SSL)
|
# if OPENSSL_VERSION_NUMBER < 0x10100000 || !defined(HAVE_OPENSSL_INIT_SSL)
|
||||||
(void)SSL_library_init();
|
(void)SSL_library_init();
|
||||||
# else
|
# else
|
||||||
(void)OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS
|
(void)OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS, NULL);
|
||||||
# if defined(OPENSSL_INIT_NO_LOAD_CONFIG) && defined(UB_ON_WINDOWS)
|
|
||||||
| OPENSSL_INIT_NO_LOAD_CONFIG
|
|
||||||
# endif
|
|
||||||
, NULL);
|
|
||||||
# endif
|
# endif
|
||||||
# if defined(HAVE_SSL) && defined(OPENSSL_THREADS) && !defined(THREADS_DISABLED)
|
# if defined(HAVE_SSL) && defined(OPENSSL_THREADS) && !defined(THREADS_DISABLED)
|
||||||
if(!ub_openssl_lock_init())
|
if(!ub_openssl_lock_init())
|
||||||
@@ -536,7 +260,6 @@ daemon_init(void)
|
|||||||
free(daemon);
|
free(daemon);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
daemon->env->modstack = &daemon->mods;
|
|
||||||
/* init edns_known_options */
|
/* init edns_known_options */
|
||||||
if(!edns_known_options_init(daemon->env)) {
|
if(!edns_known_options_init(daemon->env)) {
|
||||||
free(daemon->env);
|
free(daemon->env);
|
||||||
@@ -591,32 +314,24 @@ daemon_init(void)
|
|||||||
free(daemon);
|
free(daemon);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if(!(daemon->auth_load_info = auth_load_info_create())) {
|
|
||||||
edns_strings_delete(daemon->env->edns_strings);
|
|
||||||
auth_zones_delete(daemon->env->auth_zones);
|
|
||||||
acl_list_delete(daemon->acl_interface);
|
|
||||||
acl_list_delete(daemon->acl);
|
|
||||||
tcl_list_delete(daemon->tcl);
|
|
||||||
edns_known_options_delete(daemon->env);
|
|
||||||
free(daemon->env);
|
|
||||||
free(daemon);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
return daemon;
|
return daemon;
|
||||||
}
|
}
|
||||||
|
|
||||||
int setup_acl_for_ports(struct acl_list* list, struct listen_port* port_list)
|
static int setup_acl_for_ports(struct acl_list* list,
|
||||||
|
struct listen_port* port_list)
|
||||||
{
|
{
|
||||||
struct acl_addr* acl_node;
|
struct acl_addr* acl_node;
|
||||||
|
struct addrinfo* addr;
|
||||||
for(; port_list; port_list=port_list->next) {
|
for(; port_list; port_list=port_list->next) {
|
||||||
if(!port_list->socket) {
|
if(!port_list->socket) {
|
||||||
/* This is mainly for testbound where port_list is
|
/* This is mainly for testbound where port_list is
|
||||||
* empty. */
|
* empty. */
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
addr = port_list->socket->addr;
|
||||||
if(!(acl_node = acl_interface_insert(list,
|
if(!(acl_node = acl_interface_insert(list,
|
||||||
(struct sockaddr_storage*)port_list->socket->addr,
|
(struct sockaddr_storage*)addr->ai_addr,
|
||||||
port_list->socket->addrlen,
|
(socklen_t)addr->ai_addrlen,
|
||||||
acl_refuse))) {
|
acl_refuse))) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -725,19 +440,6 @@ daemon_open_shared_ports(struct daemon* daemon)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
|
||||||
daemon_privileged(struct daemon* daemon)
|
|
||||||
{
|
|
||||||
daemon->env->cfg = daemon->cfg;
|
|
||||||
daemon->env->alloc = &daemon->superalloc;
|
|
||||||
daemon->env->worker = NULL;
|
|
||||||
if(!modstack_call_startup(&daemon->mods, daemon->cfg->module_conf,
|
|
||||||
daemon->env)) {
|
|
||||||
fatal_exit("failed to startup modules");
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Setup modules. setup module stack.
|
* Setup modules. setup module stack.
|
||||||
* @param daemon: the daemon
|
* @param daemon: the daemon
|
||||||
@@ -747,15 +449,11 @@ static void daemon_setup_modules(struct daemon* daemon)
|
|||||||
daemon->env->cfg = daemon->cfg;
|
daemon->env->cfg = daemon->cfg;
|
||||||
daemon->env->alloc = &daemon->superalloc;
|
daemon->env->alloc = &daemon->superalloc;
|
||||||
daemon->env->worker = NULL;
|
daemon->env->worker = NULL;
|
||||||
if(daemon->mods_inited) {
|
|
||||||
modstack_call_deinit(&daemon->mods, daemon->env);
|
|
||||||
}
|
|
||||||
daemon->env->need_to_validate = 0; /* set by module init below */
|
daemon->env->need_to_validate = 0; /* set by module init below */
|
||||||
if(!modstack_call_init(&daemon->mods, daemon->cfg->module_conf,
|
if(!modstack_setup(&daemon->mods, daemon->cfg->module_conf,
|
||||||
daemon->env)) {
|
daemon->env)) {
|
||||||
fatal_exit("failed to init modules");
|
fatal_exit("failed to setup modules");
|
||||||
}
|
}
|
||||||
daemon->mods_inited = 1;
|
|
||||||
log_edns_known_options(VERB_ALGO, daemon->env);
|
log_edns_known_options(VERB_ALGO, daemon->env);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -790,30 +488,6 @@ static int daemon_get_shufport(struct daemon* daemon, int* shufport)
|
|||||||
return avail;
|
return avail;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Clear and delete per-worker alloc caches, and free memory maintained in
|
|
||||||
* superalloc.
|
|
||||||
* The rrset and message caches must be empty at the time of call.
|
|
||||||
* @param daemon: the daemon that maintains the alloc caches to be cleared.
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
daemon_clear_allocs(struct daemon* daemon)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
/* daemon->num may be different during reloads (after configuration
|
|
||||||
* read). Use old_num which has the correct value used to setup the
|
|
||||||
* worker_allocs */
|
|
||||||
for(i=0; i<daemon->old_num; i++) {
|
|
||||||
alloc_clear(daemon->worker_allocs[i]);
|
|
||||||
free(daemon->worker_allocs[i]);
|
|
||||||
}
|
|
||||||
free(daemon->worker_allocs);
|
|
||||||
daemon->worker_allocs = NULL;
|
|
||||||
|
|
||||||
alloc_clear_special(&daemon->superalloc);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Allocate empty worker structures. With backptr and thread-number,
|
* Allocate empty worker structures. With backptr and thread-number,
|
||||||
* from 0..numthread initialised. Used as user arguments to new threads.
|
* from 0..numthread initialised. Used as user arguments to new threads.
|
||||||
@@ -838,18 +512,6 @@ daemon_create_workers(struct daemon* daemon)
|
|||||||
fatal_exit("out of memory during daemon init");
|
fatal_exit("out of memory during daemon init");
|
||||||
numport = daemon_get_shufport(daemon, shufport);
|
numport = daemon_get_shufport(daemon, shufport);
|
||||||
verbose(VERB_ALGO, "total of %d outgoing ports available", numport);
|
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");
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
daemon->num = (daemon->cfg->num_threads?daemon->cfg->num_threads:1);
|
daemon->num = (daemon->cfg->num_threads?daemon->cfg->num_threads:1);
|
||||||
if(daemon->reuseport && (int)daemon->num < (int)daemon->num_ports) {
|
if(daemon->reuseport && (int)daemon->num < (int)daemon->num_ports) {
|
||||||
@@ -872,24 +534,12 @@ daemon_create_workers(struct daemon* daemon)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
for(i=0; i<daemon->num; i++) {
|
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");
|
fatal_exit("could not create worker");
|
||||||
}
|
}
|
||||||
/* create per-worker alloc caches if not reusing existing ones. */
|
|
||||||
if(!daemon->worker_allocs) {
|
|
||||||
daemon->worker_allocs = (struct alloc_cache**)calloc(
|
|
||||||
(size_t)daemon->num, sizeof(struct alloc_cache*));
|
|
||||||
if(!daemon->worker_allocs)
|
|
||||||
fatal_exit("could not allocate worker allocs");
|
|
||||||
for(i=0; i<daemon->num; i++) {
|
|
||||||
struct alloc_cache* alloc = calloc(1,
|
|
||||||
sizeof(struct alloc_cache));
|
|
||||||
if (!alloc)
|
|
||||||
fatal_exit("could not allocate worker alloc");
|
|
||||||
alloc_init(alloc, &daemon->superalloc, i);
|
|
||||||
daemon->worker_allocs[i] = alloc;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
free(shufport);
|
free(shufport);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -916,25 +566,6 @@ static void close_other_pipes(struct daemon* daemon, int thr)
|
|||||||
}
|
}
|
||||||
#endif /* THREADS_DISABLED */
|
#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.
|
* Function to start one thread.
|
||||||
* @param arg: user argument.
|
* @param arg: user argument.
|
||||||
@@ -945,15 +576,7 @@ thread_start(void* arg)
|
|||||||
{
|
{
|
||||||
struct worker* worker = (struct worker*)arg;
|
struct worker* worker = (struct worker*)arg;
|
||||||
int port_num = 0;
|
int port_num = 0;
|
||||||
set_log_thread_id(worker, worker->daemon->cfg);
|
log_thread_set(&worker->thread_num);
|
||||||
{
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
ub_thread_blocksigs();
|
ub_thread_blocksigs();
|
||||||
#ifdef THREADS_DISABLED
|
#ifdef THREADS_DISABLED
|
||||||
/* close pipe ends used by main */
|
/* close pipe ends used by main */
|
||||||
@@ -967,9 +590,8 @@ thread_start(void* arg)
|
|||||||
port_num = 0;
|
port_num = 0;
|
||||||
#endif
|
#endif
|
||||||
if(!worker_init(worker, worker->daemon->cfg,
|
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");
|
fatal_exit("Could not initialize thread");
|
||||||
}
|
|
||||||
|
|
||||||
worker_work(worker);
|
worker_work(worker);
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -1029,17 +651,16 @@ daemon_fork(struct daemon* daemon)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
log_assert(daemon);
|
log_assert(daemon);
|
||||||
daemon_reload_sslctxs(daemon);
|
if(!(daemon->views = views_create()))
|
||||||
if(!(daemon->env->views = views_create()))
|
|
||||||
fatal_exit("Could not create views: out of memory");
|
fatal_exit("Could not create views: out of memory");
|
||||||
/* create individual views and their localzone/data trees */
|
/* create individual views and their localzone/data trees */
|
||||||
if(!views_apply_cfg(daemon->env->views, daemon->cfg))
|
if(!views_apply_cfg(daemon->views, daemon->cfg))
|
||||||
fatal_exit("Could not set up views");
|
fatal_exit("Could not set up views");
|
||||||
|
|
||||||
if(!acl_list_apply_cfg(daemon->acl, daemon->cfg, daemon->env->views))
|
if(!acl_list_apply_cfg(daemon->acl, daemon->cfg, daemon->views))
|
||||||
fatal_exit("Could not setup access control list");
|
fatal_exit("Could not setup access control list");
|
||||||
if(!acl_interface_apply_cfg(daemon->acl_interface, daemon->cfg,
|
if(!acl_interface_apply_cfg(daemon->acl_interface, daemon->cfg,
|
||||||
daemon->env->views))
|
daemon->views))
|
||||||
fatal_exit("Could not setup interface control list");
|
fatal_exit("Could not setup interface control list");
|
||||||
if(!tcl_list_apply_cfg(daemon->tcl, daemon->cfg))
|
if(!tcl_list_apply_cfg(daemon->tcl, daemon->cfg))
|
||||||
fatal_exit("Could not setup TCP connection limits");
|
fatal_exit("Could not setup TCP connection limits");
|
||||||
@@ -1054,36 +675,22 @@ daemon_fork(struct daemon* daemon)
|
|||||||
"dnscrypt support");
|
"dnscrypt support");
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
if(daemon->cfg->cookie_secret_file &&
|
|
||||||
daemon->cfg->cookie_secret_file[0]) {
|
|
||||||
if(!(daemon->cookie_secrets = cookie_secrets_create()))
|
|
||||||
fatal_exit("Could not create cookie_secrets: out of memory");
|
|
||||||
if(!cookie_secrets_apply_cfg(daemon->cookie_secrets,
|
|
||||||
daemon->cfg->cookie_secret_file))
|
|
||||||
fatal_exit("Could not setup cookie_secrets");
|
|
||||||
}
|
|
||||||
/* create global local_zones */
|
/* create global local_zones */
|
||||||
if(!(daemon->local_zones = local_zones_create()))
|
if(!(daemon->local_zones = local_zones_create()))
|
||||||
fatal_exit("Could not create local zones: out of memory");
|
fatal_exit("Could not create local zones: out of memory");
|
||||||
if(!local_zones_apply_cfg(daemon->local_zones, daemon->cfg))
|
if(!local_zones_apply_cfg(daemon->local_zones, daemon->cfg))
|
||||||
fatal_exit("Could not set up local zones");
|
fatal_exit("Could not set up local zones");
|
||||||
if(!(daemon->env->fwds = forwards_create()) ||
|
|
||||||
!forwards_apply_cfg(daemon->env->fwds, daemon->cfg))
|
|
||||||
fatal_exit("Could not set forward zones");
|
|
||||||
if(!(daemon->env->hints = hints_create()) ||
|
|
||||||
!hints_apply_cfg(daemon->env->hints, daemon->cfg))
|
|
||||||
fatal_exit("Could not set root or stub hints");
|
|
||||||
|
|
||||||
/* process raw response-ip configuration data */
|
/* process raw response-ip configuration data */
|
||||||
if(!(daemon->env->respip_set = respip_set_create()))
|
if(!(daemon->respip_set = respip_set_create()))
|
||||||
fatal_exit("Could not create response IP set");
|
fatal_exit("Could not create response IP set");
|
||||||
if(!respip_global_apply_cfg(daemon->env->respip_set, daemon->cfg))
|
if(!respip_global_apply_cfg(daemon->respip_set, daemon->cfg))
|
||||||
fatal_exit("Could not set up response IP set");
|
fatal_exit("Could not set up response IP set");
|
||||||
if(!respip_views_apply_cfg(daemon->env->views, daemon->cfg,
|
if(!respip_views_apply_cfg(daemon->views, daemon->cfg,
|
||||||
&have_view_respip_cfg))
|
&have_view_respip_cfg))
|
||||||
fatal_exit("Could not set up per-view response IP sets");
|
fatal_exit("Could not set up per-view response IP sets");
|
||||||
daemon->use_response_ip = !respip_set_is_empty(
|
daemon->use_response_ip = !respip_set_is_empty(daemon->respip_set) ||
|
||||||
daemon->env->respip_set) || have_view_respip_cfg;
|
have_view_respip_cfg;
|
||||||
|
|
||||||
/* setup modules */
|
/* setup modules */
|
||||||
daemon_setup_modules(daemon);
|
daemon_setup_modules(daemon);
|
||||||
@@ -1097,10 +704,6 @@ daemon_fork(struct daemon* daemon)
|
|||||||
if(!edns_strings_apply_cfg(daemon->env->edns_strings, daemon->cfg))
|
if(!edns_strings_apply_cfg(daemon->env->edns_strings, daemon->cfg))
|
||||||
fatal_exit("Could not set up EDNS strings");
|
fatal_exit("Could not set up EDNS strings");
|
||||||
|
|
||||||
#ifdef USE_CACHEDB
|
|
||||||
daemon->env->cachedb_enabled = cachedb_is_enabled(&daemon->mods,
|
|
||||||
daemon->env);
|
|
||||||
#endif
|
|
||||||
/* response-ip-xxx options don't work as expected without the respip
|
/* response-ip-xxx options don't work as expected without the respip
|
||||||
* module. To avoid run-time operational surprise we reject such
|
* module. To avoid run-time operational surprise we reject such
|
||||||
* configuration. */
|
* configuration. */
|
||||||
@@ -1118,22 +721,11 @@ daemon_fork(struct daemon* daemon)
|
|||||||
* them to the newly created threads.
|
* them to the newly created threads.
|
||||||
*/
|
*/
|
||||||
daemon_create_workers(daemon);
|
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)
|
#if defined(HAVE_EV_LOOP) || defined(HAVE_EV_DEFAULT_LOOP)
|
||||||
/* in libev the first inited base gets signals */
|
/* 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");
|
fatal_exit("Could not initialize main thread");
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Now create the threads and init the workers.
|
/* Now create the threads and init the workers.
|
||||||
@@ -1146,9 +738,8 @@ daemon_fork(struct daemon* daemon)
|
|||||||
*/
|
*/
|
||||||
#if !(defined(HAVE_EV_LOOP) || defined(HAVE_EV_DEFAULT_LOOP))
|
#if !(defined(HAVE_EV_LOOP) || defined(HAVE_EV_DEFAULT_LOOP))
|
||||||
/* libevent has the last inited base get signals (or any base) */
|
/* 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");
|
fatal_exit("Could not initialize main thread");
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
signal_handling_playback(daemon->workers[0]);
|
signal_handling_playback(daemon->workers[0]);
|
||||||
|
|
||||||
@@ -1176,12 +767,10 @@ daemon_fork(struct daemon* daemon)
|
|||||||
|
|
||||||
/* we exited! a signal happened! Stop other threads */
|
/* we exited! a signal happened! Stop other threads */
|
||||||
daemon_stop_others(daemon);
|
daemon_stop_others(daemon);
|
||||||
auth_load_stop_threads(daemon);
|
|
||||||
|
|
||||||
/* Shutdown SHM */
|
/* Shutdown SHM */
|
||||||
shm_main_shutdown(daemon);
|
shm_main_shutdown(daemon);
|
||||||
|
|
||||||
daemon->reuse_cache = daemon->workers[0]->reuse_cache;
|
|
||||||
daemon->need_to_exit = daemon->workers[0]->need_to_exit;
|
daemon->need_to_exit = daemon->workers[0]->need_to_exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1193,50 +782,28 @@ daemon_cleanup(struct daemon* daemon)
|
|||||||
/* before stopping main worker, handle signals ourselves, so we
|
/* before stopping main worker, handle signals ourselves, so we
|
||||||
don't die on multiple reload signals for example. */
|
don't die on multiple reload signals for example. */
|
||||||
signal_handling_record();
|
signal_handling_record();
|
||||||
|
log_thread_set(NULL);
|
||||||
/* clean up caches because
|
/* clean up caches because
|
||||||
* a) RRset IDs will be recycled after a reload, causing collisions
|
* a) RRset IDs will be recycled after a reload, causing collisions
|
||||||
* b) validation config can change, thus rrset, msg, keycache clear
|
* b) validation config can change, thus rrset, msg, keycache clear */
|
||||||
*
|
slabhash_clear(&daemon->env->rrset_cache->table);
|
||||||
* If we are trying to keep the cache as long as possible, we should
|
slabhash_clear(daemon->env->msg_cache);
|
||||||
* defer the cleanup until we know whether the new configuration allows
|
|
||||||
* the reuse. (If we're exiting, cleanup should be done here). */
|
|
||||||
if(!daemon->reuse_cache || daemon->need_to_exit) {
|
|
||||||
slabhash_clear(&daemon->env->rrset_cache->table);
|
|
||||||
slabhash_clear(daemon->env->msg_cache);
|
|
||||||
}
|
|
||||||
daemon->old_num = daemon->num; /* save the current num */
|
|
||||||
forwards_delete(daemon->env->fwds);
|
|
||||||
daemon->env->fwds = NULL;
|
|
||||||
hints_delete(daemon->env->hints);
|
|
||||||
daemon->env->hints = NULL;
|
|
||||||
local_zones_delete(daemon->local_zones);
|
local_zones_delete(daemon->local_zones);
|
||||||
daemon->local_zones = NULL;
|
daemon->local_zones = NULL;
|
||||||
respip_set_delete(daemon->env->respip_set);
|
respip_set_delete(daemon->respip_set);
|
||||||
daemon->env->respip_set = NULL;
|
daemon->respip_set = NULL;
|
||||||
views_delete(daemon->env->views);
|
views_delete(daemon->views);
|
||||||
daemon->env->views = NULL;
|
daemon->views = NULL;
|
||||||
if(daemon->env->auth_zones)
|
if(daemon->env->auth_zones)
|
||||||
auth_zones_cleanup(daemon->env->auth_zones);
|
auth_zones_cleanup(daemon->env->auth_zones);
|
||||||
auth_load_info_cleanup(daemon->auth_load_info);
|
/* key cache is cleared by module desetup during next daemon_fork() */
|
||||||
/* key cache is cleared by module deinit during next daemon_fork() */
|
|
||||||
daemon_remote_clear(daemon->rc);
|
daemon_remote_clear(daemon->rc);
|
||||||
if(daemon->fast_reload_thread)
|
|
||||||
fast_reload_thread_stop(daemon->fast_reload_thread);
|
|
||||||
if(daemon->fast_reload_printq_list)
|
|
||||||
fast_reload_printq_list_delete(daemon->fast_reload_printq_list);
|
|
||||||
for(i=0; i<daemon->num; i++)
|
for(i=0; i<daemon->num; i++)
|
||||||
worker_delete(daemon->workers[i]);
|
worker_delete(daemon->workers[i]);
|
||||||
free(daemon->workers);
|
free(daemon->workers);
|
||||||
daemon->workers = NULL;
|
daemon->workers = NULL;
|
||||||
/* Unless we're trying to keep the cache, worker alloc_caches should be
|
|
||||||
* cleared and freed here. We do this after deleting workers to
|
|
||||||
* guarantee that the alloc caches are valid throughout the lifetime
|
|
||||||
* of workers. */
|
|
||||||
if(!daemon->reuse_cache || daemon->need_to_exit)
|
|
||||||
daemon_clear_allocs(daemon);
|
|
||||||
daemon->num = 0;
|
daemon->num = 0;
|
||||||
shared_ports_delete(daemon->shared_ports);
|
alloc_clear_special(&daemon->superalloc);
|
||||||
daemon->shared_ports = NULL;
|
|
||||||
#ifdef USE_DNSTAP
|
#ifdef USE_DNSTAP
|
||||||
dt_delete(daemon->dtenv);
|
dt_delete(daemon->dtenv);
|
||||||
daemon->dtenv = NULL;
|
daemon->dtenv = NULL;
|
||||||
@@ -1244,12 +811,6 @@ daemon_cleanup(struct daemon* daemon)
|
|||||||
#ifdef USE_DNSCRYPT
|
#ifdef USE_DNSCRYPT
|
||||||
dnsc_delete(daemon->dnscenv);
|
dnsc_delete(daemon->dnscenv);
|
||||||
daemon->dnscenv = NULL;
|
daemon->dnscenv = NULL;
|
||||||
#endif
|
|
||||||
#ifdef HAVE_NGTCP2
|
|
||||||
if (daemon->doq_table) {
|
|
||||||
doq_table_delete(daemon->doq_table);
|
|
||||||
daemon->doq_table = NULL;
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
daemon->cfg = NULL;
|
daemon->cfg = NULL;
|
||||||
}
|
}
|
||||||
@@ -1260,9 +821,7 @@ daemon_delete(struct daemon* daemon)
|
|||||||
size_t i;
|
size_t i;
|
||||||
if(!daemon)
|
if(!daemon)
|
||||||
return;
|
return;
|
||||||
modstack_call_deinit(&daemon->mods, daemon->env);
|
modstack_desetup(&daemon->mods, daemon->env);
|
||||||
modstack_call_destartup(&daemon->mods, daemon->env);
|
|
||||||
modstack_free(&daemon->mods);
|
|
||||||
daemon_remote_delete(daemon->rc);
|
daemon_remote_delete(daemon->rc);
|
||||||
for(i = 0; i < daemon->num_ports; i++)
|
for(i = 0; i < daemon->num_ports; i++)
|
||||||
listening_ports_free(daemon->ports[i]);
|
listening_ports_free(daemon->ports[i]);
|
||||||
@@ -1276,19 +835,20 @@ daemon_delete(struct daemon* daemon)
|
|||||||
edns_strings_delete(daemon->env->edns_strings);
|
edns_strings_delete(daemon->env->edns_strings);
|
||||||
auth_zones_delete(daemon->env->auth_zones);
|
auth_zones_delete(daemon->env->auth_zones);
|
||||||
}
|
}
|
||||||
auth_load_info_delete(daemon->auth_load_info);
|
|
||||||
ub_randfree(daemon->rand);
|
ub_randfree(daemon->rand);
|
||||||
alloc_clear(&daemon->superalloc);
|
alloc_clear(&daemon->superalloc);
|
||||||
acl_list_delete(daemon->acl);
|
acl_list_delete(daemon->acl);
|
||||||
acl_list_delete(daemon->acl_interface);
|
acl_list_delete(daemon->acl_interface);
|
||||||
tcl_list_delete(daemon->tcl);
|
tcl_list_delete(daemon->tcl);
|
||||||
cookie_secrets_delete(daemon->cookie_secrets);
|
|
||||||
listen_desetup_locks();
|
listen_desetup_locks();
|
||||||
free(daemon->chroot);
|
free(daemon->chroot);
|
||||||
free(daemon->pidfile);
|
free(daemon->pidfile);
|
||||||
free(daemon->cfgfile);
|
|
||||||
free(daemon->env);
|
free(daemon->env);
|
||||||
daemon_delete_sslctxs(daemon);
|
#ifdef HAVE_SSL
|
||||||
|
listen_sslctx_delete_ticket_keys();
|
||||||
|
SSL_CTX_free((SSL_CTX*)daemon->listen_sslctx);
|
||||||
|
SSL_CTX_free((SSL_CTX*)daemon->connect_sslctx);
|
||||||
|
#endif
|
||||||
free(daemon);
|
free(daemon);
|
||||||
/* lex cleanup */
|
/* lex cleanup */
|
||||||
ub_c_lex_destroy();
|
ub_c_lex_destroy();
|
||||||
@@ -1300,7 +860,7 @@ daemon_delete(struct daemon* daemon)
|
|||||||
# if HAVE_DECL_SSL_COMP_GET_COMPRESSION_METHODS && HAVE_DECL_SK_SSL_COMP_POP_FREE
|
# if HAVE_DECL_SSL_COMP_GET_COMPRESSION_METHODS && HAVE_DECL_SK_SSL_COMP_POP_FREE
|
||||||
# ifndef S_SPLINT_S
|
# ifndef S_SPLINT_S
|
||||||
# if OPENSSL_VERSION_NUMBER < 0x10100000
|
# 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
|
# endif
|
||||||
# endif
|
# endif
|
||||||
@@ -1323,9 +883,6 @@ daemon_delete(struct daemon* daemon)
|
|||||||
# if defined(HAVE_SSL) && defined(OPENSSL_THREADS) && !defined(THREADS_DISABLED)
|
# if defined(HAVE_SSL) && defined(OPENSSL_THREADS) && !defined(THREADS_DISABLED)
|
||||||
ub_openssl_lock_delete();
|
ub_openssl_lock_delete();
|
||||||
# endif
|
# endif
|
||||||
#ifdef HAVE_OPENSSL_CLEANUP
|
|
||||||
OPENSSL_cleanup();
|
|
||||||
#endif
|
|
||||||
#ifndef HAVE_ARC4RANDOM
|
#ifndef HAVE_ARC4RANDOM
|
||||||
_ARC4_LOCK_DESTROY();
|
_ARC4_LOCK_DESTROY();
|
||||||
#endif
|
#endif
|
||||||
@@ -1343,42 +900,8 @@ daemon_delete(struct daemon* daemon)
|
|||||||
|
|
||||||
void daemon_apply_cfg(struct daemon* daemon, struct config_file* cfg)
|
void daemon_apply_cfg(struct daemon* daemon, struct config_file* cfg)
|
||||||
{
|
{
|
||||||
int new_num = cfg->num_threads?cfg->num_threads:1;
|
|
||||||
|
|
||||||
daemon->cfg = cfg;
|
daemon->cfg = cfg;
|
||||||
config_apply(cfg);
|
config_apply(cfg);
|
||||||
|
|
||||||
/* If this is a reload and we deferred the decision on whether to
|
|
||||||
* reuse the alloc, RRset, and message caches, then check to see if
|
|
||||||
* it's safe to keep the caches:
|
|
||||||
* - changing the number of threads is obviously incompatible with
|
|
||||||
* keeping the per-thread alloc caches. It also means we have to
|
|
||||||
* clear RRset and message caches. (note that 'new_num' may be
|
|
||||||
* adjusted in daemon_create_workers, but for our purpose we can
|
|
||||||
* simply compare it with 'old_num'; if they are equal here,
|
|
||||||
* 'new_num' won't be adjusted to a different value than 'old_num').
|
|
||||||
* - changing RRset cache size effectively clears any remaining cache
|
|
||||||
* entries. We could keep their keys in alloc caches, but it would
|
|
||||||
* be more consistent with the sense of the change to clear allocs
|
|
||||||
* and free memory. To do so we also have to clear message cache.
|
|
||||||
* - only changing message cache size does not necessarily affect
|
|
||||||
* RRset or alloc cache. But almost all new subsequent queries will
|
|
||||||
* require recursive resolution anyway, so it doesn't help much to
|
|
||||||
* just keep RRset and alloc caches. For simplicity we clear/free
|
|
||||||
* the other two, too. */
|
|
||||||
if(daemon->worker_allocs &&
|
|
||||||
(new_num != daemon->old_num ||
|
|
||||||
!slabhash_is_size(daemon->env->msg_cache, cfg->msg_cache_size,
|
|
||||||
cfg->msg_cache_slabs) ||
|
|
||||||
!slabhash_is_size(&daemon->env->rrset_cache->table,
|
|
||||||
cfg->rrset_cache_size, cfg->rrset_cache_slabs)))
|
|
||||||
{
|
|
||||||
log_warn("cannot reuse caches due to critical config change");
|
|
||||||
slabhash_clear(&daemon->env->rrset_cache->table);
|
|
||||||
slabhash_clear(daemon->env->msg_cache);
|
|
||||||
daemon_clear_allocs(daemon);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!slabhash_is_size(daemon->env->msg_cache, cfg->msg_cache_size,
|
if(!slabhash_is_size(daemon->env->msg_cache, cfg->msg_cache_size,
|
||||||
cfg->msg_cache_slabs)) {
|
cfg->msg_cache_slabs)) {
|
||||||
slabhash_delete(daemon->env->msg_cache);
|
slabhash_delete(daemon->env->msg_cache);
|
||||||
|
|||||||
+6
-99
@@ -58,12 +58,6 @@ struct ub_randstate;
|
|||||||
struct daemon_remote;
|
struct daemon_remote;
|
||||||
struct respip_set;
|
struct respip_set;
|
||||||
struct shm_main_info;
|
struct shm_main_info;
|
||||||
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"
|
#include "dnstap/dnstap_config.h"
|
||||||
#ifdef USE_DNSTAP
|
#ifdef USE_DNSTAP
|
||||||
@@ -99,38 +93,14 @@ struct daemon {
|
|||||||
int rc_port;
|
int rc_port;
|
||||||
/** listening ports for remote control */
|
/** listening ports for remote control */
|
||||||
struct listen_port* rc_ports;
|
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) */
|
/** remote control connections management (for first worker) */
|
||||||
struct daemon_remote* rc;
|
struct daemon_remote* rc;
|
||||||
/** ssl context for listening to dnstcp over ssl */
|
/** ssl context for listening to dnstcp over ssl, and connecting ssl */
|
||||||
void* listen_dot_sslctx;
|
void* listen_sslctx, *connect_sslctx;
|
||||||
/** ssl context for connecting to dnstcp over ssl */
|
|
||||||
void* connect_dot_sslctx;
|
|
||||||
/** ssl context for listening to DoH */
|
|
||||||
void* listen_doh_sslctx;
|
|
||||||
/** ssl context for listening to quic */
|
|
||||||
void* listen_quic_sslctx;
|
|
||||||
/** the file name that the ssl context is made with, private key. */
|
|
||||||
char* ssl_service_key;
|
|
||||||
/** the file name that the ssl context is made with, certificate. */
|
|
||||||
char* ssl_service_pem;
|
|
||||||
/** modification time for ssl_service_key, in sec and ns. Like
|
|
||||||
* in a struct timespec, but without that for portability. */
|
|
||||||
time_t mtime_ssl_service_key;
|
|
||||||
long mtime_ns_ssl_service_key;
|
|
||||||
/** modification time for ssl_service_pem, in sec and ns. Like
|
|
||||||
* in a struct timespec, but without that for portability. */
|
|
||||||
time_t mtime_ssl_service_pem;
|
|
||||||
long mtime_ns_ssl_service_pem;
|
|
||||||
/** num threads allocated */
|
/** num threads allocated */
|
||||||
int num;
|
int num;
|
||||||
/** num threads allocated in the previous config or 0 at first */
|
|
||||||
int old_num;
|
|
||||||
/** the worker entries */
|
/** the worker entries */
|
||||||
struct worker** workers;
|
struct worker** workers;
|
||||||
/** per-worker allocation cache */
|
|
||||||
struct alloc_cache **worker_allocs;
|
|
||||||
/** do we need to exit unbound (or is it only a reload?) */
|
/** do we need to exit unbound (or is it only a reload?) */
|
||||||
int need_to_exit;
|
int need_to_exit;
|
||||||
/** master random table ; used for port div between threads on reload*/
|
/** master random table ; used for port div between threads on reload*/
|
||||||
@@ -141,8 +111,6 @@ struct daemon {
|
|||||||
struct module_env* env;
|
struct module_env* env;
|
||||||
/** stack of module callbacks */
|
/** stack of module callbacks */
|
||||||
struct module_stack mods;
|
struct module_stack mods;
|
||||||
/** The module stack has been inited */
|
|
||||||
int mods_inited;
|
|
||||||
/** access control, which client IPs are allowed to connect */
|
/** access control, which client IPs are allowed to connect */
|
||||||
struct acl_list* acl;
|
struct acl_list* acl;
|
||||||
/** access control, which interfaces are allowed to connect */
|
/** access control, which interfaces are allowed to connect */
|
||||||
@@ -155,18 +123,15 @@ struct daemon {
|
|||||||
struct timeval time_last_stat;
|
struct timeval time_last_stat;
|
||||||
/** time when daemon started */
|
/** time when daemon started */
|
||||||
struct timeval time_boot;
|
struct timeval time_boot;
|
||||||
|
/** views structure containing view tree */
|
||||||
|
struct views* views;
|
||||||
#ifdef USE_DNSTAP
|
#ifdef USE_DNSTAP
|
||||||
/** the dnstap environment master value, copied and changed by threads*/
|
/** the dnstap environment master value, copied and changed by threads*/
|
||||||
struct dt_env* dtenv;
|
struct dt_env* dtenv;
|
||||||
#endif
|
#endif
|
||||||
/** The SHM info for shared memory stats. */
|
|
||||||
struct shm_main_info* shm_info;
|
struct shm_main_info* shm_info;
|
||||||
/** if the timeout for statistics is attempted at specific offset.
|
/** response-ip set with associated actions and tags. */
|
||||||
* If it is true, the stat timeout is the interval+offset, and that
|
struct respip_set* respip_set;
|
||||||
* 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 */
|
/** some response-ip tags or actions are configured if true */
|
||||||
int use_response_ip;
|
int use_response_ip;
|
||||||
/** some RPZ policies are configured */
|
/** some RPZ policies are configured */
|
||||||
@@ -175,25 +140,6 @@ struct daemon {
|
|||||||
/** the dnscrypt environment */
|
/** the dnscrypt environment */
|
||||||
struct dnsc_env* dnscenv;
|
struct dnsc_env* dnscenv;
|
||||||
#endif
|
#endif
|
||||||
/** the doq connection table */
|
|
||||||
struct doq_table* doq_table;
|
|
||||||
/** reuse existing cache on reload if other conditions allow it. */
|
|
||||||
int reuse_cache;
|
|
||||||
/** the EDNS cookie secrets from the cookie-secret-file */
|
|
||||||
struct cookie_secrets* cookie_secrets;
|
|
||||||
/** the fast reload thread, or NULL */
|
|
||||||
struct fast_reload_thread* fast_reload_thread;
|
|
||||||
/** the fast reload printq list */
|
|
||||||
struct fast_reload_printq* fast_reload_printq_list;
|
|
||||||
/** the fast reload option to drop mesh queries, true if so. */
|
|
||||||
int fast_reload_drop_mesh;
|
|
||||||
/** for fast reload, if the tcl, tcp connection limits, has
|
|
||||||
* changes for workers */
|
|
||||||
int fast_reload_tcl_has_changes;
|
|
||||||
/** config file name */
|
|
||||||
char* cfgfile;
|
|
||||||
/** Auth load threads, the number of active threads. */
|
|
||||||
struct auth_load_general_info* auth_load_info;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -210,15 +156,6 @@ struct daemon* daemon_init(void);
|
|||||||
*/
|
*/
|
||||||
int daemon_open_shared_ports(struct daemon* daemon);
|
int daemon_open_shared_ports(struct daemon* daemon);
|
||||||
|
|
||||||
/**
|
|
||||||
* Do daemon setup that needs privileges
|
|
||||||
* like opening privileged ports or opening device files.
|
|
||||||
* The cfg member pointer must have been set for the daemon.
|
|
||||||
* @param daemon: the daemon.
|
|
||||||
* @return: false on error.
|
|
||||||
*/
|
|
||||||
int daemon_privileged(struct daemon* daemon);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fork workers and start service.
|
* Fork workers and start service.
|
||||||
* When the routine exits, it is no longer forked.
|
* When the routine exits, it is no longer forked.
|
||||||
@@ -246,34 +183,4 @@ void daemon_delete(struct daemon* daemon);
|
|||||||
*/
|
*/
|
||||||
void daemon_apply_cfg(struct daemon* daemon, struct config_file* cfg);
|
void daemon_apply_cfg(struct daemon* daemon, struct config_file* cfg);
|
||||||
|
|
||||||
/**
|
|
||||||
* Setup acl list to have entries for the port list.
|
|
||||||
* @param list: the acl interface
|
|
||||||
* @param port_list: list of open ports, or none.
|
|
||||||
* @return false on failure
|
|
||||||
*/
|
|
||||||
int setup_acl_for_ports(struct acl_list* list, struct listen_port* port_list);
|
|
||||||
|
|
||||||
/* 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 */
|
#endif /* DAEMON_H */
|
||||||
|
|||||||
+233
-5332
File diff suppressed because it is too large
Load Diff
+1
-170
@@ -46,10 +46,8 @@
|
|||||||
#ifndef DAEMON_REMOTE_H
|
#ifndef DAEMON_REMOTE_H
|
||||||
#define DAEMON_REMOTE_H
|
#define DAEMON_REMOTE_H
|
||||||
#ifdef HAVE_OPENSSL_SSL_H
|
#ifdef HAVE_OPENSSL_SSL_H
|
||||||
#include <openssl/ssl.h>
|
#include "openssl/ssl.h"
|
||||||
#endif
|
#endif
|
||||||
#include "util/locks.h"
|
|
||||||
#include "libunbound/remote.h"
|
|
||||||
struct config_file;
|
struct config_file;
|
||||||
struct listen_list;
|
struct listen_list;
|
||||||
struct listen_port;
|
struct listen_port;
|
||||||
@@ -57,7 +55,6 @@ struct worker;
|
|||||||
struct comm_reply;
|
struct comm_reply;
|
||||||
struct comm_point;
|
struct comm_point;
|
||||||
struct daemon_remote;
|
struct daemon_remote;
|
||||||
struct config_strlist_head;
|
|
||||||
|
|
||||||
/** number of milliseconds timeout on incoming remote control handshake */
|
/** number of milliseconds timeout on incoming remote control handshake */
|
||||||
#define REMOTE_CONTROL_TCP_TIMEOUT 120000
|
#define REMOTE_CONTROL_TCP_TIMEOUT 120000
|
||||||
@@ -121,145 +118,6 @@ struct remote_stream {
|
|||||||
};
|
};
|
||||||
typedef struct remote_stream RES;
|
typedef struct remote_stream RES;
|
||||||
|
|
||||||
/**
|
|
||||||
* Notification status. This is exchanged between the fast reload thread
|
|
||||||
* and the server thread, over the commpair sockets.
|
|
||||||
*/
|
|
||||||
enum fast_reload_notification {
|
|
||||||
/** nothing, not used */
|
|
||||||
fast_reload_notification_none = 0,
|
|
||||||
/** the fast reload thread is done */
|
|
||||||
fast_reload_notification_done = 1,
|
|
||||||
/** the fast reload thread is done but with an error, it failed */
|
|
||||||
fast_reload_notification_done_error = 2,
|
|
||||||
/** the fast reload thread is told to exit by the server thread.
|
|
||||||
* Sent on server quit while the reload is running. */
|
|
||||||
fast_reload_notification_exit = 3,
|
|
||||||
/** the fast reload thread has exited, after being told to exit */
|
|
||||||
fast_reload_notification_exited = 4,
|
|
||||||
/** the fast reload thread has information to print out */
|
|
||||||
fast_reload_notification_printout = 5,
|
|
||||||
/** stop as part of the reload the thread and other threads */
|
|
||||||
fast_reload_notification_reload_stop = 6,
|
|
||||||
/** ack the stop as part of the reload, and also ack start */
|
|
||||||
fast_reload_notification_reload_ack = 7,
|
|
||||||
/** resume from stop as part of the reload */
|
|
||||||
fast_reload_notification_reload_start = 8,
|
|
||||||
/** the fast reload thread wants the mainthread to poll workers,
|
|
||||||
* after the reload, sent when nopause is used */
|
|
||||||
fast_reload_notification_reload_nopause_poll = 9
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fast reload printout queue. Contains a list of strings, that need to be
|
|
||||||
* printed over the file descriptor.
|
|
||||||
*/
|
|
||||||
struct fast_reload_printq {
|
|
||||||
/** if this item is in a list, the previous and next */
|
|
||||||
struct fast_reload_printq *prev, *next;
|
|
||||||
/** if this item is in a list, it is true. */
|
|
||||||
int in_list;
|
|
||||||
/** list of strings to printout */
|
|
||||||
struct config_strlist_head* to_print;
|
|
||||||
/** the current item to print. It is malloced. NULL if none. */
|
|
||||||
char* client_item;
|
|
||||||
/** The length, strlen, of the client_item, that has to be sent. */
|
|
||||||
int client_len;
|
|
||||||
/** The number of bytes sent of client_item. */
|
|
||||||
int client_byte_count;
|
|
||||||
/** the comm point for the client connection, the remote control
|
|
||||||
* client. */
|
|
||||||
struct comm_point* client_cp;
|
|
||||||
/** the remote control connection to print output to. */
|
|
||||||
struct remote_stream remote;
|
|
||||||
/** the worker that the event is added in */
|
|
||||||
struct worker* worker;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fast reload auth zone change. Keeps track if an auth zone was removed,
|
|
||||||
* added or changed. This is needed because workers can have events for
|
|
||||||
* dealing with auth zones, like transfers, and those have to be removed
|
|
||||||
* too, not just the auth zone structure from the tree. */
|
|
||||||
struct fast_reload_auth_change {
|
|
||||||
/** next in the list of auth zone changes. */
|
|
||||||
struct fast_reload_auth_change* next;
|
|
||||||
/** the zone in the old config */
|
|
||||||
struct auth_zone* old_z;
|
|
||||||
/** the zone in the new config */
|
|
||||||
struct auth_zone* new_z;
|
|
||||||
/** if the zone was deleted */
|
|
||||||
int is_deleted;
|
|
||||||
/** if the zone was added */
|
|
||||||
int is_added;
|
|
||||||
/** if the zone has been changed */
|
|
||||||
int is_changed;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fast reload thread structure
|
|
||||||
*/
|
|
||||||
struct fast_reload_thread {
|
|
||||||
/** the thread number for the dtio thread,
|
|
||||||
* must be first to cast thread arg to int* in checklock code. */
|
|
||||||
int threadnum;
|
|
||||||
/** communication socket pair, that sends commands */
|
|
||||||
int commpair[2];
|
|
||||||
/** thread id, of the io thread */
|
|
||||||
ub_thread_type tid;
|
|
||||||
#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 */
|
|
||||||
int need_to_quit;
|
|
||||||
/** verbosity of the fast_reload command, the number of +v options */
|
|
||||||
int fr_verb;
|
|
||||||
/** option to not pause threads during reload */
|
|
||||||
int fr_nopause;
|
|
||||||
/** option to drop mesh queries */
|
|
||||||
int fr_drop_mesh;
|
|
||||||
|
|
||||||
/** the event that listens on the remote service worker to the
|
|
||||||
* commpair, it receives content from the fast reload thread. */
|
|
||||||
void* service_event;
|
|
||||||
/** if the event that listens on the remote service worker has
|
|
||||||
* been added to the comm base. */
|
|
||||||
int service_event_is_added;
|
|
||||||
/** the service event can read a cmd, nonblocking, so it can
|
|
||||||
* save the partial read cmd here */
|
|
||||||
uint32_t service_read_cmd;
|
|
||||||
/** the number of bytes in service_read_cmd */
|
|
||||||
int service_read_cmd_count;
|
|
||||||
/** the worker that the service_event is added in */
|
|
||||||
struct worker* worker;
|
|
||||||
|
|
||||||
/** the printout of output to the remote client. */
|
|
||||||
struct fast_reload_printq *printq;
|
|
||||||
|
|
||||||
/** lock on fr_output, to stop race when both remote control thread
|
|
||||||
* and fast reload thread use fr_output list. */
|
|
||||||
lock_basic_type fr_output_lock;
|
|
||||||
/** list of strings, that the fast reload thread produces that have
|
|
||||||
* to be printed. The remote control thread can pick them up with
|
|
||||||
* the lock. */
|
|
||||||
struct config_strlist_head* fr_output;
|
|
||||||
|
|
||||||
/** communication socket pair, to respond to the reload request */
|
|
||||||
int commreload[2];
|
|
||||||
|
|
||||||
/** the list of auth zone changes. */
|
|
||||||
struct fast_reload_auth_change* auth_zone_change_list;
|
|
||||||
/** the old tree of auth zones, to lookup. */
|
|
||||||
struct auth_zones* old_auth_zones;
|
|
||||||
/** If the ssl ctxs have changed. */
|
|
||||||
int sslctxs_changed;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create new remote control state for the daemon.
|
* Create new remote control state for the daemon.
|
||||||
* @param cfg: config file with key file settings.
|
* @param cfg: config file with key file settings.
|
||||||
@@ -345,31 +203,4 @@ int ssl_printf(RES* ssl, const char* format, ...)
|
|||||||
int ssl_read_line(RES* ssl, char* buf, size_t max);
|
int ssl_read_line(RES* ssl, char* buf, size_t max);
|
||||||
#endif /* HAVE_SSL */
|
#endif /* HAVE_SSL */
|
||||||
|
|
||||||
/**
|
|
||||||
* Start fast reload thread
|
|
||||||
* @param ssl: the RES connection to print to.
|
|
||||||
* @param worker: the remote servicing worker.
|
|
||||||
* @param s: the rc_state that is servicing the remote control connection to
|
|
||||||
* the remote control client. It needs to be moved away to stay connected
|
|
||||||
* while the fast reload is running.
|
|
||||||
* @param fr_verb: verbosity to print output at. 0 is nothing, 1 is some
|
|
||||||
* and 2 is more detail.
|
|
||||||
* @param fr_nopause: option to not pause threads during reload.
|
|
||||||
* @param fr_drop_mesh: option to drop mesh queries.
|
|
||||||
*/
|
|
||||||
void fast_reload_thread_start(RES* ssl, struct worker* worker,
|
|
||||||
struct rc_state* s, int fr_verb, int fr_nopause, int fr_drop_mesh);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Stop fast reload thread
|
|
||||||
* @param fast_reload_thread: the thread struct.
|
|
||||||
*/
|
|
||||||
void fast_reload_thread_stop(struct fast_reload_thread* fast_reload_thread);
|
|
||||||
|
|
||||||
/** fast reload printq delete list */
|
|
||||||
void fast_reload_printq_list_delete(struct fast_reload_printq* list);
|
|
||||||
|
|
||||||
/** Pick up per worker changes after a fast reload. */
|
|
||||||
void fast_reload_worker_pickup_changes(struct worker* worker);
|
|
||||||
|
|
||||||
#endif /* DAEMON_REMOTE_H */
|
#endif /* DAEMON_REMOTE_H */
|
||||||
|
|||||||
+26
-98
@@ -262,7 +262,6 @@ server_stats_compile(struct worker* worker, struct ub_stats_info* s, int reset)
|
|||||||
s->svr = worker->stats;
|
s->svr = worker->stats;
|
||||||
s->mesh_num_states = (long long)worker->env.mesh->all.count;
|
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_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_jostled = (long long)worker->env.mesh->stats_jostled;
|
||||||
s->mesh_dropped = (long long)worker->env.mesh->stats_dropped;
|
s->mesh_dropped = (long long)worker->env.mesh->stats_dropped;
|
||||||
s->mesh_replies_sent = (long long)worker->env.mesh->replies_sent;
|
s->mesh_replies_sent = (long long)worker->env.mesh->replies_sent;
|
||||||
@@ -274,7 +273,6 @@ server_stats_compile(struct worker* worker, struct ub_stats_info* s, int reset)
|
|||||||
/* add in the values from the mesh */
|
/* add in the values from the mesh */
|
||||||
s->svr.ans_secure += (long long)worker->env.mesh->ans_secure;
|
s->svr.ans_secure += (long long)worker->env.mesh->ans_secure;
|
||||||
s->svr.ans_bogus += (long long)worker->env.mesh->ans_bogus;
|
s->svr.ans_bogus += (long long)worker->env.mesh->ans_bogus;
|
||||||
s->svr.val_ops += (long long)worker->env.mesh->val_ops;
|
|
||||||
s->svr.ans_rcode_nodata += (long long)worker->env.mesh->ans_nodata;
|
s->svr.ans_rcode_nodata += (long long)worker->env.mesh->ans_nodata;
|
||||||
s->svr.ans_expired += (long long)worker->env.mesh->ans_expired;
|
s->svr.ans_expired += (long long)worker->env.mesh->ans_expired;
|
||||||
for(i=0; i<UB_STATS_RCODE_NUM; i++)
|
for(i=0; i<UB_STATS_RCODE_NUM; i++)
|
||||||
@@ -283,14 +281,6 @@ server_stats_compile(struct worker* worker, struct ub_stats_info* s, int reset)
|
|||||||
s->svr.rpz_action[i] += (long long)worker->env.mesh->rpz_action[i];
|
s->svr.rpz_action[i] += (long long)worker->env.mesh->rpz_action[i];
|
||||||
timehist_export(worker->env.mesh->histogram, s->svr.hist,
|
timehist_export(worker->env.mesh->histogram, s->svr.hist,
|
||||||
NUM_BUCKETS_HIST);
|
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 +=
|
|
||||||
(long long)worker->env.mesh->num_dns_error_reports;
|
|
||||||
/* values from outside network */
|
/* values from outside network */
|
||||||
s->svr.unwanted_replies = (long long)worker->back->unwanted_replies;
|
s->svr.unwanted_replies = (long long)worker->back->unwanted_replies;
|
||||||
s->svr.qtcp_outgoing = (long long)worker->back->num_tcp_outgoing;
|
s->svr.qtcp_outgoing = (long long)worker->back->num_tcp_outgoing;
|
||||||
@@ -303,10 +293,8 @@ server_stats_compile(struct worker* worker, struct ub_stats_info* s, int reset)
|
|||||||
s->svr.queries_ratelimited = (long long)get_queries_ratelimit(worker, reset);
|
s->svr.queries_ratelimited = (long long)get_queries_ratelimit(worker, reset);
|
||||||
|
|
||||||
/* get cache sizes */
|
/* get cache sizes */
|
||||||
get_slabhash_stats(worker->env.msg_cache,
|
s->svr.msg_cache_count = (long long)count_slabhash_entries(worker->env.msg_cache);
|
||||||
&s->svr.msg_cache_count, &s->svr.msg_cache_max_collisions);
|
s->svr.rrset_cache_count = (long long)count_slabhash_entries(&worker->env.rrset_cache->table);
|
||||||
get_slabhash_stats(&worker->env.rrset_cache->table,
|
|
||||||
&s->svr.rrset_cache_count, &s->svr.rrset_cache_max_collisions);
|
|
||||||
s->svr.infra_cache_count = (long long)count_slabhash_entries(worker->env.infra_cache->hosts);
|
s->svr.infra_cache_count = (long long)count_slabhash_entries(worker->env.infra_cache->hosts);
|
||||||
if(worker->env.key_cache)
|
if(worker->env.key_cache)
|
||||||
s->svr.key_cache_count = (long long)count_slabhash_entries(worker->env.key_cache->slab);
|
s->svr.key_cache_count = (long long)count_slabhash_entries(worker->env.key_cache->slab);
|
||||||
@@ -335,8 +323,20 @@ server_stats_compile(struct worker* worker, struct ub_stats_info* s, int reset)
|
|||||||
s->svr.num_query_dnscrypt_replay = 0;
|
s->svr.num_query_dnscrypt_replay = 0;
|
||||||
#endif /* USE_DNSCRYPT */
|
#endif /* USE_DNSCRYPT */
|
||||||
if(worker->env.auth_zones) {
|
if(worker->env.auth_zones) {
|
||||||
s->svr.num_query_authzone_up += (long long)worker->env.mesh->num_query_authzone_up;
|
if(reset && !worker->env.cfg->stat_cumulative) {
|
||||||
s->svr.num_query_authzone_down += (long long)worker->env.mesh->num_query_authzone_down;
|
lock_rw_wrlock(&worker->env.auth_zones->lock);
|
||||||
|
} else {
|
||||||
|
lock_rw_rdlock(&worker->env.auth_zones->lock);
|
||||||
|
}
|
||||||
|
s->svr.num_query_authzone_up = (long long)worker->env.
|
||||||
|
auth_zones->num_query_up;
|
||||||
|
s->svr.num_query_authzone_down = (long long)worker->env.
|
||||||
|
auth_zones->num_query_down;
|
||||||
|
if(reset && !worker->env.cfg->stat_cumulative) {
|
||||||
|
worker->env.auth_zones->num_query_up = 0;
|
||||||
|
worker->env.auth_zones->num_query_down = 0;
|
||||||
|
}
|
||||||
|
lock_rw_unlock(&worker->env.auth_zones->lock);
|
||||||
}
|
}
|
||||||
s->svr.mem_stream_wait =
|
s->svr.mem_stream_wait =
|
||||||
(long long)tcp_req_info_get_stream_buffer_size();
|
(long long)tcp_req_info_get_stream_buffer_size();
|
||||||
@@ -344,12 +344,6 @@ server_stats_compile(struct worker* worker, struct ub_stats_info* s, int reset)
|
|||||||
(long long)http2_get_query_buffer_size();
|
(long long)http2_get_query_buffer_size();
|
||||||
s->svr.mem_http2_response_buffer =
|
s->svr.mem_http2_response_buffer =
|
||||||
(long long)http2_get_response_buffer_size();
|
(long long)http2_get_response_buffer_size();
|
||||||
#ifdef HAVE_NGTCP2
|
|
||||||
s->svr.mem_quic = (long long)doq_table_quic_size_get(
|
|
||||||
worker->daemon->doq_table);
|
|
||||||
#else
|
|
||||||
s->svr.mem_quic = 0;
|
|
||||||
#endif /* HAVE_NGTCP2 */
|
|
||||||
|
|
||||||
/* Set neg cache usage numbers */
|
/* Set neg cache usage numbers */
|
||||||
set_neg_cache_stats(worker, &s->svr, reset);
|
set_neg_cache_stats(worker, &s->svr, reset);
|
||||||
@@ -360,11 +354,6 @@ server_stats_compile(struct worker* worker, struct ub_stats_info* s, int reset)
|
|||||||
s->svr.num_query_subnet = 0;
|
s->svr.num_query_subnet = 0;
|
||||||
s->svr.num_query_subnet_cache = 0;
|
s->svr.num_query_subnet_cache = 0;
|
||||||
#endif
|
#endif
|
||||||
#ifdef USE_CACHEDB
|
|
||||||
s->svr.num_query_cachedb = (long long)worker->env.mesh->ans_cachedb;
|
|
||||||
#else
|
|
||||||
s->svr.num_query_cachedb = 0;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* get tcp accept usage */
|
/* get tcp accept usage */
|
||||||
s->svr.tcp_accept_usage = 0;
|
s->svr.tcp_accept_usage = 0;
|
||||||
@@ -395,13 +384,6 @@ void server_stats_obtain(struct worker* worker, struct worker* who,
|
|||||||
else worker_send_cmd(who, worker_cmd_stats_noreset);
|
else worker_send_cmd(who, worker_cmd_stats_noreset);
|
||||||
verbose(VERB_ALGO, "wait for stats reply");
|
verbose(VERB_ALGO, "wait for stats reply");
|
||||||
if(tube_wait_timeout(worker->cmd, STATS_THREAD_WAIT) == 0) {
|
if(tube_wait_timeout(worker->cmd, STATS_THREAD_WAIT) == 0) {
|
||||||
#if defined(HAVE_PTHREAD) && defined(SIZEOF_PTHREAD_T) && defined(SIZEOF_UNSIGNED_LONG)
|
|
||||||
# if SIZEOF_PTHREAD_T == SIZEOF_UNSIGNED_LONG
|
|
||||||
unsigned long pthid = 0;
|
|
||||||
if(verbosity >= VERB_OPS)
|
|
||||||
memcpy(&pthid, &who->thr_id, sizeof(unsigned long));
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
verbose(VERB_OPS, "no response from thread %d"
|
verbose(VERB_OPS, "no response from thread %d"
|
||||||
#ifdef HAVE_GETTID
|
#ifdef HAVE_GETTID
|
||||||
" LWP %u"
|
" LWP %u"
|
||||||
@@ -418,32 +400,16 @@ void server_stats_obtain(struct worker* worker, struct worker* who,
|
|||||||
#endif
|
#endif
|
||||||
#if defined(HAVE_PTHREAD) && defined(SIZEOF_PTHREAD_T) && defined(SIZEOF_UNSIGNED_LONG)
|
#if defined(HAVE_PTHREAD) && defined(SIZEOF_PTHREAD_T) && defined(SIZEOF_UNSIGNED_LONG)
|
||||||
# if SIZEOF_PTHREAD_T == SIZEOF_UNSIGNED_LONG
|
# if SIZEOF_PTHREAD_T == SIZEOF_UNSIGNED_LONG
|
||||||
, pthid
|
, (unsigned long)*((unsigned long*)&who->thr_id)
|
||||||
# endif
|
# endif
|
||||||
#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);
|
memcpy(s, reply, (size_t)len);
|
||||||
free(reply);
|
free(reply);
|
||||||
}
|
}
|
||||||
@@ -455,37 +421,23 @@ void server_stats_reply(struct worker* worker, int reset)
|
|||||||
verbose(VERB_ALGO, "write stats replymsg");
|
verbose(VERB_ALGO, "write stats replymsg");
|
||||||
if(!tube_write_msg(worker->daemon->workers[0]->cmd,
|
if(!tube_write_msg(worker->daemon->workers[0]->cmd,
|
||||||
(uint8_t*)&s, sizeof(s), 0))
|
(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)
|
void server_stats_add(struct ub_stats_info* total, struct ub_stats_info* a)
|
||||||
{
|
{
|
||||||
total->svr.num_queries += a->svr.num_queries;
|
total->svr.num_queries += a->svr.num_queries;
|
||||||
total->svr.num_queries_ip_ratelimited += a->svr.num_queries_ip_ratelimited;
|
total->svr.num_queries_ip_ratelimited += a->svr.num_queries_ip_ratelimited;
|
||||||
total->svr.num_queries_cookie_valid += a->svr.num_queries_cookie_valid;
|
|
||||||
total->svr.num_queries_cookie_client += a->svr.num_queries_cookie_client;
|
|
||||||
total->svr.num_queries_cookie_invalid += a->svr.num_queries_cookie_invalid;
|
|
||||||
total->svr.num_queries_discard_timeout +=
|
|
||||||
a->svr.num_queries_discard_timeout;
|
|
||||||
total->svr.num_queries_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;
|
total->svr.num_queries_missed_cache += a->svr.num_queries_missed_cache;
|
||||||
total->svr.num_queries_prefetch += a->svr.num_queries_prefetch;
|
total->svr.num_queries_prefetch += a->svr.num_queries_prefetch;
|
||||||
total->svr.num_queries_timed_out += a->svr.num_queries_timed_out;
|
|
||||||
total->svr.num_query_authzone_up += a->svr.num_query_authzone_up;
|
|
||||||
total->svr.num_query_authzone_down += a->svr.num_query_authzone_down;
|
|
||||||
if (total->svr.max_query_time_us < a->svr.max_query_time_us)
|
|
||||||
total->svr.max_query_time_us = a->svr.max_query_time_us;
|
|
||||||
total->svr.sum_query_list_size += a->svr.sum_query_list_size;
|
total->svr.sum_query_list_size += a->svr.sum_query_list_size;
|
||||||
total->svr.ans_expired += a->svr.ans_expired;
|
total->svr.ans_expired += a->svr.ans_expired;
|
||||||
#ifdef USE_DNSCRYPT
|
#ifdef USE_DNSCRYPT
|
||||||
total->svr.num_query_dnscrypt_crypted += a->svr.num_query_dnscrypt_crypted;
|
total->svr.num_query_dnscrypt_crypted += a->svr.num_query_dnscrypt_crypted;
|
||||||
total->svr.num_query_dnscrypt_cert += a->svr.num_query_dnscrypt_cert;
|
total->svr.num_query_dnscrypt_cert += a->svr.num_query_dnscrypt_cert;
|
||||||
total->svr.num_query_dnscrypt_cleartext +=
|
total->svr.num_query_dnscrypt_cleartext += \
|
||||||
a->svr.num_query_dnscrypt_cleartext;
|
a->svr.num_query_dnscrypt_cleartext;
|
||||||
total->svr.num_query_dnscrypt_crypted_malformed +=
|
total->svr.num_query_dnscrypt_crypted_malformed += \
|
||||||
a->svr.num_query_dnscrypt_crypted_malformed;
|
a->svr.num_query_dnscrypt_crypted_malformed;
|
||||||
#endif /* USE_DNSCRYPT */
|
#endif /* USE_DNSCRYPT */
|
||||||
/* the max size reached is upped to higher of both */
|
/* the max size reached is upped to higher of both */
|
||||||
@@ -502,7 +454,6 @@ void server_stats_add(struct ub_stats_info* total, struct ub_stats_info* a)
|
|||||||
total->svr.qtls += a->svr.qtls;
|
total->svr.qtls += a->svr.qtls;
|
||||||
total->svr.qtls_resume += a->svr.qtls_resume;
|
total->svr.qtls_resume += a->svr.qtls_resume;
|
||||||
total->svr.qhttps += a->svr.qhttps;
|
total->svr.qhttps += a->svr.qhttps;
|
||||||
total->svr.qquic += a->svr.qquic;
|
|
||||||
total->svr.qipv6 += a->svr.qipv6;
|
total->svr.qipv6 += a->svr.qipv6;
|
||||||
total->svr.qbit_QR += a->svr.qbit_QR;
|
total->svr.qbit_QR += a->svr.qbit_QR;
|
||||||
total->svr.qbit_AA += a->svr.qbit_AA;
|
total->svr.qbit_AA += a->svr.qbit_AA;
|
||||||
@@ -517,13 +468,9 @@ void server_stats_add(struct ub_stats_info* total, struct ub_stats_info* a)
|
|||||||
total->svr.ans_rcode_nodata += a->svr.ans_rcode_nodata;
|
total->svr.ans_rcode_nodata += a->svr.ans_rcode_nodata;
|
||||||
total->svr.ans_secure += a->svr.ans_secure;
|
total->svr.ans_secure += a->svr.ans_secure;
|
||||||
total->svr.ans_bogus += a->svr.ans_bogus;
|
total->svr.ans_bogus += a->svr.ans_bogus;
|
||||||
total->svr.val_ops += a->svr.val_ops;
|
|
||||||
total->svr.unwanted_replies += a->svr.unwanted_replies;
|
total->svr.unwanted_replies += a->svr.unwanted_replies;
|
||||||
total->svr.unwanted_queries += a->svr.unwanted_queries;
|
total->svr.unwanted_queries += a->svr.unwanted_queries;
|
||||||
total->svr.tcp_accept_usage += a->svr.tcp_accept_usage;
|
total->svr.tcp_accept_usage += a->svr.tcp_accept_usage;
|
||||||
#ifdef USE_CACHEDB
|
|
||||||
total->svr.num_query_cachedb += a->svr.num_query_cachedb;
|
|
||||||
#endif
|
|
||||||
for(i=0; i<UB_STATS_QTYPE_NUM; i++)
|
for(i=0; i<UB_STATS_QTYPE_NUM; i++)
|
||||||
total->svr.qtype[i] += a->svr.qtype[i];
|
total->svr.qtype[i] += a->svr.qtype[i];
|
||||||
for(i=0; i<UB_STATS_QCLASS_NUM; i++)
|
for(i=0; i<UB_STATS_QCLASS_NUM; i++)
|
||||||
@@ -540,7 +487,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_states += a->mesh_num_states;
|
||||||
total->mesh_num_reply_states += a->mesh_num_reply_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_jostled += a->mesh_jostled;
|
||||||
total->mesh_dropped += a->mesh_dropped;
|
total->mesh_dropped += a->mesh_dropped;
|
||||||
total->mesh_replies_sent += a->mesh_replies_sent;
|
total->mesh_replies_sent += a->mesh_replies_sent;
|
||||||
@@ -564,8 +510,7 @@ void server_stats_insquery(struct ub_server_stats* stats, struct comm_point* c,
|
|||||||
else stats->qclass_big++;
|
else stats->qclass_big++;
|
||||||
stats->qopcode[ LDNS_OPCODE_WIRE(sldns_buffer_begin(c->buffer)) ]++;
|
stats->qopcode[ LDNS_OPCODE_WIRE(sldns_buffer_begin(c->buffer)) ]++;
|
||||||
if(c->type != comm_udp) {
|
if(c->type != comm_udp) {
|
||||||
if(c->type != comm_doq)
|
stats->qtcp++;
|
||||||
stats->qtcp++;
|
|
||||||
if(c->ssl != NULL) {
|
if(c->ssl != NULL) {
|
||||||
stats->qtls++;
|
stats->qtls++;
|
||||||
#ifdef HAVE_SSL
|
#ifdef HAVE_SSL
|
||||||
@@ -574,10 +519,6 @@ void server_stats_insquery(struct ub_server_stats* stats, struct comm_point* c,
|
|||||||
#endif
|
#endif
|
||||||
if(c->type == comm_http)
|
if(c->type == comm_http)
|
||||||
stats->qhttps++;
|
stats->qhttps++;
|
||||||
#ifdef HAVE_NGTCP2
|
|
||||||
else if(c->type == comm_doq)
|
|
||||||
stats->qquic++;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(repinfo && addr_is_ip6(&repinfo->remote_addr, repinfo->remote_addrlen))
|
if(repinfo && addr_is_ip6(&repinfo->remote_addr, repinfo->remote_addrlen))
|
||||||
@@ -614,16 +555,3 @@ void server_stats_insrcode(struct ub_server_stats* stats, sldns_buffer* buf)
|
|||||||
stats->ans_rcode_nodata ++;
|
stats->ans_rcode_nodata ++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void server_stats_downstream_cookie(struct ub_server_stats* stats,
|
|
||||||
struct edns_data* edns)
|
|
||||||
{
|
|
||||||
if(!(edns->edns_present && edns->cookie_present)) return;
|
|
||||||
if(edns->cookie_valid) {
|
|
||||||
stats->num_queries_cookie_valid++;
|
|
||||||
} else if(edns->cookie_client) {
|
|
||||||
stats->num_queries_cookie_client++;
|
|
||||||
} else {
|
|
||||||
stats->num_queries_cookie_invalid++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -126,11 +126,4 @@ void server_stats_insquery(struct ub_server_stats* stats, struct comm_point* c,
|
|||||||
*/
|
*/
|
||||||
void server_stats_insrcode(struct ub_server_stats* stats, struct sldns_buffer* buf);
|
void server_stats_insrcode(struct ub_server_stats* stats, struct sldns_buffer* buf);
|
||||||
|
|
||||||
/**
|
|
||||||
* Add DNS Cookie stats for this query
|
|
||||||
* @param stats: the stats
|
|
||||||
* @param edns: edns record
|
|
||||||
*/
|
|
||||||
void server_stats_downstream_cookie(struct ub_server_stats* stats,
|
|
||||||
struct edns_data* edns);
|
|
||||||
#endif /* DAEMON_STATS_H */
|
#endif /* DAEMON_STATS_H */
|
||||||
|
|||||||
+51
-42
@@ -174,7 +174,7 @@ static void
|
|||||||
checkrlimits(struct config_file* cfg)
|
checkrlimits(struct config_file* cfg)
|
||||||
{
|
{
|
||||||
#ifndef S_SPLINT_S
|
#ifndef S_SPLINT_S
|
||||||
#if defined(HAVE_GETRLIMIT) && !defined(unbound_testbound)
|
#ifdef HAVE_GETRLIMIT
|
||||||
/* list has number of ports to listen to, ifs number addresses */
|
/* list has number of ports to listen to, ifs number addresses */
|
||||||
int list = ((cfg->do_udp?1:0) + (cfg->do_tcp?1 +
|
int list = ((cfg->do_udp?1:0) + (cfg->do_tcp?1 +
|
||||||
(int)cfg->incoming_num_tcp:0));
|
(int)cfg->incoming_num_tcp:0));
|
||||||
@@ -366,8 +366,9 @@ readpid (const char* file)
|
|||||||
/** write pid to file.
|
/** write pid to file.
|
||||||
* @param pidfile: file name of pid file.
|
* @param pidfile: file name of pid file.
|
||||||
* @param pid: pid to write to file.
|
* @param pid: pid to write to file.
|
||||||
|
* @return false on failure
|
||||||
*/
|
*/
|
||||||
static void
|
static int
|
||||||
writepid (const char* pidfile, pid_t pid)
|
writepid (const char* pidfile, pid_t pid)
|
||||||
{
|
{
|
||||||
int fd;
|
int fd;
|
||||||
@@ -382,7 +383,7 @@ writepid (const char* pidfile, pid_t pid)
|
|||||||
, 0644)) == -1) {
|
, 0644)) == -1) {
|
||||||
log_err("cannot open pidfile %s: %s",
|
log_err("cannot open pidfile %s: %s",
|
||||||
pidfile, strerror(errno));
|
pidfile, strerror(errno));
|
||||||
return;
|
return 0;
|
||||||
}
|
}
|
||||||
while(count < strlen(pidbuf)) {
|
while(count < strlen(pidbuf)) {
|
||||||
ssize_t r = write(fd, pidbuf+count, strlen(pidbuf)-count);
|
ssize_t r = write(fd, pidbuf+count, strlen(pidbuf)-count);
|
||||||
@@ -392,16 +393,17 @@ writepid (const char* pidfile, pid_t pid)
|
|||||||
log_err("cannot write to pidfile %s: %s",
|
log_err("cannot write to pidfile %s: %s",
|
||||||
pidfile, strerror(errno));
|
pidfile, strerror(errno));
|
||||||
close(fd);
|
close(fd);
|
||||||
return;
|
return 0;
|
||||||
} else if(r == 0) {
|
} else if(r == 0) {
|
||||||
log_err("cannot write any bytes to pidfile %s: "
|
log_err("cannot write any bytes to pidfile %s: "
|
||||||
"write returns 0 bytes written", pidfile);
|
"write returns 0 bytes written", pidfile);
|
||||||
close(fd);
|
close(fd);
|
||||||
return;
|
return 0;
|
||||||
}
|
}
|
||||||
count += r;
|
count += r;
|
||||||
}
|
}
|
||||||
close(fd);
|
close(fd);
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -463,18 +465,6 @@ detach(void)
|
|||||||
#endif /* HAVE_DAEMON */
|
#endif /* HAVE_DAEMON */
|
||||||
}
|
}
|
||||||
|
|
||||||
/** setup the remote and ticket keys */
|
|
||||||
static void
|
|
||||||
setup_sslctx_remote(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");
|
|
||||||
#else /* HAVE_SSL */
|
|
||||||
(void)daemon;(void)cfg;
|
|
||||||
#endif /* HAVE_SSL */
|
|
||||||
}
|
|
||||||
|
|
||||||
/** daemonize, drop user privileges and chroot if needed */
|
/** daemonize, drop user privileges and chroot if needed */
|
||||||
static void
|
static void
|
||||||
perform_setup(struct daemon* daemon, struct config_file* cfg, int debug_mode,
|
perform_setup(struct daemon* daemon, struct config_file* cfg, int debug_mode,
|
||||||
@@ -485,11 +475,7 @@ perform_setup(struct daemon* daemon, struct config_file* cfg, int debug_mode,
|
|||||||
#endif
|
#endif
|
||||||
#ifdef HAVE_GETPWNAM
|
#ifdef HAVE_GETPWNAM
|
||||||
struct passwd *pwd = NULL;
|
struct passwd *pwd = NULL;
|
||||||
#endif
|
|
||||||
|
|
||||||
if(!daemon_privileged(daemon))
|
|
||||||
fatal_exit("could not do privileged setup");
|
|
||||||
#ifdef HAVE_GETPWNAM
|
|
||||||
if(cfg->username && cfg->username[0]) {
|
if(cfg->username && cfg->username[0]) {
|
||||||
if((pwd = getpwnam(cfg->username)) == NULL)
|
if((pwd = getpwnam(cfg->username)) == NULL)
|
||||||
fatal_exit("user '%s' does not exist.", cfg->username);
|
fatal_exit("user '%s' does not exist.", cfg->username);
|
||||||
@@ -501,8 +487,36 @@ perform_setup(struct daemon* daemon, struct config_file* cfg, int debug_mode,
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* read ssl keys while superuser and outside chroot */
|
/* read ssl keys while superuser and outside chroot */
|
||||||
setup_sslctx_remote(daemon, cfg);
|
#ifdef HAVE_SSL
|
||||||
daemon_setup_sslctxs(daemon, cfg);
|
if(!(daemon->rc = daemon_remote_create(cfg)))
|
||||||
|
fatal_exit("could not set up remote-control");
|
||||||
|
if(cfg->ssl_service_key && cfg->ssl_service_key[0]) {
|
||||||
|
if(!(daemon->listen_sslctx = listen_sslctx_create(
|
||||||
|
cfg->ssl_service_key, cfg->ssl_service_pem, NULL)))
|
||||||
|
fatal_exit("could not set up listen SSL_CTX");
|
||||||
|
if(cfg->tls_ciphers && cfg->tls_ciphers[0]) {
|
||||||
|
if (!SSL_CTX_set_cipher_list(daemon->listen_sslctx, cfg->tls_ciphers)) {
|
||||||
|
fatal_exit("failed to set tls-cipher %s", cfg->tls_ciphers);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
|
||||||
|
if(cfg->tls_ciphersuites && cfg->tls_ciphersuites[0]) {
|
||||||
|
if (!SSL_CTX_set_ciphersuites(daemon->listen_sslctx, cfg->tls_ciphersuites)) {
|
||||||
|
fatal_exit("failed to set tls-ciphersuites %s", cfg->tls_ciphersuites);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if(cfg->tls_session_ticket_keys.first &&
|
||||||
|
cfg->tls_session_ticket_keys.first->str[0] != 0) {
|
||||||
|
if(!listen_sslctx_setup_ticket_keys(daemon->listen_sslctx, cfg->tls_session_ticket_keys.first)) {
|
||||||
|
fatal_exit("could not set session ticket SSL_CTX");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(!(daemon->connect_sslctx = connect_sslctx_create(NULL, NULL,
|
||||||
|
cfg->tls_cert_bundle, cfg->tls_win_cert)))
|
||||||
|
fatal_exit("could not set up connect SSL_CTX");
|
||||||
|
#endif
|
||||||
|
|
||||||
/* init syslog (as root) if needed, before daemonize, otherwise
|
/* init syslog (as root) if needed, before daemonize, otherwise
|
||||||
* a fork error could not be printed since daemonize closed stderr.*/
|
* a fork error could not be printed since daemonize closed stderr.*/
|
||||||
@@ -531,15 +545,7 @@ perform_setup(struct daemon* daemon, struct config_file* cfg, int debug_mode,
|
|||||||
cfg, 1);
|
cfg, 1);
|
||||||
if(!daemon->pidfile)
|
if(!daemon->pidfile)
|
||||||
fatal_exit("pidfile alloc: out of memory");
|
fatal_exit("pidfile alloc: out of memory");
|
||||||
/* Check old pid if there is no username configured.
|
checkoldpid(daemon->pidfile, pidinchroot);
|
||||||
* With a username, the assumption is that the privilege
|
|
||||||
* drop makes a pidfile not removed when the server stopped
|
|
||||||
* last time. The server does not chown the pidfile for it,
|
|
||||||
* because that creates privilege escape problems, with the
|
|
||||||
* pidfile writable by unprivileged users, but used by
|
|
||||||
* privileged users. */
|
|
||||||
if(!(cfg->username && cfg->username[0]))
|
|
||||||
checkoldpid(daemon->pidfile, pidinchroot);
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -551,7 +557,18 @@ perform_setup(struct daemon* daemon, struct config_file* cfg, int debug_mode,
|
|||||||
/* write new pidfile (while still root, so can be outside chroot) */
|
/* write new pidfile (while still root, so can be outside chroot) */
|
||||||
#ifdef HAVE_KILL
|
#ifdef HAVE_KILL
|
||||||
if(cfg->pidfile && cfg->pidfile[0] && need_pidfile) {
|
if(cfg->pidfile && cfg->pidfile[0] && need_pidfile) {
|
||||||
writepid(daemon->pidfile, getpid());
|
if(writepid(daemon->pidfile, getpid())) {
|
||||||
|
if(cfg->username && cfg->username[0] && cfg_uid != (uid_t)-1 &&
|
||||||
|
pidinchroot) {
|
||||||
|
# ifdef HAVE_CHOWN
|
||||||
|
if(chown(daemon->pidfile, cfg_uid, cfg_gid) == -1) {
|
||||||
|
verbose(VERB_QUERY, "cannot chown %u.%u %s: %s",
|
||||||
|
(unsigned)cfg_uid, (unsigned)cfg_gid,
|
||||||
|
daemon->pidfile, strerror(errno));
|
||||||
|
}
|
||||||
|
# endif /* HAVE_CHOWN */
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
(void)daemon;
|
(void)daemon;
|
||||||
@@ -665,9 +682,6 @@ perform_setup(struct daemon* daemon, struct config_file* cfg, int debug_mode,
|
|||||||
* it would succeed on SIGHUP as well */
|
* it would succeed on SIGHUP as well */
|
||||||
if(!cfg->use_syslog)
|
if(!cfg->use_syslog)
|
||||||
log_init(cfg->logfile, cfg->use_syslog, cfg->chrootdir);
|
log_init(cfg->logfile, cfg->use_syslog, cfg->chrootdir);
|
||||||
daemon->cfgfile = strdup(*cfgfile);
|
|
||||||
if(!daemon->cfgfile)
|
|
||||||
fatal_exit("out of memory in daemon cfgfile strdup");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -702,7 +716,6 @@ run_daemon(const char* cfgfile, int cmdline_verbose, int debug_mode, int need_pi
|
|||||||
"the commandline to see more errors, "
|
"the commandline to see more errors, "
|
||||||
"or unbound-checkconf", cfgfile);
|
"or unbound-checkconf", cfgfile);
|
||||||
log_warn("Continuing with default config settings");
|
log_warn("Continuing with default config settings");
|
||||||
config_auto_slab_values(cfg);
|
|
||||||
}
|
}
|
||||||
apply_settings(daemon, cfg, cmdline_verbose, debug_mode);
|
apply_settings(daemon, cfg, cmdline_verbose, debug_mode);
|
||||||
if(!done_setup)
|
if(!done_setup)
|
||||||
@@ -733,11 +746,7 @@ run_daemon(const char* cfgfile, int cmdline_verbose, int debug_mode, int need_pi
|
|||||||
if(daemon->pidfile) {
|
if(daemon->pidfile) {
|
||||||
int fd;
|
int fd;
|
||||||
/* truncate pidfile */
|
/* truncate pidfile */
|
||||||
fd = open(daemon->pidfile, O_WRONLY | O_TRUNC
|
fd = open(daemon->pidfile, O_WRONLY | O_TRUNC, 0644);
|
||||||
#ifdef O_NOFOLLOW
|
|
||||||
| O_NOFOLLOW
|
|
||||||
#endif
|
|
||||||
, 0644);
|
|
||||||
if(fd != -1)
|
if(fd != -1)
|
||||||
close(fd);
|
close(fd);
|
||||||
/* delete pidfile */
|
/* delete pidfile */
|
||||||
|
|||||||
+249
-599
File diff suppressed because it is too large
Load Diff
+9
-14
@@ -47,7 +47,6 @@
|
|||||||
#include "util/netevent.h"
|
#include "util/netevent.h"
|
||||||
#include "util/locks.h"
|
#include "util/locks.h"
|
||||||
#include "util/alloc.h"
|
#include "util/alloc.h"
|
||||||
#include "util/rbtree.h"
|
|
||||||
#include "util/data/msgreply.h"
|
#include "util/data/msgreply.h"
|
||||||
#include "util/data/msgparse.h"
|
#include "util/data/msgparse.h"
|
||||||
#include "daemon/stats.h"
|
#include "daemon/stats.h"
|
||||||
@@ -73,13 +72,7 @@ enum worker_commands {
|
|||||||
/** obtain statistics without statsclear */
|
/** obtain statistics without statsclear */
|
||||||
worker_cmd_stats_noreset,
|
worker_cmd_stats_noreset,
|
||||||
/** execute remote control command */
|
/** execute remote control command */
|
||||||
worker_cmd_remote,
|
worker_cmd_remote
|
||||||
/** for fast-reload, perform stop */
|
|
||||||
worker_cmd_reload_stop,
|
|
||||||
/** for fast-reload, start again */
|
|
||||||
worker_cmd_reload_start,
|
|
||||||
/** for fast-reload, poll to make sure worker has released data */
|
|
||||||
worker_cmd_reload_poll
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -105,6 +98,10 @@ struct worker {
|
|||||||
struct listen_dnsport* front;
|
struct listen_dnsport* front;
|
||||||
/** the backside outside network interface to the auth servers */
|
/** the backside outside network interface to the auth servers */
|
||||||
struct outside_network* back;
|
struct outside_network* back;
|
||||||
|
/** ports to be used by this worker. */
|
||||||
|
int* ports;
|
||||||
|
/** number of ports for this worker */
|
||||||
|
int numports;
|
||||||
/** the signal handler */
|
/** the signal handler */
|
||||||
struct comm_signal* comsig;
|
struct comm_signal* comsig;
|
||||||
/** commpoint to listen to commands. */
|
/** commpoint to listen to commands. */
|
||||||
@@ -121,7 +118,7 @@ struct worker {
|
|||||||
/** do we need to restart or quit (on signal) */
|
/** do we need to restart or quit (on signal) */
|
||||||
int need_to_exit;
|
int need_to_exit;
|
||||||
/** allocation cache for this thread */
|
/** allocation cache for this thread */
|
||||||
struct alloc_cache *alloc;
|
struct alloc_cache alloc;
|
||||||
/** per thread statistics */
|
/** per thread statistics */
|
||||||
struct ub_server_stats stats;
|
struct ub_server_stats stats;
|
||||||
/** thread scratch regional */
|
/** thread scratch regional */
|
||||||
@@ -134,10 +131,6 @@ struct worker {
|
|||||||
/** dnstap environment, changed for this thread */
|
/** dnstap environment, changed for this thread */
|
||||||
struct dt_env dtenv;
|
struct dt_env dtenv;
|
||||||
#endif
|
#endif
|
||||||
/** reuse existing cache on reload if other conditions allow it. */
|
|
||||||
int reuse_cache;
|
|
||||||
/** tree of auth load threads, attached to this worker. */
|
|
||||||
rbtree_type auth_load_tree;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -145,9 +138,11 @@ struct worker {
|
|||||||
* with backpointers only. Use worker_init on it later.
|
* with backpointers only. Use worker_init on it later.
|
||||||
* @param daemon: the daemon that this worker thread is part of.
|
* @param daemon: the daemon that this worker thread is part of.
|
||||||
* @param id: the thread number from 0.. numthreads-1.
|
* @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.
|
* @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.
|
* Initialize worker.
|
||||||
|
|||||||
+65
-137
@@ -59,7 +59,7 @@
|
|||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is the default DNS64 prefix that is used when the dns64 module is listed
|
* This is the default DNS64 prefix that is used whent he dns64 module is listed
|
||||||
* in module-config but when the dns64-prefix variable is not present.
|
* in module-config but when the dns64-prefix variable is not present.
|
||||||
*/
|
*/
|
||||||
static const char DEFAULT_DNS64_PREFIX[] = "64:ff9b::/96";
|
static const char DEFAULT_DNS64_PREFIX[] = "64:ff9b::/96";
|
||||||
@@ -366,23 +366,22 @@ static int
|
|||||||
dns64_apply_cfg(struct dns64_env* dns64_env, struct config_file* cfg)
|
dns64_apply_cfg(struct dns64_env* dns64_env, struct config_file* cfg)
|
||||||
{
|
{
|
||||||
struct config_strlist* s;
|
struct config_strlist* s;
|
||||||
const char* dns64_prefix = cfg->dns64_prefix ?
|
verbose(VERB_ALGO, "dns64-prefix: %s", cfg->dns64_prefix);
|
||||||
cfg->dns64_prefix : DEFAULT_DNS64_PREFIX;
|
if (!netblockstrtoaddr(cfg->dns64_prefix ? cfg->dns64_prefix :
|
||||||
verbose(VERB_ALGO, "dns64-prefix: %s", dns64_prefix);
|
DEFAULT_DNS64_PREFIX, 0, &dns64_env->prefix_addr,
|
||||||
if (!netblockstrtoaddr(dns64_prefix, 0, &dns64_env->prefix_addr,
|
|
||||||
&dns64_env->prefix_addrlen, &dns64_env->prefix_net)) {
|
&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;
|
return 0;
|
||||||
}
|
}
|
||||||
if (!addr_is_ip6(&dns64_env->prefix_addr, dns64_env->prefix_addrlen)) {
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
if (dns64_env->prefix_net != 32 && dns64_env->prefix_net != 40 &&
|
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 != 48 && dns64_env->prefix_net != 56 &&
|
||||||
dns64_env->prefix_net != 64 && dns64_env->prefix_net != 96 ) {
|
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",
|
log_err("dns64-prefix length it not 32, 40, 48, 56, 64 or 96: %s",
|
||||||
dns64_prefix);
|
cfg->dns64_prefix);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
for(s = cfg->dns64_ignore_aaaa; s; s = s->next) {
|
for(s = cfg->dns64_ignore_aaaa; s; s = s->next) {
|
||||||
@@ -497,8 +496,8 @@ handle_ipv6_ptr(struct module_qstate* qstate, int id)
|
|||||||
|
|
||||||
/* Create the new sub-query. */
|
/* Create the new sub-query. */
|
||||||
fptr_ok(fptr_whitelist_modenv_attach_sub(qstate->env->attach_sub));
|
fptr_ok(fptr_whitelist_modenv_attach_sub(qstate->env->attach_sub));
|
||||||
if(!(*qstate->env->attach_sub)(qstate, &qinfo, qstate->client_info,
|
if(!(*qstate->env->attach_sub)(qstate, &qinfo, qstate->query_flags, 0, 0,
|
||||||
qstate->query_flags, 0, 0, &subq))
|
&subq))
|
||||||
return module_error;
|
return module_error;
|
||||||
if (subq) {
|
if (subq) {
|
||||||
subq->curmod = id;
|
subq->curmod = id;
|
||||||
@@ -523,8 +522,8 @@ generate_type_A_query(struct module_qstate* qstate, int id)
|
|||||||
|
|
||||||
/* Start the sub-query. */
|
/* Start the sub-query. */
|
||||||
fptr_ok(fptr_whitelist_modenv_attach_sub(qstate->env->attach_sub));
|
fptr_ok(fptr_whitelist_modenv_attach_sub(qstate->env->attach_sub));
|
||||||
if(!(*qstate->env->attach_sub)(qstate, &qinfo, qstate->client_info,
|
if(!(*qstate->env->attach_sub)(qstate, &qinfo, qstate->query_flags, 0,
|
||||||
qstate->query_flags, 0, 0, &subq))
|
0, &subq))
|
||||||
{
|
{
|
||||||
verbose(VERB_ALGO, "dns64: sub-query creation failed");
|
verbose(VERB_ALGO, "dns64: sub-query creation failed");
|
||||||
return module_error;
|
return module_error;
|
||||||
@@ -574,29 +573,28 @@ static enum module_ext_state
|
|||||||
handle_event_pass(struct module_qstate* qstate, int id)
|
handle_event_pass(struct module_qstate* qstate, int id)
|
||||||
{
|
{
|
||||||
struct dns64_qstate* iq = (struct dns64_qstate*)qstate->minfo[id];
|
struct dns64_qstate* iq = (struct dns64_qstate*)qstate->minfo[id];
|
||||||
int synth_all_cfg = qstate->env->cfg->dns64_synthall;
|
if (iq && iq->state == DNS64_NEW_QUERY
|
||||||
int synth_qname = 0;
|
&& qstate->qinfo.qtype == LDNS_RR_TYPE_PTR
|
||||||
|
&& qstate->qinfo.qname_len == 74
|
||||||
|
&& !strcmp((char*)&qstate->qinfo.qname[64], "\03ip6\04arpa"))
|
||||||
|
/* Handle PTR queries for IPv6 addresses. */
|
||||||
|
return handle_ipv6_ptr(qstate, id);
|
||||||
|
|
||||||
if(iq && iq->state == DNS64_NEW_QUERY
|
if (qstate->env->cfg->dns64_synthall &&
|
||||||
&& qstate->qinfo.qtype == LDNS_RR_TYPE_PTR
|
iq && iq->state == DNS64_NEW_QUERY
|
||||||
&& qstate->qinfo.qname_len == 74
|
&& qstate->qinfo.qtype == LDNS_RR_TYPE_AAAA)
|
||||||
&& !strcmp((char*)&qstate->qinfo.qname[64], "\03ip6\04arpa")) {
|
return generate_type_A_query(qstate, id);
|
||||||
/* Handle PTR queries for IPv6 addresses. */
|
|
||||||
return handle_ipv6_ptr(qstate, id);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(iq && iq->state == DNS64_NEW_QUERY &&
|
if(dns64_always_synth_for_qname(qstate, id) &&
|
||||||
qstate->qinfo.qtype == LDNS_RR_TYPE_AAAA &&
|
iq && iq->state == DNS64_NEW_QUERY
|
||||||
(synth_all_cfg ||
|
&& !(qstate->query_flags & BIT_CD)
|
||||||
(synth_qname=(dns64_always_synth_for_qname(qstate, id)
|
&& qstate->qinfo.qtype == LDNS_RR_TYPE_AAAA) {
|
||||||
&& !(qstate->query_flags & BIT_CD))))) {
|
verbose(VERB_ALGO, "dns64: ignore-aaaa and synthesize anyway");
|
||||||
if(synth_qname)
|
|
||||||
verbose(VERB_ALGO, "dns64: ignore-aaaa and synthesize anyway");
|
|
||||||
return generate_type_A_query(qstate, id);
|
return generate_type_A_query(qstate, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We are finished when our sub-query is finished. */
|
/* We are finished when our sub-query is finished. */
|
||||||
if(iq && iq->state == DNS64_SUBQUERY_FINISHED)
|
if (iq && iq->state == DNS64_SUBQUERY_FINISHED)
|
||||||
return module_finished;
|
return module_finished;
|
||||||
|
|
||||||
/* Otherwise, pass request to next module. */
|
/* Otherwise, pass request to next module. */
|
||||||
@@ -629,47 +627,32 @@ handle_event_moddone(struct module_qstate* qstate, int id)
|
|||||||
* synthesize in (sec 5.1.2 of RFC6147).
|
* synthesize in (sec 5.1.2 of RFC6147).
|
||||||
* - A successful AAAA query with an answer.
|
* - A successful AAAA query with an answer.
|
||||||
*/
|
*/
|
||||||
|
if((!iq || iq->state != DNS64_INTERNAL_QUERY)
|
||||||
|
&& qstate->qinfo.qtype == LDNS_RR_TYPE_AAAA
|
||||||
|
&& !(qstate->query_flags & BIT_CD)
|
||||||
|
&& !(qstate->return_msg &&
|
||||||
|
qstate->return_msg->rep &&
|
||||||
|
reply_find_answer_rrset(&qstate->qinfo,
|
||||||
|
qstate->return_msg->rep)))
|
||||||
|
/* not internal, type AAAA, not CD, and no answer RRset,
|
||||||
|
* So, this is a AAAA noerror/nodata answer */
|
||||||
|
return generate_type_A_query(qstate, id);
|
||||||
|
|
||||||
/* When an AAAA query completes check if we want to perform DNS64
|
if((!iq || iq->state != DNS64_INTERNAL_QUERY)
|
||||||
* synthesis. We skip queries with DNSSEC enabled (!CD) and
|
&& qstate->qinfo.qtype == LDNS_RR_TYPE_AAAA
|
||||||
* ones generated by us to retrieve the A/PTR record to use for
|
&& !(qstate->query_flags & BIT_CD)
|
||||||
* synth. */
|
&& dns64_always_synth_for_qname(qstate, id)) {
|
||||||
int could_synth =
|
/* if it is not internal, AAAA, not CD and listed domain,
|
||||||
qstate->qinfo.qtype == LDNS_RR_TYPE_AAAA &&
|
* generate from A record and ignore AAAA */
|
||||||
(!iq || iq->state != DNS64_INTERNAL_QUERY) &&
|
verbose(VERB_ALGO, "dns64: ignore-aaaa and synthesize anyway");
|
||||||
!(qstate->query_flags & BIT_CD);
|
|
||||||
int has_data = /* whether query returned non-empty rrset */
|
|
||||||
qstate->return_msg &&
|
|
||||||
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 ||
|
|
||||||
(synth_qname=dns64_always_synth_for_qname(qstate, id)))) {
|
|
||||||
if(synth_qname)
|
|
||||||
verbose(VERB_ALGO, "dns64: ignore-aaaa and synthesize anyway");
|
|
||||||
return generate_type_A_query(qstate, id);
|
return generate_type_A_query(qstate, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Store the response in cache. */
|
/* Store the response in cache. */
|
||||||
if( (!iq || !iq->started_no_cache_store) &&
|
if ( (!iq || !iq->started_no_cache_store) &&
|
||||||
!qstate->rpz_applied && !qstate->rpz_passthru &&
|
qstate->return_msg && qstate->return_msg->rep &&
|
||||||
!qstate->is_subnet_answer &&
|
!dns_cache_store(qstate->env, &qstate->qinfo, qstate->return_msg->rep,
|
||||||
qstate->return_msg &&
|
0, 0, 0, NULL, qstate->query_flags, qstate->qstarttime))
|
||||||
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,
|
|
||||||
qstate->query_flags, qstate->qstarttime,
|
|
||||||
qstate->is_valrec))
|
|
||||||
log_err("out of memory");
|
log_err("out of memory");
|
||||||
|
|
||||||
/* do nothing */
|
/* do nothing */
|
||||||
@@ -712,7 +695,6 @@ dns64_operate(struct module_qstate* qstate, enum module_ev event, int id,
|
|||||||
iq->state = DNS64_NEW_QUERY;
|
iq->state = DNS64_NEW_QUERY;
|
||||||
iq->started_no_cache_store = qstate->no_cache_store;
|
iq->started_no_cache_store = qstate->no_cache_store;
|
||||||
qstate->no_cache_store = 1;
|
qstate->no_cache_store = 1;
|
||||||
ATTR_FALLTHROUGH
|
|
||||||
/* fallthrough */
|
/* fallthrough */
|
||||||
case module_event_pass:
|
case module_event_pass:
|
||||||
qstate->ext_state[id] = handle_event_pass(qstate, id);
|
qstate->ext_state[id] = handle_event_pass(qstate, id);
|
||||||
@@ -726,15 +708,8 @@ dns64_operate(struct module_qstate* qstate, enum module_ev event, int id,
|
|||||||
}
|
}
|
||||||
if(qstate->ext_state[id] == module_finished) {
|
if(qstate->ext_state[id] == module_finished) {
|
||||||
iq = (struct dns64_qstate*)qstate->minfo[id];
|
iq = (struct dns64_qstate*)qstate->minfo[id];
|
||||||
if(iq && iq->state != DNS64_INTERNAL_QUERY) {
|
if(iq && iq->state != DNS64_INTERNAL_QUERY)
|
||||||
if(qstate->fwd_stub_no_cache) {
|
qstate->no_cache_store = iq->started_no_cache_store;
|
||||||
/* 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -841,7 +816,6 @@ dns64_adjust_a(int id, struct module_qstate* super, struct module_qstate* qstate
|
|||||||
size_t i, s;
|
size_t i, s;
|
||||||
struct packed_rrset_data* fd, *dd;
|
struct packed_rrset_data* fd, *dd;
|
||||||
struct ub_packed_rrset_key* fk, *dk;
|
struct ub_packed_rrset_key* fk, *dk;
|
||||||
int allocated_return_msg = 0;
|
|
||||||
|
|
||||||
verbose(VERB_ALGO, "converting A answers to AAAA answers");
|
verbose(VERB_ALGO, "converting A answers to AAAA answers");
|
||||||
|
|
||||||
@@ -857,7 +831,6 @@ dns64_adjust_a(int id, struct module_qstate* super, struct module_qstate* qstate
|
|||||||
return;
|
return;
|
||||||
memset(super->return_msg, 0, sizeof(*super->return_msg));
|
memset(super->return_msg, 0, sizeof(*super->return_msg));
|
||||||
super->return_msg->qinfo = super->qinfo;
|
super->return_msg->qinfo = super->qinfo;
|
||||||
allocated_return_msg = 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
rep = qstate->return_msg->rep;
|
rep = qstate->return_msg->rep;
|
||||||
@@ -867,17 +840,13 @@ dns64_adjust_a(int id, struct module_qstate* super, struct module_qstate* qstate
|
|||||||
*/
|
*/
|
||||||
cp = construct_reply_info_base(super->region, rep->flags, rep->qdcount,
|
cp = construct_reply_info_base(super->region, rep->flags, rep->qdcount,
|
||||||
rep->ttl, rep->prefetch_ttl, rep->serve_expired_ttl,
|
rep->ttl, rep->prefetch_ttl, rep->serve_expired_ttl,
|
||||||
rep->serve_expired_norec_ttl,
|
|
||||||
rep->an_numrrsets, rep->ns_numrrsets, rep->ar_numrrsets,
|
rep->an_numrrsets, rep->ns_numrrsets, rep->ar_numrrsets,
|
||||||
rep->rrset_count, rep->security, LDNS_EDE_NONE);
|
rep->rrset_count, rep->security);
|
||||||
if(!cp) {
|
if(!cp)
|
||||||
if(allocated_return_msg) super->return_msg = NULL;
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
/* allocate ub_key structures special or not */
|
/* allocate ub_key structures special or not */
|
||||||
if(!reply_info_alloc_rrset_keys(cp, NULL, super->region)) {
|
if(!reply_info_alloc_rrset_keys(cp, NULL, super->region)) {
|
||||||
if(allocated_return_msg) super->return_msg = NULL;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -892,10 +861,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)) {
|
if(i<rep->an_numrrsets && fk->rk.type == htons(LDNS_RR_TYPE_A)) {
|
||||||
/* also sets dk->entry.hash */
|
/* also sets dk->entry.hash */
|
||||||
dns64_synth_aaaa_data(fk, fd, dk, &dd, super->region, dns64_env);
|
dns64_synth_aaaa_data(fk, fd, dk, &dd, super->region, dns64_env);
|
||||||
if(!dd) {
|
if(!dd)
|
||||||
if(allocated_return_msg) super->return_msg = NULL;
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
/* Delete negative AAAA record from cache stored by
|
/* Delete negative AAAA record from cache stored by
|
||||||
* the iterator module */
|
* the iterator module */
|
||||||
rrset_cache_remove(super->env->rrset_cache, dk->rk.dname,
|
rrset_cache_remove(super->env->rrset_cache, dk->rk.dname,
|
||||||
@@ -912,19 +879,15 @@ dns64_adjust_a(int id, struct module_qstate* super, struct module_qstate* qstate
|
|||||||
dk->rk.dname = (uint8_t*)regional_alloc_init(super->region,
|
dk->rk.dname = (uint8_t*)regional_alloc_init(super->region,
|
||||||
fk->rk.dname, fk->rk.dname_len);
|
fk->rk.dname, fk->rk.dname_len);
|
||||||
|
|
||||||
if(!dk->rk.dname) {
|
if(!dk->rk.dname)
|
||||||
if(allocated_return_msg) super->return_msg = NULL;
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
s = packed_rrset_sizeof(fd);
|
s = packed_rrset_sizeof(fd);
|
||||||
dd = (struct packed_rrset_data*)regional_alloc_init(
|
dd = (struct packed_rrset_data*)regional_alloc_init(
|
||||||
super->region, fd, s);
|
super->region, fd, s);
|
||||||
|
|
||||||
if(!dd) {
|
if(!dd)
|
||||||
if(allocated_return_msg) super->return_msg = NULL;
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
packed_rrset_ptr_fixup(dd);
|
packed_rrset_ptr_fixup(dd);
|
||||||
@@ -955,10 +918,8 @@ dns64_adjust_ptr(struct module_qstate* qstate, struct module_qstate* super)
|
|||||||
return;
|
return;
|
||||||
super->return_msg->qinfo = super->qinfo;
|
super->return_msg->qinfo = super->qinfo;
|
||||||
if (!(super->return_msg->rep = reply_info_copy(qstate->return_msg->rep,
|
if (!(super->return_msg->rep = reply_info_copy(qstate->return_msg->rep,
|
||||||
NULL, super->region))) {
|
NULL, super->region)))
|
||||||
super->return_msg = NULL;
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Adjust the domain name of the answer RR set so that it matches the
|
* Adjust the domain name of the answer RR set so that it matches the
|
||||||
@@ -968,7 +929,6 @@ dns64_adjust_ptr(struct module_qstate* qstate, struct module_qstate* super)
|
|||||||
if(answer) {
|
if(answer) {
|
||||||
answer->rk.dname = super->qinfo.qname;
|
answer->rk.dname = super->qinfo.qname;
|
||||||
answer->rk.dname_len = super->qinfo.qname_len;
|
answer->rk.dname_len = super->qinfo.qname_len;
|
||||||
answer->entry.hash = rrset_key_hash(&answer->rk);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1009,40 +969,16 @@ dns64_inform_super(struct module_qstate* qstate, int id,
|
|||||||
}
|
}
|
||||||
super_dq->state = DNS64_SUBQUERY_FINISHED;
|
super_dq->state = DNS64_SUBQUERY_FINISHED;
|
||||||
|
|
||||||
/* If there is no successful answer, we're done.
|
/* If there is no successful answer, we're done. */
|
||||||
* Guarantee that we have at least a NOERROR reply further on. */
|
if (qstate->return_rcode != LDNS_RCODE_NOERROR
|
||||||
if(qstate->return_rcode != LDNS_RCODE_NOERROR
|
|| !qstate->return_msg
|
||||||
|| !qstate->return_msg
|
|| !qstate->return_msg->rep) {
|
||||||
|| !qstate->return_msg->rep) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* When no A record is found for synthesis fall back to AAAA again. */
|
|
||||||
if(qstate->qinfo.qtype == LDNS_RR_TYPE_A &&
|
|
||||||
!reply_find_answer_rrset(&qstate->qinfo,
|
|
||||||
qstate->return_msg->rep)) {
|
|
||||||
super_dq->state = DNS64_INTERNAL_QUERY;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Use return code from A query in response to client. */
|
/* Use return code from A query in response to client. */
|
||||||
if (super->return_rcode != LDNS_RCODE_NOERROR)
|
if (super->return_rcode != LDNS_RCODE_NOERROR)
|
||||||
super->return_rcode = qstate->return_rcode;
|
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. */
|
/* Generate a response suitable for the original query. */
|
||||||
if (qstate->qinfo.qtype == LDNS_RR_TYPE_A) {
|
if (qstate->qinfo.qtype == LDNS_RR_TYPE_A) {
|
||||||
@@ -1051,19 +987,11 @@ dns64_inform_super(struct module_qstate* qstate, int id,
|
|||||||
log_assert(qstate->qinfo.qtype == LDNS_RR_TYPE_PTR);
|
log_assert(qstate->qinfo.qtype == LDNS_RR_TYPE_PTR);
|
||||||
dns64_adjust_ptr(qstate, super);
|
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. */
|
/* Store the generated response in cache. */
|
||||||
if ( super->return_msg && super->return_msg->rep &&
|
if ( (!super_dq || !super_dq->started_no_cache_store) &&
|
||||||
(!super_dq || !super_dq->started_no_cache_store) &&
|
|
||||||
!qstate->fwd_stub_no_cache &&
|
|
||||||
!super->rpz_applied && !super->rpz_passthru &&
|
|
||||||
!super->is_subnet_answer &&
|
|
||||||
!dns_cache_store(super->env, &super->qinfo, super->return_msg->rep,
|
!dns_cache_store(super->env, &super->qinfo, super->return_msg->rep,
|
||||||
0, super->prefetch_leeway, 0, NULL, super->query_flags,
|
0, 0, 0, NULL, super->query_flags, qstate->qstarttime))
|
||||||
qstate->qstarttime, qstate->is_valrec))
|
|
||||||
log_err("out of memory");
|
log_err("out of memory");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1101,8 +1029,8 @@ dns64_get_mem(struct module_env* env, int id)
|
|||||||
*/
|
*/
|
||||||
static struct module_func_block dns64_block = {
|
static struct module_func_block dns64_block = {
|
||||||
"dns64",
|
"dns64",
|
||||||
NULL, NULL, &dns64_init, &dns64_deinit, &dns64_operate,
|
&dns64_init, &dns64_deinit, &dns64_operate, &dns64_inform_super,
|
||||||
&dns64_inform_super, &dns64_clear, &dns64_get_mem
|
&dns64_clear, &dns64_get_mem
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
+5
-32
@@ -361,7 +361,7 @@ dnscrypt_server_uncurve(struct dnsc_env* env,
|
|||||||
|
|
||||||
len -= DNSCRYPT_QUERY_HEADER_SIZE;
|
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) {
|
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);
|
uint8_t *const buf = sldns_buffer_begin(buffer);
|
||||||
size_t len = sldns_buffer_limit(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(udp){
|
||||||
if (max_len > max_reply_size)
|
if (max_len > max_reply_size)
|
||||||
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);
|
memcpy(nonce, client_nonce, crypto_box_HALF_NONCEBYTES);
|
||||||
@@ -528,7 +520,6 @@ dnscrypt_server_curve(const dnsccert *cert,
|
|||||||
DNSCRYPT_MAGIC_HEADER_LEN,
|
DNSCRYPT_MAGIC_HEADER_LEN,
|
||||||
nonce,
|
nonce,
|
||||||
crypto_box_NONCEBYTES);
|
crypto_box_NONCEBYTES);
|
||||||
sldns_buffer_flip(buffer);
|
|
||||||
sldns_buffer_set_limit(buffer, len + DNSCRYPT_REPLY_HEADER_SIZE);
|
sldns_buffer_set_limit(buffer, len + DNSCRYPT_REPLY_HEADER_SIZE);
|
||||||
return 0;
|
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);
|
dnscrypt_header = (struct dnscrypt_query_header *)sldns_buffer_begin(buffer);
|
||||||
for (i = 0U; i < dnscenv->signed_certs_count; i++) {
|
for (i = 0U; i < dnscenv->signed_certs_count; i++) {
|
||||||
if(!certs[i].keypair)
|
|
||||||
continue;
|
|
||||||
if (memcmp(certs[i].magic_query, dnscrypt_header->magic_query,
|
if (memcmp(certs[i].magic_query, dnscrypt_header->magic_query,
|
||||||
DNSCRYPT_MAGIC_HEADER_LEN) == 0) {
|
DNSCRYPT_MAGIC_HEADER_LEN) == 0) {
|
||||||
return &certs[i];
|
return &certs[i];
|
||||||
@@ -815,7 +804,6 @@ dnsc_parse_keys(struct dnsc_env *env, struct config_file *cfg)
|
|||||||
sizeof *env->keypairs);
|
sizeof *env->keypairs);
|
||||||
env->certs = sodium_allocarray(env->signed_certs_count,
|
env->certs = sodium_allocarray(env->signed_certs_count,
|
||||||
sizeof *env->certs);
|
sizeof *env->certs);
|
||||||
memset(env->certs, 0, env->signed_certs_count * sizeof(*env->certs));
|
|
||||||
|
|
||||||
cert_id = 0U;
|
cert_id = 0U;
|
||||||
keypair_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,
|
if(memcmp(current_keypair->crypt_publickey,
|
||||||
env->signed_certs[c].server_publickey,
|
env->signed_certs[c].server_publickey,
|
||||||
crypto_box_PUBLICKEYBYTES) == 0) {
|
crypto_box_PUBLICKEYBYTES) == 0) {
|
||||||
dnsccert* current_cert;
|
dnsccert *current_cert = &env->certs[cert_id++];
|
||||||
if(cert_id >= env->signed_certs_count) {
|
|
||||||
log_err("dnscrypt: secret key %s matches a cert that "
|
|
||||||
"is already bound to another key (duplicate "
|
|
||||||
"dnscrypt-secret-key?)", head->str);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
current_cert = &env->certs[cert_id++];
|
|
||||||
found_cert = 1;
|
found_cert = 1;
|
||||||
current_cert->keypair = current_keypair;
|
current_cert->keypair = current_keypair;
|
||||||
memcpy(current_cert->magic_query,
|
memcpy(current_cert->magic_query,
|
||||||
@@ -931,13 +912,12 @@ dnsc_handle_curved_request(struct dnsc_env* dnscenv,
|
|||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
dnsc_handle_uncurved_request(struct comm_reply *repinfo,
|
dnsc_handle_uncurved_request(struct comm_reply *repinfo)
|
||||||
struct sldns_buffer* buffer)
|
|
||||||
{
|
{
|
||||||
if(!repinfo->c->dnscrypt) {
|
if(!repinfo->c->dnscrypt) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
sldns_buffer_copy(repinfo->c->dnscrypt_buffer, buffer);
|
sldns_buffer_copy(repinfo->c->dnscrypt_buffer, repinfo->c->buffer);
|
||||||
if(!repinfo->is_dnscrypted) {
|
if(!repinfo->is_dnscrypted) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -983,19 +963,12 @@ dnsc_create(void)
|
|||||||
int
|
int
|
||||||
dnsc_apply_cfg(struct dnsc_env *env, struct config_file *cfg)
|
dnsc_apply_cfg(struct dnsc_env *env, struct config_file *cfg)
|
||||||
{
|
{
|
||||||
int nkeys;
|
|
||||||
if(dnsc_parse_certs(env, cfg) <= 0) {
|
if(dnsc_parse_certs(env, cfg) <= 0) {
|
||||||
fatal_exit("dnsc_apply_cfg: no cert file loaded");
|
fatal_exit("dnsc_apply_cfg: no cert file loaded");
|
||||||
}
|
}
|
||||||
nkeys = dnsc_parse_keys(env, cfg);
|
if(dnsc_parse_keys(env, cfg) <= 0) {
|
||||||
if(nkeys <= 0) {
|
|
||||||
fatal_exit("dnsc_apply_cfg: no key file loaded");
|
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);
|
randombytes_buf(env->hash_key, sizeof env->hash_key);
|
||||||
env->provider_name = cfg->dnscrypt_provider;
|
env->provider_name = cfg->dnscrypt_provider;
|
||||||
|
|
||||||
|
|||||||
+1
-2
@@ -128,8 +128,7 @@ int dnsc_handle_curved_request(struct dnsc_env* dnscenv,
|
|||||||
* \return 0 in case of failure.
|
* \return 0 in case of failure.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int dnsc_handle_uncurved_request(struct comm_reply *repinfo,
|
int dnsc_handle_uncurved_request(struct comm_reply *repinfo);
|
||||||
struct sldns_buffer* buffer);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Computes the size of the shared secret cache entry.
|
* Computes the size of the shared secret cache entry.
|
||||||
|
|||||||
+34
-127
@@ -86,31 +86,6 @@ dt_pack(const Dnstap__Dnstap *d, void **buf, size_t *sz)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** See if the message is sent due to dnstap sample rate */
|
|
||||||
static int
|
|
||||||
dt_sample_rate_limited(struct dt_env* env)
|
|
||||||
{
|
|
||||||
lock_basic_lock(&env->sample_lock);
|
|
||||||
/* Sampling is every [n] packets. Where n==1, every packet is sent */
|
|
||||||
if(env->sample_rate > 1) {
|
|
||||||
int submit = 0;
|
|
||||||
/* if sampling is engaged... */
|
|
||||||
if (env->sample_rate_count > env->sample_rate) {
|
|
||||||
/* once the count passes the limit */
|
|
||||||
/* submit the message */
|
|
||||||
submit = 1;
|
|
||||||
/* and reset the count */
|
|
||||||
env->sample_rate_count = 0;
|
|
||||||
}
|
|
||||||
/* increment count regardless */
|
|
||||||
env->sample_rate_count++;
|
|
||||||
lock_basic_unlock(&env->sample_lock);
|
|
||||||
return !submit;
|
|
||||||
}
|
|
||||||
lock_basic_unlock(&env->sample_lock);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
dt_send(const struct dt_env *env, void *buf, size_t len_buf)
|
dt_send(const struct dt_env *env, void *buf, size_t len_buf)
|
||||||
{
|
{
|
||||||
@@ -171,89 +146,71 @@ dt_create(struct config_file* cfg)
|
|||||||
env = (struct dt_env *) calloc(1, sizeof(struct dt_env));
|
env = (struct dt_env *) calloc(1, sizeof(struct dt_env));
|
||||||
if (!env)
|
if (!env)
|
||||||
return NULL;
|
return NULL;
|
||||||
lock_basic_init(&env->sample_lock);
|
|
||||||
|
|
||||||
env->dtio = dt_io_thread_create();
|
env->dtio = dt_io_thread_create();
|
||||||
if(!env->dtio) {
|
if(!env->dtio) {
|
||||||
log_err("malloc failure");
|
log_err("malloc failure");
|
||||||
dt_delete(env);
|
free(env);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if(!dt_io_thread_apply_cfg(env->dtio, cfg)) {
|
if(!dt_io_thread_apply_cfg(env->dtio, cfg)) {
|
||||||
dt_delete(env);
|
dt_io_thread_delete(env->dtio);
|
||||||
return NULL;
|
free(env);
|
||||||
}
|
|
||||||
if(!dt_apply_cfg(env, cfg)) {
|
|
||||||
dt_delete(env);
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
dt_apply_cfg(env, cfg);
|
||||||
return env;
|
return env;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static void
|
||||||
dt_apply_identity(struct dt_env *env, struct config_file *cfg)
|
dt_apply_identity(struct dt_env *env, struct config_file *cfg)
|
||||||
{
|
{
|
||||||
char buf[MAXHOSTNAMELEN+1];
|
char buf[MAXHOSTNAMELEN+1];
|
||||||
if (!cfg->dnstap_send_identity) {
|
if (!cfg->dnstap_send_identity)
|
||||||
free(env->identity);
|
return;
|
||||||
env->identity = NULL;
|
|
||||||
env->len_identity = 0;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
free(env->identity);
|
free(env->identity);
|
||||||
if (cfg->dnstap_identity == NULL || cfg->dnstap_identity[0] == 0) {
|
if (cfg->dnstap_identity == NULL || cfg->dnstap_identity[0] == 0) {
|
||||||
if (gethostname(buf, MAXHOSTNAMELEN) == 0) {
|
if (gethostname(buf, MAXHOSTNAMELEN) == 0) {
|
||||||
buf[MAXHOSTNAMELEN] = 0;
|
buf[MAXHOSTNAMELEN] = 0;
|
||||||
env->identity = strdup(buf);
|
env->identity = strdup(buf);
|
||||||
} else {
|
} else {
|
||||||
log_err("dt_apply_identity: gethostname() failed: %s",
|
fatal_exit("dt_apply_identity: gethostname() failed");
|
||||||
strerror(errno));
|
|
||||||
env->identity = NULL;
|
|
||||||
env->len_identity = 0;
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
env->identity = strdup(cfg->dnstap_identity);
|
env->identity = strdup(cfg->dnstap_identity);
|
||||||
}
|
}
|
||||||
if (env->identity == NULL) {
|
if (env->identity == NULL)
|
||||||
log_err("dt_apply_identity: strdup() failed");
|
fatal_exit("dt_apply_identity: strdup() failed");
|
||||||
env->len_identity = 0;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
env->len_identity = (unsigned int)strlen(env->identity);
|
env->len_identity = (unsigned int)strlen(env->identity);
|
||||||
verbose(VERB_OPS, "dnstap identity field set to \"%s\"",
|
verbose(VERB_OPS, "dnstap identity field set to \"%s\"",
|
||||||
env->identity);
|
env->identity);
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static void
|
||||||
dt_apply_version(struct dt_env *env, struct config_file *cfg)
|
dt_apply_version(struct dt_env *env, struct config_file *cfg)
|
||||||
{
|
{
|
||||||
if (!cfg->dnstap_send_version) {
|
if (!cfg->dnstap_send_version)
|
||||||
free(env->version);
|
return;
|
||||||
env->version = NULL;
|
|
||||||
env->len_version = 0;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
free(env->version);
|
free(env->version);
|
||||||
if (cfg->dnstap_version == NULL || cfg->dnstap_version[0] == 0)
|
if (cfg->dnstap_version == NULL || cfg->dnstap_version[0] == 0)
|
||||||
env->version = strdup(PACKAGE_STRING);
|
env->version = strdup(PACKAGE_STRING);
|
||||||
else
|
else
|
||||||
env->version = strdup(cfg->dnstap_version);
|
env->version = strdup(cfg->dnstap_version);
|
||||||
if (env->version == NULL) {
|
if (env->version == NULL)
|
||||||
log_err("dt_apply_version: strdup() failed");
|
fatal_exit("dt_apply_version: strdup() failed");
|
||||||
env->len_version = 0;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
env->len_version = (unsigned int)strlen(env->version);
|
env->len_version = (unsigned int)strlen(env->version);
|
||||||
verbose(VERB_OPS, "dnstap version field set to \"%s\"",
|
verbose(VERB_OPS, "dnstap version field set to \"%s\"",
|
||||||
env->version);
|
env->version);
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
dt_apply_logcfg(struct dt_env *env, struct config_file *cfg)
|
dt_apply_cfg(struct dt_env *env, struct config_file *cfg)
|
||||||
{
|
{
|
||||||
|
if (!cfg->dnstap)
|
||||||
|
return;
|
||||||
|
|
||||||
|
dt_apply_identity(env, cfg);
|
||||||
|
dt_apply_version(env, cfg);
|
||||||
if ((env->log_resolver_query_messages = (unsigned int)
|
if ((env->log_resolver_query_messages = (unsigned int)
|
||||||
cfg->dnstap_log_resolver_query_messages))
|
cfg->dnstap_log_resolver_query_messages))
|
||||||
{
|
{
|
||||||
@@ -284,26 +241,6 @@ dt_apply_logcfg(struct dt_env *env, struct config_file *cfg)
|
|||||||
{
|
{
|
||||||
verbose(VERB_OPS, "dnstap Message/FORWARDER_RESPONSE enabled");
|
verbose(VERB_OPS, "dnstap Message/FORWARDER_RESPONSE enabled");
|
||||||
}
|
}
|
||||||
lock_basic_lock(&env->sample_lock);
|
|
||||||
if((env->sample_rate = (unsigned int)cfg->dnstap_sample_rate))
|
|
||||||
{
|
|
||||||
verbose(VERB_OPS, "dnstap SAMPLE_RATE enabled and set to \"%d\"", (int)env->sample_rate);
|
|
||||||
}
|
|
||||||
lock_basic_unlock(&env->sample_lock);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
dt_apply_cfg(struct dt_env *env, struct config_file *cfg)
|
|
||||||
{
|
|
||||||
if (!cfg->dnstap)
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
dt_apply_logcfg(env, cfg);
|
|
||||||
if(!dt_apply_identity(env, cfg))
|
|
||||||
return 0;
|
|
||||||
if(!dt_apply_version(env, cfg))
|
|
||||||
return 0;
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
@@ -336,7 +273,6 @@ dt_delete(struct dt_env *env)
|
|||||||
if (!env)
|
if (!env)
|
||||||
return;
|
return;
|
||||||
dt_io_thread_delete(env->dtio);
|
dt_io_thread_delete(env->dtio);
|
||||||
lock_basic_destroy(&env->sample_lock);
|
|
||||||
free(env->identity);
|
free(env->identity);
|
||||||
free(env->version);
|
free(env->version);
|
||||||
free(env);
|
free(env);
|
||||||
@@ -369,7 +305,6 @@ dt_msg_fill_net(struct dt_msg *dm,
|
|||||||
struct sockaddr_storage *qs,
|
struct sockaddr_storage *qs,
|
||||||
struct sockaddr_storage *rs,
|
struct sockaddr_storage *rs,
|
||||||
enum comm_point_type cptype,
|
enum comm_point_type cptype,
|
||||||
void *cpssl,
|
|
||||||
ProtobufCBinaryData *qaddr, protobuf_c_boolean *has_qaddr,
|
ProtobufCBinaryData *qaddr, protobuf_c_boolean *has_qaddr,
|
||||||
uint32_t *qport, protobuf_c_boolean *has_qport,
|
uint32_t *qport, protobuf_c_boolean *has_qport,
|
||||||
ProtobufCBinaryData *raddr, protobuf_c_boolean *has_raddr,
|
ProtobufCBinaryData *raddr, protobuf_c_boolean *has_raddr,
|
||||||
@@ -436,26 +371,13 @@ dt_msg_fill_net(struct dt_msg *dm,
|
|||||||
*has_rport = 1;
|
*has_rport = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log_assert(cptype == comm_udp || cptype == comm_tcp);
|
||||||
if (cptype == comm_udp) {
|
if (cptype == comm_udp) {
|
||||||
/* socket_protocol */
|
/* socket_protocol */
|
||||||
dm->m.socket_protocol = DNSTAP__SOCKET_PROTOCOL__UDP;
|
dm->m.socket_protocol = DNSTAP__SOCKET_PROTOCOL__UDP;
|
||||||
dm->m.has_socket_protocol = 1;
|
dm->m.has_socket_protocol = 1;
|
||||||
} else if (cptype == comm_tcp) {
|
} else if (cptype == comm_tcp) {
|
||||||
if (cpssl == NULL) {
|
|
||||||
/* socket_protocol */
|
|
||||||
dm->m.socket_protocol = DNSTAP__SOCKET_PROTOCOL__TCP;
|
|
||||||
dm->m.has_socket_protocol = 1;
|
|
||||||
} else {
|
|
||||||
/* socket_protocol */
|
|
||||||
dm->m.socket_protocol = DNSTAP__SOCKET_PROTOCOL__DOT;
|
|
||||||
dm->m.has_socket_protocol = 1;
|
|
||||||
}
|
|
||||||
} else if (cptype == comm_http) {
|
|
||||||
/* socket_protocol */
|
/* socket_protocol */
|
||||||
dm->m.socket_protocol = DNSTAP__SOCKET_PROTOCOL__DOH;
|
|
||||||
dm->m.has_socket_protocol = 1;
|
|
||||||
} else {
|
|
||||||
/* other socket protocol */
|
|
||||||
dm->m.socket_protocol = DNSTAP__SOCKET_PROTOCOL__TCP;
|
dm->m.socket_protocol = DNSTAP__SOCKET_PROTOCOL__TCP;
|
||||||
dm->m.has_socket_protocol = 1;
|
dm->m.has_socket_protocol = 1;
|
||||||
}
|
}
|
||||||
@@ -466,19 +388,12 @@ dt_msg_send_client_query(struct dt_env *env,
|
|||||||
struct sockaddr_storage *qsock,
|
struct sockaddr_storage *qsock,
|
||||||
struct sockaddr_storage *rsock,
|
struct sockaddr_storage *rsock,
|
||||||
enum comm_point_type cptype,
|
enum comm_point_type cptype,
|
||||||
void *cpssl,
|
sldns_buffer *qmsg)
|
||||||
sldns_buffer *qmsg,
|
|
||||||
struct timeval* tstamp)
|
|
||||||
{
|
{
|
||||||
struct dt_msg dm;
|
struct dt_msg dm;
|
||||||
struct timeval qtime;
|
struct timeval qtime;
|
||||||
|
|
||||||
if(dt_sample_rate_limited(env))
|
gettimeofday(&qtime, NULL);
|
||||||
return;
|
|
||||||
|
|
||||||
if(tstamp)
|
|
||||||
memcpy(&qtime, tstamp, sizeof(qtime));
|
|
||||||
else gettimeofday(&qtime, NULL);
|
|
||||||
|
|
||||||
/* type */
|
/* type */
|
||||||
dt_msg_init(env, &dm, DNSTAP__MESSAGE__TYPE__CLIENT_QUERY);
|
dt_msg_init(env, &dm, DNSTAP__MESSAGE__TYPE__CLIENT_QUERY);
|
||||||
@@ -492,7 +407,8 @@ dt_msg_send_client_query(struct dt_env *env,
|
|||||||
dt_fill_buffer(qmsg, &dm.m.query_message, &dm.m.has_query_message);
|
dt_fill_buffer(qmsg, &dm.m.query_message, &dm.m.has_query_message);
|
||||||
|
|
||||||
/* socket_family, socket_protocol, query_address, query_port, response_address, response_port */
|
/* socket_family, socket_protocol, query_address, query_port, response_address, response_port */
|
||||||
dt_msg_fill_net(&dm, qsock, rsock, cptype, cpssl,
|
log_assert(cptype == comm_udp || cptype == comm_tcp);
|
||||||
|
dt_msg_fill_net(&dm, qsock, rsock, cptype,
|
||||||
&dm.m.query_address, &dm.m.has_query_address,
|
&dm.m.query_address, &dm.m.has_query_address,
|
||||||
&dm.m.query_port, &dm.m.has_query_port,
|
&dm.m.query_port, &dm.m.has_query_port,
|
||||||
&dm.m.response_address, &dm.m.has_response_address,
|
&dm.m.response_address, &dm.m.has_response_address,
|
||||||
@@ -508,15 +424,11 @@ dt_msg_send_client_response(struct dt_env *env,
|
|||||||
struct sockaddr_storage *qsock,
|
struct sockaddr_storage *qsock,
|
||||||
struct sockaddr_storage *rsock,
|
struct sockaddr_storage *rsock,
|
||||||
enum comm_point_type cptype,
|
enum comm_point_type cptype,
|
||||||
void *cpssl,
|
|
||||||
sldns_buffer *rmsg)
|
sldns_buffer *rmsg)
|
||||||
{
|
{
|
||||||
struct dt_msg dm;
|
struct dt_msg dm;
|
||||||
struct timeval rtime;
|
struct timeval rtime;
|
||||||
|
|
||||||
if(dt_sample_rate_limited(env))
|
|
||||||
return;
|
|
||||||
|
|
||||||
gettimeofday(&rtime, NULL);
|
gettimeofday(&rtime, NULL);
|
||||||
|
|
||||||
/* type */
|
/* type */
|
||||||
@@ -531,7 +443,8 @@ dt_msg_send_client_response(struct dt_env *env,
|
|||||||
dt_fill_buffer(rmsg, &dm.m.response_message, &dm.m.has_response_message);
|
dt_fill_buffer(rmsg, &dm.m.response_message, &dm.m.has_response_message);
|
||||||
|
|
||||||
/* socket_family, socket_protocol, query_address, query_port, response_address, response_port */
|
/* socket_family, socket_protocol, query_address, query_port, response_address, response_port */
|
||||||
dt_msg_fill_net(&dm, qsock, rsock, cptype, cpssl,
|
log_assert(cptype == comm_udp || cptype == comm_tcp);
|
||||||
|
dt_msg_fill_net(&dm, qsock, rsock, cptype,
|
||||||
&dm.m.query_address, &dm.m.has_query_address,
|
&dm.m.query_address, &dm.m.has_query_address,
|
||||||
&dm.m.query_port, &dm.m.has_query_port,
|
&dm.m.query_port, &dm.m.has_query_port,
|
||||||
&dm.m.response_address, &dm.m.has_response_address,
|
&dm.m.response_address, &dm.m.has_response_address,
|
||||||
@@ -546,7 +459,6 @@ dt_msg_send_outside_query(struct dt_env *env,
|
|||||||
struct sockaddr_storage *rsock,
|
struct sockaddr_storage *rsock,
|
||||||
struct sockaddr_storage *qsock,
|
struct sockaddr_storage *qsock,
|
||||||
enum comm_point_type cptype,
|
enum comm_point_type cptype,
|
||||||
void *cpssl,
|
|
||||||
uint8_t *zone, size_t zone_len,
|
uint8_t *zone, size_t zone_len,
|
||||||
sldns_buffer *qmsg)
|
sldns_buffer *qmsg)
|
||||||
{
|
{
|
||||||
@@ -554,14 +466,11 @@ dt_msg_send_outside_query(struct dt_env *env,
|
|||||||
struct timeval qtime;
|
struct timeval qtime;
|
||||||
uint16_t qflags;
|
uint16_t qflags;
|
||||||
|
|
||||||
if(dt_sample_rate_limited(env))
|
|
||||||
return;
|
|
||||||
|
|
||||||
gettimeofday(&qtime, NULL);
|
gettimeofday(&qtime, NULL);
|
||||||
qflags = sldns_buffer_read_u16_at(qmsg, 2);
|
qflags = sldns_buffer_read_u16_at(qmsg, 2);
|
||||||
|
|
||||||
/* type */
|
/* type */
|
||||||
if ((qflags & BIT_RD)) {
|
if (qflags & BIT_RD) {
|
||||||
if (!env->log_forwarder_query_messages)
|
if (!env->log_forwarder_query_messages)
|
||||||
return;
|
return;
|
||||||
dt_msg_init(env, &dm, DNSTAP__MESSAGE__TYPE__FORWARDER_QUERY);
|
dt_msg_init(env, &dm, DNSTAP__MESSAGE__TYPE__FORWARDER_QUERY);
|
||||||
@@ -585,7 +494,8 @@ dt_msg_send_outside_query(struct dt_env *env,
|
|||||||
dt_fill_buffer(qmsg, &dm.m.query_message, &dm.m.has_query_message);
|
dt_fill_buffer(qmsg, &dm.m.query_message, &dm.m.has_query_message);
|
||||||
|
|
||||||
/* socket_family, socket_protocol, response_address, response_port, query_address, query_port */
|
/* socket_family, socket_protocol, response_address, response_port, query_address, query_port */
|
||||||
dt_msg_fill_net(&dm, rsock, qsock, cptype, cpssl,
|
log_assert(cptype == comm_udp || cptype == comm_tcp);
|
||||||
|
dt_msg_fill_net(&dm, rsock, qsock, cptype,
|
||||||
&dm.m.response_address, &dm.m.has_response_address,
|
&dm.m.response_address, &dm.m.has_response_address,
|
||||||
&dm.m.response_port, &dm.m.has_response_port,
|
&dm.m.response_port, &dm.m.has_response_port,
|
||||||
&dm.m.query_address, &dm.m.has_query_address,
|
&dm.m.query_address, &dm.m.has_query_address,
|
||||||
@@ -600,7 +510,6 @@ dt_msg_send_outside_response(struct dt_env *env,
|
|||||||
struct sockaddr_storage *rsock,
|
struct sockaddr_storage *rsock,
|
||||||
struct sockaddr_storage *qsock,
|
struct sockaddr_storage *qsock,
|
||||||
enum comm_point_type cptype,
|
enum comm_point_type cptype,
|
||||||
void *cpssl,
|
|
||||||
uint8_t *zone, size_t zone_len,
|
uint8_t *zone, size_t zone_len,
|
||||||
uint8_t *qbuf, size_t qbuf_len,
|
uint8_t *qbuf, size_t qbuf_len,
|
||||||
const struct timeval *qtime,
|
const struct timeval *qtime,
|
||||||
@@ -610,15 +519,12 @@ dt_msg_send_outside_response(struct dt_env *env,
|
|||||||
struct dt_msg dm;
|
struct dt_msg dm;
|
||||||
uint16_t qflags;
|
uint16_t qflags;
|
||||||
|
|
||||||
if(dt_sample_rate_limited(env))
|
|
||||||
return;
|
|
||||||
|
|
||||||
(void)qbuf_len; log_assert(qbuf_len >= sizeof(qflags));
|
(void)qbuf_len; log_assert(qbuf_len >= sizeof(qflags));
|
||||||
memcpy(&qflags, qbuf, sizeof(qflags));
|
memcpy(&qflags, qbuf, sizeof(qflags));
|
||||||
qflags = ntohs(qflags);
|
qflags = ntohs(qflags);
|
||||||
|
|
||||||
/* type */
|
/* type */
|
||||||
if ((qflags & BIT_RD)) {
|
if (qflags & BIT_RD) {
|
||||||
if (!env->log_forwarder_response_messages)
|
if (!env->log_forwarder_response_messages)
|
||||||
return;
|
return;
|
||||||
dt_msg_init(env, &dm, DNSTAP__MESSAGE__TYPE__FORWARDER_RESPONSE);
|
dt_msg_init(env, &dm, DNSTAP__MESSAGE__TYPE__FORWARDER_RESPONSE);
|
||||||
@@ -647,7 +553,8 @@ dt_msg_send_outside_response(struct dt_env *env,
|
|||||||
dt_fill_buffer(rmsg, &dm.m.response_message, &dm.m.has_response_message);
|
dt_fill_buffer(rmsg, &dm.m.response_message, &dm.m.has_response_message);
|
||||||
|
|
||||||
/* socket_family, socket_protocol, response_address, response_port, query_address, query_port */
|
/* socket_family, socket_protocol, response_address, response_port, query_address, query_port */
|
||||||
dt_msg_fill_net(&dm, rsock, qsock, cptype, cpssl,
|
log_assert(cptype == comm_udp || cptype == comm_tcp);
|
||||||
|
dt_msg_fill_net(&dm, rsock, qsock, cptype,
|
||||||
&dm.m.response_address, &dm.m.has_response_address,
|
&dm.m.response_address, &dm.m.has_response_address,
|
||||||
&dm.m.response_port, &dm.m.has_response_port,
|
&dm.m.response_port, &dm.m.has_response_port,
|
||||||
&dm.m.query_address, &dm.m.has_query_address,
|
&dm.m.query_address, &dm.m.has_query_address,
|
||||||
|
|||||||
+3
-24
@@ -39,7 +39,6 @@
|
|||||||
|
|
||||||
#ifdef USE_DNSTAP
|
#ifdef USE_DNSTAP
|
||||||
|
|
||||||
#include "util/locks.h"
|
|
||||||
struct config_file;
|
struct config_file;
|
||||||
struct sldns_buffer;
|
struct sldns_buffer;
|
||||||
struct dt_msg_queue;
|
struct dt_msg_queue;
|
||||||
@@ -76,13 +75,6 @@ struct dt_env {
|
|||||||
unsigned log_forwarder_query_messages : 1;
|
unsigned log_forwarder_query_messages : 1;
|
||||||
/** whether to log Message/FORWARDER_RESPONSE */
|
/** whether to log Message/FORWARDER_RESPONSE */
|
||||||
unsigned log_forwarder_response_messages : 1;
|
unsigned log_forwarder_response_messages : 1;
|
||||||
|
|
||||||
/** lock on sample count */
|
|
||||||
lock_basic_type sample_lock;
|
|
||||||
/** rate limit value from config, samples 1/N messages */
|
|
||||||
unsigned int sample_rate;
|
|
||||||
/** rate limit counter */
|
|
||||||
unsigned int sample_rate_count;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -102,16 +94,9 @@ dt_create(struct config_file* cfg);
|
|||||||
* Apply config settings.
|
* Apply config settings.
|
||||||
* @param env: dnstap environment object.
|
* @param env: dnstap environment object.
|
||||||
* @param cfg: new config settings.
|
* @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.
|
|
||||||
* @param env: dnstap environment object.
|
|
||||||
* @param cfg: new config settings.
|
|
||||||
*/
|
|
||||||
void dt_apply_logcfg(struct dt_env *env, struct config_file *cfg);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize per-worker state in dnstap environment object.
|
* Initialize per-worker state in dnstap environment object.
|
||||||
@@ -141,16 +126,13 @@ dt_delete(struct dt_env *env);
|
|||||||
* @param rsock: local (service) address/port.
|
* @param rsock: local (service) address/port.
|
||||||
* @param cptype: comm_udp or comm_tcp.
|
* @param cptype: comm_udp or comm_tcp.
|
||||||
* @param qmsg: query message.
|
* @param qmsg: query message.
|
||||||
* @param tstamp: timestamp or NULL if none provided.
|
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
dt_msg_send_client_query(struct dt_env *env,
|
dt_msg_send_client_query(struct dt_env *env,
|
||||||
struct sockaddr_storage *qsock,
|
struct sockaddr_storage *qsock,
|
||||||
struct sockaddr_storage *rsock,
|
struct sockaddr_storage *rsock,
|
||||||
enum comm_point_type cptype,
|
enum comm_point_type cptype,
|
||||||
void *cpssl,
|
struct sldns_buffer *qmsg);
|
||||||
struct sldns_buffer *qmsg,
|
|
||||||
struct timeval* tstamp);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create and send a new dnstap "Message" event of type CLIENT_RESPONSE.
|
* Create and send a new dnstap "Message" event of type CLIENT_RESPONSE.
|
||||||
@@ -165,7 +147,6 @@ dt_msg_send_client_response(struct dt_env *env,
|
|||||||
struct sockaddr_storage *qsock,
|
struct sockaddr_storage *qsock,
|
||||||
struct sockaddr_storage *rsock,
|
struct sockaddr_storage *rsock,
|
||||||
enum comm_point_type cptype,
|
enum comm_point_type cptype,
|
||||||
void *cpssl,
|
|
||||||
struct sldns_buffer *rmsg);
|
struct sldns_buffer *rmsg);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -185,7 +166,6 @@ dt_msg_send_outside_query(struct dt_env *env,
|
|||||||
struct sockaddr_storage *rsock,
|
struct sockaddr_storage *rsock,
|
||||||
struct sockaddr_storage *qsock,
|
struct sockaddr_storage *qsock,
|
||||||
enum comm_point_type cptype,
|
enum comm_point_type cptype,
|
||||||
void *cpssl,
|
|
||||||
uint8_t *zone, size_t zone_len,
|
uint8_t *zone, size_t zone_len,
|
||||||
struct sldns_buffer *qmsg);
|
struct sldns_buffer *qmsg);
|
||||||
|
|
||||||
@@ -210,7 +190,6 @@ dt_msg_send_outside_response(struct dt_env *env,
|
|||||||
struct sockaddr_storage *rsock,
|
struct sockaddr_storage *rsock,
|
||||||
struct sockaddr_storage *qsock,
|
struct sockaddr_storage *qsock,
|
||||||
enum comm_point_type cptype,
|
enum comm_point_type cptype,
|
||||||
void *cpssl,
|
|
||||||
uint8_t *zone, size_t zone_len,
|
uint8_t *zone, size_t zone_len,
|
||||||
uint8_t *qbuf, size_t qbuf_len,
|
uint8_t *qbuf, size_t qbuf_len,
|
||||||
const struct timeval *qtime,
|
const struct timeval *qtime,
|
||||||
|
|||||||
+38
-97
@@ -5,104 +5,45 @@
|
|||||||
# Check for required dnstap libraries and add dnstap configure args.
|
# Check for required dnstap libraries and add dnstap configure args.
|
||||||
AC_DEFUN([dt_DNSTAP],
|
AC_DEFUN([dt_DNSTAP],
|
||||||
[
|
[
|
||||||
AC_ARG_ENABLE([dnstap],
|
AC_ARG_ENABLE([dnstap],
|
||||||
AS_HELP_STRING([--enable-dnstap],
|
AS_HELP_STRING([--enable-dnstap],
|
||||||
[Enable dnstap support (requires protobuf-c)]),
|
[Enable dnstap support (requires protobuf-c)]),
|
||||||
[opt_dnstap=$enableval],
|
[opt_dnstap=$enableval], [opt_dnstap=no])
|
||||||
[opt_dnstap=no])
|
|
||||||
|
|
||||||
AC_ARG_WITH([dnstap-socket-path],
|
AC_ARG_WITH([dnstap-socket-path],
|
||||||
AS_HELP_STRING([--with-dnstap-socket-path=pathname],
|
AS_HELP_STRING([--with-dnstap-socket-path=pathname],
|
||||||
[set default dnstap socket path]),
|
[set default dnstap socket path]),
|
||||||
[opt_dnstap_socket_path=$withval],
|
[opt_dnstap_socket_path=$withval], [opt_dnstap_socket_path="$1"])
|
||||||
[opt_dnstap_socket_path="$1"])
|
|
||||||
|
|
||||||
if test "x$opt_dnstap" != "xno"; then
|
if test "x$opt_dnstap" != "xno"; then
|
||||||
AC_PATH_PROG([PROTOC], [protoc])
|
AC_PATH_PROG([PROTOC_C], [protoc-c])
|
||||||
# 'protoc-c' is deprecated. We use 'protoc' instead. If it can not be
|
if test -z "$PROTOC_C"; then
|
||||||
# found, try 'protoc-c'.
|
AC_MSG_ERROR([The protoc-c program was not found. Please install protobuf-c!])
|
||||||
if test -z "$PROTOC"; then
|
|
||||||
AC_PATH_PROG([PROTOC_C], [protoc-c])
|
|
||||||
else
|
|
||||||
PROTOC_C="$PROTOC"
|
|
||||||
fi
|
|
||||||
if test -z "$PROTOC_C"; then
|
|
||||||
AC_MSG_ERROR([[The protoc or protoc-c program was not found. It is needed for dnstap, use --disable-dnstap, or install protobuf-c to provide protoc or protoc-c]])
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Check for protoc-gen-c plugin
|
|
||||||
AC_PATH_PROG([PROTOC_GEN_C], [protoc-gen-c])
|
|
||||||
if test -z "$PROTOC_GEN_C"; then
|
|
||||||
AC_MSG_ERROR([[The protoc-gen-c plugin was not found. It is needed for dnstap, use --disable-dnstap, or install protobuf-c-compiler to provide protoc-gen-c]])
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Test that protoc-gen-c actually works
|
|
||||||
AC_MSG_CHECKING([if protoc-gen-c plugin works])
|
|
||||||
cat > conftest.proto << EOF
|
|
||||||
syntax = "proto2";
|
|
||||||
message TestMessage {
|
|
||||||
optional string test_field = 1;
|
|
||||||
}
|
|
||||||
EOF
|
|
||||||
if $PROTOC_C --c_out=. conftest.proto >/dev/null 2>&1; then
|
|
||||||
AC_MSG_RESULT([yes])
|
|
||||||
rm -f conftest.proto conftest.pb-c.c conftest.pb-c.h
|
|
||||||
else
|
|
||||||
AC_MSG_RESULT([no])
|
|
||||||
rm -f conftest.proto conftest.pb-c.c conftest.pb-c.h
|
|
||||||
AC_MSG_ERROR([[The protoc-gen-c plugin is not working properly. Please ensure protobuf-c-compiler is properly installed]])
|
|
||||||
fi
|
|
||||||
|
|
||||||
AC_ARG_WITH([protobuf-c],
|
|
||||||
AS_HELP_STRING([--with-protobuf-c=path], [Path where protobuf-c is installed, for dnstap]),
|
|
||||||
[
|
|
||||||
# workaround for protobuf-c includes at old dir before protobuf-c-1.0.0
|
|
||||||
if test -f $withval/include/google/protobuf-c/protobuf-c.h; then
|
|
||||||
CFLAGS="$CFLAGS -I$withval/include/google"
|
|
||||||
else
|
|
||||||
CFLAGS="$CFLAGS -I$withval/include"
|
|
||||||
fi
|
|
||||||
LDFLAGS="$LDFLAGS -L$withval/lib"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
if test -n "$PKG_CONFIG"; then
|
|
||||||
PKG_CHECK_MODULES([PROTOBUFC], [libprotobuf-c],
|
|
||||||
[
|
|
||||||
CFLAGS="$CFLAGS $PROTOBUFC_CFLAGS"
|
|
||||||
LIBS="$LIBS $PROTOBUFC_LIBS"
|
|
||||||
],
|
|
||||||
[
|
|
||||||
# pkg-config failed; try falling back to known values
|
|
||||||
# workaround for protobuf-c includes at old dir before protobuf-c-1.0.0
|
|
||||||
if test -f /usr/include/google/protobuf-c/protobuf-c.h; then
|
|
||||||
CFLAGS="$CFLAGS -I/usr/include/google"
|
|
||||||
else
|
|
||||||
if test -f /usr/local/include/google/protobuf-c/protobuf-c.h; then
|
|
||||||
CFLAGS="$CFLAGS -I/usr/local/include/google"
|
|
||||||
LDFLAGS="$LDFLAGS -L/usr/local/lib"
|
|
||||||
else
|
|
||||||
AC_MSG_ERROR([The protobuf-c package was not found with pkg-config. Please install protobuf-c!])
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
]
|
|
||||||
)
|
|
||||||
else
|
|
||||||
# workaround for protobuf-c includes at old dir before protobuf-c-1.0.0
|
|
||||||
if test -f /usr/include/google/protobuf-c/protobuf-c.h; then
|
|
||||||
CFLAGS="$CFLAGS -I/usr/include/google"
|
|
||||||
else
|
|
||||||
if test -f /usr/local/include/google/protobuf-c/protobuf-c.h; then
|
|
||||||
CFLAGS="$CFLAGS -I/usr/local/include/google"
|
|
||||||
LDFLAGS="$LDFLAGS -L/usr/local/lib"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
]
|
|
||||||
)
|
|
||||||
AC_SEARCH_LIBS([protobuf_c_message_pack], [protobuf-c], [],
|
|
||||||
AC_MSG_ERROR([The protobuf-c library was not found. Please install the development libraries for protobuf-c!]))
|
|
||||||
$2
|
|
||||||
else
|
|
||||||
$3
|
|
||||||
fi
|
fi
|
||||||
|
AC_ARG_WITH([protobuf-c], AS_HELP_STRING([--with-protobuf-c=path],
|
||||||
|
[Path where protobuf-c is installed, for dnstap]), [
|
||||||
|
# workaround for protobuf-c includes at old dir before protobuf-c-1.0.0
|
||||||
|
if test -f $withval/include/google/protobuf-c/protobuf-c.h; then
|
||||||
|
CFLAGS="$CFLAGS -I$withval/include/google"
|
||||||
|
else
|
||||||
|
CFLAGS="$CFLAGS -I$withval/include"
|
||||||
|
fi
|
||||||
|
LDFLAGS="$LDFLAGS -L$withval/lib"
|
||||||
|
], [
|
||||||
|
# workaround for protobuf-c includes at old dir before protobuf-c-1.0.0
|
||||||
|
if test -f /usr/include/google/protobuf-c/protobuf-c.h; then
|
||||||
|
CFLAGS="$CFLAGS -I/usr/include/google"
|
||||||
|
else
|
||||||
|
if test -f /usr/local/include/google/protobuf-c/protobuf-c.h; then
|
||||||
|
CFLAGS="$CFLAGS -I/usr/local/include/google"
|
||||||
|
LDFLAGS="$LDFLAGS -L/usr/local/lib"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
])
|
||||||
|
AC_SEARCH_LIBS([protobuf_c_message_pack], [protobuf-c], [],
|
||||||
|
AC_MSG_ERROR([The protobuf-c library was not found. Please install protobuf-c!]))
|
||||||
|
$2
|
||||||
|
else
|
||||||
|
$3
|
||||||
|
fi
|
||||||
])
|
])
|
||||||
|
|||||||
+7
-75
@@ -13,8 +13,8 @@
|
|||||||
// with this file. If not, see:
|
// with this file. If not, see:
|
||||||
//
|
//
|
||||||
// <http://creativecommons.org/publicdomain/zero/1.0/>.
|
// <http://creativecommons.org/publicdomain/zero/1.0/>.
|
||||||
|
|
||||||
syntax = "proto2";
|
syntax = "proto2";
|
||||||
|
|
||||||
package dnstap;
|
package dnstap;
|
||||||
|
|
||||||
// "Dnstap": this is the top-level dnstap type, which is a "union" type that
|
// "Dnstap": this is the top-level dnstap type, which is a "union" type that
|
||||||
@@ -56,60 +56,11 @@ enum SocketFamily {
|
|||||||
INET6 = 2; // IPv6 (RFC 2460)
|
INET6 = 2; // IPv6 (RFC 2460)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SocketProtocol: the protocol used to transport a DNS message.
|
// SocketProtocol: the transport protocol of a socket. This specifies how to
|
||||||
|
// interpret "transport port" fields.
|
||||||
enum SocketProtocol {
|
enum SocketProtocol {
|
||||||
UDP = 1; // DNS over UDP transport (RFC 1035 section 4.2.1)
|
UDP = 1; // User Datagram Protocol (RFC 768)
|
||||||
TCP = 2; // DNS over TCP transport (RFC 1035 section 4.2.2)
|
TCP = 2; // Transmission Control Protocol (RFC 793)
|
||||||
DOT = 3; // DNS over TLS (RFC 7858)
|
|
||||||
DOH = 4; // DNS over HTTPS (RFC 8484)
|
|
||||||
DNSCryptUDP = 5; // DNSCrypt over UDP (https://dnscrypt.info/protocol)
|
|
||||||
DNSCryptTCP = 6; // DNSCrypt over TCP (https://dnscrypt.info/protocol)
|
|
||||||
DOQ = 7; // DNS over QUIC (RFC 9250)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Policy: information about any name server operator policy
|
|
||||||
// applied to the processing of a DNS message.
|
|
||||||
message Policy {
|
|
||||||
|
|
||||||
// Match: what aspect of the message or message exchange
|
|
||||||
// triggered the application of the Policy.
|
|
||||||
enum Match {
|
|
||||||
QNAME = 1; // Name in question section of query
|
|
||||||
CLIENT_IP = 2; // Client IP address
|
|
||||||
RESPONSE_IP = 3; // Address in A/AAAA RRSet
|
|
||||||
NS_NAME = 4; // Authoritative name server, by name
|
|
||||||
NS_IP = 5; // Authoritative name server, by IP address
|
|
||||||
}
|
|
||||||
|
|
||||||
// The Action taken to implement the Policy.
|
|
||||||
enum Action {
|
|
||||||
NXDOMAIN = 1; // Respond with NXDOMAIN
|
|
||||||
NODATA = 2; // Respond with empty answer section
|
|
||||||
PASS = 3; // Do not alter the response (passthrough)
|
|
||||||
DROP = 4; // Do not respond.
|
|
||||||
TRUNCATE = 5; // Truncate UDP response, forcing TCP retry
|
|
||||||
LOCAL_DATA = 6; // Respond with local data from policy
|
|
||||||
}
|
|
||||||
|
|
||||||
// type: the type of policy applied, e.g. "RPZ" for a
|
|
||||||
// policy from a Response Policy Zone.
|
|
||||||
optional string type = 1;
|
|
||||||
|
|
||||||
// rule: the rule matched by the message.
|
|
||||||
//
|
|
||||||
// In a RPZ context, this is the owner name of the rule in
|
|
||||||
// the Response Policy Zone in wire format.
|
|
||||||
optional bytes rule = 2;
|
|
||||||
|
|
||||||
// action: the policy action taken in response to the
|
|
||||||
// rule match.
|
|
||||||
optional Action action = 3;
|
|
||||||
|
|
||||||
// match: the feature of the message exchange which matched the rule.
|
|
||||||
optional Match match = 4;
|
|
||||||
|
|
||||||
// The matched value. Format depends on the matched feature .
|
|
||||||
optional bytes value = 5;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Message: a wire-format (RFC 1035 section 4) DNS message and associated
|
// Message: a wire-format (RFC 1035 section 4) DNS message and associated
|
||||||
@@ -207,24 +158,6 @@ message Message {
|
|||||||
// STUB_RESPONSE is a DNS response message sent from a DNS server to a
|
// STUB_RESPONSE is a DNS response message sent from a DNS server to a
|
||||||
// stub resolver, from the perspective of the stub resolver.
|
// stub resolver, from the perspective of the stub resolver.
|
||||||
STUB_RESPONSE = 10;
|
STUB_RESPONSE = 10;
|
||||||
|
|
||||||
// TOOL_QUERY is a DNS query message sent from a DNS software tool to a
|
|
||||||
// DNS server, from the perspective of the tool.
|
|
||||||
TOOL_QUERY = 11;
|
|
||||||
|
|
||||||
// TOOL_RESPONSE is a DNS response message received by a DNS software
|
|
||||||
// tool from a DNS server, from the perspective of the tool.
|
|
||||||
TOOL_RESPONSE = 12;
|
|
||||||
|
|
||||||
// UPDATE_QUERY is a Dynamic DNS Update request (RFC 2136) received
|
|
||||||
// by an authoritative name server, from the perspective of the
|
|
||||||
// authoritative name server.
|
|
||||||
UPDATE_QUERY = 13;
|
|
||||||
|
|
||||||
// UPDATE_RESPONSE is a Dynamic DNS Update response (RFC 2136) sent
|
|
||||||
// from an authoritative name server, from the perspective of the
|
|
||||||
// authoritative name server.
|
|
||||||
UPDATE_RESPONSE = 14;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// One of the Type values described above.
|
// One of the Type values described above.
|
||||||
@@ -282,9 +215,6 @@ message Message {
|
|||||||
|
|
||||||
// The responder's original wire-format DNS response message, verbatim.
|
// The responder's original wire-format DNS response message, verbatim.
|
||||||
optional bytes response_message = 14;
|
optional bytes response_message = 14;
|
||||||
|
|
||||||
// Operator policy applied to the processing of this message, if any.
|
|
||||||
optional Policy policy = 15;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// All fields except for 'type' in the Message schema are optional.
|
// All fields except for 'type' in the Message schema are optional.
|
||||||
@@ -306,6 +236,7 @@ message Message {
|
|||||||
|
|
||||||
// RESOLVER_QUERY:
|
// RESOLVER_QUERY:
|
||||||
// socket_family, socket_protocol
|
// socket_family, socket_protocol
|
||||||
|
// query_name, query_type, query_class
|
||||||
// query_message
|
// query_message
|
||||||
// query_time_sec, query_time_nsec
|
// query_time_sec, query_time_nsec
|
||||||
// query_zone
|
// query_zone
|
||||||
@@ -313,6 +244,7 @@ message Message {
|
|||||||
|
|
||||||
// RESOLVER_RESPONSE:
|
// RESOLVER_RESPONSE:
|
||||||
// socket_family, socket_protocol
|
// socket_family, socket_protocol
|
||||||
|
// query_name, query_type, query_class
|
||||||
// query_time_sec, query_time_nsec
|
// query_time_sec, query_time_nsec
|
||||||
// query_zone
|
// query_zone
|
||||||
// response_address, response_port
|
// response_address, response_port
|
||||||
|
|||||||
+14
-65
@@ -176,7 +176,10 @@ void
|
|||||||
mq_wakeup_cb(void* arg)
|
mq_wakeup_cb(void* arg)
|
||||||
{
|
{
|
||||||
struct dt_msg_queue* mq = (struct dt_msg_queue*)arg;
|
struct dt_msg_queue* mq = (struct dt_msg_queue*)arg;
|
||||||
|
/* even if the dtio is already active, because perhaps much
|
||||||
|
* traffic suddenly, we leave the timer running to save on
|
||||||
|
* managing it, the once a second timer is less work then
|
||||||
|
* starting and stopping the timer frequently */
|
||||||
lock_basic_lock(&mq->dtio->wakeup_timer_lock);
|
lock_basic_lock(&mq->dtio->wakeup_timer_lock);
|
||||||
mq->dtio->wakeup_timer_enabled = 0;
|
mq->dtio->wakeup_timer_enabled = 0;
|
||||||
lock_basic_unlock(&mq->dtio->wakeup_timer_lock);
|
lock_basic_unlock(&mq->dtio->wakeup_timer_lock);
|
||||||
@@ -207,8 +210,6 @@ dt_msg_queue_start_timer(struct dt_msg_queue* mq, int wakeupnow)
|
|||||||
lock_basic_lock(&mq->dtio->wakeup_timer_lock);
|
lock_basic_lock(&mq->dtio->wakeup_timer_lock);
|
||||||
if(mq->dtio->wakeup_timer_enabled) {
|
if(mq->dtio->wakeup_timer_enabled) {
|
||||||
if(wakeupnow) {
|
if(wakeupnow) {
|
||||||
tv.tv_sec = 0;
|
|
||||||
tv.tv_usec = 0;
|
|
||||||
comm_timer_set(mq->wakeup_timer, &tv);
|
comm_timer_set(mq->wakeup_timer, &tv);
|
||||||
}
|
}
|
||||||
lock_basic_unlock(&mq->dtio->wakeup_timer_lock);
|
lock_basic_unlock(&mq->dtio->wakeup_timer_lock);
|
||||||
@@ -220,14 +221,8 @@ dt_msg_queue_start_timer(struct dt_msg_queue* mq, int wakeupnow)
|
|||||||
if(!wakeupnow) {
|
if(!wakeupnow) {
|
||||||
tv.tv_sec = 1;
|
tv.tv_sec = 1;
|
||||||
tv.tv_usec = 0;
|
tv.tv_usec = 0;
|
||||||
/* If it is already set, keep it running. */
|
|
||||||
if(!comm_timer_is_set(mq->wakeup_timer))
|
|
||||||
comm_timer_set(mq->wakeup_timer, &tv);
|
|
||||||
} else {
|
|
||||||
tv.tv_sec = 0;
|
|
||||||
tv.tv_usec = 0;
|
|
||||||
comm_timer_set(mq->wakeup_timer, &tv);
|
|
||||||
}
|
}
|
||||||
|
comm_timer_set(mq->wakeup_timer, &tv);
|
||||||
lock_basic_unlock(&mq->dtio->wakeup_timer_lock);
|
lock_basic_unlock(&mq->dtio->wakeup_timer_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -265,9 +260,8 @@ dt_msg_queue_submit(struct dt_msg_queue* mq, void* buf, size_t len)
|
|||||||
|
|
||||||
/* acquire lock */
|
/* acquire lock */
|
||||||
lock_basic_lock(&mq->lock);
|
lock_basic_lock(&mq->lock);
|
||||||
/* if list was empty, start timer for (eventual) wakeup,
|
/* if list was empty, start timer for (eventual) wakeup */
|
||||||
* or if dtio is not writing now an eventual wakeup is needed. */
|
if(mq->first == NULL)
|
||||||
if(mq->first == NULL || !mq->dtio->event_added_is_write)
|
|
||||||
wakeupstarttimer = 1;
|
wakeupstarttimer = 1;
|
||||||
/* if list contains more than wakeupnum elements, wakeup now,
|
/* if list contains more than wakeupnum elements, wakeup now,
|
||||||
* or if list is (going to be) almost full */
|
* or if list is (going to be) almost full */
|
||||||
@@ -448,9 +442,6 @@ int dt_io_thread_apply_cfg(struct dt_io_thread* dtio, struct config_file *cfg)
|
|||||||
dtio->tls_use_sni = cfg->tls_use_sni;
|
dtio->tls_use_sni = cfg->tls_use_sni;
|
||||||
#endif /* HAVE_SSL */
|
#endif /* HAVE_SSL */
|
||||||
}
|
}
|
||||||
#ifdef HAVE_GETTID
|
|
||||||
dtio->thread_tid_log = cfg->log_thread_id;
|
|
||||||
#endif
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -797,7 +788,7 @@ static int dtio_write_ssl(struct dt_io_thread* dtio, uint8_t* buf,
|
|||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
log_crypto_err_io("dnstap io, could not SSL_write", want);
|
log_crypto_err("dnstap io, could not SSL_write");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
return r;
|
return r;
|
||||||
@@ -1038,7 +1029,7 @@ static int ssl_read_bytes(struct dt_io_thread* dtio, void* buf, size_t len)
|
|||||||
"other side");
|
"other side");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
log_crypto_err_io("could not SSL_read", want);
|
log_crypto_err("could not SSL_read");
|
||||||
verbose(VERB_DETAIL, "dnstap io: output closed by the "
|
verbose(VERB_DETAIL, "dnstap io: output closed by the "
|
||||||
"other side");
|
"other side");
|
||||||
return 0;
|
return 0;
|
||||||
@@ -1268,13 +1259,6 @@ static void dtio_sleep(struct dt_io_thread* dtio)
|
|||||||
/* unregister the event polling for write, because there is
|
/* unregister the event polling for write, because there is
|
||||||
* nothing to be written */
|
* nothing to be written */
|
||||||
(void)dtio_add_output_event_read(dtio);
|
(void)dtio_add_output_event_read(dtio);
|
||||||
|
|
||||||
/* Set wakeuptimer enabled off; so that the next worker thread that
|
|
||||||
* wants to log starts a timer if needed, since the writer thread
|
|
||||||
* has gone to sleep. */
|
|
||||||
lock_basic_lock(&dtio->wakeup_timer_lock);
|
|
||||||
dtio->wakeup_timer_enabled = 0;
|
|
||||||
lock_basic_unlock(&dtio->wakeup_timer_lock);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_SSL
|
#ifdef HAVE_SSL
|
||||||
@@ -1338,11 +1322,7 @@ static int dtio_ssl_check_peer(struct dt_io_thread* dtio)
|
|||||||
if((SSL_get_verify_mode(dtio->ssl)&SSL_VERIFY_PEER)) {
|
if((SSL_get_verify_mode(dtio->ssl)&SSL_VERIFY_PEER)) {
|
||||||
/* verification */
|
/* verification */
|
||||||
if(SSL_get_verify_result(dtio->ssl) == X509_V_OK) {
|
if(SSL_get_verify_result(dtio->ssl) == X509_V_OK) {
|
||||||
#ifdef HAVE_SSL_GET1_PEER_CERTIFICATE
|
|
||||||
X509* x = SSL_get1_peer_certificate(dtio->ssl);
|
|
||||||
#else
|
|
||||||
X509* x = SSL_get_peer_certificate(dtio->ssl);
|
X509* x = SSL_get_peer_certificate(dtio->ssl);
|
||||||
#endif
|
|
||||||
if(!x) {
|
if(!x) {
|
||||||
verbose(VERB_ALGO, "dnstap io, %s, SSL "
|
verbose(VERB_ALGO, "dnstap io, %s, SSL "
|
||||||
"connection failed no certificate",
|
"connection failed no certificate",
|
||||||
@@ -1367,11 +1347,7 @@ static int dtio_ssl_check_peer(struct dt_io_thread* dtio)
|
|||||||
#endif
|
#endif
|
||||||
X509_free(x);
|
X509_free(x);
|
||||||
} else {
|
} else {
|
||||||
#ifdef HAVE_SSL_GET1_PEER_CERTIFICATE
|
|
||||||
X509* x = SSL_get1_peer_certificate(dtio->ssl);
|
|
||||||
#else
|
|
||||||
X509* x = SSL_get_peer_certificate(dtio->ssl);
|
X509* x = SSL_get_peer_certificate(dtio->ssl);
|
||||||
#endif
|
|
||||||
if(x) {
|
if(x) {
|
||||||
log_cert(VERB_ALGO, "dnstap io, peer "
|
log_cert(VERB_ALGO, "dnstap io, peer "
|
||||||
"certificate", x);
|
"certificate", x);
|
||||||
@@ -1455,8 +1431,8 @@ static int dtio_ssl_handshake(struct dt_io_thread* dtio,
|
|||||||
} else {
|
} else {
|
||||||
unsigned long err = ERR_get_error();
|
unsigned long err = ERR_get_error();
|
||||||
if(!squelch_err_ssl_handshake(err)) {
|
if(!squelch_err_ssl_handshake(err)) {
|
||||||
log_crypto_err_io_code("dnstap io, ssl handshake failed",
|
log_crypto_err_code("dnstap io, ssl handshake failed",
|
||||||
want, err);
|
err);
|
||||||
verbose(VERB_OPS, "dnstap io, ssl handshake failed "
|
verbose(VERB_OPS, "dnstap io, ssl handshake failed "
|
||||||
"from %s", dtio->ip_str);
|
"from %s", dtio->ip_str);
|
||||||
}
|
}
|
||||||
@@ -1512,11 +1488,9 @@ void dtio_output_cb(int ATTR_UNUSED(fd), short bits, void* arg)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if((bits&UB_EV_READ) || dtio->ssl_brief_write) {
|
if((bits&UB_EV_READ || dtio->ssl_brief_write)) {
|
||||||
#ifdef HAVE_SSL
|
|
||||||
if(dtio->ssl_brief_write)
|
if(dtio->ssl_brief_write)
|
||||||
(void)dtio_disable_brief_write(dtio);
|
(void)dtio_disable_brief_write(dtio);
|
||||||
#endif
|
|
||||||
if(dtio->ready_frame_sent && !dtio->accept_frame_received) {
|
if(dtio->ready_frame_sent && !dtio->accept_frame_received) {
|
||||||
if(dtio_read_accept_frame(dtio) <= 0)
|
if(dtio_read_accept_frame(dtio) <= 0)
|
||||||
return;
|
return;
|
||||||
@@ -1539,22 +1513,8 @@ void dtio_output_cb(int ATTR_UNUSED(fd), short bits, void* arg)
|
|||||||
/* no messages on the first iteration,
|
/* no messages on the first iteration,
|
||||||
* the queues are all empty */
|
* the queues are all empty */
|
||||||
dtio_sleep(dtio);
|
dtio_sleep(dtio);
|
||||||
/* After putting to sleep, see if
|
|
||||||
* a message is in a message queue,
|
|
||||||
* if so, resume service. Stops a
|
|
||||||
* race condition where a thread could
|
|
||||||
* have one message but the dtio
|
|
||||||
* also just went to sleep. With the
|
|
||||||
* message queued between the
|
|
||||||
* dtio_find_msg and dtio_sleep
|
|
||||||
* calls. */
|
|
||||||
if(dtio_find_msg(dtio)) {
|
|
||||||
if(!dtio_add_output_event_write(dtio))
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if(!dtio->cur_msg)
|
return; /* nothing to do */
|
||||||
return; /* nothing to do */
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2133,18 +2093,7 @@ static void* dnstap_io(void* arg)
|
|||||||
struct dt_io_thread* dtio = (struct dt_io_thread*)arg;
|
struct dt_io_thread* dtio = (struct dt_io_thread*)arg;
|
||||||
time_t secs = 0;
|
time_t secs = 0;
|
||||||
struct timeval now;
|
struct timeval now;
|
||||||
const char name[16] = "unbound/dnstap"; /* seems to be the safest size
|
log_thread_set(&dtio->threadnum);
|
||||||
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);
|
|
||||||
|
|
||||||
/* setup */
|
/* setup */
|
||||||
verbose(VERB_ALGO, "start dnstap io thread");
|
verbose(VERB_ALGO, "start dnstap io thread");
|
||||||
|
|||||||
@@ -131,12 +131,6 @@ struct dt_io_thread {
|
|||||||
struct dt_io_list_item* io_list_iter;
|
struct dt_io_list_item* io_list_iter;
|
||||||
/** thread id, of the io thread */
|
/** thread id, of the io thread */
|
||||||
ub_thread_type tid;
|
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 */
|
/** if the io processing has started */
|
||||||
int started;
|
int started;
|
||||||
/** ssl context for the io thread, for tls connections. type SSL_CTX* */
|
/** ssl context for the io thread, for tls connections. type SSL_CTX* */
|
||||||
|
|||||||
+66
-344
@@ -61,7 +61,6 @@
|
|||||||
#include "services/listen_dnsport.h"
|
#include "services/listen_dnsport.h"
|
||||||
#include "sldns/sbuffer.h"
|
#include "sldns/sbuffer.h"
|
||||||
#include "sldns/wire2str.h"
|
#include "sldns/wire2str.h"
|
||||||
#include "sldns/pkthdr.h"
|
|
||||||
#ifdef USE_DNSTAP
|
#ifdef USE_DNSTAP
|
||||||
#include <protobuf-c/protobuf-c.h>
|
#include <protobuf-c/protobuf-c.h>
|
||||||
#include "dnstap/dnstap.pb-c.h"
|
#include "dnstap/dnstap.pb-c.h"
|
||||||
@@ -75,18 +74,17 @@
|
|||||||
static void usage(char* argv[])
|
static void usage(char* argv[])
|
||||||
{
|
{
|
||||||
printf("usage: %s [options]\n", argv[0]);
|
printf("usage: %s [options]\n", argv[0]);
|
||||||
printf(" Listen to dnstap messages\n");
|
printf(" Listen to dnstap messages\n");
|
||||||
printf("stdout has dnstap log, stderr has verbose server log\n");
|
printf("stdout has dnstap log, stderr has verbose server log\n");
|
||||||
printf("-u <socketpath> listen to unix socket with this file name\n");
|
printf("-u <socketpath> listen to unix socket with this file name\n");
|
||||||
printf("-s <serverip[@port]> listen for TCP on the IP and port\n");
|
printf("-s <serverip[@port]> listen for TCP on the IP and port\n");
|
||||||
printf("-t <serverip[@port]> listen for TLS on IP and port\n");
|
printf("-t <serverip[@port]> listen for TLS on IP and port\n");
|
||||||
printf("-x <server.key> server key file for TLS service\n");
|
printf("-x <server.key> server key file for TLS service\n");
|
||||||
printf("-y <server.pem> server cert file for TLS service\n");
|
printf("-y <server.pem> server cert file for TLS service\n");
|
||||||
printf("-z <verify.pem> cert file to verify client connections\n");
|
printf("-z <verify.pem> cert file to verify client connections\n");
|
||||||
printf("-l long format for DNS printout\n");
|
printf("-l long format for DNS printout\n");
|
||||||
printf("-v more verbose log output\n");
|
printf("-v more verbose log output\n");
|
||||||
printf("-c internal unit test and exit\n");
|
printf("-h this help text\n");
|
||||||
printf("-h this help text\n");
|
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -103,14 +101,6 @@ struct main_tap_data {
|
|||||||
struct tap_socket_list* acceptlist;
|
struct tap_socket_list* acceptlist;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* list of data */
|
|
||||||
struct tap_data_list {
|
|
||||||
/** next in list */
|
|
||||||
struct tap_data_list* next;
|
|
||||||
/** the data */
|
|
||||||
struct tap_data* d;
|
|
||||||
};
|
|
||||||
|
|
||||||
/** tap callback variables */
|
/** tap callback variables */
|
||||||
struct tap_data {
|
struct tap_data {
|
||||||
/** the fd */
|
/** the fd */
|
||||||
@@ -137,10 +127,6 @@ struct tap_data {
|
|||||||
uint8_t* frame;
|
uint8_t* frame;
|
||||||
/** length of this frame */
|
/** length of this frame */
|
||||||
size_t len;
|
size_t len;
|
||||||
/** back pointer to the tap_data_list entry;
|
|
||||||
* used to NULL the forward pointer to this data
|
|
||||||
* when this data is freed. */
|
|
||||||
struct tap_data_list* data_list;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/** list of sockets */
|
/** list of sockets */
|
||||||
@@ -169,89 +155,8 @@ struct tap_socket {
|
|||||||
char* ip;
|
char* ip;
|
||||||
/** for a TLS socket, the tls context */
|
/** for a TLS socket, the tls context */
|
||||||
SSL_CTX* sslctx;
|
SSL_CTX* sslctx;
|
||||||
/** dumb way to deal with memory leaks:
|
|
||||||
* tap_data was only freed on errors and not during exit leading to
|
|
||||||
* false positives when testing for memory leaks. */
|
|
||||||
struct tap_data_list* data_list;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/** try to delete tail entries from the list if all of them have no data */
|
|
||||||
static void tap_data_list_try_to_free_tail(struct tap_data_list* list)
|
|
||||||
{
|
|
||||||
struct tap_data_list* current = list;
|
|
||||||
log_assert(!list->d);
|
|
||||||
if(!list->next) /* we are the last, we can't remove ourselves */
|
|
||||||
return;
|
|
||||||
list = list->next;
|
|
||||||
while(list) {
|
|
||||||
if(list->d) /* a tail entry still has data; return */
|
|
||||||
return;
|
|
||||||
list = list->next;
|
|
||||||
}
|
|
||||||
/* keep the next */
|
|
||||||
list = current->next;
|
|
||||||
/* the tail will be removed; but not ourselves */
|
|
||||||
current->next = NULL;
|
|
||||||
while(list) {
|
|
||||||
current = list;
|
|
||||||
list = list->next;
|
|
||||||
free(current);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** delete the tap structure */
|
|
||||||
static void tap_data_free(struct tap_data* data, int free_tail)
|
|
||||||
{
|
|
||||||
if(!data)
|
|
||||||
return;
|
|
||||||
if(data->ev) {
|
|
||||||
ub_event_del(data->ev);
|
|
||||||
ub_event_free(data->ev);
|
|
||||||
}
|
|
||||||
#ifdef HAVE_SSL
|
|
||||||
SSL_free(data->ssl);
|
|
||||||
#endif
|
|
||||||
sock_close(data->fd);
|
|
||||||
free(data->id);
|
|
||||||
free(data->frame);
|
|
||||||
if(data->data_list) {
|
|
||||||
data->data_list->d = NULL;
|
|
||||||
if(free_tail)
|
|
||||||
tap_data_list_try_to_free_tail(data->data_list);
|
|
||||||
}
|
|
||||||
free(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** insert tap_data in the tap_data_list */
|
|
||||||
static int tap_data_list_insert(struct tap_data_list** liststart,
|
|
||||||
struct tap_data* d)
|
|
||||||
{
|
|
||||||
struct tap_data_list* entry = (struct tap_data_list*)
|
|
||||||
malloc(sizeof(*entry));
|
|
||||||
if(!entry)
|
|
||||||
return 0;
|
|
||||||
entry->next = *liststart;
|
|
||||||
entry->d = d;
|
|
||||||
d->data_list = entry;
|
|
||||||
*liststart = entry;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** delete the tap_data_list and free any remaining tap_data */
|
|
||||||
static void tap_data_list_delete(struct tap_data_list* list)
|
|
||||||
{
|
|
||||||
struct tap_data_list* e = list, *next;
|
|
||||||
while(e) {
|
|
||||||
next = e->next;
|
|
||||||
if(e->d) {
|
|
||||||
tap_data_free(e->d, 0);
|
|
||||||
e->d = NULL;
|
|
||||||
}
|
|
||||||
free(e);
|
|
||||||
e = next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** del the tap event */
|
/** del the tap event */
|
||||||
static void tap_socket_delev(struct tap_socket* s)
|
static void tap_socket_delev(struct tap_socket* s)
|
||||||
{
|
{
|
||||||
@@ -267,7 +172,7 @@ static void tap_socket_close(struct tap_socket* s)
|
|||||||
{
|
{
|
||||||
if(!s) return;
|
if(!s) return;
|
||||||
if(s->fd == -1) return;
|
if(s->fd == -1) return;
|
||||||
sock_close(s->fd);
|
close(s->fd);
|
||||||
s->fd = -1;
|
s->fd = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -278,7 +183,6 @@ static void tap_socket_delete(struct tap_socket* s)
|
|||||||
#ifdef HAVE_SSL
|
#ifdef HAVE_SSL
|
||||||
SSL_CTX_free(s->sslctx);
|
SSL_CTX_free(s->sslctx);
|
||||||
#endif
|
#endif
|
||||||
tap_data_list_delete(s->data_list);
|
|
||||||
ub_event_free(s->ev);
|
ub_event_free(s->ev);
|
||||||
free(s->socketpath);
|
free(s->socketpath);
|
||||||
free(s->ip);
|
free(s->ip);
|
||||||
@@ -330,7 +234,7 @@ static struct tap_socket* tap_socket_new_tcpaccept(char* ip,
|
|||||||
/** create new socket (unconnected, not base-added), or NULL malloc fail */
|
/** create new socket (unconnected, not base-added), or NULL malloc fail */
|
||||||
static struct tap_socket* tap_socket_new_tlsaccept(char* ip,
|
static struct tap_socket* tap_socket_new_tlsaccept(char* ip,
|
||||||
void (*ev_cb)(int, short, void*), void* data, char* server_key,
|
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));
|
struct tap_socket* s = calloc(1, sizeof(*s));
|
||||||
if(!s) {
|
if(!s) {
|
||||||
@@ -346,8 +250,7 @@ static struct tap_socket* tap_socket_new_tlsaccept(char* ip,
|
|||||||
s->fd = -1;
|
s->fd = -1;
|
||||||
s->ev_cb = ev_cb;
|
s->ev_cb = ev_cb;
|
||||||
s->data = data;
|
s->data = data;
|
||||||
s->sslctx = listen_sslctx_create(server_key, server_cert, verifypem,
|
s->sslctx = listen_sslctx_create(server_key, server_cert, verifypem);
|
||||||
NULL, NULL, 0, 0, 0, tls_protocols);
|
|
||||||
if(!s->sslctx) {
|
if(!s->sslctx) {
|
||||||
log_err("could not create ssl context");
|
log_err("could not create ssl context");
|
||||||
free(s->ip);
|
free(s->ip);
|
||||||
@@ -545,7 +448,6 @@ static char* q_of_msg(ProtobufCBinaryData message)
|
|||||||
char buf[300];
|
char buf[300];
|
||||||
/* header, name, type, class minimum to get the query tuple */
|
/* header, name, type, class minimum to get the query tuple */
|
||||||
if(message.len < 12 + 1 + 4 + 4) return NULL;
|
if(message.len < 12 + 1 + 4 + 4) return NULL;
|
||||||
if(LDNS_QDCOUNT(message.data) < 1) return NULL;
|
|
||||||
if(sldns_wire2str_rrquestion_buf(message.data+12, message.len-12,
|
if(sldns_wire2str_rrquestion_buf(message.data+12, message.len-12,
|
||||||
buf, sizeof(buf)) != 0) {
|
buf, sizeof(buf)) != 0) {
|
||||||
/* remove trailing newline, tabs to spaces */
|
/* remove trailing newline, tabs to spaces */
|
||||||
@@ -600,7 +502,7 @@ static char* tv_to_str(protobuf_c_boolean has_time_sec, uint64_t time_sec,
|
|||||||
time_t time_t_sec;
|
time_t time_t_sec;
|
||||||
memset(&tv, 0, sizeof(tv));
|
memset(&tv, 0, sizeof(tv));
|
||||||
if(has_time_sec) tv.tv_sec = time_sec;
|
if(has_time_sec) tv.tv_sec = time_sec;
|
||||||
if(has_time_nsec) tv.tv_usec = time_nsec/1000;
|
if(has_time_nsec) tv.tv_usec = time_nsec;
|
||||||
|
|
||||||
buf[0]=0;
|
buf[0]=0;
|
||||||
time_t_sec = tv.tv_sec;
|
time_t_sec = tv.tv_sec;
|
||||||
@@ -804,7 +706,7 @@ static ssize_t ssl_read_bytes(struct tap_data* data, void* buf, size_t len)
|
|||||||
(data->id?data->id:""));
|
(data->id?data->id:""));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
log_crypto_err_io("could not SSL_read", want);
|
log_crypto_err("could not SSL_read");
|
||||||
if(verbosity) log_info("dnstap client stream closed from %s",
|
if(verbosity) log_info("dnstap client stream closed from %s",
|
||||||
(data->id?data->id:""));
|
(data->id?data->id:""));
|
||||||
return 0;
|
return 0;
|
||||||
@@ -824,12 +726,27 @@ static ssize_t tap_receive(struct tap_data* data, void* buf, size_t len)
|
|||||||
return receive_bytes(data, data->fd, buf, len);
|
return receive_bytes(data, data->fd, buf, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** delete the tap structure */
|
||||||
|
static void tap_data_free(struct tap_data* data)
|
||||||
|
{
|
||||||
|
ub_event_del(data->ev);
|
||||||
|
ub_event_free(data->ev);
|
||||||
|
#ifdef HAVE_SSL
|
||||||
|
SSL_free(data->ssl);
|
||||||
|
#endif
|
||||||
|
close(data->fd);
|
||||||
|
free(data->id);
|
||||||
|
free(data->frame);
|
||||||
|
free(data);
|
||||||
|
}
|
||||||
|
|
||||||
/** reply with ACCEPT control frame to bidirectional client,
|
/** reply with ACCEPT control frame to bidirectional client,
|
||||||
* returns 0 on error */
|
* returns 0 on error */
|
||||||
static int reply_with_accept(struct tap_data* data)
|
static int reply_with_accept(struct tap_data* data)
|
||||||
{
|
{
|
||||||
#ifdef USE_DNSTAP
|
#ifdef USE_DNSTAP
|
||||||
/* len includes the escape and framelength */
|
/* len includes the escape and framelength */
|
||||||
|
int r;
|
||||||
size_t len = 0;
|
size_t len = 0;
|
||||||
void* acceptframe = fstrm_create_control_frame_accept(
|
void* acceptframe = fstrm_create_control_frame_accept(
|
||||||
DNSTAP_CONTENT_TYPE, &len);
|
DNSTAP_CONTENT_TYPE, &len);
|
||||||
@@ -840,19 +757,15 @@ static int reply_with_accept(struct tap_data* data)
|
|||||||
|
|
||||||
fd_set_block(data->fd);
|
fd_set_block(data->fd);
|
||||||
if(data->ssl) {
|
if(data->ssl) {
|
||||||
#ifdef HAVE_SSL
|
|
||||||
int r;
|
|
||||||
if((r=SSL_write(data->ssl, acceptframe, len)) <= 0) {
|
if((r=SSL_write(data->ssl, acceptframe, len)) <= 0) {
|
||||||
int r2;
|
if(SSL_get_error(data->ssl, r) == SSL_ERROR_ZERO_RETURN)
|
||||||
if((r2=SSL_get_error(data->ssl, r)) == SSL_ERROR_ZERO_RETURN)
|
|
||||||
log_err("SSL_write, peer closed connection");
|
log_err("SSL_write, peer closed connection");
|
||||||
else
|
else
|
||||||
log_crypto_err_io("could not SSL_write", r2);
|
log_err("could not SSL_write");
|
||||||
fd_set_nonblock(data->fd);
|
fd_set_nonblock(data->fd);
|
||||||
free(acceptframe);
|
free(acceptframe);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
} else {
|
} else {
|
||||||
if(send(data->fd, acceptframe, len, 0) == -1) {
|
if(send(data->fd, acceptframe, len, 0) == -1) {
|
||||||
log_err("send failed: %s", sock_strerror(errno));
|
log_err("send failed: %s", sock_strerror(errno));
|
||||||
@@ -876,7 +789,7 @@ static int reply_with_accept(struct tap_data* data)
|
|||||||
|
|
||||||
/** reply with FINISH control frame to bidirectional client,
|
/** reply with FINISH control frame to bidirectional client,
|
||||||
* returns 0 on error */
|
* returns 0 on error */
|
||||||
static int reply_with_finish(struct tap_data* data)
|
static int reply_with_finish(int fd)
|
||||||
{
|
{
|
||||||
#ifdef USE_DNSTAP
|
#ifdef USE_DNSTAP
|
||||||
size_t len = 0;
|
size_t len = 0;
|
||||||
@@ -886,37 +799,21 @@ static int reply_with_finish(struct tap_data* data)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
fd_set_block(data->fd);
|
fd_set_block(fd);
|
||||||
if(data->ssl) {
|
if(send(fd, finishframe, len, 0) == -1) {
|
||||||
#ifdef HAVE_SSL
|
log_err("send failed: %s", sock_strerror(errno));
|
||||||
int r;
|
fd_set_nonblock(fd);
|
||||||
if((r=SSL_write(data->ssl, finishframe, len)) <= 0) {
|
free(finishframe);
|
||||||
int r2;
|
return 0;
|
||||||
if((r2=SSL_get_error(data->ssl, r)) == SSL_ERROR_ZERO_RETURN)
|
|
||||||
log_err("SSL_write, peer closed connection");
|
|
||||||
else
|
|
||||||
log_crypto_err_io("could not SSL_write", r2);
|
|
||||||
fd_set_nonblock(data->fd);
|
|
||||||
free(finishframe);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
} else {
|
|
||||||
if(send(data->fd, finishframe, len, 0) == -1) {
|
|
||||||
log_err("send failed: %s", sock_strerror(errno));
|
|
||||||
fd_set_nonblock(data->fd);
|
|
||||||
free(finishframe);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if(verbosity) log_info("sent control frame(finish)");
|
if(verbosity) log_info("sent control frame(finish)");
|
||||||
|
|
||||||
fd_set_nonblock(data->fd);
|
fd_set_nonblock(fd);
|
||||||
free(finishframe);
|
free(finishframe);
|
||||||
return 1;
|
return 1;
|
||||||
#else
|
#else
|
||||||
log_err("no dnstap compiled, no reply");
|
log_err("no dnstap compiled, no reply");
|
||||||
(void)data;
|
(void)fd;
|
||||||
return 0;
|
return 0;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@@ -928,11 +825,7 @@ static int tap_check_peer(struct tap_data* data)
|
|||||||
if((SSL_get_verify_mode(data->ssl)&SSL_VERIFY_PEER)) {
|
if((SSL_get_verify_mode(data->ssl)&SSL_VERIFY_PEER)) {
|
||||||
/* verification */
|
/* verification */
|
||||||
if(SSL_get_verify_result(data->ssl) == X509_V_OK) {
|
if(SSL_get_verify_result(data->ssl) == X509_V_OK) {
|
||||||
#ifdef HAVE_SSL_GET1_PEER_CERTIFICATE
|
|
||||||
X509* x = SSL_get1_peer_certificate(data->ssl);
|
|
||||||
#else
|
|
||||||
X509* x = SSL_get_peer_certificate(data->ssl);
|
X509* x = SSL_get_peer_certificate(data->ssl);
|
||||||
#endif
|
|
||||||
if(!x) {
|
if(!x) {
|
||||||
if(verbosity) log_info("SSL connection %s"
|
if(verbosity) log_info("SSL connection %s"
|
||||||
" failed no certificate", data->id);
|
" failed no certificate", data->id);
|
||||||
@@ -954,11 +847,7 @@ static int tap_check_peer(struct tap_data* data)
|
|||||||
#endif
|
#endif
|
||||||
X509_free(x);
|
X509_free(x);
|
||||||
} else {
|
} else {
|
||||||
#ifdef HAVE_SSL_GET1_PEER_CERTIFICATE
|
|
||||||
X509* x = SSL_get1_peer_certificate(data->ssl);
|
|
||||||
#else
|
|
||||||
X509* x = SSL_get_peer_certificate(data->ssl);
|
X509* x = SSL_get_peer_certificate(data->ssl);
|
||||||
#endif
|
|
||||||
if(x) {
|
if(x) {
|
||||||
if(verbosity)
|
if(verbosity)
|
||||||
log_cert(VERB_ALGO, "peer certificate", x);
|
log_cert(VERB_ALGO, "peer certificate", x);
|
||||||
@@ -1000,7 +889,7 @@ static int tap_handshake(struct tap_data* data)
|
|||||||
return 0;
|
return 0;
|
||||||
} else if(r == 0) {
|
} else if(r == 0) {
|
||||||
/* closed */
|
/* closed */
|
||||||
tap_data_free(data, 1);
|
tap_data_free(data);
|
||||||
return 0;
|
return 0;
|
||||||
} else if(want == SSL_ERROR_SYSCALL) {
|
} else if(want == SSL_ERROR_SYSCALL) {
|
||||||
/* SYSCALL and errno==0 means closed uncleanly */
|
/* SYSCALL and errno==0 means closed uncleanly */
|
||||||
@@ -1018,7 +907,7 @@ static int tap_handshake(struct tap_data* data)
|
|||||||
if(!silent)
|
if(!silent)
|
||||||
log_err("SSL_handshake syscall: %s",
|
log_err("SSL_handshake syscall: %s",
|
||||||
strerror(errno));
|
strerror(errno));
|
||||||
tap_data_free(data, 1);
|
tap_data_free(data);
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
unsigned long err = ERR_get_error();
|
unsigned long err = ERR_get_error();
|
||||||
@@ -1028,7 +917,7 @@ static int tap_handshake(struct tap_data* data)
|
|||||||
verbose(VERB_OPS, "ssl handshake failed "
|
verbose(VERB_OPS, "ssl handshake failed "
|
||||||
"from %s", data->id);
|
"from %s", data->id);
|
||||||
}
|
}
|
||||||
tap_data_free(data, 1);
|
tap_data_free(data);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1036,7 +925,7 @@ static int tap_handshake(struct tap_data* data)
|
|||||||
data->ssl_handshake_done = 1;
|
data->ssl_handshake_done = 1;
|
||||||
if(!tap_check_peer(data)) {
|
if(!tap_check_peer(data)) {
|
||||||
/* closed */
|
/* closed */
|
||||||
tap_data_free(data, 1);
|
tap_data_free(data);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
@@ -1044,7 +933,7 @@ static int tap_handshake(struct tap_data* data)
|
|||||||
#endif /* HAVE_SSL */
|
#endif /* HAVE_SSL */
|
||||||
|
|
||||||
/** callback for dnstap listener */
|
/** callback for dnstap listener */
|
||||||
void dtio_tap_callback(int ATTR_UNUSED(fd), short ATTR_UNUSED(bits), void* arg)
|
void dtio_tap_callback(int fd, short ATTR_UNUSED(bits), void* arg)
|
||||||
{
|
{
|
||||||
struct tap_data* data = (struct tap_data*)arg;
|
struct tap_data* data = (struct tap_data*)arg;
|
||||||
if(verbosity>=3) log_info("tap callback");
|
if(verbosity>=3) log_info("tap callback");
|
||||||
@@ -1062,7 +951,7 @@ void dtio_tap_callback(int ATTR_UNUSED(fd), short ATTR_UNUSED(bits), void* arg)
|
|||||||
if(verbosity>=4) log_info("s recv %d", (int)ret);
|
if(verbosity>=4) log_info("s recv %d", (int)ret);
|
||||||
if(ret == 0) {
|
if(ret == 0) {
|
||||||
/* closed or error */
|
/* closed or error */
|
||||||
tap_data_free(data, 1);
|
tap_data_free(data);
|
||||||
return;
|
return;
|
||||||
} else if(ret == -1) {
|
} else if(ret == -1) {
|
||||||
/* continue later */
|
/* continue later */
|
||||||
@@ -1084,7 +973,7 @@ void dtio_tap_callback(int ATTR_UNUSED(fd), short ATTR_UNUSED(bits), void* arg)
|
|||||||
data->frame = calloc(1, data->len);
|
data->frame = calloc(1, data->len);
|
||||||
if(!data->frame) {
|
if(!data->frame) {
|
||||||
log_err("out of memory");
|
log_err("out of memory");
|
||||||
tap_data_free(data, 1);
|
tap_data_free(data);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1097,7 +986,7 @@ void dtio_tap_callback(int ATTR_UNUSED(fd), short ATTR_UNUSED(bits), void* arg)
|
|||||||
if(verbosity>=4) log_info("f recv %d", (int)r);
|
if(verbosity>=4) log_info("f recv %d", (int)r);
|
||||||
if(r == 0) {
|
if(r == 0) {
|
||||||
/* closed or error */
|
/* closed or error */
|
||||||
tap_data_free(data, 1);
|
tap_data_free(data);
|
||||||
return;
|
return;
|
||||||
} else if(r == -1) {
|
} else if(r == -1) {
|
||||||
/* continue later */
|
/* continue later */
|
||||||
@@ -1122,13 +1011,13 @@ void dtio_tap_callback(int ATTR_UNUSED(fd), short ATTR_UNUSED(bits), void* arg)
|
|||||||
data->is_bidirectional = 1;
|
data->is_bidirectional = 1;
|
||||||
if(verbosity) log_info("bidirectional stream");
|
if(verbosity) log_info("bidirectional stream");
|
||||||
if(!reply_with_accept(data)) {
|
if(!reply_with_accept(data)) {
|
||||||
tap_data_free(data, 1);
|
tap_data_free(data);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else if(data->len >= 4 && sldns_read_uint32(data->frame) ==
|
} else if(data->len >= 4 && sldns_read_uint32(data->frame) ==
|
||||||
FSTRM_CONTROL_FRAME_STOP && data->is_bidirectional) {
|
FSTRM_CONTROL_FRAME_STOP && data->is_bidirectional) {
|
||||||
if(!reply_with_finish(data)) {
|
if(!reply_with_finish(fd)) {
|
||||||
tap_data_free(data, 1);
|
tap_data_free(data);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1140,6 +1029,7 @@ void dtio_tap_callback(int ATTR_UNUSED(fd), short ATTR_UNUSED(bits), void* arg)
|
|||||||
data->len = 0;
|
data->len = 0;
|
||||||
data->len_done = 0;
|
data->len_done = 0;
|
||||||
data->data_done = 0;
|
data->data_done = 0;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** callback for main listening file descriptor */
|
/** callback for main listening file descriptor */
|
||||||
@@ -1152,9 +1042,7 @@ void dtio_mainfdcallback(int fd, short ATTR_UNUSED(bits), void* arg)
|
|||||||
char* id = NULL;
|
char* id = NULL;
|
||||||
struct sockaddr_storage addr;
|
struct sockaddr_storage addr;
|
||||||
socklen_t addrlen = (socklen_t)sizeof(addr);
|
socklen_t addrlen = (socklen_t)sizeof(addr);
|
||||||
int s;
|
int s = accept(fd, (struct sockaddr*)&addr, &addrlen);
|
||||||
memset(&addr, 0, sizeof(addr));
|
|
||||||
s = accept(fd, (struct sockaddr*)&addr, &addrlen);
|
|
||||||
if(s == -1) {
|
if(s == -1) {
|
||||||
#ifndef USE_WINSOCK
|
#ifndef USE_WINSOCK
|
||||||
/* EINTR is signal interrupt. others are closed connection. */
|
/* EINTR is signal interrupt. others are closed connection. */
|
||||||
@@ -1224,8 +1112,6 @@ void dtio_mainfdcallback(int fd, short ATTR_UNUSED(bits), void* arg)
|
|||||||
&dtio_tap_callback, data);
|
&dtio_tap_callback, data);
|
||||||
if(!data->ev) fatal_exit("could not ub_event_new");
|
if(!data->ev) fatal_exit("could not ub_event_new");
|
||||||
if(ub_event_add(data->ev, NULL) != 0) fatal_exit("could not ub_event_add");
|
if(ub_event_add(data->ev, NULL) != 0) fatal_exit("could not ub_event_add");
|
||||||
if(!tap_data_list_insert(&tap_sock->data_list, data))
|
|
||||||
fatal_exit("could not tap_data_list_insert");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** setup local accept sockets */
|
/** setup local accept sockets */
|
||||||
@@ -1261,13 +1147,13 @@ static void setup_tcp_list(struct main_tap_data* maindata,
|
|||||||
/** setup tls accept sockets */
|
/** setup tls accept sockets */
|
||||||
static void setup_tls_list(struct main_tap_data* maindata,
|
static void setup_tls_list(struct main_tap_data* maindata,
|
||||||
struct config_strlist_head* tls_list, char* server_key,
|
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;
|
struct config_strlist* item;
|
||||||
for(item = tls_list->first; item; item = item->next) {
|
for(item = tls_list->first; item; item = item->next) {
|
||||||
struct tap_socket* s;
|
struct tap_socket* s;
|
||||||
s = tap_socket_new_tlsaccept(item->str, &dtio_mainfdcallback,
|
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(!s) fatal_exit("out of memory");
|
||||||
if(!tap_socket_list_insert(&maindata->acceptlist, s))
|
if(!tap_socket_list_insert(&maindata->acceptlist, s))
|
||||||
fatal_exit("out of memory");
|
fatal_exit("out of memory");
|
||||||
@@ -1300,7 +1186,7 @@ static void
|
|||||||
setup_and_run(struct config_strlist_head* local_list,
|
setup_and_run(struct config_strlist_head* local_list,
|
||||||
struct config_strlist_head* tcp_list,
|
struct config_strlist_head* tcp_list,
|
||||||
struct config_strlist_head* tls_list, char* server_key,
|
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;
|
time_t secs = 0;
|
||||||
struct timeval now;
|
struct timeval now;
|
||||||
@@ -1326,7 +1212,7 @@ setup_and_run(struct config_strlist_head* local_list,
|
|||||||
setup_local_list(maindata, local_list);
|
setup_local_list(maindata, local_list);
|
||||||
setup_tcp_list(maindata, tcp_list);
|
setup_tcp_list(maindata, tcp_list);
|
||||||
setup_tls_list(maindata, tls_list, server_key, server_cert,
|
setup_tls_list(maindata, tls_list, server_key, server_cert,
|
||||||
verifypem, tls_protocols);
|
verifypem);
|
||||||
if(!tap_socket_list_addevs(maindata->acceptlist, base))
|
if(!tap_socket_list_addevs(maindata->acceptlist, base))
|
||||||
fatal_exit("could not setup accept events");
|
fatal_exit("could not setup accept events");
|
||||||
if(verbosity) log_info("start of service");
|
if(verbosity) log_info("start of service");
|
||||||
@@ -1340,114 +1226,6 @@ setup_and_run(struct config_strlist_head* local_list,
|
|||||||
free(maindata);
|
free(maindata);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* internal unit tests */
|
|
||||||
static int internal_unittest()
|
|
||||||
{
|
|
||||||
/* unit test tap_data_list_try_to_free_tail() */
|
|
||||||
#define unit_tap_datas_max 5
|
|
||||||
struct tap_data* datas[unit_tap_datas_max];
|
|
||||||
struct tap_data_list* list;
|
|
||||||
struct tap_socket* socket = calloc(1, sizeof(*socket));
|
|
||||||
size_t i = 0;
|
|
||||||
log_assert(socket);
|
|
||||||
log_assert(unit_tap_datas_max>2); /* needed for the test */
|
|
||||||
for(i=0; i<unit_tap_datas_max; i++) {
|
|
||||||
datas[i] = calloc(1, sizeof(struct tap_data));
|
|
||||||
log_assert(datas[i]);
|
|
||||||
log_assert(tap_data_list_insert(&socket->data_list, datas[i]));
|
|
||||||
}
|
|
||||||
/* sanity base check */
|
|
||||||
list = socket->data_list;
|
|
||||||
for(i=0; list; i++) list = list->next;
|
|
||||||
log_assert(i==unit_tap_datas_max);
|
|
||||||
|
|
||||||
/* Free the last data, tail cannot be erased */
|
|
||||||
list = socket->data_list;
|
|
||||||
while(list->next) list = list->next;
|
|
||||||
free(list->d);
|
|
||||||
list->d = NULL;
|
|
||||||
tap_data_list_try_to_free_tail(list);
|
|
||||||
list = socket->data_list;
|
|
||||||
for(i=0; list; i++) list = list->next;
|
|
||||||
log_assert(i==unit_tap_datas_max);
|
|
||||||
|
|
||||||
/* Free the third to last data, tail cannot be erased */
|
|
||||||
list = socket->data_list;
|
|
||||||
for(i=0; i<unit_tap_datas_max-3; i++) list = list->next;
|
|
||||||
free(list->d);
|
|
||||||
list->d = NULL;
|
|
||||||
tap_data_list_try_to_free_tail(list);
|
|
||||||
list = socket->data_list;
|
|
||||||
for(i=0; list; i++) list = list->next;
|
|
||||||
log_assert(i==unit_tap_datas_max);
|
|
||||||
|
|
||||||
/* Free the second to last data, try to remove tail from the third
|
|
||||||
* again, tail (last 2) should be removed */
|
|
||||||
list = socket->data_list;
|
|
||||||
for(i=0; i<unit_tap_datas_max-2; i++) list = list->next;
|
|
||||||
free(list->d);
|
|
||||||
list->d = NULL;
|
|
||||||
list = socket->data_list;
|
|
||||||
while(list->d) list = list->next;
|
|
||||||
tap_data_list_try_to_free_tail(list);
|
|
||||||
list = socket->data_list;
|
|
||||||
for(i=0; list; i++) list = list->next;
|
|
||||||
log_assert(i==unit_tap_datas_max-2);
|
|
||||||
|
|
||||||
/* Free all the remaining data, try to remove tail from the start,
|
|
||||||
* only the start should remain */
|
|
||||||
list = socket->data_list;
|
|
||||||
while(list) {
|
|
||||||
free(list->d);
|
|
||||||
list->d = NULL;
|
|
||||||
list = list->next;
|
|
||||||
}
|
|
||||||
tap_data_list_try_to_free_tail(socket->data_list);
|
|
||||||
list = socket->data_list;
|
|
||||||
for(i=0; list; i++) list = list->next;
|
|
||||||
log_assert(i==1);
|
|
||||||
|
|
||||||
/* clean up */
|
|
||||||
tap_data_list_delete(socket->data_list);
|
|
||||||
free(socket);
|
|
||||||
|
|
||||||
/* Start again. Add two elements */
|
|
||||||
socket = calloc(1, sizeof(*socket));
|
|
||||||
log_assert(socket);
|
|
||||||
for(i=0; i<2; i++) {
|
|
||||||
datas[i] = calloc(1, sizeof(struct tap_data));
|
|
||||||
log_assert(datas[i]);
|
|
||||||
log_assert(tap_data_list_insert(&socket->data_list, datas[i]));
|
|
||||||
}
|
|
||||||
/* sanity base check */
|
|
||||||
list = socket->data_list;
|
|
||||||
for(i=0; list; i++) list = list->next;
|
|
||||||
log_assert(i==2);
|
|
||||||
|
|
||||||
/* Free the last data, tail cannot be erased */
|
|
||||||
list = socket->data_list;
|
|
||||||
while(list->next) list = list->next;
|
|
||||||
free(list->d);
|
|
||||||
list->d = NULL;
|
|
||||||
tap_data_list_try_to_free_tail(list);
|
|
||||||
list = socket->data_list;
|
|
||||||
for(i=0; list; i++) list = list->next;
|
|
||||||
log_assert(i==2);
|
|
||||||
|
|
||||||
/* clean up */
|
|
||||||
tap_data_list_delete(socket->data_list);
|
|
||||||
free(socket);
|
|
||||||
|
|
||||||
if(log_get_lock()) {
|
|
||||||
lock_basic_destroy((lock_basic_type*)log_get_lock());
|
|
||||||
}
|
|
||||||
checklock_stop();
|
|
||||||
#ifdef USE_WINSOCK
|
|
||||||
WSACleanup();
|
|
||||||
#endif
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** getopt global, in case header files fail to declare it. */
|
/** getopt global, in case header files fail to declare it. */
|
||||||
extern int optind;
|
extern int optind;
|
||||||
/** getopt global, in case header files fail to declare it. */
|
/** getopt global, in case header files fail to declare it. */
|
||||||
@@ -1462,8 +1240,6 @@ int main(int argc, char** argv)
|
|||||||
struct config_strlist_head tcp_list;
|
struct config_strlist_head tcp_list;
|
||||||
struct config_strlist_head tls_list;
|
struct config_strlist_head tls_list;
|
||||||
char* server_key = NULL, *server_cert = NULL, *verifypem = NULL;
|
char* server_key = NULL, *server_cert = NULL, *verifypem = NULL;
|
||||||
|
|
||||||
char* tls_protocols = "TLSv1.2 TLSv1.3";
|
|
||||||
#ifdef USE_WINSOCK
|
#ifdef USE_WINSOCK
|
||||||
WSADATA wsa_data;
|
WSADATA wsa_data;
|
||||||
if(WSAStartup(MAKEWORD(2,2), &wsa_data) != 0) {
|
if(WSAStartup(MAKEWORD(2,2), &wsa_data) != 0) {
|
||||||
@@ -1500,7 +1276,7 @@ int main(int argc, char** argv)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* command line options */
|
/* command line options */
|
||||||
while( (c=getopt(argc, argv, "hcls:t:u:vx:y:z:")) != -1) {
|
while( (c=getopt(argc, argv, "hls:t:u:vx:y:z:")) != -1) {
|
||||||
switch(c) {
|
switch(c) {
|
||||||
case 'u':
|
case 'u':
|
||||||
if(!cfg_strlist_append(&local_list,
|
if(!cfg_strlist_append(&local_list,
|
||||||
@@ -1536,20 +1312,14 @@ int main(int argc, char** argv)
|
|||||||
case 'v':
|
case 'v':
|
||||||
verbosity++;
|
verbosity++;
|
||||||
break;
|
break;
|
||||||
case 'c':
|
|
||||||
#ifndef UNBOUND_DEBUG
|
|
||||||
fatal_exit("-c option needs compilation with "
|
|
||||||
"--enable-debug");
|
|
||||||
#endif
|
|
||||||
return internal_unittest();
|
|
||||||
case 'h':
|
case 'h':
|
||||||
case '?':
|
case '?':
|
||||||
default:
|
default:
|
||||||
usage(argv);
|
usage(argv);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* argc -= optind; not using further arguments */
|
argc -= optind;
|
||||||
/* argv += optind; not using further arguments */
|
argv += optind;
|
||||||
|
|
||||||
if(usessl) {
|
if(usessl) {
|
||||||
#ifdef HAVE_SSL
|
#ifdef HAVE_SSL
|
||||||
@@ -1563,32 +1333,21 @@ int main(int argc, char** argv)
|
|||||||
#else
|
#else
|
||||||
OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS
|
OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS
|
||||||
| OPENSSL_INIT_ADD_ALL_DIGESTS
|
| OPENSSL_INIT_ADD_ALL_DIGESTS
|
||||||
| OPENSSL_INIT_LOAD_CRYPTO_STRINGS
|
| OPENSSL_INIT_LOAD_CRYPTO_STRINGS, NULL);
|
||||||
# if defined(OPENSSL_INIT_NO_LOAD_CONFIG) && defined(UB_ON_WINDOWS)
|
|
||||||
| OPENSSL_INIT_NO_LOAD_CONFIG
|
|
||||||
# endif
|
|
||||||
, NULL);
|
|
||||||
#endif
|
#endif
|
||||||
#if OPENSSL_VERSION_NUMBER < 0x10100000 || !defined(HAVE_OPENSSL_INIT_SSL)
|
#if OPENSSL_VERSION_NUMBER < 0x10100000 || !defined(HAVE_OPENSSL_INIT_SSL)
|
||||||
(void)SSL_library_init();
|
(void)SSL_library_init();
|
||||||
#else
|
#else
|
||||||
(void)OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS
|
(void)OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS, NULL);
|
||||||
# if defined(OPENSSL_INIT_NO_LOAD_CONFIG) && defined(UB_ON_WINDOWS)
|
|
||||||
| OPENSSL_INIT_NO_LOAD_CONFIG
|
|
||||||
# endif
|
|
||||||
, NULL);
|
|
||||||
#endif
|
#endif
|
||||||
#endif /* HAVE_SSL */
|
#endif /* HAVE_SSL */
|
||||||
}
|
}
|
||||||
setup_and_run(&local_list, &tcp_list, &tls_list, server_key,
|
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(local_list.first);
|
||||||
config_delstrlist(tcp_list.first);
|
config_delstrlist(tcp_list.first);
|
||||||
config_delstrlist(tls_list.first);
|
config_delstrlist(tls_list.first);
|
||||||
|
|
||||||
if(log_get_lock()) {
|
|
||||||
lock_basic_destroy((lock_basic_type*)log_get_lock());
|
|
||||||
}
|
|
||||||
checklock_stop();
|
checklock_stop();
|
||||||
#ifdef USE_WINSOCK
|
#ifdef USE_WINSOCK
|
||||||
WSACleanup();
|
WSACleanup();
|
||||||
@@ -1659,8 +1418,7 @@ struct outbound_entry* worker_send_query(
|
|||||||
socklen_t ATTR_UNUSED(addrlen), uint8_t* ATTR_UNUSED(zone),
|
socklen_t ATTR_UNUSED(addrlen), uint8_t* ATTR_UNUSED(zone),
|
||||||
size_t ATTR_UNUSED(zonelen), int ATTR_UNUSED(tcp_upstream),
|
size_t ATTR_UNUSED(zonelen), int ATTR_UNUSED(tcp_upstream),
|
||||||
int ATTR_UNUSED(ssl_upstream), char* ATTR_UNUSED(tls_auth_name),
|
int ATTR_UNUSED(ssl_upstream), char* ATTR_UNUSED(tls_auth_name),
|
||||||
struct module_qstate* ATTR_UNUSED(q), int* ATTR_UNUSED(was_ratelimited),
|
struct module_qstate* ATTR_UNUSED(q), int* ATTR_UNUSED(was_ratelimited))
|
||||||
int* ATTR_UNUSED(ratelimit_incremented))
|
|
||||||
{
|
{
|
||||||
log_assert(0);
|
log_assert(0);
|
||||||
return 0;
|
return 0;
|
||||||
@@ -1694,8 +1452,7 @@ struct outbound_entry* libworker_send_query(
|
|||||||
socklen_t ATTR_UNUSED(addrlen), uint8_t* ATTR_UNUSED(zone),
|
socklen_t ATTR_UNUSED(addrlen), uint8_t* ATTR_UNUSED(zone),
|
||||||
size_t ATTR_UNUSED(zonelen), int ATTR_UNUSED(tcp_upstream),
|
size_t ATTR_UNUSED(zonelen), int ATTR_UNUSED(tcp_upstream),
|
||||||
int ATTR_UNUSED(ssl_upstream), char* ATTR_UNUSED(tls_auth_name),
|
int ATTR_UNUSED(ssl_upstream), char* ATTR_UNUSED(tls_auth_name),
|
||||||
struct module_qstate* ATTR_UNUSED(q), int* ATTR_UNUSED(was_ratelimited),
|
struct module_qstate* ATTR_UNUSED(q), int* ATTR_UNUSED(was_ratelimited))
|
||||||
int* ATTR_UNUSED(ratelimit_incremented))
|
|
||||||
{
|
{
|
||||||
log_assert(0);
|
log_assert(0);
|
||||||
return 0;
|
return 0;
|
||||||
@@ -1737,11 +1494,6 @@ void libworker_event_done_cb(void* ATTR_UNUSED(arg), int ATTR_UNUSED(rcode),
|
|||||||
log_assert(0);
|
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))
|
int context_query_cmp(const void* ATTR_UNUSED(a), const void* ATTR_UNUSED(b))
|
||||||
{
|
{
|
||||||
log_assert(0);
|
log_assert(0);
|
||||||
@@ -1803,33 +1555,3 @@ void remote_get_opt_ssl(char* ATTR_UNUSED(str), void* ATTR_UNUSED(arg))
|
|||||||
{
|
{
|
||||||
log_assert(0);
|
log_assert(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void fast_reload_service_cb(int ATTR_UNUSED(fd), short ATTR_UNUSED(ev),
|
|
||||||
void* ATTR_UNUSED(arg))
|
|
||||||
{
|
|
||||||
log_assert(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
int fast_reload_client_callback(struct comm_point* ATTR_UNUSED(c),
|
|
||||||
void* ATTR_UNUSED(arg), int ATTR_UNUSED(error),
|
|
||||||
struct comm_reply* ATTR_UNUSED(repinfo))
|
|
||||||
{
|
|
||||||
log_assert(0);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef HAVE_NGTCP2
|
|
||||||
void doq_client_event_cb(int ATTR_UNUSED(fd), short ATTR_UNUSED(ev),
|
|
||||||
void* ATTR_UNUSED(arg))
|
|
||||||
{
|
|
||||||
log_assert(0);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef HAVE_NGTCP2
|
|
||||||
void doq_client_timer_cb(int ATTR_UNUSED(fd), short ATTR_UNUSED(ev),
|
|
||||||
void* ATTR_UNUSED(arg))
|
|
||||||
{
|
|
||||||
log_assert(0);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|||||||
+19
-3097
File diff suppressed because it is too large
Load Diff
+5
-4
@@ -19,10 +19,11 @@ The DNSTAP code has BSD license in dnstap/dnstap.c.
|
|||||||
* Make and install: ./configure; make; make install
|
* Make and install: ./configure; make; make install
|
||||||
* --with-libevent=/path/to/libevent
|
* --with-libevent=/path/to/libevent
|
||||||
Can be set to either the system install or the build directory.
|
Can be set to either the system install or the build directory.
|
||||||
--with-libevent=no gives a builtin alternative implementation.
|
--with-libevent=no (default) gives a builtin alternative
|
||||||
Libevent is enabled by default, it is useful when having many
|
implementation. libevent is useful when having many (thousands)
|
||||||
(thousands) of outgoing ports. This improves randomization and spoof
|
of outgoing ports. This improves randomization and spoof
|
||||||
resistance. It also allows a higher number of outgoing queries.
|
resistance. For the default of 16 ports the builtin alternative
|
||||||
|
works well and is a little faster.
|
||||||
* --with-libexpat=/path/to/libexpat
|
* --with-libexpat=/path/to/libexpat
|
||||||
Can be set to the install directory of libexpat.
|
Can be set to the install directory of libexpat.
|
||||||
* --without-pthreads
|
* --without-pthreads
|
||||||
|
|||||||
+1
-21
@@ -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:
|
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.
|
The prefix must be a /96 or shorter.
|
||||||
|
|
||||||
@@ -28,23 +28,3 @@ prefix. For example:
|
|||||||
;; ANSWER SECTION:
|
;; ANSWER SECTION:
|
||||||
jazz-v4.viagenie.ca. 86400 IN AAAA 64:ff9b::ce7b:1f02
|
jazz-v4.viagenie.ca. 86400 IN AAAA 64:ff9b::ce7b:1f02
|
||||||
|
|
||||||
|
|
||||||
NAT64 support was added by David Lamparter in 2022; license(s) of the
|
|
||||||
surrounding code apply. Note that NAT64 is closely related but functionally
|
|
||||||
orthogonal to DNS64; it allows Unbound to send outgoing queries to IPv4-only
|
|
||||||
servers over IPv6 through the configured NAT64 prefix. This allows running
|
|
||||||
an Unbound instance on an IPv6-only host without breaking every single domain
|
|
||||||
that only has IPv4 servers. Whether that Unbound instance also does DNS64 is
|
|
||||||
an independent choice.
|
|
||||||
|
|
||||||
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:
|
|
||||||
|
|
||||||
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.
|
|
||||||
|
|||||||
@@ -1,21 +0,0 @@
|
|||||||
After Unbound 1.23.0, the source of the man pages is in reStructuredText format.
|
|
||||||
|
|
||||||
This helps with the online documentation at https://unbound.docs.nlnetlabs.nl
|
|
||||||
and makes it easier to maintain and contribute to the documentation.
|
|
||||||
|
|
||||||
The templated man pages (*.in) are still part of the code repository as to not
|
|
||||||
alter current procedures that could be in place by users/packagers.
|
|
||||||
|
|
||||||
These man pages (*.in) are still the ones being used when
|
|
||||||
configuring/installing Unbound.
|
|
||||||
Packagers/users do not have to generate any man pages themselves, this is done
|
|
||||||
by the core developers during development and upon releasing new versions.
|
|
||||||
|
|
||||||
The templated man pages (*.in) are generated by Sphinx (used for the online
|
|
||||||
documentation).
|
|
||||||
The online documentation has its own repository at
|
|
||||||
https://github.com/NLnetLabs/unbound-manual.
|
|
||||||
|
|
||||||
In that README.md (https://github.com/NLnetLabs/unbound-manual/README.md)
|
|
||||||
there are further simple instructions on how to generate the templated man
|
|
||||||
pages there and update them in this repository.
|
|
||||||
+41
-252
@@ -35,14 +35,9 @@ server:
|
|||||||
# statistics-cumulative: no
|
# statistics-cumulative: no
|
||||||
|
|
||||||
# enable extended statistics (query types, answer codes, status)
|
# enable extended statistics (query types, answer codes, status)
|
||||||
# printed from unbound-control. Default off, because of speed.
|
# printed from unbound-control. default off, because of speed.
|
||||||
# extended-statistics: no
|
# extended-statistics: no
|
||||||
|
|
||||||
# Inhibits selected extended statistics (qtype, qclass, qopcode, rcode,
|
|
||||||
# rpz-actions) from printing if their value is 0.
|
|
||||||
# Default on.
|
|
||||||
# statistics-inhibit-zero: yes
|
|
||||||
|
|
||||||
# number of threads to create. 1 disables threading.
|
# number of threads to create. 1 disables threading.
|
||||||
# num-threads: 1
|
# num-threads: 1
|
||||||
|
|
||||||
@@ -54,7 +49,7 @@ server:
|
|||||||
# interface: 192.0.2.153
|
# interface: 192.0.2.153
|
||||||
# interface: 192.0.2.154
|
# interface: 192.0.2.154
|
||||||
# interface: 192.0.2.154@5003
|
# interface: 192.0.2.154@5003
|
||||||
# interface: 2001:db8::5
|
# interface: 2001:DB8::5
|
||||||
# interface: eth0@5003
|
# interface: eth0@5003
|
||||||
|
|
||||||
# enable this feature to copy the source address of queries to reply.
|
# enable this feature to copy the source address of queries to reply.
|
||||||
@@ -72,12 +67,12 @@ server:
|
|||||||
# server from by ip-address. If none, the default (all) interface
|
# server from by ip-address. If none, the default (all) interface
|
||||||
# is used. Specify every interface on a 'outgoing-interface:' line.
|
# is used. Specify every interface on a 'outgoing-interface:' line.
|
||||||
# outgoing-interface: 192.0.2.153
|
# outgoing-interface: 192.0.2.153
|
||||||
# outgoing-interface: 2001:db8::5
|
# outgoing-interface: 2001:DB8::5
|
||||||
# outgoing-interface: 2001:db8::6
|
# outgoing-interface: 2001:DB8::6
|
||||||
|
|
||||||
# Specify a netblock to use remainder 64 bits as random bits for
|
# Specify a netblock to use remainder 64 bits as random bits for
|
||||||
# upstream queries. Uses freebind option (Linux).
|
# 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
|
# Also (Linux:) ip -6 addr add 2001:db8::/64 dev lo
|
||||||
# And: ip -6 route add local 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.
|
# And set prefer-ip6: yes to use the ip6 randomness from a netblock.
|
||||||
@@ -116,8 +111,8 @@ server:
|
|||||||
# so-rcvbuf: 0
|
# so-rcvbuf: 0
|
||||||
|
|
||||||
# buffer size for UDP port 53 outgoing (SO_SNDBUF socket option).
|
# buffer size for UDP port 53 outgoing (SO_SNDBUF socket option).
|
||||||
# 0 is system default. Set larger to handle spikes on very busy servers.
|
# 0 is system default. Use 4m to handle spikes on very busy servers.
|
||||||
# so-sndbuf: 4m
|
# so-sndbuf: 0
|
||||||
|
|
||||||
# use SO_REUSEPORT to distribute queries over threads.
|
# use SO_REUSEPORT to distribute queries over threads.
|
||||||
# at extreme load it could be better to turn it off to distribute even.
|
# at extreme load it could be better to turn it off to distribute even.
|
||||||
@@ -143,8 +138,8 @@ server:
|
|||||||
# edns-buffer-size: 1232
|
# edns-buffer-size: 1232
|
||||||
|
|
||||||
# Maximum UDP response size (not applied to TCP response).
|
# Maximum UDP response size (not applied to TCP response).
|
||||||
# Suggested values are 512 to 4096. Default is 1232. 65536 disables it.
|
# Suggested values are 512 to 4096. Default is 4096. 65536 disables it.
|
||||||
# max-udp-size: 1232
|
# max-udp-size: 4096
|
||||||
|
|
||||||
# max memory to use for stream(tcp and tls) waiting result buffers.
|
# max memory to use for stream(tcp and tls) waiting result buffers.
|
||||||
# stream-wait-size: 4m
|
# stream-wait-size: 4m
|
||||||
@@ -163,7 +158,7 @@ server:
|
|||||||
# msg-cache-slabs: 4
|
# msg-cache-slabs: 4
|
||||||
|
|
||||||
# the number of queries that a thread gets to service.
|
# the number of queries that a thread gets to service.
|
||||||
# num-queries-per-thread: 2048
|
# num-queries-per-thread: 1024
|
||||||
|
|
||||||
# if very busy, 50% queries run to completion, 50% get timeout in msec
|
# if very busy, 50% queries run to completion, 50% get timeout in msec
|
||||||
# jostle-timeout: 200
|
# jostle-timeout: 200
|
||||||
@@ -178,62 +173,10 @@ server:
|
|||||||
# a throwaway response (also timeouts) is received.
|
# a throwaway response (also timeouts) is received.
|
||||||
# outbound-msg-retry: 5
|
# outbound-msg-retry: 5
|
||||||
|
|
||||||
# Hard limit on the number of outgoing queries Unbound will make while
|
|
||||||
# resolving a name, making sure large NS sets do not loop.
|
|
||||||
# It resets on query restarts (e.g., CNAME) and referrals.
|
|
||||||
# max-sent-count: 32
|
|
||||||
|
|
||||||
# Hard limit on the number of times Unbound is allowed to restart a
|
|
||||||
# query upon encountering a CNAME record.
|
|
||||||
# max-query-restarts: 11
|
|
||||||
|
|
||||||
# Limit on number of NS records in NS RRset for incoming packets.
|
|
||||||
# iter-scrub-ns: 20
|
|
||||||
|
|
||||||
# Limit on number of CNAME, DNAME records for incoming packets.
|
|
||||||
# iter-scrub-cname: 11
|
|
||||||
|
|
||||||
# Limit on 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
|
|
||||||
|
|
||||||
# Should the scrubber remove promiscuous NS from positive answers,
|
|
||||||
# protects against poison attempts.
|
|
||||||
# iter-scrub-promiscuous: yes
|
|
||||||
|
|
||||||
# Limit on number of DNSSEC validation attempts for a query.
|
|
||||||
# val-validation-attempts: 32
|
|
||||||
|
|
||||||
# Limit on number of DNSSEC hash attempts for a query.
|
|
||||||
# val-hash-attempts: 32
|
|
||||||
|
|
||||||
# msec for waiting for an unknown server to reply. Increase if you
|
# msec for waiting for an unknown server to reply. Increase if you
|
||||||
# are behind a slow satellite link, to eg. 1128.
|
# are behind a slow satellite link, to eg. 1128.
|
||||||
# unknown-server-time-limit: 376
|
# unknown-server-time-limit: 376
|
||||||
|
|
||||||
# msec before recursion replies are dropped. The work item continues.
|
|
||||||
# discard-timeout: 1900
|
|
||||||
|
|
||||||
# Max number of replies waiting for recursion per IP address.
|
|
||||||
# wait-limit: 1000
|
|
||||||
|
|
||||||
# Max replies waiting for recursion for IP address with cookie.
|
|
||||||
# wait-limit-cookie: 10000
|
|
||||||
|
|
||||||
# Apart from the default, the wait limit can be set for a netblock.
|
|
||||||
# wait-limit-netblock: 192.0.2.0/24 50000
|
|
||||||
|
|
||||||
# Apart from the default, the wait limit with cookie can be adjusted.
|
|
||||||
# wait-limit-cookie-netblock: 192.0.2.0/24 50000
|
|
||||||
|
|
||||||
# Defaults for loopback, it has no wait limit.
|
|
||||||
# wait-limit-netblock: 127.0.0.0/8 -1
|
|
||||||
# wait-limit-netblock: ::1/128 -1
|
|
||||||
# wait-limit-cookie-netblock: 127.0.0.0/8 -1
|
|
||||||
# wait-limit-cookie-netblock: ::1/128 -1
|
|
||||||
|
|
||||||
# the amount of memory to use for the RRset cache.
|
# the amount of memory to use for the RRset cache.
|
||||||
# plain value in bytes or you can append k, m or G. default is "4Mb".
|
# plain value in bytes or you can append k, m or G. default is "4Mb".
|
||||||
# rrset-cache-size: 4m
|
# rrset-cache-size: 4m
|
||||||
@@ -254,11 +197,6 @@ server:
|
|||||||
# the time to live (TTL) value cap for negative responses in the cache
|
# the time to live (TTL) value cap for negative responses in the cache
|
||||||
# cache-max-negative-ttl: 3600
|
# cache-max-negative-ttl: 3600
|
||||||
|
|
||||||
# the time to live (TTL) value lower bound, in seconds. Default 0.
|
|
||||||
# For negative responses in the cache. If disabled, default,
|
|
||||||
# cache-min-ttl applies if configured.
|
|
||||||
# cache-min-negative-ttl: 0
|
|
||||||
|
|
||||||
# the time to live (TTL) value for cached roundtrip times, lameness and
|
# the time to live (TTL) value for cached roundtrip times, lameness and
|
||||||
# EDNS version information for hosts. In seconds.
|
# EDNS version information for hosts. In seconds.
|
||||||
# infra-host-ttl: 900
|
# infra-host-ttl: 900
|
||||||
@@ -291,18 +229,6 @@ server:
|
|||||||
# Enable IPv6, "yes" or "no".
|
# Enable IPv6, "yes" or "no".
|
||||||
# do-ip6: yes
|
# do-ip6: yes
|
||||||
|
|
||||||
# If running unbound on an IPv6-only host, domains that only have
|
|
||||||
# IPv4 servers would become unresolvable. If NAT64 is available in
|
|
||||||
# the network, unbound can use NAT64 to reach these servers with
|
|
||||||
# the following option. This is NOT needed for enabling DNS64 on a
|
|
||||||
# system that has IPv4 connectivity.
|
|
||||||
# Consider also enabling prefer-ip6 to prefer native IPv6 connections
|
|
||||||
# to nameservers.
|
|
||||||
# do-nat64: no
|
|
||||||
|
|
||||||
# NAT64 prefix. Defaults to using dns64-prefix value.
|
|
||||||
# nat64-prefix: 64:ff9b::0/96
|
|
||||||
|
|
||||||
# Enable UDP, "yes" or "no".
|
# Enable UDP, "yes" or "no".
|
||||||
# do-udp: yes
|
# do-udp: yes
|
||||||
|
|
||||||
@@ -331,14 +257,9 @@ server:
|
|||||||
# Enable EDNS TCP keepalive option.
|
# Enable EDNS TCP keepalive option.
|
||||||
# edns-tcp-keepalive: no
|
# edns-tcp-keepalive: no
|
||||||
|
|
||||||
# Timeout for EDNS TCP keepalive, in msec. Overrides tcp-idle-timeout
|
# Timeout for EDNS TCP keepalive, in msec.
|
||||||
# if edns-tcp-keepalive is set.
|
|
||||||
# edns-tcp-keepalive-timeout: 120000
|
# edns-tcp-keepalive-timeout: 120000
|
||||||
|
|
||||||
# UDP queries that have waited in the socket buffer for a long time
|
|
||||||
# can be dropped. Default is 0, disabled. In seconds, such as 3.
|
|
||||||
# sock-queue-timeout: 0
|
|
||||||
|
|
||||||
# Use systemd socket activation for UDP, TCP, and control sockets.
|
# Use systemd socket activation for UDP, TCP, and control sockets.
|
||||||
# use-systemd: no
|
# use-systemd: no
|
||||||
|
|
||||||
@@ -352,7 +273,6 @@ server:
|
|||||||
# Choose deny (drop message), refuse (polite error reply),
|
# Choose deny (drop message), refuse (polite error reply),
|
||||||
# allow (recursive ok), allow_setrd (recursive ok, rd bit is forced on),
|
# allow (recursive ok), allow_setrd (recursive ok, rd bit is forced on),
|
||||||
# allow_snoop (recursive and nonrecursive ok)
|
# allow_snoop (recursive and nonrecursive ok)
|
||||||
# allow_cookie (allow UDP with valid cookie or stateful transport)
|
|
||||||
# deny_non_local (drop queries unless can be answered from local-data)
|
# deny_non_local (drop queries unless can be answered from local-data)
|
||||||
# refuse_non_local (like deny_non_local but polite error reply).
|
# refuse_non_local (like deny_non_local but polite error reply).
|
||||||
# access-control: 127.0.0.0/8 allow
|
# access-control: 127.0.0.0/8 allow
|
||||||
@@ -388,7 +308,7 @@ server:
|
|||||||
# interface-action: 192.0.2.153 allow
|
# interface-action: 192.0.2.153 allow
|
||||||
# interface-action: 192.0.2.154 allow
|
# interface-action: 192.0.2.154 allow
|
||||||
# interface-action: 192.0.2.154@5003 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
|
# interface-action: eth0@5003 allow
|
||||||
|
|
||||||
# Similar to 'access-control-tag:' but for interfaces.
|
# Similar to 'access-control-tag:' but for interfaces.
|
||||||
@@ -480,10 +400,6 @@ server:
|
|||||||
# print UTC timestamp in ascii to logfile, default is epoch in seconds.
|
# print UTC timestamp in ascii to logfile, default is epoch in seconds.
|
||||||
# log-time-ascii: no
|
# log-time-ascii: no
|
||||||
|
|
||||||
# log timestamp in ISO8601 format if also log-time-ascii is enabled.
|
|
||||||
# (y-m-dTh:m:s.msec[+-]tzhours:tzminutes)
|
|
||||||
# log-time-iso: no
|
|
||||||
|
|
||||||
# print one line with time, IP, name, type, class for every query.
|
# print one line with time, IP, name, type, class for every query.
|
||||||
# log-queries: no
|
# log-queries: no
|
||||||
|
|
||||||
@@ -495,9 +411,6 @@ server:
|
|||||||
# filtering log-queries and log-replies from the log.
|
# filtering log-queries and log-replies from the log.
|
||||||
# log-tag-queryreply: no
|
# log-tag-queryreply: no
|
||||||
|
|
||||||
# log with destination address, port and type for log-replies.
|
|
||||||
# log-destaddr: no
|
|
||||||
|
|
||||||
# log the local-zone actions, like local-zone type inform is enabled
|
# log the local-zone actions, like local-zone type inform is enabled
|
||||||
# also for the other local zone types.
|
# also for the other local zone types.
|
||||||
# log-local-actions: no
|
# log-local-actions: no
|
||||||
@@ -505,10 +418,6 @@ server:
|
|||||||
# print log lines that say why queries return SERVFAIL to clients.
|
# print log lines that say why queries return SERVFAIL to clients.
|
||||||
# log-servfail: no
|
# 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.
|
# the pid file. Can be an absolute path outside of chroot/work dir.
|
||||||
# pidfile: "@UNBOUND_PIDFILE@"
|
# pidfile: "@UNBOUND_PIDFILE@"
|
||||||
|
|
||||||
@@ -560,9 +469,6 @@ server:
|
|||||||
# Harden against out of zone rrsets, to avoid spoofing attempts.
|
# Harden against out of zone rrsets, to avoid spoofing attempts.
|
||||||
# harden-glue: yes
|
# harden-glue: yes
|
||||||
|
|
||||||
# Harden against unverified (outside-zone, including sibling zone) glue rrsets
|
|
||||||
# harden-unverified-glue: no
|
|
||||||
|
|
||||||
# Harden against receiving dnssec-stripped data. If you turn it
|
# Harden against receiving dnssec-stripped data. If you turn it
|
||||||
# off, failing to validate dnskey data for a trustanchor will
|
# off, failing to validate dnskey data for a trustanchor will
|
||||||
# trigger insecure mode for that zone (like without a trustanchor).
|
# trigger insecure mode for that zone (like without a trustanchor).
|
||||||
@@ -579,18 +485,10 @@ server:
|
|||||||
# harden-referral-path: no
|
# harden-referral-path: no
|
||||||
|
|
||||||
# Harden against algorithm downgrade when multiple algorithms are
|
# Harden against algorithm downgrade when multiple algorithms are
|
||||||
# advertised in the DS record. If no, allows any algorithm
|
# advertised in the DS record. If no, allows the weakest algorithm
|
||||||
# to validate the zone which is the standard behavior for validators.
|
# to validate the zone.
|
||||||
# Check the manpage for detailed information.
|
|
||||||
# harden-algo-downgrade: no
|
# harden-algo-downgrade: no
|
||||||
|
|
||||||
# Harden against unknown records in the authority section and the
|
|
||||||
# additional section.
|
|
||||||
# harden-unknown-additional: no
|
|
||||||
|
|
||||||
# Harden CNAME redirections by following them.
|
|
||||||
# harden-cname-follow: yes
|
|
||||||
|
|
||||||
# Sent minimum amount of information to upstream servers to enhance
|
# Sent minimum amount of information to upstream servers to enhance
|
||||||
# privacy. Only sent minimum required labels of the QNAME and set QTYPE
|
# privacy. Only sent minimum required labels of the QNAME and set QTYPE
|
||||||
# to A when possible.
|
# to A when possible.
|
||||||
@@ -674,7 +572,7 @@ server:
|
|||||||
# or, just before the iterator).
|
# or, just before the iterator).
|
||||||
# module-config: "validator 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.
|
# initial file like trust-anchor-file, then it stores metadata.
|
||||||
# Use several entries, one per domain name, to track multiple zones.
|
# Use several entries, one per domain name, to track multiple zones.
|
||||||
#
|
#
|
||||||
@@ -734,10 +632,10 @@ server:
|
|||||||
# val-max-restart: 5
|
# val-max-restart: 5
|
||||||
|
|
||||||
# Should additional section of secure message also be kept clean of
|
# 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
|
# potential bogus data in the additional section. All unsigned data
|
||||||
# in the additional section is removed from secure messages.
|
# in the additional section is removed from secure messages.
|
||||||
# val-clean-additional: no
|
# val-clean-additional: yes
|
||||||
|
|
||||||
# Turn permissive mode on to permit bogus messages. Thus, messages
|
# Turn permissive mode on to permit bogus messages. Thus, messages
|
||||||
# for which security checks failed will be returned to clients,
|
# for which security checks failed will be returned to clients,
|
||||||
@@ -751,19 +649,13 @@ server:
|
|||||||
# that set CD but cannot validate themselves.
|
# that set CD but cannot validate themselves.
|
||||||
# ignore-cd-flag: no
|
# ignore-cd-flag: no
|
||||||
|
|
||||||
# Disable the DO flag in outgoing requests. It is helpful for upstream
|
|
||||||
# devices that cannot handle DNSSEC information. But do not enable it
|
|
||||||
# otherwise, because it would stop DNSSEC validation.
|
|
||||||
# disable-edns-do: no
|
|
||||||
|
|
||||||
# Serve expired responses from cache, with serve-expired-reply-ttl in
|
# Serve expired responses from cache, with serve-expired-reply-ttl in
|
||||||
# the response. By default it first tries to refresh an expired answer.
|
# the response, and then attempt to fetch the data afresh.
|
||||||
# Can be configured with serve-expired-client-timeout.
|
|
||||||
# serve-expired: no
|
# serve-expired: no
|
||||||
#
|
#
|
||||||
# Limit serving of expired responses to configured seconds after
|
# Limit serving of expired responses to configured seconds after
|
||||||
# expiration. 0 disables the limit.
|
# expiration. 0 disables the limit.
|
||||||
# serve-expired-ttl: 86400
|
# serve-expired-ttl: 0
|
||||||
#
|
#
|
||||||
# Set the TTL of expired records to the serve-expired-ttl value after a
|
# Set the TTL of expired records to the serve-expired-ttl value after a
|
||||||
# failed attempt to retrieve the record from upstream. This makes sure
|
# failed attempt to retrieve the record from upstream. This makes sure
|
||||||
@@ -772,14 +664,14 @@ server:
|
|||||||
# serve-expired-ttl-reset: no
|
# serve-expired-ttl-reset: no
|
||||||
#
|
#
|
||||||
# TTL value to use when replying with expired data.
|
# TTL value to use when replying with expired data.
|
||||||
# Capped by the original TTL of the record.
|
|
||||||
# serve-expired-reply-ttl: 30
|
# serve-expired-reply-ttl: 30
|
||||||
#
|
#
|
||||||
# Time in milliseconds before replying to the client with expired data.
|
# Time in milliseconds before replying to the client with expired data.
|
||||||
# This essentially enables the serve-stale behavior as specified in
|
# This essentially enables the serve-stale behavior as specified in
|
||||||
# RFC 8767 that first tries to resolve before immediately responding
|
# RFC 8767 that first tries to resolve before
|
||||||
# with expired data. 0 disables this behavior.
|
# immediately responding with expired data. 0 disables this behavior.
|
||||||
# serve-expired-client-timeout: 1800
|
# A recommended value is 1800.
|
||||||
|
# serve-expired-client-timeout: 0
|
||||||
|
|
||||||
# Return the original TTL as received from the upstream name server rather
|
# Return the original TTL as received from the upstream name server rather
|
||||||
# than the decrementing TTL as stored in the cache. Enabling this feature
|
# than the decrementing TTL as stored in the cache. Enabling this feature
|
||||||
@@ -838,8 +730,6 @@ server:
|
|||||||
# local-zone: "127.in-addr.arpa." nodefault
|
# local-zone: "127.in-addr.arpa." nodefault
|
||||||
# local-zone: "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa." nodefault
|
# local-zone: "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa." nodefault
|
||||||
# local-zone: "home.arpa." nodefault
|
# local-zone: "home.arpa." nodefault
|
||||||
# local-zone: "resolver.arpa." nodefault
|
|
||||||
# local-zone: "service.arpa." nodefault
|
|
||||||
# local-zone: "onion." nodefault
|
# local-zone: "onion." nodefault
|
||||||
# local-zone: "test." nodefault
|
# local-zone: "test." nodefault
|
||||||
# local-zone: "invalid." nodefault
|
# local-zone: "invalid." nodefault
|
||||||
@@ -906,12 +796,6 @@ server:
|
|||||||
# o always_transparent, always_refuse, always_nxdomain, always_nodata,
|
# o always_transparent, always_refuse, always_nxdomain, always_nodata,
|
||||||
# always_deny resolve in that way but ignore local data for
|
# always_deny resolve in that way but ignore local data for
|
||||||
# that name
|
# 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 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.
|
# o noview breaks out of that view towards global local-zones.
|
||||||
#
|
#
|
||||||
@@ -946,22 +830,6 @@ server:
|
|||||||
# add a netblock specific override to a localzone, with zone type
|
# add a netblock specific override to a localzone, with zone type
|
||||||
# local-zone-override: "example.com" 192.0.2.0/24 refuse
|
# local-zone-override: "example.com" 192.0.2.0/24 refuse
|
||||||
|
|
||||||
# Action to apply when the IP address in an AAAA or A RR in the answer
|
|
||||||
# section of a response matches the specified IP netblock.
|
|
||||||
# Requires use of the respip module.
|
|
||||||
# response-ip: 192.0.2.0/24 redirect
|
|
||||||
|
|
||||||
# Redirect as specified by the "resource record string" when the IP
|
|
||||||
# address in an AAAA or A RR in the answer section of a response
|
|
||||||
# matches the specified IP netblock.
|
|
||||||
# Requires use of the respip module.
|
|
||||||
# response-ip-data: 192.0.2.0/24 "example. A 192.0.2.1"
|
|
||||||
|
|
||||||
# Apply tag(s) when the IP address in an AAAA or A RR in the answer
|
|
||||||
# section of a response matches the specified IP netblock.
|
|
||||||
# Requires use of the respip module.
|
|
||||||
# response-ip-tag: 192.0.2.0/24 "tag1 tag2"
|
|
||||||
|
|
||||||
# service clients over TLS (on the TCP sockets) with plain DNS inside
|
# service clients over TLS (on the TCP sockets) with plain DNS inside
|
||||||
# the TLS stream, and over HTTPS using HTTP/2 as specified in RFC8484.
|
# the TLS stream, and over HTTPS using HTTP/2 as specified in RFC8484.
|
||||||
# Give the certificate to use and private key.
|
# Give the certificate to use and private key.
|
||||||
@@ -970,23 +838,21 @@ server:
|
|||||||
# tls-service-pem: "path/to/publiccertfile.pem"
|
# tls-service-pem: "path/to/publiccertfile.pem"
|
||||||
# tls-port: 853
|
# tls-port: 853
|
||||||
# https-port: 443
|
# https-port: 443
|
||||||
# quic-port: 853
|
|
||||||
|
|
||||||
# Also serve tls on these port numbers (eg. 443, ...), by listing
|
|
||||||
# tls-additional-port: portno for each of the port numbers.
|
|
||||||
|
|
||||||
# cipher setting for TLSv1.2
|
# cipher setting for TLSv1.2
|
||||||
# tls-ciphers: "DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256"
|
# tls-ciphers: "DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256"
|
||||||
# cipher setting for TLSv1.3
|
# cipher setting for TLSv1.3
|
||||||
# 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"
|
# 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.
|
# Pad responses to padded queries received over TLS
|
||||||
# Changing the value requires a restart.
|
# pad-responses: yes
|
||||||
# tls-use-sni: yes
|
|
||||||
|
|
||||||
# TLS protocols.
|
# Padded responses will be padded to the closest multiple of this size.
|
||||||
# Changing the value requires a restart.
|
# pad-responses-block-size: 468
|
||||||
# tls-protocols: "TLSv1.2 TLSv1.3"
|
|
||||||
|
# Use the SNI extension for TLS connections. Default is yes.
|
||||||
|
# Changing the value requires a reload.
|
||||||
|
# tls-use-sni: yes
|
||||||
|
|
||||||
# Add the secret file for TLS Session Ticket.
|
# Add the secret file for TLS Session Ticket.
|
||||||
# Secret file must be 80 bytes of random data.
|
# Secret file must be 80 bytes of random data.
|
||||||
@@ -1008,18 +874,15 @@ server:
|
|||||||
# and on other systems, the default openssl certificates
|
# and on other systems, the default openssl certificates
|
||||||
# tls-system-cert: no
|
# tls-system-cert: no
|
||||||
|
|
||||||
# Pad responses to padded queries received over TLS
|
|
||||||
# pad-responses: yes
|
|
||||||
|
|
||||||
# Padded responses will be padded to the closest multiple of this size.
|
|
||||||
# pad-responses-block-size: 468
|
|
||||||
|
|
||||||
# Pad queries over TLS upstreams
|
# Pad queries over TLS upstreams
|
||||||
# pad-queries: yes
|
# pad-queries: yes
|
||||||
|
|
||||||
# Padded queries will be padded to the closest multiple of this size.
|
# Padded queries will be padded to the closest multiple of this size.
|
||||||
# pad-queries-block-size: 128
|
# pad-queries-block-size: 128
|
||||||
|
|
||||||
|
# Also serve tls on these port numbers (eg. 443, ...), by listing
|
||||||
|
# tls-additional-port: portno for each of the port numbers.
|
||||||
|
|
||||||
# HTTP endpoint to provide DNS-over-HTTPS service on.
|
# HTTP endpoint to provide DNS-over-HTTPS service on.
|
||||||
# http-endpoint: "/dns-query"
|
# http-endpoint: "/dns-query"
|
||||||
|
|
||||||
@@ -1039,9 +902,6 @@ server:
|
|||||||
# Disable TLS for DNS-over-HTTP downstream service.
|
# Disable TLS for DNS-over-HTTP downstream service.
|
||||||
# http-notls-downstream: no
|
# http-notls-downstream: no
|
||||||
|
|
||||||
# Maximum number of bytes used for QUIC buffers.
|
|
||||||
# quic-size: 8m
|
|
||||||
|
|
||||||
# The interfaces that use these listed port numbers will support and
|
# The interfaces that use these listed port numbers will support and
|
||||||
# expect PROXYv2. For UDP and TCP/TLS interfaces.
|
# expect PROXYv2. For UDP and TCP/TLS interfaces.
|
||||||
# proxy-protocol-port: portno for each of the port numbers.
|
# proxy-protocol-port: portno for each of the port numbers.
|
||||||
@@ -1082,13 +942,6 @@ server:
|
|||||||
# if 0(default) it is disabled, otherwise states qps allowed per ip address
|
# if 0(default) it is disabled, otherwise states qps allowed per ip address
|
||||||
# ip-ratelimit: 0
|
# ip-ratelimit: 0
|
||||||
|
|
||||||
# global query ratelimit for all ip addresses with a valid DNS Cookie.
|
|
||||||
# feature is experimental.
|
|
||||||
# if 0(default) it is disabled, otherwise states qps allowed per ip address
|
|
||||||
# useful in combination with 'allow_cookie'.
|
|
||||||
# If used, suggested to be higher than ip-ratelimit, tenfold.
|
|
||||||
# ip-ratelimit-cookie: 0
|
|
||||||
|
|
||||||
# ip ratelimits are tracked in a cache, size in bytes of cache (or k,m).
|
# ip ratelimits are tracked in a cache, size in bytes of cache (or k,m).
|
||||||
# ip-ratelimit-size: 4m
|
# ip-ratelimit-size: 4m
|
||||||
# ip ratelimit cache slabs, reduces lock contention if equal to cpucount.
|
# ip ratelimit cache slabs, reduces lock contention if equal to cpucount.
|
||||||
@@ -1110,19 +963,6 @@ server:
|
|||||||
# the number of servers that will be used in the fast server selection.
|
# the number of servers that will be used in the fast server selection.
|
||||||
# fast-server-num: 3
|
# fast-server-num: 3
|
||||||
|
|
||||||
# reply to requests containing DNS Cookies as specified in RFC 7873 and RFC 9018.
|
|
||||||
# answer-cookie: no
|
|
||||||
|
|
||||||
# secret for DNS Cookie generation.
|
|
||||||
# useful for anycast deployments.
|
|
||||||
# example value "000102030405060708090a0b0c0d0e0f".
|
|
||||||
# cookie-secret: <128 bit random hex string>
|
|
||||||
|
|
||||||
# File with cookie secrets, the 'cookie-secret:' option is ignored
|
|
||||||
# and the file can be managed to have staging and active secrets
|
|
||||||
# with remote control commands. Disabled with "". Default is "".
|
|
||||||
# cookie-secret-file: "/usr/local/etc/unbound_cookiesecrets.txt"
|
|
||||||
|
|
||||||
# Enable to attach Extended DNS Error codes (RFC8914) to responses.
|
# Enable to attach Extended DNS Error codes (RFC8914) to responses.
|
||||||
# ede: no
|
# ede: no
|
||||||
|
|
||||||
@@ -1131,11 +971,6 @@ server:
|
|||||||
# Note that the ede option above needs to be enabled for this to work.
|
# Note that the ede option above needs to be enabled for this to work.
|
||||||
# ede-serve-expired: no
|
# ede-serve-expired: no
|
||||||
|
|
||||||
# Enable DNS Error Reporting (RFC9567).
|
|
||||||
# qname-minimisation is advised to be turned on as well to increase
|
|
||||||
# privacy on the outgoing reports.
|
|
||||||
# dns-error-reporting: no
|
|
||||||
|
|
||||||
# Specific options for ipsecmod. Unbound needs to be configured with
|
# Specific options for ipsecmod. Unbound needs to be configured with
|
||||||
# --enable-ipsecmod for these to take effect.
|
# --enable-ipsecmod for these to take effect.
|
||||||
#
|
#
|
||||||
@@ -1171,8 +1006,6 @@ server:
|
|||||||
# Timeout in milliseconds for TCP queries to auth servers.
|
# Timeout in milliseconds for TCP queries to auth servers.
|
||||||
# tcp-auth-query-timeout: 3000
|
# tcp-auth-query-timeout: 3000
|
||||||
|
|
||||||
# Number of threads to use to load auth-zones (and RPZ). 0 disables.
|
|
||||||
# auth-task-threads: 0
|
|
||||||
|
|
||||||
# Python config section. To enable:
|
# Python config section. To enable:
|
||||||
# o use --with-pythonmodule to configure before compiling.
|
# o use --with-pythonmodule to configure before compiling.
|
||||||
@@ -1276,21 +1109,19 @@ remote-control:
|
|||||||
# sources of notifies.
|
# sources of notifies.
|
||||||
# auth-zone:
|
# auth-zone:
|
||||||
# name: "."
|
# name: "."
|
||||||
# primary: 170.247.170.2 # b.root-servers.net
|
# primary: 199.9.14.201 # b.root-servers.net
|
||||||
# primary: 192.33.4.12 # c.root-servers.net
|
# primary: 192.33.4.12 # c.root-servers.net
|
||||||
# primary: 199.7.91.13 # d.root-servers.net
|
# primary: 199.7.91.13 # d.root-servers.net
|
||||||
# primary: 192.5.5.241 # f.root-servers.net
|
# primary: 192.5.5.241 # f.root-servers.net
|
||||||
# primary: 192.112.36.4 # g.root-servers.net
|
# primary: 192.112.36.4 # g.root-servers.net
|
||||||
# primary: 198.97.190.53 # h.root-servers.net
|
|
||||||
# primary: 193.0.14.129 # k.root-servers.net
|
# primary: 193.0.14.129 # k.root-servers.net
|
||||||
# primary: 192.0.47.132 # xfr.cjr.dns.icann.org
|
# primary: 192.0.47.132 # xfr.cjr.dns.icann.org
|
||||||
# primary: 192.0.32.132 # xfr.lax.dns.icann.org
|
# primary: 192.0.32.132 # xfr.lax.dns.icann.org
|
||||||
# primary: 2801:1b8:10::b # b.root-servers.net
|
# primary: 2001:500:200::b # b.root-servers.net
|
||||||
# primary: 2001:500:2::c # c.root-servers.net
|
# primary: 2001:500:2::c # c.root-servers.net
|
||||||
# primary: 2001:500:2d::d # d.root-servers.net
|
# primary: 2001:500:2d::d # d.root-servers.net
|
||||||
# primary: 2001:500:2f::f # f.root-servers.net
|
# primary: 2001:500:2f::f # f.root-servers.net
|
||||||
# primary: 2001:500:12::d0d # g.root-servers.net
|
# primary: 2001:500:12::d0d # g.root-servers.net
|
||||||
# primary: 2001:500:1::53 # h.root-servers.net
|
|
||||||
# primary: 2001:7fd::1 # k.root-servers.net
|
# primary: 2001:7fd::1 # k.root-servers.net
|
||||||
# primary: 2620:0:2830:202::132 # xfr.cjr.dns.icann.org
|
# primary: 2620:0:2830:202::132 # xfr.cjr.dns.icann.org
|
||||||
# primary: 2620:0:2d0:202::132 # xfr.lax.dns.icann.org
|
# primary: 2620:0:2d0:202::132 # xfr.lax.dns.icann.org
|
||||||
@@ -1304,16 +1135,12 @@ remote-control:
|
|||||||
# zonemd-check: no
|
# zonemd-check: no
|
||||||
# zonemd-reject-absence: no
|
# zonemd-reject-absence: no
|
||||||
# zonefile: "example.org.zone"
|
# zonefile: "example.org.zone"
|
||||||
# max-transfer-size: 0
|
|
||||||
# max-transfer-time: 0
|
|
||||||
|
|
||||||
|
|
||||||
# Views
|
# Views
|
||||||
# Create named views. Name must be unique.
|
# Create named views. Name must be unique. Map views to requests using
|
||||||
# Map views to requests using the access-control-view/interface-view options.
|
# the access-control-view option. Views can contain zero or more local-zone
|
||||||
# Views can contain zero or more local-zone and local-data options.
|
# and local-data options. Options from matching views will override global
|
||||||
# Options from matching views will override global options.
|
# options. Global options will be used if no matching view is found.
|
||||||
# Global options will be used if no matching view is found.
|
|
||||||
# With view-first yes, it will try to answer using the global local-zone and
|
# With view-first yes, it will try to answer using the global local-zone and
|
||||||
# local-data elements if there is no view specific match.
|
# local-data elements if there is no view specific match.
|
||||||
# view:
|
# view:
|
||||||
@@ -1321,8 +1148,6 @@ remote-control:
|
|||||||
# local-zone: "example.com" redirect
|
# local-zone: "example.com" redirect
|
||||||
# local-data: "example.com A 192.0.2.3"
|
# local-data: "example.com A 192.0.2.3"
|
||||||
# local-data-ptr: "192.0.2.3 www.example.com"
|
# local-data-ptr: "192.0.2.3 www.example.com"
|
||||||
# response-ip: 192.0.2.0/24 redirect
|
|
||||||
# response-ip-data: 192.0.2.0/24 "example. A 192.0.2.1"
|
|
||||||
# view-first: no
|
# view-first: no
|
||||||
# view:
|
# view:
|
||||||
# name: "anotherview"
|
# name: "anotherview"
|
||||||
@@ -1360,11 +1185,6 @@ remote-control:
|
|||||||
# backend: "testframe"
|
# backend: "testframe"
|
||||||
# # secret seed string to calculate hashed keys
|
# # secret seed string to calculate hashed keys
|
||||||
# secret-seed: "default"
|
# secret-seed: "default"
|
||||||
# # if the backend should be read from, but not written to.
|
|
||||||
# cachedb-no-store: no
|
|
||||||
# # if the cachedb should be checked before a serve-expired response is
|
|
||||||
# # given, when serve-expired is enabled.
|
|
||||||
# cachedb-check-when-serve-expired: yes
|
|
||||||
#
|
#
|
||||||
# # For "redis" backend:
|
# # For "redis" backend:
|
||||||
# # (to enable, use --with-libhiredis to configure before compiling)
|
# # (to enable, use --with-libhiredis to configure before compiling)
|
||||||
@@ -1372,36 +1192,10 @@ remote-control:
|
|||||||
# redis-server-host: 127.0.0.1
|
# redis-server-host: 127.0.0.1
|
||||||
# # redis server's TCP port
|
# # redis server's TCP port
|
||||||
# redis-server-port: 6379
|
# redis-server-port: 6379
|
||||||
# # if the server uses a unix socket, set its path, or "" when not used.
|
|
||||||
# redis-server-path: "/var/lib/redis/redis-server.sock"
|
|
||||||
# # if the server uses an AUTH password, specify here, or "" when not used.
|
|
||||||
# redis-server-password: ""
|
|
||||||
# # timeout (in ms) for communication with the redis server
|
# # timeout (in ms) for communication with the redis server
|
||||||
# redis-timeout: 100
|
# redis-timeout: 100
|
||||||
# # timeout (in ms) for commands, if 0, uses redis-timeout.
|
|
||||||
# redis-command-timeout: 0
|
|
||||||
# # timeout (in ms) for connection set up, if 0, uses redis-timeout.
|
|
||||||
# redis-connect-timeout: 0
|
|
||||||
# # set timeout on redis records based on DNS response TTL
|
# # set timeout on redis records based on DNS response TTL
|
||||||
# redis-expire-records: no
|
# redis-expire-records: no
|
||||||
# # redis logical database to use, 0 is the default database.
|
|
||||||
# redis-logical-db: 0
|
|
||||||
# # redis replica server's IP address or host name
|
|
||||||
# redis-replica-server-host: 127.0.0.1
|
|
||||||
# # redis replica server's TCP port
|
|
||||||
# redis-replica-server-port: 6379
|
|
||||||
# # if the replica server uses a unix socket, set its path, or "" when not used.
|
|
||||||
# redis-replica-server-path: "/var/lib/redis/redis-server.sock"
|
|
||||||
# # if the replica server uses an AUTH password, specify here, or "" when not used.
|
|
||||||
# redis-replica-server-password: ""
|
|
||||||
# # timeout (in ms) for communication with the redis replica server
|
|
||||||
# redis-replica-timeout: 100
|
|
||||||
# # timeout (in ms) for redis replica commands, if 0, uses redis-replica-timeout.
|
|
||||||
# redis-replica-command-timeout: 0
|
|
||||||
# # timeout (in ms) for redis replica connection set up, if 0, uses redis-replica-timeout.
|
|
||||||
# redis-replica-connect-timeout: 0
|
|
||||||
# # redis logical database to use for the replica server, 0 is the default database.
|
|
||||||
# redis-replica-logical-db: 0
|
|
||||||
|
|
||||||
# IPSet
|
# IPSet
|
||||||
# Add specify domain into set via ipset.
|
# Add specify domain into set via ipset.
|
||||||
@@ -1443,8 +1237,6 @@ remote-control:
|
|||||||
# dnstap-identity: ""
|
# dnstap-identity: ""
|
||||||
# # if "" it uses the package version.
|
# # if "" it uses the package version.
|
||||||
# dnstap-version: ""
|
# dnstap-version: ""
|
||||||
# # log only 1/N messages, if 0 it is disabled. default 0.
|
|
||||||
# dnstap-sample-rate: 0
|
|
||||||
# dnstap-log-resolver-query-messages: no
|
# dnstap-log-resolver-query-messages: no
|
||||||
# dnstap-log-resolver-response-messages: no
|
# dnstap-log-resolver-response-messages: no
|
||||||
# dnstap-log-client-query-messages: no
|
# dnstap-log-client-query-messages: no
|
||||||
@@ -1453,8 +1245,7 @@ remote-control:
|
|||||||
# dnstap-log-forwarder-response-messages: no
|
# dnstap-log-forwarder-response-messages: no
|
||||||
|
|
||||||
# Response Policy Zones
|
# Response Policy Zones
|
||||||
# RPZ policies. Applied in order of configuration. Any match from an earlier
|
# RPZ policies. Applied in order of configuration. QNAME, Response IP
|
||||||
# RPZ zone will terminate the RPZ lookup. QNAME, Response IP
|
|
||||||
# Address, nsdname, nsip and clientip triggers are supported. Supported
|
# Address, nsdname, nsip and clientip triggers are supported. Supported
|
||||||
# actions are: NXDOMAIN, NODATA, PASSTHRU, DROP, Local Data, tcp-only
|
# actions are: NXDOMAIN, NODATA, PASSTHRU, DROP, Local Data, tcp-only
|
||||||
# and drop. Policies can be loaded from a file, or using zone
|
# and drop. Policies can be loaded from a file, or using zone
|
||||||
@@ -1473,5 +1264,3 @@ remote-control:
|
|||||||
# rpz-signal-nxdomain-ra: no
|
# rpz-signal-nxdomain-ra: no
|
||||||
# for-downstream: no
|
# for-downstream: no
|
||||||
# tags: "example"
|
# tags: "example"
|
||||||
# max-transfer-size: 0
|
|
||||||
# max-transfer-time: 0
|
|
||||||
|
|||||||
+340
-329
@@ -1,306 +1,335 @@
|
|||||||
.\" Man page generated from reStructuredText.
|
.TH "libunbound" "3" "@date@" "NLnet Labs" "unbound @version@"
|
||||||
.
|
.\"
|
||||||
.
|
.\" libunbound.3 -- unbound library functions manual
|
||||||
.nr rst2man-indent-level 0
|
.\"
|
||||||
.
|
.\" Copyright (c) 2007, NLnet Labs. All rights reserved.
|
||||||
.de1 rstReportMargin
|
.\"
|
||||||
\\$1 \\n[an-margin]
|
.\" See LICENSE for the license.
|
||||||
level \\n[rst2man-indent-level]
|
.\"
|
||||||
level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
.\"
|
||||||
-
|
.SH "NAME"
|
||||||
\\n[rst2man-indent0]
|
.B libunbound,
|
||||||
\\n[rst2man-indent1]
|
.B unbound.h,
|
||||||
\\n[rst2man-indent2]
|
.B ub_ctx,
|
||||||
..
|
.B ub_result,
|
||||||
.de1 INDENT
|
.B ub_callback_type,
|
||||||
.\" .rstReportMargin pre:
|
.B ub_ctx_create,
|
||||||
. RS \\$1
|
.B ub_ctx_delete,
|
||||||
. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
|
.B ub_ctx_set_option,
|
||||||
. nr rst2man-indent-level +1
|
.B ub_ctx_get_option,
|
||||||
.\" .rstReportMargin post:
|
.B ub_ctx_config,
|
||||||
..
|
.B ub_ctx_set_fwd,
|
||||||
.de UNINDENT
|
.B ub_ctx_set_stub,
|
||||||
. RE
|
.B ub_ctx_set_tls,
|
||||||
.\" indent \\n[an-margin]
|
.B ub_ctx_resolvconf,
|
||||||
.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
.B ub_ctx_hosts,
|
||||||
.nr rst2man-indent-level -1
|
.B ub_ctx_add_ta,
|
||||||
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
.B ub_ctx_add_ta_autr,
|
||||||
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
|
.B ub_ctx_add_ta_file,
|
||||||
..
|
.B ub_ctx_trustedkeys,
|
||||||
.TH "LIBUNBOUND" "3" "@date@" "@version@" "Unbound"
|
.B ub_ctx_debugout,
|
||||||
.SH NAME
|
.B ub_ctx_debuglevel,
|
||||||
libunbound \- Unbound DNS validating resolver @version@ functions.
|
.B ub_ctx_async,
|
||||||
.SH SYNOPSIS
|
.B ub_poll,
|
||||||
.sp
|
.B ub_wait,
|
||||||
\fB#include <unbound.h>\fP
|
.B ub_fd,
|
||||||
.sp
|
.B ub_process,
|
||||||
struct ub_ctx * \fBub_ctx_create\fP(void);
|
.B ub_resolve,
|
||||||
.sp
|
.B ub_resolve_async,
|
||||||
void \fBub_ctx_delete\fP(struct ub_ctx* ctx);
|
.B ub_cancel,
|
||||||
.sp
|
.B ub_resolve_free,
|
||||||
int \fBub_ctx_set_option\fP(struct ub_ctx* ctx, char* opt, char* val);
|
.B ub_strerror,
|
||||||
.sp
|
.B ub_ctx_print_local_zones,
|
||||||
int \fBub_ctx_get_option\fP(struct ub_ctx* ctx, char* opt, char** val);
|
.B ub_ctx_zone_add,
|
||||||
.sp
|
.B ub_ctx_zone_remove,
|
||||||
int \fBub_ctx_config\fP(struct ub_ctx* ctx, char* fname);
|
.B ub_ctx_data_add,
|
||||||
.sp
|
.B ub_ctx_data_remove
|
||||||
int \fBub_ctx_set_fwd\fP(struct ub_ctx* ctx, char* addr);
|
\- Unbound DNS validating resolver @version@ functions.
|
||||||
.INDENT 0.0
|
.SH "SYNOPSIS"
|
||||||
.TP
|
.B #include <unbound.h>
|
||||||
int \fBub_ctx_set_stub\fP(struct ub_ctx* ctx, char* zone, char* addr,
|
.LP
|
||||||
int isprime);
|
\fIstruct ub_ctx *\fR
|
||||||
.UNINDENT
|
\fBub_ctx_create\fR(\fIvoid\fR);
|
||||||
.sp
|
.LP
|
||||||
int \fBub_ctx_set_tls\fP(struct ub_ctx* ctx, int tls);
|
\fIvoid\fR
|
||||||
.sp
|
\fBub_ctx_delete\fR(\fIstruct ub_ctx*\fR ctx);
|
||||||
int \fBub_ctx_resolvconf\fP(struct ub_ctx* ctx, char* fname);
|
.LP
|
||||||
.sp
|
\fIint\fR
|
||||||
int \fBub_ctx_hosts\fP(struct ub_ctx* ctx, char* fname);
|
\fBub_ctx_set_option\fR(\fIstruct ub_ctx*\fR ctx, \fIchar*\fR opt, \fIchar*\fR val);
|
||||||
.sp
|
.LP
|
||||||
int \fBub_ctx_add_ta\fP(struct ub_ctx* ctx, char* ta);
|
\fIint\fR
|
||||||
.sp
|
\fBub_ctx_get_option\fR(\fIstruct ub_ctx*\fR ctx, \fIchar*\fR opt, \fIchar**\fR val);
|
||||||
int \fBub_ctx_add_ta_autr\fP(struct ub_ctx* ctx, char* fname);
|
.LP
|
||||||
.sp
|
\fIint\fR
|
||||||
int \fBub_ctx_add_ta_file\fP(struct ub_ctx* ctx, char* fname);
|
\fBub_ctx_config\fR(\fIstruct ub_ctx*\fR ctx, \fIchar*\fR fname);
|
||||||
.sp
|
.LP
|
||||||
int \fBub_ctx_trustedkeys\fP(struct ub_ctx* ctx, char* fname);
|
\fIint\fR
|
||||||
.sp
|
\fBub_ctx_set_fwd\fR(\fIstruct ub_ctx*\fR ctx, \fIchar*\fR addr);
|
||||||
int \fBub_ctx_debugout\fP(struct ub_ctx* ctx, FILE* out);
|
.LP
|
||||||
.sp
|
\fIint\fR
|
||||||
int \fBub_ctx_debuglevel\fP(struct ub_ctx* ctx, int d);
|
\fBub_ctx_set_stub\fR(\fIstruct ub_ctx*\fR ctx, \fIchar*\fR zone,
|
||||||
.sp
|
\fIchar*\fR addr,
|
||||||
int \fBub_ctx_async\fP(struct ub_ctx* ctx, int dothread);
|
.br
|
||||||
.sp
|
\fIint\fR isprime);
|
||||||
int \fBub_poll\fP(struct ub_ctx* ctx);
|
.LP
|
||||||
.sp
|
\fIint\fR
|
||||||
int \fBub_wait\fP(struct ub_ctx* ctx);
|
\fBub_ctx_set_tls\fR(\fIstruct ub_ctx*\fR ctx, \fIint\fR tls);
|
||||||
.sp
|
.LP
|
||||||
int \fBub_fd\fP(struct ub_ctx* ctx);
|
\fIint\fR
|
||||||
.sp
|
\fBub_ctx_resolvconf\fR(\fIstruct ub_ctx*\fR ctx, \fIchar*\fR fname);
|
||||||
int \fBub_process\fP(struct ub_ctx* ctx);
|
.LP
|
||||||
.INDENT 0.0
|
\fIint\fR
|
||||||
.TP
|
\fBub_ctx_hosts\fR(\fIstruct ub_ctx*\fR ctx, \fIchar*\fR fname);
|
||||||
int \fBub_resolve\fP(struct ub_ctx* ctx, char* name,
|
.LP
|
||||||
int rrtype, int rrclass, struct ub_result** result);
|
\fIint\fR
|
||||||
.TP
|
\fBub_ctx_add_ta\fR(\fIstruct ub_ctx*\fR ctx, \fIchar*\fR ta);
|
||||||
int \fBub_resolve_async\fP(struct ub_ctx* ctx, char* name,
|
.LP
|
||||||
int rrtype, int rrclass, void* mydata,
|
\fIint\fR
|
||||||
ub_callback_type* callback, int* async_id);
|
\fBub_ctx_add_ta_autr\fR(\fIstruct ub_ctx*\fR ctx, \fIchar*\fR fname);
|
||||||
.UNINDENT
|
.LP
|
||||||
.sp
|
\fIint\fR
|
||||||
int \fBub_cancel\fP(struct ub_ctx* ctx, int async_id);
|
\fBub_ctx_add_ta_file\fR(\fIstruct ub_ctx*\fR ctx, \fIchar*\fR fname);
|
||||||
.sp
|
.LP
|
||||||
void \fBub_resolve_free\fP(struct ub_result* result);
|
\fIint\fR
|
||||||
.sp
|
\fBub_ctx_trustedkeys\fR(\fIstruct ub_ctx*\fR ctx, \fIchar*\fR fname);
|
||||||
const char * \fBub_strerror\fP(int err);
|
.LP
|
||||||
.sp
|
\fIint\fR
|
||||||
int \fBub_ctx_print_local_zones\fP(struct ub_ctx* ctx);
|
\fBub_ctx_debugout\fR(\fIstruct ub_ctx*\fR ctx, \fIFILE*\fR out);
|
||||||
.sp
|
.LP
|
||||||
int \fBub_ctx_zone_add\fP(struct ub_ctx* ctx, char* zone_name, char* zone_type);
|
\fIint\fR
|
||||||
.sp
|
\fBub_ctx_debuglevel\fR(\fIstruct ub_ctx*\fR ctx, \fIint\fR d);
|
||||||
int \fBub_ctx_zone_remove\fP(struct ub_ctx* ctx, char* zone_name);
|
.LP
|
||||||
.sp
|
\fIint\fR
|
||||||
int \fBub_ctx_data_add\fP(struct ub_ctx* ctx, char* data);
|
\fBub_ctx_async\fR(\fIstruct ub_ctx*\fR ctx, \fIint\fR dothread);
|
||||||
.sp
|
.LP
|
||||||
int \fBub_ctx_data_remove\fP(struct ub_ctx* ctx, char* data);
|
\fIint\fR
|
||||||
.SH DESCRIPTION
|
\fBub_poll\fR(\fIstruct ub_ctx*\fR ctx);
|
||||||
.sp
|
.LP
|
||||||
Unbound is an implementation of a DNS resolver, that does caching and DNSSEC
|
\fIint\fR
|
||||||
validation.
|
\fBub_wait\fR(\fIstruct ub_ctx*\fR ctx);
|
||||||
This is the library API, for using the \fB\-lunbound\fP library.
|
.LP
|
||||||
The server daemon is described in \fI\%unbound(8)\fP\&.
|
\fIint\fR
|
||||||
The library works independent from a running unbound server, and can be used to
|
\fBub_fd\fR(\fIstruct ub_ctx*\fR ctx);
|
||||||
convert hostnames to ip addresses, and back, and obtain other information from
|
.LP
|
||||||
the DNS.
|
\fIint\fR
|
||||||
The library performs public\-key validation of results with DNSSEC.
|
\fBub_process\fR(\fIstruct ub_ctx*\fR ctx);
|
||||||
.sp
|
.LP
|
||||||
The library uses a variable of type \fIstruct ub_ctx\fP to keep context between
|
\fIint\fR
|
||||||
calls.
|
\fBub_resolve\fR(\fIstruct ub_ctx*\fR ctx, \fIchar*\fR name,
|
||||||
The user must maintain it, creating it with \fBub_ctx_create\fP and deleting it
|
.br
|
||||||
with \fBub_ctx_delete\fP\&.
|
\fIint\fR rrtype, \fIint\fR rrclass, \fIstruct ub_result**\fR result);
|
||||||
It can be created and deleted at any time.
|
.LP
|
||||||
Creating it anew removes any previous configuration (such as trusted keys) and
|
\fIint\fR
|
||||||
clears any cached results.
|
\fBub_resolve_async\fR(\fIstruct ub_ctx*\fR ctx, \fIchar*\fR name,
|
||||||
.sp
|
.br
|
||||||
The functions are thread\-safe, and a context can be used in a threaded (as well
|
\fIint\fR rrtype, \fIint\fR rrclass, \fIvoid*\fR mydata,
|
||||||
as in a non\-threaded) environment.
|
.br
|
||||||
Also resolution (and validation) can be performed blocking and non\-blocking
|
\fIub_callback_type\fR callback, \fIint*\fR async_id);
|
||||||
(also called asynchronous).
|
.LP
|
||||||
The async method returns from the call immediately, so that processing can go
|
\fIint\fR
|
||||||
on, while the results become available later.
|
\fBub_cancel\fR(\fIstruct ub_ctx*\fR ctx, \fIint\fR async_id);
|
||||||
.sp
|
.LP
|
||||||
|
\fIvoid\fR
|
||||||
|
\fBub_resolve_free\fR(\fIstruct ub_result*\fR result);
|
||||||
|
.LP
|
||||||
|
\fIconst char *\fR
|
||||||
|
\fBub_strerror\fR(\fIint\fR err);
|
||||||
|
.LP
|
||||||
|
\fIint\fR
|
||||||
|
\fBub_ctx_print_local_zones\fR(\fIstruct ub_ctx*\fR ctx);
|
||||||
|
.LP
|
||||||
|
\fIint\fR
|
||||||
|
\fBub_ctx_zone_add\fR(\fIstruct ub_ctx*\fR ctx, \fIchar*\fR zone_name, \fIchar*\fR zone_type);
|
||||||
|
.LP
|
||||||
|
\fIint\fR
|
||||||
|
\fBub_ctx_zone_remove\fR(\fIstruct ub_ctx*\fR ctx, \fIchar*\fR zone_name);
|
||||||
|
.LP
|
||||||
|
\fIint\fR
|
||||||
|
\fBub_ctx_data_add\fR(\fIstruct ub_ctx*\fR ctx, \fIchar*\fR data);
|
||||||
|
.LP
|
||||||
|
\fIint\fR
|
||||||
|
\fBub_ctx_data_remove\fR(\fIstruct ub_ctx*\fR ctx, \fIchar*\fR data);
|
||||||
|
.SH "DESCRIPTION"
|
||||||
|
.B Unbound
|
||||||
|
is an implementation of a DNS resolver, that does caching and
|
||||||
|
DNSSEC validation. This is the library API, for using the \-lunbound library.
|
||||||
|
The server daemon is described in \fIunbound\fR(8).
|
||||||
|
The library works independent from a running unbound server, and
|
||||||
|
can be used to convert hostnames to ip addresses, and back,
|
||||||
|
and obtain other information from the DNS. The library performs public\-key
|
||||||
|
validation of results with DNSSEC.
|
||||||
|
.P
|
||||||
|
The library uses a variable of type \fIstruct ub_ctx\fR to keep context
|
||||||
|
between calls. The user must maintain it, creating it with
|
||||||
|
.B ub_ctx_create
|
||||||
|
and deleting it with
|
||||||
|
.B ub_ctx_delete\fR.
|
||||||
|
It can be created and deleted at any time. Creating it anew removes any
|
||||||
|
previous configuration (such as trusted keys) and clears any cached results.
|
||||||
|
.P
|
||||||
|
The functions are thread\-safe, and a context can be used in a threaded (as
|
||||||
|
well as in a non\-threaded) environment. Also resolution (and validation)
|
||||||
|
can be performed blocking and non\-blocking (also called asynchronous).
|
||||||
|
The async method returns from the call immediately, so that processing
|
||||||
|
can go on, while the results become available later.
|
||||||
|
.P
|
||||||
The functions are discussed in turn below.
|
The functions are discussed in turn below.
|
||||||
.SH FUNCTIONS
|
.SH "FUNCTIONS"
|
||||||
.INDENT 0.0
|
|
||||||
.TP
|
.TP
|
||||||
.B ub_ctx_create
|
.B ub_ctx_create
|
||||||
Create a new context, initialised with defaults.
|
Create a new context, initialised with defaults.
|
||||||
The information from \fB/etc/resolv.conf\fP and \fB/etc/hosts\fP is
|
The information from /etc/resolv.conf and /etc/hosts is not utilised
|
||||||
not utilised by default.
|
by default. Use
|
||||||
Use \fBub_ctx_resolvconf\fP and \fBub_ctx_hosts\fP to read them.
|
.B ub_ctx_resolvconf
|
||||||
Before you call this, use the openssl functions
|
and
|
||||||
\fBCRYPTO_set_id_callback\fP and \fBCRYPTO_set_locking_callback\fP to set
|
.B ub_ctx_hosts
|
||||||
up asynchronous operation if you use lib openssl (the application calls
|
to read them.
|
||||||
these functions once for initialisation).
|
Before you call this, use the openssl functions CRYPTO_set_id_callback and
|
||||||
Openssl 1.0.0 or later uses the \fBCRYPTO_THREADID_set_callback\fP
|
CRYPTO_set_locking_callback to set up asynchronous operation if you use
|
||||||
function.
|
lib openssl (the application calls these functions once for initialisation).
|
||||||
|
Openssl 1.0.0 or later uses the CRYPTO_THREADID_set_callback function.
|
||||||
.TP
|
.TP
|
||||||
.B ub_ctx_delete
|
.B ub_ctx_delete
|
||||||
Delete validation context and free associated resources.
|
Delete validation context and free associated resources.
|
||||||
Outstanding async queries are killed and callbacks are not called for
|
Outstanding async queries are killed and callbacks are not called for them.
|
||||||
them.
|
|
||||||
.TP
|
.TP
|
||||||
.B ub_ctx_set_option
|
.B ub_ctx_set_option
|
||||||
A power\-user interface that lets you specify one of the options from
|
A power\-user interface that lets you specify one of the options from the
|
||||||
the config file format, see \fI\%unbound.conf(5)\fP\&.
|
config file format, see \fIunbound.conf\fR(5). Not all options are
|
||||||
Not all options are relevant.
|
relevant. For some specific options, such as adding trust anchors, special
|
||||||
For some specific options, such as adding trust anchors, special
|
routines exist. Pass the option name with the trailing ':'.
|
||||||
routines exist.
|
|
||||||
Pass the option name with the trailing \fB\(aq:\(aq\fP\&.
|
|
||||||
.TP
|
.TP
|
||||||
.B ub_ctx_get_option
|
.B ub_ctx_get_option
|
||||||
A power\-user interface that gets an option value.
|
A power\-user interface that gets an option value. Some options cannot be
|
||||||
Some options cannot be gotten, and others return a newline separated
|
gotten, and others return a newline separated list. Pass the option name
|
||||||
list.
|
without trailing ':'. The returned value must be free(2)d by the caller.
|
||||||
Pass the option name without trailing \fB\(aq:\(aq\fP\&.
|
|
||||||
The returned value must be free(2)d by the caller.
|
|
||||||
.TP
|
.TP
|
||||||
.B ub_ctx_config
|
.B ub_ctx_config
|
||||||
A power\-user interface that lets you specify an unbound config file,
|
A power\-user interface that lets you specify an unbound config file, see
|
||||||
see \fI\%unbound.conf(5)\fP, which is read for
|
\fIunbound.conf\fR(5), which is read for configuration. Not all options are
|
||||||
configuration.
|
relevant. For some specific options, such as adding trust anchors, special
|
||||||
Not all options are relevant.
|
routines exist. This function is thread\-safe only if a single instance of
|
||||||
For some specific options, such as adding trust anchors, special
|
ub_ctx* exists in the application. If several instances exist the
|
||||||
routines exist.
|
application has to ensure that ub_ctx_config is not called in parallel by
|
||||||
This function is thread\-safe only if a single instance of \fBub_ctx\fP*
|
the different instances.
|
||||||
exists in the application.
|
|
||||||
If several instances exist the application has to ensure that
|
|
||||||
\fBub_ctx_config\fP is not called in parallel by the different instances.
|
|
||||||
.TP
|
.TP
|
||||||
.B ub_ctx_set_fwd
|
.B ub_ctx_set_fwd
|
||||||
Set machine to forward DNS queries to, the caching resolver to use.
|
Set machine to forward DNS queries to, the caching resolver to use.
|
||||||
IP4 or IP6 address.
|
IP4 or IP6 address. Forwards all DNS requests to that machine, which
|
||||||
Forwards all DNS requests to that machine, which is expected to run a
|
is expected to run a recursive resolver. If the proxy is not
|
||||||
recursive resolver.
|
DNSSEC capable, validation may fail. Can be called several times, in
|
||||||
If the proxy is not DNSSEC capable, validation may fail.
|
that case the addresses are used as backup servers.
|
||||||
Can be called several times, in that case the addresses are used as
|
At this time it is only possible to set configuration before the
|
||||||
backup servers.
|
first resolve is done.
|
||||||
At this time it is only possible to set configuration before the first
|
|
||||||
resolve is done.
|
|
||||||
.TP
|
.TP
|
||||||
.B ub_ctx_set_stub
|
.B ub_ctx_set_stub
|
||||||
Set a stub zone, authoritative dns servers to use for a particular
|
Set a stub zone, authoritative dns servers to use for a particular zone.
|
||||||
zone.
|
IP4 or IP6 address. If the address is NULL the stub entry is removed.
|
||||||
IP4 or IP6 address.
|
Set isprime true if you configure root hints with it. Otherwise similar to
|
||||||
If the address is NULL the stub entry is removed.
|
the stub zone item from unbound's config file. Can be called several times,
|
||||||
Set isprime true if you configure root hints with it.
|
for different zones, or to add multiple addresses for a particular zone.
|
||||||
Otherwise similar to the stub zone item from unbound\(aqs config file.
|
At this time it is only possible to set configuration before the
|
||||||
Can be called several times, for different zones, or to add multiple
|
first resolve is done.
|
||||||
addresses for a particular zone.
|
|
||||||
At this time it is only possible to set configuration before the first
|
|
||||||
resolve is done.
|
|
||||||
.TP
|
.TP
|
||||||
.B ub_ctx_set_tls
|
.B ub_ctx_set_tls
|
||||||
Enable DNS over TLS (DoT) for machines set with \fBub_ctx_set_fwd\fP\&.
|
Enable DNS over TLS (DoT) for machines set with
|
||||||
At this time it is only possible to set configuration before the first
|
.B ub_ctx_set_fwd.
|
||||||
resolve is done.
|
At this time it is only possible to set configuration before the
|
||||||
|
first resolve is done.
|
||||||
.TP
|
.TP
|
||||||
.B ub_ctx_resolvconf
|
.B ub_ctx_resolvconf
|
||||||
By default the root servers are queried and full resolver mode is used,
|
By default the root servers are queried and full resolver mode is used, but
|
||||||
but you can use this call to read the list of nameservers to use from
|
you can use this call to read the list of nameservers to use from the
|
||||||
the filename given.
|
filename given.
|
||||||
Usually \fB\(dq/etc/resolv.conf\(dq\fP\&.
|
Usually "/etc/resolv.conf". Uses those nameservers as caching proxies.
|
||||||
Uses those nameservers as caching proxies.
|
|
||||||
If they do not support DNSSEC, validation may fail.
|
If they do not support DNSSEC, validation may fail.
|
||||||
Only nameservers are picked up, the searchdomain, ndots and other
|
Only nameservers are picked up, the searchdomain, ndots and other
|
||||||
settings from \fIresolv.conf(5)\fP are ignored.
|
settings from \fIresolv.conf\fR(5) are ignored.
|
||||||
If fname NULL is passed, \fB\(dq/etc/resolv.conf\(dq\fP is used (if on
|
If fname NULL is passed, "/etc/resolv.conf" is used (if on Windows,
|
||||||
Windows, the system\-wide configured nameserver is picked instead).
|
the system\-wide configured nameserver is picked instead).
|
||||||
At this time it is only possible to set configuration before the first
|
At this time it is only possible to set configuration before the
|
||||||
resolve is done.
|
first resolve is done.
|
||||||
.TP
|
.TP
|
||||||
.B ub_ctx_hosts
|
.B ub_ctx_hosts
|
||||||
Read list of hosts from the filename given.
|
Read list of hosts from the filename given.
|
||||||
Usually \fB\(dq/etc/hosts\(dq\fP\&.
|
Usually "/etc/hosts". When queried for, these addresses are not marked
|
||||||
When queried for, these addresses are not marked DNSSEC secure.
|
DNSSEC secure. If fname NULL is passed, "/etc/hosts" is used
|
||||||
If fname NULL is passed, \fB\(dq/etc/hosts\(dq\fP is used (if on Windows,
|
(if on Windows, etc/hosts from WINDIR is picked instead).
|
||||||
\fBetc/hosts\fP from WINDIR is picked instead).
|
At this time it is only possible to set configuration before the
|
||||||
At this time it is only possible to set configuration before the first
|
first resolve is done.
|
||||||
resolve is done.
|
|
||||||
.TP
|
.TP
|
||||||
.B ub_ctx_add_ta
|
.B
|
||||||
|
ub_ctx_add_ta
|
||||||
Add a trust anchor to the given context.
|
Add a trust anchor to the given context.
|
||||||
At this time it is only possible to add trusted keys before the first
|
At this time it is only possible to add trusted keys before the
|
||||||
resolve is done.
|
first resolve is done.
|
||||||
The format is a string, similar to the zone\-file format,
|
The format is a string, similar to the zone\-file format,
|
||||||
\fB[domainname]\fP \fB[type]\fP \fB[rdata contents]\fP\&.
|
[domainname] [type] [rdata contents]. Both DS and DNSKEY records are accepted.
|
||||||
Both DS and DNSKEY records are accepted.
|
|
||||||
.TP
|
.TP
|
||||||
.B ub_ctx_add_ta_autr
|
.B ub_ctx_add_ta_autr
|
||||||
Add filename with automatically tracked trust anchor to the given
|
Add filename with automatically tracked trust anchor to the given context.
|
||||||
context.
|
Pass name of a file with the managed trust anchor. You can create this
|
||||||
Pass name of a file with the managed trust anchor.
|
file with \fIunbound\-anchor\fR(8) for the root anchor. You can also
|
||||||
You can create this file with
|
create it with an initial file with one line with a DNSKEY or DS record.
|
||||||
\fI\%unbound\-anchor(8)\fP for the root anchor.
|
|
||||||
You can also create it with an initial file with one line with a DNSKEY
|
|
||||||
or DS record.
|
|
||||||
If the file is writable, it is updated when the trust anchor changes.
|
If the file is writable, it is updated when the trust anchor changes.
|
||||||
At this time it is only possible to add trusted keys before the first
|
At this time it is only possible to add trusted keys before the
|
||||||
resolve is done.
|
first resolve is done.
|
||||||
.TP
|
.TP
|
||||||
.B ub_ctx_add_ta_file
|
.B ub_ctx_add_ta_file
|
||||||
Add trust anchors to the given context.
|
Add trust anchors to the given context.
|
||||||
Pass name of a file with DS and DNSKEY records in zone file format.
|
Pass name of a file with DS and DNSKEY records in zone file format.
|
||||||
At this time it is only possible to add trusted keys before the first
|
At this time it is only possible to add trusted keys before the
|
||||||
resolve is done.
|
first resolve is done.
|
||||||
.TP
|
.TP
|
||||||
.B ub_ctx_trustedkeys
|
.B ub_ctx_trustedkeys
|
||||||
Add trust anchors to the given context.
|
Add trust anchors to the given context.
|
||||||
Pass the name of a bind\-style config file with \fBtrusted\-keys{}\fP\&.
|
Pass the name of a bind\-style config file with trusted\-keys{}.
|
||||||
At this time it is only possible to add trusted keys before the first
|
At this time it is only possible to add trusted keys before the
|
||||||
resolve is done.
|
first resolve is done.
|
||||||
.TP
|
.TP
|
||||||
.B ub_ctx_debugout
|
.B ub_ctx_debugout
|
||||||
Set debug and error log output to the given stream.
|
Set debug and error log output to the given stream. Pass NULL to disable
|
||||||
Pass NULL to disable output.
|
output. Default is stderr. File\-names or using syslog can be enabled
|
||||||
Default is stderr.
|
using config options, this routine is for using your own stream.
|
||||||
File\-names or using syslog can be enabled using config options, this
|
|
||||||
routine is for using your own stream.
|
|
||||||
.TP
|
.TP
|
||||||
.B ub_ctx_debuglevel
|
.B ub_ctx_debuglevel
|
||||||
Set debug verbosity for the context.
|
Set debug verbosity for the context. Output is directed to stderr.
|
||||||
Output is directed to stderr.
|
|
||||||
Higher debug level gives more output.
|
Higher debug level gives more output.
|
||||||
.TP
|
.TP
|
||||||
.B ub_ctx_async
|
.B ub_ctx_async
|
||||||
Set a context behaviour for asynchronous action.
|
Set a context behaviour for asynchronous action.
|
||||||
if set to true, enables threading and a call to \fBub_resolve_async\fP
|
if set to true, enables threading and a call to
|
||||||
|
.B ub_resolve_async
|
||||||
creates a thread to handle work in the background.
|
creates a thread to handle work in the background.
|
||||||
If false, a process is forked to handle work in the background.
|
If false, a process is forked to handle work in the background.
|
||||||
Changes to this setting after \fBub_resolve_async\fP calls have been made
|
Changes to this setting after
|
||||||
have no effect (delete and re\-create the context to change).
|
.B ub_resolve_async
|
||||||
|
calls have been made have no effect (delete and re\-create the context
|
||||||
|
to change).
|
||||||
.TP
|
.TP
|
||||||
.B ub_poll
|
.B ub_poll
|
||||||
Poll a context to see if it has any new results.
|
Poll a context to see if it has any new results.
|
||||||
Do not poll in a loop, instead extract the \fBfd\fP below to poll for
|
Do not poll in a loop, instead extract the fd below to poll for readiness,
|
||||||
readiness, and then check, or wait using the wait routine.
|
and then check, or wait using the wait routine.
|
||||||
Returns 0 if nothing to read, or nonzero if a result is available.
|
Returns 0 if nothing to read, or nonzero if a result is available.
|
||||||
If nonzero, call \fBub_process\fP to do callbacks.
|
If nonzero, call
|
||||||
|
.B ub_process
|
||||||
|
to do callbacks.
|
||||||
.TP
|
.TP
|
||||||
.B ub_wait
|
.B ub_wait
|
||||||
Wait for a context to finish with results.
|
Wait for a context to finish with results. Calls
|
||||||
Calls \fBub_process\fP after the wait for you.
|
.B ub_process
|
||||||
After the wait, there are no more outstanding asynchronous queries.
|
after the wait for you. After the wait, there are no more outstanding
|
||||||
|
asynchronous queries.
|
||||||
.TP
|
.TP
|
||||||
.B ub_fd
|
.B ub_fd
|
||||||
Get file descriptor.
|
Get file descriptor. Wait for it to become readable, at this point
|
||||||
Wait for it to become readable, at this point answers are returned from
|
answers are returned from the asynchronous validating resolver.
|
||||||
the asynchronous validating resolver.
|
Then call the \fBub_process\fR to continue processing.
|
||||||
Then call the \fBub_process\fP to continue processing.
|
|
||||||
.TP
|
.TP
|
||||||
.B ub_process
|
.B ub_process
|
||||||
Call this routine to continue processing results from the validating
|
Call this routine to continue processing results from the validating
|
||||||
resolver (when the \fBfd\fP becomes readable).
|
resolver (when the fd becomes readable).
|
||||||
Will perform necessary callbacks.
|
Will perform necessary callbacks.
|
||||||
.TP
|
.TP
|
||||||
.B ub_resolve
|
.B ub_resolve
|
||||||
@@ -311,113 +340,95 @@ The result structure is newly allocated with the resulting data.
|
|||||||
.TP
|
.TP
|
||||||
.B ub_resolve_async
|
.B ub_resolve_async
|
||||||
Perform asynchronous resolution and validation of the target name.
|
Perform asynchronous resolution and validation of the target name.
|
||||||
Arguments mean the same as for \fBub_resolve\fP except no data is
|
Arguments mean the same as for \fBub_resolve\fR except no
|
||||||
returned immediately, instead a callback is called later.
|
data is returned immediately, instead a callback is called later.
|
||||||
The callback receives a copy of the mydata pointer, that you can use to
|
The callback receives a copy of the mydata pointer, that you can use to pass
|
||||||
pass information to the callback.
|
information to the callback. The callback type is a function pointer to
|
||||||
The callback type is a function pointer to a function declared as:
|
a function declared as
|
||||||
.INDENT 7.0
|
.IP
|
||||||
.INDENT 3.5
|
|
||||||
.sp
|
|
||||||
.nf
|
|
||||||
.ft C
|
|
||||||
void my_callback_function(void* my_arg, int err,
|
void my_callback_function(void* my_arg, int err,
|
||||||
struct ub_result* result);
|
.br
|
||||||
.ft P
|
struct ub_result* result);
|
||||||
.fi
|
.IP
|
||||||
.UNINDENT
|
The async_id is returned so you can (at your option) decide to track it
|
||||||
.UNINDENT
|
and cancel the request if needed. If you pass a NULL pointer the async_id
|
||||||
.sp
|
is not returned.
|
||||||
The \fBasync_id\fP is returned so you can (at your option) decide to
|
|
||||||
track it and cancel the request if needed.
|
|
||||||
If you pass a NULL pointer the \fBasync_id\fP is not returned.
|
|
||||||
The context, created via \fBub_ctx_create\fP, is in use during but also
|
|
||||||
after the callback and it cannot be deleted during a callback.
|
|
||||||
.TP
|
.TP
|
||||||
.B ub_cancel
|
.B ub_cancel
|
||||||
Cancel an async query in progress.
|
Cancel an async query in progress. This may return an error if the query
|
||||||
This may return an error if the query does not exist, or the query is
|
does not exist, or the query is already being delivered, in that case you
|
||||||
already being delivered, in that case you may still get a callback for
|
may still get a callback for the query.
|
||||||
the query.
|
|
||||||
.TP
|
.TP
|
||||||
.B ub_resolve_free
|
.B ub_resolve_free
|
||||||
Free struct \fBub_result\fP contents after use.
|
Free struct ub_result contents after use.
|
||||||
.TP
|
.TP
|
||||||
.B ub_strerror
|
.B ub_strerror
|
||||||
Convert error value from one of the unbound library functions to a
|
Convert error value from one of the unbound library functions
|
||||||
human readable string.
|
to a human readable string.
|
||||||
.TP
|
.TP
|
||||||
.B ub_ctx_print_local_zones
|
.B ub_ctx_print_local_zones
|
||||||
Debug printout the local authority information to debug output.
|
Debug printout the local authority information to debug output.
|
||||||
.TP
|
.TP
|
||||||
.B ub_ctx_zone_add
|
.B ub_ctx_zone_add
|
||||||
Add new zone to local authority info, like local\-zone
|
Add new zone to local authority info, like local\-zone \fIunbound.conf\fR(5)
|
||||||
\fI\%unbound.conf(5)\fP statement.
|
statement.
|
||||||
.TP
|
.TP
|
||||||
.B ub_ctx_zone_remove
|
.B ub_ctx_zone_remove
|
||||||
Delete zone from local authority info.
|
Delete zone from local authority info.
|
||||||
.TP
|
.TP
|
||||||
.B ub_ctx_data_add
|
.B ub_ctx_data_add
|
||||||
Add resource record data to local authority info, like local\-data
|
Add resource record data to local authority info, like local\-data
|
||||||
\fI\%unbound.conf(5)\fP statement.
|
\fIunbound.conf\fR(5) statement.
|
||||||
.TP
|
.TP
|
||||||
.B ub_ctx_data_remove
|
.B ub_ctx_data_remove
|
||||||
Delete local authority data from the name given.
|
Delete local authority data from the name given.
|
||||||
.UNINDENT
|
.SH "RESULT DATA STRUCTURE"
|
||||||
.SH RESULT DATA STRUCTURE
|
The result of the DNS resolution and validation is returned as
|
||||||
.sp
|
\fIstruct ub_result\fR. The result structure contains the following entries.
|
||||||
The result of the DNS resolution and validation is returned as \fIstruct
|
.P
|
||||||
ub_result\fP\&.
|
|
||||||
The result structure contains the following entries:
|
|
||||||
.INDENT 0.0
|
|
||||||
.INDENT 3.5
|
|
||||||
.sp
|
|
||||||
.nf
|
.nf
|
||||||
.ft C
|
struct ub_result {
|
||||||
struct ub_result {
|
char* qname; /* text string, original question */
|
||||||
char* qname; /* text string, original question */
|
int qtype; /* type code asked for */
|
||||||
int qtype; /* type code asked for */
|
int qclass; /* class code asked for */
|
||||||
int qclass; /* class code asked for */
|
char** data; /* array of rdata items, NULL terminated*/
|
||||||
char** data; /* array of rdata items, NULL terminated*/
|
int* len; /* array with lengths of rdata items */
|
||||||
int* len; /* array with lengths of rdata items */
|
char* canonname; /* canonical name of result */
|
||||||
char* canonname; /* canonical name of result */
|
int rcode; /* additional error code in case of no data */
|
||||||
int rcode; /* additional error code in case of no data */
|
void* answer_packet; /* full network format answer packet */
|
||||||
void* answer_packet; /* full network format answer packet */
|
int answer_len; /* length of packet in octets */
|
||||||
int answer_len; /* length of packet in octets */
|
int havedata; /* true if there is data */
|
||||||
int havedata; /* true if there is data */
|
int nxdomain; /* true if nodata because name does not exist */
|
||||||
int nxdomain; /* true if nodata because name does not exist */
|
int secure; /* true if result is secure */
|
||||||
int secure; /* true if result is secure */
|
int bogus; /* true if a security failure happened */
|
||||||
int bogus; /* true if a security failure happened */
|
char* why_bogus; /* string with error if bogus */
|
||||||
char* why_bogus; /* string with error if bogus */
|
int was_ratelimited; /* true if the query was ratelimited (SERVFAIL) by unbound */
|
||||||
int was_ratelimited; /* true if the query was ratelimited (SERVFAIL) by unbound */
|
int ttl; /* number of seconds the result is valid */
|
||||||
int ttl; /* number of seconds the result is valid */
|
};
|
||||||
};
|
|
||||||
.ft P
|
|
||||||
.fi
|
.fi
|
||||||
.UNINDENT
|
.P
|
||||||
.UNINDENT
|
If both secure and bogus are false, security was not enabled for the
|
||||||
.sp
|
domain of the query. Else, they are not both true, one of them is true.
|
||||||
If both secure and bogus are false, security was not enabled for the domain of
|
.SH "RETURN VALUES"
|
||||||
the query.
|
Many routines return an error code. The value 0 (zero) denotes no error
|
||||||
Else, they are not both true, one of them is true.
|
happened. Other values can be passed to
|
||||||
.SH RETURN VALUES
|
.B ub_strerror
|
||||||
.sp
|
to obtain a readable error string.
|
||||||
Many routines return an error code.
|
.B ub_strerror
|
||||||
The value 0 (zero) denotes no error happened.
|
returns a zero terminated string.
|
||||||
Other values can be passed to \fBub_strerror\fP to obtain a readable error
|
.B ub_ctx_create
|
||||||
string.
|
returns NULL on an error (a malloc failure).
|
||||||
\fBub_strerror\fP returns a zero terminated string.
|
.B ub_poll
|
||||||
\fBub_ctx_create\fP returns NULL on an error (a malloc failure).
|
returns true if some information may be available, false otherwise.
|
||||||
\fBub_poll\fP returns true if some information may be available, false otherwise.
|
.B ub_fd
|
||||||
\fBub_fd\fP returns a file descriptor or \-1 on error.
|
returns a file descriptor or \-1 on error.
|
||||||
\fBub_ctx_config\fP and \fBub_ctx_resolvconf\fP attempt to leave errno informative
|
.B ub_ctx_config
|
||||||
on a function return with file read failure.
|
and
|
||||||
.SH SEE ALSO
|
.B ub_ctx_resolvconf
|
||||||
.sp
|
attempt to leave errno informative on a function return with file read failure.
|
||||||
\fI\%unbound.conf(5)\fP, \fI\%unbound(8)\fP\&.
|
.SH "SEE ALSO"
|
||||||
.SH AUTHOR
|
\fIunbound.conf\fR(5),
|
||||||
Unbound developers are mentioned in the CREDITS file in the distribution.
|
\fIunbound\fR(8).
|
||||||
.SH COPYRIGHT
|
.SH "AUTHORS"
|
||||||
1999-2026, NLnet Labs
|
.B Unbound
|
||||||
.\" Generated by docutils manpage writer.
|
developers are mentioned in the CREDITS file in the distribution.
|
||||||
.
|
|
||||||
|
|||||||
@@ -1,493 +0,0 @@
|
|||||||
..
|
|
||||||
WHEN EDITING MAKE SURE EACH SENTENCE STARTS ON A NEW LINE
|
|
||||||
|
|
||||||
..
|
|
||||||
IT HELPS RENDERERS TO DO THE RIGHT THING WRT SPACE
|
|
||||||
|
|
||||||
..
|
|
||||||
IT HELPS PEOPLE DIFFING THE CHANGES
|
|
||||||
|
|
||||||
..
|
|
||||||
WHEN EDITING MAKE SURE EACH SENTENCE STARTS ON A NEW LINE
|
|
||||||
|
|
||||||
..
|
|
||||||
IT HELPS RENDERERS TO DO THE RIGHT THING WRT SPACE
|
|
||||||
|
|
||||||
..
|
|
||||||
IT HELPS PEOPLE DIFFING THE CHANGES
|
|
||||||
|
|
||||||
..
|
|
||||||
WHEN EDITING MAKE SURE EACH SENTENCE STARTS ON A NEW LINE
|
|
||||||
|
|
||||||
..
|
|
||||||
IT HELPS RENDERERS TO DO THE RIGHT THING WRT SPACE
|
|
||||||
|
|
||||||
..
|
|
||||||
IT HELPS PEOPLE DIFFING THE CHANGES
|
|
||||||
|
|
||||||
..
|
|
||||||
WHEN EDITING MAKE SURE EACH SENTENCE STARTS ON A NEW LINE
|
|
||||||
|
|
||||||
..
|
|
||||||
IT HELPS RENDERERS TO DO THE RIGHT THING WRT SPACE
|
|
||||||
|
|
||||||
..
|
|
||||||
IT HELPS PEOPLE DIFFING THE CHANGES
|
|
||||||
|
|
||||||
libunbound(3)
|
|
||||||
=============
|
|
||||||
|
|
||||||
Synopsis
|
|
||||||
--------
|
|
||||||
|
|
||||||
.. only:: html
|
|
||||||
|
|
||||||
.. code-block:: c
|
|
||||||
|
|
||||||
#include <unbound.h>
|
|
||||||
|
|
||||||
struct ub_ctx * ub_ctx_create(void);
|
|
||||||
|
|
||||||
void ub_ctx_delete(struct ub_ctx* ctx);
|
|
||||||
|
|
||||||
int ub_ctx_set_option(struct ub_ctx* ctx, char* opt, char* val);
|
|
||||||
|
|
||||||
int ub_ctx_get_option(struct ub_ctx* ctx, char* opt, char** val);
|
|
||||||
|
|
||||||
int ub_ctx_config(struct ub_ctx* ctx, char* fname);
|
|
||||||
|
|
||||||
int ub_ctx_set_fwd(struct ub_ctx* ctx, char* addr);
|
|
||||||
|
|
||||||
int ub_ctx_set_stub(struct ub_ctx* ctx, char* zone, char* addr,
|
|
||||||
int isprime);
|
|
||||||
|
|
||||||
int ub_ctx_set_tls(struct ub_ctx* ctx, int tls);
|
|
||||||
|
|
||||||
int ub_ctx_resolvconf(struct ub_ctx* ctx, char* fname);
|
|
||||||
|
|
||||||
int ub_ctx_hosts(struct ub_ctx* ctx, char* fname);
|
|
||||||
|
|
||||||
int ub_ctx_add_ta(struct ub_ctx* ctx, char* ta);
|
|
||||||
|
|
||||||
int ub_ctx_add_ta_autr(struct ub_ctx* ctx, char* fname);
|
|
||||||
|
|
||||||
int ub_ctx_add_ta_file(struct ub_ctx* ctx, char* fname);
|
|
||||||
|
|
||||||
int ub_ctx_trustedkeys(struct ub_ctx* ctx, char* fname);
|
|
||||||
|
|
||||||
int ub_ctx_debugout(struct ub_ctx* ctx, FILE* out);
|
|
||||||
|
|
||||||
int ub_ctx_debuglevel(struct ub_ctx* ctx, int d);
|
|
||||||
|
|
||||||
int ub_ctx_async(struct ub_ctx* ctx, int dothread);
|
|
||||||
|
|
||||||
int ub_poll(struct ub_ctx* ctx);
|
|
||||||
|
|
||||||
int ub_wait(struct ub_ctx* ctx);
|
|
||||||
|
|
||||||
int ub_fd(struct ub_ctx* ctx);
|
|
||||||
|
|
||||||
int ub_process(struct ub_ctx* ctx);
|
|
||||||
|
|
||||||
int ub_resolve(struct ub_ctx* ctx, char* name, int rrtype,
|
|
||||||
int rrclass, struct ub_result** result);
|
|
||||||
|
|
||||||
int ub_resolve_async(struct ub_ctx* ctx, char* name, int rrtype,
|
|
||||||
int rrclass, void* mydata, ub_callback_type callback,
|
|
||||||
int* async_id);
|
|
||||||
|
|
||||||
int ub_cancel(struct ub_ctx* ctx, int async_id);
|
|
||||||
|
|
||||||
void ub_resolve_free(struct ub_result* result);
|
|
||||||
|
|
||||||
const char * ub_strerror(int err);
|
|
||||||
|
|
||||||
int ub_ctx_print_local_zones(struct ub_ctx* ctx);
|
|
||||||
|
|
||||||
int ub_ctx_zone_add(struct ub_ctx* ctx, char* zone_name, char* zone_type);
|
|
||||||
|
|
||||||
int ub_ctx_zone_remove(struct ub_ctx* ctx, char* zone_name);
|
|
||||||
|
|
||||||
int ub_ctx_data_add(struct ub_ctx* ctx, char* data);
|
|
||||||
|
|
||||||
int ub_ctx_data_remove(struct ub_ctx* ctx, char* data);
|
|
||||||
|
|
||||||
.. only:: man
|
|
||||||
|
|
||||||
**#include <unbound.h>**
|
|
||||||
|
|
||||||
struct ub_ctx \* **ub_ctx_create**\ (void);
|
|
||||||
|
|
||||||
void **ub_ctx_delete**\ (struct ub_ctx\* ctx);
|
|
||||||
|
|
||||||
int **ub_ctx_set_option**\ (struct ub_ctx\* ctx, char\* opt, char\* val);
|
|
||||||
|
|
||||||
int **ub_ctx_get_option**\ (struct ub_ctx\* ctx, char\* opt, char\*\* val);
|
|
||||||
|
|
||||||
int **ub_ctx_config**\ (struct ub_ctx\* ctx, char* fname);
|
|
||||||
|
|
||||||
int **ub_ctx_set_fwd**\ (struct ub_ctx\* ctx, char\* addr);
|
|
||||||
|
|
||||||
int **ub_ctx_set_stub**\ (struct ub_ctx\* ctx, char\* zone, char\* addr,
|
|
||||||
int isprime);
|
|
||||||
|
|
||||||
int **ub_ctx_set_tls**\ (struct ub_ctx\* ctx, int tls);
|
|
||||||
|
|
||||||
int **ub_ctx_resolvconf**\ (struct ub_ctx\* ctx, char\* fname);
|
|
||||||
|
|
||||||
int **ub_ctx_hosts**\ (struct ub_ctx\* ctx, char\* fname);
|
|
||||||
|
|
||||||
int **ub_ctx_add_ta**\ (struct ub_ctx\* ctx, char\* ta);
|
|
||||||
|
|
||||||
int **ub_ctx_add_ta_autr**\ (struct ub_ctx\* ctx, char\* fname);
|
|
||||||
|
|
||||||
int **ub_ctx_add_ta_file**\ (struct ub_ctx\* ctx, char\* fname);
|
|
||||||
|
|
||||||
int **ub_ctx_trustedkeys**\ (struct ub_ctx\* ctx, char\* fname);
|
|
||||||
|
|
||||||
int **ub_ctx_debugout**\ (struct ub_ctx\* ctx, FILE\* out);
|
|
||||||
|
|
||||||
int **ub_ctx_debuglevel**\ (struct ub_ctx\* ctx, int d);
|
|
||||||
|
|
||||||
int **ub_ctx_async**\ (struct ub_ctx\* ctx, int dothread);
|
|
||||||
|
|
||||||
int **ub_poll**\ (struct ub_ctx\* ctx);
|
|
||||||
|
|
||||||
int **ub_wait**\ (struct ub_ctx\* ctx);
|
|
||||||
|
|
||||||
int **ub_fd**\ (struct ub_ctx\* ctx);
|
|
||||||
|
|
||||||
int **ub_process**\ (struct ub_ctx\* ctx);
|
|
||||||
|
|
||||||
int **ub_resolve**\ (struct ub_ctx\* ctx, char\* name,
|
|
||||||
int rrtype, int rrclass, struct ub_result\*\* result);
|
|
||||||
|
|
||||||
int **ub_resolve_async**\ (struct ub_ctx\* ctx, char\* name,
|
|
||||||
int rrtype, int rrclass, void\* mydata,
|
|
||||||
ub_callback_type\* callback, int\* async_id);
|
|
||||||
|
|
||||||
int **ub_cancel**\ (struct ub_ctx\* ctx, int async_id);
|
|
||||||
|
|
||||||
void **ub_resolve_free**\ (struct ub_result\* result);
|
|
||||||
|
|
||||||
const char \* **ub_strerror**\ (int err);
|
|
||||||
|
|
||||||
int **ub_ctx_print_local_zones**\ (struct ub_ctx\* ctx);
|
|
||||||
|
|
||||||
int **ub_ctx_zone_add**\ (struct ub_ctx\* ctx, char\* zone_name, char\* zone_type);
|
|
||||||
|
|
||||||
int **ub_ctx_zone_remove**\ (struct ub_ctx\* ctx, char\* zone_name);
|
|
||||||
|
|
||||||
int **ub_ctx_data_add**\ (struct ub_ctx\* ctx, char\* data);
|
|
||||||
|
|
||||||
int **ub_ctx_data_remove**\ (struct ub_ctx\* ctx, char\* data);
|
|
||||||
|
|
||||||
Description
|
|
||||||
-----------
|
|
||||||
|
|
||||||
Unbound is an implementation of a DNS resolver, that does caching and DNSSEC
|
|
||||||
validation.
|
|
||||||
This is the library API, for using the ``-lunbound`` library.
|
|
||||||
The server daemon is described in :doc:`unbound(8)</manpages/unbound>`.
|
|
||||||
The library works independent from a running unbound server, and can be used to
|
|
||||||
convert hostnames to ip addresses, and back, and obtain other information from
|
|
||||||
the DNS.
|
|
||||||
The library performs public-key validation of results with DNSSEC.
|
|
||||||
|
|
||||||
The library uses a variable of type *struct ub_ctx* to keep context between
|
|
||||||
calls.
|
|
||||||
The user must maintain it, creating it with **ub_ctx_create** and deleting it
|
|
||||||
with **ub_ctx_delete**.
|
|
||||||
It can be created and deleted at any time.
|
|
||||||
Creating it anew removes any previous configuration (such as trusted keys) and
|
|
||||||
clears any cached results.
|
|
||||||
|
|
||||||
The functions are thread-safe, and a context can be used in a threaded (as well
|
|
||||||
as in a non-threaded) environment.
|
|
||||||
Also resolution (and validation) can be performed blocking and non-blocking
|
|
||||||
(also called asynchronous).
|
|
||||||
The async method returns from the call immediately, so that processing can go
|
|
||||||
on, while the results become available later.
|
|
||||||
|
|
||||||
The functions are discussed in turn below.
|
|
||||||
|
|
||||||
Functions
|
|
||||||
---------
|
|
||||||
|
|
||||||
.. glossary::
|
|
||||||
|
|
||||||
ub_ctx_create
|
|
||||||
Create a new context, initialised with defaults.
|
|
||||||
The information from :file:`/etc/resolv.conf` and :file:`/etc/hosts` is
|
|
||||||
not utilised by default.
|
|
||||||
Use **ub_ctx_resolvconf** and **ub_ctx_hosts** to read them.
|
|
||||||
Before you call this, use the openssl functions
|
|
||||||
**CRYPTO_set_id_callback** and **CRYPTO_set_locking_callback** to set
|
|
||||||
up asynchronous operation if you use lib openssl (the application calls
|
|
||||||
these functions once for initialisation).
|
|
||||||
Openssl 1.0.0 or later uses the **CRYPTO_THREADID_set_callback**
|
|
||||||
function.
|
|
||||||
|
|
||||||
ub_ctx_delete
|
|
||||||
Delete validation context and free associated resources.
|
|
||||||
Outstanding async queries are killed and callbacks are not called for
|
|
||||||
them.
|
|
||||||
|
|
||||||
ub_ctx_set_option
|
|
||||||
A power-user interface that lets you specify one of the options from
|
|
||||||
the config file format, see :doc:`unbound.conf(5)</manpages/unbound.conf>`.
|
|
||||||
Not all options are relevant.
|
|
||||||
For some specific options, such as adding trust anchors, special
|
|
||||||
routines exist.
|
|
||||||
Pass the option name with the trailing ``':'``.
|
|
||||||
|
|
||||||
ub_ctx_get_option
|
|
||||||
A power-user interface that gets an option value.
|
|
||||||
Some options cannot be gotten, and others return a newline separated
|
|
||||||
list.
|
|
||||||
Pass the option name without trailing ``':'``.
|
|
||||||
The returned value must be free(2)d by the caller.
|
|
||||||
|
|
||||||
ub_ctx_config
|
|
||||||
A power-user interface that lets you specify an unbound config file,
|
|
||||||
see :doc:`unbound.conf(5)</manpages/unbound.conf>`, which is read for
|
|
||||||
configuration.
|
|
||||||
Not all options are relevant.
|
|
||||||
For some specific options, such as adding trust anchors, special
|
|
||||||
routines exist.
|
|
||||||
This function is thread-safe only if a single instance of **ub_ctx**\*
|
|
||||||
exists in the application.
|
|
||||||
If several instances exist the application has to ensure that
|
|
||||||
**ub_ctx_config** is not called in parallel by the different instances.
|
|
||||||
|
|
||||||
ub_ctx_set_fwd
|
|
||||||
Set machine to forward DNS queries to, the caching resolver to use.
|
|
||||||
IP4 or IP6 address.
|
|
||||||
Forwards all DNS requests to that machine, which is expected to run a
|
|
||||||
recursive resolver.
|
|
||||||
If the proxy is not DNSSEC capable, validation may fail.
|
|
||||||
Can be called several times, in that case the addresses are used as
|
|
||||||
backup servers.
|
|
||||||
At this time it is only possible to set configuration before the first
|
|
||||||
resolve is done.
|
|
||||||
|
|
||||||
ub_ctx_set_stub
|
|
||||||
Set a stub zone, authoritative dns servers to use for a particular
|
|
||||||
zone.
|
|
||||||
IP4 or IP6 address.
|
|
||||||
If the address is NULL the stub entry is removed.
|
|
||||||
Set isprime true if you configure root hints with it.
|
|
||||||
Otherwise similar to the stub zone item from unbound's config file.
|
|
||||||
Can be called several times, for different zones, or to add multiple
|
|
||||||
addresses for a particular zone.
|
|
||||||
At this time it is only possible to set configuration before the first
|
|
||||||
resolve is done.
|
|
||||||
|
|
||||||
ub_ctx_set_tls
|
|
||||||
Enable DNS over TLS (DoT) for machines set with **ub_ctx_set_fwd**.
|
|
||||||
At this time it is only possible to set configuration before the first
|
|
||||||
resolve is done.
|
|
||||||
|
|
||||||
ub_ctx_resolvconf
|
|
||||||
By default the root servers are queried and full resolver mode is used,
|
|
||||||
but you can use this call to read the list of nameservers to use from
|
|
||||||
the filename given.
|
|
||||||
Usually :file:`"/etc/resolv.conf"`.
|
|
||||||
Uses those nameservers as caching proxies.
|
|
||||||
If they do not support DNSSEC, validation may fail.
|
|
||||||
Only nameservers are picked up, the searchdomain, ndots and other
|
|
||||||
settings from *resolv.conf(5)* are ignored.
|
|
||||||
If fname NULL is passed, :file:`"/etc/resolv.conf"` is used (if on
|
|
||||||
Windows, the system-wide configured nameserver is picked instead).
|
|
||||||
At this time it is only possible to set configuration before the first
|
|
||||||
resolve is done.
|
|
||||||
|
|
||||||
ub_ctx_hosts
|
|
||||||
Read list of hosts from the filename given.
|
|
||||||
Usually :file:`"/etc/hosts"`.
|
|
||||||
When queried for, these addresses are not marked DNSSEC secure.
|
|
||||||
If fname NULL is passed, :file:`"/etc/hosts"` is used (if on Windows,
|
|
||||||
:file:`etc/hosts` from WINDIR is picked instead).
|
|
||||||
At this time it is only possible to set configuration before the first
|
|
||||||
resolve is done.
|
|
||||||
|
|
||||||
ub_ctx_add_ta
|
|
||||||
Add a trust anchor to the given context.
|
|
||||||
At this time it is only possible to add trusted keys before the first
|
|
||||||
resolve is done.
|
|
||||||
The format is a string, similar to the zone-file format,
|
|
||||||
**[domainname]** **[type]** **[rdata contents]**.
|
|
||||||
Both DS and DNSKEY records are accepted.
|
|
||||||
|
|
||||||
ub_ctx_add_ta_autr
|
|
||||||
Add filename with automatically tracked trust anchor to the given
|
|
||||||
context.
|
|
||||||
Pass name of a file with the managed trust anchor.
|
|
||||||
You can create this file with
|
|
||||||
:doc:`unbound-anchor(8)</manpages/unbound-anchor>` for the root anchor.
|
|
||||||
You can also create it with an initial file with one line with a DNSKEY
|
|
||||||
or DS record.
|
|
||||||
If the file is writable, it is updated when the trust anchor changes.
|
|
||||||
At this time it is only possible to add trusted keys before the first
|
|
||||||
resolve is done.
|
|
||||||
|
|
||||||
ub_ctx_add_ta_file
|
|
||||||
Add trust anchors to the given context.
|
|
||||||
Pass name of a file with DS and DNSKEY records in zone file format.
|
|
||||||
At this time it is only possible to add trusted keys before the first
|
|
||||||
resolve is done.
|
|
||||||
|
|
||||||
ub_ctx_trustedkeys
|
|
||||||
Add trust anchors to the given context.
|
|
||||||
Pass the name of a bind-style config file with ``trusted-keys{}``.
|
|
||||||
At this time it is only possible to add trusted keys before the first
|
|
||||||
resolve is done.
|
|
||||||
|
|
||||||
ub_ctx_debugout
|
|
||||||
Set debug and error log output to the given stream.
|
|
||||||
Pass NULL to disable output.
|
|
||||||
Default is stderr.
|
|
||||||
File-names or using syslog can be enabled using config options, this
|
|
||||||
routine is for using your own stream.
|
|
||||||
|
|
||||||
ub_ctx_debuglevel
|
|
||||||
Set debug verbosity for the context.
|
|
||||||
Output is directed to stderr.
|
|
||||||
Higher debug level gives more output.
|
|
||||||
|
|
||||||
ub_ctx_async
|
|
||||||
Set a context behaviour for asynchronous action.
|
|
||||||
if set to true, enables threading and a call to **ub_resolve_async**
|
|
||||||
creates a thread to handle work in the background.
|
|
||||||
If false, a process is forked to handle work in the background.
|
|
||||||
Changes to this setting after **ub_resolve_async** calls have been made
|
|
||||||
have no effect (delete and re-create the context to change).
|
|
||||||
|
|
||||||
ub_poll
|
|
||||||
Poll a context to see if it has any new results.
|
|
||||||
Do not poll in a loop, instead extract the **fd** below to poll for
|
|
||||||
readiness, and then check, or wait using the wait routine.
|
|
||||||
Returns 0 if nothing to read, or nonzero if a result is available.
|
|
||||||
If nonzero, call **ub_process** to do callbacks.
|
|
||||||
|
|
||||||
ub_wait
|
|
||||||
Wait for a context to finish with results.
|
|
||||||
Calls **ub_process** after the wait for you.
|
|
||||||
After the wait, there are no more outstanding asynchronous queries.
|
|
||||||
|
|
||||||
ub_fd
|
|
||||||
Get file descriptor.
|
|
||||||
Wait for it to become readable, at this point answers are returned from
|
|
||||||
the asynchronous validating resolver.
|
|
||||||
Then call the **ub_process** to continue processing.
|
|
||||||
|
|
||||||
ub_process
|
|
||||||
Call this routine to continue processing results from the validating
|
|
||||||
resolver (when the **fd** becomes readable).
|
|
||||||
Will perform necessary callbacks.
|
|
||||||
|
|
||||||
ub_resolve
|
|
||||||
Perform resolution and validation of the target name.
|
|
||||||
The name is a domain name in a zero terminated text string.
|
|
||||||
The rrtype and rrclass are DNS type and class codes.
|
|
||||||
The result structure is newly allocated with the resulting data.
|
|
||||||
|
|
||||||
ub_resolve_async
|
|
||||||
Perform asynchronous resolution and validation of the target name.
|
|
||||||
Arguments mean the same as for **ub_resolve** except no data is
|
|
||||||
returned immediately, instead a callback is called later.
|
|
||||||
The callback receives a copy of the mydata pointer, that you can use to
|
|
||||||
pass information to the callback.
|
|
||||||
The callback type is a function pointer to a function declared as:
|
|
||||||
|
|
||||||
.. code-block:: c
|
|
||||||
|
|
||||||
void my_callback_function(void* my_arg, int err,
|
|
||||||
struct ub_result* result);
|
|
||||||
|
|
||||||
The **async_id** is returned so you can (at your option) decide to
|
|
||||||
track it and cancel the request if needed.
|
|
||||||
If you pass a NULL pointer the **async_id** is not returned.
|
|
||||||
The context, created via **ub_ctx_create**, is in use during but also
|
|
||||||
after the callback and it cannot be deleted during a callback.
|
|
||||||
|
|
||||||
ub_cancel
|
|
||||||
Cancel an async query in progress.
|
|
||||||
This may return an error if the query does not exist, or the query is
|
|
||||||
already being delivered, in that case you may still get a callback for
|
|
||||||
the query.
|
|
||||||
|
|
||||||
ub_resolve_free
|
|
||||||
Free struct **ub_result** contents after use.
|
|
||||||
|
|
||||||
ub_strerror
|
|
||||||
Convert error value from one of the unbound library functions to a
|
|
||||||
human readable string.
|
|
||||||
|
|
||||||
ub_ctx_print_local_zones
|
|
||||||
Debug printout the local authority information to debug output.
|
|
||||||
|
|
||||||
ub_ctx_zone_add
|
|
||||||
Add new zone to local authority info, like local-zone
|
|
||||||
:doc:`unbound.conf(5)</manpages/unbound.conf>` statement.
|
|
||||||
|
|
||||||
ub_ctx_zone_remove
|
|
||||||
Delete zone from local authority info.
|
|
||||||
|
|
||||||
ub_ctx_data_add
|
|
||||||
Add resource record data to local authority info, like local-data
|
|
||||||
:doc:`unbound.conf(5)</manpages/unbound.conf>` statement.
|
|
||||||
|
|
||||||
ub_ctx_data_remove
|
|
||||||
Delete local authority data from the name given.
|
|
||||||
|
|
||||||
Result Data structure
|
|
||||||
---------------------
|
|
||||||
|
|
||||||
The result of the DNS resolution and validation is returned as *struct
|
|
||||||
ub_result*.
|
|
||||||
The result structure contains the following entries:
|
|
||||||
|
|
||||||
.. code-block:: c
|
|
||||||
|
|
||||||
struct ub_result {
|
|
||||||
char* qname; /* text string, original question */
|
|
||||||
int qtype; /* type code asked for */
|
|
||||||
int qclass; /* class code asked for */
|
|
||||||
char** data; /* array of rdata items, NULL terminated*/
|
|
||||||
int* len; /* array with lengths of rdata items */
|
|
||||||
char* canonname; /* canonical name of result */
|
|
||||||
int rcode; /* additional error code in case of no data */
|
|
||||||
void* answer_packet; /* full network format answer packet */
|
|
||||||
int answer_len; /* length of packet in octets */
|
|
||||||
int havedata; /* true if there is data */
|
|
||||||
int nxdomain; /* true if nodata because name does not exist */
|
|
||||||
int secure; /* true if result is secure */
|
|
||||||
int bogus; /* true if a security failure happened */
|
|
||||||
char* why_bogus; /* string with error if bogus */
|
|
||||||
int was_ratelimited; /* true if the query was ratelimited (SERVFAIL) by unbound */
|
|
||||||
int ttl; /* number of seconds the result is valid */
|
|
||||||
};
|
|
||||||
|
|
||||||
If both secure and bogus are false, security was not enabled for the domain of
|
|
||||||
the query.
|
|
||||||
Else, they are not both true, one of them is true.
|
|
||||||
|
|
||||||
Return Values
|
|
||||||
-------------
|
|
||||||
|
|
||||||
Many routines return an error code.
|
|
||||||
The value 0 (zero) denotes no error happened.
|
|
||||||
Other values can be passed to **ub_strerror** to obtain a readable error
|
|
||||||
string.
|
|
||||||
**ub_strerror** returns a zero terminated string.
|
|
||||||
**ub_ctx_create** returns NULL on an error (a malloc failure).
|
|
||||||
**ub_poll** returns true if some information may be available, false otherwise.
|
|
||||||
**ub_fd** returns a file descriptor or -1 on error.
|
|
||||||
**ub_ctx_config** and **ub_ctx_resolvconf** attempt to leave errno informative
|
|
||||||
on a function return with file read failure.
|
|
||||||
|
|
||||||
See Also
|
|
||||||
--------
|
|
||||||
|
|
||||||
:doc:`unbound.conf(5)</manpages/unbound.conf>`, :doc:`unbound(8)</manpages/unbound>`.
|
|
||||||
+135
-255
@@ -1,309 +1,189 @@
|
|||||||
.\" Man page generated from reStructuredText.
|
.TH "unbound-anchor" "8" "@date@" "NLnet Labs" "unbound @version@"
|
||||||
.
|
.\"
|
||||||
.
|
.\" unbound-anchor.8 -- unbound anchor maintenance utility manual
|
||||||
.nr rst2man-indent-level 0
|
.\"
|
||||||
.
|
.\" Copyright (c) 2008, NLnet Labs. All rights reserved.
|
||||||
.de1 rstReportMargin
|
.\"
|
||||||
\\$1 \\n[an-margin]
|
.\" See LICENSE for the license.
|
||||||
level \\n[rst2man-indent-level]
|
.\"
|
||||||
level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
.\"
|
||||||
-
|
.SH "NAME"
|
||||||
\\n[rst2man-indent0]
|
.B unbound\-anchor
|
||||||
\\n[rst2man-indent1]
|
\- Unbound anchor utility.
|
||||||
\\n[rst2man-indent2]
|
.SH "SYNOPSIS"
|
||||||
..
|
.B unbound\-anchor
|
||||||
.de1 INDENT
|
.RB [ opts ]
|
||||||
.\" .rstReportMargin pre:
|
.SH "DESCRIPTION"
|
||||||
. RS \\$1
|
.B Unbound\-anchor
|
||||||
. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
|
performs setup or update of the root trust anchor for DNSSEC validation.
|
||||||
. nr rst2man-indent-level +1
|
The program fetches the trust anchor with the method from RFC7958 when
|
||||||
.\" .rstReportMargin post:
|
regular RFC5011 update fails to bring it up to date.
|
||||||
..
|
It can be run (as root) from the commandline, or run as part of startup
|
||||||
.de UNINDENT
|
scripts. Before you start the \fIunbound\fR(8) DNS server.
|
||||||
. RE
|
.P
|
||||||
.\" indent \\n[an-margin]
|
|
||||||
.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
|
||||||
.nr rst2man-indent-level -1
|
|
||||||
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
|
||||||
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
|
|
||||||
..
|
|
||||||
.TH "UNBOUND-ANCHOR" "8" "@date@" "@version@" "Unbound"
|
|
||||||
.SH NAME
|
|
||||||
unbound-anchor \- Unbound @version@ anchor utility.
|
|
||||||
.SH SYNOPSIS
|
|
||||||
.sp
|
|
||||||
\fBunbound\-anchor\fP [\fBopts\fP]
|
|
||||||
.SH DESCRIPTION
|
|
||||||
.sp
|
|
||||||
\fBunbound\-anchor\fP performs setup or update of the root trust anchor for DNSSEC
|
|
||||||
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.
|
|
||||||
.sp
|
|
||||||
Suggested usage:
|
Suggested usage:
|
||||||
.INDENT 0.0
|
.P
|
||||||
.INDENT 3.5
|
|
||||||
.sp
|
|
||||||
.nf
|
.nf
|
||||||
.ft C
|
# in the init scripts.
|
||||||
# in the init scripts.
|
# provide or update the root anchor (if necessary)
|
||||||
# provide or update the root anchor (if necessary)
|
unbound-anchor \-a "@UNBOUND_ROOTKEY_FILE@"
|
||||||
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).
|
||||||
# Please note usage of this root anchor is at your own risk
|
#
|
||||||
# and under the terms of our LICENSE (see source).
|
# start validating resolver
|
||||||
#
|
# the unbound.conf contains:
|
||||||
# start validating resolver
|
# auto-trust-anchor-file: "@UNBOUND_ROOTKEY_FILE@"
|
||||||
# the unbound.conf contains:
|
unbound \-c unbound.conf
|
||||||
# auto\-trust\-anchor\-file: \(dq@UNBOUND_ROOTKEY_FILE@\(dq
|
|
||||||
unbound \-c unbound.conf
|
|
||||||
.ft P
|
|
||||||
.fi
|
.fi
|
||||||
.UNINDENT
|
.P
|
||||||
.UNINDENT
|
This tool provides builtin default contents for the root anchor and root
|
||||||
.sp
|
update certificate files.
|
||||||
This tool provides builtin default contents for the root anchor and root update
|
.P
|
||||||
certificate files.
|
|
||||||
.sp
|
|
||||||
It tests if the root anchor file works, and if not, and an update is possible,
|
It tests if the root anchor file works, and if not, and an update is possible,
|
||||||
attempts to update the root anchor using the root update certificate.
|
attempts to update the root anchor using the root update certificate.
|
||||||
It performs a https fetch of
|
It performs a https fetch of root-anchors.xml and checks the results (RFC7958),
|
||||||
\fI\%root\-anchors.xml\fP
|
if all checks are successful, it updates the root anchor file. Otherwise
|
||||||
and checks the results (\fI\%RFC 7958\fP); if all checks are successful, it updates
|
the root anchor file is unchanged. It performs RFC5011 tracking if the
|
||||||
the root anchor file.
|
DNSSEC information available via the DNS makes that possible.
|
||||||
Otherwise the root anchor file is unchanged.
|
.P
|
||||||
It performs \fI\%RFC 5011\fP tracking if the DNSSEC information available via the
|
It does not perform an update if the certificate is expired, if the network
|
||||||
DNS makes that possible.
|
is down or other errors occur.
|
||||||
.sp
|
.P
|
||||||
It does not perform an update if the certificate is expired, if the network is
|
|
||||||
down or other errors occur.
|
|
||||||
.sp
|
|
||||||
The available options are:
|
The available options are:
|
||||||
.INDENT 0.0
|
|
||||||
.TP
|
.TP
|
||||||
.B \-a <file>
|
.B \-a \fIfile
|
||||||
The root anchor key file, that is read in and written out.
|
The root anchor key file, that is read in and written out.
|
||||||
Default is \fB@UNBOUND_ROOTKEY_FILE@\fP\&.
|
Default is @UNBOUND_ROOTKEY_FILE@.
|
||||||
If the file does not exist, or is empty, a builtin root key is written
|
If the file does not exist, or is empty, a builtin root key is written to it.
|
||||||
to it.
|
|
||||||
.UNINDENT
|
|
||||||
.INDENT 0.0
|
|
||||||
.TP
|
.TP
|
||||||
.B \-c <file>
|
.B \-c \fIfile
|
||||||
The root update certificate file, that is read in.
|
The root update certificate file, that is read in.
|
||||||
Default is \fB@UNBOUND_ROOTCERT_FILE@\fP\&.
|
Default is @UNBOUND_ROOTCERT_FILE@.
|
||||||
If the file does not exist, or is empty, a builtin certificate is used.
|
If the file does not exist, or is empty, a builtin certificate is used.
|
||||||
.UNINDENT
|
|
||||||
.INDENT 0.0
|
|
||||||
.TP
|
.TP
|
||||||
.B \-l
|
.B \-l
|
||||||
List the builtin root key and builtin root update certificate on stdout.
|
List the builtin root key and builtin root update certificate on stdout.
|
||||||
.UNINDENT
|
|
||||||
.INDENT 0.0
|
|
||||||
.TP
|
.TP
|
||||||
.B \-u <name>
|
.B \-u \fIname
|
||||||
The server name, it connects to \fBhttps://name\fP\&.
|
The server name, it connects to https://name. Specify without https:// prefix.
|
||||||
Specify without \fBhttps://\fP prefix.
|
The default is "data.iana.org". It connects to the port specified with \-P.
|
||||||
The default is \fB\(dqdata.iana.org\(dq\fP\&.
|
|
||||||
It connects to the port specified with \fI\%\-P\fP\&.
|
|
||||||
You can pass an IPv4 address or IPv6 address (no brackets) if you want.
|
You can pass an IPv4 address or IPv6 address (no brackets) if you want.
|
||||||
.UNINDENT
|
|
||||||
.INDENT 0.0
|
|
||||||
.TP
|
.TP
|
||||||
.B \-S
|
.B \-S
|
||||||
Do not use SNI for the HTTPS connection.
|
Do not use SNI for the HTTPS connection. Default is to use SNI.
|
||||||
Default is to use SNI.
|
|
||||||
.UNINDENT
|
|
||||||
.INDENT 0.0
|
|
||||||
.TP
|
.TP
|
||||||
.B \-b <address>
|
.B \-b \fIaddress
|
||||||
The source address to bind to for domain resolution and contacting the
|
The source address to bind to for domain resolution and contacting the server
|
||||||
server on https.
|
on https. May be either an IPv4 address or IPv6 address (no brackets).
|
||||||
May be either an IPv4 address or IPv6 address (no brackets).
|
|
||||||
.UNINDENT
|
|
||||||
.INDENT 0.0
|
|
||||||
.TP
|
.TP
|
||||||
.B \-x <path>
|
.B \-x \fIpath
|
||||||
The pathname to the root\-anchors.xml file on the server.
|
The pathname to the root\-anchors.xml file on the server. (forms URL with \-u).
|
||||||
(forms URL with \fI\%\-u\fP).
|
The default is /root\-anchors/root\-anchors.xml.
|
||||||
The default is \fB/root\-anchors/root\-anchors.xml\fP\&.
|
|
||||||
.UNINDENT
|
|
||||||
.INDENT 0.0
|
|
||||||
.TP
|
.TP
|
||||||
.B \-s <path>
|
.B \-s \fIpath
|
||||||
The pathname to the root\-anchors.p7s file on the server.
|
The pathname to the root\-anchors.p7s file on the server. (forms URL with \-u).
|
||||||
(forms URL with \fI\%\-u\fP).
|
The default is /root\-anchors/root\-anchors.p7s. This file has to be a PKCS7
|
||||||
The default is \fB/root\-anchors/root\-anchors.p7s\fP\&.
|
signature over the xml file, using the pem file (\-c) as trust anchor.
|
||||||
This file has to be a PKCS7 signature over the xml file, using the pem
|
|
||||||
file (\fI\%\-c\fP) as trust anchor.
|
|
||||||
.UNINDENT
|
|
||||||
.INDENT 0.0
|
|
||||||
.TP
|
.TP
|
||||||
.B \-n <name>
|
.B \-n \fIname
|
||||||
The emailAddress for the Subject of the signer\(aqs certificate from the
|
The emailAddress for the Subject of the signer's certificate from the p7s
|
||||||
p7s signature file.
|
signature file. Only signatures from this name are allowed. default is
|
||||||
Only signatures from this name are allowed.
|
dnssec@iana.org. If you pass "" then the emailAddress is not checked.
|
||||||
The default is \fBdnssec@iana.org\fP\&.
|
|
||||||
If you pass \fB\(dq\(dq\fP then the emailAddress is not checked.
|
|
||||||
.UNINDENT
|
|
||||||
.INDENT 0.0
|
|
||||||
.TP
|
.TP
|
||||||
.B \-4
|
.B \-4
|
||||||
Use IPv4 for domain resolution and contacting the server on
|
Use IPv4 for domain resolution and contacting the server on https. Default is
|
||||||
https.
|
to use IPv4 and IPv6 where appropriate.
|
||||||
Default is to use IPv4 and IPv6 where appropriate.
|
|
||||||
.UNINDENT
|
|
||||||
.INDENT 0.0
|
|
||||||
.TP
|
.TP
|
||||||
.B \-6
|
.B \-6
|
||||||
Use IPv6 for domain resolution and contacting the server on https.
|
Use IPv6 for domain resolution and contacting the server on https. Default is
|
||||||
Default is to use IPv4 and IPv6 where appropriate.
|
to use IPv4 and IPv6 where appropriate.
|
||||||
.UNINDENT
|
|
||||||
.INDENT 0.0
|
|
||||||
.TP
|
.TP
|
||||||
.B \-f <resolv.conf>
|
.B \-f \fIresolv.conf
|
||||||
Use the given resolv.conf file.
|
Use the given resolv.conf file. Not enabled by default, but you could try to
|
||||||
Not enabled by default, but you could try to pass
|
pass /etc/resolv.conf on some systems. It contains the IP addresses of the
|
||||||
\fB/etc/resolv.conf\fP on some systems.
|
recursive nameservers to use. However, since this tool could be used to
|
||||||
It contains the IP addresses of the recursive nameservers to use.
|
bootstrap that very recursive nameserver, it would not be useful (since
|
||||||
However, since this tool could be used to bootstrap that very recursive
|
that server is not up yet, since we are bootstrapping it). It could be
|
||||||
nameserver, it would not be useful (since that server is not up yet,
|
useful in a situation where you know an upstream cache is deployed (and
|
||||||
since we are bootstrapping it).
|
running) and in captive portal situations.
|
||||||
It could be useful in a situation where you know an upstream cache is
|
|
||||||
deployed (and running) and in captive portal situations.
|
|
||||||
.UNINDENT
|
|
||||||
.INDENT 0.0
|
|
||||||
.TP
|
.TP
|
||||||
.B \-r <root.hints>
|
.B \-r \fIroot.hints
|
||||||
Use the given root.hints file (same syntax as the BIND and Unbound root
|
Use the given root.hints file (same syntax as the BIND and Unbound root hints
|
||||||
hints file) to bootstrap domain resolution.
|
file) to bootstrap domain resolution. By default a list of builtin root
|
||||||
By default a list of builtin root hints is used.
|
hints is used. Unbound\-anchor goes to the network itself for these roots,
|
||||||
unbound\-anchor goes to the network itself for these roots, to resolve
|
to resolve the server (\-u option) and to check the root DNSKEY records.
|
||||||
the server (\fI\%\-u\fP option) and to check the root DNSKEY records.
|
|
||||||
It does so, because the tool when used for bootstrapping the recursive
|
It does so, because the tool when used for bootstrapping the recursive
|
||||||
resolver, cannot use that recursive resolver itself because it is
|
resolver, cannot use that recursive resolver itself because it is bootstrapping
|
||||||
bootstrapping that server.
|
that server.
|
||||||
.UNINDENT
|
|
||||||
.INDENT 0.0
|
|
||||||
.TP
|
.TP
|
||||||
.B \-R
|
.B \-R
|
||||||
Allow fallback from \fI\%\-f\fP \fB<resolv.conf>\fP file to direct root
|
Allow fallback from \-f resolv.conf file to direct root servers query.
|
||||||
servers query.
|
It allows you to prefer local resolvers, but fallback automatically
|
||||||
It allows you to prefer local resolvers, but fallback automatically to
|
to direct root query if they do not respond or do not support DNSSEC.
|
||||||
direct root query if they do not respond or do not support DNSSEC.
|
|
||||||
.UNINDENT
|
|
||||||
.INDENT 0.0
|
|
||||||
.TP
|
.TP
|
||||||
.B \-v
|
.B \-v
|
||||||
More verbose.
|
More verbose. Once prints informational messages, multiple times may enable
|
||||||
Once prints informational messages, multiple times may enable large
|
large debug amounts (such as full certificates or byte\-dumps of downloaded
|
||||||
debug amounts (such as full certificates or byte\-dumps of downloaded
|
files). By default it prints almost nothing. It also prints nothing on
|
||||||
files).
|
errors by default; in that case the original root anchor file is simply
|
||||||
By default it prints almost nothing.
|
left undisturbed, so that a recursive server can start right after it.
|
||||||
It also prints nothing on errors by default; in that case the original
|
|
||||||
root anchor file is simply left undisturbed, so that a recursive server
|
|
||||||
can start right after it.
|
|
||||||
.UNINDENT
|
|
||||||
.INDENT 0.0
|
|
||||||
.TP
|
.TP
|
||||||
.B \-C <unbound.conf>
|
.B \-C \fIunbound.conf
|
||||||
Debug option to read \fB<unbound.conf>\fP into the resolver process
|
Debug option to read unbound.conf into the resolver process used.
|
||||||
used.
|
|
||||||
.UNINDENT
|
|
||||||
.INDENT 0.0
|
|
||||||
.TP
|
.TP
|
||||||
.B \-P <port>
|
.B \-P \fIport
|
||||||
Set the port number to use for the https connection.
|
Set the port number to use for the https connection. The default is 443.
|
||||||
The default is 443.
|
|
||||||
.UNINDENT
|
|
||||||
.INDENT 0.0
|
|
||||||
.TP
|
.TP
|
||||||
.B \-F
|
.B \-F
|
||||||
Debug option to force update of the root anchor through downloading the
|
Debug option to force update of the root anchor through downloading the xml
|
||||||
xml file and verifying it with the certificate.
|
file and verifying it with the certificate. By default it first tries to
|
||||||
By default it first tries to update by contacting the DNS, which uses
|
update by contacting the DNS, which uses much less bandwidth, is much
|
||||||
much less bandwidth, is much faster (200 msec not 2 sec), and is nicer
|
faster (200 msec not 2 sec), and is nicer to the deployed infrastructure.
|
||||||
to the deployed infrastructure.
|
With this option, it still attempts to do so (and may verbosely tell you),
|
||||||
With this option, it still attempts to do so (and may verbosely tell
|
but then ignores the result and goes on to use the xml fallback method.
|
||||||
you), but then ignores the result and goes on to use the xml fallback
|
|
||||||
method.
|
|
||||||
.UNINDENT
|
|
||||||
.INDENT 0.0
|
|
||||||
.TP
|
.TP
|
||||||
.B \-h
|
.B \-h
|
||||||
Show the version and commandline option help.
|
Show the version and commandline option help.
|
||||||
.UNINDENT
|
.SH "EXIT CODE"
|
||||||
.SH EXIT CODE
|
|
||||||
.sp
|
|
||||||
This tool exits with value 1 if the root anchor was updated using the
|
This tool exits with value 1 if the root anchor was updated using the
|
||||||
certificate or if the builtin root\-anchor was used.
|
certificate or if the builtin root-anchor was used. It exits with code
|
||||||
It exits with code 0 if no update was necessary, if the update was possible
|
0 if no update was necessary, if the update was possible with RFC5011
|
||||||
with \fI\%RFC 5011\fP tracking, or if an error occurred.
|
tracking, or if an error occurred.
|
||||||
.sp
|
.P
|
||||||
You can check the exit value in this manner:
|
You can check the exit value in this manner:
|
||||||
.INDENT 0.0
|
|
||||||
.INDENT 3.5
|
|
||||||
.sp
|
|
||||||
.nf
|
.nf
|
||||||
.ft C
|
unbound-anchor \-a "root.key" || logger "Please check root.key"
|
||||||
unbound\-anchor \-a \(dqroot.key\(dq || logger \(dqPlease check root.key\(dq
|
|
||||||
.ft P
|
|
||||||
.fi
|
.fi
|
||||||
.UNINDENT
|
|
||||||
.UNINDENT
|
|
||||||
.sp
|
|
||||||
Or something more suitable for your operational environment.
|
Or something more suitable for your operational environment.
|
||||||
.SH TRUST
|
.SH "TRUST"
|
||||||
.sp
|
The root keys and update certificate included in this tool
|
||||||
The root keys and update certificate included in this tool are provided for
|
are provided for convenience and under the terms of our
|
||||||
convenience and under the terms of our license (see the LICENSE file in the
|
license (see the LICENSE file in the source distribution or
|
||||||
source distribution or \fI\%https://github.com/NLnetLabs/unbound/blob/master/LICENSE\fP
|
https://github.com/NLnetLabs/unbound/blob/master/LICENSE) and might be stale or
|
||||||
and might be stale or not suitable to your purpose.
|
not suitable to your purpose.
|
||||||
.sp
|
.P
|
||||||
By running \fI\%unbound\-anchor \-l\fP the keys and certificate that are
|
By running "unbound\-anchor \-l" the keys and certificate that are
|
||||||
configured in the code are printed for your convenience.
|
configured in the code are printed for your convenience.
|
||||||
.sp
|
.P
|
||||||
The built\-in configuration can be overridden by providing a root\-cert file and
|
The build\-in configuration can be overridden by providing a root\-cert
|
||||||
a rootkey file.
|
file and a rootkey file.
|
||||||
.SH FILES
|
.SH "FILES"
|
||||||
.INDENT 0.0
|
|
||||||
.TP
|
.TP
|
||||||
.B @UNBOUND_ROOTKEY_FILE@
|
.I @UNBOUND_ROOTKEY_FILE@
|
||||||
The root anchor file, updated with 5011 tracking, and read and written
|
The root anchor file, updated with 5011 tracking, and read and written to.
|
||||||
to.
|
|
||||||
The file is created if it does not exist.
|
The file is created if it does not exist.
|
||||||
.TP
|
.TP
|
||||||
.B @UNBOUND_ROOTCERT_FILE@
|
.I @UNBOUND_ROOTCERT_FILE@
|
||||||
The trusted self\-signed certificate that is used to verify the
|
The trusted self\-signed certificate that is used to verify the downloaded
|
||||||
downloaded DNSSEC root trust anchor.
|
DNSSEC root trust anchor. You can update it by fetching it from
|
||||||
You can update it by fetching it from
|
https://data.iana.org/root\-anchors/icannbundle.pem (and validate it).
|
||||||
\fI\%https://data.iana.org/root\-anchors/icannbundle.pem\fP (and validate it).
|
|
||||||
If the file does not exist or is empty, a builtin version is used.
|
If the file does not exist or is empty, a builtin version is used.
|
||||||
.TP
|
.TP
|
||||||
.B \fI\%https://data.iana.org/root\-anchors/root\-anchors.xml\fP
|
.I https://data.iana.org/root\-anchors/root\-anchors.xml
|
||||||
Source for the root key information.
|
Source for the root key information.
|
||||||
.TP
|
.TP
|
||||||
.B \fI\%https://data.iana.org/root\-anchors/root\-anchors.p7s\fP
|
.I https://data.iana.org/root\-anchors/root\-anchors.p7s
|
||||||
Signature on the root key information.
|
Signature on the root key information.
|
||||||
.UNINDENT
|
.SH "SEE ALSO"
|
||||||
.SH SEE ALSO
|
\fIunbound.conf\fR(5),
|
||||||
.sp
|
\fIunbound\fR(8).
|
||||||
\fI\%unbound.conf(5)\fP,
|
|
||||||
\fI\%unbound(8)\fP\&.
|
|
||||||
.SH AUTHOR
|
|
||||||
Unbound developers are mentioned in the CREDITS file in the distribution.
|
|
||||||
.SH COPYRIGHT
|
|
||||||
1999-2026, NLnet Labs
|
|
||||||
.\" Generated by docutils manpage writer.
|
|
||||||
.
|
|
||||||
|
|||||||
@@ -1,290 +0,0 @@
|
|||||||
..
|
|
||||||
WHEN EDITING MAKE SURE EACH SENTENCE STARTS ON A NEW LINE
|
|
||||||
|
|
||||||
..
|
|
||||||
IT HELPS RENDERERS TO DO THE RIGHT THING WRT SPACE
|
|
||||||
|
|
||||||
..
|
|
||||||
IT HELPS PEOPLE DIFFING THE CHANGES
|
|
||||||
|
|
||||||
..
|
|
||||||
WHEN EDITING MAKE SURE EACH SENTENCE STARTS ON A NEW LINE
|
|
||||||
|
|
||||||
..
|
|
||||||
IT HELPS RENDERERS TO DO THE RIGHT THING WRT SPACE
|
|
||||||
|
|
||||||
..
|
|
||||||
IT HELPS PEOPLE DIFFING THE CHANGES
|
|
||||||
|
|
||||||
..
|
|
||||||
WHEN EDITING MAKE SURE EACH SENTENCE STARTS ON A NEW LINE
|
|
||||||
|
|
||||||
..
|
|
||||||
IT HELPS RENDERERS TO DO THE RIGHT THING WRT SPACE
|
|
||||||
|
|
||||||
..
|
|
||||||
IT HELPS PEOPLE DIFFING THE CHANGES
|
|
||||||
|
|
||||||
..
|
|
||||||
WHEN EDITING MAKE SURE EACH SENTENCE STARTS ON A NEW LINE
|
|
||||||
|
|
||||||
..
|
|
||||||
IT HELPS RENDERERS TO DO THE RIGHT THING WRT SPACE
|
|
||||||
|
|
||||||
..
|
|
||||||
IT HELPS PEOPLE DIFFING THE CHANGES
|
|
||||||
|
|
||||||
.. program:: unbound-anchor
|
|
||||||
|
|
||||||
unbound-anchor(8)
|
|
||||||
=================
|
|
||||||
|
|
||||||
Synopsis
|
|
||||||
--------
|
|
||||||
|
|
||||||
**unbound-anchor** [``opts``]
|
|
||||||
|
|
||||||
Description
|
|
||||||
-----------
|
|
||||||
|
|
||||||
``unbound-anchor`` performs setup or update of the root trust anchor for DNSSEC
|
|
||||||
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.
|
|
||||||
|
|
||||||
Suggested usage:
|
|
||||||
|
|
||||||
.. code-block:: text
|
|
||||||
|
|
||||||
# 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).
|
|
||||||
#
|
|
||||||
# start validating resolver
|
|
||||||
# the unbound.conf contains:
|
|
||||||
# auto-trust-anchor-file: "@UNBOUND_ROOTKEY_FILE@"
|
|
||||||
unbound -c unbound.conf
|
|
||||||
|
|
||||||
This tool provides builtin default contents for the root anchor and root update
|
|
||||||
certificate files.
|
|
||||||
|
|
||||||
It tests if the root anchor file works, and if not, and an update is possible,
|
|
||||||
attempts to update the root anchor using the root update certificate.
|
|
||||||
It performs a https fetch of
|
|
||||||
`root-anchors.xml <http://data.iana.org/root-anchors/root-anchors.xml>`__
|
|
||||||
and checks the results (:rfc:`7958`); if all checks are successful, it updates
|
|
||||||
the root anchor file.
|
|
||||||
Otherwise the root anchor file is unchanged.
|
|
||||||
It performs :rfc:`5011` tracking if the DNSSEC information available via the
|
|
||||||
DNS makes that possible.
|
|
||||||
|
|
||||||
It does not perform an update if the certificate is expired, if the network is
|
|
||||||
down or other errors occur.
|
|
||||||
|
|
||||||
The available options are:
|
|
||||||
|
|
||||||
.. option:: -a <file>
|
|
||||||
|
|
||||||
The root anchor key file, that is read in and written out.
|
|
||||||
Default is :file:`@UNBOUND_ROOTKEY_FILE@`.
|
|
||||||
If the file does not exist, or is empty, a builtin root key is written
|
|
||||||
to it.
|
|
||||||
|
|
||||||
.. option:: -c <file>
|
|
||||||
|
|
||||||
The root update certificate file, that is read in.
|
|
||||||
Default is :file:`@UNBOUND_ROOTCERT_FILE@`.
|
|
||||||
If the file does not exist, or is empty, a builtin certificate is used.
|
|
||||||
|
|
||||||
.. option:: -l
|
|
||||||
|
|
||||||
List the builtin root key and builtin root update certificate on stdout.
|
|
||||||
|
|
||||||
.. option:: -u <name>
|
|
||||||
|
|
||||||
The server name, it connects to ``https://name``.
|
|
||||||
Specify without ``https://`` prefix.
|
|
||||||
The default is ``"data.iana.org"``.
|
|
||||||
It connects to the port specified with :option:`-P`.
|
|
||||||
You can pass an IPv4 address or IPv6 address (no brackets) if you want.
|
|
||||||
|
|
||||||
.. option:: -S
|
|
||||||
|
|
||||||
Do not use SNI for the HTTPS connection.
|
|
||||||
Default is to use SNI.
|
|
||||||
|
|
||||||
.. option:: -b <address>
|
|
||||||
|
|
||||||
The source address to bind to for domain resolution and contacting the
|
|
||||||
server on https.
|
|
||||||
May be either an IPv4 address or IPv6 address (no brackets).
|
|
||||||
|
|
||||||
.. option:: -x <path>
|
|
||||||
|
|
||||||
The pathname to the root-anchors.xml file on the server.
|
|
||||||
(forms URL with :option:`-u`).
|
|
||||||
The default is :file:`/root-anchors/root-anchors.xml`.
|
|
||||||
|
|
||||||
.. option:: -s <path>
|
|
||||||
|
|
||||||
The pathname to the root-anchors.p7s file on the server.
|
|
||||||
(forms URL with :option:`-u`).
|
|
||||||
The default is :file:`/root-anchors/root-anchors.p7s`.
|
|
||||||
This file has to be a PKCS7 signature over the xml file, using the pem
|
|
||||||
file (:option:`-c`) as trust anchor.
|
|
||||||
|
|
||||||
.. option:: -n <name>
|
|
||||||
|
|
||||||
The emailAddress for the Subject of the signer's certificate from the
|
|
||||||
p7s signature file.
|
|
||||||
Only signatures from this name are allowed.
|
|
||||||
The default is ``dnssec@iana.org``.
|
|
||||||
If you pass ``""`` then the emailAddress is not checked.
|
|
||||||
|
|
||||||
.. option:: -4
|
|
||||||
|
|
||||||
Use IPv4 for domain resolution and contacting the server on
|
|
||||||
https.
|
|
||||||
Default is to use IPv4 and IPv6 where appropriate.
|
|
||||||
|
|
||||||
.. option:: -6
|
|
||||||
|
|
||||||
Use IPv6 for domain resolution and contacting the server on https.
|
|
||||||
Default is to use IPv4 and IPv6 where appropriate.
|
|
||||||
|
|
||||||
.. option:: -f <resolv.conf>
|
|
||||||
|
|
||||||
Use the given resolv.conf file.
|
|
||||||
Not enabled by default, but you could try to pass
|
|
||||||
:file:`/etc/resolv.conf` on some systems.
|
|
||||||
It contains the IP addresses of the recursive nameservers to use.
|
|
||||||
However, since this tool could be used to bootstrap that very recursive
|
|
||||||
nameserver, it would not be useful (since that server is not up yet,
|
|
||||||
since we are bootstrapping it).
|
|
||||||
It could be useful in a situation where you know an upstream cache is
|
|
||||||
deployed (and running) and in captive portal situations.
|
|
||||||
|
|
||||||
.. option:: -r <root.hints>
|
|
||||||
|
|
||||||
Use the given root.hints file (same syntax as the BIND and Unbound root
|
|
||||||
hints file) to bootstrap domain resolution.
|
|
||||||
By default a list of builtin root hints is used.
|
|
||||||
unbound-anchor goes to the network itself for these roots, to resolve
|
|
||||||
the server (:option:`-u` option) and to check the root DNSKEY records.
|
|
||||||
It does so, because the tool when used for bootstrapping the recursive
|
|
||||||
resolver, cannot use that recursive resolver itself because it is
|
|
||||||
bootstrapping that server.
|
|
||||||
|
|
||||||
.. option:: -R
|
|
||||||
|
|
||||||
Allow fallback from :option:`-f` ``<resolv.conf>`` file to direct root
|
|
||||||
servers query.
|
|
||||||
It allows you to prefer local resolvers, but fallback automatically to
|
|
||||||
direct root query if they do not respond or do not support DNSSEC.
|
|
||||||
|
|
||||||
.. option:: -v
|
|
||||||
|
|
||||||
More verbose.
|
|
||||||
Once prints informational messages, multiple times may enable large
|
|
||||||
debug amounts (such as full certificates or byte-dumps of downloaded
|
|
||||||
files).
|
|
||||||
By default it prints almost nothing.
|
|
||||||
It also prints nothing on errors by default; in that case the original
|
|
||||||
root anchor file is simply left undisturbed, so that a recursive server
|
|
||||||
can start right after it.
|
|
||||||
|
|
||||||
.. option:: -C <unbound.conf>
|
|
||||||
|
|
||||||
Debug option to read :file:`<unbound.conf>` into the resolver process
|
|
||||||
used.
|
|
||||||
|
|
||||||
.. option:: -P <port>
|
|
||||||
|
|
||||||
Set the port number to use for the https connection.
|
|
||||||
The default is 443.
|
|
||||||
|
|
||||||
.. option:: -F
|
|
||||||
|
|
||||||
Debug option to force update of the root anchor through downloading the
|
|
||||||
xml file and verifying it with the certificate.
|
|
||||||
By default it first tries to update by contacting the DNS, which uses
|
|
||||||
much less bandwidth, is much faster (200 msec not 2 sec), and is nicer
|
|
||||||
to the deployed infrastructure.
|
|
||||||
With this option, it still attempts to do so (and may verbosely tell
|
|
||||||
you), but then ignores the result and goes on to use the xml fallback
|
|
||||||
method.
|
|
||||||
|
|
||||||
.. option:: -h
|
|
||||||
|
|
||||||
Show the version and commandline option help.
|
|
||||||
|
|
||||||
Exit Code
|
|
||||||
---------
|
|
||||||
|
|
||||||
This tool exits with value 1 if the root anchor was updated using the
|
|
||||||
certificate or if the builtin root-anchor was used.
|
|
||||||
It exits with code 0 if no update was necessary, if the update was possible
|
|
||||||
with :rfc:`5011` tracking, or if an error occurred.
|
|
||||||
|
|
||||||
You can check the exit value in this manner:
|
|
||||||
|
|
||||||
.. code-block:: text
|
|
||||||
|
|
||||||
unbound-anchor -a "root.key" || logger "Please check root.key"
|
|
||||||
|
|
||||||
Or something more suitable for your operational environment.
|
|
||||||
|
|
||||||
Trust
|
|
||||||
-----
|
|
||||||
|
|
||||||
The root keys and update certificate included in this tool are provided for
|
|
||||||
convenience and under the terms of our license (see the LICENSE file in the
|
|
||||||
source distribution or https://github.com/NLnetLabs/unbound/blob/master/LICENSE
|
|
||||||
and might be stale or not suitable to your purpose.
|
|
||||||
|
|
||||||
By running :option:`unbound-anchor -l` the keys and certificate that are
|
|
||||||
configured in the code are printed for your convenience.
|
|
||||||
|
|
||||||
The built-in configuration can be overridden by providing a root-cert file and
|
|
||||||
a rootkey file.
|
|
||||||
|
|
||||||
Files
|
|
||||||
-----
|
|
||||||
|
|
||||||
@UNBOUND_ROOTKEY_FILE@
|
|
||||||
The root anchor file, updated with 5011 tracking, and read and written
|
|
||||||
to.
|
|
||||||
The file is created if it does not exist.
|
|
||||||
|
|
||||||
@UNBOUND_ROOTCERT_FILE@
|
|
||||||
The trusted self-signed certificate that is used to verify the
|
|
||||||
downloaded DNSSEC root trust anchor.
|
|
||||||
You can update it by fetching it from
|
|
||||||
https://data.iana.org/root-anchors/icannbundle.pem (and validate it).
|
|
||||||
If the file does not exist or is empty, a builtin version is used.
|
|
||||||
|
|
||||||
https://data.iana.org/root-anchors/root-anchors.xml
|
|
||||||
Source for the root key information.
|
|
||||||
|
|
||||||
https://data.iana.org/root-anchors/root-anchors.p7s
|
|
||||||
Signature on the root key information.
|
|
||||||
|
|
||||||
See Also
|
|
||||||
--------
|
|
||||||
|
|
||||||
:doc:`unbound.conf(5)</manpages/unbound.conf>`,
|
|
||||||
:doc:`unbound(8)</manpages/unbound>`.
|
|
||||||
+39
-80
@@ -1,93 +1,52 @@
|
|||||||
.\" Man page generated from reStructuredText.
|
.TH "unbound-checkconf" "8" "@date@" "NLnet Labs" "unbound @version@"
|
||||||
.
|
.\"
|
||||||
.
|
.\" unbound-checkconf.8 -- unbound configuration checker manual
|
||||||
.nr rst2man-indent-level 0
|
.\"
|
||||||
.
|
.\" Copyright (c) 2007, NLnet Labs. All rights reserved.
|
||||||
.de1 rstReportMargin
|
.\"
|
||||||
\\$1 \\n[an-margin]
|
.\" See LICENSE for the license.
|
||||||
level \\n[rst2man-indent-level]
|
.\"
|
||||||
level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
.\"
|
||||||
-
|
.SH "NAME"
|
||||||
\\n[rst2man-indent0]
|
unbound\-checkconf
|
||||||
\\n[rst2man-indent1]
|
\- Check Unbound configuration file for errors.
|
||||||
\\n[rst2man-indent2]
|
.SH "SYNOPSIS"
|
||||||
..
|
.B unbound\-checkconf
|
||||||
.de1 INDENT
|
.RB [ \-h ]
|
||||||
.\" .rstReportMargin pre:
|
.RB [ \-f ]
|
||||||
. RS \\$1
|
.RB [ \-o
|
||||||
. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
|
.IR option ]
|
||||||
. nr rst2man-indent-level +1
|
.RI [ cfgfile ]
|
||||||
.\" .rstReportMargin post:
|
.SH "DESCRIPTION"
|
||||||
..
|
.B Unbound\-checkconf
|
||||||
.de UNINDENT
|
checks the configuration file for the
|
||||||
. RE
|
\fIunbound\fR(8)
|
||||||
.\" indent \\n[an-margin]
|
DNS resolver for syntax and other errors.
|
||||||
.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
|
||||||
.nr rst2man-indent-level -1
|
|
||||||
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
|
||||||
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
|
|
||||||
..
|
|
||||||
.TH "UNBOUND-CHECKCONF" "8" "@date@" "@version@" "Unbound"
|
|
||||||
.SH NAME
|
|
||||||
unbound-checkconf \- Check Unbound @version@ configuration file for errors.
|
|
||||||
.SH SYNOPSIS
|
|
||||||
.sp
|
|
||||||
\fBunbound\-checkconf\fP [\fB\-hf\fP] [\fB\-o option\fP] [cfgfile]
|
|
||||||
.SH DESCRIPTION
|
|
||||||
.sp
|
|
||||||
\fBunbound\-checkconf\fP checks the configuration file for the
|
|
||||||
\fI\%unbound(8)\fP DNS resolver for syntax and other errors.
|
|
||||||
The config file syntax is described in
|
The config file syntax is described in
|
||||||
\fI\%unbound.conf(5)\fP\&.
|
\fIunbound.conf\fR(5).
|
||||||
.sp
|
.P
|
||||||
The available options are:
|
The available options are:
|
||||||
.INDENT 0.0
|
|
||||||
.TP
|
.TP
|
||||||
.B \-h
|
.B \-h
|
||||||
Show the version and commandline option help.
|
Show the version and commandline option help.
|
||||||
.UNINDENT
|
|
||||||
.INDENT 0.0
|
|
||||||
.TP
|
.TP
|
||||||
.B \-f
|
.B \-f
|
||||||
Print full pathname, with chroot applied to it.
|
Print full pathname, with chroot applied to it. Use with the \-o option.
|
||||||
Use with the \fI\%\-o\fP option.
|
|
||||||
.UNINDENT
|
|
||||||
.INDENT 0.0
|
|
||||||
.TP
|
.TP
|
||||||
.B \-q
|
.B \-o\fI option
|
||||||
Make the operation quiet, suppress output on success.
|
|
||||||
.UNINDENT
|
|
||||||
.INDENT 0.0
|
|
||||||
.TP
|
|
||||||
.B \-o <option>
|
|
||||||
If given, after checking the config file the value of this option is
|
If given, after checking the config file the value of this option is
|
||||||
printed to stdout.
|
printed to stdout. For "" (disabled) options an empty line is printed.
|
||||||
For \fB\(dq\(dq\fP (disabled) options an empty line is printed.
|
|
||||||
.UNINDENT
|
|
||||||
.INDENT 0.0
|
|
||||||
.TP
|
.TP
|
||||||
.B cfgfile
|
.I cfgfile
|
||||||
The config file to read with settings for Unbound.
|
The config file to read with settings for Unbound. It is checked.
|
||||||
It is checked.
|
|
||||||
If omitted, the config file at the default location is checked.
|
If omitted, the config file at the default location is checked.
|
||||||
.UNINDENT
|
.SH "EXIT CODE"
|
||||||
.SH EXIT CODE
|
The unbound\-checkconf program exits with status code 1 on error,
|
||||||
.sp
|
0 for a correct config file.
|
||||||
The \fBunbound\-checkconf\fP program exits with status code 1 on error, 0 for a
|
.SH "FILES"
|
||||||
correct config file.
|
|
||||||
.SH FILES
|
|
||||||
.INDENT 0.0
|
|
||||||
.TP
|
.TP
|
||||||
.B @ub_conf_file@
|
.I @ub_conf_file@
|
||||||
Unbound configuration file.
|
Unbound configuration file.
|
||||||
.UNINDENT
|
.SH "SEE ALSO"
|
||||||
.SH SEE ALSO
|
\fIunbound.conf\fR(5),
|
||||||
.sp
|
\fIunbound\fR(8).
|
||||||
\fI\%unbound.conf(5)\fP,
|
|
||||||
\fI\%unbound(8)\fP\&.
|
|
||||||
.SH AUTHOR
|
|
||||||
Unbound developers are mentioned in the CREDITS file in the distribution.
|
|
||||||
.SH COPYRIGHT
|
|
||||||
1999-2026, NLnet Labs
|
|
||||||
.\" Generated by docutils manpage writer.
|
|
||||||
.
|
|
||||||
|
|||||||
@@ -1,98 +0,0 @@
|
|||||||
..
|
|
||||||
WHEN EDITING MAKE SURE EACH SENTENCE STARTS ON A NEW LINE
|
|
||||||
|
|
||||||
..
|
|
||||||
IT HELPS RENDERERS TO DO THE RIGHT THING WRT SPACE
|
|
||||||
|
|
||||||
..
|
|
||||||
IT HELPS PEOPLE DIFFING THE CHANGES
|
|
||||||
|
|
||||||
..
|
|
||||||
WHEN EDITING MAKE SURE EACH SENTENCE STARTS ON A NEW LINE
|
|
||||||
|
|
||||||
..
|
|
||||||
IT HELPS RENDERERS TO DO THE RIGHT THING WRT SPACE
|
|
||||||
|
|
||||||
..
|
|
||||||
IT HELPS PEOPLE DIFFING THE CHANGES
|
|
||||||
|
|
||||||
..
|
|
||||||
WHEN EDITING MAKE SURE EACH SENTENCE STARTS ON A NEW LINE
|
|
||||||
|
|
||||||
..
|
|
||||||
IT HELPS RENDERERS TO DO THE RIGHT THING WRT SPACE
|
|
||||||
|
|
||||||
..
|
|
||||||
IT HELPS PEOPLE DIFFING THE CHANGES
|
|
||||||
|
|
||||||
..
|
|
||||||
WHEN EDITING MAKE SURE EACH SENTENCE STARTS ON A NEW LINE
|
|
||||||
|
|
||||||
..
|
|
||||||
IT HELPS RENDERERS TO DO THE RIGHT THING WRT SPACE
|
|
||||||
|
|
||||||
..
|
|
||||||
IT HELPS PEOPLE DIFFING THE CHANGES
|
|
||||||
|
|
||||||
.. program:: unbound-checkconf
|
|
||||||
|
|
||||||
unbound-checkconf(8)
|
|
||||||
====================
|
|
||||||
|
|
||||||
Synopsis
|
|
||||||
--------
|
|
||||||
|
|
||||||
**unbound-checkconf** [``-hf``] [``-o option``] [cfgfile]
|
|
||||||
|
|
||||||
Description
|
|
||||||
-----------
|
|
||||||
|
|
||||||
``unbound-checkconf`` checks the configuration file for the
|
|
||||||
:doc:`unbound(8)</manpages/unbound>` DNS resolver for syntax and other errors.
|
|
||||||
The config file syntax is described in
|
|
||||||
:doc:`unbound.conf(5)</manpages/unbound.conf>`.
|
|
||||||
|
|
||||||
The available options are:
|
|
||||||
|
|
||||||
.. option:: -h
|
|
||||||
|
|
||||||
Show the version and commandline option help.
|
|
||||||
|
|
||||||
.. option:: -f
|
|
||||||
|
|
||||||
Print full pathname, with chroot applied to it.
|
|
||||||
Use with the :option:`-o` option.
|
|
||||||
|
|
||||||
.. option:: -q
|
|
||||||
|
|
||||||
Make the operation quiet, suppress output on success.
|
|
||||||
|
|
||||||
.. option:: -o <option>
|
|
||||||
|
|
||||||
If given, after checking the config file the value of this option is
|
|
||||||
printed to stdout.
|
|
||||||
For ``""`` (disabled) options an empty line is printed.
|
|
||||||
|
|
||||||
.. option:: cfgfile
|
|
||||||
|
|
||||||
The config file to read with settings for Unbound.
|
|
||||||
It is checked.
|
|
||||||
If omitted, the config file at the default location is checked.
|
|
||||||
|
|
||||||
Exit Code
|
|
||||||
---------
|
|
||||||
|
|
||||||
The ``unbound-checkconf`` program exits with status code 1 on error, 0 for a
|
|
||||||
correct config file.
|
|
||||||
|
|
||||||
Files
|
|
||||||
-----
|
|
||||||
|
|
||||||
@ub_conf_file@
|
|
||||||
Unbound configuration file.
|
|
||||||
|
|
||||||
See Also
|
|
||||||
--------
|
|
||||||
|
|
||||||
:doc:`unbound.conf(5)</manpages/unbound.conf>`,
|
|
||||||
:doc:`unbound(8)</manpages/unbound>`.
|
|
||||||
+417
-1301
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
+85
-157
@@ -1,190 +1,118 @@
|
|||||||
.\" Man page generated from reStructuredText.
|
.TH "unbound\-host" "1" "@date@" "NLnet Labs" "unbound @version@"
|
||||||
.
|
.\"
|
||||||
.
|
.\" unbound-host.1 -- unbound DNS lookup utility
|
||||||
.nr rst2man-indent-level 0
|
.\"
|
||||||
.
|
.\" Copyright (c) 2007, NLnet Labs. All rights reserved.
|
||||||
.de1 rstReportMargin
|
.\"
|
||||||
\\$1 \\n[an-margin]
|
.\" See LICENSE for the license.
|
||||||
level \\n[rst2man-indent-level]
|
.\"
|
||||||
level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
.\"
|
||||||
-
|
.SH "NAME"
|
||||||
\\n[rst2man-indent0]
|
.B unbound\-host
|
||||||
\\n[rst2man-indent1]
|
\- unbound DNS lookup utility
|
||||||
\\n[rst2man-indent2]
|
.SH "SYNOPSIS"
|
||||||
..
|
.B unbound\-host
|
||||||
.de1 INDENT
|
.RB [ \-C
|
||||||
.\" .rstReportMargin pre:
|
.IR configfile ]
|
||||||
. RS \\$1
|
.RB [ \-vdhr46D ]
|
||||||
. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
|
.RB [ \-c
|
||||||
. nr rst2man-indent-level +1
|
.IR class ]
|
||||||
.\" .rstReportMargin post:
|
.RB [ \-t
|
||||||
..
|
.IR type ]
|
||||||
.de UNINDENT
|
.RB [ \-y
|
||||||
. RE
|
.IR key ]
|
||||||
.\" indent \\n[an-margin]
|
.RB [ \-f
|
||||||
.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
.IR keyfile ]
|
||||||
.nr rst2man-indent-level -1
|
.RB [ \-F
|
||||||
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
.IR namedkeyfile ]
|
||||||
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
|
.I hostname
|
||||||
..
|
.SH "DESCRIPTION"
|
||||||
.TH "UNBOUND-HOST" "1" "@date@" "@version@" "Unbound"
|
.B Unbound\-host
|
||||||
.SH NAME
|
uses the Unbound validating resolver to query for the hostname and display
|
||||||
unbound-host \- Unbound @version@ DNS lookup utility.
|
results. With the \fB\-v\fR option it displays validation
|
||||||
.SH SYNOPSIS
|
status: secure, insecure, bogus (security failure).
|
||||||
.sp
|
.P
|
||||||
\fBunbound\-host\fP [\fB\-C configfile\fP] [\fB\-vdhr46D\fP] [\fB\-c class\fP]
|
By default it reads no configuration file whatsoever. It attempts to reach
|
||||||
[\fB\-t type\fP] [\fB\-y key\fP] [\fB\-f keyfile\fP] [\fB\-F namedkeyfile\fP] hostname
|
the internet root servers. With \fB\-C\fR an Unbound config file and with
|
||||||
.SH DESCRIPTION
|
\fB\-r\fR resolv.conf can be read.
|
||||||
.sp
|
.P
|
||||||
\fBunbound\-host\fP uses the Unbound validating resolver to query for the hostname
|
|
||||||
and display results.
|
|
||||||
With the \fI\%\-v\fP option it displays validation status: secure, insecure,
|
|
||||||
bogus (security failure).
|
|
||||||
.sp
|
|
||||||
By default it reads no configuration file whatsoever.
|
|
||||||
It attempts to reach the internet root servers.
|
|
||||||
With \fI\%\-C\fP an unbound config file and with \fI\%\-r\fP \fBresolv.conf\fP
|
|
||||||
can be read.
|
|
||||||
.sp
|
|
||||||
The available options are:
|
The available options are:
|
||||||
.INDENT 0.0
|
|
||||||
.TP
|
.TP
|
||||||
.B hostname
|
.I hostname
|
||||||
This name is resolved (looked up in the DNS).
|
This name is resolved (looked up in the DNS).
|
||||||
If a IPv4 or IPv6 address is given, a reverse lookup is performed.
|
If a IPv4 or IPv6 address is given, a reverse lookup is performed.
|
||||||
.UNINDENT
|
|
||||||
.INDENT 0.0
|
|
||||||
.TP
|
.TP
|
||||||
.B \-h
|
.B \-h
|
||||||
Show the version and commandline option help.
|
Show the version and commandline option help.
|
||||||
.UNINDENT
|
|
||||||
.INDENT 0.0
|
|
||||||
.TP
|
.TP
|
||||||
.B \-v
|
.B \-v
|
||||||
Enable verbose output and it shows validation results, on every line.
|
Enable verbose output and it shows validation results, on every line.
|
||||||
Secure means that the NXDOMAIN (no such domain name), nodata (no such
|
Secure means that the NXDOMAIN (no such domain name), nodata (no such data)
|
||||||
data) or positive data response validated correctly with one of the
|
or positive data response validated correctly with one of the keys.
|
||||||
keys.
|
|
||||||
Insecure means that that domain name has no security set up for it.
|
Insecure means that that domain name has no security set up for it.
|
||||||
Bogus (security failure) means that the response failed one or more
|
Bogus (security failure) means that the response failed one or more checks,
|
||||||
checks, it is likely wrong, outdated, tampered with, or broken.
|
it is likely wrong, outdated, tampered with, or broken.
|
||||||
.UNINDENT
|
|
||||||
.INDENT 0.0
|
|
||||||
.TP
|
.TP
|
||||||
.B \-d
|
.B \-d
|
||||||
Enable debug output to stderr.
|
Enable debug output to stderr. One \-d shows what the resolver and validator
|
||||||
One \fI\%\-d\fP shows what the resolver and validator are doing and may
|
are doing and may tell you what is going on. More times, \-d \-d, gives a
|
||||||
tell you what is going on.
|
lot of output, with every packet sent and received.
|
||||||
More times, \fI\%\-d\fP \fI\%\-d\fP, gives a lot of output, with every
|
|
||||||
packet sent and received.
|
|
||||||
.UNINDENT
|
|
||||||
.INDENT 0.0
|
|
||||||
.TP
|
.TP
|
||||||
.B \-c <class>
|
.B \-c \fIclass
|
||||||
Specify the class to lookup for, the default is IN the internet
|
Specify the class to lookup for, the default is IN the internet class.
|
||||||
class.
|
|
||||||
.UNINDENT
|
|
||||||
.INDENT 0.0
|
|
||||||
.TP
|
.TP
|
||||||
.B \-t <type>
|
.B \-t \fItype
|
||||||
Specify the type of data to lookup.
|
Specify the type of data to lookup. The default looks for IPv4, IPv6 and
|
||||||
The default looks for IPv4, IPv6 and mail handler data, or domain name
|
mail handler data, or domain name pointers for reverse queries.
|
||||||
pointers for reverse queries.
|
|
||||||
.UNINDENT
|
|
||||||
.INDENT 0.0
|
|
||||||
.TP
|
.TP
|
||||||
.B \-y <key>
|
.B \-y \fIkey
|
||||||
Specify a public key to use as trust anchor.
|
Specify a public key to use as trust anchor. This is the base for a chain
|
||||||
This is the base for a chain of trust that is built up from the trust
|
of trust that is built up from the trust anchor to the response, in order
|
||||||
anchor to the response, in order to validate the response message.
|
to validate the response message. Can be given as a DS or DNSKEY record.
|
||||||
Can be given as a DS or DNSKEY record.
|
For example \-y "example.com DS 31560 5 1 1CFED84787E6E19CCF9372C1187325972FE546CD".
|
||||||
For example:
|
|
||||||
.INDENT 7.0
|
|
||||||
.INDENT 3.5
|
|
||||||
.sp
|
|
||||||
.nf
|
|
||||||
.ft C
|
|
||||||
\-y \(dqexample.com DS 31560 5 1 1CFED84787E6E19CCF9372C1187325972FE546CD\(dq
|
|
||||||
.ft P
|
|
||||||
.fi
|
|
||||||
.UNINDENT
|
|
||||||
.UNINDENT
|
|
||||||
.UNINDENT
|
|
||||||
.INDENT 0.0
|
|
||||||
.TP
|
.TP
|
||||||
.B \-D
|
.B \-D
|
||||||
Enables DNSSEC validation.
|
Enables DNSSEC validation. Reads the root anchor from the default configured
|
||||||
Reads the root anchor from the default configured root anchor at the
|
root anchor at the default location, \fI@UNBOUND_ROOTKEY_FILE@\fR.
|
||||||
default location, \fB@UNBOUND_ROOTKEY_FILE@\fP\&.
|
|
||||||
.UNINDENT
|
|
||||||
.INDENT 0.0
|
|
||||||
.TP
|
.TP
|
||||||
.B \-f <keyfile>
|
.B \-f \fIkeyfile
|
||||||
Reads keys from a file.
|
Reads keys from a file. Every line has a DS or DNSKEY record, in the format
|
||||||
Every line has a DS or DNSKEY record, in the format as for \fI\%\-y\fP\&.
|
as for \-y. The zone file format, the same as dig and drill produce.
|
||||||
The zone file format, the same as \fBdig\fP and \fBdrill\fP produce.
|
|
||||||
.UNINDENT
|
|
||||||
.INDENT 0.0
|
|
||||||
.TP
|
.TP
|
||||||
.B \-F <namedkeyfile>
|
.B \-F \fInamedkeyfile
|
||||||
Reads keys from a BIND\-style \fBnamed.conf\fP file.
|
Reads keys from a BIND\-style named.conf file. Only the trusted\-key {}; entries
|
||||||
Only the \fBtrusted\-key {};\fP entries are read.
|
are read.
|
||||||
.UNINDENT
|
|
||||||
.INDENT 0.0
|
|
||||||
.TP
|
.TP
|
||||||
.B \-C <configfile>
|
.B \-C \fIconfigfile
|
||||||
Uses the specified unbound.conf to prime \fI\%libunbound(3)\fP\&.
|
Uses the specified unbound.conf to prime
|
||||||
|
.IR libunbound (3).
|
||||||
Pass it as first argument if you want to override some options from the
|
Pass it as first argument if you want to override some options from the
|
||||||
config file with further arguments on the commandline.
|
config file with further arguments on the commandline.
|
||||||
.UNINDENT
|
|
||||||
.INDENT 0.0
|
|
||||||
.TP
|
.TP
|
||||||
.B \-r
|
.B \-r
|
||||||
Read \fB/etc/resolv.conf\fP, and use the forward DNS servers from
|
Read /etc/resolv.conf, and use the forward DNS servers from there (those could
|
||||||
there (those could have been set by DHCP).
|
have been set by DHCP). More info in
|
||||||
More info in \fIresolv.conf(5)\fP\&.
|
.IR resolv.conf (5).
|
||||||
Breaks validation if those servers do not support DNSSEC.
|
Breaks validation if those servers do not support DNSSEC.
|
||||||
.UNINDENT
|
|
||||||
.INDENT 0.0
|
|
||||||
.TP
|
.TP
|
||||||
.B \-4
|
.B \-4
|
||||||
Use solely the IPv4 network for sending packets.
|
Use solely the IPv4 network for sending packets.
|
||||||
.UNINDENT
|
|
||||||
.INDENT 0.0
|
|
||||||
.TP
|
.TP
|
||||||
.B \-6
|
.B \-6
|
||||||
Use solely the IPv6 network for sending packets.
|
Use solely the IPv6 network for sending packets.
|
||||||
.UNINDENT
|
.SH "EXAMPLES"
|
||||||
.SH EXAMPLES
|
Some examples of use. The keys shown below are fakes, thus a security failure
|
||||||
.sp
|
is encountered.
|
||||||
Some examples of use.
|
.P
|
||||||
The keys shown below are fakes, thus a security failure is encountered.
|
|
||||||
.INDENT 0.0
|
|
||||||
.INDENT 3.5
|
|
||||||
.sp
|
|
||||||
.nf
|
|
||||||
.ft C
|
|
||||||
$ unbound\-host www.example.com
|
$ unbound\-host www.example.com
|
||||||
|
.P
|
||||||
$ unbound\-host \-v \-y \(dqexample.com DS 31560 5 1 1CFED84787E6E19CCF9372C1187325972FE546CD\(dq www.example.com
|
$ unbound\-host \-v \-y "example.com DS 31560 5 1 1CFED84787E6E19CCF9372C1187325972FE546CD" www.example.com
|
||||||
|
.P
|
||||||
$ unbound\-host \-v \-y \(dqexample.com DS 31560 5 1 1CFED84787E6E19CCF9372C1187325972FE546CD\(dq 192.0.2.153
|
$ unbound\-host \-v \-y "example.com DS 31560 5 1 1CFED84787E6E19CCF9372C1187325972FE546CD" 192.0.2.153
|
||||||
.ft P
|
.SH "EXIT CODE"
|
||||||
.fi
|
The unbound\-host program exits with status code 1 on error,
|
||||||
.UNINDENT
|
0 on no error. The data may not be available on exit code 0, exit code 1
|
||||||
.UNINDENT
|
means the lookup encountered a fatal error.
|
||||||
.SH EXIT CODE
|
.SH "SEE ALSO"
|
||||||
.sp
|
\fIunbound.conf\fR(5),
|
||||||
The \fBunbound\-host\fP program exits with status code 1 on error, 0 on no error.
|
\fIunbound\fR(8).
|
||||||
The data may not be available on exit code 0, exit code 1 means the lookup
|
|
||||||
encountered a fatal error.
|
|
||||||
.SH SEE ALSO
|
|
||||||
.sp
|
|
||||||
\fI\%unbound.conf(5)\fP,
|
|
||||||
\fI\%unbound(8)\fP\&.
|
|
||||||
.SH AUTHOR
|
|
||||||
Unbound developers are mentioned in the CREDITS file in the distribution.
|
|
||||||
.SH COPYRIGHT
|
|
||||||
1999-2026, NLnet Labs
|
|
||||||
.\" Generated by docutils manpage writer.
|
|
||||||
.
|
|
||||||
|
|||||||
@@ -1,176 +0,0 @@
|
|||||||
..
|
|
||||||
WHEN EDITING MAKE SURE EACH SENTENCE STARTS ON A NEW LINE
|
|
||||||
|
|
||||||
..
|
|
||||||
IT HELPS RENDERERS TO DO THE RIGHT THING WRT SPACE
|
|
||||||
|
|
||||||
..
|
|
||||||
IT HELPS PEOPLE DIFFING THE CHANGES
|
|
||||||
|
|
||||||
..
|
|
||||||
WHEN EDITING MAKE SURE EACH SENTENCE STARTS ON A NEW LINE
|
|
||||||
|
|
||||||
..
|
|
||||||
IT HELPS RENDERERS TO DO THE RIGHT THING WRT SPACE
|
|
||||||
|
|
||||||
..
|
|
||||||
IT HELPS PEOPLE DIFFING THE CHANGES
|
|
||||||
|
|
||||||
..
|
|
||||||
WHEN EDITING MAKE SURE EACH SENTENCE STARTS ON A NEW LINE
|
|
||||||
|
|
||||||
..
|
|
||||||
IT HELPS RENDERERS TO DO THE RIGHT THING WRT SPACE
|
|
||||||
|
|
||||||
..
|
|
||||||
IT HELPS PEOPLE DIFFING THE CHANGES
|
|
||||||
|
|
||||||
..
|
|
||||||
WHEN EDITING MAKE SURE EACH SENTENCE STARTS ON A NEW LINE
|
|
||||||
|
|
||||||
..
|
|
||||||
IT HELPS RENDERERS TO DO THE RIGHT THING WRT SPACE
|
|
||||||
|
|
||||||
..
|
|
||||||
IT HELPS PEOPLE DIFFING THE CHANGES
|
|
||||||
|
|
||||||
.. program:: unbound-host
|
|
||||||
|
|
||||||
unbound-host(1)
|
|
||||||
===============
|
|
||||||
|
|
||||||
Synopsis
|
|
||||||
--------
|
|
||||||
|
|
||||||
**unbound-host** [``-C configfile``] [``-vdhr46D``] [``-c class``]
|
|
||||||
[``-t type``] [``-y key``] [``-f keyfile``] [``-F namedkeyfile``] hostname
|
|
||||||
|
|
||||||
Description
|
|
||||||
-----------
|
|
||||||
|
|
||||||
``unbound-host`` uses the Unbound validating resolver to query for the hostname
|
|
||||||
and display results.
|
|
||||||
With the :option:`-v` option it displays validation status: secure, insecure,
|
|
||||||
bogus (security failure).
|
|
||||||
|
|
||||||
By default it reads no configuration file whatsoever.
|
|
||||||
It attempts to reach the internet root servers.
|
|
||||||
With :option:`-C` an unbound config file and with :option:`-r` ``resolv.conf``
|
|
||||||
can be read.
|
|
||||||
|
|
||||||
The available options are:
|
|
||||||
|
|
||||||
.. option:: hostname
|
|
||||||
|
|
||||||
This name is resolved (looked up in the DNS).
|
|
||||||
If a IPv4 or IPv6 address is given, a reverse lookup is performed.
|
|
||||||
|
|
||||||
.. option:: -h
|
|
||||||
|
|
||||||
Show the version and commandline option help.
|
|
||||||
|
|
||||||
.. option:: -v
|
|
||||||
|
|
||||||
Enable verbose output and it shows validation results, on every line.
|
|
||||||
Secure means that the NXDOMAIN (no such domain name), nodata (no such
|
|
||||||
data) or positive data response validated correctly with one of the
|
|
||||||
keys.
|
|
||||||
Insecure means that that domain name has no security set up for it.
|
|
||||||
Bogus (security failure) means that the response failed one or more
|
|
||||||
checks, it is likely wrong, outdated, tampered with, or broken.
|
|
||||||
|
|
||||||
.. option:: -d
|
|
||||||
|
|
||||||
Enable debug output to stderr.
|
|
||||||
One :option:`-d` shows what the resolver and validator are doing and may
|
|
||||||
tell you what is going on.
|
|
||||||
More times, :option:`-d` :option:`-d`, gives a lot of output, with every
|
|
||||||
packet sent and received.
|
|
||||||
|
|
||||||
.. option:: -c <class>
|
|
||||||
|
|
||||||
Specify the class to lookup for, the default is IN the internet
|
|
||||||
class.
|
|
||||||
|
|
||||||
.. option:: -t <type>
|
|
||||||
|
|
||||||
Specify the type of data to lookup.
|
|
||||||
The default looks for IPv4, IPv6 and mail handler data, or domain name
|
|
||||||
pointers for reverse queries.
|
|
||||||
|
|
||||||
.. option:: -y <key>
|
|
||||||
|
|
||||||
Specify a public key to use as trust anchor.
|
|
||||||
This is the base for a chain of trust that is built up from the trust
|
|
||||||
anchor to the response, in order to validate the response message.
|
|
||||||
Can be given as a DS or DNSKEY record.
|
|
||||||
For example:
|
|
||||||
|
|
||||||
.. code-block:: text
|
|
||||||
|
|
||||||
-y "example.com DS 31560 5 1 1CFED84787E6E19CCF9372C1187325972FE546CD"
|
|
||||||
|
|
||||||
.. option:: -D
|
|
||||||
|
|
||||||
Enables DNSSEC validation.
|
|
||||||
Reads the root anchor from the default configured root anchor at the
|
|
||||||
default location, :file:`@UNBOUND_ROOTKEY_FILE@`.
|
|
||||||
|
|
||||||
.. option:: -f <keyfile>
|
|
||||||
|
|
||||||
Reads keys from a file.
|
|
||||||
Every line has a DS or DNSKEY record, in the format as for :option:`-y`.
|
|
||||||
The zone file format, the same as ``dig`` and ``drill`` produce.
|
|
||||||
|
|
||||||
.. option:: -F <namedkeyfile>
|
|
||||||
|
|
||||||
Reads keys from a BIND-style :file:`named.conf` file.
|
|
||||||
Only the ``trusted-key {};`` entries are read.
|
|
||||||
|
|
||||||
.. option:: -C <configfile>
|
|
||||||
|
|
||||||
Uses the specified unbound.conf to prime :doc:`libunbound(3)</manpages/libunbound>`.
|
|
||||||
Pass it as first argument if you want to override some options from the
|
|
||||||
config file with further arguments on the commandline.
|
|
||||||
|
|
||||||
.. option:: -r
|
|
||||||
|
|
||||||
Read :file:`/etc/resolv.conf`, and use the forward DNS servers from
|
|
||||||
there (those could have been set by DHCP).
|
|
||||||
More info in *resolv.conf(5)*.
|
|
||||||
Breaks validation if those servers do not support DNSSEC.
|
|
||||||
|
|
||||||
.. option:: -4
|
|
||||||
|
|
||||||
Use solely the IPv4 network for sending packets.
|
|
||||||
|
|
||||||
.. option:: -6
|
|
||||||
|
|
||||||
Use solely the IPv6 network for sending packets.
|
|
||||||
|
|
||||||
Examples
|
|
||||||
--------
|
|
||||||
|
|
||||||
Some examples of use.
|
|
||||||
The keys shown below are fakes, thus a security failure is encountered.
|
|
||||||
|
|
||||||
.. code-block:: text
|
|
||||||
|
|
||||||
$ unbound-host www.example.com
|
|
||||||
|
|
||||||
$ unbound-host -v -y "example.com DS 31560 5 1 1CFED84787E6E19CCF9372C1187325972FE546CD" www.example.com
|
|
||||||
|
|
||||||
$ unbound-host -v -y "example.com DS 31560 5 1 1CFED84787E6E19CCF9372C1187325972FE546CD" 192.0.2.153
|
|
||||||
|
|
||||||
Exit Code
|
|
||||||
---------
|
|
||||||
|
|
||||||
The ``unbound-host`` program exits with status code 1 on error, 0 on no error.
|
|
||||||
The data may not be available on exit code 0, exit code 1 means the lookup
|
|
||||||
encountered a fatal error.
|
|
||||||
|
|
||||||
See Also
|
|
||||||
--------
|
|
||||||
|
|
||||||
:doc:`unbound.conf(5)</manpages/unbound.conf>`,
|
|
||||||
:doc:`unbound(8)</manpages/unbound>`.
|
|
||||||
+67
-102
@@ -1,123 +1,88 @@
|
|||||||
.\" Man page generated from reStructuredText.
|
.TH "unbound" "8" "@date@" "NLnet Labs" "unbound @version@"
|
||||||
.
|
.\"
|
||||||
.
|
.\" unbound.8 -- unbound manual
|
||||||
.nr rst2man-indent-level 0
|
.\"
|
||||||
.
|
.\" Copyright (c) 2007, NLnet Labs. All rights reserved.
|
||||||
.de1 rstReportMargin
|
.\"
|
||||||
\\$1 \\n[an-margin]
|
.\" See LICENSE for the license.
|
||||||
level \\n[rst2man-indent-level]
|
.\"
|
||||||
level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
.\"
|
||||||
-
|
.SH "NAME"
|
||||||
\\n[rst2man-indent0]
|
.B unbound
|
||||||
\\n[rst2man-indent1]
|
\- Unbound DNS validating resolver @version@.
|
||||||
\\n[rst2man-indent2]
|
.SH "SYNOPSIS"
|
||||||
..
|
.B unbound
|
||||||
.de1 INDENT
|
.RB [ \-h ]
|
||||||
.\" .rstReportMargin pre:
|
.RB [ \-d ]
|
||||||
. RS \\$1
|
.RB [ \-p ]
|
||||||
. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
|
.RB [ \-v ]
|
||||||
. nr rst2man-indent-level +1
|
.RB [ \-c
|
||||||
.\" .rstReportMargin post:
|
.IR cfgfile ]
|
||||||
..
|
.SH "DESCRIPTION"
|
||||||
.de UNINDENT
|
.B Unbound
|
||||||
. RE
|
is a caching DNS resolver.
|
||||||
.\" indent \\n[an-margin]
|
.P
|
||||||
.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
It uses a built in list of authoritative nameservers for the root zone (.),
|
||||||
.nr rst2man-indent-level -1
|
|
||||||
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
|
||||||
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
|
|
||||||
..
|
|
||||||
.TH "UNBOUND" "8" "@date@" "@version@" "Unbound"
|
|
||||||
.SH NAME
|
|
||||||
unbound \- Unbound DNS validating resolver @version@.
|
|
||||||
.SH SYNOPSIS
|
|
||||||
.sp
|
|
||||||
\fBunbound\fP [\fB\-hdpVv\fP] [\fB\-c <cfgfile>\fP]
|
|
||||||
.SH DESCRIPTION
|
|
||||||
.sp
|
|
||||||
\fBunbound\fP is a caching DNS resolver.
|
|
||||||
.sp
|
|
||||||
It uses a built in list of authoritative nameservers for the root zone (\fB\&.\fP),
|
|
||||||
the so called root hints.
|
the so called root hints.
|
||||||
On receiving a DNS query it will ask the root nameservers for an answer and
|
On receiving a DNS query it will ask the root nameservers for
|
||||||
will in almost all cases receive a delegation to a top level domain (TLD)
|
an answer and will in almost all cases receive a delegation to a top level
|
||||||
authoritative nameserver.
|
domain (TLD) authoritative nameserver.
|
||||||
It will then ask that nameserver for an answer.
|
It will then ask that nameserver for an answer.
|
||||||
It will recursively continue until an answer is found or no answer is available
|
It will recursively continue until an answer is found or no answer is
|
||||||
(NXDOMAIN).
|
available (NXDOMAIN).
|
||||||
For performance and efficiency reasons that answer is cached for a certain time
|
For performance and efficiency reasons that answer is cached for a
|
||||||
(the answer\(aqs time\-to\-live or TTL).
|
certain time (the answer's time\-to\-live or TTL).
|
||||||
A second query for the same name will then be answered from the cache.
|
A second query for the same name will then be answered from the cache.
|
||||||
Unbound can also do DNSSEC validation.
|
Unbound can also do DNSSEC validation.
|
||||||
|
.P
|
||||||
|
To use a locally running
|
||||||
|
.B Unbound
|
||||||
|
for resolving put
|
||||||
.sp
|
.sp
|
||||||
To use a locally running Unbound for resolving put:
|
.RS 6n
|
||||||
.INDENT 0.0
|
|
||||||
.INDENT 3.5
|
|
||||||
.sp
|
|
||||||
.nf
|
|
||||||
.ft C
|
|
||||||
nameserver 127.0.0.1
|
nameserver 127.0.0.1
|
||||||
.ft P
|
.RE
|
||||||
.fi
|
|
||||||
.UNINDENT
|
|
||||||
.UNINDENT
|
|
||||||
.sp
|
|
||||||
into \fIresolv.conf(5)\fP\&.
|
|
||||||
.sp
|
|
||||||
If authoritative DNS is needed as well using \fI\%nsd(8)\fP,
|
|
||||||
careful setup is required because authoritative nameservers and resolvers are
|
|
||||||
using the same port number (53).
|
|
||||||
.sp
|
.sp
|
||||||
|
into
|
||||||
|
.IR resolv.conf (5).
|
||||||
|
.P
|
||||||
|
If authoritative DNS is needed as well using
|
||||||
|
.IR nsd (8),
|
||||||
|
careful setup is required because authoritative nameservers and
|
||||||
|
resolvers are using the same port number (53).
|
||||||
|
.P
|
||||||
The available options are:
|
The available options are:
|
||||||
.INDENT 0.0
|
|
||||||
.TP
|
.TP
|
||||||
.B \-h
|
.B \-h
|
||||||
Show the version number and commandline option help, and exit.
|
Show the version number and commandline option help, and exit.
|
||||||
.UNINDENT
|
|
||||||
.INDENT 0.0
|
|
||||||
.TP
|
.TP
|
||||||
.B \-c <cfgfile>
|
.B \-c\fI cfgfile
|
||||||
Set the config file with settings for unbound to read instead of reading the
|
Set the config file with settings for Unbound to read instead of reading the
|
||||||
file at the default location, \fB@ub_conf_file@\fP\&.
|
file at the default location, @ub_conf_file@. The syntax is
|
||||||
The syntax is described in \fI\%unbound.conf(5)\fP\&.
|
described in \fIunbound.conf\fR(5).
|
||||||
.UNINDENT
|
|
||||||
.INDENT 0.0
|
|
||||||
.TP
|
.TP
|
||||||
.B \-d
|
.B \-d
|
||||||
Debug flag: do not fork into the background, but stay attached to the
|
Debug flag: do not fork into the background, but stay attached to
|
||||||
console.
|
the console. This flag will also delay writing to the log file until
|
||||||
This flag will also delay writing to the log file until the thread\-spawn
|
the thread\-spawn time, so that most config and setup errors appear on
|
||||||
time, so that most config and setup errors appear on stderr.
|
stderr. If given twice or more, logging does not switch to the log file
|
||||||
If given twice or more, logging does not switch to the log file or to
|
or to syslog, but the log messages are printed to stderr all the time.
|
||||||
syslog, but the log messages are printed to stderr all the time.
|
|
||||||
.UNINDENT
|
|
||||||
.INDENT 0.0
|
|
||||||
.TP
|
.TP
|
||||||
.B \-p
|
.B \-p
|
||||||
Don\(aqt use a pidfile.
|
Don't use a pidfile. This argument should only be used by supervision
|
||||||
This argument should only be used by supervision systems which can ensure
|
systems which can ensure that only one instance of Unbound will run
|
||||||
that only one instance of Unbound will run concurrently.
|
concurrently.
|
||||||
.UNINDENT
|
|
||||||
.INDENT 0.0
|
|
||||||
.TP
|
.TP
|
||||||
.B \-v
|
.B \-v
|
||||||
Increase verbosity.
|
Increase verbosity. If given multiple times, more information is logged.
|
||||||
If given multiple times, more information is logged.
|
This is added to the verbosity (if any) from the config file.
|
||||||
This is in addition to the verbosity (if any) from the config file.
|
|
||||||
.UNINDENT
|
|
||||||
.INDENT 0.0
|
|
||||||
.TP
|
.TP
|
||||||
.B \-V
|
.B \-V
|
||||||
Show the version number and build options, and exit.
|
Show the version number and build options, and exit.
|
||||||
.UNINDENT
|
.SH "SEE ALSO"
|
||||||
.SH SEE ALSO
|
\fIunbound.conf\fR(5),
|
||||||
.sp
|
\fIunbound\-checkconf\fR(8),
|
||||||
\fI\%unbound.conf(5)\fP,
|
\fInsd\fR(8).
|
||||||
\fI\%unbound\-checkconf(8)\fP,
|
.SH "AUTHORS"
|
||||||
\fI\%nsd(8)\fP\&.
|
.B Unbound
|
||||||
.SH AUTHOR
|
developers are mentioned in the CREDITS file in the distribution.
|
||||||
Unbound developers are mentioned in the CREDITS file in the distribution.
|
|
||||||
.SH COPYRIGHT
|
|
||||||
1999-2026, NLnet Labs
|
|
||||||
.\" Generated by docutils manpage writer.
|
|
||||||
.
|
|
||||||
|
|||||||
+2412
-5719
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
+889
-2010
File diff suppressed because it is too large
Load Diff
-119
@@ -1,119 +0,0 @@
|
|||||||
..
|
|
||||||
WHEN EDITING MAKE SURE EACH SENTENCE STARTS ON A NEW LINE
|
|
||||||
|
|
||||||
..
|
|
||||||
IT HELPS RENDERERS TO DO THE RIGHT THING WRT SPACE
|
|
||||||
|
|
||||||
..
|
|
||||||
IT HELPS PEOPLE DIFFING THE CHANGES
|
|
||||||
|
|
||||||
..
|
|
||||||
WHEN EDITING MAKE SURE EACH SENTENCE STARTS ON A NEW LINE
|
|
||||||
|
|
||||||
..
|
|
||||||
IT HELPS RENDERERS TO DO THE RIGHT THING WRT SPACE
|
|
||||||
|
|
||||||
..
|
|
||||||
IT HELPS PEOPLE DIFFING THE CHANGES
|
|
||||||
|
|
||||||
..
|
|
||||||
WHEN EDITING MAKE SURE EACH SENTENCE STARTS ON A NEW LINE
|
|
||||||
|
|
||||||
..
|
|
||||||
IT HELPS RENDERERS TO DO THE RIGHT THING WRT SPACE
|
|
||||||
|
|
||||||
..
|
|
||||||
IT HELPS PEOPLE DIFFING THE CHANGES
|
|
||||||
|
|
||||||
..
|
|
||||||
WHEN EDITING MAKE SURE EACH SENTENCE STARTS ON A NEW LINE
|
|
||||||
|
|
||||||
..
|
|
||||||
IT HELPS RENDERERS TO DO THE RIGHT THING WRT SPACE
|
|
||||||
|
|
||||||
..
|
|
||||||
IT HELPS PEOPLE DIFFING THE CHANGES
|
|
||||||
|
|
||||||
.. program:: unbound
|
|
||||||
|
|
||||||
unbound(8)
|
|
||||||
==========
|
|
||||||
|
|
||||||
Synopsis
|
|
||||||
--------
|
|
||||||
|
|
||||||
**unbound** [``-hdpVv``] [``-c <cfgfile>``]
|
|
||||||
|
|
||||||
Description
|
|
||||||
-----------
|
|
||||||
|
|
||||||
``unbound`` is a caching DNS resolver.
|
|
||||||
|
|
||||||
It uses a built in list of authoritative nameservers for the root zone (``.``),
|
|
||||||
the so called root hints.
|
|
||||||
On receiving a DNS query it will ask the root nameservers for an answer and
|
|
||||||
will in almost all cases receive a delegation to a top level domain (TLD)
|
|
||||||
authoritative nameserver.
|
|
||||||
It will then ask that nameserver for an answer.
|
|
||||||
It will recursively continue until an answer is found or no answer is available
|
|
||||||
(NXDOMAIN).
|
|
||||||
For performance and efficiency reasons that answer is cached for a certain time
|
|
||||||
(the answer's time-to-live or TTL).
|
|
||||||
A second query for the same name will then be answered from the cache.
|
|
||||||
Unbound can also do DNSSEC validation.
|
|
||||||
|
|
||||||
To use a locally running Unbound for resolving put:
|
|
||||||
|
|
||||||
.. code-block:: text
|
|
||||||
|
|
||||||
nameserver 127.0.0.1
|
|
||||||
|
|
||||||
into *resolv.conf(5)*.
|
|
||||||
|
|
||||||
If authoritative DNS is needed as well using :external+nsd:doc:`manpages/nsd`,
|
|
||||||
careful setup is required because authoritative nameservers and resolvers are
|
|
||||||
using the same port number (53).
|
|
||||||
|
|
||||||
The available options are:
|
|
||||||
|
|
||||||
.. option:: -h
|
|
||||||
|
|
||||||
Show the version number and commandline option help, and exit.
|
|
||||||
|
|
||||||
.. option:: -c <cfgfile>
|
|
||||||
|
|
||||||
Set the config file with settings for unbound to read instead of reading the
|
|
||||||
file at the default location, :file:`@ub_conf_file@`.
|
|
||||||
The syntax is described in :doc:`unbound.conf(5)</manpages/unbound.conf>`.
|
|
||||||
|
|
||||||
.. option:: -d
|
|
||||||
|
|
||||||
Debug flag: do not fork into the background, but stay attached to the
|
|
||||||
console.
|
|
||||||
This flag will also delay writing to the log file until the thread-spawn
|
|
||||||
time, so that most config and setup errors appear on stderr.
|
|
||||||
If given twice or more, logging does not switch to the log file or to
|
|
||||||
syslog, but the log messages are printed to stderr all the time.
|
|
||||||
|
|
||||||
.. option:: -p
|
|
||||||
|
|
||||||
Don't use a pidfile.
|
|
||||||
This argument should only be used by supervision systems which can ensure
|
|
||||||
that only one instance of Unbound will run concurrently.
|
|
||||||
|
|
||||||
.. option:: -v
|
|
||||||
|
|
||||||
Increase verbosity.
|
|
||||||
If given multiple times, more information is logged.
|
|
||||||
This is in addition to the verbosity (if any) from the config file.
|
|
||||||
|
|
||||||
.. option:: -V
|
|
||||||
|
|
||||||
Show the version number and build options, and exit.
|
|
||||||
|
|
||||||
See Also
|
|
||||||
--------
|
|
||||||
|
|
||||||
:doc:`unbound.conf(5)</manpages/unbound.conf>`,
|
|
||||||
:doc:`unbound-checkconf(8)</manpages/unbound-checkconf>`,
|
|
||||||
:external+nsd:doc:`manpages/nsd`.
|
|
||||||
@@ -75,7 +75,6 @@ int dynlibmod_init(struct module_env* env, int id) {
|
|||||||
struct config_strlist* cfg_item = env->cfg->dynlib_file;
|
struct config_strlist* cfg_item = env->cfg->dynlib_file;
|
||||||
struct dynlibmod_env* de = (struct dynlibmod_env*)calloc(1, sizeof(struct dynlibmod_env));
|
struct dynlibmod_env* de = (struct dynlibmod_env*)calloc(1, sizeof(struct dynlibmod_env));
|
||||||
__DYNMOD dynamic_library;
|
__DYNMOD dynamic_library;
|
||||||
int i;
|
|
||||||
if (!de)
|
if (!de)
|
||||||
{
|
{
|
||||||
log_err("dynlibmod[%d]: malloc failure", dynlib_mod_idx);
|
log_err("dynlibmod[%d]: malloc failure", dynlib_mod_idx);
|
||||||
@@ -85,7 +84,7 @@ int dynlibmod_init(struct module_env* env, int id) {
|
|||||||
env->modinfo[id] = (void*) de;
|
env->modinfo[id] = (void*) de;
|
||||||
|
|
||||||
de->fname = NULL;
|
de->fname = NULL;
|
||||||
for(i = dynlib_mod_idx;
|
for(int i = dynlib_mod_idx;
|
||||||
i != 0 && cfg_item != NULL;
|
i != 0 && cfg_item != NULL;
|
||||||
i--, cfg_item = cfg_item->next) {}
|
i--, cfg_item = cfg_item->next) {}
|
||||||
|
|
||||||
@@ -297,8 +296,8 @@ inplace_cb_delete_wrapped(struct module_env* env, enum inplace_cb_list_type type
|
|||||||
*/
|
*/
|
||||||
static struct module_func_block dynlibmod_block = {
|
static struct module_func_block dynlibmod_block = {
|
||||||
"dynlib",
|
"dynlib",
|
||||||
NULL, NULL, &dynlibmod_init, &dynlibmod_deinit, &dynlibmod_operate,
|
&dynlibmod_init, &dynlibmod_deinit, &dynlibmod_operate, &dynlibmod_inform_super,
|
||||||
&dynlibmod_inform_super, &dynlibmod_clear, &dynlibmod_get_mem
|
&dynlibmod_clear, &dynlibmod_get_mem
|
||||||
};
|
};
|
||||||
|
|
||||||
struct module_func_block* dynlibmod_get_funcblock(void)
|
struct module_func_block* dynlibmod_get_funcblock(void)
|
||||||
|
|||||||
@@ -459,7 +459,6 @@ addrtree_insert(struct addrtree *tree, const addrkey_t *addr,
|
|||||||
/* Data is stored in other leafnode */
|
/* Data is stored in other leafnode */
|
||||||
node = newnode;
|
node = newnode;
|
||||||
newnode = node_create(tree, elem, scope, ttl);
|
newnode = node_create(tree, elem, scope, ttl);
|
||||||
if (!newnode) return;
|
|
||||||
if (!edge_create(newnode, addr, sourcemask, node,
|
if (!edge_create(newnode, addr, sourcemask, node,
|
||||||
index^1)) {
|
index^1)) {
|
||||||
clean_node(tree, newnode);
|
clean_node(tree, newnode);
|
||||||
|
|||||||
@@ -116,7 +116,7 @@ struct addredge {
|
|||||||
addrlen_t len;
|
addrlen_t len;
|
||||||
/** child node this edge is connected to */
|
/** child node this edge is connected to */
|
||||||
struct addrnode *node;
|
struct addrnode *node;
|
||||||
/** Parent node this edge is connected to */
|
/** Parent node this ege is connected to */
|
||||||
struct addrnode *parent_node;
|
struct addrnode *parent_node;
|
||||||
/** Index of this edge in parent_node */
|
/** Index of this edge in parent_node */
|
||||||
int parent_index;
|
int parent_index;
|
||||||
|
|||||||
+24
-356
@@ -51,16 +51,12 @@
|
|||||||
#include "services/cache/dns.h"
|
#include "services/cache/dns.h"
|
||||||
#include "util/module.h"
|
#include "util/module.h"
|
||||||
#include "util/regional.h"
|
#include "util/regional.h"
|
||||||
#include "util/fptr_wlist.h"
|
|
||||||
#include "util/storage/slabhash.h"
|
#include "util/storage/slabhash.h"
|
||||||
#include "util/config_file.h"
|
#include "util/config_file.h"
|
||||||
#include "util/data/msgreply.h"
|
#include "util/data/msgreply.h"
|
||||||
#include "sldns/sbuffer.h"
|
#include "sldns/sbuffer.h"
|
||||||
#include "sldns/wire2str.h"
|
#include "sldns/wire2str.h"
|
||||||
#include "iterator/iter_utils.h"
|
#include "iterator/iter_utils.h"
|
||||||
#ifdef USE_CACHEDB
|
|
||||||
#include "cachedb/cachedb.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/** externally called */
|
/** externally called */
|
||||||
void
|
void
|
||||||
@@ -70,7 +66,6 @@ subnet_data_delete(void *d, void *ATTR_UNUSED(arg))
|
|||||||
r = (struct subnet_msg_cache_data*)d;
|
r = (struct subnet_msg_cache_data*)d;
|
||||||
addrtree_delete(r->tree4);
|
addrtree_delete(r->tree4);
|
||||||
addrtree_delete(r->tree6);
|
addrtree_delete(r->tree6);
|
||||||
free(r->reason_fail);
|
|
||||||
free(r);
|
free(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -85,8 +80,6 @@ msg_cache_sizefunc(void *k, void *d)
|
|||||||
+ q->key.qname_len + lock_get_mem(&q->entry.lock);
|
+ q->key.qname_len + lock_get_mem(&q->entry.lock);
|
||||||
s += addrtree_size(r->tree4);
|
s += addrtree_size(r->tree4);
|
||||||
s += addrtree_size(r->tree6);
|
s += addrtree_size(r->tree6);
|
||||||
if(r->reason_fail)
|
|
||||||
s += strlen(r->reason_fail)+1;
|
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -157,36 +150,12 @@ int ecs_whitelist_check(struct query_info* qinfo,
|
|||||||
return 1;
|
return 1;
|
||||||
sn_env = (struct subnet_env*)qstate->env->modinfo[id];
|
sn_env = (struct subnet_env*)qstate->env->modinfo[id];
|
||||||
|
|
||||||
if(sq->is_subquery_nonsubnet) {
|
|
||||||
if(sq->is_subquery_scopezero) {
|
|
||||||
/* Check if the result can be stored in the global cache,
|
|
||||||
* this is okay if the address and name are not configured
|
|
||||||
* as subnet address and subnet zone. */
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Cache by default, might be disabled after parsing EDNS option
|
/* Cache by default, might be disabled after parsing EDNS option
|
||||||
* received from nameserver. */
|
* received from nameserver. */
|
||||||
if(!iter_stub_fwd_no_cache(qstate, &qstate->qinfo, NULL, NULL, NULL, 0)
|
if(!iter_stub_fwd_no_cache(qstate, &qstate->qinfo, NULL, NULL)) {
|
||||||
&& sq->ecs_client_in.subnet_validdata) {
|
|
||||||
qstate->no_cache_store = 0;
|
qstate->no_cache_store = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
sq->subnet_sent_no_subnet = 0;
|
|
||||||
if(sq->ecs_server_out.subnet_validdata && ((sq->subnet_downstream &&
|
if(sq->ecs_server_out.subnet_validdata && ((sq->subnet_downstream &&
|
||||||
qstate->env->cfg->client_subnet_always_forward) ||
|
qstate->env->cfg->client_subnet_always_forward) ||
|
||||||
ecs_is_whitelisted(sn_env->whitelist,
|
ecs_is_whitelisted(sn_env->whitelist,
|
||||||
@@ -197,24 +166,10 @@ int ecs_whitelist_check(struct query_info* qinfo,
|
|||||||
* set. */
|
* set. */
|
||||||
if(!edns_opt_list_find(qstate->edns_opts_back_out,
|
if(!edns_opt_list_find(qstate->edns_opts_back_out,
|
||||||
qstate->env->cfg->client_subnet_opcode)) {
|
qstate->env->cfg->client_subnet_opcode)) {
|
||||||
/* if the client is not wanting an EDNS subnet option,
|
|
||||||
* omit it and store that we omitted it but actually
|
|
||||||
* are doing EDNS subnet to the server. */
|
|
||||||
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,
|
subnet_ecs_opt_list_append(&sq->ecs_server_out,
|
||||||
&qstate->edns_opts_back_out, qstate, region);
|
&qstate->edns_opts_back_out, qstate, region);
|
||||||
}
|
}
|
||||||
sq->subnet_sent = 1;
|
sq->subnet_sent = 1;
|
||||||
/* Do not store servfails in global cache, since the subnet
|
|
||||||
* option is sent out. */
|
|
||||||
qstate->no_cache_store = 1;
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* Outgoing ECS option is set, but we don't want to sent it to
|
/* Outgoing ECS option is set, but we don't want to sent it to
|
||||||
@@ -249,29 +204,18 @@ subnetmod_init(struct module_env *env, int id)
|
|||||||
}
|
}
|
||||||
alloc_init(&sn_env->alloc, NULL, 0);
|
alloc_init(&sn_env->alloc, NULL, 0);
|
||||||
env->modinfo[id] = (void*)sn_env;
|
env->modinfo[id] = (void*)sn_env;
|
||||||
|
|
||||||
/* Warn that serve-expired and prefetch do not work with the subnet
|
|
||||||
* module cache. */
|
|
||||||
if(env->cfg->serve_expired)
|
|
||||||
log_warn(
|
|
||||||
"subnetcache: serve-expired is set but not working "
|
|
||||||
"for data originating from the subnet module cache.");
|
|
||||||
if(env->cfg->prefetch)
|
|
||||||
log_warn(
|
|
||||||
"subnetcache: prefetch is set but not working "
|
|
||||||
"for data originating from the subnet module cache.");
|
|
||||||
/* Copy msg_cache settings */
|
/* Copy msg_cache settings */
|
||||||
sn_env->subnet_msg_cache = slabhash_create(env->cfg->msg_cache_slabs,
|
sn_env->subnet_msg_cache = slabhash_create(env->cfg->msg_cache_slabs,
|
||||||
HASH_DEFAULT_STARTARRAY, env->cfg->msg_cache_size,
|
HASH_DEFAULT_STARTARRAY, env->cfg->msg_cache_size,
|
||||||
msg_cache_sizefunc, query_info_compare, query_entry_delete,
|
msg_cache_sizefunc, query_info_compare, query_entry_delete,
|
||||||
subnet_data_delete, NULL);
|
subnet_data_delete, NULL);
|
||||||
|
slabhash_setmarkdel(sn_env->subnet_msg_cache, &subnet_markdel);
|
||||||
if(!sn_env->subnet_msg_cache) {
|
if(!sn_env->subnet_msg_cache) {
|
||||||
log_err("subnetcache: could not create cache");
|
log_err("subnetcache: could not create cache");
|
||||||
free(sn_env);
|
free(sn_env);
|
||||||
env->modinfo[id] = NULL;
|
env->modinfo[id] = NULL;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
slabhash_setmarkdel(sn_env->subnet_msg_cache, &subnet_markdel);
|
|
||||||
/* whitelist for edns subnet capable servers */
|
/* whitelist for edns subnet capable servers */
|
||||||
sn_env->whitelist = ecs_whitelist_create();
|
sn_env->whitelist = ecs_whitelist_create();
|
||||||
if(!sn_env->whitelist ||
|
if(!sn_env->whitelist ||
|
||||||
@@ -346,18 +290,9 @@ delfunc(void *envptr, void *elemptr) {
|
|||||||
static size_t
|
static size_t
|
||||||
sizefunc(void *elemptr) {
|
sizefunc(void *elemptr) {
|
||||||
struct reply_info *elem = (struct reply_info *)elemptr;
|
struct reply_info *elem = (struct reply_info *)elemptr;
|
||||||
size_t s = sizeof (struct reply_info) - sizeof (struct rrset_ref)
|
return sizeof (struct reply_info) - sizeof (struct rrset_ref)
|
||||||
+ elem->rrset_count * sizeof (struct rrset_ref)
|
+ elem->rrset_count * sizeof (struct rrset_ref)
|
||||||
+ elem->rrset_count * sizeof (struct ub_packed_rrset_key *);
|
+ elem->rrset_count * sizeof (struct ub_packed_rrset_key *);
|
||||||
size_t i;
|
|
||||||
for (i = 0; i < elem->rrset_count; i++) {
|
|
||||||
struct ub_packed_rrset_key *key = elem->rrsets[i];
|
|
||||||
struct packed_rrset_data *data = key->entry.data;
|
|
||||||
s += ub_rrset_sizefunc(key, data);
|
|
||||||
}
|
|
||||||
if(elem->reason_bogus_str)
|
|
||||||
s += strlen(elem->reason_bogus_str)+1;
|
|
||||||
return s;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -397,7 +332,7 @@ update_cache(struct module_qstate *qstate, int id)
|
|||||||
struct slabhash *subnet_msg_cache = sne->subnet_msg_cache;
|
struct slabhash *subnet_msg_cache = sne->subnet_msg_cache;
|
||||||
struct ecs_data *edns = &sq->ecs_client_in;
|
struct ecs_data *edns = &sq->ecs_client_in;
|
||||||
size_t i;
|
size_t i;
|
||||||
int only_match_scope_zero, diff_size;
|
int only_match_scope_zero;
|
||||||
|
|
||||||
/* We already calculated hash upon lookup (lookup_and_reply) if we were
|
/* We already calculated hash upon lookup (lookup_and_reply) if we were
|
||||||
* allowed to look in the ECS cache */
|
* allowed to look in the ECS cache */
|
||||||
@@ -406,7 +341,7 @@ update_cache(struct module_qstate *qstate, int id)
|
|||||||
((struct subnet_qstate*)qstate->minfo[id])->qinfo_hash :
|
((struct subnet_qstate*)qstate->minfo[id])->qinfo_hash :
|
||||||
query_info_hash(&qstate->qinfo, qstate->query_flags);
|
query_info_hash(&qstate->qinfo, qstate->query_flags);
|
||||||
/* Step 1, general qinfo lookup */
|
/* Step 1, general qinfo lookup */
|
||||||
struct lruhash_entry* lru_entry = slabhash_lookup(subnet_msg_cache, h,
|
struct lruhash_entry *lru_entry = slabhash_lookup(subnet_msg_cache, h,
|
||||||
&qstate->qinfo, 1);
|
&qstate->qinfo, 1);
|
||||||
int need_to_insert = (lru_entry == NULL);
|
int need_to_insert = (lru_entry == NULL);
|
||||||
if (!lru_entry) {
|
if (!lru_entry) {
|
||||||
@@ -436,35 +371,6 @@ update_cache(struct module_qstate *qstate, int id)
|
|||||||
}
|
}
|
||||||
/* lru_entry->lock is locked regardless of how we got here,
|
/* lru_entry->lock is locked regardless of how we got here,
|
||||||
* either from the slabhash_lookup, or above in the new allocated */
|
* 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 */
|
/* Step 2, find the correct tree */
|
||||||
if (!(tree = get_tree(lru_entry->data, edns, sne, qstate->env->cfg))) {
|
if (!(tree = get_tree(lru_entry->data, edns, sne, qstate->env->cfg))) {
|
||||||
lock_rw_unlock(&lru_entry->lock);
|
lock_rw_unlock(&lru_entry->lock);
|
||||||
@@ -486,46 +392,25 @@ update_cache(struct module_qstate *qstate, int id)
|
|||||||
rep->ref[i].id = rep->rrsets[i]->id;
|
rep->ref[i].id = rep->rrsets[i]->id;
|
||||||
}
|
}
|
||||||
reply_info_set_ttls(rep, *qstate->env->now);
|
reply_info_set_ttls(rep, *qstate->env->now);
|
||||||
reply_info_sortref(rep);
|
|
||||||
rep->flags |= (BIT_RA | BIT_QR); /* fix flags to be sensible for */
|
rep->flags |= (BIT_RA | BIT_QR); /* fix flags to be sensible for */
|
||||||
rep->flags &= ~(BIT_AA | BIT_CD);/* a reply based on the cache */
|
rep->flags &= ~(BIT_AA | BIT_CD);/* a reply based on the cache */
|
||||||
if(edns->subnet_source_mask == 0 && edns->subnet_scope_mask == 0)
|
if(edns->subnet_source_mask == 0 && edns->subnet_scope_mask == 0)
|
||||||
only_match_scope_zero = 1;
|
only_match_scope_zero = 1;
|
||||||
else only_match_scope_zero = 0;
|
else only_match_scope_zero = 0;
|
||||||
diff_size = (int)tree->size_bytes;
|
|
||||||
addrtree_insert(tree, (addrkey_t*)edns->subnet_addr,
|
addrtree_insert(tree, (addrkey_t*)edns->subnet_addr,
|
||||||
edns->subnet_source_mask, sq->max_scope, rep,
|
edns->subnet_source_mask, sq->max_scope, rep,
|
||||||
rep->ttl, *qstate->env->now, only_match_scope_zero);
|
rep->ttl, *qstate->env->now, only_match_scope_zero);
|
||||||
diff_size = (int)tree->size_bytes - diff_size;
|
|
||||||
|
|
||||||
lock_rw_unlock(&lru_entry->lock);
|
lock_rw_unlock(&lru_entry->lock);
|
||||||
if (need_to_insert) {
|
if (need_to_insert) {
|
||||||
slabhash_insert(subnet_msg_cache, h, lru_entry, lru_entry->data,
|
slabhash_insert(subnet_msg_cache, h, lru_entry, lru_entry->data,
|
||||||
NULL);
|
NULL);
|
||||||
} else {
|
|
||||||
slabhash_update_space_used(subnet_msg_cache, h, NULL,
|
|
||||||
diff_size);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 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. */
|
/** Lookup in cache and reply true iff reply is sent. */
|
||||||
static int
|
static int
|
||||||
lookup_and_reply(struct module_qstate *qstate, int id, struct subnet_qstate *sq, int prefetch)
|
lookup_and_reply(struct module_qstate *qstate, int id, struct subnet_qstate *sq)
|
||||||
{
|
{
|
||||||
struct lruhash_entry *e;
|
struct lruhash_entry *e;
|
||||||
struct module_env *env = qstate->env;
|
struct module_env *env = qstate->env;
|
||||||
@@ -536,8 +421,6 @@ lookup_and_reply(struct module_qstate *qstate, int id, struct subnet_qstate *sq,
|
|||||||
struct addrtree *tree;
|
struct addrtree *tree;
|
||||||
struct addrnode *node;
|
struct addrnode *node;
|
||||||
uint8_t scope;
|
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));
|
memset(&sq->ecs_client_out, 0, sizeof(sq->ecs_client_out));
|
||||||
|
|
||||||
@@ -551,20 +434,12 @@ lookup_and_reply(struct module_qstate *qstate, int id, struct subnet_qstate *sq,
|
|||||||
tree = (ecs->subnet_addr_fam == EDNSSUBNET_ADDRFAM_IP4)?
|
tree = (ecs->subnet_addr_fam == EDNSSUBNET_ADDRFAM_IP4)?
|
||||||
data->tree4 : data->tree6;
|
data->tree4 : data->tree6;
|
||||||
if (!tree) { /* qinfo in cache but not for this family */
|
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);
|
lock_rw_unlock(&e->lock);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
node = addrtree_find(tree, (addrkey_t*)ecs->subnet_addr,
|
node = addrtree_find(tree, (addrkey_t*)ecs->subnet_addr,
|
||||||
ecs->subnet_source_mask, *env->now);
|
ecs->subnet_source_mask, *env->now);
|
||||||
if (!node) { /* plain old cache miss */
|
if (!node) { /* plain old cache miss */
|
||||||
if(lookup_check_servfail(qstate, data)) {
|
|
||||||
lock_rw_unlock(&e->lock);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
lock_rw_unlock(&e->lock);
|
lock_rw_unlock(&e->lock);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -573,21 +448,9 @@ lookup_and_reply(struct module_qstate *qstate, int id, struct subnet_qstate *sq,
|
|||||||
(struct reply_info *)node->elem, qstate->region, *env->now, 0,
|
(struct reply_info *)node->elem, qstate->region, *env->now, 0,
|
||||||
env->scratch);
|
env->scratch);
|
||||||
scope = (uint8_t)node->scope;
|
scope = (uint8_t)node->scope;
|
||||||
|
lock_rw_unlock(&e->lock);
|
||||||
|
|
||||||
if (!qstate->return_msg) { /* Failed allocation or expired TTL */
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -599,10 +462,6 @@ lookup_and_reply(struct module_qstate *qstate, int id, struct subnet_qstate *sq,
|
|||||||
INET6_SIZE);
|
INET6_SIZE);
|
||||||
sq->ecs_client_out.subnet_validdata = 1;
|
sq->ecs_client_out.subnet_validdata = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (prefetch && *qstate->env->now >= ((struct reply_info *)node->elem)->prefetch_ttl) {
|
|
||||||
qstate->need_refetch = 1;
|
|
||||||
}
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -621,87 +480,6 @@ common_prefix(uint8_t *a, uint8_t *b, uint8_t net)
|
|||||||
return !memcmp(a, b, n) && ((net % 8) == 0 || a[n] == b[n]);
|
return !memcmp(a, b, n) && ((net % 8) == 0 || a[n] == b[n]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Create sub request that looks up the query.
|
|
||||||
* @param qstate: query state
|
|
||||||
* @param id: module id.
|
|
||||||
* @param sq: subnet qstate
|
|
||||||
* @return false on failure.
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
generate_sub_request(struct module_qstate *qstate, int id, struct subnet_qstate* sq)
|
|
||||||
{
|
|
||||||
struct module_qstate* subq = NULL;
|
|
||||||
uint16_t qflags = 0; /* OPCODE QUERY, no flags */
|
|
||||||
int prime = 0;
|
|
||||||
int valrec = 0;
|
|
||||||
struct query_info qinf;
|
|
||||||
qinf.qname = qstate->qinfo.qname;
|
|
||||||
qinf.qname_len = qstate->qinfo.qname_len;
|
|
||||||
qinf.qtype = qstate->qinfo.qtype;
|
|
||||||
qinf.qclass = qstate->qinfo.qclass;
|
|
||||||
qinf.local_alias = NULL;
|
|
||||||
|
|
||||||
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. */
|
|
||||||
}
|
|
||||||
|
|
||||||
fptr_ok(fptr_whitelist_modenv_attach_sub(qstate->env->attach_sub));
|
|
||||||
if(!(*qstate->env->attach_sub)(qstate, &qinf, qstate->client_info,
|
|
||||||
qflags, prime, valrec, &subq)) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if(subq) {
|
|
||||||
/* It is possible to access the subquery module state. */
|
|
||||||
struct subnet_qstate* subsq;
|
|
||||||
if(!subnet_new_qstate(subq, id)) {
|
|
||||||
verbose(VERB_ALGO, "Could not allocate new subnet qstate");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
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.
|
|
||||||
* Store that the client asked for that, if so. */
|
|
||||||
if(sq->ecs_client_in.subnet_source_mask == 0 &&
|
|
||||||
edns_opt_list_find(qstate->edns_opts_front_in,
|
|
||||||
qstate->env->cfg->client_subnet_opcode)) {
|
|
||||||
subq->no_cache_store = 1;
|
|
||||||
subsq->is_subquery_scopezero = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Perform the query without subnet
|
|
||||||
* @param qstate: query state
|
|
||||||
* @param id: module id.
|
|
||||||
* @param sq: subnet qstate
|
|
||||||
* @return module state
|
|
||||||
*/
|
|
||||||
static enum module_ext_state
|
|
||||||
generate_lookup_without_subnet(struct module_qstate *qstate, int id,
|
|
||||||
struct subnet_qstate* sq)
|
|
||||||
{
|
|
||||||
verbose(VERB_ALGO, "subnetcache: make subquery to look up without subnet");
|
|
||||||
if(!generate_sub_request(qstate, id, sq)) {
|
|
||||||
verbose(VERB_ALGO, "Could not generate sub query");
|
|
||||||
qstate->return_rcode = LDNS_RCODE_SERVFAIL;
|
|
||||||
qstate->return_msg = NULL;
|
|
||||||
return module_finished;
|
|
||||||
}
|
|
||||||
sq->wait_subquery = 1;
|
|
||||||
return module_wait_subquery;
|
|
||||||
}
|
|
||||||
|
|
||||||
static enum module_ext_state
|
static enum module_ext_state
|
||||||
eval_response(struct module_qstate *qstate, int id, struct subnet_qstate *sq)
|
eval_response(struct module_qstate *qstate, int id, struct subnet_qstate *sq)
|
||||||
{
|
{
|
||||||
@@ -718,17 +496,11 @@ eval_response(struct module_qstate *qstate, int id, struct subnet_qstate *sq)
|
|||||||
/* already an answer and its not a message, but retain
|
/* already an answer and its not a message, but retain
|
||||||
* the actual rcode, instead of module_error, so send
|
* the actual rcode, instead of module_error, so send
|
||||||
* module_finished */
|
* 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;
|
return module_finished;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We have not asked for subnet data */
|
/* We have not asked for subnet data */
|
||||||
if (!sq->subnet_sent && !sq->subnet_sent_no_subnet) {
|
if (!sq->subnet_sent) {
|
||||||
if (s_in->subnet_validdata)
|
if (s_in->subnet_validdata)
|
||||||
verbose(VERB_QUERY, "subnetcache: received spurious data");
|
verbose(VERB_QUERY, "subnetcache: received spurious data");
|
||||||
if (sq->subnet_downstream) /* Copy back to client */
|
if (sq->subnet_downstream) /* Copy back to client */
|
||||||
@@ -737,25 +509,20 @@ eval_response(struct module_qstate *qstate, int id, struct subnet_qstate *sq)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* subnet sent but nothing came back */
|
/* subnet sent but nothing came back */
|
||||||
if (!s_in->subnet_validdata && !sq->subnet_sent_no_subnet) {
|
if (!s_in->subnet_validdata) {
|
||||||
/* The authority indicated no support for edns subnet. As a
|
/* The authority indicated no support for edns subnet. As a
|
||||||
* consequence the answer ended up in the regular cache. It
|
* consequence the answer ended up in the regular cache. It
|
||||||
* is still useful to put it in the edns subnet cache for
|
* is still useful to put it in the edns subnet cache for
|
||||||
* when a client explicitly asks for subnet specific answer. */
|
* when a client explicitly asks for subnet specific answer. */
|
||||||
verbose(VERB_QUERY, "subnetcache: Authority indicates no support");
|
verbose(VERB_QUERY, "subnetcache: Authority indicates no support");
|
||||||
return generate_lookup_without_subnet(qstate, id, sq);
|
if(!sq->started_no_cache_store) {
|
||||||
}
|
lock_rw_wrlock(&sne->biglock);
|
||||||
|
update_cache(qstate, id);
|
||||||
/* Purposefully there was no sent subnet, and there is consequently
|
lock_rw_unlock(&sne->biglock);
|
||||||
* no subnet in the answer. If there was, use the subnet in the answer
|
}
|
||||||
* anyway. But if there is not, treat it as a prefix 0 answer. */
|
if (sq->subnet_downstream)
|
||||||
if(sq->subnet_sent_no_subnet && !s_in->subnet_validdata) {
|
cp_edns_bad_response(c_out, c_in);
|
||||||
/* Fill in 0.0.0.0/0 scope 0, or ::0/0 scope 0, for caching. */
|
return module_finished;
|
||||||
s_in->subnet_addr_fam = s_out->subnet_addr_fam;
|
|
||||||
s_in->subnet_source_mask = 0;
|
|
||||||
s_in->subnet_scope_mask = 0;
|
|
||||||
memset(s_in->subnet_addr, 0, INET6_SIZE);
|
|
||||||
s_in->subnet_validdata = 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Being here means we have asked for and got a subnet specific
|
/* Being here means we have asked for and got a subnet specific
|
||||||
@@ -768,14 +535,13 @@ eval_response(struct module_qstate *qstate, int id, struct subnet_qstate *sq)
|
|||||||
!common_prefix(s_out->subnet_addr, s_in->subnet_addr,
|
!common_prefix(s_out->subnet_addr, s_in->subnet_addr,
|
||||||
s_out->subnet_source_mask))
|
s_out->subnet_source_mask))
|
||||||
{
|
{
|
||||||
/* we can not accept, perform query without option */
|
/* we can not accept, restart query without option */
|
||||||
verbose(VERB_QUERY, "subnetcache: forged data");
|
verbose(VERB_QUERY, "subnetcache: forged data");
|
||||||
s_out->subnet_validdata = 0;
|
s_out->subnet_validdata = 0;
|
||||||
(void)edns_opt_list_remove(&qstate->edns_opts_back_out,
|
(void)edns_opt_list_remove(&qstate->edns_opts_back_out,
|
||||||
qstate->env->cfg->client_subnet_opcode);
|
qstate->env->cfg->client_subnet_opcode);
|
||||||
sq->subnet_sent = 0;
|
sq->subnet_sent = 0;
|
||||||
sq->subnet_sent_no_subnet = 0;
|
return module_restart_next;
|
||||||
return generate_lookup_without_subnet(qstate, id, sq);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
lock_rw_wrlock(&sne->biglock);
|
lock_rw_wrlock(&sne->biglock);
|
||||||
@@ -785,20 +551,6 @@ eval_response(struct module_qstate *qstate, int id, struct subnet_qstate *sq)
|
|||||||
sne->num_msg_nocache++;
|
sne->num_msg_nocache++;
|
||||||
lock_rw_unlock(&sne->biglock);
|
lock_rw_unlock(&sne->biglock);
|
||||||
|
|
||||||
/* If there is an expired answer in the global cache, remove that,
|
|
||||||
* because expired answers would otherwise resurface once the ecs data
|
|
||||||
* expires, giving once in a while global data responses for ecs
|
|
||||||
* domains, with serve expired enabled. */
|
|
||||||
if(qstate->env->cfg->serve_expired) {
|
|
||||||
msg_cache_remove(qstate->env, qstate->qinfo.qname,
|
|
||||||
qstate->qinfo.qname_len, qstate->qinfo.qtype,
|
|
||||||
qstate->qinfo.qclass, 0);
|
|
||||||
#ifdef USE_CACHEDB
|
|
||||||
if(qstate->env->cachedb_enabled)
|
|
||||||
cachedb_msg_remove(qstate);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sq->subnet_downstream) {
|
if (sq->subnet_downstream) {
|
||||||
/* Client wants to see the answer, echo option back
|
/* Client wants to see the answer, echo option back
|
||||||
* and adjust the scope. */
|
* and adjust the scope. */
|
||||||
@@ -909,7 +661,6 @@ ecs_query_response(struct module_qstate* qstate, struct dns_msg* response,
|
|||||||
edns_opt_list_remove(&qstate->edns_opts_back_out,
|
edns_opt_list_remove(&qstate->edns_opts_back_out,
|
||||||
qstate->env->cfg->client_subnet_opcode);
|
qstate->env->cfg->client_subnet_opcode);
|
||||||
sq->subnet_sent = 0;
|
sq->subnet_sent = 0;
|
||||||
sq->subnet_sent_no_subnet = 0;
|
|
||||||
memset(&sq->ecs_server_out, 0, sizeof(sq->ecs_server_out));
|
memset(&sq->ecs_server_out, 0, sizeof(sq->ecs_server_out));
|
||||||
} else if (!sq->track_max_scope &&
|
} else if (!sq->track_max_scope &&
|
||||||
FLAGS_GET_RCODE(response->rep->flags) == LDNS_RCODE_NOERROR &&
|
FLAGS_GET_RCODE(response->rep->flags) == LDNS_RCODE_NOERROR &&
|
||||||
@@ -971,14 +722,6 @@ ecs_edns_back_parsed(struct module_qstate* qstate, int id,
|
|||||||
sq->ecs_server_in.subnet_scope_mask >
|
sq->ecs_server_in.subnet_scope_mask >
|
||||||
sq->max_scope))
|
sq->max_scope))
|
||||||
sq->max_scope = sq->ecs_server_in.subnet_scope_mask;
|
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
@@ -996,33 +739,6 @@ subnetmod_operate(struct module_qstate *qstate, enum module_ev event,
|
|||||||
strmodulevent(event));
|
strmodulevent(event));
|
||||||
log_query_info(VERB_QUERY, "subnetcache operate: query", &qstate->qinfo);
|
log_query_info(VERB_QUERY, "subnetcache operate: query", &qstate->qinfo);
|
||||||
|
|
||||||
if(sq && sq->wait_subquery_done) {
|
|
||||||
/* The subquery lookup returned. */
|
|
||||||
if(sq->ecs_client_in.subnet_source_mask == 0 &&
|
|
||||||
edns_opt_list_find(qstate->edns_opts_front_in,
|
|
||||||
qstate->env->cfg->client_subnet_opcode)) {
|
|
||||||
if(!sq->started_no_cache_store &&
|
|
||||||
qstate->return_msg) {
|
|
||||||
lock_rw_wrlock(&sne->biglock);
|
|
||||||
update_cache(qstate, id);
|
|
||||||
lock_rw_unlock(&sne->biglock);
|
|
||||||
}
|
|
||||||
if (sq->subnet_downstream)
|
|
||||||
cp_edns_bad_response(&sq->ecs_client_out,
|
|
||||||
&sq->ecs_client_in);
|
|
||||||
/* It is a scope zero lookup, append edns subnet
|
|
||||||
* option to the querier. */
|
|
||||||
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;
|
|
||||||
qstate->no_cache_store = sq->started_no_cache_store;
|
|
||||||
qstate->no_cache_lookup = sq->started_no_cache_lookup;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if((event == module_event_new || event == module_event_pass) &&
|
if((event == module_event_new || event == module_event_pass) &&
|
||||||
sq == NULL) {
|
sq == NULL) {
|
||||||
struct edns_option* ecs_opt;
|
struct edns_option* ecs_opt;
|
||||||
@@ -1033,8 +749,6 @@ subnetmod_operate(struct module_qstate *qstate, enum module_ev event,
|
|||||||
}
|
}
|
||||||
|
|
||||||
sq = (struct subnet_qstate*)qstate->minfo[id];
|
sq = (struct subnet_qstate*)qstate->minfo[id];
|
||||||
if(sq->wait_subquery)
|
|
||||||
return; /* Wait for that subquery to return */
|
|
||||||
|
|
||||||
if((ecs_opt = edns_opt_list_find(
|
if((ecs_opt = edns_opt_list_find(
|
||||||
qstate->edns_opts_front_in,
|
qstate->edns_opts_front_in,
|
||||||
@@ -1054,24 +768,11 @@ subnetmod_operate(struct module_qstate *qstate, enum module_ev event,
|
|||||||
&qstate->mesh_info->reply_list->query_reply.client_addr,
|
&qstate->mesh_info->reply_list->query_reply.client_addr,
|
||||||
&sq->ecs_client_in, qstate->env->cfg);
|
&sq->ecs_client_in, qstate->env->cfg);
|
||||||
}
|
}
|
||||||
else if(qstate->client_addr.ss_family != AF_UNSPEC) {
|
|
||||||
subnet_option_from_ss(
|
|
||||||
&qstate->client_addr,
|
|
||||||
&sq->ecs_client_in, qstate->env->cfg);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(sq->ecs_client_in.subnet_validdata == 0) {
|
if(sq->ecs_client_in.subnet_validdata == 0) {
|
||||||
/* No clients are interested in result or we could not
|
/* No clients are interested in result or we could not
|
||||||
* parse it, we don't do client subnet */
|
* parse it, we don't do client subnet */
|
||||||
sq->ecs_server_out.subnet_validdata = 0;
|
sq->ecs_server_out.subnet_validdata = 0;
|
||||||
if(edns_opt_list_find(qstate->edns_opts_front_in,
|
|
||||||
qstate->env->cfg->client_subnet_opcode)) {
|
|
||||||
/* aggregated this deaggregated state */
|
|
||||||
qstate->ext_state[id] =
|
|
||||||
generate_lookup_without_subnet(
|
|
||||||
qstate, id, sq);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
verbose(VERB_ALGO, "subnetcache: pass to next module");
|
verbose(VERB_ALGO, "subnetcache: pass to next module");
|
||||||
qstate->ext_state[id] = module_wait_module;
|
qstate->ext_state[id] = module_wait_module;
|
||||||
return;
|
return;
|
||||||
@@ -1090,12 +791,9 @@ subnetmod_operate(struct module_qstate *qstate, enum module_ev event,
|
|||||||
|
|
||||||
if(!sq->started_no_cache_lookup && !qstate->blacklist) {
|
if(!sq->started_no_cache_lookup && !qstate->blacklist) {
|
||||||
lock_rw_wrlock(&sne->biglock);
|
lock_rw_wrlock(&sne->biglock);
|
||||||
if(qstate->mesh_info->reply_list &&
|
if(lookup_and_reply(qstate, id, sq)) {
|
||||||
lookup_and_reply(qstate, id, sq,
|
|
||||||
qstate->env->cfg->prefetch)) {
|
|
||||||
sne->num_msg_cache++;
|
sne->num_msg_cache++;
|
||||||
lock_rw_unlock(&sne->biglock);
|
lock_rw_unlock(&sne->biglock);
|
||||||
qstate->is_subnet_answer = 1;
|
|
||||||
verbose(VERB_QUERY, "subnetcache: answered from cache");
|
verbose(VERB_QUERY, "subnetcache: answered from cache");
|
||||||
qstate->ext_state[id] = module_finished;
|
qstate->ext_state[id] = module_finished;
|
||||||
|
|
||||||
@@ -1113,14 +811,6 @@ subnetmod_operate(struct module_qstate *qstate, enum module_ev event,
|
|||||||
}
|
}
|
||||||
lock_rw_unlock(&sne->biglock);
|
lock_rw_unlock(&sne->biglock);
|
||||||
}
|
}
|
||||||
if(sq->ecs_client_in.subnet_source_mask == 0 &&
|
|
||||||
edns_opt_list_find(qstate->edns_opts_front_in,
|
|
||||||
qstate->env->cfg->client_subnet_opcode)) {
|
|
||||||
/* client asked for resolution without edns subnet */
|
|
||||||
qstate->ext_state[id] = generate_lookup_without_subnet(
|
|
||||||
qstate, id, sq);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
sq->ecs_server_out.subnet_addr_fam =
|
sq->ecs_server_out.subnet_addr_fam =
|
||||||
sq->ecs_client_in.subnet_addr_fam;
|
sq->ecs_client_in.subnet_addr_fam;
|
||||||
@@ -1157,8 +847,6 @@ subnetmod_operate(struct module_qstate *qstate, enum module_ev event,
|
|||||||
qstate->ext_state[id] = module_wait_module;
|
qstate->ext_state[id] = module_wait_module;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(sq && sq->wait_subquery)
|
|
||||||
return; /* Wait for that subquery to return */
|
|
||||||
/* Query handed back by next module, we have a 'final' answer */
|
/* Query handed back by next module, we have a 'final' answer */
|
||||||
if(sq && event == module_event_moddone) {
|
if(sq && event == module_event_moddone) {
|
||||||
qstate->ext_state[id] = eval_response(qstate, id, sq);
|
qstate->ext_state[id] = eval_response(qstate, id, sq);
|
||||||
@@ -1167,8 +855,6 @@ subnetmod_operate(struct module_qstate *qstate, enum module_ev event,
|
|||||||
subnet_ecs_opt_list_append(&sq->ecs_client_out,
|
subnet_ecs_opt_list_append(&sq->ecs_client_out,
|
||||||
&qstate->edns_opts_front_out, qstate,
|
&qstate->edns_opts_front_out, qstate,
|
||||||
qstate->region);
|
qstate->region);
|
||||||
if(sq->subnet_sent || sq->subnet_sent_no_subnet)
|
|
||||||
qstate->is_subnet_answer = 1;
|
|
||||||
if(verbosity >= VERB_ALGO) {
|
if(verbosity >= VERB_ALGO) {
|
||||||
subnet_log_print("reply has edns subnet",
|
subnet_log_print("reply has edns subnet",
|
||||||
edns_opt_list_find(
|
edns_opt_list_find(
|
||||||
@@ -1209,27 +895,10 @@ subnetmod_clear(struct module_qstate *ATTR_UNUSED(qstate),
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
subnetmod_inform_super(struct module_qstate *qstate, int id,
|
subnetmod_inform_super(struct module_qstate *ATTR_UNUSED(qstate),
|
||||||
struct module_qstate *super)
|
int ATTR_UNUSED(id), struct module_qstate *ATTR_UNUSED(super))
|
||||||
{
|
{
|
||||||
struct subnet_qstate* super_sq =
|
/* Not used */
|
||||||
(struct subnet_qstate*)super->minfo[id];
|
|
||||||
log_query_info(VERB_ALGO, "subnetcache inform_super: query",
|
|
||||||
&super->qinfo);
|
|
||||||
super_sq->wait_subquery = 0;
|
|
||||||
super_sq->wait_subquery_done = 1;
|
|
||||||
if(qstate->return_rcode != LDNS_RCODE_NOERROR ||
|
|
||||||
!qstate->return_msg) {
|
|
||||||
super->return_msg = NULL;
|
|
||||||
super->return_rcode = LDNS_RCODE_SERVFAIL;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
super->return_rcode = LDNS_RCODE_NOERROR;
|
|
||||||
super->return_msg = dns_copy_msg(qstate->return_msg, super->region);
|
|
||||||
if(!super->return_msg) {
|
|
||||||
log_err("subnetcache: copy response, out of memory");
|
|
||||||
super->return_rcode = LDNS_RCODE_SERVFAIL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t
|
size_t
|
||||||
@@ -1246,8 +915,7 @@ subnetmod_get_mem(struct module_env *env, int id)
|
|||||||
* The module function block
|
* The module function block
|
||||||
*/
|
*/
|
||||||
static struct module_func_block subnetmod_block = {
|
static struct module_func_block subnetmod_block = {
|
||||||
"subnetcache",
|
"subnetcache", &subnetmod_init, &subnetmod_deinit, &subnetmod_operate,
|
||||||
NULL, NULL, &subnetmod_init, &subnetmod_deinit, &subnetmod_operate,
|
|
||||||
&subnetmod_inform_super, &subnetmod_clear, &subnetmod_get_mem
|
&subnetmod_inform_super, &subnetmod_clear, &subnetmod_get_mem
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -69,18 +69,8 @@ struct subnet_env {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct subnet_msg_cache_data {
|
struct subnet_msg_cache_data {
|
||||||
/** Tree for nodes with IPv4 subnets. */
|
|
||||||
struct addrtree* tree4;
|
struct addrtree* tree4;
|
||||||
/** Tree for nodes with IPv6 subnets. */
|
|
||||||
struct addrtree* tree6;
|
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 {
|
struct subnet_qstate {
|
||||||
@@ -95,13 +85,6 @@ struct subnet_qstate {
|
|||||||
struct ecs_data ecs_server_out;
|
struct ecs_data ecs_server_out;
|
||||||
int subnet_downstream;
|
int subnet_downstream;
|
||||||
int subnet_sent;
|
int subnet_sent;
|
||||||
/**
|
|
||||||
* If there was no subnet sent because the client used source prefix
|
|
||||||
* length 0 for omitting the information. Then the answer is cached
|
|
||||||
* like subnet was a /0 scope. Like the subnet_sent flag, but when
|
|
||||||
* the EDNS subnet option is omitted because the client asked.
|
|
||||||
*/
|
|
||||||
int subnet_sent_no_subnet;
|
|
||||||
/** keep track of longest received scope, set after receiving CNAME for
|
/** keep track of longest received scope, set after receiving CNAME for
|
||||||
* incoming QNAME. */
|
* incoming QNAME. */
|
||||||
int track_max_scope;
|
int track_max_scope;
|
||||||
@@ -112,14 +95,6 @@ struct subnet_qstate {
|
|||||||
int started_no_cache_store;
|
int started_no_cache_store;
|
||||||
/** has the subnet module been started with no_cache_lookup? */
|
/** has the subnet module been started with no_cache_lookup? */
|
||||||
int started_no_cache_lookup;
|
int started_no_cache_lookup;
|
||||||
/** Wait for subquery that has been started for nonsubnet lookup. */
|
|
||||||
int wait_subquery;
|
|
||||||
/** The subquery waited for is done. */
|
|
||||||
int wait_subquery_done;
|
|
||||||
/** The subnet state is a subquery state for nonsubnet lookup. */
|
|
||||||
int is_subquery_nonsubnet;
|
|
||||||
/** This is a subquery, and it is made due to a scope zero request. */
|
|
||||||
int is_subquery_scopezero;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void subnet_data_delete(void* d, void* ATTR_UNUSED(arg));
|
void subnet_data_delete(void* d, void* ATTR_UNUSED(arg));
|
||||||
|
|||||||
@@ -100,8 +100,6 @@ ipsecmod_whitelist_apply_cfg(struct ipsecmod_env* ie,
|
|||||||
struct config_file* cfg)
|
struct config_file* cfg)
|
||||||
{
|
{
|
||||||
ie->whitelist = rbtree_create(name_tree_compare);
|
ie->whitelist = rbtree_create(name_tree_compare);
|
||||||
if (!ie->whitelist)
|
|
||||||
return 0;
|
|
||||||
if(!read_whitelist(ie->whitelist, cfg))
|
if(!read_whitelist(ie->whitelist, cfg))
|
||||||
return 0;
|
return 0;
|
||||||
name_tree_init_parents(ie->whitelist);
|
name_tree_init_parents(ie->whitelist);
|
||||||
|
|||||||
+40
-95
@@ -51,28 +51,18 @@
|
|||||||
#include "util/config_file.h"
|
#include "util/config_file.h"
|
||||||
#include "services/cache/dns.h"
|
#include "services/cache/dns.h"
|
||||||
#include "sldns/wire2str.h"
|
#include "sldns/wire2str.h"
|
||||||
#ifdef HAVE_SYS_WAIT_H
|
|
||||||
#include <sys/wait.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/** Apply configuration to ipsecmod module 'global' state. */
|
/** Apply configuration to ipsecmod module 'global' state. */
|
||||||
static int
|
static int
|
||||||
ipsecmod_apply_cfg(struct ipsecmod_env* ipsecmod_env, struct config_file* cfg)
|
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])) {
|
if(!cfg->ipsecmod_hook || (cfg->ipsecmod_hook && !cfg->ipsecmod_hook[0])) {
|
||||||
log_err("ipsecmod: missing ipsecmod-hook.");
|
log_err("ipsecmod: missing ipsecmod-hook.");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if(access(cfg->ipsecmod_hook, X_OK) != 0) {
|
if(cfg->ipsecmod_whitelist &&
|
||||||
log_err("ipsecmod: ipsecmod-hook '%s' is not an executable file: %s",
|
!ipsecmod_whitelist_apply_cfg(ipsecmod_env, cfg))
|
||||||
cfg->ipsecmod_hook, strerror(errno));
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -173,7 +163,7 @@ generate_request(struct module_qstate* qstate, int id, uint8_t* name,
|
|||||||
}
|
}
|
||||||
|
|
||||||
fptr_ok(fptr_whitelist_modenv_attach_sub(qstate->env->attach_sub));
|
fptr_ok(fptr_whitelist_modenv_attach_sub(qstate->env->attach_sub));
|
||||||
if(!(*qstate->env->attach_sub)(qstate, &ask, NULL,
|
if(!(*qstate->env->attach_sub)(qstate, &ask,
|
||||||
(uint16_t)(BIT_RD|flags), 0, 0, &newq)){
|
(uint16_t)(BIT_RD|flags), 0, 0, &newq)){
|
||||||
log_err("Could not generate request: out of memory");
|
log_err("Could not generate request: out of memory");
|
||||||
return 0;
|
return 0;
|
||||||
@@ -260,16 +250,27 @@ call_hook(struct module_qstate* qstate, struct ipsecmod_qstate* iq,
|
|||||||
struct ipsecmod_env* ATTR_UNUSED(ie))
|
struct ipsecmod_env* ATTR_UNUSED(ie))
|
||||||
{
|
{
|
||||||
size_t slen, tempdata_len, tempstring_len, i;
|
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 str[65535], *s, *tempstring;
|
||||||
char *s, *tempstring;
|
|
||||||
int w = 0, w_temp, qtype;
|
int w = 0, w_temp, qtype;
|
||||||
struct ub_packed_rrset_key* rrset_key;
|
struct ub_packed_rrset_key* rrset_key;
|
||||||
struct packed_rrset_data* rrset_data;
|
struct packed_rrset_data* rrset_data;
|
||||||
uint8_t *tempdata;
|
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. */
|
/* Copy the qname into the buffer. */
|
||||||
tempstring = sldns_wire2str_dname(qstate->qinfo.qname,
|
tempstring = sldns_wire2str_dname(qstate->qinfo.qname,
|
||||||
qstate->qinfo.qname_len);
|
qstate->qinfo.qname_len);
|
||||||
@@ -282,24 +283,17 @@ call_hook(struct module_qstate* qstate, struct ipsecmod_qstate* iq,
|
|||||||
free(tempstring);
|
free(tempstring);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if(strlen(tempstring)+1 > sizeof(qname_s)) {
|
w += sldns_str_print(&s, &slen, "\"%s\"", tempstring);
|
||||||
log_err("ipsecmod: string too long");
|
|
||||||
free(tempstring);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
snprintf(qname_s, sizeof(qname_s), "%s", tempstring);
|
|
||||||
free(tempstring);
|
free(tempstring);
|
||||||
|
/* Put space into the buffer. */
|
||||||
|
w += sldns_str_print(&s, &slen, " ");
|
||||||
/* Copy the IPSECKEY TTL into the buffer. */
|
/* Copy the IPSECKEY TTL into the buffer. */
|
||||||
rrset_data = (struct packed_rrset_data*)iq->ipseckey_rrset->entry.data;
|
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,
|
rrset_key = reply_find_answer_rrset(&qstate->return_msg->qinfo,
|
||||||
qstate->return_msg->rep);
|
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.
|
/* Double check that the records are indeed A/AAAA.
|
||||||
* This should never happen as this function is only executed for 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
|
* 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;
|
return 0;
|
||||||
}
|
}
|
||||||
rrset_data = (struct packed_rrset_data*)rrset_key->entry.data;
|
rrset_data = (struct packed_rrset_data*)rrset_key->entry.data;
|
||||||
if(!rrset_data) {
|
/* Copy the A/AAAA record(s) into the buffer. Start and end this section
|
||||||
log_err("ipsecmod: Answer has no data");
|
* with a double quote. */
|
||||||
return 0;
|
w += sldns_str_print(&s, &slen, "\"");
|
||||||
}
|
|
||||||
/* Copy the A/AAAA record(s) into the buffer. */
|
|
||||||
w = 0;
|
|
||||||
s = a_s;
|
|
||||||
slen = sizeof(a_s);
|
|
||||||
memset(s, 0, slen);
|
|
||||||
for(i=0; i<rrset_data->count; i++) {
|
for(i=0; i<rrset_data->count; i++) {
|
||||||
if(i > 0) {
|
if(i > 0) {
|
||||||
/* Put space into the buffer. */
|
/* 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) {
|
} else if((size_t)w_temp >= slen) {
|
||||||
s = NULL; /* We do not want str to point outside of buffer. */
|
s = NULL; /* We do not want str to point outside of buffer. */
|
||||||
slen = 0;
|
slen = 0;
|
||||||
log_err("ipsecmod: command addr argument too long");
|
log_err("ipsecmod: shell command too long");
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
s += w_temp;
|
s += w_temp;
|
||||||
@@ -342,17 +330,12 @@ call_hook(struct module_qstate* qstate, struct ipsecmod_qstate* iq,
|
|||||||
w += w_temp;
|
w += w_temp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(w >= (int)sizeof(a_s)) {
|
w += sldns_str_print(&s, &slen, "\"");
|
||||||
log_err("ipsecmod: command addr argument too long");
|
/* Put space into the buffer. */
|
||||||
return 0;
|
w += sldns_str_print(&s, &slen, " ");
|
||||||
}
|
|
||||||
|
|
||||||
/* Copy the IPSECKEY record(s) into the buffer. Start and end this section
|
/* Copy the IPSECKEY record(s) into the buffer. Start and end this section
|
||||||
* with a double quote. */
|
* with a double quote. */
|
||||||
w = 0;
|
w += sldns_str_print(&s, &slen, "\"");
|
||||||
s = k_s;
|
|
||||||
slen = sizeof(k_s);
|
|
||||||
memset(s, 0, slen);
|
|
||||||
rrset_data = (struct packed_rrset_data*)iq->ipseckey_rrset->entry.data;
|
rrset_data = (struct packed_rrset_data*)iq->ipseckey_rrset->entry.data;
|
||||||
for(i=0; i<rrset_data->count; i++) {
|
for(i=0; i<rrset_data->count; i++) {
|
||||||
if(i > 0) {
|
if(i > 0) {
|
||||||
@@ -379,44 +362,15 @@ call_hook(struct module_qstate* qstate, struct ipsecmod_qstate* iq,
|
|||||||
w += w_temp;
|
w += w_temp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(w >= (int)sizeof(k_s)) {
|
w += sldns_str_print(&s, &slen, "\"");
|
||||||
log_err("ipsecmod: command ipseckey argument too long");
|
if(w >= (int)sizeof(str)) {
|
||||||
|
log_err("ipsecmod: shell command too long");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
verbose(VERB_ALGO, "ipsecmod: shell command: '%s'", str);
|
||||||
/* ipsecmod-hook should return 0 on success. */
|
/* ipsecmod-hook should return 0 on success. */
|
||||||
/* exec the ipsecmod-hook */
|
if(system(str) != 0)
|
||||||
argv[0] = qstate->env->cfg->ipsecmod_hook;
|
|
||||||
argv[1] = qname_s;
|
|
||||||
argv[2] = ttl_s;
|
|
||||||
argv[3] = a_s;
|
|
||||||
argv[4] = k_s;
|
|
||||||
argv[5] = NULL;
|
|
||||||
verbose(VERB_ALGO, "ipsecmod: exec %s \"%s\" %s \"%s\" \"%s\"",
|
|
||||||
argv[0], argv[1], argv[2], argv[3], argv[4]);
|
|
||||||
if((pid = fork()) < 0) {
|
|
||||||
log_err("ipsecmod: for exec, can not fork: %s",
|
|
||||||
strerror(errno));
|
|
||||||
return 0;
|
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;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -481,12 +435,6 @@ ipsecmod_handle_query(struct module_qstate* qstate,
|
|||||||
* ipsecmod_max_ttl. */
|
* ipsecmod_max_ttl. */
|
||||||
rrset_key = reply_find_answer_rrset(&qstate->return_msg->qinfo,
|
rrset_key = reply_find_answer_rrset(&qstate->return_msg->qinfo,
|
||||||
qstate->return_msg->rep);
|
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;
|
rrset_data = (struct packed_rrset_data*)rrset_key->entry.data;
|
||||||
if(rrset_data->ttl > (time_t)qstate->env->cfg->ipsecmod_max_ttl) {
|
if(rrset_data->ttl > (time_t)qstate->env->cfg->ipsecmod_max_ttl) {
|
||||||
/* Update TTL for rrset to fixed value. */
|
/* Update TTL for rrset to fixed value. */
|
||||||
@@ -508,8 +456,7 @@ ipsecmod_handle_query(struct module_qstate* qstate,
|
|||||||
/* Store A/AAAA in cache. */
|
/* Store A/AAAA in cache. */
|
||||||
if(!dns_cache_store(qstate->env, &qstate->qinfo,
|
if(!dns_cache_store(qstate->env, &qstate->qinfo,
|
||||||
qstate->return_msg->rep, 0, qstate->prefetch_leeway,
|
qstate->return_msg->rep, 0, qstate->prefetch_leeway,
|
||||||
0, qstate->region, qstate->query_flags, qstate->qstarttime,
|
0, qstate->region, qstate->query_flags, qstate->qstarttime)) {
|
||||||
qstate->is_valrec)) {
|
|
||||||
log_err("ipsecmod: out of memory caching record");
|
log_err("ipsecmod: out of memory caching record");
|
||||||
}
|
}
|
||||||
qstate->ext_state[id] = module_finished;
|
qstate->ext_state[id] = module_finished;
|
||||||
@@ -628,8 +575,6 @@ ipsecmod_inform_super(struct module_qstate* qstate, int id,
|
|||||||
verbose(VERB_ALGO, "super has no ipsecmod state");
|
verbose(VERB_ALGO, "super has no ipsecmod state");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(!siq->enabled)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if(qstate->return_msg) {
|
if(qstate->return_msg) {
|
||||||
struct ub_packed_rrset_key* rrset_key = reply_find_answer_rrset(
|
struct ub_packed_rrset_key* rrset_key = reply_find_answer_rrset(
|
||||||
@@ -670,7 +615,7 @@ ipsecmod_get_mem(struct module_env* env, int id)
|
|||||||
*/
|
*/
|
||||||
static struct module_func_block ipsecmod_block = {
|
static struct module_func_block ipsecmod_block = {
|
||||||
"ipsecmod",
|
"ipsecmod",
|
||||||
NULL, NULL, &ipsecmod_init, &ipsecmod_deinit, &ipsecmod_operate,
|
&ipsecmod_init, &ipsecmod_deinit, &ipsecmod_operate,
|
||||||
&ipsecmod_inform_super, &ipsecmod_clear, &ipsecmod_get_mem
|
&ipsecmod_inform_super, &ipsecmod_clear, &ipsecmod_get_mem
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
+57
-175
@@ -17,19 +17,9 @@
|
|||||||
#include "sldns/wire2str.h"
|
#include "sldns/wire2str.h"
|
||||||
#include "sldns/parseutil.h"
|
#include "sldns/parseutil.h"
|
||||||
|
|
||||||
#ifdef HAVE_NET_PFVAR_H
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <sys/ioctl.h>
|
|
||||||
#include <netinet/in.h>
|
|
||||||
#include <net/if.h>
|
|
||||||
#include <net/pfvar.h>
|
|
||||||
typedef intptr_t filter_dev;
|
|
||||||
#else
|
|
||||||
#include <libmnl/libmnl.h>
|
#include <libmnl/libmnl.h>
|
||||||
#include <linux/netfilter/nfnetlink.h>
|
#include <linux/netfilter/nfnetlink.h>
|
||||||
#include <linux/netfilter/ipset/ip_set.h>
|
#include <linux/netfilter/ipset/ip_set.h>
|
||||||
typedef struct mnl_socket * filter_dev;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define BUFF_LEN 256
|
#define BUFF_LEN 256
|
||||||
|
|
||||||
@@ -51,99 +41,28 @@ static int error_response(struct module_qstate* qstate, int id, int rcode) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_NET_PFVAR_H
|
static struct mnl_socket * open_mnl_socket() {
|
||||||
static void * open_filter() {
|
struct mnl_socket *mnl;
|
||||||
filter_dev dev;
|
|
||||||
|
|
||||||
dev = open("/dev/pf", O_RDWR);
|
mnl = mnl_socket_open(NETLINK_NETFILTER);
|
||||||
if (dev == -1) {
|
if (!mnl) {
|
||||||
log_err("open(\"/dev/pf\") failed: %s", strerror(errno));
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return (void *)dev;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
static void * open_filter() {
|
|
||||||
filter_dev dev;
|
|
||||||
|
|
||||||
dev = mnl_socket_open(NETLINK_NETFILTER);
|
|
||||||
if (!dev) {
|
|
||||||
log_err("ipset: could not open netfilter.");
|
log_err("ipset: could not open netfilter.");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mnl_socket_bind(dev, 0, MNL_SOCKET_AUTOPID) < 0) {
|
if (mnl_socket_bind(mnl, 0, MNL_SOCKET_AUTOPID) < 0) {
|
||||||
mnl_socket_close(dev);
|
mnl_socket_close(mnl);
|
||||||
log_err("ipset: could not bind netfilter.");
|
log_err("ipset: could not bind netfilter.");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
return (void *)dev;
|
return mnl;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef HAVE_NET_PFVAR_H
|
static int add_to_ipset(struct mnl_socket *mnl, const char *setname, const void *ipaddr, int af) {
|
||||||
static int add_to_ipset(filter_dev dev, const char *setname, const void *ipaddr, int af) {
|
|
||||||
struct pfioc_table io;
|
|
||||||
struct pfr_addr addr;
|
|
||||||
const char *p;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
bzero(&io, sizeof(io));
|
|
||||||
bzero(&addr, sizeof(addr));
|
|
||||||
|
|
||||||
p = strrchr(setname, '/');
|
|
||||||
if (p) {
|
|
||||||
i = p - setname;
|
|
||||||
if (i >= PATH_MAX) {
|
|
||||||
errno = ENAMETOOLONG;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
memcpy(io.pfrio_table.pfrt_anchor, setname, i);
|
|
||||||
if (i < PATH_MAX)
|
|
||||||
io.pfrio_table.pfrt_anchor[i] = '\0';
|
|
||||||
p++;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
p = setname;
|
|
||||||
|
|
||||||
if (strlen(p) >= PF_TABLE_NAME_SIZE) {
|
|
||||||
errno = ENAMETOOLONG;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
strlcpy(io.pfrio_table.pfrt_name, p, PF_TABLE_NAME_SIZE);
|
|
||||||
|
|
||||||
io.pfrio_buffer = &addr;
|
|
||||||
io.pfrio_size = 1;
|
|
||||||
io.pfrio_esize = sizeof(addr);
|
|
||||||
|
|
||||||
switch (af) {
|
|
||||||
case AF_INET:
|
|
||||||
addr.pfra_ip4addr = *(struct in_addr *)ipaddr;
|
|
||||||
addr.pfra_net = 32;
|
|
||||||
break;
|
|
||||||
case AF_INET6:
|
|
||||||
addr.pfra_ip6addr = *(struct in6_addr *)ipaddr;
|
|
||||||
addr.pfra_net = 128;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
errno = EAFNOSUPPORT;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
addr.pfra_af = af;
|
|
||||||
|
|
||||||
if (ioctl(dev, DIOCRADDADDRS, &io) == -1) {
|
|
||||||
log_err("ioctl failed: %s", strerror(errno));
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
static int add_to_ipset(filter_dev dev, const char *setname, const void *ipaddr, int af) {
|
|
||||||
struct nlmsghdr *nlh;
|
struct nlmsghdr *nlh;
|
||||||
struct nfgenmsg *nfg;
|
struct nfgenmsg *nfg;
|
||||||
struct nlattr *nested[2];
|
struct nlattr *nested[2];
|
||||||
char buffer[BUFF_LEN];
|
static char buffer[BUFF_LEN];
|
||||||
|
|
||||||
if (strlen(setname) >= IPSET_MAXNAMELEN) {
|
if (strlen(setname) >= IPSET_MAXNAMELEN) {
|
||||||
errno = ENAMETOOLONG;
|
errno = ENAMETOOLONG;
|
||||||
@@ -172,15 +91,14 @@ static int add_to_ipset(filter_dev dev, const char *setname, const void *ipaddr,
|
|||||||
mnl_attr_nest_end(nlh, nested[1]);
|
mnl_attr_nest_end(nlh, nested[1]);
|
||||||
mnl_attr_nest_end(nlh, nested[0]);
|
mnl_attr_nest_end(nlh, nested[0]);
|
||||||
|
|
||||||
if (mnl_socket_sendto(dev, nlh, nlh->nlmsg_len) < 0) {
|
if (mnl_socket_sendto(mnl, nlh, nlh->nlmsg_len) < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
ipset_add_rrset_data(struct ipset_env *ie,
|
ipset_add_rrset_data(struct ipset_env *ie, struct mnl_socket *mnl,
|
||||||
struct packed_rrset_data *d, const char* setname, int af,
|
struct packed_rrset_data *d, const char* setname, int af,
|
||||||
const char* dname)
|
const char* dname)
|
||||||
{
|
{
|
||||||
@@ -205,9 +123,12 @@ ipset_add_rrset_data(struct ipset_env *ie,
|
|||||||
snprintf(ip, sizeof(ip), "(inet_ntop_error)");
|
snprintf(ip, sizeof(ip), "(inet_ntop_error)");
|
||||||
verbose(VERB_QUERY, "ipset: add %s to %s for %s", ip, setname, dname);
|
verbose(VERB_QUERY, "ipset: add %s to %s for %s", ip, setname, dname);
|
||||||
}
|
}
|
||||||
ret = add_to_ipset((filter_dev)ie->dev, setname, rr_data + 2, af);
|
ret = add_to_ipset(mnl, setname, rr_data + 2, af);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
log_err("ipset: could not add %s into %s", dname, setname);
|
log_err("ipset: could not add %s into %s", dname, setname);
|
||||||
|
|
||||||
|
mnl_socket_close(mnl);
|
||||||
|
ie->mnl = NULL;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -216,46 +137,38 @@ ipset_add_rrset_data(struct ipset_env *ie,
|
|||||||
|
|
||||||
static int
|
static int
|
||||||
ipset_check_zones_for_rrset(struct module_env *env, struct ipset_env *ie,
|
ipset_check_zones_for_rrset(struct module_env *env, struct ipset_env *ie,
|
||||||
struct ub_packed_rrset_key *rrset, const char *qname, int qlen,
|
struct mnl_socket *mnl, struct ub_packed_rrset_key *rrset,
|
||||||
const char *setname, int af)
|
const char *qname, const int qlen, const char *setname, int af)
|
||||||
{
|
{
|
||||||
char dname[LDNS_MAX_DOMAINLEN*4+16];
|
static char dname[BUFF_LEN];
|
||||||
const char *ds, *qs;
|
const char *ds, *qs;
|
||||||
int dlen, plen;
|
int dlen, plen;
|
||||||
|
|
||||||
struct config_strlist *p;
|
struct config_strlist *p;
|
||||||
struct packed_rrset_data *d;
|
struct packed_rrset_data *d;
|
||||||
|
|
||||||
dlen = sldns_wire2str_dname_buf(rrset->rk.dname, rrset->rk.dname_len, dname, sizeof(dname));
|
dlen = sldns_wire2str_dname_buf(rrset->rk.dname, rrset->rk.dname_len, dname, BUFF_LEN);
|
||||||
if (dlen == 0 || dlen >= (int)sizeof(dname)) {
|
if (dlen == 0) {
|
||||||
log_err("bad domain name");
|
log_err("bad domain name");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (dname[dlen - 1] == '.') {
|
|
||||||
dlen--;
|
|
||||||
}
|
|
||||||
if (qname[qlen - 1] == '.') {
|
|
||||||
qlen--;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (p = env->cfg->local_zones_ipset; p; p = p->next) {
|
for (p = env->cfg->local_zones_ipset; p; p = p->next) {
|
||||||
ds = NULL;
|
ds = NULL;
|
||||||
qs = NULL;
|
qs = NULL;
|
||||||
plen = strlen(p->str);
|
plen = strlen(p->str);
|
||||||
if (p->str[plen - 1] == '.') {
|
|
||||||
plen--;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dlen == plen || (dlen > plen && dname[dlen - plen - 1] == '.' )) {
|
if (dlen >= plen) {
|
||||||
ds = dname + (dlen - plen);
|
ds = dname + (dlen - plen);
|
||||||
}
|
}
|
||||||
if (qlen == plen || (qlen > plen && qname[qlen - plen - 1] == '.' )) {
|
if (qlen >= plen) {
|
||||||
qs = qname + (qlen - plen);
|
qs = qname + (qlen - plen);
|
||||||
}
|
}
|
||||||
if ((ds && strncasecmp(p->str, ds, plen) == 0)
|
if ((ds && strncasecmp(p->str, ds, plen) == 0)
|
||||||
|| (qs && strncasecmp(p->str, qs, plen) == 0)) {
|
|| (qs && strncasecmp(p->str, qs, plen) == 0)) {
|
||||||
d = (struct packed_rrset_data*)rrset->entry.data;
|
d = (struct packed_rrset_data*)rrset->entry.data;
|
||||||
ipset_add_rrset_data(ie, d, setname, af, dname);
|
ipset_add_rrset_data(ie, mnl, d, setname,
|
||||||
|
af, dname);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -265,28 +178,27 @@ ipset_check_zones_for_rrset(struct module_env *env, struct ipset_env *ie,
|
|||||||
static int ipset_update(struct module_env *env, struct dns_msg *return_msg,
|
static int ipset_update(struct module_env *env, struct dns_msg *return_msg,
|
||||||
struct query_info qinfo, struct ipset_env *ie)
|
struct query_info qinfo, struct ipset_env *ie)
|
||||||
{
|
{
|
||||||
|
struct mnl_socket *mnl;
|
||||||
size_t i;
|
size_t i;
|
||||||
const char *setname;
|
const char *setname;
|
||||||
struct ub_packed_rrset_key *rrset;
|
struct ub_packed_rrset_key *rrset;
|
||||||
int af;
|
int af;
|
||||||
char qname[LDNS_MAX_DOMAINLEN*4+16];
|
static char qname[BUFF_LEN];
|
||||||
int qlen;
|
int qlen;
|
||||||
|
|
||||||
#ifdef HAVE_NET_PFVAR_H
|
mnl = (struct mnl_socket *)ie->mnl;
|
||||||
#else
|
if (!mnl) {
|
||||||
if (!ie->dev) {
|
|
||||||
/* retry to create mnl socket */
|
/* retry to create mnl socket */
|
||||||
ie->dev = open_filter();
|
mnl = open_mnl_socket();
|
||||||
if (!ie->dev) {
|
if (!mnl) {
|
||||||
log_warn("ipset open_filter failed");
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
ie->mnl = mnl;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
qlen = sldns_wire2str_dname_buf(qinfo.qname, qinfo.qname_len,
|
qlen = sldns_wire2str_dname_buf(qinfo.qname, qinfo.qname_len,
|
||||||
qname, sizeof(qname));
|
qname, BUFF_LEN);
|
||||||
if(qlen == 0 || qlen >= (int)sizeof(qname)) {
|
if(qlen == 0) {
|
||||||
log_err("bad domain name");
|
log_err("bad domain name");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -305,8 +217,8 @@ static int ipset_update(struct module_env *env, struct dns_msg *return_msg,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (setname) {
|
if (setname) {
|
||||||
if(ipset_check_zones_for_rrset(env, ie, rrset, qname,
|
if(ipset_check_zones_for_rrset(env, ie, mnl, rrset,
|
||||||
qlen, setname, af) == -1)
|
qname, qlen, setname, af) == -1)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -314,7 +226,7 @@ static int ipset_update(struct module_env *env, struct dns_msg *return_msg,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ipset_startup(struct module_env* env, int id) {
|
int ipset_init(struct module_env* env, int id) {
|
||||||
struct ipset_env *ipset_env;
|
struct ipset_env *ipset_env;
|
||||||
|
|
||||||
ipset_env = (struct ipset_env *)calloc(1, sizeof(struct ipset_env));
|
ipset_env = (struct ipset_env *)calloc(1, sizeof(struct ipset_env));
|
||||||
@@ -325,56 +237,10 @@ int ipset_startup(struct module_env* env, int id) {
|
|||||||
|
|
||||||
env->modinfo[id] = (void *)ipset_env;
|
env->modinfo[id] = (void *)ipset_env;
|
||||||
|
|
||||||
#ifdef HAVE_NET_PFVAR_H
|
ipset_env->mnl = NULL;
|
||||||
ipset_env->dev = open_filter();
|
|
||||||
if (!ipset_env->dev) {
|
|
||||||
log_err("ipset open_filter failed");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
ipset_env->dev = NULL;
|
|
||||||
#endif
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ipset_destartup(struct module_env* env, int id) {
|
|
||||||
filter_dev dev;
|
|
||||||
struct ipset_env *ipset_env;
|
|
||||||
|
|
||||||
if (!env || !env->modinfo[id]) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
ipset_env = (struct ipset_env*)env->modinfo[id];
|
|
||||||
|
|
||||||
dev = (filter_dev)ipset_env->dev;
|
|
||||||
if (dev) {
|
|
||||||
#if HAVE_NET_PFVAR_H
|
|
||||||
close(dev);
|
|
||||||
#else
|
|
||||||
mnl_socket_close(dev);
|
|
||||||
#endif
|
|
||||||
ipset_env->dev = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
free(ipset_env);
|
|
||||||
env->modinfo[id] = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
int ipset_init(struct module_env* env, int id) {
|
|
||||||
struct ipset_env *ipset_env = env->modinfo[id];
|
|
||||||
|
|
||||||
ipset_env->name_v4 = env->cfg->ipset_name_v4;
|
ipset_env->name_v4 = env->cfg->ipset_name_v4;
|
||||||
ipset_env->name_v6 = env->cfg->ipset_name_v6;
|
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->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;
|
ipset_env->v6_enabled = !ipset_env->name_v6 || (strlen(ipset_env->name_v6) == 0) ? 0 : 1;
|
||||||
@@ -387,8 +253,24 @@ int ipset_init(struct module_env* env, int id) {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ipset_deinit(struct module_env *ATTR_UNUSED(env), int ATTR_UNUSED(id)) {
|
void ipset_deinit(struct module_env *env, int id) {
|
||||||
/* nothing */
|
struct mnl_socket *mnl;
|
||||||
|
struct ipset_env *ipset_env;
|
||||||
|
|
||||||
|
if (!env || !env->modinfo[id]) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ipset_env = (struct ipset_env *)env->modinfo[id];
|
||||||
|
|
||||||
|
mnl = (struct mnl_socket *)ipset_env->mnl;
|
||||||
|
if (mnl) {
|
||||||
|
mnl_socket_close(mnl);
|
||||||
|
ipset_env->mnl = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
free(ipset_env);
|
||||||
|
env->modinfo[id] = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ipset_new(struct module_qstate* qstate, int id) {
|
static int ipset_new(struct module_qstate* qstate, int id) {
|
||||||
@@ -494,8 +376,8 @@ size_t ipset_get_mem(struct module_env *env, int id) {
|
|||||||
*/
|
*/
|
||||||
static struct module_func_block ipset_block = {
|
static struct module_func_block ipset_block = {
|
||||||
"ipset",
|
"ipset",
|
||||||
&ipset_startup, &ipset_destartup, &ipset_init, &ipset_deinit,
|
&ipset_init, &ipset_deinit, &ipset_operate,
|
||||||
&ipset_operate, &ipset_inform_super, &ipset_clear, &ipset_get_mem
|
&ipset_inform_super, &ipset_clear, &ipset_get_mem
|
||||||
};
|
};
|
||||||
|
|
||||||
struct module_func_block * ipset_get_funcblock(void) {
|
struct module_func_block * ipset_get_funcblock(void) {
|
||||||
|
|||||||
+1
-5
@@ -37,7 +37,7 @@ extern "C" {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct ipset_env {
|
struct ipset_env {
|
||||||
void* dev;
|
void* mnl;
|
||||||
|
|
||||||
int v4_enabled;
|
int v4_enabled;
|
||||||
int v6_enabled;
|
int v6_enabled;
|
||||||
@@ -50,10 +50,6 @@ struct ipset_qstate {
|
|||||||
int dummy;
|
int dummy;
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Startup the ipset module */
|
|
||||||
int ipset_startup(struct module_env* env, int id);
|
|
||||||
/** Destartup the ipset module */
|
|
||||||
void ipset_destartup(struct module_env* env, int id);
|
|
||||||
/** Init the ipset module */
|
/** Init the ipset module */
|
||||||
int ipset_init(struct module_env* env, int id);
|
int ipset_init(struct module_env* env, int id);
|
||||||
/** Deinit the ipset module */
|
/** Deinit the ipset module */
|
||||||
|
|||||||
+25
-71
@@ -118,10 +118,10 @@ delegpt_add_ns(struct delegpt* dp, struct regional* region, uint8_t* name,
|
|||||||
sizeof(struct delegpt_ns));
|
sizeof(struct delegpt_ns));
|
||||||
if(!ns)
|
if(!ns)
|
||||||
return 0;
|
return 0;
|
||||||
|
ns->next = dp->nslist;
|
||||||
ns->namelen = len;
|
ns->namelen = len;
|
||||||
|
dp->nslist = ns;
|
||||||
ns->name = regional_alloc_init(region, name, ns->namelen);
|
ns->name = regional_alloc_init(region, name, ns->namelen);
|
||||||
if(!ns->name)
|
|
||||||
return 0;
|
|
||||||
ns->cache_lookup_count = 0;
|
ns->cache_lookup_count = 0;
|
||||||
ns->resolved = 0;
|
ns->resolved = 0;
|
||||||
ns->got4 = 0;
|
ns->got4 = 0;
|
||||||
@@ -137,9 +137,7 @@ delegpt_add_ns(struct delegpt* dp, struct regional* region, uint8_t* name,
|
|||||||
} else {
|
} else {
|
||||||
ns->tls_auth_name = NULL;
|
ns->tls_auth_name = NULL;
|
||||||
}
|
}
|
||||||
ns->next = dp->nslist;
|
return ns->name != 0;
|
||||||
dp->nslist = ns;
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct delegpt_ns*
|
struct delegpt_ns*
|
||||||
@@ -225,7 +223,11 @@ delegpt_add_addr(struct delegpt* dp, struct regional* region,
|
|||||||
sizeof(struct delegpt_addr));
|
sizeof(struct delegpt_addr));
|
||||||
if(!a)
|
if(!a)
|
||||||
return 0;
|
return 0;
|
||||||
|
a->next_target = dp->target_list;
|
||||||
|
dp->target_list = a;
|
||||||
a->next_result = 0;
|
a->next_result = 0;
|
||||||
|
a->next_usable = dp->usable_list;
|
||||||
|
dp->usable_list = a;
|
||||||
memcpy(&a->addr, addr, addrlen);
|
memcpy(&a->addr, addr, addrlen);
|
||||||
a->addrlen = addrlen;
|
a->addrlen = addrlen;
|
||||||
a->attempts = 0;
|
a->attempts = 0;
|
||||||
@@ -239,10 +241,6 @@ delegpt_add_addr(struct delegpt* dp, struct regional* region,
|
|||||||
} else {
|
} else {
|
||||||
a->tls_auth_name = NULL;
|
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;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -280,7 +278,7 @@ delegpt_count_addr(struct delegpt* dp, size_t* numaddr, size_t* numres,
|
|||||||
|
|
||||||
void delegpt_log(enum verbosity_value v, struct delegpt* dp)
|
void delegpt_log(enum verbosity_value v, struct delegpt* dp)
|
||||||
{
|
{
|
||||||
char buf[LDNS_MAX_DOMAINLEN];
|
char buf[LDNS_MAX_DOMAINLEN+1];
|
||||||
struct delegpt_ns* ns;
|
struct delegpt_ns* ns;
|
||||||
struct delegpt_addr* a;
|
struct delegpt_addr* a;
|
||||||
size_t missing=0, numns=0, numaddr=0, numres=0, numavail=0;
|
size_t missing=0, numns=0, numaddr=0, numres=0, numavail=0;
|
||||||
@@ -323,45 +321,6 @@ void delegpt_log(enum verbosity_value v, struct delegpt* dp)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
|
||||||
delegpt_addr_on_result_list(struct delegpt* dp, struct delegpt_addr* find)
|
|
||||||
{
|
|
||||||
struct delegpt_addr* a = dp->result_list;
|
|
||||||
while(a) {
|
|
||||||
if(a == find)
|
|
||||||
return 1;
|
|
||||||
a = a->next_result;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
delegpt_usable_list_remove_addr(struct delegpt* dp, struct delegpt_addr* del)
|
|
||||||
{
|
|
||||||
struct delegpt_addr* usa = dp->usable_list, *prev = NULL;
|
|
||||||
while(usa) {
|
|
||||||
if(usa == del) {
|
|
||||||
/* snip off the usable list */
|
|
||||||
if(prev)
|
|
||||||
prev->next_usable = usa->next_usable;
|
|
||||||
else dp->usable_list = usa->next_usable;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
prev = usa;
|
|
||||||
usa = usa->next_usable;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
delegpt_add_to_result_list(struct delegpt* dp, struct delegpt_addr* a)
|
|
||||||
{
|
|
||||||
if(delegpt_addr_on_result_list(dp, a))
|
|
||||||
return;
|
|
||||||
delegpt_usable_list_remove_addr(dp, a);
|
|
||||||
a->next_result = dp->result_list;
|
|
||||||
dp->result_list = a;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
delegpt_add_unused_targets(struct delegpt* dp)
|
delegpt_add_unused_targets(struct delegpt* dp)
|
||||||
{
|
{
|
||||||
@@ -400,33 +359,30 @@ delegpt_count_missing_targets(struct delegpt* dp, int* alllame)
|
|||||||
|
|
||||||
/** find NS rrset in given list */
|
/** find NS rrset in given list */
|
||||||
static struct ub_packed_rrset_key*
|
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;
|
size_t i;
|
||||||
for(i=from; i<to; i++) {
|
for(i=from; i<to; i++) {
|
||||||
if(ntohs(rep->rrsets[i]->rk.type) == LDNS_RR_TYPE_NS &&
|
if(ntohs(rep->rrsets[i]->rk.type) == LDNS_RR_TYPE_NS)
|
||||||
ntohs(rep->rrsets[i]->rk.rrset_class) == qclass)
|
|
||||||
return rep->rrsets[i];
|
return rep->rrsets[i];
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct delegpt*
|
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 ub_packed_rrset_key* ns_rrset = NULL;
|
||||||
struct delegpt* dp;
|
struct delegpt* dp;
|
||||||
size_t i;
|
size_t i;
|
||||||
/* look for NS records in the authority section... */
|
/* look for NS records in the authority section... */
|
||||||
ns_rrset = find_NS(msg->rep, msg->rep->an_numrrsets,
|
ns_rrset = find_NS(msg->rep, msg->rep->an_numrrsets,
|
||||||
msg->rep->an_numrrsets+msg->rep->ns_numrrsets,
|
msg->rep->an_numrrsets+msg->rep->ns_numrrsets);
|
||||||
msg->qinfo.qclass);
|
|
||||||
|
|
||||||
/* In some cases (even legitimate, perfectly legal cases), the
|
/* In some cases (even legitimate, perfectly legal cases), the
|
||||||
* NS set for the "referral" might be in the answer section. */
|
* NS set for the "referral" might be in the answer section. */
|
||||||
if(!ns_rrset)
|
if(!ns_rrset)
|
||||||
ns_rrset = find_NS(msg->rep, 0, msg->rep->an_numrrsets,
|
ns_rrset = find_NS(msg->rep, 0, msg->rep->an_numrrsets);
|
||||||
msg->qinfo.qclass);
|
|
||||||
|
|
||||||
/* If there was no NS rrset in the authority section, then this
|
/* If there was no NS rrset in the authority section, then this
|
||||||
* wasn't a referral message. (It might not actually be a
|
* wasn't a referral message. (It might not actually be a
|
||||||
@@ -441,7 +397,7 @@ delegpt_from_message(struct dns_msg* msg, struct regional* region, int port)
|
|||||||
dp->has_parent_side_NS = 1; /* created from message */
|
dp->has_parent_side_NS = 1; /* created from message */
|
||||||
if(!delegpt_set_name(dp, region, ns_rrset->rk.dname))
|
if(!delegpt_set_name(dp, region, ns_rrset->rk.dname))
|
||||||
return NULL;
|
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;
|
return NULL;
|
||||||
|
|
||||||
/* add glue, A and AAAA in answer and additional section */
|
/* add glue, A and AAAA in answer and additional section */
|
||||||
@@ -452,12 +408,10 @@ delegpt_from_message(struct dns_msg* msg, struct regional* region, int port)
|
|||||||
i < (msg->rep->an_numrrsets+msg->rep->ns_numrrsets))
|
i < (msg->rep->an_numrrsets+msg->rep->ns_numrrsets))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if(ntohs(s->rk.type) == LDNS_RR_TYPE_A &&
|
if(ntohs(s->rk.type) == LDNS_RR_TYPE_A) {
|
||||||
ntohs(s->rk.rrset_class) == msg->qinfo.qclass) {
|
|
||||||
if(!delegpt_add_rrset_A(dp, region, s, 0, NULL))
|
if(!delegpt_add_rrset_A(dp, region, s, 0, NULL))
|
||||||
return NULL;
|
return NULL;
|
||||||
} else if(ntohs(s->rk.type) == LDNS_RR_TYPE_AAAA &&
|
} else if(ntohs(s->rk.type) == LDNS_RR_TYPE_AAAA) {
|
||||||
ntohs(s->rk.rrset_class) == msg->qinfo.qclass) {
|
|
||||||
if(!delegpt_add_rrset_AAAA(dp, region, s, 0, NULL))
|
if(!delegpt_add_rrset_AAAA(dp, region, s, 0, NULL))
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -467,7 +421,7 @@ delegpt_from_message(struct dns_msg* msg, struct regional* region, int port)
|
|||||||
|
|
||||||
int
|
int
|
||||||
delegpt_rrset_add_ns(struct delegpt* dp, struct regional* region,
|
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*)
|
struct packed_rrset_data* nsdata = (struct packed_rrset_data*)
|
||||||
ns_rrset->entry.data;
|
ns_rrset->entry.data;
|
||||||
@@ -482,7 +436,7 @@ delegpt_rrset_add_ns(struct delegpt* dp, struct regional* region,
|
|||||||
continue; /* bad format */
|
continue; /* bad format */
|
||||||
/* add rdata of NS (= wirefmt dname), skip rdatalen bytes */
|
/* add rdata of NS (= wirefmt dname), skip rdatalen bytes */
|
||||||
if(!delegpt_add_ns(dp, region, nsdata->rr_data[i]+2, lame,
|
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 0;
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
@@ -541,7 +495,7 @@ delegpt_add_rrset(struct delegpt* dp, struct regional* region,
|
|||||||
if(!rrset)
|
if(!rrset)
|
||||||
return 1;
|
return 1;
|
||||||
if(ntohs(rrset->rk.type) == LDNS_RR_TYPE_NS)
|
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)
|
else if(ntohs(rrset->rk.type) == LDNS_RR_TYPE_A)
|
||||||
return delegpt_add_rrset_A(dp, region, rrset, lame, additions);
|
return delegpt_add_rrset_A(dp, region, rrset, lame, additions);
|
||||||
else if(ntohs(rrset->rk.type) == LDNS_RR_TYPE_AAAA)
|
else if(ntohs(rrset->rk.type) == LDNS_RR_TYPE_AAAA)
|
||||||
@@ -666,6 +620,8 @@ int delegpt_add_ns_mlc(struct delegpt* dp, uint8_t* name, uint8_t lame,
|
|||||||
free(ns);
|
free(ns);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
ns->next = dp->nslist;
|
||||||
|
dp->nslist = ns;
|
||||||
ns->cache_lookup_count = 0;
|
ns->cache_lookup_count = 0;
|
||||||
ns->resolved = 0;
|
ns->resolved = 0;
|
||||||
ns->got4 = 0;
|
ns->got4 = 0;
|
||||||
@@ -684,8 +640,6 @@ int delegpt_add_ns_mlc(struct delegpt* dp, uint8_t* name, uint8_t lame,
|
|||||||
} else {
|
} else {
|
||||||
ns->tls_auth_name = NULL;
|
ns->tls_auth_name = NULL;
|
||||||
}
|
}
|
||||||
ns->next = dp->nslist;
|
|
||||||
dp->nslist = ns;
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -711,7 +665,11 @@ int delegpt_add_addr_mlc(struct delegpt* dp, struct sockaddr_storage* addr,
|
|||||||
a = (struct delegpt_addr*)malloc(sizeof(struct delegpt_addr));
|
a = (struct delegpt_addr*)malloc(sizeof(struct delegpt_addr));
|
||||||
if(!a)
|
if(!a)
|
||||||
return 0;
|
return 0;
|
||||||
|
a->next_target = dp->target_list;
|
||||||
|
dp->target_list = a;
|
||||||
a->next_result = 0;
|
a->next_result = 0;
|
||||||
|
a->next_usable = dp->usable_list;
|
||||||
|
dp->usable_list = a;
|
||||||
memcpy(&a->addr, addr, addrlen);
|
memcpy(&a->addr, addr, addrlen);
|
||||||
a->addrlen = addrlen;
|
a->addrlen = addrlen;
|
||||||
a->attempts = 0;
|
a->attempts = 0;
|
||||||
@@ -727,10 +685,6 @@ int delegpt_add_addr_mlc(struct delegpt* dp, struct sockaddr_storage* addr,
|
|||||||
} else {
|
} else {
|
||||||
a->tls_auth_name = NULL;
|
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;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
-39
@@ -79,16 +79,6 @@ struct delegpt {
|
|||||||
* Also true if the delegationpoint was created from a delegation
|
* Also true if the delegationpoint was created from a delegation
|
||||||
* message and thus contains the parent-side-info already. */
|
* message and thus contains the parent-side-info already. */
|
||||||
uint8_t has_parent_side_NS;
|
uint8_t has_parent_side_NS;
|
||||||
/** if true, the delegation point has reached last resort processing
|
|
||||||
* and the parent side information has been possibly added to the
|
|
||||||
* delegation point.
|
|
||||||
* For now this signals that further target lookups will ignore
|
|
||||||
* the configured target-fetch-policy and only resolve on
|
|
||||||
* demand to try and avoid triggering limits at this stage (.i.e, it
|
|
||||||
* is very likely that the A/AAAA queries for the newly added name
|
|
||||||
* servers will not yield new IP addresses and trigger NXNS
|
|
||||||
* countermeasures. */
|
|
||||||
uint8_t fallback_to_parent_side_NS;
|
|
||||||
/** for assertions on type of delegpt */
|
/** for assertions on type of delegpt */
|
||||||
uint8_t dp_type_mlc;
|
uint8_t dp_type_mlc;
|
||||||
/** use SSL for upstream query */
|
/** use SSL for upstream query */
|
||||||
@@ -221,11 +211,10 @@ int delegpt_add_ns(struct delegpt* dp, struct regional* regional,
|
|||||||
* @param regional: where to allocate the info.
|
* @param regional: where to allocate the info.
|
||||||
* @param ns_rrset: NS rrset.
|
* @param ns_rrset: NS rrset.
|
||||||
* @param lame: rrset is lame, disprefer it.
|
* @param lame: rrset is lame, disprefer it.
|
||||||
* @param port: port or -1 if not set.
|
|
||||||
* @return 0 on alloc error.
|
* @return 0 on alloc error.
|
||||||
*/
|
*/
|
||||||
int delegpt_rrset_add_ns(struct delegpt* dp, struct regional* regional,
|
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.
|
* Add target address to the delegation point.
|
||||||
@@ -366,12 +355,11 @@ size_t delegpt_count_targets(struct delegpt* dp);
|
|||||||
*
|
*
|
||||||
* @param msg: the dns message, referral.
|
* @param msg: the dns message, referral.
|
||||||
* @param regional: where to allocate delegation point.
|
* @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
|
* @return new delegation point or NULL on alloc error, or if the
|
||||||
* message was not appropriate.
|
* message was not appropriate.
|
||||||
*/
|
*/
|
||||||
struct delegpt* delegpt_from_message(struct dns_msg* msg,
|
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.
|
* Mark negative return in delegation point for specific nameserver.
|
||||||
@@ -469,29 +457,4 @@ int delegpt_add_target_mlc(struct delegpt* dp, uint8_t* name, size_t namelen,
|
|||||||
/** get memory in use by dp */
|
/** get memory in use by dp */
|
||||||
size_t delegpt_get_mem(struct delegpt* dp);
|
size_t delegpt_get_mem(struct delegpt* dp);
|
||||||
|
|
||||||
/**
|
|
||||||
* See if the addr is on the result list.
|
|
||||||
* @param dp: delegation point.
|
|
||||||
* @param find: the pointer is searched for on the result list.
|
|
||||||
* @return 1 if found, 0 if not found.
|
|
||||||
*/
|
|
||||||
int delegpt_addr_on_result_list(struct delegpt* dp, struct delegpt_addr* find);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove the addr from the usable list.
|
|
||||||
* @param dp: the delegation point.
|
|
||||||
* @param del: the addr to remove from the list, the pointer is searched for.
|
|
||||||
*/
|
|
||||||
void delegpt_usable_list_remove_addr(struct delegpt* dp,
|
|
||||||
struct delegpt_addr* del);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add the delegpt_addr back to the result list, if it is not already on
|
|
||||||
* the result list. Also removes it from the usable list.
|
|
||||||
* @param dp: delegation point.
|
|
||||||
* @param a: addr to add, nothing happens if it is already on the result list.
|
|
||||||
* It is removed from the usable list.
|
|
||||||
*/
|
|
||||||
void delegpt_add_to_result_list(struct delegpt* dp, struct delegpt_addr* a);
|
|
||||||
|
|
||||||
#endif /* ITERATOR_ITER_DELEGPT_H */
|
#endif /* ITERATOR_ITER_DELEGPT_H */
|
||||||
|
|||||||
@@ -132,18 +132,6 @@ donotq_apply_cfg(struct iter_donotq* dq, struct config_file* cfg)
|
|||||||
if(cfg->do_ip6) {
|
if(cfg->do_ip6) {
|
||||||
if(!donotq_str_cfg(dq, "::1"))
|
if(!donotq_str_cfg(dq, "::1"))
|
||||||
return 0;
|
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);
|
addr_tree_init_parents(&dq->tree);
|
||||||
|
|||||||
+38
-169
@@ -71,7 +71,6 @@ forwards_create(void)
|
|||||||
sizeof(struct iter_forwards));
|
sizeof(struct iter_forwards));
|
||||||
if(!fwd)
|
if(!fwd)
|
||||||
return NULL;
|
return NULL;
|
||||||
lock_rw_init(&fwd->lock);
|
|
||||||
return fwd;
|
return fwd;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -101,7 +100,6 @@ forwards_delete(struct iter_forwards* fwd)
|
|||||||
{
|
{
|
||||||
if(!fwd)
|
if(!fwd)
|
||||||
return;
|
return;
|
||||||
lock_rw_destroy(&fwd->lock);
|
|
||||||
fwd_del_tree(fwd);
|
fwd_del_tree(fwd);
|
||||||
free(fwd);
|
free(fwd);
|
||||||
}
|
}
|
||||||
@@ -129,7 +127,7 @@ forwards_insert_data(struct iter_forwards* fwd, uint16_t c, uint8_t* nm,
|
|||||||
node->namelabs = nmlabs;
|
node->namelabs = nmlabs;
|
||||||
node->dp = dp;
|
node->dp = dp;
|
||||||
if(!rbtree_insert(fwd->tree, &node->node)) {
|
if(!rbtree_insert(fwd->tree, &node->node)) {
|
||||||
char buf[LDNS_MAX_DOMAINLEN];
|
char buf[257];
|
||||||
dname_str(nm, buf);
|
dname_str(nm, buf);
|
||||||
log_err("duplicate forward zone %s ignored.", buf);
|
log_err("duplicate forward zone %s ignored.", buf);
|
||||||
delegpt_free_mlc(dp);
|
delegpt_free_mlc(dp);
|
||||||
@@ -139,17 +137,6 @@ forwards_insert_data(struct iter_forwards* fwd, uint16_t c, uint8_t* nm,
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct iter_forward_zone*
|
|
||||||
fwd_zone_find(struct iter_forwards* fwd, uint16_t c, uint8_t* nm)
|
|
||||||
{
|
|
||||||
struct iter_forward_zone key;
|
|
||||||
key.node.key = &key;
|
|
||||||
key.dclass = c;
|
|
||||||
key.name = nm;
|
|
||||||
key.namelabs = dname_count_size_labels(nm, &key.namelen);
|
|
||||||
return (struct iter_forward_zone*)rbtree_search(fwd->tree, &key);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** insert new info into forward structure given dp */
|
/** insert new info into forward structure given dp */
|
||||||
static int
|
static int
|
||||||
forwards_insert(struct iter_forwards* fwd, uint16_t c, struct delegpt* dp)
|
forwards_insert(struct iter_forwards* fwd, uint16_t c, struct delegpt* dp)
|
||||||
@@ -228,11 +215,6 @@ read_fwds_host(struct config_stub* s, struct delegpt* dp)
|
|||||||
s->name, p->str);
|
s->name, p->str);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if(dname_subdomain_c(dname, dp->name)) {
|
|
||||||
log_warn("forward-host '%s' may have a circular "
|
|
||||||
"dependency on forward-zone '%s'",
|
|
||||||
p->str, s->name);
|
|
||||||
}
|
|
||||||
#if ! defined(HAVE_SSL_SET1_HOST) && ! defined(HAVE_X509_VERIFY_PARAM_SET1_HOST)
|
#if ! defined(HAVE_SSL_SET1_HOST) && ! defined(HAVE_X509_VERIFY_PARAM_SET1_HOST)
|
||||||
if(tls_auth_name)
|
if(tls_auth_name)
|
||||||
log_err("no name verification functionality in "
|
log_err("no name verification functionality in "
|
||||||
@@ -337,40 +319,6 @@ make_stub_holes(struct iter_forwards* fwd, struct config_file* cfg)
|
|||||||
log_err("cannot parse stub name '%s'", s->name);
|
log_err("cannot parse stub name '%s'", s->name);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if(fwd_zone_find(fwd, LDNS_RR_CLASS_IN, dname) != NULL) {
|
|
||||||
/* Already a forward zone there. */
|
|
||||||
free(dname);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if(!fwd_add_stub_hole(fwd, LDNS_RR_CLASS_IN, dname)) {
|
|
||||||
free(dname);
|
|
||||||
log_err("out of memory");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
free(dname);
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** make NULL entries for auths */
|
|
||||||
static int
|
|
||||||
make_auth_holes(struct iter_forwards* fwd, struct config_file* cfg)
|
|
||||||
{
|
|
||||||
struct config_auth* a;
|
|
||||||
uint8_t* dname;
|
|
||||||
size_t dname_len;
|
|
||||||
for(a = cfg->auths; a; a = a->next) {
|
|
||||||
if(!a->name) continue;
|
|
||||||
dname = sldns_str2wire_dname(a->name, &dname_len);
|
|
||||||
if(!dname) {
|
|
||||||
log_err("cannot parse auth name '%s'", a->name);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if(fwd_zone_find(fwd, LDNS_RR_CLASS_IN, dname) != NULL) {
|
|
||||||
/* Already a forward zone there. */
|
|
||||||
free(dname);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if(!fwd_add_stub_hole(fwd, LDNS_RR_CLASS_IN, dname)) {
|
if(!fwd_add_stub_hole(fwd, LDNS_RR_CLASS_IN, dname)) {
|
||||||
free(dname);
|
free(dname);
|
||||||
log_err("out of memory");
|
log_err("out of memory");
|
||||||
@@ -384,74 +332,45 @@ make_auth_holes(struct iter_forwards* fwd, struct config_file* cfg)
|
|||||||
int
|
int
|
||||||
forwards_apply_cfg(struct iter_forwards* fwd, struct config_file* cfg)
|
forwards_apply_cfg(struct iter_forwards* fwd, struct config_file* cfg)
|
||||||
{
|
{
|
||||||
if(fwd->tree) {
|
|
||||||
lock_unprotect(&fwd->lock, fwd->tree);
|
|
||||||
}
|
|
||||||
fwd_del_tree(fwd);
|
fwd_del_tree(fwd);
|
||||||
fwd->tree = rbtree_create(fwd_cmp);
|
fwd->tree = rbtree_create(fwd_cmp);
|
||||||
if(!fwd->tree)
|
if(!fwd->tree)
|
||||||
return 0;
|
return 0;
|
||||||
lock_protect(&fwd->lock, fwd->tree, sizeof(*fwd->tree));
|
|
||||||
|
|
||||||
lock_rw_wrlock(&fwd->lock);
|
|
||||||
/* read forward zones */
|
/* read forward zones */
|
||||||
if(!read_forwards(fwd, cfg)) {
|
if(!read_forwards(fwd, cfg))
|
||||||
lock_rw_unlock(&fwd->lock);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
if(!make_stub_holes(fwd, cfg))
|
||||||
if(!make_stub_holes(fwd, cfg)) {
|
|
||||||
lock_rw_unlock(&fwd->lock);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
|
||||||
/* TODO: Now we punch holes for auth zones as well so that in
|
|
||||||
* iterator:forward_request() we see the configured
|
|
||||||
* delegation point, but code flow/naming is hard to follow.
|
|
||||||
* Consider having a single tree with configured
|
|
||||||
* delegation points for all categories
|
|
||||||
* (stubs, forwards, auths). */
|
|
||||||
if(!make_auth_holes(fwd, cfg)) {
|
|
||||||
lock_rw_unlock(&fwd->lock);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
fwd_init_parents(fwd);
|
fwd_init_parents(fwd);
|
||||||
lock_rw_unlock(&fwd->lock);
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct delegpt*
|
struct delegpt*
|
||||||
forwards_find(struct iter_forwards* fwd, uint8_t* qname, uint16_t qclass,
|
forwards_find(struct iter_forwards* fwd, uint8_t* qname, uint16_t qclass)
|
||||||
int nolock)
|
|
||||||
{
|
{
|
||||||
struct iter_forward_zone* res;
|
rbnode_type* res = NULL;
|
||||||
struct iter_forward_zone key;
|
struct iter_forward_zone key;
|
||||||
int has_dp;
|
|
||||||
key.node.key = &key;
|
key.node.key = &key;
|
||||||
key.dclass = qclass;
|
key.dclass = qclass;
|
||||||
key.name = qname;
|
key.name = qname;
|
||||||
key.namelabs = dname_count_size_labels(qname, &key.namelen);
|
key.namelabs = dname_count_size_labels(qname, &key.namelen);
|
||||||
/* lock_() calls are macros that could be nothing, surround in {} */
|
res = rbtree_search(fwd->tree, &key);
|
||||||
if(!nolock) { lock_rw_rdlock(&fwd->lock); }
|
if(res) return ((struct iter_forward_zone*)res)->dp;
|
||||||
res = (struct iter_forward_zone*)rbtree_search(fwd->tree, &key);
|
return NULL;
|
||||||
has_dp = res && res->dp;
|
|
||||||
if(!has_dp && !nolock) { lock_rw_unlock(&fwd->lock); }
|
|
||||||
return has_dp?res->dp:NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct delegpt*
|
struct delegpt*
|
||||||
forwards_lookup(struct iter_forwards* fwd, uint8_t* qname, uint16_t qclass,
|
forwards_lookup(struct iter_forwards* fwd, uint8_t* qname, uint16_t qclass)
|
||||||
int nolock)
|
|
||||||
{
|
{
|
||||||
/* lookup the forward zone in the tree */
|
/* lookup the forward zone in the tree */
|
||||||
rbnode_type* res = NULL;
|
rbnode_type* res = NULL;
|
||||||
struct iter_forward_zone *result;
|
struct iter_forward_zone *result;
|
||||||
struct iter_forward_zone key;
|
struct iter_forward_zone key;
|
||||||
int has_dp;
|
|
||||||
key.node.key = &key;
|
key.node.key = &key;
|
||||||
key.dclass = qclass;
|
key.dclass = qclass;
|
||||||
key.name = qname;
|
key.name = qname;
|
||||||
key.namelabs = dname_count_size_labels(qname, &key.namelen);
|
key.namelabs = dname_count_size_labels(qname, &key.namelen);
|
||||||
/* lock_() calls are macros that could be nothing, surround in {} */
|
|
||||||
if(!nolock) { lock_rw_rdlock(&fwd->lock); }
|
|
||||||
if(rbtree_find_less_equal(fwd->tree, &key, &res)) {
|
if(rbtree_find_less_equal(fwd->tree, &key, &res)) {
|
||||||
/* exact */
|
/* exact */
|
||||||
result = (struct iter_forward_zone*)res;
|
result = (struct iter_forward_zone*)res;
|
||||||
@@ -459,10 +378,8 @@ forwards_lookup(struct iter_forwards* fwd, uint8_t* qname, uint16_t qclass,
|
|||||||
/* smaller element (or no element) */
|
/* smaller element (or no element) */
|
||||||
int m;
|
int m;
|
||||||
result = (struct iter_forward_zone*)res;
|
result = (struct iter_forward_zone*)res;
|
||||||
if(!result || result->dclass != qclass) {
|
if(!result || result->dclass != qclass)
|
||||||
if(!nolock) { lock_rw_unlock(&fwd->lock); }
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
|
||||||
/* count number of labels matched */
|
/* count number of labels matched */
|
||||||
(void)dname_lab_cmp(result->name, result->namelabs, key.name,
|
(void)dname_lab_cmp(result->name, result->namelabs, key.name,
|
||||||
key.namelabs, &m);
|
key.namelabs, &m);
|
||||||
@@ -472,22 +389,20 @@ forwards_lookup(struct iter_forwards* fwd, uint8_t* qname, uint16_t qclass,
|
|||||||
result = result->parent;
|
result = result->parent;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
has_dp = result && result->dp;
|
if(result)
|
||||||
if(!has_dp && !nolock) { lock_rw_unlock(&fwd->lock); }
|
return result->dp;
|
||||||
return has_dp?result->dp:NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct delegpt*
|
struct delegpt*
|
||||||
forwards_lookup_root(struct iter_forwards* fwd, uint16_t qclass, int nolock)
|
forwards_lookup_root(struct iter_forwards* fwd, uint16_t qclass)
|
||||||
{
|
{
|
||||||
uint8_t root = 0;
|
uint8_t root = 0;
|
||||||
return forwards_lookup(fwd, &root, qclass, nolock);
|
return forwards_lookup(fwd, &root, qclass);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Finds next root item in forwards lookup tree.
|
int
|
||||||
* Caller needs to handle locking of the forwards structure. */
|
forwards_next_root(struct iter_forwards* fwd, uint16_t* dclass)
|
||||||
static int
|
|
||||||
next_root_locked(struct iter_forwards* fwd, uint16_t* dclass)
|
|
||||||
{
|
{
|
||||||
struct iter_forward_zone key;
|
struct iter_forward_zone key;
|
||||||
rbnode_type* n;
|
rbnode_type* n;
|
||||||
@@ -504,7 +419,7 @@ next_root_locked(struct iter_forwards* fwd, uint16_t* dclass)
|
|||||||
}
|
}
|
||||||
/* root not first item? search for higher items */
|
/* root not first item? search for higher items */
|
||||||
*dclass = p->dclass + 1;
|
*dclass = p->dclass + 1;
|
||||||
return next_root_locked(fwd, dclass);
|
return forwards_next_root(fwd, dclass);
|
||||||
}
|
}
|
||||||
/* find class n in tree, we may get a direct hit, or if we don't
|
/* find class n in tree, we may get a direct hit, or if we don't
|
||||||
* this is the last item of the previous class so rbtree_next() takes
|
* this is the last item of the previous class so rbtree_next() takes
|
||||||
@@ -532,21 +447,10 @@ next_root_locked(struct iter_forwards* fwd, uint16_t* dclass)
|
|||||||
}
|
}
|
||||||
/* not a root node, return next higher item */
|
/* not a root node, return next higher item */
|
||||||
*dclass = p->dclass+1;
|
*dclass = p->dclass+1;
|
||||||
return next_root_locked(fwd, dclass);
|
return forwards_next_root(fwd, dclass);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
|
||||||
forwards_next_root(struct iter_forwards* fwd, uint16_t* dclass, int nolock)
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
/* lock_() calls are macros that could be nothing, surround in {} */
|
|
||||||
if(!nolock) { lock_rw_rdlock(&fwd->lock); }
|
|
||||||
ret = next_root_locked(fwd, dclass);
|
|
||||||
if(!nolock) { lock_rw_unlock(&fwd->lock); }
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t
|
size_t
|
||||||
forwards_get_mem(struct iter_forwards* fwd)
|
forwards_get_mem(struct iter_forwards* fwd)
|
||||||
{
|
{
|
||||||
@@ -554,104 +458,69 @@ forwards_get_mem(struct iter_forwards* fwd)
|
|||||||
size_t s;
|
size_t s;
|
||||||
if(!fwd)
|
if(!fwd)
|
||||||
return 0;
|
return 0;
|
||||||
lock_rw_rdlock(&fwd->lock);
|
|
||||||
s = sizeof(*fwd) + sizeof(*fwd->tree);
|
s = sizeof(*fwd) + sizeof(*fwd->tree);
|
||||||
RBTREE_FOR(p, struct iter_forward_zone*, fwd->tree) {
|
RBTREE_FOR(p, struct iter_forward_zone*, fwd->tree) {
|
||||||
s += sizeof(*p) + p->namelen + delegpt_get_mem(p->dp);
|
s += sizeof(*p) + p->namelen + delegpt_get_mem(p->dp);
|
||||||
}
|
}
|
||||||
lock_rw_unlock(&fwd->lock);
|
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct iter_forward_zone*
|
||||||
|
fwd_zone_find(struct iter_forwards* fwd, uint16_t c, uint8_t* nm)
|
||||||
|
{
|
||||||
|
struct iter_forward_zone key;
|
||||||
|
key.node.key = &key;
|
||||||
|
key.dclass = c;
|
||||||
|
key.name = nm;
|
||||||
|
key.namelabs = dname_count_size_labels(nm, &key.namelen);
|
||||||
|
return (struct iter_forward_zone*)rbtree_search(fwd->tree, &key);
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
forwards_add_zone(struct iter_forwards* fwd, uint16_t c, struct delegpt* dp,
|
forwards_add_zone(struct iter_forwards* fwd, uint16_t c, struct delegpt* dp)
|
||||||
int nolock)
|
|
||||||
{
|
{
|
||||||
struct iter_forward_zone *z;
|
struct iter_forward_zone *z;
|
||||||
/* lock_() calls are macros that could be nothing, surround in {} */
|
|
||||||
if(!nolock) { lock_rw_wrlock(&fwd->lock); }
|
|
||||||
if((z=fwd_zone_find(fwd, c, dp->name)) != NULL) {
|
if((z=fwd_zone_find(fwd, c, dp->name)) != NULL) {
|
||||||
(void)rbtree_delete(fwd->tree, &z->node);
|
(void)rbtree_delete(fwd->tree, &z->node);
|
||||||
fwd_zone_free(z);
|
fwd_zone_free(z);
|
||||||
}
|
}
|
||||||
if(!forwards_insert(fwd, c, dp)) {
|
if(!forwards_insert(fwd, c, dp))
|
||||||
if(!nolock) { lock_rw_unlock(&fwd->lock); }
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
|
||||||
fwd_init_parents(fwd);
|
fwd_init_parents(fwd);
|
||||||
if(!nolock) { lock_rw_unlock(&fwd->lock); }
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
forwards_delete_zone(struct iter_forwards* fwd, uint16_t c, uint8_t* nm,
|
forwards_delete_zone(struct iter_forwards* fwd, uint16_t c, uint8_t* nm)
|
||||||
int nolock)
|
|
||||||
{
|
{
|
||||||
struct iter_forward_zone *z;
|
struct iter_forward_zone *z;
|
||||||
/* lock_() calls are macros that could be nothing, surround in {} */
|
if(!(z=fwd_zone_find(fwd, c, nm)))
|
||||||
if(!nolock) { lock_rw_wrlock(&fwd->lock); }
|
|
||||||
if(!(z=fwd_zone_find(fwd, c, nm))) {
|
|
||||||
if(!nolock) { lock_rw_unlock(&fwd->lock); }
|
|
||||||
return; /* nothing to do */
|
return; /* nothing to do */
|
||||||
}
|
|
||||||
(void)rbtree_delete(fwd->tree, &z->node);
|
(void)rbtree_delete(fwd->tree, &z->node);
|
||||||
fwd_zone_free(z);
|
fwd_zone_free(z);
|
||||||
fwd_init_parents(fwd);
|
fwd_init_parents(fwd);
|
||||||
if(!nolock) { lock_rw_unlock(&fwd->lock); }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
forwards_add_stub_hole(struct iter_forwards* fwd, uint16_t c, uint8_t* nm,
|
forwards_add_stub_hole(struct iter_forwards* fwd, uint16_t c, uint8_t* nm)
|
||||||
int nolock)
|
|
||||||
{
|
{
|
||||||
/* lock_() calls are macros that could be nothing, surround in {} */
|
|
||||||
if(!nolock) { lock_rw_wrlock(&fwd->lock); }
|
|
||||||
if(fwd_zone_find(fwd, c, nm) != NULL) {
|
|
||||||
if(!nolock) { lock_rw_unlock(&fwd->lock); }
|
|
||||||
return 1; /* already a stub zone there */
|
|
||||||
}
|
|
||||||
if(!fwd_add_stub_hole(fwd, c, nm)) {
|
if(!fwd_add_stub_hole(fwd, c, nm)) {
|
||||||
if(!nolock) { lock_rw_unlock(&fwd->lock); }
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
fwd_init_parents(fwd);
|
fwd_init_parents(fwd);
|
||||||
if(!nolock) { lock_rw_unlock(&fwd->lock); }
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
forwards_delete_stub_hole(struct iter_forwards* fwd, uint16_t c,
|
forwards_delete_stub_hole(struct iter_forwards* fwd, uint16_t c, uint8_t* nm)
|
||||||
uint8_t* nm, int nolock)
|
|
||||||
{
|
{
|
||||||
struct iter_forward_zone *z;
|
struct iter_forward_zone *z;
|
||||||
/* lock_() calls are macros that could be nothing, surround in {} */
|
if(!(z=fwd_zone_find(fwd, c, nm)))
|
||||||
if(!nolock) { lock_rw_wrlock(&fwd->lock); }
|
|
||||||
if(!(z=fwd_zone_find(fwd, c, nm))) {
|
|
||||||
if(!nolock) { lock_rw_unlock(&fwd->lock); }
|
|
||||||
return; /* nothing to do */
|
return; /* nothing to do */
|
||||||
}
|
if(z->dp != NULL)
|
||||||
if(z->dp != NULL) {
|
|
||||||
if(!nolock) { lock_rw_unlock(&fwd->lock); }
|
|
||||||
return; /* not a stub hole */
|
return; /* not a stub hole */
|
||||||
}
|
|
||||||
(void)rbtree_delete(fwd->tree, &z->node);
|
(void)rbtree_delete(fwd->tree, &z->node);
|
||||||
fwd_zone_free(z);
|
fwd_zone_free(z);
|
||||||
fwd_init_parents(fwd);
|
fwd_init_parents(fwd);
|
||||||
if(!nolock) { lock_rw_unlock(&fwd->lock); }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
forwards_swap_tree(struct iter_forwards* fwd, struct iter_forwards* data)
|
|
||||||
{
|
|
||||||
rbtree_type* oldtree = fwd->tree;
|
|
||||||
if(oldtree) {
|
|
||||||
lock_unprotect(&fwd->lock, oldtree);
|
|
||||||
}
|
|
||||||
if(data->tree) {
|
|
||||||
lock_unprotect(&data->lock, data->tree);
|
|
||||||
}
|
|
||||||
fwd->tree = data->tree;
|
|
||||||
data->tree = oldtree;
|
|
||||||
lock_protect(&fwd->lock, fwd->tree, sizeof(*fwd->tree));
|
|
||||||
lock_protect(&data->lock, data->tree, sizeof(*data->tree));
|
|
||||||
}
|
|
||||||
|
|||||||
+8
-55
@@ -43,7 +43,6 @@
|
|||||||
#ifndef ITERATOR_ITER_FWD_H
|
#ifndef ITERATOR_ITER_FWD_H
|
||||||
#define ITERATOR_ITER_FWD_H
|
#define ITERATOR_ITER_FWD_H
|
||||||
#include "util/rbtree.h"
|
#include "util/rbtree.h"
|
||||||
#include "util/locks.h"
|
|
||||||
struct config_file;
|
struct config_file;
|
||||||
struct delegpt;
|
struct delegpt;
|
||||||
|
|
||||||
@@ -51,11 +50,6 @@ struct delegpt;
|
|||||||
* Iterator forward zones structure
|
* Iterator forward zones structure
|
||||||
*/
|
*/
|
||||||
struct iter_forwards {
|
struct iter_forwards {
|
||||||
/** lock on the forwards tree.
|
|
||||||
* When grabbing both this lock and the anchors.lock, this lock
|
|
||||||
* is grabbed first. When grabbing both this lock and the hints.lock
|
|
||||||
* this lock is grabbed first. */
|
|
||||||
lock_rw_type lock;
|
|
||||||
/**
|
/**
|
||||||
* Zones are stored in this tree. Sort order is specially chosen.
|
* Zones are stored in this tree. Sort order is specially chosen.
|
||||||
* first sorted on qclass. Then on dname in nsec-like order, so that
|
* first sorted on qclass. Then on dname in nsec-like order, so that
|
||||||
@@ -112,65 +106,47 @@ int forwards_apply_cfg(struct iter_forwards* fwd, struct config_file* cfg);
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Find forward zone exactly by name
|
* Find forward zone exactly by name
|
||||||
* The return value is contents of the forwards structure.
|
|
||||||
* Caller should lock and unlock a readlock on the forwards structure if nolock
|
|
||||||
* is set.
|
|
||||||
* Otherwise caller should unlock the readlock on the forwards structure if a
|
|
||||||
* value was returned.
|
|
||||||
* @param fwd: forward storage.
|
* @param fwd: forward storage.
|
||||||
* @param qname: The qname of the query.
|
* @param qname: The qname of the query.
|
||||||
* @param qclass: The qclass of the query.
|
* @param qclass: The qclass of the query.
|
||||||
* @param nolock: Skip locking, locking is handled by the caller.
|
|
||||||
* @return: A delegation point or null.
|
* @return: A delegation point or null.
|
||||||
*/
|
*/
|
||||||
struct delegpt* forwards_find(struct iter_forwards* fwd, uint8_t* qname,
|
struct delegpt* forwards_find(struct iter_forwards* fwd, uint8_t* qname,
|
||||||
uint16_t qclass, int nolock);
|
uint16_t qclass);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find forward zone information
|
* Find forward zone information
|
||||||
* For this qname/qclass find forward zone information, returns delegation
|
* For this qname/qclass find forward zone information, returns delegation
|
||||||
* point with server names and addresses, or NULL if no forwarding is needed.
|
* point with server names and addresses, or NULL if no forwarding is needed.
|
||||||
* The return value is contents of the forwards structure.
|
|
||||||
* Caller should lock and unlock a readlock on the forwards structure if nolock
|
|
||||||
* is set.
|
|
||||||
* Otherwise caller should unlock the readlock on the forwards structure if a
|
|
||||||
* value was returned.
|
|
||||||
*
|
*
|
||||||
* @param fwd: forward storage.
|
* @param fwd: forward storage.
|
||||||
* @param qname: The qname of the query.
|
* @param qname: The qname of the query.
|
||||||
* @param qclass: The qclass of the query.
|
* @param qclass: The qclass of the query.
|
||||||
* @param nolock: Skip locking, locking is handled by the caller.
|
|
||||||
* @return: A delegation point if the query has to be forwarded to that list,
|
* @return: A delegation point if the query has to be forwarded to that list,
|
||||||
* otherwise null.
|
* otherwise null.
|
||||||
*/
|
*/
|
||||||
struct delegpt* forwards_lookup(struct iter_forwards* fwd,
|
struct delegpt* forwards_lookup(struct iter_forwards* fwd,
|
||||||
uint8_t* qname, uint16_t qclass, int nolock);
|
uint8_t* qname, uint16_t qclass);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Same as forwards_lookup, but for the root only
|
* Same as forwards_lookup, but for the root only
|
||||||
* @param fwd: forward storage.
|
* @param fwd: forward storage.
|
||||||
* @param qclass: The qclass of the query.
|
* @param qclass: The qclass of the query.
|
||||||
* @param nolock: Skip locking, locking is handled by the caller.
|
|
||||||
* @return: A delegation point if root forward exists, otherwise null.
|
* @return: A delegation point if root forward exists, otherwise null.
|
||||||
*/
|
*/
|
||||||
struct delegpt* forwards_lookup_root(struct iter_forwards* fwd,
|
struct delegpt* forwards_lookup_root(struct iter_forwards* fwd,
|
||||||
uint16_t qclass, int nolock);
|
uint16_t qclass);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find next root item in forwards lookup tree.
|
* Find next root item in forwards lookup tree.
|
||||||
* Handles its own locking unless nolock is set. In that case the caller
|
|
||||||
* should lock and unlock a readlock on the forwards structure.
|
|
||||||
* @param fwd: the forward storage
|
* @param fwd: the forward storage
|
||||||
* @param qclass: class to look at next, or higher.
|
* @param qclass: class to look at next, or higher.
|
||||||
* @param nolock: Skip locking, locking is handled by the caller.
|
|
||||||
* @return false if none found, or if true stored in qclass.
|
* @return false if none found, or if true stored in qclass.
|
||||||
*/
|
*/
|
||||||
int forwards_next_root(struct iter_forwards* fwd, uint16_t* qclass,
|
int forwards_next_root(struct iter_forwards* fwd, uint16_t* qclass);
|
||||||
int nolock);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get memory in use by forward storage
|
* Get memory in use by forward storage
|
||||||
* Locks and unlocks the structure.
|
|
||||||
* @param fwd: forward storage.
|
* @param fwd: forward storage.
|
||||||
* @return bytes in use
|
* @return bytes in use
|
||||||
*/
|
*/
|
||||||
@@ -182,65 +158,42 @@ int fwd_cmp(const void* k1, const void* k2);
|
|||||||
/**
|
/**
|
||||||
* Add zone to forward structure. For external use since it recalcs
|
* Add zone to forward structure. For external use since it recalcs
|
||||||
* the tree parents.
|
* the tree parents.
|
||||||
* Handles its own locking unless nolock is set. In that case the caller
|
|
||||||
* should lock and unlock a writelock on the forwards structure.
|
|
||||||
* @param fwd: the forward data structure
|
* @param fwd: the forward data structure
|
||||||
* @param c: class of zone
|
* @param c: class of zone
|
||||||
* @param dp: delegation point with name and target nameservers for new
|
* @param dp: delegation point with name and target nameservers for new
|
||||||
* forward zone. malloced.
|
* forward zone. malloced.
|
||||||
* @param nolock: Skip locking, locking is handled by the caller.
|
|
||||||
* @return false on failure (out of memory);
|
* @return false on failure (out of memory);
|
||||||
*/
|
*/
|
||||||
int forwards_add_zone(struct iter_forwards* fwd, uint16_t c,
|
int forwards_add_zone(struct iter_forwards* fwd, uint16_t c,
|
||||||
struct delegpt* dp, int nolock);
|
struct delegpt* dp);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove zone from forward structure. For external use since it
|
* Remove zone from forward structure. For external use since it
|
||||||
* recalcs the tree parents.
|
* recalcs the tree parents.
|
||||||
* Handles its own locking unless nolock is set. In that case the caller
|
|
||||||
* should lock and unlock a writelock on the forwards structure.
|
|
||||||
* @param fwd: the forward data structure
|
* @param fwd: the forward data structure
|
||||||
* @param c: class of zone
|
* @param c: class of zone
|
||||||
* @param nm: name of zone (in uncompressed wireformat).
|
* @param nm: name of zone (in uncompressed wireformat).
|
||||||
* @param nolock: Skip locking, locking is handled by the caller.
|
|
||||||
*/
|
*/
|
||||||
void forwards_delete_zone(struct iter_forwards* fwd, uint16_t c,
|
void forwards_delete_zone(struct iter_forwards* fwd, uint16_t c, uint8_t* nm);
|
||||||
uint8_t* nm, int nolock);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add stub hole (empty entry in forward table, that makes resolution skip
|
* Add stub hole (empty entry in forward table, that makes resolution skip
|
||||||
* a forward-zone because the stub zone should override the forward zone).
|
* a forward-zone because the stub zone should override the forward zone).
|
||||||
* Does not add one if not necessary.
|
* Does not add one if not necessary.
|
||||||
* Handles its own locking unless nolock is set. In that case the caller
|
|
||||||
* should lock and unlock a writelock on the forwards structure.
|
|
||||||
* @param fwd: the forward data structure
|
* @param fwd: the forward data structure
|
||||||
* @param c: class of zone
|
* @param c: class of zone
|
||||||
* @param nm: name of zone (in uncompressed wireformat).
|
* @param nm: name of zone (in uncompressed wireformat).
|
||||||
* @param nolock: Skip locking, locking is handled by the caller.
|
|
||||||
* @return false on failure (out of memory);
|
* @return false on failure (out of memory);
|
||||||
*/
|
*/
|
||||||
int forwards_add_stub_hole(struct iter_forwards* fwd, uint16_t c,
|
int forwards_add_stub_hole(struct iter_forwards* fwd, uint16_t c, uint8_t* nm);
|
||||||
uint8_t* nm, int nolock);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove stub hole, if one exists.
|
* Remove stub hole, if one exists.
|
||||||
* Handles its own locking unless nolock is set. In that case the caller
|
|
||||||
* should lock and unlock a writelock on the forwards structure.
|
|
||||||
* @param fwd: the forward data structure
|
* @param fwd: the forward data structure
|
||||||
* @param c: class of zone
|
* @param c: class of zone
|
||||||
* @param nm: name of zone (in uncompressed wireformat).
|
* @param nm: name of zone (in uncompressed wireformat).
|
||||||
* @param nolock: Skip locking, locking is handled by the caller.
|
|
||||||
*/
|
*/
|
||||||
void forwards_delete_stub_hole(struct iter_forwards* fwd, uint16_t c,
|
void forwards_delete_stub_hole(struct iter_forwards* fwd, uint16_t c,
|
||||||
uint8_t* nm, int nolock);
|
uint8_t* nm);
|
||||||
|
|
||||||
/**
|
|
||||||
* Swap internal tree with preallocated entries. Caller should manage
|
|
||||||
* the locks.
|
|
||||||
* @param fwd: the forward data structure.
|
|
||||||
* @param data: the data structure used to take elements from. This contains
|
|
||||||
* the old elements on return.
|
|
||||||
*/
|
|
||||||
void forwards_swap_tree(struct iter_forwards* fwd, struct iter_forwards* data);
|
|
||||||
|
|
||||||
#endif /* ITERATOR_ITER_FWD_H */
|
#endif /* ITERATOR_ITER_FWD_H */
|
||||||
|
|||||||
+23
-89
@@ -57,8 +57,6 @@ hints_create(void)
|
|||||||
sizeof(struct iter_hints));
|
sizeof(struct iter_hints));
|
||||||
if(!hints)
|
if(!hints)
|
||||||
return NULL;
|
return NULL;
|
||||||
lock_rw_init(&hints->lock);
|
|
||||||
lock_protect(&hints->lock, &hints->tree, sizeof(hints->tree));
|
|
||||||
return hints;
|
return hints;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -85,7 +83,6 @@ hints_delete(struct iter_hints* hints)
|
|||||||
{
|
{
|
||||||
if(!hints)
|
if(!hints)
|
||||||
return;
|
return;
|
||||||
lock_rw_destroy(&hints->lock);
|
|
||||||
hints_del_tree(hints);
|
hints_del_tree(hints);
|
||||||
free(hints);
|
free(hints);
|
||||||
}
|
}
|
||||||
@@ -132,7 +129,7 @@ compile_time_root_prime(int do_ip4, int do_ip6)
|
|||||||
dp->has_parent_side_NS = 1;
|
dp->has_parent_side_NS = 1;
|
||||||
if(do_ip4) {
|
if(do_ip4) {
|
||||||
if(!ah(dp, "A.ROOT-SERVERS.NET.", "198.41.0.4")) goto failed;
|
if(!ah(dp, "A.ROOT-SERVERS.NET.", "198.41.0.4")) goto failed;
|
||||||
if(!ah(dp, "B.ROOT-SERVERS.NET.", "170.247.170.2")) goto failed;
|
if(!ah(dp, "B.ROOT-SERVERS.NET.", "199.9.14.201")) goto failed;
|
||||||
if(!ah(dp, "C.ROOT-SERVERS.NET.", "192.33.4.12")) goto failed;
|
if(!ah(dp, "C.ROOT-SERVERS.NET.", "192.33.4.12")) goto failed;
|
||||||
if(!ah(dp, "D.ROOT-SERVERS.NET.", "199.7.91.13")) goto failed;
|
if(!ah(dp, "D.ROOT-SERVERS.NET.", "199.7.91.13")) goto failed;
|
||||||
if(!ah(dp, "E.ROOT-SERVERS.NET.", "192.203.230.10")) goto failed;
|
if(!ah(dp, "E.ROOT-SERVERS.NET.", "192.203.230.10")) goto failed;
|
||||||
@@ -147,7 +144,7 @@ compile_time_root_prime(int do_ip4, int do_ip6)
|
|||||||
}
|
}
|
||||||
if(do_ip6) {
|
if(do_ip6) {
|
||||||
if(!ah(dp, "A.ROOT-SERVERS.NET.", "2001:503:ba3e::2:30")) goto failed;
|
if(!ah(dp, "A.ROOT-SERVERS.NET.", "2001:503:ba3e::2:30")) goto failed;
|
||||||
if(!ah(dp, "B.ROOT-SERVERS.NET.", "2801:1b8:10::b")) goto failed;
|
if(!ah(dp, "B.ROOT-SERVERS.NET.", "2001:500:200::b")) goto failed;
|
||||||
if(!ah(dp, "C.ROOT-SERVERS.NET.", "2001:500:2::c")) goto failed;
|
if(!ah(dp, "C.ROOT-SERVERS.NET.", "2001:500:2::c")) goto failed;
|
||||||
if(!ah(dp, "D.ROOT-SERVERS.NET.", "2001:500:2d::d")) goto failed;
|
if(!ah(dp, "D.ROOT-SERVERS.NET.", "2001:500:2d::d")) goto failed;
|
||||||
if(!ah(dp, "E.ROOT-SERVERS.NET.", "2001:500:a8::e")) goto failed;
|
if(!ah(dp, "E.ROOT-SERVERS.NET.", "2001:500:a8::e")) goto failed;
|
||||||
@@ -181,7 +178,7 @@ hints_insert(struct iter_hints* hints, uint16_t c, struct delegpt* dp,
|
|||||||
node->noprime = (uint8_t)noprime;
|
node->noprime = (uint8_t)noprime;
|
||||||
if(!name_tree_insert(&hints->tree, &node->node, dp->name, dp->namelen,
|
if(!name_tree_insert(&hints->tree, &node->node, dp->name, dp->namelen,
|
||||||
dp->namelabs, c)) {
|
dp->namelabs, c)) {
|
||||||
char buf[LDNS_MAX_DOMAINLEN];
|
char buf[257];
|
||||||
dname_str(dp->name, buf);
|
dname_str(dp->name, buf);
|
||||||
log_err("second hints for zone %s ignored.", buf);
|
log_err("second hints for zone %s ignored.", buf);
|
||||||
delegpt_free_mlc(dp);
|
delegpt_free_mlc(dp);
|
||||||
@@ -231,11 +228,6 @@ read_stubs_host(struct config_stub* s, struct delegpt* dp)
|
|||||||
s->name, p->str);
|
s->name, p->str);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if(dname_subdomain_c(dname, dp->name)) {
|
|
||||||
log_warn("stub-host '%s' may have a circular "
|
|
||||||
"dependency on stub-zone '%s'",
|
|
||||||
p->str, s->name);
|
|
||||||
}
|
|
||||||
#if ! defined(HAVE_SSL_SET1_HOST) && ! defined(HAVE_X509_VERIFY_PARAM_SET1_HOST)
|
#if ! defined(HAVE_SSL_SET1_HOST) && ! defined(HAVE_X509_VERIFY_PARAM_SET1_HOST)
|
||||||
if(tls_auth_name)
|
if(tls_auth_name)
|
||||||
log_err("no name verification functionality in "
|
log_err("no name verification functionality in "
|
||||||
@@ -446,70 +438,47 @@ read_root_hints_list(struct iter_hints* hints, struct config_file* cfg)
|
|||||||
int
|
int
|
||||||
hints_apply_cfg(struct iter_hints* hints, struct config_file* cfg)
|
hints_apply_cfg(struct iter_hints* hints, struct config_file* cfg)
|
||||||
{
|
{
|
||||||
int nolock = 1;
|
|
||||||
lock_rw_wrlock(&hints->lock);
|
|
||||||
hints_del_tree(hints);
|
hints_del_tree(hints);
|
||||||
name_tree_init(&hints->tree);
|
name_tree_init(&hints->tree);
|
||||||
|
|
||||||
/* read root hints */
|
/* read root hints */
|
||||||
if(!read_root_hints_list(hints, cfg)) {
|
if(!read_root_hints_list(hints, cfg))
|
||||||
lock_rw_unlock(&hints->lock);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
|
||||||
|
|
||||||
/* read stub hints */
|
/* read stub hints */
|
||||||
if(!read_stubs(hints, cfg)) {
|
if(!read_stubs(hints, cfg))
|
||||||
lock_rw_unlock(&hints->lock);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
|
||||||
|
|
||||||
/* use fallback compiletime root hints */
|
/* use fallback compiletime root hints */
|
||||||
if(!hints_find_root(hints, LDNS_RR_CLASS_IN, nolock)) {
|
if(!hints_lookup_root(hints, LDNS_RR_CLASS_IN)) {
|
||||||
struct delegpt* dp = compile_time_root_prime(cfg->do_ip4,
|
struct delegpt* dp = compile_time_root_prime(cfg->do_ip4,
|
||||||
cfg->do_ip6);
|
cfg->do_ip6);
|
||||||
verbose(VERB_ALGO, "no config, using builtin root hints.");
|
verbose(VERB_ALGO, "no config, using builtin root hints.");
|
||||||
if(!dp) {
|
if(!dp)
|
||||||
lock_rw_unlock(&hints->lock);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
if(!hints_insert(hints, LDNS_RR_CLASS_IN, dp, 0))
|
||||||
if(!hints_insert(hints, LDNS_RR_CLASS_IN, dp, 0)) {
|
|
||||||
lock_rw_unlock(&hints->lock);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
name_tree_init_parents(&hints->tree);
|
name_tree_init_parents(&hints->tree);
|
||||||
lock_rw_unlock(&hints->lock);
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct delegpt*
|
struct delegpt*
|
||||||
hints_find(struct iter_hints* hints, uint8_t* qname, uint16_t qclass,
|
hints_lookup_root(struct iter_hints* hints, uint16_t qclass)
|
||||||
int nolock)
|
|
||||||
{
|
|
||||||
struct iter_hints_stub *stub;
|
|
||||||
size_t len;
|
|
||||||
int has_dp;
|
|
||||||
int labs = dname_count_size_labels(qname, &len);
|
|
||||||
/* lock_() calls are macros that could be nothing, surround in {} */
|
|
||||||
if(!nolock) { lock_rw_rdlock(&hints->lock); }
|
|
||||||
stub = (struct iter_hints_stub*)name_tree_find(&hints->tree,
|
|
||||||
qname, len, labs, qclass);
|
|
||||||
has_dp = stub && stub->dp;
|
|
||||||
if(!has_dp && !nolock) { lock_rw_unlock(&hints->lock); }
|
|
||||||
return has_dp?stub->dp:NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct delegpt*
|
|
||||||
hints_find_root(struct iter_hints* hints, uint16_t qclass, int nolock)
|
|
||||||
{
|
{
|
||||||
uint8_t rootlab = 0;
|
uint8_t rootlab = 0;
|
||||||
return hints_find(hints, &rootlab, qclass, nolock);
|
struct iter_hints_stub *stub;
|
||||||
|
stub = (struct iter_hints_stub*)name_tree_find(&hints->tree,
|
||||||
|
&rootlab, 1, 1, qclass);
|
||||||
|
if(!stub)
|
||||||
|
return NULL;
|
||||||
|
return stub->dp;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct iter_hints_stub*
|
struct iter_hints_stub*
|
||||||
hints_lookup_stub(struct iter_hints* hints, uint8_t* qname,
|
hints_lookup_stub(struct iter_hints* hints, uint8_t* qname,
|
||||||
uint16_t qclass, struct delegpt* cache_dp, int nolock)
|
uint16_t qclass, struct delegpt* cache_dp)
|
||||||
{
|
{
|
||||||
size_t len;
|
size_t len;
|
||||||
int labs;
|
int labs;
|
||||||
@@ -517,20 +486,14 @@ hints_lookup_stub(struct iter_hints* hints, uint8_t* qname,
|
|||||||
|
|
||||||
/* first lookup the stub */
|
/* first lookup the stub */
|
||||||
labs = dname_count_size_labels(qname, &len);
|
labs = dname_count_size_labels(qname, &len);
|
||||||
/* lock_() calls are macros that could be nothing, surround in {} */
|
|
||||||
if(!nolock) { lock_rw_rdlock(&hints->lock); }
|
|
||||||
r = (struct iter_hints_stub*)name_tree_lookup(&hints->tree, qname,
|
r = (struct iter_hints_stub*)name_tree_lookup(&hints->tree, qname,
|
||||||
len, labs, qclass);
|
len, labs, qclass);
|
||||||
if(!r) {
|
if(!r) return NULL;
|
||||||
if(!nolock) { lock_rw_unlock(&hints->lock); }
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If there is no cache (root prime situation) */
|
/* If there is no cache (root prime situation) */
|
||||||
if(cache_dp == NULL) {
|
if(cache_dp == NULL) {
|
||||||
if(r->dp->namelabs != 1)
|
if(r->dp->namelabs != 1)
|
||||||
return r; /* no cache dp, use any non-root stub */
|
return r; /* no cache dp, use any non-root stub */
|
||||||
if(!nolock) { lock_rw_unlock(&hints->lock); }
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -547,18 +510,12 @@ hints_lookup_stub(struct iter_hints* hints, uint8_t* qname,
|
|||||||
if(dname_strict_subdomain(r->dp->name, r->dp->namelabs,
|
if(dname_strict_subdomain(r->dp->name, r->dp->namelabs,
|
||||||
cache_dp->name, cache_dp->namelabs))
|
cache_dp->name, cache_dp->namelabs))
|
||||||
return r; /* need to prime this stub */
|
return r; /* need to prime this stub */
|
||||||
if(!nolock) { lock_rw_unlock(&hints->lock); }
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
int hints_next_root(struct iter_hints* hints, uint16_t* qclass, int nolock)
|
int hints_next_root(struct iter_hints* hints, uint16_t* qclass)
|
||||||
{
|
{
|
||||||
int ret;
|
return name_tree_next_root(&hints->tree, qclass);
|
||||||
/* lock_() calls are macros that could be nothing, surround in {} */
|
|
||||||
if(!nolock) { lock_rw_rdlock(&hints->lock); }
|
|
||||||
ret = name_tree_next_root(&hints->tree, qclass);
|
|
||||||
if(!nolock) { lock_rw_unlock(&hints->lock); }
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t
|
size_t
|
||||||
@@ -567,63 +524,40 @@ hints_get_mem(struct iter_hints* hints)
|
|||||||
size_t s;
|
size_t s;
|
||||||
struct iter_hints_stub* p;
|
struct iter_hints_stub* p;
|
||||||
if(!hints) return 0;
|
if(!hints) return 0;
|
||||||
lock_rw_rdlock(&hints->lock);
|
|
||||||
s = sizeof(*hints);
|
s = sizeof(*hints);
|
||||||
RBTREE_FOR(p, struct iter_hints_stub*, &hints->tree) {
|
RBTREE_FOR(p, struct iter_hints_stub*, &hints->tree) {
|
||||||
s += sizeof(*p) + delegpt_get_mem(p->dp);
|
s += sizeof(*p) + delegpt_get_mem(p->dp);
|
||||||
}
|
}
|
||||||
lock_rw_unlock(&hints->lock);
|
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
hints_add_stub(struct iter_hints* hints, uint16_t c, struct delegpt* dp,
|
hints_add_stub(struct iter_hints* hints, uint16_t c, struct delegpt* dp,
|
||||||
int noprime, int nolock)
|
int noprime)
|
||||||
{
|
{
|
||||||
struct iter_hints_stub *z;
|
struct iter_hints_stub *z;
|
||||||
/* lock_() calls are macros that could be nothing, surround in {} */
|
|
||||||
if(!nolock) { lock_rw_wrlock(&hints->lock); }
|
|
||||||
if((z=(struct iter_hints_stub*)name_tree_find(&hints->tree,
|
if((z=(struct iter_hints_stub*)name_tree_find(&hints->tree,
|
||||||
dp->name, dp->namelen, dp->namelabs, c)) != NULL) {
|
dp->name, dp->namelen, dp->namelabs, c)) != NULL) {
|
||||||
(void)rbtree_delete(&hints->tree, &z->node);
|
(void)rbtree_delete(&hints->tree, &z->node);
|
||||||
hints_stub_free(z);
|
hints_stub_free(z);
|
||||||
}
|
}
|
||||||
if(!hints_insert(hints, c, dp, noprime)) {
|
if(!hints_insert(hints, c, dp, noprime))
|
||||||
if(!nolock) { lock_rw_unlock(&hints->lock); }
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
|
||||||
name_tree_init_parents(&hints->tree);
|
name_tree_init_parents(&hints->tree);
|
||||||
if(!nolock) { lock_rw_unlock(&hints->lock); }
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
hints_delete_stub(struct iter_hints* hints, uint16_t c, uint8_t* nm,
|
hints_delete_stub(struct iter_hints* hints, uint16_t c, uint8_t* nm)
|
||||||
int nolock)
|
|
||||||
{
|
{
|
||||||
struct iter_hints_stub *z;
|
struct iter_hints_stub *z;
|
||||||
size_t len;
|
size_t len;
|
||||||
int labs = dname_count_size_labels(nm, &len);
|
int labs = dname_count_size_labels(nm, &len);
|
||||||
/* lock_() calls are macros that could be nothing, surround in {} */
|
|
||||||
if(!nolock) { lock_rw_wrlock(&hints->lock); }
|
|
||||||
if(!(z=(struct iter_hints_stub*)name_tree_find(&hints->tree,
|
if(!(z=(struct iter_hints_stub*)name_tree_find(&hints->tree,
|
||||||
nm, len, labs, c))) {
|
nm, len, labs, c)))
|
||||||
if(!nolock) { lock_rw_unlock(&hints->lock); }
|
|
||||||
return; /* nothing to do */
|
return; /* nothing to do */
|
||||||
}
|
|
||||||
(void)rbtree_delete(&hints->tree, &z->node);
|
(void)rbtree_delete(&hints->tree, &z->node);
|
||||||
hints_stub_free(z);
|
hints_stub_free(z);
|
||||||
name_tree_init_parents(&hints->tree);
|
name_tree_init_parents(&hints->tree);
|
||||||
if(!nolock) { lock_rw_unlock(&hints->lock); }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
hints_swap_tree(struct iter_hints* hints, struct iter_hints* data)
|
|
||||||
{
|
|
||||||
rbnode_type* oldroot = hints->tree.root;
|
|
||||||
size_t oldcount = hints->tree.count;
|
|
||||||
hints->tree.root = data->tree.root;
|
|
||||||
hints->tree.count = data->tree.count;
|
|
||||||
data->tree.root = oldroot;
|
|
||||||
data->tree.count = oldcount;
|
|
||||||
}
|
|
||||||
|
|||||||
+6
-55
@@ -43,7 +43,6 @@
|
|||||||
#ifndef ITERATOR_ITER_HINTS_H
|
#ifndef ITERATOR_ITER_HINTS_H
|
||||||
#define ITERATOR_ITER_HINTS_H
|
#define ITERATOR_ITER_HINTS_H
|
||||||
#include "util/storage/dnstree.h"
|
#include "util/storage/dnstree.h"
|
||||||
#include "util/locks.h"
|
|
||||||
struct iter_env;
|
struct iter_env;
|
||||||
struct config_file;
|
struct config_file;
|
||||||
struct delegpt;
|
struct delegpt;
|
||||||
@@ -52,10 +51,6 @@ struct delegpt;
|
|||||||
* Iterator hints structure
|
* Iterator hints structure
|
||||||
*/
|
*/
|
||||||
struct iter_hints {
|
struct iter_hints {
|
||||||
/** lock on the forwards tree.
|
|
||||||
* When grabbing both this lock and the anchors.lock, this lock
|
|
||||||
* is grabbed first. */
|
|
||||||
lock_rw_type lock;
|
|
||||||
/**
|
/**
|
||||||
* Hints are stored in this tree. Sort order is specially chosen.
|
* Hints are stored in this tree. Sort order is specially chosen.
|
||||||
* first sorted on qclass. Then on dname in nsec-like order, so that
|
* first sorted on qclass. Then on dname in nsec-like order, so that
|
||||||
@@ -100,70 +95,42 @@ void hints_delete(struct iter_hints* hints);
|
|||||||
int hints_apply_cfg(struct iter_hints* hints, struct config_file* cfg);
|
int hints_apply_cfg(struct iter_hints* hints, struct config_file* cfg);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find hints for the given class.
|
* Find root hints for the given class.
|
||||||
* The return value is contents of the hints structure.
|
|
||||||
* Caller should lock and unlock a readlock on the hints structure if nolock
|
|
||||||
* is set.
|
|
||||||
* Otherwise caller should unlock the readlock on the hints structure if a
|
|
||||||
* value was returned.
|
|
||||||
* @param hints: hint storage.
|
|
||||||
* @param qname: the qname that generated the delegation point.
|
|
||||||
* @param qclass: class for which root hints are requested. host order.
|
|
||||||
* @param nolock: Skip locking, locking is handled by the caller.
|
|
||||||
* @return: NULL if no hints, or a ptr to stored hints.
|
|
||||||
*/
|
|
||||||
struct delegpt* hints_find(struct iter_hints* hints, uint8_t* qname,
|
|
||||||
uint16_t qclass, int nolock);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Same as hints_lookup, but for the root only.
|
|
||||||
* @param hints: hint storage.
|
* @param hints: hint storage.
|
||||||
* @param qclass: class for which root hints are requested. host order.
|
* @param qclass: class for which root hints are requested. host order.
|
||||||
* @param nolock: Skip locking, locking is handled by the caller.
|
|
||||||
* @return: NULL if no hints, or a ptr to stored hints.
|
* @return: NULL if no hints, or a ptr to stored hints.
|
||||||
*/
|
*/
|
||||||
struct delegpt* hints_find_root(struct iter_hints* hints,
|
struct delegpt* hints_lookup_root(struct iter_hints* hints, uint16_t qclass);
|
||||||
uint16_t qclass, int nolock);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find next root hints (to cycle through all root hints).
|
* Find next root hints (to cycle through all root hints).
|
||||||
* Handles its own locking unless nolock is set. In that case the caller
|
|
||||||
* should lock and unlock a readlock on the hints structure.
|
|
||||||
* @param hints: hint storage
|
* @param hints: hint storage
|
||||||
* @param qclass: class for which root hints are sought.
|
* @param qclass: class for which root hints are sought.
|
||||||
* 0 means give the first available root hints class.
|
* 0 means give the first available root hints class.
|
||||||
* x means, give class x or a higher class if any.
|
* x means, give class x or a higher class if any.
|
||||||
* returns the found class in this variable.
|
* returns the found class in this variable.
|
||||||
* @param nolock: Skip locking, locking is handled by the caller.
|
|
||||||
* @return true if a root hint class is found.
|
* @return true if a root hint class is found.
|
||||||
* false if not root hint class is found (qclass may have been changed).
|
* false if not root hint class is found (qclass may have been changed).
|
||||||
*/
|
*/
|
||||||
int hints_next_root(struct iter_hints* hints, uint16_t* qclass, int nolock);
|
int hints_next_root(struct iter_hints* hints, uint16_t* qclass);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Given a qname/qclass combination, and the delegation point from the cache
|
* Given a qname/qclass combination, and the delegation point from the cache
|
||||||
* for this qname/qclass, determine if this combination indicates that a
|
* for this qname/qclass, determine if this combination indicates that a
|
||||||
* stub hint exists and must be primed.
|
* stub hint exists and must be primed.
|
||||||
* The return value is contents of the hints structure.
|
|
||||||
* Caller should lock and unlock a readlock on the hints structure if nolock
|
|
||||||
* is set.
|
|
||||||
* Otherwise caller should unlock the readlock on the hints structure if a
|
|
||||||
* value was returned.
|
|
||||||
*
|
*
|
||||||
* @param hints: hint storage.
|
* @param hints: hint storage.
|
||||||
* @param qname: The qname that generated the delegation point.
|
* @param qname: The qname that generated the delegation point.
|
||||||
* @param qclass: The qclass that generated the delegation point.
|
* @param qclass: The qclass that generated the delegation point.
|
||||||
* @param dp: The cache generated delegation point.
|
* @param dp: The cache generated delegation point.
|
||||||
* @param nolock: Skip locking, locking is handled by the caller.
|
|
||||||
* @return: A priming delegation point if there is a stub hint that must
|
* @return: A priming delegation point if there is a stub hint that must
|
||||||
* be primed, otherwise null.
|
* be primed, otherwise null.
|
||||||
*/
|
*/
|
||||||
struct iter_hints_stub* hints_lookup_stub(struct iter_hints* hints,
|
struct iter_hints_stub* hints_lookup_stub(struct iter_hints* hints,
|
||||||
uint8_t* qname, uint16_t qclass, struct delegpt* dp, int nolock);
|
uint8_t* qname, uint16_t qclass, struct delegpt* dp);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get memory in use by hints
|
* Get memory in use by hints
|
||||||
* Locks and unlocks the structure.
|
|
||||||
* @param hints: hint storage.
|
* @param hints: hint storage.
|
||||||
* @return bytes in use
|
* @return bytes in use
|
||||||
*/
|
*/
|
||||||
@@ -172,39 +139,23 @@ size_t hints_get_mem(struct iter_hints* hints);
|
|||||||
/**
|
/**
|
||||||
* Add stub to hints structure. For external use since it recalcs
|
* Add stub to hints structure. For external use since it recalcs
|
||||||
* the tree parents.
|
* the tree parents.
|
||||||
* Handles its own locking unless nolock is set. In that case the caller
|
|
||||||
* should lock and unlock a writelock on the hints structure.
|
|
||||||
* @param hints: the hints data structure
|
* @param hints: the hints data structure
|
||||||
* @param c: class of zone
|
* @param c: class of zone
|
||||||
* @param dp: delegation point with name and target nameservers for new
|
* @param dp: delegation point with name and target nameservers for new
|
||||||
* hints stub. malloced.
|
* hints stub. malloced.
|
||||||
* @param noprime: set noprime option to true or false on new hint stub.
|
* @param noprime: set noprime option to true or false on new hint stub.
|
||||||
* @param nolock: Skip locking, locking is handled by the caller.
|
|
||||||
* @return false on failure (out of memory);
|
* @return false on failure (out of memory);
|
||||||
*/
|
*/
|
||||||
int hints_add_stub(struct iter_hints* hints, uint16_t c, struct delegpt* dp,
|
int hints_add_stub(struct iter_hints* hints, uint16_t c, struct delegpt* dp,
|
||||||
int noprime, int nolock);
|
int noprime);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove stub from hints structure. For external use since it
|
* Remove stub from hints structure. For external use since it
|
||||||
* recalcs the tree parents.
|
* recalcs the tree parents.
|
||||||
* Handles its own locking unless nolock is set. In that case the caller
|
|
||||||
* should lock and unlock a writelock on the hints structure.
|
|
||||||
* @param hints: the hints data structure
|
* @param hints: the hints data structure
|
||||||
* @param c: class of stub zone
|
* @param c: class of stub zone
|
||||||
* @param nm: name of stub zone (in uncompressed wireformat).
|
* @param nm: name of stub zone (in uncompressed wireformat).
|
||||||
* @param nolock: Skip locking, locking is handled by the caller.
|
|
||||||
*/
|
*/
|
||||||
void hints_delete_stub(struct iter_hints* hints, uint16_t c,
|
void hints_delete_stub(struct iter_hints* hints, uint16_t c, uint8_t* nm);
|
||||||
uint8_t* nm, int nolock);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Swap internal tree with preallocated entries. Caller should manage
|
|
||||||
* the locks.
|
|
||||||
* @param hints: the hints data structure.
|
|
||||||
* @param data: the data structure used to take elements from. This contains
|
|
||||||
* the old elements on return.
|
|
||||||
*/
|
|
||||||
void hints_swap_tree(struct iter_hints* hints, struct iter_hints* data);
|
|
||||||
|
|
||||||
#endif /* ITERATOR_ITER_HINTS_H */
|
#endif /* ITERATOR_ITER_HINTS_H */
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user