unbound: Vendor import 1.20.0

Release notes at
	https://www.nlnetlabs.nl/news/2024/May/08/unbound-1.20.0-released/

Security:	The DNSBomb vulnerability CVE-2024-33655
This commit is contained in:
Cy Schubert 2024-05-10 13:48:53 -07:00
parent 5a33598e88
commit c2a8005686
128 changed files with 53379 additions and 13271 deletions

View file

@ -1278,7 +1278,8 @@ daemon.lo daemon.o: $(srcdir)/daemon/daemon.c config.h $(srcdir)/daemon/daemon.h
$(srcdir)/util/edns.h $(srcdir)/services/listen_dnsport.h $(srcdir)/services/cache/rrset.h \
$(srcdir)/services/cache/infra.h $(srcdir)/util/rtt.h $(srcdir)/services/localzone.h \
$(srcdir)/services/authzone.h $(srcdir)/services/mesh.h $(srcdir)/services/rpz.h $(srcdir)/respip/respip.h \
$(srcdir)/util/random.h $(srcdir)/util/tube.h $(srcdir)/util/net_help.h $(srcdir)/sldns/keyraw.h
$(srcdir)/util/random.h $(srcdir)/util/tube.h $(srcdir)/util/net_help.h $(srcdir)/sldns/keyraw.h \
$(srcdir)/iterator/iter_fwd.h $(srcdir)/iterator/iter_hints.h
remote.lo remote.o: $(srcdir)/daemon/remote.c config.h $(srcdir)/daemon/remote.h $(srcdir)/daemon/worker.h \
$(srcdir)/libunbound/worker.h $(srcdir)/sldns/sbuffer.h $(srcdir)/util/data/packed_rrset.h \
$(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h $(srcdir)/util/netevent.h \
@ -1355,7 +1356,7 @@ testbound.lo testbound.o: $(srcdir)/testcode/testbound.c config.h $(srcdir)/test
$(srcdir)/util/data/msgparse.h $(srcdir)/sldns/pkthdr.h $(srcdir)/sldns/rrdef.h $(srcdir)/util/tube.h \
$(srcdir)/services/mesh.h $(srcdir)/services/rpz.h $(srcdir)/services/localzone.h $(srcdir)/services/view.h \
$(srcdir)/services/authzone.h $(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h $(srcdir)/libunbound/unbound.h \
$(srcdir)/respip/respip.h $(srcdir)/util/net_help.h $(srcdir)/util/ub_event.h
$(srcdir)/respip/respip.h $(srcdir)/util/net_help.h $(srcdir)/util/ub_event.h $(srcdir)/daemon/worker.h
testpkts.lo testpkts.o: $(srcdir)/testcode/testpkts.c config.h $(srcdir)/testcode/testpkts.h \
$(srcdir)/util/net_help.h $(srcdir)/util/log.h $(srcdir)/sldns/sbuffer.h $(srcdir)/sldns/rrdef.h $(srcdir)/sldns/pkthdr.h \
$(srcdir)/sldns/str2wire.h $(srcdir)/sldns/wire2str.h
@ -1428,7 +1429,7 @@ fake_event.lo fake_event.o: $(srcdir)/testcode/fake_event.c config.h $(srcdir)/t
$(srcdir)/util/tube.h $(srcdir)/services/mesh.h $(srcdir)/services/modstack.h $(srcdir)/services/rpz.h \
$(srcdir)/services/localzone.h $(srcdir)/services/view.h $(srcdir)/sldns/sbuffer.h $(srcdir)/services/authzone.h \
$(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h $(srcdir)/libunbound/unbound.h $(srcdir)/respip/respip.h \
$(srcdir)/sldns/wire2str.h $(srcdir)/sldns/str2wire.h $(srcdir)/daemon/remote.h
$(srcdir)/sldns/wire2str.h $(srcdir)/sldns/str2wire.h $(srcdir)/daemon/remote.h $(srcdir)/util/storage/slabhash.h $(srcdir)/daemon/daemon.h
lock_verify.lo lock_verify.o: $(srcdir)/testcode/lock_verify.c config.h $(srcdir)/util/log.h $(srcdir)/util/rbtree.h \
$(srcdir)/util/locks.h $(srcdir)/util/fptr_wlist.h $(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
$(srcdir)/util/storage/lruhash.h $(srcdir)/util/module.h \
@ -1484,7 +1485,8 @@ context.lo context.o: $(srcdir)/libunbound/context.c config.h $(srcdir)/libunbou
$(srcdir)/util/storage/slabhash.h $(srcdir)/services/cache/infra.h $(srcdir)/util/rtt.h \
$(srcdir)/util/netevent.h $(srcdir)/dnscrypt/dnscrypt.h \
$(srcdir)/services/authzone.h $(srcdir)/services/mesh.h $(srcdir)/services/rpz.h $(srcdir)/daemon/stats.h \
$(srcdir)/util/timehist.h $(srcdir)/respip/respip.h $(srcdir)/util/edns.h
$(srcdir)/util/timehist.h $(srcdir)/respip/respip.h $(srcdir)/util/edns.h \
$(srcdir)/iterator/iter_fwd.h $(srcdir)/iterator/iter_hints.h
libunbound.lo libunbound.o: $(srcdir)/libunbound/libunbound.c $(srcdir)/libunbound/unbound.h \
$(srcdir)/libunbound/unbound-event.h config.h $(srcdir)/libunbound/context.h $(srcdir)/util/locks.h \
$(srcdir)/util/log.h $(srcdir)/util/alloc.h $(srcdir)/util/rbtree.h $(srcdir)/services/modstack.h \
@ -1496,7 +1498,8 @@ libunbound.lo libunbound.o: $(srcdir)/libunbound/libunbound.c $(srcdir)/libunbou
$(srcdir)/sldns/sbuffer.h $(srcdir)/services/cache/infra.h $(srcdir)/util/rtt.h $(srcdir)/util/netevent.h \
$(srcdir)/dnscrypt/dnscrypt.h $(srcdir)/services/cache/rrset.h \
$(srcdir)/util/storage/slabhash.h $(srcdir)/services/authzone.h $(srcdir)/services/mesh.h \
$(srcdir)/services/rpz.h $(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h $(srcdir)/respip/respip.h
$(srcdir)/services/rpz.h $(srcdir)/daemon/stats.h $(srcdir)/util/timehist.h $(srcdir)/respip/respip.h \
$(srcdir)/iterator/iter_fwd.h $(srcdir)/iterator/iter_hints.h
libworker.lo libworker.o: $(srcdir)/libunbound/libworker.c config.h $(srcdir)/libunbound/libworker.h \
$(srcdir)/util/data/packed_rrset.h $(srcdir)/util/storage/lruhash.h $(srcdir)/util/locks.h $(srcdir)/util/log.h \
$(srcdir)/libunbound/context.h $(srcdir)/util/alloc.h $(srcdir)/util/rbtree.h $(srcdir)/services/modstack.h \
@ -1510,8 +1513,7 @@ libworker.lo libworker.o: $(srcdir)/libunbound/libworker.c config.h $(srcdir)/li
$(srcdir)/services/cache/rrset.h $(srcdir)/util/storage/slabhash.h $(srcdir)/services/outbound_list.h \
$(srcdir)/util/fptr_wlist.h $(srcdir)/util/tube.h $(srcdir)/util/regional.h $(srcdir)/util/random.h \
$(srcdir)/util/storage/lookup3.h $(srcdir)/util/net_help.h $(srcdir)/util/data/dname.h \
$(srcdir)/util/data/msgencode.h $(srcdir)/iterator/iter_fwd.h $(srcdir)/iterator/iter_hints.h \
$(srcdir)/sldns/str2wire.h
$(srcdir)/util/data/msgencode.h $(srcdir)/sldns/str2wire.h
unbound-host.lo unbound-host.o: $(srcdir)/smallapp/unbound-host.c config.h $(srcdir)/libunbound/unbound.h \
$(srcdir)/sldns/rrdef.h $(srcdir)/sldns/wire2str.h
asynclook.lo asynclook.o: $(srcdir)/testcode/asynclook.c config.h $(srcdir)/libunbound/unbound.h \

View file

@ -1,39 +1,43 @@
# ===========================================================================
# http://autoconf-archive.cryp.to/ac_pkg_swig.html
# https://www.gnu.org/software/autoconf-archive/ax_pkg_swig.html
# ===========================================================================
#
# SYNOPSIS
#
# AC_PROG_SWIG([major.minor.micro])
# AX_PKG_SWIG([major.minor.micro], [action-if-found], [action-if-not-found])
#
# DESCRIPTION
#
# This macro searches for a SWIG installation on your system. If found you
# should call SWIG via $(SWIG). You can use the optional first argument to
# check if the version of the available SWIG is greater than or equal to
# the value of the argument. It should have the format: N[.N[.N]] (N is a
# number between 0 and 999. Only the first N is mandatory.)
# This macro searches for a SWIG installation on your system. If found,
# then SWIG is AC_SUBST'd; if not found, then $SWIG is empty. If SWIG is
# found, then SWIG_LIB is set to the SWIG library path, and AC_SUBST'd.
#
# If the version argument is given (e.g. 1.3.17), AC_PROG_SWIG checks that
# the swig package is this version number or higher.
# You can use the optional first argument to check if the version of the
# available SWIG is greater than or equal to the value of the argument. It
# should have the format: N[.N[.N]] (N is a number between 0 and 999. Only
# the first N is mandatory.) If the version argument is given (e.g.
# 1.3.17), AX_PKG_SWIG checks that the swig package is this version number
# or higher.
#
# As usual, action-if-found is executed if SWIG is found, otherwise
# action-if-not-found is executed.
#
# In configure.in, use as:
#
# AC_PROG_SWIG(1.3.17)
# SWIG_ENABLE_CXX
# SWIG_MULTI_MODULE_SUPPORT
# SWIG_PYTHON
# AX_PKG_SWIG(1.3.17, [], [ AC_MSG_ERROR([SWIG is required to build..]) ])
# AX_SWIG_ENABLE_CXX
# AX_SWIG_MULTI_MODULE_SUPPORT
# AX_SWIG_PYTHON
#
# LAST MODIFICATION
#
# 2008-04-12
#
# COPYLEFT
# LICENSE
#
# Copyright (c) 2008 Sebastian Huber <sebastian-huber@web.de>
# Copyright (c) 2008 Alan W. Irwin <irwin@beluga.phys.uvic.ca>
# Copyright (c) 2008 Alan W. Irwin
# Copyright (c) 2008 Rafael Laboissiere <rafael@laboissiere.net>
# Copyright (c) 2008 Andrew Collier <colliera@ukzn.ac.za>
# Copyright (c) 2008 Andrew Collier
# Copyright (c) 2011 Murray Cumming <murrayc@openismus.com>
# Copyright (c) 2018 Reini Urban <rurban@cpan.org>
# Copyright (c) 2021 Vincent Danjean <Vincent.Danjean@ens-lyon.org>
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
@ -46,7 +50,7 @@
# 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/>.
# with this program. If not, see <https://www.gnu.org/licenses/>.
#
# As a special exception, the respective Autoconf Macro's copyright owner
# gives unlimited permission to copy, distribute and modify the configure
@ -57,17 +61,21 @@
# all other use of the material that constitutes the Autoconf Macro.
#
# This special exception to the GPL applies to versions of the Autoconf
# Macro released by the Autoconf Macro Archive. When you make and
# distribute a modified version of the Autoconf Macro, you may extend this
# special exception to the GPL to apply to your modified version as well.
# Macro released by the Autoconf Archive. When you make and distribute a
# modified version of the Autoconf Macro, you may extend this special
# exception to the GPL to apply to your modified version as well.
AC_DEFUN([AC_PROG_SWIG],[
AC_PATH_PROG([SWIG],[swig])
#serial 15
AC_DEFUN([AX_PKG_SWIG],[
# Find path to the "swig" executable.
AC_PATH_PROGS([SWIG],[swig swig3.0 swig2.0])
if test -z "$SWIG" ; then
AC_MSG_WARN([cannot find 'swig' program. You should look at http://www.swig.org])
SWIG='echo "Error: SWIG is not installed. You should look at http://www.swig.org" ; false'
elif test -n "$1" ; then
AC_MSG_CHECKING([for SWIG version])
m4_ifval([$3],[$3],[:])
elif test -z "$1" ; then
m4_ifval([$2],[$2],[:])
else
AC_MSG_CHECKING([SWIG version])
[swig_version=`$SWIG -version 2>&1 | grep 'SWIG Version' | sed 's/.*\([0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\).*/\1/g'`]
AC_MSG_RESULT([$swig_version])
if test -n "$swig_version" ; then
@ -77,12 +85,12 @@ AC_DEFUN([AC_PROG_SWIG],[
if test -z "$required_major" ; then
[required_major=0]
fi
[required=`echo $required | sed 's/[0-9]*[^0-9]//'`]
[required=`echo $required. | sed 's/[0-9]*[^0-9]//'`]
[required_minor=`echo $required | sed 's/[^0-9].*//'`]
if test -z "$required_minor" ; then
[required_minor=0]
fi
[required=`echo $required | sed 's/[0-9]*[^0-9]//'`]
[required=`echo $required. | sed 's/[0-9]*[^0-9]//'`]
[required_patch=`echo $required | sed 's/[^0-9].*//'`]
if test -z "$required_patch" ; then
[required_patch=0]
@ -103,30 +111,28 @@ AC_DEFUN([AC_PROG_SWIG],[
if test -z "$available_patch" ; then
[available_patch=0]
fi
[badversion=0]
if test $available_major -lt $required_major ; then
[badversion=1]
fi
if test $available_major -eq $required_major \
-a $available_minor -lt $required_minor ; then
[badversion=1]
fi
if test $available_major -eq $required_major \
-a $available_minor -eq $required_minor \
-a $available_patch -lt $required_patch ; then
[badversion=1]
fi
if test $badversion -eq 1 ; then
AC_MSG_WARN([SWIG version >= $1 is required. You have $swig_version. You should look at http://www.swig.org])
SWIG='echo "Error: SWIG version >= $1 is required. You have '"$swig_version"'. You should look at http://www.swig.org" ; false'
# Convert the version tuple into a single number for easier comparison.
# Using base 100 should be safe since SWIG internally uses BCD values
# to encode its version number.
required_swig_vernum=`expr $required_major \* 10000 \
\+ $required_minor \* 100 \+ $required_patch`
available_swig_vernum=`expr $available_major \* 10000 \
\+ $available_minor \* 100 \+ $available_patch`
if test $available_swig_vernum -lt $required_swig_vernum; then
AC_MSG_WARN([SWIG version >= $1 is required. You have $swig_version.])
SWIG=''
m4_ifval([$3],[$3],[])
else
AC_MSG_NOTICE([SWIG executable is '$SWIG'])
SWIG_LIB=`$SWIG -swiglib`
AC_MSG_NOTICE([SWIG library directory is '$SWIG_LIB'])
AC_MSG_CHECKING([for SWIG library])
SWIG_LIB=`$SWIG -swiglib | tr '\r\n' ' '`
AC_MSG_RESULT([$SWIG_LIB])
m4_ifval([$2],[$2],[])
fi
else
AC_MSG_WARN([cannot determine SWIG version])
SWIG='echo "Error: Cannot determine SWIG version. You should look at http://www.swig.org" ; false'
SWIG=''
m4_ifval([$3],[$3],[])
fi
fi
AC_SUBST([SWIG_LIB])

View file

@ -1,5 +1,5 @@
# ===========================================================================
# http://www.gnu.org/software/autoconf-archive/ax_pthread.html
# https://www.gnu.org/software/autoconf-archive/ax_pthread.html
# ===========================================================================
#
# SYNOPSIS
@ -14,24 +14,28 @@
# flags that are needed. (The user can also force certain compiler
# flags/libs to be tested by setting these environment variables.)
#
# Also sets PTHREAD_CC to any special C compiler that is needed for
# multi-threaded programs (defaults to the value of CC otherwise). (This
# is necessary on AIX to use the special cc_r compiler alias.)
# Also sets PTHREAD_CC and PTHREAD_CXX to any special C compiler that is
# needed for multi-threaded programs (defaults to the value of CC
# respectively CXX otherwise). (This is necessary on e.g. AIX to use the
# special cc_r/CC_r compiler alias.)
#
# NOTE: You are assumed to not only compile your program with these flags,
# but also link it with them as well. e.g. you should link with
# but also to link with them as well. For example, you might link with
# $PTHREAD_CC $CFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS $LIBS
# $PTHREAD_CXX $CXXFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS $LIBS
#
# If you are only building threads programs, you may wish to use these
# If you are only building threaded programs, you may wish to use these
# variables in your default LIBS, CFLAGS, and CC:
#
# LIBS="$PTHREAD_LIBS $LIBS"
# CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
# CXXFLAGS="$CXXFLAGS $PTHREAD_CFLAGS"
# CC="$PTHREAD_CC"
# CXX="$PTHREAD_CXX"
#
# In addition, if the PTHREAD_CREATE_JOINABLE thread-attribute constant
# has a nonstandard name, defines PTHREAD_CREATE_JOINABLE to that name
# (e.g. PTHREAD_CREATE_UNDETACHED on AIX).
# has a nonstandard name, this macro defines PTHREAD_CREATE_JOINABLE to
# that name (e.g. PTHREAD_CREATE_UNDETACHED on AIX).
#
# Also HAVE_PTHREAD_PRIO_INHERIT is defined if pthread is found and the
# PTHREAD_PRIO_INHERIT symbol is defined when compiling with
@ -55,6 +59,7 @@
#
# Copyright (c) 2008 Steven G. Johnson <stevenj@alum.mit.edu>
# Copyright (c) 2011 Daniel Richard G. <skunk@iSKUNK.ORG>
# Copyright (c) 2019 Marc Stevens <marc.stevens@cwi.nl>
#
# This program is free software: you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
@ -67,7 +72,7 @@
# 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/>.
# with this program. If not, see <https://www.gnu.org/licenses/>.
#
# As a special exception, the respective Autoconf Macro's copyright owner
# gives unlimited permission to copy, distribute and modify the configure
@ -82,35 +87,41 @@
# modified version of the Autoconf Macro, you may extend this special
# exception to the GPL to apply to your modified version as well.
#serial 21
#serial 31
AU_ALIAS([ACX_PTHREAD], [AX_PTHREAD])
AC_DEFUN([AX_PTHREAD], [
AC_REQUIRE([AC_CANONICAL_HOST])
AC_REQUIRE([AC_PROG_CC])
AC_REQUIRE([AC_PROG_SED])
AC_LANG_PUSH([C])
ax_pthread_ok=no
# We used to check for pthread.h first, but this fails if pthread.h
# requires special compiler flags (e.g. on True64 or Sequent).
# requires special compiler flags (e.g. on Tru64 or Sequent).
# It gets checked for in the link test anyway.
# First of all, check if the user has set any of the PTHREAD_LIBS,
# etcetera environment variables, and if threads linking works using
# them:
if test x"$PTHREAD_LIBS$PTHREAD_CFLAGS" != x; then
save_CFLAGS="$CFLAGS"
if test "x$PTHREAD_CFLAGS$PTHREAD_LIBS" != "x"; then
ax_pthread_save_CC="$CC"
ax_pthread_save_CFLAGS="$CFLAGS"
ax_pthread_save_LIBS="$LIBS"
AS_IF([test "x$PTHREAD_CC" != "x"], [CC="$PTHREAD_CC"])
AS_IF([test "x$PTHREAD_CXX" != "x"], [CXX="$PTHREAD_CXX"])
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
save_LIBS="$LIBS"
LIBS="$PTHREAD_LIBS $LIBS"
AC_MSG_CHECKING([for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS])
AC_TRY_LINK_FUNC([pthread_join], [ax_pthread_ok=yes])
AC_MSG_CHECKING([for pthread_join using $CC $PTHREAD_CFLAGS $PTHREAD_LIBS])
AC_LINK_IFELSE([AC_LANG_CALL([], [pthread_join])], [ax_pthread_ok=yes])
AC_MSG_RESULT([$ax_pthread_ok])
if test x"$ax_pthread_ok" = xno; then
if test "x$ax_pthread_ok" = "xno"; then
PTHREAD_LIBS=""
PTHREAD_CFLAGS=""
fi
LIBS="$save_LIBS"
CFLAGS="$save_CFLAGS"
CC="$ax_pthread_save_CC"
CFLAGS="$ax_pthread_save_CFLAGS"
LIBS="$ax_pthread_save_LIBS"
fi
# We must check for the threads library under a number of different
@ -118,12 +129,14 @@ fi
# (e.g. DEC) have both -lpthread and -lpthreads, where one of the
# libraries is broken (non-POSIX).
# Create a list of thread flags to try. Items starting with a "-" are
# C compiler flags, and other items are library names, except for "none"
# which indicates that we try without any flags at all, and "pthread-config"
# which is a program returning the flags for the Pth emulation library.
# Create a list of thread flags to try. Items with a "," contain both
# C compiler flags (before ",") and linker flags (after ","). Other items
# starting with a "-" are C compiler flags, and remaining items are
# library names, except for "none" which indicates that we try without
# any flags at all, and "pthread-config" which is a program returning
# the flags for the Pth emulation library.
ax_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config"
ax_pthread_flags="pthreads none -Kthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config"
# The ordering *is* (sometimes) important. Some notes on the
# individual items follow:
@ -132,82 +145,163 @@ ax_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -mt
# none: in case threads are in libc; should be tried before -Kthread and
# other compiler flags to prevent continual compiler warnings
# -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h)
# -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able)
# lthread: LinuxThreads port on FreeBSD (also preferred to -pthread)
# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads)
# -pthreads: Solaris/gcc
# -mthreads: Mingw32/gcc, Lynx/gcc
# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads), Tru64
# (Note: HP C rejects this with "bad form for `-t' option")
# -pthreads: Solaris/gcc (Note: HP C also rejects)
# -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it
# doesn't hurt to check since this sometimes defines pthreads too;
# also defines -D_REENTRANT)
# ... -mt is also the pthreads flag for HP/aCC
# doesn't hurt to check since this sometimes defines pthreads and
# -D_REENTRANT too), HP C (must be checked before -lpthread, which
# is present but should not be used directly; and before -mthreads,
# because the compiler interprets this as "-mt" + "-hreads")
# -mthreads: Mingw32/gcc, Lynx/gcc
# pthread: Linux, etcetera
# --thread-safe: KAI C++
# pthread-config: use pthread-config program (for GNU Pth library)
case ${host_os} in
case $host_os in
freebsd*)
# -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able)
# lthread: LinuxThreads port on FreeBSD (also preferred to -pthread)
ax_pthread_flags="-kthread lthread $ax_pthread_flags"
;;
hpux*)
# From the cc(1) man page: "[-mt] Sets various -D flags to enable
# multi-threading and also sets -lpthread."
ax_pthread_flags="-mt -pthread pthread $ax_pthread_flags"
;;
openedition*)
# IBM z/OS requires a feature-test macro to be defined in order to
# enable POSIX threads at all, so give the user a hint if this is
# not set. (We don't define these ourselves, as they can affect
# other portions of the system API in unpredictable ways.)
AC_EGREP_CPP([AX_PTHREAD_ZOS_MISSING],
[
# if !defined(_OPEN_THREADS) && !defined(_UNIX03_THREADS)
AX_PTHREAD_ZOS_MISSING
# endif
],
[AC_MSG_WARN([IBM z/OS requires -D_OPEN_THREADS or -D_UNIX03_THREADS to enable pthreads support.])])
;;
solaris*)
# On Solaris (at least, for some versions), libc contains stubbed
# (non-functional) versions of the pthreads routines, so link-based
# tests will erroneously succeed. (We need to link with -pthreads/-mt/
# -lpthread.) (The stubs are missing pthread_cleanup_push, or rather
# a function called by this macro, so we could check for that, but
# who knows whether they'll stub that too in a future libc.) So,
# we'll just look for -pthreads and -lpthread first:
# tests will erroneously succeed. (N.B.: The stubs are missing
# pthread_cleanup_push, or rather a function called by this macro,
# so we could check for that, but who knows whether they'll stub
# that too in a future libc.) So we'll check first for the
# standard Solaris way of linking pthreads (-mt -lpthread).
ax_pthread_flags="-pthreads pthread -mt -pthread $ax_pthread_flags"
;;
darwin*)
ax_pthread_flags="-pthread $ax_pthread_flags"
ax_pthread_flags="-mt,-lpthread pthread $ax_pthread_flags"
;;
esac
# Clang doesn't consider unrecognized options an error unless we specify
# -Werror. We throw in some extra Clang-specific options to ensure that
# this doesn't happen for GCC, which also accepts -Werror.
# Are we compiling with Clang?
AC_MSG_CHECKING([if compiler needs -Werror to reject unknown flags])
save_CFLAGS="$CFLAGS"
ax_pthread_extra_flags="-Werror"
CFLAGS="$CFLAGS $ax_pthread_extra_flags -Wunknown-warning-option -Wsizeof-array-argument"
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([int foo(void);],[foo()])],
[AC_MSG_RESULT([yes])],
[ax_pthread_extra_flags=
AC_MSG_RESULT([no])])
CFLAGS="$save_CFLAGS"
AC_CACHE_CHECK([whether $CC is Clang],
[ax_cv_PTHREAD_CLANG],
[ax_cv_PTHREAD_CLANG=no
# Note that Autoconf sets GCC=yes for Clang as well as GCC
if test "x$GCC" = "xyes"; then
AC_EGREP_CPP([AX_PTHREAD_CC_IS_CLANG],
[/* Note: Clang 2.7 lacks __clang_[a-z]+__ */
# if defined(__clang__) && defined(__llvm__)
AX_PTHREAD_CC_IS_CLANG
# endif
],
[ax_cv_PTHREAD_CLANG=yes])
fi
])
ax_pthread_clang="$ax_cv_PTHREAD_CLANG"
if test x"$ax_pthread_ok" = xno; then
for flag in $ax_pthread_flags; do
case $flag in
# GCC generally uses -pthread, or -pthreads on some platforms (e.g. SPARC)
# Note that for GCC and Clang -pthread generally implies -lpthread,
# except when -nostdlib is passed.
# This is problematic using libtool to build C++ shared libraries with pthread:
# [1] https://gcc.gnu.org/bugzilla/show_bug.cgi?id=25460
# [2] https://bugzilla.redhat.com/show_bug.cgi?id=661333
# [3] https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=468555
# To solve this, first try -pthread together with -lpthread for GCC
AS_IF([test "x$GCC" = "xyes"],
[ax_pthread_flags="-pthread,-lpthread -pthread -pthreads $ax_pthread_flags"])
# Clang takes -pthread (never supported any other flag), but we'll try with -lpthread first
AS_IF([test "x$ax_pthread_clang" = "xyes"],
[ax_pthread_flags="-pthread,-lpthread -pthread"])
# The presence of a feature test macro requesting re-entrant function
# definitions is, on some systems, a strong hint that pthreads support is
# correctly enabled
case $host_os in
darwin* | hpux* | linux* | osf* | solaris*)
ax_pthread_check_macro="_REENTRANT"
;;
aix*)
ax_pthread_check_macro="_THREAD_SAFE"
;;
*)
ax_pthread_check_macro="--"
;;
esac
AS_IF([test "x$ax_pthread_check_macro" = "x--"],
[ax_pthread_check_cond=0],
[ax_pthread_check_cond="!defined($ax_pthread_check_macro)"])
if test "x$ax_pthread_ok" = "xno"; then
for ax_pthread_try_flag in $ax_pthread_flags; do
case $ax_pthread_try_flag in
none)
AC_MSG_CHECKING([whether pthreads work without any flags])
;;
*,*)
PTHREAD_CFLAGS=`echo $ax_pthread_try_flag | sed "s/^\(.*\),\(.*\)$/\1/"`
PTHREAD_LIBS=`echo $ax_pthread_try_flag | sed "s/^\(.*\),\(.*\)$/\2/"`
AC_MSG_CHECKING([whether pthreads work with "$PTHREAD_CFLAGS" and "$PTHREAD_LIBS"])
;;
-*)
AC_MSG_CHECKING([whether pthreads work with $flag])
PTHREAD_CFLAGS="$flag"
AC_MSG_CHECKING([whether pthreads work with $ax_pthread_try_flag])
PTHREAD_CFLAGS="$ax_pthread_try_flag"
;;
pthread-config)
AC_CHECK_PROG([ax_pthread_config], [pthread-config], [yes], [no])
if test x"$ax_pthread_config" = xno; then continue; fi
AS_IF([test "x$ax_pthread_config" = "xno"], [continue])
PTHREAD_CFLAGS="`pthread-config --cflags`"
PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`"
;;
*)
AC_MSG_CHECKING([for the pthreads library -l$flag])
PTHREAD_LIBS="-l$flag"
AC_MSG_CHECKING([for the pthreads library -l$ax_pthread_try_flag])
PTHREAD_LIBS="-l$ax_pthread_try_flag"
;;
esac
save_LIBS="$LIBS"
save_CFLAGS="$CFLAGS"
ax_pthread_save_CFLAGS="$CFLAGS"
ax_pthread_save_LIBS="$LIBS"
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
LIBS="$PTHREAD_LIBS $LIBS"
CFLAGS="$CFLAGS $PTHREAD_CFLAGS $ax_pthread_extra_flags"
# Check for various functions. We must include pthread.h,
# since some functions may be macros. (On the Sequent, we
@ -218,8 +312,18 @@ for flag in $ax_pthread_flags; do
# pthread_cleanup_push because it is one of the few pthread
# functions on Solaris that doesn't have a non-functional libc stub.
# We try pthread_create on general principles.
AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <pthread.h>
static void routine(void *a) { *((int*)a) = 0; }
# if $ax_pthread_check_cond
# error "$ax_pthread_check_macro must be defined"
# endif
static void *some_global = NULL;
static void routine(void *a)
{
/* To avoid any unused-parameter or
unused-but-set-parameter warning. */
some_global = a;
}
static void *start_routine(void *a) { return a; }],
[pthread_t th; pthread_attr_t attr;
pthread_create(&th, 0, start_routine, 0);
@ -227,101 +331,187 @@ for flag in $ax_pthread_flags; do
pthread_attr_init(&attr);
pthread_cleanup_push(routine, 0);
pthread_cleanup_pop(0) /* ; */])],
[ax_pthread_ok=yes],
[])
[ax_pthread_ok=yes],
[])
LIBS="$save_LIBS"
CFLAGS="$save_CFLAGS"
CFLAGS="$ax_pthread_save_CFLAGS"
LIBS="$ax_pthread_save_LIBS"
AC_MSG_RESULT([$ax_pthread_ok])
if test "x$ax_pthread_ok" = xyes; then
break;
fi
AS_IF([test "x$ax_pthread_ok" = "xyes"], [break])
PTHREAD_LIBS=""
PTHREAD_CFLAGS=""
done
fi
# Clang needs special handling, because older versions handle the -pthread
# option in a rather... idiosyncratic way
if test "x$ax_pthread_clang" = "xyes"; then
# Clang takes -pthread; it has never supported any other flag
# (Note 1: This will need to be revisited if a system that Clang
# supports has POSIX threads in a separate library. This tends not
# to be the way of modern systems, but it's conceivable.)
# (Note 2: On some systems, notably Darwin, -pthread is not needed
# to get POSIX threads support; the API is always present and
# active. We could reasonably leave PTHREAD_CFLAGS empty. But
# -pthread does define _REENTRANT, and while the Darwin headers
# ignore this macro, third-party headers might not.)
# However, older versions of Clang make a point of warning the user
# that, in an invocation where only linking and no compilation is
# taking place, the -pthread option has no effect ("argument unused
# during compilation"). They expect -pthread to be passed in only
# when source code is being compiled.
#
# Problem is, this is at odds with the way Automake and most other
# C build frameworks function, which is that the same flags used in
# compilation (CFLAGS) are also used in linking. Many systems
# supported by AX_PTHREAD require exactly this for POSIX threads
# support, and in fact it is often not straightforward to specify a
# flag that is used only in the compilation phase and not in
# linking. Such a scenario is extremely rare in practice.
#
# Even though use of the -pthread flag in linking would only print
# a warning, this can be a nuisance for well-run software projects
# that build with -Werror. So if the active version of Clang has
# this misfeature, we search for an option to squash it.
AC_CACHE_CHECK([whether Clang needs flag to prevent "argument unused" warning when linking with -pthread],
[ax_cv_PTHREAD_CLANG_NO_WARN_FLAG],
[ax_cv_PTHREAD_CLANG_NO_WARN_FLAG=unknown
# Create an alternate version of $ac_link that compiles and
# links in two steps (.c -> .o, .o -> exe) instead of one
# (.c -> exe), because the warning occurs only in the second
# step
ax_pthread_save_ac_link="$ac_link"
ax_pthread_sed='s/conftest\.\$ac_ext/conftest.$ac_objext/g'
ax_pthread_link_step=`AS_ECHO(["$ac_link"]) | sed "$ax_pthread_sed"`
ax_pthread_2step_ac_link="($ac_compile) && (echo ==== >&5) && ($ax_pthread_link_step)"
ax_pthread_save_CFLAGS="$CFLAGS"
for ax_pthread_try in '' -Qunused-arguments -Wno-unused-command-line-argument unknown; do
AS_IF([test "x$ax_pthread_try" = "xunknown"], [break])
CFLAGS="-Werror -Wunknown-warning-option $ax_pthread_try -pthread $ax_pthread_save_CFLAGS"
ac_link="$ax_pthread_save_ac_link"
AC_LINK_IFELSE([AC_LANG_SOURCE([[int main(void){return 0;}]])],
[ac_link="$ax_pthread_2step_ac_link"
AC_LINK_IFELSE([AC_LANG_SOURCE([[int main(void){return 0;}]])],
[break])
])
done
ac_link="$ax_pthread_save_ac_link"
CFLAGS="$ax_pthread_save_CFLAGS"
AS_IF([test "x$ax_pthread_try" = "x"], [ax_pthread_try=no])
ax_cv_PTHREAD_CLANG_NO_WARN_FLAG="$ax_pthread_try"
])
case "$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG" in
no | unknown) ;;
*) PTHREAD_CFLAGS="$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG $PTHREAD_CFLAGS" ;;
esac
fi # $ax_pthread_clang = yes
# Various other checks:
if test "x$ax_pthread_ok" = xyes; then
save_LIBS="$LIBS"
LIBS="$PTHREAD_LIBS $LIBS"
save_CFLAGS="$CFLAGS"
if test "x$ax_pthread_ok" = "xyes"; then
ax_pthread_save_CFLAGS="$CFLAGS"
ax_pthread_save_LIBS="$LIBS"
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
LIBS="$PTHREAD_LIBS $LIBS"
# Detect AIX lossage: JOINABLE attribute is called UNDETACHED.
AC_MSG_CHECKING([for joinable pthread attribute])
attr_name=unknown
for attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do
AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <pthread.h>],
[int attr = $attr; return attr /* ; */])],
[attr_name=$attr; break],
[])
done
AC_MSG_RESULT([$attr_name])
if test "$attr_name" != PTHREAD_CREATE_JOINABLE; then
AC_DEFINE_UNQUOTED([PTHREAD_CREATE_JOINABLE], [$attr_name],
[Define to necessary symbol if this constant
uses a non-standard name on your system.])
fi
AC_CACHE_CHECK([for joinable pthread attribute],
[ax_cv_PTHREAD_JOINABLE_ATTR],
[ax_cv_PTHREAD_JOINABLE_ATTR=unknown
for ax_pthread_attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do
AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <pthread.h>],
[int attr = $ax_pthread_attr; return attr /* ; */])],
[ax_cv_PTHREAD_JOINABLE_ATTR=$ax_pthread_attr; break],
[])
done
])
AS_IF([test "x$ax_cv_PTHREAD_JOINABLE_ATTR" != "xunknown" && \
test "x$ax_cv_PTHREAD_JOINABLE_ATTR" != "xPTHREAD_CREATE_JOINABLE" && \
test "x$ax_pthread_joinable_attr_defined" != "xyes"],
[AC_DEFINE_UNQUOTED([PTHREAD_CREATE_JOINABLE],
[$ax_cv_PTHREAD_JOINABLE_ATTR],
[Define to necessary symbol if this constant
uses a non-standard name on your system.])
ax_pthread_joinable_attr_defined=yes
])
AC_MSG_CHECKING([if more special flags are required for pthreads])
flag=no
case ${host_os} in
aix* | freebsd* | darwin*) flag="-D_THREAD_SAFE";;
osf* | hpux*) flag="-D_REENTRANT";;
solaris*)
if test "$GCC" = "yes"; then
flag="-D_REENTRANT"
else
# TODO: What about Clang on Solaris?
flag="-mt -D_REENTRANT"
fi
;;
esac
AC_MSG_RESULT([$flag])
if test "x$flag" != xno; then
PTHREAD_CFLAGS="$flag $PTHREAD_CFLAGS"
fi
AC_CACHE_CHECK([whether more special flags are required for pthreads],
[ax_cv_PTHREAD_SPECIAL_FLAGS],
[ax_cv_PTHREAD_SPECIAL_FLAGS=no
case $host_os in
solaris*)
ax_cv_PTHREAD_SPECIAL_FLAGS="-D_POSIX_PTHREAD_SEMANTICS"
;;
esac
])
AS_IF([test "x$ax_cv_PTHREAD_SPECIAL_FLAGS" != "xno" && \
test "x$ax_pthread_special_flags_added" != "xyes"],
[PTHREAD_CFLAGS="$ax_cv_PTHREAD_SPECIAL_FLAGS $PTHREAD_CFLAGS"
ax_pthread_special_flags_added=yes])
AC_CACHE_CHECK([for PTHREAD_PRIO_INHERIT],
[ax_cv_PTHREAD_PRIO_INHERIT], [
AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <pthread.h>]],
[[int i = PTHREAD_PRIO_INHERIT;]])],
[ax_cv_PTHREAD_PRIO_INHERIT=yes],
[ax_cv_PTHREAD_PRIO_INHERIT=no])
[ax_cv_PTHREAD_PRIO_INHERIT],
[AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <pthread.h>]],
[[int i = PTHREAD_PRIO_INHERIT;
return i;]])],
[ax_cv_PTHREAD_PRIO_INHERIT=yes],
[ax_cv_PTHREAD_PRIO_INHERIT=no])
])
AS_IF([test "x$ax_cv_PTHREAD_PRIO_INHERIT" = "xyes"],
[AC_DEFINE([HAVE_PTHREAD_PRIO_INHERIT], [1], [Have PTHREAD_PRIO_INHERIT.])])
AS_IF([test "x$ax_cv_PTHREAD_PRIO_INHERIT" = "xyes" && \
test "x$ax_pthread_prio_inherit_defined" != "xyes"],
[AC_DEFINE([HAVE_PTHREAD_PRIO_INHERIT], [1], [Have PTHREAD_PRIO_INHERIT.])
ax_pthread_prio_inherit_defined=yes
])
LIBS="$save_LIBS"
CFLAGS="$save_CFLAGS"
CFLAGS="$ax_pthread_save_CFLAGS"
LIBS="$ax_pthread_save_LIBS"
# More AIX lossage: compile with *_r variant
if test "x$GCC" != xyes; then
if test "x$GCC" != "xyes"; then
case $host_os in
aix*)
AS_CASE(["x/$CC"],
[x*/c89|x*/c89_128|x*/c99|x*/c99_128|x*/cc|x*/cc128|x*/xlc|x*/xlc_v6|x*/xlc128|x*/xlc128_v6],
[#handle absolute path differently from PATH based program lookup
AS_CASE(["x$CC"],
[x/*],
[AS_IF([AS_EXECUTABLE_P([${CC}_r])],[PTHREAD_CC="${CC}_r"])],
[AC_CHECK_PROGS([PTHREAD_CC],[${CC}_r],[$CC])])])
[x*/c89|x*/c89_128|x*/c99|x*/c99_128|x*/cc|x*/cc128|x*/xlc|x*/xlc_v6|x*/xlc128|x*/xlc128_v6],
[#handle absolute path differently from PATH based program lookup
AS_CASE(["x$CC"],
[x/*],
[
AS_IF([AS_EXECUTABLE_P([${CC}_r])],[PTHREAD_CC="${CC}_r"])
AS_IF([test "x${CXX}" != "x"], [AS_IF([AS_EXECUTABLE_P([${CXX}_r])],[PTHREAD_CXX="${CXX}_r"])])
],
[
AC_CHECK_PROGS([PTHREAD_CC],[${CC}_r],[$CC])
AS_IF([test "x${CXX}" != "x"], [AC_CHECK_PROGS([PTHREAD_CXX],[${CXX}_r],[$CXX])])
]
)
])
;;
esac
fi
fi
test -n "$PTHREAD_CC" || PTHREAD_CC="$CC"
test -n "$PTHREAD_CXX" || PTHREAD_CXX="$CXX"
AC_SUBST([PTHREAD_LIBS])
AC_SUBST([PTHREAD_CFLAGS])
AC_SUBST([PTHREAD_CC])
AC_SUBST([PTHREAD_CXX])
# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND:
if test x"$ax_pthread_ok" = xyes; then
if test "x$ax_pthread_ok" = "xyes"; then
ifelse([$1],,[AC_DEFINE([HAVE_PTHREAD],[1],[Define if you have POSIX threads libraries and header files.])],[$1])
:
else

View file

@ -50,6 +50,8 @@
#include "util/data/msgreply.h"
#include "util/data/msgencode.h"
#include "services/cache/dns.h"
#include "services/mesh.h"
#include "services/modstack.h"
#include "validator/val_neg.h"
#include "validator/val_secalgo.h"
#include "iterator/iter_utils.h"
@ -265,15 +267,6 @@ cachedb_init(struct module_env* env, int id)
return 0;
}
cachedb_env->enabled = 1;
if(env->cfg->serve_expired && env->cfg->serve_expired_reply_ttl)
log_warn(
"cachedb: serve-expired-reply-ttl is set but not working for data "
"originating from the external cache; 0 TTL is used for those.");
if(env->cfg->serve_expired && env->cfg->serve_expired_client_timeout)
log_warn(
"cachedb: serve-expired-client-timeout is set but not working for "
"data originating from the external cache; expired data are used "
"in the reply without first trying to refresh the data.");
return 1;
}
@ -511,9 +504,38 @@ adjust_msg_ttl(struct dns_msg* msg, time_t adjust)
}
}
/* Set the TTL of the given RRset to fixed value. */
static void
packed_rrset_ttl_set(struct packed_rrset_data* data, time_t ttl)
{
size_t i;
size_t total = data->count + data->rrsig_count;
data->ttl = ttl;
for(i=0; i<total; i++) {
data->rr_ttl[i] = ttl;
}
data->ttl_add = 0;
}
/* Set the TTL of a DNS message and its RRs by to a fixed value. */
static void
set_msg_ttl(struct dns_msg* msg, time_t ttl)
{
size_t i;
msg->rep->ttl = ttl;
msg->rep->prefetch_ttl = PREFETCH_TTL_CALC(msg->rep->ttl);
msg->rep->serve_expired_ttl = msg->rep->ttl + SERVE_EXPIRED_TTL;
for(i=0; i<msg->rep->rrset_count; i++) {
packed_rrset_ttl_set((struct packed_rrset_data*)msg->
rep->rrsets[i]->entry.data, ttl);
}
}
/** convert dns message in buffer to return_msg */
static int
parse_data(struct module_qstate* qstate, struct sldns_buffer* buf)
parse_data(struct module_qstate* qstate, struct sldns_buffer* buf,
int* msg_expired)
{
struct msg_parse* prs;
struct edns_data edns;
@ -583,6 +605,7 @@ parse_data(struct module_qstate* qstate, struct sldns_buffer* buf)
adjust = *qstate->env->now - (time_t)timestamp;
if(qstate->return_msg->rep->ttl < adjust) {
verbose(VERB_ALGO, "cachedb msg expired");
*msg_expired = 1;
/* If serve-expired is enabled, we still use an expired message
* setting the TTL to 0. */
if(!qstate->env->cfg->serve_expired ||
@ -605,6 +628,7 @@ parse_data(struct module_qstate* qstate, struct sldns_buffer* buf)
* 'now' should be redundant given how these values were calculated,
* but we check it just in case as does good_expiry_and_qinfo(). */
if(qstate->env->cfg->serve_expired &&
!qstate->env->cfg->serve_expired_client_timeout &&
(adjust == -1 || (time_t)expiry < *qstate->env->now)) {
qstate->need_refetch = 1;
}
@ -617,7 +641,8 @@ parse_data(struct module_qstate* qstate, struct sldns_buffer* buf)
* return true if lookup was successful.
*/
static int
cachedb_extcache_lookup(struct module_qstate* qstate, struct cachedb_env* ie)
cachedb_extcache_lookup(struct module_qstate* qstate, struct cachedb_env* ie,
int* msg_expired)
{
char key[(CACHEDB_HASHSIZE/8)*2+1];
calc_hash(qstate, key, sizeof(key));
@ -634,7 +659,7 @@ cachedb_extcache_lookup(struct module_qstate* qstate, struct cachedb_env* ie)
}
/* parse dns message into return_msg */
if( !parse_data(qstate, qstate->env->scratch_buffer) ) {
if( !parse_data(qstate, qstate->env->scratch_buffer, msg_expired) ) {
return 0;
}
return 1;
@ -666,6 +691,7 @@ cachedb_extcache_store(struct module_qstate* qstate, struct cachedb_env* ie)
static int
cachedb_intcache_lookup(struct module_qstate* qstate, struct cachedb_env* cde)
{
uint8_t dpname_storage[LDNS_MAX_DOMAINLEN+1];
uint8_t* dpname=NULL;
size_t dpnamelen=0;
struct dns_msg* msg;
@ -674,7 +700,7 @@ cachedb_intcache_lookup(struct module_qstate* qstate, struct cachedb_env* cde)
return 0;
}
if(iter_stub_fwd_no_cache(qstate, &qstate->qinfo,
&dpname, &dpnamelen))
&dpname, &dpnamelen, dpname_storage, sizeof(dpname_storage)))
return 0; /* no cache for these queries */
msg = dns_cache_lookup(qstate->env, qstate->qinfo.qname,
qstate->qinfo.qname_len, qstate->qinfo.qtype,
@ -705,17 +731,39 @@ cachedb_intcache_lookup(struct module_qstate* qstate, struct cachedb_env* cde)
* Store query into the internal cache of unbound.
*/
static void
cachedb_intcache_store(struct module_qstate* qstate)
cachedb_intcache_store(struct module_qstate* qstate, int msg_expired)
{
uint32_t store_flags = qstate->query_flags;
int serve_expired = qstate->env->cfg->serve_expired;
if(qstate->env->cfg->serve_expired)
store_flags |= DNSCACHE_STORE_ZEROTTL;
if(!qstate->return_msg)
return;
if(serve_expired && msg_expired) {
/* Set TTLs to a value such that value + *env->now is
* going to be now-3 seconds. Making it expired
* in the cache. */
set_msg_ttl(qstate->return_msg, (time_t)-3);
}
(void)dns_cache_store(qstate->env, &qstate->qinfo,
qstate->return_msg->rep, 0, qstate->prefetch_leeway, 0,
qstate->region, store_flags, qstate->qstarttime);
if(serve_expired && msg_expired) {
if(qstate->env->cfg->serve_expired_client_timeout) {
/* No expired response from the query state, the
* query resolution needs to continue and it can
* pick up the expired result after the timer out
* of cache. */
return;
}
/* set TTLs to zero again */
adjust_msg_ttl(qstate->return_msg, -1);
/* Send serve expired responses based on the cachedb
* returned message, that was just stored in the cache.
* It can then continue to work on this query. */
mesh_respond_serve_expired(qstate->mesh_info);
}
}
/**
@ -731,6 +779,7 @@ cachedb_handle_query(struct module_qstate* qstate,
struct cachedb_qstate* ATTR_UNUSED(iq),
struct cachedb_env* ie, int id)
{
int msg_expired = 0;
qstate->is_cachedb_answer = 0;
/* check if we are enabled, and skip if so */
if(!ie->enabled) {
@ -765,20 +814,28 @@ cachedb_handle_query(struct module_qstate* qstate,
}
/* ask backend cache to see if we have data */
if(cachedb_extcache_lookup(qstate, ie)) {
if(cachedb_extcache_lookup(qstate, ie, &msg_expired)) {
if(verbosity >= VERB_ALGO)
log_dns_msg(ie->backend->name,
&qstate->return_msg->qinfo,
qstate->return_msg->rep);
/* store this result in internal cache */
cachedb_intcache_store(qstate);
cachedb_intcache_store(qstate, msg_expired);
/* In case we have expired data but there is a client timer for expired
* answers, pass execution to next module in order to try updating the
* data first.
* TODO: this needs revisit. The expired data stored from cachedb has
* 0 TTL which is picked up by iterator later when looking in the cache.
* Document that ext cachedb does not work properly with
* serve_stale_reply_ttl yet. */
*/
if(qstate->env->cfg->serve_expired && msg_expired) {
qstate->return_msg = NULL;
qstate->ext_state[id] = module_wait_module;
/* The expired reply is sent with
* mesh_respond_serve_expired, and so
* the need_refetch is not used. */
qstate->need_refetch = 0;
return;
}
if(qstate->need_refetch && qstate->serve_expired_data &&
qstate->serve_expired_data->timer) {
qstate->return_msg = NULL;
@ -791,6 +848,14 @@ cachedb_handle_query(struct module_qstate* qstate,
return;
}
if(qstate->serve_expired_data &&
qstate->env->cfg->cachedb_check_when_serve_expired &&
!qstate->env->cfg->serve_expired_client_timeout) {
/* Reply with expired data if any to client, because cachedb
* also has no useful, current data */
mesh_respond_serve_expired(qstate->mesh_info);
}
/* no cache fetches */
/* pass request to next module */
qstate->ext_state[id] = module_wait_module;
@ -923,4 +988,36 @@ cachedb_get_funcblock(void)
{
return &cachedb_block;
}
int
cachedb_is_enabled(struct module_stack* mods, struct module_env* env)
{
struct cachedb_env* ie;
int id = modstack_find(mods, "cachedb");
if(id == -1)
return 0;
ie = (struct cachedb_env*)env->modinfo[id];
if(ie && ie->enabled)
return 1;
return 0;
}
void cachedb_msg_remove(struct module_qstate* qstate)
{
char key[(CACHEDB_HASHSIZE/8)*2+1];
int id = modstack_find(qstate->env->modstack, "cachedb");
struct cachedb_env* ie = (struct cachedb_env*)qstate->env->modinfo[id];
log_query_info(VERB_ALGO, "cachedb msg remove", &qstate->qinfo);
calc_hash(qstate, key, sizeof(key));
sldns_buffer_clear(qstate->env->scratch_buffer);
sldns_buffer_write_u32(qstate->env->scratch_buffer, 0);
sldns_buffer_flip(qstate->env->scratch_buffer);
/* call backend */
(*ie->backend->store)(qstate->env, ie, key,
sldns_buffer_begin(qstate->env->scratch_buffer),
sldns_buffer_limit(qstate->env->scratch_buffer),
0);
}
#endif /* USE_CACHEDB */

View file

@ -41,6 +41,7 @@
*/
#include "util/module.h"
struct cachedb_backend;
struct module_stack;
/**
* The global variable environment contents for the cachedb
@ -110,3 +111,18 @@ size_t cachedb_get_mem(struct module_env* env, int id);
*/
struct module_func_block* cachedb_get_funcblock(void);
/**
* See if the cachedb is enabled.
* @param mods: module stack. It finds the cachedb module environment.
* @param env: module environment.
* @return true if exists and enabled.
*/
int cachedb_is_enabled(struct module_stack* mods, struct module_env* env);
/**
* Remove a message from the global cache. Because edns subnet has a more
* specific entry, and if not removed when everything expires, the global
* entry is used, instead of a fresh lookup of the edns subnet entry.
* @param qstate: query state.
*/
void cachedb_msg_remove(struct module_qstate* qstate);

View file

@ -379,8 +379,8 @@
/* Define to 1 if you have the `memmove' function. */
#undef HAVE_MEMMOVE
/* Define to 1 if you have the <memory.h> header file. */
#undef HAVE_MEMORY_H
/* Define to 1 if you have the <minix/config.h> header file. */
#undef HAVE_MINIX_CONFIG_H
/* Define to 1 if you have the <netdb.h> header file. */
#undef HAVE_NETDB_H
@ -587,6 +587,9 @@
/* Define to 1 if you have the <stdint.h> header file. */
#undef HAVE_STDINT_H
/* Define to 1 if you have the <stdio.h> header file. */
#undef HAVE_STDIO_H
/* Define to 1 if you have the <stdlib.h> header file. */
#undef HAVE_STDLIB_H
@ -689,6 +692,9 @@
/* Define to 1 if you have the <vfork.h> header file. */
#undef HAVE_VFORK_H
/* Define to 1 if you have the <wchar.h> header file. */
#undef HAVE_WCHAR_H
/* Define to 1 if you have the <windows.h> header file. */
#undef HAVE_WINDOWS_H
@ -830,7 +836,9 @@
/* Define to 1 if libsodium supports sodium_set_misuse_handler */
#undef SODIUM_MISUSE_HANDLER
/* Define to 1 if you have the ANSI C header files. */
/* Define to 1 if all of the C90 standard headers exist (not just the ones
required in a freestanding environment). This macro is provided for
backward compatibility; new code need not use it. */
#undef STDC_HEADERS
/* use default strptime. */
@ -926,21 +934,87 @@
#ifndef _ALL_SOURCE
# undef _ALL_SOURCE
#endif
/* Enable general extensions on macOS. */
#ifndef _DARWIN_C_SOURCE
# undef _DARWIN_C_SOURCE
#endif
/* Enable general extensions on Solaris. */
#ifndef __EXTENSIONS__
# undef __EXTENSIONS__
#endif
/* Enable GNU extensions on systems that have them. */
#ifndef _GNU_SOURCE
# undef _GNU_SOURCE
#endif
/* Enable threading extensions on Solaris. */
/* Enable X/Open compliant socket functions that do not require linking
with -lxnet on HP-UX 11.11. */
#ifndef _HPUX_ALT_XOPEN_SOCKET_API
# undef _HPUX_ALT_XOPEN_SOCKET_API
#endif
/* Identify the host operating system as Minix.
This macro does not affect the system headers' behavior.
A future release of Autoconf may stop defining this macro. */
#ifndef _MINIX
# undef _MINIX
#endif
/* Enable general extensions on NetBSD.
Enable NetBSD compatibility extensions on Minix. */
#ifndef _NETBSD_SOURCE
# undef _NETBSD_SOURCE
#endif
/* Enable OpenBSD compatibility extensions on NetBSD.
Oddly enough, this does nothing on OpenBSD. */
#ifndef _OPENBSD_SOURCE
# undef _OPENBSD_SOURCE
#endif
/* Define to 1 if needed for POSIX-compatible behavior. */
#ifndef _POSIX_SOURCE
# undef _POSIX_SOURCE
#endif
/* Define to 2 if needed for POSIX-compatible behavior. */
#ifndef _POSIX_1_SOURCE
# undef _POSIX_1_SOURCE
#endif
/* Enable POSIX-compatible threading on Solaris. */
#ifndef _POSIX_PTHREAD_SEMANTICS
# undef _POSIX_PTHREAD_SEMANTICS
#endif
/* Enable extensions specified by ISO/IEC TS 18661-5:2014. */
#ifndef __STDC_WANT_IEC_60559_ATTRIBS_EXT__
# undef __STDC_WANT_IEC_60559_ATTRIBS_EXT__
#endif
/* Enable extensions specified by ISO/IEC TS 18661-1:2014. */
#ifndef __STDC_WANT_IEC_60559_BFP_EXT__
# undef __STDC_WANT_IEC_60559_BFP_EXT__
#endif
/* Enable extensions specified by ISO/IEC TS 18661-2:2015. */
#ifndef __STDC_WANT_IEC_60559_DFP_EXT__
# undef __STDC_WANT_IEC_60559_DFP_EXT__
#endif
/* Enable extensions specified by ISO/IEC TS 18661-4:2015. */
#ifndef __STDC_WANT_IEC_60559_FUNCS_EXT__
# undef __STDC_WANT_IEC_60559_FUNCS_EXT__
#endif
/* Enable extensions specified by ISO/IEC TS 18661-3:2015. */
#ifndef __STDC_WANT_IEC_60559_TYPES_EXT__
# undef __STDC_WANT_IEC_60559_TYPES_EXT__
#endif
/* Enable extensions specified by ISO/IEC TR 24731-2:2010. */
#ifndef __STDC_WANT_LIB_EXT2__
# undef __STDC_WANT_LIB_EXT2__
#endif
/* Enable extensions specified by ISO/IEC 24747:2009. */
#ifndef __STDC_WANT_MATH_SPEC_FUNCS__
# undef __STDC_WANT_MATH_SPEC_FUNCS__
#endif
/* Enable extensions on HP NonStop. */
#ifndef _TANDEM_SOURCE
# undef _TANDEM_SOURCE
#endif
/* Enable general extensions on Solaris. */
#ifndef __EXTENSIONS__
# undef __EXTENSIONS__
/* Enable X/Open extensions. Define to 500 only if necessary
to make mbstate_t available. */
#ifndef _XOPEN_SOURCE
# undef _XOPEN_SOURCE
#endif
@ -966,11 +1040,6 @@
`char[]'. */
#undef YYTEXT_POINTER
/* Enable large inode numbers on Mac OS X 10.5. */
#ifndef _DARWIN_USE_64_BIT_INODE
# define _DARWIN_USE_64_BIT_INODE 1
#endif
/* Number of bits in a file offset, on hosts where this is settable. */
#undef _FILE_OFFSET_BITS
@ -980,19 +1049,9 @@
/* Define for large files, on AIX-style hosts. */
#undef _LARGE_FILES
/* Define to 1 if on MINIX. */
#undef _MINIX
/* Enable for compile on Minix */
#undef _NETBSD_SOURCE
/* Define to 2 if the system does not provide POSIX.1 features except with
this defined. */
#undef _POSIX_1_SOURCE
/* Define to 1 if you need to in order for `stat' and other things to work. */
#undef _POSIX_SOURCE
/* defined to use gcc ansi snprintf and sscanf that understands %lld when
compiled for windows. */
#undef __USE_MINGW_ANSI_STDIO
@ -1033,7 +1092,7 @@
/* Define to `long int' if <sys/types.h> does not define. */
#undef off_t
/* Define to `int' if <sys/types.h> does not define. */
/* Define as a signed integer type capable of holding a process identifier. */
#undef pid_t
/* Define to 'int' if not defined */

12608
configure vendored

File diff suppressed because it is too large Load diff

View file

@ -4,21 +4,21 @@ AC_PREREQ([2.56])
sinclude(acx_nlnetlabs.m4)
sinclude(ax_pthread.m4)
sinclude(acx_python.m4)
sinclude(ac_pkg_swig.m4)
sinclude(ax_pkg_swig.m4)
sinclude(dnstap/dnstap.m4)
sinclude(dnscrypt/dnscrypt.m4)
# must be numbers. ac_defun because of later processing
m4_define([VERSION_MAJOR],[1])
m4_define([VERSION_MINOR],[19])
m4_define([VERSION_MICRO],[3])
m4_define([VERSION_MINOR],[20])
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=26
LIBUNBOUND_REVISION=27
LIBUNBOUND_AGE=1
# 1.0.0 had 0:12:0
# 1.0.1 had 0:13:0
@ -112,6 +112,7 @@ LIBUNBOUND_AGE=1
# 1.19.1 had 9:24:1
# 1.19.2 had 9:25:1
# 1.19.3 had 9:26:1
# 1.20.0 had 9:27:1
# Current -- the number of the binary API that we're implementing
# Revision -- which iteration of the implementation of the binary
@ -273,6 +274,9 @@ AC_DEFINE(WINVER, 0x0502, [the version of the windows API enabled])
ACX_RSRC_VERSION(wnvs)
AC_DEFINE_UNQUOTED(RSRC_PACKAGE_VERSION, [$wnvs], [version number for resource files])
# Check for 'grep -e' program, here, since ACX_CHECK_FLTO needs that.
AC_PROG_GREP
# Checks for typedefs, structures, and compiler characteristics.
AC_C_CONST
AC_LANG([C])
@ -795,9 +799,9 @@ if test x_$ub_test_python != x_no; then
ub_have_swig=no
AC_ARG_ENABLE(swig-version-check, AS_HELP_STRING([--disable-swig-version-check],[Disable swig version check to build python modules with older swig even though that is unreliable]))
if test "$enable_swig_version_check" = "yes"; then
AC_PROG_SWIG(2.0.1)
AX_PKG_SWIG(2.0.1)
else
AC_PROG_SWIG
AX_PKG_SWIG
fi
AC_MSG_CHECKING(SWIG)
if test ! -x "$SWIG"; then

26616
configure~ Executable file

File diff suppressed because it is too large Load diff

View file

@ -22,4 +22,13 @@ pidfile=${unbound_pidfile:-"/usr/local/etc/unbound/unbound.pid"}
command_args=${unbound_flags:-"-c /usr/local/etc/unbound/unbound.conf"}
extra_commands="reload"
if test "$1" = "stop" ; then
run_rc_command "$1"
ret=$?
if test $ret -eq 0; then
rm -f "$pidfile"
fi
exit $ret
fi
run_rc_command "$1"

View file

@ -75,6 +75,7 @@ stop() {
retval=$?
echo
[ $retval -eq 0 ] && rm -f $lockfile
[ $retval -eq 0 ] && rm -f $pidfile
if egrep -q '^/[^[:space:]]+[[:space:]]+'${rootdir}'/dev/log' /proc/mounts; then
umount ${rootdir}/dev/log >/dev/null 2>&1
fi;

View file

@ -58,6 +58,7 @@ stop() {
killproc -p $pidfile unbound
retval=$?
[ $retval -eq 0 ] && rm -f $lockfile
[ $retval -eq 0 ] && rm -f $pidfile
for mountfile in /dev/log /dev/urandom /etc/localtime /etc/resolv.conf /var/run/unbound
do
if egrep -q '^/[^[:space:]]+[[:space:]]+'${rootdir}''${mountfile}'' /proc/mounts; then

View file

@ -75,6 +75,7 @@ stop() {
retval=$?
echo
[ $retval -eq 0 ] && rm -f $lockfile
[ $retval -eq 0 ] && rm -f $pidfile
if egrep -q '^/[^[:space:]]+[[:space:]]+'${rootdir}'/dev/log' /proc/mounts; then
umount ${rootdir}/dev/log >/dev/null 2>&1
fi;

View file

@ -839,6 +839,7 @@ int print_deleg_lookup(RES* ssl, struct worker* worker, uint8_t* nm,
char b[260];
struct query_info qinfo;
struct iter_hints_stub* stub;
int nolock = 0;
regional_free_all(region);
qinfo.qname = nm;
qinfo.qname_len = nmlen;
@ -850,13 +851,16 @@ int print_deleg_lookup(RES* ssl, struct worker* worker, uint8_t* nm,
if(!ssl_printf(ssl, "The following name servers are used for lookup "
"of %s\n", b))
return 0;
dp = forwards_lookup(worker->env.fwds, nm, qinfo.qclass);
dp = forwards_lookup(worker->env.fwds, nm, qinfo.qclass, nolock);
if(dp) {
if(!ssl_printf(ssl, "forwarding request:\n"))
if(!ssl_printf(ssl, "forwarding request:\n")) {
lock_rw_unlock(&worker->env.fwds->lock);
return 0;
}
print_dp_main(ssl, dp, NULL);
print_dp_details(ssl, worker, dp);
lock_rw_unlock(&worker->env.fwds->lock);
return 1;
}
@ -892,21 +896,26 @@ int print_deleg_lookup(RES* ssl, struct worker* worker, uint8_t* nm,
return 0;
continue;
}
}
}
stub = hints_lookup_stub(worker->env.hints, nm, qinfo.qclass,
dp);
dp, nolock);
if(stub) {
if(stub->noprime) {
if(!ssl_printf(ssl, "The noprime stub servers "
"are used:\n"))
"are used:\n")) {
lock_rw_unlock(&worker->env.hints->lock);
return 0;
}
} else {
if(!ssl_printf(ssl, "The stub is primed "
"with servers:\n"))
"with servers:\n")) {
lock_rw_unlock(&worker->env.hints->lock);
return 0;
}
}
print_dp_main(ssl, stub->dp, NULL);
print_dp_details(ssl, worker, stub->dp);
lock_rw_unlock(&worker->env.hints->lock);
} else {
print_dp_main(ssl, dp, msg);
print_dp_details(ssl, worker, dp);

View file

@ -91,6 +91,8 @@
#include "util/net_help.h"
#include "sldns/keyraw.h"
#include "respip/respip.h"
#include "iterator/iter_fwd.h"
#include "iterator/iter_hints.h"
#include <signal.h>
#ifdef HAVE_SYSTEMD
@ -99,6 +101,9 @@
#ifdef HAVE_NETDB_H
#include <netdb.h>
#endif
#ifdef USE_CACHEDB
#include "cachedb/cachedb.h"
#endif
/** How many quit requests happened. */
static int sig_record_quit = 0;
@ -260,6 +265,7 @@ daemon_init(void)
free(daemon);
return NULL;
}
daemon->env->modstack = &daemon->mods;
/* init edns_known_options */
if(!edns_known_options_init(daemon->env)) {
free(daemon->env);
@ -321,17 +327,15 @@ static int setup_acl_for_ports(struct acl_list* list,
struct listen_port* port_list)
{
struct acl_addr* acl_node;
struct addrinfo* addr;
for(; port_list; port_list=port_list->next) {
if(!port_list->socket) {
/* This is mainly for testbound where port_list is
* empty. */
continue;
}
addr = port_list->socket->addr;
if(!(acl_node = acl_interface_insert(list,
(struct sockaddr_storage*)addr->ai_addr,
(socklen_t)addr->ai_addrlen,
(struct sockaddr_storage*)port_list->socket->addr,
port_list->socket->addrlen,
acl_refuse))) {
return 0;
}
@ -716,6 +720,12 @@ daemon_fork(struct daemon* daemon)
fatal_exit("Could not create local zones: out of memory");
if(!local_zones_apply_cfg(daemon->local_zones, daemon->cfg))
fatal_exit("Could not set up local zones");
if(!(daemon->env->fwds = forwards_create()) ||
!forwards_apply_cfg(daemon->env->fwds, daemon->cfg))
fatal_exit("Could not set forward zones");
if(!(daemon->env->hints = hints_create()) ||
!hints_apply_cfg(daemon->env->hints, daemon->cfg))
fatal_exit("Could not set root or stub hints");
/* process raw response-ip configuration data */
if(!(daemon->respip_set = respip_set_create()))
@ -740,6 +750,10 @@ daemon_fork(struct daemon* daemon)
if(!edns_strings_apply_cfg(daemon->env->edns_strings, daemon->cfg))
fatal_exit("Could not set up EDNS strings");
#ifdef USE_CACHEDB
daemon->env->cachedb_enabled = cachedb_is_enabled(&daemon->mods,
daemon->env);
#endif
/* response-ip-xxx options don't work as expected without the respip
* module. To avoid run-time operational surprise we reject such
* configuration. */
@ -832,6 +846,10 @@ daemon_cleanup(struct daemon* daemon)
slabhash_clear(daemon->env->msg_cache);
}
daemon->old_num = daemon->num; /* save the current num */
forwards_delete(daemon->env->fwds);
daemon->env->fwds = NULL;
hints_delete(daemon->env->hints);
daemon->env->hints = NULL;
local_zones_delete(daemon->local_zones);
daemon->local_zones = NULL;
respip_set_delete(daemon->respip_set);

View file

@ -1992,12 +1992,19 @@ static int
print_root_fwds(RES* ssl, struct iter_forwards* fwds, uint8_t* root)
{
struct delegpt* dp;
dp = forwards_lookup(fwds, root, LDNS_RR_CLASS_IN);
if(!dp)
int nolock = 0;
dp = forwards_lookup(fwds, root, LDNS_RR_CLASS_IN, nolock);
if(!dp) {
return ssl_printf(ssl, "off (using root hints)\n");
}
/* if dp is returned it must be the root */
log_assert(query_dname_compare(dp->name, root)==0);
return ssl_print_name_dp(ssl, NULL, root, LDNS_RR_CLASS_IN, dp);
if(!ssl_print_name_dp(ssl, NULL, root, LDNS_RR_CLASS_IN, dp)) {
lock_rw_unlock(&fwds->lock);
return 0;
}
lock_rw_unlock(&fwds->lock);
return 1;
}
/** parse args into delegpt */
@ -2069,6 +2076,7 @@ do_forward(RES* ssl, struct worker* worker, char* args)
{
struct iter_forwards* fwd = worker->env.fwds;
uint8_t* root = (uint8_t*)"\000";
int nolock = 0;
if(!fwd) {
(void)ssl_printf(ssl, "error: structure not allocated\n");
return;
@ -2082,12 +2090,12 @@ do_forward(RES* ssl, struct worker* worker, char* args)
/* delete all the existing queries first */
mesh_delete_all(worker->env.mesh);
if(strcmp(args, "off") == 0) {
forwards_delete_zone(fwd, LDNS_RR_CLASS_IN, root);
forwards_delete_zone(fwd, LDNS_RR_CLASS_IN, root, nolock);
} else {
struct delegpt* dp;
if(!(dp = parse_delegpt(ssl, args, root)))
return;
if(!forwards_add_zone(fwd, LDNS_RR_CLASS_IN, dp)) {
if(!forwards_add_zone(fwd, LDNS_RR_CLASS_IN, dp, nolock)) {
(void)ssl_printf(ssl, "error out of memory\n");
return;
}
@ -2097,7 +2105,7 @@ do_forward(RES* ssl, struct worker* worker, char* args)
static int
parse_fs_args(RES* ssl, char* args, uint8_t** nm, struct delegpt** dp,
int* insecure, int* prime)
int* insecure, int* prime, int* tls)
{
char* zonename;
char* rest;
@ -2112,6 +2120,8 @@ parse_fs_args(RES* ssl, char* args, uint8_t** nm, struct delegpt** dp,
*insecure = 1;
else if(*args == 'p' && prime)
*prime = 1;
else if(*args == 't' && tls)
*tls = 1;
else {
(void)ssl_printf(ssl, "error: unknown option %s\n", args);
return 0;
@ -2144,25 +2154,33 @@ static void
do_forward_add(RES* ssl, struct worker* worker, char* args)
{
struct iter_forwards* fwd = worker->env.fwds;
int insecure = 0;
int insecure = 0, tls = 0;
uint8_t* nm = NULL;
struct delegpt* dp = NULL;
if(!parse_fs_args(ssl, args, &nm, &dp, &insecure, NULL))
int nolock = 1;
if(!parse_fs_args(ssl, args, &nm, &dp, &insecure, NULL, &tls))
return;
if(tls)
dp->ssl_upstream = 1;
/* prelock forwarders for atomic operation with anchors */
lock_rw_wrlock(&fwd->lock);
if(insecure && worker->env.anchors) {
if(!anchors_add_insecure(worker->env.anchors, LDNS_RR_CLASS_IN,
nm)) {
lock_rw_unlock(&fwd->lock);
(void)ssl_printf(ssl, "error out of memory\n");
delegpt_free_mlc(dp);
free(nm);
return;
}
}
if(!forwards_add_zone(fwd, LDNS_RR_CLASS_IN, dp)) {
if(!forwards_add_zone(fwd, LDNS_RR_CLASS_IN, dp, nolock)) {
lock_rw_unlock(&fwd->lock);
(void)ssl_printf(ssl, "error out of memory\n");
free(nm);
return;
}
lock_rw_unlock(&fwd->lock);
free(nm);
send_ok(ssl);
}
@ -2174,12 +2192,16 @@ do_forward_remove(RES* ssl, struct worker* worker, char* args)
struct iter_forwards* fwd = worker->env.fwds;
int insecure = 0;
uint8_t* nm = NULL;
if(!parse_fs_args(ssl, args, &nm, NULL, &insecure, NULL))
int nolock = 1;
if(!parse_fs_args(ssl, args, &nm, NULL, &insecure, NULL, NULL))
return;
/* prelock forwarders for atomic operation with anchors */
lock_rw_wrlock(&fwd->lock);
if(insecure && worker->env.anchors)
anchors_delete_insecure(worker->env.anchors, LDNS_RR_CLASS_IN,
nm);
forwards_delete_zone(fwd, LDNS_RR_CLASS_IN, nm);
forwards_delete_zone(fwd, LDNS_RR_CLASS_IN, nm, nolock);
lock_rw_unlock(&fwd->lock);
free(nm);
send_ok(ssl);
}
@ -2189,38 +2211,53 @@ static void
do_stub_add(RES* ssl, struct worker* worker, char* args)
{
struct iter_forwards* fwd = worker->env.fwds;
int insecure = 0, prime = 0;
int insecure = 0, prime = 0, tls = 0;
uint8_t* nm = NULL;
struct delegpt* dp = NULL;
if(!parse_fs_args(ssl, args, &nm, &dp, &insecure, &prime))
int nolock = 1;
if(!parse_fs_args(ssl, args, &nm, &dp, &insecure, &prime, &tls))
return;
if(tls)
dp->ssl_upstream = 1;
/* prelock forwarders and hints for atomic operation with anchors */
lock_rw_wrlock(&fwd->lock);
lock_rw_wrlock(&worker->env.hints->lock);
if(insecure && worker->env.anchors) {
if(!anchors_add_insecure(worker->env.anchors, LDNS_RR_CLASS_IN,
nm)) {
lock_rw_unlock(&fwd->lock);
lock_rw_unlock(&worker->env.hints->lock);
(void)ssl_printf(ssl, "error out of memory\n");
delegpt_free_mlc(dp);
free(nm);
return;
}
}
if(!forwards_add_stub_hole(fwd, LDNS_RR_CLASS_IN, nm)) {
if(!forwards_add_stub_hole(fwd, LDNS_RR_CLASS_IN, nm, nolock)) {
if(insecure && worker->env.anchors)
anchors_delete_insecure(worker->env.anchors,
LDNS_RR_CLASS_IN, nm);
lock_rw_unlock(&fwd->lock);
lock_rw_unlock(&worker->env.hints->lock);
(void)ssl_printf(ssl, "error out of memory\n");
delegpt_free_mlc(dp);
free(nm);
return;
}
if(!hints_add_stub(worker->env.hints, LDNS_RR_CLASS_IN, dp, !prime)) {
if(!hints_add_stub(worker->env.hints, LDNS_RR_CLASS_IN, dp, !prime,
nolock)) {
(void)ssl_printf(ssl, "error out of memory\n");
forwards_delete_stub_hole(fwd, LDNS_RR_CLASS_IN, nm);
forwards_delete_stub_hole(fwd, LDNS_RR_CLASS_IN, nm, nolock);
if(insecure && worker->env.anchors)
anchors_delete_insecure(worker->env.anchors,
LDNS_RR_CLASS_IN, nm);
lock_rw_unlock(&fwd->lock);
lock_rw_unlock(&worker->env.hints->lock);
free(nm);
return;
}
lock_rw_unlock(&fwd->lock);
lock_rw_unlock(&worker->env.hints->lock);
free(nm);
send_ok(ssl);
}
@ -2232,13 +2269,19 @@ do_stub_remove(RES* ssl, struct worker* worker, char* args)
struct iter_forwards* fwd = worker->env.fwds;
int insecure = 0;
uint8_t* nm = NULL;
if(!parse_fs_args(ssl, args, &nm, NULL, &insecure, NULL))
int nolock = 1;
if(!parse_fs_args(ssl, args, &nm, NULL, &insecure, NULL, NULL))
return;
/* prelock forwarders and hints for atomic operation with anchors */
lock_rw_wrlock(&fwd->lock);
lock_rw_wrlock(&worker->env.hints->lock);
if(insecure && worker->env.anchors)
anchors_delete_insecure(worker->env.anchors, LDNS_RR_CLASS_IN,
nm);
forwards_delete_stub_hole(fwd, LDNS_RR_CLASS_IN, nm);
hints_delete_stub(worker->env.hints, LDNS_RR_CLASS_IN, nm);
forwards_delete_stub_hole(fwd, LDNS_RR_CLASS_IN, nm, nolock);
hints_delete_stub(worker->env.hints, LDNS_RR_CLASS_IN, nm, nolock);
lock_rw_unlock(&fwd->lock);
lock_rw_unlock(&worker->env.hints->lock);
free(nm);
send_ok(ssl);
}
@ -2667,6 +2710,7 @@ do_list_forwards(RES* ssl, struct worker* worker)
struct iter_forward_zone* z;
struct trust_anchor* a;
int insecure;
lock_rw_rdlock(&fwds->lock);
RBTREE_FOR(z, struct iter_forward_zone*, fwds->tree) {
if(!z->dp) continue; /* skip empty marker for stub */
@ -2681,9 +2725,12 @@ do_list_forwards(RES* ssl, struct worker* worker)
}
if(!ssl_print_name_dp(ssl, (insecure?"forward +i":"forward"),
z->name, z->dclass, z->dp))
z->name, z->dclass, z->dp)) {
lock_rw_unlock(&fwds->lock);
return;
}
}
lock_rw_unlock(&fwds->lock);
}
/** do the list_stubs command */
@ -2694,6 +2741,7 @@ do_list_stubs(RES* ssl, struct worker* worker)
struct trust_anchor* a;
int insecure;
char str[32];
lock_rw_rdlock(&worker->env.hints->lock);
RBTREE_FOR(z, struct iter_hints_stub*, &worker->env.hints->tree) {
/* see if it is insecure */
@ -2709,9 +2757,12 @@ do_list_stubs(RES* ssl, struct worker* worker)
snprintf(str, sizeof(str), "stub %sprime%s",
(z->noprime?"no":""), (insecure?" +i":""));
if(!ssl_print_name_dp(ssl, str, z->node.name,
z->node.dclass, z->dp))
z->node.dclass, z->dp)) {
lock_rw_unlock(&worker->env.hints->lock);
return;
}
}
lock_rw_unlock(&worker->env.hints->lock);
}
/** do the list_auth_zones command */
@ -3071,26 +3122,6 @@ execute_cmd(struct daemon_remote* rc, RES* ssl, char* cmd,
} else if(cmdcmp(p, "auth_zone_transfer", 18)) {
do_auth_zone_transfer(ssl, worker, skipwhite(p+18));
return;
} else if(cmdcmp(p, "stub_add", 8)) {
/* must always distribute this cmd */
if(rc) distribute_cmd(rc, ssl, cmd);
do_stub_add(ssl, worker, skipwhite(p+8));
return;
} else if(cmdcmp(p, "stub_remove", 11)) {
/* must always distribute this cmd */
if(rc) distribute_cmd(rc, ssl, cmd);
do_stub_remove(ssl, worker, skipwhite(p+11));
return;
} else if(cmdcmp(p, "forward_add", 11)) {
/* must always distribute this cmd */
if(rc) distribute_cmd(rc, ssl, cmd);
do_forward_add(ssl, worker, skipwhite(p+11));
return;
} else if(cmdcmp(p, "forward_remove", 14)) {
/* must always distribute this cmd */
if(rc) distribute_cmd(rc, ssl, cmd);
do_forward_remove(ssl, worker, skipwhite(p+14));
return;
} else if(cmdcmp(p, "insecure_add", 12)) {
/* must always distribute this cmd */
if(rc) distribute_cmd(rc, ssl, cmd);
@ -3101,11 +3132,6 @@ execute_cmd(struct daemon_remote* rc, RES* ssl, char* cmd,
if(rc) distribute_cmd(rc, ssl, cmd);
do_insecure_remove(ssl, worker, skipwhite(p+15));
return;
} else if(cmdcmp(p, "forward", 7)) {
/* must always distribute this cmd */
if(rc) distribute_cmd(rc, ssl, cmd);
do_forward(ssl, worker, skipwhite(p+7));
return;
} else if(cmdcmp(p, "flush_stats", 11)) {
/* must always distribute this cmd */
if(rc) distribute_cmd(rc, ssl, cmd);
@ -3147,6 +3173,16 @@ execute_cmd(struct daemon_remote* rc, RES* ssl, char* cmd,
do_data_add(ssl, worker->daemon->local_zones, skipwhite(p+10));
} else if(cmdcmp(p, "local_datas", 11)) {
do_datas_add(ssl, worker->daemon->local_zones);
} else if(cmdcmp(p, "forward_add", 11)) {
do_forward_add(ssl, worker, skipwhite(p+11));
} else if(cmdcmp(p, "forward_remove", 14)) {
do_forward_remove(ssl, worker, skipwhite(p+14));
} else if(cmdcmp(p, "forward", 7)) {
do_forward(ssl, worker, skipwhite(p+7));
} else if(cmdcmp(p, "stub_add", 8)) {
do_stub_add(ssl, worker, skipwhite(p+8));
} else if(cmdcmp(p, "stub_remove", 11)) {
do_stub_remove(ssl, worker, skipwhite(p+11));
} else if(cmdcmp(p, "view_local_zone_remove", 22)) {
do_view_zone_remove(ssl, worker, skipwhite(p+22));
} else if(cmdcmp(p, "view_local_zone", 15)) {

View file

@ -366,9 +366,8 @@ readpid (const char* file)
/** write pid to file.
* @param pidfile: file name of pid file.
* @param pid: pid to write to file.
* @return false on failure
*/
static int
static void
writepid (const char* pidfile, pid_t pid)
{
int fd;
@ -383,7 +382,7 @@ writepid (const char* pidfile, pid_t pid)
, 0644)) == -1) {
log_err("cannot open pidfile %s: %s",
pidfile, strerror(errno));
return 0;
return;
}
while(count < strlen(pidbuf)) {
ssize_t r = write(fd, pidbuf+count, strlen(pidbuf)-count);
@ -393,17 +392,16 @@ writepid (const char* pidfile, pid_t pid)
log_err("cannot write to pidfile %s: %s",
pidfile, strerror(errno));
close(fd);
return 0;
return;
} else if(r == 0) {
log_err("cannot write any bytes to pidfile %s: "
"write returns 0 bytes written", pidfile);
close(fd);
return 0;
return;
}
count += r;
}
close(fd);
return 1;
}
/**
@ -545,7 +543,15 @@ perform_setup(struct daemon* daemon, struct config_file* cfg, int debug_mode,
cfg, 1);
if(!daemon->pidfile)
fatal_exit("pidfile alloc: out of memory");
checkoldpid(daemon->pidfile, pidinchroot);
/* Check old pid if there is no username configured.
* With a username, the assumption is that the privilege
* drop makes a pidfile not removed when the server stopped
* last time. The server does not chown the pidfile for it,
* because that creates privilege escape problems, with the
* pidfile writable by unprivileged users, but used by
* privileged users. */
if(cfg->username && cfg->username[0])
checkoldpid(daemon->pidfile, pidinchroot);
}
#endif
@ -557,18 +563,7 @@ perform_setup(struct daemon* daemon, struct config_file* cfg, int debug_mode,
/* write new pidfile (while still root, so can be outside chroot) */
#ifdef HAVE_KILL
if(cfg->pidfile && cfg->pidfile[0] && need_pidfile) {
if(writepid(daemon->pidfile, getpid())) {
if(cfg->username && cfg->username[0] && cfg_uid != (uid_t)-1 &&
pidinchroot) {
# ifdef HAVE_CHOWN
if(chown(daemon->pidfile, cfg_uid, cfg_gid) == -1) {
verbose(VERB_QUERY, "cannot chown %u.%u %s: %s",
(unsigned)cfg_uid, (unsigned)cfg_gid,
daemon->pidfile, strerror(errno));
}
# endif /* HAVE_CHOWN */
}
}
writepid(daemon->pidfile, getpid());
}
#else
(void)daemon;
@ -746,7 +741,11 @@ run_daemon(const char* cfgfile, int cmdline_verbose, int debug_mode, int need_pi
if(daemon->pidfile) {
int fd;
/* truncate pidfile */
fd = open(daemon->pidfile, O_WRONLY | O_TRUNC, 0644);
fd = open(daemon->pidfile, O_WRONLY | O_TRUNC
#ifdef O_NOFOLLOW
| O_NOFOLLOW
#endif
, 0644);
if(fd != -1)
close(fd);
/* delete pidfile */

View file

@ -659,7 +659,12 @@ answer_from_cache(struct worker* worker, struct query_info* qinfo,
if(rep->ttl < timenow) {
/* Check if we need to serve expired now */
if(worker->env.cfg->serve_expired &&
!worker->env.cfg->serve_expired_client_timeout) {
!worker->env.cfg->serve_expired_client_timeout
#ifdef USE_CACHEDB
&& !(worker->env.cachedb_enabled &&
worker->env.cfg->cachedb_check_when_serve_expired)
#endif
) {
if(worker->env.cfg->serve_expired_ttl &&
rep->serve_expired_ttl < timenow)
return 0;
@ -1454,8 +1459,8 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
*/
if(worker->dtenv.log_client_query_messages) {
log_addr(VERB_ALGO, "request from client", &repinfo->client_addr, repinfo->client_addrlen);
log_addr(VERB_ALGO, "to local addr", (void*)repinfo->c->socket->addr->ai_addr, repinfo->c->socket->addr->ai_addrlen);
dt_msg_send_client_query(&worker->dtenv, &repinfo->client_addr, (void*)repinfo->c->socket->addr->ai_addr, c->type, c->ssl, c->buffer,
log_addr(VERB_ALGO, "to local addr", (void*)repinfo->c->socket->addr, repinfo->c->socket->addrlen);
dt_msg_send_client_query(&worker->dtenv, &repinfo->client_addr, (void*)repinfo->c->socket->addr, c->type, c->ssl, c->buffer,
((worker->env.cfg->sock_queue_timeout && timeval_isset(&c->recv_tv))?&c->recv_tv:NULL));
}
#endif
@ -1943,10 +1948,10 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
/*
* sending src (client)/dst (local service) addresses over DNSTAP from send_reply code label (when we serviced local zone for ex.)
*/
if(worker->dtenv.log_client_response_messages) {
log_addr(VERB_ALGO, "from local addr", (void*)repinfo->c->socket->addr->ai_addr, repinfo->c->socket->addr->ai_addrlen);
if(worker->dtenv.log_client_response_messages && rc !=0) {
log_addr(VERB_ALGO, "from local addr", (void*)repinfo->c->socket->addr, repinfo->c->socket->addrlen);
log_addr(VERB_ALGO, "response to client", &repinfo->client_addr, repinfo->client_addrlen);
dt_msg_send_client_response(&worker->dtenv, &repinfo->client_addr, (void*)repinfo->c->socket->addr->ai_addr, c->type, c->ssl, c->buffer);
dt_msg_send_client_response(&worker->dtenv, &repinfo->client_addr, (void*)repinfo->c->socket->addr, c->type, c->ssl, c->buffer);
}
#endif
if(worker->env.cfg->log_replies)
@ -1961,13 +1966,13 @@ worker_handle_request(struct comm_point* c, void* arg, int error,
log_reply_info(NO_VERBOSE, &qinfo,
&repinfo->client_addr, repinfo->client_addrlen,
tv, 1, c->buffer,
(worker->env.cfg->log_destaddr?(void*)repinfo->c->socket->addr->ai_addr:NULL),
(worker->env.cfg->log_destaddr?(void*)repinfo->c->socket->addr:NULL),
c->type);
} else {
log_reply_info(NO_VERBOSE, &qinfo,
&repinfo->client_addr, repinfo->client_addrlen,
tv, 1, c->buffer,
(worker->env.cfg->log_destaddr?(void*)repinfo->c->socket->addr->ai_addr:NULL),
(worker->env.cfg->log_destaddr?(void*)repinfo->c->socket->addr:NULL),
c->type);
}
}
@ -2261,18 +2266,6 @@ worker_init(struct worker* worker, struct config_file *cfg,
worker_delete(worker);
return 0;
}
if(!(worker->env.fwds = forwards_create()) ||
!forwards_apply_cfg(worker->env.fwds, cfg)) {
log_err("Could not set forward zones");
worker_delete(worker);
return 0;
}
if(!(worker->env.hints = hints_create()) ||
!hints_apply_cfg(worker->env.hints, cfg)) {
log_err("Could not set root or stub hints");
worker_delete(worker);
return 0;
}
/* one probe timer per process -- if we have 5011 anchors */
if(autr_get_num_anchors(worker->env.anchors) > 0
#ifndef THREADS_DISABLED
@ -2345,8 +2338,6 @@ worker_delete(struct worker* worker)
outside_network_quit_prepare(worker->back);
mesh_delete(worker->env.mesh);
sldns_buffer_free(worker->env.scratch_buffer);
forwards_delete(worker->env.fwds);
hints_delete(worker->env.hints);
listen_delete(worker->front);
outside_network_delete(worker->back);
comm_signal_delete(worker->comsig);

View file

@ -1,15 +1,194 @@
1 May 2024: Wouter
- Fix for the DNSBomb vulnerability CVE-2024-33655. Thanks to Xiang Li
from the Network and Information Security Lab of Tsinghua University
for reporting it.
- Set version number to 1.20.0 for release.
29 April 2024: Yorgos
- Cleanup unnecessary strdup calls for EDE strings.
29 April 2024: Wouter
- Fix doxygen comment for errinf_to_str_bogus.
26 April 2024: Wouter
- Fix cachedb with serve-expired-client-timeout disabled. The edns
subnet module deletes global cache and cachedb cache when it
stores a result, and serve-expired is enabled, so that the global
reply, that is older than the ecs reply, does not return after
the ecs reply expires.
- Add unit tests for cachedb and subnet cache expired data.
- Man page entry for unbound-checkconf -q.
26 April 2024: Yorgos
- Fix #876: [FR] can unbound-checkconf be silenced when configuration
is valid?
25 April 2024: Wouter
- Fix configure flto check error, by finding grep for it.
- Merge #1041: Stub and Forward unshare. This has one structure
for them and fixes #1038: fatal error: Could not initialize
thread / error: reading root hints.
- Fix to disable fragmentation on systems with IP_DONTFRAG,
with a nonzero value for the socket option argument.
- Fix doc unit test for out of directory build.
24 April 2024: Wouter
- Fix ci workflow for macos for moved install locations.
23 April 2024: Yorgos
- Merge #1053: Remove child delegations from cache when grandchild
delegations are returned from parent.
22 April 2024: Wouter
- Add checklock feature verbose_locking to trace locks and unlocks.
- Fix edns subnet to sort rrset references when storing messages
in the cache. This fixes a race condition in the rrset locks.
15 April 2024: Wouter
- Fix #1048: Update ax_pkg_swig.m4 and ax_pthread.m4.
- Fix configure, autoconf for #1048.
15 April 2024: Yorgos
- Merge #1049 from Petr Menšík: Py_NoSiteFlag is not needed since
Python 3.8
12 April 2024: Wouter
- Fix cachedb for serve-expired with serve-expired-client-timeout.
- Fixup unit test for cachedb server expired client timeout with
a check if response if from upstream or from cachedb.
- Fixup cachedb to not refetch when serve-expired-client-timeout is
used.
10 April 2024: Wouter
- Implement cachedb-check-when-serve-expired: yes option, default
is enabled. When serve expired is enabled with cachedb, it first
checks cachedb before serving the expired response.
- Fixup compile without cachedb.
- Add test for cachedb serve expired.
- Extended test for cachedb serve expired.
- Fix makefile dependencies for fake_event.c.
- Fix cachedb for serve-expired with serve-expired-reply-ttl.
- Fix to not reply serve expired unless enabled for cachedb.
9 April 2024: Yorgos
- Merge #1043 from xiaoxiaoafeifei: Add loongarch support; updates
config.guess(2024-01-01) and config.sub(2024-01-01), verified
with upstream.
8 April 2024: Yorgos
- Fix #595: unbound-anchor cannot deal with full disk; it will now
first write out to a temp file before replacing the original one,
like Unbound already does for auto-trust-anchor-file.
5 April 2024: Wouter
- Fix comment syntax for view function views_find_view.
5 April 2024: Yorgos
- Merge #1027: Introduce 'cache-min-negative-ttl' option.
3 April 2024: Wouter
- Fix #1040: fix heap-buffer-overflow issue in function cfg_mark_ports
of file util/config_file.c.
- For #1040: adjust error text and disallow negative ports in other
parts of cfg_mark_ports.
3 April 2024: Yorgos
- Fix #1035: Potential Bug while parsing port from the "stub-host"
string; also affected forward-zones and remote-control host
directives.
- Fix #369: dnstap showing extra responses; for client responses
right from the cache when replying with expired data or
prefetching.
28 March 2024: Wouter
- Fix #1034: DoT forward-zone via unbound-control.
- Fix for crypto related failures to have a better error string.
27 March 2024: Wouter
- Fix name of unit test for subnet cache response.
- Fix #1032: The size of subnet_msg_cache calculation mistake cause
memory usage increased beyond expectations.
- Fix for #1032, add safeguard to make table space positive.
- Fix comment in lruhash space function.
- Fix to add unit test for lruhash space that exercises the routines.
- Fix that when the server truncates the pidfile, it does not follow
symbolic links.
- Fix that the server does not chown the pidfile.
25 March 2024: Yorgos
- Merge #831 from Pierre4012: Improve Windows NSIS installer
script (setup.nsi).
- For #831: Format text, use exclamation icon and explicit label
names.
19 March 2024: Wouter
- Fix rpz so that rpz CNAME can apply after rpz CNAME. And fix that
clientip and nsip can give a CNAME.
- Fix localdata and rpz localdata to match CNAME only if no direct
type match is available.
18 March 2024: Wouter
- Fix that rpz CNAME content is limited to the max number of cnames.
- Fix rpz, it follows iterator CNAMEs for nsip and nsdname and sets
the reply query_info values, that is better for debug logging.
- Fix rpz that copies the cname override completely to the temp
region, so there are no references to the rpz region.
- Add rpz unit test for nsip action override.
- Fix rpz for qtype CNAME after nameserver trigger.
15 March 2024: Yorgos
- Merge #1030: Persist the openssl and expat directories for repeated
Windows builds.
15 March 2024: Wouter
- Fix that addrinfo is not kept around but copied and freed, so that
log-destaddr uses a copy of the information, much like NSD does.
13 March 2024: Wouter
- Fix #1029: rpz trigger clientip and action rpz-passthru not working
as expected.
- Fix rpz that the rpz override is taken in case of clientip triggers.
Fix that the clientip passthru action is logged. Fix that the
clientip localdata action is logged. Fix rpz override action cname
for the clientip trigger.
- Fix to unify codepath for local alias for rpz cname action override.
- Fix rpz for cname override action after nsdname and nsip triggers.
12 March 2024: Yorgos
- Merge #1028: Clearer documentation for tcp-idle-timeout and
edns-tcp-keepalive-timeout.
11 March 2024: Wouter
- Fix #1021 Inconsistent Behavior with Changing rpz-cname-override
and doing a unbound-control reload.
8 March 2024: Wouter
- Fix unbound-control-setup.cmd to use 3072 bits so that certificates
are long enough for newer OpenSSL versions.
- Fix TTL of synthesized CNAME when a DNAME is used from cache.
are long enough for newer OpenSSL versions. This fix is included
in 1.19.3rc2.
- Fix TTL of synthesized CNAME when a DNAME is used from cache. This
fix is included in 1.19.3rc2.
- Remove unused portion from iter_dname_ttl unit test.
- Fix validator classification of qtype DNAME for positive and
redirection answers, and fix validator signature routine for dealing
with the synthesized CNAME for a DNAME without previously
encountering it and also for when the qtype is DNAME.
- Fix qname minimisation for reply with a DNAME for qtype CNAME that
answers it.
- Fix doc test so it ignores but outputs unsupported doxygen options.
- Fix unbound-control-setup.cmd to have CA v3 basicConstraints,
like unbound-control-setup.sh has.
like unbound-control-setup.sh has. This fix is included in 1.19.3rc2.
8 March 2024: Yorgos
- Update doc/unbound.doxygen with 'doxygen -u'. Fixes option
deprecation warnings and updates with newer defaults.
7 March 2024: Wouter
- Version set to 1.19.3 for release. After 1.19.2 point release with
security fix for CVE-2024-1931, Denial of service when trimming
EDE text on positive replies. The code repo includes the fix and
is for version 1.19.3.
is for version 1.19.3. The code repo continues for version 1.19.4,
but 1.19.3 includes the fixes in 1.19.3rc2 as well.
5 March 2024: Wouter
- Fix for #1022: Fix ede prohibited in access control refused answers.

View file

@ -1,4 +1,4 @@
README for Unbound 1.19.3
README for Unbound 1.20.0
Copyright 2007 NLnet Labs
http://unbound.net

View file

@ -1,7 +1,7 @@
#
# Example configuration file.
#
# See unbound.conf(5) man page, version 1.19.3.
# See unbound.conf(5) man page, version 1.20.0.
#
# this is a comment.
@ -191,6 +191,21 @@ server:
# are behind a slow satellite link, to eg. 1128.
# unknown-server-time-limit: 376
# msec before recursion replies are dropped. The work item continues.
# discard-timeout: 1900
# Max number of replies waiting for recursion per IP address.
# wait-limit: 1000
# Max replies waiting for recursion for IP address with cookie.
# wait-limit-cookie: 10000
# Apart from the default, the wait limit can be set for a netblock.
# wait-limit-netblock: 192.0.2.0/24 50000
# Apart from the default, the wait limit with cookie can be adjusted.
# wait-limit-cookie-netblock: 192.0.2.0/24 50000
# the amount of memory to use for the RRset cache.
# plain value in bytes or you can append k, m or G. default is "4Mb".
# rrset-cache-size: 4m
@ -211,6 +226,11 @@ server:
# the time to live (TTL) value cap for negative responses in the cache
# cache-max-negative-ttl: 3600
# the time to live (TTL) value lower bound, in seconds. Default 0.
# For negative responses in the cache. If disabled, default,
# cache-min-tll applies if configured.
# cache-min-negative-ttl: 0
# the time to live (TTL) value for cached roundtrip times, lameness and
# EDNS version information for hosts. In seconds.
# infra-host-ttl: 900
@ -283,7 +303,8 @@ server:
# Enable EDNS TCP keepalive option.
# edns-tcp-keepalive: no
# Timeout for EDNS TCP keepalive, in msec.
# Timeout for EDNS TCP keepalive, in msec. Overrides tcp-idle-timeout
# if edns-tcp-keepalive is set.
# edns-tcp-keepalive-timeout: 120000
# UDP queries that have waited in the socket buffer for a long time
@ -1247,6 +1268,9 @@ remote-control:
# secret-seed: "default"
# # if the backend should be read from, but not written to.
# cachedb-no-store: no
# # if the cachedb should be checked before a serve-expired response is
# # given, when serve-expired is enabled.
# cachedb-check-when-serve-expired: yes
#
# # For "redis" backend:
# # (to enable, use --with-libhiredis to configure before compiling)

View file

@ -1,4 +1,4 @@
.TH "libunbound" "3" "Mar 14, 2024" "NLnet Labs" "unbound 1.19.3"
.TH "libunbound" "3" "May 8, 2024" "NLnet Labs" "unbound 1.20.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.19.3 functions.
\- Unbound DNS validating resolver 1.20.0 functions.
.SH "SYNOPSIS"
.B #include <unbound.h>
.LP

View file

@ -1,4 +1,4 @@
.TH "unbound-anchor" "8" "Mar 14, 2024" "NLnet Labs" "unbound 1.19.3"
.TH "unbound-anchor" "8" "May 8, 2024" "NLnet Labs" "unbound 1.20.0"
.\"
.\" unbound-anchor.8 -- unbound anchor maintenance utility manual
.\"

View file

@ -1,4 +1,4 @@
.TH "unbound-checkconf" "8" "Mar 14, 2024" "NLnet Labs" "unbound 1.19.3"
.TH "unbound-checkconf" "8" "May 8, 2024" "NLnet Labs" "unbound 1.20.0"
.\"
.\" unbound-checkconf.8 -- unbound configuration checker manual
.\"
@ -14,6 +14,7 @@ unbound\-checkconf
.B unbound\-checkconf
.RB [ \-h ]
.RB [ \-f ]
.RB [ \-q ]
.RB [ \-o
.IR option ]
.RI [ cfgfile ]
@ -37,6 +38,9 @@ Print full pathname, with chroot applied to it. Use with the \-o option.
If given, after checking the config file the value of this option is
printed to stdout. For "" (disabled) options an empty line is printed.
.TP
.B \-q
Make the operation quiet, suppress output on success.
.TP
.I cfgfile
The config file to read with settings for Unbound. It is checked.
If omitted, the config file at the default location is checked.

View file

@ -1,4 +1,4 @@
.TH "unbound-control" "8" "Mar 14, 2024" "NLnet Labs" "unbound 1.19.3"
.TH "unbound-control" "8" "May 8, 2024" "NLnet Labs" "unbound 1.20.0"
.\"
.\" unbound-control.8 -- unbound remote control manual
.\"
@ -239,22 +239,24 @@ still be bogus, use \fBflush_zone\fR to remove it), does not affect the config f
.B insecure_remove \fIzone
Removes domain\-insecure for the given zone.
.TP
.B forward_add \fR[\fI+i\fR] \fIzone addr ...
.B forward_add \fR[\fI+it\fR] \fIzone addr ...
Add a new forward zone to running Unbound. With +i option also adds a
\fIdomain\-insecure\fR for the zone (so it can resolve insecurely if you have
a DNSSEC root trust anchor configured for other names).
The addr can be IP4, IP6 or nameserver names, like \fIforward-zone\fR config
in unbound.conf.
The +t option sets it to use tls upstream, like \fIforward\-tls\-upstream\fR: yes.
.TP
.B forward_remove \fR[\fI+i\fR] \fIzone
Remove a forward zone from running Unbound. The +i also removes a
\fIdomain\-insecure\fR for the zone.
.TP
.B stub_add \fR[\fI+ip\fR] \fIzone addr ...
.B stub_add \fR[\fI+ipt\fR] \fIzone addr ...
Add a new stub zone to running Unbound. With +i option also adds a
\fIdomain\-insecure\fR for the zone. With +p the stub zone is set to prime,
without it it is set to notprime. The addr can be IP4, IP6 or nameserver
names, like the \fIstub-zone\fR config in unbound.conf.
The +t option sets it to use tls upstream, like \fIstub\-tls\-upstream\fR: yes.
.TP
.B stub_remove \fR[\fI+i\fR] \fIzone
Remove a stub zone from running Unbound. The +i also removes a

View file

@ -1,4 +1,4 @@
.TH "unbound\-host" "1" "Mar 14, 2024" "NLnet Labs" "unbound 1.19.3"
.TH "unbound\-host" "1" "May 8, 2024" "NLnet Labs" "unbound 1.20.0"
.\"
.\" unbound-host.1 -- unbound DNS lookup utility
.\"

View file

@ -1,4 +1,4 @@
.TH "unbound" "8" "Mar 14, 2024" "NLnet Labs" "unbound 1.19.3"
.TH "unbound" "8" "May 8, 2024" "NLnet Labs" "unbound 1.20.0"
.\"
.\" unbound.8 -- unbound manual
.\"
@ -9,7 +9,7 @@
.\"
.SH "NAME"
.B unbound
\- Unbound DNS validating resolver 1.19.3.
\- Unbound DNS validating resolver 1.20.0.
.SH "SYNOPSIS"
.B unbound
.RB [ \-h ]

View file

@ -1,4 +1,4 @@
.TH "unbound.conf" "5" "Mar 14, 2024" "NLnet Labs" "unbound 1.19.3"
.TH "unbound.conf" "5" "May 8, 2024" "NLnet Labs" "unbound 1.20.0"
.\"
.\" unbound.conf.5 -- unbound.conf manual
.\"
@ -302,6 +302,36 @@ Increase this if you are behind a slow satellite link, to eg. 1128.
That would then avoid re\-querying every initial query because it times out.
Default is 376 msec.
.TP
.B discard\-timeout: \fI<msec>
The wait time in msec where recursion requests are dropped. This is
to stop a large number of replies from accumulating. They receive
no reply, the work item continues to recurse. It is nice to be a bit
larger than serve\-expired\-client\-timeout if that is enabled.
A value of 1900 msec is suggested. The value 0 disables it.
Default 1900 msec.
.TP
.B wait\-limit: \fI<number>
The number of replies that can wait for recursion, for an IP address.
This makes a ratelimit per IP address of waiting replies for recursion.
It stops very large amounts of queries waiting to be returned to one
destination. The value 0 disables wait limits. Default is 1000.
.TP
.B wait\-limit\-cookie: \fI<number>
The number of replies that can wait for recursion, for an IP address
that sent the query with a valid DNS cookie. Since the cookie validates
the client address, the limit can be higher. Default is 10000.
.TP
.B wait\-limit\-netblock: \fI<netblock> <number>
The wait limit for the netblock. If not given the wait\-limit value is
used. The most specific netblock is used to determine the limit. Useful for
overriding the default for a specific, group or individual, server.
The value -1 disables wait limits for the netblock.
.TP
.B wait\-limit\-cookie\-netblock: \fI<netblock> <number>
The wait limit for the netblock, when the query has a DNS cookie.
If not given, the wait\-limit\-cookie value is used.
The value -1 disables wait limits for the netblock.
.TP
.B so\-rcvbuf: \fI<number>
If not 0, then set the SO_RCVBUF socket option to get more buffer
space on UDP port 53 incoming queries. So that short spikes on busy
@ -388,6 +418,15 @@ Time to live maximum for negative responses, these have a SOA in the
authority section that is limited in time. Default is 3600.
This applies to nxdomain and nodata answers.
.TP
.B cache\-min\-negative\-ttl: \fI<seconds>
Time to live minimum for negative responses, these have a SOA in the
authority section that is limited in time.
Default is 0 (disabled).
If this is disabled and \fBcache-min-ttl\fR is configured, it will take effect
instead.
In that case you can set this to 1 to honor the upstream TTL.
This applies to nxdomain and nodata answers.
.TP
.B infra\-host\-ttl: \fI<seconds>
Time to live for entries in the host cache. The host cache contains
roundtrip timing, lameness and EDNS support information. Default is 900.
@ -472,6 +511,8 @@ configured value if the number of free buffers falls below 35% of the
total number configured, and finally to 0 if the number of free buffers
falls below 20% of the total number configured. A minimum timeout of
200 milliseconds is observed regardless of the option value used.
It will be overriden by \fBedns\-tcp\-keepalive\-timeout\fR if
\fBedns\-tcp\-keepalive\fR is enabled.
.TP
.B tcp-reuse-timeout: \fI<msec>\fR
The period Unbound will keep TCP persistent connections open to
@ -490,20 +531,11 @@ This option defaults to 3000 milliseconds.
Enable or disable EDNS TCP Keepalive. Default is no.
.TP
.B edns-tcp-keepalive-timeout: \fI<msec>\fR
The period Unbound will wait for a query on a TCP connection when
EDNS TCP Keepalive is active. If this timeout expires Unbound closes
the connection. If the client supports the EDNS TCP Keepalive option,
Overrides \fBtcp\-idle\-timeout\fR when \fBedns\-tcp\-keepalive\fR is enabled.
If the client supports the EDNS TCP Keepalive option,
Unbound sends the timeout value to the client to encourage it to
close the connection before the server times out.
This option defaults to 120000 milliseconds.
When the number of free incoming TCP buffers falls below 50% of
the total number configured, the advertised timeout is progressively
reduced to 1% of the configured value, then to 0.2% of the configured
value if the number of free buffers falls below 35% of the total number
configured, and finally to 0 if the number of free buffers falls below
20% of the total number configured.
A minimum actual timeout of 200 milliseconds is observed regardless of the
advertised timeout.
.TP
.B sock\-queue\-timeout: \fI<sec>\fR
UDP queries that have waited in the socket buffer for a long time can be
@ -2638,11 +2670,7 @@ If Unbound cannot even find an answer in the backend, it resolves the
query as usual, and stores the answer in the backend.
.P
This module interacts with the \fBserve\-expired\-*\fR options and will reply
with expired data if Unbound is configured for that. Currently the use
of \fBserve\-expired\-client\-timeout:\fR and
\fBserve\-expired\-reply\-ttl:\fR is not consistent for data originating from
the external cache as these will result in a reply with 0 TTL without trying to
update the data first, ignoring the configured values.
with expired data if Unbound is configured for that.
.P
If Unbound was built with
\fB\-\-with\-libhiredis\fR
@ -2698,6 +2726,16 @@ This option defaults to "default".
If the backend should be read from, but not written to. This makes this
instance not store dns messages in the backend. But if data is available it
is retrieved. The default is no.
.TP
.B cachedb-check-when-serve-expired: \fI<yes or no>\fR
If enabled, the cachedb is checked before an expired response is returned.
When \fBserve\-expired\fR is enabled, without \fBserve\-expired\-client\-timeout\fR, it then
does not immediately respond with an expired response from cache, but instead
first checks the cachedb for valid contents, and if so returns it. If the
cachedb also has no valid contents, the serve expired response is sent.
If also \fBserve\-expired\-client\-timeout\fR is enabled, the expired response
is delayed until the timeout expires. Unless the lookup succeeds within the
timeout. The default is yes.
.P
The following
.B cachedb

File diff suppressed because it is too large Load diff

View file

@ -57,6 +57,9 @@
#include "sldns/sbuffer.h"
#include "sldns/wire2str.h"
#include "iterator/iter_utils.h"
#ifdef USE_CACHEDB
#include "cachedb/cachedb.h"
#endif
/** externally called */
void
@ -152,7 +155,7 @@ int ecs_whitelist_check(struct query_info* qinfo,
/* Cache by default, might be disabled after parsing EDNS option
* received from nameserver. */
if(!iter_stub_fwd_no_cache(qstate, &qstate->qinfo, NULL, NULL)) {
if(!iter_stub_fwd_no_cache(qstate, &qstate->qinfo, NULL, NULL, NULL, 0)) {
qstate->no_cache_store = 0;
}
@ -310,9 +313,18 @@ delfunc(void *envptr, void *elemptr) {
static size_t
sizefunc(void *elemptr) {
struct reply_info *elem = (struct reply_info *)elemptr;
return sizeof (struct reply_info) - sizeof (struct rrset_ref)
size_t s = sizeof (struct reply_info) - sizeof (struct rrset_ref)
+ elem->rrset_count * sizeof (struct rrset_ref)
+ elem->rrset_count * sizeof (struct ub_packed_rrset_key *);
size_t i;
for (i = 0; i < elem->rrset_count; i++) {
struct ub_packed_rrset_key *key = elem->rrsets[i];
struct packed_rrset_data *data = key->entry.data;
s += ub_rrset_sizefunc(key, data);
}
if(elem->reason_bogus_str)
s += strlen(elem->reason_bogus_str)+1;
return s;
}
/**
@ -352,7 +364,7 @@ update_cache(struct module_qstate *qstate, int id)
struct slabhash *subnet_msg_cache = sne->subnet_msg_cache;
struct ecs_data *edns = &sq->ecs_client_in;
size_t i;
int only_match_scope_zero;
int only_match_scope_zero, diff_size;
/* We already calculated hash upon lookup (lookup_and_reply) if we were
* allowed to look in the ECS cache */
@ -412,19 +424,25 @@ update_cache(struct module_qstate *qstate, int id)
rep->ref[i].id = rep->rrsets[i]->id;
}
reply_info_set_ttls(rep, *qstate->env->now);
reply_info_sortref(rep);
rep->flags |= (BIT_RA | BIT_QR); /* fix flags to be sensible for */
rep->flags &= ~(BIT_AA | BIT_CD);/* a reply based on the cache */
if(edns->subnet_source_mask == 0 && edns->subnet_scope_mask == 0)
only_match_scope_zero = 1;
else only_match_scope_zero = 0;
diff_size = (int)tree->size_bytes;
addrtree_insert(tree, (addrkey_t*)edns->subnet_addr,
edns->subnet_source_mask, sq->max_scope, rep,
rep->ttl, *qstate->env->now, only_match_scope_zero);
diff_size = (int)tree->size_bytes - diff_size;
lock_rw_unlock(&lru_entry->lock);
if (need_to_insert) {
slabhash_insert(subnet_msg_cache, h, lru_entry, lru_entry->data,
NULL);
} else {
slabhash_update_space_used(subnet_msg_cache, h, NULL,
diff_size);
}
}
@ -587,7 +605,21 @@ eval_response(struct module_qstate *qstate, int id, struct subnet_qstate *sq)
}
sne->num_msg_nocache++;
lock_rw_unlock(&sne->biglock);
/* If there is an expired answer in the global cache, remove that,
* because expired answers would otherwise resurface once the ecs data
* expires, giving once in a while global data responses for ecs
* domains, with serve expired enabled. */
if(qstate->env->cfg->serve_expired) {
msg_cache_remove(qstate->env, qstate->qinfo.qname,
qstate->qinfo.qname_len, qstate->qinfo.qtype,
qstate->qinfo.qclass, 0);
#ifdef USE_CACHEDB
if(qstate->env->cachedb_enabled)
cachedb_msg_remove(qstate);
#endif
}
if (sq->subnet_downstream) {
/* Client wants to see the answer, echo option back
* and adjust the scope. */

View file

@ -71,6 +71,7 @@ forwards_create(void)
sizeof(struct iter_forwards));
if(!fwd)
return NULL;
lock_rw_init(&fwd->lock);
return fwd;
}
@ -100,6 +101,7 @@ forwards_delete(struct iter_forwards* fwd)
{
if(!fwd)
return;
lock_rw_destroy(&fwd->lock);
fwd_del_tree(fwd);
free(fwd);
}
@ -332,45 +334,64 @@ make_stub_holes(struct iter_forwards* fwd, struct config_file* cfg)
int
forwards_apply_cfg(struct iter_forwards* fwd, struct config_file* cfg)
{
if(fwd->tree) {
lock_unprotect(&fwd->lock, fwd->tree);
}
fwd_del_tree(fwd);
fwd->tree = rbtree_create(fwd_cmp);
if(!fwd->tree)
return 0;
lock_protect(&fwd->lock, fwd->tree, sizeof(*fwd->tree));
lock_rw_wrlock(&fwd->lock);
/* read forward zones */
if(!read_forwards(fwd, cfg))
if(!read_forwards(fwd, cfg)) {
lock_rw_unlock(&fwd->lock);
return 0;
if(!make_stub_holes(fwd, cfg))
}
if(!make_stub_holes(fwd, cfg)) {
lock_rw_unlock(&fwd->lock);
return 0;
}
fwd_init_parents(fwd);
lock_rw_unlock(&fwd->lock);
return 1;
}
struct delegpt*
forwards_find(struct iter_forwards* fwd, uint8_t* qname, uint16_t qclass)
forwards_find(struct iter_forwards* fwd, uint8_t* qname, uint16_t qclass,
int nolock)
{
rbnode_type* res = NULL;
struct iter_forward_zone* res;
struct iter_forward_zone key;
int has_dp;
key.node.key = &key;
key.dclass = qclass;
key.name = qname;
key.namelabs = dname_count_size_labels(qname, &key.namelen);
res = rbtree_search(fwd->tree, &key);
if(res) return ((struct iter_forward_zone*)res)->dp;
return NULL;
/* lock_() calls are macros that could be nothing, surround in {} */
if(!nolock) { lock_rw_rdlock(&fwd->lock); }
res = (struct iter_forward_zone*)rbtree_search(fwd->tree, &key);
has_dp = res && res->dp;
if(!has_dp && !nolock) { lock_rw_unlock(&fwd->lock); }
return has_dp?res->dp:NULL;
}
struct delegpt*
forwards_lookup(struct iter_forwards* fwd, uint8_t* qname, uint16_t qclass)
forwards_lookup(struct iter_forwards* fwd, uint8_t* qname, uint16_t qclass,
int nolock)
{
/* lookup the forward zone in the tree */
rbnode_type* res = NULL;
struct iter_forward_zone *result;
struct iter_forward_zone key;
int has_dp;
key.node.key = &key;
key.dclass = qclass;
key.name = qname;
key.namelabs = dname_count_size_labels(qname, &key.namelen);
/* lock_() calls are macros that could be nothing, surround in {} */
if(!nolock) { lock_rw_rdlock(&fwd->lock); }
if(rbtree_find_less_equal(fwd->tree, &key, &res)) {
/* exact */
result = (struct iter_forward_zone*)res;
@ -378,8 +399,10 @@ forwards_lookup(struct iter_forwards* fwd, uint8_t* qname, uint16_t qclass)
/* smaller element (or no element) */
int m;
result = (struct iter_forward_zone*)res;
if(!result || result->dclass != qclass)
if(!result || result->dclass != qclass) {
if(!nolock) { lock_rw_unlock(&fwd->lock); }
return NULL;
}
/* count number of labels matched */
(void)dname_lab_cmp(result->name, result->namelabs, key.name,
key.namelabs, &m);
@ -389,20 +412,22 @@ forwards_lookup(struct iter_forwards* fwd, uint8_t* qname, uint16_t qclass)
result = result->parent;
}
}
if(result)
return result->dp;
return NULL;
has_dp = result && result->dp;
if(!has_dp && !nolock) { lock_rw_unlock(&fwd->lock); }
return has_dp?result->dp:NULL;
}
struct delegpt*
forwards_lookup_root(struct iter_forwards* fwd, uint16_t qclass)
forwards_lookup_root(struct iter_forwards* fwd, uint16_t qclass, int nolock)
{
uint8_t root = 0;
return forwards_lookup(fwd, &root, qclass);
return forwards_lookup(fwd, &root, qclass, nolock);
}
int
forwards_next_root(struct iter_forwards* fwd, uint16_t* dclass)
/* Finds next root item in forwards lookup tree.
* Caller needs to handle locking of the forwards structure. */
static int
next_root_locked(struct iter_forwards* fwd, uint16_t* dclass)
{
struct iter_forward_zone key;
rbnode_type* n;
@ -419,7 +444,7 @@ forwards_next_root(struct iter_forwards* fwd, uint16_t* dclass)
}
/* root not first item? search for higher items */
*dclass = p->dclass + 1;
return forwards_next_root(fwd, dclass);
return next_root_locked(fwd, dclass);
}
/* find class n in tree, we may get a direct hit, or if we don't
* this is the last item of the previous class so rbtree_next() takes
@ -447,10 +472,21 @@ forwards_next_root(struct iter_forwards* fwd, uint16_t* dclass)
}
/* not a root node, return next higher item */
*dclass = p->dclass+1;
return forwards_next_root(fwd, dclass);
return next_root_locked(fwd, dclass);
}
}
int
forwards_next_root(struct iter_forwards* fwd, uint16_t* dclass, int nolock)
{
int ret;
/* lock_() calls are macros that could be nothing, surround in {} */
if(!nolock) { lock_rw_rdlock(&fwd->lock); }
ret = next_root_locked(fwd, dclass);
if(!nolock) { lock_rw_unlock(&fwd->lock); }
return ret;
}
size_t
forwards_get_mem(struct iter_forwards* fwd)
{
@ -458,10 +494,12 @@ forwards_get_mem(struct iter_forwards* fwd)
size_t s;
if(!fwd)
return 0;
lock_rw_rdlock(&fwd->lock);
s = sizeof(*fwd) + sizeof(*fwd->tree);
RBTREE_FOR(p, struct iter_forward_zone*, fwd->tree) {
s += sizeof(*p) + p->namelen + delegpt_get_mem(p->dp);
}
lock_rw_unlock(&fwd->lock);
return s;
}
@ -477,49 +515,78 @@ fwd_zone_find(struct iter_forwards* fwd, uint16_t c, uint8_t* nm)
}
int
forwards_add_zone(struct iter_forwards* fwd, uint16_t c, struct delegpt* dp)
forwards_add_zone(struct iter_forwards* fwd, uint16_t c, struct delegpt* dp,
int nolock)
{
struct iter_forward_zone *z;
/* lock_() calls are macros that could be nothing, surround in {} */
if(!nolock) { lock_rw_wrlock(&fwd->lock); }
if((z=fwd_zone_find(fwd, c, dp->name)) != NULL) {
(void)rbtree_delete(fwd->tree, &z->node);
fwd_zone_free(z);
}
if(!forwards_insert(fwd, c, dp))
if(!forwards_insert(fwd, c, dp)) {
if(!nolock) { lock_rw_unlock(&fwd->lock); }
return 0;
}
fwd_init_parents(fwd);
if(!nolock) { lock_rw_unlock(&fwd->lock); }
return 1;
}
void
forwards_delete_zone(struct iter_forwards* fwd, uint16_t c, uint8_t* nm)
forwards_delete_zone(struct iter_forwards* fwd, uint16_t c, uint8_t* nm,
int nolock)
{
struct iter_forward_zone *z;
if(!(z=fwd_zone_find(fwd, c, nm)))
/* lock_() calls are macros that could be nothing, surround in {} */
if(!nolock) { lock_rw_wrlock(&fwd->lock); }
if(!(z=fwd_zone_find(fwd, c, nm))) {
if(!nolock) { lock_rw_unlock(&fwd->lock); }
return; /* nothing to do */
}
(void)rbtree_delete(fwd->tree, &z->node);
fwd_zone_free(z);
fwd_init_parents(fwd);
if(!nolock) { lock_rw_unlock(&fwd->lock); }
}
int
forwards_add_stub_hole(struct iter_forwards* fwd, uint16_t c, uint8_t* nm)
forwards_add_stub_hole(struct iter_forwards* fwd, uint16_t c, uint8_t* nm,
int nolock)
{
/* lock_() calls are macros that could be nothing, surround in {} */
if(!nolock) { lock_rw_wrlock(&fwd->lock); }
if(fwd_zone_find(fwd, c, nm) != NULL) {
if(!nolock) { lock_rw_unlock(&fwd->lock); }
return 1; /* already a stub zone there */
}
if(!fwd_add_stub_hole(fwd, c, nm)) {
if(!nolock) { lock_rw_unlock(&fwd->lock); }
return 0;
}
fwd_init_parents(fwd);
if(!nolock) { lock_rw_unlock(&fwd->lock); }
return 1;
}
void
forwards_delete_stub_hole(struct iter_forwards* fwd, uint16_t c, uint8_t* nm)
forwards_delete_stub_hole(struct iter_forwards* fwd, uint16_t c,
uint8_t* nm, int nolock)
{
struct iter_forward_zone *z;
if(!(z=fwd_zone_find(fwd, c, nm)))
/* lock_() calls are macros that could be nothing, surround in {} */
if(!nolock) { lock_rw_wrlock(&fwd->lock); }
if(!(z=fwd_zone_find(fwd, c, nm))) {
if(!nolock) { lock_rw_unlock(&fwd->lock); }
return; /* nothing to do */
if(z->dp != NULL)
}
if(z->dp != NULL) {
if(!nolock) { lock_rw_unlock(&fwd->lock); }
return; /* not a stub hole */
}
(void)rbtree_delete(fwd->tree, &z->node);
fwd_zone_free(z);
fwd_init_parents(fwd);
if(!nolock) { lock_rw_unlock(&fwd->lock); }
}

View file

@ -43,6 +43,7 @@
#ifndef ITERATOR_ITER_FWD_H
#define ITERATOR_ITER_FWD_H
#include "util/rbtree.h"
#include "util/locks.h"
struct config_file;
struct delegpt;
@ -50,6 +51,11 @@ struct delegpt;
* Iterator forward zones structure
*/
struct iter_forwards {
/** lock on the forwards tree.
* When grabbing both this lock and the anchors.lock, this lock
* is grabbed first. When grabbing both this lock and the hints.lock
* this lock is grabbed first. */
lock_rw_type lock;
/**
* Zones are stored in this tree. Sort order is specially chosen.
* first sorted on qclass. Then on dname in nsec-like order, so that
@ -106,47 +112,65 @@ int forwards_apply_cfg(struct iter_forwards* fwd, struct config_file* cfg);
/**
* Find forward zone exactly by name
* The return value is contents of the forwards structure.
* Caller should lock and unlock a readlock on the forwards structure if nolock
* is set.
* Otherwise caller should unlock the readlock on the forwards structure if a
* value was returned.
* @param fwd: forward storage.
* @param qname: The qname of the query.
* @param qclass: The qclass of the query.
* @param nolock: Skip locking, locking is handled by the caller.
* @return: A delegation point or null.
*/
struct delegpt* forwards_find(struct iter_forwards* fwd, uint8_t* qname,
uint16_t qclass);
uint16_t qclass, int nolock);
/**
* Find forward zone information
* For this qname/qclass find forward zone information, returns delegation
* point with server names and addresses, or NULL if no forwarding is needed.
* The return value is contents of the forwards structure.
* Caller should lock and unlock a readlock on the forwards structure if nolock
* is set.
* Otherwise caller should unlock the readlock on the forwards structure if a
* value was returned.
*
* @param fwd: forward storage.
* @param qname: The qname of the query.
* @param qclass: The qclass of the query.
* @param nolock: Skip locking, locking is handled by the caller.
* @return: A delegation point if the query has to be forwarded to that list,
* otherwise null.
*/
struct delegpt* forwards_lookup(struct iter_forwards* fwd,
uint8_t* qname, uint16_t qclass);
struct delegpt* forwards_lookup(struct iter_forwards* fwd,
uint8_t* qname, uint16_t qclass, int nolock);
/**
* Same as forwards_lookup, but for the root only
* @param fwd: forward storage.
* @param qclass: The qclass of the query.
* @param nolock: Skip locking, locking is handled by the caller.
* @return: A delegation point if root forward exists, otherwise null.
*/
struct delegpt* forwards_lookup_root(struct iter_forwards* fwd,
uint16_t qclass);
struct delegpt* forwards_lookup_root(struct iter_forwards* fwd,
uint16_t qclass, int nolock);
/**
* Find next root item in forwards lookup tree.
* Handles its own locking unless nolock is set. In that case the caller
* should lock and unlock a readlock on the forwards structure.
* @param fwd: the forward storage
* @param qclass: class to look at next, or higher.
* @param nolock: Skip locking, locking is handled by the caller.
* @return false if none found, or if true stored in qclass.
*/
int forwards_next_root(struct iter_forwards* fwd, uint16_t* qclass);
int forwards_next_root(struct iter_forwards* fwd, uint16_t* qclass,
int nolock);
/**
* Get memory in use by forward storage
* Locks and unlocks the structure.
* @param fwd: forward storage.
* @return bytes in use
*/
@ -158,42 +182,56 @@ int fwd_cmp(const void* k1, const void* k2);
/**
* Add zone to forward structure. For external use since it recalcs
* the tree parents.
* Handles its own locking unless nolock is set. In that case the caller
* should lock and unlock a writelock on the forwards structure.
* @param fwd: the forward data structure
* @param c: class of zone
* @param dp: delegation point with name and target nameservers for new
* forward zone. malloced.
* @param nolock: Skip locking, locking is handled by the caller.
* @return false on failure (out of memory);
*/
int forwards_add_zone(struct iter_forwards* fwd, uint16_t c,
struct delegpt* dp);
int forwards_add_zone(struct iter_forwards* fwd, uint16_t c,
struct delegpt* dp, int nolock);
/**
* Remove zone from forward structure. For external use since it
* recalcs the tree parents.
* Handles its own locking unless nolock is set. In that case the caller
* should lock and unlock a writelock on the forwards structure.
* @param fwd: the forward data structure
* @param c: class of zone
* @param nm: name of zone (in uncompressed wireformat).
* @param nolock: Skip locking, locking is handled by the caller.
*/
void forwards_delete_zone(struct iter_forwards* fwd, uint16_t c, uint8_t* nm);
void forwards_delete_zone(struct iter_forwards* fwd, uint16_t c,
uint8_t* nm, int nolock);
/**
* Add stub hole (empty entry in forward table, that makes resolution skip
* a forward-zone because the stub zone should override the forward zone).
* Does not add one if not necessary.
* Handles its own locking unless nolock is set. In that case the caller
* should lock and unlock a writelock on the forwards structure.
* @param fwd: the forward data structure
* @param c: class of zone
* @param nm: name of zone (in uncompressed wireformat).
* @param nolock: Skip locking, locking is handled by the caller.
* @return false on failure (out of memory);
*/
int forwards_add_stub_hole(struct iter_forwards* fwd, uint16_t c, uint8_t* nm);
int forwards_add_stub_hole(struct iter_forwards* fwd, uint16_t c,
uint8_t* nm, int nolock);
/**
* Remove stub hole, if one exists.
* Handles its own locking unless nolock is set. In that case the caller
* should lock and unlock a writelock on the forwards structure.
* @param fwd: the forward data structure
* @param c: class of zone
* @param nm: name of zone (in uncompressed wireformat).
* @param nolock: Skip locking, locking is handled by the caller.
*/
void forwards_delete_stub_hole(struct iter_forwards* fwd, uint16_t c,
uint8_t* nm);
uint8_t* nm, int nolock);
#endif /* ITERATOR_ITER_FWD_H */

View file

@ -57,6 +57,8 @@ hints_create(void)
sizeof(struct iter_hints));
if(!hints)
return NULL;
lock_rw_init(&hints->lock);
lock_protect(&hints->lock, &hints->tree, sizeof(hints->tree));
return hints;
}
@ -83,6 +85,7 @@ hints_delete(struct iter_hints* hints)
{
if(!hints)
return;
lock_rw_destroy(&hints->lock);
hints_del_tree(hints);
free(hints);
}
@ -438,47 +441,70 @@ read_root_hints_list(struct iter_hints* hints, struct config_file* cfg)
int
hints_apply_cfg(struct iter_hints* hints, struct config_file* cfg)
{
int nolock = 1;
lock_rw_wrlock(&hints->lock);
hints_del_tree(hints);
name_tree_init(&hints->tree);
/* read root hints */
if(!read_root_hints_list(hints, cfg))
if(!read_root_hints_list(hints, cfg)) {
lock_rw_unlock(&hints->lock);
return 0;
}
/* read stub hints */
if(!read_stubs(hints, cfg))
if(!read_stubs(hints, cfg)) {
lock_rw_unlock(&hints->lock);
return 0;
}
/* use fallback compiletime root hints */
if(!hints_lookup_root(hints, LDNS_RR_CLASS_IN)) {
if(!hints_find_root(hints, LDNS_RR_CLASS_IN, nolock)) {
struct delegpt* dp = compile_time_root_prime(cfg->do_ip4,
cfg->do_ip6);
verbose(VERB_ALGO, "no config, using builtin root hints.");
if(!dp)
if(!dp) {
lock_rw_unlock(&hints->lock);
return 0;
if(!hints_insert(hints, LDNS_RR_CLASS_IN, dp, 0))
}
if(!hints_insert(hints, LDNS_RR_CLASS_IN, dp, 0)) {
lock_rw_unlock(&hints->lock);
return 0;
}
}
name_tree_init_parents(&hints->tree);
lock_rw_unlock(&hints->lock);
return 1;
}
struct delegpt*
hints_lookup_root(struct iter_hints* hints, uint16_t qclass)
struct delegpt*
hints_find(struct iter_hints* hints, uint8_t* qname, uint16_t qclass,
int nolock)
{
struct iter_hints_stub *stub;
size_t len;
int has_dp;
int labs = dname_count_size_labels(qname, &len);
/* lock_() calls are macros that could be nothing, surround in {} */
if(!nolock) { lock_rw_rdlock(&hints->lock); }
stub = (struct iter_hints_stub*)name_tree_find(&hints->tree,
qname, len, labs, qclass);
has_dp = stub && stub->dp;
if(!has_dp && !nolock) { lock_rw_unlock(&hints->lock); }
return has_dp?stub->dp:NULL;
}
struct delegpt*
hints_find_root(struct iter_hints* hints, uint16_t qclass, int nolock)
{
uint8_t rootlab = 0;
struct iter_hints_stub *stub;
stub = (struct iter_hints_stub*)name_tree_find(&hints->tree,
&rootlab, 1, 1, qclass);
if(!stub)
return NULL;
return stub->dp;
return hints_find(hints, &rootlab, qclass, nolock);
}
struct iter_hints_stub*
hints_lookup_stub(struct iter_hints* hints, uint8_t* qname,
uint16_t qclass, struct delegpt* cache_dp)
hints_lookup_stub(struct iter_hints* hints, uint8_t* qname,
uint16_t qclass, struct delegpt* cache_dp, int nolock)
{
size_t len;
int labs;
@ -486,14 +512,20 @@ hints_lookup_stub(struct iter_hints* hints, uint8_t* qname,
/* first lookup the stub */
labs = dname_count_size_labels(qname, &len);
/* lock_() calls are macros that could be nothing, surround in {} */
if(!nolock) { lock_rw_rdlock(&hints->lock); }
r = (struct iter_hints_stub*)name_tree_lookup(&hints->tree, qname,
len, labs, qclass);
if(!r) return NULL;
if(!r) {
if(!nolock) { lock_rw_unlock(&hints->lock); }
return NULL;
}
/* If there is no cache (root prime situation) */
if(cache_dp == NULL) {
if(r->dp->namelabs != 1)
return r; /* no cache dp, use any non-root stub */
if(!nolock) { lock_rw_unlock(&hints->lock); }
return NULL;
}
@ -510,12 +542,18 @@ hints_lookup_stub(struct iter_hints* hints, uint8_t* qname,
if(dname_strict_subdomain(r->dp->name, r->dp->namelabs,
cache_dp->name, cache_dp->namelabs))
return r; /* need to prime this stub */
if(!nolock) { lock_rw_unlock(&hints->lock); }
return NULL;
}
int hints_next_root(struct iter_hints* hints, uint16_t* qclass)
int hints_next_root(struct iter_hints* hints, uint16_t* qclass, int nolock)
{
return name_tree_next_root(&hints->tree, qclass);
int ret;
/* lock_() calls are macros that could be nothing, surround in {} */
if(!nolock) { lock_rw_rdlock(&hints->lock); }
ret = name_tree_next_root(&hints->tree, qclass);
if(!nolock) { lock_rw_unlock(&hints->lock); }
return ret;
}
size_t
@ -524,39 +562,52 @@ hints_get_mem(struct iter_hints* hints)
size_t s;
struct iter_hints_stub* p;
if(!hints) return 0;
lock_rw_rdlock(&hints->lock);
s = sizeof(*hints);
RBTREE_FOR(p, struct iter_hints_stub*, &hints->tree) {
s += sizeof(*p) + delegpt_get_mem(p->dp);
}
lock_rw_unlock(&hints->lock);
return s;
}
int
hints_add_stub(struct iter_hints* hints, uint16_t c, struct delegpt* dp,
int noprime)
int noprime, int nolock)
{
struct iter_hints_stub *z;
/* lock_() calls are macros that could be nothing, surround in {} */
if(!nolock) { lock_rw_wrlock(&hints->lock); }
if((z=(struct iter_hints_stub*)name_tree_find(&hints->tree,
dp->name, dp->namelen, dp->namelabs, c)) != NULL) {
(void)rbtree_delete(&hints->tree, &z->node);
hints_stub_free(z);
}
if(!hints_insert(hints, c, dp, noprime))
if(!hints_insert(hints, c, dp, noprime)) {
if(!nolock) { lock_rw_unlock(&hints->lock); }
return 0;
}
name_tree_init_parents(&hints->tree);
if(!nolock) { lock_rw_unlock(&hints->lock); }
return 1;
}
void
hints_delete_stub(struct iter_hints* hints, uint16_t c, uint8_t* nm)
hints_delete_stub(struct iter_hints* hints, uint16_t c, uint8_t* nm,
int nolock)
{
struct iter_hints_stub *z;
size_t len;
int labs = dname_count_size_labels(nm, &len);
/* lock_() calls are macros that could be nothing, surround in {} */
if(!nolock) { lock_rw_wrlock(&hints->lock); }
if(!(z=(struct iter_hints_stub*)name_tree_find(&hints->tree,
nm, len, labs, c)))
nm, len, labs, c))) {
if(!nolock) { lock_rw_unlock(&hints->lock); }
return; /* nothing to do */
}
(void)rbtree_delete(&hints->tree, &z->node);
hints_stub_free(z);
name_tree_init_parents(&hints->tree);
if(!nolock) { lock_rw_unlock(&hints->lock); }
}

View file

@ -43,6 +43,7 @@
#ifndef ITERATOR_ITER_HINTS_H
#define ITERATOR_ITER_HINTS_H
#include "util/storage/dnstree.h"
#include "util/locks.h"
struct iter_env;
struct config_file;
struct delegpt;
@ -51,6 +52,10 @@ struct delegpt;
* Iterator hints structure
*/
struct iter_hints {
/** lock on the forwards tree.
* When grabbing both this lock and the anchors.lock, this lock
* is grabbed first. */
lock_rw_type lock;
/**
* Hints are stored in this tree. Sort order is specially chosen.
* first sorted on qclass. Then on dname in nsec-like order, so that
@ -95,42 +100,70 @@ void hints_delete(struct iter_hints* hints);
int hints_apply_cfg(struct iter_hints* hints, struct config_file* cfg);
/**
* Find root hints for the given class.
* Find hints for the given class.
* The return value is contents of the hints structure.
* Caller should lock and unlock a readlock on the hints structure if nolock
* is set.
* Otherwise caller should unlock the readlock on the hints structure if a
* value was returned.
* @param hints: hint storage.
* @param qname: the qname that generated the delegation point.
* @param qclass: class for which root hints are requested. host order.
* @param nolock: Skip locking, locking is handled by the caller.
* @return: NULL if no hints, or a ptr to stored hints.
*/
struct delegpt* hints_lookup_root(struct iter_hints* hints, uint16_t qclass);
struct delegpt* hints_find(struct iter_hints* hints, uint8_t* qname,
uint16_t qclass, int nolock);
/**
* Same as hints_lookup, but for the root only.
* @param hints: hint storage.
* @param qclass: class for which root hints are requested. host order.
* @param nolock: Skip locking, locking is handled by the caller.
* @return: NULL if no hints, or a ptr to stored hints.
*/
struct delegpt* hints_find_root(struct iter_hints* hints,
uint16_t qclass, int nolock);
/**
* Find next root hints (to cycle through all root hints).
* Handles its own locking unless nolock is set. In that case the caller
* should lock and unlock a readlock on the hints structure.
* @param hints: hint storage
* @param qclass: class for which root hints are sought.
* 0 means give the first available root hints class.
* x means, give class x or a higher class if any.
* returns the found class in this variable.
* @param nolock: Skip locking, locking is handled by the caller.
* @return true if a root hint class is found.
* false if not root hint class is found (qclass may have been changed).
*/
int hints_next_root(struct iter_hints* hints, uint16_t* qclass);
int hints_next_root(struct iter_hints* hints, uint16_t* qclass, int nolock);
/**
* Given a qname/qclass combination, and the delegation point from the cache
* for this qname/qclass, determine if this combination indicates that a
* stub hint exists and must be primed.
* The return value is contents of the hints structure.
* Caller should lock and unlock a readlock on the hints structure if nolock
* is set.
* Otherwise caller should unlock the readlock on the hints structure if a
* value was returned.
*
* @param hints: hint storage.
* @param qname: The qname that generated the delegation point.
* @param qclass: The qclass that generated the delegation point.
* @param dp: The cache generated delegation point.
* @param nolock: Skip locking, locking is handled by the caller.
* @return: A priming delegation point if there is a stub hint that must
* be primed, otherwise null.
*/
struct iter_hints_stub* hints_lookup_stub(struct iter_hints* hints,
uint8_t* qname, uint16_t qclass, struct delegpt* dp);
struct iter_hints_stub* hints_lookup_stub(struct iter_hints* hints,
uint8_t* qname, uint16_t qclass, struct delegpt* dp, int nolock);
/**
* Get memory in use by hints
* Locks and unlocks the structure.
* @param hints: hint storage.
* @return bytes in use
*/
@ -139,23 +172,30 @@ size_t hints_get_mem(struct iter_hints* hints);
/**
* Add stub to hints structure. For external use since it recalcs
* the tree parents.
* Handles its own locking unless nolock is set. In that case the caller
* should lock and unlock a writelock on the hints structure.
* @param hints: the hints data structure
* @param c: class of zone
* @param dp: delegation point with name and target nameservers for new
* hints stub. malloced.
* @param noprime: set noprime option to true or false on new hint stub.
* @param nolock: Skip locking, locking is handled by the caller.
* @return false on failure (out of memory);
*/
int hints_add_stub(struct iter_hints* hints, uint16_t c, struct delegpt* dp,
int noprime);
int noprime, int nolock);
/**
* Remove stub from hints structure. For external use since it
* recalcs the tree parents.
* Handles its own locking unless nolock is set. In that case the caller
* should lock and unlock a writelock on the hints structure.
* @param hints: the hints data structure
* @param c: class of stub zone
* @param nm: name of stub zone (in uncompressed wireformat).
* @param nolock: Skip locking, locking is handled by the caller.
*/
void hints_delete_stub(struct iter_hints* hints, uint16_t c, uint8_t* nm);
void hints_delete_stub(struct iter_hints* hints, uint16_t c,
uint8_t* nm, int nolock);
#endif /* ITERATOR_ITER_HINTS_H */

View file

@ -1284,8 +1284,17 @@ iter_get_next_root(struct iter_hints* hints, struct iter_forwards* fwd,
uint16_t* c)
{
uint16_t c1 = *c, c2 = *c;
int r1 = hints_next_root(hints, &c1);
int r2 = forwards_next_root(fwd, &c2);
int r1, r2;
int nolock = 1;
/* prelock both forwards and hints for atomic read. */
lock_rw_rdlock(&fwd->lock);
lock_rw_rdlock(&hints->lock);
r1 = hints_next_root(hints, &c1, nolock);
r2 = forwards_next_root(fwd, &c2, nolock);
lock_rw_unlock(&fwd->lock);
lock_rw_unlock(&hints->lock);
if(!r1 && !r2) /* got none, end of list */
return 0;
else if(!r1) /* got one, return that */
@ -1450,15 +1459,21 @@ int iter_dp_cangodown(struct query_info* qinfo, struct delegpt* dp)
int
iter_stub_fwd_no_cache(struct module_qstate *qstate, struct query_info *qinf,
uint8_t** retdpname, size_t* retdpnamelen)
uint8_t** retdpname, size_t* retdpnamelen, uint8_t* dpname_storage,
size_t dpname_storage_len)
{
struct iter_hints_stub *stub;
struct delegpt *dp;
int nolock = 1;
/* Check for stub. */
/* Lock both forwards and hints for atomic read. */
lock_rw_rdlock(&qstate->env->fwds->lock);
lock_rw_rdlock(&qstate->env->hints->lock);
stub = hints_lookup_stub(qstate->env->hints, qinf->qname,
qinf->qclass, NULL);
dp = forwards_lookup(qstate->env->fwds, qinf->qname, qinf->qclass);
qinf->qclass, NULL, nolock);
dp = forwards_lookup(qstate->env->fwds, qinf->qname, qinf->qclass,
nolock);
/* see if forward or stub is more pertinent */
if(stub && stub->dp && dp) {
@ -1472,7 +1487,9 @@ iter_stub_fwd_no_cache(struct module_qstate *qstate, struct query_info *qinf,
/* check stub */
if (stub != NULL && stub->dp != NULL) {
if(stub->dp->no_cache) {
int stub_no_cache = stub->dp->no_cache;
lock_rw_unlock(&qstate->env->fwds->lock);
if(stub_no_cache) {
char qname[255+1];
char dpname[255+1];
dname_str(qinf->qname, qname);
@ -1480,15 +1497,27 @@ iter_stub_fwd_no_cache(struct module_qstate *qstate, struct query_info *qinf,
verbose(VERB_ALGO, "stub for %s %s has no_cache", qname, dpname);
}
if(retdpname) {
*retdpname = stub->dp->name;
if(stub->dp->namelen > dpname_storage_len) {
verbose(VERB_ALGO, "no cache stub dpname too long");
lock_rw_unlock(&qstate->env->hints->lock);
*retdpname = NULL;
*retdpnamelen = 0;
return stub_no_cache;
}
memmove(dpname_storage, stub->dp->name,
stub->dp->namelen);
*retdpname = dpname_storage;
*retdpnamelen = stub->dp->namelen;
}
return (stub->dp->no_cache);
lock_rw_unlock(&qstate->env->hints->lock);
return stub_no_cache;
}
/* Check for forward. */
if (dp) {
if(dp->no_cache) {
int dp_no_cache = dp->no_cache;
lock_rw_unlock(&qstate->env->hints->lock);
if(dp_no_cache) {
char qname[255+1];
char dpname[255+1];
dname_str(qinf->qname, qname);
@ -1496,11 +1525,22 @@ iter_stub_fwd_no_cache(struct module_qstate *qstate, struct query_info *qinf,
verbose(VERB_ALGO, "forward for %s %s has no_cache", qname, dpname);
}
if(retdpname) {
*retdpname = dp->name;
if(dp->namelen > dpname_storage_len) {
verbose(VERB_ALGO, "no cache dpname too long");
lock_rw_unlock(&qstate->env->fwds->lock);
*retdpname = NULL;
*retdpnamelen = 0;
return dp_no_cache;
}
memmove(dpname_storage, dp->name, dp->namelen);
*retdpname = dpname_storage;
*retdpnamelen = dp->namelen;
}
return (dp->no_cache);
lock_rw_unlock(&qstate->env->fwds->lock);
return dp_no_cache;
}
lock_rw_unlock(&qstate->env->fwds->lock);
lock_rw_unlock(&qstate->env->hints->lock);
if(retdpname) {
*retdpname = NULL;
*retdpnamelen = 0;

View file

@ -407,10 +407,14 @@ int iter_dp_cangodown(struct query_info* qinfo, struct delegpt* dp);
* Used for NXDOMAIN checks, above that it is an nxdomain from a
* different server and zone. You can pass NULL to not get it.
* @param retdpnamelen: returns the length of the dpname.
* @param dpname_storage: this is where the dpname buf is stored, if any.
* So that caller can manage the buffer.
* @param dpname_storage_len: size of dpname_storage buffer.
* @return true if no_cache is set in stub or fwd.
*/
int iter_stub_fwd_no_cache(struct module_qstate *qstate,
struct query_info *qinf, uint8_t** retdpname, size_t* retdpnamelen);
struct query_info *qinf, uint8_t** retdpname, size_t* retdpnamelen,
uint8_t* dpname_storage, size_t dpname_storage_len);
/**
* Set support for IP4 and IP6 depending on outgoing interfaces

View file

@ -52,6 +52,7 @@
#include "iterator/iter_priv.h"
#include "validator/val_neg.h"
#include "services/cache/dns.h"
#include "services/cache/rrset.h"
#include "services/cache/infra.h"
#include "services/authzone.h"
#include "util/module.h"
@ -678,30 +679,40 @@ errinf_reply(struct module_qstate* qstate, struct iter_qstate* iq)
/** see if last resort is possible - does config allow queries to parent */
static int
can_have_last_resort(struct module_env* env, uint8_t* nm, size_t nmlen,
uint16_t qclass, struct delegpt** retdp)
can_have_last_resort(struct module_env* env, uint8_t* nm, size_t ATTR_UNUSED(nmlen),
uint16_t qclass, int* have_dp, struct delegpt** retdp,
struct regional* region)
{
struct delegpt* fwddp;
struct iter_hints_stub* stub;
int labs = dname_count_labels(nm);
struct delegpt* dp = NULL;
int nolock = 0;
/* do not process a last resort (the parent side) if a stub
* or forward is configured, because we do not want to go 'above'
* the configured servers */
if(!dname_is_root(nm) && (stub = (struct iter_hints_stub*)
name_tree_find(&env->hints->tree, nm, nmlen, labs, qclass)) &&
if(!dname_is_root(nm) &&
(dp = hints_find(env->hints, nm, qclass, nolock)) &&
/* has_parent side is turned off for stub_first, where we
* are allowed to go to the parent */
stub->dp->has_parent_side_NS) {
if(retdp) *retdp = stub->dp;
dp->has_parent_side_NS) {
if(retdp) *retdp = delegpt_copy(dp, region);
lock_rw_unlock(&env->hints->lock);
if(have_dp) *have_dp = 1;
return 0;
}
if((fwddp = forwards_find(env->fwds, nm, qclass)) &&
if(dp) {
lock_rw_unlock(&env->hints->lock);
dp = NULL;
}
if((dp = forwards_find(env->fwds, nm, qclass, nolock)) &&
/* has_parent_side is turned off for forward_first, where
* we are allowed to go to the parent */
fwddp->has_parent_side_NS) {
if(retdp) *retdp = fwddp;
dp->has_parent_side_NS) {
if(retdp) *retdp = delegpt_copy(dp, region);
lock_rw_unlock(&env->fwds->lock);
if(have_dp) *have_dp = 1;
return 0;
}
/* lock_() calls are macros that could be nothing, surround in {} */
if(dp) { lock_rw_unlock(&env->fwds->lock); }
return 1;
}
@ -877,10 +888,11 @@ prime_root(struct module_qstate* qstate, struct iter_qstate* iq, int id,
{
struct delegpt* dp;
struct module_qstate* subq;
int nolock = 0;
verbose(VERB_DETAIL, "priming . %s NS",
sldns_lookup_by_id(sldns_rr_classes, (int)qclass)?
sldns_lookup_by_id(sldns_rr_classes, (int)qclass)->name:"??");
dp = hints_lookup_root(qstate->env->hints, qclass);
dp = hints_find_root(qstate->env->hints, qclass, nolock);
if(!dp) {
verbose(VERB_ALGO, "Cannot prime due to lack of hints");
return 0;
@ -890,6 +902,7 @@ prime_root(struct module_qstate* qstate, struct iter_qstate* iq, int id,
if(!generate_sub_request((uint8_t*)"\000", 1, LDNS_RR_TYPE_NS,
qclass, qstate, id, iq, QUERYTARGETS_STATE, PRIME_RESP_STATE,
&subq, 0, 0)) {
lock_rw_unlock(&qstate->env->hints->lock);
verbose(VERB_ALGO, "could not prime root");
return 0;
}
@ -900,6 +913,7 @@ prime_root(struct module_qstate* qstate, struct iter_qstate* iq, int id,
* copy dp, it is now part of the root prime query.
* dp was part of in the fixed hints structure. */
subiq->dp = delegpt_copy(dp, subq->region);
lock_rw_unlock(&qstate->env->hints->lock);
if(!subiq->dp) {
log_err("out of memory priming root, copydp");
fptr_ok(fptr_whitelist_modenv_kill_sub(
@ -911,6 +925,8 @@ prime_root(struct module_qstate* qstate, struct iter_qstate* iq, int id,
subiq->num_target_queries = 0;
subiq->dnssec_expected = iter_indicates_dnssec(
qstate->env, subiq->dp, NULL, subq->qinfo.qclass);
} else {
lock_rw_unlock(&qstate->env->hints->lock);
}
/* this module stops, our submodule starts, and does the query. */
@ -941,18 +957,21 @@ prime_stub(struct module_qstate* qstate, struct iter_qstate* iq, int id,
struct iter_hints_stub* stub;
struct delegpt* stub_dp;
struct module_qstate* subq;
int nolock = 0;
if(!qname) return 0;
stub = hints_lookup_stub(qstate->env->hints, qname, qclass, iq->dp);
stub = hints_lookup_stub(qstate->env->hints, qname, qclass, iq->dp,
nolock);
/* The stub (if there is one) does not need priming. */
if(!stub)
return 0;
if(!stub) return 0;
stub_dp = stub->dp;
/* if we have an auth_zone dp, and stub is equal, don't prime stub
* yet, unless we want to fallback and avoid the auth_zone */
if(!iq->auth_zone_avoid && iq->dp && iq->dp->auth_dp &&
query_dname_compare(iq->dp->name, stub_dp->name) == 0)
query_dname_compare(iq->dp->name, stub_dp->name) == 0) {
lock_rw_unlock(&qstate->env->hints->lock);
return 0;
}
/* is it a noprime stub (always use) */
if(stub->noprime) {
@ -961,13 +980,14 @@ prime_stub(struct module_qstate* qstate, struct iter_qstate* iq, int id,
/* copy the dp out of the fixed hints structure, so that
* it can be changed when servicing this query */
iq->dp = delegpt_copy(stub_dp, qstate->region);
lock_rw_unlock(&qstate->env->hints->lock);
if(!iq->dp) {
log_err("out of memory priming stub");
errinf(qstate, "malloc failure, priming stub");
(void)error_response(qstate, id, LDNS_RCODE_SERVFAIL);
return 1; /* return 1 to make module stop, with error */
}
log_nametypeclass(VERB_DETAIL, "use stub", stub_dp->name,
log_nametypeclass(VERB_DETAIL, "use stub", iq->dp->name,
LDNS_RR_TYPE_NS, qclass);
return r;
}
@ -981,6 +1001,7 @@ prime_stub(struct module_qstate* qstate, struct iter_qstate* iq, int id,
if(!generate_sub_request(stub_dp->name, stub_dp->namelen,
LDNS_RR_TYPE_NS, qclass, qstate, id, iq,
QUERYTARGETS_STATE, PRIME_RESP_STATE, &subq, 0, 0)) {
lock_rw_unlock(&qstate->env->hints->lock);
verbose(VERB_ALGO, "could not prime stub");
errinf(qstate, "could not generate lookup for stub prime");
(void)error_response(qstate, id, LDNS_RCODE_SERVFAIL);
@ -993,6 +1014,7 @@ prime_stub(struct module_qstate* qstate, struct iter_qstate* iq, int id,
/* Set the initial delegation point to the hint. */
/* make copy to avoid use of stub dp by different qs/threads */
subiq->dp = delegpt_copy(stub_dp, subq->region);
lock_rw_unlock(&qstate->env->hints->lock);
if(!subiq->dp) {
log_err("out of memory priming stub, copydp");
fptr_ok(fptr_whitelist_modenv_kill_sub(
@ -1009,6 +1031,8 @@ prime_stub(struct module_qstate* qstate, struct iter_qstate* iq, int id,
subiq->wait_priming_stub = 1;
subiq->dnssec_expected = iter_indicates_dnssec(
qstate->env, subiq->dp, NULL, subq->qinfo.qclass);
} else {
lock_rw_unlock(&qstate->env->hints->lock);
}
/* this module stops, our submodule starts, and does the query. */
@ -1181,7 +1205,7 @@ generate_ns_check(struct module_qstate* qstate, struct iter_qstate* iq, int id)
if(iq->depth == ie->max_dependency_depth)
return;
if(!can_have_last_resort(qstate->env, iq->dp->name, iq->dp->namelen,
iq->qchase.qclass, NULL))
iq->qchase.qclass, NULL, NULL, NULL))
return;
/* is this query the same as the nscheck? */
if(qstate->qinfo.qtype == LDNS_RR_TYPE_NS &&
@ -1294,6 +1318,7 @@ forward_request(struct module_qstate* qstate, struct iter_qstate* iq)
struct delegpt* dp;
uint8_t* delname = iq->qchase.qname;
size_t delnamelen = iq->qchase.qname_len;
int nolock = 0;
if(iq->refetch_glue && iq->dp) {
delname = iq->dp->name;
delnamelen = iq->dp->namelen;
@ -1302,12 +1327,13 @@ forward_request(struct module_qstate* qstate, struct iter_qstate* iq)
if( (iq->qchase.qtype == LDNS_RR_TYPE_DS || iq->refetch_glue)
&& !dname_is_root(iq->qchase.qname))
dname_remove_label(&delname, &delnamelen);
dp = forwards_lookup(qstate->env->fwds, delname, iq->qchase.qclass);
if(!dp)
return 0;
dp = forwards_lookup(qstate->env->fwds, delname, iq->qchase.qclass,
nolock);
if(!dp) return 0;
/* send recursion desired to forward addr */
iq->chase_flags |= BIT_RD;
iq->dp = delegpt_copy(dp, qstate->region);
lock_rw_unlock(&qstate->env->fwds->lock);
/* iq->dp checked by caller */
verbose(VERB_ALGO, "forwarding request");
return 1;
@ -1335,6 +1361,7 @@ static int
processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
struct iter_env* ie, int id)
{
uint8_t dpname_storage[LDNS_MAX_DOMAINLEN+1];
uint8_t* delname, *dpname=NULL;
size_t delnamelen, dpnamelen=0;
struct dns_msg* msg = NULL;
@ -1381,7 +1408,7 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
if (iq->refetch_glue &&
iq->dp &&
!can_have_last_resort(qstate->env, iq->dp->name,
iq->dp->namelen, iq->qchase.qclass, NULL)) {
iq->dp->namelen, iq->qchase.qclass, NULL, NULL, NULL)) {
iq->refetch_glue = 0;
}
@ -1389,8 +1416,61 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
/* This either results in a query restart (CNAME cache response), a
* terminating response (ANSWER), or a cache miss (null). */
if (iter_stub_fwd_no_cache(qstate, &iq->qchase, &dpname, &dpnamelen)) {
/* Check RPZ for override */
if(qstate->env->auth_zones) {
/* apply rpz qname triggers, like after cname */
struct dns_msg* forged_response =
rpz_callback_from_iterator_cname(qstate, iq);
if(forged_response) {
uint8_t* sname = 0;
size_t slen = 0;
int count = 0;
while(forged_response && reply_find_rrset_section_an(
forged_response->rep, iq->qchase.qname,
iq->qchase.qname_len, LDNS_RR_TYPE_CNAME,
iq->qchase.qclass) &&
iq->qchase.qtype != LDNS_RR_TYPE_CNAME &&
count++ < ie->max_query_restarts) {
/* another cname to follow */
if(!handle_cname_response(qstate, iq, forged_response,
&sname, &slen)) {
errinf(qstate, "malloc failure, CNAME info");
return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
}
iq->qchase.qname = sname;
iq->qchase.qname_len = slen;
forged_response =
rpz_callback_from_iterator_cname(qstate, iq);
}
if(forged_response != NULL) {
qstate->ext_state[id] = module_finished;
qstate->return_rcode = LDNS_RCODE_NOERROR;
qstate->return_msg = forged_response;
iq->response = forged_response;
next_state(iq, FINISHED_STATE);
if(!iter_prepend(iq, qstate->return_msg, qstate->region)) {
log_err("rpz: after cached cname, prepend rrsets: out of memory");
return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
}
qstate->return_msg->qinfo = qstate->qinfo;
return 0;
}
/* Follow the CNAME response */
iq->dp = NULL;
iq->refetch_glue = 0;
iq->query_restart_count++;
iq->sent_count = 0;
iq->dp_target_count = 0;
sock_list_insert(&qstate->reply_origin, NULL, 0, qstate->region);
if(qstate->env->cfg->qname_minimisation)
iq->minimisation_state = INIT_MINIMISE_STATE;
return next_state(iq, INIT_REQUEST_STATE);
}
}
if (iter_stub_fwd_no_cache(qstate, &iq->qchase, &dpname, &dpnamelen,
dpname_storage, sizeof(dpname_storage))) {
/* Asked to not query cache. */
verbose(VERB_ALGO, "no-cache set, going to the network");
qstate->no_cache_lookup = 1;
@ -1449,39 +1529,6 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
}
iq->qchase.qname = sname;
iq->qchase.qname_len = slen;
if(qstate->env->auth_zones) {
/* apply rpz qname triggers after cname */
struct dns_msg* forged_response =
rpz_callback_from_iterator_cname(qstate, iq);
while(forged_response && reply_find_rrset_section_an(
forged_response->rep, iq->qchase.qname,
iq->qchase.qname_len, LDNS_RR_TYPE_CNAME,
iq->qchase.qclass)) {
/* another cname to follow */
if(!handle_cname_response(qstate, iq, forged_response,
&sname, &slen)) {
errinf(qstate, "malloc failure, CNAME info");
return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
}
iq->qchase.qname = sname;
iq->qchase.qname_len = slen;
forged_response =
rpz_callback_from_iterator_cname(qstate, iq);
}
if(forged_response != NULL) {
qstate->ext_state[id] = module_finished;
qstate->return_rcode = LDNS_RCODE_NOERROR;
qstate->return_msg = forged_response;
iq->response = forged_response;
next_state(iq, FINISHED_STATE);
if(!iter_prepend(iq, qstate->return_msg, qstate->region)) {
log_err("rpz: after cached cname, prepend rrsets: out of memory");
return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
}
qstate->return_msg->qinfo = qstate->qinfo;
return 0;
}
}
/* This *is* a query restart, even if it is a cheap
* one. */
iq->dp = NULL;
@ -1494,7 +1541,6 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
iq->minimisation_state = INIT_MINIMISE_STATE;
return next_state(iq, INIT_REQUEST_STATE);
}
/* if from cache, NULL, else insert 'cache IP' len=0 */
if(qstate->reply_origin)
sock_list_insert(&qstate->reply_origin, NULL, 0, qstate->region);
@ -1555,7 +1601,7 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
}
if(iq->qchase.qtype == LDNS_RR_TYPE_DS || iq->refetch_glue ||
(iq->qchase.qtype == LDNS_RR_TYPE_NS && qstate->prefetch_leeway
&& can_have_last_resort(qstate->env, delname, delnamelen, iq->qchase.qclass, NULL))) {
&& can_have_last_resort(qstate->env, delname, delnamelen, iq->qchase.qclass, NULL, NULL, NULL))) {
/* remove first label from delname, root goes to hints,
* but only to fetch glue, not for qtype=DS. */
/* also when prefetching an NS record, fetch it again from
@ -1584,6 +1630,7 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
* root priming situation. */
if(iq->dp == NULL) {
int r;
int nolock = 0;
/* if under auth zone, no prime needed */
if(!auth_zone_delegpt(qstate, iq, delname, delnamelen))
return error_response(qstate, id,
@ -1597,12 +1644,13 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
break; /* got noprime-stub-zone, continue */
else if(r)
return 0; /* stub prime request made */
if(forwards_lookup_root(qstate->env->fwds,
iq->qchase.qclass)) {
if(forwards_lookup_root(qstate->env->fwds,
iq->qchase.qclass, nolock)) {
lock_rw_unlock(&qstate->env->fwds->lock);
/* forward zone root, no root prime needed */
/* fill in some dp - safety belt */
iq->dp = hints_lookup_root(qstate->env->hints,
iq->qchase.qclass);
iq->dp = hints_find_root(qstate->env->hints,
iq->qchase.qclass, nolock);
if(!iq->dp) {
log_err("internal error: no hints dp");
errinf(qstate, "no hints for this class");
@ -1610,6 +1658,7 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
LDNS_RCODE_SERVFAIL);
}
iq->dp = delegpt_copy(iq->dp, qstate->region);
lock_rw_unlock(&qstate->env->hints->lock);
if(!iq->dp) {
log_err("out of memory in safety belt");
errinf(qstate, "malloc failure, in safety belt");
@ -1649,15 +1698,13 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
if(iter_dp_is_useless(&qstate->qinfo, qstate->query_flags,
iq->dp, ie->supports_ipv4, ie->supports_ipv6,
ie->use_nat64)) {
struct delegpt* retdp = NULL;
if(!can_have_last_resort(qstate->env, iq->dp->name, iq->dp->namelen, iq->qchase.qclass, &retdp)) {
if(retdp) {
int have_dp = 0;
if(!can_have_last_resort(qstate->env, iq->dp->name, iq->dp->namelen, iq->qchase.qclass, &have_dp, &iq->dp, qstate->region)) {
if(have_dp) {
verbose(VERB_QUERY, "cache has stub "
"or fwd but no addresses, "
"fallback to config");
iq->dp = delegpt_copy(retdp,
qstate->region);
if(!iq->dp) {
if(have_dp && !iq->dp) {
log_err("out of memory in "
"stub/fwd fallback");
errinf(qstate, "malloc failure, for fallback to config");
@ -1677,10 +1724,11 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
}
if(dname_is_root(iq->dp->name)) {
/* use safety belt */
int nolock = 0;
verbose(VERB_QUERY, "Cache has root NS but "
"no addresses. Fallback to the safety belt.");
iq->dp = hints_lookup_root(qstate->env->hints,
iq->qchase.qclass);
iq->dp = hints_find_root(qstate->env->hints,
iq->qchase.qclass, nolock);
/* note deleg_msg is from previous lookup,
* but RD is on, so it is not used */
if(!iq->dp) {
@ -1689,6 +1737,7 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
LDNS_RCODE_REFUSED);
}
iq->dp = delegpt_copy(iq->dp, qstate->region);
lock_rw_unlock(&qstate->env->hints->lock);
if(!iq->dp) {
log_err("out of memory in safety belt");
errinf(qstate, "malloc failure, in safety belt, for root");
@ -1744,6 +1793,7 @@ processInitRequest2(struct module_qstate* qstate, struct iter_qstate* iq,
delnamelen = iq->qchase.qname_len;
if(iq->refetch_glue) {
struct iter_hints_stub* stub;
int nolock = 0;
if(!iq->dp) {
log_err("internal or malloc fail: no dp for refetch");
errinf(qstate, "malloc failure, no delegation info");
@ -1753,12 +1803,14 @@ processInitRequest2(struct module_qstate* qstate, struct iter_qstate* iq,
* this is above stub without stub-first. */
stub = hints_lookup_stub(
qstate->env->hints, iq->qchase.qname, iq->qchase.qclass,
iq->dp);
iq->dp, nolock);
if(!stub || !stub->dp->has_parent_side_NS ||
dname_subdomain_c(iq->dp->name, stub->dp->name)) {
delname = iq->dp->name;
delnamelen = iq->dp->namelen;
}
/* lock_() calls are macros that could be nothing, surround in {} */
if(stub) { lock_rw_unlock(&qstate->env->hints->lock); }
}
if(iq->qchase.qtype == LDNS_RR_TYPE_DS || iq->refetch_glue) {
if(!dname_is_root(delname))
@ -2062,7 +2114,7 @@ processLastResort(struct module_qstate* qstate, struct iter_qstate* iq,
log_assert(iq->dp);
if(!can_have_last_resort(qstate->env, iq->dp->name, iq->dp->namelen,
iq->qchase.qclass, NULL)) {
iq->qchase.qclass, NULL, NULL, NULL)) {
/* fail -- no more targets, no more hope of targets, no hope
* of a response. */
errinf(qstate, "all the configured stub or forward servers failed,");
@ -2072,21 +2124,24 @@ processLastResort(struct module_qstate* qstate, struct iter_qstate* iq,
return error_response_cache(qstate, id, LDNS_RCODE_SERVFAIL);
}
if(!iq->dp->has_parent_side_NS && dname_is_root(iq->dp->name)) {
struct delegpt* p = hints_lookup_root(qstate->env->hints,
iq->qchase.qclass);
if(p) {
struct delegpt* dp;
int nolock = 0;
dp = hints_find_root(qstate->env->hints,
iq->qchase.qclass, nolock);
if(dp) {
struct delegpt_addr* a;
iq->chase_flags &= ~BIT_RD; /* go to authorities */
for(ns = p->nslist; ns; ns=ns->next) {
for(ns = dp->nslist; ns; ns=ns->next) {
(void)delegpt_add_ns(iq->dp, qstate->region,
ns->name, ns->lame, ns->tls_auth_name,
ns->port);
}
for(a = p->target_list; a; a=a->next_target) {
for(a = dp->target_list; a; a=a->next_target) {
(void)delegpt_add_addr(iq->dp, qstate->region,
&a->addr, a->addrlen, a->bogus,
a->lame, a->tls_auth_name, -1, NULL);
}
lock_rw_unlock(&qstate->env->hints->lock);
}
iq->dp->has_parent_side_NS = 1;
} else if(!iq->dp->has_parent_side_NS) {
@ -2164,7 +2219,7 @@ processLastResort(struct module_qstate* qstate, struct iter_qstate* iq,
if( ((ie->supports_ipv6 && !ns->done_pside6) ||
((ie->supports_ipv4 || ie->use_nat64) && !ns->done_pside4)) &&
!can_have_last_resort(qstate->env, ns->name, ns->namelen,
iq->qchase.qclass, NULL)) {
iq->qchase.qclass, NULL, NULL, NULL)) {
log_nametypeclass(VERB_ALGO, "cannot pside lookup ns "
"because it is also a stub/forward,",
ns->name, LDNS_RR_TYPE_NS, iq->qchase.qclass);
@ -2746,8 +2801,51 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
delegpt_add_unused_targets(iq->dp);
if(qstate->env->auth_zones) {
/* apply rpz triggers at query time */
uint8_t* sname = NULL;
size_t snamelen = 0;
/* apply rpz triggers at query time; nameserver IP and dname */
struct dns_msg* forged_response_after_cname;
struct dns_msg* forged_response = rpz_callback_from_iterator_module(qstate, iq);
int count = 0;
while(forged_response && reply_find_rrset_section_an(
forged_response->rep, iq->qchase.qname,
iq->qchase.qname_len, LDNS_RR_TYPE_CNAME,
iq->qchase.qclass) &&
iq->qchase.qtype != LDNS_RR_TYPE_CNAME &&
count++ < ie->max_query_restarts) {
/* another cname to follow */
if(!handle_cname_response(qstate, iq, forged_response,
&sname, &snamelen)) {
errinf(qstate, "malloc failure, CNAME info");
return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
}
iq->qchase.qname = sname;
iq->qchase.qname_len = snamelen;
forged_response_after_cname =
rpz_callback_from_iterator_cname(qstate, iq);
if(forged_response_after_cname) {
forged_response = forged_response_after_cname;
} else {
/* Follow the CNAME with a query restart */
iq->deleg_msg = NULL;
iq->dp = NULL;
iq->dsns_point = NULL;
iq->auth_zone_response = 0;
iq->refetch_glue = 0;
iq->query_restart_count++;
iq->sent_count = 0;
iq->dp_target_count = 0;
if(qstate->env->cfg->qname_minimisation)
iq->minimisation_state = INIT_MINIMISE_STATE;
outbound_list_clear(&iq->outlist);
iq->num_current_queries = 0;
fptr_ok(fptr_whitelist_modenv_detach_subs(
qstate->env->detach_subs));
(*qstate->env->detach_subs)(qstate);
iq->num_target_queries = 0;
return next_state(iq, INIT_REQUEST_STATE);
}
}
if(forged_response != NULL) {
qstate->ext_state[id] = module_finished;
qstate->return_rcode = LDNS_RCODE_NOERROR;
@ -3082,7 +3180,8 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
/* DNAME to a subdomain loop; do not recurse */
type = RESPONSE_TYPE_ANSWER;
}
} else if(type == RESPONSE_TYPE_CNAME &&
}
if(type == RESPONSE_TYPE_CNAME &&
iq->qchase.qtype == LDNS_RR_TYPE_CNAME &&
iq->minimisation_state == MINIMISE_STATE &&
query_dname_compare(iq->qchase.qname, iq->qinfo_out.qname) == 0) {
@ -3193,6 +3292,7 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
}
return final_state(iq);
} else if(type == RESPONSE_TYPE_REFERRAL) {
struct delegpt* old_dp = NULL;
/* REFERRAL type responses get a reset of the
* delegation point, and back to the QUERYTARGETS_STATE. */
verbose(VERB_DETAIL, "query response was REFERRAL");
@ -3244,6 +3344,8 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
/* Reset the event state, setting the current delegation
* point to the referral. */
iq->deleg_msg = iq->response;
/* Keep current delegation point for label comparison */
old_dp = iq->dp;
iq->dp = delegpt_from_message(iq->response, qstate->region);
if (qstate->env->cfg->qname_minimisation)
iq->minimisation_state = INIT_MINIMISE_STATE;
@ -3251,6 +3353,20 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
errinf(qstate, "malloc failure, for delegation point");
return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
}
if(old_dp->namelabs + 1 < iq->dp->namelabs) {
/* We got a grandchild delegation (more than one label
* difference) than expected. Check for in-between
* delegations in the cache and remove them.
* They could prove problematic when they expire
* and rrset_expired_above() encounters them during
* delegation cache lookups. */
uint8_t* qname = iq->dp->name;
size_t qnamelen = iq->dp->namelen;
rrset_cache_remove_above(qstate->env->rrset_cache,
&qname, &qnamelen, LDNS_RR_TYPE_NS,
iq->qchase.qclass, *qstate->env->now,
old_dp->name, old_dp->namelen);
}
if(!cache_fill_missing(qstate->env, iq->qchase.qclass,
qstate->region, iq->dp)) {
errinf(qstate, "malloc failure, copy extra info into delegation point");
@ -3341,10 +3457,13 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
/* apply rpz qname triggers after cname */
struct dns_msg* forged_response =
rpz_callback_from_iterator_cname(qstate, iq);
int count = 0;
while(forged_response && reply_find_rrset_section_an(
forged_response->rep, iq->qchase.qname,
iq->qchase.qname_len, LDNS_RR_TYPE_CNAME,
iq->qchase.qclass)) {
iq->qchase.qclass) &&
iq->qchase.qtype != LDNS_RR_TYPE_CNAME &&
count++ < ie->max_query_restarts) {
/* another cname to follow */
if(!handle_cname_response(qstate, iq, forged_response,
&sname, &snamelen)) {
@ -3926,17 +4045,9 @@ processFinished(struct module_qstate* qstate, struct iter_qstate* iq,
!qstate->env->cfg->val_log_squelch) {
char* err_str = errinf_to_str_misc(qstate);
if(err_str) {
size_t err_str_len = strlen(err_str);
verbose(VERB_ALGO, "iterator EDE: %s", err_str);
/* allocate space and store the error
* string */
iq->response->rep->reason_bogus_str = regional_alloc(
qstate->region,
sizeof(char) * (err_str_len+1));
memcpy(iq->response->rep->reason_bogus_str,
err_str, err_str_len+1);
iq->response->rep->reason_bogus_str = err_str;
}
free(err_str);
}
/* we have finished processing this query */

View file

@ -53,6 +53,8 @@
#include "util/storage/slabhash.h"
#include "util/edns.h"
#include "sldns/sbuffer.h"
#include "iterator/iter_fwd.h"
#include "iterator/iter_hints.h"
int
context_finalize(struct ub_ctx* ctx)
@ -85,6 +87,12 @@ context_finalize(struct ub_ctx* ctx)
if(!auth_zones_apply_cfg(ctx->env->auth_zones, cfg, 1, &is_rpz,
ctx->env, &ctx->mods))
return UB_INITFAIL;
if(!(ctx->env->fwds = forwards_create()) ||
!forwards_apply_cfg(ctx->env->fwds, cfg))
return UB_INITFAIL;
if(!(ctx->env->hints = hints_create()) ||
!hints_apply_cfg(ctx->env->hints, cfg))
return UB_INITFAIL;
if(!edns_strings_apply_cfg(ctx->env->edns_strings, cfg))
return UB_INITFAIL;
if(!slabhash_is_size(ctx->env->msg_cache, cfg->msg_cache_size,

View file

@ -66,6 +66,8 @@
#include "services/authzone.h"
#include "services/listen_dnsport.h"
#include "sldns/sbuffer.h"
#include "iterator/iter_fwd.h"
#include "iterator/iter_hints.h"
#ifdef HAVE_PTHREAD
#include <signal.h>
#endif
@ -171,6 +173,7 @@ static struct ub_ctx* ub_ctx_create_nopipe(void)
ctx->env->worker = NULL;
ctx->env->need_to_validate = 0;
modstack_init(&ctx->mods);
ctx->env->modstack = &ctx->mods;
rbtree_init(&ctx->queries, &context_query_cmp);
return ctx;
}
@ -379,6 +382,8 @@ ub_ctx_delete(struct ub_ctx* ctx)
config_delete(ctx->env->cfg);
edns_known_options_delete(ctx->env);
edns_strings_delete(ctx->env->edns_strings);
forwards_delete(ctx->env->fwds);
hints_delete(ctx->env->hints);
auth_zones_delete(ctx->env->auth_zones);
free(ctx->env);
}

View file

@ -70,8 +70,6 @@
#include "util/data/msgreply.h"
#include "util/data/msgencode.h"
#include "util/tube.h"
#include "iterator/iter_fwd.h"
#include "iterator/iter_hints.h"
#include "sldns/sbuffer.h"
#include "sldns/str2wire.h"
#ifdef USE_DNSTAP
@ -100,8 +98,6 @@ libworker_delete_env(struct libworker* w)
!w->is_bg || w->is_bg_thread);
sldns_buffer_free(w->env->scratch_buffer);
regional_destroy(w->env->scratch);
forwards_delete(w->env->fwds);
hints_delete(w->env->hints);
ub_randfree(w->env->rnd);
free(w->env);
}
@ -159,30 +155,19 @@ libworker_setup(struct ub_ctx* ctx, int is_bg, struct ub_event_base* eb)
}
w->env->scratch = regional_create_custom(cfg->msg_buffer_size);
w->env->scratch_buffer = sldns_buffer_new(cfg->msg_buffer_size);
w->env->fwds = forwards_create();
if(w->env->fwds && !forwards_apply_cfg(w->env->fwds, cfg)) {
forwards_delete(w->env->fwds);
w->env->fwds = NULL;
}
w->env->hints = hints_create();
if(w->env->hints && !hints_apply_cfg(w->env->hints, cfg)) {
hints_delete(w->env->hints);
w->env->hints = NULL;
}
#ifdef HAVE_SSL
w->sslctx = connect_sslctx_create(NULL, NULL,
cfg->tls_cert_bundle, cfg->tls_win_cert);
if(!w->sslctx) {
/* to make the setup fail after unlock */
hints_delete(w->env->hints);
w->env->hints = NULL;
sldns_buffer_free(w->env->scratch_buffer);
w->env->scratch_buffer = NULL;
}
#endif
if(!w->is_bg || w->is_bg_thread) {
lock_basic_unlock(&ctx->cfglock);
}
if(!w->env->scratch || !w->env->scratch_buffer || !w->env->fwds ||
!w->env->hints) {
if(!w->env->scratch || !w->env->scratch_buffer) {
libworker_delete(w);
return NULL;
}

View file

@ -1416,7 +1416,7 @@ struct delegpt* dns_cache_find_delegation(struct module_env* env,
int iter_dp_is_useless(struct query_info* qinfo, uint16_t qflags,
struct delegpt* dp, int supports_ipv4, int supports_ipv6, int use_nat64);
struct iter_hints_stub* hints_lookup_stub(struct iter_hints* hints,
uint8_t* qname, uint16_t qclass, struct delegpt* dp);
uint8_t* qname, uint16_t qclass, struct delegpt* dp, int nolock);
/* Custom function to perform logic similar to the one in daemon/cachedump.c */
struct delegpt* find_delegation(struct module_qstate* qstate, char *nm, size_t nmlen);
@ -1433,6 +1433,7 @@ struct delegpt* find_delegation(struct module_qstate* qstate, char *nm, size_t n
struct query_info qinfo;
struct iter_hints_stub* stub;
uint32_t timenow = *qstate->env->now;
int nolock = 0;
regional_free_all(region);
qinfo.qname = (uint8_t*)nm;
@ -1455,9 +1456,12 @@ struct delegpt* find_delegation(struct module_qstate* qstate, char *nm, size_t n
dname_str((uint8_t*)nm, b);
continue;
}
stub = hints_lookup_stub(qstate->env->hints, qinfo.qname, qinfo.qclass, dp);
stub = hints_lookup_stub(qstate->env->hints, qinfo.qname,
qinfo.qclass, dp, nolock);
if (stub) {
return stub->dp;
struct delegpt* stubdp = delegpt_copy(stub->dp, region);
lock_rw_unlock(&qstate->env->hints->lock);
return stubdp;
} else {
return dp;
}

View file

@ -356,11 +356,11 @@ int pythonmod_init(struct module_env* env, int id)
return 0;
}
#endif
Py_NoSiteFlag = 1;
#if PY_MAJOR_VERSION >= 3
PyImport_AppendInittab(SWIG_name, (void*)SWIG_init);
#endif
#if PY_VERSION_HEX < 0x03080000
Py_NoSiteFlag = 1;
Py_Initialize();
#else
PyConfig_InitPythonConfig(&config);

View file

@ -2152,6 +2152,16 @@ auth_zones_cfg(struct auth_zones* az, struct config_auth* c)
if(az->rpz_first)
az->rpz_first->rpz_az_prev = z;
az->rpz_first = z;
} else if(c->isrpz && z->rpz) {
if(!rpz_config(z->rpz, c)) {
log_err("Could not change rpz config");
if(x) {
lock_basic_unlock(&x->lock);
}
lock_rw_unlock(&z->lock);
lock_rw_unlock(&az->rpz_lock);
return 0;
}
}
if(c->isrpz) {
lock_rw_unlock(&az->rpz_lock);

52
services/cache/dns.c vendored
View file

@ -193,46 +193,6 @@ dns_cache_store_msg(struct module_env* env, struct query_info* qinfo,
slabhash_insert(env->msg_cache, hash, &e->entry, rep, env->alloc);
}
/** see if an rrset is expired above the qname, return upper qname. */
static int
rrset_expired_above(struct module_env* env, uint8_t** qname, size_t* qnamelen,
uint16_t searchtype, uint16_t qclass, time_t now, uint8_t* expiretop,
size_t expiretoplen)
{
struct ub_packed_rrset_key *rrset;
uint8_t lablen;
while(*qnamelen > 0) {
/* look one label higher */
lablen = **qname;
*qname += lablen + 1;
*qnamelen -= lablen + 1;
if(*qnamelen <= 0)
break;
/* looks up with a time of 0, to see expired entries */
if((rrset = rrset_cache_lookup(env->rrset_cache, *qname,
*qnamelen, searchtype, qclass, 0, 0, 0))) {
struct packed_rrset_data* data =
(struct packed_rrset_data*)rrset->entry.data;
if(now > data->ttl) {
/* it is expired, this is not wanted */
lock_rw_unlock(&rrset->entry.lock);
log_nametypeclass(VERB_ALGO, "this rrset is expired", *qname, searchtype, qclass);
return 1;
}
/* it is not expired, continue looking */
lock_rw_unlock(&rrset->entry.lock);
}
/* do not look above the expiretop. */
if(expiretop && *qnamelen == expiretoplen &&
query_dname_compare(*qname, expiretop)==0)
break;
}
return 0;
}
/** find closest NS or DNAME and returns the rrset (locked) */
static struct ub_packed_rrset_key*
find_closest_of_type(struct module_env* env, uint8_t* qname, size_t qnamelen,
@ -266,12 +226,12 @@ find_closest_of_type(struct module_env* env, uint8_t* qname, size_t qnamelen,
/* check for expiry, but we have to let go of the rrset
* for the lock ordering */
lock_rw_unlock(&rrset->entry.lock);
/* the expired_above function always takes off one
* label (if qnamelen>0) and returns the final qname
* where it searched, so we can continue from there
* turning the O N*N search into O N. */
if(!rrset_expired_above(env, &qname, &qnamelen,
searchtype, qclass, now, expiretop,
/* the rrset_cache_expired_above function always takes
* off one label (if qnamelen>0) and returns the final
* qname where it searched, so we can continue from
* there turning the O N*N search into O N. */
if(!rrset_cache_expired_above(env->rrset_cache, &qname,
&qnamelen, searchtype, qclass, now, expiretop,
expiretoplen)) {
/* we want to return rrset, but it may be
* gone from cache, if so, just loop like

170
services/cache/infra.c vendored
View file

@ -234,6 +234,81 @@ setup_domain_limits(struct infra_cache* infra, struct config_file* cfg)
return 1;
}
/** find or create element in wait limit netblock tree */
static struct wait_limit_netblock_info*
wait_limit_netblock_findcreate(struct infra_cache* infra, char* str,
int cookie)
{
rbtree_type* tree;
struct sockaddr_storage addr;
int net;
socklen_t addrlen;
struct wait_limit_netblock_info* d;
if(!netblockstrtoaddr(str, 0, &addr, &addrlen, &net)) {
log_err("cannot parse wait limit netblock '%s'", str);
return 0;
}
/* can we find it? */
if(cookie)
tree = &infra->wait_limits_cookie_netblock;
else
tree = &infra->wait_limits_netblock;
d = (struct wait_limit_netblock_info*)addr_tree_find(tree, &addr,
addrlen, net);
if(d)
return d;
/* create it */
d = (struct wait_limit_netblock_info*)calloc(1, sizeof(*d));
if(!d)
return NULL;
d->limit = -1;
if(!addr_tree_insert(tree, &d->node, &addr, addrlen, net)) {
log_err("duplicate element in domainlimit tree");
free(d);
return NULL;
}
return d;
}
/** insert wait limit information into lookup tree */
static int
infra_wait_limit_netblock_insert(struct infra_cache* infra,
struct config_file* cfg)
{
struct config_str2list* p;
struct wait_limit_netblock_info* d;
for(p = cfg->wait_limit_netblock; p; p = p->next) {
d = wait_limit_netblock_findcreate(infra, p->str, 0);
if(!d)
return 0;
d->limit = atoi(p->str2);
}
for(p = cfg->wait_limit_cookie_netblock; p; p = p->next) {
d = wait_limit_netblock_findcreate(infra, p->str, 1);
if(!d)
return 0;
d->limit = atoi(p->str2);
}
return 1;
}
/** setup wait limits tree (0 on failure) */
static int
setup_wait_limits(struct infra_cache* infra, struct config_file* cfg)
{
addr_tree_init(&infra->wait_limits_netblock);
addr_tree_init(&infra->wait_limits_cookie_netblock);
if(!infra_wait_limit_netblock_insert(infra, cfg))
return 0;
addr_tree_init_parents(&infra->wait_limits_netblock);
addr_tree_init_parents(&infra->wait_limits_cookie_netblock);
return 1;
}
struct infra_cache*
infra_create(struct config_file* cfg)
{
@ -267,6 +342,10 @@ infra_create(struct config_file* cfg)
infra_delete(infra);
return NULL;
}
if(!setup_wait_limits(infra, cfg)) {
infra_delete(infra);
return NULL;
}
infra_ip_ratelimit = cfg->ip_ratelimit;
infra->client_ip_rates = slabhash_create(cfg->ip_ratelimit_slabs,
INFRA_HOST_STARTSIZE, cfg->ip_ratelimit_size, &ip_rate_sizefunc,
@ -287,6 +366,12 @@ static void domain_limit_free(rbnode_type* n, void* ATTR_UNUSED(arg))
}
}
/** delete wait_limit_netblock_info entries */
static void wait_limit_netblock_del(rbnode_type* n, void* ATTR_UNUSED(arg))
{
free(n);
}
void
infra_delete(struct infra_cache* infra)
{
@ -296,6 +381,10 @@ infra_delete(struct infra_cache* infra)
slabhash_delete(infra->domain_rates);
traverse_postorder(&infra->domain_limits, domain_limit_free, NULL);
slabhash_delete(infra->client_ip_rates);
traverse_postorder(&infra->wait_limits_netblock,
wait_limit_netblock_del, NULL);
traverse_postorder(&infra->wait_limits_cookie_netblock,
wait_limit_netblock_del, NULL);
free(infra);
}
@ -880,7 +969,8 @@ static void infra_create_ratedata(struct infra_cache* infra,
/** create rate data item for ip address */
static void infra_ip_create_ratedata(struct infra_cache* infra,
struct sockaddr_storage* addr, socklen_t addrlen, time_t timenow)
struct sockaddr_storage* addr, socklen_t addrlen, time_t timenow,
int mesh_wait)
{
hashvalue_type h = hash_addr(addr, addrlen, 0);
struct ip_rate_key* k = (struct ip_rate_key*)calloc(1, sizeof(*k));
@ -898,6 +988,7 @@ static void infra_ip_create_ratedata(struct infra_cache* infra,
k->entry.data = d;
d->qps[0] = 1;
d->timestamp[0] = timenow;
d->mesh_wait = mesh_wait;
slabhash_insert(infra->client_ip_rates, h, &k->entry, d, NULL);
}
@ -1121,6 +1212,81 @@ int infra_ip_ratelimit_inc(struct infra_cache* infra,
}
/* create */
infra_ip_create_ratedata(infra, addr, addrlen, timenow);
infra_ip_create_ratedata(infra, addr, addrlen, timenow, 0);
return 1;
}
int infra_wait_limit_allowed(struct infra_cache* infra, struct comm_reply* rep,
int cookie_valid, struct config_file* cfg)
{
struct lruhash_entry* entry;
if(cfg->wait_limit == 0)
return 1;
entry = infra_find_ip_ratedata(infra, &rep->client_addr,
rep->client_addrlen, 0);
if(entry) {
rbtree_type* tree;
struct wait_limit_netblock_info* w;
struct rate_data* d = (struct rate_data*)entry->data;
int mesh_wait = d->mesh_wait;
lock_rw_unlock(&entry->lock);
/* have the wait amount, check how much is allowed */
if(cookie_valid)
tree = &infra->wait_limits_cookie_netblock;
else tree = &infra->wait_limits_netblock;
w = (struct wait_limit_netblock_info*)addr_tree_lookup(tree,
&rep->client_addr, rep->client_addrlen);
if(w) {
if(w->limit != -1 && mesh_wait > w->limit)
return 0;
} else {
/* if there is no IP netblock specific information,
* use the configured value. */
if(mesh_wait > (cookie_valid?cfg->wait_limit_cookie:
cfg->wait_limit))
return 0;
}
}
return 1;
}
void infra_wait_limit_inc(struct infra_cache* infra, struct comm_reply* rep,
time_t timenow, struct config_file* cfg)
{
struct lruhash_entry* entry;
if(cfg->wait_limit == 0)
return;
/* Find it */
entry = infra_find_ip_ratedata(infra, &rep->client_addr,
rep->client_addrlen, 1);
if(entry) {
struct rate_data* d = (struct rate_data*)entry->data;
d->mesh_wait++;
lock_rw_unlock(&entry->lock);
return;
}
/* Create it */
infra_ip_create_ratedata(infra, &rep->client_addr,
rep->client_addrlen, timenow, 1);
}
void infra_wait_limit_dec(struct infra_cache* infra, struct comm_reply* rep,
struct config_file* cfg)
{
struct lruhash_entry* entry;
if(cfg->wait_limit == 0)
return;
entry = infra_find_ip_ratedata(infra, &rep->client_addr,
rep->client_addrlen, 1);
if(entry) {
struct rate_data* d = (struct rate_data*)entry->data;
if(d->mesh_wait > 0)
d->mesh_wait--;
lock_rw_unlock(&entry->lock);
}
}

View file

@ -122,6 +122,10 @@ struct infra_cache {
rbtree_type domain_limits;
/** hash table with query rates per client ip: ip_rate_key, ip_rate_data */
struct slabhash* client_ip_rates;
/** tree of addr_tree_node, with wait_limit_netblock_info information */
rbtree_type wait_limits_netblock;
/** tree of addr_tree_node, with wait_limit_netblock_info information */
rbtree_type wait_limits_cookie_netblock;
};
/** ratelimit, unless overridden by domain_limits, 0 is off */
@ -184,10 +188,22 @@ struct rate_data {
/** what the timestamp is of the qps array members, counter is
* valid for that timestamp. Usually now and now-1. */
time_t timestamp[RATE_WINDOW];
/** the number of queries waiting in the mesh */
int mesh_wait;
};
#define ip_rate_data rate_data
/**
* Data to store the configuration per netblock for the wait limit
*/
struct wait_limit_netblock_info {
/** The addr tree node, this must be first. */
struct addr_tree_node node;
/** the limit on the amount */
int limit;
};
/** infra host cache default hash lookup size */
#define INFRA_HOST_STARTSIZE 32
/** bytes per zonename reserved in the hostcache, dnamelen(zonename.com.) */
@ -474,4 +490,16 @@ void ip_rate_delkeyfunc(void* d, void* arg);
/* delete data */
#define ip_rate_deldatafunc rate_deldatafunc
/** See if the IP address can have another reply in the wait limit */
int infra_wait_limit_allowed(struct infra_cache* infra, struct comm_reply* rep,
int cookie_valid, struct config_file* cfg);
/** Increment number of waiting replies for IP */
void infra_wait_limit_inc(struct infra_cache* infra, struct comm_reply* rep,
time_t timenow, struct config_file* cfg);
/** Decrement number of waiting replies for IP */
void infra_wait_limit_dec(struct infra_cache* infra, struct comm_reply* rep,
struct config_file* cfg);
#endif /* SERVICES_CACHE_INFRA_H */

View file

@ -46,6 +46,7 @@
#include "util/data/packed_rrset.h"
#include "util/data/msgreply.h"
#include "util/data/msgparse.h"
#include "util/data/dname.h"
#include "util/regional.h"
#include "util/alloc.h"
#include "util/net_help.h"
@ -127,6 +128,9 @@ need_to_update_rrset(void* nd, void* cd, time_t timenow, int equal, int ns)
{
struct packed_rrset_data* newd = (struct packed_rrset_data*)nd;
struct packed_rrset_data* cached = (struct packed_rrset_data*)cd;
/* o if new data is expired, current data is better */
if( newd->ttl < timenow && cached->ttl >= timenow)
return 0;
/* o store if rrset has been validated
* everything better than bogus data
* secure is preferred */
@ -440,6 +444,89 @@ rrset_check_sec_status(struct rrset_cache* r,
lock_rw_unlock(&e->lock);
}
void
rrset_cache_remove_above(struct rrset_cache* r, uint8_t** qname, size_t*
qnamelen, uint16_t searchtype, uint16_t qclass, time_t now, uint8_t*
qnametop, size_t qnametoplen)
{
struct ub_packed_rrset_key *rrset;
uint8_t lablen;
while(*qnamelen > 0) {
/* look one label higher */
lablen = **qname;
*qname += lablen + 1;
*qnamelen -= lablen + 1;
if(*qnamelen <= 0)
return;
/* stop at qnametop */
if(qnametop && *qnamelen == qnametoplen &&
query_dname_compare(*qname, qnametop)==0)
return;
if(verbosity >= VERB_ALGO) {
/* looks up with a time of 0, to see expired entries */
if((rrset = rrset_cache_lookup(r, *qname,
*qnamelen, searchtype, qclass, 0, 0, 0))) {
struct packed_rrset_data* data =
(struct packed_rrset_data*)rrset->entry.data;
int expired = (now > data->ttl);
lock_rw_unlock(&rrset->entry.lock);
if(expired)
log_nametypeclass(verbosity, "this "
"(grand)parent rrset will be "
"removed (expired)",
*qname, searchtype, qclass);
else log_nametypeclass(verbosity, "this "
"(grand)parent rrset will be "
"removed",
*qname, searchtype, qclass);
}
}
rrset_cache_remove(r, *qname, *qnamelen, searchtype, qclass, 0);
}
}
int
rrset_cache_expired_above(struct rrset_cache* r, uint8_t** qname, size_t*
qnamelen, uint16_t searchtype, uint16_t qclass, time_t now, uint8_t*
qnametop, size_t qnametoplen)
{
struct ub_packed_rrset_key *rrset;
uint8_t lablen;
while(*qnamelen > 0) {
/* look one label higher */
lablen = **qname;
*qname += lablen + 1;
*qnamelen -= lablen + 1;
if(*qnamelen <= 0)
break;
/* looks up with a time of 0, to see expired entries */
if((rrset = rrset_cache_lookup(r, *qname,
*qnamelen, searchtype, qclass, 0, 0, 0))) {
struct packed_rrset_data* data =
(struct packed_rrset_data*)rrset->entry.data;
if(now > data->ttl) {
/* it is expired, this is not wanted */
lock_rw_unlock(&rrset->entry.lock);
log_nametypeclass(VERB_ALGO, "this rrset is expired", *qname, searchtype, qclass);
return 1;
}
/* it is not expired, continue looking */
lock_rw_unlock(&rrset->entry.lock);
}
/* do not look above the qnametop. */
if(qnametop && *qnamelen == qnametoplen &&
query_dname_compare(*qname, qnametop)==0)
break;
}
return 0;
}
void rrset_cache_remove(struct rrset_cache* r, uint8_t* nm, size_t nmlen,
uint16_t type, uint16_t dclass, uint32_t flags)
{

View file

@ -231,6 +231,37 @@ void rrset_update_sec_status(struct rrset_cache* r,
void rrset_check_sec_status(struct rrset_cache* r,
struct ub_packed_rrset_key* rrset, time_t now);
/**
* Removes rrsets above the qname, returns upper qname.
* @param r: the rrset cache.
* @param qname: the start qname, also used as the output.
* @param qnamelen: length of qname, updated when it returns.
* @param searchtype: qtype to search for.
* @param qclass: qclass to search for.
* @param now: current time.
* @param qnametop: the top qname to stop removal (it is not removed).
* @param qnametoplen: length of qnametop.
*/
void rrset_cache_remove_above(struct rrset_cache* r, uint8_t** qname,
size_t* qnamelen, uint16_t searchtype, uint16_t qclass, time_t now,
uint8_t* qnametop, size_t qnametoplen);
/**
* Sees if an rrset is expired above the qname, returns upper qname.
* @param r: the rrset cache.
* @param qname: the start qname, also used as the output.
* @param qnamelen: length of qname, updated when it returns.
* @param searchtype: qtype to search for.
* @param qclass: qclass to search for.
* @param now: current time.
* @param qnametop: the top qname, don't look farther than that.
* @param qnametoplen: length of qnametop.
* @return true if there is an expired rrset above, false otherwise.
*/
int rrset_cache_expired_above(struct rrset_cache* r, uint8_t** qname,
size_t* qnamelen, uint16_t searchtype, uint16_t qclass, time_t now,
uint8_t* qnametop, size_t qnametoplen);
/**
* Remove an rrset from the cache, by name and type and flags
* @param r: rrset cache

View file

@ -140,9 +140,11 @@ void
verbose_print_unbound_socket(struct unbound_socket* ub_sock)
{
if(verbosity >= VERB_ALGO) {
char buf[256];
log_info("listing of unbound_socket structure:");
verbose_print_addr(ub_sock->addr);
log_info("s is: %d, fam is: %s, acl: %s", ub_sock->s,
addr_to_str((void*)ub_sock->addr, ub_sock->addrlen, buf,
sizeof(buf));
log_info("%s s is: %d, fam is: %s, acl: %s", buf, ub_sock->s,
ub_sock->fam == AF_INET?"AF_INET":"AF_INET6",
ub_sock->acl?"yes":"no");
}
@ -610,7 +612,9 @@ create_udp_sock(int family, int socktype, struct sockaddr* addr,
# elif defined(IP_DONTFRAG) && !defined(__APPLE__)
/* the IP_DONTFRAG option if defined in the 11.0 OSX headers,
* but does not work on that version, so we exclude it */
int off = 0;
/* a nonzero value disables fragmentation, according to
* docs.oracle.com for ip(4). */
int off = 1;
if (setsockopt(s, IPPROTO_IP, IP_DONTFRAG,
&off, (socklen_t)sizeof(off)) < 0) {
log_err("setsockopt(..., IP_DONTFRAG, ...) failed: %s",
@ -1047,7 +1051,22 @@ make_sock(int stype, const char* ifname, const char* port,
}
}
ub_sock->addr = res;
if(!res->ai_addr) {
log_err("getaddrinfo returned no address");
freeaddrinfo(res);
sock_close(s);
return -1;
}
ub_sock->addr = memdup(res->ai_addr, res->ai_addrlen);
ub_sock->addrlen = res->ai_addrlen;
if(!ub_sock->addr) {
log_err("out of memory: allocate listening address");
freeaddrinfo(res);
sock_close(s);
return -1;
}
freeaddrinfo(res);
ub_sock->s = s;
ub_sock->fam = hints->ai_family;
ub_sock->acl = NULL;
@ -1277,8 +1296,7 @@ ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp,
if((s = make_sock_port(SOCK_DGRAM, ifname, port, hints, 1,
&noip6, rcv, snd, reuseport, transparent,
tcp_mss, nodelay, freebind, use_systemd, dscp, ub_sock)) == -1) {
if(ub_sock->addr)
freeaddrinfo(ub_sock->addr);
free(ub_sock->addr);
free(ub_sock);
if(noip6) {
log_warn("IPv6 protocol not available");
@ -1289,8 +1307,7 @@ ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp,
/* getting source addr packet info is highly non-portable */
if(!set_recvpktinfo(s, hints->ai_family)) {
sock_close(s);
if(ub_sock->addr)
freeaddrinfo(ub_sock->addr);
free(ub_sock->addr);
free(ub_sock);
return 0;
}
@ -1301,8 +1318,7 @@ ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp,
?listen_type_udpancil_dnscrypt:listen_type_udpancil,
is_pp2, ub_sock)) {
sock_close(s);
if(ub_sock->addr)
freeaddrinfo(ub_sock->addr);
free(ub_sock->addr);
free(ub_sock);
return 0;
}
@ -1314,8 +1330,7 @@ ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp,
if((s = make_sock_port(SOCK_DGRAM, ifname, port, hints, 1,
&noip6, rcv, snd, reuseport, transparent,
tcp_mss, nodelay, freebind, use_systemd, dscp, ub_sock)) == -1) {
if(ub_sock->addr)
freeaddrinfo(ub_sock->addr);
free(ub_sock->addr);
free(ub_sock);
if(noip6) {
log_warn("IPv6 protocol not available");
@ -1332,8 +1347,7 @@ ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp,
listen_type_udpancil:listen_type_udp),
is_pp2, ub_sock)) {
sock_close(s);
if(ub_sock->addr)
freeaddrinfo(ub_sock->addr);
free(ub_sock->addr);
free(ub_sock);
return 0;
}
@ -1356,8 +1370,7 @@ ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp,
if((s = make_sock_port(SOCK_STREAM, ifname, port, hints, 1,
&noip6, 0, 0, reuseport, transparent, tcp_mss, nodelay,
freebind, use_systemd, dscp, ub_sock)) == -1) {
if(ub_sock->addr)
freeaddrinfo(ub_sock->addr);
free(ub_sock->addr);
free(ub_sock);
if(noip6) {
/*log_warn("IPv6 protocol not available");*/
@ -1369,8 +1382,7 @@ ports_create_if(const char* ifname, int do_auto, int do_udp, int do_tcp,
verbose(VERB_ALGO, "setup TCP for SSL service");
if(!port_insert(list, s, port_type, is_pp2, ub_sock)) {
sock_close(s);
if(ub_sock->addr)
freeaddrinfo(ub_sock->addr);
free(ub_sock->addr);
free(ub_sock);
return 0;
}
@ -1952,8 +1964,7 @@ void listening_ports_free(struct listen_port* list)
}
/* rc_ports don't have ub_socket */
if(list->socket) {
if(list->socket->addr)
freeaddrinfo(list->socket->addr);
free(list->socket->addr);
free(list->socket);
}
free(list);

View file

@ -107,11 +107,13 @@ enum listen_type {
* socket properties (just like NSD nsd_socket structure definition)
*/
struct unbound_socket {
/** socket-address structure */
struct addrinfo* addr;
/** the address of the socket */
struct sockaddr* addr;
/** length of the address */
socklen_t addrlen;
/** socket descriptor returned by socket() syscall */
int s;
/** address family (AF_INET/IF_INET6) */
/** address family (AF_INET/AF_INET6) */
int fam;
/** ACL on the socket (listening interface) */
struct acl_addr* acl;

View file

@ -330,14 +330,16 @@ get_rr_nameclass(const char* str, uint8_t** nm, uint16_t* dclass,
static struct local_rrset*
local_data_find_type(struct local_data* data, uint16_t type, int alias_ok)
{
struct local_rrset* p;
struct local_rrset* p, *cname = NULL;
type = htons(type);
for(p = data->rrsets; p; p = p->next) {
if(p->rrset->rk.type == type)
return p;
if(alias_ok && p->rrset->rk.type == htons(LDNS_RR_TYPE_CNAME))
return p;
cname = p;
}
if(alias_ok)
return cname;
return NULL;
}

View file

@ -47,6 +47,7 @@
#include "services/outbound_list.h"
#include "services/cache/dns.h"
#include "services/cache/rrset.h"
#include "services/cache/infra.h"
#include "util/log.h"
#include "util/net_help.h"
#include "util/module.h"
@ -385,7 +386,7 @@ mesh_serve_expired_init(struct mesh_state* mstate, int timeout)
&mesh_serve_expired_lookup;
/* In case this timer already popped, start it again */
if(!mstate->s.serve_expired_data->timer) {
if(!mstate->s.serve_expired_data->timer && timeout != -1) {
mstate->s.serve_expired_data->timer = comm_timer_create(
mstate->s.env->worker_base, mesh_serve_expired_callback, mstate);
if(!mstate->s.serve_expired_data->timer)
@ -415,6 +416,14 @@ void mesh_new_client(struct mesh_area* mesh, struct query_info* qinfo,
if(rep->c->tcp_req_info) {
r_buffer = rep->c->tcp_req_info->spool_buffer;
}
if(!infra_wait_limit_allowed(mesh->env->infra_cache, rep,
edns->cookie_valid, mesh->env->cfg)) {
verbose(VERB_ALGO, "Too many queries waiting from the IP. "
"dropping incoming query.");
comm_point_drop_reply(rep);
mesh->stats_dropped++;
return;
}
if(!unique)
s = mesh_area_find(mesh, cinfo, qinfo, qflags&(BIT_RD|BIT_CD), 0, 0);
/* does this create a new reply state? */
@ -511,6 +520,19 @@ void mesh_new_client(struct mesh_area* mesh, struct query_info* qinfo,
log_err("mesh_new_client: out of memory initializing serve expired");
goto servfail_mem;
}
#ifdef USE_CACHEDB
if(!timeout && mesh->env->cfg->serve_expired &&
!mesh->env->cfg->serve_expired_client_timeout &&
(mesh->env->cachedb_enabled &&
mesh->env->cfg->cachedb_check_when_serve_expired)) {
if(!mesh_serve_expired_init(s, -1)) {
log_err("mesh_new_client: out of memory initializing serve expired");
goto servfail_mem;
}
}
#endif
infra_wait_limit_inc(mesh->env->infra_cache, rep, *mesh->env->now,
mesh->env->cfg);
/* update statistics */
if(was_detached) {
log_assert(mesh->num_detached_states > 0);
@ -616,6 +638,18 @@ mesh_new_callback(struct mesh_area* mesh, struct query_info* qinfo,
mesh_state_delete(&s->s);
return 0;
}
#ifdef USE_CACHEDB
if(!timeout && mesh->env->cfg->serve_expired &&
!mesh->env->cfg->serve_expired_client_timeout &&
(mesh->env->cachedb_enabled &&
mesh->env->cfg->cachedb_check_when_serve_expired)) {
if(!mesh_serve_expired_init(s, -1)) {
if(added)
mesh_state_delete(&s->s);
return 0;
}
}
#endif
/* update statistics */
if(was_detached) {
log_assert(mesh->num_detached_states > 0);
@ -930,6 +964,8 @@ mesh_state_cleanup(struct mesh_state* mstate)
* takes no time and also it does not do the mesh accounting */
mstate->reply_list = NULL;
for(; rep; rep=rep->next) {
infra_wait_limit_dec(mesh->env->infra_cache,
&rep->query_reply, mesh->env->cfg);
comm_point_drop_reply(&rep->query_reply);
log_assert(mesh->num_reply_addrs > 0);
mesh->num_reply_addrs--;
@ -1179,7 +1215,7 @@ mesh_do_callback(struct mesh_state* m, int rcode, struct reply_info* rep,
rcode = LDNS_RCODE_SERVFAIL;
if(!rcode && rep && (rep->security == sec_status_bogus ||
rep->security == sec_status_secure_sentinel_fail)) {
if(!(reason = errinf_to_str_bogus(&m->s)))
if(!(reason = errinf_to_str_bogus(&m->s, NULL)))
rcode = LDNS_RCODE_SERVFAIL;
}
/* send the reply */
@ -1413,6 +1449,8 @@ mesh_send_reply(struct mesh_state* m, int rcode, struct reply_info* rep,
comm_point_send_reply(&r->query_reply);
m->reply_list = rlist;
}
infra_wait_limit_dec(m->s.env->infra_cache, &r->query_reply,
m->s.env->cfg);
/* account */
log_assert(m->s.env->mesh->num_reply_addrs > 0);
m->s.env->mesh->num_reply_addrs--;
@ -1436,7 +1474,7 @@ mesh_send_reply(struct mesh_state* m, int rcode, struct reply_info* rep,
log_reply_info(NO_VERBOSE, &m->s.qinfo,
&r->query_reply.client_addr,
r->query_reply.client_addrlen, duration, 0, r_buffer,
(m->s.env->cfg->log_destaddr?(void*)r->query_reply.c->socket->addr->ai_addr:NULL),
(m->s.env->cfg->log_destaddr?(void*)r->query_reply.c->socket->addr:NULL),
r->query_reply.c->type);
}
}
@ -1464,12 +1502,32 @@ void mesh_query_done(struct mesh_state* mstate)
&& mstate->s.env->cfg->log_servfail
&& !mstate->s.env->cfg->val_log_squelch) {
char* err = errinf_to_str_servfail(&mstate->s);
if(err)
log_err("%s", err);
free(err);
if(err) { log_err("%s", err); }
}
}
for(r = mstate->reply_list; r; r = r->next) {
struct timeval old;
timeval_subtract(&old, mstate->s.env->now_tv, &r->start_time);
if(mstate->s.env->cfg->discard_timeout != 0 &&
((int)old.tv_sec)*1000+((int)old.tv_usec)/1000 >
mstate->s.env->cfg->discard_timeout) {
/* Drop the reply, it is too old */
/* 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;
verbose(VERB_ALGO, "drop reply, it is older than discard-timeout");
infra_wait_limit_dec(mstate->s.env->infra_cache,
&r->query_reply, mstate->s.env->cfg);
mstate->reply_list = NULL;
comm_point_drop_reply(&r->query_reply);
mstate->reply_list = reply_list;
mstate->s.env->mesh->stats_dropped++;
continue;
}
i++;
tv = r->start_time;
@ -1493,6 +1551,8 @@ void mesh_query_done(struct mesh_state* mstate)
* 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;
infra_wait_limit_dec(mstate->s.env->infra_cache,
&r->query_reply, mstate->s.env->cfg);
mstate->reply_list = NULL;
comm_point_drop_reply(&r->query_reply);
mstate->reply_list = reply_list;
@ -2025,6 +2085,8 @@ void mesh_state_remove_reply(struct mesh_area* mesh, struct mesh_state* m,
/* delete it, but allocated in m region */
log_assert(mesh->num_reply_addrs > 0);
mesh->num_reply_addrs--;
infra_wait_limit_dec(mesh->env->infra_cache,
&n->query_reply, mesh->env->cfg);
/* prev = prev; */
n = n->next;
@ -2165,6 +2227,28 @@ mesh_serve_expired_callback(void* arg)
log_dns_msg("Serve expired lookup", &qstate->qinfo, msg->rep);
for(r = mstate->reply_list; r; r = r->next) {
struct timeval old;
timeval_subtract(&old, mstate->s.env->now_tv, &r->start_time);
if(mstate->s.env->cfg->discard_timeout != 0 &&
((int)old.tv_sec)*1000+((int)old.tv_usec)/1000 >
mstate->s.env->cfg->discard_timeout) {
/* Drop the reply, it is too old */
/* 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;
verbose(VERB_ALGO, "drop reply, it is older than discard-timeout");
infra_wait_limit_dec(mstate->s.env->infra_cache,
&r->query_reply, mstate->s.env->cfg);
mstate->reply_list = NULL;
comm_point_drop_reply(&r->query_reply);
mstate->reply_list = reply_list;
mstate->s.env->mesh->stats_dropped++;
continue;
}
i++;
tv = r->start_time;
@ -2192,6 +2276,8 @@ mesh_serve_expired_callback(void* arg)
r, r_buffer, prev, prev_buffer);
if(r->query_reply.c->tcp_req_info)
tcp_req_info_remove_mesh_state(r->query_reply.c->tcp_req_info, mstate);
infra_wait_limit_dec(mstate->s.env->infra_cache,
&r->query_reply, mstate->s.env->cfg);
prev = r;
prev_buffer = r_buffer;
}
@ -2238,6 +2324,14 @@ mesh_serve_expired_callback(void* arg)
}
}
void
mesh_respond_serve_expired(struct mesh_state* mstate)
{
if(!mstate->s.serve_expired_data)
mesh_serve_expired_init(mstate, -1);
mesh_serve_expired_callback(mstate);
}
int mesh_jostle_exceeded(struct mesh_area* mesh)
{
if(mesh->all.count < mesh->max_reply_states)

View file

@ -690,4 +690,10 @@ mesh_serve_expired_lookup(struct module_qstate* qstate,
*/
int mesh_jostle_exceeded(struct mesh_area* mesh);
/**
* Give the serve expired responses.
* @param mstate: mesh state for query that has serve_expired_data.
*/
void mesh_respond_serve_expired(struct mesh_state* mstate);
#endif /* SERVICES_MESH_H */

View file

@ -478,6 +478,67 @@ new_cname_override(struct regional* region, uint8_t* ct, size_t ctlen)
return rrset;
}
/** delete the cname override */
static void
delete_cname_override(struct rpz* r)
{
if(r->cname_override) {
/* The cname override is what is allocated in the region. */
regional_free_all(r->region);
r->cname_override = NULL;
}
}
/** Apply rpz config elements to the rpz structure, false on failure. */
static int
rpz_apply_cfg_elements(struct rpz* r, struct config_auth* p)
{
if(p->rpz_taglist && p->rpz_taglistlen) {
r->taglistlen = p->rpz_taglistlen;
r->taglist = memdup(p->rpz_taglist, r->taglistlen);
if(!r->taglist) {
log_err("malloc failure on RPZ taglist alloc");
return 0;
}
}
if(p->rpz_action_override) {
r->action_override = rpz_config_to_action(p->rpz_action_override);
}
else
r->action_override = RPZ_NO_OVERRIDE_ACTION;
if(r->action_override == RPZ_CNAME_OVERRIDE_ACTION) {
uint8_t nm[LDNS_MAX_DOMAINLEN+1];
size_t nmlen = sizeof(nm);
if(!p->rpz_cname) {
log_err("rpz: override with cname action found, but no "
"rpz-cname-override configured");
return 0;
}
if(sldns_str2wire_dname_buf(p->rpz_cname, nm, &nmlen) != 0) {
log_err("rpz: cannot parse cname override: %s",
p->rpz_cname);
return 0;
}
r->cname_override = new_cname_override(r->region, nm, nmlen);
if(!r->cname_override) {
return 0;
}
}
r->log = p->rpz_log;
r->signal_nxdomain_ra = p->rpz_signal_nxdomain_ra;
if(p->rpz_log_name) {
if(!(r->log_name = strdup(p->rpz_log_name))) {
log_err("malloc failure on RPZ log_name strdup");
return 0;
}
}
return 1;
}
struct rpz*
rpz_create(struct config_auth* p)
{
@ -513,42 +574,8 @@ rpz_create(struct config_auth* p)
goto err;
}
r->taglistlen = p->rpz_taglistlen;
r->taglist = memdup(p->rpz_taglist, r->taglistlen);
if(p->rpz_action_override) {
r->action_override = rpz_config_to_action(p->rpz_action_override);
}
else
r->action_override = RPZ_NO_OVERRIDE_ACTION;
if(r->action_override == RPZ_CNAME_OVERRIDE_ACTION) {
uint8_t nm[LDNS_MAX_DOMAINLEN+1];
size_t nmlen = sizeof(nm);
if(!p->rpz_cname) {
log_err("rpz: override with cname action found, but no "
"rpz-cname-override configured");
goto err;
}
if(sldns_str2wire_dname_buf(p->rpz_cname, nm, &nmlen) != 0) {
log_err("rpz: cannot parse cname override: %s",
p->rpz_cname);
goto err;
}
r->cname_override = new_cname_override(r->region, nm, nmlen);
if(!r->cname_override) {
goto err;
}
}
r->log = p->rpz_log;
r->signal_nxdomain_ra = p->rpz_signal_nxdomain_ra;
if(p->rpz_log_name) {
if(!(r->log_name = strdup(p->rpz_log_name))) {
log_err("malloc failure on RPZ log_name strdup");
goto err;
}
}
if(!rpz_apply_cfg_elements(r, p))
goto err;
return r;
err:
if(r) {
@ -571,6 +598,32 @@ rpz_create(struct config_auth* p)
return NULL;
}
int
rpz_config(struct rpz* r, struct config_auth* p)
{
/* If the zonefile changes, it is read later, after which
* rpz_clear and rpz_finish_config is called. */
/* free taglist, if any */
if(r->taglist) {
free(r->taglist);
r->taglist = NULL;
r->taglistlen = 0;
}
/* free logname, if any */
if(r->log_name) {
free(r->log_name);
r->log_name = NULL;
}
delete_cname_override(r);
if(!rpz_apply_cfg_elements(r, p))
return 0;
return 1;
}
/**
* Remove RPZ zone name from dname
* Copy dname to newdname, without the originlen number of trailing bytes
@ -1191,16 +1244,20 @@ rpz_find_zone(struct local_zones* zones, uint8_t* qname, size_t qname_len, uint1
/** Find entry for RR type in the list of rrsets for the clientip. */
static struct local_rrset*
rpz_find_synthesized_rrset(uint16_t qtype,
struct clientip_synthesized_rr* data)
struct clientip_synthesized_rr* data, int alias_ok)
{
struct local_rrset* cursor = data->data;
struct local_rrset* cursor = data->data, *cname = NULL;
while( cursor != NULL) {
struct packed_rrset_key* packed_rrset = &cursor->rrset->rk;
if(htons(qtype) == packed_rrset->type) {
return cursor;
}
if(ntohs(packed_rrset->type) == LDNS_RR_TYPE_CNAME && alias_ok)
cname = cursor;
cursor = cursor->next;
}
if(alias_ok)
return cname;
return NULL;
}
@ -1386,7 +1443,7 @@ static int rpz_remove_clientip_rr(struct clientip_synthesized_rr* node,
struct local_rrset* rrset;
struct packed_rrset_data* d;
size_t index;
rrset = rpz_find_synthesized_rrset(rr_type, node);
rrset = rpz_find_synthesized_rrset(rr_type, node, 0);
if(rrset == NULL)
return 0; /* type not found, ignore */
d = (struct packed_rrset_data*)rrset->rrset->entry.data;
@ -1789,7 +1846,7 @@ rpz_apply_clientip_localdata_action(struct clientip_synthesized_rr* raddr,
}
/* check query type / rr type */
rrset = rpz_find_synthesized_rrset(qinfo->qtype, raddr);
rrset = rpz_find_synthesized_rrset(qinfo->qtype, raddr, 1);
if(rrset == NULL) {
verbose(VERB_ALGO, "rpz: unable to find local-data for query");
rrset_count = 0;
@ -1823,6 +1880,28 @@ rpz_apply_clientip_localdata_action(struct clientip_synthesized_rr* raddr,
rrset_count, rcode, rsoa);
}
/** Apply the cname override action, during worker request callback.
* false on failure. */
static int
rpz_apply_cname_override_action(struct rpz* r,
struct query_info* qinfo, struct regional* temp)
{
if(!r)
return 0;
qinfo->local_alias = regional_alloc_zero(temp,
sizeof(struct local_rrset));
if(qinfo->local_alias == NULL)
return 0; /* out of memory */
qinfo->local_alias->rrset = respip_copy_rrset(r->cname_override, temp);
if(qinfo->local_alias->rrset == NULL) {
qinfo->local_alias = NULL;
return 0; /* out of memory */
}
qinfo->local_alias->rrset->rk.dname = qinfo->qname;
qinfo->local_alias->rrset->rk.dname_len = qinfo->qname_len;
return 1;
}
/** add additional section SOA record to the reply.
* Since this gets fed into the normal iterator answer creation, it
* gets minimal-responses applied to it, that can remove the additional SOA
@ -1933,6 +2012,7 @@ rpz_synthesize_localdata_from_rrset(struct rpz* ATTR_UNUSED(r), struct module_qs
msg = rpz_dns_msg_new(ms->region);
if(msg == NULL) { return NULL; }
msg->qinfo = *qi;
new_reply_info = construct_reply_info_base(ms->region,
LDNS_RCODE_NOERROR | BIT_QR | BIT_AA | BIT_RA,
1, /* qd */
@ -1975,40 +2055,42 @@ rpz_synthesize_localdata_from_rrset(struct rpz* ATTR_UNUSED(r), struct module_qs
static inline struct dns_msg*
rpz_synthesize_nsip_localdata(struct rpz* r, struct module_qstate* ms,
struct clientip_synthesized_rr* data, struct auth_zone* az)
struct query_info* qi, struct clientip_synthesized_rr* data,
struct auth_zone* az)
{
struct query_info* qi = &ms->qinfo;
struct local_rrset* rrset;
rrset = rpz_find_synthesized_rrset(qi->qtype, data);
rrset = rpz_find_synthesized_rrset(qi->qtype, data, 1);
if(rrset == NULL) {
verbose(VERB_ALGO, "rpz: nsip: no matching local data found");
return NULL;
}
return rpz_synthesize_localdata_from_rrset(r, ms, &ms->qinfo, rrset, az);
return rpz_synthesize_localdata_from_rrset(r, ms, qi, rrset, az);
}
/* copy'n'paste from localzone.c */
static struct local_rrset*
local_data_find_type(struct local_data* data, uint16_t type, int alias_ok)
{
struct local_rrset* p;
struct local_rrset* p, *cname = NULL;
type = htons(type);
for(p = data->rrsets; p; p = p->next) {
if(p->rrset->rk.type == type)
return p;
if(alias_ok && p->rrset->rk.type == htons(LDNS_RR_TYPE_CNAME))
return p;
cname = p;
}
if(alias_ok)
return cname;
return NULL;
}
/* based on localzone.c:local_data_answer() */
static inline struct dns_msg*
rpz_synthesize_nsdname_localdata(struct rpz* r, struct module_qstate* ms,
struct local_zone* z, struct matched_delegation_point const* match,
struct auth_zone* az)
struct query_info* qi, struct local_zone* z,
struct matched_delegation_point const* match, struct auth_zone* az)
{
struct local_data key;
struct local_data* ld;
@ -2029,13 +2111,13 @@ rpz_synthesize_nsdname_localdata(struct rpz* r, struct module_qstate* ms,
return NULL;
}
rrset = local_data_find_type(ld, ms->qinfo.qtype, 1);
rrset = local_data_find_type(ld, qi->qtype, 1);
if(rrset == NULL) {
verbose(VERB_ALGO, "rpz: nsdname: no matching local data found");
return NULL;
}
return rpz_synthesize_localdata_from_rrset(r, ms, &ms->qinfo, rrset, az);
return rpz_synthesize_localdata_from_rrset(r, ms, qi, rrset, az);
}
/* like local_data_answer for qname triggers after a cname */
@ -2052,17 +2134,70 @@ rpz_synthesize_qname_localdata_msg(struct rpz* r, struct module_qstate* ms,
key.namelabs = dname_count_labels(qinfo->qname);
ld = (struct local_data*)rbtree_search(&z->data, &key.node);
if(ld == NULL) {
verbose(VERB_ALGO, "rpz: qname after cname: name not found");
verbose(VERB_ALGO, "rpz: qname: name not found");
return NULL;
}
rrset = local_data_find_type(ld, qinfo->qtype, 1);
if(rrset == NULL) {
verbose(VERB_ALGO, "rpz: qname after cname: type not found");
verbose(VERB_ALGO, "rpz: qname: type not found");
return NULL;
}
return rpz_synthesize_localdata_from_rrset(r, ms, qinfo, rrset, az);
}
/** Synthesize a CNAME message for RPZ action override */
static struct dns_msg*
rpz_synthesize_cname_override_msg(struct rpz* r, struct module_qstate* ms,
struct query_info* qinfo)
{
struct dns_msg* msg = NULL;
struct reply_info* new_reply_info;
struct ub_packed_rrset_key* rp;
msg = rpz_dns_msg_new(ms->region);
if(msg == NULL) { return NULL; }
msg->qinfo = *qinfo;
new_reply_info = construct_reply_info_base(ms->region,
LDNS_RCODE_NOERROR | BIT_QR | BIT_AA | BIT_RA,
1, /* qd */
0, /* ttl */
0, /* prettl */
0, /* expttl */
1, /* an */
0, /* ns */
0, /* ar */
1, /* total */
sec_status_insecure,
LDNS_EDE_NONE);
if(new_reply_info == NULL) {
log_err("out of memory");
return NULL;
}
new_reply_info->authoritative = 1;
rp = respip_copy_rrset(r->cname_override, ms->region);
if(rp == NULL) {
log_err("out of memory");
return NULL;
}
rp->rk.dname = qinfo->qname;
rp->rk.dname_len = qinfo->qname_len;
/* this rrset is from the rpz data, or synthesized.
* It is not actually from the network, so we flag it with this
* flags as a fake RRset. If later the cache is used to look up
* rrsets, then the fake ones are not returned (if you look without
* the flag). For like CNAME lookups from the iterator or A, AAAA
* lookups for nameserver targets, it would use the without flag
* actual data. So that the actual network data and fake data
* are kept track of separately. */
rp->rk.flags |= PACKED_RRSET_RPZ;
new_reply_info->rrsets[0] = rp;
msg->rep = new_reply_info;
return msg;
}
static int
rpz_synthesize_qname_localdata(struct module_env* env, struct rpz* r,
struct local_zone* z, enum localzone_type lzt, struct query_info* qinfo,
@ -2072,17 +2207,8 @@ rpz_synthesize_qname_localdata(struct module_env* env, struct rpz* r,
struct local_data* ld = NULL;
int ret = 0;
if(r->action_override == RPZ_CNAME_OVERRIDE_ACTION) {
qinfo->local_alias = regional_alloc_zero(temp, sizeof(struct local_rrset));
if(qinfo->local_alias == NULL) {
return 0; /* out of memory */
}
qinfo->local_alias->rrset = regional_alloc_init(temp, r->cname_override,
sizeof(*r->cname_override));
if(qinfo->local_alias->rrset == NULL) {
return 0; /* out of memory */
}
qinfo->local_alias->rrset->rk.dname = qinfo->qname;
qinfo->local_alias->rrset->rk.dname_len = qinfo->qname_len;
if(!rpz_apply_cname_override_action(r, qinfo, temp))
return 0;
if(r->log) {
log_rpz_apply("qname", z->name, NULL, RPZ_CNAME_OVERRIDE_ACTION,
qinfo, repinfo, NULL, r->log_name);
@ -2134,8 +2260,9 @@ rpz_delegation_point_ipbased_trigger_lookup(struct rpz* rpz, struct iter_qstate*
}
static struct dns_msg*
rpz_apply_nsip_trigger(struct module_qstate* ms, struct rpz* r,
struct clientip_synthesized_rr* raddr, struct auth_zone* az)
rpz_apply_nsip_trigger(struct module_qstate* ms, struct query_info* qchase,
struct rpz* r, struct clientip_synthesized_rr* raddr,
struct auth_zone* az)
{
enum rpz_action action = raddr->action;
struct dns_msg* ret = NULL;
@ -2148,16 +2275,16 @@ rpz_apply_nsip_trigger(struct module_qstate* ms, struct rpz* r,
if(action == RPZ_LOCAL_DATA_ACTION && raddr->data == NULL) {
verbose(VERB_ALGO, "rpz: bug: nsip local data action but no local data");
ret = rpz_synthesize_nodata(r, ms, &ms->qinfo, az);
ret = rpz_synthesize_nodata(r, ms, qchase, az);
goto done;
}
switch(action) {
case RPZ_NXDOMAIN_ACTION:
ret = rpz_synthesize_nxdomain(r, ms, &ms->qinfo, az);
ret = rpz_synthesize_nxdomain(r, ms, qchase, az);
break;
case RPZ_NODATA_ACTION:
ret = rpz_synthesize_nodata(r, ms, &ms->qinfo, az);
ret = rpz_synthesize_nodata(r, ms, qchase, az);
break;
case RPZ_TCP_ONLY_ACTION:
/* basically a passthru here but the tcp-only will be
@ -2166,17 +2293,20 @@ rpz_apply_nsip_trigger(struct module_qstate* ms, struct rpz* r,
ret = NULL;
break;
case RPZ_DROP_ACTION:
ret = rpz_synthesize_nodata(r, ms, &ms->qinfo, az);
ret = rpz_synthesize_nodata(r, ms, qchase, az);
ms->is_drop = 1;
break;
case RPZ_LOCAL_DATA_ACTION:
ret = rpz_synthesize_nsip_localdata(r, ms, raddr, az);
if(ret == NULL) { ret = rpz_synthesize_nodata(r, ms, &ms->qinfo, az); }
ret = rpz_synthesize_nsip_localdata(r, ms, qchase, raddr, az);
if(ret == NULL) { ret = rpz_synthesize_nodata(r, ms, qchase, az); }
break;
case RPZ_PASSTHRU_ACTION:
ret = NULL;
ms->rpz_passthru = 1;
break;
case RPZ_CNAME_OVERRIDE_ACTION:
ret = rpz_synthesize_cname_override_msg(r, ms, qchase);
break;
default:
verbose(VERB_ALGO, "rpz: nsip: bug: unhandled or invalid action: '%s'",
rpz_action_to_string(action));
@ -2194,9 +2324,9 @@ rpz_apply_nsip_trigger(struct module_qstate* ms, struct rpz* r,
}
static struct dns_msg*
rpz_apply_nsdname_trigger(struct module_qstate* ms, struct rpz* r,
struct local_zone* z, struct matched_delegation_point const* match,
struct auth_zone* az)
rpz_apply_nsdname_trigger(struct module_qstate* ms, struct query_info* qchase,
struct rpz* r, struct local_zone* z,
struct matched_delegation_point const* match, struct auth_zone* az)
{
struct dns_msg* ret = NULL;
enum rpz_action action = localzone_type_to_rpz_action(z->type);
@ -2209,10 +2339,10 @@ rpz_apply_nsdname_trigger(struct module_qstate* ms, struct rpz* r,
switch(action) {
case RPZ_NXDOMAIN_ACTION:
ret = rpz_synthesize_nxdomain(r, ms, &ms->qinfo, az);
ret = rpz_synthesize_nxdomain(r, ms, qchase, az);
break;
case RPZ_NODATA_ACTION:
ret = rpz_synthesize_nodata(r, ms, &ms->qinfo, az);
ret = rpz_synthesize_nodata(r, ms, qchase, az);
break;
case RPZ_TCP_ONLY_ACTION:
/* basically a passthru here but the tcp-only will be
@ -2221,19 +2351,22 @@ rpz_apply_nsdname_trigger(struct module_qstate* ms, struct rpz* r,
ret = NULL;
break;
case RPZ_DROP_ACTION:
ret = rpz_synthesize_nodata(r, ms, &ms->qinfo, az);
ret = rpz_synthesize_nodata(r, ms, qchase, az);
ms->is_drop = 1;
break;
case RPZ_LOCAL_DATA_ACTION:
ret = rpz_synthesize_nsdname_localdata(r, ms, z, match, az);
if(ret == NULL) { ret = rpz_synthesize_nodata(r, ms, &ms->qinfo, az); }
ret = rpz_synthesize_nsdname_localdata(r, ms, qchase, z, match, az);
if(ret == NULL) { ret = rpz_synthesize_nodata(r, ms, qchase, az); }
break;
case RPZ_PASSTHRU_ACTION:
ret = NULL;
ms->rpz_passthru = 1;
break;
case RPZ_CNAME_OVERRIDE_ACTION:
ret = rpz_synthesize_cname_override_msg(r, ms, qchase);
break;
default:
verbose(VERB_ALGO, "rpz: nsip: bug: unhandled or invalid action: '%s'",
verbose(VERB_ALGO, "rpz: nsdname: bug: unhandled or invalid action: '%s'",
rpz_action_to_string(action));
ret = NULL;
}
@ -2324,7 +2457,7 @@ rpz_callback_from_iterator_module(struct module_qstate* ms, struct iter_qstate*
/* the nsdname has precedence over the nsip triggers */
z = rpz_delegation_point_zone_lookup(is->dp, r->nsdname_zones,
ms->qinfo.qclass, &match);
is->qchase.qclass, &match);
if(z != NULL) {
lock_rw_unlock(&a->lock);
break;
@ -2347,9 +2480,9 @@ rpz_callback_from_iterator_module(struct module_qstate* ms, struct iter_qstate*
if(z) {
lock_rw_unlock(&z->lock);
}
return rpz_apply_nsip_trigger(ms, r, raddr, a);
return rpz_apply_nsip_trigger(ms, &is->qchase, r, raddr, a);
}
return rpz_apply_nsdname_trigger(ms, r, z, &match, a);
return rpz_apply_nsdname_trigger(ms, &is->qchase, r, z, &match, a);
}
struct dns_msg* rpz_callback_from_iterator_cname(struct module_qstate* ms,
@ -2412,10 +2545,10 @@ struct dns_msg* rpz_callback_from_iterator_cname(struct module_qstate* ms,
dname_str(is->qchase.qname, nm);
dname_str(z->name, zn);
if(strcmp(zn, nm) != 0)
verbose(VERB_ALGO, "rpz: qname trigger after cname %s on %s, with action=%s",
verbose(VERB_ALGO, "rpz: qname trigger %s on %s, with action=%s",
zn, nm, rpz_action_to_string(localzone_type_to_rpz_action(lzt)));
else
verbose(VERB_ALGO, "rpz: qname trigger after cname %s, with action=%s",
verbose(VERB_ALGO, "rpz: qname trigger %s, with action=%s",
nm, rpz_action_to_string(localzone_type_to_rpz_action(lzt)));
}
switch(localzone_type_to_rpz_action(lzt)) {
@ -2444,7 +2577,7 @@ struct dns_msg* rpz_callback_from_iterator_cname(struct module_qstate* ms,
ms->rpz_passthru = 1;
break;
default:
verbose(VERB_ALGO, "rpz: qname trigger after cname: bug: unhandled or invalid action: '%s'",
verbose(VERB_ALGO, "rpz: qname trigger: bug: unhandled or invalid action: '%s'",
rpz_action_to_string(localzone_type_to_rpz_action(lzt)));
ret = NULL;
}
@ -2472,8 +2605,21 @@ rpz_apply_maybe_clientip_trigger(struct auth_zones* az, struct module_env* env,
az, qinfo, repinfo, taglist, taglen, stats, z_out, a_out, r_out);
client_action = ((node == NULL) ? RPZ_INVALID_ACTION : node->action);
if(node != NULL && *r_out &&
(*r_out)->action_override != RPZ_NO_OVERRIDE_ACTION) {
client_action = (*r_out)->action_override;
}
if(client_action == RPZ_PASSTHRU_ACTION) {
if(*r_out && (*r_out)->log)
log_rpz_apply(
(node?"clientip":"qname"),
((*z_out)?(*z_out)->name:NULL),
(node?&node->node:NULL),
client_action, qinfo, repinfo, NULL,
(*r_out)->log_name);
*passthru = 1;
ret = 0;
goto done;
}
if(*z_out == NULL || (client_action != RPZ_INVALID_ACTION &&
client_action != RPZ_PASSTHRU_ACTION)) {
@ -2488,14 +2634,15 @@ rpz_apply_maybe_clientip_trigger(struct auth_zones* az, struct module_env* env,
if(client_action == RPZ_LOCAL_DATA_ACTION) {
rpz_apply_clientip_localdata_action(node, env, qinfo,
edns, repinfo, buf, temp, *a_out);
ret = 1;
} else if(client_action == RPZ_CNAME_OVERRIDE_ACTION) {
if(!rpz_apply_cname_override_action(*r_out, qinfo,
temp)) {
ret = 0;
goto done;
}
ret = 0;
} else {
if(*r_out && (*r_out)->log)
log_rpz_apply(
(node?"clientip":"qname"),
((*z_out)?(*z_out)->name:NULL),
(node?&node->node:NULL),
client_action, qinfo, repinfo, NULL,
(*r_out)->log_name);
local_zones_zone_answer(*z_out /*likely NULL, no zone*/, env, qinfo, edns,
repinfo, buf, temp, 0 /* no local data used */,
rpz_action_to_localzone_type(client_action));
@ -2503,8 +2650,15 @@ rpz_apply_maybe_clientip_trigger(struct auth_zones* az, struct module_env* env,
LDNS_RCODE_WIRE(sldns_buffer_begin(buf))
== LDNS_RCODE_NXDOMAIN)
LDNS_RA_CLR(sldns_buffer_begin(buf));
ret = 1;
}
ret = 1;
if(*r_out && (*r_out)->log)
log_rpz_apply(
(node?"clientip":"qname"),
((*z_out)?(*z_out)->name:NULL),
(node?&node->node:NULL),
client_action, qinfo, repinfo, NULL,
(*r_out)->log_name);
goto done;
}
ret = -1;

View file

@ -225,6 +225,14 @@ int rpz_clear(struct rpz* r);
*/
struct rpz* rpz_create(struct config_auth* p);
/**
* Change config on rpz, after reload.
* @param r: the rpz structure.
* @param p: the config that was read.
* @return false on failure.
*/
int rpz_config(struct rpz* r, struct config_auth* p);
/**
* String for RPZ action enum
* @param a: RPZ action to get string for

View file

@ -126,7 +126,8 @@ void view_delete(struct view* v);
*/
void views_print(struct views* v);
/* Find a view by name.
/**
* Find a view by name.
* @param vs: views
* @param name: name of the view we are looking for
* @param write: 1 for obtaining write lock on found view, 0 for read lock

View file

@ -1835,15 +1835,49 @@ verify_p7sig(BIO* data, BIO* p7s, STACK_OF(X509)* trust, const char* p7signer)
return secure;
}
/** open a temp file */
static FILE*
tempfile_open(char* tempf, size_t tempflen, const char* fname, const char* mode)
{
snprintf(tempf, tempflen, "%s~", fname);
return fopen(tempf, mode);
}
/** close an open temp file and replace the original with it */
static void
tempfile_close(FILE* fd, const char* tempf, const char* fname)
{
fflush(fd);
#ifdef HAVE_FSYNC
fsync(fileno(fd));
#else
FlushFileBuffers((HANDLE)_get_osfhandle(_fileno(fd)));
#endif
if(fclose(fd) != 0) {
printf("could not complete write: %s: %s\n",
tempf, strerror(errno));
unlink(tempf);
return;
}
/* success; overwrite actual file */
#ifdef USE_WINSOCK
(void)unlink(fname); /* windows does not replace file with rename() */
#endif
if(rename(tempf, fname) < 0) {
printf("rename(%s to %s): %s", tempf, fname, strerror(errno));
}
}
/** write unsigned root anchor file, a 5011 revoked tp */
static void
write_unsigned_root(const char* root_anchor_file)
{
FILE* out;
time_t now = time(NULL);
out = fopen(root_anchor_file, "w");
char tempf[2048];
out = tempfile_open(tempf, sizeof(tempf), root_anchor_file, "w");
if(!out) {
if(verb) printf("%s: %s\n", root_anchor_file, strerror(errno));
if(verb) printf("%s: %s\n", tempf, strerror(errno));
return;
}
if(fprintf(out, "; autotrust trust anchor file\n"
@ -1858,13 +1892,7 @@ write_unsigned_root(const char* root_anchor_file)
root_anchor_file);
if(verb && errno != 0) printf("%s\n", strerror(errno));
}
fflush(out);
#ifdef HAVE_FSYNC
fsync(fileno(out));
#else
FlushFileBuffers((HANDLE)_get_osfhandle(_fileno(out)));
#endif
fclose(out);
tempfile_close(out, tempf, root_anchor_file);
}
/** write root anchor file */
@ -1874,29 +1902,24 @@ write_root_anchor(const char* root_anchor_file, BIO* ds)
char* pp = NULL;
int len;
FILE* out;
char tempf[2048];
(void)BIO_seek(ds, 0);
len = BIO_get_mem_data(ds, &pp);
if(!len || !pp) {
if(verb) printf("out of memory\n");
return;
}
out = fopen(root_anchor_file, "w");
out = tempfile_open(tempf, sizeof(tempf), root_anchor_file, "w");
if(!out) {
if(verb) printf("%s: %s\n", root_anchor_file, strerror(errno));
if(verb) printf("%s: %s\n", tempf, strerror(errno));
return;
}
if(fwrite(pp, (size_t)len, 1, out) != 1) {
if(verb) printf("failed to write all data to %s\n",
root_anchor_file);
tempf);
if(verb && errno != 0) printf("%s\n", strerror(errno));
}
fflush(out);
#ifdef HAVE_FSYNC
fsync(fileno(out));
#else
FlushFileBuffers((HANDLE)_get_osfhandle(_fileno(out)));
#endif
fclose(out);
tempfile_close(out, tempf, root_anchor_file);
}
/** Perform the verification and update of the trustanchor file */
@ -2040,18 +2063,19 @@ try_read_anchor(const char* file)
static void
write_builtin_anchor(const char* file)
{
char tempf[2048];
const char* builtin_root_anchor = get_builtin_ds();
FILE* out = fopen(file, "w");
FILE* out = tempfile_open(tempf, sizeof(tempf), file, "w");
if(!out) {
printf("could not write builtin anchor, to file %s: %s\n",
file, strerror(errno));
tempf, strerror(errno));
return;
}
if(!fwrite(builtin_root_anchor, strlen(builtin_root_anchor), 1, out)) {
printf("could not complete write builtin anchor, to file %s: %s\n",
file, strerror(errno));
tempf, strerror(errno));
}
fclose(out);
tempfile_close(out, tempf, file);
}
/**

View file

@ -88,6 +88,7 @@ usage(void)
printf("file if omitted %s is used.\n", CONFIGFILE);
printf("-o option print value of option to stdout.\n");
printf("-f output full pathname with chroot applied, eg. with -o pidfile.\n");
printf("-q quiet (suppress output on success).\n");
printf("-h show this usage help.\n");
printf("Version %s\n", PACKAGE_VERSION);
printf("BSD licensed, see LICENSE in source package for details.\n");
@ -965,7 +966,7 @@ check_auth(struct config_file* cfg)
/** check config file */
static void
checkconf(const char* cfgfile, const char* opt, int final)
checkconf(const char* cfgfile, const char* opt, int final, int quiet)
{
char oldwd[4096];
struct config_file* cfg = config_create();
@ -998,7 +999,7 @@ checkconf(const char* cfgfile, const char* opt, int final)
check_fwd(cfg);
check_hints(cfg);
check_auth(cfg);
printf("unbound-checkconf: no errors in %s\n", cfgfile);
if(!quiet) { printf("unbound-checkconf: no errors in %s\n", cfgfile); }
config_delete(cfg);
}
@ -1012,6 +1013,7 @@ int main(int argc, char* argv[])
{
int c;
int final = 0;
int quiet = 0;
const char* f;
const char* opt = NULL;
const char* cfgfile = CONFIGFILE;
@ -1024,7 +1026,7 @@ int main(int argc, char* argv[])
cfgfile = CONFIGFILE;
#endif /* USE_WINSOCK */
/* parse the options */
while( (c=getopt(argc, argv, "fho:")) != -1) {
while( (c=getopt(argc, argv, "fhqo:")) != -1) {
switch(c) {
case 'f':
final = 1;
@ -1032,6 +1034,9 @@ int main(int argc, char* argv[])
case 'o':
opt = optarg;
break;
case 'q':
quiet = 1;
break;
case '?':
case 'h':
default:
@ -1045,7 +1050,7 @@ int main(int argc, char* argv[])
if(argc == 1)
f = argv[0];
else f = cfgfile;
checkconf(f, opt, final);
checkconf(f, opt, final, quiet);
checklock_stop();
return 0;
}

View file

@ -150,12 +150,13 @@ usage(void)
printf(" list_local_data list local-data RRs in use\n");
printf(" insecure_add zone add domain-insecure zone\n");
printf(" insecure_remove zone remove domain-insecure zone\n");
printf(" forward_add [+i] zone addr.. add forward-zone with servers\n");
printf(" forward_add [+it] zone addr.. add forward-zone with servers\n");
printf(" forward_remove [+i] zone remove forward zone\n");
printf(" stub_add [+ip] zone addr.. add stub-zone with servers\n");
printf(" stub_add [+ipt] zone addr.. add stub-zone with servers\n");
printf(" stub_remove [+i] zone remove stub zone\n");
printf(" +i also do dnssec insecure point\n");
printf(" +p set stub to use priming\n");
printf(" +t set to use tls upstream\n");
printf(" forward [off | addr ...] without arg show forward setup\n");
printf(" or off to turn off root forwarding\n");
printf(" or give list of ip addresses\n");

View file

@ -68,6 +68,17 @@ static struct thr_check* thread_infos[THRDEBUG_MAX_THREADS];
int check_locking_order = 1;
/** the pid of this runset, reasonably unique. */
static pid_t check_lock_pid;
/**
* Should checklocks print a trace of the lock and unlock calls.
* It uses fprintf for that because the log function uses a lock and that
* would loop otherwise.
*/
static int verbose_locking = 0;
/**
* Assume lock 0 0 (create_thread, create_instance), is the log lock and
* do not print for that. Otherwise the output is full of log lock accesses.
*/
static int verbose_locking_not_loglock = 1;
/** print all possible debug info on the state of the system */
static void total_debug_info(void);
@ -508,6 +519,9 @@ checklock_rdlock(enum check_lock_type type, struct checked_lock* lock,
if(key_deleted)
return;
if(verbose_locking && !(verbose_locking_not_loglock &&
lock->create_thread == 0 && lock->create_instance == 0))
fprintf(stderr, "checklock_rdlock lock %d %d %s:%d at %s:%d\n", lock->create_thread, lock->create_instance, lock->create_file, lock->create_line, file, line);
log_assert(type == check_lock_rwlock);
checklock_lockit(type, lock, func, file, line,
try_rd, timed_rd, &lock->u.rwlock, 0, 0);
@ -528,6 +542,9 @@ checklock_wrlock(enum check_lock_type type, struct checked_lock* lock,
if(key_deleted)
return;
log_assert(type == check_lock_rwlock);
if(verbose_locking && !(verbose_locking_not_loglock &&
lock->create_thread == 0 && lock->create_instance == 0))
fprintf(stderr, "checklock_wrlock lock %d %d %s:%d at %s:%d\n", lock->create_thread, lock->create_instance, lock->create_file, lock->create_line, file, line);
checklock_lockit(type, lock, func, file, line,
try_wr, timed_wr, &lock->u.rwlock, 0, 1);
}
@ -565,6 +582,9 @@ checklock_lock(enum check_lock_type type, struct checked_lock* lock,
if(key_deleted)
return;
log_assert(type != check_lock_rwlock);
if(verbose_locking && !(verbose_locking_not_loglock &&
lock->create_thread == 0 && lock->create_instance == 0))
fprintf(stderr, "checklock_lock lock %d %d %s:%d at %s:%d\n", lock->create_thread, lock->create_instance, lock->create_file, lock->create_line, file, line);
switch(type) {
case check_lock_mutex:
checklock_lockit(type, lock, func, file, line,
@ -602,6 +622,10 @@ checklock_unlock(enum check_lock_type type, struct checked_lock* lock,
if(lock->hold_count <= 0)
lock_error(lock, func, file, line, "too many unlocks");
if(verbose_locking && !(verbose_locking_not_loglock &&
lock->create_thread == 0 && lock->create_instance == 0))
fprintf(stderr, "checklock_unlock lock %d %d %s:%d at %s:%d\n", lock->create_thread, lock->create_instance, lock->create_file, lock->create_line, file, line);
/* store this point as last touched by */
lock->holder = thr;
lock->hold_count --;

View file

@ -52,6 +52,7 @@
#include "util/data/msgreply.h"
#include "util/data/msgencode.h"
#include "util/data/dname.h"
#include "util/storage/slabhash.h"
#include "util/edns.h"
#include "util/config_file.h"
#include "services/listen_dnsport.h"
@ -65,6 +66,7 @@
#include "sldns/wire2str.h"
#include "sldns/str2wire.h"
#include "daemon/remote.h"
#include "daemon/daemon.h"
#include "util/timeval_func.h"
#include <signal.h>
struct worker;
@ -154,6 +156,8 @@ repevt_string(enum replay_event_type t)
case repevt_assign: return "ASSIGN";
case repevt_traffic: return "TRAFFIC";
case repevt_infra_rtt: return "INFRA_RTT";
case repevt_flush_message: return "FLUSH_MESSAGE";
case repevt_expire_message: return "EXPIRE_MESSAGE";
default: return "UNKNOWN";
}
}
@ -691,6 +695,66 @@ do_infra_rtt(struct replay_runtime* runtime)
free(dp);
}
/** Flush message from message cache. */
static void
do_flush_message(struct replay_runtime* runtime)
{
struct replay_moment* now = runtime->now;
uint8_t rr[1024];
size_t rr_len = sizeof(rr), dname_len = 0;
hashvalue_type h;
struct query_info k;
if(sldns_str2wire_rr_question_buf(now->string, rr, &rr_len,
&dname_len, NULL, 0, NULL, 0) != 0)
fatal_exit("could not parse '%s'", now->string);
log_info("remove message %s", now->string);
k.qname = rr;
k.qname_len = dname_len;
k.qtype = sldns_wirerr_get_type(rr, rr_len, dname_len);
k.qclass = sldns_wirerr_get_class(rr, rr_len, dname_len);
k.local_alias = NULL;
h = query_info_hash(&k, 0);
slabhash_remove(runtime->daemon->env->msg_cache, h, &k);
}
/** Expire message from message cache. */
static void
do_expire_message(struct replay_runtime* runtime)
{
struct replay_moment* now = runtime->now;
uint8_t rr[1024];
size_t rr_len = sizeof(rr), dname_len = 0;
hashvalue_type h;
struct query_info k;
struct lruhash_entry* e;
if(sldns_str2wire_rr_question_buf(now->string, rr, &rr_len,
&dname_len, NULL, 0, NULL, 0) != 0)
fatal_exit("could not parse '%s'", now->string);
log_info("expire message %s", now->string);
k.qname = rr;
k.qname_len = dname_len;
k.qtype = sldns_wirerr_get_type(rr, rr_len, dname_len);
k.qclass = sldns_wirerr_get_class(rr, rr_len, dname_len);
k.local_alias = NULL;
h = query_info_hash(&k, 0);
e = slabhash_lookup(runtime->daemon->env->msg_cache, h, &k, 0);
if(e) {
struct msgreply_entry* msg = (struct msgreply_entry*)e->key;
struct reply_info* rep = (struct reply_info*)msg->entry.data;
time_t expired = runtime->now_secs;
expired -= 3;
rep->ttl = expired;
rep->prefetch_ttl = expired;
rep->serve_expired_ttl = expired;
lock_rw_unlock(&msg->entry.lock);
}
}
/** perform exponential backoff on the timeout */
static void
expon_timeout_backoff(struct replay_runtime* runtime)
@ -796,6 +860,14 @@ do_moment_and_advance(struct replay_runtime* runtime)
do_infra_rtt(runtime);
advance_moment(runtime);
break;
case repevt_flush_message:
do_flush_message(runtime);
advance_moment(runtime);
break;
case repevt_expire_message:
do_expire_message(runtime);
advance_moment(runtime);
break;
default:
fatal_exit("testbound: unknown event type %d",
runtime->now->evt_type);

View file

@ -348,6 +348,20 @@ replay_moment_read(char* remain, FILE* in, const char* name,
mom->string = strdup(m);
if(!mom->string) fatal_exit("out of memory");
if(!mom->variable) fatal_exit("out of memory");
} else if(parse_keyword(&remain, "FLUSH_MESSAGE")) {
mom->evt_type = repevt_flush_message;
while(isspace((unsigned char)*remain))
remain++;
strip_end_white(remain);
mom->string = strdup(remain);
if(!mom->string) fatal_exit("out of memory");
} else if(parse_keyword(&remain, "EXPIRE_MESSAGE")) {
mom->evt_type = repevt_expire_message;
while(isspace((unsigned char)*remain))
remain++;
strip_end_white(remain);
mom->string = strdup(remain);
if(!mom->string) fatal_exit("out of memory");
} else {
log_err("%d: unknown event type %s", pstate->lineno, remain);
free(mom);

View file

@ -85,6 +85,8 @@
* The file contents is macro expanded before match.
* o CHECK_TEMPFILE [fname] - followed by FILE_BEGIN [to match] FILE_END
* o INFRA_RTT [ip] [dp] [rtt] - update infra cache entry with rtt.
* o FLUSH_MESSAGE name type class - flushes entry in message cache.
* o EXPIRE_MESSAGE name type class - expires entry in message cache.
* o ERROR
* ; following entry starts on the next line, ENTRY_BEGIN.
* ; more STEP items
@ -148,6 +150,7 @@ struct fake_timer;
struct replay_var;
struct infra_cache;
struct sldns_buffer;
struct daemon;
/**
* A replay scenario.
@ -212,6 +215,10 @@ struct replay_moment {
repevt_assign,
/** store infra rtt cache entry: addr and string (int) */
repevt_infra_rtt,
/** flush message cache entry */
repevt_flush_message,
/** expire message cache entry */
repevt_expire_message,
/** cause traffic to flow */
repevt_traffic
}
@ -297,6 +304,8 @@ struct replay_runtime {
/** ref the infra cache (was passed to outside_network_create) */
struct infra_cache* infra;
/** the daemon structure passed in worker call to remote accept open */
struct daemon* daemon;
/** the current time in seconds */
time_t now_secs;

View file

@ -48,6 +48,7 @@
#include "testcode/fake_event.h"
#include "daemon/remote.h"
#include "libunbound/worker.h"
#include "daemon/worker.h"
#include "util/config_file.h"
#include "sldns/keyraw.h"
#ifdef UB_ON_WINDOWS
@ -532,9 +533,10 @@ void daemon_remote_clear(struct daemon_remote* ATTR_UNUSED(rc))
}
int daemon_remote_open_accept(struct daemon_remote* ATTR_UNUSED(rc),
struct listen_port* ATTR_UNUSED(ports),
struct worker* ATTR_UNUSED(worker))
struct listen_port* ATTR_UNUSED(ports), struct worker* worker)
{
struct replay_runtime* runtime = (struct replay_runtime*)worker->base;
runtime->daemon = worker->daemon;
return 1;
}

View file

@ -12,6 +12,9 @@ get_make
(cd $PRE ; $MAKE doc) > mylog 2>&1
bad=0
# filter out doxygen warnings about unsupported tags in the config, print first
grep -e "warning: ignoring unsupported tag.*file .*/doc/unbound.doxygen" mylog
grep -v -e "warning: ignoring unsupported tag.*file .*/doc/unbound.doxygen" mylog > ilog; mv ilog mylog
if grep -e "Warning" -e "warning" -e "Error" -e "error" mylog >/dev/null 2>&1;
then
cat mylog

324
testdata/cachedb_expired.crpl vendored Normal file
View file

@ -0,0 +1,324 @@
; config options
server:
target-fetch-policy: "0 0 0 0 0"
qname-minimisation: no
minimal-responses: no
serve-expired: yes
module-config: "cachedb iterator"
cachedb:
backend: "testframe"
secret-seed: "testvalue"
cachedb-check-when-serve-expired: yes
stub-zone:
name: "."
stub-addr: 193.0.14.129
CONFIG_END
SCENARIO_BEGIN Test cachedb and serve expired.
; K.ROOT-SERVERS.NET.
RANGE_BEGIN 0 400
ADDRESS 193.0.14.129
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
REPLY QR NOERROR
SECTION QUESTION
. IN NS
SECTION ANSWER
. IN NS K.ROOT-SERVERS.NET.
SECTION ADDITIONAL
K.ROOT-SERVERS.NET. IN A 193.0.14.129
ENTRY_END
ENTRY_BEGIN
MATCH opcode subdomain
ADJUST copy_id copy_query
REPLY QR NOERROR
SECTION QUESTION
com. IN NS
SECTION AUTHORITY
com. IN NS a.gtld-servers.net.
SECTION ADDITIONAL
a.gtld-servers.net. IN A 192.5.6.30
ENTRY_END
RANGE_END
; a.gtld-servers.net.
RANGE_BEGIN 0 400
ADDRESS 192.5.6.30
ENTRY_BEGIN
MATCH opcode subdomain
ADJUST copy_id copy_query
REPLY QR NOERROR
SECTION QUESTION
example.com. IN NS
SECTION AUTHORITY
example.com. IN NS ns2.example.com.
SECTION ADDITIONAL
ns2.example.com. IN A 1.2.3.5
ENTRY_END
ENTRY_BEGIN
MATCH opcode subdomain
ADJUST copy_id copy_query
REPLY QR NOERROR
SECTION QUESTION
foo.com. IN NS
SECTION AUTHORITY
foo.com. IN NS ns.example.com.
ENTRY_END
RANGE_END
; ns2.example.com.
RANGE_BEGIN 0 400
ADDRESS 1.2.3.5
ENTRY_BEGIN
MATCH opcode qname qtype
REPLY QR AA NOERROR
SECTION QUESTION
www.example.com. IN A
SECTION ANSWER
www.example.com. 10 IN A 1.2.3.4
ENTRY_END
ENTRY_BEGIN
MATCH opcode qname qtype
REPLY QR AA NOERROR
SECTION QUESTION
www2.example.com. IN A
SECTION ANSWER
www2.example.com. 10 IN A 1.2.3.5
ENTRY_END
RANGE_END
; Get an entry in cache, to make it expired.
STEP 1 QUERY
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
www.example.com. IN A
ENTRY_END
; get the answer for it
STEP 10 CHECK_ANSWER
ENTRY_BEGIN
MATCH all
REPLY QR RD RA NOERROR
SECTION QUESTION
www.example.com. IN A
SECTION ANSWER
www.example.com. 10 IN A 1.2.3.4
ENTRY_END
; Get another query in cache to make it expired.
STEP 20 QUERY
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
www2.example.com. IN A
ENTRY_END
; get the answer for it
STEP 30 CHECK_ANSWER
ENTRY_BEGIN
MATCH all
REPLY QR RD RA NOERROR
SECTION QUESTION
www2.example.com. IN A
SECTION ANSWER
www2.example.com. 10 IN A 1.2.3.5
ENTRY_END
; it is now expired
STEP 40 TIME_PASSES ELAPSE 20
; cache is expired, and cachedb is expired.
STEP 50 QUERY
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
www2.example.com. IN A
ENTRY_END
STEP 60 CHECK_ANSWER
ENTRY_BEGIN
MATCH all ttl
REPLY QR RD RA NOERROR
SECTION QUESTION
www2.example.com. IN A
SECTION ANSWER
www2.example.com. 30 IN A 1.2.3.5
ENTRY_END
; cache is expired, cachedb has no answer
STEP 70 QUERY
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
www.example.com. IN A
ENTRY_END
STEP 80 CHECK_ANSWER
ENTRY_BEGIN
MATCH all ttl
REPLY QR RD RA NOERROR
SECTION QUESTION
www.example.com. IN A
SECTION ANSWER
www.example.com. 30 IN A 1.2.3.4
ENTRY_END
STEP 90 TRAFFIC
; the entry should be refreshed in cache now.
; cache is valid and cachedb is valid.
STEP 100 QUERY
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
www.example.com. IN A
ENTRY_END
STEP 110 CHECK_ANSWER
ENTRY_BEGIN
MATCH all ttl
REPLY QR RD RA NOERROR
SECTION QUESTION
www.example.com. IN A
SECTION ANSWER
www.example.com. 10 IN A 1.2.3.4
ENTRY_END
; flush the entry from cache
STEP 120 FLUSH_MESSAGE www.example.com. IN A
; cache has no answer, cachedb valid
STEP 130 QUERY
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
www.example.com. IN A
ENTRY_END
STEP 140 CHECK_ANSWER
ENTRY_BEGIN
MATCH all ttl
REPLY QR RD RA NOERROR
SECTION QUESTION
www.example.com. IN A
SECTION ANSWER
www.example.com. 10 IN A 1.2.3.4
ENTRY_END
; it is now expired
STEP 150 TIME_PASSES ELAPSE 20
; flush the entry from cache
STEP 160 FLUSH_MESSAGE www.example.com. IN A
; cache has no answer, cachedb is expired
STEP 170 QUERY
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
www.example.com. IN A
ENTRY_END
STEP 180 CHECK_ANSWER
ENTRY_BEGIN
MATCH all ttl
REPLY QR RD RA NOERROR
SECTION QUESTION
www.example.com. IN A
SECTION ANSWER
www.example.com. 30 IN A 1.2.3.4
ENTRY_END
STEP 190 TRAFFIC
; the expired message is updated.
; cache is valid, cachedb is valid
STEP 200 QUERY
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
www.example.com. IN A
ENTRY_END
STEP 210 CHECK_ANSWER
ENTRY_BEGIN
MATCH all ttl
REPLY QR RD RA NOERROR
SECTION QUESTION
www.example.com. IN A
SECTION ANSWER
www.example.com. 10 IN A 1.2.3.4
ENTRY_END
; expire the entry in cache
STEP 220 EXPIRE_MESSAGE www.example.com. IN A
; cache is expired, cachedb valid
STEP 230 QUERY
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
www.example.com. IN A
ENTRY_END
STEP 240 CHECK_ANSWER
ENTRY_BEGIN
MATCH all ttl
REPLY QR RD RA NOERROR
SECTION QUESTION
www.example.com. IN A
SECTION ANSWER
www.example.com. 10 IN A 1.2.3.4
ENTRY_END
; it is now expired
STEP 250 TIME_PASSES ELAPSE 20
; expire the entry in cache
STEP 260 EXPIRE_MESSAGE www.example.com. IN A
; cache is expired, cachedb is expired
STEP 270 QUERY
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
www.example.com. IN A
ENTRY_END
STEP 280 CHECK_ANSWER
ENTRY_BEGIN
MATCH all ttl
REPLY QR RD RA NOERROR
SECTION QUESTION
www.example.com. IN A
SECTION ANSWER
www.example.com. 30 IN A 1.2.3.4
ENTRY_END
STEP 290 TRAFFIC
; the expired message is updated.
; cache is valid, cachedb is valid
STEP 300 QUERY
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
www.example.com. IN A
ENTRY_END
STEP 310 CHECK_ANSWER
ENTRY_BEGIN
MATCH all ttl
REPLY QR RD RA NOERROR
SECTION QUESTION
www.example.com. IN A
SECTION ANSWER
www.example.com. 10 IN A 1.2.3.4
ENTRY_END
SCENARIO_END

View file

@ -0,0 +1,343 @@
; config options
server:
target-fetch-policy: "0 0 0 0 0"
qname-minimisation: no
minimal-responses: no
serve-expired: yes
serve-expired-reply-ttl: 30
; at least one second, so we can time skip past the timer in the
; testbound script steps, but also reply within the time.
serve-expired-client-timeout: 1200
module-config: "cachedb iterator"
discard-timeout: 3000
cachedb:
backend: "testframe"
secret-seed: "testvalue"
cachedb-check-when-serve-expired: yes
stub-zone:
name: "."
stub-addr: 193.0.14.129
CONFIG_END
SCENARIO_BEGIN Test cachedb and serve-expired-client-timeout.
; K.ROOT-SERVERS.NET.
RANGE_BEGIN 0 400
ADDRESS 193.0.14.129
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
REPLY QR NOERROR
SECTION QUESTION
. IN NS
SECTION ANSWER
. IN NS K.ROOT-SERVERS.NET.
SECTION ADDITIONAL
K.ROOT-SERVERS.NET. IN A 193.0.14.129
ENTRY_END
ENTRY_BEGIN
MATCH opcode subdomain
ADJUST copy_id copy_query
REPLY QR NOERROR
SECTION QUESTION
com. IN NS
SECTION AUTHORITY
com. IN NS a.gtld-servers.net.
SECTION ADDITIONAL
a.gtld-servers.net. IN A 192.5.6.30
ENTRY_END
RANGE_END
; a.gtld-servers.net.
RANGE_BEGIN 0 400
ADDRESS 192.5.6.30
ENTRY_BEGIN
MATCH opcode subdomain
ADJUST copy_id copy_query
REPLY QR NOERROR
SECTION QUESTION
example.com. IN NS
SECTION AUTHORITY
example.com. IN NS ns2.example.com.
SECTION ADDITIONAL
ns2.example.com. IN A 1.2.3.5
ENTRY_END
ENTRY_BEGIN
MATCH opcode subdomain
ADJUST copy_id copy_query
REPLY QR NOERROR
SECTION QUESTION
foo.com. IN NS
SECTION AUTHORITY
foo.com. IN NS ns.example.com.
ENTRY_END
RANGE_END
; ns2.example.com.
RANGE_BEGIN 0 60
ADDRESS 1.2.3.5
ENTRY_BEGIN
MATCH opcode qname qtype
REPLY QR AA NOERROR
SECTION QUESTION
www.example.com. IN A
SECTION ANSWER
www.example.com. 10 IN A 1.2.3.4
ENTRY_END
ENTRY_BEGIN
MATCH opcode qname qtype
REPLY QR AA NOERROR
SECTION QUESTION
www2.example.com. IN A
SECTION ANSWER
www2.example.com. 10 IN A 1.2.3.5
ENTRY_END
RANGE_END
; ns2.example.com. - after a change
RANGE_BEGIN 80 90
ADDRESS 1.2.3.5
ENTRY_BEGIN
MATCH opcode qname qtype
REPLY QR AA NOERROR
SECTION QUESTION
www.example.com. IN A
SECTION ANSWER
www.example.com. 10 IN A 1.2.3.6
ENTRY_END
ENTRY_BEGIN
MATCH opcode qname qtype
REPLY QR AA NOERROR
SECTION QUESTION
www2.example.com. IN A
SECTION ANSWER
www2.example.com. 10 IN A 1.2.3.7
ENTRY_END
RANGE_END
; ns2.example.com. - steps 90-120 not responding.
; ns2.example.com. - after a change
RANGE_BEGIN 130 140
ADDRESS 1.2.3.5
ENTRY_BEGIN
MATCH opcode qname qtype
REPLY QR AA NOERROR
SECTION QUESTION
www.example.com. IN A
SECTION ANSWER
www.example.com. 10 IN A 1.2.3.8
ENTRY_END
ENTRY_BEGIN
MATCH opcode qname qtype
REPLY QR AA NOERROR
SECTION QUESTION
www2.example.com. IN A
SECTION ANSWER
www2.example.com. 10 IN A 1.2.3.9
ENTRY_END
RANGE_END
; ns2.example.com. - steps 150-160 not responding.
; ns2.example.com. - after a change
RANGE_BEGIN 170 200
ADDRESS 1.2.3.5
ENTRY_BEGIN
MATCH opcode qname qtype
REPLY QR AA NOERROR
SECTION QUESTION
www.example.com. IN A
SECTION ANSWER
www.example.com. 10 IN A 1.2.3.10
ENTRY_END
ENTRY_BEGIN
MATCH opcode qname qtype
REPLY QR AA NOERROR
SECTION QUESTION
www2.example.com. IN A
SECTION ANSWER
www2.example.com. 10 IN A 1.2.3.11
ENTRY_END
RANGE_END
; make time not 0
STEP 2 TIME_PASSES ELAPSE 212
; Get an entry in cache.
STEP 4 QUERY
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
www.example.com. IN A
ENTRY_END
; get the answer for it
STEP 10 CHECK_ANSWER
ENTRY_BEGIN
MATCH all
REPLY QR RD RA NOERROR
SECTION QUESTION
www.example.com. IN A
SECTION ANSWER
www.example.com. 10 IN A 1.2.3.4
ENTRY_END
; Get another query in cache.
STEP 20 QUERY
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
www2.example.com. IN A
ENTRY_END
; get the answer for it
STEP 30 CHECK_ANSWER
ENTRY_BEGIN
MATCH all
REPLY QR RD RA NOERROR
SECTION QUESTION
www2.example.com. IN A
SECTION ANSWER
www2.example.com. 10 IN A 1.2.3.5
ENTRY_END
; www.example.com and www2.example.com are in cache, www2 in cachedb.
STEP 40 FLUSH_MESSAGE www2.example.com. IN A
; now www in cache, www2 not in cache, www2 in cachedb.
; because of the client timeout, it should be able to use the
; response from cachedb for www2.
; make 2 seconds pass to decrement the TTL on the response,
; the upstream TTL would be 10, cachedb 8.
STEP 48 TIME_PASSES ELAPSE 2
STEP 50 QUERY
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
www2.example.com. IN A
ENTRY_END
STEP 60 CHECK_ANSWER
ENTRY_BEGIN
MATCH all ttl
REPLY QR RD RA NOERROR
SECTION QUESTION
www2.example.com. IN A
SECTION ANSWER
www2.example.com. 8 IN A 1.2.3.5
ENTRY_END
; make both cache and cachedb expired
STEP 70 TIME_PASSES ELAPSE 20
; www and www2 expired in cache, www2 expired in cachedb.
; the query should now try to resolve and complete within the
; client timeout, and return the upstream version.
; the upstream is changed to give a different one now.
STEP 80 QUERY
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
www2.example.com. IN A
ENTRY_END
STEP 90 CHECK_ANSWER
ENTRY_BEGIN
MATCH all ttl
REPLY QR RD RA NOERROR
SECTION QUESTION
www2.example.com. IN A
SECTION ANSWER
www2.example.com. 10 IN A 1.2.3.7
ENTRY_END
; expire the data again
STEP 100 TIME_PASSES ELAPSE 20
; the query should now try to resolve, but the upstream is not
; responsive for several testbound steps. When the timer expires,
; the expired answer should be returned.
; www2 expired in cache and www2 expired in cachedb.
STEP 110 QUERY
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
www2.example.com. IN A
ENTRY_END
; make 2 seconds pass to go past the client timeout
STEP 112 TIME_PASSES ELAPSE 2
STEP 120 CHECK_ANSWER
ENTRY_BEGIN
MATCH all ttl
REPLY QR RD RA NOERROR
SECTION QUESTION
www2.example.com. IN A
SECTION ANSWER
www2.example.com. 30 IN A 1.2.3.7
ENTRY_END
; make traffic flow to resolve the query, server responds.
STEP 130 TRAFFIC
; expire the data again
STEP 140 TIME_PASSES ELAPSE 20
; The client query tries to resolve, but gets no immediate answer,
; so the expired data is used. But the expired data is in cache and
; the query is not in cachedb.
STEP 150 QUERY
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
www.example.com. IN A
ENTRY_END
; make 2 seconds pass to go past the client timeout
STEP 152 TIME_PASSES ELAPSE 2
STEP 160 CHECK_ANSWER
ENTRY_BEGIN
MATCH all ttl
REPLY QR RD RA NOERROR
SECTION QUESTION
www.example.com. IN A
SECTION ANSWER
www.example.com. 30 IN A 1.2.3.4
ENTRY_END
; make traffic flow to resolve the query, server responds.
STEP 170 TRAFFIC
; now the client query tries to resolve, and completes within the client
; timeout, but there is expired data in cache but not in cachedb.
STEP 180 QUERY
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
www2.example.com. IN A
ENTRY_END
STEP 190 CHECK_ANSWER
ENTRY_BEGIN
MATCH all ttl
REPLY QR RD RA NOERROR
SECTION QUESTION
www2.example.com. IN A
SECTION ANSWER
www2.example.com. 10 IN A 1.2.3.11
ENTRY_END
SCENARIO_END

259
testdata/cachedb_expired_reply_ttl.crpl vendored Normal file
View file

@ -0,0 +1,259 @@
; config options
server:
target-fetch-policy: "0 0 0 0 0"
qname-minimisation: no
minimal-responses: no
serve-expired: yes
serve-expired-reply-ttl: 30
module-config: "cachedb iterator"
cachedb:
backend: "testframe"
secret-seed: "testvalue"
cachedb-check-when-serve-expired: yes
stub-zone:
name: "."
stub-addr: 193.0.14.129
CONFIG_END
SCENARIO_BEGIN Test cachedb and serve-expired-reply-ttl.
; K.ROOT-SERVERS.NET.
RANGE_BEGIN 0 400
ADDRESS 193.0.14.129
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
REPLY QR NOERROR
SECTION QUESTION
. IN NS
SECTION ANSWER
. IN NS K.ROOT-SERVERS.NET.
SECTION ADDITIONAL
K.ROOT-SERVERS.NET. IN A 193.0.14.129
ENTRY_END
ENTRY_BEGIN
MATCH opcode subdomain
ADJUST copy_id copy_query
REPLY QR NOERROR
SECTION QUESTION
com. IN NS
SECTION AUTHORITY
com. IN NS a.gtld-servers.net.
SECTION ADDITIONAL
a.gtld-servers.net. IN A 192.5.6.30
ENTRY_END
RANGE_END
; a.gtld-servers.net.
RANGE_BEGIN 0 400
ADDRESS 192.5.6.30
ENTRY_BEGIN
MATCH opcode subdomain
ADJUST copy_id copy_query
REPLY QR NOERROR
SECTION QUESTION
example.com. IN NS
SECTION AUTHORITY
example.com. IN NS ns2.example.com.
SECTION ADDITIONAL
ns2.example.com. IN A 1.2.3.5
ENTRY_END
ENTRY_BEGIN
MATCH opcode subdomain
ADJUST copy_id copy_query
REPLY QR NOERROR
SECTION QUESTION
foo.com. IN NS
SECTION AUTHORITY
foo.com. IN NS ns.example.com.
ENTRY_END
RANGE_END
; ns2.example.com.
RANGE_BEGIN 0 400
ADDRESS 1.2.3.5
ENTRY_BEGIN
MATCH opcode qname qtype
REPLY QR AA NOERROR
SECTION QUESTION
www.example.com. IN A
SECTION ANSWER
www.example.com. 10 IN A 1.2.3.4
ENTRY_END
ENTRY_BEGIN
MATCH opcode qname qtype
REPLY QR AA NOERROR
SECTION QUESTION
www2.example.com. IN A
SECTION ANSWER
www2.example.com. 10 IN A 1.2.3.5
ENTRY_END
RANGE_END
; make time not 0
STEP 2 TIME_PASSES ELAPSE 212
; Get an entry in cache, to make it expired.
STEP 4 QUERY
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
www.example.com. IN A
ENTRY_END
; get the answer for it
STEP 10 CHECK_ANSWER
ENTRY_BEGIN
MATCH all
REPLY QR RD RA NOERROR
SECTION QUESTION
www.example.com. IN A
SECTION ANSWER
www.example.com. 10 IN A 1.2.3.4
ENTRY_END
; Get another query in cache to make it expired.
STEP 20 QUERY
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
www2.example.com. IN A
ENTRY_END
; get the answer for it
STEP 30 CHECK_ANSWER
ENTRY_BEGIN
MATCH all
REPLY QR RD RA NOERROR
SECTION QUESTION
www2.example.com. IN A
SECTION ANSWER
www2.example.com. 10 IN A 1.2.3.5
ENTRY_END
; it is now expired
STEP 40 TIME_PASSES ELAPSE 20
; cache is expired, and cachedb is expired.
STEP 50 QUERY
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
www2.example.com. IN A
ENTRY_END
STEP 60 CHECK_ANSWER
ENTRY_BEGIN
MATCH all ttl
REPLY QR RD RA NOERROR
SECTION QUESTION
www2.example.com. IN A
SECTION ANSWER
www2.example.com. 30 IN A 1.2.3.5
ENTRY_END
; got an answer from upstream
STEP 61 QUERY
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
www2.example.com. IN A
ENTRY_END
STEP 62 CHECK_ANSWER
ENTRY_BEGIN
MATCH all ttl
REPLY QR RD RA NOERROR
SECTION QUESTION
www2.example.com. IN A
SECTION ANSWER
www2.example.com. 10 IN A 1.2.3.5
ENTRY_END
; cache is expired, cachedb has no answer
STEP 70 QUERY
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
www.example.com. IN A
ENTRY_END
STEP 80 CHECK_ANSWER
ENTRY_BEGIN
MATCH all ttl
REPLY QR RD RA NOERROR
SECTION QUESTION
www.example.com. IN A
SECTION ANSWER
www.example.com. 30 IN A 1.2.3.4
ENTRY_END
STEP 90 TRAFFIC
; the entry should be refreshed in cache now.
; cache is valid and cachedb is valid.
STEP 100 QUERY
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
www.example.com. IN A
ENTRY_END
STEP 110 CHECK_ANSWER
ENTRY_BEGIN
MATCH all ttl
REPLY QR RD RA NOERROR
SECTION QUESTION
www.example.com. IN A
SECTION ANSWER
www.example.com. 10 IN A 1.2.3.4
ENTRY_END
; make both cache and cachedb expired.
STEP 120 TIME_PASSES ELAPSE 20
STEP 130 FLUSH_MESSAGE www.example.com. IN A
; cache has no entry and cachedb is expired.
STEP 140 QUERY
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
www.example.com. IN A
ENTRY_END
STEP 150 CHECK_ANSWER
ENTRY_BEGIN
MATCH all ttl
REPLY QR RD RA NOERROR
SECTION QUESTION
www.example.com. IN A
SECTION ANSWER
www.example.com. 30 IN A 1.2.3.4
ENTRY_END
; the name is resolved
STEP 160 TRAFFIC
; the resolve name has been updated.
STEP 170 QUERY
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
www.example.com. IN A
ENTRY_END
STEP 180 CHECK_ANSWER
ENTRY_BEGIN
MATCH all ttl
REPLY QR RD RA NOERROR
SECTION QUESTION
www.example.com. IN A
SECTION ANSWER
www.example.com. 10 IN A 1.2.3.4
ENTRY_END
SCENARIO_END

304
testdata/cachedb_subnet_change.crpl vendored Normal file
View file

@ -0,0 +1,304 @@
; config options
server:
target-fetch-policy: "0 0 0 0 0"
qname-minimisation: no
minimal-responses: no
serve-expired: yes
serve-expired-reply-ttl: 30
; disable the serve expired client timeout.
serve-expired-client-timeout: 0
send-client-subnet: 1.2.3.4
max-client-subnet-ipv4: 17
; subnetcache is to the left of cachedb, because it sets no cache
; store for edns subnet content for modules to the right of it.
; this keeps subnet content out of cachedb as global content.
module-config: "subnetcache cachedb iterator"
cachedb:
backend: "testframe"
secret-seed: "testvalue"
cachedb-check-when-serve-expired: yes
stub-zone:
name: "."
stub-addr: 193.0.14.129
CONFIG_END
SCENARIO_BEGIN Test cachedb, subnet and serve-expired, with a domain change from global to subnet.
; So the CNAME first points to a global record, then points to a subnet record.
; K.ROOT-SERVERS.NET.
RANGE_BEGIN 0 400
ADDRESS 193.0.14.129
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
REPLY QR NOERROR
SECTION QUESTION
. IN NS
SECTION ANSWER
. IN NS K.ROOT-SERVERS.NET.
SECTION ADDITIONAL
K.ROOT-SERVERS.NET. IN A 193.0.14.129
ENTRY_END
ENTRY_BEGIN
MATCH opcode subdomain
ADJUST copy_id copy_query
REPLY QR NOERROR
SECTION QUESTION
com. IN NS
SECTION AUTHORITY
com. IN NS a.gtld-servers.net.
SECTION ADDITIONAL
a.gtld-servers.net. IN A 192.5.6.30
ENTRY_END
RANGE_END
; a.gtld-servers.net.
RANGE_BEGIN 0 400
ADDRESS 192.5.6.30
ENTRY_BEGIN
MATCH opcode subdomain
ADJUST copy_id copy_query
REPLY QR NOERROR
SECTION QUESTION
example.com. IN NS
SECTION AUTHORITY
example.com. IN NS ns2.example.com.
SECTION ADDITIONAL
ns2.example.com. IN A 1.2.3.5
ENTRY_END
ENTRY_BEGIN
MATCH opcode subdomain
ADJUST copy_id copy_query
REPLY QR NOERROR
SECTION QUESTION
foo.com. IN NS
SECTION AUTHORITY
foo.com. IN NS ns.foo.com.
SECTION ADDITIONAL
ns.foo.com. IN A 1.2.3.4
ENTRY_END
ENTRY_BEGIN
MATCH opcode subdomain
ADJUST copy_id copy_query
REPLY QR NOERROR
SECTION QUESTION
initial.com. IN NS
SECTION AUTHORITY
initial.com. IN NS ns.initial.com.
SECTION ADDITIONAL
ns.initial.com. IN A 1.2.3.6
ENTRY_END
RANGE_END
; ns2.example.com.
RANGE_BEGIN 0 30
ADDRESS 1.2.3.5
ENTRY_BEGIN
MATCH opcode qname qtype
REPLY QR AA NOERROR
SECTION QUESTION
www.example.com. IN A
SECTION ANSWER
www.example.com. 10 IN CNAME www.initial.com.
ENTRY_END
RANGE_END
; ns2.example.com. - after change
RANGE_BEGIN 40 80
ADDRESS 1.2.3.5
ENTRY_BEGIN
MATCH opcode qname qtype
REPLY QR AA NOERROR
SECTION QUESTION
www.example.com. IN A
SECTION ANSWER
www.example.com. 10 IN CNAME example.foo.com.
ENTRY_END
RANGE_END
; ns.initial.com.
RANGE_BEGIN 0 400
ADDRESS 1.2.3.6
ENTRY_BEGIN
MATCH opcode qname qtype
REPLY QR AA NOERROR
SECTION QUESTION
www.initial.com. IN A
SECTION ANSWER
www.initial.com. 10 IN A 1.2.3.4
ENTRY_END
RANGE_END
; ns.foo.com.
RANGE_BEGIN 40 80
ADDRESS 1.2.3.4
ENTRY_BEGIN
MATCH opcode qname qtype ednsdata
REPLY QR AA NOERROR
SECTION QUESTION
example.foo.com. IN A
SECTION ANSWER
example.foo.com. 10 IN A 1.2.3.5
SECTION ADDITIONAL
HEX_EDNSDATA_BEGIN
; client is 127.0.0.1
00 08 ; OPC
00 07 ; option length
00 01 ; Family
11 00 ; source mask, scopemask
7f 00 00 ; address
HEX_EDNSDATA_END
ENTRY_END
RANGE_END
; ns2.example.com. - later
RANGE_BEGIN 90 200
ADDRESS 1.2.3.5
ENTRY_BEGIN
MATCH opcode qname qtype
REPLY QR AA NOERROR
SECTION QUESTION
www.example.com. IN A
SECTION ANSWER
www.example.com. 10 IN CNAME example.foo.com.
ENTRY_END
RANGE_END
; ns.foo.com. - later
RANGE_BEGIN 90 200
ADDRESS 1.2.3.4
ENTRY_BEGIN
MATCH opcode qname qtype ednsdata
REPLY QR AA NOERROR
SECTION QUESTION
example.foo.com. IN A
SECTION ANSWER
example.foo.com. 10 IN A 1.2.3.6
SECTION ADDITIONAL
HEX_EDNSDATA_BEGIN
; client is 127.0.0.1
00 08 ; OPC
00 07 ; option length
00 01 ; Family
11 00 ; source mask, scopemask
7f 00 00 ; address
HEX_EDNSDATA_END
ENTRY_END
RANGE_END
; make time not 0
STEP 2 TIME_PASSES ELAPSE 212
; Get an entry in cache.
STEP 4 QUERY
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
www.example.com. IN A
ENTRY_END
; get the answer for it
STEP 10 CHECK_ANSWER
ENTRY_BEGIN
MATCH all ttl
REPLY QR RD RA NOERROR
SECTION QUESTION
www.example.com. IN A
SECTION ANSWER
www.example.com. 10 IN CNAME www.initial.com.
www.initial.com. 10 IN A 1.2.3.4
ENTRY_END
; now valid in cache and valid in cachedb, without subnet.
STEP 30 TIME_PASSES ELAPSE 20
; now the cache and cachedb have an expired entry.
; the upstream is updated to CNAME to a subnet zone A record.
STEP 40 QUERY ADDRESS 127.0.0.1
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
www.example.com. IN A
ENTRY_END
; the expired answer, while the ECS answer is looked up.
STEP 50 CHECK_ANSWER
ENTRY_BEGIN
MATCH all ttl
REPLY QR RD RA NOERROR
SECTION QUESTION
www.example.com. IN A
SECTION ANSWER
www.example.com. 30 IN CNAME www.initial.com.
www.initial.com. 30 IN A 1.2.3.4
ENTRY_END
; check that subnet has the query in cache.
STEP 58 TIME_PASSES ELAPSE 2
STEP 60 QUERY ADDRESS 127.0.0.1
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
www.example.com. IN A
ENTRY_END
STEP 70 CHECK_ANSWER
ENTRY_BEGIN
MATCH all
REPLY QR RD RA NOERROR
SECTION QUESTION
www.example.com. IN A
SECTION ANSWER
www.example.com. 8 IN CNAME example.foo.com.
example.foo.com. 8 IN A 1.2.3.5
ENTRY_END
; everything is expired, cache, subnetcache and cachedb.
STEP 80 TIME_PASSES ELAPSE 20
STEP 90 QUERY ADDRESS 127.0.0.1
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
www.example.com. IN A
ENTRY_END
STEP 100 CHECK_ANSWER
ENTRY_BEGIN
MATCH all
REPLY QR RD RA NOERROR
SECTION QUESTION
www.example.com. IN A
SECTION ANSWER
www.example.com. 10 IN CNAME example.foo.com.
example.foo.com. 10 IN A 1.2.3.6
ENTRY_END
; see the entry now in cache, from the subnetcache.
STEP 142 TIME_PASSES ELAPSE 2
STEP 150 QUERY ADDRESS 127.0.0.1
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
www.example.com. IN A
ENTRY_END
STEP 160 CHECK_ANSWER
ENTRY_BEGIN
MATCH all
REPLY QR RD RA NOERROR
SECTION QUESTION
www.example.com. IN A
SECTION ANSWER
www.example.com. 8 IN CNAME example.foo.com.
example.foo.com. 8 IN A 1.2.3.6
ENTRY_END
SCENARIO_END

322
testdata/cachedb_subnet_expired.crpl vendored Normal file
View file

@ -0,0 +1,322 @@
; config options
server:
target-fetch-policy: "0 0 0 0 0"
qname-minimisation: no
minimal-responses: no
serve-expired: yes
serve-expired-reply-ttl: 30
; at least one second, so we can time skip past the timer in the
; testbound script steps, but also reply within the time.
serve-expired-client-timeout: 1200
send-client-subnet: 1.2.3.4
max-client-subnet-ipv4: 17
; subnetcache is to the left of cachedb, because it sets no cache
; store for edns subnet content for modules to the right of it.
; this keeps subnet content out of cachedb as global content.
module-config: "subnetcache cachedb iterator"
discard-timeout: 3000
cachedb:
backend: "testframe"
secret-seed: "testvalue"
cachedb-check-when-serve-expired: yes
stub-zone:
name: "."
stub-addr: 193.0.14.129
CONFIG_END
SCENARIO_BEGIN Test cachedb, subnet and serve-expired-client-timeout.
; K.ROOT-SERVERS.NET.
RANGE_BEGIN 0 400
ADDRESS 193.0.14.129
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
REPLY QR NOERROR
SECTION QUESTION
. IN NS
SECTION ANSWER
. IN NS K.ROOT-SERVERS.NET.
SECTION ADDITIONAL
K.ROOT-SERVERS.NET. IN A 193.0.14.129
ENTRY_END
ENTRY_BEGIN
MATCH opcode subdomain
ADJUST copy_id copy_query
REPLY QR NOERROR
SECTION QUESTION
com. IN NS
SECTION AUTHORITY
com. IN NS a.gtld-servers.net.
SECTION ADDITIONAL
a.gtld-servers.net. IN A 192.5.6.30
ENTRY_END
RANGE_END
; a.gtld-servers.net.
RANGE_BEGIN 0 400
ADDRESS 192.5.6.30
ENTRY_BEGIN
MATCH opcode subdomain
ADJUST copy_id copy_query
REPLY QR NOERROR
SECTION QUESTION
example.com. IN NS
SECTION AUTHORITY
example.com. IN NS ns2.example.com.
SECTION ADDITIONAL
ns2.example.com. IN A 1.2.3.5
ENTRY_END
ENTRY_BEGIN
MATCH opcode subdomain
ADJUST copy_id copy_query
REPLY QR NOERROR
SECTION QUESTION
foo.com. IN NS
SECTION AUTHORITY
foo.com. IN NS ns.foo.com.
SECTION ADDITIONAL
ns.foo.com. IN A 1.2.3.4
ENTRY_END
RANGE_END
; ns2.example.com.
RANGE_BEGIN 0 30
ADDRESS 1.2.3.5
ENTRY_BEGIN
MATCH opcode qname qtype
REPLY QR AA NOERROR
SECTION QUESTION
www.example.com. IN A
SECTION ANSWER
www.example.com. 10 IN A 1.2.3.4
ENTRY_END
RANGE_END
; ns2.example.com. - after change
RANGE_BEGIN 40 100
ADDRESS 1.2.3.5
ENTRY_BEGIN
MATCH opcode qname qtype
REPLY QR AA NOERROR
SECTION QUESTION
www.example.com. IN A
SECTION ANSWER
www.example.com. 10 IN CNAME example.foo.com.
ENTRY_END
RANGE_END
; ns.foo.com.
RANGE_BEGIN 40 100
ADDRESS 1.2.3.4
ENTRY_BEGIN
MATCH opcode qname qtype ednsdata
REPLY QR AA NOERROR
SECTION QUESTION
example.foo.com. IN A
SECTION ANSWER
example.foo.com. 10 IN A 1.2.3.5
SECTION ADDITIONAL
HEX_EDNSDATA_BEGIN
; client is 127.0.0.1
00 08 ; OPC
00 07 ; option length
00 01 ; Family
11 00 ; source mask, scopemask
7f 00 00 ; address
HEX_EDNSDATA_END
ENTRY_END
RANGE_END
; ns2.example.com. and ns.foo.com - no answer in 110-130.
; ns2.example.com. - later
RANGE_BEGIN 140 200
ADDRESS 1.2.3.5
ENTRY_BEGIN
MATCH opcode qname qtype
REPLY QR AA NOERROR
SECTION QUESTION
www.example.com. IN A
SECTION ANSWER
www.example.com. 10 IN CNAME example.foo.com.
ENTRY_END
RANGE_END
; ns.foo.com. - later
RANGE_BEGIN 140 200
ADDRESS 1.2.3.4
ENTRY_BEGIN
MATCH opcode qname qtype ednsdata
REPLY QR AA NOERROR
SECTION QUESTION
example.foo.com. IN A
SECTION ANSWER
example.foo.com. 10 IN A 1.2.3.6
SECTION ADDITIONAL
HEX_EDNSDATA_BEGIN
; client is 127.0.0.1
00 08 ; OPC
00 07 ; option length
00 01 ; Family
11 00 ; source mask, scopemask
7f 00 00 ; address
HEX_EDNSDATA_END
ENTRY_END
RANGE_END
; make time not 0
STEP 2 TIME_PASSES ELAPSE 212
; Get an entry in cache.
STEP 4 QUERY
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
www.example.com. IN A
ENTRY_END
; get the answer for it
STEP 10 CHECK_ANSWER
ENTRY_BEGIN
MATCH all
REPLY QR RD RA NOERROR
SECTION QUESTION
www.example.com. IN A
SECTION ANSWER
www.example.com. 10 IN A 1.2.3.4
ENTRY_END
; now valid in cache and valid in cachedb, without subnet.
STEP 20 FLUSH_MESSAGE www.example.com. IN A
STEP 30 TIME_PASSES ELAPSE 20
; now nothing in cache and cachedb has an expired entry.
; the upstream is updated to CNAME to a subnet zone A record.
STEP 40 QUERY ADDRESS 127.0.0.1
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
www.example.com. IN A
ENTRY_END
STEP 50 CHECK_ANSWER
ENTRY_BEGIN
MATCH all
REPLY QR RD RA NOERROR
SECTION QUESTION
www.example.com. IN A
SECTION ANSWER
www.example.com. 10 IN CNAME example.foo.com.
example.foo.com. 10 IN A 1.2.3.5
ENTRY_END
; check that subnet has the query in cache.
STEP 58 TIME_PASSES ELAPSE 2
STEP 60 QUERY ADDRESS 127.0.0.1
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
www.example.com. IN A
ENTRY_END
STEP 70 CHECK_ANSWER
ENTRY_BEGIN
MATCH all
REPLY QR RD RA NOERROR
SECTION QUESTION
www.example.com. IN A
SECTION ANSWER
www.example.com. 8 IN CNAME example.foo.com.
example.foo.com. 8 IN A 1.2.3.5
ENTRY_END
; everything is expired, cache, subnetcache and cachedb.
STEP 80 TIME_PASSES ELAPSE 20
; send the query, reply arrives quickly.
STEP 90 QUERY ADDRESS 127.0.0.1
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
www.example.com. IN A
ENTRY_END
STEP 100 CHECK_ANSWER
ENTRY_BEGIN
MATCH all
REPLY QR RD RA NOERROR
SECTION QUESTION
www.example.com. IN A
SECTION ANSWER
www.example.com. 10 IN CNAME example.foo.com.
example.foo.com. 10 IN A 1.2.3.5
ENTRY_END
; everything is expired, cache, subnetcache and cachedb.
STEP 110 TIME_PASSES ELAPSE 20
; send the query, but the reply is late, and there is expired data,
; the expired entry from cachedb is used to reply with.
STEP 120 QUERY ADDRESS 127.0.0.1
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
www.example.com. IN A
ENTRY_END
STEP 122 TIME_PASSES ELAPSE 2
; But the entry has been deleted, so it cannot be served, the reply
; at step 141 is returned instead.
;STEP 130 CHECK_ANSWER
;ENTRY_BEGIN
;MATCH all
;REPLY QR RD RA NOERROR
;SECTION QUESTION
;www.example.com. IN A
;SECTION ANSWER
;www.example.com. 30 IN A 1.2.3.4
;ENTRY_END
; reply can flow again.
STEP 140 TRAFFIC
STEP 141 CHECK_ANSWER
ENTRY_BEGIN
MATCH all
REPLY QR RD RA NOERROR
SECTION QUESTION
www.example.com. IN A
SECTION ANSWER
www.example.com. 10 IN CNAME example.foo.com.
example.foo.com. 10 IN A 1.2.3.6
ENTRY_END
; see the entry now in cache, from the subnetcache.
STEP 142 TIME_PASSES ELAPSE 2
STEP 150 QUERY ADDRESS 127.0.0.1
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
www.example.com. IN A
ENTRY_END
STEP 160 CHECK_ANSWER
ENTRY_BEGIN
MATCH all
REPLY QR RD RA NOERROR
SECTION QUESTION
www.example.com. IN A
SECTION ANSWER
www.example.com. 8 IN CNAME example.foo.com.
example.foo.com. 8 IN A 1.2.3.6
ENTRY_END
SCENARIO_END

View file

@ -0,0 +1,229 @@
; config options
server:
target-fetch-policy: "0 0 0 0 0"
qname-minimisation: no
minimal-responses: no
serve-expired: yes
serve-expired-reply-ttl: 30
; at least one second, so we can time skip past the timer in the
; testbound script steps, but also reply within the time.
serve-expired-client-timeout: 1200
send-client-subnet: 1.2.3.4
max-client-subnet-ipv4: 17
; subnetcache is to the left of cachedb, because it sets no cache
; store for edns subnet content for modules to the right of it.
; this keeps subnet content out of cachedb as global content.
module-config: "subnetcache cachedb iterator"
cachedb:
backend: "testframe"
secret-seed: "testvalue"
cachedb-check-when-serve-expired: yes
stub-zone:
name: "."
stub-addr: 193.0.14.129
CONFIG_END
SCENARIO_BEGIN Test cachedb, subnet and serve-expired, with a domain change from global to subnet with serve-expired-client-timeout enabled.
; So the CNAME first points to a global record, then points to a subnet record.
; K.ROOT-SERVERS.NET.
RANGE_BEGIN 0 400
ADDRESS 193.0.14.129
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
REPLY QR NOERROR
SECTION QUESTION
. IN NS
SECTION ANSWER
. IN NS K.ROOT-SERVERS.NET.
SECTION ADDITIONAL
K.ROOT-SERVERS.NET. IN A 193.0.14.129
ENTRY_END
ENTRY_BEGIN
MATCH opcode subdomain
ADJUST copy_id copy_query
REPLY QR NOERROR
SECTION QUESTION
com. IN NS
SECTION AUTHORITY
com. IN NS a.gtld-servers.net.
SECTION ADDITIONAL
a.gtld-servers.net. IN A 192.5.6.30
ENTRY_END
RANGE_END
; a.gtld-servers.net.
RANGE_BEGIN 0 400
ADDRESS 192.5.6.30
ENTRY_BEGIN
MATCH opcode subdomain
ADJUST copy_id copy_query
REPLY QR NOERROR
SECTION QUESTION
example.com. IN NS
SECTION AUTHORITY
example.com. IN NS ns2.example.com.
SECTION ADDITIONAL
ns2.example.com. IN A 1.2.3.5
ENTRY_END
ENTRY_BEGIN
MATCH opcode subdomain
ADJUST copy_id copy_query
REPLY QR NOERROR
SECTION QUESTION
foo.com. IN NS
SECTION AUTHORITY
foo.com. IN NS ns.foo.com.
SECTION ADDITIONAL
ns.foo.com. IN A 1.2.3.4
ENTRY_END
ENTRY_BEGIN
MATCH opcode subdomain
ADJUST copy_id copy_query
REPLY QR NOERROR
SECTION QUESTION
initial.com. IN NS
SECTION AUTHORITY
initial.com. IN NS ns.initial.com.
SECTION ADDITIONAL
ns.initial.com. IN A 1.2.3.6
ENTRY_END
RANGE_END
; ns2.example.com.
RANGE_BEGIN 0 30
ADDRESS 1.2.3.5
ENTRY_BEGIN
MATCH opcode qname qtype
REPLY QR AA NOERROR
SECTION QUESTION
www.example.com. IN A
SECTION ANSWER
www.example.com. 10 IN CNAME www.initial.com.
ENTRY_END
RANGE_END
; ns2.example.com. - after change
RANGE_BEGIN 40 100
ADDRESS 1.2.3.5
ENTRY_BEGIN
MATCH opcode qname qtype
REPLY QR AA NOERROR
SECTION QUESTION
www.example.com. IN A
SECTION ANSWER
www.example.com. 10 IN CNAME example.foo.com.
ENTRY_END
RANGE_END
; ns.initial.com.
RANGE_BEGIN 0 400
ADDRESS 1.2.3.6
ENTRY_BEGIN
MATCH opcode qname qtype
REPLY QR AA NOERROR
SECTION QUESTION
www.initial.com. IN A
SECTION ANSWER
www.initial.com. 10 IN A 1.2.3.4
ENTRY_END
RANGE_END
; ns.foo.com.
RANGE_BEGIN 40 100
ADDRESS 1.2.3.4
ENTRY_BEGIN
MATCH opcode qname qtype ednsdata
REPLY QR AA NOERROR
SECTION QUESTION
example.foo.com. IN A
SECTION ANSWER
example.foo.com. 10 IN A 1.2.3.5
SECTION ADDITIONAL
HEX_EDNSDATA_BEGIN
; client is 127.0.0.1
00 08 ; OPC
00 07 ; option length
00 01 ; Family
11 00 ; source mask, scopemask
7f 00 00 ; address
HEX_EDNSDATA_END
ENTRY_END
RANGE_END
; make time not 0
STEP 2 TIME_PASSES ELAPSE 212
; Get an entry in cache.
STEP 4 QUERY
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
www.example.com. IN A
ENTRY_END
; get the answer for it
STEP 10 CHECK_ANSWER
ENTRY_BEGIN
MATCH all ttl
REPLY QR RD RA NOERROR
SECTION QUESTION
www.example.com. IN A
SECTION ANSWER
www.example.com. 10 IN CNAME www.initial.com.
www.initial.com. 10 IN A 1.2.3.4
ENTRY_END
; now valid in cache and valid in cachedb, without subnet.
STEP 30 TIME_PASSES ELAPSE 20
; now the cache and cachedb have an expired entry.
; the upstream is updated to CNAME to a subnet zone A record.
STEP 40 QUERY ADDRESS 127.0.0.1
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
www.example.com. IN A
ENTRY_END
; this answer is returned by the subnet lookup within
; the serve-expired-client-timeout.
STEP 50 CHECK_ANSWER
ENTRY_BEGIN
MATCH all ttl
REPLY QR RD RA NOERROR
SECTION QUESTION
www.example.com. IN A
SECTION ANSWER
www.example.com. 10 IN CNAME example.foo.com.
example.foo.com. 10 IN A 1.2.3.5
ENTRY_END
; check that subnet has the query in cache.
STEP 58 TIME_PASSES ELAPSE 2
STEP 60 QUERY ADDRESS 127.0.0.1
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
www.example.com. IN A
ENTRY_END
STEP 70 CHECK_ANSWER
ENTRY_BEGIN
MATCH all
REPLY QR RD RA NOERROR
SECTION QUESTION
www.example.com. IN A
SECTION ANSWER
www.example.com. 8 IN CNAME example.foo.com.
example.foo.com. 8 IN A 1.2.3.5
ENTRY_END
SCENARIO_END

View file

@ -12,6 +12,8 @@ server:
do-not-query-localhost: no
local-zone: "example.net." redirect
local-data: "example.net. IN A 10.20.30.41"
serve-expired: yes
serve-expired-reply-ttl: 30
remote-control:
control-enable: yes
control-interface: 127.0.0.1

View file

@ -81,6 +81,46 @@ for x in q1 q2 q3 q4 5 q6 q7 q8 q9 q10; do
fi
done
echo "> query for a short ttl record"
dig @127.0.0.1 -p $UNBOUND_PORT short.example.com.
echo "> wait for log to happen on timer"
sleep 3
if grep "short.example.com" tap.log >/dev/null; then :; else sleep 1; fi
if grep "short.example.com" tap.log >/dev/null; then :; else sleep 1; fi
if grep "short.example.com" tap.log >/dev/null; then :; else sleep 1; fi
if grep "short.example.com" tap.log >/dev/null; then :; else sleep 1; fi
if grep "short.example.com" tap.log >/dev/null; then :; else sleep 1; fi
if grep "short.example.com" tap.log >/dev/null; then :; else sleep 10; fi
if grep "short.example.com" tap.log; then echo "yes it is in tap.log";
else
echo "short.example.com. information not in tap.log"
echo "failed"
echo "> cat logfiles"
cat tap.log
cat tap.errlog
cat fwd.log
cat unbound.log
echo "Not OK"
exit 1
fi
echo "> query again for the now expired record"
dig @127.0.0.1 -p $UNBOUND_PORT short.example.com.
echo "> wait for log to happen on timer"
sleep 3
num_responses=`grep "short.example.com" tap.log | grep CLIENT_RESPONSE | wc -l`
# Responses should be 2 for the 2 distinct dig commands.
if test $num_responses -gt 2; then
echo "Duplicate client responses for short.example.com. in tap.log"
echo "failed"
echo "> cat logfiles"
cat tap.log
cat tap.errlog
cat fwd.log
cat unbound.log
echo "Not OK"
exit 1
fi
echo "> cat logfiles"
cat tap.log
cat tap.errlog

View file

@ -12,6 +12,16 @@ SECTION ANSWER
www IN A 10.20.30.40
ENTRY_END
ENTRY_BEGIN
MATCH opcode qtype qname
REPLY QR AA NOERROR
ADJUST copy_id
SECTION QUESTION
short IN A
SECTION ANSWER
short 2 IN A 10.20.30.40
ENTRY_END
ENTRY_BEGIN
MATCH opcode qtype qname
REPLY QR AA SERVFAIL

View file

@ -11,6 +11,7 @@ server:
chroot: ""
username: ""
do-not-query-localhost: no
discard-timeout: 3000 # testns uses sleep=2
http-query-buffer-size: 1G
http-response-buffer-size: 1G
http-max-streams: 200

View file

@ -11,6 +11,7 @@ server:
chroot: ""
username: ""
do-not-query-localhost: no
discard-timeout: 3000 # testns uses sleep=2
http-query-buffer-size: 1G
http-response-buffer-size: 1G
http-max-streams: 200

View file

@ -11,6 +11,7 @@ server:
chroot: ""
username: ""
do-not-query-localhost: no
discard-timeout: 3000 # testns uses sleep=2
http-query-buffer-size: 1G
http-response-buffer-size: 1G
http-max-streams: 200

View file

@ -11,6 +11,7 @@ server:
num-queries-per-thread: 1024
use-syslog: no
do-not-query-localhost: no
discard-timeout: 3000 # testns uses sleep=2
forward-zone:
name: "."
forward-addr: "127.0.0.1@@TOPORT@"

View file

@ -145,31 +145,6 @@ ns.example.com. IN A 1.2.3.4
ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854}
ENTRY_END
; response to query of interest
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
REPLY QR NOERROR
SECTION QUESTION
www.example.com. IN CNAME
SECTION ANSWER
www.example.com. IN CNAME www.example.net.
www.example.com. 3600 IN RRSIG CNAME DSA 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFGcJxnNxpWCBzXejiSdl4p1BKRMnAhUApoJrugVBRwFgAoYAhhqlZFac7fE= ;{id = 2854}
SECTION AUTHORITY
SECTION ADDITIONAL
ENTRY_END
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
REPLY QR NOERROR
SECTION QUESTION
www2.example.com. IN A
SECTION ANSWER
www2.example.com. 3600 IN CNAME www.example.net.
www2.example.com. 3600 IN RRSIG CNAME 3 3 3600 20070926135752 20070829135752 2854 example.com. AGgh6pDCL7VF0uJablClW7cgvsPuNzpHZ+M7nZIwi61+0RPhFZLHcN4=
ENTRY_END
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
@ -218,20 +193,6 @@ ns.example.net. IN A 1.2.3.5
ns.example.net. 3600 IN RRSIG A RSASHA1 3 3600 20070926134150 20070829134150 30899 example.net. x+tQMC9FhzT7Fcy1pM5NrOC7E8nLd7THPI3C6ie4EwL8PrxllqlR3q/DKB0d/m0qCOPcgN6HFOYURV1s4uAcsw== ;{id = 30899}
ENTRY_END
; response to query of interest
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
REPLY QR NOERROR
SECTION QUESTION
www.example.net. IN A
SECTION ANSWER
www.example.net. IN A 11.12.13.14
www.example.net. 3600 IN RRSIG A 5 3 3600 20070926134150 20070829134150 30899 example.net. CPxF5hK9Kg5eT7W6LgZwr0ePYEm9HMcSY4vvqCS6gDWB4X9jvXLCfBkCLhsNybPBpGWlsLi5wM6MTdJXuPpsRA== ;{id = 30899}
SECTION AUTHORITY
SECTION ADDITIONAL
ENTRY_END
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id

View file

@ -0,0 +1,256 @@
; config options
server:
target-fetch-policy: "0 0 0 0 0"
qname-minimisation: "no"
minimal-responses: no
stub-zone:
name: "."
stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
CONFIG_END
SCENARIO_BEGIN Test that deep delegation from the parent deletes intermediate delegations to avoid triggering the ghost domain countermeasure.
; K.ROOT-SERVERS.NET.
RANGE_BEGIN 0 19
ADDRESS 193.0.14.129
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
REPLY QR NOERROR
SECTION QUESTION
. IN NS
SECTION ANSWER
. 86400 IN NS K.ROOT-SERVERS.NET.
SECTION ADDITIONAL
K.ROOT-SERVERS.NET. 86400 IN A 193.0.14.129
ENTRY_END
; we will explicitly ask for this
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id copy_query
REPLY QR NOERROR
SECTION QUESTION
com. IN NS
SECTION AUTHORITY
com. 10 IN NS a.gtld-servers.net.
SECTION ADDITIONAL
a.gtld-servers.net. 86400 IN A 192.5.6.30
ENTRY_END
ENTRY_BEGIN
MATCH opcode subdomain
ADJUST copy_id copy_query
REPLY QR NOERROR
SECTION QUESTION
example.com. IN NS
SECTION AUTHORITY
example.com. 86400 IN NS ns.example.com.
SECTION ADDITIONAL
ns.example.com. 86400 IN A 1.2.3.4
ENTRY_END
RANGE_END
; a.gtld-servers.net.
RANGE_BEGIN 0 100
ADDRESS 192.5.6.30
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
REPLY QR NOERROR
SECTION QUESTION
com. IN NS
SECTION ANSWER
com. 10 IN NS a.gtld-servers.net.
SECTION ADDITIONAL
a.gtld-servers.net. 86400 IN A 192.5.6.30
ENTRY_END
ENTRY_BEGIN
MATCH opcode subdomain
ADJUST copy_id copy_query
REPLY QR NOERROR
SECTION QUESTION
example.com. IN NS
SECTION AUTHORITY
example.com. IN NS ns.example.com.
SECTION ADDITIONAL
ns.example.com. IN A 1.2.3.4
ENTRY_END
RANGE_END
; ns.example.com.
RANGE_BEGIN 0 100
ADDRESS 1.2.3.4
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
REPLY QR NOERROR
SECTION QUESTION
example.com. IN NS
SECTION ANSWER
example.com. IN NS ns.example.com.
SECTION ADDITIONAL
ns.example.com. IN A 1.2.3.4
ENTRY_END
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
REPLY QR NOERROR
SECTION QUESTION
ns.example.com. IN A
SECTION ANSWER
ns.example.com. IN A 1.2.3.4
SECTION AUTHORITY
example.com. IN NS ns.example.com.
ENTRY_END
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
REPLY QR NOERROR
SECTION QUESTION
ns.example.com. IN AAAA
SECTION AUTHORITY
example.com. IN NS ns.example.com.
SECTION ADDITIONAL
ns.example.com. IN A 1.2.3.4
ENTRY_END
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
REPLY QR NOERROR
SECTION QUESTION
a.example.com. IN A
SECTION ANSWER
a.example.com. IN A 10.20.30.40
SECTION AUTHORITY
example.com. IN NS ns.example.com.
SECTION ADDITIONAL
ns.example.com IN A 1.2.3.4
ENTRY_END
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
REPLY QR NOERROR
SECTION QUESTION
b.example.com. IN A
SECTION ANSWER
b.example.com. IN A 10.20.30.40
SECTION AUTHORITY
example.com. IN NS ns.example.com.
SECTION ADDITIONAL
ns.example.com IN A 1.2.3.4
ENTRY_END
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
REPLY QR NOERROR
SECTION QUESTION
c.example.com. IN A
SECTION ANSWER
c.example.com. IN A 10.20.30.40
SECTION AUTHORITY
example.com. IN NS ns.example.com.
SECTION ADDITIONAL
ns.example.com IN A 1.2.3.4
ENTRY_END
RANGE_END
; get the com. IN NS delegation in cache
STEP 0 QUERY
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
com. IN NS
ENTRY_END
STEP 1 CHECK_ANSWER
ENTRY_BEGIN
MATCH all ttl
REPLY QR RD RA NOERROR
SECTION QUESTION
com. IN NS
SECTION ANSWER
com. 10 IN NS a.gtld-servers.net.
ENTRY_END
STEP 2 QUERY
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
a.example.com. IN A
ENTRY_END
STEP 3 CHECK_ANSWER
ENTRY_BEGIN
MATCH all
REPLY QR RD RA NOERROR
SECTION QUESTION
a.example.com. IN A
SECTION ANSWER
a.example.com. IN A 10.20.30.40
SECTION AUTHORITY
example.com. IN NS ns.example.com.
SECTION ADDITIONAL
ns.example.com. IN A 1.2.3.4
ENTRY_END
; time passes for com. IN NS to expire.
STEP 9 TIME_PASSES ELAPSE 11
; the following query should go to the root instead of example.com. IN NS
; because com. IN NS is expired
STEP 10 QUERY
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
b.example.com. IN A
ENTRY_END
; root replies with the example.com IN NS delegation
; the expired com. IN NS delegation should be deleted
STEP 12 CHECK_ANSWER
ENTRY_BEGIN
MATCH all
REPLY QR RD RA NOERROR
SECTION QUESTION
b.example.com. IN A
SECTION ANSWER
b.example.com. IN A 10.20.30.40
SECTION AUTHORITY
example.com. IN NS ns.example.com.
SECTION ADDITIONAL
ns.example.com. IN A 1.2.3.4
ENTRY_END
; root is offline in this range.
; the following query should go straight to the example.com. IN NS delegation
; because the expired com. IN NS should not be in the cache anymore
STEP 20 QUERY
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
c.example.com. IN A
ENTRY_END
STEP 21 CHECK_ANSWER
ENTRY_BEGIN
MATCH all
REPLY QR RD RA NOERROR
SECTION QUESTION
c.example.com. IN A
SECTION ANSWER
c.example.com. IN A 10.20.30.40
SECTION AUTHORITY
example.com. IN NS ns.example.com.
SECTION ADDITIONAL
ns.example.com. IN A 1.2.3.4
ENTRY_END
SCENARIO_END

View file

@ -3,6 +3,7 @@ server:
target-fetch-policy: "0 0 0 0 0"
qname-minimisation: "no"
minimal-responses: no
discard-timeout: 86400
stub-zone:
name: "."

67
testdata/local_cnameother.rpl vendored Normal file
View file

@ -0,0 +1,67 @@
; config options
server:
local-zone: "a." static
local-data: "myd.a. NSEC myd2.a. CNAME NSEC"
local-data: "myd.a. CNAME myd.target.a."
; Switches the types first one then the other.
local-data: "myd2.a. CNAME myd2.target.a."
local-data: "myd2.a. NSEC myd3.a. CNAME NSEC"
stub-zone:
name: "a"
stub-addr: 1.2.3.4
CONFIG_END
SCENARIO_BEGIN Test local data queries with CNAME and other data.
RANGE_BEGIN 0 1000
ADDRESS 1.2.3.4
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
REPLY QR NOERROR
SECTION QUESTION
www.refuse.top. IN A
SECTION ANSWER
www.refuse.top. IN A 5.5.5.5
ENTRY_END
RANGE_END
; local data query for type next to CNAME, the specific type should
; be preferred over the CNAME.
STEP 10 QUERY
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
myd.a. IN NSEC
ENTRY_END
STEP 20 CHECK_ANSWER
ENTRY_BEGIN
MATCH all
REPLY QR RD RA AA
SECTION QUESTION
myd.a. IN NSEC
SECTION ANSWER
myd.a. NSEC myd2.a. CNAME NSEC
ENTRY_END
STEP 30 QUERY
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
myd2.a. IN NSEC
ENTRY_END
STEP 40 CHECK_ANSWER
ENTRY_BEGIN
MATCH all
REPLY QR RD RA AA
SECTION QUESTION
myd2.a. IN NSEC
SECTION ANSWER
myd2.a. NSEC myd3.a. CNAME NSEC
ENTRY_END
SCENARIO_END

269
testdata/rpz_clientip_override.rpl vendored Normal file
View file

@ -0,0 +1,269 @@
; config options
server:
module-config: "respip validator iterator"
target-fetch-policy: "0 0 0 0 0"
qname-minimisation: no
access-control: 192.0.0.0/8 allow
rpz:
name: "rpz.example.com."
rpz-log: yes
rpz-log-name: "rpz.example.com"
rpz-action-override: "nxdomain"
zonefile:
TEMPFILE_NAME rpz.example.com
TEMPFILE_CONTENTS rpz.example.com
$ORIGIN example.com.
rpz 3600 IN SOA ns1.rpz.example.com. hostmaster.rpz.example.com. (
1379078166 28800 7200 604800 7200 )
3600 IN NS ns1.rpz.example.com.
3600 IN NS ns2.rpz.example.com.
$ORIGIN rpz.example.com.
32.1.5.0.192.rpz-client-ip CNAME rpz-passthru.
32.2.5.0.192.rpz-client-ip A 1.2.3.5
TEMPFILE_END
rpz:
name: "rpz2.example.com."
rpz-log: yes
rpz-log-name: "rpz2.example.com"
rpz-action-override: "nodata"
zonefile:
TEMPFILE_NAME rpz2.example.com
TEMPFILE_CONTENTS rpz2.example.com
$ORIGIN example.com.
rpz2 3600 IN SOA ns1.rpz2.example.com. hostmaster.rpz2.example.com. (
1379078166 28800 7200 604800 7200 )
3600 IN NS ns1.rpz2.example.com.
3600 IN NS ns2.rpz2.example.com.
$ORIGIN rpz2.example.com.
32.4.5.0.192.rpz-client-ip A 1.2.3.5
TEMPFILE_END
rpz:
name: "rpz3.example.com."
rpz-log: yes
rpz-log-name: "rpz3.example.com"
rpz-action-override: "passthru"
zonefile:
TEMPFILE_NAME rpz3.example.com
TEMPFILE_CONTENTS rpz3.example.com
$ORIGIN example.com.
rpz3 3600 IN SOA ns1.rpz3.example.com. hostmaster.rpz3.example.com. (
1379078166 28800 7200 604800 7200 )
3600 IN NS ns1.rpz3.example.com.
3600 IN NS ns2.rpz3.example.com.
$ORIGIN rpz3.example.com.
32.5.5.0.192.rpz-client-ip A 1.2.3.5
TEMPFILE_END
rpz:
name: "rpz4.example.com."
rpz-log: yes
rpz-log-name: "rpz4.example.com"
rpz-action-override: "drop"
zonefile:
TEMPFILE_NAME rpz4.example.com
TEMPFILE_CONTENTS rpz4.example.com
$ORIGIN example.com.
rpz4 3600 IN SOA ns1.rpz4.example.com. hostmaster.rpz4.example.com. (
1379078166 28800 7200 604800 7200 )
3600 IN NS ns1.rpz4.example.com.
3600 IN NS ns2.rpz4.example.com.
$ORIGIN rpz4.example.com.
32.5.5.0.192.rpz-client-ip A 1.2.3.5
32.6.5.0.192.rpz-client-ip A 1.2.3.5
TEMPFILE_END
rpz:
name: "rpz5.example.com."
rpz-log: yes
rpz-log-name: "rpz5.example.com"
rpz-action-override: "cname"
rpz-cname-override: "target.a"
zonefile:
TEMPFILE_NAME rpz5.example.com
TEMPFILE_CONTENTS rpz5.example.com
$ORIGIN example.com.
rpz5 3600 IN SOA ns1.rpz5.example.com. hostmaster.rpz5.example.com. (
1379078166 28800 7200 604800 7200 )
3600 IN NS ns1.rpz5.example.com.
3600 IN NS ns2.rpz5.example.com.
$ORIGIN rpz5.example.com.
32.7.5.0.192.rpz-client-ip A 1.2.3.5
TEMPFILE_END
rpz:
name: "rpz6.example.com."
rpz-log: yes
rpz-log-name: "rpz6.example.com"
rpz-action-override: "disabled"
zonefile:
TEMPFILE_NAME rpz6.example.com
TEMPFILE_CONTENTS rpz6.example.com
$ORIGIN example.com.
rpz6 3600 IN SOA ns1.rpz6.example.com. hostmaster.rpz6.example.com. (
1379078166 28800 7200 604800 7200 )
3600 IN NS ns1.rpz6.example.com.
3600 IN NS ns2.rpz6.example.com.
$ORIGIN rpz6.example.com.
32.8.5.0.192.rpz-client-ip A 1.2.3.5
TEMPFILE_END
stub-zone:
name: "a."
stub-addr: 10.20.30.40
CONFIG_END
SCENARIO_BEGIN Test RPZ action override with trigger from clientip.
; a.
RANGE_BEGIN 0 1000
ADDRESS 10.20.30.40
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
REPLY QR NOERROR
SECTION QUESTION
d.a. IN A
SECTION ANSWER
d.a. IN A 1.2.3.4
ENTRY_END
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
REPLY QR NOERROR
SECTION QUESTION
target.a. IN A
SECTION ANSWER
target.a. IN A 1.2.3.6
ENTRY_END
RANGE_END
STEP 10 QUERY ADDRESS 192.0.5.2
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
d.a. IN A
ENTRY_END
STEP 11 CHECK_ANSWER
ENTRY_BEGIN
MATCH all
REPLY QR RD RA AA NXDOMAIN
SECTION QUESTION
d.a. IN A
SECTION ANSWER
ENTRY_END
STEP 20 QUERY ADDRESS 192.0.5.1
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
d.a. IN A
ENTRY_END
STEP 21 CHECK_ANSWER
ENTRY_BEGIN
MATCH all
REPLY QR RD RA AA NXDOMAIN
SECTION QUESTION
d.a. IN A
SECTION ANSWER
ENTRY_END
STEP 30 QUERY ADDRESS 192.0.5.3
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
d.a. IN A
ENTRY_END
STEP 31 CHECK_ANSWER
ENTRY_BEGIN
MATCH all
REPLY QR RD RA NOERROR
SECTION QUESTION
d.a. IN A
SECTION ANSWER
d.a. IN A 1.2.3.4
ENTRY_END
STEP 40 QUERY ADDRESS 192.0.5.4
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
d.a. IN A
ENTRY_END
STEP 41 CHECK_ANSWER
ENTRY_BEGIN
MATCH all
REPLY QR RD RA AA NOERROR
SECTION QUESTION
d.a. IN A
SECTION ANSWER
ENTRY_END
STEP 50 QUERY ADDRESS 192.0.5.5
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
d.a. IN A
ENTRY_END
STEP 51 CHECK_ANSWER
ENTRY_BEGIN
MATCH all
REPLY QR RD RA NOERROR
SECTION QUESTION
d.a. IN A
SECTION ANSWER
d.a. IN A 1.2.3.4
ENTRY_END
STEP 60 QUERY ADDRESS 192.0.5.6
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
d.a. IN A
ENTRY_END
; dropped.
STEP 70 QUERY ADDRESS 192.0.5.7
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
d.a. IN A
ENTRY_END
STEP 71 CHECK_ANSWER
ENTRY_BEGIN
MATCH all
REPLY QR RD RA AA NOERROR
SECTION QUESTION
d.a. IN A
SECTION ANSWER
d.a. CNAME target.a.
target.a. A 1.2.3.6
ENTRY_END
STEP 80 QUERY ADDRESS 192.0.5.8
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
d.a. IN A
ENTRY_END
STEP 81 CHECK_ANSWER
ENTRY_BEGIN
MATCH all
REPLY QR RD RA NOERROR
SECTION QUESTION
d.a. IN A
SECTION ANSWER
d.a. IN A 1.2.3.4
ENTRY_END
SCENARIO_END

779
testdata/rpz_cname_handle.rpl vendored Normal file
View file

@ -0,0 +1,779 @@
; config options
server:
module-config: "respip validator iterator"
target-fetch-policy: "0 0 0 0 0"
qname-minimisation: no
access-control: 192.0.0.0/8 allow
rpz:
name: "rpz.example.com."
rpz-log: yes
rpz-log-name: "rpz.example.com"
zonefile:
TEMPFILE_NAME rpz.example.com
TEMPFILE_CONTENTS rpz.example.com
$ORIGIN example.com.
rpz 3600 IN SOA ns1.rpz.example.com. hostmaster.rpz.example.com. (
1379078166 28800 7200 604800 7200 )
3600 IN NS ns1.rpz.example.com.
3600 IN NS ns2.rpz.example.com.
$ORIGIN rpz.example.com.
www.gotham.a A 1.2.3.61
www.gotham2.a CNAME g2.target.a.
g2.target.a A 1.2.3.62
www.gotham3.a CNAME g3.target.a.
g3.target.a CNAME g3b.target.a.
g3b.target.a A 1.2.3.63
www.gotham4.a CNAME g4.target.a.
g4.target.a CNAME g4b.target.a.
g4b.target.a CNAME g4c.target.a.
g4c.target.a A 1.2.3.64
w2.gotham5.a A 1.2.3.65
w2.gotham6.a CNAME g6.target.a.
g6.target.a A 1.2.3.66
w2.gotham7.a CNAME g7.target.a.
g7.target.a CNAME g7b.target.a.
g7b.target.a A 1.2.3.66
; ns1.gotham8.a
32.48.30.20.10.rpz-nsip A 1.2.3.68
; ns1.gotham9.a
32.49.30.20.10.rpz-nsip CNAME g9.target.a.
g9.target.a A 1.2.3.69
; ns1.gotham10.a
32.50.30.20.10.rpz-nsip CNAME g10.target.a.
g10.target.a CNAME g10b.target.a.
g10b.target.a A 1.2.3.70
www.gotham11.a CNAME g11.target.a.
www.gotham12.a CNAME g12.target.a.
g12.target.a CNAME g12b.target.a.
www.gotham13.a CNAME g13.target.a.
g13.target.a CNAME g13b.target.a.
g13b.target.a CNAME g13c.target.a.
w2.gotham14.a CNAME g14.target.a.
w2.gotham15.a CNAME g15.target.a.
g15.target.a CNAME g15b.target.a.
; ns1.gotham16.a
32.56.30.20.10.rpz-nsip CNAME g16.target.a.
; ns1.gotham17.a
32.57.30.20.10.rpz-nsip CNAME g17.target.a.
g17.target.a CNAME g17b.target.a.
TEMPFILE_END
stub-zone:
name: "a."
stub-addr: 10.20.30.40
CONFIG_END
SCENARIO_BEGIN Test RPZ handling of CNAMEs.
; a.
RANGE_BEGIN 0 1000
ADDRESS 10.20.30.40
ENTRY_BEGIN
MATCH opcode subdomain
ADJUST copy_id copy_query
REPLY QR NOERROR
SECTION QUESTION
gotham5.a. IN NS
SECTION AUTHORITY
gotham5.a. NS ns1.gotham5.a.
SECTION ADDITIONAL
ns1.gotham5.a. A 10.20.30.45
ENTRY_END
ENTRY_BEGIN
MATCH opcode subdomain
ADJUST copy_id copy_query
REPLY QR NOERROR
SECTION QUESTION
gotham6.a. IN NS
SECTION AUTHORITY
gotham6.a. NS ns1.gotham6.a.
SECTION ADDITIONAL
ns1.gotham6.a. A 10.20.30.46
ENTRY_END
ENTRY_BEGIN
MATCH opcode subdomain
ADJUST copy_id copy_query
REPLY QR NOERROR
SECTION QUESTION
gotham7.a. IN NS
SECTION AUTHORITY
gotham7.a. NS ns1.gotham7.a.
SECTION ADDITIONAL
ns1.gotham7.a. A 10.20.30.47
ENTRY_END
ENTRY_BEGIN
MATCH opcode subdomain
ADJUST copy_id copy_query
REPLY QR NOERROR
SECTION QUESTION
gotham8.a. IN NS
SECTION AUTHORITY
gotham8.a. NS ns1.gotham8.a.
SECTION ADDITIONAL
ns1.gotham8.a. A 10.20.30.48
ENTRY_END
ENTRY_BEGIN
MATCH opcode subdomain
ADJUST copy_id copy_query
REPLY QR NOERROR
SECTION QUESTION
gotham9.a. IN NS
SECTION AUTHORITY
gotham9.a. NS ns1.gotham9.a.
SECTION ADDITIONAL
ns1.gotham9.a. A 10.20.30.49
ENTRY_END
ENTRY_BEGIN
MATCH opcode subdomain
ADJUST copy_id copy_query
REPLY QR NOERROR
SECTION QUESTION
gotham10.a. IN NS
SECTION AUTHORITY
gotham10.a. NS ns1.gotham10.a.
SECTION ADDITIONAL
ns1.gotham10.a. A 10.20.30.50
ENTRY_END
ENTRY_BEGIN
MATCH opcode subdomain
ADJUST copy_id copy_query
REPLY QR NOERROR
SECTION QUESTION
gotham14.a. IN NS
SECTION AUTHORITY
gotham14.a. NS ns1.gotham14.a.
SECTION ADDITIONAL
ns1.gotham14.a. A 10.20.30.54
ENTRY_END
ENTRY_BEGIN
MATCH opcode subdomain
ADJUST copy_id copy_query
REPLY QR NOERROR
SECTION QUESTION
gotham15.a. IN NS
SECTION AUTHORITY
gotham15.a. NS ns1.gotham15.a.
SECTION ADDITIONAL
ns1.gotham15.a. A 10.20.30.55
ENTRY_END
ENTRY_BEGIN
MATCH opcode subdomain
ADJUST copy_id copy_query
REPLY QR NOERROR
SECTION QUESTION
gotham16.a. IN NS
SECTION AUTHORITY
gotham16.a. NS ns1.gotham16.a.
SECTION ADDITIONAL
ns1.gotham16.a. A 10.20.30.56
ENTRY_END
ENTRY_BEGIN
MATCH opcode subdomain
ADJUST copy_id copy_query
REPLY QR NOERROR
SECTION QUESTION
gotham17.a. IN NS
SECTION AUTHORITY
gotham17.a. NS ns1.gotham17.a.
SECTION ADDITIONAL
ns1.gotham17.a. A 10.20.30.57
ENTRY_END
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
REPLY QR NOERROR
SECTION QUESTION
target.a. IN A
SECTION ANSWER
target.a. IN A 1.2.3.6
ENTRY_END
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
REPLY QR AA NOERROR
SECTION QUESTION
g11.target.a. IN A
SECTION ANSWER
g11.target.a. IN A 1.2.3.11
ENTRY_END
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
REPLY QR AA NOERROR
SECTION QUESTION
g12b.target.a. IN A
SECTION ANSWER
g12b.target.a. A 1.2.3.12
ENTRY_END
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
REPLY QR AA NOERROR
SECTION QUESTION
g13c.target.a. IN A
SECTION ANSWER
g13c.target.a. A 1.2.3.13
ENTRY_END
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
REPLY QR AA NOERROR
SECTION QUESTION
g14.target.a. IN A
SECTION ANSWER
g14.target.a. A 1.2.3.14
ENTRY_END
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
REPLY QR AA NOERROR
SECTION QUESTION
g15b.target.a. IN A
SECTION ANSWER
g15b.target.a. A 1.2.3.15
ENTRY_END
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
REPLY QR AA NOERROR
SECTION QUESTION
g16.target.a. IN A
SECTION ANSWER
g16.target.a. A 1.2.3.16
ENTRY_END
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
REPLY QR AA NOERROR
SECTION QUESTION
g17b.target.a. IN A
SECTION ANSWER
g17b.target.a. A 1.2.3.17
ENTRY_END
RANGE_END
; gotham5.a.
RANGE_BEGIN 0 1000
ADDRESS 10.20.30.45
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
REPLY QR AA NOERROR
SECTION QUESTION
www.gotham5.a. IN A
SECTION ANSWER
www.gotham5.a. CNAME w2.gotham5.a.
ENTRY_END
RANGE_END
; gotham6.a.
RANGE_BEGIN 0 1000
ADDRESS 10.20.30.46
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
REPLY QR NOERROR
SECTION QUESTION
www.gotham6.a. IN A
SECTION ANSWER
www.gotham6.a. CNAME w2.gotham6.a.
ENTRY_END
RANGE_END
; gotham7.a.
RANGE_BEGIN 0 1000
ADDRESS 10.20.30.47
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
REPLY QR AA NOERROR
SECTION QUESTION
www.gotham7.a. IN A
SECTION ANSWER
www.gotham7.a. CNAME w2.gotham7.a.
ENTRY_END
RANGE_END
; gotham14.a.
RANGE_BEGIN 0 1000
ADDRESS 10.20.30.54
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
REPLY QR AA NOERROR
SECTION QUESTION
www.gotham14.a. IN A
SECTION ANSWER
www.gotham14.a. CNAME w2.gotham14.a.
ENTRY_END
RANGE_END
; gotham15.a.
RANGE_BEGIN 0 1000
ADDRESS 10.20.30.55
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
REPLY QR AA NOERROR
SECTION QUESTION
www.gotham15.a. IN A
SECTION ANSWER
www.gotham15.a. CNAME w2.gotham15.a.
ENTRY_END
RANGE_END
; Test with zero rpz CNAMEs, rpz answer.
STEP 10 QUERY
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
www.gotham.a. IN A
ENTRY_END
STEP 11 CHECK_ANSWER
ENTRY_BEGIN
MATCH all
REPLY QR RD RA AA NOERROR
SECTION QUESTION
www.gotham.a. IN A
SECTION ANSWER
www.gotham.a. A 1.2.3.61
ENTRY_END
; Test with one rpz CNAME, rpz answer.
STEP 20 QUERY
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
www.gotham2.a. IN A
ENTRY_END
STEP 21 CHECK_ANSWER
ENTRY_BEGIN
MATCH all
REPLY QR RD RA AA NOERROR
SECTION QUESTION
www.gotham2.a. IN A
SECTION ANSWER
www.gotham2.a. CNAME g2.target.a.
g2.target.a. A 1.2.3.62
ENTRY_END
; Test with two rpz CNAMEs, rpz answer.
STEP 30 QUERY
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
www.gotham3.a. IN A
ENTRY_END
STEP 31 CHECK_ANSWER
ENTRY_BEGIN
MATCH all
REPLY QR RD RA AA NOERROR
SECTION QUESTION
www.gotham3.a. IN A
SECTION ANSWER
www.gotham3.a. CNAME g3.target.a.
g3.target.a. CNAME g3b.target.a.
g3b.target.a. A 1.2.3.63
ENTRY_END
; Test with three rpz CNAMEs, rpz answer.
STEP 40 QUERY
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
www.gotham4.a. IN A
ENTRY_END
STEP 41 CHECK_ANSWER
ENTRY_BEGIN
MATCH all
REPLY QR RD RA AA NOERROR
SECTION QUESTION
www.gotham4.a. IN A
SECTION ANSWER
www.gotham4.a. CNAME g4.target.a.
g4.target.a. CNAME g4b.target.a.
g4b.target.a. CNAME g4c.target.a.
g4c.target.a. A 1.2.3.64
ENTRY_END
; Test with a CNAME from upstream, zero rpz CNAMEs, rpz answer.
STEP 50 QUERY
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
www.gotham5.a. IN A
ENTRY_END
STEP 51 CHECK_ANSWER
ENTRY_BEGIN
MATCH all
REPLY QR RD RA AA NOERROR
SECTION QUESTION
www.gotham5.a. IN A
SECTION ANSWER
www.gotham5.a. CNAME w2.gotham5.a.
w2.gotham5.a. A 1.2.3.65
ENTRY_END
; Test with a CNAME from upstream, one rpz CNAME, rpz answer.
STEP 60 QUERY
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
www.gotham6.a. IN A
ENTRY_END
STEP 61 CHECK_ANSWER
ENTRY_BEGIN
MATCH all
REPLY QR RD RA AA NOERROR
SECTION QUESTION
www.gotham6.a. IN A
SECTION ANSWER
www.gotham6.a. CNAME w2.gotham6.a.
w2.gotham6.a. CNAME g6.target.a.
g6.target.a. A 1.2.3.66
ENTRY_END
; Test with a CNAME from upstream, two rpz CNAMEs, rpz answer.
STEP 70 QUERY
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
www.gotham7.a. IN A
ENTRY_END
STEP 71 CHECK_ANSWER
ENTRY_BEGIN
MATCH all
REPLY QR RD RA AA NOERROR
SECTION QUESTION
www.gotham7.a. IN A
SECTION ANSWER
www.gotham7.a. CNAME w2.gotham7.a.
w2.gotham7.a. CNAME g7.target.a.
g7.target.a. CNAME g7b.target.a.
g7b.target.a. A 1.2.3.66
ENTRY_END
; Test with a CNAME from cache, zero rpz CNAMEs, rpz answer.
STEP 80 QUERY
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
www.gotham5.a. IN A
ENTRY_END
STEP 81 CHECK_ANSWER
ENTRY_BEGIN
MATCH all
REPLY QR RD RA AA NOERROR
SECTION QUESTION
www.gotham5.a. IN A
SECTION ANSWER
www.gotham5.a. CNAME w2.gotham5.a.
w2.gotham5.a. A 1.2.3.65
ENTRY_END
; Test with a CNAME from cache, one rpz CNAME, rpz answer.
STEP 90 QUERY
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
www.gotham6.a. IN A
ENTRY_END
STEP 91 CHECK_ANSWER
ENTRY_BEGIN
MATCH all
REPLY QR RD RA AA NOERROR
SECTION QUESTION
www.gotham6.a. IN A
SECTION ANSWER
www.gotham6.a. CNAME w2.gotham6.a.
w2.gotham6.a. CNAME g6.target.a.
g6.target.a. A 1.2.3.66
ENTRY_END
; Test with a CNAME from cache, two rpz CNAMEs, rpz answer.
STEP 100 QUERY
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
www.gotham7.a. IN A
ENTRY_END
STEP 101 CHECK_ANSWER
ENTRY_BEGIN
MATCH all
REPLY QR RD RA AA NOERROR
SECTION QUESTION
www.gotham7.a. IN A
SECTION ANSWER
www.gotham7.a. CNAME w2.gotham7.a.
w2.gotham7.a. CNAME g7.target.a.
g7.target.a. CNAME g7b.target.a.
g7b.target.a. A 1.2.3.66
ENTRY_END
; Test with lookup from nameserver, zero rpz CNAMEs, rpz nsip answer.
STEP 110 QUERY
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
www.gotham8.a. IN A
ENTRY_END
STEP 111 CHECK_ANSWER
ENTRY_BEGIN
MATCH all
REPLY QR RD RA AA NOERROR
SECTION QUESTION
www.gotham8.a. IN A
SECTION ANSWER
www.gotham8.a. A 1.2.3.68
ENTRY_END
; Test with lookup from nameserver, one rpz CNAME, rpz nsip answer.
STEP 120 QUERY
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
www.gotham9.a. IN A
ENTRY_END
STEP 121 CHECK_ANSWER
ENTRY_BEGIN
MATCH all
REPLY QR RD RA AA NOERROR
SECTION QUESTION
www.gotham9.a. IN A
SECTION ANSWER
www.gotham9.a. CNAME g9.target.a.
g9.target.a. A 1.2.3.69
ENTRY_END
; Test with lookup from nameserver, two rpz CNAMEs, rpz nsip answer.
STEP 130 QUERY
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
www.gotham10.a. IN A
ENTRY_END
STEP 131 CHECK_ANSWER
ENTRY_BEGIN
MATCH all
REPLY QR RD RA AA NOERROR
SECTION QUESTION
www.gotham10.a. IN A
SECTION ANSWER
www.gotham10.a. CNAME g10.target.a.
g10.target.a. CNAME g10b.target.a.
g10b.target.a. A 1.2.3.70
ENTRY_END
; Test with one rpz CNAME, upstream answer.
STEP 140 QUERY
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
www.gotham11.a. IN A
ENTRY_END
STEP 141 CHECK_ANSWER
ENTRY_BEGIN
MATCH all
REPLY QR RD RA AA NOERROR
SECTION QUESTION
www.gotham11.a. IN A
SECTION ANSWER
www.gotham11.a. CNAME g11.target.a.
g11.target.a. A 1.2.3.11
ENTRY_END
; Test with two rpz CNAMEs, upstream answer.
STEP 150 QUERY
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
www.gotham12.a. IN A
ENTRY_END
STEP 151 CHECK_ANSWER
ENTRY_BEGIN
MATCH all
REPLY QR RD RA AA NOERROR
SECTION QUESTION
www.gotham12.a. IN A
SECTION ANSWER
www.gotham12.a. CNAME g12.target.a.
g12.target.a. CNAME g12b.target.a.
g12b.target.a. A 1.2.3.12
ENTRY_END
; Test with three rpz CNAMEs, upstream answer.
STEP 160 QUERY
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
www.gotham13.a. IN A
ENTRY_END
STEP 161 CHECK_ANSWER
ENTRY_BEGIN
MATCH all
REPLY QR RD RA AA NOERROR
SECTION QUESTION
www.gotham13.a. IN A
SECTION ANSWER
www.gotham13.a. CNAME g13.target.a.
g13.target.a. CNAME g13b.target.a.
g13b.target.a. CNAME g13c.target.a.
g13c.target.a. A 1.2.3.13
ENTRY_END
; Test with a CNAME from upstream, one rpz CNAME, upstream answer.
STEP 170 QUERY
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
www.gotham14.a. IN A
ENTRY_END
STEP 171 CHECK_ANSWER
ENTRY_BEGIN
MATCH all
REPLY QR RD RA NOERROR
SECTION QUESTION
www.gotham14.a. IN A
SECTION ANSWER
www.gotham14.a. CNAME w2.gotham14.a.
w2.gotham14.a. CNAME g14.target.a.
g14.target.a. A 1.2.3.14
ENTRY_END
; Test with a CNAME from upstream, two rpz CNAMEs, upstream answer.
STEP 180 QUERY
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
www.gotham15.a. IN A
ENTRY_END
STEP 181 CHECK_ANSWER
ENTRY_BEGIN
MATCH all
REPLY QR RD RA NOERROR
SECTION QUESTION
www.gotham15.a. IN A
SECTION ANSWER
www.gotham15.a. CNAME w2.gotham15.a.
w2.gotham15.a. CNAME g15.target.a.
g15.target.a. CNAME g15b.target.a.
g15b.target.a. A 1.2.3.15
ENTRY_END
; Test with a CNAME from cache, one rpz CNAME, upstream answer.
STEP 190 QUERY
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
www.gotham14.a. IN A
ENTRY_END
STEP 191 CHECK_ANSWER
ENTRY_BEGIN
MATCH all
REPLY QR RD RA NOERROR
SECTION QUESTION
www.gotham14.a. IN A
SECTION ANSWER
www.gotham14.a. CNAME w2.gotham14.a.
w2.gotham14.a. CNAME g14.target.a.
g14.target.a. A 1.2.3.14
ENTRY_END
; Test with a CNAME from cache, two rpz CNAMEs, upstream answer.
STEP 200 QUERY
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
www.gotham15.a. IN A
ENTRY_END
STEP 201 CHECK_ANSWER
ENTRY_BEGIN
MATCH all
REPLY QR RD RA NOERROR
SECTION QUESTION
www.gotham15.a. IN A
SECTION ANSWER
www.gotham15.a. CNAME w2.gotham15.a.
w2.gotham15.a. CNAME g15.target.a.
g15.target.a. CNAME g15b.target.a.
g15b.target.a. A 1.2.3.15
ENTRY_END
; Test with lookup from nameserver, one rpz nsip CNAME, upstream answer.
STEP 210 QUERY
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
www.gotham16.a. IN A
ENTRY_END
STEP 211 CHECK_ANSWER
ENTRY_BEGIN
MATCH all
REPLY QR RD RA NOERROR
SECTION QUESTION
www.gotham16.a. IN A
SECTION ANSWER
www.gotham16.a. CNAME g16.target.a.
g16.target.a. A 1.2.3.16
ENTRY_END
; Test with lookup from nameserver, two rpz nsip CNAMEs, upstream answer.
STEP 220 QUERY
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
www.gotham17.a. IN A
ENTRY_END
STEP 221 CHECK_ANSWER
ENTRY_BEGIN
MATCH all
REPLY QR RD RA NOERROR
SECTION QUESTION
www.gotham17.a. IN A
SECTION ANSWER
www.gotham17.a. CNAME g17.target.a.
g17.target.a. CNAME g17b.target.a.
g17b.target.a. A 1.2.3.17
ENTRY_END
SCENARIO_END

325
testdata/rpz_nsdname_override.rpl vendored Normal file
View file

@ -0,0 +1,325 @@
; config options
server:
module-config: "respip validator iterator"
target-fetch-policy: "0 0 0 0 0"
qname-minimisation: no
access-control: 192.0.0.0/8 allow
rpz:
name: "rpz.example.com."
rpz-log: yes
rpz-log-name: "rpz.example.com"
rpz-action-override: "nxdomain"
zonefile:
TEMPFILE_NAME rpz.example.com
TEMPFILE_CONTENTS rpz.example.com
$ORIGIN example.com.
rpz 3600 IN SOA ns1.rpz.example.com. hostmaster.rpz.example.com. (
1379078166 28800 7200 604800 7200 )
3600 IN NS ns1.rpz.example.com.
3600 IN NS ns2.rpz.example.com.
$ORIGIN rpz.example.com.
ns1.gotham.a.rpz-nsdname A 1.2.3.5
TEMPFILE_END
rpz:
name: "rpz2.example.com."
rpz-log: yes
rpz-log-name: "rpz2.example.com"
rpz-action-override: "nodata"
zonefile:
TEMPFILE_NAME rpz2.example.com
TEMPFILE_CONTENTS rpz2.example.com
$ORIGIN example.com.
rpz2 3600 IN SOA ns1.rpz2.example.com. hostmaster.rpz2.example.com. (
1379078166 28800 7200 604800 7200 )
3600 IN NS ns1.rpz2.example.com.
3600 IN NS ns2.rpz2.example.com.
$ORIGIN rpz2.example.com.
ns1.gotham2.a.rpz-nsdname A 1.2.3.5
TEMPFILE_END
rpz:
name: "rpz3.example.com."
rpz-log: yes
rpz-log-name: "rpz3.example.com"
rpz-action-override: "passthru"
zonefile:
TEMPFILE_NAME rpz3.example.com
TEMPFILE_CONTENTS rpz3.example.com
$ORIGIN example.com.
rpz3 3600 IN SOA ns1.rpz3.example.com. hostmaster.rpz3.example.com. (
1379078166 28800 7200 604800 7200 )
3600 IN NS ns1.rpz3.example.com.
3600 IN NS ns2.rpz3.example.com.
$ORIGIN rpz3.example.com.
ns1.gotham3.a.rpz-nsdname A 1.2.3.5
TEMPFILE_END
rpz:
name: "rpz4.example.com."
rpz-log: yes
rpz-log-name: "rpz4.example.com"
rpz-action-override: "drop"
zonefile:
TEMPFILE_NAME rpz4.example.com
TEMPFILE_CONTENTS rpz4.example.com
$ORIGIN example.com.
rpz4 3600 IN SOA ns1.rpz4.example.com. hostmaster.rpz4.example.com. (
1379078166 28800 7200 604800 7200 )
3600 IN NS ns1.rpz4.example.com.
3600 IN NS ns2.rpz4.example.com.
$ORIGIN rpz4.example.com.
ns1.gotham3.a.rpz-nsdname A 1.2.3.5
ns1.gotham4.a.rpz-nsdname A 1.2.3.5
TEMPFILE_END
rpz:
name: "rpz5.example.com."
rpz-log: yes
rpz-log-name: "rpz5.example.com"
rpz-action-override: "cname"
rpz-cname-override: "target.a"
zonefile:
TEMPFILE_NAME rpz5.example.com
TEMPFILE_CONTENTS rpz5.example.com
$ORIGIN example.com.
rpz5 3600 IN SOA ns1.rpz5.example.com. hostmaster.rpz5.example.com. (
1379078166 28800 7200 604800 7200 )
3600 IN NS ns1.rpz5.example.com.
3600 IN NS ns2.rpz5.example.com.
$ORIGIN rpz5.example.com.
ns1.gotham5.a.rpz-nsdname A 1.2.3.5
TEMPFILE_END
rpz:
name: "rpz6.example.com."
rpz-log: yes
rpz-log-name: "rpz6.example.com"
rpz-action-override: "disabled"
zonefile:
TEMPFILE_NAME rpz6.example.com
TEMPFILE_CONTENTS rpz6.example.com
$ORIGIN example.com.
rpz6 3600 IN SOA ns1.rpz6.example.com. hostmaster.rpz6.example.com. (
1379078166 28800 7200 604800 7200 )
3600 IN NS ns1.rpz6.example.com.
3600 IN NS ns2.rpz6.example.com.
$ORIGIN rpz6.example.com.
ns1.gotham6.a.rpz-nsdname A 1.2.3.5
TEMPFILE_END
stub-zone:
name: "a."
stub-addr: 10.20.30.40
CONFIG_END
SCENARIO_BEGIN Test RPZ action override with trigger from nsdname.
; a.
RANGE_BEGIN 0 1000
ADDRESS 10.20.30.40
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
REPLY QR NOERROR
SECTION QUESTION
www.gotham.a. IN A
SECTION AUTHORITY
gotham.a. NS ns1.gotham.a.
SECTION ADDITIONAL
ns1.gotham.a. A 10.20.30.41
ENTRY_END
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
REPLY QR NOERROR
SECTION QUESTION
www.gotham2.a. IN A
SECTION AUTHORITY
gotham2.a. NS ns1.gotham2.a.
SECTION ADDITIONAL
ns1.gotham2.a. A 10.20.30.42
ENTRY_END
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
REPLY QR NOERROR
SECTION QUESTION
www.gotham3.a. IN A
SECTION AUTHORITY
gotham3.a. NS ns1.gotham3.a.
SECTION ADDITIONAL
ns1.gotham3.a. A 10.20.30.43
ENTRY_END
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
REPLY QR NOERROR
SECTION QUESTION
www.gotham4.a. IN A
SECTION AUTHORITY
gotham4.a. NS ns1.gotham4.a.
SECTION ADDITIONAL
ns1.gotham4.a. A 10.20.30.44
ENTRY_END
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
REPLY QR NOERROR
SECTION QUESTION
www.gotham5.a. IN A
SECTION AUTHORITY
gotham5.a. NS ns1.gotham5.a.
SECTION ADDITIONAL
ns1.gotham5.a. A 10.20.30.45
ENTRY_END
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
REPLY QR NOERROR
SECTION QUESTION
www.gotham6.a. IN A
SECTION AUTHORITY
gotham6.a. NS ns1.gotham6.a.
SECTION ADDITIONAL
ns1.gotham6.a. A 10.20.30.46
ENTRY_END
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
REPLY QR NOERROR
SECTION QUESTION
target.a. IN A
SECTION ANSWER
target.a. IN A 1.2.3.6
ENTRY_END
RANGE_END
; gotham3.a.
RANGE_BEGIN 0 1000
ADDRESS 10.20.30.43
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
REPLY QR NOERROR
SECTION QUESTION
www.gotham3.a. IN A
SECTION ANSWER
www.gotham3.a. A 1.2.3.4
ENTRY_END
RANGE_END
; gotham6.a.
RANGE_BEGIN 0 1000
ADDRESS 10.20.30.46
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
REPLY QR NOERROR
SECTION QUESTION
www.gotham6.a. IN A
SECTION ANSWER
www.gotham6.a. A 1.2.3.4
ENTRY_END
RANGE_END
STEP 10 QUERY
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
www.gotham.a. IN A
ENTRY_END
STEP 11 CHECK_ANSWER
ENTRY_BEGIN
MATCH all
REPLY QR RD RA AA NXDOMAIN
SECTION QUESTION
www.gotham.a. IN A
SECTION ANSWER
ENTRY_END
STEP 20 QUERY
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
www.gotham2.a. IN A
ENTRY_END
STEP 21 CHECK_ANSWER
ENTRY_BEGIN
MATCH all
REPLY QR RD RA AA NOERROR
SECTION QUESTION
www.gotham2.a. IN A
SECTION ANSWER
ENTRY_END
STEP 30 QUERY
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
www.gotham3.a. IN A
ENTRY_END
STEP 31 CHECK_ANSWER
ENTRY_BEGIN
MATCH all
REPLY QR RD RA NOERROR
SECTION QUESTION
www.gotham3.a. IN A
SECTION ANSWER
www.gotham3.a. A 1.2.3.4
ENTRY_END
STEP 40 QUERY
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
www.gotham4.a. IN A
ENTRY_END
;dropped
STEP 50 QUERY
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
www.gotham5.a. IN A
ENTRY_END
STEP 51 CHECK_ANSWER
ENTRY_BEGIN
MATCH all
REPLY QR RD RA NOERROR
SECTION QUESTION
www.gotham5.a. IN A
SECTION ANSWER
www.gotham5.a. CNAME target.a
target.a A 1.2.3.6
ENTRY_END
STEP 60 QUERY
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
www.gotham6.a. IN A
ENTRY_END
STEP 61 CHECK_ANSWER
ENTRY_BEGIN
MATCH all
REPLY QR RD RA NOERROR
SECTION QUESTION
www.gotham6.a. IN A
SECTION ANSWER
www.gotham6.a. A 1.2.3.4
ENTRY_END
SCENARIO_END

332
testdata/rpz_nsip_override.rpl vendored Normal file
View file

@ -0,0 +1,332 @@
; config options
server:
module-config: "respip validator iterator"
target-fetch-policy: "0 0 0 0 0"
qname-minimisation: no
access-control: 192.0.0.0/8 allow
rpz:
name: "rpz.example.com."
rpz-log: yes
rpz-log-name: "rpz.example.com"
rpz-action-override: "nxdomain"
zonefile:
TEMPFILE_NAME rpz.example.com
TEMPFILE_CONTENTS rpz.example.com
$ORIGIN example.com.
rpz 3600 IN SOA ns1.rpz.example.com. hostmaster.rpz.example.com. (
1379078166 28800 7200 604800 7200 )
3600 IN NS ns1.rpz.example.com.
3600 IN NS ns2.rpz.example.com.
$ORIGIN rpz.example.com.
; ns1.gotham.a
32.41.30.20.10.rpz-nsip A 1.2.3.5
TEMPFILE_END
rpz:
name: "rpz2.example.com."
rpz-log: yes
rpz-log-name: "rpz2.example.com"
rpz-action-override: "nodata"
zonefile:
TEMPFILE_NAME rpz2.example.com
TEMPFILE_CONTENTS rpz2.example.com
$ORIGIN example.com.
rpz2 3600 IN SOA ns1.rpz2.example.com. hostmaster.rpz2.example.com. (
1379078166 28800 7200 604800 7200 )
3600 IN NS ns1.rpz2.example.com.
3600 IN NS ns2.rpz2.example.com.
$ORIGIN rpz2.example.com.
; ns1.gotham2.a
32.42.30.20.10.rpz-nsip A 1.2.3.5
TEMPFILE_END
rpz:
name: "rpz3.example.com."
rpz-log: yes
rpz-log-name: "rpz3.example.com"
rpz-action-override: "passthru"
zonefile:
TEMPFILE_NAME rpz3.example.com
TEMPFILE_CONTENTS rpz3.example.com
$ORIGIN example.com.
rpz3 3600 IN SOA ns1.rpz3.example.com. hostmaster.rpz3.example.com. (
1379078166 28800 7200 604800 7200 )
3600 IN NS ns1.rpz3.example.com.
3600 IN NS ns2.rpz3.example.com.
$ORIGIN rpz3.example.com.
; ns1.gotham3.a
32.43.30.20.10.rpz-nsip A 1.2.3.5
TEMPFILE_END
rpz:
name: "rpz4.example.com."
rpz-log: yes
rpz-log-name: "rpz4.example.com"
rpz-action-override: "drop"
zonefile:
TEMPFILE_NAME rpz4.example.com
TEMPFILE_CONTENTS rpz4.example.com
$ORIGIN example.com.
rpz4 3600 IN SOA ns1.rpz4.example.com. hostmaster.rpz4.example.com. (
1379078166 28800 7200 604800 7200 )
3600 IN NS ns1.rpz4.example.com.
3600 IN NS ns2.rpz4.example.com.
$ORIGIN rpz4.example.com.
; ns1.gotham3.a
32.43.30.20.10.rpz-nsip A 1.2.3.5
; ns1.gotham4.a
32.44.30.20.10.rpz-nsip A 1.2.3.5
TEMPFILE_END
rpz:
name: "rpz5.example.com."
rpz-log: yes
rpz-log-name: "rpz5.example.com"
rpz-action-override: "cname"
rpz-cname-override: "target.a"
zonefile:
TEMPFILE_NAME rpz5.example.com
TEMPFILE_CONTENTS rpz5.example.com
$ORIGIN example.com.
rpz5 3600 IN SOA ns1.rpz5.example.com. hostmaster.rpz5.example.com. (
1379078166 28800 7200 604800 7200 )
3600 IN NS ns1.rpz5.example.com.
3600 IN NS ns2.rpz5.example.com.
$ORIGIN rpz5.example.com.
; ns1.gotham5.a
32.45.30.20.10.rpz-nsip A 1.2.3.5
TEMPFILE_END
rpz:
name: "rpz6.example.com."
rpz-log: yes
rpz-log-name: "rpz6.example.com"
rpz-action-override: "disabled"
zonefile:
TEMPFILE_NAME rpz6.example.com
TEMPFILE_CONTENTS rpz6.example.com
$ORIGIN example.com.
rpz6 3600 IN SOA ns1.rpz6.example.com. hostmaster.rpz6.example.com. (
1379078166 28800 7200 604800 7200 )
3600 IN NS ns1.rpz6.example.com.
3600 IN NS ns2.rpz6.example.com.
$ORIGIN rpz6.example.com.
; ns1.gotham6.a
32.46.30.20.10.rpz-nsip A 1.2.3.5
TEMPFILE_END
stub-zone:
name: "a."
stub-addr: 10.20.30.40
CONFIG_END
SCENARIO_BEGIN Test RPZ action override with trigger from nsip.
; a.
RANGE_BEGIN 0 1000
ADDRESS 10.20.30.40
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
REPLY QR NOERROR
SECTION QUESTION
www.gotham.a. IN A
SECTION AUTHORITY
gotham.a. NS ns1.gotham.a.
SECTION ADDITIONAL
ns1.gotham.a. A 10.20.30.41
ENTRY_END
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
REPLY QR NOERROR
SECTION QUESTION
www.gotham2.a. IN A
SECTION AUTHORITY
gotham2.a. NS ns1.gotham2.a.
SECTION ADDITIONAL
ns1.gotham2.a. A 10.20.30.42
ENTRY_END
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
REPLY QR NOERROR
SECTION QUESTION
www.gotham3.a. IN A
SECTION AUTHORITY
gotham3.a. NS ns1.gotham3.a.
SECTION ADDITIONAL
ns1.gotham3.a. A 10.20.30.43
ENTRY_END
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
REPLY QR NOERROR
SECTION QUESTION
www.gotham4.a. IN A
SECTION AUTHORITY
gotham4.a. NS ns1.gotham4.a.
SECTION ADDITIONAL
ns1.gotham4.a. A 10.20.30.44
ENTRY_END
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
REPLY QR NOERROR
SECTION QUESTION
www.gotham5.a. IN A
SECTION AUTHORITY
gotham5.a. NS ns1.gotham5.a.
SECTION ADDITIONAL
ns1.gotham5.a. A 10.20.30.45
ENTRY_END
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
REPLY QR NOERROR
SECTION QUESTION
www.gotham6.a. IN A
SECTION AUTHORITY
gotham6.a. NS ns1.gotham6.a.
SECTION ADDITIONAL
ns1.gotham6.a. A 10.20.30.46
ENTRY_END
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
REPLY QR NOERROR
SECTION QUESTION
target.a. IN A
SECTION ANSWER
target.a. IN A 1.2.3.6
ENTRY_END
RANGE_END
; gotham3.a.
RANGE_BEGIN 0 1000
ADDRESS 10.20.30.43
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
REPLY QR NOERROR
SECTION QUESTION
www.gotham3.a. IN A
SECTION ANSWER
www.gotham3.a. A 1.2.3.4
ENTRY_END
RANGE_END
; gotham6.a.
RANGE_BEGIN 0 1000
ADDRESS 10.20.30.46
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
REPLY QR NOERROR
SECTION QUESTION
www.gotham6.a. IN A
SECTION ANSWER
www.gotham6.a. A 1.2.3.4
ENTRY_END
RANGE_END
STEP 10 QUERY
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
www.gotham.a. IN A
ENTRY_END
STEP 11 CHECK_ANSWER
ENTRY_BEGIN
MATCH all
REPLY QR RD RA AA NXDOMAIN
SECTION QUESTION
www.gotham.a. IN A
SECTION ANSWER
ENTRY_END
STEP 20 QUERY
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
www.gotham2.a. IN A
ENTRY_END
STEP 21 CHECK_ANSWER
ENTRY_BEGIN
MATCH all
REPLY QR RD RA AA NOERROR
SECTION QUESTION
www.gotham2.a. IN A
SECTION ANSWER
ENTRY_END
STEP 30 QUERY
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
www.gotham3.a. IN A
ENTRY_END
STEP 31 CHECK_ANSWER
ENTRY_BEGIN
MATCH all
REPLY QR RD RA NOERROR
SECTION QUESTION
www.gotham3.a. IN A
SECTION ANSWER
www.gotham3.a. A 1.2.3.4
ENTRY_END
STEP 40 QUERY
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
www.gotham4.a. IN A
ENTRY_END
;dropped
STEP 50 QUERY
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
www.gotham5.a. IN A
ENTRY_END
STEP 51 CHECK_ANSWER
ENTRY_BEGIN
MATCH all
REPLY QR RD RA NOERROR
SECTION QUESTION
www.gotham5.a. IN A
SECTION ANSWER
www.gotham5.a. CNAME target.a
target.a A 1.2.3.6
ENTRY_END
STEP 60 QUERY
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
www.gotham6.a. IN A
ENTRY_END
STEP 61 CHECK_ANSWER
ENTRY_BEGIN
MATCH all
REPLY QR RD RA NOERROR
SECTION QUESTION
www.gotham6.a. IN A
SECTION ANSWER
www.gotham6.a. A 1.2.3.4
ENTRY_END
SCENARIO_END

90
testdata/rpz_passthru_clientip.rpl vendored Normal file
View file

@ -0,0 +1,90 @@
; config options
server:
module-config: "respip validator iterator"
target-fetch-policy: "0 0 0 0 0"
qname-minimisation: no
access-control: 192.0.0.0/8 allow
rpz:
name: "rpz.example.com."
rpz-log: yes
rpz-log-name: "rpz.example.com"
zonefile:
TEMPFILE_NAME rpz.example.com
TEMPFILE_CONTENTS rpz.example.com
$ORIGIN example.com.
rpz 3600 IN SOA ns1.rpz.example.com. hostmaster.rpz.example.com. (
1379078166 28800 7200 604800 7200 )
3600 IN NS ns1.rpz.example.com.
3600 IN NS ns2.rpz.example.com.
$ORIGIN rpz.example.com.
d.a A 127.0.0.1
32.1.5.0.192.rpz-client-ip CNAME rpz-passthru.
32.2.5.0.192.rpz-client-ip CNAME rpz-drop.
TEMPFILE_END
stub-zone:
name: "a."
stub-addr: 10.20.30.40
CONFIG_END
SCENARIO_BEGIN Test RPZ passthru ends processing after clientip.
; a.
RANGE_BEGIN 0 1000
ADDRESS 10.20.30.40
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
REPLY QR NOERROR
SECTION QUESTION
d.a. IN A
SECTION ANSWER
d.a. IN A 1.2.3.4
ENTRY_END
RANGE_END
STEP 10 QUERY ADDRESS 192.0.5.1
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
d.a. IN A
ENTRY_END
STEP 11 CHECK_ANSWER
ENTRY_BEGIN
MATCH all
REPLY QR RD RA NOERROR
SECTION QUESTION
d.a. IN A
SECTION ANSWER
d.a. A 1.2.3.4
ENTRY_END
; This reply should get the rpz data
STEP 20 QUERY ADDRESS 192.0.5.3
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
d.a. IN A
ENTRY_END
STEP 21 CHECK_ANSWER
ENTRY_BEGIN
MATCH all
REPLY QR RD RA AA NOERROR
SECTION QUESTION
d.a. IN A
SECTION ANSWER
d.a. A 127.0.0.1
ENTRY_END
; This reply should be dropped.
STEP 30 QUERY ADDRESS 192.0.5.2
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
d.a. IN A
ENTRY_END
SCENARIO_END

120
testdata/rpz_qtype_cname.rpl vendored Normal file
View file

@ -0,0 +1,120 @@
; config options
server:
module-config: "respip validator iterator"
target-fetch-policy: "0 0 0 0 0"
qname-minimisation: no
access-control: 192.0.0.0/8 allow
rpz:
name: "rpz.example.com."
rpz-log: yes
rpz-log-name: "rpz.example.com"
zonefile:
TEMPFILE_NAME rpz.example.com
TEMPFILE_CONTENTS rpz.example.com
$ORIGIN example.com.
rpz 3600 IN SOA ns1.rpz.example.com. hostmaster.rpz.example.com. (
1379078166 28800 7200 604800 7200 )
3600 IN NS ns1.rpz.example.com.
3600 IN NS ns2.rpz.example.com.
$ORIGIN rpz.example.com.
www.gotham.a CNAME foo.target.a.
32.42.30.20.10.rpz-nsip CNAME foo.target.a.
TEMPFILE_END
stub-zone:
name: "a."
stub-addr: 10.20.30.40
CONFIG_END
SCENARIO_BEGIN Test RPZ with qtype CNAME.
; a.
RANGE_BEGIN 0 1000
ADDRESS 10.20.30.40
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
REPLY QR NOERROR
SECTION QUESTION
www.gotham.a. IN A
SECTION AUTHORITY
gotham.a. NS ns1.gotham.a.
SECTION ADDITIONAL
ns1.gotham.a. A 10.20.30.41
ENTRY_END
ENTRY_BEGIN
MATCH opcode subdomain
ADJUST copy_id copy_query
REPLY QR NOERROR
SECTION QUESTION
gotham2.a. IN NS
SECTION AUTHORITY
gotham2.a. NS ns1.gotham2.a.
SECTION ADDITIONAL
ns1.gotham2.a. A 10.20.30.42
ENTRY_END
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
REPLY QR NOERROR
SECTION QUESTION
target.a. IN A
SECTION ANSWER
target.a. IN A 1.2.3.6
ENTRY_END
RANGE_END
; gotham2.a.
RANGE_BEGIN 0 1000
ADDRESS 10.20.30.42
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
REPLY QR NOERROR
SECTION QUESTION
www.gotham2.a. IN CNAME
SECTION ANSWER
www.gotham2.a. CNAME foo2.target.a.
ENTRY_END
RANGE_END
; Query for type CNAME, from the RPZ response
STEP 10 QUERY
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
www.gotham.a. IN CNAME
ENTRY_END
STEP 11 CHECK_ANSWER
ENTRY_BEGIN
MATCH all
REPLY QR RD RA AA
SECTION QUESTION
www.gotham.a. IN CNAME
SECTION ANSWER
www.gotham.a. IN CNAME foo.target.a.
ENTRY_END
; Query for type CNAME, the answer is nameserver lookup, CNAME from rpz nsip.
STEP 20 QUERY
ENTRY_BEGIN
REPLY RD
SECTION QUESTION
www.gotham2.a. IN CNAME
ENTRY_END
STEP 21 CHECK_ANSWER
ENTRY_BEGIN
MATCH all
REPLY QR RD RA AA NOERROR
SECTION QUESTION
www.gotham2.a. IN CNAME
SECTION ANSWER
www.gotham2.a. IN CNAME foo.target.a.
ENTRY_END
SCENARIO_END

View file

@ -0,0 +1,2 @@
example.org. 3600 IN SOA ns1.example.org. hostmaster.example.org. 1379078166 28800 7200 604800 7200
www.example.org. A 1.2.3.5

View file

@ -0,0 +1,6 @@
; example rpz file
rpz.example.com. 3600 IN SOA ns1.rpz.example.com. hostmaster.rpz.example.com. 1379078166 28800 7200 604800 7200
NS ns1.rpz.example.com.
NS ns2.rpz.example.com.
foo.example.net CNAME .
www.example.net A 1.2.3.4

View file

@ -0,0 +1,30 @@
server:
verbosity: 7
# num-threads: 1
interface: 127.0.0.1
port: @PORT@
use-syslog: no
directory: ""
pidfile: "unbound.pid"
chroot: ""
username: ""
module-config: "respip iterator"
log-time-ascii: yes
remote-control:
control-enable: yes
control-interface: @CONTROL_PATH@/controlpipe.@CONTROL_PID@
control-use-cert: no
rpz:
name: "rpz.example.com"
zonefile: "rpz.example.com.zone"
rpz-action-override: cname
rpz-cname-override: "www.example.org"
rpz-log: yes
rpz-log-name: "example policy"
auth-zone:
name: "example.org"
zonefile: "example.org.zone"
for-upstream: yes

16
testdata/rpz_reload.tdir/rpz_reload.dsc vendored Normal file
View file

@ -0,0 +1,16 @@
BaseName: rpz_reload
Version: 1.0
Description: check rpz reload change
CreationDate: Mon 11 Mar 16:00:00 CET 2024
Maintainer: dr. W.C.A. Wijngaards
Category:
Component:
CmdDepends:
Depends:
Help:
Pre: rpz_reload.pre
Post: rpz_reload.post
Test: rpz_reload.test
AuxFiles:
Passed:
Failure:

View file

@ -0,0 +1,12 @@
# #-- rpz_reload.post --#
# source the master var file when it's there
[ -f ../.tpkg.var.master ] && source ../.tpkg.var.master
# source the test var file when it's there
[ -f .tpkg.var.test ] && source .tpkg.var.test
#
# do your teardown here
. ../common.sh
echo "> cat logfiles"
cat unbound.log
kill_pid $UNBOUND_PID
rm -f $CONTROL_PATH/controlpipe.$CONTROL_PID

26
testdata/rpz_reload.tdir/rpz_reload.pre vendored Normal file
View file

@ -0,0 +1,26 @@
# #-- rpz_reload.pre--#
# source the master var file when it's there
[ -f ../.tpkg.var.master ] && source ../.tpkg.var.master
# use .tpkg.var.test for in test variable passing
[ -f .tpkg.var.test ] && source .tpkg.var.test
. ../common.sh
get_random_port 1
UNBOUND_PORT=$RND_PORT
echo "UNBOUND_PORT=$UNBOUND_PORT" >> .tpkg.var.test
# make config file
CONTROL_PATH=/tmp
CONTROL_PID=$$
sed -e 's/@PORT\@/'$UNBOUND_PORT'/' -e 's?@CONTROL_PATH\@?'$CONTROL_PATH'?' -e 's/@CONTROL_PID@/'$CONTROL_PID'/' < rpz_reload.conf > ub.conf
# start unbound in the background
PRE="../.."
$PRE/unbound -d -c ub.conf >unbound.log 2>&1 &
UNBOUND_PID=$!
echo "UNBOUND_PID=$UNBOUND_PID" >> .tpkg.var.test
echo "CONTROL_PATH=$CONTROL_PATH" >> .tpkg.var.test
echo "CONTROL_PID=$CONTROL_PID" >> .tpkg.var.test
cat .tpkg.var.test
wait_unbound_up unbound.log

109
testdata/rpz_reload.tdir/rpz_reload.test vendored Normal file
View file

@ -0,0 +1,109 @@
# #-- rpz_reload.test --#
# source the master var file when it's there
[ -f ../.tpkg.var.master ] && source ../.tpkg.var.master
# use .tpkg.var.test for in test variable passing
[ -f .tpkg.var.test ] && source .tpkg.var.test
PRE="../.."
. ../common.sh
# do the test
echo "> dig . SOA"
dig @127.0.0.1 -p $UNBOUND_PORT localhost. A | tee outfile
echo "> check answer"
if grep localhost outfile | grep "127.0.0.1"; then
echo "OK"
else
echo "Not OK"
exit 1
fi
echo ""
echo "> unbound-control status"
$PRE/unbound-control -c ub.conf status
if test $? -ne 0; then
echo "wrong exit value."
exit 1
else
echo "exit value: OK"
fi
# Have the RPZ block some things.
dig @127.0.0.1 -p $UNBOUND_PORT foo.example.net. A | tee outfile
echo "> check answer"
if grep "www.example.org" outfile | grep "1.2.3.5"; then
echo "OK"
else
echo "Not OK"
exit 1
fi
if grep "rpz: applied .example policy." unbound.log | grep "foo.example.net. A"; then
echo "log line OK"
else
echo "log line not OK"
exit 1
fi
dig @127.0.0.1 -p $UNBOUND_PORT www.example.net. A | tee outfile
if grep "www.example.org" outfile | grep "1.2.3.5"; then
echo "OK"
else
echo "Not OK"
exit 1
fi
if grep "rpz: applied .example policy." unbound.log | grep "www.example.net. A"; then
echo "log line OK"
else
echo "log line not OK"
exit 1
fi
# Modify the config
cp ub.conf ub2.conf
sed -e 's/rpz-action-override: cname/#rpz-action-override: ""/' \
-e 's/rpz-cname-override: "www.example.org"/rpz-cname-override: ""/' \
-e 's/rpz-log-name: "example policy"/rpz-log-name: "exrpz"/' \
< ub2.conf > ub.conf
echo ""
echo "> Modified config"
grep "rpz" ub.conf
echo ""
echo "> unbound-control reload"
$PRE/unbound-control -c ub.conf reload 2>&1 | tee outfile
if test $? -ne 0; then
echo "wrong exit value."
exit 1
fi
wait_logfile unbound.log "Restart of unbound" 60
# Check the output after reload
dig @127.0.0.1 -p $UNBOUND_PORT foo.example.net. A | tee outfile
echo "> check answer"
if grep "NXDOMAIN" outfile; then
echo "OK"
else
echo "Not OK"
exit 1
fi
if grep "rpz: applied .exrpz." unbound.log | grep "foo.example.net. A"; then
echo "log line OK"
else
echo "log line not OK"
exit 1
fi
dig @127.0.0.1 -p $UNBOUND_PORT www.example.net. A | tee outfile
if grep "1.2.3.4" outfile; then
echo "OK"
else
echo "Not OK"
exit 1
fi
if grep "rpz: applied .exrpz." unbound.log | grep "www.example.net. A"; then
echo "log line OK"
else
echo "log line not OK"
exit 1
fi
exit 0

View file

@ -9,6 +9,7 @@ server:
chroot: ""
username: ""
do-not-query-localhost: no
discard-timeout: 3000 # testns uses sleep=2
ssl-port: @PORT@
ssl-service-key: "unbound_server.key"
ssl-service-pem: "unbound_server.pem"

View file

@ -21,7 +21,7 @@ stub-zone:
stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
CONFIG_END
SCENARIO_BEGIN Test validator with positive response
SCENARIO_BEGIN Test subnet cached response
; K.ROOT-SERVERS.NET.
RANGE_BEGIN 0 100

308
testdata/subnet_cached_size.crpl vendored Normal file
View file

@ -0,0 +1,308 @@
; Ask the same question twice. Check to see second is answered
; from cache
server:
trust-anchor: "example.com. 3600 IN DS 2854 3 1 46e4ffc6e9a4793b488954bd3f0cc6af0dfb201b"
val-override-date: "20070916134226"
trust-anchor-signaling: no
target-fetch-policy: "0 0 0 0 0"
send-client-subnet: 1.2.3.4
max-client-subnet-ipv4: 17
module-config: "subnetcache validator iterator"
verbosity: 3
fake-sha1: yes
fake-dsa: yes
access-control: 127.0.0.0/8 allow_snoop
qname-minimisation: "no"
minimal-responses: no
; the size for the edns subnet cache
msg-cache-size: 1500
stub-zone:
name: "."
stub-addr: 193.0.14.129 # K.ROOT-SERVERS.NET.
CONFIG_END
SCENARIO_BEGIN Test subnet cached response size
; K.ROOT-SERVERS.NET.
RANGE_BEGIN 0 100
ADDRESS 193.0.14.129
ENTRY_BEGIN
MATCH opcode qtype qname ednsdata
ADJUST copy_id
REPLY QR NOERROR
SECTION QUESTION
. IN NS
SECTION ANSWER
. IN NS K.ROOT-SERVERS.NET.
SECTION ADDITIONAL
HEX_EDNSDATA_BEGIN
;; we expect to receive empty
HEX_EDNSDATA_END
K.ROOT-SERVERS.NET. IN A 193.0.14.129
ENTRY_END
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
REPLY QR NOERROR
SECTION QUESTION
www.example.com. IN A
SECTION AUTHORITY
com. IN NS a.gtld-servers.net.
SECTION ADDITIONAL
a.gtld-servers.net. IN A 192.5.6.30
ENTRY_END
RANGE_END
; a.gtld-servers.net.
RANGE_BEGIN 0 100
ADDRESS 192.5.6.30
ENTRY_BEGIN
MATCH opcode qtype qname ednsdata
ADJUST copy_id
REPLY QR NOERROR
SECTION QUESTION
com. IN NS
SECTION ANSWER
com. IN NS a.gtld-servers.net.
SECTION ADDITIONAL
HEX_EDNSDATA_BEGIN
;; we expect to receive empty
HEX_EDNSDATA_END
a.gtld-servers.net. IN A 192.5.6.30
ENTRY_END
ENTRY_BEGIN
MATCH opcode qtype qname
ADJUST copy_id
REPLY QR NOERROR
SECTION QUESTION
www.example.com. IN A
SECTION AUTHORITY
example.com. IN NS ns.example.com.
SECTION ADDITIONAL
ns.example.com. IN A 1.2.3.4
ENTRY_END
RANGE_END
; ns.example.com.
RANGE_BEGIN 0 100
ADDRESS 1.2.3.4
ENTRY_BEGIN
MATCH opcode qtype qname ednsdata
ADJUST copy_id
REPLY QR NOERROR
SECTION QUESTION
example.com. IN NS
SECTION ANSWER
example.com. IN NS ns.example.com.
example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854}
SECTION ADDITIONAL
HEX_EDNSDATA_BEGIN
;; we expect to receive empty
HEX_EDNSDATA_END
ns.example.com. IN A 1.2.3.4
ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854}
ENTRY_END
; response to DNSKEY priming query
ENTRY_BEGIN
MATCH opcode qtype qname ednsdata
ADJUST copy_id
REPLY QR NOERROR
SECTION QUESTION
example.com. IN DNSKEY
SECTION ANSWER
example.com. 3600 IN DNSKEY 256 3 3 ALXLUsWqUrY3JYER3T4TBJII s70j+sDS/UT2QRp61SE7S3E EXopNXoFE73JLRmvpi/UrOO/Vz4Se 6wXv/CYCKjGw06U4WRgR YXcpEhJROyNapmdIKSx hOzfLVE1gqA0PweZR8d tY3aNQSRn3sPpwJr6Mi /PqQKAMMrZ9ckJpf1+b QMOOvxgzz2U1GS18b3y ZKcgTMEaJzd/GZYzi/B N2DzQ0MsrSwYXfsNLFO Bbs8PJMW4LYIxeeOe6rUgkWOF 7CC9Dh/dduQ1QrsJhmZAEFfd6ByYV+ ;{id = 2854 (zsk), size = 1688b}
example.com. 3600 IN RRSIG DNSKEY 3 2 3600 20070926134802 20070829134802 2854 example.com. MCwCFG1yhRNtTEa3Eno2zhVVuy2EJX3wAhQeLyUp6+UXcpC5qGNu9tkrTEgPUg== ;{id = 2854}
SECTION AUTHORITY
example.com. IN NS ns.example.com.
example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854}
SECTION ADDITIONAL
HEX_EDNSDATA_BEGIN
;; we expect to receive empty
HEX_EDNSDATA_END
ns.example.com. IN A 1.2.3.4
ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926135752 20070829135752 2854 example.com. MC0CFQCMSWxVehgOQLoYclB9PIAbNP229AIUeH0vNNGJhjnZiqgIOKvs1EhzqAo= ;{id = 2854}
ENTRY_END
; response to query of interest
ENTRY_BEGIN
MATCH opcode qtype qname ednsdata
ADJUST copy_id copy_ednsdata_assume_clientsubnet
REPLY QR NOERROR
SECTION QUESTION
www.example.com. IN A
SECTION ANSWER
www.example.com. IN A 10.20.30.40
ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCQMyTjn7WWwpwAR1LlVeLpRgZGuQIUCcJDEkwAuzytTDRlYK7nIMwH1CM= ;{id = 2854}
SECTION AUTHORITY
example.com. IN NS ns.example.com.
example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854}
SECTION ADDITIONAL
HEX_EDNSDATA_BEGIN
; client is 127.0.0.1
00 08 ; OPC
00 07 ; option length
00 01 ; Family
11 00 ; source mask, scopemask
7f 00 00 ; address
HEX_EDNSDATA_END
ns.example.com. IN A 1.2.3.4
www.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFC99iE9K5y2WNgI0gFvBWaTi9wm6AhUAoUqOpDtG5Zct+Qr9F3mSdnbc6V4= ;{id = 2854}
ENTRY_END
ENTRY_BEGIN
MATCH opcode qtype qname ednsdata
ADJUST copy_id copy_ednsdata_assume_clientsubnet
REPLY QR NOERROR
SECTION QUESTION
www.example.com. IN A
SECTION ANSWER
www.example.com. IN A 10.20.30.43
www.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. AFC5G+z0jWt132hDuTIFOva59cZ7MTd+ex/osuoiQhIIuWFAr9xoZz8=
SECTION AUTHORITY
example.com. IN NS ns.example.com.
example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854}
SECTION ADDITIONAL
HEX_EDNSDATA_BEGIN
; client is 127.3.0.1
00 08 ; OPC
00 07 ; option length
00 01 ; Family
11 00 ; source mask, scopemask
7f 03 00 ; address
HEX_EDNSDATA_END
ns.example.com. IN A 1.2.3.4
ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCQMyTjn7WWwpwAR1LlVeLpRgZGuQIUCcJDEkwAuzytTDRlYK7nIMwH1CM= ;{id = 2854}
ENTRY_END
RANGE_END
STEP 1 QUERY
ENTRY_BEGIN
HEX_ANSWER_BEGIN;
00 00 01 00 00 01 00 00 ;ID 0
00 00 00 01 03 77 77 77 ; www.example.com A? (DO)
07 65 78 61 6d 70 6c 65
03 63 6f 6d 00 00 01 00
01 00 00 29 10 00 00 00
80 00 00 0b
00 08 00 07 ; OPC, optlen
00 01 11 00 ; ip4, scope 17, source 0
7f 00 00 ;127.0.0.0/17
HEX_ANSWER_END
ENTRY_END
STEP 10 CHECK_ANSWER
ENTRY_BEGIN
MATCH all ednsdata
REPLY QR RD RA AD NOERROR
SECTION QUESTION
www.example.com. IN A
SECTION ANSWER
www.example.com. IN A 10.20.30.40
www.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFC99iE9K5y2WNgI0gFvBWaTi9wm6AhUAoUqOpDtG5Zct+Qr9F3mSdnbc6V4= ;{id = 2854}
SECTION AUTHORITY
example.com. IN NS ns.example.com.
example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854}
SECTION ADDITIONAL
HEX_EDNSDATA_BEGIN
; client is 127.0.0.1
00 08 ; OPC
00 07 ; option length
00 01 ; Family
11 11 ; source mask, scopemask
7f 00 00 ; address
HEX_EDNSDATA_END
ns.example.com. IN A 1.2.3.4
ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCQMyTjn7WWwpwAR1LlVeLpRgZGuQIUCcJDEkwAuzytTDRlYK7nIMwH1CM= ;{id = 2854}
ENTRY_END
STEP 11 QUERY
ENTRY_BEGIN
HEX_ANSWER_BEGIN;
00 00 00 00 00 01 00 00 ;ID 0, no RD
00 00 00 01 03 77 77 77 ; www.example.com A? (DO)
07 65 78 61 6d 70 6c 65
03 63 6f 6d 00 00 01 00
01 00 00 29 10 00 00 00
80 00 00 0b
00 08 00 07 ; OPC, optlen
00 01 12 00 ; ip4, scope 18, source 0
7f 00 00 ;127.0.0.0/18
HEX_ANSWER_END
ENTRY_END
STEP 20 CHECK_ANSWER
ENTRY_BEGIN
MATCH all ednsdata
REPLY QR RA AD NOERROR
SECTION QUESTION
www.example.com. IN A
SECTION ANSWER
www.example.com. IN A 10.20.30.40
www.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFC99iE9K5y2WNgI0gFvBWaTi9wm6AhUAoUqOpDtG5Zct+Qr9F3mSdnbc6V4= ;{id = 2854}
SECTION AUTHORITY
example.com. IN NS ns.example.com.
example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854}
SECTION ADDITIONAL
HEX_EDNSDATA_BEGIN
; client is 127.0.0.1
00 08 ; OPC
00 07 ; option length
00 01 ; Family
12 11 ; source mask, scopemask
7f 00 00 ; address
HEX_EDNSDATA_END
ns.example.com. IN A 1.2.3.4
ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCQMyTjn7WWwpwAR1LlVeLpRgZGuQIUCcJDEkwAuzytTDRlYK7nIMwH1CM= ;{id = 2854}
ENTRY_END
; update the cache entry
STEP 30 QUERY
ENTRY_BEGIN
HEX_ANSWER_BEGIN;
00 00 01 00 00 01 00 00 ;ID 0
00 00 00 01 03 77 77 77 ; www.example.com A? (DO)
07 65 78 61 6d 70 6c 65
03 63 6f 6d 00 00 01 00
01 00 00 29 10 00 00 00
80 00 00 0b
00 08 00 07 ; OPC, optlen
00 01 11 00 ; ip4, scope 17, source 0
7f 03 00 ;127.3.0.0/17
HEX_ANSWER_END
ENTRY_END
STEP 40 CHECK_ANSWER
ENTRY_BEGIN
MATCH all ednsdata
REPLY QR RD RA AD NOERROR
SECTION QUESTION
www.example.com. IN A
SECTION ANSWER
www.example.com. IN A 10.20.30.43
www.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. AFC5G+z0jWt132hDuTIFOva59cZ7MTd+ex/osuoiQhIIuWFAr9xoZz8=
SECTION AUTHORITY
example.com. IN NS ns.example.com.
example.com. 3600 IN RRSIG NS 3 2 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCN+qHdJxoI/2tNKwsb08pra/G7aAIUAWA5sDdJTbrXA1/3OaesGBAO3sI= ;{id = 2854}
SECTION ADDITIONAL
HEX_EDNSDATA_BEGIN
; client is 127.3.0.1
00 08 ; OPC
00 07 ; option length
00 01 ; Family
11 11 ; source mask, scopemask
7f 03 00 ; address
HEX_EDNSDATA_END
ns.example.com. IN A 1.2.3.4
ns.example.com. 3600 IN RRSIG A 3 3 3600 20070926134150 20070829134150 2854 example.com. MC0CFQCQMyTjn7WWwpwAR1LlVeLpRgZGuQIUCcJDEkwAuzytTDRlYK7nIMwH1CM= ;{id = 2854}
ENTRY_END
SCENARIO_END

View file

@ -9,6 +9,7 @@ server:
chroot: ""
username: ""
do-not-query-localhost: no
discard-timeout: 3000 # testns uses sleep=2
local-zone: "example.net" static
local-data: "www1.example.net. IN A 1.2.3.1"

View file

@ -1,5 +1,5 @@
server:
verbosity: 2
verbosity: 4
# num-threads: 1
interface: 127.0.0.1
port: @PORT@
@ -9,6 +9,7 @@ server:
chroot: ""
username: ""
do-not-query-localhost: no
discard-timeout: 3000 # testns uses sleep=2
forward-zone:
name: "."

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