pbtag
pcall
PCDNSSEC
-PCKS
PCmissing
pcomp
pcount
libtdsodbc
libyaml
libzmq
+lightningstream
Lindqvist
linenos
linenum
LYg
Maik
Maikel
+MAILA
+MAILB
Majer
Makefiles
malcrafted
Meerwald
Mekking
memlock
-MEMLOCK
Memusage
menuselection
metadatabase
Shafir
shantikulkarni
shinsterneck
+shnya
showdetails
showflags
Shukla
Surfnet
swapcontext
swoga
+syncer
syncres
sysadmin
syscalls
taskqueue
tbhandler
tcely
+TCounters
tcp
tcpconnecttimeouts
tcpdump
tsigkey
tsigname
tsigsecret
+Tsinghua
tstamp
TSU
ttls
untruncated
unzero
updatepolicy
+upgradeable
upperalpha
upperroman
urandom
Xek
Xeon
XForwarded
+Xiang
xorbooter
xpf
XRecord
XXXXXX
yahttp
Yehuda
+yeswehack
Yiu
Ylitalo
yml
UNIT_TESTS: yes
steps:
- uses: PowerDNS/pdns/set-ubuntu-mirror@meta
- - uses: actions/checkout@v3.1.0
+ - uses: actions/checkout@v3
with:
fetch-depth: 5
submodules: recursive
echo "stamp=$(/bin/date +%s)" >> "$GITHUB_OUTPUT"
shell: bash
- name: let GitHub cache our ccache data
- uses: actions/cache@v3.2.6
+ uses: actions/cache@v3
with:
path: ~/.ccache
key: auth-ccache-${{ steps.get-stamp.outputs.stamp }}
working-directory: ./pdns/recursordist/
steps:
- uses: PowerDNS/pdns/set-ubuntu-mirror@meta
- - uses: actions/checkout@v3.1.0
+ - uses: actions/checkout@v3
with:
fetch-depth: 5
submodules: recursive
echo "stamp=$(/bin/date +%s)" >> "$GITHUB_OUTPUT"
shell: bash
- name: let GitHub cache our ccache data
- uses: actions/cache@v3.2.6
+ uses: actions/cache@v3
with:
path: ~/.ccache
key: recursor-${{ matrix.sanitizers }}-ccache-${{ steps.get-stamp.outputs.stamp }}
working-directory: ./pdns/dnsdistdist/
steps:
- uses: PowerDNS/pdns/set-ubuntu-mirror@meta
- - uses: actions/checkout@v3.1.0
+ - uses: actions/checkout@v3
with:
fetch-depth: 5
submodules: recursive
echo "stamp=$(/bin/date +%s)" >> "$GITHUB_OUTPUT"
shell: bash
- name: let GitHub cache our ccache data
- uses: actions/cache@v3.2.6
+ uses: actions/cache@v3
with:
path: ~/.ccache
key: dnsdist-${{ matrix.features }}-${{ matrix.sanitizers }}-ccache-${{ steps.get-stamp.outputs.stamp }}
--restart always
steps:
- uses: PowerDNS/pdns/set-ubuntu-mirror@meta
- - uses: actions/checkout@v3.1.0
+ - uses: actions/checkout@v3
with:
fetch-depth: 5
submodules: recursive
--restart always
steps:
- uses: PowerDNS/pdns/set-ubuntu-mirror@meta
- - uses: actions/checkout@v3.1.0
+ - uses: actions/checkout@v3
with:
fetch-depth: 5
submodules: recursive
ASAN_OPTIONS: detect_leaks=0
steps:
- uses: PowerDNS/pdns/set-ubuntu-mirror@meta
- - uses: actions/checkout@v3.1.0
+ - uses: actions/checkout@v3
with:
fetch-depth: 5
submodules: recursive
TSAN_OPTIONS: "halt_on_error=1:suppressions=${{ github.workspace }}/pdns/recursordist/recursor-tsan.supp"
steps:
- uses: PowerDNS/pdns/set-ubuntu-mirror@meta
- - uses: actions/checkout@v3.1.0
+ - uses: actions/checkout@v3
with:
fetch-depth: 5
submodules: recursive
TSAN_OPTIONS: "halt_on_error=1:suppressions=${{ github.workspace }}/pdns/recursordist/recursor-tsan.supp"
steps:
- uses: PowerDNS/pdns/set-ubuntu-mirror@meta
- - uses: actions/checkout@v3.1.0
+ - uses: actions/checkout@v3
with:
fetch-depth: 5
submodules: recursive
TSAN_OPTIONS: "halt_on_error=1:suppressions=${{ github.workspace }}/pdns/recursordist/recursor-tsan.supp"
steps:
- uses: PowerDNS/pdns/set-ubuntu-mirror@meta
- - uses: actions/checkout@v3.1.0
+ - uses: actions/checkout@v3
with:
fetch-depth: 5
submodules: recursive
SKIP_INCLUDEDIR_TESTS: yes
steps:
- uses: PowerDNS/pdns/set-ubuntu-mirror@meta
- - uses: actions/checkout@v3.1.0
+ - uses: actions/checkout@v3
with:
fetch-depth: 5
submodules: recursive
runs-on: ubuntu-20.04
steps:
- uses: PowerDNS/pdns/set-ubuntu-mirror@meta
- - uses: actions/checkout@v3.1.0
+ - uses: actions/checkout@v3
with:
fetch-depth: 5
submodules: recursive
run: "sudo snap install jq yq"
- name: Fail job if any of the previous jobs failed
run: "for i in `echo '${{ toJSON(needs) }}' | jq '.[].result' | tr -d '\"'`; do if [[ $i == 'failure' ]]; then echo '${{ toJSON(needs) }}'; exit 1; fi; done;"
- - uses: actions/checkout@v3.1.0
+ - uses: actions/checkout@v3
with:
fetch-depth: 5
submodules: recursive
os: ${{fromJson(needs.prepare.outputs.oslist)}}
fail-fast: false
steps:
- - uses: actions/checkout@v3.1.0
+ - uses: actions/checkout@v3
with:
fetch-depth: 0 # for correct version numbers
submodules: recursive
- centos-8-stream
- centos-9-stream
- ubuntu-kinetic
+ - ubuntu-lunar
- debian-bookworm
+ - amazon-2023
fail-fast: false
steps:
- - uses: actions/checkout@v3.1.0
+ - uses: actions/checkout@v3
with:
fetch-depth: 0 # for correct version numbers
submodules: recursive
steps:
- uses: PowerDNS/pdns/set-ubuntu-mirror@meta
- name: Checkout repository
- uses: actions/checkout@v3.1.0
+ uses: actions/checkout@v3
with:
# We must fetch at least the immediate parents so that if this is
# a pull request then we can checkout the head.
matrix:
product: ['auth', 'recursor', 'dnsdist']
steps:
- - uses: actions/checkout@v3.1.0
+ - uses: actions/checkout@v3
with:
fetch-depth: 5
submodules: recursive
runs-on: ubuntu-20.04
steps:
- uses: PowerDNS/pdns/set-ubuntu-mirror@meta
- - uses: actions/checkout@v3.1.0
+ - uses: actions/checkout@v3
- run: build-scripts/gh-actions-setup-inv-no-dist-upgrade # this runs apt update
- run: inv install-doc-deps
- run: inv install-doc-deps-pdf
# on a ubuntu-20.04 VM
runs-on: ubuntu-20.04
steps:
- - uses: actions/checkout@v3.1.0
+ - uses: actions/checkout@v3
with:
fetch-depth: 5
submodules: recursive
if: ${{ vars.SCHEDULED_MISC_DAILIES }}
runs-on: ubuntu-22.04
steps:
- - uses: actions/checkout@v3.1.0
+ - uses: actions/checkout@v3
with:
fetch-depth: 5
submodules: recursive
UNIT_TESTS: no
steps:
- uses: PowerDNS/pdns/set-ubuntu-mirror@meta
- - uses: actions/checkout@v3.1.0
+ - uses: actions/checkout@v3
with:
fetch-depth: 5
submodules: recursive
UNIT_TESTS: no
steps:
- uses: PowerDNS/pdns/set-ubuntu-mirror@meta
- - uses: actions/checkout@v3.1.0
+ - uses: actions/checkout@v3
with:
fetch-depth: 5
submodules: recursive
UNIT_TESTS: no
steps:
- uses: PowerDNS/pdns/set-ubuntu-mirror@meta
- - uses: actions/checkout@v3.1.0
+ - uses: actions/checkout@v3
with:
fetch-depth: 5
submodules: recursive
# on a ubuntu-20.04 VM
runs-on: ubuntu-20.04
steps:
- - uses: actions/checkout@v3.1.0
+ - uses: actions/checkout@v3
with:
fetch-depth: 5
submodules: recursive
.circleci/config.yml-local
.env
compile_commands.*
-/.cache
+.cache
/.clang-tidy
.gdb_history
.venv
Yes We Hack
-----------
Security issues can also be reported on [our YesWeHack page](https://yeswehack.com/programs/powerdns) and might fetch a bounty.
-Do note that only the PowerDNS software (PowerDNS Authoritative Server, the PowerDNS Recursor and dnsdist) is in scope for the HackerOne program, not our websites or other infrastructure.
+Do note that only the PowerDNS software (PowerDNS Authoritative Server, the PowerDNS Recursor and dnsdist) is in scope for the YesWeHack program, not our websites or other infrastructure.
Disclosure Policy
-----------------
# Modules
import argparse
+import re
import subprocess
import sys
# Globals
-g_version = '0.0.1'
+g_version = '1.0.2'
g_verbose = False
parser.add_argument('release', metavar='RELEASE',
choices=[# Authoritative Server
'auth-44', 'auth-45', 'auth-46', 'auth-47',
- 'auth-master',
+ 'auth-48', 'auth-master',
# Recursor
- 'rec-45', 'rec-46', 'rec-47', 'rec-48',
+ 'rec-46', 'rec-47', 'rec-48', 'rec-49',
'rec-master',
# DNSDist
'dnsdist-15', 'dnsdist-16', 'dnsdist-17',
if g_verbose:
print("Writing release files...")
- if release in ['auth-44', 'auth-45', 'auth-46', 'auth-47',
+ if release in ['auth-44', 'auth-45', 'auth-46', 'auth-47', 'auth-48',
'auth-master',
- 'rec-45', 'rec-46', 'rec-47', 'rec-48',
+ 'rec-46', 'rec-47', 'rec-48', 'rec-49',
'rec-master',
'dnsdist-15', 'dnsdist-16', 'dnsdist-17', 'dnsdist-18',
'dnsdist-master']:
write_dockerfile('el', '8', release)
write_dockerfile('debian', 'buster', release)
write_list_file('debian', 'buster', release)
- write_dockerfile('ubuntu', 'bionic', release)
- write_list_file('ubuntu', 'bionic', release)
write_dockerfile('ubuntu', 'focal', release)
write_list_file('ubuntu', 'focal', release)
write_dockerfile('raspbian', 'buster', release)
write_list_file('raspbian', 'buster', release)
- if release in ['auth-46', 'auth-47', 'auth-master',
- 'rec-45', 'rec-46', 'rec-47', 'rec-48', 'rec-master',
+ if release in ['auth-46', 'auth-47', 'auth-48', 'auth-master',
+ 'rec-46', 'rec-47', 'rec-48', 'rec-49', 'rec-master',
'dnsdist-16', 'dnsdist-17', 'dnsdist-18', 'dnsdist-master']:
write_dockerfile('debian', 'bullseye', release)
write_list_file('debian', 'bullseye', release)
if release in ['auth-46', 'auth-47', 'auth-master',
- 'rec-46', 'rec-47', 'rec-48', 'rec-master',
+ 'rec-46', 'rec-47', 'rec-48', 'rec-49', 'rec-master',
+ 'dnsdist-15', 'dnsdist-16', 'dnsdist-17', 'dnsdist-master']:
+ write_dockerfile('ubuntu', 'bionic', release)
+ write_list_file('ubuntu', 'bionic', release)
+
+ if release in ['auth-46', 'auth-47', 'auth-48', 'auth-master',
+ 'rec-46', 'rec-47', 'rec-48', 'rec-49', 'rec-master',
'dnsdist-17', 'dnsdist-18', 'dnsdist-master']:
write_dockerfile('ubuntu', 'jammy', release)
write_list_file('ubuntu', 'jammy', release)
- if release in ['auth-47', 'auth-master',
- 'rec-47', 'rec-48', 'rec-master',
+ if release in ['auth-47', 'auth-48', 'auth-master',
+ 'rec-47', 'rec-48', 'rec-49', 'rec-master',
'dnsdist-17', 'dnsdist-18', 'dnsdist-master']:
write_dockerfile('el', '9', release)
capture_run_output = not(g_verbose)
print('Running Docker container tagged {}...'.format(tag))
cp = subprocess.run(['docker', 'run', tag],
- capture_output=capture_run_output)
+ stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
+ version = re.search('(PowerDNS Authoritative Server|PowerDNS Recursor|' +
+ 'dnsdist) (\d+\.\d+\.\d+(-\w+)?)',
+ cp.stdout.decode())
+ if g_verbose:
+ print(cp.stdout.decode())
# for some reason 99 is returned on `cmd --version` :shrug:
if cp.returncode != 0 and cp.returncode != 99:
# FIXME write failed output to log
print('Error running {}: {}'.format(tag, repr(cp.returncode)))
return cp.returncode
- return cp.returncode
+ if version and version.group(2):
+ return cp.returncode, version.group(2)
+ else:
+ return cp.returncode, None
def collect_dockerfiles (release):
dockerfiles = sorted(collect_dockerfiles(release))
failed_builds = []
failed_runs = []
+ returned_versions = []
print('=== testing {} ==='.format(release))
for df in dockerfiles:
if g_verbose:
print('Skipping running {} due to undetermined tag.'.format(df))
failed_builds.append((str(df), returncode))
else:
- returncode = run(tag)
- # for some reason 99 is returned on `cmd --version` :shrug:
+ (returncode, return_version) = run(tag)
+ # for some reason 99 is returned on `cmd --version` :shrug:
+ # (not sure if this is true since using `stdout=PIPE...`)
if returncode != 0 and returncode != 99:
failed_runs.append((tag, returncode))
+ if return_version:
+ returned_versions.append((tag, return_version))
print('Test done.')
if len(failed_builds) > 0:
print('- failed builds:')
print('- failed runs:')
for fr in failed_runs:
print(' - {}'.format(fr))
+ if len(returned_versions) > 0:
+ print('- returned versions:')
+ for rv in returned_versions:
+ print(' - {}: {}'.format(rv[0], rv[1]))
+ else:
+ print('- ERROR: no returned versions (unsupported product?)')
# Main Program
numdomains="$1"
fi
+if false; then
set +x
for prefix in 'www' 'wildcard'; do
+ rm -f ${prefix}.csv
for num in $(seq 0 1000000); do
echo "${num},${prefix}.powerdnssec.org" >> ${prefix}.csv
done
done
set -x
+fi
EXIT=0
+++ /dev/null
-See /usr/share/doc/quilt/README.source
--- /dev/null
+#!/bin/bash
+
+if [ "$1" = "--cflags" ]; then
+ FLAGS=$(/usr/bin/net-snmp-config --cflags)
+ MYFLAGS=""
+ for flag in $FLAGS; do
+ if [[ "$flag" =~ -DNETSNMP* ]]; then
+ MYFLAGS="$MYFLAGS $flag"
+ fi
+ done
+ echo "$MYFLAGS"
+ exit 0
+
+elif [ "$1" = "--netsnmp-agent-libs" ]; then
+ /usr/bin/net-snmp-config "$@"
+ exit $?
+
+else
+ echo "E: debian/configure-helpers/net-snmp-config: unknown flag $1" >&2
+ exit 1
+fi
Source: pdns-recursor
Section: net
-Priority: extra
-Standards-Version: 4.1.2
-Maintainer: PowerDNS.COM BV <powerdns.support@powerdns.com>
+Maintainer: PowerDNS Autobuilder <powerdns.support@powerdns.com>
+Priority: optional
+Standards-Version: 4.5.1
+Build-Conflicts: libboost-context-dev [mips mipsel]
Build-Depends: debhelper (>= 10),
dh-autoreconf,
- libboost-all-dev,
+ libboost-context-dev [amd64 arm64 armel armhf i386 ppc64el],
+ libboost-dev,
+ libboost-filesystem-dev,
+ libboost-program-options-dev,
+ libboost-system-dev,
+ libboost-test-dev,
+ libboost-thread-dev,
libcap-dev,
libcurl4-openssl-dev,
- libluajit-5.1-dev [!arm64 !s390x],
- liblua5.3-dev [arm64 s390x],
libfstrm-dev,
+ libluajit-5.1-dev (>= 2.1.0~beta3+dfsg-5.3) [amd64 arm64] | libluajit-5.1-dev [amd64] | liblua5.3-dev,
+ libprotobuf-dev,
libsnmp-dev,
libsodium-dev,
libssl-dev,
- libsystemd-dev [linux-any],
+ libsystemd-dev,
pkg-config,
+ protobuf-compiler,
ragel,
- systemd [linux-any]
-Vcs-Git: https://anonscm.debian.org/git/pkg-dns/pdns-recursor.git
-Vcs-Browser: https://anonscm.debian.org/cgit/pkg-dns/pdns-recursor.git
+ systemd
Homepage: https://www.powerdns.com/
+Rules-Requires-Root: no
Package: pdns-recursor
Architecture: any
+Pre-Depends: ${misc:Pre-Depends}
Depends: adduser,
dns-root-data,
${misc:Depends},
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Upstream-Name: PowerDNS
Source: https://www.powerdns.com/downloads.html
+Upstream-Contact: https://mailman.powerdns.com/mailman/listinfo/pdns-users
Files: *
Copyright: 2002 - 2022 PowerDNS.COM BV and contributors
Copyright: 2002 - 2004 Wichert Akkermann <wichert@wiggy.net>
2004 - 2013 Matthijs Möhlmann <matthijs@cacholong.nl>
2012 - 2013 Marc Haber <mh+debian-packages@zugschlus.de>
- 2014 - 2016 Chris Hofstaedtler <zeha@debian.org>
- 2016 PowerDNS.COM BV and contributors
+ 2014 - 2018 Chris Hofstaedtler <zeha@debian.org>
+ 2016 - 2018 PowerDNS.COM BV and contributors
License: GPL-2
Files: ext/yahttp/*
+++ /dev/null
-# Variables for PowerDNS recursor init script.
-# Not honored when systemd is the running init.
-#
-# Set START to yes to start the pdns-recursor
-START=yes
-# Run resolvconf? (Deprecated feature.)
-RESOLVCONF=no
+++ /dev/null
-#!/bin/sh
-### BEGIN INIT INFO
-# Provides: pdns-recursor
-# Required-Start: $network $remote_fs $syslog
-# Required-Stop: $network $remote_fs $syslog
-# Default-Start: 2 3 4 5
-# Default-Stop: 0 1 6
-# Short-Description: PowerDNS Recursor - Recursive DNS Server
-# Description: PowerDNS Recursor - Recursive DNS Server
-### END INIT INFO
-
-#
-# Authors: Matthijs Möhlmann <matthijs@cacholong.nl>
-# Christoph Haas <haas@debian.org>
-#
-# Thanks to:
-# Thomas Hood <jdthood@aglu.demon.nl>
-#
-# initscript for PowerDNS recursor
-
-# Load lsb stuff for systemd redirection (if available).
-if [ -e /lib/lsb/init-functions ]; then
- . /lib/lsb/init-functions
-fi
-
-PATH=/sbin:/bin:/usr/sbin:/usr/bin
-DESC="PowerDNS Recursor"
-NAME=pdns_recursor
-DAEMON=/usr/sbin/$NAME
-# Derive the socket-dir setting from /etc/powerdns/recursor.conf
-# or fall back to the default /var/run if not specified there.
-PIDDIR=$(awk -F= '/^socket-dir=/ {print $2}' /etc/powerdns/recursor.conf)
-if [ -z "$PIDDIR" ]; then PIDDIR=/var/run/pdns-recursor; mkdir -p $PIDDIR; fi
-PIDFILE=$PIDDIR/$NAME.pid
-
-# Gracefully exit if the package has been removed.
-test -x $DAEMON || exit 0
-
-# Read config file if it is present.
-if [ -r /etc/default/pdns-recursor ]; then
- . /etc/default/pdns-recursor
-fi
-
-start() {
-# Return
-# 0 if daemon has been started / was already running
-# >0 if daemon could not be started
- start-stop-daemon --start --oknodo --quiet --pidfile $PIDFILE --exec $DAEMON --test > /dev/null || return 0
- start-stop-daemon --start --oknodo --quiet --pidfile $PIDFILE --exec $DAEMON -- --daemon=yes || return 2
-}
-
-start_resolvconf() {
- if [ "X$RESOLVCONF" = "Xyes" ] && [ -x /sbin/resolvconf ]; then
- echo "nameserver 127.0.0.1" | /sbin/resolvconf -a lo.pdns-recursor
- fi
- return 0
-}
-
-stop() {
-# Return
-# 0 if daemon has been stopped
-# 1 if daemon was already stopped
-# 2 if daemon could not be stopped
-# other if a failure occurred
- start-stop-daemon --stop --quiet --pidfile $PIDFILE --name $NAME
- RETVAL="$?"
- [ "$RETVAL" = 2 ] && return 2
- rm -f $PIDFILE
- return "$RETVAL"
-}
-
-stop_resolvconf() {
- if [ "X$RESOLVCONF" = "Xyes" ] && [ -x /sbin/resolvconf ]; then
- /sbin/resolvconf -d lo.pdns-recursor
- fi
- return 0
-}
-
-isrunning()
-{
- /usr/bin/rec_control ping > /dev/null
- return $?
-}
-
-case "$1" in
- start)
- if [ "$START" != "yes" ]; then
- echo "Not starting $DESC -- disabled."
- exit 0
- fi
- echo -n "Starting $DESC: $NAME ..."
- start
- case "$?" in
- 0)
- start_resolvconf
- echo done
- break
- ;;
- 1)
- echo "already running"
- break
- ;;
- *)
- echo "failed"
- exit 1
- ;;
- esac
- ;;
- stop)
- stop_resolvconf
- echo -n "Stopping $DESC: $NAME ..."
- stop
- case "$?" in
- 0)
- echo done
- break
- ;;
- 1)
- echo "not running"
- break
- ;;
- *)
- echo "failed"
- exit 1
- ;;
- esac
- ;;
- restart|force-reload)
- if [ "$START" != "yes" ]; then
- $0 stop
- exit 0
- fi
- echo -n "Restarting $DESC ..."
- stop
- case "$?" in
- 0|1)
- start
- case "$?" in
- 0)
- echo done
- exit 0
- ;;
- 1)
- echo "failed -- old process still running"
- exit 1
- ;;
- *)
- echo "failed to start"
- exit 1
- ;;
- esac
- ;;
- *)
- echo "failed to stop"
- exit 1
- ;;
- esac
- ;;
- status)
- if isrunning; then
- echo "$NAME is running"
- exit 0
- else
- echo "$NAME is not running or not responding"
- exit 3
- fi
- ;;
- *)
- echo "Usage: $0 {start|stop|restart|force-reload|status}" >&2
- exit 3
- ;;
-esac
-
-exit 0
-
# Source carries OpenSSL Exception
pdns-recursor: possible-gpl-code-linked-with-openssl
-# We load lsb-functions conditionally.
-pdns-recursor: init.d-script-needs-depends-on-lsb-base
case "$1" in
configure)
- if [ -z "`getent group pdns`" ]; then
- addgroup --system pdns
- fi
- if [ -z "`getent passwd pdns`" ]; then
- adduser --system --home /var/spool/powerdns --shell /bin/false --ingroup pdns --disabled-password --disabled-login --gecos "PowerDNS" pdns
- fi
- if [ "`stat -c '%U:%G' /etc/powerdns/recursor.conf`" = "root:root" ]; then
- chown root:pdns /etc/powerdns/recursor.conf
- # Make sure that pdns can read it; the default used to be 0600
- chmod g+r /etc/powerdns/recursor.conf
- fi
+ addgroup --system pdns
+ adduser --system --home /var/spool/powerdns --shell /bin/false --ingroup pdns --disabled-password --disabled-login --gecos "PowerDNS" pdns
;;
*)
;;
esac
-# Startup errors should never cause dpkg to fail.
-initscript_error() {
- return 0
-}
-
#DEBHELPER#
exit 0
--- /dev/null
+#!/bin/sh
+set -e
+
+delete_unchanged() {
+ if [ -e "$1" ] && echo "$2 $1" | md5sum --check --status; then
+ echo "Removing unchanged configuration file $1"
+ rm -f "$1"
+ fi
+}
+
+backup_conffile() {
+ if [ -e "$1" ]; then
+ echo "Moving configuration file $1 to $1.dpkg-bak"
+ mv -f "$1" "$1".dpkg-bak
+ fi
+}
+
+case "$1" in
+ install|upgrade)
+ # clean up files we no longer ship
+ delete_unchanged "/etc/default/pdns-recursor" a09916ceb17db9a49ac8cfa84790bf3b
+ delete_unchanged "/etc/default/pdns-recursor" 076b21b9b76d7ffecc918af47d2963c6
+ backup_conffile "/etc/default/pdns-recursor"
+ delete_unchanged "/etc/init.d/pdns-recursor" e2ea0586c3d99fdbafb76483a769b964
+ delete_unchanged "/etc/init.d/pdns-recursor" fb608ec5edc3d068213bac3480782355
+ backup_conffile "/etc/init.d/pdns-recursor"
+ ;;
+esac
+
+#DEBHELPER#
+++ /dev/null
-#!/bin/sh
-set -e
-
-# Startup errors should never cause dpkg to fail.
-initscript_error() {
- return 0
-}
-
-#DEBHELPER#
-
-exit 0
#!/usr/bin/make -f
-include /usr/share/dpkg/architecture.mk
-include /usr/share/dpkg/pkg-info.mk
-# Enable hardening features for daemons
+# Turn on all hardening flags, as we're a networked daemon.
# Note: blhc (build log hardening check) will find these false positives: CPPFLAGS 2 missing, LDFLAGS 1 missing
-export DEB_BUILD_MAINT_OPTIONS=hardening=+bindnow,+pie
+export DEB_BUILD_MAINT_OPTIONS = hardening=+all
+# see EXAMPLES in dpkg-buildflags(1) and read /usr/share/dpkg/*
DPKG_EXPORT_BUILDFLAGS = 1
-# Include buildflags.mk so we can append to the vars it sets.
-include /usr/share/dpkg/buildflags.mk
+include /usr/share/dpkg/default.mk
-# Only enable systemd integration on Linux operating systems
-ifeq ($(DEB_HOST_ARCH_OS),linux)
-CONFIGURE_ARGS += --enable-systemd --with-systemd=/lib/systemd/system
-DH_ARGS += --with systemd
-else
-CONFIGURE_ARGS += --disable-systemd
-endif
-
-# Only disable luajit on arm64
-ifneq ($(DEB_HOST_ARCH),arm64)
-CONFIGURE_ARGS += --with-lua=luajit
-else
-CONFIGURE_ARGS += --with-lua=lua5.3
-endif
-# Use new build system
%:
- dh $@ \
- --with autoreconf \
- $(DH_ARGS)
+ dh $@
+
+override_dh_auto_clean:
+ dh_auto_clean
+ rm -f dnslabeltext.cc
+ chmod +x mkpubsuffixcc || true
override_dh_auto_configure:
- dh_auto_configure -- \
+ PATH=debian/configure-helpers/:$$PATH dh_auto_configure -- \
--sysconfdir=/etc/powerdns \
+ --enable-systemd --with-systemd=/lib/systemd/system \
--enable-unit-tests \
+ --disable-silent-rules \
+ --with-service-user=pdns \
+ --with-service-group=pdns \
--with-libcap \
--with-libsodium \
+ --with-lua \
+ --with-net-snmp \
--enable-dns-over-tls \
--enable-dnstap \
- --with-net-snmp \
- --disable-silent-rules \
- --with-service-user=pdns \
- --with-service-group=pdns \
- $(CONFIGURE_ARGS)
+ --enable-nod
override_dh_auto_install:
dh_auto_install
install -d debian/pdns-recursor/usr/share/pdns-recursor/lua-config
install -m 644 -t debian/pdns-recursor/usr/share/pdns-recursor/lua-config debian/lua-config/rootkeys.lua
install -m 644 -t debian/pdns-recursor/etc/powerdns debian/recursor.lua
+ install -d debian/pdns-recursor/usr/share/pdns-recursor/snmp
+ install -m 644 -t debian/pdns-recursor/usr/share/pdns-recursor/snmp RECURSOR-MIB.txt
rm -f debian/pdns-recursor/etc/powerdns/recursor.conf-dist
- ./pdns_recursor --config=default | sed \
- -e 's!# config-dir=.*!config-dir=/etc/powerdns!' \
- -e 's!# include-dir=.*!&\ninclude-dir=/etc/powerdns/recursor.d!' \
- -e 's!# local-address=.*!local-address=127.0.0.1!' \
- -e 's!# lua-config-file=.*!lua-config-file=/etc/powerdns/recursor.lua!' \
- -e 's!# quiet=.*!quiet=yes!' \
- -e 's!# setgid=.*!setgid=pdns!' \
- -e 's!# setuid=.*!setuid=pdns!' \
- -e 's!# hint-file=.*!&\nhint-file=/usr/share/dns/root.hints!' \
+ ./pdns_recursor --no-config --config=default | sed \
+ -e 's!^# config-dir=.*!config-dir=/etc/powerdns!' \
+ -e 's!^# hint-file=.*!&\nhint-file=/usr/share/dns/root.hints!' \
+ -e 's!^# include-dir=.*!&\ninclude-dir=/etc/powerdns/recursor.d!' \
+ -e 's!^# local-address=.*!local-address=127.0.0.1!' \
+ -e 's!^# lua-config-file=.*!lua-config-file=/etc/powerdns/recursor.lua!' \
+ -e 's!^# quiet=.*!quiet=yes!' \
-e '/^# version-string=.*/d' \
> debian/pdns-recursor/etc/powerdns/recursor.conf
-override_dh_strip:
- dh_strip --ddeb-migration='pdns-recursor-dbg'
-
-override_dh_installinit:
- dh_installinit --error-handler=initscript_error
+override_dh_auto_test:
+ifeq (,$(filter nocheck,$(DEB_BUILD_OPTIONS)))
+ dh_auto_test
+ -cat testrunner.log
+endif
override_dh_gencontrol:
dh_gencontrol -- $(SUBSTVARS)
-override_dh_fixperms:
- dh_fixperms
-# these files often contain passwords. 640 as it is chowned to root:pdns
- chmod 0640 debian/pdns-recursor/etc/powerdns/recursor.conf
-
+# Explicitly set a compression method, as Debian and Ubuntu defaults vary widely,
+# and xz support is not available in all tools yet. Removing this override can
+# make reprepro fail.
override_dh_builddeb:
dh_builddeb -- -Zgzip
+++ /dev/null
-# Source is in html/js/d3.js
-pdns-recursor source: source-is-missing html/js/d3.v3.js line length is 32005 characters (>512)
Tests: smoke
-Depends: @, dnsutils
+Depends: dnsutils,
+ @
Restrictions: needs-root
exec 2>&1
set -ex
+restart_failed() {
+ echo E: service restart failed
+ journalctl -n200 --no-pager
+ exit 1
+}
+
cat <<EOF >>/etc/powerdns/recursor.conf
auth-zones=example.org=/etc/powerdns/example.org.zone
EOF
smoke.example.org. 172800 IN A 127.0.0.123
EOF
-service pdns-recursor restart
+service pdns-recursor restart || restart_failed
TMPFILE=$(mktemp)
cleanup() {
- rm -f "$TMPFILE"
+ rm -f "$TMPFILE"
}
trap cleanup EXIT
--- /dev/null
+# First do the source builds
+@INCLUDE Dockerfile.target.sdist
+
+# This defines the distribution base layer
+# Put only the bare minimum of common commands here, without dev tools
+FROM amazonlinux:2023 as dist-base
+ARG BUILDER_CACHE_BUSTER=
+
+# Do the actual rpm build
+@INCLUDE Dockerfile.rpmbuild
+
+# Do a test install and verify
+# Can be skipped with skiptests=1 in the environment
+# @EXEC [ "$skiptests" = "" ] && include Dockerfile.rpmtest
--- /dev/null
+# First do the source builds
+@INCLUDE Dockerfile.target.sdist
+
+@IF [ ${BUILDER_TARGET} = ubuntu-lunar ]
+FROM ubuntu:lunar as dist-base
+@ENDIF
+@IF [ ${BUILDER_TARGET} = ubuntu-lunar-amd64 ]
+FROM amd64/ubuntu:lunar as dist-base
+@ENDIF
+@IF [ ${BUILDER_TARGET} = ubuntu-lunar-arm64 ]
+FROM arm64v8/ubuntu:lunar as dist-base
+@ENDIF
+
+ARG BUILDER_CACHE_BUSTER=
+ARG APT_URL
+RUN apt-get update && apt-get -y dist-upgrade
+
+@INCLUDE Dockerfile.debbuild-prepare
+
+@IF [ -n "$M_authoritative$M_all" ]
+ADD builder-support/debian/authoritative/debian-buster/ pdns-${BUILDER_VERSION}/debian/
+@ENDIF
+
+@IF [ -n "$M_recursor$M_all" ]
+ADD builder-support/debian/recursor/debian-buster/ pdns-recursor-${BUILDER_VERSION}/debian/
+@ENDIF
+
+@IF [ -n "$M_dnsdist$M_all" ]
+ADD builder-support/debian/dnsdist/debian-buster/ dnsdist-${BUILDER_VERSION}/debian/
+@ENDIF
+
+@INCLUDE Dockerfile.debbuild
+
+# Do a test install and verify
+# Can be skipped with skiptests=1 in the environment
+# @EXEC [ "$skiptests" = "" ] && include Dockerfile.debtest
--- /dev/null
+Dockerfile.target.ubuntu-lunar
\ No newline at end of file
--- /dev/null
+Dockerfile.target.ubuntu-lunar
\ No newline at end of file
BuildRequires: systemd-devel
%endif
-%if 0%{?rhel} < 8
+%if 0%{?rhel} < 8 && 0%{?amzn} != 2023
BuildRequires: boost169-devel
%else
BuildRequires: boost-devel
%endif
-%if 0%{?rhel} >= 7
+%if 0%{?rhel} >= 7 || 0%{?amzn} == 2023
BuildRequires: gnutls-devel
BuildRequires: libcap-devel
BuildRequires: libnghttp2-devel
BuildRequires: lmdb-devel
-BuildRequires: libsodium-devel
%ifarch aarch64
BuildRequires: lua-devel
%define lua_implementation lua
BuildRequires: luajit-devel
%define lua_implementation luajit
%endif
-BuildRequires: net-snmp-devel
BuildRequires: re2-devel
BuildRequires: systemd
BuildRequires: systemd-devel
BuildRequires: systemd-units
BuildRequires: tinycdb-devel
+%if 0%{?amzn} != 2023
+BuildRequires: libsodium-devel
+BuildRequires: net-snmp-devel
+%endif
%endif
%if 0%{?suse_version}
Requires(pre): shadow
%systemd_requires
%endif
-%if 0%{?rhel} >= 7
+%if 0%{?rhel} >= 7 || 0%{?amzn} == 2023
Requires(pre): shadow-utils
BuildRequires: fstrm-devel
%systemd_requires
--disable-dnscrypt \
--without-libsodium \
--without-re2 \
- --enable-systemd --with-systemd=/lib/systemd/system \
+ --enable-systemd --with-systemd=%{_unitdir} \
--without-net-snmp
%endif
%if 0%{?rhel} >= 7
--with-libsodium \
--enable-dnscrypt \
--enable-dns-over-https \
- --enable-systemd --with-systemd=/lib/systemd/system \
+ --enable-systemd --with-systemd=%{_unitdir} \
--with-re2 \
--with-net-snmp \
PKG_CONFIG_PATH=/opt/lib64/pkgconfig
install -d %{buildroot}/%{_sysconfdir}/dnsdist
%{__mv} %{buildroot}%{_sysconfdir}/dnsdist/dnsdist.conf-dist %{buildroot}%{_sysconfdir}/dnsdist/dnsdist.conf
chmod 0640 %{buildroot}/%{_sysconfdir}/dnsdist/dnsdist.conf
-sed -i "s,/^\(ExecStart.*\)dnsdist\(.*\)\$,\1dnsdist -u dnsdist -g dnsdist\2," %{buildroot}/lib/systemd/system/dnsdist.service
-sed -i "s,/^\(ExecStart.*\)dnsdist\(.*\)\$,\1dnsdist -u dnsdist -g dnsdist\2," %{buildroot}/lib/systemd/system/dnsdist@.service
+sed -i "s,/^\(ExecStart.*\)dnsdist\(.*\)\$,\1dnsdist -u dnsdist -g dnsdist\2," %{buildroot}/%{_unitdir}/dnsdist.service
+sed -i "s,/^\(ExecStart.*\)dnsdist\(.*\)\$,\1dnsdist -u dnsdist -g dnsdist\2," %{buildroot}/%{_unitdir}/dnsdist@.service
%pre
getent group dnsdist >/dev/null || groupadd -r dnsdist
%{_mandir}/man1/*
%dir %{_sysconfdir}/dnsdist
%config(noreplace) %{_sysconfdir}/%{name}/dnsdist.conf
-/lib/systemd/system/dnsdist*
+%{_unitdir}/dnsdist*
Provides: powerdns-recursor = %{version}-%{release}
-%if 0%{?rhel} < 8
+%if 0%{?rhel} < 8 && 0%{?amzn} != 2023
BuildRequires: boost169-devel
%else
BuildRequires: boost-devel
BuildRequires: systemd
BuildRequires: systemd-devel
BuildRequires: openssl-devel
-BuildRequires: net-snmp-devel
-BuildRequires: libsodium-devel
BuildRequires: fstrm-devel
BuildRequires: libcurl-devel
+%if 0%{?amzn} != 2023
+BuildRequires: net-snmp-devel
+BuildRequires: libsodium-devel
+%endif
+
%ifarch aarch64
BuildRequires: lua-devel
%define lua_implementation lua
%configure \
--enable-option-checking=fatal \
--sysconfdir=%{_sysconfdir}/%{name} \
- --with-libsodium \
- --with-net-snmp \
--disable-silent-rules \
--disable-static \
--enable-unit-tests \
--enable-dnstap \
--with-libcap \
--with-lua=%{lua_implementation} \
- --enable-systemd --with-systemd=%{_unitdir}
+%if 0%{?amzn} != 2023
+ --with-libsodium \
+ --with-net-snmp \
+%endif
+ --enable-systemd --with-systemd=%{_unitdir} \
+ --enable-nod
make %{?_smp_mflags}
BuildRequires: krb5-devel
BuildRequires: p11-kit-devel
BuildRequires: libcurl-devel
-%if 0%{?rhel} < 8
+%if 0%{?rhel} < 8 && 0%{?amzn} != 2023
BuildRequires: boost169-devel
%else
BuildRequires: boost-devel
%endif
-BuildRequires: libsodium-devel
BuildRequires: bison
BuildRequires: openssl-devel
+%if 0%{?amzn} != 2023
+BuildRequires: libsodium-devel
+%endif
+
Requires(pre): shadow-utils
%ifarch aarch64
Summary: MySQL backend for %{name}
Group: System Environment/Daemons
Requires: %{name}%{?_isa} = %{version}-%{release}
-%if 0%{?rhel} < 8
+%if 0%{?rhel} < 8 && 0%{?amzn} != 2023
BuildRequires: mysql-devel
%else
BuildRequires: mariadb-connector-c-devel
Group: System Environment/Daemons
Requires: %{name}%{?_isa} = %{version}-%{release}
BuildRequires: yaml-cpp-devel
-%if 0%{?rhel} < 9
+%if 0%{?rhel} < 9 && 0%{?amzn} != 2023
BuildRequires: geoip-devel
%endif
BuildRequires: libmaxminddb-devel
--with-lua=%{lua_implementation} \
--with-dynmodules='%{backends}' \
--enable-tools \
+%if 0%{?amzn} != 2023
--with-libsodium \
+%endif
%if 0%{?amzn} != 2
--enable-ixfrdist \
%endif
BIND backend can only read this file, not write it.
-
.. _setting-bind-supermaster-config:
``bind-supermaster-config``
Your ``bind-config`` file should have an ``include`` statement to make sure this file is read on startup.
+.. _setting-bind-supermaster-destdir:
+
+``bind-supermaster-destdir``
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Each new zone configured via the autosecondary mechanism gets a zone file in this directory.
+This directory must be writable.
+
.. _bind-operation:
Operation
``lmdb-schema-version``
^^^^^^^^^^^^^^^^^^^^^^^
-Determines the maximum schema version LMDB is allowed to upgrade to. If the on disk LMDB database has a lower version that the current version of the LMDB schema the backend will not start, unless this setting allows it to upgrade the schema. If the version of the DB is already the same as the current schema version this setting is not checked and the backend starts normally.
+Determines the maximum schema version LMDB is allowed to upgrade to. If the on disk LMDB database has a lower version than the current version of the LMDB schema the backend will not start, unless this setting allows it to upgrade the schema. If the version of the DB is already the same as the current schema version this setting is not checked and the backend starts normally.
The default value for this setting is the highest supported schema version for the version of PowerDNS you are starting. if you want to prevent automatic schema upgrades, explicitly set this setting to the current default before upgrading PowerDNS.
4.3.x 2
4.4.x to 4.6.x 3
4.7.x and up 4
+4.8.x and up 5
================ ===================
.. _settings-lmdb-random-ids:
This number can be increased later, but never decreased.
Defaults to 100 on 32 bit systems, and 16000 on 64 bit systems.
+.. _settings-lmdb-flag-deleted:
+
+``lmdb-flag-deleted``
+^^^^^^^^^^^^^^^^^^^^^
+
+ .. versionadded:: 4.8.0
+
+Instead of deleting items from the database, flag them as deleted in the item's `Lightning Stream <https://doc.powerdns.com/lightningstream>`_ header.
+Only enable this if you are using Lightning Stream.
+
LMDB Structure
--------------
Changelogs for 4.7.x
====================
+.. changelog::
+ :version: 4.7.4
+ :released: 17th of April 2023
+
+ This is release 4.7.4 of the Authoritative Server.
+ It contains various bug fixes, some performance improvements, and one new feature (``pdnsutil list-member-zones``).
+
+ .. change::
+ :tags: Bug Fixes
+ :pullreq: 12742
+
+ Properly encode json string containing binary data
+
+ .. change::
+ :tags: Bug Fixes
+ :pullreq: 12741
+
+ Prevent a race during the processing of SVC auto-hints
+
+ .. change::
+ :tags: New Features
+ :pullreq: 12676
+
+ pdnsutil, implement list-member-zones (Kees Monshouwer)
+
+ .. change::
+ :tags: Bug Fixes
+ :pullreq: 12675
+
+ lmdb delete fixes and tests (Kees Monshouwer)
+
+ .. change::
+ :tags: Bug Fixes
+ :pullreq: 12429
+
+ minicurl: stop leaking hostlist memory
+
+ .. change::
+ :tags: Bug Fixes
+ :pullreq: 12521
+
+ ixfrdist fixes and improvements
+
+ .. change::
+ :tags: Improvements
+ :pullreq: 12458
+
+ lock.hh: include <stdexcept>
+
+ .. change::
+ :tags: Bug Fixes
+ :pullreq: 12746
+
+ Pick the right signer name when a NSEC name is also a delegation point
+
+ .. change::
+ :tags: Improvements
+ :pullreq: 12745
+
+ calm down the communicator loop
+
+ .. change::
+ :tags: Bug Fixes
+ :pullreq: 12744
+
+ Fix multiple-version IXFR request handling in ixfrdist
+
+ .. change::
+ :tags: Improvements
+ :pullreq: 12743
+
+ timeout handling for IXFRs as a client
+
.. changelog::
:version: 4.7.3
:released: 9th of December 2022
--- /dev/null
+Changelogs for 4.8.x
+====================
+
+.. changelog::
+ :version: 4.8.0-alpha1
+ :released: 21st of March 2023
+
+ This is release 4.8.0-alpha1 of the Authoritative Server.
+
+ In this release, the LMDB backend gains a new Lightning Stream-compatible schema, which requires a data migration (this is automatic, and there is no migration back to the old schema).
+ LMDB backend users should pay extra attention to the :doc:`Upgrade Notes <../upgrading>`.
+
+ `Lightning Stream <https://doc.powerdns.com/lightningstream>`_ is an `open source <https://github.com/PowerDNS/lightningstream>`_ data syncer that allows multiple nodes to sync LMDB (Lightning Memory-Mapped Database) data to and from an S3 (compatible) bucket. This has particular advantages in distributed and/or large-scale applications (i.e. ~1 million records), making DNS replication much, much easier to manage.
+
+ We are excited about how Lightning Stream simplifies running multiple distributed PowerDNS Authoritative servers, with full support for keeping record data and DNSSEC keys in sync, from multiple writers.
+
+ This version also contains various other small fixes and improvements.
+ Except for very minor ones, they are listed below.
+
+
+ .. change::
+ :tags: New Features
+ :pullreq: 12546
+
+ new lmdbbackend storage schema that is compatible with Lightning Stream
+
+ .. change::
+ :tags: Bug Fixes
+ :pullreq: 11101
+
+ save errno value as close(2) might clobber it
+
+ .. change::
+ :tags: Improvements
+ :pullreq: 11600, 12401, 12414, 12423, 12462, 12501, 12502, 12513, 12515, 12516, 12524, 12527, 12540, 12550
+
+ cleanup for OpenSSL 3.0 API
+
+
+ .. change::
+ :tags: Bug Fixes
+ :pullreq: 12127
+
+ Fix multiple-version IXFR request handling in ixfrdist (HÃ¥kan Lindqvist)
+
+ .. change::
+ :tags: Bug Fixes
+ :pullreq: 12260
+
+ Properly encode json strings containing binary data
+
+ .. change::
+ :tags: Bug Fixes
+ :pullreq: 12322
+
+ lmdb, fix TSIG key removal (Kees Monshouwer)
+
+ .. change::
+ :tags: Improvements
+ :pullreq: 11065
+
+ service files: Add more sandboxing options
+
+ .. change::
+ :tags: New Features
+ :pullreq: 12277
+
+ add byteslimit support to lua ifurlup() function
+
+ .. change::
+ :tags: Improvements
+ :pullreq: 12265
+
+ move alsoNotifies up into DNSBackend
+
+ .. change::
+ :tags: Bug Fixes
+ :pullreq: 12252
+
+ Update supported record types: remove A6 MAILA MAILB SIG and WKS, add ZONEMD
+
+ .. change::
+ :tags: Improvements
+ :pullreq: 11346
+
+ Basic abstraction for handling colored terminal output, respecting isatty(), --no-colors and NO_COLOR
+
+ .. change::
+ :tags: Bug Fixes
+ :pullreq: 12066
+
+ Detect invalid bytes in `makeBytesFromHex()`
+
+ .. change::
+ :tags: Improvements
+ :pullreq: 11858
+
+ change sdig output order (Kees Monshouwer)
+
+ .. change::
+ :tags: Bug Fixes
+ :pullreq: 11908
+
+ initialize zone cache after dropping privileges (Kees Monshouwer)
+
+ .. change::
+ :tags: Bug Fixes
+ :pullreq: 12659
+
+ Prevent a race during the processing of SVC auf-hints
+
+ .. change::
+ :tags: New Features
+ :pullreq: 12406
+
+ pdnsutil, implement list-member-zones (Kees Monshouwer)
+
+ .. change::
+ :tags: New Features
+ :pullreq: 12349
+
+ LUA: accept more hex formats in createForward[6]
+
+ .. change::
+ :tags: Bug Fixes
+ :pullreq: 12331
+
+ fix ColumnSize argument in SQLBindParameter #12324 (v1shnya)
.. toctree::
:maxdepth: 2
+ 4.8
4.7
4.6
4.5
If you believe you have found a security vulnerability that applies to DNS implementations generally, and you want to report this responsibly to a number of implementers, you might consider also using the `Open Source DNS Vulnerability mailing list <https://www.dns-oarc.net/oarc/oss-dns-vulns/>`_, managed by `DNS-OARC <https://www.dns-oarc.net/>`_.
-HackerOne
+YesWeHack
^^^^^^^^^
-Security issues can also be reported on `our HackerOne page <https://hackerone.com/powerdns>`_ and might fetch a bounty.
-Do note that only the PowerDNS software is in scope for the HackerOne program, not our websites or other infrastructure.
+Security issues can also be reported on `our YesWeHack page <https://yeswehack.com/programs/powerdns>`_ and might fetch a bounty.
+Do note that only the PowerDNS software is in scope for the YesWeHack program, not our websites or other infrastructure.
Disclosure Policy
^^^^^^^^^^^^^^^^^
If either IP address stops listening, only the other address will be
returned. If all IP addresses are down, all candidates are returned.
+You can also provide multiple sets of IP addresses to prioritize a set over the
+rest. If an IP address from the first set is available, it will be returned. If
+no addresses work in the first set, the second set is tried.
+
+For example::
+
+ www IN LUA A "ifportup(443, {{'192.0.2.1', '192.0.2.2'}, {'192.0.3.1'}})"
+
Because DNS queries require rapid answers, server availability is not checked
synchronously. In the background, a process periodically determines if IP
addresses mentioned in availability rules are, in fact, available.
-@ 86400 IN SOA pdns-public-ns1.powerdns.com. peter\.van\.dijk.powerdns.com. 2023030901 10800 3600 604800 10800
+@ 86400 IN SOA pdns-public-ns1.powerdns.com. peter\.van\.dijk.powerdns.com. 2023041700 10800 3600 604800 10800
@ 3600 IN NS pdns-public-ns1.powerdns.com.
@ 3600 IN NS pdns-public-ns2.powerdns.com.
auth-4.7.1.security-status 60 IN TXT "1 OK"
auth-4.7.2.security-status 60 IN TXT "1 OK"
auth-4.7.3.security-status 60 IN TXT "1 OK"
+auth-4.7.4.security-status 60 IN TXT "1 OK"
+auth-4.8.0-alpha1.security-status 60 IN TXT "1 Unsupported pre-release"
; Auth Debian
auth-3.4.1-2.debian.security-status 60 IN TXT "3 Upgrade now, see https://doc.powerdns.com/3/security/powerdns-advisory-2015-01/ and https://doc.powerdns.com/3/security/powerdns-advisory-2015-02/ and https://doc.powerdns.com/3/security/powerdns-advisory-2016-02/ and https://doc.powerdns.com/3/security/powerdns-advisory-2016-03/ and https://doc.powerdns.com/3/security/powerdns-advisory-2016-04/ and https://doc.powerdns.com/3/security/powerdns-advisory-2016-05/"
recursor-4.6.0.security-status 60 IN TXT "3 Upgrade now, see https://doc.powerdns.com/recursor/security-advisories/powerdns-advisory-2022-01.html"
recursor-4.6.1.security-status 60 IN TXT "3 Upgrade now, see https://doc.powerdns.com/recursor/security-advisories/powerdns-advisory-2022-02.html"
recursor-4.6.2.security-status 60 IN TXT "3 Upgrade now, see https://doc.powerdns.com/recursor/security-advisories/powerdns-advisory-2022-02.html"
-recursor-4.6.3.security-status 60 IN TXT "1 OK"
-recursor-4.6.4.security-status 60 IN TXT "1 OK"
-recursor-4.6.5.security-status 60 IN TXT "1 OK"
+recursor-4.6.3.security-status 60 IN TXT "3 Upgrade now, see https://doc.powerdns.com/recursor/security-advisories/powerdns-advisory-2023-02.html"
+recursor-4.6.4.security-status 60 IN TXT "3 Upgrade now, see https://doc.powerdns.com/recursor/security-advisories/powerdns-advisory-2023-02.html"
+recursor-4.6.5.security-status 60 IN TXT "3 Upgrade now, see https://doc.powerdns.com/recursor/security-advisories/powerdns-advisory-2023-02.html"
+recursor-4.6.6.security-status 60 IN TXT "1 OK"
recursor-4.7.0-alpha1.security-status 60 IN TXT "3 Unsupported pre-release (known vulnerabilities)"
recursor-4.7.0-beta1.security-status 60 IN TXT "3 Unsupported pre-release (known vulnerabilities)"
recursor-4.7.0-rc1.security-status 60 IN TXT "3 Unsupported pre-release (known vulnerabilities)"
recursor-4.7.0.security-status 60 IN TXT "3 Upgrade now, see https://doc.powerdns.com/recursor/security-advisories/powerdns-advisory-2022-02.html"
recursor-4.7.1.security-status 60 IN TXT "3 Upgrade now, see https://doc.powerdns.com/recursor/security-advisories/powerdns-advisory-2022-02.html"
-recursor-4.7.2.security-status 60 IN TXT "1 OK"
-recursor-4.7.3.security-status 60 IN TXT "1 OK"
-recursor-4.7.4.security-status 60 IN TXT "1 OK"
+recursor-4.7.2.security-status 60 IN TXT "3 Upgrade now, see https://doc.powerdns.com/recursor/security-advisories/powerdns-advisory-2023-02.html"
+recursor-4.7.3.security-status 60 IN TXT "3 Upgrade now, see https://doc.powerdns.com/recursor/security-advisories/powerdns-advisory-2023-02.html"
+recursor-4.7.4.security-status 60 IN TXT "3 Upgrade now, see https://doc.powerdns.com/recursor/security-advisories/powerdns-advisory-2023-02.html"
+recursor-4.7.5.security-status 60 IN TXT "1 OK"
recursor-4.8.0-alpha1.security-status 60 IN TXT "3 Unsupported pre-release (known vulnerabilities)"
recursor-4.8.0-beta1.security-status 60 IN TXT "3 Unsupported pre-release (known vulnerabilities)"
recursor-4.8.0-beta2.security-status 60 IN TXT "3 Unsupported pre-release (known vulnerabilities)"
recursor-4.8.0-rc1.security-status 60 IN TXT "3 Unsupported pre-release (known vulnerabilities)"
recursor-4.8.0.security-status 60 IN TXT "3 Upgrade now, see https://doc.powerdns.com/recursor/security-advisories/powerdns-advisory-2023-01.html"
-recursor-4.8.1.security-status 60 IN TXT "1 OK"
-recursor-4.8.2.security-status 60 IN TXT "1 OK"
-recursor-4.8.3.security-status 60 IN TXT "1 OK"
+recursor-4.8.1.security-status 60 IN TXT "3 Upgrade now, see https://doc.powerdns.com/recursor/security-advisories/powerdns-advisory-2023-02.html"
+recursor-4.8.2.security-status 60 IN TXT "3 Upgrade now, see https://doc.powerdns.com/recursor/security-advisories/powerdns-advisory-2023-02.html"
+recursor-4.8.3.security-status 60 IN TXT "3 Upgrade now, see https://doc.powerdns.com/recursor/security-advisories/powerdns-advisory-2023-02.html"
+recursor-4.8.4.security-status 60 IN TXT "1 OK"
+recursor-4.9.0-alpha1.security-status 60 IN TXT "1 Unsupported pre-release"
; Recursor Debian
recursor-3.6.2-2.debian.security-status 60 IN TXT "3 Upgrade now, see https://doc.powerdns.com/3/security/powerdns-advisory-2015-01/ and https://doc.powerdns.com/3/security/powerdns-advisory-2016-02/"
dnsdist-1.7.1.security-status 60 IN TXT "1 OK"
dnsdist-1.7.2.security-status 60 IN TXT "1 OK"
dnsdist-1.7.3.security-status 60 IN TXT "1 OK"
+dnsdist-1.7.4.security-status 60 IN TXT "1 OK"
dnsdist-1.8.0-rc1.security-status 60 IN TXT "2 Unsupported pre-release (no known vulnerabilities)"
-dnsdist-1.8.0-rc2.security-status 60 IN TXT "1 Unsupported pre-release"
+dnsdist-1.8.0-rc2.security-status 60 IN TXT "2 Unsupported pre-release (no known vulnerabilities)"
+dnsdist-1.8.0-rc3.security-status 60 IN TXT "2 Unsupported pre-release (no known vulnerabilities)"
+dnsdist-1.8.0.security-status 60 IN TXT "1 OK"
See the `3.X <https://doc.powerdns.com/3/authoritative/upgrading/>`__
upgrade notes if your version is older than 3.4.2.
+any version to 4.8.x
+--------------------
+
+LMDB backend
+^^^^^^^^^^^^
+
+Version 4.8.0-alpha1 ships a new version of the LMDB database schema (called version 5), for compatibility with `Lightning Stream <https://doc.powerdns.com/lightningstream>`_.
+This schema is somewhat experimental, and although we do intend to make databases portable/upgradeable to future releases in the 4.8 train, we currently make no promises.
+There is no downgrade process.
+If you upgrade your database (by starting 4.8.0 without ``lmdb-schema-version=4``), you cannot go back.
+
+Upgrading is only supported from database schema versions 3 and 4, that is, databases created/upgraded by version 4.4 and up.
+
4.6.0 to 4.7.0 or master
------------------------
#include <string.h>
#include <map>
+#ifndef DNSDIST
+#include "../../pdns/gettime.hh"
+#endif
+
using std::string;
using std::runtime_error;
using std::tuple;
return mdb_strerror(rc);
}
+#ifndef DNSDIST
+
+namespace LMDBLS {
+ // this also returns a pointer to the string's data. Do not hold on to it too long!
+ const LSheader* LSassertFixedHeaderSize(std::string_view val) {
+ // cerr<<"val.size()="<<val.size()<<endl;
+ if (val.size() < LS_MIN_HEADER_SIZE) {
+ throw std::runtime_error("LSheader too short");
+ }
+
+ return reinterpret_cast<const LSheader*>(val.data());
+ }
+
+ size_t LScheckHeaderAndGetSize(std::string_view val, size_t datasize) {
+ const LSheader* lsh = LSassertFixedHeaderSize(val);
+
+ if (lsh->d_version != 0) {
+ throw std::runtime_error("LSheader has wrong version (not zero)");
+ }
+
+ size_t headersize = LS_MIN_HEADER_SIZE;
+
+ unsigned char* tmp = (unsigned char*)val.data();
+ uint16_t numextra = (tmp[LS_NUMEXTRA_OFFSET] << 8) + tmp[LS_NUMEXTRA_OFFSET+1];
+
+ headersize += numextra * LS_BLOCK_SIZE;
+
+ if (val.size() < headersize) {
+ throw std::runtime_error("LSheader too short for promised extra data");
+ }
+
+ if (datasize && val.size() < (headersize+datasize)) {
+ throw std::runtime_error("Trailing data after LSheader has wrong size");
+ }
+
+ return headersize;
+ }
+
+ size_t LScheckHeaderAndGetSize(const MDBOutVal *val, size_t datasize) {
+ return LScheckHeaderAndGetSize(val->getNoStripHeader<string_view>(), datasize);
+ }
+
+ bool LSisDeleted(std::string_view val) {
+ const LSheader* lsh = LSassertFixedHeaderSize(val);
+
+ return (lsh->d_flags & LS_FLAG_DELETED) != 0;
+ }
+
+ bool s_flag_deleted{false};
+}
+
+#endif /* #ifndef DNSDIST */
+
MDBDbi::MDBDbi(MDB_env* env, MDB_txn* txn, const string_view dbname, int flags)
{
// A transaction that uses this function must finish (either commit or abort) before any other transaction in the process may use this function.
MDBRWTransactionImpl::MDBRWTransactionImpl(MDBEnv* parent, int flags):
MDBRWTransactionImpl(parent, openRWTransaction(parent, nullptr, flags))
{
+#ifndef DNSDIST
+ struct timespec tp;
+
+ gettime(&tp, true);
+
+ d_txtime = tp.tv_sec * (1000 * 1000 * 1000) + tp.tv_nsec;
+#endif
}
MDBRWTransactionImpl::~MDBRWTransactionImpl()
MDB_cursor *cursor;
int rc= mdb_cursor_open(d_txn, dbi, &cursor);
if(rc) {
- throw std::runtime_error("Error creating RO cursor: "+std::string(mdb_strerror(rc)));
+ throw std::runtime_error("Error creating RW cursor: "+std::string(mdb_strerror(rc)));
}
- return MDBRWCursor(d_rw_cursors, cursor);
+
+ return MDBRWCursor(d_rw_cursors, cursor, d_txn, d_txtime);
}
MDBRWCursor MDBRWTransactionImpl::getCursor(const MDBDbi &dbi)
#include <vector>
#include <algorithm>
+#include "config.h"
+
+#ifndef DNSDIST
+#include <boost/range/detail/common.hpp>
+#include <stdint.h>
+#include <netinet/in.h>
+#include <stdexcept>
+#include "../../pdns/misc.hh"
+#endif
+
using std::string_view;
/* open issues:
std::shared_ptr<MDBEnv> getMDBEnv(const char* fname, int flags, int mode, uint64_t mapsizeMB=(sizeof(void *)==4) ? 100 : 16000);
+#ifndef DNSDIST
+
+#if !defined(__BYTE_ORDER__) || !defined(__ORDER_LITTLE_ENDIAN__) || !defined(__ORDER_BIG_ENDIAN__)
+#error "your compiler did not define byte order macros"
+#endif
+
+// FIXME do something more portable than __builtin_bswap64
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+#define _LMDB_SAFE_BSWAP64MAYBE(x) __builtin_bswap64(x)
+#else
+#define _LMDB_SAFE_BSWAP64MAYBE(x) (x)
+#endif
+
+struct MDBOutVal; // forward declaration because of how the functions below tie in with MDBOutVal
+
+namespace LMDBLS {
+ class __attribute__((__packed__)) LSheader {
+ public:
+ uint64_t d_timestamp;
+ uint64_t d_txnid;
+ uint8_t d_version;
+ uint8_t d_flags;
+ uint32_t d_reserved;
+ uint16_t d_numextra;
+
+ LSheader(uint64_t timestamp, uint64_t txnid, uint8_t flags=0, uint8_t version=0, uint8_t numextra=0):
+ d_timestamp(_LMDB_SAFE_BSWAP64MAYBE(timestamp)),
+ d_txnid(_LMDB_SAFE_BSWAP64MAYBE(txnid)),
+ d_version(version),
+ d_flags(flags),
+ d_reserved(0),
+ d_numextra(htons(numextra))
+ {
+
+ }
+
+ std::string toString() {
+ return std::string((char*)this, sizeof(*this)) + std::string(ntohs(d_numextra)*8, '\0');
+ }
+
+
+ };
+
+ static_assert(sizeof(LSheader)==24, "LSheader size is wrong");
+
+ const size_t LS_MIN_HEADER_SIZE = sizeof(LSheader);
+ const size_t LS_BLOCK_SIZE = 8;
+ const size_t LS_NUMEXTRA_OFFSET = 22;
+ const uint8_t LS_FLAG_DELETED = 0x01;
+
+ const LSheader* LSassertFixedHeaderSize(std::string_view val);
+ size_t LScheckHeaderAndGetSize(std::string_view val, size_t datasize=0);
+ size_t LScheckHeaderAndGetSize(const MDBOutVal *val, size_t datasize=0);
+ bool LSisDeleted(std::string_view val);
+
+ extern bool s_flag_deleted;
+}
+
+#undef _LMDB_SAFE_BSWAP64MAYBE
+
+#endif /* ifndef DNSDIST */
struct MDBOutVal
return d_mdbval;
}
+#ifndef DNSDIST
template <class T,
- typename std::enable_if<std::is_arithmetic<T>::value,
+ typename std::enable_if<std::is_integral<T>::value,
T>::type* = nullptr> const
T get()
{
T ret;
- if(d_mdbval.mv_size != sizeof(T))
- throw std::runtime_error("MDB data has wrong length for type");
- memcpy(&ret, d_mdbval.mv_data, sizeof(T));
+ size_t offset = LMDBLS::LScheckHeaderAndGetSize(this, sizeof(T));
+
+ memcpy(&ret, reinterpret_cast<const char *>(d_mdbval.mv_data)+offset, sizeof(T));
+
+ static_assert(sizeof(T) == 4, "this code currently only supports 32 bit integers");
+ ret = ntohl(ret);
return ret;
}
template <class T,
- typename std::enable_if<std::is_class<T>::value,T>::type* = nullptr>
- T get() const;
-
- template<class T>
- T get_struct() const
+ typename std::enable_if<std::is_integral<T>::value,
+ T>::type* = nullptr> const
+ T getNoStripHeader()
{
T ret;
if(d_mdbval.mv_size != sizeof(T))
throw std::runtime_error("MDB data has wrong length for type");
memcpy(&ret, d_mdbval.mv_data, sizeof(T));
+
+ static_assert(sizeof(T) == 4, "this code currently only supports 32 bit integers");
+ ret = ntohl(ret);
return ret;
}
- template<class T>
- const T* get_struct_ptr() const
- {
- if(d_mdbval.mv_size != sizeof(T))
- throw std::runtime_error("MDB data has wrong length for type");
+#endif /* ifndef DNSDIST */
- return reinterpret_cast<const T*>(d_mdbval.mv_data);
- }
+ template <class T,
+ typename std::enable_if<std::is_class<T>::value,T>::type* = nullptr>
+ T get() const;
+#ifndef DNSDIST
+ template <class T,
+ typename std::enable_if<std::is_class<T>::value,T>::type* = nullptr>
+ T getNoStripHeader() const;
+#endif
+
MDB_val d_mdbval;
};
template<> inline std::string MDBOutVal::get<std::string>() const
{
+#ifndef DNSDIST
+ size_t offset = LMDBLS::LScheckHeaderAndGetSize(this);
+
+ return std::string((char*)d_mdbval.mv_data+offset, d_mdbval.mv_size-offset);
+}
+
+template<> inline std::string MDBOutVal::getNoStripHeader<std::string>() const
+{
+#endif
return std::string((char*)d_mdbval.mv_data, d_mdbval.mv_size);
}
template<> inline string_view MDBOutVal::get<string_view>() const
{
+#ifndef DNSDIST
+ size_t offset = LMDBLS::LScheckHeaderAndGetSize(this);
+
+ return string_view((char*)d_mdbval.mv_data+offset, d_mdbval.mv_size-offset);
+}
+
+template<> inline string_view MDBOutVal::getNoStripHeader<string_view>() const
+{
+#endif
return string_view((char*)d_mdbval.mv_data, d_mdbval.mv_size);
}
{
}
+#ifndef DNSDIST
template <class T,
- typename std::enable_if<std::is_arithmetic<T>::value,
+ typename std::enable_if<std::is_integral<T>::value,
T>::type* = nullptr>
MDBInVal(T i)
{
- memcpy(&d_memory[0], &i, sizeof(i));
+ static_assert(sizeof(T) == 4, "this code currently only supports 32 bit integers");
+ auto j = htonl(i); // all actual usage in our codebase is 32 bits. If that ever changes, this will break the build and avoid runtime surprises
+ memcpy(&d_memory[0], &j, sizeof(j));
+
d_mdbval.mv_size = sizeof(T);
d_mdbval.mv_data = d_memory;;
}
+#endif
MDBInVal(const char* s)
{
MDB_val d_mdbval;
private:
MDBInVal(){}
+#ifndef DNSDIST
char d_memory[sizeof(double)];
-
+#endif
};
-
-
-
class MDBROCursor;
class MDBROTransactionImpl
int rc = mdb_get(d_txn, dbi, const_cast<MDB_val*>(&key.d_mdbval),
const_cast<MDB_val*>(&val.d_mdbval));
- if(rc && rc != MDB_NOTFOUND)
+
+ if(rc && rc != MDB_NOTFOUND) {
throw std::runtime_error("getting data: " + std::string(mdb_strerror(rc)));
+ }
+
+#ifndef DNSDIST
+ if(rc != MDB_NOTFOUND) { // key was found, value was retrieved
+ std::string sval = val.getNoStripHeader<std::string>();
+ if (LMDBLS::LSisDeleted(sval)) { // but it was deleted
+ rc = MDB_NOTFOUND;
+ }
+ }
+#endif
return rc;
}
private:
std::vector<T*> *d_registry;
MDB_cursor* d_cursor{nullptr};
-
public:
+ MDB_txn* d_txn{nullptr}; // ew, public
+ uint64_t d_txtime{0};
+
MDBGenCursor():
d_registry(nullptr),
- d_cursor(nullptr)
+ d_cursor(nullptr),
+ d_txn(nullptr)
{
}
- MDBGenCursor(std::vector<T*> ®istry, MDB_cursor *cursor):
+ MDBGenCursor(std::vector<T*> ®istry, MDB_cursor *cursor, MDB_txn *txn=nullptr, uint64_t txtime=0):
d_registry(®istry),
- d_cursor(cursor)
+ d_cursor(cursor),
+ d_txn(txn),
+ d_txtime(txtime)
{
registry.emplace_back(static_cast<T*>(this));
}
close();
}
+ /*
+ to support (skip) entries marked deleted=1 in the LS header, we need to do some magic here
+ this table notes, for each cursor op:
+ * the maximum number of entries we may need to look at (1 or inf)
+ * the subsequent op that needs to be done to skip over a deleted entry (or MDB_NOTFOUND to give up and say no)
+ (table partially copied from http://www.lmdb.tech/doc/group__mdb.html#ga1206b2af8b95e7f6b0ef6b28708c9127 which I hope is a stable URL)
+ (ops only relevant for DUPSORT/DUPFIXED have been omitted)
+ (table is grouped by "skip op")
+
+ | base op | maxentries | skip op | doc description of base op
+ | MDB_FIRST | inf | MDB_NEXT | Position at first key/data item
+ | MDB_NEXT | inf | MDB_NEXT | Position at next data item
+ | MDB_SET_RANGE | inf | MDB_NEXT | Position at first key greater than or equal to specified key.
+ | MDB_LAST | inf | MDB_PREV | Position at last key/data item
+ | MDB_PREV | inf | MDB_PREV | Position at previous data item
+ | MDB_GET_CURRENT | 1 | MDB_NOTFOUND | Return key/data at current cursor position
+ | MDB_SET | 1 | MDB_NOTFOUND | Position at specified key
+ | MDB_SET_KEY | 1 | MDB_NOTFOUND | Position at specified key, return key + data
+ */
+
+private:
+ int skipDeleted(MDBOutVal& key, MDBOutVal& data, MDB_cursor_op op, int rc)
+ {
+#ifndef DNSDIST
+ // when we get here
+ // * mdb_cursor_get has been called once
+ // * it did not return an error, but it might have returned MDB_NOTFOUND
+ // * if it returned MDB_NOTFOUND, there is nothing for us to do and we pass that on
+
+ if (rc == MDB_NOTFOUND) {
+ return rc;
+ }
+
+ // when we get here
+ // * mdb_cursor_get has been called at least once
+ // * it found an entry, as far as LMDB is concerned, so key+data contain something
+ // * but that might be a LS deleted=1 entry
+ // * we know the cursor op that got us here
+
+ while (true) {
+ auto sval = data.getNoStripHeader<std::string_view>();
+
+ if (!LMDBLS::LSisDeleted(sval)) {
+ // done!
+
+ return rc;
+ }
+
+ // the found entry is set deleted, so we need to do something
+
+ // if this was a 1-entry op, this is the end
+ if (op == MDB_GET_CURRENT || op == MDB_SET || op == MDB_SET_KEY) {
+ return MDB_NOTFOUND;
+ }
+
+ // otherwise, we need to try to carry on
+ // all ops that do not map to NOTFOUND map to NEXT or PREV, including NEXT and PREV themselves
+ // so we just override the op to NEXT or PREV
+ if (op == MDB_FIRST || op == MDB_NEXT || op == MDB_SET_RANGE) {
+ op = MDB_NEXT;
+ }
+ else if (op == MDB_LAST || op == MDB_PREV) {
+ op = MDB_PREV;
+ }
+ else {
+ throw std::runtime_error("got unsupported mdb cursor op");
+ }
+
+ rc = mdb_cursor_get(d_cursor, &key.d_mdbval, &data.d_mdbval, op);
+ if(rc && rc != MDB_NOTFOUND) {
+ throw std::runtime_error("Unable to get from cursor: " + std::string(mdb_strerror(rc)));
+ }
+
+ if (rc == MDB_NOTFOUND) {
+ // we ended up finding nothing, so tell the caller
+ return rc;
+ }
+
+ // when we get here
+ // * the situation is just like the last time I wrote "when we get here"
+ // * except mdb_cursor_get has been called at least twice
+ // * so let's go back
+ }
+#else /* ifndef DNSDIST */
+ return rc;
+#endif
+ }
+
public:
int get(MDBOutVal& key, MDBOutVal& data, MDB_cursor_op op)
{
int rc = mdb_cursor_get(d_cursor, &key.d_mdbval, &data.d_mdbval, op);
if(rc && rc != MDB_NOTFOUND)
throw std::runtime_error("Unable to get from cursor: " + std::string(mdb_strerror(rc)));
- return rc;
+ return skipDeleted(key, data, op, rc);
}
int find(const MDBInVal& in, MDBOutVal& key, MDBOutVal& data)
int rc=mdb_cursor_get(d_cursor, const_cast<MDB_val*>(&key.d_mdbval), &data.d_mdbval, MDB_SET);
if(rc && rc != MDB_NOTFOUND)
throw std::runtime_error("Unable to find from cursor: " + std::string(mdb_strerror(rc)));
- return rc;
+ return skipDeleted(key, data, MDB_SET, rc);
}
int lower_bound(const MDBInVal& in, MDBOutVal& key, MDBOutVal& data)
int rc = mdb_cursor_get(d_cursor, const_cast<MDB_val*>(&key.d_mdbval), &data.d_mdbval, MDB_SET_RANGE);
if(rc && rc != MDB_NOTFOUND)
throw std::runtime_error("Unable to lower_bound from cursor: " + std::string(mdb_strerror(rc)));
- return rc;
+ return skipDeleted(key, data, MDB_SET_RANGE, rc);
}
int rc = mdb_cursor_get(d_cursor, const_cast<MDB_val*>(&key.d_mdbval), &data.d_mdbval, op);
if(rc && rc != MDB_NOTFOUND)
throw std::runtime_error("Unable to prevnext from cursor: " + std::string(mdb_strerror(rc)));
- return rc;
+ return skipDeleted(key, data, op, rc);
}
int next(MDBOutVal& key, MDBOutVal& data)
int rc = mdb_cursor_get(d_cursor, const_cast<MDB_val*>(&key.d_mdbval), &data.d_mdbval, op);
if(rc && rc != MDB_NOTFOUND)
throw std::runtime_error("Unable to next from cursor: " + std::string(mdb_strerror(rc)));
- return rc;
+ return skipDeleted(key, data, op, rc);
}
int current(MDBOutVal& key, MDBOutVal& data)
private:
std::vector<MDBRWCursor*> d_rw_cursors;
+ uint64_t d_txtime{0};
+
void closeRWCursors();
inline void closeRORWCursors() {
closeROCursors();
void clear(MDB_dbi dbi);
+#ifndef DNSDIST
void put(MDB_dbi dbi, const MDBInVal& key, const MDBInVal& val, int flags=0)
{
if(!d_txn)
throw std::runtime_error("Attempt to use a closed RW transaction for put");
int rc;
+
+ size_t txid = mdb_txn_id(d_txn);
+
+ if (d_txtime == 0) { throw std::runtime_error("got zero txtime"); }
+
+ std::string ins =
+ LMDBLS::LSheader(d_txtime, txid).toString()+
+ std::string((const char*)val.d_mdbval.mv_data, val.d_mdbval.mv_size);
+
+ MDBInVal pval = ins;
+
if((rc=mdb_put(d_txn, dbi,
const_cast<MDB_val*>(&key.d_mdbval),
- const_cast<MDB_val*>(&val.d_mdbval), flags)))
+ const_cast<MDB_val*>(&pval.d_mdbval), flags))) {
throw std::runtime_error("putting data: " + std::string(mdb_strerror(rc)));
+ }
}
-
-
- int del(MDBDbi& dbi, const MDBInVal& key, const MDBInVal& val)
+#else
+ void put(MDB_dbi dbi, const MDBInVal& key, const MDBInVal& val, int flags=0)
{
+ if(!d_txn)
+ throw std::runtime_error("Attempt to use a closed RW transaction for put");
int rc;
- rc=mdb_del(d_txn, dbi, (MDB_val*)&key.d_mdbval, (MDB_val*)&val.d_mdbval);
- if(rc && rc != MDB_NOTFOUND)
- throw std::runtime_error("deleting data: " + std::string(mdb_strerror(rc)));
- return rc;
+ if((rc=mdb_put(d_txn, dbi,
+ const_cast<MDB_val*>(&key.d_mdbval),
+ const_cast<MDB_val*>(&val.d_mdbval), flags)))
+ throw std::runtime_error("putting data: " + std::string(mdb_strerror(rc)));
}
+#endif
int del(MDBDbi& dbi, const MDBInVal& key)
{
rc=mdb_del(d_txn, dbi, (MDB_val*)&key.d_mdbval, 0);
if(rc && rc != MDB_NOTFOUND)
throw std::runtime_error("deleting data: " + std::string(mdb_strerror(rc)));
+#ifndef DNSDIST
+ if(rc != MDB_NOTFOUND && LMDBLS::s_flag_deleted) {
+ // if it did exist, we need to mark it as deleted now
+
+ size_t txid = mdb_txn_id(d_txn);
+ if (d_txtime == 0) { throw std::runtime_error("got zero txtime"); }
+
+ std::string ins =
+ // std::string((const char*)&txid, sizeof(txid)) +
+ LMDBLS::LSheader(d_txtime, txid, LMDBLS::LS_FLAG_DELETED).toString();
+
+ MDBInVal pval = ins;
+
+ if((rc=mdb_put(d_txn, dbi,
+ const_cast<MDB_val*>(&key.d_mdbval),
+ const_cast<MDB_val*>(&pval.d_mdbval), 0))) {
+ throw std::runtime_error("marking data deleted: " + std::string(mdb_strerror(rc)));
+ }
+ }
+#endif
return rc;
}
int rc = mdb_get(d_txn, dbi, const_cast<MDB_val*>(&key.d_mdbval),
const_cast<MDB_val*>(&val.d_mdbval));
- if(rc && rc != MDB_NOTFOUND)
- throw std::runtime_error("getting data: " + std::string(mdb_strerror(rc)));
- return rc;
- }
+ if(rc && rc != MDB_NOTFOUND) {
+ throw std::runtime_error("getting data: " + std::string(mdb_strerror(rc)));
+ }
+
+#ifndef DNSDIST
+ if(rc != MDB_NOTFOUND) { // key was found, value was retrieved
+ auto sval = val.getNoStripHeader<std::string_view>();
+ if (LMDBLS::LSisDeleted(sval)) { // but it was deleted
+ rc = MDB_NOTFOUND;
+ }
+ }
+#endif
- int get(MDBDbi& dbi, const MDBInVal& key, string_view& val)
- {
- MDBOutVal out;
- int rc = get(dbi, key, out);
- if(!rc)
- val = out.get<string_view>();
return rc;
}
MDBRWTransaction getRWTransaction();
MDBROTransaction getROTransaction();
+
};
/* "A cursor in a write-transaction can be closed before its transaction ends, and will otherwise be closed when its transaction ends"
MDBRWCursor &operator=(MDBRWCursor &&src) = default;
~MDBRWCursor() = default;
+#ifndef DNSDIST
void put(const MDBOutVal& key, const MDBInVal& data)
{
+ size_t txid = mdb_txn_id(this->d_txn);
+
+ if (d_txtime == 0) { throw std::runtime_error("got zero txtime"); }
+
+ std::string ins =
+ LMDBLS::LSheader(d_txtime, txid).toString()+
+ std::string((const char*)data.d_mdbval.mv_data, data.d_mdbval.mv_size);
+
+ MDBInVal pval = ins;
+
int rc = mdb_cursor_put(*this,
const_cast<MDB_val*>(&key.d_mdbval),
- const_cast<MDB_val*>(&data.d_mdbval), MDB_CURRENT);
+ const_cast<MDB_val*>(&pval.d_mdbval), MDB_CURRENT);
if(rc)
throw std::runtime_error("mdb_cursor_put: " + std::string(mdb_strerror(rc)));
}
-
-
- int put(const MDBOutVal& key, const MDBOutVal& data, int flags=0)
+#else
+ void put(const MDBOutVal& key, const MDBInVal& data)
{
- // XXX check errors
- return mdb_cursor_put(*this,
- const_cast<MDB_val*>(&key.d_mdbval),
- const_cast<MDB_val*>(&data.d_mdbval), flags);
+ int rc = mdb_cursor_put(*this,
+ const_cast<MDB_val*>(&key.d_mdbval),
+ const_cast<MDB_val*>(&data.d_mdbval), MDB_CURRENT);
+ if(rc)
+ throw std::runtime_error("mdb_cursor_put: " + std::string(mdb_strerror(rc)));
}
+#endif
+#ifndef DNSDIST
int del(int flags=0)
{
- return mdb_cursor_del(*this, flags);
- }
+ MDBOutVal key, val;
+ if (LMDBLS::s_flag_deleted) {
+ int rc_get = mdb_cursor_get (*this, &key.d_mdbval, &val.d_mdbval, MDB_GET_CURRENT);
+
+ if(rc_get) {
+ throw std::runtime_error("getting key to mark data as deleted: " + std::string(mdb_strerror(rc_get)));
+ }
+
+ size_t txid = mdb_txn_id(d_txn);
+ if (d_txtime == 0) { throw std::runtime_error("got zero txtime"); }
+
+ std::string ins =
+ LMDBLS::LSheader(d_txtime, txid, LMDBLS::LS_FLAG_DELETED).toString();
+
+ std::string skey((const char*)key.d_mdbval.mv_data, key.d_mdbval.mv_size);
+
+ MDBInVal pkey = MDBInVal(skey);
+ MDBInVal pval = ins;
+
+ int rc_put = mdb_cursor_put(*this,
+ const_cast<MDB_val*>(&pkey.d_mdbval),
+ const_cast<MDB_val*>(&pval.d_mdbval), 0 /* MDB_CURRENT */);
+ if(rc_put) {
+ throw std::runtime_error("marking data deleted: " + std::string(mdb_strerror(rc_put)));
+ }
+ return rc_put;
+ }
+ else {
+ // do a normal delete
+ return mdb_cursor_del(*this, flags);
+ }
+ }
+#endif
};
MDBOutVal maxidval, maxcontent;
unsigned int maxid{0};
if(!cursor.get(maxidval, maxcontent, MDB_LAST)) {
- maxid = maxidval.get<unsigned int>();
+ maxid = maxidval.getNoStripHeader<unsigned int>();
}
return maxid;
}
}
throw std::runtime_error("MDBGetRandomID() could not assign an unused random ID");
}
-
-
#pragma once
+#include <stdexcept>
#include <string_view>
#include <iostream>
#include "lmdb-safe.hh"
*/
unsigned int MDBGetRandomID(MDBRWTransaction& txn, MDBDbi& dbi);
+typedef std::vector<uint32_t> LMDBIDvec;
/** This is our serialization interface.
You can define your own serToString for your type if you know better
}
+namespace {
+ MDBOutVal getKeyFromCombinedKey(MDBInVal combined) {
+ if (combined.d_mdbval.mv_size < sizeof(uint32_t)) {
+ throw std::runtime_error("combined key too short to get ID from");
+ }
+
+ MDBOutVal ret;
+ ret.d_mdbval.mv_data = combined.d_mdbval.mv_data;
+ ret.d_mdbval.mv_size = combined.d_mdbval.mv_size - sizeof(uint32_t);
+
+ return ret;
+ }
+
+ MDBOutVal getIDFromCombinedKey(MDBInVal combined) {
+ if (combined.d_mdbval.mv_size < sizeof(uint32_t)) {
+ throw std::runtime_error("combined key too short to get ID from");
+ }
+
+ MDBOutVal ret;
+ ret.d_mdbval.mv_data = (char*) combined.d_mdbval.mv_data + combined.d_mdbval.mv_size - sizeof(uint32_t);
+ ret.d_mdbval.mv_size = sizeof(uint32_t);
+
+ return ret;
+ }
+
+ std::string makeCombinedKey(MDBInVal key, MDBInVal val)
+ {
+ std::string lenprefix(sizeof(uint16_t), '\0');
+ std::string skey((char*) key.d_mdbval.mv_data, key.d_mdbval.mv_size);
+ std::string sval((char*) val.d_mdbval.mv_data, val.d_mdbval.mv_size);
+
+ if (val.d_mdbval.mv_size != 0 && // empty val case, for range queries
+ val.d_mdbval.mv_size != 4) { // uint32_t case
+ throw std::runtime_error("got wrong size value in makeCombinedKey");
+ }
+
+ uint16_t len = htons(skey.size());
+ memcpy(lenprefix.data(), &len, sizeof(len));
+ std::string scombined = lenprefix + skey + sval;
+
+ return scombined;
+ }
+}
+
+
/** This is a struct that implements index operations, but
only the operations that are broadcast to all indexes.
Specifically, to deal with databases with less than the maximum
struct LMDBIndexOps
{
explicit LMDBIndexOps(Parent* parent) : d_parent(parent){}
+
void put(MDBRWTransaction& txn, const Class& t, uint32_t id, int flags=0)
{
- txn->put(d_idx, keyConv(d_parent->getMember(t)), id, flags);
+ std::string sempty("");
+ MDBInVal empty(sempty);
+
+ auto scombined = makeCombinedKey(keyConv(d_parent->getMember(t)), id);
+ MDBInVal combined(scombined);
+
+ txn->put(d_idx, combined, empty, flags);
}
void del(MDBRWTransaction& txn, const Class& t, uint32_t id)
{
- if(int rc = txn->del(d_idx, keyConv(d_parent->getMember(t)), id)) {
+ auto scombined = makeCombinedKey(keyConv(d_parent->getMember(t)), id);
+ MDBInVal combined(scombined);
+
+ if(int rc = txn->del(d_idx, combined)) {
throw std::runtime_error("Error deleting from index: " + std::string(mdb_strerror(rc)));
}
}
}
MDBDbi d_idx;
Parent* d_parent;
+
};
/** This is an index on a field in a struct, it derives from the LMDBIndexOps */
struct nullindex_t
{
template<typename Class>
- void put(MDBRWTransaction& txn, const Class& t, uint32_t id, int flags=0)
+ void put(MDBRWTransaction& /* txn */, const Class& /* t */, uint32_t /* id */, int /* flags */ =0)
{}
template<typename Class>
- void del(MDBRWTransaction& txn, const Class& t, uint32_t id)
+ void del(MDBRWTransaction& /* txn */, const Class& /* t */, uint32_t /* id */)
{}
- void openDB(std::shared_ptr<MDBEnv>& env, string_view str, int flags)
+ void openDB(std::shared_ptr<MDBEnv>& /* env */, string_view /* str */, int /* flags */)
{
}
TypedDBI(std::shared_ptr<MDBEnv> env, string_view name)
: d_env(env), d_name(name)
{
- d_main = d_env->openDB(name, MDB_CREATE | MDB_INTEGERKEY);
+ d_main = d_env->openDB(name, MDB_CREATE);
// now you might be tempted to go all MPL on this so we can get rid of the
// ugly macro. I'm not very receptive to that idea since it will make things
// EVEN uglier.
-#define openMacro(N) std::get<N>(d_tuple).openDB(d_env, std::string(name)+"_"#N, MDB_CREATE | MDB_DUPFIXED | MDB_DUPSORT);
+#define openMacro(N) std::get<N>(d_tuple).openDB(d_env, std::string(name)+"_"#N, MDB_CREATE);
openMacro(0);
openMacro(1);
openMacro(2);
ReadonlyOperations(Parent& parent) : d_parent(parent)
{}
- //! Number of entries in main database
- uint32_t size()
- {
- MDB_stat stat;
- mdb_stat(**d_parent.d_txn, d_parent.d_parent->d_main, &stat);
- return stat.ms_entries;
- }
-
- //! Number of entries in the various indexes - should be the same
- template<int N>
- uint32_t size()
- {
- MDB_stat stat;
- mdb_stat(**d_parent.d_txn, std::get<N>(d_parent.d_parent->d_tuple).d_idx, &stat);
- return stat.ms_entries;
- }
+ // //! Number of entries in main database
+ // uint32_t size()
+ // {
+ // MDB_stat stat;
+ // mdb_stat(**d_parent.d_txn, d_parent.d_parent->d_main, &stat);
+ // return stat.ms_entries;
+ // }
+
+ // //! Number of entries in the various indexes - should be the same
+ // template<int N>
+ // uint32_t size()
+ // {
+ // MDB_stat stat;
+ // mdb_stat(**d_parent.d_txn, std::get<N>(d_parent.d_parent->d_tuple).d_idx, &stat);
+ // return stat.ms_entries;
+ // }
//! Get item with id, from main table directly
bool get(uint32_t id, T& t)
template<int N>
uint32_t get(const typename std::tuple_element<N, tuple_t>::type::type& key, T& out)
{
- MDBOutVal id;
- if(!(*d_parent.d_txn)->get(std::get<N>(d_parent.d_parent->d_tuple).d_idx, keyConv(key), id)) {
- if(get(id.get<uint32_t>(), out))
- return id.get<uint32_t>();
+ // MDBOutVal out;
+ // uint32_t id;
+
+ // auto range = (*d_parent.d_txn)->prefix_range<N>(domain);
+
+ // auto range = prefix_range<N>(key);
+ LMDBIDvec ids;
+
+ get_multi<N>(key, ids);
+
+ if (ids.size() == 0) {
+ return 0;
}
- return 0;
- }
- //! Cardinality of index N
- template<int N>
- uint32_t cardinality()
- {
- auto cursor = (*d_parent.d_txn)->getCursor(std::get<N>(d_parent.d_parent->d_tuple).d_idx);
- bool first = true;
- MDBOutVal key, data;
- uint32_t count = 0;
- while(!cursor.get(key, data, first ? MDB_FIRST : MDB_NEXT_NODUP)) {
- ++count;
- first=false;
+ if (ids.size() == 1) {
+ if (get(ids[0], out)) {
+ return ids[0];
+ }
}
- return count;
+
+ throw std::runtime_error("in index get, found more than one item");
}
+ // //! Cardinality of index N
+ // template<int N>
+ // uint32_t cardinality()
+ // {
+ // auto cursor = (*d_parent.d_txn)->getCursor(std::get<N>(d_parent.d_parent->d_tuple).d_idx);
+ // bool first = true;
+ // MDBOutVal key, data;
+ // uint32_t count = 0;
+ // while(!cursor.get(key, data, first ? MDB_FIRST : MDB_NEXT_NODUP)) {
+ // ++count;
+ // first=false;
+ // }
+ // return count;
+ // }
+
//! End iterator type
struct eiter_t
{};
d_one_key(one_key), // should we stop at end of key? (equal range)
d_end(end)
{
- if(d_end)
+ if(d_end) {
return;
+ }
d_prefix.clear();
if(d_cursor.get(d_key, d_id, MDB_GET_CURRENT)) {
return;
}
+ if (d_id.d_mdbval.mv_size < LMDBLS::LS_MIN_HEADER_SIZE) {
+ throw std::runtime_error("got short value");
+ }
+
+ // MDBOutVal id = d_id;
+
+ // id.d_mdbval.mv_size -= LS_HEADER_SIZE;
+ // id.d_mdbval.mv_data = (char*)d_id.d_mdbval.mv_data + LS_HEADER_SIZE;
+
+
if(d_on_index) {
if((*d_parent->d_txn)->get(d_parent->d_parent->d_main, d_id, d_data))
throw std::runtime_error("Missing id in constructor");
return;
}
+ d_id = getIDFromCombinedKey(d_key);
+
if(d_on_index) {
if((*d_parent->d_txn)->get(d_parent->d_parent->d_main, d_id, d_data))
throw std::runtime_error("Missing id in constructor");
}
- std::function<bool(const MDBOutVal&)> filter;
+ // std::function<bool(const MDBOutVal&)> filter;
void del()
{
d_cursor.del();
}
- bool operator!=(const eiter_t& rhs) const
+ bool operator!=(const eiter_t& /* rhs */) const
{
return !d_end;
}
- bool operator==(const eiter_t& rhs) const
+ bool operator==(const eiter_t& /* rhs */) const
{
return d_end;
}
}
// implements generic ++ or --
- iter_t& genoperator(MDB_cursor_op dupop, MDB_cursor_op op)
+ iter_t& genoperator(MDB_cursor_op op)
{
MDBOutVal data;
int rc;
- next:;
- rc = d_cursor.get(d_key, d_id, d_one_key ? dupop : op);
- if(rc == MDB_NOTFOUND) {
+ // next:;
+ if (!d_one_key) {
+ rc = d_cursor.get(d_key, d_id, op);
+ }
+ if(d_one_key || rc == MDB_NOTFOUND) {
d_end = true;
}
else if(rc) {
throw std::runtime_error("in genoperator, " + std::string(mdb_strerror(rc)));
}
- else if(!d_prefix.empty() && d_key.get<std::string>().rfind(d_prefix, 0)!=0) {
+ else if(!d_prefix.empty() &&
+ // d_key.getNoStripHeader<std::string>().rfind(d_prefix, 0)!=0 &&
+ getKeyFromCombinedKey(d_key).template getNoStripHeader<std::string>() != d_prefix) {
d_end = true;
}
else {
+ // if (d_id.d_mdbval.mv_size < LS_HEADER_SIZE) throw std::runtime_error("got short value");
+
+ // MDBOutVal id = d_id;
+
+ // id.d_mdbval.mv_size -= LS_HEADER_SIZE;
+ // id.d_mdbval.mv_data = (char*)d_id.d_mdbval.mv_data+LS_HEADER_SIZE;
+
if(d_on_index) {
+ d_id = getIDFromCombinedKey(d_key);
if((*d_parent->d_txn)->get(d_parent->d_parent->d_main, d_id, data))
throw std::runtime_error("Missing id field");
- if(filter && !filter(data))
- goto next;
+ // if(filter && !filter(data))
+ // goto next;
serFromString(data.get<std::string>(), d_t);
}
else {
- if(filter && !filter(data))
- goto next;
+ // if(filter && !filter(data))
+ // goto next;
serFromString(d_id.get<std::string>(), d_t);
}
iter_t& operator++()
{
- return genoperator(MDB_NEXT_DUP, MDB_NEXT);
- }
- iter_t& operator--()
- {
- return genoperator(MDB_PREV_DUP, MDB_PREV);
+ return genoperator(MDB_NEXT);
}
+ // iter_t& operator--()
+ // {
+ // return genoperator(MDB_PREV);
+ // }
// get ID this iterator points to
uint32_t getID()
{
- if(d_on_index)
- return d_id.get<uint32_t>();
- else
- return d_key.get<uint32_t>();
+ if(d_on_index) {
+ // return d_id.get<uint32_t>();
+ return d_id.getNoStripHeader<uint32_t>();
+ }
+ else {
+ return d_key.getNoStripHeader<uint32_t>();
+ }
}
const MDBOutVal& getKey()
{
typename Parent::cursor_t cursor = (*d_parent.d_txn)->getCursor(std::get<N>(d_parent.d_parent->d_tuple).d_idx);
- std::string keystr = keyConv(key);
+ std::string keystr = makeCombinedKey(keyConv(key), MDBInVal(""));
MDBInVal in(keystr);
MDBOutVal out, id;
out.d_mdbval = in.d_mdbval;
{
typename Parent::cursor_t cursor = (*d_parent.d_txn)->getCursor(std::get<N>(d_parent.d_parent->d_tuple).d_idx);
- std::string keyString=keyConv(key);
+ std::string keyString=makeCombinedKey(keyConv(key), MDBInVal(""));
MDBInVal in(keyString);
MDBOutVal out, id;
out.d_mdbval = in.d_mdbval;
{
typename Parent::cursor_t cursor = (*d_parent.d_txn)->getCursor(std::get<N>(d_parent.d_parent->d_tuple).d_idx);
- std::string keyString=keyConv(key);
+ std::string keyString=makeCombined(keyConv(key), MDBInVal(""));
MDBInVal in(keyString);
MDBOutVal out, id;
out.d_mdbval = in.d_mdbval;
- if(cursor.get(out, id, MDB_SET_RANGE)) {
- // on_index, one_key, end
+ if(cursor.get(out, id, MDB_SET_RANGE) ||
+ getKeyFromCombinedKey(out).template getNoStripHeader<std::string>() != keyString) {
+ // on_index, one_key, end
return {iter_t{&d_parent, std::move(cursor), true, true, true}, eiter_t()};
}
return {iter_t(&d_parent, std::move(cursor), keyString), eiter_t()};
};
+ template<int N>
+ void get_multi(const typename std::tuple_element<N, tuple_t>::type::type& key, LMDBIDvec& ids)
+ {
+ // std::cerr<<"in get_multi"<<std::endl;
+ typename Parent::cursor_t cursor = (*d_parent.d_txn)->getCursor(std::get<N>(d_parent.d_parent->d_tuple).d_idx);
+
+ std::string keyString=makeCombinedKey(keyConv(key), MDBInVal(""));
+ MDBInVal in(keyString);
+ MDBOutVal out, id;
+ out.d_mdbval = in.d_mdbval;
+
+ int rc = cursor.get(out, id, MDB_SET_RANGE);
+
+ while (rc == 0) {
+ auto sout = out.getNoStripHeader<std::string>(); // FIXME: this (and many others) could probably be string_view
+ auto thiskey = getKeyFromCombinedKey(out);
+ auto sthiskey = thiskey.getNoStripHeader<std::string>();
+
+ if (sout.find(keyString) != 0) {
+ // we are no longer in range, so we are done
+ break;
+ }
+
+ if (sthiskey == keyString) {
+ auto _id = getIDFromCombinedKey(out);
+ ids.push_back(_id.getNoStripHeader<uint32_t>());
+ }
+
+ rc = cursor.get(out, id, MDB_NEXT);
+ }
+
+ if (rc != 0 && rc != MDB_NOTFOUND) {
+ throw std::runtime_error("error during get_multi");
+ }
+ };
+
Parent& d_parent;
};
}
else {
id = MDBGetMaxID(*d_txn, d_parent->d_main) + 1;
- flags = MDB_APPEND;
+ // FIXME: after dropping MDB_INTEGERKEY, we had to drop MDB_APPEND here. Check if this is an LMDB quirk.
+ // flags = MDB_APPEND;
}
}
(*d_txn)->put(d_parent->d_main, id, serToString(t), flags);
}
if (d_dolog)
- g_log << Logger::Warning << "Query " << ((long)(void*)this) << ": " << d_dtime.udiffNoReset() << " usec to execute" << endl;
+ g_log << Logger::Warning << "Query " << ((long)(void*)this) << ": " << d_dtime.udiffNoReset() << " us to execute" << endl;
return this;
}
bool hasNextRow()
{
if (d_dolog && d_residx == d_resnum) {
- g_log << Logger::Warning << "Query " << ((long)(void*)this) << ": " << d_dtime.udiffNoReset() << " total usec to last row" << endl;
+ g_log << Logger::Warning << "Query " << ((long)(void*)this) << ": " << d_dtime.udiffNoReset() << " us total to last row" << endl;
}
return d_residx < d_resnum;
}
d_cur_set = 0;
if (d_dolog) {
auto diff = d_dtime.udiffNoReset();
- g_log << Logger::Warning << "Query " << ((long)(void*)this) << ": " << diff << " usec to execute" << endl;
+ g_log << Logger::Warning << "Query " << ((long)(void*)this) << ": " << diff << " us to execute" << endl;
}
nextResult();
bool hasNextRow()
{
if (d_dolog && d_residx == d_resnum) {
- g_log << Logger::Warning << "Query " << ((long)(void*)this) << ": " << d_dtime.udiff() << " total usec to last row" << endl;
+ g_log << Logger::Warning << "Query " << ((long)(void*)this) << ": " << d_dtime.udiff() << " us total to last row" << endl;
}
return d_residx < d_resnum;
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
+#include <lmdb.h>
+#include <utility>
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "lmdbbackend.hh"
-#define SCHEMAVERSION 4
+#define SCHEMAVERSION 5
// List the class version here. Default is 0
BOOST_CLASS_VERSION(LMDBBackend::KeyDataDB, 1)
static int s_shards = 0;
static std::mutex s_lmdbStartupLock;
+std::pair<uint32_t, uint32_t> LMDBBackend::getSchemaVersionAndShards(std::string& filename)
+{
+ // cerr << "getting schema version for path " << filename << endl;
+
+ uint32_t schemaversion;
+
+ int rc;
+ MDB_env* env = nullptr;
+
+ if ((rc = mdb_env_create(&env)) != 0) {
+ throw std::runtime_error("mdb_env_create failed");
+ }
+
+ if ((rc = mdb_env_set_mapsize(env, 0)) != 0) {
+ throw std::runtime_error("mdb_env_set_mapsize failed");
+ }
+
+ if ((rc = mdb_env_set_maxdbs(env, 20)) != 0) { // we need 17: 1 {"pdns"} + 4 {"domains", "keydata", "tsig", "metadata"} * 2 {v4, v5} * 2 {main, index in _0}
+ mdb_env_close(env);
+ throw std::runtime_error("mdb_env_set_maxdbs failed");
+ }
+
+ if ((rc = mdb_env_open(env, filename.c_str(), MDB_NOSUBDIR | MDB_RDONLY, 0600)) != 0) {
+ if (rc == ENOENT) {
+ // we don't have a database yet! report schema 0, with 0 shards
+ return std::make_pair(0, 0);
+ }
+ mdb_env_close(env);
+ throw std::runtime_error("mdb_env_open failed");
+ }
+
+ MDB_txn* txn = nullptr;
+
+ if ((rc = mdb_txn_begin(env, NULL, MDB_RDONLY, &txn)) != 0) {
+ mdb_env_close(env);
+ throw std::runtime_error("mdb_txn_begin failed");
+ }
+
+ MDB_dbi dbi;
+
+ if ((rc = mdb_dbi_open(txn, "pdns", 0, &dbi)) != 0) {
+ if (rc == MDB_NOTFOUND) {
+ // this means nothing has been inited yet
+ // we pretend this means 5
+ mdb_txn_abort(txn);
+ mdb_env_close(env);
+ return std::make_pair(5, 0);
+ }
+ mdb_txn_abort(txn);
+ mdb_env_close(env);
+ throw std::runtime_error("mdb_dbi_open failed");
+ }
+
+ MDB_val key, data;
+
+ key.mv_data = (char*)"schemaversion";
+ key.mv_size = strlen((char*)key.mv_data);
+
+ if ((rc = mdb_get(txn, dbi, &key, &data)) != 0) {
+ if (rc == MDB_NOTFOUND) {
+ // this means nothing has been inited yet
+ // we pretend this means 5
+ mdb_txn_abort(txn);
+ mdb_env_close(env);
+ return std::make_pair(5, 0);
+ }
+
+ throw std::runtime_error("mdb_get pdns.schemaversion failed");
+ }
+
+ if (data.mv_size == 4) {
+ // schemaversion is < 5 and is stored in 32 bits, in host order
+
+ memcpy(&schemaversion, data.mv_data, data.mv_size);
+ }
+ else if (data.mv_size >= LMDBLS::LS_MIN_HEADER_SIZE + sizeof(schemaversion)) {
+ // schemaversion presumably is 5, stored in 32 bits, network order, after the LS header
+
+ // FIXME: get actual header size (including extension blocks) instead of just reading from the back
+ // FIXME: add a test for reading schemaversion and shards (and actual data, later) when there are variably sized headers
+ memcpy(&schemaversion, (char*)data.mv_data + data.mv_size - sizeof(schemaversion), sizeof(schemaversion));
+ schemaversion = ntohl(schemaversion);
+ }
+ else {
+ throw std::runtime_error("pdns.schemaversion had unexpected size");
+ }
+
+ uint32_t shards;
+
+ key.mv_data = (char*)"shards";
+ key.mv_size = strlen((char*)key.mv_data);
+
+ if ((rc = mdb_get(txn, dbi, &key, &data)) != 0) {
+ if (rc == MDB_NOTFOUND) {
+ cerr << "schemaversion was set, but shards was not. Dazed and confused, trying to exit." << endl;
+ mdb_txn_abort(txn);
+ mdb_env_close(env);
+ exit(1);
+ }
+
+ throw std::runtime_error("mdb_get pdns.shards failed");
+ }
+
+ if (data.mv_size == 4) {
+ // 'shards' is stored in 32 bits, in host order
+
+ memcpy(&shards, data.mv_data, data.mv_size);
+ }
+ else if (data.mv_size >= LMDBLS::LS_MIN_HEADER_SIZE + sizeof(shards)) {
+ // FIXME: get actual header size (including extension blocks) instead of just reading from the back
+ memcpy(&shards, (char*)data.mv_data + data.mv_size - sizeof(shards), sizeof(shards));
+ shards = ntohl(shards);
+ }
+ else {
+ throw std::runtime_error("pdns.shards had unexpected size");
+ }
+
+ mdb_txn_abort(txn);
+ mdb_env_close(env);
+
+ return std::make_pair(schemaversion, shards);
+}
+
+namespace
+{
+// copy sdbi to tdbi, prepending an empty LS header (24 bytes of '\0') to all values
+void copyDBIAndAddLSHeader(MDB_txn* txn, MDB_dbi sdbi, MDB_dbi tdbi)
+{
+ // FIXME: clear out target dbi first
+
+ std::string header(LMDBLS::LS_MIN_HEADER_SIZE, '\0');
+ int rc;
+
+ MDB_cursor* cur;
+
+ if ((rc = mdb_cursor_open(txn, sdbi, &cur)) != 0) {
+ throw std::runtime_error("mdb_cursur_open failed");
+ }
+
+ MDB_val key, data;
+
+ rc = mdb_cursor_get(cur, &key, &data, MDB_FIRST);
+
+ while (rc == 0) {
+ std::string skey(reinterpret_cast<const char*>(key.mv_data), key.mv_size);
+ std::string sdata(reinterpret_cast<const char*>(data.mv_data), data.mv_size);
+
+ std::string stdata = header + sdata;
+
+ // cerr<<"got key="<<makeHexDump(skey)<<", data="<<makeHexDump(sdata)<<", sdata="<<makeHexDump(stdata)<<endl;
+
+ MDB_val tkey;
+ MDB_val tdata;
+
+ tkey.mv_data = const_cast<char*>(skey.c_str());
+ tkey.mv_size = skey.size();
+ tdata.mv_data = const_cast<char*>(stdata.c_str());
+ tdata.mv_size = stdata.size();
+
+ if ((rc = mdb_put(txn, tdbi, &tkey, &tdata, 0)) != 0) {
+ throw std::runtime_error("mdb_put failed");
+ }
+
+ rc = mdb_cursor_get(cur, &key, &data, MDB_NEXT);
+ }
+ if (rc != MDB_NOTFOUND) {
+ cerr << "rc=" << rc << endl;
+ throw std::runtime_error("error while iterating dbi");
+ }
+}
+
+// migrated a typed DBI:
+// 1. change keys (uint32_t) from host to network order
+// 2. prepend empty LS header to values
+void copyTypedDBI(MDB_txn* txn, MDB_dbi sdbi, MDB_dbi tdbi)
+{
+ // FIXME: clear out target dbi first
+
+ std::string header(LMDBLS::LS_MIN_HEADER_SIZE, '\0');
+ int rc;
+
+ MDB_cursor* cur;
+
+ if ((rc = mdb_cursor_open(txn, sdbi, &cur)) != 0) {
+ throw std::runtime_error("mdb_cursur_open failed");
+ }
+
+ MDB_val key, data;
+
+ rc = mdb_cursor_get(cur, &key, &data, MDB_FIRST);
+
+ while (rc == 0) {
+ // std::string skey((char*) key.mv_data, key.mv_size);
+ std::string sdata(reinterpret_cast<const char*>(data.mv_data), data.mv_size);
+
+ std::string stdata = header + sdata;
+
+ uint32_t id;
+
+ if (key.mv_size != sizeof(uint32_t)) {
+ throw std::runtime_error("got non-uint32_t key in TypedDBI");
+ }
+
+ memcpy(&id, key.mv_data, sizeof(uint32_t));
+
+ id = htonl(id);
+
+ // cerr<<"got key="<<makeHexDump(skey)<<", data="<<makeHexDump(sdata)<<", sdata="<<makeHexDump(stdata)<<endl;
+
+ MDB_val tkey;
+ MDB_val tdata;
+
+ tkey.mv_data = reinterpret_cast<char*>(&id);
+ tkey.mv_size = sizeof(uint32_t);
+ tdata.mv_data = const_cast<char*>(stdata.c_str());
+ tdata.mv_size = stdata.size();
+
+ if ((rc = mdb_put(txn, tdbi, &tkey, &tdata, 0)) != 0) {
+ throw std::runtime_error("mdb_put failed");
+ }
+
+ rc = mdb_cursor_get(cur, &key, &data, MDB_NEXT);
+ }
+ if (rc != MDB_NOTFOUND) {
+ cerr << "rc=" << rc << endl;
+ throw std::runtime_error("error while iterating dbi");
+ }
+}
+
+// migrating an index DBI:
+// newkey = oldkey.len(), oldkey, htonl(oldvalue)
+// newvalue = empty lsheader
+void copyIndexDBI(MDB_txn* txn, MDB_dbi sdbi, MDB_dbi tdbi)
+{
+ // FIXME: clear out target dbi first
+
+ std::string header(LMDBLS::LS_MIN_HEADER_SIZE, '\0');
+ int rc;
+
+ MDB_cursor* cur;
+
+ if ((rc = mdb_cursor_open(txn, sdbi, &cur)) != 0) {
+ throw std::runtime_error("mdb_cursur_open failed");
+ }
+
+ MDB_val key, data;
+
+ rc = mdb_cursor_get(cur, &key, &data, MDB_FIRST);
+
+ while (rc == 0) {
+ std::string lenprefix(sizeof(uint16_t), '\0');
+ std::string skey((char*)key.mv_data, key.mv_size);
+
+ uint32_t id;
+
+ if (data.mv_size != sizeof(uint32_t)) {
+ throw std::runtime_error("got non-uint32_t ID value in IndexDBI");
+ }
+
+ memcpy((void*)&id, data.mv_data, sizeof(uint32_t));
+ id = htonl(id);
+
+ uint16_t len = htons(skey.size());
+ memcpy((void*)lenprefix.data(), &len, sizeof(len));
+ std::string stkey = lenprefix + skey + std::string((char*)&id, sizeof(uint32_t));
+
+ MDB_val tkey;
+ MDB_val tdata;
+
+ tkey.mv_data = (char*)stkey.c_str();
+ tkey.mv_size = stkey.size();
+ tdata.mv_data = (char*)header.c_str();
+ tdata.mv_size = header.size();
+
+ if ((rc = mdb_put(txn, tdbi, &tkey, &tdata, 0)) != 0) {
+ throw std::runtime_error("mdb_put failed");
+ }
+
+ rc = mdb_cursor_get(cur, &key, &data, MDB_NEXT);
+ }
+ if (rc != MDB_NOTFOUND) {
+ throw std::runtime_error("error while iterating dbi");
+ }
+}
+
+}
+
+bool LMDBBackend::upgradeToSchemav5(std::string& filename)
+{
+ int rc;
+
+ auto currentSchemaVersionAndShards = getSchemaVersionAndShards(filename);
+ uint32_t currentSchemaVersion = currentSchemaVersionAndShards.first;
+ uint32_t shards = currentSchemaVersionAndShards.second;
+
+ if (currentSchemaVersion != 3 && currentSchemaVersion != 4) {
+ throw std::runtime_error("upgrade to v5 requested but current schema is not v3 or v4, stopping");
+ }
+
+ MDB_env* env = nullptr;
+
+ if ((rc = mdb_env_create(&env)) != 0) {
+ throw std::runtime_error("mdb_env_create failed");
+ }
+
+ if ((rc = mdb_env_set_maxdbs(env, 20)) != 0) {
+ mdb_env_close(env);
+ throw std::runtime_error("mdb_env_set_maxdbs failed");
+ }
+
+ if ((rc = mdb_env_open(env, filename.c_str(), MDB_NOSUBDIR, 0600)) != 0) {
+ mdb_env_close(env);
+ throw std::runtime_error("mdb_env_open failed");
+ }
+
+ MDB_txn* txn = nullptr;
+
+ if ((rc = mdb_txn_begin(env, NULL, 0, &txn)) != 0) {
+ mdb_env_close(env);
+ throw std::runtime_error("mdb_txn_begin failed");
+ }
+
+ std::cerr << "migrating shards" << std::endl;
+ for (uint32_t i = 0; i < shards; i++) {
+ string shardfile = filename + "-" + std::to_string(i);
+ if (access(shardfile.c_str(), F_OK) < 0) {
+ if (errno == ENOENT) {
+ // apparently this shard doesn't exist yet, moving on
+ std::cerr << "shard " << shardfile << " not found, continuing" << std::endl;
+ continue;
+ }
+ }
+
+ std::cerr << "migrating shard " << shardfile << std::endl;
+ MDB_env* shenv = nullptr;
+
+ if ((rc = mdb_env_create(&shenv)) != 0) {
+ throw std::runtime_error("mdb_env_create failed");
+ }
+
+ if ((rc = mdb_env_set_maxdbs(shenv, 8)) != 0) {
+ mdb_env_close(env);
+ throw std::runtime_error("mdb_env_set_maxdbs failed");
+ }
+
+ if ((rc = mdb_env_open(shenv, shardfile.c_str(), MDB_NOSUBDIR, 0600)) != 0) {
+ mdb_env_close(env);
+ throw std::runtime_error("mdb_env_open failed");
+ }
+
+ MDB_txn* shtxn = nullptr;
+
+ if ((rc = mdb_txn_begin(shenv, NULL, 0, &shtxn)) != 0) {
+ mdb_env_close(env);
+ throw std::runtime_error("mdb_txn_begin failed");
+ }
+
+ MDB_dbi shdbi;
+
+ if ((rc = mdb_dbi_open(shtxn, "records", 0, &shdbi)) != 0) {
+ if (rc == MDB_NOTFOUND) {
+ mdb_txn_abort(shtxn);
+ mdb_env_close(shenv);
+ continue;
+ }
+ mdb_txn_abort(shtxn);
+ mdb_env_close(shenv);
+ throw std::runtime_error("mdb_dbi_open shard records failed");
+ }
+
+ MDB_dbi shdbi2;
+
+ if ((rc = mdb_dbi_open(shtxn, "records_v5", MDB_CREATE, &shdbi2)) != 0) {
+ mdb_dbi_close(shenv, shdbi);
+ mdb_txn_abort(shtxn);
+ mdb_env_close(shenv);
+ throw std::runtime_error("mdb_dbi_open shard records_v5 failed");
+ }
+
+ try {
+ copyDBIAndAddLSHeader(shtxn, shdbi, shdbi2);
+ }
+ catch (std::exception& e) {
+ mdb_dbi_close(shenv, shdbi2);
+ mdb_dbi_close(shenv, shdbi);
+ mdb_txn_abort(shtxn);
+ mdb_env_close(shenv);
+ throw std::runtime_error("copyDBIAndAddLSHeader failed");
+ }
+
+ cerr << "shard mbd_drop=" << mdb_drop(shtxn, shdbi, 1) << endl;
+ mdb_txn_commit(shtxn);
+ mdb_dbi_close(shenv, shdbi2);
+ mdb_env_close(shenv);
+ }
+
+ std::array<MDB_dbi, 4> fromtypeddbi;
+ std::array<MDB_dbi, 4> totypeddbi;
+
+ int index = 0;
+
+ for (const std::string& dbname : {"domains", "keydata", "tsig", "metadata"}) {
+ std::cerr << "migrating " << dbname << std::endl;
+ std::string tdbname = dbname + "_v5";
+
+ if ((rc = mdb_dbi_open(txn, dbname.c_str(), 0, &fromtypeddbi[index])) != 0) {
+ mdb_txn_abort(txn);
+ mdb_env_close(env);
+ throw std::runtime_error("mdb_dbi_open typeddbi failed");
+ }
+
+ if ((rc = mdb_dbi_open(txn, tdbname.c_str(), MDB_CREATE, &totypeddbi[index])) != 0) {
+ mdb_dbi_close(env, fromtypeddbi[index]);
+ mdb_txn_abort(txn);
+ mdb_env_close(env);
+ throw std::runtime_error("mdb_dbi_open typeddbi target failed");
+ }
+
+ try {
+ copyTypedDBI(txn, fromtypeddbi[index], totypeddbi[index]);
+ }
+ catch (std::exception& e) {
+ mdb_dbi_close(env, totypeddbi[index]);
+ mdb_dbi_close(env, fromtypeddbi[index]);
+ mdb_txn_abort(txn);
+ mdb_env_close(env);
+ throw std::runtime_error("copyTypedDBI failed");
+ }
+
+ // mdb_dbi_close(env, dbi2);
+ // mdb_dbi_close(env, dbi);
+ std::cerr << "migrated " << dbname << std::endl;
+
+ index++;
+ }
+
+ std::array<MDB_dbi, 4> fromindexdbi;
+ std::array<MDB_dbi, 4> toindexdbi;
+
+ index = 0;
+
+ for (const std::string& dbname : {"domains", "keydata", "tsig", "metadata"}) {
+ std::string fdbname = dbname + "_0";
+ std::cerr << "migrating " << dbname << std::endl;
+ std::string tdbname = dbname + "_v5_0";
+
+ if ((rc = mdb_dbi_open(txn, fdbname.c_str(), 0, &fromindexdbi[index])) != 0) {
+ mdb_txn_abort(txn);
+ mdb_env_close(env);
+ throw std::runtime_error("mdb_dbi_open indexdbi failed");
+ }
+
+ if ((rc = mdb_dbi_open(txn, tdbname.c_str(), MDB_CREATE, &toindexdbi[index])) != 0) {
+ mdb_dbi_close(env, fromindexdbi[index]);
+ mdb_txn_abort(txn);
+ mdb_env_close(env);
+ throw std::runtime_error("mdb_dbi_open indexdbi target failed");
+ }
+
+ try {
+ copyIndexDBI(txn, fromindexdbi[index], toindexdbi[index]);
+ }
+ catch (std::exception& e) {
+ mdb_dbi_close(env, toindexdbi[index]);
+ mdb_dbi_close(env, fromindexdbi[index]);
+ mdb_txn_abort(txn);
+ mdb_env_close(env);
+ throw std::runtime_error("copyIndexDBI failed");
+ }
+
+ // mdb_dbi_close(env, dbi2);
+ // mdb_dbi_close(env, dbi);
+ std::cerr << "migrated " << dbname << std::endl;
+
+ index++;
+ }
+
+ MDB_dbi dbi;
+
+ // finally, migrate the pdns db
+ if ((rc = mdb_dbi_open(txn, "pdns", 0, &dbi)) != 0) {
+ mdb_txn_abort(txn);
+ mdb_env_close(env);
+ throw std::runtime_error("mdb_dbi_open pdns failed");
+ }
+
+ MDB_val key, data;
+
+ std::string header(LMDBLS::LS_MIN_HEADER_SIZE, '\0');
+
+ for (const std::string& keyname : {"schemaversion", "shards"}) {
+ cerr << "migrating pdns." << keyname << endl;
+
+ key.mv_data = (char*)keyname.c_str();
+ key.mv_size = keyname.size();
+
+ if ((rc = mdb_get(txn, dbi, &key, &data))) {
+ throw std::runtime_error("mdb_get pdns.shards failed");
+ }
+
+ uint32_t value;
+
+ if (data.mv_size != sizeof(uint32_t)) {
+ throw std::runtime_error("got non-uint32_t key");
+ }
+
+ memcpy((void*)&value, data.mv_data, sizeof(uint32_t));
+
+ value = htonl(value);
+ if (keyname == "schemaversion") {
+ value = htonl(5);
+ }
+
+ std::string sdata((char*)data.mv_data, data.mv_size);
+
+ std::string stdata = header + std::string((char*)&value, sizeof(uint32_t));
+ ;
+
+ MDB_val tdata;
+
+ tdata.mv_data = (char*)stdata.c_str();
+ tdata.mv_size = stdata.size();
+
+ if ((rc = mdb_put(txn, dbi, &key, &tdata, 0)) != 0) {
+ throw std::runtime_error("mdb_put failed");
+ }
+ }
+
+ for (const std::string& keyname : {"uuid"}) {
+ cerr << "migrating pdns." << keyname << endl;
+
+ key.mv_data = (char*)keyname.c_str();
+ key.mv_size = keyname.size();
+
+ if ((rc = mdb_get(txn, dbi, &key, &data))) {
+ throw std::runtime_error("mdb_get pdns.shards failed");
+ }
+
+ std::string sdata((char*)data.mv_data, data.mv_size);
+
+ std::string stdata = header + sdata;
+
+ MDB_val tdata;
+
+ tdata.mv_data = (char*)stdata.c_str();
+ tdata.mv_size = stdata.size();
+
+ if ((rc = mdb_put(txn, dbi, &key, &tdata, 0)) != 0) {
+ throw std::runtime_error("mdb_put failed");
+ }
+ }
+
+ for (int i = 0; i < 4; i++) {
+ mdb_drop(txn, fromtypeddbi[i], 1);
+ mdb_drop(txn, fromindexdbi[i], 1);
+ }
+
+ cerr << "txn commit=" << mdb_txn_commit(txn) << endl;
+
+ for (int i = 0; i < 4; i++) {
+ mdb_dbi_close(env, totypeddbi[i]);
+ mdb_dbi_close(env, toindexdbi[i]);
+ }
+ mdb_env_close(env);
+
+ // throw std::runtime_error("migration done");
+ cerr << "migration done" << endl;
+ // exit(1);
+ return true;
+}
+
LMDBBackend::LMDBBackend(const std::string& suffix)
{
// overlapping domain ids in combination with relative names are a recipe for disaster
catch (const std::exception& e) {
throw std::runtime_error(std::string("Unable to parse the 'map-size' LMDB value: ") + e.what());
}
- d_tdomains = std::make_shared<tdomains_t>(getMDBEnv(getArg("filename").c_str(), MDB_NOSUBDIR | d_asyncFlag, 0600, mapSize), "domains");
- d_tmeta = std::make_shared<tmeta_t>(d_tdomains->getEnv(), "metadata");
- d_tkdb = std::make_shared<tkdb_t>(d_tdomains->getEnv(), "keydata");
- d_ttsig = std::make_shared<ttsig_t>(d_tdomains->getEnv(), "tsig");
- auto pdnsdbi = d_tdomains->getEnv()->openDB("pdns", MDB_CREATE);
+ LMDBLS::s_flag_deleted = mustDo("flag-deleted");
+
+ bool opened = false;
if (s_first) {
std::lock_guard<std::mutex> l(s_lmdbStartupLock);
if (s_first) {
- auto txn = d_tdomains->getEnv()->getRWTransaction();
+ auto filename = getArg("filename");
- uint32_t schemaversion = 1;
- MDBOutVal _schemaversion;
- if (!txn->get(pdnsdbi, "schemaversion", _schemaversion)) {
- schemaversion = _schemaversion.get<uint32_t>();
+ auto currentSchemaVersionAndShards = getSchemaVersionAndShards(filename);
+ uint32_t currentSchemaVersion = currentSchemaVersionAndShards.first;
+ // std::cerr<<"current schema version: "<<currentSchemaVersion<<", shards="<<currentSchemaVersionAndShards.second<<std::endl;
+
+ if (getArgAsNum("schema-version") != SCHEMAVERSION) {
+ throw std::runtime_error("This version of the lmdbbackend only supports schema version 5. Configuration demands a lower version. Not starting up.");
+ }
+
+ if (currentSchemaVersion > 0 && currentSchemaVersion < 3) {
+ throw std::runtime_error("this version of the lmdbbackend can only upgrade from schema v3/v4 to v5. Upgrading from older schemas is not yet supported.");
}
- if (schemaversion != SCHEMAVERSION) {
- if (getArgAsNum("schema-version") != SCHEMAVERSION) {
- throw std::runtime_error("Expected LMDB schema version " + std::to_string(SCHEMAVERSION) + " but got " + std::to_string(schemaversion));
+ if (currentSchemaVersion == 0) {
+ // no database is present yet, we can just create them
+ currentSchemaVersion = 5;
+ }
+
+ if (currentSchemaVersion == 3 || currentSchemaVersion == 4) {
+ if (!upgradeToSchemav5(filename)) {
+ throw std::runtime_error("Failed to perform LMDB schema version upgrade from v4 to v5");
}
- txn->put(pdnsdbi, "schemaversion", SCHEMAVERSION);
+ currentSchemaVersion = 5;
+ }
+
+ if (currentSchemaVersion != 5) {
+ throw std::runtime_error("Somehow, we are not at schema version 5. Giving up");
}
+ d_tdomains = std::make_shared<tdomains_t>(getMDBEnv(getArg("filename").c_str(), MDB_NOSUBDIR | d_asyncFlag, 0600, mapSize), "domains_v5");
+ d_tmeta = std::make_shared<tmeta_t>(d_tdomains->getEnv(), "metadata_v5");
+ d_tkdb = std::make_shared<tkdb_t>(d_tdomains->getEnv(), "keydata_v5");
+ d_ttsig = std::make_shared<ttsig_t>(d_tdomains->getEnv(), "tsig_v5");
+
+ auto pdnsdbi = d_tdomains->getEnv()->openDB("pdns", MDB_CREATE);
+
+ opened = true;
+
+ auto txn = d_tdomains->getEnv()->getRWTransaction();
+
MDBOutVal shards;
if (!txn->get(pdnsdbi, "shards", shards)) {
s_shards = shards.get<uint32_t>();
txn->put(pdnsdbi, "uuid", uuids);
}
+ MDBOutVal _schemaversion;
+ if (txn->get(pdnsdbi, "schemaversion", _schemaversion)) {
+ // our DB is entirely new, so we need to write the schemaversion
+ txn->put(pdnsdbi, "schemaversion", currentSchemaVersion);
+ }
txn->commit();
- if (schemaversion < 3) {
- if (!upgradeToSchemav3()) {
- throw std::runtime_error("Failed to perform LMDB schema version upgrade to " + std::to_string(SCHEMAVERSION) + " from " + std::to_string(schemaversion));
- }
- }
s_first = false;
}
}
+ if (!opened) {
+ d_tdomains = std::make_shared<tdomains_t>(getMDBEnv(getArg("filename").c_str(), MDB_NOSUBDIR | d_asyncFlag, 0600, mapSize), "domains_v5");
+ d_tmeta = std::make_shared<tmeta_t>(d_tdomains->getEnv(), "metadata_v5");
+ d_tkdb = std::make_shared<tkdb_t>(d_tdomains->getEnv(), "keydata_v5");
+ d_ttsig = std::make_shared<ttsig_t>(d_tdomains->getEnv(), "tsig_v5");
+ }
d_trecords.resize(s_shards);
d_dolog = ::arg().mustDo("query-logging");
}
{
template <class Archive>
- void save(Archive& ar, const DNSName& g, const unsigned int version)
+ void save(Archive& ar, const DNSName& g, const unsigned int /* version */)
{
if (g.empty()) {
ar& std::string();
}
template <class Archive>
- void load(Archive& ar, DNSName& g, const unsigned int version)
+ void load(Archive& ar, DNSName& g, const unsigned int /* version */)
{
string tmp;
ar& tmp;
}
template <class Archive>
- void save(Archive& ar, const QType& g, const unsigned int version)
+ void save(Archive& ar, const QType& g, const unsigned int /* version */)
{
ar& g.getCode();
}
template <class Archive>
- void load(Archive& ar, QType& g, const unsigned int version)
+ void load(Archive& ar, QType& g, const unsigned int /* version */)
{
uint16_t tmp;
ar& tmp;
}
template <class Archive>
- void save(Archive& ar, const DomainInfo& g, const unsigned int version)
+ void save(Archive& ar, const DomainInfo& g, const unsigned int /* version */)
{
ar& g.zone;
ar& g.last_check;
}
template <class Archive>
- void serialize(Archive& ar, LMDBBackend::DomainMeta& g, const unsigned int version)
+ void serialize(Archive& ar, LMDBBackend::DomainMeta& g, const unsigned int /* version */)
{
ar& g.domain& g.key& g.value;
}
template <class Archive>
- void save(Archive& ar, const LMDBBackend::KeyDataDB& g, const unsigned int version)
+ void save(Archive& ar, const LMDBBackend::KeyDataDB& g, const unsigned int /* version */)
{
ar& g.domain& g.content& g.flags& g.active& g.published;
}
}
template <class Archive>
- void serialize(Archive& ar, TSIGKey& g, const unsigned int version)
+ void serialize(Archive& ar, TSIGKey& g, const unsigned int /* version */)
{
ar& g.name;
ar& g.algorithm; // this is the ordername
MDBOutVal key, val;
// cout<<"Match: "<<makeHexDump(match);
if (!cursor.lower_bound(match, key, val)) {
- while (key.get<StringView>().rfind(match, 0) == 0) {
- if (qtype == QType::ANY || co.getQType(key.get<StringView>()) == qtype)
+ while (key.getNoStripHeader<StringView>().rfind(match, 0) == 0) {
+ if (qtype == QType::ANY || co.getQType(key.getNoStripHeader<StringView>()) == qtype)
cursor.del();
if (cursor.next(key, val))
break;
if (!shard.env) {
shard.env = getMDBEnv((getArg("filename") + "-" + std::to_string(id % s_shards)).c_str(),
MDB_NOSUBDIR | d_asyncFlag, 0600);
- shard.dbi = shard.env->openDB("records", MDB_CREATE);
+ shard.dbi = shard.env->openDB("records_v5", MDB_CREATE);
}
auto ret = std::make_shared<RecordsRWTransaction>(shard.env->getRWTransaction());
ret->db = std::make_shared<RecordsDB>(shard);
}
shard.env = getMDBEnv((getArg("filename") + "-" + std::to_string(id % s_shards)).c_str(),
MDB_NOSUBDIR | d_asyncFlag, 0600);
- shard.dbi = shard.env->openDB("records", MDB_CREATE);
+ shard.dbi = shard.env->openDB("records_v5", MDB_CREATE);
}
if (rwtxn) {
}
}
+#if 0
+// FIXME reinstate soon
bool LMDBBackend::upgradeToSchemav3()
{
g_log << Logger::Warning << "Upgrading LMDB schema" << endl;
string_view currentKey;
string value;
for (;;) {
- auto newKey = key.get<string_view>();
+ auto newKey = key.getNoStripHeader<string_view>();
if (currentKey.compare(newKey) != 0) {
if (value.size() > 0) {
newTxn->put(newShard.dbi, currentKey, value);
return true;
}
+#endif
bool LMDBBackend::deleteDomain(const DNSName& domain)
{
{ // Remove metadata
auto txn = d_tmeta->getRWTransaction();
- auto range = txn.equal_range<0>(domain);
+ LMDBIDvec ids;
+
+ txn.get_multi<0>(domain, ids);
- for (auto& iter = range.first; iter != range.second; ++iter) {
- iter.del();
+ for (auto& _id : ids) {
+ txn.del(_id);
}
txn.commit();
{ // Remove cryptokeys
auto txn = d_tkdb->getRWTransaction();
- auto range = txn.equal_range<0>(domain);
+ LMDBIDvec ids;
+ txn.get_multi<0>(domain, ids);
- for (auto& iter = range.first; iter != range.second; ++iter) {
- iter.del();
+ for (auto _id : ids) {
+ txn.del(_id);
}
txn.commit();
return true;
}
-bool LMDBBackend::list(const DNSName& target, int id, bool include_disabled)
+bool LMDBBackend::list(const DNSName& target, int /* id */, bool include_disabled)
{
d_includedisabled = include_disabled;
DomainInfo di;
{
auto dtxn = d_tdomains->getROTransaction();
- if ((di.id = dtxn.get<0>(target, di)))
- ; // cout<<"Found domain "<<target<<" on domain_id "<<di.id <<", list requested "<<id<<endl;
+ if ((di.id = dtxn.get<0>(target, di))) {
+ // cerr << "Found domain " << target << " on domain_id " << di.id << ", list requested " << id << endl;
+ }
else {
- // cout<<"Did not find "<<target<<endl;
+ // cerr << "Did not find " << target << endl;
return false;
}
}
d_matchkey = co(di.id);
MDBOutVal key, val;
- if (d_getcursor->lower_bound(d_matchkey, key, val) || key.get<StringView>().rfind(d_matchkey, 0) != 0) {
- // cout<<"Found nothing for list"<<endl;
+ auto a = d_getcursor->lower_bound(d_matchkey, key, val);
+ auto b0 = key.getNoStripHeader<StringView>();
+ auto b = b0.rfind(d_matchkey, 0);
+ if (a || b != 0) {
d_getcursor.reset();
}
return true;
}
-void LMDBBackend::lookup(const QType& type, const DNSName& qdomain, int zoneId, DNSPacket* p)
+void LMDBBackend::lookup(const QType& type, const DNSName& qdomain, int zoneId, DNSPacket* /* p */)
{
if (d_dolog) {
g_log << Logger::Warning << "Got lookup for " << qdomain << "|" << type.toString() << " in zone " << zoneId << endl;
d_matchkey = co(zoneId, relqname, type.getCode());
}
- if (d_getcursor->lower_bound(d_matchkey, key, val) || key.get<StringView>().rfind(d_matchkey, 0) != 0) {
+ if (d_getcursor->lower_bound(d_matchkey, key, val) || key.getNoStripHeader<StringView>().rfind(d_matchkey, 0) != 0) {
d_getcursor.reset();
if (d_dolog) {
- g_log << Logger::Warning << "Query " << ((long)(void*)this) << ": " << d_dtime.udiffNoReset() << " usec to execute (found nothing)" << endl;
+ g_log << Logger::Warning << "Query " << ((long)(void*)this) << ": " << d_dtime.udiffNoReset() << " us to execute (found nothing)" << endl;
}
return;
}
if (d_dolog) {
- g_log << Logger::Warning << "Query " << ((long)(void*)this) << ": " << d_dtime.udiffNoReset() << " usec to execute" << endl;
+ g_log << Logger::Warning << "Query " << ((long)(void*)this) << ": " << d_dtime.udiffNoReset() << " us to execute" << endl;
}
d_lookupdomain = hunt;
bool LMDBBackend::get(DNSZoneRecord& zr)
{
for (;;) {
+ // std::cerr<<"d_getcursor="<<d_getcursor<<std::endl;
if (!d_getcursor) {
d_rotxn.reset();
return false;
if (d_currentrrset.empty()) {
d_getcursor->current(d_currentKey, d_currentVal);
- key = d_currentKey.get<string_view>();
+ key = d_currentKey.getNoStripHeader<string_view>();
zr.dr.d_type = compoundOrdername::getQType(key).getCode();
if (zr.dr.d_type == QType::NSEC3) {
// Hit a magic NSEC3 skipping
- if (d_getcursor->next(d_currentKey, d_currentVal) || d_currentKey.get<StringView>().rfind(d_matchkey, 0) != 0) {
+ if (d_getcursor->next(d_currentKey, d_currentVal) || d_currentKey.getNoStripHeader<StringView>().rfind(d_matchkey, 0) != 0) {
+ // cerr<<"resetting d_getcursor 1"<<endl;
d_getcursor.reset();
}
continue;
d_currentrrsetpos = 0;
}
else {
- key = d_currentKey.get<string_view>();
+ key = d_currentKey.getNoStripHeader<string_view>();
}
try {
const auto& lrr = d_currentrrset.at(d_currentrrsetpos++);
zr.domain_id = compoundOrdername::getDomainID(key);
zr.dr.d_type = compoundOrdername::getQType(key).getCode();
zr.dr.d_ttl = lrr.ttl;
- zr.dr.d_content = deserializeContentZR(zr.dr.d_type, zr.dr.d_name, lrr.content);
+ zr.dr.setContent(deserializeContentZR(zr.dr.d_type, zr.dr.d_name, lrr.content));
zr.auth = lrr.auth;
}
if (d_currentrrsetpos >= d_currentrrset.size()) {
d_currentrrset.clear(); // will invalidate lrr
- if (d_getcursor->next(d_currentKey, d_currentVal) || d_currentKey.get<StringView>().rfind(d_matchkey, 0) != 0) {
+ if (d_getcursor->next(d_currentKey, d_currentVal) || d_currentKey.getNoStripHeader<StringView>().rfind(d_matchkey, 0) != 0) {
+ // cerr<<"resetting d_getcursor 2"<<endl;
d_getcursor.reset();
}
}
rr.qname = zr.dr.d_name;
rr.ttl = zr.dr.d_ttl;
rr.qtype = zr.dr.d_type;
- rr.content = zr.dr.d_content->getZoneRepresentation(true);
+ rr.content = zr.dr.getContent()->getZoneRepresentation(true);
rr.domain_id = zr.domain_id;
rr.auth = zr.auth;
rr.disabled = zr.disabled;
{
{
auto txn = d_tdomains->getROTransaction();
+ // auto range = txn.prefix_range<0>(domain);
+
+ // bool found = false;
- if (!(di.id = txn.get<0>(domain, di)))
+ // for (auto& iter = range.first ; iter != range.second; ++iter) {
+ // found = true;
+ // di.id = iter.getID();
+ // di.backend = this;
+ // }
+
+ // if (!found) {
+ // return false;
+ // }
+ if (!(di.id = txn.get<0>(domain, di))) {
return false;
+ }
+
di.backend = this;
}
return true;
}
-void LMDBBackend::getAllDomains(vector<DomainInfo>* domains, bool doSerial, bool include_disabled)
+void LMDBBackend::getAllDomains(vector<DomainInfo>* domains, bool /* doSerial */, bool include_disabled)
{
domains->clear();
auto txn = d_tdomains->getROTransaction();
for (auto iter = txn.begin(); iter != txn.end(); ++iter) {
+ // cerr<<"iter"<<endl;
DomainInfo di = *iter;
di.id = iter.getID();
{
meta.clear();
auto txn = d_tmeta->getROTransaction();
- auto range = txn.equal_range<0>(name);
+ LMDBIDvec ids;
+ txn.get_multi<0>(name, ids);
- for (auto& iter = range.first; iter != range.second; ++iter) {
- meta[iter->key].push_back(iter->value);
+ DomainMeta dm;
+ // cerr<<"getAllDomainMetadata start"<<endl;
+ for (auto id : ids) {
+ if (txn.get(id, dm)) {
+ meta[dm.key].push_back(dm.value);
+ }
}
return true;
}
{
auto txn = d_tmeta->getRWTransaction();
- auto range = txn.equal_range<0>(name);
+ LMDBIDvec ids;
+ txn.get_multi<0>(name, ids);
- for (auto& iter = range.first; iter != range.second; ++iter) {
- if (iter->key == kind)
- iter.del();
+ DomainMeta dmeta;
+ for (auto id : ids) {
+ if (txn.get(id, dmeta)) {
+ if (dmeta.key == kind) {
+ // cerr<<"delete"<<endl;
+ txn.del(id);
+ }
+ }
}
for (const auto& m : meta) {
bool LMDBBackend::getDomainKeys(const DNSName& name, std::vector<KeyData>& keys)
{
auto txn = d_tkdb->getROTransaction();
- auto range = txn.equal_range<0>(name);
- for (auto& iter = range.first; iter != range.second; ++iter) {
- KeyData kd{iter->content, iter.getID(), iter->flags, iter->active, iter->published};
- keys.push_back(kd);
+ LMDBIDvec ids;
+ txn.get_multi<0>(name, ids);
+
+ KeyDataDB key;
+
+ for (auto id : ids) {
+ if (txn.get(id, key)) {
+ KeyData kd{key.content, id, key.flags, key.active, key.published};
+ keys.push_back(kd);
+ }
}
return true;
cursor.last(key, val);
for (;;) {
- if (co.getDomainID(key.get<StringView>()) != id) {
+ if (co.getDomainID(key.getNoStripHeader<StringView>()) != id) {
//cout<<"Last record also not part of this zone!"<<endl;
// this implies something is wrong in the database, nothing we can do
return false;
}
- if (co.getQType(key.get<StringView>()) == QType::NSEC3) {
+ if (co.getQType(key.getNoStripHeader<StringView>()) == QType::NSEC3) {
serFromString(val.get<StringView>(), lrr);
if (!lrr.ttl) // the kind of NSEC3 we need
break;
return false;
}
}
- before = co.getQName(key.get<StringView>());
+ before = co.getQName(key.getNoStripHeader<StringView>());
unhashed = DNSName(lrr.content.c_str(), lrr.content.size(), 0, false) + di.zone;
// now to find after .. at the beginning of the zone
return false;
}
for (;;) {
- if (co.getQType(key.get<StringView>()) == QType::NSEC3) {
+ if (co.getQType(key.getNoStripHeader<StringView>()) == QType::NSEC3) {
serFromString(val.get<StringView>(), lrr);
if (!lrr.ttl)
break;
}
- if (cursor.next(key, val) || co.getDomainID(key.get<StringView>()) != id) {
+ if (cursor.next(key, val) || co.getDomainID(key.getNoStripHeader<StringView>()) != id) {
// cout<<"hit end of zone or database when we shouldn't"<<endl;
return false;
}
}
- after = co.getQName(key.get<StringView>());
+ after = co.getQName(key.getNoStripHeader<StringView>());
// cout<<"returning: before="<<before<<", after="<<after<<", unhashed: "<<unhashed<<endl;
return true;
}
// cout<<"Ended up at "<<co.getQName(key.get<StringView>()) <<endl;
- before = co.getQName(key.get<StringView>());
+ before = co.getQName(key.getNoStripHeader<StringView>());
if (before == qname) {
// cout << "Ended up on exact right node" << endl;
- before = co.getQName(key.get<StringView>());
+ before = co.getQName(key.getNoStripHeader<StringView>());
// unhashed should be correct now, maybe check?
if (cursor.next(key, val)) {
// xxx should find first hash now
return false;
}
for (;;) {
- if (co.getQType(key.get<StringView>()) == QType::NSEC3) {
+ if (co.getQType(key.getNoStripHeader<StringView>()) == QType::NSEC3) {
serFromString(val.get<StringView>(), lrr);
if (!lrr.ttl)
break;
}
- if (cursor.next(key, val) || co.getDomainID(key.get<StringView>()) != id) {
+ if (cursor.next(key, val) || co.getDomainID(key.getNoStripHeader<StringView>()) != id) {
// cout<<"hit end of zone or database when we shouldn't" << __LINE__<<endl;
return false;
}
}
- after = co.getQName(key.get<StringView>());
+ after = co.getQName(key.getNoStripHeader<StringView>());
// cout<<"returning: before="<<before<<", after="<<after<<", unhashed: "<<unhashed<<endl;
return true;
}
// cout <<"Going backwards to find 'before'"<<endl;
int count = 0;
for (;;) {
- if (co.getQName(key.get<StringView>()).canonCompare(qname) && co.getQType(key.get<StringView>()) == QType::NSEC3) {
+ if (co.getQName(key.getNoStripHeader<StringView>()).canonCompare(qname) && co.getQType(key.getNoStripHeader<StringView>()) == QType::NSEC3) {
// cout<<"Potentially stopping traverse at "<< co.getQName(key.get<StringView>()) <<", " << (co.getQName(key.get<StringView>()).canonCompare(qname))<<endl;
// cout<<"qname = "<<qname<<endl;
// cout<<"here = "<<co.getQName(key.get<StringView>())<<endl;
break;
}
- if (cursor.prev(key, val) || co.getDomainID(key.get<StringView>()) != id) {
+ if (cursor.prev(key, val) || co.getDomainID(key.getNoStripHeader<StringView>()) != id) {
// cout <<"XXX Hit *beginning* of zone or database"<<endl;
// this can happen, must deal with it
// should now find the last hash of the zone
cursor.prev(key, val);
for (;;) {
- if (co.getDomainID(key.get<StringView>()) != id) {
+ if (co.getDomainID(key.getNoStripHeader<StringView>()) != id) {
//cout<<"Last record also not part of this zone!"<<endl;
// this implies something is wrong in the database, nothing we can do
return false;
}
- if (co.getQType(key.get<StringView>()) == QType::NSEC3) {
+ if (co.getQType(key.getNoStripHeader<StringView>()) == QType::NSEC3) {
serFromString(val.get<StringView>(), lrr);
if (!lrr.ttl) // the kind of NSEC3 we need
break;
return false;
}
}
- before = co.getQName(key.get<StringView>());
+ before = co.getQName(key.getNoStripHeader<StringView>());
unhashed = DNSName(lrr.content.c_str(), lrr.content.size(), 0, false) + di.zone;
// cout <<"Should still find 'after'!"<<endl;
// for 'after', we need to find the first hash of this zone
return false;
}
for (;;) {
- if (co.getQType(key.get<StringView>()) == QType::NSEC3) {
+ if (co.getQType(key.getNoStripHeader<StringView>()) == QType::NSEC3) {
serFromString(val.get<StringView>(), lrr);
if (!lrr.ttl)
break;
return false;
}
}
- after = co.getQName(key.get<StringView>());
+ after = co.getQName(key.getNoStripHeader<StringView>());
// cout<<"returning: before="<<before<<", after="<<after<<", unhashed: "<<unhashed<<endl;
return true;
}
++count;
}
- before = co.getQName(key.get<StringView>());
+ before = co.getQName(key.getNoStripHeader<StringView>());
unhashed = DNSName(lrr.content.c_str(), lrr.content.size(), 0, false) + di.zone;
// cout<<"Went backwards, found "<<before<<endl;
// return us to starting point
}
// cout<<"Now going forward"<<endl;
for (int count = 0;; ++count) {
- if ((count && cursor.next(key, val)) || co.getDomainID(key.get<StringView>()) != id) {
+ if ((count && cursor.next(key, val)) || co.getDomainID(key.getNoStripHeader<StringView>()) != id) {
// cout <<"Hit end of database or zone, finding first hash then in zone "<<id<<endl;
if (cursor.lower_bound(co(id), key, val)) {
// cout<<"hit end of zone find when we shouldn't"<<endl;
return false;
}
for (;;) {
- if (co.getQType(key.get<StringView>()) == QType::NSEC3) {
+ if (co.getQType(key.getNoStripHeader<StringView>()) == QType::NSEC3) {
serFromString(val.get<StringView>(), lrr);
if (!lrr.ttl)
break;
}
// cout << "Next.. "<<endl;
}
- after = co.getQName(key.get<StringView>());
+ after = co.getQName(key.getNoStripHeader<StringView>());
// cout<<"returning: before="<<before<<", after="<<after<<", unhashed: "<<unhashed<<endl;
return true;
}
// cout<<"After "<<co.getQName(key.get<StringView>()) <<endl;
- if (co.getQType(key.get<StringView>()) == QType::NSEC3) {
+ if (co.getQType(key.getNoStripHeader<StringView>()) == QType::NSEC3) {
serFromString(val.get<StringView>(), lrr);
if (!lrr.ttl) {
break;
}
}
}
- after = co.getQName(key.get<StringView>());
+ after = co.getQName(key.getNoStripHeader<StringView>());
// cout<<"returning: before="<<before<<", after="<<after<<", unhashed: "<<unhashed<<endl;
return true;
}
if (cursor.lower_bound(matchkey, key, val)) {
// cout << "Hit end of database, bummer"<<endl;
cursor.last(key, val);
- if (co.getDomainID(key.get<string_view>()) == id) {
- before = co.getQName(key.get<string_view>()) + zonename;
+ if (co.getDomainID(key.getNoStripHeader<string_view>()) == id) {
+ before = co.getQName(key.getNoStripHeader<string_view>()) + zonename;
after = zonename;
}
// else
}
// cout<<"Cursor is at "<<co.getQName(key.get<string_view>()) <<", in zone id "<<co.getDomainID(key.get<string_view>())<< endl;
- if (co.getQType(key.get<string_view>()).getCode() && co.getDomainID(key.get<string_view>()) == id && co.getQName(key.get<string_view>()) == qname2) { // don't match ENTs
+ if (co.getQType(key.getNoStripHeader<string_view>()).getCode() && co.getDomainID(key.getNoStripHeader<string_view>()) == id && co.getQName(key.getNoStripHeader<string_view>()) == qname2) { // don't match ENTs
// cout << "Had an exact match!"<<endl;
before = qname2 + zonename;
int rc;
if (rc)
break;
- if (co.getDomainID(key.get<string_view>()) == id && key.get<StringView>().rfind(matchkey, 0) == 0)
+ if (co.getDomainID(key.getNoStripHeader<string_view>()) == id && key.getNoStripHeader<StringView>().rfind(matchkey, 0) == 0)
continue;
LMDBResourceRecord lrr;
serFromString(val.get<StringView>(), lrr);
- if (co.getQType(key.get<string_view>()).getCode() && (lrr.auth || co.getQType(key.get<string_view>()).getCode() == QType::NS))
+ if (co.getQType(key.getNoStripHeader<string_view>()).getCode() && (lrr.auth || co.getQType(key.getNoStripHeader<string_view>()).getCode() == QType::NS))
break;
}
- if (rc || co.getDomainID(key.get<string_view>()) != id) {
+ if (rc || co.getDomainID(key.getNoStripHeader<string_view>()) != id) {
// cout << "We hit the end of the zone or database. 'after' is apex" << endl;
after = zonename;
return false;
}
- after = co.getQName(key.get<string_view>()) + zonename;
+ after = co.getQName(key.getNoStripHeader<string_view>()) + zonename;
return true;
}
- if (co.getDomainID(key.get<string_view>()) != id) {
+ if (co.getDomainID(key.getNoStripHeader<string_view>()) != id) {
// cout << "Ended up in next zone, 'after' is zonename" <<endl;
after = zonename;
// cout << "Now hunting for previous" << endl;
return false;
}
- if (co.getDomainID(key.get<string_view>()) != id) {
- // cout<<"Reversed into zone, but found wrong zone id " << co.getDomainID(key.get<string_view>()) << " != "<<id<<endl;
+ if (co.getDomainID(key.getNoStripHeader<string_view>()) != id) {
+ // cout<<"Reversed into zone, but found wrong zone id " << co.getDomainID(key.getNoStripHeader<string_view>()) << " != "<<id<<endl;
// "this can't happen"
return false;
}
LMDBResourceRecord lrr;
serFromString(val.get<StringView>(), lrr);
- if (co.getQType(key.get<string_view>()).getCode() && (lrr.auth || co.getQType(key.get<string_view>()).getCode() == QType::NS))
+ if (co.getQType(key.getNoStripHeader<string_view>()).getCode() && (lrr.auth || co.getQType(key.getNoStripHeader<string_view>()).getCode() == QType::NS))
break;
}
- before = co.getQName(key.get<string_view>()) + zonename;
+ before = co.getQName(key.getNoStripHeader<string_view>()) + zonename;
// cout<<"Found: "<< before<<endl;
return true;
}
- // cout <<"We ended up after "<<qname<<", on "<<co.getQName(key.get<string_view>())<<endl;
+ // cout <<"We ended up after "<<qname<<", on "<<co.getQName(key.getNoStripHeader<string_view>())<<endl;
int skips = 0;
for (;;) {
LMDBResourceRecord lrr;
serFromString(val.get<StringView>(), lrr);
- if (co.getQType(key.get<string_view>()).getCode() && (lrr.auth || co.getQType(key.get<string_view>()).getCode() == QType::NS)) {
- after = co.getQName(key.get<string_view>()) + zonename;
- // cout <<"Found auth ("<<lrr.auth<<") or an NS record "<<after<<", type: "<<co.getQType(key.get<string_view>()).toString()<<", ttl = "<<lrr.ttl<<endl;
+ if (co.getQType(key.getNoStripHeader<string_view>()).getCode() && (lrr.auth || co.getQType(key.getNoStripHeader<string_view>()).getCode() == QType::NS)) {
+ after = co.getQName(key.getNoStripHeader<string_view>()) + zonename;
+ // cout <<"Found auth ("<<lrr.auth<<") or an NS record "<<after<<", type: "<<co.getQType(key.getNoStripHeader<string_view>()).toString()<<", ttl = "<<lrr.ttl<<endl;
// cout << makeHexDump(val.get<string>()) << endl;
break;
}
- // cout <<" oops, " << co.getQName(key.get<string_view>()) << " was not auth "<<lrr.auth<< " type=" << lrr.qtype.toString()<<" or NS, so need to skip ahead a bit more" << endl;
+ // cout <<" oops, " << co.getQName(key.getNoStripHeader<string_view>()) << " was not auth "<<lrr.auth<< " type=" << lrr.qtype.toString()<<" or NS, so need to skip ahead a bit more" << endl;
int rc = cursor.next(key, val);
if (!rc)
++skips;
- if (rc || co.getDomainID(key.get<string_view>()) != id) {
+ if (rc || co.getDomainID(key.getNoStripHeader<string_view>()) != id) {
// cout << " oops, hit end of database or zone. This means after is apex" <<endl;
after = zonename;
break;
for (;;) {
int rc = cursor.prev(key, val);
- if (rc || co.getDomainID(key.get<string_view>()) != id) {
+ if (rc || co.getDomainID(key.getNoStripHeader<string_view>()) != id) {
// XX I don't think this case can happen
// cout << "We hit the beginning of the zone or database.. now what" << endl;
return false;
}
- before = co.getQName(key.get<string_view>()) + zonename;
+ before = co.getQName(key.getNoStripHeader<string_view>()) + zonename;
LMDBResourceRecord lrr;
serFromString(val.get<string_view>(), lrr);
// cout<<"And before to "<<before<<", auth = "<<rr.auth<<endl;
- if (co.getQType(key.get<string_view>()).getCode() && (lrr.auth || co.getQType(key.get<string_view>()) == QType::NS))
+ if (co.getQType(key.getNoStripHeader<string_view>()).getCode() && (lrr.auth || co.getQType(key.getNoStripHeader<string_view>()) == QType::NS))
break;
// cout << "Oops, that was wrong, go back one more"<<endl;
}
bool hasOrderName = !ordername.empty();
bool needNSEC3 = hasOrderName;
- for (; key.get<StringView>().rfind(matchkey, 0) == 0;) {
+ for (; key.getNoStripHeader<StringView>().rfind(matchkey, 0) == 0;) {
vector<LMDBResourceRecord> lrrs;
- if (co.getQType(key.get<StringView>()) != QType::NSEC3) {
+ if (co.getQType(key.getNoStripHeader<StringView>()) != QType::NSEC3) {
serFromString(val.get<StringView>(), lrrs);
bool changed = false;
vector<LMDBResourceRecord> newRRs;
for (auto lrr : lrrs) {
- lrr.qtype = co.getQType(key.get<StringView>());
+ lrr.qtype = co.getQType(key.getNoStripHeader<StringView>());
if (!needNSEC3 && qtype != QType::ANY) {
needNSEC3 = (lrr.ordername && QType(qtype) != lrr.qtype);
}
bool del = false;
LMDBResourceRecord lrr;
matchkey = co(domain_id, rel, QType::NSEC3);
- if (!txn->txn->get(txn->db->dbi, matchkey, val)) {
+ // cerr<<"here qname="<<qname<<" ordername="<<ordername<<" qtype="<<qtype<<" matchkey="<<makeHexDump(matchkey)<<endl;
+ int txngetrc;
+ if (!(txngetrc = txn->txn->get(txn->db->dbi, matchkey, val))) {
serFromString(val.get<string_view>(), lrr);
if (needNSEC3) {
bool LMDBBackend::getTSIGKey(const DNSName& name, DNSName& algorithm, string& content)
{
auto txn = d_ttsig->getROTransaction();
- auto range = txn.equal_range<0>(name);
-
- for (auto& iter = range.first; iter != range.second; ++iter) {
- if (algorithm.empty() || algorithm == DNSName(iter->algorithm)) {
- algorithm = DNSName(iter->algorithm);
- content = iter->key;
+ LMDBIDvec ids;
+ txn.get_multi<0>(name, ids);
+
+ TSIGKey key;
+ for (auto id : ids) {
+ if (txn.get(id, key)) {
+ if (algorithm.empty() || algorithm == DNSName(key.algorithm)) {
+ algorithm = DNSName(key.algorithm);
+ content = key.key;
+ }
}
}
{
auto txn = d_ttsig->getRWTransaction();
- for (auto range = txn.equal_range<0>(name); range.first != range.second; ++range.first) {
- if (range.first->algorithm == algorithm) {
- txn.del(range.first.getID());
+ LMDBIDvec ids;
+ txn.get_multi<0>(name, ids);
+
+ TSIGKey key;
+ for (auto id : ids) {
+ if (txn.get(id, key)) {
+ if (key.algorithm == algorithm) {
+ txn.del(id);
+ }
}
}
bool LMDBBackend::deleteTSIGKey(const DNSName& name)
{
auto txn = d_ttsig->getRWTransaction();
- TSIGKey tk;
- for (auto range = txn.equal_range<0>(name); range.first != range.second; ++range.first) {
- txn.del(range.first.getID());
+ LMDBIDvec ids;
+ txn.get_multi<0>(name, ids);
+
+ TSIGKey key;
+
+ for (auto id : ids) {
+ if (txn.get(id, key)) {
+ txn.del(id);
+ }
}
txn.commit();
return true;
return true;
}
+string LMDBBackend::directBackendCmd(const string& query)
+{
+ if (query == "info") {
+ ostringstream ret;
+
+ ret << "shards: " << s_shards << endl;
+ ret << "schemaversion: " << SCHEMAVERSION << endl;
+
+ return ret.str();
+ }
+ else {
+ return "unknown lmdbbackend command\n";
+ }
+}
+
class LMDBFactory : public BackendFactory
{
public:
declare(suffix, "schema-version", "Maximum allowed schema version to run on this DB. If a lower version is found, auto update is performed", std::to_string(SCHEMAVERSION));
declare(suffix, "random-ids", "Numeric IDs inside the database are generated randomly instead of sequentially", "no");
declare(suffix, "map-size", "LMDB map size in megabytes", (sizeof(void*) == 4) ? "100" : "16000");
+ declare(suffix, "flag-deleted", "Flag entries on deletion instead of deleting them", "no");
}
DNSBackend* make(const string& suffix = "") override
{
return true;
}
+ // other
+ string directBackendCmd(const string& query) override;
+
+ // functions to use without constructing a backend object
+ static std::pair<uint32_t, uint32_t> getSchemaVersionAndShards(std::string& filename);
+ static bool upgradeToSchemav5(std::string& filename);
+
private:
struct compoundOrdername
{
+ns2.secure-delegated.dnssec-parent.com:5.6.7.8:3600
+something1.auth-ent.dnssec-parent.com:1.1.2.3:3600
:secure-delegated.dnssec-parent.com:43:\324\057\010\002\240\271\303\214\323\044\030\052\360\357f\203\015\012\016\205\241\325\211y\311\203N\030\310qw\236\004\010W\267:3600
+C\052.dnssec-parent.com:secure-delegated.dnssec-parent.com.:3600
Cwww.dnssec-parent.com:www.insecure.dnssec-parent.com.:3600
Zdnssec-parent.com:ns1.dnssec-parent.com.:ahu.example.com.:2005092501:28800:7200:604800:86400:3600
#2000081501 auto axfr-get
ednscookies.cc ednscookies.hh \
ednsoptions.cc ednsoptions.hh \
ednssubnet.cc ednssubnet.hh \
+ gettime.cc gettime.hh \
gss_context.cc gss_context.hh \
histogram.hh \
iputils.cc iputils.hh \
ednscookies.cc ednscookies.hh \
ednsoptions.cc ednsoptions.hh \
ednssubnet.cc \
+ gettime.cc gettime.hh \
gss_context.cc gss_context.hh \
ipcipher.cc ipcipher.hh \
iputils.cc iputils.hh \
dzr.dr.d_name = DNSName("version") + zone;
dzr.dr.d_ttl = 0;
dzr.dr.d_type = QType::TXT;
- dzr.dr.d_content = std::make_shared<TXTRecordContent>("2");
+ dzr.dr.setContent(std::make_shared<TXTRecordContent>("2"));
return dzr;
}
dzr.dr.d_name = prefix;
dzr.dr.d_ttl = 0;
dzr.dr.d_type = QType::PTR;
- dzr.dr.d_content = std::make_shared<PTRRecordContent>(d_zone.toString());
+ dzr.dr.setContent(std::make_shared<PTRRecordContent>(d_zone.toString()));
dzrs.emplace_back(dzr);
if (!d_coo.empty()) {
dzr.dr.d_name = DNSName("coo") + prefix;
dzr.dr.d_ttl = 0;
dzr.dr.d_type = QType::PTR;
- dzr.dr.d_content = std::make_shared<PTRRecordContent>(d_coo);
+ dzr.dr.setContent(std::make_shared<PTRRecordContent>(d_coo));
dzrs.emplace_back(dzr);
}
dzr.dr.d_name = DNSName("group") + prefix;
dzr.dr.d_ttl = 0;
dzr.dr.d_type = QType::TXT;
- dzr.dr.d_content = std::make_shared<TXTRecordContent>("\"" + group + "\"");
+ dzr.dr.setContent(std::make_shared<TXTRecordContent>("\"" + group + "\""));
dzrs.emplace_back(dzr);
}
}
::arg().set("only-notify", "Only send AXFR NOTIFY to these IP addresses or netmasks") = "0.0.0.0/0,::/0";
::arg().set("also-notify", "When notifying a zone, also notify these nameservers") = "";
::arg().set("allow-notify-from", "Allow AXFR NOTIFY from these IP ranges. If empty, drop all incoming notifies.") = "0.0.0.0/0,::/0";
- ::arg().set("slave-cycle-interval", "Schedule slave freshness checks once every .. seconds") = "60";
+ ::arg().set("slave-cycle-interval", "Schedule slave freshness checks once every .. seconds") = "";
::arg().set("xfr-cycle-interval", "Schedule primary/secondary SOA freshness checks once every .. seconds") = "60";
::arg().set("secondary-check-signature-freshness", "Check signatures in SOA freshness check. Sets DO flag on SOA queries. Outside some very problematic scenarios, say yes here.") = "yes";
::arg().set("allow-unsigned-autoprimary") = "yes";
if (!::arg().isEmpty("domain-metadata-cache-ttl"))
::arg().set("zone-metadata-cache-ttl") = ::arg()["domain-metadata-cache-ttl"];
+ if (!::arg().isEmpty("slave-cycle-interval"))
+ ::arg().set("xfr-cycle-interval") = ::arg()["slave-cycle-interval"];
// this mirroring back is on purpose, so that config dumps reflect the actual setting on both names
if (::arg().mustDo("primary"))
if (::arg().mustDo("allow-unsigned-autoprimary"))
::arg().set("allow-unsigned-supermaster") = "yes";
::arg().set("domain-metadata-cache-ttl") = ::arg()["zone-metadata-cache-ttl"];
+ ::arg().set("slave-cycle-interval") = ::arg()["xfr-cycle-interval"];
g_log.setLoglevel((Logger::Urgency)(::arg().asNum("loglevel")));
g_log.disableSyslog(::arg().mustDo("disable-syslog"));
#include "capabilities.hh"
#include "misc.hh"
-bool dropCapabilities(std::set<std::string> capabilitiesToKeep)
+bool dropCapabilities([[maybe_unused]] std::set<std::string> capabilitiesToKeep)
{
#ifdef HAVE_LIBCAP
cap_t caps = cap_get_proc();
try {
setThreadName("pdns/comm-main");
signal(SIGPIPE,SIG_IGN);
- g_log<<Logger::Error<<"Primary/secondary communicator launching"<<endl;
- PacketHandler P;
- d_tickinterval=min(::arg().asNum("slave-cycle-interval"), ::arg().asNum("xfr-cycle-interval"));
- makeNotifySockets();
+ g_log << Logger::Warning << "Primary/secondary communicator launching" << endl;
+
+ d_tickinterval = ::arg().asNum("xfr-cycle-interval");
int rc;
- time_t next, tick;
+ time_t next;
+ PacketHandler P;
+
+ makeNotifySockets();
for(;;) {
slaveRefresh(&P);
masterUpdateCheck(&P);
- tick=doNotifications(&P); // this processes any notification acknowledgements and actually send out our own notifications
-
- tick = min (tick, d_tickinterval);
-
- next=time(nullptr)+tick;
+ doNotifications(&P); // this processes any notification acknowledgements and actually send out our own notifications
+
+ next = time(nullptr) + d_tickinterval;
while(time(nullptr) < next) {
rc=d_any_sem.tryWait();
}
break; // something happened
}
- // this gets executed at least once every second
+ // this gets executed about once per second
doNotifications(&P);
}
}
_exit(1);
}
}
-
DNSZoneRecord rr;
while(b->get(rr))
if(rr.dr.d_type == QType::A || rr.dr.d_type==QType::AAAA)
- addresses.push_back(rr.dr.d_content->getZoneRepresentation()); // SOL if you have a CNAME for an NS
+ addresses.push_back(rr.dr.getContent()->getZoneRepresentation()); // SOL if you have a CNAME for an NS
}
return addresses;
}
const auto rr = *rrs.rbegin();
DNSZoneRecord dzr;
- std::shared_ptr<RRSIGRecordContent> rrsig;
db.lookup(QType(QType::RRSIG), !rr.wildcardname.empty() ? rr.wildcardname : rr.dr.d_name, rr.domain_id);
while(db.get(dzr)) {
- rrsig = getRR<RRSIGRecordContent>(dzr.dr);
- if(rrsig->d_type == rr.dr.d_type) {
+ auto rrsig = getRR<RRSIGRecordContent>(dzr.dr);
+ if (rrsig->d_type == rr.dr.d_type) {
if(!rr.wildcardname.empty()) {
dzr.dr.d_name = rr.dr.d_name;
}
};
std::string RCode::to_s(uint8_t rcode) {
- if (rcode > 0xF)
+ if (rcode > 0xF) {
return std::string("ErrOutOfRange");
+ }
return ERCode::to_s(rcode);
}
return rcodes_short_s.at(rcode);
}
-std::string ERCode::to_s(uint8_t rcode) {
- if (rcode > RCode::rcodes_s.size()-1)
+std::string ERCode::to_s(uint16_t rcode) {
+ if (rcode >= RCode::rcodes_s.size()) {
return std::string("Err#")+std::to_string(rcode);
+ }
return RCode::rcodes_s.at(rcode);
}
class RCode
{
public:
- enum rcodes_ { NoError=0, FormErr=1, ServFail=2, NXDomain=3, NotImp=4, Refused=5, YXDomain=6, YXRRSet=7, NXRRSet=8, NotAuth=9, NotZone=10};
+ enum rcodes_ : uint8_t { NoError=0, FormErr=1, ServFail=2, NXDomain=3, NotImp=4, Refused=5, YXDomain=6, YXRRSet=7, NXRRSet=8, NotAuth=9, NotZone=10};
static std::string to_s(uint8_t rcode);
static std::string to_short_s(uint8_t rcode);
const static std::array<std::string, 24> rcodes_s;
class ERCode
{
public:
- enum rcodes_ { BADVERS=16, BADSIG=16, BADKEY=17, BADTIME=18, BADMODE=19, BADNAME=20, BADALG=21, BADTRUNC=22, BADCOOKIE=23 };
- static std::string to_s(uint8_t rcode);
+ enum rcodes_ : uint16_t { BADVERS=16, BADSIG=16, BADKEY=17, BADTIME=18, BADMODE=19, BADNAME=20, BADALG=21, BADTRUNC=22, BADCOOKIE=23 };
+ static std::string to_s(uint16_t rcode);
};
class Opcode
dr.rcode = mdp.d_header.rcode;
for(MOADNSParser::answers_t::const_iterator i=mdp.d_answers.begin(); i!=mdp.d_answers.end(); ++i) {
if(i->first.d_place == 1 && i->first.d_type == mdp.d_qtype)
- dr.ips.push_back(ComboAddress(i->first.d_content->getZoneRepresentation()));
+ dr.ips.push_back(ComboAddress(i->first.getContent()->getZoneRepresentation()));
if(i->first.d_place == 2 && i->first.d_type == QType::SOA) {
dr.seenauthsoa = true;
}
if(!g_quiet)
{
cout<<i->first.d_place-1<<"\t"<<i->first.d_name<<"\tIN\t"<<DNSRecordContent::NumberToType(i->first.d_type);
- cout<<"\t"<<i->first.d_ttl<<"\t"<< i->first.d_content->getZoneRepresentation()<<"\n";
+ cout<<"\t"<<i->first.d_ttl<<"\t"<< i->first.getContent()->getZoneRepresentation()<<"\n";
}
}
{
(*d_acc)(usec/1000.0);
// if(usec > 1000000)
- // cerr<<"Slow: "<<domain<<" ("<<usec/1000.0<<" msec)\n";
+ // cerr<<"Slow: "<<domain<<" ("<<usec/1000.0<<" ms)\n";
if(!g_quiet) {
- cout<<domain.name<<"|"<<DNSRecordContent::NumberToType(domain.type)<<": ("<<usec/1000.0<<"msec) rcode: "<<dr.rcode;
+ cout<<domain.name<<"|"<<DNSRecordContent::NumberToType(domain.type)<<": ("<<usec/1000.0<<" ms) rcode: "<<dr.rcode;
for(const ComboAddress& ca : dr.ips) {
cout<<", "<<ca.toString();
}
cerr<< datafmt % "Total " % (sr.d_oks + sr.d_errors + sr.d_nodatas + sr.d_nxdomains + sr.d_unknowns + inflighter.getTimeouts()) % "" % "";
cerr<<"\n";
- cerr<< "Mean response time: "<<mean(*sr.d_acc) << " msec"<<", median: "<<median(*sr.d_acc)<< " msec\n";
+ cerr<< "Mean response time: "<<mean(*sr.d_acc) << " ms"<<", median: "<<median(*sr.d_acc)<< " ms\n";
- boost::format statfmt("Time < %6.03f msec %|30t|%6.03f%% cumulative\n");
+ boost::format statfmt("Time < %6.03f ms %|30t|%6.03f%% cumulative\n");
for (unsigned int i = 0; i < sr.d_probs.size(); ++i) {
cerr << statfmt % extended_p_square(*sr.d_acc)[i] % (100*sr.d_probs[i]);
if (!d_dontAge && !skipAging) {
if (!stale) {
// coverity[store_truncates_time_t]
- ageDNSPacket(reinterpret_cast<char *>(&response[0]), response.size(), age);
+ dnsheader_aligned dh_aligned(response.data());
+ ageDNSPacket(reinterpret_cast<char *>(&response[0]), response.size(), age, dh_aligned);
}
else {
editDNSPacketTTL(reinterpret_cast<char*>(&response[0]), response.size(),
str << base << "responses" << ' ' << state->responses.load() << " " << now << "\r\n";
str << base << "drops" << ' ' << state->reuseds.load() << " " << now << "\r\n";
str << base << "latency" << ' ' << (state->d_config.availability != DownstreamState::Availability::Down ? state->latencyUsec / 1000.0 : 0) << " " << now << "\r\n";
+ str << base << "latencytcp" << ' ' << (state->d_config.availability != DownstreamState::Availability::Down ? state->latencyUsecTCP / 1000.0 : 0) << " " << now << "\r\n";
str << base << "senderrors" << ' ' << state->sendErrors.load() << " " << now << "\r\n";
str << base << "outstanding" << ' ' << state->outstanding.load() << " " << now << "\r\n";
str << base << "tcpdiedsendingquery" << ' ' << state->tcpDiedSendingQuery.load() << " " << now << "\r\n";
usleep(toSleepUSec);
}
else {
- vinfolog("Carbon export for %s took longer (%s usec) than the configured interval (%d usec)", endpoint.server.toStringWithPort(), elapsedUSec, intervalUSec);
+ vinfolog("Carbon export for %s took longer (%s us) than the configured interval (%d us)", endpoint.server.toStringWithPort(), elapsedUSec, intervalUSec);
}
consecutiveFailures = 0;
}
{ "getTLSFrontend", true, "n", "returns the TLS frontend with index n" },
{ "getTLSFrontendCount", true, "", "returns the number of DoT listeners" },
{ "getVerbose", true, "", "get whether log messages at the verbose level will be logged" },
- { "grepq", true, "Netmask|DNS Name|100ms|{\"::1\", \"powerdns.com\", \"100ms\"} [, n]", "shows the last n queries and responses matching the specified client address or range (Netmask), or the specified DNS Name, or slower than 100ms" },
+ { "grepq", true, "Netmask|DNS Name|100ms|{\"::1\", \"powerdns.com\", \"100ms\"} [, n] [,options]", "shows the last n queries and responses matching the specified client address or range (Netmask), or the specified DNS Name, or slower than 100ms" },
{ "hashPassword", true, "password [, workFactor]", "Returns a hashed and salted version of the supplied password, usable with 'setWebserverConfig()'"},
{ "HTTPHeaderRule", true, "name, regex", "matches DoH queries with a HTTP header 'name' whose content matches the regular expression 'regex'"},
{ "HTTPPathRegexRule", true, "regex", "matches DoH queries whose HTTP path matches 'regex'"},
}
std::string toString() const override
{
- return "delay by "+std::to_string(d_msec)+ " msec";
+ return "delay by "+std::to_string(d_msec)+ " ms";
}
private:
int d_msec;
}
std::string toString() const override
{
- return "delay by "+std::to_string(d_msec)+ " msec";
+ return "delay by "+std::to_string(d_msec)+ " ms";
}
private:
int d_msec;
});
luaCtx.registerFunction<uint64_t(DownstreamState::*)()const>("getOutstanding", [](const DownstreamState& s) { return s.outstanding.load(); });
luaCtx.registerFunction<uint64_t(DownstreamState::*)()const>("getDrops", [](const DownstreamState& s) { return s.reuseds.load(); });
- luaCtx.registerFunction<double(DownstreamState::*)()const>("getLatency", [](const DownstreamState& s) { return s.latencyUsec; });
+ luaCtx.registerFunction<double(DownstreamState::*)()const>("getLatency", [](const DownstreamState& s) { return s.getRelevantLatencyUsec(); });
luaCtx.registerFunction("isUp", &DownstreamState::isUp);
luaCtx.registerFunction("setDown", &DownstreamState::setDown);
luaCtx.registerFunction("setUp", &DownstreamState::setUp);
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
+#include <fcntl.h>
+
#include "dnsdist.hh"
#include "dnsdist-lua.hh"
#include "dnsdist-dynblocks.hh"
return ret;
}
-typedef std::function<void(const StatNode&, const StatNode::Stat&, const StatNode::Stat&)> statvisitor_t;
+using statvisitor_t = std::function<void(const StatNode&, const StatNode::Stat&, const StatNode::Stat&)>;
static void statNodeRespRing(statvisitor_t visitor, uint64_t seconds)
{
auto rl = shard->respRing.lock();
for(const auto& c : *rl) {
- if (now < c.when)
+ if (now < c.when){
continue;
+ }
- if (seconds && c.when < cutoff)
+ if (seconds && c.when < cutoff) {
continue;
+ }
- root.submit(c.name, ((c.dh.rcode == 0 && c.usec == std::numeric_limits<unsigned int>::max()) ? -1 : c.dh.rcode), c.size, boost::none);
+ bool hit = c.ds.sin4.sin_family == 0;
+ if (!hit && c.ds.isIPv4() && c.ds.sin4.sin_addr.s_addr == 0 && c.ds.sin4.sin_port == 0) {
+ hit = true;
+ }
+
+ root.submit(c.name, ((c.dh.rcode == 0 && c.usec == std::numeric_limits<unsigned int>::max()) ? -1 : c.dh.rcode), c.size, hit, boost::none);
}
}
}
});
- luaCtx.writeFunction("grepq", [](LuaTypeOrArrayOf<std::string> inp, boost::optional<unsigned int> limit) {
+ luaCtx.writeFunction("grepq", [](LuaTypeOrArrayOf<std::string> inp, boost::optional<unsigned int> limit, boost::optional<LuaAssociativeTable<std::string>> options) {
setLuaNoSideEffect();
boost::optional<Netmask> nm;
boost::optional<DNSName> dn;
- int msec=-1;
+ int msec = -1;
+ std::unique_ptr<FILE, decltype(&fclose)> outputFile{nullptr, fclose};
+
+ if (options) {
+ std::string outputFileName;
+ if (getOptionalValue<std::string>(options, "outputFile", outputFileName) > 0) {
+ int fd = open(outputFileName.c_str(), O_CREAT | O_EXCL | O_WRONLY, 0600);
+ if (fd < 0) {
+ g_outputBuffer = "Error opening dump file for writing: " + stringerror() + "\n";
+ return;
+ }
+ outputFile = std::unique_ptr<FILE, decltype(&fclose)>(fdopen(fd, "w"), fclose);
+ if (outputFile == nullptr) {
+ g_outputBuffer = "Error opening dump file for writing: " + stringerror() + "\n";
+ close(fd);
+ return;
+ }
+ }
+ checkAllParametersConsumed("grepq", options);
+ }
vector<string> vec;
- auto str=boost::get<string>(&inp);
- if(str)
+ auto str = boost::get<string>(&inp);
+ if (str) {
vec.push_back(*str);
+ }
else {
auto v = boost::get<LuaArray<std::string>>(inp);
- for(const auto& a: v)
+ for (const auto& a: v) {
vec.push_back(a.second);
+ }
}
- for(const auto& s : vec) {
- try
- {
+ for (const auto& s : vec) {
+ try {
nm = Netmask(s);
- }
- catch(...) {
- if(boost::ends_with(s,"ms") && sscanf(s.c_str(), "%ums", &msec)) {
+ }
+ catch (...) {
+ if (boost::ends_with(s,"ms") && sscanf(s.c_str(), "%ums", &msec)) {
;
}
else {
- try { dn=DNSName(s); }
- catch(...)
- {
- g_outputBuffer = "Could not parse '"+s+"' as domain name or netmask";
- return;
- }
+ try {
+ dn = DNSName(s);
+ }
+ catch (...) {
+ g_outputBuffer = "Could not parse '"+s+"' as domain name or netmask";
+ return;
+ }
}
}
}
std::multimap<struct timespec, string> out;
- boost::format fmt("%-7.1f %-47s %-12s %-12s %-5d %-25s %-5s %-6.1f %-2s %-2s %-2s %-s\n");
- g_outputBuffer+= (fmt % "Time" % "Client" % "Protocol" % "Server" % "ID" % "Name" % "Type" % "Lat." % "TC" % "RD" % "AA" % "Rcode").str();
+ boost::format fmt("%-7.1f %-47s %-12s %-12s %-5d %-25s %-5s %-6.1f %-2s %-2s %-2s %-s\n");
+ const auto headLine = (fmt % "Time" % "Client" % "Protocol" % "Server" % "ID" % "Name" % "Type" % "Lat." % "TC" % "RD" % "AA" % "Rcode").str();
+ if (!outputFile) {
+ g_outputBuffer += headLine;
+ }
+ else {
+ fprintf(outputFile.get(), "%s", headLine.c_str());
+ }
- if(msec==-1) {
- for(const auto& c : qr) {
- bool nmmatch=true, dnmatch=true;
+ if (msec == -1) {
+ for (const auto& c : qr) {
+ bool nmmatch = true;
+ bool dnmatch = true;
if (nm) {
nmmatch = nm->match(c.requestor);
}
}
out.emplace(c.when, (fmt % DiffTime(now, c.when) % c.requestor.toStringWithPort() % dnsdist::Protocol(c.protocol).toString() % "" % htons(c.dh.id) % c.name.toString() % qt.toString() % "" % (c.dh.tc ? "TC" : "") % (c.dh.rd ? "RD" : "") % (c.dh.aa ? "AA" : "") % ("Question" + extra)).str());
- if(limit && *limit==++num)
+ if (limit && *limit == ++num) {
break;
+ }
}
}
}
- num=0;
-
+ num = 0;
string extra;
- for(const auto& c : rr) {
- bool nmmatch=true, dnmatch=true, msecmatch=true;
+ for (const auto& c : rr) {
+ bool nmmatch = true;
+ bool dnmatch = true;
+ bool msecmatch = true;
if (nm) {
nmmatch = nm->match(c.requestor);
}
}
}
if (msec != -1) {
- msecmatch=(c.usec/1000 > (unsigned int)msec);
+ msecmatch = (c.usec/1000 > (unsigned int)msec);
}
if (nmmatch && dnmatch && msecmatch) {
QType qt(c.qtype);
if (!c.dh.rcode) {
- extra=". " +std::to_string(htons(c.dh.ancount))+ " answers";
+ extra = ". " +std::to_string(htons(c.dh.ancount)) + " answers";
}
else {
extra.clear();
}
}
- for(const auto& p : out) {
- g_outputBuffer+=p.second;
+ for (const auto& p : out) {
+ if (!outputFile) {
+ g_outputBuffer += p.second;
+ }
+ else {
+ fprintf(outputFile.get(), "%s", p.second.c_str());
+ }
}
});
return;
}
- g_outputBuffer = (boost::format("Average response latency: %.02f msec\n") % (0.001*totlat/size)).str();
+ g_outputBuffer = (boost::format("Average response latency: %.02f ms\n") % (0.001*totlat/size)).str();
double highest=0;
for(auto iter = histo.cbegin(); iter != histo.cend(); ++iter) {
highest=std::max(highest, iter->second*1.0);
}
boost::format fmt("%7.2f\t%s\n");
- g_outputBuffer += (fmt % "msec" % "").str();
+ g_outputBuffer += (fmt % "ms" % "").str();
for(auto iter = histo.cbegin(); iter != histo.cend(); ++iter) {
int stars = (70.0 * iter->second/highest);
luaCtx.registerMember("noerrors", &StatNode::Stat::noerrors);
luaCtx.registerMember("drops", &StatNode::Stat::drops);
luaCtx.registerMember("bytes", &StatNode::Stat::bytes);
+ luaCtx.registerMember("hits", &StatNode::Stat::hits);
luaCtx.writeFunction("statNodeRespRing", [](statvisitor_t visitor, boost::optional<uint64_t> seconds) {
statNodeRespRing(visitor, seconds ? *seconds : 0U);
return getUniqueID(id);
}
-void parseRuleParams(boost::optional<luaruleparams_t> params, boost::uuids::uuid& uuid, std::string& name, uint64_t& creationOrder)
+void parseRuleParams(boost::optional<luaruleparams_t>& params, boost::uuids::uuid& uuid, std::string& name, uint64_t& creationOrder)
{
static uint64_t s_creationOrder = 0;
}
}
double udiff = sw.udiff();
- g_outputBuffer=(boost::format("Had %d matches out of %d, %.1f qps, in %.1f usec\n") % matches % times % (1000000*(1.0*times/udiff)) % udiff).str();
+ g_outputBuffer=(boost::format("Had %d matches out of %d, %.1f qps, in %.1f us\n") % matches % times % (1000000*(1.0*times/udiff)) % udiff).str();
});
getOptionalValue<bool>(vars, "useClientSubnet", config.useECS);
getOptionalValue<bool>(vars, "useProxyProtocol", config.useProxyProtocol);
- getOptionalValue<bool>(vars, "disableZeroScoping", config.disableZeroScope);
+ getOptionalValue<bool>(vars, "disableZeroScope", config.disableZeroScope);
getOptionalValue<bool>(vars, "ipBindAddrNoPort", config.ipBindAddrNoPort);
getOptionalIntegerValue("newServer", vars, "addXPF", config.xpfRRCode);
ostringstream ret;
boost::format fmt;
+ auto latFmt = boost::format("%5.1f");
if (showUUIDs) {
- fmt = boost::format("%1$-3d %15$-36s %2$-20.20s %|62t|%3% %|107t|%4$5s %|88t|%5$7.1f %|103t|%6$7d %|106t|%7$10d %|115t|%8$10d %|117t|%9$10d %|123t|%10$7d %|128t|%11$5.1f %|146t|%12$5.1f %|152t|%13$11d %14%");
- // 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
- ret << (fmt % "#" % "Name" % "Address" % "State" % "Qps" % "Qlim" % "Ord" % "Wt" % "Queries" % "Drops" % "Drate" % "Lat" % "Outstanding" % "Pools" % "UUID") << endl;
+ fmt = boost::format("%1$-3d %15$-36s %2$-20.20s %|62t|%3% %|107t|%4$5s %|88t|%5$7.1f %|103t|%6$7d %|106t|%7$10d %|115t|%8$10d %|117t|%9$10d %|123t|%10$7d %|128t|%11$5.1f %|146t|%12$5s %|152t|%16$5s %|158t|%13$11d %14%");
+ // 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 (tcp latency)
+ ret << (fmt % "#" % "Name" % "Address" % "State" % "Qps" % "Qlim" % "Ord" % "Wt" % "Queries" % "Drops" % "Drate" % "Lat" % "Outstanding" % "Pools" % "UUID" % "TCP") << endl;
}
else {
- fmt = boost::format("%1$-3d %2$-20.20s %|25t|%3% %|70t|%4$5s %|51t|%5$7.1f %|66t|%6$7d %|69t|%7$10d %|78t|%8$10d %|80t|%9$10d %|86t|%10$7d %|91t|%11$5.1f %|109t|%12$5.1f %|115t|%13$11d %14%");
- ret << (fmt % "#" % "Name" % "Address" % "State" % "Qps" % "Qlim" % "Ord" % "Wt" % "Queries" % "Drops" % "Drate" % "Lat" % "Outstanding" % "Pools") << endl;
+ fmt = boost::format("%1$-3d %2$-20.20s %|25t|%3% %|70t|%4$5s %|51t|%5$7.1f %|66t|%6$7d %|69t|%7$10d %|78t|%8$10d %|80t|%9$10d %|86t|%10$7d %|91t|%11$5.1f %|109t|%12$5s %|115t|%15$5s %|121t|%13$11d %14%");
+ ret << (fmt % "#" % "Name" % "Address" % "State" % "Qps" % "Qlim" % "Ord" % "Wt" % "Queries" % "Drops" % "Drate" % "Lat" % "Outstanding" % "Pools" % "TCP") << endl;
}
uint64_t totQPS{0}, totQueries{0}, totDrops{0};
}
pools += p;
}
+ const std::string latency = (s->latencyUsec == 0.0 ? "-" : boost::str(latFmt % (s->latencyUsec / 1000.0)));
+ const std::string latencytcp = (s->latencyUsecTCP == 0.0 ? "-" : boost::str(latFmt % (s->latencyUsecTCP / 1000.0)));
if (showUUIDs) {
- ret << (fmt % counter % s->getName() % s->d_config.remote.toStringWithPort() % status % s->queryLoad % s->qps.getRate() % s->d_config.order % s->d_config.d_weight % s->queries.load() % s->reuseds.load() % (s->dropRate) % (s->latencyUsec / 1000.0) % s->outstanding.load() % pools % *s->d_config.id) << endl;
+ ret << (fmt % counter % s->getName() % s->d_config.remote.toStringWithPort() % status % s->queryLoad % s->qps.getRate() % s->d_config.order % s->d_config.d_weight % s->queries.load() % s->reuseds.load() % (s->dropRate) % latency % s->outstanding.load() % pools % *s->d_config.id % latencytcp) << endl;
}
else {
- ret << (fmt % counter % s->getName() % s->d_config.remote.toStringWithPort() % status % s->queryLoad % s->qps.getRate() % s->d_config.order % s->d_config.d_weight % s->queries.load() % s->reuseds.load() % (s->dropRate) % (s->latencyUsec / 1000.0) % s->outstanding.load() % pools) << endl;
+ ret << (fmt % counter % s->getName() % s->d_config.remote.toStringWithPort() % status % s->queryLoad % s->qps.getRate() % s->d_config.order % s->d_config.d_weight % s->queries.load() % s->reuseds.load() % (s->dropRate) % latency % s->outstanding.load() % pools % latencytcp) << endl;
}
totQPS += s->queryLoad;
totQueries += s->queries.load();
}
if (showUUIDs) {
ret << (fmt % "All" % "" % "" % ""
- % (double)totQPS % "" % "" % "" % totQueries % totDrops % "" % "" % "" % "" % "")
+ % (double)totQPS % "" % "" % "" % totQueries % totDrops % "" % "" % "" % "" % "" % "")
<< endl;
}
else {
ret << (fmt % "All" % "" % "" % ""
- % (double)totQPS % "" % "" % "" % totQueries % totDrops % "" % "" % "" % "")
+ % (double)totQPS % "" % "" % "" % totQueries % totDrops % "" % "" % "" % "" % "")
<< endl;
}
using nmts_t = NetmaskTree<DynBlock, AddressAndPortRange>;
std::shared_ptr<DNSRule> makeRule(const luadnsrule_t& var);
-void parseRuleParams(boost::optional<luaruleparams_t> params, boost::uuids::uuid& uuid, std::string& name, uint64_t& creationOrder);
+void parseRuleParams(boost::optional<luaruleparams_t>& params, boost::uuids::uuid& uuid, std::string& name, uint64_t& creationOrder);
void checkParameterBound(const std::string& parameter, uint64_t value, size_t max = std::numeric_limits<uint16_t>::max());
vector<std::function<void(void)>> setupLua(LuaContext& luaCtx, bool client, bool configCheck, const std::string& config);
break;
case COLUMN_BACKENDLATENCY:
DNSDistSNMPAgent::setCounter64Value(request,
- server->latencyUsec/1000.0);
+ server->getRelevantLatencyUsec() / 1000.0);
break;
case COLUMN_BACKENDWEIGHT:
DNSDistSNMPAgent::setCounter64Value(request,
if (currentResponse.d_idstate.selfGenerated == false && ds) {
const auto& ids = currentResponse.d_idstate;
double udiff = ids.queryRealTime.udiff();
- vinfolog("Got answer from %s, relayed to %s (%s, %d bytes), took %f usec", ds->d_config.remote.toStringWithPort(), ids.origRemote.toStringWithPort(), (state->d_handler.isTLS() ? "DoT" : "TCP"), currentResponse.d_buffer.size(), udiff);
+ vinfolog("Got answer from %s, relayed to %s (%s, %d bytes), took %f us", ds->d_config.remote.toStringWithPort(), ids.origRemote.toStringWithPort(), (state->d_handler.isTLS() ? "DoT" : "TCP"), currentResponse.d_buffer.size(), udiff);
auto backendProtocol = ds->getProtocol();
if (backendProtocol == dnsdist::Protocol::DoUDP) {
void IncomingTCPConnectionState::notifyIOError(InternalQueryState&& query, const struct timeval& now)
{
- std::shared_ptr<IncomingTCPConnectionState> state = shared_from_this();
+ if (std::this_thread::get_id() != d_creatorThreadID) {
+ /* empty buffer will signal an IO error */
+ TCPResponse response(PacketBuffer(), std::move(query), nullptr, nullptr);
+ handleCrossProtocolResponse(now, std::move(response));
+ return;
+ }
+ std::shared_ptr<IncomingTCPConnectionState> state = shared_from_this();
--state->d_currentQueriesCount;
state->d_hadErrors = true;
void IncomingTCPConnectionState::handleXFRResponse(const struct timeval& now, TCPResponse&& response)
{
+ if (std::this_thread::get_id() != d_creatorThreadID) {
+ handleCrossProtocolResponse(now, std::move(response));
+ return;
+ }
+
std::shared_ptr<IncomingTCPConnectionState> state = shared_from_this();
queueResponse(state, now, std::move(response));
}
msgh.msg_name = (struct sockaddr*)&to;
msgh.msg_namelen = to.getSocklen();
- if(from.sin4.sin_family) {
+ if (from.sin4.sin_family) {
addCMsgSrcAddr(&msgh, &cbuf, &from, 0);
}
else {
if (!selfGenerated) {
double udiff = ids.queryRealTime.udiff();
if (!muted) {
- vinfolog("Got answer from %s, relayed to %s (UDP), took %f usec", ds->d_config.remote.toStringWithPort(), ids.origRemote.toStringWithPort(), udiff);
+ vinfolog("Got answer from %s, relayed to %s (UDP), took %f us", ds->d_config.remote.toStringWithPort(), ids.origRemote.toStringWithPort(), udiff);
}
else {
- vinfolog("Got answer from %s, NOT relayed to %s (UDP) since that frontend is muted, took %f usec", ds->d_config.remote.toStringWithPort(), ids.origRemote.toStringWithPort(), udiff);
+ vinfolog("Got answer from %s, NOT relayed to %s (UDP) since that frontend is muted, took %f us", ds->d_config.remote.toStringWithPort(), ids.origRemote.toStringWithPort(), udiff);
}
handleResponseSent(ids, udiff, dr.ids.origRemote, ds->d_config.remote, response.size(), cleartextDH, ds->getProtocol(), true);
which is used by rules and actions to at least the correct
address family */
ids.origDest = cs.local;
+ ids.hopLocal.sin4.sin_family = 0;
}
std::vector<ProxyProtocolValue> proxyProtocolValues;
return dnsdist::Protocol::DoUDP;
}
+ double getRelevantLatencyUsec() const
+ {
+ if (isTCPOnly()) {
+ return latencyUsecTCP;
+ }
+ return latencyUsec;
+ }
+
static int s_udpTimeout;
static bool s_randomizeSockets;
static bool s_randomizeIDs;
}
if (suffixMatchRuleMatches) {
- root.submit(c.name, ((c.dh.rcode == 0 && c.usec == std::numeric_limits<unsigned int>::max()) ? -1 : c.dh.rcode), c.size, boost::none);
+ bool hit = c.ds.sin4.sin_family == 0;
+ if (!hit && c.ds.isIPv4() && c.ds.sin4.sin_addr.s_addr == 0 && c.ds.sin4.sin_port == 0) {
+ hit = true;
+ }
+
+ root.submit(c.name, ((c.dh.rcode == 0 && c.usec == std::numeric_limits<unsigned int>::max()) ? -1 : c.dh.rcode), c.size, hit, boost::none);
}
}
}
size_t usableServers = 0;
for (const auto& d : servers) {
if (d.second->isUp()) {
- poss[usableServers] = std::make_pair(std::make_tuple(d.second->outstanding.load(), d.second->d_config.order, d.second->latencyUsec), d.first);
+ poss[usableServers] = std::make_pair(std::make_tuple(d.second->outstanding.load(), d.second->d_config.order, d.second->getRelevantLatencyUsec()), d.first);
usableServers++;
}
}
double dnsdist_ffi_server_get_latency(const dnsdist_ffi_server_t* server)
{
- return server->server->latencyUsec;
+ return server->server->getRelevantLatencyUsec();
}
bool dnsdist_ffi_server_is_up(const dnsdist_ffi_server_t* server)
return node->self.bytes;
}
+uint64_t dnsdist_ffi_stat_node_get_hits(const dnsdist_ffi_stat_node_t* node)
+{
+ return node->self.hits;
+}
+
unsigned int dnsdist_ffi_stat_node_get_labels_count(const dnsdist_ffi_stat_node_t* node)
{
return node->node.labelsCount;
return node->children.bytes;
}
+uint64_t dnsdist_ffi_stat_node_get_children_hits(const dnsdist_ffi_stat_node_t* node)
+{
+ return node->children.hits;
+}
+
void dnsdist_ffi_state_node_set_reason(dnsdist_ffi_stat_node_t* node, const char* reason, size_t reasonSize)
{
node->reason = std::string(reason, reasonSize);
uint64_t dnsdist_ffi_stat_node_get_servfails_count(const dnsdist_ffi_stat_node_t* node) __attribute__ ((visibility ("default")));
uint64_t dnsdist_ffi_stat_node_get_drops_count(const dnsdist_ffi_stat_node_t* node) __attribute__ ((visibility ("default")));
uint64_t dnsdist_ffi_stat_node_get_bytes(const dnsdist_ffi_stat_node_t* node) __attribute__ ((visibility ("default")));
+ uint64_t dnsdist_ffi_stat_node_get_hits(const dnsdist_ffi_stat_node_t* node) __attribute__ ((visibility ("default")));
unsigned int dnsdist_ffi_stat_node_get_labels_count(const dnsdist_ffi_stat_node_t* node) __attribute__ ((visibility ("default")));
void dnsdist_ffi_stat_node_get_full_name_raw(const dnsdist_ffi_stat_node_t* node, const char** name, size_t* nameSize) __attribute__ ((visibility ("default")));
uint64_t dnsdist_ffi_stat_node_get_children_servfails_count(const dnsdist_ffi_stat_node_t* node) __attribute__ ((visibility ("default")));
uint64_t dnsdist_ffi_stat_node_get_children_drops_count(const dnsdist_ffi_stat_node_t* node) __attribute__ ((visibility ("default")));
uint64_t dnsdist_ffi_stat_node_get_children_bytes_count(const dnsdist_ffi_stat_node_t* node) __attribute__ ((visibility ("default")));
+ uint64_t dnsdist_ffi_stat_node_get_children_hits(const dnsdist_ffi_stat_node_t* node) __attribute__ ((visibility ("default")));
void dnsdist_ffi_state_node_set_reason(dnsdist_ffi_stat_node_t* node, const char* reason, size_t reasonSize) __attribute__ ((visibility ("default")));
}
#ifndef DISABLE_SECPOLL
#include <string>
+#include <ctime>
extern std::string g_secPollSuffix;
extern time_t g_secPollInterval;
Changelog
=========
+.. changelog::
+ :version: 1.7.4
+ :released: 14th of April 2023
+
+ .. change::
+ :tags: Bug Fixes
+ :pullreq: 12183
+ :tickets: 12177
+
+ Fix building with boost < 1.56
+
+ .. change::
+ :tags: Bug Fixes
+ :pullreq: 12460
+ :tickets: 12453
+
+ lock.hh: include <stdexcept>
+
+ .. change::
+ :tags: Bug Fixes
+ :pullreq: 12569
+
+ dnsdist-protocols.hh: include <cstdint> (Sander Hoentjen)
+
+ .. change::
+ :tags: New Features
+ :pullreq: 12621
+ :tickets: 12074
+
+ Add getPoolNames() function, returning a list of pool names (Christof Chen)
+
+ .. change::
+ :tags: Bug Fixes
+ :pullreq: 12535
+
+ Fix the formatting of 'showServers'
+
+ .. change::
+ :tags: Bug Fixes
+ :pullreq: 12529
+ :tickets: 11905
+
+ Properly record the incoming flags on a timeout
+
+ .. change::
+ :tags: Bug Fixes, Metrics
+ :pullreq: 12484
+ :tickets: 11498
+
+ Properly update rcode-related metrics on RCodeAction hits
+
+ .. change::
+ :tags: Bug Fixes, DNS over TLS, DNS over HTTPS
+ :pullreq: 12421
+ :tickets: 12341
+
+ Skip invalid OCSP files after issuing a warning
+
+ .. change::
+ :tags: Bug Fixes
+ :pullreq: 12365
+ :tickets: 12357
+
+ Prevent an underflow of the TCP d_queued counter
+
+ .. change::
+ :tags: Bug Fixes, DNS over HTTPS
+ :pullreq: 12327
+
+ Fix the health-check timeout computation for DoH backend
+
+ .. change::
+ :tags: Bug Fixes, Webserver
+ :pullreq: 12260
+ :tickets: 9349
+
+ Properly encode json strings containing binary data
+
+ .. change::
+ :tags: Bug Fixes, DNS over TLS
+ :pullreq: 12237
+ :tickets: 12236
+
+ Ignore unclean TLS session shutdown
+
+ .. change::
+ :tags: Bug Fixes
+ :pullreq: 12100
+ :tickets: 12099
+
+ Properly handle single-SOA XFR responses
+
+ .. change::
+ :tags: Bug Fixes
+ :pullreq: 11830
+ :tickets: 4155
+
+ Also reconnect on ENETUNREACH. (Asgeir Storesund Nilsen)
+
+ .. change::
+ :tags: Bug Fixes
+ :pullreq: 11729
+ :tickets: 11728
+
+ Fix a bug in SetEDNSOptionAction
+
+ .. change::
+ :tags: Bug Fixes
+ :pullreq: 11718
+
+ Fix the number of concurrent queries on a backend TCP conn
+
+.. changelog::
+ :version: 1.8.0
+ :released: 30th of March 2023
+
+ .. change::
+ :tags: Bug Fixes
+ :pullreq: 12687
+
+ Fix 'Unknown key' issue for actions and rules parameters
+
+ .. change::
+ :tags: Bug Fixes
+ :pullreq: 12672
+
+ Fix a dnsheader unaligned case
+
+ .. change::
+ :tags: Bug Fixes
+ :pullreq: 12654
+
+ secpoll: explicitly include necessary ctime header for time_t
+
+.. changelog::
+ :version: 1.8.0-rc3
+ :released: 16th of March 2023
+
+ .. change::
+ :tags: Bug Fixes
+ :pullreq: 12641
+
+ Use the correct source address when harvesting failed
+
+ .. change::
+ :tags: Bug Fixes
+ :pullreq: 12639
+
+ Fix a race when a cross-protocol query triggers an IO error
+
+ .. change::
+ :tags: Improvements, Metrics, Webserver
+ :pullreq: 12638
+
+ Report per-incoming transport latencies in the web interface
+
+ .. change::
+ :tags: Improvements, Metrics
+ :pullreq: 12648
+
+ Report the TCP latency for TCP-only Do53, DoT and DoH backends
+
+ .. change::
+ :tags: Improvements
+ :pullreq: 12626
+
+ Count hits in the StatNode
+
.. changelog::
:version: 1.8.0-rc2
:released: 9th of March 2023
:tags: New Features, DNS over HTTPS, DNS over TLS
:pullreq: 11027
- Add support for password protected PCKS12 files for TLS configuration
+ Add support for password protected PKCS12 files for TLS configuration
.. change::
:tags: New Features
- Release date
- Security-Only updates
- End of Life
+ * - 1.8
+ - March 30 2023
+ -
+ -
* - 1.7
- January 17 2022
- -
+ - March 30 2023
-
* - 1.6
- May 11 2021
- -
+ - March 30 2023
-
* - 1.5
- July 30 2020
- January 17 2022
- -
+ - EOL (March 30 2023)
* - 1.4
- November 20 2019
- May 2021
:param int top: How many rules to return. Default is 10.
-.. function:: grepq(selector[, num])
- grepq(selectors[, num])
+.. function:: grepq(selector[, num [, options]])
+ grepq(selectors[, num [, options]])
+
+ .. versionchanged:: 1.9.0
+ ``options`` optional parameter table added.
Prints the last ``num`` queries and responses matching ``selector`` or ``selectors``.
Queries and responses are accounted in separate ring buffers, and answers from the packet cache are not stored in the response ring buffer.
:param str selector: Select queries based on this property.
:param {str} selectors: A lua table of selectors. Only queries matching all selectors are shown
- :param int num: Show a maximum of ``num`` recent queries+responses, default is 10.
+ :param int num: Show a maximum of ``num`` recent queries+responses.
+ :param table options: A table with key: value pairs with options described below.
+
+ Options:
+
+ * ``outputFile=path``: string - Write the output of the command to the supplied file, instead of the standard output.
.. function:: setVerbose(verbose)
PKCS12 files are only supported by the ``openssl`` provider, password-protected or not.
- :param string pathToCert: Path to a file containing the certificate or a PCKS12 file containing both a certificate and a key.
+ :param string pathToCert: Path to a file containing the certificate or a PKCS12 file containing both a certificate and a key.
:param table options: A table with key: value pairs with additional options.
Options:
* ``key="path/to/key"``: string - Path to a file containing the key corresponding to the certificate.
- * ``password="pass"``: string - Password protecting the PCKS12 file if appropriate.
+ * ``password="pass"``: string - Password protecting the PKCS12 file if appropriate.
.. code-block:: lua
newTLSCertificate("path/to/pub.crt", {key="path/to/private.pem"})
- newTLSCertificate("path/to/domain.p12", {password="passphrase"}) -- use a password protected PCKS12 file
+ newTLSCertificate("path/to/domain.p12", {password="passphrase"}) -- use a password protected PKCS12 file
DOHFrontend
~~~~~~~~~~~
:param table options: A table with key: value pairs with options.
Options:
+
* ``ipv4MaxItems``: int - The maximum number of entries in the IPv4 map. Default is 0 which will not allow any entry at all.
* ``ipv4PinnedPath``: str - The filesystem path this map should be pinned to.
* ``ipv6MaxItems``: int - The maximum number of entries in the IPv6 map. Default is 0 which will not allow any entry at all.
* ``cidr6PinnedPath``: str - The filesystem path this map should be pinned to.
* ``qnamesMaxItems``: int - The maximum number of entries in the qname map. Default is 0 which will not allow any entry at all.
* ``qnamesPinnedPath``: str - The filesystem path this map should be pinned to.
- * ``external``: bool - If set to true, DNSDist can to load the internal eBPF program.
+ * ``external``: bool - If set to true, DNSDist does not load the internal eBPF program.
.. function:: newDynBPFFilter(bpf) -> DynBPFFilter
The configuration check will now fail if the configuration file does not exist. For this reason we now create a default configuration file, based on the file previously called ``dnsdistconf.lua``, which contains commented-out examples of how to set up dnsdist.
+Latency metrics have been broken down:
+
+* per incoming protocol (Do53 UDP, Do53 TCP, DoT, DoH) for global latency metrics
+* between UDP (Do53) and TCP (Do53 TCP, DoT, DoH) for backend latency metrics
+
1.7.0 to 1.7.1
--------------
if (!du->ids.selfGenerated) {
double udiff = du->ids.queryRealTime.udiff();
- vinfolog("Got answer from %s, relayed to %s (https), took %f usec", du->downstream->d_config.remote.toStringWithPort(), du->ids.origRemote.toStringWithPort(), udiff);
+ vinfolog("Got answer from %s, relayed to %s (https), took %f us", du->downstream->d_config.remote.toStringWithPort(), du->ids.origRemote.toStringWithPort(), udiff);
auto backendProtocol = du->downstream->getProtocol();
if (backendProtocol == dnsdist::Protocol::DoUDP && du->tcp) {
du = std::move(dr.ids.du);
double udiff = du->ids.queryRealTime.udiff();
- vinfolog("Got answer from %s, relayed to %s (https), took %f usec", du->downstream->d_config.remote.toStringWithPort(), du->ids.origRemote.toStringWithPort(), udiff);
+ vinfolog("Got answer from %s, relayed to %s (https), took %f us", du->downstream->d_config.remote.toStringWithPort(), du->ids.origRemote.toStringWithPort(), udiff);
handleResponseSent(du->ids, udiff, dr.ids.origRemote, du->downstream->d_config.remote, du->response.size(), cleartextDH, du->downstream->getProtocol(), true);
</tr></table>
<p>
Uptime: <span id="uptime"></span>, Number of queries: <span id="questions"></span> (<span id="qps"></span> qps), ACL drops: <span id="acl-drops"></span>, Dynamic drops: <span id="dyn-drops"></span>, Rule drops: <span id="rule-drops"></span><br/>
- Average response time: <span id="latency"></span> ms, CPU Usage: <span id="cpu"></span>%, Cache hitrate: <span id="phitrate"></span>%, Server selection policy: <span id="server-policy"></span><br/>
+ Average response time: UDP <span id="latency"></span> ms, TCP <span id="latency-tcp"></span> ms, DoT <span id="latency-dot"></span> ms, DoH <span id="latency-doh"></span> ms <br/>
+ CPU Usage: <span id="cpu"></span>%, Cache hitrate: <span id="phitrate"></span>%, Server selection policy: <span id="server-policy"></span><br/>
Listening on: <span id="local"></span>, ACL: <span id="acl"></span>
</p>
<table width="100%" cellpadding="20">
$("#rule-drops").text(data["rule-drop"]);
$("#uptime").text(moment.duration(data["uptime"]*1000.0).humanize());
$("#latency").text((data["latency-avg10000"]/1000.0).toFixed(2));
+ $("#latency-tcp").text((data["latency-tcp-avg10000"]/1000.0).toFixed(2));
+ $("#latency-dot").text((data["latency-dot-avg10000"]/1000.0).toFixed(2));
+ $("#latency-doh").text((data["latency-doh-avg10000"]/1000.0).toFixed(2));
if(!gdata["cpu-sys-msec"])
gdata=data;
$("#version").text(data["daemon_type"]+" "+data["version"]);
$("#acl").text(data["acl"]);
$("#local").text(data["local"]);
- var bouw='<table width="100%"><tr align=right><th>#</th><th align=left>Name</th><th align=left>Address</th><th>Status</th><th>Latency</th><th>Queries</th><th>Drops</th><th>QPS</th><th>Out</th><th>Weight</th><th>Order</th><th align=left>Pools</th></tr>';
+ var bouw='<table width="100%"><tr align=right><th>#</th><th align=left>Name</th><th align=left>Address</th><th>Status</th><th>UDP Latency</th><th>TCP Latency</th><th>Queries</th><th>Drops</th><th>QPS</th><th>Out</th><th>Weight</th><th>Order</th><th align=left>Pools</th></tr>';
$.each(data["servers"], function(a,b) {
bouw = bouw + ("<tr align=right><td>"+b["id"]+"</td><td align=left>"+b["name"]+"</td><td align=left>"+b["address"]+"</td><td>"+b["state"]+"</td>");
- var latency = (b["latency"] === null) ? 0.0 : b["latency"];
- bouw = bouw + ("<td>"+latency.toFixed(2)+"</td><td>"+b["queries"]+"</td><td>"+b["reuseds"]+"</td><td>"+(b["qps"]).toFixed(2)+"</td><td>"+b["outstanding"]+"</td>");
+ var latency = (b["latency"] === null || b["latency"] === 0.0) ? "-" : b["latency"].toFixed(2);
+ var tcpLatency = (b["tcpLatency"] === null || b["tcpLatency"] === 0.0) ? "-" : b["tcpLatency"].toFixed(2);
+ bouw = bouw + ("<td>"+latency+"</td><td>"+tcpLatency+"</td><td>"+b["queries"]+"</td><td>"+b["reuseds"]+"</td><td>"+(b["qps"]).toFixed(2)+"</td><td>"+b["outstanding"]+"</td>");
bouw = bouw + ("<td>"+b["weight"]+"</td><td>"+b["order"]+"</td><td align=left>"+b["pools"]+"</td></tr>");
});
bouw = bouw + "</table>";
BOOST_CHECK_EQUAL(mdp.d_answers.at(0).first.d_type, static_cast<uint16_t>(QType::CNAME));
BOOST_CHECK_EQUAL(mdp.d_answers.at(0).first.d_class, QClass::IN);
BOOST_CHECK_EQUAL(mdp.d_answers.at(0).first.d_name, newTarget);
- auto content = std::dynamic_pointer_cast<UnknownRecordContent>(mdp.d_answers.at(0).first.d_content);
+ auto content = getRR<UnknownRecordContent>(mdp.d_answers.at(0).first);
BOOST_REQUIRE(content != nullptr);
BOOST_CHECK_EQUAL(content->getRawContent().size(), notTheTarget.getStorage().size());
DNSName DNSName::getCommonLabels(const DNSName& other) const
{
- DNSName result;
+ if (empty() || other.empty()) {
+ return DNSName();
+ }
+
+ DNSName result(g_rootdnsname);
const std::vector<std::string> ours = getRawLabels();
const std::vector<std::string> others = other.getRawLabels();
// in case we are not compressing for AXFR, no such checking is performed!
if(d_compress) {
- std::string ser = const_cast<DNSZoneRecord&>(rr).dr.d_content->serialize(rr.dr.d_name);
+ std::string ser = rr.dr.getContent()->serialize(rr.dr.d_name);
auto hash = boost::hash< std::pair<DNSName, std::string> >()({rr.dr.d_name, ser});
if(d_dedup.count(hash)) { // might be a dup
for(auto & i : d_rrs) {
maxScopeMask = max(maxScopeMask, pos->scopeMask);
pw.startRecord(pos->dr.d_name, pos->dr.d_type, pos->dr.d_ttl, pos->dr.d_class, pos->dr.d_place);
- pos->dr.d_content->toPacket(pw);
+ pos->dr.getContent()->toPacket(pw);
if(pw.size() + optsize > (d_tcp ? 65535 : getMaxReplyLen())) {
if (throwsOnTruncation) {
throw PDNSException("attempt to write an oversized chunk");
for(const auto & answer : mdp.d_answers) {
if(answer.first.d_type == QType::TSIG && answer.first.d_class == QType::ANY) {
// cast can fail, f.e. if d_content is an UnknownRecordContent.
- shared_ptr<TSIGRecordContent> content = std::dynamic_pointer_cast<TSIGRecordContent>(answer.first.d_content);
+ auto content = getRR<TSIGRecordContent>(answer.first);
if (!content) {
g_log<<Logger::Error<<"TSIG record has no or invalid content (invalid packet)"<<endl;
return false;
if(answer.first.d_type == QType::TKEY) {
// cast can fail, f.e. if d_content is an UnknownRecordContent.
- shared_ptr<TKEYRecordContent> content = std::dynamic_pointer_cast<TKEYRecordContent>(answer.first.d_content);
+ auto content = getRR<TKEYRecordContent>(answer.first);
if (!content) {
g_log<<Logger::Error<<"TKEY record has no or invalid content (invalid packet)"<<endl;
return false;
return str.str();
}
-void UnknownRecordContent::toPacket(DNSPacketWriter& pw)
+void UnknownRecordContent::toPacket(DNSPacketWriter& pw) const
{
pw.xfrBlob(string(d_record.begin(),d_record.end()));
}
rr.qname = d.d_name;
rr.qtype = QType(d.d_type);
rr.ttl = d.d_ttl;
- rr.content = d.d_content->getZoneRepresentation(true);
+ rr.content = d.getContent()->getZoneRepresentation(true);
rr.auth = false;
rr.qclass = d.d_class;
return rr;
!(d_qtype == QType::IXFR && dr.d_place == DNSResourceRecord::AUTHORITY && dr.d_type == QType::SOA) && // IXFR queries have a SOA in their AUTHORITY section
(dr.d_place == DNSResourceRecord::ANSWER || dr.d_place == DNSResourceRecord::AUTHORITY || (dr.d_type != QType::OPT && dr.d_type != QType::TSIG && dr.d_type != QType::SIG && dr.d_type != QType::TKEY) || ((dr.d_type == QType::TSIG || dr.d_type == QType::SIG || dr.d_type == QType::TKEY) && dr.d_class != QClass::ANY))) {
// cerr<<"discarding RR, query is "<<query<<", place is "<<dr.d_place<<", type is "<<dr.d_type<<", class is "<<dr.d_class<<endl;
- dr.d_content=std::make_shared<UnknownRecordContent>(dr, pr);
+ dr.setContent(std::make_shared<UnknownRecordContent>(dr, pr));
}
else {
// cerr<<"parsing RR, query is "<<query<<", place is "<<dr.d_place<<", type is "<<dr.d_type<<", class is "<<dr.d_class<<endl;
- dr.d_content=DNSRecordContent::mastermake(dr, pr, d_header.opcode);
+ dr.setContent(DNSRecordContent::mastermake(dr, pr, d_header.opcode));
}
/* XXX: XPF records should be allowed after TSIG as soon as the actual XPF option code has been assigned:
}
// method of operation: silently fail if it doesn't work - we're only trying to be nice, don't fall over on it
-void ageDNSPacket(char* packet, size_t length, uint32_t seconds)
+void ageDNSPacket(char* packet, size_t length, uint32_t seconds, const dnsheader_aligned& aligned_dh)
{
- if(length < sizeof(dnsheader))
+ if (length < sizeof(dnsheader)) {
return;
- try
- {
- const dnsheader* dh = reinterpret_cast<const dnsheader*>(packet);
- const uint64_t dqcount = ntohs(dh->qdcount);
- const uint64_t numrecords = ntohs(dh->ancount) + ntohs(dh->nscount) + ntohs(dh->arcount);
+ }
+ try {
+ const dnsheader* dhp = aligned_dh.get();
+ const uint64_t dqcount = ntohs(dhp->qdcount);
+ const uint64_t numrecords = ntohs(dhp->ancount) + ntohs(dhp->nscount) + ntohs(dhp->arcount);
DNSPacketMangler dpm(packet, length);
- uint64_t n;
- for(n=0; n < dqcount; ++n) {
+ for (uint64_t rec = 0; rec < dqcount; ++rec) {
dpm.skipDomainName();
/* type and class */
dpm.skipBytes(4);
}
- // cerr<<"Skipped "<<n<<" questions, now parsing "<<numrecords<<" records"<<endl;
- for(n=0; n < numrecords; ++n) {
+
+ for(uint64_t rec = 0; rec < numrecords; ++rec) {
dpm.skipDomainName();
uint16_t dnstype = dpm.get16BitInt();
/* class */
dpm.skipBytes(2);
- if(dnstype == QType::OPT) // not aging that one with a stick
- break;
-
- dpm.decreaseAndSkip32BitInt(seconds);
+ if (dnstype != QType::OPT) { // not aging that one with a stick
+ dpm.decreaseAndSkip32BitInt(seconds);
+ } else {
+ dpm.skipBytes(4);
+ }
dpm.skipRData();
}
}
- catch(...)
- {
- return;
+ catch(...) {
}
}
-void ageDNSPacket(std::string& packet, uint32_t seconds)
+void ageDNSPacket(std::string& packet, uint32_t seconds, const dnsheader_aligned& aligned_dh)
{
- ageDNSPacket((char*)packet.c_str(), packet.length(), seconds);
+ ageDNSPacket(packet.data(), packet.length(), seconds, aligned_dh);
}
uint32_t getDNSPacketMinTTL(const char* packet, size_t length, bool* seenAuthSOA)
virtual std::string getZoneRepresentation(bool noDot=false) const = 0;
virtual ~DNSRecordContent() {}
- virtual void toPacket(DNSPacketWriter& pw)=0;
+ virtual void toPacket(DNSPacketWriter& pw) const = 0;
// returns the wire format of the content, possibly including compressed pointers pointing to the owner name (unless canonic or lowerCase are set)
- virtual string serialize(const DNSName& qname, bool canonic=false, bool lowerCase=false) // it would rock if this were const, but it is too hard because we use the same method (xfrPacket) for both kinds of conversion (fromPacket, toPacket)
+ string serialize(const DNSName& qname, bool canonic=false, bool lowerCase=false) const
{
vector<uint8_t> packet;
DNSPacketWriter pw(packet, g_rootdnsname, 1);
d_place(place) {}
DNSName d_name;
- std::shared_ptr<DNSRecordContent> d_content;
+private:
+ std::shared_ptr<const DNSRecordContent> d_content;
+public:
uint16_t d_type{};
uint16_t d_class{};
uint32_t d_ttl{};
return s.str();
}
+ void setContent(const std::shared_ptr<const DNSRecordContent>& content)
+ {
+ d_content = content;
+ }
+
+ void setContent(std::shared_ptr<const DNSRecordContent>&& content)
+ {
+ d_content = std::move(content);
+ }
+
+ [[nodiscard]] const std::shared_ptr<const DNSRecordContent>& getContent() const
+ {
+ return d_content;
+ }
+
bool operator<(const DNSRecord& rhs) const
{
if(std::tie(d_name, d_type, d_class, d_ttl) < std::tie(rhs.d_name, rhs.d_type, rhs.d_class, rhs.d_ttl))
UnknownRecordContent(const string& zone);
string getZoneRepresentation(bool noDot) const override;
- void toPacket(DNSPacketWriter& pw) override;
+ void toPacket(DNSPacketWriter& pw) const override;
uint16_t getType() const override
{
return d_dr.d_type;
};
string simpleCompress(const string& label, const string& root="");
-void ageDNSPacket(char* packet, size_t length, uint32_t seconds);
-void ageDNSPacket(std::string& packet, uint32_t seconds);
+void ageDNSPacket(char* packet, size_t length, uint32_t seconds, const dnsheader_aligned&);
+void ageDNSPacket(std::string& packet, uint32_t seconds, const dnsheader_aligned&);
void editDNSPacketTTL(char* packet, size_t length, const std::function<uint32_t(uint8_t, uint16_t, uint16_t, uint32_t)>& visitor);
void clearDNSPacketRecordTypes(vector<uint8_t>& packet, const std::unordered_set<QType>& qtypes);
void clearDNSPacketRecordTypes(PacketBuffer& packet, const std::unordered_set<QType>& qtypes);
bool visitDNSPacket(const std::string_view& packet, const std::function<bool(uint8_t, uint16_t, uint16_t, uint32_t, uint16_t, const char*)>& visitor);
template<typename T>
-std::shared_ptr<T> getRR(const DNSRecord& dr)
+std::shared_ptr<const T> getRR(const DNSRecord& dr)
{
- return std::dynamic_pointer_cast<T>(dr.d_content);
+ return std::dynamic_pointer_cast<const T>(dr.getContent());
}
/** Simple DNSPacketMangler. Ritual is: get a pointer into the packet and moveOffset() to beyond your needs
MOADNSParser mdp(false, p.getString());
// cerr<<"Got completion, "<<mdp.d_answers.size()<<" answers, rcode: "<<mdp.d_header.rcode<<endl;
if (mdp.d_header.rcode == RCode::NoError) {
- for(const auto & answer : mdp.d_answers) {
+ for (auto& answer : mdp.d_answers) {
// cerr<<"comp: "<<(int)j->first.d_place-1<<" "<<j->first.d_label<<" " << DNSRecordContent::NumberToType(j->first.d_type)<<" "<<j->first.d_content->getZoneRepresentation()<<endl;
if(answer.first.d_place == DNSResourceRecord::ANSWER || (answer.first.d_place == DNSResourceRecord::AUTHORITY && answer.first.d_type == QType::SOA)) {
dzr.dr.d_type = answer.first.d_type;
dzr.dr.d_ttl=answer.first.d_ttl;
dzr.dr.d_place= answer.first.d_place;
- dzr.dr.d_content=answer.first.d_content;
+ dzr.dr.setContent(answer.first.getContent());
i->second.complete->addRecord(std::move(dzr));
}
}
}
#endif
-void OPTRecordContent::getData(vector<pair<uint16_t, string> >& options)
+void OPTRecordContent::getData(vector<pair<uint16_t, string> >& options) const
{
string::size_type pos=0;
uint16_t code, len;
while(d_data.size() >= 4 + pos) {
- code = 256 * (unsigned char)d_data[pos] + (unsigned char)d_data[pos+1];
- len = 256 * (unsigned char)d_data[pos+2] + (unsigned char)d_data[pos+3];
+ code = 256 * (unsigned char)d_data.at(pos) + (unsigned char)d_data.at(pos+1);
+ len = 256 * (unsigned char)d_data.at(pos+2) + (unsigned char)d_data.at(pos+3);
pos+=4;
if(pos + len > d_data.size())
}
return ret;
}
-void EUI48RecordContent::toPacket(DNSPacketWriter& pw)
+void EUI48RecordContent::toPacket(DNSPacketWriter& pw) const
{
string blob(d_eui48, d_eui48+6);
pw.xfrBlob(blob);
}
return ret;
}
-void EUI64RecordContent::toPacket(DNSPacketWriter& pw)
+void EUI64RecordContent::toPacket(DNSPacketWriter& pw) const
{
string blob(d_eui64, d_eui64+8);
pw.xfrBlob(blob);
// DNSRecord to Packet conversion
-void APLRecordContent::toPacket(DNSPacketWriter& pw) {
+void APLRecordContent::toPacket(DNSPacketWriter& pw) const {
for (auto & ard : aplrdata) {
pw.xfr16BitInt(ard.d_family);
pw.xfr8BitInt(ard.d_prefix);
if (p == d_params.end()) {
return;
}
+
std::vector<ComboAddress> h;
h.reserve(h.size() + addresses.size());
h.insert(h.end(), addresses.begin(), addresses.end());
+
try {
auto newParam = SvcParam(key, std::move(h));
d_params.erase(p);
d_params.insert(newParam);
- } catch(...) {
+ } catch (...) {
// XXX maybe we should SERVFAIL instead?
return;
}
return p;
}
+std::shared_ptr<SVCBBaseRecordContent> SVCBRecordContent::clone() const
+{
+ return std::shared_ptr<SVCBBaseRecordContent>(std::make_shared<SVCBRecordContent>(*this));
+}
+
+std::shared_ptr<SVCBBaseRecordContent> HTTPSRecordContent::clone() const
+{
+ return std::shared_ptr<SVCBBaseRecordContent>(std::make_shared<HTTPSRecordContent>(*this));
+}
+
/* SVCB end */
boilerplate_conv(TKEY,
}
uint16_t DNSKEYRecordContent::getTag() const
-{
- DNSKEYRecordContent tmp(*this);
- return makeTag(tmp.serialize(DNSName())); // this can't be const for some reason
-}
-
-uint16_t DNSKEYRecordContent::getTag()
{
return makeTag(this->serialize(DNSName()));
}
#include "dnsparser.hh"
#include "dnswriter.hh"
+#include "lock.hh"
#include "rcpgenerator.hh"
#include <set>
#include <bitset>
static std::shared_ptr<DNSRecordContent> make(const DNSRecord &dr, PacketReader& pr); \
static std::shared_ptr<DNSRecordContent> make(const string& zonedata); \
string getZoneRepresentation(bool noDot=false) const override; \
- void toPacket(DNSPacketWriter& pw) override; \
- uint16_t getType() const override { return QType::RNAME; } \
+ void toPacket(DNSPacketWriter& pw) const override; \
+ uint16_t getType() const override { return QType::RNAME; } \
+ template<class Convertor> void xfrPacket(Convertor& conv, bool noDot=false) const; \
template<class Convertor> void xfrPacket(Convertor& conv, bool noDot=false);
class NAPTRRecordContent : public DNSRecordContent
public:
includeboilerplate(ALIAS)
+ [[nodiscard]] const DNSName& getContent() const
+ {
+ return d_content;
+ }
+private:
DNSName d_content;
};
#endif
public:
OPTRecordContent(){}
includeboilerplate(OPT)
- void getData(vector<pair<uint16_t, string> > &opts);
+ void getData(vector<pair<uint16_t, string> > &opts) const;
private:
string d_data;
};
DNSKEYRecordContent();
includeboilerplate(DNSKEY)
uint16_t getTag() const;
- uint16_t getTag();
uint16_t d_flags{0};
uint8_t d_protocol{0};
bool hasParam(const SvcParam::SvcParamKey &key) const;
// Get the parameter with |key|, will throw out_of_range if param isn't there
SvcParam getParam(const SvcParam::SvcParamKey &key) const;
+ virtual std::shared_ptr<SVCBBaseRecordContent> clone() const = 0;
protected:
- uint16_t d_priority;
+ std::set<SvcParam> d_params;
DNSName d_target;
- set<SvcParam> d_params;
+ uint16_t d_priority;
// Get the iterator to parameter with |key|, return value can be d_params::end
- set<SvcParam>::const_iterator getParamIt(const SvcParam::SvcParamKey &key) const;
+ std::set<SvcParam>::const_iterator getParamIt(const SvcParam::SvcParamKey &key) const;
};
class SVCBRecordContent : public SVCBBaseRecordContent
{
public:
includeboilerplate(SVCB)
+ std::shared_ptr<SVCBBaseRecordContent> clone() const override;
};
class HTTPSRecordContent : public SVCBBaseRecordContent
{
public:
includeboilerplate(HTTPS)
+ std::shared_ptr<SVCBBaseRecordContent> clone() const override;
};
class RRSIGRecordContent : public DNSRecordContent
}
void fromPacket(PacketReader& pr);
- void toPacket(DNSPacketWriter& pw);
+ void toPacket(DNSPacketWriter& pw) const;
std::string getZoneRepresentation() const;
static constexpr size_t const nbTypes = 65536;
static std::shared_ptr<DNSRecordContent> make(const DNSRecord &dr, PacketReader& pr);
static std::shared_ptr<DNSRecordContent> make(const string& content);
string getZoneRepresentation(bool noDot=false) const override;
- void toPacket(DNSPacketWriter& pw) override;
+ void toPacket(DNSPacketWriter& pw) const override;
uint16_t getType() const override
{
return QType::NSEC;
static std::shared_ptr<DNSRecordContent> make(const DNSRecord &dr, PacketReader& pr);
static std::shared_ptr<DNSRecordContent> make(const string& content);
string getZoneRepresentation(bool noDot=false) const override;
- void toPacket(DNSPacketWriter& pw) override;
+ void toPacket(DNSPacketWriter& pw) const override;
uint8_t d_algorithm{0}, d_flags{0};
uint16_t d_iterations{0};
static std::shared_ptr<DNSRecordContent> make(const DNSRecord &dr, PacketReader& pr);
static std::shared_ptr<DNSRecordContent> make(const string& content);
string getZoneRepresentation(bool noDot=false) const override;
- void toPacket(DNSPacketWriter& pw) override;
+ void toPacket(DNSPacketWriter& pw) const override;
uint16_t getType() const override
{
static std::shared_ptr<DNSRecordContent> make(const DNSRecord &dr, PacketReader& pr);
static std::shared_ptr<DNSRecordContent> make(const string& content);
string getZoneRepresentation(bool noDot=false) const override;
- void toPacket(DNSPacketWriter& pw) override;
+ void toPacket(DNSPacketWriter& pw) const override;
uint16_t getType() const override
{
static std::shared_ptr<DNSRecordContent> make(const DNSRecord &dr, PacketReader& pr);
static std::shared_ptr<DNSRecordContent> make(const string& content);
string getZoneRepresentation(bool noDot=false) const override;
- void toPacket(DNSPacketWriter& pw) override;
+ void toPacket(DNSPacketWriter& pw) const override;
uint8_t d_version{0}, d_size{0}, d_horizpre{0}, d_vertpre{0};
uint32_t d_latitude{0}, d_longitude{0}, d_altitude{0};
static std::shared_ptr<DNSRecordContent> make(const DNSRecord &dr, PacketReader& pr);
static std::shared_ptr<DNSRecordContent> make(const string& zone); // FIXME400: DNSName& zone?
string getZoneRepresentation(bool noDot=false) const override;
- void toPacket(DNSPacketWriter& pw) override;
+ void toPacket(DNSPacketWriter& pw) const override;
uint16_t getType() const override { return QType::EUI48; }
private:
// storage for the bytes
static std::shared_ptr<DNSRecordContent> make(const DNSRecord &dr, PacketReader& pr);
static std::shared_ptr<DNSRecordContent> make(const string& zone); // FIXME400: DNSName& zone?
string getZoneRepresentation(bool noDot=false) const override;
- void toPacket(DNSPacketWriter& pw) override;
+ void toPacket(DNSPacketWriter& pw) const override;
uint16_t getType() const override { return QType::EUI64; }
private:
// storage for the bytes
return std::make_shared<RNAME##RecordContent>(zonedata); \
} \
\
-void RNAME##RecordContent::toPacket(DNSPacketWriter& pw) \
+void RNAME##RecordContent::toPacket(DNSPacketWriter& pw) const \
{ \
this->xfrPacket(pw); \
} \
CONV; \
if (conv.eof() == false) throw MOADNSException("When parsing " #RNAME " trailing data was not parsed: '" + conv.getRemaining() + "'"); \
} \
+template<class Convertor> \
+void RNAME##RecordContent::xfrPacket(Convertor& conv, bool /* noDot */) const \
+{ \
+ CONV; \
+ if (conv.eof() == false) throw MOADNSException("When parsing " #RNAME " trailing data was not parsed: '" + conv.getRemaining() + "'"); \
+} \
struct EDNSOpts
{
cout.precision(2);
for(unsigned int i =0 ; i < sizeof(limits)/sizeof(limits[0]); ++i) {
if(limits[i]!=flightTimes.size())
- cout<<"Within "<<limits[i]<<" msec: ";
+ cout<<"Within "<<limits[i]<<" ms: ";
else
- cout<<"Beyond "<<limits[i]-2<<" msec: ";
+ cout<<"Beyond "<<limits[i]-2<<" ms: ";
uint64_t here = countLessThan(limits[i]);
cout<<100.0*here/totals<<"% ("<<100.0*(here-sofar)/totals<<"%)"<<endl;
sofar=here;
if(!g_quiet) {
cout<<"orig: rcode="<<qd.d_origRcode<<"\n";
for(set<DNSRecord>::const_iterator i=canonicOrig.begin(); i!=canonicOrig.end(); ++i)
- cout<<"\t"<<i->d_name<<"\t"<<DNSRecordContent::NumberToType(i->d_type)<<"\t'" << (i->d_content ? i->d_content->getZoneRepresentation() : "") <<"'\n";
+ cout<<"\t"<<i->d_name<<"\t"<<DNSRecordContent::NumberToType(i->d_type)<<"\t'" << (i->getContent() ? i->getContent()->getZoneRepresentation() : "") <<"'\n";
cout<<"new: rcode="<<qd.d_newRcode<<"\n";
for(set<DNSRecord>::const_iterator i=canonicNew.begin(); i!=canonicNew.end(); ++i)
- cout<<"\t"<<i->d_name<<"\t"<<DNSRecordContent::NumberToType(i->d_type)<<"\t'" << (i->d_content ? i->d_content->getZoneRepresentation() : "") <<"'\n";
+ cout<<"\t"<<i->d_name<<"\t"<<DNSRecordContent::NumberToType(i->d_type)<<"\t'" << (i->getContent() ? i->getContent()->getZoneRepresentation() : "") <<"'\n";
cout<<"\n";
cout<<"-\n";
rem.sin4.sin_port=0;
if(doServFailTree)
- root.submit(qname, header.rcode, pr.d_len, rem);
+ root.submit(qname, header.rcode, pr.d_len, false, rem);
}
if(!qd.d_qcount || qd.d_qcount == qd.d_answercount) {
perc=sum*100.0/totpairs;
if(j->first < 1024)
- cout<< perc <<"% of questions answered within " << j->first << " usec (";
+ cout<< perc <<"% of questions answered within " << j->first << " us (";
else
- cout<< perc <<"% of questions answered within " << j->first/1000.0 << " msec (";
+ cout<< perc <<"% of questions answered within " << j->first/1000.0 << " ms (";
cout<<perc-lastperc<<"%)\n";
lastperc=sum*100.0/totpairs;
if(!j->second) {
perc=sum*100.0/totpairs;
if(j->first < 1024)
- cout<< perc <<"% of questions answered within " << j->first << " usec (";
+ cout<< perc <<"% of questions answered within " << j->first << " us (";
else
- cout<< perc <<"% of questions answered within " << j->first/1000.0 << " msec (";
+ cout<< perc <<"% of questions answered within " << j->first/1000.0 << " ms (";
cout<<perc-lastperc<<"%)\n";
lastperc=sum*100.0/totpairs;
cout<< (totpairs-lastsum)<<" responses ("<<((totpairs-lastsum)*100.0/answers) <<"%) older than "<< (done.rbegin()->first/1000000.0) <<" seconds"<<endl;
if(totpairs)
- cout<<"Average non-late response time: "<<tottime/totpairs<<" usec"<<endl;
+ cout<<"Average non-late response time: "<<tottime/totpairs<<" us"<<endl;
if(!g_vm["load-stats"].as<string>().empty()) {
ofstream load(g_vm["load-stats"].as<string>().c_str());
if(verified) {
udiffVerify = dt.udiff() / 100;
- cout<<"Signature & verify ok, create "<<udiffCreate<<"usec, signature "<<udiffSign<<"usec, verify "<<udiffVerify<<"usec"<<endl;
+ cout<<"Signature & verify ok, create "<<udiffCreate<<"us, signature "<<udiffSign<<"us, verify "<<udiffVerify<<"us"<<endl;
}
else {
throw runtime_error("Verification of creator "+dckeCreate->getName()+" with signer "+dckeSign->getName()+" and verifier "+dckeVerify->getName()+" failed");
// zonemd: digest = hash( RR(1) | RR(2) | RR(3) | ... ), so skip RRSIG_RDATA
if (includeRRSIG_RDATA) {
- toHash.append(const_cast<RRSIGRecordContent&>(rrc).serialize(g_rootdnsname, true, true));
+ toHash.append(rrc.serialize(g_rootdnsname, true, true));
toHash.resize(toHash.size() - rrc.d_signature.length()); // chop off the end, don't sign the signature!
}
string nameToHash(qname.toDNSStringLC());
}
}
- for(const shared_ptr<DNSRecordContent>& add : signRecords) {
+ for (const shared_ptr<const DNSRecordContent>& add : signRecords) {
toHash.append(nameToHash);
uint16_t tmp=htons(rrc.d_type);
toHash.append((char*)&tmp, 2);
{
string toHash;
toHash.assign(qname.toDNSStringLC());
- toHash.append(const_cast<DNSKEYRecordContent&>(drc).serialize(DNSName(), true, true));
+ toHash.append(drc.serialize(DNSName(), true, true));
DSRecordContent dsrc;
try {
};
struct sharedDNSSECRecordCompare {
- bool operator() (const shared_ptr<DNSRecordContent>& a, const shared_ptr<DNSRecordContent>& b) const {
+ bool operator() (const shared_ptr<const DNSRecordContent>& a, const shared_ptr<const DNSRecordContent>& b) const {
return a->serialize(g_rootdnsname, true, true) < b->serialize(g_rootdnsname, true, true);
}
};
-typedef std::set<std::shared_ptr<DNSRecordContent>, sharedDNSSECRecordCompare> sortedRecords_t;
+typedef std::set<std::shared_ptr<const DNSRecordContent>, sharedDNSSECRecordCompare> sortedRecords_t;
string getMessageForRRSET(const DNSName& qname, const RRSIGRecordContent& rrc, const sortedRecords_t& signRecords, bool processRRSIGLabels = false, bool includeRRSIG_RDATA = true);
rr.auth=false;
rr.dr.d_place = signPlace;
for(RRSIGRecordContent& rrc : rrcs) {
- rr.dr.d_content = std::make_shared<RRSIGRecordContent>(rrc);
+ rr.dr.setContent(std::make_shared<RRSIGRecordContent>(rrc));
outsigned.push_back(rr);
}
}
{
stable_sort(rrs.begin(), rrs.end(), rrsigncomp);
- DNSName signQName, wildcardQName;
+ DNSName authQName, signQName, wildcardQName;
uint16_t signQType=0;
uint32_t signTTL=0;
uint32_t origTTL=0;
DNSName signer;
for(auto pos = rrs.cbegin(); pos != rrs.cend(); ++pos) {
if(pos != rrs.cbegin() && (signQType != pos->dr.d_type || signQName != pos->dr.d_name)) {
- if(getBestAuthFromSet(authSet, signQName, signer))
+ if (getBestAuthFromSet(authSet, authQName, signer))
addSignature(dk, db, signer, signQName, wildcardQName, signQType, signTTL, signPlace, toSign, signedRecords, origTTL);
}
signedRecords.push_back(*pos);
- signQName= pos->dr.d_name.makeLowerCase();
+ signQName = pos->dr.d_name.makeLowerCase();
+ if (pos->dr.d_type == QType::NSEC) {
+ authQName = signQName.getCommonLabels(getRR<NSECRecordContent>(pos->dr)->d_next);
+ }
+ else {
+ authQName = signQName;
+ }
if(!pos->wildcardname.empty())
wildcardQName = pos->wildcardname.makeLowerCase();
else
origTTL = pos->dr.d_ttl;
signPlace = pos->dr.d_place;
if(pos->auth || pos->dr.d_type == QType::DS) {
- toSign.insert(pos->dr.d_content); // so ponder.. should this be a deep copy perhaps?
+ toSign.insert(pos->dr.getContent()); // so ponder.. should this be a deep copy perhaps?
}
}
- if(getBestAuthFromSet(authSet, signQName, signer))
+ if (getBestAuthFromSet(authSet, authQName, signer))
addSignature(dk, db, signer, signQName, wildcardQName, signQType, signTTL, signPlace, toSign, signedRecords, origTTL);
rrs.swap(signedRecords);
}
if(g_verbose) {
cout<<"Sending queries to: "<<g_dest.toStringWithPort()<<endl;
cout<<"Attempting UDP first: " << (g_onlyTCP ? "no" : "yes") <<endl;
- cout<<"Timeout: "<< g_timeoutMsec<<"msec"<<endl;
+ cout<<"Timeout: "<< g_timeoutMsec<<" ms"<<endl;
cout << "Using TCP_NODELAY: "<<g_tcpNoDelay<<endl;
}
}
cout<<"Average qps: "<<mean(qps)<<", median qps: "<<median(qps)<<endl;
- cout<<"Average UDP latency: "<<mean(udpspeeds)<<"usec, median: "<<median(udpspeeds)<<"usec"<<endl;
- cout<<"Average TCP latency: "<<mean(tcpspeeds)<<"usec, median: "<<median(tcpspeeds)<<"usec"<<endl;
+ cout<<"Average UDP latency: "<<mean(udpspeeds)<<" us, median: "<<median(udpspeeds)<<" us"<<endl;
+ cout<<"Average TCP latency: "<<mean(tcpspeeds)<<" us, median: "<<median(tcpspeeds)<<" us"<<endl;
cout<<"OK: "<<g_OK<<", network errors: "<<g_networkErrors<<", other errors: "<<g_otherErrors<<endl;
cout<<"Timeouts: "<<g_timeOuts<<endl;
bool GssContext::supported() { return false; }
GssContext::GssContext() :
d_error(GSS_CONTEXT_UNSUPPORTED), d_type(GSS_CONTEXT_NONE) {}
-GssContext::GssContext(const DNSName& label) :
+GssContext::GssContext(const DNSName& /* label */) :
d_error(GSS_CONTEXT_UNSUPPORTED), d_type(GSS_CONTEXT_NONE) {}
-void GssContext::setLocalPrincipal(const std::string& name) {}
-bool GssContext::getLocalPrincipal(std::string& name) { return false; }
-void GssContext::setPeerPrincipal(const std::string& name) {}
-bool GssContext::getPeerPrincipal(std::string& name) { return false; }
-void GssContext::generateLabel(const std::string& suffix) {}
-void GssContext::setLabel(const DNSName& label) {}
-bool GssContext::init(const std::string& input, std::string& output) { return false; }
-bool GssContext::accept(const std::string& input, std::string& output) { return false; }
+void GssContext::setLocalPrincipal(const std::string& /* name */) {}
+bool GssContext::getLocalPrincipal(std::string& /* name */) { return false; }
+void GssContext::setPeerPrincipal(const std::string& /* name */) {}
+bool GssContext::getPeerPrincipal(std::string& /* name */) { return false; }
+void GssContext::generateLabel(const std::string& /* suffix */) {}
+void GssContext::setLabel(const DNSName& /* label */) {}
+bool GssContext::init(const std::string& /* input */, std::string& /* output */) { return false; }
+bool GssContext::accept(const std::string& /* input */, std::string& /* output */) { return false; }
bool GssContext::destroy() { return false; }
bool GssContext::expired() { return false; }
bool GssContext::valid() { return false; }
-bool GssContext::sign(const std::string& input, std::string& output) { return false; }
-bool GssContext::verify(const std::string& input, const std::string& signature) { return false; }
+bool GssContext::sign(const std::string& /* input */, std::string& /* output */) { return false; }
+bool GssContext::verify(const std::string& /* input */, const std::string& /* signature */) { return false; }
GssContextError GssContext::getError() { return GSS_CONTEXT_UNSUPPORTED; }
#else
setName(name);
};
+#ifdef ENABLE_GSS_TSIG
//! Parse name into native representation
bool setName(const std::string& name)
{
-#ifdef ENABLE_GSS_TSIG
gss_buffer_desc buffer;
d_name = GSS_C_NO_NAME;
}
return true;
-#endif
+ }
+#else
+ bool setName(const std::string& /* name */)
+ {
return false;
- };
+ }
+#endif
~GssName()
{
#endif
};
+#ifdef ENABLE_GSS_TSIG
//! Compare two Gss Names, if no gss support is compiled in, returns false always
//! This is not necessarily same as string comparison between two non-parsed names
bool operator==(const GssName& rhs)
{
-#ifdef ENABLE_GSS_TSIG
OM_uint32 maj, min;
int result;
maj = gss_compare_name(&min, d_name, rhs.d_name, &result);
return (maj == GSS_S_COMPLETE && result != 0);
-#endif
+ }
+#else
+ bool operator==(const GssName& /* rhs */)
+ {
return false;
}
+#endif
+#ifdef ENABLE_GSS_TSIG
//! Compare two Gss Names, if no gss support is compiled in, returns false always
//! This is not necessarily same as string comparison between two non-parsed names
bool match(const std::string& name)
{
-#ifdef ENABLE_GSS_TSIG
OM_uint32 maj, min;
int result;
gss_name_t comp;
maj = gss_compare_name(&min, d_name, comp, &result);
gss_release_name(&min, &comp);
return (maj == GSS_S_COMPLETE && result != 0);
+ }
#else
+ bool match(const std::string& /* name */)
+ {
return false;
+ }
#endif
- };
//! Check if GSS name was parsed successfully.
bool valid()
return ret;
}
-void setSocketIgnorePMTU(int sockfd, int family)
+void setSocketIgnorePMTU([[maybe_unused]] int sockfd, [[maybe_unused]] int family)
{
if (family == AF_INET) {
#if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT)
#include "tsigverifier.hh"
vector<pair<vector<DNSRecord>, vector<DNSRecord> > > processIXFRRecords(const ComboAddress& primary, const DNSName& zone,
- const vector<DNSRecord>& records, const std::shared_ptr<SOARecordContent>& primarySOA)
+ const vector<DNSRecord>& records, const std::shared_ptr<const SOARecordContent>& primarySOA)
{
vector<pair<vector<DNSRecord>, vector<DNSRecord> > > ret;
pw.getHeader()->rd=0;
pw.getHeader()->id=dns_random_uint16();
pw.startRecord(zone, QType::SOA, 0, QClass::IN, DNSResourceRecord::AUTHORITY);
- oursr.d_content->toPacket(pw);
+ oursr.getContent()->toPacket(pw);
pw.commit();
TSIGRecordContent trc;
// SOA WHERE THIS DELTA GOES
// RECORDS TO ADD
// CURRENT PRIMARY SOA
- std::shared_ptr<SOARecordContent> primarySOA = nullptr;
+ std::shared_ptr<const SOARecordContent> primarySOA = nullptr;
vector<DNSRecord> records;
size_t receivedBytes = 0;
std::string reply;
throw std::runtime_error("Error getting the content of the first SOA record of the IXFR answer for zone '"+zone.toLogString()+"' from primary '"+primary.toStringWithPort()+"'");
}
- if(sr->d_st.serial == std::dynamic_pointer_cast<SOARecordContent>(oursr.d_content)->d_st.serial) {
+ if(sr->d_st.serial == getRR<SOARecordContent>(oursr)->d_st.serial) {
// we are up to date
return ret;
}
const ComboAddress* laddr=0, size_t maxReceivedBytes=0);
vector<pair<vector<DNSRecord>, vector<DNSRecord>>> processIXFRRecords(const ComboAddress& primary, const DNSName& zone,
- const vector<DNSRecord>& records, const std::shared_ptr<SOARecordContent>& primarySOA);
+ const vector<DNSRecord>& records, const std::shared_ptr<const SOARecordContent>& primarySOA);
} // namespace YAML
struct ixfrdiff_t {
- shared_ptr<SOARecordContent> oldSOA;
- shared_ptr<SOARecordContent> newSOA;
+ shared_ptr<const SOARecordContent> oldSOA;
+ shared_ptr<const SOARecordContent> newSOA;
vector<DNSRecord> removals;
vector<DNSRecord> additions;
uint32_t oldSOATTL;
};
struct ixfrinfo_t {
- shared_ptr<SOARecordContent> soa; // The SOA of the latest AXFR
+ shared_ptr<const SOARecordContent> soa; // The SOA of the latest AXFR
records_t latestAXFR; // The most recent AXFR
vector<std::shared_ptr<ixfrdiff_t>> ixfrDiffs;
uint32_t soaTTL;
}
}
-static void getSOAFromRecords(const records_t& records, shared_ptr<SOARecordContent>& soa, uint32_t& soaTTL) {
+static void getSOAFromRecords(const records_t& records, shared_ptr<const SOARecordContent>& soa, uint32_t& soaTTL) {
for (const auto& dnsrecord : records) {
if (dnsrecord.d_type == QType::SOA) {
soa = getRR<SOARecordContent>(dnsrecord);
throw PDNSException("No SOA in supplied records");
}
-static void makeIXFRDiff(const records_t& from, const records_t& to, std::shared_ptr<ixfrdiff_t>& diff, const shared_ptr<SOARecordContent>& fromSOA = nullptr, uint32_t fromSOATTL=0, const shared_ptr<SOARecordContent>& toSOA = nullptr, uint32_t toSOATTL = 0) {
+static void makeIXFRDiff(const records_t& from, const records_t& to, std::shared_ptr<ixfrdiff_t>& diff, const shared_ptr<const SOARecordContent>& fromSOA = nullptr, uint32_t fromSOATTL=0, const shared_ptr<const SOARecordContent>& toSOA = nullptr, uint32_t toSOATTL = 0) {
set_difference(from.cbegin(), from.cend(), to.cbegin(), to.cend(), back_inserter(diff->removals), from.value_comp());
set_difference(to.cbegin(), to.cend(), from.cbegin(), from.cend(), back_inserter(diff->additions), from.value_comp());
diff->oldSOA = fromSOA;
try {
g_log<<Logger::Info<<"Trying to initially load domain "<<domain<<" from disk"<<endl;
auto serial = getSerialFromDir(dir);
- shared_ptr<SOARecordContent> soa;
+ shared_ptr<const SOARecordContent> soa;
uint32_t soaTTL;
{
string fname = workdir + "/" + domain.toString() + "/" + std::to_string(serial);
}
DNSName domain = domainConfig.first;
- shared_ptr<SOARecordContent> current_soa;
+ shared_ptr<const SOARecordContent> current_soa;
const auto& zoneInfo = getCurrentZoneInfo(domain);
if (zoneInfo != nullptr) {
current_soa = zoneInfo->soa;
string dir = workdir + "/" + domain.toString();
g_log<<Logger::Info<<"Attempting to retrieve SOA Serial update for '"<<domain<<"' from '"<<master.toStringWithPort()<<"'"<<endl;
- shared_ptr<SOARecordContent> sr;
+ shared_ptr<const SOARecordContent> sr;
try {
zoneLastCheck = now;
g_stats.incrementSOAChecks(domain);
TSIGTriplet tt;
// The *new* SOA
- shared_ptr<SOARecordContent> soa;
+ shared_ptr<const SOARecordContent> soa;
uint32_t soaTTL = 0;
records_t records;
try {
return true;
}
-static vector<uint8_t> getSOAPacket(const MOADNSParser& mdp, const shared_ptr<SOARecordContent>& soa, uint32_t soaTTL) {
+static vector<uint8_t> getSOAPacket(const MOADNSParser& mdp, const shared_ptr<const SOARecordContent>& soa, uint32_t soaTTL) {
vector<uint8_t> packet;
DNSPacketWriter pw(packet, mdp.d_qname, mdp.d_qtype);
pw.getHeader()->id = mdp.d_header.id;
static bool addRecordToWriter(DNSPacketWriter& pw, const DNSName& zoneName, const DNSRecord& record, bool compress)
{
pw.startRecord(record.d_name + zoneName, record.d_type, record.d_ttl, QClass::IN, DNSResourceRecord::ANSWER, compress);
- record.d_content->toPacket(pw);
+ record.getContent()->toPacket(pw);
if (pw.size() > 16384) {
pw.rollback();
return false;
return false;
}
- shared_ptr<SOARecordContent> soa = zoneInfo->soa;
+ shared_ptr<const SOARecordContent> soa = zoneInfo->soa;
uint32_t soaTTL = zoneInfo->soaTTL;
const records_t& records = zoneInfo->latestAXFR;
/* Produces an IXFR if one can be made according to the rules in RFC 1995 and
* creates a SOA or AXFR packet when required by the RFC.
*/
-static bool handleIXFR(int fd, const MOADNSParser& mdp, const shared_ptr<SOARecordContent>& clientSOA) {
+static bool handleIXFR(int fd, const MOADNSParser& mdp, const shared_ptr<const SOARecordContent>& clientSOA) {
vector<std::shared_ptr<ixfrdiff_t>> toSend;
/* we get a shared pointer of the zone info that we can't modify, ever.
* query, but with the query type being IXFR and the authority section
* containing the SOA record of client's version of the zone.
*/
- shared_ptr<SOARecordContent> clientSOA;
+ shared_ptr<const SOARecordContent> clientSOA;
for (auto &answer : mdp.d_answers) {
// from dnsparser.hh:
// typedef vector<pair<DNSRecord, uint16_t > > answers_t;
#include "zoneparser-tng.hh"
#include "dnsparser.hh"
-uint32_t getSerialFromMaster(const ComboAddress& master, const DNSName& zone, shared_ptr<SOARecordContent>& sr, const TSIGTriplet& tt, const uint16_t timeout)
+uint32_t getSerialFromMaster(const ComboAddress& master, const DNSName& zone, shared_ptr<const SOARecordContent>& sr, const TSIGTriplet& tt, const uint16_t timeout)
{
vector<uint8_t> packet;
DNSPacketWriter pw(packet, zone, QType::SOA);
auto found = records.equal_range(std::tie(g_rootdnsname, t));
for(auto iter = found.first; iter != found.second; ++iter) {
- auto soa = std::dynamic_pointer_cast<SOARecordContent>(iter->d_content);
+ auto soa = getRR<SOARecordContent>(*iter);
if (soa) {
soaret = *iter;
return soa->d_st.serial;
r.d_name.isRoot() ? "@" : r.d_name.toStringNoDot().c_str(),
r.d_ttl,
DNSRecordContent::NumberToType(r.d_type).c_str(),
- r.d_content->getZoneRepresentation().c_str()) < 0) {
+ r.getContent()->getZoneRepresentation().c_str()) < 0) {
throw runtime_error(stringerror());
}
}
* Load the zone `zone` from `fname` and put the first found SOA into `soa`
* Does NOT check for nullptr
*/
-void loadSOAFromDisk(const DNSName& zone, const string& fname, shared_ptr<SOARecordContent>& soa, uint32_t& soaTTL)
+void loadSOAFromDisk(const DNSName& zone, const string& fname, shared_ptr<const SOARecordContent>& soa, uint32_t& soaTTL)
{
ZoneParserTNG zpt(fname, zone);
zpt.disableGenerate();
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/key_extractors.hpp>
#include <boost/multi_index/ordered_index.hpp>
+#include <boost/multi_index/mem_fun.hpp>
#include "dnsparser.hh"
#include "dnsrecords.hh"
struct CIContentCompareStruct
{
- bool operator()(const shared_ptr<DNSRecordContent>&a, const shared_ptr<DNSRecordContent>& b) const
+ bool operator()(const shared_ptr<const DNSRecordContent>&a, const shared_ptr<const DNSRecordContent>& b) const
{
return toLower(a->getZoneRepresentation()) < toLower(b->getZoneRepresentation());
}
member<DNSRecord, DNSName, &DNSRecord::d_name>,
member<DNSRecord, uint16_t, &DNSRecord::d_type>,
member<DNSRecord, uint16_t, &DNSRecord::d_class>,
- member<DNSRecord, shared_ptr<DNSRecordContent>, &DNSRecord::d_content> >,
+ BOOST_MULTI_INDEX_CONST_MEM_FUN(DNSRecord, const shared_ptr<const DNSRecordContent>&, getContent) >,
composite_key_compare<CanonDNSNameCompare, std::less<uint16_t>, std::less<uint16_t>, CIContentCompareStruct >
> /* ordered_non_uniquw */
> /* indexed_by */
> /* multi_index_container */ records_t;
-uint32_t getSerialFromMaster(const ComboAddress& master, const DNSName& zone, shared_ptr<SOARecordContent>& sr, const TSIGTriplet& tt = TSIGTriplet(), const uint16_t timeout = 2);
+uint32_t getSerialFromMaster(const ComboAddress& master, const DNSName& zone, shared_ptr<const SOARecordContent>& sr, const TSIGTriplet& tt = TSIGTriplet(), const uint16_t timeout = 2);
uint32_t getSerialFromDir(const std::string& dir);
uint32_t getSerialFromRecords(const records_t& records, DNSRecord& soaret);
void writeZoneToDisk(const records_t& records, const DNSName& zone, const std::string& directory);
void loadZoneFromDisk(records_t& records, const string& fname, const DNSName& zone);
-void loadSOAFromDisk(const DNSName& zone, const string& fname, shared_ptr<SOARecordContent>& soa, uint32_t& soaTTL);
+void loadSOAFromDisk(const DNSName& zone, const string& fname, shared_ptr<const SOARecordContent>& soa, uint32_t& soaTTL);
set_difference(before.cbegin(), before.cend(), after.cbegin(), after.cend(), back_inserter(diff), before.value_comp());
for(const auto& d : diff) {
- cout<<'-'<< (d.d_name+zone) <<" IN "<<DNSRecordContent::NumberToType(d.d_type)<<" "<<d.d_content->getZoneRepresentation()<<endl;
+ cout<<'-'<< (d.d_name+zone) <<" IN "<<DNSRecordContent::NumberToType(d.d_type)<<" "<<d.getContent()->getZoneRepresentation()<<endl;
}
diff.clear();
set_difference(after.cbegin(), after.cend(), before.cbegin(), before.cend(), back_inserter(diff), before.value_comp());
for(const auto& d : diff) {
- cout<<'+'<< (d.d_name+zone) <<" IN "<<DNSRecordContent::NumberToType(d.d_type)<<" "<<d.d_content->getZoneRepresentation()<<endl;
+ cout<<'+'<< (d.d_name+zone) <<" IN "<<DNSRecordContent::NumberToType(d.d_type)<<" "<<d.getContent()->getZoneRepresentation()<<endl;
}
exit(1);
}
cout<<"Checking for update, our serial number is "<<ourSerial<<".. ";
cout.flush();
- shared_ptr<SOARecordContent> sr;
+ shared_ptr<const SOARecordContent> sr;
uint32_t serial = getSerialFromMaster(master, zone, sr, tt);
if(ourSerial == serial) {
time_t sleepTime = sr ? sr->d_st.refresh : 60;
uint32_t newserial=0;
for(const auto& rr : add) {
if(rr.d_type == QType::SOA) {
- newserial=std::dynamic_pointer_cast<SOARecordContent>(rr.d_content)->d_st.serial;
+ newserial=getRR<SOARecordContent>(rr)->d_st.serial;
}
}
bool stop=false;
for(const auto& rr : remove) {
- report<<'-'<< (rr.d_name+zone) <<" IN "<<DNSRecordContent::NumberToType(rr.d_type)<<" "<<rr.d_content->getZoneRepresentation()<<endl;
- auto range = records.equal_range(std::tie(rr.d_name, rr.d_type, rr.d_class, rr.d_content));
+ report<<'-'<< (rr.d_name+zone) <<" IN "<<DNSRecordContent::NumberToType(rr.d_type)<<" "<<rr.getContent()->getZoneRepresentation()<<endl;
+ auto range = records.equal_range(std::tie(rr.d_name, rr.d_type, rr.d_class, rr.getContent()));
if(range.first == range.second) {
cout<<endl<<" !! Could not find record "<<rr.d_name<<" to remove!!"<<endl;
// stop=true;
}
for(const auto& rr : add) {
- report<<'+'<< (rr.d_name+zone) <<" IN "<<DNSRecordContent::NumberToType(rr.d_type)<<" "<<rr.d_content->getZoneRepresentation()<<endl;
+ report<<'+'<< (rr.d_name+zone) <<" IN "<<DNSRecordContent::NumberToType(rr.d_type)<<" "<<rr.getContent()->getZoneRepresentation()<<endl;
records.insert(rr);
}
if(stop) {
}
#if OPENSSL_VERSION_MAJOR >= 3
-int libssl_ticket_key_callback(SSL* s, OpenSSLTLSTicketKeysRing& keyring, unsigned char keyName[TLS_TICKETS_KEY_NAME_SIZE], unsigned char* iv, EVP_CIPHER_CTX* ectx, EVP_MAC_CTX* hctx, int enc)
+int libssl_ticket_key_callback(SSL* /* s */, OpenSSLTLSTicketKeysRing& keyring, unsigned char keyName[TLS_TICKETS_KEY_NAME_SIZE], unsigned char* iv, EVP_CIPHER_CTX* ectx, EVP_MAC_CTX* hctx, int enc)
#else
-int libssl_ticket_key_callback(SSL* s, OpenSSLTLSTicketKeysRing& keyring, unsigned char keyName[TLS_TICKETS_KEY_NAME_SIZE], unsigned char* iv, EVP_CIPHER_CTX* ectx, HMAC_CTX* hctx, int enc)
+int libssl_ticket_key_callback(SSL* /* s */, OpenSSLTLSTicketKeysRing& keyring, unsigned char keyName[TLS_TICKETS_KEY_NAME_SIZE], unsigned char* iv, EVP_CIPHER_CTX* ectx, HMAC_CTX* hctx, int enc)
#endif
{
if (enc != 0) {
return SSL_TLSEXT_ERR_NOACK;
}
-static void libssl_info_callback(const SSL *ssl, int where, int ret)
+static void libssl_info_callback(const SSL *ssl, int where, int /* ret */)
{
SSL_CTX* sslCtx = SSL_get_SSL_CTX(ssl);
if (sslCtx == nullptr) {
file.close();
}
-void OpenSSLTLSTicketKeysRing::rotateTicketsKey(time_t now)
+void OpenSSLTLSTicketKeysRing::rotateTicketsKey(time_t /* now */)
{
auto newKey = std::make_shared<OpenSSLTLSTicketKey>();
addKey(newKey);
d_lw->registerFunction("match", (bool (NetmaskGroup::*)(const ComboAddress&) const)&NetmaskGroup::match);
// DNSRecord
- d_lw->writeFunction("newDR", [](const DNSName &name, const std::string &type, unsigned int ttl, const std::string &content, int place){ QType qtype; qtype = type; auto dr = DNSRecord(); dr.d_name = name; dr.d_type = qtype.getCode(); dr.d_ttl = ttl; dr.d_content = shared_ptr<DNSRecordContent>(DNSRecordContent::mastermake(dr.d_type, QClass::IN, content)); dr.d_place = static_cast<DNSResourceRecord::Place>(place); return dr; });
+ d_lw->writeFunction("newDR", [](const DNSName &name, const std::string &type, unsigned int ttl, const std::string &content, int place){ QType qtype; qtype = type; auto dr = DNSRecord(); dr.d_name = name; dr.d_type = qtype.getCode(); dr.d_ttl = ttl; dr.setContent(shared_ptr<DNSRecordContent>(DNSRecordContent::mastermake(dr.d_type, QClass::IN, content))); dr.d_place = static_cast<DNSResourceRecord::Place>(place); return dr; });
d_lw->registerMember("name", &DNSRecord::d_name);
d_lw->registerMember("type", &DNSRecord::d_type);
d_lw->registerMember("ttl", &DNSRecord::d_ttl);
d_lw->registerMember("place", &DNSRecord::d_place);
- d_lw->registerFunction<string(DNSRecord::*)()>("getContent", [](const DNSRecord& dr) { return dr.d_content->getZoneRepresentation(); });
+ d_lw->registerFunction<string(DNSRecord::*)()>("getContent", [](const DNSRecord& dr) { return dr.getContent()->getZoneRepresentation(); });
d_lw->registerFunction<boost::optional<ComboAddress>(DNSRecord::*)()>("getCA", [](const DNSRecord& dr) {
boost::optional<ComboAddress> ret;
- if(auto arec = std::dynamic_pointer_cast<ARecordContent>(dr.d_content))
+ if(auto arec = getRR<ARecordContent>(dr))
ret=arec->getCA(53);
- else if(auto aaaarec = std::dynamic_pointer_cast<AAAARecordContent>(dr.d_content))
+ else if(auto aaaarec = getRR<AAAARecordContent>(dr))
ret=aaaarec->getCA(53);
return ret;
});
- d_lw->registerFunction<void(DNSRecord::*)(const std::string&)>("changeContent", [](DNSRecord& dr, const std::string& newContent) { dr.d_content = shared_ptr<DNSRecordContent>(DNSRecordContent::mastermake(dr.d_type, 1, newContent)); });
+ d_lw->registerFunction<void(DNSRecord::*)(const std::string&)>("changeContent", [](DNSRecord& dr, const std::string& newContent) { dr.setContent(shared_ptr<DNSRecordContent>(DNSRecordContent::mastermake(dr.d_type, 1, newContent))); });
// pdnsload
d_lw->writeFunction("pdnslog", [](const std::string& msg, boost::optional<int> loglevel) {
}
}
-
static std::string getGeo(const std::string& ip, GeoIPInterface::GeoIPQueryAttribute qa)
{
static bool initialized;
return result;
}
-static vector<ComboAddress> convComboAddressList(const iplist_t& items)
+static vector<ComboAddress> convComboAddressList(const iplist_t& items, uint16_t port=0)
{
vector<ComboAddress> result;
result.reserve(items.size());
for(const auto& item : items) {
- result.emplace_back(ComboAddress(item.second));
+ result.emplace_back(ComboAddress(item.second, port));
}
return result;
}
+/**
+ * Reads and unify single or multiple sets of ips :
+ * - {'192.0.2.1', '192.0.2.2'}
+ * - {{'192.0.2.1', '192.0.2.2'}, {'198.51.100.1'}}
+ */
+
+static vector<vector<ComboAddress>> convMultiComboAddressList(const boost::variant<iplist_t, ipunitlist_t>& items, uint16_t port = 0)
+{
+ vector<vector<ComboAddress>> candidates;
+
+ if(auto simple = boost::get<iplist_t>(&items)) {
+ vector<ComboAddress> unit = convComboAddressList(*simple, port);
+ candidates.push_back(unit);
+ } else {
+ auto units = boost::get<ipunitlist_t>(items);
+ for(const auto& u : units) {
+ vector<ComboAddress> unit = convComboAddressList(u.second, port);
+ candidates.push_back(unit);
+ }
+ }
+ return candidates;
+}
+
static vector<string> convStringList(const iplist_t& items)
{
vector<string> result;
static thread_local unique_ptr<lua_record_ctx_t> s_lua_record_ctx;
+static vector<string> genericIfUp(const boost::variant<iplist_t, ipunitlist_t>& ips, boost::optional<opts_t> options, std::function<bool(const ComboAddress&, const opts_t&)> upcheckf, uint16_t port = 0) {
+ vector<vector<ComboAddress> > candidates;
+ opts_t opts;
+ if(options)
+ opts = *options;
+
+ candidates = convMultiComboAddressList(ips, port);
+
+ for(const auto& unit : candidates) {
+ vector<ComboAddress> available;
+ for(const auto& c : unit) {
+ if (upcheckf(c, opts)) {
+ available.push_back(c);
+ }
+ }
+ if(!available.empty()) {
+ vector<ComboAddress> res = useSelector(getOptionValue(options, "selector", "random"), s_lua_record_ctx->bestwho, available);
+ return convComboAddressListToString(res);
+ }
+ }
+
+ // All units down, apply backupSelector on all candidates
+ vector<ComboAddress> ret{};
+ for(const auto& unit : candidates) {
+ ret.insert(ret.end(), unit.begin(), unit.end());
+ }
+
+ vector<ComboAddress> res = useSelector(getOptionValue(options, "backupSelector", "random"), s_lua_record_ctx->bestwho, ret);
+ return convComboAddressListToString(res);
+}
+
static void setupLuaRecords(LuaContext& lua)
{
lua.writeFunction("latlon", []() {
*
* @example ifportup(443, { '1.2.3.4', '5.4.3.2' })"
*/
- lua.writeFunction("ifportup", [](int port, const vector<pair<int, string> >& ips, const boost::optional<std::unordered_map<string,string>> options) {
- vector<ComboAddress> candidates, unavailables;
- opts_t opts;
- vector<ComboAddress > conv;
- std::string selector;
-
- if(options)
- opts = *options;
- for(const auto& i : ips) {
- ComboAddress rem(i.second, port);
- if(g_up.isUp(rem, opts)) {
- candidates.push_back(rem);
- }
- else {
- unavailables.push_back(rem);
- }
+ lua.writeFunction("ifportup", [](int port, const boost::variant<iplist_t, ipunitlist_t>& ips, const boost::optional<std::unordered_map<string,string>> options) {
+ if (port < 0) {
+ port = 0;
}
- if(!candidates.empty()) {
- // use regular selector
- selector = getOptionValue(options, "selector", "random");
- } else {
- // All units are down, apply backupSelector on all candidates
- candidates = std::move(unavailables);
- selector = getOptionValue(options, "backupSelector", "random");
+ if (port > std::numeric_limits<uint16_t>::max()) {
+ port = std::numeric_limits<uint16_t>::max();
}
- vector<ComboAddress> res = useSelector(selector, s_lua_record_ctx->bestwho, candidates);
- return convComboAddressListToString(res);
+ auto checker = [](const ComboAddress& addr, const opts_t& opts) {
+ return g_up.isUp(addr, opts);
+ };
+ return genericIfUp(ips, options, checker, port);
});
lua.writeFunction("ifurlextup", [](const vector<pair<int, opts_t> >& ipurls, boost::optional<opts_t> options) {
lua.writeFunction("ifurlup", [](const std::string& url,
const boost::variant<iplist_t, ipunitlist_t>& ips,
boost::optional<opts_t> options) {
- vector<vector<ComboAddress> > candidates;
- opts_t opts;
- if(options)
- opts = *options;
- if(auto simple = boost::get<iplist_t>(&ips)) {
- vector<ComboAddress> unit = convComboAddressList(*simple);
- candidates.push_back(unit);
- } else {
- auto units = boost::get<ipunitlist_t>(ips);
- for(const auto& u : units) {
- vector<ComboAddress> unit = convComboAddressList(u.second);
- candidates.push_back(unit);
- }
- }
- for(const auto& unit : candidates) {
- vector<ComboAddress> available;
- for(const auto& c : unit) {
- if(g_up.isUp(c, url, opts)) {
- available.push_back(c);
- }
- }
- if(!available.empty()) {
- vector<ComboAddress> res = useSelector(getOptionValue(options, "selector", "random"), s_lua_record_ctx->bestwho, available);
- return convComboAddressListToString(res);
- }
- }
-
- // All units down, apply backupSelector on all candidates
- vector<ComboAddress> ret{};
- for(const auto& unit : candidates) {
- ret.insert(ret.end(), unit.begin(), unit.end());
- }
-
- vector<ComboAddress> res = useSelector(getOptionValue(options, "backupSelector", "random"), s_lua_record_ctx->bestwho, ret);
- return convComboAddressListToString(res);
+ auto checker = [&url](const ComboAddress& addr, const opts_t& opts) {
+ return g_up.isUp(addr, url, opts);
+ };
+ return genericIfUp(ips, options, checker);
});
/*
* Returns a random IP address from the supplied list
void CommunicatorClass::notify(const DNSName &domain, const string &ip)
{
d_nq.add(domain, ip);
- d_any_sem.post();
}
return url.substr(pos, endpos-pos);
}
-void MiniCurl::setupURL(const std::string& str, const ComboAddress* rem, const ComboAddress* src, int timeout, size_t byteslimit, bool fastopen, bool verify)
+void MiniCurl::setupURL(const std::string& str, const ComboAddress* rem, const ComboAddress* src, int timeout, size_t byteslimit, [[maybe_unused]] bool fastopen, bool verify)
{
if (!d_fresh) {
curl_easy_reset(getCURLPtr(d_curl));
d_data.clear();
}
-std::string MiniCurl::getURL(const std::string& str, const ComboAddress* rem, const ComboAddress* src, int timeout, bool fastopen, bool verify, size_t byteslimit)
+std::string MiniCurl::getURL(const std::string& str, const ComboAddress* rem, const ComboAddress* src, int timeout, [[maybe_unused]] bool fastopen, bool verify, size_t byteslimit)
{
setupURL(str, rem, src, timeout, byteslimit, fastopen, verify);
auto res = curl_easy_perform(getCURLPtr(d_curl));
return flags & O_NONBLOCK;
}
-bool setReceiveSocketErrors(int sock, int af)
+bool setReceiveSocketErrors([[maybe_unused]] int sock, [[maybe_unused]] int af)
{
#ifdef __linux__
int tmp = 1, ret;
return foundMAC ? 0 : ENOENT;
}
#else
-int getMACAddress(const ComboAddress& ca, char* dest, size_t len)
+int getMACAddress(const ComboAddress& /* ca */, char* /* dest */, size_t /* len */)
{
return ENOENT;
}
return ret;
}
-uint64_t udpErrorStats(const std::string& str)
+uint64_t udpErrorStats([[maybe_unused]] const std::string& str)
{
#ifdef __linux__
ifstream ifs("/proc/net/snmp");
return 0;
}
-uint64_t udp6ErrorStats(const std::string& str)
+uint64_t udp6ErrorStats([[maybe_unused]] const std::string& str)
{
#ifdef __linux__
const std::map<std::string, std::string> keys = {
#endif
}
-int mapThreadToCPUList(pthread_t tid, const std::set<int>& cpus)
+int mapThreadToCPUList([[maybe_unused]] pthread_t tid, [[maybe_unused]] const std::set<int>& cpus)
{
#ifdef HAVE_PTHREAD_SETAFFINITY_NP
# ifdef __NetBSD__
return results;
}
-size_t getPipeBufferSize(int fd)
+size_t getPipeBufferSize([[maybe_unused]] int fd)
{
#ifdef F_GETPIPE_SZ
int res = fcntl(fd, F_GETPIPE_SZ);
#endif /* F_GETPIPE_SZ */
}
-bool setPipeBufferSize(int fd, size_t size)
+bool setPipeBufferSize([[maybe_unused]] int fd, [[maybe_unused]] size_t size)
{
#ifdef F_SETPIPE_SZ
if (size > static_cast<size_t>(std::numeric_limits<int>::max())) {
{
// cerr<<"got nsec3 ["<<i->first.d_name<<"]"<<endl;
// cerr<<i->first.d_content->getZoneRepresentation()<<endl;
- const auto r = std::dynamic_pointer_cast<NSEC3RecordContent>(i->first.d_content);
+ const auto r = getRR<NSEC3RecordContent>(i->first);
if (!r) {
continue;
}
if(i->first.d_type == QType::CNAME)
{
- namesseen.insert(DNSName(i->first.d_content->getZoneRepresentation()));
+ namesseen.insert(DNSName(i->first.getContent()->getZoneRepresentation()));
}
cout << i->first.d_place - 1 << "\t" << i->first.d_name.toString() << "\t" << i->first.d_ttl << "\tIN\t" << DNSRecordContent::NumberToType(i->first.d_type);
- cout << "\t" << i->first.d_content->getZoneRepresentation() << "\n";
+ cout << "\t" << i->first.getContent()->getZoneRepresentation() << "\n";
}
#if 0
string tmp;
};
-void NSECBitmap::toPacket(DNSPacketWriter& pw)
+void NSECBitmap::toPacket(DNSPacketWriter& pw) const
{
NSECBitmapGenerator nbg(pw);
if (d_bitset) {
}
}
-void NSECRecordContent::toPacket(DNSPacketWriter& pw)
+void NSECRecordContent::toPacket(DNSPacketWriter& pw) const
{
pw.xfrName(d_next);
d_bitmap.toPacket(pw);
}
}
-void NSEC3RecordContent::toPacket(DNSPacketWriter& pw)
+void NSEC3RecordContent::toPacket(DNSPacketWriter& pw) const
{
pw.xfr8BitInt(d_algorithm);
pw.xfr8BitInt(d_flags);
rtr.xfrHexBlob(d_salt);
}
-void NSEC3PARAMRecordContent::toPacket(DNSPacketWriter& pw)
+void NSEC3PARAMRecordContent::toPacket(DNSPacketWriter& pw) const
{
pw.xfr8BitInt(d_algorithm);
pw.xfr8BitInt(d_flags);
}
}
-void CSYNCRecordContent::toPacket(DNSPacketWriter& pw)
+void CSYNCRecordContent::toPacket(DNSPacketWriter& pw) const
{
pw.xfr32BitInt(d_serial);
pw.xfr16BitInt(d_flags);
return (int)d_len << 3;
}
-bool OpenSSLEDDSADNSCryptoKeyEngine::checkKey(std::optional<std::reference_wrapper<std::vector<std::string>>> errorMessages) const
+bool OpenSSLEDDSADNSCryptoKeyEngine::checkKey([[maybe_unused]] std::optional<std::reference_wrapper<std::vector<std::string>>> errorMessages) const
{
#if OPENSSL_VERSION_MAJOR >= 3
auto ctx = KeyContext{EVP_PKEY_CTX_new_from_pkey(nullptr, d_edkey.get(), nullptr), EVP_PKEY_CTX_free};
rr.auth=true;
if (publishCDNSKEY == "0") { // delete DS via CDNSKEY
- rr.dr.d_content=s_deleteCDNSKEYContent;
+ rr.dr.setContent(s_deleteCDNSKEYContent);
r->addRecord(std::move(rr));
return true;
}
if (!value.second.published) {
continue;
}
- rr.dr.d_content=std::make_shared<DNSKEYRecordContent>(value.first.getDNSKEY());
+ rr.dr.setContent(std::make_shared<DNSKEYRecordContent>(value.first.getDNSKEY()));
r->addRecord(DNSZoneRecord(rr));
haveOne=true;
}
rr.dr.d_type=QType::DNSKEY;
rr.dr.d_ttl=d_sd.minimum;
rr.dr.d_name=p.qdomain;
- rr.dr.d_content=std::make_shared<DNSKEYRecordContent>(value.first.getDNSKEY());
+ rr.dr.setContent(std::make_shared<DNSKEYRecordContent>(value.first.getDNSKEY()));
rr.auth=true;
r->addRecord(std::move(rr));
haveOne=true;
rr.auth=true;
if(std::find(digestAlgos.begin(), digestAlgos.end(), "0") != digestAlgos.end()) { // delete DS via CDS
- rr.dr.d_content=s_deleteCDSContent;
+ rr.dr.setContent(s_deleteCDSContent);
r->addRecord(std::move(rr));
return true;
}
continue;
}
for(auto const &digestAlgo : digestAlgos){
- rr.dr.d_content=std::make_shared<DSRecordContent>(makeDSFromDNSKey(p.qdomain, value.first.getDNSKEY(), pdns::checked_stoi<uint8_t>(digestAlgo)));
+ rr.dr.setContent(std::make_shared<DSRecordContent>(makeDSFromDNSKey(p.qdomain, value.first.getDNSKEY(), pdns::checked_stoi<uint8_t>(digestAlgo))));
r->addRecord(DNSZoneRecord(rr));
haveOne=true;
}
rr.dr.d_ttl=d_sd.minimum;
rr.dr.d_name=p.qdomain;
ns3prc.d_flags = 0; // the NSEC3PARAM 'flag' is defined to always be zero in RFC5155.
- rr.dr.d_content=std::make_shared<NSEC3PARAMRecordContent>(ns3prc);
+ rr.dr.setContent(std::make_shared<NSEC3PARAMRecordContent>(ns3prc));
rr.auth = true;
r->addRecord(std::move(rr));
return true;
}
else
content=mode;
- rr.dr.d_content = DNSRecordContent::mastermake(QType::TXT, 1, "\""+content+"\"");
+ rr.dr.setContent(DNSRecordContent::mastermake(QType::TXT, 1, "\""+content+"\""));
}
else if (target==idserver) {
// modes: disabled, hostname or custom
if(!tid.empty() && tid[0]!='"') { // see #6010 however
tid = "\"" + tid + "\"";
}
- rr.dr.d_content=DNSRecordContent::mastermake(QType::TXT, 1, tid);
+ rr.dr.setContent(DNSRecordContent::mastermake(QType::TXT, 1, tid));
}
else {
r->setRcode(RCode::Refused);
ret.push_back(rr); // put in the original
rr.dr.d_type = QType::CNAME;
rr.dr.d_name = prefix + rr.dr.d_name;
- rr.dr.d_content = std::make_shared<CNAMERecordContent>(CNAMERecordContent(prefix + getRR<DNAMERecordContent>(rr.dr)->getTarget()));
+ rr.dr.setContent(std::make_shared<CNAMERecordContent>(CNAMERecordContent(prefix + getRR<DNAMERecordContent>(rr.dr)->getTarget())));
rr.auth = false; // don't sign CNAME
target = getRR<CNAMERecordContent>(rr.dr)->getTarget();
ret.push_back(rr);
DLOG(g_log<<"Executing Lua: '"<<rec->getCode()<<"'"<<endl);
try {
auto recvec=luaSynth(rec->getCode(), target, d_sd.qname, d_sd.domain_id, p, rec->d_type, s_LUA);
- for(const auto& r : recvec) {
+ for (const auto& r : recvec) {
rr.dr.d_type = rec->d_type; // might be CNAME
- rr.dr.d_content = r;
+ rr.dr.setContent(r);
rr.scopeMask = p.getRealRemote().getBits(); // this makes sure answer is a specific as your question
ret->push_back(rr);
}
DNSName target = rrc->getTarget().isRoot() ? rec->dr.d_name : rrc->getTarget();
if (rrc->hasParam(SvcParam::ipv4hint) && rrc->autoHint(SvcParam::ipv4hint)) {
+ auto newRRC = rrc->clone();
+ if (!newRRC) {
+ continue;
+ }
if (s_SVCAutohints) {
auto hints = getIPAddressFor(target, QType::A);
if (hints.size() == 0) {
- rrc->removeParam(SvcParam::ipv4hint);
+ newRRC->removeParam(SvcParam::ipv4hint);
} else {
- rrc->setHints(SvcParam::ipv4hint, hints);
+ newRRC->setHints(SvcParam::ipv4hint, hints);
}
} else {
- rrc->removeParam(SvcParam::ipv4hint);
+ newRRC->removeParam(SvcParam::ipv4hint);
}
+ rrc = newRRC;
+ rec->dr.setContent(std::move(newRRC));
}
if (rrc->hasParam(SvcParam::ipv6hint) && rrc->autoHint(SvcParam::ipv6hint)) {
+ auto newRRC = rrc->clone();
+ if (!newRRC) {
+ continue;
+ }
if (s_SVCAutohints) {
auto hints = getIPAddressFor(target, QType::AAAA);
if (hints.size() == 0) {
- rrc->removeParam(SvcParam::ipv6hint);
+ newRRC->removeParam(SvcParam::ipv6hint);
} else {
- rrc->setHints(SvcParam::ipv6hint, hints);
+ newRRC->setHints(SvcParam::ipv6hint, hints);
}
} else {
- rrc->removeParam(SvcParam::ipv6hint);
+ newRRC->removeParam(SvcParam::ipv6hint);
}
+ rec->dr.setContent(std::move(newRRC));
}
}
rr.dr.d_name = name;
rr.dr.d_ttl = d_sd.getNegativeTTL();
rr.dr.d_type = QType::NSEC;
- rr.dr.d_content = std::make_shared<NSECRecordContent>(std::move(nrc));
+ rr.dr.setContent(std::make_shared<NSECRecordContent>(std::move(nrc)));
rr.dr.d_place = (mode == 5 ) ? DNSResourceRecord::ANSWER: DNSResourceRecord::AUTHORITY;
rr.auth = true;
rr.dr.d_name = DNSName(toBase32Hex(namehash))+d_sd.qname;
rr.dr.d_ttl = d_sd.getNegativeTTL();
rr.dr.d_type=QType::NSEC3;
- rr.dr.d_content=std::make_shared<NSEC3RecordContent>(std::move(n3rc));
+ rr.dr.setContent(std::make_shared<NSEC3RecordContent>(std::move(n3rc)));
rr.dr.d_place = (mode == 5 ) ? DNSResourceRecord::ANSWER: DNSResourceRecord::AUTHORITY;
rr.auth = true;
try {
auto recvec=luaSynth(rec->getCode(), target, d_sd.qname, d_sd.domain_id, p, rec->d_type, s_LUA);
if(!recvec.empty()) {
- for(const auto& r_it : recvec) {
+ for (const auto& r_it : recvec) {
rr.dr.d_type = rec->d_type; // might be CNAME
- rr.dr.d_content = r_it;
+ rr.dr.setContent(r_it);
rr.scopeMask = p.getRealRemote().getBits(); // this makes sure answer is a specific as your question
rrset.push_back(rr);
}
g_log<<Logger::Info<<"ALIAS record found for "<<target<<", but ALIAS expansion is disabled."<<endl;
continue;
}
- haveAlias=getRR<ALIASRecordContent>(rr.dr)->d_content;
+ haveAlias=getRR<ALIASRecordContent>(rr.dr)->getContent();
aliasScopeMask=rr.scopeMask;
}
sort(pre.begin(), pre.end(), DNSRecord::prettyCompare);
for(const auto& dr : pre) {
ostringstream os;
- os<<dr.d_name<<"\t"<<dr.d_ttl<<"\tIN\t"<<DNSRecordContent::NumberToType(dr.d_type)<<"\t"<<dr.d_content->getZoneRepresentation(true)<<endl;
+ os<<dr.d_name<<"\t"<<dr.d_ttl<<"\tIN\t"<<DNSRecordContent::NumberToType(dr.d_type)<<"\t"<<dr.getContent()->getZoneRepresentation(true)<<endl;
if(write(tmpfd, os.str().c_str(), os.str().length()) < 0)
unixDie("Writing zone to temporary file");
}
set_difference(pre.cbegin(), pre.cend(), post.cbegin(), post.cend(), back_inserter(diff), DNSRecord::prettyCompare);
for(const auto& d : diff) {
ostringstream str;
- str << col.red() << "-" << d.d_name << " " << d.d_ttl << " IN " << DNSRecordContent::NumberToType(d.d_type) << " " <<d.d_content->getZoneRepresentation(true) << col.rst() <<endl;
+ str << col.red() << "-" << d.d_name << " " << d.d_ttl << " IN " << DNSRecordContent::NumberToType(d.d_type) << " " <<d.getContent()->getZoneRepresentation(true) << col.rst() <<endl;
changed[{d.d_name,d.d_type}] += str.str();
}
for(const auto& d : diff) {
ostringstream str;
- str<<col.green() << "+" << d.d_name << " " << d.d_ttl << " IN " <<DNSRecordContent::NumberToType(d.d_type) << " " << d.d_content->getZoneRepresentation(true) << col.rst() <<endl;
+ str<<col.green() << "+" << d.d_name << " " << d.d_ttl << " IN " <<DNSRecordContent::NumberToType(d.d_type) << " " << d.getContent()->getZoneRepresentation(true) << col.rst() <<endl;
changed[{d.d_name,d.d_type}]+=str.str();
}
cout<<"Detected the following changes:"<<endl;
{
DNSRecord oldSoaDR = grouped[{zone, QType::SOA}].at(0); // there should be only one SOA record, so we can use .at(0);
ostringstream str;
- str<< col.red() << "-" << oldSoaDR.d_name << " " << oldSoaDR.d_ttl << " IN " << DNSRecordContent::NumberToType(oldSoaDR.d_type) << " " <<oldSoaDR.d_content->getZoneRepresentation(true) << col.rst() <<endl;
+ str<< col.red() << "-" << oldSoaDR.d_name << " " << oldSoaDR.d_ttl << " IN " << DNSRecordContent::NumberToType(oldSoaDR.d_type) << " " <<oldSoaDR.getContent()->getZoneRepresentation(true) << col.rst() <<endl;
SOAData sd;
B.getSOAUncached(zone, sd);
DNSResourceRecord rr;
makeIncreasedSOARecord(sd, "SOA-EDIT-INCREASE", soaEditKind, rr);
DNSRecord dr(rr);
- str << col.green() << "+" << dr.d_name << " " << dr.d_ttl<< " IN " <<DNSRecordContent::NumberToType(dr.d_type) << " " <<dr.d_content->getZoneRepresentation(true) << col.rst() <<endl;
+ str << col.green() << "+" << dr.d_name << " " << dr.d_ttl<< " IN " <<DNSRecordContent::NumberToType(dr.d_type) << " " <<dr.getContent()->getZoneRepresentation(true) << col.rst() <<endl;
changed[{dr.d_name, dr.d_type}]+=str.str();
grouped[{dr.d_name, dr.d_type}].at(0) = dr;
cout << "test-schema ZONE Test DB schema - will create ZONE" << endl;
cout << "raw-lua-from-content TYPE CONTENT Display record contents in a form suitable for dnsdist's `SpoofRawAction`" << endl;
cout << "zonemd-verify-file ZONE FILE Validate ZONEMD for ZONE" << endl;
+ cout << "lmdb-get-backend-version Get schema version supported by backend" << endl;
cout << desc << endl;
return 0;
loadMainConfig(g_vm["config-dir"].as<string>());
+ if (cmds.at(0) == "lmdb-get-backend-version") {
+ cout << "5" << endl; // FIXME this should reuse the constant from lmdbbackend but that is currently a #define in a .cc
+ return 0;
+ }
if (cmds.at(0) == "test-algorithm") {
if(cmds.size() != 2) {
cerr << "Syntax: pdnsutil test-algorithm algonum"<<endl;
}
else if (cmds.at(0) == "clear-zone") {
if(cmds.size() != 2) {
- cerr<<"Syntax: pdnsutil edit-zone ZONE"<<endl;
+ cerr<<"Syntax: pdnsutil clear-zone ZONE"<<endl;
return 0;
}
if (cmds.at(1) == ".")
attr.push_back(P11KitAttribute(CKA_LABEL, d_label));
FindObjects2(*slot, attr, key, 1);
if (key.size() == 0) {
- g_log<<Logger::Warning<<"Cannot load PCKS#11 private key "<<d_label<<std::endl;;
+ g_log<<Logger::Warning<<"Cannot load PKCS#11 private key "<<d_label<<std::endl;;
return;
}
d_private_key = key[0];
attr.push_back(P11KitAttribute(CKA_LABEL, d_pub_label));
FindObjects2(*slot, attr, key, 1);
if (key.size() == 0) {
- g_log<<Logger::Warning<<"Cannot load PCKS#11 public key "<<d_pub_label<<std::endl;
+ g_log<<Logger::Warning<<"Cannot load PKCS#11 public key "<<d_pub_label<<std::endl;
return;
}
d_public_key = key[0];
d_exponent = attr[1].str();
d_bits = attr[2].ulong();
} else {
- throw PDNSException("Cannot load attributes for PCKS#11 public key " + d_pub_label);
+ throw PDNSException("Cannot load attributes for PKCS#11 public key " + d_pub_label);
}
} else if (d_key_type == CKK_EC || d_key_type == CKK_ECDSA) {
attr.clear();
if (attr[1].str().length() != (d_bits*2/8 + 3)) throw PDNSException("EC Point data invalid");
d_ec_point = attr[1].str().substr(3);
} else {
- throw PDNSException("Cannot load attributes for PCKS#11 public key " + d_pub_label);
+ throw PDNSException("Cannot load attributes for PKCS#11 public key " + d_pub_label);
}
} else {
- throw PDNSException("Cannot determine type for PCKS#11 public key " + d_pub_label);
+ throw PDNSException("Cannot determine type for PKCS#11 public key " + d_pub_label);
}
} else {
- throw PDNSException("Cannot load attributes for PCKS#11 public key " + d_pub_label);
+ throw PDNSException("Cannot load attributes for PKCS#11 public key " + d_pub_label);
}
d_loaded = true;
REVISION "202209120000Z"
DESCRIPTION "Added metrics for answers from auths by rcode"
+ REVISION "202302240000Z"
+ DESCRIPTION "Added metrics for sharded packet cache contention"
+
::= { powerdns 2 }
powerdns OBJECT IDENTIFIER ::= { enterprises 43315 }
"Number of rcode 15 answers received"
::= { stats 144 }
+packetCacheContended OBJECT-TYPE
+ SYNTAX Counter64
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "Number of contended packet cache lock acquisitions"
+ ::= { stats 145 }
+
+packetCacheAcquired OBJECT-TYPE
+ SYNTAX Counter64
+ MAX-ACCESS read-only
+ STATUS current
+ DESCRIPTION
+ "Number of packet cache lock acquisitions"
+ ::= { stats 146 }
+
---
--- Traps / Notifications
authrcode12Count,
authrcode13Count,
authrcode14Count,
- authrcode15Count
+ authrcode15Count,
+ packetCacheContended,
+ packetCacheAcquired
}
STATUS current
DESCRIPTION "Objects conformance group for PowerDNS Recursor"
}
}
-static bool isMinimallyCoveringNSEC(const DNSName& owner, const std::shared_ptr<NSECRecordContent>& nsec)
+static bool isMinimallyCoveringNSEC(const DNSName& owner, const std::shared_ptr<const NSECRecordContent>& nsec)
{
/* this test only covers Cloudflare's ones (https://blog.cloudflare.com/black-lies/),
we might need to cover more cases described in rfc4470 as well, but the name generation algorithm
return commonPrefixIsLong(ownerHash, nextHash, AggressiveNSECCache::s_maxNSEC3CommonPrefix);
}
-void AggressiveNSECCache::insertNSEC(const DNSName& zone, const DNSName& owner, const DNSRecord& record, const std::vector<std::shared_ptr<RRSIGRecordContent>>& signatures, bool nsec3)
+void AggressiveNSECCache::insertNSEC(const DNSName& zone, const DNSName& owner, const DNSRecord& record, const std::vector<std::shared_ptr<const RRSIGRecordContent>>& signatures, bool nsec3)
{
if (nsec3 && nsec3Disabled()) {
return;
}
/* the TTL is already a TTD by now */
- if (!nsec3 && isWildcardExpanded(owner.countLabels(), signatures.at(0))) {
+ if (!nsec3 && isWildcardExpanded(owner.countLabels(), *signatures.at(0))) {
DNSName realOwner = getNSECOwnerName(owner, signatures);
- auto pair = zoneEntry->d_entries.insert({record.d_content, signatures, std::move(realOwner), std::move(next), record.d_ttl});
+ auto pair = zoneEntry->d_entries.insert({record.getContent(), signatures, std::move(realOwner), std::move(next), record.d_ttl});
if (pair.second) {
++d_entriesCount;
}
}
else {
- auto pair = zoneEntry->d_entries.insert({record.d_content, signatures, owner, std::move(next), record.d_ttl});
+ auto pair = zoneEntry->d_entries.insert({record.getContent(), signatures, owner, std::move(next), record.d_ttl});
if (pair.second) {
++d_entriesCount;
}
return false;
}
-static void addToRRSet(const time_t now, std::vector<DNSRecord>& recordSet, std::vector<std::shared_ptr<RRSIGRecordContent>> signatures, const DNSName& owner, bool doDNSSEC, std::vector<DNSRecord>& ret, DNSResourceRecord::Place place = DNSResourceRecord::AUTHORITY)
+static void addToRRSet(const time_t now, std::vector<DNSRecord>& recordSet, std::vector<std::shared_ptr<const RRSIGRecordContent>> signatures, const DNSName& owner, bool doDNSSEC, std::vector<DNSRecord>& ret, DNSResourceRecord::Place place = DNSResourceRecord::AUTHORITY)
{
uint32_t ttl = 0;
dr.d_type = QType::RRSIG;
dr.d_name = owner;
dr.d_ttl = ttl;
- dr.d_content = std::move(signature);
+ dr.setContent(std::move(signature));
dr.d_place = place;
dr.d_class = QClass::IN;
ret.push_back(std::move(dr));
}
}
-static void addRecordToRRSet(time_t now, const DNSName& owner, const QType& type, uint32_t ttl, std::shared_ptr<DNSRecordContent>& content, std::vector<std::shared_ptr<RRSIGRecordContent>> signatures, bool doDNSSEC, std::vector<DNSRecord>& ret)
+static void addRecordToRRSet(const DNSName& owner, const QType& type, uint32_t ttl, std::shared_ptr<const DNSRecordContent>& content, std::vector<std::shared_ptr<const RRSIGRecordContent>> signatures, bool doDNSSEC, std::vector<DNSRecord>& ret)
{
DNSRecord nsecRec;
nsecRec.d_type = type.getCode();
nsecRec.d_name = owner;
nsecRec.d_ttl = ttl;
- nsecRec.d_content = std::move(content);
+ nsecRec.setContent(std::move(content));
nsecRec.d_place = DNSResourceRecord::AUTHORITY;
nsecRec.d_class = QClass::IN;
ret.push_back(std::move(nsecRec));
dr.d_type = QType::RRSIG;
dr.d_name = owner;
dr.d_ttl = ttl;
- dr.d_content = std::move(signature);
+ dr.setContent(std::move(signature));
dr.d_place = DNSResourceRecord::AUTHORITY;
dr.d_class = QClass::IN;
ret.push_back(std::move(dr));
vState cachedState;
std::vector<DNSRecord> wcSet;
- std::vector<std::shared_ptr<RRSIGRecordContent>> wcSignatures;
+ std::vector<std::shared_ptr<const RRSIGRecordContent>> wcSignatures;
if (g_recCache->get(now, wildcardName, type, MemRecursorCache::RequireAuth, &wcSet, ComboAddress("127.0.0.1"), boost::none, doDNSSEC ? &wcSignatures : nullptr, nullptr, nullptr, &cachedState) <= 0 || cachedState != vState::Secure) {
VLOG(log, name << ": Unfortunately we don't have a valid entry for " << wildcardName << ", so we cannot synthesize from that wildcard" << endl);
addToRRSet(now, wcSet, wcSignatures, name, doDNSSEC, ret, DNSResourceRecord::ANSWER);
/* no need for closest encloser proof, the wildcard is there */
- addRecordToRRSet(now, nextCloser.d_owner, QType::NSEC3, nextCloser.d_ttd - now, nextCloser.d_record, nextCloser.d_signatures, doDNSSEC, ret);
+ addRecordToRRSet(nextCloser.d_owner, QType::NSEC3, nextCloser.d_ttd - now, nextCloser.d_record, nextCloser.d_signatures, doDNSSEC, ret);
/* and of course we won't deny the wildcard either */
VLOG(log, name << ": Synthesized valid answer from NSEC3s and wildcard!" << endl);
++d_nsec3WildcardHits;
+ res = RCode::NoError;
return true;
}
vState cachedState;
std::vector<DNSRecord> wcSet;
- std::vector<std::shared_ptr<RRSIGRecordContent>> wcSignatures;
+ std::vector<std::shared_ptr<const RRSIGRecordContent>> wcSignatures;
if (g_recCache->get(now, wildcardName, type, MemRecursorCache::RequireAuth, &wcSet, ComboAddress("127.0.0.1"), boost::none, doDNSSEC ? &wcSignatures : nullptr, nullptr, nullptr, &cachedState) <= 0 || cachedState != vState::Secure) {
VLOG(log, name << ": Unfortunately we don't have a valid entry for " << wildcardName << ", so we cannot synthesize from that wildcard" << endl);
}
addToRRSet(now, wcSet, wcSignatures, name, doDNSSEC, ret, DNSResourceRecord::ANSWER);
- addRecordToRRSet(now, nsec.d_owner, QType::NSEC, nsec.d_ttd - now, nsec.d_record, nsec.d_signatures, doDNSSEC, ret);
+ addRecordToRRSet(nsec.d_owner, QType::NSEC, nsec.d_ttd - now, nsec.d_record, nsec.d_signatures, doDNSSEC, ret);
VLOG(log, name << ": Synthesized valid answer from NSECs and wildcard!" << endl);
++d_nsecWildcardHits;
+ res = RCode::NoError;
return true;
}
-bool AggressiveNSECCache::getNSEC3Denial(time_t now, std::shared_ptr<LockGuarded<AggressiveNSECCache::ZoneEntry>>& zoneEntry, std::vector<DNSRecord>& soaSet, std::vector<std::shared_ptr<RRSIGRecordContent>>& soaSignatures, const DNSName& name, const QType& type, std::vector<DNSRecord>& ret, int& res, bool doDNSSEC, const OptLog& log)
+bool AggressiveNSECCache::getNSEC3Denial(time_t now, std::shared_ptr<LockGuarded<AggressiveNSECCache::ZoneEntry>>& zoneEntry, std::vector<DNSRecord>& soaSet, std::vector<std::shared_ptr<const RRSIGRecordContent>>& soaSignatures, const DNSName& name, const QType& type, std::vector<DNSRecord>& ret, int& res, bool doDNSSEC, const OptLog& log)
{
DNSName zone;
std::string salt;
ZoneEntry::CacheEntry exactNSEC3;
if (getNSEC3(now, zoneEntry, nameHash, exactNSEC3)) {
VLOG(log, name << ": Found a direct NSEC3 match for " << nameHash);
- auto nsec3 = std::dynamic_pointer_cast<NSEC3RecordContent>(exactNSEC3.d_record);
+ auto nsec3 = std::dynamic_pointer_cast<const NSEC3RecordContent>(exactNSEC3.d_record);
if (!nsec3 || nsec3->d_iterations != iterations || nsec3->d_salt != salt) {
VLOG_NO_PREFIX(log, " but the content is not valid, or has a different salt or iterations count" << endl);
return false;
}
- if (!isTypeDenied(nsec3, type)) {
+ if (!isTypeDenied(*nsec3, type)) {
VLOG_NO_PREFIX(log, " but the requested type (" << type.toString() << ") does exist" << endl);
return false;
}
const DNSName signer = getSigner(exactNSEC3.d_signatures);
/* here we need to allow an ancestor NSEC3 proving that a DS does not exist as it is an
exact match for the name */
- if (type != QType::DS && isNSEC3AncestorDelegation(signer, exactNSEC3.d_owner, nsec3)) {
+ if (type != QType::DS && isNSEC3AncestorDelegation(signer, exactNSEC3.d_owner, *nsec3)) {
/* RFC 6840 section 4.1 "Clarifications on Nonexistence Proofs":
Ancestor delegation NSEC or NSEC3 RRs MUST NOT be used to assume
nonexistence of any RRs below that zone cut, which include all RRs at
++d_nsec3Hits;
res = RCode::NoError;
addToRRSet(now, soaSet, soaSignatures, zone, doDNSSEC, ret);
- addRecordToRRSet(now, exactNSEC3.d_owner, QType::NSEC3, exactNSEC3.d_ttd - now, exactNSEC3.d_record, exactNSEC3.d_signatures, doDNSSEC, ret);
+ addRecordToRRSet(exactNSEC3.d_owner, QType::NSEC3, exactNSEC3.d_ttd - now, exactNSEC3.d_record, exactNSEC3.d_signatures, doDNSSEC, ret);
return true;
}
if (getNSEC3(now, zoneEntry, closestHash, closestNSEC3)) {
VLOG(log, name << ": Found closest encloser at " << closestEncloser << " (" << closestHash << ")" << endl);
- auto nsec3 = std::dynamic_pointer_cast<NSEC3RecordContent>(closestNSEC3.d_record);
+ auto nsec3 = std::dynamic_pointer_cast<const NSEC3RecordContent>(closestNSEC3.d_record);
if (!nsec3 || nsec3->d_iterations != iterations || nsec3->d_salt != salt) {
VLOG_NO_PREFIX(log, " but the content is not valid, or has a different salt or iterations count" << endl);
break;
const DNSName signer = getSigner(closestNSEC3.d_signatures);
/* This time we do not allow any ancestor NSEC3, as if the closest encloser is a delegation
NS we know nothing about the names in the child zone. */
- if (isNSEC3AncestorDelegation(signer, closestNSEC3.d_owner, nsec3)) {
+ if (isNSEC3AncestorDelegation(signer, closestNSEC3.d_owner, *nsec3)) {
/* RFC 6840 section 4.1 "Clarifications on Nonexistence Proofs":
Ancestor delegation NSEC or NSEC3 RRs MUST NOT be used to assume
nonexistence of any RRs below that zone cut, which include all RRs at
return false;
}
- auto nextCloserNsec3 = std::dynamic_pointer_cast<NSEC3RecordContent>(nextCloserEntry.d_record);
+ auto nextCloserNsec3 = std::dynamic_pointer_cast<const NSEC3RecordContent>(nextCloserEntry.d_record);
if (!nextCloserNsec3 || nextCloserNsec3->d_iterations != iterations || nextCloserNsec3->d_salt != salt) {
VLOG(log, name << ": The NSEC3 covering the next closer is not valid, or has a different salt or iterations count, bailing out" << endl);
return false;
if ((DNSName(wcHash) + zone) == wcEntry.d_owner) {
VLOG(log, name << ": Found an exact match for the wildcard");
- auto nsec3 = std::dynamic_pointer_cast<NSEC3RecordContent>(wcEntry.d_record);
+ auto nsec3 = std::dynamic_pointer_cast<const NSEC3RecordContent>(wcEntry.d_record);
if (!nsec3 || nsec3->d_iterations != iterations || nsec3->d_salt != salt) {
VLOG_NO_PREFIX(log, " but the content is not valid, or has a different salt or iterations count" << endl);
return false;
const DNSName wcSigner = getSigner(wcEntry.d_signatures);
/* It's an exact match for the wildcard, so it does exist. If we are looking for a DS
an ancestor NSEC3 is fine, otherwise it does not prove anything. */
- if (type != QType::DS && isNSEC3AncestorDelegation(wcSigner, wcEntry.d_owner, nsec3)) {
+ if (type != QType::DS && isNSEC3AncestorDelegation(wcSigner, wcEntry.d_owner, *nsec3)) {
/* RFC 6840 section 4.1 "Clarifications on Nonexistence Proofs":
Ancestor delegation NSEC or NSEC3 RRs MUST NOT be used to assume
nonexistence of any RRs below that zone cut, which include all RRs at
return false;
}
- if (!isTypeDenied(nsec3, type)) {
+ if (!isTypeDenied(*nsec3, type)) {
VLOG_NO_PREFIX(log, " but the requested type (" << type.toString() << ") does exist" << endl);
return synthesizeFromNSEC3Wildcard(now, name, type, ret, res, doDNSSEC, nextCloserEntry, wildcard, log);
}
return false;
}
- auto nsec3 = std::dynamic_pointer_cast<NSEC3RecordContent>(wcEntry.d_record);
+ auto nsec3 = std::dynamic_pointer_cast<const NSEC3RecordContent>(wcEntry.d_record);
if (!nsec3 || nsec3->d_iterations != iterations || nsec3->d_salt != salt) {
VLOG(log, name << ": The content of the NSEC3 covering the wildcard is not valid, or has a different salt or iterations count" << endl);
return false;
}
addToRRSet(now, soaSet, soaSignatures, zone, doDNSSEC, ret);
- addRecordToRRSet(now, closestNSEC3.d_owner, QType::NSEC3, closestNSEC3.d_ttd - now, closestNSEC3.d_record, closestNSEC3.d_signatures, doDNSSEC, ret);
+ addRecordToRRSet(closestNSEC3.d_owner, QType::NSEC3, closestNSEC3.d_ttd - now, closestNSEC3.d_record, closestNSEC3.d_signatures, doDNSSEC, ret);
/* no need to include the same NSEC3 twice */
if (nextCloserEntry.d_owner != closestNSEC3.d_owner) {
- addRecordToRRSet(now, nextCloserEntry.d_owner, QType::NSEC3, nextCloserEntry.d_ttd - now, nextCloserEntry.d_record, nextCloserEntry.d_signatures, doDNSSEC, ret);
+ addRecordToRRSet(nextCloserEntry.d_owner, QType::NSEC3, nextCloserEntry.d_ttd - now, nextCloserEntry.d_record, nextCloserEntry.d_signatures, doDNSSEC, ret);
}
if (wcEntry.d_owner != closestNSEC3.d_owner && wcEntry.d_owner != nextCloserEntry.d_owner) {
- addRecordToRRSet(now, wcEntry.d_owner, QType::NSEC3, wcEntry.d_ttd - now, wcEntry.d_record, wcEntry.d_signatures, doDNSSEC, ret);
+ addRecordToRRSet(wcEntry.d_owner, QType::NSEC3, wcEntry.d_ttd - now, wcEntry.d_record, wcEntry.d_signatures, doDNSSEC, ret);
}
VLOG(log, name << ": Found valid NSEC3s covering the requested name and type!" << endl);
vState cachedState;
std::vector<DNSRecord> soaSet;
- std::vector<std::shared_ptr<RRSIGRecordContent>> soaSignatures;
+ std::vector<std::shared_ptr<const RRSIGRecordContent>> soaSignatures;
/* we might not actually need the SOA if we find a matching wildcard, but let's not bother for now */
if (g_recCache->get(now, zone, QType::SOA, MemRecursorCache::RequireAuth, &soaSet, who, routingTag, doDNSSEC ? &soaSignatures : nullptr, nullptr, nullptr, &cachedState) <= 0 || cachedState != vState::Secure) {
VLOG(log, name << ": No valid SOA found for " << zone << ", which is the best match for " << name << endl);
return false;
}
- auto content = std::dynamic_pointer_cast<NSECRecordContent>(entry.d_record);
+ auto content = std::dynamic_pointer_cast<const NSECRecordContent>(entry.d_record);
if (!content) {
return false;
}
VLOG_NO_PREFIX(log, ": found a possible NSEC at " << entry.d_owner << " ");
// note that matchesNSEC() takes care of ruling out ancestor NSECs for us
- auto denial = matchesNSEC(name, type.getCode(), entry.d_owner, content, entry.d_signatures, log);
+ auto denial = matchesNSEC(name, type.getCode(), entry.d_owner, *content, entry.d_signatures, log);
if (denial == dState::NODENIAL || denial == dState::INCONCLUSIVE) {
VLOG_NO_PREFIX(log, " but it does not cover us" << endl);
return false;
VLOG_NO_PREFIX(log, ": found a possible NSEC at " << wcEntry.d_owner << " ");
- auto nsecContent = std::dynamic_pointer_cast<NSECRecordContent>(wcEntry.d_record);
+ auto nsecContent = std::dynamic_pointer_cast<const NSECRecordContent>(wcEntry.d_record);
- denial = matchesNSEC(wc, type.getCode(), wcEntry.d_owner, nsecContent, wcEntry.d_signatures, log);
+ denial = matchesNSEC(wc, type.getCode(), wcEntry.d_owner, *nsecContent, wcEntry.d_signatures, log);
if (denial == dState::NODENIAL || denial == dState::INCONCLUSIVE) {
if (wcEntry.d_owner == wc) {
ret.reserve(ret.size() + soaSet.size() + soaSignatures.size() + /* NSEC */ 1 + entry.d_signatures.size() + (needWildcard ? (/* NSEC */ 1 + wcEntry.d_signatures.size()) : 0));
addToRRSet(now, soaSet, soaSignatures, zone, doDNSSEC, ret);
- addRecordToRRSet(now, entry.d_owner, QType::NSEC, entry.d_ttd - now, entry.d_record, entry.d_signatures, doDNSSEC, ret);
+ addRecordToRRSet(entry.d_owner, QType::NSEC, entry.d_ttd - now, entry.d_record, entry.d_signatures, doDNSSEC, ret);
if (needWildcard) {
- addRecordToRRSet(now, wcEntry.d_owner, QType::NSEC, wcEntry.d_ttd - now, wcEntry.d_record, wcEntry.d_signatures, doDNSSEC, ret);
+ addRecordToRRSet(wcEntry.d_owner, QType::NSEC, wcEntry.d_ttd - now, wcEntry.d_record, wcEntry.d_signatures, doDNSSEC, ret);
}
VLOG(log, name << ": Found valid NSECs covering the requested name and type!" << endl);
return s_maxNSEC3CommonPrefix == 0;
}
- void insertNSEC(const DNSName& zone, const DNSName& owner, const DNSRecord& record, const std::vector<std::shared_ptr<RRSIGRecordContent>>& signatures, bool nsec3);
+ void insertNSEC(const DNSName& zone, const DNSName& owner, const DNSRecord& record, const std::vector<std::shared_ptr<const RRSIGRecordContent>>& signatures, bool nsec3);
bool getDenial(time_t, const DNSName& name, const QType& type, std::vector<DNSRecord>& ret, int& res, const ComboAddress& who, const boost::optional<std::string>& routingTag, bool doDNSSEC, const OptLog& log = std::nullopt);
void removeZoneInfo(const DNSName& zone, bool subzones);
struct CacheEntry
{
- std::shared_ptr<DNSRecordContent> d_record;
- std::vector<std::shared_ptr<RRSIGRecordContent>> d_signatures;
+ std::shared_ptr<const DNSRecordContent> d_record;
+ std::vector<std::shared_ptr<const RRSIGRecordContent>> d_signatures;
DNSName d_owner;
DNSName d_next;
std::shared_ptr<LockGuarded<ZoneEntry>> getBestZone(const DNSName& zone);
bool getNSECBefore(time_t now, std::shared_ptr<LockGuarded<ZoneEntry>>& zoneEntry, const DNSName& name, ZoneEntry::CacheEntry& entry);
bool getNSEC3(time_t now, std::shared_ptr<LockGuarded<ZoneEntry>>& zoneEntry, const DNSName& name, ZoneEntry::CacheEntry& entry);
- bool getNSEC3Denial(time_t now, std::shared_ptr<LockGuarded<ZoneEntry>>& zoneEntry, std::vector<DNSRecord>& soaSet, std::vector<std::shared_ptr<RRSIGRecordContent>>& soaSignatures, const DNSName& name, const QType& type, std::vector<DNSRecord>& ret, int& res, bool doDNSSEC, const OptLog&);
+ bool getNSEC3Denial(time_t now, std::shared_ptr<LockGuarded<ZoneEntry>>& zoneEntry, std::vector<DNSRecord>& soaSet, std::vector<std::shared_ptr<const RRSIGRecordContent>>& soaSignatures, const DNSName& name, const QType& type, std::vector<DNSRecord>& ret, int& res, bool doDNSSEC, const OptLog&);
bool synthesizeFromNSEC3Wildcard(time_t now, const DNSName& name, const QType& type, std::vector<DNSRecord>& ret, int& res, bool doDNSSEC, ZoneEntry::CacheEntry& nextCloser, const DNSName& wildcardName, const OptLog&);
bool synthesizeFromNSECWildcard(time_t now, const DNSName& name, const QType& type, std::vector<DNSRecord>& ret, int& res, bool doDNSSEC, ZoneEntry::CacheEntry& nsec, const DNSName& wildcardName, const OptLog&);
AC_CANONICAL_HOST
# Add some default CFLAGS and CXXFLAGS, can be appended to using the environment variables
-CFLAGS="-Wall -Wextra -Wshadow -Wno-unused-parameter -Wmissing-declarations -Wredundant-decls -fvisibility=hidden -g -O2 $CFLAGS"
-CXXFLAGS="-Wall -Wextra -Wshadow -Wno-unused-parameter -Wmissing-declarations -Wredundant-decls -fvisibility=hidden -g -O2 $CXXFLAGS"
+CFLAGS="-Wall -Wextra -Wshadow -Wmissing-declarations -Wredundant-decls -fvisibility=hidden -g -O2 $CFLAGS"
+CXXFLAGS="-Wall -Wextra -Wshadow -Wmissing-declarations -Wredundant-decls -fvisibility=hidden -g -O2 $CXXFLAGS"
AC_SUBST([pdns_configure_args],["$ac_configure_args"])
AC_DEFINE_UNQUOTED([PDNS_CONFIG_ARGS],
Changelogs for 4.6.X
====================
+.. changelog::
+ :version: 4.6.6
+ :released: 29th of March 2023
+
+ .. change::
+ :tags: Bug Fixes
+ :pullreq: 12702
+
+ PowerDNS Security Advisory 2023-02: Deterred spoofing attempts can lead to authoritative servers being marked unavailable.
+
.. changelog::
:version: 4.6.5
:released: 25th of November 2022
Changelogs for 4.7.X
====================
+.. changelog::
+ :version: 4.7.5
+ :released: 29th of March 2023
+
+ .. change::
+ :tags: Bug Fixes
+ :pullreq: 12701
+
+ PowerDNS Security Advisory 2023-02: Deterred spoofing attempts can lead to authoritative servers being marked unavailable.
+
.. changelog::
:version: 4.7.4
:released: 25th of November 2022
Changelogs for 4.8.X
====================
+.. changelog::
+ :version: 4.8.4
+ :released: 29th of March 2023
+
+ .. change::
+ :tags: Bug Fixes
+ :pullreq: 12700
+
+ PowerDNS Security Advisory 2023-02: Deterred spoofing attempts can lead to authoritative servers being marked unavailable.
+
.. changelog::
:version: 4.8.3
:released: 7th of March 2023
--- /dev/null
+Changelogs for 4.9.X
+====================
+
+.. changelog::
+ :version: 4.9.0-alpha1
+ :released: 14th of April 2023
+
+ .. change::
+ :tags: Improvements
+ :pullreq: 12710
+
+ Cleanup rcode enums: base one is 8 bit unsigned, extended one 16 bit unsigned
+
+ .. change::
+ :tags: Improvements
+ :pullreq: 12594
+
+ Sharded and shared packet cache.
+
+ .. change::
+ :tags: Improvements
+ :pullreq: 12709
+
+ More fine grained capping of packet cache TTL.
+
+ .. change::
+ :tags: Bug Fixes
+ :pullreq: 12655
+ :tickets: 12486
+
+ Rework root priming code to allow multiple addresses per NS.
+
+ .. change::
+ :tags: Improvements
+ :pullreq: 10072,12716
+
+ Update Debian packaging for Recursor (Chris Hofstaedtler).
+
+ .. change::
+ :tags: Improvements
+ :pullreq: 12497
+
+ Unify shorthands for seconds in log messages (Josh Soref).
+
+ .. change::
+ :tags: Improvements
+ :pullreq: 12674
+
+ Validate: Stop passing shared pointers all the way down.
+
+ .. change::
+ :tags: Improvements
+ :pullreq: 12688
+
+ Re-establish "recursion depth is always increasing" invariant.
+
+ .. change::
+ :tags: Bug Fixes
+ :pullreq: 12672
+
+ Fix a dnsheader unaligned case.
+
+ .. change::
+ :tags: Improvements
+ :pullreq: 12550,12540,12524,12516,12515,12513,12502,12501,12462,12412,12401
+
+ OpenSSL 3.0 compatibility.
+
+ .. change::
+ :tags: Bug Fixes
+ :pullreq: 12554
+
+ Serve-stale-extensions works on 30s so an hour should be 120. (Andreas Jakum)
+
+ .. change::
+ :tags: Bug Fixes
+ :pullreq: 12539
+
+ Fix doc typo (Matt Nordhoff).
+
+ .. change::
+ :tags: Improvements
+ :pullreq: 12493
+
+ Only store NSEC3 records in aggressive cache if we expect them to be effective.
+
+ .. change::
+ :tags: Improvements
+ :pullreq: 11777
+
+ rec_control trace-regex: trace to a file or stdout instead of the general log.
+
+ .. change::
+ :tags: Bug Fixes
+ :pullreq: 12495
+
+ Logging tweaks (Josh Soref).
+
+ .. change::
+ :tags: Improvements
+ :pullreq: 12434
+
+ Unify trace logging code in syncres and validator.
+
+ .. change::
+ :tags: Improvements
+ :pullreq: 12446,12695
+
+ Stack protector for mthread stacks.
+
+ .. change::
+ :tags: Improvements
+ :pullreq: 12425
+
+ Change the way RD=0 forwarded queries are handled.
+
+ .. change::
+ :tags: Improvements
+ :pullreq: 12381
+
+ Enable FORTIFY_SOURCE=3 when supported by the compiler.
+
+ .. change::
+ :tags: Bug Fixes
+ :pullreq: 12419
+ :tickets: 12374
+
+ Negcache dump code: close fd on fdopen fail.
+
+ .. change::
+ :tags: Improvements
+ :pullreq: 12396
+
+ Introduce a thread-safe version of stringerror().
+
+ .. change::
+ :tags: Improvements
+ :pullreq: 12399
+ :tickets: 11138
+
+ Name recursor threads consistently with a "rec/" prefix.
+
+ .. change::
+ :tags: Bug Fixes
+ :pullreq: 12392
+
+ Be more careful saving errno in makeClientSocket() and closesocket()
+
+ .. change::
+ :tags: Improvements
+ :pullreq: 12373
+
+ Rec: Warn on high (90%) mthread stack usage.
+
+ .. change::
+ :tags: Improvements
+ :pullreq: 12334,12691,12698
+
+ Rec: Generate EDE in more cases, specifically on unreachable auths or synthesized results.
+
+ .. change::
+ :tags: Bug Fixes
+ :pullreq: 12368
+
+ Add the 'parse packet from auth' error message to structured logging.
+
+ .. change::
+ :tags: Improvements
+ :pullreq: 12292
+
+ Wrap the CURL raw pointers in smart pointers.
+
+ .. change::
+ :tags: Improvements
+ :pullreq: 12318
+ :tickets: 12241
+
+ Reorganization: move recursor specific files to recursordist.
+
+ .. change::
+ :tags: Improvements
+ :pullreq: 12193,12348,12323
+
+ Introducing TCounters.
+
+ .. change::
+ :tags: Improvements
+ :pullreq: 12120
+ :tickets: 12090
+
+ If we encounter a loop in QM, continue with the next iteration.
+
+ .. change::
+ :tags: Improvements
+ :pullreq: 12121
+ :tickets: 12080
+
+ More clear trace message for cache-only lookups.
+
.. toctree::
:maxdepth: 2
+ 4.9
4.8
4.7
4.6
The first line specifies that additional records should be added to the results of ``MX`` queries using the default mode.
The qtype of the records to be added are ``A`` and ``AAAA``.
-The default mode is ``pdns.AdditionalMode.CacheOnlyRequireAuth``, this mode will only look in the record cache.
+The default mode is ``pdns.AdditionalMode.CacheOnlyRequireAuth``; this mode will only look in the record cache.
The second line specifies that three record types should be added to ``NAPTR`` answers.
If needed, the Recursor will do an active resolve to retrieve these records.
+Note that with record types such as ``NAPTR`` which can return records such as ``SRV``, which may themselves return additional
+``A`` or ``AAAA`` records, the above example would not be sufficient to return those additional ``A`` and/or ``AAAA`` records.
+In such a case, you would need to add an additional line to tell the recursor to fetch the additional records for the ``SRV``
+qtype as well. An example configuration for this case is shown below:
+
+.. code-block:: Lua
+
+ addAllowedAdditionalQType(pdns.NAPTR, {pdns.A, pdns.AAAA, pdns.SRV}, {mode=pdns.AdditionalMode.ResolveImmediately})
+ addAllowedAdditionalQType(pdns.SRV, {pdns.A, pdns.AAAA}, {mode=pdns.AdditionalMode.ResolveImmediately})
+
The modes available are:
``pdns.AdditionalMode.Ignore``
When deploying (large scale) IPv6, please be aware some Linux distributions leave IPv6 routing cache tables at very small default values.
Please check and if necessary raise ``sysctl net.ipv6.route.max_size``.
-Set :ref:`setting-threads` to your number of CPU cores minus the number of distributor threads (but values above 8 rarely improve performance).
+Set :ref:`setting-threads` to your number of CPU cores minus the number of distributor threads.
Threading and distribution of queries
-------------------------------------
-When running with several threads, you can either ask PowerDNS to start one or more special threads to dispatch the incoming queries to the workers by setting :ref:`setting-pdns-distributes-queries` to true, or let the worker threads handle the incoming queries themselves.
+When running with several threads, you can either ask PowerDNS to start one or more special threads to dispatch the incoming queries to the workers by setting :ref:`setting-pdns-distributes-queries` to ``yes``, or let the worker threads handle the incoming queries themselves.
+The latter is the default since version 4.9.0.
The dispatch thread enabled by :ref:`setting-pdns-distributes-queries` tries to send the same queries to the same thread to maximize the cache-hit ratio.
If the incoming query rate is so high that the dispatch thread becomes a bottleneck, you can increase :ref:`setting-distributor-threads` to use more than one.
-If :ref:`setting-pdns-distributes-queries` is set to false and either ``SO_REUSEPORT`` support is not available or the :ref:`setting-reuseport` directive is set to false, all worker threads share the same listening sockets.
+If :ref:`setting-pdns-distributes-queries` is set to ``no`` and either ``SO_REUSEPORT`` support is not available or the :ref:`setting-reuseport` directive is set to ``no``, all worker threads share the same listening sockets.
This prevents a single thread from having to handle every incoming queries, but can lead to thundering herd issues where all threads are awoken at once when a query arrives.
-If ``SO_REUSEPORT`` support is available and :ref:`setting-reuseport` is set to true, separate listening sockets are opened for each worker thread and the query distributions is handled by the kernel, avoiding any thundering herd issue as well as preventing the distributor thread from becoming the bottleneck.
+If ``SO_REUSEPORT`` support is available and :ref:`setting-reuseport` is set to ``yes``, which is the
+default since version 4.9.0, separate listening sockets are opened for each worker thread and the query distributions is handled by the kernel, avoiding any thundering herd issue as well as preventing the distributor thread from becoming the bottleneck.
+
+On some systems setting :ref:`setting-reuseport` to ``yes`` does not have the desired effect.
+If your systems shows imbalance in the number of queries processed per thread (as reported by the periodic statistics report), try switching :ref:`setting-reuseport` to ``no`` and/or setting :ref:`setting-pdns-distributes-queries` to ``yes``.
.. versionadded:: 4.1.0
The :ref:`setting-cpu-map` parameter can be used to pin worker threads to specific CPUs, in order to keep caches as warm as possible and optimize memory access on NUMA systems.
.. versionadded:: 4.2.0
The :ref:`setting-distributor-threads` parameter can be used to run more than one distributor thread.
+.. versionchanged:: 4.9.0
+ The :ref:`setting-reuseport` parameter now defaults to ``yes``.
+
+.. versionchanged:: 4.9.0
+ The :ref:`setting-pdns-distributes-queries` parameter now defaults to ``no``.
+
+
MTasker and MThreads
--------------------
Sample Linux command lines would be::
## IPv4
+ ## NOTRACK rules for 53/udp, keep in mind that you also need your regular rules for 53/tcp
iptables -t raw -I OUTPUT -p udp --dport 53 -j CT --notrack
iptables -t raw -I OUTPUT -p udp --sport 53 -j CT --notrack
iptables -t raw -I PREROUTING -p udp --dport 53 -j CT --notrack
iptables -I OUTPUT -p udp --sport 53 -j ACCEPT
## IPv6
+ ## NOTRACK rules for 53/udp, keep in mind that you also need your regular rules for 53/tcp
ip6tables -t raw -I OUTPUT -p udp --dport 53 -j CT --notrack
ip6tables -t raw -I OUTPUT -p udp --sport 53 -j CT --notrack
ip6tables -t raw -I PREROUTING -p udp --sport 53 -j CT --notrack
The settings can be made permanent by using the ``--permanent`` flag::
## IPv4
+ ## NOTRACK rules for 53/udp, keep in mind that you also need your regular rules for 53/tcp
firewall-cmd --direct --add-rule ipv4 raw OUTPUT 0 -p udp --dport 53 -j CT --notrack
firewall-cmd --direct --add-rule ipv4 raw OUTPUT 0 -p udp --sport 53 -j CT --notrack
firewall-cmd --direct --add-rule ipv4 raw PREROUTING 0 -p udp --dport 53 -j CT --notrack
firewall-cmd --direct --add-rule ipv4 filter OUTPUT 0 -p udp --sport 53 -j ACCEPT
## IPv6
+ ## NOTRACK rules for 53/udp, keep in mind that you also need your regular rules for 53/tcp
firewall-cmd --direct --add-rule ipv6 raw OUTPUT 0 -p udp --dport 53 -j CT --notrack
firewall-cmd --direct --add-rule ipv6 raw OUTPUT 0 -p udp --sport 53 -j CT --notrack
firewall-cmd --direct --add-rule ipv6 raw PREROUTING 0 -p udp --dport 53 -j CT --notrack
--- /dev/null
+PowerDNS Security Advisory 2023-02: Deterred spoofing attempts can lead to authoritative servers being marked unavailable
+=========================================================================================================================
+
+- CVE: CVE-2023-26437
+- Date: 29th of March 2023
+- Affects: PowerDNS Recursor up to and including 4.6.5, 4.7.4 and 4.8.3
+- Not affected: PowerDNS Recursor 4.6.6, 4.7.5 and 4.8.4
+- Severity: Low
+- Impact: Denial of service
+- Exploit: Successful spoofing may lead to authoritative servers being marked unavailable
+- Risk of system compromise: None
+- Solution: Upgrade to patched version
+
+When the recursor detects and deters a spoofing attempt or receives certain malformed DNS packets,
+it throttles the server that was the target of the impersonation attempt so that other authoritative
+servers for the same zone will be more likely to be used in the future, in case the attacker
+controls the path to one server only. Unfortunately this mechanism can be used by an attacker with
+the ability to send queries to the recursor, guess the correct source port of the corresponding
+outgoing query and inject packets with a spoofed IP address to force the recursor to mark specific
+authoritative servers as not available, leading a denial of service for the zones served by those
+servers.
+
+CVSS 3.0 score: 3.7 (Low)
+https://www.first.org/cvss/calculator/3.0#CVSS:3.0/AV:N/AC:H/PR:N/UI:R/S:C/C:N/I:N/A:L
+
+Thanks to Xiang Li from Network and Information Security Laboratory, Tsinghua University for reporting this issue.
+
+
The number of records to cache in the aggressive cache. If set to a value greater than 0, the recursor will cache NSEC and NSEC3 records to generate negative answers, as defined in :rfc:`8198`.
To use this, DNSSEC processing or validation must be enabled by setting `dnssec`_ to ``process``, ``log-fail`` or ``validate``.
-.. _setting-aggressive-cache-max-nsec3-hit-ratio:
+.. _setting-aggressive-cache-min-nsec3-hit-ratio:
``aggressive-cache-min-nsec3-hit-ratio``
----------------------------------------
-
-.. versionadded: 4.9.0
+.. versionadded:: 4.9.0
- Integer
- Default: 2000
- Default: 1 if `pdns-distributes-queries`_ is set, 0 otherwise
If `pdns-distributes-queries`_ is set, spawn this number of distributor threads on startup. Distributor threads
-handle incoming queries and distribute them to other threads based on a hash of the query, to maximize the cache hit
-ratio.
+handle incoming queries and distribute them to other threads based on a hash of the query.
.. _setting-dot-to-auth-names:
``packetcache-ttl``
-------------------
- Integer
-- Default: 3600
+- Default: 86400
Maximum number of seconds to cache an item in the packet cache, no matter what the original TTL specified.
+.. versionchanged:: 4.9.0
+
+ The default was changed from 3600 (1 hour) to 86400 (24 hours).
+
+.. _setting-packetcache-negative-ttl:
+
+``packetcache-negative-ttl``
+----------------------------
+.. versionadded:: 4.9.0
+
+- Integer
+- Default: 60
+
+Maximum number of seconds to cache an ``NxDomain`` or ``NoData`` answer in the packetcache.
+This setting's maximum is capped to `packetcache-ttl`_.
+i.e. setting ``packetcache-ttl=15`` and keeping ``packetcache-negative-ttl`` at the default will lower ``packetcache-negative-ttl`` to ``15``.
+
.. _setting-packetcache-servfail-ttl:
``packetcache-servfail-ttl``
Maximum number of seconds to cache an answer indicating a failure to resolve in the packet cache.
Before version 4.6.0 only ``ServFail`` answers were considered as such. Starting with 4.6.0, all responses with a code other than ``NoError`` and ``NXDomain``, or without records in the answer and authority sections, are considered as a failure to resolve.
+Since 4.9.0, negative answers are handled separately from resolving failures.
.. versionchanged:: 4.0.0
This setting's maximum is capped to `packetcache-ttl`_.
i.e. setting ``packetcache-ttl=15`` and keeping ``packetcache-servfail-ttl`` at the default will lower ``packetcache-servfail-ttl`` to ``15``.
+
+.. _setting-packetcache-shards:
+
+``packetcache-shards``
+------------------------
+.. versionadded:: 4.9.0
+
+- Integer
+- Default: 1024
+
+Sets the number of shards in the packet cache. If you have high contention as reported by ``packetcache-contented/packetcache-acquired``,
+you can try to enlarge this value or run with fewer threads.
+
.. _setting-pdns-distributes-queries:
``pdns-distributes-queries``
----------------------------
- Boolean
-- Default: yes
+- Default: no
If set, PowerDNS will use distinct threads to listen to client sockets and distribute that work to worker-threads using a hash of the query.
-This feature should maximize the cache hit ratio.
-To use more than one thread set `distributor-threads` in version 4.2.0 or newer.
-Enabling should improve performance for medium sized resolvers.
+This feature should maximize the cache hit ratio on versions before 4.9.0.
+To use more than one thread set `distributor-threads`_ in version 4.2.0 or newer.
+Enabling should improve performance on systems where `reuseport`_ does not have the effect of
+balancing the queries evenly over multiple worker threads.
+
+.. versionchanged:: 4.9.0
+
+ Default changed to ``no``, previously it was ``yes``.
.. _setting-protobuf-use-kernel-timestamp:
``reuseport``
-------------
- Boolean
-- Default: no
+- Default: yes
If ``SO_REUSEPORT`` support is available, allows multiple threads and processes to open listening sockets for the same port.
-Since 4.1.0, when ``pdns-distributes-queries`` is set to false and ``reuseport`` is enabled, every worker-thread will open a separate listening socket to let the kernel distribute the incoming queries instead of running a distributor thread (which could otherwise be a bottleneck) and avoiding thundering herd issues, thus leading to much higher performance on multi-core boxes.
+Since 4.1.0, when `pdns-distributes-queries`_ is disabled and `reuseport`_ is enabled, every worker-thread will open a separate listening socket to let the kernel distribute the incoming queries instead of running a distributor thread (which could otherwise be a bottleneck) and avoiding thundering herd issues, thus leading to much higher performance on multi-core boxes.
+
+.. versionchanged:: 4.9.0
+
+ The default is changed to ``yes``, previously it was ``no``.
+ If ``SO_REUSEPORT`` support is not available, the setting defaults to ``no``.
.. _setting-rng:
This affects the results shown by ``rec_control get-qtypelist`` and the ``response-by-qtype``, ``response-sizes`` and ``response-by-rcode`` items returned by the ``/api/v1/servers/localhost/statistics`` API endpoint.
Additionally, most ``RCodes`` and ``QTypes`` that are marked ``Unassigned``, ``Reserved`` or ``Obsolete`` by IANA are not accounted, to reduce the memory consumed by these metrics.
+New settings
+~~~~~~~~~~~~
+- The :ref:`setting-packetcache-negative-ttl` settings to control the TTL of negative (NxDomain or NoData) answers in the packet cache has been introduced.
+- The :ref:`setting-stack-cache-size` setting to control the number of allocated mthread stacks has been introduced.
+- The :ref:`setting-packetcache-shards` settings to control the number of shards in the packet cache has been introduced.
+- The :ref:`setting-aggressive-cache-min-nsec3-hit-ratio` setting to control which NSEC3 records are stored in the aggressive NSEC cache has been introduced.
+
+Changed settings
+~~~~~~~~~~~~~~~~
+The first two settings below have effect on the way the recursor distributes queries over threads.
+In some rare cases, this can have negative performance impact.
+In those cases it might be needed to change these settings.
+See :doc:`performance`.
+
+- The :ref:`setting-pdns-distributes-queries` default has been changed to ``no``.
+- The :ref:`setting-reuseport` default has been changed to ``yes``.
+
+- The :ref:`setting-packetcache-ttl` default has been changed to 24 hours.
+
:program:`rec_control`
^^^^^^^^^^^^^^^^^^^^^^
The ``trace_regex`` subcommand has been changed to take a file argument.
The ``dump-nsspeeds`` command has changed format to make it more readable and lists the last round trip time recorded for each address.
The ``get-proxymapping-stats`` and ``get-remotelogger-stats`` subcommands have been added.
-
4.7.2 to 4.7.3
--------------
NotSupported = 21,
NoReachableAuthority = 22,
NetworkError = 23,
- InvalidData = 24
+ InvalidData = 24,
+ SignatureExpiredBeforeValid = 25,
+ TooEarly = 26,
+ UnsupportedNSEC3IterationsValue = 27,
+ UnableToConformToPolicy = 28,
+ Synthesized = 29,
};
uint16_t infoCode;
std::string extraText;
"kind", Logging::Loggable(getKindToString(d_kind)));
}
-DNSRecord DNSFilterEngine::Policy::getRecordFromCustom(const DNSName& qname, const std::shared_ptr<DNSRecordContent>& custom) const
+DNSRecord DNSFilterEngine::Policy::getRecordFromCustom(const DNSName& qname, const std::shared_ptr<const DNSRecordContent>& custom) const
{
DNSRecord dr;
dr.d_name = qname;
dr.d_ttl = d_ttl;
dr.d_class = QClass::IN;
dr.d_place = DNSResourceRecord::ANSWER;
- dr.d_content = custom;
+ dr.setContent(custom);
if (dr.d_type == QType::CNAME) {
- const auto content = std::dynamic_pointer_cast<CNAMERecordContent>(custom);
+ const auto content = std::dynamic_pointer_cast<const CNAMERecordContent>(custom);
if (content) {
DNSName target = content->getTarget();
if (target.isWildcard()) {
target.chopOff();
- dr.d_content = std::make_shared<CNAMERecordContent>(qname + target);
+ dr.setContent(std::make_shared<CNAMERecordContent>(qname + target));
}
}
}
dr.d_ttl = d_ttl;
dr.d_class = QClass::IN;
dr.d_place = DNSResourceRecord::ANSWER;
- dr.d_content = custom;
+ dr.setContent(custom);
if (dr.d_type == QType::CNAME) {
- const auto content = std::dynamic_pointer_cast<CNAMERecordContent>(custom);
+ const auto content = std::dynamic_pointer_cast<const CNAMERecordContent>(custom);
if (content) {
DNSName target = content->getTarget();
if (target.isWildcard()) {
target.chopOff();
- dr.d_content = std::make_shared<CNAMERecordContent>(qname + target);
+ dr.setContent(std::make_shared<CNAMERecordContent>(qname + target));
}
}
}
dr.d_ttl = static_cast<uint32_t>(d_ttl);
dr.d_type = QType::CNAME;
dr.d_class = QClass::IN;
- dr.d_content = DNSRecordContent::mastermake(QType::CNAME, QClass::IN, getKindToString(d_kind));
+ dr.setContent(DNSRecordContent::mastermake(QType::CNAME, QClass::IN, getKindToString(d_kind)));
result.push_back(std::move(dr));
}
{
auto records = pol.getRecords(name);
for (const auto& dr : records) {
- fprintf(fp, "%s %" PRIu32 " IN %s %s\n", dr.d_name.toString().c_str(), dr.d_ttl, QType(dr.d_type).toString().c_str(), dr.d_content->getZoneRepresentation().c_str());
+ fprintf(fp, "%s %" PRIu32 " IN %s %s\n", dr.d_name.toString().c_str(), dr.d_ttl, QType(dr.d_type).toString().c_str(), dr.getContent()->getZoneRepresentation().c_str());
}
}
auto records = pol.getRecords(full);
for (const auto& dr : records) {
- fprintf(fp, "%s %" PRIu32 " IN %s %s\n", dr.d_name.toString().c_str(), dr.d_ttl, QType(dr.d_type).toString().c_str(), dr.d_content->getZoneRepresentation().c_str());
+ fprintf(fp, "%s %" PRIu32 " IN %s %s\n", dr.d_name.toString().c_str(), dr.d_ttl, QType(dr.d_type).toString().c_str(), dr.getContent()->getZoneRepresentation().c_str());
}
}
{
}
- Policy(PolicyKind kind, PolicyType type, int32_t ttl = 0, std::shared_ptr<PolicyZoneData> data = nullptr, const std::vector<std::shared_ptr<DNSRecordContent>>& custom = {}) :
+ Policy(PolicyKind kind, PolicyType type, int32_t ttl = 0, std::shared_ptr<PolicyZoneData> data = nullptr, const std::vector<std::shared_ptr<const DNSRecordContent>>& custom = {}) :
d_custom(custom), d_zoneData(data), d_ttl(ttl), d_kind(kind), d_type(type)
{
}
std::vector<DNSRecord> getCustomRecords(const DNSName& qname, uint16_t qtype) const;
std::vector<DNSRecord> getRecords(const DNSName& qname) const;
- std::vector<std::shared_ptr<DNSRecordContent>> d_custom;
+ std::vector<std::shared_ptr<const DNSRecordContent>> d_custom;
std::shared_ptr<PolicyZoneData> d_zoneData{nullptr};
DNSName d_trigger;
string d_hit;
PolicyType d_type;
private:
- DNSRecord getRecordFromCustom(const DNSName& qname, const std::shared_ptr<DNSRecordContent>& custom) const;
+ DNSRecord getRecordFromCustom(const DNSName& qname, const std::shared_ptr<const DNSRecordContent>& custom) const;
};
class Zone
#include <unistd.h>
// On OpenBSD mem used as stack should be marked MAP_STACK
-#if !defined(MAP_STACK)
-#define MAP_STACK 0
+#ifdef __OpenBSD__
+#define PDNS_MAP_STACK MAP_STACK
+#else
+#define PDNS_MAP_STACK 0
#endif
template <typename T>
#else
const int protection = PROT_NONE;
#endif
- void* p = mmap(nullptr, allocatedSize, protection, MAP_PRIVATE | MAP_ANON | MAP_STACK, -1, 0);
+ void* p = mmap(nullptr, allocatedSize, protection, MAP_PRIVATE | MAP_ANON | PDNS_MAP_STACK, -1, 0);
if (p == MAP_FAILED) {
throw std::bad_alloc();
}
map.emplace(key, value.to_string());
mapArguments(map, args...);
}
- void mapArguments(std::map<std::string, std::string>& map) const
- {
- return;
- }
+
+ void mapArguments(std::map<std::string, std::string>& /* map */) const {}
};
using log_t = const std::shared_ptr<Logger>&;
dr.d_ttl = ttl.get_value_or(3600);
dr.d_type = type;
dr.d_place = place;
- dr.d_content = DNSRecordContent::mastermake(type, QClass::IN, content);
+ dr.setContent(DNSRecordContent::mastermake(type, QClass::IN, content));
records.push_back(dr);
}
void RecursorLua4::postPrepareContext()
{
- d_lw->registerMember<const DNSName (DNSQuestion::*)>("qname", [](const DNSQuestion& dq) -> const DNSName& { return dq.qname; }, [](DNSQuestion& dq, const DNSName& newName) { (void) newName; });
- d_lw->registerMember<uint16_t (DNSQuestion::*)>("qtype", [](const DNSQuestion& dq) -> uint16_t { return dq.qtype; }, [](DNSQuestion& dq, uint16_t newType) { (void) newType; });
- d_lw->registerMember<bool (DNSQuestion::*)>("isTcp", [](const DNSQuestion& dq) -> bool { return dq.isTcp; }, [](DNSQuestion& dq, bool newTcp) { (void) newTcp; });
- d_lw->registerMember<const ComboAddress (DNSQuestion::*)>("localaddr", [](const DNSQuestion& dq) -> const ComboAddress& { return dq.local; }, [](DNSQuestion& dq, const ComboAddress& newLocal) { (void) newLocal; });
- d_lw->registerMember<const ComboAddress (DNSQuestion::*)>("remoteaddr", [](const DNSQuestion& dq) -> const ComboAddress& { return dq.remote; }, [](DNSQuestion& dq, const ComboAddress& newRemote) { (void) newRemote; });
- d_lw->registerMember<uint8_t (DNSQuestion::*)>("validationState", [](const DNSQuestion& dq) -> uint8_t { return (vStateIsBogus(dq.validationState) ? /* in order not to break older scripts */ static_cast<uint8_t>(255) : static_cast<uint8_t>(dq.validationState)); }, [](DNSQuestion& dq, uint8_t newState) { (void) newState; });
- d_lw->registerMember<vState (DNSQuestion::*)>("detailedValidationState", [](const DNSQuestion& dq) -> vState { return dq.validationState; }, [](DNSQuestion& dq, vState newState) { (void) newState; });
+ d_lw->registerMember<const DNSName (DNSQuestion::*)>("qname", [](const DNSQuestion& dq) -> const DNSName& { return dq.qname; }, [](DNSQuestion& /* dq */, const DNSName& newName) { (void) newName; });
+ d_lw->registerMember<uint16_t (DNSQuestion::*)>("qtype", [](const DNSQuestion& dq) -> uint16_t { return dq.qtype; }, [](DNSQuestion& /* dq */, uint16_t newType) { (void) newType; });
+ d_lw->registerMember<bool (DNSQuestion::*)>("isTcp", [](const DNSQuestion& dq) -> bool { return dq.isTcp; }, [](DNSQuestion& /* dq */, bool newTcp) { (void) newTcp; });
+ d_lw->registerMember<const ComboAddress (DNSQuestion::*)>("localaddr", [](const DNSQuestion& dq) -> const ComboAddress& { return dq.local; }, [](DNSQuestion& /* dq */, const ComboAddress& newLocal) { (void) newLocal; });
+ d_lw->registerMember<const ComboAddress (DNSQuestion::*)>("remoteaddr", [](const DNSQuestion& dq) -> const ComboAddress& { return dq.remote; }, [](DNSQuestion& /* dq */, const ComboAddress& newRemote) { (void) newRemote; });
+ d_lw->registerMember<uint8_t (DNSQuestion::*)>("validationState", [](const DNSQuestion& dq) -> uint8_t { return (vStateIsBogus(dq.validationState) ? /* in order not to break older scripts */ static_cast<uint8_t>(255) : static_cast<uint8_t>(dq.validationState)); }, [](DNSQuestion& /* dq */, uint8_t newState) { (void) newState; });
+ d_lw->registerMember<vState (DNSQuestion::*)>("detailedValidationState", [](const DNSQuestion& dq) -> vState { return dq.validationState; }, [](DNSQuestion& /* dq */, vState newState) { (void) newState; });
d_lw->registerMember<bool (DNSQuestion::*)>("variable", [](const DNSQuestion& dq) -> bool { return dq.variable; }, [](DNSQuestion& dq, bool newVariable) { dq.variable = newVariable; });
d_lw->registerMember<bool (DNSQuestion::*)>("wantsRPZ", [](const DNSQuestion& dq) -> bool { return dq.wantsRPZ; }, [](DNSQuestion& dq, bool newWantsRPZ) { dq.wantsRPZ = newWantsRPZ; });
}
return result;
},
- [](EDNSOptionView& option, uint16_t newSize) { (void) newSize; });
+ [](EDNSOptionView& /* option */, uint16_t newSize) { (void) newSize; });
d_lw->registerFunction<std::string(EDNSOptionView::*)()>("getContent", [](const EDNSOptionView& option) {
if (option.values.empty()) {
return std::string();
}
return std::string(option.values.at(0).content, option.values.at(0).size); });
- d_lw->registerFunction<string(DNSRecord::*)()>("getContent", [](const DNSRecord& dr) { return dr.d_content->getZoneRepresentation(); });
+ d_lw->registerFunction<string(DNSRecord::*)()>("getContent", [](const DNSRecord& dr) { return dr.getContent()->getZoneRepresentation(); });
d_lw->registerFunction<boost::optional<ComboAddress>(DNSRecord::*)()>("getCA", [](const DNSRecord& dr) {
boost::optional<ComboAddress> ret;
- if(auto rec = std::dynamic_pointer_cast<ARecordContent>(dr.d_content))
+ if(auto rec = getRR<ARecordContent>(dr))
ret=rec->getCA(53);
- else if(auto aaaarec = std::dynamic_pointer_cast<AAAARecordContent>(dr.d_content))
+ else if(auto aaaarec = getRR<AAAARecordContent>(dr))
ret=aaaarec->getCA(53);
return ret;
});
d_lw->registerFunction<const ProxyProtocolValue, std::string()>("getContent", [](const ProxyProtocolValue& value) { return value.content; });
d_lw->registerFunction<const ProxyProtocolValue, uint8_t()>("getType", [](const ProxyProtocolValue& value) { return value.type; });
- d_lw->registerFunction<void(DNSRecord::*)(const std::string&)>("changeContent", [](DNSRecord& dr, const std::string& newContent) { dr.d_content = DNSRecordContent::mastermake(dr.d_type, QClass::IN, newContent); });
+ d_lw->registerFunction<void(DNSRecord::*)(const std::string&)>("changeContent", [](DNSRecord& dr, const std::string& newContent) { dr.setContent(DNSRecordContent::mastermake(dr.d_type, QClass::IN, newContent)); });
d_lw->registerFunction("addAnswer", &DNSQuestion::addAnswer);
d_lw->registerFunction("addRecord", &DNSQuestion::addRecord);
d_lw->registerFunction("getRecords", &DNSQuestion::getRecords);
return getRegisteredName(dname);
});
- d_lw->registerMember<const DNSName (PolicyEvent::*)>("qname", [](const PolicyEvent& event) -> const DNSName& { return event.qname; }, [](PolicyEvent& event, const DNSName& newName) { (void) newName; });
- d_lw->registerMember<uint16_t (PolicyEvent::*)>("qtype", [](const PolicyEvent& event) -> uint16_t { return event.qtype.getCode(); }, [](PolicyEvent& event, uint16_t newType) { (void) newType; });
- d_lw->registerMember<bool (PolicyEvent::*)>("isTcp", [](const PolicyEvent& event) -> bool { return event.isTcp; }, [](PolicyEvent& event, bool newTcp) { (void) newTcp; });
- d_lw->registerMember<const ComboAddress (PolicyEvent::*)>("remote", [](const PolicyEvent& event) -> const ComboAddress& { return event.remote; }, [](PolicyEvent& event, const ComboAddress& newRemote) { (void) newRemote; });
+ d_lw->registerMember<const DNSName (PolicyEvent::*)>("qname", [](const PolicyEvent& event) -> const DNSName& { return event.qname; }, [](PolicyEvent& /* event */, const DNSName& newName) { (void) newName; });
+ d_lw->registerMember<uint16_t (PolicyEvent::*)>("qtype", [](const PolicyEvent& event) -> uint16_t { return event.qtype.getCode(); }, [](PolicyEvent& /* event */, uint16_t newType) { (void) newType; });
+ d_lw->registerMember<bool (PolicyEvent::*)>("isTcp", [](const PolicyEvent& event) -> bool { return event.isTcp; }, [](PolicyEvent& /* event */, bool newTcp) { (void) newTcp; });
+ d_lw->registerMember<const ComboAddress (PolicyEvent::*)>("remote", [](const PolicyEvent& event) -> const ComboAddress& { return event.remote; }, [](PolicyEvent& /* event */, const ComboAddress& newRemote) { (void) newRemote; });
d_lw->registerMember("appliedPolicy", &PolicyEvent::appliedPolicy);
d_lw->registerFunction<void(PolicyEvent::*)(const std::string&)>("addPolicyTag", [](PolicyEvent& event, const std::string& tag) { if (event.policyTags) { event.policyTags->insert(tag); } });
d_lw->registerFunction<void(PolicyEvent::*)(const std::vector<std::pair<int, std::string> >&)>("setPolicyTags", [](PolicyEvent& event, const std::vector<std::pair<int, std::string> >& tags) {
dr.d_type = type;
dr.d_class = QClass::IN;
dr.d_place = DNSResourceRecord::Place(place);
- dr.d_content = DNSRecordContent::mastermake(type, QClass::IN, std::string(content, contentSize));
+ dr.setContent(DNSRecordContent::mastermake(type, QClass::IN, std::string(content, contentSize)));
ref->params.records.push_back(std::move(dr));
return true;
record->name = ref->insert(std::move(name))->c_str();
}
if (raw) {
- auto content = ref->insert(r.d_content->serialize(r.d_name, true));
+ auto content = ref->insert(r.getContent()->serialize(r.d_name, true));
record->content = content->data();
record->content_len = content->size();
}
else {
- auto content = ref->insert(r.d_content->getZoneRepresentation());
+ auto content = ref->insert(r.getContent()->getZoneRepresentation());
record->content = content->data();
record->content_len = content->size();
}
try {
DNSRecord& r = ref->handle.d_dq.currentRecords->at(i);
if (raw) {
- r.d_content = DNSRecordContent::deserialize(r.d_name, r.d_type, string(content, contentLen));
+ r.setContent(DNSRecordContent::deserialize(r.d_name, r.d_type, string(content, contentLen)));
}
else {
- r.d_content = DNSRecordContent::mastermake(r.d_type, QClass::IN, string(content, contentLen));
+ r.setContent(DNSRecordContent::mastermake(r.d_type, QClass::IN, string(content, contentLen)));
}
return true;
dr.d_class = QClass::IN;
dr.d_place = DNSResourceRecord::Place(place);
if (raw) {
- dr.d_content = DNSRecordContent::deserialize(dr.d_name, dr.d_type, string(content, contentLen));
+ dr.setContent(DNSRecordContent::deserialize(dr.d_name, dr.d_type, string(content, contentLen)));
}
else {
- dr.d_content = DNSRecordContent::mastermake(type, QClass::IN, string(content, contentLen));
+ dr.setContent(DNSRecordContent::mastermake(type, QClass::IN, string(content, contentLen)));
}
ref->handle.d_dq.currentRecords->push_back(std::move(dr));
}
}
-static bool tcpconnect(const struct timeval& now, const ComboAddress& ip, TCPOutConnectionManager::Connection& connection, bool& dnsOverTLS, const std::string& nsName)
+static bool tcpconnect(const ComboAddress& ip, TCPOutConnectionManager::Connection& connection, bool& dnsOverTLS, const std::string& nsName)
{
dnsOverTLS = SyncRes::s_dot_to_port_853 && ip.getPort() == 853;
if (context && !context->d_nsName.empty()) {
nsName = context->d_nsName.toStringNoDot();
}
- isNew = tcpconnect(*now, ip, connection, dnsOverTLS, nsName);
+ isNew = tcpconnect(ip, connection, dnsOverTLS, nsName);
ret = tcpsendrecv(ip, connection, localip, vpacket, len, buf);
#ifdef HAVE_FSTRM
if (fstrmQEnabled) {
extern __thread size_t t_mainStackSize;
#endif /* HAVE_FIBER_SANITIZER */
+#ifdef HAVE_FIBER_SANITIZER
static inline void notifyStackSwitch(const void* startOfStack, size_t stackSize)
{
-#ifdef HAVE_FIBER_SANITIZER
__sanitizer_start_switch_fiber(nullptr, startOfStack, stackSize);
-#endif /* HAVE_FIBER_SANITIZER */
}
+#else
+static inline void notifyStackSwitch(const void* /* startOfStack */, size_t /* stackSize */)
+{}
+#endif /* HAVE_FIBER_SANITIZER */
static inline void notifyStackSwitchToKernel()
{
*
* \param fp A pointer to an open FILE object
*/
-size_t NegCache::doDump(int fd, size_t maxCacheEntries)
+size_t NegCache::doDump(int fd, size_t maxCacheEntries, time_t now)
{
int newfd = dup(fd);
if (newfd == -1) {
}
fprintf(fp.get(), "; negcache dump follows\n;\n");
- struct timeval now;
- Utility::gettimeofday(&now, nullptr);
-
size_t ret = 0;
size_t shard = 0;
auto& sidx = m->d_map.get<SequenceTag>();
for (const NegCacheEntry& ne : sidx) {
ret++;
- int64_t ttl = ne.d_ttd - now.tv_sec;
+ int64_t ttl = ne.d_ttd - now;
fprintf(fp.get(), "%s %" PRId64 " IN %s VIA %s ; (%s) origttl=%" PRIu32 " ss=%hu\n", ne.d_name.toString().c_str(), ttl, ne.d_qtype.toString().c_str(), ne.d_auth.toString().c_str(), vStateToString(ne.d_validationState).c_str(), ne.d_orig_ttl, ne.d_servedStale);
for (const auto& rec : ne.authoritySOA.records) {
- fprintf(fp.get(), "%s %" PRId64 " IN %s %s ; (%s)\n", rec.d_name.toString().c_str(), ttl, DNSRecordContent::NumberToType(rec.d_type).c_str(), rec.d_content->getZoneRepresentation().c_str(), vStateToString(ne.d_validationState).c_str());
+ fprintf(fp.get(), "%s %" PRId64 " IN %s %s ; (%s)\n", rec.d_name.toString().c_str(), ttl, DNSRecordContent::NumberToType(rec.d_type).c_str(), rec.getContent()->getZoneRepresentation().c_str(), vStateToString(ne.d_validationState).c_str());
}
for (const auto& sig : ne.authoritySOA.signatures) {
- fprintf(fp.get(), "%s %" PRId64 " IN RRSIG %s ;\n", sig.d_name.toString().c_str(), ttl, sig.d_content->getZoneRepresentation().c_str());
+ fprintf(fp.get(), "%s %" PRId64 " IN RRSIG %s ;\n", sig.d_name.toString().c_str(), ttl, sig.getContent()->getZoneRepresentation().c_str());
}
for (const auto& rec : ne.DNSSECRecords.records) {
- fprintf(fp.get(), "%s %" PRId64 " IN %s %s ; (%s)\n", rec.d_name.toString().c_str(), ttl, DNSRecordContent::NumberToType(rec.d_type).c_str(), rec.d_content->getZoneRepresentation().c_str(), vStateToString(ne.d_validationState).c_str());
+ fprintf(fp.get(), "%s %" PRId64 " IN %s %s ; (%s)\n", rec.d_name.toString().c_str(), ttl, DNSRecordContent::NumberToType(rec.d_type).c_str(), rec.getContent()->getZoneRepresentation().c_str(), vStateToString(ne.d_validationState).c_str());
}
for (const auto& sig : ne.DNSSECRecords.signatures) {
- fprintf(fp.get(), "%s %" PRId64 " IN RRSIG %s ;\n", sig.d_name.toString().c_str(), ttl, sig.d_content->getZoneRepresentation().c_str());
+ fprintf(fp.get(), "%s %" PRId64 " IN RRSIG %s ;\n", sig.d_name.toString().c_str(), ttl, sig.getContent()->getZoneRepresentation().c_str());
}
}
}
size_t count(const DNSName& qname, QType qtype);
void prune(size_t maxEntries);
void clear();
- size_t doDump(int fd, size_t maxCacheEntries);
+ size_t doDump(int fd, size_t maxCacheEntries, time_t now = time(nullptr));
size_t wipe(const DNSName& name, bool subtree = false);
size_t wipeTyped(const DNSName& name, QType qtype);
size_t size() const;
}
public:
- void preRemoval(MapCombo::LockedContent& map, const NegCacheEntry& entry)
- {
- }
+ void preRemoval(MapCombo::LockedContent& /* map */, const NegCacheEntry& /* entry */) {}
};
std::mutex PersistentSBF::d_cachedir_mutex;
-void PersistentSBF::remove_tmp_files(const filesystem::path& p, std::lock_guard<std::mutex>& lock)
+void PersistentSBF::remove_tmp_files(const filesystem::path& p, std::lock_guard<std::mutex>& /* lock */)
{
Regex file_regex(d_prefix + ".*\\." + bf_suffix + "\\..{8}$");
for (filesystem::directory_iterator i(p); i != filesystem::directory_iterator(); ++i) {
thread_local std::unique_ptr<MT_t> MT; // the big MTasker
std::unique_ptr<MemRecursorCache> g_recCache;
std::unique_ptr<NegCache> g_negCache;
+std::unique_ptr<RecursorPacketCache> g_packetCache;
-thread_local std::unique_ptr<RecursorPacketCache> t_packetCache;
thread_local std::unique_ptr<FDMultiplexer> t_fdm;
thread_local std::unique_ptr<addrringbuf_t> t_remotes, t_servfailremotes, t_largeanswerremotes, t_bogusremotes;
thread_local std::unique_ptr<boost::circular_buffer<pair<DNSName, uint16_t>>> t_queryring, t_servfailqueryring, t_bogusqueryring;
thread_local std::unique_ptr<UDPClientSocks> t_udpclientsocks;
/* these two functions are used by LWRes */
-LWResult::Result asendto(const char* data, size_t len, int flags,
+LWResult::Result asendto(const char* data, size_t len, int /* flags */,
const ComboAddress& toaddr, uint16_t id, const DNSName& domain, uint16_t qtype, bool ecs, int* fd)
{
return LWResult::Result::Success;
}
-LWResult::Result arecvfrom(PacketBuffer& packet, int flags, const ComboAddress& fromaddr, size_t* d_len,
+LWResult::Result arecvfrom(PacketBuffer& packet, int /* flags */, const ComboAddress& fromaddr, size_t* d_len,
uint16_t id, const DNSName& domain, uint16_t qtype, int fd, const struct timeval* now)
{
static const unsigned int nearMissLimit = ::arg().asNum("spoof-nearmiss-max");
bool oldWantsRPZ = sr.getWantsRPZ();
sr.setWantsRPZ(false);
vector<DNSRecord> ans;
- res = sr.beginResolve(DNSName(spoofed.d_content->getZoneRepresentation()), qtype, QClass::IN, ans);
+ res = sr.beginResolve(DNSName(spoofed.getContent()->getZoneRepresentation()), qtype, QClass::IN, ans);
for (const auto& rec : ans) {
if (rec.d_place == DNSResourceRecord::ANSWER) {
ret.push_back(rec);
}
}
-static bool addRecordToPacket(DNSPacketWriter& pw, const DNSRecord& rec, uint32_t& minTTL, uint32_t ttlCap, const uint16_t maxAnswerSize)
+static bool addRecordToPacket(DNSPacketWriter& pw, const DNSRecord& rec, uint32_t& minTTL, uint32_t ttlCap, const uint16_t maxAnswerSize, bool& seenAuthSOA)
{
pw.startRecord(rec.d_name, rec.d_type, (rec.d_ttl > ttlCap ? ttlCap : rec.d_ttl), rec.d_class, rec.d_place);
+ if (rec.d_type == QType::SOA && rec.d_place == DNSResourceRecord::AUTHORITY) {
+ seenAuthSOA = true;
+ }
+
if (rec.d_type != QType::OPT) // their TTL ain't real
minTTL = min(minTTL, rec.d_ttl);
- rec.d_content->toPacket(pw);
+ rec.getContent()->toPacket(pw);
if (pw.size() > static_cast<size_t>(maxAnswerSize)) {
pw.rollback();
if (rec.d_place != DNSResourceRecord::ADDITIONAL) {
if (record.d_place == DNSResourceRecord::ANSWER || record.d_place == DNSResourceRecord::ADDITIONAL) {
// Create a string that represent a triplet of (qname, qtype and RR[type, name, content])
std::stringstream ss;
- ss << dname.toDNSStringLC() << ":" << qtype << ":" << qtype << ":" << record.d_type << ":" << record.d_name.toDNSStringLC() << ":" << record.d_content->getZoneRepresentation();
+ ss << dname.toDNSStringLC() << ":" << qtype << ":" << qtype << ":" << record.d_type << ":" << record.d_name.toDNSStringLC() << ":" << record.getContent()->getZoneRepresentation();
if (t_udrDBp && t_udrDBp->isUniqueResponse(ss.str())) {
if (g_udrLog) {
// This should also probably log to a dedicated file.
- SLOG(g_log << Logger::Notice << "Unique response observed: qname=" << dname << " qtype=" << QType(qtype) << " rrtype=" << QType(record.d_type) << " rrname=" << record.d_name << " rrcontent=" << record.d_content->getZoneRepresentation() << endl,
+ SLOG(g_log << Logger::Notice << "Unique response observed: qname=" << dname << " qtype=" << QType(qtype) << " rrtype=" << QType(record.d_type) << " rrname=" << record.d_name << " rrcontent=" << record.getContent()->getZoneRepresentation() << endl,
nodlogger->info(Logr::Debug, "New response observed",
"qtype", Logging::Loggable(QType(qtype)),
"rrtype", Logging::Loggable(QType(record.d_type)),
"rrname", Logging::Loggable(record.d_name),
- "rrcontent", Logging::Loggable(record.d_content->getZoneRepresentation())););
+ "rrcontent", Logging::Loggable(record.getContent()->getZoneRepresentation())););
}
ret = true;
}
if (auto rec = getRR<ARecordContent>(rr)) {
ComboAddress ipv4(rec->getCA());
memcpy(&prefix.sin6.sin6_addr.s6_addr[12], &ipv4.sin4.sin_addr.s_addr, sizeof(ipv4.sin4.sin_addr.s_addr));
- rr.d_content = std::make_shared<AAAARecordContent>(prefix);
+ rr.setContent(std::make_shared<AAAARecordContent>(prefix));
rr.d_type = QType::AAAA;
}
seenA = true;
DNSRecord rr;
rr.d_name = qname;
rr.d_type = QType::CNAME;
- rr.d_content = std::make_shared<CNAMERecordContent>(newquery);
+ rr.setContent(std::make_shared<CNAMERecordContent>(newquery));
ret.push_back(rr);
auto log = g_slog->withName("dns64")->withValues("method", Logging::Loggable("getPTR"));
// fclose by unique_ptr does implicit flush
}
+static uint32_t capPacketCacheTTL(const struct dnsheader& hdr, uint32_t ttl, bool seenAuthSOA)
+{
+ if (hdr.rcode == RCode::NXDomain || (hdr.rcode == RCode::NoError && hdr.ancount == 0 && seenAuthSOA)) {
+ ttl = std::min(ttl, SyncRes::s_packetcachenegativettl);
+ }
+ else if ((hdr.rcode != RCode::NoError && hdr.rcode != RCode::NXDomain) || (hdr.ancount == 0 && hdr.nscount == 0)) {
+ ttl = min(ttl, SyncRes::s_packetcacheservfailttl);
+ }
+ else {
+ ttl = std::min(ttl, SyncRes::s_packetcachettl);
+ }
+ return ttl;
+}
+
void startDoResolve(void* p)
{
auto dc = std::unique_ptr<DNSComboWriter>(reinterpret_cast<DNSComboWriter*>(p));
If we have a TTL cap, this value can't be larger than the
cap no matter what. */
uint32_t minTTL = dc->d_ttlCap;
+ bool seenAuthSOA = false;
sr.d_eventTrace = std::move(dc->d_eventTrace);
sr.setId(MT->getTid());
continue;
}
- if (!addRecordToPacket(pw, *i, minTTL, dc->d_ttlCap, maxanswersize)) {
+ if (!addRecordToPacket(pw, *i, minTTL, dc->d_ttlCap, maxanswersize, seenAuthSOA)) {
needCommit = false;
break;
}
#endif
}
- if (t_packetCache && !variableAnswer && !sr.wasVariable()) {
- const auto& hdr = pw.getHeader();
- if ((hdr->rcode != RCode::NoError && hdr->rcode != RCode::NXDomain) || (hdr->ancount == 0 && hdr->nscount == 0)) {
- minTTL = min(minTTL, SyncRes::s_packetcacheservfailttl);
- }
- minTTL = min(minTTL, SyncRes::s_packetcachettl);
- t_packetCache->insertResponsePacket(dc->d_tag, dc->d_qhash, std::move(dc->d_query), dc->d_mdp.d_qname,
+ if (g_packetCache && !variableAnswer && !sr.wasVariable()) {
+ minTTL = capPacketCacheTTL(*pw.getHeader(), minTTL, seenAuthSOA);
+ g_packetCache->insertResponsePacket(dc->d_tag, dc->d_qhash, std::move(dc->d_query), dc->d_mdp.d_qname,
dc->d_mdp.d_qtype, dc->d_mdp.d_qclass,
string((const char*)&*packet.begin(), packet.size()),
g_now.tv_sec,
string& response, uint32_t& qhash,
RecursorPacketCache::OptPBData& pbData, bool tcp, const ComboAddress& source, const ComboAddress& mappedSource)
{
- if (!t_packetCache) {
+ if (!g_packetCache) {
return false;
}
bool cacheHit = false;
vState valState;
if (qnameParsed) {
- cacheHit = t_packetCache->getResponsePacket(tag, data, qname, qtype, qclass, now.tv_sec, &response, &age, &valState, &qhash, &pbData, tcp);
+ cacheHit = g_packetCache->getResponsePacket(tag, data, qname, qtype, qclass, now.tv_sec, &response, &age, &valState, &qhash, &pbData, tcp);
}
else {
- cacheHit = t_packetCache->getResponsePacket(tag, data, qname, &qtype, &qclass, now.tv_sec, &response, &age, &valState, &qhash, &pbData, tcp);
+ cacheHit = g_packetCache->getResponsePacket(tag, data, qname, &qtype, &qclass, now.tv_sec, &response, &age, &valState, &qhash, &pbData, tcp);
}
if (cacheHit) {
t_Counters.at(rec::Counter::packetCacheHits)++;
t_Counters.at(rec::Counter::syncresqueries)++; // XXX
- ageDNSPacket(response, age);
if (response.length() >= sizeof(struct dnsheader)) {
- const struct dnsheader* dh = reinterpret_cast<const dnsheader*>(response.data());
- updateResponseStats(dh->rcode, source, response.length(), nullptr, 0);
- t_Counters.at(rec::ResponseStats::responseStats).submitResponse(qtype, response.length(), dh->rcode);
+ dnsheader_aligned dh_aligned(response.data());
+ ageDNSPacket(response, age, dh_aligned);
+ const auto* dhp = dh_aligned.get();
+ updateResponseStats(dhp->rcode, source, response.length(), nullptr, 0);
+ t_Counters.at(rec::ResponseStats::responseStats).submitResponse(qtype, response.length(), dhp->rcode);
}
// we assume 0 usec
return 0;
}
-static void handleNewUDPQuestion(int fd, FDMultiplexer::funcparam_t& var)
+static void handleNewUDPQuestion(int fd, FDMultiplexer::funcparam_t& /* var */)
{
ssize_t len;
static const size_t maxIncomingQuerySize = g_proxyProtocolACL.empty() ? 512 : (512 + g_proxyProtocolMaximumSize);
static void handleUDPServerResponse(int fd, FDMultiplexer::funcparam_t& var)
{
std::shared_ptr<PacketID> pid = boost::any_cast<std::shared_ptr<PacketID>>(var);
- ssize_t len;
PacketBuffer packet;
packet.resize(g_outgoingEDNSBufsize);
ComboAddress fromaddr;
socklen_t addrlen = sizeof(fromaddr);
- len = recvfrom(fd, &packet.at(0), packet.size(), 0, (sockaddr*)&fromaddr, &addrlen);
+ ssize_t len = recvfrom(fd, &packet.at(0), packet.size(), 0, reinterpret_cast<sockaddr*>(&fromaddr), &addrlen);
- if (len < (ssize_t)sizeof(dnsheader)) {
- if (len < 0)
- ; // cerr<<"Error on fd "<<fd<<": "<<stringerror()<<"\n";
- else {
- t_Counters.at(rec::Counter::serverParseError)++;
- if (g_logCommonErrors)
- SLOG(g_log << Logger::Error << "Unable to parse packet from remote UDP server " << fromaddr.toString() << ": packet smaller than DNS header" << endl,
- g_slogout->info(Logr::Error, "Unable to parse packet from remote UDP server", "from", Logging::Loggable(fromaddr)));
- }
+ const ssize_t signed_sizeof_sdnsheader = sizeof(dnsheader);
+ if (len < 0) {
+ // len < 0: error on socket
t_udpclientsocks->returnSocket(fd);
- PacketBuffer empty;
+ PacketBuffer empty;
MT_t::waiters_t::iterator iter = MT->d_waiters.find(pid);
- if (iter != MT->d_waiters.end())
+ if (iter != MT->d_waiters.end()) {
doResends(iter, pid, empty);
+ }
+ MT->sendEvent(pid, &empty); // this denotes error (does retry lookup using other NS)
+ return;
+ }
- MT->sendEvent(pid, &empty); // this denotes error (does lookup again.. at least L1 will be hot)
+ if (len < signed_sizeof_sdnsheader) {
+ // We have received a packet that cannot be a valid DNS packet, as it has no complete header
+ // Drop it, but continue to wait for other packets
+ t_Counters.at(rec::Counter::serverParseError)++;
+ if (g_logCommonErrors) {
+ SLOG(g_log << Logger::Error << "Unable to parse too short packet from remote UDP server " << fromaddr.toString() << ": packet smaller than DNS header" << endl,
+ g_slogout->info(Logr::Error, "Unable to parse too short packet from remote UDP server", "from", Logging::Loggable(fromaddr)));
+ }
return;
}
+ // We have at least a full header
packet.resize(len);
dnsheader dh;
memcpy(&dh, &packet.at(0), sizeof(dh));
}
else {
try {
- if (len > 12)
- pident->domain = DNSName(reinterpret_cast<const char*>(packet.data()), len, 12, false, &pident->type); // don't copy this from above - we need to do the actual read
+ if (len > signed_sizeof_sdnsheader) {
+ pident->domain = DNSName(reinterpret_cast<const char*>(packet.data()), len, static_cast<int>(sizeof(dnsheader)), false, &pident->type); // don't copy this from above - we need to do the actual read
+ }
+ else {
+ // len == sizeof(dnsheader), only header case
+ // We will do a full scan search later to see if we can match this reply even without a domain
+ pident->domain.clear();
+ pident->type = 0;
+ }
}
catch (std::exception& e) {
+ // Parse error, continue waiting for other packets
t_Counters.at(rec::Counter::serverParseError)++; // won't be fed to lwres.cc, so we have to increment
SLOG(g_log << Logger::Warning << "Error in packet from remote nameserver " << fromaddr.toStringWithPort() << ": " << e.what() << endl,
g_slogudpin->error(Logr::Warning, e.what(), "Error in packet from remote nameserver", "from", Logging::Loggable(fromaddr)));
}
}
- MT_t::waiters_t::iterator iter = MT->d_waiters.find(pident);
- if (iter != MT->d_waiters.end()) {
- doResends(iter, pident, packet);
+ if (!pident->domain.empty()) {
+ MT_t::waiters_t::iterator iter = MT->d_waiters.find(pident);
+ if (iter != MT->d_waiters.end()) {
+ doResends(iter, pident, packet);
+ }
}
retryWithName:
- if (!MT->sendEvent(pident, &packet)) {
+ if (pident->domain.empty() || MT->sendEvent(pident, &packet) == 0) {
/* we did not find a match for this response, something is wrong */
// we do a full scan for outstanding queries on unexpected answers. not too bad since we only accept them on the right port number, which is hard enough to guess
size_t zoneIdx;
std::string dumpFile;
- std::shared_ptr<SOARecordContent> sr = nullptr;
+ std::shared_ptr<const SOARecordContent> sr = nullptr;
try {
std::string seedFile;
struct luaConfigDelayedThreads
{
// Please make sure that the tuple below only contains value types since they are used as parameters in a thread ct
- std::vector<std::tuple<std::vector<ComboAddress>, boost::optional<DNSFilterEngine::Policy>, bool, uint32_t, size_t, TSIGTriplet, size_t, ComboAddress, uint16_t, uint32_t, std::shared_ptr<SOARecordContent>, std::string>> rpzPrimaryThreads;
+ std::vector<std::tuple<std::vector<ComboAddress>, boost::optional<DNSFilterEngine::Policy>, bool, uint32_t, size_t, TSIGTriplet, size_t, ComboAddress, uint16_t, uint32_t, std::shared_ptr<const SOARecordContent>, std::string>> rpzPrimaryThreads;
};
void loadRecursorLuaConfig(const std::string& fname, luaConfigDelayedThreads& delayedThreads, ProxyMapping&);
}
std::thread t(nod::NODDB::startHousekeepingThread, t_nodDBp, std::this_thread::get_id());
t.detach();
- g_nod_pbtag = ::arg()["new-domain-pb-tag"];
}
if (g_udrEnabled) {
uint32_t num_cells = ::arg().asNum("unique-response-db-size");
}
std::thread t(nod::UniqueResponseDB::startHousekeepingThread, t_udrDBp, std::this_thread::get_id());
t.detach();
- g_udr_pbtag = ::arg()["unique-response-pb-tag"];
}
}
// Setup Unique DNS Response subsystem
g_udrEnabled = ::arg().mustDo("unique-response-tracking");
g_udrLog = ::arg().mustDo("unique-response-log");
+ g_nod_pbtag = ::arg()["new-domain-pb-tag"];
+ g_udr_pbtag = ::arg()["unique-response-pb-tag"];
}
#endif /* NOD_ENABLED */
::arg().set("quiet") = g_quiet ? "" : "no";
}
-static void checkLinuxIPv6Limits(Logr::log_t log)
+static void checkLinuxIPv6Limits([[maybe_unused]] Logr::log_t log)
{
#ifdef __linux__
string line;
uint64_t cacheMisses = g_recCache->cacheMisses;
uint64_t cacheSize = g_recCache->size();
auto rc_stats = g_recCache->stats();
- double r = rc_stats.second == 0 ? 0.0 : (100.0 * rc_stats.first / rc_stats.second);
+ auto pc_stats = g_packetCache ? g_packetCache->stats() : std::pair<uint64_t, uint64_t>{0, 0};
+ double rrc = rc_stats.second == 0 ? 0.0 : (100.0 * rc_stats.first / rc_stats.second);
+ double rpc = pc_stats.second == 0 ? 0.0 : (100.0 * pc_stats.first / pc_stats.second);
uint64_t negCacheSize = g_negCache->size();
auto taskPushes = getTaskPushes();
auto taskExpired = getTaskExpired();
auto taskSize = getTaskSize();
- uint64_t pcSize = broadcastAccFunction<uint64_t>(pleaseGetPacketCacheSize);
- uint64_t pcHits = broadcastAccFunction<uint64_t>(pleaseGetPacketCacheHits);
+ uint64_t pcSize = g_packetCache ? g_packetCache->size() : 0;
+ uint64_t pcHits = g_packetCache ? g_packetCache->getHits() : 0;
auto log = g_slog->withName("stats");
if (qcounter > 0 && (cacheHits + cacheMisses) > 0 && syncresqueries > 0 && outqueries > 0) {
if (!g_slogStructured) {
g_log << Logger::Notice << "stats: " << qcounter << " questions, " << cacheSize << " cache entries, " << negCacheSize << " negative entries, " << ratePercentage(cacheHits, cacheHits + cacheMisses) << "% cache hits" << endl;
- g_log << Logger::Notice << "stats: cache contended/acquired " << rc_stats.first << '/' << rc_stats.second << " = " << r << '%' << endl;
+ g_log << Logger::Notice << "stats: record cache contended/acquired " << rc_stats.first << '/' << rc_stats.second << " = " << rrc << '%' << endl;
+ g_log << Logger::Notice << "stats: packet cache contended/acquired " << pc_stats.first << '/' << pc_stats.second << " = " << rpc << '%' << endl;
g_log << Logger::Notice << "stats: throttle map: "
<< SyncRes::getThrottledServersSize() << ", ns speeds: "
"record-cache-hitratio-perc", Logging::Loggable(ratePercentage(cacheHits, cacheHits + cacheMisses)),
"record-cache-contended", Logging::Loggable(rc_stats.first),
"record-cache-acquired", Logging::Loggable(rc_stats.second),
- "record-cache-contended-perc", Logging::Loggable(r));
+ "record-cache-contended-perc", Logging::Loggable(rrc),
+ "packetcache-contended", Logging::Loggable(pc_stats.first),
+ "packetcache-acquired", Logging::Loggable(pc_stats.second),
+ "packetcache-contended-perc", Logging::Loggable(rpc));
log->info(Logr::Info, m,
"throttle-entries", Logging::Loggable(SyncRes::getThrottledServersSize()),
"nsspeed-entries", Logging::Loggable(SyncRes::getNSSpeedsSize()),
template ProxyMappingStats_t broadcastAccFunction(const std::function<ProxyMappingStats_t*()>& fun);
template RemoteLoggerStats_t broadcastAccFunction(const std::function<RemoteLoggerStats_t*()>& fun);
-static int serviceMain(int argc, char* argv[], Logr::log_t log)
+static int serviceMain(int /* argc */, char* /* argv */[], Logr::log_t log)
{
g_log.setName(g_programname);
g_log.disableSyslog(::arg().mustDo("disable-syslog"));
g_maxNSEC3Iterations = ::arg().asNum("nsec3-max-iterations");
g_maxCacheEntries = ::arg().asNum("max-cache-entries");
- g_maxPacketCacheEntries = ::arg().asNum("max-packetcache-entries");
luaConfigDelayedThreads delayedLuaThreads;
try {
SyncRes::s_maxnegttl = ::arg().asNum("max-negative-ttl");
SyncRes::s_maxbogusttl = ::arg().asNum("max-cache-bogus-ttl");
SyncRes::s_maxcachettl = max(::arg().asNum("max-cache-ttl"), 15);
+
SyncRes::s_packetcachettl = ::arg().asNum("packetcache-ttl");
- // Cap the packetcache-servfail-ttl to the packetcache-ttl
- uint32_t packetCacheServFailTTL = ::arg().asNum("packetcache-servfail-ttl");
- SyncRes::s_packetcacheservfailttl = (packetCacheServFailTTL > SyncRes::s_packetcachettl) ? SyncRes::s_packetcachettl : packetCacheServFailTTL;
+ // Cap the packetcache-servfail-ttl and packetcache-negative-ttl to packetcache-ttl
+ SyncRes::s_packetcacheservfailttl = std::min(static_cast<unsigned int>(::arg().asNum("packetcache-servfail-ttl")), SyncRes::s_packetcachettl);
+ SyncRes::s_packetcachenegativettl = std::min(static_cast<unsigned int>(::arg().asNum("packetcache-negative-ttl")), SyncRes::s_packetcachettl);
+
SyncRes::s_serverdownmaxfails = ::arg().asNum("server-down-max-fails");
SyncRes::s_serverdownthrottletime = ::arg().asNum("server-down-throttle-time");
SyncRes::s_nonresolvingnsmaxfails = ::arg().asNum("non-resolving-ns-max-fails");
return RecThreadInfo::runThreads(log);
}
-static void handlePipeRequest(int fd, FDMultiplexer::funcparam_t& var)
+static void handlePipeRequest(int fd, FDMultiplexer::funcparam_t& /* var */)
{
ThreadMSG* tmsg = nullptr;
delete tmsg;
}
-static void handleRCC(int fd, FDMultiplexer::funcparam_t& var)
+static void handleRCC(int fd, FDMultiplexer::funcparam_t& /* var */)
{
auto log = g_slog->withName("control");
try {
t_Counters.updateSnap(now, g_regressionTestMode);
// Below are the tasks that run for every recursorThread, including handler and taskThread
- if (t_packetCache) {
- static thread_local PeriodicTask packetCacheTask{"packetCacheTask", 5};
- packetCacheTask.runIfDue(now, []() {
- size_t sz = g_maxPacketCacheEntries / (RecThreadInfo::numWorkers() + RecThreadInfo::numDistributors());
- t_packetCache->setMaxSize(sz); // g_maxPacketCacheEntries might have changed by rec_control
- t_packetCache->doPruneTo(sz);
- });
- }
static thread_local PeriodicTask pruneTCPTask{"pruneTCPTask", 5};
pruneTCPTask.runIfDue(now, [now]() {
});
}
else if (info.isHandler()) {
+ if (g_packetCache) {
+ static PeriodicTask packetCacheTask{"packetCacheTask", 5};
+ packetCacheTask.runIfDue(now, []() {
+ g_packetCache->doPruneTo(g_maxPacketCacheEntries);
+ });
+ }
static PeriodicTask recordCachePruneTask{"RecordCachePruneTask", 5};
recordCachePruneTask.runIfDue(now, []() {
g_recCache->doPrune(g_maxCacheEntries);
}
}
- if (!::arg().mustDo("disable-packetcache") && (threadInfo.isDistributor() || threadInfo.isWorker())) {
- // Only enable packet cache for thread processing queries from the outside world
- t_packetCache = std::make_unique<RecursorPacketCache>(g_maxPacketCacheEntries / (RecThreadInfo::numWorkers() + RecThreadInfo::numDistributors()));
- }
-
#ifdef NOD_ENABLED
if (threadInfo.isWorker())
setupNODThread(log);
::arg().set("max-negative-ttl", "maximum number of seconds to keep a negative cached entry in memory") = "3600";
::arg().set("max-cache-bogus-ttl", "maximum number of seconds to keep a Bogus (positive or negative) cached entry in memory") = "3600";
::arg().set("max-cache-ttl", "maximum number of seconds to keep a cached entry in memory") = "86400";
- ::arg().set("packetcache-ttl", "maximum number of seconds to keep a cached entry in packetcache") = "3600";
+ ::arg().set("packetcache-ttl", "maximum number of seconds to keep a cached entry in packetcache") = "86400";
::arg().set("max-packetcache-entries", "maximum number of entries to keep in the packetcache") = "500000";
::arg().set("packetcache-servfail-ttl", "maximum number of seconds to keep a cached servfail entry in packetcache") = "60";
+ ::arg().set("packetcache-negative-ttl", "maximum number of seconds to keep a cached NxDomain or NoData entry in packetcache") = "60";
::arg().set("server-id", "Returned when queried for 'id.server' TXT or NSID, defaults to hostname, set custom or 'disabled'") = "";
::arg().set("stats-ringbuffer-entries", "maximum number of packets to store statistics for") = "10000";
::arg().set("version-string", "string reported on version.pdns or version.bind") = fullVersionString();
::arg().set("ecs-add-for", "List of client netmasks for which EDNS Client Subnet will be added") = "0.0.0.0/0, ::/0, " LOCAL_NETS_INVERSE;
::arg().set("ecs-scope-zero-address", "Address to send to allow-listed authoritative servers for incoming queries with ECS prefix-length source of 0") = "";
::arg().setSwitch("use-incoming-edns-subnet", "Pass along received EDNS Client Subnet information") = "no";
- ::arg().setSwitch("pdns-distributes-queries", "If PowerDNS itself should distribute queries over threads") = "yes";
+ ::arg().setSwitch("pdns-distributes-queries", "If PowerDNS itself should distribute queries over threads") = "no";
::arg().setSwitch("root-nx-trust", "If set, believe that an NXDOMAIN from the root means the TLD does not exist") = "yes";
::arg().setSwitch("any-to-tcp", "Answer ANY queries with tc=1, shunting to TCP") = "no";
::arg().setSwitch("lowercase-outgoing", "Force outgoing questions to lowercase") = "no";
::arg().set("include-dir", "Include *.conf files from this directory") = "";
::arg().set("security-poll-suffix", "Domain name from which to query security update notifications") = "secpoll.powerdns.com.";
+#ifdef SO_REUSEPORT
+ ::arg().setSwitch("reuseport", "Enable SO_REUSEPORT allowing multiple recursors processes to listen to 1 address") = "yes";
+#else
::arg().setSwitch("reuseport", "Enable SO_REUSEPORT allowing multiple recursors processes to listen to 1 address") = "no";
-
+#endif
::arg().setSwitch("snmp-agent", "If set, register as an SNMP agent") = "no";
::arg().set("snmp-master-socket", "If set and snmp-agent is set, the socket to use to register to the SNMP daemon (deprecated)") = "";
::arg().set("snmp-daemon-socket", "If set and snmp-agent is set, the socket to use to register to the SNMP daemon") = "";
::arg().setSwitch("nothing-below-nxdomain", "When an NXDOMAIN exists in cache for a name with fewer labels than the qname, send NXDOMAIN without doing a lookup (see RFC 8020)") = "dnssec";
::arg().set("max-generate-steps", "Maximum number of $GENERATE steps when loading a zone from a file") = "0";
::arg().set("max-include-depth", "Maximum nested $INCLUDE depth when loading a zone from a file") = "20";
+
::arg().set("record-cache-shards", "Number of shards in the record cache") = "1024";
+ ::arg().set("packetcache-shards", "Number of shards in the packet cache") = "1024";
+
::arg().set("refresh-on-ttl-perc", "If a record is requested from the cache and only this % of original TTL remains, refetch") = "0";
::arg().set("record-cache-locked-ttl-perc", "Replace records in record cache only after this % of original TTL has passed") = "0";
g_recCache = std::make_unique<MemRecursorCache>(::arg().asNum("record-cache-shards"));
g_negCache = std::make_unique<NegCache>(::arg().asNum("record-cache-shards") / 8);
+ if (!::arg().mustDo("disable-packetcache")) {
+ g_maxPacketCacheEntries = ::arg().asNum("max-packetcache-entries");
+ g_packetCache = std::make_unique<RecursorPacketCache>(g_maxPacketCacheEntries, ::arg().asNum("packetcache-shards"));
+ }
ret = serviceMain(argc, argv, startupLog);
}
return broadcastAccFunction<string>([=] { return pleaseUseNewTraceRegex(begin != end ? *begin : "", fileno); });
}
-static uint64_t* pleaseWipePacketCache(const DNSName& canon, bool subtree, uint16_t qtype)
-{
- return new uint64_t(t_packetCache ? t_packetCache->doWipePacketCache(canon, qtype, subtree) : 0);
-}
-
struct WipeCacheResult wipeCaches(const DNSName& canon, bool subtree, uint16_t qtype)
{
struct WipeCacheResult res;
try {
res.record_count = g_recCache->doWipeCache(canon, subtree, qtype);
// scanbuild complains here about an allocated function object that is being leaked. Needs investigation
- res.packet_count = broadcastAccFunction<uint64_t>([=] { return pleaseWipePacketCache(canon, subtree, qtype); });
+ if (g_packetCache) {
+ res.packet_count = g_packetCache->doWipePacketCache(canon, qtype, subtree);
+ }
res.negative_record_count = g_negCache->wipe(canon, subtree);
if (g_aggressiveNSECCache) {
g_aggressiveNSECCache->removeZoneInfo(canon, subtree);
typedef MTasker<std::shared_ptr<PacketID>, PacketBuffer, PacketIDCompare> MT_t;
extern thread_local std::unique_ptr<MT_t> MT; // the big MTasker
-extern thread_local std::unique_ptr<RecursorPacketCache> t_packetCache;
+extern std::unique_ptr<RecursorPacketCache> g_packetCache;
using RemoteLoggerStats_t = std::unordered_map<std::string, RemoteLoggerInterface::Stats>;
switch (record.d_type) {
case QType::A: {
- const auto& content = dynamic_cast<const ARecordContent&>(*(record.d_content));
- ComboAddress data = content.getCA();
+ const auto& content = getRR<ARecordContent>(record);
+ if (!content) {
+ return;
+ }
+ ComboAddress data = content->getCA();
pbf_rr.add_bytes(static_cast<protozero::pbf_tag_type>(pdns::ProtoZero::Message::RRField::rdata), reinterpret_cast<const char*>(&data.sin4.sin_addr.s_addr), sizeof(data.sin4.sin_addr.s_addr));
break;
}
case QType::AAAA: {
- const auto& content = dynamic_cast<const AAAARecordContent&>(*(record.d_content));
- ComboAddress data = content.getCA();
+ const auto& content = getRR<AAAARecordContent>(record);
+ if (!content) {
+ return;
+ }
+ ComboAddress data = content->getCA();
pbf_rr.add_bytes(static_cast<protozero::pbf_tag_type>(pdns::ProtoZero::Message::RRField::rdata), reinterpret_cast<const char*>(&data.sin6.sin6_addr.s6_addr), sizeof(data.sin6.sin6_addr.s6_addr));
break;
}
case QType::CNAME: {
- const auto& content = dynamic_cast<const CNAMERecordContent&>(*(record.d_content));
- add(content.getTarget().toString());
+ const auto& content = getRR<CNAMERecordContent>(record);
+ if (!content) {
+ return;
+ }
+ add(content->getTarget().toString());
break;
}
case QType::TXT: {
- const auto& content = dynamic_cast<const TXTRecordContent&>(*(record.d_content));
- add(content.d_text);
+ const auto& content = getRR<TXTRecordContent>(record);
+ if (!content) {
+ return;
+ }
+ add(content->d_text);
break;
}
case QType::NS: {
- const auto& content = dynamic_cast<const NSRecordContent&>(*(record.d_content));
- add(content.getNS().toString());
+ const auto& content = getRR<NSRecordContent>(record);
+ if (!content) {
+ return;
+ }
+ add(content->getNS().toString());
break;
}
case QType::PTR: {
- const auto& content = dynamic_cast<const PTRRecordContent&>(*(record.d_content));
- add(content.getContent().toString());
+ const auto& content = getRR<PTRRecordContent>(record);
+ if (!content) {
+ return;
+ }
+ add(content->getContent().toString());
break;
}
case QType::MX: {
- const auto& content = dynamic_cast<const MXRecordContent&>(*(record.d_content));
- add(content.d_mxname.toString());
+ const auto& content = getRR<MXRecordContent>(record);
+ if (!content) {
+ return;
+ }
+ add(content->d_mxname.toString());
break;
}
case QType::SPF: {
- const auto& content = dynamic_cast<const SPFRecordContent&>(*(record.d_content));
- add(content.getText());
+ const auto& content = getRR<SPFRecordContent>(record);
+ if (!content) {
+ return;
+ }
+ add(content->getText());
break;
}
case QType::SRV: {
- const auto& content = dynamic_cast<const SRVRecordContent&>(*(record.d_content));
- add(content.d_target.toString());
+ const auto& content = getRR<SRVRecordContent>(record);
+ if (!content) {
+ return;
+ }
+ add(content->d_target.toString());
break;
}
default:
static const oid rcode14AnswersOID[] = {RECURSOR_STATS_OID, 143};
static const oid rcode15AnswersOID[] = {RECURSOR_STATS_OID, 144};
+static const oid packetCacheContendedOID[] = {RECURSOR_STATS_OID, 145};
+static const oid packetCacheAcquiredOID[] = {RECURSOR_STATS_OID, 146};
+
static std::unordered_map<oid, std::string> s_statsMap;
/* We are never called for a GETNEXT if it's registered as a
/* a instance handler also only hands us one request at a time, so
we don't need to loop over a list of requests; we'll only get one. */
-static int handleCounter64Stats(netsnmp_mib_handler* handler,
+static int handleCounter64Stats(netsnmp_mib_handler* /* handler */,
netsnmp_handler_registration* reginfo,
netsnmp_agent_request_info* reqinfo,
netsnmp_request_info* requests)
}
}
-static int handleDisabledCounter64Stats(netsnmp_mib_handler* handler,
+static int handleDisabledCounter64Stats(netsnmp_mib_handler* /* handler */,
netsnmp_handler_registration* reginfo,
netsnmp_agent_request_info* reqinfo,
netsnmp_request_info* requests)
registerCounter64Stat("non-resolving-nameserver-entries", nonResolvingNameserverEntriesOID, OID_LENGTH(nonResolvingNameserverEntriesOID));
registerCounter64Stat("maintenance-usec", maintenanceUSecOID, OID_LENGTH(maintenanceUSecOID));
registerCounter64Stat("maintenance-calls", maintenanceCallsOID, OID_LENGTH(maintenanceCallsOID));
+ registerCounter64Stat("packetcache-contended", packetCacheContendedOID, OID_LENGTH(packetCacheContendedOID));
+ registerCounter64Stat("packetcache-acquired", packetCacheAcquiredOID, OID_LENGTH(packetCacheAcquiredOID));
#define RCODE(num) registerCounter64Stat("auth-" + RCode::to_short_s(num) + "-answers", rcode##num##AnswersOID, OID_LENGTH(rcode##num##AnswersOID))
RCODE(0);
{
d_fd = -1;
}
- bool handleTCPReadResult(int fd, ssize_t bytes)
+ bool handleTCPReadResult(int /* fd */, ssize_t bytes)
{
if (bytes == 0) {
/* EOF */
TCPIOHandlerStateChange(pid->lowState, newstate, pid);
}
-void checkFastOpenSysctl(bool active, Logr::log_t log)
+void checkFastOpenSysctl([[maybe_unused]] bool active, [[maybe_unused]] Logr::log_t log)
{
#ifdef __linux__
string line;
// Potentially the two fields below could be merged into a single map. ATM it is not clear to me
// if that would make the code easier to read.
std::map<pair<DNSName, QType>, vector<DNSRecord>> d_all;
- std::map<pair<DNSName, QType>, vector<shared_ptr<RRSIGRecordContent>>> d_sigs;
+ std::map<pair<DNSName, QType>, vector<shared_ptr<const RRSIGRecordContent>>> d_sigs;
// Maybe use a SuffixMatchTree?
std::set<DNSName> d_delegations;
found->second.push_back(rr);
}
else {
- vector<shared_ptr<RRSIGRecordContent>> sigsrr;
+ vector<shared_ptr<const RRSIGRecordContent>> sigsrr;
sigsrr.push_back(rr);
d_sigs.insert({sigkey, sigsrr});
}
case QType::RRSIG:
break;
default: {
- vector<shared_ptr<RRSIGRecordContent>> sigsrr;
+ vector<shared_ptr<const RRSIGRecordContent>> sigsrr;
auto it = d_sigs.find(key);
if (it != d_sigs.end()) {
sigsrr = it->second;
return g_aggressiveNSECCache->dumpToFile(fp, now);
}
-static uint64_t* pleaseDump(int fd)
-{
- return new uint64_t(t_packetCache ? t_packetCache->doDump(fd) : 0);
-}
-
static uint64_t* pleaseDumpEDNSMap(int fd)
{
return new uint64_t(SyncRes::doEDNSDump(fd));
}
// Does not follow the generic dump to file pattern, has a more complex lambda
-static RecursorControlChannel::Answer doDumpCache(int s)
+static RecursorControlChannel::Answer doDumpCache(int socket)
{
- auto fdw = getfd(s);
+ auto fdw = getfd(socket);
if (fdw < 0) {
return {1, "Error opening dump file for writing: " + stringerror() + "\n"};
}
uint64_t total = 0;
try {
- int fd = fdw;
- total = g_recCache->doDump(fd, g_maxCacheEntries.load()) + g_negCache->doDump(fd, g_maxCacheEntries.load() / 8) + broadcastAccFunction<uint64_t>([fd] { return pleaseDump(fd); }) + dumpAggressiveNSECCache(fd);
+ total += g_recCache->doDump(fdw, g_maxCacheEntries.load());
+ total += g_negCache->doDump(fdw, g_maxCacheEntries.load() / 8);
+ total += g_packetCache ? g_packetCache->doDump(fdw) : 0;
+ total += dumpAggressiveNSECCache(fdw);
}
catch (...) {
}
}
try {
g_maxPacketCacheEntries = pdns::checked_stoi<uint32_t>(*begin);
+ g_packetCache->setMaxSize(g_maxPacketCacheEntries);
return "New max packetcache entries: " + std::to_string(g_maxPacketCacheEntries) + "\n";
}
catch (const std::exception& e) {
return g_recCache->cacheMisses;
}
-uint64_t* pleaseGetPacketCacheSize()
-{
- return new uint64_t(t_packetCache ? t_packetCache->size() : 0);
-}
-
-static uint64_t* pleaseGetPacketCacheBytes()
-{
- return new uint64_t(t_packetCache ? t_packetCache->bytes() : 0);
-}
-
-static uint64_t doGetPacketCacheSize()
-{
- return broadcastAccFunction<uint64_t>(pleaseGetPacketCacheSize);
-}
-
-static uint64_t doGetPacketCacheBytes()
-{
- return broadcastAccFunction<uint64_t>(pleaseGetPacketCacheBytes);
-}
-
-uint64_t* pleaseGetPacketCacheHits()
-{
- return new uint64_t(t_packetCache ? t_packetCache->d_hits : 0);
-}
-
-static uint64_t doGetPacketCacheHits()
-{
- return broadcastAccFunction<uint64_t>(pleaseGetPacketCacheHits);
-}
-
-static uint64_t* pleaseGetPacketCacheMisses()
-{
- return new uint64_t(t_packetCache ? t_packetCache->d_misses : 0);
-}
-
-static uint64_t doGetPacketCacheMisses()
-{
- return broadcastAccFunction<uint64_t>(pleaseGetPacketCacheMisses);
-}
-
static uint64_t doGetMallocated()
{
// this turned out to be broken
addGetStat("record-cache-contended", []() { return g_recCache->stats().first; });
addGetStat("record-cache-acquired", []() { return g_recCache->stats().second; });
- addGetStat("packetcache-hits", doGetPacketCacheHits);
- addGetStat("packetcache-misses", doGetPacketCacheMisses);
- addGetStat("packetcache-entries", doGetPacketCacheSize);
- addGetStat("packetcache-bytes", doGetPacketCacheBytes);
+ addGetStat("packetcache-hits", [] { return g_packetCache ? g_packetCache->getHits() : 0; });
+ addGetStat("packetcache-misses", [] { return g_packetCache ? g_packetCache->getMisses() : 0; });
+ addGetStat("packetcache-entries", [] { return g_packetCache ? g_packetCache->size() : 0; });
+ addGetStat("packetcache-bytes", [] { return g_packetCache ? g_packetCache->bytes() : 0; });
+ addGetStat("packetcache-contended", []() { return g_packetCache ? g_packetCache->stats().first : 0; });
+ addGetStat("packetcache-acquired", []() { return g_packetCache ? g_packetCache->stats().second : 0; });
addGetStat("aggressive-nsec-cache-entries", []() { return g_aggressiveNSECCache ? g_aggressiveNSECCache->getEntriesCount() : 0; });
addGetStat("aggressive-nsec-cache-nsec-hits", []() { return g_aggressiveNSECCache ? g_aggressiveNSECCache->getNSECHits() : 0; });
unsigned int RecursorPacketCache::s_refresh_ttlperc{0};
-int RecursorPacketCache::doWipePacketCache(const DNSName& name, uint16_t qtype, bool subtree)
+void RecursorPacketCache::setShardSizes(size_t shardSize)
{
- int count = 0;
- auto& idx = d_packetCache.get<NameTag>();
- for (auto iter = idx.lower_bound(name); iter != idx.end();) {
- if (subtree) {
- if (!iter->d_name.isPartOf(name)) { // this is case insensitive
- break;
- }
- }
- else {
- if (iter->d_name != name)
- break;
+ for (auto& shard : d_maps) {
+ auto lock = shard.lock();
+ lock->d_shardSize = shardSize;
+ }
+}
+
+uint64_t RecursorPacketCache::size() const
+{
+ uint64_t count = 0;
+ for (const auto& map : d_maps) {
+ count += map.d_entriesCount;
+ }
+ return count;
+}
+
+uint64_t RecursorPacketCache::bytes()
+{
+ uint64_t sum = 0;
+ for (auto& shard : d_maps) {
+ auto lock = shard.lock();
+ for (const auto& entry : lock->d_map) {
+ sum += sizeof(entry) + entry.d_packet.length() + 4;
}
+ }
+ return sum;
+}
- if (qtype == 0xffff || iter->d_type == qtype) {
- iter = idx.erase(iter);
- count++;
+uint64_t RecursorPacketCache::getHits()
+{
+ uint64_t sum = 0;
+ for (auto& shard : d_maps) {
+ auto lock = shard.lock();
+ sum += lock->d_hits;
+ }
+ return sum;
+}
+
+uint64_t RecursorPacketCache::getMisses()
+{
+ uint64_t sum = 0;
+ for (auto& shard : d_maps) {
+ auto lock = shard.lock();
+ sum += lock->d_misses;
+ }
+ return sum;
+}
+
+pair<uint64_t, uint64_t> RecursorPacketCache::stats()
+{
+ uint64_t contended = 0;
+ uint64_t acquired = 0;
+ for (auto& shard : d_maps) {
+ auto content = shard.lock();
+ contended += content->d_contended_count;
+ acquired += content->d_acquired_count;
+ }
+ return {contended, acquired};
+}
+
+uint64_t RecursorPacketCache::doWipePacketCache(const DNSName& name, uint16_t qtype, bool subtree)
+{
+ uint64_t count = 0;
+ for (auto& map : d_maps) {
+ auto shard = map.lock();
+ auto& idx = shard->d_map.get<NameTag>();
+ for (auto iter = idx.lower_bound(name); iter != idx.end();) {
+ if (subtree) {
+ if (!iter->d_name.isPartOf(name)) { // this is case insensitive
+ break;
+ }
+ }
+ else {
+ if (iter->d_name != name) {
+ break;
+ }
+ }
+ if (qtype == 0xffff || iter->d_type == qtype) {
+ iter = idx.erase(iter);
+ map.d_entriesCount--;
+ count++;
+ }
+ else {
+ ++iter;
+ }
}
- else
- ++iter;
}
return count;
}
return queryMatches(iter->d_query, queryPacket, qname, optionsToSkip);
}
-bool RecursorPacketCache::checkResponseMatches(std::pair<packetCache_t::index<HashTag>::type::iterator, packetCache_t::index<HashTag>::type::iterator> range, const std::string& queryPacket, const DNSName& qname, uint16_t qtype, uint16_t qclass, time_t now, std::string* responsePacket, uint32_t* age, vState* valState, OptPBData* pbdata)
+bool RecursorPacketCache::checkResponseMatches(MapCombo::LockedContent& shard, std::pair<packetCache_t::index<HashTag>::type::iterator, packetCache_t::index<HashTag>::type::iterator> range, const std::string& queryPacket, const DNSName& qname, uint16_t qtype, uint16_t qclass, time_t now, std::string* responsePacket, uint32_t* age, vState* valState, OptPBData* pbdata)
{
for (auto iter = range.first; iter != range.second; ++iter) {
// the possibility is VERY real that we get hits that are not right - birthday paradox
if (now < iter->d_ttd) { // it is right, it is fresh!
*age = static_cast<uint32_t>(now - iter->d_creation);
// we know ttl is > 0
- uint32_t ttl = static_cast<uint32_t>(iter->d_ttd - now);
+ auto ttl = static_cast<uint32_t>(iter->d_ttd - now);
if (s_refresh_ttlperc > 0 && !iter->d_submitted) {
const uint32_t deadline = iter->getOrigTTL() * s_refresh_ttlperc / 100;
const bool almostExpired = ttl <= deadline;
responsePacket->replace(sizeof(dnsheader), wirelength, queryPacket, sizeof(dnsheader), wirelength);
}
- d_hits++;
- moveCacheItemToBack<SequencedTag>(d_packetCache, iter);
+ shard.d_hits++;
+ moveCacheItemToBack<SequencedTag>(shard.d_map, iter);
if (pbdata != nullptr) {
if (iter->d_pbdata) {
return true;
}
- else {
- // We used to move the item to the front of "the to be deleted" sequence,
- // but we very likely will update the entry very soon, so leave it
- d_misses++;
- break;
- }
+ // We used to move the item to the front of "the to be deleted" sequence,
+ // but we very likely will update the entry very soon, so leave it
+ shard.d_misses++;
+ break;
}
return false;
}
-bool RecursorPacketCache::getResponsePacket(unsigned int tag, const std::string& queryPacket, time_t now,
- std::string* responsePacket, uint32_t* age, uint32_t* qhash)
-{
- DNSName qname;
- uint16_t qtype, qclass;
- vState valState;
- return getResponsePacket(tag, queryPacket, qname, &qtype, &qclass, now, responsePacket, age, &valState, qhash, nullptr, false);
-}
-
-bool RecursorPacketCache::getResponsePacket(unsigned int tag, const std::string& queryPacket, const DNSName& qname, uint16_t qtype, uint16_t qclass, time_t now,
- std::string* responsePacket, uint32_t* age, uint32_t* qhash)
-{
- vState valState;
- return getResponsePacket(tag, queryPacket, qname, qtype, qclass, now, responsePacket, age, &valState, qhash, nullptr, false);
-}
-
static const std::unordered_set<uint16_t> s_skipOptions = {EDNSOptionCode::ECS, EDNSOptionCode::COOKIE};
bool RecursorPacketCache::getResponsePacket(unsigned int tag, const std::string& queryPacket, const DNSName& qname, uint16_t qtype, uint16_t qclass, time_t now,
std::string* responsePacket, uint32_t* age, vState* valState, uint32_t* qhash, OptPBData* pbdata, bool tcp)
{
*qhash = canHashPacket(queryPacket, s_skipOptions);
- const auto& idx = d_packetCache.get<HashTag>();
+ auto& map = getMap(tag, *qhash, tcp);
+ auto shard = map.lock();
+ const auto& idx = shard->d_map.get<HashTag>();
auto range = idx.equal_range(std::tie(tag, *qhash, tcp));
if (range.first == range.second) {
- d_misses++;
+ shard->d_misses++;
return false;
}
- return checkResponseMatches(range, queryPacket, qname, qtype, qclass, now, responsePacket, age, valState, pbdata);
+ return checkResponseMatches(*shard, range, queryPacket, qname, qtype, qclass, now, responsePacket, age, valState, pbdata);
}
bool RecursorPacketCache::getResponsePacket(unsigned int tag, const std::string& queryPacket, DNSName& qname, uint16_t* qtype, uint16_t* qclass, time_t now,
std::string* responsePacket, uint32_t* age, vState* valState, uint32_t* qhash, OptPBData* pbdata, bool tcp)
{
*qhash = canHashPacket(queryPacket, s_skipOptions);
- const auto& idx = d_packetCache.get<HashTag>();
+ auto& map = getMap(tag, *qhash, tcp);
+ auto shard = map.lock();
+ const auto& idx = shard->d_map.get<HashTag>();
auto range = idx.equal_range(std::tie(tag, *qhash, tcp));
if (range.first == range.second) {
- d_misses++;
+ shard->d_misses++;
return false;
}
- qname = DNSName(queryPacket.c_str(), queryPacket.length(), sizeof(dnsheader), false, qtype, qclass, 0);
+ qname = DNSName(queryPacket.c_str(), static_cast<int>(queryPacket.length()), sizeof(dnsheader), false, qtype, qclass);
- return checkResponseMatches(range, queryPacket, qname, *qtype, *qclass, now, responsePacket, age, valState, pbdata);
+ return checkResponseMatches(*shard, range, queryPacket, qname, *qtype, *qclass, now, responsePacket, age, valState, pbdata);
}
void RecursorPacketCache::insertResponsePacket(unsigned int tag, uint32_t qhash, std::string&& query, const DNSName& qname, uint16_t qtype, uint16_t qclass, std::string&& responsePacket, time_t now, uint32_t ttl, const vState& valState, OptPBData&& pbdata, bool tcp)
{
- auto& idx = d_packetCache.get<HashTag>();
+ auto& map = getMap(tag, qhash, tcp);
+ auto shard = map.lock();
+ auto& idx = shard->d_map.get<HashTag>();
auto range = idx.equal_range(std::tie(tag, qhash, tcp));
auto iter = range.first;
continue;
}
- moveCacheItemToBack<SequencedTag>(d_packetCache, iter);
+ moveCacheItemToBack<SequencedTag>(shard->d_map, iter);
iter->d_packet = std::move(responsePacket);
iter->d_query = std::move(query);
iter->d_ttd = now + ttl;
return;
}
- struct Entry e(qname, qtype, qclass, std::move(responsePacket), std::move(query), tcp, qhash, now + ttl, now, tag, valState);
+ struct Entry entry(qname, qtype, qclass, std::move(responsePacket), std::move(query), tcp, qhash, now + ttl, now, tag, valState);
if (pbdata) {
- e.d_pbdata = std::move(*pbdata);
+ entry.d_pbdata = std::move(*pbdata);
}
- d_packetCache.insert(e);
+ shard->d_map.insert(entry);
+ map.d_entriesCount++;
- if (d_packetCache.size() > d_maxSize) {
- auto& seq_idx = d_packetCache.get<SequencedTag>();
+ if (shard->d_map.size() > shard->d_shardSize) {
+ auto& seq_idx = shard->d_map.get<SequencedTag>();
seq_idx.erase(seq_idx.begin());
+ map.d_entriesCount--;
}
+ assert(map.d_entriesCount == shard->d_map.size()); // XXX
}
-uint64_t RecursorPacketCache::bytes() const
-{
- uint64_t sum = 0;
- for (const auto& e : d_packetCache) {
- sum += sizeof(e) + e.d_packet.length() + 4;
- }
- return sum;
-}
-
-void RecursorPacketCache::doPruneTo(size_t maxCached)
+void RecursorPacketCache::doPruneTo(size_t maxSize)
{
- pruneCollection<SequencedTag>(d_packetCache, maxCached);
+ size_t cacheSize = size();
+ pruneMutexCollectionsVector<SequencedTag>(*this, d_maps, maxSize, cacheSize);
}
-uint64_t RecursorPacketCache::doDump(int fd)
+uint64_t RecursorPacketCache::doDump(int file)
{
- auto fp = std::unique_ptr<FILE, int (*)(FILE*)>(fdopen(dup(fd), "w"), fclose);
- if (!fp) { // dup probably failed
+ int fdupped = dup(file);
+ if (fdupped == -1) {
+ return 0;
+ }
+ auto filePtr = std::unique_ptr<FILE, decltype(&fclose)>(fdopen(fdupped, "w"), fclose);
+ if (!filePtr) {
+ close(fdupped);
return 0;
}
- fprintf(fp.get(), "; main packet cache dump from thread follows\n;\n");
-
- const auto& sidx = d_packetCache.get<SequencedTag>();
uint64_t count = 0;
time_t now = time(nullptr);
- for (const auto& i : sidx) {
- count++;
- try {
- fprintf(fp.get(), "%s %" PRId64 " %s ; tag %d %s\n", i.d_name.toString().c_str(), static_cast<int64_t>(i.d_ttd - now), DNSRecordContent::NumberToType(i.d_type).c_str(), i.d_tag, i.d_tcp ? "tcp" : "udp");
- }
- catch (...) {
- fprintf(fp.get(), "; error printing '%s'\n", i.d_name.empty() ? "EMPTY" : i.d_name.toString().c_str());
+ size_t shardNum = 0;
+ size_t min = std::numeric_limits<size_t>::max();
+ size_t max = 0;
+ uint64_t maxSize = 0;
+
+ for (auto& shard : d_maps) {
+ auto lock = shard.lock();
+ const auto& sidx = lock->d_map.get<SequencedTag>();
+ const auto shardSize = lock->d_map.size();
+ fprintf(filePtr.get(), "; packetcache shard %zu; size %zu/%zu\n", shardNum, shardSize, lock->d_shardSize);
+ min = std::min(min, shardSize);
+ max = std::max(max, shardSize);
+ maxSize += lock->d_shardSize;
+ shardNum++;
+ for (const auto& entry : sidx) {
+ count++;
+ try {
+ fprintf(filePtr.get(), "%s %" PRId64 " %s ; tag %d %s\n", entry.d_name.toString().c_str(), static_cast<int64_t>(entry.d_ttd - now), DNSRecordContent::NumberToType(entry.d_type).c_str(), entry.d_tag, entry.d_tcp ? "tcp" : "udp");
+ }
+ catch (...) {
+ fprintf(filePtr.get(), "; error printing '%s'\n", entry.d_name.empty() ? "EMPTY" : entry.d_name.toString().c_str());
+ }
}
}
+ fprintf(filePtr.get(), "; packetcache size: %" PRIu64 "/%" PRIu64 " shards: %zu min/max shard size: %zu/%zu\n", size(), maxSize, d_maps.size(), min, max);
return count;
}
#include "packetcache.hh"
#include "validate.hh"
+#include "lock.hh"
+#include "stat_t.hh"
#ifdef HAVE_CONFIG_H
#include "config.h"
using namespace ::boost::multi_index;
-//! Stores whole packets, ready for lobbing back at the client. Not threadsafe.
-/* Note: we store answers as value AND KEY, and with careful work, we make sure that
- you can use a query as a key too. But query and answer must compare as identical!
-
- This precludes doing anything smart with EDNS directly from the packet */
class RecursorPacketCache : public PacketCache
{
public:
std::string d_response;
bool d_tagged;
};
- typedef boost::optional<PBData> OptPBData;
+ using OptPBData = boost::optional<PBData>;
- RecursorPacketCache(size_t maxsize) :
- d_maxSize(maxsize)
+ RecursorPacketCache(size_t maxsize, size_t shards = 1024) :
+ d_maps(shards)
{
+ setMaxSize(maxsize);
+ }
+
+ bool getResponsePacket(unsigned int tag, const std::string& queryPacket, time_t now,
+ std::string* responsePacket, uint32_t* age, uint32_t* qhash)
+ {
+ DNSName qname;
+ uint16_t qtype{0};
+ uint16_t qclass{0};
+ vState valState{vState::Indeterminate};
+ return getResponsePacket(tag, queryPacket, qname, &qtype, &qclass, now, responsePacket, age, &valState, qhash, nullptr, false);
+ }
+
+ bool getResponsePacket(unsigned int tag, const std::string& queryPacket, const DNSName& qname, uint16_t qtype, uint16_t qclass, time_t now,
+ std::string* responsePacket, uint32_t* age, uint32_t* qhash)
+ {
+ vState valState{vState::Indeterminate};
+ return getResponsePacket(tag, queryPacket, qname, qtype, qclass, now, responsePacket, age, &valState, qhash, nullptr, false);
}
- bool getResponsePacket(unsigned int tag, const std::string& queryPacket, time_t now, std::string* responsePacket, uint32_t* age, uint32_t* qhash);
- bool getResponsePacket(unsigned int tag, const std::string& queryPacket, const DNSName& qname, uint16_t qtype, uint16_t qclass, time_t now, std::string* responsePacket, uint32_t* age, uint32_t* qhash);
bool getResponsePacket(unsigned int tag, const std::string& queryPacket, const DNSName& qname, uint16_t qtype, uint16_t qclass, time_t now, std::string* responsePacket, uint32_t* age, vState* valState, uint32_t* qhash, OptPBData* pbdata, bool tcp);
bool getResponsePacket(unsigned int tag, const std::string& queryPacket, DNSName& qname, uint16_t* qtype, uint16_t* qclass, time_t now, std::string* responsePacket, uint32_t* age, vState* valState, uint32_t* qhash, OptPBData* pbdata, bool tcp);
void insertResponsePacket(unsigned int tag, uint32_t qhash, std::string&& query, const DNSName& qname, uint16_t qtype, uint16_t qclass, std::string&& responsePacket, time_t now, uint32_t ttl, const vState& valState, OptPBData&& pbdata, bool tcp);
- void doPruneTo(size_t maxSize = 250000);
- uint64_t doDump(int fd);
- int doWipePacketCache(const DNSName& name, uint16_t qtype = 0xffff, bool subtree = false);
+ void doPruneTo(size_t maxSize);
+ uint64_t doDump(int file);
+ uint64_t doWipePacketCache(const DNSName& name, uint16_t qtype = 0xffff, bool subtree = false);
- void setMaxSize(size_t sz)
+ void setMaxSize(size_t size)
{
- d_maxSize = sz;
- }
-
- uint64_t size() const
- {
- return d_packetCache.size();
+ if (size < d_maps.size()) {
+ size = d_maps.size();
+ }
+ setShardSizes(size / d_maps.size());
}
- uint64_t bytes() const;
- uint64_t d_hits{0};
- uint64_t d_misses{0};
+ [[nodiscard]] uint64_t size() const;
+ [[nodiscard]] uint64_t bytes();
+ [[nodiscard]] uint64_t getHits();
+ [[nodiscard]] uint64_t getMisses();
+ [[nodiscard]] pair<uint64_t, uint64_t> stats();
private:
- struct HashTag
- {
- };
- struct NameTag
- {
- };
struct Entry
{
Entry(const DNSName& qname, uint16_t qtype, uint16_t qclass, std::string&& packet, std::string&& query, bool tcp,
}
};
+ struct HashTag
+ {
+ };
+ struct NameTag
+ {
+ };
struct SequencedTag
{
};
- typedef multi_index_container<
- Entry,
- indexed_by<
- hashed_non_unique<tag<HashTag>,
- composite_key<Entry,
- member<Entry, uint32_t, &Entry::d_tag>,
- member<Entry, uint32_t, &Entry::d_qhash>,
- member<Entry, bool, &Entry::d_tcp>>>,
- sequenced<tag<SequencedTag>>,
- ordered_non_unique<tag<NameTag>, member<Entry, DNSName, &Entry::d_name>, CanonDNSNameCompare>>>
- packetCache_t;
-
- packetCache_t d_packetCache;
- size_t d_maxSize;
+ using packetCache_t = multi_index_container<Entry,
+ indexed_by<hashed_non_unique<tag<HashTag>,
+ composite_key<Entry,
+ member<Entry, uint32_t, &Entry::d_tag>,
+ member<Entry, uint32_t, &Entry::d_qhash>,
+ member<Entry, bool, &Entry::d_tcp>>>,
+ sequenced<tag<SequencedTag>>,
+ ordered_non_unique<tag<NameTag>, member<Entry, DNSName, &Entry::d_name>, CanonDNSNameCompare>>>;
+
+ struct MapCombo
+ {
+ MapCombo() = default;
+ MapCombo(const MapCombo&) = delete;
+ MapCombo& operator=(const MapCombo&) = delete;
+ struct LockedContent
+ {
+ packetCache_t d_map;
+ size_t d_shardSize{0};
+ uint64_t d_hits{0};
+ uint64_t d_misses{0};
+ uint64_t d_contended_count{0};
+ uint64_t d_acquired_count{0};
+ void invalidate() {}
+ };
+ pdns::stat_t d_entriesCount{0};
+
+ LockGuardedTryHolder<MapCombo::LockedContent> lock()
+ {
+ auto locked = d_content.try_lock();
+ if (!locked.owns_lock()) {
+ locked.lock();
+ ++locked->d_contended_count;
+ }
+ ++locked->d_acquired_count;
+ return locked;
+ }
+
+ private:
+ LockGuarded<LockedContent> d_content;
+ };
+
+ vector<MapCombo> d_maps;
+
+ static size_t combine(unsigned int tag, uint32_t hash, bool tcp)
+ {
+ size_t ret = 0;
+ boost::hash_combine(ret, tag);
+ boost::hash_combine(ret, hash);
+ boost::hash_combine(ret, tcp);
+ return ret;
+ }
+
+ MapCombo& getMap(unsigned int tag, uint32_t hash, bool tcp)
+ {
+ return d_maps.at(combine(tag, hash, tcp) % d_maps.size());
+ }
+
+ [[nodiscard]] const MapCombo& getMap(unsigned int tag, uint32_t hash, bool tcp) const
+ {
+ return d_maps.at(combine(tag, hash, tcp) % d_maps.size());
+ }
static bool qrMatch(const packetCache_t::index<HashTag>::type::iterator& iter, const std::string& queryPacket, const DNSName& qname, uint16_t qtype, uint16_t qclass);
- bool checkResponseMatches(std::pair<packetCache_t::index<HashTag>::type::iterator, packetCache_t::index<HashTag>::type::iterator> range, const std::string& queryPacket, const DNSName& qname, uint16_t qtype, uint16_t qclass, time_t now, std::string* responsePacket, uint32_t* age, vState* valState, OptPBData* pbdata);
+ bool checkResponseMatches(MapCombo::LockedContent& shard, std::pair<packetCache_t::index<HashTag>::type::iterator, packetCache_t::index<HashTag>::type::iterator> range, const std::string& queryPacket, const DNSName& qname, uint16_t qtype, uint16_t qclass, time_t now, std::string* responsePacket, uint32_t* age, vState* valState, OptPBData* pbdata);
+
+ void setShardSizes(size_t shardSize);
+
+public:
+ void preRemoval(MapCombo::LockedContent& /* map */, const Entry& /* entry */)
+ {
+ }
};
size_t MemRecursorCache::size() const
{
size_t count = 0;
- for (const auto& map : d_maps) {
- count += map.d_entriesCount;
+ for (const auto& shard : d_maps) {
+ count += shard.d_entriesCount;
}
return count;
}
pair<uint64_t, uint64_t> MemRecursorCache::stats()
{
- uint64_t c = 0, a = 0;
- for (auto& mc : d_maps) {
- auto content = mc.lock();
- c += content->d_contended_count;
- a += content->d_acquired_count;
- }
- return pair<uint64_t, uint64_t>(c, a);
+ uint64_t contended = 0;
+ uint64_t acquired = 0;
+ for (auto& shard : d_maps) {
+ auto lockedShard = shard.lock();
+ contended += lockedShard->d_contended_count;
+ acquired += lockedShard->d_acquired_count;
+ }
+ return {contended, acquired};
}
size_t MemRecursorCache::ecsIndexSize()
{
// XXX!
size_t count = 0;
- for (auto& mc : d_maps) {
- auto content = mc.lock();
- count += content->d_ecsIndex.size();
+ for (auto& shard : d_maps) {
+ auto lockedShard = shard.lock();
+ count += lockedShard->d_ecsIndex.size();
}
return count;
}
size_t MemRecursorCache::bytes()
{
size_t ret = 0;
- for (auto& mc : d_maps) {
- auto m = mc.lock();
- for (const auto& i : m->d_map) {
+ for (auto& shard : d_maps) {
+ auto lockedShard = shard.lock();
+ for (const auto& entry : lockedShard->d_map) {
ret += sizeof(struct CacheEntry);
- ret += i.d_qname.toString().length();
- for (const auto& record : i.d_records) {
+ ret += entry.d_qname.toString().length();
+ for (const auto& record : entry.d_records) {
ret += sizeof(record); // XXX WRONG we don't know the stored size!
}
}
}
}
-time_t MemRecursorCache::handleHit(MapCombo::LockedContent& content, MemRecursorCache::OrderedTagIterator_t& entry, const DNSName& qname, uint32_t& origTTL, vector<DNSRecord>* res, vector<std::shared_ptr<RRSIGRecordContent>>* signatures, std::vector<std::shared_ptr<DNSRecord>>* authorityRecs, bool* variable, boost::optional<vState>& state, bool* wasAuth, DNSName* fromAuthZone, ComboAddress* fromAuthIP)
+time_t MemRecursorCache::handleHit(MapCombo::LockedContent& content, MemRecursorCache::OrderedTagIterator_t& entry, const DNSName& qname, uint32_t& origTTL, vector<DNSRecord>* res, vector<std::shared_ptr<const RRSIGRecordContent>>* signatures, std::vector<std::shared_ptr<DNSRecord>>* authorityRecs, bool* variable, boost::optional<vState>& state, bool* wasAuth, DNSName* fromAuthZone, ComboAddress* fromAuthIP)
{
// MUTEX SHOULD BE ACQUIRED (as indicated by the reference to the content which is protected by a lock)
time_t ttd = entry->d_ttd;
origTTL = entry->d_orig_ttl;
- if (variable && (!entry->d_netmask.empty() || entry->d_rtag)) {
+ if (variable != nullptr && (!entry->d_netmask.empty() || entry->d_rtag)) {
*variable = true;
}
- if (res) {
+ if (res != nullptr) {
res->reserve(res->size() + entry->d_records.size());
- for (const auto& k : entry->d_records) {
- DNSRecord dr;
- dr.d_name = qname;
- dr.d_type = entry->d_qtype;
- dr.d_class = QClass::IN;
- dr.d_content = k;
+ for (const auto& record : entry->d_records) {
+ DNSRecord result;
+ result.d_name = qname;
+ result.d_type = entry->d_qtype;
+ result.d_class = QClass::IN;
+ result.setContent(record);
// coverity[store_truncates_time_t]
- dr.d_ttl = static_cast<uint32_t>(entry->d_ttd);
- dr.d_place = DNSResourceRecord::ANSWER;
- res->push_back(std::move(dr));
+ result.d_ttl = static_cast<uint32_t>(entry->d_ttd);
+ result.d_place = DNSResourceRecord::ANSWER;
+ res->push_back(std::move(result));
}
}
- if (signatures) {
+ if (signatures != nullptr) {
signatures->insert(signatures->end(), entry->d_signatures.begin(), entry->d_signatures.end());
}
- if (authorityRecs) {
+ if (authorityRecs != nullptr) {
authorityRecs->insert(authorityRecs->end(), entry->d_authorityRecs.begin(), entry->d_authorityRecs.end());
}
updateDNSSECValidationStateFromCache(state, entry->d_state);
- if (wasAuth) {
+ if (wasAuth != nullptr) {
*wasAuth = *wasAuth && entry->d_auth;
}
- if (fromAuthZone) {
+ if (fromAuthZone != nullptr) {
*fromAuthZone = entry->d_authZone;
}
- if (fromAuthIP) {
+ if (fromAuthIP != nullptr) {
*fromAuthIP = entry->d_from;
}
return map.d_map.end();
}
-MemRecursorCache::Entries MemRecursorCache::getEntries(MapCombo::LockedContent& map, const DNSName& qname, const QType qt, const OptTag& rtag)
+MemRecursorCache::Entries MemRecursorCache::getEntries(MapCombo::LockedContent& map, const DNSName& qname, const QType /* qt */, const OptTag& rtag)
{
// MUTEX SHOULD BE ACQUIRED
if (!map.d_cachecachevalid || map.d_cachedqname != qname || map.d_cachedrtag != rtag) {
return ttl;
}
// returns -1 for no hits
-time_t MemRecursorCache::get(time_t now, const DNSName& qname, const QType qt, Flags flags, vector<DNSRecord>* res, const ComboAddress& who, const OptTag& routingTag, vector<std::shared_ptr<RRSIGRecordContent>>* signatures, std::vector<std::shared_ptr<DNSRecord>>* authorityRecs, bool* variable, vState* state, bool* wasAuth, DNSName* fromAuthZone, ComboAddress* fromAuthIP)
+time_t MemRecursorCache::get(time_t now, const DNSName& qname, const QType qt, Flags flags, vector<DNSRecord>* res, const ComboAddress& who, const OptTag& routingTag, vector<std::shared_ptr<const RRSIGRecordContent>>* signatures, std::vector<std::shared_ptr<DNSRecord>>* authorityRecs, bool* variable, vState* state, bool* wasAuth, DNSName* fromAuthZone, ComboAddress* fromAuthIP)
{
bool requireAuth = flags & RequireAuth;
bool refresh = flags & Refresh;
boost::optional<vState> cachedState{boost::none};
uint32_t origTTL;
- if (res) {
+ if (res != nullptr) {
res->clear();
}
const uint16_t qtype = qt.getCode();
- if (wasAuth) {
+ if (wasAuth != nullptr) {
// we might retrieve more than one entry, we need to set that to true
// so it will be set to false if at least one entry is not auth
*wasAuth = true;
}
- auto& mc = getMap(qname);
- auto map = mc.lock();
+ auto& shard = getMap(qname);
+ auto lockedShard = shard.lock();
/* If we don't have any netmask-specific entries at all, let's just skip this
to be able to use the nice d_cachecache hack. */
- if (qtype != QType::ANY && !map->d_ecsIndex.empty() && !routingTag) {
+ if (qtype != QType::ANY && !lockedShard->d_ecsIndex.empty() && !routingTag) {
if (qtype == QType::ADDR) {
time_t ret = -1;
- auto entryA = getEntryUsingECSIndex(*map, now, qname, QType::A, requireAuth, who, serveStale);
- if (entryA != map->d_map.end()) {
- ret = handleHit(*map, entryA, qname, origTTL, res, signatures, authorityRecs, variable, cachedState, wasAuth, fromAuthZone, fromAuthIP);
+ auto entryA = getEntryUsingECSIndex(*lockedShard, now, qname, QType::A, requireAuth, who, serveStale);
+ if (entryA != lockedShard->d_map.end()) {
+ ret = handleHit(*lockedShard, entryA, qname, origTTL, res, signatures, authorityRecs, variable, cachedState, wasAuth, fromAuthZone, fromAuthIP);
}
- auto entryAAAA = getEntryUsingECSIndex(*map, now, qname, QType::AAAA, requireAuth, who, serveStale);
- if (entryAAAA != map->d_map.end()) {
- time_t ttdAAAA = handleHit(*map, entryAAAA, qname, origTTL, res, signatures, authorityRecs, variable, cachedState, wasAuth, fromAuthZone, fromAuthIP);
+ auto entryAAAA = getEntryUsingECSIndex(*lockedShard, now, qname, QType::AAAA, requireAuth, who, serveStale);
+ if (entryAAAA != lockedShard->d_map.end()) {
+ time_t ttdAAAA = handleHit(*lockedShard, entryAAAA, qname, origTTL, res, signatures, authorityRecs, variable, cachedState, wasAuth, fromAuthZone, fromAuthIP);
if (ret > 0) {
ret = std::min(ret, ttdAAAA);
}
return ret > 0 ? (ret - now) : ret;
}
else {
- auto entry = getEntryUsingECSIndex(*map, now, qname, qtype, requireAuth, who, serveStale);
- if (entry != map->d_map.end()) {
- time_t ret = handleHit(*map, entry, qname, origTTL, res, signatures, authorityRecs, variable, cachedState, wasAuth, fromAuthZone, fromAuthIP);
+ auto entry = getEntryUsingECSIndex(*lockedShard, now, qname, qtype, requireAuth, who, serveStale);
+ if (entry != lockedShard->d_map.end()) {
+ time_t ret = handleHit(*lockedShard, entry, qname, origTTL, res, signatures, authorityRecs, variable, cachedState, wasAuth, fromAuthZone, fromAuthIP);
if (state && cachedState) {
*state = *cachedState;
}
}
if (routingTag) {
- auto entries = getEntries(*map, qname, qt, routingTag);
+ auto entries = getEntries(*lockedShard, qname, qt, routingTag);
bool found = false;
time_t ttd;
if (entries.first != entries.second) {
OrderedTagIterator_t firstIndexIterator;
for (auto i = entries.first; i != entries.second; ++i) {
- firstIndexIterator = map->d_map.project<OrderedTag>(i);
+ firstIndexIterator = lockedShard->d_map.project<OrderedTag>(i);
// When serving stale, we consider expired records
if (!i->isEntryUsable(now, serveStale)) {
- moveCacheItemToFront<SequencedTag>(map->d_map, firstIndexIterator);
+ moveCacheItemToFront<SequencedTag>(lockedShard->d_map, firstIndexIterator);
continue;
}
handleServeStaleBookkeeping(now, serveStale, firstIndexIterator);
- ttd = handleHit(*map, firstIndexIterator, qname, origTTL, res, signatures, authorityRecs, variable, cachedState, wasAuth, fromAuthZone, fromAuthIP);
+ ttd = handleHit(*lockedShard, firstIndexIterator, qname, origTTL, res, signatures, authorityRecs, variable, cachedState, wasAuth, fromAuthZone, fromAuthIP);
if (qt != QType::ANY && qt != QType::ADDR) { // normally if we have a hit, we are done
break;
}
}
// Try (again) without tag
- auto entries = getEntries(*map, qname, qt, boost::none);
+ auto entries = getEntries(*lockedShard, qname, qt, boost::none);
if (entries.first != entries.second) {
OrderedTagIterator_t firstIndexIterator;
time_t ttd;
for (auto i = entries.first; i != entries.second; ++i) {
- firstIndexIterator = map->d_map.project<OrderedTag>(i);
+ firstIndexIterator = lockedShard->d_map.project<OrderedTag>(i);
// When serving stale, we consider expired records
if (!i->isEntryUsable(now, serveStale)) {
- moveCacheItemToFront<SequencedTag>(map->d_map, firstIndexIterator);
+ moveCacheItemToFront<SequencedTag>(lockedShard->d_map, firstIndexIterator);
continue;
}
handleServeStaleBookkeeping(now, serveStale, firstIndexIterator);
- ttd = handleHit(*map, firstIndexIterator, qname, origTTL, res, signatures, authorityRecs, variable, cachedState, wasAuth, fromAuthZone, fromAuthIP);
+ ttd = handleHit(*lockedShard, firstIndexIterator, qname, origTTL, res, signatures, authorityRecs, variable, cachedState, wasAuth, fromAuthZone, fromAuthIP);
if (qt != QType::ANY && qt != QType::ADDR) { // normally if we have a hit, we are done
break;
return true;
}
-void MemRecursorCache::replace(time_t now, const DNSName& qname, const QType qt, const vector<DNSRecord>& content, const vector<shared_ptr<RRSIGRecordContent>>& signatures, const std::vector<std::shared_ptr<DNSRecord>>& authorityRecs, bool auth, const DNSName& authZone, boost::optional<Netmask> ednsmask, const OptTag& routingTag, vState state, boost::optional<ComboAddress> from, bool refresh)
+void MemRecursorCache::replace(time_t now, const DNSName& qname, const QType qt, const vector<DNSRecord>& content, const vector<shared_ptr<const RRSIGRecordContent>>& signatures, const std::vector<std::shared_ptr<DNSRecord>>& authorityRecs, bool auth, const DNSName& authZone, boost::optional<Netmask> ednsmask, const OptTag& routingTag, vState state, boost::optional<ComboAddress> from, bool refresh)
{
- auto& mc = getMap(qname);
- auto map = mc.lock();
+ auto& shard = getMap(qname);
+ auto lockedShard = shard.lock();
- map->d_cachecachevalid = false;
+ lockedShard->d_cachecachevalid = false;
if (ednsmask) {
ednsmask = ednsmask->getNormalized();
}
// We only store an ednsmask if we do not have a tag and we do have a mask.
auto key = std::make_tuple(qname, qt.getCode(), ednsmask ? routingTag : boost::none, (ednsmask && !routingTag) ? *ednsmask : Netmask());
bool isNew = false;
- cache_t::iterator stored = map->d_map.find(key);
- if (stored == map->d_map.end()) {
- stored = map->d_map.insert(CacheEntry(key, auth)).first;
- ++mc.d_entriesCount;
+ cache_t::iterator stored = lockedShard->d_map.find(key);
+ if (stored == lockedShard->d_map.end()) {
+ stored = lockedShard->d_map.insert(CacheEntry(key, auth)).first;
+ ++shard.d_entriesCount;
isNew = true;
}
/* don't bother building an ecsIndex if we don't have any netmask-specific entries */
if (!routingTag && ednsmask && !ednsmask->empty()) {
auto ecsIndexKey = std::make_tuple(qname, qt.getCode());
- auto ecsIndex = map->d_ecsIndex.find(ecsIndexKey);
- if (ecsIndex == map->d_ecsIndex.end()) {
- ecsIndex = map->d_ecsIndex.insert(ECSIndexEntry(qname, qt.getCode())).first;
+ auto ecsIndex = lockedShard->d_ecsIndex.find(ecsIndexKey);
+ if (ecsIndex == lockedShard->d_ecsIndex.end()) {
+ ecsIndex = lockedShard->d_ecsIndex.insert(ECSIndexEntry(qname, qt.getCode())).first;
}
ecsIndex->addMask(*ednsmask);
}
prior to calling this function, so the TTL actually holds a TTD. */
ce.d_ttd = min(maxTTD, static_cast<time_t>(i.d_ttl)); // XXX this does weird things if TTLs differ in the set
ce.d_orig_ttl = ce.d_ttd - now;
- ce.d_records.push_back(i.d_content);
+ ce.d_records.push_back(i.getContent());
}
if (!isNew) {
- moveCacheItemToBack<SequencedTag>(map->d_map, stored);
+ moveCacheItemToBack<SequencedTag>(lockedShard->d_map, stored);
}
ce.d_submitted = false;
ce.d_servedStale = 0;
- map->d_map.replace(stored, ce);
+ lockedShard->d_map.replace(stored, ce);
}
size_t MemRecursorCache::doWipeCache(const DNSName& name, bool sub, const QType qtype)
size_t count = 0;
if (!sub) {
- auto& mc = getMap(name);
- auto map = mc.lock();
- map->d_cachecachevalid = false;
- auto& idx = map->d_map.get<OrderedTag>();
+ auto& shard = getMap(name);
+ auto lockedShard = shard.lock();
+ lockedShard->d_cachecachevalid = false;
+ auto& idx = lockedShard->d_map.get<OrderedTag>();
auto range = idx.equal_range(name);
auto i = range.first;
while (i != range.second) {
if (i->d_qtype == qtype || qtype == 0xffff) {
i = idx.erase(i);
count++;
- --mc.d_entriesCount;
+ --shard.d_entriesCount;
}
else {
++i;
}
if (qtype == 0xffff) {
- auto& ecsIdx = map->d_ecsIndex.get<OrderedTag>();
+ auto& ecsIdx = lockedShard->d_ecsIndex.get<OrderedTag>();
auto ecsIndexRange = ecsIdx.equal_range(name);
ecsIdx.erase(ecsIndexRange.first, ecsIndexRange.second);
}
else {
- auto& ecsIdx = map->d_ecsIndex.get<HashedTag>();
+ auto& ecsIdx = lockedShard->d_ecsIndex.get<HashedTag>();
auto ecsIndexRange = ecsIdx.equal_range(std::tie(name, qtype));
ecsIdx.erase(ecsIndexRange.first, ecsIndexRange.second);
}
// Name should be doLimitTime or so
bool MemRecursorCache::doAgeCache(time_t now, const DNSName& name, const QType qtype, uint32_t newTTL)
{
- auto& mc = getMap(name);
- auto map = mc.lock();
- cache_t::iterator iter = map->d_map.find(std::tie(name, qtype));
- if (iter == map->d_map.end()) {
+ auto& shard = getMap(name);
+ auto lockedShard = shard.lock();
+ cache_t::iterator iter = lockedShard->d_map.find(std::tie(name, qtype));
+ if (iter == lockedShard->d_map.end()) {
return false;
}
CacheEntry ce = *iter;
- if (ce.d_ttd < now)
+ if (ce.d_ttd < now) {
return false; // would be dead anyhow
+ }
uint32_t maxTTL = static_cast<uint32_t>(ce.d_ttd - now);
if (maxTTL > newTTL) {
- map->d_cachecachevalid = false;
+ lockedShard->d_cachecachevalid = false;
time_t newTTD = now + newTTL;
if (ce.d_ttd > newTTD) {
ce.d_ttd = newTTD;
- map->d_map.replace(iter, ce);
+ lockedShard->d_map.replace(iter, ce);
}
return true;
}
fprintf(fp.get(), "; main record cache dump follows\n;\n");
uint64_t count = 0;
- size_t shard = 0;
+ size_t shardNumber = 0;
size_t min = std::numeric_limits<size_t>::max();
size_t max = 0;
- for (auto& mc : d_maps) {
- auto map = mc.lock();
- const auto shardSize = map->d_map.size();
- fprintf(fp.get(), "; record cache shard %zu; size %zu\n", shard, shardSize);
+ for (auto& shard : d_maps) {
+ auto lockedShard = shard.lock();
+ const auto shardSize = lockedShard->d_map.size();
+ fprintf(fp.get(), "; record cache shard %zu; size %zu\n", shardNumber, shardSize);
min = std::min(min, shardSize);
max = std::max(max, shardSize);
- shard++;
- const auto& sidx = map->d_map.get<SequencedTag>();
+ shardNumber++;
+ const auto& sidx = lockedShard->d_map.get<SequencedTag>();
time_t now = time(nullptr);
for (const auto& i : sidx) {
for (const auto& j : i.d_records) {
namespace boost
{
-size_t hash_value(const MemRecursorCache::OptTag& o)
+size_t hash_value(const MemRecursorCache::OptTag& rtag)
{
- return o ? hash_value(o.get()) : 0xcafebaaf;
+ return rtag ? hash_value(rtag.get()) : 0xcafebaaf;
}
}
static constexpr Flags Refresh = 1 << 1;
static constexpr Flags ServeStale = 1 << 2;
- time_t get(time_t, const DNSName& qname, const QType qt, Flags flags, vector<DNSRecord>* res, const ComboAddress& who, const OptTag& routingTag = boost::none, vector<std::shared_ptr<RRSIGRecordContent>>* signatures = nullptr, std::vector<std::shared_ptr<DNSRecord>>* authorityRecs = nullptr, bool* variable = nullptr, vState* state = nullptr, bool* wasAuth = nullptr, DNSName* fromAuthZone = nullptr, ComboAddress* fromAuthIP = nullptr);
+ time_t get(time_t, const DNSName& qname, const QType qt, Flags flags, vector<DNSRecord>* res, const ComboAddress& who, const OptTag& routingTag = boost::none, vector<std::shared_ptr<const RRSIGRecordContent>>* signatures = nullptr, std::vector<std::shared_ptr<DNSRecord>>* authorityRecs = nullptr, bool* variable = nullptr, vState* state = nullptr, bool* wasAuth = nullptr, DNSName* fromAuthZone = nullptr, ComboAddress* fromAuthIP = nullptr);
- void replace(time_t, const DNSName& qname, const QType qt, const vector<DNSRecord>& content, const vector<shared_ptr<RRSIGRecordContent>>& signatures, const std::vector<std::shared_ptr<DNSRecord>>& authorityRecs, bool auth, const DNSName& authZone, boost::optional<Netmask> ednsmask = boost::none, const OptTag& routingTag = boost::none, vState state = vState::Indeterminate, boost::optional<ComboAddress> from = boost::none, bool refresh = false);
+ void replace(time_t, const DNSName& qname, const QType qt, const vector<DNSRecord>& content, const vector<shared_ptr<const RRSIGRecordContent>>& signatures, const std::vector<std::shared_ptr<DNSRecord>>& authorityRecs, bool auth, const DNSName& authZone, boost::optional<Netmask> ednsmask = boost::none, const OptTag& routingTag = boost::none, vState state = vState::Indeterminate, boost::optional<ComboAddress> from = boost::none, bool refresh = false);
void doPrune(size_t keep);
uint64_t doDump(int fd, size_t maxCacheEntries);
{
}
- typedef vector<std::shared_ptr<DNSRecordContent>> records_t;
+ typedef vector<std::shared_ptr<const DNSRecordContent>> records_t;
bool isStale(time_t now) const
{
bool shouldReplace(time_t now, bool auth, vState state, bool refresh);
records_t d_records;
- std::vector<std::shared_ptr<RRSIGRecordContent>> d_signatures;
+ std::vector<std::shared_ptr<const RRSIGRecordContent>> d_signatures;
std::vector<std::shared_ptr<DNSRecord>> d_authorityRecs;
DNSName d_qname;
DNSName d_authZone;
Entries getEntries(MapCombo::LockedContent& content, const DNSName& qname, const QType qt, const OptTag& rtag);
cache_t::const_iterator getEntryUsingECSIndex(MapCombo::LockedContent& content, time_t now, const DNSName& qname, QType qtype, bool requireAuth, const ComboAddress& who, bool serveStale);
- time_t handleHit(MapCombo::LockedContent& content, OrderedTagIterator_t& entry, const DNSName& qname, uint32_t& origTTL, vector<DNSRecord>* res, vector<std::shared_ptr<RRSIGRecordContent>>* signatures, std::vector<std::shared_ptr<DNSRecord>>* authorityRecs, bool* variable, boost::optional<vState>& state, bool* wasAuth, DNSName* authZone, ComboAddress* fromAuthIP);
+ time_t handleHit(MapCombo::LockedContent& content, OrderedTagIterator_t& entry, const DNSName& qname, uint32_t& origTTL, vector<DNSRecord>* res, vector<std::shared_ptr<const RRSIGRecordContent>>* signatures, std::vector<std::shared_ptr<DNSRecord>>* authorityRecs, bool* variable, boost::optional<vState>& state, bool* wasAuth, DNSName* authZone, ComboAddress* fromAuthIP);
void updateStaleEntry(time_t now, OrderedTagIterator_t& entry);
void handleServeStaleBookkeeping(time_t, bool, OrderedTagIterator_t&);
#include "config.h"
#endif
+#include "arguments.hh"
#include "syncres.hh"
#include "reczones-helpers.hh"
+#include "root-addresses.hh"
+#include "zoneparser-tng.hh"
+
+static void putIntoCache(time_t now, QType qtype, vState state, const ComboAddress& from, const set<DNSName>& seen, const std::multimap<DNSName, DNSRecord>& allRecords)
+{
+ for (const auto& name : seen) {
+ auto records = allRecords.equal_range(name);
+ vector<DNSRecord> aset;
+ for (auto elem = records.first; elem != records.second; ++elem) {
+ aset.emplace_back(elem->second);
+ }
+ // Put non-default root hints into cache as authoritative. As argued below in
+ // putDefaultHintsIntoCache, this is actually wrong, but people might depend on it by having
+ // root-hints that refer to servers that aren't actually capable or willing to serve root data.
+ g_recCache->replace(now, name, qtype, aset, {}, {}, true, g_rootdnsname, boost::none, boost::none, state, from);
+ }
+}
+
+static void parseHintFile(time_t now, const std::string& hintfile, set<DNSName>& seenA, set<DNSName>& seenAAAA, set<DNSName>& seenNS, std::multimap<DNSName, DNSRecord>& aRecords, std::multimap<DNSName, DNSRecord>& aaaaRecords, vector<DNSRecord>& nsvec)
+{
+ ZoneParserTNG zpt(hintfile);
+ zpt.setMaxGenerateSteps(::arg().asNum("max-generate-steps"));
+ zpt.setMaxIncludes(::arg().asNum("max-include-depth"));
+ DNSResourceRecord rrecord;
+
+ while (zpt.get(rrecord)) {
+ rrecord.ttl += now;
+ switch (rrecord.qtype) {
+ case QType::A:
+ seenA.insert(rrecord.qname);
+ aRecords.emplace(rrecord.qname, DNSRecord(rrecord));
+ break;
+ case QType::AAAA:
+ seenAAAA.insert(rrecord.qname);
+ aaaaRecords.emplace(rrecord.qname, DNSRecord(rrecord));
+ break;
+ case QType::NS:
+ seenNS.emplace(rrecord.content);
+ rrecord.content = toLower(rrecord.content);
+ nsvec.emplace_back(rrecord);
+ break;
+ }
+ }
+}
+
+static bool determineReachable(const set<DNSName>& names, const set<DNSName>& nameservers)
+{
+ bool reachable = false;
+ for (auto const& record : names) {
+ if (nameservers.count(record) != 0) {
+ reachable = true;
+ break;
+ }
+ }
+ return reachable;
+}
+
+bool readHintsIntoCache(time_t now, const std::string& hintfile, std::vector<DNSRecord>& nsvec)
+{
+ const ComboAddress from("255.255.255.255");
+ set<DNSName> seenNS;
+ set<DNSName> seenA;
+ set<DNSName> seenAAAA;
+
+ std::multimap<DNSName, DNSRecord> aRecords;
+ std::multimap<DNSName, DNSRecord> aaaaRecords;
+
+ parseHintFile(now, hintfile, seenA, seenAAAA, seenNS, aRecords, aaaaRecords, nsvec);
+
+ putIntoCache(now, QType::A, vState::Insecure, from, seenA, aRecords);
+ putIntoCache(now, QType::AAAA, vState::Insecure, from, seenAAAA, aaaaRecords);
+
+ bool reachableA = determineReachable(seenA, seenNS);
+ bool reachableAAAA = determineReachable(seenAAAA, seenNS);
+
+ auto log = g_slog->withName("config");
+ if (SyncRes::s_doIPv4 && !SyncRes::s_doIPv6 && !reachableA) {
+ SLOG(g_log << Logger::Error << "Running IPv4 only but no IPv4 root hints" << endl,
+ log->info(Logr::Error, "Running IPv4 only but no IPv4 root hints"));
+ return false;
+ }
+ if (!SyncRes::s_doIPv4 && SyncRes::s_doIPv6 && !reachableAAAA) {
+ SLOG(g_log << Logger::Error << "Running IPv6 only but no IPv6 root hints" << endl,
+ log->info(Logr::Error, "Running IPv6 only but no IPv6 root hints"));
+ return false;
+ }
+ if (SyncRes::s_doIPv4 && SyncRes::s_doIPv6 && !reachableA && !reachableAAAA) {
+ SLOG(g_log << Logger::Error << "No valid root hints" << endl,
+ log->info(Logr::Error, "No valid root hints"));
+ return false;
+ }
+ return true;
+}
+
+void putDefaultHintsIntoCache(time_t now, std::vector<DNSRecord>& nsvec)
+{
+ const ComboAddress from("255.255.255.255");
+
+ DNSRecord arr;
+ DNSRecord aaaarr;
+ DNSRecord nsrr;
+
+ nsrr.d_name = g_rootdnsname;
+ arr.d_type = QType::A;
+ aaaarr.d_type = QType::AAAA;
+ nsrr.d_type = QType::NS;
+ arr.d_ttl = aaaarr.d_ttl = nsrr.d_ttl = now + 3600000;
+
+ string templ = "a.root-servers.net.";
+
+ static_assert(rootIps4.size() == rootIps6.size());
+
+ for (size_t letter = 0; letter < rootIps4.size(); ++letter) {
+ templ.at(0) = static_cast<char>(letter + 'a');
+ aaaarr.d_name = arr.d_name = DNSName(templ);
+ nsrr.setContent(std::make_shared<NSRecordContent>(DNSName(templ)));
+ nsvec.push_back(nsrr);
+
+ if (!rootIps4.at(letter).empty()) {
+ arr.setContent(std::make_shared<ARecordContent>(ComboAddress(rootIps4.at(letter))));
+ /*
+ * Originally the hint records were inserted with the auth flag set, with the consequence that
+ * data from AUTHORITY and ADDITIONAL sections (as seen in a . NS response) were not used. This
+ * (together with the long ttl) caused outdated hint to be kept in cache. So insert as non-auth,
+ * and the extra sections in the . NS refreshing cause the cached records to be updated with
+ * up-to-date information received from a real root server.
+ *
+ * Note that if a user query is done for one of the root-server.net names, it will be inserted
+ * into the cache with the auth bit set. Further NS refreshes will not update that entry. If all
+ * root names are queried at the same time by a user, all root-server.net names will be marked
+ * auth and will expire at the same time. A re-prime is then triggered, as before, when the
+ * records were inserted with the auth bit set and the TTD comes.
+ */
+ g_recCache->replace(now, DNSName(templ), QType::A, {arr}, {}, {}, false, g_rootdnsname, boost::none, boost::none, vState::Insecure, from);
+ }
+ if (!rootIps6.at(letter).empty()) {
+ aaaarr.setContent(std::make_shared<AAAARecordContent>(ComboAddress(rootIps6.at(letter))));
+ g_recCache->replace(now, DNSName(templ), QType::AAAA, {aaaarr}, {}, {}, false, g_rootdnsname, boost::none, boost::none, vState::Insecure, from);
+ }
+ }
+}
template <typename T>
static SyncRes::AuthDomain makeSOAAndNSNodes(DNSRecord& dr, T content)
dr.d_place = DNSResourceRecord::ANSWER;
dr.d_ttl = 86400;
dr.d_type = QType::SOA;
- dr.d_content = DNSRecordContent::mastermake(QType::SOA, 1, "localhost. root 1 604800 86400 2419200 604800");
+ dr.setContent(DNSRecordContent::mastermake(QType::SOA, 1, "localhost. root 1 604800 86400 2419200 604800"));
SyncRes::AuthDomain ad;
ad.d_rdForward = false;
ad.d_records.insert(dr);
dr.d_type = QType::NS;
- dr.d_content = std::make_shared<NSRecordContent>(content);
+ dr.setContent(std::make_shared<NSRecordContent>(content));
ad.d_records.insert(dr);
return ad;
auto recType = address.isIPv6() ? QType::AAAA : QType::A;
dr.d_type = recType;
dr.d_ttl = 86400;
- dr.d_content = DNSRecordContent::mastermake(recType, QClass::IN, address.toStringNoInterface());
+ dr.setContent(DNSRecordContent::mastermake(recType, QClass::IN, address.toStringNoInterface()));
entry->second.d_records.insert(dr);
}
// Add a PTR entry for the primary name for reverse lookups.
dr.d_type = QType::PTR;
- dr.d_content = DNSRecordContent::mastermake(QType::PTR, 1, DNSName(canonicalHostname).toString());
+ dr.setContent(DNSRecordContent::mastermake(QType::PTR, 1, DNSName(canonicalHostname).toString()));
ad.d_records.insert(dr);
addToDomainMap(newMap, ad, dr.d_name, log, false, true);
#include "syncres.hh"
#include "logger.hh"
+bool readHintsIntoCache(time_t now, const std::string& hintfile, std::vector<DNSRecord>& nsvec);
+void putDefaultHintsIntoCache(time_t now, std::vector<DNSRecord>& nsvec);
+
void makeIPToNamesZone(const std::shared_ptr<SyncRes::domainmap_t>& newMap,
const vector<string>& parts,
Logr::log_t log);
#endif
#include "reczones-helpers.hh"
-#include "syncres.hh"
#include "arguments.hh"
-#include "zoneparser-tng.hh"
-#include "logger.hh"
#include "dnsrecords.hh"
-#include "root-addresses.hh"
+#include "logger.hh"
+#include "syncres.hh"
+#include "zoneparser-tng.hh"
extern int g_argc;
extern char** g_argv;
-bool primeHints(time_t ignored)
+bool primeHints(time_t now)
{
- // prime root cache
- const vState validationState = vState::Insecure;
- const ComboAddress from("255.255.255.255");
- vector<DNSRecord> nsset;
-
- time_t now = time(nullptr);
-
- auto log = g_slog->withName("config");
const string hintfile = ::arg()["hint-file"];
+ vector<DNSRecord> nsvec;
+ bool ret = true;
+
if (hintfile == "no") {
+ auto log = g_slog->withName("config");
SLOG(g_log << Logger::Debug << "Priming root disabled by hint-file=no" << endl,
log->info(Logr::Debug, "Priming root disabled by hint-file=no"));
- return true;
+ return ret;
}
- if (hintfile.empty()) {
- DNSRecord arr, aaaarr, nsrr;
- nsrr.d_name = g_rootdnsname;
- arr.d_type = QType::A;
- aaaarr.d_type = QType::AAAA;
- nsrr.d_type = QType::NS;
-
- arr.d_ttl = aaaarr.d_ttl = nsrr.d_ttl = now + 3600000;
-
- for (char c = 'a'; c <= 'm'; ++c) {
- char templ[40];
- strncpy(templ, "a.root-servers.net.", sizeof(templ) - 1);
- templ[sizeof(templ) - 1] = '\0';
- *templ = c;
- aaaarr.d_name = arr.d_name = DNSName(templ);
- nsrr.d_content = std::make_shared<NSRecordContent>(DNSName(templ));
- arr.d_content = std::make_shared<ARecordContent>(ComboAddress(rootIps4[c - 'a']));
- vector<DNSRecord> aset;
- aset.push_back(arr);
- /*
- * Originally the hint records were inserted with the auth flag set, with the consequence that data from AUTHORITY and
- * ADDITIONAL sections (as seen in a . NS response) were not used. This (together with the long ttl) caused outdated
- * hint to be kept in cache. So insert as non-auth, and the extra sections in the . NS refreshing cause the cached
- * records to be updated with up-to-date information received from a real root server.
- *
- * Note that if a user query is done for one of the root-server.net names, it will be inserted into the cache with the
- * auth bit set. Further NS refreshes will not update that entry. If all root names are queried at the same time by a user,
- * all root-server.net names will be marked auth and will expire at the same time. A re-prime is then triggered,
- * as before, when the records were inserted with the auth bit set and the TTD comes.
- */
- g_recCache->replace(now, DNSName(templ), QType(QType::A), aset, vector<std::shared_ptr<RRSIGRecordContent>>(), vector<std::shared_ptr<DNSRecord>>(), false, g_rootdnsname, boost::none, boost::none, validationState, from); // auth, nuke it all
- if (rootIps6[c - 'a'] != NULL) {
- aaaarr.d_content = std::make_shared<AAAARecordContent>(ComboAddress(rootIps6[c - 'a']));
-
- vector<DNSRecord> aaaaset;
- aaaaset.push_back(aaaarr);
- g_recCache->replace(now, DNSName(templ), QType(QType::AAAA), aaaaset, vector<std::shared_ptr<RRSIGRecordContent>>(), vector<std::shared_ptr<DNSRecord>>(), false, g_rootdnsname, boost::none, boost::none, validationState, from);
- }
- nsset.push_back(nsrr);
- }
+ if (hintfile.empty()) {
+ putDefaultHintsIntoCache(now, nsvec);
}
else {
- ZoneParserTNG zpt(hintfile);
- zpt.setMaxGenerateSteps(::arg().asNum("max-generate-steps"));
- zpt.setMaxIncludes(::arg().asNum("max-include-depth"));
- DNSResourceRecord rr;
- set<DNSName> seenNS;
- set<DNSName> seenA;
- set<DNSName> seenAAAA;
-
- while (zpt.get(rr)) {
- rr.ttl += now;
- if (rr.qtype.getCode() == QType::A) {
- seenA.insert(rr.qname);
- vector<DNSRecord> aset;
- aset.push_back(DNSRecord(rr));
- g_recCache->replace(now, rr.qname, QType(QType::A), aset, vector<std::shared_ptr<RRSIGRecordContent>>(), vector<std::shared_ptr<DNSRecord>>(), true, g_rootdnsname, boost::none, boost::none, validationState, from); // auth, etc see above
- }
- else if (rr.qtype.getCode() == QType::AAAA) {
- seenAAAA.insert(rr.qname);
- vector<DNSRecord> aaaaset;
- aaaaset.push_back(DNSRecord(rr));
- g_recCache->replace(now, rr.qname, QType(QType::AAAA), aaaaset, vector<std::shared_ptr<RRSIGRecordContent>>(), vector<std::shared_ptr<DNSRecord>>(), true, g_rootdnsname, boost::none, boost::none, validationState, from);
- }
- else if (rr.qtype.getCode() == QType::NS) {
- seenNS.insert(DNSName(rr.content));
- rr.content = toLower(rr.content);
- nsset.push_back(DNSRecord(rr));
- }
- }
-
- // Check reachability of A and AAAA records
- bool reachableA = false, reachableAAAA = false;
- for (auto const& r : seenA) {
- if (seenNS.count(r)) {
- reachableA = true;
- break;
- }
- }
- for (auto const& r : seenAAAA) {
- if (seenNS.count(r)) {
- reachableAAAA = true;
- break;
- }
- }
- if (SyncRes::s_doIPv4 && !SyncRes::s_doIPv6 && !reachableA) {
- SLOG(g_log << Logger::Error << "Running IPv4 only but no IPv4 root hints" << endl,
- log->info(Logr::Error, "Running IPv4 only but no IPv4 root hints"));
- return false;
- }
- if (!SyncRes::s_doIPv4 && SyncRes::s_doIPv6 && !reachableAAAA) {
- SLOG(g_log << Logger::Error << "Running IPv6 only but no IPv6 root hints" << endl,
- log->info(Logr::Error, "Running IPv6 only but no IPv6 root hints"));
- return false;
- }
- if (SyncRes::s_doIPv4 && SyncRes::s_doIPv6 && !reachableA && !reachableAAAA) {
- SLOG(g_log << Logger::Error << "No valid root hints" << endl,
- log->info(Logr::Error, "No valid root hints"));
- return false;
- }
+ ret = readHintsIntoCache(now, hintfile, nsvec);
}
g_recCache->doWipeCache(g_rootdnsname, false, QType::NS);
- g_recCache->replace(now, g_rootdnsname, QType(QType::NS), nsset, vector<std::shared_ptr<RRSIGRecordContent>>(), vector<std::shared_ptr<DNSRecord>>(), false, g_rootdnsname, boost::none, boost::none, validationState, from); // and stuff in the cache
- return true;
+ g_recCache->replace(now, g_rootdnsname, QType::NS, nsvec, {}, {}, false, g_rootdnsname, boost::none, boost::none, vState::Insecure, ComboAddress("255.255.255.255")); // and stuff in the cache
+ return ret;
}
static void convertServersForAD(const std::string& zone, const std::string& input, SyncRes::AuthDomain& ad, const char* sepa, Logr::log_t log, bool verbose = true)
*/
#pragma once
-static const char* const rootIps4[] = {
+#include <array>
+#include <string>
+
+const std::array<const std::string, 13> rootIps4 = {
"198.41.0.4", // a.root-servers.net.
"199.9.14.201", // b.root-servers.net.
"192.33.4.12", // c.root-servers.net.
"199.7.83.42", // l.root-servers.net.
"202.12.27.33" // m.root-servers.net.
};
-static size_t const rootIps4Count = sizeof(rootIps4) / sizeof(*rootIps4);
-static const char* const rootIps6[] = {
+const std::array<const std::string, 13> rootIps6 = {
"2001:503:ba3e::2:30", // a.root-servers.net.
"2001:500:200::b", // b.root-servers.net.
"2001:500:2::c", // c.root-servers.net.
"2001:500:9f::42", // l.root-servers.net.
"2001:dc3::35" // m.root-servers.net.
};
-static size_t const rootIps6Count = sizeof(rootIps6) / sizeof(*rootIps6);
}
else {
pol.d_kind = DNSFilterEngine::PolicyKind::Custom;
- pol.d_custom.emplace_back(dr.d_content);
+ pol.d_custom.emplace_back(dr.getContent());
// cerr<<"Wants custom "<<crcTarget<<" for "<<dr.d_name<<": ";
}
}
}
else {
pol.d_kind = DNSFilterEngine::PolicyKind::Custom;
- pol.d_custom.emplace_back(dr.d_content);
+ pol.d_custom.emplace_back(dr.getContent());
// cerr<<"Wants custom "<<dr.d_content->getZoneRepresentation()<<" for "<<dr.d_name<<": ";
}
}
}
}
-static shared_ptr<SOARecordContent> loadRPZFromServer(Logr::log_t plogger, const ComboAddress& primary, const DNSName& zoneName, std::shared_ptr<DNSFilterEngine::Zone> zone, const boost::optional<DNSFilterEngine::Policy>& defpol, bool defpolOverrideLocal, uint32_t maxTTL, const TSIGTriplet& tt, size_t maxReceivedBytes, const ComboAddress& localAddress, uint16_t axfrTimeout)
+static shared_ptr<const SOARecordContent> loadRPZFromServer(Logr::log_t plogger, const ComboAddress& primary, const DNSName& zoneName, std::shared_ptr<DNSFilterEngine::Zone> zone, const boost::optional<DNSFilterEngine::Policy>& defpol, bool defpolOverrideLocal, uint32_t maxTTL, const TSIGTriplet& tt, size_t maxReceivedBytes, const ComboAddress& localAddress, uint16_t axfrTimeout)
{
auto logger = plogger->withValues("primary", Logging::Loggable(primary));
time_t last = 0;
time_t axfrStart = time(nullptr);
time_t axfrNow = time(nullptr);
- shared_ptr<SOARecordContent> sr;
+ shared_ptr<const SOARecordContent> sr;
while (axfr.getChunk(nop, &chunk, (axfrStart + axfrTimeout - axfrNow))) {
for (auto& dr : chunk) {
if (dr.d_type == QType::NS || dr.d_type == QType::TSIG) {
}
// this function is silent - you do the logging
-std::shared_ptr<SOARecordContent> loadRPZFromFile(const std::string& fname, std::shared_ptr<DNSFilterEngine::Zone> zone, const boost::optional<DNSFilterEngine::Policy>& defpol, bool defpolOverrideLocal, uint32_t maxTTL)
+std::shared_ptr<const SOARecordContent> loadRPZFromFile(const std::string& fname, std::shared_ptr<DNSFilterEngine::Zone> zone, const boost::optional<DNSFilterEngine::Policy>& defpol, bool defpolOverrideLocal, uint32_t maxTTL)
{
- shared_ptr<SOARecordContent> sr = nullptr;
+ shared_ptr<const SOARecordContent> sr = nullptr;
ZoneParserTNG zpt(fname);
zpt.setMaxGenerateSteps(::arg().asNum("max-generate-steps"));
zpt.setMaxIncludes(::arg().asNum("max-include-depth"));
return true;
}
-void RPZIXFRTracker(const std::vector<ComboAddress>& primaries, const boost::optional<DNSFilterEngine::Policy>& defpol, bool defpolOverrideLocal, uint32_t maxTTL, size_t zoneIdx, const TSIGTriplet& tt, size_t maxReceivedBytes, const ComboAddress& localAddress, const uint16_t xfrTimeout, const uint32_t refreshFromConf, std::shared_ptr<SOARecordContent> sr, const std::string& dumpZoneFileName, uint64_t configGeneration)
+void RPZIXFRTracker(const std::vector<ComboAddress>& primaries, const boost::optional<DNSFilterEngine::Policy>& defpol, bool defpolOverrideLocal, uint32_t maxTTL, size_t zoneIdx, const TSIGTriplet& tt, size_t maxReceivedBytes, const ComboAddress& localAddress, const uint16_t xfrTimeout, const uint32_t refreshFromConf, std::shared_ptr<const SOARecordContent> sr, const std::string& dumpZoneFileName, uint64_t configGeneration)
{
setThreadName("rec/rpzixfr");
bool isPreloaded = sr != nullptr;
for (;;) {
DNSRecord dr;
- dr.d_content = sr;
+ dr.setContent(sr);
if (skipRefreshDelay) {
skipRefreshDelay = false;
/* we need to make a _full copy_ of the zone we are going to work on */
std::shared_ptr<DNSFilterEngine::Zone> newZone = std::make_shared<DNSFilterEngine::Zone>(*oldZone);
/* initialize the current serial to the last one */
- std::shared_ptr<SOARecordContent> currentSR = sr;
+ std::shared_ptr<const SOARecordContent> currentSR = sr;
int totremove = 0, totadd = 0;
bool fullUpdate = false;
extern bool g_logRPZChanges;
-std::shared_ptr<SOARecordContent> loadRPZFromFile(const std::string& fname, std::shared_ptr<DNSFilterEngine::Zone> zone, const boost::optional<DNSFilterEngine::Policy>& defpol, bool defpolOverrideLocal, uint32_t maxTTL);
-void RPZIXFRTracker(const std::vector<ComboAddress>& primaries, const boost::optional<DNSFilterEngine::Policy>& defpol, bool defpolOverrideLocal, uint32_t maxTTL, size_t zoneIdx, const TSIGTriplet& tt, size_t maxReceivedBytes, const ComboAddress& localAddress, const uint16_t xfrTimeout, const uint32_t reloadFromConf, shared_ptr<SOARecordContent> sr, const std::string& dumpZoneFileName, uint64_t configGeneration);
+std::shared_ptr<const SOARecordContent> loadRPZFromFile(const std::string& fname, std::shared_ptr<DNSFilterEngine::Zone> zone, const boost::optional<DNSFilterEngine::Policy>& defpol, bool defpolOverrideLocal, uint32_t maxTTL);
+void RPZIXFRTracker(const std::vector<ComboAddress>& primaries, const boost::optional<DNSFilterEngine::Policy>& defpol, bool defpolOverrideLocal, uint32_t maxTTL, size_t zoneIdx, const TSIGTriplet& tt, size_t maxReceivedBytes, const ComboAddress& localAddress, const uint16_t xfrTimeout, const uint32_t reloadFromConf, shared_ptr<const SOARecordContent> sr, const std::string& dumpZoneFileName, uint64_t configGeneration);
struct rpzStats
{
unsigned int SyncRes::s_minimumECSTTL;
unsigned int SyncRes::s_packetcachettl;
unsigned int SyncRes::s_packetcacheservfailttl;
+unsigned int SyncRes::s_packetcachenegativettl;
unsigned int SyncRes::s_serverdownmaxfails;
unsigned int SyncRes::s_serverdownthrottletime;
unsigned int SyncRes::s_nonresolvingnsmaxfails;
dr.d_ttl = 86400;
for (const auto& ans : answers) {
dr.d_type = ans.first;
- dr.d_content = DNSRecordContent::mastermake(ans.first, qclass, ans.second);
+ dr.setContent(DNSRecordContent::mastermake(ans.first, qclass, ans.second));
ret.push_back(dr);
}
}
return true;
}
-bool SyncRes::doOOBResolve(const DNSName& qname, const QType qtype, vector<DNSRecord>& ret, unsigned int depth, const string& prefix, int& res)
+bool SyncRes::doOOBResolve(const DNSName& qname, const QType qtype, vector<DNSRecord>& ret, unsigned int /* depth */, const string& prefix, int& res)
{
DNSName authdomain(qname);
domainmap_t::const_iterator iter = getBestAuthZone(&authdomain);
setQNameMinimization(false);
setQMFallbackMode(true);
- // We might have hit a depth level check, but we still want to allow some recursion levels in the fallback
- // no-qname-minimization case. This has the effect that a qname minimization fallback case might reach 150% of
- // maxdepth.
- res = doResolveNoQNameMinimization(qname, qtype, ret, depth / 2, beenthere, context);
+ auto oldEDE = context.extendedError;
+ res = doResolveNoQNameMinimization(qname, qtype, ret, depth + 1, beenthere, context);
if (res == RCode::NoError) {
t_Counters.at(rec::Counter::qnameminfallbacksuccess)++;
}
+ else {
+ // as doResolveNoQNameMinimization clears the EDE, we put it back here, it is relevant but might not be set by the last effort attempt
+ if (!context.extendedError) {
+ context.extendedError = oldEDE;
+ }
+ }
LOG(prefix << qname << ": Step5 End resolve: " << RCode::to_s(res) << "/" << ret.size() << endl);
return res;
return RCode::ServFail;
}
+unsigned int SyncRes::getAdjustedRecursionBound() const
+{
+ auto bound = s_maxdepth; // 40 is default value of s_maxdepth
+ if (getQMFallbackMode()) {
+ // We might have hit a depth level check, but we still want to allow some recursion levels in the fallback
+ // no-qname-minimization case. This has the effect that a qname minimization fallback case might reach 150% of
+ // maxdepth, taking care to not repeatedly increase the bound.
+ bound += s_maxdepth / 2;
+ }
+ return bound;
+}
+
/*! This function will check the cache and go out to the internet if the answer is not in cache
*
* \param qname The name we need an answer for
*/
int SyncRes::doResolveNoQNameMinimization(const DNSName& qname, const QType qtype, vector<DNSRecord>& ret, unsigned int depth, set<GetBestNSAnswer>& beenthere, Context& context, bool* fromCache, StopAtDelegation* stopAtDelegation)
{
+ context.extendedError.reset();
auto prefix = getPrefix(depth);
LOG(prefix << qname << ": Wants " << (d_doDNSSEC ? "" : "NO ") << "DNSSEC processing, " << (d_requireAuthData ? "" : "NO ") << "auth data required by query for " << qtype << endl);
- if (s_maxdepth > 0 && depth > s_maxdepth) {
- string msg = "More than " + std::to_string(s_maxdepth) + " (max-recursion-depth) levels of recursion needed while resolving " + qname.toLogString();
- LOG(prefix << qname << ": " << msg << endl);
- throw ImmediateServFailException(msg);
+ if (s_maxdepth > 0) {
+ auto bound = getAdjustedRecursionBound();
+ if (depth > bound) {
+ string msg = "More than " + std::to_string(bound) + " (adjusted max-recursion-depth) levels of recursion needed while resolving " + qname.toLogString();
+ LOG(prefix << qname << ": " << msg << endl);
+ throw ImmediateServFailException(msg);
+ }
}
+
int res = 0;
const int iterations = !d_refresh && MemRecursorCache::s_maxServedStaleExtensions > 0 ? 2 : 1;
bool SyncRes::doCNAMECacheCheck(const DNSName& qname, const QType qtype, vector<DNSRecord>& ret, unsigned int depth, const string& prefix, int& res, Context& context, bool wasAuthZone, bool wasForwardRecurse)
{
- if ((depth > 9 && d_outqueries > 10 && d_throttledqueries > 5) || depth > 15) {
+ // Even if s_maxdepth is zero, we want to have this check
+ auto bound = std::max(40U, getAdjustedRecursionBound());
+ // Bounds were > 9 and > 15 originally, now they are derived from s_maxdepth (default 40)
+ // Apply more strict bound if we see throttling
+ if ((depth >= bound / 4 && d_outqueries > 10 && d_throttledqueries > 5) || depth > bound * 3 / 8) {
LOG(prefix << qname << ": Recursing (CNAME or other indirection) too deep, depth=" << depth << endl);
res = RCode::ServFail;
return true;
}
vector<DNSRecord> cset;
- vector<std::shared_ptr<RRSIGRecordContent>> signatures;
+ vector<std::shared_ptr<const RRSIGRecordContent>> signatures;
vector<std::shared_ptr<DNSRecord>> authorityRecs;
bool wasAuth;
uint32_t capTTL = std::numeric_limits<uint32_t>::max();
}
}
- LOG(prefix << qname << ": Found cache " << foundQT.toString() << " hit for '" << foundName << "|" << foundQT.toString() << "' to '" << record.d_content->getZoneRepresentation() << "', validation state is " << context.state << endl);
+ LOG(prefix << qname << ": Found cache " << foundQT.toString() << " hit for '" << foundName << "|" << foundQT.toString() << "' to '" << record.getContent()->getZoneRepresentation() << "', validation state is " << context.state << endl);
DNSRecord dr = record;
dr.d_ttl -= d_now.tv_sec;
sigdr.d_type = QType::RRSIG;
sigdr.d_name = foundName;
sigdr.d_ttl = ttl;
- sigdr.d_content = signature;
+ sigdr.setContent(signature);
sigdr.d_place = DNSResourceRecord::ANSWER;
sigdr.d_class = QClass::IN;
ret.push_back(sigdr);
dr.d_type = QType::CNAME;
dr.d_name = targetPrefix + foundName;
newTarget = targetPrefix + dnameSuffix;
- dr.d_content = std::make_shared<CNAMERecordContent>(CNAMERecordContent(newTarget));
+ dr.setContent(std::make_shared<CNAMERecordContent>(CNAMERecordContent(newTarget)));
ret.push_back(dr);
}
catch (const std::exception& e) {
struct CacheEntry
{
vector<DNSRecord> records;
- vector<shared_ptr<RRSIGRecordContent>> signatures;
+ vector<shared_ptr<const RRSIGRecordContent>> signatures;
uint32_t signaturesTTL{std::numeric_limits<uint32_t>::max()};
};
struct CacheKey
return std::tie(type, place, name) < std::tie(rhs.type, rhs.place, rhs.name);
}
};
-typedef map<CacheKey, CacheEntry> tcache_t;
+using tcache_t = map<CacheKey, CacheEntry>;
}
static void reapRecordsFromNegCacheEntryForValidation(tcache_t& tcache, const vector<DNSRecord>& records)
}
}
-static void reapSignaturesForValidation(std::map<QType, CacheEntry>& entries, const vector<std::shared_ptr<RRSIGRecordContent>>& signatures)
+static void reapSignaturesForValidation(std::map<QType, CacheEntry>& entries, const vector<std::shared_ptr<const RRSIGRecordContent>>& signatures)
{
for (const auto& sig : signatures) {
entries[sig->d_type].signatures.push_back(sig);
giveNegative = true;
cachedState = ne.d_validationState;
if (s_addExtendedResolutionDNSErrors) {
- context.extendedError = EDNSExtendedError{0, "Result synthesized by root-nx-trust"};
+ context.extendedError = EDNSExtendedError{static_cast<uint16_t>(EDNSExtendedError::code::Synthesized), "Result synthesized by root-nx-trust"};
}
}
else if (g_negCache->get(qname, qtype, d_now, ne, false, d_serveStale, d_refresh)) {
LOG(prefix << qname << "|" << qtype << ": Is negatively cached via '" << ne.d_auth << "' for another " << sttl << " seconds" << endl);
res = RCode::NoError;
if (s_addExtendedResolutionDNSErrors) {
- context.extendedError = EDNSExtendedError{0, "Result from negative cache"};
+ context.extendedError = EDNSExtendedError{static_cast<uint16_t>(EDNSExtendedError::code::Synthesized), "Result from negative cache"};
}
}
else {
LOG(prefix << qname << ": Entire name '" << qname << "' is negatively cached via '" << ne.d_auth << "' for another " << sttl << " seconds" << endl);
if (s_addExtendedResolutionDNSErrors) {
- context.extendedError = EDNSExtendedError{0, "Result from negative cache for entire name"};
+ context.extendedError = EDNSExtendedError{static_cast<uint16_t>(EDNSExtendedError::code::Synthesized), "Result from negative cache for entire name"};
}
}
}
cachedState = ne.d_validationState;
LOG(prefix << qname << ": Name '" << negCacheName << "' and below, is negatively cached via '" << ne.d_auth << "' for another " << sttl << " seconds" << endl);
if (s_addExtendedResolutionDNSErrors) {
- context.extendedError = EDNSExtendedError{0, "Result synthesized by nothing-below-nxdomain (RFC8020)"};
+ context.extendedError = EDNSExtendedError{static_cast<uint16_t>(EDNSExtendedError::code::Synthesized), "Result synthesized by nothing-below-nxdomain (RFC8020)"};
}
break;
}
vector<DNSRecord> cset;
bool found = false, expired = false;
- vector<std::shared_ptr<RRSIGRecordContent>> signatures;
+ vector<std::shared_ptr<const RRSIGRecordContent>> signatures;
vector<std::shared_ptr<DNSRecord>> authorityRecs;
uint32_t ttl = 0;
uint32_t capTTL = std::numeric_limits<uint32_t>::max();
for (auto j = cset.cbegin(); j != cset.cend(); ++j) {
- LOG(j->d_content->getZoneRepresentation());
+ LOG(j->getContent()->getZoneRepresentation());
if (j->d_class != QClass::IN) {
continue;
dr.d_type = QType::RRSIG;
dr.d_name = sqname;
dr.d_ttl = ttl;
- dr.d_content = signature;
+ dr.setContent(signature);
dr.d_place = DNSResourceRecord::ANSWER;
dr.d_class = QClass::IN;
ret.push_back(dr);
if (g_aggressiveNSECCache->getDenial(d_now.tv_sec, qname, qtype, ret, res, d_cacheRemote, d_routingTag, d_doDNSSEC, LogObject(prefix))) {
context.state = vState::Secure;
if (s_addExtendedResolutionDNSErrors) {
- context.extendedError = EDNSExtendedError{0, "Result synthesized from aggressive NSEC cache (RFC8198)"};
+ context.extendedError = EDNSExtendedError{static_cast<uint16_t>(EDNSExtendedError::code::Synthesized), "Result synthesized from aggressive NSEC cache (RFC8198)"};
}
return true;
}
return nameservers;
}
-static uint32_t getRRSIGTTL(const time_t now, const std::shared_ptr<RRSIGRecordContent>& rrsig)
+static uint32_t getRRSIGTTL(const time_t now, const std::shared_ptr<const RRSIGRecordContent>& rrsig)
{
uint32_t res = 0;
if (now < rrsig->d_sigexpire) {
if (rrsig) {
if (rrsig->d_type == QType::SOA) {
ne.authoritySOA.signatures.push_back(rec);
- if (lowestTTL && isRRSIGNotExpired(now, rrsig)) {
+ if (lowestTTL && isRRSIGNotExpired(now, *rrsig)) {
*lowestTTL = min(*lowestTTL, rec.d_ttl);
*lowestTTL = min(*lowestTTL, getRRSIGTTL(now, rrsig));
}
}
if (nsecTypes.count(rrsig->d_type)) {
ne.DNSSECRecords.signatures.push_back(rec);
- if (lowestTTL && isRRSIGNotExpired(now, rrsig)) {
+ if (lowestTTL && isRRSIGNotExpired(now, *rrsig)) {
*lowestTTL = min(*lowestTTL, rec.d_ttl);
*lowestTTL = min(*lowestTTL, getRRSIGTTL(now, rrsig));
}
}
}
for (const auto& rec : ne.DNSSECRecords.records) {
- cspmap[{rec.d_name, rec.d_type}].records.insert(rec.d_content);
+ cspmap[{rec.d_name, rec.d_type}].records.insert(rec.getContent());
}
return cspmap;
}
return false;
}
-vector<ComboAddress> SyncRes::retrieveAddressesForNS(const std::string& prefix, const DNSName& qname, std::vector<std::pair<DNSName, float>>::const_iterator& tns, const unsigned int depth, set<GetBestNSAnswer>& beenthere, const vector<std::pair<DNSName, float>>& rnameservers, NsSet& nameservers, bool& sendRDQuery, bool& pierceDontQuery, bool& flawedNSSet, bool cacheOnly, unsigned int& nretrieveAddressesForNS)
+vector<ComboAddress> SyncRes::retrieveAddressesForNS(const std::string& prefix, const DNSName& qname, std::vector<std::pair<DNSName, float>>::const_iterator& tns, const unsigned int depth, set<GetBestNSAnswer>& beenthere, const vector<std::pair<DNSName, float>>& rnameservers, NsSet& nameservers, bool& sendRDQuery, bool& pierceDontQuery, bool& /* flawedNSSet */, bool cacheOnly, unsigned int& nretrieveAddressesForNS)
{
vector<ComboAddress> result;
return g_dnssecmode != DNSSECMode::Off && g_dnssecmode != DNSSECMode::ProcessNoValidate;
}
-uint32_t SyncRes::computeLowestTTD(const std::vector<DNSRecord>& records, const std::vector<std::shared_ptr<RRSIGRecordContent>>& signatures, uint32_t signaturesTTL, const std::vector<std::shared_ptr<DNSRecord>>& authorityRecs) const
+uint32_t SyncRes::computeLowestTTD(const std::vector<DNSRecord>& records, const std::vector<std::shared_ptr<const RRSIGRecordContent>>& signatures, uint32_t signaturesTTL, const std::vector<std::shared_ptr<DNSRecord>>& authorityRecs) const
{
uint32_t lowestTTD = std::numeric_limits<uint32_t>::max();
for (const auto& record : records) {
lowestTTD = min(lowestTTD, static_cast<uint32_t>(signaturesTTL + d_now.tv_sec));
for (const auto& sig : signatures) {
- if (isRRSIGNotExpired(d_now.tv_sec, sig)) {
+ if (isRRSIGNotExpired(d_now.tv_sec, *sig)) {
// we don't decrement d_sigexpire by 'now' because we actually want a TTD, not a TTL */
lowestTTD = min(lowestTTD, static_cast<uint32_t>(sig->d_sigexpire));
}
if (entry->d_type == QType::RRSIG && validationEnabled()) {
auto rrsig = getRR<RRSIGRecordContent>(*entry);
if (rrsig) {
- if (isRRSIGNotExpired(d_now.tv_sec, rrsig)) {
+ if (isRRSIGNotExpired(d_now.tv_sec, *rrsig)) {
// we don't decrement d_sigexpire by 'now' because we actually want a TTD, not a TTL */
lowestTTD = min(lowestTTD, static_cast<uint32_t>(rrsig->d_sigexpire));
}
return result;
}
-vState SyncRes::validateDNSKeys(const DNSName& zone, const std::vector<DNSRecord>& dnskeys, const std::vector<std::shared_ptr<RRSIGRecordContent>>& signatures, unsigned int depth, const string& prefix)
+vState SyncRes::validateDNSKeys(const DNSName& zone, const std::vector<DNSRecord>& dnskeys, const std::vector<std::shared_ptr<const RRSIGRecordContent>>& signatures, unsigned int depth, const string& prefix)
{
dsmap_t ds;
if (signatures.empty()) {
return vState::BogusUnableToGetDNSKEYs;
}
-vState SyncRes::validateRecordsWithSigs(unsigned int depth, const string& prefix, const DNSName& qname, const QType qtype, const DNSName& name, const QType type, const std::vector<DNSRecord>& records, const std::vector<std::shared_ptr<RRSIGRecordContent>>& signatures)
+vState SyncRes::validateRecordsWithSigs(unsigned int depth, const string& prefix, const DNSName& qname, const QType qtype, const DNSName& name, const QType type, const std::vector<DNSRecord>& records, const std::vector<std::shared_ptr<const RRSIGRecordContent>>& signatures)
{
skeyset_t keys;
if (signatures.empty()) {
sortedRecords_t recordcontents;
for (const auto& record : records) {
- recordcontents.insert(record.d_content);
+ recordcontents.insert(record.getContent());
}
LOG(prefix << name << ": Going to validate " << recordcontents.size() << " record contents with " << signatures.size() << " sigs and " << keys.size() << " keys for " << name << "|" << type.toString() << endl);
}
if (!rec->d_name.isPartOf(auth)) {
- LOG(prefix << qname << ": Removing record '" << rec->d_name << "|" << DNSRecordContent::NumberToType(rec->d_type) << "|" << rec->d_content->getZoneRepresentation() << "' in the " << (int)rec->d_place << " section received from " << auth << endl);
+ LOG(prefix << qname << ": Removing record '" << rec->d_name << "|" << DNSRecordContent::NumberToType(rec->d_type) << "|" << rec->getContent()->getZoneRepresentation() << "' in the " << (int)rec->d_place << " section received from " << auth << endl);
rec = lwr.d_records.erase(rec);
continue;
}
/* for now we allow a CNAME for the exact qname in ANSWER with AA=0, because Amazon DNS servers
are sending such responses */
if (!(rec->d_type == QType::CNAME && qname == rec->d_name)) {
- LOG(prefix << qname << ": Removing record '" << rec->d_name << "|" << DNSRecordContent::NumberToType(rec->d_type) << "|" << rec->d_content->getZoneRepresentation() << "' in the answer section without the AA bit set received from " << auth << endl);
+ LOG(prefix << qname << ": Removing record '" << rec->d_name << "|" << DNSRecordContent::NumberToType(rec->d_type) << "|" << rec->getContent()->getZoneRepresentation() << "' in the answer section without the AA bit set received from " << auth << endl);
rec = lwr.d_records.erase(rec);
continue;
}
}
if (rec->d_type == QType::DNAME && (rec->d_place != DNSResourceRecord::ANSWER || !qname.isPartOf(rec->d_name))) {
- LOG(prefix << qname << ": Removing invalid DNAME record '" << rec->d_name << "|" << DNSRecordContent::NumberToType(rec->d_type) << "|" << rec->d_content->getZoneRepresentation() << "' in the " << (int)rec->d_place << " section received from " << auth << endl);
+ LOG(prefix << qname << ": Removing invalid DNAME record '" << rec->d_name << "|" << DNSRecordContent::NumberToType(rec->d_type) << "|" << rec->getContent()->getZoneRepresentation() << "' in the " << (int)rec->d_place << " section received from " << auth << endl);
rec = lwr.d_records.erase(rec);
continue;
}
if (rec->d_place == DNSResourceRecord::ANSWER && (qtype != QType::ANY && rec->d_type != qtype.getCode() && s_redirectionQTypes.count(rec->d_type) == 0 && rec->d_type != QType::SOA && rec->d_type != QType::RRSIG)) {
- LOG(prefix << qname << ": Removing irrelevant record '" << rec->d_name << "|" << DNSRecordContent::NumberToType(rec->d_type) << "|" << rec->d_content->getZoneRepresentation() << "' in the ANSWER section received from " << auth << endl);
+ LOG(prefix << qname << ": Removing irrelevant record '" << rec->d_name << "|" << DNSRecordContent::NumberToType(rec->d_type) << "|" << rec->getContent()->getZoneRepresentation() << "' in the ANSWER section received from " << auth << endl);
rec = lwr.d_records.erase(rec);
continue;
}
/* dealing with the records in authority */
if (rec->d_place == DNSResourceRecord::AUTHORITY && rec->d_type != QType::NS && rec->d_type != QType::DS && rec->d_type != QType::SOA && rec->d_type != QType::RRSIG && rec->d_type != QType::NSEC && rec->d_type != QType::NSEC3) {
- LOG(prefix << qname << ": Removing irrelevant record '" << rec->d_name << "|" << DNSRecordContent::NumberToType(rec->d_type) << "|" << rec->d_content->getZoneRepresentation() << "' in the AUTHORITY section received from " << auth << endl);
+ LOG(prefix << qname << ": Removing irrelevant record '" << rec->d_name << "|" << DNSRecordContent::NumberToType(rec->d_type) << "|" << rec->getContent()->getZoneRepresentation() << "' in the AUTHORITY section received from " << auth << endl);
rec = lwr.d_records.erase(rec);
continue;
}
if (rec->d_place == DNSResourceRecord::AUTHORITY && rec->d_type == QType::SOA) {
if (!qname.isPartOf(rec->d_name)) {
- LOG(prefix << qname << ": Removing irrelevant SOA record '" << rec->d_name << "|" << rec->d_content->getZoneRepresentation() << "' in the AUTHORITY section received from " << auth << endl);
+ LOG(prefix << qname << ": Removing irrelevant SOA record '" << rec->d_name << "|" << rec->getContent()->getZoneRepresentation() << "' in the AUTHORITY section received from " << auth << endl);
rec = lwr.d_records.erase(rec);
continue;
}
if (!(lwr.d_aabit || wasForwardRecurse)) {
- LOG(prefix << qname << ": Removing irrelevant record '" << rec->d_name << "|" << DNSRecordContent::NumberToType(rec->d_type) << "|" << rec->d_content->getZoneRepresentation() << "' in the AUTHORITY section received from " << auth << endl);
+ LOG(prefix << qname << ": Removing irrelevant record '" << rec->d_name << "|" << DNSRecordContent::NumberToType(rec->d_type) << "|" << rec->getContent()->getZoneRepresentation() << "' in the AUTHORITY section received from " << auth << endl);
rec = lwr.d_records.erase(rec);
continue;
}
* because they are somewhat easy to insert into a large, fragmented UDP response
* for an off-path attacker by injecting spoofed UDP fragments. So do not add these to allowedAdditionals.
*/
- LOG(prefix << qname << ": Removing NS record '" << rec->d_name << "|" << DNSRecordContent::NumberToType(rec->d_type) << "|" << rec->d_content->getZoneRepresentation() << "' in the " << (int)rec->d_place << " section of a " << (isNXDomain ? "NXD" : "NXQTYPE") << " response received from " << auth << endl);
+ LOG(prefix << qname << ": Removing NS record '" << rec->d_name << "|" << DNSRecordContent::NumberToType(rec->d_type) << "|" << rec->getContent()->getZoneRepresentation() << "' in the " << (int)rec->d_place << " section of a " << (isNXDomain ? "NXD" : "NXQTYPE") << " response received from " << auth << endl);
rec = lwr.d_records.erase(rec);
continue;
}
* We don't want to pick up root NS records in AUTHORITY and their associated ADDITIONAL sections of random queries.
* So don't add them to allowedAdditionals.
*/
- LOG(prefix << qname << ": Removing NS record '" << rec->d_name << "|" << DNSRecordContent::NumberToType(rec->d_type) << "|" << rec->d_content->getZoneRepresentation() << "' in the " << (int)rec->d_place << " section of a response received from " << auth << endl);
+ LOG(prefix << qname << ": Removing NS record '" << rec->d_name << "|" << DNSRecordContent::NumberToType(rec->d_type) << "|" << rec->getContent()->getZoneRepresentation() << "' in the " << (int)rec->d_place << " section of a response received from " << auth << endl);
rec = lwr.d_records.erase(rec);
continue;
}
/* dealing with the records in additional */
if (rec->d_place == DNSResourceRecord::ADDITIONAL && rec->d_type != QType::A && rec->d_type != QType::AAAA && rec->d_type != QType::RRSIG) {
- LOG(prefix << qname << ": Removing irrelevant record '" << rec->d_name << "|" << DNSRecordContent::NumberToType(rec->d_type) << "|" << rec->d_content->getZoneRepresentation() << "' in the ADDITIONAL section received from " << auth << endl);
+ LOG(prefix << qname << ": Removing irrelevant record '" << rec->d_name << "|" << DNSRecordContent::NumberToType(rec->d_type) << "|" << rec->getContent()->getZoneRepresentation() << "' in the ADDITIONAL section received from " << auth << endl);
rec = lwr.d_records.erase(rec);
continue;
}
if (rec->d_place == DNSResourceRecord::ADDITIONAL && allowedAdditionals.count(rec->d_name) == 0) {
- LOG(prefix << qname << ": Removing irrelevant additional record '" << rec->d_name << "|" << DNSRecordContent::NumberToType(rec->d_type) << "|" << rec->d_content->getZoneRepresentation() << "' in the ADDITIONAL section received from " << auth << endl);
+ LOG(prefix << qname << ": Removing irrelevant additional record '" << rec->d_name << "|" << DNSRecordContent::NumberToType(rec->d_type) << "|" << rec->getContent()->getZoneRepresentation() << "' in the ADDITIONAL section received from " << auth << endl);
rec = lwr.d_records.erase(rec);
continue;
}
count can be lower than the name's label count if it was
synthesized from the wildcard. Note that the difference might
be > 1. */
- if (rec.d_name == qname && isWildcardExpanded(labelCount, rrsig)) {
+ if (rec.d_name == qname && isWildcardExpanded(labelCount, *rrsig)) {
gatherWildcardProof = true;
- if (!isWildcardExpandedOntoItself(rec.d_name, labelCount, rrsig)) {
+ if (!isWildcardExpandedOntoItself(rec.d_name, labelCount, *rrsig)) {
/* if we have a wildcard expanded onto itself, we don't need to prove
that the exact name doesn't exist because it actually does.
We still want to gather the corresponding NSEC/NSEC3 records
continue;
}
- LOG(prefix << qname << ": Accept answer '" << rec.d_name << "|" << DNSRecordContent::NumberToType(rec.d_type) << "|" << rec.d_content->getZoneRepresentation() << "' from '" << auth << "' nameservers? ttl=" << rec.d_ttl << ", place=" << (int)rec.d_place << " ");
+ LOG(prefix << qname << ": Accept answer '" << rec.d_name << "|" << DNSRecordContent::NumberToType(rec.d_type) << "|" << rec.getContent()->getZoneRepresentation() << "' from '" << auth << "' nameservers? ttl=" << rec.d_ttl << ", place=" << (int)rec.d_place << " ");
// We called sanitizeRecords before, so all ANY, non-IN and non-aa/non-forwardrecurse answer records are already removed
wildcard in its non-expanded form in the cache to be able to synthesize wildcard answers later */
const auto& rrsig = i->second.signatures.at(0);
- if (isWildcardExpanded(labelCount, rrsig) && !isWildcardExpandedOntoItself(i->first.name, labelCount, rrsig)) {
+ if (isWildcardExpanded(labelCount, *rrsig) && !isWildcardExpandedOntoItself(i->first.name, labelCount, *rrsig)) {
DNSName realOwner = getNSECOwnerName(i->first.name, i->second.signatures);
std::vector<DNSRecord> content;
}
// for ANY answers we *must* have an authoritative answer, unless we are forwarding recursively
else if (rec.d_place == DNSResourceRecord::ANSWER && rec.d_name == qname && (rec.d_type == qtype.getCode() || ((lwr.d_aabit || sendRDQuery) && qtype == QType::ANY))) {
- LOG(prefix << qname << ": Answer is in: resolved to '" << rec.d_content->getZoneRepresentation() << "|" << DNSRecordContent::NumberToType(rec.d_type) << "'" << endl);
+ LOG(prefix << qname << ": Answer is in: resolved to '" << rec.getContent()->getZoneRepresentation() << "|" << DNSRecordContent::NumberToType(rec.d_type) << "'" << endl);
done = true;
rcode = RCode::NoError;
else if (rec.d_place == DNSResourceRecord::AUTHORITY && rec.d_type == QType::NS && qname.isPartOf(rec.d_name)) {
if (moreSpecificThan(rec.d_name, auth)) {
newauth = rec.d_name;
- LOG(prefix << qname << ": Got NS record '" << rec.d_name << "' -> '" << rec.d_content->getZoneRepresentation() << "'" << endl);
+ LOG(prefix << qname << ": Got NS record '" << rec.d_name << "' -> '" << rec.getContent()->getZoneRepresentation() << "'" << endl);
/* check if we have a referral from the parent zone to a child zone for a DS query, which is not right */
if (qtype == QType::DS && (newauth.isPartOf(qname) || qname == newauth)) {
}
}
else {
- LOG(prefix << qname << ": Got upwards/level NS record '" << rec.d_name << "' -> '" << rec.d_content->getZoneRepresentation() << "', had '" << auth << "'" << endl);
+ LOG(prefix << qname << ": Got upwards/level NS record '" << rec.d_name << "' -> '" << rec.getContent()->getZoneRepresentation() << "', had '" << auth << "'" << endl);
if (auto content = getRR<NSRecordContent>(rec)) {
nsset.insert(content->getNS());
}
}
}
else if (rec.d_place == DNSResourceRecord::AUTHORITY && rec.d_type == QType::DS && qname.isPartOf(rec.d_name)) {
- LOG(prefix << qname << ": Got DS record '" << rec.d_name << "' -> '" << rec.d_content->getZoneRepresentation() << "'" << endl);
+ LOG(prefix << qname << ": Got DS record '" << rec.d_name << "' -> '" << rec.getContent()->getZoneRepresentation() << "'" << endl);
}
else if (realreferral && rec.d_place == DNSResourceRecord::AUTHORITY && (rec.d_type == QType::NSEC || rec.d_type == QType::NSEC3) && newauth.isPartOf(auth)) {
/* we might have received a denial of the DS, let's check */
cnamerec.d_name = qname;
cnamerec.d_type = QType::CNAME;
cnamerec.d_ttl = dnameTTL;
- cnamerec.d_content = std::make_shared<CNAMERecordContent>(CNAMERecordContent(newtarget));
+ cnamerec.setContent(std::make_shared<CNAMERecordContent>(CNAMERecordContent(newtarget)));
ret.push_back(std::move(cnamerec));
}
if (s_addExtendedResolutionDNSErrors) {
extendedError = EDNSExtendedError{static_cast<uint16_t>(EDNSExtendedError::code::NoReachableAuthority), "Timeout waiting for answer(s)"};
}
- throw ImmediateServFailException("Too much time waiting for " + qname.toLogString() + "|" + qtype.toString() + ", timeouts: " + std::to_string(d_timeouts) + ", throttles: " + std::to_string(d_throttledqueries) + ", queries: " + std::to_string(d_outqueries) + ", " + std::to_string(d_totUsec / 1000) + "msec");
+ throw ImmediateServFailException("Too much time waiting for " + qname.toLogString() + "|" + qtype.toString() + ", timeouts: " + std::to_string(d_timeouts) + ", throttles: " + std::to_string(d_throttledqueries) + ", queries: " + std::to_string(d_outqueries) + ", " + std::to_string(d_totUsec / 1000) + " ms");
}
if (doTCP) {
}
d_totUsec += lwr.d_usec;
+
+ if (resolveret == LWResult::Result::Spoofed) {
+ spoofed = true;
+ return false;
+ }
+
accountAuthLatency(lwr.d_usec, remoteIP.sin4.sin_family);
++t_Counters.at(rec::RCode::auth).rcodeCounters.at(static_cast<uint8_t>(lwr.d_rcode));
if (resolveret == LWResult::Result::Timeout) {
/* Time out */
- LOG(prefix << qname << ": Timeout resolving after " << lwr.d_usec / 1000.0 << "msec " << (doTCP ? "over TCP" : "") << endl);
+ LOG(prefix << qname << ": Timeout resolving after " << lwr.d_usec / 1000.0 << " ms " << (doTCP ? "over TCP" : "") << endl);
d_timeouts++;
t_Counters.at(rec::Counter::outgoingtimeouts)++;
LOG(prefix << qname << ": Hit a local resource limit resolving" << (doTCP ? " over TCP" : "") << ", probable error: " << stringerror() << endl);
t_Counters.at(rec::Counter::resourceLimits)++;
}
- else if (resolveret == LWResult::Result::Spoofed) {
- spoofed = true;
- }
else {
/* LWResult::Result::PermanentError */
t_Counters.at(rec::Counter::unreachables)++;
return true;
}
-void SyncRes::handleNewTarget(const std::string& prefix, const DNSName& qname, const DNSName& newtarget, const QType qtype, std::vector<DNSRecord>& ret, int& rcode, int depth, const std::vector<DNSRecord>& recordsFromAnswer, vState& state)
+void SyncRes::handleNewTarget(const std::string& prefix, const DNSName& qname, const DNSName& newtarget, const QType qtype, std::vector<DNSRecord>& ret, int& rcode, unsigned int depth, const std::vector<DNSRecord>& recordsFromAnswer, vState& state)
{
if (newtarget == qname) {
LOG(prefix << qname << ": Status=got a CNAME referral to self, returning SERVFAIL" << endl);
setQNameMinimization(false);
}
- if (depth > 10) {
+ // Was 10 originally, default s_maxdepth is 40, but even if it is zero we want to apply a bound
+ auto bound = std::max(40U, getAdjustedRecursionBound()) / 4;
+ if (depth > bound) {
LOG(prefix << qname << ": Status=got a CNAME referral, but recursing too deep, returning SERVFAIL" << endl);
rcode = RCode::ServFail;
return;
if(remoteIP->sin4.sin_family==AF_INET6)
lwr.d_usec/=3;
*/
- // cout<<"msec: "<<lwr.d_usec/1000.0<<", "<<g_avgLatency/1000.0<<'\n';
+ // cout<<"ms: "<<lwr.d_usec/1000.0<<", "<<g_avgLatency/1000.0<<'\n';
s_nsSpeeds.lock()->find_or_enter(tns->first.empty() ? DNSName(remoteIP->toStringWithPort()) : tns->first, d_now).submit(*remoteIP, lwr.d_usec, d_now);
static unsigned int s_maxcachettl;
static unsigned int s_packetcachettl;
static unsigned int s_packetcacheservfailttl;
+ static unsigned int s_packetcachenegativettl;
static unsigned int s_serverdownmaxfails;
static unsigned int s_serverdownthrottletime;
static unsigned int s_nonresolvingnsmaxfails;
boost::optional<Netmask> getEDNSSubnetMask(const DNSName& dn, const ComboAddress& rem);
bool validationEnabled() const;
- uint32_t computeLowestTTD(const std::vector<DNSRecord>& records, const std::vector<std::shared_ptr<RRSIGRecordContent>>& signatures, uint32_t signaturesTTL, const std::vector<std::shared_ptr<DNSRecord>>& authorityRecs) const;
+ uint32_t computeLowestTTD(const std::vector<DNSRecord>& records, const std::vector<std::shared_ptr<const RRSIGRecordContent>>& signatures, uint32_t signaturesTTL, const std::vector<std::shared_ptr<DNSRecord>>& authorityRecs) const;
void updateValidationState(const DNSName& qname, vState& state, const vState stateUpdate, const string& prefix);
- vState validateRecordsWithSigs(unsigned int depth, const string& prefix, const DNSName& qname, const QType qtype, const DNSName& name, const QType type, const std::vector<DNSRecord>& records, const std::vector<std::shared_ptr<RRSIGRecordContent>>& signatures);
- vState validateDNSKeys(const DNSName& zone, const std::vector<DNSRecord>& dnskeys, const std::vector<std::shared_ptr<RRSIGRecordContent>>& signatures, unsigned int depth, const string& prefix);
+ vState validateRecordsWithSigs(unsigned int depth, const string& prefix, const DNSName& qname, const QType qtype, const DNSName& name, const QType type, const std::vector<DNSRecord>& records, const std::vector<std::shared_ptr<const RRSIGRecordContent>>& signatures);
+ vState validateDNSKeys(const DNSName& zone, const std::vector<DNSRecord>& dnskeys, const std::vector<std::shared_ptr<const RRSIGRecordContent>>& signatures, unsigned int depth, const string& prefix);
vState getDNSKeys(const DNSName& signer, skeyset_t& keys, bool& servFailOccurred, unsigned int depth, const string& prefix);
dState getDenialValidationState(const NegCache::NegCacheEntry& ne, const dState expectedState, bool referralToUnsigned, const string& prefix);
void updateDenialValidationState(const DNSName& qname, vState& neValidationState, const DNSName& neName, vState& state, const dState denialState, const dState expectedState, bool isDS, unsigned int depth, const string& prefix);
void initZoneCutsFromTA(const DNSName& from, const string& prefix);
size_t countSupportedDS(const dsmap_t& dsmap, const string& prefix);
- void handleNewTarget(const std::string& prefix, const DNSName& qname, const DNSName& newtarget, QType qtype, std::vector<DNSRecord>& ret, int& rcode, int depth, const std::vector<DNSRecord>& recordsFromAnswer, vState& state);
+ void handleNewTarget(const std::string& prefix, const DNSName& qname, const DNSName& newtarget, QType qtype, std::vector<DNSRecord>& ret, int& rcode, unsigned int depth, const std::vector<DNSRecord>& recordsFromAnswer, vState& state);
void handlePolicyHit(const std::string& prefix, const DNSName& qname, QType qtype, vector<DNSRecord>& ret, bool& done, int& rcode, unsigned int depth);
+ unsigned int getAdjustedRecursionBound() const;
void setUpdatingRootNS()
{
TCPAction highState{TCPAction::DoingRead};
IOState lowState{IOState::NeedRead};
- bool operator<(const PacketID& b) const
+ bool operator<(const PacketID& /* b */) const
{
// We don't want explicit PacketID compare here, but always via predicate classes below
assert(0);
uint64_t* pleaseGetFailedServersSize();
uint64_t* pleaseGetConcurrentQueries();
uint64_t* pleaseGetThrottleSize();
-uint64_t* pleaseGetPacketCacheHits();
-uint64_t* pleaseGetPacketCacheSize();
void doCarbonDump(void*);
bool primeHints(time_t now = time(nullptr));
const char* isoDateTimeMillis(const struct timeval& tv, char* buf, size_t sz);
size_t queriesCount = 0;
- sr->setAsyncCallback([target1, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target1, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
if (type == QType::DS || type == QType::DNSKEY) {
size_t queriesCount = 0;
- sr->setAsyncCallback([target, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
if (type == QType::DS || type == QType::DNSKEY) {
size_t queriesCount = 0;
- sr->setAsyncCallback([target, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
if (type == QType::DS || type == QType::DNSKEY) {
size_t queriesCount = 0;
- sr->setAsyncCallback([target, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
if (type == QType::DS || type == QType::DNSKEY) {
size_t queriesCount = 0;
- sr->setAsyncCallback([target, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
if (type == QType::DS || type == QType::DNSKEY) {
size_t queriesCount = 0;
- sr->setAsyncCallback([target1, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target1, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
if (type == QType::DS || type == QType::DNSKEY) {
size_t queriesCount = 0;
- sr->setAsyncCallback([target, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
if (type == QType::DS || type == QType::DNSKEY) {
size_t queriesCount = 0;
- sr->setAsyncCallback([target, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
if (type == QType::DS || type == QType::DNSKEY) {
size_t queriesCount = 0;
- sr->setAsyncCallback([target, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
if (type == QType::DS || type == QType::DNSKEY) {
size_t queriesCount = 0;
- sr->setAsyncCallback([target, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
if (type == QType::DS || type == QType::DNSKEY) {
rec.d_name = DNSName("www.powerdns.com");
rec.d_type = QType::NSEC;
rec.d_ttl = now.tv_sec + 10;
- rec.d_content = getRecordContent(QType::NSEC, "z.powerdns.com. A RRSIG NSEC");
+ rec.setContent(getRecordContent(QType::NSEC, "z.powerdns.com. A RRSIG NSEC"));
auto rrsig = std::make_shared<RRSIGRecordContent>("NSEC 5 3 10 20370101000000 20370101000000 24567 dummy. data");
cache->insertNSEC(DNSName("powerdns.com"), rec.d_name, rec, {rrsig}, false);
rec.d_name = DNSName("z.powerdns.com");
- rec.d_content = getRecordContent(QType::NSEC, "zz.powerdns.com. AAAA RRSIG NSEC");
+ rec.setContent(getRecordContent(QType::NSEC, "zz.powerdns.com. AAAA RRSIG NSEC"));
cache->insertNSEC(DNSName("powerdns.com"), rec.d_name, rec, {rrsig}, false);
rec.d_name = DNSName("www.powerdns.org");
rec.d_type = QType::NSEC3;
rec.d_ttl = now.tv_sec + 10;
- rec.d_content = getRecordContent(QType::NSEC3, "1 0 500 ab HASG==== A RRSIG NSEC3");
+ rec.setContent(getRecordContent(QType::NSEC3, "1 0 500 ab HASG==== A RRSIG NSEC3"));
rrsig = std::make_shared<RRSIGRecordContent>("NSEC3 5 3 10 20370101000000 20370101000000 24567 dummy. data");
cache->insertNSEC(DNSName("powerdns.org"), rec.d_name, rec, {rrsig}, true);
rec.d_name = DNSName("www.powerdns.com");
rec.d_type = QType::NSEC;
rec.d_ttl = now.tv_sec + 10;
- rec.d_content = getRecordContent(QType::NSEC, "z.powerdns.com. A RRSIG NSEC");
+ rec.setContent(getRecordContent(QType::NSEC, "z.powerdns.com. A RRSIG NSEC"));
auto rrsig = std::make_shared<RRSIGRecordContent>("NSEC 5 3 10 20370101000000 20370101000000 24567 dummy. data");
cache->insertNSEC(DNSName("powerdns.com"), rec.d_name, rec, {rrsig}, false);
rec.d_name = DNSName("z.powerdns.com");
- rec.d_content = getRecordContent(QType::NSEC, "zz.powerdns.com. AAAA RRSIG NSEC");
+ rec.setContent(getRecordContent(QType::NSEC, "zz.powerdns.com. AAAA RRSIG NSEC"));
cache->insertNSEC(DNSName("powerdns.com"), rec.d_name, rec, {rrsig}, false);
BOOST_CHECK_EQUAL(cache->getEntriesCount(), 2U);
rec.d_name = DNSName("www.powerdns.org");
rec.d_type = QType::NSEC3;
rec.d_ttl = now.tv_sec + 10;
- rec.d_content = getRecordContent(QType::NSEC3, "1 0 500 ab HASG==== A RRSIG NSEC3");
+ rec.setContent(getRecordContent(QType::NSEC3, "1 0 500 ab HASG==== A RRSIG NSEC3"));
rrsig = std::make_shared<RRSIGRecordContent>("NSEC3 5 3 10 20370101000000 20370101000000 24567 dummy. data");
cache->insertNSEC(DNSName("powerdns.org"), rec.d_name, rec, {rrsig}, true);
rec.d_name = DNSName("www.powerdns.com");
rec.d_type = QType::NSEC;
rec.d_ttl = now.tv_sec + 10;
- rec.d_content = getRecordContent(QType::NSEC, "z.powerdns.com. A RRSIG NSEC");
+ rec.setContent(getRecordContent(QType::NSEC, "z.powerdns.com. A RRSIG NSEC"));
auto rrsig = std::make_shared<RRSIGRecordContent>("NSEC 5 3 10 20370101000000 20370101000000 24567 dummy. data");
cache->insertNSEC(DNSName("powerdns.com"), rec.d_name, rec, {rrsig}, false);
rec.d_name = DNSName("z.powerdns.com");
- rec.d_content = getRecordContent(QType::NSEC, "zz.powerdns.com. AAAA RRSIG NSEC");
+ rec.setContent(getRecordContent(QType::NSEC, "zz.powerdns.com. AAAA RRSIG NSEC"));
cache->insertNSEC(DNSName("powerdns.com"), rec.d_name, rec, {rrsig}, false);
rec.d_name = DNSName("www.powerdns.org");
rec.d_type = QType::NSEC3;
rec.d_ttl = now.tv_sec + 10;
- rec.d_content = getRecordContent(QType::NSEC3, "1 0 50 ab HASG==== A RRSIG NSEC3");
+ rec.setContent(getRecordContent(QType::NSEC3, "1 0 50 ab HASG==== A RRSIG NSEC3"));
rrsig = std::make_shared<RRSIGRecordContent>("NSEC3 5 3 10 20370101000000 20370101000000 24567 dummy. data");
cache->insertNSEC(DNSName("powerdns.org"), rec.d_name, rec, {rrsig}, true);
drSOA.d_name = zone;
drSOA.d_type = QType::SOA;
drSOA.d_class = QClass::IN;
- drSOA.d_content = std::make_shared<SOARecordContent>("pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600");
+ drSOA.setContent(std::make_shared<SOARecordContent>("pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600"));
drSOA.d_ttl = static_cast<uint32_t>(ttd); // XXX truncation
drSOA.d_place = DNSResourceRecord::ANSWER;
records.push_back(drSOA);
nrc.set(type);
}
- rec.d_content = std::make_shared<NSEC3RecordContent>(nrc);
+ rec.setContent(std::make_shared<NSEC3RecordContent>(nrc));
auto rrsig = std::make_shared<RRSIGRecordContent>("NSEC3 5 3 10 20370101000000 20370101000000 24567 dummy. data");
cache->insertNSEC(zone, rec.d_name, rec, {rrsig}, true);
nrc.set(type);
}
- rec.d_content = std::make_shared<NSEC3RecordContent>(nrc);
+ rec.setContent(std::make_shared<NSEC3RecordContent>(nrc));
rrsig = std::make_shared<RRSIGRecordContent>("NSEC3 5 3 10 20370101000000 20370101000000 24567 dummy. data");
cache->insertNSEC(zone, rec.d_name, rec, {rrsig}, true);
nrc.set(type);
}
- rec.d_content = std::make_shared<NSEC3RecordContent>(nrc);
+ rec.setContent(std::make_shared<NSEC3RecordContent>(nrc));
rrsig = std::make_shared<RRSIGRecordContent>("NSEC3 5 3 10 20370101000000 20370101000000 24567 dummy. data");
cache->insertNSEC(zone, rec.d_name, rec, {rrsig}, true);
drSOA.d_name = zone;
drSOA.d_type = QType::SOA;
drSOA.d_class = QClass::IN;
- drSOA.d_content = std::make_shared<SOARecordContent>("pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600");
+ drSOA.setContent(std::make_shared<SOARecordContent>("pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600"));
drSOA.d_ttl = static_cast<uint32_t>(ttd); // XXX truncation
drSOA.d_place = DNSResourceRecord::ANSWER;
records.push_back(drSOA);
nrc.set(type);
}
- rec.d_content = std::make_shared<NSECRecordContent>(nrc);
+ rec.setContent(std::make_shared<NSECRecordContent>(nrc));
auto rrsig = std::make_shared<RRSIGRecordContent>("NSEC 5 3 10 20370101000000 20370101000000 24567 sub.powerdns.com. data");
cache->insertNSEC(zone, rec.d_name, rec, {rrsig}, false);
nrc.set(type);
}
- rec.d_content = std::make_shared<NSECRecordContent>(nrc);
+ rec.setContent(std::make_shared<NSECRecordContent>(nrc));
auto rrsig = std::make_shared<RRSIGRecordContent>("NSEC 5 3 10 20370101000000 20370101000000 24567 powerdns.com. data");
cache->insertNSEC(zone, rec.d_name, rec, {rrsig}, false);
nrc.set(type);
}
- rec.d_content = std::make_shared<NSECRecordContent>(nrc);
+ rec.setContent(std::make_shared<NSECRecordContent>(nrc));
auto rrsig = std::make_shared<RRSIGRecordContent>("NSEC 5 3 10 20370101000000 20370101000000 24567 powerdns.com. data");
cache->insertNSEC(zone, rec.d_name, rec, {rrsig}, false);
nrc.set(type);
}
- rec.d_content = std::make_shared<NSECRecordContent>(nrc);
+ rec.setContent(std::make_shared<NSECRecordContent>(nrc));
auto rrsig = std::make_shared<RRSIGRecordContent>("NSEC 5 3 10 20370101000000 20370101000000 24567 powerdns.com. data");
cache->insertNSEC(zone, rec.d_name, rec, {rrsig}, false);
nrc.set(type);
}
- rec.d_content = std::make_shared<NSECRecordContent>(nrc);
+ rec.setContent(std::make_shared<NSECRecordContent>(nrc));
auto rrsig = std::make_shared<RRSIGRecordContent>("NSEC 5 3 10 20370101000000 20370101000000 24567 powerdns.com. data");
cache->insertNSEC(zone, rec.d_name, rec, {rrsig}, false);
drSOA.d_name = zone;
drSOA.d_type = QType::SOA;
drSOA.d_class = QClass::IN;
- drSOA.d_content = std::make_shared<SOARecordContent>("pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600");
+ drSOA.setContent(std::make_shared<SOARecordContent>("pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600"));
drSOA.d_ttl = static_cast<uint32_t>(ttd); // XXX truncation
drSOA.d_place = DNSResourceRecord::ANSWER;
records.push_back(drSOA);
nrc.set(type);
}
- rec.d_content = std::make_shared<NSEC3RecordContent>(nrc);
+ rec.setContent(std::make_shared<NSEC3RecordContent>(nrc));
auto rrsig = std::make_shared<RRSIGRecordContent>("NSEC3 5 3 10 20370101000000 20370101000000 24567 sub.powerdns.com. data");
cache->insertNSEC(zone, rec.d_name, rec, {rrsig}, true);
nrc.set(type);
}
- rec.d_content = std::make_shared<NSEC3RecordContent>(nrc);
+ rec.setContent(std::make_shared<NSEC3RecordContent>(nrc));
auto rrsig = std::make_shared<RRSIGRecordContent>("NSEC3 5 3 10 20370101000000 20370101000000 24567 powerdns.com. data");
cache->insertNSEC(zone, rec.d_name, rec, {rrsig}, true);
nrc.set(type);
}
- rec.d_content = std::make_shared<NSEC3RecordContent>(nrc);
+ rec.setContent(std::make_shared<NSEC3RecordContent>(nrc));
auto rrsig = std::make_shared<RRSIGRecordContent>("NSEC3 5 3 10 20370101000000 20370101000000 24567 powerdns.com. data");
cache->insertNSEC(zone, rec.d_name, rec, {rrsig}, true);
nrc.set(type);
}
- rec.d_content = std::make_shared<NSEC3RecordContent>(nrc);
+ rec.setContent(std::make_shared<NSEC3RecordContent>(nrc));
auto rrsig = std::make_shared<RRSIGRecordContent>("NSEC3 5 3 10 20370101000000 20370101000000 24567 powerdns.com. data");
cache->insertNSEC(zone, rec.d_name, rec, {rrsig}, true);
nrc.set(type);
}
- rec.d_content = std::make_shared<NSEC3RecordContent>(nrc);
+ rec.setContent(std::make_shared<NSEC3RecordContent>(nrc));
auto rrsig = std::make_shared<RRSIGRecordContent>("NSEC3 5 3 10 20370101000000 20370101000000 24567 powerdns.com. data");
cache->insertNSEC(zone, rec.d_name, rec, {rrsig}, true);
nrc.set(type);
}
- rec.d_content = std::make_shared<NSEC3RecordContent>(nrc);
+ rec.setContent(std::make_shared<NSEC3RecordContent>(nrc));
auto rrsig = std::make_shared<RRSIGRecordContent>("NSEC3 5 3 10 20370101000000 20370101000000 24567 powerdns.com. data");
cache->insertNSEC(zone, rec.d_name, rec, {rrsig}, true);
nrc.set(type);
}
- rec.d_content = std::make_shared<NSEC3RecordContent>(nrc);
+ rec.setContent(std::make_shared<NSEC3RecordContent>(nrc));
auto rrsig = std::make_shared<RRSIGRecordContent>("NSEC3 5 3 10 20370101000000 20370101000000 24567 powerdns.com. data");
cache->insertNSEC(zone, rec.d_name, rec, {rrsig}, true);
nrc.set(type);
}
- rec.d_content = std::make_shared<NSEC3RecordContent>(nrc);
+ rec.setContent(std::make_shared<NSEC3RecordContent>(nrc));
auto rrsig = std::make_shared<RRSIGRecordContent>("NSEC3 5 3 10 20370101000000 20370101000000 24567 powerdns.com. data");
cache->insertNSEC(zone, rec.d_name, rec, {rrsig}, true);
nrc.set(type);
}
- rec.d_content = std::make_shared<NSEC3RecordContent>(nrc);
+ rec.setContent(std::make_shared<NSEC3RecordContent>(nrc));
auto rrsig = std::make_shared<RRSIGRecordContent>("NSEC3 5 3 10 20370101000000 20370101000000 24567 powerdns.com. data");
cache->insertNSEC(zone, rec.d_name, rec, {rrsig}, true);
/* blocked A */
DNSRecord dr;
dr.d_type = QType::A;
- dr.d_content = DNSRecordContent::mastermake(QType::A, QClass::IN, responseIP.toString());
+ dr.setContent(DNSRecordContent::mastermake(QType::A, QClass::IN, responseIP.toString()));
const auto matchingPolicy = dfe.getPostPolicy({dr}, std::unordered_map<std::string, bool>(), DNSFilterEngine::maximumPriority);
BOOST_CHECK(matchingPolicy.d_type == DNSFilterEngine::PolicyType::ResponseIP);
BOOST_CHECK(matchingPolicy.d_kind == DNSFilterEngine::PolicyKind::Drop);
/* allowed A */
DNSRecord dr;
dr.d_type = QType::A;
- dr.d_content = DNSRecordContent::mastermake(QType::A, QClass::IN, "192.0.2.142");
+ dr.setContent(DNSRecordContent::mastermake(QType::A, QClass::IN, "192.0.2.142"));
const auto matchingPolicy = dfe.getPostPolicy({dr}, std::unordered_map<std::string, bool>(), DNSFilterEngine::maximumPriority);
BOOST_CHECK(matchingPolicy.d_type == DNSFilterEngine::PolicyType::None);
DNSFilterEngine::Policy zonePolicy;
const auto& record = records.at(0);
BOOST_CHECK(record.d_type == QType::CNAME);
BOOST_CHECK(record.d_class == QClass::IN);
- auto content = std::dynamic_pointer_cast<CNAMERecordContent>(record.d_content);
+ auto content = getRR<CNAMERecordContent>(record);
BOOST_CHECK(content != nullptr);
BOOST_CHECK_EQUAL(content->getTarget().toString(), "garden.example.net.");
}
const auto& record = records.at(0);
BOOST_CHECK(record.d_type == QType::A);
BOOST_CHECK(record.d_class == QClass::IN);
- auto content = std::dynamic_pointer_cast<ARecordContent>(record.d_content);
+ auto content = getRR<ARecordContent>(record);
BOOST_CHECK(content != nullptr);
BOOST_CHECK_EQUAL(content->getCA().toString(), "192.0.2.1");
}
const auto& record = records.at(1);
BOOST_CHECK(record.d_type == QType::A);
BOOST_CHECK(record.d_class == QClass::IN);
- auto content = std::dynamic_pointer_cast<ARecordContent>(record.d_content);
+ auto content = getRR<ARecordContent>(record);
BOOST_CHECK(content != nullptr);
BOOST_CHECK_EQUAL(content->getCA().toString(), "192.0.2.2");
}
const auto& record = records.at(0);
BOOST_CHECK(record.d_type == QType::MX);
BOOST_CHECK(record.d_class == QClass::IN);
- auto content = std::dynamic_pointer_cast<MXRecordContent>(record.d_content);
+ auto content = getRR<MXRecordContent>(record);
BOOST_CHECK(content != nullptr);
BOOST_CHECK_EQUAL(content->d_mxname.toString(), "garden-mail.example.net.");
}
const auto& record = records.at(0);
BOOST_CHECK(record.d_type == QType::A);
BOOST_CHECK(record.d_class == QClass::IN);
- auto content = std::dynamic_pointer_cast<ARecordContent>(record.d_content);
+ auto content = getRR<ARecordContent>(record);
BOOST_CHECK(content != nullptr);
BOOST_CHECK_EQUAL(content->getCA().toString(), "192.0.2.2");
}
const auto& record = records.at(0);
BOOST_CHECK(record.d_type == QType::MX);
BOOST_CHECK(record.d_class == QClass::IN);
- auto content = std::dynamic_pointer_cast<MXRecordContent>(record.d_content);
+ auto content = getRR<MXRecordContent>(record);
BOOST_CHECK(content != nullptr);
BOOST_CHECK_EQUAL(content->d_mxname.toString(), "garden-mail.example.net.");
}
const auto& record1 = records.at(0);
BOOST_CHECK(record1.d_type == QType::A);
BOOST_CHECK(record1.d_class == QClass::IN);
- auto content1 = std::dynamic_pointer_cast<ARecordContent>(record1.d_content);
+ auto content1 = getRR<ARecordContent>(record1);
BOOST_CHECK(content1 != nullptr);
BOOST_CHECK_EQUAL(content1->getCA().toString(), "1.2.3.4");
const auto& record2 = records.at(1);
BOOST_CHECK(record2.d_type == QType::A);
BOOST_CHECK(record2.d_class == QClass::IN);
- auto content2 = std::dynamic_pointer_cast<ARecordContent>(record2.d_content);
+ auto content2 = getRR<ARecordContent>(record2);
BOOST_CHECK(content2 != nullptr);
BOOST_CHECK_EQUAL(content2->getCA().toString(), "1.2.3.5");
}
const auto& record1 = records.at(0);
BOOST_CHECK(record1.d_type == QType::AAAA);
BOOST_CHECK(record1.d_class == QClass::IN);
- auto content1 = std::dynamic_pointer_cast<AAAARecordContent>(record1.d_content);
+ auto content1 = getRR<AAAARecordContent>(record1);
BOOST_CHECK(content1 != nullptr);
BOOST_CHECK_EQUAL(content1->getCA().toString(), "::1234");
}
const auto& record1 = records.at(0);
BOOST_CHECK(record1.d_type == QType::A);
BOOST_CHECK(record1.d_class == QClass::IN);
- auto content1 = std::dynamic_pointer_cast<ARecordContent>(record1.d_content);
+ auto content1 = getRR<ARecordContent>(record1);
BOOST_CHECK(content1 != nullptr);
BOOST_CHECK_EQUAL(content1->getCA().toString(), "1.2.3.4");
}
const auto& record1 = records.at(0);
BOOST_CHECK(record1.d_type == QType::AAAA);
BOOST_CHECK(record1.d_class == QClass::IN);
- auto content1 = std::dynamic_pointer_cast<AAAARecordContent>(record1.d_content);
+ auto content1 = getRR<AAAARecordContent>(record1);
BOOST_CHECK(content1 != nullptr);
BOOST_CHECK_EQUAL(content1->getCA().toString(), "::1234");
}
const auto& record1 = records.at(0);
BOOST_CHECK(record1.d_type == QType::AAAA);
BOOST_CHECK(record1.d_class == QClass::IN);
- auto content1 = std::dynamic_pointer_cast<AAAARecordContent>(record1.d_content);
+ auto content1 = getRR<AAAARecordContent>(record1);
BOOST_CHECK(content1 != nullptr);
BOOST_CHECK_EQUAL(content1->getCA().toString(), "::1234");
}
const auto& record = records.at(0);
BOOST_CHECK(record.d_type == QType::CNAME);
BOOST_CHECK(record.d_class == QClass::IN);
- auto content = std::dynamic_pointer_cast<CNAMERecordContent>(record.d_content);
+ auto content = getRR<CNAMERecordContent>(record);
BOOST_CHECK(content != nullptr);
BOOST_CHECK_EQUAL(content->getTarget().toString(), "garden1a.example.net.");
}
const auto& record = records.at(0);
BOOST_CHECK(record.d_type == QType::CNAME);
BOOST_CHECK(record.d_class == QClass::IN);
- auto content = std::dynamic_pointer_cast<CNAMERecordContent>(record.d_content);
+ auto content = getRR<CNAMERecordContent>(record);
BOOST_CHECK(content != nullptr);
BOOST_CHECK_EQUAL(content->getTarget().toString(), "garden1b.example.net.");
}
const auto& record = records.at(0);
BOOST_CHECK(record.d_type == QType::CNAME);
BOOST_CHECK(record.d_class == QClass::IN);
- auto content = std::dynamic_pointer_cast<CNAMERecordContent>(record.d_content);
+ auto content = getRR<CNAMERecordContent>(record);
BOOST_CHECK(content != nullptr);
BOOST_CHECK_EQUAL(content->getTarget().toString(), "garden1a.example.net.");
}
const auto& record = records.at(0);
BOOST_CHECK(record.d_type == QType::CNAME);
BOOST_CHECK(record.d_class == QClass::IN);
- auto content = std::dynamic_pointer_cast<CNAMERecordContent>(record.d_content);
+ auto content = getRR<CNAMERecordContent>(record);
BOOST_CHECK(content != nullptr);
BOOST_CHECK_EQUAL(content->getTarget().toString(), "garden2a.example.net.");
}
const auto& record = records.at(0);
BOOST_CHECK(record.d_type == QType::CNAME);
BOOST_CHECK(record.d_class == QClass::IN);
- auto content = std::dynamic_pointer_cast<CNAMERecordContent>(record.d_content);
+ auto content = getRR<CNAMERecordContent>(record);
BOOST_CHECK(content != nullptr);
BOOST_CHECK_EQUAL(content->getTarget().toString(), "client1a.example.net.");
}
const auto& record = records.at(0);
BOOST_CHECK(record.d_type == QType::CNAME);
BOOST_CHECK(record.d_class == QClass::IN);
- auto content = std::dynamic_pointer_cast<CNAMERecordContent>(record.d_content);
+ auto content = getRR<CNAMERecordContent>(record);
BOOST_CHECK(content != nullptr);
BOOST_CHECK_EQUAL(content->getTarget().toString(), "garden1a.example.net.");
}
const auto& record = records.at(0);
BOOST_CHECK(record.d_type == QType::CNAME);
BOOST_CHECK(record.d_class == QClass::IN);
- auto content = std::dynamic_pointer_cast<CNAMERecordContent>(record.d_content);
+ auto content = getRR<CNAMERecordContent>(record);
BOOST_CHECK(content != nullptr);
BOOST_CHECK_EQUAL(content->getTarget().toString(), "garden1a.example.net.");
}
const auto& record = records.at(0);
BOOST_CHECK(record.d_type == QType::CNAME);
BOOST_CHECK(record.d_class == QClass::IN);
- auto content = std::dynamic_pointer_cast<CNAMERecordContent>(record.d_content);
+ auto content = getRR<CNAMERecordContent>(record);
BOOST_CHECK(content != nullptr);
BOOST_CHECK_EQUAL(content->getTarget().toString(), "garden2a.example.net.");
}
const auto& record = records.at(0);
BOOST_CHECK(record.d_type == QType::CNAME);
BOOST_CHECK(record.d_class == QClass::IN);
- auto content = std::dynamic_pointer_cast<CNAMERecordContent>(record.d_content);
+ auto content = getRR<CNAMERecordContent>(record);
BOOST_CHECK(content != nullptr);
BOOST_CHECK_EQUAL(content->getTarget().toString(), "nsname1a.example.net.");
}
const auto& record = records.at(0);
BOOST_CHECK(record.d_type == QType::CNAME);
BOOST_CHECK(record.d_class == QClass::IN);
- auto content = std::dynamic_pointer_cast<CNAMERecordContent>(record.d_content);
+ auto content = getRR<CNAMERecordContent>(record);
BOOST_CHECK(content != nullptr);
BOOST_CHECK_EQUAL(content->getTarget().toString(), "nsip1a.example.net.");
}
/* blocked A in the response */
DNSRecord dr;
dr.d_type = QType::A;
- dr.d_content = DNSRecordContent::mastermake(QType::A, QClass::IN, responseIP.toString());
+ dr.setContent(DNSRecordContent::mastermake(QType::A, QClass::IN, responseIP.toString()));
const auto matchingPolicy = dfe.getPostPolicy({dr}, std::unordered_map<std::string, bool>(), DNSFilterEngine::maximumPriority);
BOOST_CHECK(matchingPolicy.d_type == DNSFilterEngine::PolicyType::ResponseIP);
BOOST_CHECK(matchingPolicy.d_kind == DNSFilterEngine::PolicyKind::Custom);
const auto& record = records.at(0);
BOOST_CHECK(record.d_type == QType::CNAME);
BOOST_CHECK(record.d_class == QClass::IN);
- auto content = std::dynamic_pointer_cast<CNAMERecordContent>(record.d_content);
+ auto content = getRR<CNAMERecordContent>(record);
BOOST_CHECK(content != nullptr);
BOOST_CHECK_EQUAL(content->getTarget().toString(), "response1a.example.net.");
}
/* blocked A in the response, except 1 is disabled and 2's priority is too high */
DNSRecord dr;
dr.d_type = QType::A;
- dr.d_content = DNSRecordContent::mastermake(QType::A, QClass::IN, responseIP.toString());
+ dr.setContent(DNSRecordContent::mastermake(QType::A, QClass::IN, responseIP.toString()));
const auto matchingPolicy = dfe.getPostPolicy({dr}, {{zone1->getName(), true}}, 1);
BOOST_CHECK(matchingPolicy.d_type == DNSFilterEngine::PolicyType::None);
BOOST_CHECK(matchingPolicy.d_kind == DNSFilterEngine::PolicyKind::NoAction);
#else
-static void willThrow(void* p)
+static void willThrow(void* /* p */)
{
throw std::runtime_error("Help!");
}
rec.d_type = qtype;
rec.d_ttl = 600;
rec.d_place = DNSResourceRecord::AUTHORITY;
- rec.d_content = DNSRecordContent::mastermake(qtype, QClass::IN, content);
+ rec.setContent(DNSRecordContent::mastermake(qtype, QClass::IN, content));
ret.records.push_back(rec);
if (sigs) {
rec.d_type = QType::RRSIG;
- rec.d_content = std::make_shared<RRSIGRecordContent>(QType(qtype).toString() + " 5 3 600 2037010100000000 2037010100000000 24567 dummy data");
+ rec.setContent(std::make_shared<RRSIGRecordContent>(QType(qtype).toString() + " 5 3 600 2037010100000000 2037010100000000 24567 dummy data"));
ret.signatures.push_back(rec);
}
if (!fp)
BOOST_FAIL("Temporary file could not be opened");
- cache.doDump(fileno(fp.get()), 0);
+ cache.doDump(fileno(fp.get()), 0, now.tv_sec);
rewind(fp.get());
char* line = nullptr;
BOOST_AUTO_TEST_SUITE(nod_cc)
-static bool pdns_exception(PDNSException const& ex) { return true; }
+static bool pdns_exception(PDNSException const& /* ex */) { return true; }
BOOST_AUTO_TEST_CASE(test_basic)
{
std::vector<DNSRecord> records;
std::vector<std::shared_ptr<DNSRecord>> authRecords;
- std::vector<std::shared_ptr<RRSIGRecordContent>> signatures;
+ std::vector<std::shared_ptr<const RRSIGRecordContent>> signatures;
const DNSName authZone(".");
time_t ttd = now + 30;
dr0.d_name = power;
dr0.d_type = QType::AAAA;
dr0.d_class = QClass::IN;
- dr0.d_content = std::make_shared<AAAARecordContent>(dr0Content);
+ dr0.setContent(std::make_shared<AAAARecordContent>(dr0Content));
dr0.d_ttl = static_cast<uint32_t>(ttd); // XXX truncation
dr0.d_place = DNSResourceRecord::ANSWER;
dr1.d_name = power;
dr1.d_type = QType::AAAA;
dr1.d_class = QClass::IN;
- dr1.d_content = std::make_shared<AAAARecordContent>(dr1Content);
+ dr1.setContent(std::make_shared<AAAARecordContent>(dr1Content));
dr1.d_ttl = static_cast<uint32_t>(ttd); // XXX truncation
dr1.d_place = DNSResourceRecord::ANSWER;
dr2.d_name = power;
dr2.d_type = QType::A;
dr2.d_class = QClass::IN;
- dr2.d_content = std::make_shared<ARecordContent>(dr2Content);
+ dr2.setContent(std::make_shared<ARecordContent>(dr2Content));
dr2.d_ttl = static_cast<uint32_t>(ttd); // XXX truncation
// the place should not matter to the cache
dr2.d_place = DNSResourceRecord::AUTHORITY;
dr3.d_name = power;
dr3.d_type = QType::A;
dr3.d_class = QClass::IN;
- dr3.d_content = std::make_shared<ARecordContent>(dr3Content);
+ dr3.setContent(std::make_shared<ARecordContent>(dr3Content));
dr3.d_ttl = static_cast<uint32_t>(ttd + 100); // XXX truncation
// the place should not matter to the cache
dr3.d_place = DNSResourceRecord::AUTHORITY;
dr4.d_name = power;
dr4.d_type = QType::A;
dr4.d_class = QClass::IN;
- dr4.d_content = std::make_shared<ARecordContent>(dr4Content);
+ dr4.setContent(std::make_shared<ARecordContent>(dr4Content));
dr4.d_ttl = static_cast<uint32_t>(ttd); // XXX truncation
dr4.d_place = DNSResourceRecord::AUTHORITY;
std::vector<DNSRecord> records;
std::vector<std::shared_ptr<DNSRecord>> authRecords;
- std::vector<std::shared_ptr<RRSIGRecordContent>> signatures;
+ std::vector<std::shared_ptr<const RRSIGRecordContent>> signatures;
time_t now = time(nullptr);
BOOST_CHECK_EQUAL(MRC.size(), 0U);
ns1.d_name = ghost;
ns1.d_type = QType::NS;
ns1.d_class = QClass::IN;
- ns1.d_content = std::make_shared<NSRecordContent>(ns1Content);
+ ns1.setContent(std::make_shared<NSRecordContent>(ns1Content));
ns1.d_ttl = static_cast<uint32_t>(ttd); // XXX truncation
ns1.d_place = DNSResourceRecord::ANSWER;
records.push_back(ns1);
std::vector<DNSRecord> records;
std::vector<std::shared_ptr<DNSRecord>> authRecords;
- std::vector<std::shared_ptr<RRSIGRecordContent>> signatures;
+ std::vector<std::shared_ptr<const RRSIGRecordContent>> signatures;
time_t now = time(nullptr);
BOOST_CHECK_EQUAL(MRC.size(), 0U);
ns1.d_name = record1;
ns1.d_type = QType::NS;
ns1.d_class = QClass::IN;
- ns1.d_content = std::make_shared<NSRecordContent>(record1);
+ ns1.setContent(std::make_shared<NSRecordContent>(record1));
ns1.d_ttl = static_cast<uint32_t>(ttd); // XXX truncation
ns1.d_place = DNSResourceRecord::ANSWER;
records.push_back(ns1);
MemRecursorCache MRC(1);
std::vector<DNSRecord> records;
- std::vector<std::shared_ptr<RRSIGRecordContent>> signatures;
+ std::vector<std::shared_ptr<const RRSIGRecordContent>> signatures;
std::vector<std::shared_ptr<DNSRecord>> authRecs;
const DNSName authZone(".");
BOOST_CHECK_EQUAL(MRC.size(), 0U);
dr1.d_name = power1;
dr1.d_type = QType::AAAA;
dr1.d_class = QClass::IN;
- dr1.d_content = std::make_shared<AAAARecordContent>(dr1Content);
+ dr1.setContent(std::make_shared<AAAARecordContent>(dr1Content));
dr1.d_ttl = static_cast<uint32_t>(ttd); // XXX truncation
dr1.d_place = DNSResourceRecord::ANSWER;
dr2.d_name = power2;
dr2.d_type = QType::AAAA;
dr2.d_class = QClass::IN;
- dr2.d_content = std::make_shared<AAAARecordContent>(dr2Content);
+ dr2.setContent(std::make_shared<AAAARecordContent>(dr2Content));
dr2.d_ttl = static_cast<uint32_t>(ttd); // XXX truncation
dr2.d_place = DNSResourceRecord::ANSWER;
MemRecursorCache MRC(1);
std::vector<DNSRecord> records;
- std::vector<std::shared_ptr<RRSIGRecordContent>> signatures;
+ std::vector<std::shared_ptr<const RRSIGRecordContent>> signatures;
std::vector<std::shared_ptr<DNSRecord>> authRecs;
const DNSName authZone(".");
BOOST_CHECK_EQUAL(MRC.size(), 0U);
dr1.d_name = power1;
dr1.d_type = QType::AAAA;
dr1.d_class = QClass::IN;
- dr1.d_content = std::make_shared<AAAARecordContent>(dr1Content);
+ dr1.setContent(std::make_shared<AAAARecordContent>(dr1Content));
dr1.d_ttl = static_cast<uint32_t>(ttd);
dr1.d_place = DNSResourceRecord::ANSWER;
dr2.d_name = power2;
dr2.d_type = QType::AAAA;
dr2.d_class = QClass::IN;
- dr2.d_content = std::make_shared<AAAARecordContent>(dr2Content);
+ dr2.setContent(std::make_shared<AAAARecordContent>(dr2Content));
dr2.d_ttl = static_cast<uint32_t>(ttd);
dr2.d_place = DNSResourceRecord::ANSWER;
r1.d_name = power1;
r1.d_type = QType::A;
r1.d_class = QClass::IN;
- r1.d_content = std::make_shared<ARecordContent>(r1Content);
+ r1.setContent(std::make_shared<ARecordContent>(r1Content));
r1.d_ttl = static_cast<uint32_t>(ttd);
r1.d_place = DNSResourceRecord::ANSWER;
records.push_back(r1);
const DNSName authZone(".");
std::vector<DNSRecord> records;
std::vector<std::shared_ptr<DNSRecord>> authRecords;
- std::vector<std::shared_ptr<RRSIGRecordContent>> signatures;
+ std::vector<std::shared_ptr<const RRSIGRecordContent>> signatures;
time_t now = time(nullptr);
std::vector<DNSRecord> retrieved;
ComboAddress who("192.0.2.1");
dr1.d_name = power;
dr1.d_type = QType::A;
dr1.d_class = QClass::IN;
- dr1.d_content = std::make_shared<ARecordContent>(dr1Content);
+ dr1.setContent(std::make_shared<ARecordContent>(dr1Content));
dr1.d_ttl = static_cast<uint32_t>(ttd);
dr1.d_place = DNSResourceRecord::ANSWER;
dr2.d_name = power;
dr2.d_type = QType::A;
dr2.d_class = QClass::IN;
- dr2.d_content = std::make_shared<ARecordContent>(dr2Content);
+ dr2.setContent(std::make_shared<ARecordContent>(dr2Content));
dr2.d_ttl = static_cast<uint32_t>(now + 5);
dr2.d_place = DNSResourceRecord::ANSWER;
const DNSName authZone(".");
std::vector<DNSRecord> records;
std::vector<std::shared_ptr<DNSRecord>> authRecords;
- std::vector<std::shared_ptr<RRSIGRecordContent>> signatures;
+ std::vector<std::shared_ptr<const RRSIGRecordContent>> signatures;
time_t now = time(nullptr);
std::vector<DNSRecord> retrieved;
ComboAddress who("192.0.2.1");
dr1.d_name = power;
dr1.d_type = QType::A;
dr1.d_class = QClass::IN;
- dr1.d_content = std::make_shared<ARecordContent>(dr1Content);
+ dr1.setContent(std::make_shared<ARecordContent>(dr1Content));
dr1.d_ttl = static_cast<uint32_t>(ttd);
dr1.d_place = DNSResourceRecord::ANSWER;
const DNSName authZone(".");
std::vector<std::shared_ptr<DNSRecord>> authRecords;
- std::vector<std::shared_ptr<RRSIGRecordContent>> signatures;
+ std::vector<std::shared_ptr<const RRSIGRecordContent>> signatures;
time_t now = time(nullptr);
time_t ttd = now + 30;
dr0.d_name = power;
dr0.d_type = QType::A;
dr0.d_class = QClass::IN;
- dr0.d_content = std::make_shared<ARecordContent>(dr0Content);
+ dr0.setContent(std::make_shared<ARecordContent>(dr0Content));
dr0.d_ttl = static_cast<uint32_t>(ttd);
dr0.d_place = DNSResourceRecord::ANSWER;
std::vector<DNSRecord> rset0;
dr0tagged.d_name = power;
dr0tagged.d_type = QType::A;
dr0tagged.d_class = QClass::IN;
- dr0tagged.d_content = std::make_shared<ARecordContent>(dr0taggedContent);
+ dr0tagged.setContent(std::make_shared<ARecordContent>(dr0taggedContent));
dr0tagged.d_ttl = static_cast<uint32_t>(ttd);
dr0tagged.d_place = DNSResourceRecord::ANSWER;
std::vector<DNSRecord> rset0tagged;
dr1.d_name = power;
dr1.d_type = QType::A;
dr1.d_class = QClass::IN;
- dr1.d_content = std::make_shared<ARecordContent>(dr1Content);
+ dr1.setContent(std::make_shared<ARecordContent>(dr1Content));
dr1.d_ttl = static_cast<uint32_t>(ttd);
dr1.d_place = DNSResourceRecord::ANSWER;
std::vector<DNSRecord> rset1;
dr2.d_name = power;
dr2.d_type = QType::A;
dr2.d_class = QClass::IN;
- dr2.d_content = std::make_shared<ARecordContent>(dr2Content);
+ dr2.setContent(std::make_shared<ARecordContent>(dr2Content));
dr2.d_ttl = static_cast<uint32_t>(ttd);
dr2.d_place = DNSResourceRecord::ANSWER;
std::vector<DNSRecord> rset2;
dr3.d_name = power;
dr3.d_type = QType::A;
dr3.d_class = QClass::IN;
- dr3.d_content = std::make_shared<ARecordContent>(dr3Content);
+ dr3.setContent(std::make_shared<ARecordContent>(dr3Content));
dr3.d_ttl = static_cast<uint32_t>(ttd);
dr3.d_place = DNSResourceRecord::ANSWER;
std::vector<DNSRecord> rset3;
BOOST_TEST_MESSAGE("-----------------------------------------------------");
}
+const std::string hints = ". 3600 IN NS ns.\n"
+ ". 3600 IN NS ns1.\n"
+ "ns. 3600 IN A 192.168.178.16\n"
+ "ns. 3600 IN A 192.168.178.17\n"
+ "ns. 3600 IN A 192.168.178.18\n"
+ "ns. 3600 IN AAAA 1::2\n"
+ "ns. 3600 IN AAAA 1::3\n"
+ "ns1. 3600 IN A 192.168.178.18\n";
+
+BOOST_AUTO_TEST_CASE(test_UserHints)
+{
+
+ g_recCache = make_unique<MemRecursorCache>();
+
+ ::arg().set("max-generate-steps") = "0";
+ ::arg().set("max-include-depth") = "0";
+ char temp[] = "/tmp/hintsXXXXXXXXXX";
+ int fd = mkstemp(temp);
+ BOOST_REQUIRE(fd > 0);
+ FILE* fp = fdopen(fd, "w");
+ BOOST_REQUIRE(fp != nullptr);
+ size_t written = fwrite(hints.data(), 1, hints.length(), fp);
+ BOOST_REQUIRE(written == hints.length());
+ BOOST_REQUIRE(fclose(fp) == 0);
+
+ time_t now = time(nullptr);
+ std::vector<DNSRecord> nsvec;
+
+ auto ok = readHintsIntoCache(now, std::string(temp), nsvec);
+ BOOST_CHECK(ok);
+ BOOST_CHECK_EQUAL(nsvec.size(), 2U);
+
+ const MemRecursorCache::Flags flags = 0;
+
+ BOOST_CHECK(g_recCache->get(now, DNSName("ns"), QType::A, flags, &nsvec, ComboAddress()) > 0);
+ BOOST_CHECK_EQUAL(nsvec.size(), 3U);
+
+ BOOST_CHECK(g_recCache->get(now, DNSName("ns"), QType::AAAA, flags, &nsvec, ComboAddress()) > 0);
+ BOOST_CHECK_EQUAL(nsvec.size(), 2U);
+
+ BOOST_CHECK(g_recCache->get(now, DNSName("ns1"), QType::A, flags, &nsvec, ComboAddress()) > 0);
+ BOOST_CHECK_EQUAL(nsvec.size(), 1U);
+}
+
BOOST_AUTO_TEST_SUITE_END()
{
}
-void BaseLua4::getFeatures(Features&)
+void BaseLua4::getFeatures(Features& /* features */)
{
}
-bool RecursorLua4::preoutquery(const ComboAddress& ns, const ComboAddress& requestor, const DNSName& query, const QType& qtype, bool isTcp, vector<DNSRecord>& res, int& ret, RecEventTrace& et, const struct timeval& tv) const
+bool RecursorLua4::preoutquery(const ComboAddress& /* ns */, const ComboAddress& /* requestor */, const DNSName& /* query */, const QType& /* qtype */, bool /* isTcp */, vector<DNSRecord>& /* res */, int& /* ret */, RecEventTrace& /* et */, const struct timeval& /* tv */) const
{
return false;
}
-bool RecursorLua4::policyHitEventFilter(const ComboAddress& remote, const DNSName& qname, const QType& qtype, bool tcp, DNSFilterEngine::Policy& policy, std::unordered_set<std::string>& tags, std::unordered_map<std::string, bool>& discardedPolicies) const
+bool RecursorLua4::policyHitEventFilter(const ComboAddress& /* remote */, const DNSName& /* qname */, const QType& /* qtype */, bool /* tcp */, DNSFilterEngine::Policy& /* policy */, std::unordered_set<std::string>& /* tags */, std::unordered_map<std::string, bool>& /* discardedPolicies */) const
{
return false;
}
{
}
-void RecursorLua4::getFeatures(Features& features)
+void RecursorLua4::getFeatures(Features& /* features */)
{
}
-LWResult::Result asyncresolve(const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, const std::shared_ptr<std::vector<std::unique_ptr<RemoteLogger>>>& outgoingLoggers, const std::shared_ptr<std::vector<std::unique_ptr<FrameStreamLogger>>>& fstrmLoggers, const std::set<uint16_t>& exportTypes, LWResult* res, bool* chained)
+LWResult::Result asyncresolve(const ComboAddress& /* ip */, const DNSName& /* domain */, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, const std::shared_ptr<std::vector<std::unique_ptr<RemoteLogger>>>& /* outgoingLoggers */, const std::shared_ptr<std::vector<std::unique_ptr<FrameStreamLogger>>>& /* fstrmLoggers */, const std::set<uint16_t>& /* exportTypes */, LWResult* /* res */, bool* /* chained */)
{
return LWResult::Result::Timeout;
}
templ[sizeof(templ) - 1] = '\0';
*templ = c;
aaaarr.d_name = arr.d_name = DNSName(templ);
- nsrr.d_content = std::make_shared<NSRecordContent>(DNSName(templ));
- arr.d_content = std::make_shared<ARecordContent>(ComboAddress(rootIps4[c - 'a']));
+ nsrr.setContent(std::make_shared<NSRecordContent>(DNSName(templ)));
+ arr.setContent(std::make_shared<ARecordContent>(ComboAddress(rootIps4[c - 'a'])));
vector<DNSRecord> aset;
aset.push_back(arr);
- g_recCache->replace(now, DNSName(templ), QType(QType::A), aset, vector<std::shared_ptr<RRSIGRecordContent>>(), vector<std::shared_ptr<DNSRecord>>(), false, g_rootdnsname);
- if (rootIps6[c - 'a'] != NULL) {
- aaaarr.d_content = std::make_shared<AAAARecordContent>(ComboAddress(rootIps6[c - 'a']));
+ g_recCache->replace(now, DNSName(templ), QType(QType::A), aset, vector<std::shared_ptr<const RRSIGRecordContent>>(), vector<std::shared_ptr<DNSRecord>>(), false, g_rootdnsname);
+ if (!rootIps6[c - 'a'].empty()) {
+ aaaarr.setContent(std::make_shared<AAAARecordContent>(ComboAddress(rootIps6[c - 'a'])));
vector<DNSRecord> aaaaset;
aaaaset.push_back(aaaarr);
- g_recCache->replace(now, DNSName(templ), QType(QType::AAAA), aaaaset, vector<std::shared_ptr<RRSIGRecordContent>>(), vector<std::shared_ptr<DNSRecord>>(), false, g_rootdnsname);
+ g_recCache->replace(now, DNSName(templ), QType(QType::AAAA), aaaaset, vector<std::shared_ptr<const RRSIGRecordContent>>(), vector<std::shared_ptr<DNSRecord>>(), false, g_rootdnsname);
}
nsset.push_back(nsrr);
}
- g_recCache->replace(now, g_rootdnsname, QType(QType::NS), nsset, vector<std::shared_ptr<RRSIGRecordContent>>(), vector<std::shared_ptr<DNSRecord>>(), false, g_rootdnsname); // and stuff in the cache
+ g_recCache->replace(now, g_rootdnsname, QType(QType::NS), nsset, vector<std::shared_ptr<const RRSIGRecordContent>>(), vector<std::shared_ptr<DNSRecord>>(), false, g_rootdnsname); // and stuff in the cache
return true;
}
bool isRootServer(const ComboAddress& ip)
{
if (ip.isIPv4()) {
- for (size_t idx = 0; idx < rootIps4Count; idx++) {
+ for (size_t idx = 0; idx < rootIps4.size(); idx++) {
if (ip.toString() == rootIps4[idx]) {
return true;
}
}
}
else {
- for (size_t idx = 0; idx < rootIps6Count; idx++) {
+ for (size_t idx = 0; idx < rootIps6.size(); idx++) {
if (ip.toString() == rootIps6[idx]) {
return true;
}
sortedRecords_t recordcontents;
for (const auto& record : records) {
if (record.d_name == name && record.d_type == type) {
- recordcontents.insert(record.d_content);
+ recordcontents.insert(record.getContent());
}
}
rec.d_name = records[recordsCount - 1].d_name;
rec.d_ttl = records[recordsCount - 1].d_ttl;
- rec.d_content = std::make_shared<RRSIGRecordContent>(rrc);
+ rec.setContent(std::make_shared<RRSIGRecordContent>(rrc));
records.push_back(rec);
return true;
rec.d_type = QType::DNSKEY;
rec.d_ttl = ttl;
- rec.d_content = std::make_shared<DNSKEYRecordContent>(it->second.first.getDNSKEY());
+ rec.setContent(std::make_shared<DNSKEYRecordContent>(it->second.first.getDNSKEY()));
records.push_back(rec);
}
rec.d_type = QType::DS;
rec.d_place = place;
rec.d_ttl = ttl;
- rec.d_content = std::make_shared<DSRecordContent>(it->second.second);
+ rec.setContent(std::make_shared<DSRecordContent>(it->second.second));
records.push_back(rec);
return true;
rec.d_name = domain;
rec.d_ttl = ttl;
rec.d_type = QType::NSEC;
- rec.d_content = std::make_shared<NSECRecordContent>(std::move(nrc));
+ rec.setContent(std::make_shared<NSECRecordContent>(std::move(nrc)));
rec.d_place = DNSResourceRecord::AUTHORITY;
records.push_back(rec);
rec.d_name = hashedName;
rec.d_ttl = ttl;
rec.d_type = QType::NSEC3;
- rec.d_content = std::make_shared<NSEC3RecordContent>(std::move(nrc));
+ rec.setContent(std::make_shared<NSEC3RecordContent>(std::move(nrc)));
rec.d_place = DNSResourceRecord::AUTHORITY;
records.push_back(rec);
size_t queriesCount = 0;
- sr->setAsyncCallback([target, &queriesCount](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, &queriesCount](const ComboAddress& /* ip */, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
if (domain == target && type == QType::NS) {
size_t queriesCount = 0;
- sr->setAsyncCallback([&queriesCount](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([&queriesCount](const ComboAddress& /* ip */, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
if (domain == g_rootdnsname && type == QType::NS) {
then call getRootNS(), for which at least one of the root servers needs to answer.
None will, so it should ServFail.
*/
- sr->setAsyncCallback([&downServers](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([&downServers](const ComboAddress& ip, const DNSName& /* domain */, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* /* res */, bool* /* chained */) {
downServers.insert(ip);
return LWResult::Result::Timeout;
});
primeHints();
const DNSName target("www.example.com.");
- sr->setAsyncCallback([target](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target](const ComboAddress& /* ip */, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
if (domain == g_rootdnsname && type == QType::NS) {
setLWResult(res, 0, true, false, true);
size_t queriesCount = 0;
- auto asynccb = [target, &queriesCount, aroot, newA, newAAAA](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ auto asynccb = [target, &queriesCount, aroot, newA, newAAAA](const ComboAddress& /* ip */, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
if (domain == target && type == QType::NS) {
size_t queriesWithEDNS = 0;
size_t queriesWithoutEDNS = 0;
- sr->setAsyncCallback([&queriesWithEDNS, &queriesWithoutEDNS, &noEDNSServer, sample](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([&queriesWithEDNS, &queriesWithoutEDNS, &noEDNSServer, sample](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool /* sendRDQuery */, int EDNS0Level, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
if (EDNS0Level != 0) {
queriesWithEDNS++;
noEDNSServer = ip;
size_t queriesWithoutEDNS = 0;
std::set<ComboAddress> usedServers;
- sr->setAsyncCallback([&queriesWithEDNS, &queriesWithoutEDNS, &usedServers](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([&queriesWithEDNS, &queriesWithoutEDNS, &usedServers](const ComboAddress& ip, const DNSName& /* domain */, int type, bool /* doTCP */, bool /* sendRDQuery */, int EDNS0Level, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
if (EDNS0Level > 0) {
queriesWithEDNS++;
}
for (const auto qtype : invalidTypes) {
size_t queriesCount = 0;
- sr->setAsyncCallback([&queriesCount](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([&queriesCount](const ComboAddress& /* ip */, const DNSName& /* domain */, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* /* res */, bool* /* chained */) {
queriesCount++;
return LWResult::Result::Timeout;
});
std::unique_ptr<SyncRes> sr;
initSR(sr);
- sr->setAsyncCallback([](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([](const ComboAddress& /* ip */, const DNSName& domain, int type, bool doTCP, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
if (!doTCP) {
setLWResult(res, 0, false, true, false);
return LWResult::Result::Success;
size_t tcpQueriesCount = 0;
- sr->setAsyncCallback([&tcpQueriesCount](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([&tcpQueriesCount](const ComboAddress& /* ip */, const DNSName& domain, int /* type */, bool doTCP, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
if (!doTCP) {
setLWResult(res, 0, true, true, false);
return LWResult::Result::Success;
primeHints();
- sr->setAsyncCallback([&downServers](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([&downServers](const ComboAddress& ip, const DNSName& /* domain */, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
if (isRootServer(ip)) {
setLWResult(res, 0, false, false, true);
addRecordToLW(res, "com.", QType::NS, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY, 172800);
primeHints();
- sr->setAsyncCallback([&downServers](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([&downServers](const ComboAddress& ip, const DNSName& /* domain */, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
if (isRootServer(ip)) {
setLWResult(res, 0, false, false, true);
addRecordToLW(res, "com.", QType::NS, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY, 172800);
std::set<ComboAddress> downServers;
- sr->setAsyncCallback([&downServers](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([&downServers](const ComboAddress& ip, const DNSName& /* domain */, int /* type */, bool doTCP, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
if (isRootServer(ip)) {
setLWResult(res, 0, false, false, true);
addRecordToLW(res, "lock-up.", QType::NS, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY, 172800);
std::set<ComboAddress> downServers;
size_t queriesCount = 0;
- sr->setAsyncCallback([&queriesCount, &downServers](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([&queriesCount, &downServers](const ComboAddress& ip, const DNSName& /* domain */, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
if (isRootServer(ip)) {
setLWResult(res, 0, false, false, true);
addRecordToLW(res, "lock-up.", QType::NS, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY, 172800);
std::set<ComboAddress> downServers;
size_t queriesCount = 0;
- sr->setAsyncCallback([&queriesCount, &downServers](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([&queriesCount, &downServers](const ComboAddress& ip, const DNSName& /* domain */, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
if (isRootServer(ip)) {
setLWResult(res, 0, false, false, true);
addRecordToLW(res, "refused.", QType::NS, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY, 172800);
ad.d_servers = forwardedNSs;
(*SyncRes::t_sstorage.domainmap)[target] = ad;
- sr->setAsyncCallback([&queriesCount, &downServers](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([&queriesCount, &downServers](const ComboAddress& ip, const DNSName& /* domain */, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
if (isRootServer(ip)) {
setLWResult(res, 0, false, false, true);
addRecordToLW(res, "refused.", QType::NS, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY, 172800);
ad.d_servers = forwardedNSs;
(*SyncRes::t_sstorage.domainmap)[DNSName("refused.")] = ad;
- sr->setAsyncCallback([&queriesCount, &downServers](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([&queriesCount, &downServers](const ComboAddress& ip, const DNSName& /* domain */, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
if (isRootServer(ip)) {
setLWResult(res, 0, false, false, true);
addRecordToLW(res, "refused.", QType::NS, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY, 172800);
DNSName target("www.powerdns.com.");
- sr->setAsyncCallback([target](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target](const ComboAddress& ip, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
if (isRootServer(ip)) {
setLWResult(res, 0, false, false, true);
if (domain == target) {
primeHints();
- sr->setAsyncCallback([&downServers](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([&downServers](const ComboAddress& ip, const DNSName& /* domain */, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
if (isRootServer(ip)) {
setLWResult(res, 0, false, false, true);
addRecordToLW(res, "com.", QType::NS, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY, 172800);
const DNSName target("powerdns.com.");
- sr->setAsyncCallback([target](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target](const ComboAddress& ip, const DNSName& domain, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
/* this will cause issue with qname minimization if we ever implement it */
if (domain != target) {
return LWResult::Result::Timeout;
const DNSName target("powerdns.com.");
- sr->setAsyncCallback([target](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target](const ComboAddress& ip, const DNSName& domain, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
if (isRootServer(ip)) {
setLWResult(res, 0, false, false, true);
const DNSName target("powerdns.com.");
- sr->setAsyncCallback([target](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target](const ComboAddress& ip, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
if (isRootServer(ip)) {
setLWResult(res, 0, false, false, true);
incomingECS.source = Netmask("192.0.2.128/32");
sr->setQuerySource(ComboAddress(), boost::optional<const EDNSSubnetOpts&>(incomingECS));
- sr->setAsyncCallback([target](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target](const ComboAddress& ip, const DNSName& domain, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
BOOST_REQUIRE(srcmask);
BOOST_CHECK_EQUAL(srcmask->toString(), "192.0.2.0/24");
incomingECS.source = Netmask("2001:DB8::FF/128");
sr->setQuerySource(ComboAddress(), boost::optional<const EDNSSubnetOpts&>(incomingECS));
- sr->setAsyncCallback([target](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target](const ComboAddress& ip, const DNSName& domain, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
if (isRootServer(ip)) {
BOOST_REQUIRE(!srcmask);
// No incoming ECS data
sr->setQuerySource(ComboAddress("192.0.2.127"), boost::none);
- sr->setAsyncCallback([target](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target](const ComboAddress& ip, const DNSName& domain, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
if (isRootServer(ip)) {
BOOST_REQUIRE(!srcmask);
// No incoming ECS data, Requestor IP not in ecs-add-for
sr->setQuerySource(ComboAddress("192.0.2.127"), boost::none);
- sr->setAsyncCallback([target](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target](const ComboAddress& ip, const DNSName& domain, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
if (isRootServer(ip)) {
BOOST_REQUIRE(!srcmask);
incomingECS.source = Netmask("192.0.0.0/16");
sr->setQuerySource(ComboAddress("192.0.2.127"), boost::optional<const EDNSSubnetOpts&>(incomingECS));
- sr->setAsyncCallback([target](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target](const ComboAddress& ip, const DNSName& domain, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
if (isRootServer(ip)) {
BOOST_REQUIRE(!srcmask);
incomingECS.source = Netmask("0.0.0.0/0");
sr->setQuerySource(ComboAddress("192.0.2.127"), boost::optional<const EDNSSubnetOpts&>(incomingECS));
- sr->setAsyncCallback([target](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target](const ComboAddress& ip, const DNSName& domain, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
if (isRootServer(ip)) {
BOOST_REQUIRE(!srcmask);
const DNSName target("cname.powerdns.com.");
const DNSName cnameTarget("cname-target.powerdns.com");
- sr->setAsyncCallback([target, cnameTarget](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, cnameTarget](const ComboAddress& ip, const DNSName& domain, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
if (isRootServer(ip)) {
setLWResult(res, 0, false, false, true);
addRecordToLW(res, domain, QType::NS, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY, 172800);
const DNSName target("cname.powerdns.com.");
const DNSName cnameTarget("cname-target.powerdns.com");
- sr->setAsyncCallback([target, cnameTarget](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, cnameTarget](const ComboAddress& ip, const DNSName& domain, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
if (isRootServer(ip)) {
setLWResult(res, 0, false, false, true);
addRecordToLW(res, "powerdns.com.", QType::NS, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY, 172800);
const DNSName target("cname.powerdns.com.");
const DNSName cnameTarget("cname-target.powerdns.com");
- sr->setAsyncCallback([target, cnameTarget](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, cnameTarget](const ComboAddress& ip, const DNSName& domain, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
if (isRootServer(ip)) {
setLWResult(res, 0, false, false, true);
size_t count = 0;
const DNSName target("cname.powerdns.com.");
- sr->setAsyncCallback([target, &count](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, &count](const ComboAddress& ip, const DNSName& domain, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
count++;
if (isRootServer(ip)) {
const DNSName target3("cname3.powerdns.com.");
const DNSName target4("cname4.powerdns.com.");
- sr->setAsyncCallback([target1, target2, target3, target4, &count](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target1, target2, target3, target4, &count](const ComboAddress& ip, const DNSName& domain, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
count++;
if (isRootServer(ip)) {
size_t depth = 0;
const DNSName target("cname.powerdns.com.");
- sr->setAsyncCallback([target, &depth](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, &depth](const ComboAddress& ip, const DNSName& domain, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
if (isRootServer(ip)) {
setLWResult(res, 0, false, false, true);
size_t queries = 0;
const DNSName target("cname.powerdns.com.");
- sr->setAsyncCallback([target, &queries](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, &queries](const ComboAddress& ip, const DNSName& domain, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queries++;
if (isRootServer(ip)) {
size_t queries = 0;
- sr->setAsyncCallback([dnameOwner, dnameTarget, target, cnameTarget, uncachedTarget, uncachedCNAMETarget, &queries](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([dnameOwner, dnameTarget, target, cnameTarget, uncachedTarget, uncachedCNAMETarget, &queries](const ComboAddress& ip, const DNSName& domain, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queries++;
if (isRootServer(ip)) {
size_t queries = 0;
- sr->setAsyncCallback([dnameOwner, dnameTarget, target, cnameTarget, keys, &queries](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([dnameOwner, dnameTarget, target, cnameTarget, keys, &queries](const ComboAddress& ip, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queries++;
/* We don't use the genericDSAndDNSKEYHandler here, as it would deny names existing at the wrong level of the tree, due to the way computeZoneCuts works
* As such, we need to do some more work to make the answers correct.
size_t queries = 0;
- sr->setAsyncCallback([dnameOwner, dnameTarget, target, cnameTarget, keys, &queries](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([dnameOwner, dnameTarget, target, cnameTarget, keys, &queries](const ComboAddress& /* ip */, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queries++;
if (type == QType::DS || type == QType::DNSKEY) {
size_t queries = 0;
- sr->setAsyncCallback([dnameOwner, dnameTarget, target, cnameTarget, keys, &queries](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([dnameOwner, dnameTarget, target, cnameTarget, keys, &queries](const ComboAddress& ip, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queries++;
if (isRootServer(ip)) {
size_t queries = 0;
- sr->setAsyncCallback([dnameOwner, dnameTarget, target, cnameTarget, &queries](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([dnameOwner, dnameTarget, target, cnameTarget, &queries](const ComboAddress& ip, const DNSName& domain, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queries++;
if (isRootServer(ip)) {
const DNSName target("powerdns.com.");
- sr->setAsyncCallback([target](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target](const ComboAddress& ip, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
/* this will cause issue with qname minimization if we ever implement it */
if (domain != target) {
return LWResult::Result::Timeout;
int queries = 0;
const DNSName target("powerdns.com.");
- sr->setAsyncCallback([target, &v4Hit, &v6Hit, &queries](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, &v4Hit, &v6Hit, &queries](const ComboAddress& ip, const DNSName& domain, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queries++;
if (isRootServer(ip)) {
setLWResult(res, 0, false, false, true);
int queries = 0;
const DNSName target("powerdns.com.");
- sr->setAsyncCallback([target, &queries](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, &queries](const ComboAddress& ip, const DNSName& domain, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queries++;
if (isRootServer(ip)) {
setLWResult(res, 0, false, false, true);
int queries = 0;
const DNSName target("powerdns.com.");
- sr->setAsyncCallback([target, &queries](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, &queries](const ComboAddress& ip, const DNSName& domain, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queries++;
if (isRootServer(ip)) {
setLWResult(res, 0, false, false, true);
size_t queriesCount = 0;
- sr->setAsyncCallback([target, targetAddr, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, targetAddr, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
if (type == QType::DS) {
size_t queriesCount = 0;
- sr->setAsyncCallback([target, targetAddr, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, targetAddr, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
if (type == QType::DS) {
size_t queriesCount = 0;
- sr->setAsyncCallback([targetAddr, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([targetAddr, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
if (type == QType::DS) {
size_t queriesCount = 0;
- sr->setAsyncCallback([targetAddr, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([targetAddr, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
if (type == QType::DS) {
size_t queriesCount = 0;
- sr->setAsyncCallback([targetAddr, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([targetAddr, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
if (type == QType::DS) {
size_t queriesCount = 0;
- sr->setAsyncCallback([targetAddr, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([targetAddr, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
if (type == QType::DS) {
size_t queriesCount = 0;
- sr->setAsyncCallback([targetAddr, &queriesCount, keys, wrongKeys](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([targetAddr, &queriesCount, keys, wrongKeys](const ComboAddress& ip, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
if (type == QType::DS) {
const int theTTL = 5;
- sr->setAsyncCallback([&downServers, &downCount, &lookupCount, target](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([&downServers, &downCount, &lookupCount, target](const ComboAddress& ip, const DNSName& /* domain */, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
/* this will cause issue with qname minimization if we ever implement it */
if (downServers.find(ip) != downServers.end()) {
downCount++;
const int theTTL = 5;
- sr->setAsyncCallback([&downServers, &downCount, &lookupCount, target](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([&downServers, &downCount, &lookupCount, target](const ComboAddress& ip, const DNSName& /* domain */, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
/* this will cause issue with qname minimization if we ever implement it */
if (downServers.find(ip) != downServers.end()) {
downCount++;
const int theTTL = 5;
const int negTTL = 60;
- sr->setAsyncCallback([&downServers, &downCount, &lookupCount, &negLookup, target](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([&downServers, &downCount, &lookupCount, &negLookup, target](const ComboAddress& ip, const DNSName& /* domain */, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
/* this will cause issue with qname minimization if we ever implement it */
if (downServers.find(ip) != downServers.end()) {
downCount++;
const int theTTL = 5;
const int negTTL = 60;
- sr->setAsyncCallback([&downServers, &downCount, &lookupCount, &cnameOK, target, auth](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([&downServers, &downCount, &lookupCount, &cnameOK, target, auth](const ComboAddress& ip, const DNSName& /* domain */, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
/* this will cause issue with qname minimization if we ever implement it */
if (downServers.find(ip) != downServers.end()) {
downCount++;
const int theTTL = 5;
- sr->setAsyncCallback([&downServers, &downCount, &lookupCount, target](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([&downServers, &downCount, &lookupCount, target](const ComboAddress& ip, const DNSName& /* domain */, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
/* this will cause issue with qname minimization if we ever implement it */
if (downServers.find(ip) != downServers.end()) {
const DNSName target1("powerdns.com.");
const DNSName target2("pdns.com.");
- sr->setAsyncCallback([=](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([=](const ComboAddress& ip, const DNSName& domain, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
/* this will cause issue with qname minimization if we ever implement it */
if (domain != target1 && domain != target2) {
return LWResult::Result::Timeout;
const DNSName target1("powerdns.com.");
const DNSName target2("pdns.com.");
- sr->setAsyncCallback([=](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([=](const ComboAddress& ip, const DNSName& domain, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
/* this will cause issue with qname minimization if we ever implement it */
if (domain != target1 && domain != target2) {
return LWResult::Result::Timeout;
const DNSName target("powerdns.com.");
- sr->setAsyncCallback([=](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([=](const ComboAddress& ip, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
/* this will cause issue with qname minimization if we ever implement it */
if (domain != target) {
return LWResult::Result::Timeout;
size_t queries = 0;
const DNSName target("www.powerdns.com.");
- sr->setAsyncCallback([target, &queries](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, &queries](const ComboAddress& ip, const DNSName& domain, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queries++;
if (isRootServer(ip)) {
const DNSName target2("powerdns.org.");
size_t queriesToNS = 0;
- sr->setAsyncCallback([target1, target2, &queriesToNS](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target1, target2, &queriesToNS](const ComboAddress& ip, const DNSName& domain, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesToNS++;
if (isRootServer(ip)) {
const DNSName target2("powerdns.org.");
size_t queriesToNS = 0;
- sr->setAsyncCallback([target1, target2, &queriesToNS](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target1, target2, &queriesToNS](const ComboAddress& ip, const DNSName& domain, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesToNS++;
if (isRootServer(ip)) {
size_t queryCount = 0;
- sr->setAsyncCallback([target, &queryCount](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, &queryCount](const ComboAddress& ip, const DNSName& domain, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
if (isRootServer(ip)) {
setLWResult(res, 0, false, false, true);
size_t queries = 0;
const DNSName target("cname.powerdns.com.");
- sr->setAsyncCallback([target, &queries](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, &queries](const ComboAddress& ip, const DNSName& domain, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queries++;
if (isRootServer(ip)) {
const ComboAddress ns("192.0.2.1:53");
size_t queriesToNS = 0;
- sr->setAsyncCallback([target, ns, &queriesToNS](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, ns, &queriesToNS](const ComboAddress& ip, const DNSName& domain, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
if (isRootServer(ip)) {
setLWResult(res, 0, false, false, true);
const ComboAddress ns("192.0.2.1:53");
size_t queriesToNS = 0;
- sr->setAsyncCallback([target, ns, &queriesToNS](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, ns, &queriesToNS](const ComboAddress& ip, const DNSName& domain, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
if (isRootServer(ip)) {
setLWResult(res, 0, false, false, true);
const ComboAddress ns("192.0.2.1:53");
size_t queriesCount = 0;
- sr->setAsyncCallback([target1, target2, ns, &queriesCount](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target1, target2, ns, &queriesCount](const ComboAddress& ip, const DNSName& domain, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
if (isRootServer(ip)) {
/* This time the root denies target1 with a "com." SOA instead of a "." one.
We should add target1 to the negcache, but not "com.". */
- sr->setAsyncCallback([target1, target2, ns, &queriesCount](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target1, target2, ns, &queriesCount](const ComboAddress& ip, const DNSName& domain, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
if (isRootServer(ip)) {
const ComboAddress ns("192.0.2.1:53");
size_t queriesCount = 0;
- sr->setAsyncCallback([target1, target2, ns, &queriesCount](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target1, target2, ns, &queriesCount](const ComboAddress& ip, const DNSName& domain, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
if (isRootServer(ip)) {
const ComboAddress ns("192.0.2.1:53");
size_t queriesCount = 0;
- sr->setAsyncCallback([ns, &queriesCount](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([ns, &queriesCount](const ComboAddress& ip, const DNSName& /* domain */, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
if (isRootServer(ip)) {
size_t queriesCount = 0;
- sr->setAsyncCallback([target1, target2, target3, target4, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target1, target2, target3, target4, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
DNSName auth = domain;
const ComboAddress ns("192.0.2.1:53");
size_t queriesCount = 0;
- sr->setAsyncCallback([ns, target1, target2, target3, &queriesCount](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([ns, target1, target2, target3, &queriesCount](const ComboAddress& ip, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
if (isRootServer(ip)) {
const ComboAddress ns("192.0.2.1:53");
size_t queriesCount = 0;
- sr->setAsyncCallback([ns, target1, target2, target3, &queriesCount](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([ns, target1, target2, target3, &queriesCount](const ComboAddress& ip, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
if (isRootServer(ip)) {
incomingECS.source = Netmask("192.0.2.128/32");
sr->setQuerySource(ComboAddress(), boost::optional<const EDNSSubnetOpts&>(incomingECS));
- sr->setAsyncCallback([target, cnameTarget](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, cnameTarget](const ComboAddress& ip, const DNSName& domain, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
BOOST_REQUIRE(srcmask);
BOOST_CHECK_EQUAL(srcmask->toString(), "192.0.2.0/24");
sr->setQuerySource(ComboAddress(), boost::optional<const EDNSSubnetOpts&>(incomingECS));
SyncRes::s_ecsipv4cachelimit = 24;
- sr->setAsyncCallback([target](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target](const ComboAddress& /* ip */, const DNSName& /* domain */, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
BOOST_REQUIRE(srcmask);
BOOST_CHECK_EQUAL(srcmask->toString(), "192.0.2.0/24");
sr->setQuerySource(ComboAddress(), boost::optional<const EDNSSubnetOpts&>(incomingECS));
SyncRes::s_ecsipv4cachelimit = 16;
- sr->setAsyncCallback([target](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target](const ComboAddress& /* ip */, const DNSName& /* domain */, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
BOOST_REQUIRE(srcmask);
BOOST_CHECK_EQUAL(srcmask->toString(), "192.0.2.0/24");
sr->setQuerySource(ComboAddress(), boost::optional<const EDNSSubnetOpts&>(incomingECS));
SyncRes::s_ecscachelimitttl = 30;
- sr->setAsyncCallback([target](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target](const ComboAddress& /* ip */, const DNSName& /* domain */, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
BOOST_REQUIRE(srcmask);
BOOST_CHECK_EQUAL(srcmask->toString(), "192.0.2.0/24");
SyncRes::s_ecscachelimitttl = 100;
SyncRes::s_ecsipv4cachelimit = 24;
- sr->setAsyncCallback([target](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target](const ComboAddress& /* ip */, const DNSName& /* domain */, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
BOOST_REQUIRE(srcmask);
BOOST_CHECK_EQUAL(srcmask->toString(), "192.0.2.0/24");
SyncRes::s_ecscachelimitttl = 100;
SyncRes::s_ecsipv4cachelimit = 16;
- sr->setAsyncCallback([target](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target](const ComboAddress& /* ip */, const DNSName& /* domain */, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
BOOST_REQUIRE(srcmask);
BOOST_CHECK_EQUAL(srcmask->toString(), "192.0.2.0/24");
std::map<ComboAddress, uint64_t> nsCounts;
- sr->setAsyncCallback([target, &nsCounts](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, &nsCounts](const ComboAddress& ip, const DNSName& domain, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
if (isRootServer(ip)) {
setLWResult(res, 0, false, false, true);
addRecordToLW(res, domain, QType::NS, "pdns-public-ns1.powerdns.com.", DNSResourceRecord::AUTHORITY, 172800);
const DNSName target("powerdns.com.");
- sr->setAsyncCallback([target](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target](const ComboAddress& ip, const DNSName& domain, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
if (isRootServer(ip)) {
setLWResult(res, 0, false, false, true);
addRecordToLW(res, domain, QType::NS, "pdns-public-ns1.powerdns.com.", DNSResourceRecord::AUTHORITY, 172800);
/* we populate the cache with a flawed NSset, i.e. there is a NS entry but no corresponding glue */
time_t now = sr->getNow().tv_sec;
std::vector<DNSRecord> records;
- std::vector<shared_ptr<RRSIGRecordContent>> sigs;
+ std::vector<shared_ptr<const RRSIGRecordContent>> sigs;
addRecordToList(records, target, QType::NS, "pdns-public-ns1.powerdns.com.", DNSResourceRecord::AUTHORITY, now + 3600);
g_recCache->replace(now, target, QType(QType::NS), records, sigs, vector<std::shared_ptr<DNSRecord>>(), true, g_rootdnsname, boost::optional<Netmask>());
const DNSName target("powerdns.com.");
size_t queriesCount = 0;
- sr->setAsyncCallback([&queriesCount, target](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([&queriesCount, target](const ComboAddress& ip, const DNSName& domain, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
if (isRootServer(ip) && domain == target) {
const DNSName target("powerdns.com.");
size_t queriesCount = 0;
- sr->setAsyncCallback([&queriesCount, target](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([&queriesCount, target](const ComboAddress& ip, const DNSName& domain, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
if (isRootServer(ip) && domain == target) {
const DNSName target("powerdns.com.");
- sr->setAsyncCallback([target](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target](const ComboAddress& /* ip */, const DNSName& /* domain */, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* /* res */, bool* /* chained */) {
return LWResult::Result::Timeout;
});
/* we populate the cache with everything we need */
time_t now = sr->getNow().tv_sec;
std::vector<DNSRecord> records;
- std::vector<shared_ptr<RRSIGRecordContent>> sigs;
+ std::vector<shared_ptr<const RRSIGRecordContent>> sigs;
addRecordToList(records, target, QType::A, "192.0.2.1", DNSResourceRecord::ANSWER, now + 3600);
g_recCache->replace(now, target, QType(QType::A), records, sigs, vector<std::shared_ptr<DNSRecord>>(), true, g_rootdnsname, boost::optional<Netmask>());
sr->setCacheOnly();
- sr->setAsyncCallback([target, &queriesCount](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, &queriesCount](const ComboAddress& /* ip */, const DNSName& /* domain */, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* /* res */, bool* /* chained */) {
queriesCount++;
return LWResult::Result::Timeout;
});
const DNSName target("cachettl.powerdns.com.");
const ComboAddress ns("192.0.2.1:53");
- sr->setAsyncCallback([target, ns](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, ns](const ComboAddress& ip, const DNSName& domain, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
if (isRootServer(ip)) {
setLWResult(res, 0, false, false, true);
sr->setQuerySource(ComboAddress(), boost::optional<const EDNSSubnetOpts&>(incomingECS));
SyncRes::addEDNSDomain(target);
- sr->setAsyncCallback([target, ns](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, ns](const ComboAddress& ip, const DNSName& domain, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
BOOST_REQUIRE(srcmask);
BOOST_CHECK_EQUAL(srcmask->toString(), "192.0.2.0/24");
const DNSName target("powerdns.com.");
- sr->setAsyncCallback([target](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target](const ComboAddress& ip, const DNSName& domain, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
if (isRootServer(ip)) {
setLWResult(res, 0, false, false, true);
addRecordToLW(res, domain, QType::NS, "pdns-public-ns1.powerdns.com.", DNSResourceRecord::AUTHORITY, 172800);
const time_t now = sr->getNow().tv_sec;
std::vector<DNSRecord> records;
- std::vector<shared_ptr<RRSIGRecordContent>> sigs;
+ std::vector<shared_ptr<const RRSIGRecordContent>> sigs;
addRecordToList(records, target, QType::A, "192.0.2.42", DNSResourceRecord::ANSWER, now - 60);
g_recCache->replace(now - 3600, target, QType(QType::A), records, sigs, vector<std::shared_ptr<DNSRecord>>(), true, g_rootdnsname, boost::optional<Netmask>());
const DNSName target("powerdns.com.");
- auto cb = [target](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ auto cb = [target](const ComboAddress& ip, const DNSName& domain, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
if (isRootServer(ip)) {
setLWResult(res, 0, false, false, true);
addRecordToLW(res, domain, QType::NS, "pdns-public-ns1.powerdns.com.", DNSResourceRecord::AUTHORITY, 172800);
const time_t now = sr->getNow().tv_sec;
std::vector<DNSRecord> records;
- std::vector<shared_ptr<RRSIGRecordContent>> sigs;
+ std::vector<shared_ptr<const RRSIGRecordContent>> sigs;
addRecordToList(records, target, QType::A, "192.0.2.2", DNSResourceRecord::ANSWER, now + 29);
g_recCache->replace(now - 30, target, QType(QType::A), records, sigs, vector<std::shared_ptr<DNSRecord>>(), true, g_rootdnsname, boost::optional<Netmask>());
check that we only return one result, and we only cache one too. */
const DNSName target("cache-auth.powerdns.com.");
- sr->setAsyncCallback([target](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target](const ComboAddress& /* ip */, const DNSName& domain, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
setLWResult(res, 0, true, false, true);
addRecordToLW(res, domain, QType::A, "192.0.2.2", DNSResourceRecord::ANSWER, 10);
addRecordToLW(res, domain, QType::A, "192.0.2.2", DNSResourceRecord::ADDITIONAL, 10);
const DNSName target("powerdns.com.");
- sr->setAsyncCallback([target](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target](const ComboAddress& ip, const DNSName& domain, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
if (isRootServer(ip)) {
setLWResult(res, 0, false, false, true);
addRecordToLW(res, "com.", QType::NS, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY, 172800);
const DNSName target("powerdns.com.");
sr->setAsyncCallback(
- [target](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level,
- struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context,
- LWResult* res, bool* chained) {
+ [target](const ComboAddress& /* ip */, const DNSName& /* domain */, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */,
+ struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */,
+ LWResult* res, bool* /* chained */) {
setLWResult(res, 0, true, false, true);
return LWResult::Result::Success;
});
const DNSName target2("www2.powerdns.com."); // in bailiwick, but not asked for
const DNSName target3("www.random.net."); // out of bailiwick and not asked for
- sr->setAsyncCallback([target, target2, target3](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, target2, target3](const ComboAddress& ip, const DNSName& domain, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
if (isRootServer(ip)) {
setLWResult(res, 0, false, false, true);
addRecordToLW(res, "powerdns.com.", QType::NS, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY, 172800);
generateKeyMaterial(DNSName("powerdns.com"), DNSSECKeeper::ECDSA256, DNSSECKeeper::DIGEST_SHA256, keys, luaconfsCopy.dsAnchors);
g_luaconfs.setState(luaconfsCopy);
- sr->setAsyncCallback([target, target2, target3, keys](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, target2, target3, keys](const ComboAddress& ip, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
if (type == QType::DS || type == QType::DNSKEY) {
return genericDSAndDNSKEYHandler(res, domain, domain, type, keys, false);
}
const DNSName target("powerdns.com.");
- sr->setAsyncCallback([target](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target](const ComboAddress& /* ip */, const DNSName& domain, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
setLWResult(res, 0, true, false, true);
addRecordToLW(res, domain, QType::A, "192.0.2.42");
addRecordToLW(res, domain, QType::ANY, "\\# 0");
const DNSName target("powerdns.com.");
- sr->setAsyncCallback([target](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target](const ComboAddress& /* ip */, const DNSName& domain, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
setLWResult(res, 0, true, false, true);
addRecordToLW(res, domain, QType::SOA, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY, 3600);
/* the NSEC and RRSIG contents are complete garbage, please ignore them */
const DNSName target("powerdns.com.");
- sr->setAsyncCallback([target](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target](const ComboAddress& /* ip */, const DNSName& domain, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
setLWResult(res, 0, true, false, true);
addRecordToLW(res, domain, QType::SOA, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY, 3600);
/* the NSEC and RRSIG contents are complete garbage, please ignore them */
const DNSName target("powerdns.com.");
- sr->setAsyncCallback([target](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target](const ComboAddress& /* ip */, const DNSName& domain, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
setLWResult(res, RCode::NXDomain, true, false, true);
addRecordToLW(res, domain, QType::SOA, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY, 3600);
/* the NSEC and RRSIG contents are complete garbage, please ignore them */
const DNSName target("powerdns.com.");
- sr->setAsyncCallback([target](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target](const ComboAddress& /* ip */, const DNSName& domain, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
setLWResult(res, RCode::NXDomain, true, false, true);
addRecordToLW(res, domain, QType::SOA, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY, 3600);
/* the NSEC and RRSIG contents are complete garbage, please ignore them */
/* apart from special names and QClass::ANY, anything else than QClass::IN should be rejected right away */
size_t queriesCount = 0;
- sr->setAsyncCallback([&queriesCount](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([&queriesCount](const ComboAddress& /* ip */, const DNSName& /* domain */, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* /* res */, bool* /* chained */) {
queriesCount++;
return LWResult::Result::Timeout;
});
const DNSName target("powerdns.com.");
- sr->setAsyncCallback([target](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target](const ComboAddress& /* ip */, const DNSName& domain, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
setLWResult(res, 0, false, false, true);
addRecordToLW(res, domain, QType::A, "192.0.2.1");
return LWResult::Result::Success;
/* check that the record in the answer section has not been cached */
const ComboAddress who;
vector<DNSRecord> cached;
- vector<std::shared_ptr<RRSIGRecordContent>> signatures;
+ vector<std::shared_ptr<const RRSIGRecordContent>> signatures;
BOOST_REQUIRE_GT(g_recCache->get(now, target, QType(QType::A), MemRecursorCache::None, &cached, who, boost::none, &signatures), 0);
}
/* {A,I}XFR, RRSIG and NSEC3 should be rejected right away */
size_t queriesCount = 0;
- sr->setAsyncCallback([&queriesCount](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([&queriesCount](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* /* res */, bool* /* chained */) {
cerr << "asyncresolve called to ask " << ip.toStringWithPort() << " about " << domain.toString() << " / " << QType(type).toString() << " over " << (doTCP ? "TCP" : "UDP") << " (rd: " << sendRDQuery << ", EDNS0 level: " << EDNS0Level << ")" << endl;
queriesCount++;
return LWResult::Result::Timeout;
size_t queriesCount = 0;
- sr->setAsyncCallback([&queriesCount](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([&queriesCount](const ComboAddress& /* ip */, const DNSName& /* domain */, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* /* res */, bool* /* chained */) {
queriesCount++;
return LWResult::Result::Timeout;
});
const DNSName target("rpz.powerdns.com.");
const ComboAddress ns("192.0.2.1:53");
- sr->setAsyncCallback([target, ns](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, ns](const ComboAddress& ip, const DNSName& domain, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
if (isRootServer(ip)) {
setLWResult(res, false, true, false, true);
addRecordToLW(res, "com.", QType::NS, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY, 172800);
const DNSName target("rpz.powerdns.com.");
const ComboAddress ns("[2001:DB8::42]:53");
- sr->setAsyncCallback([target, ns](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, ns](const ComboAddress& ip, const DNSName& domain, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
if (isRootServer(ip)) {
setLWResult(res, 0, false, false, true);
addRecordToLW(res, "com.", QType::NS, "a.gtld-servers.net.", DNSResourceRecord::AUTHORITY, 172800);
const ComboAddress ns("192.0.2.1:53");
const DNSName nsName("ns1.powerdns.com.");
- sr->setAsyncCallback([target, ns, nsName](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, ns, nsName](const ComboAddress& ip, const DNSName& domain, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
if (isRootServer(ip)) {
setLWResult(res, 0, false, false, true);
addRecordToLW(res, domain, QType::NS, nsName.toString(), DNSResourceRecord::AUTHORITY, 172800);
const ComboAddress ns("192.0.2.1:53");
const DNSName nsName("ns1.powerdns.com.");
- sr->setAsyncCallback([target, ns, nsName](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, ns, nsName](const ComboAddress& ip, const DNSName& domain, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
if (isRootServer(ip)) {
setLWResult(res, 0, false, false, true);
addRecordToLW(res, domain, QType::NS, nsName.toString(), DNSResourceRecord::AUTHORITY, 172800);
size_t queriesCount = 0;
- sr->setAsyncCallback([forwardedNS, &queriesCount](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([forwardedNS, &queriesCount](const ComboAddress& ip, const DNSName& domain, int /* type */, bool /* doTCP */, bool sendRDQuery, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
++queriesCount;
if (ip == forwardedNS) {
BOOST_CHECK_EQUAL(sendRDQuery, false);
ad.d_servers.push_back(forwardedNS);
(*SyncRes::t_sstorage.domainmap)[target] = ad;
- sr->setAsyncCallback([forwardedNS, &queriesCount](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([forwardedNS, &queriesCount](const ComboAddress& ip, const DNSName& domain, int /* type */, bool /* doTCP */, bool sendRDQuery, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
if (ip == forwardedNS) {
size_t queriesCount = 0;
- sr->setAsyncCallback([forwardedNS, &queriesCount](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([forwardedNS, &queriesCount](const ComboAddress& ip, const DNSName& domain, int /* type */, bool /* doTCP */, bool sendRDQuery, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
++queriesCount;
if (ip == forwardedNS) {
BOOST_CHECK_EQUAL(sendRDQuery, true);
ad.d_servers.push_back(forwardedNS);
(*SyncRes::t_sstorage.domainmap)[target] = ad;
- sr->setAsyncCallback([forwardedNS](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([forwardedNS](const ComboAddress& ip, const DNSName& domain, int /* type */, bool /* doTCP */, bool sendRDQuery, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
if (ip == forwardedNS) {
BOOST_CHECK_EQUAL(sendRDQuery, true);
ad.d_servers.push_back(forwardedNS);
(*SyncRes::t_sstorage.domainmap)[g_rootdnsname] = ad;
- sr->setAsyncCallback([target, cnameTarget, keys, forwardedNS, &queriesCount](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, cnameTarget, keys, forwardedNS, &queriesCount](const ComboAddress& ip, const DNSName& domain, int type, bool /* doTCP */, bool sendRDQuery, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
BOOST_CHECK_EQUAL(sendRDQuery, true);
ad.d_servers.push_back(forwardedNS);
(*SyncRes::t_sstorage.domainmap)[DNSName("test.")] = ad;
- sr->setAsyncCallback([parent, target1, target2, keys, forwardedNS, &queriesCount, &DSforParentCount](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([parent, target1, target2, keys, forwardedNS, &queriesCount, &DSforParentCount](const ComboAddress& ip, const DNSName& domain, int type, bool /* doTCP */, bool sendRDQuery, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
BOOST_CHECK_EQUAL(sendRDQuery, false);
ad.d_servers.push_back(forwardedNS);
(*SyncRes::t_sstorage.domainmap)[g_rootdnsname] = ad;
- sr->setAsyncCallback([target, cnameTarget, keys, forwardedNS, &queriesCount](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, cnameTarget, keys, forwardedNS, &queriesCount](const ComboAddress& ip, const DNSName& domain, int type, bool /* doTCP */, bool sendRDQuery, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
BOOST_CHECK_EQUAL(sendRDQuery, true);
size_t queriesCount = 0;
- sr->setAsyncCallback([target, forwardedNS, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, forwardedNS, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool /* doTCP */, bool sendRDQuery, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
BOOST_CHECK_EQUAL(sendRDQuery, true);
dr.d_name = target;
dr.d_type = QType::A;
dr.d_ttl = 1800;
- dr.d_content = std::make_shared<ARecordContent>(targetAddr);
+ dr.setContent(std::make_shared<ARecordContent>(targetAddr));
ad.d_records.insert(dr);
(*SyncRes::t_sstorage.domainmap)[authZone] = ad;
- sr->setAsyncCallback([&queriesCount](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([&queriesCount](const ComboAddress& /* ip */, const DNSName& /* domain */, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* /* res */, bool* /* chained */) {
queriesCount++;
return LWResult::Result::Timeout;
});
dr.d_name = target;
dr.d_type = QType::CNAME;
dr.d_ttl = 1800;
- dr.d_content = std::make_shared<CNAMERecordContent>(targetCname);
+ dr.setContent(std::make_shared<CNAMERecordContent>(targetCname));
ad.d_records.insert(dr);
dr.d_place = DNSResourceRecord::ANSWER;
dr.d_name = targetCname;
dr.d_type = QType::A;
dr.d_ttl = 1800;
- dr.d_content = std::make_shared<ARecordContent>(targetCnameAddr);
+ dr.setContent(std::make_shared<ARecordContent>(targetCnameAddr));
ad.d_records.insert(dr);
(*SyncRes::t_sstorage.domainmap)[authZone] = ad;
- sr->setAsyncCallback([&queriesCount](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([&queriesCount](const ComboAddress& /* ip */, const DNSName& /* domain */, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* /* res */, bool* /* chained */) {
queriesCount++;
return LWResult::Result::Timeout;
});
dr.d_name = target;
dr.d_type = QType::SOA;
dr.d_ttl = 3600;
- dr.d_content = std::make_shared<SOARecordContent>("pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600");
+ dr.setContent(std::make_shared<SOARecordContent>("pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600"));
ad.d_records.insert(dr);
dr.d_place = DNSResourceRecord::ANSWER;
dr.d_name = target;
dr.d_type = QType::A;
dr.d_ttl = 3600;
- dr.d_content = std::make_shared<ARecordContent>(addr);
+ dr.setContent(std::make_shared<ARecordContent>(addr));
ad.d_records.insert(dr);
auto map = std::make_shared<SyncRes::domainmap_t>();
(*map)[target] = ad;
SyncRes::setDomainMap(map);
- sr->setAsyncCallback([&queriesCount](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([&queriesCount](const ComboAddress& /* ip */, const DNSName& domain, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
setLWResult(res, 0, true, false, true);
addRecordToLW(res, domain, QType::A, "192.0.2.42");
dr.d_name = authZone;
dr.d_type = QType::SOA;
dr.d_ttl = 3600;
- dr.d_content = std::make_shared<SOARecordContent>("pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600");
+ dr.setContent(std::make_shared<SOARecordContent>("pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600"));
ad.d_records.insert(dr);
dr.d_place = DNSResourceRecord::ANSWER;
dr.d_name = authZone;
dr.d_type = QType::A;
dr.d_ttl = 3600;
- dr.d_content = std::make_shared<ARecordContent>(addr);
+ dr.setContent(std::make_shared<ARecordContent>(addr));
ad.d_records.insert(dr);
auto map = std::make_shared<SyncRes::domainmap_t>();
(*map)[authZone] = ad;
SyncRes::setDomainMap(map);
- sr->setAsyncCallback([&queriesCount, target, authZone](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([&queriesCount, target, authZone](const ComboAddress& /* ip */, const DNSName& domain, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
if (domain == target) {
dr.d_name = target;
dr.d_type = QType::SOA;
dr.d_ttl = 3600;
- dr.d_content = std::make_shared<SOARecordContent>("pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600");
+ dr.setContent(std::make_shared<SOARecordContent>("pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600"));
ad.d_records.insert(dr);
dr.d_place = DNSResourceRecord::ANSWER;
dr.d_name = target;
dr.d_type = QType::CNAME;
dr.d_ttl = 3600;
- dr.d_content = std::make_shared<CNAMERecordContent>(externalCNAME);
+ dr.setContent(std::make_shared<CNAMERecordContent>(externalCNAME));
ad.d_records.insert(dr);
auto map = std::make_shared<SyncRes::domainmap_t>();
(*map)[target] = ad;
SyncRes::setDomainMap(map);
- sr->setAsyncCallback([&queriesCount, externalCNAME, addr](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([&queriesCount, externalCNAME, addr](const ComboAddress& /* ip */, const DNSName& domain, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
if (domain == externalCNAME) {
dr.d_name = target;
dr.d_type = QType::SOA;
dr.d_ttl = 3600;
- dr.d_content = std::make_shared<SOARecordContent>("pdns-public-ns1.powerdns.corp. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600");
+ dr.setContent(std::make_shared<SOARecordContent>("pdns-public-ns1.powerdns.corp. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600"));
ad.d_records.insert(dr);
dr.d_place = DNSResourceRecord::ANSWER;
dr.d_name = target;
dr.d_type = QType::A;
dr.d_ttl = 3600;
- dr.d_content = std::make_shared<ARecordContent>(addr);
+ dr.setContent(std::make_shared<ARecordContent>(addr));
ad.d_records.insert(dr);
auto map = std::make_shared<SyncRes::domainmap_t>();
(*map)[target] = ad;
SyncRes::setDomainMap(map);
- sr->setAsyncCallback([&queriesCount](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([&queriesCount](const ComboAddress& /* ip */, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
if (type != QType::DS) {
setLWResult(res, 0, true, false, true);
dr.d_name = target;
dr.d_type = QType::A;
dr.d_ttl = 3600;
- dr.d_content = std::make_shared<ARecordContent>(ComboAddress("192.0.2.1"));
+ dr.setContent(std::make_shared<ARecordContent>(ComboAddress("192.0.2.1")));
ad.d_records.insert(dr);
dr.d_place = DNSResourceRecord::ANSWER;
dr.d_name = authZone;
dr.d_type = QType::SOA;
dr.d_ttl = 3600;
- dr.d_content = std::make_shared<SOARecordContent>("pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600");
+ dr.setContent(std::make_shared<SOARecordContent>("pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600"));
ad.d_records.insert(dr);
auto map = std::make_shared<SyncRes::domainmap_t>();
(*map)[authZone] = ad;
SyncRes::setDomainMap(map);
- sr->setAsyncCallback([&queriesCount](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([&queriesCount](const ComboAddress& /* ip */, const DNSName& /* domain */, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* /* res */, bool* /* chained */) {
queriesCount++;
return LWResult::Result::Timeout;
dr.d_name = DNSName("powerdns.com.");
dr.d_type = QType::SOA;
dr.d_ttl = 3600;
- dr.d_content = std::make_shared<SOARecordContent>("pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600");
+ dr.setContent(std::make_shared<SOARecordContent>("pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600"));
ad.d_records.insert(dr);
auto map = std::make_shared<SyncRes::domainmap_t>();
(*map)[authZone] = ad;
SyncRes::setDomainMap(map);
- sr->setAsyncCallback([&queriesCount](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([&queriesCount](const ComboAddress& /* ip */, const DNSName& /* domain */, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* /* res */, bool* /* chained */) {
queriesCount++;
return LWResult::Result::Timeout;
dr.d_name = authZone;
dr.d_type = QType::SOA;
dr.d_ttl = 3600;
- dr.d_content = std::make_shared<SOARecordContent>("pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600");
+ dr.setContent(std::make_shared<SOARecordContent>("pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600"));
ad.d_records.insert(dr);
dr.d_place = DNSResourceRecord::ANSWER;
dr.d_name = DNSName("test.powerdns.com.");
dr.d_type = QType::NS;
dr.d_ttl = 3600;
- dr.d_content = std::make_shared<NSRecordContent>(ns);
+ dr.setContent(std::make_shared<NSRecordContent>(ns));
ad.d_records.insert(dr);
dr.d_place = DNSResourceRecord::ANSWER;
dr.d_name = ns;
dr.d_type = QType::A;
dr.d_ttl = 3600;
- dr.d_content = std::make_shared<ARecordContent>(nsAddr);
+ dr.setContent(std::make_shared<ARecordContent>(nsAddr));
ad.d_records.insert(dr);
auto map = std::make_shared<SyncRes::domainmap_t>();
takes too long. */
const time_t fixedNow = sr->getNow().tv_sec;
- sr->setAsyncCallback([&queriesCount, target, targetAddr, nsAddr, authZone, keys, fixedNow](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([&queriesCount, target, targetAddr, nsAddr, authZone, keys, fixedNow](const ComboAddress& ip, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
if (type == QType::DS || type == QType::DNSKEY) {
return genericDSAndDNSKEYHandler(res, domain, DNSName("."), type, keys, domain == DNSName("com.") || domain == authZone, fixedNow);
dr.d_name = authZone;
dr.d_type = QType::SOA;
dr.d_ttl = 3600;
- dr.d_content = std::make_shared<SOARecordContent>("pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600");
+ dr.setContent(std::make_shared<SOARecordContent>("pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600"));
ad.d_records.insert(dr);
dr.d_place = DNSResourceRecord::ANSWER;
dr.d_name = DNSName("test.powerdns.com.");
dr.d_type = QType::NS;
dr.d_ttl = 3600;
- dr.d_content = std::make_shared<NSRecordContent>(ns);
+ dr.setContent(std::make_shared<NSRecordContent>(ns));
ad.d_records.insert(dr);
dr.d_place = DNSResourceRecord::ANSWER;
dr.d_name = ns;
dr.d_type = QType::A;
dr.d_ttl = 3600;
- dr.d_content = std::make_shared<ARecordContent>(nsAddr);
+ dr.setContent(std::make_shared<ARecordContent>(nsAddr));
ad.d_records.insert(dr);
auto map = std::make_shared<SyncRes::domainmap_t>();
(*map)[authZone] = ad;
SyncRes::setDomainMap(map);
- sr->setAsyncCallback([&queriesCount, nsAddr, target, targetAddr](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([&queriesCount, nsAddr, target, targetAddr](const ComboAddress& ip, const DNSName& domain, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
if (ip == ComboAddress(nsAddr.toString(), 53) && domain == target) {
dr.d_name = authZone;
dr.d_type = QType::SOA;
dr.d_ttl = 3600;
- dr.d_content = std::make_shared<SOARecordContent>("pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600");
+ dr.setContent(std::make_shared<SOARecordContent>("pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600"));
ad.d_records.insert(dr);
dr.d_place = DNSResourceRecord::ANSWER;
dr.d_name = DNSName("*.powerdns.com.");
dr.d_type = QType::A;
dr.d_ttl = 3600;
- dr.d_content = std::make_shared<ARecordContent>(targetAddr);
+ dr.setContent(std::make_shared<ARecordContent>(targetAddr));
ad.d_records.insert(dr);
auto map = std::make_shared<SyncRes::domainmap_t>();
(*map)[authZone] = ad;
SyncRes::setDomainMap(map);
- sr->setAsyncCallback([&queriesCount](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([&queriesCount](const ComboAddress& /* ip */, const DNSName& /* domain */, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* /* res */, bool* /* chained */) {
queriesCount++;
return LWResult::Result::Timeout;
dr.d_name = authZone;
dr.d_type = QType::SOA;
dr.d_ttl = 3600;
- dr.d_content = std::make_shared<SOARecordContent>("pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600");
+ dr.setContent(std::make_shared<SOARecordContent>("pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600"));
ad.d_records.insert(dr);
dr.d_place = DNSResourceRecord::ANSWER;
dr.d_name = DNSName("abc.xyz.test.powerdns.com.");
dr.d_type = QType::A;
dr.d_ttl = 3600;
- dr.d_content = std::make_shared<ARecordContent>(targetAddr1);
+ dr.setContent(std::make_shared<ARecordContent>(targetAddr1));
ad.d_records.insert(dr);
dr.d_place = DNSResourceRecord::ANSWER;
dr.d_name = DNSName("*.powerdns.com.");
dr.d_type = QType::A;
dr.d_ttl = 3600;
- dr.d_content = std::make_shared<ARecordContent>(targetAddr2);
+ dr.setContent(std::make_shared<ARecordContent>(targetAddr2));
ad.d_records.insert(dr);
auto map = std::make_shared<SyncRes::domainmap_t>();
(*map)[authZone] = ad;
SyncRes::setDomainMap(map);
- sr->setAsyncCallback([&queriesCount](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([&queriesCount](const ComboAddress& /* ip */, const DNSName& /* domain */, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* /* res */, bool* /* chained */) {
queriesCount++;
return LWResult::Result::Timeout;
dr.d_name = authZone;
dr.d_type = QType::SOA;
dr.d_ttl = 3600;
- dr.d_content = std::make_shared<SOARecordContent>("pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600");
+ dr.setContent(std::make_shared<SOARecordContent>("pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600"));
ad.d_records.insert(dr);
dr.d_place = DNSResourceRecord::ANSWER;
dr.d_name = DNSName("*.powerdns.com.");
dr.d_type = QType::A;
dr.d_ttl = 3600;
- dr.d_content = std::make_shared<ARecordContent>(targetAddr);
+ dr.setContent(std::make_shared<ARecordContent>(targetAddr));
ad.d_records.insert(dr);
auto map = std::make_shared<SyncRes::domainmap_t>();
(*map)[authZone] = ad;
SyncRes::setDomainMap(map);
- sr->setAsyncCallback([&queriesCount](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([&queriesCount](const ComboAddress& /* ip */, const DNSName& /* domain */, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* /* res */, bool* /* chained */) {
queriesCount++;
return LWResult::Result::Timeout;
dr.d_name = target;
dr.d_type = QType::SOA;
dr.d_ttl = 3600;
- dr.d_content = std::make_shared<SOARecordContent>("pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600");
+ dr.setContent(std::make_shared<SOARecordContent>("pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600"));
ad.d_records.insert(dr);
dr.d_place = DNSResourceRecord::ANSWER;
dr.d_name = target;
dr.d_type = QType::A;
dr.d_ttl = 3600;
- dr.d_content = std::make_shared<ARecordContent>(addr);
+ dr.setContent(std::make_shared<ARecordContent>(addr));
ad.d_records.insert(dr);
auto map = std::make_shared<SyncRes::domainmap_t>();
(*map)[target] = ad;
SyncRes::setDomainMap(map);
- sr->setAsyncCallback([&queriesCount](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([&queriesCount](const ComboAddress& /* ip */, const DNSName& domain, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
setLWResult(res, 0, true, false, true);
addRecordToLW(res, domain, QType::A, "192.0.2.42");
skeyset_t keyset;
keyset.insert(std::make_shared<DNSKEYRecordContent>(dpk.getDNSKEY()));
- std::vector<std::shared_ptr<RRSIGRecordContent>> sigs;
+ std::vector<std::shared_ptr<const RRSIGRecordContent>> sigs;
sigs.push_back(std::make_shared<RRSIGRecordContent>(rrc));
BOOST_CHECK(validateWithKeySet(now, qname, recordcontents, sigs, keyset, std::nullopt) == vState::Secure);
size_t queriesCount = 0;
- sr->setAsyncCallback([target, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, &queriesCount, keys](const ComboAddress& /* ip */, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
if (domain == target && type == QType::NS) {
size_t queriesCount = 0;
- sr->setAsyncCallback([target, &queriesCount, zskeys, kskeys](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, &queriesCount, zskeys, kskeys](const ComboAddress& /* ip */, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
if (domain == target && type == QType::NS) {
size_t queriesCount = 0;
- sr->setAsyncCallback([target, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, &queriesCount, keys](const ComboAddress& /* ip */, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
if (domain == target && type == QType::NS) {
size_t queriesCount = 0;
- sr->setAsyncCallback([target, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, &queriesCount, keys](const ComboAddress& /* ip */, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
if (domain == target && type == QType::NS) {
size_t queriesCount = 0;
- sr->setAsyncCallback([target, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, &queriesCount, keys](const ComboAddress& /* ip */, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
if (domain == target && type == QType::NS) {
size_t queriesCount = 0;
- sr->setAsyncCallback([target, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, &queriesCount, keys](const ComboAddress& /* ip */, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
if (domain == target && type == QType::NS) {
size_t queriesCount = 0;
- sr->setAsyncCallback([target, &queriesCount, keys, rrsigkeys](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, &queriesCount, keys, rrsigkeys](const ComboAddress& /* ip */, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
if (domain == target && type == QType::NS) {
size_t queriesCount = 0;
- sr->setAsyncCallback([target, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, &queriesCount, keys](const ComboAddress& /* ip */, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
if (domain == target && type == QType::NS) {
size_t queriesCount = 0;
- sr->setAsyncCallback([target, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, &queriesCount, keys](const ComboAddress& /* ip */, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
if (domain == target && type == QType::NS) {
size_t queriesCount = 0;
- sr->setAsyncCallback([target, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, &queriesCount, keys](const ComboAddress& /* ip */, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
if (domain == target && type == QType::NS) {
size_t queriesCount = 0;
- sr->setAsyncCallback([target, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, &queriesCount, keys](const ComboAddress& /* ip */, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
if (domain == target && type == QType::NS) {
size_t queriesCount = 0;
- sr->setAsyncCallback([target, &queriesCount, keys, fixedNow](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, &queriesCount, keys, fixedNow](const ComboAddress& /* ip */, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
if (domain == target && type == QType::NS) {
size_t queriesCount = 0;
- sr->setAsyncCallback([target, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, &queriesCount, keys](const ComboAddress& /* ip */, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
if (domain == target && type == QType::NS) {
size_t queriesCount = 0;
- sr->setAsyncCallback([target, targetAddr, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, targetAddr, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
DNSName auth = domain;
size_t queriesCount = 0;
- sr->setAsyncCallback([target, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
DNSName auth = domain;
const time_t fixedNow = sr->getNow().tv_sec;
- sr->setAsyncCallback([target, targetAddr, &queriesCount, keys, fixedNow](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, targetAddr, &queriesCount, keys, fixedNow](const ComboAddress& ip, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
DNSName auth = domain;
size_t queriesCount = 0;
- sr->setAsyncCallback([target, targetAddr, &queriesCount, keys, fixedNow](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, targetAddr, &queriesCount, keys, fixedNow](const ComboAddress& ip, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
DNSName auth = domain;
size_t queriesCount = 0;
- sr->setAsyncCallback([target, targetAddr, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, targetAddr, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
DNSName auth = domain;
size_t queriesCount = 0;
- sr->setAsyncCallback([target, targetAddr, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, targetAddr, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
DNSName auth = domain;
size_t queriesCount = 0;
- sr->setAsyncCallback([target, targetAddr, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, targetAddr, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
DNSName auth = domain;
size_t queriesCount = 0;
- sr->setAsyncCallback([target, targetAddr, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, targetAddr, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
if (type == QType::DS || type == QType::DNSKEY) {
size_t queriesCount = 0;
- sr->setAsyncCallback([target, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
if (type == QType::DS || type == QType::DNSKEY) {
size_t queriesCount = 0;
- sr->setAsyncCallback([target, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
DNSName auth = domain;
size_t queriesCount = 0;
- sr->setAsyncCallback([target, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
if (type == QType::DS || type == QType::DNSKEY) {
size_t queriesCount = 0;
- sr->setAsyncCallback([target, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
if (type == QType::DS || type == QType::DNSKEY) {
size_t queriesCount = 0;
- sr->setAsyncCallback([target, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
if (type == QType::DS || type == QType::DNSKEY) {
size_t queriesCount = 0;
- sr->setAsyncCallback([target, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
if (type == QType::DS || type == QType::DNSKEY) {
size_t queriesCount = 0;
- sr->setAsyncCallback([target, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
if (type == QType::DS || type == QType::DNSKEY) {
size_t queriesCount = 0;
- sr->setAsyncCallback([target, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
if (type == QType::DS || type == QType::DNSKEY) {
size_t queriesCount = 0;
- sr->setAsyncCallback([target, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
if (type == QType::DS || type == QType::DNSKEY) {
size_t queriesCount = 0;
- sr->setAsyncCallback([target, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
if (type == QType::DS || type == QType::DNSKEY) {
size_t queriesCount = 0;
- sr->setAsyncCallback([target, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
if (type == QType::DS || type == QType::DNSKEY) {
g_luaconfs.setState(luaconfsCopy);
- sr->setAsyncCallback([target, keys](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, keys](const ComboAddress& /* ip */, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
if (type == QType::DS || type == QType::DNSKEY) {
if (domain == target) {
const auto auth = DNSName("powerdns.com.");
g_luaconfs.setState(luaconfsCopy);
- sr->setAsyncCallback([target, keys](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, keys](const ComboAddress& /* ip */, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
if (type == QType::DS || type == QType::DNSKEY) {
if (domain == target) {
const auto auth = DNSName("powerdns.com.");
g_luaconfs.setState(luaconfsCopy);
- sr->setAsyncCallback([target, keys](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, keys](const ComboAddress& /* ip */, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
if (type == QType::DS || type == QType::DNSKEY) {
if (domain == target) {
const auto auth = DNSName("powerdns.com.");
size_t queriesCount = 0;
- sr->setAsyncCallback([&queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([&queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
DNSName auth(domain);
const time_t fixedNow = sr->getNow().tv_sec;
- sr->setAsyncCallback([target, targetAddr, &queriesCount, keys, fixedNow](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, targetAddr, &queriesCount, keys, fixedNow](const ComboAddress& ip, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
DNSName auth = domain;
}
}
-static void dnssec_secure_servfail_dnskey(DNSSECMode mode, vState expectedValidationResult)
+static void dnssec_secure_servfail_dnskey(DNSSECMode mode, vState /* expectedValidationResult */)
{
std::unique_ptr<SyncRes> sr;
initSR(sr, true);
const time_t fixedNow = sr->getNow().tv_sec;
- sr->setAsyncCallback([target, targetAddr, &queriesCount, keys, fixedNow](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, targetAddr, &queriesCount, keys, fixedNow](const ComboAddress& ip, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
DNSName auth = domain;
const time_t fixedNow = sr->getNow().tv_sec;
- sr->setAsyncCallback([target, targetAddr, &queriesCount, keys, pdnskeys, fixedNow](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, targetAddr, &queriesCount, keys, pdnskeys, fixedNow](const ComboAddress& ip, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
DNSName auth = domain;
size_t queriesCount = 0;
size_t dsQueriesCount = 0;
- sr->setAsyncCallback([target, &queriesCount, &dsQueriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, &queriesCount, &dsQueriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
if (type == QType::DS) {
size_t queriesCount = 0;
- sr->setAsyncCallback([target, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
if (type == QType::DS) {
size_t queriesCount = 0;
- sr->setAsyncCallback([target, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
if (type == QType::DNSKEY || (type == QType::DS && domain != target)) {
size_t queriesCount = 0;
- sr->setAsyncCallback([target, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, &queriesCount, keys](const ComboAddress& /* ip */, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
if (type == QType::DS) {
size_t queriesCount = 0;
- sr->setAsyncCallback([target, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
if (type == QType::DS) {
size_t queriesCount = 0;
- sr->setAsyncCallback([target, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
if (type == QType::DS) {
size_t queriesCount = 0;
- sr->setAsyncCallback([target, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
if (type == QType::DS) {
size_t queriesCount = 0;
size_t dsQueriesCount = 0;
- sr->setAsyncCallback([target, &queriesCount, &dsQueriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, &queriesCount, &dsQueriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
if (type == QType::DS) {
size_t queriesCount = 0;
- sr->setAsyncCallback([target, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
if (type == QType::DS || type == QType::DNSKEY) {
size_t queriesCount = 0;
- sr->setAsyncCallback([target, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
if (type == QType::DS || type == QType::DNSKEY) {
size_t queriesCount = 0;
- sr->setAsyncCallback([target, targetAddr, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, targetAddr, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
if (type == QType::DS) {
size_t queriesCount = 0;
- sr->setAsyncCallback([target, targetAddr, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, targetAddr, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
if (type == QType::DS) {
size_t queriesCount = 0;
- sr->setAsyncCallback([target, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
if (type == QType::DS) {
size_t queriesCount = 0;
- sr->setAsyncCallback([target, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
if (type == QType::DS || type == QType::DNSKEY) {
size_t queriesCount = 0;
- sr->setAsyncCallback([target, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
if (type == QType::DS || type == QType::DNSKEY) {
size_t queriesCount = 0;
- sr->setAsyncCallback([target, targetAddr, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, targetAddr, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
if (type == QType::DS) {
size_t queriesCount = 0;
- sr->setAsyncCallback([target, targetAddr, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, targetAddr, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
if (type == QType::DS) {
size_t queriesCount = 0;
- sr->setAsyncCallback([target, targetAddr, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, targetAddr, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
if (type == QType::DS) {
size_t queriesCount = 0;
- sr->setAsyncCallback([target, targetAddr, &queriesCount, keys, pdnskeys](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, targetAddr, &queriesCount, keys, pdnskeys](const ComboAddress& ip, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
if (type == QType::DS) {
size_t queriesCount = 0;
- sr->setAsyncCallback([target, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
if (type == QType::DS || type == QType::DNSKEY) {
size_t queriesCount = 0;
- sr->setAsyncCallback([target, targetAddr, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, targetAddr, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
if (type == QType::DS) {
size_t queriesCount = 0;
- sr->setAsyncCallback([target, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
if (type == QType::DS) {
size_t queriesCount = 0;
- sr->setAsyncCallback([target, targetCName, targetCNameAddr, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, targetCName, targetCNameAddr, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
if (type == QType::DS) {
size_t queriesCount = 0;
- sr->setAsyncCallback([target, targetCName1, targetCName2, targetCName2Addr, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, targetCName1, targetCName2, targetCName2Addr, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
if (type == QType::DS || type == QType::DNSKEY) {
size_t queriesCount = 0;
- sr->setAsyncCallback([target, targetCName, targetCNameAddr, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, targetCName, targetCNameAddr, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
if (type == QType::DS) {
size_t queriesCount = 0;
- sr->setAsyncCallback([target, targetCName, targetCNameAddr, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, targetCName, targetCNameAddr, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
if (type == QType::DS || type == QType::DNSKEY) {
size_t queriesCount = 0;
- sr->setAsyncCallback([target, targetCName, targetCNameAddr, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, targetCName, targetCNameAddr, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
if (type == QType::DS || type == QType::DNSKEY) {
size_t queriesCount = 0;
- sr->setAsyncCallback([target, targetCName, targetCNameAddr, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, targetCName, targetCNameAddr, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
if (type == QType::DS || type == QType::DNSKEY) {
size_t queriesCount = 0;
- sr->setAsyncCallback([target, targetCName, targetCNameAddr, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, targetCName, targetCNameAddr, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
if (type == QType::DS) {
size_t queriesCount = 0;
- sr->setAsyncCallback([target, targetAddr, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, targetAddr, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
if (type == QType::DNSKEY) {
size_t queriesCount = 0;
- sr->setAsyncCallback([target, targetAddr, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, targetAddr, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
if (type == QType::DNSKEY) {
size_t queriesCount = 0;
- sr->setAsyncCallback([target, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, &queriesCount, keys](const ComboAddress& /* ip */, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
if (domain == target && type == QType::NS) {
size_t queriesCount = 0;
- sr->setAsyncCallback([target, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, &queriesCount, keys](const ComboAddress& /* ip */, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
if (domain == target && type == QType::NS) {
size_t queriesCount = 0;
- sr->setAsyncCallback([target, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, &queriesCount, keys](const ComboAddress& /* ip */, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
if (type == QType::DS || type == QType::DNSKEY) {
size_t queriesCount = 0;
- sr->setAsyncCallback([target, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
if (type == QType::DS || type == QType::DNSKEY) {
size_t queriesCount = 0;
- sr->setAsyncCallback([target, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
if (type == QType::DS || type == QType::DNSKEY) {
size_t queriesCount = 0;
- sr->setAsyncCallback([target, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, &queriesCount, keys](const ComboAddress& /* ip */, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
if (type == QType::DS || type == QType::DNSKEY) {
size_t queriesCount = 0;
- sr->setAsyncCallback([target, targetCName, targetCNameAddr, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, targetCName, targetCNameAddr, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
if (type == QType::DS) {
size_t queriesCount = 0;
- sr->setAsyncCallback([target, targetCName, targetCNameAddr, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, targetCName, targetCNameAddr, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
if (type == QType::DS) {
vector<DNSRecord> records;
sortedRecords_t recordContents;
- vector<shared_ptr<RRSIGRecordContent>> signatureContents;
+ vector<shared_ptr<const RRSIGRecordContent>> signatureContents;
/*
No wrap test case:
a.example.org. -> d.example.org. denies the existence of b.example.org.
*/
addNSECRecordToLW(DNSName("a.example.org."), DNSName("d.example.org"), {QType::A, QType::TXT, QType::RRSIG, QType::NSEC}, 600, records);
- recordContents.insert(records.at(0).d_content);
+ recordContents.insert(records.at(0).getContent());
addRRSIG(keys, records, DNSName("example.org."), 300);
signatureContents.push_back(getRR<RRSIGRecordContent>(records.at(1)));
records.clear();
recordContents.clear();
signatureContents.clear();
addNSECRecordToLW(DNSName("example.org."), DNSName("+.example.org"), {QType::A, QType::TXT, QType::RRSIG, QType::NSEC}, 600, records);
- recordContents.insert(records.at(0).d_content);
+ recordContents.insert(records.at(0).getContent());
addRRSIG(keys, records, DNSName("example.org."), 300);
signatureContents.push_back(getRR<RRSIGRecordContent>(records.at(1)));
records.clear();
vector<DNSRecord> records;
sortedRecords_t recordContents;
- vector<shared_ptr<RRSIGRecordContent>> signatureContents;
+ vector<shared_ptr<const RRSIGRecordContent>> signatureContents;
/*
Wrap case 1 test case:
z.example.org. -> b.example.org. denies the existence of a.example.org.
*/
addNSECRecordToLW(DNSName("z.example.org."), DNSName("b.example.org"), {QType::A, QType::TXT, QType::RRSIG, QType::NSEC}, 600, records);
- recordContents.insert(records.at(0).d_content);
+ recordContents.insert(records.at(0).getContent());
addRRSIG(keys, records, DNSName("example.org."), 300);
signatureContents.push_back(getRR<RRSIGRecordContent>(records.at(1)));
records.clear();
vector<DNSRecord> records;
sortedRecords_t recordContents;
- vector<shared_ptr<RRSIGRecordContent>> signatureContents;
+ vector<shared_ptr<const RRSIGRecordContent>> signatureContents;
/*
Wrap case 2 test case:
y.example.org. -> a.example.org. denies the existence of z.example.org.
*/
addNSECRecordToLW(DNSName("y.example.org."), DNSName("a.example.org"), {QType::A, QType::TXT, QType::RRSIG, QType::NSEC}, 600, records);
- recordContents.insert(records.at(0).d_content);
+ recordContents.insert(records.at(0).getContent());
addRRSIG(keys, records, DNSName("example.org."), 300);
signatureContents.push_back(getRR<RRSIGRecordContent>(records.at(1)));
records.clear();
vector<DNSRecord> records;
sortedRecords_t recordContents;
- vector<shared_ptr<RRSIGRecordContent>> signatureContents;
+ vector<shared_ptr<const RRSIGRecordContent>> signatureContents;
/*
Only one NSEC in the whole zone test case:
a.example.org. -> a.example.org. denies the existence of b.example.org.
*/
addNSECRecordToLW(DNSName("a.example.org."), DNSName("a.example.org"), {QType::A, QType::TXT, QType::RRSIG, QType::NSEC}, 600, records);
- recordContents.insert(records.at(0).d_content);
+ recordContents.insert(records.at(0).getContent());
addRRSIG(keys, records, DNSName("example.org."), 300);
signatureContents.push_back(getRR<RRSIGRecordContent>(records.at(1)));
records.clear();
vector<DNSRecord> records;
sortedRecords_t recordContents;
- vector<shared_ptr<RRSIGRecordContent>> signatureContents;
+ vector<shared_ptr<const RRSIGRecordContent>> signatureContents;
/*
The RRSIG from "." denies the existence of anything between a. and c.,
including b.
*/
addNSECRecordToLW(DNSName("a."), DNSName("c."), {QType::NS}, 600, records);
- recordContents.insert(records.at(0).d_content);
+ recordContents.insert(records.at(0).getContent());
addRRSIG(keys, records, DNSName("."), 300);
signatureContents.push_back(getRR<RRSIGRecordContent>(records.at(1)));
records.clear();
recordContents.clear();
signatureContents.clear();
addNSECRecordToLW(DNSName("."), DNSName("+"), {QType::A, QType::TXT, QType::RRSIG, QType::NSEC}, 600, records);
- recordContents.insert(records.at(0).d_content);
+ recordContents.insert(records.at(0).getContent());
addRRSIG(keys, records, DNSName("."), 300);
signatureContents.push_back(getRR<RRSIGRecordContent>(records.at(1)));
records.clear();
vector<DNSRecord> records;
sortedRecords_t recordContents;
- vector<shared_ptr<RRSIGRecordContent>> signatureContents;
+ vector<shared_ptr<const RRSIGRecordContent>> signatureContents;
/*
The RRSIG from "." denies the existence of any type except NS at a.
or a DS.
*/
addNSECRecordToLW(DNSName("a."), DNSName("b."), {QType::NS}, 600, records);
- recordContents.insert(records.at(0).d_content);
+ recordContents.insert(records.at(0).getContent());
addRRSIG(keys, records, DNSName("."), 300);
signatureContents.push_back(getRR<RRSIGRecordContent>(records.at(1)));
records.clear();
vector<DNSRecord> records;
sortedRecords_t recordContents;
- vector<shared_ptr<RRSIGRecordContent>> signatureContents;
+ vector<shared_ptr<const RRSIGRecordContent>> signatureContents;
addNSECRecordToLW(DNSName("example.org."), DNSName("a.example.org"), {QType::A, QType::TXT, QType::RRSIG, QType::NSEC}, 600, records);
- recordContents.insert(records.at(0).d_content);
+ recordContents.insert(records.at(0).getContent());
addRRSIG(keys, records, DNSName("example.org."), 300);
signatureContents.push_back(getRR<RRSIGRecordContent>(records.at(1)));
records.clear();
vector<DNSRecord> records;
sortedRecords_t recordContents;
- vector<shared_ptr<RRSIGRecordContent>> signatureContents;
+ vector<shared_ptr<const RRSIGRecordContent>> signatureContents;
/*
* RFC 5155 section 8.9:
we correctly detect that it's not.
*/
addNSECRecordToLW(DNSName("a."), DNSName("b."), {}, 600, records);
- recordContents.insert(records.at(0).d_content);
+ recordContents.insert(records.at(0).getContent());
addRRSIG(keys, records, DNSName("."), 300);
signatureContents.push_back(getRR<RRSIGRecordContent>(records.at(1)));
records.clear();
vector<DNSRecord> records;
sortedRecords_t recordContents;
- vector<shared_ptr<RRSIGRecordContent>> signatureContents;
+ vector<shared_ptr<const RRSIGRecordContent>> signatureContents;
/*
* RFC 5155 section 8.9:
NS has to be set since it is proving an insecure delegation, but SOA should NOT!
*/
addNSECRecordToLW(DNSName("a."), DNSName("b."), {QType::NS, QType::SOA}, 600, records);
- recordContents.insert(records.at(0).d_content);
+ recordContents.insert(records.at(0).getContent());
addRRSIG(keys, records, DNSName("."), 300);
signatureContents.push_back(getRR<RRSIGRecordContent>(records.at(1)));
records.clear();
vector<DNSRecord> records;
sortedRecords_t recordContents;
- vector<shared_ptr<RRSIGRecordContent>> signatureContents;
+ vector<shared_ptr<const RRSIGRecordContent>> signatureContents;
addNSECRecordToLW(DNSName("a.powerdns.com."), DNSName("a.c.powerdns.com."), {QType::CNAME}, 600, records);
- recordContents.insert(records.at(0).d_content);
+ recordContents.insert(records.at(0).getContent());
addRRSIG(keys, records, DNSName("powerdns.com."), 300);
signatureContents.push_back(getRR<RRSIGRecordContent>(records.at(1)));
records.clear();
vector<DNSRecord> records;
sortedRecords_t recordContents;
- vector<shared_ptr<RRSIGRecordContent>> signatureContents;
+ vector<shared_ptr<const RRSIGRecordContent>> signatureContents;
addNSEC3UnhashedRecordToLW(DNSName("powerdns.com."), DNSName("powerdns.com."), "whatever", {QType::A}, 600, records);
- recordContents.insert(records.at(0).d_content);
+ recordContents.insert(records.at(0).getContent());
addRRSIG(keys, records, DNSName("powerdns.com."), 300);
signatureContents.push_back(getRR<RRSIGRecordContent>(records.at(1)));
vector<DNSRecord> records;
sortedRecords_t recordContents;
- vector<shared_ptr<RRSIGRecordContent>> signatureContents;
+ vector<shared_ptr<const RRSIGRecordContent>> signatureContents;
addNSEC3UnhashedRecordToLW(DNSName("a.powerdns.com."), DNSName("powerdns.com."), "whatever", {QType::CNAME}, 600, records);
- recordContents.insert(records.at(0).d_content);
+ recordContents.insert(records.at(0).getContent());
addRRSIG(keys, records, DNSName("powerdns.com."), 300);
signatureContents.push_back(getRR<RRSIGRecordContent>(records.at(1)));
vector<DNSRecord> records;
sortedRecords_t recordContents;
- vector<shared_ptr<RRSIGRecordContent>> signatureContents;
+ vector<shared_ptr<const RRSIGRecordContent>> signatureContents;
addNSECRecordToLW(DNSName("a.powerdns.com."), DNSName("d.powerdns.com"), {QType::A, QType::TXT, QType::RRSIG, QType::NSEC}, 600, records);
- recordContents.insert(records.at(0).d_content);
+ recordContents.insert(records.at(0).getContent());
addRRSIG(keys, records, DNSName("powerdns.com."), 300);
signatureContents.push_back(getRR<RRSIGRecordContent>(records.at(1)));
records.clear();
vector<DNSRecord> records;
sortedRecords_t recordContents;
- vector<shared_ptr<RRSIGRecordContent>> signatureContents;
+ vector<shared_ptr<const RRSIGRecordContent>> signatureContents;
addNSEC3NarrowRecordToLW(DNSName("a.powerdns.com."), DNSName("powerdns.com."), {QType::A, QType::TXT, QType::RRSIG, QType::NSEC}, 600, records, 10);
- recordContents.insert(records.at(0).d_content);
+ recordContents.insert(records.at(0).getContent());
addRRSIG(keys, records, DNSName("powerdns.com."), 300);
signatureContents.push_back(getRR<RRSIGRecordContent>(records.at(1)));
signatureContents.clear();
records.clear();
addNSEC3UnhashedRecordToLW(DNSName("powerdns.com."), DNSName("powerdns.com."), "whatever", {QType::A, QType::TXT, QType::RRSIG, QType::NSEC}, 600, records, 10);
- recordContents.insert(records.at(0).d_content);
+ recordContents.insert(records.at(0).getContent());
addRRSIG(keys, records, DNSName("powerdns.com."), 300);
signatureContents.push_back(getRR<RRSIGRecordContent>(records.at(1)));
vector<DNSRecord> records;
sortedRecords_t recordContents;
- vector<shared_ptr<RRSIGRecordContent>> signatureContents;
+ vector<shared_ptr<const RRSIGRecordContent>> signatureContents;
/* proves that a.example.com does exist, and has been generated from a wildcard (see the RRSIG below) */
addNSECRecordToLW(DNSName("a.example.org."), DNSName("d.example.org"), {QType::A, QType::TXT, QType::RRSIG, QType::NSEC}, 600, records);
- recordContents.insert(records.at(0).d_content);
+ recordContents.insert(records.at(0).getContent());
addRRSIG(keys, records, DNSName("example.org."), 300, false, boost::none, DNSName("example.org."));
signatureContents.push_back(getRR<RRSIGRecordContent>(records.at(1)));
records.clear();
vector<DNSRecord> records;
sortedRecords_t recordContents;
- vector<shared_ptr<RRSIGRecordContent>> signatureContents;
+ vector<shared_ptr<const RRSIGRecordContent>> signatureContents;
/* proves that b.example.com does not exist */
addNSECRecordToLW(DNSName("a.example.org."), DNSName("d.example.org"), {QType::A, QType::TXT, QType::RRSIG, QType::NSEC}, 600, records);
- recordContents.insert(records.at(0).d_content);
+ recordContents.insert(records.at(0).getContent());
addRRSIG(keys, records, DNSName("example.org."), 300);
signatureContents.push_back(getRR<RRSIGRecordContent>(records.at(1)));
records.clear();
recordContents.clear();
signatureContents.clear();
addNSECRecordToLW(DNSName("*.example.org."), DNSName("+.example.org"), {QType::A, QType::TXT, QType::RRSIG, QType::NSEC}, 600, records);
- recordContents.insert(records.at(0).d_content);
+ recordContents.insert(records.at(0).getContent());
addRRSIG(keys, records, DNSName("example.org."), 300);
signatureContents.push_back(getRR<RRSIGRecordContent>(records.at(1)));
records.clear();
recordContents.clear();
signatureContents.clear();
addNSECRecordToLW(DNSName("*.example.org."), DNSName("+.example.org"), {QType::CNAME, QType::RRSIG, QType::NSEC}, 600, records);
- recordContents.insert(records.at(0).d_content);
+ recordContents.insert(records.at(0).getContent());
addRRSIG(keys, records, DNSName("example.org."), 300);
signatureContents.push_back(getRR<RRSIGRecordContent>(records.at(1)));
records.clear();
vector<DNSRecord> records;
sortedRecords_t recordContents;
- vector<shared_ptr<RRSIGRecordContent>> signatureContents;
+ vector<shared_ptr<const RRSIGRecordContent>> signatureContents;
/* proves that b.example.com does not exist */
addNSEC3NarrowRecordToLW(DNSName("b.example.org"), DNSName("example.org."), {QType::A, QType::TXT, QType::RRSIG, QType::NSEC3}, 600, records);
- recordContents.insert(records.at(0).d_content);
+ recordContents.insert(records.at(0).getContent());
addRRSIG(keys, records, DNSName("example.org."), 300);
signatureContents.push_back(getRR<RRSIGRecordContent>(records.at(1)));
signatureContents.clear();
records.clear();
addNSEC3UnhashedRecordToLW(DNSName("example.org."), DNSName("example.org."), "whatever", {QType::A, QType::TXT, QType::RRSIG, QType::NSEC}, 600, records);
- recordContents.insert(records.at(0).d_content);
+ recordContents.insert(records.at(0).getContent());
addRRSIG(keys, records, DNSName("example.org."), 300);
signatureContents.push_back(getRR<RRSIGRecordContent>(records.at(1)));
signatureContents.clear();
records.clear();
addNSEC3UnhashedRecordToLW(DNSName("*.example.org."), DNSName("example.org"), "whatever", {QType::A, QType::TXT, QType::RRSIG, QType::NSEC3}, 600, records);
- recordContents.insert(records.at(0).d_content);
+ recordContents.insert(records.at(0).getContent());
addRRSIG(keys, records, DNSName("example.org."), 300);
signatureContents.push_back(getRR<RRSIGRecordContent>(records.at(1)));
signatureContents.clear();
records.clear();
addNSEC3UnhashedRecordToLW(DNSName("*.example.org."), DNSName("example.org"), "whatever", {QType::CNAME, QType::RRSIG, QType::NSEC3}, 600, records);
- recordContents.insert(records.at(0).d_content);
+ recordContents.insert(records.at(0).getContent());
addRRSIG(keys, records, DNSName("example.org."), 300);
signatureContents.push_back(getRR<RRSIGRecordContent>(records.at(1)));
vector<DNSRecord> records;
sortedRecords_t recordContents;
- vector<shared_ptr<RRSIGRecordContent>> signatureContents;
+ vector<shared_ptr<const RRSIGRecordContent>> signatureContents;
addNSECRecordToLW(DNSName("a.powerdns.com."), DNSName("a.c.powerdns.com."), {QType::A}, 600, records);
- recordContents.insert(records.at(0).d_content);
+ recordContents.insert(records.at(0).getContent());
addRRSIG(keys, records, DNSName("powerdns.com."), 300);
signatureContents.push_back(getRR<RRSIGRecordContent>(records.at(1)));
records.clear();
recordContents.clear();
signatureContents.clear();
addNSECRecordToLW(DNSName(").powerdns.com."), DNSName("+.powerdns.com."), {}, 600, records);
- recordContents.insert(records.at(0).d_content);
+ recordContents.insert(records.at(0).getContent());
addRRSIG(keys, records, DNSName("powerdns.com."), 300);
signatureContents.push_back(getRR<RRSIGRecordContent>(records.at(1)));
records.clear();
vector<DNSRecord> records;
sortedRecords_t recordContents;
- vector<shared_ptr<RRSIGRecordContent>> signatureContents;
+ vector<shared_ptr<const RRSIGRecordContent>> signatureContents;
/*
The RRSIG from "." denies the existence of any type except NS at a.
be used to deny anything except the whole name or a DS.
*/
addNSEC3UnhashedRecordToLW(DNSName("a."), DNSName("."), "whatever", {QType::NS}, 600, records);
- recordContents.insert(records.at(0).d_content);
+ recordContents.insert(records.at(0).getContent());
addRRSIG(keys, records, DNSName("."), 300);
signatureContents.push_back(getRR<RRSIGRecordContent>(records.at(1)));
signatureContents.clear();
records.clear();
addNSEC3NarrowRecordToLW(DNSName("sub.a."), DNSName("."), {QType::A, QType::TXT, QType::RRSIG, QType::NSEC3}, 600, records);
- recordContents.insert(records.at(0).d_content);
+ recordContents.insert(records.at(0).getContent());
addRRSIG(keys, records, DNSName("."), 300);
signatureContents.push_back(getRR<RRSIGRecordContent>(records.at(1)));
signatureContents.clear();
records.clear();
addNSEC3NarrowRecordToLW(DNSName("*.a."), DNSName("."), {QType::A, QType::TXT, QType::RRSIG, QType::NSEC3}, 600, records);
- recordContents.insert(records.at(0).d_content);
+ recordContents.insert(records.at(0).getContent());
addRRSIG(keys, records, DNSName("."), 300);
signatureContents.push_back(getRR<RRSIGRecordContent>(records.at(1)));
vector<DNSRecord> records;
sortedRecords_t recordContents;
- vector<shared_ptr<RRSIGRecordContent>> signatureContents;
+ vector<shared_ptr<const RRSIGRecordContent>> signatureContents;
/* adding a NSEC3 with more iterations that we support */
addNSEC3UnhashedRecordToLW(DNSName("a."), DNSName("."), "whatever", {QType::AAAA}, 600, records, g_maxNSEC3Iterations + 100);
- recordContents.insert(records.at(0).d_content);
+ recordContents.insert(records.at(0).getContent());
addRRSIG(keys, records, DNSName("."), 300);
signatureContents.push_back(getRR<RRSIGRecordContent>(records.at(1)));
vector<DNSRecord> records;
sortedRecords_t recordContents;
- vector<shared_ptr<RRSIGRecordContent>> signatureContents;
+ vector<shared_ptr<const RRSIGRecordContent>> signatureContents;
/*
* RFC 5155 section 8.9:
we correctly detect that it's not.
*/
addNSEC3UnhashedRecordToLW(DNSName("a."), DNSName("."), "whatever", {}, 600, records);
- recordContents.insert(records.at(0).d_content);
+ recordContents.insert(records.at(0).getContent());
addRRSIG(keys, records, DNSName("."), 300);
signatureContents.push_back(getRR<RRSIGRecordContent>(records.at(1)));
vector<DNSRecord> records;
sortedRecords_t recordContents;
- vector<shared_ptr<RRSIGRecordContent>> signatureContents;
+ vector<shared_ptr<const RRSIGRecordContent>> signatureContents;
/*
* RFC 5155 section 8.9:
NS has to be set since it is proving an insecure delegation, but SOA should NOT!
*/
addNSEC3UnhashedRecordToLW(DNSName("a."), DNSName("."), "whatever", {QType::NS, QType::SOA}, 600, records);
- recordContents.insert(records.at(0).d_content);
+ recordContents.insert(records.at(0).getContent());
addRRSIG(keys, records, DNSName("."), 300);
signatureContents.push_back(getRR<RRSIGRecordContent>(records.at(1)));
vector<DNSRecord> records;
sortedRecords_t recordContents;
- vector<shared_ptr<RRSIGRecordContent>> signatureContents;
+ vector<shared_ptr<const RRSIGRecordContent>> signatureContents;
/*
* RFC 7129 section 5.1:
a wildcard proof).
*/
addNSEC3UnhashedRecordToLW(DNSName("was.here."), DNSName("."), "whatever", {}, 600, records, 10, true /* opt out */);
- recordContents.insert(records.at(0).d_content);
+ recordContents.insert(records.at(0).getContent());
addRRSIG(keys, records, DNSName("."), 300);
signatureContents.push_back(getRR<RRSIGRecordContent>(records.at(1)));
signatureContents.clear();
records.clear();
addNSEC3NarrowRecordToLW(DNSName("ent.was.here."), DNSName("."), {QType::RRSIG, QType::NSEC3}, 600, records, 10, true /* opt-out */);
- recordContents.insert(records.at(0).d_content);
+ recordContents.insert(records.at(0).getContent());
addRRSIG(keys, records, DNSName("."), 300);
signatureContents.push_back(getRR<RRSIGRecordContent>(records.at(1)));
size_t queriesCount = 0;
const time_t fixedNow = sr->getNow().tv_sec;
- sr->setAsyncCallback([target, &queriesCount, keys, fixedNow](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, &queriesCount, keys, fixedNow](const ComboAddress& /* ip */, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
DNSName auth = domain;
size_t queriesCount = 0;
const time_t fixedNow = sr->getNow().tv_sec;
- sr->setAsyncCallback([&queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([&queriesCount, keys](const ComboAddress& /* ip */, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
DNSName auth = domain;
size_t queriesCount = 0;
const time_t tnow = sr->getNow().tv_sec;
- sr->setAsyncCallback([target, targetAddr, &queriesCount, keys, tnow](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, targetAddr, &queriesCount, keys, tnow](const ComboAddress& /* ip */, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
DNSName auth = domain;
/* check that the entry has not been cached for longer than the RRSIG validity */
const ComboAddress who;
vector<DNSRecord> cached;
- vector<std::shared_ptr<RRSIGRecordContent>> signatures;
+ vector<std::shared_ptr<const RRSIGRecordContent>> signatures;
BOOST_REQUIRE_EQUAL(g_recCache->get(tnow, target, QType(QType::A), MemRecursorCache::RequireAuth, &cached, who, boost::none, &signatures), 1);
BOOST_REQUIRE_EQUAL(cached.size(), 1U);
BOOST_REQUIRE_EQUAL(signatures.size(), 1U);
size_t queriesCount = 0;
- sr->setAsyncCallback([target, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, &queriesCount, keys](const ComboAddress& /* ip */, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
if (type == QType::DS || type == QType::DNSKEY) {
size_t queriesCount = 0;
- sr->setAsyncCallback([target, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, &queriesCount, keys](const ComboAddress& /* ip */, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
if (type == QType::DS || type == QType::DNSKEY) {
size_t queriesCount = 0;
- sr->setAsyncCallback([target, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, &queriesCount, keys](const ComboAddress& /* ip */, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
if (type == QType::DS || type == QType::DNSKEY) {
size_t queriesCount = 0;
- sr->setAsyncCallback([target, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, &queriesCount, keys](const ComboAddress& /* ip */, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
if (type == QType::DS || type == QType::DNSKEY) {
size_t queriesCount = 0;
- sr->setAsyncCallback([target, cnameTarget, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, cnameTarget, &queriesCount, keys](const ComboAddress& /* ip */, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
if (type == QType::DS || type == QType::DNSKEY) {
size_t queriesCount = 0;
- sr->setAsyncCallback([target, cnameTarget, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, cnameTarget, &queriesCount, keys](const ComboAddress& /* ip */, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
if (type == QType::DS || type == QType::DNSKEY) {
size_t queriesCount = 0;
- sr->setAsyncCallback([target, cnameTarget, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, cnameTarget, &queriesCount, keys](const ComboAddress& /* ip */, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
if (type == QType::DS || type == QType::DNSKEY) {
size_t queriesCount = 0;
- sr->setAsyncCallback([target, addTarget, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, addTarget, &queriesCount, keys](const ComboAddress& /* ip */, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
if (type == QType::DS || type == QType::DNSKEY) {
size_t queriesCount = 0;
const time_t fixedNow = sr->getNow().tv_sec;
- sr->setAsyncCallback([target, &queriesCount, keys, fixedNow](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, &queriesCount, keys, fixedNow](const ComboAddress& /* ip */, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
DNSName auth = domain;
size_t queriesCount = 0;
- sr->setAsyncCallback([target, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, &queriesCount, keys](const ComboAddress& /* ip */, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
if (type == QType::DS || type == QType::DNSKEY) {
size_t queriesCount = 0;
- sr->setAsyncCallback([target, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, &queriesCount, keys](const ComboAddress& /* ip */, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
DNSName auth = domain;
size_t queriesCount = 0;
- sr->setAsyncCallback([target, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, &queriesCount, keys](const ComboAddress& /* ip */, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
DNSName auth = domain;
const DNSName target("WWW.POWERDNS.COM");
const DNSName cname("WWW.PowerDNS.org");
- sr->setAsyncCallback([target, cname, &sentOutQnames](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, cname, &sentOutQnames](const ComboAddress& ip, const DNSName& domain, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
sentOutQnames.push_back(domain);
if (isRootServer(ip)) {
BOOST_CHECK_EQUAL(res, RCode::NoError);
BOOST_REQUIRE_EQUAL(ret.size(), 2U);
- BOOST_CHECK_EQUAL(ret[0].d_content->getZoneRepresentation(), cname.toString());
+ BOOST_CHECK_EQUAL(ret[0].getContent()->getZoneRepresentation(), cname.toString());
BOOST_REQUIRE_EQUAL(sentOutQnames.size(), 4U);
BOOST_CHECK_EQUAL(sentOutQnames[0].toString(), target.makeLowerCase().toString());
auto rootkey = keys.find(g_rootdnsname);
keys2.insert(*rootkey);
- sr->setAsyncCallback([target, keys, keys2](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, keys, keys2](const ComboAddress& /* ip */, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
DNSName auth = domain;
auth.chopOff();
if (type == QType::DS || type == QType::DNSKEY) {
// But add the existing root key otherwise no RRSIG can be created
keys3.insert(*rootkey);
- sr->setAsyncCallback([target, keys, keys2, keys3](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, keys, keys2, keys3](const ComboAddress& /* ip */, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
DNSName auth = domain;
auth.chopOff();
if (type == QType::DS || type == QType::DNSKEY) {
// But add the existing root key otherwise no RRSIG can be created
keys3.insert(*rootkey);
- sr->setAsyncCallback([target, keys, keys2, keys3](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, keys, keys2, keys3](const ComboAddress& /* ip */, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
DNSName auth = domain;
auth.chopOff();
if (type == QType::DS || type == QType::DNSKEY) {
const DNSName cnameTarget("cname-target.powerdns.com");
size_t queriesCount = 0;
- sr->setAsyncCallback([target, cnameTarget, &queriesCount](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, cnameTarget, &queriesCount](const ComboAddress& ip, const DNSName& domain, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
if (isRootServer(ip)) {
generateKeyMaterial(DNSName("powerdns.com."), DNSSECKeeper::ECDSA256, DNSSECKeeper::DIGEST_SHA256, keys);
g_luaconfs.setState(luaconfsCopy);
- sr->setAsyncCallback([keys](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([keys](const ComboAddress& ip, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
if (type == QType::DS || type == QType::DNSKEY) {
if (domain == DNSName("cname.powerdns.com.")) {
return genericDSAndDNSKEYHandler(res, domain, domain, type, keys, false /* no cut */);
const DNSName target("sanitization.powerdns.com.");
- sr->setAsyncCallback([target](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target](const ComboAddress& /* ip */, const DNSName& domain, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
setLWResult(res, 0, true, false, true);
addRecordToLW(res, domain, QType::A, "192.0.2.1");
/* should be scrubbed because it doesn't match the QType */
const DNSName target("sanitization.powerdns.com.");
- sr->setAsyncCallback([target](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target](const ComboAddress& /* ip */, const DNSName& domain, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
setLWResult(res, 0, true, false, true);
addRecordToLW(res, domain, QType::A, "192.0.2.1");
addRecordToLW(res, domain, QType::AAAA, "2001:db8::1", DNSResourceRecord::ADDITIONAL);
size_t queriesCount = 0;
- sr->setAsyncCallback([target, &queriesCount](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, &queriesCount](const ComboAddress& ip, const DNSName& /* domain */, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
if (isRootServer(ip)) {
/* check that we accepted the DS from the parent, and not from the child zone */
BOOST_CHECK_GT(g_recCache->get(now, DNSName("powerdns.com."), QType(QType::DS), MemRecursorCache::None, &cached, who), 0);
BOOST_REQUIRE_EQUAL(cached.size(), 1U);
- BOOST_CHECK_EQUAL(cached.at(0).d_content->getZoneRepresentation(), "1 8 2 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
+ BOOST_CHECK_EQUAL(cached.at(0).getContent()->getZoneRepresentation(), "1 8 2 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
}
BOOST_AUTO_TEST_CASE(test_records_sanitization_scrubs_ns_nxd)
const DNSName target("sanitization-ns-nxd.powerdns.com.");
- sr->setAsyncCallback([target](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target](const ComboAddress& /* ip */, const DNSName& /* domain */, int /* type */, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
setLWResult(res, RCode::NXDomain, true, false, true);
addRecordToLW(res, "powerdns.com.", QType::SOA, "pdns-public-ns1.powerdns.com. pieter\\.lexis.powerdns.com. 2017032301 10800 3600 604800 3600", DNSResourceRecord::AUTHORITY);
addRecordToLW(res, "powerdns.com.", QType::NS, "spoofed.ns.", DNSResourceRecord::AUTHORITY, 172800);
size_t queriesCount = 0;
- sr->setAsyncCallback([target, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
if (domain.isPartOf(DNSName("signed.ds-ignorant.com.")) && ip == ComboAddress("192.0.2.1:53")) {
size_t queriesCount = 0;
- sr->setAsyncCallback([target, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, boost::optional<Netmask>& srcmask, boost::optional<const ResolveContext&> context, LWResult* res, bool* chained) {
+ sr->setAsyncCallback([target, &queriesCount, keys](const ComboAddress& ip, const DNSName& domain, int type, bool /* doTCP */, bool /* sendRDQuery */, int /* EDNS0Level */, struct timeval* /* now */, boost::optional<Netmask>& /* srcmask */, boost::optional<const ResolveContext&> /* context */, LWResult* res, bool* /* chained */) {
queriesCount++;
if (domain.isPartOf(DNSName("signed.ds-ignorant.com.")) && ip == ComboAddress("192.0.2.1:53")) {
{"name", dr.d_name.toString()},
{"type", DNSRecordContent::NumberToType(dr.d_type)},
{"ttl", (double)dr.d_ttl},
- {"content", dr.d_content->getZoneRepresentation()}});
+ {"content", dr.getContent()->getZoneRepresentation()}});
}
// id is the canonical lookup key, which doesn't actually match the name (in some cases)
const SyncRes::AuthDomain& zone = val.second;
for (const SyncRes::AuthDomain::records_t::value_type& rr : zone.d_records) {
- if (pdns_ci_find(rr.d_name.toString(), q) == string::npos && pdns_ci_find(rr.d_content->getZoneRepresentation(), q) == string::npos)
+ if (pdns_ci_find(rr.d_name.toString(), q) == string::npos && pdns_ci_find(rr.getContent()->getZoneRepresentation(), q) == string::npos)
continue;
doc.push_back(Json::object{
{"zone_id", zoneId},
{"zone_name", zoneName},
{"name", rr.d_name.toString()},
- {"content", rr.d_content->getZoneRepresentation()}});
+ {"content", rr.getContent()->getZoneRepresentation()}});
}
}
resp->setJsonBody(doc);
{"record-cache-contended",
MetricDefinition(PrometheusMetricType::counter,
- "Number of contented record cache lock acquisitions")},
+ "Number of contended record cache lock acquisitions")},
+
+ {"packetcache-acquired",
+ MetricDefinition(PrometheusMetricType::counter,
+ "Number of packet cache lock acquisitions")},
+
+ {"packetcache-contended",
+ MetricDefinition(PrometheusMetricType::counter,
+ "Number of contended packet cache lock acquisitions")},
{"taskqueue-expired",
MetricDefinition(PrometheusMetricType::counter,
rr.qname = i.first.d_name;
rr.qtype = i.first.d_type;
rr.ttl = i.first.d_ttl;
- rr.content = i.first.d_content->getZoneRepresentation(true);
+ rr.content = i.first.getContent()->getZoneRepresentation(true);
result->push_back(rr);
}
bool gotSOA=false;
for(const MOADNSParser::answers_t::value_type& drc : mdp.d_answers) {
if(drc.first.d_type == QType::SOA && drc.first.d_name == *domain) {
- shared_ptr<SOARecordContent> src=getRR<SOARecordContent>(drc.first);
+ auto src = getRR<SOARecordContent>(drc.first);
if (src) {
- *theirSerial=src->d_st.serial;
+ *theirSerial = src->d_st.serial;
gotSOA = true;
}
}
if(drc.first.d_type == QType::RRSIG && drc.first.d_name == *domain) {
- shared_ptr<RRSIGRecordContent> rrc=getRR<RRSIGRecordContent>(drc.first);
+ auto rrc = getRR<RRSIGRecordContent>(drc.first);
if(rrc && rrc->d_type == QType::SOA) {
*theirInception= std::max(*theirInception, rrc->d_siginception);
*theirExpire = std::max(*theirExpire, rrc->d_sigexpire);
if (rrType == QType::NSEC3PARAM) {
g_log<<Logger::Notice<<msgPrefix<<"Adding/updating NSEC3PARAM for zone, resetting ordernames."<<endl;
- *ns3pr = NSEC3PARAMRecordContent(rr->d_content->getZoneRepresentation(), di->zone);
+ *ns3pr = NSEC3PARAMRecordContent(rr->getContent()->getZoneRepresentation(), di->zone);
*narrow = false; // adding a NSEC3 will cause narrow mode to be dropped, as you cannot specify that in a NSEC3PARAM record
d_dk.setNSEC3PARAM(di->zone, *ns3pr, (*narrow));
*haveNSEC3 = true;
SOAData sdOld, sdUpdate;
DNSResourceRecord *oldRec = &rrset.front();
fillSOAData(oldRec->content, sdOld);
- oldRec->setContent(rr->d_content->getZoneRepresentation());
+ oldRec->setContent(rr->getContent()->getZoneRepresentation());
fillSOAData(oldRec->content, sdUpdate);
if (rfc1982LessThan(sdOld.serial, sdUpdate.serial)) {
di->backend->replaceRRSet(di->id, oldRec->qname, oldRec->qtype, rrset);
} else if (rrType == QType::CNAME) {
int changedCNames = 0;
for (auto& i : rrset) {
- if (i.ttl != rr->d_ttl || i.content != rr->d_content->getZoneRepresentation()) {
+ if (i.ttl != rr->d_ttl || i.content != rr->getContent()->getZoneRepresentation()) {
i.ttl = rr->d_ttl;
- i.setContent(rr->d_content->getZoneRepresentation());
+ i.setContent(rr->getContent()->getZoneRepresentation());
changedCNames++;
}
}
rrType.getCode() == QType::SRV) {
lowerCase = true;
}
- string content = rr->d_content->getZoneRepresentation();
+ string content = rr->getContent()->getZoneRepresentation();
if (lowerCase) content = toLower(content);
for (auto& i : rrset) {
string icontent = i.getZoneRepresentation();
if (rr->d_class == QClass::ANY)
d_dk.unsetNSEC3PARAM(rr->d_name);
else if (rr->d_class == QClass::NONE) {
- NSEC3PARAMRecordContent nsec3rr(rr->d_content->getZoneRepresentation(), di->zone);
+ NSEC3PARAMRecordContent nsec3rr(rr->getContent()->getZoneRepresentation(), di->zone);
if (*haveNSEC3 && ns3pr->getZoneRepresentation() == nsec3rr.getZoneRepresentation())
d_dk.unsetNSEC3PARAM(rr->d_name);
else
repr = rc->getZoneRepresentation(true);
DLOG(g_log<<msgPrefix<<"Adjusted TXT content to ["<<repr<<"]"<<endl);
}
- DLOG(g_log<<msgPrefix<<"Matching RR in RRset - (adjusted) representation from request=["<<repr<<"], rr->d_content->getZoneRepresentation()=["<<rr->d_content->getZoneRepresentation()<<"]"<<endl);
- if (rrType == rec.qtype && repr == rr->d_content->getZoneRepresentation())
+ DLOG(g_log<<msgPrefix<<"Matching RR in RRset - (adjusted) representation from request=["<<repr<<"], rr->getContent()->getZoneRepresentation()=["<<rr->getContent()->getZoneRepresentation()<<"]"<<endl);
+ if (rrType == rec.qtype && repr == rr->getContent()->getZoneRepresentation())
recordsToDelete.push_back(rec);
else
rrset.push_back(rec);
if (nsRRInZone.size() > nsRRtoDelete.size()) { // only delete if the NS's we delete are less then what we have in the zone (3.4.2.4)
for (auto& inZone: nsRRInZone) {
for (auto& rr: nsRRtoDelete) {
- if (inZone.getZoneRepresentation() == (rr)->d_content->getZoneRepresentation())
+ if (inZone.getZoneRepresentation() == (rr)->getContent()->getZoneRepresentation())
changedRecords += performUpdate(msgPrefix, rr, &di, isPresigned, &narrow, &haveNSEC3, &ns3pr, &updatedSerial);
}
}
for(MOADNSParser::answers_t::const_iterator i=mdp.d_answers.begin(); i!=mdp.d_answers.end(); ++i) {
if(i->first.d_type != QType::TKEY) continue;
// recover TKEY record
- tkrc = TKEYRecordContent(i->first.d_content->getZoneRepresentation());
+ tkrc = TKEYRecordContent(i->first.getContent()->getZoneRepresentation());
input = tkrc.d_key;
}
}
if (!tsig) {
std::cerr<<"Unexpected TSIG signature in data"<<endl;
}
- trc = TSIGRecordContent(i->first.d_content->getZoneRepresentation());
+ trc = TSIGRecordContent(i->first.getContent()->getZoneRepresentation());
continue;
}
if(i->first.d_type == QType::SOA)
++soacount;
}
else if (i->first.d_type == QType::NSEC3PARAM) {
- ns3pr = NSEC3PARAMRecordContent(i->first.d_content->getZoneRepresentation());
- isNSEC3 = true;
+ ns3pr = NSEC3PARAMRecordContent(i->first.getContent()->getZoneRepresentation());
+ isNSEC3 = true;
}
ostringstream o;
o<<"\t"<<i->first.d_ttl<<"\tIN\t"<<DNSRecordContent::NumberToType(i->first.d_type);
if(showdetails)
{
- o<<"\t"<<i->first.d_content->getZoneRepresentation();
+ o<<"\t"<<i->first.getContent()->getZoneRepresentation();
}
else if(i->first.d_type == QType::RRSIG)
{
- string zoneRep = i->first.d_content->getZoneRepresentation();
+ string zoneRep = i->first.getContent()->getZoneRepresentation();
vector<string> parts;
stringtok(parts, zoneRep);
o<<"\t"<<parts[0]<<" "<<parts[1]<<" "<<parts[2]<<" "<<parts[3]<<" [expiry] [inception] [keytag] "<<parts[7]<<" ...";
}
else if(i->first.d_type == QType::NSEC3)
{
- string zoneRep = i->first.d_content->getZoneRepresentation();
+ string zoneRep = i->first.getContent()->getZoneRepresentation();
vector<string> parts;
stringtok(parts, zoneRep);
o<<"\t"<<parts[0]<<" ";
}
else if(i->first.d_type == QType::DNSKEY)
{
- string zoneRep = i->first.d_content->getZoneRepresentation();
+ string zoneRep = i->first.getContent()->getZoneRepresentation();
vector<string> parts;
stringtok(parts, zoneRep);
o<<"\t"<<parts[0]<<" "<<parts[1]<<" "<<parts[2]<<" ...";
}
else
{
- o<<"\t"<<i->first.d_content->getZoneRepresentation();
+ o<<"\t"<<i->first.getContent()->getZoneRepresentation();
}
records.emplace_back(i->first.d_name, o.str());
<< ttl(i->first.d_ttl) << "\t" << nameForClass(i->first.d_class, i->first.d_type) << "\t"
<< DNSRecordContent::NumberToType(i->first.d_type);
if (dumpluaraw) {
- cout<<"\t"<< makeLuaString(i->first.d_content->serialize(DNSName(), true))<<endl;
+ cout<<"\t"<< makeLuaString(i->first.getContent()->serialize(DNSName(), true))<<endl;
continue;
}
if (i->first.d_class == QClass::IN) {
if (i->first.d_type == QType::RRSIG) {
- string zoneRep = i->first.d_content->getZoneRepresentation();
+ string zoneRep = i->first.getContent()->getZoneRepresentation();
vector<string> parts;
stringtok(parts, zoneRep);
cout << "\t" << parts[0] << " "
continue;
}
if (!showflags && i->first.d_type == QType::NSEC3) {
- string zoneRep = i->first.d_content->getZoneRepresentation();
+ string zoneRep = i->first.getContent()->getZoneRepresentation();
vector<string> parts;
stringtok(parts, zoneRep);
cout << "\t" << parts[0] << " [flags] "
continue;
}
if (i->first.d_type == QType::DNSKEY) {
- string zoneRep = i->first.d_content->getZoneRepresentation();
+ string zoneRep = i->first.getContent()->getZoneRepresentation();
vector<string> parts;
stringtok(parts, zoneRep);
cout << "\t" << parts[0] << " "
continue;
}
if (i->first.d_type == QType::SOA && hidesoadetails) {
- string zoneRep = i->first.d_content->getZoneRepresentation();
+ string zoneRep = i->first.getContent()->getZoneRepresentation();
vector<string> parts;
stringtok(parts, zoneRep);
cout << "\t" << parts[0] << " "
continue;
}
}
- cout << "\t" << i->first.d_content->getZoneRepresentation() << "\n";
+ cout << "\t" << i->first.getContent()->getZoneRepresentation() << "\n";
}
EDNSOpts edo;
soa.d_type = QType::SOA;
soa.d_ttl = sd.ttl;
soa.d_place = place;
- soa.d_content = makeSOAContent(edited);
+ soa.setContent(makeSOAContent(edited));
DNSZoneRecord dzr;
dzr.domain_id = sd.domain_id;
bool
dedupLessThan(const DNSZoneRecord& a, const DNSZoneRecord &b)
{
- return std::make_tuple(a.dr.d_content->getZoneRepresentation(), a.dr.d_ttl) < std::make_tuple(b.dr.d_content->getZoneRepresentation(), b.dr.d_ttl); // XXX SLOW SLOW SLOW
+ return std::make_tuple(a.dr.getContent()->getZoneRepresentation(), a.dr.d_ttl) < std::make_tuple(b.dr.getContent()->getZoneRepresentation(), b.dr.d_ttl); // XXX SLOW SLOW SLOW
}
bool dedupEqual(const DNSZoneRecord& a, const DNSZoneRecord &b)
{
- return std::make_tuple(a.dr.d_content->getZoneRepresentation(), a.dr.d_ttl) == std::make_tuple(b.dr.d_content->getZoneRepresentation(), b.dr.d_ttl); // XXX SLOW SLOW SLOW
+ return std::make_tuple(a.dr.getContent()->getZoneRepresentation(), a.dr.d_ttl) == std::make_tuple(b.dr.getContent()->getZoneRepresentation(), b.dr.d_ttl); // XXX SLOW SLOW SLOW
}
}
}
-void LOCRecordContent::toPacket(DNSPacketWriter& pw)
+void LOCRecordContent::toPacket(DNSPacketWriter& pw) const
{
pw.xfr8BitInt(d_version);
pw.xfr8BitInt(d_size);
st.serial=di.serial;
DNSRecord drsoa;
- drsoa.d_content = std::make_shared<SOARecordContent>(g_rootdnsname, g_rootdnsname, st);
+ drsoa.setContent(std::make_shared<SOARecordContent>(g_rootdnsname, g_rootdnsname, st));
auto deltas = getIXFRDeltas(remote, domain, drsoa, xfrTimeout, false, tt, laddr.sin4.sin_family ? &laddr : nullptr, ((size_t) ::arg().asNum("xfr-max-received-mbytes")) * 1024 * 1024);
zs.numDeltas=deltas.size();
// cout<<"Got "<<deltas.size()<<" deltas from serial "<<di.serial<<", applying.."<<endl;
snmp_read2(&fdset);
}
-void SNMPAgent::handleTrapsCB(int fd, FDMultiplexer::funcparam_t& var)
+void SNMPAgent::handleTrapsCB(int /* fd */, FDMultiplexer::funcparam_t& var)
{
SNMPAgent** agent = boost::any_cast<SNMPAgent*>(&var);
if (!agent || !*agent)
cmd();
}
double delta=dt.ndiff()/1000000000.0;
- boost::format fmt("'%s' %.02f seconds: %.1f runs/s, %.02f usec/run");
+ boost::format fmt("'%s' %.02f seconds: %.1f runs/s, %.02f us/run");
cerr<< (fmt % cmd.getName() % delta % (runs/delta) % (delta* 1000000.0/runs)) << endl;
g_totalRuns += runs;
throw SSqlException(string("Error while retrieving SQLite query results: ")+SSQLite3ErrorString(d_db->db()));
}
if(d_dolog)
- g_log<<Logger::Warning<< "Query "<<((long)(void*)this)<<": "<<d_dtime.udiffNoReset()<<" usec to execute"<<endl;
+ g_log<<Logger::Warning<< "Query "<<((long)(void*)this)<<": "<<d_dtime.udiffNoReset()<<" us to execute"<<endl;
return this;
}
bool hasNextRow() {
if(d_dolog && d_rc != SQLITE_ROW) {
- g_log<<Logger::Warning<< "Query "<<((long)(void*)this)<<": "<<d_dtime.udiffNoReset()<<" total usec to last row"<<endl;
+ g_log<<Logger::Warning<< "Query "<<((long)(void*)this)<<": "<<d_dtime.udiffNoReset()<<" us total to last row"<<endl;
}
return d_rc == SQLITE_ROW;
}
childstat.servfails += s.servfails;
childstat.drops += s.drops;
childstat.bytes += s.bytes;
+ childstat.hits += s.hits;
if(children.size()>1024 && !silent) {
cout<<string(depth, ' ')<<name<<": too many to print"<<endl;
childstat.nxdomains<<" nxdomains, "<<
childstat.servfails<<" servfails, "<<
childstat.drops<<" drops, "<<
- childstat.bytes<<" bytes"<<endl;
+ childstat.bytes<<" bytes, "<<
+ childstat.hits<<" hits"<<endl;
newstat+=childstat;
}
-void StatNode::submit(const DNSName& domain, int rcode, unsigned int bytes, boost::optional<const ComboAddress&> remote)
+void StatNode::submit(const DNSName& domain, int rcode, unsigned int bytes, bool hit, boost::optional<const ComboAddress&> remote)
{
// cerr<<"FIRST submit called on '"<<domain<<"'"<<endl;
std::vector<string> tmp = domain.getRawLabels();
}
auto last = tmp.end() - 1;
- children[*last].submit(last, tmp.begin(), "", rcode, bytes, remote, 1);
+ children[*last].submit(last, tmp.begin(), "", rcode, bytes, remote, 1, hit);
}
/* www.powerdns.com. ->
www.powerdns.com.
*/
-void StatNode::submit(std::vector<string>::const_iterator end, std::vector<string>::const_iterator begin, const std::string& domain, int rcode, unsigned int bytes, boost::optional<const ComboAddress&> remote, unsigned int count)
+void StatNode::submit(std::vector<string>::const_iterator end, std::vector<string>::const_iterator begin, const std::string& domain, int rcode, unsigned int bytes, boost::optional<const ComboAddress&> remote, unsigned int count, bool hit)
{
// cerr<<"Submit called for domain='"<<domain<<"': ";
// for(const std::string& n : labels)
// cerr<<"Hit the end, set our fullname to '"<<fullname<<"'"<<endl<<endl;
s.queries++;
s.bytes += bytes;
- if(rcode<0)
+ if (rcode < 0) {
s.drops++;
- else if(rcode==0)
+ }
+ else if (rcode == RCode::NoError) {
s.noerrors++;
- else if(rcode==2)
+ }
+ else if (rcode == RCode::ServFail) {
s.servfails++;
- else if(rcode==3)
+ }
+ else if (rcode == RCode::NXDomain) {
s.nxdomains++;
+ }
if (remote) {
s.remotes[*remote]++;
}
+
+ if (hit) {
+ ++s.hits;
+ }
}
else {
if (fullname.empty()) {
}
// cerr<<"Not yet end, set our fullname to '"<<fullname<<"', recursing"<<endl;
--end;
- children[*end].submit(end, begin, fullname, rcode, bytes, remote, count+1);
+ children[*end].submit(end, begin, fullname, rcode, bytes, remote, count+1, hit);
}
}
struct Stat
{
- Stat(): queries(0), noerrors(0), nxdomains(0), servfails(0), drops(0), bytes(0)
+ Stat()
{
}
- uint64_t queries, noerrors, nxdomains, servfails, drops, bytes;
+
+ uint64_t queries{0};
+ uint64_t noerrors{0};
+ uint64_t nxdomains{0};
+ uint64_t servfails{0};
+ uint64_t drops{0};
+ uint64_t bytes{0};
+ uint64_t hits{0};
+ using remotes_t = std::map<ComboAddress,int,ComboAddress::addressOnlyLessThan>;
+ remotes_t remotes;
Stat& operator+=(const Stat& rhs) {
- queries+=rhs.queries;
- noerrors+=rhs.noerrors;
- nxdomains+=rhs.nxdomains;
- servfails+=rhs.servfails;
- drops+=rhs.drops;
- bytes+=rhs.bytes;
+ queries += rhs.queries;
+ noerrors += rhs.noerrors;
+ nxdomains += rhs.nxdomains;
+ servfails += rhs.servfails;
+ drops += rhs.drops;
+ bytes += rhs.bytes;
+ hits += rhs.hits;
- for(const remotes_t::value_type& rem : rhs.remotes) {
- remotes[rem.first]+=rem.second;
+ for (const remotes_t::value_type& rem : rhs.remotes) {
+ remotes[rem.first] += rem.second;
}
return *this;
}
- typedef std::map<ComboAddress,int,ComboAddress::addressOnlyLessThan> remotes_t;
- remotes_t remotes;
};
+ using visitor_t = std::function<void(const StatNode*, const Stat& selfstat, const Stat& childstat)>;
+ using children_t = std::map<std::string, StatNode, CIStringCompare>;
+
Stat s;
std::string name;
std::string fullname;
uint8_t labelsCount{0};
- void submit(const DNSName& domain, int rcode, unsigned int bytes, boost::optional<const ComboAddress&> remote);
-
+ void submit(const DNSName& domain, int rcode, unsigned int bytes, bool hit, boost::optional<const ComboAddress&> remote);
Stat print(unsigned int depth=0, Stat newstat=Stat(), bool silent=false) const;
- typedef std::function<void(const StatNode*, const Stat& selfstat, const Stat& childstat)> visitor_t;
void visit(visitor_t visitor, Stat& newstat, unsigned int depth=0) const;
bool empty() const
{
return children.empty() && s.remotes.empty();
}
- typedef std::map<std::string,StatNode, CIStringCompare> children_t;
children_t children;
private:
- void submit(std::vector<string>::const_iterator end, std::vector<string>::const_iterator begin, const std::string& domain, int rcode, unsigned int bytes, boost::optional<const ComboAddress&> remote, unsigned int count);
+ void submit(std::vector<string>::const_iterator end, std::vector<string>::const_iterator begin, const std::string& domain, int rcode, unsigned int bytes, boost::optional<const ComboAddress&> remote, unsigned int count, bool hit);
};
cout<<"res: "<<res<<endl;
for(const auto& r : ret) {
- cout<<r.dr.d_content->getZoneRepresentation()<<endl;
+ cout<<r.dr.getContent()->getZoneRepresentation()<<endl;
}
}
catch(std::exception &e)
private:
/* called in a client context, if the client advertised more than one ALPN values and the server returned more than one as well, to select the one to use. */
#ifndef DISABLE_NPN
- static int npnSelectCallback(SSL* s, unsigned char** out, unsigned char* outlen, const unsigned char* in, unsigned int inlen, void* arg)
+ static int npnSelectCallback(SSL* /* s */, unsigned char** out, unsigned char* outlen, const unsigned char* in, unsigned int inlen, void* arg)
{
if (!arg) {
return SSL_TLSEXT_ERR_ALERT_WARNING;
continue;
}
zrr.dr.d_type = QType::DNSKEY;
- zrr.dr.d_content = std::make_shared<DNSKEYRecordContent>(value.first.getDNSKEY());
+ zrr.dr.setContent(std::make_shared<DNSKEYRecordContent>(value.first.getDNSKEY()));
DNSName keyname = NSEC3Zone ? DNSName(toBase32Hex(hashQNameWithSalt(ns3pr, zrr.dr.d_name))) : zrr.dr.d_name;
zrrs.push_back(zrr);
zrr.dr.d_type=QType::CDNSKEY;
if (publishCDNSKEY == "0") {
doCDNSKEY = false;
- zrr.dr.d_content=PacketHandler::s_deleteCDNSKEYContent;
+ zrr.dr.setContent(PacketHandler::s_deleteCDNSKEYContent);
zrrs.push_back(zrr);
} else {
- zrr.dr.d_content = std::make_shared<DNSKEYRecordContent>(value.first.getDNSKEY());
+ zrr.dr.setContent(std::make_shared<DNSKEYRecordContent>(value.first.getDNSKEY()));
zrrs.push_back(zrr);
}
}
stringtok(digestAlgos, publishCDS, ", ");
if(std::find(digestAlgos.begin(), digestAlgos.end(), "0") != digestAlgos.end()) {
doCDS = false;
- zrr.dr.d_content=PacketHandler::s_deleteCDSContent;
+ zrr.dr.setContent(PacketHandler::s_deleteCDSContent);
zrrs.push_back(zrr);
} else {
for(auto const &digestAlgo : digestAlgos) {
- zrr.dr.d_content=std::make_shared<DSRecordContent>(makeDSFromDNSKey(target, value.first.getDNSKEY(), pdns::checked_stoi<uint8_t>(digestAlgo)));
+ zrr.dr.setContent(std::make_shared<DSRecordContent>(makeDSFromDNSKey(target, value.first.getDNSKEY(), pdns::checked_stoi<uint8_t>(digestAlgo))));
zrrs.push_back(zrr);
}
}
uint8_t flags = ns3pr.d_flags;
zrr.dr.d_type = QType::NSEC3PARAM;
ns3pr.d_flags = 0;
- zrr.dr.d_content = std::make_shared<NSEC3PARAMRecordContent>(ns3pr);
+ zrr.dr.setContent(std::make_shared<NSEC3PARAMRecordContent>(ns3pr));
ns3pr.d_flags = flags;
DNSName keyname = DNSName(toBase32Hex(hashQNameWithSalt(ns3pr, zrr.dr.d_name)));
zrrs.push_back(zrr);
zrr.dr.d_name = target;
zrr.dr.d_ttl = 0;
zrr.dr.d_type = QType::NS;
- zrr.dr.d_content = std::make_shared<NSRecordContent>("invalid.");
+ zrr.dr.setContent(std::make_shared<NSRecordContent>("invalid."));
zrrs.emplace_back(zrr);
}
if(zrr.dr.d_name.isPartOf(target)) {
if (zrr.dr.d_type == QType::ALIAS && ::arg().mustDo("outgoing-axfr-expand-alias")) {
vector<DNSZoneRecord> ips;
- int ret1 = stubDoResolve(getRR<ALIASRecordContent>(zrr.dr)->d_content, QType::A, ips);
- int ret2 = stubDoResolve(getRR<ALIASRecordContent>(zrr.dr)->d_content, QType::AAAA, ips);
+ int ret1 = stubDoResolve(getRR<ALIASRecordContent>(zrr.dr)->getContent(), QType::A, ips);
+ int ret2 = stubDoResolve(getRR<ALIASRecordContent>(zrr.dr)->getContent(), QType::AAAA, ips);
if(ret1 != RCode::NoError || ret2 != RCode::NoError) {
- g_log<<Logger::Warning<<logPrefix<<"error resolving for ALIAS "<<zrr.dr.d_content->getZoneRepresentation()<<", aborting AXFR"<<endl;
+ g_log<<Logger::Warning<<logPrefix<<"error resolving for ALIAS "<<zrr.dr.getContent()->getZoneRepresentation()<<", aborting AXFR"<<endl;
outpacket->setRcode(RCode::ServFail);
sendPacket(outpacket,outsock);
return 0;
}
- for(const auto& ip: ips) {
+ for (auto& ip: ips) {
zrr.dr.d_type = ip.dr.d_type;
- zrr.dr.d_content = ip.dr.d_content;
+ zrr.dr.setContent(ip.dr.getContent());
zrrs.push_back(zrr);
}
continue;
}
}
- for (auto loopRR : zrrs) {
+ for (auto& loopRR : zrrs) {
if ((loopRR.dr.d_type == QType::SVCB || loopRR.dr.d_type == QType::HTTPS)) {
// Process auto hints
// TODO this is an almost copy of the code in the packethandler
if (rrc == nullptr) {
continue;
}
- DNSName svcTarget = rrc->getTarget().isRoot() ? loopRR.dr.d_name : rrc->getTarget();
- if (rrc->autoHint(SvcParam::ipv4hint)) {
+ auto newRRC = rrc->clone();
+ if (!newRRC) {
+ continue;
+ }
+ DNSName svcTarget = newRRC->getTarget().isRoot() ? loopRR.dr.d_name : newRRC->getTarget();
+ if (newRRC->autoHint(SvcParam::ipv4hint)) {
sd.db->lookup(QType::A, svcTarget, sd.domain_id);
vector<ComboAddress> hints;
DNSZoneRecord rr;
hints.push_back(arrc->getCA());
}
if (hints.size() == 0) {
- rrc->removeParam(SvcParam::ipv4hint);
+ newRRC->removeParam(SvcParam::ipv4hint);
} else {
- rrc->setHints(SvcParam::ipv4hint, hints);
+ newRRC->setHints(SvcParam::ipv4hint, hints);
}
}
- if (rrc->autoHint(SvcParam::ipv6hint)) {
+ if (newRRC->autoHint(SvcParam::ipv6hint)) {
sd.db->lookup(QType::AAAA, svcTarget, sd.domain_id);
vector<ComboAddress> hints;
DNSZoneRecord rr;
hints.push_back(arrc->getCA());
}
if (hints.size() == 0) {
- rrc->removeParam(SvcParam::ipv6hint);
+ newRRC->removeParam(SvcParam::ipv6hint);
} else {
- rrc->setHints(SvcParam::ipv6hint, hints);
+ newRRC->setHints(SvcParam::ipv6hint, hints);
}
}
+
+ loopRR.dr.setContent(std::move(newRRC));
}
}
unsigned int udiff;
DTime dt;
dt.set();
- int records=0;
for(DNSZoneRecord &loopZRR : zrrs) {
- records++;
if(securedZone && (loopZRR.auth || loopZRR.dr.d_type == QType::NS)) {
if (NSEC3Zone || loopZRR.dr.d_type) {
if (presignedZone && NSEC3Zone && loopZRR.dr.d_type == QType::RRSIG && getRR<RRSIGRecordContent>(loopZRR.dr)->d_type == QType::NSEC3) {
zrr.dr.d_name = iter->first+sd.qname;
zrr.dr.d_ttl = sd.getNegativeTTL();
- zrr.dr.d_content = std::make_shared<NSEC3RecordContent>(std::move(n3rc));
+ zrr.dr.setContent(std::make_shared<NSEC3RecordContent>(std::move(n3rc)));
zrr.dr.d_type = QType::NSEC3;
zrr.dr.d_place = DNSResourceRecord::ANSWER;
zrr.auth=true;
zrr.dr.d_name = iter->first;
zrr.dr.d_ttl = sd.getNegativeTTL();
- zrr.dr.d_content = std::make_shared<NSECRecordContent>(std::move(nrc));
+ zrr.dr.setContent(std::make_shared<NSECRecordContent>(std::move(nrc)));
zrr.dr.d_type = QType::NSEC;
zrr.dr.d_place = DNSResourceRecord::ANSWER;
zrr.auth=true;
const DNSRecord *rr = &answer.first;
if (rr->d_type == QType::SOA && rr->d_place == DNSResourceRecord::AUTHORITY) {
vector<string>parts;
- stringtok(parts, rr->d_content->getZoneRepresentation());
+ stringtok(parts, rr->getContent()->getZoneRepresentation());
if (parts.size() >= 3) {
try {
pdns::checked_stoi_into(serial, parts[2]);
rec.d_type = type;
rec.d_ttl = ttl;
- rec.d_content = getRecordContent(type, content);
+ rec.setContent(getRecordContent(type, content));
records.push_back(rec);
}
BOOST_CHECK_EQUAL(name2.getCommonLabels(name1), DNSName("powerdns.com"));
const DNSName name3("www.powerdns.org");
- BOOST_CHECK_EQUAL(name1.getCommonLabels(name3), DNSName());
- BOOST_CHECK_EQUAL(name2.getCommonLabels(name3), DNSName());
- BOOST_CHECK_EQUAL(name3.getCommonLabels(name1), DNSName());
- BOOST_CHECK_EQUAL(name3.getCommonLabels(name2), DNSName());
+ BOOST_CHECK_EQUAL(name1.getCommonLabels(name3), g_rootdnsname);
+ BOOST_CHECK_EQUAL(name2.getCommonLabels(name3), g_rootdnsname);
+ BOOST_CHECK_EQUAL(name3.getCommonLabels(name1), g_rootdnsname);
+ BOOST_CHECK_EQUAL(name3.getCommonLabels(name2), g_rootdnsname);
const DNSName name4("WWw.PowErDnS.org");
BOOST_CHECK_EQUAL(name3.getCommonLabels(name4), name3);
BOOST_CHECK_EQUAL(name4.getCommonLabels(name3), name4);
+
+ const DNSName(name5);
+ BOOST_CHECK_EQUAL(name1.getCommonLabels(name5), DNSName());
+ BOOST_CHECK_EQUAL(name5.getCommonLabels(name1), DNSName());
}
BOOST_AUTO_TEST_SUITE_END()
auto firstPacket = generatePacket(3600);
auto expectedAlteredPacket = generatePacket(1800);
- ageDNSPacket(reinterpret_cast<char*>(firstPacket.data()), firstPacket.size(), 1800);
+ dnsheader_aligned dh_aligned(firstPacket.data());
+ ageDNSPacket(reinterpret_cast<char*>(firstPacket.data()), firstPacket.size(), 1800, dh_aligned);
BOOST_REQUIRE_EQUAL(firstPacket.size(), expectedAlteredPacket.size());
for (size_t idx = 0; idx < firstPacket.size(); idx++) {
/* now call it with a truncated packet, missing the last TTL and rdata,
the packet should not be altered. */
- ageDNSPacket(reinterpret_cast<char*>(firstPacket.data()), firstPacket.size() - sizeof(uint32_t) - /* rdata length */ sizeof (uint16_t) - /* IPv4 payload in rdata */ 4 - /* size of OPT record */ 11, 900);
+ ageDNSPacket(reinterpret_cast<char*>(firstPacket.data()), firstPacket.size() - sizeof(uint32_t) - /* rdata length */ sizeof (uint16_t) - /* IPv4 payload in rdata */ 4 - /* size of OPT record */ 11, 900, dh_aligned);
BOOST_CHECK(firstPacket == expectedAlteredPacket);
/* now remove more than the remaining TTL. We expect ageDNSPacket
to cap this at zero and not cause an unsigned underflow into
the 2^32-1 neighbourhood */
- ageDNSPacket(reinterpret_cast<char*>(firstPacket.data()), firstPacket.size(), 1801);
+ ageDNSPacket(reinterpret_cast<char*>(firstPacket.data()), firstPacket.size(), 1801, dh_aligned);
uint32_t ttl = 0;
const auto& record = parser.d_answers.at(0).first;
BOOST_REQUIRE(record.d_type == QType::NSEC3);
BOOST_REQUIRE(record.d_class == QClass::IN);
- auto content = std::dynamic_pointer_cast<NSEC3RecordContent>(record.d_content);
+ auto content = getRR<NSEC3RecordContent>(record);
BOOST_REQUIRE(content);
BOOST_CHECK_EQUAL(content->numberOfTypesSet(), 0U);
for (size_t idx = 0; idx < 65536; idx++) {
ttd.tv_sec -= 5;
bool writeCBCalled = false;
- auto writeCB = [](int fd, FDMultiplexer::funcparam_t& param) {
+ auto writeCB = [](int /* fd */, FDMultiplexer::funcparam_t& param) {
auto calledPtr = boost::any_cast<bool*>(param);
BOOST_REQUIRE(calledPtr != nullptr);
*calledPtr = true;
BOOST_CHECK_EQUAL(ready, 0);
bool readCBCalled = false;
- auto readCB = [](int fd, FDMultiplexer::funcparam_t& param) {
+ auto readCB = [](int /* fd */, FDMultiplexer::funcparam_t& param) {
auto calledPtr = boost::any_cast<bool*>(param);
BOOST_REQUIRE(calledPtr != nullptr);
*calledPtr = true;
bool readCBCalled = false;
bool writeCBCalled = false;
- auto readCB = [](int fd, FDMultiplexer::funcparam_t& param) {
+ auto readCB = [](int /* fd */, FDMultiplexer::funcparam_t& param) {
auto calledPtr = boost::any_cast<bool*>(param);
BOOST_REQUIRE(calledPtr != nullptr);
*calledPtr = true;
};
- auto writeCB = [](int fd, FDMultiplexer::funcparam_t& param) {
+ auto writeCB = [](int /* fd */, FDMultiplexer::funcparam_t& param) {
auto calledPtr = boost::any_cast<bool*>(param);
BOOST_REQUIRE(calledPtr != nullptr);
*calledPtr = true;
BOOST_CHECK_EQUAL(answer.first.d_ttl, 0U);
BOOST_CHECK_EQUAL(tsigFound, false);
- shared_ptr<TSIGRecordContent> rectrc = getRR<TSIGRecordContent>(answer.first);
+ auto rectrc = getRR<TSIGRecordContent>(answer.first);
if (rectrc) {
trc = *rectrc;
theirMac = rectrc->d_mac;
return;
}
+ auto inception = time(nullptr);
// retain original name for response
tkey_out->d_error = 0;
tkey_out->d_mode = tkey_in.d_mode;
tkey_out->d_algo = tkey_in.d_algo;
- tkey_out->d_inception = time((time_t*)nullptr);
+ tkey_out->d_inception = inception;
tkey_out->d_expiration = tkey_out->d_inception+15;
if (tkey_in.d_mode == 3) { // establish context
zrr.dr.d_ttl = 0;
zrr.dr.d_type = QType::TKEY;
zrr.dr.d_class = QClass::ANY;
- zrr.dr.d_content = tkey_out;
+ zrr.dr.setContent(std::move(tkey_out));
zrr.dr.d_place = DNSResourceRecord::ANSWER;
r->addRecord(std::move(zrr));
{
TSIGRecordContent trc;
trc.d_algoName = DNSName("gss-tsig");
- trc.d_time = tkey_out->d_inception;
+ trc.d_time = inception;
trc.d_fudge = 300;
trc.d_mac = "";
trc.d_origID = p.d.id;
LINE1:alloutqueries#00ff00:"outqueries/s"
rrdtool graph $GRAPHOPTS --start -$1 $WWWPREFIX/qa-latency-$2.png -w $WSIZE -h $HSIZE -l 0 \
- -t "Questions/answer latency in milliseconds" \
- -v "msec" \
+ -t "Questions/answer latency in ms" \
+ -v "ms" \
DEF:qalatency=pdns_recursor.rrd:qa-latency:AVERAGE \
CDEF:mqalatency=qalatency,1000,/ \
LINE1:mqalatency#ff0000:"questions/s"
}
if(answer.first.d_type == QType::TSIG) {
- shared_ptr<TSIGRecordContent> trc = getRR<TSIGRecordContent>(answer.first);
+ auto trc = getRR<TSIGRecordContent>(answer.first);
if(trc) {
theirMac = trc->d_mac;
d_trc.d_time = trc->d_time;
DNSZoneRecord rr;
rr.dr.d_name = sd->qname;
rr.dr.d_type = QType::SOA;
- rr.dr.d_content = makeSOAContent(*sd);
+ rr.dr.setContent(makeSOAContent(*sd));
rr.dr.d_ttl = sd->ttl;
rr.domain_id = sd->domain_id;
DNSZoneRecord rr;
rr.dr.d_name = sd.qname;
rr.dr.d_type = QType::SOA;
- rr.dr.d_content = makeSOAContent(sd);
+ rr.dr.setContent(makeSOAContent(sd));
rr.dr.d_ttl = sd.ttl;
rr.domain_id = sd.domain_id;
-void Utility::setBindAny(int af, sock_t sock)
+void Utility::setBindAny([[maybe_unused]] int af, [[maybe_unused]] sock_t sock)
{
const int one = 1;
// Returns the current time.
-int Utility::gettimeofday( struct timeval *tv, void *tz )
+int Utility::gettimeofday( struct timeval *tv, void * /* tz */)
{
- return ::gettimeofday(tv,nullptr);
+ return ::gettimeofday(tv, nullptr);
}
// Sets the random seed.
return (key.d_flags & 128) != 0;
}
-static vector<shared_ptr<DNSKEYRecordContent > > getByTag(const skeyset_t& keys, uint16_t tag, uint8_t algorithm, const OptLog& log)
+static vector<shared_ptr<const DNSKEYRecordContent > > getByTag(const skeyset_t& keys, uint16_t tag, uint8_t algorithm, const OptLog& log)
{
- vector<shared_ptr<DNSKEYRecordContent>> ret;
+ vector<shared_ptr<const DNSKEYRecordContent>> ret;
for (const auto& key : keys) {
if (!isAZoneKey(*key)) {
using nsec3HashesCache = std::map<std::tuple<DNSName, std::string, uint16_t>, std::string>;
-static std::string getHashFromNSEC3(const DNSName& qname, const std::shared_ptr<NSEC3RecordContent>& nsec3, nsec3HashesCache& cache)
+static std::string getHashFromNSEC3(const DNSName& qname, const NSEC3RecordContent& nsec3, nsec3HashesCache& cache)
{
std::string result;
- if (g_maxNSEC3Iterations && nsec3->d_iterations > g_maxNSEC3Iterations) {
+ if (g_maxNSEC3Iterations && nsec3.d_iterations > g_maxNSEC3Iterations) {
return result;
}
- auto key = std::make_tuple(qname, nsec3->d_salt, nsec3->d_iterations);
+ auto key = std::make_tuple(qname, nsec3.d_salt, nsec3.d_iterations);
auto it = cache.find(key);
if (it != cache.end())
{
return it->second;
}
- result = hashQNameWithSalt(nsec3->d_salt, nsec3->d_iterations, qname);
+ result = hashQNameWithSalt(nsec3.d_salt, nsec3.d_iterations, qname);
cache[key] = result;
return result;
}
continue;
}
- const string h = getHashFromNSEC3(zone, nsec3, cache);
+ const string h = getHashFromNSEC3(zone, *nsec3, cache);
if (h.empty()) {
return false;
}
Labels field of the covering RRSIG RR, then the RRset and its
covering RRSIG RR were created as a result of wildcard expansion."
*/
-bool isWildcardExpanded(unsigned int labelCount, const std::shared_ptr<RRSIGRecordContent>& sign)
+bool isWildcardExpanded(unsigned int labelCount, const RRSIGRecordContent& sign)
{
- if (sign && sign->d_labels < labelCount) {
+ if (sign.d_labels < labelCount) {
return true;
}
return false;
}
-static bool isWildcardExpanded(const DNSName& owner, const std::vector<std::shared_ptr<RRSIGRecordContent> >& signatures)
+static bool isWildcardExpanded(const DNSName& owner, const std::vector<std::shared_ptr<const RRSIGRecordContent> >& signatures)
{
if (signatures.empty()) {
return false;
const auto& sign = signatures.at(0);
unsigned int labelsCount = owner.countLabels();
- return isWildcardExpanded(labelsCount, sign);
+ return isWildcardExpanded(labelsCount, *sign);
}
-bool isWildcardExpandedOntoItself(const DNSName& owner, unsigned int labelCount, const std::shared_ptr<RRSIGRecordContent>& sign)
+bool isWildcardExpandedOntoItself(const DNSName& owner, unsigned int labelCount, const RRSIGRecordContent& sign)
{
- if (owner.isWildcard() && (labelCount - 1) == sign->d_labels) {
+ if (owner.isWildcard() && (labelCount - 1) == sign.d_labels) {
/* this is a wildcard alright, but it has not been expanded */
return true;
}
return false;
}
-static bool isWildcardExpandedOntoItself(const DNSName& owner, const std::vector<std::shared_ptr<RRSIGRecordContent> >& signatures)
+static bool isWildcardExpandedOntoItself(const DNSName& owner, const std::vector<std::shared_ptr<const RRSIGRecordContent> >& signatures)
{
if (signatures.empty()) {
return false;
const auto& sign = signatures.at(0);
unsigned int labelsCount = owner.countLabels();
- return isWildcardExpandedOntoItself(owner, labelsCount, sign);
+ return isWildcardExpandedOntoItself(owner, labelsCount, *sign);
}
/* if this is a wildcard NSEC, the owner name has been modified
to match the name. Make sure we use the original '*' form. */
-DNSName getNSECOwnerName(const DNSName& initialOwner, const std::vector<std::shared_ptr<RRSIGRecordContent> >& signatures)
+DNSName getNSECOwnerName(const DNSName& initialOwner, const std::vector<std::shared_ptr<const RRSIGRecordContent> >& signatures)
{
DNSName result = initialOwner;
return result;
}
-static bool isNSECAncestorDelegation(const DNSName& signer, const DNSName& owner, const std::shared_ptr<NSECRecordContent>& nsec)
+static bool isNSECAncestorDelegation(const DNSName& signer, const DNSName& owner, const NSECRecordContent& nsec)
{
- return nsec->isSet(QType::NS) &&
- !nsec->isSet(QType::SOA) &&
+ return nsec.isSet(QType::NS) &&
+ !nsec.isSet(QType::SOA) &&
signer.countLabels() < owner.countLabels();
}
-bool isNSEC3AncestorDelegation(const DNSName& signer, const DNSName& owner, const std::shared_ptr<NSEC3RecordContent>& nsec3)
+bool isNSEC3AncestorDelegation(const DNSName& signer, const DNSName& owner, const NSEC3RecordContent& nsec3)
{
- return nsec3->isSet(QType::NS) &&
- !nsec3->isSet(QType::SOA) &&
+ return nsec3.isSet(QType::NS) &&
+ !nsec3.isSet(QType::SOA) &&
signer.countLabels() < owner.countLabels();
}
if (v.first.second == QType::NSEC) {
for (const auto& r : v.second.records) {
VLOG(log, ":\t"<<r->getZoneRepresentation()<<endl);
- auto nsec = std::dynamic_pointer_cast<NSECRecordContent>(r);
+ auto nsec = std::dynamic_pointer_cast<const NSECRecordContent>(r);
if (!nsec) {
continue;
}
}
VLOG(log, qname << ":\tWildcard matches");
- if (qtype == 0 || isTypeDenied(nsec, QType(qtype))) {
+ if (qtype == 0 || isTypeDenied(*nsec, QType(qtype))) {
VLOG_NO_PREFIX(log, " and proves that the type did not exist"<<endl);
return true;
}
if (v.first.second == QType::NSEC) {
for (const auto& r : v.second.records) {
VLOG(log, qname << ":\t"<<r->getZoneRepresentation()<<endl);
- auto nsec = std::dynamic_pointer_cast<NSECRecordContent>(r);
+ auto nsec = std::dynamic_pointer_cast<const NSECRecordContent>(r);
if (!nsec) {
continue;
}
if (v.first.second == QType::NSEC3) {
for (const auto& r : v.second.records) {
VLOG(log, closestEncloser << ":\t"<<r->getZoneRepresentation()<<endl);
- auto nsec3 = std::dynamic_pointer_cast<NSEC3RecordContent>(r);
+ auto nsec3 = std::dynamic_pointer_cast<const NSEC3RecordContent>(r);
if (!nsec3) {
continue;
}
continue;
}
- string h = getHashFromNSEC3(wildcard, nsec3, cache);
+ string h = getHashFromNSEC3(wildcard, *nsec3, cache);
if (h.empty()) {
return false;
}
that (original) owner name other than DS RRs, and all RRs below that
owner name regardless of type.
*/
- if (qtype != QType::DS && isNSEC3AncestorDelegation(signer, v.first.first, nsec3)) {
+ if (qtype != QType::DS && isNSEC3AncestorDelegation(signer, v.first.first, *nsec3)) {
/* this is an "ancestor delegation" NSEC3 RR */
VLOG_NO_PREFIX(log, " BUT an ancestor delegation NSEC3 RR can only deny the existence of a DS"<<endl);
return false;
}
- if (qtype == 0 || isTypeDenied(nsec3, QType(qtype))) {
+ if (qtype == 0 || isTypeDenied(*nsec3, QType(qtype))) {
VLOG_NO_PREFIX(log, " and proves that the type did not exist"<<endl);
return true;
}
return false;
}
-dState matchesNSEC(const DNSName& name, uint16_t qtype, const DNSName& nsecOwner, const std::shared_ptr<NSECRecordContent>& nsec, const std::vector<std::shared_ptr<RRSIGRecordContent>>& signatures, const OptLog& log)
+dState matchesNSEC(const DNSName& name, uint16_t qtype, const DNSName& nsecOwner, const NSECRecordContent& nsec, const std::vector<std::shared_ptr<const RRSIGRecordContent>>& signatures, const OptLog& log)
{
const DNSName signer = getSigner(signatures);
if (!name.isPartOf(signer) || !nsecOwner.isPartOf(signer)) {
return dState::NXQTYPE;
}
- if (name.isPartOf(owner) && nsec->isSet(QType::DNAME)) {
+ if (name.isPartOf(owner) && nsec.isSet(QType::DNAME)) {
/* rfc6672 section 5.3.2: DNAME Bit in NSEC Type Map
In any negative response, the NSEC or NSEC3 [RFC5155] record type
return dState::NODENIAL;
}
- if (isCoveredByNSEC(name, owner, nsec->d_next)) {
- VLOG_NO_PREFIX(log, name << ": is covered by ("<<owner<<" to "<<nsec->d_next<<")");
+ if (isCoveredByNSEC(name, owner, nsec.d_next)) {
+ VLOG_NO_PREFIX(log, name << ": is covered by ("<<owner<<" to "<<nsec.d_next<<")");
- if (nsecProvesENT(name, owner, nsec->d_next)) {
+ if (nsecProvesENT(name, owner, nsec.d_next)) {
VLOG_NO_PREFIX(log, " denies existence of type "<<name<<"/"<<QType(qtype)<<" by proving that "<<name<<" is an ENT"<<endl);
return dState::NXQTYPE;
}
continue;
}
- auto nsec = std::dynamic_pointer_cast<NSECRecordContent>(r);
+ auto nsec = std::dynamic_pointer_cast<const NSECRecordContent>(r);
if (!nsec) {
continue;
}
that (original) owner name other than DS RRs, and all RRs below that
owner name regardless of type.
*/
- if (qname.isPartOf(owner) && isNSECAncestorDelegation(signer, owner, nsec)) {
+ if (qname.isPartOf(owner) && isNSECAncestorDelegation(signer, owner, *nsec)) {
/* this is an "ancestor delegation" NSEC RR */
if (!(qtype == QType::DS && qname == owner)) {
VLOG(log, qname << ": An ancestor delegation NSEC RR can only deny the existence of a DS"<<endl);
/* check if the type is denied */
if (qname == owner) {
- if (!isTypeDenied(nsec, QType(qtype))) {
+ if (!isTypeDenied(*nsec, QType(qtype))) {
VLOG(log, qname << ": Does _not_ deny existence of type "<<QType(qtype)<<endl);
return dState::NODENIAL;
}
} else if(v.first.second==QType::NSEC3) {
for (const auto& r : v.second.records) {
VLOG(log, qname << ":\t"<<r->getZoneRepresentation()<<endl);
- auto nsec3 = std::dynamic_pointer_cast<NSEC3RecordContent>(r);
+ auto nsec3 = std::dynamic_pointer_cast<const NSEC3RecordContent>(r);
if (!nsec3) {
continue;
}
continue;
}
- string h = getHashFromNSEC3(qname, nsec3, cache);
+ string h = getHashFromNSEC3(qname, *nsec3, cache);
if (h.empty()) {
VLOG(log, qname << ": Unsupported hash, ignoring"<<endl);
return dState::INSECURE;
that (original) owner name other than DS RRs, and all RRs below that
owner name regardless of type.
*/
- if (qtype != QType::DS && isNSEC3AncestorDelegation(signer, qname, nsec3)) {
+ if (qtype != QType::DS && isNSEC3AncestorDelegation(signer, qname, *nsec3)) {
/* this is an "ancestor delegation" NSEC3 RR */
VLOG(log, qname << ": An ancestor delegation NSEC3 RR can only deny the existence of a DS"<<endl);
return dState::NODENIAL;
}
- if (!isTypeDenied(nsec3, QType(qtype))) {
+ if (!isTypeDenied(*nsec3, QType(qtype))) {
VLOG(log, qname << ": Does _not_ deny existence of type "<<QType(qtype)<<" for name "<<qname<<" (not opt-out)."<<endl);
return dState::NODENIAL;
}
if(v.first.second==QType::NSEC3) {
for(const auto& r : v.second.records) {
VLOG(log, qname << ":\t"<<r->getZoneRepresentation()<<endl);
- auto nsec3 = std::dynamic_pointer_cast<NSEC3RecordContent>(r);
+ auto nsec3 = std::dynamic_pointer_cast<const NSEC3RecordContent>(r);
if (!nsec3) {
continue;
}
continue;
}
- string h = getHashFromNSEC3(closestEncloser, nsec3, cache);
+ string h = getHashFromNSEC3(closestEncloser, *nsec3, cache);
if (h.empty()) {
return dState::INSECURE;
}
VLOG(log, qname << ": Comparing "<<toBase32Hex(h)<<" ("<<closestEncloser<<") against "<<toBase32Hex(beginHash)<<endl);
if (beginHash == h) {
/* If the closest encloser is a delegation NS we know nothing about the names in the child zone. */
- if (isNSEC3AncestorDelegation(signer, v.first.first, nsec3)) {
+ if (isNSEC3AncestorDelegation(signer, v.first.first, *nsec3)) {
VLOG(log, qname << ": An ancestor delegation NSEC3 RR can only deny the existence of a DS"<<endl);
continue;
}
if(v.first.second==QType::NSEC3) {
for(const auto& r : v.second.records) {
VLOG(log, qname << ":\t"<<r->getZoneRepresentation()<<endl);
- auto nsec3 = std::dynamic_pointer_cast<NSEC3RecordContent>(r);
+ auto nsec3 = std::dynamic_pointer_cast<const NSEC3RecordContent>(r);
if(!nsec3)
continue;
- string h = getHashFromNSEC3(nextCloser, nsec3, cache);
+ string h = getHashFromNSEC3(nextCloser, *nsec3, cache);
if (h.empty()) {
return dState::INSECURE;
}
return dState::NODENIAL;
}
-bool isRRSIGNotExpired(const time_t now, const shared_ptr<RRSIGRecordContent>& sig)
+bool isRRSIGNotExpired(const time_t now, const RRSIGRecordContent& sig)
{
// Should use https://www.rfc-editor.org/rfc/rfc4034.txt section 3.1.5
- return sig->d_sigexpire >= now;
+ return sig.d_sigexpire >= now;
}
-bool isRRSIGIncepted(const time_t now, const shared_ptr<RRSIGRecordContent>& sig)
+bool isRRSIGIncepted(const time_t now, const RRSIGRecordContent& sig)
{
// Should use https://www.rfc-editor.org/rfc/rfc4034.txt section 3.1.5
- return sig->d_siginception - g_signatureInceptionSkew <= now;
+ return sig.d_siginception - g_signatureInceptionSkew <= now;
}
-static bool checkSignatureWithKey(const DNSName& qname, time_t now, const shared_ptr<RRSIGRecordContent> sig, const shared_ptr<DNSKEYRecordContent> key, const std::string& msg, vState& ede, const OptLog& log)
+static bool checkSignatureWithKey(const DNSName& qname, time_t now, const RRSIGRecordContent& sig, const DNSKEYRecordContent& key, const std::string& msg, vState& ede, const OptLog& log)
{
bool result = false;
try {
- The validator's notion of the current time MUST be greater than or equal to the time listed in the RRSIG RR's Inception field.
*/
if (isRRSIGIncepted(now, sig) && isRRSIGNotExpired(now, sig)) {
- auto dke = DNSCryptoKeyEngine::makeFromPublicKeyString(key->d_algorithm, key->d_key);
- result = dke->verify(msg, sig->d_signature);
- VLOG(log, qname << ": Signature by key with tag "<<sig->d_tag<<" and algorithm "<<DNSSECKeeper::algorithm2name(sig->d_algorithm)<<" was " << (result ? "" : "NOT ")<<"valid"<<endl);
+ auto dke = DNSCryptoKeyEngine::makeFromPublicKeyString(key.d_algorithm, key.d_key);
+ result = dke->verify(msg, sig.d_signature);
+ VLOG(log, qname << ": Signature by key with tag "<<sig.d_tag<<" and algorithm "<<DNSSECKeeper::algorithm2name(sig.d_algorithm)<<" was " << (result ? "" : "NOT ")<<"valid"<<endl);
if (!result) {
ede = vState::BogusNoValidRRSIG;
}
}
else {
- ede = ((sig->d_siginception - g_signatureInceptionSkew) > now) ? vState::BogusSignatureNotYetValid : vState::BogusSignatureExpired;
- VLOG(log, qname << ": Signature is "<<(ede == vState::BogusSignatureNotYetValid ? "not yet valid" : "expired")<<" (inception: "<<sig->d_siginception<<", inception skew: "<<g_signatureInceptionSkew<<", expiration: "<<sig->d_sigexpire<<", now: "<<now<<")"<<endl);
+ ede = ((sig.d_siginception - g_signatureInceptionSkew) > now) ? vState::BogusSignatureNotYetValid : vState::BogusSignatureExpired;
+ VLOG(log, qname << ": Signature is "<<(ede == vState::BogusSignatureNotYetValid ? "not yet valid" : "expired")<<" (inception: "<<sig.d_siginception<<", inception skew: "<<g_signatureInceptionSkew<<", expiration: "<<sig.d_sigexpire<<", now: "<<now<<")"<<endl);
}
}
catch (const std::exception& e) {
return result;
}
-vState validateWithKeySet(time_t now, const DNSName& name, const sortedRecords_t& toSign, const vector<shared_ptr<RRSIGRecordContent> >& signatures, const skeyset_t& keys, const OptLog& log, bool validateAllSigs)
+vState validateWithKeySet(time_t now, const DNSName& name, const sortedRecords_t& toSign, const vector<shared_ptr<const RRSIGRecordContent> >& signatures, const skeyset_t& keys, const OptLog& log, bool validateAllSigs)
{
bool foundKey = false;
bool isValid = false;
string msg = getMessageForRRSET(name, *signature, toSign, true);
for (const auto& key : keysMatchingTag) {
vState ede;
- bool signIsValid = checkSignatureWithKey(name, now, signature, key, msg, ede, log);
+ bool signIsValid = checkSignatureWithKey(name, now, *signature, *key, msg, ede, log);
foundKey = true;
if (signIsValid) {
}
else {
VLOG(log, name << ": signature invalid"<<endl);
- if (isRRSIGIncepted(now, signature)) {
+ if (isRRSIGIncepted(now, *signature)) {
noneIncepted = false;
}
- if (isRRSIGNotExpired(now, signature)) {
+ if (isRRSIGNotExpired(now, *signature)) {
allExpired = false;
}
}
}
}
else {
- cspmap[{rec.d_name, rec.d_type}].records.insert(rec.d_content);
+ cspmap[{rec.d_name, rec.d_type}].records.insert(rec.getContent());
}
}
return cspmap;
return true;
}
-vState validateDNSKeysAgainstDS(time_t now, const DNSName& zone, const dsmap_t& dsmap, const skeyset_t& tkeys, const sortedRecords_t& toSign, const vector<shared_ptr<RRSIGRecordContent> >& sigs, skeyset_t& validkeys, const OptLog& log)
+vState validateDNSKeysAgainstDS(time_t now, const DNSName& zone, const dsmap_t& dsmap, const skeyset_t& tkeys, const sortedRecords_t& toSign, const vector<shared_ptr<const RRSIGRecordContent> >& sigs, skeyset_t& validkeys, const OptLog& log)
{
/*
* Check all DNSKEY records against all DS records and place all DNSKEY records
string msg = getMessageForRRSET(zone, *sig, toSign);
for (const auto& key : bytag) {
// cerr<<"validating : ";
- bool signIsValid = checkSignatureWithKey(zone, now, sig, key, msg, ede, log);
+ bool signIsValid = checkSignatureWithKey(zone, now, *sig, *key, msg, ede, log);
- if (signIsValid)
- {
+ if (signIsValid) {
VLOG(log, zone << ": Validation succeeded - whole DNSKEY set is valid"<<endl);
validkeys = tkeys;
break;
return true;
}
-DNSName getSigner(const std::vector<std::shared_ptr<RRSIGRecordContent> >& signatures)
+DNSName getSigner(const std::vector<std::shared_ptr<const RRSIGRecordContent> >& signatures)
{
for (const auto& sig : signatures) {
if (sig) {
struct ContentSigPair
{
sortedRecords_t records;
- vector<shared_ptr<RRSIGRecordContent>> signatures;
+ vector<shared_ptr<const RRSIGRecordContent>> signatures;
// ponder adding a validate method that accepts a key
};
typedef map<pair<DNSName,uint16_t>, ContentSigPair> cspmap_t;
struct sharedDNSKeyRecordContentCompare
{
- bool operator() (const shared_ptr<DNSKEYRecordContent>& a, const shared_ptr<DNSKEYRecordContent>& b) const
+ bool operator() (const shared_ptr<const DNSKEYRecordContent>& a, const shared_ptr<const DNSKEYRecordContent>& b) const
{
return *a < *b;
}
};
-typedef set<shared_ptr<DNSKEYRecordContent>, sharedDNSKeyRecordContentCompare > skeyset_t;
+typedef set<shared_ptr<const DNSKEYRecordContent>, sharedDNSKeyRecordContentCompare > skeyset_t;
-vState validateWithKeySet(time_t now, const DNSName& name, const sortedRecords_t& records, const vector<shared_ptr<RRSIGRecordContent> >& signatures, const skeyset_t& keys, const OptLog& log, bool validateAllSigs=true);
+vState validateWithKeySet(time_t now, const DNSName& name, const sortedRecords_t& records, const vector<shared_ptr<const RRSIGRecordContent> >& signatures, const skeyset_t& keys, const OptLog& log, bool validateAllSigs=true);
bool isCoveredByNSEC(const DNSName& name, const DNSName& begin, const DNSName& next);
bool isCoveredByNSEC3Hash(const std::string& h, const std::string& beginHash, const std::string& nextHash);
bool isCoveredByNSEC3Hash(const DNSName& h, const DNSName& beginHash, const DNSName& nextHash);
cspmap_t harvestCSPFromRecs(const vector<DNSRecord>& recs);
bool getTrustAnchor(const map<DNSName,dsmap_t>& anchors, const DNSName& zone, dsmap_t &res);
bool haveNegativeTrustAnchor(const map<DNSName,std::string>& negAnchors, const DNSName& zone, std::string& reason);
-vState validateDNSKeysAgainstDS(time_t now, const DNSName& zone, const dsmap_t& dsmap, const skeyset_t& tkeys, const sortedRecords_t& toSign, const vector<shared_ptr<RRSIGRecordContent> >& sigs, skeyset_t& validkeys, const OptLog&);
+vState validateDNSKeysAgainstDS(time_t now, const DNSName& zone, const dsmap_t& dsmap, const skeyset_t& tkeys, const sortedRecords_t& toSign, const vector<shared_ptr<const RRSIGRecordContent> >& sigs, skeyset_t& validkeys, const OptLog&);
dState getDenial(const cspmap_t &validrrsets, const DNSName& qname, const uint16_t qtype, bool referralToUnsigned, bool wantsNoDataProof, const OptLog& log = std::nullopt, bool needsWildcardProof=true, unsigned int wildcardLabelsCount=0);
bool isSupportedDS(const DSRecordContent& ds, const OptLog&);
-DNSName getSigner(const std::vector<std::shared_ptr<RRSIGRecordContent> >& signatures);
+DNSName getSigner(const std::vector<std::shared_ptr<const RRSIGRecordContent> >& signatures);
bool denialProvesNoDelegation(const DNSName& zone, const std::vector<DNSRecord>& dsrecords);
-bool isRRSIGNotExpired(const time_t now, const std::shared_ptr<RRSIGRecordContent>& sig);
-bool isRRSIGIncepted(const time_t now, const shared_ptr<RRSIGRecordContent>& sig);
-bool isWildcardExpanded(unsigned int labelCount, const std::shared_ptr<RRSIGRecordContent>& sign);
-bool isWildcardExpandedOntoItself(const DNSName& owner, unsigned int labelCount, const std::shared_ptr<RRSIGRecordContent>& sign);
+bool isRRSIGNotExpired(const time_t now, const RRSIGRecordContent& sig);
+bool isRRSIGIncepted(const time_t now, const RRSIGRecordContent& sig);
+bool isWildcardExpanded(unsigned int labelCount, const RRSIGRecordContent& sign);
+bool isWildcardExpandedOntoItself(const DNSName& owner, unsigned int labelCount, const RRSIGRecordContent& sign);
void updateDNSSECValidationState(vState& state, const vState stateUpdate);
-dState matchesNSEC(const DNSName& name, uint16_t qtype, const DNSName& nsecOwner, const std::shared_ptr<NSECRecordContent>& nsec, const std::vector<std::shared_ptr<RRSIGRecordContent>>& signatures, const OptLog&);
+dState matchesNSEC(const DNSName& name, uint16_t qtype, const DNSName& nsecOwner, const NSECRecordContent& nsec, const std::vector<std::shared_ptr<const RRSIGRecordContent>>& signatures, const OptLog&);
-bool isNSEC3AncestorDelegation(const DNSName& signer, const DNSName& owner, const std::shared_ptr<NSEC3RecordContent>& nsec3);
-DNSName getNSECOwnerName(const DNSName& initialOwner, const std::vector<std::shared_ptr<RRSIGRecordContent> >& signatures);
+bool isNSEC3AncestorDelegation(const DNSName& signer, const DNSName& owner, const NSEC3RecordContent& nsec3);
+DNSName getNSECOwnerName(const DNSName& initialOwner, const std::vector<std::shared_ptr<const RRSIGRecordContent> >& signatures);
DNSName getClosestEncloserFromNSEC(const DNSName& name, const DNSName& owner, const DNSName& next);
template <typename NSEC> bool isTypeDenied(const NSEC& nsec, const QType& type)
{
- if (nsec->isSet(type.getCode())) {
+ if (nsec.isSet(type.getCode())) {
return false;
}
/* RFC 6840 section 4.3 */
- if (nsec->isSet(QType::CNAME)) {
+ if (nsec.isSet(QType::CNAME)) {
return false;
}
}
DNSRecord rec;
rec.d_name = dnsResourceRecord.qname;
- rec.d_content = drc;
+ rec.setContent(std::move(drc));
rec.d_type = dnsResourceRecord.qtype;
rec.d_class = dnsResourceRecord.qclass;
rec.d_ttl = dnsResourceRecord.ttl;
if (record.d_class == QClass::IN && record.d_name == d_zone) {
switch (record.d_type) {
case QType::SOA: {
- d_soaRecordContent = std::dynamic_pointer_cast<SOARecordContent>(record.d_content);
+ d_soaRecordContent = getRR<SOARecordContent>(record);
if (d_soaRecordContent == nullptr) {
throw PDNSException("Invalid SOA record");
}
break;
}
case QType::DNSKEY: {
- auto dnskey = std::dynamic_pointer_cast<DNSKEYRecordContent>(record.d_content);
+ auto dnskey = getRR<DNSKEYRecordContent>(record);
if (dnskey == nullptr) {
throw PDNSException("Invalid DNSKEY record");
}
break;
}
case QType::ZONEMD: {
- auto zonemd = std::dynamic_pointer_cast<ZONEMDRecordContent>(record.d_content);
+ auto zonemd = getRR<ZONEMDRecordContent>(record);
if (zonemd == nullptr) {
throw PDNSException("Invalid ZONEMD record");
}
break;
}
case QType::RRSIG: {
- auto rrsig = std::dynamic_pointer_cast<RRSIGRecordContent>(record.d_content);
+ auto rrsig = getRR<RRSIGRecordContent>(record);
if (rrsig == nullptr) {
throw PDNSException("Invalid RRSIG record");
}
break;
}
case QType::NSEC: {
- auto nsec = std::dynamic_pointer_cast<NSECRecordContent>(record.d_content);
+ auto nsec = getRR<NSECRecordContent>(record);
if (nsec == nullptr) {
throw PDNSException("Invalid NSEC record");
}
// Handled below
break;
case QType::NSEC3PARAM: {
- auto param = std::dynamic_pointer_cast<NSEC3PARAMRecordContent>(record.d_content);
+ auto param = getRR<NSEC3PARAMRecordContent>(record);
if (param == nullptr) {
throw PDNSException("Invalid NSEC3PARAM record");
}
if (record.d_class == QClass::IN && (d_nsec3label.empty() || record.d_name == d_nsec3label)) {
switch (record.d_type) {
case QType::NSEC3: {
- auto nsec3 = std::dynamic_pointer_cast<NSEC3RecordContent>(record.d_content);
+ auto nsec3 = getRR<NSEC3RecordContent>(record);
if (nsec3 == nullptr) {
throw PDNSException("Invalid NSEC3 record");
}
break;
}
case QType::RRSIG: {
- auto rrsig = std::dynamic_pointer_cast<RRSIGRecordContent>(record.d_content);
+ auto rrsig = getRR<RRSIGRecordContent>(record);
if (rrsig == nullptr) {
throw PDNSException("Invalid RRSIG record");
}
}
}
RRSetKey_t key = std::pair(record.d_name, record.d_type);
- d_resourceRecordSets[key].push_back(record.d_content);
+ d_resourceRecordSets[key].push_back(record.getContent());
d_resourceRecordSetTTLs[key] = record.d_ttl;
}
sortedRecords_t sorted;
for (auto& rr : rrset.second) {
if (qtype == QType::RRSIG) {
- const auto rrsig = std::dynamic_pointer_cast<RRSIGRecordContent>(rr);
+ const auto rrsig = std::dynamic_pointer_cast<const RRSIGRecordContent>(rr);
if (rrsig->d_type == QType::ZONEMD && qname == d_zone) {
continue;
}
// RRSIG is special, since original TTL depends on qtype covered by RRSIG
// which can be different per record
for (const auto& rrsig : sorted) {
- auto rrsigc = std::dynamic_pointer_cast<RRSIGRecordContent>(rrsig);
+ auto rrsigc = std::dynamic_pointer_cast<const RRSIGRecordContent>(rrsig);
RRSIGRecordContent rrc;
rrc.d_originalttl = d_resourceRecordSetTTLs[pair(rrset.first.first, rrsigc->d_type)];
rrc.d_type = qtype;
void verify(bool& validationDone, bool& validationOK);
// Return the zone's apex DNSKEYs
- const std::set<shared_ptr<DNSKEYRecordContent>>& getDNSKEYs() const
+ const std::set<shared_ptr<const DNSKEYRecordContent>>& getDNSKEYs() const
{
return d_dnskeys;
}
// Return the zone's apex RRSIGs
- const std::vector<shared_ptr<RRSIGRecordContent>>& getRRSIGs() const
+ const std::vector<shared_ptr<const RRSIGRecordContent>>& getRRSIGs() const
{
return d_rrsigs;
}
// Return the zone's apex ZONEMDs
- std::vector<shared_ptr<ZONEMDRecordContent>> getZONEMDs() const
+ std::vector<shared_ptr<const ZONEMDRecordContent>> getZONEMDs() const
{
- std::vector<shared_ptr<ZONEMDRecordContent>> ret;
+ std::vector<shared_ptr<const ZONEMDRecordContent>> ret;
for (const auto& zonemd : d_zonemdRecords) {
ret.emplace_back(zonemd.second.record);
}
return d_nsec3label;
}
- const std::vector<shared_ptr<NSEC3PARAMRecordContent>>& getNSEC3Params() const
+ const std::vector<shared_ptr<const NSEC3PARAMRecordContent>>& getNSEC3Params() const
{
return d_nsec3params;
}
private:
- typedef std::pair<DNSName, QType> RRSetKey_t;
- typedef std::vector<std::shared_ptr<DNSRecordContent>> RRVector_t;
+ using RRSetKey_t = std::pair<DNSName, QType>;
+ using RRVector_t = std::vector<std::shared_ptr<const DNSRecordContent>>;
struct CanonRRSetKeyCompare
{
}
};
- typedef std::map<RRSetKey_t, RRVector_t, CanonRRSetKeyCompare> RRSetMap_t;
+ using RRSetMap_t = std::map<RRSetKey_t, RRVector_t, CanonRRSetKeyCompare>;
struct ZoneMDAndDuplicateFlag
{
- std::shared_ptr<ZONEMDRecordContent> record;
+ const std::shared_ptr<const ZONEMDRecordContent> record;
bool duplicate;
};
RRSetMap_t d_resourceRecordSets;
std::map<RRSetKey_t, uint32_t> d_resourceRecordSetTTLs;
- std::shared_ptr<SOARecordContent> d_soaRecordContent;
- std::set<shared_ptr<DNSKEYRecordContent>> d_dnskeys;
- std::vector<shared_ptr<RRSIGRecordContent>> d_rrsigs;
- std::vector<shared_ptr<NSEC3PARAMRecordContent>> d_nsec3params;
+ std::shared_ptr<const SOARecordContent> d_soaRecordContent;
+ std::set<shared_ptr<const DNSKEYRecordContent>> d_dnskeys;
+ std::vector<shared_ptr<const RRSIGRecordContent>> d_rrsigs;
+ std::vector<shared_ptr<const NSEC3PARAMRecordContent>> d_nsec3params;
ContentSigPair d_nsecs;
map<DNSName, ContentSigPair> d_nsec3s;
DNSName d_nsec3label;
# Now run pdns and the tests.
print("Launching server...")
print(format_call_args(servercmd))
-serverproc = subprocess.Popen(servercmd, close_fds=True, text=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+server_stdout = tempfile.TemporaryFile()
+server_stderr = tempfile.TemporaryFile()
+serverproc = subprocess.Popen(servercmd, close_fds=True, text=True, stdout=server_stdout, stderr=server_stderr)
+
+def finalize_server():
+ serverproc.terminate()
+ serverproc.wait()
+
+ print("==STDOUT==")
+ server_stdout.seek(0, 0)
+ sys.stdout.flush()
+ sys.stdout.buffer.write(server_stdout.read())
+ server_stdout.close()
+
+ print("==STDERR==")
+ server_stderr.seek(0, 0)
+ sys.stdout.flush()
+ sys.stdout.buffer.write(server_stderr.read())
+ server_stderr.close()
+
print("Waiting for webserver port to become available...")
available = False
if not available:
print("Webserver port not reachable after 10 tries, giving up.")
- serverproc.terminate()
- serverproc.wait()
- print("==STDOUT===")
- print(serverproc.stdout.read())
- print("==STDERRR===")
- print(serverproc.stderr.read())
+ finalize_server()
sys.exit(2)
print("Query for example.com/A to create statistic data...")
if wait:
print("Waiting as requested, press ENTER to stop.")
raw_input()
- serverproc.terminate()
- serverproc.wait()
- print("==STDOUT===")
- print(serverproc.stdout.read())
- print("==STDERRR===")
- print(serverproc.stderr.read())
+ finalize_server()
sys.exit(returncode)
all.ifportup 3600 IN LUA A "ifportup(8080, {{'{prefix}.101', '{prefix}.102'}})"
some.ifportup 3600 IN LUA A "ifportup(8080, {{'192.168.42.21', '{prefix}.102'}})"
+multi.ifportup 3600 IN LUA A "ifportup(8080, {{ {{'192.168.42.23'}}, {{'192.168.42.21', '{prefix}.102'}}, {{'{prefix}.101'}} }})"
none.ifportup 3600 IN LUA A "ifportup(8080, {{'192.168.42.21', '192.168.21.42'}})"
all.noneup.ifportup 3600 IN LUA A "ifportup(8080, {{'192.168.42.21', '192.168.21.42'}}, {{ backupSelector='all' }})"
config IN LUA LUA ("settings={{stringmatch='Programming in Lua'}} "
"EUWips={{'{prefix}.101','{prefix}.102'}} "
"EUEips={{'192.168.42.101','192.168.42.102'}} "
- "NLips={{'{prefix}.111', '{prefix}.112'}} "
- "USAips={{'{prefix}.103'}} ")
+ "NLips={{'{prefix}.111', '{prefix}.112'}} "
+ "USAips={{'{prefix}.103', '192.168.42.105'}} ")
usa IN LUA A ( ";include('config') "
"return ifurlup('http://www.lua.org:8080/', "
- "{{USAips, EUEips}}, settings) ")
+ "USAips, settings) ")
+
+usa-ext IN LUA A ( ";include('config') "
+ "return ifurlup('http://www.lua.org:8080/', "
+ "{{EUEips, USAips}}, settings) ")
mix.ifurlup IN LUA A ("ifurlup('http://www.other.org:8080/ping.json', "
"{{ '192.168.42.101', '{prefix}.101' }}, "
"{{ stringmatch='pong' }}) ")
-eu-west IN LUA A ( ";include('config') "
- "return ifurlup('http://www.lua.org:8080/', "
- "{{EUWips, EUEips, USAips}}, settings) ")
-
ifurlextup IN LUA A "ifurlextup({{{{['192.168.0.1']='http://{prefix}.101:8080/404',['192.168.0.2']='http://{prefix}.102:8080/404'}}, {{['192.168.0.3']='http://{prefix}.101:8080/'}}}})"
nl IN LUA A ( ";include('config') "
self.assertRcodeEqual(res, dns.rcode.NOERROR)
self.assertAnyRRsetInAnswer(res, expected)
+ def testIfportupWithSomeDownMultiset(self):
+ """
+ Basic ifportup() test with some ports DOWN from multiple sets
+ """
+ query = dns.message.make_query('multi.ifportup.example.org', 'A')
+ expected = [
+ dns.rrset.from_text('multi.ifportup.example.org.', 0, dns.rdataclass.IN, 'A',
+ '192.168.42.21'),
+ dns.rrset.from_text('multi.ifportup.example.org.', 0, dns.rdataclass.IN, 'A',
+ '192.168.42.23'),
+ dns.rrset.from_text('multi.ifportup.example.org.', 0, dns.rdataclass.IN, 'A',
+ '{prefix}.102'.format(prefix=self._PREFIX)),
+ dns.rrset.from_text('multi.ifportup.example.org.', 0, dns.rdataclass.IN, 'A',
+ '{prefix}.101'.format(prefix=self._PREFIX))
+ ]
+
+ # we first expect any of the IPs as no check has been performed yet
+ res = self.sendUDPQuery(query)
+ self.assertRcodeEqual(res, dns.rcode.NOERROR)
+ self.assertAnyRRsetInAnswer(res, expected)
+
+ # An ip is up in 2 sets, but we expect only the one from the middle set
+ expected = [expected[2]]
+ res = self.sendUDPQuery(query)
+ self.assertRcodeEqual(res, dns.rcode.NOERROR)
+ self.assertAnyRRsetInAnswer(res, expected)
+
def testIfportupWithAllDown(self):
"""
Basic ifportup() test with all ports DOWN
reachable = [
'{prefix}.103'.format(prefix=self._PREFIX)
]
- unreachable = ['192.168.42.101', '192.168.42.102']
+ unreachable = ['192.168.42.105']
ips = reachable + unreachable
all_rrs = []
reachable_rrs = []
self.assertRcodeEqual(res, dns.rcode.NOERROR)
self.assertAnyRRsetInAnswer(res, reachable_rrs)
+ def testIfurlupMultiSet(self):
+ """
+ Basic ifurlup() test with mutiple sets
+ """
+ reachable = [
+ '{prefix}.103'.format(prefix=self._PREFIX)
+ ]
+ unreachable = ['192.168.42.101', '192.168.42.102', '192.168.42.105']
+ ips = reachable + unreachable
+ all_rrs = []
+ reachable_rrs = []
+ for ip in ips:
+ rr = dns.rrset.from_text('usa-ext.example.org.', 0, dns.rdataclass.IN, 'A', ip)
+ all_rrs.append(rr)
+ if ip in reachable:
+ reachable_rrs.append(rr)
+
+ query = dns.message.make_query('usa-ext.example.org', 'A')
+ res = self.sendUDPQuery(query)
+ self.assertRcodeEqual(res, dns.rcode.NOERROR)
+ self.assertAnyRRsetInAnswer(res, all_rrs)
+
+ # the timeout in the LUA health checker is 2 second, so we make sure to wait slightly longer here
+ time.sleep(3)
+ res = self.sendUDPQuery(query)
+ self.assertRcodeEqual(res, dns.rcode.NOERROR)
+ self.assertAnyRRsetInAnswer(res, reachable_rrs)
+
def testIfurlextup(self):
expected = [dns.rrset.from_text('ifurlextup.example.org.', 0, dns.rdataclass.IN, dns.rdatatype.A, '192.168.0.3')]
_toResponderQueue = Queue()
_fromResponderQueue = Queue()
_queueTimeout = 1
- _dnsdistStartupDelay = 2.0
_dnsdist = None
_responsesCounter = {}
_config_template = """
_checkConfigExpectedOutput = None
_verboseMode = False
_skipListeningOnCL = False
+ _alternateListeningAddr = None
+ _alternateListeningPort = None
_backgroundThreads = {}
_UDPResponder = None
_TCPResponder = None
with open(logFile, 'w') as fdLog:
cls._dnsdist = subprocess.Popen(dnsdistcmd, close_fds=True, stdout=fdLog, stderr=fdLog)
- cls.waitForTCPSocket(cls._dnsDistListeningAddr, cls._dnsDistPort);
+ if cls._alternateListeningAddr and cls._alternateListeningPort:
+ cls.waitForTCPSocket(cls._alternateListeningAddr, cls._alternateListeningPort)
+ else:
+ cls.waitForTCPSocket(cls._dnsDistListeningAddr, cls._dnsDistPort)
if cls._dnsdist.poll() is not None:
print(f"\n*** startDNSDist log for {logFile} ***")
return
try:
p.terminate()
- for count in range(10):
+ for count in range(20):
x = p.poll()
if x is not None:
break
libnacl>=1.4.3,<1.7
requests>=2.1.0
protobuf>=3.0
+pyasn1==0.4.8
pysnmp>=4.3.4
future>=0.17.1
pycurl>=7.43.0
'doh-query-pipe-full', 'doh-response-pipe-full', 'proxy-protocol-invalid', 'tcp-listen-overflows',
'outgoing-doh-query-pipe-full', 'tcp-query-pipe-full', 'tcp-cross-protocol-query-pipe-full',
'tcp-cross-protocol-response-pipe-full']
+ _verboseMode = True
+
+ @classmethod
+ def setUpClass(cls):
+ cls.startResponders()
+ cls.startDNSDist()
+ cls.setUpSockets()
+ cls.waitForTCPSocket('127.0.0.1', cls._webServerPort)
+ print("Launching tests..")
class TestAPIBasics(APITestsBase):
setWebserverConfig({password="%s", apiKey="%s", maxConcurrentConnections=%d})
"""
+ @classmethod
+ def setUpClass(cls):
+ cls.startResponders()
+ cls.startDNSDist()
+ cls.setUpSockets()
+ # do no check if the web server socket is up, because this
+ # might mess up the concurrent connections counter
+
def testConcurrentConnections(self):
"""
Web: Concurrent connections
self.assertEqual(receivedQuery, query)
self.assertEqual(receivedResponse, response)
+class TestAdvancedGetLocalAddressOnNonDefaultLoopbackBind(DNSDistTest):
+ # this one is tricky: on the loopback interface we cannot harvest the destination
+ # address, so we exercise a different code path when we bind on a different address
+ # than the default 127.0.0.1 one
+ _config_template = """
+ newServer{address="127.0.0.1:%s"}
+ addLocal('127.0.1.19:%d')
+ """
+ _config_params = ['_testServerPort', '_dnsDistPort']
+ _acl = ['127.0.0.1/32']
+ _skipListeningOnCL = True
+ _alternateListeningAddr = '127.0.1.19'
+ _alternateListeningPort = DNSDistTest._dnsDistPort
+
+ def testAdvancedCheckSourceAddrOnNonDefaultLoopbackBind(self):
+ """
+ Advanced: Check the source address used to reply on a non-default loopback bind
+ """
+ name = 'source-addr-non-default-loopback.advanced.tests.powerdns.com.'
+ query = dns.message.make_query(name, 'A', 'IN')
+ response = dns.message.make_response(query)
+ rrset = dns.rrset.from_text(name,
+ 60,
+ dns.rdataclass.IN,
+ dns.rdatatype.A,
+ '192.0.2.42')
+ response.answer.append(rrset)
+
+ # a bit more tricky, UDP-only IPv4
+ sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
+ sock.settimeout(1.0)
+ sock.connect(('127.0.1.19', self._dnsDistPort))
+ self._toResponderQueue.put(response, True, 1.0)
+ try:
+ data = query.to_wire()
+ sock.send(data)
+ (data, remote) = sock.recvfrom(4096)
+ self.assertEquals(remote[0], '127.0.1.19')
+ except socket.timeout:
+ data = None
+
+ self.assertTrue(data)
+ receivedResponse = dns.message.from_wire(data)
+ receivedQuery = self._fromResponderQueue.get(True, 1.0)
+ receivedQuery.id = query.id
+ self.assertEqual(receivedQuery, query)
+ self.assertEqual(receivedResponse, response)
+
class TestAdvancedAllowHeaderOnly(DNSDistTest):
_config_template = """
if line.startswith('#') or line.startswith('All'):
continue
tokens = line.split()
- self.assertTrue(len(tokens) == 12 or len(tokens) == 13)
+ self.assertTrue(len(tokens) == 13 or len(tokens) == 14)
if tokens[1] == '127.0.0.1:10652':
# in this particular case, the upgraded backend
# does not replace the existing one and thus
else:
self.assertEquals(tokens[2], 'UP')
pool = ''
- if len(tokens) == 13:
- pool = tokens[12]
+ if len(tokens) == 14:
+ pool = tokens[13]
backends[tokens[1]] = pool
expected = {
_resolverCertificateValidFrom = int(time.time() - 60)
_resolverCertificateValidUntil = int(time.time() + 7200)
- _dnsdistStartupDelay = 10
-
def doDNSCryptQuery(self, client, query, response, tcp):
self._toResponderQueue.put(response)
data = client.query(query.to_wire(), tcp=tcp)
addDOHLocal("127.0.0.1:%s", "%s", "%s", { "/" }, { maxConcurrentTCPConnections=%d })
"""
_config_params = ['_testServerPort', '_dohServerPort', '_serverCert', '_serverKey', '_maxTCPConnsPerDOHFrontend']
+ _alternateListeningAddr = '127.0.0.1'
+ _alternateListeningPort = _dohServerPort
def testTCPConnsPerDOHFrontend(self):
"""
self.checkQueryEDNSWithoutECS(expectedQuery, receivedQuery)
self.assertEqual(response, receivedResponse)
-class TestDOHWithPCKS12Cert(DNSDistDOHTest):
+class TestDOHWithPKCS12Cert(DNSDistDOHTest):
_serverCert = 'server.p12'
_pkcs12Password = 'passw0rd'
_serverName = 'tls.tests.dnsdist.org'
def testProtocolDOH(self):
"""
- DoH: Test Simple DOH Query with a password protected PCKS12 file configured
+ DoH: Test Simple DOH Query with a password protected PKCS12 file configured
"""
name = 'simple.doh.tests.powerdns.com.'
query = dns.message.make_query(name, 'A', 'IN', use_edns=False)
_dohBaseURL = ("https://%s:%d/" % (_serverName, _dohServerPort))
_config_params = ['_tlsServerPort', '_serverCert', '_serverKey', '_dohServerPort', '_serverCert', '_serverKey', '_testServerPort', '_webServerPort', '_webServerAPIKeyHashed']
+ @classmethod
+ def setUpClass(cls):
+ cls.startResponders()
+ cls.startDNSDist()
+ cls.setUpSockets()
+ cls.waitForTCPSocket('127.0.0.1', cls._webServerPort)
+ print("Launching tests..")
+
def getMetric(self, name):
headers = {'x-api-key': self._webServerAPIKey}
url = 'http://127.0.0.1:' + str(self._webServerPort) + '/api/v1/servers/localhost'
addTLSLocal("127.0.0.1:%s", "%s", "%s", { provider="openssl", maxConcurrentTCPConnections=%d })
"""
_config_params = ['_testServerPort', '_tlsServerPort', '_serverCert', '_serverKey', '_maxTCPConnsPerTLSFrontend']
+ _alternateListeningAddr = '127.0.0.1'
+ _alternateListeningPort = _tlsServerPort
def testTCPConnsPerTLSFrontend(self):
"""
--- /dev/null
+#!/usr/bin/env bash
+set -e
+if [ "${PDNS_DEBUG}" = "YES" ]; then
+ set -x
+fi
+
+rootPath=$(readlink -f $(dirname $0))
+
+for random in no yes
+do
+ workdir=$(mktemp -d)
+
+ cat << EOF > "${workdir}/pdns-lmdb.conf"
+ module-dir=../regression-tests/modules
+ launch=lmdb
+ lmdb-filename=${workdir}/pdns.lmdb
+ lmdb-shards=2
+ lmdb-random-ids=$random
+EOF
+
+ echo === random=$random
+
+ echo == creating zone
+ $PDNSUTIL --config-dir="${workdir}" --config-name=lmdb create-zone example.com
+
+ $PDNSUTIL --config-dir="${workdir}" --config-name=lmdb set-meta example.com FOO BAR
+ $PDNSUTIL --config-dir="${workdir}" --config-name=lmdb show-zone example.com | grep FOO
+ mdb_dump -p -a -n ${workdir}/pdns.lmdb | egrep -o 'FOO[0-9]*' | LC_ALL=C sort
+
+ $PDNSUTIL --config-dir="${workdir}" --config-name=lmdb set-meta example.com FOO2 BAR2
+ $PDNSUTIL --config-dir="${workdir}" --config-name=lmdb show-zone example.com | grep FOO
+ mdb_dump -p -a -n ${workdir}/pdns.lmdb | egrep -o 'FOO[0-9]*' | LC_ALL=C sort
+
+ $PDNSUTIL --config-dir="${workdir}" --config-name=lmdb set-meta example.com FOO2 BAR2
+ $PDNSUTIL --config-dir="${workdir}" --config-name=lmdb show-zone example.com | grep FOO
+ mdb_dump -p -a -n ${workdir}/pdns.lmdb | egrep -o 'FOO[0-9]*' | LC_ALL=C sort
+
+ echo == deleting zone
+ $PDNSUTIL --config-dir="${workdir}" --config-name=lmdb delete-zone example.com
+ mdb_dump -p -a -n ${workdir}/pdns.lmdb | egrep -o 'FOO[0-9]*' | LC_ALL=C sort
+done
\ No newline at end of file
--- /dev/null
+This test verifies that, with the LMDB-backend, pdnsutil set-meta and delete-zone do not leave old unreachable metadata items lying around
+
--- /dev/null
+=== random=no
+== creating zone
+Set 'example.com' meta FOO = BAR
+ FOO BAR
+FOO
+Set 'example.com' meta FOO2 = BAR2
+ FOO BAR
+ FOO2 BAR2
+FOO
+FOO2
+Set 'example.com' meta FOO2 = BAR2
+ FOO BAR
+ FOO2 BAR2
+FOO
+FOO2
+== deleting zone
+=== random=yes
+== creating zone
+Set 'example.com' meta FOO = BAR
+ FOO BAR
+FOO
+Set 'example.com' meta FOO2 = BAR2
+ FOO BAR
+ FOO2 BAR2
+FOO
+FOO2
+Set 'example.com' meta FOO2 = BAR2
+ FOO BAR
+ FOO2 BAR2
+FOO
+FOO2
+== deleting zone
do
${MD5SUM} ../regression-tests/zones/$zone
done
+${MD5SUM} ../modules/tinydnsbackend/data
${MD5SUM} ../modules/tinydnsbackend/data.cdb
dee3e8b568549d9450134b555ca73990 ../regression-tests/zones/sub.test.dyndns
e7c0fd528e8aaedb1ea3b6daaead4de2 ../regression-tests/zones/wtest.com
42b442de632686e94bde75acf66cf524 ../regression-tests/zones/nztest.com
-b06133eb32c5bdf346223563501ba8f8 ../regression-tests/zones/dnssec-parent.com
+7f79c98efdb1d3d2318ac666d2fb5642 ../regression-tests/zones/dnssec-parent.com
e9be89b6e5e0da8910c69e46f35d20ab ../regression-tests/zones/insecure.dnssec-parent.com
6510bf48aa3ca3501b73a1f510852a34 ../regression-tests/zones/delegated.dnssec-parent.com
a63dc120391d9df0003f2ec4f461a6af ../regression-tests/zones/secure-delegated.dnssec-parent.com
9aeed2c26d0c3ba3baf22dfa9568c451 ../regression-tests/zones/2.0.192.in-addr.arpa
99c73e8b5db5781fec1ac3fa6a2662a9 ../regression-tests/zones/cryptokeys.org
1f9e19be0cff67330f3a0a5347654f91 ../regression-tests/zones/hiddencryptokeys.org
-ab699fca1a52598202a1494cddd192ff ../modules/tinydnsbackend/data.cdb
+964425367cec0d828222b144c4e1c540 ../modules/tinydnsbackend/data
+f3932b1df41d683f47516455b571c358 ../modules/tinydnsbackend/data.cdb
trace=yes
dont-query=
local-address=127.0.0.1
-packetcache-ttl=0
-packetcache-servfail-ttl=0
+packetcache-ttl=15
+packetcache-servfail-ttl=15
max-cache-ttl=15
-threads=1
+threads=2
loglevel=9
disable-syslog=yes
log-common-errors=yes
nose>=1.3.7
protobuf>=2.5; sys_platform != 'darwin'
protobuf>=3.0; sys_platform == 'darwin'
+pyasn1==0.4.8
pysnmp>=4.3.4
requests>=2.1.0
Twisted>0.15.0
self.assertTrue(False)
+ def testNoEDE(self):
+ # This isn't an aggresive cache check, but the strcuture is very similar to the others,
+ # so letys place it here.
+ # It test the issue that an intermediate EDE does not get reported with the final answer
+ # https://github.com/PowerDNS/pdns/pull/12694
+ self.wipe()
+
+ res = self.sendQuery('host1.sub.secure.example.', 'TXT')
+ self.assertRcodeEqual(res, dns.rcode.NOERROR)
+ self.assertAnswerEmpty(res)
+ self.assertAuthorityHasSOA(res)
+ self.assertMessageIsAuthenticated(res)
+ self.assertEqual(res.edns, 0)
+ self.assertEqual(len(res.options), 0)
+
+ res = self.sendQuery('host1.sub.secure.example.', 'A')
+ self.assertRcodeEqual(res, dns.rcode.NOERROR)
+ self.assertMessageIsAuthenticated(res)
+ self.assertEqual(res.edns, 0)
+ self.assertEqual(len(res.options), 0)
+
def testNoData(self):
self.wipe()
self.assertEqual(res.edns, 0)
self.assertEqual(len(res.options), 1)
self.assertEqual(res.options[0].otype, 15)
- self.assertEqual(res.options[0], extendederrors.ExtendedErrorOption(0, b'Result synthesized from aggressive NSEC cache (RFC8198)'))
+ self.assertEqual(res.options[0], extendederrors.ExtendedErrorOption(29, b'Result synthesized from aggressive NSEC cache (RFC8198)'))
class AggressiveNSECCacheNSEC(AggressiveNSECCacheBase):
_confdir = 'AggressiveNSECCacheNSEC'
self.assertEqual(res.edns, 0)
self.assertEqual(len(res.options), 1)
self.assertEqual(res.options[0].otype, 15)
- self.assertEqual(res.options[0], extendederrors.ExtendedErrorOption(0, b'Result synthesized from aggressive NSEC cache (RFC8198)'))
+ self.assertEqual(res.options[0], extendederrors.ExtendedErrorOption(29, b'Result synthesized from aggressive NSEC cache (RFC8198)'))
def testWildcard(self):
self.wipe()
self.assertEqual(res.edns, 0)
self.assertEqual(len(res.options), 1)
self.assertEqual(res.options[0].otype, 15)
- self.assertEqual(res.options[0], extendederrors.ExtendedErrorOption(0, b'Result synthesized from aggressive NSEC cache (RFC8198)'))
+ self.assertEqual(res.options[0], extendederrors.ExtendedErrorOption(29, b'Result synthesized from aggressive NSEC cache (RFC8198)'))
# now we ask for a type that does not exist at the wildcard
hits = self.getMetric('aggressive-nsec-cache-nsec-hits')
self.assertEqual(res.edns, 0)
self.assertEqual(len(res.options), 1)
self.assertEqual(res.options[0].otype, 15)
- self.assertEqual(res.options[0], extendederrors.ExtendedErrorOption(0, b'Result synthesized from aggressive NSEC cache (RFC8198)'))
+ self.assertEqual(res.options[0], extendederrors.ExtendedErrorOption(29, b'Result synthesized from aggressive NSEC cache (RFC8198)'))
# we can also ask a different type, for a different name that is covered
# by the NSEC and matches the wildcard (but the type does not exist)
self.assertEqual(res.edns, 0)
self.assertEqual(len(res.options), 1)
self.assertEqual(res.options[0].otype, 15)
- self.assertEqual(res.options[0], extendederrors.ExtendedErrorOption(0, b'Result synthesized from aggressive NSEC cache (RFC8198)'))
+ self.assertEqual(res.options[0], extendederrors.ExtendedErrorOption(29, b'Result synthesized from aggressive NSEC cache (RFC8198)'))
def test_Bogus(self):
self.wipe()
self.assertEqual(res.edns, 0)
self.assertEqual(len(res.options), 1)
self.assertEqual(res.options[0].otype, 15)
- self.assertEqual(res.options[0], extendederrors.ExtendedErrorOption(0, b'Result synthesized from aggressive NSEC cache (RFC8198)'))
+ self.assertEqual(res.options[0], extendederrors.ExtendedErrorOption(29, b'Result synthesized from aggressive NSEC cache (RFC8198)'))
def testWildcard(self):
self.wipe()
self.assertEqual(res.edns, 0)
self.assertEqual(len(res.options), 1)
self.assertEqual(res.options[0].otype, 15)
- self.assertEqual(res.options[0], extendederrors.ExtendedErrorOption(0, b'Result synthesized from aggressive NSEC cache (RFC8198)'))
+ self.assertEqual(res.options[0], extendederrors.ExtendedErrorOption(29, b'Result synthesized from aggressive NSEC cache (RFC8198)'))
# now we ask for a type that does not exist at the wildcard
nbQueries = self.getMetric('all-outqueries')
self.assertEqual(res.edns, 0)
self.assertEqual(len(res.options), 1)
self.assertEqual(res.options[0].otype, 15)
- self.assertEqual(res.options[0], extendederrors.ExtendedErrorOption(0, b'Result synthesized from aggressive NSEC cache (RFC8198)'))
+ self.assertEqual(res.options[0], extendederrors.ExtendedErrorOption(29, b'Result synthesized from aggressive NSEC cache (RFC8198)'))
# we can also ask a different type, for a different name that is covered
# by the NSEC3s and matches the wildcard (but the type does not exist)
self.assertEqual(res.edns, 0)
self.assertEqual(len(res.options), 1)
self.assertEqual(res.options[0].otype, 15)
- self.assertEqual(res.options[0], extendederrors.ExtendedErrorOption(0, b'Result synthesized from aggressive NSEC cache (RFC8198)'))
+ self.assertEqual(res.options[0], extendederrors.ExtendedErrorOption(29, b'Result synthesized from aggressive NSEC cache (RFC8198)'))
def test_OptOut(self):
self.wipe()
trace=yes
dont-query=
local-address=127.0.0.1
-packetcache-ttl=0
-packetcache-servfail-ttl=0
+packetcache-ttl=15
+packetcache-servfail-ttl=15
max-cache-ttl=600
-threads=1
+threads=2
loglevel=9
disable-syslog=yes
log-common-errors=yes
function preresolve (dq)
dq.rcode = pdns.NOERROR
dq:addAnswer(pdns.TXT, pdnsrandom())
+ dq.variable = true
return true
end
"""
self.assertTrue(foundMisses)
def testNotify(self):
+ self.waitForTCPSocket("127.0.0.1", self._wsPort)
# first query
qname = 'a.example.'
query = dns.message.make_query(qname, 'A', want_dnssec=True)
_apiKey = 'secretapikey'
_config_template = """
packetcache-ttl=10
+ packetcache-negative-ttl=8
packetcache-servfail-ttl=5
auth-zones=example=configs/%s/example.zone
webserver=yes
super(PacketCacheRecursorTest, cls).generateRecursorConfig(confdir)
def checkPacketCacheMetrics(self, expectedHits, expectedMisses):
+ self.waitForTCPSocket("127.0.0.1", self._wsPort)
headers = {'x-api-key': self._apiKey}
url = 'http://127.0.0.1:' + str(self._wsPort) + '/api/v1/servers/localhost/statistics'
r = requests.get(url, headers=headers, timeout=self._wsTimeout)
self.assertTrue(foundMisses)
def testPacketCache(self):
+ self.waitForTCPSocket("127.0.0.1", self._wsPort)
# first query, no cookie
qname = 'a.example.'
query = dns.message.make_query(qname, 'A', want_dnssec=True)
self.assertRRsetInAnswer(res, expected)
self.checkPacketCacheMetrics(6, 4)
- # NXDomain should get default packetcache TTL (10)
+ # NXDomain should get negative packetcache TTL (8)
query = dns.message.make_query('nxdomain.example.', 'A', want_dnssec=True)
res = self.sendUDPQuery(query)
self.assertRcodeEqual(res, dns.rcode.NXDOMAIN)
self.checkPacketCacheMetrics(6, 5)
- # NoData should get default packetcache TTL (10)
+ # NoData should get negative packetcache TTL (8)
query = dns.message.make_query('a.example.', 'AAAA', want_dnssec=True)
res = self.sendUDPQuery(query)
self.assertRcodeEqual(res, dns.rcode.NOERROR)
try:
ret = subprocess.check_output(rec_controlCmd, stderr=subprocess.STDOUT)
self.assertTrue((b"a.example. 10 A ; tag 0 udp\n" in ret) or (b"a.example. 9 A ; tag 0 udp\n" in ret))
- self.assertTrue((b"nxdomain.example. 10 A ; tag 0 udp\n" in ret) or (b"nxdomain.example. 9 A ; tag 0 udp\n" in ret))
- self.assertTrue((b"a.example. 10 AAAA ; tag 0 udp\n" in ret) or (b"a.example. 9 AAAA ; tag 0 udp\n" in ret))
+ self.assertTrue((b"nxdomain.example. 8 A ; tag 0 udp\n" in ret) or (b"nxdomain.example. 7 A ; tag 0 udp\n" in ret))
+ self.assertTrue((b"a.example. 8 AAAA ; tag 0 udp\n" in ret) or (b"a.example. 7 AAAA ; tag 0 udp\n" in ret))
self.assertTrue((b"f.example. 5 A ; tag 0 udp\n" in ret) or (b"f.example. 4 A ; tag 0 udp\n" in ret))
except subprocess.CalledProcessError as e:
webserver-address=127.0.0.1
webserver-password=%s
api-key=%s
+disable-packetcache
""" % (_confdir, _wsPort, _wsPassword, _apiKey)
_xfrDone = 0
self.assertEqual(res.edns, 0)
self.assertEqual(len(res.options), 1)
self.assertEqual(res.options[0].otype, 15)
- self.assertEqual(res.options[0], extendederrors.ExtendedErrorOption(0, b'Result synthesized by root-nx-trust'))
+ self.assertEqual(res.options[0], extendederrors.ExtendedErrorOption(29, b'Result synthesized by root-nx-trust'))
trace=yes
dont-query=
local-address=127.0.0.1
-packetcache-ttl=0
-packetcache-servfail-ttl=0
+packetcache-ttl=15
+packetcache-servfail-ttl=15
max-cache-ttl=600
-threads=1
+threads=2
loglevel=9
disable-syslog=yes
log-common-errors=yes
<measurement><name>system CPU seconds</name><value>%S</value></measurement>
<measurement><name>wallclock seconds</name><value>%e</value></measurement>
<measurement><name>%% CPU used</name><value>%P</value></measurement>
-' ${RECURSOR} --daemon=no --local-port=$port --socket-dir=./ --trace=$TRACE --config-dir=. --max-mthreads=$mthreads --query-local-address="0.0.0.0${QLA6}" --threads=$threads --record-cache-shards=$shards --disable-packetcache --refresh-on-ttl-perc=10 --dnssec=validate > recursor.log 2>&1 &
+' ${RECURSOR} --daemon=no --local-port=$port --socket-dir=./ --trace=$TRACE --config-dir=. --max-mthreads=$mthreads --query-local-address="0.0.0.0${QLA6}" --threads=$threads --record-cache-shards=$shards --refresh-on-ttl-perc=10 --dnssec=validate --pdns-distributes-queries --reuseport=no > recursor.log 2>&1 &
sleep 3
if [ ! -e pdns_recursor.pid ]; then
cat recursor.log
*.out
start
step.*
+verify-dnssec-zone/allow-missing
+*.dnssec-parent.com. 3600 IN CNAME secure-delegated.dnssec-parent.com.
delegated.dnssec-parent.com. 3600 IN NS ns1.delegated.dnssec-parent.com.
delegated.dnssec-parent.com. 3600 IN NS ns2.delegated.dnssec-parent.com.
dnssec-parent.com. 3600 IN A 9.9.9.9
+*.dnssec-parent.com. 3600 IN CNAME secure-delegated.dnssec-parent.com.
+*.dnssec-parent.com. 3600 IN NSEC insecure-delegated.ent.ent.auth-ent.dnssec-parent.com. CNAME RRSIG NSEC
+*.dnssec-parent.com. 3600 IN RRSIG CNAME 13 2 3600 [expiry] [inception] [keytag] dnssec-parent.com. ...
+*.dnssec-parent.com. 3600 IN RRSIG NSEC 13 2 3600 [expiry] [inception] [keytag] dnssec-parent.com. ...
delegated.dnssec-parent.com. 3600 IN NS ns1.delegated.dnssec-parent.com.
delegated.dnssec-parent.com. 3600 IN NS ns2.delegated.dnssec-parent.com.
delegated.dnssec-parent.com. 3600 IN NSEC insecure.dnssec-parent.com. NS RRSIG NSEC
dnssec-parent.com. 3600 IN A 9.9.9.9
dnssec-parent.com. 3600 IN NS ns1.dnssec-parent.com.
dnssec-parent.com. 3600 IN NS ns2.dnssec-parent.com.
-dnssec-parent.com. 3600 IN NSEC insecure-delegated.ent.ent.auth-ent.dnssec-parent.com. A NS SOA RRSIG NSEC DNSKEY CDS CDNSKEY
+dnssec-parent.com. 3600 IN NSEC *.dnssec-parent.com. A NS SOA RRSIG NSEC DNSKEY CDS CDNSKEY
dnssec-parent.com. 3600 IN RRSIG A 13 2 3600 [expiry] [inception] [keytag] dnssec-parent.com. ...
dnssec-parent.com. 3600 IN RRSIG NS 13 2 3600 [expiry] [inception] [keytag] dnssec-parent.com. ...
dnssec-parent.com. 3600 IN RRSIG NSEC 13 2 3600 [expiry] [inception] [keytag] dnssec-parent.com. ...
+*.dnssec-parent.com. 3600 IN CNAME secure-delegated.dnssec-parent.com.
+*.dnssec-parent.com. 3600 IN NSEC3 1 0 1 abcd [next owner] CNAME RRSIG
+*.dnssec-parent.com. 3600 IN RRSIG CNAME 13 2 3600 [expiry] [inception] [keytag] dnssec-parent.com. ...
+*.dnssec-parent.com. 3600 IN RRSIG NSEC3 13 3 3600 [expiry] [inception] [keytag] dnssec-parent.com. ...
auth-ent.dnssec-parent.com. 3600 IN NSEC3 1 0 1 abcd [next owner]
auth-ent.dnssec-parent.com. 3600 IN RRSIG NSEC3 13 3 3600 [expiry] [inception] [keytag] dnssec-parent.com. ...
delegated.dnssec-parent.com. 3600 IN NS ns1.delegated.dnssec-parent.com.
+*.dnssec-parent.com. 3600 IN CNAME secure-delegated.dnssec-parent.com.
+*.dnssec-parent.com. 3600 IN NSEC3 1 1 1 abcd [next owner] CNAME RRSIG
+*.dnssec-parent.com. 3600 IN RRSIG CNAME 13 2 3600 [expiry] [inception] [keytag] dnssec-parent.com. ...
+*.dnssec-parent.com. 3600 IN RRSIG NSEC3 13 3 3600 [expiry] [inception] [keytag] dnssec-parent.com. ...
auth-ent.dnssec-parent.com. 3600 IN NSEC3 1 1 1 abcd [next owner]
auth-ent.dnssec-parent.com. 3600 IN RRSIG NSEC3 13 3 3600 [expiry] [inception] [keytag] dnssec-parent.com. ...
delegated.dnssec-parent.com. 3600 IN NS ns1.delegated.dnssec-parent.com.
1 7on3vems0f8k9999ikei0ig4lfijekdr.dnssec-parent.com. 3600 IN RRSIG NSEC3 13 3 3600 [expiry] [inception] [keytag] dnssec-parent.com. ...
1 dnssec-parent.com. 3600 IN RRSIG SOA 13 2 3600 [expiry] [inception] [keytag] dnssec-parent.com. ...
1 dnssec-parent.com. 3600 IN SOA ns1.dnssec-parent.com. ahu.example.com. 2005092501 28800 7200 604800 86400
-1 dvkuo8kja65gcsq600e6di9u719lsj8u.dnssec-parent.com. 3600 IN NSEC3 1 1 1 abcd NIH4L3ODLUG7EN20PENJ8DGNU4OHC98F A NS SOA RRSIG DNSKEY NSEC3PARAM CDS CDNSKEY
+1 dvkuo8kja65gcsq600e6di9u719lsj8u.dnssec-parent.com. 3600 IN NSEC3 1 1 1 abcd K25OPIULTRKGKRMR3UC09CSK20QHT1LJ A NS SOA RRSIG DNSKEY NSEC3PARAM CDS CDNSKEY
1 dvkuo8kja65gcsq600e6di9u719lsj8u.dnssec-parent.com. 3600 IN RRSIG NSEC3 13 3 3600 [expiry] [inception] [keytag] dnssec-parent.com. ...
2 . 32768 IN OPT
Rcode: 0 (No Error), RD: 0, QR: 1, TC: 0, AA: 1, opcode: 0
-1 dnssec-parent.com. 3600 IN NSEC insecure-delegated.ent.ent.auth-ent.dnssec-parent.com. A NS SOA RRSIG NSEC DNSKEY CDS CDNSKEY
-1 dnssec-parent.com. 3600 IN RRSIG NSEC 13 2 3600 [expiry] [inception] [keytag] dnssec-parent.com. ...
+1 *.dnssec-parent.com. 3600 IN NSEC insecure-delegated.ent.ent.auth-ent.dnssec-parent.com. CNAME RRSIG NSEC
+1 *.dnssec-parent.com. 3600 IN RRSIG NSEC 13 2 3600 [expiry] [inception] [keytag] dnssec-parent.com. ...
1 dnssec-parent.com. 3600 IN RRSIG SOA 13 2 3600 [expiry] [inception] [keytag] dnssec-parent.com. ...
1 dnssec-parent.com. 3600 IN SOA ns1.dnssec-parent.com. ahu.example.com. 2005092501 28800 7200 604800 86400
2 . 32768 IN OPT
--- /dev/null
+#!/bin/sh
+cleandig secure-delegated1.dnssec-parent.com A dnssec
--- /dev/null
+Check that we generate the right NSECs when the NSEC name is a delegation point.
--- /dev/null
+0 secure-delegated.dnssec-parent.com. 3600 IN A 9.9.9.9
+0 secure-delegated.dnssec-parent.com. 3600 IN RRSIG A 8 3 3600 [expiry] [inception] [keytag] secure-delegated.dnssec-parent.com. ...
+0 secure-delegated1.dnssec-parent.com. 3600 IN CNAME secure-delegated.dnssec-parent.com.
+0 secure-delegated1.dnssec-parent.com. 3600 IN RRSIG CNAME 13 2 3600 [expiry] [inception] [keytag] dnssec-parent.com. ...
+1 secure-delegated.dnssec-parent.com. 3600 IN NSEC www.dnssec-parent.com. NS DS RRSIG NSEC
+1 secure-delegated.dnssec-parent.com. 3600 IN RRSIG NSEC 13 3 3600 [expiry] [inception] [keytag] dnssec-parent.com. ...
+2 . 32768 IN OPT
+Rcode: 0 (No Error), RD: 0, QR: 1, TC: 0, AA: 1, opcode: 0
+Reply to question for qname='secure-delegated1.dnssec-parent.com.', qtype=A
--- /dev/null
+0 secure-delegated.dnssec-parent.com. 3600 IN A 9.9.9.9
+0 secure-delegated.dnssec-parent.com. 3600 IN RRSIG A 8 3 3600 [expiry] [inception] [keytag] secure-delegated.dnssec-parent.com. ...
+0 secure-delegated1.dnssec-parent.com. 3600 IN CNAME secure-delegated.dnssec-parent.com.
+0 secure-delegated1.dnssec-parent.com. 3600 IN RRSIG CNAME 13 2 3600 [expiry] [inception] [keytag] dnssec-parent.com. ...
+1 1an9kidorpirlabrh3be2n8k5taoe1v0.dnssec-parent.com. 3600 IN NSEC3 1 [flags] 1 abcd 1AN9KIDORPIRLABRH3BE2N8K5TAOE1V2
+1 1an9kidorpirlabrh3be2n8k5taoe1v0.dnssec-parent.com. 3600 IN RRSIG NSEC3 13 3 3600 [expiry] [inception] [keytag] dnssec-parent.com. ...
+2 . 32768 IN OPT
+Rcode: 0 (No Error), RD: 0, QR: 1, TC: 0, AA: 1, opcode: 0
+Reply to question for qname='secure-delegated1.dnssec-parent.com.', qtype=A
--- /dev/null
+0 secure-delegated.dnssec-parent.com. 3600 IN A 9.9.9.9
+0 secure-delegated.dnssec-parent.com. 3600 IN RRSIG A 8 3 3600 [expiry] [inception] [keytag] secure-delegated.dnssec-parent.com. ...
+0 secure-delegated1.dnssec-parent.com. 3600 IN CNAME secure-delegated.dnssec-parent.com.
+0 secure-delegated1.dnssec-parent.com. 3600 IN RRSIG CNAME 13 2 3600 [expiry] [inception] [keytag] dnssec-parent.com. ...
+1 u97st412oa8b4bgjc1dgtb4qi5di8dmv.dnssec-parent.com. 3600 IN NSEC3 1 [flags] 1 abcd 1SCAQA30LQ0DO5EIRNE4KPJFBEBFGR54
+1 u97st412oa8b4bgjc1dgtb4qi5di8dmv.dnssec-parent.com. 3600 IN RRSIG NSEC3 13 3 3600 [expiry] [inception] [keytag] dnssec-parent.com. ...
+2 . 32768 IN OPT
+Rcode: 0 (No Error), RD: 0, QR: 1, TC: 0, AA: 1, opcode: 0
+Reply to question for qname='secure-delegated1.dnssec-parent.com.', qtype=A
--- /dev/null
+0 secure-delegated.dnssec-parent.com. 3600 IN A 9.9.9.9
+0 secure-delegated.dnssec-parent.com. 3600 IN RRSIG A 8 3 3600 [expiry] [inception] [keytag] secure-delegated.dnssec-parent.com. ...
+0 secure-delegated1.dnssec-parent.com. 3600 IN CNAME secure-delegated.dnssec-parent.com.
+0 secure-delegated1.dnssec-parent.com. 3600 IN RRSIG CNAME 13 2 3600 [expiry] [inception] [keytag] dnssec-parent.com. ...
+1 qoqsriqrvi1g1ql3tpph2248q9ldpepf.dnssec-parent.com. 3600 IN NSEC3 1 [flags] 1 abcd 1SCAQA30LQ0DO5EIRNE4KPJFBEBFGR54 A RRSIG
+1 qoqsriqrvi1g1ql3tpph2248q9ldpepf.dnssec-parent.com. 3600 IN RRSIG NSEC3 13 3 3600 [expiry] [inception] [keytag] dnssec-parent.com. ...
+2 . 32768 IN OPT
+Rcode: 0 (No Error), RD: 0, QR: 1, TC: 0, AA: 1, opcode: 0
+Reply to question for qname='secure-delegated1.dnssec-parent.com.', qtype=A
something1.auth-ent IN A 1.1.2.3
insecure IN NS ns.example.com.
www IN CNAME www.insecure
+* IN CNAME secure-delegated
'ruby-dev',
'sqlite3',
'unixodbc-dev',
+ 'cmake',
]
rec_build_deps = [
'libcap-dev',
'libsystemd0',
'libyaml-cpp0.6',
'libzmq3-dev',
+ 'lmdb-utils',
'prometheus',
'ruby-bundler',
'ruby-dev',
c.run('git clone https://git.code.sf.net/p/ed448goldilocks/code /tmp/libdecaf')
with c.cd('/tmp/libdecaf'):
c.run('git checkout 41f349')
- c.run('cmake -B build '
+ c.run('CC=clang-12 CXX=clang-12 '
+ 'cmake -B build '
'-DCMAKE_INSTALL_PREFIX=/usr/local '
'-DCMAKE_INSTALL_LIBDIR=lib '
'-DENABLE_STATIC=OFF '
@task
def ci_docs_upload_master(c, docs_host, pdf, username, product, directory=""):
- c.run(f"rsync -crv --delete --no-p --chmod=g=rwX --exclude '*~' ./docs/_build/{product}-html-docs/ {username}@{docs_host}:{directory}")
- c.run(f"rsync -crv --no-p --chmod=g=rwX --exclude '*~' ./docs/_build/{product}-html-docs.tar.bz2 {username}@{docs_host}:{directory}/html-docs.tar.bz2")
- c.run(f"rsync -crv --no-p --chmod=g=rwX --exclude '*~' ./docs/_build/latex/{pdf} {username}@{docs_host}:{directory}")
+ rsync_cmd = " ".join([
+ "rsync",
+ "--checksum",
+ "--recursive",
+ "--verbose",
+ "--no-p",
+ "--chmod=g=rwX",
+ "--exclude '*~'",
+ ])
+ c.run(f"{rsync_cmd} --delete ./docs/_build/{product}-html-docs/ {username}@{docs_host}:{directory}")
+ c.run(f"{rsync_cmd} ./docs/_build/{product}-html-docs.tar.bz2 {username}@{docs_host}:{directory}/html-docs.tar.bz2")
+ c.run(f"{rsync_cmd} ./docs/_build/latex/{pdf} {username}@{docs_host}:{directory}")
@task
def ci_docs_add_ssh(c, ssh_key, host_key):
c.run('chmod 600 ~/.ssh/id_ed25519')
c.run(f'echo "{host_key}" > ~/.ssh/known_hosts')
+
+def get_sanitizers():
+ sanitizers = os.getenv('SANITIZERS')
+ if sanitizers != '':
+ sanitizers = sanitizers.split('+')
+ sanitizers = ['--enable-' + sanitizer for sanitizer in sanitizers]
+ sanitizers = ' '.join(sanitizers)
+ return sanitizers
+
+
+def get_cflags():
+ return " ".join([
+ "-O1",
+ "-Werror=vla",
+ "-Werror=shadow",
+ "-Wformat=2",
+ "-Werror=format-security",
+ "-Werror=string-plus-int",
+ ])
+
+
+def get_cxxflags():
+ return " ".join([
+ get_cflags(),
+ "-Wp,-D_GLIBCXX_ASSERTIONS",
+ ])
+
+
+def get_base_configure_cmd():
+ return " ".join([
+ f'CFLAGS="{get_cflags()}"',
+ f'CXXFLAGS="{get_cxxflags()}"',
+ './configure',
+ "CC='clang-12'",
+ "CXX='clang++-12'",
+ "--enable-option-checking=fatal",
+ "--enable-systemd",
+ "--with-libsodium",
+ "--enable-fortify-source=auto",
+ "--enable-auto-var-init=pattern",
+ ])
+
+
@task
def ci_auth_configure(c):
- sanitizers = ' '.join('--enable-'+x for x in os.getenv('SANITIZERS').split('+')) if os.getenv('SANITIZERS') != '' else ''
- unittests = ' --enable-unit-tests --enable-backend-unit-tests' if os.getenv('UNIT_TESTS') == 'yes' else ''
- fuzzingtargets = ' --enable-fuzz-targets' if os.getenv('FUZZING_TARGETS') == 'yes' else ''
- res = c.run('''CFLAGS="-O1 -Werror=vla -Werror=shadow -Wformat=2 -Werror=format-security -Werror=string-plus-int" \
- CXXFLAGS="-O1 -Werror=vla -Werror=shadow -Wformat=2 -Werror=format-security -Werror=string-plus-int -Wp,-D_GLIBCXX_ASSERTIONS" \
- ./configure \
- CC='clang-12' \
- CXX='clang++-12' \
- LDFLAGS='-L/usr/local/lib -Wl,-rpath,/usr/local/lib' \
- --enable-option-checking=fatal \
- --with-modules='bind geoip gmysql godbc gpgsql gsqlite3 ldap lmdb lua2 pipe remote tinydns' \
- --enable-systemd \
- --enable-tools \
- --enable-fuzz-targets \
- --enable-experimental-pkcs11 \
- --enable-experimental-gss-tsig \
- --enable-remotebackend-zeromq \
- --with-lmdb=/usr \
- --with-libsodium \
- --with-libdecaf \
- --prefix=/opt/pdns-auth \
- --enable-ixfrdist \
- --enable-fortify-source=auto \
- --enable-auto-var-init=pattern ''' + sanitizers + unittests + fuzzingtargets, warn=True)
+ sanitizers = get_sanitizers()
+
+ unittests = os.getenv('UNIT_TESTS')
+ if unittests == 'yes':
+ unittests = '--enable-unit-tests --enable-backend-unit-tests'
+ else:
+ unittests = ''
+
+ fuzz_targets = os.getenv('FUZZING_TARGETS')
+ fuzz_targets = '--enable-fuzz-targets' if fuzz_targets == 'yes' else ''
+
+ modules = " ".join([
+ "bind",
+ "geoip",
+ "gmysql",
+ "godbc",
+ "gpgsql",
+ "gsqlite3",
+ "ldap",
+ "lmdb",
+ "lua2",
+ "pipe",
+ "remote",
+ "tinydns",
+ ])
+ configure_cmd = " ".join([
+ get_base_configure_cmd(),
+ "LDFLAGS='-L/usr/local/lib -Wl,-rpath,/usr/local/lib'",
+ f"--with-modules='{modules}'",
+ "--enable-tools",
+ "--enable-experimental-pkcs11",
+ "--enable-experimental-gss-tsig",
+ "--enable-remotebackend-zeromq",
+ "--with-lmdb=/usr",
+ "--with-libdecaf",
+ "--prefix=/opt/pdns-auth",
+ "--enable-ixfrdist",
+ sanitizers,
+ unittests,
+ fuzz_targets,
+ ])
+ res = c.run(configure_cmd, warn=True)
if res.exited != 0:
c.run('cat config.log')
raise UnexpectedExit(res)
+
+
@task
def ci_rec_configure(c):
- sanitizers = ' '.join('--enable-'+x for x in os.getenv('SANITIZERS').split('+')) if os.getenv('SANITIZERS') != '' else ''
- unittests = ' --enable-unit-tests' if os.getenv('UNIT_TESTS') == 'yes' else ''
- res = c.run(''' CFLAGS="-O1 -Werror=vla -Werror=shadow -Wformat=2 -Werror=format-security -Werror=string-plus-int" \
- CXXFLAGS="-O1 -Werror=vla -Werror=shadow -Wformat=2 -Werror=format-security -Werror=string-plus-int -Wp,-D_GLIBCXX_ASSERTIONS" \
- ./configure \
- CC='clang-12' \
- CXX='clang++-12' \
- --enable-option-checking=fatal \
- --enable-nod \
- --enable-systemd \
- --prefix=/opt/pdns-recursor \
- --with-libsodium \
- --with-lua=luajit \
- --with-libcap \
- --with-net-snmp \
- --enable-fortify-source=auto \
- --enable-auto-var-init=pattern \
- --enable-dns-over-tls ''' + sanitizers + unittests, warn=True)
+ sanitizers = get_sanitizers()
+
+ unittests = os.getenv('UNIT_TESTS')
+ unittests = '--enable-unit-tests' if unittests == 'yes' else ''
+
+ configure_cmd = " ".join([
+ get_base_configure_cmd(),
+ "--enable-nod",
+ "--prefix=/opt/pdns-recursor",
+ "--with-lua=luajit",
+ "--with-libcap",
+ "--with-net-snmp",
+ "--enable-dns-over-tls",
+ sanitizers,
+ unittests,
+ ])
+ res = c.run(configure_cmd, warn=True)
if res.exited != 0:
c.run('cat config.log')
raise UnexpectedExit(res)
+
@task
def ci_dnsdist_configure(c, features):
additional_flags = ''