...
 
Commits (33)
...@@ -467,6 +467,7 @@ pylint: ...@@ -467,6 +467,7 @@ pylint:
tarball-create: tarball-create:
stage: precheck stage: precheck
<<: *base_image <<: *base_image
<<: *default_triggering_rules
script: script:
- *configure - *configure
- make -j${BUILD_PARALLEL_JOBS:-1} all V=1 - make -j${BUILD_PARALLEL_JOBS:-1} all V=1
...@@ -477,8 +478,6 @@ tarball-create: ...@@ -477,8 +478,6 @@ tarball-create:
needs: needs:
- job: autoreconf - job: autoreconf
artifacts: true artifacts: true
only:
- tags
# Jobs for doc builds on Debian 10 "buster" (amd64) # Jobs for doc builds on Debian 10 "buster" (amd64)
......
5475. [bug] Fix RPZ wildcard passthru ignored when a rejection
would overwrite a passthru action matching some
rule in a previously loaded passthru rpz zone.
[GL #1619]
5474. [bug] dns_rdata_hip_next() failed to return ISC_R_NOMORE
when it should have. [GL !3880]
5473. [func] The rbt hashtable implementation has been changed
to use faster hash-function (HalfSipHash2-4) and
uses Fibonacci hashing for better distribution.
Setting the max-cache-size now preallocates fixed
size hashtable, so the rehashing doesn't cause
resolution brownouts when growing the hashtable.
[GL #1775]
5472. [func] The statistics channel has been updated to use the 5472. [func] The statistics channel has been updated to use the
new network manager. [GL #2022] new network manager. [GL #2022]
......
...@@ -15,6 +15,7 @@ AM_CPPFLAGS += \ ...@@ -15,6 +15,7 @@ AM_CPPFLAGS += \
$(LMDB_CFLAGS) \ $(LMDB_CFLAGS) \
$(MAXMINDDB_CFLAGS) \ $(MAXMINDDB_CFLAGS) \
$(DNSTAP_CFLAGS) \ $(DNSTAP_CFLAGS) \
$(LIBUV_CFLAGS) \
$(ZLIB_CFLAGS) $(ZLIB_CFLAGS)
if HAVE_JSON_C if HAVE_JSON_C
...@@ -102,6 +103,7 @@ named_LDADD = \ ...@@ -102,6 +103,7 @@ named_LDADD = \
$(LMDB_LIBS) \ $(LMDB_LIBS) \
$(MAXMINDDB_LIBS) \ $(MAXMINDDB_LIBS) \
$(DNSTAP_LIBS) \ $(DNSTAP_LIBS) \
$(LIBUV_LIBS) \
$(LIBXML2_LIBS) \ $(LIBXML2_LIBS) \
$(ZLIB_LIBS) $(ZLIB_LIBS)
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include <stdbool.h> #include <stdbool.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <uv.h>
#include <isc/app.h> #include <isc/app.h>
#include <isc/attributes.h> #include <isc/attributes.h>
...@@ -525,6 +526,9 @@ printversion(bool verbose) { ...@@ -525,6 +526,9 @@ printversion(bool verbose) {
printf("linked to OpenSSL version: %s\n", printf("linked to OpenSSL version: %s\n",
SSLeay_version(SSLEAY_VERSION)); SSLeay_version(SSLEAY_VERSION));
#endif /* OPENSSL_VERSION_NUMBER >= 0x10100000L */ #endif /* OPENSSL_VERSION_NUMBER >= 0x10100000L */
printf("compiled with libuv version: %d.%d.%d\n", UV_VERSION_MAJOR,
UV_VERSION_MINOR, UV_VERSION_PATCH);
printf("linked to libuv version: %s\n", uv_version_string());
#ifdef HAVE_LIBXML2 #ifdef HAVE_LIBXML2
printf("compiled with libxml2 version: %s\n", LIBXML_DOTTED_VERSION); printf("compiled with libxml2 version: %s\n", LIBXML_DOTTED_VERSION);
printf("linked to libxml2 version: %s\n", xmlParserVersion); printf("linked to libxml2 version: %s\n", xmlParserVersion);
......
...@@ -10116,7 +10116,7 @@ named_server_destroy(named_server_t **serverp) { ...@@ -10116,7 +10116,7 @@ named_server_destroy(named_server_t **serverp) {
static void static void
fatal(named_server_t *server, const char *msg, isc_result_t result) { fatal(named_server_t *server, const char *msg, isc_result_t result) {
if (server != NULL) { if (server != NULL && server->task != NULL) {
/* /*
* Prevent races between the OpenSSL on_exit registered * Prevent races between the OpenSSL on_exit registered
* function and any other OpenSSL calls from other tasks * function and any other OpenSSL calls from other tasks
......
...@@ -67,7 +67,7 @@ ...@@ -67,7 +67,7 @@
<ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName> <ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName>
<BrowseInformation>true</BrowseInformation> <BrowseInformation>true</BrowseInformation>
<ForcedIncludeFiles>..\..\..\config.h</ForcedIncludeFiles> <ForcedIncludeFiles>..\..\..\config.h</ForcedIncludeFiles>
<AdditionalIncludeDirectories>@OPENSSL_INC@@GSSAPI_INC@@GEOIP_INC@.\;..\..\..\;@LIBXML2_INC@..\win32\include;..\include;..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\dns\include;..\..\..\lib\isccc\include;..\..\..\lib\isccfg\include;..\..\..\lib\bind9\include;..\..\..\lib\ns\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>@LIBUV_INC@@OPENSSL_INC@@GSSAPI_INC@@GEOIP_INC@.\;..\..\..\;@LIBXML2_INC@..\win32\include;..\include;..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\dns\include;..\..\..\lib\isccc\include;..\..\..\lib\isccfg\include;..\..\..\lib\bind9\include;..\..\..\lib\ns\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<CompileAs>CompileAsC</CompileAs> <CompileAs>CompileAsC</CompileAs>
</ClCompile> </ClCompile>
<Link> <Link>
...@@ -75,7 +75,7 @@ ...@@ -75,7 +75,7 @@
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>
<OutputFile>..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt)</OutputFile> <OutputFile>..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt)</OutputFile>
<AdditionalLibraryDirectories>..\..\..\lib\isc\win32\$(Configuration);..\..\..\lib\dns\win32\$(Configuration);..\..\..\lib\isccc\win32\$(Configuration);..\..\..\lib\isccfg\win32\$(Configuration);..\..\..\lib\bind9\win32\$(Configuration);..\..\..\lib\ns\win32\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories> <AdditionalLibraryDirectories>..\..\..\lib\isc\win32\$(Configuration);..\..\..\lib\dns\win32\$(Configuration);..\..\..\lib\isccc\win32\$(Configuration);..\..\..\lib\isccfg\win32\$(Configuration);..\..\..\lib\bind9\win32\$(Configuration);..\..\..\lib\ns\win32\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>@OPENSSL_LIB@@LIBXML2_LIB@@GSSAPI_LIB@@GEOIP_LIB@libisc.lib;libdns.lib;libisccc.lib;libisccfg.lib;libbind9.lib;libns.lib;version.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies> <AdditionalDependencies>@LIBUV_LIB@@OPENSSL_LIB@@LIBXML2_LIB@@GSSAPI_LIB@@GEOIP_LIB@libisc.lib;libdns.lib;libisccc.lib;libisccfg.lib;libbind9.lib;libns.lib;version.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link> </Link>
<PreBuildEvent> <PreBuildEvent>
<Command>cd .. <Command>cd ..
...@@ -103,7 +103,7 @@ perl -e "print \";\";" &gt;&gt; xsl.c ...@@ -103,7 +103,7 @@ perl -e "print \";\";" &gt;&gt; xsl.c
<ObjectFileName>.\$(Configuration)\</ObjectFileName> <ObjectFileName>.\$(Configuration)\</ObjectFileName>
<ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName> <ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName>
<ForcedIncludeFiles>..\..\..\config.h</ForcedIncludeFiles> <ForcedIncludeFiles>..\..\..\config.h</ForcedIncludeFiles>
<AdditionalIncludeDirectories>@OPENSSL_INC@@GSSAPI_INC@@GEOIP_INC@.\;..\..\..\;@LIBXML2_INC@..\win32\include;..\include;..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\dns\include;..\..\..\lib\isccc\include;..\..\..\lib\isccfg\include;..\..\..\lib\bind9\include;..\..\..\lib\ns\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>@LIBUV_INC@@OPENSSL_INC@@GSSAPI_INC@@GEOIP_INC@.\;..\..\..\;@LIBXML2_INC@..\win32\include;..\include;..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\dns\include;..\..\..\lib\isccc\include;..\..\..\lib\isccfg\include;..\..\..\lib\bind9\include;..\..\..\lib\ns\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<CompileAs>CompileAsC</CompileAs> <CompileAs>CompileAsC</CompileAs>
</ClCompile> </ClCompile>
<Link> <Link>
...@@ -114,7 +114,7 @@ perl -e "print \";\";" &gt;&gt; xsl.c ...@@ -114,7 +114,7 @@ perl -e "print \";\";" &gt;&gt; xsl.c
<OutputFile>..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt)</OutputFile> <OutputFile>..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt)</OutputFile>
<LinkTimeCodeGeneration>Default</LinkTimeCodeGeneration> <LinkTimeCodeGeneration>Default</LinkTimeCodeGeneration>
<AdditionalLibraryDirectories>..\..\..\lib\isc\win32\$(Configuration);..\..\..\lib\dns\win32\$(Configuration);..\..\..\lib\isccc\win32\$(Configuration);..\..\..\lib\isccfg\win32\$(Configuration);..\..\..\lib\bind9\win32\$(Configuration);..\..\..\lib\ns\win32\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories> <AdditionalLibraryDirectories>..\..\..\lib\isc\win32\$(Configuration);..\..\..\lib\dns\win32\$(Configuration);..\..\..\lib\isccc\win32\$(Configuration);..\..\..\lib\isccfg\win32\$(Configuration);..\..\..\lib\bind9\win32\$(Configuration);..\..\..\lib\ns\win32\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>@OPENSSL_LIB@@LIBXML2_LIB@@GSSAPI_LIB@@GEOIP_LIB@libisc.lib;libdns.lib;libisccc.lib;libisccfg.lib;libbind9.lib;libns.lib;version.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies> <AdditionalDependencies>@LIBUV_LIB@@OPENSSL_LIB@@LIBXML2_LIB@@GSSAPI_LIB@@GEOIP_LIB@libisc.lib;libdns.lib;libisccc.lib;libisccfg.lib;libbind9.lib;libns.lib;version.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link> </Link>
<PreBuildEvent> <PreBuildEvent>
<Command>cd .. <Command>cd ..
......
#!/bin/sh
#
# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#
# See the COPYRIGHT file distributed with this work for additional
# information regarding copyright ownership.
. $SYSTEMTESTTOP/conf.sh
$FEATURETEST --have-dlopen || {
echo_i "dlopen() not supported - skipping dlzexternal test"
exit 255
}
exit 0
...@@ -589,7 +589,8 @@ static dns_dbmethods_t sampledb_methods = { ...@@ -589,7 +589,8 @@ static dns_dbmethods_t sampledb_methods = {
NULL, /* getsize */ NULL, /* getsize */
NULL, /* setservestalettl */ NULL, /* setservestalettl */
NULL, /* getservestalettl */ NULL, /* getservestalettl */
NULL /* setgluecachestats */ NULL, /* setgluecachestats */
NULL /* adjusthashsize */
}; };
/* Auxiliary driver functions. */ /* Auxiliary driver functions. */
......
#!/bin/sh
#
# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#
# See the COPYRIGHT file distributed with this work for additional
# information regarding copyright ownership.
. $SYSTEMTESTTOP/conf.sh
$FEATURETEST --have-dlopen || {
echo_i "dlopen() not supported - skipping dyndb test"
exit 255
}
exit 0
...@@ -40,7 +40,6 @@ usage(void) { ...@@ -40,7 +40,6 @@ usage(void) {
fprintf(stderr, " --enable-dnsrps\n"); fprintf(stderr, " --enable-dnsrps\n");
fprintf(stderr, " --gethostname\n"); fprintf(stderr, " --gethostname\n");
fprintf(stderr, " --gssapi\n"); fprintf(stderr, " --gssapi\n");
fprintf(stderr, " --have-dlopen\n");
fprintf(stderr, " --have-geoip2\n"); fprintf(stderr, " --have-geoip2\n");
fprintf(stderr, " --have-libxml2\n"); fprintf(stderr, " --have-libxml2\n");
fprintf(stderr, " --ipv6only=no\n"); fprintf(stderr, " --ipv6only=no\n");
...@@ -110,10 +109,6 @@ main(int argc, char **argv) { ...@@ -110,10 +109,6 @@ main(int argc, char **argv) {
#endif /* HAVE_GSSAPI */ #endif /* HAVE_GSSAPI */
} }
if (strcmp(argv[1], "--have-dlopen") == 0) {
return (0);
}
if (strcmp(argv[1], "--have-geoip2") == 0) { if (strcmp(argv[1], "--have-geoip2") == 0) {
#ifdef HAVE_GEOIP2 #ifdef HAVE_GEOIP2
return (0); return (0);
......
#!/bin/sh
#
# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#
# See the COPYRIGHT file distributed with this work for additional
# information regarding copyright ownership.
. $SYSTEMTESTTOP/conf.sh
$FEATURETEST --have-dlopen || {
echo_i "dlopen() not supported - skipping filter-aaaa test"
exit 255
}
exit 0
; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
;
; This Source Code Form is subject to the terms of the Mozilla Public
; License, v. 2.0. If a copy of the MPL was not distributed with this
; file, You can obtain one at http://mozilla.org/MPL/2.0/.
;
; See the COPYRIGHT file distributed with this work for additional
; information regarding copyright ownership.
$TTL 3600
@ IN SOA ns.example.com. root.example.com. 1 3600 3600 3600 3600
@ NS ns.example.com.
ns.example.com. A 10.53.0.1
@ A 1.2.3.4
www A 1.2.3.5
...@@ -66,3 +66,8 @@ zone "test2.example.net" { ...@@ -66,3 +66,8 @@ zone "test2.example.net" {
type master; type master;
file "test2.example.net.db"; file "test2.example.net.db";
}; };
zone "example.com" {
type master;
file "example.com.db";
};
$ORIGIN given.zone.
$TTL 3600
@ IN SOA ns.given.zone. hostmaster.given.zone. 1 600 300 604800 3600
IN NS ns.given.zone.
ns.given.zone. IN A 127.0.0.1
; this should be ignored as it matches an earlier passthru entry.
example.com CNAME .
; this should be ignored as it matches an earlier wildcard passthru entry.
www.example.com CNAME .
$ORIGIN passthru.zone.
$TTL 3600
@ IN SOA ns.passthru.zone. hostmaster.passthru.zone. 1 600 300 604800 3600
IN NS ns.passthru.zone.
ns.passthru.zone. IN A 127.0.0.1
example.com CNAME rpz-passthru.
*.example.com CNAME rpz-passthru.
/*
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* See the COPYRIGHT file distributed with this work for additional
* information regarding copyright ownership.
*/
# common configuration
include "named.conf.header";
view "recursive" {
# policy configuration to be tested
response-policy {
zone "passthru.zone" policy passthru;
zone "given.zone" policy given;
} qname-wait-recurse yes
nsdname-enable yes
nsip-enable yes;
# policy zones to be tested
zone "passthru.zone" { type master; file "db.passthru"; };
zone "given.zone" { type master; file "db.given"; };
zone "." {
type hint;
file "root.hint";
};
recursion yes;
dnssec-validation yes;
};
...@@ -473,6 +473,21 @@ for mode in native dnsrps; do ...@@ -473,6 +473,21 @@ for mode in native dnsrps; do
status=1 status=1
} }
t=`expr $t + 1`
echo_i "testing wildcard passthru before explicit drop (${t})"
add_test_marker 10.53.0.2
run_server wildcard4
$DIG $DIGOPTS example.com a @10.53.0.2 -p ${PORT} > dig.out.${t}.1
grep "status: NOERROR" dig.out.${t}.1 > /dev/null || {
echo_i "test ${t} failed"
status=1
}
$DIG $DIGOPTS www.example.com a @10.53.0.2 -p ${PORT} > dig.out.${t}.2
grep "status: NOERROR" dig.out.${t}.2 > /dev/null || {
echo_i "test ${t} failed"
status=1
}
if [ "$mode" = "native" ]; then if [ "$mode" = "native" ]; then
# Check for invalid prefix length error # Check for invalid prefix length error
t=`expr $t + 1` t=`expr $t + 1`
......
...@@ -131,17 +131,13 @@ start_servers() { ...@@ -131,17 +131,13 @@ start_servers() {
fi fi
} }
stop_servers_failed() {
echoinfo "I:$systest:stopping servers failed"
echofail "R:$systest:FAIL"
echoend "E:$systest:$(date_with_args)"
exit 1
}
stop_servers() { stop_servers() {
if $stopservers; then if $stopservers; then
echoinfo "I:$systest:stopping servers" echoinfo "I:$systest:stopping servers"
$PERL stop.pl "$systest" || stop_servers_failed if ! $PERL stop.pl "$systest"; then
echoinfo "I:$systest:stopping servers failed"
return 1
fi
fi fi
} }
...@@ -217,7 +213,7 @@ if [ -r "$systest/tests.sh" ]; then ...@@ -217,7 +213,7 @@ if [ -r "$systest/tests.sh" ]; then
( cd "$systest" && $SHELL tests.sh "$@" ) ( cd "$systest" && $SHELL tests.sh "$@" )
status=$? status=$?
run=$((run+1)) run=$((run+1))
stop_servers stop_servers || status=1
fi fi
if [ -n "$PYTEST" ]; then if [ -n "$PYTEST" ]; then
...@@ -232,7 +228,7 @@ if [ -n "$PYTEST" ]; then ...@@ -232,7 +228,7 @@ if [ -n "$PYTEST" ]; then
test_status=$(cat "$systest/$test.status") test_status=$(cat "$systest/$test.status")
fi fi
status=$((status+test_status)) status=$((status+test_status))
stop_servers stop_servers || status=1
done done
else else
echoinfo "I:$systest:pytest not installed, skipping python tests" echoinfo "I:$systest:pytest not installed, skipping python tests"
...@@ -250,55 +246,65 @@ else ...@@ -250,55 +246,65 @@ else
exit $status exit $status
fi fi
if [ $status != 0 ]; then get_core_dumps() {
echofail "R:$systest:FAIL" find "$systest/" \( -name 'core*' -or -name '*.core' \) ! -name '*.gz' ! -name '*.txt' | sort
# Do not clean up - we need the evidence. }
else
core_dumps="$(find "$systest/" -name 'core*' -or -name '*.core' | sort | tr '\n' ' ')" core_dumps=$(get_core_dumps | tr '\n' ' ')
assertion_failures=$(find "$systest/" -name named.run -print0 | xargs -0 grep "assertion failure" | wc -l) assertion_failures=$(find "$systest/" -name named.run -print0 | xargs -0 grep "assertion failure" | wc -l)
sanitizer_summaries=$(find "$systest/" -name 'tsan.*' | wc -l) sanitizer_summaries=$(find "$systest/" -name 'tsan.*' | wc -l)
if [ -n "$core_dumps" ]; then if [ -n "$core_dumps" ]; then
echoinfo "I:$systest:Test claims success despite crashes: $core_dumps" status=1
echofail "R:$systest:FAIL" echoinfo "I:$systest:Core dump(s) found: $core_dumps"
# Do not clean up - we need the evidence. get_core_dumps | while read -r coredump; do
find "$systest/" -name 'core*' -or -name '*.core' | while read -r coredump; do
export SYSTESTDIR="$systest" export SYSTESTDIR="$systest"
echoinfo "D:$systest:backtrace from $coredump start" echoinfo "D:$systest:backtrace from $coredump:"
binary=$(gdb --batch --core="$coredump" | sed -ne "s/Core was generated by \`//;s/ .*'.$//p;") echoinfo "D:$systest:--------------------------------------------------------------------------------"
binary=$(gdb --batch --core="$coredump" 2>/dev/null | sed -ne "s/Core was generated by \`//;s/ .*'.$//p;")
"${top_builddir}/libtool" --mode=execute gdb \ "${top_builddir}/libtool" --mode=execute gdb \
--batch \ -batch \
--command=run.gdb \ -ex bt \
--core="$coredump" \ -core="$coredump" \
-- \ -- \
"$binary" "$binary" 2>/dev/null | sed -n '/^Core was generated by/,$p' | cat_d
echoinfo "D:$systest:backtrace from $coredump end" echoinfo "D:$systest:--------------------------------------------------------------------------------"
coredump_backtrace=$(basename "${coredump}")-backtrace.txt
echoinfo "D:$systest:full backtrace from $coredump saved in $coredump_backtrace"
"${top_builddir}/libtool" --mode=execute gdb \
-batch \
-command=run.gdb \
-core="$coredump" \
-- \
"$binary" > "$coredump_backtrace" 2>&1
echoinfo "D:$systest:core dump $coredump archived as $coredump.gz"
gzip -1 "${coredump}"
done done
elif [ "$assertion_failures" -ne 0 ]; then elif [ "$assertion_failures" -ne 0 ]; then
status=1
SYSTESTDIR="$systest" SYSTESTDIR="$systest"
echoinfo "I:$systest:Test claims success despite $assertion_failures assertion failure(s)" echoinfo "I:$systest:$assertion_failures assertion failure(s) found"
find "$systest/" -name 'tsan.*' -print0 | xargs -0 grep "SUMMARY: " | sort -u | cat_d find "$systest/" -name 'tsan.*' -print0 | xargs -0 grep "SUMMARY: " | sort -u | cat_d
elif [ "$sanitizer_summaries" -ne 0 ]; then
status=1
echoinfo "I:$systest:$sanitizer_summaries sanitizer report(s) found"
fi
if [ $status -ne 0 ]; then
echofail "R:$systest:FAIL" echofail "R:$systest:FAIL"
# Do not clean up - we need the evidence. else
elif [ "$sanitizer_summaries" -ne 0 ]; then
echoinfo "I:$systest:Test claims success despite $sanitizer_summaries sanitizer reports(s)"
echofail "R:$systest:FAIL"
else
echopass "R:$systest:PASS" echopass "R:$systest:PASS"
if $clean if $clean; then
then
( cd "${systest}" && $SHELL clean.sh "$@" ) ( cd "${systest}" && $SHELL clean.sh "$@" )
if [ "${srcdir}" != "${builddir}" ]; then if [ "${srcdir}" != "${builddir}" ]; then
rm -rf "./${systest}" ## FIXME (this also removes compiled binaries) rm -rf "./${systest}" ## FIXME (this also removes compiled binaries)
fi fi
if test -d ${srcdir}/../../../.git if test -d ${srcdir}/../../../.git; then
then
git status -su --ignored "${systest}" 2>/dev/null | \ git status -su --ignored "${systest}" 2>/dev/null | \
sed -n -e 's|^?? \(.*\)|I:file \1 not removed|p' \ sed -n -e 's|^?? \(.*\)|I:file \1 not removed|p' \
-e 's|^!! \(.*/named.run\)$|I:file \1 not removed|p' \ -e 's|^!! \(.*/named.run\)$|I:file \1 not removed|p' \
-e 's|^!! \(.*/named.memstats\)$|I:file \1 not removed|p' -e 's|^!! \(.*/named.memstats\)$|I:file \1 not removed|p'
fi fi
fi fi
fi
fi fi
echoend "E:$systest:$(date_with_args)" echoend "E:$systest:$(date_with_args)"
......
...@@ -650,19 +650,6 @@ AC_COMPILE_IFELSE( ...@@ -650,19 +650,6 @@ AC_COMPILE_IFELSE(
AC_MSG_RESULT([yes])], AC_MSG_RESULT([yes])],
[AC_MSG_RESULT([no])]) [AC_MSG_RESULT([no])])
AC_MSG_CHECKING([for SipHash support])
AC_COMPILE_IFELSE(
[AC_LANG_PROGRAM([[#include <openssl/evp.h>
#include <openssl/opensslv.h>]],
[[#if OPENSSL_VERSION_NUMBER < 0x10101010L
#error OpenSSL >= 1.1.1a required for working SipHash initialization
#endif
EVP_PKEY *key = EVP_PKEY_new_raw_private_key(
EVP_PKEY_SIPHASH, NULL, NULL, 0);]])],
[AC_DEFINE([HAVE_OPENSSL_SIPHASH], [1], [define if OpenSSL supports SipHash])
AC_MSG_RESULT([yes])],
[AC_MSG_RESULT([no])])
# #
# Check for OpenSSL SHA-1 support # Check for OpenSSL SHA-1 support
# #
......
...@@ -39,7 +39,12 @@ New Features ...@@ -39,7 +39,12 @@ New Features
Feature Changes Feature Changes
~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~
- None. - BIND's cache database implementation has been updated to use a faster
hash-function with better distribution. In addition, the effective
max-cache-size (configured explicitly, defaulting to a value based on system
memory or set to 'unlimited') now pre-allocates fixed size hash tables. This
prevents interruption to query resolution when the hash tables need to be
increased in size. [GL #1775]
Bug Fixes Bug Fixes
~~~~~~~~~ ~~~~~~~~~
......
...@@ -756,7 +756,8 @@ grow_names(isc_task_t *task, isc_event_t *ev) { ...@@ -756,7 +756,8 @@ grow_names(isc_task_t *task, isc_event_t *ev) {
isc_mutex_t *newnamelocks = NULL; isc_mutex_t *newnamelocks = NULL;
isc_result_t result; isc_result_t result;
unsigned int *newname_refcnt = NULL; unsigned int *newname_refcnt = NULL;
unsigned int i, n, bucket; unsigned int i, n;
unsigned int bucket;
adb = ev->ev_arg; adb = ev->ev_arg;
INSIST(DNS_ADB_VALID(adb)); INSIST(DNS_ADB_VALID(adb));
...@@ -4838,7 +4839,7 @@ void ...@@ -4838,7 +4839,7 @@ void
dns_adb_flushname(dns_adb_t *adb, const dns_name_t *name) { dns_adb_flushname(dns_adb_t *adb, const dns_name_t *name) {
dns_adbname_t *adbname; dns_adbname_t *adbname;
dns_adbname_t *nextname; dns_adbname_t *nextname;
int bucket; unsigned int bucket;
REQUIRE(DNS_ADB_VALID(adb)); REQUIRE(DNS_ADB_VALID(adb));
REQUIRE(name != NULL); REQUIRE(name != NULL);
......
...@@ -285,7 +285,8 @@ dns_badcache_find(dns_badcache_t *bc, const dns_name_t *name, ...@@ -285,7 +285,8 @@ dns_badcache_find(dns_badcache_t *bc, const dns_name_t *name,
dns_rdatatype_t type, uint32_t *flagp, isc_time_t *now) { dns_rdatatype_t type, uint32_t *flagp, isc_time_t *now) {
dns_bcentry_t *bad, *prev, *next; dns_bcentry_t *bad, *prev, *next;
bool answer = false; bool answer = false;
unsigned int i, hash; unsigned int i;
unsigned int hash;
REQUIRE(VALID_BADCACHE(bc)); REQUIRE(VALID_BADCACHE(bc));
REQUIRE(name != NULL); REQUIRE(name != NULL);
...@@ -385,7 +386,7 @@ dns_badcache_flushname(dns_badcache_t *bc, const dns_name_t *name) { ...@@ -385,7 +386,7 @@ dns_badcache_flushname(dns_badcache_t *bc, const dns_name_t *name) {
dns_bcentry_t *bad, *prev, *next; dns_bcentry_t *bad, *prev, *next;
isc_result_t result; isc_result_t result;
isc_time_t now; isc_time_t now;
unsigned int i; unsigned int hash;
REQUIRE(VALID_BADCACHE(bc)); REQUIRE(VALID_BADCACHE(bc));
REQUIRE(name != NULL); REQUIRE(name != NULL);
...@@ -396,16 +397,16 @@ dns_badcache_flushname(dns_badcache_t *bc, const dns_name_t *name) { ...@@ -396,16 +397,16 @@ dns_badcache_flushname(dns_badcache_t *bc, const dns_name_t *name) {
if (result != ISC_R_SUCCESS) { if (result != ISC_R_SUCCESS) {
isc_time_settoepoch(&now); isc_time_settoepoch(&now);
} }
i = dns_name_hash(name, false) % bc->size; hash = dns_name_hash(name, false) % bc->size;
LOCK(&bc->tlocks[i]); LOCK(&bc->tlocks[hash]);
prev = NULL; prev = NULL;
for (bad = bc->table[i]; bad != NULL; bad = next) { for (bad = bc->table[hash]; bad != NULL; bad = next) {
int n; int n;
next = bad->next; next = bad->next;
n = isc_time_compare(&bad->expire, &now); n = isc_time_compare(&bad->expire, &now);
if (n < 0 || dns_name_equal(name, &bad->name)) { if (n < 0 || dns_name_equal(name, &bad->name)) {
if (prev == NULL) { if (prev == NULL) {
bc->table[i] = bad->next; bc->table[hash] = bad->next;
} else { } else {
prev->next = bad->next; prev->next = bad->next;
} }
...@@ -417,7 +418,7 @@ dns_badcache_flushname(dns_badcache_t *bc, const dns_name_t *name) { ...@@ -417,7 +418,7 @@ dns_badcache_flushname(dns_badcache_t *bc, const dns_name_t *name) {
prev = bad; prev = bad;
} }
} }
UNLOCK(&bc->tlocks[i]); UNLOCK(&bc->tlocks[hash]);
RWUNLOCK(&bc->lock, isc_rwlocktype_read); RWUNLOCK(&bc->lock, isc_rwlocktype_read);
} }
......
...@@ -956,6 +956,7 @@ dns_cache_setcachesize(dns_cache_t *cache, size_t size) { ...@@ -956,6 +956,7 @@ dns_cache_setcachesize(dns_cache_t *cache, size_t size) {
* time, or replacing other limits). * time, or replacing other limits).
*/ */
isc_mem_setwater(cache->mctx, water, cache, hiwater, lowater); isc_mem_setwater(cache->mctx, water, cache, hiwater, lowater);
dns_db_adjusthashsize(cache->db, size);
} }
} }
......
...@@ -831,6 +831,17 @@ dns_db_hashsize(dns_db_t *db) { ...@@ -831,6 +831,17 @@ dns_db_hashsize(dns_db_t *db) {
return ((db->methods->hashsize)(db)); return ((db->methods->hashsize)(db));
} }
isc_result_t
dns_db_adjusthashsize(dns_db_t *db, size_t size) {
REQUIRE(DNS_DB_VALID(db));
if (db->methods->adjusthashsize != NULL) {
return ((db->methods->adjusthashsize)(db, size));
}
return (ISC_R_NOTIMPLEMENTED);
}
void void
dns_db_settask(dns_db_t *db, isc_task_t *task) { dns_db_settask(dns_db_t *db, isc_task_t *task) {
REQUIRE(DNS_DB_VALID(db)); REQUIRE(DNS_DB_VALID(db));
......
...@@ -967,7 +967,8 @@ static dns_dbmethods_t rpsdb_db_methods = { ...@@ -967,7 +967,8 @@ static dns_dbmethods_t rpsdb_db_methods = {
NULL, /* getsize */ NULL, /* getsize */
NULL, /* setservestalettl */ NULL, /* setservestalettl */
NULL, /* getservestalettl */ NULL, /* getservestalettl */
NULL /* setgluecachestats */ NULL, /* setgluecachestats */
NULL /* adjusthashsize */
}; };
static dns_rdatasetmethods_t rpsdb_rdataset_methods = { static dns_rdatasetmethods_t rpsdb_rdataset_methods = {
......
...@@ -179,6 +179,7 @@ typedef struct dns_dbmethods { ...@@ -179,6 +179,7 @@ typedef struct dns_dbmethods {
isc_result_t (*setservestalettl)(dns_db_t *db, dns_ttl_t ttl); isc_result_t (*setservestalettl)(dns_db_t *db, dns_ttl_t ttl);
isc_result_t (*getservestalettl)(dns_db_t *db, dns_ttl_t *ttl); isc_result_t (*getservestalettl)(dns_db_t *db, dns_ttl_t *ttl);
isc_result_t (*setgluecachestats)(dns_db_t *db, isc_stats_t *stats); isc_result_t (*setgluecachestats)(dns_db_t *db, isc_stats_t *stats);
isc_result_t (*adjusthashsize)(dns_db_t *db, size_t size);
} dns_dbmethods_t; } dns_dbmethods_t;
typedef isc_result_t (*dns_dbcreatefunc_t)(isc_mem_t * mctx, typedef isc_result_t (*dns_dbcreatefunc_t)(isc_mem_t * mctx,
...@@ -1363,6 +1364,23 @@ dns_db_hashsize(dns_db_t *db); ...@@ -1363,6 +1364,23 @@ dns_db_hashsize(dns_db_t *db);
* 0 if not implemented. * 0 if not implemented.
*/ */
isc_result_t
dns_db_adjusthashsize(dns_db_t *db, size_t size);
/*%<
* For database implementations using a hash table, adjust
* the size of the hash table to store objects with size
* memory footprint.
*
* Requires:
*
* \li 'db' is a valid database.
* \li 'size' is maximum memory footprint of the database
*
* Returns:
* \li #ISC_R_SUCCESS The registration succeeded
* \li #ISC_R_NOMEMORY Out of memory
*/
void void
dns_db_settask(dns_db_t *db, isc_task_t *task); dns_db_settask(dns_db_t *db, isc_task_t *task);
/*%< /*%<
......
...@@ -684,6 +684,17 @@ dns_rbt_hashsize(dns_rbt_t *rbt); ...@@ -684,6 +684,17 @@ dns_rbt_hashsize(dns_rbt_t *rbt);
* \li rbt is a valid rbt manager. * \li rbt is a valid rbt manager.
*/ */
isc_result_t
dns_rbt_adjusthashsize(dns_rbt_t *rbt, size_t size);
/*%<
* Adjust the number of buckets in the 'rbt' hash table, according to the
* expected maximum size of the rbt database.
*
* Requires:
* \li rbt is a valid rbt manager.
* \li size is expected maximum memory footprint of rbt.
*/
void void
dns_rbt_destroy(dns_rbt_t **rbtp); dns_rbt_destroy(dns_rbt_t **rbtp);
isc_result_t isc_result_t
......
...@@ -464,7 +464,8 @@ dns_name_hash(const dns_name_t *name, bool case_sensitive) { ...@@ -464,7 +464,8 @@ dns_name_hash(const dns_name_t *name, bool case_sensitive) {
length = 16; length = 16;
} }
return (isc_hash_function(name->ndata, length, case_sensitive)); /* High bits are more random. */
return (isc_hash32(name->ndata, length, case_sensitive));
} }
unsigned int unsigned int
...@@ -478,7 +479,8 @@ dns_name_fullhash(const dns_name_t *name, bool case_sensitive) { ...@@ -478,7 +479,8 @@ dns_name_fullhash(const dns_name_t *name, bool case_sensitive) {
return (0); return (0);
} }
return (isc_hash_function(name->ndata, name->length, case_sensitive)); /* High bits are more random. */
return (isc_hash32(name->ndata, name->length, case_sensitive));
} }
dns_namereln_t dns_namereln_t
......
...@@ -59,13 +59,27 @@ ...@@ -59,13 +59,27 @@
#define CHAIN_MAGIC ISC_MAGIC('0', '-', '0', '-') #define CHAIN_MAGIC ISC_MAGIC('0', '-', '0', '-')
#define VALID_CHAIN(chain) ISC_MAGIC_VALID(chain, CHAIN_MAGIC) #define VALID_CHAIN(chain) ISC_MAGIC_VALID(chain, CHAIN_MAGIC)
#define RBT_HASH_SIZE 64 #define RBT_HASH_MIN_BITS 16
#define RBT_HASH_MAX_BITS 32
#define RBT_HASH_OVERCOMMIT 3
#define RBT_HASH_BUCKETSIZE 4096 /* FIXME: What would be a good value here? */
#ifdef RBT_MEM_TEST #ifdef RBT_MEM_TEST
#undef RBT_HASH_SIZE #undef RBT_HASH_SIZE
#define RBT_HASH_SIZE 2 /*%< To give the reallocation code a workout. */ #define RBT_HASH_SIZE 2 /*%< To give the reallocation code a workout. */
#endif /* ifdef RBT_MEM_TEST */ #endif /* ifdef RBT_MEM_TEST */
#define GOLDEN_RATIO_32 0x61C88647
#define HASHSIZE(bits) (UINT64_C(1) << (bits))
static inline uint32_t
hash_32(uint32_t val, unsigned int bits) {
REQUIRE(bits <= RBT_HASH_MAX_BITS);
/* High bits are more random. */
return (val * GOLDEN_RATIO_32 >> (32 - bits));
}
struct dns_rbt { struct dns_rbt {
unsigned int magic; unsigned int magic;
isc_mem_t *mctx; isc_mem_t *mctx;
...@@ -73,7 +87,8 @@ struct dns_rbt { ...@@ -73,7 +87,8 @@ struct dns_rbt {
void (*data_deleter)(void *, void *); void (*data_deleter)(void *, void *);
void *deleter_arg; void *deleter_arg;
unsigned int nodecount; unsigned int nodecount;
size_t hashsize; uint16_t hashbits;
uint16_t maxhashbits;
dns_rbtnode_t **hashtable; dns_rbtnode_t **hashtable;
void *mmap_location; void *mmap_location;
}; };
...@@ -384,8 +399,12 @@ hash_node(dns_rbt_t *rbt, dns_rbtnode_t *node, const dns_name_t *name); ...@@ -384,8 +399,12 @@ hash_node(dns_rbt_t *rbt, dns_rbtnode_t *node, const dns_name_t *name);
static inline void static inline void
unhash_node(dns_rbt_t *rbt, dns_rbtnode_t *node); unhash_node(dns_rbt_t *rbt, dns_rbtnode_t *node);
static uint32_t
rehash_bits(dns_rbt_t *rbt, size_t newcount);
static void
rehash(dns_rbt_t *rbt, uint32_t newbits);
static void static void
rehash(dns_rbt_t *rbt, unsigned int newcount); maybe_rehash(dns_rbt_t *rbt, size_t size);
static inline void static inline void
rotate_left(dns_rbtnode_t *node, dns_rbtnode_t **rootp); rotate_left(dns_rbtnode_t *node, dns_rbtnode_t **rootp);
...@@ -920,7 +939,7 @@ dns_rbt_deserialize_tree(void *base_address, size_t filesize, ...@@ -920,7 +939,7 @@ dns_rbt_deserialize_tree(void *base_address, size_t filesize,
result = ISC_R_INVALIDFILE; result = ISC_R_INVALIDFILE;
goto cleanup; goto cleanup;
} }
rehash(rbt, header->nodecount); maybe_rehash(rbt, header->nodecount);
CHECK(treefix(rbt, base_address, filesize, rbt->root, dns_rootname, CHECK(treefix(rbt, base_address, filesize, rbt->root, dns_rootname,
datafixer, fixer_arg, &crc)); datafixer, fixer_arg, &crc));
...@@ -980,7 +999,8 @@ dns_rbt_create(isc_mem_t *mctx, dns_rbtdeleter_t deleter, void *deleter_arg, ...@@ -980,7 +999,8 @@ dns_rbt_create(isc_mem_t *mctx, dns_rbtdeleter_t deleter, void *deleter_arg,
rbt->root = NULL; rbt->root = NULL;
rbt->nodecount = 0; rbt->nodecount = 0;
rbt->hashtable = NULL; rbt->hashtable = NULL;
rbt->hashsize = 0; rbt->hashbits = 0;
rbt->maxhashbits = RBT_HASH_MAX_BITS;
rbt->mmap_location = NULL; rbt->mmap_location = NULL;
result = inithash(rbt); result = inithash(rbt);
...@@ -1024,8 +1044,8 @@ dns_rbt_destroy2(dns_rbt_t **rbtp, unsigned int quantum) { ...@@ -1024,8 +1044,8 @@ dns_rbt_destroy2(dns_rbt_t **rbtp, unsigned int quantum) {
rbt->mmap_location = NULL; rbt->mmap_location = NULL;
if (rbt->hashtable != NULL) { if (rbt->hashtable != NULL) {
isc_mem_put(rbt->mctx, rbt->hashtable, size_t size = HASHSIZE(rbt->hashbits) * sizeof(dns_rbtnode_t *);
rbt->hashsize * sizeof(dns_rbtnode_t *)); isc_mem_put(rbt->mctx, rbt->hashtable, size);
} }
rbt->magic = 0; rbt->magic = 0;
...@@ -1045,7 +1065,20 @@ size_t ...@@ -1045,7 +1065,20 @@ size_t
dns_rbt_hashsize(dns_rbt_t *rbt) { dns_rbt_hashsize(dns_rbt_t *rbt) {
REQUIRE(VALID_RBT(rbt)); REQUIRE(VALID_RBT(rbt));
return (rbt->hashsize); return (1 << rbt->hashbits);
}
isc_result_t
dns_rbt_adjusthashsize(dns_rbt_t *rbt, size_t size) {
REQUIRE(VALID_RBT(rbt));
size_t newsize = size / RBT_HASH_BUCKETSIZE;
rbt->maxhashbits = rehash_bits(rbt, newsize);
maybe_rehash(rbt, newsize);
return (ISC_R_SUCCESS);
} }
static inline isc_result_t static inline isc_result_t
...@@ -1544,7 +1577,7 @@ dns_rbt_findnode(dns_rbt_t *rbt, const dns_name_t *name, dns_name_t *foundname, ...@@ -1544,7 +1577,7 @@ dns_rbt_findnode(dns_rbt_t *rbt, const dns_name_t *name, dns_name_t *foundname,
dns_rbtnode_t *up_current; dns_rbtnode_t *up_current;
unsigned int nlabels; unsigned int nlabels;
unsigned int tlabels = 1; unsigned int tlabels = 1;
unsigned int hash; uint32_t hash;
/* /*
* The case of current not being a subtree root, * The case of current not being a subtree root,
...@@ -1587,7 +1620,8 @@ dns_rbt_findnode(dns_rbt_t *rbt, const dns_name_t *name, dns_name_t *foundname, ...@@ -1587,7 +1620,8 @@ dns_rbt_findnode(dns_rbt_t *rbt, const dns_name_t *name, dns_name_t *foundname,
* Walk all the nodes in the hash bucket pointed * Walk all the nodes in the hash bucket pointed
* by the computed hash value. * by the computed hash value.
*/ */
for (hnode = rbt->hashtable[hash % rbt->hashsize]; for (hnode = rbt->hashtable[hash_32(hash,
rbt->hashbits)];
hnode != NULL; hnode = hnode->hashnext) hnode != NULL; hnode = hnode->hashnext)
{ {
dns_name_t hnode_name; dns_name_t hnode_name;
...@@ -2267,13 +2301,13 @@ create_node(isc_mem_t *mctx, const dns_name_t *name, dns_rbtnode_t **nodep) { ...@@ -2267,13 +2301,13 @@ create_node(isc_mem_t *mctx, const dns_name_t *name, dns_rbtnode_t **nodep) {
*/ */
static inline void static inline void
hash_add_node(dns_rbt_t *rbt, dns_rbtnode_t *node, const dns_name_t *name) { hash_add_node(dns_rbt_t *rbt, dns_rbtnode_t *node, const dns_name_t *name) {
unsigned int hash; uint32_t hash;
REQUIRE(name != NULL); REQUIRE(name != NULL);
HASHVAL(node) = dns_name_fullhash(name, false); HASHVAL(node) = dns_name_fullhash(name, false);
hash = HASHVAL(node) % rbt->hashsize; hash = hash_32(HASHVAL(node), rbt->hashbits);
HASHNEXT(node) = rbt->hashtable[hash]; HASHNEXT(node) = rbt->hashtable[hash];
rbt->hashtable[hash] = node; rbt->hashtable[hash] = node;
...@@ -2284,45 +2318,56 @@ hash_add_node(dns_rbt_t *rbt, dns_rbtnode_t *node, const dns_name_t *name) { ...@@ -2284,45 +2318,56 @@ hash_add_node(dns_rbt_t *rbt, dns_rbtnode_t *node, const dns_name_t *name) {
*/ */
static isc_result_t static isc_result_t
inithash(dns_rbt_t *rbt) { inithash(dns_rbt_t *rbt) {
unsigned int bytes; size_t size;
rbt->hashsize = RBT_HASH_SIZE;
bytes = (unsigned int)rbt->hashsize * sizeof(dns_rbtnode_t *);
rbt->hashtable = isc_mem_get(rbt->mctx, bytes);
memset(rbt->hashtable, 0, bytes); rbt->hashbits = RBT_HASH_MIN_BITS;
size = HASHSIZE(rbt->hashbits) * sizeof(dns_rbtnode_t *);
rbt->hashtable = isc_mem_get(rbt->mctx, size);
memset(rbt->hashtable, 0, size);
return (ISC_R_SUCCESS); return (ISC_R_SUCCESS);
} }
static uint32_t
rehash_bits(dns_rbt_t *rbt, size_t newcount) {
uint32_t oldbits = rbt->hashbits;
uint32_t newbits = oldbits;
while (newcount >= HASHSIZE(newbits) && newbits <= rbt->maxhashbits) {
newbits += 1;
}
return (newbits);
}
/* /*
* Rebuild the hashtable to reduce the load factor * Rebuild the hashtable to reduce the load factor
*/ */
static void static void
rehash(dns_rbt_t *rbt, unsigned int newcount) { rehash(dns_rbt_t *rbt, uint32_t newbits) {
unsigned int oldsize; uint32_t oldbits;
size_t oldsize;
dns_rbtnode_t **oldtable; dns_rbtnode_t **oldtable;
dns_rbtnode_t *node; size_t newsize;
dns_rbtnode_t *nextnode;
unsigned int hash; REQUIRE(rbt->hashbits <= rbt->maxhashbits);
unsigned int i; REQUIRE(newbits <= rbt->maxhashbits);
oldsize = (unsigned int)rbt->hashsize; oldbits = rbt->hashbits;
oldsize = HASHSIZE(oldbits);
oldtable = rbt->hashtable; oldtable = rbt->hashtable;
do {
INSIST((rbt->hashsize * 2 + 1) > rbt->hashsize);
rbt->hashsize = rbt->hashsize * 2 + 1;
} while (newcount >= (rbt->hashsize * 3));
rbt->hashtable = isc_mem_get(rbt->mctx,
rbt->hashsize * sizeof(dns_rbtnode_t *));
for (i = 0; i < rbt->hashsize; i++) { rbt->hashbits = newbits;
rbt->hashtable[i] = NULL; newsize = HASHSIZE(rbt->hashbits);
} rbt->hashtable = isc_mem_get(rbt->mctx,
newsize * sizeof(dns_rbtnode_t *));
memset(rbt->hashtable, 0, newsize * sizeof(dns_rbtnode_t *));
for (i = 0; i < oldsize; i++) { for (size_t i = 0; i < oldsize; i++) {
dns_rbtnode_t *node;
dns_rbtnode_t *nextnode;
for (node = oldtable[i]; node != NULL; node = nextnode) { for (node = oldtable[i]; node != NULL; node = nextnode) {
hash = HASHVAL(node) % rbt->hashsize; uint32_t hash = hash_32(HASHVAL(node), rbt->hashbits);
nextnode = HASHNEXT(node); nextnode = HASHNEXT(node);
HASHNEXT(node) = rbt->hashtable[hash]; HASHNEXT(node) = rbt->hashtable[hash];
rbt->hashtable[hash] = node; rbt->hashtable[hash] = node;
...@@ -2332,6 +2377,14 @@ rehash(dns_rbt_t *rbt, unsigned int newcount) { ...@@ -2332,6 +2377,14 @@ rehash(dns_rbt_t *rbt, unsigned int newcount) {
isc_mem_put(rbt->mctx, oldtable, oldsize * sizeof(dns_rbtnode_t *)); isc_mem_put(rbt->mctx, oldtable, oldsize * sizeof(dns_rbtnode_t *));
} }
static void
maybe_rehash(dns_rbt_t *rbt, size_t newcount) {
uint32_t newbits = rehash_bits(rbt, newcount);
if (rbt->hashbits < newbits && newbits <= RBT_HASH_MAX_BITS) {
rehash(rbt, newbits);
}
}
/* /*
* Add a node to the hash table. Rehash the hashtable if the node count * Add a node to the hash table. Rehash the hashtable if the node count
* rises above a critical level. * rises above a critical level.
...@@ -2340,8 +2393,8 @@ static inline void ...@@ -2340,8 +2393,8 @@ static inline void
hash_node(dns_rbt_t *rbt, dns_rbtnode_t *node, const dns_name_t *name) { hash_node(dns_rbt_t *rbt, dns_rbtnode_t *node, const dns_name_t *name) {
REQUIRE(DNS_RBTNODE_VALID(node)); REQUIRE(DNS_RBTNODE_VALID(node));
if (rbt->nodecount >= (rbt->hashsize * 3)) { if (rbt->nodecount >= (HASHSIZE(rbt->hashbits) * RBT_HASH_OVERCOMMIT)) {
rehash(rbt, rbt->nodecount); maybe_rehash(rbt, rbt->nodecount);
} }
hash_add_node(rbt, node, name); hash_add_node(rbt, node, name);
...@@ -2352,12 +2405,12 @@ hash_node(dns_rbt_t *rbt, dns_rbtnode_t *node, const dns_name_t *name) { ...@@ -2352,12 +2405,12 @@ hash_node(dns_rbt_t *rbt, dns_rbtnode_t *node, const dns_name_t *name) {
*/ */
static inline void static inline void
unhash_node(dns_rbt_t *rbt, dns_rbtnode_t *node) { unhash_node(dns_rbt_t *rbt, dns_rbtnode_t *node) {
unsigned int bucket; uint32_t bucket;
dns_rbtnode_t *bucket_node; dns_rbtnode_t *bucket_node;
REQUIRE(DNS_RBTNODE_VALID(node)); REQUIRE(DNS_RBTNODE_VALID(node));
bucket = HASHVAL(node) % rbt->hashsize; bucket = hash_32(HASHVAL(node), rbt->hashbits);
bucket_node = rbt->hashtable[bucket]; bucket_node = rbt->hashtable[bucket];
if (bucket_node == node) { if (bucket_node == node) {
......
...@@ -7987,6 +7987,22 @@ hashsize(dns_db_t *db) { ...@@ -7987,6 +7987,22 @@ hashsize(dns_db_t *db) {
return (size); return (size);
} }
static isc_result_t
adjusthashsize(dns_db_t *db, size_t size) {
isc_result_t result;
dns_rbtdb_t *rbtdb;
rbtdb = (dns_rbtdb_t *)db;
REQUIRE(VALID_RBTDB(rbtdb));
RWLOCK(&rbtdb->tree_lock, isc_rwlocktype_write);
result = dns_rbt_adjusthashsize(rbtdb->tree, size);
RWUNLOCK(&rbtdb->tree_lock, isc_rwlocktype_write);
return (result);
}
static void static void
settask(dns_db_t *db, isc_task_t *task) { settask(dns_db_t *db, isc_task_t *task) {
dns_rbtdb_t *rbtdb; dns_rbtdb_t *rbtdb;
...@@ -8392,7 +8408,8 @@ static dns_dbmethods_t zone_methods = { attach, ...@@ -8392,7 +8408,8 @@ static dns_dbmethods_t zone_methods = { attach,
getsize, getsize,
NULL, /* setservestalettl */ NULL, /* setservestalettl */
NULL, /* getservestalettl */ NULL, /* getservestalettl */
setgluecachestats }; setgluecachestats,
adjusthashsize };
static dns_dbmethods_t cache_methods = { attach, static dns_dbmethods_t cache_methods = { attach,
detach, detach,
...@@ -8441,7 +8458,8 @@ static dns_dbmethods_t cache_methods = { attach, ...@@ -8441,7 +8458,8 @@ static dns_dbmethods_t cache_methods = { attach,
NULL, /* getsize */ NULL, /* getsize */
setservestalettl, setservestalettl,
getservestalettl, getservestalettl,
NULL }; NULL,
adjusthashsize };
isc_result_t isc_result_t
dns_rbtdb_create(isc_mem_t *mctx, const dns_name_t *origin, dns_dbtype_t type, dns_rbtdb_create(isc_mem_t *mctx, const dns_name_t *origin, dns_dbtype_t type,
......
...@@ -165,7 +165,9 @@ totext_hip(ARGS_TOTEXT) { ...@@ -165,7 +165,9 @@ totext_hip(ARGS_TOTEXT) {
region.length = key_len; region.length = key_len;
RETERR(isc_base64_totext(&region, 1, "", target)); RETERR(isc_base64_totext(&region, 1, "", target));
region.length = length - key_len; region.length = length - key_len;
if (region.length > 0) {
RETERR(str_totext(tctx->linebreak, target)); RETERR(str_totext(tctx->linebreak, target));
}
/* /*
* Rendezvous Servers. * Rendezvous Servers.
...@@ -441,7 +443,7 @@ dns_rdata_hip_next(dns_rdata_hip_t *hip) { ...@@ -441,7 +443,7 @@ dns_rdata_hip_next(dns_rdata_hip_t *hip) {
dns_name_fromregion(&name, &region); dns_name_fromregion(&name, &region);
hip->offset += name.length; hip->offset += name.length;
INSIST(hip->offset <= hip->servers_len); INSIST(hip->offset <= hip->servers_len);
return (ISC_R_SUCCESS); return (hip->offset < hip->servers_len ? ISC_R_SUCCESS : ISC_R_NOMORE);
} }
void void
......
...@@ -2746,6 +2746,7 @@ dns_rpz_find_name(dns_rpz_zones_t *rpzs, dns_rpz_type_t rpz_type, ...@@ -2746,6 +2746,7 @@ dns_rpz_find_name(dns_rpz_zones_t *rpzs, dns_rpz_type_t rpz_type,
nmnode = NULL; nmnode = NULL;
result = dns_rbt_findnode(rpzs->rbt, trig_name, NULL, &nmnode, &chain, result = dns_rbt_findnode(rpzs->rbt, trig_name, NULL, &nmnode, &chain,
DNS_RBTFIND_EMPTYDATA, NULL, NULL); DNS_RBTFIND_EMPTYDATA, NULL, NULL);
switch (result) { switch (result) {
case ISC_R_SUCCESS: case ISC_R_SUCCESS:
nm_data = nmnode->data; nm_data = nmnode->data;
...@@ -2760,7 +2761,42 @@ dns_rpz_find_name(dns_rpz_zones_t *rpzs, dns_rpz_type_t rpz_type, ...@@ -2760,7 +2761,42 @@ dns_rpz_find_name(dns_rpz_zones_t *rpzs, dns_rpz_type_t rpz_type,
case DNS_R_PARTIALMATCH: case DNS_R_PARTIALMATCH:
i = chain.level_matches; i = chain.level_matches;
while (i >= 0 && (nmnode = chain.levels[i]) != NULL) { nmnode = chain.levels[chain.level_matches];
/*
* Whenever an exact match is found by dns_rbt_findnode(),
* the highest level node in the chain will not be put into
* chain->levels[] array, but instead the chain->end
* pointer will be adjusted to point to that node.
*
* Suppose we have the following entries in a rpz zone:
* example.com CNAME rpz-passthru.
* *.example.com CNAME rpz-passthru.
*
* A query for www.example.com would result in the
* following chain object returned by dns_rbt_findnode():
* chain->level_count = 2
* chain->level_matches = 2
* chain->levels[0] = .
* chain->levels[1] = example.com
* chain->levels[2] = NULL
* chain->end = www
*
* Since exact matches only care for testing rpz set bits,
* we need to test for rpz wild bits through iterating the
* nodechain, and that includes testing the rpz wild bits
* in the highest level node found. In the case of an exact
* match, chain->levels[chain->level_matches] will be NULL,
* to address that we must use chain->end as the start
* point, then iterate over the remaining levels in the
* chain.
*/
if (nmnode == NULL) {
--i;
nmnode = chain.end;
}
while (nmnode != NULL) {
nm_data = nmnode->data; nm_data = nmnode->data;
if (nm_data != NULL) { if (nm_data != NULL) {
if (rpz_type == DNS_RPZ_TYPE_QNAME) { if (rpz_type == DNS_RPZ_TYPE_QNAME) {
...@@ -2769,7 +2805,13 @@ dns_rpz_find_name(dns_rpz_zones_t *rpzs, dns_rpz_type_t rpz_type, ...@@ -2769,7 +2805,13 @@ dns_rpz_find_name(dns_rpz_zones_t *rpzs, dns_rpz_type_t rpz_type,
found_zbits |= nm_data->wild.ns; found_zbits |= nm_data->wild.ns;
} }
} }
i--;
if (i >= 0) {
nmnode = chain.levels[i];
--i;
} else {
break;
}
} }
break; break;
......
...@@ -954,7 +954,7 @@ make_log_buf(dns_rrl_t *rrl, dns_rrl_entry_t *e, const char *str1, ...@@ -954,7 +954,7 @@ make_log_buf(dns_rrl_t *rrl, dns_rrl_entry_t *e, const char *str1,
(void)dns_rdatatype_totext(e->key.s.qtype, &lb); (void)dns_rdatatype_totext(e->key.s.qtype, &lb);
} }
} }
snprintf(strbuf, sizeof(strbuf), " (%08x)", snprintf(strbuf, sizeof(strbuf), " (%08" PRIx32 ")",
e->key.s.qname_hash); e->key.s.qname_hash);
add_log_str(&lb, strbuf, strlen(strbuf)); add_log_str(&lb, strbuf, strlen(strbuf));
} }
......
...@@ -1309,7 +1309,8 @@ static dns_dbmethods_t sdb_methods = { ...@@ -1309,7 +1309,8 @@ static dns_dbmethods_t sdb_methods = {
NULL, /* getsize */ NULL, /* getsize */
NULL, /* setservestalettl */ NULL, /* setservestalettl */
NULL, /* getservestalettl */ NULL, /* getservestalettl */
NULL /* setgluecachestats */ NULL, /* setgluecachestats */
NULL /* adjusthashsize */
}; };
static isc_result_t static isc_result_t
......
...@@ -1281,7 +1281,8 @@ static dns_dbmethods_t sdlzdb_methods = { ...@@ -1281,7 +1281,8 @@ static dns_dbmethods_t sdlzdb_methods = {
NULL, /* getsize */ NULL, /* getsize */
NULL, /* setservestalettl */ NULL, /* setservestalettl */
NULL, /* getservestalettl */ NULL, /* getservestalettl */
NULL /* setgluecachestats */ NULL, /* setgluecachestats */
NULL /* adjusthashsize */
}; };
/* /*
......
...@@ -75,6 +75,7 @@ typedef struct text_ok { ...@@ -75,6 +75,7 @@ typedef struct text_ok {
const char *text_in; /* text passed to fromtext_*() */ const char *text_in; /* text passed to fromtext_*() */
const char *text_out; /* text expected from totext_*(); const char *text_out; /* text expected from totext_*();
* NULL indicates text_in is invalid */ * NULL indicates text_in is invalid */
unsigned int loop;
} text_ok_t; } text_ok_t;
/* /*
...@@ -84,6 +85,7 @@ typedef struct wire_ok { ...@@ -84,6 +85,7 @@ typedef struct wire_ok {
unsigned char data[512]; /* RDATA in wire format */ unsigned char data[512]; /* RDATA in wire format */
size_t len; /* octets of data to parse */ size_t len; /* octets of data to parse */
bool ok; /* is this RDATA valid? */ bool ok; /* is this RDATA valid? */
unsigned int loop;
} wire_ok_t; } wire_ok_t;
#define COMPARE(r1, r2, answer) \ #define COMPARE(r1, r2, answer) \
...@@ -97,32 +99,41 @@ typedef struct wire_ok { ...@@ -97,32 +99,41 @@ typedef struct wire_ok {
#define TEXT_VALID_CHANGED(data_in, data_out) \ #define TEXT_VALID_CHANGED(data_in, data_out) \
{ \ { \
data_in, data_out \ data_in, data_out, 0 \
} }
#define TEXT_VALID(data) \ #define TEXT_VALID(data) \
{ \ { \
data, data \ data, data, 0 \
}
#define TEXT_VALID_LOOP(loop, data) \
{ \
data, data, loop \
}
#define TEXT_VALID_LOOPCHG(loop, data_in, data_out) \
{ \
data_in, data_out, loop \
} }
#define TEXT_INVALID(data) \ #define TEXT_INVALID(data) \
{ \ { \
data, NULL \ data, NULL, 0 \
} }
#define TEXT_SENTINEL() TEXT_INVALID(NULL) #define TEXT_SENTINEL() TEXT_INVALID(NULL)
#define VARGC(...) (sizeof((unsigned char[]){ __VA_ARGS__ })) #define VARGC(...) (sizeof((unsigned char[]){ __VA_ARGS__ }))
#define WIRE_TEST(ok, ...) \ #define WIRE_TEST(ok, loop, ...) \
{ \ { \
{ __VA_ARGS__ }, VARGC(__VA_ARGS__), ok \ { __VA_ARGS__ }, VARGC(__VA_ARGS__), ok, loop \
} }
#define WIRE_VALID(...) WIRE_TEST(true, __VA_ARGS__) #define WIRE_VALID(...) WIRE_TEST(true, 0, __VA_ARGS__)
#define WIRE_VALID_LOOP(loop, ...) WIRE_TEST(true, loop, __VA_ARGS__)
/* /*
* WIRE_INVALID() test cases must always have at least one octet specified to * WIRE_INVALID() test cases must always have at least one octet specified to
* distinguish them from WIRE_SENTINEL(). Use the 'empty_ok' parameter passed * distinguish them from WIRE_SENTINEL(). Use the 'empty_ok' parameter passed
* to check_wire_ok() for indicating whether empty RDATA is allowed for a given * to check_wire_ok() for indicating whether empty RDATA is allowed for a given
* RR type or not. * RR type or not.
*/ */
#define WIRE_INVALID(FIRST, ...) WIRE_TEST(false, FIRST, __VA_ARGS__) #define WIRE_INVALID(FIRST, ...) WIRE_TEST(false, 0, FIRST, __VA_ARGS__)
#define WIRE_SENTINEL() WIRE_TEST(false) #define WIRE_SENTINEL() WIRE_TEST(false, 0)
/* /*
* Call dns_rdata_fromwire() for data in 'src', which is 'srclen' octets in * Call dns_rdata_fromwire() for data in 'src', which is 'srclen' octets in
...@@ -252,13 +263,15 @@ rdata_checknames(dns_rdata_t *rdata) { ...@@ -252,13 +263,15 @@ rdata_checknames(dns_rdata_t *rdata) {
* check_text_ok_single() and check_wire_ok_single(). * check_text_ok_single() and check_wire_ok_single().
*/ */
static void static void
check_struct_conversions(dns_rdata_t *rdata, size_t structsize) { check_struct_conversions(dns_rdata_t *rdata, size_t structsize,
unsigned int loop) {
dns_rdataclass_t rdclass = rdata->rdclass; dns_rdataclass_t rdclass = rdata->rdclass;
dns_rdatatype_t type = rdata->type; dns_rdatatype_t type = rdata->type;
isc_result_t result; isc_result_t result;
isc_buffer_t target; isc_buffer_t target;
void *rdata_struct; void *rdata_struct;
char buf[1024]; char buf[1024];
unsigned int count = 0;
rdata_struct = isc_mem_allocate(dt_mctx, structsize); rdata_struct = isc_mem_allocate(dt_mctx, structsize);
assert_non_null(rdata_struct); assert_non_null(rdata_struct);
...@@ -284,6 +297,29 @@ check_struct_conversions(dns_rdata_t *rdata, size_t structsize) { ...@@ -284,6 +297,29 @@ check_struct_conversions(dns_rdata_t *rdata, size_t structsize) {
assert_memory_equal(buf, rdata->data, rdata->length); assert_memory_equal(buf, rdata->data, rdata->length);
/*
* Check that one can walk hip rendezvous servers.
*/