aboutsummaryrefslogtreecommitdiff
path: root/contrib
diff options
context:
space:
mode:
authorCy Schubert <cy@FreeBSD.org>2020-08-24 18:14:04 +0000
committerCy Schubert <cy@FreeBSD.org>2020-08-24 18:14:04 +0000
commit25039b37d3883b8fdae50475cbea41a255a08ee2 (patch)
tree107a2df1bfda36ef3220a93fff6212e0c354ed36 /contrib
parent0a5eb308d3006e2f386620f7266b6593b300b987 (diff)
parent7973006f41cdaf144441d1a39f9f075053435e2f (diff)
downloadsrc-25039b37d3883b8fdae50475cbea41a255a08ee2.tar.gz
src-25039b37d3883b8fdae50475cbea41a255a08ee2.zip
MFV 364468:
Update unbound 1.10.1 --> 1.11.0. MFH: 1 month
Notes
Notes: svn path=/head/; revision=364721
Diffstat (limited to 'contrib')
-rw-r--r--contrib/unbound/.github/FUNDING.yml12
-rw-r--r--contrib/unbound/.travis.yml342
-rw-r--r--contrib/unbound/Makefile.in124
-rw-r--r--contrib/unbound/README-Travis.md278
-rw-r--r--contrib/unbound/acx_python.m45
-rw-r--r--contrib/unbound/cachedb/cachedb.c5
-rw-r--r--contrib/unbound/cachedb/cachedb.h2
-rw-r--r--contrib/unbound/cachedb/redis.c59
-rwxr-xr-xcontrib/unbound/config.guess895
-rw-r--r--contrib/unbound/config.h.in23
-rwxr-xr-xcontrib/unbound/config.sub2620
-rwxr-xr-xcontrib/unbound/configure224
-rw-r--r--contrib/unbound/configure.ac86
-rw-r--r--contrib/unbound/contrib/aaaa-filter-iterator.patch14
-rw-r--r--contrib/unbound/contrib/android/15-android.conf37
-rwxr-xr-xcontrib/unbound/contrib/android/install_expat.sh51
-rwxr-xr-xcontrib/unbound/contrib/android/install_ndk.sh60
-rwxr-xr-xcontrib/unbound/contrib/android/install_openssl.sh44
-rwxr-xr-xcontrib/unbound/contrib/android/install_tools.sh6
-rwxr-xr-xcontrib/unbound/contrib/android/setenv_android.sh203
-rw-r--r--contrib/unbound/contrib/fastrpz.patch122
-rw-r--r--contrib/unbound/contrib/ios/15-ios.conf41
-rwxr-xr-xcontrib/unbound/contrib/ios/install_expat.sh56
-rwxr-xr-xcontrib/unbound/contrib/ios/install_openssl.sh52
-rwxr-xr-xcontrib/unbound/contrib/ios/install_tools.sh8
-rw-r--r--contrib/unbound/contrib/ios/openssl.patch48
-rwxr-xr-xcontrib/unbound/contrib/ios/setenv_ios.sh274
-rw-r--r--contrib/unbound/contrib/libunbound.pc.in3
-rw-r--r--contrib/unbound/contrib/unbound.service.in2
-rw-r--r--contrib/unbound/daemon/acl_list.c2
-rw-r--r--contrib/unbound/daemon/daemon.c6
-rw-r--r--contrib/unbound/daemon/remote.c18
-rw-r--r--contrib/unbound/daemon/unbound.c10
-rw-r--r--contrib/unbound/daemon/worker.c44
-rw-r--r--contrib/unbound/dns64/dns64.c2
-rw-r--r--contrib/unbound/dnstap/dnstap.c90
-rw-r--r--contrib/unbound/dnstap/dnstap.h22
-rw-r--r--contrib/unbound/dnstap/dnstap.m49
-rw-r--r--contrib/unbound/dnstap/dnstap_fstrm.c236
-rw-r--r--contrib/unbound/dnstap/dnstap_fstrm.h194
-rw-r--r--contrib/unbound/dnstap/dtstream.c2128
-rw-r--r--contrib/unbound/dnstap/dtstream.h341
-rw-r--r--contrib/unbound/dnstap/unbound-dnstap-socket.c1594
-rw-r--r--contrib/unbound/doc/Changelog324
-rw-r--r--contrib/unbound/doc/README2
-rw-r--r--contrib/unbound/doc/example.conf.in71
-rw-r--r--contrib/unbound/doc/libunbound.3.in4
-rw-r--r--contrib/unbound/doc/unbound-anchor.8.in5
-rw-r--r--contrib/unbound/doc/unbound-checkconf.8.in2
-rw-r--r--contrib/unbound/doc/unbound-control.8.in2
-rw-r--r--contrib/unbound/doc/unbound-host.1.in2
-rw-r--r--contrib/unbound/doc/unbound.8.in4
-rw-r--r--contrib/unbound/doc/unbound.conf.5.in157
-rw-r--r--contrib/unbound/dynlibmod/dynlibmod.c301
-rw-r--r--contrib/unbound/dynlibmod/dynlibmod.h139
-rw-r--r--contrib/unbound/dynlibmod/examples/helloworld.c130
-rw-r--r--contrib/unbound/edns-subnet/subnetmod.c29
-rw-r--r--contrib/unbound/edns-subnet/subnetmod.h7
-rw-r--r--contrib/unbound/iterator/iter_utils.c57
-rw-r--r--contrib/unbound/iterator/iterator.c11
-rw-r--r--contrib/unbound/iterator/iterator.h5
-rw-r--r--contrib/unbound/libunbound/libworker.c28
-rw-r--r--contrib/unbound/libunbound/unbound.h1
-rw-r--r--contrib/unbound/respip/respip.c41
-rw-r--r--contrib/unbound/services/authzone.c63
-rw-r--r--contrib/unbound/services/authzone.h9
-rw-r--r--contrib/unbound/services/listen_dnsport.c90
-rw-r--r--contrib/unbound/services/listen_dnsport.h9
-rw-r--r--contrib/unbound/services/localzone.c2
-rw-r--r--contrib/unbound/services/mesh.c107
-rw-r--r--contrib/unbound/services/modstack.c9
-rw-r--r--contrib/unbound/services/outside_network.c121
-rw-r--r--contrib/unbound/services/outside_network.h14
-rw-r--r--contrib/unbound/services/rpz.c33
-rw-r--r--contrib/unbound/services/rpz.h8
-rw-r--r--contrib/unbound/sldns/parseutil.c2
-rw-r--r--contrib/unbound/smallapp/unbound-anchor.c35
-rw-r--r--contrib/unbound/smallapp/unbound-checkconf.c154
-rwxr-xr-xcontrib/unbound/smallapp/unbound-control-setup.sh.in209
-rw-r--r--contrib/unbound/smallapp/unbound-control.c12
-rw-r--r--contrib/unbound/smallapp/worker_cb.c16
-rw-r--r--contrib/unbound/util/config_file.c43
-rw-r--r--contrib/unbound/util/config_file.h25
-rw-r--r--contrib/unbound/util/configlexer.lex77
-rw-r--r--contrib/unbound/util/configparser.y155
-rw-r--r--contrib/unbound/util/fptr_wlist.c57
-rw-r--r--contrib/unbound/util/iana_ports.inc3
-rw-r--r--contrib/unbound/util/mini_event.h2
-rw-r--r--contrib/unbound/util/net_help.c159
-rw-r--r--contrib/unbound/util/net_help.h38
-rw-r--r--contrib/unbound/util/netevent.c59
-rw-r--r--contrib/unbound/util/netevent.h18
-rw-r--r--contrib/unbound/util/shm_side/shm_main.c4
-rw-r--r--contrib/unbound/util/ub_event.c4
-rw-r--r--contrib/unbound/validator/val_secalgo.c5
-rw-r--r--contrib/unbound/validator/val_sigcrypt.c2
96 files changed, 10906 insertions, 2352 deletions
diff --git a/contrib/unbound/.github/FUNDING.yml b/contrib/unbound/.github/FUNDING.yml
index ecee84aa4132..2a357c0c7778 100644
--- a/contrib/unbound/.github/FUNDING.yml
+++ b/contrib/unbound/.github/FUNDING.yml
@@ -1,12 +1,2 @@
-# These are supported funding model platforms
-
-github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
-patreon: # Replace with a single Patreon username
-open_collective: # Replace with a single Open Collective username
-ko_fi: # Replace with a single Ko-fi username
-tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
-community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
-liberapay: # Replace with a single Liberapay username
-issuehunt: # Replace with a single IssueHunt username
-otechie: # Replace with a single Otechie username
+github: [NLnetLabs]
custom: ['https://nlnetlabs.nl/funding/']
diff --git a/contrib/unbound/.travis.yml b/contrib/unbound/.travis.yml
index 45a7cb153501..37ea672b3494 100644
--- a/contrib/unbound/.travis.yml
+++ b/contrib/unbound/.travis.yml
@@ -1,7 +1,8 @@
-sudo: false
language: c
-compiler:
- - gcc
+
+git:
+ depth: 5
+
addons:
apt:
packages:
@@ -9,8 +10,335 @@ addons:
- libevent-dev
- libexpat-dev
- clang
+ homebrew:
+ packages:
+ - openssl
+ - libevent
+ - expat
+ 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
+ compiler: clang
+ arch: amd64
+ env:
+ - CONFIG_OPTS="--enable-debug --disable-flto"
+ - os: osx
+ name: Clang on OS X, Amd64
+ compiler: clang
+ arch: amd64
+ env:
+ - TEST_OSX=yes
+ - CONFIG_OPTS="--enable-debug --disable-flto --with-ssl=/usr/local/opt/openssl/"
+ - 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
+ name: Libevent, Clang on OS X, Amd64
+ compiler: clang
+ arch: amd64
+ env:
+ - TEST_OSX=yes
+ - TEST_LIBEVENT=yes
+ - CONFIG_OPTS="--with-ssl=/usr/local/opt/openssl/ --with-libevent=/usr/local/opt/libevent/"
+ - 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: xcode10
+ 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"
+ - os: osx
+ osx_image: xcode10
+ 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"
+ - os: osx
+ osx_image: xcode10
+ 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"
+ - os: osx
+ osx_image: xcode10
+ 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"
+ - os: osx
+ osx_image: xcode10
+ 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"
+ - os: osx
+ osx_image: xcode10
+ 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"
+ - os: osx
+ osx_image: xcode10
+ 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"
+ - os: osx
+ osx_image: xcode10
+ 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"
+ - 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: 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:
- - ./configure --enable-debug --disable-flto
- - make
- - make test
- - (cd testdata/clang-analysis.tdir; bash clang-analysis.test)
+ - |
+ if [ "$TEST_UBSAN" = "yes" ]; then
+ export CFLAGS="-DNDEBUG -g2 -O3 -fsanitize=undefined -fno-sanitize-recover"
+ ./configure
+ make -j 2
+ make test
+ elif [ "$TEST_ASAN" = "yes" ]; then
+ export CFLAGS="-DNDEBUG -g2 -O3 -fsanitize=address"
+ ./configure
+ make -j 2
+ make test
+ elif [ "$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
+ ./configure \
+ --build="$AUTOTOOLS_BUILD" --host="$AUTOTOOLS_HOST" \
+ --prefix="$IOS_PREFIX" \
+ --with-ssl="$IOS_PREFIX" --disable-gost \
+ --with-libexpat="$IOS_PREFIX";
+ make -j 2
+ make install
+ elif [ "$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
+ ./configure \
+ --build="$AUTOTOOLS_BUILD" --host="$AUTOTOOLS_HOST" \
+ --prefix="$ANDROID_PREFIX" \
+ --with-ssl="$ANDROID_PREFIX" --disable-gost \
+ --with-libexpat="$ANDROID_PREFIX";
+ make -j 2
+ make install
+ elif [ "$TEST_OSX" = "yes" ]; then
+ ./configure --enable-debug --disable-flto --with-ssl=/usr/local/opt/openssl/
+ make -j 2
+ make test
+ (cd testdata/clang-analysis.tdir; bash clang-analysis.test)
+ else
+ ./configure ${CONFIG_OPTS}
+ make -j 2
+ make test
+ (cd testdata/clang-analysis.tdir; bash clang-analysis.test)
+ fi
diff --git a/contrib/unbound/Makefile.in b/contrib/unbound/Makefile.in
index a20058cc23c6..bac212df2170 100644
--- a/contrib/unbound/Makefile.in
+++ b/contrib/unbound/Makefile.in
@@ -25,6 +25,7 @@ DNSTAP_SRC=@DNSTAP_SRC@
DNSTAP_OBJ=@DNSTAP_OBJ@
DNSCRYPT_SRC=@DNSCRYPT_SRC@
DNSCRYPT_OBJ=@DNSCRYPT_OBJ@
+WITH_DYNLIBMODULE=@WITH_DYNLIBMODULE@
WITH_PYTHONMODULE=@WITH_PYTHONMODULE@
WITH_PYUNBOUND=@WITH_PYUNBOUND@
PY_MAJOR_VERSION=@PY_MAJOR_VERSION@
@@ -77,7 +78,7 @@ LINT=splint
LINTFLAGS=+quiet -weak -warnposix -unrecog -Din_addr_t=uint32_t -Du_int=unsigned -Du_char=uint8_t -preproc -Drlimit=rlimit64 -D__gnuc_va_list=va_list -formatcode
#-Dglob64=glob -Dglobfree64=globfree
# compat with openssl linux edition.
-LINTFLAGS+="-DBN_ULONG=unsigned long" -Dkrb5_int32=int "-Dkrb5_ui_4=unsigned int" -DPQ_64BIT=uint64_t -DRC4_INT=unsigned -fixedformalarray -D"ENGINE=unsigned" -D"RSA=unsigned" -D"DSA=unsigned" -D"EVP_PKEY=unsigned" -D"EVP_MD=unsigned" -D"SSL=unsigned" -D"SSL_CTX=unsigned" -D"X509=unsigned" -D"RC4_KEY=unsigned" -D"EVP_MD_CTX=unsigned" -D"ECDSA_SIG=DSA_SIG" -Dfstrm_res=int
+LINTFLAGS+="-DBN_ULONG=unsigned long" -Dkrb5_int32=int "-Dkrb5_ui_4=unsigned int" -DPQ_64BIT=uint64_t -DRC4_INT=unsigned -fixedformalarray -D"ENGINE=unsigned" -D"RSA=unsigned" -D"DSA=unsigned" -D"EVP_PKEY=unsigned" -D"EVP_MD=unsigned" -D"SSL=unsigned" -D"SSL_CTX=unsigned" -D"X509=unsigned" -D"RC4_KEY=unsigned" -D"EVP_MD_CTX=unsigned" -D"ECDSA_SIG=DSA_SIG"
# compat with NetBSD
LINTFLAGS+=@NETBSD_LINTFLAGS@
# compat with OpenBSD
@@ -87,6 +88,12 @@ LINTFLAGS+="-D__uint16_t=uint16_t" "-DEVP_PKEY_ASN1_METHOD=int" "-D_RuneLocale=i
INSTALL=$(SHELL) $(srcdir)/install-sh
+DYNLIBMOD_SRC=dynlibmod/dynlibmod.c
+DYNLIBMOD_OBJ=@DYNLIBMOD_OBJ@
+DYNLIBMOD_HEADER=@DYNLIBMOD_HEADER@
+DYNLIBMOD_EXTRALIBS=@DYNLIBMOD_EXTRALIBS@
+
+
#pythonmod.c is not here, it is mentioned by itself in its own rules,
#makedepend fails on missing interface.h otherwise.
PYTHONMOD_SRC=pythonmod/pythonmod_utils.c
@@ -140,7 +147,7 @@ autotrust.lo val_anchor.lo rpz.lo \
validator.lo val_kcache.lo val_kentry.lo val_neg.lo val_nsec3.lo val_nsec.lo \
val_secalgo.lo val_sigcrypt.lo val_utils.lo dns64.lo cachedb.lo redis.lo authzone.lo \
$(SUBNET_OBJ) $(PYTHONMOD_OBJ) $(CHECKLOCK_OBJ) $(DNSTAP_OBJ) $(DNSCRYPT_OBJ) \
-$(IPSECMOD_OBJ) $(IPSET_OBJ) respip.lo
+$(IPSECMOD_OBJ) $(IPSET_OBJ) $(DYNLIBMOD_OBJ) respip.lo
COMMON_OBJ_WITHOUT_UB_EVENT=$(COMMON_OBJ_WITHOUT_NETCALL) netevent.lo listen_dnsport.lo \
outside_network.lo
COMMON_OBJ=$(COMMON_OBJ_WITHOUT_UB_EVENT) ub_event.lo
@@ -219,7 +226,7 @@ MEMSTATS_OBJ_LINK=$(MEMSTATS_OBJ) worker_cb.lo $(COMMON_OBJ) $(COMPAT_OBJ) \
$(SLDNS_OBJ)
ASYNCLOOK_SRC=testcode/asynclook.c
ASYNCLOOK_OBJ=asynclook.lo
-ASYNCLOOK_OBJ_LINK=$(ASYNCLOOK_OBJ) log.lo locks.lo $(COMPAT_OBJ) @ASYNCLOOK_ALLOCCHECK_EXTRA_OBJ@
+ASYNCLOOK_OBJ_LINK=$(ASYNCLOOK_OBJ) log.lo locks.lo $(CHECKLOCK_OBJ) $(COMPAT_OBJ) @ASYNCLOOK_ALLOCCHECK_EXTRA_OBJ@
STREAMTCP_SRC=testcode/streamtcp.c
STREAMTCP_OBJ=streamtcp.lo
STREAMTCP_OBJ_LINK=$(STREAMTCP_OBJ) worker_cb.lo $(COMMON_OBJ) $(COMPAT_OBJ) \
@@ -233,6 +240,10 @@ DELAYER_OBJ_LINK=$(DELAYER_OBJ) worker_cb.lo $(COMMON_OBJ) $(COMPAT_OBJ) \
$(SLDNS_OBJ)
IPSET_SRC=@IPSET_SRC@
IPSET_OBJ=@IPSET_OBJ@
+DNSTAP_SOCKET_SRC=dnstap/unbound-dnstap-socket.c
+DNSTAP_SOCKET_OBJ=unbound-dnstap-socket.lo
+DNSTAP_SOCKET_OBJ_LINK=$(DNSTAP_SOCKET_OBJ) $(COMMON_OBJ) \
+$(COMPAT_OBJ) $(SLDNS_OBJ)
LIBUNBOUND_SRC=libunbound/context.c libunbound/libunbound.c \
libunbound/libworker.c
LIBUNBOUND_OBJ=context.lo libunbound.lo libworker.lo ub_event_pluggable.lo
@@ -259,7 +270,7 @@ ALL_SRC=$(COMMON_SRC) $(UNITTEST_SRC) $(DAEMON_SRC) \
$(TESTBOUND_SRC) $(LOCKVERIFY_SRC) $(PKTVIEW_SRC) \
$(MEMSTATS_SRC) $(CHECKCONF_SRC) $(LIBUNBOUND_SRC) $(HOST_SRC) \
$(ASYNCLOOK_SRC) $(STREAMTCP_SRC) $(PERF_SRC) $(DELAYER_SRC) \
- $(CONTROL_SRC) $(UBANCHOR_SRC) $(PETAL_SRC) \
+ $(CONTROL_SRC) $(UBANCHOR_SRC) $(PETAL_SRC) $(DNSTAP_SOCKET_SRC)\
$(PYTHONMOD_SRC) $(PYUNBOUND_SRC) $(WIN_DAEMON_THE_SRC) \
$(SVCINST_SRC) $(SVCUNINST_SRC) $(ANCHORUPD_SRC) $(SLDNS_SRC)
@@ -267,7 +278,7 @@ ALL_OBJ=$(COMMON_OBJ) $(UNITTEST_OBJ) $(DAEMON_OBJ) \
$(TESTBOUND_OBJ) $(LOCKVERIFY_OBJ) $(PKTVIEW_OBJ) \
$(MEMSTATS_OBJ) $(CHECKCONF_OBJ) $(LIBUNBOUND_OBJ) $(HOST_OBJ) \
$(ASYNCLOOK_OBJ) $(STREAMTCP_OBJ) $(PERF_OBJ) $(DELAYER_OBJ) \
- $(CONTROL_OBJ) $(UBANCHOR_OBJ) $(PETAL_OBJ) \
+ $(CONTROL_OBJ) $(UBANCHOR_OBJ) $(PETAL_OBJ) $(DNSTAP_SOCKET_OBJ)\
$(COMPAT_OBJ) $(PYUNBOUND_OBJ) \
$(SVCINST_OBJ) $(SVCUNINST_OBJ) $(ANCHORUPD_OBJ) $(SLDNS_OBJ)
@@ -306,6 +317,7 @@ rsrc_unbound_checkconf.o: $(srcdir)/winrc/rsrc_unbound_checkconf.rc config.h
TEST_BIN=asynclook$(EXEEXT) delayer$(EXEEXT) \
lock-verify$(EXEEXT) memstats$(EXEEXT) perf$(EXEEXT) \
petal$(EXEEXT) pktview$(EXEEXT) streamtcp$(EXEEXT) \
+ unbound-dnstap-socket$(EXEEXT) \
testbound$(EXEEXT) unittest$(EXEEXT)
tests: all $(TEST_BIN)
@@ -315,7 +327,7 @@ longcheck: longtest
test: unittest$(EXEEXT) testbound$(EXEEXT)
./unittest$(EXEEXT)
./testbound$(EXEEXT) -s
- for x in $(srcdir)/testdata/*.rpl; do echo -n "$$x "; if ./testbound$(EXEEXT) -p $$x >/dev/null 2>&1; then echo OK; else echo failed; exit 1; fi done
+ for x in $(srcdir)/testdata/*.rpl; do printf "%s" "$$x "; if ./testbound$(EXEEXT) -p $$x >/dev/null 2>&1; then echo OK; else echo failed; exit 1; fi done
@echo test OK
longtest: tests
@@ -328,13 +340,13 @@ libunbound.la: $(LIBUNBOUND_OBJ_LINK)
$(LINK_LIB) $(UBSYMS) -o $@ $(LIBUNBOUND_OBJ_LINK) -rpath $(libdir) $(SSLLIB) $(LIBS)
unbound$(EXEEXT): $(DAEMON_OBJ_LINK) libunbound.la
- $(LINK) -o $@ $(DAEMON_OBJ_LINK) $(EXTRALINK) $(SSLLIB) $(LIBS)
+ $(LINK) -o $@ $(DAEMON_OBJ_LINK) $(EXTRALINK) $(SSLLIB) $(LIBS) $(DYNLIBMOD_EXTRALIBS)
unbound-checkconf$(EXEEXT): $(CHECKCONF_OBJ_LINK) libunbound.la
- $(LINK) -o $@ $(CHECKCONF_OBJ_LINK) $(EXTRALINK) $(SSLLIB) $(LIBS)
+ $(LINK) -o $@ $(CHECKCONF_OBJ_LINK) $(EXTRALINK) $(SSLLIB) $(LIBS) $(DYNLIBMOD_EXTRALIBS)
unbound-control$(EXEEXT): $(CONTROL_OBJ_LINK) libunbound.la
- $(LINK) -o $@ $(CONTROL_OBJ_LINK) $(EXTRALINK) $(SSLLIB) $(LIBS)
+ $(LINK) -o $@ $(CONTROL_OBJ_LINK) $(EXTRALINK) $(SSLLIB) $(LIBS) $(DYNLIBMOD_EXTRALIBS)
unbound-host$(EXEEXT): $(HOST_OBJ_LINK) libunbound.la
$(LINK) -o $@ $(HOST_OBJ_LINK) -L. -L.libs -lunbound $(SSLLIB) $(LIBS)
@@ -352,34 +364,34 @@ anchor-update$(EXEEXT): $(ANCHORUPD_OBJ_LINK) libunbound.la
$(LINK) -o $@ $(ANCHORUPD_OBJ_LINK) -L. -L.libs -lunbound $(LIBS)
unittest$(EXEEXT): $(UNITTEST_OBJ_LINK)
- $(LINK) -o $@ $(UNITTEST_OBJ_LINK) $(SSLLIB) $(LIBS)
+ $(LINK) -o $@ $(UNITTEST_OBJ_LINK) $(SSLLIB) $(LIBS) $(DYNLIBMOD_EXTRALIBS)
testbound$(EXEEXT): $(TESTBOUND_OBJ_LINK)
- $(LINK) -o $@ $(TESTBOUND_OBJ_LINK) $(SSLLIB) $(LIBS)
+ $(LINK) -o $@ $(TESTBOUND_OBJ_LINK) $(SSLLIB) $(LIBS) $(DYNLIBMOD_EXTRALIBS)
lock-verify$(EXEEXT): $(LOCKVERIFY_OBJ_LINK)
- $(LINK) -o $@ $(LOCKVERIFY_OBJ_LINK) $(SSLLIB) $(LIBS)
+ $(LINK) -o $@ $(LOCKVERIFY_OBJ_LINK) $(SSLLIB) $(LIBS) $(DYNLIBMOD_EXTRALIBS)
petal$(EXEEXT): $(PETAL_OBJ_LINK)
$(LINK) -o $@ $(PETAL_OBJ_LINK) $(SSLLIB) $(LIBS)
pktview$(EXEEXT): $(PKTVIEW_OBJ_LINK)
- $(LINK) -o $@ $(PKTVIEW_OBJ_LINK) $(SSLLIB) $(LIBS)
+ $(LINK) -o $@ $(PKTVIEW_OBJ_LINK) $(SSLLIB) $(LIBS) $(DYNLIBMOD_EXTRALIBS)
memstats$(EXEEXT): $(MEMSTATS_OBJ_LINK)
- $(LINK) -o $@ $(MEMSTATS_OBJ_LINK) $(SSLLIB) $(LIBS)
+ $(LINK) -o $@ $(MEMSTATS_OBJ_LINK) $(SSLLIB) $(LIBS) $(DYNLIBMOD_EXTRALIBS)
asynclook$(EXEEXT): $(ASYNCLOOK_OBJ_LINK) libunbound.la
$(LINK) -o $@ $(ASYNCLOOK_OBJ_LINK) -L. -L.libs -lunbound $(SSLLIB) $(LIBS)
streamtcp$(EXEEXT): $(STREAMTCP_OBJ_LINK)
- $(LINK) -o $@ $(STREAMTCP_OBJ_LINK) $(SSLLIB) $(LIBS)
+ $(LINK) -o $@ $(STREAMTCP_OBJ_LINK) $(SSLLIB) $(LIBS) $(DYNLIBMOD_EXTRALIBS)
perf$(EXEEXT): $(PERF_OBJ_LINK)
- $(LINK) -o $@ $(PERF_OBJ_LINK) $(SSLLIB) $(LIBS)
+ $(LINK) -o $@ $(PERF_OBJ_LINK) $(SSLLIB) $(LIBS) $(DYNLIBMOD_EXTRALIBS)
delayer$(EXEEXT): $(DELAYER_OBJ_LINK)
- $(LINK) -o $@ $(DELAYER_OBJ_LINK) $(SSLLIB) $(LIBS)
+ $(LINK) -o $@ $(DELAYER_OBJ_LINK) $(SSLLIB) $(LIBS) $(DYNLIBMOD_EXTRALIBS)
signit$(EXEEXT): testcode/signit.c
$(CC) $(CPPFLAGS) $(CFLAGS) @PTHREAD_CFLAGS_ONLY@ -o $@ testcode/signit.c $(LDFLAGS) -lldns $(SSLLIB) $(LIBS)
@@ -401,7 +413,13 @@ dnstap/dnstap.pb-c.c dnstap/dnstap.pb-c.h: $(srcdir)/dnstap/dnstap.proto
@-if test ! -d dnstap; then $(INSTALL) -d dnstap; fi
$(PROTOC_C) --c_out=. --proto_path=$(srcdir) $(srcdir)/dnstap/dnstap.proto
+unbound-dnstap-socket$(EXEEXT): $(DNSTAP_SOCKET_OBJ_LINK)
+ $(LINK) -o $@ $(DNSTAP_SOCKET_OBJ_LINK) $(SSLLIB) $(LIBS) $(DYNLIBMOD_EXTRALIBS)
+
dnstap.pb-c.lo dnstap.pb-c.o: dnstap/dnstap.pb-c.c dnstap/dnstap.pb-c.h
+dtstream.lo dtstream.o: $(srcdir)/dnstap/dtstream.c config.h $(srcdir)/dnstap/dtstream.h
+dnstap_fstrm.lo dnstap_fstrm.o: $(srcdir)/dnstap/dnstap_fstrm.c config.h $(srcdir)/dnstap/dnstap_fstrm.h
+unbound-dnstap-socket.lo unbound-dnstap-socket.o: $(srcdir)/dnstap/unbound-dnstap-socket.c config.h $(srcdir)/dnstap/dtstream.h
# dnscrypt
dnscrypt.lo dnscrypt.o: $(srcdir)/dnscrypt/dnscrypt.c config.h \
@@ -455,6 +473,7 @@ clean:
rm -f unbound$(EXEEXT) unbound-checkconf$(EXEEXT) unbound-host$(EXEEXT) unbound-control$(EXEEXT) unbound-anchor$(EXEEXT) unbound-control-setup libunbound.la unbound.h
rm -f $(ALL_SRC:.c=.lint)
rm -f _unbound.la libunbound/python/libunbound_wrap.c libunbound/python/unbound.py pythonmod/interface.h pythonmod/unboundmodule.py
+ rm -f libunbound.a
rm -rf autom4te.cache .libs build doc/html doc/xml
distclean: clean
@@ -629,6 +648,7 @@ depend:
-e 's?$$(srcdir)/pythonmod/pythonmod.h?$$(PYTHONMOD_HEADER)?g' \
-e 's?$$(srcdir)/edns-subnet/subnetmod.h $$(srcdir)/edns-subnet/subnet-whitelist.h $$(srcdir)/edns-subnet/edns-subnet.h $$(srcdir)/edns-subnet/addrtree.h?$$(SUBNET_HEADER)?g' \
-e 's?$$(srcdir)/ipsecmod/ipsecmod.h $$(srcdir)/ipsecmod/ipsecmod-whitelist.h?$$(IPSECMOD_HEADER)?g' \
+ -e 's?$$(srcdir)/dynlibmod/dynlibmod.h?$$(DYNLIBMOD_HEADER)?g' \
-e 's!\(.*\)\.o[ :]*!\1.lo \1.o: !g' \
> $(DEPEND_TMP)
cp $(DEPEND_TARGET) $(DEPEND_TMP2)
@@ -796,12 +816,13 @@ modstack.lo modstack.o: $(srcdir)/services/modstack.c config.h $(srcdir)/service
$(srcdir)/util/module.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \
$(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgparse.h \
$(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/fptr_wlist.h $(srcdir)/util/netevent.h \
- $(srcdir)/dnscrypt/dnscrypt.h $(srcdir)/util/tube.h \
- $(srcdir)/services/mesh.h $(srcdir)/util/rbtree.h $(srcdir)/services/rpz.h $(srcdir)/services/localzone.h \
- $(srcdir)/util/storage/dnstree.h $(srcdir)/services/view.h $(srcdir)/sldns/sbuffer.h \
- $(srcdir)/util/config_file.h $(srcdir)/services/authzone.h $(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h \
- $(srcdir)/libunbound/unbound.h $(srcdir)/respip/respip.h $(srcdir)/dns64/dns64.h $(srcdir)/iterator/iterator.h \
- $(srcdir)/services/outbound_list.h $(srcdir)/validator/validator.h $(srcdir)/validator/val_utils.h
+ $(srcdir)/dnscrypt/dnscrypt.h $(srcdir)/dnscrypt/cert.h \
+ $(srcdir)/util/tube.h $(srcdir)/services/mesh.h $(srcdir)/util/rbtree.h $(srcdir)/dns64/dns64.h \
+ $(srcdir)/iterator/iterator.h $(srcdir)/services/outbound_list.h $(srcdir)/validator/validator.h \
+ $(srcdir)/validator/val_utils.h $(srcdir)/respip/respip.h $(srcdir)/services/localzone.h \
+ $(srcdir)/util/storage/dnstree.h $(srcdir)/services/view.h $(PYTHONMOD_HEADER) $(srcdir)/ipsecmod/ipsecmod.h \
+ $(srcdir)/util/storage/slabhash.h $(srcdir)/edns-subnet/addrtree.h $(srcdir)/edns-subnet/edns-subnet.h \
+ $(srcdir)/ipset/ipset.h $(srcdir)/dynlibmod/dynlibmod.h
view.lo view.o: $(srcdir)/services/view.c config.h $(srcdir)/services/view.h $(srcdir)/util/rbtree.h \
$(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/services/localzone.h $(srcdir)/util/storage/dnstree.h \
$(srcdir)/util/module.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/data/msgreply.h \
@@ -886,21 +907,23 @@ authzone.lo authzone.o: $(srcdir)/services/authzone.c config.h $(srcdir)/service
$(srcdir)/validator/val_secalgo.h
fptr_wlist.lo fptr_wlist.o: $(srcdir)/util/fptr_wlist.c config.h $(srcdir)/util/fptr_wlist.h \
$(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
- $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/module.h \
- $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgparse.h \
- $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/tube.h $(srcdir)/services/mesh.h $(srcdir)/util/rbtree.h \
- $(srcdir)/services/modstack.h $(srcdir)/services/rpz.h $(srcdir)/services/localzone.h \
- $(srcdir)/util/storage/dnstree.h $(srcdir)/services/view.h $(srcdir)/sldns/sbuffer.h \
- $(srcdir)/util/config_file.h $(srcdir)/services/authzone.h $(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h \
- $(srcdir)/libunbound/unbound.h $(srcdir)/respip/respip.h $(srcdir)/util/mini_event.h $(srcdir)/util/rbtree.h \
- $(srcdir)/services/outside_network.h $(srcdir)/services/cache/infra.h \
- $(srcdir)/util/rtt.h $(srcdir)/services/cache/rrset.h $(srcdir)/util/storage/slabhash.h $(srcdir)/dns64/dns64.h \
- $(srcdir)/iterator/iterator.h $(srcdir)/services/outbound_list.h $(srcdir)/iterator/iter_fwd.h \
- $(srcdir)/validator/validator.h $(srcdir)/validator/val_utils.h $(srcdir)/validator/val_anchor.h \
- $(srcdir)/validator/val_nsec3.h $(srcdir)/validator/val_sigcrypt.h $(srcdir)/validator/val_kentry.h \
- $(srcdir)/validator/val_neg.h $(srcdir)/validator/autotrust.h $(srcdir)/libunbound/libworker.h \
- $(srcdir)/libunbound/context.h $(srcdir)/util/alloc.h $(srcdir)/libunbound/unbound-event.h \
- $(srcdir)/libunbound/worker.h
+ $(srcdir)/dnscrypt/cert.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/storage/lruhash.h \
+ $(srcdir)/util/module.h $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h \
+ $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/tube.h \
+ $(srcdir)/services/mesh.h $(srcdir)/util/rbtree.h $(srcdir)/services/modstack.h $(srcdir)/util/mini_event.h \
+ $(srcdir)/services/outside_network.h $(srcdir)/services/localzone.h \
+ $(srcdir)/util/storage/dnstree.h $(srcdir)/services/view.h $(srcdir)/services/authzone.h \
+ $(srcdir)/services/cache/infra.h $(srcdir)/util/rtt.h $(srcdir)/services/cache/rrset.h \
+ $(srcdir)/util/storage/slabhash.h $(srcdir)/dns64/dns64.h $(srcdir)/iterator/iterator.h \
+ $(srcdir)/services/outbound_list.h $(srcdir)/iterator/iter_fwd.h $(srcdir)/validator/validator.h \
+ $(srcdir)/validator/val_utils.h $(srcdir)/validator/val_anchor.h $(srcdir)/validator/val_nsec3.h \
+ $(srcdir)/validator/val_sigcrypt.h $(srcdir)/validator/val_kentry.h $(srcdir)/validator/val_neg.h \
+ $(srcdir)/validator/autotrust.h $(srcdir)/libunbound/libworker.h $(srcdir)/libunbound/context.h \
+ $(srcdir)/util/alloc.h $(srcdir)/libunbound/unbound.h $(srcdir)/libunbound/unbound-event.h \
+ $(srcdir)/libunbound/worker.h $(srcdir)/sldns/sbuffer.h $(srcdir)/util/config_file.h $(srcdir)/respip/respip.h \
+ $(PYTHONMOD_HEADER) $(srcdir)/ipsecmod/ipsecmod.h $(srcdir)/edns-subnet/subnetmod.h $(srcdir)/util/net_help.h \
+ $(srcdir)/edns-subnet/addrtree.h $(srcdir)/edns-subnet/edns-subnet.h $(srcdir)/ipset/ipset.h \
+ $(srcdir)/dynlibmod/dynlibmod.h
locks.lo locks.o: $(srcdir)/util/locks.c config.h $(srcdir)/util/locks.h $(srcdir)/util/log.h
log.lo log.o: $(srcdir)/util/log.c config.h $(srcdir)/util/log.h $(srcdir)/util/locks.h $(srcdir)/sldns/sbuffer.h
mini_event.lo mini_event.o: $(srcdir)/util/mini_event.c config.h $(srcdir)/util/mini_event.h $(srcdir)/util/rbtree.h \
@@ -1108,7 +1131,32 @@ respip.lo respip.o: $(srcdir)/respip/respip.c config.h $(srcdir)/services/localz
$(srcdir)/util/regional.h
checklocks.lo checklocks.o: $(srcdir)/testcode/checklocks.c config.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \
$(srcdir)/testcode/checklocks.h
+dnstap.lo dnstap.o: $(srcdir)/dnstap/dnstap.c config.h $(srcdir)/sldns/sbuffer.h \
+ $(srcdir)/util/config_file.h $(srcdir)/util/net_help.h $(srcdir)/util/log.h $(srcdir)/util/netevent.h \
+ $(srcdir)/dnscrypt/dnscrypt.h $(srcdir)/dnscrypt/cert.h \
+ $(srcdir)/util/locks.h $(srcdir)/dnstap/dnstap.h \
+ dnstap/dnstap.pb-c.h
+dnstap.pb-c.lo dnstap.pb-c.o: dnstap/dnstap.pb-c.c dnstap/dnstap.pb-c.h \
+
+dynlibmod.lo dynlibmod.o: $(srcdir)/dynlibmod/dynlibmod.c config.h $(srcdir)/dynlibmod/dynlibmod.h \
+ $(srcdir)/util/module.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \
+ $(srcdir)/util/data/msgreply.h $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgparse.h \
+ $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/rbtree.h\
+ $(srcdir)/util/storage/dnstree.h $(srcdir)/util/fptr_wlist.h $(srcdir)/util/netevent.h \
+ $(srcdir)/dnscrypt/dnscrypt.h $(srcdir)/util/tube.h \
+ $(srcdir)/services/mesh.h $(srcdir)/services/modstack.h $(srcdir)/util/regional.h $(srcdir)/util/net_help.h \
+ $(srcdir)/util/config_file.h $(srcdir)/services/cache/dns.h $(srcdir)/sldns/wire2str.h
+dnscrypt.lo dnscrypt.o: $(srcdir)/dnscrypt/dnscrypt.c config.h $(srcdir)/sldns/sbuffer.h \
+ $(srcdir)/util/config_file.h $(srcdir)/util/net_help.h $(srcdir)/util/log.h $(srcdir)/util/netevent.h \
+ $(srcdir)/dnscrypt/dnscrypt.h $(srcdir)/dnscrypt/cert.h \
+ $(srcdir)/util/locks.h $(srcdir)/util/storage/slabhash.h $(srcdir)/util/storage/lruhash.h \
+ $(srcdir)/util/storage/lookup3.h
ipsecmod.lo ipsecmod.o: $(srcdir)/ipsecmod/ipsecmod.c config.h
+ipset.lo ipset.o: $(srcdir)/ipset/ipset.c config.h $(srcdir)/ipset/ipset.h $(srcdir)/util/module.h \
+ $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/data/msgreply.h \
+ $(srcdir)/util/data/packed_rrset.h $(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h \
+ $(srcdir)/sldns/rrdef.h $(srcdir)/util/regional.h $(srcdir)/util/config_file.h $(srcdir)/services/cache/dns.h \
+ $(srcdir)/sldns/sbuffer.h $(srcdir)/sldns/wire2str.h $(srcdir)/sldns/parseutil.h
ipsecmod-whitelist.lo ipsecmod-whitelist.o: $(srcdir)/ipsecmod/ipsecmod-whitelist.c config.h
unitanchor.lo unitanchor.o: $(srcdir)/testcode/unitanchor.c config.h $(srcdir)/util/log.h $(srcdir)/util/data/dname.h \
$(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/testcode/unitmain.h \
diff --git a/contrib/unbound/README-Travis.md b/contrib/unbound/README-Travis.md
new file mode 100644
index 000000000000..3ce22cc20f59
--- /dev/null
+++ b/contrib/unbound/README-Travis.md
@@ -0,0 +1,278 @@
+# Travis Testing
+
+Unbound 1.10 and above leverage Travis CI to increase coverage of compilers and platforms. Compilers include Clang and GCC; while platforms include Android, iOS, Linux, and OS X on AMD64, Aarch64, PowerPC and s390x hardware.
+
+Android is tested on armv7a, aarch64, x86 and x86_64. The Android recipes build and install OpenSSL and Expat, and then builds Unbound. The testing is tailored for Android NDK-r19 and above, and includes NDK-r20 and NDK-r21. Mips and Mips64 are not tested because they are no longer supported under current NDKs.
+
+iOS is tested for iPhoneOS, WatchOS, AppleTVOS, iPhoneSimulator, AppleTVSimulator and WatchSimulator. The testing uses Xcode 10 on OS X 10.13.
+
+The Unbound Travis configuration file `.travis.yml` does not use top-level keys like `os:` and `compiler:` so there is no matrix expansion. Instead Unbound specifies the exact job to run under the `jobs:` and `include:` keys.
+
+## Typical recipe
+
+A typical recipe tests Clang and GCC on various hardware. The hardware includes AMD64, Aarch64, PowerPC and s390x. PowerPC is a little-endian platform, and s390x is a big-endian platform. There are pairs of recipes that are similar to the following.
+
+```
+- os: linux
+ name: GCC on Linux, Aarch64
+ compiler: gcc
+ arch: arm64
+ dist: bionic
+- os: linux
+ name: Clang on Linux, Aarch64
+ compiler: clang
+ arch: arm64
+ dist: bionic
+```
+
+OS X provides a single recipe to test Clang. GCC is not tested because GCC is an alias for Clang.
+
+## Sanitizer builds
+
+Two sanitizer builds are tested using Clang and GCC, for a total of four builds. The first sanitizer is Undefined Behavior sanitizer (UBsan), and the second is Address sanitizer (Asan). The sanitizers are only run on AMD64 hardware. Note the environment includes `TEST_UBSAN=yes` or `TEST_ASAN=yes` for the sanitizer builds.
+
+The recipes are similar to the following.
+
+```
+- 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
+```
+
+When the Travis script encounters a sanitizer it uses different `CFLAGS` and configuration string.
+
+```
+if [ "$TEST_UBSAN" = "yes" ]; then
+ export CFLAGS="-DNDEBUG -g2 -O3 -fsanitize=undefined -fno-sanitize-recover"
+ ./configure
+ make -j 2
+ make test
+elif [ "$TEST_ASAN" = "yes" ]; then
+ export CFLAGS="-DNDEBUG -g2 -O3 -fsanitize=address"
+ ./configure
+ make -j 2
+ make test
+...
+```
+
+## Android builds
+
+Travis tests Android builds for the armv7a, aarch64, x86 and x86_64 architectures. The builds are trickier than other builds for several reasons. The testing requires installation of the Android NDK and SDK, it requires a cross-compile, and requires OpenSSL and Expat prerequisites. The Android cross-compiles also require care to set the Autotools triplet, the OpenSSL triplet, the toolchain path, the tool variables, and the sysroot. The discussion below detail the steps of the Android recipes.
+
+### Android job
+
+The first step sets environmental variables for the cross-compile using the Travis job. A typical job with variables is shown below.
+
+```
+- 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"
+```
+
+### ANDROID_NDK_ROOT
+
+The second step for Android is to set the environmental variables `ANDROID_NDK_ROOT` and `ANDROID_SDK_ROOT`. This is an important step because the NDK and SDK use the variables internally to locate their own tools. Also see [Recommended NDK Directory?](https://groups.google.com/forum/#!topic/android-ndk/qZjhOaynHXc) on the android-ndk mailing list. (Many folks miss this step, or use incorrect variables like `ANDROID_NDK_HOME` or `ANDROID_SDK_HOME`).
+
+If you are working from a developer machine you probably already have the necessary tools installed. You should ensure `ANDROID_NDK_ROOT` and `ANDROID_SDK_ROOT` are set properly.
+
+### Tool installation
+
+The second step installs tools needed for OpenSSL, Expat and Unbound. This step is handled in by the script `contrib/android/install_tools.sh`. The tools include curl, tar, zip, unzip and java.
+
+```
+before_script:
+ - |
+ if [ "$TEST_ANDROID" = "yes" ]; then
+ ./contrib/android/install_tools.sh
+ elif [ "$TEST_IOS" = "yes" ]; then
+ ./contrib/ios/install_tools.sh
+ fi
+```
+
+### NDK installation
+
+The third step installs the NDK and SDK. This step is handled in by the script `contrib/android/install_ndk.sh`. The script uses `ANDROID_NDK_ROOT` and `ANDROID_SDK_ROOT` to place the NDK and SDK in the `$HOME` directory.
+
+If you are working from a developer machine you probably already have a NDK and SDK installed.
+
+### Android environment
+
+The fourth step sets the Android cross-compile environment using the script `contrib/android/setenv_android.sh`. The script is `sourced` so the variables in the script are available to the calling shell. The script sets variables like `CC`, `CXX`, `AS` and `AR`; sets `CFLAGS` and `CXXFLAGS`; sets a `sysroot` so Android headers and libraries are found; and adds the path to the toolchain to `PATH`.
+
+`contrib/android/setenv_android.sh` knows which toolchain and architecture to select by inspecting environmental variables set by Travis for the job. In particular, the variables `ANDROID_CPU` and `ANDROID_API` tell `contrib/android/setenv_android.sh` which tools and libraries to select.
+
+The `contrib/android/setenv_android.sh` script specifies the tools in a `case` statement like the following. There is a case for each of the architectures armv7a, aarch64, x86 and x86_64.
+
+```
+armv8a|aarch64|arm64|arm64-v8a)
+ CC="aarch64-linux-android$ANDROID_API-clang"
+ CXX="aarch64-linux-android$ANDROID_API-clang++"
+ LD="aarch64-linux-android-ld"
+ AS="aarch64-linux-android-as"
+ AR="aarch64-linux-android-ar"
+ RANLIB="aarch64-linux-android-ranlib"
+ STRIP="aarch64-linux-android-strip"
+
+ CFLAGS="-funwind-tables -fexceptions"
+ CXXFLAGS="-funwind-tables -fexceptions -frtti"
+```
+
+### OpenSSL and Expat
+
+The fifth step builds OpenSSL and Expat. OpenSSL and Expat are built for Android using the scripts `contrib/android/install_openssl.sh` and `contrib/android/install_expat.sh`. The scripts download, configure and install the latest release version of the libraries. The libraries are configured with `--prefix="$ANDROID_PREFIX"` so the headers are placed in `$ANDROID_PREFIX/include` directory, and the libraries are placed in the `$ANDROID_PREFIX/lib` directory.
+
+`ANDROID_PREFIX` is the value `$HOME/android$ANDROID_API-$ANDROID_CPU`. The libraries will be installed in `$HOME/android23-armv7a`, `$HOME/android23-aarch64`, etc. For Autotools projects, the appropriate `PKG_CONFIG_PATH` is exported. `PKG_CONFIG_PATH` 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/android23-armv7a/lib/pkgconfig` and `$HOME/android23-aarch64/lib/pkgconfig`.
+
+OpenSSL also uses a custom configuration file called `15-android.conf`. It is a copy of the OpenSSL's project file and located at `contrib/android/15-android.conf`. The Unbound version is copied to the OpenSSL source files after unpacking the OpenSSL distribution. The Unbound version has legacy NDK support removed and some other fixes, like `ANDROID_NDK_ROOT` awareness. The changes mean Unbound's `15-android.conf` will only work with Unbound, with NDK-r19 and above, and a properly set environment.
+
+OpenSSL is configured with `no-engine`. If you want to include OpenSSL engines then edit `contrib/android/install_openssl.sh` and remove the config option.
+
+### Android build
+
+Finally, once OpenSSL and Expat are built, then the Travis script configures and builds Unbound. The recipe looks as follows.
+
+```
+elif [ "$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
+ ./configure \
+ --build="$AUTOTOOLS_BUILD" \
+ --host="$AUTOTOOLS_HOST" \
+ --prefix="$ANDROID_PREFIX" \
+ --with-ssl="$ANDROID_PREFIX" \
+ --with-libexpat="$ANDROID_PREFIX" \
+ --disable-gost;
+ make -j 2
+ make install
+```
+
+Travis only smoke tests an Android build using a compile, link and install. The self tests are not run. TODO: figure out how to fire up an emulator, push the tests to the device and run them.
+
+### Android flags
+
+`contrib/android/setenv_android.sh` uses specific flags for `CFLAGS` and `CXXFLAGS`. They are taken from `ndk-build`, so we consider them the official flag set. It is important to use the same flags across projects to avoid subtle problems due to mixing and matching different flags.
+
+`CXXFLAGS` includes `-fexceptions` and `-frtti` because exceptions and runtime type info are disabled by default. `CFLAGS` include `-funwind-tables` and `-fexceptions` to ensure C++ exceptions pass through C code, if needed. Also see `docs/CPLUSPLUS-SUPPORT.html` in the NDK docs.
+
+To inspect the flags used by `ndk-build` for a platform clone ASOP's [ndk-samples](https://github.com/android/ndk-samples/tree/master/hello-jni) and build the `hello-jni` project. Use the `V=1` flag to see the full compiler output from `ndk-build`.
+
+## iOS builds
+
+Travis tests iOS builds for the armv7a, armv7s and aarch64 architectures for iPhoneOS, AppleTVOS and WatchOS. iPhoneOS is tested using both 32-bit builds (iPhones) and 64-bit builds (iPads). Travis also tests compiles against the simulators. The builds are trickier than other builds for several reasons. The testing requires a cross-compile, and requires OpenSSL and Expat prerequisites. The iOS cross-compiles also require care to set the Autotools triplet, the OpenSSL triplet, the toolchain path, the tool variables, and the sysroot. The discussion below detail the steps of the iOS recipes.
+
+### iOS job
+
+The first step sets environmental variables for the cross-compile using the Travis job. A typical job with variables is shown below.
+
+```
+- os: osx
+ osx_image: xcode10
+ 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"
+```
+
+### Tool installation
+
+The second step installs tools needed for OpenSSL, Expat and Unbound. This step is handled in by the script `contrib/ios/install_tools.sh`. The tools include autotools, curl and perl. The installation happens at the `before_script:` stage of Travis.
+
+```
+before_script:
+ - |
+ if [ "$TEST_ANDROID" = "yes" ]; then
+ ./contrib/android/install_tools.sh
+ elif [ "$TEST_IOS" = "yes" ]; then
+ ./contrib/ios/install_tools.sh
+ fi
+```
+
+### iOS environment
+
+The third step sets the iOS cross-compile environment using the script `contrib/ios/setenv_ios.sh`. The script is `sourced` so the variables in the script are available to the calling shell. The script sets variables like `CC`, `CXX`, `AS` and `AR`; sets `CFLAGS` and `CXXFLAGS`; sets a `sysroot` so iOS headers and libraries are found; and adds the path to the toolchain to `PATH`.
+
+`contrib/ios/setenv_ios.sh` knows which toolchain and architecture to select by inspecting environmental variables set by Travis for the job. In particular, the variables `IOS_SDK` and `IOS_CPU` tell `contrib/ios/setenv_ios.sh` which tools and libraries to select.
+
+The `contrib/ios/setenv_ios.sh` script specifies the tools to use during the cross-compile. For Apple SDKs, the tool names are the same as a desktop. There are no special prefixes for the mobile tools.
+
+```
+CPP=cpp
+CC=clang
+CXX=clang++
+LD=ld
+AS=as
+AR=ar
+RANLIB=ranlib
+STRIP=strip
+```
+
+If you are working from a developer machine you probably already have the necessary tools installed.
+
+### OpenSSL and Expat
+
+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.
+
+`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`.
+
+OpenSSL also uses a custom configuration file called `15-ios.conf`. It is a copy of the OpenSSL's project file and located at `contrib/ios/15-ios.conf`. The Unbound version is copied to the OpenSSL source files after unpacking the OpenSSL distribution. The changes mean Unbound's `15-ios.conf` will only work with Unbound and a properly set environment.
+
+OpenSSL is configured with `no-engine`. Engines require dynamic loading so engines are disabled permanently in `15-ios.conf`.
+
+### iOS build
+
+Finally, once OpenSSL and Expat are built, then the Travis script configures and builds Unbound. The full recipe looks as follows.
+
+```
+elif [ "$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
+ ./configure \
+ --build="$AUTOTOOLS_BUILD" \
+ --host="$AUTOTOOLS_HOST" \
+ --prefix="$IOS_PREFIX" \
+ --with-ssl="$IOS_PREFIX" \
+ --with-libexpat="$IOS_PREFIX" \
+ --disable-gost;
+ make -j 2
+ make install
+```
+
+Travis only smoke tests an iOS build using a compile, link and install. The self tests are not run. TODO: figure out how to fire up an simulator, push the tests to the device and run them.
+
+### iOS flags
+
+`contrib/ios/setenv_ios.sh` uses specific flags for `CFLAGS` and `CXXFLAGS`. They are taken from Xcode, so we consider them the official flag set. It is important to use the same flags across projects to avoid subtle problems due to mixing and matching different flags.
diff --git a/contrib/unbound/acx_python.m4 b/contrib/unbound/acx_python.m4
index 2940971f1a4e..a84daa035884 100644
--- a/contrib/unbound/acx_python.m4
+++ b/contrib/unbound/acx_python.m4
@@ -58,6 +58,11 @@ $ac_distutils_result])
AC_MSG_RESULT([$PYTHON_LDFLAGS])
AC_SUBST([PYTHON_LDFLAGS])
+ if test -z "$PYTHON_LIBDIR"; then
+ PYTHON_LIBDIR=`$PYTHON -c "from distutils.sysconfig import *; \
+ print(get_config_var('LIBDIR'));"`
+ fi
+
#
# Check for site packages
#
diff --git a/contrib/unbound/cachedb/cachedb.c b/contrib/unbound/cachedb/cachedb.c
index c5be516225f9..eed4d5fd9bed 100644
--- a/contrib/unbound/cachedb/cachedb.c
+++ b/contrib/unbound/cachedb/cachedb.c
@@ -160,7 +160,7 @@ testframe_lookup(struct module_env* env, struct cachedb_env* cachedb_env,
static void
testframe_store(struct module_env* env, struct cachedb_env* cachedb_env,
- char* key, uint8_t* data, size_t data_len)
+ char* key, uint8_t* data, size_t data_len, time_t ATTR_UNUSED(ttl))
{
struct testframe_moddata* d = (struct testframe_moddata*)
cachedb_env->backend_data;
@@ -606,7 +606,8 @@ cachedb_extcache_store(struct module_qstate* qstate, struct cachedb_env* ie)
/* call backend */
(*ie->backend->store)(qstate->env, ie, key,
sldns_buffer_begin(qstate->env->scratch_buffer),
- sldns_buffer_limit(qstate->env->scratch_buffer));
+ sldns_buffer_limit(qstate->env->scratch_buffer),
+ qstate->return_msg->rep->ttl);
}
/**
diff --git a/contrib/unbound/cachedb/cachedb.h b/contrib/unbound/cachedb/cachedb.h
index 27187dc56dc6..05c4368e60b4 100644
--- a/contrib/unbound/cachedb/cachedb.h
+++ b/contrib/unbound/cachedb/cachedb.h
@@ -84,7 +84,7 @@ struct cachedb_backend {
/** Store (env, cachedb_env, key, data, data_len) */
void (*store)(struct module_env*, struct cachedb_env*, char*,
- uint8_t*, size_t);
+ uint8_t*, size_t, time_t);
};
#define CACHEDB_HASHSIZE 256 /* bit hash */
diff --git a/contrib/unbound/cachedb/redis.c b/contrib/unbound/cachedb/redis.c
index 3dfbf8f7a25c..16c3741f786b 100644
--- a/contrib/unbound/cachedb/redis.c
+++ b/contrib/unbound/cachedb/redis.c
@@ -59,6 +59,9 @@ struct redis_moddata {
struct timeval timeout; /* timeout for connection setup and commands */
};
+static redisReply* redis_command(struct module_env*, struct cachedb_env*,
+ const char*, const uint8_t*, size_t);
+
static redisContext*
redis_connect(const struct redis_moddata* moddata)
{
@@ -114,6 +117,33 @@ redis_init(struct module_env* env, struct cachedb_env* cachedb_env)
for(i = 0; i < moddata->numctxs; i++)
moddata->ctxs[i] = redis_connect(moddata);
cachedb_env->backend_data = moddata;
+ if(env->cfg->redis_expire_records) {
+ redisReply* rep = NULL;
+ int redis_reply_type = 0;
+ /** check if setex command is supported */
+ rep = redis_command(env, cachedb_env,
+ "SETEX __UNBOUND_REDIS_CHECK__ 1 none", NULL, 0);
+ if(!rep) {
+ /** init failed, no response from redis server*/
+ log_err("redis_init: failed to init redis, the "
+ "redis-expire-records option requires the SETEX command "
+ "(redis >= 2.0.0)");
+ return 0;
+ }
+ redis_reply_type = rep->type;
+ freeReplyObject(rep);
+ switch(redis_reply_type) {
+ case REDIS_REPLY_STATUS:
+ break;
+ default:
+ /** init failed, setex command not supported */
+ log_err("redis_init: failed to init redis, the "
+ "redis-expire-records option requires the SETEX command "
+ "(redis >= 2.0.0)");
+ return 0;
+ }
+ }
+
return 1;
}
@@ -219,7 +249,7 @@ redis_lookup(struct module_env* env, struct cachedb_env* cachedb_env,
rep = redis_command(env, cachedb_env, cmdbuf, NULL, 0);
if(!rep)
return 0;
- switch (rep->type) {
+ switch(rep->type) {
case REDIS_REPLY_NIL:
verbose(VERB_ALGO, "redis_lookup: no data cached");
break;
@@ -249,16 +279,33 @@ redis_lookup(struct module_env* env, struct cachedb_env* cachedb_env,
static void
redis_store(struct module_env* env, struct cachedb_env* cachedb_env,
- char* key, uint8_t* data, size_t data_len)
+ char* key, uint8_t* data, size_t data_len, time_t ttl)
{
redisReply* rep;
- char cmdbuf[4+(CACHEDB_HASHSIZE/8)*2+3+1]; /* "SET " + key + " %b" */
int n;
+ int set_ttl = (env->cfg->redis_expire_records &&
+ (!env->cfg->serve_expired || env->cfg->serve_expired_ttl > 0));
+ /* Supported commands:
+ * - "SET " + key + " %b"
+ * - "SETEX " + key + " " + ttl + " %b"
+ */
+ char cmdbuf[6+(CACHEDB_HASHSIZE/8)*2+11+3+1];
+
+ if (!set_ttl) {
+ verbose(VERB_ALGO, "redis_store %s (%d bytes)", key, (int)data_len);
+ /* build command to set to a binary safe string */
+ n = snprintf(cmdbuf, sizeof(cmdbuf), "SET %s %%b", key);
+ } else {
+ /* add expired ttl time to redis ttl to avoid premature eviction of key */
+ ttl += env->cfg->serve_expired_ttl;
+ verbose(VERB_ALGO, "redis_store %s (%d bytes) with ttl %u",
+ key, (int)data_len, (uint32_t)ttl);
+ /* build command to set to a binary safe string */
+ n = snprintf(cmdbuf, sizeof(cmdbuf), "SETEX %s %u %%b", key,
+ (uint32_t)ttl);
+ }
- verbose(VERB_ALGO, "redis_store %s (%d bytes)", key, (int)data_len);
- /* build command to set to a binary safe string */
- n = snprintf(cmdbuf, sizeof(cmdbuf), "SET %s %%b", key);
if(n < 0 || n >= (int)sizeof(cmdbuf)) {
log_err("redis_store: unexpected failure to build command");
return;
diff --git a/contrib/unbound/config.guess b/contrib/unbound/config.guess
index 7ea49fadcd8b..e94095c5fbe8 100755
--- a/contrib/unbound/config.guess
+++ b/contrib/unbound/config.guess
@@ -1,8 +1,8 @@
-#!/usr/bin/sh
+#! /bin/sh
# Attempt to guess a canonical system name.
-# Copyright 1992-2016 Free Software Foundation, Inc.
+# Copyright 1992-2020 Free Software Foundation, Inc.
-timestamp='2016-10-02'
+timestamp='2020-07-12'
# 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
@@ -15,7 +15,7 @@ timestamp='2016-10-02'
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
-# along with this program; if not, see <http://www.gnu.org/licenses/>.
+# along with this program; if not, see <https://www.gnu.org/licenses/>.
#
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
@@ -27,7 +27,7 @@ timestamp='2016-10-02'
# Originally written by Per Bothner; maintained since 2000 by Ben Elliston.
#
# You can get the latest version of this script from:
-# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess
+# https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess
#
# Please send patches to <config-patches@gnu.org>.
@@ -39,7 +39,7 @@ Usage: $0 [OPTION]
Output the configuration name of the system \`$me' is run on.
-Operation modes:
+Options:
-h, --help print this help, then exit
-t, --time-stamp print date of last modification, then exit
-v, --version print version number, then exit
@@ -50,7 +50,7 @@ version="\
GNU config.guess ($timestamp)
Originally written by Per Bothner.
-Copyright 1992-2016 Free Software Foundation, Inc.
+Copyright 1992-2020 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
@@ -84,8 +84,6 @@ if test $# != 0; then
exit 1
fi
-trap 'exit 1' 1 2 15
-
# CC_FOR_BUILD -- compiler used by this script. Note that the use of a
# compiler to aid in system detection is discouraged as it requires
# temporary files to be created and, as you can see below, it is a
@@ -96,34 +94,40 @@ trap 'exit 1' 1 2 15
# Portable tmp directory creation inspired by the Autoconf team.
-set_cc_for_build='
-trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ;
-trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ;
-: ${TMPDIR=/tmp} ;
- { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } ||
- { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } ||
- { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } ||
- { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ;
-dummy=$tmp/dummy ;
-tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ;
-case $CC_FOR_BUILD,$HOST_CC,$CC in
- ,,) echo "int x;" > $dummy.c ;
- for c in cc gcc c89 c99 ; do
- if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then
- CC_FOR_BUILD="$c"; break ;
- fi ;
- done ;
- if test x"$CC_FOR_BUILD" = x ; then
- CC_FOR_BUILD=no_compiler_found ;
- fi
- ;;
- ,,*) CC_FOR_BUILD=$CC ;;
- ,*,*) CC_FOR_BUILD=$HOST_CC ;;
-esac ; set_cc_for_build= ;'
+tmp=
+# shellcheck disable=SC2172
+trap 'test -z "$tmp" || rm -fr "$tmp"' 0 1 2 13 15
+
+set_cc_for_build() {
+ # prevent multiple calls if $tmp is already set
+ test "$tmp" && return 0
+ : "${TMPDIR=/tmp}"
+ # shellcheck disable=SC2039
+ { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } ||
+ { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir "$tmp" 2>/dev/null) ; } ||
+ { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir "$tmp" 2>/dev/null) && echo "Warning: creating insecure temp directory" >&2 ; } ||
+ { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; }
+ dummy=$tmp/dummy
+ case ${CC_FOR_BUILD-},${HOST_CC-},${CC-} in
+ ,,) echo "int x;" > "$dummy.c"
+ for driver in cc gcc c89 c99 ; do
+ if ($driver -c -o "$dummy.o" "$dummy.c") >/dev/null 2>&1 ; then
+ CC_FOR_BUILD="$driver"
+ break
+ fi
+ done
+ if test x"$CC_FOR_BUILD" = x ; then
+ CC_FOR_BUILD=no_compiler_found
+ fi
+ ;;
+ ,,*) CC_FOR_BUILD=$CC ;;
+ ,*,*) CC_FOR_BUILD=$HOST_CC ;;
+ esac
+}
# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
# (ghazi@noc.rutgers.edu 1994-08-24)
-if (test -f /.attbin/uname) >/dev/null 2>&1 ; then
+if test -f /.attbin/uname ; then
PATH=$PATH:/.attbin ; export PATH
fi
@@ -132,14 +136,14 @@ UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown
UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
-case "${UNAME_SYSTEM}" in
+case "$UNAME_SYSTEM" in
Linux|GNU|GNU/*)
# If the system lacks a compiler, then just pick glibc.
# We could probably try harder.
LIBC=gnu
- eval $set_cc_for_build
- cat <<-EOF > $dummy.c
+ set_cc_for_build
+ cat <<-EOF > "$dummy.c"
#include <features.h>
#if defined(__UCLIBC__)
LIBC=uclibc
@@ -149,13 +153,20 @@ Linux|GNU|GNU/*)
LIBC=gnu
#endif
EOF
- eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC' | sed 's, ,,g'`
+ eval "`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^LIBC' | sed 's, ,,g'`"
+
+ # If ldd exists, use it to detect musl libc.
+ if command -v ldd >/dev/null && \
+ ldd --version 2>&1 | grep -q ^musl
+ then
+ LIBC=musl
+ fi
;;
esac
# Note: order is significant - the case branches are not exclusive.
-case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
+case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in
*:NetBSD:*:*)
# NetBSD (nbsd) targets should (where applicable) match one or
# more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*,
@@ -169,30 +180,30 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
# portion of the name. We always set it to "unknown".
sysctl="sysctl -n hw.machine_arch"
UNAME_MACHINE_ARCH=`(uname -p 2>/dev/null || \
- /sbin/$sysctl 2>/dev/null || \
- /usr/sbin/$sysctl 2>/dev/null || \
+ "/sbin/$sysctl" 2>/dev/null || \
+ "/usr/sbin/$sysctl" 2>/dev/null || \
echo unknown)`
- case "${UNAME_MACHINE_ARCH}" in
+ case "$UNAME_MACHINE_ARCH" in
armeb) machine=armeb-unknown ;;
arm*) machine=arm-unknown ;;
sh3el) machine=shl-unknown ;;
sh3eb) machine=sh-unknown ;;
sh5el) machine=sh5le-unknown ;;
earmv*)
- arch=`echo ${UNAME_MACHINE_ARCH} | sed -e 's,^e\(armv[0-9]\).*$,\1,'`
- endian=`echo ${UNAME_MACHINE_ARCH} | sed -ne 's,^.*\(eb\)$,\1,p'`
- machine=${arch}${endian}-unknown
+ arch=`echo "$UNAME_MACHINE_ARCH" | sed -e 's,^e\(armv[0-9]\).*$,\1,'`
+ endian=`echo "$UNAME_MACHINE_ARCH" | sed -ne 's,^.*\(eb\)$,\1,p'`
+ machine="${arch}${endian}"-unknown
;;
- *) machine=${UNAME_MACHINE_ARCH}-unknown ;;
+ *) machine="$UNAME_MACHINE_ARCH"-unknown ;;
esac
# The Operating System including object format, if it has switched
# to ELF recently (or will in the future) and ABI.
- case "${UNAME_MACHINE_ARCH}" in
+ case "$UNAME_MACHINE_ARCH" in
earm*)
os=netbsdelf
;;
arm*|i386|m68k|ns32k|sh3*|sparc|vax)
- eval $set_cc_for_build
+ set_cc_for_build
if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
| grep -q __ELF__
then
@@ -208,10 +219,10 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
;;
esac
# Determine ABI tags.
- case "${UNAME_MACHINE_ARCH}" in
+ case "$UNAME_MACHINE_ARCH" in
earm*)
expr='s/^earmv[0-9]/-eabi/;s/eb$//'
- abi=`echo ${UNAME_MACHINE_ARCH} | sed -e "$expr"`
+ abi=`echo "$UNAME_MACHINE_ARCH" | sed -e "$expr"`
;;
esac
# The OS release
@@ -219,45 +230,60 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
# thus, need a distinct triplet. However, they do not need
# kernel version information, so it can be replaced with a
# suitable tag, in the style of linux-gnu.
- case "${UNAME_VERSION}" in
+ case "$UNAME_VERSION" in
Debian*)
release='-gnu'
;;
*)
- release=`echo ${UNAME_RELEASE} | sed -e 's/[-_].*//' | cut -d. -f1,2`
+ release=`echo "$UNAME_RELEASE" | sed -e 's/[-_].*//' | cut -d. -f1,2`
;;
esac
# Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
# contains redundant information, the shorter form:
# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
- echo "${machine}-${os}${release}${abi}"
+ echo "$machine-${os}${release}${abi-}"
exit ;;
*:Bitrig:*:*)
UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'`
- echo ${UNAME_MACHINE_ARCH}-unknown-bitrig${UNAME_RELEASE}
+ echo "$UNAME_MACHINE_ARCH"-unknown-bitrig"$UNAME_RELEASE"
exit ;;
*:OpenBSD:*:*)
UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'`
- echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE}
+ echo "$UNAME_MACHINE_ARCH"-unknown-openbsd"$UNAME_RELEASE"
exit ;;
*:LibertyBSD:*:*)
UNAME_MACHINE_ARCH=`arch | sed 's/^.*BSD\.//'`
- echo ${UNAME_MACHINE_ARCH}-unknown-libertybsd${UNAME_RELEASE}
+ echo "$UNAME_MACHINE_ARCH"-unknown-libertybsd"$UNAME_RELEASE"
+ exit ;;
+ *:MidnightBSD:*:*)
+ echo "$UNAME_MACHINE"-unknown-midnightbsd"$UNAME_RELEASE"
exit ;;
*:ekkoBSD:*:*)
- echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE}
+ echo "$UNAME_MACHINE"-unknown-ekkobsd"$UNAME_RELEASE"
exit ;;
*:SolidBSD:*:*)
- echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE}
+ echo "$UNAME_MACHINE"-unknown-solidbsd"$UNAME_RELEASE"
+ exit ;;
+ *:OS108:*:*)
+ echo "$UNAME_MACHINE"-unknown-os108_"$UNAME_RELEASE"
exit ;;
macppc:MirBSD:*:*)
- echo powerpc-unknown-mirbsd${UNAME_RELEASE}
+ echo powerpc-unknown-mirbsd"$UNAME_RELEASE"
exit ;;
*:MirBSD:*:*)
- echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE}
+ echo "$UNAME_MACHINE"-unknown-mirbsd"$UNAME_RELEASE"
exit ;;
*:Sortix:*:*)
- echo ${UNAME_MACHINE}-unknown-sortix
+ echo "$UNAME_MACHINE"-unknown-sortix
+ exit ;;
+ *:Twizzler:*:*)
+ echo "$UNAME_MACHINE"-unknown-twizzler
+ exit ;;
+ *:Redox:*:*)
+ echo "$UNAME_MACHINE"-unknown-redox
+ exit ;;
+ mips:OSF1:*.*)
+ echo mips-dec-osf1
exit ;;
alpha:OSF1:*:*)
case $UNAME_RELEASE in
@@ -310,28 +336,19 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
# A Tn.n version is a released field test version.
# A Xn.n version is an unreleased experimental baselevel.
# 1.2 uses "1.2" for uname -r.
- echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz`
+ echo "$UNAME_MACHINE"-dec-osf"`echo "$UNAME_RELEASE" | sed -e 's/^[PVTX]//' | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz`"
# Reset EXIT trap before exiting to avoid spurious non-zero exit code.
exitcode=$?
trap '' 0
exit $exitcode ;;
- Alpha\ *:Windows_NT*:*)
- # How do we know it's Interix rather than the generic POSIX subsystem?
- # Should we change UNAME_MACHINE based on the output of uname instead
- # of the specific Alpha model?
- echo alpha-pc-interix
- exit ;;
- 21064:Windows_NT:50:3)
- echo alpha-dec-winnt3.5
- exit ;;
Amiga*:UNIX_System_V:4.0:*)
echo m68k-unknown-sysv4
exit ;;
*:[Aa]miga[Oo][Ss]:*:*)
- echo ${UNAME_MACHINE}-unknown-amigaos
+ echo "$UNAME_MACHINE"-unknown-amigaos
exit ;;
*:[Mm]orph[Oo][Ss]:*:*)
- echo ${UNAME_MACHINE}-unknown-morphos
+ echo "$UNAME_MACHINE"-unknown-morphos
exit ;;
*:OS/390:*:*)
echo i370-ibm-openedition
@@ -343,7 +360,7 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
echo powerpc-ibm-os400
exit ;;
arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
- echo arm-acorn-riscix${UNAME_RELEASE}
+ echo arm-acorn-riscix"$UNAME_RELEASE"
exit ;;
arm*:riscos:*:*|arm*:RISCOS:*:*)
echo arm-unknown-riscos
@@ -370,19 +387,19 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
sparc) echo sparc-icl-nx7; exit ;;
esac ;;
s390x:SunOS:*:*)
- echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ echo "$UNAME_MACHINE"-ibm-solaris2"`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`"
exit ;;
sun4H:SunOS:5.*:*)
- echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ echo sparc-hal-solaris2"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`"
exit ;;
sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
- echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ echo sparc-sun-solaris2"`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`"
exit ;;
i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*)
- echo i386-pc-auroraux${UNAME_RELEASE}
+ echo i386-pc-auroraux"$UNAME_RELEASE"
exit ;;
i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*)
- eval $set_cc_for_build
+ set_cc_for_build
SUN_ARCH=i386
# If there is a compiler, see if it is configured for 64-bit objects.
# Note that the Sun cc does not turn __LP64__ into 1 like gcc does.
@@ -395,13 +412,13 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
SUN_ARCH=x86_64
fi
fi
- echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ echo "$SUN_ARCH"-pc-solaris2"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`"
exit ;;
sun4*:SunOS:6*:*)
# According to config.sub, this is the proper way to canonicalize
# SunOS6. Hard to guess exactly what SunOS6 will be like, but
# it's likely to be more like Solaris than SunOS4.
- echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ echo sparc-sun-solaris3"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`"
exit ;;
sun4*:SunOS:*:*)
case "`/usr/bin/arch -k`" in
@@ -410,25 +427,25 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
;;
esac
# Japanese Language versions have a version number like `4.1.3-JL'.
- echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'`
+ echo sparc-sun-sunos"`echo "$UNAME_RELEASE"|sed -e 's/-/_/'`"
exit ;;
sun3*:SunOS:*:*)
- echo m68k-sun-sunos${UNAME_RELEASE}
+ echo m68k-sun-sunos"$UNAME_RELEASE"
exit ;;
sun*:*:4.2BSD:*)
UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
- test "x${UNAME_RELEASE}" = x && UNAME_RELEASE=3
+ test "x$UNAME_RELEASE" = x && UNAME_RELEASE=3
case "`/bin/arch`" in
sun3)
- echo m68k-sun-sunos${UNAME_RELEASE}
+ echo m68k-sun-sunos"$UNAME_RELEASE"
;;
sun4)
- echo sparc-sun-sunos${UNAME_RELEASE}
+ echo sparc-sun-sunos"$UNAME_RELEASE"
;;
esac
exit ;;
aushp:SunOS:*:*)
- echo sparc-auspex-sunos${UNAME_RELEASE}
+ echo sparc-auspex-sunos"$UNAME_RELEASE"
exit ;;
# The situation for MiNT is a little confusing. The machine name
# can be virtually everything (everything which is not
@@ -439,44 +456,44 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
# MiNT. But MiNT is downward compatible to TOS, so this should
# be no problem.
atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
- echo m68k-atari-mint${UNAME_RELEASE}
+ echo m68k-atari-mint"$UNAME_RELEASE"
exit ;;
atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
- echo m68k-atari-mint${UNAME_RELEASE}
+ echo m68k-atari-mint"$UNAME_RELEASE"
exit ;;
*falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
- echo m68k-atari-mint${UNAME_RELEASE}
+ echo m68k-atari-mint"$UNAME_RELEASE"
exit ;;
milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
- echo m68k-milan-mint${UNAME_RELEASE}
+ echo m68k-milan-mint"$UNAME_RELEASE"
exit ;;
hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
- echo m68k-hades-mint${UNAME_RELEASE}
+ echo m68k-hades-mint"$UNAME_RELEASE"
exit ;;
*:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
- echo m68k-unknown-mint${UNAME_RELEASE}
+ echo m68k-unknown-mint"$UNAME_RELEASE"
exit ;;
m68k:machten:*:*)
- echo m68k-apple-machten${UNAME_RELEASE}
+ echo m68k-apple-machten"$UNAME_RELEASE"
exit ;;
powerpc:machten:*:*)
- echo powerpc-apple-machten${UNAME_RELEASE}
+ echo powerpc-apple-machten"$UNAME_RELEASE"
exit ;;
RISC*:Mach:*:*)
echo mips-dec-mach_bsd4.3
exit ;;
RISC*:ULTRIX:*:*)
- echo mips-dec-ultrix${UNAME_RELEASE}
+ echo mips-dec-ultrix"$UNAME_RELEASE"
exit ;;
VAX*:ULTRIX*:*:*)
- echo vax-dec-ultrix${UNAME_RELEASE}
+ echo vax-dec-ultrix"$UNAME_RELEASE"
exit ;;
2020:CLIX:*:* | 2430:CLIX:*:*)
- echo clipper-intergraph-clix${UNAME_RELEASE}
+ echo clipper-intergraph-clix"$UNAME_RELEASE"
exit ;;
mips:*:*:UMIPS | mips:*:*:RISCos)
- eval $set_cc_for_build
- sed 's/^ //' << EOF >$dummy.c
+ set_cc_for_build
+ sed 's/^ //' << EOF > "$dummy.c"
#ifdef __cplusplus
#include <stdio.h> /* for printf() prototype */
int main (int argc, char *argv[]) {
@@ -485,23 +502,23 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
#endif
#if defined (host_mips) && defined (MIPSEB)
#if defined (SYSTYPE_SYSV)
- printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0);
+ printf ("mips-mips-riscos%ssysv\\n", argv[1]); exit (0);
#endif
#if defined (SYSTYPE_SVR4)
- printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0);
+ printf ("mips-mips-riscos%ssvr4\\n", argv[1]); exit (0);
#endif
#if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)
- printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0);
+ printf ("mips-mips-riscos%sbsd\\n", argv[1]); exit (0);
#endif
#endif
exit (-1);
}
EOF
- $CC_FOR_BUILD -o $dummy $dummy.c &&
- dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` &&
- SYSTEM_NAME=`$dummy $dummyarg` &&
+ $CC_FOR_BUILD -o "$dummy" "$dummy.c" &&
+ dummyarg=`echo "$UNAME_RELEASE" | sed -n 's/\([0-9]*\).*/\1/p'` &&
+ SYSTEM_NAME=`"$dummy" "$dummyarg"` &&
{ echo "$SYSTEM_NAME"; exit; }
- echo mips-mips-riscos${UNAME_RELEASE}
+ echo mips-mips-riscos"$UNAME_RELEASE"
exit ;;
Motorola:PowerMAX_OS:*:*)
echo powerpc-motorola-powermax
@@ -527,17 +544,17 @@ EOF
AViiON:dgux:*:*)
# DG/UX returns AViiON for all architectures
UNAME_PROCESSOR=`/usr/bin/uname -p`
- if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ]
+ if [ "$UNAME_PROCESSOR" = mc88100 ] || [ "$UNAME_PROCESSOR" = mc88110 ]
then
- if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \
- [ ${TARGET_BINARY_INTERFACE}x = x ]
+ if [ "$TARGET_BINARY_INTERFACE"x = m88kdguxelfx ] || \
+ [ "$TARGET_BINARY_INTERFACE"x = x ]
then
- echo m88k-dg-dgux${UNAME_RELEASE}
+ echo m88k-dg-dgux"$UNAME_RELEASE"
else
- echo m88k-dg-dguxbcs${UNAME_RELEASE}
+ echo m88k-dg-dguxbcs"$UNAME_RELEASE"
fi
else
- echo i586-dg-dgux${UNAME_RELEASE}
+ echo i586-dg-dgux"$UNAME_RELEASE"
fi
exit ;;
M88*:DolphinOS:*:*) # DolphinOS (SVR3)
@@ -554,7 +571,7 @@ EOF
echo m68k-tektronix-bsd
exit ;;
*:IRIX*:*:*)
- echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`
+ echo mips-sgi-irix"`echo "$UNAME_RELEASE"|sed -e 's/-/_/g'`"
exit ;;
????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id
@@ -566,14 +583,14 @@ EOF
if [ -x /usr/bin/oslevel ] ; then
IBM_REV=`/usr/bin/oslevel`
else
- IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+ IBM_REV="$UNAME_VERSION.$UNAME_RELEASE"
fi
- echo ${UNAME_MACHINE}-ibm-aix${IBM_REV}
+ echo "$UNAME_MACHINE"-ibm-aix"$IBM_REV"
exit ;;
*:AIX:2:3)
if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
- eval $set_cc_for_build
- sed 's/^ //' << EOF >$dummy.c
+ set_cc_for_build
+ sed 's/^ //' << EOF > "$dummy.c"
#include <sys/systemcfg.h>
main()
@@ -584,7 +601,7 @@ EOF
exit(0);
}
EOF
- if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy`
+ if $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=`"$dummy"`
then
echo "$SYSTEM_NAME"
else
@@ -598,7 +615,7 @@ EOF
exit ;;
*:AIX:*:[4567])
IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`
- if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then
+ if /usr/sbin/lsattr -El "$IBM_CPU_ID" | grep ' POWER' >/dev/null 2>&1; then
IBM_ARCH=rs6000
else
IBM_ARCH=powerpc
@@ -607,18 +624,18 @@ EOF
IBM_REV=`/usr/bin/lslpp -Lqc bos.rte.libc |
awk -F: '{ print $3 }' | sed s/[0-9]*$/0/`
else
- IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+ IBM_REV="$UNAME_VERSION.$UNAME_RELEASE"
fi
- echo ${IBM_ARCH}-ibm-aix${IBM_REV}
+ echo "$IBM_ARCH"-ibm-aix"$IBM_REV"
exit ;;
*:AIX:*:*)
echo rs6000-ibm-aix
exit ;;
- ibmrt:4.4BSD:*|romp-ibm:BSD:*)
+ ibmrt:4.4BSD:*|romp-ibm:4.4BSD:*)
echo romp-ibm-bsd4.4
exit ;;
ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and
- echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to
+ echo romp-ibm-bsd"$UNAME_RELEASE" # 4.3 with uname added to
exit ;; # report: romp-ibm BSD 4.3
*:BOSX:*:*)
echo rs6000-bull-bosx
@@ -633,28 +650,28 @@ EOF
echo m68k-hp-bsd4.4
exit ;;
9000/[34678]??:HP-UX:*:*)
- HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
- case "${UNAME_MACHINE}" in
- 9000/31? ) HP_ARCH=m68000 ;;
- 9000/[34]?? ) HP_ARCH=m68k ;;
+ HPUX_REV=`echo "$UNAME_RELEASE"|sed -e 's/[^.]*.[0B]*//'`
+ case "$UNAME_MACHINE" in
+ 9000/31?) HP_ARCH=m68000 ;;
+ 9000/[34]??) HP_ARCH=m68k ;;
9000/[678][0-9][0-9])
if [ -x /usr/bin/getconf ]; then
sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
- case "${sc_cpu_version}" in
+ case "$sc_cpu_version" in
523) HP_ARCH=hppa1.0 ;; # CPU_PA_RISC1_0
528) HP_ARCH=hppa1.1 ;; # CPU_PA_RISC1_1
532) # CPU_PA_RISC2_0
- case "${sc_kernel_bits}" in
+ case "$sc_kernel_bits" in
32) HP_ARCH=hppa2.0n ;;
64) HP_ARCH=hppa2.0w ;;
'') HP_ARCH=hppa2.0 ;; # HP-UX 10.20
esac ;;
esac
fi
- if [ "${HP_ARCH}" = "" ]; then
- eval $set_cc_for_build
- sed 's/^ //' << EOF >$dummy.c
+ if [ "$HP_ARCH" = "" ]; then
+ set_cc_for_build
+ sed 's/^ //' << EOF > "$dummy.c"
#define _HPUX_SOURCE
#include <stdlib.h>
@@ -687,13 +704,13 @@ EOF
exit (0);
}
EOF
- (CCOPTS="" $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy`
+ (CCOPTS="" $CC_FOR_BUILD -o "$dummy" "$dummy.c" 2>/dev/null) && HP_ARCH=`"$dummy"`
test -z "$HP_ARCH" && HP_ARCH=hppa
fi ;;
esac
- if [ ${HP_ARCH} = hppa2.0w ]
+ if [ "$HP_ARCH" = hppa2.0w ]
then
- eval $set_cc_for_build
+ set_cc_for_build
# hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating
# 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler
@@ -712,15 +729,15 @@ EOF
HP_ARCH=hppa64
fi
fi
- echo ${HP_ARCH}-hp-hpux${HPUX_REV}
+ echo "$HP_ARCH"-hp-hpux"$HPUX_REV"
exit ;;
ia64:HP-UX:*:*)
- HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
- echo ia64-hp-hpux${HPUX_REV}
+ HPUX_REV=`echo "$UNAME_RELEASE"|sed -e 's/[^.]*.[0B]*//'`
+ echo ia64-hp-hpux"$HPUX_REV"
exit ;;
3050*:HI-UX:*:*)
- eval $set_cc_for_build
- sed 's/^ //' << EOF >$dummy.c
+ set_cc_for_build
+ sed 's/^ //' << EOF > "$dummy.c"
#include <unistd.h>
int
main ()
@@ -745,11 +762,11 @@ EOF
exit (0);
}
EOF
- $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` &&
+ $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=`"$dummy"` &&
{ echo "$SYSTEM_NAME"; exit; }
echo unknown-hitachi-hiuxwe2
exit ;;
- 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
+ 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:*)
echo hppa1.1-hp-bsd
exit ;;
9000/8??:4.3bsd:*:*)
@@ -758,7 +775,7 @@ EOF
*9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*)
echo hppa1.0-hp-mpeix
exit ;;
- hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
+ hp7??:OSF1:*:* | hp8?[79]:OSF1:*:*)
echo hppa1.1-hp-osf
exit ;;
hp8??:OSF1:*:*)
@@ -766,9 +783,9 @@ EOF
exit ;;
i*86:OSF1:*:*)
if [ -x /usr/sbin/sysversion ] ; then
- echo ${UNAME_MACHINE}-unknown-osf1mk
+ echo "$UNAME_MACHINE"-unknown-osf1mk
else
- echo ${UNAME_MACHINE}-unknown-osf1
+ echo "$UNAME_MACHINE"-unknown-osf1
fi
exit ;;
parisc*:Lites*:*:*)
@@ -793,130 +810,123 @@ EOF
echo c4-convex-bsd
exit ;;
CRAY*Y-MP:*:*:*)
- echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ echo ymp-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'
exit ;;
CRAY*[A-Z]90:*:*:*)
- echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \
+ echo "$UNAME_MACHINE"-cray-unicos"$UNAME_RELEASE" \
| sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
-e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \
-e 's/\.[^.]*$/.X/'
exit ;;
CRAY*TS:*:*:*)
- echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ echo t90-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'
exit ;;
CRAY*T3E:*:*:*)
- echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ echo alphaev5-cray-unicosmk"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'
exit ;;
CRAY*SV1:*:*:*)
- echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ echo sv1-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'
exit ;;
*:UNICOS/mp:*:*)
- echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ echo craynv-cray-unicosmp"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'
exit ;;
F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
FUJITSU_PROC=`uname -m | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz`
FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'`
- FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
+ FUJITSU_REL=`echo "$UNAME_RELEASE" | sed -e 's/ /_/'`
echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
exit ;;
5000:UNIX_System_V:4.*:*)
FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'`
- FUJITSU_REL=`echo ${UNAME_RELEASE} | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/ /_/'`
+ FUJITSU_REL=`echo "$UNAME_RELEASE" | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/ /_/'`
echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
exit ;;
i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
- echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
+ echo "$UNAME_MACHINE"-pc-bsdi"$UNAME_RELEASE"
exit ;;
sparc*:BSD/OS:*:*)
- echo sparc-unknown-bsdi${UNAME_RELEASE}
+ echo sparc-unknown-bsdi"$UNAME_RELEASE"
exit ;;
*:BSD/OS:*:*)
- echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
+ echo "$UNAME_MACHINE"-unknown-bsdi"$UNAME_RELEASE"
+ exit ;;
+ arm:FreeBSD:*:*)
+ UNAME_PROCESSOR=`uname -p`
+ set_cc_for_build
+ if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \
+ | grep -q __ARM_PCS_VFP
+ then
+ echo "${UNAME_PROCESSOR}"-unknown-freebsd"`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`"-gnueabi
+ else
+ echo "${UNAME_PROCESSOR}"-unknown-freebsd"`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`"-gnueabihf
+ fi
exit ;;
*:FreeBSD:*:*)
UNAME_PROCESSOR=`/usr/bin/uname -p`
- case ${UNAME_PROCESSOR} in
+ case "$UNAME_PROCESSOR" in
amd64)
- echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
- *)
- echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+ UNAME_PROCESSOR=x86_64 ;;
+ i386)
+ UNAME_PROCESSOR=i586 ;;
esac
+ echo "$UNAME_PROCESSOR"-unknown-freebsd"`echo "$UNAME_RELEASE"|sed -e 's/[-(].*//'`"
exit ;;
i*:CYGWIN*:*)
- echo ${UNAME_MACHINE}-pc-cygwin
+ echo "$UNAME_MACHINE"-pc-cygwin
exit ;;
*:MINGW64*:*)
- echo ${UNAME_MACHINE}-pc-mingw64
+ echo "$UNAME_MACHINE"-pc-mingw64
exit ;;
*:MINGW*:*)
- echo ${UNAME_MACHINE}-pc-mingw32
+ echo "$UNAME_MACHINE"-pc-mingw32
exit ;;
*:MSYS*:*)
- echo ${UNAME_MACHINE}-pc-msys
- exit ;;
- i*:windows32*:*)
- # uname -m includes "-pc" on this system.
- echo ${UNAME_MACHINE}-mingw32
+ echo "$UNAME_MACHINE"-pc-msys
exit ;;
i*:PW*:*)
- echo ${UNAME_MACHINE}-pc-pw32
+ echo "$UNAME_MACHINE"-pc-pw32
exit ;;
*:Interix*:*)
- case ${UNAME_MACHINE} in
+ case "$UNAME_MACHINE" in
x86)
- echo i586-pc-interix${UNAME_RELEASE}
+ echo i586-pc-interix"$UNAME_RELEASE"
exit ;;
authenticamd | genuineintel | EM64T)
- echo x86_64-unknown-interix${UNAME_RELEASE}
+ echo x86_64-unknown-interix"$UNAME_RELEASE"
exit ;;
IA64)
- echo ia64-unknown-interix${UNAME_RELEASE}
+ echo ia64-unknown-interix"$UNAME_RELEASE"
exit ;;
esac ;;
- [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*)
- echo i${UNAME_MACHINE}-pc-mks
- exit ;;
- 8664:Windows_NT:*)
- echo x86_64-pc-mks
- exit ;;
- i*:Windows_NT*:* | Pentium*:Windows_NT*:*)
- # How do we know it's Interix rather than the generic POSIX subsystem?
- # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we
- # UNAME_MACHINE based on the output of uname instead of i386?
- echo i586-pc-interix
- exit ;;
i*:UWIN*:*)
- echo ${UNAME_MACHINE}-pc-uwin
+ echo "$UNAME_MACHINE"-pc-uwin
exit ;;
amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*)
- echo x86_64-unknown-cygwin
- exit ;;
- p*:CYGWIN*:*)
- echo powerpcle-unknown-cygwin
+ echo x86_64-pc-cygwin
exit ;;
prep*:SunOS:5.*:*)
- echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ echo powerpcle-unknown-solaris2"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`"
exit ;;
*:GNU:*:*)
# the GNU system
- echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-${LIBC}`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
+ echo "`echo "$UNAME_MACHINE"|sed -e 's,[-/].*$,,'`-unknown-$LIBC`echo "$UNAME_RELEASE"|sed -e 's,/.*$,,'`"
exit ;;
*:GNU/*:*:*)
# other systems with GNU libc and userland
- echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr "[:upper:]" "[:lower:]"``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-${LIBC}
+ echo "$UNAME_MACHINE-unknown-`echo "$UNAME_SYSTEM" | sed 's,^[^/]*/,,' | tr "[:upper:]" "[:lower:]"``echo "$UNAME_RELEASE"|sed -e 's/[-(].*//'`-$LIBC"
exit ;;
- i*86:Minix:*:*)
- echo ${UNAME_MACHINE}-pc-minix
+ *:Minix:*:*)
+ echo "$UNAME_MACHINE"-unknown-minix
exit ;;
aarch64:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
exit ;;
aarch64_be:Linux:*:*)
UNAME_MACHINE=aarch64_be
- echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
exit ;;
alpha:Linux:*:*)
- case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
+ case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' /proc/cpuinfo 2>/dev/null` in
EV5) UNAME_MACHINE=alphaev5 ;;
EV56) UNAME_MACHINE=alphaev56 ;;
PCA56) UNAME_MACHINE=alphapca56 ;;
@@ -927,140 +937,178 @@ EOF
esac
objdump --private-headers /bin/sh | grep -q ld.so.1
if test "$?" = 0 ; then LIBC=gnulibc1 ; fi
- echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
exit ;;
arc:Linux:*:* | arceb:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
exit ;;
arm*:Linux:*:*)
- eval $set_cc_for_build
+ set_cc_for_build
if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \
| grep -q __ARM_EABI__
then
- echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
else
if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \
| grep -q __ARM_PCS_VFP
then
- echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabi
+ echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"eabi
else
- echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabihf
+ echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"eabihf
fi
fi
exit ;;
avr32*:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
exit ;;
cris:Linux:*:*)
- echo ${UNAME_MACHINE}-axis-linux-${LIBC}
+ echo "$UNAME_MACHINE"-axis-linux-"$LIBC"
exit ;;
crisv32:Linux:*:*)
- echo ${UNAME_MACHINE}-axis-linux-${LIBC}
+ echo "$UNAME_MACHINE"-axis-linux-"$LIBC"
exit ;;
e2k:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
exit ;;
frv:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
exit ;;
hexagon:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
exit ;;
i*86:Linux:*:*)
- echo ${UNAME_MACHINE}-pc-linux-${LIBC}
+ echo "$UNAME_MACHINE"-pc-linux-"$LIBC"
exit ;;
ia64:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
exit ;;
k1om:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
exit ;;
m32r*:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
exit ;;
m68*:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
exit ;;
mips:Linux:*:* | mips64:Linux:*:*)
- eval $set_cc_for_build
- sed 's/^ //' << EOF >$dummy.c
+ set_cc_for_build
+ IS_GLIBC=0
+ test x"${LIBC}" = xgnu && IS_GLIBC=1
+ sed 's/^ //' << EOF > "$dummy.c"
#undef CPU
- #undef ${UNAME_MACHINE}
- #undef ${UNAME_MACHINE}el
+ #undef mips
+ #undef mipsel
+ #undef mips64
+ #undef mips64el
+ #if ${IS_GLIBC} && defined(_ABI64)
+ LIBCABI=gnuabi64
+ #else
+ #if ${IS_GLIBC} && defined(_ABIN32)
+ LIBCABI=gnuabin32
+ #else
+ LIBCABI=${LIBC}
+ #endif
+ #endif
+
+ #if ${IS_GLIBC} && defined(__mips64) && defined(__mips_isa_rev) && __mips_isa_rev>=6
+ CPU=mipsisa64r6
+ #else
+ #if ${IS_GLIBC} && !defined(__mips64) && defined(__mips_isa_rev) && __mips_isa_rev>=6
+ CPU=mipsisa32r6
+ #else
+ #if defined(__mips64)
+ CPU=mips64
+ #else
+ CPU=mips
+ #endif
+ #endif
+ #endif
+
#if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
- CPU=${UNAME_MACHINE}el
+ MIPS_ENDIAN=el
#else
#if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
- CPU=${UNAME_MACHINE}
+ MIPS_ENDIAN=
#else
- CPU=
+ MIPS_ENDIAN=
#endif
#endif
EOF
- eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'`
- test x"${CPU}" != x && { echo "${CPU}-unknown-linux-${LIBC}"; exit; }
+ eval "`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^CPU\|^MIPS_ENDIAN\|^LIBCABI'`"
+ test "x$CPU" != x && { echo "$CPU${MIPS_ENDIAN}-unknown-linux-$LIBCABI"; exit; }
;;
mips64el:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
exit ;;
openrisc*:Linux:*:*)
- echo or1k-unknown-linux-${LIBC}
+ echo or1k-unknown-linux-"$LIBC"
exit ;;
or32:Linux:*:* | or1k*:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
exit ;;
padre:Linux:*:*)
- echo sparc-unknown-linux-${LIBC}
+ echo sparc-unknown-linux-"$LIBC"
exit ;;
parisc64:Linux:*:* | hppa64:Linux:*:*)
- echo hppa64-unknown-linux-${LIBC}
+ echo hppa64-unknown-linux-"$LIBC"
exit ;;
parisc:Linux:*:* | hppa:Linux:*:*)
# Look for CPU level
case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
- PA7*) echo hppa1.1-unknown-linux-${LIBC} ;;
- PA8*) echo hppa2.0-unknown-linux-${LIBC} ;;
- *) echo hppa-unknown-linux-${LIBC} ;;
+ PA7*) echo hppa1.1-unknown-linux-"$LIBC" ;;
+ PA8*) echo hppa2.0-unknown-linux-"$LIBC" ;;
+ *) echo hppa-unknown-linux-"$LIBC" ;;
esac
exit ;;
ppc64:Linux:*:*)
- echo powerpc64-unknown-linux-${LIBC}
+ echo powerpc64-unknown-linux-"$LIBC"
exit ;;
ppc:Linux:*:*)
- echo powerpc-unknown-linux-${LIBC}
+ echo powerpc-unknown-linux-"$LIBC"
exit ;;
ppc64le:Linux:*:*)
- echo powerpc64le-unknown-linux-${LIBC}
+ echo powerpc64le-unknown-linux-"$LIBC"
exit ;;
ppcle:Linux:*:*)
- echo powerpcle-unknown-linux-${LIBC}
+ echo powerpcle-unknown-linux-"$LIBC"
exit ;;
riscv32:Linux:*:* | riscv64:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
exit ;;
s390:Linux:*:* | s390x:Linux:*:*)
- echo ${UNAME_MACHINE}-ibm-linux-${LIBC}
+ echo "$UNAME_MACHINE"-ibm-linux-"$LIBC"
exit ;;
sh64*:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
exit ;;
sh*:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
exit ;;
sparc:Linux:*:* | sparc64:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
exit ;;
tile*:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
exit ;;
vax:Linux:*:*)
- echo ${UNAME_MACHINE}-dec-linux-${LIBC}
+ echo "$UNAME_MACHINE"-dec-linux-"$LIBC"
exit ;;
x86_64:Linux:*:*)
- echo ${UNAME_MACHINE}-pc-linux-${LIBC}
+ set_cc_for_build
+ LIBCABI=$LIBC
+ if [ "$CC_FOR_BUILD" != no_compiler_found ]; then
+ if (echo '#ifdef __ILP32__'; echo IS_X32; echo '#endif') | \
+ (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
+ grep IS_X32 >/dev/null
+ then
+ LIBCABI="$LIBC"x32
+ fi
+ fi
+ echo "$UNAME_MACHINE"-pc-linux-"$LIBCABI"
exit ;;
xtensa*:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
exit ;;
i*86:DYNIX/ptx:4*:*)
# ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
@@ -1074,34 +1122,34 @@ EOF
# I am not positive that other SVR4 systems won't match this,
# I just have to hope. -- rms.
# Use sysv4.2uw... so that sysv4* matches it.
- echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
+ echo "$UNAME_MACHINE"-pc-sysv4.2uw"$UNAME_VERSION"
exit ;;
i*86:OS/2:*:*)
# If we were able to find `uname', then EMX Unix compatibility
# is probably installed.
- echo ${UNAME_MACHINE}-pc-os2-emx
+ echo "$UNAME_MACHINE"-pc-os2-emx
exit ;;
i*86:XTS-300:*:STOP)
- echo ${UNAME_MACHINE}-unknown-stop
+ echo "$UNAME_MACHINE"-unknown-stop
exit ;;
i*86:atheos:*:*)
- echo ${UNAME_MACHINE}-unknown-atheos
+ echo "$UNAME_MACHINE"-unknown-atheos
exit ;;
i*86:syllable:*:*)
- echo ${UNAME_MACHINE}-pc-syllable
+ echo "$UNAME_MACHINE"-pc-syllable
exit ;;
i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*)
- echo i386-unknown-lynxos${UNAME_RELEASE}
+ echo i386-unknown-lynxos"$UNAME_RELEASE"
exit ;;
i*86:*DOS:*:*)
- echo ${UNAME_MACHINE}-pc-msdosdjgpp
+ echo "$UNAME_MACHINE"-pc-msdosdjgpp
exit ;;
- i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*)
- UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'`
+ i*86:*:4.*:*)
+ UNAME_REL=`echo "$UNAME_RELEASE" | sed 's/\/MP$//'`
if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
- echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL}
+ echo "$UNAME_MACHINE"-univel-sysv"$UNAME_REL"
else
- echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL}
+ echo "$UNAME_MACHINE"-pc-sysv"$UNAME_REL"
fi
exit ;;
i*86:*:5:[678]*)
@@ -1111,12 +1159,12 @@ EOF
*Pentium) UNAME_MACHINE=i586 ;;
*Pent*|*Celeron) UNAME_MACHINE=i686 ;;
esac
- echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}
+ echo "$UNAME_MACHINE-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}"
exit ;;
i*86:*:3.2:*)
if test -f /usr/options/cb.name; then
UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
- echo ${UNAME_MACHINE}-pc-isc$UNAME_REL
+ echo "$UNAME_MACHINE"-pc-isc"$UNAME_REL"
elif /bin/uname -X 2>/dev/null >/dev/null ; then
UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')`
(/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486
@@ -1126,9 +1174,9 @@ EOF
&& UNAME_MACHINE=i686
(/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \
&& UNAME_MACHINE=i686
- echo ${UNAME_MACHINE}-pc-sco$UNAME_REL
+ echo "$UNAME_MACHINE"-pc-sco"$UNAME_REL"
else
- echo ${UNAME_MACHINE}-pc-sysv32
+ echo "$UNAME_MACHINE"-pc-sysv32
fi
exit ;;
pc:*:*:*)
@@ -1148,9 +1196,9 @@ EOF
exit ;;
i860:*:4.*:*) # i860-SVR4
if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
- echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4
+ echo i860-stardent-sysv"$UNAME_RELEASE" # Stardent Vistra i860-SVR4
else # Add other i860-SVR4 vendors below as they are discovered.
- echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4
+ echo i860-unknown-sysv"$UNAME_RELEASE" # Unknown i860-SVR4
fi
exit ;;
mini*:CTIX:SYS*5:*)
@@ -1170,9 +1218,9 @@ EOF
test -r /etc/.relid \
&& OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
- && { echo i486-ncr-sysv4.3${OS_REL}; exit; }
+ && { echo i486-ncr-sysv4.3"$OS_REL"; exit; }
/bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
- && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
+ && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } ;;
3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
&& { echo i486-ncr-sysv4; exit; } ;;
@@ -1181,28 +1229,28 @@ EOF
test -r /etc/.relid \
&& OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
- && { echo i486-ncr-sysv4.3${OS_REL}; exit; }
+ && { echo i486-ncr-sysv4.3"$OS_REL"; exit; }
/bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
- && { echo i586-ncr-sysv4.3${OS_REL}; exit; }
+ && { echo i586-ncr-sysv4.3"$OS_REL"; exit; }
/bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \
- && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
+ && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } ;;
m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)
- echo m68k-unknown-lynxos${UNAME_RELEASE}
+ echo m68k-unknown-lynxos"$UNAME_RELEASE"
exit ;;
mc68030:UNIX_System_V:4.*:*)
echo m68k-atari-sysv4
exit ;;
TSUNAMI:LynxOS:2.*:*)
- echo sparc-unknown-lynxos${UNAME_RELEASE}
+ echo sparc-unknown-lynxos"$UNAME_RELEASE"
exit ;;
rs6000:LynxOS:2.*:*)
- echo rs6000-unknown-lynxos${UNAME_RELEASE}
+ echo rs6000-unknown-lynxos"$UNAME_RELEASE"
exit ;;
PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*)
- echo powerpc-unknown-lynxos${UNAME_RELEASE}
+ echo powerpc-unknown-lynxos"$UNAME_RELEASE"
exit ;;
SM[BE]S:UNIX_SV:*:*)
- echo mips-dde-sysv${UNAME_RELEASE}
+ echo mips-dde-sysv"$UNAME_RELEASE"
exit ;;
RM*:ReliantUNIX-*:*:*)
echo mips-sni-sysv4
@@ -1213,7 +1261,7 @@ EOF
*:SINIX-*:*:*)
if uname -p 2>/dev/null >/dev/null ; then
UNAME_MACHINE=`(uname -p) 2>/dev/null`
- echo ${UNAME_MACHINE}-sni-sysv4
+ echo "$UNAME_MACHINE"-sni-sysv4
else
echo ns32k-sni-sysv
fi
@@ -1233,23 +1281,23 @@ EOF
exit ;;
i*86:VOS:*:*)
# From Paul.Green@stratus.com.
- echo ${UNAME_MACHINE}-stratus-vos
+ echo "$UNAME_MACHINE"-stratus-vos
exit ;;
*:VOS:*:*)
# From Paul.Green@stratus.com.
echo hppa1.1-stratus-vos
exit ;;
mc68*:A/UX:*:*)
- echo m68k-apple-aux${UNAME_RELEASE}
+ echo m68k-apple-aux"$UNAME_RELEASE"
exit ;;
news*:NEWS-OS:6*:*)
echo mips-sony-newsos6
exit ;;
R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
if [ -d /usr/nec ]; then
- echo mips-nec-sysv${UNAME_RELEASE}
+ echo mips-nec-sysv"$UNAME_RELEASE"
else
- echo mips-unknown-sysv${UNAME_RELEASE}
+ echo mips-unknown-sysv"$UNAME_RELEASE"
fi
exit ;;
BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only.
@@ -1268,60 +1316,71 @@ EOF
echo x86_64-unknown-haiku
exit ;;
SX-4:SUPER-UX:*:*)
- echo sx4-nec-superux${UNAME_RELEASE}
+ echo sx4-nec-superux"$UNAME_RELEASE"
exit ;;
SX-5:SUPER-UX:*:*)
- echo sx5-nec-superux${UNAME_RELEASE}
+ echo sx5-nec-superux"$UNAME_RELEASE"
exit ;;
SX-6:SUPER-UX:*:*)
- echo sx6-nec-superux${UNAME_RELEASE}
+ echo sx6-nec-superux"$UNAME_RELEASE"
exit ;;
SX-7:SUPER-UX:*:*)
- echo sx7-nec-superux${UNAME_RELEASE}
+ echo sx7-nec-superux"$UNAME_RELEASE"
exit ;;
SX-8:SUPER-UX:*:*)
- echo sx8-nec-superux${UNAME_RELEASE}
+ echo sx8-nec-superux"$UNAME_RELEASE"
exit ;;
SX-8R:SUPER-UX:*:*)
- echo sx8r-nec-superux${UNAME_RELEASE}
+ echo sx8r-nec-superux"$UNAME_RELEASE"
exit ;;
SX-ACE:SUPER-UX:*:*)
- echo sxace-nec-superux${UNAME_RELEASE}
+ echo sxace-nec-superux"$UNAME_RELEASE"
exit ;;
Power*:Rhapsody:*:*)
- echo powerpc-apple-rhapsody${UNAME_RELEASE}
+ echo powerpc-apple-rhapsody"$UNAME_RELEASE"
exit ;;
*:Rhapsody:*:*)
- echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE}
+ echo "$UNAME_MACHINE"-apple-rhapsody"$UNAME_RELEASE"
+ exit ;;
+ arm64:Darwin:*:*)
+ echo aarch64-apple-darwin"$UNAME_RELEASE"
exit ;;
*:Darwin:*:*)
- UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown
- eval $set_cc_for_build
- if test "$UNAME_PROCESSOR" = unknown ; then
- UNAME_PROCESSOR=powerpc
+ UNAME_PROCESSOR=`uname -p`
+ case $UNAME_PROCESSOR in
+ unknown) UNAME_PROCESSOR=powerpc ;;
+ esac
+ if command -v xcode-select > /dev/null 2> /dev/null && \
+ ! xcode-select --print-path > /dev/null 2> /dev/null ; then
+ # Avoid executing cc if there is no toolchain installed as
+ # cc will be a stub that puts up a graphical alert
+ # prompting the user to install developer tools.
+ CC_FOR_BUILD=no_compiler_found
+ else
+ set_cc_for_build
fi
- if test `echo "$UNAME_RELEASE" | sed -e 's/\..*//'` -le 10 ; then
- if [ "$CC_FOR_BUILD" != no_compiler_found ]; then
- if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \
- (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
- grep IS_64BIT_ARCH >/dev/null
- then
- case $UNAME_PROCESSOR in
- i386) UNAME_PROCESSOR=x86_64 ;;
- powerpc) UNAME_PROCESSOR=powerpc64 ;;
- esac
- fi
+ if [ "$CC_FOR_BUILD" != no_compiler_found ]; then
+ if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \
+ (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
+ grep IS_64BIT_ARCH >/dev/null
+ then
+ case $UNAME_PROCESSOR in
+ i386) UNAME_PROCESSOR=x86_64 ;;
+ powerpc) UNAME_PROCESSOR=powerpc64 ;;
+ esac
+ fi
+ # On 10.4-10.6 one might compile for PowerPC via gcc -arch ppc
+ if (echo '#ifdef __POWERPC__'; echo IS_PPC; echo '#endif') | \
+ (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
+ grep IS_PPC >/dev/null
+ then
+ UNAME_PROCESSOR=powerpc
fi
elif test "$UNAME_PROCESSOR" = i386 ; then
- # Avoid executing cc on OS X 10.9, as it ships with a stub
- # that puts up a graphical alert prompting to install
- # developer tools. Any system running Mac OS X 10.7 or
- # later (Darwin 11 and later) is required to have a 64-bit
- # processor. This is not true of the ARM version of Darwin
- # that Apple uses in portable devices.
- UNAME_PROCESSOR=x86_64
+ # uname -m returns i386 or x86_64
+ UNAME_PROCESSOR=$UNAME_MACHINE
fi
- echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
+ echo "$UNAME_PROCESSOR"-apple-darwin"$UNAME_RELEASE"
exit ;;
*:procnto*:*:* | *:QNX:[0123456789]*:*)
UNAME_PROCESSOR=`uname -p`
@@ -1329,19 +1388,25 @@ EOF
UNAME_PROCESSOR=i386
UNAME_MACHINE=pc
fi
- echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE}
+ echo "$UNAME_PROCESSOR"-"$UNAME_MACHINE"-nto-qnx"$UNAME_RELEASE"
exit ;;
*:QNX:*:4*)
echo i386-pc-qnx
exit ;;
- NEO-?:NONSTOP_KERNEL:*:*)
- echo neo-tandem-nsk${UNAME_RELEASE}
+ NEO-*:NONSTOP_KERNEL:*:*)
+ echo neo-tandem-nsk"$UNAME_RELEASE"
exit ;;
NSE-*:NONSTOP_KERNEL:*:*)
- echo nse-tandem-nsk${UNAME_RELEASE}
+ echo nse-tandem-nsk"$UNAME_RELEASE"
+ exit ;;
+ NSR-*:NONSTOP_KERNEL:*:*)
+ echo nsr-tandem-nsk"$UNAME_RELEASE"
+ exit ;;
+ NSV-*:NONSTOP_KERNEL:*:*)
+ echo nsv-tandem-nsk"$UNAME_RELEASE"
exit ;;
- NSR-?:NONSTOP_KERNEL:*:*)
- echo nsr-tandem-nsk${UNAME_RELEASE}
+ NSX-*:NONSTOP_KERNEL:*:*)
+ echo nsx-tandem-nsk"$UNAME_RELEASE"
exit ;;
*:NonStop-UX:*:*)
echo mips-compaq-nonstopux
@@ -1350,18 +1415,19 @@ EOF
echo bs2000-siemens-sysv
exit ;;
DS/*:UNIX_System_V:*:*)
- echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE}
+ echo "$UNAME_MACHINE"-"$UNAME_SYSTEM"-"$UNAME_RELEASE"
exit ;;
*:Plan9:*:*)
# "uname -m" is not consistent, so use $cputype instead. 386
# is converted to i386 for consistency with other x86
# operating systems.
+ # shellcheck disable=SC2154
if test "$cputype" = 386; then
UNAME_MACHINE=i386
else
UNAME_MACHINE="$cputype"
fi
- echo ${UNAME_MACHINE}-unknown-plan9
+ echo "$UNAME_MACHINE"-unknown-plan9
exit ;;
*:TOPS-10:*:*)
echo pdp10-unknown-tops10
@@ -1382,14 +1448,14 @@ EOF
echo pdp10-unknown-its
exit ;;
SEI:*:*:SEIUX)
- echo mips-sei-seiux${UNAME_RELEASE}
+ echo mips-sei-seiux"$UNAME_RELEASE"
exit ;;
*:DragonFly:*:*)
- echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
+ echo "$UNAME_MACHINE"-unknown-dragonfly"`echo "$UNAME_RELEASE"|sed -e 's/[-(].*//'`"
exit ;;
*:*VMS:*:*)
UNAME_MACHINE=`(uname -p) 2>/dev/null`
- case "${UNAME_MACHINE}" in
+ case "$UNAME_MACHINE" in
A*) echo alpha-dec-vms ; exit ;;
I*) echo ia64-dec-vms ; exit ;;
V*) echo vax-dec-vms ; exit ;;
@@ -1398,32 +1464,190 @@ EOF
echo i386-pc-xenix
exit ;;
i*86:skyos:*:*)
- echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE} | sed -e 's/ .*$//'`
+ echo "$UNAME_MACHINE"-pc-skyos"`echo "$UNAME_RELEASE" | sed -e 's/ .*$//'`"
exit ;;
i*86:rdos:*:*)
- echo ${UNAME_MACHINE}-pc-rdos
+ echo "$UNAME_MACHINE"-pc-rdos
exit ;;
i*86:AROS:*:*)
- echo ${UNAME_MACHINE}-pc-aros
+ echo "$UNAME_MACHINE"-pc-aros
exit ;;
x86_64:VMkernel:*:*)
- echo ${UNAME_MACHINE}-unknown-esx
+ echo "$UNAME_MACHINE"-unknown-esx
exit ;;
amd64:Isilon\ OneFS:*:*)
echo x86_64-unknown-onefs
exit ;;
+ *:Unleashed:*:*)
+ echo "$UNAME_MACHINE"-unknown-unleashed"$UNAME_RELEASE"
+ exit ;;
+esac
+
+# No uname command or uname output not recognized.
+set_cc_for_build
+cat > "$dummy.c" <<EOF
+#ifdef _SEQUENT_
+#include <sys/types.h>
+#include <sys/utsname.h>
+#endif
+#if defined(ultrix) || defined(_ultrix) || defined(__ultrix) || defined(__ultrix__)
+#if defined (vax) || defined (__vax) || defined (__vax__) || defined(mips) || defined(__mips) || defined(__mips__) || defined(MIPS) || defined(__MIPS__)
+#include <signal.h>
+#if defined(_SIZE_T_) || defined(SIGLOST)
+#include <sys/utsname.h>
+#endif
+#endif
+#endif
+main ()
+{
+#if defined (sony)
+#if defined (MIPSEB)
+ /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed,
+ I don't know.... */
+ printf ("mips-sony-bsd\n"); exit (0);
+#else
+#include <sys/param.h>
+ printf ("m68k-sony-newsos%s\n",
+#ifdef NEWSOS4
+ "4"
+#else
+ ""
+#endif
+ ); exit (0);
+#endif
+#endif
+
+#if defined (NeXT)
+#if !defined (__ARCHITECTURE__)
+#define __ARCHITECTURE__ "m68k"
+#endif
+ int version;
+ version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;
+ if (version < 4)
+ printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);
+ else
+ printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version);
+ exit (0);
+#endif
+
+#if defined (MULTIMAX) || defined (n16)
+#if defined (UMAXV)
+ printf ("ns32k-encore-sysv\n"); exit (0);
+#else
+#if defined (CMU)
+ printf ("ns32k-encore-mach\n"); exit (0);
+#else
+ printf ("ns32k-encore-bsd\n"); exit (0);
+#endif
+#endif
+#endif
+
+#if defined (__386BSD__)
+ printf ("i386-pc-bsd\n"); exit (0);
+#endif
+
+#if defined (sequent)
+#if defined (i386)
+ printf ("i386-sequent-dynix\n"); exit (0);
+#endif
+#if defined (ns32000)
+ printf ("ns32k-sequent-dynix\n"); exit (0);
+#endif
+#endif
+
+#if defined (_SEQUENT_)
+ struct utsname un;
+
+ uname(&un);
+ if (strncmp(un.version, "V2", 2) == 0) {
+ printf ("i386-sequent-ptx2\n"); exit (0);
+ }
+ if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */
+ printf ("i386-sequent-ptx1\n"); exit (0);
+ }
+ printf ("i386-sequent-ptx\n"); exit (0);
+#endif
+
+#if defined (vax)
+#if !defined (ultrix)
+#include <sys/param.h>
+#if defined (BSD)
+#if BSD == 43
+ printf ("vax-dec-bsd4.3\n"); exit (0);
+#else
+#if BSD == 199006
+ printf ("vax-dec-bsd4.3reno\n"); exit (0);
+#else
+ printf ("vax-dec-bsd\n"); exit (0);
+#endif
+#endif
+#else
+ printf ("vax-dec-bsd\n"); exit (0);
+#endif
+#else
+#if defined(_SIZE_T_) || defined(SIGLOST)
+ struct utsname un;
+ uname (&un);
+ printf ("vax-dec-ultrix%s\n", un.release); exit (0);
+#else
+ printf ("vax-dec-ultrix\n"); exit (0);
+#endif
+#endif
+#endif
+#if defined(ultrix) || defined(_ultrix) || defined(__ultrix) || defined(__ultrix__)
+#if defined(mips) || defined(__mips) || defined(__mips__) || defined(MIPS) || defined(__MIPS__)
+#if defined(_SIZE_T_) || defined(SIGLOST)
+ struct utsname *un;
+ uname (&un);
+ printf ("mips-dec-ultrix%s\n", un.release); exit (0);
+#else
+ printf ("mips-dec-ultrix\n"); exit (0);
+#endif
+#endif
+#endif
+
+#if defined (alliant) && defined (i860)
+ printf ("i860-alliant-bsd\n"); exit (0);
+#endif
+
+ exit (1);
+}
+EOF
+
+$CC_FOR_BUILD -o "$dummy" "$dummy.c" 2>/dev/null && SYSTEM_NAME=`$dummy` &&
+ { echo "$SYSTEM_NAME"; exit; }
+
+# Apollos put the system type in the environment.
+test -d /usr/apollo && { echo "$ISP-apollo-$SYSTYPE"; exit; }
+
+echo "$0: unable to guess system type" >&2
+
+case "$UNAME_MACHINE:$UNAME_SYSTEM" in
+ mips:Linux | mips64:Linux)
+ # If we got here on MIPS GNU/Linux, output extra information.
+ cat >&2 <<EOF
+
+NOTE: MIPS GNU/Linux systems require a C compiler to fully recognize
+the system type. Please install a C compiler and try again.
+EOF
+ ;;
esac
cat >&2 <<EOF
-$0: unable to guess system type
This script (version $timestamp), has failed to recognize the
-operating system you are using. If your script is old, overwrite
-config.guess and config.sub with the latest versions from:
+operating system you are using. If your script is old, overwrite *all*
+copies of config.guess and config.sub with the latest versions from:
- http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess
+ https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess
and
- http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub
+ https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub
+EOF
+
+year=`echo $timestamp | sed 's,-.*,,'`
+# shellcheck disable=SC2003
+if test "`expr "\`date +%Y\`" - "$year"`" -lt 3 ; then
+ cat >&2 <<EOF
If $0 has already been updated, send the following data and any
information you think might be pertinent to config-patches@gnu.org to
@@ -1446,16 +1670,17 @@ hostinfo = `(hostinfo) 2>/dev/null`
/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null`
/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null`
-UNAME_MACHINE = ${UNAME_MACHINE}
-UNAME_RELEASE = ${UNAME_RELEASE}
-UNAME_SYSTEM = ${UNAME_SYSTEM}
-UNAME_VERSION = ${UNAME_VERSION}
+UNAME_MACHINE = "$UNAME_MACHINE"
+UNAME_RELEASE = "$UNAME_RELEASE"
+UNAME_SYSTEM = "$UNAME_SYSTEM"
+UNAME_VERSION = "$UNAME_VERSION"
EOF
+fi
exit 1
# Local variables:
-# eval: (add-hook 'write-file-hooks 'time-stamp)
+# eval: (add-hook 'before-save-hook 'time-stamp)
# time-stamp-start: "timestamp='"
# time-stamp-format: "%:y-%02m-%02d"
# time-stamp-end: "'"
diff --git a/contrib/unbound/config.h.in b/contrib/unbound/config.h.in
index 78d47fedc139..f7a4095ed348 100644
--- a/contrib/unbound/config.h.in
+++ b/contrib/unbound/config.h.in
@@ -28,6 +28,9 @@
/* Whether daemon is deprecated */
#undef DEPRECATED_DAEMON
+/* Define this to enable kernel based UDP source port randomization. */
+#undef DISABLE_EXPLICIT_PORT_RANDOMISATION
+
/* default dnstap socket path */
#undef DNSTAP_SOCKET_PATH
@@ -176,6 +179,9 @@
/* Define to 1 if you have the `endservent' function. */
#undef HAVE_ENDSERVENT
+/* Define to 1 if you have the `ENGINE_cleanup' function. */
+#undef HAVE_ENGINE_CLEANUP
+
/* Define to 1 if you have the `ERR_free_strings' function. */
#undef HAVE_ERR_FREE_STRINGS
@@ -380,6 +386,9 @@
/* Define to 1 if you have the <openssl/conf.h> header file. */
#undef HAVE_OPENSSL_CONF_H
+/* Define to 1 if you have the <openssl/core_names.h> header file. */
+#undef HAVE_OPENSSL_CORE_NAMES_H
+
/* Define to 1 if you have the <openssl/dh.h> header file. */
#undef HAVE_OPENSSL_DH_H
@@ -494,8 +503,9 @@
/* Define to 1 if you have the `SSL_CTX_set_security_level' function. */
#undef HAVE_SSL_CTX_SET_SECURITY_LEVEL
-/* Define to 1 if you have the `SSL_CTX_set_tlsext_ticket_key_cb' function. */
-#undef HAVE_SSL_CTX_SET_TLSEXT_TICKET_KEY_CB
+/* Define to 1 if you have the `SSL_CTX_set_tlsext_ticket_key_evp_cb'
+ function. */
+#undef HAVE_SSL_CTX_SET_TLSEXT_TICKET_KEY_EVP_CB
/* Define to 1 if you have the `SSL_get0_peername' function. */
#undef HAVE_SSL_GET0_PEERNAME
@@ -590,6 +600,9 @@
/* Define to 1 if you have the <sys/wait.h> header file. */
#undef HAVE_SYS_WAIT_H
+/* Define to 1 if you have the <TargetConditionals.h> header file. */
+#undef HAVE_TARGETCONDITIONALS_H
+
/* Define to 1 if you have the <time.h> header file. */
#undef HAVE_TIME_H
@@ -805,6 +818,9 @@
/* Define to 1 to use ipset support */
#undef USE_IPSET
+/* Define if you enable libevent */
+#undef USE_LIBEVENT
+
/* Define if you want to use internal select based events */
#undef USE_MINI_EVENT
@@ -854,6 +870,9 @@
/* the version of the windows API enabled */
#undef WINVER
+/* Define if you want dynlib module. */
+#undef WITH_DYNLIBMODULE
+
/* Define if you want Python module. */
#undef WITH_PYTHONMODULE
diff --git a/contrib/unbound/config.sub b/contrib/unbound/config.sub
index ba15a57a5cf3..3d9a8dc3d5a7 100755
--- a/contrib/unbound/config.sub
+++ b/contrib/unbound/config.sub
@@ -1,8 +1,8 @@
-#!/usr/bin/sh
+#! /bin/sh
# Configuration validation subroutine script.
-# Copyright 1992-2016 Free Software Foundation, Inc.
+# Copyright 1992-2020 Free Software Foundation, Inc.
-timestamp='2016-09-05'
+timestamp='2020-07-10'
# 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
@@ -15,7 +15,7 @@ timestamp='2016-09-05'
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
-# along with this program; if not, see <http://www.gnu.org/licenses/>.
+# along with this program; if not, see <https://www.gnu.org/licenses/>.
#
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
@@ -33,7 +33,7 @@ timestamp='2016-09-05'
# Otherwise, we print the canonical config type on stdout and succeed.
# You can get the latest version of this script from:
-# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub
+# https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub
# This file is supposed to be the same for all GNU packages
# and recognize all the CPU types, system types and aliases
@@ -57,7 +57,7 @@ Usage: $0 [OPTION] CPU-MFR-OPSYS or ALIAS
Canonicalize a configuration name.
-Operation modes:
+Options:
-h, --help print this help, then exit
-t, --time-stamp print date of last modification, then exit
-v, --version print version number, then exit
@@ -67,7 +67,7 @@ Report bugs and patches to <config-patches@gnu.org>."
version="\
GNU config.sub ($timestamp)
-Copyright 1992-2016 Free Software Foundation, Inc.
+Copyright 1992-2020 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
@@ -89,12 +89,12 @@ while test $# -gt 0 ; do
- ) # Use stdin as input.
break ;;
-* )
- echo "$me: invalid option $1$help"
+ echo "$me: invalid option $1$help" >&2
exit 1 ;;
*local*)
# First pass through any local machine types.
- echo $1
+ echo "$1"
exit ;;
* )
@@ -110,1242 +110,1167 @@ case $# in
exit 1;;
esac
-# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any).
-# Here we must recognize all the valid KERNEL-OS combinations.
-maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
-case $maybe_os in
- nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \
- linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \
- knetbsd*-gnu* | netbsd*-gnu* | netbsd*-eabi* | \
- kopensolaris*-gnu* | cloudabi*-eabi* | \
- storm-chaos* | os2-emx* | rtmk-nova*)
- os=-$maybe_os
- basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
- ;;
- android-linux)
- os=-linux-android
- basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown
- ;;
- *)
- basic_machine=`echo $1 | sed 's/-[^-]*$//'`
- if [ $basic_machine != $1 ]
- then os=`echo $1 | sed 's/.*-/-/'`
- else os=; fi
- ;;
-esac
+# Split fields of configuration type
+# shellcheck disable=SC2162
+IFS="-" read field1 field2 field3 field4 <<EOF
+$1
+EOF
-### Let's recognize common machines as not being operating systems so
-### that things like config.sub decstation-3100 work. We also
-### recognize some manufacturers as not being operating systems, so we
-### can provide default operating systems below.
-case $os in
- -sun*os*)
- # Prevent following clause from handling this invalid input.
- ;;
- -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \
- -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \
- -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \
- -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
- -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
- -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
- -apple | -axis | -knuth | -cray | -microblaze*)
- os=
- basic_machine=$1
- ;;
- -bluegene*)
- os=-cnk
- ;;
- -sim | -cisco | -oki | -wec | -winbond)
- os=
- basic_machine=$1
- ;;
- -scout)
- ;;
- -wrs)
- os=-vxworks
- basic_machine=$1
- ;;
- -chorusos*)
- os=-chorusos
- basic_machine=$1
- ;;
- -chorusrdb)
- os=-chorusrdb
- basic_machine=$1
- ;;
- -hiux*)
- os=-hiuxwe2
- ;;
- -sco6)
- os=-sco5v6
- basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
- ;;
- -sco5)
- os=-sco3.2v5
- basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
- ;;
- -sco4)
- os=-sco3.2v4
- basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
- ;;
- -sco3.2.[4-9]*)
- os=`echo $os | sed -e 's/sco3.2./sco3.2v/'`
- basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
- ;;
- -sco3.2v[4-9]*)
- # Don't forget version if it is 3.2v4 or newer.
- basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
- ;;
- -sco5v6*)
- # Don't forget version if it is 3.2v4 or newer.
- basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
- ;;
- -sco*)
- os=-sco3.2v2
- basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
- ;;
- -udk*)
- basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
- ;;
- -isc)
- os=-isc2.2
- basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
- ;;
- -clix*)
- basic_machine=clipper-intergraph
- ;;
- -isc*)
- basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
- ;;
- -lynx*178)
- os=-lynxos178
- ;;
- -lynx*5)
- os=-lynxos5
- ;;
- -lynx*)
- os=-lynxos
+# Separate into logical components for further validation
+case $1 in
+ *-*-*-*-*)
+ echo Invalid configuration \`"$1"\': more than four components >&2
+ exit 1
;;
- -ptx*)
- basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'`
+ *-*-*-*)
+ basic_machine=$field1-$field2
+ basic_os=$field3-$field4
;;
- -windowsnt*)
- os=`echo $os | sed -e 's/windowsnt/winnt/'`
+ *-*-*)
+ # Ambiguous whether COMPANY is present, or skipped and KERNEL-OS is two
+ # parts
+ maybe_os=$field2-$field3
+ case $maybe_os in
+ nto-qnx* | linux-* | uclinux-uclibc* \
+ | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* \
+ | netbsd*-eabi* | kopensolaris*-gnu* | cloudabi*-eabi* \
+ | storm-chaos* | os2-emx* | rtmk-nova*)
+ basic_machine=$field1
+ basic_os=$maybe_os
+ ;;
+ android-linux)
+ basic_machine=$field1-unknown
+ basic_os=linux-android
+ ;;
+ *)
+ basic_machine=$field1-$field2
+ basic_os=$field3
+ ;;
+ esac
;;
- -psos*)
- os=-psos
+ *-*)
+ # A lone config we happen to match not fitting any pattern
+ case $field1-$field2 in
+ decstation-3100)
+ basic_machine=mips-dec
+ basic_os=
+ ;;
+ *-*)
+ # Second component is usually, but not always the OS
+ case $field2 in
+ # Prevent following clause from handling this valid os
+ sun*os*)
+ basic_machine=$field1
+ basic_os=$field2
+ ;;
+ # Manufacturers
+ dec* | mips* | sequent* | encore* | pc533* | sgi* | sony* \
+ | att* | 7300* | 3300* | delta* | motorola* | sun[234]* \
+ | unicom* | ibm* | next | hp | isi* | apollo | altos* \
+ | convergent* | ncr* | news | 32* | 3600* | 3100* \
+ | hitachi* | c[123]* | convex* | sun | crds | omron* | dg \
+ | ultra | tti* | harris | dolphin | highlevel | gould \
+ | cbm | ns | masscomp | apple | axis | knuth | cray \
+ | microblaze* | sim | cisco \
+ | oki | wec | wrs | winbond)
+ basic_machine=$field1-$field2
+ basic_os=
+ ;;
+ *)
+ basic_machine=$field1
+ basic_os=$field2
+ ;;
+ esac
+ ;;
+ esac
;;
- -mint | -mint[0-9]*)
- basic_machine=m68k-atari
- os=-mint
+ *)
+ # Convert single-component short-hands not valid as part of
+ # multi-component configurations.
+ case $field1 in
+ 386bsd)
+ basic_machine=i386-pc
+ basic_os=bsd
+ ;;
+ a29khif)
+ basic_machine=a29k-amd
+ basic_os=udi
+ ;;
+ adobe68k)
+ basic_machine=m68010-adobe
+ basic_os=scout
+ ;;
+ alliant)
+ basic_machine=fx80-alliant
+ basic_os=
+ ;;
+ altos | altos3068)
+ basic_machine=m68k-altos
+ basic_os=
+ ;;
+ am29k)
+ basic_machine=a29k-none
+ basic_os=bsd
+ ;;
+ amdahl)
+ basic_machine=580-amdahl
+ basic_os=sysv
+ ;;
+ amiga)
+ basic_machine=m68k-unknown
+ basic_os=
+ ;;
+ amigaos | amigados)
+ basic_machine=m68k-unknown
+ basic_os=amigaos
+ ;;
+ amigaunix | amix)
+ basic_machine=m68k-unknown
+ basic_os=sysv4
+ ;;
+ apollo68)
+ basic_machine=m68k-apollo
+ basic_os=sysv
+ ;;
+ apollo68bsd)
+ basic_machine=m68k-apollo
+ basic_os=bsd
+ ;;
+ aros)
+ basic_machine=i386-pc
+ basic_os=aros
+ ;;
+ aux)
+ basic_machine=m68k-apple
+ basic_os=aux
+ ;;
+ balance)
+ basic_machine=ns32k-sequent
+ basic_os=dynix
+ ;;
+ blackfin)
+ basic_machine=bfin-unknown
+ basic_os=linux
+ ;;
+ cegcc)
+ basic_machine=arm-unknown
+ basic_os=cegcc
+ ;;
+ convex-c1)
+ basic_machine=c1-convex
+ basic_os=bsd
+ ;;
+ convex-c2)
+ basic_machine=c2-convex
+ basic_os=bsd
+ ;;
+ convex-c32)
+ basic_machine=c32-convex
+ basic_os=bsd
+ ;;
+ convex-c34)
+ basic_machine=c34-convex
+ basic_os=bsd
+ ;;
+ convex-c38)
+ basic_machine=c38-convex
+ basic_os=bsd
+ ;;
+ cray)
+ basic_machine=j90-cray
+ basic_os=unicos
+ ;;
+ crds | unos)
+ basic_machine=m68k-crds
+ basic_os=
+ ;;
+ da30)
+ basic_machine=m68k-da30
+ basic_os=
+ ;;
+ decstation | pmax | pmin | dec3100 | decstatn)
+ basic_machine=mips-dec
+ basic_os=
+ ;;
+ delta88)
+ basic_machine=m88k-motorola
+ basic_os=sysv3
+ ;;
+ dicos)
+ basic_machine=i686-pc
+ basic_os=dicos
+ ;;
+ djgpp)
+ basic_machine=i586-pc
+ basic_os=msdosdjgpp
+ ;;
+ ebmon29k)
+ basic_machine=a29k-amd
+ basic_os=ebmon
+ ;;
+ es1800 | OSE68k | ose68k | ose | OSE)
+ basic_machine=m68k-ericsson
+ basic_os=ose
+ ;;
+ gmicro)
+ basic_machine=tron-gmicro
+ basic_os=sysv
+ ;;
+ go32)
+ basic_machine=i386-pc
+ basic_os=go32
+ ;;
+ h8300hms)
+ basic_machine=h8300-hitachi
+ basic_os=hms
+ ;;
+ h8300xray)
+ basic_machine=h8300-hitachi
+ basic_os=xray
+ ;;
+ h8500hms)
+ basic_machine=h8500-hitachi
+ basic_os=hms
+ ;;
+ harris)
+ basic_machine=m88k-harris
+ basic_os=sysv3
+ ;;
+ hp300 | hp300hpux)
+ basic_machine=m68k-hp
+ basic_os=hpux
+ ;;
+ hp300bsd)
+ basic_machine=m68k-hp
+ basic_os=bsd
+ ;;
+ hppaosf)
+ basic_machine=hppa1.1-hp
+ basic_os=osf
+ ;;
+ hppro)
+ basic_machine=hppa1.1-hp
+ basic_os=proelf
+ ;;
+ i386mach)
+ basic_machine=i386-mach
+ basic_os=mach
+ ;;
+ isi68 | isi)
+ basic_machine=m68k-isi
+ basic_os=sysv
+ ;;
+ m68knommu)
+ basic_machine=m68k-unknown
+ basic_os=linux
+ ;;
+ magnum | m3230)
+ basic_machine=mips-mips
+ basic_os=sysv
+ ;;
+ merlin)
+ basic_machine=ns32k-utek
+ basic_os=sysv
+ ;;
+ mingw64)
+ basic_machine=x86_64-pc
+ basic_os=mingw64
+ ;;
+ mingw32)
+ basic_machine=i686-pc
+ basic_os=mingw32
+ ;;
+ mingw32ce)
+ basic_machine=arm-unknown
+ basic_os=mingw32ce
+ ;;
+ monitor)
+ basic_machine=m68k-rom68k
+ basic_os=coff
+ ;;
+ morphos)
+ basic_machine=powerpc-unknown
+ basic_os=morphos
+ ;;
+ moxiebox)
+ basic_machine=moxie-unknown
+ basic_os=moxiebox
+ ;;
+ msdos)
+ basic_machine=i386-pc
+ basic_os=msdos
+ ;;
+ msys)
+ basic_machine=i686-pc
+ basic_os=msys
+ ;;
+ mvs)
+ basic_machine=i370-ibm
+ basic_os=mvs
+ ;;
+ nacl)
+ basic_machine=le32-unknown
+ basic_os=nacl
+ ;;
+ ncr3000)
+ basic_machine=i486-ncr
+ basic_os=sysv4
+ ;;
+ netbsd386)
+ basic_machine=i386-pc
+ basic_os=netbsd
+ ;;
+ netwinder)
+ basic_machine=armv4l-rebel
+ basic_os=linux
+ ;;
+ news | news700 | news800 | news900)
+ basic_machine=m68k-sony
+ basic_os=newsos
+ ;;
+ news1000)
+ basic_machine=m68030-sony
+ basic_os=newsos
+ ;;
+ necv70)
+ basic_machine=v70-nec
+ basic_os=sysv
+ ;;
+ nh3000)
+ basic_machine=m68k-harris
+ basic_os=cxux
+ ;;
+ nh[45]000)
+ basic_machine=m88k-harris
+ basic_os=cxux
+ ;;
+ nindy960)
+ basic_machine=i960-intel
+ basic_os=nindy
+ ;;
+ mon960)
+ basic_machine=i960-intel
+ basic_os=mon960
+ ;;
+ nonstopux)
+ basic_machine=mips-compaq
+ basic_os=nonstopux
+ ;;
+ os400)
+ basic_machine=powerpc-ibm
+ basic_os=os400
+ ;;
+ OSE68000 | ose68000)
+ basic_machine=m68000-ericsson
+ basic_os=ose
+ ;;
+ os68k)
+ basic_machine=m68k-none
+ basic_os=os68k
+ ;;
+ paragon)
+ basic_machine=i860-intel
+ basic_os=osf
+ ;;
+ parisc)
+ basic_machine=hppa-unknown
+ basic_os=linux
+ ;;
+ psp)
+ basic_machine=mipsallegrexel-sony
+ basic_os=psp
+ ;;
+ pw32)
+ basic_machine=i586-unknown
+ basic_os=pw32
+ ;;
+ rdos | rdos64)
+ basic_machine=x86_64-pc
+ basic_os=rdos
+ ;;
+ rdos32)
+ basic_machine=i386-pc
+ basic_os=rdos
+ ;;
+ rom68k)
+ basic_machine=m68k-rom68k
+ basic_os=coff
+ ;;
+ sa29200)
+ basic_machine=a29k-amd
+ basic_os=udi
+ ;;
+ sei)
+ basic_machine=mips-sei
+ basic_os=seiux
+ ;;
+ sequent)
+ basic_machine=i386-sequent
+ basic_os=
+ ;;
+ sps7)
+ basic_machine=m68k-bull
+ basic_os=sysv2
+ ;;
+ st2000)
+ basic_machine=m68k-tandem
+ basic_os=
+ ;;
+ stratus)
+ basic_machine=i860-stratus
+ basic_os=sysv4
+ ;;
+ sun2)
+ basic_machine=m68000-sun
+ basic_os=
+ ;;
+ sun2os3)
+ basic_machine=m68000-sun
+ basic_os=sunos3
+ ;;
+ sun2os4)
+ basic_machine=m68000-sun
+ basic_os=sunos4
+ ;;
+ sun3)
+ basic_machine=m68k-sun
+ basic_os=
+ ;;
+ sun3os3)
+ basic_machine=m68k-sun
+ basic_os=sunos3
+ ;;
+ sun3os4)
+ basic_machine=m68k-sun
+ basic_os=sunos4
+ ;;
+ sun4)
+ basic_machine=sparc-sun
+ basic_os=
+ ;;
+ sun4os3)
+ basic_machine=sparc-sun
+ basic_os=sunos3
+ ;;
+ sun4os4)
+ basic_machine=sparc-sun
+ basic_os=sunos4
+ ;;
+ sun4sol2)
+ basic_machine=sparc-sun
+ basic_os=solaris2
+ ;;
+ sun386 | sun386i | roadrunner)
+ basic_machine=i386-sun
+ basic_os=
+ ;;
+ sv1)
+ basic_machine=sv1-cray
+ basic_os=unicos
+ ;;
+ symmetry)
+ basic_machine=i386-sequent
+ basic_os=dynix
+ ;;
+ t3e)
+ basic_machine=alphaev5-cray
+ basic_os=unicos
+ ;;
+ t90)
+ basic_machine=t90-cray
+ basic_os=unicos
+ ;;
+ toad1)
+ basic_machine=pdp10-xkl
+ basic_os=tops20
+ ;;
+ tpf)
+ basic_machine=s390x-ibm
+ basic_os=tpf
+ ;;
+ udi29k)
+ basic_machine=a29k-amd
+ basic_os=udi
+ ;;
+ ultra3)
+ basic_machine=a29k-nyu
+ basic_os=sym1
+ ;;
+ v810 | necv810)
+ basic_machine=v810-nec
+ basic_os=none
+ ;;
+ vaxv)
+ basic_machine=vax-dec
+ basic_os=sysv
+ ;;
+ vms)
+ basic_machine=vax-dec
+ basic_os=vms
+ ;;
+ vsta)
+ basic_machine=i386-pc
+ basic_os=vsta
+ ;;
+ vxworks960)
+ basic_machine=i960-wrs
+ basic_os=vxworks
+ ;;
+ vxworks68)
+ basic_machine=m68k-wrs
+ basic_os=vxworks
+ ;;
+ vxworks29k)
+ basic_machine=a29k-wrs
+ basic_os=vxworks
+ ;;
+ xbox)
+ basic_machine=i686-pc
+ basic_os=mingw32
+ ;;
+ ymp)
+ basic_machine=ymp-cray
+ basic_os=unicos
+ ;;
+ *)
+ basic_machine=$1
+ basic_os=
+ ;;
+ esac
;;
esac
-# Decode aliases for certain CPU-COMPANY combinations.
+# Decode 1-component or ad-hoc basic machines
case $basic_machine in
- # Recognize the basic CPU types without company name.
- # Some are omitted here because they have special meanings below.
- 1750a | 580 \
- | a29k \
- | aarch64 | aarch64_be \
- | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
- | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
- | am33_2.0 \
- | arc | arceb \
- | arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \
- | avr | avr32 \
- | ba \
- | be32 | be64 \
- | bfin \
- | c4x | c8051 | clipper \
- | d10v | d30v | dlx | dsp16xx \
- | e2k | epiphany \
- | fido | fr30 | frv | ft32 \
- | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
- | hexagon \
- | i370 | i860 | i960 | ia64 \
- | ip2k | iq2000 \
- | k1om \
- | le32 | le64 \
- | lm32 \
- | m32c | m32r | m32rle | m68000 | m68k | m88k \
- | maxq | mb | microblaze | microblazeel | mcore | mep | metag \
- | mips | mipsbe | mipseb | mipsel | mipsle \
- | mips16 \
- | mips64 | mips64el \
- | mips64octeon | mips64octeonel \
- | mips64orion | mips64orionel \
- | mips64r5900 | mips64r5900el \
- | mips64vr | mips64vrel \
- | mips64vr4100 | mips64vr4100el \
- | mips64vr4300 | mips64vr4300el \
- | mips64vr5000 | mips64vr5000el \
- | mips64vr5900 | mips64vr5900el \
- | mipsisa32 | mipsisa32el \
- | mipsisa32r2 | mipsisa32r2el \
- | mipsisa32r6 | mipsisa32r6el \
- | mipsisa64 | mipsisa64el \
- | mipsisa64r2 | mipsisa64r2el \
- | mipsisa64r6 | mipsisa64r6el \
- | mipsisa64sb1 | mipsisa64sb1el \
- | mipsisa64sr71k | mipsisa64sr71kel \
- | mipsr5900 | mipsr5900el \
- | mipstx39 | mipstx39el \
- | mn10200 | mn10300 \
- | moxie \
- | mt \
- | msp430 \
- | nds32 | nds32le | nds32be \
- | nios | nios2 | nios2eb | nios2el \
- | ns16k | ns32k \
- | open8 | or1k | or1knd | or32 \
- | pdp10 | pdp11 | pj | pjl \
- | powerpc | powerpc64 | powerpc64le | powerpcle \
- | pyramid \
- | riscv32 | riscv64 \
- | rl78 | rx \
- | score \
- | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[234]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
- | sh64 | sh64le \
- | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \
- | sparcv8 | sparcv9 | sparcv9b | sparcv9v \
- | spu \
- | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \
- | ubicom32 \
- | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \
- | visium \
- | we32k \
- | x86 | xc16x | xstormy16 | xtensa \
- | z8k | z80)
- basic_machine=$basic_machine-unknown
- ;;
- c54x)
- basic_machine=tic54x-unknown
- ;;
- c55x)
- basic_machine=tic55x-unknown
- ;;
- c6x)
- basic_machine=tic6x-unknown
- ;;
- leon|leon[3-9])
- basic_machine=sparc-$basic_machine
- ;;
- m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | nvptx | picochip)
- basic_machine=$basic_machine-unknown
- os=-none
+ # Here we handle the default manufacturer of certain CPU types. It is in
+ # some cases the only manufacturer, in others, it is the most popular.
+ w89k)
+ cpu=hppa1.1
+ vendor=winbond
;;
- m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k)
+ op50n)
+ cpu=hppa1.1
+ vendor=oki
;;
- ms1)
- basic_machine=mt-unknown
+ op60c)
+ cpu=hppa1.1
+ vendor=oki
;;
-
- strongarm | thumb | xscale)
- basic_machine=arm-unknown
+ ibm*)
+ cpu=i370
+ vendor=ibm
;;
- xgate)
- basic_machine=$basic_machine-unknown
- os=-none
+ orion105)
+ cpu=clipper
+ vendor=highlevel
;;
- xscaleeb)
- basic_machine=armeb-unknown
+ mac | mpw | mac-mpw)
+ cpu=m68k
+ vendor=apple
;;
-
- xscaleel)
- basic_machine=armel-unknown
+ pmac | pmac-mpw)
+ cpu=powerpc
+ vendor=apple
;;
- # We use `pc' rather than `unknown'
- # because (1) that's what they normally are, and
- # (2) the word "unknown" tends to confuse beginning users.
- i*86 | x86_64)
- basic_machine=$basic_machine-pc
- ;;
- # Object if more than one company name word.
- *-*-*)
- echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
- exit 1
- ;;
- # Recognize the basic CPU types with company name.
- 580-* \
- | a29k-* \
- | aarch64-* | aarch64_be-* \
- | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \
- | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
- | alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \
- | arm-* | armbe-* | armle-* | armeb-* | armv*-* \
- | avr-* | avr32-* \
- | ba-* \
- | be32-* | be64-* \
- | bfin-* | bs2000-* \
- | c[123]* | c30-* | [cjt]90-* | c4x-* \
- | c8051-* | clipper-* | craynv-* | cydra-* \
- | d10v-* | d30v-* | dlx-* \
- | e2k-* | elxsi-* \
- | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \
- | h8300-* | h8500-* \
- | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
- | hexagon-* \
- | i*86-* | i860-* | i960-* | ia64-* \
- | ip2k-* | iq2000-* \
- | k1om-* \
- | le32-* | le64-* \
- | lm32-* \
- | m32c-* | m32r-* | m32rle-* \
- | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
- | m88110-* | m88k-* | maxq-* | mcore-* | metag-* \
- | microblaze-* | microblazeel-* \
- | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
- | mips16-* \
- | mips64-* | mips64el-* \
- | mips64octeon-* | mips64octeonel-* \
- | mips64orion-* | mips64orionel-* \
- | mips64r5900-* | mips64r5900el-* \
- | mips64vr-* | mips64vrel-* \
- | mips64vr4100-* | mips64vr4100el-* \
- | mips64vr4300-* | mips64vr4300el-* \
- | mips64vr5000-* | mips64vr5000el-* \
- | mips64vr5900-* | mips64vr5900el-* \
- | mipsisa32-* | mipsisa32el-* \
- | mipsisa32r2-* | mipsisa32r2el-* \
- | mipsisa32r6-* | mipsisa32r6el-* \
- | mipsisa64-* | mipsisa64el-* \
- | mipsisa64r2-* | mipsisa64r2el-* \
- | mipsisa64r6-* | mipsisa64r6el-* \
- | mipsisa64sb1-* | mipsisa64sb1el-* \
- | mipsisa64sr71k-* | mipsisa64sr71kel-* \
- | mipsr5900-* | mipsr5900el-* \
- | mipstx39-* | mipstx39el-* \
- | mmix-* \
- | mt-* \
- | msp430-* \
- | nds32-* | nds32le-* | nds32be-* \
- | nios-* | nios2-* | nios2eb-* | nios2el-* \
- | none-* | np1-* | ns16k-* | ns32k-* \
- | open8-* \
- | or1k*-* \
- | orion-* \
- | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
- | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \
- | pyramid-* \
- | riscv32-* | riscv64-* \
- | rl78-* | romp-* | rs6000-* | rx-* \
- | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \
- | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
- | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \
- | sparclite-* \
- | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx*-* \
- | tahoe-* \
- | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
- | tile*-* \
- | tron-* \
- | ubicom32-* \
- | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \
- | vax-* \
- | visium-* \
- | we32k-* \
- | x86-* | x86_64-* | xc16x-* | xps100-* \
- | xstormy16-* | xtensa*-* \
- | ymp-* \
- | z8k-* | z80-*)
- ;;
- # Recognize the basic CPU types without company name, with glob match.
- xtensa*)
- basic_machine=$basic_machine-unknown
- ;;
# Recognize the various machine names and aliases which stand
# for a CPU type and a company and sometimes even an OS.
- 386bsd)
- basic_machine=i386-unknown
- os=-bsd
- ;;
3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)
- basic_machine=m68000-att
+ cpu=m68000
+ vendor=att
;;
3b*)
- basic_machine=we32k-att
- ;;
- a29khif)
- basic_machine=a29k-amd
- os=-udi
- ;;
- abacus)
- basic_machine=abacus-unknown
- ;;
- adobe68k)
- basic_machine=m68010-adobe
- os=-scout
- ;;
- alliant | fx80)
- basic_machine=fx80-alliant
- ;;
- altos | altos3068)
- basic_machine=m68k-altos
- ;;
- am29k)
- basic_machine=a29k-none
- os=-bsd
- ;;
- amd64)
- basic_machine=x86_64-pc
- ;;
- amd64-*)
- basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'`
- ;;
- amdahl)
- basic_machine=580-amdahl
- os=-sysv
- ;;
- amiga | amiga-*)
- basic_machine=m68k-unknown
- ;;
- amigaos | amigados)
- basic_machine=m68k-unknown
- os=-amigaos
- ;;
- amigaunix | amix)
- basic_machine=m68k-unknown
- os=-sysv4
- ;;
- apollo68)
- basic_machine=m68k-apollo
- os=-sysv
- ;;
- apollo68bsd)
- basic_machine=m68k-apollo
- os=-bsd
- ;;
- aros)
- basic_machine=i386-pc
- os=-aros
- ;;
- asmjs)
- basic_machine=asmjs-unknown
- ;;
- aux)
- basic_machine=m68k-apple
- os=-aux
- ;;
- balance)
- basic_machine=ns32k-sequent
- os=-dynix
- ;;
- blackfin)
- basic_machine=bfin-unknown
- os=-linux
- ;;
- blackfin-*)
- basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'`
- os=-linux
+ cpu=we32k
+ vendor=att
;;
bluegene*)
- basic_machine=powerpc-ibm
- os=-cnk
- ;;
- c54x-*)
- basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'`
- ;;
- c55x-*)
- basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'`
- ;;
- c6x-*)
- basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'`
- ;;
- c90)
- basic_machine=c90-cray
- os=-unicos
- ;;
- cegcc)
- basic_machine=arm-unknown
- os=-cegcc
- ;;
- convex-c1)
- basic_machine=c1-convex
- os=-bsd
- ;;
- convex-c2)
- basic_machine=c2-convex
- os=-bsd
- ;;
- convex-c32)
- basic_machine=c32-convex
- os=-bsd
- ;;
- convex-c34)
- basic_machine=c34-convex
- os=-bsd
- ;;
- convex-c38)
- basic_machine=c38-convex
- os=-bsd
- ;;
- cray | j90)
- basic_machine=j90-cray
- os=-unicos
- ;;
- craynv)
- basic_machine=craynv-cray
- os=-unicosmp
- ;;
- cr16 | cr16-*)
- basic_machine=cr16-unknown
- os=-elf
- ;;
- crds | unos)
- basic_machine=m68k-crds
- ;;
- crisv32 | crisv32-* | etraxfs*)
- basic_machine=crisv32-axis
- ;;
- cris | cris-* | etrax*)
- basic_machine=cris-axis
- ;;
- crx)
- basic_machine=crx-unknown
- os=-elf
- ;;
- da30 | da30-*)
- basic_machine=m68k-da30
- ;;
- decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn)
- basic_machine=mips-dec
+ cpu=powerpc
+ vendor=ibm
+ basic_os=cnk
;;
decsystem10* | dec10*)
- basic_machine=pdp10-dec
- os=-tops10
+ cpu=pdp10
+ vendor=dec
+ basic_os=tops10
;;
decsystem20* | dec20*)
- basic_machine=pdp10-dec
- os=-tops20
+ cpu=pdp10
+ vendor=dec
+ basic_os=tops20
;;
delta | 3300 | motorola-3300 | motorola-delta \
| 3300-motorola | delta-motorola)
- basic_machine=m68k-motorola
- ;;
- delta88)
- basic_machine=m88k-motorola
- os=-sysv3
- ;;
- dicos)
- basic_machine=i686-pc
- os=-dicos
- ;;
- djgpp)
- basic_machine=i586-pc
- os=-msdosdjgpp
- ;;
- dpx20 | dpx20-*)
- basic_machine=rs6000-bull
- os=-bosx
- ;;
- dpx2* | dpx2*-bull)
- basic_machine=m68k-bull
- os=-sysv3
- ;;
- e500v[12])
- basic_machine=powerpc-unknown
- os=$os"spe"
+ cpu=m68k
+ vendor=motorola
;;
- e500v[12]-*)
- basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
- os=$os"spe"
- ;;
- ebmon29k)
- basic_machine=a29k-amd
- os=-ebmon
- ;;
- elxsi)
- basic_machine=elxsi-elxsi
- os=-bsd
+ dpx2*)
+ cpu=m68k
+ vendor=bull
+ basic_os=sysv3
;;
encore | umax | mmax)
- basic_machine=ns32k-encore
+ cpu=ns32k
+ vendor=encore
;;
- es1800 | OSE68k | ose68k | ose | OSE)
- basic_machine=m68k-ericsson
- os=-ose
+ elxsi)
+ cpu=elxsi
+ vendor=elxsi
+ basic_os=${basic_os:-bsd}
;;
fx2800)
- basic_machine=i860-alliant
+ cpu=i860
+ vendor=alliant
;;
genix)
- basic_machine=ns32k-ns
- ;;
- gmicro)
- basic_machine=tron-gmicro
- os=-sysv
- ;;
- go32)
- basic_machine=i386-pc
- os=-go32
+ cpu=ns32k
+ vendor=ns
;;
h3050r* | hiux*)
- basic_machine=hppa1.1-hitachi
- os=-hiuxwe2
- ;;
- h8300hms)
- basic_machine=h8300-hitachi
- os=-hms
- ;;
- h8300xray)
- basic_machine=h8300-hitachi
- os=-xray
- ;;
- h8500hms)
- basic_machine=h8500-hitachi
- os=-hms
- ;;
- harris)
- basic_machine=m88k-harris
- os=-sysv3
- ;;
- hp300-*)
- basic_machine=m68k-hp
- ;;
- hp300bsd)
- basic_machine=m68k-hp
- os=-bsd
- ;;
- hp300hpux)
- basic_machine=m68k-hp
- os=-hpux
+ cpu=hppa1.1
+ vendor=hitachi
+ basic_os=hiuxwe2
;;
hp3k9[0-9][0-9] | hp9[0-9][0-9])
- basic_machine=hppa1.0-hp
+ cpu=hppa1.0
+ vendor=hp
;;
hp9k2[0-9][0-9] | hp9k31[0-9])
- basic_machine=m68000-hp
+ cpu=m68000
+ vendor=hp
;;
hp9k3[2-9][0-9])
- basic_machine=m68k-hp
+ cpu=m68k
+ vendor=hp
;;
hp9k6[0-9][0-9] | hp6[0-9][0-9])
- basic_machine=hppa1.0-hp
+ cpu=hppa1.0
+ vendor=hp
;;
hp9k7[0-79][0-9] | hp7[0-79][0-9])
- basic_machine=hppa1.1-hp
+ cpu=hppa1.1
+ vendor=hp
;;
hp9k78[0-9] | hp78[0-9])
# FIXME: really hppa2.0-hp
- basic_machine=hppa1.1-hp
+ cpu=hppa1.1
+ vendor=hp
;;
hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893)
# FIXME: really hppa2.0-hp
- basic_machine=hppa1.1-hp
+ cpu=hppa1.1
+ vendor=hp
;;
hp9k8[0-9][13679] | hp8[0-9][13679])
- basic_machine=hppa1.1-hp
+ cpu=hppa1.1
+ vendor=hp
;;
hp9k8[0-9][0-9] | hp8[0-9][0-9])
- basic_machine=hppa1.0-hp
- ;;
- hppa-next)
- os=-nextstep3
- ;;
- hppaosf)
- basic_machine=hppa1.1-hp
- os=-osf
- ;;
- hppro)
- basic_machine=hppa1.1-hp
- os=-proelf
- ;;
- i370-ibm* | ibm*)
- basic_machine=i370-ibm
+ cpu=hppa1.0
+ vendor=hp
;;
i*86v32)
- basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
- os=-sysv32
+ cpu=`echo "$1" | sed -e 's/86.*/86/'`
+ vendor=pc
+ basic_os=sysv32
;;
i*86v4*)
- basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
- os=-sysv4
+ cpu=`echo "$1" | sed -e 's/86.*/86/'`
+ vendor=pc
+ basic_os=sysv4
;;
i*86v)
- basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
- os=-sysv
+ cpu=`echo "$1" | sed -e 's/86.*/86/'`
+ vendor=pc
+ basic_os=sysv
;;
i*86sol2)
- basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
- os=-solaris2
- ;;
- i386mach)
- basic_machine=i386-mach
- os=-mach
+ cpu=`echo "$1" | sed -e 's/86.*/86/'`
+ vendor=pc
+ basic_os=solaris2
;;
- i386-vsta | vsta)
- basic_machine=i386-unknown
- os=-vsta
+ j90 | j90-cray)
+ cpu=j90
+ vendor=cray
+ basic_os=${basic_os:-unicos}
;;
iris | iris4d)
- basic_machine=mips-sgi
- case $os in
- -irix*)
+ cpu=mips
+ vendor=sgi
+ case $basic_os in
+ irix*)
;;
*)
- os=-irix4
+ basic_os=irix4
;;
esac
;;
- isi68 | isi)
- basic_machine=m68k-isi
- os=-sysv
- ;;
- leon-*|leon[3-9]-*)
- basic_machine=sparc-`echo $basic_machine | sed 's/-.*//'`
- ;;
- m68knommu)
- basic_machine=m68k-unknown
- os=-linux
- ;;
- m68knommu-*)
- basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'`
- os=-linux
- ;;
- m88k-omron*)
- basic_machine=m88k-omron
- ;;
- magnum | m3230)
- basic_machine=mips-mips
- os=-sysv
- ;;
- merlin)
- basic_machine=ns32k-utek
- os=-sysv
- ;;
- microblaze*)
- basic_machine=microblaze-xilinx
- ;;
- mingw64)
- basic_machine=x86_64-pc
- os=-mingw64
- ;;
- mingw32)
- basic_machine=i686-pc
- os=-mingw32
- ;;
- mingw32ce)
- basic_machine=arm-unknown
- os=-mingw32ce
- ;;
miniframe)
- basic_machine=m68000-convergent
- ;;
- *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*)
- basic_machine=m68k-atari
- os=-mint
- ;;
- mips3*-*)
- basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`
+ cpu=m68000
+ vendor=convergent
;;
- mips3*)
- basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
- ;;
- monitor)
- basic_machine=m68k-rom68k
- os=-coff
- ;;
- morphos)
- basic_machine=powerpc-unknown
- os=-morphos
- ;;
- moxiebox)
- basic_machine=moxie-unknown
- os=-moxiebox
- ;;
- msdos)
- basic_machine=i386-pc
- os=-msdos
- ;;
- ms1-*)
- basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'`
- ;;
- msys)
- basic_machine=i686-pc
- os=-msys
- ;;
- mvs)
- basic_machine=i370-ibm
- os=-mvs
- ;;
- nacl)
- basic_machine=le32-unknown
- os=-nacl
- ;;
- ncr3000)
- basic_machine=i486-ncr
- os=-sysv4
- ;;
- netbsd386)
- basic_machine=i386-unknown
- os=-netbsd
- ;;
- netwinder)
- basic_machine=armv4l-rebel
- os=-linux
- ;;
- news | news700 | news800 | news900)
- basic_machine=m68k-sony
- os=-newsos
- ;;
- news1000)
- basic_machine=m68030-sony
- os=-newsos
+ *mint | mint[0-9]* | *MiNT | *MiNT[0-9]*)
+ cpu=m68k
+ vendor=atari
+ basic_os=mint
;;
news-3600 | risc-news)
- basic_machine=mips-sony
- os=-newsos
- ;;
- necv70)
- basic_machine=v70-nec
- os=-sysv
- ;;
- next | m*-next )
- basic_machine=m68k-next
- case $os in
- -nextstep* )
+ cpu=mips
+ vendor=sony
+ basic_os=newsos
+ ;;
+ next | m*-next)
+ cpu=m68k
+ vendor=next
+ case $basic_os in
+ openstep*)
+ ;;
+ nextstep*)
;;
- -ns2*)
- os=-nextstep2
+ ns2*)
+ basic_os=nextstep2
;;
*)
- os=-nextstep3
+ basic_os=nextstep3
;;
esac
;;
- nh3000)
- basic_machine=m68k-harris
- os=-cxux
- ;;
- nh[45]000)
- basic_machine=m88k-harris
- os=-cxux
- ;;
- nindy960)
- basic_machine=i960-intel
- os=-nindy
- ;;
- mon960)
- basic_machine=i960-intel
- os=-mon960
- ;;
- nonstopux)
- basic_machine=mips-compaq
- os=-nonstopux
- ;;
np1)
- basic_machine=np1-gould
- ;;
- neo-tandem)
- basic_machine=neo-tandem
- ;;
- nse-tandem)
- basic_machine=nse-tandem
- ;;
- nsr-tandem)
- basic_machine=nsr-tandem
+ cpu=np1
+ vendor=gould
;;
op50n-* | op60c-*)
- basic_machine=hppa1.1-oki
- os=-proelf
- ;;
- openrisc | openrisc-*)
- basic_machine=or32-unknown
- ;;
- os400)
- basic_machine=powerpc-ibm
- os=-os400
- ;;
- OSE68000 | ose68000)
- basic_machine=m68000-ericsson
- os=-ose
- ;;
- os68k)
- basic_machine=m68k-none
- os=-os68k
+ cpu=hppa1.1
+ vendor=oki
+ basic_os=proelf
;;
pa-hitachi)
- basic_machine=hppa1.1-hitachi
- os=-hiuxwe2
- ;;
- paragon)
- basic_machine=i860-intel
- os=-osf
- ;;
- parisc)
- basic_machine=hppa-unknown
- os=-linux
- ;;
- parisc-*)
- basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'`
- os=-linux
+ cpu=hppa1.1
+ vendor=hitachi
+ basic_os=hiuxwe2
;;
pbd)
- basic_machine=sparc-tti
+ cpu=sparc
+ vendor=tti
;;
pbb)
- basic_machine=m68k-tti
- ;;
- pc532 | pc532-*)
- basic_machine=ns32k-pc532
- ;;
- pc98)
- basic_machine=i386-pc
- ;;
- pc98-*)
- basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'`
- ;;
- pentium | p5 | k5 | k6 | nexgen | viac3)
- basic_machine=i586-pc
- ;;
- pentiumpro | p6 | 6x86 | athlon | athlon_*)
- basic_machine=i686-pc
- ;;
- pentiumii | pentium2 | pentiumiii | pentium3)
- basic_machine=i686-pc
+ cpu=m68k
+ vendor=tti
;;
- pentium4)
- basic_machine=i786-pc
- ;;
- pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*)
- basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`
- ;;
- pentiumpro-* | p6-* | 6x86-* | athlon-*)
- basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
- ;;
- pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*)
- basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
- ;;
- pentium4-*)
- basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'`
+ pc532)
+ cpu=ns32k
+ vendor=pc532
;;
pn)
- basic_machine=pn-gould
- ;;
- power) basic_machine=power-ibm
- ;;
- ppc | ppcbe) basic_machine=powerpc-unknown
- ;;
- ppc-* | ppcbe-*)
- basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
- ;;
- ppcle | powerpclittle)
- basic_machine=powerpcle-unknown
- ;;
- ppcle-* | powerpclittle-*)
- basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'`
+ cpu=pn
+ vendor=gould
;;
- ppc64) basic_machine=powerpc64-unknown
- ;;
- ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'`
- ;;
- ppc64le | powerpc64little)
- basic_machine=powerpc64le-unknown
- ;;
- ppc64le-* | powerpc64little-*)
- basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'`
+ power)
+ cpu=power
+ vendor=ibm
;;
ps2)
- basic_machine=i386-ibm
- ;;
- pw32)
- basic_machine=i586-unknown
- os=-pw32
- ;;
- rdos | rdos64)
- basic_machine=x86_64-pc
- os=-rdos
- ;;
- rdos32)
- basic_machine=i386-pc
- os=-rdos
- ;;
- rom68k)
- basic_machine=m68k-rom68k
- os=-coff
+ cpu=i386
+ vendor=ibm
;;
rm[46]00)
- basic_machine=mips-siemens
+ cpu=mips
+ vendor=siemens
;;
rtpc | rtpc-*)
- basic_machine=romp-ibm
- ;;
- s390 | s390-*)
- basic_machine=s390-ibm
- ;;
- s390x | s390x-*)
- basic_machine=s390x-ibm
- ;;
- sa29200)
- basic_machine=a29k-amd
- os=-udi
+ cpu=romp
+ vendor=ibm
;;
- sb1)
- basic_machine=mipsisa64sb1-unknown
+ sde)
+ cpu=mipsisa32
+ vendor=sde
+ basic_os=${basic_os:-elf}
;;
- sb1el)
- basic_machine=mipsisa64sb1el-unknown
+ simso-wrs)
+ cpu=sparclite
+ vendor=wrs
+ basic_os=vxworks
;;
- sde)
- basic_machine=mipsisa32-sde
- os=-elf
+ tower | tower-32)
+ cpu=m68k
+ vendor=ncr
;;
- sei)
- basic_machine=mips-sei
- os=-seiux
+ vpp*|vx|vx-*)
+ cpu=f301
+ vendor=fujitsu
;;
- sequent)
- basic_machine=i386-sequent
+ w65)
+ cpu=w65
+ vendor=wdc
;;
- sh)
- basic_machine=sh-hitachi
- os=-hms
+ w89k-*)
+ cpu=hppa1.1
+ vendor=winbond
+ basic_os=proelf
;;
- sh5el)
- basic_machine=sh5le-unknown
+ none)
+ cpu=none
+ vendor=none
;;
- sh64)
- basic_machine=sh64-unknown
+ leon|leon[3-9])
+ cpu=sparc
+ vendor=$basic_machine
;;
- sparclite-wrs | simso-wrs)
- basic_machine=sparclite-wrs
- os=-vxworks
+ leon-*|leon[3-9]-*)
+ cpu=sparc
+ vendor=`echo "$basic_machine" | sed 's/-.*//'`
;;
- sps7)
- basic_machine=m68k-bull
- os=-sysv2
+
+ *-*)
+ # shellcheck disable=SC2162
+ IFS="-" read cpu vendor <<EOF
+$basic_machine
+EOF
;;
- spur)
- basic_machine=spur-unknown
+ # We use `pc' rather than `unknown'
+ # because (1) that's what they normally are, and
+ # (2) the word "unknown" tends to confuse beginning users.
+ i*86 | x86_64)
+ cpu=$basic_machine
+ vendor=pc
;;
- st2000)
- basic_machine=m68k-tandem
+ # These rules are duplicated from below for sake of the special case above;
+ # i.e. things that normalized to x86 arches should also default to "pc"
+ pc98)
+ cpu=i386
+ vendor=pc
;;
- stratus)
- basic_machine=i860-stratus
- os=-sysv4
+ x64 | amd64)
+ cpu=x86_64
+ vendor=pc
;;
- strongarm-* | thumb-*)
- basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'`
+ # Recognize the basic CPU types without company name.
+ *)
+ cpu=$basic_machine
+ vendor=unknown
;;
- sun2)
- basic_machine=m68000-sun
+esac
+
+unset -v basic_machine
+
+# Decode basic machines in the full and proper CPU-Company form.
+case $cpu-$vendor in
+ # Here we handle the default manufacturer of certain CPU types in canonical form. It is in
+ # some cases the only manufacturer, in others, it is the most popular.
+ craynv-unknown)
+ vendor=cray
+ basic_os=${basic_os:-unicosmp}
;;
- sun2os3)
- basic_machine=m68000-sun
- os=-sunos3
+ c90-unknown | c90-cray)
+ vendor=cray
+ basic_os=${Basic_os:-unicos}
;;
- sun2os4)
- basic_machine=m68000-sun
- os=-sunos4
+ fx80-unknown)
+ vendor=alliant
;;
- sun3os3)
- basic_machine=m68k-sun
- os=-sunos3
+ romp-unknown)
+ vendor=ibm
;;
- sun3os4)
- basic_machine=m68k-sun
- os=-sunos4
+ mmix-unknown)
+ vendor=knuth
;;
- sun4os3)
- basic_machine=sparc-sun
- os=-sunos3
+ microblaze-unknown | microblazeel-unknown)
+ vendor=xilinx
;;
- sun4os4)
- basic_machine=sparc-sun
- os=-sunos4
+ rs6000-unknown)
+ vendor=ibm
;;
- sun4sol2)
- basic_machine=sparc-sun
- os=-solaris2
+ vax-unknown)
+ vendor=dec
;;
- sun3 | sun3-*)
- basic_machine=m68k-sun
+ pdp11-unknown)
+ vendor=dec
;;
- sun4)
- basic_machine=sparc-sun
+ we32k-unknown)
+ vendor=att
;;
- sun386 | sun386i | roadrunner)
- basic_machine=i386-sun
+ cydra-unknown)
+ vendor=cydrome
;;
- sv1)
- basic_machine=sv1-cray
- os=-unicos
+ i370-ibm*)
+ vendor=ibm
;;
- symmetry)
- basic_machine=i386-sequent
- os=-dynix
+ orion-unknown)
+ vendor=highlevel
;;
- t3e)
- basic_machine=alphaev5-cray
- os=-unicos
+ xps-unknown | xps100-unknown)
+ cpu=xps100
+ vendor=honeywell
;;
- t90)
- basic_machine=t90-cray
- os=-unicos
+
+ # Here we normalize CPU types with a missing or matching vendor
+ dpx20-unknown | dpx20-bull)
+ cpu=rs6000
+ vendor=bull
+ basic_os=${basic_os:-bosx}
;;
- tile*)
- basic_machine=$basic_machine-unknown
- os=-linux-gnu
+
+ # Here we normalize CPU types irrespective of the vendor
+ amd64-*)
+ cpu=x86_64
;;
- tx39)
- basic_machine=mipstx39-unknown
+ blackfin-*)
+ cpu=bfin
+ basic_os=linux
;;
- tx39el)
- basic_machine=mipstx39el-unknown
+ c54x-*)
+ cpu=tic54x
;;
- toad1)
- basic_machine=pdp10-xkl
- os=-tops20
+ c55x-*)
+ cpu=tic55x
;;
- tower | tower-32)
- basic_machine=m68k-ncr
+ c6x-*)
+ cpu=tic6x
;;
- tpf)
- basic_machine=s390x-ibm
- os=-tpf
+ e500v[12]-*)
+ cpu=powerpc
+ basic_os=${basic_os}"spe"
;;
- udi29k)
- basic_machine=a29k-amd
- os=-udi
+ mips3*-*)
+ cpu=mips64
;;
- ultra3)
- basic_machine=a29k-nyu
- os=-sym1
+ ms1-*)
+ cpu=mt
;;
- v810 | necv810)
- basic_machine=v810-nec
- os=-none
+ m68knommu-*)
+ cpu=m68k
+ basic_os=linux
;;
- vaxv)
- basic_machine=vax-dec
- os=-sysv
+ m9s12z-* | m68hcs12z-* | hcs12z-* | s12z-*)
+ cpu=s12z
;;
- vms)
- basic_machine=vax-dec
- os=-vms
+ openrisc-*)
+ cpu=or32
;;
- vpp*|vx|vx-*)
- basic_machine=f301-fujitsu
+ parisc-*)
+ cpu=hppa
+ basic_os=linux
;;
- vxworks960)
- basic_machine=i960-wrs
- os=-vxworks
+ pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*)
+ cpu=i586
;;
- vxworks68)
- basic_machine=m68k-wrs
- os=-vxworks
+ pentiumpro-* | p6-* | 6x86-* | athlon-* | athalon_*-*)
+ cpu=i686
;;
- vxworks29k)
- basic_machine=a29k-wrs
- os=-vxworks
+ pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*)
+ cpu=i686
;;
- w65*)
- basic_machine=w65-wdc
- os=-none
+ pentium4-*)
+ cpu=i786
;;
- w89k-*)
- basic_machine=hppa1.1-winbond
- os=-proelf
+ pc98-*)
+ cpu=i386
;;
- xbox)
- basic_machine=i686-pc
- os=-mingw32
+ ppc-* | ppcbe-*)
+ cpu=powerpc
;;
- xps | xps100)
- basic_machine=xps100-honeywell
+ ppcle-* | powerpclittle-*)
+ cpu=powerpcle
;;
- xscale-* | xscalee[bl]-*)
- basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'`
+ ppc64-*)
+ cpu=powerpc64
;;
- ymp)
- basic_machine=ymp-cray
- os=-unicos
+ ppc64le-* | powerpc64little-*)
+ cpu=powerpc64le
;;
- z8k-*-coff)
- basic_machine=z8k-unknown
- os=-sim
+ sb1-*)
+ cpu=mipsisa64sb1
;;
- z80-*-coff)
- basic_machine=z80-unknown
- os=-sim
+ sb1el-*)
+ cpu=mipsisa64sb1el
;;
- none)
- basic_machine=none-none
- os=-none
+ sh5e[lb]-*)
+ cpu=`echo "$cpu" | sed 's/^\(sh.\)e\(.\)$/\1\2e/'`
;;
-
-# Here we handle the default manufacturer of certain CPU types. It is in
-# some cases the only manufacturer, in others, it is the most popular.
- w89k)
- basic_machine=hppa1.1-winbond
+ spur-*)
+ cpu=spur
;;
- op50n)
- basic_machine=hppa1.1-oki
+ strongarm-* | thumb-*)
+ cpu=arm
;;
- op60c)
- basic_machine=hppa1.1-oki
+ tx39-*)
+ cpu=mipstx39
;;
- romp)
- basic_machine=romp-ibm
+ tx39el-*)
+ cpu=mipstx39el
;;
- mmix)
- basic_machine=mmix-knuth
+ x64-*)
+ cpu=x86_64
;;
- rs6000)
- basic_machine=rs6000-ibm
+ xscale-* | xscalee[bl]-*)
+ cpu=`echo "$cpu" | sed 's/^xscale/arm/'`
;;
- vax)
- basic_machine=vax-dec
+ arm64-*)
+ cpu=aarch64
;;
- pdp10)
- # there are many clones, so DEC is not a safe bet
- basic_machine=pdp10-unknown
+
+ # Recognize the canonical CPU Types that limit and/or modify the
+ # company names they are paired with.
+ cr16-*)
+ basic_os=${basic_os:-elf}
;;
- pdp11)
- basic_machine=pdp11-dec
+ crisv32-* | etraxfs*-*)
+ cpu=crisv32
+ vendor=axis
;;
- we32k)
- basic_machine=we32k-att
+ cris-* | etrax*-*)
+ cpu=cris
+ vendor=axis
;;
- sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele)
- basic_machine=sh-unknown
+ crx-*)
+ basic_os=${basic_os:-elf}
;;
- sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v)
- basic_machine=sparc-sun
+ neo-tandem)
+ cpu=neo
+ vendor=tandem
;;
- cydra)
- basic_machine=cydra-cydrome
+ nse-tandem)
+ cpu=nse
+ vendor=tandem
;;
- orion)
- basic_machine=orion-highlevel
+ nsr-tandem)
+ cpu=nsr
+ vendor=tandem
;;
- orion105)
- basic_machine=clipper-highlevel
+ nsv-tandem)
+ cpu=nsv
+ vendor=tandem
;;
- mac | mpw | mac-mpw)
- basic_machine=m68k-apple
+ nsx-tandem)
+ cpu=nsx
+ vendor=tandem
;;
- pmac | pmac-mpw)
- basic_machine=powerpc-apple
+ mipsallegrexel-sony)
+ cpu=mipsallegrexel
+ vendor=sony
;;
- *-unknown)
- # Make sure to match an already-canonicalized machine name.
+ tile*-*)
+ basic_os=${basic_os:-linux-gnu}
;;
+
*)
- echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
- exit 1
+ # Recognize the canonical CPU types that are allowed with any
+ # company name.
+ case $cpu in
+ 1750a | 580 \
+ | a29k \
+ | aarch64 | aarch64_be \
+ | abacus \
+ | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] \
+ | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] \
+ | alphapca5[67] | alpha64pca5[67] \
+ | am33_2.0 \
+ | amdgcn \
+ | arc | arceb \
+ | arm | arm[lb]e | arme[lb] | armv* \
+ | avr | avr32 \
+ | asmjs \
+ | ba \
+ | be32 | be64 \
+ | bfin | bpf | bs2000 \
+ | c[123]* | c30 | [cjt]90 | c4x \
+ | c8051 | clipper | craynv | csky | cydra \
+ | d10v | d30v | dlx | dsp16xx \
+ | e2k | elxsi | epiphany \
+ | f30[01] | f700 | fido | fr30 | frv | ft32 | fx80 \
+ | h8300 | h8500 \
+ | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
+ | hexagon \
+ | i370 | i*86 | i860 | i960 | ia16 | ia64 \
+ | ip2k | iq2000 \
+ | k1om \
+ | le32 | le64 \
+ | lm32 \
+ | m32c | m32r | m32rle \
+ | m5200 | m68000 | m680[012346]0 | m68360 | m683?2 | m68k \
+ | m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x \
+ | m88110 | m88k | maxq | mb | mcore | mep | metag \
+ | microblaze | microblazeel \
+ | mips | mipsbe | mipseb | mipsel | mipsle \
+ | mips16 \
+ | mips64 | mips64eb | mips64el \
+ | mips64octeon | mips64octeonel \
+ | mips64orion | mips64orionel \
+ | mips64r5900 | mips64r5900el \
+ | mips64vr | mips64vrel \
+ | mips64vr4100 | mips64vr4100el \
+ | mips64vr4300 | mips64vr4300el \
+ | mips64vr5000 | mips64vr5000el \
+ | mips64vr5900 | mips64vr5900el \
+ | mipsisa32 | mipsisa32el \
+ | mipsisa32r2 | mipsisa32r2el \
+ | mipsisa32r6 | mipsisa32r6el \
+ | mipsisa64 | mipsisa64el \
+ | mipsisa64r2 | mipsisa64r2el \
+ | mipsisa64r6 | mipsisa64r6el \
+ | mipsisa64sb1 | mipsisa64sb1el \
+ | mipsisa64sr71k | mipsisa64sr71kel \
+ | mipsr5900 | mipsr5900el \
+ | mipstx39 | mipstx39el \
+ | mmix \
+ | mn10200 | mn10300 \
+ | moxie \
+ | mt \
+ | msp430 \
+ | nds32 | nds32le | nds32be \
+ | nfp \
+ | nios | nios2 | nios2eb | nios2el \
+ | none | np1 | ns16k | ns32k | nvptx \
+ | open8 \
+ | or1k* \
+ | or32 \
+ | orion \
+ | picochip \
+ | pdp10 | pdp11 | pj | pjl | pn | power \
+ | powerpc | powerpc64 | powerpc64le | powerpcle | powerpcspe \
+ | pru \
+ | pyramid \
+ | riscv | riscv32 | riscv64 \
+ | rl78 | romp | rs6000 | rx \
+ | s390 | s390x \
+ | score \
+ | sh | shl \
+ | sh[1234] | sh[24]a | sh[24]ae[lb] | sh[23]e | she[lb] | sh[lb]e \
+ | sh[1234]e[lb] | sh[12345][lb]e | sh[23]ele | sh64 | sh64le \
+ | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet \
+ | sparclite \
+ | sparcv8 | sparcv9 | sparcv9b | sparcv9v | sv1 | sx* \
+ | spu \
+ | tahoe \
+ | tic30 | tic4x | tic54x | tic55x | tic6x | tic80 \
+ | tron \
+ | ubicom32 \
+ | v70 | v850 | v850e | v850e1 | v850es | v850e2 | v850e2v3 \
+ | vax \
+ | visium \
+ | w65 \
+ | wasm32 | wasm64 \
+ | we32k \
+ | x86 | x86_64 | xc16x | xgate | xps100 \
+ | xstormy16 | xtensa* \
+ | ymp \
+ | z8k | z80)
+ ;;
+
+ *)
+ echo Invalid configuration \`"$1"\': machine \`"$cpu-$vendor"\' not recognized 1>&2
+ exit 1
+ ;;
+ esac
;;
esac
# Here we canonicalize certain aliases for manufacturers.
-case $basic_machine in
- *-digital*)
- basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'`
+case $vendor in
+ digital*)
+ vendor=dec
;;
- *-commodore*)
- basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'`
+ commodore*)
+ vendor=cbm
;;
*)
;;
@@ -1353,203 +1278,215 @@ esac
# Decode manufacturer-specific aliases for certain operating systems.
-if [ x"$os" != x"" ]
+if [ x$basic_os != x ]
then
-case $os in
- # First match some system type aliases
- # that might get confused with valid system types.
- # -solaris* is a basic system type, with this one exception.
- -auroraux)
- os=-auroraux
+
+# First recognize some ad-hoc caes, or perhaps split kernel-os, or else just
+# set os.
+case $basic_os in
+ gnu/linux*)
+ kernel=linux
+ os=`echo $basic_os | sed -e 's|gnu/linux|gnu|'`
+ ;;
+ nto-qnx*)
+ kernel=nto
+ os=`echo $basic_os | sed -e 's|nto-qnx|qnx|'`
+ ;;
+ *-*)
+ # shellcheck disable=SC2162
+ IFS="-" read kernel os <<EOF
+$basic_os
+EOF
+ ;;
+ # Default OS when just kernel was specified
+ nto*)
+ kernel=nto
+ os=`echo $basic_os | sed -e 's|nto|qnx|'`
+ ;;
+ linux*)
+ kernel=linux
+ os=`echo $basic_os | sed -e 's|linux|gnu|'`
;;
- -solaris1 | -solaris1.*)
- os=`echo $os | sed -e 's|solaris1|sunos4|'`
+ *)
+ kernel=
+ os=$basic_os
;;
- -solaris)
- os=-solaris2
+esac
+
+# Now, normalize the OS (knowing we just have one component, it's not a kernel,
+# etc.)
+case $os in
+ # First match some system type aliases that might get confused
+ # with valid system types.
+ # solaris* is a basic system type, with this one exception.
+ auroraux)
+ os=auroraux
;;
- -svr4*)
- os=-sysv4
+ bluegene*)
+ os=cnk
;;
- -unixware*)
- os=-sysv4.2uw
+ solaris1 | solaris1.*)
+ os=`echo $os | sed -e 's|solaris1|sunos4|'`
;;
- -gnu/linux*)
- os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'`
+ solaris)
+ os=solaris2
;;
- # First accept the basic system types.
- # The portable systems comes first.
- # Each alternative MUST END IN A *, to match a version number.
- # -sysv* is not here because it comes later, after sysvr4.
- -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
- | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\
- | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \
- | -sym* | -kopensolaris* | -plan9* \
- | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
- | -aos* | -aros* | -cloudabi* | -sortix* \
- | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
- | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
- | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \
- | -bitrig* | -openbsd* | -solidbsd* | -libertybsd* \
- | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \
- | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
- | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
- | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
- | -chorusos* | -chorusrdb* | -cegcc* \
- | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
- | -midipix* | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \
- | -linux-newlib* | -linux-musl* | -linux-uclibc* \
- | -uxpv* | -beos* | -mpeix* | -udk* | -moxiebox* \
- | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
- | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
- | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
- | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
- | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
- | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
- | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* \
- | -onefs* | -tirtos* | -phoenix*)
- # Remember, each alternative MUST END IN *, to match a version number.
- ;;
- -qnx*)
- case $basic_machine in
- x86-* | i*86-*)
- ;;
- *)
- os=-nto$os
- ;;
- esac
+ unixware*)
+ os=sysv4.2uw
;;
- -nto-qnx*)
+ # es1800 is here to avoid being matched by es* (a different OS)
+ es1800*)
+ os=ose
;;
- -nto*)
- os=`echo $os | sed -e 's|nto|nto-qnx|'`
+ # Some version numbers need modification
+ chorusos*)
+ os=chorusos
;;
- -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \
- | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \
- | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*)
+ isc)
+ os=isc2.2
;;
- -mac*)
- os=`echo $os | sed -e 's|mac|macos|'`
+ sco6)
+ os=sco5v6
;;
- -linux-dietlibc)
- os=-linux-dietlibc
+ sco5)
+ os=sco3.2v5
;;
- -linux*)
- os=`echo $os | sed -e 's|linux|linux-gnu|'`
+ sco4)
+ os=sco3.2v4
;;
- -sunos5*)
- os=`echo $os | sed -e 's|sunos5|solaris2|'`
+ sco3.2.[4-9]*)
+ os=`echo $os | sed -e 's/sco3.2./sco3.2v/'`
;;
- -sunos6*)
- os=`echo $os | sed -e 's|sunos6|solaris3|'`
+ sco*v* | scout)
+ # Don't match below
;;
- -opened*)
- os=-openedition
+ sco*)
+ os=sco3.2v2
;;
- -os400*)
- os=-os400
+ psos*)
+ os=psos
;;
- -wince*)
- os=-wince
+ qnx*)
+ case $cpu in
+ x86 | i*86)
+ ;;
+ *)
+ os=nto-$os
+ ;;
+ esac
;;
- -osfrose*)
- os=-osfrose
+ hiux*)
+ os=hiuxwe2
;;
- -osf*)
- os=-osf
+ lynx*178)
+ os=lynxos178
;;
- -utek*)
- os=-bsd
+ lynx*5)
+ os=lynxos5
;;
- -dynix*)
- os=-bsd
+ lynxos*)
+ # don't get caught up in next wildcard
;;
- -acis*)
- os=-aos
+ lynx*)
+ os=lynxos
;;
- -atheos*)
- os=-atheos
+ mac[0-9]*)
+ os=`echo "$os" | sed -e 's|mac|macos|'`
;;
- -syllable*)
- os=-syllable
+ opened*)
+ os=openedition
;;
- -386bsd)
- os=-bsd
+ os400*)
+ os=os400
;;
- -ctix* | -uts*)
- os=-sysv
+ sunos5*)
+ os=`echo "$os" | sed -e 's|sunos5|solaris2|'`
;;
- -nova*)
- os=-rtmk-nova
+ sunos6*)
+ os=`echo "$os" | sed -e 's|sunos6|solaris3|'`
;;
- -ns2 )
- os=-nextstep2
+ wince*)
+ os=wince
;;
- -nsk*)
- os=-nsk
+ utek*)
+ os=bsd
;;
- # Preserve the version number of sinix5.
- -sinix5.*)
- os=`echo $os | sed -e 's|sinix|sysv|'`
+ dynix*)
+ os=bsd
;;
- -sinix*)
- os=-sysv4
+ acis*)
+ os=aos
;;
- -tpf*)
- os=-tpf
+ atheos*)
+ os=atheos
;;
- -triton*)
- os=-sysv3
+ syllable*)
+ os=syllable
;;
- -oss*)
- os=-sysv3
+ 386bsd)
+ os=bsd
;;
- -svr4)
- os=-sysv4
+ ctix* | uts*)
+ os=sysv
;;
- -svr3)
- os=-sysv3
+ nova*)
+ os=rtmk-nova
;;
- -sysvr4)
- os=-sysv4
+ ns2)
+ os=nextstep2
;;
- # This must come after -sysvr4.
- -sysv*)
+ # Preserve the version number of sinix5.
+ sinix5.*)
+ os=`echo $os | sed -e 's|sinix|sysv|'`
;;
- -ose*)
- os=-ose
+ sinix*)
+ os=sysv4
;;
- -es1800*)
- os=-ose
+ tpf*)
+ os=tpf
;;
- -xenix)
- os=-xenix
+ triton*)
+ os=sysv3
;;
- -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
- os=-mint
+ oss*)
+ os=sysv3
;;
- -aros*)
- os=-aros
+ svr4*)
+ os=sysv4
;;
- -zvmoe)
- os=-zvmoe
+ svr3)
+ os=sysv3
;;
- -dicos*)
- os=-dicos
+ sysvr4)
+ os=sysv4
;;
- -nacl*)
+ ose*)
+ os=ose
;;
- -ios)
+ *mint | mint[0-9]* | *MiNT | MiNT[0-9]*)
+ os=mint
;;
- -none)
+ dicos*)
+ os=dicos
+ ;;
+ pikeos*)
+ # Until real need of OS specific support for
+ # particular features comes up, bare metal
+ # configurations are quite functional.
+ case $cpu in
+ arm*)
+ os=eabi
+ ;;
+ *)
+ os=elf
+ ;;
+ esac
;;
*)
- # Get rid of the `-' at the beginning of $os.
- os=`echo $os | sed 's/[^-]*-//'`
- echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2
- exit 1
+ # No normalization, but not necessarily accepted, that comes below.
;;
esac
+
else
# Here we handle the default operating systems that come with various machines.
@@ -1562,261 +1499,352 @@ else
# will signal an error saying that MANUFACTURER isn't an operating
# system, and we'll never get to this point.
-case $basic_machine in
+kernel=
+case $cpu-$vendor in
score-*)
- os=-elf
+ os=elf
;;
spu-*)
- os=-elf
+ os=elf
;;
*-acorn)
- os=-riscix1.2
+ os=riscix1.2
;;
arm*-rebel)
- os=-linux
+ kernel=linux
+ os=gnu
;;
arm*-semi)
- os=-aout
+ os=aout
;;
c4x-* | tic4x-*)
- os=-coff
+ os=coff
;;
c8051-*)
- os=-elf
+ os=elf
+ ;;
+ clipper-intergraph)
+ os=clix
;;
hexagon-*)
- os=-elf
+ os=elf
;;
tic54x-*)
- os=-coff
+ os=coff
;;
tic55x-*)
- os=-coff
+ os=coff
;;
tic6x-*)
- os=-coff
+ os=coff
;;
# This must come before the *-dec entry.
pdp10-*)
- os=-tops20
+ os=tops20
;;
pdp11-*)
- os=-none
+ os=none
;;
*-dec | vax-*)
- os=-ultrix4.2
+ os=ultrix4.2
;;
m68*-apollo)
- os=-domain
+ os=domain
;;
i386-sun)
- os=-sunos4.0.2
+ os=sunos4.0.2
;;
m68000-sun)
- os=-sunos3
+ os=sunos3
;;
m68*-cisco)
- os=-aout
+ os=aout
;;
mep-*)
- os=-elf
+ os=elf
;;
mips*-cisco)
- os=-elf
+ os=elf
;;
mips*-*)
- os=-elf
+ os=elf
;;
or32-*)
- os=-coff
+ os=coff
;;
*-tti) # must be before sparc entry or we get the wrong os.
- os=-sysv3
+ os=sysv3
;;
sparc-* | *-sun)
- os=-sunos4.1.1
+ os=sunos4.1.1
;;
- *-be)
- os=-beos
+ pru-*)
+ os=elf
;;
- *-haiku)
- os=-haiku
+ *-be)
+ os=beos
;;
*-ibm)
- os=-aix
+ os=aix
;;
*-knuth)
- os=-mmixware
+ os=mmixware
;;
*-wec)
- os=-proelf
+ os=proelf
;;
*-winbond)
- os=-proelf
+ os=proelf
;;
*-oki)
- os=-proelf
+ os=proelf
;;
*-hp)
- os=-hpux
+ os=hpux
;;
*-hitachi)
- os=-hiux
+ os=hiux
;;
i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent)
- os=-sysv
+ os=sysv
;;
*-cbm)
- os=-amigaos
+ os=amigaos
;;
*-dg)
- os=-dgux
+ os=dgux
;;
*-dolphin)
- os=-sysv3
+ os=sysv3
;;
m68k-ccur)
- os=-rtu
+ os=rtu
;;
m88k-omron*)
- os=-luna
+ os=luna
;;
- *-next )
- os=-nextstep
+ *-next)
+ os=nextstep
;;
*-sequent)
- os=-ptx
+ os=ptx
;;
*-crds)
- os=-unos
+ os=unos
;;
*-ns)
- os=-genix
+ os=genix
;;
i370-*)
- os=-mvs
- ;;
- *-next)
- os=-nextstep3
+ os=mvs
;;
*-gould)
- os=-sysv
+ os=sysv
;;
*-highlevel)
- os=-bsd
+ os=bsd
;;
*-encore)
- os=-bsd
+ os=bsd
;;
*-sgi)
- os=-irix
+ os=irix
;;
*-siemens)
- os=-sysv4
+ os=sysv4
;;
*-masscomp)
- os=-rtu
+ os=rtu
;;
f30[01]-fujitsu | f700-fujitsu)
- os=-uxpv
+ os=uxpv
;;
*-rom68k)
- os=-coff
+ os=coff
;;
*-*bug)
- os=-coff
+ os=coff
;;
*-apple)
- os=-macos
+ os=macos
;;
*-atari*)
- os=-mint
+ os=mint
+ ;;
+ *-wrs)
+ os=vxworks
;;
*)
- os=-none
+ os=none
;;
esac
+
fi
+# Now, validate our (potentially fixed-up) OS.
+case $os in
+ # Sometimes we do "kernel-abi", so those need to count as OSes.
+ musl* | newlib* | uclibc*)
+ ;;
+ # Likewise for "kernel-libc"
+ eabi | eabihf | gnueabi | gnueabihf)
+ ;;
+ # Now accept the basic system types.
+ # The portable systems comes first.
+ # Each alternative MUST end in a * to match a version number.
+ gnu* | android* | bsd* | mach* | minix* | genix* | ultrix* | irix* \
+ | *vms* | esix* | aix* | cnk* | sunos | sunos[34]* \
+ | hpux* | unos* | osf* | luna* | dgux* | auroraux* | solaris* \
+ | sym* | plan9* | psp* | sim* | xray* | os68k* | v88r* \
+ | hiux* | abug | nacl* | netware* | windows* \
+ | os9* | macos* | osx* | ios* \
+ | mpw* | magic* | mmixware* | mon960* | lnews* \
+ | amigaos* | amigados* | msdos* | newsos* | unicos* | aof* \
+ | aos* | aros* | cloudabi* | sortix* | twizzler* \
+ | nindy* | vxsim* | vxworks* | ebmon* | hms* | mvs* \
+ | clix* | riscos* | uniplus* | iris* | isc* | rtu* | xenix* \
+ | mirbsd* | netbsd* | dicos* | openedition* | ose* \
+ | bitrig* | openbsd* | solidbsd* | libertybsd* | os108* \
+ | ekkobsd* | freebsd* | riscix* | lynxos* | os400* \
+ | bosx* | nextstep* | cxux* | aout* | elf* | oabi* \
+ | ptx* | coff* | ecoff* | winnt* | domain* | vsta* \
+ | udi* | lites* | ieee* | go32* | aux* | hcos* \
+ | chorusrdb* | cegcc* | glidix* \
+ | cygwin* | msys* | pe* | moss* | proelf* | rtems* \
+ | midipix* | mingw32* | mingw64* | mint* \
+ | uxpv* | beos* | mpeix* | udk* | moxiebox* \
+ | interix* | uwin* | mks* | rhapsody* | darwin* \
+ | openstep* | oskit* | conix* | pw32* | nonstopux* \
+ | storm-chaos* | tops10* | tenex* | tops20* | its* \
+ | os2* | vos* | palmos* | uclinux* | nucleus* | morphos* \
+ | scout* | superux* | sysv* | rtmk* | tpf* | windiss* \
+ | powermax* | dnix* | nx6 | nx7 | sei* | dragonfly* \
+ | skyos* | haiku* | rdos* | toppers* | drops* | es* \
+ | onefs* | tirtos* | phoenix* | fuchsia* | redox* | bme* \
+ | midnightbsd* | amdhsa* | unleashed* | emscripten* | wasi* \
+ | nsk* | powerunix* | genode* | zvmoe* )
+ ;;
+ # This one is extra strict with allowed versions
+ sco3.2v2 | sco3.2v[4-9]* | sco5v6*)
+ # Don't forget version if it is 3.2v4 or newer.
+ ;;
+ none)
+ ;;
+ *)
+ echo Invalid configuration \`"$1"\': OS \`"$os"\' not recognized 1>&2
+ exit 1
+ ;;
+esac
+
+# As a final step for OS-related things, validate the OS-kernel combination
+# (given a valid OS), if there is a kernel.
+case $kernel-$os in
+ linux-gnu* | linux-dietlibc* | linux-android* | linux-newlib* | linux-musl* | linux-uclibc* )
+ ;;
+ -dietlibc* | -newlib* | -musl* | -uclibc* )
+ # These are just libc implementations, not actual OSes, and thus
+ # require a kernel.
+ echo "Invalid configuration \`$1': libc \`$os' needs explicit kernel." 1>&2
+ exit 1
+ ;;
+ kfreebsd*-gnu* | kopensolaris*-gnu*)
+ ;;
+ nto-qnx*)
+ ;;
+ *-eabi* | *-gnueabi*)
+ ;;
+ -*)
+ # Blank kernel with real OS is always fine.
+ ;;
+ *-*)
+ echo "Invalid configuration \`$1': Kernel \`$kernel' not known to work with OS \`$os'." 1>&2
+ exit 1
+ ;;
+esac
+
# Here we handle the case where we know the os, and the CPU type, but not the
# manufacturer. We pick the logical manufacturer.
-vendor=unknown
-case $basic_machine in
- *-unknown)
- case $os in
- -riscix*)
+case $vendor in
+ unknown)
+ case $cpu-$os in
+ *-riscix*)
vendor=acorn
;;
- -sunos*)
+ *-sunos*)
vendor=sun
;;
- -cnk*|-aix*)
+ *-cnk* | *-aix*)
vendor=ibm
;;
- -beos*)
+ *-beos*)
vendor=be
;;
- -hpux*)
+ *-hpux*)
vendor=hp
;;
- -mpeix*)
+ *-mpeix*)
vendor=hp
;;
- -hiux*)
+ *-hiux*)
vendor=hitachi
;;
- -unos*)
+ *-unos*)
vendor=crds
;;
- -dgux*)
+ *-dgux*)
vendor=dg
;;
- -luna*)
+ *-luna*)
vendor=omron
;;
- -genix*)
+ *-genix*)
vendor=ns
;;
- -mvs* | -opened*)
+ *-clix*)
+ vendor=intergraph
+ ;;
+ *-mvs* | *-opened*)
+ vendor=ibm
+ ;;
+ *-os400*)
vendor=ibm
;;
- -os400*)
+ s390-* | s390x-*)
vendor=ibm
;;
- -ptx*)
+ *-ptx*)
vendor=sequent
;;
- -tpf*)
+ *-tpf*)
vendor=ibm
;;
- -vxsim* | -vxworks* | -windiss*)
+ *-vxsim* | *-vxworks* | *-windiss*)
vendor=wrs
;;
- -aux*)
+ *-aux*)
vendor=apple
;;
- -hms*)
+ *-hms*)
vendor=hitachi
;;
- -mpw* | -macos*)
+ *-mpw* | *-macos*)
vendor=apple
;;
- -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+ *-*mint | *-mint[0-9]* | *-*MiNT | *-MiNT[0-9]*)
vendor=atari
;;
- -vos*)
+ *-vos*)
vendor=stratus
;;
esac
- basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"`
;;
esac
-echo $basic_machine$os
+echo "$cpu-$vendor-${kernel:+$kernel-}$os"
exit
# Local variables:
-# eval: (add-hook 'write-file-hooks 'time-stamp)
+# eval: (add-hook 'before-save-hook 'time-stamp)
# time-stamp-start: "timestamp='"
# time-stamp-format: "%:y-%02m-%02d"
# time-stamp-end: "'"
diff --git a/contrib/unbound/configure b/contrib/unbound/configure
index bdec1f0024c7..ed66e853047d 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.10.1.
+# Generated by GNU Autoconf 2.69 for unbound 1.11.0.
#
# Report bugs to <unbound-bugs@nlnetlabs.nl or https://github.com/NLnetLabs/unbound/issues>.
#
@@ -591,8 +591,8 @@ MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='unbound'
PACKAGE_TARNAME='unbound'
-PACKAGE_VERSION='1.10.1'
-PACKAGE_STRING='unbound 1.10.1'
+PACKAGE_VERSION='1.11.0'
+PACKAGE_STRING='unbound 1.11.0'
PACKAGE_BUGREPORT='unbound-bugs@nlnetlabs.nl or https://github.com/NLnetLabs/unbound/issues'
PACKAGE_URL=''
@@ -649,6 +649,7 @@ ENABLE_DNSCRYPT
ENABLE_DNSCRYPT_XCHACHA20
DNSTAP_OBJ
DNSTAP_SRC
+DNSTAP_SOCKET_PATH
opt_dnstap_socket_path
ENABLE_DNSTAP
PROTOC_C
@@ -699,6 +700,10 @@ PYTHON_LDFLAGS
PYTHON_CPPFLAGS
PYTHON
PYTHON_VERSION
+DYNLIBMOD_EXTRALIBS
+DYNLIBMOD_HEADER
+DYNLIBMOD_OBJ
+WITH_DYNLIBMODULE
PTHREAD_CFLAGS_ONLY
PTHREAD_CFLAGS
PTHREAD_LIBS
@@ -855,6 +860,7 @@ enable_alloc_nonregional
with_pthreads
with_solaris_threads
with_syslog_facility
+with_dynlibmodule
with_pyunbound
with_pythonmodule
enable_swig_version_check
@@ -883,13 +889,13 @@ enable_allsymbols
enable_dnstap
with_dnstap_socket_path
with_protobuf_c
-with_libfstrm
enable_dnscrypt
with_libsodium
enable_cachedb
enable_ipsecmod
enable_ipset
with_libmnl
+enable_explicit_port_randomisation
with_libunbound_only
'
ac_precious_vars='build_alias
@@ -1452,7 +1458,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.10.1 to adapt to many kinds of systems.
+\`configure' configures unbound 1.11.0 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1517,7 +1523,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
- short | recursive ) echo "Configuration of unbound 1.10.1:";;
+ short | recursive ) echo "Configuration of unbound 1.11.0:";;
esac
cat <<\_ACEOF
@@ -1572,13 +1578,16 @@ Optional Features:
--enable-allsymbols export all symbols from libunbound and link binaries
to it, smaller install size but libunbound export
table is polluted by internal symbols
- --enable-dnstap Enable dnstap support (requires fstrm, protobuf-c)
+ --enable-dnstap Enable dnstap support (requires protobuf-c)
--enable-dnscrypt Enable dnscrypt support (requires libsodium)
--enable-cachedb enable cachedb module that can use external cache
storage
--enable-ipsecmod Enable ipsecmod module that facilitates
opportunistic IPsec
--enable-ipset enable ipset module
+ --disable-explicit-port-randomisation
+ disable explicit source port randomisation and rely
+ on the kernel to provide random source ports
Optional Packages:
--with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
@@ -1614,6 +1623,8 @@ Optional Packages:
--with-solaris-threads use solaris native thread library.
--with-syslog-facility=LOCAL0 - LOCAL7
set SYSLOG_FACILITY, default DAEMON
+ --with-dynlibmodule build dynamic library module, or
+ --without-dynlibmodule to disable it. (default=no)
--with-pyunbound build PyUnbound, or --without-pyunbound to skip it.
(default=no)
--with-pythonmodule build Python module, or --without-pythonmodule to
@@ -1634,7 +1645,6 @@ Optional Packages:
--with-dnstap-socket-path=pathname
set default dnstap socket path
--with-protobuf-c=path Path where protobuf-c is installed, for dnstap
- --with-libfstrm=path Path where libfstrm is installed, for dnstap
--with-libsodium=path Path where libsodium is installed, for dnscrypt
--with-libmnl=path specify explicit path for libmnl.
--with-libunbound-only do not build daemon and tool programs
@@ -1740,7 +1750,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
-unbound configure 1.10.1
+unbound configure 1.11.0
generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc.
@@ -2449,7 +2459,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.10.1, which was
+It was created by unbound $as_me 1.11.0, which was
generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@
@@ -2799,13 +2809,13 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
UNBOUND_VERSION_MAJOR=1
-UNBOUND_VERSION_MINOR=10
+UNBOUND_VERSION_MINOR=11
-UNBOUND_VERSION_MICRO=1
+UNBOUND_VERSION_MICRO=0
LIBUNBOUND_CURRENT=9
-LIBUNBOUND_REVISION=8
+LIBUNBOUND_REVISION=9
LIBUNBOUND_AGE=1
# 1.0.0 had 0:12:0
# 1.0.1 had 0:13:0
@@ -2881,6 +2891,7 @@ LIBUNBOUND_AGE=1
# 1.9.6 had 9:6:1
# 1.10.0 had 9:7:1
# 1.10.1 had 9:8:1
+# 1.11.0 had 9:9:1
# Current -- the number of the binary API that we're implementing
# Revision -- which iteration of the implementation of the binary
@@ -14729,6 +14740,20 @@ fi
done
+# Check for Apple header. This uncovers TARGET_OS_IPHONE, TARGET_OS_TV or TARGET_OS_WATCH
+for ac_header in TargetConditionals.h
+do :
+ ac_fn_c_check_header_mongrel "$LINENO" "TargetConditionals.h" "ac_cv_header_TargetConditionals_h" "$ac_includes_default"
+if test "x$ac_cv_header_TargetConditionals_h" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_TARGETCONDITIONALS_H 1
+_ACEOF
+
+fi
+
+done
+
+
# check for types.
# Using own tests for int64* because autoconf builtin only give 32bit.
ac_fn_c_check_type "$LINENO" "int8_t" "ac_cv_type_int8_t" "$ac_includes_default"
@@ -17171,6 +17196,34 @@ cat >>confdefs.h <<_ACEOF
_ACEOF
+# Check for dynamic library module
+
+# Check whether --with-dynlibmodule was given.
+if test "${with_dynlibmodule+set}" = set; then :
+ withval=$with_dynlibmodule;
+else
+ withval="no"
+fi
+
+
+if test x_$withval != x_no; then
+
+$as_echo "#define WITH_DYNLIBMODULE 1" >>confdefs.h
+
+ WITH_DYNLIBMODULE=yes
+
+ DYNLIBMOD_OBJ="dynlibmod.lo"
+
+ DYNLIBMOD_HEADER='$(srcdir)/dynlibmod/dynlibmod.h'
+
+ if test $on_mingw = "no"; then
+ DYNLIBMOD_EXTRALIBS="-ldl -export-dynamic"
+ else
+ DYNLIBMOD_EXTRALIBS="-Wl,--export-all-symbols,--out-implib,libunbound.a"
+ fi
+
+fi
+
# Check for PyUnbound
# Check whether --with-pyunbound was given.
@@ -17312,6 +17365,11 @@ $as_echo_n "checking for Python library path... " >&6; }
$as_echo "$PYTHON_LDFLAGS" >&6; }
+ if test -z "$PYTHON_LIBDIR"; then
+ PYTHON_LIBDIR=`$PYTHON -c "from distutils.sysconfig import *; \
+ print(get_config_var('LIBDIR'));"`
+ fi
+
#
# Check for site packages
#
@@ -17417,6 +17475,15 @@ $as_echo "#define HAVE_PYTHON 1" >>confdefs.h
else
CPPFLAGS="$PYTHON_CPPFLAGS"
fi
+ if test "$PYTHON_LIBDIR" != "/usr/lib" -a "$PYTHON_LIBDIR" != "" -a "$PYTHON_LIBDIR" != "/usr/lib64"; then
+
+ if test "x$enable_rpath" = xyes; then
+ if echo "$PYTHON_LIBDIR" | grep "^/" >/dev/null; then
+ RUNTIME_PATH="$RUNTIME_PATH -R$PYTHON_LIBDIR"
+ fi
+ fi
+
+ fi
ub_have_python=yes
if test -n "$PKG_CONFIG" && \
{ { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"\"python\${PY_MAJOR_VERSION}\"\""; } >&5
@@ -18259,7 +18326,7 @@ else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
-for ac_header in openssl/conf.h openssl/engine.h openssl/bn.h openssl/dh.h openssl/dsa.h openssl/rsa.h
+for ac_header in openssl/conf.h openssl/engine.h openssl/bn.h openssl/dh.h openssl/dsa.h openssl/rsa.h openssl/core_names.h
do :
as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default
@@ -18273,7 +18340,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 ERR_load_crypto_strings CRYPTO_cleanup_all_ex_data ERR_free_strings RAND_cleanup DSA_SIG_set0 EVP_dss1 EVP_DigestVerify SSL_CTX_set_tlsext_ticket_key_cb EVP_aes_256_cbc EVP_EncryptInit_ex HMAC_Init_ex CRYPTO_THREADID_set_callback
+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
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"
@@ -18289,7 +18356,7 @@ done
# these check_funcs need -lssl
BAKLIBS="$LIBS"
LIBS="-lssl $LIBS"
-for ac_func in OPENSSL_init_ssl SSL_CTX_set_security_level SSL_set1_host SSL_get0_peername X509_VERIFY_PARAM_set1_host SSL_CTX_set_ciphersuites
+for ac_func in OPENSSL_init_ssl SSL_CTX_set_security_level SSL_set1_host SSL_get0_peername X509_VERIFY_PARAM_set1_host SSL_CTX_set_ciphersuites SSL_CTX_set_tlsext_ticket_key_evp_cb
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"
@@ -19107,31 +19174,34 @@ esac
if test "${with_libevent+set}" = set; then :
withval=$with_libevent;
else
- withval="no"
+ with_libevent="no"
fi
-if test x_$withval = x_yes -o x_$withval != x_no; then
+if test "x_$with_libevent" != x_no; then
+
+$as_echo "#define USE_LIBEVENT 1" >>confdefs.h
+
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for libevent" >&5
$as_echo_n "checking for libevent... " >&6; }
- if test x_$withval = x_ -o x_$withval = x_yes; then
- withval="/usr/local /opt/local /usr/lib /usr/pkg /usr/sfw /usr"
+ if test "x_$with_libevent" = x_ -o "x_$with_libevent" = x_yes; then
+ with_libevent="/usr/local /opt/local /usr/lib /usr/pkg /usr/sfw /usr"
fi
- for dir in $withval; do
+ for dir in $with_libevent; do
thedir="$dir"
if test -f "$dir/include/event.h" -o -f "$dir/include/event2/event.h"; then
found_libevent="yes"
- if test "$thedir" != "/usr"; then
- CPPFLAGS="$CPPFLAGS -I$thedir/include"
- fi
- break;
- fi
+ if test "$thedir" != "/usr"; then
+ CPPFLAGS="$CPPFLAGS -I$thedir/include"
+ fi
+ break;
+ fi
done
if test x_$found_libevent != x_yes; then
if test -f "$dir/event.h" -a \( -f "$dir/libevent.la" -o -f "$dir/libev.la" \) ; then
# libevent source directory
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: found in $thedir" >&5
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: found in $thedir" >&5
$as_echo "found in $thedir" >&6; }
- CPPFLAGS="$CPPFLAGS -I$thedir -I$thedir/include"
+ CPPFLAGS="$CPPFLAGS -I$thedir -I$thedir/include"
BAK_LDFLAGS_SET="1"
BAK_LDFLAGS="$LDFLAGS"
# remove evdns from linking
@@ -19144,10 +19214,10 @@ $as_echo "found in $thedir" >&6; }
cp $ev_files_o build/libevent
cp $ev_files_lo build/libevent
cp $ev_files_libso build/libevent/.libs
- LATE_LDFLAGS="build/libevent/*.lo -lm"
+ LATE_LDFLAGS="build/libevent/*.lo -lm"
LDFLAGS="build/libevent/*.o $LDFLAGS -lm"
else
- as_fn_error $? "Cannot find the libevent library in $withval
+ as_fn_error $? "Cannot find the libevent library in $with_libevent
You can restart ./configure --with-libevent=no to use a builtin alternative.
Please note that this alternative is not as capable as libevent when using
large outgoing port ranges. " "$LINENO" 5
@@ -20968,73 +21038,6 @@ else
fi
-
-# Check whether --with-libfstrm was given.
-if test "${with_libfstrm+set}" = set; then :
- withval=$with_libfstrm;
- CFLAGS="$CFLAGS -I$withval/include"
- LDFLAGS="$LDFLAGS -L$withval/lib"
-
-fi
-
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing fstrm_iothr_init" >&5
-$as_echo_n "checking for library containing fstrm_iothr_init... " >&6; }
-if ${ac_cv_search_fstrm_iothr_init+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- ac_func_search_save_LIBS=$LIBS
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-/* Override any GCC internal prototype to avoid an error.
- Use char because int might match the return type of a GCC
- builtin and then its argument prototype would still apply. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char fstrm_iothr_init ();
-int
-main ()
-{
-return fstrm_iothr_init ();
- ;
- return 0;
-}
-_ACEOF
-for ac_lib in '' fstrm; do
- if test -z "$ac_lib"; then
- ac_res="none required"
- else
- ac_res=-l$ac_lib
- LIBS="-l$ac_lib $ac_func_search_save_LIBS"
- fi
- if ac_fn_c_try_link "$LINENO"; then :
- ac_cv_search_fstrm_iothr_init=$ac_res
-fi
-rm -f core conftest.err conftest.$ac_objext \
- conftest$ac_exeext
- if ${ac_cv_search_fstrm_iothr_init+:} false; then :
- break
-fi
-done
-if ${ac_cv_search_fstrm_iothr_init+:} false; then :
-
-else
- ac_cv_search_fstrm_iothr_init=no
-fi
-rm conftest.$ac_ext
-LIBS=$ac_func_search_save_LIBS
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_fstrm_iothr_init" >&5
-$as_echo "$ac_cv_search_fstrm_iothr_init" >&6; }
-ac_res=$ac_cv_search_fstrm_iothr_init
-if test "$ac_res" != no; then :
- test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
-
-else
- as_fn_error $? "The fstrm library was not found. Please install fstrm!" "$LINENO" 5
-fi
-
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing protobuf_c_message_pack" >&5
$as_echo_n "checking for library containing protobuf_c_message_pack... " >&6; }
if ${ac_cv_search_protobuf_c_message_pack+:} false; then :
@@ -21108,10 +21111,12 @@ cat >>confdefs.h <<_ACEOF
#define DNSTAP_SOCKET_PATH "$hdr_dnstap_socket_path"
_ACEOF
+ DNSTAP_SOCKET_PATH="$hdr_dnstap_socket_path"
- DNSTAP_SRC="dnstap/dnstap.c dnstap/dnstap.pb-c.c"
- DNSTAP_OBJ="dnstap.lo dnstap.pb-c.lo"
+ DNSTAP_SRC="dnstap/dnstap.c dnstap/dnstap.pb-c.c dnstap/dnstap_fstrm.c dnstap/dtstream.c"
+
+ DNSTAP_OBJ="dnstap.lo dnstap.pb-c.lo dnstap_fstrm.lo dtstream.lo"
else
@@ -21443,6 +21448,21 @@ $as_echo "found in $dir" >&6; }
# nothing
;;
esac
+# Check whether --enable-explicit-port-randomisation was given.
+if test "${enable_explicit_port_randomisation+set}" = set; then :
+ enableval=$enable_explicit_port_randomisation;
+fi
+
+case "$enable_explicit_port_randomisation" in
+ no)
+
+$as_echo "#define DISABLE_EXPLICIT_PORT_RANDOMISATION 1" >>confdefs.h
+
+ ;;
+ yes|*)
+ ;;
+esac
+
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if ${MAKE:-make} supports $< with implicit rule in scope" >&5
$as_echo_n "checking if ${MAKE:-make} supports $< with implicit rule in scope... " >&6; }
@@ -21599,7 +21619,7 @@ _ACEOF
-version=1.10.1
+version=1.11.0
date=`date +'%b %e, %Y'`
@@ -22118,7 +22138,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.10.1, which was
+This file was extended by unbound $as_me 1.11.0, which was
generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -22184,7 +22204,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.10.1
+unbound config.status 1.11.0
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 3e00c999c803..1d16dce72bf8 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],[10])
-m4_define([VERSION_MICRO],[1])
+m4_define([VERSION_MINOR],[11])
+m4_define([VERSION_MICRO],[0])
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=8
+LIBUNBOUND_REVISION=9
LIBUNBOUND_AGE=1
# 1.0.0 had 0:12:0
# 1.0.1 had 0:13:0
@@ -94,6 +94,7 @@ LIBUNBOUND_AGE=1
# 1.9.6 had 9:6:1
# 1.10.0 had 9:7:1
# 1.10.1 had 9:8:1
+# 1.11.0 had 9:9:1
# Current -- the number of the binary API that we're implementing
# Revision -- which iteration of the implementation of the binary
@@ -399,6 +400,9 @@ PKG_PROG_PKG_CONFIG
# Checks for header files.
AC_CHECK_HEADERS([stdarg.h stdbool.h netinet/in.h netinet/tcp.h sys/param.h sys/socket.h sys/un.h sys/uio.h sys/resource.h arpa/inet.h syslog.h netdb.h sys/wait.h pwd.h glob.h grp.h login_cap.h winsock2.h ws2tcpip.h endian.h sys/endian.h libkern/OSByteOrder.h sys/ipc.h sys/shm.h],,, [AC_INCLUDES_DEFAULT])
+# Check for Apple header. This uncovers TARGET_OS_IPHONE, TARGET_OS_TV or TARGET_OS_WATCH
+AC_CHECK_HEADERS([TargetConditionals.h])
+
# check for types.
# Using own tests for int64* because autoconf builtin only give 32bit.
AC_CHECK_TYPE(int8_t, signed char)
@@ -624,6 +628,28 @@ case "${UNBOUND_SYSLOG_FACILITY}" in
esac
AC_DEFINE_UNQUOTED(UB_SYSLOG_FACILITY,${UNBOUND_SYSLOG_FACILITY},[the SYSLOG_FACILITY to use, default LOG_DAEMON])
+# Check for dynamic library module
+AC_ARG_WITH(dynlibmodule,
+ AC_HELP_STRING([--with-dynlibmodule],
+ [build dynamic library module, or --without-dynlibmodule to disable it. (default=no)]),
+ [], [ withval="no" ])
+
+if test x_$withval != x_no; then
+ AC_DEFINE(WITH_DYNLIBMODULE, 1, [Define if you want dynlib module.])
+ WITH_DYNLIBMODULE=yes
+ AC_SUBST(WITH_DYNLIBMODULE)
+ DYNLIBMOD_OBJ="dynlibmod.lo"
+ AC_SUBST(DYNLIBMOD_OBJ)
+ DYNLIBMOD_HEADER='$(srcdir)/dynlibmod/dynlibmod.h'
+ AC_SUBST(DYNLIBMOD_HEADER)
+ if test $on_mingw = "no"; then
+ DYNLIBMOD_EXTRALIBS="-ldl -export-dynamic"
+ else
+ DYNLIBMOD_EXTRALIBS="-Wl,--export-all-symbols,--out-implib,libunbound.a"
+ fi
+ AC_SUBST(DYNLIBMOD_EXTRALIBS)
+fi
+
# Check for PyUnbound
AC_ARG_WITH(pyunbound,
AC_HELP_STRING([--with-pyunbound],
@@ -675,6 +701,9 @@ if test x_$ub_test_python != x_no; then
else
CPPFLAGS="$PYTHON_CPPFLAGS"
fi
+ if test "$PYTHON_LIBDIR" != "/usr/lib" -a "$PYTHON_LIBDIR" != "" -a "$PYTHON_LIBDIR" != "/usr/lib64"; then
+ ACX_RUNTIME_PATH_ADD([$PYTHON_LIBDIR])
+ fi
ub_have_python=yes
PKG_CHECK_EXISTS(["python${PY_MAJOR_VERSION}"],
[PC_PY_DEPENDENCY="python${PY_MAJOR_VERSION}"],
@@ -821,13 +850,13 @@ if grep VERSION_TEXT $ssldir/include/openssl/opensslv.h | grep "LibreSSL" >/dev/
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],,, [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 ERR_load_crypto_strings CRYPTO_cleanup_all_ex_data ERR_free_strings RAND_cleanup DSA_SIG_set0 EVP_dss1 EVP_DigestVerify SSL_CTX_set_tlsext_ticket_key_cb EVP_aes_256_cbc EVP_EncryptInit_ex HMAC_Init_ex CRYPTO_THREADID_set_callback])
+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],,, [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])
# these check_funcs need -lssl
BAKLIBS="$LIBS"
LIBS="-lssl $LIBS"
-AC_CHECK_FUNCS([OPENSSL_init_ssl SSL_CTX_set_security_level SSL_set1_host SSL_get0_peername X509_VERIFY_PARAM_set1_host SSL_CTX_set_ciphersuites])
+AC_CHECK_FUNCS([OPENSSL_init_ssl SSL_CTX_set_security_level SSL_set1_host SSL_get0_peername X509_VERIFY_PARAM_set1_host SSL_CTX_set_ciphersuites SSL_CTX_set_tlsext_ticket_key_evp_cb])
LIBS="$BAKLIBS"
AC_CHECK_DECLS([SSL_COMP_get_compression_methods,sk_SSL_COMP_pop_free,SSL_CTX_set_ecdh_auto], [], [], [
@@ -1215,28 +1244,29 @@ esac
# check for libevent
AC_ARG_WITH(libevent, AC_HELP_STRING([--with-libevent=pathname],
[use libevent (will check /usr/local /opt/local /usr/lib /usr/pkg /usr/sfw /usr or you can specify an explicit path). Slower, but allows use of large outgoing port ranges.]),
- [ ],[ withval="no" ])
-if test x_$withval = x_yes -o x_$withval != x_no; then
+ [ ],[ with_libevent="no" ])
+if test "x_$with_libevent" != x_no; then
+ AC_DEFINE([USE_LIBEVENT], [1], [Define if you enable libevent])
AC_MSG_CHECKING(for libevent)
- if test x_$withval = x_ -o x_$withval = x_yes; then
- withval="/usr/local /opt/local /usr/lib /usr/pkg /usr/sfw /usr"
+ if test "x_$with_libevent" = x_ -o "x_$with_libevent" = x_yes; then
+ with_libevent="/usr/local /opt/local /usr/lib /usr/pkg /usr/sfw /usr"
fi
- for dir in $withval; do
+ for dir in $with_libevent; do
thedir="$dir"
if test -f "$dir/include/event.h" -o -f "$dir/include/event2/event.h"; then
found_libevent="yes"
- dnl assume /usr is in default path.
- if test "$thedir" != "/usr"; then
- CPPFLAGS="$CPPFLAGS -I$thedir/include"
- fi
- break;
- fi
+ dnl assume /usr is in default path.
+ if test "$thedir" != "/usr"; then
+ CPPFLAGS="$CPPFLAGS -I$thedir/include"
+ fi
+ break;
+ fi
done
if test x_$found_libevent != x_yes; then
if test -f "$dir/event.h" -a \( -f "$dir/libevent.la" -o -f "$dir/libev.la" \) ; then
# libevent source directory
- AC_MSG_RESULT(found in $thedir)
- CPPFLAGS="$CPPFLAGS -I$thedir -I$thedir/include"
+ AC_MSG_RESULT(found in $thedir)
+ CPPFLAGS="$CPPFLAGS -I$thedir -I$thedir/include"
BAK_LDFLAGS_SET="1"
BAK_LDFLAGS="$LDFLAGS"
# remove evdns from linking
@@ -1249,10 +1279,10 @@ if test x_$withval = x_yes -o x_$withval != x_no; then
cp $ev_files_o build/libevent
cp $ev_files_lo build/libevent
cp $ev_files_libso build/libevent/.libs
- LATE_LDFLAGS="build/libevent/*.lo -lm"
+ LATE_LDFLAGS="build/libevent/*.lo -lm"
LDFLAGS="build/libevent/*.o $LDFLAGS -lm"
else
- AC_MSG_ERROR([Cannot find the libevent library in $withval
+ AC_MSG_ERROR([Cannot find the libevent library in $with_libevent
You can restart ./configure --with-libevent=no to use a builtin alternative.
Please note that this alternative is not as capable as libevent when using
large outgoing port ranges. ])
@@ -1688,9 +1718,10 @@ dt_DNSTAP([$UNBOUND_RUN_DIR/dnstap.sock],
ACX_ESCAPE_BACKSLASH($opt_dnstap_socket_path, hdr_dnstap_socket_path)
AC_DEFINE_UNQUOTED(DNSTAP_SOCKET_PATH,
["$hdr_dnstap_socket_path"], [default dnstap socket path])
+ AC_SUBST(DNSTAP_SOCKET_PATH,["$hdr_dnstap_socket_path"])
- AC_SUBST([DNSTAP_SRC], ["dnstap/dnstap.c dnstap/dnstap.pb-c.c"])
- AC_SUBST([DNSTAP_OBJ], ["dnstap.lo dnstap.pb-c.lo"])
+ AC_SUBST([DNSTAP_SRC], ["dnstap/dnstap.c dnstap/dnstap.pb-c.c dnstap/dnstap_fstrm.c dnstap/dtstream.c"])
+ AC_SUBST([DNSTAP_OBJ], ["dnstap.lo dnstap.pb-c.lo dnstap_fstrm.lo dtstream.lo"])
],
[
AC_SUBST([ENABLE_DNSTAP], [0])
@@ -1778,6 +1809,15 @@ case "$enable_ipset" in
# nothing
;;
esac
+AC_ARG_ENABLE(explicit-port-randomisation, AC_HELP_STRING([--disable-explicit-port-randomisation], [disable explicit source port randomisation and rely on the kernel to provide random source ports]))
+case "$enable_explicit_port_randomisation" in
+ no)
+ AC_DEFINE([DISABLE_EXPLICIT_PORT_RANDOMISATION], [1], [Define this to enable kernel based UDP source port randomization.])
+ ;;
+ yes|*)
+ ;;
+esac
+
AC_MSG_CHECKING([if ${MAKE:-make} supports $< with implicit rule in scope])
# on openBSD, the implicit rule make $< work.
diff --git a/contrib/unbound/contrib/aaaa-filter-iterator.patch b/contrib/unbound/contrib/aaaa-filter-iterator.patch
index b5c5268223d1..9881bde892ad 100644
--- a/contrib/unbound/contrib/aaaa-filter-iterator.patch
+++ b/contrib/unbound/contrib/aaaa-filter-iterator.patch
@@ -13,9 +13,9 @@ Index: trunk/doc/unbound.conf.5.in
+This also causes an additional A query to be sent for each AAAA query.
+This breaks DNSSEC!
+.TP
- .B private\-address: \fI<IP address or subnet>
- Give IPv4 of IPv6 addresses or classless subnets. These are addresses
- on your private network, and are not allowed to be returned for
+ .B aggressive\-nsec: \fI<yes or no>
+ Aggressive NSEC uses the DNSSEC NSEC chain to synthesize NXDOMAIN
+ and other denials, using information from previous NXDOMAINs answers.
Index: trunk/iterator/iter_scrub.c
===================================================================
--- trunk/iterator/iter_scrub.c (revision 4357)
@@ -125,7 +125,7 @@ Index: trunk/iterator/iterator.c
+ * ASN: This event state was added as an intermediary step between
+ * QUERYTARGETS_STATE and the next step, in order to cast a subquery for the
+ * purpose of caching A records for the queried name.
-+ *
++ *
+ * @param qstate: query state.
+ * @param iq: iterator query state.
+ * @param ie: iterator shared global environment.
@@ -147,9 +147,9 @@ Index: trunk/iterator/iterator.c
+
+ /* re-throw same query, but with a different type */
+ if(!generate_sub_request(iq->qchase.qname,
-+ iq->qchase.qname_len, LDNS_RR_TYPE_A,
++ iq->qchase.qname_len, LDNS_RR_TYPE_A,
+ iq->qchase.qclass, qstate, id, iq,
-+ INIT_REQUEST_STATE, FINISHED_STATE, &subq, 1)) {
++ INIT_REQUEST_STATE, FINISHED_STATE, &subq, 1, 0)) {
+ log_nametypeclass(VERB_ALGO, "ASN-AAAA-filter: failed "
+ "preloading of A record for",
+ iq->qchase.qname, LDNS_RR_TYPE_A,
@@ -188,7 +188,7 @@ Index: trunk/iterator/iterator.c
return 0;
}
-+/**
++/**
+ * ASN: Do final processing on responses to A queries originated from AAAA
+ * queries. Events reach this state after the iterative resolution algorithm
+ * terminates.
diff --git a/contrib/unbound/contrib/android/15-android.conf b/contrib/unbound/contrib/android/15-android.conf
new file mode 100644
index 000000000000..e1fc91e703f2
--- /dev/null
+++ b/contrib/unbound/contrib/android/15-android.conf
@@ -0,0 +1,37 @@
+#### Android...
+#
+# Heavily hacked 15-android.conf based on OpenSSL's config file of the same name.
+# This 15-android.conf avoids compiler errors using NDK-r20. This 15-android.conf
+# requires an environment set (sourced) using setenv-android.sh.
+
+my %targets = (
+ "android" => {
+ inherit_from => [ "linux-generic32" ],
+ template => 1,
+ bin_cflags => add("-fPIE"),
+ bin_lflags => add("-pie"),
+ enable => [ ],
+ },
+
+ "android-arm" => {
+ inherit_from => [ "android", asm("armv4_asm") ],
+ bn_ops => [ "BN_LLONG", "RC4_CHAR" ],
+ },
+ "android-arm64" => {
+ inherit_from => [ "android", asm("aarch64_asm") ],
+ bn_ops => [ "SIXTY_FOUR_BIT_LONG", "RC4_CHAR" ],
+ perlasm_scheme => "linux64",
+ },
+
+ "android-x86" => {
+ inherit_from => [ "android", asm("x86_asm") ],
+ cflags => add(picker(release => "-fomit-frame-pointer")),
+ bn_ops => [ "BN_LLONG", "RC4_INT" ],
+ perlasm_scheme => "android",
+ },
+ "android-x86_64" => {
+ inherit_from => [ "android", asm("x86_64_asm") ],
+ bn_ops => [ "SIXTY_FOUR_BIT_LONG", "RC4_INT" ],
+ perlasm_scheme => "elf",
+ },
+);
diff --git a/contrib/unbound/contrib/android/install_expat.sh b/contrib/unbound/contrib/android/install_expat.sh
new file mode 100755
index 000000000000..ffb22322c803
--- /dev/null
+++ b/contrib/unbound/contrib/android/install_expat.sh
@@ -0,0 +1,51 @@
+#!/usr/bin/env bash
+
+echo "Downloading Expat"
+if ! curl -L -k -s -o expat-2.2.9.tar.gz https://github.com/libexpat/libexpat/releases/download/R_2_2_9/expat-2.2.9.tar.gz;
+then
+ echo "Failed to download Expat"
+ exit 1
+fi
+
+echo "Unpacking Expat"
+rm -rf ./expat-2.2.9
+if ! tar -xf expat-2.2.9.tar.gz;
+then
+ echo "Failed to unpack Expat"
+ exit 1
+fi
+
+cd expat-2.2.9 || exit 1
+
+echo "Configuring Expat"
+if ! ./configure --build="$AUTOTOOLS_BUILD" --host="$AUTOTOOLS_HOST" --prefix="$ANDROID_PREFIX"; then
+ echo "Error: Failed to configure Expat"
+ exit 1
+fi
+
+# Cleanup warnings, https://github.com/libexpat/libexpat/issues/383
+echo "Fixing Makefiles"
+(IFS="" find "$PWD" -name 'Makefile' -print | while read -r file
+do
+ cp -p "$file" "$file.fixed"
+ sed 's|-Wduplicated-cond ||g; s|-Wduplicated-branches ||g; s|-Wlogical-op ||g' "$file" > "$file.fixed"
+ mv "$file.fixed" "$file"
+
+ cp -p "$file" "$file.fixed"
+ sed 's|-Wrestrict ||g; s|-Wjump-misses-init ||g; s|-Wmisleading-indentation ||g' "$file" > "$file.fixed"
+ mv "$file.fixed" "$file"
+done)
+
+echo "Building Expat"
+if ! make; then
+ echo "Failed to build Expat"
+ exit 1
+fi
+
+echo "Installing Expat"
+if ! make install; then
+ echo "Failed to install Expat"
+ exit 1
+fi
+
+exit 0
diff --git a/contrib/unbound/contrib/android/install_ndk.sh b/contrib/unbound/contrib/android/install_ndk.sh
new file mode 100755
index 000000000000..6e07b5d6cbfd
--- /dev/null
+++ b/contrib/unbound/contrib/android/install_ndk.sh
@@ -0,0 +1,60 @@
+#!/usr/bin/env bash
+
+if [ -z "$ANDROID_SDK_ROOT" ]; then
+ echo "ERROR: ANDROID_SDK_ROOT is not a valid path. Please set it."
+ echo "SDK root is $ANDROID_SDK_ROOT"
+ exit 1
+fi
+
+if [ -z "$ANDROID_NDK_ROOT" ]; then
+ echo "ERROR: ANDROID_NDK_ROOT is not a valid path. Please set it."
+ echo "NDK root is $ANDROID_NDK_ROOT"
+ exit 1
+fi
+
+echo "Using ANDROID_SDK_ROOT: $ANDROID_SDK_ROOT"
+echo "Using ANDROID_NDK_ROOT: $ANDROID_NDK_ROOT"
+
+echo "Downloading SDK"
+if ! curl -L -k -s -o "$HOME/android-sdk.zip" https://dl.google.com/android/repository/commandlinetools-linux-6200805_latest.zip;
+then
+ echo "Failed to download SDK"
+ exit 1
+fi
+
+echo "Downloading NDK"
+if ! curl -L -k -s -o "$HOME/android-ndk.zip" https://dl.google.com/android/repository/android-ndk-r20b-linux-x86_64.zip;
+then
+ echo "Failed to download NDK"
+ exit 1
+fi
+
+echo "Unpacking SDK to $ANDROID_SDK_ROOT"
+if ! unzip -qq "$HOME/android-sdk.zip" -d "$ANDROID_SDK_ROOT";
+then
+ echo "Failed to unpack SDK"
+ exit 1
+fi
+
+echo "Unpacking NDK to $ANDROID_NDK_ROOT"
+if ! unzip -qq "$HOME/android-ndk.zip" -d "$HOME";
+then
+ echo "Failed to unpack NDK"
+ exit 1
+fi
+
+if ! mv "$HOME/android-ndk-r20b" "$ANDROID_NDK_ROOT";
+then
+ echo "Failed to move $HOME/android-ndk-r20b to $ANDROID_NDK_ROOT"
+ exit 1
+fi
+
+rm -f "$HOME/android-sdk.zip"
+rm -f "$HOME/android-ndk.zip"
+
+# https://stackoverflow.com/a/47028911/608639
+touch "$ANDROID_SDK_ROOT/repositories.cfg"
+
+echo "Finished installing SDK and NDK"
+
+exit 0
diff --git a/contrib/unbound/contrib/android/install_openssl.sh b/contrib/unbound/contrib/android/install_openssl.sh
new file mode 100755
index 000000000000..e4fb87266e2e
--- /dev/null
+++ b/contrib/unbound/contrib/android/install_openssl.sh
@@ -0,0 +1,44 @@
+#!/usr/bin/env bash
+
+echo "Downloading OpenSSL"
+if ! curl -L -k -s -o openssl-1.1.1d.tar.gz https://www.openssl.org/source/openssl-1.1.1d.tar.gz;
+then
+ echo "Failed to download OpenSSL"
+ exit 1
+fi
+
+echo "Unpacking OpenSSL"
+rm -rf ./openssl-1.1.1d
+if ! tar -xf openssl-1.1.1d.tar.gz;
+then
+ echo "Failed to unpack OpenSSL"
+ exit 1
+fi
+
+cd openssl-1.1.1d || exit 1
+
+if ! cp ../contrib/android/15-android.conf Configurations/; then
+ echo "Failed to copy OpenSSL Android config"
+ exit 1
+fi
+
+echo "Configuring OpenSSL"
+if ! ./Configure "$OPENSSL_HOST" no-comp no-asm no-hw no-engine shared \
+ --prefix="$ANDROID_PREFIX" --openssldir="$ANDROID_PREFIX"; then
+ echo "Failed to configure OpenSSL"
+ exit 1
+fi
+
+echo "Building OpenSSL"
+if ! make; then
+ echo "Failed to build OpenSSL"
+ exit 1
+fi
+
+echo "Installing OpenSSL"
+if ! make install_sw; then
+ echo "Failed to install OpenSSL"
+ exit 1
+fi
+
+exit 0
diff --git a/contrib/unbound/contrib/android/install_tools.sh b/contrib/unbound/contrib/android/install_tools.sh
new file mode 100755
index 000000000000..0f595a0bcb12
--- /dev/null
+++ b/contrib/unbound/contrib/android/install_tools.sh
@@ -0,0 +1,6 @@
+#!/usr/bin/env bash
+
+# This step should install tools needed for all packages - OpenSSL, Expat and Unbound
+echo "Updating tools"
+sudo apt-get -qq update
+sudo apt-get -qq install --no-install-recommends curl tar zip unzip perl openjdk-8-jdk autoconf automake libtool pkg-config
diff --git a/contrib/unbound/contrib/android/setenv_android.sh b/contrib/unbound/contrib/android/setenv_android.sh
new file mode 100755
index 000000000000..fe7f6503c6d6
--- /dev/null
+++ b/contrib/unbound/contrib/android/setenv_android.sh
@@ -0,0 +1,203 @@
+#!/usr/bin/env bash
+
+# ====================================================================
+# Sets the cross compile environment for Android
+#
+# Based upon OpenSSL's setenv-android.sh by TH, JW, and SM.
+# Heavily modified by JWW for Crypto++.
+# Updated by Skycoder42 for current recommendations for Android.
+# Modified by JWW for Unbound.
+# ====================================================================
+
+#########################################
+##### Some validation #####
+#########################################
+
+if [ -z "$ANDROID_API" ]; then
+ echo "ANDROID_API is not set. Please set it"
+ [[ "$0" = "${BASH_SOURCE[0]}" ]] && exit 1 || return 1
+fi
+
+if [ -z "$ANDROID_CPU" ]; then
+ echo "ANDROID_CPU is not set. Please set it"
+ [[ "$0" = "${BASH_SOURCE[0]}" ]] && exit 1 || return 1
+fi
+
+if [ ! -d "$ANDROID_NDK_ROOT" ]; then
+ echo "ERROR: ANDROID_NDK_ROOT is not a valid path. Please set it."
+ echo "NDK root is $ANDROID_NDK_ROOT"
+ [ "$0" = "${BASH_SOURCE[0]}" ] && exit 1 || return 1
+fi
+
+# cryptest-android.sh may run this script without sourcing.
+if [ "$0" = "${BASH_SOURCE[0]}" ]; then
+ echo "setenv-android.sh is usually sourced, but not this time."
+fi
+
+#####################################################################
+
+# Need to set THIS_HOST to darwin-x86_64, linux-x86_64,
+# windows, or windows-x86_64
+
+if [[ "$(uname -s | grep -i -c darwin)" -ne 0 ]]; then
+ THIS_HOST=darwin-x86_64
+elif [[ "$(uname -s | grep -i -c linux)" -ne 0 ]]; then
+ THIS_HOST=linux-x86_64
+else
+ echo "ERROR: Unknown host"
+ [ "$0" = "${BASH_SOURCE[0]}" ] && exit 1 || return 1
+fi
+
+ANDROID_TOOLCHAIN="$ANDROID_NDK_ROOT/toolchains/llvm/prebuilt/$THIS_HOST/bin"
+ANDROID_SYSROOT="$ANDROID_NDK_ROOT/toolchains/llvm/prebuilt/$THIS_HOST/sysroot"
+
+# Error checking
+if [ ! -d "$ANDROID_TOOLCHAIN" ]; then
+ echo "ERROR: ANDROID_TOOLCHAIN is not a valid path. Please set it."
+ echo "Path is $ANDROID_TOOLCHAIN"
+ [ "$0" = "${BASH_SOURCE[0]}" ] && exit 1 || return 1
+fi
+
+# Error checking
+if [ ! -d "$ANDROID_SYSROOT" ]; then
+ echo "ERROR: ANDROID_SYSROOT is not a valid path. Please set it."
+ echo "Path is $ANDROID_SYSROOT"
+ [ "$0" = "${BASH_SOURCE[0]}" ] && exit 1 || return 1
+fi
+
+#####################################################################
+
+THE_ARCH=$(tr '[:upper:]' '[:lower:]' <<< "$ANDROID_CPU")
+
+# https://developer.android.com/ndk/guides/abis.html
+case "$THE_ARCH" in
+ armv7*|armeabi*)
+ CC="armv7a-linux-androideabi$ANDROID_API-clang"
+ CXX="armv7a-linux-androideabi$ANDROID_API-clang++"
+ LD="arm-linux-androideabi-ld"
+ AS="arm-linux-androideabi-as"
+ AR="arm-linux-androideabi-ar"
+ RANLIB="arm-linux-androideabi-ranlib"
+ STRIP="arm-linux-androideabi-strip"
+
+ CFLAGS="-march=armv7-a -mthumb -mfloat-abi=softfp -funwind-tables -fexceptions"
+ CXXFLAGS="-march=armv7-a -mthumb -mfloat-abi=softfp -funwind-tables -fexceptions -frtti"
+ ;;
+
+ armv8*|aarch64|arm64*)
+ CC="aarch64-linux-android$ANDROID_API-clang"
+ CXX="aarch64-linux-android$ANDROID_API-clang++"
+ LD="aarch64-linux-android-ld"
+ AS="aarch64-linux-android-as"
+ AR="aarch64-linux-android-ar"
+ RANLIB="aarch64-linux-android-ranlib"
+ STRIP="aarch64-linux-android-strip"
+
+ CFLAGS="-funwind-tables -fexceptions"
+ CXXFLAGS="-funwind-tables -fexceptions -frtti"
+ ;;
+
+ x86)
+ CC="i686-linux-android$ANDROID_API-clang"
+ CXX="i686-linux-android$ANDROID_API-clang++"
+ LD="i686-linux-android-ld"
+ AS="i686-linux-android-as"
+ AR="i686-linux-android-ar"
+ RANLIB="i686-linux-android-ranlib"
+ STRIP="i686-linux-android-strip"
+
+ CFLAGS="-mtune=intel -mssse3 -mfpmath=sse -funwind-tables -fexceptions"
+ CXXFLAGS="-mtune=intel -mssse3 -mfpmath=sse -funwind-tables -fexceptions -frtti"
+ ;;
+
+ x86_64|x64)
+ CC="x86_64-linux-android$ANDROID_API-clang"
+ CXX="x86_64-linux-android$ANDROID_API-clang++"
+ LD="x86_64-linux-android-ld"
+ AS="x86_64-linux-android-as"
+ AR="x86_64-linux-android-ar"
+ RANLIB="x86_64-linux-android-ranlib"
+ STRIP="x86_64-linux-android-strip"
+
+ CFLAGS="-march=x86-64 -msse4.2 -mpopcnt -mtune=intel -funwind-tables -fexceptions"
+ CXXFLAGS="-march=x86-64 -msse4.2 -mpopcnt -mtune=intel -funwind-tables -fexceptions -frtti"
+ ;;
+
+ *)
+ echo "ERROR: Unknown architecture $ANDROID_CPU"
+ [ "$0" = "${BASH_SOURCE[0]}" ] && exit 1 || return 1
+ ;;
+esac
+
+#####################################################################
+
+# Error checking
+if [ ! -e "$ANDROID_TOOLCHAIN/$CC" ]; then
+ echo "ERROR: Failed to find Android clang. Please edit this script."
+ [ "$0" = "${BASH_SOURCE[0]}" ] && exit 1 || return 1
+fi
+
+# Error checking
+if [ ! -e "$ANDROID_TOOLCHAIN/$CXX" ]; then
+ echo "ERROR: Failed to find Android clang++. Please edit this script."
+ [ "$0" = "${BASH_SOURCE[0]}" ] && exit 1 || return 1
+fi
+
+# Error checking
+if [ ! -e "$ANDROID_TOOLCHAIN/$RANLIB" ]; then
+ echo "ERROR: Failed to find Android ranlib. Please edit this script."
+ [ "$0" = "${BASH_SOURCE[0]}" ] && exit 1 || return 1
+fi
+
+# Error checking
+if [ ! -e "$ANDROID_TOOLCHAIN/$AR" ]; then
+ echo "ERROR: Failed to find Android ar. Please edit this script."
+ [ "$0" = "${BASH_SOURCE[0]}" ] && exit 1 || return 1
+fi
+
+# Error checking
+if [ ! -e "$ANDROID_TOOLCHAIN/$AS" ]; then
+ echo "ERROR: Failed to find Android as. Please edit this script."
+ [ "$0" = "${BASH_SOURCE[0]}" ] && exit 1 || return 1
+fi
+
+# Error checking
+if [ ! -e "$ANDROID_TOOLCHAIN/$LD" ]; then
+ echo "ERROR: Failed to find Android ld. Please edit this script."
+ [ "$0" = "${BASH_SOURCE[0]}" ] && exit 1 || return 1
+fi
+
+#####################################################################
+
+LENGTH=${#ANDROID_TOOLCHAIN}
+SUBSTR=${PATH:0:$LENGTH}
+if [ "$SUBSTR" != "$ANDROID_TOOLCHAIN" ]; then
+ export PATH="$ANDROID_TOOLCHAIN:$PATH"
+fi
+
+#####################################################################
+
+export CPP CC CXX LD AS AR RANLIB STRIP
+export ANDROID_SYSROOT="$AOSP_SYSROOT"
+export CPPFLAGS="-D__ANDROID_API__=$ANDROID_API"
+export CFLAGS="$CFLAGS --sysroot=$AOSP_SYSROOT"
+export CXXFLAGS="$CXXFLAGS -stdlib=libc++ --sysroot=$AOSP_SYSROOT"
+
+#####################################################################
+
+echo "ANDROID_TOOLCHAIN: $ANDROID_TOOLCHAIN"
+
+echo "CPP: $(command -v "$CPP")"
+echo "CC: $(command -v "$CC")"
+echo "CXX: $(command -v "$CXX")"
+echo "LD: $(command -v "$LD")"
+echo "AS: $(command -v "$AS")"
+echo "AR: $(command -v "$AR")"
+
+echo "ANDROID_SYSROOT: $ANDROID_SYSROOT"
+
+echo "CPPFLAGS: $CPPFLAGS"
+echo "CFLAGS: $CFLAGS"
+echo "CXXFLAGS: $CXXFLAGS"
+
+[ "$0" = "${BASH_SOURCE[0]}" ] && exit 0 || return 0
diff --git a/contrib/unbound/contrib/fastrpz.patch b/contrib/unbound/contrib/fastrpz.patch
index aacd5ab826b8..5b3c18a7cdd7 100644
--- a/contrib/unbound/contrib/fastrpz.patch
+++ b/contrib/unbound/contrib/fastrpz.patch
@@ -2,7 +2,7 @@ Description: based on the included patch contrib/fastrpz.patch
Author: fastrpz@farsightsecurity.com
---
diff --git a/Makefile.in b/Makefile.in
-index a20058cc..495779cc 100644
+index bac212df..4824927f 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -23,6 +23,8 @@ CHECKLOCK_SRC=testcode/checklocks.c
@@ -13,8 +13,8 @@ index a20058cc..495779cc 100644
+FASTRPZ_OBJ=@FASTRPZ_OBJ@
DNSCRYPT_SRC=@DNSCRYPT_SRC@
DNSCRYPT_OBJ=@DNSCRYPT_OBJ@
- WITH_PYTHONMODULE=@WITH_PYTHONMODULE@
-@@ -127,7 +129,7 @@ validator/val_sigcrypt.c validator/val_utils.c dns64/dns64.c \
+ WITH_DYNLIBMODULE=@WITH_DYNLIBMODULE@
+@@ -134,7 +136,7 @@ validator/val_sigcrypt.c validator/val_utils.c dns64/dns64.c \
edns-subnet/edns-subnet.c edns-subnet/subnetmod.c \
edns-subnet/addrtree.c edns-subnet/subnet-whitelist.c \
cachedb/cachedb.c cachedb/redis.c respip/respip.c $(CHECKLOCK_SRC) \
@@ -23,16 +23,16 @@ index a20058cc..495779cc 100644
COMMON_OBJ_WITHOUT_NETCALL=dns.lo infra.lo rrset.lo dname.lo msgencode.lo \
as112.lo msgparse.lo msgreply.lo packed_rrset.lo iterator.lo iter_delegpt.lo \
iter_donotq.lo iter_fwd.lo iter_hints.lo iter_priv.lo iter_resptype.lo \
-@@ -140,7 +142,7 @@ autotrust.lo val_anchor.lo rpz.lo \
+@@ -147,7 +149,7 @@ autotrust.lo val_anchor.lo rpz.lo \
validator.lo val_kcache.lo val_kentry.lo val_neg.lo val_nsec3.lo val_nsec.lo \
val_secalgo.lo val_sigcrypt.lo val_utils.lo dns64.lo cachedb.lo redis.lo authzone.lo \
$(SUBNET_OBJ) $(PYTHONMOD_OBJ) $(CHECKLOCK_OBJ) $(DNSTAP_OBJ) $(DNSCRYPT_OBJ) \
--$(IPSECMOD_OBJ) $(IPSET_OBJ) respip.lo
-+$(FASTRPZ_OBJ) $(IPSECMOD_OBJ) $(IPSET_OBJ) respip.lo
+-$(IPSECMOD_OBJ) $(IPSET_OBJ) $(DYNLIBMOD_OBJ) respip.lo
++$(FASTRPZ_OBJ) $(IPSECMOD_OBJ) $(IPSET_OBJ) $(DYNLIBMOD_OBJ) respip.lo
COMMON_OBJ_WITHOUT_UB_EVENT=$(COMMON_OBJ_WITHOUT_NETCALL) netevent.lo listen_dnsport.lo \
outside_network.lo
COMMON_OBJ=$(COMMON_OBJ_WITHOUT_UB_EVENT) ub_event.lo
-@@ -410,6 +412,11 @@ dnscrypt.lo dnscrypt.o: $(srcdir)/dnscrypt/dnscrypt.c config.h \
+@@ -428,6 +430,11 @@ dnscrypt.lo dnscrypt.o: $(srcdir)/dnscrypt/dnscrypt.c config.h \
$(srcdir)/util/config_file.h $(srcdir)/util/log.h \
$(srcdir)/util/netevent.h
@@ -45,10 +45,10 @@ index a20058cc..495779cc 100644
pythonmod.lo pythonmod.o: $(srcdir)/pythonmod/pythonmod.c config.h \
pythonmod/interface.h \
diff --git a/config.h.in b/config.h.in
-index 78d47fed..e33073e4 100644
+index f7a4095e..d5a4fa01 100644
--- a/config.h.in
+++ b/config.h.in
-@@ -1345,4 +1345,11 @@ void *unbound_stat_realloc_log(void *ptr, size_t size, const char* file,
+@@ -1364,4 +1364,11 @@ void *unbound_stat_realloc_log(void *ptr, size_t size, const char* file,
/** the version of unbound-control that this software implements */
#define UNBOUND_CONTROL_VERSION 1
@@ -62,7 +62,7 @@ index 78d47fed..e33073e4 100644
+/** turn on fastrpz response policy zones */
+#undef ENABLE_FASTRPZ
diff --git a/configure.ac b/configure.ac
-index 2b91dd3c..e6063d17 100644
+index 5c373d9d..e45abd89 100644
--- a/configure.ac
+++ b/configure.ac
@@ -6,6 +6,7 @@ sinclude(ax_pthread.m4)
@@ -73,10 +73,10 @@ index 2b91dd3c..e6063d17 100644
sinclude(dnscrypt/dnscrypt.m4)
# must be numbers. ac_defun because of later processing
-@@ -1778,6 +1779,9 @@ case "$enable_ipset" in
- ;;
+@@ -1819,6 +1820,9 @@ case "$enable_explicit_port_randomisation" in
esac
+
+# check for Fastrpz with fastrpz/rpz.m4
+ck_FASTRPZ
+
@@ -84,7 +84,7 @@ index 2b91dd3c..e6063d17 100644
# on openBSD, the implicit rule make $< work.
# on Solaris, it does not work ($? is changed sources, $^ lists dependencies).
diff --git a/daemon/daemon.c b/daemon/daemon.c
-index 8b0fc348..7ffb9221 100644
+index 5d427925..f89f1437 100644
--- a/daemon/daemon.c
+++ b/daemon/daemon.c
@@ -91,6 +91,9 @@
@@ -97,8 +97,8 @@ index 8b0fc348..7ffb9221 100644
#ifdef HAVE_SYSTEMD
#include <systemd/sd-daemon.h>
-@@ -458,6 +461,14 @@ daemon_create_workers(struct daemon* daemon)
- dt_apply_cfg(daemon->dtenv, daemon->cfg);
+@@ -456,6 +459,14 @@ daemon_create_workers(struct daemon* daemon)
+ fatal_exit("dt_create failed");
#else
fatal_exit("dnstap enabled in config but not built with dnstap support");
+#endif
@@ -112,7 +112,7 @@ index 8b0fc348..7ffb9221 100644
#endif
}
for(i=0; i<daemon->num; i++) {
-@@ -731,6 +742,9 @@ daemon_cleanup(struct daemon* daemon)
+@@ -729,6 +740,9 @@ daemon_cleanup(struct daemon* daemon)
#ifdef USE_DNSCRYPT
dnsc_delete(daemon->dnscenv);
daemon->dnscenv = NULL;
@@ -139,7 +139,7 @@ index 3effbafb..4d4c34da 100644
/**
diff --git a/daemon/worker.c b/daemon/worker.c
-index eb7fdf2f..1982228d 100644
+index 23e3244c..b63d49b7 100644
--- a/daemon/worker.c
+++ b/daemon/worker.c
@@ -76,6 +76,9 @@
@@ -152,7 +152,7 @@ index eb7fdf2f..1982228d 100644
#include "sldns/wire2str.h"
#include "util/shm_side/shm_main.h"
#include "dnscrypt/dnscrypt.h"
-@@ -534,8 +537,27 @@ answer_norec_from_cache(struct worker* worker, struct query_info* qinfo,
+@@ -535,8 +538,27 @@ answer_norec_from_cache(struct worker* worker, struct query_info* qinfo,
/* not secure */
secure = 0;
break;
@@ -180,7 +180,7 @@ index eb7fdf2f..1982228d 100644
/* return this delegation from the cache */
edns_bak = *edns;
edns->edns_version = EDNS_ADVERTISED_VERSION;
-@@ -710,6 +732,23 @@ answer_from_cache(struct worker* worker, struct query_info* qinfo,
+@@ -711,6 +733,23 @@ answer_from_cache(struct worker* worker, struct query_info* qinfo,
*is_secure_answer = 0;
}
} else *is_secure_answer = 0;
@@ -204,7 +204,7 @@ index eb7fdf2f..1982228d 100644
edns_bak = *edns;
edns->edns_version = EDNS_ADVERTISED_VERSION;
-@@ -1435,6 +1474,15 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
+@@ -1436,6 +1475,15 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
log_addr(VERB_ALGO, "refused nonrec (cache snoop) query from",
&repinfo->addr, repinfo->addrlen);
goto send_reply;
@@ -220,7 +220,7 @@ index eb7fdf2f..1982228d 100644
}
/* If we've found a local alias, replace the qname with the alias
-@@ -1485,12 +1533,21 @@ lookup_cache:
+@@ -1486,12 +1534,21 @@ lookup_cache:
h = query_info_hash(lookup_qinfo, sldns_buffer_read_u16_at(c->buffer, 2));
if((e=slabhash_lookup(worker->env.msg_cache, h, lookup_qinfo, 0))) {
/* answer from cache - we have acquired a readlock on it */
@@ -244,7 +244,7 @@ index eb7fdf2f..1982228d 100644
/* prefetch it if the prefetch TTL expired.
* Note that if there is more than one pass
* its qname must be that used for cache
-@@ -1547,11 +1604,19 @@ lookup_cache:
+@@ -1548,11 +1605,19 @@ lookup_cache:
lock_rw_unlock(&e->lock);
}
if(!LDNS_RD_WIRE(sldns_buffer_begin(c->buffer))) {
@@ -267,10 +267,10 @@ index eb7fdf2f..1982228d 100644
}
verbose(VERB_ALGO, "answer norec from cache -- "
diff --git a/doc/unbound.conf.5.in b/doc/unbound.conf.5.in
-index 38c2d298..3b07f392 100644
+index cd43f04e..b92a1af8 100644
--- a/doc/unbound.conf.5.in
+++ b/doc/unbound.conf.5.in
-@@ -1828,6 +1828,81 @@ List domain for which the AAAA records are ignored and the A record is
+@@ -1878,6 +1878,81 @@ List domain for which the AAAA records are ignored and the A record is
used by dns64 processing instead. Can be entered multiple times, list a
new domain for which it applies, one per line. Applies also to names
underneath the name given.
@@ -2888,7 +2888,7 @@ index 00000000..21235355
+ fi
+])
diff --git a/iterator/iterator.c b/iterator/iterator.c
-index 1e0113a8..2fcbf547 100644
+index 23b07ea9..c3d31a33 100644
--- a/iterator/iterator.c
+++ b/iterator/iterator.c
@@ -68,6 +68,9 @@
@@ -2901,7 +2901,7 @@ index 1e0113a8..2fcbf547 100644
/* in msec */
int UNKNOWN_SERVER_NICENESS = 376;
-@@ -555,6 +558,23 @@ handle_cname_response(struct module_qstate* qstate, struct iter_qstate* iq,
+@@ -563,6 +566,23 @@ handle_cname_response(struct module_qstate* qstate, struct iter_qstate* iq,
if(ntohs(r->rk.type) == LDNS_RR_TYPE_CNAME &&
query_dname_compare(*mname, r->rk.dname) == 0 &&
!iter_find_rrset_in_prepend_answer(iq, r)) {
@@ -2925,7 +2925,7 @@ index 1e0113a8..2fcbf547 100644
/* Add this relevant CNAME rrset to the prepend list.*/
if(!iter_add_prepend_answer(qstate, iq, r))
return 0;
-@@ -563,6 +583,9 @@ handle_cname_response(struct module_qstate* qstate, struct iter_qstate* iq,
+@@ -571,6 +591,9 @@ handle_cname_response(struct module_qstate* qstate, struct iter_qstate* iq,
/* Other rrsets in the section are ignored. */
}
@@ -2935,7 +2935,7 @@ index 1e0113a8..2fcbf547 100644
/* add authority rrsets to authority prepend, for wildcarded CNAMEs */
for(i=msg->rep->an_numrrsets; i<msg->rep->an_numrrsets +
msg->rep->ns_numrrsets; i++) {
-@@ -1199,6 +1222,7 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
+@@ -1231,6 +1254,7 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
uint8_t* delname;
size_t delnamelen;
struct dns_msg* msg = NULL;
@@ -2943,7 +2943,7 @@ index 1e0113a8..2fcbf547 100644
log_query_info(VERB_DETAIL, "resolving", &qstate->qinfo);
/* check effort */
-@@ -1285,8 +1309,7 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
+@@ -1317,8 +1341,7 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
}
if(msg) {
/* handle positive cache response */
@@ -2953,7 +2953,7 @@ index 1e0113a8..2fcbf547 100644
if(verbosity >= VERB_ALGO) {
log_dns_msg("msg from cache lookup", &msg->qinfo,
msg->rep);
-@@ -1294,7 +1317,22 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
+@@ -1326,7 +1349,22 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
(int)msg->rep->ttl,
(int)msg->rep->prefetch_ttl);
}
@@ -2976,7 +2976,7 @@ index 1e0113a8..2fcbf547 100644
if(type == RESPONSE_TYPE_CNAME) {
uint8_t* sname = 0;
size_t slen = 0;
-@@ -2718,6 +2756,62 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
+@@ -2801,6 +2839,62 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
sock_list_insert(&qstate->reply_origin,
&qstate->reply->addr, qstate->reply->addrlen,
qstate->region);
@@ -3039,7 +3039,7 @@ index 1e0113a8..2fcbf547 100644
if(iq->minimisation_state != DONOT_MINIMISE_STATE
&& !(iq->chase_flags & BIT_RD)) {
if(FLAGS_GET_RCODE(iq->response->rep->flags) !=
-@@ -3471,12 +3565,44 @@ processFinished(struct module_qstate* qstate, struct iter_qstate* iq,
+@@ -3563,12 +3657,44 @@ processFinished(struct module_qstate* qstate, struct iter_qstate* iq,
* but only if we did recursion. The nonrecursion referral
* from cache does not need to be stored in the msg cache. */
if(!qstate->no_cache_store && qstate->query_flags&BIT_RD) {
@@ -3085,10 +3085,10 @@ index 1e0113a8..2fcbf547 100644
qstate->return_msg = iq->response;
return 0;
diff --git a/iterator/iterator.h b/iterator/iterator.h
-index a2f1b570..e1e4a738 100644
+index 342ac207..49b0ecdd 100644
--- a/iterator/iterator.h
+++ b/iterator/iterator.h
-@@ -386,6 +386,16 @@ struct iter_qstate {
+@@ -396,6 +396,16 @@ struct iter_qstate {
*/
int minimise_count;
@@ -3104,12 +3104,12 @@ index a2f1b570..e1e4a738 100644
+
/**
* Count number of time-outs. Used to prevent resolving failures when
- * the QNAME minimisation QTYPE is blocked. */
+ * the QNAME minimisation QTYPE is blocked. Used to determine if
diff --git a/services/cache/dns.c b/services/cache/dns.c
-index 2a5bca4a..6de8863a 100644
+index 7b6e142c..6d7449f5 100644
--- a/services/cache/dns.c
+++ b/services/cache/dns.c
-@@ -967,6 +967,14 @@ dns_cache_store(struct module_env* env, struct query_info* msgqinf,
+@@ -969,6 +969,14 @@ dns_cache_store(struct module_env* env, struct query_info* msgqinf,
struct regional* region, uint32_t flags)
{
struct reply_info* rep = NULL;
@@ -3125,7 +3125,7 @@ index 2a5bca4a..6de8863a 100644
rep = reply_info_copy(msgrep, env->alloc, NULL);
if(!rep)
diff --git a/services/mesh.c b/services/mesh.c
-index 9114ef4c..3dc518e5 100644
+index 4b0c5db4..eb9cfa5b 100644
--- a/services/mesh.c
+++ b/services/mesh.c
@@ -61,6 +61,9 @@
@@ -3138,7 +3138,7 @@ index 9114ef4c..3dc518e5 100644
#include "respip/respip.h"
#include "services/listen_dnsport.h"
-@@ -1195,6 +1198,13 @@ mesh_send_reply(struct mesh_state* m, int rcode, struct reply_info* rep,
+@@ -1207,6 +1210,13 @@ mesh_send_reply(struct mesh_state* m, int rcode, struct reply_info* rep,
else secure = 0;
if(!rep && rcode == LDNS_RCODE_NOERROR)
rcode = LDNS_RCODE_SERVFAIL;
@@ -3152,7 +3152,7 @@ index 9114ef4c..3dc518e5 100644
/* send the reply */
/* We don't reuse the encoded answer if either the previous or current
* response has a local alias. We could compare the alias records
-@@ -1415,6 +1425,7 @@ struct mesh_state* mesh_area_find(struct mesh_area* mesh,
+@@ -1434,6 +1444,7 @@ struct mesh_state* mesh_area_find(struct mesh_area* mesh,
key.s.is_valrec = valrec;
key.s.qinfo = *qinfo;
key.s.query_flags = qflags;
@@ -3160,7 +3160,7 @@ index 9114ef4c..3dc518e5 100644
/* We are searching for a similar mesh state when we DO want to
* aggregate the state. Thus unique is set to NULL. (default when we
* desire aggregation).*/
-@@ -1461,6 +1472,10 @@ int mesh_state_add_reply(struct mesh_state* s, struct edns_data* edns,
+@@ -1480,6 +1491,10 @@ int mesh_state_add_reply(struct mesh_state* s, struct edns_data* edns,
if(!r)
return 0;
r->query_reply = *rep;
@@ -3172,11 +3172,11 @@ index 9114ef4c..3dc518e5 100644
if(edns->opt_list) {
r->edns.opt_list = edns_opt_copy_region(edns->opt_list,
diff --git a/util/config_file.c b/util/config_file.c
-index 52ca5a18..0660248f 100644
+index 0e9ee471..a5fd72e0 100644
--- a/util/config_file.c
+++ b/util/config_file.c
-@@ -1460,6 +1460,8 @@ config_delete(struct config_file* cfg)
- free(cfg->dnstap_socket_path);
+@@ -1495,6 +1495,8 @@ config_delete(struct config_file* cfg)
+ free(cfg->dnstap_tls_client_cert_file);
free(cfg->dnstap_identity);
free(cfg->dnstap_version);
+ if (cfg->rpz_cstr)
@@ -3185,10 +3185,10 @@ index 52ca5a18..0660248f 100644
config_deldblstrlist(cfg->ratelimit_below_domain);
config_delstrlist(cfg->python_script);
diff --git a/util/config_file.h b/util/config_file.h
-index 8739ca2a..a2dcf215 100644
+index 66e5025d..504f4f92 100644
--- a/util/config_file.h
+++ b/util/config_file.h
-@@ -499,6 +499,11 @@ struct config_file {
+@@ -522,6 +522,11 @@ struct config_file {
/** true to disable DNSSEC lameness check in iterator */
int disable_dnssec_lame_check;
@@ -3201,10 +3201,10 @@ index 8739ca2a..a2dcf215 100644
int ip_ratelimit;
/** number of slabs for ip_ratelimit cache */
diff --git a/util/configlexer.lex b/util/configlexer.lex
-index deedffa5..301458a3 100644
+index 83cea4b9..9a7feea4 100644
--- a/util/configlexer.lex
+++ b/util/configlexer.lex
-@@ -446,6 +446,10 @@ dnstap-log-forwarder-query-messages{COLON} {
+@@ -467,6 +467,10 @@ dnstap-log-forwarder-query-messages{COLON} {
YDVAR(1, VAR_DNSTAP_LOG_FORWARDER_QUERY_MESSAGES) }
dnstap-log-forwarder-response-messages{COLON} {
YDVAR(1, VAR_DNSTAP_LOG_FORWARDER_RESPONSE_MESSAGES) }
@@ -3216,18 +3216,18 @@ index deedffa5..301458a3 100644
ip-ratelimit{COLON} { YDVAR(1, VAR_IP_RATELIMIT) }
ratelimit{COLON} { YDVAR(1, VAR_RATELIMIT) }
diff --git a/util/configparser.y b/util/configparser.y
-index d471babe..cb6b1d63 100644
+index fe600a99..ce43390f 100644
--- a/util/configparser.y
+++ b/util/configparser.y
-@@ -125,6 +125,7 @@ extern struct config_parser_state* cfg_parser;
+@@ -128,6 +128,7 @@ extern struct config_parser_state* cfg_parser;
%token VAR_DNSTAP_LOG_CLIENT_RESPONSE_MESSAGES
%token VAR_DNSTAP_LOG_FORWARDER_QUERY_MESSAGES
%token VAR_DNSTAP_LOG_FORWARDER_RESPONSE_MESSAGES
+%token VAR_RPZ VAR_RPZ_ENABLE VAR_RPZ_ZONE VAR_RPZ_OPTION
%token VAR_RESPONSE_IP_TAG VAR_RESPONSE_IP VAR_RESPONSE_IP_DATA
%token VAR_HARDEN_ALGO_DOWNGRADE VAR_IP_TRANSPARENT
- %token VAR_DISABLE_DNSSEC_LAME_CHECK
-@@ -173,7 +174,7 @@ extern struct config_parser_state* cfg_parser;
+ %token VAR_IP_DSCP
+@@ -179,7 +180,7 @@ extern struct config_parser_state* cfg_parser;
%%
toplevelvars: /* empty */ | toplevelvars toplevelvar ;
@@ -3236,7 +3236,7 @@ index d471babe..cb6b1d63 100644
forwardstart contents_forward | pythonstart contents_py |
rcstart contents_rc | dtstart contents_dt | viewstart contents_view |
dnscstart contents_dnsc | cachedbstart contents_cachedb |
-@@ -2837,6 +2838,50 @@ dt_dnstap_log_forwarder_response_messages: VAR_DNSTAP_LOG_FORWARDER_RESPONSE_MES
+@@ -2939,6 +2940,50 @@ dt_dnstap_log_forwarder_response_messages: VAR_DNSTAP_LOG_FORWARDER_RESPONSE_MES
free($2);
}
;
@@ -3384,7 +3384,7 @@ index 729877ba..ccd1a0c2 100644
/**
diff --git a/util/netevent.c b/util/netevent.c
-index 9fe5da2d..037e70d1 100644
+index 3e7a433e..f20d806f 100644
--- a/util/netevent.c
+++ b/util/netevent.c
@@ -57,6 +57,9 @@
@@ -3397,7 +3397,7 @@ index 9fe5da2d..037e70d1 100644
/* -------- Start of local definitions -------- */
/** if CMSG_ALIGN is not defined on this platform, a workaround */
-@@ -590,6 +593,9 @@ comm_point_udp_ancil_callback(int fd, short event, void* arg)
+@@ -596,6 +599,9 @@ comm_point_udp_ancil_callback(int fd, short event, void* arg)
struct cmsghdr* cmsg;
#endif /* S_SPLINT_S */
@@ -3407,7 +3407,7 @@ index 9fe5da2d..037e70d1 100644
rep.c = (struct comm_point*)arg;
log_assert(rep.c->type == comm_udp);
-@@ -679,6 +685,9 @@ comm_point_udp_callback(int fd, short event, void* arg)
+@@ -685,6 +691,9 @@ comm_point_udp_callback(int fd, short event, void* arg)
int i;
struct sldns_buffer *buffer;
@@ -3417,7 +3417,7 @@ index 9fe5da2d..037e70d1 100644
rep.c = (struct comm_point*)arg;
log_assert(rep.c->type == comm_udp);
-@@ -722,6 +731,9 @@ comm_point_udp_callback(int fd, short event, void* arg)
+@@ -728,6 +737,9 @@ comm_point_udp_callback(int fd, short event, void* arg)
(void)comm_point_send_udp_msg(rep.c, buffer,
(struct sockaddr*)&rep.addr, rep.addrlen);
}
@@ -3427,7 +3427,7 @@ index 9fe5da2d..037e70d1 100644
if(!rep.c || rep.c->fd != fd) /* commpoint closed to -1 or reused for
another UDP port. Note rep.c cannot be reused with TCP fd. */
break;
-@@ -3192,6 +3204,9 @@ comm_point_send_reply(struct comm_reply *repinfo)
+@@ -3175,6 +3187,9 @@ comm_point_send_reply(struct comm_reply *repinfo)
repinfo->c->tcp_timeout_msec);
}
}
@@ -3437,7 +3437,7 @@ index 9fe5da2d..037e70d1 100644
}
void
-@@ -3201,6 +3216,9 @@ comm_point_drop_reply(struct comm_reply* repinfo)
+@@ -3184,6 +3199,9 @@ comm_point_drop_reply(struct comm_reply* repinfo)
return;
log_assert(repinfo->c);
log_assert(repinfo->c->type != comm_tcp_accept);
@@ -3447,7 +3447,7 @@ index 9fe5da2d..037e70d1 100644
if(repinfo->c->type == comm_udp)
return;
if(repinfo->c->tcp_req_info)
-@@ -3222,6 +3240,9 @@ comm_point_start_listening(struct comm_point* c, int newfd, int msec)
+@@ -3205,6 +3223,9 @@ comm_point_start_listening(struct comm_point* c, int newfd, int msec)
{
verbose(VERB_ALGO, "comm point start listening %d (%d msec)",
c->fd==-1?newfd:c->fd, msec);
@@ -3458,7 +3458,7 @@ index 9fe5da2d..037e70d1 100644
/* no use to start listening no free slots. */
return;
diff --git a/util/netevent.h b/util/netevent.h
-index d80c72b3..0233292f 100644
+index bb2cd1e5..666067e8 100644
--- a/util/netevent.h
+++ b/util/netevent.h
@@ -120,6 +120,10 @@ struct comm_reply {
diff --git a/contrib/unbound/contrib/ios/15-ios.conf b/contrib/unbound/contrib/ios/15-ios.conf
new file mode 100644
index 000000000000..364ed6ebfd29
--- /dev/null
+++ b/contrib/unbound/contrib/ios/15-ios.conf
@@ -0,0 +1,41 @@
+#### iPhoneOS/iOS
+#
+# It takes recent enough Xcode to use following two targets. It shouldn't
+# be a problem by now, but if they don't work, original targets below
+# that depend on manual definition of environment variables should still
+# work...
+#
+my %targets = (
+ "ios-common" => {
+ template => 1,
+ inherit_from => [ "darwin-common" ],
+ sys_id => "iOS",
+ disable => [ "engine", "async" ],
+ },
+ "ios-xcrun" => {
+ inherit_from => [ "ios-common", asm("armv4_asm") ],
+ bn_ops => [ "BN_LLONG", "RC4_CHAR" ],
+ perlasm_scheme => "ios32",
+ },
+ "ios64-xcrun" => {
+ inherit_from => [ "ios-common", asm("aarch64_asm") ],
+ bn_ops => [ "SIXTY_FOUR_BIT_LONG", "RC4_CHAR" ],
+ perlasm_scheme => "ios64",
+ },
+ "iossimulator-xcrun" => {
+ inherit_from => [ "ios-common" ],
+ },
+
+ "iphoneos-cross" => {
+ inherit_from => [ "ios-common" ],
+ cflags => add("-Wall -fno-common"),
+ },
+ "ios-cross" => {
+ inherit_from => [ "ios-xcrun" ],
+ cflags => add("-Wall -fno-common"),
+ },
+ "ios64-cross" => {
+ inherit_from => [ "ios64-xcrun" ],
+ cflags => add("-Wall -fno-common"),
+ },
+);
diff --git a/contrib/unbound/contrib/ios/install_expat.sh b/contrib/unbound/contrib/ios/install_expat.sh
new file mode 100755
index 000000000000..9471b5aff2dd
--- /dev/null
+++ b/contrib/unbound/contrib/ios/install_expat.sh
@@ -0,0 +1,56 @@
+#!/usr/bin/env bash
+
+echo "Downloading Expat"
+if ! curl -L -k -s -o expat-2.2.9.tar.gz https://github.com/libexpat/libexpat/releases/download/R_2_2_9/expat-2.2.9.tar.gz;
+then
+ echo "Failed to download Expat"
+ exit 1
+fi
+
+echo "Unpacking Expat"
+rm -rf ./expat-2.2.9
+if ! tar -xf expat-2.2.9.tar.gz;
+then
+ echo "Failed to unpack Expat"
+ exit 1
+fi
+
+cd expat-2.2.9 || exit 1
+
+export PKG_CONFIG_PATH="$IOS_PREFIX/lib/pkgconfig"
+
+echo "Configuring Expat"
+if ! ./configure \
+ --build="$AUTOTOOLS_BUILD" --host="$AUTOTOOLS_HOST" \
+ --prefix="$IOS_PREFIX" ; then
+ echo "Error: Failed to configure Expat"
+ cat config.log
+ exit 1
+fi
+
+# Cleanup warnings, https://github.com/libexpat/libexpat/issues/383
+echo "Fixing Makefiles"
+(IFS="" find "$PWD" -name 'Makefile' -print | while read -r file
+do
+ cp -p "$file" "$file.fixed"
+ sed 's|-Wduplicated-cond ||g; s|-Wduplicated-branches ||g; s|-Wlogical-op ||g' "$file" > "$file.fixed"
+ mv "$file.fixed" "$file"
+
+ cp -p "$file" "$file.fixed"
+ sed 's|-Wrestrict ||g; s|-Wjump-misses-init ||g; s|-Wmisleading-indentation ||g' "$file" > "$file.fixed"
+ mv "$file.fixed" "$file"
+done)
+
+echo "Building Expat"
+if ! make; then
+ echo "Failed to build Expat"
+ exit 1
+fi
+
+echo "Installing Expat"
+if ! make install; then
+ echo "Failed to install Expat"
+ exit 1
+fi
+
+exit 0
diff --git a/contrib/unbound/contrib/ios/install_openssl.sh b/contrib/unbound/contrib/ios/install_openssl.sh
new file mode 100755
index 000000000000..31e65d64e353
--- /dev/null
+++ b/contrib/unbound/contrib/ios/install_openssl.sh
@@ -0,0 +1,52 @@
+#!/usr/bin/env bash
+
+echo "Downloading OpenSSL"
+if ! curl -L -k -s -o openssl-1.1.1d.tar.gz https://www.openssl.org/source/openssl-1.1.1d.tar.gz;
+then
+ echo "Failed to download OpenSSL"
+ exit 1
+fi
+
+echo "Unpacking OpenSSL"
+rm -rf ./openssl-1.1.1d
+if ! tar -xf openssl-1.1.1d.tar.gz;
+then
+ echo "Failed to unpack OpenSSL"
+ exit 1
+fi
+
+cd openssl-1.1.1d || exit 1
+
+if ! cp ../contrib/ios/15-ios.conf Configurations/; then
+ echo "Failed to copy OpenSSL ios config"
+ exit 1
+fi
+
+# OpenSSL 1.1.1d patch. OK to remove once OpenSSL version is bumped.
+# ocsp.c:947:23: error: 'fork' is unavailable: not available on tvOS and watchOS.
+# Also see https://github.com/openssl/openssl/issues/7607.
+if ! patch -u -p0 < ../contrib/ios/openssl.patch; then
+ echo "Failed to patch OpenSSL"
+ exit 1
+fi
+
+echo "Configuring OpenSSL"
+if ! ./Configure "$OPENSSL_HOST" -DNO_FORK no-comp no-asm no-hw no-engine no-tests no-unit-test \
+ --prefix="$IOS_PREFIX" --openssldir="$IOS_PREFIX"; then
+ echo "Failed to configure OpenSSL"
+ exit 1
+fi
+
+echo "Building OpenSSL"
+if ! make; then
+ echo "Failed to build OpenSSL"
+ exit 1
+fi
+
+echo "Installing OpenSSL"
+if ! make install_sw; then
+ echo "Failed to install OpenSSL"
+ exit 1
+fi
+
+exit 0
diff --git a/contrib/unbound/contrib/ios/install_tools.sh b/contrib/unbound/contrib/ios/install_tools.sh
new file mode 100755
index 000000000000..55fef454e852
--- /dev/null
+++ b/contrib/unbound/contrib/ios/install_tools.sh
@@ -0,0 +1,8 @@
+#!/usr/bin/env bash
+
+# This step should install tools needed for all packages - OpenSSL, Expat and Unbound
+echo "Updating tools"
+brew update 1>/dev/null
+echo "Installing tools"
+# already installed are: autoconf automake libtool pkg-config
+brew install curl perl 1>/dev/null
diff --git a/contrib/unbound/contrib/ios/openssl.patch b/contrib/unbound/contrib/ios/openssl.patch
new file mode 100644
index 000000000000..58cef232c9e9
--- /dev/null
+++ b/contrib/unbound/contrib/ios/openssl.patch
@@ -0,0 +1,48 @@
+--- apps/speed.c
++++ apps/speed.c
+@@ -99,6 +99,13 @@
+ #endif
+ #include <openssl/modes.h>
+
++/* fork() breaks AppleTVOS, WatchOS, AppleTVSimulator and WatchSimulator */
++/* Users should configure with -DNO_FORK */
++#if defined(NO_FORK)
++# undef HAVE_FORK
++# define HAVE_FORK 0
++#endif
++
+ #ifndef HAVE_FORK
+ # if defined(OPENSSL_SYS_VMS) || defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_VXWORKS)
+ # define HAVE_FORK 0
+@@ -110,6 +117,7 @@
+ #if HAVE_FORK
+ # undef NO_FORK
+ #else
++# undef NO_FORK
+ # define NO_FORK
+ #endif
+
+--- apps/ocsp.c
++++ apps/ocsp.c
+@@ -36,6 +36,13 @@
+ # include <openssl/x509v3.h>
+ # include <openssl/rand.h>
+
++/* fork() breaks AppleTVOS, WatchOS, AppleTVSimulator and WatchSimulator */
++/* Users should configure with -DNO_FORK */
++#if defined(NO_FORK)
++# undef HAVE_FORK
++# define HAVE_FORK 0
++#endif
++
+ #ifndef HAVE_FORK
+ # if defined(OPENSSL_SYS_VMS) || defined(OPENSSL_SYS_WINDOWS)
+ # define HAVE_FORK 0
+@@ -47,6 +54,7 @@
+ #if HAVE_FORK
+ # undef NO_FORK
+ #else
++# undef NO_FORK
+ # define NO_FORK
+ #endif
+
diff --git a/contrib/unbound/contrib/ios/setenv_ios.sh b/contrib/unbound/contrib/ios/setenv_ios.sh
new file mode 100755
index 000000000000..df433d17c2d3
--- /dev/null
+++ b/contrib/unbound/contrib/ios/setenv_ios.sh
@@ -0,0 +1,274 @@
+#!/usr/bin/env bash
+
+# ====================================================================
+# Sets the cross compile environment for Xcode/iOS
+#
+# Based upon OpenSSL's setenv-ios.sh by TH, JW, and SM.
+# Heavily modified by JWW for Crypto++.
+# Modified by JWW for Unbound.
+# ====================================================================
+
+#########################################
+##### Some validation #####
+#########################################
+
+# In the past we could mostly infer arch or cpu from the SDK (and
+# mostly vice-versa). Nowadays we need it set for us because Apple
+# platforms can be either 32-bit or 64-bit.
+
+if [ -z "$IOS_SDK" ]; then
+ echo "IOS_SDK is not set. Please set it"
+ [[ "$0" = "${BASH_SOURCE[0]}" ]] && exit 1 || return 1
+fi
+
+if [ -z "$IOS_CPU" ]; then
+ echo "IOS_CPU is not set. Please set it"
+ [[ "$0" = "${BASH_SOURCE[0]}" ]] && exit 1 || return 1
+fi
+
+# cryptest-ios.sh may run this script without sourcing.
+if [ "$0" = "${BASH_SOURCE[0]}" ]; then
+ echo "setenv-ios.sh is usually sourced, but not this time."
+fi
+
+#########################################
+##### Small Fixups, if needed #####
+#########################################
+
+if [[ "$IOS_SDK" == "iPhone" ]]; then
+ IOS_SDK=iPhoneOS
+fi
+
+if [[ "$IOS_SDK" == "iPhoneOSSimulator" ]]; then
+ IOS_SDK=iPhoneSimulator
+fi
+
+if [[ "$IOS_SDK" == "TV" || "$IOS_SDK" == "AppleTV" ]]; then
+ IOS_SDK=AppleTVOS
+fi
+
+if [[ "$IOS_SDK" == "Watch" || "$IOS_SDK" == "AppleWatch" ]]; then
+ IOS_SDK=WatchOS
+fi
+
+if [[ "$IOS_CPU" == "aarch64" || "$IOS_CPU" == "armv8"* ]] ; then
+ IOS_CPU=arm64
+fi
+
+########################################
+##### Environment #####
+########################################
+
+# The flags below were tested with Xcode 8 on Travis. If
+# you use downlevel versions of Xcode, then you can push
+# xxx-version-min=n lower. For example, Xcode 6 can use
+# -miphoneos-version-min=5.
+
+# iPhones can be either 32-bit or 64-bit
+if [[ "$IOS_SDK" == "iPhoneOS" && "$IOS_CPU" == "armv7"* ]]; then
+ MIN_VER=-miphoneos-version-min=6
+elif [[ "$IOS_SDK" == "iPhoneOS" && "$IOS_CPU" == "arm64" ]]; then
+ MIN_VER=-miphoneos-version-min=6
+
+# Fixups for convenience
+elif [[ "$IOS_SDK" == "iPhoneOS" && "$IOS_CPU" == "i386" ]]; then
+ IOS_SDK=iPhoneSimulator
+ # MIN_VER=-miphoneos-version-min=6
+ MIN_VER=-miphonesimulator-version-min=6
+elif [[ "$IOS_SDK" == "iPhoneOS" && "$IOS_CPU" == "x86_64" ]]; then
+ IOS_SDK=iPhoneSimulator
+ # MIN_VER=-miphoneos-version-min=6
+ MIN_VER=-miphonesimulator-version-min=6
+
+# Simulator builds
+elif [[ "$IOS_SDK" == "iPhoneSimulator" && "$IOS_CPU" == "i386" ]]; then
+ MIN_VER=-miphonesimulator-version-min=6
+elif [[ "$IOS_SDK" == "iPhoneSimulator" && "$IOS_CPU" == "x86_64" ]]; then
+ MIN_VER=-miphonesimulator-version-min=6
+
+# Apple TV can be 32-bit Intel (1st gen), 32-bit ARM (2nd, 3rd gen) or 64-bit ARM (4th gen)
+elif [[ "$IOS_SDK" == "AppleTVOS" && "$IOS_CPU" == "i386" ]]; then
+ MIN_VER=-mappletvos-version-min=6
+elif [[ "$IOS_SDK" == "AppleTVOS" && "$IOS_CPU" == "armv7"* ]]; then
+ MIN_VER=-mappletvos-version-min=6
+elif [[ "$IOS_SDK" == "AppleTVOS" && "$IOS_CPU" == "arm64" ]]; then
+ MIN_VER=-mappletvos-version-min=6
+
+# Simulator builds
+elif [[ "$IOS_SDK" == "AppleTVSimulator" && "$IOS_CPU" == "i386" ]]; then
+ MIN_VER=-mappletvsimulator-version-min=6
+elif [[ "$IOS_SDK" == "AppleTVSimulator" && "$IOS_CPU" == "x86_64" ]]; then
+ MIN_VER=-mappletvsimulator-version-min=6
+
+# Watch can be either 32-bit or 64-bit ARM. TODO: figure out which
+# -mwatchos-version-min=n is needed for arm64. 9 is not enough.
+elif [[ "$IOS_SDK" == "WatchOS" && "$IOS_CPU" == "armv7"* ]]; then
+ MIN_VER=-mwatchos-version-min=6
+elif [[ "$IOS_SDK" == "WatchOS" && "$IOS_CPU" == "arm64" ]]; then
+ MIN_VER=-mwatchos-version-min=10
+
+# Simulator builds. TODO: figure out which -watchos-version-min=n
+# is needed for arm64. 6 compiles and links, but is it correct?
+elif [[ "$IOS_SDK" == "WatchSimulator" && "$IOS_CPU" == "i386" ]]; then
+ MIN_VER=-mwatchsimulator-version-min=6
+elif [[ "$IOS_SDK" == "WatchSimulator" && "$IOS_CPU" == "x86_64" ]]; then
+ MIN_VER=-mwatchsimulator-version-min=6
+
+# And the final catch-all
+else
+ echo "IOS_SDK and IOS_CPU are not valid. Please fix them"
+ [[ "$0" = "${BASH_SOURCE[0]}" ]] && exit 1 || return 1
+fi
+
+#####################################################################
+
+# Xcode 6 and below cannot handle -miphonesimulator-version-min
+# Fix it so the simulator will compile as expected. This trick
+# may work on other SDKs, but it was not tested.
+
+if [ -n "$(command -v xcodebuild 2>/dev/null)" ]; then
+ # Output of xcodebuild is similar to "Xcode 6.2". The first cut gets
+ # the dotted decimal value. The second cut gets the major version.
+ XCODE_VERSION=$(xcodebuild -version 2>/dev/null | head -n 1 | cut -f2 -d" " | cut -f1 -d".")
+ if [ -z "$XCODE_VERSION" ]; then XCODE_VERSION=100; fi
+
+ if [ "$XCODE_VERSION" -le 6 ]; then
+ MIN_VER="${MIN_VER//iphonesimulator/iphoneos}"
+ fi
+fi
+
+#####################################################################
+
+# Allow a user override? I think we should be doing this. The use case is,
+# move /Applications/Xcode somewhere else for a side-by-side installation.
+if [ -z "${XCODE_DEVELOPER-}" ]; then
+ XCODE_DEVELOPER=$(xcode-select -print-path 2>/dev/null)
+fi
+
+if [ ! -d "$XCODE_DEVELOPER" ]; then
+ echo "ERROR: unable to find XCODE_DEVELOPER directory."
+ [ "$0" = "${BASH_SOURCE[0]}" ] && exit 1 || return 1
+fi
+
+# XCODE_DEVELOPER_SDK is the SDK location.
+XCODE_DEVELOPER_SDK="$XCODE_DEVELOPER/Platforms/$IOS_SDK.platform"
+
+if [ ! -d "$XCODE_DEVELOPER_SDK" ]; then
+ echo "ERROR: unable to find XCODE_DEVELOPER_SDK directory."
+ echo " Is the SDK supported by Xcode and installed?"
+ [ "$0" = "${BASH_SOURCE[0]}" ] && exit 1 || return 1
+fi
+
+# XCODE_TOOLCHAIN is the location of the actual compiler tools.
+if [ -d "$XCODE_DEVELOPER/Toolchains/XcodeDefault.xctoolchain/usr/bin/" ]; then
+ XCODE_TOOLCHAIN="$XCODE_DEVELOPER/Toolchains/XcodeDefault.xctoolchain/usr/bin/"
+elif [ -d "$XCODE_DEVELOPER_SDK/Developer/usr/bin/" ]; then
+ XCODE_TOOLCHAIN="$XCODE_DEVELOPER_SDK/Developer/usr/bin/"
+fi
+
+if [ -z "$XCODE_TOOLCHAIN" ] || [ ! -d "$XCODE_TOOLCHAIN" ]; then
+ echo "ERROR: unable to find Xcode cross-compiler tools."
+ [ "$0" = "${BASH_SOURCE[0]}" ] && exit 1 || return 1
+fi
+
+# XCODE_SDK is the SDK name/version being used - adjust the list as appropriate.
+# For example, remove 4.3, 6.2, and 6.1 if they are not installed. We go back to
+# the 1.0 SDKs because Apple WatchOS uses low numbers, like 2.0 and 2.1.
+XCODE_SDK=
+for i in $(seq -f "%.1f" 30.0 -0.1 1.0)
+do
+ if [ -d "$XCODE_DEVELOPER_SDK/Developer/SDKs/$IOS_SDK$i.sdk" ]; then
+ XCODE_SDK="$IOS_SDK$i.sdk"
+ break
+ fi
+done
+
+# Error checking
+if [ -z "$XCODE_SDK" ]; then
+ echo "ERROR: unable to find a SDK."
+ [ "$0" = "${BASH_SOURCE[0]}" ] && exit 1 || return 1
+fi
+
+IOS_SYSROOT="$XCODE_DEVELOPER_SDK/Developer/SDKs/$XCODE_SDK"
+
+if [ -z "$IOS_SYSROOT" ] || [ ! -d "$IOS_SYSROOT" ]; then
+ echo "ERROR: unable to find IOS_SYSROOT directory."
+ [ "$0" = "${BASH_SOURCE[0]}" ] && exit 1 || return 1
+fi
+
+#####################################################################
+
+# We want to set AR=libtool and ARFLAGS="-static -o",
+# but I am not sure Autotools can handle it.
+CPP=cpp; CC=clang; CXX=clang++; LD=ld
+AS=as; AR=ar; RANLIB=ranlib; STRIP=strip
+
+# Error checking
+if [ ! -e "$XCODE_TOOLCHAIN/$CC" ]; then
+ echo "ERROR: Failed to find iOS clang. Please edit this script."
+ [ "$0" = "${BASH_SOURCE[0]}" ] && exit 1 || return 1
+fi
+
+# Error checking
+if [ ! -e "$XCODE_TOOLCHAIN/$CXX" ]; then
+ echo "ERROR: Failed to find iOS clang++. Please edit this script."
+ [ "$0" = "${BASH_SOURCE[0]}" ] && exit 1 || return 1
+fi
+
+# Error checking
+if [ ! -e "$XCODE_TOOLCHAIN/$RANLIB" ]; then
+ echo "ERROR: Failed to find iOS ranlib. Please edit this script."
+ [ "$0" = "${BASH_SOURCE[0]}" ] && exit 1 || return 1
+fi
+
+# Error checking
+if [ ! -e "$XCODE_TOOLCHAIN/$AR" ]; then
+ echo "ERROR: Failed to find iOS ar. Please edit this script."
+ [ "$0" = "${BASH_SOURCE[0]}" ] && exit 1 || return 1
+fi
+
+# Error checking
+if [ ! -e "$XCODE_TOOLCHAIN/$AS" ]; then
+ echo "ERROR: Failed to find iOS as. Please edit this script."
+ [ "$0" = "${BASH_SOURCE[0]}" ] && exit 1 || return 1
+fi
+
+# Error checking
+if [ ! -e "$XCODE_TOOLCHAIN/$LD" ]; then
+ echo "ERROR: Failed to find iOS ld. Please edit this script."
+ [ "$0" = "${BASH_SOURCE[0]}" ] && exit 1 || return 1
+fi
+
+#####################################################################
+
+LENGTH=${#XCODE_TOOLCHAIN}
+SUBSTR=${PATH:0:$LENGTH}
+if [ "$SUBSTR" != "$XCODE_TOOLCHAIN" ]; then
+ export PATH="$XCODE_TOOLCHAIN":"$PATH"
+fi
+
+#####################################################################
+
+export CPP CC CXX LD AS AR RANLIB STRIP
+export IOS_SYSROOT
+export CFLAGS="-arch $IOS_CPU $MIN_VER --sysroot=$IOS_SYSROOT"
+export CXXFLAGS="-arch $IOS_CPU $MIN_VER -stdlib-libc++ --sysroot=$IOS_SYSROOT"
+
+#####################################################################
+
+echo "XCODE_TOOLCHAIN: $XCODE_TOOLCHAIN"
+
+echo "CPP: $(command -v "$CPP")"
+echo "CC: $(command -v "$CC")"
+echo "CXX: $(command -v "$CXX")"
+echo "LD: $(command -v "$LD")"
+echo "AS: $(command -v "$AS")"
+echo "AR: $(command -v "$AR")"
+
+echo "IOS_SYSROOT: $IOS_SYSROOT"
+
+echo "CPPFLAGS: $CPPFLAGS"
+echo "CFLAGS: $CFLAGS"
+echo "CXXFLAGS: $CXXFLAGS"
+
+[ "$0" = "${BASH_SOURCE[0]}" ] && exit 0 || return 0
diff --git a/contrib/unbound/contrib/libunbound.pc.in b/contrib/unbound/contrib/libunbound.pc.in
index 1442ed523adc..453bf7d4f8b1 100644
--- a/contrib/unbound/contrib/libunbound.pc.in
+++ b/contrib/unbound/contrib/libunbound.pc.in
@@ -7,8 +7,7 @@ Name: unbound
Description: Library with validating, recursive, and caching DNS resolver
URL: http://www.unbound.net
Version: @PACKAGE_VERSION@
-Requires: @PC_CRYPTO_DEPENDENCY@ @PC_LIBEVENT_DEPENDENCY@
-Requires.private: @PC_PY_DEPENDENCY@ @PC_LIBBSD_DEPENDENCY@
+Requires.private: @PC_PY_DEPENDENCY@ @PC_LIBBSD_DEPENDENCY@ @PC_CRYPTO_DEPENDENCY@ @PC_LIBEVENT_DEPENDENCY@
Libs: -L${libdir} -lunbound
Libs.private: @SSLLIB@ @LIBS@
Cflags: -I${includedir}
diff --git a/contrib/unbound/contrib/unbound.service.in b/contrib/unbound/contrib/unbound.service.in
index 8c51bcbbef78..8ebe529c9ab6 100644
--- a/contrib/unbound/contrib/unbound.service.in
+++ b/contrib/unbound/contrib/unbound.service.in
@@ -76,7 +76,7 @@ RestrictSUIDSGID=yes
ReadWritePaths=@UNBOUND_RUN_DIR@ @UNBOUND_CHROOT_DIR@
# Below rules are needed when chroot is enabled (usually it's enabled by default).
-# If chroot is disabled like chrooot: "" then they may be safely removed.
+# If chroot is disabled like chroot: "" then they may be safely removed.
TemporaryFileSystem=@UNBOUND_CHROOT_DIR@/dev:ro
TemporaryFileSystem=@UNBOUND_CHROOT_DIR@/run:ro
BindReadOnlyPaths=-/run/systemd/notify:@UNBOUND_CHROOT_DIR@/run/systemd/notify
diff --git a/contrib/unbound/daemon/acl_list.c b/contrib/unbound/daemon/acl_list.c
index c16a920d99ee..84324575e718 100644
--- a/contrib/unbound/daemon/acl_list.c
+++ b/contrib/unbound/daemon/acl_list.c
@@ -273,7 +273,7 @@ check_data(const char* data, const struct config_strlist* head)
if(res == 0)
return 1;
log_err("rr data [char %d] parse error %s",
- (int)LDNS_WIREPARSE_OFFSET(res)-13,
+ (int)LDNS_WIREPARSE_OFFSET(res)-2,
sldns_get_errorstr_parse(res));
return 0;
}
diff --git a/contrib/unbound/daemon/daemon.c b/contrib/unbound/daemon/daemon.c
index 8b0fc3483ab7..5d4279259ed6 100644
--- a/contrib/unbound/daemon/daemon.c
+++ b/contrib/unbound/daemon/daemon.c
@@ -451,11 +451,9 @@ daemon_create_workers(struct daemon* daemon)
fatal_exit("out of memory during daemon init");
if(daemon->cfg->dnstap) {
#ifdef USE_DNSTAP
- daemon->dtenv = dt_create(daemon->cfg->dnstap_socket_path,
- (unsigned int)daemon->num);
+ daemon->dtenv = dt_create(daemon->cfg);
if (!daemon->dtenv)
fatal_exit("dt_create failed");
- dt_apply_cfg(daemon->dtenv, daemon->cfg);
#else
fatal_exit("dnstap enabled in config but not built with dnstap support");
#endif
@@ -783,7 +781,7 @@ daemon_delete(struct daemon* daemon)
# endif
# ifdef HAVE_OPENSSL_CONFIG
EVP_cleanup();
-# if (OPENSSL_VERSION_NUMBER < 0x10100000) && !defined(OPENSSL_NO_ENGINE)
+# if (OPENSSL_VERSION_NUMBER < 0x10100000) && !defined(OPENSSL_NO_ENGINE) && defined(HAVE_ENGINE_CLEANUP)
ENGINE_cleanup();
# endif
CONF_modules_free();
diff --git a/contrib/unbound/daemon/remote.c b/contrib/unbound/daemon/remote.c
index 1782a39cad7c..aa263d074c64 100644
--- a/contrib/unbound/daemon/remote.c
+++ b/contrib/unbound/daemon/remote.c
@@ -329,7 +329,7 @@ add_open(const char* ip, int nr, struct listen_port** list, int noproto_is_err,
/* open fd */
fd = create_tcp_accept_sock(res, 1, &noproto, 0,
- cfg->ip_transparent, 0, cfg->ip_freebind, cfg->use_systemd);
+ cfg->ip_transparent, 0, cfg->ip_freebind, cfg->use_systemd, cfg->ip_dscp);
freeaddrinfo(res);
}
@@ -804,6 +804,9 @@ print_mem(RES* ssl, struct worker* worker, struct daemon* daemon,
size_t dnscrypt_shared_secret = 0;
size_t dnscrypt_nonce = 0;
#endif /* USE_DNSCRYPT */
+#ifdef WITH_DYNLIBMODULE
+ size_t dynlib = 0;
+#endif /* WITH_DYNLIBMODULE */
msg = slabhash_get_mem(daemon->env->msg_cache);
rrset = slabhash_get_mem(&daemon->env->rrset_cache->table);
val = mod_get_mem(&worker->env, "validator");
@@ -822,6 +825,9 @@ print_mem(RES* ssl, struct worker* worker, struct daemon* daemon,
dnscrypt_nonce = slabhash_get_mem(daemon->dnscenv->nonces_cache);
}
#endif /* USE_DNSCRYPT */
+#ifdef WITH_DYNLIBMODULE
+ dynlib = mod_get_mem(&worker->env, "dynlib");
+#endif /* WITH_DYNLIBMODULE */
if(!print_longnum(ssl, "mem.cache.rrset"SQ, rrset))
return 0;
@@ -849,6 +855,10 @@ print_mem(RES* ssl, struct worker* worker, struct daemon* daemon,
dnscrypt_nonce))
return 0;
#endif /* USE_DNSCRYPT */
+#ifdef WITH_DYNLIBMODULE
+ if(!print_longnum(ssl, "mem.mod.dynlibmod"SQ, dynlib))
+ return 0;
+#endif /* WITH_DYNLIBMODULE */
if(!print_longnum(ssl, "mem.streamwait"SQ,
(size_t)s->svr.mem_stream_wait))
return 0;
@@ -907,7 +917,7 @@ static int
print_ext(RES* ssl, struct ub_stats_info* s)
{
int i;
- char nm[16];
+ char nm[32];
const sldns_rr_descriptor* desc;
const sldns_lookup_table* lt;
/* TYPE */
@@ -1124,6 +1134,10 @@ parse_arg_name(RES* ssl, char* str, uint8_t** res, size_t* len, int* labs)
*res = NULL;
*len = 0;
*labs = 0;
+ if(str[0] == '\0') {
+ ssl_printf(ssl, "error: this option requires a domain name\n");
+ return 0;
+ }
status = sldns_str2wire_dname_buf(str, nm, &nmlen);
if(status != 0) {
ssl_printf(ssl, "error cannot parse name %s at %d: %s\n", str,
diff --git a/contrib/unbound/daemon/unbound.c b/contrib/unbound/daemon/unbound.c
index af76fc84fe51..3f96603c4307 100644
--- a/contrib/unbound/daemon/unbound.c
+++ b/contrib/unbound/daemon/unbound.c
@@ -88,6 +88,14 @@
# include "nss.h"
#endif
+#ifdef HAVE_TARGETCONDITIONALS_H
+#include <TargetConditionals.h>
+#endif
+
+#if defined(TARGET_OS_TV) || defined(TARGET_OS_WATCH)
+#undef HAVE_FORK
+#endif
+
/** print build options. */
static void
print_build_options(void)
@@ -526,6 +534,8 @@ perform_setup(struct daemon* daemon, struct config_file* cfg, int debug_mode,
LOGIN_SETALL & ~LOGIN_SETUSER & ~LOGIN_SETGROUP) != 0)
log_warn("unable to setusercontext %s: %s",
cfg->username, strerror(errno));
+#else
+ (void)pwd;
#endif /* HAVE_SETUSERCONTEXT */
}
#endif /* HAVE_GETPWNAM */
diff --git a/contrib/unbound/daemon/worker.c b/contrib/unbound/daemon/worker.c
index eb7fdf2f576d..23e3244c5041 100644
--- a/contrib/unbound/daemon/worker.c
+++ b/contrib/unbound/daemon/worker.c
@@ -79,6 +79,7 @@
#include "sldns/wire2str.h"
#include "util/shm_side/shm_main.h"
#include "dnscrypt/dnscrypt.h"
+#include "dnstap/dtstream.h"
#ifdef HAVE_SYS_TYPES_H
# include <sys/types.h>
@@ -1807,14 +1808,14 @@ worker_init(struct worker* worker, struct config_file *cfg,
worker->back = outside_network_create(worker->base,
cfg->msg_buffer_size, (size_t)cfg->outgoing_num_ports,
cfg->out_ifs, cfg->num_out_ifs, cfg->do_ip4, cfg->do_ip6,
- cfg->do_tcp?cfg->outgoing_num_tcp:0,
+ cfg->do_tcp?cfg->outgoing_num_tcp:0, cfg->ip_dscp,
worker->daemon->env->infra_cache, worker->rndstate,
cfg->use_caps_bits_for_id, worker->ports, worker->numports,
cfg->unwanted_threshold, cfg->outgoing_tcp_mss,
&worker_alloc_cleanup, worker,
cfg->do_udp || cfg->udp_upstream_without_downstream,
worker->daemon->connect_sslctx, cfg->delay_close,
- dtenv);
+ cfg->tls_use_sni, dtenv);
if(!worker->back) {
log_err("could not create outgoing sockets");
worker_delete(worker);
@@ -1914,6 +1915,20 @@ worker_init(struct worker* worker, struct config_file *cfg,
) {
auth_xfer_pickup_initial(worker->env.auth_zones, &worker->env);
}
+#ifdef USE_DNSTAP
+ if(worker->daemon->cfg->dnstap
+#ifndef THREADS_DISABLED
+ && worker->thread_num == 0
+#endif
+ ) {
+ if(!dt_io_thread_start(dtenv->dtio, comm_base_internal(
+ worker->base), worker->daemon->num)) {
+ log_err("could not start dnstap io thread");
+ worker_delete(worker);
+ return 0;
+ }
+ }
+#endif /* USE_DNSTAP */
if(!worker->env.mesh || !worker->env.scratch_buffer) {
worker_delete(worker);
return 0;
@@ -1961,6 +1976,16 @@ worker_delete(struct worker* worker)
wsvc_desetup_worker(worker);
#endif /* UB_ON_WINDOWS */
}
+#ifdef USE_DNSTAP
+ if(worker->daemon->cfg->dnstap
+#ifndef THREADS_DISABLED
+ && worker->thread_num == 0
+#endif
+ ) {
+ dt_io_thread_stop(worker->dtenv.dtio);
+ }
+ dt_deinit(&worker->dtenv);
+#endif /* USE_DNSTAP */
comm_base_delete(worker->base);
ub_randfree(worker->rndstate);
alloc_clear(&worker->alloc);
@@ -2099,3 +2124,18 @@ int codeline_cmp(const void* ATTR_UNUSED(a), const void* ATTR_UNUSED(b))
return 0;
}
+#ifdef USE_DNSTAP
+void dtio_tap_callback(int ATTR_UNUSED(fd), short ATTR_UNUSED(ev),
+ void* ATTR_UNUSED(arg))
+{
+ log_assert(0);
+}
+#endif
+
+#ifdef USE_DNSTAP
+void dtio_mainfdcallback(int ATTR_UNUSED(fd), short ATTR_UNUSED(ev),
+ void* ATTR_UNUSED(arg))
+{
+ log_assert(0);
+}
+#endif
diff --git a/contrib/unbound/dns64/dns64.c b/contrib/unbound/dns64/dns64.c
index 1a569059aff4..5c70119a54de 100644
--- a/contrib/unbound/dns64/dns64.c
+++ b/contrib/unbound/dns64/dns64.c
@@ -227,7 +227,7 @@ ipv4_to_ptr(uint32_t ipv4, char ptr[], size_t nm_len)
static const char IPV4_PTR_SUFFIX[] = "\07in-addr\04arpa";
int i;
char* c = ptr;
- log_assert(nm_len == MAX_PTR_QNAME_IPV4);
+ log_assert(nm_len == MAX_PTR_QNAME_IPV4); (void)nm_len;
for (i = 0; i < 4; ++i) {
*c = uitoa((unsigned int)(ipv4 % 256), c + 1);
diff --git a/contrib/unbound/dnstap/dnstap.c b/contrib/unbound/dnstap/dnstap.c
index aabf8eec9071..cc5449dff4a1 100644
--- a/contrib/unbound/dnstap/dnstap.c
+++ b/contrib/unbound/dnstap/dnstap.c
@@ -49,13 +49,12 @@
#include "util/netevent.h"
#include "util/log.h"
-#include <fstrm.h>
#include <protobuf-c/protobuf-c.h>
#include "dnstap/dnstap.h"
+#include "dnstap/dtstream.h"
#include "dnstap/dnstap.pb-c.h"
-#define DNSTAP_CONTENT_TYPE "protobuf:dnstap.Dnstap"
#define DNSTAP_INITIAL_BUF_SIZE 256
struct dt_msg {
@@ -90,13 +89,7 @@ dt_pack(const Dnstap__Dnstap *d, void **buf, size_t *sz)
static void
dt_send(const struct dt_env *env, void *buf, size_t len_buf)
{
- fstrm_res res;
- if (!buf)
- return;
- res = fstrm_iothr_submit(env->iothr, env->ioq, buf, len_buf,
- fstrm_free_wrapper, NULL);
- if (res != fstrm_res_success)
- free(buf);
+ dt_msg_queue_submit(env->msgqueue, buf, len_buf);
}
static void
@@ -135,56 +128,33 @@ check_socket_file(const char* socket_path)
}
struct dt_env *
-dt_create(const char *socket_path, unsigned num_workers)
+dt_create(struct config_file* cfg)
{
-#ifdef UNBOUND_DEBUG
- fstrm_res res;
-#endif
struct dt_env *env;
- struct fstrm_iothr_options *fopt;
- struct fstrm_unix_writer_options *fuwopt;
- struct fstrm_writer *fw;
- struct fstrm_writer_options *fwopt;
- verbose(VERB_OPS, "attempting to connect to dnstap socket %s",
- socket_path);
- log_assert(socket_path != NULL);
- log_assert(num_workers > 0);
- check_socket_file(socket_path);
+ if(cfg->dnstap && cfg->dnstap_socket_path && cfg->dnstap_socket_path[0] &&
+ (cfg->dnstap_ip==NULL || cfg->dnstap_ip[0]==0)) {
+ verbose(VERB_OPS, "attempting to connect to dnstap socket %s",
+ cfg->dnstap_socket_path);
+ check_socket_file(cfg->dnstap_socket_path);
+ }
env = (struct dt_env *) calloc(1, sizeof(struct dt_env));
if (!env)
return NULL;
- fwopt = fstrm_writer_options_init();
-#ifdef UNBOUND_DEBUG
- res =
-#else
- (void)
-#endif
- fstrm_writer_options_add_content_type(fwopt,
- DNSTAP_CONTENT_TYPE, sizeof(DNSTAP_CONTENT_TYPE) - 1);
- log_assert(res == fstrm_res_success);
-
- fuwopt = fstrm_unix_writer_options_init();
- fstrm_unix_writer_options_set_socket_path(fuwopt, socket_path);
-
- fw = fstrm_unix_writer_init(fuwopt, fwopt);
- log_assert(fw != NULL);
-
- fopt = fstrm_iothr_options_init();
- fstrm_iothr_options_set_num_input_queues(fopt, num_workers);
- env->iothr = fstrm_iothr_init(fopt, &fw);
- if (env->iothr == NULL) {
- verbose(VERB_DETAIL, "dt_create: fstrm_iothr_init() failed");
- fstrm_writer_destroy(&fw);
+ env->dtio = dt_io_thread_create();
+ if(!env->dtio) {
+ log_err("malloc failure");
free(env);
- env = NULL;
+ return NULL;
}
- fstrm_iothr_options_destroy(&fopt);
- fstrm_unix_writer_options_destroy(&fuwopt);
- fstrm_writer_options_destroy(&fwopt);
-
+ if(!dt_io_thread_apply_cfg(env->dtio, cfg)) {
+ dt_io_thread_delete(env->dtio);
+ free(env);
+ return NULL;
+ }
+ dt_apply_cfg(env, cfg);
return env;
}
@@ -272,19 +242,33 @@ dt_apply_cfg(struct dt_env *env, struct config_file *cfg)
int
dt_init(struct dt_env *env)
{
- env->ioq = fstrm_iothr_get_input_queue(env->iothr);
- if (env->ioq == NULL)
+ env->msgqueue = dt_msg_queue_create();
+ if(!env->msgqueue) {
+ log_err("malloc failure");
+ return 0;
+ }
+ if(!dt_io_thread_register_queue(env->dtio, env->msgqueue)) {
+ log_err("malloc failure");
+ dt_msg_queue_delete(env->msgqueue);
+ env->msgqueue = NULL;
return 0;
+ }
return 1;
}
void
+dt_deinit(struct dt_env* env)
+{
+ dt_io_thread_unregister_queue(env->dtio, env->msgqueue);
+ dt_msg_queue_delete(env->msgqueue);
+}
+
+void
dt_delete(struct dt_env *env)
{
if (!env)
return;
- verbose(VERB_OPS, "closing dnstap socket");
- fstrm_iothr_destroy(&env->iothr);
+ dt_io_thread_delete(env->dtio);
free(env->identity);
free(env->version);
free(env);
diff --git a/contrib/unbound/dnstap/dnstap.h b/contrib/unbound/dnstap/dnstap.h
index 0103c1c0e201..cfef6fc420b9 100644
--- a/contrib/unbound/dnstap/dnstap.h
+++ b/contrib/unbound/dnstap/dnstap.h
@@ -40,16 +40,16 @@
#ifdef USE_DNSTAP
struct config_file;
-struct fstrm_io;
-struct fstrm_queue;
struct sldns_buffer;
+struct dt_msg_queue;
struct dt_env {
- /** dnstap I/O thread */
- struct fstrm_iothr *iothr;
+ /** the io thread (made by the struct daemon) */
+ struct dt_io_thread* dtio;
- /** dnstap I/O thread input queue */
- struct fstrm_iothr_queue *ioq;
+ /** valid in worker struct, not in daemon struct, the per-worker
+ * message list */
+ struct dt_msg_queue* msgqueue;
/** dnstap "identity" field, NULL if disabled */
char *identity;
@@ -84,12 +84,11 @@ struct dt_env {
* of the structure) to ensure lock-free access to its own per-worker circular
* queue. Duplicate the environment object if more than one worker needs to
* share access to the dnstap I/O socket.
- * @param socket_path: path to dnstap logging socket, must be non-NULL.
- * @param num_workers: number of worker threads, must be > 0.
+ * @param cfg: with config settings.
* @return dt_env object, NULL on failure.
*/
struct dt_env *
-dt_create(const char *socket_path, unsigned num_workers);
+dt_create(struct config_file* cfg);
/**
* Apply config settings.
@@ -108,6 +107,11 @@ int
dt_init(struct dt_env *env);
/**
+ * Deletes the per-worker state created by dt_init
+ */
+void dt_deinit(struct dt_env *env);
+
+/**
* Delete dnstap environment object. Closes dnstap I/O socket and deletes all
* per-worker I/O queues.
*/
diff --git a/contrib/unbound/dnstap/dnstap.m4 b/contrib/unbound/dnstap/dnstap.m4
index 5b78b3e267c3..ba723e0becec 100644
--- a/contrib/unbound/dnstap/dnstap.m4
+++ b/contrib/unbound/dnstap/dnstap.m4
@@ -7,7 +7,7 @@ AC_DEFUN([dt_DNSTAP],
[
AC_ARG_ENABLE([dnstap],
AS_HELP_STRING([--enable-dnstap],
- [Enable dnstap support (requires fstrm, protobuf-c)]),
+ [Enable dnstap support (requires protobuf-c)]),
[opt_dnstap=$enableval], [opt_dnstap=no])
AC_ARG_WITH([dnstap-socket-path],
@@ -40,13 +40,6 @@ AC_DEFUN([dt_DNSTAP],
fi
fi
])
- AC_ARG_WITH([libfstrm], AC_HELP_STRING([--with-libfstrm=path],
- [Path where libfstrm is installed, for dnstap]), [
- CFLAGS="$CFLAGS -I$withval/include"
- LDFLAGS="$LDFLAGS -L$withval/lib"
- ])
- AC_SEARCH_LIBS([fstrm_iothr_init], [fstrm], [],
- AC_MSG_ERROR([The fstrm library was not found. Please install fstrm!]))
AC_SEARCH_LIBS([protobuf_c_message_pack], [protobuf-c], [],
AC_MSG_ERROR([The protobuf-c library was not found. Please install protobuf-c!]))
$2
diff --git a/contrib/unbound/dnstap/dnstap_fstrm.c b/contrib/unbound/dnstap/dnstap_fstrm.c
new file mode 100644
index 000000000000..289e78bdf0f4
--- /dev/null
+++ b/contrib/unbound/dnstap/dnstap_fstrm.c
@@ -0,0 +1,236 @@
+/*
+ * dnstap/dnstap_fstrm.c - Frame Streams protocol for dnstap
+ *
+ * Copyright (c) 2020, NLnet Labs. All rights reserved.
+ *
+ * This software is open source.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of the NLNET LABS nor the names of its contributors may
+ * be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+/**
+ * \file
+ *
+ * Definitions for the Frame Streams data transport protocol for
+ * dnstap message logs.
+ */
+
+#include "config.h"
+#include "dnstap/dnstap_fstrm.h"
+#include "sldns/sbuffer.h"
+#include "sldns/wire2str.h"
+
+void* fstrm_create_control_frame_start(char* contenttype, size_t* len)
+{
+ uint32_t* control;
+ size_t n;
+ /* start framestream message:
+ * 4byte 0: control indicator.
+ * 4byte bigendian: length of control frame
+ * 4byte bigendian: type START
+ * 4byte bigendian: option: content-type
+ * 4byte bigendian: length of string
+ * string of content type (dnstap)
+ */
+ n = 4+4+4+4+4+strlen(contenttype);
+ control = malloc(n);
+ if(!control)
+ return NULL;
+ control[0] = 0;
+ control[1] = htonl(4+4+4+strlen(contenttype));
+ control[2] = htonl(FSTRM_CONTROL_FRAME_START);
+ control[3] = htonl(FSTRM_CONTROL_FIELD_TYPE_CONTENT_TYPE);
+ control[4] = htonl(strlen(contenttype));
+ memmove(&control[5], contenttype, strlen(contenttype));
+ *len = n;
+ return control;
+}
+
+void* fstrm_create_control_frame_stop(size_t* len)
+{
+ uint32_t* control;
+ size_t n;
+ /* stop framestream message:
+ * 4byte 0: control indicator.
+ * 4byte bigendian: length of control frame
+ * 4byte bigendian: type STOP
+ */
+ n = 4+4+4;
+ control = malloc(n);
+ if(!control)
+ return NULL;
+ control[0] = 0;
+ control[1] = htonl(4);
+ control[2] = htonl(FSTRM_CONTROL_FRAME_STOP);
+ *len = n;
+ return control;
+}
+
+void* fstrm_create_control_frame_ready(char* contenttype, size_t* len)
+{
+ uint32_t* control;
+ size_t n;
+ /* start bidirectional stream:
+ * 4 bytes 0 escape
+ * 4 bytes bigendian length of frame
+ * 4 bytes bigendian type READY
+ * 4 bytes bigendian frame option content type
+ * 4 bytes bigendian length of string
+ * string of content type.
+ */
+ /* len includes the escape and framelength */
+ n = 4+4+4+4+4+strlen(contenttype);
+ control = malloc(n);
+ if(!control) {
+ return NULL;
+ }
+ control[0] = 0;
+ control[1] = htonl(4+4+4+strlen(contenttype));
+ control[2] = htonl(FSTRM_CONTROL_FRAME_READY);
+ control[3] = htonl(FSTRM_CONTROL_FIELD_TYPE_CONTENT_TYPE);
+ control[4] = htonl(strlen(contenttype));
+ memmove(&control[5], contenttype, strlen(contenttype));
+ *len = n;
+ return control;
+}
+
+void* fstrm_create_control_frame_accept(char* contenttype, size_t* len)
+{
+ uint32_t* control;
+ size_t n;
+ /* control frame on reply:
+ * 4 bytes 0 escape
+ * 4 bytes bigendian length of frame
+ * 4 bytes bigendian type ACCEPT
+ * 4 bytes bigendian frame option content type
+ * 4 bytes bigendian length of string
+ * string of content type.
+ */
+ /* len includes the escape and framelength */
+ n = 4+4+4+4+4+strlen(contenttype);
+ control = malloc(n);
+ if(!control) {
+ return NULL;
+ }
+ control[0] = 0;
+ control[1] = htonl(4+4+4+strlen(contenttype));
+ control[2] = htonl(FSTRM_CONTROL_FRAME_ACCEPT);
+ control[3] = htonl(FSTRM_CONTROL_FIELD_TYPE_CONTENT_TYPE);
+ control[4] = htonl(strlen(contenttype));
+ memmove(&control[5], contenttype, strlen(contenttype));
+ *len = n;
+ return control;
+}
+
+void* fstrm_create_control_frame_finish(size_t* len)
+{
+ uint32_t* control;
+ size_t n;
+ /* control frame on reply:
+ * 4 bytes 0 escape
+ * 4 bytes bigendian length of frame
+ * 4 bytes bigendian type FINISH
+ */
+ /* len includes the escape and framelength */
+ n = 4+4+4;
+ control = malloc(n);
+ if(!control) {
+ return NULL;
+ }
+ control[0] = 0;
+ control[1] = htonl(4);
+ control[2] = htonl(FSTRM_CONTROL_FRAME_FINISH);
+ *len = n;
+ return control;
+}
+
+char* fstrm_describe_control(void* pkt, size_t len)
+{
+ uint32_t frametype = 0;
+ char buf[512];
+ char* str = buf;
+ size_t remain, slen = sizeof(buf);
+ uint8_t* pos;
+
+ buf[0]=0;
+ if(len < 4) {
+ snprintf(buf, sizeof(buf), "malformed control frame, "
+ "too short, len=%u", (unsigned int)len);
+ return strdup(buf);
+ }
+ frametype = sldns_read_uint32(pkt);
+ if(frametype == FSTRM_CONTROL_FRAME_ACCEPT) {
+ (void)sldns_str_print(&str, &slen, "accept");
+ } else if(frametype == FSTRM_CONTROL_FRAME_START) {
+ (void)sldns_str_print(&str, &slen, "start");
+ } else if(frametype == FSTRM_CONTROL_FRAME_STOP) {
+ (void)sldns_str_print(&str, &slen, "stop");
+ } else if(frametype == FSTRM_CONTROL_FRAME_READY) {
+ (void)sldns_str_print(&str, &slen, "ready");
+ } else if(frametype == FSTRM_CONTROL_FRAME_FINISH) {
+ (void)sldns_str_print(&str, &slen, "finish");
+ } else {
+ (void)sldns_str_print(&str, &slen, "type%d", (int)frametype);
+ }
+
+ /* show the content type options */
+ pos = pkt + 4;
+ remain = len - 4;
+ while(remain >= 8) {
+ uint32_t field_type = sldns_read_uint32(pos);
+ uint32_t field_len = sldns_read_uint32(pos+4);
+ if(remain < field_len) {
+ (void)sldns_str_print(&str, &slen, "malformed_field");
+ break;
+ }
+ if(field_type == FSTRM_CONTROL_FIELD_TYPE_CONTENT_TYPE) {
+ char tempf[512];
+ (void)sldns_str_print(&str, &slen, " content-type(");
+ if(field_len < sizeof(tempf)-1) {
+ memmove(tempf, pos+8, field_len);
+ tempf[field_len] = 0;
+ (void)sldns_str_print(&str, &slen, "%s", tempf);
+ } else {
+ (void)sldns_str_print(&str, &slen, "<error-too-long>");
+ }
+ (void)sldns_str_print(&str, &slen, ")");
+ } else {
+ (void)sldns_str_print(&str, &slen,
+ " field(type %u, length %u)",
+ (unsigned int)field_type,
+ (unsigned int)field_len);
+ }
+ pos += 8 + field_len;
+ remain -= (8 + field_len);
+ }
+ if(remain > 0)
+ (void)sldns_str_print(&str, &slen, " trailing-bytes"
+ "(length %u)", (unsigned int)remain);
+ return strdup(buf);
+}
diff --git a/contrib/unbound/dnstap/dnstap_fstrm.h b/contrib/unbound/dnstap/dnstap_fstrm.h
new file mode 100644
index 000000000000..8b37d5f9e2d8
--- /dev/null
+++ b/contrib/unbound/dnstap/dnstap_fstrm.h
@@ -0,0 +1,194 @@
+/*
+ * dnstap/dnstap_fstrm.h - Frame Streams protocol for dnstap
+ *
+ * Copyright (c) 2020, NLnet Labs. All rights reserved.
+ *
+ * This software is open source.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of the NLNET LABS nor the names of its contributors may
+ * be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+/**
+ * \file
+ *
+ * Definitions for the Frame Streams data transport protocol for
+ * dnstap message logs.
+ */
+
+#ifndef DNSTAP_FSTRM_H
+#define DNSTAP_FSTRM_H
+
+/* Frame Streams data transfer protocol encode for DNSTAP messages.
+ * The protocol looks to be specified in the libfstrm library.
+ *
+ * Quick writeup for DNSTAP usage, from reading fstrm/control.h eloquent
+ * comments and fstrm/control.c for some bytesize details (the content type
+ * length).
+ *
+ * The Frame Streams can be unidirectional or bi-directional.
+ * bi-directional streams use control frame types READY, ACCEPT and FINISH.
+ * uni-directional streams use control frame types START and STOP.
+ * unknown control frame types should be ignored by the receiver, they
+ * do not change the data frame encoding.
+ *
+ * bi-directional control frames implement a simple handshake protocol
+ * between sender and receiver.
+ *
+ * The uni-directional control frames have one start and one stop frame,
+ * before and after the data. The start frame can have a content type.
+ * The start and stop frames are not optional.
+ *
+ * data frames are preceded by 4byte length, bigendian.
+ * zero length data frames are not possible, they are an escape that
+ * signals the presence of a control frame.
+ *
+ * a control frame consists of 0 value in 4byte bigendian, this is really
+ * the data frame length, with 0 the escape sequence that indicates one
+ * control frame follows.
+ * Then, 4byte bigendian, length of the control frame message.
+ * Then, the control frame payload (of that length). with in it:
+ * 4byte bigendian, control type (eg. START, STOP, READY, ACCEPT, FINISH).
+ * perhaps nothing more (STOP, FINISH), but for other types maybe
+ * control fields
+ * 4byte bigendian, the control-field-type, currently only content-type.
+ * 4byte bigendian, length of the string for this option.
+ * .. bytes of that string.
+ *
+ * The START type can have only one field. Field max len 256.
+ * control frame max frame length 512 (excludes the 0-escape and control
+ * frame length bytes).
+ *
+ * the bidirectional type of transmission is like this:
+ * client sends READY (with content type included),
+ * client waits for ACCEPT (with content type included),
+ * client sends START (with matched content type from ACCEPT)
+ * .. data frames
+ * client sends STOP.
+ * client waits for FINISH frame.
+ *
+ */
+
+/** max length of Frame Streams content type field string */
+#define FSTRM_CONTENT_TYPE_LENGTH_MAX 256
+/** control frame value to denote the control frame ACCEPT */
+#define FSTRM_CONTROL_FRAME_ACCEPT 0x01
+/** control frame value to denote the control frame START */
+#define FSTRM_CONTROL_FRAME_START 0x02
+/** control frame value to denote the control frame STOP */
+#define FSTRM_CONTROL_FRAME_STOP 0x03
+/** control frame value to denote the control frame READY */
+#define FSTRM_CONTROL_FRAME_READY 0x04
+/** control frame value to denote the control frame FINISH */
+#define FSTRM_CONTROL_FRAME_FINISH 0x05
+/** the constant that denotes the control field type that is the
+ * string for the content type of the stream. */
+#define FSTRM_CONTROL_FIELD_TYPE_CONTENT_TYPE 0x01
+/** the content type for DNSTAP frame streams */
+#define DNSTAP_CONTENT_TYPE "protobuf:dnstap.Dnstap"
+
+/**
+ * This creates an FSTRM control frame of type START.
+ * @param contenttype: a zero delimited string with the content type.
+ * eg. use the constant DNSTAP_CONTENT_TYPE, which is defined as
+ * "protobuf:dnstap.Dnstap", for a dnstap frame stream.
+ * @param len: if a buffer is returned this is the length of that buffer.
+ * @return NULL on malloc failure. Returns a malloced buffer with the
+ * protocol message. The buffer starts with the 4 bytes of 0 that indicate
+ * a control frame. The buffer should be sent without preceding it with
+ * the 'len' variable (like data frames are), but straight the content of the
+ * buffer, because the lengths are included in the buffer. This is so that
+ * the zero control indicator can be included before the control frame length.
+ */
+void* fstrm_create_control_frame_start(char* contenttype, size_t* len);
+
+/**
+ * This creates an FSTRM control frame of type READY.
+ * @param contenttype: a zero delimited string with the content type.
+ * eg. use the constant DNSTAP_CONTENT_TYPE, which is defined as
+ * "protobuf:dnstap.Dnstap", for a dnstap frame stream.
+ * @param len: if a buffer is returned this is the length of that buffer.
+ * @return NULL on malloc failure. Returns a malloced buffer with the
+ * protocol message. The buffer starts with the 4 bytes of 0 that indicate
+ * a control frame. The buffer should be sent without preceding it with
+ * the 'len' variable (like data frames are), but straight the content of the
+ * buffer, because the lengths are included in the buffer. This is so that
+ * the zero control indicator can be included before the control frame length.
+ */
+void* fstrm_create_control_frame_ready(char* contenttype, size_t* len);
+
+/**
+ * This creates an FSTRM control frame of type STOP.
+ * @param len: if a buffer is returned this is the length of that buffer.
+ * @return NULL on malloc failure. Returns a malloced buffer with the
+ * protocol message. The buffer starts with the 4 bytes of 0 that indicate
+ * a control frame. The buffer should be sent without preceding it with
+ * the 'len' variable (like data frames are), but straight the content of the
+ * buffer, because the lengths are included in the buffer. This is so that
+ * the zero control indicator can be included before the control frame length.
+ */
+void* fstrm_create_control_frame_stop(size_t* len);
+
+/**
+ * This creates an FSTRM control frame of type ACCEPT.
+ * @param contenttype: a zero delimited string with the content type.
+ * for dnstap streams use DNSTAP_CONTENT_TYPE.
+ * @param len: if a buffer is returned this is the length of that buffer.
+ * @return NULL on malloc failure. Returns a malloced buffer with the
+ * protocol message. The buffer starts with the 4 bytes of 0 that indicate
+ * a control frame. The buffer should be sent without preceding it with
+ * the 'len' variable (like data frames are), but straight the content of the
+ * buffer, because the lengths are included in the buffer. This is so that
+ * the zero control indicator can be included before the control frame length.
+ */
+void* fstrm_create_control_frame_accept(char* contenttype, size_t* len);
+
+/**
+ * This creates an FSTRM control frame of type FINISH.
+ * @param len: if a buffer is returned this is the length of that buffer.
+ * @return NULL on malloc failure. Returns a malloced buffer with the
+ * protocol message. The buffer starts with the 4 bytes of 0 that indicate
+ * a control frame. The buffer should be sent without preceding it with
+ * the 'len' variable (like data frames are), but straight the content of the
+ * buffer, because the lengths are included in the buffer. This is so that
+ * the zero control indicator can be included before the control frame length.
+ */
+void* fstrm_create_control_frame_finish(size_t* len);
+
+/**
+ * Return string that describes a control packet. For debug, logs.
+ * Like 'start content-type(protobuf:dnstap.Dnstap)' or 'stop'.
+ * @param pkt: the packet data, that is the data after the 4 zero start
+ * bytes and 4 length bytes.
+ * @param len: the length of the control packet data, in pkt. This is the
+ * ntohl of the 4 bytes length preceding the data.
+ * @return zero delimited string, malloced. Or NULL on malloc failure.
+ */
+char* fstrm_describe_control(void* pkt, size_t len);
+
+#endif /* DNSTAP_FSTRM_H */
diff --git a/contrib/unbound/dnstap/dtstream.c b/contrib/unbound/dnstap/dtstream.c
new file mode 100644
index 000000000000..dda3ef1ff485
--- /dev/null
+++ b/contrib/unbound/dnstap/dtstream.c
@@ -0,0 +1,2128 @@
+/*
+ * dnstap/dtstream.c - Frame Streams thread for unbound DNSTAP
+ *
+ * Copyright (c) 2020, NLnet Labs. All rights reserved.
+ *
+ * This software is open source.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of the NLNET LABS nor the names of its contributors may
+ * be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+/**
+ * \file
+ *
+ * An implementation of the Frame Streams data transport protocol for
+ * the Unbound DNSTAP message logging facility.
+ */
+
+#include "config.h"
+#include "dnstap/dtstream.h"
+#include "dnstap/dnstap_fstrm.h"
+#include "util/config_file.h"
+#include "util/ub_event.h"
+#include "util/net_help.h"
+#include "services/outside_network.h"
+#include "sldns/sbuffer.h"
+#ifdef HAVE_SYS_UN_H
+#include <sys/un.h>
+#endif
+#include <fcntl.h>
+#ifdef HAVE_OPENSSL_SSL_H
+#include <openssl/ssl.h>
+#endif
+#ifdef HAVE_OPENSSL_ERR_H
+#include <openssl/err.h>
+#endif
+
+/** number of messages to process in one output callback */
+#define DTIO_MESSAGES_PER_CALLBACK 100
+/** the msec to wait for reconnect (if not immediate, the first attempt) */
+#define DTIO_RECONNECT_TIMEOUT_MIN 10
+/** the msec to wait for reconnect max after backoff */
+#define DTIO_RECONNECT_TIMEOUT_MAX 1000
+/** the msec to wait for reconnect slow, to stop busy spinning on reconnect */
+#define DTIO_RECONNECT_TIMEOUT_SLOW 1000
+
+/** maximum length of received frame */
+#define DTIO_RECV_FRAME_MAX_LEN 1000
+
+struct stop_flush_info;
+/** DTIO command channel commands */
+enum {
+ /** DTIO command channel stop */
+ DTIO_COMMAND_STOP = 0,
+ /** DTIO command channel wakeup */
+ DTIO_COMMAND_WAKEUP = 1
+} dtio_channel_command;
+
+/** open the output channel */
+static void dtio_open_output(struct dt_io_thread* dtio);
+/** add output event for read and write */
+static int dtio_add_output_event_write(struct dt_io_thread* dtio);
+/** start reconnection attempts */
+static void dtio_reconnect_enable(struct dt_io_thread* dtio);
+/** stop from stop_flush event loop */
+static void dtio_stop_flush_exit(struct stop_flush_info* info);
+/** setup a start control message */
+static int dtio_control_start_send(struct dt_io_thread* dtio);
+#ifdef HAVE_SSL
+/** enable briefly waiting for a read event, for SSL negotiation */
+static int dtio_enable_brief_read(struct dt_io_thread* dtio);
+/** enable briefly waiting for a write event, for SSL negotiation */
+static int dtio_enable_brief_write(struct dt_io_thread* dtio);
+#endif
+
+struct dt_msg_queue*
+dt_msg_queue_create(void)
+{
+ struct dt_msg_queue* mq = calloc(1, sizeof(*mq));
+ if(!mq) return NULL;
+ mq->maxsize = 1*1024*1024; /* set max size of buffer, per worker,
+ about 1 M should contain 64K messages with some overhead,
+ or a whole bunch smaller ones */
+ lock_basic_init(&mq->lock);
+ lock_protect(&mq->lock, mq, sizeof(*mq));
+ return mq;
+}
+
+/** clear the message list, caller must hold the lock */
+static void
+dt_msg_queue_clear(struct dt_msg_queue* mq)
+{
+ struct dt_msg_entry* e = mq->first, *next=NULL;
+ while(e) {
+ next = e->next;
+ free(e->buf);
+ free(e);
+ e = next;
+ }
+ mq->first = NULL;
+ mq->last = NULL;
+ mq->cursize = 0;
+}
+
+void
+dt_msg_queue_delete(struct dt_msg_queue* mq)
+{
+ if(!mq) return;
+ lock_basic_destroy(&mq->lock);
+ dt_msg_queue_clear(mq);
+ free(mq);
+}
+
+/** make the dtio wake up by sending a wakeup command */
+static void dtio_wakeup(struct dt_io_thread* dtio)
+{
+ uint8_t cmd = DTIO_COMMAND_WAKEUP;
+ if(!dtio) return;
+ if(!dtio->started) return;
+
+ while(1) {
+ ssize_t r = write(dtio->commandpipe[1], &cmd, sizeof(cmd));
+ if(r == -1) {
+#ifndef USE_WINSOCK
+ if(errno == EINTR || errno == EAGAIN)
+ continue;
+ log_err("dnstap io wakeup: write: %s", strerror(errno));
+#else
+ if(WSAGetLastError() == WSAEINPROGRESS)
+ continue;
+ if(WSAGetLastError() == WSAEWOULDBLOCK)
+ continue;
+ log_err("dnstap io stop: write: %s",
+ wsa_strerror(WSAGetLastError()));
+#endif
+ break;
+ }
+ break;
+ }
+}
+
+void
+dt_msg_queue_submit(struct dt_msg_queue* mq, void* buf, size_t len)
+{
+ int wakeup = 0;
+ struct dt_msg_entry* entry;
+
+ /* check conditions */
+ if(!buf) return;
+ if(len == 0) {
+ /* it is not possible to log entries with zero length,
+ * because the framestream protocol does not carry it.
+ * However the protobuf serialization does not create zero
+ * length datagrams for dnstap, so this should not happen. */
+ free(buf);
+ return;
+ }
+ if(!mq) {
+ free(buf);
+ return;
+ }
+
+ /* allocate memory for queue entry */
+ entry = malloc(sizeof(*entry));
+ if(!entry) {
+ log_err("out of memory logging dnstap");
+ free(buf);
+ return;
+ }
+ entry->next = NULL;
+ entry->buf = buf;
+ entry->len = len;
+
+ /* aqcuire lock */
+ lock_basic_lock(&mq->lock);
+ /* list was empty, wakeup dtio */
+ if(mq->first == NULL)
+ wakeup = 1;
+ /* see if it is going to fit */
+ if(mq->cursize + len > mq->maxsize) {
+ /* buffer full, or congested. */
+ /* drop */
+ lock_basic_unlock(&mq->lock);
+ free(buf);
+ free(entry);
+ return;
+ }
+ mq->cursize += len;
+ /* append to list */
+ if(mq->last) {
+ mq->last->next = entry;
+ } else {
+ mq->first = entry;
+ }
+ mq->last = entry;
+ /* release lock */
+ lock_basic_unlock(&mq->lock);
+
+ if(wakeup)
+ dtio_wakeup(mq->dtio);
+}
+
+struct dt_io_thread* dt_io_thread_create(void)
+{
+ struct dt_io_thread* dtio = calloc(1, sizeof(*dtio));
+ return dtio;
+}
+
+void dt_io_thread_delete(struct dt_io_thread* dtio)
+{
+ struct dt_io_list_item* item, *nextitem;
+ if(!dtio) return;
+ item=dtio->io_list;
+ while(item) {
+ nextitem = item->next;
+ free(item);
+ item = nextitem;
+ }
+ free(dtio->socket_path);
+ free(dtio->ip_str);
+ free(dtio->tls_server_name);
+ free(dtio->client_key_file);
+ free(dtio->client_cert_file);
+ if(dtio->ssl_ctx) {
+#ifdef HAVE_SSL
+ SSL_CTX_free(dtio->ssl_ctx);
+#endif
+ }
+ free(dtio);
+}
+
+int dt_io_thread_apply_cfg(struct dt_io_thread* dtio, struct config_file *cfg)
+{
+ if(!cfg->dnstap) {
+ log_warn("cannot setup dnstap because dnstap-enable is no");
+ return 0;
+ }
+
+ /* what type of connectivity do we have */
+ if(cfg->dnstap_ip && cfg->dnstap_ip[0]) {
+ if(cfg->dnstap_tls)
+ dtio->upstream_is_tls = 1;
+ else dtio->upstream_is_tcp = 1;
+ } else {
+ dtio->upstream_is_unix = 1;
+ }
+ dtio->is_bidirectional = cfg->dnstap_bidirectional;
+
+ if(dtio->upstream_is_unix) {
+ if(!cfg->dnstap_socket_path ||
+ cfg->dnstap_socket_path[0]==0) {
+ log_err("dnstap setup: no dnstap-socket-path for "
+ "socket connect");
+ return 0;
+ }
+ free(dtio->socket_path);
+ dtio->socket_path = strdup(cfg->dnstap_socket_path);
+ if(!dtio->socket_path) {
+ log_err("dnstap setup: malloc failure");
+ return 0;
+ }
+ }
+
+ if(dtio->upstream_is_tcp || dtio->upstream_is_tls) {
+ if(!cfg->dnstap_ip || cfg->dnstap_ip[0] == 0) {
+ log_err("dnstap setup: no dnstap-ip for TCP connect");
+ return 0;
+ }
+ free(dtio->ip_str);
+ dtio->ip_str = strdup(cfg->dnstap_ip);
+ if(!dtio->ip_str) {
+ log_err("dnstap setup: malloc failure");
+ return 0;
+ }
+ }
+
+ if(dtio->upstream_is_tls) {
+#ifdef HAVE_SSL
+ if(cfg->dnstap_tls_server_name &&
+ cfg->dnstap_tls_server_name[0]) {
+ free(dtio->tls_server_name);
+ dtio->tls_server_name = strdup(
+ cfg->dnstap_tls_server_name);
+ if(!dtio->tls_server_name) {
+ log_err("dnstap setup: malloc failure");
+ return 0;
+ }
+ if(!check_auth_name_for_ssl(dtio->tls_server_name))
+ return 0;
+ }
+ if(cfg->dnstap_tls_client_key_file &&
+ cfg->dnstap_tls_client_key_file[0]) {
+ dtio->use_client_certs = 1;
+ free(dtio->client_key_file);
+ dtio->client_key_file = strdup(
+ cfg->dnstap_tls_client_key_file);
+ if(!dtio->client_key_file) {
+ log_err("dnstap setup: malloc failure");
+ return 0;
+ }
+ if(!cfg->dnstap_tls_client_cert_file ||
+ cfg->dnstap_tls_client_cert_file[0]==0) {
+ log_err("dnstap setup: client key "
+ "authentication enabled with "
+ "dnstap-tls-client-key-file, but "
+ "no dnstap-tls-client-cert-file "
+ "is given");
+ return 0;
+ }
+ free(dtio->client_cert_file);
+ dtio->client_cert_file = strdup(
+ cfg->dnstap_tls_client_cert_file);
+ if(!dtio->client_cert_file) {
+ log_err("dnstap setup: malloc failure");
+ return 0;
+ }
+ } else {
+ dtio->use_client_certs = 0;
+ dtio->client_key_file = NULL;
+ dtio->client_cert_file = NULL;
+ }
+
+ if(cfg->dnstap_tls_cert_bundle) {
+ dtio->ssl_ctx = connect_sslctx_create(
+ dtio->client_key_file,
+ dtio->client_cert_file,
+ cfg->dnstap_tls_cert_bundle, 0);
+ } else {
+ dtio->ssl_ctx = connect_sslctx_create(
+ dtio->client_key_file,
+ dtio->client_cert_file,
+ cfg->tls_cert_bundle, cfg->tls_win_cert);
+ }
+ if(!dtio->ssl_ctx) {
+ log_err("could not setup SSL CTX");
+ return 0;
+ }
+ dtio->tls_use_sni = cfg->tls_use_sni;
+#endif /* HAVE_SSL */
+ }
+ return 1;
+}
+
+int dt_io_thread_register_queue(struct dt_io_thread* dtio,
+ struct dt_msg_queue* mq)
+{
+ struct dt_io_list_item* item = malloc(sizeof(*item));
+ if(!item) return 0;
+ lock_basic_lock(&mq->lock);
+ mq->dtio = dtio;
+ lock_basic_unlock(&mq->lock);
+ item->queue = mq;
+ item->next = dtio->io_list;
+ dtio->io_list = item;
+ dtio->io_list_iter = NULL;
+ return 1;
+}
+
+void dt_io_thread_unregister_queue(struct dt_io_thread* dtio,
+ struct dt_msg_queue* mq)
+{
+ struct dt_io_list_item* item, *prev=NULL;
+ if(!dtio) return;
+ item = dtio->io_list;
+ while(item) {
+ if(item->queue == mq) {
+ /* found it */
+ if(prev) prev->next = item->next;
+ else dtio->io_list = item->next;
+ /* the queue itself only registered, not deleted */
+ lock_basic_lock(&item->queue->lock);
+ item->queue->dtio = NULL;
+ lock_basic_unlock(&item->queue->lock);
+ free(item);
+ dtio->io_list_iter = NULL;
+ return;
+ }
+ prev = item;
+ item = item->next;
+ }
+}
+
+/** pick a message from the queue, the routine locks and unlocks,
+ * returns true if there is a message */
+static int dt_msg_queue_pop(struct dt_msg_queue* mq, void** buf,
+ size_t* len)
+{
+ lock_basic_lock(&mq->lock);
+ if(mq->first) {
+ struct dt_msg_entry* entry = mq->first;
+ mq->first = entry->next;
+ if(!entry->next) mq->last = NULL;
+ mq->cursize -= entry->len;
+ lock_basic_unlock(&mq->lock);
+
+ *buf = entry->buf;
+ *len = entry->len;
+ free(entry);
+ return 1;
+ }
+ lock_basic_unlock(&mq->lock);
+ return 0;
+}
+
+/** find message in queue, false if no message, true if message to send */
+static int dtio_find_in_queue(struct dt_io_thread* dtio,
+ struct dt_msg_queue* mq)
+{
+ void* buf=NULL;
+ size_t len=0;
+ if(dt_msg_queue_pop(mq, &buf, &len)) {
+ dtio->cur_msg = buf;
+ dtio->cur_msg_len = len;
+ dtio->cur_msg_done = 0;
+ dtio->cur_msg_len_done = 0;
+ return 1;
+ }
+ return 0;
+}
+
+/** find a new message to write, search message queues, false if none */
+static int dtio_find_msg(struct dt_io_thread* dtio)
+{
+ struct dt_io_list_item *spot, *item;
+
+ spot = dtio->io_list_iter;
+ /* use the next queue for the next message lookup,
+ * if we hit the end(NULL) the NULL restarts the iter at start. */
+ if(spot)
+ dtio->io_list_iter = spot->next;
+ else if(dtio->io_list)
+ dtio->io_list_iter = dtio->io_list->next;
+
+ /* scan from spot to end-of-io_list */
+ item = spot;
+ while(item) {
+ if(dtio_find_in_queue(dtio, item->queue))
+ return 1;
+ item = item->next;
+ }
+ /* scan starting at the start-of-list (to wrap around the end) */
+ item = dtio->io_list;
+ while(item) {
+ if(dtio_find_in_queue(dtio, item->queue))
+ return 1;
+ item = item->next;
+ }
+ return 0;
+}
+
+/** callback for the dnstap reconnect, to start reconnecting to output */
+void dtio_reconnect_timeout_cb(int ATTR_UNUSED(fd),
+ short ATTR_UNUSED(bits), void* arg)
+{
+ struct dt_io_thread* dtio = (struct dt_io_thread*)arg;
+ dtio->reconnect_is_added = 0;
+ verbose(VERB_ALGO, "dnstap io: reconnect timer");
+
+ dtio_open_output(dtio);
+ if(dtio->event) {
+ if(!dtio_add_output_event_write(dtio))
+ return;
+ /* nothing wrong so far, wait on the output event */
+ return;
+ }
+ /* exponential backoff and retry on timer */
+ dtio_reconnect_enable(dtio);
+}
+
+/** attempt to reconnect to the output, after a timeout */
+static void dtio_reconnect_enable(struct dt_io_thread* dtio)
+{
+ struct timeval tv;
+ int msec;
+ if(dtio->want_to_exit) return;
+ if(dtio->reconnect_is_added)
+ return; /* already done */
+
+ /* exponential backoff, store the value for next timeout */
+ msec = dtio->reconnect_timeout;
+ if(msec == 0) {
+ dtio->reconnect_timeout = DTIO_RECONNECT_TIMEOUT_MIN;
+ } else {
+ dtio->reconnect_timeout = msec*2;
+ if(dtio->reconnect_timeout > DTIO_RECONNECT_TIMEOUT_MAX)
+ dtio->reconnect_timeout = DTIO_RECONNECT_TIMEOUT_MAX;
+ }
+ verbose(VERB_ALGO, "dnstap io: set reconnect attempt after %d msec",
+ msec);
+
+ /* setup wait timer */
+ memset(&tv, 0, sizeof(tv));
+ tv.tv_sec = msec/1000;
+ tv.tv_usec = (msec%1000)*1000;
+ if(ub_timer_add(dtio->reconnect_timer, dtio->event_base,
+ &dtio_reconnect_timeout_cb, dtio, &tv) != 0) {
+ log_err("dnstap io: could not reconnect ev timer add");
+ return;
+ }
+ dtio->reconnect_is_added = 1;
+}
+
+/** remove dtio reconnect timer */
+static void dtio_reconnect_del(struct dt_io_thread* dtio)
+{
+ if(!dtio->reconnect_is_added)
+ return;
+ ub_timer_del(dtio->reconnect_timer);
+ dtio->reconnect_is_added = 0;
+}
+
+/** clear the reconnect exponential backoff timer.
+ * We have successfully connected so we can try again with short timeouts. */
+static void dtio_reconnect_clear(struct dt_io_thread* dtio)
+{
+ dtio->reconnect_timeout = 0;
+ dtio_reconnect_del(dtio);
+}
+
+/** reconnect slowly, because we already know we have to wait for a bit */
+static void dtio_reconnect_slow(struct dt_io_thread* dtio, int msec)
+{
+ dtio_reconnect_del(dtio);
+ dtio->reconnect_timeout = msec;
+ dtio_reconnect_enable(dtio);
+}
+
+/** delete the current message in the dtio, and reset counters */
+static void dtio_cur_msg_free(struct dt_io_thread* dtio)
+{
+ free(dtio->cur_msg);
+ dtio->cur_msg = NULL;
+ dtio->cur_msg_len = 0;
+ dtio->cur_msg_done = 0;
+ dtio->cur_msg_len_done = 0;
+}
+
+/** delete the buffer and counters used to read frame */
+static void dtio_read_frame_free(struct dt_frame_read_buf* rb)
+{
+ if(rb->buf) {
+ free(rb->buf);
+ rb->buf = NULL;
+ }
+ rb->buf_count = 0;
+ rb->buf_cap = 0;
+ rb->frame_len = 0;
+ rb->frame_len_done = 0;
+ rb->control_frame = 0;
+}
+
+/** del the output file descriptor event for listening */
+static void dtio_del_output_event(struct dt_io_thread* dtio)
+{
+ if(!dtio->event_added)
+ return;
+ ub_event_del(dtio->event);
+ dtio->event_added = 0;
+ dtio->event_added_is_write = 0;
+}
+
+/** close dtio socket and set it to -1 */
+static void dtio_close_fd(struct dt_io_thread* dtio)
+{
+#ifndef USE_WINSOCK
+ close(dtio->fd);
+#else
+ closesocket(dtio->fd);
+#endif
+ dtio->fd = -1;
+}
+
+/** close and stop the output file descriptor event */
+static void dtio_close_output(struct dt_io_thread* dtio)
+{
+ if(!dtio->event)
+ return;
+ ub_event_free(dtio->event);
+ dtio->event = NULL;
+ if(dtio->ssl) {
+#ifdef HAVE_SSL
+ SSL_shutdown(dtio->ssl);
+ SSL_free(dtio->ssl);
+ dtio->ssl = NULL;
+#endif
+ }
+ dtio_close_fd(dtio);
+
+ /* if there is a (partial) message, discard it
+ * we cannot send (the remainder of) it, and a new
+ * connection needs to start with a control frame. */
+ if(dtio->cur_msg) {
+ dtio_cur_msg_free(dtio);
+ }
+
+ dtio->ready_frame_sent = 0;
+ dtio->accept_frame_received = 0;
+ dtio_read_frame_free(&dtio->read_frame);
+
+ dtio_reconnect_enable(dtio);
+}
+
+/** check for pending nonblocking connect errors,
+ * returns 1 if it is okay. -1 on error (close it), 0 to try later */
+static int dtio_check_nb_connect(struct dt_io_thread* dtio)
+{
+ int error = 0;
+ socklen_t len = (socklen_t)sizeof(error);
+ if(!dtio->check_nb_connect)
+ return 1; /* everything okay */
+ if(getsockopt(dtio->fd, SOL_SOCKET, SO_ERROR, (void*)&error,
+ &len) < 0) {
+#ifndef USE_WINSOCK
+ error = errno; /* on solaris errno is error */
+#else
+ error = WSAGetLastError();
+#endif
+ }
+#ifndef USE_WINSOCK
+#if defined(EINPROGRESS) && defined(EWOULDBLOCK)
+ if(error == EINPROGRESS || error == EWOULDBLOCK)
+ return 0; /* try again later */
+#endif
+#else
+ if(error == WSAEINPROGRESS) {
+ return 0; /* try again later */
+ } else if(error == WSAEWOULDBLOCK) {
+ ub_winsock_tcp_wouldblock((dtio->stop_flush_event?
+ dtio->stop_flush_event:dtio->event), UB_EV_WRITE);
+ return 0; /* try again later */
+ }
+#endif
+ if(error != 0) {
+ char* to = dtio->socket_path;
+ if(!to) to = dtio->ip_str;
+ if(!to) to = "";
+#ifndef USE_WINSOCK
+ log_err("dnstap io: failed to connect to \"%s\": %s",
+ to, strerror(error));
+#else
+ log_err("dnstap io: failed to connect to \"%s\": %s",
+ to, wsa_strerror(error));
+#endif
+ return -1; /* error, close it */
+ }
+
+ if(dtio->ip_str)
+ verbose(VERB_DETAIL, "dnstap io: connected to %s",
+ dtio->ip_str);
+ else if(dtio->socket_path)
+ verbose(VERB_DETAIL, "dnstap io: connected to \"%s\"",
+ dtio->socket_path);
+ dtio_reconnect_clear(dtio);
+ dtio->check_nb_connect = 0;
+ return 1; /* everything okay */
+}
+
+#ifdef HAVE_SSL
+/** write to ssl output
+ * returns number of bytes written, 0 if nothing happened,
+ * try again later, or -1 if the channel is to be closed. */
+static int dtio_write_ssl(struct dt_io_thread* dtio, uint8_t* buf,
+ size_t len)
+{
+ int r;
+ ERR_clear_error();
+ r = SSL_write(dtio->ssl, buf, len);
+ if(r <= 0) {
+ int want = SSL_get_error(dtio->ssl, r);
+ if(want == SSL_ERROR_ZERO_RETURN) {
+ /* closed */
+ return -1;
+ } else if(want == SSL_ERROR_WANT_READ) {
+ /* we want a brief read event */
+ dtio_enable_brief_read(dtio);
+ return 0;
+ } else if(want == SSL_ERROR_WANT_WRITE) {
+ /* write again later */
+ return 0;
+ } else if(want == SSL_ERROR_SYSCALL) {
+#ifdef EPIPE
+ if(errno == EPIPE && verbosity < 2)
+ return -1; /* silence 'broken pipe' */
+#endif
+#ifdef ECONNRESET
+ if(errno == ECONNRESET && verbosity < 2)
+ return -1; /* silence reset by peer */
+#endif
+ if(errno != 0) {
+ log_err("dnstap io, SSL_write syscall: %s",
+ strerror(errno));
+ }
+ return -1;
+ }
+ log_crypto_err("dnstap io, could not SSL_write");
+ return -1;
+ }
+ return r;
+}
+#endif /* HAVE_SSL */
+
+/** write buffer to output.
+ * returns number of bytes written, 0 if nothing happened,
+ * try again later, or -1 if the channel is to be closed. */
+static int dtio_write_buf(struct dt_io_thread* dtio, uint8_t* buf,
+ size_t len)
+{
+ ssize_t ret;
+ if(dtio->fd == -1)
+ return -1;
+#ifdef HAVE_SSL
+ if(dtio->ssl)
+ return dtio_write_ssl(dtio, buf, len);
+#endif
+ ret = send(dtio->fd, (void*)buf, len, 0);
+ if(ret == -1) {
+#ifndef USE_WINSOCK
+ if(errno == EINTR || errno == EAGAIN)
+ return 0;
+ log_err("dnstap io: failed send: %s", strerror(errno));
+#else
+ if(WSAGetLastError() == WSAEINPROGRESS)
+ return 0;
+ if(WSAGetLastError() == WSAEWOULDBLOCK) {
+ ub_winsock_tcp_wouldblock((dtio->stop_flush_event?
+ dtio->stop_flush_event:dtio->event),
+ UB_EV_WRITE);
+ return 0;
+ }
+ log_err("dnstap io: failed send: %s",
+ wsa_strerror(WSAGetLastError()));
+#endif
+ return -1;
+ }
+ return ret;
+}
+
+#ifdef HAVE_WRITEV
+/** write with writev, len and message, in one write, if possible.
+ * return true if message is done, false if incomplete */
+static int dtio_write_with_writev(struct dt_io_thread* dtio)
+{
+ uint32_t sendlen = htonl(dtio->cur_msg_len);
+ struct iovec iov[2];
+ ssize_t r;
+ iov[0].iov_base = ((uint8_t*)&sendlen)+dtio->cur_msg_len_done;
+ iov[0].iov_len = sizeof(sendlen)-dtio->cur_msg_len_done;
+ iov[1].iov_base = dtio->cur_msg;
+ iov[1].iov_len = dtio->cur_msg_len;
+ log_assert(iov[0].iov_len > 0);
+ r = writev(dtio->fd, iov, 2);
+ if(r == -1) {
+#ifndef USE_WINSOCK
+ if(errno == EINTR || errno == EAGAIN)
+ return 0;
+ log_err("dnstap io: failed writev: %s", strerror(errno));
+#else
+ if(WSAGetLastError() == WSAEINPROGRESS)
+ return 0;
+ if(WSAGetLastError() == WSAEWOULDBLOCK) {
+ ub_winsock_tcp_wouldblock((dtio->stop_flush_event?
+ dtio->stop_flush_event:dtio->event),
+ UB_EV_WRITE);
+ return 0;
+ }
+ log_err("dnstap io: failed writev: %s",
+ wsa_strerror(WSAGetLastError()));
+#endif
+ /* close the channel */
+ dtio_del_output_event(dtio);
+ dtio_close_output(dtio);
+ return 0;
+ }
+ /* written r bytes */
+ dtio->cur_msg_len_done += r;
+ if(dtio->cur_msg_len_done < 4)
+ return 0;
+ if(dtio->cur_msg_len_done > 4) {
+ dtio->cur_msg_done = dtio->cur_msg_len_done-4;
+ dtio->cur_msg_len_done = 4;
+ }
+ if(dtio->cur_msg_done < dtio->cur_msg_len)
+ return 0;
+ return 1;
+}
+#endif /* HAVE_WRITEV */
+
+/** write more of the length, preceding the data frame.
+ * return true if message is done, false if incomplete. */
+static int dtio_write_more_of_len(struct dt_io_thread* dtio)
+{
+ uint32_t sendlen;
+ int r;
+ if(dtio->cur_msg_len_done >= 4)
+ return 1;
+#ifdef HAVE_WRITEV
+ if(!dtio->ssl) {
+ /* we try writev for everything.*/
+ return dtio_write_with_writev(dtio);
+ }
+#endif /* HAVE_WRITEV */
+ sendlen = htonl(dtio->cur_msg_len);
+ r = dtio_write_buf(dtio,
+ ((uint8_t*)&sendlen)+dtio->cur_msg_len_done,
+ sizeof(sendlen)-dtio->cur_msg_len_done);
+ if(r == -1) {
+ /* close the channel */
+ dtio_del_output_event(dtio);
+ dtio_close_output(dtio);
+ return 0;
+ } else if(r == 0) {
+ /* try again later */
+ return 0;
+ }
+ dtio->cur_msg_len_done += r;
+ if(dtio->cur_msg_len_done < 4)
+ return 0;
+ return 1;
+}
+
+/** write more of the data frame.
+ * return true if message is done, false if incomplete. */
+static int dtio_write_more_of_data(struct dt_io_thread* dtio)
+{
+ int r;
+ if(dtio->cur_msg_done >= dtio->cur_msg_len)
+ return 1;
+ r = dtio_write_buf(dtio,
+ ((uint8_t*)dtio->cur_msg)+dtio->cur_msg_done,
+ dtio->cur_msg_len - dtio->cur_msg_done);
+ if(r == -1) {
+ /* close the channel */
+ dtio_del_output_event(dtio);
+ dtio_close_output(dtio);
+ return 0;
+ } else if(r == 0) {
+ /* try again later */
+ return 0;
+ }
+ dtio->cur_msg_done += r;
+ if(dtio->cur_msg_done < dtio->cur_msg_len)
+ return 0;
+ return 1;
+}
+
+/** write more of the current messsage. false if incomplete, true if
+ * the message is done */
+static int dtio_write_more(struct dt_io_thread* dtio)
+{
+ if(dtio->cur_msg_len_done < 4) {
+ if(!dtio_write_more_of_len(dtio))
+ return 0;
+ }
+ if(dtio->cur_msg_done < dtio->cur_msg_len) {
+ if(!dtio_write_more_of_data(dtio))
+ return 0;
+ }
+ return 1;
+}
+
+/** Receive bytes from dtio->fd, store in buffer. Returns 0: closed,
+ * -1: continue, >0: number of bytes read into buffer */
+static ssize_t receive_bytes(struct dt_io_thread* dtio, void* buf, size_t len) {
+ ssize_t r;
+ r = recv(dtio->fd, (void*)buf, len, 0);
+ if(r == -1) {
+ char* to = dtio->socket_path;
+ if(!to) to = dtio->ip_str;
+ if(!to) to = "";
+#ifndef USE_WINSOCK
+ if(errno == EINTR || errno == EAGAIN)
+ return -1; /* try later */
+#else
+ if(WSAGetLastError() == WSAEINPROGRESS) {
+ return -1; /* try later */
+ } else if(WSAGetLastError() == WSAEWOULDBLOCK) {
+ ub_winsock_tcp_wouldblock(
+ (dtio->stop_flush_event?
+ dtio->stop_flush_event:dtio->event),
+ UB_EV_READ);
+ return -1; /* try later */
+ }
+#endif
+ if(dtio->reconnect_timeout > DTIO_RECONNECT_TIMEOUT_MIN &&
+ verbosity < 4)
+ return 0; /* no log retries on low verbosity */
+ log_err("dnstap io: output closed, recv %s: %s", to,
+ strerror(errno));
+ /* and close below */
+ return 0;
+ }
+ if(r == 0) {
+ if(dtio->reconnect_timeout > DTIO_RECONNECT_TIMEOUT_MIN &&
+ verbosity < 4)
+ return 0; /* no log retries on low verbosity */
+ verbose(VERB_DETAIL, "dnstap io: output closed by the other side");
+ /* and close below */
+ return 0;
+ }
+ /* something was received */
+ return r;
+}
+
+#ifdef HAVE_SSL
+/** Receive bytes over TLS from dtio->fd, store in buffer. Returns 0: closed,
+ * -1: continue, >0: number of bytes read into buffer */
+static int ssl_read_bytes(struct dt_io_thread* dtio, void* buf, size_t len)
+{
+ int r;
+ ERR_clear_error();
+ r = SSL_read(dtio->ssl, buf, len);
+ if(r <= 0) {
+ int want = SSL_get_error(dtio->ssl, r);
+ if(want == SSL_ERROR_ZERO_RETURN) {
+ if(dtio->reconnect_timeout > DTIO_RECONNECT_TIMEOUT_MIN &&
+ verbosity < 4)
+ return 0; /* no log retries on low verbosity */
+ verbose(VERB_DETAIL, "dnstap io: output closed by the "
+ "other side");
+ return 0;
+ } else if(want == SSL_ERROR_WANT_READ) {
+ /* continue later */
+ return -1;
+ } else if(want == SSL_ERROR_WANT_WRITE) {
+ (void)dtio_enable_brief_write(dtio);
+ return -1;
+ } else if(want == SSL_ERROR_SYSCALL) {
+#ifdef ECONNRESET
+ if(dtio->reconnect_timeout > DTIO_RECONNECT_TIMEOUT_MIN &&
+ errno == ECONNRESET && verbosity < 4)
+ return 0; /* silence reset by peer */
+#endif
+ if(errno != 0)
+ log_err("SSL_read syscall: %s",
+ strerror(errno));
+ verbose(VERB_DETAIL, "dnstap io: output closed by the "
+ "other side");
+ return 0;
+ }
+ log_crypto_err("could not SSL_read");
+ verbose(VERB_DETAIL, "dnstap io: output closed by the "
+ "other side");
+ return 0;
+ }
+ return r;
+}
+#endif /* HAVE_SSL */
+
+/** check if the output fd has been closed,
+ * it returns false if the stream is closed. */
+static int dtio_check_close(struct dt_io_thread* dtio)
+{
+ /* we don't want to read any packets, but if there are we can
+ * discard the input (ignore it). Ignore of unknown (control)
+ * packets is okay for the framestream protocol. And also, the
+ * read call can return that the stream has been closed by the
+ * other side. */
+ uint8_t buf[1024];
+ int r = -1;
+
+
+ if(dtio->fd == -1) return 0;
+
+ while(r != 0) {
+ /* not interested in buffer content, overwrite */
+ r = receive_bytes(dtio, (void*)buf, sizeof(buf));
+ if(r == -1)
+ return 1;
+ }
+ /* the other end has been closed */
+ /* close the channel */
+ dtio_del_output_event(dtio);
+ dtio_close_output(dtio);
+ return 0;
+}
+
+/** Read accept frame. Returns -1: continue reading, 0: closed,
+ * 1: valid accept received. */
+static int dtio_read_accept_frame(struct dt_io_thread* dtio)
+{
+ int r;
+ size_t read_frame_done;
+ while(dtio->read_frame.frame_len_done < 4) {
+#ifdef HAVE_SSL
+ if(dtio->ssl) {
+ r = ssl_read_bytes(dtio,
+ (uint8_t*)&dtio->read_frame.frame_len+
+ dtio->read_frame.frame_len_done,
+ 4-dtio->read_frame.frame_len_done);
+ } else {
+#endif
+ r = receive_bytes(dtio,
+ (uint8_t*)&dtio->read_frame.frame_len+
+ dtio->read_frame.frame_len_done,
+ 4-dtio->read_frame.frame_len_done);
+#ifdef HAVE_SSL
+ }
+#endif
+ if(r == -1)
+ return -1; /* continue reading */
+ if(r == 0) {
+ /* connection closed */
+ goto close_connection;
+ }
+ dtio->read_frame.frame_len_done += r;
+ if(dtio->read_frame.frame_len_done < 4)
+ return -1; /* continue reading */
+
+ if(dtio->read_frame.frame_len == 0) {
+ dtio->read_frame.frame_len_done = 0;
+ dtio->read_frame.control_frame = 1;
+ continue;
+ }
+ dtio->read_frame.frame_len = ntohl(dtio->read_frame.frame_len);
+ if(dtio->read_frame.frame_len > DTIO_RECV_FRAME_MAX_LEN) {
+ verbose(VERB_OPS, "dnstap: received frame exceeds max "
+ "length of %d bytes, closing connection",
+ DTIO_RECV_FRAME_MAX_LEN);
+ goto close_connection;
+ }
+ dtio->read_frame.buf = calloc(1, dtio->read_frame.frame_len);
+ dtio->read_frame.buf_cap = dtio->read_frame.frame_len;
+ if(!dtio->read_frame.buf) {
+ log_err("dnstap io: out of memory (creating read "
+ "buffer)");
+ goto close_connection;
+ }
+ }
+ if(dtio->read_frame.buf_count < dtio->read_frame.frame_len) {
+#ifdef HAVE_SSL
+ if(dtio->ssl) {
+ r = ssl_read_bytes(dtio, dtio->read_frame.buf+
+ dtio->read_frame.buf_count,
+ dtio->read_frame.buf_cap-
+ dtio->read_frame.buf_count);
+ } else {
+#endif
+ r = receive_bytes(dtio, dtio->read_frame.buf+
+ dtio->read_frame.buf_count,
+ dtio->read_frame.buf_cap-
+ dtio->read_frame.buf_count);
+#ifdef HAVE_SSL
+ }
+#endif
+ if(r == -1)
+ return -1; /* continue reading */
+ if(r == 0) {
+ /* connection closed */
+ goto close_connection;
+ }
+ dtio->read_frame.buf_count += r;
+ if(dtio->read_frame.buf_count < dtio->read_frame.frame_len)
+ return -1; /* continue reading */
+ }
+
+ /* Complete frame received, check if this is a valid ACCEPT control
+ * frame. */
+ if(dtio->read_frame.frame_len < 4) {
+ verbose(VERB_OPS, "dnstap: invalid data received");
+ goto close_connection;
+ }
+ if(sldns_read_uint32(dtio->read_frame.buf) !=
+ FSTRM_CONTROL_FRAME_ACCEPT) {
+ verbose(VERB_ALGO, "dnstap: invalid control type received, "
+ "ignored");
+ dtio->ready_frame_sent = 0;
+ dtio->accept_frame_received = 0;
+ dtio_read_frame_free(&dtio->read_frame);
+ return -1;
+ }
+ read_frame_done = 4; /* control frame type */
+
+ /* Iterate over control fields, ignore unknown types.
+ * Need to be able to read at least 8 bytes (control field type +
+ * length). */
+ while(read_frame_done+8 < dtio->read_frame.frame_len) {
+ uint32_t type = sldns_read_uint32(dtio->read_frame.buf +
+ read_frame_done);
+ uint32_t len = sldns_read_uint32(dtio->read_frame.buf +
+ read_frame_done + 4);
+ if(type == FSTRM_CONTROL_FIELD_TYPE_CONTENT_TYPE) {
+ if(len == strlen(DNSTAP_CONTENT_TYPE) &&
+ read_frame_done+8+len <=
+ dtio->read_frame.frame_len &&
+ memcmp(dtio->read_frame.buf + read_frame_done +
+ + 8, DNSTAP_CONTENT_TYPE, len) == 0) {
+ if(!dtio_control_start_send(dtio)) {
+ verbose(VERB_OPS, "dnstap io: out of "
+ "memory while sending START frame");
+ goto close_connection;
+ }
+ dtio->accept_frame_received = 1;
+ return 1;
+ } else {
+ /* unknow content type */
+ verbose(VERB_ALGO, "dnstap: ACCEPT frame "
+ "contains unknown content type, "
+ "closing connection");
+ goto close_connection;
+ }
+ }
+ /* unknown option, try next */
+ read_frame_done += 8+len;
+ }
+
+
+close_connection:
+ dtio_del_output_event(dtio);
+ dtio_reconnect_slow(dtio, DTIO_RECONNECT_TIMEOUT_SLOW);
+ dtio_close_output(dtio);
+ return 0;
+}
+
+/** add the output file descriptor event for listening, read only */
+static int dtio_add_output_event_read(struct dt_io_thread* dtio)
+{
+ if(!dtio->event)
+ return 0;
+ if(dtio->event_added && !dtio->event_added_is_write)
+ return 1;
+ /* we have to (re-)register the event */
+ if(dtio->event_added)
+ ub_event_del(dtio->event);
+ ub_event_del_bits(dtio->event, UB_EV_WRITE);
+ if(ub_event_add(dtio->event, NULL) != 0) {
+ log_err("dnstap io: out of memory (adding event)");
+ dtio->event_added = 0;
+ dtio->event_added_is_write = 0;
+ /* close output and start reattempts to open it */
+ dtio_close_output(dtio);
+ return 0;
+ }
+ dtio->event_added = 1;
+ dtio->event_added_is_write = 0;
+ return 1;
+}
+
+/** add the output file descriptor event for listening, read and write */
+static int dtio_add_output_event_write(struct dt_io_thread* dtio)
+{
+ if(!dtio->event)
+ return 0;
+ if(dtio->event_added && dtio->event_added_is_write)
+ return 1;
+ /* we have to (re-)register the event */
+ if(dtio->event_added)
+ ub_event_del(dtio->event);
+ ub_event_add_bits(dtio->event, UB_EV_WRITE);
+ if(ub_event_add(dtio->event, NULL) != 0) {
+ log_err("dnstap io: out of memory (adding event)");
+ dtio->event_added = 0;
+ dtio->event_added_is_write = 0;
+ /* close output and start reattempts to open it */
+ dtio_close_output(dtio);
+ return 0;
+ }
+ dtio->event_added = 1;
+ dtio->event_added_is_write = 1;
+ return 1;
+}
+
+/** put the dtio thread to sleep */
+static void dtio_sleep(struct dt_io_thread* dtio)
+{
+ /* unregister the event polling for write, because there is
+ * nothing to be written */
+ (void)dtio_add_output_event_read(dtio);
+}
+
+#ifdef HAVE_SSL
+/** enable the brief read condition */
+static int dtio_enable_brief_read(struct dt_io_thread* dtio)
+{
+ dtio->ssl_brief_read = 1;
+ if(dtio->stop_flush_event) {
+ ub_event_del(dtio->stop_flush_event);
+ ub_event_del_bits(dtio->stop_flush_event, UB_EV_WRITE);
+ if(ub_event_add(dtio->stop_flush_event, NULL) != 0) {
+ log_err("dnstap io, stop flush, could not ub_event_add");
+ return 0;
+ }
+ return 1;
+ }
+ return dtio_add_output_event_read(dtio);
+}
+#endif /* HAVE_SSL */
+
+#ifdef HAVE_SSL
+/** disable the brief read condition */
+static int dtio_disable_brief_read(struct dt_io_thread* dtio)
+{
+ dtio->ssl_brief_read = 0;
+ if(dtio->stop_flush_event) {
+ ub_event_del(dtio->stop_flush_event);
+ ub_event_add_bits(dtio->stop_flush_event, UB_EV_WRITE);
+ if(ub_event_add(dtio->stop_flush_event, NULL) != 0) {
+ log_err("dnstap io, stop flush, could not ub_event_add");
+ return 0;
+ }
+ return 1;
+ }
+ return dtio_add_output_event_write(dtio);
+}
+#endif /* HAVE_SSL */
+
+#ifdef HAVE_SSL
+/** enable the brief write condition */
+static int dtio_enable_brief_write(struct dt_io_thread* dtio)
+{
+ dtio->ssl_brief_write = 1;
+ return dtio_add_output_event_write(dtio);
+}
+#endif /* HAVE_SSL */
+
+#ifdef HAVE_SSL
+/** disable the brief write condition */
+static int dtio_disable_brief_write(struct dt_io_thread* dtio)
+{
+ dtio->ssl_brief_write = 0;
+ return dtio_add_output_event_read(dtio);
+}
+#endif /* HAVE_SSL */
+
+#ifdef HAVE_SSL
+/** check peer verification after ssl handshake connection, false if closed*/
+static int dtio_ssl_check_peer(struct dt_io_thread* dtio)
+{
+ if((SSL_get_verify_mode(dtio->ssl)&SSL_VERIFY_PEER)) {
+ /* verification */
+ if(SSL_get_verify_result(dtio->ssl) == X509_V_OK) {
+ X509* x = SSL_get_peer_certificate(dtio->ssl);
+ if(!x) {
+ verbose(VERB_ALGO, "dnstap io, %s, SSL "
+ "connection failed no certificate",
+ dtio->ip_str);
+ return 0;
+ }
+ log_cert(VERB_ALGO, "dnstap io, peer certificate",
+ x);
+#ifdef HAVE_SSL_GET0_PEERNAME
+ if(SSL_get0_peername(dtio->ssl)) {
+ verbose(VERB_ALGO, "dnstap io, %s, SSL "
+ "connection to %s authenticated",
+ dtio->ip_str,
+ SSL_get0_peername(dtio->ssl));
+ } else {
+#endif
+ verbose(VERB_ALGO, "dnstap io, %s, SSL "
+ "connection authenticated",
+ dtio->ip_str);
+#ifdef HAVE_SSL_GET0_PEERNAME
+ }
+#endif
+ X509_free(x);
+ } else {
+ X509* x = SSL_get_peer_certificate(dtio->ssl);
+ if(x) {
+ log_cert(VERB_ALGO, "dnstap io, peer "
+ "certificate", x);
+ X509_free(x);
+ }
+ verbose(VERB_ALGO, "dnstap io, %s, SSL connection "
+ "failed: failed to authenticate",
+ dtio->ip_str);
+ return 0;
+ }
+ } else {
+ /* unauthenticated, the verify peer flag was not set
+ * in ssl when the ssl object was created from ssl_ctx */
+ verbose(VERB_ALGO, "dnstap io, %s, SSL connection",
+ dtio->ip_str);
+ }
+ return 1;
+}
+#endif /* HAVE_SSL */
+
+#ifdef HAVE_SSL
+/** perform ssl handshake, returns 1 if okay, 0 to stop */
+static int dtio_ssl_handshake(struct dt_io_thread* dtio,
+ struct stop_flush_info* info)
+{
+ int r;
+ if(dtio->ssl_brief_read) {
+ /* assume the brief read condition is satisfied,
+ * if we need more or again, we can set it again */
+ if(!dtio_disable_brief_read(dtio)) {
+ if(info) dtio_stop_flush_exit(info);
+ return 0;
+ }
+ }
+ if(dtio->ssl_handshake_done)
+ return 1;
+
+ ERR_clear_error();
+ r = SSL_do_handshake(dtio->ssl);
+ if(r != 1) {
+ int want = SSL_get_error(dtio->ssl, r);
+ if(want == SSL_ERROR_WANT_READ) {
+ /* we want to read on the connection */
+ if(!dtio_enable_brief_read(dtio)) {
+ if(info) dtio_stop_flush_exit(info);
+ return 0;
+ }
+ return 0;
+ } else if(want == SSL_ERROR_WANT_WRITE) {
+ /* we want to write on the connection */
+ return 0;
+ } else if(r == 0) {
+ /* closed */
+ if(info) dtio_stop_flush_exit(info);
+ dtio_del_output_event(dtio);
+ dtio_reconnect_slow(dtio, DTIO_RECONNECT_TIMEOUT_SLOW);
+ dtio_close_output(dtio);
+ return 0;
+ } else if(want == SSL_ERROR_SYSCALL) {
+ /* SYSCALL and errno==0 means closed uncleanly */
+ int silent = 0;
+#ifdef EPIPE
+ if(errno == EPIPE && verbosity < 2)
+ silent = 1; /* silence 'broken pipe' */
+#endif
+#ifdef ECONNRESET
+ if(errno == ECONNRESET && verbosity < 2)
+ silent = 1; /* silence reset by peer */
+#endif
+ if(errno == 0)
+ silent = 1;
+ if(!silent)
+ log_err("dnstap io, SSL_handshake syscall: %s",
+ strerror(errno));
+ /* closed */
+ if(info) dtio_stop_flush_exit(info);
+ dtio_del_output_event(dtio);
+ dtio_reconnect_slow(dtio, DTIO_RECONNECT_TIMEOUT_SLOW);
+ dtio_close_output(dtio);
+ return 0;
+ } else {
+ unsigned long err = ERR_get_error();
+ if(!squelch_err_ssl_handshake(err)) {
+ log_crypto_err_code("dnstap io, ssl handshake failed",
+ err);
+ verbose(VERB_OPS, "dnstap io, ssl handshake failed "
+ "from %s", dtio->ip_str);
+ }
+ /* closed */
+ if(info) dtio_stop_flush_exit(info);
+ dtio_del_output_event(dtio);
+ dtio_reconnect_slow(dtio, DTIO_RECONNECT_TIMEOUT_SLOW);
+ dtio_close_output(dtio);
+ return 0;
+ }
+
+ }
+ /* check peer verification */
+ dtio->ssl_handshake_done = 1;
+
+ if(!dtio_ssl_check_peer(dtio)) {
+ /* closed */
+ if(info) dtio_stop_flush_exit(info);
+ dtio_del_output_event(dtio);
+ dtio_reconnect_slow(dtio, DTIO_RECONNECT_TIMEOUT_SLOW);
+ dtio_close_output(dtio);
+ return 0;
+ }
+ return 1;
+}
+#endif /* HAVE_SSL */
+
+/** callback for the dnstap events, to write to the output */
+void dtio_output_cb(int ATTR_UNUSED(fd), short bits, void* arg)
+{
+ struct dt_io_thread* dtio = (struct dt_io_thread*)arg;
+ int i;
+
+ if(dtio->check_nb_connect) {
+ int connect_err = dtio_check_nb_connect(dtio);
+ if(connect_err == -1) {
+ /* close the channel */
+ dtio_del_output_event(dtio);
+ dtio_close_output(dtio);
+ return;
+ } else if(connect_err == 0) {
+ /* try again later */
+ return;
+ }
+ /* nonblocking connect check passed, continue */
+ }
+
+#ifdef HAVE_SSL
+ if(dtio->ssl &&
+ (!dtio->ssl_handshake_done || dtio->ssl_brief_read)) {
+ if(!dtio_ssl_handshake(dtio, NULL))
+ return;
+ }
+#endif
+
+ if((bits&UB_EV_READ || dtio->ssl_brief_write)) {
+ if(dtio->ssl_brief_write)
+ (void)dtio_disable_brief_write(dtio);
+ if(dtio->ready_frame_sent && !dtio->accept_frame_received) {
+ if(dtio_read_accept_frame(dtio) <= 0)
+ return;
+ } else if(!dtio_check_close(dtio))
+ return;
+ }
+
+ /* loop to process a number of messages. This improves throughput,
+ * because selecting on write-event if not needed for busy messages
+ * (dnstap log) generation and if they need to all be written back.
+ * The write event is usually not blocked up. But not forever,
+ * because the event loop needs to stay responsive for other events.
+ * If there are no (more) messages, or if the output buffers get
+ * full, it returns out of the loop. */
+ for(i=0; i<DTIO_MESSAGES_PER_CALLBACK; i++) {
+ /* see if there are messages that need writing */
+ if(!dtio->cur_msg) {
+ if(!dtio_find_msg(dtio)) {
+ if(i == 0) {
+ /* no messages on the first iteration,
+ * the queues are all empty */
+ dtio_sleep(dtio);
+ }
+ return; /* nothing to do */
+ }
+ }
+
+ /* write it */
+ if(dtio->cur_msg_done < dtio->cur_msg_len) {
+ if(!dtio_write_more(dtio))
+ return;
+ }
+
+ /* done with the current message */
+ dtio_cur_msg_free(dtio);
+
+ /* If this is a bidirectional stream the first message will be
+ * the READY control frame. We can only continue writing after
+ * receiving an ACCEPT control frame. */
+ if(dtio->is_bidirectional && !dtio->ready_frame_sent) {
+ dtio->ready_frame_sent = 1;
+ (void)dtio_add_output_event_read(dtio);
+ break;
+ }
+ }
+}
+
+/** callback for the dnstap commandpipe, to stop the dnstap IO */
+void dtio_cmd_cb(int fd, short ATTR_UNUSED(bits), void* arg)
+{
+ struct dt_io_thread* dtio = (struct dt_io_thread*)arg;
+ uint8_t cmd;
+ ssize_t r;
+ if(dtio->want_to_exit)
+ return;
+ r = read(fd, &cmd, sizeof(cmd));
+ if(r == -1) {
+#ifndef USE_WINSOCK
+ if(errno == EINTR || errno == EAGAIN)
+ return; /* ignore this */
+ log_err("dnstap io: failed to read: %s", strerror(errno));
+#else
+ if(WSAGetLastError() == WSAEINPROGRESS)
+ return;
+ if(WSAGetLastError() == WSAEWOULDBLOCK)
+ return;
+ log_err("dnstap io: failed to read: %s",
+ wsa_strerror(WSAGetLastError()));
+#endif
+ /* and then fall through to quit the thread */
+ } else if(r == 0) {
+ verbose(VERB_ALGO, "dnstap io: cmd channel closed");
+ } else if(r == 1 && cmd == DTIO_COMMAND_STOP) {
+ verbose(VERB_ALGO, "dnstap io: cmd channel cmd quit");
+ } else if(r == 1 && cmd == DTIO_COMMAND_WAKEUP) {
+ verbose(VERB_ALGO, "dnstap io: cmd channel cmd wakeup");
+
+ if(dtio->is_bidirectional && !dtio->accept_frame_received) {
+ verbose(VERB_ALGO, "dnstap io: cmd wakeup ignored, "
+ "waiting for ACCEPT control frame");
+ return;
+ }
+
+ /* reregister event */
+ if(!dtio_add_output_event_write(dtio))
+ return;
+ return;
+ } else if(r == 1) {
+ verbose(VERB_ALGO, "dnstap io: cmd channel unknown command");
+ }
+ dtio->want_to_exit = 1;
+ if(ub_event_base_loopexit((struct ub_event_base*)dtio->event_base)
+ != 0) {
+ log_err("dnstap io: could not loopexit");
+ }
+}
+
+#ifndef THREADS_DISABLED
+/** setup the event base for the dnstap io thread */
+static void dtio_setup_base(struct dt_io_thread* dtio, time_t* secs,
+ struct timeval* now)
+{
+ memset(now, 0, sizeof(*now));
+ dtio->event_base = ub_default_event_base(0, secs, now);
+ if(!dtio->event_base) {
+ fatal_exit("dnstap io: could not create event_base");
+ }
+}
+#endif /* THREADS_DISABLED */
+
+/** setup the cmd event for dnstap io */
+static void dtio_setup_cmd(struct dt_io_thread* dtio)
+{
+ struct ub_event* cmdev;
+ fd_set_nonblock(dtio->commandpipe[0]);
+ cmdev = ub_event_new(dtio->event_base, dtio->commandpipe[0],
+ UB_EV_READ | UB_EV_PERSIST, &dtio_cmd_cb, dtio);
+ if(!cmdev) {
+ fatal_exit("dnstap io: out of memory");
+ }
+ dtio->command_event = cmdev;
+ if(ub_event_add(cmdev, NULL) != 0) {
+ fatal_exit("dnstap io: out of memory (adding event)");
+ }
+}
+
+/** setup the reconnect event for dnstap io */
+static void dtio_setup_reconnect(struct dt_io_thread* dtio)
+{
+ dtio_reconnect_clear(dtio);
+ dtio->reconnect_timer = ub_event_new(dtio->event_base, -1,
+ UB_EV_TIMEOUT, &dtio_reconnect_timeout_cb, dtio);
+ if(!dtio->reconnect_timer) {
+ fatal_exit("dnstap io: out of memory");
+ }
+}
+
+/**
+ * structure to keep track of information during stop flush
+ */
+struct stop_flush_info {
+ /** the event base during stop flush */
+ struct ub_event_base* base;
+ /** did we already want to exit this stop-flush event base */
+ int want_to_exit_flush;
+ /** has the timer fired */
+ int timer_done;
+ /** the dtio */
+ struct dt_io_thread* dtio;
+ /** the stop control frame */
+ void* stop_frame;
+ /** length of the stop frame */
+ size_t stop_frame_len;
+ /** how much we have done of the stop frame */
+ size_t stop_frame_done;
+};
+
+/** exit the stop flush base */
+static void dtio_stop_flush_exit(struct stop_flush_info* info)
+{
+ if(info->want_to_exit_flush)
+ return;
+ info->want_to_exit_flush = 1;
+ if(ub_event_base_loopexit(info->base) != 0) {
+ log_err("dnstap io: could not loopexit");
+ }
+}
+
+/** send the stop control,
+ * return true if completed the frame. */
+static int dtio_control_stop_send(struct stop_flush_info* info)
+{
+ struct dt_io_thread* dtio = info->dtio;
+ int r;
+ if(info->stop_frame_done >= info->stop_frame_len)
+ return 1;
+ r = dtio_write_buf(dtio, ((uint8_t*)info->stop_frame) +
+ info->stop_frame_done, info->stop_frame_len -
+ info->stop_frame_done);
+ if(r == -1) {
+ verbose(VERB_ALGO, "dnstap io: stop flush: output closed");
+ dtio_stop_flush_exit(info);
+ return 0;
+ }
+ if(r == 0) {
+ /* try again later, or timeout */
+ return 0;
+ }
+ info->stop_frame_done += r;
+ if(info->stop_frame_done < info->stop_frame_len)
+ return 0; /* not done yet */
+ return 1;
+}
+
+void dtio_stop_timer_cb(int ATTR_UNUSED(fd), short ATTR_UNUSED(bits),
+ void* arg)
+{
+ struct stop_flush_info* info = (struct stop_flush_info*)arg;
+ if(info->want_to_exit_flush)
+ return;
+ verbose(VERB_ALGO, "dnstap io: stop flush timer expired, stop flush");
+ info->timer_done = 1;
+ dtio_stop_flush_exit(info);
+}
+
+void dtio_stop_ev_cb(int ATTR_UNUSED(fd), short bits, void* arg)
+{
+ struct stop_flush_info* info = (struct stop_flush_info*)arg;
+ struct dt_io_thread* dtio = info->dtio;
+ if(info->want_to_exit_flush)
+ return;
+ if(dtio->check_nb_connect) {
+ /* we don't start the stop_flush if connect still
+ * in progress, but the check code is here, just in case */
+ int connect_err = dtio_check_nb_connect(dtio);
+ if(connect_err == -1) {
+ /* close the channel, exit the stop flush */
+ dtio_stop_flush_exit(info);
+ dtio_del_output_event(dtio);
+ dtio_close_output(dtio);
+ return;
+ } else if(connect_err == 0) {
+ /* try again later */
+ return;
+ }
+ /* nonblocking connect check passed, continue */
+ }
+#ifdef HAVE_SSL
+ if(dtio->ssl &&
+ (!dtio->ssl_handshake_done || dtio->ssl_brief_read)) {
+ if(!dtio_ssl_handshake(dtio, info))
+ return;
+ }
+#endif
+
+ if((bits&UB_EV_READ)) {
+ if(!dtio_check_close(dtio)) {
+ if(dtio->fd == -1) {
+ verbose(VERB_ALGO, "dnstap io: "
+ "stop flush: output closed");
+ dtio_stop_flush_exit(info);
+ }
+ return;
+ }
+ }
+ /* write remainder of last frame */
+ if(dtio->cur_msg) {
+ if(dtio->cur_msg_done < dtio->cur_msg_len) {
+ if(!dtio_write_more(dtio)) {
+ if(dtio->fd == -1) {
+ verbose(VERB_ALGO, "dnstap io: "
+ "stop flush: output closed");
+ dtio_stop_flush_exit(info);
+ }
+ return;
+ }
+ }
+ verbose(VERB_ALGO, "dnstap io: stop flush completed "
+ "last frame");
+ dtio_cur_msg_free(dtio);
+ }
+ /* write stop frame */
+ if(info->stop_frame_done < info->stop_frame_len) {
+ if(!dtio_control_stop_send(info))
+ return;
+ verbose(VERB_ALGO, "dnstap io: stop flush completed "
+ "stop control frame");
+ }
+ /* when last frame and stop frame are sent, exit */
+ dtio_stop_flush_exit(info);
+}
+
+/** flush at end, last packet and stop control */
+static void dtio_control_stop_flush(struct dt_io_thread* dtio)
+{
+ /* briefly attempt to flush the previous packet to the output,
+ * this could be a partial packet, or even the start control frame */
+ time_t secs = 0;
+ struct timeval now;
+ struct stop_flush_info info;
+ struct timeval tv;
+ struct ub_event* timer, *stopev;
+
+ if(dtio->fd == -1 || dtio->check_nb_connect) {
+ /* no connection or we have just connected, so nothing is
+ * sent yet, so nothing to stop or flush */
+ return;
+ }
+ if(dtio->ssl && !dtio->ssl_handshake_done) {
+ /* no SSL connection has been established yet */
+ return;
+ }
+
+ memset(&info, 0, sizeof(info));
+ memset(&now, 0, sizeof(now));
+ info.dtio = dtio;
+ info.base = ub_default_event_base(0, &secs, &now);
+ if(!info.base) {
+ log_err("dnstap io: malloc failure");
+ return;
+ }
+ timer = ub_event_new(info.base, -1, UB_EV_TIMEOUT,
+ &dtio_stop_timer_cb, &info);
+ if(!timer) {
+ log_err("dnstap io: malloc failure");
+ ub_event_base_free(info.base);
+ return;
+ }
+ memset(&tv, 0, sizeof(tv));
+ tv.tv_sec = 2;
+ if(ub_timer_add(timer, info.base, &dtio_stop_timer_cb, &info,
+ &tv) != 0) {
+ log_err("dnstap io: cannot event_timer_add");
+ ub_event_free(timer);
+ ub_event_base_free(info.base);
+ return;
+ }
+ stopev = ub_event_new(info.base, dtio->fd, UB_EV_READ |
+ UB_EV_WRITE | UB_EV_PERSIST, &dtio_stop_ev_cb, &info);
+ if(!stopev) {
+ log_err("dnstap io: malloc failure");
+ ub_timer_del(timer);
+ ub_event_free(timer);
+ ub_event_base_free(info.base);
+ return;
+ }
+ if(ub_event_add(stopev, NULL) != 0) {
+ log_err("dnstap io: cannot event_add");
+ ub_event_free(stopev);
+ ub_timer_del(timer);
+ ub_event_free(timer);
+ ub_event_base_free(info.base);
+ return;
+ }
+ info.stop_frame = fstrm_create_control_frame_stop(
+ &info.stop_frame_len);
+ if(!info.stop_frame) {
+ log_err("dnstap io: malloc failure");
+ ub_event_del(stopev);
+ ub_event_free(stopev);
+ ub_timer_del(timer);
+ ub_event_free(timer);
+ ub_event_base_free(info.base);
+ return;
+ }
+ dtio->stop_flush_event = stopev;
+
+ /* wait briefly, or until finished */
+ verbose(VERB_ALGO, "dnstap io: stop flush started");
+ if(ub_event_base_dispatch(info.base) < 0) {
+ log_err("dnstap io: dispatch flush failed, errno is %s",
+ strerror(errno));
+ }
+ verbose(VERB_ALGO, "dnstap io: stop flush ended");
+ free(info.stop_frame);
+ dtio->stop_flush_event = NULL;
+ ub_event_del(stopev);
+ ub_event_free(stopev);
+ ub_timer_del(timer);
+ ub_event_free(timer);
+ ub_event_base_free(info.base);
+}
+
+/** perform desetup and free stuff when the dnstap io thread exits */
+static void dtio_desetup(struct dt_io_thread* dtio)
+{
+ dtio_control_stop_flush(dtio);
+ dtio_del_output_event(dtio);
+ dtio_close_output(dtio);
+ ub_event_del(dtio->command_event);
+ ub_event_free(dtio->command_event);
+#ifndef USE_WINSOCK
+ close(dtio->commandpipe[0]);
+#else
+ _close(dtio->commandpipe[0]);
+#endif
+ dtio->commandpipe[0] = -1;
+ dtio_reconnect_del(dtio);
+ ub_event_free(dtio->reconnect_timer);
+ dtio_cur_msg_free(dtio);
+#ifndef THREADS_DISABLED
+ ub_event_base_free(dtio->event_base);
+#endif
+}
+
+/** setup a start control message */
+static int dtio_control_start_send(struct dt_io_thread* dtio)
+{
+ log_assert(dtio->cur_msg == NULL && dtio->cur_msg_len == 0);
+ dtio->cur_msg = fstrm_create_control_frame_start(DNSTAP_CONTENT_TYPE,
+ &dtio->cur_msg_len);
+ if(!dtio->cur_msg) {
+ return 0;
+ }
+ /* setup to send the control message */
+ /* set that the buffer needs to be sent, but the length
+ * of that buffer is already written, that way the buffer can
+ * start with 0 length and then the length of the control frame
+ * in it */
+ dtio->cur_msg_done = 0;
+ dtio->cur_msg_len_done = 4;
+ return 1;
+}
+
+/** setup a ready control message */
+static int dtio_control_ready_send(struct dt_io_thread* dtio)
+{
+ log_assert(dtio->cur_msg == NULL && dtio->cur_msg_len == 0);
+ dtio->cur_msg = fstrm_create_control_frame_ready(DNSTAP_CONTENT_TYPE,
+ &dtio->cur_msg_len);
+ if(!dtio->cur_msg) {
+ return 0;
+ }
+ /* setup to send the control message */
+ /* set that the buffer needs to be sent, but the length
+ * of that buffer is already written, that way the buffer can
+ * start with 0 length and then the length of the control frame
+ * in it */
+ dtio->cur_msg_done = 0;
+ dtio->cur_msg_len_done = 4;
+ return 1;
+}
+
+/** open the output file descriptor for af_local */
+static int dtio_open_output_local(struct dt_io_thread* dtio)
+{
+#ifdef HAVE_SYS_UN_H
+ struct sockaddr_un s;
+ dtio->fd = socket(AF_LOCAL, SOCK_STREAM, 0);
+ if(dtio->fd == -1) {
+#ifndef USE_WINSOCK
+ log_err("dnstap io: failed to create socket: %s",
+ strerror(errno));
+#else
+ log_err("dnstap io: failed to create socket: %s",
+ wsa_strerror(WSAGetLastError()));
+#endif
+ return 0;
+ }
+ memset(&s, 0, sizeof(s));
+#ifdef HAVE_STRUCT_SOCKADDR_UN_SUN_LEN
+ /* this member exists on BSDs, not Linux */
+ s.sun_len = (unsigned)sizeof(s);
+#endif
+ s.sun_family = AF_LOCAL;
+ /* length is 92-108, 104 on FreeBSD */
+ (void)strlcpy(s.sun_path, dtio->socket_path, sizeof(s.sun_path));
+ fd_set_nonblock(dtio->fd);
+ if(connect(dtio->fd, (struct sockaddr*)&s, (socklen_t)sizeof(s))
+ == -1) {
+ char* to = dtio->socket_path;
+#ifndef USE_WINSOCK
+ log_err("dnstap io: failed to connect to \"%s\": %s",
+ to, strerror(errno));
+#else
+ log_err("dnstap io: failed to connect to \"%s\": %s",
+ to, wsa_strerror(WSAGetLastError()));
+#endif
+ dtio_close_fd(dtio);
+ return 0;
+ }
+ return 1;
+#else
+ log_err("cannot create af_local socket");
+ return 0;
+#endif /* HAVE_SYS_UN_H */
+}
+
+/** open the output file descriptor for af_inet and af_inet6 */
+static int dtio_open_output_tcp(struct dt_io_thread* dtio)
+{
+ struct sockaddr_storage addr;
+ socklen_t addrlen;
+ memset(&addr, 0, sizeof(addr));
+ addrlen = (socklen_t)sizeof(addr);
+
+ if(!extstrtoaddr(dtio->ip_str, &addr, &addrlen)) {
+ log_err("could not parse IP '%s'", dtio->ip_str);
+ return 0;
+ }
+ dtio->fd = socket(addr.ss_family, SOCK_STREAM, 0);
+ if(dtio->fd == -1) {
+#ifndef USE_WINSOCK
+ log_err("can't create socket: %s", strerror(errno));
+#else
+ log_err("can't create socket: %s",
+ wsa_strerror(WSAGetLastError()));
+#endif
+ return 0;
+ }
+ fd_set_nonblock(dtio->fd);
+ if(connect(dtio->fd, (struct sockaddr*)&addr, addrlen) == -1) {
+ if(errno == EINPROGRESS)
+ return 1; /* wait until connect done*/
+#ifndef USE_WINSOCK
+ if(tcp_connect_errno_needs_log(
+ (struct sockaddr *)&addr, addrlen)) {
+ log_err("dnstap io: failed to connect to %s: %s",
+ dtio->ip_str, strerror(errno));
+ }
+#else
+ if(WSAGetLastError() == WSAEINPROGRESS ||
+ WSAGetLastError() == WSAEWOULDBLOCK)
+ return 1; /* wait until connect done*/
+ if(tcp_connect_errno_needs_log(
+ (struct sockaddr *)&addr, addrlen)) {
+ log_err("dnstap io: failed to connect to %s: %s",
+ dtio->ip_str, wsa_strerror(WSAGetLastError()));
+ }
+#endif
+ dtio_close_fd(dtio);
+ return 0;
+ }
+ return 1;
+}
+
+/** setup the SSL structure for new connection */
+static int dtio_setup_ssl(struct dt_io_thread* dtio)
+{
+ dtio->ssl = outgoing_ssl_fd(dtio->ssl_ctx, dtio->fd);
+ if(!dtio->ssl) return 0;
+ dtio->ssl_handshake_done = 0;
+ dtio->ssl_brief_read = 0;
+
+ if(!set_auth_name_on_ssl(dtio->ssl, dtio->tls_server_name,
+ dtio->tls_use_sni)) {
+ return 0;
+ }
+ return 1;
+}
+
+/** open the output file descriptor */
+static void dtio_open_output(struct dt_io_thread* dtio)
+{
+ struct ub_event* ev;
+ if(dtio->upstream_is_unix) {
+ if(!dtio_open_output_local(dtio)) {
+ dtio_reconnect_enable(dtio);
+ return;
+ }
+ } else if(dtio->upstream_is_tcp || dtio->upstream_is_tls) {
+ if(!dtio_open_output_tcp(dtio)) {
+ dtio_reconnect_enable(dtio);
+ return;
+ }
+ if(dtio->upstream_is_tls) {
+ if(!dtio_setup_ssl(dtio)) {
+ dtio_close_fd(dtio);
+ dtio_reconnect_enable(dtio);
+ return;
+ }
+ }
+ }
+ dtio->check_nb_connect = 1;
+
+ /* the EV_READ is to read ACCEPT control messages, and catch channel
+ * close. EV_WRITE is to write packets */
+ ev = ub_event_new(dtio->event_base, dtio->fd,
+ UB_EV_READ | UB_EV_WRITE | UB_EV_PERSIST, &dtio_output_cb,
+ dtio);
+ if(!ev) {
+ log_err("dnstap io: out of memory");
+ if(dtio->ssl) {
+#ifdef HAVE_SSL
+ SSL_free(dtio->ssl);
+ dtio->ssl = NULL;
+#endif
+ }
+ dtio_close_fd(dtio);
+ dtio_reconnect_enable(dtio);
+ return;
+ }
+ dtio->event = ev;
+
+ /* setup protocol control message to start */
+ if((!dtio->is_bidirectional && !dtio_control_start_send(dtio)) ||
+ (dtio->is_bidirectional && !dtio_control_ready_send(dtio)) ) {
+ log_err("dnstap io: out of memory");
+ ub_event_free(dtio->event);
+ dtio->event = NULL;
+ if(dtio->ssl) {
+#ifdef HAVE_SSL
+ SSL_free(dtio->ssl);
+ dtio->ssl = NULL;
+#endif
+ }
+ dtio_close_fd(dtio);
+ dtio_reconnect_enable(dtio);
+ return;
+ }
+}
+
+/** perform the setup of the writer thread on the established event_base */
+static void dtio_setup_on_base(struct dt_io_thread* dtio)
+{
+ dtio_setup_cmd(dtio);
+ dtio_setup_reconnect(dtio);
+ dtio_open_output(dtio);
+ if(!dtio_add_output_event_write(dtio))
+ return;
+}
+
+#ifndef THREADS_DISABLED
+/** the IO thread function for the DNSTAP IO */
+static void* dnstap_io(void* arg)
+{
+ struct dt_io_thread* dtio = (struct dt_io_thread*)arg;
+ time_t secs = 0;
+ struct timeval now;
+ log_thread_set(&dtio->threadnum);
+
+ /* setup */
+ verbose(VERB_ALGO, "start dnstap io thread");
+ dtio_setup_base(dtio, &secs, &now);
+ dtio_setup_on_base(dtio);
+
+ /* run */
+ if(ub_event_base_dispatch(dtio->event_base) < 0) {
+ log_err("dnstap io: dispatch failed, errno is %s",
+ strerror(errno));
+ }
+
+ /* cleanup */
+ verbose(VERB_ALGO, "stop dnstap io thread");
+ dtio_desetup(dtio);
+ return NULL;
+}
+#endif /* THREADS_DISABLED */
+
+int dt_io_thread_start(struct dt_io_thread* dtio, void* event_base_nothr,
+ int numworkers)
+{
+ /* set up the thread, can fail */
+#ifndef USE_WINSOCK
+ if(pipe(dtio->commandpipe) == -1) {
+ log_err("failed to create pipe: %s", strerror(errno));
+ return 0;
+ }
+#else
+ if(_pipe(dtio->commandpipe, 4096, _O_BINARY) == -1) {
+ log_err("failed to create _pipe: %s",
+ wsa_strerror(WSAGetLastError()));
+ return 0;
+ }
+#endif
+
+ /* start the thread */
+ dtio->threadnum = numworkers+1;
+ dtio->started = 1;
+#ifndef THREADS_DISABLED
+ ub_thread_create(&dtio->tid, dnstap_io, dtio);
+ (void)event_base_nothr;
+#else
+ dtio->event_base = event_base_nothr;
+ dtio_setup_on_base(dtio);
+#endif
+ return 1;
+}
+
+void dt_io_thread_stop(struct dt_io_thread* dtio)
+{
+#ifndef THREADS_DISABLED
+ uint8_t cmd = DTIO_COMMAND_STOP;
+#endif
+ if(!dtio) return;
+ if(!dtio->started) return;
+ verbose(VERB_ALGO, "dnstap io: send stop cmd");
+
+#ifndef THREADS_DISABLED
+ while(1) {
+ ssize_t r = write(dtio->commandpipe[1], &cmd, sizeof(cmd));
+ if(r == -1) {
+#ifndef USE_WINSOCK
+ if(errno == EINTR || errno == EAGAIN)
+ continue;
+ log_err("dnstap io stop: write: %s", strerror(errno));
+#else
+ if(WSAGetLastError() == WSAEINPROGRESS)
+ continue;
+ if(WSAGetLastError() == WSAEWOULDBLOCK)
+ continue;
+ log_err("dnstap io stop: write: %s",
+ wsa_strerror(WSAGetLastError()));
+#endif
+ break;
+ }
+ break;
+ }
+ dtio->started = 0;
+#endif /* THREADS_DISABLED */
+
+#ifndef USE_WINSOCK
+ close(dtio->commandpipe[1]);
+#else
+ _close(dtio->commandpipe[1]);
+#endif
+ dtio->commandpipe[1] = -1;
+#ifndef THREADS_DISABLED
+ ub_thread_join(dtio->tid);
+#else
+ dtio->want_to_exit = 1;
+ dtio_desetup(dtio);
+#endif
+}
diff --git a/contrib/unbound/dnstap/dtstream.h b/contrib/unbound/dnstap/dtstream.h
new file mode 100644
index 000000000000..ede491f30d3e
--- /dev/null
+++ b/contrib/unbound/dnstap/dtstream.h
@@ -0,0 +1,341 @@
+/*
+ * dnstap/dtstream.h - Frame Streams thread for unbound DNSTAP
+ *
+ * Copyright (c) 2020, NLnet Labs. All rights reserved.
+ *
+ * This software is open source.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of the NLNET LABS nor the names of its contributors may
+ * be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+/**
+ * \file
+ *
+ * An implementation of the Frame Streams data transport protocol for
+ * the Unbound DNSTAP message logging facility.
+ */
+
+#ifndef DTSTREAM_H
+#define DTSTREAM_H
+
+#include "util/locks.h"
+struct dt_msg_entry;
+struct dt_io_list_item;
+struct dt_io_thread;
+struct config_file;
+
+/**
+ * A message buffer with dnstap messages queued up. It is per-worker.
+ * It has locks to synchronize. If the buffer is full, a new message
+ * cannot be added and is discarded. A thread reads the messages and sends
+ * them.
+ */
+struct dt_msg_queue {
+ /** lock of the buffer structure. Hold this lock to add or remove
+ * entries to the buffer. Release it so that other threads can also
+ * put messages to log, or a message can be taken out to send away
+ * by the writer thread.
+ */
+ lock_basic_type lock;
+ /** the maximum size of the buffer, in bytes */
+ size_t maxsize;
+ /** current size of the buffer, in bytes. data bytes of messages.
+ * If a new message make it more than maxsize, the buffer is full */
+ size_t cursize;
+ /** list of messages. The messages are added to the back and taken
+ * out from the front. */
+ struct dt_msg_entry* first, *last;
+ /** reference to the io thread to wakeup */
+ struct dt_io_thread* dtio;
+};
+
+/**
+ * An entry in the dt_msg_queue. contains one DNSTAP message.
+ * It is malloced.
+ */
+struct dt_msg_entry {
+ /** next in the list. */
+ struct dt_msg_entry* next;
+ /** the buffer with the data to send, an encoded DNSTAP message */
+ void* buf;
+ /** the length to send. */
+ size_t len;
+};
+
+/**
+ * Containing buffer and counter for reading DNSTAP frames.
+ */
+struct dt_frame_read_buf {
+ /** Buffer containing frame, except length counter(s). */
+ void* buf;
+ /** Number of bytes written to buffer. */
+ size_t buf_count;
+ /** Capacity of the buffer. */
+ size_t buf_cap;
+
+ /** Frame length field. Will contain the 2nd length field for control
+ * frames. */
+ uint32_t frame_len;
+ /** Number of bytes that have been written to the frame_length field. */
+ size_t frame_len_done;
+
+ /** Set to 1 if this is a control frame, 0 otherwise (ie data frame). */
+ int control_frame;
+};
+
+/**
+ * IO thread that reads from the queues and writes them.
+ */
+struct dt_io_thread {
+ /** the thread number for the dtio thread,
+ * must be first to cast thread arg to int* in checklock code. */
+ int threadnum;
+ /** event base, for event handling */
+ void* event_base;
+ /** list of queues that is registered to get written */
+ struct dt_io_list_item* io_list;
+ /** iterator point in the io_list, to pick from them in a
+ * round-robin fashion, instead of only from the first when busy.
+ * if NULL it means start at the start of the list. */
+ struct dt_io_list_item* io_list_iter;
+ /** thread id, of the io thread */
+ ub_thread_type tid;
+ /** if the io processing has started */
+ int started;
+ /** ssl context for the io thread, for tls connections. type SSL_CTX* */
+ void* ssl_ctx;
+ /** if SNI will be used for TLS connections. */
+ int tls_use_sni;
+
+ /** file descriptor that the thread writes to */
+ int fd;
+ /** event structure that the thread uses */
+ void* event;
+ /** the event is added */
+ int event_added;
+ /** event added is a write event */
+ int event_added_is_write;
+ /** check for nonblocking connect errors on fd */
+ int check_nb_connect;
+ /** ssl for current connection, type SSL* */
+ void* ssl;
+ /** true if the handshake for SSL is done, 0 if not */
+ int ssl_handshake_done;
+ /** true if briefly the SSL wants a read event, 0 if not.
+ * This happens during negotiation, we then do not want to write,
+ * but wait for a read event. */
+ int ssl_brief_read;
+ /** true if SSL_read is waiting for a write event. Set back to 0 after
+ * single write event is handled. */
+ int ssl_brief_write;
+
+ /** the buffer that currently getting written, or NULL if no
+ * (partial) message written now */
+ void* cur_msg;
+ /** length of the current message */
+ size_t cur_msg_len;
+ /** number of bytes written for the current message */
+ size_t cur_msg_done;
+ /** number of bytes of the length that have been written,
+ * for the current message length that precedes the frame */
+ size_t cur_msg_len_done;
+
+ /** command pipe that stops the pipe if closed. Used to quit
+ * the program. [0] is read, [1] is written to. */
+ int commandpipe[2];
+ /** the event to listen to the commandpipe */
+ void* command_event;
+ /** the io thread wants to exit */
+ int want_to_exit;
+
+ /** in stop flush, this is nonNULL and references the stop_ev */
+ void* stop_flush_event;
+
+ /** the timer event for connection retries */
+ void* reconnect_timer;
+ /** if the reconnect timer is added to the event base */
+ int reconnect_is_added;
+ /** the current reconnection timeout, it is increased with
+ * exponential backoff, in msec */
+ int reconnect_timeout;
+
+ /** If the log server is connected to over unix domain sockets,
+ * eg. a file is named that is created to log onto. */
+ int upstream_is_unix;
+ /** if the log server is connected to over TCP. The ip address and
+ * port are used */
+ int upstream_is_tcp;
+ /** if the log server is connected to over TLS. ip address, port,
+ * and client certificates can be used for authentication. */
+ int upstream_is_tls;
+
+ /** Perform bidirectional Frame Streams handshake before sending
+ * messages. */
+ int is_bidirectional;
+ /** Set if the READY control frame has been sent. */
+ int ready_frame_sent;
+ /** Set if valid ACCEPT frame is received. */
+ int accept_frame_received;
+ /** (partially) read frame */
+ struct dt_frame_read_buf read_frame;
+
+ /** the file path for unix socket (or NULL) */
+ char* socket_path;
+ /** the ip address and port number (or NULL) */
+ char* ip_str;
+ /** is the TLS upstream authenticated by name, if nonNULL,
+ * we use the same cert bundle as used by other TLS streams. */
+ char* tls_server_name;
+ /** are client certificates in use */
+ int use_client_certs;
+ /** client cert files: the .key file */
+ char* client_key_file;
+ /** client cert files: the .pem file */
+ char* client_cert_file;
+};
+
+/**
+ * IO thread list of queues list item
+ * lists a worker queue that should be looked at and sent to the log server.
+ */
+struct dt_io_list_item {
+ /** next in the list of buffers to inspect */
+ struct dt_io_list_item* next;
+ /** buffer of this worker */
+ struct dt_msg_queue* queue;
+};
+
+/**
+ * Create new (empty) worker message queue. Limit set to default on max.
+ * @return NULL on malloc failure or a new queue (not locked).
+ */
+struct dt_msg_queue* dt_msg_queue_create(void);
+
+/**
+ * Delete a worker message queue. It has to be unlinked from access,
+ * so it can be deleted without lock worries. The queue is emptied (deleted).
+ * @param mq: message queue.
+ */
+void dt_msg_queue_delete(struct dt_msg_queue* mq);
+
+/**
+ * Submit a message to the queue. The queue is locked by the routine,
+ * the message is inserted, and then the queue is unlocked so the
+ * message can be picked up by the writer thread.
+ * @param mq: message queue.
+ * @param buf: buffer with message (dnstap contents).
+ * The buffer must have been malloced by caller. It is linked in
+ * the queue, and is free()d after use. If the routine fails
+ * the buffer is freed as well (and nothing happens, the item
+ * could not be logged).
+ * @param len: length of buffer.
+ */
+void dt_msg_queue_submit(struct dt_msg_queue* mq, void* buf, size_t len);
+
+/**
+ * Create IO thread.
+ * @return new io thread object. not yet started. or NULL malloc failure.
+ */
+struct dt_io_thread* dt_io_thread_create(void);
+
+/**
+ * Delete the IO thread structure.
+ * @param dtio: the io thread that is deleted. It must not be running.
+ */
+void dt_io_thread_delete(struct dt_io_thread* dtio);
+
+/**
+ * Apply config to the dtio thread
+ * @param dtio: io thread, not yet started.
+ * @param cfg: config file struct.
+ * @return false on malloc failure.
+ */
+int dt_io_thread_apply_cfg(struct dt_io_thread* dtio,
+ struct config_file *cfg);
+
+/**
+ * Register a msg queue to the io thread. It will be polled to see if
+ * there are messages and those then get removed and sent, when the thread
+ * is running.
+ * @param dtio: the io thread.
+ * @param mq: message queue to register.
+ * @return false on failure (malloc failure).
+ */
+int dt_io_thread_register_queue(struct dt_io_thread* dtio,
+ struct dt_msg_queue* mq);
+
+/**
+ * Unregister queue from io thread.
+ * @param dtio: the io thread.
+ * @param mq: message queue.
+ */
+void dt_io_thread_unregister_queue(struct dt_io_thread* dtio,
+ struct dt_msg_queue* mq);
+
+/**
+ * Start the io thread
+ * @param dtio: the io thread.
+ * @param event_base_nothr: the event base to attach the events to, in case
+ * we are running without threads. With threads, this is ignored
+ * and a thread is started to process the dnstap log messages.
+ * @param numworkers: number of worker threads. The dnstap io thread is
+ * that number +1 as the threadnumber (in logs).
+ * @return false on failure.
+ */
+int dt_io_thread_start(struct dt_io_thread* dtio, void* event_base_nothr,
+ int numworkers);
+
+/**
+ * Stop the io thread
+ * @param dtio: the io thread.
+ */
+void dt_io_thread_stop(struct dt_io_thread* dtio);
+
+/** callback for the dnstap reconnect, to start reconnecting to output */
+void dtio_reconnect_timeout_cb(int fd, short bits, void* arg);
+
+/** callback for the dnstap events, to write to the output */
+void dtio_output_cb(int fd, short bits, void* arg);
+
+/** callback for the dnstap commandpipe, to stop the dnstap IO */
+void dtio_cmd_cb(int fd, short bits, void* arg);
+
+/** callback for the timer when the thread stops and wants to finish up */
+void dtio_stop_timer_cb(int fd, short bits, void* arg);
+
+/** callback for the output when the thread stops and wants to finish up */
+void dtio_stop_ev_cb(int fd, short bits, void* arg);
+
+/** callback for unbound-dnstap-socket */
+void dtio_tap_callback(int fd, short bits, void* arg);
+
+/** callback for unbound-dnstap-socket */
+void dtio_mainfdcallback(int fd, short bits, void* arg);
+
+#endif /* DTSTREAM_H */
diff --git a/contrib/unbound/dnstap/unbound-dnstap-socket.c b/contrib/unbound/dnstap/unbound-dnstap-socket.c
new file mode 100644
index 000000000000..44a0eda95994
--- /dev/null
+++ b/contrib/unbound/dnstap/unbound-dnstap-socket.c
@@ -0,0 +1,1594 @@
+/*
+ * dnstap/unbound-dnstap-socket.c - debug program that listens for DNSTAP logs.
+ *
+ * Copyright (c) 2020, NLnet Labs. All rights reserved.
+ *
+ * This software is open source.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of the NLNET LABS nor the names of its contributors may
+ * be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * \file
+ *
+ * This program listens on a DNSTAP socket for logged messages.
+ */
+#include "config.h"
+#ifdef HAVE_GETOPT_H
+#include <getopt.h>
+#endif
+#include <signal.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <signal.h>
+#include <ctype.h>
+#ifdef HAVE_SYS_UN_H
+#include <sys/un.h>
+#endif
+#include <openssl/ssl.h>
+#include <openssl/rand.h>
+#include <openssl/err.h>
+#include "dnstap/dtstream.h"
+#include "dnstap/dnstap_fstrm.h"
+#include "util/log.h"
+#include "util/ub_event.h"
+#include "util/net_help.h"
+#include "services/listen_dnsport.h"
+#include "sldns/sbuffer.h"
+#include "sldns/wire2str.h"
+#ifdef USE_DNSTAP
+#include <protobuf-c/protobuf-c.h>
+#include "dnstap/dnstap.pb-c.h"
+#endif /* USE_DNSTAP */
+#include "util/config_file.h"
+
+/** listen backlog on TCP connections for dnstap logs */
+#define LISTEN_BACKLOG 16
+
+/** usage information for streamtcp */
+static void usage(char* argv[])
+{
+ printf("usage: %s [options]\n", argv[0]);
+ printf(" Listen to dnstap messages\n");
+ printf("stdout has dnstap log, stderr has verbose server log\n");
+ printf("-u <socketpath> listen to unix socket with this file name\n");
+ printf("-s <serverip[@port]> listen for TCP on the IP and port\n");
+ printf("-t <serverip[@port]> listen for TLS on IP and port\n");
+ printf("-x <server.key> server key file for TLS service\n");
+ printf("-y <server.pem> server cert file for TLS service\n");
+ printf("-z <verify.pem> cert file to verify client connections\n");
+ printf("-l long format for DNS printout\n");
+ printf("-v more verbose log output\n");
+ printf("-h this help text\n");
+ exit(1);
+}
+
+/** long format option, for multiline printout per message */
+static int longformat = 0;
+
+struct tap_socket_list;
+struct tap_socket;
+/** main tap callback data */
+struct main_tap_data {
+ /** the event base (to loopexit) */
+ struct ub_event_base* base;
+ /** the list of accept sockets */
+ struct tap_socket_list* acceptlist;
+};
+
+/** tap callback variables */
+struct tap_data {
+ /** the fd */
+ int fd;
+ /** the ub event */
+ struct ub_event* ev;
+ /** the SSL for TLS streams */
+ SSL* ssl;
+ /** is the ssl handshake done */
+ int ssl_handshake_done;
+ /** we are briefly waiting to write (in the struct event) */
+ int ssl_brief_write;
+ /** string that identifies the socket (or NULL), like IP address */
+ char* id;
+ /** have we read the length, and how many bytes of it */
+ int len_done;
+ /** have we read the data, and how many bytes of it */
+ size_t data_done;
+ /** are we reading a control frame */
+ int control_frame;
+ /** are we bi-directional (if false, uni-directional) */
+ int is_bidirectional;
+ /** data of the frame */
+ uint8_t* frame;
+ /** length of this frame */
+ size_t len;
+};
+
+/** list of sockets */
+struct tap_socket_list {
+ /** next in list */
+ struct tap_socket_list* next;
+ /** the socket */
+ struct tap_socket* s;
+};
+
+/** tap socket */
+struct tap_socket {
+ /** fd of socket */
+ int fd;
+ /** the event for it */
+ struct ub_event *ev;
+ /** has the event been added */
+ int ev_added;
+ /** the callback, for the event, ev_cb(fd, bits, arg) */
+ void (*ev_cb)(int, short, void*);
+ /** data element, (arg for the tap_socket struct) */
+ void* data;
+ /** socketpath, if this is an AF_LOCAL socket */
+ char* socketpath;
+ /** IP, if this is a TCP socket */
+ char* ip;
+ /** for a TLS socket, the tls context */
+ SSL_CTX* sslctx;
+};
+
+/** del the tap event */
+static void tap_socket_delev(struct tap_socket* s)
+{
+ if(!s) return;
+ if(!s->ev) return;
+ if(!s->ev_added) return;
+ ub_event_del(s->ev);
+ s->ev_added = 0;
+}
+
+/** close the tap socket */
+static void tap_socket_close(struct tap_socket* s)
+{
+ if(!s) return;
+ if(s->fd == -1) return;
+ close(s->fd);
+ s->fd = -1;
+}
+
+/** delete tap socket */
+static void tap_socket_delete(struct tap_socket* s)
+{
+ if(!s) return;
+#ifdef HAVE_SSL
+ SSL_CTX_free(s->sslctx);
+#endif
+ ub_event_free(s->ev);
+ free(s->socketpath);
+ free(s->ip);
+ free(s);
+}
+
+/** create new socket (unconnected, not base-added), or NULL malloc fail */
+static struct tap_socket* tap_socket_new_local(char* socketpath,
+ void (*ev_cb)(int, short, void*), void* data)
+{
+ struct tap_socket* s = calloc(1, sizeof(*s));
+ if(!s) {
+ log_err("malloc failure");
+ return NULL;
+ }
+ s->socketpath = strdup(socketpath);
+ if(!s->socketpath) {
+ free(s);
+ log_err("malloc failure");
+ return NULL;
+ }
+ s->fd = -1;
+ s->ev_cb = ev_cb;
+ s->data = data;
+ return s;
+}
+
+/** create new socket (unconnected, not base-added), or NULL malloc fail */
+static struct tap_socket* tap_socket_new_tcpaccept(char* ip,
+ void (*ev_cb)(int, short, void*), void* data)
+{
+ struct tap_socket* s = calloc(1, sizeof(*s));
+ if(!s) {
+ log_err("malloc failure");
+ return NULL;
+ }
+ s->ip = strdup(ip);
+ if(!s->ip) {
+ free(s);
+ log_err("malloc failure");
+ return NULL;
+ }
+ s->fd = -1;
+ s->ev_cb = ev_cb;
+ s->data = data;
+ return s;
+}
+
+/** create new socket (unconnected, not base-added), or NULL malloc fail */
+static struct tap_socket* tap_socket_new_tlsaccept(char* ip,
+ void (*ev_cb)(int, short, void*), void* data, char* server_key,
+ char* server_cert, char* verifypem)
+{
+ struct tap_socket* s = calloc(1, sizeof(*s));
+ if(!s) {
+ log_err("malloc failure");
+ return NULL;
+ }
+ s->ip = strdup(ip);
+ if(!s->ip) {
+ free(s);
+ log_err("malloc failure");
+ return NULL;
+ }
+ s->fd = -1;
+ s->ev_cb = ev_cb;
+ s->data = data;
+ s->sslctx = listen_sslctx_create(server_key, server_cert, verifypem);
+ if(!s->sslctx) {
+ log_err("could not create ssl context");
+ free(s->ip);
+ free(s);
+ return NULL;
+ }
+ return s;
+}
+
+/** setup tcp accept socket on IP string */
+static int make_tcp_accept(char* ip)
+{
+#ifdef SO_REUSEADDR
+ int on = 1;
+#endif
+ struct sockaddr_storage addr;
+ socklen_t len;
+ int s;
+
+ memset(&addr, 0, sizeof(addr));
+ len = (socklen_t)sizeof(addr);
+ if(!extstrtoaddr(ip, &addr, &len)) {
+ log_err("could not parse IP '%s'", ip);
+ return -1;
+ }
+
+ if((s = socket(addr.ss_family, SOCK_STREAM, 0)) == -1) {
+#ifndef USE_WINSOCK
+ log_err("can't create socket: %s", strerror(errno));
+#else
+ log_err("can't create socket: %s",
+ wsa_strerror(WSAGetLastError()));
+#endif
+ return -1;
+ }
+#ifdef SO_REUSEADDR
+ if(setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (void*)&on,
+ (socklen_t)sizeof(on)) < 0) {
+#ifndef USE_WINSOCK
+ log_err("setsockopt(.. SO_REUSEADDR ..) failed: %s",
+ strerror(errno));
+ close(s);
+#else
+ log_err("setsockopt(.. SO_REUSEADDR ..) failed: %s",
+ wsa_strerror(WSAGetLastError()));
+ closesocket(s);
+#endif
+ return -1;
+ }
+#endif /* SO_REUSEADDR */
+ if(bind(s, (struct sockaddr*)&addr, len) != 0) {
+#ifndef USE_WINSOCK
+ log_err_addr("can't bind socket", strerror(errno),
+ &addr, len);
+ close(s);
+#else
+ log_err_addr("can't bind socket",
+ wsa_strerror(WSAGetLastError()), &addr, len);
+ closesocket(s);
+#endif
+ return -1;
+ }
+ if(!fd_set_nonblock(s)) {
+#ifndef USE_WINSOCK
+ close(s);
+#else
+ closesocket(s);
+#endif
+ return -1;
+ }
+ if(listen(s, LISTEN_BACKLOG) == -1) {
+#ifndef USE_WINSOCK
+ log_err("can't listen: %s", strerror(errno));
+ close(s);
+#else
+ log_err("can't listen: %s", wsa_strerror(WSAGetLastError()));
+ closesocket(s);
+#endif
+ return -1;
+ }
+ return s;
+}
+
+/** setup socket on event base */
+static int tap_socket_setup(struct tap_socket* s, struct ub_event_base* base)
+{
+ if(s->socketpath) {
+ /* AF_LOCAL accept socket */
+ s->fd = create_local_accept_sock(s->socketpath, NULL, 0);
+ if(s->fd == -1) {
+ log_err("could not create local socket");
+ return 0;
+ }
+ } else if(s->ip || s->sslctx) {
+ /* TCP accept socket */
+ s->fd = make_tcp_accept(s->ip);
+ if(s->fd == -1) {
+ log_err("could not create tcp socket");
+ return 0;
+ }
+ }
+ s->ev = ub_event_new(base, s->fd, UB_EV_READ | UB_EV_PERSIST,
+ s->ev_cb, s);
+ if(!s->ev) {
+ log_err("could not ub_event_new");
+ return 0;
+ }
+ if(ub_event_add(s->ev, NULL) != 0) {
+ log_err("could not ub_event_add");
+ return 0;
+ }
+ s->ev_added = 1;
+ return 1;
+}
+
+/** add tap socket to list */
+static int tap_socket_list_insert(struct tap_socket_list** liststart,
+ struct tap_socket* s)
+{
+ struct tap_socket_list* entry = (struct tap_socket_list*)
+ malloc(sizeof(*entry));
+ if(!entry)
+ return 0;
+ entry->next = *liststart;
+ entry->s = s;
+ *liststart = entry;
+ return 1;
+}
+
+/** delete the list */
+static void tap_socket_list_delete(struct tap_socket_list* list)
+{
+ struct tap_socket_list* e = list, *next;
+ while(e) {
+ next = e->next;
+ tap_socket_delev(e->s);
+ tap_socket_close(e->s);
+ tap_socket_delete(e->s);
+ free(e);
+ e = next;
+ }
+}
+
+/** setup accept events */
+static int tap_socket_list_addevs(struct tap_socket_list* list,
+ struct ub_event_base* base)
+{
+ struct tap_socket_list* entry;
+ for(entry = list; entry; entry = entry->next) {
+ if(!tap_socket_setup(entry->s, base)) {
+ log_err("could not setup socket");
+ return 0;
+ }
+ }
+ return 1;
+}
+
+#ifdef USE_DNSTAP
+/** log control frame contents */
+static void log_control_frame(uint8_t* pkt, size_t len)
+{
+ char* desc;
+ if(verbosity == 0) return;
+ desc = fstrm_describe_control(pkt, len);
+ if(!desc) {
+ log_err("out of memory");
+ return;
+ }
+ log_info("control frame %s", desc);
+ free(desc);
+}
+
+/** convert mtype to string */
+static const char* mtype_to_str(enum _Dnstap__Message__Type mtype)
+{
+ switch(mtype) {
+ case DNSTAP__MESSAGE__TYPE__AUTH_QUERY:
+ return "AUTH_QUERY";
+ case DNSTAP__MESSAGE__TYPE__AUTH_RESPONSE:
+ return "AUTH_RESPONSE";
+ case DNSTAP__MESSAGE__TYPE__RESOLVER_QUERY:
+ return "RESOLVER_QUERY";
+ case DNSTAP__MESSAGE__TYPE__RESOLVER_RESPONSE:
+ return "RESOLVER_RESPONSE";
+ case DNSTAP__MESSAGE__TYPE__CLIENT_QUERY:
+ return "CLIENT_QUERY";
+ case DNSTAP__MESSAGE__TYPE__CLIENT_RESPONSE:
+ return "CLIENT_RESPONSE";
+ case DNSTAP__MESSAGE__TYPE__FORWARDER_QUERY:
+ return "FORWARDER_QUERY";
+ case DNSTAP__MESSAGE__TYPE__FORWARDER_RESPONSE:
+ return "FORWARDER_RESPONSE";
+ case DNSTAP__MESSAGE__TYPE__STUB_QUERY:
+ return "STUB_QUERY";
+ case DNSTAP__MESSAGE__TYPE__STUB_RESPONSE:
+ return "STUB_RESPONSE";
+ default: break;
+ }
+ return "unknown_message_type";
+}
+
+/** convert type address to a string ip4 or ip6, malloced or NULL on fail */
+static char* str_of_addr(ProtobufCBinaryData address)
+{
+ char buf[64];
+ socklen_t len = sizeof(buf);
+ if(address.len == 4) {
+ if(inet_ntop(AF_INET, address.data, buf, len)!=0)
+ return strdup(buf);
+ } else if(address.len == 16) {
+ if(inet_ntop(AF_INET6, address.data, buf, len)!=0)
+ return strdup(buf);
+ }
+ return NULL;
+}
+
+/** convert message buffer (of dns bytes) to the first qname, type, class,
+ * malloced or NULL on fail */
+static char* q_of_msg(ProtobufCBinaryData message)
+{
+ char buf[300];
+ /* header, name, type, class minimum to get the query tuple */
+ if(message.len < 12 + 1 + 4 + 4) return NULL;
+ if(sldns_wire2str_rrquestion_buf(message.data+12, message.len-12,
+ buf, sizeof(buf)) != 0) {
+ /* remove trailing newline, tabs to spaces */
+ /* remove the newline: */
+ if(buf[0] != 0) buf[strlen(buf)-1]=0;
+ /* remove first tab (before type) */
+ if(strrchr(buf, '\t')) *strrchr(buf, '\t')=' ';
+ /* remove second tab (before class) */
+ if(strrchr(buf, '\t')) *strrchr(buf, '\t')=' ';
+ return strdup(buf);
+ }
+ return NULL;
+}
+
+/** convert possible string or hex data to string. malloced or NULL */
+static char* possible_str(ProtobufCBinaryData str)
+{
+ int is_str = 1;
+ size_t i;
+ for(i=0; i<str.len; i++) {
+ if(!isprint((unsigned char)str.data[i]))
+ is_str = 0;
+ }
+ if(is_str) {
+ char* res = malloc(str.len+1);
+ if(res) {
+ memmove(res, str.data, str.len);
+ res[str.len] = 0;
+ return res;
+ }
+ } else {
+ const char* hex = "0123456789ABCDEF";
+ char* res = malloc(str.len*2+1);
+ if(res) {
+ for(i=0; i<str.len; i++) {
+ res[i*2] = hex[(str.data[i]&0xf0)>>4];
+ res[i*2+1] = hex[str.data[i]&0x0f];
+ }
+ res[str.len*2] = 0;
+ return res;
+ }
+ }
+ return NULL;
+}
+
+/** convert timeval to string, malloced or NULL */
+static char* tv_to_str(protobuf_c_boolean has_time_sec, uint64_t time_sec,
+ protobuf_c_boolean has_time_nsec, uint32_t time_nsec)
+{
+ char buf[64], buf2[256];
+ struct timeval tv;
+ time_t time_t_sec;
+ memset(&tv, 0, sizeof(tv));
+ if(has_time_sec) tv.tv_sec = time_sec;
+ if(has_time_nsec) tv.tv_usec = time_nsec;
+
+ buf[0]=0;
+ time_t_sec = tv.tv_sec;
+ (void)ctime_r(&time_t_sec, buf);
+ snprintf(buf2, sizeof(buf2), "%u.%9.9u %s",
+ (unsigned)time_sec, (unsigned)time_nsec, buf);
+ return strdup(buf2);
+}
+
+/** log data frame contents */
+static void log_data_frame(uint8_t* pkt, size_t len)
+{
+ Dnstap__Dnstap* d = dnstap__dnstap__unpack(NULL, len, pkt);
+ const char* mtype = NULL;
+ char* maddr=NULL, *qinf=NULL;
+ if(!d) {
+ log_err("could not unpack");
+ return;
+ }
+ if(d->base.descriptor != &dnstap__dnstap__descriptor) {
+ log_err("wrong base descriptor");
+ dnstap__dnstap__free_unpacked(d, NULL);
+ return;
+ }
+ if(d->type != DNSTAP__DNSTAP__TYPE__MESSAGE) {
+ log_err("dnstap type not type_message");
+ dnstap__dnstap__free_unpacked(d, NULL);
+ return;
+ }
+ if(d->message) {
+ mtype = mtype_to_str(d->message->type);
+ if(d->message->has_query_address)
+ maddr = str_of_addr(d->message->query_address);
+ else if(d->message->has_response_address)
+ maddr = str_of_addr(d->message->response_address);
+ if(d->message->has_query_message)
+ qinf = q_of_msg(d->message->query_message);
+ else if(d->message->has_response_message)
+ qinf = q_of_msg(d->message->response_message);
+
+ } else {
+ mtype = "nomessage";
+ }
+
+ printf("%s%s%s%s%s\n", mtype, (maddr?" ":""), (maddr?maddr:""),
+ (qinf?" ":""), (qinf?qinf:""));
+ free(maddr);
+ free(qinf);
+
+ if(longformat) {
+ char* id=NULL, *vs=NULL;
+ if(d->has_identity) {
+ id=possible_str(d->identity);
+ }
+ if(d->has_version) {
+ vs=possible_str(d->version);
+ }
+ if(id || vs)
+ printf("identity: %s%s%s\n", (id?id:""),
+ (id&&vs?" ":""), (vs?vs:""));
+ free(id);
+ free(vs);
+
+ if(d->message && d->message->has_query_message &&
+ d->message->query_message.data) {
+ char* qmsg = sldns_wire2str_pkt(
+ d->message->query_message.data,
+ d->message->query_message.len);
+ if(qmsg) {
+ printf("query_message:\n%s", qmsg);
+ free(qmsg);
+ }
+ }
+ if(d->message && d->message->has_query_time_sec) {
+ char* qtv = tv_to_str(d->message->has_query_time_sec,
+ d->message->query_time_sec,
+ d->message->has_query_time_nsec,
+ d->message->query_time_nsec);
+ if(qtv) {
+ printf("query_time: %s\n", qtv);
+ free(qtv);
+ }
+ }
+ if(d->message && d->message->has_response_message &&
+ d->message->response_message.data) {
+ char* rmsg = sldns_wire2str_pkt(
+ d->message->response_message.data,
+ d->message->response_message.len);
+ if(rmsg) {
+ printf("response_message:\n%s", rmsg);
+ free(rmsg);
+ }
+ }
+ if(d->message && d->message->has_response_time_sec) {
+ char* rtv = tv_to_str(d->message->has_response_time_sec,
+ d->message->response_time_sec,
+ d->message->has_response_time_nsec,
+ d->message->response_time_nsec);
+ if(rtv) {
+ printf("response_time: %s\n", rtv);
+ free(rtv);
+ }
+ }
+ }
+ fflush(stdout);
+ dnstap__dnstap__free_unpacked(d, NULL);
+}
+#endif /* USE_DNSTAP */
+
+/** receive bytes from fd, prints errors if bad,
+ * returns 0: closed/error, -1: continue, >0 number of bytes */
+static ssize_t receive_bytes(struct tap_data* data, int fd, void* buf,
+ size_t len)
+{
+ ssize_t ret = recv(fd, buf, len, 0);
+ if(ret == 0) {
+ /* closed */
+ if(verbosity) log_info("dnstap client stream closed from %s",
+ (data->id?data->id:""));
+ return 0;
+ } else if(ret == -1) {
+ /* error */
+#ifndef USE_WINSOCK
+ if(errno == EINTR || errno == EAGAIN)
+ return -1;
+ log_err("could not recv: %s", strerror(errno));
+#else /* USE_WINSOCK */
+ if(WSAGetLastError() == WSAEINPROGRESS)
+ return -1;
+ if(WSAGetLastError() == WSAEWOULDBLOCK) {
+ ub_winsock_tcp_wouldblock(data->ev, UB_EV_READ);
+ return -1;
+ }
+ log_err("could not recv: %s",
+ wsa_strerror(WSAGetLastError()));
+#endif
+ if(verbosity) log_info("dnstap client stream closed from %s",
+ (data->id?data->id:""));
+ return 0;
+ }
+ return ret;
+}
+
+/* define routine for have_ssl only to avoid unused function warning */
+#ifdef HAVE_SSL
+/** set to wait briefly for a write event, for one event call */
+static void tap_enable_brief_write(struct tap_data* data)
+{
+ ub_event_del(data->ev);
+ ub_event_del_bits(data->ev, UB_EV_READ);
+ ub_event_add_bits(data->ev, UB_EV_WRITE);
+ if(ub_event_add(data->ev, NULL) != 0)
+ log_err("could not ub_event_add in tap_enable_brief_write");
+ data->ssl_brief_write = 1;
+}
+#endif /* HAVE_SSL */
+
+/* define routine for have_ssl only to avoid unused function warning */
+#ifdef HAVE_SSL
+/** stop the brief wait for a write event. back to reading. */
+static void tap_disable_brief_write(struct tap_data* data)
+{
+ ub_event_del(data->ev);
+ ub_event_del_bits(data->ev, UB_EV_WRITE);
+ ub_event_add_bits(data->ev, UB_EV_READ);
+ if(ub_event_add(data->ev, NULL) != 0)
+ log_err("could not ub_event_add in tap_disable_brief_write");
+ data->ssl_brief_write = 0;
+}
+#endif /* HAVE_SSL */
+
+#ifdef HAVE_SSL
+/** receive bytes over ssl stream, prints errors if bad,
+ * returns 0: closed/error, -1: continue, >0 number of bytes */
+static ssize_t ssl_read_bytes(struct tap_data* data, void* buf, size_t len)
+{
+ int r;
+ ERR_clear_error();
+ r = SSL_read(data->ssl, buf, len);
+ if(r <= 0) {
+ int want = SSL_get_error(data->ssl, r);
+ if(want == SSL_ERROR_ZERO_RETURN) {
+ /* closed */
+ if(verbosity) log_info("dnstap client stream closed from %s",
+ (data->id?data->id:""));
+ return 0;
+ } else if(want == SSL_ERROR_WANT_READ) {
+ /* continue later */
+ return -1;
+ } else if(want == SSL_ERROR_WANT_WRITE) {
+ /* set to briefly write */
+ tap_enable_brief_write(data);
+ return -1;
+ } else if(want == SSL_ERROR_SYSCALL) {
+#ifdef ECONNRESET
+ if(errno == ECONNRESET && verbosity < 2)
+ return 0; /* silence reset by peer */
+#endif
+ if(errno != 0)
+ log_err("SSL_read syscall: %s",
+ strerror(errno));
+ if(verbosity) log_info("dnstap client stream closed from %s",
+ (data->id?data->id:""));
+ return 0;
+ }
+ log_crypto_err("could not SSL_read");
+ if(verbosity) log_info("dnstap client stream closed from %s",
+ (data->id?data->id:""));
+ return 0;
+ }
+ return r;
+}
+#endif /* HAVE_SSL */
+
+/** receive bytes on the tap connection, prints errors if bad,
+ * returns 0: closed/error, -1: continue, >0 number of bytes */
+static ssize_t tap_receive(struct tap_data* data, void* buf, size_t len)
+{
+#ifdef HAVE_SSL
+ if(data->ssl)
+ return ssl_read_bytes(data, buf, len);
+#endif
+ return receive_bytes(data, data->fd, buf, len);
+}
+
+/** delete the tap structure */
+void tap_data_free(struct tap_data* data)
+{
+ ub_event_del(data->ev);
+ ub_event_free(data->ev);
+#ifdef HAVE_SSL
+ SSL_free(data->ssl);
+#endif
+ close(data->fd);
+ free(data->id);
+ free(data->frame);
+ free(data);
+}
+
+/** reply with ACCEPT control frame to bidirectional client,
+ * returns 0 on error */
+static int reply_with_accept(struct tap_data* data)
+{
+#ifdef USE_DNSTAP
+ /* len includes the escape and framelength */
+ int r;
+ size_t len = 0;
+ void* acceptframe = fstrm_create_control_frame_accept(
+ DNSTAP_CONTENT_TYPE, &len);
+ if(!acceptframe) {
+ log_err("out of memory");
+ return 0;
+ }
+
+ fd_set_block(data->fd);
+ if(data->ssl) {
+ if((r=SSL_write(data->ssl, acceptframe, len)) <= 0) {
+ if(SSL_get_error(data->ssl, r) == SSL_ERROR_ZERO_RETURN)
+ log_err("SSL_write, peer closed connection");
+ else
+ log_err("could not SSL_write");
+ fd_set_nonblock(data->fd);
+ free(acceptframe);
+ return 0;
+ }
+ } else {
+ if(send(data->fd, acceptframe, len, 0) == -1) {
+#ifndef USE_WINSOCK
+ log_err("send failed: %s", strerror(errno));
+#else
+ log_err("send failed: %s",
+ wsa_strerror(WSAGetLastError()));
+#endif
+ fd_set_nonblock(data->fd);
+ free(acceptframe);
+ return 0;
+ }
+ }
+ if(verbosity) log_info("sent control frame(accept) content-type:(%s)",
+ DNSTAP_CONTENT_TYPE);
+
+ fd_set_nonblock(data->fd);
+ free(acceptframe);
+ return 1;
+#else
+ log_err("no dnstap compiled, no reply");
+ (void)data;
+ return 0;
+#endif
+}
+
+/** reply with FINISH control frame to bidirectional client,
+ * returns 0 on error */
+static int reply_with_finish(int fd)
+{
+#ifdef USE_DNSTAP
+ size_t len = 0;
+ void* finishframe = fstrm_create_control_frame_finish(&len);
+ if(!finishframe) {
+ log_err("out of memory");
+ return 0;
+ }
+
+ fd_set_block(fd);
+ if(send(fd, finishframe, len, 0) == -1) {
+#ifndef USE_WINSOCK
+ log_err("send failed: %s", strerror(errno));
+#else
+ log_err("send failed: %s", wsa_strerror(WSAGetLastError()));
+#endif
+ fd_set_nonblock(fd);
+ free(finishframe);
+ return 0;
+ }
+ if(verbosity) log_info("sent control frame(finish)");
+
+ fd_set_nonblock(fd);
+ free(finishframe);
+ return 1;
+#else
+ log_err("no dnstap compiled, no reply");
+ (void)fd;
+ return 0;
+#endif
+}
+
+#ifdef HAVE_SSL
+/** check SSL peer certificate, return 0 on fail */
+static int tap_check_peer(struct tap_data* data)
+{
+ if((SSL_get_verify_mode(data->ssl)&SSL_VERIFY_PEER)) {
+ /* verification */
+ if(SSL_get_verify_result(data->ssl) == X509_V_OK) {
+ X509* x = SSL_get_peer_certificate(data->ssl);
+ if(!x) {
+ if(verbosity) log_info("SSL connection %s"
+ " failed no certificate", data->id);
+ return 0;
+ }
+ if(verbosity)
+ log_cert(VERB_ALGO, "peer certificate", x);
+#ifdef HAVE_SSL_GET0_PEERNAME
+ if(SSL_get0_peername(data->ssl)) {
+ if(verbosity) log_info("SSL connection %s "
+ "to %s authenticated", data->id,
+ SSL_get0_peername(data->ssl));
+ } else {
+#endif
+ if(verbosity) log_info("SSL connection %s "
+ "authenticated", data->id);
+#ifdef HAVE_SSL_GET0_PEERNAME
+ }
+#endif
+ X509_free(x);
+ } else {
+ X509* x = SSL_get_peer_certificate(data->ssl);
+ if(x) {
+ if(verbosity)
+ log_cert(VERB_ALGO, "peer certificate", x);
+ X509_free(x);
+ }
+ if(verbosity) log_info("SSL connection %s failed: "
+ "failed to authenticate", data->id);
+ return 0;
+ }
+ } else {
+ /* unauthenticated, the verify peer flag was not set
+ * in ssl when the ssl object was created from ssl_ctx */
+ if(verbosity) log_info("SSL connection %s", data->id);
+ }
+ return 1;
+}
+#endif /* HAVE_SSL */
+
+#ifdef HAVE_SSL
+/** perform SSL handshake, return 0 to wait for events, 1 if done */
+static int tap_handshake(struct tap_data* data)
+{
+ int r;
+ if(data->ssl_brief_write) {
+ /* write condition has been satisfied, back to reading */
+ tap_disable_brief_write(data);
+ }
+ if(data->ssl_handshake_done)
+ return 1;
+
+ ERR_clear_error();
+ r = SSL_do_handshake(data->ssl);
+ if(r != 1) {
+ int want = SSL_get_error(data->ssl, r);
+ if(want == SSL_ERROR_WANT_READ) {
+ return 0;
+ } else if(want == SSL_ERROR_WANT_WRITE) {
+ tap_enable_brief_write(data);
+ return 0;
+ } else if(r == 0) {
+ /* closed */
+ tap_data_free(data);
+ return 0;
+ } else if(want == SSL_ERROR_SYSCALL) {
+ /* SYSCALL and errno==0 means closed uncleanly */
+ int silent = 0;
+#ifdef EPIPE
+ if(errno == EPIPE && verbosity < 2)
+ silent = 1; /* silence 'broken pipe' */
+#endif
+#ifdef ECONNRESET
+ if(errno == ECONNRESET && verbosity < 2)
+ silent = 1; /* silence reset by peer */
+#endif
+ if(errno == 0)
+ silent = 1;
+ if(!silent)
+ log_err("SSL_handshake syscall: %s",
+ strerror(errno));
+ tap_data_free(data);
+ return 0;
+ } else {
+ unsigned long err = ERR_get_error();
+ if(!squelch_err_ssl_handshake(err)) {
+ log_crypto_err_code("ssl handshake failed",
+ err);
+ verbose(VERB_OPS, "ssl handshake failed "
+ "from %s", data->id);
+ }
+ tap_data_free(data);
+ return 0;
+ }
+ }
+ /* check peer verification */
+ data->ssl_handshake_done = 1;
+ if(!tap_check_peer(data)) {
+ /* closed */
+ tap_data_free(data);
+ return 0;
+ }
+ return 1;
+}
+#endif /* HAVE_SSL */
+
+/** callback for dnstap listener */
+void dtio_tap_callback(int fd, short ATTR_UNUSED(bits), void* arg)
+{
+ struct tap_data* data = (struct tap_data*)arg;
+ if(verbosity>=3) log_info("tap callback");
+#ifdef HAVE_SSL
+ if(data->ssl && (!data->ssl_handshake_done ||
+ data->ssl_brief_write)) {
+ if(!tap_handshake(data))
+ return;
+ }
+#endif
+ while(data->len_done < 4) {
+ uint32_t l = (uint32_t)data->len;
+ ssize_t ret = tap_receive(data,
+ ((uint8_t*)&l)+data->len_done, 4-data->len_done);
+ if(verbosity>=4) log_info("s recv %d", (int)ret);
+ if(ret == 0) {
+ /* closed or error */
+ tap_data_free(data);
+ return;
+ } else if(ret == -1) {
+ /* continue later */
+ return;
+ }
+ data->len_done += ret;
+ data->len = (size_t)l;
+ if(data->len_done < 4)
+ return; /* continue later */
+ data->len = (size_t)(ntohl(l));
+ if(verbosity>=3) log_info("length is %d", (int)data->len);
+ if(data->len == 0) {
+ /* it is a control frame */
+ data->control_frame = 1;
+ /* read controlframelen */
+ data->len_done = 0;
+ } else {
+ /* allocate frame size */
+ data->frame = calloc(1, data->len);
+ if(!data->frame) {
+ log_err("out of memory");
+ tap_data_free(data);
+ return;
+ }
+ }
+ }
+
+ /* we want to read the full length now */
+ if(data->data_done < data->len) {
+ ssize_t r = tap_receive(data, data->frame + data->data_done,
+ data->len - data->data_done);
+ if(verbosity>=4) log_info("f recv %d", (int)r);
+ if(r == 0) {
+ /* closed or error */
+ tap_data_free(data);
+ return;
+ } else if(r == -1) {
+ /* continue later */
+ return;
+ }
+ data->data_done += r;
+ if(data->data_done < data->len)
+ return; /* continue later */
+ }
+
+ /* we are done with a frame */
+ if(verbosity>=3) log_info("received %sframe len %d",
+ (data->control_frame?"control ":""), (int)data->len);
+#ifdef USE_DNSTAP
+ if(data->control_frame)
+ log_control_frame(data->frame, data->len);
+ else log_data_frame(data->frame, data->len);
+#endif
+
+ if(data->len >= 4 && sldns_read_uint32(data->frame) ==
+ FSTRM_CONTROL_FRAME_READY) {
+ data->is_bidirectional = 1;
+ if(verbosity) log_info("bidirectional stream");
+ if(!reply_with_accept(data)) {
+ tap_data_free(data);
+ }
+ } else if(data->len >= 4 && sldns_read_uint32(data->frame) ==
+ FSTRM_CONTROL_FRAME_STOP && data->is_bidirectional) {
+ if(!reply_with_finish(fd)) {
+ tap_data_free(data);
+ return;
+ }
+ }
+
+ /* prepare for next frame */
+ free(data->frame);
+ data->frame = NULL;
+ data->control_frame = 0;
+ data->len = 0;
+ data->len_done = 0;
+ data->data_done = 0;
+
+}
+
+/** callback for main listening file descriptor */
+void dtio_mainfdcallback(int fd, short ATTR_UNUSED(bits), void* arg)
+{
+ struct tap_socket* tap_sock = (struct tap_socket*)arg;
+ struct main_tap_data* maindata = (struct main_tap_data*)
+ tap_sock->data;
+ struct tap_data* data;
+ char* id = NULL;
+ struct sockaddr_storage addr;
+ socklen_t addrlen = (socklen_t)sizeof(addr);
+ int s = accept(fd, (struct sockaddr*)&addr, &addrlen);
+ if(s == -1) {
+#ifndef USE_WINSOCK
+ /* EINTR is signal interrupt. others are closed connection. */
+ if( errno == EINTR || errno == EAGAIN
+#ifdef EWOULDBLOCK
+ || errno == EWOULDBLOCK
+#endif
+#ifdef ECONNABORTED
+ || errno == ECONNABORTED
+#endif
+#ifdef EPROTO
+ || errno == EPROTO
+#endif /* EPROTO */
+ )
+ return;
+ log_err_addr("accept failed", strerror(errno), &addr, addrlen);
+#else /* USE_WINSOCK */
+ if(WSAGetLastError() == WSAEINPROGRESS ||
+ WSAGetLastError() == WSAECONNRESET)
+ return;
+ if(WSAGetLastError() == WSAEWOULDBLOCK) {
+ ub_winsock_tcp_wouldblock(maindata->ev, UB_EV_READ);
+ return;
+ }
+ log_err_addr("accept failed", wsa_strerror(WSAGetLastError()),
+ &addr, addrlen);
+#endif
+ return;
+ }
+ fd_set_nonblock(s);
+ if(verbosity) {
+ if(addr.ss_family == AF_LOCAL) {
+#ifdef HAVE_SYS_UN_H
+ struct sockaddr_un* usock = calloc(1, sizeof(struct sockaddr_un) + 1);
+ if(usock) {
+ socklen_t ulen = sizeof(struct sockaddr_un);
+ if(getsockname(fd, (struct sockaddr*)usock, &ulen) != -1) {
+ log_info("accepted new dnstap client from %s", usock->sun_path);
+ id = strdup(usock->sun_path);
+ } else {
+ log_info("accepted new dnstap client");
+ }
+ free(usock);
+ } else {
+ log_info("accepted new dnstap client");
+ }
+#endif /* HAVE_SYS_UN_H */
+ } else if(addr.ss_family == AF_INET ||
+ addr.ss_family == AF_INET6) {
+ char ip[256];
+ addr_to_str(&addr, addrlen, ip, sizeof(ip));
+ log_info("accepted new dnstap client from %s", ip);
+ id = strdup(ip);
+ } else {
+ log_info("accepted new dnstap client");
+ }
+ }
+
+ data = calloc(1, sizeof(*data));
+ if(!data) fatal_exit("out of memory");
+ data->fd = s;
+ data->id = id;
+ if(tap_sock->sslctx) {
+ data->ssl = incoming_ssl_fd(tap_sock->sslctx, data->fd);
+ if(!data->ssl) fatal_exit("could not SSL_new");
+ }
+ data->ev = ub_event_new(maindata->base, s, UB_EV_READ | UB_EV_PERSIST,
+ &dtio_tap_callback, data);
+ if(!data->ev) fatal_exit("could not ub_event_new");
+ if(ub_event_add(data->ev, NULL) != 0) fatal_exit("could not ub_event_add");
+}
+
+/** setup local accept sockets */
+static void setup_local_list(struct main_tap_data* maindata,
+ struct config_strlist_head* local_list)
+{
+ struct config_strlist* item;
+ for(item = local_list->first; item; item = item->next) {
+ struct tap_socket* s;
+ s = tap_socket_new_local(item->str, &dtio_mainfdcallback,
+ maindata);
+ if(!s) fatal_exit("out of memory");
+ if(!tap_socket_list_insert(&maindata->acceptlist, s))
+ fatal_exit("out of memory");
+ }
+}
+
+/** setup tcp accept sockets */
+static void setup_tcp_list(struct main_tap_data* maindata,
+ struct config_strlist_head* tcp_list)
+{
+ struct config_strlist* item;
+ for(item = tcp_list->first; item; item = item->next) {
+ struct tap_socket* s;
+ s = tap_socket_new_tcpaccept(item->str, &dtio_mainfdcallback,
+ maindata);
+ if(!s) fatal_exit("out of memory");
+ if(!tap_socket_list_insert(&maindata->acceptlist, s))
+ fatal_exit("out of memory");
+ }
+}
+
+/** setup tls accept sockets */
+static void setup_tls_list(struct main_tap_data* maindata,
+ struct config_strlist_head* tls_list, char* server_key,
+ char* server_cert, char* verifypem)
+{
+ struct config_strlist* item;
+ for(item = tls_list->first; item; item = item->next) {
+ struct tap_socket* s;
+ s = tap_socket_new_tlsaccept(item->str, &dtio_mainfdcallback,
+ maindata, server_key, server_cert, verifypem);
+ if(!s) fatal_exit("out of memory");
+ if(!tap_socket_list_insert(&maindata->acceptlist, s))
+ fatal_exit("out of memory");
+ }
+}
+
+/** signal variable */
+static struct ub_event_base* sig_base = NULL;
+/** do we have to quit */
+int sig_quit = 0;
+/** signal handler for user quit */
+static RETSIGTYPE main_sigh(int sig)
+{
+ verbose(VERB_ALGO, "exit on signal %d\n", sig);
+ if(sig_base)
+ ub_event_base_loopexit(sig_base);
+ sig_quit = 1;
+}
+
+/** setup and run the server to listen to DNSTAP messages */
+static void
+setup_and_run(struct config_strlist_head* local_list,
+ struct config_strlist_head* tcp_list,
+ struct config_strlist_head* tls_list, char* server_key,
+ char* server_cert, char* verifypem)
+{
+ time_t secs = 0;
+ struct timeval now;
+ struct main_tap_data* maindata;
+ struct ub_event_base* base;
+ const char *evnm="event", *evsys="", *evmethod="";
+
+ maindata = calloc(1, sizeof(*maindata));
+ if(!maindata) fatal_exit("out of memory");
+ memset(&now, 0, sizeof(now));
+ base = ub_default_event_base(1, &secs, &now);
+ if(!base) fatal_exit("could not create ub_event base");
+ maindata->base = base;
+ sig_base = base;
+ if(sig_quit) {
+ ub_event_base_free(base);
+ free(maindata);
+ return;
+ }
+ ub_get_event_sys(base, &evnm, &evsys, &evmethod);
+ if(verbosity) log_info("%s %s uses %s method", evnm, evsys, evmethod);
+
+ setup_local_list(maindata, local_list);
+ setup_tcp_list(maindata, tcp_list);
+ setup_tls_list(maindata, tls_list, server_key, server_cert,
+ verifypem);
+ if(!tap_socket_list_addevs(maindata->acceptlist, base))
+ fatal_exit("could not setup accept events");
+ if(verbosity) log_info("start of service");
+
+ ub_event_base_dispatch(base);
+
+ if(verbosity) log_info("end of service");
+ sig_base = NULL;
+ tap_socket_list_delete(maindata->acceptlist);
+ ub_event_base_free(base);
+ free(maindata);
+}
+
+/** getopt global, in case header files fail to declare it. */
+extern int optind;
+/** getopt global, in case header files fail to declare it. */
+extern char* optarg;
+
+/** main program for streamtcp */
+int main(int argc, char** argv)
+{
+ int c;
+ int usessl = 0;
+ struct config_strlist_head local_list;
+ struct config_strlist_head tcp_list;
+ struct config_strlist_head tls_list;
+ char* server_key = NULL, *server_cert = NULL, *verifypem = NULL;
+#ifdef USE_WINSOCK
+ WSADATA wsa_data;
+ if(WSAStartup(MAKEWORD(2,2), &wsa_data) != 0) {
+ printf("WSAStartup failed\n");
+ return 1;
+ }
+#endif
+ if(signal(SIGINT, main_sigh) == SIG_ERR ||
+#ifdef SIGQUIT
+ signal(SIGQUIT, main_sigh) == SIG_ERR ||
+#endif
+#ifdef SIGHUP
+ signal(SIGHUP, main_sigh) == SIG_ERR ||
+#endif
+#ifdef SIGBREAK
+ signal(SIGBREAK, main_sigh) == SIG_ERR ||
+#endif
+ signal(SIGTERM, main_sigh) == SIG_ERR)
+ fatal_exit("could not bind to signal");
+ memset(&local_list, 0, sizeof(local_list));
+ memset(&tcp_list, 0, sizeof(tcp_list));
+ memset(&tls_list, 0, sizeof(tls_list));
+
+ /* lock debug start (if any) */
+ log_ident_set("unbound-dnstap-socket");
+ log_init(0, 0, 0);
+ checklock_start();
+
+#ifdef SIGPIPE
+ if(signal(SIGPIPE, SIG_IGN) == SIG_ERR) {
+ perror("could not install signal handler for SIGPIPE");
+ return 1;
+ }
+#endif
+
+ /* command line options */
+ while( (c=getopt(argc, argv, "hls:t:u:vx:y:z:")) != -1) {
+ switch(c) {
+ case 'u':
+ if(!cfg_strlist_append(&local_list,
+ strdup(optarg)))
+ fatal_exit("out of memory");
+ break;
+ case 's':
+ if(!cfg_strlist_append(&tcp_list,
+ strdup(optarg)))
+ fatal_exit("out of memory");
+ break;
+ case 't':
+ if(!cfg_strlist_append(&tls_list,
+ strdup(optarg)))
+ fatal_exit("out of memory");
+ usessl = 1;
+ break;
+ case 'x':
+ server_key = optarg;
+ usessl = 1;
+ break;
+ case 'y':
+ server_cert = optarg;
+ usessl = 1;
+ break;
+ case 'z':
+ verifypem = optarg;
+ usessl = 1;
+ break;
+ case 'l':
+ longformat = 1;
+ break;
+ case 'v':
+ verbosity++;
+ break;
+ case 'h':
+ case '?':
+ default:
+ usage(argv);
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ if(usessl) {
+#ifdef HAVE_SSL
+#if OPENSSL_VERSION_NUMBER < 0x10100000 || !defined(HAVE_OPENSSL_INIT_SSL)
+ ERR_load_SSL_strings();
+#endif
+#if OPENSSL_VERSION_NUMBER < 0x10100000 || !defined(HAVE_OPENSSL_INIT_CRYPTO)
+# ifndef S_SPLINT_S
+ OpenSSL_add_all_algorithms();
+# endif
+#else
+ OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS
+ | OPENSSL_INIT_ADD_ALL_DIGESTS
+ | OPENSSL_INIT_LOAD_CRYPTO_STRINGS, NULL);
+#endif
+#if OPENSSL_VERSION_NUMBER < 0x10100000 || !defined(HAVE_OPENSSL_INIT_SSL)
+ (void)SSL_library_init();
+#else
+ (void)OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS, NULL);
+#endif
+#endif /* HAVE_SSL */
+ }
+ setup_and_run(&local_list, &tcp_list, &tls_list, server_key,
+ server_cert, verifypem);
+ config_delstrlist(local_list.first);
+ config_delstrlist(tcp_list.first);
+ config_delstrlist(tls_list.first);
+
+ checklock_stop();
+#ifdef USE_WINSOCK
+ WSACleanup();
+#endif
+ return 0;
+}
+
+/***--- definitions to make fptr_wlist work. ---***/
+/* These are callbacks, similar to smallapp callbacks, except the debug
+ * tool callbacks are not in it */
+struct tube;
+struct query_info;
+#include "util/data/packed_rrset.h"
+
+void worker_handle_control_cmd(struct tube* ATTR_UNUSED(tube),
+ uint8_t* ATTR_UNUSED(buffer), size_t ATTR_UNUSED(len),
+ int ATTR_UNUSED(error), void* ATTR_UNUSED(arg))
+{
+ log_assert(0);
+}
+
+int worker_handle_request(struct comm_point* ATTR_UNUSED(c),
+ void* ATTR_UNUSED(arg), int ATTR_UNUSED(error),
+ struct comm_reply* ATTR_UNUSED(repinfo))
+{
+ log_assert(0);
+ return 0;
+}
+
+int worker_handle_reply(struct comm_point* ATTR_UNUSED(c),
+ void* ATTR_UNUSED(arg), int ATTR_UNUSED(error),
+ struct comm_reply* ATTR_UNUSED(reply_info))
+{
+ log_assert(0);
+ return 0;
+}
+
+int worker_handle_service_reply(struct comm_point* ATTR_UNUSED(c),
+ void* ATTR_UNUSED(arg), int ATTR_UNUSED(error),
+ struct comm_reply* ATTR_UNUSED(reply_info))
+{
+ log_assert(0);
+ return 0;
+}
+
+int remote_accept_callback(struct comm_point* ATTR_UNUSED(c),
+ void* ATTR_UNUSED(arg), int ATTR_UNUSED(error),
+ struct comm_reply* ATTR_UNUSED(repinfo))
+{
+ log_assert(0);
+ return 0;
+}
+
+int remote_control_callback(struct comm_point* ATTR_UNUSED(c),
+ void* ATTR_UNUSED(arg), int ATTR_UNUSED(error),
+ struct comm_reply* ATTR_UNUSED(repinfo))
+{
+ log_assert(0);
+ return 0;
+}
+
+void worker_sighandler(int ATTR_UNUSED(sig), void* ATTR_UNUSED(arg))
+{
+ log_assert(0);
+}
+
+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), int ATTR_UNUSED(ssl_upstream),
+ char* ATTR_UNUSED(tls_auth_name), struct module_qstate* ATTR_UNUSED(q))
+{
+ log_assert(0);
+ return 0;
+}
+
+#ifdef UB_ON_WINDOWS
+void
+worker_win_stop_cb(int ATTR_UNUSED(fd), short ATTR_UNUSED(ev), void*
+ ATTR_UNUSED(arg)) {
+ log_assert(0);
+}
+
+void
+wsvc_cron_cb(void* ATTR_UNUSED(arg))
+{
+ log_assert(0);
+}
+#endif /* UB_ON_WINDOWS */
+
+void
+worker_alloc_cleanup(void* ATTR_UNUSED(arg))
+{
+ log_assert(0);
+}
+
+struct outbound_entry* libworker_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), int ATTR_UNUSED(ssl_upstream),
+ char* ATTR_UNUSED(tls_auth_name), struct module_qstate* ATTR_UNUSED(q))
+{
+ log_assert(0);
+ return 0;
+}
+
+int libworker_handle_reply(struct comm_point* ATTR_UNUSED(c),
+ void* ATTR_UNUSED(arg), int ATTR_UNUSED(error),
+ struct comm_reply* ATTR_UNUSED(reply_info))
+{
+ log_assert(0);
+ return 0;
+}
+
+int libworker_handle_service_reply(struct comm_point* ATTR_UNUSED(c),
+ void* ATTR_UNUSED(arg), int ATTR_UNUSED(error),
+ struct comm_reply* ATTR_UNUSED(reply_info))
+{
+ log_assert(0);
+ return 0;
+}
+
+void libworker_handle_control_cmd(struct tube* ATTR_UNUSED(tube),
+ uint8_t* ATTR_UNUSED(buffer), size_t ATTR_UNUSED(len),
+ int ATTR_UNUSED(error), void* ATTR_UNUSED(arg))
+{
+ log_assert(0);
+}
+
+void libworker_fg_done_cb(void* ATTR_UNUSED(arg), int ATTR_UNUSED(rcode),
+ struct sldns_buffer* ATTR_UNUSED(buf), enum sec_status ATTR_UNUSED(s),
+ char* ATTR_UNUSED(why_bogus), int ATTR_UNUSED(was_ratelimited))
+{
+ log_assert(0);
+}
+
+void libworker_bg_done_cb(void* ATTR_UNUSED(arg), int ATTR_UNUSED(rcode),
+ struct sldns_buffer* ATTR_UNUSED(buf), enum sec_status ATTR_UNUSED(s),
+ char* ATTR_UNUSED(why_bogus), int ATTR_UNUSED(was_ratelimited))
+{
+ log_assert(0);
+}
+
+void libworker_event_done_cb(void* ATTR_UNUSED(arg), int ATTR_UNUSED(rcode),
+ struct sldns_buffer* ATTR_UNUSED(buf), enum sec_status ATTR_UNUSED(s),
+ char* ATTR_UNUSED(why_bogus), int ATTR_UNUSED(was_ratelimited))
+{
+ log_assert(0);
+}
+
+int context_query_cmp(const void* ATTR_UNUSED(a), const void* ATTR_UNUSED(b))
+{
+ log_assert(0);
+ return 0;
+}
+
+void worker_stat_timer_cb(void* ATTR_UNUSED(arg))
+{
+ log_assert(0);
+}
+
+void worker_probe_timer_cb(void* ATTR_UNUSED(arg))
+{
+ log_assert(0);
+}
+
+void worker_start_accept(void* ATTR_UNUSED(arg))
+{
+ log_assert(0);
+}
+
+void worker_stop_accept(void* ATTR_UNUSED(arg))
+{
+ log_assert(0);
+}
+
+/** keep track of lock id in lock-verify application */
+struct order_id {
+ /** the thread id that created it */
+ int thr;
+ /** the instance number of creation */
+ int instance;
+};
+
+int order_lock_cmp(const void* e1, const void* e2)
+{
+ const struct order_id* o1 = e1;
+ const struct order_id* o2 = e2;
+ if(o1->thr < o2->thr) return -1;
+ if(o1->thr > o2->thr) return 1;
+ if(o1->instance < o2->instance) return -1;
+ if(o1->instance > o2->instance) return 1;
+ return 0;
+}
+
+int
+codeline_cmp(const void* a, const void* b)
+{
+ return strcmp(a, b);
+}
+
+int replay_var_compare(const void* ATTR_UNUSED(a), const void* ATTR_UNUSED(b))
+{
+ log_assert(0);
+ return 0;
+}
+
+void remote_get_opt_ssl(char* ATTR_UNUSED(str), void* ATTR_UNUSED(arg))
+{
+ log_assert(0);
+}
diff --git a/contrib/unbound/doc/Changelog b/contrib/unbound/doc/Changelog
index 725b82ac64b4..3339e77b30c6 100644
--- a/contrib/unbound/doc/Changelog
+++ b/contrib/unbound/doc/Changelog
@@ -1,6 +1,330 @@
+20 July 2020: Wouter
+ - Fix streamtcp to print packet data to stdout. This makes the
+ stdout and stderr not mix together lines, when parsing its output.
+ - Fix contrib/fastrpz.patch to apply cleanly. It fixes for changes
+ due to added libdynmod, but it does not compile, it conflicts with
+ new rpz code.
+ - branch now named 1.11.0 and 1.11.0rc1 tag.
+
+17 July 2020: Wouter
+ - Fix libnettle compile for session ticket key callback function
+ changes.
+ - Fix lock dependency cycle in rpz zone config setup.
+
+17 July 2020: Ralph
+ - Merge PR #234 - Ensure proper alignment of cmsg buffers by Jérémie
+ Courrèges-Anglas.
+ - Fix PR #234 log_assert sizeof to use union buffer.
+
+16 July 2020: Wouter
+ - Fix check conf test for referencing installation paths.
+ - Fix unused variable warning for clang analyzer.
+
+16 July 2020: George
+ - Introduce 'include-toplevel:' configuration option.
+
+16 July 2020: Ralph
+ - Add bidirectional frame streams support.
+
+8 July 2020: Wouter
+ - Fix add missing DSA header, for compilation without deprecated
+ OpenSSL APIs.
+ - Fix to use SSL_CTX_set_tlsext_ticket_key_evp_cb in OpenSSL
+ 3.0.0-alpha4.
+ - Longer keys for the test set, this avoids weak crypto errors.
+
+7 July 2020: Wouter
+ - Fix #259: Fix unbound-checkconf does not check view existence.
+ unbound-checkconf checks access-control-view, access-control-tags,
+ access-control-tag-actions and access-control-tag-datas.
+ - Fix offset of error printout for access-control-tag-datas.
+ - Review fixes for checkconf #259 change.
+
+6 July 2020: Wouter
+ - run_vm cleanup better and removes trailing slash on single argument.
+
+29 June 2020: Wouter
+ - Move reply list clean for serve expired mesh callback to after
+ the reply is sent, so that script callbacks have reply_info.
+ - Also move reply list clean for mesh callbacks to the scrip callback
+ can see the reply_info.
+ - Fix for mesh accounting if the reply list already empty to begin
+ with.
+ - Fix for mesh accounting when rpz decides to drop a reply with a
+ tcp stream waiting for it.
+ - Review fix for number of detached states due to use of variable
+ after end of loop.
+ - Fix tcp req info drop due to size call into mesh accounting
+ removal of mesh state during mesh send reply.
+
+24 June 2020: Wouter
+ - iana portlist updated.
+ - doxygen file comments for dynlibmodule.
+
+17 June 2020: Wouter
+ - Fix default explanation in man page for qname-minimisation-strict.
+ - Fix display of event loop method with libev.
+
+8 June 2020: Wouter
+ - Mention tls name possible when tls is enabled for stub-addr in the
+ man page.
+
+27 May 2020: George
+ - Merge PR #241 by Robert Edmonds: contrib/libunbound.pc.in: Do not use
+ "Requires:".
+
+25 May 2020: George
+ - Update contrib/aaaa-filter-iterator.patch for the recent
+ generate_sub_request() change and to apply cleanly.
+
+21 May 2020: George
+ - Fix for integer overflow when printing RDF_TYPE_TIME.
+
+19 May 2020: Wouter
+ - CVE-2020-12662 Unbound can be tricked into amplifying an incoming
+ query into a large number of queries directed to a target.
+ - CVE-2020-12663 Malformed answers from upstream name servers can be
+ used to make Unbound unresponsive.
+ - Release 1.10.1 is 1.10.0 with fixes, code repository continues,
+ including those fixes, towards the next release. Configure has
+ version 1.10.2 version number in it.
+ - For PR #93: windows compile warnings removal
+ - windows compile warnings removal for ip dscp option code.
+ - For PR #93: unit test for dynlib module.
+
+18 May 2020: Wouter
+ - For PR #93: dynlibmod can handle reloads and deinit and inits again,
+ with dlclose and dlopen of the library again. Also for multiple
+ modules. Fix memory leak by not closing dlopened content. Fix
+ to allow one dynlibmod instance by unbound-checkconf.
+ - For PR #93: checkconf allows multiple dynlib in module-config, for
+ a couple cases.
+ - For PR #93: checkconf allows python dynlib in module-config, for
+ a couple cases.
+ - For PR #93: man page spelling reference fix.
+ - For PR #93: fix link of other executables for dynlibmod dependency.
+
+15 May 2020: Wouter
+ - Merge PR #93: Add dynamic library support.
+ - Fixed conflicts for PR #93 and make configure, yacc, lex.
+ - For PR #93: Fix warnings for dynlibmodule.
+
+15 May 2020: Ralph
+ - Cache ECS answers with longest scope of CNAME chain.
+
+22 April 2020: George
+ - Explicitly use 'rrset-roundrobin: no' for test cases.
+
+21 April 2020: Wouter
+ - Merge #225 from akhait: KSK-2010 has been revoked. It removes the
+ KSK-2010 from the default list in unbound-anchor, now that the
+ revocation period is over. KSK-2017 is the only trust anchor in
+ the shipped default now.
+
+21 April 2020: George
+ - Change default value for 'rrset-roundrobin' to yes.
+ - Fix tests for new rrset-roundrobin default.
+
+20 April 2020: Wouter
+ - Fix #222: --enable-rpath, fails to rpath python lib.
+ - Fix for count of reply states in the mesh.
+ - Remove unneeded was_mesh_reply check.
+
+17 April 2020: George
+ - Add SNI support on more TLS connections (fixes #193).
+ - Add SNI support to unbound-anchor.
+
+16 April 2020: George
+ - Add doxygen documentation for DSCP.
+
+16 April 2020: Wouter
+ - Fix help return code in unbound-control-setup script.
+ - Fix for posix shell syntax for trap in nsd-control-setup.
+ - Fix for posix shell syntax for trap in run_msg.sh test script.
+
+15 April 2020: George
+ - Fix #220: auth-zone section in config may lead to segfault.
+
+7 April 2020: Wouter
+ - Merge PR #214 from gearnode: unbound-control-setup recreate
+ certificates. With the -r option the certificates are created
+ again, without it, only the files that do not exist are created.
+
+6 April 2020: Ralph
+ - Keep track of number of timeouts. Use this counter to determine if
+ capsforid fallback should be started.
+
+6 April 2020: George
+ - More documentation for redis-expire-records option.
+
+1 April 2020: George
+ - Merge PR #206: Redis TTL, by Talkabout.
+
+30 March 2020: Wouter
+ - Merge PR #207: Clarify if-automatic listens on 0.0.0.0 and ::
+ - Merge PR #208: Fix uncached CLIENT_RESPONSE'es on stateful
+ transports.
+
+27 March 2020: Wouter
+ - Merge PR #203 from noloader: Update README-Travis.md with current
+ procedures.
+
+27 March 2020: Ralph
+ - Make unbound-control error returned on missing domain name more user
+ friendly.
+
+26 March 2020: Ralph
+ - Fix RPZ concurrency issue when using auth_zone_reload.
+
+25 March 2020: George
+ - Merge PR #201 from noloader: Fix OpenSSL cross-compaile warnings.
+ - Fix on #201.
+
+24 March 2020: Wouter
+ - Merge PR #200 from yarikk: add ip-dscp option to specify the DSCP
+ tag for outgoing packets.
+ - Fixes on #200.
+ - Travis fix for ios by omitting tools from install.
+
+23 March 2020: Wouter
+ - Fix compile on Solaris for unbound-checkconf.
+
+20 March 2020: George
+ - Merge PR #198 from fobser: Declare lz_enter_rr_into_zone() static, it's
+ only used in this file.
+
+20 March 2020: Wouter
+ - Merge PR #197 from fobser: Make log_ident_revert_to_default() a
+ proper prototype.
+
+19 March 2020: Ralph
+ - Merge PR#191: Update iOS testing on Travis, by Jeffrey Walton.
+ - Fix #158: open tls-session-ticket-keys as binary, for Windows. By
+ Daisuke HIGASHI.
+ - Merge PR#134, Allow the kernel to provide random source ports. By
+ Florian Obser.
+ - Log warning when using outgoing-port-permit and outgoing-port-avoid
+ while explicit port randomisation is disabled.
+ - Merge PR#194: Add libevent testing to Travis, by Jeffrey Walton.
+ - Fix .travis.yml error, missing 'env' option.
+
+16 March 2020: Wouter
+ - Fix #192: In the unbound-checkconf tool, the module config of
+ dns64 subnetcache respip validator iterator is whitelisted, it was
+ reported it seems to work.
+
+12 March 2020: Wouter
+ - Fix compile of test tools without protobuf.
+
+11 March 2020: Ralph
+ - Add check to make sure RPZ records are subdomains of configured
+ zone origin.
+
+11 March 2020: George
+ - Fix #189: mini_event.h:142:17: error: field 'ev_timeout' has incomplete
+ type, by noloader.
+ - Changelog entry for (Fix #189, Merge PR #190).
+
+11 March 2020: Wouter
+ - Fix #188: unbound-control.c:882:6: error: 'execlp' is
+ unavailable: not available on tvOS.
+
+6 March 2020: George
+ - Merge PR #186, fix #183: Fix unrecognized 'echo -n' option on OS X, by
+ noloader
+
+5 March 2020: Wouter
+ - Fix PR #182 from noloader: Add iOS testing to Travis.
+
+4 March 2020: Ralph
+ - Update README-Travis.md (from PR #179), by Jeffrey Walton.
+
+4 March 2020: George
+ - Merge PR #181 from noloader: Fix OpenSSL -pie warning on Android.
+
+4 March 2020: Wouter
+ - Merge PR #180 from noloader: Avoid calling exit in Travis script.
+
+3 March 2020: George
+ - Upgrade config.guess(2020-01-01) and config.sub(2020-01-01).
+
+2 March 2020: Ralph
+ - Fix #175, Merge PR #176: fix link error when OpenSSL is configured
+ with no-engine, thanks noloader.
+
+2 March 2020: George
+ - Fix compiler warning in dns64/dns64.c
+ - Merge PR #174: Add Android to Travis testing, by noloader.
+ - Move android build scripts to contrib/ and allow android tests to fail.
+
+2 March 2020: Wouter
+ - Fix #177: dnstap does not build on macOS.
+
+28 February 2020: Ralph
+ - Merge PR #172: Add IBM s390x arch for testing, by noloader.
+
+28 February 2020: Wouter
+ - Merge PR #173: updated makedist.sh for config.guess and
+ config.sub and sha256 digest for gpg, by noloader.
+ - Merge PR #164: Framestreams, this branch implements dnstap
+ unidirectional connectivity in unbound. This has a number of
+ new features.
+
+ The dependency on libfstrm is removed. The fstrm protocol code
+ resides in dnstap/dnstap_fstrm.h and dnstap/dnstap_fstrm.c. This
+ contains a brief definition of what unbound needs.
+
+ The make unbound-dnstap-socket builds a debug tool,
+ unbound-dnstap-socket. It can listen, accept multiple DNSTAP
+ streams and print information. Commandline options control it.
+
+ Unbound can reconnect if the unix domain socket file socket is
+ closed. This uses exponential backoff after which it uses a
+ one second timer to throttle cpu down. There is also support
+ to use TCP and TLS for connecting to the log server. There
+ are new config options to turn them on, in the dnstap section
+ in the man page and example config file. dnstap-ip with IP
+ address of server for TCP or TLS use. dnstap-tls to turn
+ on TLS. And dnstap-tls-server-name, dnstap-tls-cert-bundle,
+ dnstap-tls-client-key-file and dnstap-tls-client-cert-file
+ to configure the certificates for server authentication and
+ client authentication, or leave at "" to not use that.
+
+27 February 2020: George
+ - Merge PR #171: Add additional compilers and platforms to Travis
+ testing, by noloader.
+
+27 February 2020: Wouter
+ - Fix #169: Fix warning for daemon/remote.c output may be truncated
+ from snprintf.
+ - Fix #170: Fix gcc undefined sanitizer signed integer overflow
+ warning in signature expiry RFC1982 serial number arithmetic.
+ - Fix more undefined sanitizer issues, in respip copy_rrset null
+ dname, and in the client_info_compare routine for null memcmp.
+
+26 February 2020: Wouter
+ - iana portlist updated.
+
+25 February 2020: Wouter
+ - Fix #165: Add prefer-ip4: yesno config option to prefer ipv4 for
+ using ipv4 filters, because the hosts ip6 netblock /64 is not owned
+ by one operator, and thus reputation is shared.
+
+24 February 2020: George
+ - Merge PR #166: Fix typo in unbound.service.in, by glitsj16.
+
20 February 2020: Wouter
- Updated contrib/unbound_smf23.tar.gz with Solaris SMF service for
Unbound from Yuri Voinov.
+ - master branch has 1.10.1 version.
+
+18 February 2020: Wouter
+ - protect X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS with ifdef for
+ different openssl versions.
+
+17 February 2020: Wouter
+ - changelog point where the tag for 1.10.0rc2 release is. And with
+ the unbound_smf23 commit added to it, that is the 1.10.0 release.
17 February 2020: Ralph
- Add respip to supported module-config options in unbound-checkconf.
diff --git a/contrib/unbound/doc/README b/contrib/unbound/doc/README
index 6bd34bbed956..6bd9a4c5fdae 100644
--- a/contrib/unbound/doc/README
+++ b/contrib/unbound/doc/README
@@ -1,4 +1,4 @@
-README for Unbound 1.10.1
+README for Unbound 1.11.0
Copyright 2007 NLnet Labs
http://unbound.net
diff --git a/contrib/unbound/doc/example.conf.in b/contrib/unbound/doc/example.conf.in
index d9fe9c60b3d0..4f6411033e69 100644
--- a/contrib/unbound/doc/example.conf.in
+++ b/contrib/unbound/doc/example.conf.in
@@ -1,13 +1,17 @@
#
# Example configuration file.
#
-# See unbound.conf(5) man page, version 1.10.1.
+# See unbound.conf(5) man page, version 1.11.0.
#
# this is a comment.
-#Use this to include other text into the file.
+# Use this anywhere in the file to include other text into this file.
#include: "otherfile.conf"
+# Use this anywhere in the file to include other text, that explicitly starts a
+# clause, into this file. Text after this directive needs to start a clause.
+#include-toplevel: "otherfile.conf"
+
# The server clause sets the main parameters.
server:
# whitespace is not necessary, but looks cleaner.
@@ -70,6 +74,9 @@ server:
# Set this to yes to prefer ipv6 upstream servers over ipv4.
# prefer-ip6: no
+ # Prefer ipv4 upstream servers, even if ipv6 is available.
+ # prefer-ip4: no
+
# number of ports to allocate per thread, determines the size of the
# port range that can be open simultaneously. About double the
# num-queries-per-thread, or, use as many as the OS will allow you.
@@ -116,6 +123,11 @@ server:
# Linux only. On Linux you also have ip-transparent that is similar.
# ip-freebind: no
+ # the value of the Differentiated Services Codepoint (DSCP)
+ # in the differentiated services field (DS) of the outgoing
+ # IP packets
+ # ip-dscp: 0
+
# EDNS reassembly buffer to advertise to UDP peers (the actual buffer
# is set with msg-buffer-size). 1472 can solve fragmentation (timeouts)
# edns-buffer-size: 4096
@@ -465,7 +477,7 @@ server:
# deny-any: no
# if yes, Unbound rotates RRSet order in response.
- # rrset-roundrobin: no
+ # rrset-roundrobin: yes
# if yes, Unbound doesn't insert authority/additional sections
# into response messages when those sections are not required.
@@ -738,6 +750,10 @@ server:
# cipher setting for TLSv1.3
# tls-ciphersuites: "TLS_AES_128_GCM_SHA256:TLS_AES_128_CCM_8_SHA256:TLS_AES_128_CCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256"
+ # Use the SNI extension for TLS connections. Default is yes.
+ # Changing the value requires a reload.
+ # tls-use-sni: yes
+
# Add the secret file for TLS Session Ticket.
# Secret file must be 80 bytes of random data.
# First key use to encrypt and decrypt TLS session tickets.
@@ -847,6 +863,17 @@ python:
# Script file to load
# python-script: "@UNBOUND_SHARE_DIR@/ubmodule-tst.py"
+# Dynamic library config section. To enable:
+# o use --with-dynlibmodule to configure before compiling.
+# o list dynlib in the module-config string (above) to enable.
+# It can be placed anywhere, the dynlib module is only a very thin wrapper
+# to load modules dynamically.
+# o and give a dynlib-file to run. If more than one dynlib entry is listed in
+# the module-config then you need one dynlib-file per instance.
+dynlib:
+ # Script file to load
+ # dynlib-file: "@UNBOUND_SHARE_DIR@/dynlib.so"
+
# Remote control config section.
remote-control:
# Enable remote control with unbound-control(8) here.
@@ -1005,10 +1032,12 @@ remote-control:
# redis-server-port: 6379
# # timeout (in ms) for communication with the redis server
# redis-timeout: 100
+# # set timeout on redis records based on DNS response TTL
+# redis-expire-records: no
# IPSet
# Add specify domain into set via ipset.
-# Note: To enable ipset needs run unbound as root user.
+# Note: To enable ipset unbound needs to run as root user.
# ipset:
# # set name for ip v4 addresses
# name-v4: "list-v4"
@@ -1016,6 +1045,40 @@ remote-control:
# name-v6: "list-v6"
#
+# Dnstap logging support, if compiled in. To enable, set the dnstap-enable
+# to yes and also some of dnstap-log-..-messages to yes. And select an
+# upstream log destination, by socket path, TCP or TLS destination.
+# dnstap:
+# dnstap-enable: no
+# # if set to yes frame streams will be used in bidirectional mode
+# dnstap-bidirectional: yes
+# dnstap-socket-path: "@DNSTAP_SOCKET_PATH@"
+# # if "" use the unix socket in dnstap-socket-path, otherwise,
+# # set it to "IPaddress[@port]" of the destination.
+# dnstap-ip: ""
+# # if set to yes if you want to use TLS to dnstap-ip, no for TCP.
+# dnstap-tls: yes
+# # name for authenticating the upstream server. or "" disabled.
+# dnstap-tls-server-name: ""
+# # if "", it uses the cert bundle from the main unbound config.
+# dnstap-tls-cert-bundle: ""
+# # key file for client authentication, or "" disabled.
+# dnstap-tls-client-key-file: ""
+# # cert file for client authentication, or "" disabled.
+# dnstap-tls-client-cert-file: ""
+# dnstap-send-identity: no
+# dnstap-send-version: no
+# # if "" it uses the hostname.
+# dnstap-identity: ""
+# # if "" it uses the package version.
+# dnstap-version: ""
+# dnstap-log-resolver-query-messages: no
+# dnstap-log-resolver-response-messages: no
+# dnstap-log-client-query-messages: no
+# dnstap-log-client-response-messages: no
+# dnstap-log-forwarder-query-messages: no
+# 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:
diff --git a/contrib/unbound/doc/libunbound.3.in b/contrib/unbound/doc/libunbound.3.in
index 69c201116246..10bda1614b26 100644
--- a/contrib/unbound/doc/libunbound.3.in
+++ b/contrib/unbound/doc/libunbound.3.in
@@ -1,4 +1,4 @@
-.TH "libunbound" "3" "May 19, 2020" "NLnet Labs" "unbound 1.10.1"
+.TH "libunbound" "3" "Jul 27, 2020" "NLnet Labs" "unbound 1.11.0"
.\"
.\" 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.10.1 functions.
+\- Unbound DNS validating resolver 1.11.0 functions.
.SH "SYNOPSIS"
.B #include <unbound.h>
.LP
diff --git a/contrib/unbound/doc/unbound-anchor.8.in b/contrib/unbound/doc/unbound-anchor.8.in
index 680066a75072..1c7799ca11d8 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" "May 19, 2020" "NLnet Labs" "unbound 1.10.1"
+.TH "unbound-anchor" "8" "Jul 27, 2020" "NLnet Labs" "unbound 1.11.0"
.\"
.\" unbound-anchor.8 -- unbound anchor maintenance utility manual
.\"
@@ -69,6 +69,9 @@ The server name, it connects to https://name. Specify without https:// prefix.
The default is "data.iana.org". It connects to the port specified with \-P.
You can pass an IPv4 address or IPv6 address (no brackets) if you want.
.TP
+.B \-S
+Do not use SNI for the HTTPS connection. Default is to use SNI.
+.TP
.B \-b \fIaddress
The source address to bind to for domain resolution and contacting the server
on https. May be either an IPv4 address or IPv6 address (no brackets).
diff --git a/contrib/unbound/doc/unbound-checkconf.8.in b/contrib/unbound/doc/unbound-checkconf.8.in
index fd972f9c06aa..025795462bb6 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" "May 19, 2020" "NLnet Labs" "unbound 1.10.1"
+.TH "unbound-checkconf" "8" "Jul 27, 2020" "NLnet Labs" "unbound 1.11.0"
.\"
.\" 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 3747b1fa670e..154450303366 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" "May 19, 2020" "NLnet Labs" "unbound 1.10.1"
+.TH "unbound-control" "8" "Jul 27, 2020" "NLnet Labs" "unbound 1.11.0"
.\"
.\" unbound-control.8 -- unbound remote control manual
.\"
diff --git a/contrib/unbound/doc/unbound-host.1.in b/contrib/unbound/doc/unbound-host.1.in
index e2dcc4a9b0ee..cae708d66b12 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" "May 19, 2020" "NLnet Labs" "unbound 1.10.1"
+.TH "unbound\-host" "1" "Jul 27, 2020" "NLnet Labs" "unbound 1.11.0"
.\"
.\" unbound-host.1 -- unbound DNS lookup utility
.\"
diff --git a/contrib/unbound/doc/unbound.8.in b/contrib/unbound/doc/unbound.8.in
index 74c900ebcc0d..fcdb3d833406 100644
--- a/contrib/unbound/doc/unbound.8.in
+++ b/contrib/unbound/doc/unbound.8.in
@@ -1,4 +1,4 @@
-.TH "unbound" "8" "May 19, 2020" "NLnet Labs" "unbound 1.10.1"
+.TH "unbound" "8" "Jul 27, 2020" "NLnet Labs" "unbound 1.11.0"
.\"
.\" unbound.8 -- unbound manual
.\"
@@ -9,7 +9,7 @@
.\"
.SH "NAME"
.B unbound
-\- Unbound DNS validating resolver 1.10.1.
+\- Unbound DNS validating resolver 1.11.0.
.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 ffdbf8caa65b..04dca3561ea2 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" "May 19, 2020" "NLnet Labs" "unbound 1.10.1"
+.TH "unbound.conf" "5" "Jul 27, 2020" "NLnet Labs" "unbound 1.11.0"
.\"
.\" unbound.conf.5 -- unbound.conf manual
.\"
@@ -77,6 +77,12 @@ for the included files works, relative pathnames for the included names work
if the directory where the daemon is started equals its chroot/working
directory or is specified before the include statement with directory: dir.
Wildcards can be used to include multiple files, see \fIglob\fR(7).
+.P
+For a more structural include option, the
+.B include\-toplevel:
+directive can be used. This closes whatever clause is currently active (if any)
+and forces the use of clauses in the included files and right after this
+directive.
.SS "Server Options"
These options are part of the
.B server:
@@ -126,9 +132,12 @@ interface and port number), if not specified the default port (from
Same as interface: (for ease of compatibility with nsd.conf).
.TP
.B interface\-automatic: \fI<yes or no>
-Detect source interface on UDP queries and copy them to replies. This
-feature is experimental, and needs support in your OS for particular socket
-options. Default value is no.
+Listen on all addresses on all (current and future) interfaces, detect the
+source interface on UDP queries and copy them to replies. This is a lot like
+ip\-transparent, but this option services all interfaces whilst with
+ip\-transparent you can select which (future) interfaces unbound provides
+service on. This feature is experimental, and needs support in your OS for
+particular socket options. Default value is no.
.TP
.B outgoing\-interface: \fI<ip address or ip6 netblock>
Interface to use to connect to the network. This interface is used to send
@@ -323,6 +332,12 @@ IP addresses that are nonlocal or do not exist, like when the network
interface or IP address is down. Exists only on Linux, where the similar
ip\-transparent option is also available.
.TP
+.B ip-dscp: \fI<number>
+The value of the Differentiated Services Codepoint (DSCP) in the
+differentiated services field (DS) of the outgoing IP packet headers.
+The field replaces the outdated IPv4 Type-Of-Service field and the
+IPV6 traffic class field.
+.TP
.B rrset\-cache\-size: \fI<number>
Number of bytes size of the RRset cache. Default is 4 megabytes.
A plain number is in bytes, append 'k', 'm' or 'g' for kilobytes, megabytes
@@ -381,6 +396,13 @@ IPv6 to the internet nameservers. With this option you can disable the
ipv6 transport for sending DNS traffic, it does not impact the contents of
the DNS traffic, which may have ip4 and ip6 addresses in it.
.TP
+.B prefer\-ip4: \fI<yes or no>
+If enabled, prefer IPv4 transport for sending DNS queries to internet
+nameservers. Default is no. Useful if the IPv6 netblock the server has,
+the entire /64 of that is not owned by one operator and the reputation of
+the netblock /64 is an issue, using IPv4 then uses the IPv4 filters that
+the upstream servers have.
+.TP
.B prefer\-ip6: \fI<yes or no>
If enabled, prefer IPv6 transport for sending DNS queries to internet
nameservers. Default is no.
@@ -530,6 +552,11 @@ and that is the default.
Set the list of ciphersuites to allow when serving TLS. This is for newer
TLS 1.3 connections. Use "" for defaults, and that is the default.
.TP
+.B tls\-use\-sni: \fI<yes or no>
+Enable or disable sending the SNI extension on TLS connections.
+Default is yes.
+Changing the value requires a reload.
+.TP
.B use\-systemd: \fI<yes or no>
Enable or disable systemd socket activation.
Default is no.
@@ -843,7 +870,7 @@ NXDOMAIN from a DNSSEC signed zone. Default is yes.
QNAME minimisation in strict mode. Do not fall-back to sending full QNAME to
potentially broken nameservers. A lot of domains will not be resolvable when
this option in enabled. Only use if you know what you are doing.
-This option only has effect when qname-minimisation is enabled. Default is off.
+This option only has effect when qname-minimisation is enabled. Default is no.
.TP
.B aggressive\-nsec: \fI<yes or no>
Aggressive NSEC uses the DNSSEC NSEC chain to synthesize NXDOMAIN
@@ -911,7 +938,7 @@ are none.
.TP
.B rrset\-roundrobin: \fI<yes or no>
If yes, Unbound rotates RRSet order in response (the random number is taken
-from the query ID, for speed and thread safety). Default is no.
+from the query ID, for speed and thread safety). Default is yes.
.TP
.B minimal-responses: \fI<yes or no>
If yes, Unbound doesn't insert authority/additional sections into response
@@ -942,7 +969,9 @@ EDNS client subnet support the default is "subnetcache validator iterator".
Most modules that need to be listed here have to be listed at the beginning
of the line. The cachedb module has to be listed just before the iterator.
The python module can be listed in different places, it then processes the
-output of the module it is just before.
+output of the module it is just before. The dynlib module can be listed pretty
+much anywhere, it is only a very thin wrapper that allows dynamic libraries to
+run in its place.
.TP
.B trust\-anchor\-file: \fI<filename>
File with trusted keys for validation. Both DS and DNSKEY entries can appear
@@ -1591,6 +1620,9 @@ Name of stub zone nameserver. Is itself resolved before it is used.
.B stub\-addr: \fI<IP address>
IP address of stub zone nameserver. Can be IP 4 or IP 6.
To use a nondefault port for DNS communication append '@' with the port number.
+If tls is enabled, then you can append a '#' and a name, then it'll check
+the tls authentication certificates with that name. If you combine
+the '@' and '#', the '@' comes first.
.TP
.B stub\-prime: \fI<yes or no>
This option is by default no. If enabled it performs NS set priming,
@@ -1809,6 +1841,24 @@ directory.
.B python\-script: \fI<python file>\fR
The script file to load. Repeat this option for every python module instance
added to the \fBmodule\-config:\fR option.
+.SS "Dynamic Library Module Options"
+.LP
+The
+.B dynlib:
+clause gives the settings for the \fIdynlib\fR module. This module is only
+a very small wrapper that allows dynamic modules to be loaded on runtime
+instead of being compiled into the application. To enable the dynlib module it
+has to be compiled into the daemon, and the word "dynlib" has to be put in the
+\fBmodule\-config:\fR option. Multiple instances of dynamic libraries are
+supported by adding the word "dynlib" more than once.
+.LP
+The \fBdynlib\-file:\fR path should be specified as an absolute path relative
+to the new path set by \fBchroot:\fR option, or as a relative path to the
+working directory.
+.TP
+.B dynlib\-file: \fI<dynlib file>\fR
+The dynamic library file to load. Repeat this option for every dynlib module
+instance added to the \fBmodule\-config:\fR option.
.SS "DNS64 Module Options"
.LP
The dns64 module must be configured in the \fBmodule\-config:\fR "dns64
@@ -2060,6 +2110,11 @@ even if some data have expired in terms of DNS TTL or the Redis server has
cached too much data;
if necessary the Redis server must be configured to limit the cache size,
preferably with some kind of least-recently-used eviction policy.
+Additionaly, the \fBredis\-expire\-records\fR option can be used in order to
+set the relative DNS TTL of the message as timeout to the Redis records; keep
+in mind that some additional memory is used per key and that the expire
+information is stored as absolute Unix timestamps in Redis (computer time must
+be stable).
This backend uses synchronous communication with the Redis server
based on the assumption that the communication is stable and sufficiently
fast.
@@ -2114,6 +2169,94 @@ If this timeout expires Unbound closes the connection, treats it as
if the Redis server does not have the requested data, and will try to
re-establish a new connection later.
This option defaults to 100 milliseconds.
+.TP
+.B redis-expire-records: \fI<yes or no>
+If Redis record expiration is enabled. If yes, unbound sets timeout for Redis
+records so that Redis can evict keys that have expired automatically. If
+unbound is configured with \fBserve-expired\fR and \fBserve-expired-ttl\fR is 0,
+this option is internally reverted to "no". Redis SETEX support is required
+for this option (Redis >= 2.0.0).
+This option defaults to no.
+.SS DNSTAP Logging Options
+DNSTAP support, when compiled in, is enabled in the \fBdnstap:\fR section.
+This starts an extra thread (when compiled with threading) that writes
+the log information to the destination. If unbound is compiled without
+threading it does not spawn a thread, but connects per-process to the
+destination.
+.TP
+.B dnstap-enable: \fI<yes or no>
+If dnstap is enabled. Default no. If yes, it connects to the dnstap server
+and if any of the dnstap-log-..-messages options is enabled it sends logs
+for those messages to the server.
+.TP
+.B dnstap-bidirectional: \fI<yes or no>
+Use frame streams in bidirectional mode to transfer DNSTAP messages. Default is
+yes.
+.TP
+.B dnstap-socket-path: \fI<file name>
+Sets the unix socket file name for connecting to the server that is
+listening on that socket. Default is "@DNSTAP_SOCKET_PATH@".
+.TP
+.B dnstap-ip: \fI<IPaddress[@port]>
+If "", the unix socket is used, if set with an IP address (IPv4 or IPv6)
+that address is used to connect to the server.
+.TP
+.B dnstap-tls: \fI<yes or no>
+Set this to use TLS to connect to the server specified in \fBdnstap-ip\fR.
+The default is yes. If set to no, TCP is used to connect to the server.
+.TP
+.B dnstap-tls-server-name: \fI<name of TLS authentication>
+The TLS server name to authenticate the server with. Used when \fBdnstap-tls\fR is enabled. If "" it is ignored, default "".
+.TP
+.B dnstap-tls-cert-bundle: \fI<file name of cert bundle>
+The pem file with certs to verify the TLS server certificate. If "" the
+server default cert bundle is used, or the windows cert bundle on windows.
+Default is "".
+.TP
+.B dnstap-tls-client-key-file: \fI<file name>
+The client key file for TLS client authentication. If "" client
+authentication is not used. Default is "".
+.TP
+.B dnstap-tls-client-cert-file: \fI<file name>
+The client cert file for TLS client authentication. Default is "".
+.TP
+.B dnstap-send-identity: \fI<yes or no>
+If enabled, the server identity is included in the log messages.
+Default is no.
+.TP
+.B dnstap-send-version: \fI<yes or no>
+If enabled, the server version if included in the log messages.
+Default is no.
+.TP
+.B dnstap-identity: \fI<string>
+The identity to send with messages, if "" the hostname is used.
+Default is "".
+.TP
+.B dnstap-version: \fI<string>
+The version to send with messages, if "" the package version is used.
+Default is "".
+.TP
+.B dnstap-log-resolver-query-messages: \fI<yes or no>
+Enable to log resolver query messages. Default is no.
+These are messages from unbound to upstream servers.
+.TP
+.B dnstap-log-resolver-response-messages: \fI<yes or no>
+Enable to log resolver response messages. Default is no.
+These are replies from upstream servers to unbound.
+.TP
+.B dnstap-log-client-query-messages: \fI<yes or no>
+Enable to log client query messages. Default is no.
+These are client queries to unbound.
+.TP
+.B dnstap-log-client-response-messages: \fI<yes or no>
+Enable to log client response messages. Default is no.
+These are responses from unbound to clients.
+.TP
+.B dnstap-log-forwarder-query-messages: \fI<yes or no>
+Enable to log forwarder query messages. Default is no.
+.TP
+.B dnstap-log-forwarder-response-messages: \fI<yes or no>
+Enable to log forwarder response messages. Default is no.
.SS Response Policy Zone Options
.LP
Response Policy Zones are configured with \fBrpz:\fR, and each one must have a
diff --git a/contrib/unbound/dynlibmod/dynlibmod.c b/contrib/unbound/dynlibmod/dynlibmod.c
new file mode 100644
index 000000000000..f9751d8c6f73
--- /dev/null
+++ b/contrib/unbound/dynlibmod/dynlibmod.c
@@ -0,0 +1,301 @@
+/**
+ * \file
+ * This file contains the dynamic library module for Unbound.
+ * This loads a dynamic library (.dll, .so) and calls that for the
+ * module actions.
+ */
+#include "config.h"
+#include "util/module.h"
+#include "util/config_file.h"
+#include "dynlibmod/dynlibmod.h"
+
+#if HAVE_WINDOWS_H
+#include <windows.h>
+#define __DYNMOD HMODULE
+#define __DYNSYM FARPROC
+#define __LOADSYM GetProcAddress
+void log_dlerror() {
+ DWORD dwLastError = GetLastError();
+ LPSTR MessageBuffer;
+ DWORD dwBufferLength;
+ DWORD dwFormatFlags = FORMAT_MESSAGE_ALLOCATE_BUFFER |
+ FORMAT_MESSAGE_IGNORE_INSERTS |
+ FORMAT_MESSAGE_FROM_SYSTEM ;
+ if((dwBufferLength = FormatMessageA(
+ dwFormatFlags,
+ NULL, // module to get message from (NULL == system)
+ dwLastError,
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // default language
+ (LPSTR) &MessageBuffer,
+ 0,
+ NULL
+ )))
+ {
+ log_err("dynlibmod: %s (%ld)", MessageBuffer, dwLastError);
+ LocalFree(MessageBuffer);
+ }
+
+}
+
+HMODULE open_library(const char* fname) {
+ return LoadLibrary(fname);
+}
+
+void close_library(const char* fname, __DYNMOD handle) {
+ (void)fname;
+ (void)handle;
+}
+#else
+#include <dlfcn.h>
+#define __DYNMOD void*
+#define __DYNSYM void*
+#define __LOADSYM dlsym
+void log_dlerror() {
+ log_err("dynlibmod: %s", dlerror());
+}
+
+void* open_library(const char* fname) {
+ return dlopen(fname, RTLD_LAZY | RTLD_GLOBAL);
+}
+
+void close_library(const char* fname, __DYNMOD handle) {
+ if(!handle) return;
+ if(dlclose(handle) != 0) {
+ log_err("dlclose %s: %s", fname, strerror(errno));
+ }
+}
+#endif
+
+/** module counter for multiple dynlib modules */
+static int dynlib_mod_count = 0;
+
+/** dynlib module init */
+int dynlibmod_init(struct module_env* env, int id) {
+ int dynlib_mod_idx = dynlib_mod_count++;
+ struct config_strlist* cfg_item = env->cfg->dynlib_file;
+ struct dynlibmod_env* de = (struct dynlibmod_env*)calloc(1, sizeof(struct dynlibmod_env));
+ __DYNMOD dynamic_library;
+ if (!de)
+ {
+ log_err("dynlibmod[%d]: malloc failure", dynlib_mod_idx);
+ return 0;
+ }
+
+ env->modinfo[id] = (void*) de;
+
+ de->fname = NULL;
+ for(int i = dynlib_mod_idx;
+ i != 0 && cfg_item != NULL;
+ i--, cfg_item = cfg_item->next) {}
+
+ if (cfg_item == NULL || cfg_item->str == NULL || cfg_item->str[0] == 0) {
+ log_err("dynlibmod[%d]: no dynamic library given.", dynlib_mod_idx);
+ return 0;
+ } else {
+ de->fname = cfg_item->str;
+ }
+ verbose(VERB_ALGO, "dynlibmod[%d]: Trying to load library %s", dynlib_mod_idx, de->fname);
+ dynamic_library = open_library(de->fname);
+ de->dynamic_library = (void*)dynamic_library;
+ if (dynamic_library == NULL) {
+ log_dlerror();
+ log_err("dynlibmod[%d]: unable to load dynamic library \"%s\".", dynlib_mod_idx, de->fname);
+ return 0;
+ } else {
+ __DYNSYM initializer;
+ __DYNSYM deinitializer;
+ __DYNSYM operate;
+ __DYNSYM inform;
+ __DYNSYM clear;
+ __DYNSYM get_mem;
+ initializer = __LOADSYM(dynamic_library,"init");
+ if (initializer == NULL) {
+ log_dlerror();
+ log_err("dynlibmod[%d]: unable to load init procedure from dynamic library \"%s\".", dynlib_mod_idx, de->fname);
+ return 0;
+ } else {
+ de->func_init = (func_init_t)(void*)initializer;
+ }
+ deinitializer = __LOADSYM(dynamic_library,"deinit");
+ if (deinitializer == NULL) {
+ log_dlerror();
+ log_err("dynlibmod[%d]: unable to load deinit procedure from dynamic library \"%s\".", dynlib_mod_idx, de->fname);
+ return 0;
+ } else {
+ de->func_deinit = (func_deinit_t)(void*)deinitializer;
+ }
+ operate = __LOADSYM(dynamic_library,"operate");
+ if (operate == NULL) {
+ log_dlerror();
+ log_err("dynlibmod[%d]: unable to load operate procedure from dynamic library \"%s\".", dynlib_mod_idx, de->fname);
+ return 0;
+ } else {
+ de->func_operate = (func_operate_t)(void*)operate;
+ }
+ inform = __LOADSYM(dynamic_library,"inform_super");
+ if (inform == NULL) {
+ log_dlerror();
+ log_err("dynlibmod[%d]: unable to load inform_super procedure from dynamic library \"%s\".", dynlib_mod_idx, de->fname);
+ return 0;
+ } else {
+ de->func_inform = (func_inform_t)(void*)inform;
+ }
+ clear = __LOADSYM(dynamic_library,"clear");
+ if (clear == NULL) {
+ log_dlerror();
+ log_err("dynlibmod[%d]: unable to load clear procedure from dynamic library \"%s\".", dynlib_mod_idx, de->fname);
+ return 0;
+ } else {
+ de->func_clear = (func_clear_t)(void*)clear;
+ }
+ get_mem = __LOADSYM(dynamic_library,"get_mem");
+ if (get_mem == NULL) {
+ log_dlerror();
+ log_err("dynlibmod[%d]: unable to load get_mem procedure from dynamic library \"%s\".", dynlib_mod_idx, de->fname);
+ return 0;
+ } else {
+ de->func_get_mem = (func_get_mem_t)(void*)get_mem;
+ }
+ }
+ de->inplace_cb_delete_wrapped = &inplace_cb_delete_wrapped;
+ de->inplace_cb_register_wrapped = &inplace_cb_register_wrapped;
+ return de->func_init(env, id);
+}
+
+/** dynlib module deinit */
+void dynlibmod_deinit(struct module_env* env, int id) {
+ struct dynlibmod_env* de = env->modinfo[id];
+ if(de == NULL)
+ return;
+ de->func_deinit(env, id);
+ close_library(de->fname, (__DYNMOD)de->dynamic_library);
+ dynlib_mod_count--;
+ de->fname = NULL;
+ free(de);
+}
+
+/** dynlib module operate on a query */
+void dynlibmod_operate(struct module_qstate* qstate, enum module_ev event,
+ int id, struct outbound_entry* outbound) {
+ struct dynlibmod_env* de = qstate->env->modinfo[id];
+
+ de->func_operate(qstate, event, id, outbound);
+}
+
+/** dynlib module */
+void dynlibmod_inform_super(struct module_qstate* qstate, int id,
+ struct module_qstate* super) {
+ struct dynlibmod_env* de = qstate->env->modinfo[id];
+
+ de->func_inform(qstate, id, super);
+}
+
+/** dynlib module cleanup query state */
+void dynlibmod_clear(struct module_qstate* qstate, int id) {
+ struct dynlibmod_env* de = qstate->env->modinfo[id];
+
+ de->func_clear(qstate, id);
+}
+
+/** dynlib module alloc size routine */
+size_t dynlibmod_get_mem(struct module_env* env, int id) {
+ struct dynlibmod_env* de = (struct dynlibmod_env*)env->modinfo[id];
+ size_t size;
+ verbose(VERB_ALGO, "dynlibmod: get_mem, id: %d, de:%p", id, de);
+ if(!de)
+ return 0;
+
+ size = de->func_get_mem(env, id);
+ return size + sizeof(*de);
+}
+
+int dynlib_inplace_cb_reply_generic(struct query_info* qinfo,
+ struct module_qstate* qstate, struct reply_info* rep, int rcode,
+ struct edns_data* edns, struct edns_option** opt_list_out,
+ struct comm_reply* repinfo, struct regional* region, int id,
+ void* callback) {
+ struct cb_pair* cb_pair = (struct cb_pair*) callback;
+ return ((inplace_cb_reply_func_type*) cb_pair->cb)(qinfo, qstate, rep, rcode, edns, opt_list_out, repinfo, region, id, cb_pair->cb_arg);
+}
+
+int dynlib_inplace_cb_query_generic(struct query_info* qinfo, uint16_t flags,
+ struct module_qstate* qstate, struct sockaddr_storage* addr,
+ socklen_t addrlen, uint8_t* zone, size_t zonelen, struct regional* region,
+ int id, void* callback) {
+ struct cb_pair* cb_pair = (struct cb_pair*) callback;
+ return ((inplace_cb_query_func_type*) cb_pair->cb)(qinfo, flags, qstate, addr, addrlen, zone, zonelen, region, id, cb_pair->cb_arg);
+}
+
+int dynlib_inplace_cb_edns_back_parsed(struct module_qstate* qstate,
+ int id, void* cb_args) {
+ struct cb_pair* cb_pair = (struct cb_pair*) cb_args;
+ return ((inplace_cb_edns_back_parsed_func_type*) cb_pair->cb)(qstate, id, cb_pair->cb_arg);
+}
+
+int dynlib_inplace_cb_query_response(struct module_qstate* qstate,
+ struct dns_msg* response, int id, void* cb_args) {
+ struct cb_pair* cb_pair = (struct cb_pair*) cb_args;
+ return ((inplace_cb_query_response_func_type*) cb_pair->cb)(qstate, response, id, cb_pair->cb_arg);
+}
+
+int
+inplace_cb_register_wrapped(void* cb, enum inplace_cb_list_type type, void* cbarg,
+ struct module_env* env, int id) {
+ struct cb_pair* cb_pair = malloc(sizeof(struct cb_pair));
+ cb_pair->cb = cb;
+ cb_pair->cb_arg = cbarg;
+ if(type >= inplace_cb_reply && type <= inplace_cb_reply_servfail) {
+ return inplace_cb_register(&dynlib_inplace_cb_reply_generic, type, (void*) cb_pair, env, id);
+ } else if(type == inplace_cb_query) {
+ return inplace_cb_register(&dynlib_inplace_cb_query_generic, type, (void*) cb_pair, env, id);
+ } else if(type == inplace_cb_query_response) {
+ return inplace_cb_register(&dynlib_inplace_cb_query_response, type, (void*) cb_pair, env, id);
+ } else if(type == inplace_cb_edns_back_parsed) {
+ return inplace_cb_register(&dynlib_inplace_cb_edns_back_parsed, type, (void*) cb_pair, env, id);
+ } else {
+ return 0;
+ }
+}
+
+void
+inplace_cb_delete_wrapped(struct module_env* env, enum inplace_cb_list_type type,
+ int id) {
+ struct inplace_cb* temp = env->inplace_cb_lists[type];
+ struct inplace_cb* prev = NULL;
+
+ while(temp) {
+ if(temp->id == id) {
+ if(!prev) {
+ env->inplace_cb_lists[type] = temp->next;
+ free(temp->cb_arg);
+ free(temp);
+ temp = env->inplace_cb_lists[type];
+ }
+ else {
+ prev->next = temp->next;
+ free(temp->cb_arg);
+ free(temp);
+ temp = prev->next;
+ }
+ }
+ else {
+ prev = temp;
+ temp = temp->next;
+ }
+ }
+}
+
+
+/**
+ * The module function block
+ */
+static struct module_func_block dynlibmod_block = {
+ "dynlib",
+ &dynlibmod_init, &dynlibmod_deinit, &dynlibmod_operate, &dynlibmod_inform_super,
+ &dynlibmod_clear, &dynlibmod_get_mem
+};
+
+struct module_func_block* dynlibmod_get_funcblock(void)
+{
+ return &dynlibmod_block;
+}
diff --git a/contrib/unbound/dynlibmod/dynlibmod.h b/contrib/unbound/dynlibmod/dynlibmod.h
new file mode 100644
index 000000000000..c34cf0e88d92
--- /dev/null
+++ b/contrib/unbound/dynlibmod/dynlibmod.h
@@ -0,0 +1,139 @@
+/*
+ * dynlibmod.h: module header file
+ *
+ * Copyright (c) 2019, Peter Munch-Ellingsen (peterme AT peterme.net)
+ *
+ * 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 organization nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+/**
+ * \file
+ * Dynamic loading module for unbound. Loads dynamic library.
+ */
+#ifndef DYNLIBMOD_H
+#define DYNLIBMOD_H
+#include "util/module.h"
+#include "services/outbound_list.h"
+
+/**
+ * Get the module function block.
+ * @return: function block with function pointers to module methods.
+ */
+struct module_func_block* dynlibmod_get_funcblock(void);
+
+/** dynlib module init */
+int dynlibmod_init(struct module_env* env, int id);
+
+/** dynlib module deinit */
+void dynlibmod_deinit(struct module_env* env, int id);
+
+/** dynlib module operate on a query */
+void dynlibmod_operate(struct module_qstate* qstate, enum module_ev event,
+ int id, struct outbound_entry* outbound);
+
+/** dynlib module */
+void dynlibmod_inform_super(struct module_qstate* qstate, int id,
+ struct module_qstate* super);
+
+/** dynlib module cleanup query state */
+void dynlibmod_clear(struct module_qstate* qstate, int id);
+
+/** dynlib module alloc size routine */
+size_t dynlibmod_get_mem(struct module_env* env, int id);
+
+int dynlib_inplace_cb_reply_generic(struct query_info* qinfo,
+ struct module_qstate* qstate, struct reply_info* rep, int rcode,
+ struct edns_data* edns, struct edns_option** opt_list_out,
+ struct comm_reply* repinfo, struct regional* region, int id,
+ void* callback);
+
+int dynlib_inplace_cb_query_generic(struct query_info* qinfo, uint16_t flags,
+ struct module_qstate* qstate, struct sockaddr_storage* addr,
+ socklen_t addrlen, uint8_t* zone, size_t zonelen, struct regional* region,
+ int id, void* callback);
+
+int dynlib_inplace_cb_edns_back_parsed(struct module_qstate* qstate,
+ int id, void* cb_args);
+
+int dynlib_inplace_cb_query_response(struct module_qstate* qstate,
+ struct dns_msg* response, int id, void* cb_args);
+
+int
+inplace_cb_register_wrapped(void* cb, enum inplace_cb_list_type type, void* cbarg,
+ struct module_env* env, int id);
+
+void
+inplace_cb_delete_wrapped(struct module_env* env, enum inplace_cb_list_type type,
+ int id);
+
+struct cb_pair {
+ void *cb;
+ void *cb_arg;
+};
+
+/**
+ * Global state for the module.
+ */
+
+typedef int (*func_init_t)(struct module_env*, int);
+typedef void (*func_deinit_t)(struct module_env*, int);
+typedef void (*func_operate_t)(struct module_qstate*, enum module_ev, int, struct outbound_entry*);
+typedef void (*func_inform_t)(struct module_qstate*, int, struct module_qstate*);
+typedef void (*func_clear_t)(struct module_qstate*, int);
+typedef size_t (*func_get_mem_t)(struct module_env*, int);
+typedef void (*inplace_cb_delete_wrapped_t)(struct module_env*, enum inplace_cb_list_type, int);
+typedef int (*inplace_cb_register_wrapped_t)(void*, enum inplace_cb_list_type, void*, struct module_env*, int);
+
+
+struct dynlibmod_env {
+ /** Dynamic library filename. */
+ const char* fname;
+ /** dynamic library handle */
+ void* dynamic_library;
+ /** Module init function */
+ func_init_t func_init;
+ /** Module deinit function */
+ func_deinit_t func_deinit;
+ /** Module operate function */
+ func_operate_t func_operate;
+ /** Module super_inform function */
+ func_inform_t func_inform;
+ /** Module clear function */
+ func_clear_t func_clear;
+ /** Module get_mem function */
+ func_get_mem_t func_get_mem;
+ /** Wrapped inplace callback functions to circumvent callback whitelisting */
+ inplace_cb_delete_wrapped_t inplace_cb_delete_wrapped;
+ inplace_cb_register_wrapped_t inplace_cb_register_wrapped;
+ /** Pointer to any data the dynamic library might want to keep */
+ void *dyn_env;
+};
+
+
+#endif /* DYNLIBMOD_H */
diff --git a/contrib/unbound/dynlibmod/examples/helloworld.c b/contrib/unbound/dynlibmod/examples/helloworld.c
new file mode 100644
index 000000000000..acb6b5d9bda6
--- /dev/null
+++ b/contrib/unbound/dynlibmod/examples/helloworld.c
@@ -0,0 +1,130 @@
+/**
+ * \file
+ *
+ * This is an example to show how dynamic libraries can be made to work with
+ * unbound. To build a .so file simply run:
+ * gcc -I../.. -shared -Wall -Werror -fpic -o helloworld.so helloworld.c
+ * And to build for windows, first make unbound with the --with-dynlibmod
+ * switch, then use this command:
+ * x86_64-w64-mingw32-gcc -m64 -I../.. -shared -Wall -Werror -fpic
+ * -o helloworld.dll helloworld.c -L../.. -l:libunbound.a
+ * to cross-compile a 64-bit Windows DLL.
+ */
+
+#include "../../config.h"
+#include "../../util/module.h"
+#include "../../sldns/parseutil.h"
+#include "../dynlibmod.h"
+
+/* Declare the EXPORT macro that expands to exporting the symbol for DLLs when
+ * compiling for Windows. All procedures marked with EXPORT in this example are
+ * called directly by the dynlib module and must be present for the module to
+ * load correctly. */
+#ifdef HAVE_WINDOWS_H
+#define EXPORT __declspec(dllexport)
+#else
+#define EXPORT
+#endif
+
+/* Forward declare a callback, implemented at the bottom of this file */
+int reply_callback(struct query_info* qinfo,
+ struct module_qstate* qstate, struct reply_info* rep, int rcode,
+ struct edns_data* edns, struct edns_option** opt_list_out,
+ struct comm_reply* repinfo, struct regional* region, int id,
+ void* callback);
+
+/* Init is called when the module is first loaded. It should be used to set up
+ * the environment for this module and do any other initialisation required. */
+EXPORT int init(struct module_env* env, int id) {
+ log_info("dynlib: hello world from init");
+ struct dynlibmod_env* de = (struct dynlibmod_env*) env->modinfo[id];
+ de->inplace_cb_register_wrapped(&reply_callback,
+ inplace_cb_reply,
+ NULL, env, id);
+ struct dynlibmod_env* local_env = env->modinfo[id];
+ local_env->dyn_env = NULL;
+ return 1;
+}
+
+/* Deinit is run as the program is shutting down. It should be used to clean up
+ * the environment and any left over data. */
+EXPORT void deinit(struct module_env* env, int id) {
+ log_info("dynlib: hello world from deinit");
+ struct dynlibmod_env* de = (struct dynlibmod_env*) env->modinfo[id];
+ de->inplace_cb_delete_wrapped(env, inplace_cb_reply, id);
+ if (de->dyn_env != NULL) free(de->dyn_env);
+}
+
+/* Operate is called every time a query passes by this module. The event can be
+ * used to determine which direction in the module chain it came from. */
+EXPORT void operate(struct module_qstate* qstate, enum module_ev event,
+ int id, struct outbound_entry* entry) {
+ log_info("dynlib: hello world from operate");
+ log_info("dynlib: incoming query: %s %s(%d) %s(%d)",
+ qstate->qinfo.qname,
+ sldns_lookup_by_id(sldns_rr_classes, qstate->qinfo.qclass)->name,
+ qstate->qinfo.qclass,
+ sldns_rr_descript(qstate->qinfo.qtype)->_name,
+ qstate->qinfo.qtype);
+ if (event == module_event_new || event == module_event_pass) {
+ qstate->ext_state[id] = module_wait_module;
+ struct dynlibmod_env* env = qstate->env->modinfo[id];
+ if (env->dyn_env == NULL) {
+ env->dyn_env = calloc(3, sizeof(int));
+ ((int *)env->dyn_env)[0] = 42;
+ ((int *)env->dyn_env)[1] = 102;
+ ((int *)env->dyn_env)[2] = 192;
+ } else {
+ log_err("dynlib: already has data!");
+ qstate->ext_state[id] = module_error;
+ }
+ } else if (event == module_event_moddone) {
+ qstate->ext_state[id] = module_finished;
+ } else {
+ qstate->ext_state[id] = module_error;
+ }
+}
+
+/* Inform super is called when a query is completed or errors out, but only if
+ * a sub-query has been registered to it by this module. Look at
+ * mesh_attach_sub in services/mesh.h to see how this is done. */
+EXPORT void inform_super(struct module_qstate* qstate, int id,
+ struct module_qstate* super) {
+ log_info("dynlib: hello world from inform_super");
+}
+
+/* Clear is called once a query is complete and the response has been sent
+ * back. It is used to clear up any per-query allocations. */
+EXPORT void clear(struct module_qstate* qstate, int id) {
+ log_info("dynlib: hello world from clear");
+ struct dynlibmod_env* env = qstate->env->modinfo[id];
+ if (env->dyn_env != NULL) {
+ free(env->dyn_env);
+ env->dyn_env = NULL;
+ }
+}
+
+/* Get mem is called when Unbound is printing performance information. This
+ * only happens explicitly and is only used to show memory usage to the user. */
+EXPORT size_t get_mem(struct module_env* env, int id) {
+ log_info("dynlib: hello world from get_mem");
+ return 0;
+}
+
+/* The callback that was forward declared earlier. It is registered in the init
+ * procedure to run when a query is being replied to. */
+int reply_callback(struct query_info* qinfo,
+ struct module_qstate* qstate, struct reply_info* rep, int rcode,
+ struct edns_data* edns, struct edns_option** opt_list_out,
+ struct comm_reply* repinfo, struct regional* region, int id,
+ void* callback) {
+ log_info("dynlib: hello world from callback");
+ struct dynlibmod_env* env = qstate->env->modinfo[id];
+ if (env->dyn_env != NULL) {
+ log_info("dynlib: numbers gotten from query: %d, %d, and %d",
+ ((int *)env->dyn_env)[0],
+ ((int *)env->dyn_env)[1],
+ ((int *)env->dyn_env)[2]);
+ }
+ return 0;
+}
diff --git a/contrib/unbound/edns-subnet/subnetmod.c b/contrib/unbound/edns-subnet/subnetmod.c
index 37dc550cd69c..f1b401b9080c 100644
--- a/contrib/unbound/edns-subnet/subnetmod.c
+++ b/contrib/unbound/edns-subnet/subnetmod.c
@@ -386,8 +386,7 @@ update_cache(struct module_qstate *qstate, int id)
rep->flags |= (BIT_RA | BIT_QR); /* fix flags to be sensible for */
rep->flags &= ~(BIT_AA | BIT_CD);/* a reply based on the cache */
addrtree_insert(tree, (addrkey_t*)edns->subnet_addr,
- edns->subnet_source_mask,
- sq->ecs_server_in.subnet_scope_mask, rep,
+ edns->subnet_source_mask, sq->max_scope, rep,
rep->ttl, *qstate->env->now);
lock_rw_unlock(&lru_entry->lock);
@@ -543,7 +542,7 @@ eval_response(struct module_qstate *qstate, int id, struct subnet_qstate *sq)
c_out->subnet_addr_fam = c_in->subnet_addr_fam;
c_out->subnet_source_mask = c_in->subnet_source_mask;
memcpy(&c_out->subnet_addr, &c_in->subnet_addr, INET6_SIZE);
- c_out->subnet_scope_mask = s_in->subnet_scope_mask;
+ c_out->subnet_scope_mask = sq->max_scope;
/* Limit scope returned to client to scope used for caching. */
if(c_out->subnet_addr_fam == EDNSSUBNET_ADDRFAM_IP4) {
if(c_out->subnet_scope_mask >
@@ -648,6 +647,19 @@ ecs_query_response(struct module_qstate* qstate, struct dns_msg* response,
qstate->env->cfg->client_subnet_opcode);
sq->subnet_sent = 0;
memset(&sq->ecs_server_out, 0, sizeof(sq->ecs_server_out));
+ } else if (!sq->track_max_scope &&
+ FLAGS_GET_RCODE(response->rep->flags) == LDNS_RCODE_NOERROR &&
+ response->rep->an_numrrsets > 0
+ ) {
+ struct ub_packed_rrset_key* s = response->rep->rrsets[0];
+ if(ntohs(s->rk.type) == LDNS_RR_TYPE_CNAME &&
+ query_dname_compare(qstate->qinfo.qname,
+ s->rk.dname) == 0) {
+ /* CNAME response for QNAME. From now on keep track of
+ * longest received ECS prefix for all queries on this
+ * qstate. */
+ sq->track_max_scope = 1;
+ }
}
return 1;
}
@@ -663,16 +675,19 @@ ecs_edns_back_parsed(struct module_qstate* qstate, int id,
return 1;
if((ecs_opt = edns_opt_list_find(
qstate->edns_opts_back_in,
- qstate->env->cfg->client_subnet_opcode))) {
- if(parse_subnet_option(ecs_opt, &sq->ecs_server_in) &&
- sq->subnet_sent &&
- sq->ecs_server_in.subnet_validdata)
+ qstate->env->cfg->client_subnet_opcode)) &&
+ parse_subnet_option(ecs_opt, &sq->ecs_server_in) &&
+ sq->subnet_sent && sq->ecs_server_in.subnet_validdata) {
/* Only skip global cache store if we sent an ECS option
* and received one back. Answers from non-whitelisted
* servers will end up in global cache. Answers for
* queries with 0 source will not (unless nameserver
* does not support ECS). */
qstate->no_cache_store = 1;
+ if(!sq->track_max_scope || (sq->track_max_scope &&
+ sq->ecs_server_in.subnet_scope_mask >
+ sq->max_scope))
+ sq->max_scope = sq->ecs_server_in.subnet_scope_mask;
}
return 1;
diff --git a/contrib/unbound/edns-subnet/subnetmod.h b/contrib/unbound/edns-subnet/subnetmod.h
index e408627b0abd..27ba2ee74129 100644
--- a/contrib/unbound/edns-subnet/subnetmod.h
+++ b/contrib/unbound/edns-subnet/subnetmod.h
@@ -45,6 +45,7 @@
#include "util/alloc.h"
#include "util/net_help.h"
#include "util/storage/slabhash.h"
+#include "util/data/dname.h"
#include "edns-subnet/addrtree.h"
#include "edns-subnet/edns-subnet.h"
@@ -83,6 +84,12 @@ struct subnet_qstate {
struct ecs_data ecs_server_out;
int subnet_downstream;
int subnet_sent;
+ /** keep track of longest received scope, set after receiving CNAME for
+ * incoming QNAME. */
+ int track_max_scope;
+ /** longest received scope mask since track_max_scope is set. This value
+ * is used for caching and answereing to client. */
+ uint8_t max_scope;
/** has the subnet module been started with no_cache_store? */
int started_no_cache_store;
};
diff --git a/contrib/unbound/iterator/iter_utils.c b/contrib/unbound/iterator/iter_utils.c
index 3c14de86e7b4..7bc67da69b2e 100644
--- a/contrib/unbound/iterator/iter_utils.c
+++ b/contrib/unbound/iterator/iter_utils.c
@@ -484,6 +484,63 @@ iter_filter_order(struct iter_env* iter_env, struct module_env* env,
got_num = num4ok;
*selected_rtt = num4_lowrtt;
}
+ } else if (env->cfg->prefer_ip4) {
+ int got_num4 = 0;
+ int low_rtt4 = 0;
+ int i;
+ int attempt = -1; /* filter to make sure addresses have
+ less attempts on them than the first, to force round
+ robin when all the IPv4 addresses fail */
+ int num6ok = 0; /* number ip6 at low attempt count */
+ int num6_lowrtt = 0;
+ prev = NULL;
+ a = dp->result_list;
+ for(i = 0; i < got_num; i++) {
+ swap_to_front = 0;
+ if(a->addr.ss_family != AF_INET && attempt == -1) {
+ /* if we only have ip6 at low attempt count,
+ * then ip4 is failing, and we need to
+ * select one of the remaining IPv6 addrs */
+ attempt = a->attempts;
+ num6ok++;
+ num6_lowrtt = a->sel_rtt;
+ } else if(a->addr.ss_family != AF_INET && attempt == a->attempts) {
+ num6ok++;
+ if(num6_lowrtt == 0 || a->sel_rtt < num6_lowrtt) {
+ num6_lowrtt = a->sel_rtt;
+ }
+ }
+ if(a->addr.ss_family == AF_INET) {
+ if(attempt == -1) {
+ attempt = a->attempts;
+ } else if(a->attempts > attempt) {
+ break;
+ }
+ got_num4++;
+ swap_to_front = 1;
+ if(low_rtt4 == 0 || a->sel_rtt < low_rtt4) {
+ low_rtt4 = a->sel_rtt;
+ }
+ }
+ /* swap to front if IPv4, or move to next result */
+ if(swap_to_front && prev) {
+ n = a->next_result;
+ prev->next_result = n;
+ a->next_result = dp->result_list;
+ dp->result_list = a;
+ a = n;
+ } else {
+ prev = a;
+ a = a->next_result;
+ }
+ }
+ if(got_num4 > 0) {
+ got_num = got_num4;
+ *selected_rtt = low_rtt4;
+ } else if(num6ok > 0) {
+ got_num = num6ok;
+ *selected_rtt = num6_lowrtt;
+ }
}
return got_num;
}
diff --git a/contrib/unbound/iterator/iterator.c b/contrib/unbound/iterator/iterator.c
index 9d36660c0b18..23b07ea9095b 100644
--- a/contrib/unbound/iterator/iterator.c
+++ b/contrib/unbound/iterator/iterator.c
@@ -162,7 +162,7 @@ iter_new(struct module_qstate* qstate, int id)
iq->qchase = qstate->qinfo;
outbound_list_init(&iq->outlist);
iq->minimise_count = 0;
- iq->minimise_timeout_count = 0;
+ iq->timeout_count = 0;
if (qstate->env->cfg->qname_minimisation)
iq->minimisation_state = INIT_MINIMISE_STATE;
else
@@ -2239,7 +2239,7 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
iq->qinfo_out.qname = iq->qchase.qname;
iq->qinfo_out.qname_len = iq->qchase.qname_len;
iq->minimise_count++;
- iq->minimise_timeout_count = 0;
+ iq->timeout_count = 0;
iter_dec_attempts(iq->dp, 1);
@@ -2327,7 +2327,7 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
}
}
if(iq->minimisation_state == SKIP_MINIMISE_STATE) {
- if(iq->minimise_timeout_count < MAX_MINIMISE_TIMEOUT_COUNT)
+ if(iq->timeout_count < MAX_MINIMISE_TIMEOUT_COUNT)
/* Do not increment qname, continue incrementing next
* iteration */
iq->minimisation_state = MINIMISE_STATE;
@@ -2668,14 +2668,15 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
if(iq->response == NULL) {
/* Don't increment qname when QNAME minimisation is enabled */
if(qstate->env->cfg->qname_minimisation) {
- iq->minimise_timeout_count++;
iq->minimisation_state = SKIP_MINIMISE_STATE;
}
+ iq->timeout_count++;
iq->chase_to_rd = 0;
iq->dnssec_lame_query = 0;
verbose(VERB_ALGO, "query response was timeout");
return next_state(iq, QUERYTARGETS_STATE);
}
+ iq->timeout_count = 0;
type = response_type_from_server(
(int)((iq->chase_flags&BIT_RD) || iq->chase_to_rd),
iq->response, &iq->qinfo_out, iq->dp);
@@ -3690,7 +3691,7 @@ process_response(struct module_qstate* qstate, struct iter_qstate* iq,
iq->response = NULL;
iq->state = QUERY_RESP_STATE;
if(event == module_event_noreply || event == module_event_error) {
- if(event == module_event_noreply && iq->sent_count >= 3 &&
+ if(event == module_event_noreply && iq->timeout_count >= 3 &&
qstate->env->cfg->use_caps_bits_for_id &&
!iq->caps_fallback && !is_caps_whitelisted(ie, iq)) {
/* start fallback */
diff --git a/contrib/unbound/iterator/iterator.h b/contrib/unbound/iterator/iterator.h
index 53dcab3b18b2..342ac207e826 100644
--- a/contrib/unbound/iterator/iterator.h
+++ b/contrib/unbound/iterator/iterator.h
@@ -398,8 +398,9 @@ struct iter_qstate {
/**
* Count number of time-outs. Used to prevent resolving failures when
- * the QNAME minimisation QTYPE is blocked. */
- int minimise_timeout_count;
+ * the QNAME minimisation QTYPE is blocked. Used to determine if
+ * capsforid fallback should be started.*/
+ int timeout_count;
/** True if the current response is from auth_zone */
int auth_zone_response;
diff --git a/contrib/unbound/libunbound/libworker.c b/contrib/unbound/libunbound/libworker.c
index 6cb97ff1fd4a..44b8d790561f 100644
--- a/contrib/unbound/libunbound/libworker.c
+++ b/contrib/unbound/libunbound/libworker.c
@@ -74,6 +74,14 @@
#include "sldns/sbuffer.h"
#include "sldns/str2wire.h"
+#ifdef HAVE_TARGETCONDITIONALS_H
+#include <TargetConditionals.h>
+#endif
+
+#if defined(TARGET_OS_TV) || defined(TARGET_OS_WATCH)
+#undef HAVE_FORK
+#endif
+
/** handle new query command for bg worker */
static void handle_newq(struct libworker* w, uint8_t* buf, uint32_t len);
@@ -225,12 +233,12 @@ libworker_setup(struct ub_ctx* ctx, int is_bg, struct ub_event_base* eb)
w->back = outside_network_create(w->base, cfg->msg_buffer_size,
(size_t)cfg->outgoing_num_ports, cfg->out_ifs,
cfg->num_out_ifs, cfg->do_ip4, cfg->do_ip6,
- cfg->do_tcp?cfg->outgoing_num_tcp:0,
+ cfg->do_tcp?cfg->outgoing_num_tcp:0, cfg->ip_dscp,
w->env->infra_cache, w->env->rnd, cfg->use_caps_bits_for_id,
ports, numports, cfg->unwanted_threshold,
cfg->outgoing_tcp_mss, &libworker_alloc_cleanup, w,
cfg->do_udp || cfg->udp_upstream_without_downstream, w->sslctx,
- cfg->delay_close, NULL);
+ cfg->delay_close, cfg->tls_use_sni, NULL);
w->env->outnet = w->back;
if(!w->is_bg || w->is_bg_thread) {
lock_basic_unlock(&ctx->cfglock);
@@ -1047,3 +1055,19 @@ wsvc_cron_cb(void* ATTR_UNUSED(arg))
log_assert(0);
}
#endif /* UB_ON_WINDOWS */
+
+#ifdef USE_DNSTAP
+void dtio_tap_callback(int ATTR_UNUSED(fd), short ATTR_UNUSED(ev),
+ void* ATTR_UNUSED(arg))
+{
+ log_assert(0);
+}
+#endif
+
+#ifdef USE_DNSTAP
+void dtio_mainfdcallback(int ATTR_UNUSED(fd), short ATTR_UNUSED(ev),
+ void* ATTR_UNUSED(arg))
+{
+ log_assert(0);
+}
+#endif
diff --git a/contrib/unbound/libunbound/unbound.h b/contrib/unbound/libunbound/unbound.h
index ca9592d62d52..b53426c76d54 100644
--- a/contrib/unbound/libunbound/unbound.h
+++ b/contrib/unbound/libunbound/unbound.h
@@ -642,6 +642,7 @@ struct ub_shm_stat_info {
long long respip;
long long dnscrypt_shared_secret;
long long dnscrypt_nonce;
+ long long dynlib;
} mem;
};
diff --git a/contrib/unbound/respip/respip.c b/contrib/unbound/respip/respip.c
index f504f55791ac..6fa4f18851fd 100644
--- a/contrib/unbound/respip/respip.c
+++ b/contrib/unbound/respip/respip.c
@@ -502,10 +502,16 @@ copy_rrset(const struct ub_packed_rrset_key* key, struct regional* region)
ck->entry.hash = key->entry.hash;
ck->entry.key = ck;
ck->rk = key->rk;
- ck->rk.dname = regional_alloc_init(region, key->rk.dname,
- key->rk.dname_len);
- if(!ck->rk.dname)
- return NULL;
+ if(key->rk.dname) {
+ ck->rk.dname = regional_alloc_init(region, key->rk.dname,
+ key->rk.dname_len);
+ if(!ck->rk.dname)
+ return NULL;
+ ck->rk.dname_len = key->rk.dname_len;
+ } else {
+ ck->rk.dname = NULL;
+ ck->rk.dname_len = 0;
+ }
if((unsigned)data->count >= 0xffff00U)
return NULL; /* guard against integer overflow in dsize */
@@ -908,6 +914,7 @@ respip_rewrite_reply(const struct query_info* qinfo,
int ret = 1;
struct ub_packed_rrset_key* redirect_rrset = NULL;
struct rpz* r;
+ struct auth_zone* a;
struct ub_packed_rrset_key* data = NULL;
int rpz_used = 0;
int rpz_log = 0;
@@ -949,6 +956,10 @@ respip_rewrite_reply(const struct query_info* qinfo,
}
if(!raddr && !view->isfirst)
goto done;
+ if(!raddr && view->isfirst) {
+ lock_rw_unlock(&view->lock);
+ view = NULL;
+ }
}
if(!raddr && (raddr = respip_addr_lookup(rep, ipset,
&rrset_id))) {
@@ -959,7 +970,9 @@ respip_rewrite_reply(const struct query_info* qinfo,
ipset->tagname, ipset->num_tags);
}
lock_rw_rdlock(&az->rpz_lock);
- for(r = az->rpz_first; r && !raddr; r = r->next) {
+ for(a = az->rpz_first; a && !raddr; a = a->rpz_az_next) {
+ lock_rw_rdlock(&a->lock);
+ r = a->rpz;
if(!r->taglist || taglist_intersect(r->taglist,
r->taglistlen, ctaglist, ctaglen)) {
if((raddr = respip_addr_lookup(rep,
@@ -969,16 +982,21 @@ respip_rewrite_reply(const struct query_info* qinfo,
region, &rpz_used)) {
log_err("out of memory");
lock_rw_unlock(&raddr->lock);
+ lock_rw_unlock(&a->lock);
lock_rw_unlock(&az->rpz_lock);
return 0;
}
- if(!rpz_used) {
- lock_rw_unlock(&raddr->lock);
- raddr = NULL;
- actinfo->rpz_disabled++;
+ if(rpz_used) {
+ /* break to make sure 'a' stays pointed
+ * to used auth_zone, and keeps lock */
+ break;
}
+ lock_rw_unlock(&raddr->lock);
+ raddr = NULL;
+ actinfo->rpz_disabled++;
}
- }
+ }
+ lock_rw_unlock(&a->lock);
}
lock_rw_unlock(&az->rpz_lock);
if(raddr && !search_only) {
@@ -1032,6 +1050,9 @@ respip_rewrite_reply(const struct query_info* qinfo,
if(raddr) {
lock_rw_unlock(&raddr->lock);
}
+ if(rpz_used) {
+ lock_rw_unlock(&a->lock);
+ }
return ret;
}
diff --git a/contrib/unbound/services/authzone.c b/contrib/unbound/services/authzone.c
index 8854bc647953..5064d2c61080 100644
--- a/contrib/unbound/services/authzone.c
+++ b/contrib/unbound/services/authzone.c
@@ -392,12 +392,12 @@ auth_zone_delete(struct auth_zone* z, struct auth_zones* az)
if(az && z->rpz) {
/* keep RPZ linked list intact */
lock_rw_wrlock(&az->rpz_lock);
- if(z->rpz->prev)
- z->rpz->prev->next = z->rpz->next;
+ if(z->rpz_az_prev)
+ z->rpz_az_prev->rpz_az_next = z->rpz_az_next;
else
- az->rpz_first = z->rpz->next;
- if(z->rpz->next)
- z->rpz->next->prev = z->rpz->prev;
+ az->rpz_first = z->rpz_az_next;
+ if(z->rpz_az_next)
+ z->rpz_az_next->rpz_az_prev = z->rpz_az_prev;
lock_rw_unlock(&az->rpz_lock);
}
if(z->rpz)
@@ -426,9 +426,11 @@ auth_zone_create(struct auth_zones* az, uint8_t* nm, size_t nmlen,
}
rbtree_init(&z->data, &auth_data_cmp);
lock_rw_init(&z->lock);
- lock_protect(&z->lock, &z->name, sizeof(*z)-sizeof(rbnode_type));
+ lock_protect(&z->lock, &z->name, sizeof(*z)-sizeof(rbnode_type)-
+ sizeof(&z->rpz_az_next)-sizeof(&z->rpz_az_prev));
lock_rw_wrlock(&z->lock);
- /* z lock protects all, except rbtree itself, which is az->lock */
+ /* z lock protects all, except rbtree itself and the rpz linked list
+ * pointers, which are protected using az->lock */
if(!rbtree_insert(&az->ztree, &z->node)) {
lock_rw_unlock(&z->lock);
auth_zone_delete(z, NULL);
@@ -1178,9 +1180,9 @@ az_insert_rr(struct auth_zone* z, uint8_t* rr, size_t rr_len,
return 0;
}
if(z->rpz) {
- if(!(rpz_insert_rr(z->rpz, z->namelen, dname, dname_len,
- rr_type, rr_class, rr_ttl, rdata, rdatalen, rr,
- rr_len)))
+ if(!(rpz_insert_rr(z->rpz, z->name, z->namelen, dname,
+ dname_len, rr_type, rr_class, rr_ttl, rdata, rdatalen,
+ rr, rr_len)))
return 0;
}
return 1;
@@ -1864,15 +1866,26 @@ auth_zones_cfg(struct auth_zones* az, struct config_auth* c)
struct auth_xfer* x = NULL;
/* create zone */
+ if(c->isrpz) {
+ /* if the rpz lock is needed, grab it before the other
+ * locks to avoid a lock dependency cycle */
+ lock_rw_wrlock(&az->rpz_lock);
+ }
lock_rw_wrlock(&az->lock);
if(!(z=auth_zones_find_or_add_zone(az, c->name))) {
lock_rw_unlock(&az->lock);
+ if(c->isrpz) {
+ lock_rw_unlock(&az->rpz_lock);
+ }
return 0;
}
if(c->masters || c->urls) {
if(!(x=auth_zones_find_or_add_xfer(az, z))) {
lock_rw_unlock(&az->lock);
lock_rw_unlock(&z->lock);
+ if(c->isrpz) {
+ lock_rw_unlock(&az->rpz_lock);
+ }
return 0;
}
}
@@ -1887,6 +1900,9 @@ auth_zones_cfg(struct auth_zones* az, struct config_auth* c)
lock_basic_unlock(&x->lock);
}
lock_rw_unlock(&z->lock);
+ if(c->isrpz) {
+ lock_rw_unlock(&az->rpz_lock);
+ }
return 0;
}
z->for_downstream = c->for_downstream;
@@ -1897,11 +1913,14 @@ auth_zones_cfg(struct auth_zones* az, struct config_auth* c)
fatal_exit("Could not setup RPZ zones");
return 0;
}
- lock_rw_wrlock(&az->rpz_lock);
- z->rpz->next = az->rpz_first;
+ lock_protect(&z->lock, &z->rpz->local_zones, sizeof(*z->rpz));
+ /* the az->rpz_lock is locked above */
+ z->rpz_az_next = az->rpz_first;
if(az->rpz_first)
- az->rpz_first->prev = z->rpz;
- az->rpz_first = z->rpz;
+ az->rpz_first->rpz_az_prev = z;
+ az->rpz_first = z;
+ }
+ if(c->isrpz) {
lock_rw_unlock(&az->rpz_lock);
}
@@ -5331,7 +5350,7 @@ void auth_xfer_transfer_lookup_callback(void* arg, int rcode, sldns_buffer* buf,
log_assert(xfr->task_transfer);
lock_basic_lock(&xfr->lock);
env = xfr->task_transfer->env;
- if(env->outnet->want_to_quit) {
+ if(!env || env->outnet->want_to_quit) {
lock_basic_unlock(&xfr->lock);
return; /* stop on quit */
}
@@ -5770,7 +5789,7 @@ auth_xfer_transfer_timer_callback(void* arg)
log_assert(xfr->task_transfer);
lock_basic_lock(&xfr->lock);
env = xfr->task_transfer->env;
- if(env->outnet->want_to_quit) {
+ if(!env || env->outnet->want_to_quit) {
lock_basic_unlock(&xfr->lock);
return; /* stop on quit */
}
@@ -5812,7 +5831,7 @@ auth_xfer_transfer_tcp_callback(struct comm_point* c, void* arg, int err,
log_assert(xfr->task_transfer);
lock_basic_lock(&xfr->lock);
env = xfr->task_transfer->env;
- if(env->outnet->want_to_quit) {
+ if(!env || env->outnet->want_to_quit) {
lock_basic_unlock(&xfr->lock);
return 0; /* stop on quit */
}
@@ -5893,7 +5912,7 @@ auth_xfer_transfer_http_callback(struct comm_point* c, void* arg, int err,
log_assert(xfr->task_transfer);
lock_basic_lock(&xfr->lock);
env = xfr->task_transfer->env;
- if(env->outnet->want_to_quit) {
+ if(!env || env->outnet->want_to_quit) {
lock_basic_unlock(&xfr->lock);
return 0; /* stop on quit */
}
@@ -6107,7 +6126,7 @@ auth_xfer_probe_timer_callback(void* arg)
log_assert(xfr->task_probe);
lock_basic_lock(&xfr->lock);
env = xfr->task_probe->env;
- if(env->outnet->want_to_quit) {
+ if(!env || env->outnet->want_to_quit) {
lock_basic_unlock(&xfr->lock);
return; /* stop on quit */
}
@@ -6143,7 +6162,7 @@ auth_xfer_probe_udp_callback(struct comm_point* c, void* arg, int err,
log_assert(xfr->task_probe);
lock_basic_lock(&xfr->lock);
env = xfr->task_probe->env;
- if(env->outnet->want_to_quit) {
+ if(!env || env->outnet->want_to_quit) {
lock_basic_unlock(&xfr->lock);
return 0; /* stop on quit */
}
@@ -6388,7 +6407,7 @@ void auth_xfer_probe_lookup_callback(void* arg, int rcode, sldns_buffer* buf,
log_assert(xfr->task_probe);
lock_basic_lock(&xfr->lock);
env = xfr->task_probe->env;
- if(env->outnet->want_to_quit) {
+ if(!env || env->outnet->want_to_quit) {
lock_basic_unlock(&xfr->lock);
return; /* stop on quit */
}
@@ -6465,7 +6484,7 @@ auth_xfer_timer(void* arg)
log_assert(xfr->task_nextprobe);
lock_basic_lock(&xfr->lock);
env = xfr->task_nextprobe->env;
- if(env->outnet->want_to_quit) {
+ if(!env || env->outnet->want_to_quit) {
lock_basic_unlock(&xfr->lock);
return; /* stop on quit */
}
diff --git a/contrib/unbound/services/authzone.h b/contrib/unbound/services/authzone.h
index 9bb131ad8b39..3d94f30d6202 100644
--- a/contrib/unbound/services/authzone.h
+++ b/contrib/unbound/services/authzone.h
@@ -82,8 +82,8 @@ struct auth_zones {
size_t num_query_up;
/** number of queries downstream */
size_t num_query_down;
- /** first rpz item in linked list */
- struct rpz* rpz_first;
+ /** first auth zone containing rpz item in linked list */
+ struct auth_zone* rpz_first;
/** rw lock for rpz linked list, needed when iterating or editing linked
* list. */
lock_rw_type rpz_lock;
@@ -138,6 +138,11 @@ struct auth_zone {
int zone_deleted;
/** deletelist pointer, unused normally except during delete */
struct auth_zone* delete_next;
+ /* not protected by auth_zone lock, must be last items in struct */
+ /** next auth zone containing RPZ data, or NULL */
+ struct auth_zone* rpz_az_next;
+ /** previous auth zone containing RPZ data, or NULL */
+ struct auth_zone* rpz_az_prev;
};
/**
diff --git a/contrib/unbound/services/listen_dnsport.c b/contrib/unbound/services/listen_dnsport.c
index 7e2afd843be8..cc56d3fd3167 100644
--- a/contrib/unbound/services/listen_dnsport.c
+++ b/contrib/unbound/services/listen_dnsport.c
@@ -179,9 +179,10 @@ int
create_udp_sock(int family, int socktype, struct sockaddr* addr,
socklen_t addrlen, int v6only, int* inuse, int* noproto,
int rcv, int snd, int listen, int* reuseport, int transparent,
- int freebind, int use_systemd)
+ int freebind, int use_systemd, int dscp)
{
int s;
+ char* err;
#if defined(SO_REUSEADDR) || defined(SO_REUSEPORT) || defined(IPV6_USE_MIN_MTU) || defined(IP_TRANSPARENT) || defined(IP_BINDANY) || defined(IP_FREEBIND) || defined (SO_BINDANY)
int on=1;
#endif
@@ -451,6 +452,9 @@ create_udp_sock(int family, int socktype, struct sockaddr* addr,
# endif
#endif /* SO_SNDBUF */
}
+ err = set_ip_dscp(s, family, dscp);
+ if(err != NULL)
+ log_warn("error setting IP DiffServ codepoint %d on UDP socket: %s", dscp, err);
if(family == AF_INET6) {
# if defined(IPV6_V6ONLY)
if(v6only) {
@@ -638,9 +642,10 @@ create_udp_sock(int family, int socktype, struct sockaddr* addr,
int
create_tcp_accept_sock(struct addrinfo *addr, int v6only, int* noproto,
- int* reuseport, int transparent, int mss, int freebind, int use_systemd)
+ int* reuseport, int transparent, int mss, int freebind, int use_systemd, int dscp)
{
int s;
+ char* err;
#if defined(SO_REUSEADDR) || defined(SO_REUSEPORT) || defined(IPV6_V6ONLY) || defined(IP_TRANSPARENT) || defined(IP_BINDANY) || defined(IP_FREEBIND) || defined(SO_BINDANY)
int on = 1;
#endif
@@ -793,6 +798,9 @@ create_tcp_accept_sock(struct addrinfo *addr, int v6only, int* noproto,
strerror(errno));
}
#endif /* IP_TRANSPARENT || IP_BINDANY || SO_BINDANY */
+ err = set_ip_dscp(s, addr->ai_family, dscp);
+ if(err != NULL)
+ log_warn("error setting IP DiffServ codepoint %d on TCP socket: %s", dscp, err);
if(
#ifdef HAVE_SYSTEMD
!got_fd_from_systemd &&
@@ -866,6 +874,55 @@ create_tcp_accept_sock(struct addrinfo *addr, int v6only, int* noproto,
return s;
}
+char*
+set_ip_dscp(int socket, int addrfamily, int dscp)
+{
+ int ds;
+
+ if(dscp == 0)
+ return NULL;
+ ds = dscp << 2;
+ switch(addrfamily) {
+ case AF_INET6:
+ if(setsockopt(socket, IPPROTO_IPV6, IPV6_TCLASS, (void*)&ds, sizeof(ds)) < 0)
+ return sock_strerror(errno);
+ break;
+ default:
+ if(setsockopt(socket, IPPROTO_IP, IP_TOS, (void*)&ds, sizeof(ds)) < 0)
+ return sock_strerror(errno);
+ break;
+ }
+ return NULL;
+}
+
+# ifndef USE_WINSOCK
+char*
+sock_strerror(int errn)
+{
+ return strerror(errn);
+}
+
+void
+sock_close(int socket)
+{
+ close(socket);
+}
+
+# else
+char*
+sock_strerror(int ATTR_UNUSED(errn))
+{
+ return wsa_strerror(WSAGetLastError());
+}
+
+void
+sock_close(int socket)
+{
+ closesocket(socket);
+}
+
+# endif /* USE_WINSOCK */
+
int
create_local_accept_sock(const char *path, int* noproto, int use_systemd)
{
@@ -952,7 +1009,7 @@ err:
static int
make_sock(int stype, const char* ifname, const char* port,
struct addrinfo *hints, int v6only, int* noip6, size_t rcv, size_t snd,
- int* reuseport, int transparent, int tcp_mss, int freebind, int use_systemd)
+ int* reuseport, int transparent, int tcp_mss, int freebind, int use_systemd, int dscp)
{
struct addrinfo *res = NULL;
int r, s, inuse, noproto;
@@ -980,7 +1037,7 @@ make_sock(int stype, const char* ifname, const char* port,
s = create_udp_sock(res->ai_family, res->ai_socktype,
(struct sockaddr*)res->ai_addr, res->ai_addrlen,
v6only, &inuse, &noproto, (int)rcv, (int)snd, 1,
- reuseport, transparent, freebind, use_systemd);
+ reuseport, transparent, freebind, use_systemd, dscp);
if(s == -1 && inuse) {
log_err("bind: address already in use");
} else if(s == -1 && noproto && hints->ai_family == AF_INET6){
@@ -988,7 +1045,7 @@ make_sock(int stype, const char* ifname, const char* port,
}
} else {
s = create_tcp_accept_sock(res, v6only, &noproto, reuseport,
- transparent, tcp_mss, freebind, use_systemd);
+ transparent, tcp_mss, freebind, use_systemd, dscp);
if(s == -1 && noproto && hints->ai_family == AF_INET6){
*noip6 = 1;
}
@@ -1001,7 +1058,7 @@ make_sock(int stype, const char* ifname, const char* port,
static int
make_sock_port(int stype, const char* ifname, const char* port,
struct addrinfo *hints, int v6only, int* noip6, size_t rcv, size_t snd,
- int* reuseport, int transparent, int tcp_mss, int freebind, int use_systemd)
+ int* reuseport, int transparent, int tcp_mss, int freebind, int use_systemd, int dscp)
{
char* s = strchr(ifname, '@');
if(s) {
@@ -1023,10 +1080,10 @@ make_sock_port(int stype, const char* ifname, const char* port,
(void)strlcpy(p, s+1, sizeof(p));
p[strlen(s+1)]=0;
return make_sock(stype, newif, p, hints, v6only, noip6,
- rcv, snd, reuseport, transparent, tcp_mss, freebind, use_systemd);
+ rcv, snd, reuseport, transparent, tcp_mss, freebind, use_systemd, dscp);
}
return make_sock(stype, ifname, port, hints, v6only, noip6, rcv, snd,
- reuseport, transparent, tcp_mss, freebind, use_systemd);
+ reuseport, transparent, tcp_mss, freebind, use_systemd, dscp);
}
/**
@@ -1146,6 +1203,7 @@ if_is_ssl(const char* ifname, const char* port, int ssl_port,
* @param freebind: set IP_FREEBIND socket option.
* @param use_systemd: if true, fetch sockets from systemd.
* @param dnscrypt_port: dnscrypt service port number
+ * @param dscp: DSCP to use.
* @return: returns false on error.
*/
static int
@@ -1154,7 +1212,7 @@ ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp,
size_t rcv, size_t snd, int ssl_port,
struct config_strlist* tls_additional_port, int* reuseport,
int transparent, int tcp_mss, int freebind, int use_systemd,
- int dnscrypt_port)
+ int dnscrypt_port, int dscp)
{
int s, noip6=0;
#ifdef USE_DNSCRYPT
@@ -1171,7 +1229,7 @@ ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp,
if(do_auto) {
if((s = make_sock_port(SOCK_DGRAM, ifname, port, hints, 1,
&noip6, rcv, snd, reuseport, transparent,
- tcp_mss, freebind, use_systemd)) == -1) {
+ tcp_mss, freebind, use_systemd, dscp)) == -1) {
if(noip6) {
log_warn("IPv6 protocol not available");
return 1;
@@ -1200,7 +1258,7 @@ ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp,
/* regular udp socket */
if((s = make_sock_port(SOCK_DGRAM, ifname, port, hints, 1,
&noip6, rcv, snd, reuseport, transparent,
- tcp_mss, freebind, use_systemd)) == -1) {
+ tcp_mss, freebind, use_systemd, dscp)) == -1) {
if(noip6) {
log_warn("IPv6 protocol not available");
return 1;
@@ -1222,7 +1280,7 @@ ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp,
tls_additional_port);
if((s = make_sock_port(SOCK_STREAM, ifname, port, hints, 1,
&noip6, 0, 0, reuseport, transparent, tcp_mss,
- freebind, use_systemd)) == -1) {
+ freebind, use_systemd, dscp)) == -1) {
if(noip6) {
/*log_warn("IPv6 protocol not available");*/
return 1;
@@ -1421,7 +1479,7 @@ listening_ports_open(struct config_file* cfg, int* reuseport)
cfg->ssl_port, cfg->tls_additional_port,
reuseport, cfg->ip_transparent,
cfg->tcp_mss, cfg->ip_freebind, cfg->use_systemd,
- cfg->dnscrypt_port)) {
+ cfg->dnscrypt_port, cfg->ip_dscp)) {
listening_ports_free(list);
return NULL;
}
@@ -1435,7 +1493,7 @@ listening_ports_open(struct config_file* cfg, int* reuseport)
cfg->ssl_port, cfg->tls_additional_port,
reuseport, cfg->ip_transparent,
cfg->tcp_mss, cfg->ip_freebind, cfg->use_systemd,
- cfg->dnscrypt_port)) {
+ cfg->dnscrypt_port, cfg->ip_dscp)) {
listening_ports_free(list);
return NULL;
}
@@ -1451,7 +1509,7 @@ listening_ports_open(struct config_file* cfg, int* reuseport)
cfg->ssl_port, cfg->tls_additional_port,
reuseport, cfg->ip_transparent,
cfg->tcp_mss, cfg->ip_freebind, cfg->use_systemd,
- cfg->dnscrypt_port)) {
+ cfg->dnscrypt_port, cfg->ip_dscp)) {
listening_ports_free(list);
return NULL;
}
@@ -1465,7 +1523,7 @@ listening_ports_open(struct config_file* cfg, int* reuseport)
cfg->ssl_port, cfg->tls_additional_port,
reuseport, cfg->ip_transparent,
cfg->tcp_mss, cfg->ip_freebind, cfg->use_systemd,
- cfg->dnscrypt_port)) {
+ cfg->dnscrypt_port, cfg->ip_dscp)) {
listening_ports_free(list);
return NULL;
}
diff --git a/contrib/unbound/services/listen_dnsport.h b/contrib/unbound/services/listen_dnsport.h
index ad84d8322643..ddd1b63a4d95 100644
--- a/contrib/unbound/services/listen_dnsport.h
+++ b/contrib/unbound/services/listen_dnsport.h
@@ -205,11 +205,12 @@ void listen_start_accept(struct listen_dnsport* listen);
* @param transparent: set IP_TRANSPARENT socket option.
* @param freebind: set IP_FREEBIND socket option.
* @param use_systemd: if true, fetch sockets from systemd.
+ * @param dscp: DSCP to use.
* @return: the socket. -1 on error.
*/
int create_udp_sock(int family, int socktype, struct sockaddr* addr,
socklen_t addrlen, int v6only, int* inuse, int* noproto, int rcv,
- int snd, int listen, int* reuseport, int transparent, int freebind, int use_systemd);
+ int snd, int listen, int* reuseport, int transparent, int freebind, int use_systemd, int dscp);
/**
* Create and bind TCP listening socket
@@ -222,10 +223,11 @@ int create_udp_sock(int family, int socktype, struct sockaddr* addr,
* @param mss: maximum segment size of the socket. if zero, leaves the default.
* @param freebind: set IP_FREEBIND socket option.
* @param use_systemd: if true, fetch sockets from systemd.
+ * @param dscp: DSCP to use.
* @return: the socket. -1 on error.
*/
int create_tcp_accept_sock(struct addrinfo *addr, int v6only, int* noproto,
- int* reuseport, int transparent, int mss, int freebind, int use_systemd);
+ int* reuseport, int transparent, int mss, int freebind, int use_systemd, int dscp);
/**
* Create and bind local listening socket
@@ -367,4 +369,7 @@ int tcp_req_info_handle_read_close(struct tcp_req_info* req);
/** get the size of currently used tcp stream wait buffers (in bytes) */
size_t tcp_req_info_get_stream_buffer_size(void);
+char* set_ip_dscp(int socket, int addrfamily, int ds);
+char* sock_strerror(int errn);
+
#endif /* LISTEN_DNSPORT_H */
diff --git a/contrib/unbound/services/localzone.c b/contrib/unbound/services/localzone.c
index 18407832ff41..6aaf0c05518c 100644
--- a/contrib/unbound/services/localzone.c
+++ b/contrib/unbound/services/localzone.c
@@ -518,7 +518,7 @@ local_zone_enter_rr(struct local_zone* z, uint8_t* nm, size_t nmlen,
}
/** enter data RR into auth zone */
-int
+static int
lz_enter_rr_into_zone(struct local_zone* z, const char* rrstr)
{
uint8_t* nm;
diff --git a/contrib/unbound/services/mesh.c b/contrib/unbound/services/mesh.c
index 9114ef4c4e2d..4b0c5db418f7 100644
--- a/contrib/unbound/services/mesh.c
+++ b/contrib/unbound/services/mesh.c
@@ -159,16 +159,28 @@ client_info_compare(const struct respip_client_info* ci_a,
return 1;
if(ci_a->taglen != ci_b->taglen)
return (ci_a->taglen < ci_b->taglen) ? -1 : 1;
- cmp = memcmp(ci_a->taglist, ci_b->taglist, ci_a->taglen);
- if(cmp != 0)
- return cmp;
+ if(ci_a->taglist && !ci_b->taglist)
+ return -1;
+ if(!ci_a->taglist && ci_b->taglist)
+ return 1;
+ if(ci_a->taglist && ci_b->taglist) {
+ cmp = memcmp(ci_a->taglist, ci_b->taglist, ci_a->taglen);
+ if(cmp != 0)
+ return cmp;
+ }
if(ci_a->tag_actions_size != ci_b->tag_actions_size)
return (ci_a->tag_actions_size < ci_b->tag_actions_size) ?
-1 : 1;
- cmp = memcmp(ci_a->tag_actions, ci_b->tag_actions,
- ci_a->tag_actions_size);
- if(cmp != 0)
- return cmp;
+ if(ci_a->tag_actions && !ci_b->tag_actions)
+ return -1;
+ if(!ci_a->tag_actions && ci_b->tag_actions)
+ return 1;
+ if(ci_a->tag_actions && ci_b->tag_actions) {
+ cmp = memcmp(ci_a->tag_actions, ci_b->tag_actions,
+ ci_a->tag_actions_size);
+ if(cmp != 0)
+ return cmp;
+ }
if(ci_a->tag_datas != ci_b->tag_datas)
return ci_a->tag_datas < ci_b->tag_datas ? -1 : 1;
if(ci_a->view != ci_b->view)
@@ -1284,7 +1296,7 @@ mesh_send_reply(struct mesh_state* m, int rcode, struct reply_info* rep,
void mesh_query_done(struct mesh_state* mstate)
{
- struct mesh_reply* r, *reply_list = NULL;
+ struct mesh_reply* r;
struct mesh_reply* prev = NULL;
struct sldns_buffer* prev_buffer = NULL;
struct mesh_cb* c;
@@ -1308,27 +1320,7 @@ void mesh_query_done(struct mesh_state* mstate)
free(err);
}
}
- if(mstate->reply_list) {
- /* set the reply_list to NULL during the mesh_query_done
- * processing, so that calls back into the mesh from
- * tcp_req_info (deciding to drop the reply and thus
- * unregister the mesh_reply from the mstate) are stopped
- * because the list is empty.
- * The mstate is then likely not a reply_state, and maybe
- * also a detached_state.
- */
- reply_list = mstate->reply_list;
- mstate->reply_list = NULL;
- if(!mstate->reply_list && !mstate->cb_list) {
- /* was a reply state, not anymore */
- log_assert(mstate->s.env->mesh->num_reply_states > 0);
- mstate->s.env->mesh->num_reply_states--;
- }
- if(!mstate->reply_list && !mstate->cb_list &&
- mstate->super_set.count == 0)
- mstate->s.env->mesh->num_detached_states++;
- }
- for(r = reply_list; r; r = r->next) {
+ for(r = mstate->reply_list; r; r = r->next) {
/* if a response-ip address block has been stored the
* information should be logged for each client. */
if(mstate->s.respip_action_info &&
@@ -1352,15 +1344,31 @@ void mesh_query_done(struct mesh_state* mstate)
/* if this query is determined to be dropped during the
* mesh processing, this is the point to take that action. */
if(mstate->s.is_drop) {
+ /* briefly set the reply_list to NULL, so that the
+ * tcp req info cleanup routine that calls the mesh
+ * to deregister the meshstate for it is not done
+ * because the list is NULL and also accounting is not
+ * done there, but instead we do that here. */
+ struct mesh_reply* reply_list = mstate->reply_list;
+ mstate->reply_list = NULL;
comm_point_drop_reply(&r->query_reply);
+ mstate->reply_list = reply_list;
} else {
struct sldns_buffer* r_buffer = r->query_reply.c->buffer;
+ struct mesh_reply* rlist = mstate->reply_list;
if(r->query_reply.c->tcp_req_info) {
r_buffer = r->query_reply.c->tcp_req_info->spool_buffer;
prev_buffer = NULL;
}
+ /* 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 */
+ mstate->reply_list = NULL;
mesh_send_reply(mstate, mstate->s.return_rcode, rep,
r, r_buffer, prev, prev_buffer);
+ mstate->reply_list = rlist;
if(r->query_reply.c->tcp_req_info) {
tcp_req_info_remove_mesh_state(r->query_reply.c->tcp_req_info, mstate);
r_buffer = NULL;
@@ -1369,6 +1377,17 @@ void mesh_query_done(struct mesh_state* mstate)
prev_buffer = r_buffer;
}
}
+ if(mstate->reply_list) {
+ mstate->reply_list = NULL;
+ if(!mstate->reply_list && !mstate->cb_list) {
+ /* was a reply state, not anymore */
+ log_assert(mstate->s.env->mesh->num_reply_states > 0);
+ mstate->s.env->mesh->num_reply_states--;
+ }
+ if(!mstate->reply_list && !mstate->cb_list &&
+ mstate->super_set.count == 0)
+ mstate->s.env->mesh->num_detached_states++;
+ }
mstate->replies_sent = 1;
while((c = mstate->cb_list) != NULL) {
/* take this cb off the list; so that the list can be
@@ -1863,7 +1882,7 @@ mesh_serve_expired_callback(void* arg)
{
struct mesh_state* mstate = (struct mesh_state*) arg;
struct module_qstate* qstate = &mstate->s;
- struct mesh_reply* r;
+ struct mesh_reply* r, *rlist;
struct mesh_area* mesh = qstate->env->mesh;
struct dns_msg* msg;
struct mesh_cb* c;
@@ -1946,16 +1965,7 @@ mesh_serve_expired_callback(void* arg)
if(verbosity >= VERB_ALGO)
log_dns_msg("Serve expired lookup", &qstate->qinfo, msg->rep);
- r = mstate->reply_list;
- mstate->reply_list = NULL;
- if(!mstate->reply_list && !mstate->cb_list) {
- log_assert(mesh->num_reply_states > 0);
- mesh->num_reply_states--;
- if(mstate->super_set.count == 0) {
- mesh->num_detached_states++;
- }
- }
- for(; r; r = r->next) {
+ for(r = mstate->reply_list; r; r = r->next) {
/* If address info is returned, it means the action should be an
* 'inform' variant and the information should be logged. */
if(actinfo.addrinfo) {
@@ -1977,8 +1987,15 @@ mesh_serve_expired_callback(void* arg)
r_buffer = r->query_reply.c->buffer;
if(r->query_reply.c->tcp_req_info)
r_buffer = r->query_reply.c->tcp_req_info->spool_buffer;
+ /* 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 */
+ rlist = mstate->reply_list;
+ mstate->reply_list = NULL;
mesh_send_reply(mstate, LDNS_RCODE_NOERROR, msg->rep,
r, r_buffer, prev, prev_buffer);
+ mstate->reply_list = rlist;
if(r->query_reply.c->tcp_req_info)
tcp_req_info_remove_mesh_state(r->query_reply.c->tcp_req_info, mstate);
prev = r;
@@ -1988,6 +2005,16 @@ mesh_serve_expired_callback(void* arg)
mesh->ans_expired++;
}
+ if(mstate->reply_list) {
+ mstate->reply_list = NULL;
+ if(!mstate->reply_list && !mstate->cb_list) {
+ log_assert(mesh->num_reply_states > 0);
+ mesh->num_reply_states--;
+ if(mstate->super_set.count == 0) {
+ mesh->num_detached_states++;
+ }
+ }
+ }
while((c = mstate->cb_list) != NULL) {
/* take this cb off the list; so that the list can be
* changed, eg. by adds from the callback routine */
diff --git a/contrib/unbound/services/modstack.c b/contrib/unbound/services/modstack.c
index 68e5928146dd..a600549b16c3 100644
--- a/contrib/unbound/services/modstack.c
+++ b/contrib/unbound/services/modstack.c
@@ -51,6 +51,9 @@
#ifdef WITH_PYTHONMODULE
#include "pythonmod/pythonmod.h"
#endif
+#ifdef WITH_DYNLIBMODULE
+#include "dynlibmod/dynlibmod.h"
+#endif
#ifdef USE_CACHEDB
#include "cachedb/cachedb.h"
#endif
@@ -140,6 +143,9 @@ module_list_avail(void)
#ifdef WITH_PYTHONMODULE
"python",
#endif
+#ifdef WITH_DYNLIBMODULE
+ "dynlib",
+#endif
#ifdef USE_CACHEDB
"cachedb",
#endif
@@ -171,6 +177,9 @@ module_funcs_avail(void)
#ifdef WITH_PYTHONMODULE
&pythonmod_get_funcblock,
#endif
+#ifdef WITH_DYNLIBMODULE
+ &dynlibmod_get_funcblock,
+#endif
#ifdef USE_CACHEDB
&cachedb_get_funcblock,
#endif
diff --git a/contrib/unbound/services/outside_network.c b/contrib/unbound/services/outside_network.c
index 80b1f12454d6..44e01d7450cb 100644
--- a/contrib/unbound/services/outside_network.c
+++ b/contrib/unbound/services/outside_network.c
@@ -205,18 +205,25 @@ pick_outgoing_tcp(struct waiting_tcp* w, int s)
/** get TCP file descriptor for address, returns -1 on failure,
* tcp_mss is 0 or maxseg size to set for TCP packets. */
int
-outnet_get_tcp_fd(struct sockaddr_storage* addr, socklen_t addrlen, int tcp_mss)
+outnet_get_tcp_fd(struct sockaddr_storage* addr, socklen_t addrlen, int tcp_mss, int dscp)
{
int s;
+ int af;
+ char* err;
#ifdef SO_REUSEADDR
int on = 1;
#endif
#ifdef INET6
- if(addr_is_ip6(addr, addrlen))
+ if(addr_is_ip6(addr, addrlen)){
s = socket(PF_INET6, SOCK_STREAM, IPPROTO_TCP);
- else
+ af = AF_INET6;
+ } else {
+#else
+ {
#endif
+ af = AF_INET;
s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
+ }
if(s == -1) {
#ifndef USE_WINSOCK
log_err_addr("outgoing tcp: socket", strerror(errno),
@@ -236,6 +243,12 @@ outnet_get_tcp_fd(struct sockaddr_storage* addr, socklen_t addrlen, int tcp_mss)
}
#endif
+ err = set_ip_dscp(s, af, dscp);
+ if(err != NULL) {
+ verbose(VERB_ALGO, "outgoing tcp:"
+ "error setting IP DiffServ codepoint on socket");
+ }
+
if(tcp_mss > 0) {
#if defined(IPPROTO_TCP) && defined(TCP_MAXSEG)
if(setsockopt(s, IPPROTO_TCP, TCP_MAXSEG,
@@ -291,7 +304,7 @@ outnet_tcp_take_into_use(struct waiting_tcp* w, uint8_t* pkt, size_t pkt_len)
log_assert(pkt);
log_assert(w->addrlen > 0);
/* open socket */
- s = outnet_get_tcp_fd(&w->addr, w->addrlen, w->outnet->tcp_mss);
+ s = outnet_get_tcp_fd(&w->addr, w->addrlen, w->outnet->tcp_mss, w->outnet->ip_dscp);
if(s == -1)
return 0;
@@ -373,45 +386,16 @@ outnet_tcp_take_into_use(struct waiting_tcp* w, uint8_t* pkt, size_t pkt_len)
comm_point_tcp_win_bio_cb(pend->c, pend->c->ssl);
#endif
pend->c->ssl_shake_state = comm_ssl_shake_write;
- if(w->tls_auth_name) {
+ if(!set_auth_name_on_ssl(pend->c->ssl, w->tls_auth_name,
+ w->outnet->tls_use_sni)) {
+ pend->c->fd = s;
#ifdef HAVE_SSL
- (void)SSL_set_tlsext_host_name(pend->c->ssl, w->tls_auth_name);
+ SSL_free(pend->c->ssl);
#endif
+ pend->c->ssl = NULL;
+ comm_point_close(pend->c);
+ return 0;
}
-#ifdef HAVE_SSL_SET1_HOST
- if(w->tls_auth_name) {
- SSL_set_verify(pend->c->ssl, SSL_VERIFY_PEER, NULL);
- /* setting the hostname makes openssl verify the
- * host name in the x509 certificate in the
- * SSL connection*/
- if(!SSL_set1_host(pend->c->ssl, w->tls_auth_name)) {
- log_err("SSL_set1_host failed");
- pend->c->fd = s;
- SSL_free(pend->c->ssl);
- pend->c->ssl = NULL;
- comm_point_close(pend->c);
- return 0;
- }
- }
-#elif defined(HAVE_X509_VERIFY_PARAM_SET1_HOST)
- /* openssl 1.0.2 has this function that can be used for
- * set1_host like verification */
- if(w->tls_auth_name) {
- X509_VERIFY_PARAM* param = SSL_get0_param(pend->c->ssl);
- X509_VERIFY_PARAM_set_hostflags(param, X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS);
- if(!X509_VERIFY_PARAM_set1_host(param, w->tls_auth_name, strlen(w->tls_auth_name))) {
- log_err("X509_VERIFY_PARAM_set1_host failed");
- pend->c->fd = s;
- SSL_free(pend->c->ssl);
- pend->c->ssl = NULL;
- comm_point_close(pend->c);
- return 0;
- }
- SSL_set_verify(pend->c->ssl, SSL_VERIFY_PEER, NULL);
- }
-#else
- verbose(VERB_ALGO, "the query has an auth_name, but libssl has no call to perform TLS authentication");
-#endif /* HAVE_SSL_SET1_HOST */
}
w->pkt = NULL;
w->next_waiting = (void*)pend;
@@ -512,7 +496,9 @@ portcomm_loweruse(struct outside_network* outnet, struct port_comm* pc)
comm_point_close(pc->cp);
pif = pc->pif;
log_assert(pif->inuse > 0);
+#ifndef DISABLE_EXPLICIT_PORT_RANDOMISATION
pif->avail_ports[pif->avail_total - pif->inuse] = pc->number;
+#endif
pif->inuse--;
pif->out[pc->index] = pif->out[pif->inuse];
pif->out[pc->index]->index = pc->index;
@@ -725,10 +711,12 @@ create_pending_tcp(struct outside_network* outnet, size_t bufsize)
static int setup_if(struct port_if* pif, const char* addrstr,
int* avail, int numavail, size_t numfd)
{
+#ifndef DISABLE_EXPLICIT_PORT_RANDOMISATION
pif->avail_total = numavail;
pif->avail_ports = (int*)memdup(avail, (size_t)numavail*sizeof(int));
if(!pif->avail_ports)
return 0;
+#endif
if(!ipstrtoaddr(addrstr, UNBOUND_DNS_PORT, &pif->addr, &pif->addrlen) &&
!netblockstrtoaddr(addrstr, UNBOUND_DNS_PORT,
&pif->addr, &pif->addrlen, &pif->pfxlen))
@@ -745,11 +733,11 @@ static int setup_if(struct port_if* pif, const char* addrstr,
struct outside_network*
outside_network_create(struct comm_base *base, size_t bufsize,
size_t num_ports, char** ifs, int num_ifs, int do_ip4,
- int do_ip6, size_t num_tcp, struct infra_cache* infra,
+ int do_ip6, size_t num_tcp, int dscp, struct infra_cache* infra,
struct ub_randstate* rnd, int use_caps_for_id, int* availports,
int numavailports, size_t unwanted_threshold, int tcp_mss,
void (*unwanted_action)(void*), void* unwanted_param, int do_udp,
- void* sslctx, int delayclose, struct dt_env* dtenv)
+ void* sslctx, int delayclose, int tls_use_sni, struct dt_env* dtenv)
{
struct outside_network* outnet = (struct outside_network*)
calloc(1, sizeof(struct outside_network));
@@ -765,6 +753,7 @@ outside_network_create(struct comm_base *base, size_t bufsize,
outnet->infra = infra;
outnet->rnd = rnd;
outnet->sslctx = sslctx;
+ outnet->tls_use_sni = tls_use_sni;
#ifdef USE_DNSTAP
outnet->dtenv = dtenv;
#else
@@ -778,6 +767,7 @@ outside_network_create(struct comm_base *base, size_t bufsize,
outnet->use_caps_for_id = use_caps_for_id;
outnet->do_udp = do_udp;
outnet->tcp_mss = tcp_mss;
+ outnet->ip_dscp = dscp;
#ifndef S_SPLINT_S
if(delayclose) {
outnet->delayclose = 1;
@@ -955,7 +945,9 @@ outside_network_delete(struct outside_network* outnet)
comm_point_delete(pc->cp);
free(pc);
}
+#ifndef DISABLE_EXPLICIT_PORT_RANDOMISATION
free(outnet->ip4_ifs[i].avail_ports);
+#endif
free(outnet->ip4_ifs[i].out);
}
free(outnet->ip4_ifs);
@@ -969,7 +961,9 @@ outside_network_delete(struct outside_network* outnet)
comm_point_delete(pc->cp);
free(pc);
}
+#ifndef DISABLE_EXPLICIT_PORT_RANDOMISATION
free(outnet->ip6_ifs[i].avail_ports);
+#endif
free(outnet->ip6_ifs[i].out);
}
free(outnet->ip6_ifs);
@@ -1059,11 +1053,12 @@ sai6_putrandom(struct sockaddr_in6 *sa, int pfxlen, struct ub_randstate *rnd)
* @param port: port override for addr.
* @param inuse: if -1 is returned, this bool means the port was in use.
* @param rnd: random state (for address randomisation).
+ * @param dscp: DSCP to use.
* @return fd or -1
*/
static int
udp_sockport(struct sockaddr_storage* addr, socklen_t addrlen, int pfxlen,
- int port, int* inuse, struct ub_randstate* rnd)
+ int port, int* inuse, struct ub_randstate* rnd, int dscp)
{
int fd, noproto;
if(addr_is_ip6(addr, addrlen)) {
@@ -1078,13 +1073,13 @@ udp_sockport(struct sockaddr_storage* addr, socklen_t addrlen, int pfxlen,
}
fd = create_udp_sock(AF_INET6, SOCK_DGRAM,
(struct sockaddr*)&sa, addrlen, 1, inuse, &noproto,
- 0, 0, 0, NULL, 0, freebind, 0);
+ 0, 0, 0, NULL, 0, freebind, 0, dscp);
} else {
struct sockaddr_in* sa = (struct sockaddr_in*)addr;
sa->sin_port = (in_port_t)htons((uint16_t)port);
fd = create_udp_sock(AF_INET, SOCK_DGRAM,
(struct sockaddr*)addr, addrlen, 1, inuse, &noproto,
- 0, 0, 0, NULL, 0, 0, 0);
+ 0, 0, 0, NULL, 0, 0, 0, dscp);
}
return fd;
}
@@ -1133,6 +1128,7 @@ select_ifport(struct outside_network* outnet, struct pending* pend,
while(1) {
my_if = ub_random_max(outnet->rnd, num_if);
pif = &ifs[my_if];
+#ifndef DISABLE_EXPLICIT_PORT_RANDOMISATION
my_port = ub_random_max(outnet->rnd, pif->avail_total);
if(my_port < pif->inuse) {
/* port already open */
@@ -1144,8 +1140,11 @@ select_ifport(struct outside_network* outnet, struct pending* pend,
/* try to open new port, if fails, loop to try again */
log_assert(pif->inuse < pif->maxout);
portno = pif->avail_ports[my_port - pif->inuse];
+#else
+ my_port = portno = 0;
+#endif
fd = udp_sockport(&pif->addr, pif->addrlen, pif->pfxlen,
- portno, &inuse, outnet->rnd);
+ portno, &inuse, outnet->rnd, outnet->ip_dscp);
if(fd == -1 && !inuse) {
/* nonrecoverable error making socket */
return 0;
@@ -1167,8 +1166,10 @@ select_ifport(struct outside_network* outnet, struct pending* pend,
/* grab port in interface */
pif->out[pif->inuse] = pend->pc;
+#ifndef DISABLE_EXPLICIT_PORT_RANDOMISATION
pif->avail_ports[my_port - pif->inuse] =
pif->avail_ports[pif->avail_total-pif->inuse-1];
+#endif
pif->inuse++;
break;
}
@@ -2192,10 +2193,11 @@ fd_for_dest(struct outside_network* outnet, struct sockaddr_storage* to_addr,
{
struct sockaddr_storage* addr;
socklen_t addrlen;
- int i, try, pnum;
+ int i, try, pnum, dscp;
struct port_if* pif;
/* create fd */
+ dscp = outnet->ip_dscp;
for(try = 0; try<1000; try++) {
int port = 0;
int freebind = 0;
@@ -2225,6 +2227,7 @@ fd_for_dest(struct outside_network* outnet, struct sockaddr_storage* to_addr,
}
addr = &pif->addr;
addrlen = pif->addrlen;
+#ifndef DISABLE_EXPLICIT_PORT_RANDOMISATION
pnum = ub_random_max(outnet->rnd, pif->avail_total);
if(pnum < pif->inuse) {
/* port already open */
@@ -2233,19 +2236,21 @@ fd_for_dest(struct outside_network* outnet, struct sockaddr_storage* to_addr,
/* unused ports in start part of array */
port = pif->avail_ports[pnum - pif->inuse];
}
-
+#else
+ pnum = port = 0;
+#endif
if(addr_is_ip6(to_addr, to_addrlen)) {
struct sockaddr_in6 sa = *(struct sockaddr_in6*)addr;
sa.sin6_port = (in_port_t)htons((uint16_t)port);
fd = create_udp_sock(AF_INET6, SOCK_DGRAM,
(struct sockaddr*)&sa, addrlen, 1, &inuse, &noproto,
- 0, 0, 0, NULL, 0, freebind, 0);
+ 0, 0, 0, NULL, 0, freebind, 0, dscp);
} else {
struct sockaddr_in* sa = (struct sockaddr_in*)addr;
sa->sin_port = (in_port_t)htons((uint16_t)port);
fd = create_udp_sock(AF_INET, SOCK_DGRAM,
(struct sockaddr*)addr, addrlen, 1, &inuse, &noproto,
- 0, 0, 0, NULL, 0, freebind, 0);
+ 0, 0, 0, NULL, 0, freebind, 0, dscp);
}
if(fd != -1) {
return fd;
@@ -2294,6 +2299,11 @@ setup_comm_ssl(struct comm_point* cp, struct outside_network* outnet,
#endif
cp->ssl_shake_state = comm_ssl_shake_write;
/* https verification */
+#ifdef HAVE_SSL
+ if(outnet->tls_use_sni) {
+ (void)SSL_set_tlsext_host_name(cp->ssl, host);
+ }
+#endif
#ifdef HAVE_SSL_SET1_HOST
if((SSL_CTX_get_verify_mode(outnet->sslctx)&SSL_VERIFY_PEER)) {
/* because we set SSL_VERIFY_PEER, in netevent in
@@ -2316,7 +2326,9 @@ setup_comm_ssl(struct comm_point* cp, struct outside_network* outnet,
* set1_host like verification */
if((SSL_CTX_get_verify_mode(outnet->sslctx)&SSL_VERIFY_PEER)) {
X509_VERIFY_PARAM* param = SSL_get0_param(cp->ssl);
+# ifdef X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS
X509_VERIFY_PARAM_set_hostflags(param, X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS);
+# endif
if(!X509_VERIFY_PARAM_set1_host(param, host, strlen(host))) {
log_err("X509_VERIFY_PARAM_set1_host failed");
return 0;
@@ -2335,7 +2347,7 @@ outnet_comm_point_for_tcp(struct outside_network* outnet,
sldns_buffer* query, int timeout, int ssl, char* host)
{
struct comm_point* cp;
- int fd = outnet_get_tcp_fd(to_addr, to_addrlen, outnet->tcp_mss);
+ int fd = outnet_get_tcp_fd(to_addr, to_addrlen, outnet->tcp_mss, outnet->ip_dscp);
if(fd == -1) {
return 0;
}
@@ -2397,7 +2409,7 @@ outnet_comm_point_for_http(struct outside_network* outnet,
{
/* cp calls cb with err=NETEVENT_DONE when transfer is done */
struct comm_point* cp;
- int fd = outnet_get_tcp_fd(to_addr, to_addrlen, outnet->tcp_mss);
+ int fd = outnet_get_tcp_fd(to_addr, to_addrlen, outnet->tcp_mss, outnet->ip_dscp);
if(fd == -1) {
return 0;
}
@@ -2455,7 +2467,10 @@ if_get_mem(struct port_if* pif)
{
size_t s;
int i;
- s = sizeof(*pif) + sizeof(int)*pif->avail_total +
+ s = sizeof(*pif) +
+#ifndef DISABLE_EXPLICIT_PORT_RANDOMISATION
+ sizeof(int)*pif->avail_total +
+#endif
sizeof(struct port_comm*)*pif->maxout;
for(i=0; i<pif->inuse; i++)
s += sizeof(*pif->out[i]) +
diff --git a/contrib/unbound/services/outside_network.h b/contrib/unbound/services/outside_network.h
index 3456a3da38b0..c8f6d5724a87 100644
--- a/contrib/unbound/services/outside_network.h
+++ b/contrib/unbound/services/outside_network.h
@@ -132,12 +132,16 @@ struct outside_network {
struct ub_randstate* rnd;
/** ssl context to create ssl wrapped TCP with DNS connections */
void* sslctx;
+ /** if SNI will be used for TLS connections */
+ int tls_use_sni;
#ifdef USE_DNSTAP
/** dnstap environment */
struct dt_env* dtenv;
#endif
/** maximum segment size of tcp socket */
int tcp_mss;
+ /** IP_TOS socket option requested on the sockets */
+ int ip_dscp;
/**
* Array of tcp pending used for outgoing TCP connections.
@@ -172,11 +176,13 @@ struct port_if {
* if 0, no randomisation. */
int pfxlen;
+#ifndef DISABLE_EXPLICIT_PORT_RANDOMISATION
/** the available ports array. These are unused.
* Only the first total-inuse part is filled. */
int* avail_ports;
/** the total number of available ports (size of the array) */
int avail_total;
+#endif
/** array of the commpoints currently in use.
* allocated for max number of fds, first part in use. */
@@ -399,6 +405,7 @@ struct serviced_query {
* @param do_ip4: service IP4.
* @param do_ip6: service IP6.
* @param num_tcp: number of outgoing tcp buffers to preallocate.
+ * @param dscp: DSCP to use.
* @param infra: pointer to infra cached used for serviced queries.
* @param rnd: stored to create random numbers for serviced queries.
* @param use_caps_for_id: enable to use 0x20 bits to encode id randomness.
@@ -412,16 +419,17 @@ struct serviced_query {
* @param sslctx: context to create outgoing connections with (if enabled).
* @param delayclose: if not 0, udp sockets are delayed before timeout closure.
* msec to wait on timeouted udp sockets.
+ * @param tls_use_sni: if SNI is used for TLS connections.
* @param dtenv: environment to send dnstap events with (if enabled).
* @return: the new structure (with no pending answers) or NULL on error.
*/
struct outside_network* outside_network_create(struct comm_base* base,
size_t bufsize, size_t num_ports, char** ifs, int num_ifs,
- int do_ip4, int do_ip6, size_t num_tcp, struct infra_cache* infra,
+ int do_ip4, int do_ip6, size_t num_tcp, int dscp, struct infra_cache* infra,
struct ub_randstate* rnd, int use_caps_for_id, int* availports,
int numavailports, size_t unwanted_threshold, int tcp_mss,
void (*unwanted_action)(void*), void* unwanted_param, int do_udp,
- void* sslctx, int delayclose, struct dt_env *dtenv);
+ void* sslctx, int delayclose, int tls_use_sni, struct dt_env *dtenv);
/**
* Delete outside_network structure.
@@ -540,7 +548,7 @@ size_t serviced_get_mem(struct serviced_query* sq);
/** get TCP file descriptor for address, returns -1 on failure,
* tcp_mss is 0 or maxseg size to set for TCP packets. */
-int outnet_get_tcp_fd(struct sockaddr_storage* addr, socklen_t addrlen, int tcp_mss);
+int outnet_get_tcp_fd(struct sockaddr_storage* addr, socklen_t addrlen, int tcp_mss, int dscp);
/**
* Create udp commpoint suitable for sending packets to the destination.
diff --git a/contrib/unbound/services/rpz.c b/contrib/unbound/services/rpz.c
index 643b20c91d20..105f238d0a6d 100644
--- a/contrib/unbound/services/rpz.c
+++ b/contrib/unbound/services/rpz.c
@@ -586,7 +586,7 @@ rpz_insert_response_ip_trigger(struct rpz* r, uint8_t* dname, size_t dnamelen,
}
int
-rpz_insert_rr(struct rpz* r, size_t aznamelen, uint8_t* dname,
+rpz_insert_rr(struct rpz* r, uint8_t* azname, size_t aznamelen, uint8_t* dname,
size_t dnamelen, uint16_t rr_type, uint16_t rr_class, uint32_t rr_ttl,
uint8_t* rdatawl, size_t rdatalen, uint8_t* rr, size_t rr_len)
{
@@ -596,9 +596,17 @@ rpz_insert_rr(struct rpz* r, size_t aznamelen, uint8_t* dname,
enum rpz_action a;
uint8_t* policydname;
+ if(!dname_subdomain_c(dname, azname)) {
+ log_err("RPZ: name of record to insert into RPZ is not a "
+ "subdomain of the configured name of the RPZ zone");
+ return 0;
+ }
+
log_assert(dnamelen >= aznamelen);
- if(!(policydname = calloc(1, (dnamelen-aznamelen)+1)))
+ if(!(policydname = calloc(1, (dnamelen-aznamelen)+1))) {
+ log_err("malloc error while inserting RPZ RR");
return 0;
+ }
a = rpz_rr_to_action(rr_type, rdatawl, rdatalen);
if(!(policydnamelen = strip_dname_origin(dname, dnamelen, aznamelen,
@@ -826,6 +834,8 @@ rpz_remove_qname_trigger(struct rpz* r, uint8_t* dname, size_t dnamelen,
delete_zone = rpz_data_delete_rr(z, dname,
dnamelen, rr_type, rdatawl, rdatalen);
else if(a != localzone_type_to_rpz_action(z->type)) {
+ lock_rw_unlock(&z->lock);
+ lock_rw_unlock(&r->local_zones->lock);
return;
}
lock_rw_unlock(&z->lock);
@@ -931,13 +941,16 @@ rpz_apply_qname_trigger(struct auth_zones* az, struct module_env* env,
struct regional* temp, struct comm_reply* repinfo,
uint8_t* taglist, size_t taglen, struct ub_server_stats* stats)
{
- struct rpz* r;
+ 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(r = az->rpz_first; r; r = r->next) {
+ for(a = az->rpz_first; a; a = a->rpz_az_next) {
+ lock_rw_rdlock(&a->lock);
+ r = a->rpz;
if(!r->taglist || taglist_intersect(r->taglist,
r->taglistlen, taglist, taglen)) {
z = rpz_find_zone(r, qinfo->qname, qinfo->qname_len,
@@ -955,13 +968,14 @@ rpz_apply_qname_trigger(struct auth_zones* az, struct module_env* env,
}
if(z)
break;
- }
+ }
+ lock_rw_unlock(&a->lock); /* not found in this auth_zone */
}
lock_rw_unlock(&az->rpz_lock);
if(!z)
- return 0;
+ return 0; /* not holding auth_zone.lock anymore */
-
+ log_assert(r);
if(r->action_override == RPZ_NO_OVERRIDE_ACTION)
lzt = z->type;
else
@@ -972,6 +986,7 @@ rpz_apply_qname_trigger(struct auth_zones* az, struct module_env* env,
regional_alloc_zero(temp, sizeof(struct local_rrset));
if(!qinfo->local_alias) {
lock_rw_unlock(&z->lock);
+ lock_rw_unlock(&a->lock);
return 0; /* out of memory */
}
qinfo->local_alias->rrset =
@@ -979,6 +994,7 @@ rpz_apply_qname_trigger(struct auth_zones* az, struct module_env* env,
sizeof(*r->cname_override));
if(!qinfo->local_alias->rrset) {
lock_rw_unlock(&z->lock);
+ lock_rw_unlock(&a->lock);
return 0; /* out of memory */
}
qinfo->local_alias->rrset->rk.dname = qinfo->qname;
@@ -988,6 +1004,7 @@ rpz_apply_qname_trigger(struct auth_zones* az, struct module_env* env,
qinfo, repinfo, r->log_name);
stats->rpz_action[RPZ_CNAME_OVERRIDE_ACTION]++;
lock_rw_unlock(&z->lock);
+ lock_rw_unlock(&a->lock);
return 0;
}
@@ -1000,6 +1017,7 @@ rpz_apply_qname_trigger(struct auth_zones* az, struct module_env* env,
repinfo, 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;
}
@@ -1010,6 +1028,7 @@ rpz_apply_qname_trigger(struct auth_zones* az, struct module_env* env,
qinfo, repinfo, r->log_name);
stats->rpz_action[localzone_type_to_rpz_action(lzt)]++;
lock_rw_unlock(&z->lock);
+ lock_rw_unlock(&a->lock);
return ret;
}
diff --git a/contrib/unbound/services/rpz.h b/contrib/unbound/services/rpz.h
index 676a4f2a8406..77a2db55ced4 100644
--- a/contrib/unbound/services/rpz.h
+++ b/contrib/unbound/services/rpz.h
@@ -86,7 +86,8 @@ enum rpz_action {
/**
* RPZ containing policies. Pointed to from corresponding auth-zone. Part of a
* linked list to keep configuration order. Iterating or changing the linked
- * list requires the rpz_lock from struct auth_zones.
+ * list requires the rpz_lock from struct auth_zones. Changing items in this
+ * struct require the lock from struct auth_zone.
*/
struct rpz {
struct local_zones* local_zones;
@@ -97,14 +98,13 @@ struct rpz {
struct ub_packed_rrset_key* cname_override;
int log;
char* log_name;
- struct rpz* next;
- struct rpz* prev;
struct regional* region;
};
/**
* Create policy from RR and add to this RPZ.
* @param r: the rpz to add the policy to.
+ * @param azname: dname of the auth-zone
* @param aznamelen: the length of the auth-zone name
* @param dname: dname of the RR
* @param dnamelen: length of the dname
@@ -117,7 +117,7 @@ struct rpz {
* @param rr_len: the length of the complete RR
* @return: 0 on error
*/
-int rpz_insert_rr(struct rpz* r, size_t aznamelen, uint8_t* dname,
+int rpz_insert_rr(struct rpz* r, uint8_t* azname, size_t aznamelen, uint8_t* dname,
size_t dnamelen, uint16_t rr_type, uint16_t rr_class, uint32_t rr_ttl,
uint8_t* rdatawl, size_t rdatalen, uint8_t* rr, size_t rr_len);
diff --git a/contrib/unbound/sldns/parseutil.c b/contrib/unbound/sldns/parseutil.c
index 82dbc0fe113e..3515d64c5d10 100644
--- a/contrib/unbound/sldns/parseutil.c
+++ b/contrib/unbound/sldns/parseutil.c
@@ -167,7 +167,7 @@ sldns_gmtime64_r(int64_t clock, struct tm *result)
static int64_t
sldns_serial_arithmetics_time(int32_t time, time_t now)
{
- int32_t offset = time - (int32_t) now;
+ int32_t offset = (int32_t)((uint32_t) time - (uint32_t) now);
return (int64_t) now + offset;
}
diff --git a/contrib/unbound/smallapp/unbound-anchor.c b/contrib/unbound/smallapp/unbound-anchor.c
index 7d4f493be394..18d6ad5000db 100644
--- a/contrib/unbound/smallapp/unbound-anchor.c
+++ b/contrib/unbound/smallapp/unbound-anchor.c
@@ -187,6 +187,7 @@ usage(void)
printf("-c file cert file, default %s\n", ROOT_CERT_FILE);
printf("-l list builtin key and cert on stdout\n");
printf("-u name server in https url, default %s\n", URLNAME);
+ printf("-S do not use SNI for the https connection\n");
printf("-x path pathname to xml in url, default %s\n", XMLNAME);
printf("-s path pathname to p7s in url, default %s\n", P7SNAME);
printf("-n name signer's subject emailAddress, default %s\n", P7SIGNER);
@@ -245,9 +246,7 @@ get_builtin_ds(void)
return
/* The anchors must start on a new line with ". IN DS and end with \n"[;]
* because the makedist script greps on the source here */
-/* anchor 19036 is from 2010 */
/* anchor 20326 is from 2017 */
-". IN DS 19036 8 2 49AAC11D7B6F6446702E54A1607371607A1A41855200FD2CE1CDDE32F24E8FB5\n"
". IN DS 20326 8 2 E06D44B80B8F1D39A95C0B0D7C65D08458E880409BBC683457104237C7F8EC8D\n";
}
@@ -765,7 +764,7 @@ setup_sslctx(void)
/** initiate TLS on a connection */
static SSL*
-TLS_initiate(SSL_CTX* sslctx, int fd)
+TLS_initiate(SSL_CTX* sslctx, int fd, const char* urlname, int use_sni)
{
X509* x;
int r;
@@ -781,6 +780,9 @@ TLS_initiate(SSL_CTX* sslctx, int fd)
SSL_free(ssl);
return NULL;
}
+ if(use_sni) {
+ (void)SSL_set_tlsext_host_name(ssl, urlname);
+ }
while(1) {
ERR_clear_error();
if( (r=SSL_do_handshake(ssl)) == 1)
@@ -1116,7 +1118,7 @@ read_http_result(SSL* ssl)
/** https to an IP addr, return BIO with pathname or NULL */
static BIO*
https_to_ip(struct ip_list* ip, const char* pathname, const char* urlname,
- struct ip_list* src)
+ struct ip_list* src, int use_sni)
{
int fd;
SSL* ssl;
@@ -1130,7 +1132,7 @@ https_to_ip(struct ip_list* ip, const char* pathname, const char* urlname,
SSL_CTX_free(sslctx);
return NULL;
}
- ssl = TLS_initiate(sslctx, fd);
+ ssl = TLS_initiate(sslctx, fd, urlname, use_sni);
if(!ssl) {
SSL_CTX_free(sslctx);
fd_close(fd);
@@ -1154,11 +1156,12 @@ https_to_ip(struct ip_list* ip, const char* pathname, const char* urlname,
* @param pathname: pathname of file on server to GET.
* @param urlname: name to pass as the virtual host for this request.
* @param src: if nonNULL, source address to bind to.
+ * @param use_sni: if SNI will be used.
* @return a memory BIO with the file in it.
*/
static BIO*
https(struct ip_list* ip_list, const char* pathname, const char* urlname,
- struct ip_list* src)
+ struct ip_list* src, int use_sni)
{
struct ip_list* ip;
BIO* bio = NULL;
@@ -1166,7 +1169,7 @@ https(struct ip_list* ip_list, const char* pathname, const char* urlname,
wipe_ip_usage(ip_list);
while( (ip = pick_random_ip(ip_list)) ) {
ip->used = 1;
- bio = https_to_ip(ip, pathname, urlname, src);
+ bio = https_to_ip(ip, pathname, urlname, src, use_sni);
if(bio) break;
}
if(!bio) {
@@ -1922,7 +1925,7 @@ do_certupdate(const char* root_anchor_file, const char* root_cert_file,
const char* urlname, const char* xmlname, const char* p7sname,
const char* p7signer, const char* res_conf, const char* root_hints,
const char* debugconf, const char* srcaddr, int ip4only, int ip6only,
- int port)
+ int port, int use_sni)
{
STACK_OF(X509)* cert;
@@ -1956,8 +1959,8 @@ do_certupdate(const char* root_anchor_file, const char* root_cert_file,
#endif
/* fetch the necessary files over HTTPS */
- xml = https(ip_list, xmlname, urlname, src);
- p7s = https(ip_list, p7sname, urlname, src);
+ xml = https(ip_list, xmlname, urlname, src, use_sni);
+ p7s = https(ip_list, p7sname, urlname, src, use_sni);
/* verify and update the root anchor */
verify_and_update_anchor(root_anchor_file, xml, p7s, cert, p7signer);
@@ -2228,7 +2231,7 @@ do_root_update_work(const char* root_anchor_file, const char* root_cert_file,
const char* urlname, const char* xmlname, const char* p7sname,
const char* p7signer, const char* res_conf, const char* root_hints,
const char* debugconf, const char* srcaddr, int ip4only, int ip6only,
- int force, int res_conf_fallback, int port)
+ int force, int res_conf_fallback, int port, int use_sni)
{
struct ub_result* dnskey;
int used_builtin = 0;
@@ -2271,7 +2274,7 @@ do_root_update_work(const char* root_anchor_file, const char* root_cert_file,
probe_date_allows_certupdate(root_anchor_file)) || force) {
if(do_certupdate(root_anchor_file, root_cert_file, urlname,
xmlname, p7sname, p7signer, res_conf, root_hints,
- debugconf, srcaddr, ip4only, ip6only, port))
+ debugconf, srcaddr, ip4only, ip6only, port, use_sni))
return 1;
return used_builtin;
}
@@ -2300,8 +2303,9 @@ int main(int argc, char* argv[])
const char* srcaddr = NULL;
int dolist=0, ip4only=0, ip6only=0, force=0, port = HTTPS_PORT;
int res_conf_fallback = 0;
+ int use_sni = 1;
/* parse the options */
- while( (c=getopt(argc, argv, "46C:FRP:a:b:c:f:hln:r:s:u:vx:")) != -1) {
+ while( (c=getopt(argc, argv, "46C:FRSP:a:b:c:f:hln:r:s:u:vx:")) != -1) {
switch(c) {
case 'l':
dolist = 1;
@@ -2324,6 +2328,9 @@ int main(int argc, char* argv[])
case 'u':
urlname = optarg;
break;
+ case 'S':
+ use_sni = 0;
+ break;
case 'x':
xmlname = optarg;
break;
@@ -2390,5 +2397,5 @@ int main(int argc, char* argv[])
return do_root_update_work(root_anchor_file, root_cert_file, urlname,
xmlname, p7sname, p7signer, res_conf, root_hints, debugconf,
- srcaddr, ip4only, ip6only, force, res_conf_fallback, port);
+ srcaddr, ip4only, ip6only, force, res_conf_fallback, port, use_sni);
}
diff --git a/contrib/unbound/smallapp/unbound-checkconf.c b/contrib/unbound/smallapp/unbound-checkconf.c
index 91ad54abd8db..eddd406a8067 100644
--- a/contrib/unbound/smallapp/unbound-checkconf.c
+++ b/contrib/unbound/smallapp/unbound-checkconf.c
@@ -58,6 +58,7 @@
#include "services/authzone.h"
#include "respip/respip.h"
#include "sldns/sbuffer.h"
+#include "sldns/str2wire.h"
#ifdef HAVE_GETOPT_H
#include <getopt.h>
#endif
@@ -194,6 +195,94 @@ localzonechecks(struct config_file* cfg)
local_zones_delete(zs);
}
+/** checks for acl and views */
+static void
+acl_view_tag_checks(struct config_file* cfg, struct views* views)
+{
+ int d;
+ struct sockaddr_storage a;
+ socklen_t alen;
+ struct config_str2list* acl;
+ struct config_str3list* s3;
+ struct config_strbytelist* sb;
+
+ /* acl_view */
+ for(acl=cfg->acl_view; acl; acl = acl->next) {
+ struct view* v;
+ if(!netblockstrtoaddr(acl->str, UNBOUND_DNS_PORT, &a, &alen,
+ &d)) {
+ fatal_exit("cannot parse access-control-view "
+ "address %s %s", acl->str, acl->str2);
+ }
+ v = views_find_view(views, acl->str2, 0);
+ if(!v) {
+ fatal_exit("cannot find view for "
+ "access-control-view: %s %s",
+ acl->str, acl->str2);
+ }
+ lock_rw_unlock(&v->lock);
+ }
+
+ /* acl_tags */
+ for(sb=cfg->acl_tags; sb; sb = sb->next) {
+ if(!netblockstrtoaddr(sb->str, UNBOUND_DNS_PORT, &a, &alen,
+ &d)) {
+ fatal_exit("cannot parse access-control-tags "
+ "address %s", sb->str);
+ }
+ }
+
+ /* acl_tag_actions */
+ for(s3=cfg->acl_tag_actions; s3; s3 = s3->next) {
+ enum localzone_type t;
+ if(!netblockstrtoaddr(s3->str, UNBOUND_DNS_PORT, &a, &alen,
+ &d)) {
+ fatal_exit("cannot parse access-control-tag-actions "
+ "address %s %s %s",
+ s3->str, s3->str2, s3->str3);
+ }
+ if(find_tag_id(cfg, s3->str2) == -1) {
+ fatal_exit("cannot parse tag %s (define-tag it), "
+ "for access-control-tag-actions: %s %s %s",
+ s3->str2, s3->str, s3->str2, s3->str3);
+ }
+ if(!local_zone_str2type(s3->str3, &t)) {
+ fatal_exit("cannot parse access control action type %s"
+ " for access-control-tag-actions: %s %s %s",
+ s3->str3, s3->str, s3->str2, s3->str3);
+ }
+ }
+
+ /* acl_tag_datas */
+ for(s3=cfg->acl_tag_datas; s3; s3 = s3->next) {
+ char buf[65536];
+ uint8_t rr[LDNS_RR_BUF_SIZE];
+ size_t len = sizeof(rr);
+ int res;
+ if(!netblockstrtoaddr(s3->str, UNBOUND_DNS_PORT, &a, &alen,
+ &d)) {
+ fatal_exit("cannot parse access-control-tag-datas address %s %s '%s'",
+ s3->str, s3->str2, s3->str3);
+ }
+ if(find_tag_id(cfg, s3->str2) == -1) {
+ fatal_exit("cannot parse tag %s (define-tag it), "
+ "for access-control-tag-datas: %s %s '%s'",
+ s3->str2, s3->str, s3->str2, s3->str3);
+ }
+ /* '.' is sufficient for validation, and it makes the call to
+ * sldns_wirerr_get_type() simpler below. */
+ snprintf(buf, sizeof(buf), "%s %s", ".", s3->str3);
+ res = sldns_str2wire_rr_buf(buf, rr, &len, NULL, 3600, NULL,
+ 0, NULL, 0);
+ if(res != 0) {
+ fatal_exit("cannot parse rr data [char %d] parse error %s, for access-control-tag-datas: %s %s '%s'",
+ (int)LDNS_WIREPARSE_OFFSET(res)-2,
+ sldns_get_errorstr_parse(res),
+ s3->str, s3->str2, s3->str3);
+ }
+ }
+}
+
/** check view and response-ip configuration */
static void
view_and_respipchecks(struct config_file* cfg)
@@ -211,6 +300,7 @@ view_and_respipchecks(struct config_file* cfg)
fatal_exit("Could not setup respip set");
if(!respip_views_apply_cfg(views, cfg, &ignored))
fatal_exit("Could not setup per-view respip sets");
+ acl_view_tag_checks(cfg, views);
views_delete(views);
respip_set_delete(respip);
}
@@ -481,6 +571,8 @@ morechecks(struct config_file* cfg)
fatal_exit("num_threads value weird");
if(!cfg->do_ip4 && !cfg->do_ip6)
fatal_exit("ip4 and ip6 are both disabled, pointless");
+ if(!cfg->do_ip4 && cfg->prefer_ip4)
+ fatal_exit("cannot prefer and disable ip4, pointless");
if(!cfg->do_ip6 && cfg->prefer_ip6)
fatal_exit("cannot prefer and disable ip6, pointless");
if(!cfg->do_udp && !cfg->do_tcp)
@@ -567,6 +659,64 @@ morechecks(struct config_file* cfg)
&& strcmp(cfg->module_conf, "python dns64 iterator") != 0
&& strcmp(cfg->module_conf, "python dns64 validator iterator") != 0
#endif
+#ifdef WITH_DYNLIBMODULE
+ && strcmp(cfg->module_conf, "dynlib iterator") != 0
+ && strcmp(cfg->module_conf, "dynlib dynlib iterator") != 0
+ && strcmp(cfg->module_conf, "dynlib dynlib dynlib iterator") != 0
+ && strcmp(cfg->module_conf, "python dynlib iterator") != 0
+ && strcmp(cfg->module_conf, "python dynlib dynlib iterator") != 0
+ && strcmp(cfg->module_conf, "python dynlib dynlib dynlib iterator") != 0
+ && strcmp(cfg->module_conf, "dynlib respip iterator") != 0
+ && strcmp(cfg->module_conf, "dynlib validator iterator") != 0
+ && strcmp(cfg->module_conf, "dynlib dynlib validator iterator") != 0
+ && strcmp(cfg->module_conf, "dynlib dynlib dynlib validator iterator") != 0
+ && strcmp(cfg->module_conf, "python dynlib validator iterator") != 0
+ && strcmp(cfg->module_conf, "python dynlib dynlib validator iterator") != 0
+ && strcmp(cfg->module_conf, "python dynlib dynlib dynlib validator iterator") != 0
+ && strcmp(cfg->module_conf, "dynlib respip validator iterator") != 0
+ && strcmp(cfg->module_conf, "validator dynlib iterator") != 0
+ && strcmp(cfg->module_conf, "dns64 dynlib iterator") != 0
+ && strcmp(cfg->module_conf, "dns64 dynlib validator iterator") != 0
+ && strcmp(cfg->module_conf, "dns64 validator dynlib iterator") != 0
+ && strcmp(cfg->module_conf, "dynlib dns64 iterator") != 0
+ && strcmp(cfg->module_conf, "dynlib dns64 validator iterator") != 0
+ && strcmp(cfg->module_conf, "dynlib dns64 cachedb iterator") != 0
+ && strcmp(cfg->module_conf, "dynlib dns64 validator cachedb iterator") != 0
+ && strcmp(cfg->module_conf, "dns64 dynlib cachedb iterator") != 0
+ && strcmp(cfg->module_conf, "dns64 dynlib validator cachedb iterator") != 0
+ && strcmp(cfg->module_conf, "dynlib cachedb iterator") != 0
+ && strcmp(cfg->module_conf, "dynlib respip cachedb iterator") != 0
+ && strcmp(cfg->module_conf, "dynlib validator cachedb iterator") != 0
+ && strcmp(cfg->module_conf, "dynlib respip validator cachedb iterator") != 0
+ && strcmp(cfg->module_conf, "cachedb dynlib iterator") != 0
+ && strcmp(cfg->module_conf, "respip cachedb dynlib iterator") != 0
+ && strcmp(cfg->module_conf, "validator cachedb dynlib iterator") != 0
+ && strcmp(cfg->module_conf, "respip validator cachedb dynlib iterator") != 0
+ && strcmp(cfg->module_conf, "validator dynlib cachedb iterator") != 0
+ && strcmp(cfg->module_conf, "respip validator dynlib cachedb iterator") != 0
+ && strcmp(cfg->module_conf, "dynlib subnetcache iterator") != 0
+ && strcmp(cfg->module_conf, "dynlib respip subnetcache iterator") != 0
+ && strcmp(cfg->module_conf, "subnetcache dynlib iterator") != 0
+ && strcmp(cfg->module_conf, "respip subnetcache dynlib iterator") != 0
+ && strcmp(cfg->module_conf, "dynlib subnetcache validator iterator") != 0
+ && strcmp(cfg->module_conf, "dynlib respip subnetcache validator iterator") != 0
+ && strcmp(cfg->module_conf, "subnetcache dynlib validator iterator") != 0
+ && strcmp(cfg->module_conf, "respip subnetcache dynlib validator iterator") != 0
+ && strcmp(cfg->module_conf, "subnetcache validator dynlib iterator") != 0
+ && strcmp(cfg->module_conf, "respip subnetcache validator dynlib iterator") != 0
+ && strcmp(cfg->module_conf, "dynlib ipsecmod iterator") != 0
+ && strcmp(cfg->module_conf, "dynlib ipsecmod respip iterator") != 0
+ && strcmp(cfg->module_conf, "ipsecmod dynlib iterator") != 0
+ && strcmp(cfg->module_conf, "ipsecmod dynlib respip iterator") != 0
+ && strcmp(cfg->module_conf, "ipsecmod validator iterator") != 0
+ && strcmp(cfg->module_conf, "ipsecmod respip validator iterator") != 0
+ && strcmp(cfg->module_conf, "dynlib ipsecmod validator iterator") != 0
+ && strcmp(cfg->module_conf, "dynlib ipsecmod respip validator iterator") != 0
+ && strcmp(cfg->module_conf, "ipsecmod dynlib validator iterator") != 0
+ && strcmp(cfg->module_conf, "ipsecmod dynlib respip validator iterator") != 0
+ && strcmp(cfg->module_conf, "ipsecmod validator dynlib iterator") != 0
+ && strcmp(cfg->module_conf, "ipsecmod respip validator dynlib iterator") != 0
+#endif
#ifdef USE_CACHEDB
&& strcmp(cfg->module_conf, "validator cachedb iterator") != 0
&& strcmp(cfg->module_conf, "respip validator cachedb iterator") != 0
@@ -598,6 +748,8 @@ morechecks(struct config_file* cfg)
&& strcmp(cfg->module_conf, "respip subnetcache validator iterator") != 0
&& strcmp(cfg->module_conf, "dns64 subnetcache iterator") != 0
&& strcmp(cfg->module_conf, "dns64 subnetcache validator iterator") != 0
+ && strcmp(cfg->module_conf, "dns64 subnetcache respip iterator") != 0
+ && strcmp(cfg->module_conf, "dns64 subnetcache respip validator iterator") != 0
#endif
#if defined(WITH_PYTHONMODULE) && defined(CLIENT_SUBNET)
&& strcmp(cfg->module_conf, "python subnetcache iterator") != 0
@@ -701,7 +853,7 @@ check_auth(struct config_file* cfg)
{
int is_rpz = 0;
struct auth_zones* az = auth_zones_create();
- if(!az || !auth_zones_apply_cfg(az, cfg, 0i, &is_rpz)) {
+ if(!az || !auth_zones_apply_cfg(az, cfg, 0, &is_rpz)) {
fatal_exit("Could not setup authority zones");
}
auth_zones_delete(az);
diff --git a/contrib/unbound/smallapp/unbound-control-setup.sh.in b/contrib/unbound/smallapp/unbound-control-setup.sh.in
index f4024b435530..3e506e84e236 100755
--- a/contrib/unbound/smallapp/unbound-control-setup.sh.in
+++ b/contrib/unbound/smallapp/unbound-control-setup.sh.in
@@ -5,22 +5,22 @@
# Copyright (c) 2008, 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
@@ -57,87 +57,144 @@ SVR_BASE=unbound_server
# base name for unbound-control keys
CTL_BASE=unbound_control
+# flag to recreate generated certificates
+RECREATE=0
+
# we want -rw-r----- access (say you run this as root: grp=yes (server), all=no).
umask 0027
# end of options
-# functions:
-error ( ) {
- echo "$0 fatal error: $1"
- exit 1
+set -eu
+
+cleanup() {
+ echo "removing artifacts"
+
+ rm -rf \
+ server.cnf \
+ client.cnf \
+ "${SVR_BASE}_trust.pem" \
+ "${CTL_BASE}_trust.pem" \
+ "${SVR_BASE}_trust.srl"
}
-# check arguments:
-while test $# -ne 0; do
- case $1 in
- -d)
- if test $# -eq 1; then error "need argument for -d"; fi
- DESTDIR="$2"
- shift
- ;;
- *)
- echo "unbound-control-setup.sh - setup SSL keys for unbound-control"
- echo " -d dir use directory to store keys and certificates."
- echo " default: $DESTDIR"
- echo "please run this command using the same user id that the "
- echo "unbound daemon uses, it needs read privileges."
- exit 1
- ;;
- esac
- shift
+fatal() {
+ printf "fatal error: $*\n" >/dev/stderr
+ exit 1
+}
+
+usage() {
+ cat <<EOF
+usage: $0 OPTIONS
+OPTIONS
+-d <dir> used directory to store keys and certificates (default: $DESTDIR)
+-h show help notice
+-r recreate certificates
+EOF
+}
+
+OPTIND=1
+while getopts 'd:hr' arg; do
+ case "$arg" in
+ d) DESTDIR="$OPTARG" ;;
+ h) usage; exit 1 ;;
+ r) RECREATE=1 ;;
+ ?) fatal "'$arg' unknown option" ;;
+ esac
done
+shift $((OPTIND - 1))
+
-# go!:
echo "setup in directory $DESTDIR"
-cd "$DESTDIR" || error "could not cd to $DESTDIR"
-
-# create certificate keys; do not recreate if they already exist.
-if test -f $SVR_BASE.key; then
- echo "$SVR_BASE.key exists"
-else
- echo "generating $SVR_BASE.key"
- openssl genrsa -out $SVR_BASE.key $BITS || error "could not genrsa"
+cd "$DESTDIR"
+
+trap cleanup INT
+
+# ===
+# Generate server certificate
+# ===
+
+# generate private key; do no recreate it if they already exist.
+if [ ! -f "$SVR_BASE.key" ]; then
+ openssl genrsa -out "$SVR_BASE.key" "$BITS"
fi
-if test -f $CTL_BASE.key; then
- echo "$CTL_BASE.key exists"
-else
- echo "generating $CTL_BASE.key"
- openssl genrsa -out $CTL_BASE.key $BITS || error "could not genrsa"
+
+cat >server.cnf <<EOF
+default_bits=$BITS
+default_md=$HASH
+prompt=no
+distinguished_name=req_distinguished_name
+[req_distinguished_name]
+commonName=$SERVERNAME
+EOF
+
+[ -f server.cnf ] || fatal "cannot create openssl configuration"
+
+if [ ! -f "$SVR_BASE.pem" -o $RECREATE -eq 1 ]; then
+ openssl req \
+ -new -x509 \
+ -key "$SVR_BASE.key" \
+ -config server.cnf \
+ -days "$DAYS" \
+ -out "$SVR_BASE.pem"
+
+ [ ! -f "SVR_BASE.pem" ] || fatal "cannot create server certificate"
fi
-# create self-signed cert for server
-echo "[req]" > request.cfg
-echo "default_bits=$BITS" >> request.cfg
-echo "default_md=$HASH" >> request.cfg
-echo "prompt=no" >> request.cfg
-echo "distinguished_name=req_distinguished_name" >> request.cfg
-echo "" >> request.cfg
-echo "[req_distinguished_name]" >> request.cfg
-echo "commonName=$SERVERNAME" >> request.cfg
+# ===
+# Generate client certificate
+# ===
-test -f request.cfg || error "could not create request.cfg"
+# generate private key; do no recreate it if they already exist.
+if [ ! -f "$CTL_BASE.key" ]; then
+ openssl genrsa -out "$CTL_BASE.key" "$BITS"
+fi
+
+cat >client.cnf <<EOF
+[req]
+default_bits=$BITS
+default_md=$HASH
+prompt=no
+distinguished_name=req_distinguished_name
+[req_distinguished_name]
+commonName=$CLIENTNAME
+EOF
+
+[ -f client.cnf ] || fatal "cannot create openssl configuration"
+
+if [ ! -f "$CTL_BASE.pem" -o $RECREATE -eq 1 ]; then
+ openssl x509 \
+ -addtrust serverAuth \
+ -in "$SVR_BASE.pem" \
+ -out "${SVR_BASE}_trust.pem"
+
+ openssl req \
+ -new \
+ -config client.cnf \
+ -key "$CTL_BASE.key" \
+ | openssl x509 \
+ -req \
+ -days "$DAYS" \
+ -CA "${SVR_BASE}_trust.pem" \
+ -CAkey "$SVR_BASE.key" \
+ -CAcreateserial \
+ -$HASH \
+ -out "$CTL_BASE.pem"
+
+ [ ! -f "CTL_BASE.pem" ] || fatal "cannot create signed client certificate"
+fi
+
+# remove unused permissions
+chmod o-rw \
+ "$SVR_BASE.pem" \
+ "$SVR_BASE.key" \
+ "$CTL_BASE.pem" \
+ "$CTL_BASE.key"
+
+cleanup
+
+echo "Setup success. Certificates created. Enable in unbound.conf file to use"
-echo "create $SVR_BASE.pem (self signed certificate)"
-openssl req -key $SVR_BASE.key -config request.cfg -new -x509 -days $DAYS -out $SVR_BASE.pem || error "could not create $SVR_BASE.pem"
-# create trusted usage pem
-openssl x509 -in $SVR_BASE.pem -addtrust serverAuth -out $SVR_BASE"_trust.pem"
-
-# create client request and sign it, piped
-echo "[req]" > request.cfg
-echo "default_bits=$BITS" >> request.cfg
-echo "default_md=$HASH" >> request.cfg
-echo "prompt=no" >> request.cfg
-echo "distinguished_name=req_distinguished_name" >> request.cfg
-echo "" >> request.cfg
-echo "[req_distinguished_name]" >> request.cfg
-echo "commonName=$CLIENTNAME" >> request.cfg
-
-test -f request.cfg || error "could not create request.cfg"
-
-echo "create $CTL_BASE.pem (signed client certificate)"
-openssl req -key $CTL_BASE.key -config request.cfg -new | openssl x509 -req -days $DAYS -CA $SVR_BASE"_trust.pem" -CAkey $SVR_BASE.key -CAcreateserial -$HASH -out $CTL_BASE.pem
-test -f $CTL_BASE.pem || error "could not create $CTL_BASE.pem"
# create trusted usage pem
# openssl x509 -in $CTL_BASE.pem -addtrust clientAuth -out $CTL_BASE"_trust.pem"
@@ -148,13 +205,3 @@ test -f $CTL_BASE.pem || error "could not create $CTL_BASE.pem"
# echo "empty password is used, simply click OK on the password dialog box."
# openssl pkcs12 -export -in $CTL_BASE"_trust.pem" -inkey $CTL_BASE.key -name "unbound remote control client cert" -out $CTL_BASE"_browser.pfx" -password "pass:" || error "could not create browser certificate"
-# set desired permissions
-chmod 0640 $SVR_BASE.pem $SVR_BASE.key $CTL_BASE.pem $CTL_BASE.key
-
-# remove crap
-rm -f request.cfg
-rm -f $CTL_BASE"_trust.pem" $SVR_BASE"_trust.pem" $SVR_BASE"_trust.srl"
-
-echo "Setup success. Certificates created. Enable in unbound.conf file to use"
-
-exit 0
diff --git a/contrib/unbound/smallapp/unbound-control.c b/contrib/unbound/smallapp/unbound-control.c
index ef96b18bf1b9..ce5f0e04d4c5 100644
--- a/contrib/unbound/smallapp/unbound-control.c
+++ b/contrib/unbound/smallapp/unbound-control.c
@@ -74,6 +74,10 @@
#include <sys/un.h>
#endif
+#ifdef HAVE_TARGETCONDITIONALS_H
+#include <TargetConditionals.h>
+#endif
+
static void usage(void) ATTR_NORETURN;
static void ssl_err(const char* s) ATTR_NORETURN;
static void ssl_path_err(const char* s, const char *path) ATTR_NORETURN;
@@ -264,6 +268,9 @@ static void print_mem(struct ub_shm_stat_info* shm_stat,
#ifdef USE_IPSECMOD
PR_LL("mem.mod.ipsecmod", shm_stat->mem.ipsecmod);
#endif
+#ifdef WITH_DYNLIBMODULE
+ PR_LL("mem.mod.dynlib", shm_stat->mem.dynlib);
+#endif
#ifdef USE_DNSCRYPT
PR_LL("mem.cache.dnscrypt_shared_secret",
shm_stat->mem.dnscrypt_shared_secret);
@@ -879,11 +886,16 @@ int main(int argc, char* argv[])
if(argc == 0)
usage();
if(argc >= 1 && strcmp(argv[0], "start")==0) {
+#if defined(TARGET_OS_TV) || defined(TARGET_OS_WATCH)
+ fatal_exit("could not exec unbound: %s",
+ strerror(ENOSYS));
+#else
if(execlp("unbound", "unbound", "-c", cfgfile,
(char*)NULL) < 0) {
fatal_exit("could not exec unbound: %s",
strerror(errno));
}
+#endif
}
if(argc >= 1 && strcmp(argv[0], "stats_shm")==0) {
print_stats_shm(cfgfile);
diff --git a/contrib/unbound/smallapp/worker_cb.c b/contrib/unbound/smallapp/worker_cb.c
index 6c3bd0049082..78d921a3c6e9 100644
--- a/contrib/unbound/smallapp/worker_cb.c
+++ b/contrib/unbound/smallapp/worker_cb.c
@@ -248,3 +248,19 @@ void remote_get_opt_ssl(char* ATTR_UNUSED(str), void* ATTR_UNUSED(arg))
{
log_assert(0);
}
+
+#ifdef USE_DNSTAP
+void dtio_tap_callback(int ATTR_UNUSED(fd), short ATTR_UNUSED(ev),
+ void* ATTR_UNUSED(arg))
+{
+ log_assert(0);
+}
+#endif
+
+#ifdef USE_DNSTAP
+void dtio_mainfdcallback(int ATTR_UNUSED(fd), short ATTR_UNUSED(ev),
+ void* ATTR_UNUSED(arg))
+{
+ log_assert(0);
+}
+#endif
diff --git a/contrib/unbound/util/config_file.c b/contrib/unbound/util/config_file.c
index e98b281a081f..f0d600617eef 100644
--- a/contrib/unbound/util/config_file.c
+++ b/contrib/unbound/util/config_file.c
@@ -116,6 +116,7 @@ config_create(void)
cfg->ssl_upstream = 0;
cfg->tls_cert_bundle = NULL;
cfg->tls_win_cert = 0;
+ cfg->tls_use_sni = 1;
cfg->use_syslog = 1;
cfg->log_identity = NULL; /* changed later with argv[0] */
cfg->log_time_ascii = 0;
@@ -186,6 +187,7 @@ config_create(void)
cfg->so_reuseport = REUSEPORT_DEFAULT;
cfg->ip_transparent = 0;
cfg->ip_freebind = 0;
+ cfg->ip_dscp = 0;
cfg->num_ifs = 0;
cfg->ifs = NULL;
cfg->num_out_ifs = 0;
@@ -266,13 +268,14 @@ config_create(void)
cfg->unblock_lan_zones = 0;
cfg->insecure_lan_zones = 0;
cfg->python_script = NULL;
+ cfg->dynlib_file = NULL;
cfg->remote_control_enable = 0;
cfg->control_ifs.first = NULL;
cfg->control_ifs.last = NULL;
cfg->control_port = UNBOUND_CONTROL_PORT;
cfg->control_use_cert = 1;
cfg->minimal_responses = 1;
- cfg->rrset_roundrobin = 0;
+ cfg->rrset_roundrobin = 1;
cfg->unknown_server_time_limit = 376;
cfg->max_udp_size = 4096;
if(!(cfg->server_key_file = strdup(RUN_DIR"/unbound_server.key")))
@@ -295,6 +298,8 @@ config_create(void)
if(!(cfg->dnstap_socket_path = strdup(DNSTAP_SOCKET_PATH)))
goto error_exit;
#endif
+ cfg->dnstap_bidirectional = 1;
+ cfg->dnstap_tls = 1;
cfg->disable_dnssec_lame_check = 0;
cfg->ip_ratelimit = 0;
cfg->ratelimit = 0;
@@ -335,6 +340,7 @@ config_create(void)
if(!(cfg->redis_server_host = strdup("127.0.0.1"))) goto error_exit;
cfg->redis_timeout = 100;
cfg->redis_server_port = 6379;
+ cfg->redis_expire_records = 0;
#endif /* USE_REDIS */
#endif /* USE_CACHEDB */
#ifdef USE_IPSET
@@ -504,6 +510,7 @@ int config_set_option(struct config_file* cfg, const char* opt,
else S_STRLIST_APPEND("tls-session-ticket-keys:", tls_session_ticket_keys)
else S_STR("tls-ciphers:", tls_ciphers)
else S_STR("tls-ciphersuites:", tls_ciphersuites)
+ else S_YNO("tls-use-sni:", tls_use_sni)
else S_YNO("interface-automatic:", if_automatic)
else S_YNO("use-systemd:", use_systemd)
else S_YNO("do-daemonize:", do_daemonize)
@@ -523,6 +530,7 @@ int config_set_option(struct config_file* cfg, const char* opt,
else S_YNO("so-reuseport:", so_reuseport)
else S_YNO("ip-transparent:", ip_transparent)
else S_YNO("ip-freebind:", ip_freebind)
+ else S_NUMBER_OR_ZERO("ip-dscp:", ip_dscp)
else S_MEMSIZE("rrset-cache-size:", rrset_cache_size)
else S_POW2("rrset-cache-slabs:", rrset_cache_slabs)
else S_YNO("prefetch:", prefetch)
@@ -622,6 +630,7 @@ int config_set_option(struct config_file* cfg, const char* opt,
else S_STR("control-cert-file:", control_cert_file)
else S_STR("module-config:", module_conf)
else S_STRLIST("python-script:", python_script)
+ else S_STRLIST("dynlib-file:", dynlib_file)
else S_YNO("disable-dnssec-lame-check:", disable_dnssec_lame_check)
#ifdef CLIENT_SUBNET
/* Can't set max subnet prefix here, since that value is used when
@@ -631,7 +640,15 @@ int config_set_option(struct config_file* cfg, const char* opt,
#endif
#ifdef USE_DNSTAP
else S_YNO("dnstap-enable:", dnstap)
+ else S_YNO("dnstap-bidirectional:", dnstap_bidirectional)
else S_STR("dnstap-socket-path:", dnstap_socket_path)
+ else S_STR("dnstap-ip:", dnstap_ip)
+ else S_YNO("dnstap-tls:", dnstap_tls)
+ else S_STR("dnstap-tls-server-name:", dnstap_tls_server_name)
+ else S_STR("dnstap-tls-cert-bundle:", dnstap_tls_cert_bundle)
+ else S_STR("dnstap-tls-client-key-file:", dnstap_tls_client_key_file)
+ else S_STR("dnstap-tls-client-cert-file:",
+ dnstap_tls_client_cert_file)
else S_YNO("dnstap-send-identity:", dnstap_send_identity)
else S_YNO("dnstap-send-version:", dnstap_send_version)
else S_STR("dnstap-identity:", dnstap_identity)
@@ -915,6 +932,7 @@ config_get_option(struct config_file* cfg, const char* opt,
else O_YNO(opt, "so-reuseport", so_reuseport)
else O_YNO(opt, "ip-transparent", ip_transparent)
else O_YNO(opt, "ip-freebind", ip_freebind)
+ else O_DEC(opt, "ip-dscp", ip_dscp)
else O_MEM(opt, "rrset-cache-size", rrset_cache_size)
else O_DEC(opt, "rrset-cache-slabs", rrset_cache_slabs)
else O_YNO(opt, "prefetch-key", prefetch_key)
@@ -949,6 +967,7 @@ config_get_option(struct config_file* cfg, const char* opt,
else O_LST(opt, "tls-session-ticket-keys", tls_session_ticket_keys.first)
else O_STR(opt, "tls-ciphers", tls_ciphers)
else O_STR(opt, "tls-ciphersuites", tls_ciphersuites)
+ else O_YNO(opt, "tls-use-sni", tls_use_sni)
else O_YNO(opt, "use-systemd", use_systemd)
else O_YNO(opt, "do-daemonize", do_daemonize)
else O_STR(opt, "chroot", chrootdir)
@@ -1038,7 +1057,16 @@ config_get_option(struct config_file* cfg, const char* opt,
#endif
#ifdef USE_DNSTAP
else O_YNO(opt, "dnstap-enable", dnstap)
+ else O_YNO(opt, "dnstap-bidirectional", dnstap_bidirectional)
else O_STR(opt, "dnstap-socket-path", dnstap_socket_path)
+ else O_STR(opt, "dnstap-ip", dnstap_ip)
+ else O_YNO(opt, "dnstap-tls", dnstap_tls)
+ else O_STR(opt, "dnstap-tls-server-name", dnstap_tls_server_name)
+ else O_STR(opt, "dnstap-tls-cert-bundle", dnstap_tls_cert_bundle)
+ else O_STR(opt, "dnstap-tls-client-key-file",
+ dnstap_tls_client_key_file)
+ else O_STR(opt, "dnstap-tls-client-cert-file",
+ dnstap_tls_client_cert_file)
else O_YNO(opt, "dnstap-send-identity", dnstap_send_identity)
else O_YNO(opt, "dnstap-send-version", dnstap_send_version)
else O_STR(opt, "dnstap-identity", dnstap_identity)
@@ -1076,6 +1104,7 @@ config_get_option(struct config_file* cfg, const char* opt,
else O_YNO(opt, "insecure-lan-zones", insecure_lan_zones)
else O_DEC(opt, "max-udp-size", max_udp_size)
else O_LST(opt, "python-script", python_script)
+ else O_LST(opt, "dynlib-file", dynlib_file)
else O_YNO(opt, "disable-dnssec-lame-check", disable_dnssec_lame_check)
else O_DEC(opt, "ip-ratelimit", ip_ratelimit)
else O_DEC(opt, "ratelimit", ratelimit)
@@ -1116,6 +1145,7 @@ config_get_option(struct config_file* cfg, const char* opt,
else O_STR(opt, "redis-server-host", redis_server_host)
else O_DEC(opt, "redis-server-port", redis_server_port)
else O_DEC(opt, "redis-timeout", redis_timeout)
+ else O_YNO(opt, "redis-expire-records", redis_expire_records)
#endif /* USE_REDIS */
#endif /* USE_CACHEDB */
#ifdef USE_IPSET
@@ -1458,11 +1488,17 @@ config_delete(struct config_file* cfg)
free(cfg->dns64_prefix);
config_delstrlist(cfg->dns64_ignore_aaaa);
free(cfg->dnstap_socket_path);
+ free(cfg->dnstap_ip);
+ free(cfg->dnstap_tls_server_name);
+ free(cfg->dnstap_tls_cert_bundle);
+ free(cfg->dnstap_tls_client_key_file);
+ free(cfg->dnstap_tls_client_cert_file);
free(cfg->dnstap_identity);
free(cfg->dnstap_version);
config_deldblstrlist(cfg->ratelimit_for_domain);
config_deldblstrlist(cfg->ratelimit_below_domain);
config_delstrlist(cfg->python_script);
+ config_delstrlist(cfg->dynlib_file);
#ifdef USE_IPSECMOD
free(cfg->ipsecmod_hook);
config_delstrlist(cfg->ipsecmod_whitelist);
@@ -1509,6 +1545,11 @@ int
cfg_mark_ports(const char* str, int allow, int* avail, int num)
{
char* mid = strchr(str, '-');
+#ifdef DISABLE_EXPLICIT_PORT_RANDOMISATION
+ log_warn("Explicit port randomisation disabled, ignoring "
+ "outgoing-port-permit and outgoing-port-avoid configuration "
+ "options");
+#endif
if(!mid) {
int port = atoi(str);
if(port == 0 && strcmp(str, "0") != 0) {
diff --git a/contrib/unbound/util/config_file.h b/contrib/unbound/util/config_file.h
index 8739ca2ae1e8..66e5025d05b2 100644
--- a/contrib/unbound/util/config_file.h
+++ b/contrib/unbound/util/config_file.h
@@ -85,6 +85,8 @@ struct config_file {
int do_ip4;
/** do ip6 query support. */
int do_ip6;
+ /** prefer ip4 upstream queries. */
+ int prefer_ip4;
/** prefer ip6 upstream queries. */
int prefer_ip6;
/** do udp query support. */
@@ -126,6 +128,8 @@ struct config_file {
char* tls_ciphers;
/** TLS chiphersuites (TLSv1.3) */
char* tls_ciphersuites;
+ /** if SNI is to be used */
+ int tls_use_sni;
/** outgoing port range number of ports (per thread) */
int outgoing_num_ports;
@@ -186,6 +190,8 @@ struct config_file {
int ip_transparent;
/** IP_FREEBIND socket option request on port 53 sockets */
int ip_freebind;
+ /** IP_TOS socket option requested on port 53 sockets */
+ int ip_dscp;
/** number of interfaces to open. If 0 default all interfaces. */
int num_ifs;
@@ -444,6 +450,9 @@ struct config_file {
/** Python script file */
struct config_strlist* python_script;
+ /** Dynamic library file */
+ struct config_strlist* dynlib_file;
+
/** Use systemd socket activation. */
int use_systemd;
@@ -472,8 +481,22 @@ struct config_file {
/** true to enable dnstap support */
int dnstap;
+ /** using bidirectional frame streams if true */
+ int dnstap_bidirectional;
/** dnstap socket path */
char* dnstap_socket_path;
+ /** dnstap IP */
+ char* dnstap_ip;
+ /** dnstap TLS enable */
+ int dnstap_tls;
+ /** dnstap tls server authentication name */
+ char* dnstap_tls_server_name;
+ /** dnstap server cert bundle */
+ char* dnstap_tls_cert_bundle;
+ /** dnstap client key for client authentication */
+ char* dnstap_tls_client_key_file;
+ /** dnstap client cert for client authentication */
+ char* dnstap_tls_client_cert_file;
/** true to send "identity" via dnstap */
int dnstap_send_identity;
/** true to send "version" via dnstap */
@@ -582,6 +605,8 @@ struct config_file {
int redis_server_port;
/** timeout (in ms) for communication with the redis server */
int redis_timeout;
+ /** set timeout on redis records based on DNS response ttl */
+ int redis_expire_records;
#endif
#endif
diff --git a/contrib/unbound/util/configlexer.lex b/contrib/unbound/util/configlexer.lex
index 148135153f9e..f548e7324f34 100644
--- a/contrib/unbound/util/configlexer.lex
+++ b/contrib/unbound/util/configlexer.lex
@@ -46,11 +46,13 @@ struct inc_state {
int line;
YY_BUFFER_STATE buffer;
struct inc_state* next;
+ int inc_toplevel;
};
static struct inc_state* config_include_stack = NULL;
static int inc_depth = 0;
static int inc_prev = 0;
static int num_args = 0;
+static int inc_toplevel = 0;
void init_cfg_parse(void)
{
@@ -58,14 +60,15 @@ void init_cfg_parse(void)
inc_depth = 0;
inc_prev = 0;
num_args = 0;
+ inc_toplevel = 0;
}
-static void config_start_include(const char* filename)
+static void config_start_include(const char* filename, int toplevel)
{
FILE *input;
struct inc_state* s;
char* nm;
- if(inc_depth++ > 100000) {
+ if(inc_depth+1 > 100000) {
ub_c_error_msg("too many include files");
return;
}
@@ -97,17 +100,20 @@ static void config_start_include(const char* filename)
return;
}
LEXOUT(("switch_to_include_file(%s)\n", filename));
+ inc_depth++;
s->filename = cfg_parser->filename;
s->line = cfg_parser->line;
s->buffer = YY_CURRENT_BUFFER;
+ s->inc_toplevel = inc_toplevel;
s->next = config_include_stack;
config_include_stack = s;
cfg_parser->filename = nm;
cfg_parser->line = 1;
+ inc_toplevel = toplevel;
yy_switch_to_buffer(yy_create_buffer(input, YY_BUF_SIZE));
}
-static void config_start_include_glob(const char* filename)
+static void config_start_include_glob(const char* filename, int toplevel)
{
/* check for wildcards */
@@ -140,19 +146,19 @@ static void config_start_include_glob(const char* filename)
globfree(&g);
if(r == GLOB_NOMATCH)
return; /* no matches for pattern */
- config_start_include(filename); /* let original deal with it */
+ config_start_include(filename, toplevel); /* let original deal with it */
return;
}
/* process files found, if any */
for(i=(int)g.gl_pathc-1; i>=0; i--) {
- config_start_include(g.gl_pathv[i]);
+ config_start_include(g.gl_pathv[i], toplevel);
}
globfree(&g);
return;
}
#endif /* HAVE_GLOB */
- config_start_include(filename);
+ config_start_include(filename, toplevel);
}
static void config_end_include(void)
@@ -166,6 +172,7 @@ static void config_end_include(void)
yy_delete_buffer(YY_CURRENT_BUFFER);
yy_switch_to_buffer(s->buffer);
config_include_stack = s->next;
+ inc_toplevel = s->inc_toplevel;
free(s);
}
@@ -200,7 +207,7 @@ COLON \:
DQANY [^\"\n\r\\]|\\.
SQANY [^\'\n\r\\]|\\.
-%x quotedstring singlequotedstr include include_quoted val
+%x quotedstring singlequotedstr include include_quoted val include_toplevel include_toplevel_quoted
%%
<INITIAL,val>{SPACE}* {
@@ -221,6 +228,7 @@ outgoing-num-tcp{COLON} { YDVAR(1, VAR_OUTGOING_NUM_TCP) }
incoming-num-tcp{COLON} { YDVAR(1, VAR_INCOMING_NUM_TCP) }
do-ip4{COLON} { YDVAR(1, VAR_DO_IP4) }
do-ip6{COLON} { YDVAR(1, VAR_DO_IP6) }
+prefer-ip4{COLON} { YDVAR(1, VAR_PREFER_IP4) }
prefer-ip6{COLON} { YDVAR(1, VAR_PREFER_IP6) }
do-udp{COLON} { YDVAR(1, VAR_DO_UDP) }
do-tcp{COLON} { YDVAR(1, VAR_DO_TCP) }
@@ -248,6 +256,7 @@ tls-additional-port{COLON} { YDVAR(1, VAR_TLS_ADDITIONAL_PORT) }
tls-session-ticket-keys{COLON} { YDVAR(1, VAR_TLS_SESSION_TICKET_KEYS) }
tls-ciphers{COLON} { YDVAR(1, VAR_TLS_CIPHERS) }
tls-ciphersuites{COLON} { YDVAR(1, VAR_TLS_CIPHERSUITES) }
+tls-use-sni{COLON} { YDVAR(1, VAR_TLS_USE_SNI) }
use-systemd{COLON} { YDVAR(1, VAR_USE_SYSTEMD) }
do-daemonize{COLON} { YDVAR(1, VAR_DO_DAEMONIZE) }
interface{COLON} { YDVAR(1, VAR_INTERFACE) }
@@ -259,6 +268,7 @@ so-sndbuf{COLON} { YDVAR(1, VAR_SO_SNDBUF) }
so-reuseport{COLON} { YDVAR(1, VAR_SO_REUSEPORT) }
ip-transparent{COLON} { YDVAR(1, VAR_IP_TRANSPARENT) }
ip-freebind{COLON} { YDVAR(1, VAR_IP_FREEBIND) }
+ip-dscp{COLON} { YDVAR(1, VAR_IP_DSCP) }
chroot{COLON} { YDVAR(1, VAR_CHROOT) }
username{COLON} { YDVAR(1, VAR_USERNAME) }
directory{COLON} { YDVAR(1, VAR_DIRECTORY) }
@@ -413,6 +423,8 @@ control-key-file{COLON} { YDVAR(1, VAR_CONTROL_KEY_FILE) }
control-cert-file{COLON} { YDVAR(1, VAR_CONTROL_CERT_FILE) }
python-script{COLON} { YDVAR(1, VAR_PYTHON_SCRIPT) }
python{COLON} { YDVAR(0, VAR_PYTHON) }
+dynlib-file{COLON} { YDVAR(1, VAR_DYNLIB_FILE) }
+dynlib{COLON} { YDVAR(0, VAR_DYNLIB) }
domain-insecure{COLON} { YDVAR(1, VAR_DOMAIN_INSECURE) }
minimal-responses{COLON} { YDVAR(1, VAR_MINIMAL_RESPONSES) }
rrset-roundrobin{COLON} { YDVAR(1, VAR_RRSET_ROUNDROBIN) }
@@ -430,7 +442,16 @@ access-control-view{COLON} { YDVAR(2, VAR_ACCESS_CONTROL_VIEW) }
local-zone-override{COLON} { YDVAR(3, VAR_LOCAL_ZONE_OVERRIDE) }
dnstap{COLON} { YDVAR(0, VAR_DNSTAP) }
dnstap-enable{COLON} { YDVAR(1, VAR_DNSTAP_ENABLE) }
+dnstap-bidirectional{COLON} { YDVAR(1, VAR_DNSTAP_BIDIRECTIONAL) }
dnstap-socket-path{COLON} { YDVAR(1, VAR_DNSTAP_SOCKET_PATH) }
+dnstap-ip{COLON} { YDVAR(1, VAR_DNSTAP_IP) }
+dnstap-tls{COLON} { YDVAR(1, VAR_DNSTAP_TLS) }
+dnstap-tls-server-name{COLON} { YDVAR(1, VAR_DNSTAP_TLS_SERVER_NAME) }
+dnstap-tls-cert-bundle{COLON} { YDVAR(1, VAR_DNSTAP_TLS_CERT_BUNDLE) }
+dnstap-tls-client-key-file{COLON} {
+ YDVAR(1, VAR_DNSTAP_TLS_CLIENT_KEY_FILE) }
+dnstap-tls-client-cert-file{COLON} {
+ YDVAR(1, VAR_DNSTAP_TLS_CLIENT_CERT_FILE) }
dnstap-send-identity{COLON} { YDVAR(1, VAR_DNSTAP_SEND_IDENTITY) }
dnstap-send-version{COLON} { YDVAR(1, VAR_DNSTAP_SEND_VERSION) }
dnstap-identity{COLON} { YDVAR(1, VAR_DNSTAP_IDENTITY) }
@@ -491,6 +512,7 @@ secret-seed{COLON} { YDVAR(1, VAR_CACHEDB_SECRETSEED) }
redis-server-host{COLON} { YDVAR(1, VAR_CACHEDB_REDISHOST) }
redis-server-port{COLON} { YDVAR(1, VAR_CACHEDB_REDISPORT) }
redis-timeout{COLON} { YDVAR(1, VAR_CACHEDB_REDISTIMEOUT) }
+redis-expire-records{COLON} { YDVAR(1, VAR_CACHEDB_REDISEXPIRERECORDS) }
ipset{COLON} { YDVAR(0, VAR_IPSET) }
name-v4{COLON} { YDVAR(1, VAR_IPSET_NAME_V4) }
name-v6{COLON} { YDVAR(1, VAR_IPSET_NAME_V6) }
@@ -552,7 +574,7 @@ tcp-connection-limit{COLON} { YDVAR(2, VAR_TCP_CONNECTION_LIMIT) }
<include>\" { LEXOUT(("IQS ")); BEGIN(include_quoted); }
<include>{UNQUOTEDLETTER}* {
LEXOUT(("Iunquotedstr(%s) ", ub_c_text));
- config_start_include_glob(ub_c_text);
+ config_start_include_glob(ub_c_text, 0);
BEGIN(inc_prev);
}
<include_quoted><<EOF>> {
@@ -565,7 +587,7 @@ tcp-connection-limit{COLON} { YDVAR(2, VAR_TCP_CONNECTION_LIMIT) }
<include_quoted>\" {
LEXOUT(("IQE "));
ub_c_text[ub_c_leng - 1] = '\0';
- config_start_include_glob(ub_c_text);
+ config_start_include_glob(ub_c_text,0);
BEGIN(inc_prev);
}
<INITIAL,val><<EOF>> {
@@ -574,11 +596,48 @@ tcp-connection-limit{COLON} { YDVAR(2, VAR_TCP_CONNECTION_LIMIT) }
if (!config_include_stack) {
yyterminate();
} else {
+ fclose(yyin);
+ int prev_toplevel = inc_toplevel;
fclose(ub_c_in);
config_end_include();
+ if(prev_toplevel) return (VAR_FORCE_TOPLEVEL);
}
}
+ /* include-toplevel: directive */
+<INITIAL,val>include-toplevel{COLON} {
+ LEXOUT(("v(%s) ", ub_c_text)); inc_prev = YYSTATE; BEGIN(include_toplevel);
+}
+<include_toplevel><<EOF>> {
+ ub_c_error("EOF inside include_toplevel directive");
+ BEGIN(inc_prev);
+}
+<include_toplevel>{SPACE}* { LEXOUT(("ITSP ")); /* ignore */ }
+<include_toplevel>{NEWLINE} { LEXOUT(("NL\n")); cfg_parser->line++; }
+<include_toplevel>\" { LEXOUT(("ITQS ")); BEGIN(include_toplevel_quoted); }
+<include_toplevel>{UNQUOTEDLETTER}* {
+ LEXOUT(("ITunquotedstr(%s) ", ub_c_text));
+ config_start_include_glob(ub_c_text, 1);
+ BEGIN(inc_prev);
+ return (VAR_FORCE_TOPLEVEL);
+}
+<include_toplevel_quoted><<EOF>> {
+ ub_c_error("EOF inside quoted string");
+ BEGIN(inc_prev);
+}
+<include_toplevel_quoted>{DQANY}* { LEXOUT(("ITSTR(%s) ", ub_c_text)); yymore(); }
+<include_toplevel_quoted>{NEWLINE} {
+ ub_c_error("newline before \" in include name");
+ cfg_parser->line++; BEGIN(inc_prev);
+}
+<include_toplevel_quoted>\" {
+ LEXOUT(("ITQE "));
+ ub_c_text[yyleng - 1] = '\0';
+ config_start_include_glob(ub_c_text, 1);
+ BEGIN(inc_prev);
+ return (VAR_FORCE_TOPLEVEL);
+}
+
<val>{UNQUOTEDLETTER}* { LEXOUT(("unquotedstr(%s) ", ub_c_text));
if(--num_args == 0) { BEGIN(INITIAL); }
ub_c_lval.str = strdup(ub_c_text); return STRING_ARG; }
diff --git a/contrib/unbound/util/configparser.y b/contrib/unbound/util/configparser.y
index 798f4a972fd8..fe600a999d45 100644
--- a/contrib/unbound/util/configparser.y
+++ b/contrib/unbound/util/configparser.y
@@ -69,8 +69,9 @@ extern struct config_parser_state* cfg_parser;
%token SPACE LETTER NEWLINE COMMENT COLON ANY ZONESTR
%token <str> STRING_ARG
+%token VAR_FORCE_TOPLEVEL
%token VAR_SERVER VAR_VERBOSITY VAR_NUM_THREADS VAR_PORT
-%token VAR_OUTGOING_RANGE VAR_INTERFACE
+%token VAR_OUTGOING_RANGE VAR_INTERFACE VAR_PREFER_IP4
%token VAR_DO_IP4 VAR_DO_IP6 VAR_PREFER_IP6 VAR_DO_UDP VAR_DO_TCP
%token VAR_TCP_MSS VAR_OUTGOING_TCP_MSS VAR_TCP_IDLE_TIMEOUT
%token VAR_EDNS_TCP_KEEPALIVE VAR_EDNS_TCP_KEEPALIVE_TIMEOUT
@@ -116,8 +117,10 @@ extern struct config_parser_state* cfg_parser;
%token VAR_UNBLOCK_LAN_ZONES VAR_INSECURE_LAN_ZONES
%token VAR_INFRA_CACHE_MIN_RTT
%token VAR_DNS64_PREFIX VAR_DNS64_SYNTHALL VAR_DNS64_IGNORE_AAAA
-%token VAR_DNSTAP VAR_DNSTAP_ENABLE VAR_DNSTAP_SOCKET_PATH
-%token VAR_DNSTAP_SEND_IDENTITY VAR_DNSTAP_SEND_VERSION
+%token VAR_DNSTAP VAR_DNSTAP_ENABLE VAR_DNSTAP_SOCKET_PATH VAR_DNSTAP_IP
+%token VAR_DNSTAP_TLS VAR_DNSTAP_TLS_SERVER_NAME VAR_DNSTAP_TLS_CERT_BUNDLE
+%token VAR_DNSTAP_TLS_CLIENT_KEY_FILE VAR_DNSTAP_TLS_CLIENT_CERT_FILE
+%token VAR_DNSTAP_SEND_IDENTITY VAR_DNSTAP_SEND_VERSION VAR_DNSTAP_BIDIRECTIONAL
%token VAR_DNSTAP_IDENTITY VAR_DNSTAP_VERSION
%token VAR_DNSTAP_LOG_RESOLVER_QUERY_MESSAGES
%token VAR_DNSTAP_LOG_RESOLVER_RESPONSE_MESSAGES
@@ -127,6 +130,7 @@ extern struct config_parser_state* cfg_parser;
%token VAR_DNSTAP_LOG_FORWARDER_RESPONSE_MESSAGES
%token VAR_RESPONSE_IP_TAG VAR_RESPONSE_IP VAR_RESPONSE_IP_DATA
%token VAR_HARDEN_ALGO_DOWNGRADE VAR_IP_TRANSPARENT
+%token VAR_IP_DSCP
%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
@@ -159,6 +163,7 @@ extern struct config_parser_state* cfg_parser;
%token VAR_IPSECMOD_MAX_TTL VAR_IPSECMOD_WHITELIST VAR_IPSECMOD_STRICT
%token VAR_CACHEDB VAR_CACHEDB_BACKEND VAR_CACHEDB_SECRETSEED
%token VAR_CACHEDB_REDISHOST VAR_CACHEDB_REDISPORT VAR_CACHEDB_REDISTIMEOUT
+%token VAR_CACHEDB_REDISEXPIRERECORDS
%token VAR_UDP_UPSTREAM_WITHOUT_DOWNSTREAM VAR_FOR_UPSTREAM
%token VAR_AUTH_ZONE VAR_ZONEFILE VAR_MASTER VAR_URL VAR_FOR_DOWNSTREAM
%token VAR_FALLBACK_ENABLED VAR_TLS_ADDITIONAL_PORT VAR_LOW_RTT VAR_LOW_RTT_PERMIL
@@ -166,10 +171,11 @@ extern struct config_parser_state* cfg_parser;
%token VAR_ALLOW_NOTIFY VAR_TLS_WIN_CERT VAR_TCP_CONNECTION_LIMIT
%token VAR_FORWARD_NO_CACHE VAR_STUB_NO_CACHE VAR_LOG_SERVFAIL VAR_DENY_ANY
%token VAR_UNKNOWN_SERVER_TIME_LIMIT VAR_LOG_TAG_QUERYREPLY
-%token VAR_STREAM_WAIT_SIZE VAR_TLS_CIPHERS VAR_TLS_CIPHERSUITES
+%token VAR_STREAM_WAIT_SIZE VAR_TLS_CIPHERS VAR_TLS_CIPHERSUITES VAR_TLS_USE_SNI
%token VAR_IPSET VAR_IPSET_NAME_V4 VAR_IPSET_NAME_V6
%token VAR_TLS_SESSION_TICKET_KEYS VAR_RPZ VAR_TAGS VAR_RPZ_ACTION_OVERRIDE
%token VAR_RPZ_CNAME_OVERRIDE VAR_RPZ_LOG VAR_RPZ_LOG_NAME
+%token VAR_DYNLIB VAR_DYNLIB_FILE
%%
toplevelvars: /* empty */ | toplevelvars toplevelvar ;
@@ -178,20 +184,25 @@ toplevelvar: serverstart contents_server | stubstart contents_stub |
rcstart contents_rc | dtstart contents_dt | viewstart contents_view |
dnscstart contents_dnsc | cachedbstart contents_cachedb |
ipsetstart contents_ipset | authstart contents_auth |
- rpzstart contents_rpz
+ rpzstart contents_rpz | dynlibstart contents_dl |
+ force_toplevel
+ ;
+force_toplevel: VAR_FORCE_TOPLEVEL
+ {
+ OUTYY(("\nP(force-toplevel)\n"));
+ }
;
-
/* server: declaration */
serverstart: VAR_SERVER
{
- OUTYY(("\nP(server:)\n"));
+ OUTYY(("\nP(server:)\n"));
}
;
-contents_server: contents_server content_server
+contents_server: contents_server content_server
| ;
content_server: server_num_threads | server_verbosity | server_port |
server_outgoing_range | server_do_ip4 |
- server_do_ip6 | server_prefer_ip6 |
+ server_do_ip6 | server_prefer_ip4 | server_prefer_ip6 |
server_do_udp | server_do_tcp |
server_tcp_mss | server_outgoing_tcp_mss | server_tcp_idle_timeout |
server_tcp_keepalive | server_tcp_keepalive_timeout |
@@ -239,6 +250,7 @@ content_server: server_num_threads | server_verbosity | server_port |
server_dns64_prefix | server_dns64_synthall | server_dns64_ignore_aaaa |
server_infra_cache_min_rtt | server_harden_algo_downgrade |
server_ip_transparent | server_ip_ratelimit | server_ratelimit |
+ server_ip_dscp |
server_ip_ratelimit_slabs | server_ratelimit_slabs |
server_ip_ratelimit_size | server_ratelimit_size |
server_ratelimit_for_domain |
@@ -272,7 +284,8 @@ content_server: server_num_threads | server_verbosity | server_port |
server_tcp_connection_limit | server_log_servfail | server_deny_any |
server_unknown_server_time_limit | server_log_tag_queryreply |
server_stream_wait_size | server_tls_ciphers |
- server_tls_ciphersuites | server_tls_session_ticket_keys
+ server_tls_ciphersuites | server_tls_session_ticket_keys |
+ server_tls_use_sni
;
stubstart: VAR_STUB_ZONE
{
@@ -780,6 +793,15 @@ server_do_tcp: VAR_DO_TCP STRING_ARG
free($2);
}
;
+server_prefer_ip4: VAR_PREFER_IP4 STRING_ARG
+ {
+ OUTYY(("P(server_prefer_ip4:%s)\n", $2));
+ if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0)
+ yyerror("expected yes or no.");
+ else cfg_parser->cfg->prefer_ip4 = (strcmp($2, "yes")==0);
+ free($2);
+ }
+ ;
server_prefer_ip6: VAR_PREFER_IP6 STRING_ARG
{
OUTYY(("P(server_prefer_ip6:%s)\n", $2));
@@ -938,6 +960,15 @@ server_tls_session_ticket_keys: VAR_TLS_SESSION_TICKET_KEYS STRING_ARG
yyerror("out of memory");
}
;
+server_tls_use_sni: VAR_TLS_USE_SNI STRING_ARG
+ {
+ OUTYY(("P(server_tls_use_sni:%s)\n", $2));
+ if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0)
+ yyerror("expected yes or no.");
+ else cfg_parser->cfg->tls_use_sni = (strcmp($2, "yes")==0);
+ free($2);
+ }
+ ;
server_use_systemd: VAR_USE_SYSTEMD STRING_ARG
{
OUTYY(("P(server_use_systemd:%s)\n", $2));
@@ -1247,6 +1278,20 @@ server_ip_freebind: VAR_IP_FREEBIND STRING_ARG
free($2);
}
;
+server_ip_dscp: VAR_IP_DSCP STRING_ARG
+ {
+ OUTYY(("P(server_ip_dscp:%s)\n", $2));
+ if(atoi($2) == 0 && strcmp($2, "0") != 0)
+ yyerror("number expected");
+ else if (atoi($2) > 63)
+ yyerror("value too large (max 63)");
+ else if (atoi($2) < 0)
+ yyerror("value too small (min 0)");
+ else
+ cfg_parser->cfg->ip_dscp = atoi($2);
+ free($2);
+ }
+ ;
server_stream_wait_size: VAR_STREAM_WAIT_SIZE STRING_ARG
{
OUTYY(("P(server_stream_wait_size:%s)\n", $2));
@@ -2719,7 +2764,10 @@ dtstart: VAR_DNSTAP
;
contents_dt: contents_dt content_dt
| ;
-content_dt: dt_dnstap_enable | dt_dnstap_socket_path |
+content_dt: dt_dnstap_enable | dt_dnstap_socket_path | dt_dnstap_bidirectional |
+ dt_dnstap_ip | dt_dnstap_tls | dt_dnstap_tls_server_name |
+ dt_dnstap_tls_cert_bundle |
+ dt_dnstap_tls_client_key_file | dt_dnstap_tls_client_cert_file |
dt_dnstap_send_identity | dt_dnstap_send_version |
dt_dnstap_identity | dt_dnstap_version |
dt_dnstap_log_resolver_query_messages |
@@ -2738,6 +2786,16 @@ dt_dnstap_enable: VAR_DNSTAP_ENABLE STRING_ARG
free($2);
}
;
+dt_dnstap_bidirectional: VAR_DNSTAP_BIDIRECTIONAL STRING_ARG
+ {
+ OUTYY(("P(dt_dnstap_bidirectional:%s)\n", $2));
+ if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0)
+ yyerror("expected yes or no.");
+ else cfg_parser->cfg->dnstap_bidirectional =
+ (strcmp($2, "yes")==0);
+ free($2);
+ }
+ ;
dt_dnstap_socket_path: VAR_DNSTAP_SOCKET_PATH STRING_ARG
{
OUTYY(("P(dt_dnstap_socket_path:%s)\n", $2));
@@ -2745,6 +2803,50 @@ dt_dnstap_socket_path: VAR_DNSTAP_SOCKET_PATH STRING_ARG
cfg_parser->cfg->dnstap_socket_path = $2;
}
;
+dt_dnstap_ip: VAR_DNSTAP_IP STRING_ARG
+ {
+ OUTYY(("P(dt_dnstap_ip:%s)\n", $2));
+ free(cfg_parser->cfg->dnstap_ip);
+ cfg_parser->cfg->dnstap_ip = $2;
+ }
+ ;
+dt_dnstap_tls: VAR_DNSTAP_TLS STRING_ARG
+ {
+ OUTYY(("P(dt_dnstap_tls:%s)\n", $2));
+ if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0)
+ yyerror("expected yes or no.");
+ else cfg_parser->cfg->dnstap_tls = (strcmp($2, "yes")==0);
+ free($2);
+ }
+ ;
+dt_dnstap_tls_server_name: VAR_DNSTAP_TLS_SERVER_NAME STRING_ARG
+ {
+ OUTYY(("P(dt_dnstap_tls_server_name:%s)\n", $2));
+ free(cfg_parser->cfg->dnstap_tls_server_name);
+ cfg_parser->cfg->dnstap_tls_server_name = $2;
+ }
+ ;
+dt_dnstap_tls_cert_bundle: VAR_DNSTAP_TLS_CERT_BUNDLE STRING_ARG
+ {
+ OUTYY(("P(dt_dnstap_tls_cert_bundle:%s)\n", $2));
+ free(cfg_parser->cfg->dnstap_tls_cert_bundle);
+ cfg_parser->cfg->dnstap_tls_cert_bundle = $2;
+ }
+ ;
+dt_dnstap_tls_client_key_file: VAR_DNSTAP_TLS_CLIENT_KEY_FILE STRING_ARG
+ {
+ OUTYY(("P(dt_dnstap_tls_client_key_file:%s)\n", $2));
+ free(cfg_parser->cfg->dnstap_tls_client_key_file);
+ cfg_parser->cfg->dnstap_tls_client_key_file = $2;
+ }
+ ;
+dt_dnstap_tls_client_cert_file: VAR_DNSTAP_TLS_CLIENT_CERT_FILE STRING_ARG
+ {
+ OUTYY(("P(dt_dnstap_tls_client_cert_file:%s)\n", $2));
+ free(cfg_parser->cfg->dnstap_tls_client_cert_file);
+ cfg_parser->cfg->dnstap_tls_client_cert_file = $2;
+ }
+ ;
dt_dnstap_send_identity: VAR_DNSTAP_SEND_IDENTITY STRING_ARG
{
OUTYY(("P(dt_dnstap_send_identity:%s)\n", $2));
@@ -2852,6 +2954,21 @@ py_script: VAR_PYTHON_SCRIPT STRING_ARG
if(!cfg_strlist_append_ex(&cfg_parser->cfg->python_script, $2))
yyerror("out of memory");
}
+dynlibstart: VAR_DYNLIB
+ {
+ OUTYY(("\nP(dynlib:)\n"));
+ }
+ ;
+contents_dl: contents_dl content_dl
+ | ;
+content_dl: dl_file
+ ;
+dl_file: VAR_DYNLIB_FILE STRING_ARG
+ {
+ OUTYY(("P(dynlib-file:%s)\n", $2));
+ if(!cfg_strlist_append_ex(&cfg_parser->cfg->dynlib_file, $2))
+ yyerror("out of memory");
+ }
server_disable_dnssec_lame_check: VAR_DISABLE_DNSSEC_LAME_CHECK STRING_ARG
{
OUTYY(("P(disable_dnssec_lame_check:%s)\n", $2));
@@ -3003,7 +3120,8 @@ cachedbstart: VAR_CACHEDB
contents_cachedb: contents_cachedb content_cachedb
| ;
content_cachedb: cachedb_backend_name | cachedb_secret_seed |
- redis_server_host | redis_server_port | redis_timeout
+ redis_server_host | redis_server_port | redis_timeout |
+ redis_expire_records
;
cachedb_backend_name: VAR_CACHEDB_BACKEND STRING_ARG
{
@@ -3069,6 +3187,19 @@ redis_timeout: VAR_CACHEDB_REDISTIMEOUT STRING_ARG
free($2);
}
;
+redis_expire_records: VAR_CACHEDB_REDISEXPIRERECORDS STRING_ARG
+ {
+ #if defined(USE_CACHEDB) && defined(USE_REDIS)
+ OUTYY(("P(redis_expire_records:%s)\n", $2));
+ if(strcmp($2, "yes") != 0 && strcmp($2, "no") != 0)
+ yyerror("expected yes or no.");
+ else cfg_parser->cfg->redis_expire_records = (strcmp($2, "yes")==0);
+ #else
+ OUTYY(("P(Compiled without cachedb or redis, ignoring)\n"));
+ #endif
+ free($2);
+ }
+ ;
server_tcp_connection_limit: VAR_TCP_CONNECTION_LIMIT STRING_ARG STRING_ARG
{
OUTYY(("P(server_tcp_connection_limit:%s %s)\n", $2, $3));
diff --git a/contrib/unbound/util/fptr_wlist.c b/contrib/unbound/util/fptr_wlist.c
index 84d41cc84641..aa275ed534b7 100644
--- a/contrib/unbound/util/fptr_wlist.c
+++ b/contrib/unbound/util/fptr_wlist.c
@@ -81,6 +81,9 @@
#ifdef WITH_PYTHONMODULE
#include "pythonmod/pythonmod.h"
#endif
+#ifdef WITH_DYNLIBMODULE
+#include "dynlibmod/dynlibmod.h"
+#endif
#ifdef USE_CACHEDB
#include "cachedb/cachedb.h"
#endif
@@ -93,6 +96,9 @@
#ifdef USE_IPSET
#include "ipset/ipset.h"
#endif
+#ifdef USE_DNSTAP
+#include "dnstap/dtstream.h"
+#endif
int
fptr_whitelist_comm_point(comm_point_callback_type *fptr)
@@ -168,6 +174,15 @@ fptr_whitelist_event(void (*fptr)(int, short, void *))
else if(fptr == &tube_handle_signal) return 1;
else if(fptr == &comm_base_handle_slow_accept) return 1;
else if(fptr == &comm_point_http_handle_callback) return 1;
+#ifdef USE_DNSTAP
+ else if(fptr == &dtio_output_cb) return 1;
+ else if(fptr == &dtio_cmd_cb) return 1;
+ else if(fptr == &dtio_reconnect_timeout_cb) return 1;
+ else if(fptr == &dtio_stop_timer_cb) return 1;
+ else if(fptr == &dtio_stop_ev_cb) return 1;
+ else if(fptr == &dtio_tap_callback) return 1;
+ else if(fptr == &dtio_mainfdcallback) return 1;
+#endif
#ifdef UB_ON_WINDOWS
else if(fptr == &worker_win_stop_cb) return 1;
#endif
@@ -380,6 +395,9 @@ fptr_whitelist_mod_init(int (*fptr)(struct module_env* env, int id))
#ifdef WITH_PYTHONMODULE
else if(fptr == &pythonmod_init) return 1;
#endif
+#ifdef WITH_DYNLIBMODULE
+ else if(fptr == &dynlibmod_init) return 1;
+#endif
#ifdef USE_CACHEDB
else if(fptr == &cachedb_init) return 1;
#endif
@@ -405,6 +423,9 @@ fptr_whitelist_mod_deinit(void (*fptr)(struct module_env* env, int id))
#ifdef WITH_PYTHONMODULE
else if(fptr == &pythonmod_deinit) return 1;
#endif
+#ifdef WITH_DYNLIBMODULE
+ else if(fptr == &dynlibmod_deinit) return 1;
+#endif
#ifdef USE_CACHEDB
else if(fptr == &cachedb_deinit) return 1;
#endif
@@ -431,6 +452,9 @@ fptr_whitelist_mod_operate(void (*fptr)(struct module_qstate* qstate,
#ifdef WITH_PYTHONMODULE
else if(fptr == &pythonmod_operate) return 1;
#endif
+#ifdef WITH_DYNLIBMODULE
+ else if(fptr == &dynlibmod_operate) return 1;
+#endif
#ifdef USE_CACHEDB
else if(fptr == &cachedb_operate) return 1;
#endif
@@ -457,6 +481,9 @@ fptr_whitelist_mod_inform_super(void (*fptr)(
#ifdef WITH_PYTHONMODULE
else if(fptr == &pythonmod_inform_super) return 1;
#endif
+#ifdef WITH_DYNLIBMODULE
+ else if(fptr == &dynlibmod_inform_super) return 1;
+#endif
#ifdef USE_CACHEDB
else if(fptr == &cachedb_inform_super) return 1;
#endif
@@ -483,6 +510,9 @@ fptr_whitelist_mod_clear(void (*fptr)(struct module_qstate* qstate,
#ifdef WITH_PYTHONMODULE
else if(fptr == &pythonmod_clear) return 1;
#endif
+#ifdef WITH_DYNLIBMODULE
+ else if(fptr == &dynlibmod_clear) return 1;
+#endif
#ifdef USE_CACHEDB
else if(fptr == &cachedb_clear) return 1;
#endif
@@ -508,6 +538,9 @@ fptr_whitelist_mod_get_mem(size_t (*fptr)(struct module_env* env, int id))
#ifdef WITH_PYTHONMODULE
else if(fptr == &pythonmod_get_mem) return 1;
#endif
+#ifdef WITH_DYNLIBMODULE
+ else if(fptr == &dynlibmod_get_mem) return 1;
+#endif
#ifdef USE_CACHEDB
else if(fptr == &cachedb_get_mem) return 1;
#endif
@@ -566,18 +599,30 @@ int fptr_whitelist_inplace_cb_reply_generic(inplace_cb_reply_func_type* fptr,
#ifdef WITH_PYTHONMODULE
if(fptr == &python_inplace_cb_reply_generic) return 1;
#endif
+#ifdef WITH_DYNLIBMODULE
+ if(fptr == &dynlib_inplace_cb_reply_generic) return 1;
+#endif
} else if(type == inplace_cb_reply_cache) {
#ifdef WITH_PYTHONMODULE
if(fptr == &python_inplace_cb_reply_generic) return 1;
#endif
+#ifdef WITH_DYNLIBMODULE
+ if(fptr == &dynlib_inplace_cb_reply_generic) return 1;
+#endif
} else if(type == inplace_cb_reply_local) {
#ifdef WITH_PYTHONMODULE
if(fptr == &python_inplace_cb_reply_generic) return 1;
#endif
+#ifdef WITH_DYNLIBMODULE
+ if(fptr == &dynlib_inplace_cb_reply_generic) return 1;
+#endif
} else if(type == inplace_cb_reply_servfail) {
#ifdef WITH_PYTHONMODULE
if(fptr == &python_inplace_cb_reply_generic) return 1;
#endif
+#ifdef WITH_DYNLIBMODULE
+ if(fptr == &dynlib_inplace_cb_reply_generic) return 1;
+#endif
}
return 0;
}
@@ -592,6 +637,10 @@ int fptr_whitelist_inplace_cb_query(inplace_cb_query_func_type* fptr)
if(fptr == &python_inplace_cb_query_generic)
return 1;
#endif
+#ifdef WITH_DYNLIBMODULE
+ if(fptr == &dynlib_inplace_cb_query_generic)
+ return 1;
+#endif
(void)fptr;
return 0;
}
@@ -605,6 +654,10 @@ int fptr_whitelist_inplace_cb_edns_back_parsed(
#else
(void)fptr;
#endif
+#ifdef WITH_DYNLIBMODULE
+ if(fptr == &dynlib_inplace_cb_edns_back_parsed)
+ return 1;
+#endif
return 0;
}
@@ -617,6 +670,10 @@ int fptr_whitelist_inplace_cb_query_response(
#else
(void)fptr;
#endif
+#ifdef WITH_DYNLIBMODULE
+ if(fptr == &dynlib_inplace_cb_query_response)
+ return 1;
+#endif
return 0;
}
diff --git a/contrib/unbound/util/iana_ports.inc b/contrib/unbound/util/iana_ports.inc
index 3b8afe54e829..79488f49a2c9 100644
--- a/contrib/unbound/util/iana_ports.inc
+++ b/contrib/unbound/util/iana_ports.inc
@@ -3771,6 +3771,7 @@
4188,
4191,
4192,
+4195,
4197,
4199,
4300,
@@ -4539,6 +4540,7 @@
6850,
6868,
6888,
+6924,
6935,
6936,
6946,
@@ -5229,6 +5231,7 @@
18241,
18262,
18463,
+18516,
18634,
18635,
18668,
diff --git a/contrib/unbound/util/mini_event.h b/contrib/unbound/util/mini_event.h
index 204894d97af2..1734ca574c60 100644
--- a/contrib/unbound/util/mini_event.h
+++ b/contrib/unbound/util/mini_event.h
@@ -54,6 +54,8 @@
#if defined(USE_MINI_EVENT) && !defined(USE_WINSOCK)
+#include <sys/time.h>
+
#ifndef HAVE_EVENT_BASE_FREE
#define HAVE_EVENT_BASE_FREE
#endif
diff --git a/contrib/unbound/util/net_help.c b/contrib/unbound/util/net_help.c
index 0869f91f954e..f59a4d65370d 100644
--- a/contrib/unbound/util/net_help.c
+++ b/contrib/unbound/util/net_help.c
@@ -55,6 +55,9 @@
#ifdef HAVE_OPENSSL_ERR_H
#include <openssl/err.h>
#endif
+#ifdef HAVE_OPENSSL_CORE_NAMES_H
+#include <openssl/core_names.h>
+#endif
#ifdef USE_WINSOCK
#include <wincrypt.h>
#endif
@@ -67,8 +70,8 @@ uint16_t EDNS_ADVERTISED_SIZE = 4096;
/** minimal responses when positive answer: default is no */
int MINIMAL_RESPONSES = 0;
-/** rrset order roundrobin: default is no */
-int RRSET_ROUNDROBIN = 0;
+/** rrset order roundrobin: default is yes */
+int RRSET_ROUNDROBIN = 1;
/** log tag queries with name instead of 'info' for filtering */
int LOG_TAG_QUERYREPLY = 0;
@@ -79,6 +82,32 @@ static struct tls_session_ticket_key {
unsigned char *hmac_key;
} *ticket_keys;
+/**
+ * callback TLS session ticket encrypt and decrypt
+ * For use with SSL_CTX_set_tlsext_ticket_key_cb or
+ * SSL_CTX_set_tlsext_ticket_key_evp_cb
+ * @param s: the SSL_CTX to use (from connect_sslctx_create())
+ * @param key_name: secret name, 16 bytes
+ * @param iv: up to EVP_MAX_IV_LENGTH.
+ * @param evp_ctx: the evp cipher context, function sets this.
+ * @param hmac_ctx: the hmac context, function sets this.
+ * with ..key_cb it is of type HMAC_CTX*
+ * with ..key_evp_cb it is of type EVP_MAC_CTX*
+ * @param enc: 1 is encrypt, 0 is decrypt
+ * @return 0 on no ticket, 1 for okay, and 2 for okay but renew the ticket
+ * (the ticket is decrypt only). and <0 for failures.
+ */
+#ifdef HAVE_SSL
+int tls_session_ticket_key_cb(SSL *s, unsigned char* key_name,
+ unsigned char* iv, EVP_CIPHER_CTX *evp_ctx,
+#ifdef HAVE_SSL_CTX_SET_TLSEXT_TICKET_KEY_EVP_CB
+ EVP_MAC_CTX *hmac_ctx,
+#else
+ HMAC_CTX* hmac_ctx,
+#endif
+ int enc);
+#endif /* HAVE_SSL */
+
/* returns true is string addr is an ip6 specced address */
int
str_is_ip6(const char* str)
@@ -829,6 +858,32 @@ void log_crypto_err_code(const char* str, unsigned long err)
#endif /* HAVE_SSL */
}
+#ifdef HAVE_SSL
+/** log certificate details */
+void
+log_cert(unsigned level, const char* str, void* cert)
+{
+ BIO* bio;
+ char nul = 0;
+ char* pp = NULL;
+ long len;
+ if(verbosity < level) return;
+ bio = BIO_new(BIO_s_mem());
+ if(!bio) return;
+ X509_print_ex(bio, (X509*)cert, 0, (unsigned long)-1
+ ^(X509_FLAG_NO_SUBJECT
+ |X509_FLAG_NO_ISSUER|X509_FLAG_NO_VALIDITY
+ |X509_FLAG_NO_EXTENSIONS|X509_FLAG_NO_AUX
+ |X509_FLAG_NO_ATTRIBUTES));
+ BIO_write(bio, &nul, (int)sizeof(nul));
+ len = BIO_get_mem_data(bio, &pp);
+ if(len != 0 && pp) {
+ verbose(level, "%s: \n%s", str, pp);
+ }
+ BIO_free(bio);
+}
+#endif /* HAVE_SSL */
+
int
listen_sslctx_setup(void* ctxt)
{
@@ -970,7 +1025,7 @@ void* listen_sslctx_create(char* key, char* pem, char* verifypem)
}
SSL_CTX_set_client_CA_list(ctx, SSL_load_client_CA_file(
verifypem));
- SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL);
+ SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL);
}
return ctx;
#else
@@ -1191,6 +1246,60 @@ void* outgoing_ssl_fd(void* sslctx, int fd)
#endif
}
+int check_auth_name_for_ssl(char* auth_name)
+{
+ if(!auth_name) return 1;
+#if defined(HAVE_SSL) && !defined(HAVE_SSL_SET1_HOST) && !defined(HAVE_X509_VERIFY_PARAM_SET1_HOST)
+ log_err("the query has an auth_name %s, but libssl has no call to "
+ "perform TLS authentication. Remove that name from config "
+ "or upgrade the ssl crypto library.", auth_name);
+ return 0;
+#else
+ return 1;
+#endif
+}
+
+/** set the authname on an SSL structure, SSL* ssl */
+int set_auth_name_on_ssl(void* ssl, char* auth_name, int use_sni)
+{
+ if(!auth_name) return 1;
+#ifdef HAVE_SSL
+ if(use_sni) {
+ (void)SSL_set_tlsext_host_name(ssl, auth_name);
+ }
+#else
+ (void)ssl;
+ (void)use_sni;
+#endif
+#ifdef HAVE_SSL_SET1_HOST
+ SSL_set_verify(ssl, SSL_VERIFY_PEER, NULL);
+ /* setting the hostname makes openssl verify the
+ * host name in the x509 certificate in the
+ * SSL connection*/
+ if(!SSL_set1_host(ssl, auth_name)) {
+ log_err("SSL_set1_host failed");
+ return 0;
+ }
+#elif defined(HAVE_X509_VERIFY_PARAM_SET1_HOST)
+ /* openssl 1.0.2 has this function that can be used for
+ * set1_host like verification */
+ if(auth_name) {
+ X509_VERIFY_PARAM* param = SSL_get0_param(ssl);
+# ifdef X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS
+ X509_VERIFY_PARAM_set_hostflags(param, X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS);
+# endif
+ if(!X509_VERIFY_PARAM_set1_host(param, auth_name, strlen(auth_name))) {
+ log_err("X509_VERIFY_PARAM_set1_host failed");
+ return 0;
+ }
+ SSL_set_verify(ssl, SSL_VERIFY_PEER, NULL);
+ }
+#else
+ verbose(VERB_ALGO, "the query has an auth_name, but libssl has no call to perform TLS authentication");
+#endif /* HAVE_SSL_SET1_HOST */
+ return 1;
+}
+
#if defined(HAVE_SSL) && defined(OPENSSL_THREADS) && !defined(THREADS_DISABLED) && defined(CRYPTO_LOCK) && OPENSSL_VERSION_NUMBER < 0x10100000L
/** global lock list for openssl locks */
static lock_basic_type *ub_openssl_locks = NULL;
@@ -1285,7 +1394,7 @@ int listen_sslctx_setup_ticket_keys(void* sslctx, struct config_strlist* tls_ses
if(!data)
return 0;
- f = fopen(p->str, "r");
+ f = fopen(p->str, "rb");
if(!f) {
log_err("could not read tls-session-ticket-key %s: %s", p->str, strerror(errno));
free(data);
@@ -1308,10 +1417,17 @@ int listen_sslctx_setup_ticket_keys(void* sslctx, struct config_strlist* tls_ses
}
/* terminate array with NULL key name entry */
keys->key_name = NULL;
+# ifdef HAVE_SSL_CTX_SET_TLSEXT_TICKET_KEY_EVP_CB
+ if(SSL_CTX_set_tlsext_ticket_key_evp_cb(sslctx, tls_session_ticket_key_cb) == 0) {
+ log_err("no support for TLS session ticket");
+ return 0;
+ }
+# else
if(SSL_CTX_set_tlsext_ticket_key_cb(sslctx, tls_session_ticket_key_cb) == 0) {
log_err("no support for TLS session ticket");
return 0;
}
+# endif
return 1;
#else
(void)sslctx;
@@ -1321,13 +1437,27 @@ int listen_sslctx_setup_ticket_keys(void* sslctx, struct config_strlist* tls_ses
}
-int tls_session_ticket_key_cb(void *ATTR_UNUSED(sslctx), unsigned char* key_name, unsigned char* iv, void *evp_sctx, void *hmac_ctx, int enc)
+#ifdef HAVE_SSL
+int tls_session_ticket_key_cb(SSL *ATTR_UNUSED(sslctx), unsigned char* key_name,
+ unsigned char* iv, EVP_CIPHER_CTX *evp_sctx,
+#ifdef HAVE_SSL_CTX_SET_TLSEXT_TICKET_KEY_EVP_CB
+ EVP_MAC_CTX *hmac_ctx,
+#else
+ HMAC_CTX* hmac_ctx,
+#endif
+ int enc)
{
#ifdef HAVE_SSL
+# ifdef HAVE_SSL_CTX_SET_TLSEXT_TICKET_KEY_EVP_CB
+ OSSL_PARAM params[3];
+# else
const EVP_MD *digest;
+# endif
const EVP_CIPHER *cipher;
int evp_cipher_length;
+# ifndef HAVE_SSL_CTX_SET_TLSEXT_TICKET_KEY_EVP_CB
digest = EVP_sha256();
+# endif
cipher = EVP_aes_256_cbc();
evp_cipher_length = EVP_CIPHER_iv_length(cipher);
if( enc == 1 ) {
@@ -1342,7 +1472,14 @@ int tls_session_ticket_key_cb(void *ATTR_UNUSED(sslctx), unsigned char* key_name
verbose(VERB_CLIENT, "EVP_EncryptInit_ex failed");
return -1;
}
-#ifndef HMAC_INIT_EX_RETURNS_VOID
+#ifdef HAVE_SSL_CTX_SET_TLSEXT_TICKET_KEY_EVP_CB
+ params[0] = OSSL_PARAM_construct_octet_string(OSSL_MAC_PARAM_KEY,
+ ticket_keys->hmac_key, 32);
+ params[1] = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_DIGEST,
+ "sha256", 0);
+ params[2] = OSSL_PARAM_construct_end();
+ EVP_MAC_set_ctx_params(hmac_ctx, params);
+#elif !defined(HMAC_INIT_EX_RETURNS_VOID)
if (HMAC_Init_ex(hmac_ctx, ticket_keys->hmac_key, 32, digest, NULL) != 1) {
verbose(VERB_CLIENT, "HMAC_Init_ex failed");
return -1;
@@ -1366,7 +1503,14 @@ int tls_session_ticket_key_cb(void *ATTR_UNUSED(sslctx), unsigned char* key_name
return 0;
}
-#ifndef HMAC_INIT_EX_RETURNS_VOID
+#ifdef HAVE_SSL_CTX_SET_TLSEXT_TICKET_KEY_EVP_CB
+ params[0] = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_KEY,
+ key->hmac_key, 32);
+ params[1] = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_DIGEST,
+ "sha256", 0);
+ params[2] = OSSL_PARAM_construct_end();
+ EVP_MAC_set_ctx_params(hmac_ctx, params);
+#elif !defined(HMAC_INIT_EX_RETURNS_VOID)
if (HMAC_Init_ex(hmac_ctx, key->hmac_key, 32, digest, NULL) != 1) {
verbose(VERB_CLIENT, "HMAC_Init_ex failed");
return -1;
@@ -1391,6 +1535,7 @@ int tls_session_ticket_key_cb(void *ATTR_UNUSED(sslctx), unsigned char* key_name
return 0;
#endif
}
+#endif /* HAVE_SSL */
void
listen_sslctx_delete_ticket_keys(void)
diff --git a/contrib/unbound/util/net_help.h b/contrib/unbound/util/net_help.h
index 7a33a72035d5..29943ada090f 100644
--- a/contrib/unbound/util/net_help.h
+++ b/contrib/unbound/util/net_help.h
@@ -386,6 +386,14 @@ void log_crypto_err(const char* str);
void log_crypto_err_code(const char* str, unsigned long err);
/**
+ * Log certificate details verbosity, string, of X509 cert
+ * @param level: verbosity level
+ * @param str: string to prefix on output
+ * @param cert: X509* structure.
+ */
+void log_cert(unsigned level, const char* str, void* cert);
+
+/**
* Set SSL_OP_NOxxx options on SSL context to disable bad crypto
* @param ctxt: SSL_CTX*
* @return false on failure.
@@ -435,6 +443,22 @@ void* incoming_ssl_fd(void* sslctx, int fd);
void* outgoing_ssl_fd(void* sslctx, int fd);
/**
+ * check if authname SSL functionality is available, false if not
+ * @param auth_name: the name for the remote server, used for error print.
+ * @return false if SSL functionality to check the SSL name is not available.
+ */
+int check_auth_name_for_ssl(char* auth_name);
+
+/**
+ * set auth name on SSL for verification
+ * @param ssl: SSL* to set
+ * @param auth_name: if NULL nothing happens, otherwise the name to check.
+ * @param use_sni: if SNI will be used.
+ * @return 1 on success or NULL auth_name, 0 on failure.
+ */
+int set_auth_name_on_ssl(void* ssl, char* auth_name, int use_sni);
+
+/**
* Initialize openssl locking for thread safety
* @return false on failure (alloc failure).
*/
@@ -454,20 +478,6 @@ void ub_openssl_lock_delete(void);
int listen_sslctx_setup_ticket_keys(void* sslctx,
struct config_strlist* tls_session_ticket_keys);
-/**
- * callback TLS session ticket encrypt and decrypt
- * For use with SSL_CTX_set_tlsext_ticket_key_cb
- * @param s: the SSL_CTX to use (from connect_sslctx_create())
- * @param key_name: secret name, 16 bytes
- * @param iv: up to EVP_MAX_IV_LENGTH.
- * @param evp_ctx: the evp cipher context, function sets this.
- * @param hmac_ctx: the hmax context, function sets this.
- * @param enc: 1 is encrypt, 0 is decrypt
- * @return 0 on no ticket, 1 for okay, and 2 for okay but renew the ticket
- * (the ticket is decrypt only). and <0 for failures.
- */
-int tls_session_ticket_key_cb(void *s, unsigned char* key_name,unsigned char* iv, void *evp_ctx, void *hmac_ctx, int enc);
-
/** Free memory used for TLS session ticket keys */
void listen_sslctx_delete_ticket_keys(void);
diff --git a/contrib/unbound/util/netevent.c b/contrib/unbound/util/netevent.c
index 9fe5da2d45a3..3e7a433e5021 100644
--- a/contrib/unbound/util/netevent.c
+++ b/contrib/unbound/util/netevent.c
@@ -447,7 +447,10 @@ comm_point_send_udp_msg_if(struct comm_point *c, sldns_buffer* packet,
ssize_t sent;
struct msghdr msg;
struct iovec iov[1];
- char control[256];
+ union {
+ struct cmsghdr hdr;
+ char buf[256];
+ } control;
#ifndef S_SPLINT_S
struct cmsghdr *cmsg;
#endif /* S_SPLINT_S */
@@ -465,9 +468,9 @@ comm_point_send_udp_msg_if(struct comm_point *c, sldns_buffer* packet,
iov[0].iov_len = sldns_buffer_remaining(packet);
msg.msg_iov = iov;
msg.msg_iovlen = 1;
- msg.msg_control = control;
+ msg.msg_control = control.buf;
#ifndef S_SPLINT_S
- msg.msg_controllen = sizeof(control);
+ msg.msg_controllen = sizeof(control.buf);
#endif /* S_SPLINT_S */
msg.msg_flags = 0;
@@ -477,7 +480,7 @@ comm_point_send_udp_msg_if(struct comm_point *c, sldns_buffer* packet,
#ifdef IP_PKTINFO
void* cmsg_data;
msg.msg_controllen = CMSG_SPACE(sizeof(struct in_pktinfo));
- log_assert(msg.msg_controllen <= sizeof(control));
+ log_assert(msg.msg_controllen <= sizeof(control.buf));
cmsg->cmsg_level = IPPROTO_IP;
cmsg->cmsg_type = IP_PKTINFO;
memmove(CMSG_DATA(cmsg), &r->pktinfo.v4info,
@@ -488,7 +491,7 @@ comm_point_send_udp_msg_if(struct comm_point *c, sldns_buffer* packet,
cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo));
#elif defined(IP_SENDSRCADDR)
msg.msg_controllen = CMSG_SPACE(sizeof(struct in_addr));
- log_assert(msg.msg_controllen <= sizeof(control));
+ log_assert(msg.msg_controllen <= sizeof(control.buf));
cmsg->cmsg_level = IPPROTO_IP;
cmsg->cmsg_type = IP_SENDSRCADDR;
memmove(CMSG_DATA(cmsg), &r->pktinfo.v4addr,
@@ -501,7 +504,7 @@ comm_point_send_udp_msg_if(struct comm_point *c, sldns_buffer* packet,
} else if(r->srctype == 6) {
void* cmsg_data;
msg.msg_controllen = CMSG_SPACE(sizeof(struct in6_pktinfo));
- log_assert(msg.msg_controllen <= sizeof(control));
+ log_assert(msg.msg_controllen <= sizeof(control.buf));
cmsg->cmsg_level = IPPROTO_IPV6;
cmsg->cmsg_type = IPV6_PKTINFO;
memmove(CMSG_DATA(cmsg), &r->pktinfo.v6info,
@@ -513,7 +516,7 @@ comm_point_send_udp_msg_if(struct comm_point *c, sldns_buffer* packet,
} else {
/* try to pass all 0 to use default route */
msg.msg_controllen = CMSG_SPACE(sizeof(struct in6_pktinfo));
- log_assert(msg.msg_controllen <= sizeof(control));
+ log_assert(msg.msg_controllen <= sizeof(control.buf));
cmsg->cmsg_level = IPPROTO_IPV6;
cmsg->cmsg_type = IPV6_PKTINFO;
memset(CMSG_DATA(cmsg), 0, sizeof(struct in6_pktinfo));
@@ -584,7 +587,10 @@ comm_point_udp_ancil_callback(int fd, short event, void* arg)
struct msghdr msg;
struct iovec iov[1];
ssize_t rcv;
- char ancil[256];
+ union {
+ struct cmsghdr hdr;
+ char buf[256];
+ } ancil;
int i;
#ifndef S_SPLINT_S
struct cmsghdr* cmsg;
@@ -608,9 +614,9 @@ comm_point_udp_ancil_callback(int fd, short event, void* arg)
iov[0].iov_len = sldns_buffer_remaining(rep.c->buffer);
msg.msg_iov = iov;
msg.msg_iovlen = 1;
- msg.msg_control = ancil;
+ msg.msg_control = ancil.buf;
#ifndef S_SPLINT_S
- msg.msg_controllen = sizeof(ancil);
+ msg.msg_controllen = sizeof(ancil.buf);
#endif /* S_SPLINT_S */
msg.msg_flags = 0;
rcv = recvmsg(fd, &msg, 0);
@@ -1027,34 +1033,8 @@ tcp_callback_reader(struct comm_point* c)
}
#ifdef HAVE_SSL
-/** log certificate details */
-static void
-log_cert(unsigned level, const char* str, X509* cert)
-{
- BIO* bio;
- char nul = 0;
- char* pp = NULL;
- long len;
- if(verbosity < level) return;
- bio = BIO_new(BIO_s_mem());
- if(!bio) return;
- X509_print_ex(bio, cert, 0, (unsigned long)-1
- ^(X509_FLAG_NO_SUBJECT
- |X509_FLAG_NO_ISSUER|X509_FLAG_NO_VALIDITY
- |X509_FLAG_NO_EXTENSIONS|X509_FLAG_NO_AUX
- |X509_FLAG_NO_ATTRIBUTES));
- BIO_write(bio, &nul, (int)sizeof(nul));
- len = BIO_get_mem_data(bio, &pp);
- if(len != 0 && pp) {
- verbose(level, "%s: \n%s", str, pp);
- }
- BIO_free(bio);
-}
-#endif /* HAVE_SSL */
-
-#ifdef HAVE_SSL
/** true if the ssl handshake error has to be squelched from the logs */
-static int
+int
squelch_err_ssl_handshake(unsigned long err)
{
if(verbosity >= VERB_QUERY)
@@ -3183,7 +3163,10 @@ comm_point_send_reply(struct comm_reply *repinfo)
if(repinfo->c->tcp_parent->dtenv != NULL &&
repinfo->c->tcp_parent->dtenv->log_client_response_messages)
dt_msg_send_client_response(repinfo->c->tcp_parent->dtenv,
- &repinfo->addr, repinfo->c->type, repinfo->c->buffer);
+ &repinfo->addr, repinfo->c->type,
+ ( repinfo->c->tcp_req_info
+ ? repinfo->c->tcp_req_info->spool_buffer
+ : repinfo->c->buffer ));
#endif
if(repinfo->c->tcp_req_info) {
tcp_req_info_send_reply(repinfo->c->tcp_req_info);
diff --git a/contrib/unbound/util/netevent.h b/contrib/unbound/util/netevent.h
index d80c72b33431..bb2cd1e53732 100644
--- a/contrib/unbound/util/netevent.h
+++ b/contrib/unbound/util/netevent.h
@@ -783,7 +783,23 @@ void comm_base_handle_slow_accept(int fd, short event, void* arg);
void comm_point_tcp_win_bio_cb(struct comm_point* c, void* ssl);
#endif
-/** see if errno for tcp connect has to be logged or not. This uses errno */
+/**
+ * See if errno for tcp connect has to be logged or not. This uses errno
+ * @param addr: apart from checking errno, the addr is checked for ip4mapped
+ * and broadcast type, hence passed.
+ * @param addrlen: length of the addr parameter.
+ * @return true if it needs to be logged.
+ */
int tcp_connect_errno_needs_log(struct sockaddr* addr, socklen_t addrlen);
+#ifdef HAVE_SSL
+/**
+ * True if the ssl handshake error has to be squelched from the logs
+ * @param err: the error returned by the openssl routine, ERR_get_error.
+ * This is a packed structure with elements that are examined.
+ * @return true if the error is squelched (not logged).
+ */
+int squelch_err_ssl_handshake(unsigned long err);
+#endif
+
#endif /* NET_EVENT_H */
diff --git a/contrib/unbound/util/shm_side/shm_main.c b/contrib/unbound/util/shm_side/shm_main.c
index 46a71510fea3..af8c5bcf3705 100644
--- a/contrib/unbound/util/shm_side/shm_main.c
+++ b/contrib/unbound/util/shm_side/shm_main.c
@@ -285,6 +285,10 @@ void shm_main_run(struct worker *worker)
shm_stat->mem.ipsecmod = (long long)mod_get_mem(&worker->env,
"ipsecmod");
#endif
+#ifdef WITH_DYNLIBMODULE
+ shm_stat->mem.dynlib = (long long)mod_get_mem(&worker->env,
+ "dynlib");
+#endif
}
server_stats_add(stat_total, stat_info);
diff --git a/contrib/unbound/util/ub_event.c b/contrib/unbound/util/ub_event.c
index 9af476ad4084..68f633bb0ef2 100644
--- a/contrib/unbound/util/ub_event.c
+++ b/contrib/unbound/util/ub_event.c
@@ -148,7 +148,7 @@ const char* ub_event_get_version(void)
return event_get_version();
}
-#if (defined(HAVE_EV_LOOP) || defined(HAVE_EV_DEFAULT_LOOP)) && defined(EVBACKEND_SELECT)
+#if (defined(HAVE_EV_LOOP) || defined(HAVE_EV_DEFAULT_LOOP)) && defined(EV_FEATURE_BACKENDS)
static const char* ub_ev_backend2str(int b)
{
switch(b) {
@@ -184,7 +184,7 @@ ub_get_event_sys(struct ub_event_base* base, const char** n, const char** s,
*n = "libev";
if (!b)
b = (struct event_base*)ev_default_loop(EVFLAG_AUTO);
-# ifdef EVBACKEND_SELECT
+# ifdef EV_FEATURE_BACKENDS
*m = ub_ev_backend2str(ev_backend((struct ev_loop*)b));
# else
*m = "not obtainable";
diff --git a/contrib/unbound/validator/val_secalgo.c b/contrib/unbound/validator/val_secalgo.c
index 8f17c53e86de..65bca8b69d6e 100644
--- a/contrib/unbound/validator/val_secalgo.c
+++ b/contrib/unbound/validator/val_secalgo.c
@@ -77,6 +77,10 @@ int fake_sha1 = 0;
#include <openssl/engine.h>
#endif
+#if defined(HAVE_OPENSSL_DSA_H) && defined(USE_DSA)
+#include <openssl/dsa.h>
+#endif
+
/**
* Output a libcrypto openssl error to the logfile.
* @param str: string to add to it.
@@ -1746,6 +1750,7 @@ _verify_nettle_ecdsa(sldns_buffer* buf, unsigned int digest_size, unsigned char*
res &= nettle_ecdsa_verify (&pubkey, SHA256_DIGEST_SIZE, digest, &signature);
mpz_clear(x);
mpz_clear(y);
+ nettle_ecc_point_clear(&pubkey);
break;
}
case SHA384_DIGEST_SIZE:
diff --git a/contrib/unbound/validator/val_sigcrypt.c b/contrib/unbound/validator/val_sigcrypt.c
index 33d206de8d7f..de730f681893 100644
--- a/contrib/unbound/validator/val_sigcrypt.c
+++ b/contrib/unbound/validator/val_sigcrypt.c
@@ -1343,7 +1343,7 @@ adjust_ttl(struct val_env* ve, uint32_t unow,
if(ve->date_override) {
now = ve->date_override;
} else now = (int32_t)unow;
- expittl = expi - now;
+ expittl = (int32_t)((uint32_t)expi - (uint32_t)now);
/* so now:
* d->ttl: rrset ttl read from message or cache. May be reduced