diff --git a/contrib/unbound/.gitattributes b/contrib/unbound/.gitattributes deleted file mode 100644 index 6414a0ab5302..000000000000 --- a/contrib/unbound/.gitattributes +++ /dev/null @@ -1 +0,0 @@ -testdata/*.[0-9] linguist-documentation diff --git a/contrib/unbound/.github/FUNDING.yml b/contrib/unbound/.github/FUNDING.yml deleted file mode 100644 index 2a357c0c7778..000000000000 --- a/contrib/unbound/.github/FUNDING.yml +++ /dev/null @@ -1,2 +0,0 @@ -github: [NLnetLabs] -custom: ['https://nlnetlabs.nl/funding/'] diff --git a/contrib/unbound/.github/ISSUE_TEMPLATE/bug_report.md b/contrib/unbound/.github/ISSUE_TEMPLATE/bug_report.md deleted file mode 100644 index 35d7ee94f9da..000000000000 --- a/contrib/unbound/.github/ISSUE_TEMPLATE/bug_report.md +++ /dev/null @@ -1,41 +0,0 @@ ---- -name: Bug report -about: Create a report to help us improve Unbound -title: '' -labels: '' -assignees: '' - ---- - - - -**Describe the bug** -A clear and concise description of what the bug is. - -**To reproduce** -Steps to reproduce the behavior: -1. -2. -3. - -**Expected behavior** -A clear and concise description of what you expected to happen. - -**System:** - - Unbound version: - - OS: - - `unbound -V` output: - -**Additional information** -Add any other information that you may have gathered about the issue here. diff --git a/contrib/unbound/.github/ISSUE_TEMPLATE/feature_request.md b/contrib/unbound/.github/ISSUE_TEMPLATE/feature_request.md deleted file mode 100644 index e9ca08b7ab65..000000000000 --- a/contrib/unbound/.github/ISSUE_TEMPLATE/feature_request.md +++ /dev/null @@ -1,31 +0,0 @@ ---- -name: Feature request -about: Suggest an idea for Unbound -title: "[FR]" -labels: '' -assignees: '' - ---- - - - -**Current behavior** -Is there a current behavior that the feature relates to? -If yes, would you wish the current behavior to change? - -**Describe the desired feature** -A clear and concise description of what the feature should be. - -**Potential use-case** -Describe how you see this feature being useful to other Unbound users. diff --git a/contrib/unbound/.github/workflows/analysis_ports.yml b/contrib/unbound/.github/workflows/analysis_ports.yml deleted file mode 100644 index fbbdd80185a9..000000000000 --- a/contrib/unbound/.github/workflows/analysis_ports.yml +++ /dev/null @@ -1,346 +0,0 @@ -name: Analysis and Ports - -on: - workflow_dispatch: - inputs: - start: - description: 'Start analysis and port workflow' - default: 'yes' - required: true - -jobs: - build: - runs-on: ${{ matrix.os }} - strategy: - matrix: - include: - - name: GCC on Linux - os: ubuntu-latest - config: "--enable-debug --disable-flto" - make_test: "yes" - - name: Clang-analyzer - os: ubuntu-latest - config: "CC=clang --enable-debug --disable-flto --disable-static" - make_test: "yes" - clang_analysis: "yes" - - name: libevent - os: ubuntu-latest - install_libevent: "yes" - config: "CC=clang --enable-debug --disable-flto --with-libevent --disable-static" - make_test: "yes" - clang_analysis: "yes" - - name: OS X - os: macos-latest - install_expat: "yes" - config: "--enable-debug --disable-flto --with-ssl=/usr/local/opt/openssl --with-libexpat=/usr/local/opt/expat" - make_test: "yes" - - name: Clang on OS X - os: macos-latest - install_expat: "yes" - config: "CC=clang --enable-debug --disable-flto --with-ssl=/usr/local/opt/openssl --with-libexpat=/usr/local/opt/expat --disable-static" - make_test: "yes" - clang_analysis: "yes" - - name: ubsan (gcc undefined behaviour sanitizer) - os: ubuntu-latest - config: 'CFLAGS="-DNDEBUG -g2 -O3 -fsanitize=undefined -fno-sanitize-recover=all" --disable-flto --disable-static' - make_test: "yes" - - name: asan (gcc address sanitizer) - os: ubuntu-latest - config: 'CFLAGS="-DNDEBUG -g2 -O3 -fsanitize=address" --disable-flto --disable-static' - 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 - os: macos-latest - AUTOTOOLS_HOST: aarch64-apple-ios - OPENSSL_HOST: ios64-cross - IOS_SDK: iPhoneOS - IOS_CPU: arm64 - test_ios: "yes" - config: "no" - make: "no" - - name: Apple TV on iOS, arm64 - os: macos-latest - AUTOTOOLS_HOST: aarch64-apple-ios - OPENSSL_HOST: ios64-cross - IOS_SDK: AppleTVOS - IOS_CPU: arm64 - test_ios: "yes" - config: "no" - make: "no" - - name: Apple Watch on iOS, armv7 - os: macos-latest - AUTOTOOLS_HOST: armv7-apple-ios - OPENSSL_HOST: ios-cross - IOS_SDK: WatchOS - IOS_CPU: armv7k - test_ios: "yes" - config: "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 - os: macos-latest - AUTOTOOLS_HOST: x86_64-apple-ios - OPENSSL_HOST: iphoneos-cross - IOS_SDK: iPhoneSimulator - IOS_CPU: x86_64 - test_ios: "yes" - config: "no" - make: "no" - - name: AppleTVSimulator on OS X, x86_64 - os: macos-latest - AUTOTOOLS_HOST: x86_64-apple-ios - OPENSSL_HOST: iphoneos-cross - IOS_SDK: AppleTVSimulator - IOS_CPU: x86_64 - test_ios: "yes" - config: "no" - make: "no" - - name: WatchSimulator on OS X, i386 - os: macos-latest - AUTOTOOLS_HOST: i386-apple-ios - OPENSSL_HOST: iphoneos-cross - IOS_SDK: WatchSimulator - IOS_CPU: i386 - test_ios: "yes" - config: "no" - make: "no" - - name: Android armv7a - os: ubuntu-latest - AUTOTOOLS_HOST: armv7a-linux-androidabi - OPENSSL_HOST: android-arm - ANDROID_CPU: armv7a - ANDROID_API: 23 - test_android: "yes" - config: "no" - make: "no" - - name: Android aarch64 - os: ubuntu-latest - AUTOTOOLS_HOST: aarch64-linux-android - OPENSSL_HOST: android-arm64 - ANDROID_CPU: aarch64 - ANDROID_API: 23 - test_android: "yes" - config: "no" - make: "no" - - name: Android x86 - os: ubuntu-latest - AUTOTOOLS_HOST: i686-linux-android - OPENSSL_HOST: android-x86 - ANDROID_CPU: x86 - ANDROID_API: 23 - test_android: "yes" - config: "no" - make: "no" - - name: Android x86_64 - os: ubuntu-latest - AUTOTOOLS_HOST: x86_64-linux-android - OPENSSL_HOST: android-x86_64 - ANDROID_CPU: x86_64 - ANDROID_API: 23 - test_android: "yes" - config: "no" - make: "no" - - name: Windows - os: windows-latest - test_windows: "yes" - config: "no" - make: "no" - - steps: - - uses: actions/checkout@v2 - with: - submodules: false - - name: test_windows - if: ${{ matrix.test_windows == 'yes' }} - shell: bash - run: | - export unboundpath=`pwd` - echo unboundpath=${unboundpath} - cd .. - export prepath=`pwd` - echo prepath=${prepath} - #echo "curl cpanm" - #curl -L -k -s -S -o cpanm https://cpanmin.us/ - #echo "perl cpanm Pod::Usage" - #perl cpanm Pod::Usage - mkdir openssl - echo "curl openssl" - curl -L -k -s -S -o openssl-1.1.1j.tar.gz https://www.openssl.org/source/openssl-1.1.1j.tar.gz - tar xzf openssl-1.1.1j.tar.gz - cd openssl-1.1.1j - # remove pod::Usage because we do not need -help or -man output - # from the Configure script - echo "Fixup ./Configure by removing use Pod::Usage require" - sed -e 's/use Pod::Usage//' < Configure > Configure.fix - echo "./Configure.fix no-shared no-asm -DOPENSSL_NO_CAPIENG mingw64 --prefix=\""$prepath/openssl\""" - ./Configure.fix no-shared no-asm -DOPENSSL_NO_CAPIENG mingw64 --prefix="$prepath/openssl" - # make the libs only, build faster - echo "make build_libs" - #make - make build_libs - mv Makefile Makefile.orig - # fixup \\ in the installtop to /. - echo "fixup INSTALLTOP" - sed -e 's?^INSTALLTOP=.*$?INSTALLTOP='"$prepath"'/openssl?' < Makefile.orig > Makefile - # install the includes and libs only, build faster - echo "make install_dev" - #make install_sw - make install_dev - cd .. - mkdir expat - echo "curl expat" - 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 expat-2.2.10.tar.gz - 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\"" - ./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. - echo "Fixup Makefiles by renaming SHELL to SHELLZZ" - mv Makefile Makefile.orig - sed -e 's/SHELL/SHELLZZ/g' < Makefile.orig > Makefile - mv lib/Makefile lib/Makefile.orig - sed -e 's/SHELL/SHELLZZ/g' < lib/Makefile.orig > lib/Makefile - mv doc/Makefile doc/Makefile.orig - sed -e 's/SHELL/SHELLZZ/g' < doc/Makefile.orig > doc/Makefile - mv examples/Makefile examples/Makefile.orig - sed -e 's/SHELL/SHELLZZ/g' < examples/Makefile.orig > examples/Makefile - mv tests/Makefile tests/Makefile.orig - sed -e 's/SHELL/SHELLZZ/g' < tests/Makefile.orig > tests/Makefile - mv xmlwf/Makefile xmlwf/Makefile.orig - sed -e 's/SHELL/SHELLZZ/g' < xmlwf/Makefile.orig > xmlwf/Makefile - echo "make" - make - echo "make install" - make install - cd .. - echo "unbound" - cd unbound - echo "./configure --enable-debug --enable-static-exe --disable-flto \"--with-ssl=$prepath/openssl\" --with-libexpat=\"$prepath/expat\" --disable-shared" - ./configure --enable-debug --enable-static-exe --disable-flto "--with-ssl=$prepath/openssl" --with-libexpat="$prepath/expat" --disable-shared - make - # specific test output - #make testbound.exe; ./testbound.exe -s - #make testbound; ./testbound.exe -p testdata/acl.rpl -o -vvvv - make test - - name: test_android - if: ${{ matrix.test_android == 'yes' }} - env: - AUTOTOOLS_HOST: ${{ matrix.AUTOTOOLS_HOST }} - OPENSSL_HOST: ${{ matrix.OPENSSL_HOST }} - ANDROID_API: ${{ matrix.ANDROID_API }} - ANDROID_CPU: ${{ matrix.ANDROID_CPU }} - run: | - #(already installed) ./contrib/android/install_tools.sh - export ANDROID_PREFIX="$HOME/android$ANDROID_API-$ANDROID_CPU" - echo ANDROID_PREFIX=${ANDROID_PREFIX} - export ANDROID_SDK_ROOT="$HOME/android-sdk" - echo ANDROID_SDK_ROOT=${ANDROID_SDK_ROOT} - export ANDROID_NDK_ROOT="$HOME/android-ndk" - echo ANDROID_NDK_ROOT=${ANDROID_NDK_ROOT} - export AUTOTOOLS_BUILD="$(./config.guess)" - echo AUTOTOOLS_BUILD=${AUTOTOOLS_BUILD} - export PKG_CONFIG_PATH="$ANDROID_PREFIX/lib/pkgconfig" - echo PKG_CONFIG_PATH=${PKG_CONFIG_PATH} - 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} - echo "::group::install_ndk" - echo "./contrib/android/install_ndk.sh" - ./contrib/android/install_ndk.sh - echo "::endgroup::" - echo "::group::setenv_android.sh" - echo "./contrib/android/setenv_android.sh" - source ./contrib/android/setenv_android.sh - echo "::endgroup::" - echo "::group::install_openssl" - echo "./contrib/android/install_openssl.sh" - ./contrib/android/install_openssl.sh - echo "::endgroup::" - echo "::group::install_expat" - echo "./contrib/android/install_expat.sh" - ./contrib/android/install_expat.sh - echo "::endgroup::" - echo "::group::configure" - echo "./configure ${CONFIG_OPTS}" - ./configure ${CONFIG_OPTS} - echo "::endgroup::" - echo "::group::make" - # make is here to preserve environment variables - make - echo "::endgroup::" - echo "::group::make install" - make install - echo "::endgroup::" - - name: test ios - if: ${{ matrix.test_ios == 'yes' }} - env: - AUTOTOOLS_HOST: ${{ matrix.AUTOTOOLS_HOST }} - OPENSSL_HOST: ${{ matrix.OPENSSL_HOST }} - IOS_SDK: ${{ matrix.IOS_SDK }} - IOS_CPU: ${{ matrix.IOS_CPU }} - run: | - #(already installed) ./contrib/ios/install_tools.sh - export AUTOTOOLS_BUILD="$(./config.guess)" - echo AUTOTOOLS_BUILD=${AUTOTOOLS_BUILD} - export IOS_PREFIX="$HOME/$IOS_SDK-$IOS_CPU" - echo IOS_PREFIX=${IOS_PREFIX} - export PKG_CONFIG_PATH="$IOS_PREFIX/lib/pkgconfig" - echo PKG_CONFIG_PATH=${PKG_CONFIG_PATH} - 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} - echo "::group::setenv_ios.sh" - echo "./contrib/ios/setenv_ios.sh" - source ./contrib/ios/setenv_ios.sh - echo "::endgroup::" - echo "::group::install_openssl" - echo "./contrib/ios/install_openssl.sh" - ./contrib/ios/install_openssl.sh - echo "::endgroup::" - echo "::group::install_expat" - echo "./contrib/ios/install_expat.sh" - ./contrib/ios/install_expat.sh - echo "::endgroup::" - echo "::group::configure" - echo "./configure ${CONFIG_OPTS}" - ./configure ${CONFIG_OPTS} - echo "::endgroup::" - echo "::group::make" - # make is here to preserve environment variables - make - echo "::endgroup::" - echo "::group::make install" - make install - echo "::endgroup::" - - name: install libevent - if: ${{ matrix.install_libevent == 'yes' }} - run: sudo apt-get install libevent-dev - - name: install expat - if: ${{ matrix.install_expat == 'yes' }} - run: brew install expat - - name: configure - if: ${{ matrix.config != 'no' }} - run: ./configure ${{ matrix.config }} - - name: make - if: ${{ matrix.make != 'no' }} - run: make - - name: make test - if: ${{ matrix.make_test == 'yes' }} - run: make test - - name: clang-analysis - if: ${{ matrix.clang_analysis == 'yes' }} - run: (cd testdata/clang-analysis.tdir; bash clang-analysis.test) diff --git a/contrib/unbound/.github/workflows/ci.yml b/contrib/unbound/.github/workflows/ci.yml deleted file mode 100644 index 73d68fbf35c9..000000000000 --- a/contrib/unbound/.github/workflows/ci.yml +++ /dev/null @@ -1,21 +0,0 @@ -name: ci - -on: - push: - branches: [ master ] - pull_request: - branches: [ master ] - -jobs: - build: - - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v2 - - name: configure - run: ./configure --enable-debug - - name: make - run: make - - name: make test - run: make test diff --git a/contrib/unbound/.travis.yml b/contrib/unbound/.travis.yml deleted file mode 100644 index 1f514b5d08d4..000000000000 --- a/contrib/unbound/.travis.yml +++ /dev/null @@ -1,380 +0,0 @@ -language: c - -git: - depth: 5 - -addons: - apt: - packages: - - libssl-dev - - libevent-dev - - libexpat-dev - - clang - homebrew: - packages: - - openssl - - libevent - - expat - # homebrew update takes 20min or hangs, so disable update - #update: true - -jobs: - include: - - os: linux - name: GCC on Linux, Amd64 - compiler: gcc - arch: amd64 - env: - - CONFIG_OPTS="--enable-debug --disable-flto" - - os: linux - name: Clang on Linux, Amd64, clang-analysis - compiler: clang - arch: amd64 - env: - - CONFIG_OPTS="--enable-debug --disable-flto" - - TEST_ANALYZER=yes - - os: osx - osx_image: xcode12.2 - name: Clang on OS X, Amd64, clang-analysis - compiler: clang - arch: amd64 - env: - - TEST_OSX=yes - - CONFIG_OPTS="--enable-debug --disable-flto --with-ssl=/usr/local/opt/openssl --with-libexpat=/usr/local/opt/expat" - - TEST_ANALYZER=yes - - HOMEBREW_NO_AUTO_UPDATE=1 - - os: linux - name: Libevent, GCC on Linux, Amd64 - compiler: gcc - arch: amd64 - env: - - TEST_LIBEVENT=yes - - CONFIG_OPTS="--with-libevent" - - os: linux - name: Libevent, Clang on Linux, Amd64 - compiler: clang - arch: amd64 - env: - - TEST_LIBEVENT=yes - - CONFIG_OPTS="--with-libevent" - - os: osx - osx_image: xcode12.2 - name: Libevent, Clang on OS X, Amd64 - compiler: clang - arch: amd64 - env: - - TEST_OSX=yes - - TEST_LIBEVENT=yes - - CONFIG_OPTS="--disable-flto --with-ssl=/usr/local/opt/openssl --with-libevent=/usr/local/opt/libevent --with-libexpat=/usr/local/opt/expat" - - HOMEBREW_NO_AUTO_UPDATE=1 - - os: linux - name: UBsan, GCC on Linux, Amd64 - compiler: gcc - arch: amd64 - dist: bionic - env: - - TEST_UBSAN=yes - - os: linux - name: UBsan, Clang on Linux, Amd64 - compiler: clang - arch: amd64 - dist: bionic - env: - - TEST_UBSAN=yes - - os: linux - name: Asan, GCC on Linux, Amd64 - compiler: gcc - arch: amd64 - dist: bionic - env: - - TEST_ASAN=yes - - os: linux - name: Asan, Clang on Linux, Amd64 - compiler: clang - arch: amd64 - dist: bionic - env: - - TEST_ASAN=yes - - os: linux - name: GCC on Linux, Aarch64 - compiler: gcc - arch: arm64 - dist: bionic - env: - - CONFIG_OPTS="--enable-debug --disable-flto" - - os: linux - name: Clang on Linux, Aarch64 - compiler: clang - arch: arm64 - dist: bionic - env: - - CONFIG_OPTS="--enable-debug --disable-flto" - - os: linux - name: GCC on Linux, PowerPC64 - compiler: gcc - arch: ppc64le - dist: bionic - env: - - CONFIG_OPTS="--enable-debug --disable-flto" - - os: linux - name: Clang on Linux, PowerPC64 - compiler: clang - arch: ppc64le - dist: bionic - env: - - CONFIG_OPTS="--enable-debug --disable-flto" - - os: linux - name: GCC on Linux, s390x - compiler: gcc - arch: s390x - dist: bionic - env: - - CONFIG_OPTS="--enable-debug --disable-flto" - - os: linux - name: Clang on Linux, s390x - compiler: clang - arch: s390x - dist: bionic - env: - - CONFIG_OPTS="--enable-debug --disable-flto" - - os: osx - osx_image: xcode12.2 - name: Apple iPhone on iOS, armv7 - compiler: clang - env: - - TEST_IOS=yes - - AUTOTOOLS_HOST=armv7-apple-ios - - OPENSSL_HOST=ios-cross - - IOS_SDK=iPhoneOS - - IOS_CPU=armv7s - - IOS_PREFIX="$HOME/$IOS_SDK-$IOS_CPU" - - HOMEBREW_NO_AUTO_UPDATE=1 - - os: osx - osx_image: xcode12.2 - name: Apple iPhone on iOS, arm64 - compiler: clang - env: - - TEST_IOS=yes - - AUTOTOOLS_HOST=aarch64-apple-ios - - OPENSSL_HOST=ios64-cross - - IOS_SDK=iPhoneOS - - IOS_CPU=arm64 - - IOS_PREFIX="$HOME/$IOS_SDK-$IOS_CPU" - - HOMEBREW_NO_AUTO_UPDATE=1 - - os: osx - osx_image: xcode12.2 - name: Apple TV on iOS, arm64 - compiler: clang - env: - - TEST_IOS=yes - - AUTOTOOLS_HOST=aarch64-apple-ios - - OPENSSL_HOST=ios64-cross - - IOS_SDK=AppleTVOS - - IOS_CPU=arm64 - - IOS_PREFIX="$HOME/$IOS_SDK-$IOS_CPU" - - HOMEBREW_NO_AUTO_UPDATE=1 - - os: osx - osx_image: xcode12.2 - name: Apple Watch on iOS, armv7 - compiler: clang - env: - - TEST_IOS=yes - - AUTOTOOLS_HOST=armv7-apple-ios - - OPENSSL_HOST=ios-cross - - IOS_SDK=WatchOS - - IOS_CPU=armv7k - - IOS_PREFIX="$HOME/$IOS_SDK-$IOS_CPU" - - HOMEBREW_NO_AUTO_UPDATE=1 - - os: osx - osx_image: xcode12.2 - name: iPhoneSimulator on OS X, i386 - env: - - TEST_IOS=yes - - AUTOTOOLS_HOST=i386-apple-ios - - OPENSSL_HOST=iphoneos-cross - - IOS_CPU=i386 - - IOS_SDK=iPhoneSimulator - - IOS_PREFIX="$HOME/$IOS_SDK-$IOS_CPU" - - HOMEBREW_NO_AUTO_UPDATE=1 - - os: osx - osx_image: xcode12.2 - name: iPhoneSimulator on OS X, x86_64 - env: - - TEST_IOS=yes - - AUTOTOOLS_HOST=x86_64-apple-ios - - OPENSSL_HOST=iphoneos-cross - - IOS_CPU=x86_64 - - IOS_SDK=iPhoneSimulator - - IOS_PREFIX="$HOME/$IOS_SDK-$IOS_CPU" - - HOMEBREW_NO_AUTO_UPDATE=1 - - os: osx - osx_image: xcode12.2 - name: AppleTVSimulator on OS X, x86_64 - env: - - TEST_IOS=yes - - AUTOTOOLS_HOST=x86_64-apple-ios - - OPENSSL_HOST=iphoneos-cross - - IOS_CPU=x86_64 - - IOS_SDK=AppleTVSimulator - - IOS_PREFIX="$HOME/$IOS_SDK-$IOS_CPU" - - HOMEBREW_NO_AUTO_UPDATE=1 - - os: osx - osx_image: xcode12.2 - name: WatchSimulator on OS X, i386 - env: - - TEST_IOS=yes - - AUTOTOOLS_HOST=i386-apple-ios - - OPENSSL_HOST=iphoneos-cross - - IOS_CPU=i386 - - IOS_SDK=WatchSimulator - - IOS_PREFIX="$HOME/$IOS_SDK-$IOS_CPU" - - HOMEBREW_NO_AUTO_UPDATE=1 - - os: linux - name: Android armv7a, Linux, Amd64 - compiler: clang - arch: amd64 - dist: bionic - env: - - TEST_ANDROID=yes - - AUTOTOOLS_HOST=armv7a-linux-androideabi - - OPENSSL_HOST=android-arm - - ANDROID_CPU=armv7a - - ANDROID_API=23 - - ANDROID_PREFIX="$HOME/android$ANDROID_API-$ANDROID_CPU" - - ANDROID_SDK_ROOT="$HOME/android-sdk" - - ANDROID_NDK_ROOT="$HOME/android-ndk" - - os: linux - name: Android aarch64, Linux, Amd64 - compiler: clang - arch: amd64 - dist: bionic - env: - - TEST_ANDROID=yes - - AUTOTOOLS_HOST=aarch64-linux-android - - OPENSSL_HOST=android-arm64 - - ANDROID_CPU=aarch64 - - ANDROID_API=23 - - ANDROID_PREFIX="$HOME/android$ANDROID_API-$ANDROID_CPU" - - ANDROID_SDK_ROOT="$HOME/android-sdk" - - ANDROID_NDK_ROOT="$HOME/android-ndk" - - os: linux - name: Android x86, Linux, Amd64 - compiler: clang - arch: amd64 - dist: bionic - env: - - TEST_ANDROID=yes - - AUTOTOOLS_HOST=i686-linux-android - - OPENSSL_HOST=android-x86 - - ANDROID_CPU=x86 - - ANDROID_API=23 - - ANDROID_PREFIX="$HOME/android$ANDROID_API-$ANDROID_CPU" - - ANDROID_SDK_ROOT="$HOME/android-sdk" - - ANDROID_NDK_ROOT="$HOME/android-ndk" - - os: linux - name: Android x86_64, Linux, Amd64 - compiler: clang - arch: amd64 - dist: bionic - env: - - TEST_ANDROID=yes - - AUTOTOOLS_HOST=x86_64-linux-android - - OPENSSL_HOST=android-x86_64 - - ANDROID_CPU=x86_64 - - ANDROID_API=23 - - ANDROID_PREFIX="$HOME/android$ANDROID_API-$ANDROID_CPU" - - ANDROID_SDK_ROOT="$HOME/android-sdk" - - ANDROID_NDK_ROOT="$HOME/android-ndk" - - allow_failures: - - os: osx - name: Apple iPhone on iOS, armv7 - - os: osx - name: Apple iPhone on iOS, arm64 - - os: osx - name: Apple TV on iOS, arm64 - - os: osx - name: Apple Watch on iOS, armv7 - - os: osx - name: iPhoneSimulator on OS X, i386 - - os: osx - name: iPhoneSimulator on OS X, x86_64 - - os: osx - name: AppleTVSimulator on OS X, x86_64 - - os: osx - name: WatchSimulator on OS X, i386 - - os: linux - name: Android armv7a, Linux, Amd64 - - os: linux - name: Android aarch64, Linux, Amd64 - - os: linux - name: Android x86, Linux, Amd64 - - os: linux - name: Android x86_64, Linux, Amd64 - -before_script: - - | - if [ "$TEST_ANDROID" = "yes" ]; then - ./contrib/android/install_tools.sh - elif [ "$TEST_IOS" = "yes" ]; then - ./contrib/ios/install_tools.sh - fi - -# The Travis docs say to avoid calling exit in the script. It leads to -# some code duplication to avoid failures in cross-compiles. Also see -# https://docs.travis-ci.com/user/job-lifecycle/ in the Travis docs. -script: - - | - export MAKE_TEST="yes" - if [ "$TEST_UBSAN" = "yes" ]; then - export CFLAGS="-DNDEBUG -g2 -O3 -fsanitize=undefined -fno-sanitize-recover=all" - elif [ "$TEST_ASAN" = "yes" ]; then - export CFLAGS="-DNDEBUG -g2 -O3 -fsanitize=address" - fi - - | - if [ "$TEST_IOS" = "yes" ]; then - export AUTOTOOLS_BUILD="$(./config.guess)" - export PKG_CONFIG_PATH="$IOS_PREFIX/lib/pkgconfig" - source ./contrib/ios/setenv_ios.sh - ./contrib/ios/install_openssl.sh - ./contrib/ios/install_expat.sh - export CONFIG_OPTS="\ - --build=$AUTOTOOLS_BUILD --host=$AUTOTOOLS_HOST \ - --prefix=$IOS_PREFIX \ - --with-ssl=$IOS_PREFIX --disable-gost \ - --with-libexpat=$IOS_PREFIX " - echo CONFIG_OPTS ${CONFIG_OPTS} - export MAKE_TEST=no - export TEST_INSTALL=yes - fi - - | - if [ "$TEST_ANDROID" = "yes" ]; then - export AUTOTOOLS_BUILD="$(./config.guess)" - export PKG_CONFIG_PATH="$ANDROID_PREFIX/lib/pkgconfig" - ./contrib/android/install_ndk.sh - source ./contrib/android/setenv_android.sh - ./contrib/android/install_openssl.sh - ./contrib/android/install_expat.sh - export CONFIG_OPTS="\ - --build=$AUTOTOOLS_BUILD --host=$AUTOTOOLS_HOST \ - --prefix=$ANDROID_PREFIX \ - --with-ssl=$ANDROID_PREFIX --disable-gost \ - --with-libexpat=$ANDROID_PREFIX " - echo CONFIG_OPTS ${CONFIG_OPTS} - export MAKE_TEST=no - export TEST_INSTALL=yes - fi - - ./configure ${CONFIG_OPTS} - - make -j 2 - - | - if [ "$MAKE_TEST" = "yes" ]; then - make test - fi - - | - if [ "$TEST_INSTALL" = "yes" ]; then - make install - fi - - | - if [ "$TEST_ANALYZER" = "yes" ]; then - (cd testdata/clang-analysis.tdir; bash clang-analysis.test) - fi diff --git a/contrib/unbound/Makefile.in b/contrib/unbound/Makefile.in index ff5dc8fae856..55125a441977 100644 --- a/contrib/unbound/Makefile.in +++ b/contrib/unbound/Makefile.in @@ -61,6 +61,7 @@ PYTHON_CPPFLAGS=-I. @PYTHON_CPPFLAGS@ CFLAGS=-DSRCDIR=$(srcdir) @CFLAGS@ LDFLAGS=@LDFLAGS@ LIBS=@LIBS@ +PYTHON_LIBS=@PYTHON_LIBS@ LIBOBJS=@LIBOBJS@ # filter out ctime_r from compat obj. LIBOBJ_WITHOUT_CTIME=@LIBOBJ_WITHOUT_CTIME@ @@ -85,6 +86,8 @@ LINTFLAGS+=@NETBSD_LINTFLAGS@ LINTFLAGS+="-Dsigset_t=long" # FreeBSD LINTFLAGS+="-D__uint16_t=uint16_t" "-DEVP_PKEY_ASN1_METHOD=int" "-D_RuneLocale=int" "-D__va_list=va_list" "-D__uint32_t=uint32_t" "-D_Alignof(x)=x" "-D__aligned(x)=" "-D__requires_exclusive(x)=" "-D__requires_unlocked(x)=" "-D__locks_exclusive(x)=" "-D__trylocks_exclusive(x)=" "-D__unlocks(x)=" "-D__locks_shared(x)=" "-D__trylocks_shared(x)=" +# GCC Docker +LINTFLAGS+=@GCC_DOCKER_LINTFLAGS@ INSTALL=$(SHELL) $(srcdir)/install-sh @@ -476,7 +479,7 @@ libunbound/python/libunbound_wrap.c: $(srcdir)/libunbound/python/libunbound.i un # Pyunbound python unbound wrapper _unbound.la: libunbound_wrap.lo libunbound.la - $(LIBTOOL) --tag=CC --mode=link $(CC) $(RUNTIME_PATH) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -module -avoid-version -no-undefined -shared -o $@ libunbound_wrap.lo -rpath $(PYTHON_SITE_PKG) -L. -L.libs libunbound.la $(LIBS) + $(LIBTOOL) --tag=CC --mode=link $(CC) $(RUNTIME_PATH) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -module -avoid-version -no-undefined -shared -o $@ libunbound_wrap.lo -rpath $(PYTHON_SITE_PKG) -L. -L.libs libunbound.la $(PYTHON_LIBS) util/config_file.c: util/configparser.h util/configlexer.c: $(srcdir)/util/configlexer.lex util/configparser.h diff --git a/contrib/unbound/README-Travis.md b/contrib/unbound/README-Travis.md index 3ce22cc20f59..ca64456124af 100644 --- a/contrib/unbound/README-Travis.md +++ b/contrib/unbound/README-Travis.md @@ -241,7 +241,7 @@ If you are working from a developer machine you probably already have the necess The fourth step builds OpenSSL and Expat. OpenSSL and Expat are built for iOS using the scripts `contrib/ios/install_openssl.sh` and `contrib/ios/install_expat.sh`. The scripts download, configure and install the latest release version of the libraries. The libraries are configured with `--prefix="$IOS_PREFIX"` so the headers are placed in `$IOS_PREFIX/include` directory, and the libraries are placed in the `$IOS_PREFIX/lib` directory. -`IOS_PREFIX` is the value `$HOME/$IOS_SDK-$IOS_CPU`. The scheme handles both iOS SDKs and cpu architectures so the pair recieves a unique installation directory. The libraries will be installed in `$HOME/iPhoneOS-armv7s`, `$HOME/iPhoneOS-arm64`, `$HOME/iPhoneSimulator-i386`, etc. For Autotools projects, the appropriate `PKG_CONFIG_PATH` is exported. +`IOS_PREFIX` is the value `$HOME/$IOS_SDK-$IOS_CPU`. The scheme handles both iOS SDKs and cpu architectures so the pair receives a unique installation directory. The libraries will be installed in `$HOME/iPhoneOS-armv7s`, `$HOME/iPhoneOS-arm64`, `$HOME/iPhoneSimulator-i386`, etc. For Autotools projects, the appropriate `PKG_CONFIG_PATH` is exported. `PKG_CONFIG_PATH` is an important variable. It is the userland equivalent to sysroot, and allows Autotools to find non-system headers and libraries for an architecture. Typical `PKG_CONFIG_PATH` are `$HOME/iPhoneOS-armv7s/lib/pkgconfig` and `$HOME/iPhoneOS-arm64/lib/pkgconfig`. diff --git a/contrib/unbound/acx_nlnetlabs.m4 b/contrib/unbound/acx_nlnetlabs.m4 index 39e92d875331..1574f97bfe02 100644 --- a/contrib/unbound/acx_nlnetlabs.m4 +++ b/contrib/unbound/acx_nlnetlabs.m4 @@ -2,7 +2,10 @@ # Copyright 2009, Wouter Wijngaards, NLnet Labs. # BSD licensed. # -# Version 41 +# Version 43 +# 2021-08-17 fix sed script in ssldir split handling. +# 2021-08-17 fix for openssl to detect split version, with ssldir_include +# and ssldir_lib output directories. # 2021-07-30 fix for openssl use of lib64 directory. # 2021-06-14 fix nonblocking test to use host instead of target for mingw test. # 2021-05-17 fix nonblocking socket test from grep on mingw32 to mingw for @@ -647,6 +650,30 @@ AC_DEFUN([ACX_SSL_CHECKS], [ withval=$1 if test x_$withval != x_no; then AC_MSG_CHECKING(for SSL) + if test -n "$withval"; then + dnl look for openssl install with different version, eg. + dnl in /usr/include/openssl11/openssl/ssl.h + dnl and /usr/lib64/openssl11/libssl.so + dnl with the --with-ssl=/usr/include/openssl11 + if test ! -f "$withval/include/openssl/ssl.h" -a -f "$withval/openssl/ssl.h"; then + ssldir="$withval" + found_ssl="yes" + withval="" + ssldir_include="$ssldir" + dnl find the libdir + ssldir_lib=`echo $ssldir | sed -e 's/include/lib/'` + if test -f "$ssldir_lib/libssl.a" -o -f "$ssldir_lib/libssl.so"; then + : # found here + else + ssldir_lib=`echo $ssldir | sed -e 's/include/lib64/'` + if test -f "$ssldir_lib/libssl.a" -o -f "$ssldir_lib/libssl.so"; then + : # found here + else + AC_MSG_ERROR([Could not find openssl lib file, $ssldir_lib/libssl.[so,a], pass like "/usr/local" or "/usr/include/openssl11"]) + fi + fi + fi + fi if test x_$withval = x_ -o x_$withval = x_yes; then withval="/usr/local/ssl /usr/lib/ssl /usr/ssl /usr/pkg /usr/local /opt/local /usr/sfw /usr" fi @@ -654,12 +681,12 @@ AC_DEFUN([ACX_SSL_CHECKS], [ ssldir="$dir" if test -f "$dir/include/openssl/ssl.h"; then found_ssl="yes" - AC_DEFINE_UNQUOTED([HAVE_SSL], [], [Define if you have the SSL libraries installed.]) - dnl assume /usr/include is already in the include-path. - if test "$ssldir" != "/usr"; then - CPPFLAGS="$CPPFLAGS -I$ssldir/include" - LIBSSL_CPPFLAGS="$LIBSSL_CPPFLAGS -I$ssldir/include" - fi + ssldir_include="$ssldir/include" + if test ! -d "$ssldir/lib" -a -d "$ssldir/lib64"; then + ssldir_lib="$ssldir/lib64" + else + ssldir_lib="$ssldir/lib" + fi break; fi done @@ -667,19 +694,16 @@ AC_DEFUN([ACX_SSL_CHECKS], [ AC_MSG_ERROR(Cannot find the SSL libraries in $withval) else AC_MSG_RESULT(found in $ssldir) + AC_DEFINE_UNQUOTED([HAVE_SSL], [], [Define if you have the SSL libraries installed.]) HAVE_SSL=yes - dnl assume /usr is already in the lib and dynlib paths. - if test "$ssldir" != "/usr" -a "$ssldir" != ""; then - if test ! -d "$ssldir/lib" -a -d "$ssldir/lib64"; then - LDFLAGS="$LDFLAGS -L$ssldir/lib64" - LIBSSL_LDFLAGS="$LIBSSL_LDFLAGS -L$ssldir/lib64" - ACX_RUNTIME_PATH_ADD([$ssldir/lib64]) - else - LDFLAGS="$LDFLAGS -L$ssldir/lib" - LIBSSL_LDFLAGS="$LIBSSL_LDFLAGS -L$ssldir/lib" - ACX_RUNTIME_PATH_ADD([$ssldir/lib]) - fi - fi + dnl assume /usr is already in the include, lib and dynlib paths. + if test "$ssldir" != "/usr"; then + CPPFLAGS="$CPPFLAGS -I$ssldir_include" + LIBSSL_CPPFLAGS="$LIBSSL_CPPFLAGS -I$ssldir_include" + LDFLAGS="$LDFLAGS -L$ssldir_lib" + LIBSSL_LDFLAGS="$LIBSSL_LDFLAGS -L$ssldir_lib" + ACX_RUNTIME_PATH_ADD([$ssldir_lib]) + fi AC_MSG_CHECKING([for EVP_sha256 in -lcrypto]) LIBS="$LIBS -lcrypto" @@ -758,7 +782,7 @@ dnl AC_DEFUN([ACX_WITH_SSL], [ AC_ARG_WITH(ssl, AS_HELP_STRING([--with-ssl=pathname],[enable SSL (will check /usr/local/ssl - /usr/lib/ssl /usr/ssl /usr/pkg /usr/local /opt/local /usr/sfw /usr)]),[ + /usr/lib/ssl /usr/ssl /usr/pkg /usr/local /opt/local /usr/sfw /usr or specify like /usr/include/openssl11)]),[ ],[ withval="yes" ]) @@ -776,7 +800,7 @@ dnl AC_DEFUN([ACX_WITH_SSL_OPTIONAL], [ AC_ARG_WITH(ssl, AS_HELP_STRING([--with-ssl=pathname],[enable SSL (will check /usr/local/ssl - /usr/lib/ssl /usr/ssl /usr/pkg /usr/local /opt/local /usr/sfw /usr)]),[ + /usr/lib/ssl /usr/ssl /usr/pkg /usr/local /opt/local /usr/sfw /usr or specify like /usr/include/openssl11)]),[ ],[ withval="yes" ]) diff --git a/contrib/unbound/cachedb/cachedb.c b/contrib/unbound/cachedb/cachedb.c index af4ffe5f28b5..725bc6ce8b38 100644 --- a/contrib/unbound/cachedb/cachedb.c +++ b/contrib/unbound/cachedb/cachedb.c @@ -519,7 +519,7 @@ parse_data(struct module_qstate* qstate, struct sldns_buffer* buf) sldns_buffer_set_limit(buf, lim); return 0; } - if(parse_extract_edns(prs, &edns, qstate->env->scratch) != + if(parse_extract_edns_from_response_msg(prs, &edns, qstate->env->scratch) != LDNS_RCODE_NOERROR) { sldns_buffer_set_limit(buf, lim); return 0; diff --git a/contrib/unbound/config.h.in b/contrib/unbound/config.h.in index ea6afa4802ee..e8a26735d2d3 100644 --- a/contrib/unbound/config.h.in +++ b/contrib/unbound/config.h.in @@ -72,6 +72,9 @@ /* If we have be64toh */ #undef HAVE_BE64TOH +/* Define to 1 if you have the `BIO_set_callback_ex' function. */ +#undef HAVE_BIO_SET_CALLBACK_EX + /* Define to 1 if you have the header file. */ #undef HAVE_BSD_STDLIB_H @@ -315,6 +318,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_IFADDRS_H +/* Define to 1 if you have the `if_nametoindex' function. */ +#undef HAVE_IF_NAMETOINDEX + /* Define to 1 if you have the `inet_aton' function. */ #undef HAVE_INET_ATON diff --git a/contrib/unbound/config.sub b/contrib/unbound/config.sub index d80c5d759e48..d74fb6deac94 100755 --- a/contrib/unbound/config.sub +++ b/contrib/unbound/config.sub @@ -4,7 +4,7 @@ # shellcheck disable=SC2006,SC2268 # see below for rationale -timestamp='2021-07-03' +timestamp='2021-08-14' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by @@ -121,9 +121,11 @@ esac # Split fields of configuration type # shellcheck disable=SC2162 +saved_IFS=$IFS IFS="-" read field1 field2 field3 field4 <&2 diff --git a/contrib/unbound/configure b/contrib/unbound/configure index 346fd5e5b076..df25819eabbf 100755 --- a/contrib/unbound/configure +++ b/contrib/unbound/configure @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.69 for unbound 1.13.2. +# Generated by GNU Autoconf 2.69 for unbound 1.14.0rc1. # # Report bugs to . # @@ -591,8 +591,8 @@ MAKEFLAGS= # Identity of this package. PACKAGE_NAME='unbound' PACKAGE_TARNAME='unbound' -PACKAGE_VERSION='1.13.2' -PACKAGE_STRING='unbound 1.13.2' +PACKAGE_VERSION='1.14.0rc1' +PACKAGE_STRING='unbound 1.14.0rc1' PACKAGE_BUGREPORT='unbound-bugs@nlnetlabs.nl or https://github.com/NLnetLabs/unbound/issues' PACKAGE_URL='' @@ -682,6 +682,7 @@ SSLLIB HAVE_SSL PC_CRYPTO_DEPENDENCY CONFIG_DATE +GCC_DOCKER_LINTFLAGS NETBSD_LINTFLAGS PYUNBOUND_UNINSTALL PYUNBOUND_INSTALL @@ -697,6 +698,7 @@ swig SWIG_LIB SWIG PC_PY_DEPENDENCY +PYTHON_LIBS PY_MAJOR_VERSION PYTHON_SITE_PKG PYTHON_LDFLAGS @@ -1464,7 +1466,7 @@ if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures unbound 1.13.2 to adapt to many kinds of systems. +\`configure' configures unbound 1.14.0rc1 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1529,7 +1531,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of unbound 1.13.2:";; + short | recursive ) echo "Configuration of unbound 1.14.0rc1:";; esac cat <<\_ACEOF @@ -1649,7 +1651,7 @@ Optional Packages: --with-nettle=path use libnettle as crypto library, installed at path. --with-ssl=pathname enable SSL (will check /usr/local/ssl /usr/lib/ssl /usr/ssl /usr/pkg /usr/local /opt/local /usr/sfw - /usr) + /usr or specify like /usr/include/openssl11) --with-libbsd Use portable libbsd functions --with-deprecate-rsa-1024 Deprecate RSA 1024 bit length, makes that an @@ -1771,7 +1773,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -unbound configure 1.13.2 +unbound configure 1.14.0rc1 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. @@ -2480,7 +2482,7 @@ cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by unbound $as_me 1.13.2, which was +It was created by unbound $as_me 1.14.0rc1, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ @@ -2830,13 +2832,13 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu UNBOUND_VERSION_MAJOR=1 -UNBOUND_VERSION_MINOR=13 +UNBOUND_VERSION_MINOR=14 -UNBOUND_VERSION_MICRO=2 +UNBOUND_VERSION_MICRO=0rc1 LIBUNBOUND_CURRENT=9 -LIBUNBOUND_REVISION=13 +LIBUNBOUND_REVISION=14 LIBUNBOUND_AGE=1 # 1.0.0 had 0:12:0 # 1.0.1 had 0:13:0 @@ -2917,6 +2919,7 @@ LIBUNBOUND_AGE=1 # 1.13.0 had 9:11:1 # 1.13.1 had 9:12:1 # 1.13.2 had 9:13:1 +# 1.14.0 had 9:14:1 # Current -- the number of the binary API that we're implementing # Revision -- which iteration of the implementation of the binary @@ -15322,7 +15325,7 @@ if test "$ac_res" != no; then : fi -# check wether strptime also works +# check whether strptime also works # check some functions of the OS before linking libs (while still runnable). for ac_header in unistd.h @@ -17553,11 +17556,15 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu $as_echo "#define HAVE_PYTHON 1" >>confdefs.h - if test -n "$LIBS"; then - LIBS="$PYTHON_LDFLAGS $LIBS" - else - LIBS="$PYTHON_LDFLAGS" + if test x_$ub_with_pythonmod != x_no; then + if test -n "$LIBS"; then + LIBS="$PYTHON_LDFLAGS $LIBS" + else + LIBS="$PYTHON_LDFLAGS" + fi fi + PYTHON_LIBS="$PYTHON_LDFLAGS" + if test -n "$CPPFLAGS"; then CPPFLAGS="$CPPFLAGS $PYTHON_CPPFLAGS" else @@ -17886,6 +17893,12 @@ fi if test "`uname`" = "NetBSD"; then NETBSD_LINTFLAGS='"-D__RENAME(x)=" -D_NETINET_IN_H_' +fi + +if test "`uname -o`" = "GNU/Linux"; then + # splint cannot parse modern c99 header files + GCC_DOCKER_LINTFLAGS='-syntax' + fi CONFIG_DATE=`date +%Y%m%d` @@ -17993,6 +18006,25 @@ fi if test x_$withval != x_no; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for SSL" >&5 $as_echo_n "checking for SSL... " >&6; } + if test -n "$withval"; then + if test ! -f "$withval/include/openssl/ssl.h" -a -f "$withval/openssl/ssl.h"; then + ssldir="$withval" + found_ssl="yes" + withval="" + ssldir_include="$ssldir" + ssldir_lib=`echo $ssldir | sed -e 's/include/lib/'` + if test -f "$ssldir_lib/libssl.a" -o -f "$ssldir_lib/libssl.so"; then + : # found here + else + ssldir_lib=`echo $ssldir | sed -e 's/include/lib64/'` + if test -f "$ssldir_lib/libssl.a" -o -f "$ssldir_lib/libssl.so"; then + : # found here + else + as_fn_error $? "Could not find openssl lib file, $ssldir_lib/libssl.so,a, pass like \"/usr/local\" or \"/usr/include/openssl11\"" "$LINENO" 5 + fi + fi + fi + fi if test x_$withval = x_ -o x_$withval = x_yes; then withval="/usr/local/ssl /usr/lib/ssl /usr/ssl /usr/pkg /usr/local /opt/local /usr/sfw /usr" fi @@ -18000,15 +18032,12 @@ $as_echo_n "checking for SSL... " >&6; } ssldir="$dir" if test -f "$dir/include/openssl/ssl.h"; then found_ssl="yes" - -cat >>confdefs.h <<_ACEOF -#define HAVE_SSL /**/ -_ACEOF - - if test "$ssldir" != "/usr"; then - CPPFLAGS="$CPPFLAGS -I$ssldir/include" - LIBSSL_CPPFLAGS="$LIBSSL_CPPFLAGS -I$ssldir/include" - fi + ssldir_include="$ssldir/include" + if test ! -d "$ssldir/lib" -a -d "$ssldir/lib64"; then + ssldir_lib="$ssldir/lib64" + else + ssldir_lib="$ssldir/lib" + fi break; fi done @@ -18017,30 +18046,25 @@ _ACEOF else { $as_echo "$as_me:${as_lineno-$LINENO}: result: found in $ssldir" >&5 $as_echo "found in $ssldir" >&6; } + +cat >>confdefs.h <<_ACEOF +#define HAVE_SSL /**/ +_ACEOF + HAVE_SSL=yes - if test "$ssldir" != "/usr" -a "$ssldir" != ""; then - if test ! -d "$ssldir/lib" -a -d "$ssldir/lib64"; then - LDFLAGS="$LDFLAGS -L$ssldir/lib64" - LIBSSL_LDFLAGS="$LIBSSL_LDFLAGS -L$ssldir/lib64" + if test "$ssldir" != "/usr"; then + CPPFLAGS="$CPPFLAGS -I$ssldir_include" + LIBSSL_CPPFLAGS="$LIBSSL_CPPFLAGS -I$ssldir_include" + LDFLAGS="$LDFLAGS -L$ssldir_lib" + LIBSSL_LDFLAGS="$LIBSSL_LDFLAGS -L$ssldir_lib" if test "x$enable_rpath" = xyes; then - if echo "$ssldir/lib64" | grep "^/" >/dev/null; then - RUNTIME_PATH="$RUNTIME_PATH -R$ssldir/lib64" + if echo "$ssldir_lib" | grep "^/" >/dev/null; then + RUNTIME_PATH="$RUNTIME_PATH -R$ssldir_lib" fi fi - else - LDFLAGS="$LDFLAGS -L$ssldir/lib" - LIBSSL_LDFLAGS="$LIBSSL_LDFLAGS -L$ssldir/lib" - - if test "x$enable_rpath" = xyes; then - if echo "$ssldir/lib" | grep "^/" >/dev/null; then - RUNTIME_PATH="$RUNTIME_PATH -R$ssldir/lib" - fi - fi - - fi - fi + fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for EVP_sha256 in -lcrypto" >&5 $as_echo_n "checking for EVP_sha256 in -lcrypto... " >&6; } @@ -18328,7 +18352,7 @@ rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext SSLLIB="-lssl" -PC_CRYPTO_DEPENDENCY="libcrypto libssl" +PC_CRYPTO_DEPENDENCY="" # check if -lcrypt32 is needed because CAPIENG needs that. (on windows) @@ -18369,7 +18393,7 @@ rm -f core conftest.err conftest.$ac_objext \ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for LibreSSL" >&5 $as_echo_n "checking for LibreSSL... " >&6; } -if grep VERSION_TEXT $ssldir/include/openssl/opensslv.h | grep "LibreSSL" >/dev/null; then +if grep VERSION_TEXT $ssldir_include/openssl/opensslv.h | grep "LibreSSL" >/dev/null; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } @@ -18436,7 +18460,7 @@ fi done -for ac_func in OPENSSL_config EVP_sha1 EVP_sha256 EVP_sha512 FIPS_mode 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 +for ac_func in OPENSSL_config EVP_sha1 EVP_sha256 EVP_sha512 FIPS_mode 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 do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" @@ -18758,7 +18782,7 @@ $as_echo "#define CLIENT_SUBNET 1" >>confdefs.h ;; esac -# check wether gost also works +# check whether gost also works # Check whether --enable-gost was given. if test "${enable_gost+set}" = set; then : @@ -18791,7 +18815,7 @@ $as_echo_n "checking if GOST works... " >&6; } if test c${cross_compiling} = cno; then BAKCFLAGS="$CFLAGS" if test -n "$ssldir"; then - CFLAGS="$CFLAGS -Wl,-rpath,$ssldir/lib" + CFLAGS="$CFLAGS -Wl,-rpath,$ssldir_lib" fi if test "$cross_compiling" = yes; then : { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 @@ -18974,8 +18998,8 @@ fi # see if OPENSSL 1.0.0 or later (has EVP MD and Verify independency) { $as_echo "$as_me:${as_lineno-$LINENO}: checking if openssl supports SHA2 and ECDSA with EVP" >&5 $as_echo_n "checking if openssl supports SHA2 and ECDSA with EVP... " >&6; } - if grep OPENSSL_VERSION_TEXT $ssldir/include/openssl/opensslv.h | grep "OpenSSL" >/dev/null; then - if grep OPENSSL_VERSION_NUMBER $ssldir/include/openssl/opensslv.h | grep 0x0 >/dev/null; then + if grep OPENSSL_VERSION_TEXT $ssldir_include/openssl/opensslv.h | grep "OpenSSL" >/dev/null; then + if grep OPENSSL_VERSION_NUMBER $ssldir_include/openssl/opensslv.h | grep 0x0 >/dev/null; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } @@ -20398,7 +20422,7 @@ if test "$ac_res" != no; then : fi -for ac_func in 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 +for ac_func in 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 do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" @@ -21816,7 +21840,7 @@ _ACEOF -version=1.13.2 +version=1.14.0rc1 date=`date +'%b %e, %Y'` @@ -22335,7 +22359,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by unbound $as_me 1.13.2, which was +This file was extended by unbound $as_me 1.14.0rc1, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -22401,7 +22425,7 @@ _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -unbound config.status 1.13.2 +unbound config.status 1.14.0rc1 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" diff --git a/contrib/unbound/configure.ac b/contrib/unbound/configure.ac index fe911723c87e..418ea099f6ad 100644 --- a/contrib/unbound/configure.ac +++ b/contrib/unbound/configure.ac @@ -10,15 +10,15 @@ sinclude(dnscrypt/dnscrypt.m4) # must be numbers. ac_defun because of later processing m4_define([VERSION_MAJOR],[1]) -m4_define([VERSION_MINOR],[13]) -m4_define([VERSION_MICRO],[2]) +m4_define([VERSION_MINOR],[14]) +m4_define([VERSION_MICRO],[0rc1]) AC_INIT([unbound],m4_defn([VERSION_MAJOR]).m4_defn([VERSION_MINOR]).m4_defn([VERSION_MICRO]),[unbound-bugs@nlnetlabs.nl or https://github.com/NLnetLabs/unbound/issues],[unbound]) AC_SUBST(UNBOUND_VERSION_MAJOR, [VERSION_MAJOR]) AC_SUBST(UNBOUND_VERSION_MINOR, [VERSION_MINOR]) AC_SUBST(UNBOUND_VERSION_MICRO, [VERSION_MICRO]) LIBUNBOUND_CURRENT=9 -LIBUNBOUND_REVISION=13 +LIBUNBOUND_REVISION=14 LIBUNBOUND_AGE=1 # 1.0.0 had 0:12:0 # 1.0.1 had 0:13:0 @@ -99,6 +99,7 @@ LIBUNBOUND_AGE=1 # 1.13.0 had 9:11:1 # 1.13.1 had 9:12:1 # 1.13.2 had 9:13:1 +# 1.14.0 had 9:14:1 # Current -- the number of the binary API that we're implementing # Revision -- which iteration of the implementation of the binary @@ -457,7 +458,7 @@ AC_SUBST(RUNTIME_PATH) AC_SEARCH_LIBS([inet_pton], [nsl]) AC_SEARCH_LIBS([socket], [socket]) -# check wether strptime also works +# check whether strptime also works AC_DEFUN([AC_CHECK_STRPTIME_WORKS], [AC_REQUIRE([AC_PROG_CC]) AC_MSG_CHECKING(whether strptime works) @@ -699,11 +700,15 @@ if test x_$ub_test_python != x_no; then AC_SUBST(PY_MAJOR_VERSION) # Have Python AC_DEFINE(HAVE_PYTHON,1,[Define if you have Python libraries and header files.]) - if test -n "$LIBS"; then - LIBS="$PYTHON_LDFLAGS $LIBS" - else - LIBS="$PYTHON_LDFLAGS" + if test x_$ub_with_pythonmod != x_no; then + if test -n "$LIBS"; then + LIBS="$PYTHON_LDFLAGS $LIBS" + else + LIBS="$PYTHON_LDFLAGS" + fi fi + PYTHON_LIBS="$PYTHON_LDFLAGS" + AC_SUBST(PYTHON_LIBS) if test -n "$CPPFLAGS"; then CPPFLAGS="$CPPFLAGS $PYTHON_CPPFLAGS" else @@ -776,6 +781,12 @@ if test "`uname`" = "NetBSD"; then NETBSD_LINTFLAGS='"-D__RENAME(x)=" -D_NETINET_IN_H_' AC_SUBST(NETBSD_LINTFLAGS) fi + +if test "`uname -o`" = "GNU/Linux"; then + # splint cannot parse modern c99 header files + GCC_DOCKER_LINTFLAGS='-syntax' + AC_SUBST(GCC_DOCKER_LINTFLAGS) +fi CONFIG_DATE=`date +%Y%m%d` AC_SUBST(CONFIG_DATE) @@ -830,7 +841,7 @@ ACX_WITH_SSL ACX_LIB_SSL SSLLIB="-lssl" -PC_CRYPTO_DEPENDENCY="libcrypto libssl" +PC_CRYPTO_DEPENDENCY="" AC_SUBST(PC_CRYPTO_DEPENDENCY) # check if -lcrypt32 is needed because CAPIENG needs that. (on windows) @@ -850,7 +861,7 @@ AC_LINK_IFELSE([AC_LANG_PROGRAM([[]], [[ ]) AC_MSG_CHECKING([for LibreSSL]) -if grep VERSION_TEXT $ssldir/include/openssl/opensslv.h | grep "LibreSSL" >/dev/null; then +if grep VERSION_TEXT $ssldir_include/openssl/opensslv.h | grep "LibreSSL" >/dev/null; then AC_MSG_RESULT([yes]) AC_DEFINE([HAVE_LIBRESSL], [1], [Define if we have LibreSSL]) # libressl provides these compat functions, but they may also be @@ -860,7 +871,7 @@ else AC_MSG_RESULT([no]) fi AC_CHECK_HEADERS([openssl/conf.h openssl/engine.h openssl/bn.h openssl/dh.h openssl/dsa.h openssl/rsa.h openssl/core_names.h openssl/param_build.h],,, [AC_INCLUDES_DEFAULT]) -AC_CHECK_FUNCS([OPENSSL_config EVP_sha1 EVP_sha256 EVP_sha512 FIPS_mode EVP_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]) +AC_CHECK_FUNCS([OPENSSL_config EVP_sha1 EVP_sha256 EVP_sha512 FIPS_mode 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 BAKLIBS="$LIBS" @@ -973,14 +984,14 @@ case "$enable_subnet" in ;; esac -# check wether gost also works +# check whether gost also works AC_DEFUN([AC_CHECK_GOST_WORKS], [AC_REQUIRE([AC_PROG_CC]) AC_MSG_CHECKING([if GOST works]) if test c${cross_compiling} = cno; then BAKCFLAGS="$CFLAGS" if test -n "$ssldir"; then - CFLAGS="$CFLAGS -Wl,-rpath,$ssldir/lib" + CFLAGS="$CFLAGS -Wl,-rpath,$ssldir_lib" fi AC_RUN_IFELSE([AC_LANG_SOURCE([[ #include @@ -1103,8 +1114,8 @@ case "$enable_ecdsa" in ]) # 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]) - if grep OPENSSL_VERSION_TEXT $ssldir/include/openssl/opensslv.h | grep "OpenSSL" >/dev/null; then - if grep OPENSSL_VERSION_NUMBER $ssldir/include/openssl/opensslv.h | grep 0x0 >/dev/null; then + if grep OPENSSL_VERSION_TEXT $ssldir_include/openssl/opensslv.h | grep "OpenSSL" >/dev/null; then + if grep OPENSSL_VERSION_NUMBER $ssldir_include/openssl/opensslv.h | grep 0x0 >/dev/null; then AC_MSG_RESULT([no]) AC_DEFINE_UNQUOTED([USE_ECDSA_EVP_WORKAROUND], [1], [Define this to enable an EVP workaround for older openssl]) else @@ -1594,7 +1605,7 @@ AC_LINK_IFELSE([AC_LANG_PROGRAM([ AC_MSG_RESULT(no)) AC_SEARCH_LIBS([setusercontext], [util]) -AC_CHECK_FUNCS([tzset sigprocmask fcntl getpwnam endpwent getrlimit setrlimit setsid chroot kill chown sleep usleep random srandom recvmsg sendmsg writev socketpair glob initgroups strftime localtime_r setusercontext _beginthreadex endservent endprotoent fsync shmget accept4 getifaddrs]) +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]) AC_CHECK_FUNCS([setresuid],,[AC_CHECK_FUNCS([setreuid])]) AC_CHECK_FUNCS([setresgid],,[AC_CHECK_FUNCS([setregid])]) diff --git a/contrib/unbound/contrib/Dockerfile.tests b/contrib/unbound/contrib/Dockerfile.tests new file mode 100644 index 000000000000..417daccb21f9 --- /dev/null +++ b/contrib/unbound/contrib/Dockerfile.tests @@ -0,0 +1,11 @@ +FROM gcc:latest +WORKDIR /usr/src/unbound +RUN apt-get update +# install semantic parser & lexical analyzer +RUN apt-get install -y bison flex +# install packages used in tests +RUN apt-get install -y ldnsutils dnsutils xxd splint doxygen netcat +# accept short rsa keys, which are used in tests +RUN sed -i 's/SECLEVEL=2/SECLEVEL=1/g' /usr/lib/ssl/openssl.cnf + +CMD ["/bin/bash"] diff --git a/contrib/unbound/contrib/drop2rpz b/contrib/unbound/contrib/drop2rpz index 01602f651166..6ac9b492efe3 100644 --- a/contrib/unbound/contrib/drop2rpz +++ b/contrib/unbound/contrib/drop2rpz @@ -4,7 +4,7 @@ # # unbound.conf: # rpz: -# name: "spamhaus-drop.rpz.local." +# name: "drop.spamhaus.org.rpz.local." # zonefile: "/path/tp/spamhaus-drop.rpz.local" # rpz-log: yes # rpz-log-name: "spamhaus-drop" diff --git a/contrib/unbound/contrib/unbound.service.in b/contrib/unbound/contrib/unbound.service.in index 90ee708ce2c5..ada5fac9c224 100644 --- a/contrib/unbound/contrib/unbound.service.in +++ b/contrib/unbound/contrib/unbound.service.in @@ -64,7 +64,8 @@ ProtectClock=true ProtectControlGroups=true ProtectKernelLogs=true ProtectKernelModules=true -ProtectKernelTunables=true +# This breaks using socket options like 'so-rcvbuf'. Explicitly disable for visibility. +ProtectKernelTunables=false ProtectProc=invisible ProtectSystem=strict RuntimeDirectory=unbound diff --git a/contrib/unbound/daemon/daemon.c b/contrib/unbound/daemon/daemon.c index 6d666788325a..0e3923b4e9f2 100644 --- a/contrib/unbound/daemon/daemon.c +++ b/contrib/unbound/daemon/daemon.c @@ -210,7 +210,6 @@ daemon_init(void) } #endif /* USE_WINSOCK */ signal_handling_record(); - checklock_start(); #ifdef HAVE_SSL # ifdef HAVE_ERR_LOAD_CRYPTO_STRINGS ERR_load_crypto_strings(); @@ -280,6 +279,7 @@ daemon_init(void) free(daemon); return NULL; } + listen_setup_locks(); if(gettimeofday(&daemon->time_boot, NULL) < 0) log_err("gettimeofday: %s", strerror(errno)); daemon->time_last_stat = daemon->time_boot; @@ -781,6 +781,7 @@ daemon_delete(struct daemon* daemon) alloc_clear(&daemon->superalloc); acl_list_delete(daemon->acl); tcl_list_delete(daemon->tcl); + listen_desetup_locks(); free(daemon->chroot); free(daemon->pidfile); free(daemon->env); diff --git a/contrib/unbound/daemon/remote.c b/contrib/unbound/daemon/remote.c index 923ddefa4f29..adf0383895d4 100644 --- a/contrib/unbound/daemon/remote.c +++ b/contrib/unbound/daemon/remote.c @@ -813,7 +813,7 @@ print_mem(RES* ssl, struct worker* worker, struct daemon* daemon, iter = mod_get_mem(&worker->env, "iterator"); respip = mod_get_mem(&worker->env, "respip"); #ifdef CLIENT_SUBNET - subnet = mod_get_mem(&worker->env, "subnet"); + subnet = mod_get_mem(&worker->env, "subnetcache"); #endif /* CLIENT_SUBNET */ #ifdef USE_IPSECMOD ipsecmod = mod_get_mem(&worker->env, "ipsecmod"); diff --git a/contrib/unbound/daemon/stats.c b/contrib/unbound/daemon/stats.c index 8720a52d6c6e..d08f18dbb137 100644 --- a/contrib/unbound/daemon/stats.c +++ b/contrib/unbound/daemon/stats.c @@ -137,7 +137,7 @@ static void set_subnet_stats(struct worker* worker, struct ub_server_stats* svr, int reset) { - int m = modstack_find(&worker->env.mesh->mods, "subnet"); + int m = modstack_find(&worker->env.mesh->mods, "subnetcache"); struct subnet_env* sne; if(m == -1) return; diff --git a/contrib/unbound/daemon/unbound.c b/contrib/unbound/daemon/unbound.c index 934a96c8068b..457a08032857 100644 --- a/contrib/unbound/daemon/unbound.c +++ b/contrib/unbound/daemon/unbound.c @@ -781,6 +781,7 @@ main(int argc, char* argv[]) int cmdline_cfg = 0; #endif + checklock_start(); log_init(NULL, 0, NULL); log_ident_default = strrchr(argv[0],'/')?strrchr(argv[0],'/')+1:argv[0]; log_ident_set_default(log_ident_default); diff --git a/contrib/unbound/daemon/worker.c b/contrib/unbound/daemon/worker.c index e9e163a0448b..5d2483cd2cd9 100644 --- a/contrib/unbound/daemon/worker.c +++ b/contrib/unbound/daemon/worker.c @@ -146,7 +146,7 @@ worker_mem_report(struct worker* ATTR_UNUSED(worker), (&worker->env, i); #ifdef CLIENT_SUBNET else if(strcmp(worker->env.mesh->mods.mod[i]->name, - "subnet")==0) + "subnetcache")==0) subnet += (*worker->env.mesh->mods.mod[i]->get_mem) (&worker->env, i); #endif /* CLIENT_SUBNET */ @@ -205,7 +205,7 @@ worker_mem_report(struct worker* ATTR_UNUSED(worker), (&worker->env, i); #ifdef CLIENT_SUBNET else if(strcmp(worker->env.mesh->mods.mod[i]->name, - "subnet")==0) + "subnetcache")==0) subnet += (*worker->env.mesh->mods.mod[i]->get_mem) (&worker->env, i); #endif /* CLIENT_SUBNET */ @@ -449,7 +449,6 @@ answer_norec_from_cache(struct worker* worker, struct query_info* qinfo, * Then check if it needs validation, if so, this routine fails, * so that iterator can prime and validator can verify rrsets. */ - struct edns_data edns_bak; uint16_t udpsize = edns->udp_size; int secure = 0; time_t timenow = *worker->env.now; @@ -508,7 +507,6 @@ answer_norec_from_cache(struct worker* worker, struct query_info* qinfo, } } /* return this delegation from the cache */ - edns_bak = *edns; edns->edns_version = EDNS_ADVERTISED_VERSION; edns->udp_size = EDNS_ADVERTISED_SIZE; edns->ext_rcode = 0; @@ -518,15 +516,13 @@ answer_norec_from_cache(struct worker* worker, struct query_info* qinfo, worker->env.now_tv)) return 0; msg->rep->flags |= BIT_QR|BIT_RA; - if(!apply_edns_options(edns, &edns_bak, worker->env.cfg, - repinfo->c, worker->scratchpad) || - !reply_info_answer_encode(&msg->qinfo, msg->rep, id, flags, + if(!reply_info_answer_encode(&msg->qinfo, msg->rep, id, flags, repinfo->c->buffer, 0, 1, worker->scratchpad, udpsize, edns, (int)(edns->bits & EDNS_DO), secure)) { if(!inplace_cb_reply_servfail_call(&worker->env, qinfo, NULL, NULL, LDNS_RCODE_SERVFAIL, edns, repinfo, worker->scratchpad, worker->env.now_tv)) - edns->opt_list = NULL; + edns->opt_list_inplace_cb_out = NULL; error_encode(repinfo->c->buffer, LDNS_RCODE_SERVFAIL, &msg->qinfo, id, flags, edns); } @@ -604,7 +600,6 @@ answer_from_cache(struct worker* worker, struct query_info* qinfo, struct reply_info* rep, uint16_t id, uint16_t flags, struct comm_reply* repinfo, struct edns_data* edns) { - struct edns_data edns_bak; time_t timenow = *worker->env.now; uint16_t udpsize = edns->udp_size; struct reply_info* encode_rep = rep; @@ -685,7 +680,6 @@ answer_from_cache(struct worker* worker, struct query_info* qinfo, } } else *is_secure_answer = 0; - edns_bak = *edns; edns->edns_version = EDNS_ADVERTISED_VERSION; edns->udp_size = EDNS_ADVERTISED_SIZE; edns->ext_rcode = 0; @@ -722,15 +716,13 @@ answer_from_cache(struct worker* worker, struct query_info* qinfo, if(!*partial_repp) goto bail_out; } - } else if(!apply_edns_options(edns, &edns_bak, worker->env.cfg, - repinfo->c, worker->scratchpad) || - !reply_info_answer_encode(qinfo, encode_rep, id, flags, + } else if(!reply_info_answer_encode(qinfo, encode_rep, id, flags, repinfo->c->buffer, timenow, 1, worker->scratchpad, udpsize, edns, (int)(edns->bits & EDNS_DO), *is_secure_answer)) { if(!inplace_cb_reply_servfail_call(&worker->env, qinfo, NULL, NULL, LDNS_RCODE_SERVFAIL, edns, repinfo, worker->scratchpad, worker->env.now_tv)) - edns->opt_list = NULL; + edns->opt_list_inplace_cb_out = NULL; error_encode(repinfo->c->buffer, LDNS_RCODE_SERVFAIL, qinfo, id, flags, edns); } @@ -789,6 +781,14 @@ chaos_replystr(sldns_buffer* pkt, char** str, int num, struct edns_data* edns, int i; unsigned int rd = LDNS_RD_WIRE(sldns_buffer_begin(pkt)); unsigned int cd = LDNS_CD_WIRE(sldns_buffer_begin(pkt)); + size_t udpsize = edns->udp_size; + edns->edns_version = EDNS_ADVERTISED_VERSION; + edns->udp_size = EDNS_ADVERTISED_SIZE; + edns->bits &= EDNS_DO; + if(!inplace_cb_reply_local_call(&worker->env, NULL, NULL, NULL, + LDNS_RCODE_NOERROR, edns, repinfo, worker->scratchpad, + worker->env.now_tv)) + edns->opt_list_inplace_cb_out = NULL; sldns_buffer_clear(pkt); sldns_buffer_skip(pkt, (ssize_t)sizeof(uint16_t)); /* skip id */ sldns_buffer_write_u16(pkt, (uint16_t)(BIT_QR|BIT_RA)); @@ -804,6 +804,12 @@ chaos_replystr(sldns_buffer* pkt, char** str, int num, struct edns_data* edns, for(i=0; i255) len=255; /* cap size of TXT record */ + if(sldns_buffer_position(pkt)+2+2+2+4+2+1+len+ + calc_edns_field_size(edns) > udpsize) { + sldns_buffer_write_u16_at(pkt, 6, i); /* ANCOUNT */ + LDNS_TC_SET(sldns_buffer_begin(pkt)); + break; + } sldns_buffer_write_u16(pkt, 0xc00c); /* compr ptr to query */ sldns_buffer_write_u16(pkt, LDNS_RR_TYPE_TXT); sldns_buffer_write_u16(pkt, LDNS_RR_CLASS_CH); @@ -813,13 +819,6 @@ chaos_replystr(sldns_buffer* pkt, char** str, int num, struct edns_data* edns, sldns_buffer_write(pkt, str[i], len); } sldns_buffer_flip(pkt); - edns->edns_version = EDNS_ADVERTISED_VERSION; - edns->udp_size = EDNS_ADVERTISED_SIZE; - edns->bits &= EDNS_DO; - if(!inplace_cb_reply_local_call(&worker->env, NULL, NULL, NULL, - LDNS_RCODE_NOERROR, edns, repinfo, worker->scratchpad, - worker->env.now_tv)) - edns->opt_list = NULL; if(sldns_buffer_capacity(pkt) >= sldns_buffer_limit(pkt)+calc_edns_field_size(edns)) attach_edns_record(pkt, edns); @@ -1004,7 +1003,6 @@ answer_notify(struct worker* w, struct query_info* qinfo, edns->udp_size = EDNS_ADVERTISED_SIZE; edns->ext_rcode = 0; edns->bits &= EDNS_DO; - edns->opt_list = NULL; error_encode(pkt, rcode, qinfo, *(uint16_t*)(void *)sldns_buffer_begin(pkt), sldns_buffer_read_u16_at(pkt, 2), edns); @@ -1241,7 +1239,8 @@ worker_handle_request(struct comm_point* c, void* arg, int error, } goto send_reply; } - if((ret=parse_edns_from_pkt(c->buffer, &edns, worker->scratchpad)) != 0) { + if((ret=parse_edns_from_query_pkt(c->buffer, &edns, worker->env.cfg, c, + worker->scratchpad)) != 0) { struct edns_data reply_edns; verbose(VERB_ALGO, "worker parse edns: formerror."); log_addr(VERB_CLIENT,"from",&repinfo->addr, repinfo->addrlen); @@ -1256,13 +1255,14 @@ worker_handle_request(struct comm_point* c, void* arg, int error, goto send_reply; } if(edns.edns_present) { - struct edns_option* edns_opt; if(edns.edns_version != 0) { edns.ext_rcode = (uint8_t)(EDNS_RCODE_BADVERS>>4); edns.edns_version = EDNS_ADVERTISED_VERSION; edns.udp_size = EDNS_ADVERTISED_SIZE; edns.bits &= EDNS_DO; - edns.opt_list = NULL; + edns.opt_list_in = NULL; + edns.opt_list_out = NULL; + edns.opt_list_inplace_cb_out = NULL; edns.padding_block_size = 0; verbose(VERB_ALGO, "query with bad edns version."); log_addr(VERB_CLIENT,"from",&repinfo->addr, repinfo->addrlen); @@ -1282,26 +1282,6 @@ worker_handle_request(struct comm_point* c, void* arg, int error, log_addr(VERB_CLIENT,"from",&repinfo->addr, repinfo->addrlen); edns.udp_size = NORMAL_UDP_SIZE; } - if(c->type != comm_udp) { - edns_opt = edns_opt_list_find(edns.opt_list, LDNS_EDNS_KEEPALIVE); - if(edns_opt && edns_opt->opt_len > 0) { - edns.ext_rcode = 0; - edns.edns_version = EDNS_ADVERTISED_VERSION; - edns.udp_size = EDNS_ADVERTISED_SIZE; - edns.bits &= EDNS_DO; - edns.opt_list = NULL; - verbose(VERB_ALGO, "query with bad edns keepalive."); - log_addr(VERB_CLIENT,"from",&repinfo->addr, repinfo->addrlen); - error_encode(c->buffer, LDNS_RCODE_FORMERR, &qinfo, - *(uint16_t*)(void *)sldns_buffer_begin(c->buffer), - sldns_buffer_read_u16_at(c->buffer, 2), NULL); - if(sldns_buffer_capacity(c->buffer) >= - sldns_buffer_limit(c->buffer)+calc_edns_field_size(&edns)) - attach_edns_record(c->buffer, &edns); - regional_free_all(worker->scratchpad); - goto send_reply; - } - } } if(edns.udp_size > worker->daemon->cfg->max_udp_size && c->type == comm_udp) { @@ -1355,7 +1335,7 @@ worker_handle_request(struct comm_point* c, void* arg, int error, goto send_reply; } if(worker->env.auth_zones && - rpz_apply_qname_trigger(worker->env.auth_zones, + rpz_callback_from_worker_request(worker->env.auth_zones, &worker->env, &qinfo, &edns, c->buffer, worker->scratchpad, repinfo, acladdr->taglist, acladdr->taglen, &worker->stats)) { regional_free_all(worker->scratchpad); @@ -1453,7 +1433,7 @@ worker_handle_request(struct comm_point* c, void* arg, int error, * this is a two-pass operation, and lookup_qinfo is different for * each pass. We should still pass the original qinfo to * answer_from_cache(), however, since it's used to build the reply. */ - if(!edns_bypass_cache_stage(edns.opt_list, &worker->env)) { + if(!edns_bypass_cache_stage(edns.opt_list_in, &worker->env)) { is_expired_answer = 0; is_secure_answer = 0; h = query_info_hash(lookup_qinfo, sldns_buffer_read_u16_at(c->buffer, 2)); @@ -1988,8 +1968,8 @@ worker_delete(struct worker* worker) struct outbound_entry* worker_send_query(struct query_info* qinfo, uint16_t flags, int dnssec, int want_dnssec, int nocaps, struct sockaddr_storage* addr, - socklen_t addrlen, uint8_t* zone, size_t zonelen, int ssl_upstream, - char* tls_auth_name, struct module_qstate* q) + socklen_t addrlen, uint8_t* zone, size_t zonelen, int tcp_upstream, + int ssl_upstream, char* tls_auth_name, struct module_qstate* q) { struct worker* worker = q->env->worker; struct outbound_entry* e = (struct outbound_entry*)regional_alloc( @@ -1998,7 +1978,7 @@ worker_send_query(struct query_info* qinfo, uint16_t flags, int dnssec, return NULL; e->qstate = q; e->qsent = outnet_serviced_query(worker->back, qinfo, flags, dnssec, - want_dnssec, nocaps, q->env->cfg->tcp_upstream, + want_dnssec, nocaps, tcp_upstream, ssl_upstream, tls_auth_name, addr, addrlen, zone, zonelen, q, worker_handle_service_reply, e, worker->back->udp_buff, q->env); if(!e->qsent) { @@ -2045,7 +2025,7 @@ struct outbound_entry* libworker_send_query( uint16_t ATTR_UNUSED(flags), int ATTR_UNUSED(dnssec), int ATTR_UNUSED(want_dnssec), int ATTR_UNUSED(nocaps), struct sockaddr_storage* ATTR_UNUSED(addr), socklen_t ATTR_UNUSED(addrlen), - uint8_t* ATTR_UNUSED(zone), size_t ATTR_UNUSED(zonelen), + uint8_t* ATTR_UNUSED(zone), size_t ATTR_UNUSED(zonelen), int ATTR_UNUSED(tcp_upstream), int ATTR_UNUSED(ssl_upstream), char* ATTR_UNUSED(tls_auth_name), struct module_qstate* ATTR_UNUSED(q)) { diff --git a/contrib/unbound/dns64/dns64.c b/contrib/unbound/dns64/dns64.c index c79bc9c65796..d01b436e1d6c 100644 --- a/contrib/unbound/dns64/dns64.c +++ b/contrib/unbound/dns64/dns64.c @@ -685,8 +685,12 @@ dns64_operate(struct module_qstate* qstate, enum module_ev event, int id, switch(event) { case module_event_new: /* Tag this query as being new and fall through. */ - iq = (struct dns64_qstate*)regional_alloc( - qstate->region, sizeof(*iq)); + if (!(iq = (struct dns64_qstate*)regional_alloc( + qstate->region, sizeof(*iq)))) { + log_err("out of memory"); + qstate->ext_state[id] = module_error; + return; + } qstate->minfo[id] = iq; iq->state = DNS64_NEW_QUERY; iq->started_no_cache_store = qstate->no_cache_store; @@ -913,8 +917,9 @@ dns64_adjust_ptr(struct module_qstate* qstate, struct module_qstate* super) sizeof(struct dns_msg)))) return; super->return_msg->qinfo = super->qinfo; - super->return_msg->rep = reply_info_copy(qstate->return_msg->rep, NULL, - super->region); + if (!(super->return_msg->rep = reply_info_copy(qstate->return_msg->rep, + NULL, super->region))) + return; /* * Adjust the domain name of the answer RR set so that it matches the diff --git a/contrib/unbound/dnscrypt/dnscrypt.c b/contrib/unbound/dnscrypt/dnscrypt.c index 9b324ae69052..4902447fda01 100644 --- a/contrib/unbound/dnscrypt/dnscrypt.c +++ b/contrib/unbound/dnscrypt/dnscrypt.c @@ -435,7 +435,7 @@ dnscrypt_hrtime(void) /** * Add the server nonce part to once. - * The nonce is made half of client nonce and the seconf half of the server + * The nonce is made half of client nonce and the second half of the server * nonce, both of them of size crypto_box_HALF_NONCEBYTES. * \param[in] nonce: a uint8_t* of size crypto_box_NONCEBYTES */ @@ -674,7 +674,7 @@ dnsc_find_cert(struct dnsc_env* dnscenv, struct sldns_buffer* buffer) /** * Insert local-zone and local-data into configuration. * In order to be able to serve certs over TXT, we can reuse the local-zone and - * local-data config option. The zone and qname are infered from the + * local-data config option. The zone and qname are inferred from the * provider_name and the content of the TXT record from the certificate content. * returns the number of certificate TXT record that were loaded. * < 0 in case of error. diff --git a/contrib/unbound/dnscrypt/dnscrypt.h b/contrib/unbound/dnscrypt/dnscrypt.h index 666f54e62aa4..b0da9b732681 100644 --- a/contrib/unbound/dnscrypt/dnscrypt.h +++ b/contrib/unbound/dnscrypt/dnscrypt.h @@ -114,7 +114,7 @@ void dnsc_delete(struct dnsc_env *env); /** * handle a crypted dnscrypt request. - * Determine wether or not a query is coming over the dnscrypt listener and + * Determine whether or not a query is coming over the dnscrypt listener and * attempt to uncurve it or detect if it is a certificate query. * return 0 in case of failure. */ @@ -122,7 +122,7 @@ int dnsc_handle_curved_request(struct dnsc_env* dnscenv, struct comm_reply* repinfo); /** * handle an unencrypted dnscrypt request. - * Determine wether or not a query is going over the dnscrypt channel and + * Determine whether or not a query is going over the dnscrypt channel and * attempt to curve it unless it was not crypted like when it is a * certificate query. * \return 0 in case of failure. diff --git a/contrib/unbound/dnstap/dtstream.c b/contrib/unbound/dnstap/dtstream.c index f1ace3c34023..14aacaef567b 100644 --- a/contrib/unbound/dnstap/dtstream.c +++ b/contrib/unbound/dnstap/dtstream.c @@ -251,7 +251,7 @@ dt_msg_queue_submit(struct dt_msg_queue* mq, void* buf, size_t len) entry->buf = buf; entry->len = len; - /* aqcuire lock */ + /* acquire lock */ lock_basic_lock(&mq->lock); /* if list was empty, start timer for (eventual) wakeup */ if(mq->first == NULL) @@ -930,7 +930,7 @@ static int dtio_write_more_of_data(struct dt_io_thread* dtio) return 1; } -/** write more of the current messsage. false if incomplete, true if +/** write more of the current message. false if incomplete, true if * the message is done */ static int dtio_write_more(struct dt_io_thread* dtio) { @@ -1181,7 +1181,7 @@ static int dtio_read_accept_frame(struct dt_io_thread* dtio) goto close_connection; return 1; } else { - /* unknow content type */ + /* unknown content type */ verbose(VERB_ALGO, "dnstap: ACCEPT frame " "contains unknown content type, " "closing connection"); diff --git a/contrib/unbound/dnstap/unbound-dnstap-socket.c b/contrib/unbound/dnstap/unbound-dnstap-socket.c index 3de8ab3f0899..990b8a866af1 100644 --- a/contrib/unbound/dnstap/unbound-dnstap-socket.c +++ b/contrib/unbound/dnstap/unbound-dnstap-socket.c @@ -1264,9 +1264,9 @@ int main(int argc, char** argv) memset(&tls_list, 0, sizeof(tls_list)); /* lock debug start (if any) */ + checklock_start(); log_ident_set("unbound-dnstap-socket"); log_init(0, 0, 0); - checklock_start(); #ifdef SIGPIPE if(signal(SIGPIPE, SIG_IGN) == SIG_ERR) { @@ -1415,8 +1415,9 @@ struct outbound_entry* worker_send_query( int ATTR_UNUSED(dnssec), int ATTR_UNUSED(want_dnssec), int ATTR_UNUSED(nocaps), struct sockaddr_storage* ATTR_UNUSED(addr), socklen_t ATTR_UNUSED(addrlen), uint8_t* ATTR_UNUSED(zone), - size_t ATTR_UNUSED(zonelen), int ATTR_UNUSED(ssl_upstream), - char* ATTR_UNUSED(tls_auth_name), struct module_qstate* ATTR_UNUSED(q)) + size_t ATTR_UNUSED(zonelen), int ATTR_UNUSED(tcp_upstream), + int ATTR_UNUSED(ssl_upstream), char* ATTR_UNUSED(tls_auth_name), + struct module_qstate* ATTR_UNUSED(q)) { log_assert(0); return 0; @@ -1447,8 +1448,9 @@ struct outbound_entry* libworker_send_query( int ATTR_UNUSED(dnssec), int ATTR_UNUSED(want_dnssec), int ATTR_UNUSED(nocaps), struct sockaddr_storage* ATTR_UNUSED(addr), socklen_t ATTR_UNUSED(addrlen), uint8_t* ATTR_UNUSED(zone), - size_t ATTR_UNUSED(zonelen), int ATTR_UNUSED(ssl_upstream), - char* ATTR_UNUSED(tls_auth_name), struct module_qstate* ATTR_UNUSED(q)) + size_t ATTR_UNUSED(zonelen), int ATTR_UNUSED(tcp_upstream), + int ATTR_UNUSED(ssl_upstream), char* ATTR_UNUSED(tls_auth_name), + struct module_qstate* ATTR_UNUSED(q)) { log_assert(0); return 0; diff --git a/contrib/unbound/doc/Changelog b/contrib/unbound/doc/Changelog index 91abd0da0258..8aec7694f42d 100644 --- a/contrib/unbound/doc/Changelog +++ b/contrib/unbound/doc/Changelog @@ -1,3 +1,167 @@ +1 December 2021: Wouter + - configure is set to 1.14.0, and release branch. + - Fix doc/unbound.doxygen to remove obsolete tag warning. + +1 December 2021: George + - Merge PR #511 from yan12125: Reduce unnecessary linking. + - Merge PR #493 from Jaap: Fix generation of libunbound.pc. + - Merge PR #555 from fobser: Allow interface names as scope-id in IPv6 + link-local addresses. + - Merge PR #562 from Willem: Reset keepalive per new tcp session. + - Merge PR #522 from sibeream: memory management violations fixed. + - Merge PR #530 from Shchelk: Fix: dereferencing a null pointer. + - Fix #454: listen_dnsport.c:825: error: ‘IPV6_TCLASS’ undeclared. + - Fix #574: Review fixes for size allocation. + +30 November 2021: Wouter + - Fix to remove git tracking and ci information from release tarballs. + - iana portlist update. + +29 November 2021: Wouter + - Merge PR #570 from rex4539: Fix typos. + - Fix for #570: regen aclocal.m4, fix configure.ac for spelling. + - Fix to make python module opt_list use opt_list_in. + - Fix #574: unbound-checkconf reports fatal error if interface names + are used as value for interfaces: + - Fix #574: Review fixes for it. + - Fix #576: [FR] UB_* error codes in unbound.h + - Fix #574: Review fix for spelling. + +15 November 2021: Tom + - Improve EDNS option handling, now also works for synthesised + responses such as local-data and server.id CH TXT responses. + +5 November 2021: George + - Fix for #558: fix loop in comm_point->tcp_free when a comm_point is + reclaimed more than once during callbacks. + - Fix for #558: clear the UB_EV_TIMEOUT bit before adding an event. + +5 November 2021: Wouter + - Fix that forward-zone name is documented as the full name of the + zone. It is not relative but a fully qualified domain name. + - Fix analyzer review failure in rpz action override code to not + crash on unlocking the local zone lock. + - Fix to remove unused code from rpz resolve client and action + function. + - Merge #565: unbound.service.in: Disable ProtectKernelTunables again. + +2 November 2021: Wouter + - Fix #552: Unbound assumes index.html exists on RPZ host. + +11 October 2021: Wouter + - Fix chaos replies to have truncation for short message lengths, + or long reply strings. + - Fix to protect custom regional create against small values. + +4 October 2021: Wouter + - Fix to add example.conf note for outbound-msg-retry. + +27 September 2021: Wouter + - Implement RFC8375: Special-Use Domain 'home.arpa.'. + +21 September 2021: Wouter + - For crosscompile on windows, detect 64bit stackprotector library. + - Fix crosscompile shell syntax. + - Fix crosscompile windows to use libssp when it exists. + - For the windows compile script disable gost. + - Fix that on windows, use BIO_set_callback_ex instead of deprecated + BIO_set_callback. + - Fix crosscompile script for the shared build flags. + +20 September 2021: Wouter + - Fix crosscompile on windows to work with openssl 3.0.0 the + link with ws2_32 needs -l:libssp.a for __strcpy_chk. + Also copy results from lib64 directory if needed. + +10 September 2021: Wouter + - Fix initialisation errors reported by gcc sanitizer. + - Fix lock debug code for gcc sanitizer reports. + - Fix more initialisation errors reported by gcc sanitizer. + +8 September 2021: Wouter + - Merged #41 from Moritz Schneider: made outbound-msg-retry + configurable. + - Small fixes for #41: changelog, conflicts resolved, + processQueryResponse takes an iterator env argument like other + functions in the iterator, no colon in string for set_option, + and some whitespace style, to make it similar to the rest. + - Fix for #41: change outbound retry to int to fix signed comparison + warnings. + - Fix root_anchor test to check with new icannbundle date. + +3 September 2021: Wouter + - Fix #538: Fix subnetcache statistics. + +1 September 2021: Wouter + - Fix tcp fastopen failure when disabled, try normal connect instead. + +27 August 2021: Wouter + - Fix #533: Negative responses get cached even when setting + cache-max-negative-ttl: 1 + +25 August 2021: Wouter + - Merge #401: RPZ triggers. This add additional RPZ triggers, + unbound supports a full set of rpz triggers, and this now + includes nsdname, nsip and clientip triggers. Also actions + are fully supported, and this now includes the tcp-only action. + - Fix #536: error: RPZ: name of record (drop.spamhaus.org.rpz.local.) + to insert into RPZ. + - Fix the stream wait stream_wait_count_lock and http2 buffer locks + setup and desetup from race condition. + - Fix RPZ locks. Do not unlock zones lock if requested and rpz find + zone does not find the zone. Readlock the clientip that is found + for ipbased triggers. Unlock the nsdname zone lock when done. + Unlock zone and ip in rpz nsip and nsdname callback. Unlock + authzone and localzone if clientip found in rpz worker call. + - Fix compile warning in libunbound for listen desetup routine. + - Fix asynclook unit test for setup of lockchecks before log. + +20 August 2021: Wouter + - Fix #529: Fix: log_assert does nothing if UNBOUND_DEBUG is + undefined. + - Fix #531: Fix: passed to proc after free. + +17 August 2021: Wouter + - Fix that --with-ssl can use "/usr/include/openssl11" to pass the + location of a different openssl version. + - Fix #527: not sending quad9 cert to syslog (and may be more). + - Fix sed script in ssldir split handling. + +16 August 2021: George + - Merge PR #528 from fobser: Make sldns_str2wire_svcparam_buf() + static. + +16 August 2021: Wouter + - Fix to support harden-algo-downgrade for ZONEMD dnssec checks. + +13 August 2021: Wouter + - Support using system-wide crypto policies. + - Fix for #431: Squelch permission denied errors for udp connect, + and udp send, they are visible at higher verbosity settings. + - Fix zonemd verification of key that is not in DNS but in the zone + and needs a chain of trust. + - zonemd, fix order of bogus printout string manipulation. + +12 August 2021: George + - Merge PR #514, from ziollek: Docker environment for run tests. + - For #514: generate configure. + +12 August 2021: Wouter + - And 1.13.2rc1 became the 1.13.2 with the fix for the python module + build. The current code repository continues with version 1.13.3. + - Add test tool readzone to .gitignore. + - Merge #521: Update mini_event.c. + - Merge #523: fix: free() call more than once with the same pointer. + - Merge #519: Support for selective enabling tcp-upstream for + stub/forward zones. + - For #519: note stub-tcp-upstream and forward-tcp-upstream in + the example configuration file. + - For #519: yacc and lex. And fix python bindings, and test program + unbound-dnstap-socket. + - For #519: fix comments for doxygen. + - Fix to print error from unbound-anchor for writing to the key + file, also when not verbose. + 5 August 2021: Wouter - Tag for 1.13.2rc1 release. - Fix #520: Unbound 1.13.2rc1 fails to build python module. diff --git a/contrib/unbound/doc/README b/contrib/unbound/doc/README index a051380e1d7b..ea18f4fe5c05 100644 --- a/contrib/unbound/doc/README +++ b/contrib/unbound/doc/README @@ -1,4 +1,4 @@ -README for Unbound 1.13.2 +README for Unbound 1.14.0rc1 Copyright 2007 NLnet Labs http://unbound.net diff --git a/contrib/unbound/doc/README.tests b/contrib/unbound/doc/README.tests index 5385e2b2221f..376f01717fdd 100644 --- a/contrib/unbound/doc/README.tests +++ b/contrib/unbound/doc/README.tests @@ -15,6 +15,14 @@ You need to have the following programs installed and in your PATH. * xxd and nc (optional) - for (malformed) packet transmission. The optional programs are detected and can be omitted. +You can also use prepared Dockerfile to run tests inside docker based on latest gcc image: +* build container: docker build -t unbound-tester -f contrib/Dockerfile.tests . +* run container: docker run -it --mount type=bind,source="$(pwd)",target=/usr/src/unbound --rm unbound-tester +* configure environment: ./configure +* run test: make test +* run long tests: make longtest +It is worth to mention that you need to enable [ipv6 in your docker daemon configuration](https://docs.docker.com/config/daemon/ipv6/) because some tests need ipv6 network stack. + testdata/ contains the data for tests. testcode/ contains scripts and c code for the tests. diff --git a/contrib/unbound/doc/example.conf.in b/contrib/unbound/doc/example.conf.in index a0c002d2c386..2dfd770fd4c5 100644 --- a/contrib/unbound/doc/example.conf.in +++ b/contrib/unbound/doc/example.conf.in @@ -1,7 +1,7 @@ # # Example configuration file. # -# See unbound.conf(5) man page, version 1.13.2. +# See unbound.conf(5) man page, version 1.14.0rc1. # # this is a comment. @@ -164,6 +164,9 @@ server: # perform connect for UDP sockets to mitigate ICMP side channel. # udp-connect: yes + # The number of retries when a non-positive response is received. + # outbound-msg-retry: 5 + # msec for waiting for an unknown server to reply. Increase if you # are behind a slow satellite link, to eg. 1128. # unknown-server-time-limit: 376 @@ -666,6 +669,7 @@ server: # local-zone: "localhost." 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: "home.arpa." nodefault # local-zone: "onion." nodefault # local-zone: "test." nodefault # local-zone: "invalid." nodefault @@ -987,6 +991,7 @@ remote-control: # stub-addr: 192.0.2.68 # stub-prime: no # stub-first: no +# stub-tcp-upstream: no # stub-tls-upstream: no # stub-no-cache: no # stub-zone: @@ -1004,6 +1009,7 @@ remote-control: # forward-addr: 192.0.2.68 # forward-addr: 192.0.2.73@5355 # forward to port 5355. # forward-first: no +# forward-tcp-upstream: no # forward-tls-upstream: no # forward-no-cache: no # forward-zone: @@ -1150,10 +1156,11 @@ remote-control: # dnstap-log-forwarder-response-messages: no # Response Policy Zones -# RPZ policies. Applied in order of configuration. QNAME and Response IP -# Address trigger are the only supported triggers. Supported actions are: -# NXDOMAIN, NODATA, PASSTHRU, DROP and Local Data. Policies can be loaded from -# file, using zone transfer, or using HTTP. The respip module needs to be added +# RPZ policies. Applied in order of configuration. QNAME, Response IP +# Address, nsdname, nsip and clientip triggers are supported. Supported +# actions are: NXDOMAIN, NODATA, PASSTHRU, DROP, Local Data, tcp-only +# and drop. Policies can be loaded from a file, or using zone +# transfer, or using HTTP. The respip module needs to be added # to the module-config, e.g.: module-config: "respip validator iterator". # rpz: # name: "rpz.example.com" diff --git a/contrib/unbound/doc/libunbound.3.in b/contrib/unbound/doc/libunbound.3.in index 73562cd6b41f..a35b41bf0525 100644 --- a/contrib/unbound/doc/libunbound.3.in +++ b/contrib/unbound/doc/libunbound.3.in @@ -1,4 +1,4 @@ -.TH "libunbound" "3" "Aug 12, 2021" "NLnet Labs" "unbound 1.13.2" +.TH "libunbound" "3" "Dec 2, 2021" "NLnet Labs" "unbound 1.14.0rc1" .\" .\" libunbound.3 -- unbound library functions manual .\" @@ -44,7 +44,7 @@ .B ub_ctx_zone_remove, .B ub_ctx_data_add, .B ub_ctx_data_remove -\- Unbound DNS validating resolver 1.13.2 functions. +\- Unbound DNS validating resolver 1.14.0rc1 functions. .SH "SYNOPSIS" .B #include .LP diff --git a/contrib/unbound/doc/unbound-anchor.8.in b/contrib/unbound/doc/unbound-anchor.8.in index 25f7f1baf147..84d6f348c484 100644 --- a/contrib/unbound/doc/unbound-anchor.8.in +++ b/contrib/unbound/doc/unbound-anchor.8.in @@ -1,4 +1,4 @@ -.TH "unbound-anchor" "8" "Aug 12, 2021" "NLnet Labs" "unbound 1.13.2" +.TH "unbound-anchor" "8" "Dec 2, 2021" "NLnet Labs" "unbound 1.14.0rc1" .\" .\" unbound-anchor.8 -- unbound anchor maintenance utility manual .\" diff --git a/contrib/unbound/doc/unbound-checkconf.8.in b/contrib/unbound/doc/unbound-checkconf.8.in index e9b8ba2d60c0..2453a1984532 100644 --- a/contrib/unbound/doc/unbound-checkconf.8.in +++ b/contrib/unbound/doc/unbound-checkconf.8.in @@ -1,4 +1,4 @@ -.TH "unbound-checkconf" "8" "Aug 12, 2021" "NLnet Labs" "unbound 1.13.2" +.TH "unbound-checkconf" "8" "Dec 2, 2021" "NLnet Labs" "unbound 1.14.0rc1" .\" .\" unbound-checkconf.8 -- unbound configuration checker manual .\" diff --git a/contrib/unbound/doc/unbound-control.8.in b/contrib/unbound/doc/unbound-control.8.in index fb3510fa3cb5..d268b0b94b7e 100644 --- a/contrib/unbound/doc/unbound-control.8.in +++ b/contrib/unbound/doc/unbound-control.8.in @@ -1,4 +1,4 @@ -.TH "unbound-control" "8" "Aug 12, 2021" "NLnet Labs" "unbound 1.13.2" +.TH "unbound-control" "8" "Dec 2, 2021" "NLnet Labs" "unbound 1.14.0rc1" .\" .\" unbound-control.8 -- unbound remote control manual .\" @@ -684,8 +684,8 @@ specific cache, after getting processed by the edns client subnet module. .TP .I num.rpz.action. Number of queries answered using configured RPZ policy, per RPZ action type. -Possible actions are: nxdomain, nodata, passthru, drop, local_data, disabled, -and cname_override. +Possible actions are: nxdomain, nodata, passthru, drop, tcp\-only, local\-data, +disabled, and cname\-override. .SH "FILES" .TP .I @ub_conf_file@ diff --git a/contrib/unbound/doc/unbound-host.1.in b/contrib/unbound/doc/unbound-host.1.in index 4823b9afcaf5..85863835b505 100644 --- a/contrib/unbound/doc/unbound-host.1.in +++ b/contrib/unbound/doc/unbound-host.1.in @@ -1,4 +1,4 @@ -.TH "unbound\-host" "1" "Aug 12, 2021" "NLnet Labs" "unbound 1.13.2" +.TH "unbound\-host" "1" "Dec 2, 2021" "NLnet Labs" "unbound 1.14.0rc1" .\" .\" unbound-host.1 -- unbound DNS lookup utility .\" diff --git a/contrib/unbound/doc/unbound.8.in b/contrib/unbound/doc/unbound.8.in index 82c4e98eb191..6f956b6a184d 100644 --- a/contrib/unbound/doc/unbound.8.in +++ b/contrib/unbound/doc/unbound.8.in @@ -1,4 +1,4 @@ -.TH "unbound" "8" "Aug 12, 2021" "NLnet Labs" "unbound 1.13.2" +.TH "unbound" "8" "Dec 2, 2021" "NLnet Labs" "unbound 1.14.0rc1" .\" .\" unbound.8 -- unbound manual .\" @@ -9,7 +9,7 @@ .\" .SH "NAME" .B unbound -\- Unbound DNS validating resolver 1.13.2. +\- Unbound DNS validating resolver 1.14.0rc1. .SH "SYNOPSIS" .B unbound .RB [ \-h ] diff --git a/contrib/unbound/doc/unbound.conf.5.in b/contrib/unbound/doc/unbound.conf.5.in index e44560ec9eb6..baf024b70960 100644 --- a/contrib/unbound/doc/unbound.conf.5.in +++ b/contrib/unbound/doc/unbound.conf.5.in @@ -1,4 +1,4 @@ -.TH "unbound.conf" "5" "Aug 12, 2021" "NLnet Labs" "unbound 1.13.2" +.TH "unbound.conf" "5" "Dec 2, 2021" "NLnet Labs" "unbound 1.14.0rc1" .\" .\" unbound.conf.5 -- unbound.conf manual .\" @@ -485,7 +485,9 @@ advertised timeout. .TP .B tcp\-upstream: \fI Enable or disable whether the upstream queries use TCP only for transport. -Default is no. Useful in tunneling scenarios. +Default is no. Useful in tunneling scenarios. If set to no you can specify +TCP transport only for selected forward or stub zones using forward-tcp-upstream +or stub-tcp-upstream respectively. .TP .B udp\-upstream\-without\-downstream: \fI Enable udp upstream even if do-udp is no. Default is no, and this does not @@ -1410,13 +1412,13 @@ has no other effect than turning off default contents for the given zone. Use \fInodefault\fR if you use exactly that zone, if you want to use a subzone, use \fItransparent\fR. .P -The default zones are localhost, reverse 127.0.0.1 and ::1, the onion, test, -invalid and the AS112 zones. The AS112 zones are reverse DNS zones for -private use and reserved IP addresses for which the servers on the internet -cannot provide correct answers. They are configured by default to give -nxdomain (no reverse information) answers. The defaults can be turned off -by specifying your own local\-zone of that name, or using the 'nodefault' -type. Below is a list of the default zone contents. +The default zones are localhost, reverse 127.0.0.1 and ::1, the home.arpa, +the onion, test, invalid and the AS112 zones. The AS112 zones are reverse +DNS zones for private use and reserved IP addresses for which the servers +on the internet cannot provide correct answers. They are configured by +default to give nxdomain (no reverse information) answers. The defaults +can be turned off by specifying your own local\-zone of that name, or +using the 'nodefault' type. Below is a list of the default zone contents. .TP 10 \h'5'\fIlocalhost\fR The IP4 and IP6 localhost information is given. NS and SOA records are provided @@ -1457,6 +1459,15 @@ local\-data: "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0. PTR localhost." .fi .TP 10 +\h'5'\fIhome.arpa (RFC 8375)\fR +Default content: +.nf +local\-zone: "home.arpa." static +local\-data: "home.arpa. 10800 IN NS localhost." +local\-data: "home.arpa. 10800 IN + SOA localhost. nobody.invalid. 1 3600 1200 604800 10800" +.fi +.TP 10 \h'5'\fIonion (RFC 7686)\fR Default content: .nf @@ -1702,6 +1713,11 @@ This can make ordinary queries complete (if repeatedly queried for), and enter the cache, whilst also mitigating the traffic flow by the factor given. .TP 5 +.B outbound\-msg\-retry: \fI +The number of retries unbound will do in case of a non positive response is +received. If a forward nameserver is used, this is the number of retries per +forward nameserver in case of throwaway response. +.TP 5 .B fast\-server\-permil: \fI Specify how many times out of 1000 to pick from the set of fastest servers. 0 turns the feature off. A value of 900 would pick from the fastest @@ -1822,7 +1838,7 @@ zone. The local zone nodefault (or \fItransparent\fR) clause makes the (reverse\-) zone bypass unbound's filtering of RFC1918 zones. .TP .B name: \fI -Name of the stub zone. +Name of the stub zone. This is the full domain name of the zone. .TP .B stub\-host: \fI Name of stub zone nameserver. Is itself resolved before it is used. @@ -1853,6 +1869,10 @@ Default is no. .B stub\-ssl\-upstream: \fI Alternate syntax for \fBstub\-tls\-upstream\fR. .TP +.B stub\-tcp\-upstream: \fI +If it is set to "yes" then upstream queries use TCP only for transport regardless of global flag tcp-upstream. +Default is no. +.TP .B stub\-no\-cache: \fI Default is no. If enabled, data inside the stub is not cached. This is useful when you want immediate changes to be visible. @@ -1875,7 +1895,7 @@ forward all queries to that other server (unless it can answer from the cache). .TP .B name: \fI -Name of the forward zone. +Name of the forward zone. This is the full domain name of the zone. .TP .B forward\-host: \fI Name of server to forward to. Is itself resolved before it is used. @@ -1905,6 +1925,10 @@ load CA certs, otherwise the connections cannot be authenticated. .B forward\-ssl\-upstream: \fI Alternate syntax for \fBforward\-tls\-upstream\fR. .TP +.B forward\-tcp\-upstream: \fI +If it is set to "yes" then upstream queries use TCP only for transport regardless of global flag tcp-upstream. +Default is no. +.TP .B forward\-no\-cache: \fI Default is no. If enabled, data inside the forward is not cached. This is useful when you want immediate changes to be visible. @@ -2391,7 +2415,7 @@ This option defaults to "default". .P The following .B cachedb -otions are specific to the redis backend. +options are specific to the redis backend. .TP .B redis-server-host: \fI\fR The IP (either v6 or v4) address or domain name of the Redis server. @@ -2506,10 +2530,49 @@ with a different name. RPZ clauses are applied in order of configuration. The \fBrespip\fR module needs to be added to the \fBmodule-config\fR, e.g.: \fBmodule-config: "respip validator iterator"\fR. .P -Only the QNAME and Response IP Address triggers are supported. The supported RPZ -actions are: NXDOMAIN, NODATA, PASSTHRU, DROP and Local Data. RPZ QNAME triggers -are applied after -\fBlocal-zones\fR and before \fBauth-zones\fR. +QNAME, Response IP Address, nsdname, nsip and clientip triggers are supported. +Supported actions are: NXDOMAIN, NODATA, PASSTHRU, DROP, Local Data, tcp\-only +and drop. RPZ QNAME triggers are applied after \fBlocal\-zones\fR and +before \fBauth\-zones\fR. +.P +The rpz zone is formatted with a SOA start record as usual. The items in +the zone are entries, that specify what to act on (the trigger) and what to +do (the action). The trigger to act on is recorded in the name, the action +to do is recorded as the resource record. The names all end in the zone +name, so you could type the trigger names without a trailing dot in the +zonefile. +.P +An example RPZ record, that answers example.com with NXDOMAIN +.nf + example.com CNAME . +.fi +.P +The triggers are encoded in the name on the left +.nf + name query name + netblock.rpz-client-ip client IP address + netblock.rpz-ip response IP address in the answer + name.rpz-nsdname nameserver name + netblock.rpz-nsip nameserver IP address +.fi +The netblock is written as .. +For IPv6 use 'zz' for '::'. Specify individual addresses with scope length +of 32 or 128. For example, 24.10.100.51.198.rpz-ip is 198.51.100.10/24 and +32.10.zz.db8.2001.rpz-ip is 2001:db8:0:0:0:0:0:10/32. +.P +The actions are specified with the record on the right +.nf + CNAME . nxdomain reply + CNAME *. nodata reply + CNAME rpz-passthru. do nothing, allow to continue + CNAME rpz-drop. the query is dropped + CNAME rpz-tcp-only. answer over TCP + A 192.0.2.1 answer with this IP address +.fi +Other records like AAAA, TXT and other CNAMEs (not rpz-..) can also be used to +answer queries with that content. +.P +The RPZ zones can be configured in the config file with these settings in the \fBrpz:\fR block. .TP .B name: \fI Name of the authority zone. diff --git a/contrib/unbound/doc/unbound.doxygen b/contrib/unbound/doc/unbound.doxygen index 823e092536e4..7222dbc274e9 100644 --- a/contrib/unbound/doc/unbound.doxygen +++ b/contrib/unbound/doc/unbound.doxygen @@ -279,10 +279,10 @@ TYPEDEF_HIDES_STRUCT = NO # For small to medium size projects (<1000 input files) the default value is # probably good enough. For larger projects a too small cache size can cause # doxygen to be busy swapping symbols to and from disk most of the time -# causing a significant performance penality. +# causing a significant performance penalty. # If the system has enough physical memory increasing the cache will improve the # performance by keeping more symbols in memory. Note that the value works on -# a logarithmic scale so increasing the size by one will rougly double the +# a logarithmic scale so increasing the size by one will roughly double the # memory usage. The cache size is given by this formula: # 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, # corresponding to a cache size of 2^16 = 65536 symbols @@ -779,7 +779,7 @@ ALPHABETICAL_INDEX = YES # the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns # in which this list will be split (can be a number in the range [1..20]) -COLS_IN_ALPHA_INDEX = 5 +#COLS_IN_ALPHA_INDEX = 5 # In case all classes in a project start with a common prefix, all # classes will be put under the same header in the alphabetical index. diff --git a/contrib/unbound/edns-subnet/edns-subnet.h b/contrib/unbound/edns-subnet/edns-subnet.h index 4b306080ad6d..6ab541de9487 100644 --- a/contrib/unbound/edns-subnet/edns-subnet.h +++ b/contrib/unbound/edns-subnet/edns-subnet.h @@ -59,7 +59,7 @@ struct ecs_data { /** * copy the first n BITS from src to dst iff both src and dst - * are large enough, return 0 on succes + * are large enough, return 0 on success */ int copy_clear(uint8_t* dst, size_t dstlen, uint8_t* src, size_t srclen, size_t n); diff --git a/contrib/unbound/edns-subnet/subnetmod.c b/contrib/unbound/edns-subnet/subnetmod.c index ade40c66e85f..81f0bf3ade55 100644 --- a/contrib/unbound/edns-subnet/subnetmod.c +++ b/contrib/unbound/edns-subnet/subnetmod.c @@ -497,7 +497,7 @@ eval_response(struct module_qstate *qstate, int id, struct subnet_qstate *sq) if (!s_in->subnet_validdata) { /* The authority indicated no support for edns subnet. As a * consequence the answer ended up in the regular cache. It - * is still usefull 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. */ verbose(VERB_QUERY, "subnetcache: Authority indicates no support"); if(!sq->started_no_cache_store) { diff --git a/contrib/unbound/ipsecmod/ipsecmod.c b/contrib/unbound/ipsecmod/ipsecmod.c index e42af6f497ea..577f7112e194 100644 --- a/contrib/unbound/ipsecmod/ipsecmod.c +++ b/contrib/unbound/ipsecmod/ipsecmod.c @@ -37,7 +37,7 @@ * \file * * This file contains a module that facilitates opportunistic IPsec. It does so - * by also quering for the IPSECKEY for A/AAAA queries and calling a + * by also querying for the IPSECKEY for A/AAAA queries and calling a * configurable hook (eg. signaling an IKE daemon) before replying. */ diff --git a/contrib/unbound/ipsecmod/ipsecmod.h b/contrib/unbound/ipsecmod/ipsecmod.h index e00816d4bf99..272f473c2eac 100644 --- a/contrib/unbound/ipsecmod/ipsecmod.h +++ b/contrib/unbound/ipsecmod/ipsecmod.h @@ -37,7 +37,7 @@ * \file * * This file contains a module that facilitates opportunistic IPsec. It does so - * by also quering for the IPSECKEY for A/AAAA queries and calling a + * by also querying for the IPSECKEY for A/AAAA queries and calling a * configurable hook (eg. signaling an IKE daemon) before replying. */ diff --git a/contrib/unbound/iterator/iter_delegpt.c b/contrib/unbound/iterator/iter_delegpt.c index 9a672b0af39d..bdac42b0ddb3 100644 --- a/contrib/unbound/iterator/iter_delegpt.c +++ b/contrib/unbound/iterator/iter_delegpt.c @@ -73,6 +73,7 @@ struct delegpt* delegpt_copy(struct delegpt* dp, struct regional* region) copy->bogus = dp->bogus; copy->has_parent_side_NS = dp->has_parent_side_NS; copy->ssl_upstream = dp->ssl_upstream; + copy->tcp_upstream = dp->tcp_upstream; for(ns = dp->nslist; ns; ns = ns->next) { if(!delegpt_add_ns(copy, region, ns->name, ns->lame)) return NULL; diff --git a/contrib/unbound/iterator/iter_delegpt.h b/contrib/unbound/iterator/iter_delegpt.h index 138eb6e1b60a..9c8cfb281bae 100644 --- a/contrib/unbound/iterator/iter_delegpt.h +++ b/contrib/unbound/iterator/iter_delegpt.h @@ -83,6 +83,8 @@ struct delegpt { uint8_t dp_type_mlc; /** use SSL for upstream query */ uint8_t ssl_upstream; + /** use TCP for upstream query */ + uint8_t tcp_upstream; /** delegpt from authoritative zone that is locally hosted */ uint8_t auth_dp; /*** no cache */ diff --git a/contrib/unbound/iterator/iter_fwd.c b/contrib/unbound/iterator/iter_fwd.c index ea3d70e07320..128007a0412c 100644 --- a/contrib/unbound/iterator/iter_fwd.c +++ b/contrib/unbound/iterator/iter_fwd.c @@ -276,6 +276,8 @@ read_forwards(struct iter_forwards* fwd, struct config_file* cfg) dp->no_cache = s->no_cache; /* use SSL for queries to this forwarder */ dp->ssl_upstream = (uint8_t)s->ssl_upstream; + /* use TCP for queries to this forwarder */ + dp->tcp_upstream = (uint8_t)s->tcp_upstream; verbose(VERB_QUERY, "Forward zone server list:"); delegpt_log(VERB_QUERY, dp); if(!forwards_insert(fwd, LDNS_RR_CLASS_IN, dp)) diff --git a/contrib/unbound/iterator/iter_hints.c b/contrib/unbound/iterator/iter_hints.c index 60e518122ed1..5819cfb1703d 100644 --- a/contrib/unbound/iterator/iter_hints.c +++ b/contrib/unbound/iterator/iter_hints.c @@ -287,6 +287,8 @@ read_stubs(struct iter_hints* hints, struct config_file* cfg) dp->no_cache = s->no_cache; /* ssl_upstream */ dp->ssl_upstream = (uint8_t)s->ssl_upstream; + /* tcp_upstream */ + dp->tcp_upstream = (uint8_t)s->tcp_upstream; delegpt_log(VERB_QUERY, dp); if(!hints_insert(hints, LDNS_RR_CLASS_IN, dp, !s->isprime)) return 0; @@ -395,10 +397,10 @@ read_root_hints(struct iter_hints* hints, char* fname) delegpt_free_mlc(dp); return 1; } + delegpt_log(VERB_QUERY, dp); if(!hints_insert(hints, c, dp, 0)) { return 0; } - delegpt_log(VERB_QUERY, dp); return 1; stop_read: diff --git a/contrib/unbound/iterator/iter_utils.c b/contrib/unbound/iterator/iter_utils.c index 668f898eb0ff..2482a1f40f03 100644 --- a/contrib/unbound/iterator/iter_utils.c +++ b/contrib/unbound/iterator/iter_utils.c @@ -4,22 +4,22 @@ * Copyright (c) 2007, NLnet Labs. All rights reserved. * * This software is open source. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. - * + * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. - * + * * Neither the name of the NLNET LABS nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -37,7 +37,7 @@ * \file * * This file contains functions to assist the iterator module. - * Configuration options. Forward zones. + * Configuration options. Forward zones. */ #include "config.h" #include "iterator/iter_utils.h" @@ -141,7 +141,7 @@ caps_white_apply_cfg(rbtree_type* ntree, struct config_file* cfg) return 1; } -int +int iter_apply_cfg(struct iter_env* iter_env, struct config_file* cfg) { int i; @@ -151,7 +151,7 @@ iter_apply_cfg(struct iter_env* iter_env, struct config_file* cfg) for(i=0; imax_dependency_depth+1; i++) verbose(VERB_QUERY, "target fetch policy for level %d is %d", i, iter_env->target_fetch_policy[i]); - + if(!iter_env->donotq) iter_env->donotq = donotq_create(); if(!iter_env->donotq || !donotq_apply_cfg(iter_env->donotq, cfg)) { @@ -176,6 +176,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; return 1; } @@ -212,7 +213,7 @@ iter_apply_cfg(struct iter_env* iter_env, struct config_file* cfg) * dnsseclame servers get penalty * USEFUL_SERVER_TOP_TIMEOUT*3 .. * recursion lame servers get penalty - * UNKNOWN_SERVER_NICENESS + * UNKNOWN_SERVER_NICENESS * If no information is known about the server, this is * returned. 376 msec or so. * +BLACKLIST_PENALTY (of USEFUL_TOP_TIMEOUT*4) for dnssec failed IPs. @@ -221,11 +222,11 @@ iter_apply_cfg(struct iter_env* iter_env, struct config_file* cfg) * is turned off (so we do not discard the reply). * When a final value is chosen that is recursionlame; RD bit is set on query. * Because of the numbers this means recursionlame also have dnssec lameness - * checking turned off. + * checking turned off. */ static int iter_filter_unsuitable(struct iter_env* iter_env, struct module_env* env, - uint8_t* name, size_t namelen, uint16_t qtype, time_t now, + uint8_t* name, size_t namelen, uint16_t qtype, time_t now, struct delegpt_addr* a) { int rtt, lame, reclame, dnsseclame; @@ -243,8 +244,8 @@ iter_filter_unsuitable(struct iter_env* iter_env, struct module_env* env, return -1; /* there is no ip4 available */ } /* check lameness - need zone , class info */ - if(infra_get_lame_rtt(env->infra_cache, &a->addr, a->addrlen, - name, namelen, qtype, &lame, &dnsseclame, &reclame, + if(infra_get_lame_rtt(env->infra_cache, &a->addr, a->addrlen, + name, namelen, qtype, &lame, &dnsseclame, &reclame, &rtt, now)) { log_addr(VERB_ALGO, "servselect", &a->addr, a->addrlen); verbose(VERB_ALGO, " rtt=%d%s%s%s%s", rtt, @@ -282,7 +283,7 @@ iter_filter_unsuitable(struct iter_env* iter_env, struct module_env* env, /** lookup RTT information, and also store fastest rtt (if any) */ static int iter_fill_rtt(struct iter_env* iter_env, struct module_env* env, - uint8_t* name, size_t namelen, uint16_t qtype, time_t now, + uint8_t* name, size_t namelen, uint16_t qtype, time_t now, struct delegpt* dp, int* best_rtt, struct sock_list* blacklist, size_t* num_suitable_results) { @@ -293,7 +294,7 @@ iter_fill_rtt(struct iter_env* iter_env, struct module_env* env, if(dp->bogus) return 0; /* NS bogus, all bogus, nothing found */ for(a=dp->result_list; a; a = a->next_result) { - a->sel_rtt = iter_filter_unsuitable(iter_env, env, + a->sel_rtt = iter_filter_unsuitable(iter_env, env, name, namelen, qtype, now, a); if(a->sel_rtt != -1) { if(sock_list_find(blacklist, &a->addr, a->addrlen)) @@ -329,7 +330,7 @@ nth_rtt(struct delegpt_addr* result_list, size_t num_results, size_t n) int rtt_band; size_t i; int* rtt_list, *rtt_index; - + if(num_results < 1 || n >= num_results) { return -1; } @@ -361,8 +362,8 @@ nth_rtt(struct delegpt_addr* result_list, size_t num_results, size_t n) * returns number of best targets (or 0, no suitable targets) */ static int iter_filter_order(struct iter_env* iter_env, struct module_env* env, - uint8_t* name, size_t namelen, uint16_t qtype, time_t now, - struct delegpt* dp, int* selected_rtt, int open_target, + uint8_t* name, size_t namelen, uint16_t qtype, time_t now, + struct delegpt* dp, int* selected_rtt, int open_target, struct sock_list* blacklist, time_t prefetch) { int got_num = 0, low_rtt = 0, swap_to_front, rtt_band = RTT_BAND, nth; @@ -370,9 +371,9 @@ iter_filter_order(struct iter_env* iter_env, struct module_env* env, struct delegpt_addr* a, *n, *prev=NULL; /* fillup sel_rtt and find best rtt in the bunch */ - got_num = iter_fill_rtt(iter_env, env, name, namelen, qtype, now, dp, + got_num = iter_fill_rtt(iter_env, env, name, namelen, qtype, now, dp, &low_rtt, blacklist, &num_results); - if(got_num == 0) + if(got_num == 0) return 0; if(low_rtt >= USEFUL_SERVER_TOP_TIMEOUT && (delegpt_count_missing_targets(dp) > 0 || open_target > 0)) { @@ -548,9 +549,9 @@ iter_filter_order(struct iter_env* iter_env, struct module_env* env, return got_num; } -struct delegpt_addr* -iter_server_selection(struct iter_env* iter_env, - struct module_env* env, struct delegpt* dp, +struct delegpt_addr* +iter_server_selection(struct iter_env* iter_env, + struct module_env* env, struct delegpt* dp, uint8_t* name, size_t namelen, uint16_t qtype, int* dnssec_lame, int* chase_to_rd, int open_target, struct sock_list* blacklist, time_t prefetch) @@ -592,7 +593,7 @@ iter_server_selection(struct iter_env* iter_env, if(num == 1) { a = dp->result_list; - if(++a->attempts < OUTBOUND_MSG_RETRY) + if(++a->attempts < iter_env->outbound_msg_retry) return a; dp->result_list = a->next_result; return a; @@ -602,7 +603,7 @@ iter_server_selection(struct iter_env* iter_env, log_assert(num > 1); /* grab secure random number, to pick unexpected server. * also we need it to be threadsafe. */ - sel = ub_random_max(env->rnd, num); + sel = ub_random_max(env->rnd, num); a = dp->result_list; prev = NULL; while(sel > 0 && a) { @@ -612,7 +613,7 @@ iter_server_selection(struct iter_env* iter_env, } if(!a) /* robustness */ return NULL; - if(++a->attempts < OUTBOUND_MSG_RETRY) + if(++a->attempts < iter_env->outbound_msg_retry) return a; /* remove it from the delegation point result list */ if(prev) @@ -621,8 +622,8 @@ iter_server_selection(struct iter_env* iter_env, return a; } -struct dns_msg* -dns_alloc_msg(sldns_buffer* pkt, struct msg_parse* msg, +struct dns_msg* +dns_alloc_msg(sldns_buffer* pkt, struct msg_parse* msg, struct regional* region) { struct dns_msg* m = (struct dns_msg*)regional_alloc(region, @@ -637,7 +638,7 @@ dns_alloc_msg(sldns_buffer* pkt, struct msg_parse* msg, return m; } -struct dns_msg* +struct dns_msg* dns_copy_msg(struct dns_msg* from, struct regional* region) { struct dns_msg* m = (struct dns_msg*)regional_alloc(region, @@ -653,7 +654,7 @@ dns_copy_msg(struct dns_msg* from, struct regional* region) return m; } -void +void iter_dns_store(struct module_env* env, struct query_info* msgqinf, struct reply_info* msgrep, int is_referral, time_t leeway, int pside, struct regional* region, uint16_t flags) @@ -663,7 +664,7 @@ iter_dns_store(struct module_env* env, struct query_info* msgqinf, log_err("out of memory: cannot store data in cache"); } -int +int iter_ns_probability(struct ub_randstate* rnd, int n, int m) { int sel; @@ -671,7 +672,7 @@ iter_ns_probability(struct ub_randstate* rnd, int n, int m) return 1; /* we do not need secure random numbers here, but * we do need it to be threadsafe, so we use this */ - sel = ub_random_max(rnd, m); + sel = ub_random_max(rnd, m); return (sel < n); } @@ -688,12 +689,12 @@ causes_cycle(struct module_qstate* qstate, uint8_t* name, size_t namelen, qinf.local_alias = NULL; fptr_ok(fptr_whitelist_modenv_detect_cycle( qstate->env->detect_cycle)); - return (*qstate->env->detect_cycle)(qstate, &qinf, + return (*qstate->env->detect_cycle)(qstate, &qinf, (uint16_t)(BIT_RD|BIT_CD), qstate->is_priming, qstate->is_valrec); } -void +void iter_mark_cycle_targets(struct module_qstate* qstate, struct delegpt* dp) { struct delegpt_ns* ns; @@ -701,21 +702,21 @@ iter_mark_cycle_targets(struct module_qstate* qstate, struct delegpt* dp) if(ns->resolved) continue; /* see if this ns as target causes dependency cycle */ - if(causes_cycle(qstate, ns->name, ns->namelen, + if(causes_cycle(qstate, ns->name, ns->namelen, LDNS_RR_TYPE_AAAA, qstate->qinfo.qclass) || - causes_cycle(qstate, ns->name, ns->namelen, + causes_cycle(qstate, ns->name, ns->namelen, LDNS_RR_TYPE_A, qstate->qinfo.qclass)) { log_nametypeclass(VERB_QUERY, "skipping target due " "to dependency cycle (harden-glue: no may " - "fix some of the cycles)", - ns->name, LDNS_RR_TYPE_A, + "fix some of the cycles)", + ns->name, LDNS_RR_TYPE_A, qstate->qinfo.qclass); ns->resolved = 1; } } } -void +void iter_mark_pside_cycle_targets(struct module_qstate* qstate, struct delegpt* dp) { struct delegpt_ns* ns; @@ -723,14 +724,14 @@ iter_mark_pside_cycle_targets(struct module_qstate* qstate, struct delegpt* dp) if(ns->done_pside4 && ns->done_pside6) continue; /* see if this ns as target causes dependency cycle */ - if(causes_cycle(qstate, ns->name, ns->namelen, + if(causes_cycle(qstate, ns->name, ns->namelen, LDNS_RR_TYPE_A, qstate->qinfo.qclass)) { log_nametypeclass(VERB_QUERY, "skipping target due " "to dependency cycle", ns->name, LDNS_RR_TYPE_A, qstate->qinfo.qclass); ns->done_pside4 = 1; } - if(causes_cycle(qstate, ns->name, ns->namelen, + if(causes_cycle(qstate, ns->name, ns->namelen, LDNS_RR_TYPE_AAAA, qstate->qinfo.qclass)) { log_nametypeclass(VERB_QUERY, "skipping target due " "to dependency cycle", ns->name, @@ -740,8 +741,8 @@ iter_mark_pside_cycle_targets(struct module_qstate* qstate, struct delegpt* dp) } } -int -iter_dp_is_useless(struct query_info* qinfo, uint16_t qflags, +int +iter_dp_is_useless(struct query_info* qinfo, uint16_t qflags, struct delegpt* dp) { struct delegpt_ns* ns; @@ -760,14 +761,14 @@ iter_dp_is_useless(struct query_info* qinfo, uint16_t qflags, /* either available or unused targets */ if(dp->usable_list || dp->result_list) return 0; - + /* see if query is for one of the nameservers, which is glue */ if( (qinfo->qtype == LDNS_RR_TYPE_A || qinfo->qtype == LDNS_RR_TYPE_AAAA) && dname_subdomain_c(qinfo->qname, dp->name) && delegpt_find_ns(dp, qinfo->qname, qinfo->qname_len)) return 1; - + for(ns = dp->nslist; ns; ns = ns->next) { if(ns->resolved) /* skip failed targets */ continue; @@ -785,7 +786,7 @@ iter_qname_indicates_dnssec(struct module_env* env, struct query_info *qinfo) return 0; /* a trust anchor exists above the name? */ if((a=anchors_lookup(env->anchors, qinfo->qname, qinfo->qname_len, - qinfo->qclass))) { + qinfo->qclass))) { if(a->numDS == 0 && a->numDNSKEY == 0) { /* insecure trust point */ lock_basic_unlock(&a->lock); @@ -798,7 +799,7 @@ iter_qname_indicates_dnssec(struct module_env* env, struct query_info *qinfo) return 0; } -int +int iter_indicates_dnssec(struct module_env* env, struct delegpt* dp, struct dns_msg* msg, uint16_t dclass) { @@ -842,7 +843,7 @@ iter_indicates_dnssec(struct module_env* env, struct delegpt* dp, return 0; } -int +int iter_msg_has_dnssec(struct dns_msg* msg) { size_t i; @@ -875,7 +876,7 @@ int iter_msg_from_zone(struct dns_msg* msg, struct delegpt* dp, * and referral to example.com. NS ... , then origin zone * is .com. For a referral to sub.example.com. NS ... then * we do not know, since example.com. may be in between. */ - for(i=0; irep->an_numrrsets+msg->rep->ns_numrrsets; + for(i=0; irep->an_numrrsets+msg->rep->ns_numrrsets; i++) { struct ub_packed_rrset_key* s = msg->rep->rrsets[i]; if(ntohs(s->rk.type) == LDNS_RR_TYPE_NS && @@ -890,7 +891,7 @@ int iter_msg_from_zone(struct dns_msg* msg, struct delegpt* dp, return 0; } log_assert(type==RESPONSE_TYPE_ANSWER || type==RESPONSE_TYPE_CNAME); - /* not a referral, and not lame delegation (upwards), so, + /* not a referral, and not lame delegation (upwards), so, * any NS rrset must be from the zone itself */ if(reply_find_rrset_section_an(msg->rep, dp->name, dp->namelen, LDNS_RR_TYPE_NS, dclass) || @@ -906,7 +907,7 @@ int iter_msg_from_zone(struct dns_msg* msg, struct delegpt* dp, } /** - * check equality of two rrsets + * check equality of two rrsets * @param k1: rrset * @param k2: rrset * @return true if equal @@ -935,7 +936,7 @@ rrset_equal(struct ub_packed_rrset_key* k1, struct ub_packed_rrset_key* k2) for(i=0; irr_len[i] != d2->rr_len[i] || /* no ttl check: d1->rr_ttl[i] != d2->rr_ttl[i] ||*/ - memcmp(d1->rr_data[i], d2->rr_data[i], + memcmp(d1->rr_data[i], d2->rr_data[i], d1->rr_len[i]) != 0) return 0; } @@ -966,7 +967,7 @@ rrset_canonical_sort_cmp(const void* x, const void* y) return 0; } -int +int reply_equal(struct reply_info* p, struct reply_info* q, struct regional* region) { size_t i; @@ -1024,7 +1025,7 @@ reply_equal(struct reply_info* p, struct reply_info* q, struct regional* region) return 1; } -void +void caps_strip_reply(struct reply_info* rep) { size_t i; @@ -1066,8 +1067,8 @@ int caps_failed_rcode(struct reply_info* rep) FLAGS_GET_RCODE(rep->flags) == LDNS_RCODE_NXDOMAIN); } -void -iter_store_parentside_rrset(struct module_env* env, +void +iter_store_parentside_rrset(struct module_env* env, struct ub_packed_rrset_key* rrset) { struct rrset_ref ref; @@ -1107,12 +1108,12 @@ iter_store_parentside_NS(struct module_env* env, struct reply_info* rep) } } -void iter_store_parentside_neg(struct module_env* env, +void iter_store_parentside_neg(struct module_env* env, struct query_info* qinfo, struct reply_info* rep) { /* TTL: NS from referral in iq->deleg_msg, * or first RR from iq->response, - * or servfail5secs if !iq->response */ + * or servfail5secs if !iq->response */ time_t ttl = NORR_TTL; struct ub_packed_rrset_key* neg; struct packed_rrset_data* newd; @@ -1133,7 +1134,7 @@ void iter_store_parentside_neg(struct module_env* env, neg->rk.type = htons(qinfo->qtype); neg->rk.rrset_class = htons(qinfo->qclass); neg->rk.flags = 0; - neg->rk.dname = regional_alloc_init(env->scratch, qinfo->qname, + neg->rk.dname = regional_alloc_init(env->scratch, qinfo->qname, qinfo->qname_len); if(!neg->rk.dname) { log_err("out of memory in store_parentside_neg"); @@ -1141,7 +1142,7 @@ void iter_store_parentside_neg(struct module_env* env, } neg->rk.dname_len = qinfo->qname_len; neg->entry.hash = rrset_key_hash(&neg->rk); - newd = (struct packed_rrset_data*)regional_alloc_zero(env->scratch, + newd = (struct packed_rrset_data*)regional_alloc_zero(env->scratch, sizeof(struct packed_rrset_data) + sizeof(size_t) + sizeof(uint8_t*) + sizeof(time_t) + sizeof(uint16_t)); if(!newd) { @@ -1166,13 +1167,13 @@ void iter_store_parentside_neg(struct module_env* env, iter_store_parentside_rrset(env, neg); } -int +int iter_lookup_parent_NS_from_cache(struct module_env* env, struct delegpt* dp, struct regional* region, struct query_info* qinfo) { struct ub_packed_rrset_key* akey; - akey = rrset_cache_lookup(env->rrset_cache, dp->name, - dp->namelen, LDNS_RR_TYPE_NS, qinfo->qclass, + akey = rrset_cache_lookup(env->rrset_cache, dp->name, + dp->namelen, LDNS_RR_TYPE_NS, qinfo->qclass, PACKED_RRSET_PARENT_SIDE, *env->now, 0); if(akey) { log_rrset_key(VERB_ALGO, "found parent-side NS in cache", akey); @@ -1195,8 +1196,8 @@ int iter_lookup_parent_glue_from_cache(struct module_env* env, size_t num = delegpt_count_targets(dp); for(ns = dp->nslist; ns; ns = ns->next) { /* get cached parentside A */ - akey = rrset_cache_lookup(env->rrset_cache, ns->name, - ns->namelen, LDNS_RR_TYPE_A, qinfo->qclass, + akey = rrset_cache_lookup(env->rrset_cache, ns->name, + ns->namelen, LDNS_RR_TYPE_A, qinfo->qclass, PACKED_RRSET_PARENT_SIDE, *env->now, 0); if(akey) { log_rrset_key(VERB_ALGO, "found parent-side", akey); @@ -1207,8 +1208,8 @@ int iter_lookup_parent_glue_from_cache(struct module_env* env, lock_rw_unlock(&akey->entry.lock); } /* get cached parentside AAAA */ - akey = rrset_cache_lookup(env->rrset_cache, ns->name, - ns->namelen, LDNS_RR_TYPE_AAAA, qinfo->qclass, + akey = rrset_cache_lookup(env->rrset_cache, ns->name, + ns->namelen, LDNS_RR_TYPE_AAAA, qinfo->qclass, PACKED_RRSET_PARENT_SIDE, *env->now, 0); if(akey) { log_rrset_key(VERB_ALGO, "found parent-side", akey); @@ -1223,8 +1224,8 @@ int iter_lookup_parent_glue_from_cache(struct module_env* env, return delegpt_count_targets(dp) != num; } -int -iter_get_next_root(struct iter_hints* hints, struct iter_forwards* fwd, +int +iter_get_next_root(struct iter_hints* hints, struct iter_forwards* fwd, uint16_t* c) { uint16_t c1 = *c, c2 = *c; @@ -1246,7 +1247,7 @@ void iter_scrub_ds(struct dns_msg* msg, struct ub_packed_rrset_key* ns, uint8_t* z) { /* Only the DS record for the delegation itself is expected. - * We allow DS for everything between the bailiwick and the + * We allow DS for everything between the bailiwick and the * zonecut, thus DS records must be at or above the zonecut. * And the DS records must be below the server authority zone. * The answer section is already scrubbed. */ @@ -1260,7 +1261,7 @@ iter_scrub_ds(struct dns_msg* msg, struct ub_packed_rrset_key* ns, uint8_t* z) s->rk.dname, ntohs(s->rk.type), ntohs(s->rk.rrset_class)); memmove(msg->rep->rrsets+i, msg->rep->rrsets+i+1, - sizeof(struct ub_packed_rrset_key*) * + sizeof(struct ub_packed_rrset_key*) * (msg->rep->rrset_count-i-1)); msg->rep->ns_numrrsets--; msg->rep->rrset_count--; @@ -1284,11 +1285,11 @@ iter_scrub_nxdomain(struct dns_msg* msg) msg->rep->an_numrrsets = 0; } -void iter_dec_attempts(struct delegpt* dp, int d) +void iter_dec_attempts(struct delegpt* dp, int d, int outbound_msg_retry) { struct delegpt_addr* a; for(a=dp->target_list; a; a = a->next_target) { - if(a->attempts >= OUTBOUND_MSG_RETRY) { + if(a->attempts >= outbound_msg_retry) { /* add back to result list */ a->next_result = dp->result_list; dp->result_list = a; @@ -1299,7 +1300,8 @@ void iter_dec_attempts(struct delegpt* dp, int d) } } -void iter_merge_retry_counts(struct delegpt* dp, struct delegpt* old) +void iter_merge_retry_counts(struct delegpt* dp, struct delegpt* old, + int outbound_msg_retry) { struct delegpt_addr* a, *o, *prev; for(a=dp->target_list; a; a = a->next_target) { @@ -1313,7 +1315,7 @@ void iter_merge_retry_counts(struct delegpt* dp, struct delegpt* old) prev = NULL; a = dp->usable_list; while(a) { - if(a->attempts >= OUTBOUND_MSG_RETRY) { + if(a->attempts >= outbound_msg_retry) { log_addr(VERB_ALGO, "remove from usable list dp", &a->addr, a->addrlen); /* remove from result list */ diff --git a/contrib/unbound/iterator/iter_utils.h b/contrib/unbound/iterator/iter_utils.h index 509d2921e306..0a40916c0e02 100644 --- a/contrib/unbound/iterator/iter_utils.h +++ b/contrib/unbound/iterator/iter_utils.h @@ -347,16 +347,19 @@ void iter_scrub_nxdomain(struct dns_msg* msg); * Remove query attempts from all available ips. For 0x20. * @param dp: delegpt. * @param d: decrease. + * @param outbound_msg_retry: number of retries of outgoing queries */ -void iter_dec_attempts(struct delegpt* dp, int d); +void iter_dec_attempts(struct delegpt* dp, int d, int outbound_msg_retry); /** * Add retry counts from older delegpt to newer delegpt. * Does not waste time on timeout'd (or other failing) addresses. * @param dp: new delegationpoint. * @param old: old delegationpoint. + * @param outbound_msg_retry: number of retries of outgoing queries */ -void iter_merge_retry_counts(struct delegpt* dp, struct delegpt* old); +void iter_merge_retry_counts(struct delegpt* dp, struct delegpt* old, + int outbound_msg_retry); /** * See if a DS response (type ANSWER) is too low: a nodata answer with diff --git a/contrib/unbound/iterator/iterator.c b/contrib/unbound/iterator/iterator.c index f0105ad4b085..48238a231b13 100644 --- a/contrib/unbound/iterator/iterator.c +++ b/contrib/unbound/iterator/iterator.c @@ -2298,7 +2298,7 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq, iq->minimise_count++; iq->timeout_count = 0; - iter_dec_attempts(iq->dp, 1); + iter_dec_attempts(iq->dp, 1, ie->outbound_msg_retry); /* Limit number of iterations for QNAMEs with more * than MAX_MINIMISE_COUNT labels. Send first MINIMISE_ONE_LAB @@ -2500,7 +2500,7 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq, (int)iq->caps_server+1, (int)naddr*3); iq->response = iq->caps_response; iq->caps_fallback = 0; - iter_dec_attempts(iq->dp, 3); /* space for fallback */ + iter_dec_attempts(iq->dp, 3, ie->outbound_msg_retry); /* space for fallback */ iq->num_current_queries++; /* RespState decrements it*/ iq->referral_count++; /* make sure we don't loop */ iq->sent_count = 0; @@ -2529,6 +2529,23 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq, /* Add the current set of unused targets to our queue. */ delegpt_add_unused_targets(iq->dp); + if(qstate->env->auth_zones) { + /* apply rpz triggers at query time */ + struct dns_msg* forged_response = rpz_callback_from_iterator_module(qstate, iq); + if(forged_response != NULL) { + qstate->ext_state[id] = module_finished; + qstate->return_rcode = FLAGS_GET_RCODE(forged_response->rep->flags); + qstate->return_msg = forged_response; + iq->response = forged_response; + next_state(iq, FINISHED_STATE); + if(!iter_prepend(iq, qstate->return_msg, qstate->region)) { + log_err("rpz, prepend rrsets: out of memory"); + return error_response(qstate, id, LDNS_RCODE_SERVFAIL); + } + return 0; + } + } + /* Select the next usable target, filtering out unsuitable targets. */ target = iter_server_selection(ie, qstate->env, iq->dp, iq->dp->name, iq->dp->namelen, iq->qchase.qtype, @@ -2588,7 +2605,7 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq, (int)iq->caps_server+1); iq->response = iq->caps_response; iq->caps_fallback = 0; - iter_dec_attempts(iq->dp, 3); /* space for fallback */ + iter_dec_attempts(iq->dp, 3, ie->outbound_msg_retry); /* space for fallback */ iq->num_current_queries++; /* RespState decrements it*/ iq->referral_count++; /* make sure we don't loop */ iq->sent_count = 0; @@ -2666,6 +2683,7 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq, iq->dnssec_expected, iq->caps_fallback || is_caps_whitelisted( ie, iq), &target->addr, target->addrlen, iq->dp->name, iq->dp->namelen, + (iq->dp->tcp_upstream || qstate->env->cfg->tcp_upstream), (iq->dp->ssl_upstream || qstate->env->cfg->ssl_upstream), target->tls_auth_name, qstate); if(!outq) { @@ -2707,6 +2725,7 @@ find_NS(struct reply_info* rep, size_t from, size_t to) * * @param qstate: query state. * @param iq: iterator query state. + * @param ie: iterator shared global environment. * @param id: module id. * @return true if the event requires more immediate processing, false if * not. This is generally only true when forwarding the request to @@ -2714,10 +2733,11 @@ find_NS(struct reply_info* rep, size_t from, size_t to) */ static int processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq, - int id) + struct iter_env* ie, int id) { int dnsseclame = 0; enum response_type type; + iq->num_current_queries--; if(!inplace_cb_query_response_call(qstate->env, qstate, iq->response)) @@ -2983,7 +3003,8 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq, } if(iq->store_parent_NS && query_dname_compare(iq->dp->name, iq->store_parent_NS->name) == 0) - iter_merge_retry_counts(iq->dp, iq->store_parent_NS); + iter_merge_retry_counts(iq->dp, iq->store_parent_NS, + ie->outbound_msg_retry); delegpt_log(VERB_ALGO, iq->dp); /* Count this as a referral. */ iq->referral_count++; @@ -3061,6 +3082,39 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq, /* set the current request's qname to the new value. */ iq->qchase.qname = sname; iq->qchase.qname_len = snamelen; + if(qstate->env->auth_zones) { + /* apply rpz qname triggers after cname */ + struct dns_msg* forged_response = + rpz_callback_from_iterator_cname(qstate, iq); + while(forged_response && reply_find_rrset_section_an( + forged_response->rep, iq->qchase.qname, + iq->qchase.qname_len, LDNS_RR_TYPE_CNAME, + iq->qchase.qclass)) { + /* another cname to follow */ + if(!handle_cname_response(qstate, iq, forged_response, + &sname, &snamelen)) { + errinf(qstate, "malloc failure, CNAME info"); + return error_response(qstate, id, LDNS_RCODE_SERVFAIL); + } + iq->qchase.qname = sname; + iq->qchase.qname_len = snamelen; + forged_response = + rpz_callback_from_iterator_cname(qstate, iq); + } + if(forged_response != NULL) { + qstate->ext_state[id] = module_finished; + qstate->return_rcode = FLAGS_GET_RCODE(forged_response->rep->flags); + qstate->return_msg = forged_response; + iq->response = forged_response; + next_state(iq, FINISHED_STATE); + if(!iter_prepend(iq, qstate->return_msg, qstate->region)) { + log_err("rpz after cname, prepend rrsets: out of memory"); + return error_response(qstate, id, LDNS_RCODE_SERVFAIL); + } + qstate->return_msg->qinfo = qstate->qinfo; + return 0; + } + } /* Clear the query state, since this is a query restart. */ iq->deleg_msg = NULL; iq->dp = NULL; @@ -3188,7 +3242,7 @@ prime_supers(struct module_qstate* qstate, int id, struct module_qstate* forq) /* Convert our response to a delegation point */ dp = delegpt_from_message(qstate->return_msg, forq->region); if(!dp) { - /* if there is no convertable delegation point, then + /* if there is no convertible delegation point, then * the ANSWER type was (presumably) a negative answer. */ verbose(VERB_ALGO, "prime response was not a positive " "ANSWER; failing"); @@ -3694,7 +3748,7 @@ iter_handle(struct module_qstate* qstate, struct iter_qstate* iq, cont = processQueryTargets(qstate, iq, ie, id); break; case QUERY_RESP_STATE: - cont = processQueryResponse(qstate, iq, id); + cont = processQueryResponse(qstate, iq, ie, id); break; case PRIME_RESP_STATE: cont = processPrimeResponse(qstate, id); @@ -3764,7 +3818,7 @@ process_response(struct module_qstate* qstate, struct iter_qstate* iq, iq->num_current_queries--; /* need fresh attempts for the 0x20 fallback, if * that was the cause for the failure */ - iter_dec_attempts(iq->dp, 3); + iter_dec_attempts(iq->dp, 3, ie->outbound_msg_retry); verbose(VERB_DETAIL, "Capsforid: timeouts, starting fallback"); goto handle_it; } @@ -3798,15 +3852,15 @@ process_response(struct module_qstate* qstate, struct iter_qstate* iq, goto handle_it; } /* edns is not examined, but removed from message to help cache */ - if(parse_extract_edns(prs, &edns, qstate->env->scratch) != + if(parse_extract_edns_from_response_msg(prs, &edns, qstate->env->scratch) != LDNS_RCODE_NOERROR) { iq->parse_failures++; goto handle_it; } /* Copy the edns options we may got from the back end */ - if(edns.opt_list) { - qstate->edns_opts_back_in = edns_opt_copy_region(edns.opt_list, + if(edns.opt_list_in) { + qstate->edns_opts_back_in = edns_opt_copy_region(edns.opt_list_in, qstate->region); if(!qstate->edns_opts_back_in) { log_err("out of memory on incoming message"); diff --git a/contrib/unbound/iterator/iterator.h b/contrib/unbound/iterator/iterator.h index dc5e57527d87..a9e58569fcf3 100644 --- a/contrib/unbound/iterator/iterator.h +++ b/contrib/unbound/iterator/iterator.h @@ -94,8 +94,6 @@ extern int UNKNOWN_SERVER_NICENESS; * Equals RTT_MAX_TIMEOUT */ #define USEFUL_SERVER_TOP_TIMEOUT 120000 -/** number of retries on outgoing queries */ -#define OUTBOUND_MSG_RETRY 5 /** RTT band, within this amount from the best, servers are chosen randomly. * Chosen so that the UNKNOWN_SERVER_NICENESS falls within the band of a * fast server, this causes server exploration as a side benefit. msec. */ @@ -139,6 +137,9 @@ struct iter_env { lock_basic_type queries_ratelimit_lock; /** number of queries that have been ratelimited */ size_t num_queries_ratelimited; + + /** number of retries on outgoing queries */ + int outbound_msg_retry; }; /** diff --git a/contrib/unbound/libunbound/context.c b/contrib/unbound/libunbound/context.c index e589c6ae28d7..c8d911f13c7f 100644 --- a/contrib/unbound/libunbound/context.c +++ b/contrib/unbound/libunbound/context.c @@ -48,6 +48,7 @@ #include "services/cache/rrset.h" #include "services/cache/infra.h" #include "services/authzone.h" +#include "services/listen_dnsport.h" #include "util/data/msgreply.h" #include "util/storage/slabhash.h" #include "util/edns.h" @@ -73,6 +74,7 @@ context_finalize(struct ub_ctx* ctx) config_apply(cfg); if(!modstack_setup(&ctx->mods, cfg->module_conf, ctx->env)) return UB_INITFAIL; + listen_setup_locks(); log_edns_known_options(VERB_ALGO, ctx->env); ctx->local_zones = local_zones_create(); if(!ctx->local_zones) diff --git a/contrib/unbound/libunbound/context.h b/contrib/unbound/libunbound/context.h index 78f8731e236e..c0c86fb52697 100644 --- a/contrib/unbound/libunbound/context.h +++ b/contrib/unbound/libunbound/context.h @@ -176,35 +176,6 @@ struct ctx_query { struct ub_result* res; }; -/** - * The error constants - */ -enum ub_ctx_err { - /** no error */ - UB_NOERROR = 0, - /** socket operation. Set to -1, so that if an error from _fd() is - * passed (-1) it gives a socket error. */ - UB_SOCKET = -1, - /** alloc failure */ - UB_NOMEM = -2, - /** syntax error */ - UB_SYNTAX = -3, - /** DNS service failed */ - UB_SERVFAIL = -4, - /** fork() failed */ - UB_FORKFAIL = -5, - /** cfg change after finalize() */ - UB_AFTERFINAL = -6, - /** initialization failed (bad settings) */ - UB_INITFAIL = -7, - /** error in pipe communication with async bg worker */ - UB_PIPE = -8, - /** error reading from file (resolv.conf) */ - UB_READFILE = -9, - /** error async_id does not exist or result already been delivered */ - UB_NOID = -10 -}; - /** * Command codes for libunbound pipe. * diff --git a/contrib/unbound/libunbound/libunbound.c b/contrib/unbound/libunbound/libunbound.c index c9e24ba8d8f2..038b7b927a74 100644 --- a/contrib/unbound/libunbound/libunbound.c +++ b/contrib/unbound/libunbound/libunbound.c @@ -64,6 +64,7 @@ #include "services/cache/infra.h" #include "services/cache/rrset.h" #include "services/authzone.h" +#include "services/listen_dnsport.h" #include "sldns/sbuffer.h" #ifdef HAVE_PTHREAD #include @@ -185,6 +186,7 @@ ub_ctx_create(void) ub_randfree(ctx->seed_rnd); config_delete(ctx->env->cfg); modstack_desetup(&ctx->mods, ctx->env); + listen_desetup_locks(); edns_known_options_delete(ctx->env); edns_strings_delete(ctx->env->edns_strings); free(ctx->env); @@ -198,6 +200,7 @@ ub_ctx_create(void) ub_randfree(ctx->seed_rnd); config_delete(ctx->env->cfg); modstack_desetup(&ctx->mods, ctx->env); + listen_desetup_locks(); edns_known_options_delete(ctx->env); edns_strings_delete(ctx->env->edns_strings); free(ctx->env); @@ -344,6 +347,7 @@ ub_ctx_delete(struct ub_ctx* ctx) } ub_randfree(ctx->seed_rnd); alloc_clear(&ctx->superalloc); + listen_desetup_locks(); traverse_postorder(&ctx->queries, delq, NULL); if(ctx_logfile_overridden) { log_file(NULL); diff --git a/contrib/unbound/libunbound/libworker.c b/contrib/unbound/libunbound/libworker.c index 8a9ca9419480..7f753435d068 100644 --- a/contrib/unbound/libunbound/libworker.c +++ b/contrib/unbound/libunbound/libworker.c @@ -600,7 +600,9 @@ setup_qinfo_edns(struct libworker* w, struct ctx_query* q, edns->ext_rcode = 0; edns->edns_version = 0; edns->bits = EDNS_DO; - edns->opt_list = NULL; + edns->opt_list_in = NULL; + edns->opt_list_out = NULL; + edns->opt_list_inplace_cb_out = NULL; edns->padding_block_size = 0; if(sldns_buffer_capacity(w->back->udp_buff) < 65535) edns->udp_size = (uint16_t)sldns_buffer_capacity( @@ -881,7 +883,7 @@ void libworker_alloc_cleanup(void* arg) struct outbound_entry* libworker_send_query(struct query_info* qinfo, uint16_t flags, int dnssec, int want_dnssec, int nocaps, struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* zone, - size_t zonelen, int ssl_upstream, char* tls_auth_name, + size_t zonelen, int tcp_upstream, int ssl_upstream, char* tls_auth_name, struct module_qstate* q) { struct libworker* w = (struct libworker*)q->env->worker; @@ -891,7 +893,7 @@ struct outbound_entry* libworker_send_query(struct query_info* qinfo, return NULL; e->qstate = q; e->qsent = outnet_serviced_query(w->back, qinfo, flags, dnssec, - want_dnssec, nocaps, q->env->cfg->tcp_upstream, ssl_upstream, + want_dnssec, nocaps, tcp_upstream, ssl_upstream, tls_auth_name, addr, addrlen, zone, zonelen, q, libworker_handle_service_reply, e, w->back->udp_buff, q->env); if(!e->qsent) { @@ -975,7 +977,7 @@ struct outbound_entry* worker_send_query(struct query_info* ATTR_UNUSED(qinfo), uint16_t ATTR_UNUSED(flags), int ATTR_UNUSED(dnssec), int ATTR_UNUSED(want_dnssec), int ATTR_UNUSED(nocaps), struct sockaddr_storage* ATTR_UNUSED(addr), socklen_t ATTR_UNUSED(addrlen), - uint8_t* ATTR_UNUSED(zone), size_t ATTR_UNUSED(zonelen), + uint8_t* ATTR_UNUSED(zone), size_t ATTR_UNUSED(zonelen), int ATTR_UNUSED(tcp_upstream), int ATTR_UNUSED(ssl_upstream), char* ATTR_UNUSED(tls_auth_name), struct module_qstate* ATTR_UNUSED(q)) { diff --git a/contrib/unbound/libunbound/unbound-event.h b/contrib/unbound/libunbound/unbound-event.h index 4d694b8b4c5d..a5d5c038b68f 100644 --- a/contrib/unbound/libunbound/unbound-event.h +++ b/contrib/unbound/libunbound/unbound-event.h @@ -41,7 +41,7 @@ * * Use ub_ctx_create_event_ub_base() to create an unbound context that uses * the user provided event base API. Then, use the ub_resolve_event call - * to add DNS resolve queries to the context. Those then run whith the + * to add DNS resolve queries to the context. Those then run with the * provided event_base, and when they are done you get a function callback. * * This method does not fork another process or create a thread, the effort diff --git a/contrib/unbound/libunbound/unbound.h b/contrib/unbound/libunbound/unbound.h index 945c17a8fb5b..ee8558759065 100644 --- a/contrib/unbound/libunbound/unbound.h +++ b/contrib/unbound/libunbound/unbound.h @@ -224,7 +224,7 @@ struct ub_result { * It is called with * void* my_arg: your pointer to a (struct of) data of your choice, * or NULL. - * int err: if 0 all is OK, otherwise an error occured and no results + * int err: if 0 all is OK, otherwise an error occurred and no results * are forthcoming. * struct result: pointer to more detailed result structure. * This structure is allocated on the heap and needs to be @@ -232,6 +232,35 @@ struct ub_result { */ typedef void (*ub_callback_type)(void*, int, struct ub_result*); +/** + * The error constants + */ +enum ub_ctx_err { + /** no error */ + UB_NOERROR = 0, + /** socket operation. Set to -1, so that if an error from _fd() is + * passed (-1) it gives a socket error. */ + UB_SOCKET = -1, + /** alloc failure */ + UB_NOMEM = -2, + /** syntax error */ + UB_SYNTAX = -3, + /** DNS service failed */ + UB_SERVFAIL = -4, + /** fork() failed */ + UB_FORKFAIL = -5, + /** cfg change after finalize() */ + UB_AFTERFINAL = -6, + /** initialization failed (bad settings) */ + UB_INITFAIL = -7, + /** error in pipe communication with async bg worker */ + UB_PIPE = -8, + /** error reading from file (resolv.conf) */ + UB_READFILE = -9, + /** error async_id does not exist or result already been delivered */ + UB_NOID = -10 +}; + /** * Create a resolving and validation context. * The information from /etc/resolv.conf and /etc/hosts is not utilised by @@ -563,6 +592,7 @@ void ub_resolve_free(struct ub_result* result); /** * Convert error value to a human readable string. * @param err: error code from one of the libunbound functions. + * The error codes are from the type enum ub_ctx_err. * @return pointer to constant text string, zero terminated. */ const char* ub_strerror(int err); diff --git a/contrib/unbound/libunbound/worker.h b/contrib/unbound/libunbound/worker.h index bf7473861af8..974b66a30e84 100644 --- a/contrib/unbound/libunbound/worker.h +++ b/contrib/unbound/libunbound/worker.h @@ -62,17 +62,18 @@ struct query_info; * @param addrlen: length of addr. * @param zone: delegation point name. * @param zonelen: length of zone name wireformat dname. + * @param tcp_upstream: use TCP for upstream queries. * @param ssl_upstream: use SSL for upstream queries. * @param tls_auth_name: if ssl_upstream, use this name with TLS * authentication. - * @param q: wich query state to reactivate upon return. + * @param q: which query state to reactivate upon return. * @return: false on failure (memory or socket related). no query was * sent. */ struct outbound_entry* libworker_send_query(struct query_info* qinfo, uint16_t flags, int dnssec, int want_dnssec, int nocaps, struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* zone, - size_t zonelen, int ssl_upstream, char* tls_auth_name, + size_t zonelen, int tcp_upstream, int ssl_upstream, char* tls_auth_name, struct module_qstate* q); /** process incoming serviced query replies from the network */ @@ -113,17 +114,18 @@ void worker_sighandler(int sig, void* arg); * @param addrlen: length of addr. * @param zone: wireformat dname of the zone. * @param zonelen: length of zone name. + * @param tcp_upstream: use TCP for upstream queries. * @param ssl_upstream: use SSL for upstream queries. * @param tls_auth_name: if ssl_upstream, use this name with TLS * authentication. - * @param q: wich query state to reactivate upon return. + * @param q: which query state to reactivate upon return. * @return: false on failure (memory or socket related). no query was * sent. */ struct outbound_entry* worker_send_query(struct query_info* qinfo, uint16_t flags, int dnssec, int want_dnssec, int nocaps, struct sockaddr_storage* addr, socklen_t addrlen, uint8_t* zone, - size_t zonelen, int ssl_upstream, char* tls_auth_name, + size_t zonelen, int tcp_upstream, int ssl_upstream, char* tls_auth_name, struct module_qstate* q); /** diff --git a/contrib/unbound/respip/respip.c b/contrib/unbound/respip/respip.c index aae41f5d6368..3d1b3feaf460 100644 --- a/contrib/unbound/respip/respip.c +++ b/contrib/unbound/respip/respip.c @@ -25,6 +25,7 @@ #include "respip/respip.h" #include "services/view.h" #include "sldns/rrdef.h" +#include "util/data/dname.h" /** Subset of resp_addr.node, used for inform-variant logging */ @@ -483,8 +484,8 @@ respip_views_apply_cfg(struct views* vs, struct config_file* cfg, * This function returns the copied rrset key on success, and NULL on memory * allocation failure. */ -static struct ub_packed_rrset_key* -copy_rrset(const struct ub_packed_rrset_key* key, struct regional* region) +struct ub_packed_rrset_key* +respip_copy_rrset(const struct ub_packed_rrset_key* key, struct regional* region) { struct ub_packed_rrset_key* ck = regional_alloc(region, sizeof(struct ub_packed_rrset_key)); @@ -602,7 +603,7 @@ rdata2sockaddr(const struct packed_rrset_data* rd, uint16_t rtype, size_t i, */ static struct resp_addr* respip_addr_lookup(const struct reply_info *rep, struct respip_set* rs, - size_t* rrset_id) + size_t* rrset_id, size_t* rr_id) { size_t i; struct resp_addr* ra; @@ -625,6 +626,7 @@ respip_addr_lookup(const struct reply_info *rep, struct respip_set* rs, &ss, addrlen); if(ra) { *rrset_id = i; + *rr_id = j; lock_rw_rdlock(&ra->lock); lock_rw_unlock(&rs->lock); return ra; @@ -635,43 +637,6 @@ respip_addr_lookup(const struct reply_info *rep, struct respip_set* rs, return NULL; } -/* - * Create a new reply_info based on 'rep'. The new info is based on - * the passed 'rep', but ignores any rrsets except for the first 'an_numrrsets' - * RRsets in the answer section. These answer rrsets are copied to the - * new info, up to 'copy_rrsets' rrsets (which must not be larger than - * 'an_numrrsets'). If an_numrrsets > copy_rrsets, the remaining rrsets array - * entries will be kept empty so the caller can fill them later. When rrsets - * are copied, they are shallow copied. The caller must ensure that the - * copied rrsets are valid throughout its lifetime and must provide appropriate - * mutex if it can be shared by multiple threads. - */ -static struct reply_info * -make_new_reply_info(const struct reply_info* rep, struct regional* region, - size_t an_numrrsets, size_t copy_rrsets) -{ - struct reply_info* new_rep; - size_t i; - - /* create a base struct. we specify 'insecure' security status as - * the modified response won't be DNSSEC-valid. In our faked response - * the authority and additional sections will be empty (except possible - * EDNS0 OPT RR in the additional section appended on sending it out), - * so the total number of RRsets is an_numrrsets. */ - new_rep = construct_reply_info_base(region, rep->flags, - rep->qdcount, rep->ttl, rep->prefetch_ttl, - rep->serve_expired_ttl, an_numrrsets, 0, 0, an_numrrsets, - sec_status_insecure); - if(!new_rep) - return NULL; - if(!reply_info_alloc_rrset_keys(new_rep, NULL, region)) - return NULL; - for(i=0; irrsets[i] = rep->rrsets[i]; - - return new_rep; -} - /** * See if response-ip or tag data should override the original answer rrset * (which is rep->rrsets[rrset_id]) and if so override it. @@ -730,7 +695,7 @@ respip_data_answer(enum respip_action action, "response-ip redirect with tag data [%d] %s", tag, (tagrk.dname = rep->rrsets[rrset_id]->rk.dname; @@ -807,7 +772,6 @@ respip_nodata_answer(uint16_t qtype, enum respip_action action, * is explicitly specified. */ int rcode = (action == respip_always_nxdomain)? LDNS_RCODE_NXDOMAIN:LDNS_RCODE_NOERROR; - /* We should empty the answer section except for any preceding * CNAMEs (in that case rrset_id > 0). Type-ANY case is * special as noted in respip_data_answer(). */ @@ -907,7 +871,7 @@ respip_rewrite_reply(const struct query_info* qinfo, size_t tag_datas_size; struct view* view = NULL; struct respip_set* ipset = NULL; - size_t rrset_id = 0; + size_t rrset_id = 0, rr_id = 0; enum respip_action action = respip_none; int tag = -1; struct resp_addr* raddr = NULL; @@ -948,7 +912,7 @@ respip_rewrite_reply(const struct query_info* qinfo, lock_rw_rdlock(&view->lock); if(view->respip_set) { if((raddr = respip_addr_lookup(rep, - view->respip_set, &rrset_id))) { + view->respip_set, &rrset_id, &rr_id))) { /** for per-view respip directives the action * can only be direct (i.e. not tag-based) */ action = raddr->action; @@ -962,7 +926,7 @@ respip_rewrite_reply(const struct query_info* qinfo, } } if(!raddr && (raddr = respip_addr_lookup(rep, ipset, - &rrset_id))) { + &rrset_id, &rr_id))) { action = (enum respip_action)local_data_find_tag_action( raddr->taglist, raddr->taglen, ctaglist, ctaglen, tag_actions, tag_actions_size, @@ -976,7 +940,7 @@ respip_rewrite_reply(const struct query_info* qinfo, if(!r->taglist || taglist_intersect(r->taglist, r->taglistlen, ctaglist, ctaglen)) { if((raddr = respip_addr_lookup(rep, - r->respip_set, &rrset_id))) { + r->respip_set, &rrset_id, &rr_id))) { if(!respip_use_rpz(raddr, r, &action, &data, &rpz_log, &log_name, &rpz_cname_override, region, &rpz_used)) { @@ -987,6 +951,21 @@ respip_rewrite_reply(const struct query_info* qinfo, return 0; } if(rpz_used) { + if(verbosity >= VERB_ALGO) { + struct sockaddr_storage ss; + socklen_t ss_len = 0; + char nm[256], ip[256]; + char qn[255+1]; + if(!rdata2sockaddr(rep->rrsets[rrset_id]->entry.data, ntohs(rep->rrsets[rrset_id]->rk.type), rr_id, &ss, &ss_len)) + snprintf(ip, sizeof(ip), "invalidRRdata"); + else + addr_to_str(&ss, ss_len, ip, sizeof(ip)); + dname_str(qinfo->qname, qn); + addr_to_str(&raddr->node.addr, + raddr->node.addrlen, + nm, sizeof(nm)); + verbose(VERB_ALGO, "respip: rpz response-ip trigger %s/%d on %s %s with action %s", nm, raddr->node.net, qn, ip, rpz_action_to_string(respip_action_to_rpz_action(action))); + } /* break to make sure 'a' stays pointed * to used auth_zone, and keeps lock */ break; @@ -1209,7 +1188,7 @@ respip_merge_cname(struct reply_info* base_rep, if(!new_rep) return 0; for(i=0,j=base_rep->an_numrrsets; ian_numrrsets; i++,j++) { - new_rep->rrsets[j] = copy_rrset(tgt_rep->rrsets[i], region); + new_rep->rrsets[j] = respip_copy_rrset(tgt_rep->rrsets[i], region); if(!new_rep->rrsets[j]) return 0; } diff --git a/contrib/unbound/respip/respip.h b/contrib/unbound/respip/respip.h index bbd471421c1e..3dfb4e9f01c7 100644 --- a/contrib/unbound/respip/respip.h +++ b/contrib/unbound/respip/respip.h @@ -294,4 +294,7 @@ respip_enter_rr(struct regional* region, struct resp_addr* raddr, */ void respip_sockaddr_delete(struct respip_set* set, struct resp_addr* node); + +struct ub_packed_rrset_key* +respip_copy_rrset(const struct ub_packed_rrset_key* key, struct regional* region); #endif /* RESPIP_RESPIP_H */ diff --git a/contrib/unbound/services/authzone.c b/contrib/unbound/services/authzone.c index d56f74a0ab3c..4598a8286510 100644 --- a/contrib/unbound/services/authzone.c +++ b/contrib/unbound/services/authzone.c @@ -84,7 +84,7 @@ #define AUTH_PROBE_TIMEOUT_STOP 1000 /* msec */ /* auth transfer timeout for TCP connections, in msec */ #define AUTH_TRANSFER_TIMEOUT 10000 /* msec */ -/* auth transfer max backoff for failed tranfers and probes */ +/* auth transfer max backoff for failed transfers and probes */ #define AUTH_TRANSFER_MAX_BACKOFF 86400 /* sec */ /* auth http port number */ #define AUTH_HTTP_PORT 80 @@ -243,7 +243,7 @@ msg_add_rrset_an(struct auth_zone* z, struct regional* region, return 1; } -/** add rrset to authority section (no additonal section rrsets yet) */ +/** add rrset to authority section (no additional section rrsets yet) */ static int msg_add_rrset_ns(struct auth_zone* z, struct regional* region, struct dns_msg* msg, struct auth_data* node, struct auth_rrset* rrset) @@ -1950,6 +1950,17 @@ static int auth_zone_zonemd_check_hash(struct auth_zone* z, return 0; } +/** find the apex SOA RRset, if it exists */ +struct auth_rrset* auth_zone_get_soa_rrset(struct auth_zone* z) +{ + struct auth_data* apex; + struct auth_rrset* soa; + apex = az_find_name(z, z->name, z->namelen); + if(!apex) return NULL; + soa = az_domain_rrset(apex, LDNS_RR_TYPE_SOA); + return soa; +} + /** find serial number of zone or false if none */ int auth_zone_get_serial(struct auth_zone* z, uint32_t* serial) @@ -3507,7 +3518,7 @@ auth_error_encode(struct query_info* qinfo, struct module_env* env, if(!inplace_cb_reply_local_call(env, qinfo, NULL, NULL, rcode, edns, repinfo, temp, env->now_tv)) - edns->opt_list = NULL; + edns->opt_list_inplace_cb_out = NULL; error_encode(buf, rcode|BIT_AA, qinfo, *(uint16_t*)sldns_buffer_begin(buf), sldns_buffer_read_u16_at(buf, 2), edns); @@ -5347,7 +5358,9 @@ xfr_transfer_lookup_host(struct auth_xfer* xfr, struct module_env* env) edns.ext_rcode = 0; edns.edns_version = 0; edns.bits = EDNS_DO; - edns.opt_list = NULL; + edns.opt_list_in = NULL; + edns.opt_list_out = NULL; + edns.opt_list_inplace_cb_out = NULL; edns.padding_block_size = 0; if(sldns_buffer_capacity(buf) < 65535) edns.udp_size = (uint16_t)sldns_buffer_capacity(buf); @@ -6480,7 +6493,7 @@ auth_xfer_probe_udp_callback(struct comm_point* c, void* arg, int err, comm_point_delete(xfr->task_probe->cp); xfr->task_probe->cp = NULL; - /* if the result was not a successfull probe, we need + /* if the result was not a successful probe, we need * to send the next one */ xfr_probe_nextmaster(xfr); xfr_probe_send_or_end(xfr, env); @@ -6536,7 +6549,9 @@ xfr_probe_lookup_host(struct auth_xfer* xfr, struct module_env* env) edns.ext_rcode = 0; edns.edns_version = 0; edns.bits = EDNS_DO; - edns.opt_list = NULL; + edns.opt_list_in = NULL; + edns.opt_list_out = NULL; + edns.opt_list_inplace_cb_out = NULL; edns.padding_block_size = 0; if(sldns_buffer_capacity(buf) < 65535) edns.udp_size = (uint16_t)sldns_buffer_capacity(buf); @@ -7149,7 +7164,7 @@ parse_url(char* url, char** host, char** file, int* port, int* ssl) while(p && *p == '/') p++; if(!p || p[0] == 0) - *file = strdup("index.html"); + *file = strdup("/"); else *file = strdup(p); if(!*file) { log_err("malloc failure"); @@ -7683,7 +7698,7 @@ static void auth_zone_log(uint8_t* name, enum verbosity_value level, static int zonemd_dnssec_verify_rrset(struct auth_zone* z, struct module_env* env, struct module_stack* mods, struct ub_packed_rrset_key* dnskey, struct auth_data* node, - struct auth_rrset* rrset, char** why_bogus) + struct auth_rrset* rrset, char** why_bogus, uint8_t* sigalg) { struct ub_packed_rrset_key pk; enum sec_status sec; @@ -7711,7 +7726,7 @@ static int zonemd_dnssec_verify_rrset(struct auth_zone* z, auth_zone_log(z->name, VERB_ALGO, "zonemd: verify %s RRset with DNSKEY", typestr); } - sec = dnskeyset_verify_rrset(env, ve, &pk, dnskey, NULL, why_bogus, + sec = dnskeyset_verify_rrset(env, ve, &pk, dnskey, sigalg, why_bogus, LDNS_SECTION_ANSWER, NULL); if(sec == sec_status_secure) { return 1; @@ -7755,7 +7770,7 @@ static int nsec3_of_param_has_type(struct auth_rrset* nsec3, int algo, static int zonemd_check_dnssec_absence(struct auth_zone* z, struct module_env* env, struct module_stack* mods, struct ub_packed_rrset_key* dnskey, struct auth_data* apex, - char** reason, char** why_bogus) + char** reason, char** why_bogus, uint8_t* sigalg) { struct auth_rrset* nsec = NULL; if(!apex) { @@ -7767,7 +7782,7 @@ static int zonemd_check_dnssec_absence(struct auth_zone* z, struct ub_packed_rrset_key pk; /* dnssec verify the NSEC */ if(!zonemd_dnssec_verify_rrset(z, env, mods, dnskey, apex, - nsec, why_bogus)) { + nsec, why_bogus, sigalg)) { *reason = "DNSSEC verify failed for NSEC RRset"; return 0; } @@ -7810,7 +7825,7 @@ static int zonemd_check_dnssec_absence(struct auth_zone* z, } /* dnssec verify the NSEC3 */ if(!zonemd_dnssec_verify_rrset(z, env, mods, dnskey, match, - nsec3, why_bogus)) { + nsec3, why_bogus, sigalg)) { *reason = "DNSSEC verify failed for NSEC3 RRset"; return 0; } @@ -7831,7 +7846,8 @@ static int zonemd_check_dnssec_absence(struct auth_zone* z, static int zonemd_check_dnssec_soazonemd(struct auth_zone* z, struct module_env* env, struct module_stack* mods, struct ub_packed_rrset_key* dnskey, struct auth_data* apex, - struct auth_rrset* zonemd_rrset, char** reason, char** why_bogus) + struct auth_rrset* zonemd_rrset, char** reason, char** why_bogus, + uint8_t* sigalg) { struct auth_rrset* soa; if(!apex) { @@ -7844,12 +7860,12 @@ static int zonemd_check_dnssec_soazonemd(struct auth_zone* z, return 0; } if(!zonemd_dnssec_verify_rrset(z, env, mods, dnskey, apex, soa, - why_bogus)) { + why_bogus, sigalg)) { *reason = "DNSSEC verify failed for SOA RRset"; return 0; } if(!zonemd_dnssec_verify_rrset(z, env, mods, dnskey, apex, - zonemd_rrset, why_bogus)) { + zonemd_rrset, why_bogus, sigalg)) { *reason = "DNSSEC verify failed for ZONEMD RRset"; return 0; } @@ -7908,12 +7924,14 @@ static void auth_zone_zonemd_fail(struct auth_zone* z, struct module_env* env, * @param is_insecure: if true, the dnskey is not used, the zone is insecure. * And dnssec is not used. It is DNSSEC secure insecure or not under * a trust anchor. + * @param sigalg: if nonNULL provide algorithm downgrade protection. + * Otherwise one algorithm is enough. Must have space of ALGO_NEEDS_MAX+1. * @param result: if not NULL result reason copied here. */ static void auth_zone_verify_zonemd_with_key(struct auth_zone* z, struct module_env* env, struct module_stack* mods, struct ub_packed_rrset_key* dnskey, - int is_insecure, char** result) + int is_insecure, char** result, uint8_t* sigalg) { char* reason = NULL, *why_bogus = NULL; struct auth_data* apex = NULL; @@ -7943,7 +7961,7 @@ auth_zone_verify_zonemd_with_key(struct auth_zone* z, struct module_env* env, } else if(!zonemd_rrset && dnskey && !is_insecure) { /* fetch, DNSSEC verify, and check NSEC/NSEC3 */ if(!zonemd_check_dnssec_absence(z, env, mods, dnskey, apex, - &reason, &why_bogus)) { + &reason, &why_bogus, sigalg)) { auth_zone_zonemd_fail(z, env, reason, why_bogus, result); return; } @@ -7951,7 +7969,7 @@ auth_zone_verify_zonemd_with_key(struct auth_zone* z, struct module_env* env, } else if(zonemd_rrset && dnskey && !is_insecure) { /* check DNSSEC verify of SOA and ZONEMD */ if(!zonemd_check_dnssec_soazonemd(z, env, mods, dnskey, apex, - zonemd_rrset, &reason, &why_bogus)) { + zonemd_rrset, &reason, &why_bogus, sigalg)) { auth_zone_zonemd_fail(z, env, reason, why_bogus, result); return; } @@ -8065,15 +8083,78 @@ zonemd_get_dnskey_from_anchor(struct auth_zone* z, struct module_env* env, return NULL; } +/** verify the DNSKEY from the zone with looked up DS record */ +static struct ub_packed_rrset_key* +auth_zone_verify_zonemd_key_with_ds(struct auth_zone* z, + struct module_env* env, struct module_stack* mods, + struct ub_packed_rrset_key* ds, int* is_insecure, char** why_bogus, + struct ub_packed_rrset_key* keystorage, uint8_t* sigalg) +{ + struct auth_data* apex; + struct auth_rrset* dnskey_rrset; + enum sec_status sec; + struct val_env* ve; + int m; + + /* fetch DNSKEY from zone data */ + apex = az_find_name(z, z->name, z->namelen); + if(!apex) { + *why_bogus = "in verifywithDS, zone has no apex"; + return NULL; + } + dnskey_rrset = az_domain_rrset(apex, LDNS_RR_TYPE_DNSKEY); + if(!dnskey_rrset || dnskey_rrset->data->count==0) { + *why_bogus = "in verifywithDS, zone has no DNSKEY"; + return NULL; + } + + m = modstack_find(mods, "validator"); + if(m == -1) { + *why_bogus = "in verifywithDS, have no validator module"; + return NULL; + } + ve = (struct val_env*)env->modinfo[m]; + + memset(keystorage, 0, sizeof(*keystorage)); + keystorage->entry.key = keystorage; + keystorage->entry.data = dnskey_rrset->data; + keystorage->rk.dname = apex->name; + keystorage->rk.dname_len = apex->namelen; + keystorage->rk.type = htons(LDNS_RR_TYPE_DNSKEY); + keystorage->rk.rrset_class = htons(z->dclass); + auth_zone_log(z->name, VERB_QUERY, "zonemd: verify zone DNSKEY with DS"); + sec = val_verify_DNSKEY_with_DS(env, ve, keystorage, ds, sigalg, + why_bogus, NULL); + regional_free_all(env->scratch); + if(sec == sec_status_secure) { + /* success */ + return keystorage; + } else if(sec == sec_status_insecure) { + /* insecure */ + *is_insecure = 1; + } else { + /* bogus */ + *is_insecure = 0; + if(*why_bogus == NULL) + *why_bogus = "verify failed"; + auth_zone_log(z->name, VERB_ALGO, + "zonemd: verify DNSKEY RRset with DS failed: %s", + *why_bogus); + } + return NULL; +} + /** callback for ZONEMD lookup of DNSKEY */ void auth_zonemd_dnskey_lookup_callback(void* arg, int rcode, sldns_buffer* buf, enum sec_status sec, char* why_bogus, int ATTR_UNUSED(was_ratelimited)) { struct auth_zone* z = (struct auth_zone*)arg; struct module_env* env; - char* reason = NULL; - struct ub_packed_rrset_key* dnskey = NULL; - int is_insecure = 0; + char* reason = NULL, *ds_bogus = NULL, *typestr="DNSKEY"; + struct ub_packed_rrset_key* dnskey = NULL, *ds = NULL; + int is_insecure = 0, downprot; + struct ub_packed_rrset_key keystorage; + uint8_t sigalg[ALGO_NEEDS_MAX+1]; lock_rw_wrlock(&z->lock); env = z->zonemd_callback_env; @@ -8084,16 +8165,22 @@ void auth_zonemd_dnskey_lookup_callback(void* arg, int rcode, sldns_buffer* buf, lock_rw_unlock(&z->lock); return; /* stop on quit */ } + if(z->zonemd_callback_qtype == LDNS_RR_TYPE_DS) + typestr = "DS"; + downprot = env->cfg->harden_algo_downgrade; /* process result */ if(sec == sec_status_bogus) { reason = why_bogus; - if(!reason) - reason = "lookup of DNSKEY was bogus"; + if(!reason) { + if(z->zonemd_callback_qtype == LDNS_RR_TYPE_DNSKEY) + reason = "lookup of DNSKEY was bogus"; + else reason = "lookup of DS was bogus"; + } auth_zone_log(z->name, VERB_ALGO, - "zonemd lookup of DNSKEY was bogus: %s", reason); + "zonemd lookup of %s was bogus: %s", typestr, reason); } else if(rcode == LDNS_RCODE_NOERROR) { - uint16_t wanted_qtype = LDNS_RR_TYPE_DNSKEY; + uint16_t wanted_qtype = z->zonemd_callback_qtype; struct regional* temp = env->scratch; struct query_info rq; struct reply_info* rep; @@ -8106,25 +8193,29 @@ void auth_zonemd_dnskey_lookup_callback(void* arg, int rcode, sldns_buffer* buf, struct ub_packed_rrset_key* answer = reply_find_answer_rrset(&rq, rep); if(answer && sec == sec_status_secure) { - dnskey = answer; + if(z->zonemd_callback_qtype == LDNS_RR_TYPE_DNSKEY) + dnskey = answer; + else ds = answer; auth_zone_log(z->name, VERB_ALGO, - "zonemd lookup of DNSKEY was secure"); + "zonemd lookup of %s was secure", typestr); } else if(sec == sec_status_secure && !answer) { is_insecure = 1; auth_zone_log(z->name, VERB_ALGO, - "zonemd lookup of DNSKEY has no content, but is secure, treat as insecure"); + "zonemd lookup of %s has no content, but is secure, treat as insecure", typestr); } else if(sec == sec_status_insecure) { is_insecure = 1; auth_zone_log(z->name, VERB_ALGO, - "zonemd lookup of DNSKEY was insecure"); + "zonemd lookup of %s was insecure", typestr); } else if(sec == sec_status_indeterminate) { is_insecure = 1; auth_zone_log(z->name, VERB_ALGO, - "zonemd lookup of DNSKEY was indeterminate, treat as insecure"); + "zonemd lookup of %s was indeterminate, treat as insecure", typestr); } else { auth_zone_log(z->name, VERB_ALGO, - "zonemd lookup of DNSKEY has nodata"); - reason = "lookup of DNSKEY has nodata"; + "zonemd lookup of %s has nodata", typestr); + if(z->zonemd_callback_qtype == LDNS_RR_TYPE_DNSKEY) + reason = "lookup of DNSKEY has nodata"; + else reason = "lookup of DS has nodata"; } } else if(rep && rq.qtype == wanted_qtype && query_dname_compare(z->name, rq.qname) == 0 && @@ -8137,40 +8228,52 @@ void auth_zonemd_dnskey_lookup_callback(void* arg, int rcode, sldns_buffer* buf, * trust, as insecure. */ is_insecure = 1; auth_zone_log(z->name, VERB_ALGO, - "zonemd lookup of DNSKEY was secure NXDOMAIN, treat as insecure"); + "zonemd lookup of %s was secure NXDOMAIN, treat as insecure", typestr); } else if(rep && rq.qtype == wanted_qtype && query_dname_compare(z->name, rq.qname) == 0 && FLAGS_GET_RCODE(rep->flags) == LDNS_RCODE_NXDOMAIN && sec == sec_status_insecure) { is_insecure = 1; auth_zone_log(z->name, VERB_ALGO, - "zonemd lookup of DNSKEY was insecure NXDOMAIN, treat as insecure"); + "zonemd lookup of %s was insecure NXDOMAIN, treat as insecure", typestr); } else if(rep && rq.qtype == wanted_qtype && query_dname_compare(z->name, rq.qname) == 0 && FLAGS_GET_RCODE(rep->flags) == LDNS_RCODE_NXDOMAIN && sec == sec_status_indeterminate) { is_insecure = 1; auth_zone_log(z->name, VERB_ALGO, - "zonemd lookup of DNSKEY was indeterminate NXDOMAIN, treat as insecure"); + "zonemd lookup of %s was indeterminate NXDOMAIN, treat as insecure", typestr); } else { auth_zone_log(z->name, VERB_ALGO, - "zonemd lookup of DNSKEY has no answer"); - reason = "lookup of DNSKEY has no answer"; + "zonemd lookup of %s has no answer", typestr); + if(z->zonemd_callback_qtype == LDNS_RR_TYPE_DNSKEY) + reason = "lookup of DNSKEY has no answer"; + else reason = "lookup of DS has no answer"; } } else { auth_zone_log(z->name, VERB_ALGO, - "zonemd lookup of DNSKEY failed"); - reason = "lookup of DNSKEY failed"; + "zonemd lookup of %s failed", typestr); + if(z->zonemd_callback_qtype == LDNS_RR_TYPE_DNSKEY) + reason = "lookup of DNSKEY failed"; + else reason = "lookup of DS failed"; + } + + if(!reason && !is_insecure && !dnskey && ds) { + dnskey = auth_zone_verify_zonemd_key_with_ds(z, env, + &env->mesh->mods, ds, &is_insecure, &ds_bogus, + &keystorage, downprot?sigalg:NULL); + if(!dnskey && !is_insecure && !reason) + reason = "DNSKEY verify with DS failed"; } if(reason) { - auth_zone_zonemd_fail(z, env, reason, NULL, NULL); + auth_zone_zonemd_fail(z, env, reason, ds_bogus, NULL); lock_rw_unlock(&z->lock); return; } auth_zone_verify_zonemd_with_key(z, env, &env->mesh->mods, dnskey, - is_insecure, NULL); + is_insecure, NULL, downprot?sigalg:NULL); regional_free_all(env->scratch); lock_rw_unlock(&z->lock); } @@ -8183,14 +8286,21 @@ zonemd_lookup_dnskey(struct auth_zone* z, struct module_env* env) uint16_t qflags = BIT_RD; struct edns_data edns; sldns_buffer* buf = env->scratch_buffer; + int fetch_ds = 0; + if(!z->fallback_enabled) { + /* we cannot actually get the DNSKEY, because it is in the + * zone we have ourselves, and it is not served yet + * (possibly), so fetch type DS */ + fetch_ds = 1; + } if(z->zonemd_callback_env) { /* another worker is already working on the callback * for the DNSKEY lookup for ZONEMD verification. * We do not also have to do ZONEMD verification, let that * worker do it */ auth_zone_log(z->name, VERB_ALGO, - "zonemd needs lookup of DNSKEY and that already worked on by another worker"); + "zonemd needs lookup of %s and that already is worked on by another worker", (fetch_ds?"DS":"DNSKEY")); return 1; } @@ -8199,21 +8309,26 @@ zonemd_lookup_dnskey(struct auth_zone* z, struct module_env* env) qinfo.qname_len = z->namelen; qinfo.qname = z->name; qinfo.qclass = z->dclass; - qinfo.qtype = LDNS_RR_TYPE_DNSKEY; + if(fetch_ds) + qinfo.qtype = LDNS_RR_TYPE_DS; + else qinfo.qtype = LDNS_RR_TYPE_DNSKEY; qinfo.local_alias = NULL; if(verbosity >= VERB_ALGO) { char buf1[512]; char buf2[LDNS_MAX_DOMAINLEN+1]; dname_str(z->name, buf2); - snprintf(buf1, sizeof(buf1), "auth zone %s: lookup DNSKEY " - "for zonemd verification", buf2); + snprintf(buf1, sizeof(buf1), "auth zone %s: lookup %s " + "for zonemd verification", buf2, + (fetch_ds?"DS":"DNSKEY")); log_query_info(VERB_ALGO, buf1, &qinfo); } edns.edns_present = 1; edns.ext_rcode = 0; edns.edns_version = 0; edns.bits = EDNS_DO; - edns.opt_list = NULL; + edns.opt_list_in = NULL; + edns.opt_list_out = NULL; + edns.opt_list_inplace_cb_out = NULL; if(sldns_buffer_capacity(buf) < 65535) edns.udp_size = (uint16_t)sldns_buffer_capacity(buf); else edns.udp_size = 65535; @@ -8221,12 +8336,14 @@ zonemd_lookup_dnskey(struct auth_zone* z, struct module_env* env) /* store the worker-specific module env for the callback. * We can then reference this when the callback executes */ z->zonemd_callback_env = env; + z->zonemd_callback_qtype = qinfo.qtype; /* the callback can be called straight away */ lock_rw_unlock(&z->lock); if(!mesh_new_callback(env->mesh, &qinfo, qflags, &edns, buf, 0, &auth_zonemd_dnskey_lookup_callback, z)) { lock_rw_wrlock(&z->lock); - log_err("out of memory lookup up dnskey for zonemd"); + log_err("out of memory lookup of %s for zonemd", + (fetch_ds?"DS":"DNSKEY")); return 0; } lock_rw_wrlock(&z->lock); @@ -8245,6 +8362,8 @@ void auth_zone_verify_zonemd(struct auth_zone* z, struct module_env* env, * If not present check if absence is allowed by DNSSEC */ if(!z->zonemd_check) return; + if(z->data.count == 0) + return; /* no data */ /* if zone is under a trustanchor */ /* is it equal to trustanchor - get dnskey's verified */ @@ -8298,7 +8417,7 @@ void auth_zone_verify_zonemd(struct auth_zone* z, struct module_env* env, } auth_zone_verify_zonemd_with_key(z, env, mods, dnskey, is_insecure, - result); + result, NULL); regional_free_all(env->scratch); } diff --git a/contrib/unbound/services/authzone.h b/contrib/unbound/services/authzone.h index ffe234d59b53..d24e569d3b85 100644 --- a/contrib/unbound/services/authzone.h +++ b/contrib/unbound/services/authzone.h @@ -143,6 +143,8 @@ struct auth_zone { * worker has already picked up the zonemd verification task and * this worker does not have to do it as well. */ struct module_env* zonemd_callback_env; + /** for the zonemd callback, the type of data looked up */ + uint16_t zonemd_callback_qtype; /** zone has been deleted */ int zone_deleted; /** deletelist pointer, unused normally except during delete */ @@ -634,6 +636,9 @@ int auth_zones_startprobesequence(struct auth_zones* az, /** read auth zone from zonefile. caller must lock zone. false on failure */ int auth_zone_read_zonefile(struct auth_zone* z, struct config_file* cfg); +/** find the apex SOA RRset, if it exists. NULL if no SOA RRset. */ +struct auth_rrset* auth_zone_get_soa_rrset(struct auth_zone* z); + /** find serial number of zone or false if none (no SOA record) */ int auth_zone_get_serial(struct auth_zone* z, uint32_t* serial); diff --git a/contrib/unbound/services/cache/rrset.h b/contrib/unbound/services/cache/rrset.h index 35a0d732b048..7c36d4032ebc 100644 --- a/contrib/unbound/services/cache/rrset.h +++ b/contrib/unbound/services/cache/rrset.h @@ -120,7 +120,7 @@ void rrset_cache_touch(struct rrset_cache* r, struct ub_packed_rrset_key* key, * the new rrset. The reference may be changed if the cached rrset is * superior. * Before calling the rrset is presumed newly allocated and changeable. - * Afer calling you do not hold a lock, and the rrset is inserted in + * After calling you do not hold a lock, and the rrset is inserted in * the hashtable so you need a lock to change it. * @param alloc: how to allocate (and deallocate) the special rrset key. * @param timenow: current time (to see if ttl in cache is expired). @@ -143,7 +143,7 @@ int rrset_cache_update(struct rrset_cache* r, struct rrset_ref* ref, * @param rrset: which rrset to cache as wildcard. This rrset is left * untouched. * @param ce: the closest encloser, will be uses to generate the wildcard dname. - * @param ce_len: the closest encloser lenght. + * @param ce_len: the closest encloser length. * @param alloc: how to allocate (and deallocate) the special rrset key. * @param timenow: current time (to see if ttl in cache is expired). */ diff --git a/contrib/unbound/services/listen_dnsport.c b/contrib/unbound/services/listen_dnsport.c index b43def567501..6a33fbcdaf7e 100644 --- a/contrib/unbound/services/listen_dnsport.c +++ b/contrib/unbound/services/listen_dnsport.c @@ -869,9 +869,14 @@ set_ip_dscp(int socket, int addrfamily, int dscp) ds = dscp << 2; switch(addrfamily) { case AF_INET6: - if(setsockopt(socket, IPPROTO_IPV6, IPV6_TCLASS, (void*)&ds, sizeof(ds)) < 0) + #ifdef IPV6_TCLASS + if(setsockopt(socket, IPPROTO_IPV6, IPV6_TCLASS, (void*)&ds, + sizeof(ds)) < 0) return sock_strerror(errno); break; + #else + return "IPV6_TCLASS not defined on this system"; + #endif default: if(setsockopt(socket, IPPROTO_IP, IP_TOS, (void*)&ds, sizeof(ds)) < 0) return sock_strerror(errno); @@ -1306,6 +1311,38 @@ listen_cp_insert(struct comm_point* c, struct listen_dnsport* front) return 1; } +void listen_setup_locks(void) +{ + if(!stream_wait_lock_inited) { + lock_basic_init(&stream_wait_count_lock); + stream_wait_lock_inited = 1; + } + if(!http2_query_buffer_lock_inited) { + lock_basic_init(&http2_query_buffer_count_lock); + http2_query_buffer_lock_inited = 1; + } + if(!http2_response_buffer_lock_inited) { + lock_basic_init(&http2_response_buffer_count_lock); + http2_response_buffer_lock_inited = 1; + } +} + +void listen_desetup_locks(void) +{ + if(stream_wait_lock_inited) { + stream_wait_lock_inited = 0; + lock_basic_destroy(&stream_wait_count_lock); + } + if(http2_query_buffer_lock_inited) { + http2_query_buffer_lock_inited = 0; + lock_basic_destroy(&http2_query_buffer_count_lock); + } + if(http2_response_buffer_lock_inited) { + http2_response_buffer_lock_inited = 0; + lock_basic_destroy(&http2_response_buffer_count_lock); + } +} + struct listen_dnsport* listen_create(struct comm_base* base, struct listen_port* ports, size_t bufsize, int tcp_accept_count, int tcp_idle_timeout, @@ -1327,18 +1364,6 @@ listen_create(struct comm_base* base, struct listen_port* ports, free(front); return NULL; } - if(!stream_wait_lock_inited) { - lock_basic_init(&stream_wait_count_lock); - stream_wait_lock_inited = 1; - } - if(!http2_query_buffer_lock_inited) { - lock_basic_init(&http2_query_buffer_count_lock); - http2_query_buffer_lock_inited = 1; - } - if(!http2_response_buffer_lock_inited) { - lock_basic_init(&http2_response_buffer_count_lock); - http2_response_buffer_lock_inited = 1; - } /* create comm points as needed */ while(ports) { @@ -1454,18 +1479,6 @@ listen_delete(struct listen_dnsport* front) #endif sldns_buffer_free(front->udp_buff); free(front); - if(stream_wait_lock_inited) { - stream_wait_lock_inited = 0; - lock_basic_destroy(&stream_wait_count_lock); - } - if(http2_query_buffer_lock_inited) { - http2_query_buffer_lock_inited = 0; - lock_basic_destroy(&http2_query_buffer_count_lock); - } - if(http2_response_buffer_lock_inited) { - http2_response_buffer_lock_inited = 0; - lock_basic_destroy(&http2_response_buffer_count_lock); - } } #ifdef HAVE_GETIFADDRS @@ -2610,7 +2623,7 @@ static int http2_req_begin_headers_cb(nghttp2_session* session, int ret; if(frame->hd.type != NGHTTP2_HEADERS || frame->headers.cat != NGHTTP2_HCAT_REQUEST) { - /* only interrested in request headers */ + /* only interested in request headers */ return 0; } if(!(h2_stream = http2_stream_create(frame->hd.stream_id))) { @@ -2738,7 +2751,7 @@ static int http2_req_header_cb(nghttp2_session* session, * the HEADER */ if(frame->hd.type != NGHTTP2_HEADERS || frame->headers.cat != NGHTTP2_HCAT_REQUEST) { - /* only interrested in request headers */ + /* only interested in request headers */ return 0; } if(!(h2_stream = nghttp2_session_get_stream_user_data(session, @@ -2834,7 +2847,7 @@ static int http2_req_header_cb(nghttp2_session* session, h2_stream->query_too_large = 1; return 0; } - /* guaranteed to only contian digits and be null terminated */ + /* guaranteed to only contain digits and be null terminated */ h2_stream->content_length = atoi((const char*)value); if(h2_stream->content_length > h2_session->c->http2_stream_max_qbuffer_size) { @@ -2874,7 +2887,7 @@ static int http2_req_data_chunk_recv_cb(nghttp2_session* ATTR_UNUSED(session), /* setting this to msg-buffer-size can result in a lot * of memory consuption. Most queries should fit in a * single DATA frame, and most POST queries will - * containt content-length which does not impose this + * contain content-length which does not impose this * limit. */ qlen = len; } diff --git a/contrib/unbound/services/listen_dnsport.h b/contrib/unbound/services/listen_dnsport.h index 1e51be9bfcab..0e63236bcbce 100644 --- a/contrib/unbound/services/listen_dnsport.h +++ b/contrib/unbound/services/listen_dnsport.h @@ -199,6 +199,11 @@ listen_create(struct comm_base* base, struct listen_port* ports, */ void listen_delete(struct listen_dnsport* listen); +/** setup the locks for the listen ports */ +void listen_setup_locks(void); +/** desetup the locks for the listen ports */ +void listen_desetup_locks(void); + /** * delete listen_list of commpoints. Calls commpointdelete() on items. * This may close the fds or not depending on flags. diff --git a/contrib/unbound/services/localzone.c b/contrib/unbound/services/localzone.c index 54f55ab810e4..77d0107f9f6f 100644 --- a/contrib/unbound/services/localzone.c +++ b/contrib/unbound/services/localzone.c @@ -465,7 +465,7 @@ lz_find_create_node(struct local_zone* z, uint8_t* nm, size_t nmlen, /* Mark the SOA record for the zone. This only marks the SOA rrset; the data * for the RR is entered later on local_zone_enter_rr() as with the other - * records. An artifical soa_negative record with a modified TTL (minimum of + * records. An artificial soa_negative record with a modified TTL (minimum of * the TTL and the SOA.MINIMUM) is also created and marked for usage with * negative answers and to avoid allocations during those answers. */ static int @@ -898,6 +898,11 @@ int local_zone_enter_defaults(struct local_zones* zones, struct config_file* cfg } lock_rw_unlock(&z->lock); } + /* home.arpa. zone (RFC 8375) */ + if(!add_empty_default(zones, cfg, "home.arpa.")) { + log_err("out of memory adding default zone"); + return 0; + } /* onion. zone (RFC 7686) */ if(!add_empty_default(zones, cfg, "onion.")) { log_err("out of memory adding default zone"); @@ -1294,7 +1299,7 @@ local_error_encode(struct query_info* qinfo, struct module_env* env, if(!inplace_cb_reply_local_call(env, qinfo, NULL, NULL, rcode, edns, repinfo, temp, env->now_tv)) - edns->opt_list = NULL; + edns->opt_list_inplace_cb_out = NULL; error_encode(buf, r, qinfo, *(uint16_t*)sldns_buffer_begin(buf), sldns_buffer_read_u16_at(buf, 2), edns); } @@ -1521,7 +1526,7 @@ local_data_answer(struct local_zone* z, struct module_env* env, /* write qname */ memmove(d->rr_data[0] + sizeof(uint16_t), qinfo->qname, qinfo->qname_len - 1); - /* write cname target wilcard wildcard label */ + /* write cname target wildcard label */ memmove(d->rr_data[0] + sizeof(uint16_t) + qinfo->qname_len - 1, ctarget + 2, ctargetlen - 2); @@ -1570,6 +1575,15 @@ local_zone_does_not_cover(struct local_zone* z, struct query_info* qinfo, return (lr == NULL); } +static inline int +local_zone_is_udp_query(struct comm_reply* repinfo) { + return repinfo != NULL + ? (repinfo->c != NULL + ? repinfo->c->type == comm_udp + : 0) + : 0; +} + int local_zones_zone_answer(struct local_zone* z, struct module_env* env, struct query_info* qinfo, struct edns_data* edns, @@ -1592,7 +1606,9 @@ local_zones_zone_answer(struct local_zone* z, struct module_env* env, lz_type == local_zone_redirect || lz_type == local_zone_inform_redirect || lz_type == local_zone_always_nxdomain || - lz_type == local_zone_always_nodata) { + lz_type == local_zone_always_nodata || + (lz_type == local_zone_truncate + && local_zone_is_udp_query(repinfo))) { /* for static, reply nodata or nxdomain * for redirect, reply nodata */ /* no additional section processing, @@ -1602,9 +1618,11 @@ local_zones_zone_answer(struct local_zone* z, struct module_env* env, */ int rcode = (ld || lz_type == local_zone_redirect || lz_type == local_zone_inform_redirect || - lz_type == local_zone_always_nodata)? + lz_type == local_zone_always_nodata || + lz_type == local_zone_truncate)? LDNS_RCODE_NOERROR:LDNS_RCODE_NXDOMAIN; - if(z->soa && z->soa_negative) + rcode = (lz_type == local_zone_truncate ? (rcode|BIT_TC) : rcode); + if(z != NULL && z->soa && z->soa_negative) return local_encode(qinfo, env, edns, repinfo, buf, temp, z->soa_negative, 0, rcode); local_error_encode(qinfo, env, edns, repinfo, buf, temp, rcode, @@ -1661,7 +1679,7 @@ local_zones_zone_answer(struct local_zone* z, struct module_env* env, * does not, then we should make this noerror/nodata */ if(ld && ld->rrsets) { int rcode = LDNS_RCODE_NOERROR; - if(z->soa && z->soa_negative) + if(z != NULL && z->soa && z->soa_negative) return local_encode(qinfo, env, edns, repinfo, buf, temp, z->soa_negative, 0, rcode); local_error_encode(qinfo, env, edns, repinfo, buf, temp, rcode, @@ -1860,6 +1878,7 @@ const char* local_zone_type2str(enum localzone_type t) case local_zone_always_deny: return "always_deny"; case local_zone_always_null: return "always_null"; case local_zone_noview: return "noview"; + case local_zone_truncate: return "truncate"; case local_zone_invalid: return "invalid"; } return "badtyped"; @@ -1899,6 +1918,8 @@ int local_zone_str2type(const char* type, enum localzone_type* t) *t = local_zone_always_null; else if(strcmp(type, "noview") == 0) *t = local_zone_noview; + else if(strcmp(type, "truncate") == 0) + *t = local_zone_truncate; else if(strcmp(type, "nodefault") == 0) *t = local_zone_nodefault; else return 0; diff --git a/contrib/unbound/services/localzone.h b/contrib/unbound/services/localzone.h index b52d81dc72cb..19534f7509ed 100644 --- a/contrib/unbound/services/localzone.h +++ b/contrib/unbound/services/localzone.h @@ -101,6 +101,8 @@ enum localzone_type { local_zone_always_null, /** answer not from the view, but global or no-answer */ local_zone_noview, + /** truncate the response; client should retry via tcp */ + local_zone_truncate, /** Invalid type, cannot be used to generate answer */ local_zone_invalid }; @@ -255,7 +257,7 @@ void local_zone_delete(struct local_zone* z); * @param dclass: class to lookup. * @param dtype: type to lookup, if type DS a zone higher is used for zonecuts. * @param taglist: taglist to lookup. - * @param taglen: lenth of taglist. + * @param taglen: length of taglist. * @param ignoretags: lookup zone by name and class, regardless the * local-zone's tags. * @return closest local_zone or NULL if no covering zone is found. @@ -563,6 +565,8 @@ enum respip_action { respip_always_nodata = local_zone_always_nodata, /** answer with nodata response */ respip_always_deny = local_zone_always_deny, + /** RPZ: truncate answer in order to force switch to tcp */ + respip_truncate = local_zone_truncate, /* The rest of the values are only possible as * access-control-tag-action */ diff --git a/contrib/unbound/services/mesh.c b/contrib/unbound/services/mesh.c index 5679a8b64e58..cdcfedda270c 100644 --- a/contrib/unbound/services/mesh.c +++ b/contrib/unbound/services/mesh.c @@ -461,7 +461,7 @@ void mesh_new_client(struct mesh_area* mesh, struct query_info* qinfo, struct edns_data* edns, struct comm_reply* rep, uint16_t qid) { struct mesh_state* s = NULL; - int unique = unique_mesh_state(edns->opt_list, mesh->env); + int unique = unique_mesh_state(edns->opt_list_in, mesh->env); int was_detached = 0; int was_noreply = 0; int added = 0; @@ -505,7 +505,7 @@ void mesh_new_client(struct mesh_area* mesh, struct query_info* qinfo, log_err("mesh_state_create: out of memory; SERVFAIL"); if(!inplace_cb_reply_servfail_call(mesh->env, qinfo, NULL, NULL, LDNS_RCODE_SERVFAIL, edns, rep, mesh->env->scratch, mesh->env->now_tv)) - edns->opt_list = NULL; + edns->opt_list_inplace_cb_out = NULL; error_encode(r_buffer, LDNS_RCODE_SERVFAIL, qinfo, qid, qflags, edns); comm_point_send_reply(rep); @@ -514,14 +514,14 @@ void mesh_new_client(struct mesh_area* mesh, struct query_info* qinfo, if(unique) mesh_state_make_unique(s); /* copy the edns options we got from the front */ - if(edns->opt_list) { - s->s.edns_opts_front_in = edns_opt_copy_region(edns->opt_list, + if(edns->opt_list_in) { + s->s.edns_opts_front_in = edns_opt_copy_region(edns->opt_list_in, s->s.region); if(!s->s.edns_opts_front_in) { log_err("mesh_state_create: out of memory; SERVFAIL"); if(!inplace_cb_reply_servfail_call(mesh->env, qinfo, NULL, NULL, LDNS_RCODE_SERVFAIL, edns, rep, mesh->env->scratch, mesh->env->now_tv)) - edns->opt_list = NULL; + edns->opt_list_inplace_cb_out = NULL; error_encode(r_buffer, LDNS_RCODE_SERVFAIL, qinfo, qid, qflags, edns); comm_point_send_reply(rep); @@ -594,7 +594,7 @@ void mesh_new_client(struct mesh_area* mesh, struct query_info* qinfo, servfail_mem: if(!inplace_cb_reply_servfail_call(mesh->env, qinfo, &s->s, NULL, LDNS_RCODE_SERVFAIL, edns, rep, mesh->env->scratch, mesh->env->now_tv)) - edns->opt_list = NULL; + edns->opt_list_inplace_cb_out = NULL; error_encode(r_buffer, LDNS_RCODE_SERVFAIL, qinfo, qid, qflags, edns); comm_point_send_reply(rep); @@ -609,7 +609,7 @@ mesh_new_callback(struct mesh_area* mesh, struct query_info* qinfo, uint16_t qid, mesh_cb_func_type cb, void* cb_arg) { struct mesh_state* s = NULL; - int unique = unique_mesh_state(edns->opt_list, mesh->env); + int unique = unique_mesh_state(edns->opt_list_in, mesh->env); int timeout = mesh->env->cfg->serve_expired? mesh->env->cfg->serve_expired_client_timeout:0; int was_detached = 0; @@ -632,8 +632,8 @@ mesh_new_callback(struct mesh_area* mesh, struct query_info* qinfo, } if(unique) mesh_state_make_unique(s); - if(edns->opt_list) { - s->s.edns_opts_front_in = edns_opt_copy_region(edns->opt_list, + if(edns->opt_list_in) { + s->s.edns_opts_front_in = edns_opt_copy_region(edns->opt_list_in, s->s.region); if(!s->s.edns_opts_front_in) { return 0; @@ -1145,11 +1145,11 @@ mesh_do_callback(struct mesh_state* m, int rcode, struct reply_info* rep, if(rcode == LDNS_RCODE_SERVFAIL) { if(!inplace_cb_reply_servfail_call(m->s.env, &m->s.qinfo, &m->s, rep, rcode, &r->edns, NULL, m->s.region, start_time)) - r->edns.opt_list = NULL; + r->edns.opt_list_inplace_cb_out = NULL; } else { if(!inplace_cb_reply_call(m->s.env, &m->s.qinfo, &m->s, rep, rcode, &r->edns, NULL, m->s.region, start_time)) - r->edns.opt_list = NULL; + r->edns.opt_list_inplace_cb_out = NULL; } fptr_ok(fptr_whitelist_mesh_cb(r->cb)); (*r->cb)(r->cb_arg, rcode, r->buf, sec_status_unchecked, NULL, @@ -1183,6 +1183,22 @@ mesh_do_callback(struct mesh_state* m, int rcode, struct reply_info* rep, m->s.env->mesh->num_reply_addrs--; } +static inline int +mesh_is_rpz_respip_tcponly_action(struct mesh_state const* m) +{ + struct respip_action_info const* respip_info = m->s.respip_action_info; + return respip_info == NULL + ? 0 + : (respip_info->rpz_used + && !respip_info->rpz_disabled + && respip_info->action == respip_truncate); +} + +static inline int +mesh_is_udp(struct mesh_reply const* r) { + return r->query_reply.c->type == comm_udp; +} + /** * Send reply to mesh reply entry * @param m: mesh state to send it for. @@ -1201,15 +1217,17 @@ mesh_send_reply(struct mesh_state* m, int rcode, struct reply_info* rep, struct timeval end_time; struct timeval duration; int secure; - /* Copy the client's EDNS for later restore, to make sure the edns - * compare is with the correct edns options. */ - struct edns_data edns_bak = r->edns; /* briefly set the replylist to null in case the * meshsendreply calls tcpreqinfo sendreply that * comm_point_drops because of size, and then the * null stops the mesh state remove and thus * reply_list modification and accounting */ struct mesh_reply* rlist = m->reply_list; + + /* rpz: apply actions */ + rcode = mesh_is_udp(r) && mesh_is_rpz_respip_tcponly_action(m) + ? (rcode|BIT_TC) : rcode; + /* examine security status */ if(m->s.env->need_to_validate && (!(r->qflags&BIT_CD) || m->s.env->cfg->ignore_cd) && rep && @@ -1248,8 +1266,9 @@ mesh_send_reply(struct mesh_state* m, int rcode, struct reply_info* rep, prev->edns.edns_present == r->edns.edns_present && prev->edns.bits == r->edns.bits && prev->edns.udp_size == r->edns.udp_size && - edns_opt_list_compare(prev->edns.opt_list, r->edns.opt_list) - == 0) { + edns_opt_list_compare(prev->edns.opt_list_out, r->edns.opt_list_out) == 0 && + edns_opt_list_compare(prev->edns.opt_list_inplace_cb_out, r->edns.opt_list_inplace_cb_out) == 0 + ) { /* if the previous reply is identical to this one, fix ID */ if(prev_buffer != r_buffer) sldns_buffer_copy(r_buffer, prev_buffer); @@ -1265,11 +1284,11 @@ mesh_send_reply(struct mesh_state* m, int rcode, struct reply_info* rep, if(rcode == LDNS_RCODE_SERVFAIL) { if(!inplace_cb_reply_servfail_call(m->s.env, &m->s.qinfo, &m->s, rep, rcode, &r->edns, &r->query_reply, m->s.region, &r->start_time)) - r->edns.opt_list = NULL; + r->edns.opt_list_inplace_cb_out = NULL; } else { if(!inplace_cb_reply_call(m->s.env, &m->s.qinfo, &m->s, rep, rcode, &r->edns, &r->query_reply, m->s.region, &r->start_time)) - r->edns.opt_list = NULL; + r->edns.opt_list_inplace_cb_out = NULL; } error_encode(r_buffer, rcode, &m->s.qinfo, r->qid, r->qflags, &r->edns); @@ -1286,9 +1305,6 @@ mesh_send_reply(struct mesh_state* m, int rcode, struct reply_info* rep, m->s.qinfo.local_alias = r->local_alias; if(!inplace_cb_reply_call(m->s.env, &m->s.qinfo, &m->s, rep, LDNS_RCODE_NOERROR, &r->edns, &r->query_reply, m->s.region, &r->start_time) || - !apply_edns_options(&r->edns, &edns_bak, - m->s.env->cfg, r->query_reply.c, - m->s.region) || !reply_info_answer_encode(&m->s.qinfo, rep, r->qid, r->qflags, r_buffer, 0, 1, m->s.env->scratch, udp_size, &r->edns, (int)(r->edns.bits & EDNS_DO), @@ -1296,11 +1312,10 @@ mesh_send_reply(struct mesh_state* m, int rcode, struct reply_info* rep, { if(!inplace_cb_reply_servfail_call(m->s.env, &m->s.qinfo, &m->s, rep, LDNS_RCODE_SERVFAIL, &r->edns, &r->query_reply, m->s.region, &r->start_time)) - r->edns.opt_list = NULL; + r->edns.opt_list_inplace_cb_out = NULL; error_encode(r_buffer, LDNS_RCODE_SERVFAIL, &m->s.qinfo, r->qid, r->qflags, &r->edns); } - r->edns = edns_bak; m->reply_list = NULL; comm_point_send_reply(&r->query_reply); m->reply_list = rlist; @@ -1346,7 +1361,7 @@ void mesh_query_done(struct mesh_state* mstate) } if(mstate->s.return_rcode == LDNS_RCODE_SERVFAIL || (rep && FLAGS_GET_RCODE(rep->flags) == LDNS_RCODE_SERVFAIL)) { - /* we are SERVFAILing; check for expired asnwer here */ + /* we are SERVFAILing; check for expired answer here */ mesh_serve_expired_callback(mstate); if((mstate->reply_list || mstate->cb_list) && mstate->s.env->cfg->log_servfail @@ -1488,12 +1503,15 @@ int mesh_state_add_cb(struct mesh_state* s, struct edns_data* edns, r->cb = cb; r->cb_arg = cb_arg; r->edns = *edns; - if(edns->opt_list) { - r->edns.opt_list = edns_opt_copy_region(edns->opt_list, - s->s.region); - if(!r->edns.opt_list) - return 0; - } + if(edns->opt_list_in && !(r->edns.opt_list_in = + edns_opt_copy_region(edns->opt_list_in, s->s.region))) + return 0; + if(edns->opt_list_out && !(r->edns.opt_list_out = + edns_opt_copy_region(edns->opt_list_out, s->s.region))) + return 0; + if(edns->opt_list_inplace_cb_out && !(r->edns.opt_list_inplace_cb_out = + edns_opt_copy_region(edns->opt_list_inplace_cb_out, s->s.region))) + return 0; r->qid = qid; r->qflags = qflags; r->next = s->cb_list; @@ -1512,12 +1530,15 @@ int mesh_state_add_reply(struct mesh_state* s, struct edns_data* edns, return 0; r->query_reply = *rep; r->edns = *edns; - if(edns->opt_list) { - r->edns.opt_list = edns_opt_copy_region(edns->opt_list, - s->s.region); - if(!r->edns.opt_list) - return 0; - } + if(edns->opt_list_in && !(r->edns.opt_list_in = + edns_opt_copy_region(edns->opt_list_in, s->s.region))) + return 0; + if(edns->opt_list_out && !(r->edns.opt_list_out = + edns_opt_copy_region(edns->opt_list_out, s->s.region))) + return 0; + if(edns->opt_list_inplace_cb_out && !(r->edns.opt_list_inplace_cb_out = + edns_opt_copy_region(edns->opt_list_inplace_cb_out, s->s.region))) + return 0; r->qid = qid; r->qflags = qflags; r->start_time = *s->s.env->now_tv; @@ -1563,7 +1584,7 @@ int mesh_state_add_reply(struct mesh_state* s, struct edns_data* edns, return 0; /* the rrset is not packed, like in the cache, but it is - * individualy allocated with an allocator from localzone. */ + * individually allocated with an allocator from localzone. */ d = regional_alloc_zero(s->s.region, sizeof(*d)); if(!d) return 0; diff --git a/contrib/unbound/services/outbound_list.h b/contrib/unbound/services/outbound_list.h index ad59e42d1929..73c137d50993 100644 --- a/contrib/unbound/services/outbound_list.h +++ b/contrib/unbound/services/outbound_list.h @@ -79,7 +79,7 @@ void outbound_list_init(struct outbound_list* list); * Clear the user owner outbound list structure. * Deletes serviced queries. * @param list: the list structure. It is cleared, but the list struct itself - * is callers responsability to delete. + * is callers responsibility to delete. */ void outbound_list_clear(struct outbound_list* list); diff --git a/contrib/unbound/services/outside_network.c b/contrib/unbound/services/outside_network.c index a3f982e72185..f4a5d0707845 100644 --- a/contrib/unbound/services/outside_network.c +++ b/contrib/unbound/services/outside_network.c @@ -1935,7 +1935,7 @@ select_id(struct outside_network* outnet, struct pending* pend, LDNS_ID_SET(sldns_buffer_begin(packet), pend->id); id_tries++; if(id_tries == MAX_ID_RETRY) { - pend->id=99999; /* non existant ID */ + pend->id=99999; /* non existent ID */ log_err("failed to generate unique ID, drop msg"); return 0; } @@ -1962,6 +1962,7 @@ static int udp_connect_needs_log(int err) case ENETDOWN: # endif case EPERM: + case EACCES: if(verbosity >= VERB_ALGO) return 1; return 0; @@ -2708,7 +2709,9 @@ serviced_encode(struct serviced_query* sq, sldns_buffer* buff, int with_edns) edns.edns_present = 1; edns.ext_rcode = 0; edns.edns_version = EDNS_ADVERTISED_VERSION; - edns.opt_list = sq->opt_list; + edns.opt_list_in = NULL; + edns.opt_list_out = sq->opt_list; + edns.opt_list_inplace_cb_out = NULL; if(sq->status == serviced_query_UDP_EDNS_FRAG) { if(addr_is_ip6(&sq->addr, sq->addrlen)) { if(EDNS_FRAG_SIZE_IP6 < EDNS_ADVERTISED_SIZE) @@ -2731,8 +2734,8 @@ serviced_encode(struct serviced_query* sq, sldns_buffer* buff, int with_edns) padding_option.opt_code = LDNS_EDNS_PADDING; padding_option.opt_len = 0; padding_option.opt_data = NULL; - padding_option.next = edns.opt_list; - edns.opt_list = &padding_option; + padding_option.next = edns.opt_list_out; + edns.opt_list_out = &padding_option; edns.padding_block_size = sq->padding_block_size; } attach_edns_record(buff, &edns); diff --git a/contrib/unbound/services/rpz.c b/contrib/unbound/services/rpz.c index 3a1ec00d7d38..d408f9383d24 100644 --- a/contrib/unbound/services/rpz.c +++ b/contrib/unbound/services/rpz.c @@ -50,45 +50,50 @@ #include "util/data/dname.h" #include "util/locks.h" #include "util/regional.h" +#include "util/data/msgencode.h" +#include "services/cache/dns.h" +#include "iterator/iterator.h" +#include "iterator/iter_delegpt.h" +#include "daemon/worker.h" + +typedef struct resp_addr rpz_aclnode_type; + +struct matched_delegation_point { + uint8_t* dname; + size_t dname_len; +}; /** string for RPZ action enum */ const char* rpz_action_to_string(enum rpz_action a) { switch(a) { - case RPZ_NXDOMAIN_ACTION: return "nxdomain"; - case RPZ_NODATA_ACTION: return "nodata"; - case RPZ_PASSTHRU_ACTION: return "passthru"; - case RPZ_DROP_ACTION: return "drop"; - case RPZ_TCP_ONLY_ACTION: return "tcp_only"; - case RPZ_INVALID_ACTION: return "invalid"; - case RPZ_LOCAL_DATA_ACTION: return "local_data"; - case RPZ_DISABLED_ACTION: return "disabled"; - case RPZ_CNAME_OVERRIDE_ACTION: return "cname_override"; - case RPZ_NO_OVERRIDE_ACTION: return "no_override"; + case RPZ_NXDOMAIN_ACTION: return "rpz-nxdomain"; + case RPZ_NODATA_ACTION: return "rpz-nodata"; + case RPZ_PASSTHRU_ACTION: return "rpz-passthru"; + case RPZ_DROP_ACTION: return "rpz-drop"; + case RPZ_TCP_ONLY_ACTION: return "rpz-tcp-only"; + case RPZ_INVALID_ACTION: return "rpz-invalid"; + case RPZ_LOCAL_DATA_ACTION: return "rpz-local-data"; + case RPZ_DISABLED_ACTION: return "rpz-disabled"; + case RPZ_CNAME_OVERRIDE_ACTION: return "rpz-cname-override"; + case RPZ_NO_OVERRIDE_ACTION: return "rpz-no-override"; + default: return "rpz-unknown-action"; } - return "unknown"; } /** RPZ action enum for config string */ static enum rpz_action rpz_config_to_action(char* a) { - if(strcmp(a, "nxdomain") == 0) - return RPZ_NXDOMAIN_ACTION; - else if(strcmp(a, "nodata") == 0) - return RPZ_NODATA_ACTION; - else if(strcmp(a, "passthru") == 0) - return RPZ_PASSTHRU_ACTION; - else if(strcmp(a, "drop") == 0) - return RPZ_DROP_ACTION; - else if(strcmp(a, "tcp_only") == 0) - return RPZ_TCP_ONLY_ACTION; - else if(strcmp(a, "cname") == 0) - return RPZ_CNAME_OVERRIDE_ACTION; - else if(strcmp(a, "disabled") == 0) - return RPZ_DISABLED_ACTION; - return RPZ_INVALID_ACTION; + if(strcmp(a, "nxdomain") == 0) return RPZ_NXDOMAIN_ACTION; + else if(strcmp(a, "nodata") == 0) return RPZ_NODATA_ACTION; + else if(strcmp(a, "passthru") == 0) return RPZ_PASSTHRU_ACTION; + else if(strcmp(a, "drop") == 0) return RPZ_DROP_ACTION; + else if(strcmp(a, "tcp_only") == 0) return RPZ_TCP_ONLY_ACTION; + else if(strcmp(a, "cname") == 0) return RPZ_CNAME_OVERRIDE_ACTION; + else if(strcmp(a, "disabled") == 0) return RPZ_DISABLED_ACTION; + else return RPZ_INVALID_ACTION; } /** string for RPZ trigger enum */ @@ -96,14 +101,14 @@ static const char* rpz_trigger_to_string(enum rpz_trigger r) { switch(r) { - case RPZ_QNAME_TRIGGER: return "qname"; - case RPZ_CLIENT_IP_TRIGGER: return "client_ip"; - case RPZ_RESPONSE_IP_TRIGGER: return "response_ip"; - case RPZ_NSDNAME_TRIGGER: return "nsdname"; - case RPZ_NSIP_TRIGGER: return "nsip"; - case RPZ_INVALID_TRIGGER: return "invalid"; + case RPZ_QNAME_TRIGGER: return "rpz-qname"; + case RPZ_CLIENT_IP_TRIGGER: return "rpz-client-ip"; + case RPZ_RESPONSE_IP_TRIGGER: return "rpz-response-ip"; + case RPZ_NSDNAME_TRIGGER: return "rpz-nsdname"; + case RPZ_NSIP_TRIGGER: return "rpz-nsip"; + case RPZ_INVALID_TRIGGER: return "rpz-invalid"; + default: return "rpz-unknown-trigger"; } - return "unknown"; } /** @@ -137,6 +142,31 @@ get_tld_label(uint8_t* dname, size_t maxdnamelen) return prevlab; } +/** + * The RR types that are to be ignored. + * DNSSEC RRs at the apex, and SOA and NS are ignored. + */ +static int +rpz_type_ignored(uint16_t rr_type) +{ + switch(rr_type) { + case LDNS_RR_TYPE_SOA: + case LDNS_RR_TYPE_NS: + case LDNS_RR_TYPE_DNAME: + /* all DNSSEC-related RRs must be ignored */ + case LDNS_RR_TYPE_DNSKEY: + case LDNS_RR_TYPE_DS: + case LDNS_RR_TYPE_RRSIG: + case LDNS_RR_TYPE_NSEC: + case LDNS_RR_TYPE_NSEC3: + case LDNS_RR_TYPE_NSEC3PARAM: + return 1; + default: + break; + } + return 0; +} + /** * Classify RPZ action for RR type/rdata * @param rr_type: the RR type @@ -208,15 +238,15 @@ static enum localzone_type rpz_action_to_localzone_type(enum rpz_action a) { switch(a) { - case RPZ_NXDOMAIN_ACTION: return local_zone_always_nxdomain; - case RPZ_NODATA_ACTION: return local_zone_always_nodata; - case RPZ_DROP_ACTION: return local_zone_always_deny; - case RPZ_PASSTHRU_ACTION: return local_zone_always_transparent; + case RPZ_NXDOMAIN_ACTION: return local_zone_always_nxdomain; + case RPZ_NODATA_ACTION: return local_zone_always_nodata; + case RPZ_DROP_ACTION: return local_zone_always_deny; + case RPZ_PASSTHRU_ACTION: return local_zone_always_transparent; case RPZ_LOCAL_DATA_ACTION: /* fallthrough */ case RPZ_CNAME_OVERRIDE_ACTION: return local_zone_redirect; - case RPZ_INVALID_ACTION: /* fallthrough */ - case RPZ_TCP_ONLY_ACTION: /* fallthrough */ - default: return local_zone_invalid; + case RPZ_TCP_ONLY_ACTION: return local_zone_truncate; + case RPZ_INVALID_ACTION: /* fallthrough */ + default: return local_zone_invalid; } } @@ -224,15 +254,15 @@ enum respip_action rpz_action_to_respip_action(enum rpz_action a) { switch(a) { - case RPZ_NXDOMAIN_ACTION: return respip_always_nxdomain; - case RPZ_NODATA_ACTION: return respip_always_nodata; - case RPZ_DROP_ACTION: return respip_always_deny; - case RPZ_PASSTHRU_ACTION: return respip_always_transparent; - case RPZ_LOCAL_DATA_ACTION: /* fallthrough */ + case RPZ_NXDOMAIN_ACTION: return respip_always_nxdomain; + case RPZ_NODATA_ACTION: return respip_always_nodata; + case RPZ_DROP_ACTION: return respip_always_deny; + case RPZ_PASSTHRU_ACTION: return respip_always_transparent; + case RPZ_LOCAL_DATA_ACTION: /* fallthrough */ case RPZ_CNAME_OVERRIDE_ACTION: return respip_redirect; - case RPZ_INVALID_ACTION: /* fallthrough */ - case RPZ_TCP_ONLY_ACTION: /* fallthrough */ - default: return respip_invalid; + case RPZ_TCP_ONLY_ACTION: return respip_truncate; + case RPZ_INVALID_ACTION: /* fallthrough */ + default: return respip_invalid; } } @@ -240,14 +270,14 @@ static enum rpz_action localzone_type_to_rpz_action(enum localzone_type lzt) { switch(lzt) { - case local_zone_always_nxdomain: return RPZ_NXDOMAIN_ACTION; - case local_zone_always_nodata: return RPZ_NODATA_ACTION; - case local_zone_always_deny: return RPZ_DROP_ACTION; - case local_zone_always_transparent: return RPZ_PASSTHRU_ACTION; - case local_zone_redirect: return RPZ_LOCAL_DATA_ACTION; - case local_zone_invalid: - default: - return RPZ_INVALID_ACTION; + case local_zone_always_nxdomain: return RPZ_NXDOMAIN_ACTION; + case local_zone_always_nodata: return RPZ_NODATA_ACTION; + case local_zone_always_deny: return RPZ_DROP_ACTION; + case local_zone_always_transparent: return RPZ_PASSTHRU_ACTION; + case local_zone_redirect: return RPZ_LOCAL_DATA_ACTION; + case local_zone_truncate: return RPZ_TCP_ONLY_ACTION; + case local_zone_invalid: /* fallthrough */ + default: return RPZ_INVALID_ACTION; } } @@ -255,14 +285,14 @@ enum rpz_action respip_action_to_rpz_action(enum respip_action a) { switch(a) { - case respip_always_nxdomain: return RPZ_NXDOMAIN_ACTION; - case respip_always_nodata: return RPZ_NODATA_ACTION; - case respip_always_deny: return RPZ_DROP_ACTION; - case respip_always_transparent: return RPZ_PASSTHRU_ACTION; - case respip_redirect: return RPZ_LOCAL_DATA_ACTION; - case respip_invalid: - default: - return RPZ_INVALID_ACTION; + case respip_always_nxdomain: return RPZ_NXDOMAIN_ACTION; + case respip_always_nodata: return RPZ_NODATA_ACTION; + case respip_always_deny: return RPZ_DROP_ACTION; + case respip_always_transparent: return RPZ_PASSTHRU_ACTION; + case respip_redirect: return RPZ_LOCAL_DATA_ACTION; + case respip_truncate: return RPZ_TCP_ONLY_ACTION; + case respip_invalid: /* fallthrough */ + default: return RPZ_INVALID_ACTION; } } @@ -298,12 +328,55 @@ rpz_dname_to_trigger(uint8_t* dname, size_t dname_len) return RPZ_QNAME_TRIGGER; } -void rpz_delete(struct rpz* r) +static inline struct clientip_synthesized_rrset* +rpz_clientip_synthesized_set_create(void) +{ + struct clientip_synthesized_rrset* set = calloc(1, sizeof(*set)); + if(set == NULL) { + return NULL; + } + set->region = regional_create(); + if(set->region == NULL) { + free(set); + return NULL; + } + addr_tree_init(&set->entries); + lock_rw_init(&set->lock); + return set; +} + +static void +rpz_clientip_synthesized_rr_delete(rbnode_type* n, void* ATTR_UNUSED(arg)) +{ + struct clientip_synthesized_rr* r = (struct clientip_synthesized_rr*)n->key; + lock_rw_destroy(&r->lock); +#ifdef THREADS_DISABLED + (void)r; +#endif +} + +static inline void +rpz_clientip_synthesized_set_delete(struct clientip_synthesized_rrset* set) +{ + if(set == NULL) { + return; + } + lock_rw_destroy(&set->lock); + traverse_postorder(&set->entries, rpz_clientip_synthesized_rr_delete, NULL); + regional_destroy(set->region); + free(set); +} + +void +rpz_delete(struct rpz* r) { if(!r) return; local_zones_delete(r->local_zones); + local_zones_delete(r->nsdname_zones); respip_set_delete(r->respip_set); + rpz_clientip_synthesized_set_delete(r->client_set); + rpz_clientip_synthesized_set_delete(r->ns_set); regional_destroy(r->region); free(r->taglist); free(r->log_name); @@ -315,13 +388,31 @@ rpz_clear(struct rpz* r) { /* must hold write lock on auth_zone */ local_zones_delete(r->local_zones); + r->local_zones = NULL; + local_zones_delete(r->nsdname_zones); + r->nsdname_zones = NULL; respip_set_delete(r->respip_set); + r->respip_set = NULL; + rpz_clientip_synthesized_set_delete(r->client_set); + r->client_set = NULL; + rpz_clientip_synthesized_set_delete(r->ns_set); + r->ns_set = NULL; if(!(r->local_zones = local_zones_create())){ return 0; } + r->nsdname_zones = local_zones_create(); + if(r->nsdname_zones == NULL) { + return 0; + } if(!(r->respip_set = respip_set_create())) { return 0; } + if(!(r->client_set = rpz_clientip_synthesized_set_create())) { + return 0; + } + if(!(r->ns_set = rpz_clientip_synthesized_set_create())) { + return 0; + } return 1; } @@ -331,6 +422,14 @@ rpz_finish_config(struct rpz* r) lock_rw_wrlock(&r->respip_set->lock); addr_tree_init_parents(&r->respip_set->ip_tree); lock_rw_unlock(&r->respip_set->lock); + + lock_rw_wrlock(&r->client_set->lock); + addr_tree_init_parents(&r->client_set->entries); + lock_rw_unlock(&r->client_set->lock); + + lock_rw_wrlock(&r->ns_set->lock); + addr_tree_init_parents(&r->ns_set->entries); + lock_rw_unlock(&r->ns_set->lock); } /** new rrset containing CNAME override, does not yet contain a dname */ @@ -394,9 +493,26 @@ rpz_create(struct config_auth* p) if(!(r->local_zones = local_zones_create())){ goto err; } + + r->nsdname_zones = local_zones_create(); + if(r->local_zones == NULL){ + goto err; + } + if(!(r->respip_set = respip_set_create())) { goto err; } + + r->client_set = rpz_clientip_synthesized_set_create(); + if(r->client_set == NULL) { + goto err; + } + + r->ns_set = rpz_clientip_synthesized_set_create(); + if(r->ns_set == NULL) { + goto err; + } + r->taglistlen = p->rpz_taglistlen; r->taglist = memdup(p->rpz_taglist, r->taglistlen); if(p->rpz_action_override) { @@ -437,8 +553,14 @@ rpz_create(struct config_auth* p) if(r) { if(r->local_zones) local_zones_delete(r->local_zones); + if(r->nsdname_zones) + local_zones_delete(r->nsdname_zones); if(r->respip_set) respip_set_delete(r->respip_set); + if(r->client_set != NULL) + rpz_clientip_synthesized_set_delete(r->client_set); + if(r->ns_set != NULL) + rpz_clientip_synthesized_set_delete(r->ns_set); if(r->taglist) free(r->taglist); if(r->region) @@ -467,19 +589,17 @@ strip_dname_origin(uint8_t* dname, size_t dnamelen, size_t originlen, return newdnamelen + 1; /* + 1 for root label */ } -/** Insert RR into RPZ's local-zone */ static void -rpz_insert_qname_trigger(struct rpz* r, uint8_t* dname, size_t dnamelen, - enum rpz_action a, uint16_t rrtype, uint16_t rrclass, uint32_t ttl, - uint8_t* rdata, size_t rdata_len, uint8_t* rr, size_t rr_len) +rpz_insert_local_zones_trigger(struct local_zones* lz, uint8_t* dname, + size_t dnamelen, enum rpz_action a, uint16_t rrtype, uint16_t rrclass, + uint32_t ttl, uint8_t* rdata, size_t rdata_len, uint8_t* rr, size_t rr_len) { struct local_zone* z; enum localzone_type tp = local_zone_always_transparent; int dnamelabs = dname_count_labels(dname); - char* rrstr; int newzone = 0; - if(a == RPZ_TCP_ONLY_ACTION || a == RPZ_INVALID_ACTION) { + if(a == RPZ_INVALID_ACTION) { char str[255+1]; if(rrtype == LDNS_RR_TYPE_SOA || rrtype == LDNS_RR_TYPE_NS || rrtype == LDNS_RR_TYPE_DNAME || @@ -499,56 +619,360 @@ rpz_insert_qname_trigger(struct rpz* r, uint8_t* dname, size_t dnamelen, return; } - lock_rw_wrlock(&r->local_zones->lock); + lock_rw_wrlock(&lz->lock); /* exact match */ - z = local_zones_find(r->local_zones, dname, dnamelen, dnamelabs, - LDNS_RR_CLASS_IN); - if(z && a != RPZ_LOCAL_DATA_ACTION) { - rrstr = sldns_wire2str_rr(rr, rr_len); - if(!rrstr) { - log_err("malloc error while inserting RPZ qname " - "trigger"); + z = local_zones_find(lz, dname, dnamelen, dnamelabs, LDNS_RR_CLASS_IN); + if(z != NULL && a != RPZ_LOCAL_DATA_ACTION) { + char* rrstr = sldns_wire2str_rr(rr, rr_len); + if(rrstr == NULL) { + log_err("malloc error while inserting rpz nsdname trigger"); free(dname); - lock_rw_unlock(&r->local_zones->lock); + lock_rw_unlock(&lz->lock); return; } - verbose(VERB_ALGO, "RPZ: skipping duplicate record: '%s'", - rrstr); + if(rrstr[0]) + rrstr[strlen(rrstr)-1]=0; /* remove newline */ + verbose(VERB_ALGO, "rpz: skipping duplicate record: '%s'", rrstr); free(rrstr); free(dname); - lock_rw_unlock(&r->local_zones->lock); + lock_rw_unlock(&lz->lock); return; } - if(!z) { + if(z == NULL) { tp = rpz_action_to_localzone_type(a); - if(!(z = local_zones_add_zone(r->local_zones, dname, dnamelen, - dnamelabs, rrclass, tp))) { - log_warn("RPZ create failed"); - lock_rw_unlock(&r->local_zones->lock); + z = local_zones_add_zone(lz, dname, dnamelen, + dnamelabs, rrclass, tp); + if(z == NULL) { + log_warn("rpz: create failed"); + lock_rw_unlock(&lz->lock); /* dname will be free'd in failed local_zone_create() */ return; } newzone = 1; } if(a == RPZ_LOCAL_DATA_ACTION) { - rrstr = sldns_wire2str_rr(rr, rr_len); - if(!rrstr) { - log_err("malloc error while inserting RPZ qname " - "trigger"); + char* rrstr = sldns_wire2str_rr(rr, rr_len); + if(rrstr == NULL) { + log_err("malloc error while inserting rpz nsdname trigger"); free(dname); - lock_rw_unlock(&r->local_zones->lock); + lock_rw_unlock(&lz->lock); return; } lock_rw_wrlock(&z->lock); - local_zone_enter_rr(z, dname, dnamelen, dnamelabs, - rrtype, rrclass, ttl, rdata, rdata_len, rrstr); + local_zone_enter_rr(z, dname, dnamelen, dnamelabs, rrtype, + rrclass, ttl, rdata, rdata_len, rrstr); lock_rw_unlock(&z->lock); free(rrstr); } - if(!newzone) + if(!newzone) { free(dname); - lock_rw_unlock(&r->local_zones->lock); - return; + } + lock_rw_unlock(&lz->lock); +} + +static void +rpz_log_dname(char const* msg, uint8_t* dname, size_t dname_len) +{ + char buf[LDNS_MAX_DOMAINLEN+1]; + (void)dname_len; + dname_str(dname, buf); + verbose(VERB_ALGO, "rpz: %s: <%s>", msg, buf); +} + +static void +rpz_insert_qname_trigger(struct rpz* r, uint8_t* dname, size_t dnamelen, + enum rpz_action a, uint16_t rrtype, uint16_t rrclass, uint32_t ttl, + uint8_t* rdata, size_t rdata_len, uint8_t* rr, size_t rr_len) +{ + if(a == RPZ_INVALID_ACTION) { + verbose(VERB_ALGO, "rpz: skipping invalid action"); + free(dname); + return; + } + + rpz_insert_local_zones_trigger(r->local_zones, dname, dnamelen, a, rrtype, + rrclass, ttl, rdata, rdata_len, rr, rr_len); +} + +static int +rpz_strip_nsdname_suffix(uint8_t* dname, size_t maxdnamelen, + uint8_t** stripdname, size_t* stripdnamelen) +{ + uint8_t* tldstart = get_tld_label(dname, maxdnamelen); + uint8_t swap; + if(tldstart == NULL) { + if(dname == NULL) { + *stripdname = NULL; + *stripdnamelen = 0; + return 0; + } + *stripdname = memdup(dname, maxdnamelen); + if(!*stripdname) { + *stripdnamelen = 0; + log_err("malloc failure for rpz strip suffix"); + return 0; + } + *stripdnamelen = maxdnamelen; + return 1; + } + /* shorten the domain name briefly, + * then we allocate a new name with the correct length */ + swap = *tldstart; + *tldstart = 0; + (void)dname_count_size_labels(dname, stripdnamelen); + *stripdname = memdup(dname, *stripdnamelen); + *tldstart = swap; + if(!*stripdname) { + *stripdnamelen = 0; + log_err("malloc failure for rpz strip suffix"); + return 0; + } + return 1; +} + +static void +rpz_insert_nsdname_trigger(struct rpz* r, uint8_t* dname, size_t dnamelen, + enum rpz_action a, uint16_t rrtype, uint16_t rrclass, uint32_t ttl, + uint8_t* rdata, size_t rdata_len, uint8_t* rr, size_t rr_len) +{ + uint8_t* dname_stripped = NULL; + size_t dnamelen_stripped = 0; + + rpz_strip_nsdname_suffix(dname, dnamelen, &dname_stripped, + &dnamelen_stripped); + if(a == RPZ_INVALID_ACTION) { + verbose(VERB_ALGO, "rpz: skipping invalid action"); + free(dname_stripped); + return; + } + + /* dname_stripped is consumed or freed by the insert routine */ + rpz_insert_local_zones_trigger(r->nsdname_zones, dname_stripped, + dnamelen_stripped, a, rrtype, rrclass, ttl, rdata, rdata_len, + rr, rr_len); +} + +static int +rpz_insert_ipaddr_based_trigger(struct respip_set* set, struct sockaddr_storage* addr, + socklen_t addrlen, int net, enum rpz_action a, uint16_t rrtype, + uint16_t rrclass, uint32_t ttl, uint8_t* rdata, size_t rdata_len, + uint8_t* rr, size_t rr_len) +{ + struct resp_addr* node; + char* rrstr; + enum respip_action respa = rpz_action_to_respip_action(a); + + lock_rw_wrlock(&set->lock); + rrstr = sldns_wire2str_rr(rr, rr_len); + if(rrstr == NULL) { + log_err("malloc error while inserting rpz ipaddr based trigger"); + lock_rw_unlock(&set->lock); + return 0; + } + + node = respip_sockaddr_find_or_create(set, addr, addrlen, net, 1, rrstr); + if(node == NULL) { + lock_rw_unlock(&set->lock); + free(rrstr); + return 0; + } + + lock_rw_wrlock(&node->lock); + lock_rw_unlock(&set->lock); + + node->action = respa; + + if(a == RPZ_LOCAL_DATA_ACTION) { + respip_enter_rr(set->region, node, rrtype, + rrclass, ttl, rdata, rdata_len, rrstr, ""); + } + + lock_rw_unlock(&node->lock); + free(rrstr); + return 1; +} + +static inline struct clientip_synthesized_rr* +rpz_clientip_ensure_entry(struct clientip_synthesized_rrset* set, + struct sockaddr_storage* addr, socklen_t addrlen, int net) +{ + int insert_ok; + struct clientip_synthesized_rr* node = + (struct clientip_synthesized_rr*)addr_tree_find(&set->entries, + addr, addrlen, net); + + if(node != NULL) { return node; } + + /* node does not yet exist => allocate one */ + node = regional_alloc_zero(set->region, sizeof(*node)); + if(node == NULL) { + log_err("out of memory"); + return NULL; + } + + lock_rw_init(&node->lock); + node->action = RPZ_INVALID_ACTION; + insert_ok = addr_tree_insert(&set->entries, &node->node, + addr, addrlen, net); + if (!insert_ok) { + log_warn("rpz: unexpected: unable to insert clientip address node"); + /* we can not free the just allocated node. + * theoretically a memleak */ + return NULL; + } + + return node; +} + +static void +rpz_report_rrset_error(const char* msg, uint8_t* rr, size_t rr_len) { + char* rrstr = sldns_wire2str_rr(rr, rr_len); + if(rrstr == NULL) { + log_err("malloc error while inserting rpz clientip based record"); + return; + } + log_err("rpz: unexpected: unable to insert %s: %s", msg, rrstr); + free(rrstr); +} + +/* from localzone.c; difference is we don't have a dname */ +struct local_rrset* +rpz_clientip_new_rrset(struct regional* region, + struct clientip_synthesized_rr* raddr, uint16_t rrtype, uint16_t rrclass) +{ + struct packed_rrset_data* pd; + struct local_rrset* rrset = (struct local_rrset*) + regional_alloc_zero(region, sizeof(*rrset)); + if(rrset == NULL) { + log_err("out of memory"); + return NULL; + } + rrset->next = raddr->data; + raddr->data = rrset; + rrset->rrset = (struct ub_packed_rrset_key*) + regional_alloc_zero(region, sizeof(*rrset->rrset)); + if(rrset->rrset == NULL) { + log_err("out of memory"); + return NULL; + } + rrset->rrset->entry.key = rrset->rrset; + pd = (struct packed_rrset_data*)regional_alloc_zero(region, sizeof(*pd)); + if(pd == NULL) { + log_err("out of memory"); + return NULL; + } + pd->trust = rrset_trust_prim_noglue; + pd->security = sec_status_insecure; + rrset->rrset->entry.data = pd; + rrset->rrset->rk.type = htons(rrtype); + rrset->rrset->rk.rrset_class = htons(rrclass); + rrset->rrset->rk.dname = regional_alloc_zero(region, 1); + if(rrset->rrset->rk.dname == NULL) { + log_err("out of memory"); + return NULL; + } + rrset->rrset->rk.dname_len = 1; + return rrset; +} + +static int +rpz_clientip_enter_rr(struct regional* region, struct clientip_synthesized_rr* raddr, + uint16_t rrtype, uint16_t rrclass, time_t ttl, uint8_t* rdata, + size_t rdata_len) +{ + struct local_rrset* rrset; + if (rrtype == LDNS_RR_TYPE_CNAME && raddr->data != NULL) { + log_err("CNAME response-ip data can not co-exist with other " + "client-ip data"); + return 0; + } + + rrset = rpz_clientip_new_rrset(region, raddr, rrtype, rrclass); + if(raddr->data == NULL) { + return 0; + } + + return rrset_insert_rr(region, rrset->rrset->entry.data, rdata, rdata_len, ttl, ""); +} + +static int +rpz_clientip_insert_trigger_rr(struct clientip_synthesized_rrset* set, struct sockaddr_storage* addr, + socklen_t addrlen, int net, enum rpz_action a, uint16_t rrtype, + uint16_t rrclass, uint32_t ttl, uint8_t* rdata, size_t rdata_len, + uint8_t* rr, size_t rr_len) +{ + struct clientip_synthesized_rr* node; + + lock_rw_wrlock(&set->lock); + + node = rpz_clientip_ensure_entry(set, addr, addrlen, net); + if(node == NULL) { + lock_rw_unlock(&set->lock); + rpz_report_rrset_error("client ip address", rr, rr_len); + return 0; + } + + lock_rw_wrlock(&node->lock); + lock_rw_unlock(&set->lock); + + node->action = a; + if(a == RPZ_LOCAL_DATA_ACTION) { + if(!rpz_clientip_enter_rr(set->region, node, rrtype, + rrclass, ttl, rdata, rdata_len)) { + verbose(VERB_ALGO, "rpz: unable to insert clientip rr"); + lock_rw_unlock(&node->lock); + return 0; + } + + } + + lock_rw_unlock(&node->lock); + + return 1; +} + +static int +rpz_insert_clientip_trigger(struct rpz* r, uint8_t* dname, size_t dnamelen, + enum rpz_action a, uint16_t rrtype, uint16_t rrclass, uint32_t ttl, + uint8_t* rdata, size_t rdata_len, uint8_t* rr, size_t rr_len) +{ + struct sockaddr_storage addr; + socklen_t addrlen; + int net, af; + + if(a == RPZ_INVALID_ACTION) { + return 0; + } + + if(!netblockdnametoaddr(dname, dnamelen, &addr, &addrlen, &net, &af)) { + verbose(VERB_ALGO, "rpz: unable to parse client ip"); + return 0; + } + + return rpz_clientip_insert_trigger_rr(r->client_set, &addr, addrlen, net, + a, rrtype, rrclass, ttl, rdata, rdata_len, rr, rr_len); +} + +static int +rpz_insert_nsip_trigger(struct rpz* r, uint8_t* dname, size_t dnamelen, + enum rpz_action a, uint16_t rrtype, uint16_t rrclass, uint32_t ttl, + uint8_t* rdata, size_t rdata_len, uint8_t* rr, size_t rr_len) +{ + struct sockaddr_storage addr; + socklen_t addrlen; + int net, af; + + if(a == RPZ_INVALID_ACTION) { + return 0; + } + + if(!netblockdnametoaddr(dname, dnamelen, &addr, &addrlen, &net, &af)) { + verbose(VERB_ALGO, "rpz: unable to parse ns ip"); + return 0; + } + + return rpz_clientip_insert_trigger_rr(r->ns_set, &addr, addrlen, net, + a, rrtype, rrclass, ttl, rdata, rdata_len, rr, rr_len); } /** Insert RR into RPZ's respip_set */ @@ -557,15 +981,21 @@ rpz_insert_response_ip_trigger(struct rpz* r, uint8_t* dname, size_t dnamelen, enum rpz_action a, uint16_t rrtype, uint16_t rrclass, uint32_t ttl, uint8_t* rdata, size_t rdata_len, uint8_t* rr, size_t rr_len) { - struct resp_addr* node; struct sockaddr_storage addr; socklen_t addrlen; int net, af; - char* rrstr; - enum respip_action respa = rpz_action_to_respip_action(a); - if(a == RPZ_TCP_ONLY_ACTION || a == RPZ_INVALID_ACTION || - respa == respip_invalid) { + if(a == RPZ_INVALID_ACTION) { + return 0; + } + + if(!netblockdnametoaddr(dname, dnamelen, &addr, &addrlen, &net, &af)) { + verbose(VERB_ALGO, "rpz: unable to parse response ip"); + return 0; + } + + if(a == RPZ_INVALID_ACTION || + rpz_action_to_respip_action(a) == respip_invalid) { char str[255+1]; dname_str(dname, str); verbose(VERB_ALGO, "RPZ: respip trigger, %s skipping unsupported action: %s", @@ -573,34 +1003,8 @@ rpz_insert_response_ip_trigger(struct rpz* r, uint8_t* dname, size_t dnamelen, return 0; } - if(!netblockdnametoaddr(dname, dnamelen, &addr, &addrlen, &net, &af)) - return 0; - - lock_rw_wrlock(&r->respip_set->lock); - rrstr = sldns_wire2str_rr(rr, rr_len); - if(!rrstr) { - log_err("malloc error while inserting RPZ respip trigger"); - lock_rw_unlock(&r->respip_set->lock); - return 0; - } - if(!(node=respip_sockaddr_find_or_create(r->respip_set, &addr, addrlen, - net, 1, rrstr))) { - lock_rw_unlock(&r->respip_set->lock); - free(rrstr); - return 0; - } - - lock_rw_wrlock(&node->lock); - lock_rw_unlock(&r->respip_set->lock); - node->action = respa; - - if(a == RPZ_LOCAL_DATA_ACTION) { - respip_enter_rr(r->respip_set->region, node, rrtype, - rrclass, ttl, rdata, rdata_len, rrstr, ""); - } - lock_rw_unlock(&node->lock); - free(rrstr); - return 1; + return rpz_insert_ipaddr_based_trigger(r->respip_set, &addr, addrlen, net, + a, rrtype, rrclass, ttl, rdata, rdata_len, rr, rr_len); } int @@ -614,15 +1018,19 @@ rpz_insert_rr(struct rpz* r, uint8_t* azname, size_t aznamelen, uint8_t* dname, enum rpz_action a; uint8_t* policydname; + if(rpz_type_ignored(rr_type)) { + /* this rpz action is not valid, eg. this is the SOA or NS RR */ + return 1; + } if(!dname_subdomain_c(dname, azname)) { char* dname_str = sldns_wire2str_dname(dname, dnamelen); char* azname_str = sldns_wire2str_dname(azname, aznamelen); if(dname_str && azname_str) { - log_err("RPZ: name of record (%s) to insert into RPZ is not a " + log_err("rpz: name of record (%s) to insert into RPZ is not a " "subdomain of the configured name of the RPZ zone (%s)", dname_str, azname_str); } else { - log_err("RPZ: name of record to insert into RPZ is not a " + log_err("rpz: name of record to insert into RPZ is not a " "subdomain of the configured name of the RPZ zone"); } free(dname_str); @@ -645,23 +1053,37 @@ rpz_insert_rr(struct rpz* r, uint8_t* azname, size_t aznamelen, uint8_t* dname, t = rpz_dname_to_trigger(policydname, policydnamelen); if(t == RPZ_INVALID_TRIGGER) { free(policydname); - verbose(VERB_ALGO, "RPZ: skipping invalid trigger"); + verbose(VERB_ALGO, "rpz: skipping invalid trigger"); return 1; } if(t == RPZ_QNAME_TRIGGER) { + /* policydname will be consumed, no free */ rpz_insert_qname_trigger(r, policydname, policydnamelen, a, rr_type, rr_class, rr_ttl, rdatawl, rdatalen, rr, rr_len); - } - else if(t == RPZ_RESPONSE_IP_TRIGGER) { + } else if(t == RPZ_RESPONSE_IP_TRIGGER) { rpz_insert_response_ip_trigger(r, policydname, policydnamelen, a, rr_type, rr_class, rr_ttl, rdatawl, rdatalen, rr, rr_len); free(policydname); - } - else { + } else if(t == RPZ_CLIENT_IP_TRIGGER) { + rpz_insert_clientip_trigger(r, policydname, policydnamelen, + a, rr_type, rr_class, rr_ttl, rdatawl, rdatalen, rr, + rr_len); free(policydname); - verbose(VERB_ALGO, "RPZ: skipping unsupported trigger: %s", + } else if(t == RPZ_NSIP_TRIGGER) { + rpz_insert_nsip_trigger(r, policydname, policydnamelen, + a, rr_type, rr_class, rr_ttl, rdatawl, rdatalen, rr, + rr_len); + free(policydname); + } else if(t == RPZ_NSDNAME_TRIGGER) { + rpz_insert_nsdname_trigger(r, policydname, policydnamelen, + a, rr_type, rr_class, rr_ttl, rdatawl, rdatalen, rr, + rr_len); + free(policydname); + } else { + free(policydname); + verbose(VERB_ALGO, "rpz: skipping unsupported trigger: %s", rpz_trigger_to_string(t)); } return 1; @@ -669,18 +1091,18 @@ rpz_insert_rr(struct rpz* r, uint8_t* azname, size_t aznamelen, uint8_t* dname, /** * Find RPZ local-zone by qname. - * @param r: rpz containing local-zone tree + * @param zones: local-zone tree * @param qname: qname * @param qname_len: length of qname * @param qclass: qclass - * @param only_exact: if 1 only excact (non wildcard) matches are returned + * @param only_exact: if 1 only exact (non wildcard) matches are returned * @param wr: get write lock for local-zone if 1, read lock if 0 * @param zones_keep_lock: if set do not release the r->local_zones lock, this * makes the caller of this function responsible for releasing the lock. * @return: NULL or local-zone holding rd or wr lock */ static struct local_zone* -rpz_find_zone(struct rpz* r, uint8_t* qname, size_t qname_len, uint16_t qclass, +rpz_find_zone(struct local_zones* zones, uint8_t* qname, size_t qname_len, uint16_t qclass, int only_exact, int wr, int zones_keep_lock) { uint8_t* ce; @@ -689,16 +1111,19 @@ rpz_find_zone(struct rpz* r, uint8_t* qname, size_t qname_len, uint16_t qclass, uint8_t wc[LDNS_MAX_DOMAINLEN+1]; int exact; struct local_zone* z = NULL; + if(wr) { - lock_rw_wrlock(&r->local_zones->lock); + lock_rw_wrlock(&zones->lock); } else { - lock_rw_rdlock(&r->local_zones->lock); + lock_rw_rdlock(&zones->lock); } - z = local_zones_find_le(r->local_zones, qname, qname_len, + z = local_zones_find_le(zones, qname, qname_len, dname_count_labels(qname), LDNS_RR_CLASS_IN, &exact); if(!z || (only_exact && !exact)) { - lock_rw_unlock(&r->local_zones->lock); + if(!zones_keep_lock) { + lock_rw_unlock(&zones->lock); + } return NULL; } if(wr) { @@ -707,7 +1132,7 @@ rpz_find_zone(struct rpz* r, uint8_t* qname, size_t qname_len, uint16_t qclass, lock_rw_rdlock(&z->lock); } if(!zones_keep_lock) { - lock_rw_unlock(&r->local_zones->lock); + lock_rw_unlock(&zones->lock); } if(exact) @@ -721,7 +1146,7 @@ rpz_find_zone(struct rpz* r, uint8_t* qname, size_t qname_len, uint16_t qclass, if(!ce /* should not happen */) { lock_rw_unlock(&z->lock); if(zones_keep_lock) { - lock_rw_unlock(&r->local_zones->lock); + lock_rw_unlock(&zones->lock); } return NULL; } @@ -729,7 +1154,7 @@ rpz_find_zone(struct rpz* r, uint8_t* qname, size_t qname_len, uint16_t qclass, if(ce_len+2 > sizeof(wc)) { lock_rw_unlock(&z->lock); if(zones_keep_lock) { - lock_rw_unlock(&r->local_zones->lock); + lock_rw_unlock(&zones->lock); } return NULL; } @@ -740,15 +1165,15 @@ rpz_find_zone(struct rpz* r, uint8_t* qname, size_t qname_len, uint16_t qclass, if(!zones_keep_lock) { if(wr) { - lock_rw_wrlock(&r->local_zones->lock); + lock_rw_wrlock(&zones->lock); } else { - lock_rw_rdlock(&r->local_zones->lock); + lock_rw_rdlock(&zones->lock); } } - z = local_zones_find_le(r->local_zones, wc, + z = local_zones_find_le(zones, wc, ce_len+2, ce_labs+1, qclass, &exact); if(!z || !exact) { - lock_rw_unlock(&r->local_zones->lock); + lock_rw_unlock(&zones->lock); return NULL; } if(wr) { @@ -757,7 +1182,7 @@ rpz_find_zone(struct rpz* r, uint8_t* qname, size_t qname_len, uint16_t qclass, lock_rw_rdlock(&z->lock); } if(!zones_keep_lock) { - lock_rw_unlock(&r->local_zones->lock); + lock_rw_unlock(&zones->lock); } return z; } @@ -766,7 +1191,7 @@ rpz_find_zone(struct rpz* r, uint8_t* qname, size_t qname_len, uint16_t qclass, * Remove RR from RPZ's local-data * @param z: local-zone for RPZ, holding write lock * @param policydname: dname of RR to remove - * @param policydnamelen: lenth of policydname + * @param policydnamelen: length of policydname * @param rr_type: RR type of RR to remove * @param rdata: rdata of RR to remove * @param rdatalen: length of rdata @@ -852,10 +1277,10 @@ rpz_remove_qname_trigger(struct rpz* r, uint8_t* dname, size_t dnamelen, { struct local_zone* z; int delete_zone = 1; - z = rpz_find_zone(r, dname, dnamelen, rr_class, + z = rpz_find_zone(r->local_zones, dname, dnamelen, rr_class, 1 /* only exact */, 1 /* wr lock */, 1 /* keep lock*/); if(!z) { - verbose(VERB_ALGO, "RPZ: cannot remove RR from IXFR, " + verbose(VERB_ALGO, "rpz: cannot remove RR from IXFR, " "RPZ domain not found"); return; } @@ -891,7 +1316,7 @@ rpz_remove_response_ip_trigger(struct rpz* r, uint8_t* dname, size_t dnamelen, lock_rw_wrlock(&r->respip_set->lock); if(!(node = (struct resp_addr*)addr_tree_find( &r->respip_set->ip_tree, &addr, addrlen, net))) { - verbose(VERB_ALGO, "RPZ: cannot remove RR from IXFR, " + verbose(VERB_ALGO, "rpz: cannot remove RR from IXFR, " "RPZ domain not found"); lock_rw_unlock(&r->respip_set->lock); return; @@ -944,118 +1369,998 @@ rpz_remove_rr(struct rpz* r, size_t aznamelen, uint8_t* dname, size_t dnamelen, /** print log information for an applied RPZ policy. Based on local-zone's * lz_inform_print(). + * The repinfo contains the reply address. If it is NULL, the module + * state is used to report the first IP address (if any). + * The dname is used, for the applied rpz, if NULL, addrnode is used. */ static void -log_rpz_apply(uint8_t* dname, enum rpz_action a, struct query_info* qinfo, - struct comm_reply* repinfo, char* log_name) +log_rpz_apply(char* trigger, uint8_t* dname, struct addr_tree_node* addrnode, + enum rpz_action a, struct query_info* qinfo, + struct comm_reply* repinfo, struct module_qstate* ms, char* log_name) { - char ip[128], txt[512]; + char ip[128], txt[512], portstr[32]; char dnamestr[LDNS_MAX_DOMAINLEN+1]; - uint16_t port = ntohs(((struct sockaddr_in*)&repinfo->addr)->sin_port); - dname_str(dname, dnamestr); - addr_to_str(&repinfo->addr, repinfo->addrlen, ip, sizeof(ip)); - if(log_name) - snprintf(txt, sizeof(txt), "RPZ applied [%s] %s %s %s@%u", - log_name, dnamestr, rpz_action_to_string(a), ip, - (unsigned)port); - else - snprintf(txt, sizeof(txt), "RPZ applied %s %s %s@%u", - dnamestr, rpz_action_to_string(a), ip, (unsigned)port); + uint16_t port = 0; + if(dname) { + dname_str(dname, dnamestr); + } else if(addrnode) { + char a[128]; + addr_to_str(&addrnode->addr, addrnode->addrlen, a, sizeof(a)); + snprintf(dnamestr, sizeof(dnamestr), "%s/%d", a, addrnode->net); + } else { + dnamestr[0]=0; + } + if(repinfo) { + addr_to_str(&repinfo->addr, repinfo->addrlen, ip, sizeof(ip)); + port = ntohs(((struct sockaddr_in*)&repinfo->addr)->sin_port); + } else if(ms && ms->mesh_info && ms->mesh_info->reply_list) { + addr_to_str(&ms->mesh_info->reply_list->query_reply.addr, ms->mesh_info->reply_list->query_reply.addrlen, ip, sizeof(ip)); + port = ntohs(((struct sockaddr_in*)&ms->mesh_info->reply_list->query_reply.addr)->sin_port); + } else { + ip[0]=0; + port = 0; + } + snprintf(portstr, sizeof(portstr), "@%u", (unsigned)port); + snprintf(txt, sizeof(txt), "rpz: applied %s%s%s%s%s%s %s %s%s", + (log_name?"[":""), (log_name?log_name:""), (log_name?"] ":""), + (strcmp(trigger,"qname")==0?"":trigger), + (strcmp(trigger,"qname")==0?"":" "), + dnamestr, rpz_action_to_string(a), + (ip[0]?ip:""), (ip[0]?portstr:"")); log_nametypeclass(0, txt, qinfo->qname, qinfo->qtype, qinfo->qclass); } -int -rpz_apply_qname_trigger(struct auth_zones* az, struct module_env* env, - struct query_info* qinfo, struct edns_data* edns, sldns_buffer* buf, - struct regional* temp, struct comm_reply* repinfo, - uint8_t* taglist, size_t taglen, struct ub_server_stats* stats) +static struct clientip_synthesized_rr* +rpz_ipbased_trigger_lookup(struct clientip_synthesized_rrset* set, + struct sockaddr_storage* addr, socklen_t addrlen, char* triggername) { + struct clientip_synthesized_rr* raddr = NULL; + enum rpz_action action = RPZ_INVALID_ACTION; + + lock_rw_rdlock(&set->lock); + + raddr = (struct clientip_synthesized_rr*)addr_tree_lookup(&set->entries, + addr, addrlen); + if(raddr != NULL) { + lock_rw_rdlock(&raddr->lock); + action = raddr->action; + if(verbosity >= VERB_ALGO) { + char ip[256], net[256]; + addr_to_str(addr, addrlen, ip, sizeof(ip)); + addr_to_str(&raddr->node.addr, raddr->node.addrlen, + net, sizeof(net)); + verbose(VERB_ALGO, "rpz: trigger %s %s/%d on %s action=%s", + triggername, net, raddr->node.net, ip, rpz_action_to_string(action)); + } + } + lock_rw_unlock(&set->lock); + + return raddr; +} + +static inline +struct clientip_synthesized_rr* +rpz_resolve_client_action_and_zone(struct auth_zones* az, struct query_info* qinfo, + struct comm_reply* repinfo, uint8_t* taglist, size_t taglen, + struct ub_server_stats* stats, + /* output parameters */ + struct local_zone** z_out, struct auth_zone** a_out, struct rpz** r_out) +{ + struct clientip_synthesized_rr* node = NULL; + struct auth_zone* a = NULL; struct rpz* r = NULL; - struct auth_zone* a; - int ret; - enum localzone_type lzt; struct local_zone* z = NULL; - struct local_data* ld = NULL; + lock_rw_rdlock(&az->rpz_lock); + for(a = az->rpz_first; a; a = a->rpz_az_next) { lock_rw_rdlock(&a->lock); r = a->rpz; - if(!r->disabled && (!r->taglist || taglist_intersect(r->taglist, - r->taglistlen, taglist, taglen))) { - z = rpz_find_zone(r, qinfo->qname, qinfo->qname_len, - qinfo->qclass, 0, 0, 0); - if(z && r->action_override == RPZ_DISABLED_ACTION) { - if(r->log) - log_rpz_apply(z->name, - r->action_override, - qinfo, repinfo, r->log_name); - /* TODO only register stats when stats_extended? - * */ - stats->rpz_action[r->action_override]++; + if(r->disabled) { + lock_rw_unlock(&a->lock); + continue; + } + if(r->taglist && !taglist_intersect(r->taglist, + r->taglistlen, taglist, taglen)) { + lock_rw_unlock(&a->lock); + continue; + } + z = rpz_find_zone(r->local_zones, qinfo->qname, qinfo->qname_len, + qinfo->qclass, 0, 0, 0); + node = rpz_ipbased_trigger_lookup(r->client_set, &repinfo->addr, repinfo->addrlen, "clientip"); + if((z || node) && r->action_override == RPZ_DISABLED_ACTION) { + if(r->log) + log_rpz_apply((node?"clientip":"qname"), + (z?z->name:NULL), + (node?&node->node:NULL), + r->action_override, + qinfo, repinfo, NULL, r->log_name); + stats->rpz_action[r->action_override]++; + if(z != NULL) { lock_rw_unlock(&z->lock); z = NULL; } - if(z) - break; + if(node != NULL) { + lock_rw_unlock(&node->lock); + node = NULL; + } } - lock_rw_unlock(&a->lock); /* not found in this auth_zone */ + if(z || node) { + break; + } + /* not found in this auth_zone */ + lock_rw_unlock(&a->lock); } + lock_rw_unlock(&az->rpz_lock); - if(!z) - return 0; /* not holding auth_zone.lock anymore */ - log_assert(r); - if(r->action_override == RPZ_NO_OVERRIDE_ACTION) - lzt = z->type; - else - lzt = rpz_action_to_localzone_type(r->action_override); + *r_out = r; + *a_out = a; + *z_out = z; + return node; +} + +static inline int +rpz_is_udp_query(struct comm_reply* repinfo) { + return repinfo != NULL + ? (repinfo->c != NULL + ? repinfo->c->type == comm_udp + : 0) + : 0; +} + +/** encode answer consisting of 1 rrset */ +static int +rpz_local_encode(struct module_env* env, struct query_info* qinfo, + struct edns_data* edns, struct comm_reply* repinfo, sldns_buffer* buf, + struct regional* temp, struct ub_packed_rrset_key* rrset, int ansec, + int rcode, struct ub_packed_rrset_key* soa_rrset) +{ + struct reply_info rep; + uint16_t udpsize; + struct ub_packed_rrset_key* rrsetlist[3]; + + memset(&rep, 0, sizeof(rep)); + rep.flags = (uint16_t)((BIT_QR | BIT_AA | BIT_RA) | rcode); + rep.qdcount = 1; + rep.rrset_count = ansec; + rep.rrsets = rrsetlist; + if(ansec > 0) { + rep.an_numrrsets = 1; + rep.rrsets[0] = rrset; + rep.ttl = ((struct packed_rrset_data*)rrset->entry.data)->rr_ttl[0]; + } + if(soa_rrset != NULL) { + rep.ar_numrrsets = 1; + rep.rrsets[rep.rrset_count] = soa_rrset; + rep.rrset_count ++; + if(rep.ttl < ((struct packed_rrset_data*)soa_rrset->entry.data)->rr_ttl[0]) { + rep.ttl = ((struct packed_rrset_data*)soa_rrset->entry.data)->rr_ttl[0]; + } + } + + udpsize = edns->udp_size; + edns->edns_version = EDNS_ADVERTISED_VERSION; + edns->udp_size = EDNS_ADVERTISED_SIZE; + edns->ext_rcode = 0; + edns->bits &= EDNS_DO; + if(!inplace_cb_reply_local_call(env, qinfo, NULL, &rep, rcode, edns, + repinfo, temp, env->now_tv) || + !reply_info_answer_encode(qinfo, &rep, + *(uint16_t*)sldns_buffer_begin(buf), sldns_buffer_read_u16_at(buf, 2), + buf, 0, 0, temp, udpsize, edns, (int)(edns->bits&EDNS_DO), 0)) { + error_encode(buf, (LDNS_RCODE_SERVFAIL|BIT_AA), qinfo, + *(uint16_t*)sldns_buffer_begin(buf), + sldns_buffer_read_u16_at(buf, 2), edns); + } + + return 1; +} + +static struct local_rrset* +rpz_find_synthesized_rrset(int qtype, struct clientip_synthesized_rr* data) { + struct local_rrset* cursor = data->data; + while( cursor != NULL) { + struct packed_rrset_key* packed_rrset = &cursor->rrset->rk; + if(htons(qtype) == packed_rrset->type) { + return cursor; + } + cursor = cursor->next; + } + return NULL; +} + +/** allocate SOA record ubrrsetkey in region */ +static struct ub_packed_rrset_key* +make_soa_ubrrset(struct auth_zone* auth_zone, struct auth_rrset* soa, + struct regional* temp) +{ + struct ub_packed_rrset_key csoa; + if(!soa) + return NULL; + memset(&csoa, 0, sizeof(csoa)); + csoa.entry.key = &csoa; + csoa.rk.rrset_class = htons(LDNS_RR_CLASS_IN); + csoa.rk.type = htons(LDNS_RR_TYPE_SOA); + csoa.rk.flags |= PACKED_RRSET_FIXEDTTL + | PACKED_RRSET_RPZ; + csoa.rk.dname = auth_zone->name; + csoa.rk.dname_len = auth_zone->namelen; + csoa.entry.hash = rrset_key_hash(&csoa.rk); + csoa.entry.data = soa->data; + return respip_copy_rrset(&csoa, temp); +} + +static void +rpz_apply_clientip_localdata_action(struct clientip_synthesized_rr* raddr, + struct module_env* env, struct query_info* qinfo, + struct edns_data* edns, struct comm_reply* repinfo, sldns_buffer* buf, + struct regional* temp, struct auth_zone* auth_zone) +{ + struct local_rrset* rrset; + enum rpz_action action = RPZ_INVALID_ACTION; + struct ub_packed_rrset_key* rp = NULL; + struct ub_packed_rrset_key* rsoa = NULL; + int rcode = LDNS_RCODE_NOERROR|BIT_AA; + int rrset_count = 1; + + /* prepare synthesized answer for client */ + action = raddr->action; + if(action == RPZ_LOCAL_DATA_ACTION && raddr->data == NULL ) { + verbose(VERB_ALGO, "rpz: bug: local-data action but no local data"); + return; + } + + /* check query type / rr type */ + rrset = rpz_find_synthesized_rrset(qinfo->qtype, raddr); + if(rrset == NULL) { + verbose(VERB_ALGO, "rpz: unable to find local-data for query"); + rrset_count = 0; + goto nodata; + } + + rp = respip_copy_rrset(rrset->rrset, temp); + if(!rp) { + verbose(VERB_ALGO, "rpz: local data action: out of memory"); + return; + } + + rp->rk.flags |= PACKED_RRSET_FIXEDTTL | PACKED_RRSET_RPZ; + rp->rk.dname = qinfo->qname; + rp->rk.dname_len = qinfo->qname_len; + rp->entry.hash = rrset_key_hash(&rp->rk); +nodata: + if(auth_zone) { + struct auth_rrset* soa = NULL; + soa = auth_zone_get_soa_rrset(auth_zone); + if(soa) { + rsoa = make_soa_ubrrset(auth_zone, soa, temp); + if(!rsoa) { + verbose(VERB_ALGO, "rpz: local data action soa: out of memory"); + return; + } + } + } + + rpz_local_encode(env, qinfo, edns, repinfo, buf, temp, rp, + rrset_count, rcode, rsoa); +} + +/** add additional section SOA record to the reply. + * Since this gets fed into the normal iterator answer creation, it + * gets minimal-responses applied to it, that can remove the additional SOA + * again. */ +static int +rpz_add_soa(struct reply_info* rep, struct module_qstate* ms, + struct auth_zone* az) +{ + struct auth_rrset* soa = NULL; + struct ub_packed_rrset_key* rsoa = NULL; + struct ub_packed_rrset_key** prevrrsets; + if(!az) return 1; + soa = auth_zone_get_soa_rrset(az); + if(!soa) return 1; + if(!rep) return 0; + rsoa = make_soa_ubrrset(az, soa, ms->region); + if(!rsoa) return 0; + prevrrsets = rep->rrsets; + rep->rrsets = regional_alloc_zero(ms->region, + sizeof(*rep->rrsets)*(rep->rrset_count+1)); + if(!rep->rrsets) + return 0; + if(prevrrsets && rep->rrset_count > 0) + memcpy(rep->rrsets, prevrrsets, rep->rrset_count*sizeof(*rep->rrsets)); + rep->rrset_count++; + rep->ar_numrrsets++; + rep->rrsets[rep->rrset_count-1] = rsoa; + return 1; +} + +static inline struct dns_msg* +rpz_dns_msg_new(struct regional* region) +{ + struct dns_msg* msg = + (struct dns_msg*)regional_alloc(region, + sizeof(struct dns_msg)); + if(msg == NULL) { return NULL; } + memset(msg, 0, sizeof(struct dns_msg)); + + return msg; +} + +static inline struct dns_msg* +rpz_synthesize_nodata(struct rpz* ATTR_UNUSED(r), struct module_qstate* ms, + struct query_info* qinfo, struct auth_zone* az) +{ + struct dns_msg* msg = rpz_dns_msg_new(ms->region); + if(msg == NULL) { return msg; } + msg->qinfo = *qinfo; + msg->rep = construct_reply_info_base(ms->region, + LDNS_RCODE_NOERROR | BIT_RD | BIT_QR | BIT_AA | BIT_RA, + 1, /* qd */ + 0, /* ttl */ + 0, /* prettl */ + 0, /* expttl */ + 0, /* an */ + 0, /* ns */ + 0, /* ar */ + 0, /* total */ + sec_status_insecure); + if(msg->rep) + msg->rep->authoritative = 1; + if(!rpz_add_soa(msg->rep, ms, az)) + return NULL; + return msg; +} + +static inline struct dns_msg* +rpz_synthesize_nxdomain(struct rpz* ATTR_UNUSED(r), struct module_qstate* ms, + struct query_info* qinfo, struct auth_zone* az) +{ + struct dns_msg* msg = rpz_dns_msg_new(ms->region); + if(msg == NULL) { return msg; } + msg->qinfo = *qinfo; + msg->rep = construct_reply_info_base(ms->region, + LDNS_RCODE_NXDOMAIN | BIT_RD | BIT_QR | BIT_AA | BIT_RA, + 1, /* qd */ + 0, /* ttl */ + 0, /* prettl */ + 0, /* expttl */ + 0, /* an */ + 0, /* ns */ + 0, /* ar */ + 0, /* total */ + sec_status_insecure); + if(msg->rep) + msg->rep->authoritative = 1; + if(!rpz_add_soa(msg->rep, ms, az)) + return NULL; + return msg; +} + +static inline struct dns_msg* +rpz_synthesize_localdata_from_rrset(struct rpz* ATTR_UNUSED(r), struct module_qstate* ms, + struct query_info* qi, struct local_rrset* rrset, struct auth_zone* az) +{ + struct dns_msg* msg = NULL; + struct reply_info* new_reply_info; + struct ub_packed_rrset_key* rp; + + + msg = rpz_dns_msg_new(ms->region); + if(msg == NULL) { return NULL; } + + new_reply_info = construct_reply_info_base(ms->region, + LDNS_RCODE_NOERROR | BIT_RD | BIT_QR | BIT_AA | BIT_RA, + 1, /* qd */ + 0, /* ttl */ + 0, /* prettl */ + 0, /* expttl */ + 1, /* an */ + 0, /* ns */ + 0, /* ar */ + 1, /* total */ + sec_status_insecure); + if(new_reply_info == NULL) { + log_err("out of memory"); + return NULL; + } + new_reply_info->authoritative = 1; + rp = respip_copy_rrset(rrset->rrset, ms->region); + if(rp == NULL) { + log_err("out of memory"); + return NULL; + } + rp->rk.dname = qi->qname; + rp->rk.dname_len = qi->qname_len; + /* this rrset is from the rpz data, or synthesized. + * It is not actually from the network, so we flag it with this + * flags as a fake RRset. If later the cache is used to look up + * rrsets, then the fake ones are not returned (if you look without + * the flag). For like CNAME lookups from the iterator or A, AAAA + * lookups for nameserver targets, it would use the without flag + * actual data. So that the actual network data and fake data + * are kept track of separately. */ + rp->rk.flags |= PACKED_RRSET_RPZ; + new_reply_info->rrsets[0] = rp; + msg->rep = new_reply_info; + if(!rpz_add_soa(msg->rep, ms, az)) + return NULL; + return msg; +} + +static inline struct dns_msg* +rpz_synthesize_nsip_localdata(struct rpz* r, struct module_qstate* ms, + struct clientip_synthesized_rr* data, struct auth_zone* az) +{ + struct query_info* qi = &ms->qinfo; + struct local_rrset* rrset; + + rrset = rpz_find_synthesized_rrset(qi->qtype, data); + if(rrset == NULL) { + verbose(VERB_ALGO, "rpz: nsip: no matching local data found"); + return NULL; + } + + return rpz_synthesize_localdata_from_rrset(r, ms, &ms->qinfo, rrset, az); +} + +/* copy'n'paste from localzone.c */ +static struct local_rrset* +local_data_find_type(struct local_data* data, uint16_t type, int alias_ok) +{ + struct local_rrset* p; + type = htons(type); + for(p = data->rrsets; p; p = p->next) { + if(p->rrset->rk.type == type) + return p; + if(alias_ok && p->rrset->rk.type == htons(LDNS_RR_TYPE_CNAME)) + return p; + } + return NULL; +} + +/* based on localzone.c:local_data_answer() */ +static inline struct dns_msg* +rpz_synthesize_nsdname_localdata(struct rpz* r, struct module_qstate* ms, + struct local_zone* z, struct matched_delegation_point const* match, + struct auth_zone* az) +{ + struct local_data key; + struct local_data* ld; + struct local_rrset* rrset; + + if(match->dname == NULL) { return NULL; } + + key.node.key = &key; + key.name = match->dname; + key.namelen = match->dname_len; + key.namelabs = dname_count_labels(match->dname); + + rpz_log_dname("nsdname local data", key.name, key.namelen); + + ld = (struct local_data*)rbtree_search(&z->data, &key.node); + if(ld == NULL) { + verbose(VERB_ALGO, "rpz: nsdname: impossible: qname not found"); + return NULL; + } + + rrset = local_data_find_type(ld, ms->qinfo.qtype, 1); + if(rrset == NULL) { + verbose(VERB_ALGO, "rpz: nsdname: no matching local data found"); + return NULL; + } + + return rpz_synthesize_localdata_from_rrset(r, ms, &ms->qinfo, rrset, az); +} + +/* like local_data_answer for qname triggers after a cname */ +static struct dns_msg* +rpz_synthesize_qname_localdata_msg(struct rpz* r, struct module_qstate* ms, + struct query_info* qinfo, struct local_zone* z, struct auth_zone* az) +{ + struct local_data key; + struct local_data* ld; + struct local_rrset* rrset; + key.node.key = &key; + key.name = qinfo->qname; + key.namelen = qinfo->qname_len; + key.namelabs = dname_count_labels(qinfo->qname); + ld = (struct local_data*)rbtree_search(&z->data, &key.node); + if(ld == NULL) { + verbose(VERB_ALGO, "rpz: qname after cname: name not found"); + return NULL; + } + rrset = local_data_find_type(ld, qinfo->qtype, 1); + if(rrset == NULL) { + verbose(VERB_ALGO, "rpz: qname after cname: type not found"); + return NULL; + } + return rpz_synthesize_localdata_from_rrset(r, ms, qinfo, rrset, az); +} + +static int +rpz_synthesize_qname_localdata(struct module_env* env, struct rpz* r, + struct local_zone* z, enum localzone_type lzt, struct query_info* qinfo, + struct edns_data* edns, sldns_buffer* buf, struct regional* temp, + struct comm_reply* repinfo, struct ub_server_stats* stats) +{ + struct local_data* ld = NULL; + int ret = 0; if(r->action_override == RPZ_CNAME_OVERRIDE_ACTION) { - qinfo->local_alias = - regional_alloc_zero(temp, sizeof(struct local_rrset)); - if(!qinfo->local_alias) { - lock_rw_unlock(&z->lock); - lock_rw_unlock(&a->lock); + qinfo->local_alias = regional_alloc_zero(temp, sizeof(struct local_rrset)); + if(qinfo->local_alias == NULL) { return 0; /* out of memory */ } - qinfo->local_alias->rrset = - regional_alloc_init(temp, r->cname_override, - sizeof(*r->cname_override)); - if(!qinfo->local_alias->rrset) { - lock_rw_unlock(&z->lock); - lock_rw_unlock(&a->lock); + qinfo->local_alias->rrset = regional_alloc_init(temp, r->cname_override, + sizeof(*r->cname_override)); + if(qinfo->local_alias->rrset == NULL) { return 0; /* out of memory */ } qinfo->local_alias->rrset->rk.dname = qinfo->qname; qinfo->local_alias->rrset->rk.dname_len = qinfo->qname_len; - if(r->log) - log_rpz_apply(z->name, RPZ_CNAME_OVERRIDE_ACTION, - qinfo, repinfo, r->log_name); + if(r->log) { + log_rpz_apply("qname", z->name, NULL, RPZ_CNAME_OVERRIDE_ACTION, + qinfo, repinfo, NULL, r->log_name); + } stats->rpz_action[RPZ_CNAME_OVERRIDE_ACTION]++; - lock_rw_unlock(&z->lock); - lock_rw_unlock(&a->lock); return 0; } if(lzt == local_zone_redirect && local_data_answer(z, env, qinfo, edns, repinfo, buf, temp, dname_count_labels(qinfo->qname), &ld, lzt, -1, NULL, 0, NULL, 0)) { - if(r->log) - log_rpz_apply(z->name, + if(r->log) { + log_rpz_apply("qname", z->name, NULL, localzone_type_to_rpz_action(lzt), qinfo, - repinfo, r->log_name); + repinfo, NULL, r->log_name); + } stats->rpz_action[localzone_type_to_rpz_action(lzt)]++; - lock_rw_unlock(&z->lock); - lock_rw_unlock(&a->lock); return !qinfo->local_alias; } ret = local_zones_zone_answer(z, env, qinfo, edns, repinfo, buf, temp, 0 /* no local data used */, lzt); - if(r->log) - log_rpz_apply(z->name, localzone_type_to_rpz_action(lzt), - qinfo, repinfo, r->log_name); + if(r->log) { + log_rpz_apply("qname", z->name, NULL, localzone_type_to_rpz_action(lzt), + qinfo, repinfo, NULL, r->log_name); + } stats->rpz_action[localzone_type_to_rpz_action(lzt)]++; + return ret; +} + +struct clientip_synthesized_rr* +rpz_delegation_point_ipbased_trigger_lookup(struct rpz* rpz, struct iter_qstate* is) +{ + struct delegpt_addr* cursor; + struct clientip_synthesized_rr* action = NULL; + if(is->dp == NULL) { return NULL; } + for(cursor = is->dp->target_list; + cursor != NULL; + cursor = cursor->next_target) { + if(cursor->bogus) { continue; } + action = rpz_ipbased_trigger_lookup(rpz->ns_set, &cursor->addr, + cursor->addrlen, "nsip"); + if(action != NULL) { return action; } + } + return NULL; +} + +struct dns_msg* +rpz_apply_nsip_trigger(struct module_qstate* ms, struct rpz* r, + struct clientip_synthesized_rr* raddr, struct auth_zone* az) +{ + enum rpz_action action = raddr->action; + struct dns_msg* ret = NULL; + + if(r->action_override != RPZ_NO_OVERRIDE_ACTION) { + verbose(VERB_ALGO, "rpz: using override action=%s (replaces=%s)", + rpz_action_to_string(r->action_override), rpz_action_to_string(action)); + action = r->action_override; + } + + if(action == RPZ_LOCAL_DATA_ACTION && raddr->data == NULL) { + verbose(VERB_ALGO, "rpz: bug: nsip local data action but no local data"); + ret = rpz_synthesize_nodata(r, ms, &ms->qinfo, az); + goto done; + } + + switch(action) { + case RPZ_NXDOMAIN_ACTION: + ret = rpz_synthesize_nxdomain(r, ms, &ms->qinfo, az); + break; + case RPZ_NODATA_ACTION: + ret = rpz_synthesize_nodata(r, ms, &ms->qinfo, az); + break; + case RPZ_TCP_ONLY_ACTION: + /* basically a passthru here but the tcp-only will be + * honored before the query gets sent. */ + ms->respip_action_info->action = respip_truncate; + ret = NULL; + break; + case RPZ_DROP_ACTION: + ret = rpz_synthesize_nodata(r, ms, &ms->qinfo, az); + ms->is_drop = 1; + break; + case RPZ_LOCAL_DATA_ACTION: + ret = rpz_synthesize_nsip_localdata(r, ms, raddr, az); + if(ret == NULL) { ret = rpz_synthesize_nodata(r, ms, &ms->qinfo, az); } + break; + case RPZ_PASSTHRU_ACTION: + ret = NULL; + break; + default: + verbose(VERB_ALGO, "rpz: nsip: bug: unhandled or invalid action: '%s'", + rpz_action_to_string(action)); + ret = NULL; + } + +done: + if(r->log) + log_rpz_apply("nsip", NULL, &raddr->node, + action, &ms->qinfo, NULL, ms, r->log_name); + if(ms->env->worker) + ms->env->worker->stats.rpz_action[action]++; + lock_rw_unlock(&raddr->lock); + return ret; +} + +struct dns_msg* +rpz_apply_nsdname_trigger(struct module_qstate* ms, struct rpz* r, + struct local_zone* z, struct matched_delegation_point const* match, + struct auth_zone* az) +{ + struct dns_msg* ret = NULL; + enum rpz_action action = localzone_type_to_rpz_action(z->type); + + if(r->action_override != RPZ_NO_OVERRIDE_ACTION) { + verbose(VERB_ALGO, "rpz: using override action=%s (replaces=%s)", + rpz_action_to_string(r->action_override), rpz_action_to_string(action)); + action = r->action_override; + } + + switch(action) { + case RPZ_NXDOMAIN_ACTION: + ret = rpz_synthesize_nxdomain(r, ms, &ms->qinfo, az); + break; + case RPZ_NODATA_ACTION: + ret = rpz_synthesize_nodata(r, ms, &ms->qinfo, az); + break; + case RPZ_TCP_ONLY_ACTION: + /* basically a passthru here but the tcp-only will be + * honored before the query gets sent. */ + ms->respip_action_info->action = respip_truncate; + ret = NULL; + break; + case RPZ_DROP_ACTION: + ret = rpz_synthesize_nodata(r, ms, &ms->qinfo, az); + ms->is_drop = 1; + break; + case RPZ_LOCAL_DATA_ACTION: + ret = rpz_synthesize_nsdname_localdata(r, ms, z, match, az); + if(ret == NULL) { ret = rpz_synthesize_nodata(r, ms, &ms->qinfo, az); } + break; + case RPZ_PASSTHRU_ACTION: + ret = NULL; + break; + default: + verbose(VERB_ALGO, "rpz: nsip: bug: unhandled or invalid action: '%s'", + rpz_action_to_string(action)); + ret = NULL; + } + + if(r->log) + log_rpz_apply("nsdname", match->dname, NULL, + action, &ms->qinfo, NULL, ms, r->log_name); + if(ms->env->worker) + ms->env->worker->stats.rpz_action[action]++; + lock_rw_unlock(&z->lock); + return ret; +} + +static struct local_zone* +rpz_delegation_point_zone_lookup(struct delegpt* dp, struct local_zones* zones, + uint16_t qclass, + /* output parameter */ + struct matched_delegation_point* match) +{ + struct delegpt_ns* nameserver; + struct local_zone* z = NULL; + + /* the rpz specs match the nameserver names (NS records), not the + * name of the delegation point itself, to the nsdname triggers */ + for(nameserver = dp->nslist; + nameserver != NULL; + nameserver = nameserver->next) { + z = rpz_find_zone(zones, nameserver->name, nameserver->namelen, + qclass, 0, 0, 0); + if(z != NULL) { + match->dname = nameserver->name; + match->dname_len = nameserver->namelen; + if(verbosity >= VERB_ALGO) { + char nm[255+1], zn[255+1]; + dname_str(match->dname, nm); + dname_str(z->name, zn); + if(strcmp(nm, zn) != 0) + verbose(VERB_ALGO, "rpz: trigger nsdname %s on %s action=%s", + zn, nm, rpz_action_to_string(localzone_type_to_rpz_action(z->type))); + else + verbose(VERB_ALGO, "rpz: trigger nsdname %s action=%s", + nm, rpz_action_to_string(localzone_type_to_rpz_action(z->type))); + } + break; + } + } + + return z; +} + +struct dns_msg* +rpz_callback_from_iterator_module(struct module_qstate* ms, struct iter_qstate* is) +{ + struct auth_zones* az; + struct auth_zone* a; + struct clientip_synthesized_rr* raddr = NULL; + struct rpz* r = NULL; + struct local_zone* z = NULL; + struct matched_delegation_point match = {0}; + + if(ms->env == NULL || ms->env->auth_zones == NULL) { return 0; } + + az = ms->env->auth_zones; + + verbose(VERB_ALGO, "rpz: iterator module callback: have_rpz=%d", az->rpz_first != NULL); + + lock_rw_rdlock(&az->rpz_lock); + + /* precedence of RPZ works, loosely, like this: + * CNAMEs in order of the CNAME chain. rpzs in the order they are + * configured. In an RPZ: first client-IP addr, then QNAME, then + * response IP, then NSDNAME, then NSIP. Longest match first. Smallest + * one from a set. */ + /* we use the precedence rules for the topics and triggers that + * are pertinent at this stage of the resolve processing */ + for(a = az->rpz_first; a != NULL; a = a->rpz_az_next) { + lock_rw_rdlock(&a->lock); + r = a->rpz; + if(r->disabled) { + lock_rw_unlock(&a->lock); + continue; + } + + /* the nsdname has precedence over the nsip triggers */ + z = rpz_delegation_point_zone_lookup(is->dp, r->nsdname_zones, + ms->qinfo.qclass, &match); + if(z != NULL) { + lock_rw_unlock(&a->lock); + break; + } + + raddr = rpz_delegation_point_ipbased_trigger_lookup(r, is); + if(raddr != NULL) { + lock_rw_unlock(&a->lock); + break; + } + lock_rw_unlock(&a->lock); + } + + lock_rw_unlock(&az->rpz_lock); + + if(raddr == NULL && z == NULL) { return NULL; } + else if(raddr != NULL) { + if(z) { + lock_rw_unlock(&z->lock); + } + return rpz_apply_nsip_trigger(ms, r, raddr, a); + } else if(z != NULL) { + if(raddr) { + lock_rw_unlock(&raddr->lock); + } + return rpz_apply_nsdname_trigger(ms, r, z, &match, a); + } else { return NULL; } +} + +struct dns_msg* rpz_callback_from_iterator_cname(struct module_qstate* ms, + struct iter_qstate* is) +{ + struct auth_zones* az; + struct auth_zone* a = NULL; + struct rpz* r = NULL; + struct local_zone* z = NULL; + enum localzone_type lzt; + struct dns_msg* ret = NULL; + + if(ms->env == NULL || ms->env->auth_zones == NULL) { return 0; } + az = ms->env->auth_zones; + + lock_rw_rdlock(&az->rpz_lock); + + for(a = az->rpz_first; a; a = a->rpz_az_next) { + lock_rw_rdlock(&a->lock); + r = a->rpz; + if(r->disabled) { + lock_rw_unlock(&a->lock); + continue; + } + z = rpz_find_zone(r->local_zones, is->qchase.qname, + is->qchase.qname_len, is->qchase.qclass, 0, 0, 0); + if(z && r->action_override == RPZ_DISABLED_ACTION) { + if(r->log) + log_rpz_apply("qname", z->name, NULL, + r->action_override, + &ms->qinfo, NULL, ms, r->log_name); + if(ms->env->worker) + ms->env->worker->stats.rpz_action[r->action_override]++; + lock_rw_unlock(&z->lock); + z = NULL; + } + if(z) { + break; + } + /* not found in this auth_zone */ + lock_rw_unlock(&a->lock); + } + lock_rw_unlock(&az->rpz_lock); + + if(z == NULL) + return NULL; + if(r->action_override == RPZ_NO_OVERRIDE_ACTION) { + lzt = z->type; + } else { + lzt = rpz_action_to_localzone_type(r->action_override); + } + + if(verbosity >= VERB_ALGO) { + char nm[255+1], zn[255+1]; + dname_str(is->qchase.qname, nm); + dname_str(z->name, zn); + if(strcmp(zn, nm) != 0) + verbose(VERB_ALGO, "rpz: qname trigger after cname %s on %s, with action=%s", + zn, nm, rpz_action_to_string(localzone_type_to_rpz_action(lzt))); + else + verbose(VERB_ALGO, "rpz: qname trigger after cname %s, with action=%s", + nm, rpz_action_to_string(localzone_type_to_rpz_action(lzt))); + } + switch(localzone_type_to_rpz_action(lzt)) { + case RPZ_NXDOMAIN_ACTION: + ret = rpz_synthesize_nxdomain(r, ms, &is->qchase, a); + break; + case RPZ_NODATA_ACTION: + ret = rpz_synthesize_nodata(r, ms, &is->qchase, a); + break; + case RPZ_TCP_ONLY_ACTION: + /* basically a passthru here but the tcp-only will be + * honored before the query gets sent. */ + ms->respip_action_info->action = respip_truncate; + ret = NULL; + break; + case RPZ_DROP_ACTION: + ret = rpz_synthesize_nodata(r, ms, &is->qchase, a); + ms->is_drop = 1; + break; + case RPZ_LOCAL_DATA_ACTION: + ret = rpz_synthesize_qname_localdata_msg(r, ms, &is->qchase, z, a); + if(ret == NULL) { ret = rpz_synthesize_nodata(r, ms, &is->qchase, a); } + break; + case RPZ_PASSTHRU_ACTION: + ret = NULL; + break; + default: + verbose(VERB_ALGO, "rpz: qname trigger after cname: bug: unhandled or invalid action: '%s'", + rpz_action_to_string(localzone_type_to_rpz_action(lzt))); + ret = NULL; + } + lock_rw_unlock(&z->lock); + lock_rw_unlock(&a->lock); + return ret; +} + +static int +rpz_apply_maybe_clientip_trigger(struct auth_zones* az, struct module_env* env, + struct query_info* qinfo, struct edns_data* edns, struct comm_reply* repinfo, + uint8_t* taglist, size_t taglen, struct ub_server_stats* stats, + sldns_buffer* buf, struct regional* temp, + /* output parameters */ + struct local_zone** z_out, struct auth_zone** a_out, struct rpz** r_out) +{ + int ret = 0; + enum rpz_action client_action; + struct clientip_synthesized_rr* node = rpz_resolve_client_action_and_zone( + az, qinfo, repinfo, taglist, taglen, stats, z_out, a_out, r_out); + + client_action = ((node == NULL) ? RPZ_INVALID_ACTION : node->action); + + if(*z_out == NULL || (client_action != RPZ_INVALID_ACTION && + client_action != RPZ_PASSTHRU_ACTION)) { + if(client_action == RPZ_PASSTHRU_ACTION + || client_action == RPZ_INVALID_ACTION + || (client_action == RPZ_TCP_ONLY_ACTION + && !rpz_is_udp_query(repinfo))) { + ret = 0; + goto done; + } + stats->rpz_action[client_action]++; + if(client_action == RPZ_LOCAL_DATA_ACTION) { + rpz_apply_clientip_localdata_action(node, env, qinfo, + edns, repinfo, buf, temp, *a_out); + } else { + if(*r_out && (*r_out)->log) + log_rpz_apply( + (node?"clientip":"qname"), + ((*z_out)?(*z_out)->name:NULL), + (node?&node->node:NULL), + client_action, qinfo, repinfo, NULL, + (*r_out)->log_name); + local_zones_zone_answer(*z_out /*likely NULL, no zone*/, env, qinfo, edns, + repinfo, buf, temp, 0 /* no local data used */, + rpz_action_to_localzone_type(client_action)); + } + ret = 1; + goto done; + } + ret = -1; +done: + if(node != NULL) { + lock_rw_unlock(&node->lock); + } + return ret; +} + +int +rpz_callback_from_worker_request(struct auth_zones* az, struct module_env* env, + struct query_info* qinfo, struct edns_data* edns, sldns_buffer* buf, + struct regional* temp, struct comm_reply* repinfo, uint8_t* taglist, + size_t taglen, struct ub_server_stats* stats) +{ + struct rpz* r = NULL; + struct auth_zone* a = NULL; + struct local_zone* z = NULL; + int ret; + enum localzone_type lzt; + + int clientip_trigger = rpz_apply_maybe_clientip_trigger(az, env, qinfo, + edns, repinfo, taglist, taglen, stats, buf, temp, &z, &a, &r); + if(clientip_trigger >= 0) { + if(a) { + lock_rw_unlock(&a->lock); + } + if(z) { + lock_rw_unlock(&z->lock); + } + return clientip_trigger; + } + + if(z == NULL) { + if(a) { + lock_rw_unlock(&a->lock); + } + return 0; + } + + log_assert(r); + + if(r->action_override == RPZ_NO_OVERRIDE_ACTION) { + lzt = z->type; + } else { + lzt = rpz_action_to_localzone_type(r->action_override); + } + + if(verbosity >= VERB_ALGO) { + char nm[255+1], zn[255+1]; + dname_str(qinfo->qname, nm); + dname_str(z->name, zn); + if(strcmp(zn, nm) != 0) + verbose(VERB_ALGO, "rpz: qname trigger %s on %s with action=%s", + zn, nm, rpz_action_to_string(localzone_type_to_rpz_action(lzt))); + else + verbose(VERB_ALGO, "rpz: qname trigger %s with action=%s", + nm, rpz_action_to_string(localzone_type_to_rpz_action(lzt))); + } + + ret = rpz_synthesize_qname_localdata(env, r, z, lzt, qinfo, edns, buf, temp, + repinfo, stats); + lock_rw_unlock(&z->lock); lock_rw_unlock(&a->lock); diff --git a/contrib/unbound/services/rpz.h b/contrib/unbound/services/rpz.h index d5996a6cfa26..691475743606 100644 --- a/contrib/unbound/services/rpz.h +++ b/contrib/unbound/services/rpz.h @@ -50,6 +50,7 @@ #include "sldns/sbuffer.h" #include "daemon/stats.h" #include "respip/respip.h" +struct iter_qstate; /** * RPZ triggers, only the QNAME trigger is currently supported in Unbound. @@ -83,6 +84,27 @@ enum rpz_action { RPZ_CNAME_OVERRIDE_ACTION, /* RPZ CNAME action override*/ }; +struct clientip_synthesized_rrset{ + struct regional* region; + struct rbtree_type entries; + lock_rw_type lock; /* lock on the respip tree */ +}; + +struct clientip_synthesized_rr { + /** node in address tree */ + struct addr_tree_node node; + /** lock on the node item */ + lock_rw_type lock; + /** tag bitlist */ + uint8_t* taglist; + /** length of the taglist (in bytes) */ + size_t taglen; + /** action for this address span */ + enum rpz_action action; + /** "local data" for this node */ + struct local_rrset* data; +}; + /** * RPZ containing policies. Pointed to from corresponding auth-zone. Part of a * linked list to keep configuration order. Iterating or changing the linked @@ -92,6 +114,9 @@ enum rpz_action { struct rpz { struct local_zones* local_zones; struct respip_set* respip_set; + struct clientip_synthesized_rrset* client_set; + struct clientip_synthesized_rrset* ns_set; + struct local_zones* nsdname_zones; uint8_t* taglist; size_t taglistlen; enum rpz_action action_override; @@ -147,15 +172,38 @@ void rpz_remove_rr(struct rpz* r, size_t aznamelen, uint8_t* dname, * @param temp: scratchpad * @param repinfo: reply info * @param taglist: taglist to lookup. - * @param taglen: lenth of taglist. + * @param taglen: length of taglist. * @param stats: worker stats struct * @return: 1 if client answer is ready, 0 to continue resolving */ -int rpz_apply_qname_trigger(struct auth_zones* az, struct module_env* env, +int rpz_callback_from_worker_request(struct auth_zones* az, struct module_env* env, struct query_info* qinfo, struct edns_data* edns, sldns_buffer* buf, struct regional* temp, struct comm_reply* repinfo, uint8_t* taglist, size_t taglen, struct ub_server_stats* stats); +/** + * Callback to process when the iterator module is about to send queries. + * Checks for nsip and nsdname triggers. + * @param qstate: the query state. + * @param iq: iterator module query state. + * @return NULL if nothing is done. Or a new message with the contents from + * the rpz, based on the delegation point. It is allocated in the + * qstate region. + */ +struct dns_msg* rpz_callback_from_iterator_module(struct module_qstate* qstate, + struct iter_qstate* iq); + +/** + * Callback to process when the iterator module has followed a cname. + * There can be a qname trigger for the new query name. + * @param qstate: the query state. + * @param iq: iterator module query state. + * @return NULL if nothing is done. Or a new message with the contents from + * the rpz, based on the iq.qchase. It is allocated in the qstate region. + */ +struct dns_msg* rpz_callback_from_iterator_cname(struct module_qstate* qstate, + struct iter_qstate* iq); + /** * Delete RPZ * @param r: RPZ struct to delete @@ -186,7 +234,7 @@ enum rpz_action respip_action_to_rpz_action(enum respip_action a); /** - * Prepare RPZ after procesing feed content. + * Prepare RPZ after processing feed content. * @param r: RPZ to use */ void rpz_finish_config(struct rpz* r); diff --git a/contrib/unbound/sldns/parseutil.h b/contrib/unbound/sldns/parseutil.h index 74d7c727571a..208fd2fbca8b 100644 --- a/contrib/unbound/sldns/parseutil.h +++ b/contrib/unbound/sldns/parseutil.h @@ -58,7 +58,7 @@ time_t sldns_mktime_from_utc(const struct tm *tm); * The function interprets time as the number of seconds since epoch * with respect to now using serial arithmetics (rfc1982). * That number of seconds is then converted to broken-out time information. - * This is especially usefull when converting the inception and expiration + * This is especially useful when converting the inception and expiration * fields of RRSIG records. * * \param[in] time number of seconds since epoch (midnight, January 1st, 1970) diff --git a/contrib/unbound/sldns/str2wire.c b/contrib/unbound/sldns/str2wire.c index fbd615cbfd7d..ddaccd1b292d 100644 --- a/contrib/unbound/sldns/str2wire.c +++ b/contrib/unbound/sldns/str2wire.c @@ -1427,7 +1427,7 @@ sldns_str2wire_svcbparam_parse_next_unescaped_comma(const char *val) } /* The source is already properly unescaped, this double unescaping is purely to allow for - * comma's in comma seperated alpn lists. + * comma's in comma separated alpn lists. * * In draft-ietf-dnsop-svcb-https-06 Section 7: * To enable simpler parsing, this SvcParamValue MUST NOT contain escape sequences. @@ -1565,7 +1565,7 @@ sldns_str2wire_svcparam_value(const char *key, size_t key_len, return LDNS_WIREPARSE_ERR_GENERAL; } -int sldns_str2wire_svcparam_buf(const char* str, uint8_t* rd, size_t* rd_len) +static int sldns_str2wire_svcparam_buf(const char* str, uint8_t* rd, size_t* rd_len) { const char* eq_pos; char unescaped_val[LDNS_MAX_RDFLEN]; diff --git a/contrib/unbound/sldns/wire2str.h b/contrib/unbound/sldns/wire2str.h index b1ad459e3780..548c66300d92 100644 --- a/contrib/unbound/sldns/wire2str.h +++ b/contrib/unbound/sldns/wire2str.h @@ -59,7 +59,7 @@ char* sldns_wire2str_pkt(uint8_t* data, size_t len); char* sldns_wire2str_rr(uint8_t* rr, size_t len); /** - * Conver wire dname to a string. + * Convert wire dname to a string. * @param dname: the dname in uncompressed wireformat. * @param dname_len: length of the dname. * @return string or NULL on failure. diff --git a/contrib/unbound/smallapp/unbound-anchor.c b/contrib/unbound/smallapp/unbound-anchor.c index 2ddd7ff69033..027980be117a 100644 --- a/contrib/unbound/smallapp/unbound-anchor.c +++ b/contrib/unbound/smallapp/unbound-anchor.c @@ -2037,13 +2037,13 @@ write_builtin_anchor(const char* file) const char* builtin_root_anchor = get_builtin_ds(); FILE* out = fopen(file, "w"); if(!out) { - if(verb) printf("%s: %s\n", file, strerror(errno)); - if(verb) printf(" could not write builtin anchor\n"); + printf("could not write builtin anchor, to file %s: %s\n", + file, strerror(errno)); return; } if(!fwrite(builtin_root_anchor, strlen(builtin_root_anchor), 1, out)) { - if(verb) printf("%s: %s\n", file, strerror(errno)); - if(verb) printf(" could not complete write builtin anchor\n"); + printf("could not complete write builtin anchor, to file %s: %s\n", + file, strerror(errno)); } fclose(out); } diff --git a/contrib/unbound/smallapp/unbound-checkconf.c b/contrib/unbound/smallapp/unbound-checkconf.c index 8e5656355843..8f114b862c9a 100644 --- a/contrib/unbound/smallapp/unbound-checkconf.c +++ b/contrib/unbound/smallapp/unbound-checkconf.c @@ -54,6 +54,7 @@ #include "iterator/iter_hints.h" #include "validator/validator.h" #include "services/localzone.h" +#include "services/listen_dnsport.h" #include "services/view.h" #include "services/authzone.h" #include "respip/respip.h" @@ -334,19 +335,64 @@ interfacechecks(struct config_file* cfg) int d; struct sockaddr_storage a; socklen_t alen; - int i, j; + int i, j, i2, j2; + char*** resif = NULL; + int* num_resif = NULL; + + if(cfg->num_ifs != 0) { + resif = (char***)calloc(cfg->num_ifs, sizeof(char**)); + if(!resif) fatal_exit("malloc failure"); + num_resif = (int*)calloc(cfg->num_ifs, sizeof(int)); + if(!num_resif) fatal_exit("malloc failure"); + } for(i=0; inum_ifs; i++) { - if(!extstrtoaddr(cfg->ifs[i], &a, &alen)) { - fatal_exit("cannot parse interface specified as '%s'", - cfg->ifs[i]); - } - for(j=0; jnum_ifs; j++) { - if(i!=j && strcmp(cfg->ifs[i], cfg->ifs[j])==0) + /* search for duplicates in IP or ifname arguments */ + for(i2=0; i2ifs[i], cfg->ifs[i2]) == 0) { fatal_exit("interface: %s present twice, " "cannot bind same ports twice.", cfg->ifs[i]); + } + } + if(!resolve_interface_names(&cfg->ifs[i], 1, NULL, &resif[i], + &num_resif[i])) { + fatal_exit("could not resolve interface names, for %s", + cfg->ifs[i]); + } + /* search for duplicates in the returned addresses */ + for(j=0; jifs[i], resif[i][j]) != 0) + fatal_exit("cannot parse interface address '%s' from the interface specified as '%s'", + resif[i][j], cfg->ifs[i]); + else + fatal_exit("cannot parse interface specified as '%s'", + cfg->ifs[i]); + } + for(i2=0; i2ifs[i], resif[i][j]) != 0) + snprintf(info1, sizeof(info1), "address %s from interface: %s", resif[i][j], cfg->ifs[i]); + else snprintf(info1, sizeof(info1), "interface: %s", cfg->ifs[i]); + if(strcmp(cfg->ifs[i2], resif[i2][j2]) != 0) + snprintf(info2, sizeof(info2), "address %s from interface: %s", resif[i2][j2], cfg->ifs[i2]); + else snprintf(info2, sizeof(info2), "interface: %s", cfg->ifs[i2]); + fatal_exit("%s present twice, cannot bind the same ports twice. The first entry is %s and the second is %s", resif[i][j], info2, info1); + } + } + } } } + + for(i=0; inum_ifs; i++) { + config_del_strarray(resif[i], num_resif[i]); + } + free(resif); + free(num_resif); + for(i=0; inum_out_ifs; i++) { if(!ipstrtoaddr(cfg->out_ifs[i], UNBOUND_DNS_PORT, &a, &alen) && !netblockstrtoaddr(cfg->out_ifs[i], UNBOUND_DNS_PORT, &a, &alen, &d)) { @@ -909,9 +955,9 @@ int main(int argc, char* argv[]) const char* f; const char* opt = NULL; const char* cfgfile = CONFIGFILE; + checklock_start(); log_ident_set("unbound-checkconf"); log_init(NULL, 0, NULL); - checklock_start(); #ifdef USE_WINSOCK /* use registry config file in preference to compiletime location */ if(!(cfgfile=w_lookup_reg_str("Software\\Unbound", "ConfigFile"))) diff --git a/contrib/unbound/smallapp/unbound-control.c b/contrib/unbound/smallapp/unbound-control.c index f28875b9c538..0ebbd8305848 100644 --- a/contrib/unbound/smallapp/unbound-control.c +++ b/contrib/unbound/smallapp/unbound-control.c @@ -944,9 +944,9 @@ int main(int argc, char* argv[]) extern int check_locking_order; check_locking_order = 0; #endif /* USE_THREAD_DEBUG */ + checklock_start(); log_ident_set("unbound-control"); log_init(NULL, 0, NULL); - checklock_start(); #ifdef USE_WINSOCK /* use registry config file in preference to compiletime location */ if(!(cfgfile=w_lookup_reg_str("Software\\Unbound", "ConfigFile"))) diff --git a/contrib/unbound/smallapp/worker_cb.c b/contrib/unbound/smallapp/worker_cb.c index 473e32a607f8..78e773938c88 100644 --- a/contrib/unbound/smallapp/worker_cb.c +++ b/contrib/unbound/smallapp/worker_cb.c @@ -99,7 +99,7 @@ struct outbound_entry* worker_send_query( int ATTR_UNUSED(dnssec), int ATTR_UNUSED(want_dnssec), int ATTR_UNUSED(nocaps), struct sockaddr_storage* ATTR_UNUSED(addr), socklen_t ATTR_UNUSED(addrlen), uint8_t* ATTR_UNUSED(zone), - size_t ATTR_UNUSED(zonelen), int ATTR_UNUSED(ssl_upstream), + size_t ATTR_UNUSED(zonelen), int ATTR_UNUSED(tcp_upstream), int ATTR_UNUSED(ssl_upstream), char* ATTR_UNUSED(tls_auth_name), struct module_qstate* ATTR_UNUSED(q)) { log_assert(0); @@ -131,7 +131,7 @@ struct outbound_entry* libworker_send_query( int ATTR_UNUSED(dnssec), int ATTR_UNUSED(want_dnssec), int ATTR_UNUSED(nocaps), struct sockaddr_storage* ATTR_UNUSED(addr), socklen_t ATTR_UNUSED(addrlen), uint8_t* ATTR_UNUSED(zone), - size_t ATTR_UNUSED(zonelen), int ATTR_UNUSED(ssl_upstream), + size_t ATTR_UNUSED(zonelen), int ATTR_UNUSED(tcp_upstream), int ATTR_UNUSED(ssl_upstream), char* ATTR_UNUSED(tls_auth_name), struct module_qstate* ATTR_UNUSED(q)) { log_assert(0); diff --git a/contrib/unbound/testdata/auth_zonemd_xfr_chain_keyinxfr.rpl b/contrib/unbound/testdata/auth_zonemd_xfr_chain_keyinxfr.rpl new file mode 100644 index 000000000000..2feec88c075a --- /dev/null +++ b/contrib/unbound/testdata/auth_zonemd_xfr_chain_keyinxfr.rpl @@ -0,0 +1,315 @@ +; config options +server: + target-fetch-policy: "0 0 0 0 0" + trust-anchor: "com. DS 1444 8 2 0d72034e3e18a9ef383c164b68302433bbde957616e10cf44575fea2abae469c" + trust-anchor-signaling: no + val-override-date: 20201020135527 + +auth-zone: + name: "example.com." + ## zonefile (or none). + ## zonefile: "example.com.zone" + ## master by IP address or hostname + ## can list multiple masters, each on one line. + ## master: + master: 1.2.3.44 + ## url for http fetch + ## url: + ## queries from downstream clients get authoritative answers. + ## for-downstream: yes + + ## The for-downstream and fallback are disabled, the key cannot be + ## retrieved by DNS lookup, it is in the xfr itself. + ## only after the zone is loaded can it be looked up. + for-downstream: no + ## queries are used to fetch authoritative answers from this zone, + ## instead of unbound itself sending queries there. + ## for-upstream: yes + for-upstream: yes + ## on failures with for-upstream, fallback to sending queries to + ## the authority servers + ## fallback-enabled: no + fallback-enabled: no + zonemd-check: yes + + ## this line generates zonefile: \n"/tmp/xxx.example.com"\n + zonefile: +TEMPFILE_NAME example.com + ## this is the inline file /tmp/xxx.example.com + ## the tempfiles are deleted when the testrun is over. +TEMPFILE_CONTENTS example.com +TEMPFILE_END + +stub-zone: + name: "." + stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET. +CONFIG_END + +SCENARIO_BEGIN Test authority zone with AXFR with ZONEMD with key in xfr + +; K.ROOT-SERVERS.NET. +RANGE_BEGIN 0 100 + ADDRESS 193.0.14.129 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS K.ROOT-SERVERS.NET. +SECTION ADDITIONAL +K.ROOT-SERVERS.NET. IN A 193.0.14.129 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION AUTHORITY +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END +RANGE_END + +; a.gtld-servers.net. +RANGE_BEGIN 0 100 + ADDRESS 192.5.6.30 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS a.gtld-servers.net. +SECTION ADDITIONAL +a.gtld-servers.net. IN A 192.5.6.30 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qname qtype +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +example.com. IN DS +SECTION ANSWER +example.com. 3600 IN DS 55566 8 2 9c148338951ce1c3b5cd3da532f3d90dfcf92595148022f2c2fd98e5deee90af +example.com. 3600 IN RRSIG DS 8 2 3600 20201116135527 20201019135527 1444 com. BpV1M171SSkbdlGawwweJwQ0W+aNaCrgkt2QTsxCvbo1acR5i3AKm4REOUzo4I36lRx26mYkF9Topkeu0aFmov7P2uUhCxk4faFK7k87k97FAqZaDGp/K9b3YCfiwJBc5pJSUW0ndU/Ve5zAh/wL493RMSC7LwJr5JjV0NxydFk= +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION AUTHORITY +example.com. IN NS ns.example.com. +example.com. 3600 IN DS 55566 8 2 9c148338951ce1c3b5cd3da532f3d90dfcf92595148022f2c2fd98e5deee90af +example.com. 3600 IN RRSIG DS 8 2 3600 20201116135527 20201019135527 1444 com. BpV1M171SSkbdlGawwweJwQ0W+aNaCrgkt2QTsxCvbo1acR5i3AKm4REOUzo4I36lRx26mYkF9Topkeu0aFmov7P2uUhCxk4faFK7k87k97FAqZaDGp/K9b3YCfiwJBc5pJSUW0ndU/Ve5zAh/wL493RMSC7LwJr5JjV0NxydFk= +SECTION ADDITIONAL +ns.example.com. IN A 1.2.3.44 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +com. IN DNSKEY +SECTION ANSWER +com. 3600 IN DNSKEY 257 3 8 AwEAAbd9WqjzE2Pynz21OG5doSf9hFzMr5dhzz2waZ3vTa+0o5r7AjTAqmA1yH/B3+aAMihUm5ucZSfVqo7+kOaRE8yFj9aivOmA1n1+JLevJq/oyvQyjxQN2Qb89LyaNUT5oKZIiL+uyyhNW3KDR3SSbQ/GBwQNDHVcZi+JDR3RC0r7 ;{id = 1444 (ksk), size = 1024b} +com. 3600 IN RRSIG DNSKEY 8 1 3600 20201116135527 20201019135527 1444 com. BEOMfWvi6RgnHaHsst+Ed265hBuCkgMR7gDpu89J7ZrVL6DzMKnNVFdgjl/9xwLj/pkukc7qeLSHjAfLlN0E4THW7PVshscQnjvXCkktG2Ejx9fTyllAqeGDh9z9QDGlQZIGTMgb9413qZhNqe2Tda9PTJRpiZ8b4bdQp6V1kVo= +SECTION ADDITIONAL +ENTRY_END +RANGE_END + +; ns.example.net. +RANGE_BEGIN 0 100 + ADDRESS 1.2.3.44 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.net. IN NS +SECTION ANSWER +example.net. IN NS ns.example.net. +SECTION ADDITIONAL +ns.example.net. IN A 1.2.3.44 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.example.net. IN A +SECTION ANSWER +ns.example.net. IN A 1.2.3.44 +SECTION AUTHORITY +example.net. IN NS ns.example.net. +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ns.example.net. IN AAAA +SECTION AUTHORITY +example.net. IN NS ns.example.net. +SECTION ADDITIONAL +www.example.net. IN A 1.2.3.44 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN NS +SECTION ANSWER +example.com. IN NS ns.example.net. +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 10.20.30.40 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +example.com. IN SOA +SECTION ANSWER +; serial, refresh, retry, expire, minimum +example.com. IN SOA ns.example.com. hostmaster.example.com. 1 3600 900 86400 3600 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR AA NOERROR +SECTION QUESTION +example.com. IN AXFR +SECTION ANSWER +example.com. 3600 IN SOA ns.example.com. hostmaster.example.com. 200154054 28800 7200 604800 3600 +example.com. 3600 IN RRSIG SOA 8 2 3600 20201116135527 20201019135527 55566 example.com. gcFHT/Q4iDZ78CK6fyY2HZr8sRtgH2Rna9fEs06RW0gqMnfDntweoIaBamOZ7NlAP84aY2bZeanmEccmkHexByUpodCoKQ4NzVXctLr0TO4PVoFyfUfj62fjhM56SF8ioDxsoDQcPtYXcjNQjwfntWofMqHCMxrb9LzbgePzhOM= +example.com. 3600 IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 8 2 3600 20201116135527 20201019135527 55566 example.com. X+V3XsbJbBi9OsHpjMkGCox8RLY/uXp/XX/O/flTrIre9fMDWm9ZGnewtuQFpLgGc6hUTi0eLsuRWRA5fZXEKUBhmoR2Ph01KgE1gvlL7v6zPWQwXVcBRUr3mOSbYdNNkHkXEjiDBGEhNkfqR216zNgw563eEGXOkLUFNIx5Zpg= +example.com. 3600 IN DNSKEY 256 3 8 AwEAAdug/L739i0mgN2nuK/bhxu3wFn5Ud9nK2+XUmZQlPUEZUC5YZvm1rfMmEWTGBn87fFxEu/kjFZHJ55JLzqsbbpVHLbmKCTT2gYR2FV2WDKROGKuYbVkJIXdKAjJ0ONuK507NinYvlWXIoxHn22KAWOd9wKgSTNHBlmGkX+ts3hh ;{id = 55566 (zsk), size = 1024b} +example.com. 3600 IN RRSIG DNSKEY 8 2 3600 20201116135527 20201019135527 55566 example.com. fsdnVg38PKQTH2mDOwkXL6Jre7JP7Gf8WI3CvIbmeYQUJtAlpcSbZkS3wInm3kKMxOuT55BWzndQzpfmpo91OqJjG27W0k9301NMLUwFprA6b9HK+iPAT0JpYPDPzcm1bQdarLzLS+eD/GPwmyVSX7Gze+08VfE8m8sOW2r7UjA= +example.com. 3600 IN TYPE63 \# 70 0bee1bc6010258f7620f93204bbb31b44f795b3409cc4abd9ef5601decc15675bd7751213152984eddce0626e6062e744b03b3e47711202fbb79e4a2eb8bc5cf46741b5cae6f +example.com. 3600 IN RRSIG TYPE63 8 2 3600 20201116135527 20201019135527 55566 example.com. orn8ZF/yqj9u4WrhiO6gtEcTaVsnZSWWZLfXhcIOiWSB8kKCxtZl5cG17dD3Du1NllUwMRqkp0KleLhIoUS9xeQ/0x05u+CYLrfQ62oAiD7q54ZQzpXJIH52aQzKV70ZnO03CZowhQBnetmIoKX6xLogKo8pt+BdQbo3oVHxV8Y= +example.com. 3600 IN NSEC bar.example.com. NS SOA RRSIG NSEC DNSKEY TYPE63 +example.com. 3600 IN RRSIG NSEC 8 2 3600 20201116135527 20201019135527 55566 example.com. ufLrlOQprAqjnH85Rt3T0Mxd3ZB0mBeeNIr84eFJ8Rk6WiWEPm0Y1R7GRufNI24Mj7iqLcL4nJM6KK6B7dJqjqu73jw1acuYNnbsoV2BNDRXRFP2FNWTpctVdi+955f3FzgsmEJXfGiSUG0YXAEcZmdCPCn5ii2jk8mk7r6KKYo= +bar.example.com. 3600 IN A 1.2.3.4 +bar.example.com. 3600 IN RRSIG A 8 3 3600 20201116135527 20201019135527 55566 example.com. NYhmRicF4C9+YxpWeQrepy4ALM1CM0USoDuGi3W5Xtp4/+YpCJfSIdR9vlJaJ2WayYuZrz9Ai2ci7oWwE1Fn3oywGwCKvGo9m0c3mC2eEtphE19wrop6pWu6um4RiFhmzYS1voraA3PAdYzze9U4NHzlk0+sb5vNZW9dSZS30Ds= +bar.example.com. 3600 IN NSEC ding.example.com. A RRSIG NSEC +bar.example.com. 3600 IN RRSIG NSEC 8 3 3600 20201116135527 20201019135527 55566 example.com. VhsGuBx20DXQZNU8ITAMnasn6NVyEjN9xtB8msH5xJn80UCuaqvFBURzcPWN3aHnykEvGfdPF/9P3WvlON0cMikWkqSLy6Q9bpvgAq13HWYh+ZcDoqLtICaB7RkBQc+6aHAqZFyQbD8/m8Kxt5eVJtV6rEuf+yPX0+3aXHhsRg0= +ding.example.com. 3600 IN A 1.2.3.4 +ding.example.com. 3600 IN RRSIG A 8 3 3600 20201116135527 20201019135527 55566 example.com. OERsruISkpd1s68ute8Xm8YXisBCTkkiDMt34K+0dVqvySOJq63d3qN18BeUxZxLyHDB1eR3nZZKqEdkTqrv2r98skhWhjnOECpFbu5gKjtN/KPexbbJ+rxC0QqciuWOC7M6YE0cvI17/RB9KhVRy5rqY2X4Gt2wk2CNeD1dAko= +ding.example.com. 3600 IN NSEC foo.example.com. A RRSIG NSEC +ding.example.com. 3600 IN RRSIG NSEC 8 3 3600 20201116135527 20201019135527 55566 example.com. nb1W2aaKrU5iAQiY8gMsoMOejID19JMTEwY2rRoe+KsvzMs0rE0ifEkqit4blXaU0tfy0foJ70uqdJFqBoGz1NcSwZ6GNk/iNfGvG3XpxZ/zqEe7kkIucqqei794G7z9psqV94yZ3WaT+IswPpWrSaWv1w41RtcWufPhe4fOAmU= +foo.example.com. 3600 IN A 1.2.3.4 +foo.example.com. 3600 IN RRSIG A 8 3 3600 20201116135527 20201019135527 55566 example.com. ZcUngb2pUejwnsshbJN/Dfr+Bzu8fcZXyqLArQ+10Bw1IPHyfx7yyUJ43V5tTYVHPSEsJzTnaWj+olVrNhVZxq5e0pgzSYPfGln2FEItEvMIOn33j8yKTpPW2MLyuFF5ZkXhosG20EUwRMvMmRHRz9mIZfwWoMbSGPukmLh8zMA= +foo.example.com. 3600 IN NSEC ns.example.com. A RRSIG NSEC +foo.example.com. 3600 IN RRSIG NSEC 8 3 3600 20201116135527 20201019135527 55566 example.com. fUZEpkEULRWDntN5Z7Kr8M83Hjhf08ECMKRpo6IBoBc3ayenj+YMgWAvFXC825wjENPYYWNGag0d32U83zCZxqgv+8uXZd3B7QDpTbL41aWZdc++s5YWTkYjyOWwJ1XHOv4nL3qEnJBXVzo/E1gbSKhTFuG97i+7J1MFd9MsC5s= +ns.example.com. 3600 IN A 127.0.0.1 +ns.example.com. 3600 IN RRSIG A 8 3 3600 20201116135527 20201019135527 55566 example.com. SiuxuPtN/ITd+Z20j8UNUHJWbLHirE8zQOWMv5fAZ1rPKpAidrZgUL8J417GdrTwkueU2ywAJ7EzFJSwNTa7o/wUnq7svmOR6Ze6UQsKuZFZGEfqPNDRp4YuF86LU5jChuo+f/IRpydHrxVwGxDPCR9KarDM+ewfW+yI5bZeZcg= +ns.example.com. 3600 IN NSEC www.example.com. A RRSIG NSEC +ns.example.com. 3600 IN RRSIG NSEC 8 3 3600 20201116135527 20201019135527 55566 example.com. 0upKNYjiow4NDJm3I1RbUddE9GGuFYEVKswww5BAc/6WHuukupncL30lskvcSKGpByDssP2Hi2CufyEtYeGWh6q1TxtOFRqFBX1p6Q5b3tBlCtvv4h31dQR9uqLvq+GkGS5MR+0LO5kWagIpZmnI8YY5plVdXEtNbp2Ar8zvz/A= +www.example.com. 3600 IN A 127.0.0.1 +www.example.com. 3600 IN RRSIG A 8 3 3600 20201116135527 20201019135527 55566 example.com. AaIeICaPjV50TDrpbyOn94+hs8EYIMTmN4pYqj7e8GIGimqQIk5jgpwSx6SOoOF+uOqkf9GKHkQTn5YVGaeXwEQleg7mPTmMYKAOk06Y7MFUO1Vwt1Vt7Wo+Cpa3x2a1CmEkfFOi4WqP43VJnUtjjKmXoKRz3VUmqByyJYUAGbQ= +www.example.com. 3600 IN NSEC example.com. A RRSIG NSEC +www.example.com. 3600 IN RRSIG NSEC 8 3 3600 20201116135527 20201019135527 55566 example.com. meg/t6nIBqQZ0d5/dT7uu/3CuP4vE+HxqFQaj2fjUNceA/6C7QIQnqQ5Kyblg+XijDkQX0yvyFNHYdgF16UDgFT7tlNUCHk1SpF5BWzV4c4tBEhxASTz7UQo111O3Tyd6CldPzO/Se15Ud0/ZYltHEqWTfY5nJoXC/OJD9V2QOI= +example.com. 3600 IN SOA ns.example.com. hostmaster.example.com. 200154054 28800 7200 604800 3600 +ENTRY_END +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 20 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA SERVFAIL +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +ENTRY_END + +STEP 30 TIME_PASSES ELAPSE 10 +STEP 40 TRAFFIC + +STEP 50 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.example.com. IN A +ENTRY_END + +; recursion happens here. +STEP 60 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +www.example.com. IN A +SECTION ANSWER +www.example.com. IN A 127.0.0.1 +ENTRY_END + +; the zonefile was updated with new contents +STEP 70 CHECK_TEMPFILE example.com +FILE_BEGIN +example.com. 3600 IN SOA ns.example.com. hostmaster.example.com. 200154054 28800 7200 604800 3600 +example.com. 3600 IN RRSIG SOA 8 2 3600 20201116135527 20201019135527 55566 example.com. gcFHT/Q4iDZ78CK6fyY2HZr8sRtgH2Rna9fEs06RW0gqMnfDntweoIaBamOZ7NlAP84aY2bZeanmEccmkHexByUpodCoKQ4NzVXctLr0TO4PVoFyfUfj62fjhM56SF8ioDxsoDQcPtYXcjNQjwfntWofMqHCMxrb9LzbgePzhOM= +example.com. 3600 IN NS ns.example.com. +example.com. 3600 IN RRSIG NS 8 2 3600 20201116135527 20201019135527 55566 example.com. X+V3XsbJbBi9OsHpjMkGCox8RLY/uXp/XX/O/flTrIre9fMDWm9ZGnewtuQFpLgGc6hUTi0eLsuRWRA5fZXEKUBhmoR2Ph01KgE1gvlL7v6zPWQwXVcBRUr3mOSbYdNNkHkXEjiDBGEhNkfqR216zNgw563eEGXOkLUFNIx5Zpg= +example.com. 3600 IN NSEC bar.example.com. NS SOA RRSIG NSEC DNSKEY ZONEMD +example.com. 3600 IN RRSIG NSEC 8 2 3600 20201116135527 20201019135527 55566 example.com. ufLrlOQprAqjnH85Rt3T0Mxd3ZB0mBeeNIr84eFJ8Rk6WiWEPm0Y1R7GRufNI24Mj7iqLcL4nJM6KK6B7dJqjqu73jw1acuYNnbsoV2BNDRXRFP2FNWTpctVdi+955f3FzgsmEJXfGiSUG0YXAEcZmdCPCn5ii2jk8mk7r6KKYo= +example.com. 3600 IN DNSKEY 256 3 8 AwEAAdug/L739i0mgN2nuK/bhxu3wFn5Ud9nK2+XUmZQlPUEZUC5YZvm1rfMmEWTGBn87fFxEu/kjFZHJ55JLzqsbbpVHLbmKCTT2gYR2FV2WDKROGKuYbVkJIXdKAjJ0ONuK507NinYvlWXIoxHn22KAWOd9wKgSTNHBlmGkX+ts3hh ;{id = 55566} +example.com. 3600 IN RRSIG DNSKEY 8 2 3600 20201116135527 20201019135527 55566 example.com. fsdnVg38PKQTH2mDOwkXL6Jre7JP7Gf8WI3CvIbmeYQUJtAlpcSbZkS3wInm3kKMxOuT55BWzndQzpfmpo91OqJjG27W0k9301NMLUwFprA6b9HK+iPAT0JpYPDPzcm1bQdarLzLS+eD/GPwmyVSX7Gze+08VfE8m8sOW2r7UjA= +example.com. 3600 IN ZONEMD 200154054 1 2 58F7620F93204BBB31B44F795B3409CC4ABD9EF5601DECC15675BD7751213152984EDDCE0626E6062E744B03B3E47711202FBB79E4A2EB8BC5CF46741B5CAE6F +example.com. 3600 IN RRSIG ZONEMD 8 2 3600 20201116135527 20201019135527 55566 example.com. orn8ZF/yqj9u4WrhiO6gtEcTaVsnZSWWZLfXhcIOiWSB8kKCxtZl5cG17dD3Du1NllUwMRqkp0KleLhIoUS9xeQ/0x05u+CYLrfQ62oAiD7q54ZQzpXJIH52aQzKV70ZnO03CZowhQBnetmIoKX6xLogKo8pt+BdQbo3oVHxV8Y= +bar.example.com. 3600 IN A 1.2.3.4 +bar.example.com. 3600 IN RRSIG A 8 3 3600 20201116135527 20201019135527 55566 example.com. NYhmRicF4C9+YxpWeQrepy4ALM1CM0USoDuGi3W5Xtp4/+YpCJfSIdR9vlJaJ2WayYuZrz9Ai2ci7oWwE1Fn3oywGwCKvGo9m0c3mC2eEtphE19wrop6pWu6um4RiFhmzYS1voraA3PAdYzze9U4NHzlk0+sb5vNZW9dSZS30Ds= +bar.example.com. 3600 IN NSEC ding.example.com. A RRSIG NSEC +bar.example.com. 3600 IN RRSIG NSEC 8 3 3600 20201116135527 20201019135527 55566 example.com. VhsGuBx20DXQZNU8ITAMnasn6NVyEjN9xtB8msH5xJn80UCuaqvFBURzcPWN3aHnykEvGfdPF/9P3WvlON0cMikWkqSLy6Q9bpvgAq13HWYh+ZcDoqLtICaB7RkBQc+6aHAqZFyQbD8/m8Kxt5eVJtV6rEuf+yPX0+3aXHhsRg0= +ding.example.com. 3600 IN A 1.2.3.4 +ding.example.com. 3600 IN RRSIG A 8 3 3600 20201116135527 20201019135527 55566 example.com. OERsruISkpd1s68ute8Xm8YXisBCTkkiDMt34K+0dVqvySOJq63d3qN18BeUxZxLyHDB1eR3nZZKqEdkTqrv2r98skhWhjnOECpFbu5gKjtN/KPexbbJ+rxC0QqciuWOC7M6YE0cvI17/RB9KhVRy5rqY2X4Gt2wk2CNeD1dAko= +ding.example.com. 3600 IN NSEC foo.example.com. A RRSIG NSEC +ding.example.com. 3600 IN RRSIG NSEC 8 3 3600 20201116135527 20201019135527 55566 example.com. nb1W2aaKrU5iAQiY8gMsoMOejID19JMTEwY2rRoe+KsvzMs0rE0ifEkqit4blXaU0tfy0foJ70uqdJFqBoGz1NcSwZ6GNk/iNfGvG3XpxZ/zqEe7kkIucqqei794G7z9psqV94yZ3WaT+IswPpWrSaWv1w41RtcWufPhe4fOAmU= +foo.example.com. 3600 IN A 1.2.3.4 +foo.example.com. 3600 IN RRSIG A 8 3 3600 20201116135527 20201019135527 55566 example.com. ZcUngb2pUejwnsshbJN/Dfr+Bzu8fcZXyqLArQ+10Bw1IPHyfx7yyUJ43V5tTYVHPSEsJzTnaWj+olVrNhVZxq5e0pgzSYPfGln2FEItEvMIOn33j8yKTpPW2MLyuFF5ZkXhosG20EUwRMvMmRHRz9mIZfwWoMbSGPukmLh8zMA= +foo.example.com. 3600 IN NSEC ns.example.com. A RRSIG NSEC +foo.example.com. 3600 IN RRSIG NSEC 8 3 3600 20201116135527 20201019135527 55566 example.com. fUZEpkEULRWDntN5Z7Kr8M83Hjhf08ECMKRpo6IBoBc3ayenj+YMgWAvFXC825wjENPYYWNGag0d32U83zCZxqgv+8uXZd3B7QDpTbL41aWZdc++s5YWTkYjyOWwJ1XHOv4nL3qEnJBXVzo/E1gbSKhTFuG97i+7J1MFd9MsC5s= +ns.example.com. 3600 IN A 127.0.0.1 +ns.example.com. 3600 IN RRSIG A 8 3 3600 20201116135527 20201019135527 55566 example.com. SiuxuPtN/ITd+Z20j8UNUHJWbLHirE8zQOWMv5fAZ1rPKpAidrZgUL8J417GdrTwkueU2ywAJ7EzFJSwNTa7o/wUnq7svmOR6Ze6UQsKuZFZGEfqPNDRp4YuF86LU5jChuo+f/IRpydHrxVwGxDPCR9KarDM+ewfW+yI5bZeZcg= +ns.example.com. 3600 IN NSEC www.example.com. A RRSIG NSEC +ns.example.com. 3600 IN RRSIG NSEC 8 3 3600 20201116135527 20201019135527 55566 example.com. 0upKNYjiow4NDJm3I1RbUddE9GGuFYEVKswww5BAc/6WHuukupncL30lskvcSKGpByDssP2Hi2CufyEtYeGWh6q1TxtOFRqFBX1p6Q5b3tBlCtvv4h31dQR9uqLvq+GkGS5MR+0LO5kWagIpZmnI8YY5plVdXEtNbp2Ar8zvz/A= +www.example.com. 3600 IN A 127.0.0.1 +www.example.com. 3600 IN RRSIG A 8 3 3600 20201116135527 20201019135527 55566 example.com. AaIeICaPjV50TDrpbyOn94+hs8EYIMTmN4pYqj7e8GIGimqQIk5jgpwSx6SOoOF+uOqkf9GKHkQTn5YVGaeXwEQleg7mPTmMYKAOk06Y7MFUO1Vwt1Vt7Wo+Cpa3x2a1CmEkfFOi4WqP43VJnUtjjKmXoKRz3VUmqByyJYUAGbQ= +www.example.com. 3600 IN NSEC example.com. A RRSIG NSEC +www.example.com. 3600 IN RRSIG NSEC 8 3 3600 20201116135527 20201019135527 55566 example.com. meg/t6nIBqQZ0d5/dT7uu/3CuP4vE+HxqFQaj2fjUNceA/6C7QIQnqQ5Kyblg+XijDkQX0yvyFNHYdgF16UDgFT7tlNUCHk1SpF5BWzV4c4tBEhxASTz7UQo111O3Tyd6CldPzO/Se15Ud0/ZYltHEqWTfY5nJoXC/OJD9V2QOI= +FILE_END + +SCENARIO_END diff --git a/contrib/unbound/testdata/fwd_error_retries.rpl b/contrib/unbound/testdata/fwd_error_retries.rpl new file mode 100644 index 000000000000..b63086c0f46a --- /dev/null +++ b/contrib/unbound/testdata/fwd_error_retries.rpl @@ -0,0 +1,27 @@ +; config options +server: + outbound-msg-retry: 1 + +forward-zone: + name: "." + forward-addr: 216.0.0.1 +CONFIG_END +SCENARIO_BEGIN Test basic forwarding with servfail and retry of 1 +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +www.example.com. IN A +ENTRY_END +; query fails with servfail, now we make only outgoing-msg-retry=1 retries +STEP 2 ERROR +; returns servfail +STEP 14 CHECK_ANSWER +ENTRY_BEGIN +MATCH opcode qname qtype +SECTION QUESTION +REPLY SERVFAIL QR RD RA +MATCH all +www.example.com. IN A +ENTRY_END +SCENARIO_END diff --git a/contrib/unbound/testdata/fwd_udp_with_tcp_upstream.tdir/fwd_udp_with_tcp_upstream.conf b/contrib/unbound/testdata/fwd_udp_with_tcp_upstream.tdir/fwd_udp_with_tcp_upstream.conf new file mode 100644 index 000000000000..6daf2eeecc36 --- /dev/null +++ b/contrib/unbound/testdata/fwd_udp_with_tcp_upstream.tdir/fwd_udp_with_tcp_upstream.conf @@ -0,0 +1,20 @@ +server: + verbosity: 5 + # num-threads: 1 + interface: 127.0.0.1 + port: @PORT@ + use-syslog: no + directory: "" + pidfile: "unbound.pid" + chroot: "" + username: "" + do-not-query-localhost: no +forward-zone: + name: "tcp.example.com" + forward-addr: "127.0.0.1@@TOPORT@" + forward-tcp-upstream: "yes" +forward-zone: + name: "udp.example.com" + forward-addr: "127.0.0.1@@TOPORT@" + forward-tcp-upstream: "no" + diff --git a/contrib/unbound/testdata/fwd_udp_with_tcp_upstream.tdir/fwd_udp_with_tcp_upstream.dsc b/contrib/unbound/testdata/fwd_udp_with_tcp_upstream.tdir/fwd_udp_with_tcp_upstream.dsc new file mode 100644 index 000000000000..5b1f0d3d1ab4 --- /dev/null +++ b/contrib/unbound/testdata/fwd_udp_with_tcp_upstream.tdir/fwd_udp_with_tcp_upstream.dsc @@ -0,0 +1,16 @@ +BaseName: fwd_udp_with_tcp_upstream +Version: 1.0 +Description: Forward an UDP packet to upstream via TCP and return reply. +CreationDate: Thu Aug 5 07:44:41 CEST 2021 +Maintainer: ziollek +Category: +Component: +CmdDepends: +Depends: +Help: +Pre: fwd_udp_with_tcp_upstream.pre +Post: fwd_udp_with_tcp_upstream.post +Test: fwd_udp_with_tcp_upstream.test +AuxFiles: +Passed: +Failure: diff --git a/contrib/unbound/testdata/fwd_udp_with_tcp_upstream.tdir/fwd_udp_with_tcp_upstream.post b/contrib/unbound/testdata/fwd_udp_with_tcp_upstream.tdir/fwd_udp_with_tcp_upstream.post new file mode 100644 index 000000000000..0013eca71a4d --- /dev/null +++ b/contrib/unbound/testdata/fwd_udp_with_tcp_upstream.tdir/fwd_udp_with_tcp_upstream.post @@ -0,0 +1,10 @@ +# #-- fwd_udp_with_tcp_upstream.post --# +# source the master var file when it's there +[ -f ../.tpkg.var.master ] && source ../.tpkg.var.master +# source the test var file when it's there +[ -f .tpkg.var.test ] && source .tpkg.var.test +# +# do your teardown here +. ../common.sh +kill_pid $FWD_PID +kill_pid $UNBOUND_PID diff --git a/contrib/unbound/testdata/fwd_udp_with_tcp_upstream.tdir/fwd_udp_with_tcp_upstream.pre b/contrib/unbound/testdata/fwd_udp_with_tcp_upstream.tdir/fwd_udp_with_tcp_upstream.pre new file mode 100644 index 000000000000..546787a5fc9f --- /dev/null +++ b/contrib/unbound/testdata/fwd_udp_with_tcp_upstream.tdir/fwd_udp_with_tcp_upstream.pre @@ -0,0 +1,31 @@ +# #-- fwd_udp_with_tcp_upstream.pre--# +# source the master var file when it's there +[ -f ../.tpkg.var.master ] && source ../.tpkg.var.master +# use .tpkg.var.test for in test variable passing +[ -f .tpkg.var.test ] && source .tpkg.var.test + +. ../common.sh +get_random_port 2 +UNBOUND_PORT=$RND_PORT +FWD_PORT=$(($RND_PORT + 1)) +echo "UNBOUND_PORT=$UNBOUND_PORT" >> .tpkg.var.test +echo "FWD_PORT=$FWD_PORT" >> .tpkg.var.test + +# start forwarder +get_ldns_testns +$LDNS_TESTNS -p $FWD_PORT fwd_udp_with_tcp_upstream.testns >fwd.log 2>&1 & +FWD_PID=$! +echo "FWD_PID=$FWD_PID" >> .tpkg.var.test + +# make config file +sed -e 's/@PORT\@/'$UNBOUND_PORT'/' -e 's/@TOPORT\@/'$FWD_PORT'/' < fwd_udp_with_tcp_upstream.conf > ub.conf +# start unbound in the background +PRE="../.." +$PRE/unbound -d -c ub.conf >unbound.log 2>&1 & +UNBOUND_PID=$! +echo "UNBOUND_PID=$UNBOUND_PID" >> .tpkg.var.test + +cat .tpkg.var.test +wait_ldns_testns_up fwd.log +wait_unbound_up unbound.log + diff --git a/contrib/unbound/testdata/fwd_udp_with_tcp_upstream.tdir/fwd_udp_with_tcp_upstream.test b/contrib/unbound/testdata/fwd_udp_with_tcp_upstream.tdir/fwd_udp_with_tcp_upstream.test new file mode 100644 index 000000000000..fad6497beb15 --- /dev/null +++ b/contrib/unbound/testdata/fwd_udp_with_tcp_upstream.tdir/fwd_udp_with_tcp_upstream.test @@ -0,0 +1,35 @@ +# #-- fwd_udp_with_tcp_upstream.test --# +# source the master var file when it's there +[ -f ../.tpkg.var.master ] && source ../.tpkg.var.master +# use .tpkg.var.test for in test variable passing +[ -f .tpkg.var.test ] && source .tpkg.var.test + +PRE="../.." +# do the test +echo "> dig tcp.example.com." +dig @localhost -p $UNBOUND_PORT tcp.example.com. | tee outfile +echo "> cat logfiles" +cat fwd.log +cat unbound.log +echo "> check answer" +if grep "10.20.30.40" outfile; then + echo "OK" +else + echo "Not OK" + exit 1 +fi + +echo "> dig udp.example.com." +dig @localhost -p $UNBOUND_PORT udp.example.com. | tee outfile +echo "> cat logfiles" +cat fwd.log +cat unbound.log +echo "> check answer" +if grep "10.20.30.80" outfile; then + echo "OK" +else + echo "Not OK" + exit 1 +fi + +exit 0 diff --git a/contrib/unbound/testdata/fwd_udp_with_tcp_upstream.tdir/fwd_udp_with_tcp_upstream.testns b/contrib/unbound/testdata/fwd_udp_with_tcp_upstream.tdir/fwd_udp_with_tcp_upstream.testns new file mode 100644 index 000000000000..04089af0e1b6 --- /dev/null +++ b/contrib/unbound/testdata/fwd_udp_with_tcp_upstream.tdir/fwd_udp_with_tcp_upstream.testns @@ -0,0 +1,25 @@ +; nameserver test file +$ORIGIN example.com. +$TTL 3600 + +ENTRY_BEGIN +MATCH opcode qtype qname +MATCH TCP +REPLY QR AA NOERROR +ADJUST copy_id +SECTION QUESTION +tcp IN A +SECTION ANSWER +tcp IN A 10.20.30.40 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +MATCH UDP +REPLY QR AA NOERROR +ADJUST copy_id +SECTION QUESTION +udp IN A +SECTION ANSWER +udp IN A 10.20.30.80 +ENTRY_END diff --git a/contrib/unbound/testdata/http_user_agent.tdir/http_user_agent.test b/contrib/unbound/testdata/http_user_agent.tdir/http_user_agent.test index afc0fbbe6f4b..dce2d476c8f6 100644 --- a/contrib/unbound/testdata/http_user_agent.tdir/http_user_agent.test +++ b/contrib/unbound/testdata/http_user_agent.tdir/http_user_agent.test @@ -81,12 +81,12 @@ echo "> cat logfiles" cat petal.log cat unbound.log -# check petal.log for the correct number of occurences. +# check petal.log for the correct number of occurrences. # It should be 2 User-Agents, one being the custom. -echo "> check User-Agent occurences" -occurences=`grep "User-Agent:" petal.log | wc -l` -echo $occurences -if test $occurences -eq 2; then +echo "> check User-Agent occurrences" +occurrences=`grep "User-Agent:" petal.log | wc -l` +echo $occurrences +if test $occurrences -eq 2; then echo "OK" else echo "Not OK" diff --git a/contrib/unbound/testdata/rpz_clientip.rpl b/contrib/unbound/testdata/rpz_clientip.rpl new file mode 100644 index 000000000000..78e05ad91994 --- /dev/null +++ b/contrib/unbound/testdata/rpz_clientip.rpl @@ -0,0 +1,264 @@ +; config options +server: + module-config: "respip validator iterator" + target-fetch-policy: "0 0 0 0 0" + qname-minimisation: no + minimal-responses: no + access-control: 192.0.0.0/8 allow + +rpz: + name: "rpz.example.com." + zonefile: +TEMPFILE_NAME rpz.example.com +TEMPFILE_CONTENTS rpz.example.com +$ORIGIN example.com. +rpz 3600 IN SOA ns1.rpz.example.com. hostmaster.rpz.example.com. ( + 1379078166 28800 7200 604800 7200 ) + 3600 IN NS ns1.rpz.example.com. + 3600 IN NS ns2.rpz.example.com. +$ORIGIN rpz.example.com. +24.0.0.0.192.rpz-client-ip CNAME . +24.0.1.0.192.rpz-client-ip CNAME *. +24.0.2.0.192.rpz-client-ip CNAME rpz-drop. +24.0.3.0.192.rpz-client-ip CNAME rpz-passthru. +24.0.4.0.192.rpz-client-ip CNAME rpz-tcp-only. +24.0.5.0.192.rpz-client-ip A 127.0.0.1 +24.0.5.0.192.rpz-client-ip TXT "42" +TEMPFILE_END + +stub-zone: + name: "a." + stub-addr: 10.20.30.40 +CONFIG_END + +SCENARIO_BEGIN Test RPZ client ip triggers + +RANGE_BEGIN 0 100 + ADDRESS 10.20.30.40 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +a. IN NS +SECTION ANSWER +a. IN NS ns.a. +SECTION ADDITIONAL +ns.a IN A 10.20.30.40 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +a.a. IN TXT +SECTION ANSWER +a.a. IN TXT "upstream txt rr a.a." +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +a.a. IN A +SECTION ANSWER +a.a. IN A 10.20.30.40 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +a.a. IN AAAA +SECTION ANSWER +a.a. IN AAAA 2001:db8::123 +ENTRY_END + +RANGE_END + +; unrelated client ip address -- passthru + +STEP 10 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +a.a. IN TXT +ENTRY_END + +STEP 11 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +a.a. IN TXT +SECTION ANSWER +a.a. IN TXT "upstream txt rr a.a." +ENTRY_END + +; should be NXDOMAIN + +STEP 20 QUERY ADDRESS 192.0.0.1 +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +a.a. IN TXT +ENTRY_END + +STEP 21 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR AA RD RA NXDOMAIN +SECTION QUESTION +a.a. IN TXT +SECTION ANSWER +ENTRY_END + +; should be NODATA + +STEP 30 QUERY ADDRESS 192.0.1.1 +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +a.a. IN TXT +ENTRY_END + +STEP 31 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR AA RD RA NOERROR +SECTION QUESTION +a.a. IN TXT +SECTION ANSWER +ENTRY_END + +; should be PASSTHRU + +STEP 40 QUERY ADDRESS 192.0.3.1 +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +a.a. IN TXT +ENTRY_END + +STEP 41 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +a.a. IN TXT +SECTION ANSWER +a.a. IN TXT "upstream txt rr a.a." +ENTRY_END + +; should be TRUNCATED + +STEP 50 QUERY ADDRESS 192.0.4.1 +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +a.a. IN TXT +ENTRY_END + +STEP 51 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR AA TC RD RA NOERROR +SECTION QUESTION +a.a. IN TXT +SECTION ANSWER +ENTRY_END + +; should not be TRUNCATED via TCP + +STEP 52 QUERY ADDRESS 192.0.4.1 +ENTRY_BEGIN +MATCH TCP +REPLY RD +SECTION QUESTION +a.a. IN TXT +ENTRY_END + +STEP 53 CHECK_ANSWER +ENTRY_BEGIN +MATCH all TCP +REPLY QR RD RA NOERROR +SECTION QUESTION +a.a. IN TXT +SECTION ANSWER +a.a. IN TXT "upstream txt rr a.a." +ENTRY_END + +; should be synthesized + +STEP 60 QUERY ADDRESS 192.0.5.1 +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +a.a. IN A +ENTRY_END + +STEP 61 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR AA RD RA NOERROR +SECTION QUESTION +a.a. IN A +SECTION ANSWER +a.a. IN A 127.0.0.1 +SECTION ADDITIONAL +rpz.example.com. 3600 IN SOA ns1.rpz.example.com. hostmaster.rpz.example.com. ( 1379078166 28800 7200 604800 7200 ) +ENTRY_END + +; should be synthesized + +STEP 62 QUERY ADDRESS 192.0.5.1 +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +a.a. IN TXT +ENTRY_END + +STEP 63 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR AA RD RA NOERROR +SECTION QUESTION +a.a. IN TXT +SECTION ANSWER +a.a. IN TXT "42" +SECTION ADDITIONAL +rpz.example.com. 3600 IN SOA ns1.rpz.example.com. hostmaster.rpz.example.com. ( 1379078166 28800 7200 604800 7200 ) +ENTRY_END + +; should be synthesized NODATA + +STEP 64 QUERY ADDRESS 192.0.5.1 +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +a.a. IN AAAA +ENTRY_END + +STEP 65 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR AA RD RA NOERROR +SECTION QUESTION +a.a. IN AAAA +SECTION ADDITIONAL +rpz.example.com. 3600 IN SOA ns1.rpz.example.com. hostmaster.rpz.example.com. ( 1379078166 28800 7200 604800 7200 ) +ENTRY_END + +; should be DROPPED + +STEP 90 QUERY ADDRESS 192.0.2.1 +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +a.a. IN TXT +ENTRY_END + +SCENARIO_END diff --git a/contrib/unbound/testdata/rpz_nsdname.rpl b/contrib/unbound/testdata/rpz_nsdname.rpl new file mode 100644 index 000000000000..08ff3c2e2f5b --- /dev/null +++ b/contrib/unbound/testdata/rpz_nsdname.rpl @@ -0,0 +1,390 @@ +; config options +server: + module-config: "respip validator iterator" + target-fetch-policy: "0 0 0 0 0" + qname-minimisation: no + access-control: 192.0.0.0/8 allow + +rpz: + name: "rpz.example.com." + rpz-log: yes + rpz-log-name: "rpz.example.com" + zonefile: +TEMPFILE_NAME rpz.example.com +TEMPFILE_CONTENTS rpz.example.com +$ORIGIN example.com. +rpz 3600 IN SOA ns1.rpz.example.com. hostmaster.rpz.example.com. ( + 1379078166 28800 7200 604800 7200 ) + 3600 IN NS ns1.rpz.example.com. + 3600 IN NS ns2.rpz.example.com. +$ORIGIN rpz.example.com. +ns1.gotham.aa.rpz-nsdname CNAME . +ns1.gotham.bb.rpz-nsdname CNAME *. +ns1.gotham.cc.rpz-nsdname CNAME rpz-drop. +ns1.gotham.com.rpz-nsdname CNAME rpz-passthru. +ns1.gotham.dd.rpz-nsdname CNAME rpz-tcp-only. +ns1.gotham.ff.rpz-nsdname A 127.0.0.1 +ns1.gotham.ff.rpz-nsdname TXT "42" +TEMPFILE_END + +stub-zone: + name: "." + stub-addr: 1.1.1.1 +CONFIG_END + +SCENARIO_BEGIN Test RPZ nsip triggers + +; . -------------------------------------------------------------------------- +RANGE_BEGIN 0 100 + ADDRESS 1.1.1.1 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS ns.root. +SECTION ADDITIONAL +ns.root IN A 1.1.1.1 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +com. IN A +SECTION AUTHORITY +com. IN NS ns1.com. +SECTION ADDITIONAL +ns1.com. IN A 8.8.8.8 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +aa. IN A +SECTION AUTHORITY +aa. IN NS ns1.aa. +SECTION ADDITIONAL +ns1.aa. IN A 8.8.0.8 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +bb. IN A +SECTION AUTHORITY +bb. IN NS ns1.bb. +SECTION ADDITIONAL +ns1.bb. IN A 8.8.1.8 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +cc. IN A +SECTION AUTHORITY +cc. IN NS ns1.cc. +SECTION ADDITIONAL +ns1.cc. IN A 8.8.2.8 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +dd. IN A +SECTION AUTHORITY +dd. IN NS ns1.dd. +SECTION ADDITIONAL +ns1.dd. IN A 8.8.3.8 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +ee. IN A +SECTION AUTHORITY +ee. IN NS ns1.ee. +SECTION ADDITIONAL +ns1.ee. IN A 8.8.5.8 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +ff. IN A +SECTION AUTHORITY +ff. IN NS ns1.ff. +SECTION ADDITIONAL +ns1.ff. IN A 8.8.6.8 +ENTRY_END + +RANGE_END + +; com. ----------------------------------------------------------------------- +RANGE_BEGIN 0 100 + ADDRESS 8.8.8.8 + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS ns1.com. +SECTION ADDITIONAL +ns1.com. IN A 8.8.8.8 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +gotham.com. IN A +SECTION AUTHORITY +gotham.com. IN NS ns1.gotham.com. +SECTION ADDITIONAL +ns1.gotham.com. IN A 192.0.6.1 +ENTRY_END + +RANGE_END + +; aa. ------------------------------------------------------------------------ +RANGE_BEGIN 0 100 + ADDRESS 8.8.0.8 + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +aa. IN NS +SECTION ANSWER +aa. IN NS ns1.aa. +SECTION ADDITIONAL +ns1.aa. IN A 8.8.0.8 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +gotham.aa. IN A +SECTION AUTHORITY +gotham.aa. IN NS ns1.gotham.aa. +SECTION ADDITIONAL +ns1.gotham.aa. IN A 192.0.0.1 +ENTRY_END + +RANGE_END + +; bb. ------------------------------------------------------------------------ +RANGE_BEGIN 0 100 + ADDRESS 8.8.1.8 + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +bb. IN NS +SECTION ANSWER +bb. IN NS ns1.bb. +SECTION ADDITIONAL +ns1.bb. IN A 8.8.1.8 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +gotham.bb. IN A +SECTION AUTHORITY +gotham.bb. IN NS ns1.gotham.bb. +SECTION ADDITIONAL +ns1.gotham.bb. IN A 192.0.1.1 +ENTRY_END + +RANGE_END + +; ff. ------------------------------------------------------------------------ +RANGE_BEGIN 0 100 + ADDRESS 8.8.6.8 + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ff. IN NS +SECTION ANSWER +ff. IN NS ns1.ff. +SECTION ADDITIONAL +ns1.ff. IN A 8.8.6.8 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +gotham.ff. IN A +SECTION AUTHORITY +gotham.ff. IN NS ns1.gotham.ff. +SECTION ADDITIONAL +ns1.gotham.ff. IN A 192.0.5.1 +ENTRY_END + +RANGE_END + +; ns1.gotham.com. ------------------------------------------------------------ +RANGE_BEGIN 0 100 + ADDRESS 192.0.6.1 + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +gotham.com. IN A +SECTION ANSWER +gotham.com. IN A 192.0.6.2 +ENTRY_END + +RANGE_END + +; ns1.gotham.aa. ------------------------------------------------------------- +RANGE_BEGIN 0 100 + ADDRESS 192.0.0.1 + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +gotham.aa. IN A +SECTION ANSWER +gotham.aa. IN A 192.0.0.2 +ENTRY_END + +RANGE_END + +; ns1.gotham.bb. ------------------------------------------------------------- +RANGE_BEGIN 0 100 + ADDRESS 192.0.1.1 + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +gotham.bb. IN A +SECTION ANSWER +gotham.bb. IN A 192.0.1.2 +ENTRY_END + +RANGE_END + +; ns1.gotham.ff. ------------------------------------------------------------- +RANGE_BEGIN 0 100 + ADDRESS 192.0.5.1 + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +gotham.ff. IN A +SECTION ANSWER +gotham.ff. IN A 192.0.5.2 +ENTRY_END + +RANGE_END + +; ---------------------------------------------------------------------------- + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +gotham.com. IN A +ENTRY_END + +STEP 2 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +gotham.com. IN A +SECTION ANSWER +gotham.com. IN A 192.0.6.2 +ENTRY_END + +STEP 10 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +gotham.aa. IN A +ENTRY_END + +STEP 11 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NXDOMAIN +SECTION QUESTION +gotham.aa. IN A +SECTION ANSWER +ENTRY_END + +STEP 20 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +gotham.bb. IN A +ENTRY_END + +STEP 21 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AA NOERROR +SECTION QUESTION +gotham.bb. IN A +SECTION ANSWER +ENTRY_END + +STEP 30 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +gotham.ff. IN A +ENTRY_END + +STEP 31 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AA NOERROR +SECTION QUESTION +gotham.ff. IN A +SECTION ANSWER +gotham.ff. IN A 127.0.0.1 +ENTRY_END + +SCENARIO_END diff --git a/contrib/unbound/testdata/rpz_nsip.rpl b/contrib/unbound/testdata/rpz_nsip.rpl new file mode 100644 index 000000000000..ac132cae0996 --- /dev/null +++ b/contrib/unbound/testdata/rpz_nsip.rpl @@ -0,0 +1,408 @@ +; config options +server: + module-config: "respip validator iterator" + target-fetch-policy: "0 0 0 0 0" + qname-minimisation: no + access-control: 192.0.0.0/8 allow + +rpz: + name: "rpz.example.com." + rpz-log: yes + rpz-log-name: "rpz.example.com" + zonefile: +TEMPFILE_NAME rpz.example.com +TEMPFILE_CONTENTS rpz.example.com +$ORIGIN example.com. +rpz 3600 IN SOA ns1.rpz.gotham.com. hostmaster.rpz.example.com. ( + 1379078166 28800 7200 604800 7200 ) + 3600 IN NS ns1.rpz.example.com. + 3600 IN NS ns2.rpz.example.com. +$ORIGIN rpz.example.com. +24.0.0.0.192.rpz-nsip CNAME . +24.0.1.0.192.rpz-nsip CNAME *. +24.0.2.0.192.rpz-nsip CNAME rpz-drop. +24.0.3.0.192.rpz-nsip CNAME rpz-passthru. +24.0.4.0.192.rpz-nsip CNAME rpz-tcp-only. +24.0.5.0.192.rpz-nsip A 127.0.0.1 +24.0.5.0.192.rpz-nsip TXT "42" +TEMPFILE_END + +stub-zone: + name: "." + stub-addr: 1.1.1.1 +CONFIG_END + +SCENARIO_BEGIN Test RPZ nsip triggers + +; . -------------------------------------------------------------------------- +RANGE_BEGIN 0 100 + ADDRESS 1.1.1.1 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS ns.root. +SECTION ADDITIONAL +ns.root IN A 1.1.1.1 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +com. IN A +SECTION AUTHORITY +com. IN NS ns1.com. +SECTION ADDITIONAL +ns1.com. IN A 8.8.8.8 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +aa. IN A +SECTION AUTHORITY +aa. IN NS ns1.aa. +SECTION ADDITIONAL +ns1.aa. IN A 8.8.0.8 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +bb. IN A +SECTION AUTHORITY +bb. IN NS ns1.bb. +SECTION ADDITIONAL +ns1.bb. IN A 8.8.1.8 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +cc. IN A +SECTION AUTHORITY +cc. IN NS ns1.cc. +SECTION ADDITIONAL +ns1.cc. IN A 8.8.2.8 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +dd. IN A +SECTION AUTHORITY +dd. IN NS ns1.dd. +SECTION ADDITIONAL +ns1.dd. IN A 8.8.3.8 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +ee. IN A +SECTION AUTHORITY +ee. IN NS ns1.ee. +SECTION ADDITIONAL +ns1.ee. IN A 8.8.5.8 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +ff. IN A +SECTION AUTHORITY +ff. IN NS ns1.ff. +SECTION ADDITIONAL +ns1.ff. IN A 8.8.6.8 +ENTRY_END + +RANGE_END + +; com. ----------------------------------------------------------------------- +RANGE_BEGIN 0 100 + ADDRESS 8.8.8.8 + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +com. IN NS +SECTION ANSWER +com. IN NS ns1.com. +SECTION ADDITIONAL +ns1.com. IN A 8.8.8.8 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +gotham.com. IN A +SECTION AUTHORITY +gotham.com. IN NS ns1.gotham.com. +SECTION ADDITIONAL +ns1.gotham.com. IN A 192.0.6.1 +ENTRY_END + +RANGE_END + +; aa. ------------------------------------------------------------------------ +RANGE_BEGIN 0 100 + ADDRESS 8.8.0.8 + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +aa. IN NS +SECTION ANSWER +aa. IN NS ns1.aa. +SECTION ADDITIONAL +ns1.aa. IN A 8.8.0.8 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +gotham.aa. IN A +SECTION AUTHORITY +gotham.aa. IN NS ns1.gotham.aa. +SECTION ADDITIONAL +ns1.gotham.aa. IN A 192.0.0.1 +ENTRY_END + +RANGE_END + +; bb. ------------------------------------------------------------------------ +RANGE_BEGIN 0 100 + ADDRESS 8.8.1.8 + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +bb. IN NS +SECTION ANSWER +bb. IN NS ns1.bb. +SECTION ADDITIONAL +ns1.bb. IN A 8.8.1.8 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +gotham.bb. IN A +SECTION AUTHORITY +gotham.bb. IN NS ns1.gotham.bb. +SECTION ADDITIONAL +ns1.gotham.bb. IN A 192.0.1.1 +ENTRY_END + +RANGE_END + +; ff. ------------------------------------------------------------------------ +RANGE_BEGIN 0 100 + ADDRESS 8.8.6.8 + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +ff. IN NS +SECTION ANSWER +ff. IN NS ns1.ff. +SECTION ADDITIONAL +ns1.ff. IN A 8.8.6.8 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode subdomain +ADJUST copy_id copy_query +REPLY QR NOERROR +SECTION QUESTION +gotham.ff. IN A +SECTION AUTHORITY +gotham.ff. IN NS ns1.gotham.ff. +SECTION ADDITIONAL +ns1.gotham.ff. IN A 192.0.5.1 +ENTRY_END + +RANGE_END + +; ns1.gotham.com. ------------------------------------------------------------ +RANGE_BEGIN 0 100 + ADDRESS 192.0.6.1 + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +gotham.com. IN A +SECTION ANSWER +gotham.com. IN A 192.0.6.2 +ENTRY_END + +RANGE_END + +; ns1.gotham.aa. ------------------------------------------------------------- +RANGE_BEGIN 0 100 + ADDRESS 192.0.0.1 + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +gotham.aa. IN A +SECTION ANSWER +gotham.aa. IN A 192.0.0.2 +ENTRY_END + +RANGE_END + +; ns1.gotham.bb. ------------------------------------------------------------- +RANGE_BEGIN 0 100 + ADDRESS 192.0.1.1 + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +gotham.bb. IN A +SECTION ANSWER +gotham.bb. IN A 192.0.1.2 +ENTRY_END + +RANGE_END + +; ns1.gotham.ff. ------------------------------------------------------------- +RANGE_BEGIN 0 100 + ADDRESS 192.0.5.1 + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +gotham.ff. IN A +SECTION ANSWER +gotham.ff. IN A 192.0.5.2 +ENTRY_END + +RANGE_END + +; ---------------------------------------------------------------------------- + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +gotham.com. IN A +ENTRY_END + +STEP 2 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +gotham.com. IN A +SECTION ANSWER +gotham.com. IN A 192.0.6.2 +ENTRY_END + +STEP 10 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +gotham.aa. IN A +ENTRY_END + +STEP 11 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NXDOMAIN +SECTION QUESTION +gotham.aa. IN A +SECTION ANSWER +ENTRY_END + +STEP 20 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +gotham.bb. IN A +ENTRY_END + +STEP 21 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AA NOERROR +SECTION QUESTION +gotham.bb. IN A +SECTION ANSWER +ENTRY_END + +STEP 30 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +gotham.ff. IN A +ENTRY_END + +STEP 31 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AA NOERROR +SECTION QUESTION +gotham.ff. IN A +SECTION ANSWER +gotham.ff. IN A 127.0.0.1 +ENTRY_END + +; again with more cache items +STEP 40 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +gotham.ff. IN A +ENTRY_END + +STEP 41 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA AA NOERROR +SECTION QUESTION +gotham.ff. IN A +SECTION ANSWER +gotham.ff. IN A 127.0.0.1 +ENTRY_END + +SCENARIO_END diff --git a/contrib/unbound/testdata/rpz_qname_tcponly.rpl b/contrib/unbound/testdata/rpz_qname_tcponly.rpl new file mode 100644 index 000000000000..d30b88616227 --- /dev/null +++ b/contrib/unbound/testdata/rpz_qname_tcponly.rpl @@ -0,0 +1,117 @@ +; config options +server: + module-config: "respip validator iterator" + target-fetch-policy: "0 0 0 0 0" + qname-minimisation: no + +rpz: + name: "rpz.example.com." + zonefile: +TEMPFILE_NAME rpz.example.com +TEMPFILE_CONTENTS rpz.example.com +$ORIGIN example.com. +rpz 3600 IN SOA ns1.rpz.example.com. hostmaster.rpz.example.com. ( + 1379078166 28800 7200 604800 7200 ) + 3600 IN NS ns1.rpz.example.com. + 3600 IN NS ns2.rpz.example.com. +$ORIGIN rpz.example.com. +a.a CNAME rpz-passthru. +b.a CNAME rpz-tcp-only. +TEMPFILE_END + +stub-zone: + name: "a." + stub-addr: 10.20.30.40 +CONFIG_END + +SCENARIO_BEGIN Test RPZ qname trigger and tcp-only action + +RANGE_BEGIN 0 100 + ADDRESS 10.20.30.40 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +a. IN NS +SECTION ANSWER +a. IN NS ns.a. +SECTION ADDITIONAL +ns.a IN A 10.20.30.40 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +a.a. IN TXT +SECTION ANSWER +a.a. IN TXT "upstream txt rr a.a." +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +b.a. IN TXT +SECTION ANSWER +b.a. IN TXT "upstream txt rr b.a." +ENTRY_END + +RANGE_END + +STEP 10 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +a.a. IN TXT +ENTRY_END + +STEP 11 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +a.a. IN TXT +SECTION ANSWER +a.a. IN TXT "upstream txt rr a.a." +ENTRY_END + +STEP 20 QUERY +ENTRY_BEGIN +MATCH UDP +REPLY RD +SECTION QUESTION +b.a. IN TXT +ENTRY_END + +STEP 21 CHECK_ANSWER +ENTRY_BEGIN +MATCH all UDP +REPLY QR AA TC RD RA NOERROR +SECTION QUESTION +b.a. IN TXT +SECTION ANSWER +ENTRY_END + +STEP 30 QUERY +ENTRY_BEGIN +MATCH TCP +REPLY RD +SECTION QUESTION +b.a. IN TXT +ENTRY_END + +STEP 31 CHECK_ANSWER +ENTRY_BEGIN +MATCH all TCP +REPLY QR RD RA NOERROR +SECTION QUESTION +b.a. IN TXT +SECTION ANSWER +b.a. IN TXT "upstream txt rr b.a." +ENTRY_END + +SCENARIO_END diff --git a/contrib/unbound/testdata/rpz_respip_tcponly.rpl b/contrib/unbound/testdata/rpz_respip_tcponly.rpl new file mode 100644 index 000000000000..c495de2038a1 --- /dev/null +++ b/contrib/unbound/testdata/rpz_respip_tcponly.rpl @@ -0,0 +1,207 @@ +; config options +server: + module-config: "respip validator iterator" + target-fetch-policy: "0 0 0 0 0" + qname-minimisation: no + +rpz: + name: "rpz.example.com." + zonefile: +TEMPFILE_NAME rpz.example.com +TEMPFILE_CONTENTS rpz.example.com +$ORIGIN example.com. +rpz 3600 IN SOA ns1.rpz.example.com. hostmaster.rpz.example.com. ( + 1379078166 28800 7200 604800 7200 ) + 3600 IN NS ns1.rpz.example.com. + 3600 IN NS ns2.rpz.example.com. +$ORIGIN rpz.example.com. +8.0.0.0.10.rpz-ip CNAME *. +16.0.0.10.10.rpz-ip CNAME . +24.0.10.10.10.rpz-ip CNAME rpz-drop. +32.10.10.10.10.rpz-ip CNAME rpz-passthru. +32.1.1.1.10.rpz-ip CNAME rpz-tcp-only. +TEMPFILE_END + +stub-zone: + name: "." + stub-addr: 10.20.30.40 +CONFIG_END + +SCENARIO_BEGIN Test RPZ response IP address trigger and tcp-only action + +RANGE_BEGIN 0 100 + ADDRESS 10.20.30.40 +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS ns. +SECTION ADDITIONAL +ns. IN A 10.20.30.40 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +a. IN A +SECTION ANSWER +a. IN A 10.0.0.123 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +b. IN A +SECTION ANSWER +b. IN A 10.1.0.123 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +c. IN A +SECTION ANSWER +c. IN A 10.11.0.123 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +d. IN A +SECTION ANSWER +d. IN A 10.10.0.123 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +f. IN A +SECTION ANSWER +f. IN A 10.10.10.10 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +ADJUST copy_id +REPLY QR NOERROR +SECTION QUESTION +y. IN A +SECTION ANSWER +y. IN A 10.1.1.1 +ENTRY_END + +RANGE_END + +STEP 1 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +a. IN A +ENTRY_END + +STEP 2 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +a. IN A +SECTION ANSWER +ENTRY_END + +STEP 10 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +b. IN A +ENTRY_END + +STEP 11 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +b. IN A +SECTION ANSWER +ENTRY_END + +STEP 13 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +d. IN A +ENTRY_END + +STEP 14 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NXDOMAIN +SECTION QUESTION +d. IN A +SECTION ANSWER +ENTRY_END + +STEP 17 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +f. IN A +ENTRY_END + +STEP 18 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR RD RA NOERROR +SECTION QUESTION +f. IN A +SECTION ANSWER +f. IN A 10.10.10.10 +ENTRY_END + +STEP 30 QUERY +ENTRY_BEGIN +REPLY RD +SECTION QUESTION +y. IN A +ENTRY_END + +STEP 31 CHECK_ANSWER +ENTRY_BEGIN +MATCH all +REPLY QR TC RD RA NOERROR +SECTION QUESTION +y. IN A +SECTION ANSWER +ENTRY_END + +STEP 40 QUERY +ENTRY_BEGIN +MATCH TCP +REPLY RD +SECTION QUESTION +y. IN A +ENTRY_END + +STEP 41 CHECK_ANSWER +ENTRY_BEGIN +MATCH all TCP +REPLY QR RD RA NOERROR +SECTION QUESTION +y. IN A +SECTION ANSWER +y. IN A 10.1.1.1 +ENTRY_END + +SCENARIO_END diff --git a/contrib/unbound/testdata/stub_udp_with_tcp_upstream.tdir/stub_udp_with_tcp_upstream.conf b/contrib/unbound/testdata/stub_udp_with_tcp_upstream.tdir/stub_udp_with_tcp_upstream.conf new file mode 100644 index 000000000000..d57c787b154c --- /dev/null +++ b/contrib/unbound/testdata/stub_udp_with_tcp_upstream.tdir/stub_udp_with_tcp_upstream.conf @@ -0,0 +1,19 @@ +server: + verbosity: 2 + # num-threads: 1 + interface: 127.0.0.1 + port: @PORT@ + use-syslog: no + directory: "" + pidfile: "unbound.pid" + chroot: "" + username: "" + do-not-query-localhost: no +stub-zone: + name: "tcp.example.com" + stub-addr: "127.0.0.1@@TOPORT@" + stub-tcp-upstream: "yes" +stub-zone: + name: "udp.example.com" + stub-addr: "127.0.0.1@@TOPORT@" + stub-tcp-upstream: "no" \ No newline at end of file diff --git a/contrib/unbound/testdata/stub_udp_with_tcp_upstream.tdir/stub_udp_with_tcp_upstream.dsc b/contrib/unbound/testdata/stub_udp_with_tcp_upstream.tdir/stub_udp_with_tcp_upstream.dsc new file mode 100644 index 000000000000..526ff67f98f9 --- /dev/null +++ b/contrib/unbound/testdata/stub_udp_with_tcp_upstream.tdir/stub_udp_with_tcp_upstream.dsc @@ -0,0 +1,16 @@ +BaseName: stub_udp_with_tcp_upstream +Version: 1.0 +Description: Stub server contacted via UDP with tcp upstream. +CreationDate: Thu Aug 5 07:44:41 CEST 2021 +Maintainer: ziollek +Category: +Component: +CmdDepends: +Depends: +Help: +Pre: stub_udp_with_tcp_upstream.pre +Post: stub_udp_with_tcp_upstream.post +Test: stub_udp_with_tcp_upstream.test +AuxFiles: +Passed: +Failure: diff --git a/contrib/unbound/testdata/stub_udp_with_tcp_upstream.tdir/stub_udp_with_tcp_upstream.post b/contrib/unbound/testdata/stub_udp_with_tcp_upstream.tdir/stub_udp_with_tcp_upstream.post new file mode 100644 index 000000000000..c804b6c46d64 --- /dev/null +++ b/contrib/unbound/testdata/stub_udp_with_tcp_upstream.tdir/stub_udp_with_tcp_upstream.post @@ -0,0 +1,10 @@ +# #-- stub_udp_with_tcp_upstream.post --# +# source the master var file when it's there +[ -f ../.tpkg.var.master ] && source ../.tpkg.var.master +# source the test var file when it's there +[ -f .tpkg.var.test ] && source .tpkg.var.test +# +# do your teardown here +. ../common.sh +kill_pid $FWD_PID +kill_pid $UNBOUND_PID diff --git a/contrib/unbound/testdata/stub_udp_with_tcp_upstream.tdir/stub_udp_with_tcp_upstream.pre b/contrib/unbound/testdata/stub_udp_with_tcp_upstream.tdir/stub_udp_with_tcp_upstream.pre new file mode 100644 index 000000000000..2bca63b9d56b --- /dev/null +++ b/contrib/unbound/testdata/stub_udp_with_tcp_upstream.tdir/stub_udp_with_tcp_upstream.pre @@ -0,0 +1,35 @@ +# #-- stub_udp_with_tcp_upstream.pre--# +# source the master var file when it's there +[ -f ../.tpkg.var.master ] && source ../.tpkg.var.master +# use .tpkg.var.test for in test variable passing +[ -f .tpkg.var.test ] && source .tpkg.var.test +. ../common.sh + +get_random_port 2 +UNBOUND_PORT=$RND_PORT +FWD_PORT=$(($RND_PORT + 1)) +echo "UNBOUND_PORT=$UNBOUND_PORT" >> .tpkg.var.test +echo "FWD_PORT=$FWD_PORT" >> .tpkg.var.test + +# start forwarder +get_ldns_testns +$LDNS_TESTNS -p $FWD_PORT stub_udp_with_tcp_upstream.testns >fwd.log 2>&1 & +FWD_PID=$! +echo "FWD_PID=$FWD_PID" >> .tpkg.var.test + +# make config file +sed -e 's/@PORT\@/'$UNBOUND_PORT'/' -e 's/@TOPORT\@/'$FWD_PORT'/' < stub_udp_with_tcp_upstream.conf > ub.conf +# start unbound in the background +PRE="../.." +$PRE/unbound -d -c ub.conf >unbound.log 2>&1 & +UNBOUND_PID=$! +echo "UNBOUND_PID=$UNBOUND_PID" >> .tpkg.var.test + +cat .tpkg.var.test + +# wait for forwarder to come up +wait_ldns_testns_up fwd.log + +# wait for unbound to come up +wait_unbound_up unbound.log + diff --git a/contrib/unbound/testdata/stub_udp_with_tcp_upstream.tdir/stub_udp_with_tcp_upstream.test b/contrib/unbound/testdata/stub_udp_with_tcp_upstream.tdir/stub_udp_with_tcp_upstream.test new file mode 100644 index 000000000000..43591ac16c0f --- /dev/null +++ b/contrib/unbound/testdata/stub_udp_with_tcp_upstream.tdir/stub_udp_with_tcp_upstream.test @@ -0,0 +1,37 @@ +# #-- stub_udp_with_tcp_upstream.test --# +# source the master var file when it's there +[ -f ../.tpkg.var.master ] && source ../.tpkg.var.master +# use .tpkg.var.test for in test variable passing +[ -f .tpkg.var.test ] && source .tpkg.var.test + +PRE="../.." +# do the test +echo "> dig tcp.example.com." +dig @127.0.0.1 -p $UNBOUND_PORT tcp.example.com. | tee outfile +echo "> cat logfiles" +cat fwd.log +cat unbound.log +echo "> check answer" +if grep "10.20.30.40" outfile; then + echo "OK" +else + echo "Not OK" + exit 1 +fi + + +# check if second stub is requested via udp +echo "> dig udp.example.com." +dig @127.0.0.1 -p $UNBOUND_PORT udp.example.com. | tee outfile +echo "> cat logfiles" +cat fwd.log +cat unbound.log +echo "> check answer" +if grep "10.20.30.80" outfile; then + echo "OK" +else + echo "Not OK" + exit 1 +fi + +exit 0 diff --git a/contrib/unbound/testdata/stub_udp_with_tcp_upstream.tdir/stub_udp_with_tcp_upstream.testns b/contrib/unbound/testdata/stub_udp_with_tcp_upstream.tdir/stub_udp_with_tcp_upstream.testns new file mode 100644 index 000000000000..f2155414e045 --- /dev/null +++ b/contrib/unbound/testdata/stub_udp_with_tcp_upstream.tdir/stub_udp_with_tcp_upstream.testns @@ -0,0 +1,48 @@ +; nameserver test file +$ORIGIN example.com. +$TTL 3600 + +ENTRY_BEGIN +MATCH opcode qtype qname +MATCH TCP +REPLY QR AA NOERROR +ADJUST copy_id +SECTION QUESTION +tcp IN A +SECTION ANSWER +tcp IN A 10.20.30.40 +SECTION AUTHORITY +@ IN NS ns.example.com. +SECTION ADDITIONAL +ns IN A 127.0.0.1 +ENTRY_END + +ENTRY_BEGIN +MATCH opcode qtype qname +MATCH UDP +REPLY QR AA NOERROR +ADJUST copy_id +SECTION QUESTION +udp IN A +SECTION ANSWER +udp IN A 10.20.30.80 +SECTION AUTHORITY +@ IN NS ns.example.com. +SECTION ADDITIONAL +ns IN A 127.0.0.1 +ENTRY_END + +; root prime +ENTRY_BEGIN +MATCH opcode qtype qname +REPLY QR AA NOERROR +ADJUST copy_id +SECTION QUESTION +. IN NS +SECTION ANSWER +. IN NS root.server. +SECTION AUTHORITY +SECTION ADDITIONAL +root.server. IN A 127.0.0.1 +ENTRY_END + diff --git a/contrib/unbound/testdata/svcb.tdir/svcb.test b/contrib/unbound/testdata/svcb.tdir/svcb.test index 707287d5cf89..17330e08fde6 100644 --- a/contrib/unbound/testdata/svcb.tdir/svcb.test +++ b/contrib/unbound/testdata/svcb.tdir/svcb.test @@ -80,7 +80,7 @@ else fi -# check all the succes and write them +# check all the success and write them if ! $PRE/readzone svcb.success-cases.zone > svcb.success-cases.zone.out then echo "Some particular success cases did not succeed to parse" diff --git a/contrib/unbound/util/config_file.c b/contrib/unbound/util/config_file.c index 083654ebad4c..413d7e3221dd 100644 --- a/contrib/unbound/util/config_file.c +++ b/contrib/unbound/util/config_file.c @@ -328,6 +328,7 @@ config_create(void) cfg->ratelimit_size = 4*1024*1024; cfg->ratelimit_for_domain = NULL; cfg->ratelimit_below_domain = NULL; + cfg->outbound_msg_retry = 5; cfg->ip_ratelimit_factor = 10; cfg->ratelimit_factor = 10; cfg->qname_minimisation = 1; @@ -752,6 +753,7 @@ int config_set_option(struct config_file* cfg, const char* opt, else S_POW2("ratelimit-slabs:", ratelimit_slabs) else S_NUMBER_OR_ZERO("ip-ratelimit-factor:", ip_ratelimit_factor) else S_NUMBER_OR_ZERO("ratelimit-factor:", ratelimit_factor) + else S_NUMBER_NONZERO("outbound-msg-retry:", outbound_msg_retry) else S_SIZET_NONZERO("fast-server-num:", fast_server_num) else S_NUMBER_OR_ZERO("fast-server-permil:", fast_server_permil) else S_YNO("qname-minimisation:", qname_minimisation) @@ -1195,6 +1197,7 @@ config_get_option(struct config_file* cfg, const char* opt, else O_LS2(opt, "ratelimit-below-domain", ratelimit_below_domain) else O_DEC(opt, "ip-ratelimit-factor", ip_ratelimit_factor) else O_DEC(opt, "ratelimit-factor", ratelimit_factor) + else O_UNS(opt, "outbound-msg-retry", outbound_msg_retry) else O_DEC(opt, "fast-server-num", fast_server_num) else O_DEC(opt, "fast-server-permil", fast_server_permil) else O_DEC(opt, "val-sig-skew-min", val_sig_skew_min) diff --git a/contrib/unbound/util/config_file.h b/contrib/unbound/util/config_file.h index aed6812dafe8..18910bee39fc 100644 --- a/contrib/unbound/util/config_file.h +++ b/contrib/unbound/util/config_file.h @@ -578,6 +578,8 @@ struct config_file { struct config_str2list* ratelimit_below_domain; /** ratelimit factor, 0 blocks all, 10 allows 1/10 of traffic */ int ratelimit_factor; + /** number of retries on outgoing queries */ + int outbound_msg_retry; /** minimise outgoing QNAME and hide original QTYPE if possible */ int qname_minimisation; /** minimise QNAME in strict mode, minimise according to RFC. @@ -697,6 +699,8 @@ struct config_stub { int isprime; /** if forward-first is set (failover to without if fails) */ int isfirst; + /** use tcp for queries to this stub */ + int tcp_upstream; /** use SSL for queries to this stub */ int ssl_upstream; /*** no cache */ @@ -1106,7 +1110,7 @@ int cfg_count_numbers(const char* str); int cfg_parse_memsize(const char* str, size_t* res); /** - * Parse nsid from string into binary nsid. nsid is either a hexidecimal + * Parse nsid from string into binary nsid. nsid is either a hexadecimal * string or an ascii string prepended with ascii_ in which case the * characters after ascii_ are simply copied. * @param str: the string to parse. diff --git a/contrib/unbound/util/configlexer.lex b/contrib/unbound/util/configlexer.lex index b961a84d9401..0fcd74a0cf53 100644 --- a/contrib/unbound/util/configlexer.lex +++ b/contrib/unbound/util/configlexer.lex @@ -332,6 +332,7 @@ stub-first{COLON} { YDVAR(1, VAR_STUB_FIRST) } stub-no-cache{COLON} { YDVAR(1, VAR_STUB_NO_CACHE) } stub-ssl-upstream{COLON} { YDVAR(1, VAR_STUB_SSL_UPSTREAM) } stub-tls-upstream{COLON} { YDVAR(1, VAR_STUB_SSL_UPSTREAM) } +stub-tcp-upstream{COLON} { YDVAR(1, VAR_STUB_TCP_UPSTREAM) } forward-zone{COLON} { YDVAR(0, VAR_FORWARD_ZONE) } forward-addr{COLON} { YDVAR(1, VAR_FORWARD_ADDR) } forward-host{COLON} { YDVAR(1, VAR_FORWARD_HOST) } @@ -339,6 +340,7 @@ forward-first{COLON} { YDVAR(1, VAR_FORWARD_FIRST) } forward-no-cache{COLON} { YDVAR(1, VAR_FORWARD_NO_CACHE) } forward-ssl-upstream{COLON} { YDVAR(1, VAR_FORWARD_SSL_UPSTREAM) } forward-tls-upstream{COLON} { YDVAR(1, VAR_FORWARD_SSL_UPSTREAM) } +forward-tcp-upstream{COLON} { YDVAR(1, VAR_FORWARD_TCP_UPSTREAM) } auth-zone{COLON} { YDVAR(0, VAR_AUTH_ZONE) } rpz{COLON} { YDVAR(0, VAR_RPZ) } tags{COLON} { YDVAR(1, VAR_TAGS) } @@ -500,6 +502,7 @@ ratelimit-for-domain{COLON} { YDVAR(2, VAR_RATELIMIT_FOR_DOMAIN) } ratelimit-below-domain{COLON} { YDVAR(2, VAR_RATELIMIT_BELOW_DOMAIN) } ip-ratelimit-factor{COLON} { YDVAR(1, VAR_IP_RATELIMIT_FACTOR) } ratelimit-factor{COLON} { YDVAR(1, VAR_RATELIMIT_FACTOR) } +outbound-msg-retry{COLON} { YDVAR(1, VAR_OUTBOUND_MSG_RETRY) } low-rtt{COLON} { YDVAR(1, VAR_LOW_RTT) } fast-server-num{COLON} { YDVAR(1, VAR_FAST_SERVER_NUM) } low-rtt-pct{COLON} { YDVAR(1, VAR_FAST_SERVER_PERMIL) } diff --git a/contrib/unbound/util/configparser.y b/contrib/unbound/util/configparser.y index e22d48d41055..1daf853d5749 100644 --- a/contrib/unbound/util/configparser.y +++ b/contrib/unbound/util/configparser.y @@ -4,24 +4,24 @@ * Copyright (c) 2001-2006, NLnet Labs. All rights reserved. * * Copyright (c) 2007, NLnet Labs. All rights reserved. - * + * * This software is open source. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: - * + * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. - * + * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. - * + * * Neither the name of the NLNET LABS nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR @@ -88,13 +88,13 @@ extern struct config_parser_state* cfg_parser; %token VAR_TRUST_ANCHOR_FILE VAR_TRUST_ANCHOR VAR_VAL_OVERRIDE_DATE %token VAR_BOGUS_TTL VAR_VAL_CLEAN_ADDITIONAL VAR_VAL_PERMISSIVE_MODE %token VAR_INCOMING_NUM_TCP VAR_MSG_BUFFER_SIZE VAR_KEY_CACHE_SIZE -%token VAR_KEY_CACHE_SLABS VAR_TRUSTED_KEYS_FILE -%token VAR_VAL_NSEC3_KEYSIZE_ITERATIONS VAR_USE_SYSLOG +%token VAR_KEY_CACHE_SLABS VAR_TRUSTED_KEYS_FILE +%token VAR_VAL_NSEC3_KEYSIZE_ITERATIONS VAR_USE_SYSLOG %token VAR_OUTGOING_INTERFACE VAR_ROOT_HINTS VAR_DO_NOT_QUERY_LOCALHOST %token VAR_CACHE_MAX_TTL VAR_HARDEN_DNSSEC_STRIPPED VAR_ACCESS_CONTROL %token VAR_LOCAL_ZONE VAR_LOCAL_DATA VAR_INTERFACE_AUTOMATIC %token VAR_STATISTICS_INTERVAL VAR_DO_DAEMONIZE VAR_USE_CAPS_FOR_ID -%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_NEG_CACHE_SIZE VAR_HARDEN_REFERRAL_PATH VAR_PRIVATE_ADDRESS %token VAR_PRIVATE_DOMAIN VAR_REMOTE_CONTROL VAR_CONTROL_ENABLE @@ -113,6 +113,7 @@ extern struct config_parser_state* cfg_parser; %token VAR_SSL_UPSTREAM VAR_TCP_AUTH_QUERY_TIMEOUT VAR_SSL_SERVICE_KEY %token VAR_SSL_SERVICE_PEM VAR_SSL_PORT VAR_FORWARD_FIRST %token VAR_STUB_SSL_UPSTREAM VAR_FORWARD_SSL_UPSTREAM VAR_TLS_CERT_BUNDLE +%token VAR_STUB_TCP_UPSTREAM VAR_FORWARD_TCP_UPSTREAM %token VAR_HTTPS_PORT VAR_HTTP_ENDPOINT VAR_HTTP_MAX_STREAMS %token VAR_HTTP_QUERY_BUFFER_SIZE VAR_HTTP_RESPONSE_BUFFER_SIZE %token VAR_HTTP_NODELAY VAR_HTTP_NOTLS_DOWNSTREAM @@ -138,6 +139,7 @@ extern struct config_parser_state* cfg_parser; %token VAR_DISABLE_DNSSEC_LAME_CHECK %token VAR_IP_RATELIMIT VAR_IP_RATELIMIT_SLABS VAR_IP_RATELIMIT_SIZE %token VAR_RATELIMIT VAR_RATELIMIT_SLABS VAR_RATELIMIT_SIZE +%token VAR_OUTBOUND_MSG_RETRY %token VAR_RATELIMIT_FOR_DOMAIN VAR_RATELIMIT_BELOW_DOMAIN %token VAR_IP_RATELIMIT_FACTOR VAR_RATELIMIT_FACTOR %token VAR_SEND_CLIENT_SUBNET VAR_CLIENT_SUBNET_ZONE @@ -189,7 +191,7 @@ extern struct config_parser_state* cfg_parser; %% toplevelvars: /* empty */ | toplevelvars toplevelvar ; toplevelvar: serverstart contents_server | stubstart contents_stub | - forwardstart contents_forward | pythonstart contents_py | + forwardstart contents_forward | pythonstart contents_py | rcstart contents_rc | dtstart contents_dt | viewstart contents_view | dnscstart contents_dnsc | cachedbstart contents_cachedb | ipsetstart contents_ipset | authstart contents_auth | @@ -203,7 +205,7 @@ force_toplevel: VAR_FORCE_TOPLEVEL ; /* server: declaration */ serverstart: VAR_SERVER - { + { OUTYY(("\nP(server:)\n")); } ; @@ -215,14 +217,14 @@ content_server: server_num_threads | server_verbosity | server_port | server_do_udp | server_do_tcp | server_tcp_mss | server_outgoing_tcp_mss | server_tcp_idle_timeout | server_tcp_keepalive | server_tcp_keepalive_timeout | - server_interface | server_chroot | server_username | + server_interface | server_chroot | server_username | server_directory | server_logfile | server_pidfile | server_msg_cache_size | server_msg_cache_slabs | - server_num_queries_per_thread | server_rrset_cache_size | - server_rrset_cache_slabs | server_outgoing_num_tcp | - server_infra_host_ttl | server_infra_lame_ttl | + server_num_queries_per_thread | server_rrset_cache_size | + server_rrset_cache_slabs | server_outgoing_num_tcp | + server_infra_host_ttl | server_infra_lame_ttl | server_infra_cache_slabs | server_infra_cache_numhosts | - server_infra_cache_lame_size | server_target_fetch_policy | + server_infra_cache_lame_size | server_target_fetch_policy | server_harden_short_bufsize | server_harden_large_queries | server_do_not_query_address | server_hide_identity | server_hide_version | server_identity | server_version | @@ -230,22 +232,22 @@ content_server: server_num_threads | server_verbosity | server_port | server_harden_glue | server_module_conf | server_trust_anchor_file | server_trust_anchor | server_val_override_date | server_bogus_ttl | server_val_clean_additional | server_val_permissive_mode | - server_incoming_num_tcp | server_msg_buffer_size | - server_key_cache_size | server_key_cache_slabs | + server_incoming_num_tcp | server_msg_buffer_size | + server_key_cache_size | server_key_cache_slabs | server_trusted_keys_file | server_val_nsec3_keysize_iterations | server_use_syslog | server_outgoing_interface | server_root_hints | server_do_not_query_localhost | server_cache_max_ttl | server_harden_dnssec_stripped | server_access_control | server_local_zone | server_local_data | server_interface_automatic | - server_statistics_interval | server_do_daemonize | + server_statistics_interval | server_do_daemonize | server_use_caps_for_id | server_statistics_cumulative | server_outgoing_port_permit | server_outgoing_port_avoid | server_dlv_anchor_file | server_dlv_anchor | server_neg_cache_size | server_harden_referral_path | server_private_address | - server_private_domain | server_extended_statistics | - server_local_data_ptr | server_jostle_timeout | - server_unwanted_reply_threshold | server_log_time_ascii | - server_domain_insecure | server_val_sig_skew_min | + server_private_domain | server_extended_statistics | + server_local_data_ptr | server_jostle_timeout | + server_unwanted_reply_threshold | server_log_time_ascii | + server_domain_insecure | server_val_sig_skew_min | server_val_sig_skew_max | server_val_max_restart | server_cache_min_ttl | server_val_log_level | server_auto_trust_anchor_file | server_add_holddown | @@ -269,9 +271,9 @@ content_server: server_num_threads | server_verbosity | server_port | server_ip_ratelimit_size | server_ratelimit_size | server_ratelimit_for_domain | server_ratelimit_below_domain | server_ratelimit_factor | - server_ip_ratelimit_factor | server_send_client_subnet | - server_client_subnet_zone | server_client_subnet_always_forward | - server_client_subnet_opcode | + server_ip_ratelimit_factor | server_outbound_msg_retry | + server_send_client_subnet | server_client_subnet_zone | + server_client_subnet_always_forward | server_client_subnet_opcode | server_max_client_subnet_ipv4 | server_max_client_subnet_ipv6 | server_min_client_subnet_ipv4 | server_min_client_subnet_ipv6 | server_max_ecs_tree_size_ipv4 | server_max_ecs_tree_size_ipv6 | @@ -312,52 +314,55 @@ content_server: server_num_threads | server_verbosity | server_port | stubstart: VAR_STUB_ZONE { struct config_stub* s; - OUTYY(("\nP(stub_zone:)\n")); + OUTYY(("\nP(stub_zone:)\n")); s = (struct config_stub*)calloc(1, sizeof(struct config_stub)); if(s) { s->next = cfg_parser->cfg->stubs; cfg_parser->cfg->stubs = s; - } else + } else { yyerror("out of memory"); + } } ; -contents_stub: contents_stub content_stub +contents_stub: contents_stub content_stub | ; content_stub: stub_name | stub_host | stub_addr | stub_prime | stub_first | - stub_no_cache | stub_ssl_upstream + stub_no_cache | stub_ssl_upstream | stub_tcp_upstream ; forwardstart: VAR_FORWARD_ZONE { struct config_stub* s; - OUTYY(("\nP(forward_zone:)\n")); + OUTYY(("\nP(forward_zone:)\n")); s = (struct config_stub*)calloc(1, sizeof(struct config_stub)); if(s) { s->next = cfg_parser->cfg->forwards; cfg_parser->cfg->forwards = s; - } else + } else { yyerror("out of memory"); + } } ; -contents_forward: contents_forward content_forward +contents_forward: contents_forward content_forward | ; content_forward: forward_name | forward_host | forward_addr | forward_first | - forward_no_cache | forward_ssl_upstream + forward_no_cache | forward_ssl_upstream | forward_tcp_upstream ; viewstart: VAR_VIEW { struct config_view* s; - OUTYY(("\nP(view:)\n")); + OUTYY(("\nP(view:)\n")); s = (struct config_view*)calloc(1, sizeof(struct config_view)); if(s) { s->next = cfg_parser->cfg->views; if(s->next && !s->next->name) yyerror("view without name"); cfg_parser->cfg->views = s; - } else + } else { yyerror("out of memory"); + } } ; -contents_view: contents_view content_view +contents_view: contents_view content_view | ; content_view: view_name | view_local_zone | view_local_data | view_first | view_response_ip | view_response_ip_data | view_local_data_ptr @@ -365,7 +370,7 @@ content_view: view_name | view_local_zone | view_local_data | view_first | authstart: VAR_AUTH_ZONE { struct config_auth* s; - OUTYY(("\nP(auth_zone:)\n")); + OUTYY(("\nP(auth_zone:)\n")); s = (struct config_auth*)calloc(1, sizeof(struct config_auth)); if(s) { s->next = cfg_parser->cfg->auths; @@ -377,11 +382,12 @@ authstart: VAR_AUTH_ZONE s->zonemd_check = 0; s->zonemd_reject_absence = 0; s->isrpz = 0; - } else + } else { yyerror("out of memory"); + } } ; -contents_auth: contents_auth content_auth +contents_auth: contents_auth content_auth | ; content_auth: auth_name | auth_zonefile | auth_master | auth_url | auth_for_downstream | auth_for_upstream | auth_fallback_enabled | @@ -463,8 +469,9 @@ rpzstart: VAR_RPZ s->for_upstream = 0; s->fallback_enabled = 0; s->isrpz = 1; - } else + } else { yyerror("out of memory"); + } } ; contents_rpz: contents_rpz content_rpz @@ -473,27 +480,27 @@ content_rpz: auth_name | auth_zonefile | rpz_tag | auth_master | auth_url | auth_allow_notify | rpz_action_override | rpz_cname_override | rpz_log | rpz_log_name ; -server_num_threads: VAR_NUM_THREADS STRING_ARG - { - OUTYY(("P(server_num_threads:%s)\n", $2)); +server_num_threads: VAR_NUM_THREADS STRING_ARG + { + OUTYY(("P(server_num_threads:%s)\n", $2)); if(atoi($2) == 0 && strcmp($2, "0") != 0) yyerror("number expected"); else cfg_parser->cfg->num_threads = atoi($2); free($2); } ; -server_verbosity: VAR_VERBOSITY STRING_ARG - { - OUTYY(("P(server_verbosity:%s)\n", $2)); +server_verbosity: VAR_VERBOSITY STRING_ARG + { + OUTYY(("P(server_verbosity:%s)\n", $2)); if(atoi($2) == 0 && strcmp($2, "0") != 0) yyerror("number expected"); else cfg_parser->cfg->verbosity = atoi($2); free($2); } ; -server_statistics_interval: VAR_STATISTICS_INTERVAL STRING_ARG - { - OUTYY(("P(server_statistics_interval:%s)\n", $2)); +server_statistics_interval: VAR_STATISTICS_INTERVAL STRING_ARG + { + OUTYY(("P(server_statistics_interval:%s)\n", $2)); if(strcmp($2, "") == 0 || strcmp($2, "0") == 0) cfg_parser->cfg->stat_interval = 0; else if(atoi($2) == 0) @@ -529,9 +536,9 @@ server_shm_enable: VAR_SHM_ENABLE STRING_ARG free($2); } ; -server_shm_key: VAR_SHM_KEY STRING_ARG - { - OUTYY(("P(server_shm_key:%s)\n", $2)); +server_shm_key: VAR_SHM_KEY STRING_ARG + { + OUTYY(("P(server_shm_key:%s)\n", $2)); if(strcmp($2, "") == 0 || strcmp($2, "0") == 0) cfg_parser->cfg->shm_key = 0; else if(atoi($2) == 0) @@ -704,7 +711,7 @@ server_interface: VAR_INTERFACE STRING_ARG OUTYY(("P(server_interface:%s)\n", $2)); if(cfg_parser->cfg->num_ifs == 0) cfg_parser->cfg->ifs = calloc(1, sizeof(char*)); - else cfg_parser->cfg->ifs = realloc(cfg_parser->cfg->ifs, + else cfg_parser->cfg->ifs = realloc(cfg_parser->cfg->ifs, (cfg_parser->cfg->num_ifs+1)*sizeof(char*)); if(!cfg_parser->cfg->ifs) yyerror("out of memory"); @@ -717,8 +724,8 @@ server_outgoing_interface: VAR_OUTGOING_INTERFACE STRING_ARG OUTYY(("P(server_outgoing_interface:%s)\n", $2)); if(cfg_parser->cfg->num_out_ifs == 0) cfg_parser->cfg->out_ifs = calloc(1, sizeof(char*)); - else cfg_parser->cfg->out_ifs = realloc( - cfg_parser->cfg->out_ifs, + else cfg_parser->cfg->out_ifs = realloc( + cfg_parser->cfg->out_ifs, (cfg_parser->cfg->num_out_ifs+1)*sizeof(char*)); if(!cfg_parser->cfg->out_ifs) yyerror("out of memory"); @@ -739,7 +746,7 @@ server_outgoing_range: VAR_OUTGOING_RANGE STRING_ARG server_outgoing_port_permit: VAR_OUTGOING_PORT_PERMIT STRING_ARG { OUTYY(("P(server_outgoing_port_permit:%s)\n", $2)); - if(!cfg_mark_ports($2, 1, + if(!cfg_mark_ports($2, 1, cfg_parser->cfg->outgoing_avail_ports, 65536)) yyerror("port number or range (\"low-high\") expected"); free($2); @@ -748,7 +755,7 @@ server_outgoing_port_permit: VAR_OUTGOING_PORT_PERMIT STRING_ARG server_outgoing_port_avoid: VAR_OUTGOING_PORT_AVOID STRING_ARG { OUTYY(("P(server_outgoing_port_avoid:%s)\n", $2)); - if(!cfg_mark_ports($2, 0, + if(!cfg_mark_ports($2, 0, cfg_parser->cfg->outgoing_avail_ports, 65536)) yyerror("port number or range (\"low-high\") expected"); free($2); @@ -838,10 +845,10 @@ server_prefer_ip6: VAR_PREFER_IP6 STRING_ARG server_tcp_mss: VAR_TCP_MSS STRING_ARG { OUTYY(("P(server_tcp_mss:%s)\n", $2)); - if(atoi($2) == 0 && strcmp($2, "0") != 0) - yyerror("number expected"); - else cfg_parser->cfg->tcp_mss = atoi($2); - free($2); + if(atoi($2) == 0 && strcmp($2, "0") != 0) + yyerror("number expected"); + else cfg_parser->cfg->tcp_mss = atoi($2); + free($2); } ; server_outgoing_tcp_mss: VAR_OUTGOING_TCP_MSS STRING_ARG @@ -1141,23 +1148,23 @@ server_log_queries: VAR_LOG_QUERIES STRING_ARG } ; server_log_replies: VAR_LOG_REPLIES STRING_ARG - { - OUTYY(("P(server_log_replies:%s)\n", $2)); - if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->log_replies = (strcmp($2, "yes")==0); - free($2); - } - ; + { + OUTYY(("P(server_log_replies:%s)\n", $2)); + if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) + yyerror("expected yes or no."); + else cfg_parser->cfg->log_replies = (strcmp($2, "yes")==0); + free($2); + } + ; server_log_tag_queryreply: VAR_LOG_TAG_QUERYREPLY STRING_ARG - { - OUTYY(("P(server_log_tag_queryreply:%s)\n", $2)); - if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->log_tag_queryreply = (strcmp($2, "yes")==0); - free($2); - } - ; + { + OUTYY(("P(server_log_tag_queryreply:%s)\n", $2)); + if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) + yyerror("expected yes or no."); + else cfg_parser->cfg->log_tag_queryreply = (strcmp($2, "yes")==0); + free($2); + } + ; server_log_servfail: VAR_LOG_SERVFAIL STRING_ARG { OUTYY(("P(server_log_servfail:%s)\n", $2)); @@ -1168,14 +1175,14 @@ server_log_servfail: VAR_LOG_SERVFAIL STRING_ARG } ; server_log_local_actions: VAR_LOG_LOCAL_ACTIONS STRING_ARG - { - OUTYY(("P(server_log_local_actions:%s)\n", $2)); - if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->log_local_actions = (strcmp($2, "yes")==0); - free($2); - } - ; + { + OUTYY(("P(server_log_local_actions:%s)\n", $2)); + if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) + yyerror("expected yes or no."); + else cfg_parser->cfg->log_local_actions = (strcmp($2, "yes")==0); + free($2); + } + ; server_chroot: VAR_CHROOT STRING_ARG { OUTYY(("P(server_chroot:%s)\n", $2)); @@ -1209,7 +1216,7 @@ server_directory: VAR_DIRECTORY STRING_ARG cfg_parser->chroot)) == 0) d += strlen(cfg_parser->chroot); if(d[0]) { - if(chdir(d)) + if(chdir(d)) log_err("cannot chdir to directory: %s (%s)", d, strerror(errno)); } @@ -1402,35 +1409,35 @@ server_so_sndbuf: VAR_SO_SNDBUF STRING_ARG } ; server_so_reuseport: VAR_SO_REUSEPORT STRING_ARG - { - OUTYY(("P(server_so_reuseport:%s)\n", $2)); - if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->so_reuseport = - (strcmp($2, "yes")==0); - free($2); - } - ; + { + OUTYY(("P(server_so_reuseport:%s)\n", $2)); + if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) + yyerror("expected yes or no."); + else cfg_parser->cfg->so_reuseport = + (strcmp($2, "yes")==0); + free($2); + } + ; server_ip_transparent: VAR_IP_TRANSPARENT STRING_ARG - { - OUTYY(("P(server_ip_transparent:%s)\n", $2)); - if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->ip_transparent = - (strcmp($2, "yes")==0); - free($2); - } - ; + { + OUTYY(("P(server_ip_transparent:%s)\n", $2)); + if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) + yyerror("expected yes or no."); + else cfg_parser->cfg->ip_transparent = + (strcmp($2, "yes")==0); + free($2); + } + ; server_ip_freebind: VAR_IP_FREEBIND STRING_ARG - { - OUTYY(("P(server_ip_freebind:%s)\n", $2)); - if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) - yyerror("expected yes or no."); - else cfg_parser->cfg->ip_freebind = - (strcmp($2, "yes")==0); - free($2); - } - ; + { + OUTYY(("P(server_ip_freebind:%s)\n", $2)); + if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) + yyerror("expected yes or no."); + else cfg_parser->cfg->ip_freebind = + (strcmp($2, "yes")==0); + free($2); + } + ; server_ip_dscp: VAR_IP_DSCP STRING_ARG { OUTYY(("P(server_ip_dscp:%s)\n", $2)); @@ -1488,9 +1495,9 @@ server_msg_cache_size: VAR_MSG_CACHE_SIZE STRING_ARG server_msg_cache_slabs: VAR_MSG_CACHE_SLABS STRING_ARG { OUTYY(("P(server_msg_cache_slabs:%s)\n", $2)); - if(atoi($2) == 0) + if(atoi($2) == 0) { yyerror("number expected"); - else { + } else { cfg_parser->cfg->msg_cache_slabs = atoi($2); if(!is_pow2(cfg_parser->cfg->msg_cache_slabs)) yyerror("must be a power of 2"); @@ -1539,7 +1546,7 @@ server_unblock_lan_zones: VAR_UNBLOCK_LAN_ZONES STRING_ARG OUTYY(("P(server_unblock_lan_zones:%s)\n", $2)); if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) yyerror("expected yes or no."); - else cfg_parser->cfg->unblock_lan_zones = + else cfg_parser->cfg->unblock_lan_zones = (strcmp($2, "yes")==0); free($2); } @@ -1549,7 +1556,7 @@ server_insecure_lan_zones: VAR_INSECURE_LAN_ZONES STRING_ARG OUTYY(("P(server_insecure_lan_zones:%s)\n", $2)); if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) yyerror("expected yes or no."); - else cfg_parser->cfg->insecure_lan_zones = + else cfg_parser->cfg->insecure_lan_zones = (strcmp($2, "yes")==0); free($2); } @@ -1565,9 +1572,9 @@ server_rrset_cache_size: VAR_RRSET_CACHE_SIZE STRING_ARG server_rrset_cache_slabs: VAR_RRSET_CACHE_SLABS STRING_ARG { OUTYY(("P(server_rrset_cache_slabs:%s)\n", $2)); - if(atoi($2) == 0) + if(atoi($2) == 0) { yyerror("number expected"); - else { + } else { cfg_parser->cfg->rrset_cache_slabs = atoi($2); if(!is_pow2(cfg_parser->cfg->rrset_cache_slabs)) yyerror("must be a power of 2"); @@ -1612,9 +1619,9 @@ server_infra_cache_lame_size: VAR_INFRA_CACHE_LAME_SIZE STRING_ARG server_infra_cache_slabs: VAR_INFRA_CACHE_SLABS STRING_ARG { OUTYY(("P(server_infra_cache_slabs:%s)\n", $2)); - if(atoi($2) == 0) + if(atoi($2) == 0) { yyerror("number expected"); - else { + } else { cfg_parser->cfg->infra_cache_slabs = atoi($2); if(!is_pow2(cfg_parser->cfg->infra_cache_slabs)) yyerror("must be a power of 2"); @@ -1653,7 +1660,7 @@ server_harden_short_bufsize: VAR_HARDEN_SHORT_BUFSIZE STRING_ARG OUTYY(("P(server_harden_short_bufsize:%s)\n", $2)); if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) yyerror("expected yes or no."); - else cfg_parser->cfg->harden_short_bufsize = + else cfg_parser->cfg->harden_short_bufsize = (strcmp($2, "yes")==0); free($2); } @@ -1663,7 +1670,7 @@ server_harden_large_queries: VAR_HARDEN_LARGE_QUERIES STRING_ARG OUTYY(("P(server_harden_large_queries:%s)\n", $2)); if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) yyerror("expected yes or no."); - else cfg_parser->cfg->harden_large_queries = + else cfg_parser->cfg->harden_large_queries = (strcmp($2, "yes")==0); free($2); } @@ -1673,7 +1680,7 @@ server_harden_glue: VAR_HARDEN_GLUE STRING_ARG OUTYY(("P(server_harden_glue:%s)\n", $2)); if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) yyerror("expected yes or no."); - else cfg_parser->cfg->harden_glue = + else cfg_parser->cfg->harden_glue = (strcmp($2, "yes")==0); free($2); } @@ -1683,7 +1690,7 @@ server_harden_dnssec_stripped: VAR_HARDEN_DNSSEC_STRIPPED STRING_ARG OUTYY(("P(server_harden_dnssec_stripped:%s)\n", $2)); if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) yyerror("expected yes or no."); - else cfg_parser->cfg->harden_dnssec_stripped = + else cfg_parser->cfg->harden_dnssec_stripped = (strcmp($2, "yes")==0); free($2); } @@ -1693,7 +1700,7 @@ server_harden_below_nxdomain: VAR_HARDEN_BELOW_NXDOMAIN STRING_ARG OUTYY(("P(server_harden_below_nxdomain:%s)\n", $2)); if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) yyerror("expected yes or no."); - else cfg_parser->cfg->harden_below_nxdomain = + else cfg_parser->cfg->harden_below_nxdomain = (strcmp($2, "yes")==0); free($2); } @@ -1703,7 +1710,7 @@ server_harden_referral_path: VAR_HARDEN_REFERRAL_PATH STRING_ARG OUTYY(("P(server_harden_referral_path:%s)\n", $2)); if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) yyerror("expected yes or no."); - else cfg_parser->cfg->harden_referral_path = + else cfg_parser->cfg->harden_referral_path = (strcmp($2, "yes")==0); free($2); } @@ -1713,7 +1720,7 @@ server_harden_algo_downgrade: VAR_HARDEN_ALGO_DOWNGRADE STRING_ARG OUTYY(("P(server_harden_algo_downgrade:%s)\n", $2)); if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) yyerror("expected yes or no."); - else cfg_parser->cfg->harden_algo_downgrade = + else cfg_parser->cfg->harden_algo_downgrade = (strcmp($2, "yes")==0); free($2); } @@ -1723,7 +1730,7 @@ server_use_caps_for_id: VAR_USE_CAPS_FOR_ID STRING_ARG OUTYY(("P(server_use_caps_for_id:%s)\n", $2)); if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) yyerror("expected yes or no."); - else cfg_parser->cfg->use_caps_bits_for_id = + else cfg_parser->cfg->use_caps_bits_for_id = (strcmp($2, "yes")==0); free($2); } @@ -1797,7 +1804,7 @@ server_do_not_query_localhost: VAR_DO_NOT_QUERY_LOCALHOST STRING_ARG OUTYY(("P(server_do_not_query_localhost:%s)\n", $2)); if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) yyerror("expected yes or no."); - else cfg_parser->cfg->donotquery_localhost = + else cfg_parser->cfg->donotquery_localhost = (strcmp($2, "yes")==0); free($2); } @@ -1808,8 +1815,8 @@ server_access_control: VAR_ACCESS_CONTROL STRING_ARG STRING_ARG if(strcmp($3, "deny")!=0 && strcmp($3, "refuse")!=0 && strcmp($3, "deny_non_local")!=0 && strcmp($3, "refuse_non_local")!=0 && - strcmp($3, "allow_setrd")!=0 && - strcmp($3, "allow")!=0 && + strcmp($3, "allow_setrd")!=0 && + strcmp($3, "allow")!=0 && strcmp($3, "allow_snoop")!=0) { yyerror("expected deny, refuse, deny_non_local, " "refuse_non_local, allow, allow_setrd or " @@ -1835,7 +1842,7 @@ server_val_override_date: VAR_VAL_OVERRIDE_DATE STRING_ARG if(*$2 == '\0' || strcmp($2, "0") == 0) { cfg_parser->cfg->val_date_override = 0; } else if(strlen($2) == 14) { - cfg_parser->cfg->val_date_override = + cfg_parser->cfg->val_date_override = cfg_convert_timeval($2); if(!cfg_parser->cfg->val_date_override) yyerror("bad date/time specification"); @@ -1927,7 +1934,7 @@ server_val_clean_additional: VAR_VAL_CLEAN_ADDITIONAL STRING_ARG OUTYY(("P(server_val_clean_additional:%s)\n", $2)); if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) yyerror("expected yes or no."); - else cfg_parser->cfg->val_clean_additional = + else cfg_parser->cfg->val_clean_additional = (strcmp($2, "yes")==0); free($2); } @@ -1937,7 +1944,7 @@ server_val_permissive_mode: VAR_VAL_PERMISSIVE_MODE STRING_ARG OUTYY(("P(server_val_permissive_mode:%s)\n", $2)); if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) yyerror("expected yes or no."); - else cfg_parser->cfg->val_permissive_mode = + else cfg_parser->cfg->val_permissive_mode = (strcmp($2, "yes")==0); free($2); } @@ -2114,9 +2121,9 @@ server_key_cache_size: VAR_KEY_CACHE_SIZE STRING_ARG server_key_cache_slabs: VAR_KEY_CACHE_SLABS STRING_ARG { OUTYY(("P(server_key_cache_slabs:%s)\n", $2)); - if(atoi($2) == 0) + if(atoi($2) == 0) { yyerror("number expected"); - else { + } else { cfg_parser->cfg->key_cache_slabs = atoi($2); if(!is_pow2(cfg_parser->cfg->key_cache_slabs)) yyerror("must be a power of 2"); @@ -2171,7 +2178,7 @@ server_local_zone: VAR_LOCAL_ZONE STRING_ARG STRING_ARG free($3); #endif } else { - if(!cfg_str2list_insert(&cfg_parser->cfg->local_zones, + if(!cfg_str2list_insert(&cfg_parser->cfg->local_zones, $2, $3)) fatal_exit("out of memory adding local-zone"); } @@ -2379,19 +2386,18 @@ server_response_ip_tag: VAR_RESPONSE_IP_TAG STRING_ARG STRING_ARG } } ; -server_ip_ratelimit: VAR_IP_RATELIMIT STRING_ARG - { - OUTYY(("P(server_ip_ratelimit:%s)\n", $2)); +server_ip_ratelimit: VAR_IP_RATELIMIT STRING_ARG + { + OUTYY(("P(server_ip_ratelimit:%s)\n", $2)); if(atoi($2) == 0 && strcmp($2, "0") != 0) yyerror("number expected"); else cfg_parser->cfg->ip_ratelimit = atoi($2); free($2); } ; - -server_ratelimit: VAR_RATELIMIT STRING_ARG - { - OUTYY(("P(server_ratelimit:%s)\n", $2)); +server_ratelimit: VAR_RATELIMIT STRING_ARG + { + OUTYY(("P(server_ratelimit:%s)\n", $2)); if(atoi($2) == 0 && strcmp($2, "0") != 0) yyerror("number expected"); else cfg_parser->cfg->ratelimit = atoi($2); @@ -2399,13 +2405,13 @@ server_ratelimit: VAR_RATELIMIT STRING_ARG } ; server_ip_ratelimit_size: VAR_IP_RATELIMIT_SIZE STRING_ARG - { - OUTYY(("P(server_ip_ratelimit_size:%s)\n", $2)); - if(!cfg_parse_memsize($2, &cfg_parser->cfg->ip_ratelimit_size)) - yyerror("memory size expected"); - free($2); - } - ; + { + OUTYY(("P(server_ip_ratelimit_size:%s)\n", $2)); + if(!cfg_parse_memsize($2, &cfg_parser->cfg->ip_ratelimit_size)) + yyerror("memory size expected"); + free($2); + } + ; server_ratelimit_size: VAR_RATELIMIT_SIZE STRING_ARG { OUTYY(("P(server_ratelimit_size:%s)\n", $2)); @@ -2415,24 +2421,24 @@ server_ratelimit_size: VAR_RATELIMIT_SIZE STRING_ARG } ; server_ip_ratelimit_slabs: VAR_IP_RATELIMIT_SLABS STRING_ARG - { - OUTYY(("P(server_ip_ratelimit_slabs:%s)\n", $2)); - if(atoi($2) == 0) - yyerror("number expected"); - else { - cfg_parser->cfg->ip_ratelimit_slabs = atoi($2); - if(!is_pow2(cfg_parser->cfg->ip_ratelimit_slabs)) - yyerror("must be a power of 2"); - } - free($2); - } - ; + { + OUTYY(("P(server_ip_ratelimit_slabs:%s)\n", $2)); + if(atoi($2) == 0) { + yyerror("number expected"); + } else { + cfg_parser->cfg->ip_ratelimit_slabs = atoi($2); + if(!is_pow2(cfg_parser->cfg->ip_ratelimit_slabs)) + yyerror("must be a power of 2"); + } + free($2); + } + ; server_ratelimit_slabs: VAR_RATELIMIT_SLABS STRING_ARG { OUTYY(("P(server_ratelimit_slabs:%s)\n", $2)); - if(atoi($2) == 0) + if(atoi($2) == 0) { yyerror("number expected"); - else { + } else { cfg_parser->cfg->ratelimit_slabs = atoi($2); if(!is_pow2(cfg_parser->cfg->ratelimit_slabs)) yyerror("must be a power of 2"); @@ -2470,42 +2476,51 @@ server_ratelimit_below_domain: VAR_RATELIMIT_BELOW_DOMAIN STRING_ARG STRING_ARG } } ; -server_ip_ratelimit_factor: VAR_IP_RATELIMIT_FACTOR STRING_ARG - { - OUTYY(("P(server_ip_ratelimit_factor:%s)\n", $2)); - if(atoi($2) == 0 && strcmp($2, "0") != 0) - yyerror("number expected"); - else cfg_parser->cfg->ip_ratelimit_factor = atoi($2); - free($2); +server_ip_ratelimit_factor: VAR_IP_RATELIMIT_FACTOR STRING_ARG + { + OUTYY(("P(server_ip_ratelimit_factor:%s)\n", $2)); + if(atoi($2) == 0 && strcmp($2, "0") != 0) + yyerror("number expected"); + else cfg_parser->cfg->ip_ratelimit_factor = atoi($2); + free($2); } ; -server_ratelimit_factor: VAR_RATELIMIT_FACTOR STRING_ARG - { - OUTYY(("P(server_ratelimit_factor:%s)\n", $2)); +server_ratelimit_factor: VAR_RATELIMIT_FACTOR STRING_ARG + { + OUTYY(("P(server_ratelimit_factor:%s)\n", $2)); if(atoi($2) == 0 && strcmp($2, "0") != 0) yyerror("number expected"); else cfg_parser->cfg->ratelimit_factor = atoi($2); free($2); } ; -server_low_rtt: VAR_LOW_RTT STRING_ARG - { +server_outbound_msg_retry: VAR_OUTBOUND_MSG_RETRY STRING_ARG + { + OUTYY(("P(server_outbound_msg_retry:%s)\n", $2)); + if(atoi($2) == 0 && strcmp($2, "0") != 0) + yyerror("number expected"); + else cfg_parser->cfg->outbound_msg_retry = atoi($2); + free($2); + } + ; +server_low_rtt: VAR_LOW_RTT STRING_ARG + { OUTYY(("P(low-rtt option is deprecated, use fast-server-num instead)\n")); free($2); } ; -server_fast_server_num: VAR_FAST_SERVER_NUM STRING_ARG - { - OUTYY(("P(server_fast_server_num:%s)\n", $2)); +server_fast_server_num: VAR_FAST_SERVER_NUM STRING_ARG + { + OUTYY(("P(server_fast_server_num:%s)\n", $2)); if(atoi($2) <= 0) yyerror("number expected"); else cfg_parser->cfg->fast_server_num = atoi($2); free($2); } ; -server_fast_server_permil: VAR_FAST_SERVER_PERMIL STRING_ARG - { - OUTYY(("P(server_fast_server_permil:%s)\n", $2)); +server_fast_server_permil: VAR_FAST_SERVER_PERMIL STRING_ARG + { + OUTYY(("P(server_fast_server_permil:%s)\n", $2)); if(atoi($2) == 0 && strcmp($2, "0") != 0) yyerror("number expected"); else cfg_parser->cfg->fast_server_permil = atoi($2); @@ -2517,7 +2532,7 @@ server_qname_minimisation: VAR_QNAME_MINIMISATION STRING_ARG OUTYY(("P(server_qname_minimisation:%s)\n", $2)); if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) yyerror("expected yes or no."); - else cfg_parser->cfg->qname_minimisation = + else cfg_parser->cfg->qname_minimisation = (strcmp($2, "yes")==0); free($2); } @@ -2527,7 +2542,7 @@ server_qname_minimisation_strict: VAR_QNAME_MINIMISATION_STRICT STRING_ARG OUTYY(("P(server_qname_minimisation_strict:%s)\n", $2)); if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) yyerror("expected yes or no."); - else cfg_parser->cfg->qname_minimisation_strict = + else cfg_parser->cfg->qname_minimisation_strict = (strcmp($2, "yes")==0); free($2); } @@ -2716,17 +2731,27 @@ stub_ssl_upstream: VAR_STUB_SSL_UPSTREAM STRING_ARG OUTYY(("P(stub-ssl-upstream:%s)\n", $2)); if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) yyerror("expected yes or no."); - else cfg_parser->cfg->stubs->ssl_upstream = + else cfg_parser->cfg->stubs->ssl_upstream = (strcmp($2, "yes")==0); free($2); } ; +stub_tcp_upstream: VAR_STUB_TCP_UPSTREAM STRING_ARG + { + OUTYY(("P(stub-tcp-upstream:%s)\n", $2)); + if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) + yyerror("expected yes or no."); + else cfg_parser->cfg->stubs->tcp_upstream = + (strcmp($2, "yes")==0); + free($2); + } + ; stub_prime: VAR_STUB_PRIME STRING_ARG { OUTYY(("P(stub-prime:%s)\n", $2)); if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) yyerror("expected yes or no."); - else cfg_parser->cfg->stubs->isprime = + else cfg_parser->cfg->stubs->isprime = (strcmp($2, "yes")==0); free($2); } @@ -2778,11 +2803,21 @@ forward_ssl_upstream: VAR_FORWARD_SSL_UPSTREAM STRING_ARG OUTYY(("P(forward-ssl-upstream:%s)\n", $2)); if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) yyerror("expected yes or no."); - else cfg_parser->cfg->forwards->ssl_upstream = + else cfg_parser->cfg->forwards->ssl_upstream = (strcmp($2, "yes")==0); free($2); } ; +forward_tcp_upstream: VAR_FORWARD_TCP_UPSTREAM STRING_ARG + { + OUTYY(("P(forward-tcp-upstream:%s)\n", $2)); + if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) + yyerror("expected yes or no."); + else cfg_parser->cfg->forwards->tcp_upstream = + (strcmp($2, "yes")==0); + free($2); + } + ; auth_name: VAR_NAME STRING_ARG { OUTYY(("P(name:%s)\n", $2)); @@ -2922,7 +2957,7 @@ view_local_zone: VAR_LOCAL_ZONE STRING_ARG STRING_ARG #endif } else { if(!cfg_str2list_insert( - &cfg_parser->cfg->views->local_zones, + &cfg_parser->cfg->views->local_zones, $2, $3)) fatal_exit("out of memory adding local-zone"); } @@ -2979,11 +3014,11 @@ view_first: VAR_VIEW_FIRST STRING_ARG } ; rcstart: VAR_REMOTE_CONTROL - { - OUTYY(("\nP(remote-control:)\n")); + { + OUTYY(("\nP(remote-control:)\n")); } ; -contents_rc: contents_rc content_rc +contents_rc: contents_rc content_rc | ; content_rc: rc_control_enable | rc_control_interface | rc_control_port | rc_server_key_file | rc_server_cert_file | rc_control_key_file | @@ -2994,7 +3029,7 @@ rc_control_enable: VAR_CONTROL_ENABLE STRING_ARG OUTYY(("P(control_enable:%s)\n", $2)); if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0) yyerror("expected yes or no."); - else cfg_parser->cfg->remote_control_enable = + else cfg_parser->cfg->remote_control_enable = (strcmp($2, "yes")==0); free($2); } @@ -3233,8 +3268,8 @@ dt_dnstap_log_forwarder_response_messages: VAR_DNSTAP_LOG_FORWARDER_RESPONSE_MES } ; pythonstart: VAR_PYTHON - { - OUTYY(("\nP(python:)\n")); + { + OUTYY(("\nP(python:)\n")); } ; contents_py: contents_py content_py @@ -3365,44 +3400,44 @@ dnsc_dnscrypt_secret_key: VAR_DNSCRYPT_SECRET_KEY STRING_ARG ; dnsc_dnscrypt_shared_secret_cache_size: VAR_DNSCRYPT_SHARED_SECRET_CACHE_SIZE STRING_ARG { - OUTYY(("P(dnscrypt_shared_secret_cache_size:%s)\n", $2)); - if(!cfg_parse_memsize($2, &cfg_parser->cfg->dnscrypt_shared_secret_cache_size)) - yyerror("memory size expected"); - free($2); + OUTYY(("P(dnscrypt_shared_secret_cache_size:%s)\n", $2)); + if(!cfg_parse_memsize($2, &cfg_parser->cfg->dnscrypt_shared_secret_cache_size)) + yyerror("memory size expected"); + free($2); } ; dnsc_dnscrypt_shared_secret_cache_slabs: VAR_DNSCRYPT_SHARED_SECRET_CACHE_SLABS STRING_ARG { - OUTYY(("P(dnscrypt_shared_secret_cache_slabs:%s)\n", $2)); - if(atoi($2) == 0) - yyerror("number expected"); - else { - cfg_parser->cfg->dnscrypt_shared_secret_cache_slabs = atoi($2); - if(!is_pow2(cfg_parser->cfg->dnscrypt_shared_secret_cache_slabs)) - yyerror("must be a power of 2"); - } - free($2); + OUTYY(("P(dnscrypt_shared_secret_cache_slabs:%s)\n", $2)); + if(atoi($2) == 0) { + yyerror("number expected"); + } else { + cfg_parser->cfg->dnscrypt_shared_secret_cache_slabs = atoi($2); + if(!is_pow2(cfg_parser->cfg->dnscrypt_shared_secret_cache_slabs)) + yyerror("must be a power of 2"); + } + free($2); } ; dnsc_dnscrypt_nonce_cache_size: VAR_DNSCRYPT_NONCE_CACHE_SIZE STRING_ARG { - OUTYY(("P(dnscrypt_nonce_cache_size:%s)\n", $2)); - if(!cfg_parse_memsize($2, &cfg_parser->cfg->dnscrypt_nonce_cache_size)) - yyerror("memory size expected"); - free($2); + OUTYY(("P(dnscrypt_nonce_cache_size:%s)\n", $2)); + if(!cfg_parse_memsize($2, &cfg_parser->cfg->dnscrypt_nonce_cache_size)) + yyerror("memory size expected"); + free($2); } ; dnsc_dnscrypt_nonce_cache_slabs: VAR_DNSCRYPT_NONCE_CACHE_SLABS STRING_ARG { - OUTYY(("P(dnscrypt_nonce_cache_slabs:%s)\n", $2)); - if(atoi($2) == 0) - yyerror("number expected"); - else { - cfg_parser->cfg->dnscrypt_nonce_cache_slabs = atoi($2); - if(!is_pow2(cfg_parser->cfg->dnscrypt_nonce_cache_slabs)) - yyerror("must be a power of 2"); - } - free($2); + OUTYY(("P(dnscrypt_nonce_cache_slabs:%s)\n", $2)); + if(atoi($2) == 0) { + yyerror("number expected"); + } else { + cfg_parser->cfg->dnscrypt_nonce_cache_slabs = atoi($2); + if(!is_pow2(cfg_parser->cfg->dnscrypt_nonce_cache_slabs)) + yyerror("must be a power of 2"); + } + free($2); } ; cachedbstart: VAR_CACHEDB diff --git a/contrib/unbound/util/data/msgencode.c b/contrib/unbound/util/data/msgencode.c index 5f297b551bfb..fe21cfb86bd1 100644 --- a/contrib/unbound/util/data/msgencode.c +++ b/contrib/unbound/util/data/msgencode.c @@ -796,7 +796,10 @@ calc_edns_field_size(struct edns_data* edns) struct edns_option* opt; if(!edns || !edns->edns_present) return 0; - for(opt = edns->opt_list; opt; opt = opt->next) { + for(opt = edns->opt_list_inplace_cb_out; opt; opt = opt->next) { + rdatalen += 4 + opt->opt_len; + } + for(opt = edns->opt_list_out; opt; opt = opt->next) { rdatalen += 4 + opt->opt_len; } /* domain root '.' + type + class + ttl + rdatalen */ @@ -827,7 +830,17 @@ attach_edns_record_max_msg_sz(sldns_buffer* pkt, struct edns_data* edns, rdatapos = sldns_buffer_position(pkt); sldns_buffer_write_u16(pkt, 0); /* rdatalen */ /* write rdata */ - for(opt=edns->opt_list; opt; opt=opt->next) { + for(opt=edns->opt_list_inplace_cb_out; opt; opt=opt->next) { + if (opt->opt_code == LDNS_EDNS_PADDING) { + padding_option = opt; + continue; + } + sldns_buffer_write_u16(pkt, opt->opt_code); + sldns_buffer_write_u16(pkt, opt->opt_len); + if(opt->opt_len != 0) + sldns_buffer_write(pkt, opt->opt_data, opt->opt_len); + } + for(opt=edns->opt_list_out; opt; opt=opt->next) { if (opt->opt_code == LDNS_EDNS_PADDING) { padding_option = opt; continue; @@ -860,8 +873,7 @@ attach_edns_record_max_msg_sz(sldns_buffer* pkt, struct edns_data* edns, sldns_buffer_skip(pkt, pad_sz); } } - if(edns->opt_list) - sldns_buffer_write_u16_at(pkt, rdatapos, + sldns_buffer_write_u16_at(pkt, rdatapos, sldns_buffer_position(pkt)-rdatapos-2); sldns_buffer_flip(pkt); } diff --git a/contrib/unbound/util/data/msgparse.c b/contrib/unbound/util/data/msgparse.c index 6ee5559db07b..a600a8c60151 100644 --- a/contrib/unbound/util/data/msgparse.c +++ b/contrib/unbound/util/data/msgparse.c @@ -37,10 +37,12 @@ * Routines for message parsing a packet buffer to a descriptive structure. */ #include "config.h" +#include "util/config_file.h" #include "util/data/msgparse.h" #include "util/data/msgreply.h" #include "util/data/dname.h" #include "util/data/packed_rrset.h" +#include "util/netevent.h" #include "util/storage/lookup3.h" #include "util/regional.h" #include "sldns/rrdef.h" @@ -938,11 +940,40 @@ parse_packet(sldns_buffer* pkt, struct msg_parse* msg, struct regional* region) return 0; } +static int +edns_opt_list_append_keepalive(struct edns_option** list, int msec, + struct regional* region) +{ + uint8_t data[2]; /* For keepalive value */ + data[0] = (uint8_t)((msec >> 8) & 0xff); + data[1] = (uint8_t)(msec & 0xff); + return edns_opt_list_append(list, LDNS_EDNS_KEEPALIVE, sizeof(data), + data, region); +} + /** parse EDNS options from EDNS wireformat rdata */ static int -parse_edns_options(uint8_t* rdata_ptr, size_t rdata_len, - struct edns_data* edns, struct regional* region) +parse_edns_options_from_query(uint8_t* rdata_ptr, size_t rdata_len, + struct edns_data* edns, struct config_file* cfg, struct comm_point* c, + struct regional* region) { + /* To respond with a Keepalive option, the client connection must have + * received one message with a TCP Keepalive EDNS option, and that + * option must have 0 length data. Subsequent messages sent on that + * connection will have a TCP Keepalive option. + * + * In the if-statement below, the option is added unsolicited. This + * means that the client has sent an KEEPALIVE option earlier. We know + * here this is true, because c->tcp_keepalive is set. + */ + if (cfg && cfg->do_tcp_keepalive && c && c->type != comm_udp && c->tcp_keepalive) { + if(!edns_opt_list_append_keepalive(&edns->opt_list_out, + c->tcp_timeout_msec / 100, region)) { + log_err("out of memory"); + return LDNS_RCODE_SERVFAIL; + } + } + /* while still more options, and have code+len to read */ /* ignores partial content (i.e. rdata len 3) */ while(rdata_len >= 4) { @@ -952,20 +983,81 @@ parse_edns_options(uint8_t* rdata_ptr, size_t rdata_len, rdata_len -= 4; if(opt_len > rdata_len) break; /* option code partial */ - if(!edns_opt_append(edns, region, opt_code, opt_len, - rdata_ptr)) { + + /* handle parse time edns options here */ + switch(opt_code) { + case LDNS_EDNS_NSID: + if (!cfg || !cfg->nsid) + break; + if(!edns_opt_list_append(&edns->opt_list_out, + LDNS_EDNS_NSID, cfg->nsid_len, + cfg->nsid, region)) { + log_err("out of memory"); + return LDNS_RCODE_SERVFAIL; + } + break; + + case LDNS_EDNS_KEEPALIVE: + /* To respond with a Keepalive option, the client + * connection must have received one message with a TCP + * Keepalive EDNS option, and that option must have 0 + * length data. Subsequent messages sent on that + * connection will have a TCP Keepalive option. + * + * This should be the first time the client sends this + * option, so c->tcp_keepalive is not set. + * Besides adding the reply KEEPALIVE option, + * c->tcp_keepalive will be set so that the + * option will be added unsolicited in subsequent + * responses (see the comment above the if-statement + * at the start of this function). + */ + if (!cfg || !cfg->do_tcp_keepalive || !c || + c->type == comm_udp || c->tcp_keepalive) + break; + if(opt_len) { + verbose(VERB_ALGO, "query with bad edns keepalive."); + return LDNS_RCODE_FORMERR; + } + if(!edns_opt_list_append_keepalive(&edns->opt_list_out, + c->tcp_timeout_msec / 100, + region)) { + log_err("out of memory"); + return LDNS_RCODE_SERVFAIL; + } + c->tcp_keepalive = 1; + break; + + case LDNS_EDNS_PADDING: + if(!cfg || !cfg->pad_responses || + !c || c->type != comm_tcp ||!c->ssl) + break; + if(!edns_opt_list_append(&edns->opt_list_out, + LDNS_EDNS_PADDING, + 0, NULL, region)) { + log_err("out of memory"); + return LDNS_RCODE_SERVFAIL; + } + edns->padding_block_size = cfg->pad_responses_block_size; + break; + + default: + break; + } + if(!edns_opt_list_append(&edns->opt_list_in, + opt_code, opt_len, rdata_ptr, region)) { log_err("out of memory"); - return 0; + return LDNS_RCODE_SERVFAIL; } rdata_ptr += opt_len; rdata_len -= opt_len; } - return 1; + return LDNS_RCODE_NOERROR; } int -parse_extract_edns(struct msg_parse* msg, struct edns_data* edns, - struct regional* region) +parse_extract_edns_from_response_msg(struct msg_parse* msg, + struct edns_data* edns, struct regional* region) { struct rrset_parse* rrset = msg->rrset_first; struct rrset_parse* prev = 0; @@ -1019,18 +1111,35 @@ parse_extract_edns(struct msg_parse* msg, struct edns_data* edns, edns->edns_version = found->rr_last->ttl_data[1]; edns->bits = sldns_read_uint16(&found->rr_last->ttl_data[2]); edns->udp_size = ntohs(found->rrset_class); - edns->opt_list = NULL; + edns->opt_list_in = NULL; + edns->opt_list_out = NULL; + edns->opt_list_inplace_cb_out = NULL; edns->padding_block_size = 0; /* take the options */ rdata_len = found->rr_first->size-2; rdata_ptr = found->rr_first->ttl_data+6; - if(!parse_edns_options(rdata_ptr, rdata_len, edns, region)) - return 0; + /* while still more options, and have code+len to read */ + /* ignores partial content (i.e. rdata len 3) */ + while(rdata_len >= 4) { + uint16_t opt_code = sldns_read_uint16(rdata_ptr); + uint16_t opt_len = sldns_read_uint16(rdata_ptr+2); + rdata_ptr += 4; + rdata_len -= 4; + if(opt_len > rdata_len) + break; /* option code partial */ + + if(!edns_opt_list_append(&edns->opt_list_in, + opt_code, opt_len, rdata_ptr, region)) { + log_err("out of memory"); + break; + } + rdata_ptr += opt_len; + rdata_len -= opt_len; + } /* ignore rrsigs */ - - return 0; + return LDNS_RCODE_NOERROR; } /** skip RR in packet */ @@ -1060,8 +1169,8 @@ skip_pkt_rrs(sldns_buffer* pkt, int num) } int -parse_edns_from_pkt(sldns_buffer* pkt, struct edns_data* edns, - struct regional* region) +parse_edns_from_query_pkt(sldns_buffer* pkt, struct edns_data* edns, + struct config_file* cfg, struct comm_point* c, struct regional* region) { size_t rdata_len; uint8_t* rdata_ptr; @@ -1093,7 +1202,9 @@ parse_edns_from_pkt(sldns_buffer* pkt, struct edns_data* edns, edns->ext_rcode = sldns_buffer_read_u8(pkt); /* ttl used for bits */ edns->edns_version = sldns_buffer_read_u8(pkt); edns->bits = sldns_buffer_read_u16(pkt); - edns->opt_list = NULL; + edns->opt_list_in = NULL; + edns->opt_list_out = NULL; + edns->opt_list_inplace_cb_out = NULL; edns->padding_block_size = 0; /* take the options */ @@ -1101,12 +1212,9 @@ parse_edns_from_pkt(sldns_buffer* pkt, struct edns_data* edns, if(sldns_buffer_remaining(pkt) < rdata_len) return LDNS_RCODE_FORMERR; rdata_ptr = sldns_buffer_current(pkt); - if(!parse_edns_options(rdata_ptr, rdata_len, edns, region)) - return LDNS_RCODE_SERVFAIL; - /* ignore rrsigs */ - - return 0; + return parse_edns_options_from_query(rdata_ptr, rdata_len, edns, cfg, + c, region); } void diff --git a/contrib/unbound/util/data/msgparse.h b/contrib/unbound/util/data/msgparse.h index d2fd9c806657..4c0559a739a4 100644 --- a/contrib/unbound/util/data/msgparse.h +++ b/contrib/unbound/util/data/msgparse.h @@ -70,6 +70,8 @@ struct rrset_parse; struct rr_parse; struct regional; struct edns_option; +struct config_file; +struct comm_point; /** number of buckets in parse rrset hash table. Must be power of 2. */ #define PARSE_TABLE_SIZE 32 @@ -225,8 +227,15 @@ struct edns_data { uint16_t bits; /** UDP reassembly size. */ uint16_t udp_size; - /** rdata element list, or NULL if none */ - struct edns_option* opt_list; + /** rdata element list of options of an incoming packet created at + * parse time, or NULL if none */ + struct edns_option* opt_list_in; + /** rdata element list of options to encode for outgoing packets, + * or NULL if none */ + struct edns_option* opt_list_out; + /** rdata element list of outgoing edns options from modules + * or NULL if none */ + struct edns_option* opt_list_inplace_cb_out; /** block size to pad */ uint16_t padding_block_size; }; @@ -281,8 +290,8 @@ int parse_packet(struct sldns_buffer* pkt, struct msg_parse* msg, * @return: 0 on success. or an RCODE on an error. * RCODE formerr if OPT in wrong section, and so on. */ -int parse_extract_edns(struct msg_parse* msg, struct edns_data* edns, - struct regional* region); +int parse_extract_edns_from_response_msg(struct msg_parse* msg, + struct edns_data* edns, struct regional* region); /** * If EDNS data follows a query section, extract it and initialize edns struct. @@ -290,12 +299,14 @@ int parse_extract_edns(struct msg_parse* msg, struct edns_data* edns, * section. At end, right after EDNS data or no movement if failed. * @param edns: the edns data allocated by the caller. Does not have to be * initialised. + * @param cfg: the configuration (with nsid value etc.) + * @param c: commpoint to determine transport (if needed) * @param region: region to alloc results in (edns option contents) * @return: 0 on success, or an RCODE on error. * RCODE formerr if OPT is badly formatted and so on. */ -int parse_edns_from_pkt(struct sldns_buffer* pkt, struct edns_data* edns, - struct regional* region); +int parse_edns_from_query_pkt(struct sldns_buffer* pkt, struct edns_data* edns, + struct config_file* cfg, struct comm_point* c, struct regional* region); /** * Calculate hash value for rrset in packet. diff --git a/contrib/unbound/util/data/msgreply.c b/contrib/unbound/util/data/msgreply.c index 00272fd1c64e..ec46e4724780 100644 --- a/contrib/unbound/util/data/msgreply.c +++ b/contrib/unbound/util/data/msgreply.c @@ -166,6 +166,32 @@ reply_info_alloc_rrset_keys(struct reply_info* rep, struct alloc_cache* alloc, return 1; } +struct reply_info * +make_new_reply_info(const struct reply_info* rep, struct regional* region, + size_t an_numrrsets, size_t copy_rrsets) +{ + struct reply_info* new_rep; + size_t i; + + /* create a base struct. we specify 'insecure' security status as + * the modified response won't be DNSSEC-valid. In our faked response + * the authority and additional sections will be empty (except possible + * EDNS0 OPT RR in the additional section appended on sending it out), + * so the total number of RRsets is an_numrrsets. */ + new_rep = construct_reply_info_base(region, rep->flags, + rep->qdcount, rep->ttl, rep->prefetch_ttl, + rep->serve_expired_ttl, an_numrrsets, 0, 0, an_numrrsets, + sec_status_insecure); + if(!new_rep) + return NULL; + if(!reply_info_alloc_rrset_keys(new_rep, NULL, region)) + return NULL; + for(i=0; irrsets[i] = rep->rrsets[i]; + + return new_rep; +} + /** find the minimumttl in the rdata of SOA record */ static time_t soa_find_minttl(struct rr_parse* rr) @@ -196,13 +222,17 @@ rdata_copy(sldns_buffer* pkt, struct packed_rrset_data* data, uint8_t* to, * minimum-ttl in the rdata of the SOA record */ if(*rr_ttl > soa_find_minttl(rr)) *rr_ttl = soa_find_minttl(rr); - if(*rr_ttl > MAX_NEG_TTL) - *rr_ttl = MAX_NEG_TTL; } if(!SERVE_ORIGINAL_TTL && (*rr_ttl < MIN_TTL)) *rr_ttl = MIN_TTL; if(!SERVE_ORIGINAL_TTL && (*rr_ttl > MAX_TTL)) *rr_ttl = MAX_TTL; + if(type == LDNS_RR_TYPE_SOA && section == LDNS_SECTION_AUTHORITY) { + /* max neg ttl overrides the min and max ttl of everything + * else, it is for a more specific record */ + if(*rr_ttl > MAX_NEG_TTL) + *rr_ttl = MAX_NEG_TTL; + } if(*rr_ttl < data->ttl) data->ttl = *rr_ttl; @@ -488,14 +518,13 @@ int reply_info_parse(sldns_buffer* pkt, struct alloc_cache* alloc, if((ret = parse_packet(pkt, msg, region)) != 0) { return ret; } - if((ret = parse_extract_edns(msg, edns, region)) != 0) + if((ret = parse_extract_edns_from_response_msg(msg, edns, region)) != 0) return ret; /* parse OK, allocate return structures */ /* this also performs dname decompression */ if(!parse_create_msg(pkt, msg, alloc, qinf, rep, NULL)) { query_info_clear(qinf); - reply_info_parsedelete(*rep, alloc); *rep = NULL; return LDNS_RCODE_SERVFAIL; } @@ -960,34 +989,6 @@ parse_reply_in_temp_region(sldns_buffer* pkt, struct regional* region, return rep; } -int edns_opt_append(struct edns_data* edns, struct regional* region, - uint16_t code, size_t len, uint8_t* data) -{ - struct edns_option** prevp; - struct edns_option* opt; - - /* allocate new element */ - opt = (struct edns_option*)regional_alloc(region, sizeof(*opt)); - if(!opt) - return 0; - opt->next = NULL; - opt->opt_code = code; - opt->opt_len = len; - opt->opt_data = NULL; - if(len > 0) { - opt->opt_data = regional_alloc_init(region, data, len); - if(!opt->opt_data) - return 0; - } - - /* append at end of list */ - prevp = &edns->opt_list; - while(*prevp != NULL) - prevp = &((*prevp)->next); - *prevp = opt; - return 1; -} - int edns_opt_list_append(struct edns_option** list, uint16_t code, size_t len, uint8_t* data, struct regional* region) { @@ -1068,7 +1069,7 @@ static int inplace_cb_reply_call_generic( (void)(*(inplace_cb_reply_func_type*)cb->cb)(qinfo, qstate, rep, rcode, edns, &opt_list_out, repinfo, region, start_time, cb->id, cb->cb_arg); } - edns->opt_list = opt_list_out; + edns->opt_list_inplace_cb_out = opt_list_out; return 1; } diff --git a/contrib/unbound/util/data/msgreply.h b/contrib/unbound/util/data/msgreply.h index c6b220ed8d71..81c763fc7c3a 100644 --- a/contrib/unbound/util/data/msgreply.h +++ b/contrib/unbound/util/data/msgreply.h @@ -382,6 +382,21 @@ struct reply_info* reply_info_copy(struct reply_info* rep, int reply_info_alloc_rrset_keys(struct reply_info* rep, struct alloc_cache* alloc, struct regional* region); +/* + * Create a new reply_info based on 'rep'. The new info is based on + * the passed 'rep', but ignores any rrsets except for the first 'an_numrrsets' + * RRsets in the answer section. These answer rrsets are copied to the + * new info, up to 'copy_rrsets' rrsets (which must not be larger than + * 'an_numrrsets'). If an_numrrsets > copy_rrsets, the remaining rrsets array + * entries will be kept empty so the caller can fill them later. When rrsets + * are copied, they are shallow copied. The caller must ensure that the + * copied rrsets are valid throughout its lifetime and must provide appropriate + * mutex if it can be shared by multiple threads. + */ +struct reply_info * +make_new_reply_info(const struct reply_info* rep, struct regional* region, + size_t an_numrrsets, size_t copy_rrsets); + /** * Copy a parsed rrset into given key, decompressing and allocating rdata. * @param pkt: packet for decompression @@ -503,18 +518,6 @@ void log_reply_info(enum verbosity_value v, struct query_info *qinf, void log_query_info(enum verbosity_value v, const char* str, struct query_info* qinf); -/** - * Append edns option to edns data structure - * @param edns: the edns data structure to append the edns option to. - * @param region: region to allocate the new edns option. - * @param code: the edns option's code. - * @param len: the edns option's length. - * @param data: the edns option's data. - * @return false on failure. - */ -int edns_opt_append(struct edns_data* edns, struct regional* region, - uint16_t code, size_t len, uint8_t* data); - /** * Append edns option to edns option list * @param list: the edns option list to append the edns option to. diff --git a/contrib/unbound/util/data/packed_rrset.h b/contrib/unbound/util/data/packed_rrset.h index ff95c0af0e8d..e1feb22bb7f6 100644 --- a/contrib/unbound/util/data/packed_rrset.h +++ b/contrib/unbound/util/data/packed_rrset.h @@ -61,6 +61,13 @@ typedef uint64_t rrset_id_type; * updated on encoding in a reply. This flag is not expected to be set in * cached data. */ #define PACKED_RRSET_FIXEDTTL 0x80000000 +/** This rrset is from RPZ. It is not real, it is synthesized data to block + * access. The flag makes lookups, from cache in iterator, ignore the fake + * items and only use actual data. Eg. when the iterator looksup NS, CNAME, + * A and AAAA types, it then gets items without this flag that are the + * actual network. But messages with these records in it can be stored in + * the cache and retrieved for a reply. */ +#define PACKED_RRSET_RPZ 0x8 /** number of rrs and rrsets for integer overflow protection. More than * this is not really possible (64K packet has much less RRs and RRsets) in @@ -88,6 +95,7 @@ struct packed_rrset_key { * o PACKED_RRSET_PARENT_SIDE * o PACKED_RRSET_SOA_NEG * o PACKED_RRSET_FIXEDTTL (not supposed to be cached) + * o PACKED_RRSET_RPZ */ uint32_t flags; /** the rrset type in network format */ diff --git a/contrib/unbound/util/edns.c b/contrib/unbound/util/edns.c index 664cadd53da9..e0819f1cd3b4 100644 --- a/contrib/unbound/util/edns.c +++ b/contrib/unbound/util/edns.c @@ -133,53 +133,3 @@ edns_string_addr_lookup(rbtree_type* tree, struct sockaddr_storage* addr, return (struct edns_string_addr*)addr_tree_lookup(tree, addr, addrlen); } -static int edns_keepalive(struct edns_data* edns_out, struct edns_data* edns_in, - struct comm_point* c, struct regional* region) -{ - if(c->type == comm_udp) - return 1; - - /* To respond with a Keepalive option, the client connection - * must have received one message with a TCP Keepalive EDNS option, - * and that option must have 0 length data. Subsequent messages - * sent on that connection will have a TCP Keepalive option. - */ - if(c->tcp_keepalive || - edns_opt_list_find(edns_in->opt_list, LDNS_EDNS_KEEPALIVE)) { - int keepalive = c->tcp_timeout_msec / 100; - uint8_t data[2]; - data[0] = (uint8_t)((keepalive >> 8) & 0xff); - data[1] = (uint8_t)(keepalive & 0xff); - if(!edns_opt_list_append(&edns_out->opt_list, LDNS_EDNS_KEEPALIVE, - sizeof(data), data, region)) - return 0; - c->tcp_keepalive = 1; - } - return 1; -} - -int apply_edns_options(struct edns_data* edns_out, struct edns_data* edns_in, - struct config_file* cfg, struct comm_point* c, struct regional* region) -{ - if(cfg->do_tcp_keepalive && - !edns_keepalive(edns_out, edns_in, c, region)) - return 0; - - if (cfg->nsid && edns_opt_list_find(edns_in->opt_list, LDNS_EDNS_NSID) - && !edns_opt_list_append(&edns_out->opt_list, - LDNS_EDNS_NSID, cfg->nsid_len, cfg->nsid, region)) - return 0; - - if(!cfg->pad_responses || c->type != comm_tcp || !c->ssl - || !edns_opt_list_find(edns_in->opt_list, LDNS_EDNS_PADDING)) { - ; /* pass */ - } - - else if(!edns_opt_list_append(&edns_out->opt_list, LDNS_EDNS_PADDING - , 0, NULL, region)) - return 0; - else - edns_out->padding_block_size = cfg->pad_responses_block_size; - - return 1; -} diff --git a/contrib/unbound/util/edns.h b/contrib/unbound/util/edns.h index 11742eb5b723..d9ded0b84dc4 100644 --- a/contrib/unbound/util/edns.h +++ b/contrib/unbound/util/edns.h @@ -106,16 +106,4 @@ struct edns_string_addr* edns_string_addr_lookup(rbtree_type* tree, struct sockaddr_storage* addr, socklen_t addrlen); -/** - * Apply common EDNS options. - * - * @param edns_out: initialised edns information with outbound edns. - * @param edns_in: initialised edns information with received edns. - * @param cfg: configuration. - * @param c: comm channel. - * @param region: the region to allocate the edns options in. - */ -int apply_edns_options(struct edns_data* edns_out, struct edns_data* edns_in, - struct config_file* cfg, struct comm_point* c, struct regional* region); - #endif diff --git a/contrib/unbound/util/fptr_wlist.c b/contrib/unbound/util/fptr_wlist.c index de6dbd02a37d..f8dac65c59a0 100644 --- a/contrib/unbound/util/fptr_wlist.c +++ b/contrib/unbound/util/fptr_wlist.c @@ -335,7 +335,7 @@ int fptr_whitelist_modenv_send_query(struct outbound_entry* (*fptr)( struct query_info* qinfo, uint16_t flags, int dnssec, int want_dnssec, int nocaps, struct sockaddr_storage* addr, socklen_t addrlen, - uint8_t* zone, size_t zonelen, int ssl_upstream, char* tls_auth_name, + uint8_t* zone, size_t zonelen, int tcp_upstream, int ssl_upstream, char* tls_auth_name, struct module_qstate* q)) { if(fptr == &worker_send_query) return 1; diff --git a/contrib/unbound/util/fptr_wlist.h b/contrib/unbound/util/fptr_wlist.h index cd331febb070..a5470992550f 100644 --- a/contrib/unbound/util/fptr_wlist.h +++ b/contrib/unbound/util/fptr_wlist.h @@ -212,7 +212,7 @@ int fptr_whitelist_hash_markdelfunc(lruhash_markdelfunc_type fptr); int fptr_whitelist_modenv_send_query(struct outbound_entry* (*fptr)( struct query_info* qinfo, uint16_t flags, int dnssec, int want_dnssec, int nocaps, struct sockaddr_storage* addr, socklen_t addrlen, - uint8_t* zone, size_t zonelen, int ssl_upstream, char* tls_auth_name, + uint8_t* zone, size_t zonelen, int tcp_upstream, int ssl_upstream, char* tls_auth_name, struct module_qstate* q)); /** diff --git a/contrib/unbound/util/iana_ports.inc b/contrib/unbound/util/iana_ports.inc index b93af015da6f..9183c3987292 100644 --- a/contrib/unbound/util/iana_ports.inc +++ b/contrib/unbound/util/iana_ports.inc @@ -2499,6 +2499,7 @@ 2870, 2871, 2872, +2873, 2874, 2875, 2876, diff --git a/contrib/unbound/util/mini_event.c b/contrib/unbound/util/mini_event.c index 661d88d2e6f6..c05dc668c676 100644 --- a/contrib/unbound/util/mini_event.c +++ b/contrib/unbound/util/mini_event.c @@ -337,6 +337,15 @@ int event_del(struct event* ev) FD_CLR(FD_SET_T ev->ev_fd, &ev->ev_base->writes); FD_CLR(FD_SET_T ev->ev_fd, &ev->ev_base->ready); FD_CLR(FD_SET_T ev->ev_fd, &ev->ev_base->content); + if(ev->ev_fd == ev->ev_base->maxfd) { + int i = ev->ev_base->maxfd - 1; + for (; i > 3; i--) { + if (NULL != ev->ev_base->fds[i]) { + break; + } + } + ev->ev_base->maxfd = i; + } } ev->added = 0; return 0; diff --git a/contrib/unbound/util/module.h b/contrib/unbound/util/module.h index 81a31a9cca46..c6b7e573ce00 100644 --- a/contrib/unbound/util/module.h +++ b/contrib/unbound/util/module.h @@ -354,10 +354,11 @@ struct module_env { * @param addrlen: length of addr. * @param zone: delegation point name. * @param zonelen: length of zone name. + * @param tcp_upstream: use TCP for upstream queries. * @param ssl_upstream: use SSL for upstream queries. * @param tls_auth_name: if ssl_upstream, use this name with TLS * authentication. - * @param q: wich query state to reactivate upon return. + * @param q: which query state to reactivate upon return. * @return: false on failure (memory or socket related). no query was * sent. Or returns an outbound entry with qsent and qstate set. * This outbound_entry will be used on later module invocations @@ -366,7 +367,7 @@ struct module_env { struct outbound_entry* (*send_query)(struct query_info* qinfo, uint16_t flags, int dnssec, int want_dnssec, int nocaps, struct sockaddr_storage* addr, socklen_t addrlen, - uint8_t* zone, size_t zonelen, int ssl_upstream, + uint8_t* zone, size_t zonelen, int tcp_upstream, int ssl_upstream, char* tls_auth_name, struct module_qstate* q); /** diff --git a/contrib/unbound/util/net_help.c b/contrib/unbound/util/net_help.c index 06bc1f5dd7e6..d63fccd55ca2 100644 --- a/contrib/unbound/util/net_help.c +++ b/contrib/unbound/util/net_help.c @@ -38,6 +38,12 @@ */ #include "config.h" +#ifdef HAVE_SYS_TYPES_H +# include +#endif +#ifdef HAVE_NET_IF_H +#include +#endif #include "util/net_help.h" #include "util/log.h" #include "util/data/dname.h" @@ -266,7 +272,10 @@ ipstrtoaddr(const char* ip, int port, struct sockaddr_storage* addr, return 0; (void)strlcpy(buf, ip, sizeof(buf)); buf[s-ip]=0; - sa->sin6_scope_id = (uint32_t)atoi(s+1); +#ifdef HAVE_IF_NAMETOINDEX + if (!(sa->sin6_scope_id = if_nametoindex(s+1))) +#endif /* HAVE_IF_NAMETOINDEX */ + sa->sin6_scope_id = (uint32_t)atoi(s+1); ip = buf; } if(inet_pton((int)sa->sin6_family, ip, &sa->sin6_addr) <= 0) { @@ -881,6 +890,12 @@ log_cert(unsigned level, const char* str, void* cert) BIO_write(bio, &nul, (int)sizeof(nul)); len = BIO_get_mem_data(bio, &pp); if(len != 0 && pp) { + /* reduce size of cert printout */ + char* s; + while((s=strstr(pp, " "))!=NULL) + memmove(s, s+1, strlen(s+1)+1); + while((s=strstr(pp, "\t\t"))!=NULL) + memmove(s, s+1, strlen(s+1)+1); verbose(level, "%s: \n%s", str, pp); } BIO_free(bio); @@ -945,9 +960,12 @@ listen_sslctx_setup(void* ctxt) } #endif #if defined(SHA256_DIGEST_LENGTH) && defined(USE_ECDSA) + /* if we detect system-wide crypto policies, use those */ + if (access( "/etc/crypto-policies/config", F_OK ) != 0 ) { /* if we have sha256, set the cipher list to have no known vulns */ - if(!SSL_CTX_set_cipher_list(ctx, "TLS13-CHACHA20-POLY1305-SHA256:TLS13-AES-256-GCM-SHA384:TLS13-AES-128-GCM-SHA256:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256")) - log_crypto_err("could not set cipher list with SSL_CTX_set_cipher_list"); + if(!SSL_CTX_set_cipher_list(ctx, "TLS13-CHACHA20-POLY1305-SHA256:TLS13-AES-256-GCM-SHA384:TLS13-AES-128-GCM-SHA256:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256")) + log_crypto_err("could not set cipher list with SSL_CTX_set_cipher_list"); + } #endif if((SSL_CTX_set_options(ctx, SSL_OP_CIPHER_SERVER_PREFERENCE) & @@ -1172,6 +1190,7 @@ void* connect_sslctx_create(char* key, char* pem, char* verifypem, int wincert) if((SSL_CTX_set_options(ctx, SSL_OP_NO_RENEGOTIATION) & SSL_OP_NO_RENEGOTIATION) != SSL_OP_NO_RENEGOTIATION) { log_crypto_err("could not set SSL_OP_NO_RENEGOTIATION"); + SSL_CTX_free(ctx); return 0; } #endif diff --git a/contrib/unbound/util/netevent.c b/contrib/unbound/util/netevent.c index 11c642a2bc38..595e5dc80516 100644 --- a/contrib/unbound/util/netevent.c +++ b/contrib/unbound/util/netevent.c @@ -300,6 +300,7 @@ udp_send_errno_needs_log(struct sockaddr* addr, socklen_t addrlen) case ENETDOWN: # endif case EPERM: + case EACCES: if(verbosity < VERB_ALGO) return 0; default: @@ -817,6 +818,7 @@ setup_tcp_handler(struct comm_point* c, int fd, int cur, int max) #endif c->tcp_is_reading = 1; c->tcp_byte_count = 0; + c->tcp_keepalive = 0; /* if more than half the tcp handlers are in use, use a shorter * timeout for this TCP connection, we need to make space for * other connections to be able to get attention */ @@ -942,7 +944,16 @@ int comm_point_perform_accept(struct comm_point* c, #ifdef USE_WINSOCK static long win_bio_cb(BIO *b, int oper, const char* ATTR_UNUSED(argp), - int ATTR_UNUSED(argi), long argl, long retvalue) +#ifdef HAVE_BIO_SET_CALLBACK_EX + size_t ATTR_UNUSED(len), +#endif + int ATTR_UNUSED(argi), long argl, +#ifndef HAVE_BIO_SET_CALLBACK_EX + long retvalue +#else + int retvalue, size_t* ATTR_UNUSED(processed) +#endif + ) { int wsa_err = WSAGetLastError(); /* store errcode before it is gone */ verbose(VERB_ALGO, "bio_cb %d, %s %s %s", oper, @@ -972,9 +983,17 @@ comm_point_tcp_win_bio_cb(struct comm_point* c, void* thessl) { SSL* ssl = (SSL*)thessl; /* set them both just in case, but usually they are the same BIO */ +#ifdef HAVE_BIO_SET_CALLBACK_EX + BIO_set_callback_ex(SSL_get_rbio(ssl), &win_bio_cb); +#else BIO_set_callback(SSL_get_rbio(ssl), &win_bio_cb); +#endif BIO_set_callback_arg(SSL_get_rbio(ssl), (char*)c->ev->ev); +#ifdef HAVE_BIO_SET_CALLBACK_EX + BIO_set_callback_ex(SSL_get_wbio(ssl), &win_bio_cb); +#else BIO_set_callback(SSL_get_wbio(ssl), &win_bio_cb); +#endif BIO_set_callback_arg(SSL_get_wbio(ssl), (char*)c->ev->ev); } #endif @@ -1036,6 +1055,7 @@ comm_point_tcp_accept_callback(int fd, short event, void* arg) /* clear leftover flags from previous use, and then set the * correct event base for the event structure for libevent */ ub_event_free(c_hdl->ev->ev); + c_hdl->ev->ev = NULL; if((c_hdl->type == comm_tcp && c_hdl->tcp_req_info) || c_hdl->type == comm_local || c_hdl->type == comm_raw) c_hdl->tcp_do_toggle_rw = 0; @@ -1092,6 +1112,7 @@ comm_point_tcp_accept_callback(int fd, short event, void* arg) /* grab the tcp handler buffers */ c->cur_tcp_count++; c->tcp_free = c_hdl->tcp_free; + c_hdl->tcp_free = NULL; if(!c->tcp_free) { /* stop accepting incoming queries for now. */ comm_point_stop_listening(c); @@ -1113,9 +1134,11 @@ reclaim_tcp_handler(struct comm_point* c) } comm_point_close(c); if(c->tcp_parent) { - c->tcp_parent->cur_tcp_count--; - c->tcp_free = c->tcp_parent->tcp_free; - c->tcp_parent->tcp_free = c; + if(c != c->tcp_parent->tcp_free) { + c->tcp_parent->cur_tcp_count--; + c->tcp_free = c->tcp_parent->tcp_free; + c->tcp_parent->tcp_free = c; + } if(!c->tcp_free) { /* re-enable listening on accept socket */ comm_point_start_listening(c->tcp_parent, -1, -1); @@ -1862,13 +1885,22 @@ comm_point_tcp_handle_write(int fd, struct comm_point* c) if(errno == EINTR || errno == EAGAIN) return 1; /* Not handling EISCONN here as shouldn't ever hit that case.*/ - if(errno != EPIPE && errno != 0 && verbosity < 2) - return 0; /* silence lots of chatter in the logs */ - if(errno != EPIPE && errno != 0) { + if(errno != EPIPE +#ifdef EOPNOTSUPP + /* if /proc/sys/net/ipv4/tcp_fastopen is + * disabled on Linux, sendmsg may return + * 'Operation not supported', if so + * fallthrough to ordinary connect. */ + && errno != EOPNOTSUPP +#endif + && errno != 0) { + if(verbosity < 2) + return 0; /* silence lots of chatter in the logs */ log_err_addr("tcp sendmsg", strerror(errno), &c->repinfo.addr, c->repinfo.addrlen); return 0; } + verbose(VERB_ALGO, "tcp sendmsg for fastopen failed (with %s), try normal connect", strerror(errno)); /* fallthrough to nonFASTOPEN * (MSG_FASTOPEN on Linux 3 produces EPIPE) * we need to perform connect() */ @@ -2201,9 +2233,11 @@ reclaim_http_handler(struct comm_point* c) } comm_point_close(c); if(c->tcp_parent) { - c->tcp_parent->cur_tcp_count--; - c->tcp_free = c->tcp_parent->tcp_free; - c->tcp_parent->tcp_free = c; + if(c != c->tcp_parent->tcp_free) { + c->tcp_parent->cur_tcp_count--; + c->tcp_free = c->tcp_parent->tcp_free; + c->tcp_parent->tcp_free = c; + } if(!c->tcp_free) { /* re-enable listening on accept socket */ comm_point_start_listening(c->tcp_parent, -1, -1); @@ -4140,6 +4174,10 @@ comm_point_start_listening(struct comm_point* c, int newfd, int msec) c->timeout->tv_sec = msec/1000; c->timeout->tv_usec = (msec%1000)*1000; #endif /* S_SPLINT_S */ + } else { + if(msec == 0 || !c->timeout) { + ub_event_del_bits(c->ev->ev, UB_EV_TIMEOUT); + } } if(c->type == comm_tcp || c->type == comm_http) { ub_event_del_bits(c->ev->ev, UB_EV_READ|UB_EV_WRITE); @@ -4164,6 +4202,7 @@ comm_point_start_listening(struct comm_point* c, int newfd, int msec) } if(ub_event_add(c->ev->ev, msec==0?NULL:c->timeout) != 0) { log_err("event_add failed. in cpsl."); + return; } c->event_added = 1; } @@ -4177,11 +4216,15 @@ void comm_point_listen_for_rw(struct comm_point* c, int rd, int wr) } c->event_added = 0; } + if(!c->timeout) { + ub_event_del_bits(c->ev->ev, UB_EV_TIMEOUT); + } ub_event_del_bits(c->ev->ev, UB_EV_READ|UB_EV_WRITE); if(rd) ub_event_add_bits(c->ev->ev, UB_EV_READ); if(wr) ub_event_add_bits(c->ev->ev, UB_EV_WRITE); if(ub_event_add(c->ev->ev, c->timeout) != 0) { log_err("event_add failed. in cplf."); + return; } c->event_added = 1; } diff --git a/contrib/unbound/util/netevent.h b/contrib/unbound/util/netevent.h index c79f99b3eb6d..9f4d28ba9f8f 100644 --- a/contrib/unbound/util/netevent.h +++ b/contrib/unbound/util/netevent.h @@ -743,7 +743,7 @@ struct comm_signal* comm_signal_create(struct comm_base* base, void (*callback)(int, void*), void* cb_arg); /** - * Bind signal struct to catch a signal. A signle comm_signal can be bound + * Bind signal struct to catch a signal. A single comm_signal can be bound * to multiple signals, calling comm_signal_bind multiple times. * @param comsig: the communication point, with callback information. * @param sig: signal number. diff --git a/contrib/unbound/util/regional.c b/contrib/unbound/util/regional.c index bd67ecf50af3..93e911c5ec1a 100644 --- a/contrib/unbound/util/regional.c +++ b/contrib/unbound/util/regional.c @@ -103,6 +103,8 @@ regional_create_custom_large_object(size_t size, size_t large_object_size) struct regional* regional_create_custom(size_t size) { + if(size < sizeof(struct regional)) + size = sizeof(struct regional); return regional_create_custom_large_object(size, REGIONAL_LARGE_OBJECT_SIZE); } diff --git a/contrib/unbound/util/shm_side/shm_main.c b/contrib/unbound/util/shm_side/shm_main.c index 51039abf3ed8..6fd1f5ea638c 100644 --- a/contrib/unbound/util/shm_side/shm_main.c +++ b/contrib/unbound/util/shm_side/shm_main.c @@ -281,7 +281,7 @@ void shm_main_run(struct worker *worker) shm_stat->mem.subnet = 0; #ifdef CLIENT_SUBNET shm_stat->mem.subnet = (long long)mod_get_mem(&worker->env, - "subnet"); + "subnetcache"); #endif /* ipsecmod mem value is available in shm, also when not enabled, * to make the struct easier to memmap by other applications, diff --git a/contrib/unbound/util/tube.c b/contrib/unbound/util/tube.c index dc6e3c2e7f78..40556e72020b 100644 --- a/contrib/unbound/util/tube.c +++ b/contrib/unbound/util/tube.c @@ -363,7 +363,11 @@ int tube_read_msg(struct tube* tube, uint8_t** buf, uint32_t* len, } d += r; } - log_assert(*len < 65536*2); + if (*len >= 65536*2) { + log_err("tube msg length %u is too big", (unsigned)*len); + (void)fd_set_nonblock(fd); + return 0; + } *buf = (uint8_t*)malloc(*len); if(!*buf) { log_err("tube read out of memory"); diff --git a/contrib/unbound/util/ub_event.c b/contrib/unbound/util/ub_event.c index 68f633bb0ef2..8cd87ec4e1d4 100644 --- a/contrib/unbound/util/ub_event.c +++ b/contrib/unbound/util/ub_event.c @@ -1,5 +1,5 @@ /* - * util/ub_event.c - directly call libevent (compatability) functions + * util/ub_event.c - directly call libevent (compatibility) functions * * Copyright (c) 2007, NLnet Labs. All rights reserved. * diff --git a/contrib/unbound/validator/autotrust.c b/contrib/unbound/validator/autotrust.c index 9643a3ddb38b..55e82c176dae 100644 --- a/contrib/unbound/validator/autotrust.c +++ b/contrib/unbound/validator/autotrust.c @@ -2377,7 +2377,9 @@ probe_anchor(struct module_env* env, struct trust_anchor* tp) edns.ext_rcode = 0; edns.edns_version = 0; edns.bits = EDNS_DO; - edns.opt_list = NULL; + edns.opt_list_in = NULL; + edns.opt_list_out = NULL; + edns.opt_list_inplace_cb_out = NULL; edns.padding_block_size = 0; if(sldns_buffer_capacity(buf) < 65535) edns.udp_size = (uint16_t)sldns_buffer_capacity(buf); diff --git a/contrib/unbound/validator/validator.c b/contrib/unbound/validator/validator.c index d4d48d956895..e6307284fb0e 100644 --- a/contrib/unbound/validator/validator.c +++ b/contrib/unbound/validator/validator.c @@ -140,7 +140,7 @@ val_apply_cfg(struct module_env* env, struct val_env* val_env, val_env->max_restart = cfg->val_max_restart; c = cfg_count_numbers(cfg->val_nsec3_key_iterations); if(c < 1 || (c&1)) { - log_err("validator: unparseable or odd nsec3 key " + log_err("validator: unparsable or odd nsec3 key " "iterations: %s", cfg->val_nsec3_key_iterations); return 0; } @@ -484,7 +484,7 @@ generate_keytag_query(struct module_qstate* qstate, int id, return 0; } - /* Not interrested in subquery response. Restore the ext_state, + /* Not interested in subquery response. Restore the ext_state, * that might be changed by generate_request() */ qstate->ext_state[id] = ext_state; diff --git a/contrib/unbound/validator/validator.h b/contrib/unbound/validator/validator.h index a928e10a65d8..a97eab25bc4a 100644 --- a/contrib/unbound/validator/validator.h +++ b/contrib/unbound/validator/validator.h @@ -68,7 +68,7 @@ struct config_strlist; #define SENTINEL_IS "root-key-sentinel-is-ta-" /** Root key sentinel is not ta preamble */ #define SENTINEL_NOT "root-key-sentinel-not-ta-" -/** Root key sentinal keytag length */ +/** Root key sentinel keytag length */ #define SENTINEL_KEYTAG_LEN 5 /**